static gboolean fu_provider_chug_verify (FuProvider *provider, FuDevice *device, FuProviderVerifyFlags flags, GError **error) { FuProviderChug *provider_chug = FU_PROVIDER_CHUG (provider); FuProviderChugPrivate *priv = GET_PRIVATE (provider_chug); FuProviderChugItem *item; GChecksumType checksum_type; gsize len; g_autoptr(GError) error_local = NULL; g_autofree gchar *hash = NULL; g_autofree guint8 *data = NULL; /* find item */ item = g_hash_table_lookup (priv->devices, fu_device_get_id (device)); if (item == NULL) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_NOT_FOUND, "cannot find: %s", fu_device_get_id (device)); return FALSE; } /* open */ if (!fu_provider_chug_open (item, error)) return FALSE; /* get the firmware from the device */ g_debug ("ColorHug: Verifying firmware"); ch_device_queue_read_firmware (priv->device_queue, item->usb_device, &data, &len); fu_provider_set_status (provider, FWUPD_STATUS_DEVICE_VERIFY); 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); g_usb_device_close (item->usb_device, NULL); return FALSE; } /* get the checksum */ checksum_type = fu_provider_get_checksum_type (flags); hash = g_compute_checksum_for_data (checksum_type, (guchar *) data, len); fu_device_set_checksum (device, hash); fu_device_set_checksum_kind (device, checksum_type); /* we're done here */ if (!g_usb_device_close (item->usb_device, &error_local)) g_debug ("Failed to close: %s", error_local->message); return TRUE; }
static void fu_provider_chug_get_firmware_version (FuProviderChugItem *item) { FuProviderChugPrivate *priv = GET_PRIVATE (item->provider_chug); guint16 major; guint16 micro; guint16 minor; guint8 idx; g_autoptr(GError) error = NULL; g_autofree gchar *version = NULL; /* try to get the version without claiming interface */ 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_SPECIFIC, 'F', 'W', NULL); if (idx != 0x00) { g_autofree 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_version (item->device, tmp); goto out; } } g_usb_device_close (item->usb_device, NULL); /* attempt to open the device and get the serial number */ if (!ch_device_open (item->usb_device, &error)) { g_debug ("Failed to claim interface, polling: %s", error->message); return; } ch_device_queue_get_firmware_ver (priv->device_queue, item->usb_device, &major, &minor, µ); if (!ch_device_queue_process (priv->device_queue, CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE, NULL, &error)) { g_warning ("Failed to get serial: %s", error->message); 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_version (item->device, version); out: /* we're done here */ g_clear_error (&error); if (!g_usb_device_close (item->usb_device, &error)) g_debug ("Failed to close: %s", error->message); }
int main (int argc, char *argv[]) { gboolean ret; GError *error = NULL; GMainLoop *loop = NULL; GUsbContext *ctx; GUsbDevice *device = NULL; int retval = 0; GUsbDeviceList *list = NULL; ChDeviceQueue *device_queue; /* setup usb */ g_type_init (); ctx = g_usb_context_new (&error); if (ctx == NULL) { g_warning ("Cannot connect to USB : %s", error->message); g_error_free (error); retval = 1; goto out; } list = g_usb_device_list_new (ctx); device_queue = ch_device_queue_new (); ret = connect_device (list, &device, &error); if (!ret) { g_warning ("Cannot connect to device : %s", error->message); g_error_free (error); retval = 1; goto out; } /* reset device so it boots back into bootloader mode */ g_warning ("Switching to bootloader mode\n"); ch_device_queue_reset (device_queue, device); ret = ch_device_queue_process (device_queue, CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE, NULL, &error); if (!ret) { g_warning ("Failed to reboot : %s", error->message); g_error_free (error); retval = 1; goto out; } /* wait for device to re-appear */ loop = g_main_loop_new (NULL, FALSE); g_timeout_add (5000, quit_loop_cb, loop); g_main_loop_run (loop); g_object_unref (device); ret = connect_device (list, &device, &error); if (!ret) { g_warning ("Cannot connect to device : %s", error->message); g_error_free (error); retval = 1; goto out; } /* boot into firmware mode */ g_warning ("Switching to firmware mode\n"); ch_device_queue_boot_flash (device_queue, device); ret = ch_device_queue_process (device_queue, CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE, NULL, &error); if (!ret) { g_warning ("Failed to boot into firmware mode : %s", error->message); g_error_free (error); retval = 1; goto out; } /* wait for device to re-appear */ g_timeout_add (5000, quit_loop_cb, loop); g_main_loop_run (loop); g_object_unref (device); ret = connect_device (list, &device, &error); if (!ret) { g_warning ("Cannot connect to device : %s", error->message); g_error_free (error); retval = 1; goto out; } /* turn on LEDs */ g_warning ("Turning on LEDs\n"); ch_device_queue_set_leds (device_queue, device, 3, 0, 0, 0); ret = ch_device_queue_process (device_queue, CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE, NULL, &error); if (!ret) { g_warning ("Failed to turn on LEDs : %s", error->message); g_error_free (error); retval = 1; goto out; } /* success */ g_warning ("ALL OKAY\n"); out: if (loop != NULL) g_main_loop_unref (loop); if (ctx != NULL) g_object_unref (ctx); if (device_queue != NULL) g_object_unref (device_queue); if (device != NULL) g_object_unref (device); if (list != NULL) g_object_unref (list); return retval; }
static gboolean fu_provider_chug_update (FuProvider *provider, FuDevice *device, GBytes *blob_fw, FwupdInstallFlags flags, GError **error) { FuProviderChug *provider_chug = FU_PROVIDER_CHUG (provider); FuProviderChugPrivate *priv = GET_PRIVATE (provider_chug); FuProviderChugItem *item; g_autoptr(GError) error_local = NULL; /* find item */ item = g_hash_table_lookup (priv->devices, fu_device_get_id (device)); if (item == NULL) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_NOT_FOUND, "cannot find: %s", fu_device_get_id (device)); return FALSE; } /* this file is so small, just slurp it all in one go */ item->fw_bin = g_bytes_ref (blob_fw); /* check this firmware is actually for this device */ if (!ch_device_check_firmware (item->usb_device, g_bytes_get_data (item->fw_bin, NULL), g_bytes_get_size (item->fw_bin), &error_local)) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED, "firmware is not suitable: %s", error_local->message); return FALSE; } /* switch to bootloader mode */ if (!item->is_bootloader) { g_debug ("ColorHug: Switching to bootloader mode"); if (!fu_provider_chug_open (item, error)) return FALSE; ch_device_queue_reset (priv->device_queue, item->usb_device); fu_provider_set_status (provider, FWUPD_STATUS_DEVICE_RESTART); 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 reset device: %s", error_local->message); g_usb_device_close (item->usb_device, NULL); return FALSE; } /* this device has just gone away, no error possible */ g_usb_device_close (item->usb_device, NULL); /* wait for reconnection */ g_debug ("ColorHug: Waiting for bootloader"); if (!fu_provider_chug_wait_for_connect (provider_chug, item, error)) return FALSE; } /* open the device, which is now in bootloader mode */ if (!fu_provider_chug_open (item, error)) return FALSE; /* write firmware */ g_debug ("ColorHug: Writing firmware"); ch_device_queue_write_firmware (priv->device_queue, item->usb_device, g_bytes_get_data (item->fw_bin, NULL), g_bytes_get_size (item->fw_bin)); fu_provider_set_status (provider, FWUPD_STATUS_DEVICE_WRITE); 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); g_usb_device_close (item->usb_device, NULL); return FALSE; } /* verify firmware */ g_debug ("ColorHug: Veifying firmware"); ch_device_queue_verify_firmware (priv->device_queue, item->usb_device, g_bytes_get_data (item->fw_bin, NULL), g_bytes_get_size (item->fw_bin)); fu_provider_set_status (provider, FWUPD_STATUS_DEVICE_VERIFY); 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); g_usb_device_close (item->usb_device, NULL); return FALSE; } /* boot into the new firmware */ g_debug ("ColorHug: Booting new firmware"); ch_device_queue_boot_flash (priv->device_queue, item->usb_device); fu_provider_set_status (provider, FWUPD_STATUS_DEVICE_RESTART); 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 boot flash: %s", error_local->message); g_usb_device_close (item->usb_device, NULL); return FALSE; } /* this device has just gone away, no error possible */ g_usb_device_close (item->usb_device, NULL); /* wait for firmware mode */ if (!fu_provider_chug_wait_for_connect (provider_chug, item, error)) return FALSE; if (!fu_provider_chug_open (item, error)) return FALSE; /* set flash success */ g_debug ("ColorHug: Setting flash success"); ch_device_queue_set_flash_success (priv->device_queue, item->usb_device, 1); 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 set flash success: %s", error_local->message); g_usb_device_close (item->usb_device, NULL); return FALSE; } /* close, orderly */ if (!g_usb_device_close (item->usb_device, &error_local)) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_WRITE, "failed to close device: %s", error_local->message); g_usb_device_close (item->usb_device, NULL); return FALSE; } /* get the new firmware version */ g_debug ("ColorHug: Getting new firmware version"); item->got_version = FALSE; fu_provider_chug_get_firmware_version (item); if (item->got_version) g_debug ("ColorHug: DONE!"); return TRUE; }