[Spice-devel,SPICE-GTK,Win,USB] win usb: request for driver uninstall only for driver that were installed

Submitted by Uri Lublin on Aug. 15, 2013, 3:41 p.m.

Details

Message ID 1376581295-15823-1-git-send-email-uril@redhat.com
State New
Headers show

Not browsing as part of any series.

Commit Message

Uri Lublin Aug. 15, 2013, 3:41 p.m.
Currently when spice_usb_device_manager_remove_dev() is called,
for windows clients a request to uninstall the driver is sent to usbclerk.

This cause problems when 2 instances (A and B) of the client are running:
- Both A and B get notified about a new USB device when it's plugged in
- A is requested to usbredir the USB device.
- A requests usbclerk to install WinUSB driver for that device.
- usbclerk starts installing the driver
- Windows sends to both A and B - device removal events, which may cause
  B to call spice_usb_device_manager_remove_dev.
- usbclerk completes installing the driver and reply to A
- B requests usbclerk to remove the WinUSB driver for that device.

To prevent that, spice-gtk now requests usbclerk to remove the driver
only if it was the instance that requested the driver to be installed.
This is done with the help of a new device SPICE_USB_DEVICE_STATE_INSTALLED
state.

rhbz#919166
---
 gtk/usb-device-manager.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

Patch hide | download patch | download mbox

diff --git a/gtk/usb-device-manager.c b/gtk/usb-device-manager.c
index 71d3462..1051d10 100644
--- a/gtk/usb-device-manager.c
+++ b/gtk/usb-device-manager.c
@@ -135,6 +135,7 @@  enum {
     SPICE_USB_DEVICE_STATE_DISCONNECTING,
     SPICE_USB_DEVICE_STATE_INSTALLING,
     SPICE_USB_DEVICE_STATE_UNINSTALLING,
+    SPICE_USB_DEVICE_STATE_INSTALLED,
     SPICE_USB_DEVICE_STATE_MAX
 };

@@ -1106,7 +1107,11 @@  static void spice_usb_device_manager_drv_install_cb(GObject *gobject,

     spice_usb_device_unref(device);

-    spice_usb_device_set_state(device, SPICE_USB_DEVICE_STATE_NONE);
+    if (is_install) {
+        spice_usb_device_set_state(device, SPICE_USB_DEVICE_STATE_INSTALLED);
+    } else {
+        spice_usb_device_set_state(device, SPICE_USB_DEVICE_STATE_NONE);
+    }

     if (err) {
         g_warning("win usb driver %s failed -- %s", opstr, err->message);
@@ -1550,10 +1555,17 @@  void spice_usb_device_manager_disconnect_device(SpiceUsbDeviceManager *self,
 #ifdef G_OS_WIN32
     SpiceWinUsbDriver *installer;
     UsbInstallCbInfo *cbinfo;
+    guint8 state;

     g_warn_if_fail(device != NULL);
     g_warn_if_fail(self->priv->installer != NULL);

+    state = spice_usb_device_get_state(device);
+    if ((state != SPICE_USB_DEVICE_STATE_INSTALLED) &&
+        (state != SPICE_USB_DEVICE_STATE_CONNECTED)) {
+        return;
+    }
+
     spice_usb_device_set_state(device, SPICE_USB_DEVICE_STATE_UNINSTALLING);
     if (! self->priv->installer) {
         self->priv->installer = spice_win_usb_driver_new();

Comments

ACK.

On 08/15/2013 05:41 PM, Uri Lublin wrote:
> Currently when spice_usb_device_manager_remove_dev() is called,
> for windows clients a request to uninstall the driver is sent to usbclerk.
>
> This cause problems when 2 instances (A and B) of the client are running:
> - Both A and B get notified about a new USB device when it's plugged in
> - A is requested to usbredir the USB device.
> - A requests usbclerk to install WinUSB driver for that device.
> - usbclerk starts installing the driver
> - Windows sends to both A and B - device removal events, which may cause
>    B to call spice_usb_device_manager_remove_dev.
> - usbclerk completes installing the driver and reply to A
> - B requests usbclerk to remove the WinUSB driver for that device.
>
> To prevent that, spice-gtk now requests usbclerk to remove the driver
> only if it was the instance that requested the driver to be installed.
> This is done with the help of a new device SPICE_USB_DEVICE_STATE_INSTALLED
> state.
>
> rhbz#919166
> ---
>   gtk/usb-device-manager.c | 14 +++++++++++++-
>   1 file changed, 13 insertions(+), 1 deletion(-)
>
> diff --git a/gtk/usb-device-manager.c b/gtk/usb-device-manager.c
> index 71d3462..1051d10 100644
> --- a/gtk/usb-device-manager.c
> +++ b/gtk/usb-device-manager.c
> @@ -135,6 +135,7 @@ enum {
>       SPICE_USB_DEVICE_STATE_DISCONNECTING,
>       SPICE_USB_DEVICE_STATE_INSTALLING,
>       SPICE_USB_DEVICE_STATE_UNINSTALLING,
> +    SPICE_USB_DEVICE_STATE_INSTALLED,
>       SPICE_USB_DEVICE_STATE_MAX
>   };
>
> @@ -1106,7 +1107,11 @@ static void spice_usb_device_manager_drv_install_cb(GObject *gobject,
>
>       spice_usb_device_unref(device);
>
> -    spice_usb_device_set_state(device, SPICE_USB_DEVICE_STATE_NONE);
> +    if (is_install) {
> +        spice_usb_device_set_state(device, SPICE_USB_DEVICE_STATE_INSTALLED);
> +    } else {
> +        spice_usb_device_set_state(device, SPICE_USB_DEVICE_STATE_NONE);
> +    }
>
>       if (err) {
>           g_warning("win usb driver %s failed -- %s", opstr, err->message);
> @@ -1550,10 +1555,17 @@ void spice_usb_device_manager_disconnect_device(SpiceUsbDeviceManager *self,
>   #ifdef G_OS_WIN32
>       SpiceWinUsbDriver *installer;
>       UsbInstallCbInfo *cbinfo;
> +    guint8 state;
>
>       g_warn_if_fail(device != NULL);
>       g_warn_if_fail(self->priv->installer != NULL);
>
> +    state = spice_usb_device_get_state(device);
> +    if ((state != SPICE_USB_DEVICE_STATE_INSTALLED) &&
> +        (state != SPICE_USB_DEVICE_STATE_CONNECTED)) {
> +        return;
> +    }
> +
>       spice_usb_device_set_state(device, SPICE_USB_DEVICE_STATE_UNINSTALLING);
>       if (! self->priv->installer) {
>           self->priv->installer = spice_win_usb_driver_new();
>