This commit was manufactured by cvs2svn to create tag 'hwinfo-8_12'.
[opensuse:hwinfo.git] / hwinfo.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <fcntl.h>
6 #include <getopt.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9
10 #include "hd.h"
11
12 static int get_probe_flags(int, char **, hd_data_t *);
13 static void progress(char *, char *);
14
15 // ##### temporary solution, fix it later!
16 str_list_t *read_file(char *file_name, unsigned start_line, unsigned lines);
17 str_list_t *search_str_list(str_list_t *sl, char *str);
18 str_list_t *add_str_list(str_list_t **sl, char *str);
19 char *new_str(const char *);
20
21 static unsigned deb = 0;
22 static char *log_file = "";
23 static char *list = NULL;
24 static int listplus = 0;
25
26 static int test = 0;
27 static int is_short = 0;
28
29 static char *showconfig = NULL;
30 static char *saveconfig = NULL;
31 static hd_hw_item_t hw_item[100] = { };
32 static int hw_items = 0;
33
34 int braille_install_info(hd_data_t *hd_data);
35 int x11_install_info(hd_data_t *hd_data);
36 int oem_install_info(hd_data_t *hd_data);
37 void dump_packages(hd_data_t *hd_data);
38
39 void do_hw(hd_data_t *hd_data, FILE *f, hd_hw_item_t hw_item);
40 void do_hw_multi(hd_data_t *hd_data, FILE *f, hd_hw_item_t *hw_items);
41 void do_short(hd_data_t *hd_data, hd_t *hd, FILE *f);
42 void do_test(hd_data_t *hd_data);
43 void help(void);
44 void dump_db_raw(hd_data_t *hd_data);
45 void dump_db(hd_data_t *hd_data);
46
47
48 struct {
49   unsigned db_idx;
50   unsigned separate:1;
51 } opt;
52
53 struct option options[] = {
54   { "special", 1, NULL, 1 },
55   { "help", 0, NULL, 'h' },
56   { "debug", 1, NULL, 'd' },
57   { "version", 0, NULL, 400 },
58   { "log", 1, NULL, 'l' },
59   { "packages", 0, NULL, 'p' },
60   { "test", 0, NULL, 300 },
61   { "format", 1, NULL, 301 },
62   { "show-config", 1, NULL, 302 },
63   { "save-config", 1, NULL, 303 },
64   { "short", 0, NULL, 304 },
65   { "fast", 0, NULL, 305 },
66   { "dump-db", 1, NULL, 306 },
67   { "dump-db-raw", 1, NULL, 307 },
68   { "separate", 0, NULL, 308 },
69   { "cdrom", 0, NULL, 1000 + hw_cdrom },
70   { "floppy", 0, NULL, 1000 + hw_floppy },
71   { "disk", 0, NULL, 1000 + hw_disk },
72   { "network", 0, NULL, 1000 + hw_network },
73   { "display", 0, NULL, 1000 + hw_display },
74   { "gfxcard", 0, NULL, 1000 + hw_display },
75   { "framebuffer", 0, NULL, 1000 + hw_framebuffer },
76   { "monitor", 0, NULL, 1000 + hw_monitor },
77   { "camera", 0, NULL, 1000 + hw_camera },
78   { "mouse", 0, NULL, 1000 + hw_mouse },
79   { "joystick", 0, NULL, 1000 + hw_joystick },
80   { "keyboard", 0, NULL, 1000 + hw_keyboard },
81   { "chipcard", 0, NULL, 1000 + hw_chipcard },
82   { "sound", 0, NULL, 1000 + hw_sound },
83   { "isdn", 0, NULL, 1000 + hw_isdn },
84   { "modem", 0, NULL, 1000 + hw_modem },
85   { "storage-ctrl", 0, NULL, 1000 + hw_storage_ctrl },
86   { "storage_ctrl", 0, NULL, 1000 + hw_storage_ctrl },
87   { "netcard", 0, NULL, 1000 + hw_network_ctrl },
88   { "netcards", 0, NULL, 1000 + hw_network_ctrl },      // outdated, just kept for comaptibility
89   { "network-ctrl", 0, NULL, 1000 + hw_network_ctrl },
90   { "network_ctrl", 0, NULL, 1000 + hw_network_ctrl },
91   { "printer", 0, NULL, 1000 + hw_printer },
92   { "tv", 0, NULL, 1000 + hw_tv },
93   { "dvb", 0, NULL, 1000 + hw_dvb },
94   { "scanner", 0, NULL, 1000 + hw_scanner },
95   { "braille", 0, NULL, 1000 + hw_braille },
96   { "sys", 0, NULL, 1000 + hw_sys },
97   { "bios", 0, NULL, 1000 + hw_bios },
98   { "cpu", 0, NULL, 1000 + hw_cpu },
99   { "partition", 0, NULL, 1000 + hw_partition },
100   { "usb-ctrl", 0, NULL, 1000 + hw_usb_ctrl },
101   { "usb_ctrl", 0, NULL, 1000 + hw_usb_ctrl },
102   { "usb", 0, NULL, 1000 + hw_usb },
103   { "pci", 0, NULL, 1000 + hw_pci },
104   { "isapnp", 0, NULL, 1000 + hw_isapnp },
105   { "scsi", 0, NULL, 1000 + hw_scsi },
106   { "ide", 0, NULL, 1000 + hw_ide },
107   { "bridge", 0, NULL, 1000 + hw_bridge },
108   { "hub", 0, NULL, 1000 + hw_hub },
109   { "memory", 0, NULL, 1000 + hw_memory },
110   { "manual", 0, NULL, 1000 + hw_manual },
111   { "pcmcia", 0, NULL, 1000 + hw_pcmcia },
112   { "pcmcia_ctrl", 0, NULL, 1000 + hw_pcmcia_ctrl },
113   { "ieee1394", 0, NULL, 1000 + hw_ieee1394 },
114   { "ieee1394_ctrl", 0, NULL, 1000 + hw_ieee1394_ctrl },
115   { "firewire", 0, NULL, 1000 + hw_ieee1394 },
116   { "firewire_ctrl", 0, NULL, 1000 + hw_ieee1394_ctrl },
117   { "hotplug", 0, NULL, 1000 + hw_hotplug },
118   { "hotplug_ctrl", 0, NULL, 1000 + hw_hotplug_ctrl },
119   { "zip", 0, NULL, 1000 + hw_zip },
120   { "pppoe", 0, NULL, 1000 + hw_pppoe },
121   { "dsl", 0, NULL, 1000 + hw_pppoe },
122   { "wlan", 0, NULL, 1000 + hw_wlan },
123   { "all", 0, NULL, 2000 },
124   { "reallyall", 0, NULL, 2001 },
125   { "smp", 0, NULL, 2002 },
126   { "arch", 0, NULL, 2003 },
127   { }
128 };
129
130
131 /*
132  * Just scan the hardware and dump all info.
133  */
134 int main(int argc, char **argv)
135 {
136   hd_data_t *hd_data;
137   hd_t *hd;
138   FILE *f = NULL;
139   long l = 0;
140   int i;
141   unsigned first_probe = 1;
142
143   hd_data = calloc(1, sizeof *hd_data);
144   hd_data->progress = isatty(1) ? progress : NULL;
145   hd_data->debug=~(HD_DEB_DRIVER_INFO | HD_DEB_HDDB);
146
147   for(i = 0; i < argc; i++) {
148     if(strstr(argv[i], "--") == argv[i]) break;
149   }
150
151   if(i != argc) {
152     /* new style interface */
153
154     opterr = 0;
155
156     while((i = getopt_long(argc, argv, "hd:l:p", options, NULL)) != -1) {
157       switch(i) {
158         case 1:
159           if(!strcmp(optarg, "braille")) {
160             braille_install_info(hd_data);
161           }
162           else if(!strcmp(optarg, "x11")) {
163             x11_install_info(hd_data);
164           }
165           else if(!strcmp(optarg, "oem")) {
166             oem_install_info(hd_data);
167           }
168           else {
169             help();
170             return 1;
171           }
172           break;
173
174         case 'd':
175           hd_data->debug = strtol(optarg, NULL, 0);
176           break;
177
178         case 'l':
179           log_file = optarg;
180           break;
181
182         case 'p':
183           dump_packages(hd_data);
184           break;
185
186         case 300:
187           do_test(hd_data);
188           break;
189
190         case 301:
191           hd_data->flags.dformat = strtol(optarg, NULL, 0);
192           break;
193
194         case 302:
195           showconfig = optarg;
196           break;
197
198         case 303:
199           saveconfig = optarg;
200           break;
201
202         case 304:
203           is_short = 1;
204           break;
205
206         case 305:
207           hd_data->flags.fast = 1;
208           break;
209
210         case 306:
211           opt.db_idx = strtoul(optarg, NULL, 0);
212           dump_db(hd_data);
213           break;
214
215         case 307:
216           opt.db_idx = strtoul(optarg, NULL, 0);
217           dump_db_raw(hd_data);
218           break;
219
220         case 308:
221           /* basically for debugging */
222           opt.separate = 1;
223           break;
224
225         case 400:
226           printf("%s\n", hd_version());
227           break;
228
229         case 1000 ... 1100:
230           if(hw_items < (int) (sizeof hw_item / sizeof *hw_item) - 1)
231             hw_item[hw_items++] = i - 1000;
232           break;
233
234         case 2000:
235         case 2001:
236         case 2002:
237         case 2003:
238           if(hw_items < (int) (sizeof hw_item / sizeof *hw_item) - 1)
239             hw_item[hw_items++] = i;
240           break;
241
242         default:
243           help();
244           return 0;
245       }
246     }
247
248     if(!hw_items && is_short) hw_item[hw_items++] = 2000;       /* all */
249
250     if(hw_items >= 0 || showconfig || saveconfig) {
251       if(*log_file) f = fopen(log_file, "w+");
252
253       if(opt.separate || hw_items <= 1) {
254         for(i = 0; i < hw_items; i++) {
255           if(i) fputc('\n', f ? f : stdout);
256           do_hw(hd_data, f, hw_item[i]);
257         }
258       }
259       else {
260         hw_item[hw_items] = 0;
261         do_hw_multi(hd_data, f, hw_item);
262       }
263
264 #ifndef LIBHD_TINY
265       if(showconfig) {
266         hd = hd_read_config(hd_data, showconfig);
267         if(hd) {
268           hd_dump_entry(hd_data, hd, f ? f : stdout);
269           hd = hd_free_hd_list(hd);
270         }
271         else {
272           fprintf(f ? f : stdout, "No config data: %s\n", showconfig);
273         }
274       }
275
276       if(saveconfig) {
277         for(hd = hd_data->hd; hd; hd = hd->next) {
278           if(!strcmp(hd->unique_id, saveconfig)) {
279             i = hd_write_config(hd_data, hd);
280             fprintf(f ? f : stdout, "%s: %s\n",
281               saveconfig,
282               i ? "Error writing config data" : "config saved"
283             );
284             break;
285           }
286         }
287         if(!hd) {
288           fprintf(f ? f : stdout, "No such hardware: %s\n", saveconfig);
289         }
290       }
291 #endif
292
293       if(f) fclose(f);
294     }
295
296     hd_free_hd_data(hd_data);
297     free(hd_data);
298
299     return 0;
300   }
301
302   /* old style interface */
303
304   argc--; argv++;
305
306   if(argc == 1 && !strcmp(*argv, "-h")) {
307     help();
308     return 0;
309   }
310
311   do {
312     if(first_probe)                             /* only for the 1st probing */
313       hd_set_probe_feature(hd_data, pr_default);
314     else {
315       hd_clear_probe_feature(hd_data, pr_all);
316     }
317
318     if((i = get_probe_flags(argc, argv, hd_data)) < 0) return 1;
319     deb = hd_data->debug;
320     argc -= i; argv += i;
321
322     hd_scan(hd_data);
323     if(hd_data->progress) printf("\r%64s\r", "");
324
325     first_probe = 0;
326   } while(argc);
327
328   if(*log_file) f = fopen(log_file, "w+");
329
330   if((hd_data->debug & HD_DEB_SHOW_LOG) && hd_data->log) {
331     if(*log_file) {
332       fprintf(f ? f : stdout,
333         "============ start hardware log ============\n"
334       );
335     }
336     fprintf(f ? f : stdout,
337       "============ start debug info ============\n%s=========== end debug info ============\n",
338       hd_data->log
339     );
340   }
341
342   if(f) l = ftell(f);
343
344   for(hd = hd_data->hd; hd; hd = hd->next) {
345     hd_dump_entry(hd_data, hd, f ? f : stdout);
346   }
347
348   if(*log_file) {
349     fprintf(f ? f : stdout,
350       "============ end hardware log ============\n"
351     );
352   }
353
354   i = -1;
355   if(list) {
356     if(!strcmp(list, "cdrom")) i = hw_cdrom;
357     if(!strcmp(list, "disk")) i = hw_disk;
358     if(!strcmp(list, "floppy")) i = hw_floppy;
359     if(!strcmp(list, "network")) i = hw_network;
360     if(!strcmp(list, "display")) i = hw_display;
361     if(!strcmp(list, "monitor")) i = hw_monitor;
362     if(!strcmp(list, "mouse")) i = hw_mouse;
363     if(!strcmp(list, "keyboard")) i = hw_keyboard;
364     if(!strcmp(list, "sound")) i = hw_sound;
365     if(!strcmp(list, "isdn")) i = hw_isdn;
366     if(!strcmp(list, "modem")) i = hw_modem;
367     if(!strcmp(list, "storage_ctrl")) i = hw_storage_ctrl;
368     if(!strcmp(list, "network_ctrl")) i = hw_network_ctrl;
369     if(!strcmp(list, "netcards")) i = hw_network_ctrl;
370     if(!strcmp(list, "printer")) i = hw_printer;
371     if(!strcmp(list, "tv")) i = hw_tv;
372     if(!strcmp(list, "scanner")) i = hw_scanner;
373     if(!strcmp(list, "braille")) i = hw_braille;
374     if(!strcmp(list, "sys")) i = hw_sys;
375     if(!strcmp(list, "cpu")) i = hw_cpu;
376
377     if(i >= 0) {
378       hd = hd_list(hd_data, i, listplus, NULL);
379       printf("\n");
380       printf("-- %s list --\n", list);
381       for(; hd; hd = hd->next) hd_dump_entry(hd_data, hd, stdout);
382       printf("-- %s list end --\n", list);
383       hd = hd_free_hd_list(hd);
384     }
385   }
386
387   if(f) fclose(f);
388
389   hd_free_hd_data(hd_data);
390   free(hd_data);
391
392   return 0;
393 }
394
395
396 void do_hw(hd_data_t *hd_data, FILE *f, hd_hw_item_t hw_item)
397 {
398   hd_t *hd, *hd0;
399   int smp = -1, i;
400   char *s, *t;
401   enum boot_arch b_arch;
402   enum cpu_arch c_arch;
403
404   hd0 = NULL;
405
406   switch(hw_item) {
407     case 2002:
408       smp = hd_smp_support(hd_data);
409       break;
410
411     case 2000:
412     case 2001:
413     case 2003:
414       i = -1;
415       switch((int) hw_item) {
416         case 2000: i = pr_default; break;
417         case 2001: i = pr_all; break;
418         case 2003: i = pr_cpu; break;
419       }
420       if(i != -1) {
421         hd_clear_probe_feature(hd_data, pr_all);
422         hd_set_probe_feature(hd_data, i);
423         hd_scan(hd_data);
424         hd0 = hd_data->hd;
425       }
426       break;
427
428     default:
429       hd0 = hd_list(hd_data, hw_item, 1, NULL);
430   }
431
432   if(hd_data->progress) {
433     printf("\r%64s\r", "");
434     fflush(stdout);
435   }
436
437   if(f) {
438     if((hd_data->debug & HD_DEB_SHOW_LOG) && hd_data->log) {
439       fprintf(f,
440         "============ start hardware log ============\n"
441       );
442       fprintf(f,
443         "============ start debug info ============\n%s=========== end debug info ============\n",
444         hd_data->log
445       );
446     }
447
448     for(hd = hd_data->hd; hd; hd = hd->next) {
449       hd_dump_entry(hd_data, hd, f);
450     }
451
452     fprintf(f,
453       "============ end hardware log ============\n"
454     );
455   }
456
457   if(hw_item == 2002) {
458     fprintf(f ? f : stdout,
459       "SMP support: %s",
460       smp < 0 ? "unknown" : smp > 0 ? "yes" : "no"
461     );
462     if(smp > 0) fprintf(f ? f : stdout, " (%u cpus)", smp);
463     fprintf(f ? f : stdout, "\n");
464   }
465   else if(hw_item == 2003) {
466     c_arch = hd_cpu_arch(hd_data);
467     b_arch = hd_boot_arch(hd_data);
468
469     s = t = "Unknown";
470     switch(c_arch) {
471       case arch_unknown:
472         break;
473       case arch_intel:
474         s = "X86 (32)";
475         break;
476       case arch_alpha:
477         s = "Alpha";
478         break;
479       case arch_sparc:
480         s = "Sparc (32)";
481         break;
482       case arch_sparc64:
483         s = "UltraSparc (64)";
484         break;
485       case arch_ppc:
486         s = "PowerPC";
487         break;
488       case arch_ppc64:
489         s = "PowerPC (64)";
490         break;
491       case arch_68k:
492         s = "68k";
493         break;
494       case arch_ia64:
495         s = "IA-64";
496         break;
497       case arch_s390:
498         s = "S390";
499         break;
500       case arch_s390x:
501         s = "S390x";
502         break;
503       case arch_arm:
504         s = "ARM";
505         break;
506       case arch_mips:
507         s = "MIPS";
508         break;
509       case arch_x86_64:
510         s = "X86_64";
511         break;
512     }
513
514     switch(b_arch) {
515       case boot_unknown:
516         break;
517       case boot_lilo:
518         t = "lilo";
519         break;
520       case boot_milo:
521         t = "milo";
522         break;
523       case boot_aboot:
524         t = "aboot";
525         break;
526       case boot_silo:
527         t = "silo";
528         break;
529       case boot_ppc:
530         t = "ppc";
531         break;
532       case boot_elilo:
533         t = "elilo";
534         break;
535       case boot_s390:
536         t = "s390";
537         break;
538       case boot_mips:
539         t = "mips";
540         break;
541       case boot_grub:
542         t = "grub";
543         break;
544     }
545
546     fprintf(f ? f : stdout, "Arch: %s/%s\n", s, t);
547   }
548   else {
549     if(is_short) {
550       /* always to stdout */
551       do_short(hd_data, hd0, stdout);
552       if(f) do_short(hd_data, hd0, f);
553     }
554     else {
555       for(hd = hd0; hd; hd = hd->next) {
556         hd_dump_entry(hd_data, hd, f ? f : stdout);
557       }
558     }
559   }
560
561   if(hw_item == hw_display && hd0) {
562     fprintf(f ? f : stdout, "\nPrimary display adapter: #%u\n", hd_display_adapter(hd_data));
563   }
564
565   if(hd0 != hd_data->hd) hd_free_hd_list(hd0);
566 }
567
568
569 void do_hw_multi(hd_data_t *hd_data, FILE *f, hd_hw_item_t *hw_items)
570 {
571   hd_t *hd, *hd0;
572
573   hd0 = hd_list2(hd_data, hw_items, 1);
574
575   if(hd_data->progress) {
576     printf("\r%64s\r", "");
577     fflush(stdout);
578   }
579
580   if(f) {
581     if((hd_data->debug & HD_DEB_SHOW_LOG) && hd_data->log) {
582       fprintf(f,
583         "============ start hardware log ============\n"
584       );
585       fprintf(f,
586         "============ start debug info ============\n%s=========== end debug info ============\n",
587         hd_data->log
588       );
589     }
590
591     for(hd = hd_data->hd; hd; hd = hd->next) {
592       hd_dump_entry(hd_data, hd, f);
593     }
594
595     fprintf(f,
596       "============ end hardware log ============\n"
597     );
598   }
599
600   if(is_short) {
601     /* always to stdout */
602     do_short(hd_data, hd0, stdout);
603     if(f) do_short(hd_data, hd0, f);
604   }
605   else {
606     for(hd = hd0; hd; hd = hd->next) {
607       hd_dump_entry(hd_data, hd, f ? f : stdout);
608     }
609   }
610
611   hd_free_hd_list(hd0);
612 }
613
614
615 void do_short(hd_data_t *hd_data, hd_t *hd, FILE *f)
616 {
617 #ifndef LIBHD_TINY
618   hd_hw_item_t item;
619   hd_t *hd1;
620   int i;
621   char *s;
622
623   for(item = 1; item < hw_all; item++) {
624     i = 0;
625     s = hd_hw_item_name(item);
626     if(!s) continue;
627
628     if(item == hw_sys) continue;
629
630     for(hd1 = hd; hd1; hd1 = hd1->next) {
631       if(hd1->hw_class == item) {
632         if(!i++) fprintf(f, "%s:\n", s);
633         fprintf(f, "  %-20s %s\n",
634           hd1->unix_dev_name ? hd1->unix_dev_name : "",
635           hd1->model ? hd1->model : "???"
636         );
637       }
638     }
639   }
640 #endif
641 }
642
643
644 #if 1
645 typedef struct {
646   char *vendor, *model, *driver;
647 } scanner_t;
648
649 static scanner_t scanner_data[] = {
650   { "Abaton", "SCAN 300/GS", "abaton" },
651   { "Abaton", "SCAN 300/S", "abaton" },
652   { "Acer", "300f", "SnapScan" },
653   { "Acer", "310s", "SnapScan" },
654   { "Acer", "610plus", "SnapScan" },
655   { "Acer", "610s", "SnapScan" },
656   { "Acer", "Prisa 1240", "SnapScan" },
657   { "Acer", "Prisa 3300", "SnapScan" },
658   { "Acer", "Prisa 4300", "SnapScan" },
659   { "Acer", "Prisa 5300", "SnapScan" },
660   { "Acer", "Prisa 620s", "SnapScan" },
661   { "Acer", "Prisa 620u", "SnapScan" },
662   { "Acer", "Prisa 620ut", "SnapScan" },
663   { "Acer", "Prisa 640bu", "SnapScan" },
664   { "Acer", "Prisa 640u", "SnapScan" },
665   { "Agfa", "Arcus II", "microtek" },
666   { "Agfa", "DuoScan", "microtek" },
667   { "Agfa", "FOCUS COLOR", "agfafocus" },
668   { "Agfa", "FOCUS GS SCANNER", "agfafocus" },
669   { "Agfa", "FOCUS II", "agfafocus" },
670   { "Agfa", "FOCUS LINEART SCANNER", "agfafocus" },
671   { "Agfa", "SnapScan 1212u", "SnapScan" },
672   { "Agfa", "SnapScan 1236s", "SnapScan" },
673   { "Agfa", "SnapScan 1236u", "SnapScan" },
674   { "Agfa", "SnapScan 300", "SnapScan" },
675   { "Agfa", "SnapScan 310", "SnapScan" },
676   { "Agfa", "SnapScan 600", "SnapScan" },
677   { "Agfa", "SnapScan e20", "SnapScan" },
678   { "Agfa", "SnapScan e25", "SnapScan" },
679   { "Agfa", "SnapScan e40", "SnapScan" },
680   { "Agfa", "SnapScan e50", "SnapScan" },
681   { "Agfa", "SnapScan e60", "SnapScan" },
682   { "Agfa", "StudioScan", "microtek" },
683   { "Agfa", "StudioScan II", "microtek" },
684   { "Agfa", "StudioScan IIsi", "microtek" },
685   { "Apple", "APPLE SCANNER", "apple" },
686   { "Apple", "COLORONESCANNER", "apple" },
687   { "Apple", "ONESCANNER", "apple" },
688   { "Artec", "A6000C", "artec" },
689   { "Artec", "A6000C PLUS", "artec" },
690   { "Artec", "AM12S", "artec" },
691   { "Artec", "AT12", "artec" },
692   { "Artec", "AT3", "artec" },
693   { "Artec", "AT6", "artec" },
694   { "Artec", "ColorOneScanner", "artec" },
695   { "Avision", "AV 620 CS", "avision" },
696   { "Avision", "AV 6240", "avision" },
697   { "Avision", "AV 630 CS", "avision" },
698   { "B&H SCSI", "COPISCAN II 2135", "bh" },
699   { "B&H SCSI", "COPISCAN II 2137", "bh" },
700   { "B&H SCSI", "COPISCAN II 2137A", "bh" },
701   { "B&H SCSI", "COPISCAN II 2138A", "bh" },
702   { "B&H SCSI", "COPISCAN II 3238", "bh" },
703   { "B&H SCSI", "COPISCAN II 3338", "bh" },
704   { "B&H SCSI", "COPISCAN II 6338", "bh" },
705   { "BlackWidow", "BW4800SP", "artec" },
706   { "Canon", "CANOSCAN 2700F", "canon" },
707   { "Canon", "CANOSCAN 300", "canon" },
708   { "Canon", "CANOSCAN 600", "canon" },
709   { "Devcom", "9636PRO", "pie" },
710   { "Devcom", "9636S", "pie" },
711   { "EDGE", "KTX-9600US", "umax" },
712   { "Epson", "ES-8500", "epson" },
713   { "Epson", "EXPRESSION 1600", "epson" },
714   { "Epson", "EXPRESSION 1680", "epson" },
715   { "Epson", "EXPRESSION 636", "epson" },
716   { "Epson", "EXPRESSION 800", "epson" },
717   { "Epson", "FILMSCAN 200", "epson" },
718   { "Epson", "GT-5500", "epson" },
719   { "Epson", "GT-7000", "epson" },
720   { "Epson", "GT-8000", "epson" },
721   { "Epson", "PERFECTION 1200PHOTO", "epson" },
722   { "Epson", "PERFECTION 1200S", "epson" },
723   { "Epson", "PERFECTION 1200U", "epson" },
724   { "Epson", "PERFECTION 1240", "epson" },
725   { "Epson", "PERFECTION 1640", "epson" },
726   { "Epson", "PERFECTION 1650", "epson" },
727   { "Epson", "PERFECTION 610", "epson" },
728   { "Epson", "PERFECTION 636S", "epson" },
729   { "Epson", "PERFECTION 636U", "epson" },
730   { "Epson", "PERFECTION 640", "epson" },
731   { "Epson", "PERFECTION1200", "epson" },
732   { "Epson", "Perfection 600", "umax" },
733   { "Escom", "Image Scanner 256", "umax" },
734   { "Escort", "Galleria 600", "umax" },
735   { "Fujitsu", "M3091DCD", "m3091" },
736   { "Fujitsu", "M3096G", "m3096g" },
737   { "Fujitsu", "SP15C", "sp15c" },
738   { "Genius", "ColorPage-HR5 Pro", "umax" },
739   { "Guillemot", "Maxi Scan A4 Deluxe", "SnapScan" },
740   { "HP", "HP OFFICEJET K SERIES", "hp" },
741   { "HP", "HP OFFICEJET V SERIES", "hp" },
742   { "HP", "HP PHOTOSMART PHOTOSCANNER", "hp" },
743   { "HP", "HP PSC 700 SERIES", "hp" },
744   { "HP", "HP PSC 900 SERIES", "hp" },
745   { "HP", "HP SCANJET 3C", "hp" },
746   { "HP", "HP SCANJET 3P", "hp" },
747   { "HP", "HP SCANJET 4100C", "hp" },
748   { "HP", "HP SCANJET 4C", "hp" },
749   { "HP", "HP SCANJET 4P", "hp" },
750   { "HP", "HP SCANJET 5200C", "hp" },
751   { "HP", "HP SCANJET 6100C", "hp" },
752   { "HP", "HP SCANJET 6200C", "hp" },
753   { "HP", "HP SCANJET 6250C", "hp" },
754   { "HP", "HP SCANJET 6300C", "hp" },
755   { "HP", "HP SCANJET 6350C", "hp" },
756   { "HP", "HP SCANJET 6390C", "hp" },
757   { "HP", "HP SCANJET IIC", "hp" },
758   { "HP", "HP SCANJET IICX", "hp" },
759   { "HP", "HP SCANJET IIP", "hp" },
760   { "HP", "HP ScanJet 5p", "hp" },
761   { "HP", "HP4200", "hp4200" },
762   { "Highscreen", "Scanboostar Premium", "umax" },
763   { "Linotype Hell", "Jade", "umax" },
764   { "Linotype Hell", "Jade2", "umax" },
765   { "Linotype Hell", "Linoscan 1400", "umax" },
766   { "Linotype Hell", "Opal", "umax" },
767   { "Linotype Hell", "Opal Ultra", "umax" },
768   { "Linotype Hell", "Saphir", "umax" },
769   { "Linotype Hell", "Saphir HiRes", "umax" },
770   { "Linotype Hell", "Saphir Ultra", "umax" },
771   { "Linotype Hell", "Saphir Ultra II", "umax" },
772   { "Linotype Hell", "Saphir2", "umax" },
773   { "Microtek", "Phantom 636", "microtek2" },
774   { "Microtek", "ScanMaker 330", "microtek2" },
775   { "Microtek", "ScanMaker 3600", "sm3600" },
776   { "Microtek", "ScanMaker 630", "microtek2" },
777   { "Microtek", "ScanMaker 636", "microtek2" },
778   { "Microtek", "ScanMaker 9600XL", "microtek2" },
779   { "Microtek", "ScanMaker E3plus", "microtek2" },
780   { "Microtek", "ScanMaker V300", "microtek2" },
781   { "Microtek", "ScanMaker V310", "microtek2" },
782   { "Microtek", "ScanMaker V600", "microtek2" },
783   { "Microtek", "ScanMaker V6USL", "microtek2" },
784   { "Microtek", "ScanMaker X6", "microtek2" },
785   { "Microtek", "ScanMaker X6EL", "microtek2" },
786   { "Microtek", "ScanMaker X6USB", "microtek2" },
787   { "Microtek", "Scanmaker 35", "microtek" },
788   { "Microtek", "Scanmaker 35t+", "microtek" },
789   { "Microtek", "Scanmaker 45t", "microtek" },
790   { "Microtek", "Scanmaker 600G", "microtek" },
791   { "Microtek", "Scanmaker 600G S", "microtek" },
792   { "Microtek", "Scanmaker 600GS", "microtek" },
793   { "Microtek", "Scanmaker 600S", "microtek" },
794   { "Microtek", "Scanmaker 600Z", "microtek" },
795   { "Microtek", "Scanmaker 600Z S", "microtek" },
796   { "Microtek", "Scanmaker 600ZS", "microtek" },
797   { "Microtek", "Scanmaker E2", "microtek" },
798   { "Microtek", "Scanmaker E3", "microtek" },
799   { "Microtek", "Scanmaker E6", "microtek" },
800   { "Microtek", "Scanmaker II", "microtek" },
801   { "Microtek", "Scanmaker IIG", "microtek" },
802   { "Microtek", "Scanmaker IIHR", "microtek" },
803   { "Microtek", "Scanmaker III", "microtek" },
804   { "Microtek", "Scanmaker IISP", "microtek" },
805   { "Microtek", "SlimScan C6", "microtek2" },
806   { "Mustek", "1200 CU", "mustek_usb" },
807   { "Mustek", "1200 CU Plus", "mustek_usb" },
808   { "Mustek", "1200 UB", "mustek_usb" },
809   { "Mustek", "600 CU", "mustek_usb" },
810   { "Mustek", "Paragon 1200 A3 Pro", "mustek" },
811   { "Mustek", "Paragon 1200 III SP", "mustek" },
812   { "Mustek", "Paragon 1200 LS", "mustek" },
813   { "Mustek", "Paragon 1200 SP Pro", "mustek" },
814   { "Mustek", "Paragon 600 II CD", "mustek" },
815   { "Mustek", "Paragon 800 II SP", "mustek" },
816   { "Mustek", "Paragon MFC-600S", "mustek" },
817   { "Mustek", "Paragon MFC-800S", "mustek" },
818   { "Mustek", "Paragon MFS-12000CX", "mustek" },
819   { "Mustek", "Paragon MFS-12000SP", "mustek" },
820   { "Mustek", "Paragon MFS-1200SP", "mustek" },
821   { "Mustek", "Paragon MFS-6000CX", "mustek" },
822   { "Mustek", "Paragon MFS-6000SP", "mustek" },
823   { "Mustek", "Paragon MFS-8000SP", "mustek" },
824   { "Mustek", "ScanExpress 12000SP", "mustek" },
825   { "Mustek", "ScanExpress 12000SP Plus", "mustek" },
826   { "Mustek", "ScanExpress 6000SP", "mustek" },
827   { "Mustek", "ScanExpress A3 SP", "mustek" },
828   { "Mustek", "ScanMagic 600 II SP", "mustek" },
829   { "Mustek", "ScanMagic 9636S", "mustek" },
830   { "Mustek", "ScanMagic 9636S Plus", "mustek" },
831   { "NEC", "PC-IN500/4C", "nec" },
832   { "Nikon", "AX-210", "umax" },
833   { "Nikon", "LS-1000", "coolscan" },
834   { "Nikon", "LS-20", "coolscan" },
835   { "Nikon", "LS-2000", "coolscan" },
836   { "Nikon", "LS-30", "coolscan" },
837   { "Pie", "9630S", "pie" },
838   { "Pie", "ScanAce 1230S", "pie" },
839   { "Pie", "ScanAce 1236S", "pie" },
840   { "Pie", "ScanAce 630S", "pie" },
841   { "Pie", "ScanAce 636S", "plustek" },
842   { "Pie", "ScanAce II", "pie" },
843   { "Pie", "ScanAce II Plus", "pie" },
844   { "Pie", "ScanAce III", "pie" },
845   { "Pie", "ScanAce III Plus", "pie" },
846   { "Pie", "ScanAce Plus", "pie" },
847   { "Pie", "ScanAce ScanMedia", "pie" },
848   { "Pie", "ScanAce ScanMedia II", "pie" },
849   { "Pie", "ScanAce V", "pie" },
850   { "Plustek", "OpticPro 19200S", "artec" },
851   { "Polaroid", "DMC", "dmc" },
852   { "Ricoh", "Ricoh IS50", "ricoh" },
853   { "Ricoh", "Ricoh IS60", "ricoh" },
854   { "Scanport", "SQ4836", "microtek2" },
855   { "Sharp", "9036 Flatbed scanner", "sharp" },
856   { "Sharp", "JX-250", "sharp" },
857   { "Sharp", "JX-320", "sharp" },
858   { "Sharp", "JX-330", "sharp" },
859   { "Sharp", "JX-350", "sharp" },
860   { "Sharp", "JX-610", "sharp" },
861   { "Siemens", "9036 Flatbed scanner", "s9036" },
862   { "Siemens", "FOCUS COLOR PLUS", "agfafocus" },
863   { "Siemens", "ST400", "st400" },
864   { "Siemens", "ST800", "st400" },
865   { "Tamarack", "Artiscan 12000C", "tamarack" },
866   { "Tamarack", "Artiscan 6000C", "tamarack" },
867   { "Tamarack", "Artiscan 8000C", "tamarack" },
868   { "Trust", "Compact Scan USB 19200", "mustek_usb" },
869   { "Trust", "Imagery 1200 SP", "mustek" },
870   { "Trust", "Imagery 4800 SP", "mustek" },
871   { "Trust", "SCSI Connect 19200", "mustek" },
872   { "Trust", "SCSI excellence series 19200", "mustek" },
873   { "UMAX", "Astra 1200S", "umax" },
874   { "UMAX", "Astra 1220S", "umax" },
875   { "UMAX", "Astra 2100S", "umax" },
876   { "UMAX", "Astra 2200", "umax" },
877   { "UMAX", "Astra 2200 S", "umax" },
878   { "UMAX", "Astra 2200 U", "umax" },
879   { "UMAX", "Astra 2400S", "umax" },
880   { "UMAX", "Astra 600S", "umax" },
881   { "UMAX", "Astra 610S", "umax" },
882   { "UMAX", "Gemini D-16", "umax" },
883   { "UMAX", "Mirage D-16L", "umax" },
884   { "UMAX", "Mirage II", "umax" },
885   { "UMAX", "Mirage IIse", "umax" },
886   { "UMAX", "PL-II", "umax" },
887   { "UMAX", "PSD", "umax" },
888   { "UMAX", "PowerLook", "umax" },
889   { "UMAX", "PowerLook 2000", "umax" },
890   { "UMAX", "PowerLook 3000", "umax" },
891   { "UMAX", "PowerLook III", "umax" },
892   { "UMAX", "Supervista S-12", "umax" },
893   { "UMAX", "UC 1200S", "umax" },
894   { "UMAX", "UC 1200SE", "umax" },
895   { "UMAX", "UC 1260", "umax" },
896   { "UMAX", "UC 630", "umax" },
897   { "UMAX", "UC 840", "umax" },
898   { "UMAX", "UG 630", "umax" },
899   { "UMAX", "UG 80", "umax" },
900   { "UMAX", "UMAX S-12", "umax" },
901   { "UMAX", "UMAX S-12G", "umax" },
902   { "UMAX", "UMAX S-6E", "umax" },
903   { "UMAX", "UMAX S-6EG", "umax" },
904   { "UMAX", "UMAX VT600", "umax" },
905   { "UMAX", "Vista S6", "umax" },
906   { "UMAX", "Vista S6E", "umax" },
907   { "UMAX", "Vista-S8", "umax" },
908   { "UMAX", "Vista-T630", "umax" },
909   { "Ultima", "A6000C", "artec" },
910   { "Ultima", "A6000C PLUS", "artec" },
911   { "Ultima", "AM12S", "artec" },
912   { "Ultima", "AT12", "artec" },
913   { "Ultima", "AT3", "artec" },
914   { "Ultima", "AT6", "artec" },
915   { "Ultima", "ColorOneScanner", "artec" },
916   { "Vobis", "HighScan", "microtek2" },
917   { "Vobis", "Scanboostar Premium", "umax" },
918   { "Vuego", "Close SnapScan 310 compatible.", "SnapScan" }
919 };
920
921 static char *scanner_info(hd_t *hd)
922 {
923   int i;
924
925   if(!hd->vendor.name || !hd->device.name) return NULL;
926
927   for(i = 0; (unsigned) i < sizeof scanner_data / sizeof *scanner_data; i++) {
928     if(
929       !strcasecmp(scanner_data[i].vendor, hd->vendor.name) &&
930       !strcasecmp(scanner_data[i].model, hd->device.name)
931     ) {
932       return scanner_data[i].driver;
933     }
934   }
935
936   return NULL;
937 }
938
939 #endif
940
941 void do_test(hd_data_t *hd_data)
942 {
943 #if 1
944   hd_t *hd, *hd0;
945   hd_res_t *res;
946   driver_info_t *di;
947   FILE *f;
948   int i, wheels, buttons;
949   unsigned u;
950   uint64_t ul;
951   char *s, *s1;
952   hd_hw_item_t item, items[] = {
953     hw_display, hw_monitor, hw_tv, hw_sound, hw_mouse, hw_disk, hw_cdrom,
954     hw_floppy, hw_modem, hw_isdn, hw_scanner, hw_camera
955   };
956
957   hd_set_probe_feature(hd_data, pr_default);
958   hd_scan(hd_data);
959
960   f = fopen("/tmp/hw_overview.log", "w");
961
962   for(i = 0; (unsigned) i < sizeof items / sizeof *items; i++) {
963     item = items[i];
964     hd0 = hd_list(hd_data, item, 0, NULL);
965
966     if(!hd0) continue;
967   
968     switch(item) {
969       case hw_disk:
970         fprintf(f, "Disk\n");
971         for(hd = hd0; hd; hd = hd->next) {
972           u = 0;
973           for(res = hd->res; res; res = res->next) {
974             if(res->any.type == res_size && res->size.unit == size_unit_sectors) {
975               ul = (uint64_t) res->size.val1 * (res->size.val2 ?: 0x200);
976               u = ((ul >> 29) + 1) >> 1;
977             }
978           }
979           s = hd->bus.name;
980           fprintf(f, "  %s", hd->model);
981           if(u) {
982             fprintf(f, " (");
983             if(s) fprintf(f, "%s, ", s);
984             fprintf(f, "%u GB)", u);
985           }
986           fprintf(f, "\n");
987         }
988         fprintf(f, "\n");
989         break;
990
991       case hw_cdrom:
992         fprintf(f, "CD-ROM\n");
993         for(hd = hd0; hd; hd = hd->next) {
994           s = hd->bus.name;
995           fprintf(f, "  %s (", hd->model);
996           if(s) fprintf(f, "%s, ", s);
997           fprintf(f, "%s)", hd->prog_if.name ?: "CD-ROM");
998           fprintf(f, "\n");
999         }
1000         fprintf(f, "\n");
1001         break;
1002
1003       case hw_monitor:
1004         fprintf(f, "Monitor\n");
1005         for(hd = hd0; hd; hd = hd->next) {
1006           s = hd->model;
1007           if(!strcmp(hd->unique_id, "rdCR.EY_qmtb9YY0")) s = "not detected";
1008           fprintf(f, "  %s\n", s);
1009         }
1010         fprintf(f, "\n");
1011         break;
1012
1013       case hw_display:
1014         fprintf(f, "GFX Card\n");
1015         for(hd = hd0; hd; hd = hd->next) {
1016           u = 0;
1017           s1 = NULL;
1018           for(di = hd->driver_info; di; di = di->next) {
1019             if(di->any.type == di_x11) {
1020               if(!s1) s1 = di->x11.server;
1021               if(di->x11.x3d && !u) {
1022                 s1 = di->x11.server;
1023                 u = 1;
1024               }
1025             }
1026           }
1027           if(!s1) {
1028             s1 = "not supported";
1029             u = 0;
1030           }
1031           fprintf(f, "  %s (%s", hd->model, s1);
1032           if(u) fprintf(f, ", 3D support");
1033           fprintf(f, ")");
1034           fprintf(f, "\n");
1035         }
1036         fprintf(f, "\n");
1037         break;
1038
1039       case hw_mouse:
1040         fprintf(f, "Mouse\n");
1041         for(hd = hd0; hd; hd = hd->next) {
1042           buttons = wheels = -1;        // make gcc happy
1043           s = NULL;
1044           for(di = hd->driver_info; di; di = di->next) {
1045             if(di->any.type == di_mouse) {
1046               buttons = di->mouse.buttons;
1047               wheels = di->mouse.wheels;
1048               s = di->mouse.xf86;
1049               break;
1050             }
1051           }
1052           if(!s) {
1053             s = "not supported";
1054             buttons = wheels = -1;
1055           }
1056           fprintf(f, "  %s (%s", hd->model, s);
1057           if(buttons >= 0) fprintf(f, ", %d buttons", buttons);
1058           if(wheels >= 0) fprintf(f, ", %d wheels", wheels);
1059           fprintf(f, ")");
1060           fprintf(f, "\n");
1061         }
1062         fprintf(f, "\n");
1063         break;
1064
1065       case hw_tv:
1066         fprintf(f, "TV Card\n");
1067         for(hd = hd0; hd; hd = hd->next) {
1068           s = NULL;
1069           for(di = hd->driver_info; di; di = di->next) {
1070             if(
1071               (di->any.type == di_any || di->any.type == di_module) &&
1072               di->any.hddb0 &&
1073               di->any.hddb0->str
1074             ) {
1075               s = di->any.hddb0->str;
1076               break;
1077             }
1078           }
1079           if(!s) {
1080             s = "not supported";
1081           }
1082           fprintf(f, "  %s (%s)\n", hd->model, s);
1083         }
1084         fprintf(f, "\n");
1085         break;
1086
1087       case hw_sound:
1088         fprintf(f, "Sound Card\n");
1089         for(hd = hd0; hd; hd = hd->next) {
1090           s = NULL;
1091           for(di = hd->driver_info; di; di = di->next) {
1092             if(
1093               (di->any.type == di_any || di->any.type == di_module) &&
1094               di->any.hddb0 &&
1095               di->any.hddb0->str
1096             ) {
1097               s = di->any.hddb0->str;
1098               break;
1099             }
1100           }
1101           if(!s) {
1102             s = "not supported";
1103           }
1104           fprintf(f, "  %s (%s)\n", hd->model, s);
1105         }
1106         fprintf(f, "\n");
1107         break;
1108
1109       case hw_camera:
1110         fprintf(f, "Digital Camera/WebCam\n");
1111         for(hd = hd0; hd; hd = hd->next) {
1112           fprintf(f, "  %s\n", hd->model);
1113         }
1114         fprintf(f, "\n");
1115         break;
1116
1117       case hw_floppy:
1118         fprintf(f, "Floppy/Zip Drive\n");
1119         for(hd = hd0; hd; hd = hd->next) {
1120           fprintf(f, "  %s\n", hd->model);
1121         }
1122         fprintf(f, "\n");
1123         break;
1124
1125       case hw_modem:
1126         fprintf(f, "Modem\n");
1127         for(hd = hd0; hd; hd = hd->next) {
1128           fprintf(f, "  %s\n", hd->model);
1129         }
1130         fprintf(f, "\n");
1131         break;
1132
1133       case hw_isdn:
1134         fprintf(f, "ISDN\n");
1135         for(hd = hd0; hd; hd = hd->next) {
1136           fprintf(f, "  %s (%ssupported)\n", hd->model, hd->driver_info ? "" : "not ");
1137         }
1138         fprintf(f, "\n");
1139         break;
1140
1141       case hw_scanner:
1142         fprintf(f, "Scanner\n");
1143         for(hd = hd0; hd; hd = hd->next) {
1144           s = scanner_info(hd);
1145           if(!s) s = "not supported";
1146           fprintf(f, "  %s (%s)\n", hd->model, s);
1147         }
1148         fprintf(f, "\n");
1149         break;
1150
1151       default:
1152         break;
1153     }
1154
1155     hd_free_hd_list(hd0);
1156
1157   }
1158
1159   fclose(f);
1160
1161   f = fopen("/tmp/hw_detail.log", "w");
1162
1163   if(hd_data->log) {
1164     fprintf(f,
1165       "============ start detailed hardware log ============\n"
1166     );
1167     fprintf(f,
1168       "============ start debug info ============\n%s=========== end debug info ============\n",
1169       hd_data->log
1170     );
1171   }
1172
1173   for(hd = hd_data->hd; hd; hd = hd->next) {
1174     hd_dump_entry(hd_data, hd, f);
1175   }
1176
1177   fprintf(f,
1178     "============ end detailed hardware log ============\n"
1179   );
1180
1181   fclose(f);
1182
1183   fprintf(stderr, "\n");
1184
1185 #endif
1186
1187 #if 0
1188   hd_t *hd;
1189   hd_t *hd0 = NULL;
1190
1191   for(hd = hd_list(hd_data, hw_cdrom, 1, hd0); hd; hd = hd->next) {
1192     fprintf(stderr, "cdrom: %s, %s\n", hd->unix_dev_name, hd->model);
1193   }
1194
1195   for(hd = hd_list(hd_data, hw_cdrom, 1, hd0); hd; hd = hd->next) {
1196     fprintf(stderr, "cdrom: %s, %s\n", hd->unix_dev_name, hd->model);
1197   }
1198 #endif
1199
1200 #if 0
1201   hd_t *hd;
1202
1203   hd = hd_list(hd_data, hw_disk, 1, NULL);
1204   hd_free_hd_list(hd);
1205   hd_free_hd_data(hd_data);
1206
1207   hd = hd_list(hd_data, hw_cdrom, 1, NULL);
1208   hd_free_hd_list(hd);
1209   hd_free_hd_data(hd_data);
1210
1211   hd = hd_list(hd_data, hw_storage_ctrl, 1, NULL);
1212   hd_free_hd_list(hd);
1213   hd_free_hd_data(hd_data);
1214
1215   hd = hd_list(hd_data, hw_display, 1, NULL);
1216   hd_free_hd_list(hd);
1217   hd_free_hd_data(hd_data);
1218
1219 #if 0
1220   for(hd = hd_data->hd; hd; hd = hd->next) {
1221     hd_dump_entry(hd_data, hd, stdout);
1222   }
1223
1224   printf("%s\n", hd_data->log);
1225 #endif
1226
1227 #endif
1228
1229 #if 0
1230   hd_t *hd, *hd0;
1231
1232   hd0 = hd_list(hd_data, hw_sound, 1, NULL);
1233   hd0 = hd_list(hd_data, hw_sound, 1, NULL);
1234
1235   for(hd = hd0; hd; hd = hd->next) {
1236     hd_dump_entry(hd_data, hd, stdout);
1237   }
1238
1239 #if 0
1240   hd_data->log = free_mem(hd_data->log);
1241   dump_hddb_data(hd_data, hd_data->hddb_dev, "hddb_dev, final");  
1242   if(hd_data->log) printf("%s", hd_data->log);
1243 #endif
1244
1245 #endif
1246 }
1247
1248
1249 void help()
1250 {
1251   fprintf(stderr,
1252     "Usage: hwinfo [options]\n"
1253     "Probe for hardware.\n"
1254     "  --short        just a short listing\n"
1255     "  --log logfile  write info to logfile\n"
1256     "  --debug level  set debuglevel\n"
1257     "  --version      show libhd version\n"
1258     "  --dump-db n    dump hardware data base, 0: external, 1: internal\n"
1259     "  --hw_item      probe for hw_item\n"
1260     "  hw_item is one of:\n"
1261     "    cdrom, floppy, disk, network, gfxcard, framebuffer, monitor, camera,\n"
1262     "    mouse, joystick, keyboard, chipcard, sound, isdn, modem, storage-ctrl,\n"
1263     "    netcard, printer, tv, dvb, scanner, braille, sys, bios, cpu, partition,\n"
1264     "    usb-ctrl, usb, pci, isapnp, ide, scsi, bridge, hub, memory, smp, pppoe,\n"
1265     "    pcmcia, pcmcia-ctrl, wlan, zip, all, reallyall\n\n"
1266     "  Note: debug info is shown only in the log file. (If you specify a\n"
1267     "  log file the debug level is implicitly set to a reasonable value.)\n"
1268   );
1269 }
1270
1271
1272 /*
1273  * Parse command line options.
1274  */
1275 int get_probe_flags(int argc, char **argv, hd_data_t *hd_data)
1276 {
1277   int i, j, k;
1278   char *s, *t;
1279   for(i = 0; i < argc; i++) {
1280     s = argv[i];
1281
1282     if(!strcmp(s, ".")) {
1283       return i + 1;
1284     }
1285
1286     t = "debug=";
1287     if(!strncmp(s, t, strlen(t))) {
1288       hd_data->debug = strtol(s + strlen(t), NULL, 0);
1289       continue;
1290     }
1291
1292     t = "list=";
1293     if(!strncmp(s, t, strlen(t))) {
1294       list = s + strlen(t);
1295       continue;
1296     }
1297
1298     t = "list+=";
1299     if(!strncmp(s, t, strlen(t))) {
1300       list = s + strlen(t);
1301       listplus = 1;
1302       continue;
1303     }
1304
1305     t = "log=";
1306     if(!strncmp(s, t, strlen(t))) {
1307       log_file = s + strlen(t);
1308       continue;
1309     }
1310
1311     k = 1;
1312     if(*s == '+')
1313       s++;
1314     else if(*s == '-')
1315       k = 0, s++;
1316
1317     if((j = hd_probe_feature_by_name(s))) {
1318       if(k)
1319         hd_set_probe_feature(hd_data, j);
1320       else
1321         hd_clear_probe_feature(hd_data, j);
1322       continue;
1323     }
1324
1325     fprintf(stderr, "oops: don't know what to do with \"%s\"\n", s);
1326     return -1;
1327   }
1328
1329   return argc;
1330 }
1331
1332 /*
1333  * A simple progress function.
1334  */
1335 void progress(char *pos, char *msg)
1336 {
1337   if(!test) printf("\r%64s\r", "");
1338   printf("> %s: %s", pos, msg);
1339   if(test) printf("\n");
1340   fflush(stdout);
1341 }
1342
1343
1344 #define INSTALL_INF     "/etc/install.inf"
1345
1346 int braille_install_info(hd_data_t *hd_data)
1347 {
1348   hd_t *hd;
1349   int ok = 0;
1350   char *braille = NULL;
1351   char *braille_dev = NULL;
1352   str_list_t *sl0, *sl;
1353   FILE *f;
1354
1355   hd = hd_list(hd_data, hw_braille, 1, NULL);
1356
1357   if(hd_data->progress) {
1358     printf("\r%64s\r", "");
1359     fflush(stdout);
1360   }
1361
1362   for(; hd; hd = hd->next) {
1363     if(
1364       hd->base_class.id == bc_braille &&        /* is a braille display */
1365       hd->unix_dev_name &&                      /* and has a device name */
1366       (braille = hd->device.name)
1367     ) {
1368       braille_dev = hd->unix_dev_name;
1369       ok = 1;
1370       break;
1371     }
1372   }
1373
1374   if(!ok) return 1;
1375
1376   printf("found a %s at %s\n", braille, braille_dev);
1377
1378   sl0 = read_file(INSTALL_INF, 0, 0);
1379   f = fopen(INSTALL_INF, "w");
1380   if(!f) {
1381     perror(INSTALL_INF);
1382     return 1;
1383   }
1384   
1385   for(sl = sl0; sl; sl = sl->next) {
1386     if(
1387       strstr(sl->str, "Braille:") != sl->str &&
1388       strstr(sl->str, "Brailledevice:") != sl->str
1389     ) {
1390       fprintf(f, "%s", sl->str);
1391     }
1392   }
1393
1394   fprintf(f, "Braille: %s\n", braille);
1395   fprintf(f, "Brailledevice: %s\n", braille_dev);
1396   
1397   fclose(f);
1398
1399   return 0;
1400 }
1401
1402
1403 /*
1404  * get VGA parameter from /proc/cmdline
1405  */
1406 int get_fb_mode()
1407 {
1408 #ifndef __PPC__
1409   FILE *f;
1410   char buf[256], *s, *t;
1411   int i, fb_mode = 0;
1412
1413   if((f = fopen("/proc/cmdline", "r"))) {
1414     if(fgets(buf, sizeof buf, f)) {
1415       t = buf;
1416       while((s = strsep(&t, " "))) {
1417         if(sscanf(s, "vga=%i", &i) == 1) fb_mode = i;
1418         if(strstr(s, "vga=normal") == s) fb_mode = 0;
1419       }
1420     }
1421     fclose(f);
1422   }
1423
1424   return fb_mode > 0x10 ? fb_mode : 0;
1425 #else /* __PPC__ */
1426   /* this is the only valid test for active framebuffer ... */
1427   FILE *f = NULL;
1428   int fb_mode = 0;
1429   if((f = fopen("/dev/fb", "r"))) {
1430     fb_mode++;
1431     fclose(f);
1432   }
1433
1434   return fb_mode;
1435 #endif
1436 }
1437
1438
1439 /*
1440  * read "x11i=" entry from /proc/cmdline
1441  */
1442 char *get_x11i()
1443 {
1444   FILE *f;
1445   char buf[256], *s, *t;
1446   static char x11i[64] = { };
1447
1448   if(!*x11i) return x11i;
1449
1450   if((f = fopen("/proc/cmdline", "r"))) {
1451     if(fgets(buf, sizeof buf, f)) {
1452       t = buf;
1453       while((s = strsep(&t, " "))) {
1454         if(sscanf(s, "x11i=%60s", x11i) == 1) break;
1455       }
1456     }
1457     fclose(f);
1458   }
1459
1460   return x11i;
1461 }
1462
1463
1464 /*
1465  * Assumes xf86_ver to be either "3" or "4" (or empty).
1466  */
1467 char *get_xserver(hd_data_t *hd_data, char **version, char **busid, driver_info_t **x11_driver)
1468 {
1469   static char display[16];
1470   static char xf86_ver[2];
1471   static char id[32];
1472   char c, *x11i = get_x11i();
1473   driver_info_t *di;
1474   hd_t *hd;
1475
1476   *x11_driver = NULL;
1477
1478   *display = *xf86_ver = *id = c = 0;
1479   *version = xf86_ver;
1480   *busid = id;
1481
1482   if(x11i) {
1483     if(*x11i == '3' || *x11i == '4') {
1484       c = *x11i;
1485     }
1486     else {
1487       if(*x11i >= 'A' && *x11i <= 'Z') {
1488         c = '3';
1489       }
1490       if(*x11i >= 'a' && *x11i <= 'z') {
1491         c = '4';
1492       }
1493       if(c) {
1494         strncpy(display, x11i, sizeof display - 1);
1495         display[sizeof display - 1] = 0;
1496       }
1497     }
1498   }
1499
1500   if(c) { xf86_ver[0] = c; xf86_ver[1] = 0; }
1501
1502   hd = hd_get_device_by_idx(hd_data, hd_display_adapter(hd_data));
1503
1504   if(hd && hd->bus.id == bus_pci)
1505     sprintf(id, "%d:%d:%d", hd->slot >> 8, hd->slot & 0xff, hd->func);
1506
1507   if(!hd || *display) return display;
1508
1509   for(di = hd->driver_info; di; di = di->next) {
1510     if(di->any.type == di_x11 && di->x11.server && di->x11.xf86_ver && !di->x11.x3d) {
1511       if(c == 0 || c == di->x11.xf86_ver[0]) {
1512         xf86_ver[0] = di->x11.xf86_ver[0];
1513         xf86_ver[1] = 0;
1514         strncpy(display, di->x11.server, sizeof display - 1);
1515         display[sizeof display - 1] = 0;
1516         *x11_driver = di;
1517         break;
1518       }
1519     }
1520   }
1521
1522
1523   if(*display) return display;
1524
1525   if(c == 0) c = '4';   /* default to XF 4, if nothing else is known  */
1526
1527   xf86_ver[0] = c;
1528   xf86_ver[1] = 0;
1529   strcpy(display, c == '3' ? "FBDev" : "fbdev");
1530
1531   return display;
1532 }
1533
1534 int x11_install_info(hd_data_t *hd_data)
1535 {
1536   hd_t *hd;
1537   driver_info_t *di;
1538   char *x11i;
1539   int fb_mode, kbd_ok = 0;
1540   unsigned yast2_color = 0;
1541   char *xkbrules = NULL, *xkbmodel = NULL, *xkblayout = NULL;
1542   char *xserver, *version, *busid;
1543   driver_info_t *x11_driver;
1544   str_list_t *sl0, *sl;
1545   FILE *f;
1546
1547   /* get color info */
1548   hd_set_probe_feature(hd_data, pr_cpu);
1549   hd_set_probe_feature(hd_data, pr_prom);
1550   hd_scan(hd_data);
1551
1552   x11i = get_x11i();
1553   fb_mode = get_fb_mode();
1554
1555   hd_list(hd_data, hw_display, 1, NULL);
1556
1557   for(hd = hd_list(hd_data, hw_keyboard, 1, NULL); hd; hd = hd->next) {
1558     kbd_ok = 1;
1559     di = hd->driver_info;
1560     if(di && di->any.type == di_kbd) {
1561       xkbrules = di->kbd.XkbRules;
1562       xkbmodel = di->kbd.XkbModel;
1563       xkblayout = di->kbd.XkbLayout;
1564       break;
1565     }
1566     /* don't free di */
1567   }
1568   
1569   xserver = get_xserver(hd_data, &version, &busid, &x11_driver);
1570
1571   switch(hd_mac_color(hd_data)) {
1572     case 0x01:
1573       yast2_color = 0x5a4add;
1574       break;
1575     case 0x04:
1576       yast2_color = 0x32cd32;
1577       break;
1578     case 0x05:
1579       yast2_color = 0xff7f50;
1580       break;
1581     case 0x07:
1582       yast2_color = 0x000000;
1583       break;
1584     case 0xff:
1585       yast2_color = 0x7f7f7f;
1586       break;
1587   }
1588
1589   if(hd_data->progress) {
1590     printf("\r%64s\r", "");
1591     fflush(stdout);
1592   }
1593
1594   sl0 = read_file(INSTALL_INF, 0, 0);
1595   f = fopen(INSTALL_INF, "w");
1596   if(!f) {
1597     perror(INSTALL_INF);
1598     return 1;
1599   }
1600   
1601   for(sl = sl0; sl; sl = sl->next) {
1602     if(
1603       strstr(sl->str, "Framebuffer:") != sl->str &&
1604       strstr(sl->str, "XServer:") != sl->str &&
1605       strstr(sl->str, "XVersion:") != sl->str &&
1606       strstr(sl->str, "XBusID:") != sl->str &&
1607       strstr(sl->str, "X11i:") != sl->str &&
1608       strstr(sl->str, "Keyboard:") != sl->str &&
1609       strstr(sl->str, "XkbRules:") != sl->str &&
1610       strstr(sl->str, "XkbModel:") != sl->str &&
1611       strstr(sl->str, "XkbLayout:") != sl->str &&
1612       strstr(sl->str, "XF86Ext:") != sl->str &&
1613       strstr(sl->str, "XF86Raw:") != sl->str
1614     ) {
1615       fprintf(f, "%s", sl->str);
1616     }
1617   }
1618
1619   fprintf(f, "Keyboard: %d\n", kbd_ok);
1620   if(fb_mode) fprintf(f, "Framebuffer: 0x%04x\n", fb_mode);
1621   if(x11i) fprintf(f, "X11i: %s\n", x11i);
1622   if(xserver && *xserver) {
1623     fprintf(f, "XServer: %s\n", xserver);
1624     if(*version) fprintf(f, "XVersion: %s\n", version);
1625     if(*busid) fprintf(f, "XBusID: %s\n", busid);
1626   }
1627   if(xkbrules && *xkbrules) fprintf(f, "XkbRules: %s\n", xkbrules);
1628   if(xkbmodel && *xkbmodel) fprintf(f, "XkbModel: %s\n", xkbmodel);
1629   if(xkblayout && *xkblayout) fprintf(f, "XkbLayout: %s\n", xkblayout);
1630
1631   if(x11_driver) {
1632     for(sl = x11_driver->x11.extensions; sl; sl = sl->next) {
1633       if(*sl->str) fprintf(f, "XF86Ext:   Load\t\t\"%s\"\n", sl->str);
1634     }
1635     for(sl = x11_driver->x11.options; sl; sl = sl->next) {
1636       if(*sl->str) fprintf(f, "XF86Raw:   Option\t\"%s\"\n", sl->str);
1637     }
1638     for(sl = x11_driver->x11.raw; sl; sl = sl->next) {
1639       if(*sl->str) fprintf(f, "XF86Raw:   %s\n", sl->str);
1640     }
1641   }
1642
1643   fclose(f);
1644
1645   return 0;
1646 }
1647
1648
1649 char *xserver3map[] =
1650 {
1651 #ifdef __i386__
1652   "VGA16", "xvga16",
1653   "RUSH", "xrush",
1654 #endif
1655 #if defined(__i386__) || defined(__alpha__) || defined(__ia64__)
1656   "SVGA", "xsvga",
1657   "3DLABS", "xglint",
1658 #endif
1659 #if defined(__i386__) || defined(__alpha__)
1660   "MACH64", "xmach64",
1661   "P9000", "xp9k",
1662   "S3", "xs3",
1663 #endif
1664 #ifdef __alpha__
1665   "TGA", "xtga",
1666 #endif
1667 #ifdef __sparc__
1668   "SUNMONO", "xsunmono",
1669   "SUN", "xsun",
1670   "SUN24", "xsun24",
1671 #endif
1672 #if 0
1673   "VMWARE", "xvmware",
1674 #endif
1675   0, 0
1676 };
1677
1678
1679 void dump_packages(hd_data_t *hd_data)
1680 {
1681   str_list_t *sl;
1682   int i;
1683
1684   hd_data->progress = NULL;
1685   hd_scan(hd_data);
1686
1687   sl = get_hddb_packages(hd_data);
1688
1689   for(i = 0; xserver3map[i]; i += 2) {
1690     if (!search_str_list(sl, xserver3map[i + 1]))
1691       add_str_list(&sl, new_str(xserver3map[i + 1]));
1692   }
1693
1694   for(; sl; sl = sl->next) {
1695     printf("%s\n", sl->str);
1696   }
1697 }
1698
1699
1700 struct x11pack {
1701   struct x11pack *next;
1702   char *pack;
1703 };
1704
1705 int oem_install_info(hd_data_t *hd_data)
1706 {
1707   hd_t *hd;
1708   str_list_t *str;
1709   str_list_t *x11packs = 0;
1710   str_list_t *sl0, *sl;
1711   FILE *f;
1712   int pcmcia, i;
1713
1714   driver_info_x11_t *di, *drvinfo;
1715
1716   hd_set_probe_feature(hd_data, pr_pci);
1717   hd_scan(hd_data);
1718   pcmcia = hd_has_pcmcia(hd_data);
1719
1720   for(hd = hd_list(hd_data, hw_display, 1, NULL); hd; hd = hd->next) {
1721     for(str = hd->requires; str; str = str->next) {
1722       if(!search_str_list(x11packs, str->str)) {
1723         add_str_list(&x11packs, str->str);
1724       }
1725     }
1726     drvinfo = (driver_info_x11_t *) hd->driver_info;
1727     for (di = drvinfo; di; di = (driver_info_x11_t *)di->next) {
1728       if (di->type != di_x11)
1729         continue;
1730       if (di->xf86_ver[0] == '3') {
1731         char *server = di->server;
1732         if (server) {
1733           for (i = 0; xserver3map[i]; i += 2)
1734             if (!strcmp(xserver3map[i], server))
1735               break;
1736           if (xserver3map[i])
1737             if (!search_str_list(x11packs, xserver3map[i + 1]))
1738               add_str_list(&x11packs, xserver3map[i + 1]);
1739         }
1740       }
1741     }
1742   }
1743
1744   if(hd_data->progress) {
1745     printf("\r%64s\r", "");
1746     fflush(stdout);
1747   }
1748
1749   sl0 = read_file(INSTALL_INF, 0, 0);
1750   f = fopen(INSTALL_INF, "w");
1751   if(!f) {
1752     perror(INSTALL_INF);
1753     return 1;
1754   }
1755   for(sl = sl0; sl; sl = sl->next) {
1756     if(
1757       strstr(sl->str, "X11Packages:") != sl->str &&
1758       strstr(sl->str, "Pcmcia:") != sl->str
1759     ) {
1760       fprintf(f, "%s", sl->str);
1761     }
1762   }
1763   if (x11packs) {
1764     fprintf(f, "X11Packages: ");
1765     for (sl = x11packs; sl; sl = sl->next) {
1766       if (sl != x11packs)
1767         fputc(',', f);
1768       fprintf(f, "%s", sl->str);
1769     }
1770     fputc('\n', f);
1771   }
1772   if (pcmcia)
1773     fprintf(f, "Pcmcia: %d\n", pcmcia);
1774   fclose(f);
1775   return 0;
1776 }
1777
1778
1779 void dump_db_raw(hd_data_t *hd_data)
1780 {
1781   hd_data->progress = NULL;
1782   hd_clear_probe_feature(hd_data, pr_all);
1783   hd_scan(hd_data);
1784
1785   if(opt.db_idx >= sizeof hd_data->hddb2 / sizeof *hd_data->hddb2) return;
1786
1787   hddb_dump_raw(hd_data->hddb2[opt.db_idx], stdout);
1788 }
1789
1790
1791 void dump_db(hd_data_t *hd_data)
1792 {
1793   hd_data->progress = NULL;
1794   hd_clear_probe_feature(hd_data, pr_all);
1795   hd_scan(hd_data);
1796
1797   if(opt.db_idx >= sizeof hd_data->hddb2 / sizeof *hd_data->hddb2) return;
1798
1799   hddb_dump(hd_data->hddb2[opt.db_idx], stdout);
1800 }
1801