<div dir="ltr">Hi<br><div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Nov 11, 2014 at 3:29 PM, Fabiano Fidêncio <span dir="ltr"><<a href="mailto:fidencio@redhat.com" target="_blank">fidencio@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">As we only can filter USB devices by their Classes and sometimes it is<br>
not enough (eg: I do not want to have Keyboard and Mouse, but want to<br>
have have Joysticks, being all of them part of HID Class), provide to<br>
the applications a way match the device itself with the desired Class,<br>
SubClass and Protocol, so the applications refine the filter provided<br>
by usbredir.<br>
---<br>
This patch was written based on <a href="https://bugzilla.gnome.org/show_bug.cgi?id=698430" target="_blank">https://bugzilla.gnome.org/show_bug.cgi?id=698430</a><br>
Any suggestion to have a shorter short-log is welcome :-)<br></blockquote><div><br></div><div>Not so much the log, but rather the code could have been made much shorter.<br><br></div><div>I would rather see a spice_usb_device_get_libusb_device() getter tbh. I don't think libusb is going to be replaced any time soon.<br><br></div><div>Hans, could you review too? thanks<br><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
---<br>
 gtk/map-file             |  1 +<br>
 gtk/spice-glib-sym-file  |  1 +<br>
 gtk/usb-device-manager.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++<br>
 gtk/usb-device-manager.h |  1 +<br>
 4 files changed, 99 insertions(+)<br>
<br>
diff --git a/gtk/map-file b/gtk/map-file<br>
index 9f8d04e..6bbf407 100644<br>
--- a/gtk/map-file<br>
+++ b/gtk/map-file<br>
@@ -124,6 +124,7 @@ spice_usb_device_manager_get_devices;<br>
 spice_usb_device_manager_get_devices_with_filter;<br>
 spice_usb_device_manager_get_type;<br>
 spice_usb_device_manager_is_device_connected;<br>
+spice_usb_device_matches_interface;<br>
 spice_usb_device_widget_get_type;<br>
 spice_usb_device_widget_new;<br>
 spice_usbredir_channel_get_type;<br>
diff --git a/gtk/spice-glib-sym-file b/gtk/spice-glib-sym-file<br>
index 2189fa5..83f7f18 100644<br>
--- a/gtk/spice-glib-sym-file<br>
+++ b/gtk/spice-glib-sym-file<br>
@@ -101,6 +101,7 @@ spice_usb_device_manager_get_devices<br>
 spice_usb_device_manager_get_devices_with_filter<br>
 spice_usb_device_manager_get_type<br>
 spice_usb_device_manager_is_device_connected<br>
+spice_usb_device_matches_interface<br>
 spice_usbredir_channel_get_type<br>
 spice_util_get_debug<br>
 spice_util_get_version_string<br>
diff --git a/gtk/usb-device-manager.c b/gtk/usb-device-manager.c<br>
index 5013b6c..6749b0d 100644<br>
--- a/gtk/usb-device-manager.c<br>
+++ b/gtk/usb-device-manager.c<br>
@@ -706,6 +706,30 @@ static gboolean spice_usb_device_manager_get_device_descriptor(<br>
     return TRUE;<br>
 }<br>
<br>
+static gboolean spice_usb_device_manager_get_config_descriptor(<br>
+    libusb_device *libdev,<br>
+    struct libusb_config_descriptor **config)<br>
+{<br>
+    int errcode;<br>
+    const gchar *errstr;<br>
+<br>
+    g_return_val_if_fail(libdev != NULL, FALSE);<br>
+    g_return_val_if_fail(config != NULL, FALSE);<br>
+<br>
+    errcode = libusb_get_active_config_descriptor(libdev, config);<br>
+    if (errcode < 0) {<br>
+        int bus, addr;<br>
+<br>
+        bus = libusb_get_bus_number(libdev);<br>
+        addr = libusb_get_device_address(libdev);<br>
+        errstr = spice_usbutil_libusb_strerror(errcode);<br>
+        g_warning("Cannot get config descriptor for (%p) %d.%d -- %s(%d)",<br>
+                  libdev, bus, addr, errstr, errcode);<br>
+        return FALSE;<br>
+    }<br>
+    return TRUE;<br>
+}<br>
+<br>
 static gboolean spice_usb_device_manager_get_libdev_vid_pid(<br>
     libusb_device *libdev, int *vid, int *pid)<br>
 {<br>
@@ -1726,7 +1750,79 @@ gchar *spice_usb_device_get_description(SpiceUsbDevice *device, const gchar *for<br>
 #endif<br>
 }<br>
<br>
+static guint8 spice_usb_device_get_interface_class(libusb_device *libdev)<br>
+{<br>
+    struct libusb_config_descriptor *config;<br>
+    guint8 interface_class;<br>
+<br>
+    g_return_val_if_fail(libdev != NULL, 0);<br>
+<br>
+    config = g_malloc(sizeof(*config));<br>
+    spice_usb_device_manager_get_config_descriptor(libdev, &config);<br>
+    interface_class = config->interface->altsetting->bInterfaceClass;<br>
+    libusb_free_config_descriptor(config);<br>
+<br>
+    return interface_class;<br>
+}<br>
+<br>
+static guint8 spice_usb_device_get_interface_subclass(libusb_device *libdev)<br>
+{<br>
+    struct libusb_config_descriptor *config;<br>
+    guint8 interface_subclass;<br>
+<br>
+    g_return_val_if_fail(libdev != NULL, 0);<br>
+<br>
+    config = g_malloc(sizeof(*config));<br>
+    spice_usb_device_manager_get_config_descriptor(libdev, &config);<br>
+    interface_subclass = config->interface->altsetting->bInterfaceSubClass;<br>
+    libusb_free_config_descriptor(config);<br>
+<br>
+    return interface_subclass;<br>
+}<br>
+<br>
+static guint8 spice_usb_device_get_interface_protocol(libusb_device *libdev)<br>
+{<br>
+    struct libusb_config_descriptor *config;<br>
+    guint8 interface_protocol;<br>
+<br>
+    g_return_val_if_fail(libdev != NULL, 0);<br>
+<br>
+    config = g_malloc(sizeof(*config));<br>
+    spice_usb_device_manager_get_config_descriptor(libdev, &config);<br>
+    interface_protocol = config->interface->altsetting->bInterfaceProtocol;<br>
+    libusb_free_config_descriptor(config);<br>
+<br>
+    return interface_protocol;<br>
+}<br>
+<br>
+/**<br>
+ * spice_usb_device_matches_interface:<br>
+ * @device: #SpiceUsbDevice to check if the interface info matches with<br>
+ * @class: the interface class to be checked<br>
+ * @subclass: the interface usbclass to be checked<br>
+ * @protocol; the interface protocol to be checked<br>
+ *<br>
+ * Compares if the device's interface class, subclass and protocol match with<br>
+ * the received interface class, subclass and protocol.<br>
+ *<br>
+ * Returns: TRUE if the device's interface matches with the receveid one.<br>
+ *          FALSE, otherwise.<br>
+ *<br>
+ * Since: 0.27<br>
+ **/<br>
+gboolean spice_usb_device_matches_interface(const SpiceUsbDevice *device, guint8 class, guint8 subclass, guint8 protocol)<br>
+{<br>
+    const SpiceUsbDeviceInfo *info = (const SpiceUsbDeviceInfo *)device;<br>
+<br>
+    g_return_val_if_fail(info != NULL, FALSE);<br>
+<br>
+    if ((spice_usb_device_get_interface_class(info->libdev) == class) &&<br>
+        (spice_usb_device_get_interface_subclass(info->libdev) == subclass) &&<br>
+        (spice_usb_device_get_interface_protocol(info->libdev) == protocol))<br>
+        return TRUE;<br>
<br>
+    return FALSE;<br>
+}<br>
<br>
 #ifdef USE_USBREDIR<br>
 /*<br>
diff --git a/gtk/usb-device-manager.h b/gtk/usb-device-manager.h<br>
index a7e3515..9959fe5 100644<br>
--- a/gtk/usb-device-manager.h<br>
+++ b/gtk/usb-device-manager.h<br>
@@ -89,6 +89,7 @@ GType spice_usb_device_get_type(void);<br>
 GType spice_usb_device_manager_get_type(void);<br>
<br>
 gchar *spice_usb_device_get_description(SpiceUsbDevice *device, const gchar *format);<br>
+gboolean spice_usb_device_matches_interface(const SpiceUsbDevice *device, guint8 class, guint8 subclass, guint8 protocol);<br>
<br>
 SpiceUsbDeviceManager *spice_usb_device_manager_get(SpiceSession *session,<br>
                                                     GError **err);<br>
<span class="HOEnZb"><font color="#888888">--<br>
2.1.0<br>
<br>
_______________________________________________<br>
Spice-devel mailing list<br>
<a href="mailto:Spice-devel@lists.freedesktop.org">Spice-devel@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/spice-devel" target="_blank">http://lists.freedesktop.org/mailman/listinfo/spice-devel</a><br>
</font></span></blockquote></div><br><br clear="all"><br>-- <br><div class="gmail_signature">Marc-André Lureau</div>
</div></div></div>