[Spice-devel] [spice-gtk Win32 v4 06/17] Windows mingw: usb: Dynamically install a libusb driver for USB devices

Hans de Goede hdegoede at redhat.com
Thu Jul 5 23:46:27 PDT 2012


Hi,

On 07/05/2012 10:43 PM, Uri Lublin wrote:
> - Added win-usb-driver-install.[ch]
> - Added win-usb-clerk.h
>
> Operation (on Windows, spice-gtk point of view):
> - After some sanity checks, just before redir'ing a USB device
>    a libusb driver needs to be installed (before libusb can open the device)
> - A connection (NamedPipe) is established with usb-clerk, a libusb
>    driver installation service, and a request for driver installation
>    is sent.
> - Installation status is asynchronously read from the pipe, and
>    spice_usb_drv_install_finished() is called.
> - Upon a successful intallation, usbredir continues.
>
> Linux operation is not changed.
> ---
>   gtk/Makefile.am              |    3 +
>   gtk/usb-device-manager.c     |  150 +++++++++++++++-
>   gtk/win-usb-clerk.h          |   35 ++++
>   gtk/win-usb-driver-install.c |  387 ++++++++++++++++++++++++++++++++++++++++++
>   gtk/win-usb-driver-install.h |   98 +++++++++++
>   5 files changed, 663 insertions(+), 10 deletions(-)
>   create mode 100644 gtk/win-usb-clerk.h
>   create mode 100644 gtk/win-usb-driver-install.c
>   create mode 100644 gtk/win-usb-driver-install.h
>

<snip>

> @@ -635,7 +649,7 @@ static void spice_usb_device_manager_add_dev(SpiceUsbDeviceManager  *self,
>               spice_usb_device_manager_connect_device_async(self,
>                                      device, NULL,
>                                      spice_usb_device_manager_auto_connect_cb,
> -                                   g_object_ref(device));
> +                                   device);
>           }
>       }
>


This seems wrong as spice_usb_device_manager_auto_connect_cb will still do a spice_usb_device_unref, so
we must ref it here to match, also this seems like something which belongs in a different patch...

> @@ -700,6 +714,87 @@ static void spice_usb_device_manager_channel_connect_cb(
>       g_object_unref(result);
>   }
>
> +#ifdef G_OS_WIN32
> +
> +typedef struct _UsbInstallCbInfo {
> +    SpiceUsbDeviceManager *manager;
> +    SpiceUsbDevice        *device;
> +    SpiceWinUsbDriver     *installer;
> +    GCancellable          *cancellable;
> +    GAsyncReadyCallback   callback;
> +    gpointer              user_data;
> +} UsbInstallCbInfo;
> +
> +/**
> + * spice_usb_device_manager_drv_install_cb:
> + * @gobject: #SpiceWinUsbDriver in charge of installing the driver
> + * @res: #GAsyncResult of async win usb driver installation
> + * @user_data: #SpiceUsbDeviceManager requested the installation
> + *
> + * Called when an Windows libusb driver installation completed.
> + *
> + * If the driver installation was successful, continue with USB
> + * device redirection
> + */
> +static void spice_usb_device_manager_drv_install_cb(GObject *gobject,
> +                                                    GAsyncResult *res,
> +                                                    gpointer user_data)
> +{
> +    SpiceUsbDeviceManager *self;
> +    SpiceWinUsbDriver *installer;
> +    gint status;
> +    GError *err = NULL;
> +    SpiceUsbDevice *device;
> +    UsbInstallCbInfo *cbinfo;
> +    GCancellable *cancellable;
> +    GAsyncReadyCallback callback;
> +
> +    SPICE_DEBUG("Win USB driver Installation finished");
> +
> +    g_return_if_fail(user_data != NULL);
> +
> +    cbinfo = user_data;
> +    self        = cbinfo->manager;
> +    device      = cbinfo->device;
> +    installer   = cbinfo->installer;
> +    cancellable = cbinfo->cancellable;
> +    callback    = cbinfo->callback;
> +    user_data   = cbinfo->user_data;
> +
> +    g_free(cbinfo);
> +
> +    g_return_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self));
> +    g_return_if_fail(SPICE_IS_WIN_USB_DRIVER(installer));
> +    g_return_if_fail(device!= NULL);
> +
> +    status = spice_win_usb_driver_install_finish(installer, res, &err);
> +
> +    g_object_unref(installer);
> +
> +    if (err) {
> +        g_warning("win usb driver installation failed -- %s",
> +                  err->message);
> +        g_error_free(err);
> +        spice_usb_device_unref(device);
> +        return;
> +    }
> +
> +    if (!status) {
> +        g_warning("failed to install win usb driver (status=0)");
> +        spice_usb_device_unref(device);

Can you please raise the appropriate error signal here, so that the user gets
an error dialog ?

> +        return;
> +    }
> +
> +    /* device is already ref'ed */
> +    _spice_usb_device_manager_connect_device_async(self,
> +                                                   device,
> +                                                   cancellable,
> +                                                   callback,
> +                                                   user_data);
> +
> +}
> +#endif
> +
>   /* ------------------------------------------------------------------ */
>   /* private api                                                        */
>
> @@ -873,6 +968,7 @@ gboolean spice_usb_device_manager_is_device_connected(SpiceUsbDeviceManager *sel
>       return !!spice_usb_device_manager_get_channel_for_dev(self, device);
>   }
>
> +#ifdef USE_USBREDIR
>   /**
>    * spice_usb_device_manager_connect_device_async:
>    * @manager: the #SpiceUsbDeviceManager manager
> @@ -881,11 +977,12 @@ gboolean spice_usb_device_manager_is_device_connected(SpiceUsbDeviceManager *sel
>    * @callback: a #GAsyncReadyCallback to call when the request is satisfied
>    * @user_data: data to pass to callback
>    */
> -void spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
> -                                             SpiceUsbDevice *device,
> -                                             GCancellable *cancellable,
> -                                             GAsyncReadyCallback callback,
> -                                             gpointer user_data)
> +static void
> +_spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
> +                                               SpiceUsbDevice *device,
> +                                               GCancellable *cancellable,
> +                                               GAsyncReadyCallback callback,
> +                                               gpointer user_data)
>   {
>       GSimpleAsyncResult *result;
>
> @@ -897,7 +994,6 @@ void spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
>       result = g_simple_async_result_new(G_OBJECT(self), callback, user_data,
>                                  spice_usb_device_manager_connect_device_async);
>
> -#ifdef USE_USBREDIR
>       SpiceUsbDeviceManagerPrivate *priv = self->priv;
>       libusb_device *libdev;
>       guint i;
> @@ -924,17 +1020,51 @@ void spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
>           libusb_unref_device(libdev);
>           return;
>       }
> -#endif
>
>       g_simple_async_result_set_error(result,
>                               SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
>                               _("No free USB channel"));
> -#ifdef USE_USBREDIR
>   done:
> -#endif
>       g_simple_async_result_complete_in_idle(result);
>       g_object_unref(result);
>   }
> +#endif
> +
> +
> +void spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
> +                                             SpiceUsbDevice *device,
> +                                             GCancellable *cancellable,
> +                                             GAsyncReadyCallback callback,
> +                                             gpointer user_data)
> +{
> +
> +#ifdef USE_USBREDIR
> +    device = spice_usb_device_ref(device);
> +
> +#ifdef G_OS_WIN32
> +    SpiceWinUsbDriver *installer;
> +    UsbInstallCbInfo *cbinfo;
> +
> +    installer = spice_win_usb_driver_new();
> +    cbinfo = g_new0(UsbInstallCbInfo, 1);
> +    cbinfo->manager     = self;
> +    cbinfo->device      = device;
> +    cbinfo->installer   = installer;
> +    cbinfo->cancellable = cancellable;
> +    cbinfo->callback    = callback;
> +    cbinfo->user_data   = user_data;
> +    spice_win_usb_driver_install(installer, device, NULL,
> +                                 spice_usb_device_manager_drv_install_cb,
> +                                 cbinfo);
> +#else
> +    _spice_usb_device_manager_connect_device_async(self,
> +                                                   device,
> +                                                   cancellable,
> +                                                   callback,
> +                                                   user_data);
> +#endif
> +#endif
> +}
>
>   gboolean spice_usb_device_manager_connect_device_finish(
>       SpiceUsbDeviceManager *self, GAsyncResult *res, GError **err)

<snip>

Regards,

Hans


More information about the Spice-devel mailing list