]>
Commit | Line | Data |
---|---|---|
a6316ce4 MT |
1 | #! /usr/bin/perl |
2 | ||
3 | use Getopt::Long; | |
4 | use XML::Writer; | |
5 | use XML::Parser; | |
6 | use IO; | |
7 | use Dumpvalue; | |
8 | ||
9 | sub help; | |
10 | ||
11 | sub read_name_file; | |
12 | sub read_driver_file; | |
13 | sub read_id_file; | |
14 | sub read_pcimap_file; | |
15 | sub read_usbmap_file; | |
16 | sub read_alias_file; | |
17 | sub read_modinfo_file; | |
18 | sub eisa_id; | |
19 | sub eisa_str; | |
20 | ||
21 | sub remove_nops; | |
22 | sub remove_duplicates; | |
23 | sub fix_driver_info; | |
24 | ||
25 | sub cmp_id; | |
26 | sub cmp_skey; | |
27 | sub cmp_item; | |
28 | ||
29 | sub match_id; | |
30 | sub match_skey; | |
31 | sub match_item; | |
32 | ||
33 | sub join_skey; | |
34 | ||
35 | sub split_item; | |
36 | ||
37 | sub get_xml_data; | |
38 | sub parse_xml_item; | |
39 | sub parse_xml_key; | |
40 | sub parse_xml_id; | |
41 | sub parse_xml_id_id; | |
42 | sub parse_xml_id_range; | |
43 | sub parse_xml_id_mask; | |
44 | sub parse_xml_driver; | |
45 | sub parse_xml_driver_display; | |
46 | sub parse_xml_driver_module; | |
47 | sub parse_xml_driver_mouse; | |
48 | sub parse_xml_driver_xfree; | |
49 | sub parse_xml_pair; | |
50 | sub parse_xml_cdata; | |
51 | sub idstr2value; | |
52 | ||
53 | sub dump2ids; | |
54 | sub dump2xml; | |
55 | sub dump_xml_item; | |
56 | sub dump_xml_names; | |
57 | sub dump_xml_drivers; | |
58 | sub id2xml; | |
59 | ||
60 | sub hd_dtd; | |
61 | sub hd_dtd_internal; | |
62 | ||
63 | $dump = new Dumpvalue(); | |
64 | ||
65 | ( | |
66 | $he_other, $he_bus_id, $he_baseclass_id, $he_subclass_id, $he_progif_id, | |
67 | $he_vendor_id, $he_device_id, $he_subvendor_id, $he_subdevice_id, $he_rev_id, | |
68 | $he_bus_name, $he_baseclass_name, $he_subclass_name, $he_progif_name, | |
69 | $he_vendor_name, $he_device_name, $he_subvendor_name, $he_subdevice_name, | |
70 | $he_rev_name, $he_serial, $he_driver, $he_requires, | |
71 | $he_nomask, | |
72 | $he_driver_module_insmod, $he_driver_module_modprobe, | |
73 | $he_driver_module_config, $he_driver_xfree, $he_driver_xfree_config, | |
74 | $he_driver_mouse, $he_driver_display, $he_driver_any | |
75 | ) = ( 0 .. 100 ); | |
76 | $he_class_id = $he_nomask; | |
77 | ||
78 | @ent_names = ( | |
79 | "other", "bus.id", "baseclass.id", "subclass.id", "progif.id", | |
80 | "vendor.id", "device.id", "subvendor.id", "subdevice.id", "rev.id", | |
81 | "bus.name", "baseclass.name", "subclass.name", "progif.name", | |
82 | "vendor.name", "device.name", "subvendor.name", "subdevice.name", | |
83 | "rev.name", "serial", "driver", "requires", | |
84 | "class.id", "driver.module.insmod", "driver.module.modprobe", | |
85 | "driver.module.config", "driver.xfree", "driver.xfree.config", | |
86 | "driver.mouse", "driver.display", "driver.any" | |
87 | ); | |
88 | @ent_values{@ent_names} = ( 0 .. 100 ); | |
89 | ||
90 | @xml_names = ( | |
91 | "other", "bus", "baseclass", "subclass", "progif", | |
92 | "vendor", "device", "subvendor", "subdevice", "revision", | |
93 | "bus", "baseclass", "subclass", "progif", | |
94 | "vendor", "device", "subvendor", "subdevice", | |
95 | "revision", "serial", "driver", "requires" | |
96 | ); | |
97 | @xml_values{@xml_names} = ( 0 .. 100 ); | |
98 | ||
99 | ( $tag_none, $tag_pci, $tag_eisa, $tag_usb, $tag_special, $tag_pcmcia ) = ( 0 .. 5 ); | |
100 | ||
101 | @tag_name = ( "", "pci", "eisa", "usb", "special", "pcmcia" ); | |
102 | @tag_values{@tag_name} = ( 0 .. 5 ); | |
103 | $tag_values{none} = 0; | |
104 | ||
105 | ( $flag_id, $flag_range, $flag_mask, $flag_string, $flag_regexp ) = ( 0 .. 4 ); | |
106 | $flag_cont = 8; | |
107 | ||
108 | # map usb modules to device classes | |
109 | %usbmod2class = ( | |
110 | 'ov511' => [ 0x10f, 0 ], | |
111 | 'pwc' => [ 0x10f, 0 ], | |
112 | 'hpusbscsi' => [ 0x10c, 0 ], | |
113 | 'microtek' => [ 0x10c, 0 ], | |
114 | 'scanner' => [ 0x10c, 0 ] | |
115 | ); | |
116 | ||
117 | ||
118 | # options | |
119 | $opt_write_ids = 1; | |
120 | $opt_write_xml = 0; | |
121 | $opt_sort_ids = 0; | |
122 | $opt_sort_reverse = 0; | |
123 | $opt_sort_random = 0; # for testing | |
124 | $opt_split = 0; | |
125 | $opt_with_source = 0; | |
126 | $opt_fix_driver = 1; | |
127 | $opt_help = 0; | |
128 | $opt_internal_dtd = 0; | |
129 | ||
130 | $opt_ok = GetOptions( | |
131 | 'ids' => \$opt_write_ids, | |
132 | 'no-ids' => sub { $opt_write_ids = 0 }, | |
133 | 'xml' => \$opt_write_xml, | |
134 | 'no-xml' => sub { $opt_write_xml = 0 }, | |
135 | 'sort' => \$opt_sort, | |
136 | 'reverse' => \$opt_sort_reverse, | |
137 | 'random' => \$opt_sort_random, | |
138 | 'split' => \$opt_split, | |
139 | 'with-source' => \$opt_with_source, | |
140 | 'fix-driver' => \$opt_fix_driver, | |
141 | 'no-fix-driver' => sub { $opt_fix_driver = 0 }, | |
142 | 'internal-dtd' => \$opt_internal_dtd, | |
143 | 'help' => \&help | |
144 | ) ; | |
145 | ||
146 | for $f (@ARGV) { | |
147 | if(open F, $f) { | |
148 | @f = (<F>); | |
149 | close F; | |
150 | ||
151 | # file format check | |
152 | ||
153 | undef $format; | |
154 | ||
155 | for (@f) { | |
156 | if(/^\s*\<\?xml\s/) { | |
157 | $format = 'xml'; | |
158 | last; | |
159 | } | |
160 | ||
161 | if(/^#\s+pci\s+module\s+vendor\s+device\s+subvendor\s+subdevice\s+class\s+class_mask\s+driver_data\s*$/) { | |
162 | $format = 'pcimap'; | |
163 | last; | |
164 | } | |
165 | ||
166 | if(/^#\s+usb\s+module\s+match_flags\s+idVendor\s+idProduct\s+/) { | |
167 | $format = 'usbmap'; | |
168 | last; | |
169 | } | |
170 | ||
171 | if(/^\s*alias\s+(pci|pnp|usb):\S+\s+\S+$/) { | |
172 | $format = 'alias'; | |
173 | last; | |
174 | } | |
175 | ||
176 | if(/^\s*alias:\s+(pci|pnp|usb):\S+\s*$/) { | |
177 | $format = 'modinfo'; | |
178 | last; | |
179 | } | |
180 | ||
181 | } | |
182 | ||
183 | if(!$format) { | |
184 | $i = join "|", map "\Q$_", @ent_names; | |
185 | for (@f) { | |
186 | if(/^\s*[+&|]?($i)\s/) { | |
187 | $format = 'ids'; | |
188 | last; | |
189 | } | |
190 | } | |
191 | } | |
192 | ||
193 | if(!$format) { | |
194 | for (@f) { | |
195 | if(/^\t[a-z]\s/) { | |
196 | $format = 'drivers'; | |
197 | last; | |
198 | } | |
199 | } | |
200 | } | |
201 | ||
202 | $format = 'names' if !$format; | |
203 | ||
204 | if($format eq 'names') { | |
205 | ||
206 | print STDERR "====== \"$f\": name info ======\n"; | |
207 | read_name_file $f, \@f; | |
208 | ||
209 | } | |
210 | elsif($format eq 'drivers') { | |
211 | ||
212 | print STDERR "====== \"$f\": driver info ======\n"; | |
213 | read_driver_file $f, \@f; | |
214 | ||
215 | } | |
216 | elsif($format eq 'xml') { | |
217 | ||
218 | print STDERR "====== \"$f\": xml info ======\n"; | |
219 | $xmlp = new XML::Parser(Style => 'Tree', ParseParamEnt => 1); | |
220 | get_xml_data $xmlp->parsefile($f); | |
221 | ||
222 | } | |
223 | elsif($format eq 'ids') { | |
224 | ||
225 | print STDERR "====== \"$f\": id info ======\n"; | |
226 | read_id_file $f, \@f; | |
227 | ||
228 | } | |
229 | elsif($format eq 'pcimap') { | |
230 | ||
231 | print STDERR "====== \"$f\": pcimap info ======\n"; | |
232 | read_pcimap_file $f, \@f; | |
233 | ||
234 | } | |
235 | elsif($format eq 'usbmap') { | |
236 | ||
237 | print STDERR "====== \"$f\": usbmap info ======\n"; | |
238 | read_usbmap_file $f, \@f; | |
239 | ||
240 | } | |
241 | elsif($format eq 'alias') { | |
242 | ||
243 | print STDERR "====== \"$f\": alias info ======\n"; | |
244 | read_alias_file $f, \@f; | |
245 | ||
246 | } | |
247 | elsif($format eq 'modinfo') { | |
248 | ||
249 | print STDERR "====== \"$f\": module info ======\n"; | |
250 | read_modinfo_file $f, \@f; | |
251 | ||
252 | } | |
253 | } | |
254 | else { | |
255 | die "$f: $!\n" | |
256 | } | |
257 | } | |
258 | ||
259 | print STDERR "removing unnecessary items\n"; | |
260 | remove_nops; | |
261 | ||
262 | print STDERR "got ${\scalar @hd} items\n"; | |
263 | ||
264 | if($opt_fix_driver) { | |
265 | fix_driver_info; | |
266 | } | |
267 | ||
268 | if($opt_split) { | |
269 | print STDERR "splitting items\n"; | |
270 | for (@hd) { | |
271 | push @hd_new, split_item($_); | |
272 | } | |
273 | @hd = @hd_new; | |
274 | undef @hd_new; | |
275 | } | |
276 | ||
277 | if($opt_sort_ids) { | |
278 | print STDERR "sorting\n"; | |
279 | if($opt_sort_random) { | |
280 | @hd = sort { $cmp_item_cnt++, rand() <=> rand() } @hd; | |
281 | } | |
282 | elsif($opt_sort_reverse) { | |
283 | @hd = sort { cmp_item $b, $a } @hd; | |
284 | } | |
285 | else { | |
286 | @hd = sort { cmp_item $a, $b } @hd; | |
287 | } | |
288 | } | |
289 | ||
290 | if($opt_write_ids) { | |
291 | print STDERR "writing \"hd.ids\"\n"; | |
292 | dump2ids; | |
293 | } | |
294 | ||
295 | if($opt_write_xml) { | |
296 | print STDERR "writing \"hd.xml\"\n"; | |
297 | dump2xml; | |
298 | } | |
299 | ||
300 | print STDERR "cmps: $cmp_item_cnt\n" if $cmp_item_cnt; | |
301 | ||
302 | # $dump->dumpValue( \@hd ); | |
303 | ||
304 | ||
305 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
306 | ||
307 | sub help | |
308 | { | |
309 | print STDERR | |
310 | "Usage: convert_hd [options] files\n" . | |
311 | "Convert various hardware info to libhd/hwinfo internal format or to XML.\n" . | |
312 | " --ids write internal format (default) to \"hd.ids\"\n" . | |
313 | " --no-ids do not write internal format\n" . | |
314 | " --xml write XML to \"hd.xml\", DTD to \"hd.dtd\"\n" . | |
315 | " --no-xml do not write XML (default)\n" . | |
316 | " --with-source add comment to each item indicating info source\n" . | |
317 | " --internal-dtd generate internal dtd\n\n" . | |
318 | " Note: for more sophisticated operations on hardware data use check_hd.\n"; | |
319 | ||
320 | exit 0; | |
321 | } | |
322 | ||
323 | ||
324 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
325 | sub num | |
326 | { | |
327 | return $_[0] =~ /^0/ ? oct $_[0] : return $_[0] + 0; | |
328 | } | |
329 | ||
330 | ||
331 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
332 | # | |
333 | # read file with name/class info | |
334 | # | |
335 | # (either pciutils or SaX/SaX2 format) | |
336 | # | |
337 | ||
338 | sub read_name_file | |
339 | { | |
340 | my ( $file_name, $file, $line, $sax_version, $tag, $id, $val, $ent ); | |
341 | my ( @id0, @id1, @id2, @id3, @id4, $raw, $opt, $ext, $srv, $str ); | |
342 | local $_; | |
343 | ||
344 | my $rnf_add_id0 = sub | |
345 | { | |
346 | my ( $id0, $name0, $ent_id0, $ent_name0, $id, $val ); | |
347 | ||
348 | # note: $tag belongs to read_name_file() | |
349 | ( $ent_id0, $ent_name0, $tag, $id0, $name0 ) = @_; | |
350 | ||
351 | $ent = $ent_id0; | |
352 | ||
353 | @id0 = ( $flag_id, $tag, $id0 ); | |
354 | undef @id1; undef @id2; undef @id3; | |
355 | ||
356 | $id->[$ent_id0] = [ @id0 ]; | |
357 | $val->[$ent_name0] = [ $flag_string, $name0 ]; | |
358 | ||
359 | push @hd, [ "$file_name($line)", [ $id ], $val ]; | |
360 | }; | |
361 | ||
362 | my $rnf_add_bus = sub | |
363 | { | |
364 | $rnf_add_id0->($he_bus_id, $he_bus_name, 0, @_); | |
365 | }; | |
366 | ||
367 | my $rnf_add_baseclass = sub | |
368 | { | |
369 | $rnf_add_id0->($he_baseclass_id, $he_baseclass_name, 0, @_); | |
370 | }; | |
371 | ||
372 | my $rnf_add_vendor = sub | |
373 | { | |
374 | $rnf_add_id0->($he_vendor_id, $he_vendor_name, @_); | |
375 | }; | |
376 | ||
377 | my $rnf_add_subdevice = sub | |
378 | { | |
379 | my ( $id2, $id3, $range, $name, $class, $id, $val ); | |
380 | ||
381 | ( $id2, $id3, $range, $name, $class ) = @_; | |
382 | ||
383 | @id2 = ( $flag_id, $tag, $id2 ); | |
384 | @id3 = ( $flag_id, $tag, $id3 ); | |
385 | $id3[3] = $range if defined $range; | |
386 | ||
387 | if($ent == $he_device_id || $ent == $he_subdevice_id) { | |
388 | $ent = $he_subdevice_id; | |
389 | ||
390 | $id->[$he_vendor_id] = [ @id0 ]; | |
391 | $id->[$he_device_id] = [ @id1 ]; | |
392 | $id->[$he_subvendor_id] = [ @id2 ]; | |
393 | $id->[$he_subdevice_id] = [ @id3 ]; | |
394 | $val->[$he_subdevice_name] = [ $flag_string, $name ]; | |
395 | if(defined $class) { | |
396 | $val->[$he_baseclass_id] = [ $flag_id, $tag_none, $class >> 8 ]; | |
397 | $val->[$he_subclass_id] = [ $flag_id, $tag_none, $class & 0xff ]; | |
398 | } | |
399 | } | |
400 | else { | |
401 | die "oops $file_name($line): subdevice id expected\n"; | |
402 | } | |
403 | ||
404 | push @hd, [ "$file_name($line)", [ $id ], $val ]; | |
405 | }; | |
406 | ||
407 | ( $file_name, $file ) = @_; | |
408 | ||
409 | $line = 0; | |
410 | undef $sax_version; | |
411 | ||
412 | for (@$file) { | |
413 | $line++; | |
414 | chomp; | |
415 | s/\s*$//; | |
416 | next if /^\s*[#;]/; | |
417 | next if /^$/; | |
418 | ||
419 | # SaX Identity file | |
420 |