diff --git a/docs/libfwupd/libfwupd-docs.xml b/docs/libfwupd/libfwupd-docs.xml index db379ef8a..a7d1ccbf8 100644 --- a/docs/libfwupd/libfwupd-docs.xml +++ b/docs/libfwupd/libfwupd-docs.xml @@ -43,6 +43,7 @@ + diff --git a/plugins/altos/fu-altos-device.c b/plugins/altos/fu-altos-device.c index 6afe18fea..7c5bf7de7 100644 --- a/plugins/altos/fu-altos-device.c +++ b/plugins/altos/fu-altos-device.c @@ -35,7 +35,6 @@ typedef struct { FuAltosDeviceKind kind; - GUsbDevice *usb_device; guint32 serial[9]; gchar *guid; gchar *tty; @@ -46,7 +45,7 @@ typedef struct gint tty_fd; } FuAltosDevicePrivate; -G_DEFINE_TYPE_WITH_PRIVATE (FuAltosDevice, fu_altos_device, FU_TYPE_DEVICE) +G_DEFINE_TYPE_WITH_PRIVATE (FuAltosDevice, fu_altos_device, FU_TYPE_USB_DEVICE) #define GET_PRIVATE(o) (fu_altos_device_get_instance_private (o)) @@ -103,8 +102,6 @@ fu_altos_device_finalize (GObject *object) g_free (priv->guid); g_free (priv->tty); g_free (priv->version); - if (priv->usb_device != NULL) - g_object_unref (priv->usb_device); G_OBJECT_CLASS (fu_altos_device_parent_class)->finalize (object); } @@ -132,6 +129,7 @@ static gboolean fu_altos_device_find_tty (FuAltosDevice *device, GError **error) { FuAltosDevicePrivate *priv = GET_PRIVATE (device); + GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (device)); g_autoptr(GList) devices = NULL; g_autoptr(GUdevClient) gudev_client = g_udev_client_new (NULL); @@ -155,10 +153,10 @@ fu_altos_device_find_tty (FuAltosDevice *device, GError **error) /* check correct device */ if (g_udev_device_get_sysfs_attr_as_int (dev, "busnum") != - g_usb_device_get_bus (priv->usb_device)) + g_usb_device_get_bus (usb_device)) continue; if (g_udev_device_get_sysfs_attr_as_int (dev, "devnum") != - g_usb_device_get_address (priv->usb_device)) + g_usb_device_get_address (usb_device)) continue; /* success */ @@ -171,8 +169,8 @@ fu_altos_device_find_tty (FuAltosDevice *device, GError **error) FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED, "failed to find tty for %u:%u", - g_usb_device_get_bus (priv->usb_device), - g_usb_device_get_address (priv->usb_device)); + g_usb_device_get_bus (usb_device), + g_usb_device_get_address (usb_device)); return FALSE; } @@ -722,6 +720,7 @@ gboolean fu_altos_device_probe (FuAltosDevice *device, GError **error) { FuAltosDevicePrivate *priv = GET_PRIVATE (device); + GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (device)); /* bootloader uses tty */ if (priv->kind == FU_ALTOS_DEVICE_KIND_BOOTLOADER) @@ -735,13 +734,13 @@ fu_altos_device_probe (FuAltosDevice *device, GError **error) g_autoptr(FuDeviceLocker) locker = NULL; /* open */ - locker = fu_device_locker_new (priv->usb_device, error); + locker = fu_device_locker_new (usb_device, error); if (locker == NULL) return FALSE; /* get string */ - version_idx = g_usb_device_get_product_index (priv->usb_device); - version = g_usb_device_get_string_descriptor (priv->usb_device, + version_idx = g_usb_device_get_product_index (usb_device); + version = g_usb_device_get_string_descriptor (usb_device, version_idx, error); if (version == NULL) @@ -766,23 +765,13 @@ static void fu_altos_device_init_real (FuAltosDevice *device) { FuAltosDevicePrivate *priv = GET_PRIVATE (device); - g_autofree gchar *devid1 = NULL; - g_autofree gchar *vendor_id = NULL; /* allowed, but requires manual bootloader step */ fu_device_add_flag (FU_DEVICE (device), FWUPD_DEVICE_FLAG_UPDATABLE); - /* set USB platform ID */ - fu_device_set_platform_id (FU_DEVICE (device), - g_usb_device_get_platform_id (priv->usb_device)); - /* set default vendor */ fu_device_set_vendor (FU_DEVICE (device), "altusmetrum.org"); - /* set vendor ID */ - vendor_id = g_strdup_printf ("USB:0x%04X", g_usb_device_get_vid (priv->usb_device)); - fu_device_set_vendor_id (FU_DEVICE (device), vendor_id); - /* set name */ switch (priv->kind) { case FU_ALTOS_DEVICE_KIND_BOOTLOADER: @@ -800,13 +789,6 @@ fu_altos_device_init_real (FuAltosDevice *device) fu_device_set_summary (FU_DEVICE (device), "A USB hardware random number generator"); - /* add USB\VID_0000&PID_0000 */ - devid1 = g_strdup_printf ("USB\\VID_%04X&PID_%04X", - g_usb_device_get_vid (priv->usb_device), - g_usb_device_get_pid (priv->usb_device)); - fu_device_add_guid (FU_DEVICE (device), devid1); - g_debug ("saving runtime GUID of %s", devid1); - /* only the bootloader can do the update */ if (priv->kind != FU_ALTOS_DEVICE_KIND_BOOTLOADER) { fu_device_add_flag (FU_DEVICE (device), @@ -823,8 +805,6 @@ typedef struct { FuAltosDevice * fu_altos_device_new (GUsbDevice *usb_device) { - FuAltosDevice *device; - FuAltosDevicePrivate *priv; const FuAltosDeviceVidPid vidpids[] = { { 0xfffe, 0x000a, FU_ALTOS_DEVICE_KIND_BOOTLOADER }, { 0x1d50, 0x60c6, FU_ALTOS_DEVICE_KIND_CHAOSKEY }, @@ -833,16 +813,18 @@ fu_altos_device_new (GUsbDevice *usb_device) /* set kind */ for (guint j = 0; vidpids[j].vid != 0x0000; j++) { - if (g_usb_device_get_vid (usb_device) != vidpids[j].vid) - continue; - if (g_usb_device_get_pid (usb_device) != vidpids[j].pid) - continue; - device = g_object_new (FU_TYPE_ALTOS_DEVICE, NULL); - priv = GET_PRIVATE (device); - priv->kind = vidpids[j].kind; - priv->usb_device = g_object_ref (usb_device); - fu_altos_device_init_real (device); - return device; + if (g_usb_device_get_vid (usb_device) == vidpids[j].vid && + g_usb_device_get_pid (usb_device) == vidpids[j].pid) { + FuAltosDevice *device; + FuAltosDevicePrivate *priv; + device = g_object_new (FU_TYPE_ALTOS_DEVICE, + "usb-device", usb_device, + NULL); + priv = GET_PRIVATE (device); + priv->kind = vidpids[j].kind; + fu_altos_device_init_real (device); + return device; + } } return NULL; } diff --git a/plugins/altos/fu-altos-device.h b/plugins/altos/fu-altos-device.h index 05075a041..c83f0c44f 100644 --- a/plugins/altos/fu-altos-device.h +++ b/plugins/altos/fu-altos-device.h @@ -30,11 +30,11 @@ G_BEGIN_DECLS #define FU_TYPE_ALTOS_DEVICE (fu_altos_device_get_type ()) -G_DECLARE_DERIVABLE_TYPE (FuAltosDevice, fu_altos_device, FU, ALTOS_DEVICE, FuDevice) +G_DECLARE_DERIVABLE_TYPE (FuAltosDevice, fu_altos_device, FU, ALTOS_DEVICE, FuUsbDevice) struct _FuAltosDeviceClass { - FuDeviceClass parent_class; + FuUsbDeviceClass parent_class; }; typedef enum { diff --git a/plugins/altos/fu-plugin-altos.c b/plugins/altos/fu-plugin-altos.c index 773e0343c..8c90975c1 100644 --- a/plugins/altos/fu-plugin-altos.c +++ b/plugins/altos/fu-plugin-altos.c @@ -21,8 +21,6 @@ #include "config.h" -#include - #include "fu-plugin.h" #include "fu-plugin-vfuncs.h" @@ -35,16 +33,8 @@ fu_plugin_altos_device_added (FuPlugin *plugin, { const gchar *platform_id = NULL; g_autofree gchar *runtime_id = NULL; - g_autoptr(AsProfile) profile = as_profile_new (); - g_autoptr(AsProfileTask) ptask = NULL; g_autoptr(FuAltosDevice) dev = NULL; - /* profile */ - ptask = as_profile_start (profile, "FuPluginAltos:added{%04x:%04x}", - g_usb_device_get_vid (usb_device), - g_usb_device_get_pid (usb_device)); - g_assert (ptask != NULL); - /* get kind */ dev = fu_altos_device_new (usb_device); if (dev == NULL) { diff --git a/plugins/colorhug/fu-colorhug-device.c b/plugins/colorhug/fu-colorhug-device.c index 91d978f29..6cfc04a7d 100644 --- a/plugins/colorhug/fu-colorhug-device.c +++ b/plugins/colorhug/fu-colorhug-device.c @@ -30,14 +30,12 @@ typedef struct { ChDeviceQueue *device_queue; - GUsbDevice *usb_device; - FuDeviceLocker *usb_device_locker; gboolean is_bootloader; GFileProgressCallback progress_cb; gpointer progress_data; } FuColorhugDevicePrivate; -G_DEFINE_TYPE_WITH_PRIVATE (FuColorhugDevice, fu_colorhug_device, FU_TYPE_DEVICE) +G_DEFINE_TYPE_WITH_PRIVATE (FuColorhugDevice, fu_colorhug_device, FU_TYPE_USB_DEVICE) #define GET_PRIVATE(o) (fu_colorhug_device_get_instance_private (o)) @@ -48,10 +46,6 @@ fu_colorhug_device_finalize (GObject *object) FuColorhugDevicePrivate *priv = GET_PRIVATE (device); g_object_unref (priv->device_queue); - if (priv->usb_device_locker != NULL) - g_object_unref (priv->usb_device_locker); - if (priv->usb_device != NULL) - g_object_unref (priv->usb_device); G_OBJECT_CLASS (fu_colorhug_device_parent_class)->finalize (object); } @@ -67,29 +61,6 @@ fu_colorhug_device_progress_cb (ChDeviceQueue *device_queue, priv->progress_cb (percentage, 100, priv->progress_data); } -static void -fu_colorhug_device_init (FuColorhugDevice *device) -{ - FuColorhugDevicePrivate *priv = GET_PRIVATE (device); - priv->device_queue = ch_device_queue_new (); - g_signal_connect (priv->device_queue, "progress_changed", - G_CALLBACK (fu_colorhug_device_progress_cb), device); -} - -static void -fu_colorhug_device_class_init (FuColorhugDeviceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - object_class->finalize = fu_colorhug_device_finalize; -} - -GUsbDevice * -fu_colorhug_device_get_usb_device (FuColorhugDevice *device) -{ - FuColorhugDevicePrivate *priv = GET_PRIVATE (device); - return priv->usb_device; -} - gboolean fu_colorhug_device_get_is_bootloader (FuColorhugDevice *device) { @@ -101,6 +72,7 @@ gboolean fu_colorhug_device_detach (FuColorhugDevice *device, GError **error) { FuColorhugDevicePrivate *priv = GET_PRIVATE (device); + GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (device)); g_autoptr(GError) error_local = NULL; /* set up progress callback */ @@ -108,7 +80,7 @@ fu_colorhug_device_detach (FuColorhugDevice *device, GError **error) priv->progress_data = NULL; g_debug ("rebooting..."); - ch_device_queue_reset (priv->device_queue, priv->usb_device); + ch_device_queue_reset (priv->device_queue, usb_device); if (!ch_device_queue_process (priv->device_queue, CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE, NULL, &error_local)) { @@ -126,6 +98,7 @@ gboolean fu_colorhug_device_attach (FuColorhugDevice *device, GError **error) { FuColorhugDevicePrivate *priv = GET_PRIVATE (device); + GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (device)); g_autoptr(GError) error_local = NULL; /* set up progress callback */ @@ -133,7 +106,7 @@ fu_colorhug_device_attach (FuColorhugDevice *device, GError **error) priv->progress_data = NULL; g_debug ("rebooting..."); - ch_device_queue_boot_flash (priv->device_queue, priv->usb_device); + ch_device_queue_boot_flash (priv->device_queue, usb_device); if (!ch_device_queue_process (priv->device_queue, CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE, NULL, &error_local)) { @@ -151,6 +124,7 @@ gboolean fu_colorhug_device_set_flash_success (FuColorhugDevice *device, GError **error) { FuColorhugDevicePrivate *priv = GET_PRIVATE (device); + GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (device)); g_autoptr(GError) error_local = NULL; /* set up progress callback */ @@ -159,7 +133,7 @@ fu_colorhug_device_set_flash_success (FuColorhugDevice *device, GError **error) g_debug ("setting flash success"); ch_device_queue_set_flash_success (priv->device_queue, - priv->usb_device, + usb_device, 0x01); if (!ch_device_queue_process (priv->device_queue, CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE, @@ -174,194 +148,17 @@ fu_colorhug_device_set_flash_success (FuColorhugDevice *device, GError **error) return TRUE; } -gboolean -fu_colorhug_device_open (FuColorhugDevice *device, GError **error) +static gboolean +fu_colorhug_device_open (FuUsbDevice *device, GError **error) { - FuColorhugDevicePrivate *priv = GET_PRIVATE (device); + FuColorhugDevice *self = FU_COLORHUG_DEVICE (device); + FuColorhugDevicePrivate *priv = GET_PRIVATE (self); + GUsbDevice *usb_device = fu_usb_device_get_dev (device); + ChDeviceMode mode; guint8 idx; gboolean got_version = FALSE; - g_autoptr(FuDeviceLocker) locker = NULL; - /* set up progress callback */ - priv->progress_cb = NULL; - priv->progress_data = NULL; - - /* already open */ - if (priv->usb_device_locker != NULL) - return TRUE; - - /* open */ - locker = fu_device_locker_new (priv->usb_device, error); - if (locker == NULL) - return FALSE; - if (!g_usb_device_set_configuration (priv->usb_device, CH_USB_CONFIG, error)) - return FALSE; - if (!g_usb_device_claim_interface (priv->usb_device, CH_USB_INTERFACE, - G_USB_DEVICE_CLAIM_INTERFACE_BIND_KERNEL_DRIVER, - error)) { - return FALSE; - } - - /* get version from descriptors */ - idx = g_usb_device_get_custom_index (priv->usb_device, - G_USB_DEVICE_CLASS_VENDOR_SPECIFIC, - 'F', 'W', NULL); - if (idx != 0x00) { - g_autofree gchar *tmp = NULL; - tmp = g_usb_device_get_string_descriptor (priv->usb_device, - idx, NULL); - if (tmp != NULL) { - got_version = TRUE; - g_debug ("obtained fwver using extension '%s'", tmp); - fu_device_set_version (FU_DEVICE (device), tmp); - } - } - - /* got things the old fashioned way */ - if (!got_version) { - guint16 major; - guint16 micro; - guint16 minor; - g_autofree gchar *version = NULL; - g_autoptr(GError) error_local = NULL; - ch_device_queue_get_firmware_ver (priv->device_queue, priv->usb_device, - &major, &minor, µ); - if (!ch_device_queue_process (priv->device_queue, - CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE, - NULL, &error_local)) { - g_warning ("failed to get firmware version: %s", - error_local->message); - } - got_version = TRUE; - version = g_strdup_printf ("%i.%i.%i", major, minor, micro); - g_debug ("obtained fwver using API '%s'", version); - fu_device_set_version (FU_DEVICE (device), version); - } - - /* success */ - priv->usb_device_locker = g_steal_pointer (&locker); - return TRUE; -} - -gboolean -fu_colorhug_device_close (FuColorhugDevice *device, GError **error) -{ - FuColorhugDevicePrivate *priv = GET_PRIVATE (device); - g_clear_object (&priv->usb_device_locker); - return TRUE; -} - -gboolean -fu_colorhug_device_verify_firmware (FuColorhugDevice *device, - GFileProgressCallback progress_cb, - gpointer progress_data, - GError **error) -{ - FuColorhugDevicePrivate *priv = GET_PRIVATE (device); - gsize len; - g_autoptr(GError) error_local = NULL; - g_autofree guint8 *data2 = NULL; - GChecksumType checksum_types[] = { - G_CHECKSUM_SHA1, - G_CHECKSUM_SHA256, - 0 }; - - /* set up progress callback */ - priv->progress_cb = progress_cb; - priv->progress_data = progress_data; - - /* get the firmware from the device */ - g_debug ("verifying firmware"); - ch_device_queue_read_firmware (priv->device_queue, priv->usb_device, - &data2, &len); - if (!ch_device_queue_process (priv->device_queue, - CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE, - NULL, &error_local)) { - g_set_error (error, - FWUPD_ERROR, - FWUPD_ERROR_WRITE, - "failed to dump firmware: %s", - error_local->message); - return FALSE; - } - - /* get the checksum */ - for (guint i = 0; checksum_types[i] != 0; i++) { - g_autofree gchar *hash = NULL; - hash = g_compute_checksum_for_data (checksum_types[i], - (guchar *) data2, len); - fu_device_add_checksum (device, hash); - } - - return TRUE; -} - -gboolean -fu_colorhug_device_write_firmware (FuColorhugDevice *device, GBytes *fw, - GFileProgressCallback progress_cb, - gpointer progress_data, - GError **error) -{ - FuColorhugDevicePrivate *priv = GET_PRIVATE (device); - g_autoptr(GError) error_local = NULL; - - /* set up progress callback */ - priv->progress_cb = progress_cb; - priv->progress_data = progress_data; - - g_debug ("writing firmware"); - ch_device_queue_set_flash_success (priv->device_queue, - priv->usb_device, - 0x00); - ch_device_queue_write_firmware (priv->device_queue, priv->usb_device, - g_bytes_get_data (fw, NULL), - g_bytes_get_size (fw)); - if (!ch_device_queue_process (priv->device_queue, - CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE, - NULL, &error_local)) { - g_set_error (error, - FWUPD_ERROR, - FWUPD_ERROR_WRITE, - "failed to write firmware: %s", - error_local->message); - return FALSE; - } - - /* verify firmware */ - g_debug ("verifying firmware"); - ch_device_queue_verify_firmware (priv->device_queue, priv->usb_device, - g_bytes_get_data (fw, NULL), - g_bytes_get_size (fw)); - if (!ch_device_queue_process (priv->device_queue, - CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE, - NULL, &error_local)) { - g_set_error (error, - FWUPD_ERROR, - FWUPD_ERROR_WRITE, - "failed to verify firmware: %s", - error_local->message); - return FALSE; - } - - /* success! */ - return TRUE; -} - -gboolean -fu_colorhug_device_set_usb_device (FuColorhugDevice *device, - GUsbDevice *usb_device, - GError **error) -{ - FuColorhugDevicePrivate *priv = GET_PRIVATE (device); - ChDeviceMode mode; - - g_set_object (&priv->usb_device, usb_device); - fu_device_set_platform_id (FU_DEVICE (device), - g_usb_device_get_platform_id (priv->usb_device)); - fu_device_set_vendor (FU_DEVICE (device), "Hughski Limited"); - fu_device_set_vendor_id (FU_DEVICE (device), "USB:0x273F"); - fu_device_set_equivalent_id (FU_DEVICE (device), - g_usb_device_get_platform_id (usb_device)); + /* add hardcoded bits */ fu_device_add_guid (FU_DEVICE (device), ch_device_get_guid (usb_device)); fu_device_add_icon (FU_DEVICE (device), "colorimeter-colorhug"); fu_device_add_flag (FU_DEVICE (device), FWUPD_DEVICE_FLAG_UPDATABLE); @@ -412,9 +209,175 @@ fu_colorhug_device_set_usb_device (FuColorhugDevice *device, break; } + /* set up progress callback */ + priv->progress_cb = NULL; + priv->progress_data = NULL; + + /* open */ + if (!g_usb_device_set_configuration (usb_device, CH_USB_CONFIG, error)) + return FALSE; + if (!g_usb_device_claim_interface (usb_device, CH_USB_INTERFACE, + G_USB_DEVICE_CLAIM_INTERFACE_BIND_KERNEL_DRIVER, + error)) { + return FALSE; + } + + /* get version from descriptors */ + idx = g_usb_device_get_custom_index (usb_device, + G_USB_DEVICE_CLASS_VENDOR_SPECIFIC, + 'F', 'W', NULL); + if (idx != 0x00) { + g_autofree gchar *tmp = NULL; + tmp = g_usb_device_get_string_descriptor (usb_device, + idx, NULL); + if (tmp != NULL) { + got_version = TRUE; + g_debug ("obtained fwver using extension '%s'", tmp); + fu_device_set_version (FU_DEVICE (device), tmp); + } + } + + /* got things the old fashioned way */ + if (!got_version) { + guint16 major; + guint16 micro; + guint16 minor; + g_autofree gchar *version = NULL; + g_autoptr(GError) error_local = NULL; + ch_device_queue_get_firmware_ver (priv->device_queue, usb_device, + &major, &minor, µ); + if (!ch_device_queue_process (priv->device_queue, + CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE, + NULL, &error_local)) { + g_warning ("failed to get firmware version: %s", + error_local->message); + } + got_version = TRUE; + version = g_strdup_printf ("%i.%i.%i", major, minor, micro); + g_debug ("obtained fwver using API '%s'", version); + fu_device_set_version (FU_DEVICE (device), version); + } + + /* success */ return TRUE; } +gboolean +fu_colorhug_device_verify_firmware (FuColorhugDevice *device, + GFileProgressCallback progress_cb, + gpointer progress_data, + GError **error) +{ + FuColorhugDevicePrivate *priv = GET_PRIVATE (device); + GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (device)); + gsize len; + g_autoptr(GError) error_local = NULL; + g_autofree guint8 *data2 = NULL; + GChecksumType checksum_types[] = { + G_CHECKSUM_SHA1, + G_CHECKSUM_SHA256, + 0 }; + + /* set up progress callback */ + priv->progress_cb = progress_cb; + priv->progress_data = progress_data; + + /* get the firmware from the device */ + g_debug ("verifying firmware"); + ch_device_queue_read_firmware (priv->device_queue, usb_device, + &data2, &len); + if (!ch_device_queue_process (priv->device_queue, + CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE, + NULL, &error_local)) { + g_set_error (error, + FWUPD_ERROR, + FWUPD_ERROR_WRITE, + "failed to dump firmware: %s", + error_local->message); + return FALSE; + } + + /* get the checksum */ + for (guint i = 0; checksum_types[i] != 0; i++) { + g_autofree gchar *hash = NULL; + hash = g_compute_checksum_for_data (checksum_types[i], + (guchar *) data2, len); + fu_device_add_checksum (device, hash); + } + + return TRUE; +} + +gboolean +fu_colorhug_device_write_firmware (FuColorhugDevice *device, GBytes *fw, + GFileProgressCallback progress_cb, + gpointer progress_data, + GError **error) +{ + FuColorhugDevicePrivate *priv = GET_PRIVATE (device); + GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (device)); + g_autoptr(GError) error_local = NULL; + + /* set up progress callback */ + priv->progress_cb = progress_cb; + priv->progress_data = progress_data; + + g_debug ("writing firmware"); + ch_device_queue_set_flash_success (priv->device_queue, + usb_device, + 0x00); + ch_device_queue_write_firmware (priv->device_queue, usb_device, + g_bytes_get_data (fw, NULL), + g_bytes_get_size (fw)); + if (!ch_device_queue_process (priv->device_queue, + CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE, + NULL, &error_local)) { + g_set_error (error, + FWUPD_ERROR, + FWUPD_ERROR_WRITE, + "failed to write firmware: %s", + error_local->message); + return FALSE; + } + + /* verify firmware */ + g_debug ("verifying firmware"); + ch_device_queue_verify_firmware (priv->device_queue, usb_device, + g_bytes_get_data (fw, NULL), + g_bytes_get_size (fw)); + if (!ch_device_queue_process (priv->device_queue, + CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE, + NULL, &error_local)) { + g_set_error (error, + FWUPD_ERROR, + FWUPD_ERROR_WRITE, + "failed to verify firmware: %s", + error_local->message); + return FALSE; + } + + /* success! */ + return TRUE; +} + +static void +fu_colorhug_device_init (FuColorhugDevice *device) +{ + FuColorhugDevicePrivate *priv = GET_PRIVATE (device); + priv->device_queue = ch_device_queue_new (); + g_signal_connect (priv->device_queue, "progress_changed", + G_CALLBACK (fu_colorhug_device_progress_cb), device); +} + +static void +fu_colorhug_device_class_init (FuColorhugDeviceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + FuUsbDeviceClass *klass_usb_device = FU_USB_DEVICE_CLASS (klass); + object_class->finalize = fu_colorhug_device_finalize; + klass_usb_device->open = fu_colorhug_device_open; +} + /** * fu_colorhug_device_new: * @@ -427,9 +390,9 @@ fu_colorhug_device_set_usb_device (FuColorhugDevice *device, FuColorhugDevice * fu_colorhug_device_new (GUsbDevice *usb_device) { - g_autoptr(FuColorhugDevice) device = NULL; - device = g_object_new (FU_TYPE_COLORHUG_DEVICE, NULL); - if (!fu_colorhug_device_set_usb_device (device, usb_device, NULL)) - return NULL; - return g_steal_pointer (&device); + FuColorhugDevice *device = NULL; + device = g_object_new (FU_TYPE_COLORHUG_DEVICE, + "usb-device", usb_device, + NULL); + return device; } diff --git a/plugins/colorhug/fu-colorhug-device.h b/plugins/colorhug/fu-colorhug-device.h index 57393cf58..ed4479741 100644 --- a/plugins/colorhug/fu-colorhug-device.h +++ b/plugins/colorhug/fu-colorhug-device.h @@ -30,23 +30,17 @@ G_BEGIN_DECLS #define FU_TYPE_COLORHUG_DEVICE (fu_colorhug_device_get_type ()) -G_DECLARE_DERIVABLE_TYPE (FuColorhugDevice, fu_colorhug_device, FU, COLORHUG_DEVICE, FuDevice) +G_DECLARE_DERIVABLE_TYPE (FuColorhugDevice, fu_colorhug_device, FU, COLORHUG_DEVICE, FuUsbDevice) struct _FuColorhugDeviceClass { - FuDeviceClass parent_class; + FuUsbDeviceClass parent_class; }; FuColorhugDevice *fu_colorhug_device_new (GUsbDevice *usb_device); -gboolean fu_colorhug_device_set_usb_device (FuColorhugDevice *device, - GUsbDevice *usb_device, - GError **error); -GUsbDevice *fu_colorhug_device_get_usb_device (FuColorhugDevice *device); gboolean fu_colorhug_device_get_is_bootloader (FuColorhugDevice *device); /* object methods */ -gboolean fu_colorhug_device_open (FuColorhugDevice *device, - GError **error); gboolean fu_colorhug_device_close (FuColorhugDevice *device, GError **error); gboolean fu_colorhug_device_detach (FuColorhugDevice *device, diff --git a/plugins/colorhug/fu-plugin-colorhug.c b/plugins/colorhug/fu-plugin-colorhug.c index acac0b2d1..d242a1bcf 100644 --- a/plugins/colorhug/fu-plugin-colorhug.c +++ b/plugins/colorhug/fu-plugin-colorhug.c @@ -21,7 +21,6 @@ #include "config.h" -#include #include #include @@ -34,14 +33,12 @@ gboolean fu_plugin_update_detach (FuPlugin *plugin, FuDevice *device, GError **error) { FuColorhugDevice *colorhug_dev = FU_COLORHUG_DEVICE (device); + GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (device)); g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(GUsbDevice) usb_device2 = NULL; /* open device */ - locker = fu_device_locker_new_full (colorhug_dev, - (FuDeviceLockerFunc) fu_colorhug_device_open, - (FuDeviceLockerFunc) fu_colorhug_device_close, - error); + locker = fu_device_locker_new (device, error); if (locker == NULL) return FALSE; @@ -59,7 +56,7 @@ fu_plugin_update_detach (FuPlugin *plugin, FuDevice *device, GError **error) /* wait for replug */ g_clear_object (&locker); usb_device2 = g_usb_context_wait_for_replug (fu_plugin_get_usb_context (plugin), - fu_colorhug_device_get_usb_device (colorhug_dev), + usb_device, 10000, error); if (usb_device2 == NULL) { g_prefix_error (error, "device did not come back: "); @@ -67,7 +64,7 @@ fu_plugin_update_detach (FuPlugin *plugin, FuDevice *device, GError **error) } /* set the new device until we can use a new FuDevice */ - fu_colorhug_device_set_usb_device (colorhug_dev, usb_device2, NULL); + fu_usb_device_set_dev (FU_USB_DEVICE (colorhug_dev), usb_device2); /* success */ return TRUE; @@ -77,14 +74,12 @@ gboolean fu_plugin_update_attach (FuPlugin *plugin, FuDevice *device, GError **error) { FuColorhugDevice *colorhug_dev = FU_COLORHUG_DEVICE (device); + GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (device)); g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(GUsbDevice) usb_device2 = NULL; /* open device */ - locker = fu_device_locker_new_full (colorhug_dev, - (FuDeviceLockerFunc) fu_colorhug_device_open, - (FuDeviceLockerFunc) fu_colorhug_device_close, - error); + locker = fu_device_locker_new (device, error); if (locker == NULL) return FALSE; @@ -102,7 +97,7 @@ fu_plugin_update_attach (FuPlugin *plugin, FuDevice *device, GError **error) /* wait for replug */ g_clear_object (&locker); usb_device2 = g_usb_context_wait_for_replug (fu_plugin_get_usb_context (plugin), - fu_colorhug_device_get_usb_device (colorhug_dev), + usb_device, 10000, error); if (usb_device2 == NULL) { g_prefix_error (error, "device did not come back: "); @@ -110,7 +105,7 @@ fu_plugin_update_attach (FuPlugin *plugin, FuDevice *device, GError **error) } /* set the new device until we can use a new FuDevice */ - fu_colorhug_device_set_usb_device (colorhug_dev, usb_device2, NULL); + fu_usb_device_set_dev (FU_USB_DEVICE (colorhug_dev), usb_device2); /* success */ return TRUE; @@ -123,10 +118,7 @@ fu_plugin_update_reload (FuPlugin *plugin, FuDevice *device, GError **error) g_autoptr(FuDeviceLocker) locker = NULL; /* also set flash success */ - locker = fu_device_locker_new_full (colorhug_dev, - (FuDeviceLockerFunc) fu_colorhug_device_open, - (FuDeviceLockerFunc) fu_colorhug_device_close, - error); + locker = fu_device_locker_new (device, error); if (locker == NULL) return FALSE; if (!fu_colorhug_device_set_flash_success (colorhug_dev, error)) @@ -149,11 +141,12 @@ fu_plugin_update (FuPlugin *plugin, GError **error) { FuColorhugDevice *colorhug_dev = FU_COLORHUG_DEVICE (device); + GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (device)); g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(GError) error_local = NULL; /* check this firmware is actually for this device */ - if (!ch_device_check_firmware (fu_colorhug_device_get_usb_device (colorhug_dev), + if (!ch_device_check_firmware (usb_device, g_bytes_get_data (blob_fw, NULL), g_bytes_get_size (blob_fw), &error_local)) { @@ -166,10 +159,7 @@ fu_plugin_update (FuPlugin *plugin, } /* write firmware */ - locker = fu_device_locker_new_full (colorhug_dev, - (FuDeviceLockerFunc) fu_colorhug_device_open, - (FuDeviceLockerFunc) fu_colorhug_device_close, - error); + locker = fu_device_locker_new (device, error); if (locker == NULL) return FALSE; fu_plugin_set_status (plugin, FWUPD_STATUS_DEVICE_WRITE); @@ -189,10 +179,7 @@ fu_plugin_verify (FuPlugin *plugin, g_autoptr(FuDeviceLocker) locker = NULL; /* write firmware */ - locker = fu_device_locker_new_full (colorhug_dev, - (FuDeviceLockerFunc) fu_colorhug_device_open, - (FuDeviceLockerFunc) fu_colorhug_device_close, - error); + locker = fu_device_locker_new (device, error); if (locker == NULL) return FALSE; fu_plugin_set_status (plugin, FWUPD_STATUS_DEVICE_VERIFY); @@ -208,10 +195,8 @@ fu_plugin_colorhug_device_added_cb (GUsbContext *ctx, FuPlugin *plugin) { ChDeviceMode mode; - g_autoptr(AsProfile) profile = as_profile_new (); - g_autoptr(AsProfileTask) ptask = NULL; g_autoptr(FuDeviceLocker) locker = NULL; - g_autoptr(FuColorhugDevice) dev = NULL; + g_autoptr(FuColorhugDevice) device = NULL; g_autoptr(GError) error = NULL; /* ignore */ @@ -224,32 +209,17 @@ fu_plugin_colorhug_device_added_cb (GUsbContext *ctx, mode == CH_DEVICE_MODE_FIRMWARE_PLUS) return; - /* profile */ - ptask = as_profile_start (profile, "FuPluginColorhug:added{%04x:%04x}", - g_usb_device_get_vid (usb_device), - g_usb_device_get_pid (usb_device)); - g_assert (ptask != NULL); - - /* create the device */ - dev = fu_colorhug_device_new (usb_device); - if (dev == NULL) { - g_warning ("invalid device type detected!"); - return; - } - /* open the device */ - locker = fu_device_locker_new_full (dev, - (FuDeviceLockerFunc) fu_colorhug_device_open, - (FuDeviceLockerFunc) fu_colorhug_device_close, - &error); + device = fu_colorhug_device_new (usb_device); + locker = fu_device_locker_new (device, &error); if (locker == NULL) { g_warning ("failed to open device: %s", error->message); return; } /* insert to hash */ - fu_plugin_device_add (plugin, FU_DEVICE (dev)); - fu_plugin_cache_add (plugin, g_usb_device_get_platform_id (usb_device), dev); + fu_plugin_device_add (plugin, FU_DEVICE (device)); + fu_plugin_cache_add (plugin, g_usb_device_get_platform_id (usb_device), device); } static void @@ -257,16 +227,16 @@ fu_plugin_colorhug_device_removed_cb (GUsbContext *ctx, GUsbDevice *usb_device, FuPlugin *plugin) { - FuDevice *dev; + FuDevice *device; const gchar *platform_id = NULL; /* already in database */ platform_id = g_usb_device_get_platform_id (usb_device); - dev = fu_plugin_cache_lookup (plugin, platform_id); - if (dev == NULL) + device = fu_plugin_cache_lookup (plugin, platform_id); + if (device == NULL) return; - fu_plugin_device_remove (plugin, dev); + fu_plugin_device_remove (plugin, device); fu_plugin_cache_remove (plugin, platform_id); } diff --git a/plugins/ebitdo/fu-ebitdo-device.c b/plugins/ebitdo/fu-ebitdo-device.c index 8d9d35756..b8dbe471e 100644 --- a/plugins/ebitdo/fu-ebitdo-device.c +++ b/plugins/ebitdo/fu-ebitdo-device.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * - * Copyright (C) 2016 Richard Hughes + * Copyright (C) 2016-2017 Richard Hughes * * Licensed under the GNU Lesser General Public License Version 2.1 * @@ -30,12 +30,10 @@ typedef struct { FuEbitdoDeviceKind kind; - GUsbDevice *usb_device; - FuDeviceLocker *usb_device_locker; guint32 serial[9]; } FuEbitdoDevicePrivate; -G_DEFINE_TYPE_WITH_PRIVATE (FuEbitdoDevice, fu_ebitdo_device, FU_TYPE_DEVICE) +G_DEFINE_TYPE_WITH_PRIVATE (FuEbitdoDevice, fu_ebitdo_device, FU_TYPE_USB_DEVICE) #define GET_PRIVATE(o) (fu_ebitdo_device_get_instance_private (o)) @@ -103,32 +101,6 @@ fu_ebitdo_device_kind_to_string (FuEbitdoDeviceKind kind) return NULL; } -static void -fu_ebitdo_device_finalize (GObject *object) -{ - FuEbitdoDevice *device = FU_EBITDO_DEVICE (object); - FuEbitdoDevicePrivate *priv = GET_PRIVATE (device); - - if (priv->usb_device_locker != NULL) - g_object_unref (priv->usb_device_locker); - if (priv->usb_device != NULL) - g_object_unref (priv->usb_device); - - G_OBJECT_CLASS (fu_ebitdo_device_parent_class)->finalize (object); -} - -static void -fu_ebitdo_device_init (FuEbitdoDevice *device) -{ -} - -static void -fu_ebitdo_device_class_init (FuEbitdoDeviceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - object_class->finalize = fu_ebitdo_device_finalize; -} - FuEbitdoDeviceKind fu_ebitdo_device_get_kind (FuEbitdoDevice *device) { @@ -146,6 +118,7 @@ fu_ebitdo_device_send (FuEbitdoDevice *device, GError **error) { FuEbitdoDevicePrivate *priv = GET_PRIVATE (device); + GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (device)); guint8 packet[FU_EBITDO_USB_EP_SIZE]; gsize actual_length; guint8 ep_out = FU_EBITDO_USB_RUNTIME_EP_OUT; @@ -190,7 +163,7 @@ fu_ebitdo_device_send (FuEbitdoDevice *device, } /* get data from device */ - if (!g_usb_device_interrupt_transfer (priv->usb_device, + if (!g_usb_device_interrupt_transfer (usb_device, ep_out, packet, FU_EBITDO_USB_EP_SIZE, @@ -216,6 +189,7 @@ fu_ebitdo_device_receive (FuEbitdoDevice *device, GError **error) { FuEbitdoDevicePrivate *priv = GET_PRIVATE (device); + GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (device)); guint8 packet[FU_EBITDO_USB_EP_SIZE]; gsize actual_length; guint8 ep_in = FU_EBITDO_USB_RUNTIME_EP_IN; @@ -228,7 +202,7 @@ fu_ebitdo_device_receive (FuEbitdoDevice *device, /* get data from device */ memset (packet, 0x0, sizeof(packet)); - if (!g_usb_device_interrupt_transfer (priv->usb_device, + if (!g_usb_device_interrupt_transfer (usb_device, ep_in, packet, FU_EBITDO_USB_EP_SIZE, @@ -342,7 +316,7 @@ fu_ebitdo_device_set_version (FuEbitdoDevice *device, guint32 version) static gboolean fu_ebitdo_device_validate (FuEbitdoDevice *device, GError **error) { - FuEbitdoDevicePrivate *priv = GET_PRIVATE (device); + GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (device)); guint8 idx; g_autofree gchar *ven = NULL; const gchar *whitelist[] = { @@ -351,12 +325,12 @@ fu_ebitdo_device_validate (FuEbitdoDevice *device, GError **error) NULL }; /* this is a new, always valid, VID */ - if (g_usb_device_get_vid (priv->usb_device) == 0x2dc8) + if (g_usb_device_get_vid (usb_device) == 0x2dc8) return TRUE; /* verify the vendor prefix against a whitelist */ - idx = g_usb_device_get_manufacturer_index (priv->usb_device); - ven = g_usb_device_get_string_descriptor (priv->usb_device, idx, error); + idx = g_usb_device_get_manufacturer_index (usb_device); + ven = g_usb_device_get_string_descriptor (usb_device, idx, error); if (ven == NULL) { g_prefix_error (error, "could not check vendor descriptor: "); return FALSE; @@ -373,27 +347,21 @@ fu_ebitdo_device_validate (FuEbitdoDevice *device, GError **error) return FALSE; } -gboolean -fu_ebitdo_device_open (FuEbitdoDevice *device, GError **error) +static gboolean +fu_ebitdo_device_open (FuUsbDevice *device, GError **error) { - FuEbitdoDevicePrivate *priv = GET_PRIVATE (device); + FuEbitdoDevice *self = FU_EBITDO_DEVICE (device); + FuEbitdoDevicePrivate *priv = GET_PRIVATE (self); + GUsbDevice *usb_device = fu_usb_device_get_dev (device); gdouble tmp; guint32 version_tmp = 0; guint32 serial_tmp[9]; - g_autoptr(FuDeviceLocker) locker = NULL; - - /* already open */ - if (priv->usb_device_locker != NULL) - return TRUE; /* open, then ensure this is actually 8Bitdo hardware */ g_debug ("opening %s", fu_ebitdo_device_kind_to_string (priv->kind)); - locker = fu_device_locker_new (priv->usb_device, error); - if (locker == NULL) + if (!fu_ebitdo_device_validate (self, error)) return FALSE; - if (!fu_ebitdo_device_validate (device, error)) - return FALSE; - if (!g_usb_device_claim_interface (priv->usb_device, 0, /* 0 = idx? */ + if (!g_usb_device_claim_interface (usb_device, 0, /* 0 = idx? */ G_USB_DEVICE_CLAIM_INTERFACE_BIND_KERNEL_DRIVER, error)) { return FALSE; @@ -401,7 +369,7 @@ fu_ebitdo_device_open (FuEbitdoDevice *device, GError **error) /* in firmware mode */ if (priv->kind != FU_EBITDO_DEVICE_KIND_BOOTLOADER) { - if (!fu_ebitdo_device_send (device, + if (!fu_ebitdo_device_send (self, FU_EBITDO_PKT_TYPE_USER_CMD, FU_EBITDO_PKT_CMD_GET_VERSION, 0, @@ -409,19 +377,19 @@ fu_ebitdo_device_open (FuEbitdoDevice *device, GError **error) error)) { return FALSE; } - if (!fu_ebitdo_device_receive (device, + if (!fu_ebitdo_device_receive (self, (guint8 *) &version_tmp, sizeof(version_tmp), error)) { return FALSE; } tmp = (gdouble) GUINT32_FROM_LE (version_tmp); - fu_ebitdo_device_set_version (device, tmp); + fu_ebitdo_device_set_version (self, tmp); return TRUE; } /* get version */ - if (!fu_ebitdo_device_send (device, + if (!fu_ebitdo_device_send (self, FU_EBITDO_PKT_TYPE_USER_CMD, FU_EBITDO_PKT_CMD_UPDATE_FIRMWARE_DATA, FU_EBITDO_PKT_CMD_FW_GET_VERSION, @@ -429,17 +397,17 @@ fu_ebitdo_device_open (FuEbitdoDevice *device, GError **error) error)) { return FALSE; } - if (!fu_ebitdo_device_receive (device, + if (!fu_ebitdo_device_receive (self, (guint8 *) &version_tmp, sizeof(version_tmp), error)) { return FALSE; } tmp = (gdouble) GUINT32_FROM_LE (version_tmp); - fu_ebitdo_device_set_version (device, tmp); + fu_ebitdo_device_set_version (self, tmp); /* get verification ID */ - if (!fu_ebitdo_device_send (device, + if (!fu_ebitdo_device_send (self, FU_EBITDO_PKT_TYPE_USER_CMD, FU_EBITDO_PKT_CMD_GET_VERIFICATION_ID, 0x00, /* cmd */ @@ -448,7 +416,7 @@ fu_ebitdo_device_open (FuEbitdoDevice *device, GError **error) return FALSE; } memset (serial_tmp, 0x00, sizeof (serial_tmp)); - if (!fu_ebitdo_device_receive (device, + if (!fu_ebitdo_device_receive (self, (guint8 *) &serial_tmp, sizeof(serial_tmp), error)) { return FALSE; @@ -457,15 +425,6 @@ fu_ebitdo_device_open (FuEbitdoDevice *device, GError **error) priv->serial[i] = GUINT32_FROM_LE (serial_tmp[i]); /* success */ - priv->usb_device_locker = g_steal_pointer (&locker); - return TRUE; -} - -gboolean -fu_ebitdo_device_close (FuEbitdoDevice *device, GError **error) -{ - FuEbitdoDevicePrivate *priv = GET_PRIVATE (device); - g_clear_object (&priv->usb_device_locker); return TRUE; } @@ -646,17 +605,11 @@ static void fu_ebitdo_device_init_real (FuEbitdoDevice *device) { FuEbitdoDevicePrivate *priv = GET_PRIVATE (device); - g_autofree gchar *devid1 = NULL; g_autofree gchar *name = NULL; - g_autofree gchar *vendor_id = NULL; /* allowed, but requires manual bootloader step */ fu_device_add_flag (FU_DEVICE (device), FWUPD_DEVICE_FLAG_UPDATABLE); - /* set USB platform ID */ - fu_device_set_platform_id (FU_DEVICE (device), - g_usb_device_get_platform_id (priv->usb_device)); - /* set name and vendor */ name = g_strdup_printf ("%s Gamepad", fu_ebitdo_device_kind_to_string (priv->kind)); @@ -665,20 +618,9 @@ fu_ebitdo_device_init_real (FuEbitdoDevice *device) "A redesigned classic game controller"); fu_device_set_vendor (FU_DEVICE (device), "8Bitdo"); - /* set vendor ID */ - vendor_id = g_strdup_printf ("USB:0x%04X", g_usb_device_get_vid (priv->usb_device)); - fu_device_set_vendor_id (FU_DEVICE (device), vendor_id); - /* add a hardcoded icon name */ fu_device_add_icon (FU_DEVICE (device), "input-gaming"); - /* add USB\VID_0000&PID_0000 */ - devid1 = g_strdup_printf ("USB\\VID_%04X&PID_%04X", - g_usb_device_get_vid (priv->usb_device), - g_usb_device_get_pid (priv->usb_device)); - fu_device_add_guid (FU_DEVICE (device), devid1); - g_debug ("saving runtime GUID of %s", devid1); - /* only the bootloader can do the update */ if (priv->kind != FU_EBITDO_DEVICE_KIND_BOOTLOADER) { fu_device_add_flag (FU_DEVICE (device), @@ -692,12 +634,9 @@ typedef struct { FuEbitdoDeviceKind kind; } FuEbitdoVidPid; -gboolean -fu_ebitdo_device_set_usb_device (FuEbitdoDevice *device, - GUsbDevice *usb_device, - GError **error) +FuEbitdoDeviceKind +fu_ebitdo_device_kind_from_dev (GUsbDevice *usb_device) { - FuEbitdoDevicePrivate *priv = GET_PRIVATE (device); const FuEbitdoVidPid vidpids[] = { /* legacy VIDs */ { 0x0483, 0x5750, FU_EBITDO_DEVICE_KIND_BOOTLOADER }, @@ -722,22 +661,23 @@ fu_ebitdo_device_set_usb_device (FuEbitdoDevice *device, /* find correct kind */ for (guint j = 0; vidpids[j].vid != 0x0000; j++) { - if (g_usb_device_get_vid (usb_device) != vidpids[j].vid) - continue; - if (g_usb_device_get_pid (usb_device) != vidpids[j].pid) - continue; - priv->kind = vidpids[j].kind; - g_set_object (&priv->usb_device, usb_device); - fu_ebitdo_device_init_real (device); - return TRUE; + if (g_usb_device_get_vid (usb_device) == vidpids[j].vid && + g_usb_device_get_pid (usb_device) == vidpids[j].pid) + return vidpids[j].kind; } + return FU_EBITDO_DEVICE_KIND_UNKNOWN; +} - /* unsupported */ - g_set_error_literal (error, - G_IO_ERROR, - G_IO_ERROR_NOT_SUPPORTED, - "not a supported 8Bitdo game-pad"); - return FALSE; +static void +fu_ebitdo_device_init (FuEbitdoDevice *device) +{ +} + +static void +fu_ebitdo_device_class_init (FuEbitdoDeviceClass *klass) +{ + FuUsbDeviceClass *klass_usb_device = FU_USB_DEVICE_CLASS (klass); + klass_usb_device->open = fu_ebitdo_device_open; } /** @@ -750,11 +690,15 @@ fu_ebitdo_device_set_usb_device (FuEbitdoDevice *device, * Since: 0.1.0 **/ FuEbitdoDevice * -fu_ebitdo_device_new (GUsbDevice *usb_device) +fu_ebitdo_device_new (FuEbitdoDeviceKind kind, GUsbDevice *usb_device) { - g_autoptr(FuEbitdoDevice) device = NULL; - device = g_object_new (FU_TYPE_EBITDO_DEVICE, NULL); - if (!fu_ebitdo_device_set_usb_device (device, usb_device, NULL)) - return NULL; - return g_steal_pointer (&device); + FuEbitdoDevice *device; + FuEbitdoDevicePrivate *priv; + device = g_object_new (FU_TYPE_EBITDO_DEVICE, + "usb-device", usb_device, + NULL); + priv = GET_PRIVATE (device); + priv->kind = kind; + fu_ebitdo_device_init_real (device); + return FU_EBITDO_DEVICE (device); } diff --git a/plugins/ebitdo/fu-ebitdo-device.h b/plugins/ebitdo/fu-ebitdo-device.h index 8605383a6..4b91eb081 100644 --- a/plugins/ebitdo/fu-ebitdo-device.h +++ b/plugins/ebitdo/fu-ebitdo-device.h @@ -30,11 +30,11 @@ G_BEGIN_DECLS #define FU_TYPE_EBITDO_DEVICE (fu_ebitdo_device_get_type ()) -G_DECLARE_DERIVABLE_TYPE (FuEbitdoDevice, fu_ebitdo_device, FU, EBITDO_DEVICE, FuDevice) +G_DECLARE_DERIVABLE_TYPE (FuEbitdoDevice, fu_ebitdo_device, FU, EBITDO_DEVICE, FuUsbDevice) struct _FuEbitdoDeviceClass { - FuDeviceClass parent_class; + FuUsbDeviceClass parent_class; }; typedef enum { @@ -51,13 +51,12 @@ typedef enum { FU_EBITDO_DEVICE_KIND_LAST } FuEbitdoDeviceKind; -FuEbitdoDevice *fu_ebitdo_device_new (GUsbDevice *usb_device); -gboolean fu_ebitdo_device_set_usb_device (FuEbitdoDevice *device, - GUsbDevice *usb_device, - GError **error); +FuEbitdoDevice *fu_ebitdo_device_new (FuEbitdoDeviceKind kind, + GUsbDevice *usb_device); /* helpers */ FuEbitdoDeviceKind fu_ebitdo_device_kind_from_string (const gchar *kind); +FuEbitdoDeviceKind fu_ebitdo_device_kind_from_dev (GUsbDevice *usb_device); const gchar *fu_ebitdo_device_kind_to_string (FuEbitdoDeviceKind kind); /* getters */ @@ -65,10 +64,6 @@ FuEbitdoDeviceKind fu_ebitdo_device_get_kind (FuEbitdoDevice *device); const guint32 *fu_ebitdo_device_get_serial (FuEbitdoDevice *device); /* object methods */ -gboolean fu_ebitdo_device_open (FuEbitdoDevice *device, - GError **error); -gboolean fu_ebitdo_device_close (FuEbitdoDevice *device, - GError **error); gboolean fu_ebitdo_device_write_firmware (FuEbitdoDevice *device, GBytes *fw, GFileProgressCallback progress_cb, diff --git a/plugins/ebitdo/fu-ebitdo-tool.c b/plugins/ebitdo/fu-ebitdo-tool.c index 7ff3006ea..6854323bd 100644 --- a/plugins/ebitdo/fu-ebitdo-tool.c +++ b/plugins/ebitdo/fu-ebitdo-tool.c @@ -65,10 +65,11 @@ main (int argc, char **argv) g_usb_context_enumerate (usb_ctx); devices = g_usb_context_get_devices (usb_ctx); for (guint i = 0; i < devices->len; i++) { - GUsbDevice *usb_dev_tmp = g_ptr_array_index (devices, i); - g_autoptr(FuEbitdoDevice) dev_tmp = fu_ebitdo_device_new (usb_dev_tmp); - if (dev_tmp != NULL) { - dev = g_object_ref (dev_tmp); + GUsbDevice *usb_device = g_ptr_array_index (devices, i); + FuEbitdoDeviceKind ebitdo_kind; + ebitdo_kind = fu_ebitdo_device_kind_from_dev (usb_device); + if (ebitdo_kind != FU_EBITDO_DEVICE_KIND_UNKNOWN) { + dev = fu_ebitdo_device_new (ebitdo_kind, usb_device); break; } } @@ -80,10 +81,7 @@ main (int argc, char **argv) } /* open device */ - locker = fu_device_locker_new_full (dev, - (FuDeviceLockerFunc) fu_ebitdo_device_open, - (FuDeviceLockerFunc) fu_ebitdo_device_close, - &error); + locker = fu_device_locker_new (dev, &error); if (locker == NULL) { g_print ("Failed to open USB device: %s\n", error->message); return 1; diff --git a/plugins/ebitdo/fu-plugin-ebitdo.c b/plugins/ebitdo/fu-plugin-ebitdo.c index 62d7addb5..24f3e984f 100644 --- a/plugins/ebitdo/fu-plugin-ebitdo.c +++ b/plugins/ebitdo/fu-plugin-ebitdo.c @@ -21,8 +21,6 @@ #include "config.h" -#include - #include "fu-ebitdo-device.h" #include "fu-plugin.h" @@ -36,35 +34,19 @@ fu_plugin_ebitdo_device_added (FuPlugin *plugin, FuEbitdoDeviceKind ebitdo_kind; const gchar *platform_id = NULL; g_autofree gchar *runtime_id = NULL; - g_autoptr(AsProfile) profile = as_profile_new (); - g_autoptr(AsProfileTask) ptask = NULL; g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(FuEbitdoDevice) dev = NULL; - /* ignore hubs */ - ptask = as_profile_start (profile, "FuPluginEbitdo:added{%04x:%04x}", - g_usb_device_get_vid (usb_device), - g_usb_device_get_pid (usb_device)); - g_assert (ptask != NULL); - - /* create the device */ - dev = fu_ebitdo_device_new (usb_device); - if (dev == NULL) { - g_set_error_literal (error, - FWUPD_ERROR, - FWUPD_ERROR_NOT_SUPPORTED, - "invalid 8Bitdo device type detected"); - return FALSE; - } + /* ignore wrong hardware */ + ebitdo_kind = fu_ebitdo_device_kind_from_dev (usb_device); + if (ebitdo_kind == FU_EBITDO_DEVICE_KIND_UNKNOWN) + return TRUE; /* open the device */ - locker = fu_device_locker_new_full (dev, - (FuDeviceLockerFunc) fu_ebitdo_device_open, - (FuDeviceLockerFunc) fu_ebitdo_device_close, - error); + dev = fu_ebitdo_device_new (ebitdo_kind, usb_device); + locker = fu_device_locker_new (dev, error); if (locker == NULL) return FALSE; - ebitdo_kind = fu_ebitdo_device_get_kind (dev); /* only the bootloader can do the update */ platform_id = g_usb_device_get_platform_id (usb_device); @@ -108,18 +90,12 @@ fu_plugin_update (FuPlugin *plugin, FwupdInstallFlags flags, GError **error) { - GUsbContext *usb_ctx = fu_plugin_get_usb_context (plugin); + GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (dev)); FuEbitdoDevice *ebitdo_dev = FU_EBITDO_DEVICE (dev); g_autoptr(FuDeviceLocker) locker = NULL; - g_autoptr(GUsbDevice) usb_device = NULL; g_autoptr(GUsbDevice) usb_device2 = NULL; /* get version */ - usb_device = g_usb_context_find_by_platform_id (usb_ctx, - fu_device_get_platform_id (dev), - error); - if (usb_device == NULL) - return FALSE; if (fu_ebitdo_device_get_kind (ebitdo_dev) != FU_EBITDO_DEVICE_KIND_BOOTLOADER) { g_set_error_literal (error, FWUPD_ERROR, @@ -129,10 +105,7 @@ fu_plugin_update (FuPlugin *plugin, } /* write the firmware */ - locker = fu_device_locker_new_full (ebitdo_dev, - (FuDeviceLockerFunc) fu_ebitdo_device_open, - (FuDeviceLockerFunc) fu_ebitdo_device_close, - error); + locker = fu_device_locker_new (ebitdo_dev, error); if (locker == NULL) return FALSE; fu_plugin_set_status (plugin, FWUPD_STATUS_DEVICE_WRITE); @@ -155,10 +128,7 @@ fu_plugin_update (FuPlugin *plugin, g_prefix_error (error, "device did not come back: "); return FALSE; } - if (!fu_ebitdo_device_set_usb_device (ebitdo_dev, usb_device2, error)) { - g_prefix_error (error, "wrong device came back: "); - return FALSE; - } + fu_usb_device_set_dev (FU_USB_DEVICE (ebitdo_dev), usb_device2); /* success */ return TRUE; @@ -171,10 +141,7 @@ fu_plugin_update_reload (FuPlugin *plugin, FuDevice *dev, GError **error) g_autoptr(FuDeviceLocker) locker = NULL; /* get the new version number */ - locker = fu_device_locker_new_full (ebitdo_dev, - (FuDeviceLockerFunc) fu_ebitdo_device_open, - (FuDeviceLockerFunc) fu_ebitdo_device_close, - error); + locker = fu_device_locker_new (ebitdo_dev, error); if (locker == NULL) { g_prefix_error (error, "failed to re-open device: "); return FALSE; diff --git a/plugins/nitrokey/fu-nitrokey-device.c b/plugins/nitrokey/fu-nitrokey-device.c index c34bbb8db..ebaf71ce9 100644 --- a/plugins/nitrokey/fu-nitrokey-device.c +++ b/plugins/nitrokey/fu-nitrokey-device.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * - * Copyright (C) 2016 Richard Hughes + * Copyright (C) 2016-2017 Richard Hughes * * Licensed under the GNU Lesser General Public License Version 2.1 * @@ -27,15 +27,7 @@ #include "fu-nitrokey-common.h" #include "fu-nitrokey-device.h" -typedef struct -{ - GUsbDevice *usb_device; - FuDeviceLocker *usb_device_locker; -} FuNitrokeyDevicePrivate; - -G_DEFINE_TYPE_WITH_PRIVATE (FuNitrokeyDevice, fu_nitrokey_device, FU_TYPE_DEVICE) - -#define GET_PRIVATE(o) (fu_nitrokey_device_get_instance_private (o)) +G_DEFINE_TYPE (FuNitrokeyDevice, fu_nitrokey_device, FU_TYPE_USB_DEVICE) #define NITROKEY_TRANSACTION_TIMEOUT 100 /* ms */ #define NITROKEY_NR_RETRIES 5 @@ -87,33 +79,6 @@ typedef struct __attribute__((packed)) { guint8 StickKeysNotInitiated; } NitrokeyGetDeviceStatusPayload; -static void -fu_nitrokey_device_finalize (GObject *object) -{ - FuNitrokeyDevice *device = FU_NITROKEY_DEVICE (object); - FuNitrokeyDevicePrivate *priv = GET_PRIVATE (device); - - if (priv->usb_device_locker != NULL) - g_object_unref (priv->usb_device_locker); - if (priv->usb_device != NULL) - g_object_unref (priv->usb_device); - - G_OBJECT_CLASS (fu_nitrokey_device_parent_class)->finalize (object); -} - -static void -fu_nitrokey_device_init (FuNitrokeyDevice *device) -{ -} - -static void -fu_nitrokey_device_class_init (FuNitrokeyDeviceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - object_class->finalize = fu_nitrokey_device_finalize; -} - - static void _dump_to_console (const gchar *title, const guint8 *buf, gsize buf_sz) { @@ -258,29 +223,18 @@ nitrokey_execute_cmd_full (GUsbDevice *usb_device, guint8 command, return FALSE; } -gboolean -fu_nitrokey_device_open (FuNitrokeyDevice *device, GError **error) +static gboolean +fu_nitrokey_device_open (FuUsbDevice *device, GError **error) { - FuNitrokeyDevicePrivate *priv = GET_PRIVATE (device); - g_autofree gchar *vendor_id = NULL; + GUsbDevice *usb_device = fu_usb_device_get_dev (device); NitrokeyGetDeviceStatusPayload payload; - const gchar *platform_id = NULL; guint8 buf_reply[NITROKEY_REPLY_DATA_LENGTH]; - g_autofree gchar *devid1 = NULL; g_autofree gchar *platform_id_fixed = NULL; g_autofree gchar *version = NULL; - g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(GError) error_local = NULL; - /* already open */ - if (priv->usb_device_locker != NULL) - return TRUE; - - /* open, then ensure this is actually 8Bitdo hardware */ - locker = fu_device_locker_new (priv->usb_device, error); - if (locker == NULL) - return FALSE; - if (!g_usb_device_claim_interface (priv->usb_device, 0x02, /* idx */ + /* claim interface */ + if (!g_usb_device_claim_interface (usb_device, 0x02, /* idx */ G_USB_DEVICE_CLAIM_INTERFACE_BIND_KERNEL_DRIVER, error)) { g_prefix_error (error, "failed to do claim nitrokey: "); @@ -288,7 +242,7 @@ fu_nitrokey_device_open (FuNitrokeyDevice *device, GError **error) } /* get firmware version */ - if (!nitrokey_execute_cmd_full (priv->usb_device, + if (!nitrokey_execute_cmd_full (usb_device, NITROKEY_CMD_GET_DEVICE_STATUS, NULL, 0, buf_reply, sizeof(buf_reply), @@ -299,12 +253,6 @@ fu_nitrokey_device_open (FuNitrokeyDevice *device, GError **error) _dump_to_console ("payload", buf_reply, sizeof(buf_reply)); memcpy (&payload, buf_reply, sizeof(buf_reply)); - /* we use a modified version of the platform ID so we can have multiple - * FuDeviceItems for the same device -- when we can have the same device - * handled by multiple plugins this won't be required... */ - platform_id = g_usb_device_get_platform_id (priv->usb_device); - platform_id_fixed = g_strdup_printf ("%s_workaround", platform_id); - fu_device_set_platform_id (FU_DEVICE (device), platform_id_fixed); fu_device_set_name (FU_DEVICE (device), "Nitrokey Storage"); fu_device_set_vendor (FU_DEVICE (device), "Nitrokey"); fu_device_set_summary (FU_DEVICE (device), "A secure memory stick"); @@ -312,54 +260,48 @@ fu_nitrokey_device_open (FuNitrokeyDevice *device, GError **error) version = g_strdup_printf ("%u.%u", payload.VersionMinor, payload.VersionMajor); fu_device_set_version (FU_DEVICE (device), version); - /* set vendor ID */ - vendor_id = g_strdup_printf ("USB:0x%04X", g_usb_device_get_vid (priv->usb_device)); - fu_device_set_vendor_id (FU_DEVICE (device), vendor_id); - - /* use the USB VID:PID hash */ - devid1 = g_strdup_printf ("USB\\VID_%04X&PID_%04X", - g_usb_device_get_vid (priv->usb_device), - g_usb_device_get_pid (priv->usb_device)); - fu_device_add_guid (FU_DEVICE (device), devid1); - /* allowed, but requires manual bootloader step */ fu_device_add_flag (FU_DEVICE (device), FWUPD_DEVICE_FLAG_UPDATABLE); fu_device_add_flag (FU_DEVICE (device), FWUPD_DEVICE_FLAG_NEEDS_BOOTLOADER); /* success */ - priv->usb_device_locker = g_steal_pointer (&locker); return TRUE; } -gboolean -fu_nitrokey_device_close (FuNitrokeyDevice *device, GError **error) +static gboolean +fu_nitrokey_device_close (FuUsbDevice *device, GError **error) { - FuNitrokeyDevicePrivate *priv = GET_PRIVATE (device); + GUsbDevice *usb_device = fu_usb_device_get_dev (device); g_autoptr(GError) error_local = NULL; /* reconnect kernel driver */ - if (!g_usb_device_release_interface (priv->usb_device, 0x02, + if (!g_usb_device_release_interface (usb_device, 0x02, G_USB_DEVICE_CLAIM_INTERFACE_BIND_KERNEL_DRIVER, &error_local)) { g_warning ("failed to release interface: %s", error_local->message); } - - g_clear_object (&priv->usb_device_locker); return TRUE; } static void -fu_nitrokey_device_set_usb_device (FuNitrokeyDevice *device, GUsbDevice *usb_device) +fu_nitrokey_device_init (FuNitrokeyDevice *device) { - FuNitrokeyDevicePrivate *priv = GET_PRIVATE (device); - g_set_object (&priv->usb_device, usb_device); +} + +static void +fu_nitrokey_device_class_init (FuNitrokeyDeviceClass *klass) +{ + FuUsbDeviceClass *klass_usb_device = FU_USB_DEVICE_CLASS (klass); + klass_usb_device->open = fu_nitrokey_device_open; + klass_usb_device->close = fu_nitrokey_device_close; } FuNitrokeyDevice * fu_nitrokey_device_new (GUsbDevice *usb_device) { - g_autoptr(FuNitrokeyDevice) device = NULL; - device = g_object_new (FU_TYPE_NITROKEY_DEVICE, NULL); - fu_nitrokey_device_set_usb_device (device, usb_device); - return g_steal_pointer (&device); + FuNitrokeyDevice *device; + device = g_object_new (FU_TYPE_NITROKEY_DEVICE, + "usb-device", usb_device, + NULL); + return FU_NITROKEY_DEVICE (device); } diff --git a/plugins/nitrokey/fu-nitrokey-device.h b/plugins/nitrokey/fu-nitrokey-device.h index 7310b3937..19ca714db 100644 --- a/plugins/nitrokey/fu-nitrokey-device.h +++ b/plugins/nitrokey/fu-nitrokey-device.h @@ -30,20 +30,15 @@ G_BEGIN_DECLS #define FU_TYPE_NITROKEY_DEVICE (fu_nitrokey_device_get_type ()) -G_DECLARE_DERIVABLE_TYPE (FuNitrokeyDevice, fu_nitrokey_device, FU, NITROKEY_DEVICE, FuDevice) +G_DECLARE_DERIVABLE_TYPE (FuNitrokeyDevice, fu_nitrokey_device, FU, NITROKEY_DEVICE, FuUsbDevice) struct _FuNitrokeyDeviceClass { - FuDeviceClass parent_class; + FuUsbDeviceClass parent_class; }; FuNitrokeyDevice *fu_nitrokey_device_new (GUsbDevice *usb_device); -gboolean fu_nitrokey_device_open (FuNitrokeyDevice *device, - GError **error); -gboolean fu_nitrokey_device_close (FuNitrokeyDevice *device, - GError **error); - G_END_DECLS #endif /* __FU_NITROKEY_DEVICE_H */ diff --git a/plugins/nitrokey/fu-plugin-nitrokey.c b/plugins/nitrokey/fu-plugin-nitrokey.c index 99af085c5..fcae2bda0 100644 --- a/plugins/nitrokey/fu-plugin-nitrokey.c +++ b/plugins/nitrokey/fu-plugin-nitrokey.c @@ -21,7 +21,6 @@ #include "config.h" -#include #include #include "fu-plugin.h" @@ -36,8 +35,6 @@ fu_plugin_nitrokey_device_added_cb (GUsbContext *ctx, FuPlugin *plugin) { const gchar *platform_id = NULL; - g_autoptr(AsProfile) profile = as_profile_new (); - g_autoptr(AsProfileTask) ptask = NULL; g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(FuNitrokeyDevice) dev = NULL; g_autoptr(GError) error = NULL; @@ -48,12 +45,6 @@ fu_plugin_nitrokey_device_added_cb (GUsbContext *ctx, if (g_usb_device_get_pid (usb_device) != 0x4109) return; - /* profile */ - ptask = as_profile_start (profile, "FuPluginNitrokey:added{%04x:%04x}", - g_usb_device_get_vid (usb_device), - g_usb_device_get_pid (usb_device)); - g_assert (ptask != NULL); - /* is already in database */ platform_id = g_usb_device_get_platform_id (usb_device); dev = fu_plugin_cache_lookup (plugin, platform_id); @@ -64,10 +55,7 @@ fu_plugin_nitrokey_device_added_cb (GUsbContext *ctx, /* open the device */ dev = fu_nitrokey_device_new (usb_device); - locker = fu_device_locker_new_full (dev, - (FuDeviceLockerFunc) fu_nitrokey_device_open, - (FuDeviceLockerFunc) fu_nitrokey_device_close, - &error); + locker = fu_device_locker_new (dev, &error); if (locker == NULL) { g_warning ("failed to open device: %s", error->message); return; diff --git a/plugins/steelseries/fu-plugin-steelseries.c b/plugins/steelseries/fu-plugin-steelseries.c index b2c0c661f..80f454113 100644 --- a/plugins/steelseries/fu-plugin-steelseries.c +++ b/plugins/steelseries/fu-plugin-steelseries.c @@ -21,7 +21,6 @@ #include "config.h" -#include #include #include "fu-plugin.h" @@ -39,10 +38,7 @@ fu_plugin_steelseries_device_added_cb (GUsbContext *ctx, gboolean ret; gsize actual_len = 0; guint8 data[32]; - g_autofree gchar *devid1 = NULL; g_autofree gchar *version = NULL; - g_autoptr(AsProfile) profile = as_profile_new (); - g_autoptr(AsProfileTask) ptask = NULL; g_autoptr(FuDevice) dev = NULL; g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(GError) error_local = NULL; @@ -53,12 +49,6 @@ fu_plugin_steelseries_device_added_cb (GUsbContext *ctx, if (g_usb_device_get_pid (usb_device) != 0x1702) return; - /* profile */ - ptask = as_profile_start (profile, "FuPluginSteelseries:added{%04x:%04x}", - g_usb_device_get_vid (usb_device), - g_usb_device_get_pid (usb_device)); - g_assert (ptask != NULL); - /* is already in database */ platform_id = g_usb_device_get_platform_id (usb_device); dev = fu_plugin_cache_lookup (plugin, platform_id); @@ -122,8 +112,7 @@ fu_plugin_steelseries_device_added_cb (GUsbContext *ctx, } /* insert to hash if valid */ - dev = fu_device_new (); - fu_device_set_id (dev, platform_id); + dev = fu_usb_device_new (usb_device); fu_device_set_name (dev, "SteelSeries Rival 100"); fu_device_set_vendor (dev, "SteelSeries"); fu_device_set_summary (dev, "An optical gaming mouse"); @@ -132,12 +121,6 @@ fu_plugin_steelseries_device_added_cb (GUsbContext *ctx, data[0], data[1], data[2]); fu_device_set_version (dev, version); - /* use the USB VID:PID hash */ - devid1 = g_strdup_printf ("USB\\VID_%04X&PID_%04X", - g_usb_device_get_vid (usb_device), - g_usb_device_get_pid (usb_device)); - fu_device_add_guid (dev, devid1); - /* we're done here */ if (!g_usb_device_release_interface (usb_device, iface_idx, G_USB_DEVICE_CLAIM_INTERFACE_BIND_KERNEL_DRIVER, diff --git a/plugins/usb/fu-plugin-usb.c b/plugins/usb/fu-plugin-usb.c index b2072c33e..cfa03af8f 100644 --- a/plugins/usb/fu-plugin-usb.c +++ b/plugins/usb/fu-plugin-usb.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * - * Copyright (C) 2016 Richard Hughes + * Copyright (C) 2016-2017 Richard Hughes * * Licensed under the GNU General Public License Version 2 * @@ -21,23 +21,9 @@ #include "config.h" -#include - #include "fu-plugin.h" #include "fu-plugin-vfuncs.h" -static gchar * -_bcd_version_from_uint16 (guint16 val) -{ -#if AS_CHECK_VERSION(0,7,3) - return as_utils_version_from_uint16 (val, AS_VERSION_PARSE_FLAG_USE_BCD); -#else - guint maj = ((val >> 12) & 0x0f) * 10 + ((val >> 8) & 0x0f); - guint min = ((val >> 4) & 0x0f) * 10 + (val & 0x0f); - return g_strdup_printf ("%u.%u", maj, min); -#endif -} - static void fu_plugin_usb_device_added_cb (GUsbContext *ctx, GUsbDevice *device, @@ -45,13 +31,7 @@ fu_plugin_usb_device_added_cb (GUsbContext *ctx, { const gchar *platform_id = NULL; guint8 idx = 0x00; - g_autofree gchar *devid1 = NULL; - g_autofree gchar *devid2 = NULL; g_autofree gchar *product = NULL; - g_autofree gchar *vendor_id = NULL; - g_autofree gchar *version = NULL; - g_autoptr(AsProfile) profile = as_profile_new (); - g_autoptr(AsProfileTask) ptask = NULL; g_autoptr(FuDevice) dev = NULL; g_autoptr(FuDeviceLocker) locker = NULL; g_autoptr(GError) error = NULL; @@ -59,10 +39,6 @@ fu_plugin_usb_device_added_cb (GUsbContext *ctx, /* ignore hubs */ if (g_usb_device_get_device_class (device) == G_USB_DEVICE_CLASS_HUB) return; - ptask = as_profile_start (profile, "FuPluginUsb:added{%04x:%04x}", - g_usb_device_get_vid (device), - g_usb_device_get_pid (device)); - g_assert (ptask != NULL); /* is already in database */ platform_id = g_usb_device_get_platform_id (device); @@ -80,38 +56,17 @@ fu_plugin_usb_device_added_cb (GUsbContext *ctx, } /* insert to hash if valid */ - dev = fu_device_new (); - fu_device_set_id (dev, platform_id); - - /* get product */ - idx = g_usb_device_get_product_index (device); - if (idx != 0x00) { - g_autoptr(AsProfileTask) ptask2 = NULL; - ptask2 = as_profile_start_literal (profile, "FuPluginUsb:get-string-desc"); - g_assert (ptask2 != NULL); - product = g_usb_device_get_string_descriptor (device, idx, NULL); - } - if (product == NULL) { - g_debug ("no product string descriptor"); - return; - } - fu_device_set_name (dev, product); + dev = fu_usb_device_new (device); /* get version number, falling back to the USB device release */ idx = g_usb_device_get_custom_index (device, G_USB_DEVICE_CLASS_VENDOR_SPECIFIC, 'F', 'W', NULL); - if (idx != 0x00) + if (idx != 0x00) { + g_autofree gchar *version = NULL; version = g_usb_device_get_string_descriptor (device, idx, NULL); - if (version == NULL) { - guint16 release = g_usb_device_get_release (device); - version = _bcd_version_from_uint16 (release); + fu_device_set_version (dev, version); } - fu_device_set_version (dev, version); - - /* set vendor ID */ - vendor_id = g_strdup_printf ("USB:0x%04X", g_usb_device_get_vid (device)); - fu_device_set_vendor_id (dev, vendor_id); /* get GUID from the descriptor if set */ idx = g_usb_device_get_custom_index (device, @@ -123,17 +78,6 @@ fu_plugin_usb_device_added_cb (GUsbContext *ctx, fu_device_add_guid (dev, guid); } - /* also fall back to the USB VID:PID hash */ - devid1 = g_strdup_printf ("USB\\VID_%04X&PID_%04X", - g_usb_device_get_vid (device), - g_usb_device_get_pid (device)); - fu_device_add_guid (dev, devid1); - devid2 = g_strdup_printf ("USB\\VID_%04X&PID_%04X&REV_%04X", - g_usb_device_get_vid (device), - g_usb_device_get_pid (device), - g_usb_device_get_release (device)); - fu_device_add_guid (dev, devid2); - /* use a small delay for hotplugging so that other, better, plugins * can claim this interface and add the FuDevice */ fu_plugin_device_add_delay (plugin, dev); diff --git a/src/fu-device-locker.c b/src/fu-device-locker.c index 91bede563..df7327f75 100644 --- a/src/fu-device-locker.c +++ b/src/fu-device-locker.c @@ -25,6 +25,7 @@ #include #include "fu-device-locker.h" +#include "fu-usb-device.h" /** * SECTION:fu-device-locker @@ -86,8 +87,10 @@ fu_device_locker_init (FuDeviceLocker *self) * manually closed using g_clear_object(). * * The functions used for opening and closing the device are set automatically. - * If the @device is not a type or supertype of @GUsbDevice then this function - * will not work. For custom objects please use fu_device_locker_new_full(). + * If the @device is not a type or supertype of #GUsbDevice or #FuUsbDevice + * then this function will not work. + * + * For custom objects please use fu_device_locker_new_full(). * * NOTE: If the @open_func failed then the @close_func will not be called. * @@ -108,6 +111,14 @@ fu_device_locker_new (gpointer device, GError **error) (FuDeviceLockerFunc) g_usb_device_close, error); } + + /* FuUsbDevice */ + if (FU_IS_USB_DEVICE (device)) { + return fu_device_locker_new_full (device, + (FuDeviceLockerFunc) fu_usb_device_open, + (FuDeviceLockerFunc) fu_usb_device_close, + error); + } g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, diff --git a/src/fu-plugin.h b/src/fu-plugin.h index b7cb87993..498cac600 100644 --- a/src/fu-plugin.h +++ b/src/fu-plugin.h @@ -32,6 +32,7 @@ #include "fu-device-locker.h" #include "fu-quirks.h" #include "fu-hwids.h" +#include "fu-usb-device.h" G_BEGIN_DECLS diff --git a/src/fu-usb-device.c b/src/fu-usb-device.c new file mode 100644 index 000000000..7189c7def --- /dev/null +++ b/src/fu-usb-device.c @@ -0,0 +1,319 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2017 Richard Hughes + * + * Licensed under the GNU Lesser General Public License Version 2.1 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include + +#include "fu-usb-device.h" + +/** + * SECTION:fu-device + * @short_description: a USB device + * + * An object that represents a USB device. + * + * See also: #FuDevice + */ + +typedef struct +{ + GUsbDevice *usb_device; + FuDeviceLocker *usb_device_locker; +} FuUsbDevicePrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (FuUsbDevice, fu_usb_device, FU_TYPE_DEVICE) +enum { + PROP_0, + PROP_USB_DEVICE, + PROP_LAST +}; + +#define GET_PRIVATE(o) (fu_usb_device_get_instance_private (o)) + +static void +fu_usb_device_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + FuUsbDevice *device = FU_USB_DEVICE (object); + FuUsbDevicePrivate *priv = GET_PRIVATE (device); + switch (prop_id) { + case PROP_USB_DEVICE: + g_value_set_object (value, priv->usb_device); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +fu_usb_device_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + FuUsbDevice *device = FU_USB_DEVICE (object); + switch (prop_id) { + case PROP_USB_DEVICE: + fu_usb_device_set_dev (device, g_value_get_object (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +fu_usb_device_finalize (GObject *object) +{ + FuUsbDevice *device = FU_USB_DEVICE (object); + FuUsbDevicePrivate *priv = GET_PRIVATE (device); + + if (priv->usb_device_locker != NULL) + g_object_unref (priv->usb_device_locker); + if (priv->usb_device != NULL) + g_object_unref (priv->usb_device); + + G_OBJECT_CLASS (fu_usb_device_parent_class)->finalize (object); +} + +static void +fu_usb_device_init (FuUsbDevice *device) +{ +} + +static void +fu_usb_device_class_init (FuUsbDeviceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GParamSpec *pspec; + + object_class->finalize = fu_usb_device_finalize; + object_class->get_property = fu_usb_device_get_property; + object_class->set_property = fu_usb_device_set_property; + + pspec = g_param_spec_object ("usb-device", NULL, NULL, + G_USB_TYPE_DEVICE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_NAME); + g_object_class_install_property (object_class, PROP_USB_DEVICE, pspec); +} + +/** + * fu_usb_device_open: + * @device: A #FuUsbDevice + * @error: A #GError, or %NULL + * + * Opens a USB device, optionally running a object-specific vfunc. + * + * Returns: %TRUE for success + * + * Since: 1.0.2 + **/ +gboolean +fu_usb_device_open (FuUsbDevice *device, GError **error) +{ + FuUsbDevicePrivate *priv = GET_PRIVATE (device); + FuUsbDeviceClass *klass = FU_USB_DEVICE_GET_CLASS (device); + guint idx; + g_autoptr(AsProfile) profile = as_profile_new (); + g_autoptr(AsProfileTask) ptask = NULL; + g_autoptr(FuDeviceLocker) locker = NULL; + + g_return_val_if_fail (FU_IS_USB_DEVICE (device), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + /* already open */ + if (priv->usb_device_locker != NULL) + return TRUE; + + /* profile */ + ptask = as_profile_start (profile, "%s:added{%04x:%04x}", + fu_device_get_plugin (FU_DEVICE (device)), + g_usb_device_get_vid (priv->usb_device), + g_usb_device_get_pid (priv->usb_device)); + g_assert (ptask != NULL); + + /* open */ + locker = fu_device_locker_new (priv->usb_device, error); + if (locker == NULL) + return FALSE; + + /* get vendor */ + idx = g_usb_device_get_manufacturer_index (priv->usb_device); + if (idx != 0xff) { + g_autofree gchar *tmp = NULL; + tmp = g_usb_device_get_string_descriptor (priv->usb_device, + idx, error); + if (tmp == NULL) + return FALSE; + fu_device_set_vendor (FU_DEVICE (device), tmp); + } + + /* get product */ + idx = g_usb_device_get_product_index (priv->usb_device); + if (idx != 0xff) { + g_autofree gchar *tmp = NULL; + tmp = g_usb_device_get_string_descriptor (priv->usb_device, + idx, error); + if (tmp == NULL) + return FALSE; + fu_device_set_name (FU_DEVICE (device), tmp); + } + + /* subclassed */ + if (klass->open != NULL) { + if (!klass->open (device, error)) + return FALSE; + } + + /* success */ + priv->usb_device_locker = g_steal_pointer (&locker); + return TRUE; +} + +/** + * fu_usb_device_open: + * @device: A #FuUsbDevice + * @error: A #GError, or %NULL + * + * Closes a USB device, optionally running a object-specific vfunc. + * + * Returns: %TRUE for success + * + * Since: 1.0.2 + **/ +gboolean +fu_usb_device_close (FuUsbDevice *device, GError **error) +{ + FuUsbDevicePrivate *priv = GET_PRIVATE (device); + FuUsbDeviceClass *klass = FU_USB_DEVICE_GET_CLASS (device); + + g_return_val_if_fail (FU_IS_USB_DEVICE (device), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + /* subclassed */ + if (klass->close != NULL) { + if (!klass->close (device, error)) + return FALSE; + } + + g_clear_object (&priv->usb_device_locker); + return TRUE; +} + +static gchar * +_bcd_version_from_uint16 (guint16 val) +{ +#if AS_CHECK_VERSION(0,7,3) + return as_utils_version_from_uint16 (val, AS_VERSION_PARSE_FLAG_USE_BCD); +#else + guint maj = ((val >> 12) & 0x0f) * 10 + ((val >> 8) & 0x0f); + guint min = ((val >> 4) & 0x0f) * 10 + (val & 0x0f); + return g_strdup_printf ("%u.%u", maj, min); +#endif +} + +/** + * fu_usb_device_set_dev: + * @device: A #FuUsbDevice + * @usb_device: A #GUsbDevice, or %NULL + * + * Sets the #GUsbDevice to use. + * + * Since: 1.0.2 + **/ +void +fu_usb_device_set_dev (FuUsbDevice *device, GUsbDevice *usb_device) +{ + FuUsbDevicePrivate *priv = GET_PRIVATE (device); + guint16 release = g_usb_device_get_release (usb_device); + g_autofree gchar *devid1 = NULL; + g_autofree gchar *devid2 = NULL; + g_autofree gchar *vendor_id = NULL; + + g_return_if_fail (FU_IS_USB_DEVICE (device)); + + /* allow replacement */ + g_set_object (&priv->usb_device, usb_device); + if (usb_device == NULL) + return; + + /* add both device IDs */ + devid1 = g_strdup_printf ("USB\\VID_%04X&PID_%04X", + g_usb_device_get_vid (usb_device), + g_usb_device_get_pid (usb_device)); + fu_device_add_guid (FU_DEVICE (device), devid1); + devid2 = g_strdup_printf ("USB\\VID_%04X&PID_%04X&REV_%04X", + g_usb_device_get_vid (usb_device), + g_usb_device_get_pid (usb_device), + release); + fu_device_add_guid (FU_DEVICE (device), devid2); + + /* set vendor ID */ + vendor_id = g_strdup_printf ("USB:0x%04X", g_usb_device_get_vid (usb_device)); + fu_device_set_vendor_id (FU_DEVICE (device), vendor_id); + + /* set the version if the release has been set */ + if (release != 0x0) { + g_autofree gchar *version = _bcd_version_from_uint16 (release); + fu_device_set_version (FU_DEVICE (device), version); + } + + /* set USB platform ID automatically */ + fu_device_set_platform_id (FU_DEVICE (device), + g_usb_device_get_platform_id (usb_device)); +} + +/** + * fu_usb_device_get_dev: + * @device: A #FuUsbDevice + * + * Gets the #GUsbDevice. + * + * Returns: (transfer none): a #GUsbDevice, or %NULL + * + * Since: 1.0.2 + **/ +GUsbDevice * +fu_usb_device_get_dev (FuUsbDevice *device) +{ + FuUsbDevicePrivate *priv = GET_PRIVATE (device); + g_return_val_if_fail (FU_IS_USB_DEVICE (device), NULL); + return priv->usb_device; +} + +/** + * fu_usb_device_new: + * + * Creates a new #FuUsbDevice. + * + * Returns: (transfer full): a #FuUsbDevice + * + * Since: 1.0.2 + **/ +FuDevice * +fu_usb_device_new (GUsbDevice *usb_device) +{ + FuUsbDevice *device = g_object_new (FU_TYPE_USB_DEVICE, NULL); + fu_usb_device_set_dev (device, usb_device); + return FU_DEVICE (device); +} diff --git a/src/fu-usb-device.h b/src/fu-usb-device.h new file mode 100644 index 000000000..b745fda51 --- /dev/null +++ b/src/fu-usb-device.h @@ -0,0 +1,56 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2017 Richard Hughes + * + * Licensed under the GNU Lesser General Public License Version 2.1 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __FU_USB_DEVICE_H +#define __FU_USB_DEVICE_H + +#include +#include + +#include "fu-plugin.h" + +G_BEGIN_DECLS + +#define FU_TYPE_USB_DEVICE (fu_usb_device_get_type ()) +G_DECLARE_DERIVABLE_TYPE (FuUsbDevice, fu_usb_device, FU, USB_DEVICE, FuDevice) + +struct _FuUsbDeviceClass +{ + FuDeviceClass parent_class; + gboolean (*open) (FuUsbDevice *device, + GError **error); + gboolean (*close) (FuUsbDevice *device, + GError **error); + gpointer __reserved[29]; +}; + +FuDevice *fu_usb_device_new (GUsbDevice *usb_device); +GUsbDevice *fu_usb_device_get_dev (FuUsbDevice *device); +void fu_usb_device_set_dev (FuUsbDevice *device, + GUsbDevice *usb_device); +gboolean fu_usb_device_open (FuUsbDevice *device, + GError **error); +gboolean fu_usb_device_close (FuUsbDevice *device, + GError **error); + +G_END_DECLS + +#endif /* __FU_USB_DEVICE_H */ diff --git a/src/meson.build b/src/meson.build index 57852b4d1..8d0383be7 100644 --- a/src/meson.build +++ b/src/meson.build @@ -31,6 +31,7 @@ libfwupdprivate = static_library( 'fu-quirks.c', 'fu-smbios.c', 'fu-test.c', + 'fu-usb-device.c', ], include_directories : [ include_directories('..'), @@ -133,6 +134,7 @@ executable( 'fu-plugin.c', 'fu-quirks.c', 'fu-smbios.c', + 'fu-usb-device.c', ], include_directories : [ include_directories('..'), @@ -195,6 +197,7 @@ if get_option('enable-tests') 'fu-quirks.c', 'fu-smbios.c', 'fu-test.c', + 'fu-usb-device.c', ], include_directories : [ include_directories('..'), @@ -248,6 +251,7 @@ if get_option('enable-introspection') 'fu-plugin.h', 'fu-quirks.c', 'fu-quirks.h', + 'fu-usb-device.c', ], nsversion : '1.0', namespace : 'Fu',