From 3b0be1b8bb2822dd4584bdaca24e266a0533203f Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Tue, 28 Apr 2015 16:44:54 +0100 Subject: [PATCH] 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. --- README.md | 14 ++++++++++++++ src/fu-provider-chug.c | 41 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index b735e53b4..521d56f53 100644 --- a/README.md +++ b/README.md @@ -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 =================== diff --git a/src/fu-provider-chug.c b/src/fu-provider-chug.c index 5d921612b..d7c314794 100644 --- a/src/fu-provider-chug.c +++ b/src/fu-provider-chug.c @@ -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);