# USB Header script # # Copyright 2006-2012, Haiku. # Distributed under the terms of the MIT License. # # Authors: # John Drinkwater, john@nextraweb.com # # Use with http://www.linux-usb.org/usb.ids # run as: awk -v HEADERFILE=usbhdr.h -f usb-header.awk usb.ids BEGIN { # field separator, defining because user could have overridden FS = " " # Pass this in from outside with -v HEADERFILE=filenametouse # we require usbhdr.h for our system ofile = HEADERFILE # possibly use this in the future 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 print "#\tGenerated by usb-header.awk, source data from the following URI:\n#\thttp://www.linux-usb.org/usb.ids\n#" > ofile print "#\tHeader created on " strftime( "%A, %d %b %Y %H:%M:%S %Z", systime() ) > ofile print "#endif" > ofile # and we start with vendors.. print "\ntypedef struct _USB_VENTABLE\n{\n\tunsigned short\tVenId ;\n\tconst char *\tVenName ;\n} USB_VENTABLE, *PUSB_VENTABLE ;\n" > ofile print "USB_VENTABLE\tUsbVenTable [] =\n{" > ofile } # matches vendor - starts with an id as first thing on the line # because this occurs first in the header file, we output it without worry /^[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]] / { if ( vendorcount++ > 0 ) { formatting = ",\n" } else { formatting = "" } # store vendor ID for possible devices afterwards vendorid = $1 vendor = substr($0, 7) gsub( /\"/, "&&", vendor ) # Remove double interrogation points that may be interpreted as trigraphs gsub( /\?\?\?/, "xxx", vendor ) gsub( /\?\?/, "xx", vendor ) printf "%s", formatting "\t{ 0x" vendorid ", \"" vendor "\" }" > ofile } # matches device /^\t[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]] / { device = substr($0, 8) gsub( /\\/, "&&", device ) gsub( /\"/, "&&", device ) # Remove double interrogation points that may be interpreted as trigraphs gsub( /\?\?\?/, "xxx", device ) gsub( /\?\?/, "xx", device ) # store device ID for possible devices afterwards deviceid = $1 devicecount++ devices[devicecount, 1] = vendorid devices[devicecount, 2] = $1 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 { print "\n};\n\n// Use this value for loop control during searching:\n#define\tUSB_VENTABLE_LEN\t(sizeof(UsbVenTable)/sizeof(USB_VENTABLE))\n" > ofile if ( devicecount > 0 ) { print "typedef struct _USB_DEVTABLE\n{\n\tunsigned short VenId ;\n\tunsigned short DevId ;\n\tconst char *\tChipDesc ;\n} USB_DEVTABLE, *PUSB_DEVTABLE ;\n" > ofile print "USB_DEVTABLE\tUsbDevTable [] =\n{" > ofile for (i = 1; i <= devicecount; i++) { if (i != 1) { formatting = ",\n" } else { formatting = "" } printf "%s", formatting "\t{ 0x" devices[i, 1] ", 0x" devices[i, 2] ", \"" devices[i, 3] "\" }" > ofile } print "\n} ;\n\n// Use this value for loop control during searching:\n#define USB_DEVTABLE_LEN (sizeof(UsbDevTable)/sizeof(USB_DEVTABLE))\n" > ofile } 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) }