/* * Add udev info. */ void int_udev(hd_data_t *hd_data) { hd_udevinfo_t *ui; hd_t *hd; str_list_t *sl; if(!hd_data->udevinfo) read_udevinfo(hd_data); if(!hd_data->udevinfo) return; for(hd = hd_data->hd; hd; hd = hd->next) { if(!hd->unix_dev_names && hd->unix_dev_name) { add_str_list(&hd->unix_dev_names, hd->unix_dev_name); } if(!hd->sysfs_id) continue; for(ui = hd_data->udevinfo; ui; ui = ui->next) { if(ui->name && !strcmp(ui->sysfs, hd->sysfs_id)) { if(!search_str_list(hd->unix_dev_names, ui->name)) { add_str_list(&hd->unix_dev_names, ui->name); } for(sl = ui->links; sl; sl = sl->next) { if(!search_str_list(hd->unix_dev_names, sl->str)) { add_str_list(&hd->unix_dev_names, sl->str); } } if(!hd->unix_dev_name || hd_data->flags.udev) { sl = hd->unix_dev_names; if(hd_data->flags.udev) { /* use first link as canonical device name */ if(ui->links) sl = sl->next; } hd->unix_dev_name = new_str(sl->str); } break; } } } for(hd = hd_data->hd; hd; hd = hd->next) { if(!hd->unix_dev_names) continue; for(ui = hd_data->udevinfo; ui; ui = ui->next) { if(search_str_list(hd->unix_dev_names, ui->name)) { for(sl = ui->links; sl; sl = sl->next) { if(!search_str_list(hd->unix_dev_names, sl->str)) { add_str_list(&hd->unix_dev_names, sl->str); } } } } } }
void int_update_driver_data(hd_data_t *hd_data, hd_t *hd) { hd_sysfsdrv_t *sf; str_list_t *sl; hd->driver_modules = free_str_list(hd->driver_modules); for(sl = hd->drivers; sl; sl = sl->next) { for(sf = hd_data->sysfsdrv; sf; sf = sf->next) { if(sf->module && !strcmp(sf->driver, sl->str)) { add_str_list(&hd->driver_modules, sf->module); } } } hd->driver = free_mem(hd->driver); hd->driver_module = free_mem(hd->driver_module); if(hd->drivers && hd->drivers->str) { hd->driver = new_str(hd->drivers->str); for(sf = hd_data->sysfsdrv; sf; sf = sf->next) { if(sf->module && !strcmp(sf->driver, hd->driver)) { hd->driver_module = new_str(sf->module); } } } }
t_str *add_str(t_str *begin, char *str, char c) { int i; t_str *list; i = 0; if (!begin) begin = add_str_list(NULL); list = begin; while (list->next) list = list->next; if (str) { while (str[i]) { if (list->index < 32) { list->str[list->index] = str[i]; list->index++; i++; } else { list->next = add_str_list(begin); list = list->next; } } } else if (c) { if (list->index < 32) { list->str[list->index] = c; list->index++; } else { list->next = add_str_list(begin); list = list->next; list->str[list->index] = c; list->index++; } } return (begin); }
void hd2prop_append_list(hal_prop_t **list, const char *key, char *str) { hal_prop_t *prop; str_list_t *sl = NULL; if(!str) return; prop = hal_get_list(*list, key); if(!prop) { add_str_list(&sl, str); hd2prop_add_list(list, key, sl); return; } add_str_list(&prop->val.list, str); }
str_list_t *str_list_dup(str_list_t *orig) { str_list_t *dup = NULL; for(; orig != NULL; orig = orig->next) { add_str_list(&dup, orig->str); } return dup; }
void at_cmd(hd_data_t *hd_data, char *at, int raw, int log_it) { static unsigned u = 1; char *s, *s0; ser_device_t *sm; str_list_t *sl; int modems = 0; for(sm = hd_data->ser_modem; sm; sm = sm->next) { if(sm->do_io) { sm->buf_len = 0; modems++; } } if(modems == 0) return; PROGRESS(9, u, "write at cmd"); write_modem(hd_data, at); PROGRESS(9, u, "read at resp"); usleep (200000); read_modem(hd_data); PROGRESS(9, u, "read ok"); u++; for(sm = hd_data->ser_modem; sm; sm = sm->next) { if(sm->do_io) { sm->at_resp = free_str_list(sm->at_resp); if(sm->buf_len == 0 || raw) continue; s0 = sm->buf; while((s = strsep(&s0, "\r\n"))) { if(*s) add_str_list(&sm->at_resp, s); } } } if(!(hd_data->debug & HD_DEB_MODEM) || !log_it) return; for(sm = hd_data->ser_modem; sm; sm = sm->next) { if(sm->do_io) { ADD2LOG("%s@%u: %s\n", sm->dev_name, sm->cur_baud, at); if(raw) { ADD2LOG(" "); hexdump(&hd_data->log, 1, sm->buf_len, sm->buf); ADD2LOG("\n"); } else { for(sl = sm->at_resp; sl; sl = sl->next) ADD2LOG(" %s\n", sl->str); } } } }
/* * If hd->unix_dev_name is not in hd->unix_dev_names, add it. */ void int_devicenames(hd_data_t *hd_data) { hd_t *hd; for(hd = hd_data->hd; hd; hd = hd->next) { if( hd->unix_dev_name && !search_str_list(hd->unix_dev_names, hd->unix_dev_name) ) { add_str_list(&hd->unix_dev_names, hd->unix_dev_name); } } }
/* * Add driver data, if it is missing. * * Interface function, don't use internally. */ void hd_add_driver_data(hd_data_t *hd_data, hd_t *hd) { char *s; if(hd->drivers) return; hd_sysfs_driver_list(hd_data); s = hd_sysfs_find_driver(hd_data, hd->sysfs_id, 1); if(s) add_str_list(&hd->drivers, s); int_update_driver_data(hd_data, hd); }
str_list_t *prop2hd_list(hal_prop_t *prop, const char *id) { str_list_t *sl0 = NULL, *sl; prop = hal_get_list(prop, id); if(prop) { for(sl = prop->val.list; sl; sl = sl->next) { add_str_list(&sl0, sl->str); } } return sl0; }
void hd2prop_add_list(hal_prop_t **list, const char *key, str_list_t *sl) { hal_prop_t *prop; if(sl) { prop = hal_get_new(list, key); prop->type = p_list; for(; sl; sl = sl->next) { add_str_list(&prop->val.list, sl->str); } } else { hal_invalidate_all(*list, key); } }
/* * Tag ide soft raid disks. */ void int_softraid(hd_data_t *hd_data) { hd_t *hd; str_list_t *raid, *sl, *raid_sysfs = NULL, *sl1; size_t len; char *s; if(hd_data->flags.fast) return; for(hd = hd_data->hd; hd; hd = hd->next) { if( hd->base_class.id == bc_storage_device && hd->status.available != status_no ) break; } /* no disks -> no check necessary */ if(!hd) return; raid = read_file("| /sbin/dmraid -rc 2>/dev/null", 0, 0); for(sl = raid; sl; sl = sl->next) { s = *sl->str ? strchr(sl->str + 1, '/') : NULL; if(s) { sl1 = add_str_list(&raid_sysfs, NULL); str_printf(&sl1->str, 0, "/block%s", s); len = strlen(sl1->str); if(len) sl1->str[len - 1] = 0; } } free_str_list(raid); ADD2LOG("----- soft raid devices -----\n"); for(sl = raid_sysfs; sl; sl = sl->next) { ADD2LOG(" %s\n", sl->str); } ADD2LOG("----- soft raid devices end -----\n"); for(hd = hd_data->hd; hd; hd = hd->next) { if(search_str_list(raid_sysfs, hd->sysfs_id)) { hd->is.softraiddisk = 1; } } free_str_list(raid_sysfs); }
char *export_str(t_str *begin) { int i; int i2; char *str; i = 0; i2 = 0; if (!begin) begin = add_str_list(NULL); str = (char *)malloc(sizeof(char) * str_cpt_index(begin) + 1); if (begin->next) { while (begin->next) { while (i < 32 && begin->str[i] != 0) { str[i2] = begin->str[i]; i2++; i++; } begin = begin->next; i = 0; } while (i < 32 && begin->str[i] != 0) { str[i2] = begin->str[i]; i2++; i++; } } else { while (i < 32 && begin->str[i] != 0) { str[i2] = begin->str[i]; i2++; i++; } } str[i2] = '\0'; return(str); }
int str_cpt_index(t_str *begin) { int total; total = 0; if (!begin) begin = add_str_list(NULL); if (begin->next) { while (begin->next) { total = total + begin->index; begin = begin->next; } total = total + begin->index; return (total); } else while (begin->str[total] != 0) total++; return (total); }
/* * Read kernel log info. Combine with /var/log/boot.msg. * Remove time stamps. */ void read_klog(hd_data_t *hd_data) { str_list_t *sl, **sl_new; char *str, *s; _read_klog(hd_data); free_str_list(hd_data->klog_raw); hd_data->klog_raw = hd_data->klog; hd_data->klog = NULL; for(sl = hd_data->klog_raw, sl_new = &hd_data->klog; sl; sl = sl->next, sl_new = &(*sl_new)->next) { str = add_str_list(sl_new, sl->str)->str; if(str[0] == '<' && str[1] && str[2] == '>' && str[3] == '[') { s = str + 4; while(*s && *s != ']') s++; if(*s) s++; if(*s) s++; // skip space for(str += 3; (*str++ = *s++);); } } }
void hd_scan_wlan(hd_data_t *hd_data) { hd_t *hd; hd_res_t *res; struct iw_range range; int k; int skfd; struct wpa_driver_ops *wpa_drv=NULL; if(!hd_probe_feature(hd_data, pr_wlan)) return; hd_data->module = mod_wlan; PROGRESS(1, 0, "detecting wlan features"); if ((skfd = iw_sockets_open()) < 0) { ADD2LOG( "could not open socket, wlan feature query failed\n" ); return; } for(hd = hd_data->hd; hd; hd = hd->next) { if( hd->base_class.id == bc_network && hd->unix_dev_name ) { /* Get list of frequencies / channels */ if(iw_get_range_info(skfd, hd->unix_dev_name, &range) < 0) { /* this failed, maybe device does not support wireless extensions */ continue; } ADD2LOG("*** device %s is wireless ***\n", hd->unix_dev_name); hd->is.wlan = 1; hd->sub_class.id = 0x82; /* wlan */ res = new_mem(sizeof *res); res->any.type = res_wlan; if(range.num_frequency > 0) { char buff[20]; for(k = 0; k < range.num_frequency; k++) { snprintf(buff, 19, "%i", range.freq[k].i); add_str_list(&res->wlan.channels, buff); snprintf(buff, 19, "%g", (float)iw_freq2float(&(range.freq[k]))/1000000000); add_str_list(&res->wlan.frequencies, buff); } for(k = 0; k < range.num_bitrates; k++) { snprintf(buff, 19, "%g", (float)range.bitrate[k]/1000000); add_str_list(&res->wlan.bitrates, buff); } for(k = 0; k < range.num_encoding_sizes; k++) { snprintf(buff, 19, "WEP%i", range.encoding_size[k]*8); add_str_list(&res->wlan.enc_modes, buff); } /* open mode is always supported */ add_str_list(&res->wlan.auth_modes, "open"); /* if WEP is supported, be assume shared key auth support */ if(range.num_encoding_sizes) { add_str_list(&res->wlan.auth_modes, "sharedkey"); } /* detect WPA capabilities */ if (!hd_data->flags.nowpa && hd->drivers) { if (search_str_list(hd->drivers, "ath_pci")) wpa_drv = &wpa_driver_madwifi_ops; else if (strncmp(hd->drivers->str, "at76", 4)==0) wpa_drv = &wpa_driver_atmel_ops; else wpa_drv = &wpa_driver_wext_ops; } if (wpa_drv) { if (wpa_drv->set_wpa(hd->unix_dev_name, 1) == 0) { add_str_list(&res->wlan.auth_modes, "wpa-psk"); add_str_list(&res->wlan.auth_modes, "wpa-eap"); if (wpa_drv->set_auth_alg && wpa_drv->set_auth_alg(hd->unix_dev_name, AUTH_ALG_LEAP)==0) add_str_list(&res->wlan.auth_modes, "wpa-leap"); if (wpa_drv->set_key(hd->unix_dev_name, WPA_ALG_TKIP, "ff:ff:ff:ff:ff:ff", 0, 0, 0, 0, "00000000000000000000000000000000", 32) ==0) add_str_list(&res->wlan.enc_modes, "TKIP"); if (wpa_drv->set_key(hd->unix_dev_name, WPA_ALG_CCMP, "ff:ff:ff:ff:ff:ff", 0, 0, 0, 0, "0000000000000000", 16) ==0) add_str_list(&res->wlan.enc_modes, "CCMP"); wpa_drv->set_wpa(hd->unix_dev_name, 0); } } } add_res_entry(&hd->res, res); } } }
void hd_scan_net(hd_data_t *hd_data) { unsigned u; int if_type, if_carrier; hd_t *hd, *hd_card; char *s, *t, *hw_addr; hd_res_t *res, *res1, *res2; uint64_t ul0; str_list_t *sf_class, *sf_class_e; char *sf_cdev = NULL, *sf_dev = NULL; char *sf_drv_name, *sf_drv; if(!hd_probe_feature(hd_data, pr_net)) return; hd_data->module = mod_net; /* some clean-up */ remove_hd_entries(hd_data); hd_data->net = free_str_list(hd_data->net); PROGRESS(1, 0, "get network data"); sf_class = read_dir("/sys/class/net", 'l'); if(!sf_class) sf_class = read_dir("/sys/class/net", 'd'); if(!sf_class) { ADD2LOG("sysfs: no such class: net\n"); return; } for(sf_class_e = sf_class; sf_class_e; sf_class_e = sf_class_e->next) { str_printf(&sf_cdev, 0, "/sys/class/net/%s", sf_class_e->str); hd_card = NULL; ADD2LOG( " net interface: name = %s, path = %s\n", sf_class_e->str, hd_sysfs_id(sf_cdev) ); if_type = -1; if(hd_attr_uint(get_sysfs_attr_by_path(sf_cdev, "type"), &ul0, 0)) { if_type = ul0; ADD2LOG(" type = %d\n", if_type); } if_carrier = -1; if(hd_attr_uint(get_sysfs_attr_by_path(sf_cdev, "carrier"), &ul0, 0)) { if_carrier = ul0; ADD2LOG(" carrier = %d\n", if_carrier); } hw_addr = NULL; if((s = get_sysfs_attr_by_path(sf_cdev, "address"))) { hw_addr = canon_str(s, strlen(s)); ADD2LOG(" hw_addr = %s\n", hw_addr); } sf_dev = new_str(hd_read_sysfs_link(sf_cdev, "device")); if(sf_dev) { ADD2LOG(" net device: path = %s\n", hd_sysfs_id(sf_dev)); } sf_drv_name = NULL; sf_drv = hd_read_sysfs_link(sf_dev, "driver"); if(sf_drv) { sf_drv_name = strrchr(sf_drv, '/'); if(sf_drv_name) sf_drv_name++; ADD2LOG( " net driver: name = %s, path = %s\n", sf_drv_name, hd_sysfs_id(sf_drv) ); } hd = add_hd_entry(hd_data, __LINE__, 0); hd->base_class.id = bc_network_interface; hd->sub_class.id = sc_nif_other; res1 = NULL; if(hw_addr && strspn(hw_addr, "0:") != strlen(hw_addr)) { res1 = new_mem(sizeof *res1); res1->hwaddr.type = res_hwaddr; res1->hwaddr.addr = new_str(hw_addr); add_res_entry(&hd->res, res1); } res2 = NULL; if(if_carrier >= 0) { res = new_mem(sizeof *res); res->link.type = res_link; res->link.state = if_carrier ? 1 : 0; add_res_entry(&hd->res, res); } hd->unix_dev_name = new_str(sf_class_e->str); hd->sysfs_id = new_str(hd_sysfs_id(sf_cdev)); if(sf_drv_name) { add_str_list(&hd->drivers, sf_drv_name); } else if(hd->res) { get_driverinfo(hd_data, hd); } switch(if_type) { case ARPHRD_ETHER: /* eth */ hd->sub_class.id = sc_nif_ethernet; break; case ARPHRD_LOOPBACK: /* lo */ hd->sub_class.id = sc_nif_loopback; break; case ARPHRD_SIT: /* sit */ hd->sub_class.id = sc_nif_sit; break; case ARPHRD_FDDI: /* fddi */ hd->sub_class.id = sc_nif_fddi; break; case ARPHRD_IEEE802_TR: /* tr */ hd->sub_class.id = sc_nif_tokenring; break; #if 0 case ARPHRD_IEEE802: /* fc */ hd->sub_class.id = sc_nif_fc; break; #endif default: hd->sub_class.id = sc_nif_other; } if(!strcmp(hd->unix_dev_name, "lo")) { hd->sub_class.id = sc_nif_loopback; } else if(sscanf(hd->unix_dev_name, "eth%u", &u) == 1) { hd->sub_class.id = sc_nif_ethernet; hd->slot = u; } else if(sscanf(hd->unix_dev_name, "tr%u", &u) == 1) { hd->sub_class.id = sc_nif_tokenring; hd->slot = u; } else if(sscanf(hd->unix_dev_name, "fddi%u", &u) == 1) { hd->sub_class.id = sc_nif_fddi; hd->slot = u; } else if(sscanf(hd->unix_dev_name, "ctc%u", &u) == 1) { hd->sub_class.id = sc_nif_ctc; hd->slot = u; } else if(sscanf(hd->unix_dev_name, "iucv%u", &u) == 1) { hd->sub_class.id = sc_nif_iucv; hd->slot = u; } else if(sscanf(hd->unix_dev_name, "hsi%u", &u) == 1) { hd->sub_class.id = sc_nif_hsi; hd->slot = u; } else if(sscanf(hd->unix_dev_name, "qeth%u", &u) == 1) { hd->sub_class.id = sc_nif_qeth; hd->slot = u; } else if(sscanf(hd->unix_dev_name, "escon%u", &u) == 1) { hd->sub_class.id = sc_nif_escon; hd->slot = u; } else if(sscanf(hd->unix_dev_name, "myri%u", &u) == 1) { hd->sub_class.id = sc_nif_myrinet; hd->slot = u; } else if(sscanf(hd->unix_dev_name, "sit%u", &u) == 1) { hd->sub_class.id = sc_nif_sit; /* ipv6 over ipv4 tunnel */ hd->slot = u; } else if(sscanf(hd->unix_dev_name, "wlan%u", &u) == 1) { hd->sub_class.id = sc_nif_wlan; hd->slot = u; } else if(sscanf(hd->unix_dev_name, "xp%u", &u) == 1) { hd->sub_class.id = sc_nif_xp; hd->slot = u; } else if(sscanf(hd->unix_dev_name, "usb%u", &u) == 1) { hd->sub_class.id = sc_nif_usb; hd->slot = u; } /* ##### add more interface names here */ else { for(s = hd->unix_dev_name; *s; s++) if(isdigit(*s)) break; if(*s && (u = strtoul(s, &s, 10), !*s)) { hd->slot = u; } } hd->bus.id = bus_none; hd_card = NULL; if(sf_dev) { s = new_str(hd_sysfs_id(sf_dev)); hd->sysfs_device_link = new_str(s); hd_card = hd_find_sysfs_id(hd_data, s); // try one above, if not found if(!hd_card) { t = strrchr(s, '/'); if(t) { *t = 0; hd_card = hd_find_sysfs_id(hd_data, s); } } /* if one card has several interfaces (as with PS3), check interface names, too */ if( hd_card && hd_card->unix_dev_name && hd->unix_dev_name && strcmp(hd->unix_dev_name, hd_card->unix_dev_name) ) { hd_card = hd_find_sysfs_id_devname(hd_data, s, hd->unix_dev_name); } s = free_mem(s); if(hd_card) { hd->attached_to = hd_card->idx; /* for cards with strange pci classes */ hd_set_hw_class(hd_card, hw_network_ctrl); /* add hw addr to network card */ if(res1) { u = 0; for(res = hd_card->res; res; res = res->next) { if( res->any.type == res_hwaddr && !strcmp(res->hwaddr.addr, res1->hwaddr.addr) ) { u = 1; break; } } if(!u) { res = new_mem(sizeof *res); res->hwaddr.type = res_hwaddr; res->hwaddr.addr = new_str(res1->hwaddr.addr); add_res_entry(&hd_card->res, res); } } /* * add interface names... * but not wmasterX (bnc #441778) */ if(if_type != 801) add_if_name(hd_card, hd); } } if(!hd_card && hw_addr) { /* try to find card based on hwaddr (for prom-based cards) */ for(hd_card = hd_data->hd; hd_card; hd_card = hd_card->next) { if( hd_card->base_class.id != bc_network || hd_card->sub_class.id != 0 ) continue; for(res = hd_card->res; res; res = res->next) { if( res->any.type == res_hwaddr && !strcmp(hw_addr, res->hwaddr.addr) ) break; } if(res) { hd->attached_to = hd_card->idx; break; } } } hw_addr = free_mem(hw_addr); /* fix card type */ if(hd_card) { if( (hd_card->base_class.id == 0 && hd_card->sub_class.id == 0) || (hd_card->base_class.id == bc_network && hd_card->sub_class.id == 0x80) ) { switch(hd->sub_class.id) { case sc_nif_ethernet: hd_card->base_class.id = bc_network; hd_card->sub_class.id = 0; break; case sc_nif_usb: hd_card->base_class.id = bc_network; hd_card->sub_class.id = 0x91; break; } } } sf_dev = free_mem(sf_dev); } sf_cdev = free_mem(sf_cdev); sf_class = free_str_list(sf_class); if(hd_is_sgi_altix(hd_data)) add_xpnet(hd_data); add_uml(hd_data); add_kma(hd_data); /* add link status info & dump eeprom */ for(hd = hd_data->hd ; hd; hd = hd->next) { if( hd->module == hd_data->module && hd->base_class.id == bc_network_interface ) { char *buf = NULL; str_list_t *sl0, *sl; if(hd_probe_feature(hd_data, pr_net_eeprom) && hd->unix_dev_name) { PROGRESS(2, 0, "eeprom dump"); str_printf(&buf, 0, "|/usr/sbin/ethtool -e %s 2>/dev/null", hd->unix_dev_name); if((sl0 = read_file(buf, 0, 0))) { ADD2LOG("----- %s %s -----\n", hd->unix_dev_name, "EEPROM dump"); for(sl = sl0; sl; sl = sl->next) { ADD2LOG("%s", sl->str); } ADD2LOG("----- %s end -----\n", "EEPROM dump"); free_str_list(sl0); } free(buf); } for(res = hd->res; res; res = res->next) { if(res->any.type == res_link) break; } if(!res) get_linkstate(hd_data, hd); if(!(hd_card = hd_get_device_by_idx(hd_data, hd->attached_to))) continue; for(res = hd->res; res; res = res->next) { if(res->any.type == res_link) break; } if(res) { for(res1 = hd_card->res; res1; res1 = res1->next) { if(res1->any.type == res_link) break; } if(res && !res1) { res1 = new_mem(sizeof *res1); res1->link.type = res_link; res1->link.state = res->link.state; add_res_entry(&hd_card->res, res1); } } } } }
/* * Read kernel log info. Combine with /var/log/boot.msg. */ void _read_klog(hd_data_t *hd_data) { char buf[0x2000 + 1], *s; int i, j, len, n; str_list_t *sl, *sl1, *sl2, *sl_last, **ssl, *sl_next; /* some clean-up */ hd_data->klog = free_str_list(hd_data->klog); sl1 = read_file(KLOG_BOOT, 0, 0); sl2 = NULL; /* * remove non-canonical lines (not starting with <[0-9]>) at the start and * at the end */ /* note: the implementations assumes that at least *one* line is ok */ for(sl_last = NULL, sl = sl1; sl; sl = (sl_last = sl)->next) { if(str_ok(sl)) { if(sl_last) { sl_last->next = NULL; free_str_list(sl1); sl1 = sl; } break; } } for(sl_last = NULL, sl = sl1; sl; sl = (sl_last = sl)->next) { if(!str_ok(sl)) { if(sl_last) { sl_last->next = NULL; free_str_list(sl); } break; } } n = klogctl(3, buf, sizeof buf - 1); if(n <= 0) { hd_data->klog = sl1; return; } if(n > (int) sizeof buf - 1) n = sizeof buf - 1; buf[n] = 0; for(i = j = 0; i < n; i++) { if(buf[i] == '\n') { len = i - j + 1; s = new_mem(len + 1); memcpy(s, buf + j, len); add_str_list(&sl2, s); s = free_mem(s); j = i + 1; } } /* the 1st line may be incomplete */ if(sl2 && !str_ok(sl2)) { sl_next = sl2->next; sl2->next = NULL; free_str_list(sl2); sl2 = sl_next; } if(!sl1) { hd_data->klog = sl2; return; } if(sl1 && !sl2) { hd_data->klog = sl1; return; } /* now, try to join sl1 & sl2 */ for(sl_last = NULL, sl = sl1; sl; sl = (sl_last = sl)->next) { if(!str_list_cmp(sl, sl2)) { free_str_list(sl); if(sl_last) sl_last->next = NULL; else sl1 = NULL; break; } } /* append sl2 to sl1 */ for(ssl = &sl1; *ssl; ssl = &(*ssl)->next); *ssl = sl2; hd_data->klog = sl1; }
void get_input_devices(hd_data_t *hd_data) { hd_t *hd; str_list_t *input, *sl, *sl1; char *s; unsigned ok, u, is_mouse, is_joystick; unsigned bus, vendor, product, version; unsigned mouse_buttons, mouse_wheels; char *name = NULL, *handlers = NULL, *key = NULL, *rel = NULL, *abso = NULL; size_t len; str_list_t *handler_list; hd_dev_num_t dev_num = { type: 'c', range: 1 }; input = read_file("/proc/bus/input/devices", 0, 0); ADD2LOG("----- /proc/bus/input/devices -----\n"); for(sl = input; sl; sl = sl->next) { ADD2LOG(" %s", sl->str); } ADD2LOG("----- /proc/bus/input/devices end -----\n"); for(ok = 0, sl = input; sl; sl = sl->next) { if(*sl->str == '\n') { ADD2LOG("bus = %u, name = %s\n", bus, name); if(handlers) ADD2LOG(" handlers = %s\n", handlers); if(key) ADD2LOG(" key = %s\n", key); if(rel) ADD2LOG(" rel = %s\n", rel); if(abso) ADD2LOG(" abs = %s\n", abso); mouse_buttons = 0; if(key) { for(u = BTN_MOUSE; u < BTN_MOUSE + 8; u++) { if(test_bit(key, u)) mouse_buttons++; } } ADD2LOG(" mouse buttons = %u\n", mouse_buttons); mouse_wheels = 0; if(rel) { for(u = REL_HWHEEL; u <= REL_MAX; u++) { if(test_bit(rel, u)) mouse_wheels++; } } ADD2LOG(" mouse wheels = %u\n", mouse_wheels); if(ok && handlers) { handler_list = hd_split(' ', handlers); is_mouse = strstr(handlers, "mouse") ? 1 : 0; is_joystick = strstr(handlers, "js") ? 1 : 0; if( // HP Virtual Management Device vendor == 0x03f0 && product == 0x1126 && mouse_buttons >= 3 ) is_mouse = 1; ADD2LOG(" is_mouse = %u\n", is_mouse); ADD2LOG(" is_joystick = %u\n", is_joystick); if(bus == BUS_USB) { s = NULL; for(sl1 = handler_list; sl1; sl1 = sl1->next) { if(sscanf(sl1->str, "mouse%u", &u) == 1) { str_printf(&s, 0, "/dev/input/mouse%u", u); break; } } if(!s && (is_mouse || is_joystick)) for(sl1 = handler_list; sl1; sl1 = sl1->next) { if(sscanf(sl1->str, "event%u", &u) == 1) { str_printf(&s, 0, "/dev/input/event%u", u); break; } } if(s) { for(hd = hd_data->hd; hd; hd = hd->next) { if( (hd->unix_dev_name2 && !strcmp(hd->unix_dev_name2, s)) || (hd->unix_dev_name && !strcmp(hd->unix_dev_name, s)) ) { if(!hd->base_class.id) { if (is_mouse) { hd->base_class.id = bc_mouse; hd->sub_class.id = sc_mou_usb; } else if (is_joystick) { hd->base_class.id = bc_joystick; } } if (is_mouse) { hd_set_hw_class(hd, hw_mouse); hd->compat_vendor.id = MAKE_ID(TAG_SPECIAL, 0x0210); hd->compat_device.id = MAKE_ID(TAG_SPECIAL, (mouse_wheels << 4) + mouse_buttons); } else if (is_joystick) { hd_set_hw_class(hd, hw_joystick); /* add buttons and axis details */ add_joystick_details(hd_data, hd, key, abso); } if(hd->unix_dev_name) add_str_list(&hd->unix_dev_names, hd->unix_dev_name); if(hd->unix_dev_name2) add_str_list(&hd->unix_dev_names, hd->unix_dev_name2); for(sl1 = handler_list; sl1; sl1 = sl1->next) { if(sscanf(sl1->str, "event%u", &u) == 1) { str_printf(&s, 0, "/dev/input/event%u", u); if(!search_str_list(hd->unix_dev_names, s)) add_str_list(&hd->unix_dev_names, s); s = free_mem(s); } /* add /dev/input/jsN joystick device name */ else if (is_joystick) { if(sscanf(sl1->str, "js%u", &u) == 1) { str_printf(&s, 0, "/dev/input/js%u", u); if(!search_str_list(hd->unix_dev_names, s)) add_str_list(&hd->unix_dev_names, s); if(!hd->unix_dev_name2) hd->unix_dev_name2 = new_str(s); s = free_mem(s); } } } break; } } } s = free_mem(s); } else { // keyboard if(search_str_list(handler_list, "kbd") && test_bit(key, KEY_1)) { hd = add_hd_entry(hd_data, __LINE__, 0); hd->base_class.id = bc_keyboard; hd->sub_class.id = sc_keyboard_kbd; hd->bus.id = bus_ps2; hd->vendor.id = MAKE_ID(0, vendor); hd->device.id = MAKE_ID(0, product); hd->compat_vendor.id = MAKE_ID(TAG_SPECIAL, 0x0211); hd->compat_device.id = MAKE_ID(TAG_SPECIAL, 0x0001); hd->device.name = new_str(name); for(sl1 = handler_list; sl1; sl1 = sl1->next) { if(sscanf(sl1->str, "event%u", &u) == 1) { str_printf(&hd->unix_dev_name, 0, "/dev/input/event%u", u); dev_num.major = 13; dev_num.minor = 64 + u; hd->unix_dev_num = dev_num; break; } } } // mouse else if(is_mouse) { hd = add_hd_entry(hd_data, __LINE__, 0); hd->vendor.id = MAKE_ID(0, vendor); hd->device.id = MAKE_ID(0, product); hd->compat_vendor.id = MAKE_ID(TAG_SPECIAL, 0x0210); hd->compat_device.id = MAKE_ID(TAG_SPECIAL, (mouse_wheels << 4) + mouse_buttons); hd->base_class.id = bc_mouse; if(bus == BUS_ADB) { hd->sub_class.id = sc_mou_bus; hd->bus.id = bus_adb; } else { hd->sub_class.id = sc_mou_ps2; hd->bus.id = bus_ps2; } hd->device.name = new_str(name); #if 0 /* Synaptics/Alps TouchPad */ if( vendor == 2 && (product == 7 || product == 8) && test_bit(abso, ABS_X) && test_bit(abso, ABS_Y) && test_bit(abso, ABS_PRESSURE) && test_bit(key, BTN_TOOL_FINGER) ) { } #endif hd->unix_dev_name = new_str(DEV_MICE); dev_num.major = 13; dev_num.minor = 63; hd->unix_dev_num = dev_num; for(sl1 = handler_list; sl1; sl1 = sl1->next) { if(sscanf(sl1->str, "mouse%u", &u) == 1) { str_printf(&hd->unix_dev_name2, 0, "/dev/input/mouse%u", u); dev_num.major = 13; dev_num.minor = 32 + u; hd->unix_dev_num2 = dev_num; break; } } add_str_list(&hd->unix_dev_names, hd->unix_dev_name); add_str_list(&hd->unix_dev_names, hd->unix_dev_name2); for(sl1 = handler_list; sl1; sl1 = sl1->next) { if(sscanf(sl1->str, "event%u", &u) == 1) { s = NULL; str_printf(&s, 0, "/dev/input/event%u", u); add_str_list(&hd->unix_dev_names, s); s = free_mem(s); break; } } } // joystick else if(is_joystick) { hd = add_hd_entry(hd_data, __LINE__, 0); hd->vendor.id = MAKE_ID(0, vendor); hd->device.id = MAKE_ID(0, product); hd_set_hw_class(hd, hw_joystick); hd->base_class.id = bc_joystick; hd->device.name = new_str(name); // gameport? (see <linux/input.h>) if (bus == BUS_GAMEPORT) hd->bus.id = bus_gameport; /* add buttons and axis details */ add_joystick_details(hd_data, hd, key, abso); // add eventX device for(sl1 = handler_list; sl1; sl1 = sl1->next) { if(sscanf(sl1->str, "event%u", &u) == 1) { str_printf(&hd->unix_dev_name, 0, "/dev/input/event%u", u); dev_num.major = 13; dev_num.minor = 64 + u; hd->unix_dev_num = dev_num; break; } } // add jsX device for(sl1 = handler_list; sl1; sl1 = sl1->next) { if(sscanf(sl1->str, "js%u", &u) == 1) { str_printf(&hd->unix_dev_name2, 0, "/dev/input/js%u", u); break; } } add_str_list(&hd->unix_dev_names, hd->unix_dev_name); add_str_list(&hd->unix_dev_names, hd->unix_dev_name2); } else { ADD2LOG("unknown non-USB input device\n"); } } handler_list = free_str_list(handler_list); } ok = 0; name = free_mem(name); handlers = free_mem(handlers); key = free_mem(key); rel = free_mem(rel); abso = free_mem(abso); } if(sscanf(sl->str, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x", &bus, &vendor, &product, &version) == 4) { ok = 1; continue; } if(!strncmp(sl->str, INP_NAME, sizeof INP_NAME - 1)) { s = sl->str + sizeof INP_NAME; len = strlen(s); if(len > 2) { name = canon_str(s, len - 2); } continue; } if(!strncmp(sl->str, INP_HANDLERS, sizeof INP_HANDLERS - 1)) { s = sl->str + sizeof INP_HANDLERS - 1; handlers = canon_str(s, strlen(s)); continue; } if(!strncmp(sl->str, INP_KEY, sizeof INP_KEY - 1)) { s = sl->str + sizeof INP_KEY - 1; key = canon_str(s, strlen(s)); key = all_bits(key); continue; } if(!strncmp(sl->str, INP_REL, sizeof INP_REL - 1)) { s = sl->str + sizeof INP_REL - 1; rel = canon_str(s, strlen(s)); rel = all_bits(rel); continue; } if(!strncmp(sl->str, INP_ABS, sizeof INP_ABS - 1)) { s = sl->str + sizeof INP_ABS - 1; abso = canon_str(s, strlen(s)); abso = all_bits(abso); continue; } } free_str_list(input); } char *all_bits(char *str) { str_list_t *sl, *sl0; char *s = NULL; unsigned long u; if(!str) return NULL; sl = sl0 = hd_split(' ', str); for(; sl; sl = sl->next) { u = strtoul(sl->str, NULL, 16); str_printf(&s, -1, "%0*lx", (int) sizeof (unsigned long) * 2, u); } free_str_list(sl0); free_mem(str); return s; }
void get_usb_devs(hd_data_t *hd_data) { uint64_t ul0; unsigned u1, u2, u3; hd_t *hd, *hd1; usb_t *usb; str_list_t *sl, *usb_devs = NULL; char *s, *s1, *t; hd_res_t *res; size_t l; str_list_t *sf_bus, *sf_bus_e; char *sf_dev, *sf_dev_2; sf_bus = read_dir("/sys/bus/usb/devices", 'l'); if(!sf_bus) { ADD2LOG("sysfs: no such bus: usb\n"); return; } for(sf_bus_e = sf_bus; sf_bus_e; sf_bus_e = sf_bus_e->next) { sf_dev = hd_read_sysfs_link("/sys/bus/usb/devices", sf_bus_e->str); if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev, "bNumInterfaces"), &ul0, 0)) { add_str_list(&usb_devs, sf_dev); ADD2LOG(" usb dev: %s\n", hd_sysfs_id(sf_dev)); } } for(sf_bus_e = sf_bus; sf_bus_e; sf_bus_e = sf_bus_e->next) { sf_dev = new_str(hd_read_sysfs_link("/sys/bus/usb/devices", sf_bus_e->str)); ADD2LOG( " usb device: name = %s\n path = %s\n", sf_bus_e->str, hd_sysfs_id(sf_dev) ); if( hd_attr_uint(get_sysfs_attr_by_path(sf_dev, "bInterfaceNumber"), &ul0, 16) ) { hd = add_hd_entry(hd_data, __LINE__, 0); hd->detail = new_mem(sizeof *hd->detail); hd->detail->type = hd_detail_usb; hd->detail->usb.data = usb = new_mem(sizeof *usb); hd->sysfs_id = new_str(hd_sysfs_id(sf_dev)); hd->sysfs_bus_id = new_str(sf_bus_e->str); hd->bus.id = bus_usb; hd->func = ul0; usb->ifdescr = ul0; if((s = get_sysfs_attr_by_path(sf_dev, "modalias"))) { s = canon_str(s, strlen(s)); ADD2LOG(" modalias = \"%s\"\n", s); if(s && *s) { hd->modalias = s; s = NULL; } s = free_mem(s); } ADD2LOG(" bInterfaceNumber = %u\n", hd->func); if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev, "bInterfaceClass"), &ul0, 16)) { usb->i_cls = ul0; ADD2LOG(" bInterfaceClass = %u\n", usb->i_cls); } if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev, "bInterfaceSubClass"), &ul0, 16)) { usb->i_sub = ul0; ADD2LOG(" bInterfaceSubClass = %u\n", usb->i_sub); } if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev, "bInterfaceProtocol"), &ul0, 16)) { usb->i_prot = ul0; ADD2LOG(" bInterfaceProtocol = %u\n", usb->i_prot); } /* device has longest matching sysfs id */ u2 = strlen(sf_dev); s = NULL; for(u3 = 0, sl = usb_devs; sl; sl = sl->next) { u1 = strlen(sl->str); if(u1 > u3 && u1 <= u2 && !strncmp(sf_dev, sl->str, u1)) { u3 = u1; s = sl->str; } } if(s) { ADD2LOG(" if: %s @ %s\n", hd->sysfs_bus_id, hd_sysfs_id(s)); sf_dev_2 = new_str(s); if(sf_dev_2) { if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev_2, "bDeviceClass"), &ul0, 16)) { usb->d_cls = ul0; ADD2LOG(" bDeviceClass = %u\n", usb->d_cls); } if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev_2, "bDeviceSubClass"), &ul0, 16)) { usb->d_sub = ul0; ADD2LOG(" bDeviceSubClass = %u\n", usb->d_sub); } if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev_2, "bDeviceProtocol"), &ul0, 16)) { usb->d_prot = ul0; ADD2LOG(" bDeviceProtocol = %u\n", usb->d_prot); } if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev_2, "idVendor"), &ul0, 16)) { usb->vendor = ul0; ADD2LOG(" idVendor = 0x%04x\n", usb->vendor); } if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev_2, "idProduct"), &ul0, 16)) { usb->device = ul0; ADD2LOG(" idProduct = 0x%04x\n", usb->device); } if((s = get_sysfs_attr_by_path(sf_dev_2, "manufacturer"))) { usb->manufact = canon_str(s, strlen(s)); ADD2LOG(" manufacturer = \"%s\"\n", usb->manufact); } if((s = get_sysfs_attr_by_path(sf_dev_2, "product"))) { usb->product = canon_str(s, strlen(s)); ADD2LOG(" product = \"%s\"\n", usb->product); } if((s = get_sysfs_attr_by_path(sf_dev_2, "serial"))) { usb->serial = canon_str(s, strlen(s)); ADD2LOG(" serial = \"%s\"\n", usb->serial); } if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev_2, "bcdDevice"), &ul0, 16)) { usb->rev = ul0; ADD2LOG(" bcdDevice = %04x\n", usb->rev); } if((s = get_sysfs_attr_by_path(sf_dev_2, "speed"))) { s = canon_str(s, strlen(s)); if(!strcmp(s, "1.5")) usb->speed = 15*100000; else if(!strcmp(s, "12")) usb->speed = 12*1000000; else if(!strcmp(s, "480")) usb->speed = 480*1000000; ADD2LOG(" speed = \"%s\"\n", s); s = free_mem(s); } sf_dev_2 = free_mem(sf_dev_2); } } if(usb->vendor || usb->device) { hd->vendor.id = MAKE_ID(TAG_USB, usb->vendor); hd->device.id = MAKE_ID(TAG_USB, usb->device); } if(usb->manufact) hd->vendor.name = new_str(usb->manufact); if(usb->product) hd->device.name = new_str(usb->product); if(usb->serial) hd->serial = new_str(usb->serial); if(usb->rev) str_printf(&hd->revision.name, 0, "%x.%02x", usb->rev >> 8, usb->rev & 0xff); if(usb->speed) { res = add_res_entry(&hd->res, new_mem(sizeof *res)); res->baud.type = res_baud; res->baud.speed = usb->speed; } s = hd_sysfs_find_driver(hd_data, hd->sysfs_id, 1); if(s) add_str_list(&hd->drivers, s); set_class_entries(hd_data, hd, usb); if(!hd_data->scanner_db) { hd_data->scanner_db = hd_module_list(hd_data, 1); } if( hd->drivers && search_str_list(hd_data->scanner_db, hd->drivers->str) ) { hd->base_class.id = bc_scanner; } // ###### FIXME if(hd->base_class.id == bc_modem) { hd->unix_dev_name = new_str("/dev/ttyACM0"); } } sf_dev = free_mem(sf_dev); }
void pcmcia_read_data(hd_data_t *hd_data) { hd_t *hd, *hd2; unsigned u0, u1, func_id; uint64_t ul0; char *s, *t; char *prod1, *prod2, *prod3, *prod4; str_list_t *sl; str_list_t *sf_bus, *sf_bus_e; char *sf_dev; sf_bus = reverse_str_list(read_dir("/sys/bus/pcmcia/devices", 'l')); if(!sf_bus) { ADD2LOG("sysfs: no such bus: pcmcia\n"); return; } for(sf_bus_e = sf_bus; sf_bus_e; sf_bus_e = sf_bus_e->next) { sf_dev = new_str(hd_read_sysfs_link("/sys/bus/pcmcia/devices", sf_bus_e->str)); ADD2LOG( " pcmcia device: name = %s\n path = %s\n", sf_bus_e->str, hd_sysfs_id(sf_dev) ); if(sscanf(sf_bus_e->str, "%x.%x", &u0, &u1) != 2) continue; hd = add_hd_entry(hd_data, __LINE__, 0); hd->sysfs_id = new_str(hd_sysfs_id(sf_dev)); hd->sysfs_bus_id = new_str(sf_bus_e->str); hd->bus.id = bus_pcmcia; hd->slot = u0; hd->func = u1; hd->hotplug_slot = u0 + 1; hd->hotplug = hp_pcmcia; s = hd_sysfs_find_driver(hd_data, hd->sysfs_id, 1); if(s) add_str_list(&hd->drivers, s); if((s = get_sysfs_attr_by_path(sf_dev, "modalias"))) { hd->modalias = canon_str(s, strlen(s)); ADD2LOG(" modalias = \"%s\"\n", s); } if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev, "manf_id"), &ul0, 0)) { ADD2LOG(" manf_id = 0x%04x\n", (unsigned) ul0); hd->vendor.id = MAKE_ID(TAG_PCMCIA, ul0); } if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev, "card_id"), &ul0, 0)) { ADD2LOG(" card_id = 0x%04x\n", (unsigned) ul0); hd->device.id = MAKE_ID(TAG_PCMCIA, ul0); } /* * "multifunction", "memory", "serial", "parallel", * "fixed disk", "video", "network", "AIMS", * "SCSI" */ func_id = 0; if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev, "func_id"), &ul0, 0)) { func_id = ul0; ADD2LOG(" func_id = 0x%04x\n", func_id); } prod1 = NULL; if((s = get_sysfs_attr_by_path(sf_dev, "prod_id1"))) { prod1 = canon_str(s, strlen(s)); ADD2LOG(" prod_id1 = \"%s\"\n", prod1); } prod2 = NULL; if((s = get_sysfs_attr_by_path(sf_dev, "prod_id2"))) { prod2 = canon_str(s, strlen(s)); ADD2LOG(" prod_id2 = \"%s\"\n", prod2); } prod3 = NULL; if((s = get_sysfs_attr_by_path(sf_dev, "prod_id3"))) { prod3 = canon_str(s, strlen(s)); ADD2LOG(" prod_id3 = \"%s\"\n", prod3); } prod4 = NULL; if((s = get_sysfs_attr_by_path(sf_dev, "prod_id4"))) { prod4 = canon_str(s, strlen(s)); ADD2LOG(" prod_id4 = \"%s\"\n", prod4); } if(func_id == 6) { hd->base_class.id = bc_network; hd->sub_class.id = 0x80; /* other */ } if(prod1 && *prod1) { add_str_list(&hd->extra_info, prod1); hd->vendor.name = prod1; prod1 = NULL; } if(prod2 && *prod2) { add_str_list(&hd->extra_info, prod2); hd->device.name = prod2; prod2 = NULL; } if(prod3 && *prod3) add_str_list(&hd->extra_info, prod3); if(prod4 && *prod4) add_str_list(&hd->extra_info, prod4); for(sl = hd->extra_info; sl ; sl = sl->next) { if(strstr(sl->str, "Ethernet")) hd->sub_class.id = 0; /* ethernet */ if( !hd->revision.name && !sl->next && ( !strncasecmp(sl->str, "rev.", sizeof "rev." - 1) || ( (sl->str[0] == 'V' || sl->str[0] == 'v') && (sl->str[1] >= '0' && sl->str[1] <= '9') ) ) ) { hd->revision.name = new_str(sl->str); } } prod1 = free_mem(prod1); prod2 = free_mem(prod2); prod3 = free_mem(prod3); prod4 = free_mem(prod4); s = new_str(hd->sysfs_id); if((t = strrchr(s, '/'))) { *t = 0; if((hd2 = hd_find_sysfs_id(hd_data, s))) { hd->attached_to = hd2->idx; } } free_mem(s); free_mem(sf_dev); } free_str_list(sf_bus); }