This commit was manufactured by cvs2svn to create tag 'hwinfo-8_12'.
[opensuse:hwinfo.git] / hwscan.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <getopt.h>
6
7 #include "hd.h"
8
9 struct option options[] = {
10   { "help", 0, NULL, 'h' },
11   { "verbose", 0, NULL, 'v' },
12   { "version", 0, NULL, 400 },
13   { "show", 1, NULL, 500 },
14   { "list", 0, NULL, 501 },
15   { "cfg", 1, NULL, 502 },
16   { "avail", 1, NULL, 503 },
17   { "need", 1, NULL, 504 },
18   { "new", 0, NULL, 505 },
19   { "fast", 0, NULL, 506 },
20   { "silent", 0, NULL, 507 },
21   { "boot", 0, NULL, 508 },
22   { "active", 1, NULL, 509 },
23   { "sys", 0, NULL, 1000 + hw_sys },
24   { "cpu", 0, NULL, 1000 + hw_cpu },
25   { "keyboard", 0, NULL, 1000 + hw_keyboard },
26   { "braille", 0, NULL, 1000 + hw_braille },
27   { "mouse", 0, NULL, 1000 + hw_mouse },
28   { "joystick", 0, NULL, 1000 + hw_joystick },
29   { "printer", 0, NULL, 1000 + hw_printer },
30   { "scanner", 0, NULL, 1000 + hw_scanner },
31   { "chipcard", 0, NULL, 1000 + hw_chipcard },
32   { "monitor", 0, NULL, 1000 + hw_monitor },
33   { "tv", 0, NULL, 1000 + hw_tv },
34   { "gfxcard", 0, NULL, 1000 + hw_display },
35   { "framebuffer", 0, NULL, 1000 + hw_framebuffer },
36   { "camera", 0, NULL, 1000 + hw_camera },
37   { "sound", 0, NULL, 1000 + hw_sound },
38   { "storage-ctrl", 0, NULL, 1000 + hw_storage_ctrl },
39   { "storage_ctrl", 0, NULL, 1000 + hw_storage_ctrl },
40   { "netcard", 0, NULL, 1000 + hw_network_ctrl },
41   { "network-ctrl", 0, NULL, 1000 + hw_network_ctrl },
42   { "network_ctrl", 0, NULL, 1000 + hw_network_ctrl },
43   { "isdn", 0, NULL, 1000 + hw_isdn },
44   { "modem", 0, NULL, 1000 + hw_modem },
45   { "network", 0, NULL, 1000 + hw_network },
46   { "disk", 0, NULL, 1000 + hw_disk },
47   { "partition", 0, NULL, 1000 + hw_partition },
48   { "cdrom", 0, NULL, 1000 + hw_cdrom },
49   { "floppy", 0, NULL, 1000 + hw_floppy },
50   { "update", 0, NULL, 1000 + hw_manual },
51   { "usb-ctrl", 0, NULL, 1000 + hw_usb_ctrl },
52   { "usb_ctrl", 0, NULL, 1000 + hw_usb_ctrl },
53   { "usb", 0, NULL, 1000 + hw_usb },
54   { "bios", 0, NULL, 1000 + hw_bios },
55   { "pci", 0, NULL, 1000 + hw_pci },
56   { "isapnp", 0, NULL, 1000 + hw_isapnp },
57   { "bridge", 0, NULL, 1000 + hw_bridge },
58   { "hub", 0, NULL, 1000 + hw_hub },
59   { "scsi", 0, NULL, 1000 + hw_scsi },
60   { "ide", 0, NULL, 1000 + hw_ide },
61   { "memory", 0, NULL, 1000 + hw_memory },
62   { "dvb", 0, NULL, 1000 + hw_dvb },
63   { "pcmcia", 0, NULL, 1000 + hw_pcmcia },
64   { "pcmcia_ctrl", 0, NULL, 1000 + hw_pcmcia_ctrl },
65   { "ieee1394", 0, NULL, 1000 + hw_ieee1394 },
66   { "firewire", 0, NULL, 1000 + hw_ieee1394 },
67   { "ieee1394_ctrl", 0, NULL, 1000 + hw_ieee1394_ctrl },
68   { "firewire_ctrl", 0, NULL, 1000 + hw_ieee1394_ctrl },
69   { "hotplug", 0, NULL, 1000 + hw_hotplug },
70   { "hotplug_ctrl", 0, NULL, 1000 + hw_hotplug_ctrl },
71   { "zip", 0, NULL, 1000 + hw_zip },
72   { "pppoe", 0, NULL, 1000 + hw_pppoe },
73   { "dsl", 0, NULL, 1000 + hw_pppoe },
74   { "wlan", 0, NULL, 1000 + hw_wlan },
75   { "all", 0, NULL, 1000 + hw_all },
76   { }
77 };
78
79 int verbose = 0;
80 hd_hw_item_t scan_item[100] = { };
81 unsigned scan_items = 0;
82 int found_items = 0;
83
84 struct {
85   unsigned show:1;
86   unsigned scan:1;
87   unsigned list:1;
88   unsigned config_cfg:1;
89   unsigned config_avail:1;
90   unsigned config_need:1;
91   unsigned config_active:1;
92   unsigned new:1;
93   unsigned fast:1;
94   unsigned silent:1;
95   unsigned boot:1;
96 } opt;
97
98 void help(void);
99 int do_scan(hd_hw_item_t *items);
100 int do_show(char *id);
101 int do_list(hd_hw_item_t *items);
102 int do_config(int type, char *val, char *id);
103 int fast_ok(hd_hw_item_t *items);
104 int has_item(hd_hw_item_t *items, hd_hw_item_t item);
105 int has_hw_class(hd_t *hd, hd_hw_item_t *items);
106
107
108 int main(int argc, char **argv)
109 {
110   int rc = 0;
111
112 #ifndef LIBHD_TINY
113
114   char *id = NULL;
115   char *config_cfg = NULL;
116   char *config_avail = NULL;
117   char *config_need = NULL;
118   char *config_active = NULL;
119   int i;
120   int ok = 0;
121   FILE *f;
122
123   opterr = 0;
124
125   while((i = getopt_long(argc, argv, "hv", options, NULL)) != -1) {
126     switch(i) {
127       case 'v':
128         verbose++;
129         break;
130
131       case 400:
132         printf("%s\n", hd_version());
133         ok = 1;
134         break;
135
136       case 500:
137         opt.show = 1;
138         id = optarg;
139         break;
140
141       case 501:
142         opt.list = 1;
143         break;
144
145       case 502:
146         opt.config_cfg = 1;
147         config_cfg = optarg;
148         break;
149
150       case 503:
151         opt.config_avail = 1;
152         config_avail = optarg;
153         break;
154
155       case 504:
156         opt.config_need = 1;
157         config_need = optarg;
158         break;
159
160       case 505:
161         opt.new = 1;
162         break;
163
164       case 506:
165         opt.fast = 1;
166         break;
167
168       case 507:
169         opt.silent = 1;
170         break;
171
172       case 508:
173         opt.boot = 1;
174         break;
175
176       case 509:
177         opt.config_active = 1;
178         config_active = optarg;
179         break;
180
181       case 1000 ... 1100:
182         opt.scan = 1;
183         if(scan_items + 1 < sizeof scan_item / sizeof *scan_item) {
184           scan_item[scan_items++] = i - 1000;
185         }
186         break;
187
188       default:
189         help();
190         return 1;
191     }
192   }
193
194   scan_item[scan_items] = 0;
195
196   if(opt.scan && !opt.list) {
197     if(argv[optind] || !scan_items) return help(), 1;
198     rc = do_scan(scan_item);
199     if(found_items) {
200       unlink(HARDWARE_DIR "/.update");          /* the old file */
201       unlink(HARDWARE_UNIQUE_KEYS "/.update");  /* so we trigger a rescan */
202       if((f = fopen(HARDWARE_UNIQUE_KEYS "/.update", "a"))) fclose(f);
203     }
204     ok = 1;
205   }
206
207   if(opt.show) {
208     do_show(id);
209     ok = 1;
210   }
211
212   if(opt.list) {
213     do_list(scan_item);
214     ok = 1;
215   }
216
217   if(opt.config_cfg) {
218     if(!argv[optind]) return help(), 1;
219     do_config(1, config_cfg, argv[optind]);
220     ok = 1;
221   }
222
223   if(opt.config_avail) {
224     if(!argv[optind]) return help(), 1;
225     do_config(2, config_avail, argv[optind]);
226     ok = 1;
227   }
228
229   if(opt.config_need) {
230     if(!argv[optind]) return help(), 1;
231     do_config(3, config_need, argv[optind]);
232     ok = 1;
233   }
234
235   if(opt.config_active) {
236     if(!argv[optind]) return help(), 1;
237     do_config(4, config_active, argv[optind]);
238     ok = 1;
239   }
240
241   if(!ok) help();
242
243 #endif          /* !defined(LIBHD_TINY) */
244
245   return rc;
246 }
247
248 void help()
249 {
250   fprintf(stderr,
251     "Usage: hwscan [options]\n"
252     "Show information about currently known hardware.\n"
253     "  --list            show list of known hardware\n"
254     "  --version         show libhd version\n"
255     "  --silent          don't show hardware config changes\n"
256     "  --boot            run only if we haven't been disabled via 'hwprobe=-scan'\n"
257     "  --cfg=state id    change 'configured' status; id is one of the\n"
258     "                    ids from 'hwscan --list'\n"
259     "                    state is one of new, no, yes\n"
260     "  --avail=state id  change 'available' status\n"
261     "  --need=state id   change 'needed' status\n"
262     "  --active=state id change 'active' status\n"
263     "  --hw_item         probe for hw_item and update status info\n"
264     "  hw_item is one of:\n"
265     "    cdrom, floppy, disk, network, gfxcard, framebuffer, monitor, camera,\n"
266     "    mouse, joystick, keyboard, chipcard, sound, isdn, modem, storage-ctrl,\n"
267     "    netcard, printer, tv, dvb, scanner, braille, sys, bios, cpu, partition,\n"
268     "    usb-ctrl, usb, pci, isapnp, ide, scsi, bridge, hub, memory, smp, pppoe,\n"
269     "    pcmcia, pcmcia-ctrl, wlan, zip\n"
270   );
271 }
272
273 #ifndef LIBHD_TINY
274
275 int do_scan(hd_hw_item_t *items)
276 {
277   int run_config = 0;
278   hd_status_t status = { };
279   hd_data_t *hd_data;
280   hd_t *hd, *hd1;
281   int err = 0;
282
283   if(opt.fast) opt.fast = fast_ok(items);
284
285   hd_data = calloc(1, sizeof *hd_data);
286
287   if(opt.boot) {
288     /* look if we have been disabled */
289     hd_clear_probe_feature(hd_data, pr_all);
290     hd_scan(hd_data);
291     hd_set_probe_feature(hd_data, pr_scan);
292     if(!hd_probe_feature(hd_data, pr_scan)) {
293       hd_free_hd_data(hd_data);
294       free(hd_data);
295       return 0;
296     }
297   }
298
299   hd_data->flags.list_all = 1;
300   hd_data->flags.fast = opt.fast;
301
302   hd = hd_list2(hd_data, items, 1);
303
304   if(hd) found_items = 1;
305
306   for(hd1 = hd; hd1; hd1 = hd1->next) {
307     err = hd_write_config(hd_data, hd1);
308     if(verbose >= 2) {
309       printf(
310         "write=%d %s: (cfg=%s, avail=%s, need=%s, active=%s",
311         err,
312         hd1->unique_id,
313         hd_status_value_name(hd1->status.configured),
314         hd_status_value_name(hd1->status.available),
315         hd_status_value_name(hd1->status.needed),
316         hd_status_value_name(hd1->status.active)
317       );
318       if(hd1->unix_dev_name) {
319         printf(", dev=%s", hd1->unix_dev_name);
320       }
321       printf(
322         ") %s\n",
323         hd1->model
324       );
325       
326     }
327     if(err) break;
328   }
329
330   if(err) {
331     fprintf(stderr,
332       "Error writing configuration for %s (%s)\n",
333       hd1->unique_id,
334       hd1->model
335     );
336     exit(1);
337   }
338
339   hd = hd_free_hd_list(hd);
340
341   if(opt.new) {
342     status.configured = status_new;
343   }
344   else {
345     status.reconfig = status_yes;
346   }
347
348   hd = hd_list_with_status2(hd_data, items, status);
349   if(hd) run_config = 1;
350
351   if(verbose) {
352     for(hd1 = hd; hd1; hd1 = hd1->next) {
353       printf(
354         "%s: (cfg=%s, avail=%s, need=%s, active=%s",
355         hd1->unique_id,
356         hd_status_value_name(hd1->status.configured),
357         hd_status_value_name(hd1->status.available),
358         hd_status_value_name(hd1->status.needed),
359         hd_status_value_name(hd1->status.active)
360       );
361       if(hd1->unix_dev_name) {
362         printf(", dev=%s", hd1->unix_dev_name);
363       }
364       printf(
365         ") %s\n",
366         hd1->model
367       );
368     }
369   }
370   else if(!opt.silent) {
371     for(hd1 = hd; hd1; hd1 = hd1->next) printf("%s\n", hd1->unique_id);
372   }
373
374   hd = hd_free_hd_list(hd);
375
376   hd_free_hd_data(hd_data);
377   free(hd_data);
378
379   return run_config ^ 1;
380 }
381
382
383 int do_show(char *id)
384 {
385   hd_data_t *hd_data;
386   hd_t *hd;
387
388   hd_data = calloc(1, sizeof *hd_data);
389
390   hd = hd_read_config(hd_data, id);
391
392   if(hd) {
393     hd_data->debug = -1;
394     hd_dump_entry(hd_data, hd, stdout);
395     hd = hd_free_hd_list(hd);
396   }
397   else {
398     printf("no such hardware item: %s\n", id);
399   }
400
401   hd_free_hd_data(hd_data);
402   free(hd_data);
403
404   return 0;
405 }
406
407
408 int do_list(hd_hw_item_t *items)
409 {
410   hd_data_t *hd_data;
411   hd_t *hd, *hd_manual;
412   char *s;
413   char status[64];
414   int i;
415
416   hd_data = calloc(1, sizeof *hd_data);
417
418   hd_manual = hd_list(hd_data, hw_manual, 1, NULL);
419
420   for(hd = hd_manual; hd; hd = hd->next) {
421     if(opt.scan && ! has_hw_class(hd, items)) continue;
422
423     strcpy(status, "(");
424
425     i = 0;
426     if(hd->status.configured && (s = hd_status_value_name(hd->status.configured))) {
427       sprintf(status + strlen(status), "%scfg=%s", i ? ", " : "", s);
428       i++;
429     }
430
431     if(hd->status.available && (s = hd_status_value_name(hd->status.available))) {
432       sprintf(status + strlen(status), "%savail=%s", i ? ", " : "", s);
433       i++;
434     }
435
436     if(hd->status.needed && (s = hd_status_value_name(hd->status.needed))) {
437       sprintf(status + strlen(status), "%sneed=%s", i ? ", " : "", s);
438       i++;
439     }
440
441     if(hd->status.active && (s = hd_status_value_name(hd->status.active))) {
442       sprintf(status + strlen(status), "%sactive=%s", i ? ", " : "", s);
443       i++;
444     }
445
446     strcat(status, ")");
447
448     s = hd_hw_item_name(hd->hw_class);
449     if(!s) s = "???";
450
451     printf("%s: %-32s %-16s %s\n", hd->unique_id, status, s, hd->model);
452     if(hd->config_string) {
453       printf("   configured as: \"%s\"\n", hd->config_string);
454     }
455   }
456
457   hd_free_hd_list(hd_manual);
458
459   hd_free_hd_data(hd_data);
460   free(hd_data);
461
462   return 0;
463 }
464
465
466 int do_config(int type, char *val, char *id)
467 {
468   hd_data_t *hd_data;
469   hd_t *hd;
470   hd_status_value_t status = 0;
471   int i;
472   char *s;
473
474   hd_data = calloc(1, sizeof *hd_data);
475
476   hd = hd_read_config(hd_data, id);
477
478   if(hd) {
479     for(i = 1; i < 8; i++) {
480       s = hd_status_value_name(i);
481       if(s && !strcmp(val, s)) {
482         status = i;
483         break;
484       }
485     }
486     if(!status) {
487       printf("invalid status: %s\n", val);
488     }
489     else {
490       switch(type) {
491         case 1:
492           hd->status.configured = status;
493           break;
494
495         case 2:
496           hd->status.available = status;
497           break;
498
499         case 3:
500           hd->status.needed = status;
501           break;
502
503         case 4:
504           hd->status.active = status;
505           break;
506       }
507       hd_write_config(hd_data, hd);
508     }
509     hd = hd_free_hd_list(hd);
510   }
511   else {
512     printf("no such hardware item: %s\n", id);
513   }
514
515   hd_free_hd_data(hd_data);
516   free(hd_data);
517
518   return 0;
519 }
520
521
522 /*
523  * Check whether a 'fast' scan would suffice to re-check the presence
524  * of all known hardware.
525  */
526 int fast_ok(hd_hw_item_t *items)
527 {
528   hd_data_t *hd_data;
529   hd_t *hd, *hd1;
530   int ok = 1;
531
532   if(!has_item(items, hw_mouse) && !has_item(items, hw_storage_ctrl)) {
533     return 1;
534   }
535
536   hd_data = calloc(1, sizeof *hd_data);
537
538   hd_data->flags.list_all = 1;
539
540   hd = hd_list(hd_data, hw_manual, 1, NULL);
541
542   for(hd1 = hd; hd1; hd1 = hd1->next) {
543     /* serial mice */
544     if(hd1->hw_class == hw_mouse && hd1->bus.id == bus_serial) {
545       ok = 0;
546       break;
547     }
548     /* parallel zip */
549     if(hd1->hw_class == hw_storage_ctrl && hd1->bus.id == bus_parallel) {
550       ok = 0;
551       break;
552     }
553   }
554
555   hd_free_hd_data(hd_data);
556   free(hd_data);
557
558   return ok;
559 }
560
561
562 /* check if item is in items */
563 int has_item(hd_hw_item_t *items, hd_hw_item_t item)
564 {
565   while(*items) if(*items++ == item) return 1;
566
567   return 0;
568 }
569
570
571 /* check if one of items is in hw_class */
572 int has_hw_class(hd_t *hd, hd_hw_item_t *items)
573 {
574   while(*items) if(hd_is_hw_class(hd, *items++)) return 1;
575
576   return 0;
577 }
578
579
580 #endif          /* !defined(LIBHD_TINY) */