Get the firmware version from the device descriptors

Not claiming the interface means we can avoid blocking other applications just
to get the current firmware version.

See https://blogs.gnome.org/hughsie/2015/04/29/updating-openhardware-firmware-2/
for more details about what is required from firmware.
This commit is contained in:
Richard Hughes 2015-04-28 16:44:54 +01:00
parent 274818a11e
commit 3b0be1b8bb
2 changed files with 50 additions and 5 deletions

View File

@ -235,6 +235,20 @@ themselves using the `appstream-builder` command line tool, for example:
Please [email us](mailto://richard@hughsie.com) if you just want to upload `.cab`
files and you would like us to generate metadata for your product.
### How does fwupd know the device firmware version?
For generic USB devices you can use a firmware version extension that is used
by a few OpenHardware projects. This means the fwupd daemon can obtain the
firmware version without claiming the interface on the device and preventing
other software from using it straight away.
For closed-source devices a product-specific provider can be used, although
this isn't covered here.
To implement the firmware version extension just create an interface descriptor
with class code `0xff`, subclass code `0x46` and protocol `0x57` pointing to a
string descriptor with the firmware version.
An example commit to the ColorHug project can be found [here](https://github.com/hughski/colorhug2-firmware/commit/5e1bb64ad722a9d2d95927e305fd869b4a3a46a8).
Adding Trusted Keys
===================

View File

@ -166,12 +166,39 @@ fu_provider_chug_get_firmware_version (FuProviderChugItem *item)
guint16 major;
guint16 micro;
guint16 minor;
#if G_USB_CHECK_VERSION(0,2,5)
guint8 idx;
#endif
_cleanup_error_free_ GError *error = NULL;
_cleanup_free_ gchar *version = NULL;
/* try to get the version without claiming interface */
#if G_USB_CHECK_VERSION(0,2,5)
if (!g_usb_device_open (item->usb_device, &error)) {
g_debug ("Failed to open, polling: %s", error->message);
return;
}
idx = g_usb_device_get_custom_index (item->usb_device,
G_USB_DEVICE_CLASS_VENDOR,
'F', 'W', NULL);
if (idx != 0x00) {
_cleanup_free_ gchar *tmp = NULL;
tmp = g_usb_device_get_string_descriptor (item->usb_device,
idx, NULL);
if (tmp != NULL) {
item->got_version = TRUE;
g_debug ("obtained fwver using extension '%s'", tmp);
fu_device_set_metadata (item->device,
FU_DEVICE_KEY_VERSION, tmp);
goto out;
}
}
g_usb_device_close (item->usb_device, NULL);
#endif
/* attempt to open the device and get the serial number */
if (!ch_device_open (item->usb_device, &error)) {
g_debug ("Failed to open, polling: %s", error->message);
g_debug ("Failed to claim interface, polling: %s", error->message);
return;
}
ch_device_queue_get_firmware_ver (priv->device_queue, item->usb_device,
@ -180,12 +207,16 @@ fu_provider_chug_get_firmware_version (FuProviderChugItem *item)
CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE,
NULL, &error)) {
g_warning ("Failed to get serial: %s", error->message);
} else {
item->got_version = TRUE;
version = g_strdup_printf ("%i.%i.%i", major, minor, micro);
fu_device_set_metadata (item->device, FU_DEVICE_KEY_VERSION, version);
goto out;
}
/* got things the old fashioned way */
item->got_version = TRUE;
version = g_strdup_printf ("%i.%i.%i", major, minor, micro);
g_debug ("obtained fwver using API '%s'", version);
fu_device_set_metadata (item->device, FU_DEVICE_KEY_VERSION, version);
out:
/* we're done here */
if (!g_usb_device_close (item->usb_device, &error))
g_debug ("Failed to close: %s", error->message);