14ea3e0d3SJérôme Duval# USB Header script 24ea3e0d3SJérôme Duval# 34ea3e0d3SJérôme Duval# Copyright 2006-2012, Haiku. 44ea3e0d3SJérôme Duval# Distributed under the terms of the MIT License. 54ea3e0d3SJérôme Duval# 64ea3e0d3SJérôme Duval# Authors: 74ea3e0d3SJérôme Duval# John Drinkwater, john@nextraweb.com 84ea3e0d3SJérôme Duval# 94ea3e0d3SJérôme Duval# Use with http://www.linux-usb.org/usb.ids 104ea3e0d3SJérôme Duval# run as: awk -v HEADERFILE=usbhdr.h -f usb-header.awk usb.ids 114ea3e0d3SJérôme Duval 124ea3e0d3SJérôme DuvalBEGIN { 134ea3e0d3SJérôme Duval 144ea3e0d3SJérôme Duval # field separator, defining because user could have overridden 154ea3e0d3SJérôme Duval FS = " " 164ea3e0d3SJérôme Duval 174ea3e0d3SJérôme Duval # Pass this in from outside with -v HEADERFILE=filenametouse 184ea3e0d3SJérôme Duval # we require usbhdr.h for our system 194ea3e0d3SJérôme Duval ofile = HEADERFILE 204ea3e0d3SJérôme Duval 214ea3e0d3SJérôme Duval # possibly use this in the future 224ea3e0d3SJérôme Duval cleanvalues = "[^A-Za-z0-9{}\"'&@?!*.,:;+<> \\t\\/_\\[\\]=#()-]" 234ea3e0d3SJérôme Duval # ToDo: currently IDs aren't checked, we dumbly assume the source is clean 244ea3e0d3SJérôme Duval 25edeaa9c0SJérôme Duval inClassesDefinition = 0 26edeaa9c0SJérôme Duval 274ea3e0d3SJérôme Duval # descriptive output header 284ea3e0d3SJérôme Duval print "#if 0" > ofile 294ea3e0d3SJérôme Duval print "#\tUSBHDR.H: USB Vendors, Devices\n#" > ofile 304ea3e0d3SJérôme Duval print "#\tGenerated by usb-header.awk, source data from the following URI:\n#\thttp://www.linux-usb.org/usb.ids\n#" > ofile 314ea3e0d3SJérôme Duval print "#\tHeader created on " strftime( "%A, %d %b %Y %H:%M:%S %Z", systime() ) > ofile 324ea3e0d3SJérôme Duval print "#endif" > ofile 334ea3e0d3SJérôme Duval 344ea3e0d3SJérôme Duval # and we start with vendors.. 354ea3e0d3SJérôme Duval print "\ntypedef struct _USB_VENTABLE\n{\n\tunsigned short\tVenId ;\n\tconst char *\tVenName ;\n} USB_VENTABLE, *PUSB_VENTABLE ;\n" > ofile 364ea3e0d3SJérôme Duval print "USB_VENTABLE\tUsbVenTable [] =\n{" > ofile 374ea3e0d3SJérôme Duval} 384ea3e0d3SJérôme Duval 394ea3e0d3SJérôme Duval# matches vendor - starts with an id as first thing on the line 404ea3e0d3SJérôme Duval# because this occurs first in the header file, we output it without worry 414ea3e0d3SJérôme Duval/^[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]] / { 424ea3e0d3SJérôme Duval 434ea3e0d3SJérôme Duval if ( vendorcount++ > 0 ) { 444ea3e0d3SJérôme Duval formatting = ",\n" 454ea3e0d3SJérôme Duval } else { 464ea3e0d3SJérôme Duval formatting = "" 474ea3e0d3SJérôme Duval } 484ea3e0d3SJérôme Duval 494ea3e0d3SJérôme Duval # store vendor ID for possible devices afterwards 504ea3e0d3SJérôme Duval vendorid = $1 514ea3e0d3SJérôme Duval vendor = substr($0, 7) 5224502382SJérôme Duval gsub( /\"/, "&&", vendor ) 534ea3e0d3SJérôme Duval 54*c75dc6afSPulkoMandy # Remove double interrogation points that may be interpreted as trigraphs 55*c75dc6afSPulkoMandy gsub( /\?\?\?/, "xxx", vendor ) 56*c75dc6afSPulkoMandy gsub( /\?\?/, "xx", vendor ) 57*c75dc6afSPulkoMandy 58d7a4a01fSJérôme Duval printf "%s", formatting "\t{ 0x" vendorid ", \"" vendor "\" }" > ofile 594ea3e0d3SJérôme Duval} 604ea3e0d3SJérôme Duval 614ea3e0d3SJérôme Duval# matches device 624ea3e0d3SJérôme Duval/^\t[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]] / { 634ea3e0d3SJérôme Duval 644ea3e0d3SJérôme Duval device = substr($0, 8) 6524502382SJérôme Duval gsub( /\\/, "&&", device ) 6624502382SJérôme Duval gsub( /\"/, "&&", device ) 674ea3e0d3SJérôme Duval 68*c75dc6afSPulkoMandy # Remove double interrogation points that may be interpreted as trigraphs 69*c75dc6afSPulkoMandy gsub( /\?\?\?/, "xxx", device ) 70*c75dc6afSPulkoMandy gsub( /\?\?/, "xx", device ) 71*c75dc6afSPulkoMandy 724ea3e0d3SJérôme Duval # store device ID for possible devices afterwards 734ea3e0d3SJérôme Duval deviceid = $1 744ea3e0d3SJérôme Duval devicecount++ 754ea3e0d3SJérôme Duval devices[devicecount, 1] = vendorid 764ea3e0d3SJérôme Duval devices[devicecount, 2] = $1 774ea3e0d3SJérôme Duval devices[devicecount, 3] = device 784ea3e0d3SJérôme Duval} 794ea3e0d3SJérôme Duval 80edeaa9c0SJérôme Duval# match device class - store data for later 81edeaa9c0SJérôme Duval/^C [[:xdigit:]][[:xdigit:]] / { 82edeaa9c0SJérôme Duval 83edeaa9c0SJérôme Duval class = $2 84edeaa9c0SJérôme Duval classname = substr($0, 7) 85edeaa9c0SJérôme Duval gsub( /\"/, "\\\"", classname ) 86edeaa9c0SJérôme Duval 87edeaa9c0SJérôme Duval inClassesDefinition = 1 88edeaa9c0SJérôme Duval 89edeaa9c0SJérôme Duval classcount++ 90edeaa9c0SJérôme Duval classes[classcount, 1] = class 91edeaa9c0SJérôme Duval classes[classcount, 2] = "00" 92edeaa9c0SJérôme Duval classes[classcount, 3] = "00" 93edeaa9c0SJérôme Duval classes[classcount, 4] = classname 94edeaa9c0SJérôme Duval classes[classcount, 5] = "" 95edeaa9c0SJérôme Duval classes[classcount, 6] = "" 96edeaa9c0SJérôme Duval} 97edeaa9c0SJérôme Duval 98edeaa9c0SJérôme Duval# match subclass, use device class data captured earlier, and output 99edeaa9c0SJérôme DuvalinClassesDefinition && (/^\t[[:xdigit:]][[:xdigit:]] /) { 100edeaa9c0SJérôme Duval subclass = $1 101edeaa9c0SJérôme Duval subclassname = substr($0, 6) 102edeaa9c0SJérôme Duval gsub( /\"/, "\\\"", subclassname ) 103edeaa9c0SJérôme Duval 104edeaa9c0SJérôme Duval classcount++ 105edeaa9c0SJérôme Duval classes[classcount, 1] = class 106edeaa9c0SJérôme Duval classes[classcount, 2] = subclass 107edeaa9c0SJérôme Duval classes[classcount, 3] = "00" 108edeaa9c0SJérôme Duval classes[classcount, 4] = classname 109edeaa9c0SJérôme Duval classes[classcount, 5] = subclassname 110edeaa9c0SJérôme Duval classes[classcount, 6] = "" 111edeaa9c0SJérôme Duval} 112edeaa9c0SJérôme Duval 113edeaa9c0SJérôme Duval# match protocol 114edeaa9c0SJérôme DuvalinClassesDefinition && (/^\t\t[[:xdigit:]][[:xdigit:]] /) { 115edeaa9c0SJérôme Duval 116edeaa9c0SJérôme Duval protocol = $1 117edeaa9c0SJérôme Duval protocolname = substr($0, 7) 118edeaa9c0SJérôme Duval gsub( /\"/, "\\\"", protocolname ) 119edeaa9c0SJérôme Duval 120edeaa9c0SJérôme Duval classcount++ 121edeaa9c0SJérôme Duval classes[classcount, 1] = class 122edeaa9c0SJérôme Duval classes[classcount, 2] = subclass 123edeaa9c0SJérôme Duval classes[classcount, 3] = protocol 124edeaa9c0SJérôme Duval classes[classcount, 4] = classname 125edeaa9c0SJérôme Duval classes[classcount, 5] = subclassname 126edeaa9c0SJérôme Duval classes[classcount, 6] = protocolname 127edeaa9c0SJérôme Duval} 128edeaa9c0SJérôme Duval 129edeaa9c0SJérôme Duval#match comments 130edeaa9c0SJérôme Duval/^#/ { 131edeaa9c0SJérôme Duval inClassesDefinition = false 132edeaa9c0SJérôme Duval} 133edeaa9c0SJérôme Duval 134edeaa9c0SJérôme Duval 1354ea3e0d3SJérôme Duval# We've processed the file, now output. 1364ea3e0d3SJérôme DuvalEND { 1374ea3e0d3SJérôme Duval 1384ea3e0d3SJérôme Duval 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 1394ea3e0d3SJérôme Duval 1404ea3e0d3SJérôme Duval if ( devicecount > 0 ) { 1414ea3e0d3SJérôme Duval 1424ea3e0d3SJérôme Duval 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 1434ea3e0d3SJérôme Duval print "USB_DEVTABLE\tUsbDevTable [] =\n{" > ofile 1444ea3e0d3SJérôme Duval for (i = 1; i <= devicecount; i++) { 1454ea3e0d3SJérôme Duval 1464ea3e0d3SJérôme Duval if (i != 1) { 1474ea3e0d3SJérôme Duval formatting = ",\n" 1484ea3e0d3SJérôme Duval } else { 1494ea3e0d3SJérôme Duval formatting = "" 1504ea3e0d3SJérôme Duval } 151d7a4a01fSJérôme Duval printf "%s", formatting "\t{ 0x" devices[i, 1] ", 0x" devices[i, 2] ", \"" devices[i, 3] "\" }" > ofile 1524ea3e0d3SJérôme Duval } 1534ea3e0d3SJérôme Duval print "\n} ;\n\n// Use this value for loop control during searching:\n#define USB_DEVTABLE_LEN (sizeof(UsbDevTable)/sizeof(USB_DEVTABLE))\n" > ofile 1544ea3e0d3SJérôme Duval 1554ea3e0d3SJérôme Duval } 1564ea3e0d3SJérôme Duval 157edeaa9c0SJérôme Duval if ( classcount > 0 ) { 158edeaa9c0SJérôme Duval print "typedef struct _USB_CLASSCODETABLE\n{\n\tunsigned char BaseClass ;\n\tunsigned char SubClass ;\n\tunsigned char Protocol ;" > ofile 159edeaa9c0SJérôme Duval print "\tconst char *\t\tBaseDesc ;\n\tconst char *\t\tSubDesc ;\n\tconst char *\t\tProtocolDesc ;\n} USB_CLASSCODETABLE, *PUSB_CLASSCODETABLE ;\n" > ofile 160edeaa9c0SJérôme Duval print "USB_CLASSCODETABLE UsbClassCodeTable [] =\n{" > ofile 161edeaa9c0SJérôme Duval currentclass = classes[1, 1] 162edeaa9c0SJérôme Duval for (i = 1; i <= classcount; i++) { 163edeaa9c0SJérôme Duval 164edeaa9c0SJérôme Duval if (i != 1) { 165edeaa9c0SJérôme Duval formatting = ",\n" 166edeaa9c0SJérôme Duval } else { 167edeaa9c0SJérôme Duval formatting = "" 168edeaa9c0SJérôme Duval } 169edeaa9c0SJérôme Duval 170edeaa9c0SJérôme Duval # pretty print separate classes 171edeaa9c0SJérôme Duval if ( currentclass != classes[i, 1] ) { 172edeaa9c0SJérôme Duval formatting = formatting "\n" 173edeaa9c0SJérôme Duval currentclass = classes[i, 1] 174edeaa9c0SJérôme Duval } 175edeaa9c0SJérôme Duval 176edeaa9c0SJérôme Duval # if the next item has the same details, we know we're to skip ourselves 177edeaa9c0SJérôme Duval # this is because the programming interface name needs to be used, and we dont have it ourselves 178edeaa9c0SJérôme Duval if ( ( classes[i, 1] != classes[i+1, 1] ) || ( classes[i, 2] != classes[i+1, 2] ) || ( classes[i, 3] != classes[i+1, 3] ) ) { 179edeaa9c0SJérôme Duval 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 180edeaa9c0SJérôme Duval } 181edeaa9c0SJérôme Duval } 182edeaa9c0SJérôme Duval print "\n} ;\n\n// Use this value for loop control during searching:\n#define USB_CLASSCODETABLE_LEN (sizeof(UsbClassCodeTable)/sizeof(USB_CLASSCODETABLE))\n" > ofile 183edeaa9c0SJérôme Duval 184edeaa9c0SJérôme Duval } 185edeaa9c0SJérôme Duval 186edeaa9c0SJérôme Duval 1874ea3e0d3SJérôme Duval close(ofile) 1884ea3e0d3SJérôme Duval} 1894ea3e0d3SJérôme Duval 1904ea3e0d3SJérôme Duval 191