From edeaa9c0c75c09964afedce16e04bc1359798665 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Mon, 10 Oct 2022 20:00:59 +0200 Subject: [PATCH] listusb: generate class code table from usb.ids, and use it Change-Id: I43b79c5abc74306aba9a69991aeb5e110b2d790b Reviewed-on: https://review.haiku-os.org/c/haiku/+/5737 Reviewed-by: Fredrik Holmqvist --- headers/private/shared/usb-utils.h | 24 ++++ src/apps/devices/usb-header.awk | 87 +++++++++++++ src/bin/listusb/listusb.cpp | 196 +++-------------------------- 3 files changed, 127 insertions(+), 180 deletions(-) diff --git a/headers/private/shared/usb-utils.h b/headers/private/shared/usb-utils.h index 4ce85ea259..78a7740104 100644 --- a/headers/private/shared/usb-utils.h +++ b/headers/private/shared/usb-utils.h @@ -12,6 +12,30 @@ #include "usbhdr.h" +static void +usb_get_class_info(uint8 usb_class_base_id, uint8 usb_class_sub_id, uint8 usb_class_proto_id, + char *classInfo, size_t size) +{ + USB_CLASSCODETABLE *foundItem = NULL; + int i; + for (i = 0; i < (int)USB_CLASSCODETABLE_LEN; i++) { + if ((usb_class_base_id == UsbClassCodeTable[i].BaseClass) + && (usb_class_sub_id == UsbClassCodeTable[i].SubClass)) { + foundItem = &UsbClassCodeTable[i]; + if (usb_class_proto_id == UsbClassCodeTable[i].Protocol) + break; + } + } + if (foundItem) { + snprintf(classInfo, size, "%s (%s%s%s)", foundItem->BaseDesc, foundItem->SubDesc, + (foundItem->ProtocolDesc && strcmp("", foundItem->ProtocolDesc)) ? ", " : "", + foundItem->ProtocolDesc); + } else + snprintf(classInfo, size, "%s (%u:%u:%u)", "(Unknown)", + usb_class_base_id, usb_class_sub_id, usb_class_proto_id); +} + + void usb_get_vendor_info(uint16 vendorID, const char **vendorName) { diff --git a/src/apps/devices/usb-header.awk b/src/apps/devices/usb-header.awk index 84e0d08064..810ecbcff9 100644 --- a/src/apps/devices/usb-header.awk +++ b/src/apps/devices/usb-header.awk @@ -22,6 +22,8 @@ BEGIN { cleanvalues = "[^A-Za-z0-9{}\"'&@?!*.,:;+<> \\t\\/_\\[\\]=#()-]" # ToDo: currently IDs aren't checked, we dumbly assume the source is clean + inClassesDefinition = 0 + # descriptive output header print "#if 0" > ofile print "#\tUSBHDR.H: USB Vendors, Devices\n#" > ofile @@ -67,6 +69,61 @@ BEGIN { devices[devicecount, 3] = device } +# match device class - store data for later +/^C [[:xdigit:]][[:xdigit:]] / { + + class = $2 + classname = substr($0, 7) + gsub( /\"/, "\\\"", classname ) + + inClassesDefinition = 1 + + classcount++ + classes[classcount, 1] = class + classes[classcount, 2] = "00" + classes[classcount, 3] = "00" + classes[classcount, 4] = classname + classes[classcount, 5] = "" + classes[classcount, 6] = "" +} + +# match subclass, use device class data captured earlier, and output +inClassesDefinition && (/^\t[[:xdigit:]][[:xdigit:]] /) { + subclass = $1 + subclassname = substr($0, 6) + gsub( /\"/, "\\\"", subclassname ) + + classcount++ + classes[classcount, 1] = class + classes[classcount, 2] = subclass + classes[classcount, 3] = "00" + classes[classcount, 4] = classname + classes[classcount, 5] = subclassname + classes[classcount, 6] = "" +} + +# match protocol +inClassesDefinition && (/^\t\t[[:xdigit:]][[:xdigit:]] /) { + + protocol = $1 + protocolname = substr($0, 7) + gsub( /\"/, "\\\"", protocolname ) + + classcount++ + classes[classcount, 1] = class + classes[classcount, 2] = subclass + classes[classcount, 3] = protocol + classes[classcount, 4] = classname + classes[classcount, 5] = subclassname + classes[classcount, 6] = protocolname +} + +#match comments +/^#/ { + inClassesDefinition = false +} + + # We've processed the file, now output. END { @@ -89,6 +146,36 @@ END { } + if ( classcount > 0 ) { + print "typedef struct _USB_CLASSCODETABLE\n{\n\tunsigned char BaseClass ;\n\tunsigned char SubClass ;\n\tunsigned char Protocol ;" > ofile + print "\tconst char *\t\tBaseDesc ;\n\tconst char *\t\tSubDesc ;\n\tconst char *\t\tProtocolDesc ;\n} USB_CLASSCODETABLE, *PUSB_CLASSCODETABLE ;\n" > ofile + print "USB_CLASSCODETABLE UsbClassCodeTable [] =\n{" > ofile + currentclass = classes[1, 1] + for (i = 1; i <= classcount; i++) { + + if (i != 1) { + formatting = ",\n" + } else { + formatting = "" + } + + # pretty print separate classes + if ( currentclass != classes[i, 1] ) { + formatting = formatting "\n" + currentclass = classes[i, 1] + } + + # if the next item has the same details, we know we're to skip ourselves + # this is because the programming interface name needs to be used, and we dont have it ourselves + if ( ( classes[i, 1] != classes[i+1, 1] ) || ( classes[i, 2] != classes[i+1, 2] ) || ( classes[i, 3] != classes[i+1, 3] ) ) { + printf formatting "\t{ 0x" classes[i, 1] ", 0x" classes[i, 2] ", 0x" classes[i, 3] ", \"" classes[i, 4] "\", \"" classes[i, 5] "\", \"" classes[i, 6] "\" }" > ofile + } + } + print "\n} ;\n\n// Use this value for loop control during searching:\n#define USB_CLASSCODETABLE_LEN (sizeof(UsbClassCodeTable)/sizeof(USB_CLASSCODETABLE))\n" > ofile + + } + + close(ofile) } diff --git a/src/bin/listusb/listusb.cpp b/src/bin/listusb/listusb.cpp index 29b7840591..da770826b4 100644 --- a/src/bin/listusb/listusb.cpp +++ b/src/bin/listusb/listusb.cpp @@ -21,175 +21,6 @@ #include "listusb.h" -const char* -ClassName(int classNumber) { - switch (classNumber) { - case 0: - return "Per-interface classes"; - case USB_AUDIO_DEVICE_CLASS: - return "Audio"; - case 2: - return "Communication"; - case 3: - return "HID"; - case 5: - return "Physical"; - case 6: - return "Image"; - case 7: - return "Printer"; - case 8: - return "Mass storage"; - case 9: - return "Hub"; - case 10: - return "CDC-Data"; - case 11: - return "Smart card"; - case 13: - return "Content security"; - case USB_VIDEO_DEVICE_CLASS: - return "Video"; - case 15: - return "Personal Healthcare"; - case 0xDC: - return "Diagnostic device"; - case 0xE0: - return "Wireless controller"; - case 0xEF: - return "Miscellaneous"; - case 0xFE: - return "Application specific"; - case 0xFF: - return "Vendor specific"; - } - - return "Unknown"; -} - - -const char* -SubclassName(int classNumber, int subclass) -{ - if (classNumber == 0xEF) { - if (subclass == 0x02) - return " (Common)"; - if (subclass == 0x04) - return " (RNDIS)"; - if (subclass == 0x05) - return " (USB3 Vision)"; - if (subclass == 0x06) - return " (STEP)"; - if (subclass == 0x07) - return " (DVB Command Interface)"; - } - - if (classNumber == USB_VIDEO_DEVICE_CLASS) { - switch (subclass) { - case USB_VIDEO_INTERFACE_UNDEFINED_SUBCLASS: - return " (Undefined)"; - case USB_VIDEO_INTERFACE_VIDEOCONTROL_SUBCLASS: - return " (Control)"; - case USB_VIDEO_INTERFACE_VIDEOSTREAMING_SUBCLASS: - return " (Streaming)"; - case USB_VIDEO_INTERFACE_COLLECTION_SUBCLASS: - return " (Collection)"; - } - } - - if (classNumber == 0xFE) { - if (subclass == 0x01) - return " (Firmware Upgrade)"; - if (subclass == 0x02) - return " (IrDA)"; - if (subclass == 0x03) - return " (Test and measurement)"; - } - - return ""; -} - - -const char* -ProtocolName(int classNumber, int subclass, int protocol) -{ - switch (classNumber) { - case 0x09: - if (subclass == 0x00) - { - switch (protocol) { - case 0x00: - return " (Full speed)"; - case 0x01: - return " (Hi-speed, single TT)"; - case 0x02: - return " (Hi-speed, multiple TT)"; - case 0x03: - return " (Super speed)"; - } - } - case 0xE0: - if (subclass == 0x01 && protocol == 0x01) - return " (Bluetooth control)"; - if (subclass == 0x01 && protocol == 0x02) - return " (UWB Radio)"; - if (subclass == 0x01 && protocol == 0x03) - return " (RNDIS control)"; - if (subclass == 0x01 && protocol == 0x04) - return " (Bluetooth AMP)"; - if (subclass == 0x02 && protocol == 0x01) - return " (Host wire adapter)"; - if (subclass == 0x02 && protocol == 0x02) - return " (Device wire adapter)"; - if (subclass == 0x02 && protocol == 0x03) - return " (Device wire isochronous)"; - case 0xEF: - if (subclass == 0x01 && protocol == 0x01) - return " (Microsoft Active Sync)"; - if (subclass == 0x01 && protocol == 0x02) - return " (Palm Sync)"; - if (subclass == 0x02 && protocol == 0x01) - return " (Interface Association)"; - if (subclass == 0x02 && protocol == 0x02) - return " (Wire adapter multifunction peripheral)"; - if (subclass == 0x03 && protocol == 0x01) - return " (Cable based association framework)"; - if (subclass == 0x04 && protocol == 0x01) - return " (RNDIS Ethernet)"; - if (subclass == 0x04 && protocol == 0x02) - return " (RNDIS Wifi)"; - if (subclass == 0x04 && protocol == 0x03) - return " (RNDIS WiMAX)"; - if (subclass == 0x04 && protocol == 0x04) - return " (RNDIS WWAN)"; - if (subclass == 0x04 && protocol == 0x05) - return " (RNDIS raw IPv4)"; - if (subclass == 0x04 && protocol == 0x06) - return " (RNDIS raw IPv6)"; - if (subclass == 0x04 && protocol == 0x07) - return " (RNDIS GPRS)"; - if (subclass == 0x05 && protocol == 0x00) - return " (USB3 vision control)"; - if (subclass == 0x05 && protocol == 0x01) - return " (USB3 vision event)"; - if (subclass == 0x05 && protocol == 0x02) - return " (USB3 vision streaming)"; - if (subclass == 0x06 && protocol == 0x01) - return " (STEP)"; - if (subclass == 0x06 && protocol == 0x02) - return " (STEP RAW)"; - if (subclass == 0x07 && protocol == 0x01) - return " (DVB Command Interface in IAD)"; - if (subclass == 0x07 && protocol == 0x02) - return " (DVB Command Interface in interface descriptor)"; - if (subclass == 0x07 && protocol == 0x03) - return " (Media interface in interface descriptor)"; - break; - } - return ""; -} - - void DumpCDCDescriptor(const usb_generic_descriptor* descriptor, int subclass) { @@ -400,14 +231,17 @@ DumpInterface(const BUSBInterface* interface) if (!interface) return; + char classInfo[128]; + usb_get_class_info(interface->Class(), 0, 0, classInfo, sizeof(classInfo)); printf(" Class .............. 0x%02x (%s)\n", - interface->Class(), ClassName(interface->Class())); + interface->Class(), classInfo); + usb_get_class_info(interface->Class(), interface->Subclass(), 0, classInfo, sizeof(classInfo)); printf(" Subclass ........... 0x%02x%s\n", - interface->Subclass(), - SubclassName(interface->Class(), interface->Subclass())); + interface->Subclass(), classInfo); + usb_get_class_info(interface->Class(), interface->Subclass(), interface->Protocol(), classInfo, + sizeof(classInfo)); printf(" Protocol ........... 0x%02x%s\n", - interface->Protocol(), ProtocolName(interface->Class(), - interface->Subclass(), interface->Protocol())); + interface->Protocol(), classInfo); printf(" Interface String ... \"%s\"\n", interface->InterfaceString()); @@ -486,13 +320,15 @@ DumpInfo(BUSBDevice& device, bool verbose) return; } + char classInfo[128]; printf("[Device /dev/bus/usb%s]\n", device.Location()); - printf(" Class .................. 0x%02x (%s)\n", device.Class(), - ClassName(device.Class())); - printf(" Subclass ............... 0x%02x%s\n", device.Subclass(), - SubclassName(device.Class(), device.Subclass())); - printf(" Protocol ............... 0x%02x%s\n", device.Protocol(), - ProtocolName(device.Class(), device.Subclass(), device.Protocol())); + usb_get_class_info(device.Class(), 0, 0, classInfo, sizeof(classInfo)); + printf(" Class .................. 0x%02x (%s)\n", device.Class(), classInfo); + usb_get_class_info(device.Class(), device.Subclass(), 0, classInfo, sizeof(classInfo)); + printf(" Subclass ............... 0x%02x%s\n", device.Subclass(), classInfo); + usb_get_class_info(device.Class(), device.Subclass(), device.Protocol(), classInfo, + sizeof(classInfo)); + printf(" Protocol ............... 0x%02x%s\n", device.Protocol(), classInfo); printf(" Max Endpoint 0 Packet .. %d\n", device.MaxEndpoint0PacketSize()); uint32_t version = device.USBVersion(); printf(" USB Version ............ %d.%d\n", version >> 8, version & 0xFF);