dfu: Fix replugging when using dfu-tool to flash hardware

All kinds of things break when using more than one GUsbContext at the
same time.
This commit is contained in:
Richard Hughes 2021-11-12 14:49:44 +00:00
parent f9cba32625
commit da4f50ccf0

View File

@ -27,6 +27,7 @@ typedef struct {
gchar *device_vid_pid; gchar *device_vid_pid;
guint16 transfer_size; guint16 transfer_size;
FuContext *ctx; FuContext *ctx;
GUsbContext *usb_context;
} FuDfuTool; } FuDfuTool;
static void static void
@ -37,6 +38,8 @@ fu_dfu_tool_free(FuDfuTool *self)
g_free(self->device_vid_pid); g_free(self->device_vid_pid);
if (self->cancellable != NULL) if (self->cancellable != NULL)
g_object_unref(self->cancellable); g_object_unref(self->cancellable);
if (self->usb_context != NULL)
g_object_unref(self->usb_context);
g_object_unref(self->ctx); g_object_unref(self->ctx);
if (self->cmd_array != NULL) if (self->cmd_array != NULL)
g_ptr_array_unref(self->cmd_array); g_ptr_array_unref(self->cmd_array);
@ -164,14 +167,13 @@ fu_dfu_tool_run(FuDfuTool *self, const gchar *command, gchar **values, GError **
static FuDfuDevice * static FuDfuDevice *
fu_dfu_tool_get_default_device(FuDfuTool *self, GError **error) fu_dfu_tool_get_default_device(FuDfuTool *self, GError **error)
{ {
g_autoptr(GUsbContext) usb_context = NULL;
g_autoptr(GPtrArray) devices = NULL; g_autoptr(GPtrArray) devices = NULL;
/* get all the DFU devices */ /* get all the DFU devices */
usb_context = g_usb_context_new(error); self->usb_context = g_usb_context_new(error);
if (usb_context == NULL) if (self->usb_context == NULL)
return NULL; return NULL;
g_usb_context_enumerate(usb_context); g_usb_context_enumerate(self->usb_context);
/* we specified it manually */ /* we specified it manually */
if (self->device_vid_pid != NULL) { if (self->device_vid_pid != NULL) {
@ -207,8 +209,10 @@ fu_dfu_tool_get_default_device(FuDfuTool *self, GError **error)
} }
/* find device */ /* find device */
usb_device = usb_device = g_usb_context_find_by_vid_pid(self->usb_context,
g_usb_context_find_by_vid_pid(usb_context, (guint16)vid, (guint16)pid, error); (guint16)vid,
(guint16)pid,
error);
if (usb_device == NULL) { if (usb_device == NULL) {
g_prefix_error(error, g_prefix_error(error,
"no device matches for %04x:%04x: ", "no device matches for %04x:%04x: ",
@ -222,7 +226,7 @@ fu_dfu_tool_get_default_device(FuDfuTool *self, GError **error)
} }
/* auto-detect first device */ /* auto-detect first device */
devices = g_usb_context_get_devices(usb_context); devices = g_usb_context_get_devices(self->usb_context);
for (guint i = 0; i < devices->len; i++) { for (guint i = 0; i < devices->len; i++) {
GUsbDevice *usb_device = g_ptr_array_index(devices, i); GUsbDevice *usb_device = g_ptr_array_index(devices, i);
g_autoptr(FuDfuDevice) device = fu_dfu_device_new(usb_device); g_autoptr(FuDfuDevice) device = fu_dfu_device_new(usb_device);
@ -241,20 +245,14 @@ fu_dfu_device_wait_for_replug(FuDfuTool *self, FuDfuDevice *device, guint timeou
{ {
GUsbDevice *usb_device = fu_usb_device_get_dev(FU_USB_DEVICE(device)); GUsbDevice *usb_device = fu_usb_device_get_dev(FU_USB_DEVICE(device));
g_autoptr(GUsbDevice) usb_device2 = NULL; g_autoptr(GUsbDevice) usb_device2 = NULL;
g_autoptr(GUsbContext) usb_context = NULL;
g_autoptr(GError) error_local = NULL; g_autoptr(GError) error_local = NULL;
/* get all the DFU devices */
usb_context = g_usb_context_new(error);
if (usb_context == NULL)
return FALSE;
/* close */ /* close */
if (!fu_device_close(FU_DEVICE(device), &error_local)) if (!fu_device_close(FU_DEVICE(device), &error_local))
g_debug("failed to close: %s", error_local->message); g_debug("failed to close: %s", error_local->message);
/* watch the device disappear and re-appear */ /* watch the device disappear and re-appear */
usb_device2 = g_usb_context_wait_for_replug(usb_context, usb_device, timeout, error); usb_device2 = g_usb_context_wait_for_replug(self->usb_context, usb_device, timeout, error);
if (usb_device2 == NULL) if (usb_device2 == NULL)
return FALSE; return FALSE;