6
#include <sys/utsname.h>
15
* @defgroup HDDBint Hardware DB (HDDB)
16
* @ingroup libhdInternals
17
* @brief Hardware DB functions
22
extern hddb2_data_t hddb_internal;
24
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
27
// #define HDDB_EXTERNAL_ONLY
29
static char *hid_tag_names[] = { "", "pci ", "eisa ", "usb ", "special ", "pcmcia " };
30
// just experimenting...
31
static char *hid_tag_names2[] = { "", "pci ", "eisa ", "usb ", "int ", "pcmcia " };
34
pref_empty, pref_new, pref_and, pref_or, pref_add
37
typedef struct line_s {
45
unsigned val[32]; /**< arbitrary (approx. max. number of modules/xf86 config lines) */
49
* Hardware DB search struct.
50
* @note except for driver, all strings are static and _must not_ be freed
53
hddb_entry_mask_t key;
54
hddb_entry_mask_t value;
55
hddb_entry_mask_t value_mask[he_nomask];
72
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
73
static void hddb_init_pci(hd_data_t *hd_data);
74
static char *get_mi_field(char *str, char *tag, int field_len, unsigned *value, unsigned *has_value);
75
static modinfo_t *parse_modinfo(str_list_t *file);
76
static driver_info_t *hd_modinfo_db(hd_data_t *hd_data, modinfo_t *modinfo_db, hd_t *hd, driver_info_t *drv_info);
77
static void hddb_init_external(hd_data_t *hd_data);
79
static line_t *parse_line(char *str);
80
static unsigned store_string(hddb2_data_t *x, char *str);
81
static unsigned store_list(hddb2_data_t *x, hddb_list_t *list);
82
static unsigned store_value(hddb2_data_t *x, unsigned val);
83
static unsigned store_entry(hddb2_data_t *x, tmp_entry_t *te);
84
static void clear_entry(tmp_entry_t *te);
85
static void add_value(tmp_entry_t *te, hddb_entry_t idx, unsigned val);
86
static hddb_entry_mask_t add_entry(hddb2_data_t *hddb2, tmp_entry_t *te, hddb_entry_t idx, char *str);
87
static int compare_ids(hddb2_data_t *hddb, hddb_search_t *hs, hddb_entry_mask_t mask, unsigned key);
88
static void complete_ids(hddb2_data_t *hddb, hddb_search_t *hs, hddb_entry_mask_t key_mask, hddb_entry_mask_t mask, unsigned val_idx);
89
static int hddb_search(hd_data_t *hd_data, hddb_search_t *hs, int max_recursions);
91
static void test_db(hd_data_t *hd_data);
93
static driver_info_t *hddb_to_device_driver(hd_data_t *hd_data, hddb_search_t *hs);
94
static driver_info_t *kbd_driver(hd_data_t *hd_data, hd_t *hd);
95
static driver_info_t *monitor_driver(hd_data_t *hd_data, hd_t *hd);
98
/* static int chk_free_biosmem(hd_data_t *hd_data, unsigned addr, unsigned len); */
99
/* static isdn_parm_t *new_isdn_parm(isdn_parm_t **ip); */
100
static driver_info_t *isdn_driver(hd_data_t *hd_data, hd_t *hd, cdb_isdn_card *cic);
101
static driver_info_t *dsl_driver(hd_data_t *hd_data, hd_t *hd, cdb_isdn_card *cic);
104
static hd_res_t *get_res(hd_t *h, enum resource_types t, unsigned index);
105
static driver_info_t *reorder_x11(driver_info_t *di0, char *info);
106
static void expand_driver_info(hd_data_t *hd_data, hd_t *hd);
107
static char *module_cmd(hd_t *hd, char *cmd);
110
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
111
void hddb_init_pci(hd_data_t *hd_data)
113
str_list_t *sl = NULL;
117
if(!hd_data->modinfo) {
119
r = getenv("LIBHD_KERNELVERSION");
120
if(!r || !*r) r = ubuf.release;
121
str_printf(&s, 0, "/lib/modules/%s/modules.alias", r);
122
sl = read_file(s, 0, 0);
126
hd_data->modinfo = parse_modinfo(sl);
128
sl = free_str_list(sl);
133
if(!hd_data->modinfo_ext) {
134
sl = read_file("/WHATEVER", 0, 0);
135
hd_data->modinfo_ext = parse_modinfo(sl);
136
sl = free_str_list(sl);
142
char *get_mi_field(char *str, char *tag, int field_len, unsigned *value, unsigned *has_value)
148
if(strncmp(str, tag, i)) return NULL;
157
i = sscanf(str, "%8x%n", value, &j);
158
if(i < 1) return NULL;
167
modinfo_t *parse_modinfo(str_list_t *file)
171
modinfo_t *modinfo, *m;
174
char alias[256], module[256];
177
for(len = 1, sl = file; sl; sl = sl->next) len++;
179
modinfo = new_mem(len * sizeof *modinfo);
181
for(m = modinfo, sl = file; sl; sl = sl->next) {
182
if(sscanf(sl->str, "alias %255s %255s", alias, module) != 2) continue;
184
m->module = new_str(module);
185
m->alias = new_str(alias);
188
if(!strncmp(alias, "pci:", sizeof "pci:" - 1)) {
189
s = alias + sizeof "pci:" - 1;
193
if(!(s = get_mi_field(s, "v", 8, &m->pci.vendor, &u))) continue;
194
m->pci.has.vendor = u;
196
if(!(s = get_mi_field(s, "d", 8, &m->pci.device, &u))) continue;
197
m->pci.has.device = u;
199
if(!(s = get_mi_field(s, "sv", 8, &m->pci.sub_vendor, &u))) continue;
200
m->pci.has.sub_vendor = u;
202
if(!(s = get_mi_field(s, "sd", 8, &m->pci.sub_device, &u))) continue;
203
m->pci.has.sub_device = u;
205
if(!(s = get_mi_field(s, "bc", 2, &m->pci.base_class, &u))) continue;
206
m->pci.has.base_class = u;
208
if(!(s = get_mi_field(s, "sc", 2, &m->pci.sub_class, &u))) continue;
209
m->pci.has.sub_class = u;
211
if(!(s = get_mi_field(s, "i", 2, &m->pci.prog_if, &u))) continue;
212
m->pci.has.prog_if = u;
218
/* note: list stops at first entry with m->type == mi_none */
221
fprintf(stderr, "--- modinfo ---\n");
222
for(m = modinfo; m->type; m++) {
225
fprintf(stderr, "%s: %s\n v 0x%x:%u, d 0x%x:%u, sv 0x%x:%u, sd 0x%x:%u, bc 0x%x:%u, sc 0x%x:%u, i 0x%x:%u\n",
227
m->pci.vendor, m->pci.has.vendor,
228
m->pci.device, m->pci.has.device,
229
m->pci.sub_vendor, m->pci.has.sub_vendor,
230
m->pci.sub_device, m->pci.has.sub_device,
231
m->pci.base_class, m->pci.has.base_class,
232
m->pci.sub_class, m->pci.has.sub_class,
233
m->pci.prog_if, m->pci.has.prog_if
238
fprintf(stderr, "%s: %s\n",
254
* return prio, 0: no match
256
int match_modinfo(modinfo_t *db, modinfo_t *match)
261
if(db->type != match->type) return prio;
265
if(db->pci.has.base_class) {
266
if(match->pci.has.base_class && db->pci.base_class == match->pci.base_class) {
274
if(db->pci.has.sub_class) {
275
if(match->pci.has.sub_class && db->pci.sub_class == match->pci.sub_class) {
283
if(db->pci.has.prog_if) {
284
if(match->pci.has.prog_if && db->pci.prog_if == match->pci.prog_if) {
292
if(db->pci.has.vendor) {
293
if(match->pci.has.vendor && db->pci.vendor == match->pci.vendor) {
301
if(db->pci.has.device) {
302
if(match->pci.has.device && db->pci.device == match->pci.device) {
310
if(db->pci.has.sub_vendor) {
311
if(match->pci.has.sub_vendor && db->pci.sub_vendor == match->pci.sub_vendor) {
319
if(db->pci.has.sub_device) {
320
if(match->pci.has.sub_device && db->pci.sub_device == match->pci.sub_device) {
331
if(match->alias && db->alias) {
332
if(!fnmatch(db->alias, match->alias, 0)) {
333
s = strchr(db->alias, '*');
334
prio = s ? s - db->alias + 1 : strlen(db->alias) + 1;
347
driver_info_t *hd_modinfo_db(hd_data_t *hd_data, modinfo_t *modinfo_db, hd_t *hd, driver_info_t *drv_info)
349
driver_info_t **di = NULL, *di2;
351
char *mod_list[16 /* arbitrary, > 0 */];
352
int mod_prio[sizeof mod_list / sizeof *mod_list];
353
int i, prio, mod_list_len;
354
modinfo_t match = { };
356
if(!modinfo_db) return drv_info;
359
ID_TAG(hd->vendor.id) == TAG_PCI ||
360
ID_TAG(hd->device.id) == TAG_PCI
365
match.type = mi_other;
368
match.alias = hd->modalias;
370
if(!match.type) return drv_info;
372
/* don't add module info if driver info of some other type exists */
373
for(di = &drv_info; *di; di = &(*di)->next) {
374
if((*di)->any.type != di_module) return drv_info;
377
if(match.type == mi_pci) {
379
match.pci.vendor = ID_VALUE(hd->vendor.id);
380
match.pci.has.vendor = 1;
383
match.pci.device = ID_VALUE(hd->device.id);
384
match.pci.has.device = 1;
386
if(hd->sub_vendor.id) {
387
match.pci.sub_vendor = ID_VALUE(hd->sub_vendor.id);
388
match.pci.has.sub_vendor = 1;
390
if(hd->sub_device.id) {
391
match.pci.sub_device = ID_VALUE(hd->sub_device.id);
392
match.pci.has.sub_device = 1;
394
match.pci.base_class = hd->base_class.id;
395
match.pci.has.base_class = 1;
396
match.pci.sub_class = hd->sub_class.id;
397
match.pci.has.sub_class = 1;
398
match.pci.prog_if = hd->prog_if.id;
399
match.pci.has.prog_if = 1;
403
hd->detail->type == hd_detail_pci &&
404
(pci = hd->detail->pci.data)
406
match.pci.base_class = pci->base_class;
407
match.pci.sub_class = pci->sub_class;
408
match.pci.prog_if = pci->prog_if;
412
for(mod_list_len = 0; modinfo_db->type; modinfo_db++) {
413
if((prio = match_modinfo(modinfo_db, &match))) {
414
for(di2 = drv_info; di2; di2 = di2->next) {
416
di2->any.type == di_module &&
418
di2->any.hddb0->str &&
419
!hd_mod_cmp(di2->any.hddb0->str, modinfo_db->module)
425
for(i = 0; i < mod_list_len; i++) {
426
if(!strcmp(mod_list[i], modinfo_db->module)) {
427
if(prio > mod_prio[i]) mod_prio[i] = prio;
432
if(i < mod_list_len) continue;
434
mod_prio[mod_list_len] = prio;
435
mod_list[mod_list_len++] = modinfo_db->module;
437
if(mod_list_len >= sizeof mod_list / sizeof *mod_list) break;
441
if(!mod_list_len && hd->modalias && !strchr(hd->modalias, ':')) {
442
mod_prio[mod_list_len] = 0;
443
mod_list[mod_list_len++] = hd->modalias;
446
for(prio = 256; prio >= 0; prio--) {
447
for(i = 0; i < mod_list_len; i++) {
448
if(mod_prio[i] == prio) {
449
*di = new_mem(sizeof **di);
450
(*di)->any.type = di_module;
451
(*di)->module.modprobe = 1;
452
add_str_list(&(*di)->any.hddb0, mod_list[i]);
462
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
463
void hddb_init(hd_data_t *hd_data)
465
hddb_init_pci(hd_data);
466
hddb_init_external(hd_data);
468
#ifndef HDDB_EXTERNAL_ONLY
469
hd_data->hddb2[1] = &hddb_internal;
478
void hddb_init_external(hd_data_t *hd_data)
480
str_list_t *sl, *sl0;
482
unsigned l_start, l_end /* end points _past_ last element */;
483
unsigned u, ent, l_nr = 1;
484
tmp_entry_t tmp_entry[he_nomask /* _must_ be he_nomask! */];
485
hddb_entry_mask_t entry_mask = 0;
487
hddb_list_t dbl = {};
490
if(hd_data->hddb2[0]) return;
492
hddb2 = hd_data->hddb2[0] = new_mem(sizeof *hd_data->hddb2[0]);
494
sl0 = read_file(hd_get_hddb_path("hd.ids"), 0, 0);
499
for(sl = sl0; sl; sl = sl->next, l_nr++) {
500
l = parse_line(sl->str);
502
ADD2LOG("hd.ids line %d: invalid line\n", l_nr);
506
if(l->prefix == pref_empty) continue;
509
if((state == 2 && !entry_mask) || state == 1) {
510
ADD2LOG("hd.ids line %d: new item not allowed\n", l_nr);
514
if(state == 2 && entry_mask) {
515
ent = store_entry(hddb2, tmp_entry);
517
ADD2LOG("hd.ids line %d: internal hddb oops 1\n", l_nr);
521
if(l_end && l_end > l_start) {
522
for(u = l_start; u < l_end; u++) {
523
hddb2->list[u].value_mask = entry_mask;
524
hddb2->list[u].value = ent;
529
clear_entry(tmp_entry);
531
l_start = store_list(hddb2, &dbl);
537
ADD2LOG("hd.ids line %d: must start item first\n", l_nr);
544
if(state != 1 || !entry_mask || l_end <= l_start || l_end < 1) {
545
ADD2LOG("hd.ids line %d: must start item first\n", l_nr);
549
ent = store_entry(hddb2, tmp_entry);
551
ADD2LOG("hd.ids line %d: internal hddb oops 2\n", l_nr);
555
hddb2->list[l_end - 1].key_mask = entry_mask;
556
hddb2->list[l_end - 1].key = ent;
558
clear_entry(tmp_entry);
559
u = store_list(hddb2, &dbl);
561
ADD2LOG("hd.ids line %d: internal hddb oops 2\n", l_nr);
569
if(state == 1 && !entry_mask) {
570
ADD2LOG("hd.ids line %d: driver info not allowed\n", l_nr);
574
if(state == 1 && l_end > l_start) {
575
ent = store_entry(hddb2, tmp_entry);
577
ADD2LOG("hd.ids line %d: internal hddb oops 3\n", l_nr);
581
hddb2->list[l_end - 1].key_mask = entry_mask;
582
hddb2->list[l_end - 1].key = ent;
584
clear_entry(tmp_entry);
587
if(state != 2 || l_end == 0) {
588
ADD2LOG("hd.ids line %d: driver info not allowed\n", l_nr);
599
u = add_entry(hddb2, tmp_entry, l->key, l->value);
604
ADD2LOG("hd.ids line %d: invalid info\n", l_nr);
609
if(state == 4) break; /* error */
612
/* finalize last item */
613
if(state == 2 && entry_mask) {
614
ent = store_entry(hddb2, tmp_entry);
616
ADD2LOG("hd.ids line %d: internal hddb oops 4\n", l_nr);
619
else if(l_end && l_end > l_start) {
620
for(u = l_start; u < l_end; u++) {
621
hddb2->list[u].value_mask = entry_mask;
622
hddb2->list[u].value = ent;
627
sl0 = free_str_list(sl0);
630
/* there was an error */
632
free_mem(hddb2->list);
633
free_mem(hddb2->ids);
634
free_mem(hddb2->strings);
635
hd_data->hddb2[0] = free_mem(hd_data->hddb2[0]);
640
line_t *parse_line(char *str)
646
/* drop leading spaces */
647
while(isspace(*str)) str++;
649
/* skip emtpy lines and comments */
650
if(!*str || *str == ';' || *str == '#') {
651
l.prefix = pref_empty;
675
while(isspace(*str)) str++;
678
while(*str && !isspace(*str)) str++;
680
while(isspace(*str)) str++;
682
for(i = 0; (unsigned) i < sizeof hddb_entry_strings / sizeof *hddb_entry_strings; i++) {
683
if(!strcmp(s, hddb_entry_strings[i])) {
689
if((unsigned) i >= sizeof hddb_entry_strings / sizeof *hddb_entry_strings) return NULL;
693
/* drop trailing white space */
696
if(isspace(str[i - 1]))
702
/* special case: drop leading and final double quotes, if any */
704
if(i >= 2 && l.value[0] == '"' && l.value[i - 1] == '"') {
709
// fprintf(stderr, "pre = %d, key = %d, val = \"%s\"\n", l.prefix, l.key, l.value);
715
unsigned store_string(hddb2_data_t *x, char *str)
717
unsigned l = strlen(str), u;
719
if(x->strings_len + l >= x->strings_max) {
720
x->strings_max += l + 0x1000; /* >4k steps */
721
x->strings = resize_mem(x->strings, x->strings_max * sizeof *x->strings);
724
/* make sure the 1st byte is 0 */
725
if(x->strings_len == 0) {
726
*x->strings = 0; /* resize_mem does _not_ clear memory */
730
if(l == 0) return 0; /* 1st byte is always 0 */
732
strcpy(x->strings + (u = x->strings_len), str);
733
x->strings_len += l + 1;
739
unsigned store_list(hddb2_data_t *x, hddb_list_t *list)
741
if(x->list_len == x->list_max) {
742
x->list_max += 0x100; /* 4k steps */
743
x->list = resize_mem(x->list, x->list_max * sizeof *x->list);
746
x->list[x->list_len++] = *list;
748
return x->list_len - 1;
752
unsigned store_value(hddb2_data_t *x, unsigned val)
754
if(x->ids_len == x->ids_max) {
755
x->ids_max += 0x400; /* 4k steps */
756
x->ids = resize_mem(x->ids, x->ids_max * sizeof *x->ids);
759
x->ids[x->ids_len++] = val;
761
return x->ids_len - 1;
765
/* returns index in hddb2->ids */
766
unsigned store_entry(hddb2_data_t *x, tmp_entry_t *te)
769
unsigned ent = -1, u, v;
771
for(i = 0; i < he_nomask; i++) {
773
for(j = 0; j < te[i].len; j++) {
774
v = te[i].val[j] | (1 << 31);
775
if(j == te[i].len - 1) v &= ~(1 << 31);
776
u = store_value(x, v);
777
if(ent == -1u) ent = u;
785
void clear_entry(tmp_entry_t *te)
787
memset(te, 0, he_nomask * sizeof *te);
790
void add_value(tmp_entry_t *te, hddb_entry_t idx, unsigned val)
792
if(idx >= he_nomask) return;
795
if((unsigned) te->len >= sizeof te->val / sizeof *te->val) return;
797
te->val[te->len++] = val;
800
int parse_id(char *str, unsigned *id, unsigned *range, unsigned *mask)
802
static unsigned id0, val;
804
char c = 0, *s, *t = NULL;
806
*id = *range = *mask = 0;
808
if(!str || !*str) return 0;
810
for(s = str; *str && !isspace(*str); str++);
812
c = *(t = str); /* remember for later */
815
while(isspace(*str)) str++;
818
if(!strcmp(s, "pci")) tag = TAG_PCI;
819
else if(!strcmp(s, "usb")) tag = TAG_USB;
820
else if(!strcmp(s, "special")) tag = TAG_SPECIAL;
821
else if(!strcmp(s, "eisa")) tag = TAG_EISA;
822
else if(!strcmp(s, "isapnp")) tag = TAG_EISA;
823
else if(!strcmp(s, "pcmcia")) tag = TAG_PCMCIA;
826
if(t) *t = c; /* restore */
830
id0 = strtoul(str, &s, 0);
833
id0 = name2eisa_id(str);
837
if(!tag) tag = TAG_EISA;
840
while(isspace(*s)) s++;
841
if(*s && *s != '&' && *s != '+') return 0;
843
*id = MAKE_ID(tag, id0);
849
while(isspace(*s)) s++;
851
val = strtoul(s, &str, 0);
853
if(s == str) return 0;
855
while(isspace(*str)) str++;
859
if(c == '+') *range = val; else *mask = val;
861
return c == '+' ? 2 : 3;
865
hddb_entry_mask_t add_entry(hddb2_data_t *hddb2, tmp_entry_t *te, hddb_entry_t idx, char *str)
867
hddb_entry_mask_t mask = 0;
869
unsigned u, u0, u1, u2;
871
str_list_t *sl, *sl0;
873
for(i = 0; (unsigned) i < sizeof hddb_is_numeric / sizeof *hddb_is_numeric; i++) {
874
if(idx == hddb_is_numeric[i]) break;
877
if((unsigned) i < sizeof hddb_is_numeric / sizeof *hddb_is_numeric) {
882
if(idx == he_hwclass) {
883
sl0 = hd_split('|', str);
884
for(u0 = u1 = 0, sl = sl0; sl && u1 <= 16; sl = sl->next) {
885
u = hd_hw_item_type(sl->str);
896
i = parse_id(str, &u0, &u1, &u2);
901
add_value(te, idx, MAKE_DATA(FLAG_ID, u0));
905
add_value(te, idx, MAKE_DATA(FLAG_RANGE, u1));
906
add_value(te, idx, MAKE_DATA(FLAG_ID, u0));
910
add_value(te, idx, MAKE_DATA(FLAG_MASK, u2));
911
add_value(te, idx, MAKE_DATA(FLAG_ID, u0));
919
if(idx < he_nomask) {
923
u = store_string(hddb2, str);
924
// fprintf(stderr, ">>> %s\n", str);
925
add_value(te, idx, MAKE_DATA(FLAG_STRING, u));
930
if(idx == he_class_id) {
931
i = parse_id(str, &u0, &u1, &u2);
933
u = ID_VALUE(u0) >> 8;
934
add_value(te, he_baseclass_id, MAKE_DATA(FLAG_ID, u));
936
add_value(te, he_subclass_id, MAKE_DATA(FLAG_ID, u));
937
/* add_value(te, he_progif_id, MAKE_DATA(FLAG_ID, 0)); */
938
mask |= (1 << he_baseclass_id) + (1 << he_subclass_id) /* + (1 << he_progif_id) */;
942
case he_driver_module_insmod:
946
case he_driver_module_modprobe:
950
case he_driver_module_config:
954
case he_driver_xfree:
958
case he_driver_xfree_config:
962
case he_driver_mouse:
966
case he_driver_display:
979
s = new_mem(strlen(str) + 3);
983
mask |= add_entry(hddb2, te, he_driver, s);
994
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
995
void hddb_dump_raw(hddb2_data_t *hddb, FILE *f)
998
unsigned u, fl, v, t, id;
1003
fprintf(f, "=== strings 0x%05x/0x%05x ===\n", hddb->strings_len, hddb->strings_max);
1005
for(s = hddb->strings, i = 0, u = 0; u < hddb->strings_len; u++) {
1006
if(!hddb->strings[u]) {
1007
fprintf(f, "%4d (0x%05x): \"%s\"\n", i, (unsigned) (s - hddb->strings), s);
1009
s = hddb->strings + u + 1;
1013
fprintf(f, "\n=== ids 0x%05x/0x%05x ===\n", hddb->ids_len, hddb->ids_max);
1015
for(u = 0; u < hddb->ids_len; u++) {
1016
fprintf(f, "0x%05x: 0x%08x ", u, hddb->ids[u]);
1017
if(hddb->ids[u] & (1 << 31)) fprintf(f, " ");
1018
fl = DATA_FLAG(hddb->ids[u]) & 0x7;
1019
v = DATA_VALUE(hddb->ids[u]);
1020
if(fl == FLAG_STRING && v < hddb->strings_len) {
1021
fprintf(f, "\"%s\"", hddb->strings + v);
1023
else if(fl == FLAG_MASK) {
1024
fprintf(f, "&0x%04x", v);
1026
else if(fl == FLAG_RANGE) {
1027
fprintf(f, "+0x%04x", v);
1029
else if(fl == FLAG_ID) {
1032
fprintf(f, "%s0x%04x", hid_tag_name(t), id);
1034
fprintf(f, " (%s)", eisa_vendor_str(id));
1040
fprintf(f, "\n=== search list 0x%05x/0x%05x ===\n", hddb->list_len, hddb->list_max);
1042
for(u = 0; u < hddb->list_len; u++) {
1044
"%4d: 0x%08x 0x%08x 0x%05x 0x%05x\n",
1045
u, hddb->list[u].key_mask, hddb->list[u].value_mask,
1046
hddb->list[u].key, hddb->list[u].value
1052
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1053
void hddb_dump_ent_name(hddb2_data_t *hddb, FILE *f, char pre, hddb_entry_t ent)
1055
int len, tab_ind = 24;
1057
if(ent >= sizeof hddb_entry_strings / sizeof *hddb_entry_strings) return;
1059
fprintf(f, "%c%s\t", pre, hddb_entry_strings[ent]);
1061
len = strlen(hddb_entry_strings[ent]) + 1;
1063
for(len = (len & ~7) + 8; len < tab_ind; len += 8) {
1069
void hddb_dump_skey(hddb2_data_t *hddb, FILE *f, prefix_t pre, hddb_entry_mask_t key_mask, unsigned key)
1071
static char pref_char[5] = { ' ', ' ', '&', '|', '+' };
1073
unsigned rm_val = 0, r_or_m = 0;
1074
unsigned fl, val, *ids, id, tag, u;
1078
if(pre >= sizeof pref_char) return;
1080
if(key >= hddb->ids_len) return;
1082
ids = hddb->ids + key;
1084
for(ent = 0; ent < he_nomask && key_mask; ent++, key_mask >>= 1) {
1085
if(!(key_mask & 1)) continue;
1087
fl = DATA_FLAG(*ids);
1088
val = DATA_VALUE(*ids);
1092
while((fl & FLAG_CONT)) {
1093
if(fl == (FLAG_CONT | FLAG_RANGE)) {
1097
else if(fl == (FLAG_CONT | FLAG_MASK)) {
1107
fl = DATA_FLAG(*ids);
1108
val = DATA_VALUE(*ids);
1113
if(ent != he_driver) {
1114
hddb_dump_ent_name(hddb, f, pref_char[pre], ent);
1119
if(ent == he_hwclass) {
1121
for(u = (val & 0xffffff); u; u >>= 8) {
1122
s = hd_hw_item_name(u & 0xff);
1123
if(s) fprintf(f, "%s", s);
1124
if(u > 0x100) fprintf(f, "|");
1127
else if(tag == TAG_EISA && (ent == he_vendor_id || ent == he_subvendor_id)) {
1128
fprintf(f, "%s", eisa_vendor_str(id));
1132
if(ent == he_bus_id || ent == he_subclass_id || ent == he_progif_id) {
1135
else if(ent == he_baseclass_id) {
1138
fprintf(f, "%s0x%0*x", hid_tag_name(tag), u, id);
1141
fprintf(f, "%c0x%04x", r_or_m == 1 ? '+' : '&', rm_val);
1144
else if(fl == FLAG_STRING) {
1145
if(val < hddb->strings_len) {
1146
str_val = hddb->strings + val;
1147
fprintf(f, "%s", str_val);
1156
fl = DATA_FLAG(*ids) & ~FLAG_CONT;
1157
val = DATA_VALUE(*ids);
1158
if(fl != FLAG_STRING) break;
1160
if(val < hddb->strings_len) str_val = hddb->strings + val;
1162
if(!*str_val && !str_val[1] == '\t') break;
1166
i = he_driver_xfree;
1170
i = he_driver_xfree_config;
1174
i = he_driver_module_insmod;
1178
i = he_driver_module_modprobe;
1182
i = he_driver_module_config;
1186
i = he_driver_mouse;
1190
i = he_driver_display;
1203
hddb_dump_ent_name(hddb, f, pref_char[pre], i);
1204
fprintf(f, "%s\n", str_val + 2);
1206
while((*ids & (1 << 31)));
1209
/* at this point 'ids' must be the _current_ entry (_not_ the next) */
1211
/* skip potential garbage/unhandled entries */
1212
while((*ids & (1 << 31))) ids++;
1216
if(pre != pref_add) pre = pref_and;
1221
void hddb_dump(hddb2_data_t *hddb, FILE *f)
1227
for(u = 0; u < hddb->list_len; u++) {
1228
hddb_dump_skey(hddb, f, pref_new, hddb->list[u].key_mask, hddb->list[u].key);
1229
hddb_dump_skey(hddb, f, pref_add, hddb->list[u].value_mask, hddb->list[u].value);
1235
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1236
int compare_ids(hddb2_data_t *hddb, hddb_search_t *hs, hddb_entry_mask_t mask, unsigned key)
1239
unsigned rm_val = 0, r_or_m = 0, res = 0;
1240
unsigned fl, val, ok, *ids, id;
1241
char *str, *str_val;
1243
if(key >= hddb->ids_len) return 1;
1245
ids = hddb->ids + key;
1247
for(ent = 0; ent < he_nomask && mask && !res; ent++, mask >>= 1) {
1248
if(!(mask & 1)) continue;
1250
fl = DATA_FLAG(*ids);
1251
val = DATA_VALUE(*ids);
1255
while((fl & FLAG_CONT)) {
1256
if(fl == (FLAG_CONT | FLAG_RANGE)) {
1260
else if(fl == (FLAG_CONT | FLAG_MASK)) {
1270
fl = DATA_FLAG(*ids);
1271
val = DATA_VALUE(*ids);
1277
str = str_val = NULL;
1286
case he_baseclass_id:
1287
id = hs->base_class.id;
1290
case he_subclass_id:
1291
id = hs->sub_class.id;
1295
id = hs->prog_if.id;
1306
case he_subvendor_id:
1307
id = hs->sub_vendor.id;
1310
case he_subdevice_id:
1311
id = hs->sub_device.id;
1315
id = hs->revision.id;
1318
case he_detail_ccw_data_cu_model:
1319
id = hs->cu_model.id;
1323
/* not allowed as search key */
1332
else if(fl == FLAG_STRING) {
1333
if(val < hddb->strings_len) str_val = hddb->strings + val;
1340
case he_baseclass_name:
1341
str = hs->base_class.name;
1344
case he_subclass_name:
1345
str = hs->sub_class.name;
1348
case he_progif_name:
1349
str = hs->prog_if.name;
1352
case he_vendor_name:
1353
str = hs->vendor.name;
1356
case he_device_name:
1357
str = hs->device.name;
1360
case he_subvendor_name:
1361
str = hs->sub_vendor.name;
1364
case he_subdevice_name:
1365
str = hs->sub_device.name;
1369
str = hs->revision.name;
1389
if(id < val || id >= val + rm_val) res = 1;
1393
if((id & ~rm_val) != val) res = 1;
1397
if(id != val) res = 1;
1402
if(str && str_val) {
1403
if(strcmp(str, str_val)) res = 1;
1419
"cmp: 0x%05x: (ent = %2d, id = 0x%x, val = 0x%x%c0x%x) = %d\n",
1420
key, ent, id, val, r_or_m == 1 ? '+' : '&', rm_val, res
1425
"cmp: 0x%05x: (ent = %2d, id = 0x%x, val = 0x%x) = %d\n",
1426
key, ent, id, val, res
1433
"cmp: 0x%05x: (ent = %2d, id = \"%s\", val = \"%s\") = %d\n",
1434
key, ent, str, str_val, res
1440
printf("cmp: 0x%05x: (ent = %2d, *** unhandled key ***) = %d\n", key, ent, res);
1444
/* at this point 'ids' must be the _current_ entry (_not_ the next) */
1446
/* skip potential garbage/unhandled entries */
1447
while((*ids & (1 << 31))) ids++;
1457
hddb2_data_t *hddb, hddb_search_t *hs,
1458
hddb_entry_mask_t key_mask, hddb_entry_mask_t mask, unsigned val_idx
1463
unsigned fl, val, ok;
1464
char **str, *str_val;
1466
if(val_idx >= hddb->ids_len) return;
1468
ids = hddb->ids + val_idx;
1470
for(ent = 0; ent < he_nomask && mask; ent++, mask >>= 1) {
1471
if(!(mask & 1)) continue;
1473
fl = DATA_FLAG(*ids);
1474
val = DATA_VALUE(*ids);
1489
case he_baseclass_id:
1490
id = &hs->base_class.id;
1493
case he_subclass_id:
1494
id = &hs->sub_class.id;
1498
id = &hs->prog_if.id;
1502
id = &hs->vendor.id;
1506
id = &hs->device.id;
1509
case he_subvendor_id:
1510
id = &hs->sub_vendor.id;
1513
case he_subdevice_id:
1514
id = &hs->sub_device.id;
1518
id = &hs->revision.id;
1521
case he_detail_ccw_data_cu_model:
1522
id = &hs->cu_model.id;
1534
else if(fl == FLAG_STRING) {
1535
if(val < hddb->strings_len) str_val = hddb->strings + val;
1539
str = &hs->bus.name;
1542
case he_baseclass_name:
1543
str = &hs->base_class.name;
1546
case he_subclass_name:
1547
str = &hs->sub_class.name;
1550
case he_progif_name:
1551
str = &hs->prog_if.name;
1554
case he_vendor_name:
1555
str = &hs->vendor.name;
1558
case he_device_name:
1559
str = &hs->device.name;
1562
case he_subvendor_name:
1563
str = &hs->sub_vendor.name;
1566
case he_subdevice_name:
1567
str = &hs->sub_device.name;
1571
str = &hs->revision.name;
1583
str = &hs->requires;
1593
(hs->value_mask[ent] & key_mask) == hs->value_mask[ent] &&
1594
key_mask != hs->value_mask[ent]
1596
hs->value_mask[ent] = key_mask;
1597
hs->value |= 1 << ent;
1600
/* don't change if already set */
1605
if((hs->value & (1 << ent))) {
1606
/* don't change if already set */
1609
else if(ent != he_driver) {
1610
hs->value |= 1 << ent;
1619
printf("add: 0x%05x: (ent = %2d, val = 0x%08x)\n", val_idx, ent, val);
1626
printf("add: 0x%05x: (ent = %2d, val = \"%s\")\n", val_idx, ent, str_val);
1632
hs->driver = free_str_list(hs->driver);
1635
fl = DATA_FLAG(*ids) & ~FLAG_CONT;
1636
val = DATA_VALUE(*ids);
1637
if(fl != FLAG_STRING) break;
1639
if(val < hddb->strings_len) str_val = hddb->strings + val;
1642
printf("add: 0x%05x: (ent = %2d, val = \"%s\")\n", val_idx, ent, str_val);
1644
add_str_list(&hs->driver, str_val);
1646
while((*ids & (1 << 31)));
1654
printf("add: 0x%05x: (ent = %2d, *** unhandled value ***)\n", val_idx, ent);
1658
/* at this point 'ids' must be the _current_ entry (_not_ the next) */
1660
/* skip potential garbage/unhandled entries */
1661
while((*ids & (1 << 31))) ids++;
1667
int hddb_search(hd_data_t *hd_data, hddb_search_t *hs, int max_recursions)
1673
hddb_entry_mask_t all_values = 0;
1677
if(!max_recursions) max_recursions = 2;
1679
while(max_recursions--) {
1680
for(db_idx = 0; (unsigned) db_idx < sizeof hd_data->hddb2 / sizeof *hd_data->hddb2; db_idx++) {
1681
if(!(hddb = hd_data->hddb2[db_idx])) continue;
1683
for(u = 0; u < hddb->list_len; u++) {
1685
(hs->key & hddb->list[u].key_mask) == hddb->list[u].key_mask
1686
/* && (hs->value & hddb->list[u].value_mask) != hddb->list[u].value_mask */
1688
i = compare_ids(hddb, hs, hddb->list[u].key_mask, hddb->list[u].key);
1690
complete_ids(hddb, hs,
1691
hddb->list[u].key_mask,
1692
hddb->list[u].value_mask, hddb->list[u].value
1699
all_values |= hs->value;
1701
if(!max_recursions) break;
1703
hs->key |= hs->value;
1705
memset(hs->value_mask, 0, sizeof hs->value_mask);
1708
hs->value = all_values;
1713
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1715
void test_db(hd_data_t *hd_data)
1717
hddb_search_t hs = {};
1721
hs.key |= (1 << he_bus_id) + (1 << he_serial);
1723
hs.serial = "ser 0123";
1725
i = hddb_search(hd_data, &hs, 0);
1727
printf("%d, >%s<\n", i, hs.bus.name);
1732
str_list_t *hddb_get_packages(hd_data_t *hd_data)
1738
unsigned device_class(hd_data_t *hd_data, unsigned vendor, unsigned device)
1740
hddb_search_t hs = {};
1742
hs.vendor.id = vendor;
1743
hs.device.id = device;
1744
hs.key |= (1 << he_vendor_id) + (1 << he_device_id);
1746
hddb_search(hd_data, &hs, 1);
1749
(hs.value & ((1 << he_baseclass_id) + (1 << he_subclass_id))) ==
1750
((1 << he_baseclass_id) + (1 << he_subclass_id))
1752
return (hs.base_class.id << 8) + (hs.sub_class.id & 0xff);
1759
unsigned sub_device_class(hd_data_t *hd_data, unsigned vendor, unsigned device, unsigned sub_vendor, unsigned sub_device)
1761
hddb_search_t hs = {};
1763
hs.vendor.id = vendor;
1764
hs.device.id = device;
1765
hs.sub_vendor.id = sub_vendor;
1766
hs.sub_device.id = sub_device;
1767
hs.key |= (1 << he_vendor_id) + (1 << he_device_id) + (1 << he_subvendor_id) + (1 << he_subdevice_id);
1769
hddb_search(hd_data, &hs, 1);
1772
(hs.value & ((1 << he_baseclass_id) + (1 << he_subclass_id))) ==
1773
((1 << he_baseclass_id) + (1 << he_subclass_id))
1775
return (hs.base_class.id << 8) + (hs.sub_class.id & 0xff);
1782
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1783
void hddb_add_info(hd_data_t *hd_data, hd_t *hd)
1785
hddb_search_t hs = {};
1786
driver_info_t *new_driver_info = NULL;
1792
if(hd->tag.fixed) return;
1794
hs.bus.id = hd->bus.id;
1795
hs.key |= 1 << he_bus_id;
1797
hs.base_class.id = hd->base_class.id;
1798
hs.key |= 1 << he_baseclass_id;
1800
hs.sub_class.id = hd->sub_class.id;
1801
hs.key |= 1 << he_subclass_id;
1803
hs.prog_if.id = hd->prog_if.id;
1804
hs.key |= 1 << he_progif_id;
1807
hs.vendor.id = hd->vendor.id;
1808
hs.key |= 1 << he_vendor_id;
1811
if(hd->vendor.name) {
1812
hs.vendor.name = hd->vendor.name;
1813
hs.key |= 1 << he_vendor_name;
1817
hs.device.id = hd->device.id;
1818
hs.key |= 1 << he_device_id;
1821
if(hd->device.name) {
1822
hs.device.name = hd->device.name;
1823
hs.key |= 1 << he_device_name;
1826
if(hd->sub_vendor.id) {
1827
hs.sub_vendor.id = hd->sub_vendor.id;
1828
hs.key |= 1 << he_subvendor_id;
1831
if(hd->sub_device.id) {
1832
hs.sub_device.id = hd->sub_device.id;
1833
hs.key |= 1 << he_subdevice_id;
1836
hs.revision.id = hd->revision.id;
1837
hs.key |= 1 << he_rev_id;
1839
if(hd->revision.name) {
1840
hs.revision.name = hd->revision.name;
1841
hs.key |= 1 << he_rev_name;
1845
hs.serial = hd->serial;
1846
hs.key |= 1 << he_serial;
1849
if(hd->detail && hd->detail->ccw.data) {
1850
hs.cu_model.id=hd->detail->ccw.data->cu_model;
1851
hs.key |= 1 << he_detail_ccw_data_cu_model;
1854
hddb_search(hd_data, &hs, 0);
1856
if((hs.value & (1 << he_bus_id))) {
1857
hd->bus.id = hs.bus.id;
1860
if((hs.value & (1 << he_bus_name))) {
1861
if(!hd->ref) free_mem(hd->bus.name);
1862
hd->bus.name = new_str(hs.bus.name);
1865
if((hs.value & (1 << he_baseclass_id))) {
1866
hd->base_class.id = hs.base_class.id;
1869
if((hs.value & (1 << he_baseclass_name))) {
1870
if(!hd->ref) free_mem(hd->base_class.name);
1871
hd->base_class.name = new_str(hs.base_class.name);
1874
if((hs.value & (1 << he_subclass_id))) {
1875
hd->sub_class.id = hs.sub_class.id;
1878
if((hs.value & (1 << he_subclass_name))) {
1879
if(!hd->ref) free_mem(hd->sub_class.name);
1880
hd->sub_class.name = new_str(hs.sub_class.name);
1883
if((hs.value & (1 << he_progif_id))) {
1884
hd->prog_if.id = hs.prog_if.id;
1887
if((hs.value & (1 << he_progif_name))) {
1888
if(!hd->ref) free_mem(hd->prog_if.name);
1889
hd->prog_if.name = new_str(hs.prog_if.name);
1892
if((hs.value & (1 << he_requires))) {
1893
if(!hd->ref) hd->requires = free_str_list(hd->requires);
1894
hd->requires = hd_split('|', hs.requires);
1897
if((hs.value & (1 << he_vendor_id))) {
1898
hd->vendor.id = hs.vendor.id;
1901
if((hs.value & (1 << he_vendor_name))) {
1902
if(!hd->ref) free_mem(hd->vendor.name);
1903
hd->vendor.name = new_str(hs.vendor.name);
1906
if((hs.value & (1 << he_device_id))) {
1907
hd->device.id = hs.device.id;
1910
if((hs.value & (1 << he_device_name))) {
1911
if(!hd->ref) free_mem(hd->device.name);
1912
hd->device.name = new_str(hs.device.name);
1915
if((hs.value & (1 << he_subvendor_id))) {
1916
hd->sub_vendor.id = hs.sub_vendor.id;
1919
if((hs.value & (1 << he_subvendor_name))) {
1920
if(!hd->ref) free_mem(hd->sub_vendor.name);
1921
hd->sub_vendor.name = new_str(hs.sub_vendor.name);
1924
if((hs.value & (1 << he_subdevice_id))) {
1925
hd->sub_device.id = hs.sub_device.id;
1928
if((hs.value & (1 << he_subdevice_name))) {
1929
if(!hd->ref) free_mem(hd->sub_device.name);
1930
hd->sub_device.name = new_str(hs.sub_device.name);
1933
if((hs.value & (1 << he_detail_ccw_data_cu_model))) {
1934
if(hd->detail && hd->detail->ccw.data)
1935
hd->detail->ccw.data->cu_model=hs.cu_model.id;
1938
if((hs.value & (1 << he_hwclass))) {
1939
for(u = hs.hwclass; u; u >>= 8) {
1940
hd_set_hw_class(hd, u & 0xff);
1944
/* look for sub vendor again */
1946
if(!hd->sub_vendor.name && hd->sub_vendor.id) {
1947
hddb_search_t hs2 = {};
1949
hs2.vendor.id = hd->sub_vendor.id;
1950
hs2.key |= 1 << he_vendor_id;
1952
hddb_search(hd_data, &hs2, 1);
1954
if((hs2.value & (1 << he_vendor_name))) {
1955
hd->sub_vendor.name = new_str(hs2.vendor.name);
1959
/* look for compat device name */
1961
hd->compat_vendor.id &&
1962
hd->compat_device.id &&
1963
!hd->compat_vendor.name &&
1964
!hd->compat_device.name
1966
hddb_search_t hs2 = {};
1968
hs2.vendor.id = hd->compat_vendor.id;
1969
hs2.key |= 1 << he_vendor_id;
1971
hs2.device.id = hd->compat_device.id;
1972
hs2.key |= 1 << he_device_id;
1974
hddb_search(hd_data, &hs2, 1);
1976
if((hs2.value & (1 << he_vendor_name))) {
1977
hd->compat_vendor.name = new_str(hs2.vendor.name);
1980
if((hs2.value & (1 << he_device_name))) {
1981
hd->compat_device.name = new_str(hs2.device.name);
1985
/* get package info for compat device id */
1988
hddb_search_t hs2 = {};
1990
hs2.vendor.id = hd->compat_vendor.id;
1991
hs2.key |= 1 << he_vendor_id;
1993
hs2.device.id = hd->compat_device.id;
1994
hs2.key |= 1 << he_device_id;
1996
hddb_search(hd_data, &hs2, 1);
1998
if((hs2.value & (1 << he_requires))) {
1999
hd->requires = hd_split('|', hs2.requires);
2003
/* get driver info */
2006
if((cic = get_isdn_info(hd))) {
2007
new_driver_info = isdn_driver(hd_data, hd, cic);
2008
if(!hd->model && cic->lname && *cic->lname) {
2009
hd->model = new_str(cic->lname);
2013
if (!new_driver_info && ((cic = get_dsl_info(hd)))) {
2014
new_driver_info = dsl_driver(hd_data, hd, cic);
2015
if(!hd->model && cic->lname && *cic->lname) {
2016
hd->model = new_str(cic->lname);
2022
if(!new_driver_info) {
2023
new_driver_info = hd_modinfo_db(hd_data, hd_data->modinfo_ext, hd, new_driver_info);
2027
if(!new_driver_info && (hs.value & (1 << he_driver))) {
2028
new_driver_info = hddb_to_device_driver(hd_data, &hs);
2031
if(!new_driver_info && (hd->compat_vendor.id || hd->compat_device.id)) {
2032
memset(&hs, 0, sizeof hs);
2034
if(hd->compat_vendor.id) {
2035
hs.vendor.id = hd->compat_vendor.id;
2036
hs.key |= 1 << he_vendor_id;
2038
if(hd->compat_device.id) {
2039
hs.device.id = hd->compat_device.id;
2040
hs.key |= 1 << he_device_id;
2043
hddb_search(hd_data, &hs, 1);
2045
if((hs.value & (1 << he_driver))) {
2046
new_driver_info = hddb_to_device_driver(hd_data, &hs);
2051
/* acpi: load temperature control modules */
2052
if(!new_driver_info && hd->is.with_acpi) {
2053
memset(&hs, 0, sizeof hs);
2055
hs.vendor.id = MAKE_ID(TAG_SPECIAL, 0xf001);
2056
hs.key |= 1 << he_vendor_id;
2058
hs.device.id = MAKE_ID(TAG_SPECIAL, 4);
2059
hs.key |= 1 << he_device_id;
2061
hddb_search(hd_data, &hs, 1);
2063
if((hs.value & (1 << he_driver))) {
2064
new_driver_info = hddb_to_device_driver(hd_data, &hs);
2068
if(!new_driver_info && hd->base_class.id == bc_keyboard) {
2069
new_driver_info = kbd_driver(hd_data, hd);
2072
if(!new_driver_info && hd->base_class.id == bc_monitor) {
2073
new_driver_info = monitor_driver(hd_data, hd);
2076
new_driver_info = hd_modinfo_db(hd_data, hd_data->modinfo, hd, new_driver_info);
2078
if(new_driver_info) {
2080
hd->driver_info = free_driver_info(hd->driver_info);
2082
hd->driver_info = new_driver_info;
2083
expand_driver_info(hd_data, hd);
2086
free_str_list(hs.driver);
2090
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2091
driver_info_t *hddb_to_device_driver(hd_data_t *hd_data, hddb_search_t *hs)
2094
driver_info_t *di = NULL, *di0 = NULL;
2097
for(sl = hs->driver; sl; sl = sl->next) {
2098
if(!sl->str || !*sl->str || sl->str[1] != '\t') return NULL;
2100
if(di && (*sl->str == 'M' || *sl->str == 'X')) {
2101
add_str_list(&di->any.hddb1, sl->str + 2);
2106
di = di->next = new_mem(sizeof *di);
2108
di = di0 = new_mem(sizeof *di);
2112
di->any.type = di_display;
2116
di->module.modprobe = 1;
2118
di->any.type = di_module;
2122
di->any.type = di_mouse;
2126
di->any.type = di_x11;
2130
di->any.type = di_any;
2133
s = new_str(sl->str + 2);
2134
for(t0 = s; (t = strsep(&t0, "|")); ) {
2135
add_str_list(&di->any.hddb0, t);
2144
driver_info_t *kbd_driver(hd_data_t *hd_data, hd_t *hd)
2147
driver_info_kbd_t *ki;
2148
int arch = hd_cpu_arch(hd_data);
2157
3 Canadian-Bilingual
2167
13 International (ISO)
2172
18 Netherlands/Dutch
2194
} country_code[] = {
2195
{ 5, "cs", "cz-us-qwertz" },
2196
{ 8, "fr", "fr-latin1" },
2197
{ 9, "de", "de-latin1-nodeadkeys" },
2201
{ 23, "ru", "ru1" },
2207
if(hd->sub_class.id == sc_keyboard_console) return NULL;
2209
di = new_mem(sizeof *di);
2210
di->kbd.type = di_kbd;
2217
ki->XkbRules = new_str("xfree86");
2218
ki->XkbModel = new_str("pc104");
2223
ki->XkbRules = new_str("xfree86");
2224
ki->XkbModel = new_str("macintosh");
2225
for(hd_tmp = hd_data->hd; hd_tmp; hd_tmp = hd_tmp->next) {
2227
hd_tmp->base_class.id == bc_internal &&
2228
hd_tmp->sub_class.id == sc_int_cpu &&
2230
hd_tmp->detail->type == hd_detail_cpu &&
2231
hd_tmp->detail->cpu.data
2233
s1 = hd_tmp->detail->cpu.data->vend_name;
2234
if(s1 && (strstr(s1, "CHRP ") == s1 || strstr(s1, "PReP ") == s1)) {
2235
free_mem(ki->XkbModel);
2236
ki->XkbModel = new_str("pc104");
2244
if(hd->vendor.id == MAKE_ID(TAG_SPECIAL, 0x0202)) {
2245
ki->XkbRules = new_str("sun");
2246
u = ID_VALUE(hd->device.id);
2247
if(u == 4) ki->XkbModel = new_str("type4");
2249
ki->XkbModel = new_str(ID_VALUE(hd->sub_device.id) == 2 ? "type5_euro" : "type5");
2253
switch(hd->prog_if.id) {
2254
case 0: case 1: case 33: case 34: case 80: case 81:
2256
s1 = "us"; s2 = "sunkeymap";
2260
s1 = "fr"; s2 = "sunt5-fr-latin1"; // fr_BE?
2267
case 4: case 36: case 83:
2271
case 5: case 37: case 84:
2272
s1 = "de"; s2 = "sunt5-de-latin1";
2275
case 6: case 38: case 85:
2279
case 7: case 39: case 86:
2283
case 8: case 40: case 87:
2285
if(u == 4) s2 = "sunt4-no-latin1";
2288
case 9: case 41: case 88:
2292
case 10: case 42: case 89:
2294
s2 = u == 4 ? "sunt4-es" : "sunt5-es";
2297
case 11: case 43: case 90:
2298
s1 = "se"; s2 = "sunt5-fi-latin1"; // se is swedish, not fi
2301
case 12: case 44: case 91:
2302
s1 = "fr"; s2 = "sunt5-fr-latin1"; // fr_CH
2305
case 13: case 45: case 92:
2306
s1 = "de"; s2 = "sunt5-de-latin1"; // de_CH
2309
case 14: case 46: case 93:
2310
s1 = "gb"; s2 = "sunt5-uk";
2313
case 16: case 47: case 94:
2317
case 17: case 48: case 95:
2321
case 32: case 49: case 96:
2326
s1 = "fr"; s2 = "sunt5-fr-latin1"; // fr_CA
2334
s1 = "pl"; s2 = "sun-pl";
2342
s1 = "ru"; s2 = "sunt5-ru";
2345
ki->XkbLayout = new_str(s1);
2346
ki->keymap = new_str(s2);
2349
ki->XkbRules = new_str("xfree86");
2350
ki->XkbModel = new_str("pc104");
2355
ki->XkbRules = new_str("xfree86");
2359
hd->bus.id == bus_usb &&
2361
hd->detail->type == hd_detail_usb &&
2362
(usb = hd->detail->usb.data) &&
2365
for(u = 0; u < sizeof country_code / sizeof *country_code; u++) {
2366
if(country_code[u].country == usb->country) {
2367
if(!ki->XkbLayout) ki->XkbLayout = new_str(country_code[u].layout);
2368
if(!ki->keymap) ki->keymap = new_str(country_code[u].keymap);
2378
driver_info_t *monitor_driver(hd_data_t *hd_data, hd_t *hd)
2380
driver_info_t *di = NULL;
2381
driver_info_display_t *ddi;
2384
unsigned width = 640, height = 480;
2388
hd->detail->type == hd_detail_monitor &&
2389
(mi = hd->detail->monitor.data) &&
2392
di = new_mem(sizeof *di);
2393
di->display.type = di_display;
2394
ddi = &(di->display);
2396
ddi->min_vsync = mi->min_vsync;
2397
ddi->max_vsync = mi->max_vsync;
2398
ddi->min_hsync = mi->min_hsync;
2399
ddi->max_hsync = mi->max_hsync;
2400
ddi->bandwidth = mi->clock / 1000;
2401
ddi->hdisp = mi->hdisp;
2402
ddi->hsyncstart= mi->hsyncstart;
2403
ddi->hsyncend = mi->hsyncend;
2404
ddi->htotal = mi->htotal;
2405
ddi->hflag = mi->hflag;
2406
ddi->vdisp = mi->vdisp;
2407
ddi->vsyncstart= mi->vsyncstart;
2408
ddi->vsyncend = mi->vsyncend;
2409
ddi->vtotal = mi->vtotal;
2410
ddi->vflag = mi->vflag;
2412
for(res = hd->res; res; res = res->next) {
2413
if(res->any.type == res_monitor) {
2414
if(res->monitor.width * res->monitor.height > width * height ) {
2415
width = res->monitor.width;
2416
height = res->monitor.height;
2422
ddi->height = height;
2432
int chk_free_biosmem(hd_data_t *hd_data, unsigned addr, unsigned len)
2437
addr -= hd_data->bios_rom.start;
2439
!hd_data->bios_rom.data ||
2440
addr >= hd_data->bios_rom.size ||
2441
addr + len > hd_data->bios_rom.size
2444
for(c = 0xff, u = addr; u < addr + len; u++) {
2445
c &= hd_data->bios_rom.data[u];
2448
return c == 0xff ? 1 : 0;
2451
isdn_parm_t *new_isdn_parm(isdn_parm_t **ip)
2453
while(*ip) ip = &(*ip)->next;
2455
return *ip = new_mem(sizeof **ip);
2459
driver_info_t *isdn_driver(hd_data_t *hd_data, hd_t *hd, cdb_isdn_card *cic)
2461
driver_info_t *di0, *di;
2462
cdb_isdn_vario *civ;
2464
uint64_t i, irqs, irqs2;
2468
str_list_t *sl, *sl0;
2470
if(!cic) return NULL;
2472
di0 = new_mem(sizeof *di0);
2477
while((civ = hd_cdbisdn_get_vario(drv))) {
2478
drv = civ->next_vario;
2480
di->next = new_mem(sizeof *di);
2485
di->isdn.type = di_isdn;
2486
di->isdn.i4l_type = civ->typ;
2487
di->isdn.i4l_subtype = civ->subtyp;
2488
di->isdn.i4l_name = new_str(cic->lname);
2490
if(civ->need_pkg && *civ->need_pkg) {
2491
sl0 = hd_split(',', (char *) civ->need_pkg);
2492
for(sl = sl0; sl; sl = sl->next) {
2493
if(!search_str_list(hd->requires, sl->str)) {
2494
add_str_list(&hd->requires, sl->str);
2500
if(hd->bus.id == bus_pci) continue;
2503
civ = hd_cdbisdn_get_vario(cic->vario);
2505
if (civ->irq && civ->irq[0]) {
2506
ip = new_isdn_parm(&di->isdn.params);
2507
ip->name = new_str("IRQ");
2508
ip->type = CDBISDN_P_IRQ;
2510
if (civ->io && civ->io[0]) {
2511
ip = new_isdn_parm(&di->isdn.params);
2512
ip->name = new_str("IO");
2513
ip->type = CDBISDN_P_IO;
2515
if (civ->membase && civ->membase[0]) {
2516
ip = new_isdn_parm(&di->isdn.params);
2517
ip->name = new_str("MEMBASE");
2518
ip->type = CDBISDN_P_MEM;
2520
while((ipi = hd_ihw_get_parameter(ici->handle, pnr++))) {
2521
ip = new_isdn_parm(&di->isdn.params);
2522
ip->name = new_str(ipi->name);
2523
ip->type = ipi->type & P_TYPE_MASK;
2524
ip->flags = ipi->flags & P_PROPERTY_MASK;
2525
ip->def_value = ipi->def_value;
2526
if(ipi->list) ip->alt_values = *ipi->list;
2527
ip->alt_value = new_mem(ip->alt_values * sizeof *ip->alt_value);
2528
for(i = 0; i < ip->alt_values; i++) {
2529
ip->alt_value[i] = ipi->list[i + 1];
2533
if((ip->flags & P_SOFTSET)) {
2536
update_irq_usage(hd_data);
2538
for(i = 0; i < ip->alt_values; i++) {
2539
irqs |= 1ull << ip->alt_value[i];
2541
irqs &= ~(hd_data->used_irqs | hd_data->assigned_irqs);
2543
irqs &= 0xffffull; /* max. 16 on intel */
2545
* The point is, that this is relevant for isa boards only
2546
* and those have irq values < 16 anyway. So it really
2547
* doesn't matter if we mask with 0xffff or not.
2555
irqs2 = irqs & ~0xc018ull;
2556
/* see if we can avoid irqs 3,4,14,15 */
2557
if(irqs2) irqs = irqs2;
2559
/* try default value first */
2560
if(ip->def_value && (irqs & (1ull << ip->def_value))) {
2561
irq_val = ip->def_value;
2564
for(i = 0; i < 64 && irqs; i++, irqs >>= 1) {
2565
if((irqs & 1)) irq_val = i;
2569
ip->value = irq_val;
2570
hd_data->assigned_irqs |= 1ull << irq_val;
2578
if(!hd_data->bios_rom.data) {
2580
ip->value = ip->def_value;
2584
/* ###### 0x2000 is just guessing -> should be provided by libihw */
2585
if(ip->def_value && chk_free_biosmem(hd_data, ip->def_value, 0x2000)) {
2586
ip->value = ip->def_value;
2589
for(i = ip->alt_values - 1; i >= 0; i--) {
2590
if(chk_free_biosmem(hd_data, ip->alt_value[i], 0x2000)) {
2591
ip->value = ip->alt_value[i];
2597
if(!ip->value) ip->conflict = 1;
2603
else if((ip->flags & P_DEFINE)) {
2607
res = get_res(hd, res_irq, 0);
2608
if(res) ip->value = res->irq.base;
2611
res = get_res(hd, res_mem, 0);
2612
if(res) ip->value = res->mem.base;
2615
res = get_res(hd, res_io, 0);
2616
if(res) ip->value = res->io.base;
2621
res = get_res(hd, res_io, ip->type - P_IO0);
2622
if(res) ip->value = res->io.base;
2624
// ##### might break for 64bit pci entries?
2631
res = get_res(hd, res_mem, ip->type - P_BASE0);
2632
if(res) ip->value = res->mem.base;
2637
if(!res) ip->valid = 0;
2642
if(!di) di0 = free_mem(di0);
2647
driver_info_t *dsl_driver(hd_data_t *hd_data, hd_t *hd, cdb_isdn_card *cic)
2649
driver_info_t *di0, *di;
2650
cdb_isdn_vario *civ;
2652
str_list_t *sl, *sl0;
2654
if(!cic) return NULL;
2656
di0 = new_mem(sizeof *di0);
2661
while((civ = hd_cdbisdn_get_vario(drv))) {
2662
drv = civ->next_vario;
2664
di->next = new_mem(sizeof *di);
2669
di->dsl.type = di_dsl;
2670
if(civ->interface && *civ->interface) {
2671
if (!strcmp(civ->interface, "CAPI20")) {
2672
di->dsl.mode = new_str("capiadsl");
2673
if(civ->mod_name && *civ->mod_name)
2674
di->dsl.name = new_str(civ->mod_name);
2676
di->dsl.name = new_str("unknown");
2677
} else if (!strcmp(civ->interface, "pppoe")) {
2678
di->dsl.mode = new_str("pppoe");
2679
if(civ->mod_name && *civ->mod_name)
2680
di->dsl.name = new_str(civ->mod_name);
2682
di->dsl.name = new_str("none");
2684
di->dsl.mode = new_str("unknown");
2685
di->dsl.name = new_str("unknown");
2688
di->dsl.mode = new_str("unknown");
2689
di->dsl.name = new_str("unknown");
2692
if(civ->need_pkg && *civ->need_pkg) {
2693
sl0 = hd_split(',', (char *) civ->need_pkg);
2694
for(sl = sl0; sl; sl = sl->next) {
2695
if(!search_str_list(hd->requires, sl->str)) {
2696
add_str_list(&hd->requires, sl->str);
2702
if(hd->bus.id == bus_pci) continue;
2704
if(!di) di0 = free_mem(di0);
2709
#endif /* WITH_ISDN */
2712
hd_res_t *get_res(hd_t *hd, enum resource_types t, unsigned index)
2716
for(res = hd->res; res; res = res->next) {
2717
if(res->any.type == t) {
2718
if(!index) return res;
2727
driver_info_t *reorder_x11(driver_info_t *di0, char *info)
2729
driver_info_t *di, *di_new, **di_list;
2732
for(dis = 0, di = di0; di; di = di->next) dis++;
2734
di_list = new_mem(dis * sizeof *di_list);
2736
for(i = 0, di = di0; di; di = di->next) {
2741
for(i = found = 0; i < dis; i++) {
2743
!strcmp(di_list[i]->x11.xf86_ver, info) ||
2744
!strcmp(di_list[i]->x11.server, info)
2748
di = di->next = di_list[i];
2751
di = di_new = di_list[i];
2758
for(i = 0; i < dis; i++) {
2761
di = di->next = di_list[i];
2764
di = di_new = di_list[i];
2773
if(!found && strlen(info) > 1) {
2774
free_driver_info(di_new);
2775
di_new = new_mem(sizeof *di_new);
2776
di_new->any.type = di_x11;
2777
di_new->x11.server = new_str(info);
2778
di_new->x11.xf86_ver = new_str(*info >= 'A' && *info <= 'Z' ? "3" : "4");
2785
void expand_driver_info(hd_data_t *hd_data, hd_t *hd)
2791
str_list_t *sl, *sl1, *sl2, *cmd;
2793
if(!hd || !hd->driver_info) return;
2795
for(di = hd->driver_info; di; di = di->next) {
2796
switch(di->any.type) {
2798
for(i = 0, sl = di->display.hddb0; sl; sl = sl->next, i++) {
2799
if(i == 0 && sscanf(sl->str, "%ux%u", &u1, &u2) == 2) {
2800
di->display.width = u1;
2801
di->display.height = u2;
2803
else if(i == 1 && sscanf(sl->str, "%u-%u", &u1, &u2) == 2) {
2804
di->display.min_vsync = u1;
2805
di->display.max_vsync = u2;
2807
else if(i == 2 && sscanf(sl->str, "%u-%u", &u1, &u2) == 2) {
2808
di->display.min_hsync = u1;
2809
di->display.max_hsync = u2;
2811
else if(i == 3 && sscanf(sl->str, "%u", &u1) == 1) {
2812
di->display.bandwidth = u1;
2818
for(di->module.active = 1, sl = di->module.hddb0; sl; sl = sl->next) {
2819
t0 = s = new_str(sl->str);
2821
t = strsep(&t0, " ");
2823
add_str_list(&di->module.names, t);
2824
di->module.active &= (
2825
hd_module_is_active(hd_data, t) |
2826
(search_str_list(hd->drivers, t) ? 1 : 0)
2830
add_str_list(&di->module.mod_args, module_cmd(hd, t0));
2833
add_str_list(&di->module.mod_args, NULL);
2838
for(sl = di->module.hddb1; sl; sl = sl->next) {
2839
s = module_cmd(hd, sl->str);
2840
if(s) str_printf(&di->module.conf, -1, "%s\n", s);
2845
di->mouse.buttons = di->mouse.wheels = -1;
2848
hd->compat_vendor.id == MAKE_ID(TAG_SPECIAL, 0x0210) &&
2849
ID_TAG(hd->compat_device.id) == TAG_SPECIAL
2851
u1 = hd->compat_device.id;
2854
hd->vendor.id == MAKE_ID(TAG_SPECIAL, 0x0210) &&
2855
ID_TAG(hd->device.id) == TAG_SPECIAL
2860
di->mouse.wheels = ID_VALUE(u1) >> 4;
2861
di->mouse.buttons = ID_VALUE(u1) & 15;
2863
for(i = 0, sl = di->mouse.hddb0; sl; sl = sl->next, i++) {
2865
di->mouse.xf86 = new_str(sl->str);
2868
di->mouse.gpm = new_str(sl->str);
2870
else if(i == 2 && *sl->str) {
2871
di->mouse.buttons = strtol(sl->str, NULL, 10);
2873
else if(i == 3 && *sl->str) {
2874
di->mouse.wheels = strtol(sl->str, NULL, 10);
2880
for(i = 0, sl = di->x11.hddb0; sl; sl = sl->next, i++) {
2882
di->x11.xf86_ver = new_str(sl->str);
2885
di->x11.server = new_str(sl->str);
2888
if(!strcmp(sl->str, "3d")) di->x11.x3d = 1;
2892
s = new_str(sl->str);
2893
for(t0 = s; (t = strsep(&t0, ",")); ) {
2894
add_str_list(&di->x11.packages, t);
2900
s = new_str(sl->str);
2901
for(t0 = s; (t = strsep(&t0, ",")); ) {
2902
add_str_list(&di->x11.extensions, t);
2907
s = new_str(sl->str);
2908
for(t0 = s; (t = strsep(&t0, ",")); ) {
2909
add_str_list(&di->x11.options, t);
2914
for(sl2 = sl1 = hd_split(',', sl->str); sl2; sl2 = sl2->next) {
2915
u1 = strtoul(sl2->str, NULL, 0);
2918
di->x11.colors.c8 = 1;
2919
di->x11.colors.all |= (1 << 0);
2923
di->x11.colors.c15 = 1;
2924
di->x11.colors.all |= (1 << 1);
2928
di->x11.colors.c16 = 1;
2929
di->x11.colors.all |= (1 << 2);
2933
di->x11.colors.c24 = 1;
2934
di->x11.colors.all |= (1 << 3);
2938
di->x11.colors.c32 = 1;
2939
di->x11.colors.all |= (1 << 4);
2946
di->x11.dacspeed = strtol(sl->str, NULL, 10);
2949
di->x11.script = new_str(sl->str);
2952
for(i = 0, sl = di->x11.hddb1; sl; sl = sl->next, i++) {
2953
add_str_list(&di->x11.raw, sl->str);
2956
// ######## for compatibility
2957
for(sl = hd->requires; sl; sl = sl->next) {
2958
add_str_list(&di->x11.packages, sl->str);
2968
di = hd->driver_info;
2969
if(di && di->any.type == di_x11 && !hd_probe_feature(hd_data, pr_ignx11)) {
2970
cmd = get_cmdline(hd_data, "x11");
2971
if(cmd && *cmd->str) {
2972
hd->driver_info = reorder_x11(di, cmd->str);
2979
char *module_cmd(hd_t *hd, char *cmd)
2981
static char buf[256];
2986
// skip inactive PnP cards
2987
// ##### Really necessary here?
2991
hd->detail->isapnp.data &&
2992
!(hd->detail->isapnp.data->flags & (1 << isapnp_flag_act))
2997
if(sscanf(cmd, "<io%u>%n", &idx, &ofs) >= 1) {
2998
if((res = get_res(hd, res_io, idx))) {
2999
s += sprintf(s, "0x%02"PRIx64, res->io.base);
3006
else if(sscanf(cmd, "<irq%u>%n", &idx, &ofs) >= 1) {
3007
if((res = get_res(hd, res_irq, idx))) {
3008
s += sprintf(s, "%u", res->irq.base);
3019
if(s - buf > (int) sizeof buf - 20) return NULL;
3027
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3028
char *hid_tag_name(int tag)
3030
return (unsigned) tag < sizeof hid_tag_names / sizeof *hid_tag_names ? hid_tag_names[tag] : "";
3033
char *hid_tag_name2(int tag)
3035
return (unsigned) tag < sizeof hid_tag_names2 / sizeof *hid_tag_names2 ? hid_tag_names2[tag] : "";