diff options
author | Michael Brown <mcb30@ipxe.org> | 2015-09-14 17:52:25 +0100 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2015-09-14 21:56:40 +0100 |
commit | 668dc73d526fa67957b9c10100f9ca5f2ab60522 (patch) | |
tree | cf6887506d5ac016fd04497cbd568463292903de /src | |
parent | 549a0caabb2f239fc702ccea3c1825518e13d121 (diff) | |
download | ipxe-668dc73d526fa67957b9c10100f9ca5f2ab60522.tar.gz |
[usb] Allow for wildcard USB class IDs
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>
Diffstat (limited to 'src')
-rw-r--r-- | src/drivers/bus/usb.c | 25 | ||||
-rw-r--r-- | src/drivers/net/dm96xx.c | 1 | ||||
-rw-r--r-- | src/drivers/net/ecm.c | 6 | ||||
-rw-r--r-- | src/drivers/net/ncm.c | 6 | ||||
-rw-r--r-- | src/drivers/net/smsc75xx.c | 3 | ||||
-rw-r--r-- | src/drivers/usb/usbhub.c | 18 | ||||
-rw-r--r-- | src/drivers/usb/usbio.c | 7 | ||||
-rw-r--r-- | src/drivers/usb/usbkbd.c | 7 | ||||
-rw-r--r-- | src/include/ipxe/usb.h | 45 |
9 files changed, 69 insertions, 49 deletions
diff --git a/src/drivers/bus/usb.c b/src/drivers/bus/usb.c index d8d7f6b37..63a7e46a6 100644 --- a/src/drivers/bus/usb.c +++ b/src/drivers/bus/usb.c @@ -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] ); diff --git a/src/drivers/net/dm96xx.c b/src/drivers/net/dm96xx.c index b4eff50ab..817a84a29 100644 --- a/src/drivers/net/dm96xx.c +++ b/src/drivers/net/dm96xx.c @@ -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, diff --git a/src/drivers/net/ecm.c b/src/drivers/net/ecm.c index f24a435a5..371611d54 100644 --- a/src/drivers/net/ecm.c +++ b/src/drivers/net/ecm.c @@ -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, diff --git a/src/drivers/net/ncm.c b/src/drivers/net/ncm.c index 3c3ab90f1..afa794ea3 100644 --- a/src/drivers/net/ncm.c +++ b/src/drivers/net/ncm.c @@ -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, diff --git a/src/drivers/net/smsc75xx.c b/src/drivers/net/smsc75xx.c index 854329c5c..5e4e0e12b 100644 --- a/src/drivers/net/smsc75xx.c +++ b/src/drivers/net/smsc75xx.c @@ -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, diff --git a/src/drivers/usb/usbhub.c b/src/drivers/usb/usbhub.c index 97d21ef4e..5cfc40520 100644 --- a/src/drivers/usb/usbhub.c +++ b/src/drivers/usb/usbhub.c @@ -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, diff --git a/src/drivers/usb/usbio.c b/src/drivers/usb/usbio.c index 55c61ed49..153f39421 100644 --- a/src/drivers/usb/usbio.c +++ b/src/drivers/usb/usbio.c @@ -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 ); diff --git a/src/drivers/usb/usbkbd.c b/src/drivers/usb/usbkbd.c index b134bc78a..512adfe2f 100644 --- a/src/drivers/usb/usbkbd.c +++ b/src/drivers/usb/usbkbd.c @@ -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, diff --git a/src/include/ipxe/usb.h b/src/include/ipxe/usb.h index 8fee00e56..b3ce7b741 100644 --- a/src/include/ipxe/usb.h +++ b/src/include/ipxe/usb.h @@ -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 |