[Spice-devel] [spice-gtk] [PATCH] Provide a method to check if a USB device matches a specific class, subclass and protocol

Uri Lublin uril at redhat.com
Wed Nov 12 09:58:57 PST 2014


On 11/12/2014 07:22 PM, Fabiano FidĂȘncio wrote:
> 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.

The default can be to block all HID devices.
If a user wants to usbredir a specific device, e.g. a Joystick,
s/he can find out its VID/PID (using lsusb) and add a rule
to the usb-filter accordingly.
I agree it's not as convenient as filtering by subclass/protocol.

Another comment with regards to your patch is:
config->interface may hold an array of (bNumInterfaces) interfaces
and you are only looking at the first one.
Same for config->interface->altsetting

As for the Windows comment, with the patch applied windows
build is going to fail, isn't it ?

Regards,
     Uri.

>
>>> ---
>>> 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,



More information about the Spice-devel mailing list