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