1# USB Header script 2# 3# Copyright 2006-2012, Haiku. 4# Distributed under the terms of the MIT License. 5# 6# Authors: 7# John Drinkwater, john@nextraweb.com 8# 9# Use with http://www.linux-usb.org/usb.ids 10# run as: awk -v HEADERFILE=usbhdr.h -f usb-header.awk usb.ids 11 12BEGIN { 13 14 # field separator, defining because user could have overridden 15 FS = " " 16 17 # Pass this in from outside with -v HEADERFILE=filenametouse 18 # we require usbhdr.h for our system 19 ofile = HEADERFILE 20 21 # possibly use this in the future 22 cleanvalues = "[^A-Za-z0-9{}\"'&@?!*.,:;+<> \\t\\/_\\[\\]=#()-]" 23 # ToDo: currently IDs aren't checked, we dumbly assume the source is clean 24 25 inClassesDefinition = 0 26 27 # descriptive output header 28 print "#if 0" > ofile 29 print "#\tUSBHDR.H: USB Vendors, Devices\n#" > ofile 30 print "#\tGenerated by usb-header.awk, source data from the following URI:\n#\thttp://www.linux-usb.org/usb.ids\n#" > ofile 31 print "#\tHeader created on " strftime( "%A, %d %b %Y %H:%M:%S %Z", systime() ) > ofile 32 print "#endif" > ofile 33 34 # and we start with vendors.. 35 print "\ntypedef struct _USB_VENTABLE\n{\n\tunsigned short\tVenId ;\n\tconst char *\tVenName ;\n} USB_VENTABLE, *PUSB_VENTABLE ;\n" > ofile 36 print "USB_VENTABLE\tUsbVenTable [] =\n{" > ofile 37} 38 39# matches vendor - starts with an id as first thing on the line 40# because this occurs first in the header file, we output it without worry 41/^[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]] / { 42 43 if ( vendorcount++ > 0 ) { 44 formatting = ",\n" 45 } else { 46 formatting = "" 47 } 48 49 # store vendor ID for possible devices afterwards 50 vendorid = $1 51 vendor = substr($0, 7) 52 gsub( /\"/, "&&", vendor ) 53 54 # Remove double interrogation points that may be interpreted as trigraphs 55 gsub( /\?\?\?/, "xxx", vendor ) 56 gsub( /\?\?/, "xx", vendor ) 57 58 printf "%s", formatting "\t{ 0x" vendorid ", \"" vendor "\" }" > ofile 59} 60 61# matches device 62/^\t[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]] / { 63 64 device = substr($0, 8) 65 gsub( /\\/, "&&", device ) 66 gsub( /\"/, "&&", device ) 67 68 # Remove double interrogation points that may be interpreted as trigraphs 69 gsub( /\?\?\?/, "xxx", device ) 70 gsub( /\?\?/, "xx", device ) 71 72 # store device ID for possible devices afterwards 73 deviceid = $1 74 devicecount++ 75 devices[devicecount, 1] = vendorid 76 devices[devicecount, 2] = $1 77 devices[devicecount, 3] = device 78} 79 80# match device class - store data for later 81/^C [[:xdigit:]][[:xdigit:]] / { 82 83 class = $2 84 classname = substr($0, 7) 85 gsub( /\"/, "\\\"", classname ) 86 87 inClassesDefinition = 1 88 89 classcount++ 90 classes[classcount, 1] = class 91 classes[classcount, 2] = "00" 92 classes[classcount, 3] = "00" 93 classes[classcount, 4] = classname 94 classes[classcount, 5] = "" 95 classes[classcount, 6] = "" 96} 97 98# match subclass, use device class data captured earlier, and output 99inClassesDefinition && (/^\t[[:xdigit:]][[:xdigit:]] /) { 100 subclass = $1 101 subclassname = substr($0, 6) 102 gsub( /\"/, "\\\"", subclassname ) 103 104 classcount++ 105 classes[classcount, 1] = class 106 classes[classcount, 2] = subclass 107 classes[classcount, 3] = "00" 108 classes[classcount, 4] = classname 109 classes[classcount, 5] = subclassname 110 classes[classcount, 6] = "" 111} 112 113# match protocol 114inClassesDefinition && (/^\t\t[[:xdigit:]][[:xdigit:]] /) { 115 116 protocol = $1 117 protocolname = substr($0, 7) 118 gsub( /\"/, "\\\"", protocolname ) 119 120 classcount++ 121 classes[classcount, 1] = class 122 classes[classcount, 2] = subclass 123 classes[classcount, 3] = protocol 124 classes[classcount, 4] = classname 125 classes[classcount, 5] = subclassname 126 classes[classcount, 6] = protocolname 127} 128 129#match comments 130/^#/ { 131 inClassesDefinition = false 132} 133 134 135# We've processed the file, now output. 136END { 137 138 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 139 140 if ( devicecount > 0 ) { 141 142 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 143 print "USB_DEVTABLE\tUsbDevTable [] =\n{" > ofile 144 for (i = 1; i <= devicecount; i++) { 145 146 if (i != 1) { 147 formatting = ",\n" 148 } else { 149 formatting = "" 150 } 151 printf "%s", formatting "\t{ 0x" devices[i, 1] ", 0x" devices[i, 2] ", \"" devices[i, 3] "\" }" > ofile 152 } 153 print "\n} ;\n\n// Use this value for loop control during searching:\n#define USB_DEVTABLE_LEN (sizeof(UsbDevTable)/sizeof(USB_DEVTABLE))\n" > ofile 154 155 } 156 157 if ( classcount > 0 ) { 158 print "typedef struct _USB_CLASSCODETABLE\n{\n\tunsigned char BaseClass ;\n\tunsigned char SubClass ;\n\tunsigned char Protocol ;" > ofile 159 print "\tconst char *\t\tBaseDesc ;\n\tconst char *\t\tSubDesc ;\n\tconst char *\t\tProtocolDesc ;\n} USB_CLASSCODETABLE, *PUSB_CLASSCODETABLE ;\n" > ofile 160 print "USB_CLASSCODETABLE UsbClassCodeTable [] =\n{" > ofile 161 currentclass = classes[1, 1] 162 for (i = 1; i <= classcount; i++) { 163 164 if (i != 1) { 165 formatting = ",\n" 166 } else { 167 formatting = "" 168 } 169 170 # pretty print separate classes 171 if ( currentclass != classes[i, 1] ) { 172 formatting = formatting "\n" 173 currentclass = classes[i, 1] 174 } 175 176 # if the next item has the same details, we know we're to skip ourselves 177 # this is because the programming interface name needs to be used, and we dont have it ourselves 178 if ( ( classes[i, 1] != classes[i+1, 1] ) || ( classes[i, 2] != classes[i+1, 2] ) || ( classes[i, 3] != classes[i+1, 3] ) ) { 179 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 180 } 181 } 182 print "\n} ;\n\n// Use this value for loop control during searching:\n#define USB_CLASSCODETABLE_LEN (sizeof(UsbClassCodeTable)/sizeof(USB_CLASSCODETABLE))\n" > ofile 183 184 } 185 186 187 close(ofile) 188} 189 190 191