]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/hwinfo/src/hd/manual.c
Signierten GPG-Schluessel importiert.
[people/pmueller/ipfire-2.x.git] / src / hwinfo / src / hd / manual.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <dirent.h>
6 #include <ctype.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9
10 #include "hd.h"
11 #include "hd_int.h"
12 #include "manual.h"
13 #include "hddb.h"
14
15 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
16 *
17 * hardware in /var/lib/hardware/
18 *
19 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
20 */
21
22 typedef struct {
23 int key;
24 char *value;
25 } hash_t;
26
27 /* corresponds to hd_status_value_t */
28 static hash_t status_names[] = {
29 { status_no, "no" },
30 { status_yes, "yes" },
31 { status_unknown, "unknown" },
32 { status_new, "new" },
33 { 0, NULL }
34 };
35
36 /* corresponds to hd_hw_item_t */
37 static hash_t hw_items[] = {
38 { hw_sys, "system" },
39 { hw_cpu, "cpu" },
40 { hw_keyboard, "keyboard" },
41 { hw_braille, "braille" },
42 { hw_mouse, "mouse" },
43 { hw_joystick, "joystick" },
44 { hw_printer, "printer" },
45 { hw_scanner, "scanner" },
46 { hw_chipcard, "chipcard" },
47 { hw_monitor, "monitor" },
48 { hw_tv, "tv card" },
49 { hw_display, "graphics card" },
50 { hw_framebuffer, "framebuffer" },
51 { hw_camera, "camera" },
52 { hw_sound, "sound" },
53 { hw_storage_ctrl, "storage" },
54 { hw_network_ctrl, "network" },
55 { hw_isdn, "isdn adapter" },
56 { hw_modem, "modem" },
57 { hw_network, "network interface" },
58 { hw_disk, "disk" },
59 { hw_partition, "partition" },
60 { hw_cdrom, "cdrom" },
61 { hw_floppy, "floppy" },
62 { hw_manual, "manual" },
63 { hw_usb_ctrl, "usb controller" },
64 { hw_usb, "usb" },
65 { hw_bios, "bios" },
66 { hw_pci, "pci" },
67 { hw_isapnp, "isapnp" },
68 { hw_bridge, "bridge" },
69 { hw_hub, "hub" },
70 { hw_scsi, "scsi" },
71 { hw_ide, "ide" },
72 { hw_memory, "memory" },
73 { hw_dvb, "dvb card" },
74 { hw_pcmcia, "pcmcia" },
75 { hw_pcmcia_ctrl, "pcmcia controller" },
76 { hw_ieee1394, "firewire" },
77 { hw_ieee1394_ctrl, "firewire controller" },
78 { hw_hotplug, "hotplug" },
79 { hw_hotplug_ctrl, "hotplug controller" },
80 { hw_zip, "zip" },
81 { hw_pppoe, "pppoe" },
82 { hw_wlan, "wlan card" },
83 { hw_dsl, "DSL adapter" },
84 { hw_block, "block device" },
85 { hw_tape, "tape" },
86 { hw_vbe, "vesa bios" },
87 { hw_bluetooth, "bluetooth" },
88 { hw_unknown, "unknown" },
89 { 0, NULL }
90 };
91
92 typedef enum {
93 hw_id_unique = 1, hw_id_parent, hw_id_child, hw_id_hwclass, hw_id_model,
94 hw_id_configured, hw_id_available, hw_id_needed, hw_id_cfgstring, hw_id_active
95 } hw_id_t;
96
97 #ifndef LIBHD_TINY
98
99 #define MAN_SECT_GENERAL "General"
100 #define MAN_SECT_STATUS "Status"
101 #define MAN_SECT_HARDWARE "Hardware"
102
103 static hash_t hw_ids_general[] = {
104 { hw_id_unique, "UniqueID" },
105 { hw_id_parent, "ParentID" },
106 { hw_id_child, "ChildIDs" },
107 { hw_id_hwclass, "HWClass" },
108 { hw_id_model, "Model" },
109 { 0, NULL }
110 };
111
112 static hash_t hw_ids_status[] = {
113 { hw_id_configured, "Configured" },
114 { hw_id_available, "Available" },
115 { hw_id_needed, "Needed" },
116 { hw_id_cfgstring, "ConfigString" },
117 { hw_id_active, "Active" },
118 { 0, NULL }
119 };
120
121 /* structure elements from hd_t */
122 typedef enum {
123 hwdi_bus = 1, hwdi_slot, hwdi_func, hwdi_base_class, hwdi_sub_class,
124 hwdi_prog_if, hwdi_dev, hwdi_vend, hwdi_sub_dev, hwdi_sub_vend, hwdi_rev,
125 hwdi_compat_dev, hwdi_compat_vend, hwdi_dev_name, hwdi_vend_name,
126 hwdi_sub_dev_name, hwdi_sub_vend_name, hwdi_rev_name, hwdi_serial,
127 hwdi_unix_dev_name, hwdi_unix_dev_name2, hwdi_unix_dev_names, hwdi_rom_id,
128 hwdi_broken, hwdi_usb_guid, hwdi_res_mem, hwdi_res_phys_mem, hwdi_res_io,
129 hwdi_res_irq, hwdi_res_dma, hwdi_res_size, hwdi_res_baud, hwdi_res_cache,
130 hwdi_res_disk_geo, hwdi_res_monitor, hwdi_res_framebuffer, hwdi_features,
131 hwdi_hotplug, hwdi_class_list, hwdi_drivers, hwdi_sysfs_id,
132 hwdi_sysfs_busid, hwdi_sysfs_link
133 } hw_hd_items_t;
134
135 static hash_t hw_ids_hd_items[] = {
136 { hwdi_bus, "Bus" },
137 { hwdi_slot, "Slot" },
138 { hwdi_func, "Function" },
139 { hwdi_base_class, "BaseClass" },
140 { hwdi_sub_class, "SubClass" },
141 { hwdi_prog_if, "ProgIF" },
142 { hwdi_dev, "DeviceID" },
143 { hwdi_vend, "VendorID" },
144 { hwdi_sub_dev, "SubDeviceID" },
145 { hwdi_sub_vend, "SubVendorID" },
146 { hwdi_rev, "RevisionID" },
147 { hwdi_compat_dev, "CompatDeviceID" },
148 { hwdi_compat_vend, "CompatVendorID" },
149 { hwdi_dev_name, "DeviceName" },
150 { hwdi_vend_name, "VendorName" },
151 { hwdi_sub_dev_name, "SubDeviceName" },
152 { hwdi_sub_vend_name, "SubVendorName" },
153 { hwdi_rev_name, "RevisionName" },
154 { hwdi_serial, "Serial" },
155 { hwdi_unix_dev_name, "UnixDevice" },
156 { hwdi_unix_dev_name2, "UnixDeviceAlt" },
157 { hwdi_unix_dev_names, "UnixDeviceList" },
158 { hwdi_rom_id, "ROMID" },
159 { hwdi_broken, "Broken" },
160 { hwdi_usb_guid, "USBGUID" },
161 { hwdi_res_phys_mem, "Res.PhysMemory" },
162 { hwdi_res_mem, "Res.Memory" },
163 { hwdi_res_io, "Res.IO" },
164 { hwdi_res_irq, "Res.Interrupts" },
165 { hwdi_res_dma, "Res.DMA" },
166 { hwdi_res_size, "Res.Size" },
167 { hwdi_res_baud, "Res.Baud" },
168 { hwdi_res_cache, "Res.Cache" },
169 { hwdi_res_disk_geo, "Res.DiskGeometry" },
170 { hwdi_res_monitor, "Res.Monitor" },
171 { hwdi_res_framebuffer, "Res.Framebuffer" },
172 { hwdi_features, "Features" },
173 { hwdi_hotplug, "Hotplug" },
174 { hwdi_class_list, "HWClassList" },
175 { hwdi_drivers, "Drivers" },
176 { hwdi_sysfs_id, "SysfsID" },
177 { hwdi_sysfs_busid, "SysfsBusID" },
178 { hwdi_sysfs_link, "SysfsLink" },
179 { 0, NULL }
180 };
181 #endif
182
183 static char *key2value(hash_t *hash, int id);
184
185 #ifndef LIBHD_TINY
186
187 static int value2key(hash_t *hash, char *str);
188 static void dump_manual(hd_data_t *hd_data);
189 static unsigned str2id(char *str);
190 static void manual2hd(hd_data_t *hd_data, hd_manual_t *entry, hd_t *hd);
191 static void hd2manual(hd_t *hd, hd_manual_t *entry);
192
193 void hd_scan_manual(hd_data_t *hd_data)
194 {
195 DIR *dir;
196 struct dirent *de;
197 hd_manual_t *entry, **entry_next;
198 int i;
199 hd_t *hd, *hd1;
200
201 if(!hd_probe_feature(hd_data, pr_manual)) return;
202
203 hd_data->module = mod_manual;
204
205 /* some clean-up */
206 remove_hd_entries(hd_data);
207
208 hd_data->manual = hd_free_manual(hd_data->manual);
209 entry_next = &hd_data->manual;
210
211 if((dir = opendir(HARDWARE_UNIQUE_KEYS))) {
212 i = 0;
213 while((de = readdir(dir))) {
214 if(*de->d_name == '.') continue;
215 PROGRESS(1, ++i, "read");
216 if((entry = hd_manual_read_entry(hd_data, de->d_name))) {
217 ADD2LOG(" got %s\n", entry->unique_id);
218 *entry_next = entry;
219 entry_next = &entry->next;
220 }
221 }
222 closedir(dir);
223 }
224
225 /* for compatibility: read old files, too */
226 if((dir = opendir(HARDWARE_DIR))) {
227 i = 0;
228 while((de = readdir(dir))) {
229 if(*de->d_name == '.') continue;
230 for(entry = hd_data->manual; entry; entry = entry->next) {
231 if(entry->unique_id && !strcmp(entry->unique_id, de->d_name)) break;
232 }
233 if(entry) continue;
234 PROGRESS(2, ++i, "read");
235 if((entry = hd_manual_read_entry(hd_data, de->d_name))) {
236 ADD2LOG(" got %s\n", entry->unique_id);
237 *entry_next = entry;
238 entry_next = &entry->next;
239 }
240 }
241 closedir(dir);
242 }
243
244 if(hd_data->debug) dump_manual(hd_data);
245
246 /* initialize some useful status value */
247 for(hd = hd_data->hd; hd; hd = hd->next) {
248 if(
249 !hd->status.configured &&
250 !hd->status.available &&
251 !hd->status.needed &&
252 !hd->status.active &&
253 !hd->status.invalid
254 ) {
255 hd->status.configured = status_new;
256 hd->status.available = hd->module == mod_manual ? status_unknown : status_yes;
257 hd->status.needed = status_no;
258 hd->status.active = status_unknown;
259 }
260 }
261
262 hd_data->flags.keep_kmods = 1;
263 for(entry = hd_data->manual; entry; entry = entry->next) {
264
265 for(hd = hd_data->hd; hd; hd = hd->next) {
266 if(hd->unique_id && !strcmp(hd->unique_id, entry->unique_id)) break;
267 }
268
269 if(hd) {
270 /* just update config status */
271 hd->status = entry->status;
272 hd->status.available = status_yes;
273
274 hd->config_string = new_str(entry->config_string);
275 }
276 else {
277 /* add new entry */
278 hd = add_hd_entry(hd_data, __LINE__, 0);
279
280 manual2hd(hd_data, entry, hd);
281
282 if(hd->status.available != status_unknown) hd->status.available = status_no;
283
284 if(hd->parent_id) {
285 for(hd1 = hd_data->hd; hd1; hd1 = hd1->next) {
286 if(hd1->unique_id && !strcmp(hd1->unique_id, hd->parent_id)) {
287 hd->attached_to = hd1->idx;
288 break;
289 }
290 }
291 }
292 }
293 }
294 hd_data->flags.keep_kmods = 0;
295
296 }
297
298
299 void hd_scan_manual2(hd_data_t *hd_data)
300 {
301 hd_t *hd, *hd1;
302
303 /* check if it's necessary to reconfigure this hardware */
304 for(hd = hd_data->hd; hd; hd = hd->next) {
305 hd->status.reconfig = status_no;
306
307 if(hd->status.needed != status_yes) continue;
308
309 if(hd->status.available == status_no) {
310 hd->status.reconfig = status_yes;
311 continue;
312 }
313
314 if(hd->status.available != status_unknown) continue;
315
316 for(hd1 = hd_data->hd; hd1; hd1 = hd1->next) {
317 if(hd1 == hd) continue;
318
319 if(
320 hd1->hw_class == hd->hw_class &&
321 hd1->status.configured == status_new &&
322 hd1->status.available == status_yes
323 ) break;
324 }
325
326 if(hd1) hd->status.reconfig = status_yes;
327 }
328 }
329
330
331 int value2key(hash_t *hash, char *str)
332 {
333 for(; hash->value; hash++) {
334 if(!strcmp(hash->value, str)) break;
335 }
336
337 return hash->key;
338 }
339
340 #endif
341
342 char *key2value(hash_t *hash, int id)
343 {
344 for(; hash->value; hash++) {
345 if(hash->key == id) break;
346 }
347
348 return hash->value;
349 }
350
351 char *hd_hw_item_name(hd_hw_item_t item)
352 {
353 return key2value(hw_items, item);
354 }
355
356
357 #ifndef LIBHD_TINY
358
359 char *hd_status_value_name(hd_status_value_t status)
360 {
361 return key2value(status_names, status);
362 }
363
364 /*
365 * read an entry
366 */
367 hd_manual_t *hd_manual_read_entry(hd_data_t *hd_data, const char *id)
368 {
369 char path[PATH_MAX];
370 int i, j, line;
371 str_list_t *sl, *sl0;
372 hd_manual_t *entry;
373 hash_t *sect;
374 char *s, *s1, *s2;
375 int err = 0;
376
377 snprintf(path, sizeof path, "%s/%s", HARDWARE_UNIQUE_KEYS, id);
378
379 if(!(sl0 = read_file(path, 0, 0))) {
380 /* try old location, too */
381 snprintf(path, sizeof path, "%s/%s", HARDWARE_DIR, id);
382 if(!(sl0 = read_file(path, 0, 0))) return NULL;
383 }
384
385 entry = new_mem(sizeof *entry);
386
387 // default list: no valid entries
388 sect = hw_ids_general + sizeof hw_ids_general / sizeof *hw_ids_general - 1;
389
390 for(line = 1, sl = sl0; sl; sl = sl->next, line++) {
391 s = sl->str;
392 while(isspace(*s)) s++;
393 if(!*s || *s == '#' || *s == ';') continue; /* empty lines & comments */
394
395 s2 = s;
396 s1 = strsep(&s2, "=");
397
398 if(!s2 && *s == '[') {
399 s2 = s + 1;
400 s1 = strsep(&s2, "]");
401 if(s1) {
402 if(!strcmp(s1, MAN_SECT_GENERAL)) {
403 sect = hw_ids_general;
404 continue;
405 }
406 if(!strcmp(s1, MAN_SECT_STATUS)) {
407 sect = hw_ids_status;
408 continue;
409 }
410 if(!strcmp(s1, MAN_SECT_HARDWARE)) {
411 sect = NULL;
412 continue;
413 }
414 }
415 s2 = NULL;
416 }
417
418 if(!s2) {
419 ADD2LOG(" %s: invalid line %d\n", id, line);
420 err = 1;
421 break;
422 }
423
424 if(sect) {
425 i = value2key(sect, s1);
426 if(!i) {
427 ADD2LOG(" %s: invalid line %d\n", id, line);
428 err = 1;
429 break;
430 }
431 s = canon_str(s2, strlen(s2));
432 switch(i) {
433 case hw_id_unique:
434 entry->unique_id = s;
435 s = NULL;
436 break;
437
438 case hw_id_parent:
439 entry->parent_id = s;
440 s = NULL;
441 break;
442
443 case hw_id_child:
444 entry->child_ids = s;
445 s = NULL;
446 break;
447
448 case hw_id_hwclass:
449 j = value2key(hw_items, s);
450 entry->hw_class = j;
451 if(!j) err = 1;
452 break;
453
454 case hw_id_model:
455 entry->model = s;
456 s = NULL;
457 break;
458
459 case hw_id_configured:
460 j = value2key(status_names, s);
461 entry->status.configured = j;
462 if(!j) err = 1;
463 break;
464
465 case hw_id_available:
466 j = value2key(status_names, s);
467 entry->status.available_orig =
468 entry->status.available = j;
469 if(!j) err = 1;
470 break;
471
472 case hw_id_needed:
473 j = value2key(status_names, s);
474 entry->status.needed = j;
475 if(!j) err = 1;
476 break;
477
478 case hw_id_active:
479 j = value2key(status_names, s);
480 entry->status.active = j;
481 if(!j) err = 1;
482 break;
483
484 case hw_id_cfgstring:
485 entry->config_string = s;
486 s = NULL;
487 break;
488
489 default:
490 err = 1;
491 }
492
493 free_mem(s);
494
495 if(err) {
496 ADD2LOG(" %s: invalid line %d\n", id, line);
497 break;
498 }
499 }
500 else {
501 add_str_list(&entry->key, s1);
502 s = canon_str(s2, strlen(s2));
503 add_str_list(&entry->value, s);
504 free_mem(s);
505 }
506 }
507
508 free_str_list(sl0);
509
510 /*
511 * do some basic consistency checks
512 */
513
514 if(!entry->unique_id || strcmp(entry->unique_id, id)) {
515 ADD2LOG(" %s: unique id does not match file name\n", id);
516 err = 1;
517 }
518
519 /*
520 * if the status info is completely missing, fake some:
521 * new hardware, not autodetectable, not needed
522 */
523 if(
524 !entry->status.configured &&
525 !entry->status.available &&
526 !entry->status.needed &&
527 !entry->status.invalid
528 ) {
529 entry->status.configured = status_new;
530 entry->status.available = status_unknown;
531 entry->status.needed = status_no;
532 }
533
534 if(!entry->status.active) entry->status.active = status_unknown;
535
536 if(
537 !entry->status.configured ||
538 !entry->status.available ||
539 !entry->status.needed ||
540 !entry->status.active
541 ) {
542 ADD2LOG(" %s: incomplete status\n", id);
543 err = 1;
544 }
545
546 if(!entry->hw_class) {
547 ADD2LOG(" %s: no class\n", id);
548 err = 1;
549 }
550
551 if(!entry->model) {
552 ADD2LOG(" %s: no model\n", id);
553 err = 1;
554 }
555
556 if(err) {
557 entry = hd_free_manual(entry);
558 }
559
560 return entry;
561 }
562
563
564 /*
565 * write an entry
566 */
567
568 int hd_manual_write_entry(hd_data_t *hd_data, hd_manual_t *entry)
569 {
570 FILE *f;
571 char path[PATH_MAX];
572 int error = 0;
573 struct stat sbuf;
574 str_list_t *sl1, *sl2;
575
576 if(!entry) return 0;
577 if(!entry->unique_id || entry->status.invalid) return 1;
578
579 snprintf(path, sizeof path, "%s/%s", HARDWARE_UNIQUE_KEYS, entry->unique_id);
580
581 if(!(f = fopen(path, "w"))) {
582 /* maybe we have to create the HARDWARE_UNIQUE_KEYS directory first... */
583
584 if(lstat(HARDWARE_DIR, &sbuf)) {
585 mkdir(HARDWARE_DIR, 0755);
586 }
587
588 if(lstat(HARDWARE_UNIQUE_KEYS, &sbuf)) {
589 mkdir(HARDWARE_UNIQUE_KEYS, 0755);
590 }
591
592 if(!(f = fopen(path, "w"))) return 2;
593 }
594
595 fprintf(f, "[%s]\n", MAN_SECT_GENERAL);
596
597 if(
598 !fprintf(f, "%s=%s\n",
599 key2value(hw_ids_general, hw_id_unique),
600 entry->unique_id
601 )
602 ) error = 3;
603
604 if(
605 entry->parent_id &&
606 !fprintf(f, "%s=%s\n",
607 key2value(hw_ids_general, hw_id_parent),
608 entry->parent_id
609 )
610 ) error = 3;
611
612 if(
613 entry->child_ids &&
614 !fprintf(f, "%s=%s\n",
615 key2value(hw_ids_general, hw_id_child),
616 entry->child_ids
617 )
618 ) error = 3;
619
620 if(
621 (entry->hw_class && key2value(hw_items, entry->hw_class)) &&
622 !fprintf(f, "%s=%s\n",
623 key2value(hw_ids_general, hw_id_hwclass),
624 key2value(hw_items, entry->hw_class)
625 )
626 ) error = 3;
627
628 if(
629 entry->model &&
630 !fprintf(f, "%s=%s\n",
631 key2value(hw_ids_general, hw_id_model),
632 entry->model
633 )
634 ) error = 3;
635
636 fprintf(f, "\n[%s]\n", MAN_SECT_STATUS);
637
638 if(
639 (entry->status.configured && key2value(status_names, entry->status.configured)) &&
640 !fprintf(f, "%s=%s\n",
641 key2value(hw_ids_status, hw_id_configured),
642 key2value(status_names, entry->status.configured)
643 )
644 ) error = 4;
645
646 if(
647 (entry->status.available && key2value(status_names, entry->status.available)) &&
648 !fprintf(f, "%s=%s\n",
649 key2value(hw_ids_status, hw_id_available),
650 key2value(status_names, entry->status.available)
651 )
652 ) error = 4;
653
654 if(
655 (entry->status.needed && key2value(status_names, entry->status.needed)) &&
656 !fprintf(f, "%s=%s\n",
657 key2value(hw_ids_status, hw_id_needed),
658 key2value(status_names, entry->status.needed)
659 )
660 ) error = 4;
661
662 if(
663 (entry->status.active && key2value(status_names, entry->status.active)) &&
664 !fprintf(f, "%s=%s\n",
665 key2value(hw_ids_status, hw_id_active),
666 key2value(status_names, entry->status.active)
667 )
668 ) error = 4;
669
670 if(
671 entry->config_string &&
672 !fprintf(f, "%s=%s\n",
673 key2value(hw_ids_status, hw_id_cfgstring),
674 entry->config_string
675 )
676 ) error = 4;
677
678 fprintf(f, "\n[%s]\n", MAN_SECT_HARDWARE);
679
680 for(
681 sl1 = entry->key, sl2 = entry->value;
682 sl1 && sl2;
683 sl1 = sl1->next, sl2 = sl2->next
684 ) {
685 if(!fprintf(f, "%s=%s\n", sl1->str, sl2->str)) {
686 error = 5;
687 break;
688 }
689 }
690
691 fputs("\n", f);
692
693 fclose(f);
694
695 /* remove old file */
696 if(!error) {
697 snprintf(path, sizeof path, "%s/%s", HARDWARE_DIR, entry->unique_id);
698 unlink(path);
699 }
700
701 return error;
702 }
703
704
705 void dump_manual(hd_data_t *hd_data)
706 {
707 hd_manual_t *entry;
708 static const char *txt = "manually configured hardware";
709 str_list_t *sl1, *sl2;
710
711 if(!hd_data->manual) return;
712
713 ADD2LOG("----- %s -----\n", txt);
714 for(entry = hd_data->manual; entry; entry = entry->next) {
715 ADD2LOG(" %s=%s\n",
716 key2value(hw_ids_general, hw_id_unique),
717 entry->unique_id
718 );
719 if(entry->parent_id)
720 ADD2LOG(" %s=%s\n",
721 key2value(hw_ids_general, hw_id_parent),
722 entry->parent_id
723 );
724 if(entry->child_ids)
725 ADD2LOG(" %s=%s\n",
726 key2value(hw_ids_general, hw_id_child),
727 entry->child_ids
728 );
729 ADD2LOG(" %s=%s\n",
730 key2value(hw_ids_general, hw_id_hwclass),
731 key2value(hw_items, entry->hw_class)
732 );
733 ADD2LOG(" %s=%s\n",
734 key2value(hw_ids_general, hw_id_model),
735 entry->model
736 );
737 ADD2LOG(" %s=%s\n",
738 key2value(hw_ids_status, hw_id_configured),
739 key2value(status_names, entry->status.configured)
740 );
741 ADD2LOG(" %s=%s\n",
742 key2value(hw_ids_status, hw_id_available),
743 key2value(status_names, entry->status.available)
744 );
745 ADD2LOG(" %s=%s\n",
746 key2value(hw_ids_status, hw_id_needed),
747 key2value(status_names, entry->status.needed)
748 );
749 ADD2LOG(" %s=%s\n",
750 key2value(hw_ids_status, hw_id_active),
751 key2value(status_names, entry->status.active)
752 );
753 if(entry->config_string)
754 ADD2LOG(" %s=%s\n",
755 key2value(hw_ids_status, hw_id_cfgstring),
756 entry->config_string
757 );
758 for(
759 sl1 = entry->key, sl2 = entry->value;
760 sl1 && sl2;
761 sl1 = sl1->next, sl2 = sl2->next
762 ) {
763 ADD2LOG(" %s=%s\n", sl1->str, sl2->str);
764 }
765 }
766 ADD2LOG("----- %s end -----\n", txt);
767 }
768
769
770 unsigned str2id(char *str)
771 {
772 unsigned id;
773 unsigned tag = 0;
774
775 if(strlen(str) == 3) return name2eisa_id(str);
776
777 switch(*str) {
778 case 'p':
779 tag = TAG_PCI; str++; break;
780
781 case 'r':
782 str++; break;
783
784 case 'u':
785 tag = TAG_USB; str++; break;
786
787 case 's':
788 tag = TAG_SPECIAL; str++; break;
789
790 case 'P':
791 tag = TAG_PCMCIA; str++; break;
792
793 }
794
795 id = strtoul(str, &str, 16);
796 if(*str) return 0;
797
798 return MAKE_ID(tag, ID_VALUE(id));
799 }
800
801
802 /*
803 * move info from hd_manual_t to hd_t
804 */
805 void manual2hd(hd_data_t *hd_data, hd_manual_t *entry, hd_t *hd)
806 {
807 str_list_t *sl1, *sl2;
808 hw_hd_items_t item;
809 unsigned tag, u0, u1, u2, u3, u4;
810 hd_res_t *res;
811 uint64_t u64_0, u64_1;
812 char *s;
813 int i;
814
815 if(!hd || !entry) return;
816
817 hd->unique_id = new_str(entry->unique_id);
818 hd->parent_id = new_str(entry->parent_id);
819 hd->child_ids = hd_split(',', entry->child_ids);
820 hd->model = new_str(entry->model);
821 hd->hw_class = entry->hw_class;
822
823 hd->config_string = new_str(entry->config_string);
824
825 hd->status = entry->status;
826
827 for(
828 sl1 = entry->key, sl2 = entry->value;
829 sl1 && sl2;
830 sl1 = sl1->next, sl2 = sl2->next
831 ) {
832 switch(item = value2key(hw_ids_hd_items, sl1->str)) {
833 case hwdi_bus:
834 hd->bus.id = strtoul(sl2->str, NULL, 0);
835 break;
836
837 case hwdi_slot:
838 hd->slot = strtoul(sl2->str, NULL, 0);
839 break;
840
841 case hwdi_func:
842 hd->func = strtoul(sl2->str, NULL, 0);
843 break;
844
845 case hwdi_base_class:
846 hd->base_class.id = strtoul(sl2->str, NULL, 0);
847 break;
848
849 case hwdi_sub_class:
850 hd->sub_class.id = strtoul(sl2->str, NULL, 0);
851 break;
852
853 case hwdi_prog_if:
854 hd->prog_if.id = strtoul(sl2->str, NULL, 0);
855 break;
856
857 case hwdi_dev:
858 hd->device.id = str2id(sl2->str);
859 break;
860
861 case hwdi_vend:
862 hd->vendor.id = str2id(sl2->str);
863 break;
864
865 case hwdi_sub_dev:
866 hd->sub_device.id = str2id(sl2->str);
867 break;
868
869 case hwdi_sub_vend:
870 hd->sub_vendor.id = str2id(sl2->str);
871 break;
872
873 case hwdi_rev:
874 hd->revision.id = strtoul(sl2->str, NULL, 0);
875 break;
876
877 case hwdi_compat_dev:
878 hd->compat_device.id = str2id(sl2->str);
879 break;
880
881 case hwdi_compat_vend:
882 hd->compat_vendor.id = str2id(sl2->str);
883 break;
884
885 case hwdi_dev_name:
886 hd->device.name = new_str(sl2->str);
887 break;
888
889 case hwdi_vend_name:
890 hd->vendor.name = new_str(sl2->str);
891 break;
892
893 case hwdi_sub_dev_name:
894 hd->sub_device.name = new_str(sl2->str);
895 break;
896
897 case hwdi_sub_vend_name:
898 hd->sub_vendor.name = new_str(sl2->str);
899 break;
900
901 case hwdi_rev_name:
902 hd->revision.name = new_str(sl2->str);
903 break;
904
905 case hwdi_serial:
906 hd->serial = new_str(sl2->str);
907 break;
908
909 case hwdi_unix_dev_name:
910 hd->unix_dev_name = new_str(sl2->str);
911 break;
912
913 case hwdi_unix_dev_name2:
914 hd->unix_dev_name2 = new_str(sl2->str);
915 break;
916
917 case hwdi_unix_dev_names:
918 hd->unix_dev_names = hd_split(' ', sl2->str);
919 break;
920
921 case hwdi_drivers:
922 hd->drivers = hd_split('|', sl2->str);
923 break;
924
925 case hwdi_sysfs_id:
926 hd->sysfs_id = new_str(sl2->str);
927 break;
928
929 case hwdi_sysfs_busid:
930 hd->sysfs_bus_id = new_str(sl2->str);
931 break;
932
933 case hwdi_sysfs_link:
934 hd->sysfs_device_link = new_str(sl2->str);
935 break;
936
937 case hwdi_rom_id:
938 hd->rom_id = new_str(sl2->str);
939 break;
940
941 case hwdi_broken:
942 hd->broken = strtoul(sl2->str, NULL, 0);
943 break;
944
945 case hwdi_usb_guid:
946 hd->usb_guid = new_str(sl2->str);
947 break;
948
949 case hwdi_hotplug:
950 hd->hotplug = strtol(sl2->str, NULL, 0);
951 break;
952
953 case hwdi_class_list:
954 for(
955 u0 = 0, s = sl2->str;
956 u0 < sizeof hd->hw_class_list / sizeof *hd->hw_class_list;
957 u0++
958 ) {
959 if(*s && s[1] && (i = hex(s, 2)) >= 0) {
960 hd->hw_class_list[u0] = i;
961 s += 2;
962 }
963 else {
964 break;
965 }
966 }
967 break;
968
969 case hwdi_res_mem:
970 res = add_res_entry(&hd->res, new_mem(sizeof *res));
971 res->any.type = res_mem;
972 if(sscanf(sl2->str, "0x%"SCNx64",0x%"SCNx64",%u,%u,%u", &u64_0, &u64_1, &u0, &u1, &u2) == 5) {
973 res->mem.base = u64_0;
974 res->mem.range = u64_1;
975 res->mem.enabled = u0;
976 res->mem.access = u1;
977 res->mem.prefetch = u2;
978 }
979 break;
980
981 case hwdi_res_phys_mem:
982 res = add_res_entry(&hd->res, new_mem(sizeof *res));
983 res->any.type = res_phys_mem;
984 if(sscanf(sl2->str, "0x%"SCNx64"", &u64_0) == 1) {
985 res->phys_mem.range = u64_0;
986 }
987 break;
988
989 case hwdi_res_io:
990 res = add_res_entry(&hd->res, new_mem(sizeof *res));
991 res->any.type = res_io;
992 if(sscanf(sl2->str, "0x%"SCNx64",0x%"SCNx64",%u,%u", &u64_0, &u64_1, &u0, &u1) == 4) {
993 res->io.base = u64_0;
994 res->io.range = u64_1;
995 res->io.enabled = u0;
996 res->io.access = u1;
997 }
998 break;
999
1000 case hwdi_res_irq:
1001 res = add_res_entry(&hd->res, new_mem(sizeof *res));
1002 res->any.type = res_irq;
1003 if(sscanf(sl2->str, "%u,%u,%u", &u0, &u1, &u2) == 3) {
1004 res->irq.base = u0;
1005 res->irq.triggered = u1;
1006 res->irq.enabled = u2;
1007 }
1008 break;
1009
1010 case hwdi_res_dma:
1011 res = add_res_entry(&hd->res, new_mem(sizeof *res));
1012 res->any.type = res_dma;
1013 if(sscanf(sl2->str, "%u,%u", &u0, &u1) == 2) {
1014 res->dma.base = u0;
1015 res->dma.enabled = u1;
1016 }
1017 break;
1018
1019 case hwdi_res_size:
1020 res = add_res_entry(&hd->res, new_mem(sizeof *res));
1021 res->any.type = res_size;
1022 if(sscanf(sl2->str, "%u,%u,%u", &u0, &u1, &u2) == 3) {
1023 res->size.unit = u0;
1024 res->size.val1 = u1;
1025 res->size.val2 = u2;
1026 }
1027 break;
1028
1029 case hwdi_res_baud:
1030 res = add_res_entry(&hd->res, new_mem(sizeof *res));
1031 res->any.type = res_baud;
1032 if(sscanf(sl2->str, "%u,%u,%u,%u,%u", &u0, &u1, &u2, &u3, &u4) == 5) {
1033 res->baud.speed = u0;
1034 res->baud.bits = u1;
1035 res->baud.stopbits = u2;
1036 res->baud.parity = (char) u3;
1037 res->baud.handshake = (char) u4;
1038 }
1039 break;
1040
1041 case hwdi_res_cache:
1042 res = add_res_entry(&hd->res, new_mem(sizeof *res));
1043 res->any.type = res_cache;
1044 if(sscanf(sl2->str, "%u", &u0) == 1) {
1045 res->cache.size = u0;
1046 }
1047 break;
1048
1049 case hwdi_res_disk_geo:
1050 res = add_res_entry(&hd->res, new_mem(sizeof *res));
1051 res->any.type = res_disk_geo;
1052 if(sscanf(sl2->str, "%u,%u,%u,%u", &u0, &u1, &u2, &u3) == 4) {
1053 res->disk_geo.cyls = u0;
1054 res->disk_geo.heads = u1;
1055 res->disk_geo.sectors = u2;
1056 res->disk_geo.geotype = u3;
1057 }
1058 break;
1059
1060 case hwdi_res_monitor:
1061 res = add_res_entry(&hd->res, new_mem(sizeof *res));
1062 res->any.type = res_monitor;
1063 if(sscanf(sl2->str, "%u,%u,%u,%u", &u0, &u1, &u2, &u3) == 4) {
1064 res->monitor.width = u0;
1065 res->monitor.height = u1;
1066 res->monitor.vfreq = u2;
1067 res->monitor.interlaced = u3;
1068 }
1069 break;
1070
1071 case hwdi_res_framebuffer:
1072 res = add_res_entry(&hd->res, new_mem(sizeof *res));
1073 res->any.type = res_framebuffer;
1074 if(sscanf(sl2->str, "%u,%u,%u,%u,%u", &u0, &u1, &u2, &u3, &u4) == 5) {
1075 res->framebuffer.width = u0;
1076 res->framebuffer.height = u1;
1077 res->framebuffer.bytes_p_line = u2;
1078 res->framebuffer.colorbits = u3;
1079 res->framebuffer.mode = u4;
1080 }
1081 break;
1082
1083 case hwdi_features:
1084 u0 = strtoul(sl2->str, NULL, 0);
1085 if(u0 & (1 << 0)) hd->is.agp = 1;
1086 if(u0 & (1 << 1)) hd->is.isapnp = 1;
1087 if(u0 & (1 << 2)) hd->is.softraiddisk = 1;
1088 if(u0 & (1 << 3)) hd->is.zip = 1;
1089 if(u0 & (1 << 4)) hd->is.cdr = 1;
1090 if(u0 & (1 << 5)) hd->is.cdrw = 1;
1091 if(u0 & (1 << 6)) hd->is.dvd = 1;
1092 if(u0 & (1 << 7)) hd->is.dvdr = 1;
1093 if(u0 & (1 << 8)) hd->is.dvdram = 1;
1094 if(u0 & (1 << 9)) hd->is.pppoe = 1;
1095 if(u0 & (1 << 10)) hd->is.wlan = 1;
1096 break;
1097 }
1098 }
1099
1100 if(hd->device.id || hd->vendor.id) {
1101 tag = ID_TAG(hd->device.id);
1102 tag = tag ? tag : ID_TAG(hd->vendor.id);
1103 tag = tag ? tag : TAG_PCI;
1104 hd->device.id = MAKE_ID(tag, ID_VALUE(hd->device.id));
1105 hd->vendor.id = MAKE_ID(tag, ID_VALUE(hd->vendor.id));
1106 }
1107
1108 if(hd->sub_device.id || hd->sub_vendor.id) {
1109 tag = ID_TAG(hd->sub_device.id);
1110 tag = tag ? tag : ID_TAG(hd->sub_vendor.id);
1111 tag = tag ? tag : TAG_PCI;
1112 hd->sub_device.id = MAKE_ID(tag, ID_VALUE(hd->sub_device.id));
1113 hd->sub_vendor.id = MAKE_ID(tag, ID_VALUE(hd->sub_vendor.id));
1114 }
1115
1116 if(hd->compat_device.id || hd->compat_vendor.id) {
1117 tag = ID_TAG(hd->compat_device.id);
1118 tag = tag ? tag : ID_TAG(hd->compat_vendor.id);
1119 tag = tag ? tag : TAG_PCI;
1120 hd->compat_device.id = MAKE_ID(tag, ID_VALUE(hd->compat_device.id));
1121 hd->compat_vendor.id = MAKE_ID(tag, ID_VALUE(hd->compat_vendor.id));
1122 }
1123
1124 if(hd->status.available == status_unknown) hd->is.manual = 1;
1125
1126 /* create some entries, if missing */
1127
1128 if(!hd->device.id && !hd->vendor.id && !hd->device.name) {
1129 hd->device.name = new_str(hd->model);
1130 }
1131
1132 if(hd->hw_class && !hd->base_class.id) {
1133 switch(hd->hw_class) {
1134 case hw_cdrom:
1135 hd->base_class.id = bc_storage_device;
1136 hd->sub_class.id = sc_sdev_cdrom;
1137 break;
1138
1139 case hw_mouse:
1140 hd->base_class.id = bc_mouse;
1141 hd->sub_class.id = sc_mou_other;
1142 break;
1143
1144 default:
1145 break;
1146 }
1147 }
1148
1149 hddb_add_info(hd_data, hd);
1150 }
1151
1152
1153 void hd2manual(hd_t *hd, hd_manual_t *entry)
1154 {
1155 char *s, *t;
1156 hd_res_t *res;
1157 str_list_t *sl;
1158 unsigned u;
1159
1160 if(!hd || !entry) return;
1161
1162 entry->unique_id = new_str(hd->unique_id);
1163 entry->parent_id = new_str(hd->parent_id);
1164 entry->child_ids = hd_join(",", hd->child_ids);
1165 entry->model = new_str(hd->model);
1166 entry->hw_class = hd->hw_class;
1167
1168 entry->config_string = new_str(hd->config_string);
1169
1170 entry->status = hd->status;
1171
1172 if(
1173 !entry->status.configured &&
1174 !entry->status.available &&
1175 !entry->status.needed &&
1176 !entry->status.active &&
1177 !entry->status.invalid
1178 ) {
1179 entry->status.configured = status_new;
1180 entry->status.available = hd->module == mod_manual ? status_unknown : status_yes;
1181 entry->status.needed = status_no;
1182 entry->status.active = status_unknown;
1183 }
1184
1185 s = NULL;
1186
1187 if(hd->broken) {
1188 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_broken));
1189 str_printf(&s, 0, "0x%x", hd->broken);
1190 add_str_list(&entry->value, s);
1191 }
1192
1193 if(hd->bus.id) {
1194 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_bus));
1195 str_printf(&s, 0, "0x%x", hd->bus.id);
1196 add_str_list(&entry->value, s);
1197 }
1198
1199 if(hd->slot) {
1200 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_slot));
1201 str_printf(&s, 0, "0x%x", hd->slot);
1202 add_str_list(&entry->value, s);
1203 }
1204
1205 if(hd->func) {
1206 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_func));
1207 str_printf(&s, 0, "0x%x", hd->func);
1208 add_str_list(&entry->value, s);
1209 }
1210
1211 if(hd->base_class.id) {
1212 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_base_class));
1213 str_printf(&s, 0, "0x%x", hd->base_class.id);
1214 add_str_list(&entry->value, s);
1215 }
1216
1217 if(hd->sub_class.id) {
1218 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_sub_class));
1219 str_printf(&s, 0, "0x%x", hd->sub_class.id);
1220 add_str_list(&entry->value, s);
1221 }
1222
1223 if(hd->prog_if.id) {
1224 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_prog_if));
1225 str_printf(&s, 0, "0x%x", hd->prog_if.id);
1226 add_str_list(&entry->value, s);
1227 }
1228
1229 if(hd->device.id || hd->vendor.id) {
1230 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_vend));
1231 add_str_list(&entry->value, vend_id2str(hd->vendor.id));
1232 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_dev));
1233 str_printf(&s, 0, "%04x", ID_VALUE(hd->device.id));
1234 add_str_list(&entry->value, s);
1235 }
1236
1237 if(hd->sub_device.id || hd->sub_vendor.id) {
1238 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_sub_vend));
1239 add_str_list(&entry->value, vend_id2str(hd->sub_vendor.id));
1240 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_sub_dev));
1241 str_printf(&s, 0, "%04x", ID_VALUE(hd->sub_device.id));
1242 add_str_list(&entry->value, s);
1243 }
1244
1245 if(hd->revision.id) {
1246 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_rev));
1247 str_printf(&s, 0, "0x%x", hd->revision.id);
1248 add_str_list(&entry->value, s);
1249 }
1250
1251 if(hd->compat_device.id || hd->compat_vendor.id) {
1252 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_compat_vend));
1253 add_str_list(&entry->value, vend_id2str(hd->compat_vendor.id));
1254 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_compat_dev));
1255 str_printf(&s, 0, "%04x", ID_VALUE(hd->compat_device.id));
1256 add_str_list(&entry->value, s);
1257 }
1258
1259 if(hd->device.name) {
1260 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_dev_name));
1261 add_str_list(&entry->value, hd->device.name);
1262 }
1263
1264 if(hd->vendor.name) {
1265 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_vend_name));
1266 add_str_list(&entry->value, hd->vendor.name);
1267 }
1268
1269 if(hd->sub_device.name) {
1270 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_sub_dev_name));
1271 add_str_list(&entry->value, hd->sub_device.name);
1272 }
1273
1274 if(hd->sub_vendor.name) {
1275 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_sub_vend_name));
1276 add_str_list(&entry->value, hd->sub_vendor.name);
1277 }
1278
1279 if(hd->revision.name) {
1280 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_rev_name));
1281 add_str_list(&entry->value, hd->revision.name);
1282 }
1283
1284 if(hd->serial) {
1285 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_serial));
1286 add_str_list(&entry->value, hd->serial);
1287 }
1288
1289 if(hd->unix_dev_name) {
1290 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_unix_dev_name));
1291 add_str_list(&entry->value, hd->unix_dev_name);
1292 }
1293
1294 if(hd->unix_dev_name2) {
1295 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_unix_dev_name2));
1296 add_str_list(&entry->value, hd->unix_dev_name2);
1297 }
1298
1299 if(hd->unix_dev_names) {
1300 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_unix_dev_names));
1301 s = free_mem(s);
1302 s = hd_join(" ", hd->unix_dev_names);
1303 add_str_list(&entry->value, s);
1304 }
1305
1306 if(hd->drivers) {
1307 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_drivers));
1308 s = free_mem(s);
1309 s = hd_join("|", hd->drivers);
1310 add_str_list(&entry->value, s);
1311 }
1312
1313 if(hd->sysfs_id) {
1314 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_sysfs_id));
1315 add_str_list(&entry->value, hd->sysfs_id);
1316 }
1317
1318 if(hd->sysfs_bus_id) {
1319 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_sysfs_busid));
1320 add_str_list(&entry->value, hd->sysfs_bus_id);
1321 }
1322
1323 if(hd->sysfs_device_link) {
1324 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_sysfs_link));
1325 add_str_list(&entry->value, hd->sysfs_device_link);
1326 }
1327
1328 if(hd->rom_id) {
1329 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_rom_id));
1330 add_str_list(&entry->value, hd->rom_id);
1331 }
1332
1333 if(hd->usb_guid) {
1334 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_usb_guid));
1335 add_str_list(&entry->value, hd->usb_guid);
1336 }
1337
1338 if(hd->hotplug) {
1339 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_hotplug));
1340 str_printf(&s, 0, "%d", hd->hotplug);
1341 add_str_list(&entry->value, s);
1342 }
1343
1344 s = free_mem(s);
1345 for(u = 0; u < sizeof hd->hw_class_list / sizeof *hd->hw_class_list; u++) {
1346 str_printf(&s, -1, "%02x", hd->hw_class_list[u]);
1347 }
1348 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_class_list));
1349 add_str_list(&entry->value, s);
1350
1351 u = 0;
1352 if(hd->is.agp) u |= 1 << 0;
1353 if(hd->is.isapnp) u |= 1 << 1;
1354 if(hd->is.softraiddisk) u |= 1 << 2;
1355 if(hd->is.zip) u |= 1 << 3;
1356 if(hd->is.cdr) u |= 1 << 4;
1357 if(hd->is.cdrw) u |= 1 << 5;
1358 if(hd->is.dvd) u |= 1 << 6;
1359 if(hd->is.dvdr) u |= 1 << 7;
1360 if(hd->is.dvdram) u |= 1 << 8;
1361 if(hd->is.pppoe) u |= 1 << 9;
1362 if(hd->is.wlan) u |= 1 << 10;
1363
1364 if(u) {
1365 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_features));
1366 str_printf(&s, 0, "0x%x", u);
1367 add_str_list(&entry->value, s);
1368 }
1369
1370 for(res = hd->res; res; res = res->next) {
1371 sl = NULL;
1372 switch(res->any.type) {
1373 case res_mem:
1374 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_res_mem));
1375 str_printf(&s, 0, "0x%"PRIx64"", res->mem.base);
1376 add_str_list(&sl, s);
1377 str_printf(&s, 0, "0x%"PRIx64"", res->mem.range);
1378 add_str_list(&sl, s);
1379 str_printf(&s, 0, "%u", res->mem.enabled);
1380 add_str_list(&sl, s);
1381 str_printf(&s, 0, "%u", res->mem.access);
1382 add_str_list(&sl, s);
1383 str_printf(&s, 0, "%u", res->mem.prefetch);
1384 add_str_list(&sl, s);
1385 break;
1386
1387 case res_phys_mem:
1388 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_res_phys_mem));
1389 str_printf(&s, 0, "0x%"PRIx64"", res->phys_mem.range);
1390 add_str_list(&sl, s);
1391 break;
1392
1393 case res_io:
1394 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_res_io));
1395 str_printf(&s, 0, "0x%"PRIx64"", res->io.base);
1396 add_str_list(&sl, s);
1397 str_printf(&s, 0, "0x%"PRIx64"", res->io.range);
1398 add_str_list(&sl, s);
1399 str_printf(&s, 0, "%u", res->io.enabled);
1400 add_str_list(&sl, s);
1401 str_printf(&s, 0, "%u", res->io.access);
1402 add_str_list(&sl, s);
1403 break;
1404
1405 case res_irq:
1406 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_res_irq));
1407 str_printf(&s, 0, "%u", res->irq.base);
1408 add_str_list(&sl, s);
1409 str_printf(&s, 0, "%u", res->irq.triggered);
1410 add_str_list(&sl, s);
1411 str_printf(&s, 0, "%u", res->irq.enabled);
1412 add_str_list(&sl, s);
1413 break;
1414
1415 case res_dma:
1416 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_res_dma));
1417 str_printf(&s, 0, "%u", res->dma.base);
1418 add_str_list(&sl, s);
1419 str_printf(&s, 0, "%u", res->dma.enabled);
1420 add_str_list(&sl, s);
1421 break;
1422
1423 case res_size:
1424 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_res_size));
1425 str_printf(&s, 0, "%u", res->size.unit);
1426 add_str_list(&sl, s);
1427 str_printf(&s, 0, "%"PRIu64, res->size.val1);
1428 add_str_list(&sl, s);
1429 str_printf(&s, 0, "%"PRIu64, res->size.val2);
1430 add_str_list(&sl, s);
1431 break;
1432
1433 case res_baud:
1434 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_res_baud));
1435 str_printf(&s, 0, "%u", res->baud.speed);
1436 add_str_list(&sl, s);
1437 str_printf(&s, 0, "%u", res->baud.bits);
1438 add_str_list(&sl, s);
1439 str_printf(&s, 0, "%u", res->baud.stopbits);
1440 add_str_list(&sl, s);
1441 str_printf(&s, 0, "0x%02x", (unsigned) res->baud.parity);
1442 add_str_list(&sl, s);
1443 str_printf(&s, 0, "0x%02x", (unsigned) res->baud.handshake);
1444 add_str_list(&sl, s);
1445 break;
1446
1447 case res_cache:
1448 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_res_cache));
1449 str_printf(&s, 0, "%u", res->cache.size);
1450 add_str_list(&sl, s);
1451 break;
1452
1453 case res_disk_geo:
1454 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_res_disk_geo));
1455 str_printf(&s, 0, "%u", res->disk_geo.cyls);
1456 add_str_list(&sl, s);
1457 str_printf(&s, 0, "%u", res->disk_geo.heads);
1458 add_str_list(&sl, s);
1459 str_printf(&s, 0, "%u", res->disk_geo.sectors);
1460 add_str_list(&sl, s);
1461 str_printf(&s, 0, "%u", res->disk_geo.geotype);
1462 add_str_list(&sl, s);
1463 break;
1464
1465 case res_monitor:
1466 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_res_monitor));
1467 str_printf(&s, 0, "%u", res->monitor.width);
1468 add_str_list(&sl, s);
1469 str_printf(&s, 0, "%u", res->monitor.height);
1470 add_str_list(&sl, s);
1471 str_printf(&s, 0, "%u", res->monitor.vfreq);
1472 add_str_list(&sl, s);
1473 str_printf(&s, 0, "%u", res->monitor.interlaced);
1474 add_str_list(&sl, s);
1475 break;
1476
1477 case res_framebuffer:
1478 add_str_list(&entry->key, key2value(hw_ids_hd_items, hwdi_res_framebuffer));
1479 str_printf(&s, 0, "%u", res->framebuffer.width);
1480 add_str_list(&sl, s);
1481 str_printf(&s, 0, "%u", res->framebuffer.height);
1482 add_str_list(&sl, s);
1483 str_printf(&s, 0, "%u", res->framebuffer.bytes_p_line);
1484 add_str_list(&sl, s);
1485 str_printf(&s, 0, "%u", res->framebuffer.colorbits);
1486 add_str_list(&sl, s);
1487 str_printf(&s, 0, "%u", res->framebuffer.mode);
1488 add_str_list(&sl, s);
1489 break;
1490
1491 default:
1492 break;
1493 }
1494 /* keep entry->key & entry->value symmetrical! */
1495 if(sl) {
1496 t = hd_join(",", sl);
1497 add_str_list(&entry->value, t);
1498 free_mem(t);
1499 free_str_list(sl);
1500 }
1501 }
1502
1503 free_mem(s);
1504 }
1505
1506
1507 hd_t *hd_read_config(hd_data_t *hd_data, const char *id)
1508 {
1509 hd_t *hd = NULL;
1510 hd_manual_t *entry;
1511
1512 hddb_init(hd_data);
1513
1514 entry = hd_manual_read_entry(hd_data, id);
1515
1516 if(entry) {
1517 hd = new_mem(sizeof *hd);
1518 hd->module = hd_data->module;
1519 hd->line = __LINE__;
1520 hd->tag.freeit = 1; /* make it a 'stand alone' entry */
1521 manual2hd(hd_data, entry, hd);
1522 hd_free_manual(entry);
1523 }
1524
1525 return hd;
1526 }
1527
1528
1529 int hd_write_config(hd_data_t *hd_data, hd_t *hd)
1530 {
1531 int err = 0;
1532 hd_manual_t *entry;
1533
1534 if(!hd_report_this(hd_data, hd)) return 0;
1535
1536 entry = new_mem(sizeof *entry);
1537
1538 hd2manual(hd, entry);
1539
1540 err = entry->unique_id ? hd_manual_write_entry(hd_data, entry) : 5;
1541
1542 hd_free_manual(entry);
1543
1544 return err;
1545 }
1546
1547
1548 #endif /* LIBHD_TINY */
1549