[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