As we only can filter USB devices by their Classes and sometimes it is not enough (eg: I do not want to have Keyboard and Mouse, but want to have have Joysticks, being all of them part of HID Class), provide to the applications a way match the device itself with the desired Class, SubClass and Protocol, so the applications refine the filter provided by usbredir. --- This patch was written based on https://bugzilla.gnome.org/show_bug.cgi?id=698430 Any suggestion to have a shorter short-log is welcome :-) --- gtk/map-file | 1 + gtk/spice-glib-sym-file | 1 + gtk/usb-device-manager.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++ gtk/usb-device-manager.h | 1 + 4 files changed, 99 insertions(+) diff --git a/gtk/map-file b/gtk/map-file index 9f8d04e..6bbf407 100644 --- a/gtk/map-file +++ b/gtk/map-file @@ -124,6 +124,7 @@ spice_usb_device_manager_get_devices; spice_usb_device_manager_get_devices_with_filter; spice_usb_device_manager_get_type; spice_usb_device_manager_is_device_connected; +spice_usb_device_matches_interface; spice_usb_device_widget_get_type; spice_usb_device_widget_new; spice_usbredir_channel_get_type; diff --git a/gtk/spice-glib-sym-file b/gtk/spice-glib-sym-file index 2189fa5..83f7f18 100644 --- a/gtk/spice-glib-sym-file +++ b/gtk/spice-glib-sym-file @@ -101,6 +101,7 @@ spice_usb_device_manager_get_devices spice_usb_device_manager_get_devices_with_filter spice_usb_device_manager_get_type spice_usb_device_manager_is_device_connected +spice_usb_device_matches_interface spice_usbredir_channel_get_type spice_util_get_debug spice_util_get_version_string diff --git a/gtk/usb-device-manager.c b/gtk/usb-device-manager.c index 5013b6c..6749b0d 100644 --- a/gtk/usb-device-manager.c +++ b/gtk/usb-device-manager.c @@ -706,6 +706,30 @@ static gboolean spice_usb_device_manager_get_device_descriptor( return TRUE; } +static gboolean spice_usb_device_manager_get_config_descriptor( + libusb_device *libdev, + struct libusb_config_descriptor **config) +{ + int errcode; + const gchar *errstr; + + g_return_val_if_fail(libdev != NULL, FALSE); + g_return_val_if_fail(config != NULL, FALSE); + + errcode = libusb_get_active_config_descriptor(libdev, config); + if (errcode < 0) { + int bus, addr; + + bus = libusb_get_bus_number(libdev); + addr = libusb_get_device_address(libdev); + errstr = spice_usbutil_libusb_strerror(errcode); + g_warning("Cannot get config descriptor for (%p) %d.%d -- %s(%d)", + libdev, bus, addr, errstr, errcode); + return FALSE; + } + return TRUE; +} + static gboolean spice_usb_device_manager_get_libdev_vid_pid( libusb_device *libdev, int *vid, int *pid) { @@ -1726,7 +1750,79 @@ gchar *spice_usb_device_get_description(SpiceUsbDevice *device, const gchar *for #endif } +static guint8 spice_usb_device_get_interface_class(libusb_device *libdev) +{ + struct libusb_config_descriptor *config; + guint8 interface_class; + + g_return_val_if_fail(libdev != NULL, 0); + + config = g_malloc(sizeof(*config)); + spice_usb_device_manager_get_config_descriptor(libdev, &config); + interface_class = config->interface->altsetting->bInterfaceClass; + libusb_free_config_descriptor(config); + + return interface_class; +} + +static guint8 spice_usb_device_get_interface_subclass(libusb_device *libdev) +{ + struct libusb_config_descriptor *config; + guint8 interface_subclass; + + g_return_val_if_fail(libdev != NULL, 0); + + config = g_malloc(sizeof(*config)); + spice_usb_device_manager_get_config_descriptor(libdev, &config); + interface_subclass = config->interface->altsetting->bInterfaceSubClass; + libusb_free_config_descriptor(config); + + return interface_subclass; +} + +static guint8 spice_usb_device_get_interface_protocol(libusb_device *libdev) +{ + struct libusb_config_descriptor *config; + guint8 interface_protocol; + + g_return_val_if_fail(libdev != NULL, 0); + + config = g_malloc(sizeof(*config)); + spice_usb_device_manager_get_config_descriptor(libdev, &config); + interface_protocol = config->interface->altsetting->bInterfaceProtocol; + libusb_free_config_descriptor(config); + + return interface_protocol; +} + +/** + * spice_usb_device_matches_interface: + * @device: #SpiceUsbDevice to check if the interface info matches with + * @class: the interface class to be checked + * @subclass: the interface usbclass to be checked + * @protocol; the interface protocol to be checked + * + * Compares if the device's interface class, subclass and protocol match with + * the received interface class, subclass and protocol. + * + * Returns: TRUE if the device's interface matches with the receveid one. + * FALSE, otherwise. + * + * Since: 0.27 + **/ +gboolean spice_usb_device_matches_interface(const SpiceUsbDevice *device, guint8 class, guint8 subclass, guint8 protocol) +{ + const SpiceUsbDeviceInfo *info = (const SpiceUsbDeviceInfo *)device; + + g_return_val_if_fail(info != NULL, FALSE); + + if ((spice_usb_device_get_interface_class(info->libdev) == class) && + (spice_usb_device_get_interface_subclass(info->libdev) == subclass) && + (spice_usb_device_get_interface_protocol(info->libdev) == protocol)) + return TRUE; + return FALSE; +} #ifdef USE_USBREDIR /* diff --git a/gtk/usb-device-manager.h b/gtk/usb-device-manager.h index a7e3515..9959fe5 100644 --- a/gtk/usb-device-manager.h +++ b/gtk/usb-device-manager.h @@ -89,6 +89,7 @@ GType spice_usb_device_get_type(void); GType spice_usb_device_manager_get_type(void); gchar *spice_usb_device_get_description(SpiceUsbDevice *device, const gchar *format); +gboolean spice_usb_device_matches_interface(const SpiceUsbDevice *device, guint8 class, guint8 subclass, guint8 protocol); SpiceUsbDeviceManager *spice_usb_device_manager_get(SpiceSession *session, GError **err); -- 2.1.0 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel