]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[usb] Allow for wildcard USB class IDs
authorMichael Brown <mcb30@ipxe.org>
Mon, 14 Sep 2015 16:52:25 +0000 (17:52 +0100)
committerMichael Brown <mcb30@ipxe.org>
Mon, 14 Sep 2015 20:56:40 +0000 (21:56 +0100)
Make the class ID a property of the USB driver (rather than a property
of the USB device ID), and allow USB drivers to specify a wildcard ID
for any of the three component IDs (class, subclass, or protocol).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/drivers/bus/usb.c
src/drivers/net/dm96xx.c
src/drivers/net/ecm.c
src/drivers/net/ncm.c
src/drivers/net/smsc75xx.c
src/drivers/usb/usbhub.c
src/drivers/usb/usbio.c
src/drivers/usb/usbkbd.c
src/include/ipxe/usb.h

index d8d7f6b37686f8a0ee1e17a1ea89cb403272c1a9..63a7e46a6daeebd84e5651721243a0bee76e8b35 100644 (file)
@@ -985,6 +985,7 @@ static int usb_describe ( struct usb_device *usb,
        unsigned int i;
 
        /* Fill in vendor and product ID */
+       memset ( desc, 0, sizeof ( *desc ) );
        desc->vendor = le16_to_cpu ( usb->device.vendor );
        desc->product = le16_to_cpu ( usb->device.product );
 
@@ -1023,7 +1024,7 @@ static int usb_describe ( struct usb_device *usb,
        interfaces[0] = first;
 
        /* Look for a CDC union descriptor, if applicable */
-       if ( ( desc->class.class == USB_CLASS_CDC ) &&
+       if ( ( desc->class.class.class == USB_CLASS_CDC ) &&
             ( cdc_union = cdc_union_descriptor ( config, interface ) ) ) {
 
                /* Determine interface count */
@@ -1096,15 +1097,17 @@ struct usb_driver * usb_find_driver ( struct usb_function_descriptor *desc,
        for_each_table_entry ( driver, USB_DRIVERS ) {
                for ( i = 0 ; i < driver->id_count ; i++ ) {
 
-                       /* Check for a matching ID */
+                       /* Ignore non-matching driver class */
+                       if ( ( driver->class.class.scalar ^ desc->class.scalar )
+                            & driver->class.mask.scalar )
+                               continue;
+
+                       /* Look for a matching ID */
                        *id = &driver->ids[i];
                        if ( ( ( (*id)->vendor == desc->vendor ) ||
                               ( (*id)->vendor == USB_ANY_ID ) ) &&
                             ( ( (*id)->product == desc->product ) ||
-                              ( (*id)->product == USB_ANY_ID ) ) &&
-                            ( (*id)->class.class == desc->class.class ) &&
-                            ( (*id)->class.subclass == desc->class.subclass )&&
-                            ( (*id)->class.protocol == desc->class.protocol ) )
+                              ( (*id)->product == USB_ANY_ID ) ) )
                                return driver;
                }
        }
@@ -1178,8 +1181,9 @@ static int usb_probe ( struct usb_function *func,
        if ( ! driver ) {
                DBGC ( usb, "USB %s %04x:%04x class %d:%d:%d has no driver\n",
                       func->name, func->desc.vendor, func->desc.product,
-                      func->desc.class.class, func->desc.class.subclass,
-                      func->desc.class.protocol );
+                      func->desc.class.class.class,
+                      func->desc.class.class.subclass,
+                      func->desc.class.class.protocol );
                return -ENOENT;
        }
 
@@ -1265,8 +1269,9 @@ usb_probe_all ( struct usb_device *usb,
                        goto err_probe;
                DBGC ( usb, "USB %s %04x:%04x class %d:%d:%d interfaces ",
                       func->name, func->desc.vendor, func->desc.product,
-                      func->desc.class.class, func->desc.class.subclass,
-                      func->desc.class.protocol );
+                      func->desc.class.class.class,
+                      func->desc.class.class.subclass,
+                      func->desc.class.class.protocol );
                for ( i = 0 ; i < func->desc.count ; i++ )
                        DBGC ( usb, "%s%d", ( i ? "," : "" ),
                               func->interface[i] );
index b4eff50abfff23899605df8b7ea6e5400c44b0d0..817a84a29fa5965612ab7af3998cd7dc6ef8b7a5 100644 (file)
@@ -666,6 +666,7 @@ static struct usb_device_id dm96xx_ids[] = {
 struct usb_driver dm96xx_driver __usb_driver = {
        .ids = dm96xx_ids,
        .id_count = ( sizeof ( dm96xx_ids ) / sizeof ( dm96xx_ids[0] ) ),
+       .class = USB_CLASS_ID ( USB_ANY_ID, USB_ANY_ID, USB_ANY_ID ),
        .score = USB_SCORE_NORMAL,
        .probe = dm96xx_probe,
        .remove = dm96xx_remove,
index f24a435a52da5e705baa8dcf7333d918e10cb0d5..371611d54ea9de3e71004d3abb37e31d7fe88d7c 100644 (file)
@@ -503,11 +503,6 @@ static struct usb_device_id ecm_ids[] = {
                .name = "cdc-ecm",
                .vendor = USB_ANY_ID,
                .product = USB_ANY_ID,
-               .class = {
-                       .class = USB_CLASS_CDC,
-                       .subclass = USB_SUBCLASS_CDC_ECM,
-                       .protocol = 0,
-               },
        },
 };
 
@@ -515,6 +510,7 @@ static struct usb_device_id ecm_ids[] = {
 struct usb_driver ecm_driver __usb_driver = {
        .ids = ecm_ids,
        .id_count = ( sizeof ( ecm_ids ) / sizeof ( ecm_ids[0] ) ),
+       .class = USB_CLASS_ID ( USB_CLASS_CDC, USB_SUBCLASS_CDC_ECM, 0 ),
        .score = USB_SCORE_NORMAL,
        .probe = ecm_probe,
        .remove = ecm_remove,
index 3c3ab90f1c857ca432568b15a0273489a9e702ff..afa794ea352cccabecf03a45e2162deeaf9e3162 100644 (file)
@@ -655,11 +655,6 @@ static struct usb_device_id ncm_ids[] = {
                .name = "cdc-ncm",
                .vendor = USB_ANY_ID,
                .product = USB_ANY_ID,
-               .class = {
-                       .class = USB_CLASS_CDC,
-                       .subclass = USB_SUBCLASS_CDC_NCM,
-                       .protocol = 0,
-               },
        },
 };
 
@@ -667,6 +662,7 @@ static struct usb_device_id ncm_ids[] = {
 struct usb_driver ncm_driver __usb_driver = {
        .ids = ncm_ids,
        .id_count = ( sizeof ( ncm_ids ) / sizeof ( ncm_ids[0] ) ),
+       .class = USB_CLASS_ID ( USB_CLASS_CDC, USB_SUBCLASS_CDC_NCM, 0 ),
        .score = USB_SCORE_NORMAL,
        .probe = ncm_probe,
        .remove = ncm_remove,
index 854329c5ca3500fafbfa599ae8825f3b6de264af..5e4e0e12b8652ca59a485e9ead286509a203eaac 100644 (file)
@@ -1038,13 +1038,11 @@ static struct usb_device_id smsc75xx_ids[] = {
                .name = "smsc7500",
                .vendor = 0x0424,
                .product = 0x7500,
-               .class = { 0xff, 0x00, 0xff },
        },
        {
                .name = "smsc7505",
                .vendor = 0x0424,
                .product = 0x7505,
-               .class = { 0xff, 0x00, 0xff },
        },
 };
 
@@ -1052,6 +1050,7 @@ static struct usb_device_id smsc75xx_ids[] = {
 struct usb_driver smsc75xx_driver __usb_driver = {
        .ids = smsc75xx_ids,
        .id_count = ( sizeof ( smsc75xx_ids ) / sizeof ( smsc75xx_ids[0] ) ),
+       .class = USB_CLASS_ID ( 0xff, 0x00, 0xff ),
        .score = USB_SCORE_NORMAL,
        .probe = smsc75xx_probe,
        .remove = smsc75xx_remove,
index 97d21ef4eefd5c8cd8bd27b2408faa73b81acc96..5cfc405203b9b7b5c06eb334155c0da4108e4469 100644 (file)
@@ -517,24 +517,9 @@ static void hub_remove ( struct usb_function *func ) {
 /** USB hub device IDs */
 static struct usb_device_id hub_ids[] = {
        {
-               .name = "hub-1",
+               .name = "hub",
                .vendor = USB_ANY_ID,
                .product = USB_ANY_ID,
-               .class = {
-                       .class = USB_CLASS_HUB,
-                       .subclass = 0,
-                       .protocol = 0,
-               },
-       },
-       {
-               .name = "hub-2",
-               .vendor = USB_ANY_ID,
-               .product = USB_ANY_ID,
-               .class = {
-                       .class = USB_CLASS_HUB,
-                       .subclass = 0,
-                       .protocol = 1,
-               },
        },
 };
 
@@ -542,6 +527,7 @@ static struct usb_device_id hub_ids[] = {
 struct usb_driver usb_hub_driver __usb_driver = {
        .ids = hub_ids,
        .id_count = ( sizeof ( hub_ids ) / sizeof ( hub_ids[0] ) ),
+       .class = USB_CLASS_ID ( USB_CLASS_HUB, 0, USB_ANY_ID ),
        .score = USB_SCORE_NORMAL,
        .probe = hub_probe,
        .remove = hub_remove,
index 55c61ed4918af4eae60765b55b05cb5f9ced8c2d..153f39421ff20c3ee92a315b8983baa482a52459 100644 (file)
@@ -1316,6 +1316,7 @@ static int usbio_supported ( EFI_HANDLE handle ) {
                       "%s\n", efi_handle_name ( handle ), strerror ( rc ) );
                goto err_get_device_descriptor;
        }
+       memset ( &desc, 0, sizeof ( desc ) );
        desc.vendor = device.IdVendor;
        desc.product = device.IdProduct;
 
@@ -1327,9 +1328,9 @@ static int usbio_supported ( EFI_HANDLE handle ) {
                       "%s\n", efi_handle_name ( handle ), strerror ( rc ) );
                goto err_get_interface_descriptor;
        }
-       desc.class.class = interface.InterfaceClass;
-       desc.class.subclass = interface.InterfaceSubClass;
-       desc.class.protocol = interface.InterfaceProtocol;
+       desc.class.class.class = interface.InterfaceClass;
+       desc.class.class.subclass = interface.InterfaceSubClass;
+       desc.class.class.protocol = interface.InterfaceProtocol;
 
        /* Look for a driver for this interface */
        driver = usb_find_driver ( &desc, &id );
index b134bc78a194bbd932e678ac21139557ef65ad70..512adfe2f10c4bdef115e69713a462a722633137 100644 (file)
@@ -437,11 +437,6 @@ static struct usb_device_id usbkbd_ids[] = {
                .name = "kbd",
                .vendor = USB_ANY_ID,
                .product = USB_ANY_ID,
-               .class = {
-                       .class = USB_CLASS_HID,
-                       .subclass = USB_SUBCLASS_HID_BOOT,
-                       .protocol = USBKBD_PROTOCOL,
-               },
        },
 };
 
@@ -449,6 +444,8 @@ static struct usb_device_id usbkbd_ids[] = {
 struct usb_driver usbkbd_driver __usb_driver = {
        .ids = usbkbd_ids,
        .id_count = ( sizeof ( usbkbd_ids ) / sizeof ( usbkbd_ids[0] ) ),
+       .class = USB_CLASS_ID ( USB_CLASS_HID, USB_SUBCLASS_HID_BOOT,
+                               USBKBD_PROTOCOL ),
        .score = USB_SCORE_NORMAL,
        .probe = usbkbd_probe,
        .remove = usbkbd_remove,
index 8fee00e5614bcaaa7388c2ba52858e59821cee32..b3ce7b7410890a5e57d7c82475f0a3c6020e8838 100644 (file)
@@ -615,6 +615,14 @@ extern int usb_prefill ( struct usb_endpoint *ep );
 extern int usb_refill ( struct usb_endpoint *ep );
 extern void usb_flush ( struct usb_endpoint *ep );
 
+/** A USB class descriptor */
+union usb_class_descriptor {
+       /** Class */
+       struct usb_class class;
+       /** Scalar value */
+       uint32_t scalar;
+};
+
 /**
  * A USB function descriptor
  *
@@ -627,7 +635,7 @@ struct usb_function_descriptor {
        /** Product ID */
        uint16_t product;
        /** Class */
-       struct usb_class class;
+       union usb_class_descriptor class;
        /** Number of interfaces */
        unsigned int count;
 };
@@ -1298,19 +1306,50 @@ struct usb_device_id {
        uint16_t vendor;
        /** Product ID */
        uint16_t product;
-       /** Class */
-       struct usb_class class;
 };
 
 /** Match-anything ID */
 #define USB_ANY_ID 0xffff
 
+/** A USB class ID */
+struct usb_class_id {
+       /** Class */
+       union usb_class_descriptor class;
+       /** Class mask */
+       union usb_class_descriptor mask;
+};
+
+/** Construct USB class ID
+ *
+ * @v base             Base class code (or USB_ANY_ID)
+ * @v subclass         Subclass code (or USB_ANY_ID)
+ * @v protocol         Protocol code (or USB_ANY_ID)
+ */
+#define USB_CLASS_ID( base, subclass, protocol ) {                     \
+       .class = {                                                      \
+               .class = {                                              \
+                       ( (base) & 0xff ),                              \
+                       ( (subclass) & 0xff ),                          \
+                       ( (protocol) & 0xff ),                          \
+               },                                                      \
+       },                                                              \
+       .mask = {                                                       \
+               .class = {                                              \
+                       ( ( (base) == USB_ANY_ID ) ? 0x00 : 0xff ),     \
+                       ( ( (subclass) == USB_ANY_ID ) ? 0x00 : 0xff ), \
+                       ( ( (protocol) == USB_ANY_ID ) ? 0x00 : 0xff ), \
+               },                                                      \
+               },                                                      \
+       }
+
 /** A USB driver */
 struct usb_driver {
        /** USB ID table */
        struct usb_device_id *ids;
        /** Number of entries in ID table */
        unsigned int id_count;
+       /** Class ID */
+       struct usb_class_id class;
        /** Driver score
         *
         * This is used to determine the preferred configuration for a