From 108b029b68c41f1d3ffada83c6c494e7f75e660e Mon Sep 17 00:00:00 2001 From: Rosen Kolev Date: Wed, 21 Sep 2011 18:11:13 +0300 Subject: Extended USB device matching. Extended the USB device matching, adding checks for interface class, interface subclass, and interface protocol. --- drivers/usb/core/usb.c | 34 ++++++++++++++++++++++++++++++++++ include/usb/usb.h | 22 ++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index a23446ad1b..67c20166d7 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -1283,10 +1283,13 @@ static int usb_match_device(struct usb_device *dev, const struct usb_device_id * return 1; } + /* returns 0 if no match, 1 if match */ static int usb_match_one_id(struct usb_device *usbdev, const struct usb_device_id *id) { + int ifno; + /* proc_connectinfo in devio.c may call us with id == NULL. */ if (id == NULL) return 0; @@ -1294,6 +1297,37 @@ static int usb_match_one_id(struct usb_device *usbdev, if (!usb_match_device(usbdev, id)) return 0; + /* The interface class, subclass, and protocol should never be + * checked for a match if the device class is Vendor Specific, + * unless the match record specifies the Vendor ID. */ + if (usbdev->descriptor.bDeviceClass == USB_CLASS_VENDOR_SPEC && + !(id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && + (id->match_flags & USB_DEVICE_ID_MATCH_INT_INFO)) + return 0; + + if ( (id->match_flags & USB_DEVICE_ID_MATCH_INT_INFO) ) { + /* match any interface */ + for (ifno=0; ifnoconfig.no_of_if; ifno++) { + struct usb_interface_descriptor *intf; + intf = &usbdev->config.if_desc[ifno]; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) && + (id->bInterfaceClass != intf->bInterfaceClass)) + continue; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) && + (id->bInterfaceSubClass != intf->bInterfaceSubClass)) + continue; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) && + (id->bInterfaceProtocol != intf->bInterfaceProtocol)) + continue; + break; + } + if (ifno >= usbdev->config.no_of_if) + return 0; + } + return 1; } EXPORT_SYMBOL(usb_match_one_id); diff --git a/include/usb/usb.h b/include/usb/usb.h index 67157863f7..08fd1a1185 100644 --- a/include/usb/usb.h +++ b/include/usb/usb.h @@ -480,6 +480,13 @@ struct usb_device_id { #define USB_DEVICE_ID_MATCH_VENDOR 0x0001 #define USB_DEVICE_ID_MATCH_DEVICE \ (USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT) +#define USB_DEVICE_ID_MATCH_INT_CLASS 0x0080 +#define USB_DEVICE_ID_MATCH_INT_SUBCLASS 0x0100 +#define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200 +#define USB_DEVICE_ID_MATCH_INT_INFO \ + (USB_DEVICE_ID_MATCH_INT_CLASS | \ + USB_DEVICE_ID_MATCH_INT_SUBCLASS | \ + USB_DEVICE_ID_MATCH_INT_PROTOCOL) /** * USB_DEVICE - macro used to describe a specific usb device @@ -494,6 +501,21 @@ struct usb_device_id { .idVendor = (vend), \ .idProduct = (prod) +/** + * USB_INTERFACE_INFO - macro used to describe a class of usb interfaces + * @cl: bInterfaceClass value + * @sc: bInterfaceSubClass value + * @pr: bInterfaceProtocol value + * + * This macro is used to create a struct usb_device_id that matches a + * specific class of interfaces. + */ +#define USB_INTERFACE_INFO(cl, sc, pr) \ + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO, \ + .bInterfaceClass = (cl), \ + .bInterfaceSubClass = (sc), \ + .bInterfaceProtocol = (pr) + #define USB_CTRL_SET_TIMEOUT 5000 #define USB_CTRL_GET_TIMEOUT 5000 -- cgit v1.2.3