Переглянути джерело

[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>
tags/v1.20.1
Michael Brown 9 роки тому
джерело
коміт
668dc73d52

+ 15
- 10
src/drivers/bus/usb.c Переглянути файл

@@ -985,6 +985,7 @@ static int usb_describe ( struct usb_device *usb,
985 985
 	unsigned int i;
986 986
 
987 987
 	/* Fill in vendor and product ID */
988
+	memset ( desc, 0, sizeof ( *desc ) );
988 989
 	desc->vendor = le16_to_cpu ( usb->device.vendor );
989 990
 	desc->product = le16_to_cpu ( usb->device.product );
990 991
 
@@ -1023,7 +1024,7 @@ static int usb_describe ( struct usb_device *usb,
1023 1024
 	interfaces[0] = first;
1024 1025
 
1025 1026
 	/* Look for a CDC union descriptor, if applicable */
1026
-	if ( ( desc->class.class == USB_CLASS_CDC ) &&
1027
+	if ( ( desc->class.class.class == USB_CLASS_CDC ) &&
1027 1028
 	     ( cdc_union = cdc_union_descriptor ( config, interface ) ) ) {
1028 1029
 
1029 1030
 		/* Determine interface count */
@@ -1096,15 +1097,17 @@ struct usb_driver * usb_find_driver ( struct usb_function_descriptor *desc,
1096 1097
 	for_each_table_entry ( driver, USB_DRIVERS ) {
1097 1098
 		for ( i = 0 ; i < driver->id_count ; i++ ) {
1098 1099
 
1099
-			/* Check for a matching ID */
1100
+			/* Ignore non-matching driver class */
1101
+			if ( ( driver->class.class.scalar ^ desc->class.scalar )
1102
+			     & driver->class.mask.scalar )
1103
+				continue;
1104
+
1105
+			/* Look for a matching ID */
1100 1106
 			*id = &driver->ids[i];
1101 1107
 			if ( ( ( (*id)->vendor == desc->vendor ) ||
1102 1108
 			       ( (*id)->vendor == USB_ANY_ID ) ) &&
1103 1109
 			     ( ( (*id)->product == desc->product ) ||
1104
-			       ( (*id)->product == USB_ANY_ID ) ) &&
1105
-			     ( (*id)->class.class == desc->class.class ) &&
1106
-			     ( (*id)->class.subclass == desc->class.subclass )&&
1107
-			     ( (*id)->class.protocol == desc->class.protocol ) )
1110
+			       ( (*id)->product == USB_ANY_ID ) ) )
1108 1111
 				return driver;
1109 1112
 		}
1110 1113
 	}
@@ -1178,8 +1181,9 @@ static int usb_probe ( struct usb_function *func,
1178 1181
 	if ( ! driver ) {
1179 1182
 		DBGC ( usb, "USB %s %04x:%04x class %d:%d:%d has no driver\n",
1180 1183
 		       func->name, func->desc.vendor, func->desc.product,
1181
-		       func->desc.class.class, func->desc.class.subclass,
1182
-		       func->desc.class.protocol );
1184
+		       func->desc.class.class.class,
1185
+		       func->desc.class.class.subclass,
1186
+		       func->desc.class.class.protocol );
1183 1187
 		return -ENOENT;
1184 1188
 	}
1185 1189
 
@@ -1265,8 +1269,9 @@ usb_probe_all ( struct usb_device *usb,
1265 1269
 			goto err_probe;
1266 1270
 		DBGC ( usb, "USB %s %04x:%04x class %d:%d:%d interfaces ",
1267 1271
 		       func->name, func->desc.vendor, func->desc.product,
1268
-		       func->desc.class.class, func->desc.class.subclass,
1269
-		       func->desc.class.protocol );
1272
+		       func->desc.class.class.class,
1273
+		       func->desc.class.class.subclass,
1274
+		       func->desc.class.class.protocol );
1270 1275
 		for ( i = 0 ; i < func->desc.count ; i++ )
1271 1276
 			DBGC ( usb, "%s%d", ( i ? "," : "" ),
1272 1277
 			       func->interface[i] );

+ 1
- 0
src/drivers/net/dm96xx.c Переглянути файл

@@ -666,6 +666,7 @@ static struct usb_device_id dm96xx_ids[] = {
666 666
 struct usb_driver dm96xx_driver __usb_driver = {
667 667
 	.ids = dm96xx_ids,
668 668
 	.id_count = ( sizeof ( dm96xx_ids ) / sizeof ( dm96xx_ids[0] ) ),
669
+	.class = USB_CLASS_ID ( USB_ANY_ID, USB_ANY_ID, USB_ANY_ID ),
669 670
 	.score = USB_SCORE_NORMAL,
670 671
 	.probe = dm96xx_probe,
671 672
 	.remove = dm96xx_remove,

+ 1
- 5
src/drivers/net/ecm.c Переглянути файл

@@ -503,11 +503,6 @@ static struct usb_device_id ecm_ids[] = {
503 503
 		.name = "cdc-ecm",
504 504
 		.vendor = USB_ANY_ID,
505 505
 		.product = USB_ANY_ID,
506
-		.class = {
507
-			.class = USB_CLASS_CDC,
508
-			.subclass = USB_SUBCLASS_CDC_ECM,
509
-			.protocol = 0,
510
-		},
511 506
 	},
512 507
 };
513 508
 
@@ -515,6 +510,7 @@ static struct usb_device_id ecm_ids[] = {
515 510
 struct usb_driver ecm_driver __usb_driver = {
516 511
 	.ids = ecm_ids,
517 512
 	.id_count = ( sizeof ( ecm_ids ) / sizeof ( ecm_ids[0] ) ),
513
+	.class = USB_CLASS_ID ( USB_CLASS_CDC, USB_SUBCLASS_CDC_ECM, 0 ),
518 514
 	.score = USB_SCORE_NORMAL,
519 515
 	.probe = ecm_probe,
520 516
 	.remove = ecm_remove,

+ 1
- 5
src/drivers/net/ncm.c Переглянути файл

@@ -655,11 +655,6 @@ static struct usb_device_id ncm_ids[] = {
655 655
 		.name = "cdc-ncm",
656 656
 		.vendor = USB_ANY_ID,
657 657
 		.product = USB_ANY_ID,
658
-		.class = {
659
-			.class = USB_CLASS_CDC,
660
-			.subclass = USB_SUBCLASS_CDC_NCM,
661
-			.protocol = 0,
662
-		},
663 658
 	},
664 659
 };
665 660
 
@@ -667,6 +662,7 @@ static struct usb_device_id ncm_ids[] = {
667 662
 struct usb_driver ncm_driver __usb_driver = {
668 663
 	.ids = ncm_ids,
669 664
 	.id_count = ( sizeof ( ncm_ids ) / sizeof ( ncm_ids[0] ) ),
665
+	.class = USB_CLASS_ID ( USB_CLASS_CDC, USB_SUBCLASS_CDC_NCM, 0 ),
670 666
 	.score = USB_SCORE_NORMAL,
671 667
 	.probe = ncm_probe,
672 668
 	.remove = ncm_remove,

+ 1
- 2
src/drivers/net/smsc75xx.c Переглянути файл

@@ -1038,13 +1038,11 @@ static struct usb_device_id smsc75xx_ids[] = {
1038 1038
 		.name = "smsc7500",
1039 1039
 		.vendor = 0x0424,
1040 1040
 		.product = 0x7500,
1041
-		.class = { 0xff, 0x00, 0xff },
1042 1041
 	},
1043 1042
 	{
1044 1043
 		.name = "smsc7505",
1045 1044
 		.vendor = 0x0424,
1046 1045
 		.product = 0x7505,
1047
-		.class = { 0xff, 0x00, 0xff },
1048 1046
 	},
1049 1047
 };
1050 1048
 
@@ -1052,6 +1050,7 @@ static struct usb_device_id smsc75xx_ids[] = {
1052 1050
 struct usb_driver smsc75xx_driver __usb_driver = {
1053 1051
 	.ids = smsc75xx_ids,
1054 1052
 	.id_count = ( sizeof ( smsc75xx_ids ) / sizeof ( smsc75xx_ids[0] ) ),
1053
+	.class = USB_CLASS_ID ( 0xff, 0x00, 0xff ),
1055 1054
 	.score = USB_SCORE_NORMAL,
1056 1055
 	.probe = smsc75xx_probe,
1057 1056
 	.remove = smsc75xx_remove,

+ 2
- 16
src/drivers/usb/usbhub.c Переглянути файл

@@ -517,24 +517,9 @@ static void hub_remove ( struct usb_function *func ) {
517 517
 /** USB hub device IDs */
518 518
 static struct usb_device_id hub_ids[] = {
519 519
 	{
520
-		.name = "hub-1",
520
+		.name = "hub",
521 521
 		.vendor = USB_ANY_ID,
522 522
 		.product = USB_ANY_ID,
523
-		.class = {
524
-			.class = USB_CLASS_HUB,
525
-			.subclass = 0,
526
-			.protocol = 0,
527
-		},
528
-	},
529
-	{
530
-		.name = "hub-2",
531
-		.vendor = USB_ANY_ID,
532
-		.product = USB_ANY_ID,
533
-		.class = {
534
-			.class = USB_CLASS_HUB,
535
-			.subclass = 0,
536
-			.protocol = 1,
537
-		},
538 523
 	},
539 524
 };
540 525
 
@@ -542,6 +527,7 @@ static struct usb_device_id hub_ids[] = {
542 527
 struct usb_driver usb_hub_driver __usb_driver = {
543 528
 	.ids = hub_ids,
544 529
 	.id_count = ( sizeof ( hub_ids ) / sizeof ( hub_ids[0] ) ),
530
+	.class = USB_CLASS_ID ( USB_CLASS_HUB, 0, USB_ANY_ID ),
545 531
 	.score = USB_SCORE_NORMAL,
546 532
 	.probe = hub_probe,
547 533
 	.remove = hub_remove,

+ 4
- 3
src/drivers/usb/usbio.c Переглянути файл

@@ -1316,6 +1316,7 @@ static int usbio_supported ( EFI_HANDLE handle ) {
1316 1316
 		       "%s\n", efi_handle_name ( handle ), strerror ( rc ) );
1317 1317
 		goto err_get_device_descriptor;
1318 1318
 	}
1319
+	memset ( &desc, 0, sizeof ( desc ) );
1319 1320
 	desc.vendor = device.IdVendor;
1320 1321
 	desc.product = device.IdProduct;
1321 1322
 
@@ -1327,9 +1328,9 @@ static int usbio_supported ( EFI_HANDLE handle ) {
1327 1328
 		       "%s\n", efi_handle_name ( handle ), strerror ( rc ) );
1328 1329
 		goto err_get_interface_descriptor;
1329 1330
 	}
1330
-	desc.class.class = interface.InterfaceClass;
1331
-	desc.class.subclass = interface.InterfaceSubClass;
1332
-	desc.class.protocol = interface.InterfaceProtocol;
1331
+	desc.class.class.class = interface.InterfaceClass;
1332
+	desc.class.class.subclass = interface.InterfaceSubClass;
1333
+	desc.class.class.protocol = interface.InterfaceProtocol;
1333 1334
 
1334 1335
 	/* Look for a driver for this interface */
1335 1336
 	driver = usb_find_driver ( &desc, &id );

+ 2
- 5
src/drivers/usb/usbkbd.c Переглянути файл

@@ -437,11 +437,6 @@ static struct usb_device_id usbkbd_ids[] = {
437 437
 		.name = "kbd",
438 438
 		.vendor = USB_ANY_ID,
439 439
 		.product = USB_ANY_ID,
440
-		.class = {
441
-			.class = USB_CLASS_HID,
442
-			.subclass = USB_SUBCLASS_HID_BOOT,
443
-			.protocol = USBKBD_PROTOCOL,
444
-		},
445 440
 	},
446 441
 };
447 442
 
@@ -449,6 +444,8 @@ static struct usb_device_id usbkbd_ids[] = {
449 444
 struct usb_driver usbkbd_driver __usb_driver = {
450 445
 	.ids = usbkbd_ids,
451 446
 	.id_count = ( sizeof ( usbkbd_ids ) / sizeof ( usbkbd_ids[0] ) ),
447
+	.class = USB_CLASS_ID ( USB_CLASS_HID, USB_SUBCLASS_HID_BOOT,
448
+				USBKBD_PROTOCOL ),
452 449
 	.score = USB_SCORE_NORMAL,
453 450
 	.probe = usbkbd_probe,
454 451
 	.remove = usbkbd_remove,

+ 42
- 3
src/include/ipxe/usb.h Переглянути файл

@@ -615,6 +615,14 @@ extern int usb_prefill ( struct usb_endpoint *ep );
615 615
 extern int usb_refill ( struct usb_endpoint *ep );
616 616
 extern void usb_flush ( struct usb_endpoint *ep );
617 617
 
618
+/** A USB class descriptor */
619
+union usb_class_descriptor {
620
+	/** Class */
621
+	struct usb_class class;
622
+	/** Scalar value */
623
+	uint32_t scalar;
624
+};
625
+
618 626
 /**
619 627
  * A USB function descriptor
620 628
  *
@@ -627,7 +635,7 @@ struct usb_function_descriptor {
627 635
 	/** Product ID */
628 636
 	uint16_t product;
629 637
 	/** Class */
630
-	struct usb_class class;
638
+	union usb_class_descriptor class;
631 639
 	/** Number of interfaces */
632 640
 	unsigned int count;
633 641
 };
@@ -1298,19 +1306,50 @@ struct usb_device_id {
1298 1306
 	uint16_t vendor;
1299 1307
 	/** Product ID */
1300 1308
 	uint16_t product;
1301
-	/** Class */
1302
-	struct usb_class class;
1303 1309
 };
1304 1310
 
1305 1311
 /** Match-anything ID */
1306 1312
 #define USB_ANY_ID 0xffff
1307 1313
 
1314
+/** A USB class ID */
1315
+struct usb_class_id {
1316
+	/** Class */
1317
+	union usb_class_descriptor class;
1318
+	/** Class mask */
1319
+	union usb_class_descriptor mask;
1320
+};
1321
+
1322
+/** Construct USB class ID
1323
+ *
1324
+ * @v base		Base class code (or USB_ANY_ID)
1325
+ * @v subclass		Subclass code (or USB_ANY_ID)
1326
+ * @v protocol		Protocol code (or USB_ANY_ID)
1327
+ */
1328
+#define USB_CLASS_ID( base, subclass, protocol ) {			\
1329
+	.class = {							\
1330
+		.class = {						\
1331
+			( (base) & 0xff ),				\
1332
+			( (subclass) & 0xff ),				\
1333
+			( (protocol) & 0xff ),				\
1334
+		},							\
1335
+	},								\
1336
+	.mask = {							\
1337
+		.class = {						\
1338
+			( ( (base) == USB_ANY_ID ) ? 0x00 : 0xff ),	\
1339
+			( ( (subclass) == USB_ANY_ID ) ? 0x00 : 0xff ),	\
1340
+			( ( (protocol) == USB_ANY_ID ) ? 0x00 : 0xff ),	\
1341
+		},							\
1342
+		},							\
1343
+	}
1344
+
1308 1345
 /** A USB driver */
1309 1346
 struct usb_driver {
1310 1347
 	/** USB ID table */
1311 1348
 	struct usb_device_id *ids;
1312 1349
 	/** Number of entries in ID table */
1313 1350
 	unsigned int id_count;
1351
+	/** Class ID */
1352
+	struct usb_class_id class;
1314 1353
 	/** Driver score
1315 1354
 	 *
1316 1355
 	 * This is used to determine the preferred configuration for a

Завантаження…
Відмінити
Зберегти