[Spice-devel] [spice-gtk] [PATCH] Provide a method to check if a USB device matches a specific class, subclass and protocol
Fabiano FidĂȘncio
fabiano at fidencio.org
Wed Nov 12 09:22:58 PST 2014
Hi Uri,
On Wed, Nov 12, 2014 at 6:01 PM, Uri Lublin <uril at redhat.com> wrote:
> Hi Fabiano,
>
> Please see some comments below.
>
> On 11/11/2014 04:29 PM, Fabiano FidĂȘncio wrote:
>>
>> 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.
>
>
> Note that the filter can act upon VID/PID such that any specific device can
> have its own rule, e.g. -1, VID, PID, -1, 1
Yeah, but still hard to filter for all keyboard devices, for instance.
>
>> ---
>> 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);
>
>
> I think you should first look at the device descriptor for that information
> and only if it's specified there that the information is to be found
> in the interface, look at the config_descriptor. (But I'm not
> sure, maybe the config_descriptor always contains that
> information)
Hmmm. You're right. When bDeviceClass is 0, means that I should check
in the Interface level, as shown in the lsusb -v
Bus 003 Device 013: ID 05ac:0220 Apple, Inc. Aluminum Keyboard (ANSI)
Couldn't open device, some information will be missing
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x05ac Apple, Inc.
idProduct 0x0220 Aluminum Keyboard (ANSI)
bcdDevice 0.69
iManufacturer 1
iProduct 2
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 59
bNumInterfaces 2
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xa0
(Bus Powered)
Remote Wakeup
MaxPower 20mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 1 Boot Interface Subclass
bInterfaceProtocol 1 Keyboard
iInterface 0
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.11
bCountryCode 33 US
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 75
Report Descriptors:
** UNAVAILABLE **
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 10
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 0 No Subclass
bInterfaceProtocol 0 None
iInterface 0
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.11
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 47
Report Descriptors:
** UNAVAILABLE **
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0001 1x 1 bytes
bInterval 10
>
>
>> + 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));
>
>
> You do not need to allocate memory here.
> libusb_get_active_config_descriptor allocates memory for you (if
> successful).
> So, this memory is leaked.
> Same below.
Ooops, thanks!
>
>
>> + 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
>
> s/usbclass/subclass/
>>
>> + * @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);
>
>
> Note that on Windows, currently, we do not keep info->libdev, as
> it may change upon device installation.
>
Yeah, unfortunately Windows is not going to take advantage of these bits.
> Regards,
> Uri.
>>
>> +
>> + 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);
>
>
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel
Best Regards,
--
Fabiano FidĂȘncio
More information about the Spice-devel
mailing list