[Spice-devel] [spice-gtk Win32 v4 03/17] Make SpiceUsbDevice a box for SpiceUsbDeviceInfo, instead of a box for libusb_device

Uri Lublin uril at redhat.com
Thu Jul 5 13:43:55 PDT 2012


Note that this change may affect performance a bit, as sometimes there is
a need to find the libusb_device or the SpiceUsbDevice. Likely it's negligible.
---
 gtk/channel-usbredir.c        |    2 +-
 gtk/usb-device-manager-priv.h |   10 ++-
 gtk/usb-device-manager.c      |  188 +++++++++++++++++++++++++++++-----------
 3 files changed, 146 insertions(+), 54 deletions(-)

diff --git a/gtk/channel-usbredir.c b/gtk/channel-usbredir.c
index 3d57152..354d2e1 100644
--- a/gtk/channel-usbredir.c
+++ b/gtk/channel-usbredir.c
@@ -569,7 +569,7 @@ static void do_emit_main_context(GObject *object, int event, gpointer params)
             spice_usb_device_manager_device_error(
                 spice_usb_device_manager_get(
                     spice_channel_get_session(SPICE_CHANNEL(channel)), NULL),
-                (SpiceUsbDevice *)p->device, p->error);
+                p->device, p->error);
         }
         break;
     }
diff --git a/gtk/usb-device-manager-priv.h b/gtk/usb-device-manager-priv.h
index 912e3bf..435184e 100644
--- a/gtk/usb-device-manager-priv.h
+++ b/gtk/usb-device-manager-priv.h
@@ -31,9 +31,17 @@ gboolean spice_usb_device_manager_start_event_listening(
 void spice_usb_device_manager_stop_event_listening(
     SpiceUsbDeviceManager *manager);

+#ifdef USE_USBREDIR
+#include <libusb.h>
 void spice_usb_device_manager_device_error(
-    SpiceUsbDeviceManager *manager, SpiceUsbDevice *device, GError *err);
+    SpiceUsbDeviceManager *manager, libusb_device *device, GError *err);

+guint8 spice_usb_device_get_busnum(SpiceUsbDevice *device);
+guint8 spice_usb_device_get_devaddr(SpiceUsbDevice *device);
+guint16 spice_usb_device_get_vid(SpiceUsbDevice *device);
+guint16 spice_usb_device_get_pid(SpiceUsbDevice *device);
+
+#endif
 G_END_DECLS

 #endif /* __SPICE_USB_DEVICE_MANAGER_PRIV_H__ */
diff --git a/gtk/usb-device-manager.c b/gtk/usb-device-manager.c
index c4cbc20..93bcc9b 100644
--- a/gtk/usb-device-manager.c
+++ b/gtk/usb-device-manager.c
@@ -129,13 +129,21 @@ static void spice_usb_device_unref(SpiceUsbDevice *device);

 static gboolean spice_usb_device_equal_libdev(SpiceUsbDevice *device,
                                               libusb_device *libdev);
+static SpiceUsbDevice *
+spice_usb_device_manager_libdev_to_device(SpiceUsbDeviceManager *self,
+                                          libusb_device *libdev);
+static libusb_device *
+spice_usb_device_manager_device_to_libdev(SpiceUsbDeviceManager *self,
+                                          SpiceUsbDevice *device);
+
 G_DEFINE_BOXED_TYPE(SpiceUsbDevice, spice_usb_device,
-                    (GBoxedCopyFunc)libusb_ref_device,
-                    (GBoxedFreeFunc)libusb_unref_device)
+                    (GBoxedCopyFunc)spice_usb_device_ref,
+                    (GBoxedFreeFunc)spice_usb_device_unref)

 #else
 G_DEFINE_BOXED_TYPE(SpiceUsbDevice, spice_usb_device, g_object_ref, g_object_unref)
-#endif
+#endif /* USBREDIR */
+
 static void spice_usb_device_manager_initable_iface_init(GInitableIface *iface);

 static guint signals[LAST_SIGNAL] = { 0, };
@@ -153,7 +161,7 @@ static void spice_usb_device_manager_init(SpiceUsbDeviceManager *self)
     priv->channels = g_ptr_array_new();
 #ifdef USE_USBREDIR
     priv->devices  = g_ptr_array_new_with_free_func((GDestroyNotify)
-                                                    libusb_unref_device);
+                                                    spice_usb_device_unref);
 #endif
 }

@@ -536,12 +544,12 @@ static void spice_usb_device_manager_auto_connect_cb(GObject      *gobject,
                                                      gpointer      user_data)
 {
     SpiceUsbDeviceManager *self = SPICE_USB_DEVICE_MANAGER(gobject);
-    libusb_device *device = user_data;
+    SpiceUsbDevice *device = user_data;
     GError *err = NULL;

     spice_usb_device_manager_connect_device_finish(self, res, &err);
     if (err) {
-        gchar *desc = spice_usb_device_get_description((SpiceUsbDevice *)device, NULL);
+        gchar *desc = spice_usb_device_get_description(device, NULL);
         g_prefix_error(&err, "Could not auto-redirect %s: ", desc);
         g_free(desc);

@@ -549,16 +557,18 @@ static void spice_usb_device_manager_auto_connect_cb(GObject      *gobject,
         g_signal_emit(self, signals[AUTO_CONNECT_FAILED], 0, device, err);
         g_error_free(err);
     }
-    libusb_unref_device(device);
+    spice_usb_device_unref(device);
 }

 static void spice_usb_device_manager_add_dev(SpiceUsbDeviceManager  *self,
                                              GUdevDevice            *udev)
 {
     SpiceUsbDeviceManagerPrivate *priv = self->priv;
-    libusb_device *device = NULL, **dev_list = NULL;
+    libusb_device **dev_list = NULL;
+    SpiceUsbDevice *device = NULL;
     const gchar *devtype, *devclass;
     int i, bus, address;
+    gboolean filter_ok = FALSE;

     devtype = g_udev_device_get_property(udev, "DEVTYPE");
     /* Check if this is a usb device (and not an interface) */
@@ -583,11 +593,19 @@ static void spice_usb_device_manager_add_dev(SpiceUsbDeviceManager  *self,
     for (i = 0; dev_list && dev_list[i]; i++) {
         if (libusb_get_bus_number(dev_list[i]) == bus &&
             libusb_get_device_address(dev_list[i]) == address) {
-            device = libusb_ref_device(dev_list[i]);
+            device = (SpiceUsbDevice*)spice_usb_device_set_info(dev_list[i]);
             break;
         }
     }

+    if (device && priv->auto_connect) {
+        /* check filter before unref'ing dev_list[i] */
+        filter_ok = usbredirhost_check_device_filter(
+                                priv->auto_conn_filter_rules,
+                                priv->auto_conn_filter_rules_count,
+                                dev_list[i], 0) == 0;
+    }
+
     if (!priv->coldplug_list)
         libusb_free_device_list(dev_list, 1);

@@ -600,21 +618,17 @@ static void spice_usb_device_manager_add_dev(SpiceUsbDeviceManager  *self,
     g_ptr_array_add(priv->devices, device);

     if (priv->auto_connect) {
-        gboolean can_redirect, auto_ok;
+        gboolean can_redirect;

         can_redirect = spice_usb_device_manager_can_redirect_device(
-                                        self, (SpiceUsbDevice *)device, NULL);
-
-        auto_ok = usbredirhost_check_device_filter(
-                            priv->auto_conn_filter_rules,
-                            priv->auto_conn_filter_rules_count,
-                            device, 0) == 0;
+                                        self, device, NULL);

-        if (can_redirect && auto_ok)
+        if (can_redirect && filter_ok) {
             spice_usb_device_manager_connect_device_async(self,
-                                   (SpiceUsbDevice *)device, NULL,
+                                   device, NULL,
                                    spice_usb_device_manager_auto_connect_cb,
-                                   libusb_ref_device(device));
+                                   g_object_ref(device));
+        }
     }

     SPICE_DEBUG("device added %p", device);
@@ -625,7 +639,7 @@ static void spice_usb_device_manager_remove_dev(SpiceUsbDeviceManager  *self,
                                                 GUdevDevice            *udev)
 {
     SpiceUsbDeviceManagerPrivate *priv = self->priv;
-    libusb_device *curr, *device = NULL;
+    SpiceUsbDevice *curr, *device = NULL;
     int bus, address;
     guint i;

@@ -634,8 +648,8 @@ static void spice_usb_device_manager_remove_dev(SpiceUsbDeviceManager  *self,

     for (i = 0; i < priv->devices->len; i++) {
         curr = g_ptr_array_index(priv->devices, i);
-        if (libusb_get_bus_number(curr) == bus &&
-               libusb_get_device_address(curr) == address) {
+        if (spice_usb_device_get_busnum(curr) == bus &&
+               spice_usb_device_get_devaddr(curr) == address) {
             device = curr;
             break;
         }
@@ -740,24 +754,32 @@ void spice_usb_device_manager_stop_event_listening(
         priv->event_thread_run = FALSE;
 }

+G_GNUC_INTERNAL
 void spice_usb_device_manager_device_error(
-    SpiceUsbDeviceManager *self, SpiceUsbDevice *device, GError *err)
+    SpiceUsbDeviceManager *self, libusb_device *libdev, GError *err)
 {
+    SpiceUsbDevice *device;
+
+    g_return_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self));
+    g_return_if_fail(libdev != 0);
+
+    device = spice_usb_device_manager_libdev_to_device(self, libdev);
+
     g_signal_emit(self, signals[DEVICE_ERROR], 0, device, err);
 }
 #endif

 static SpiceUsbredirChannel *spice_usb_device_manager_get_channel_for_dev(
-    SpiceUsbDeviceManager *manager, SpiceUsbDevice *_device)
+    SpiceUsbDeviceManager *manager, SpiceUsbDevice *device)
 {
 #ifdef USE_USBREDIR
     SpiceUsbDeviceManagerPrivate *priv = manager->priv;
-    libusb_device *device = (libusb_device *)_device;
     guint i;

     for (i = 0; i < priv->channels->len; i++) {
         SpiceUsbredirChannel *channel = g_ptr_array_index(priv->channels, i);
-        if (spice_usbredir_channel_get_device(channel) == device)
+        libusb_device *libdev = spice_usbredir_channel_get_device(channel);
+        if (spice_usb_device_equal_libdev(device, libdev))
             return channel;
     }
 #endif
@@ -817,10 +839,10 @@ GPtrArray* spice_usb_device_manager_get_devices(SpiceUsbDeviceManager *self)
     guint i;

     devices_copy = g_ptr_array_new_with_free_func((GDestroyNotify)
-                                                  libusb_unref_device);
+                                                  spice_usb_device_unref);
     for (i = 0; i < priv->devices->len; i++) {
-        libusb_device *device = g_ptr_array_index(priv->devices, i);
-        g_ptr_array_add(devices_copy, libusb_ref_device(device));
+        SpiceUsbDevice *device = g_ptr_array_index(priv->devices, i);
+        g_ptr_array_add(devices_copy, spice_usb_device_ref(device));
     }
 #endif

@@ -869,6 +891,7 @@ void spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,

 #ifdef USE_USBREDIR
     SpiceUsbDeviceManagerPrivate *priv = self->priv;
+    libusb_device *libdev;
     guint i;

     if (spice_usb_device_manager_is_device_connected(self, device)) {
@@ -884,11 +907,13 @@ void spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
         if (spice_usbredir_channel_get_device(channel))
             continue; /* Skip already used channels */

+        libdev = spice_usb_device_manager_device_to_libdev(self, device);
         spice_usbredir_channel_connect_device_async(channel,
-                                 (libusb_device *)device,
+                                 libdev,
                                  cancellable,
                                  spice_usb_device_manager_channel_connect_cb,
                                  result);
+        libusb_unref_device(libdev);
         return;
     }
 #endif
@@ -980,13 +1005,20 @@ spice_usb_device_manager_can_redirect_device(SpiceUsbDeviceManager  *self,
         g_ptr_array_index(priv->channels, 0),
         &guest_filter_rules, &guest_filter_rules_count);

-    if (guest_filter_rules &&
-            usbredirhost_check_device_filter(
+    if (guest_filter_rules) {
+        gboolean filter_ok;
+        libusb_device *ldev;
+        ldev = spice_usb_device_manager_device_to_libdev(self, device);
+        g_return_val_if_fail(ldev != NULL, FALSE);
+        filter_ok = (usbredirhost_check_device_filter(
                             guest_filter_rules, guest_filter_rules_count,
-                            (libusb_device *)device, 0) != 0) {
-        g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
-                            _("Some USB devices are blocked by host policy"));
-        return FALSE;
+                            ldev, 0) == 0);
+        libusb_unref_device(ldev);
+        if (!filter_ok) {
+            g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
+                                _("Some USB devices are blocked by host policy"));
+            return FALSE;
+        }
     }

     /* Check if there are free channels */
@@ -1030,34 +1062,32 @@ spice_usb_device_manager_can_redirect_device(SpiceUsbDeviceManager  *self,
  *
  * Returns: a newly-allocated string holding the description, or %NULL if failed
  */
-gchar *spice_usb_device_get_description(SpiceUsbDevice *_device, const gchar *format)
+gchar *spice_usb_device_get_description(SpiceUsbDevice *device, const gchar *format)
 {
 #ifdef USE_USBREDIR
-    libusb_device *device = (libusb_device *)_device;
-    struct libusb_device_descriptor desc;
-    int bus, address;
+    int bus, addr, vid, pid;
     gchar *description, *descriptor, *manufacturer = NULL, *product = NULL;

-    g_return_val_if_fail(device != NULL, NULL);
+    g_return_val_if_fail(device!= NULL, NULL);

-    bus     = libusb_get_bus_number(device);
-    address = libusb_get_device_address(device);
+    bus  = spice_usb_device_get_busnum(device);
+    addr = spice_usb_device_get_devaddr(device);
+    vid  = spice_usb_device_get_vid(device);
+    pid  = spice_usb_device_get_pid(device);

-    if (libusb_get_device_descriptor(device, &desc) == LIBUSB_SUCCESS) {
-        spice_usb_util_get_device_strings(bus, address,
-                                          desc.idVendor, desc.idProduct,
-                                          &manufacturer, &product);
-        descriptor = g_strdup_printf("[%04x:%04x]", desc.idVendor, desc.idProduct);
+    if ((vid > 0) && (pid > 0)) {
+        descriptor = g_strdup_printf("[%04x:%04x]", vid, pid);
     } else {
-        spice_usb_util_get_device_strings(bus, address, -1, -1,
-                                          &manufacturer, &product);
         descriptor = g_strdup("");
     }

+    spice_usb_util_get_device_strings(bus, addr, vid, pid,
+                                      &manufacturer, &product);
+
     if (!format)
         format = _("%s %s %s at %d-%d");

-    description = g_strdup_printf(format, manufacturer, product, descriptor, bus, address);
+    description = g_strdup_printf(format, manufacturer, product, descriptor, bus, addr);

     g_free(manufacturer);
     g_free(descriptor);
@@ -1070,7 +1100,6 @@ gchar *spice_usb_device_get_description(SpiceUsbDevice *_device, const gchar *fo
 }


-
 #ifdef USE_USBREDIR
 /*
  * SpiceUsbDeviceInfo
@@ -1196,4 +1225,59 @@ spice_usb_device_equal_libdev(SpiceUsbDevice *device,

     return ((bus1 == bus2) && (addr1 == addr2));
 }
+
+static SpiceUsbDevice *
+spice_usb_device_manager_libdev_to_device(SpiceUsbDeviceManager *self,
+                                          libusb_device *libdev)
+{
+    SpiceUsbDeviceManagerPrivate *priv = self->priv;
+    SpiceUsbDevice *device = NULL;
+    int i;
+
+    for (i = 0; i < priv->devices->len; i++) {
+        device = g_ptr_array_index(priv->devices, i);
+        if (spice_usb_device_equal_libdev(device, libdev)) {
+            break; /* found it */
+        }
+        device = NULL; /* did not find it yet */
+    }
+    return device;
+}
+
+/*
+ * Caller must libusb_unref_device the libusb_device returned by this function.
+ * Returns a libusb_device, or NULL upon failure
+ */
+static libusb_device *
+spice_usb_device_manager_device_to_libdev(SpiceUsbDeviceManager *self,
+                                          SpiceUsbDevice *device)
+{
+    libusb_device *d, **devlist;
+    guint8 bus, addr;
+    int i;
+
+    g_return_val_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self), NULL);
+    g_return_val_if_fail(device != NULL, NULL);
+    g_return_val_if_fail(self->priv != NULL, NULL);
+    g_return_val_if_fail(self->priv->context != NULL, NULL);
+
+    bus  = spice_usb_device_get_busnum(device);
+    addr = spice_usb_device_get_devaddr(device);
+
+    libusb_get_device_list(self->priv->context, &devlist);
+    if (!devlist)
+        return NULL;
+
+    for (i = 0; (d = devlist[i]) != NULL; i++) {
+        if ((libusb_get_bus_number(d) == bus) &&
+            (libusb_get_device_address(d) == addr)) {
+            libusb_ref_device(d);
+            break;
+        }
+    }
+
+    libusb_free_device_list(devlist, 1);
+
+    return d;
+}
 #endif /* USE_USBREDIR */
-- 
1.7.7.6



More information about the Spice-devel mailing list