#include #include #include #include #include #include #include #include /* AST_LIST_ENTRY() */ #include "mutils.h" #include "tty.h" struct dev_descr { AST_LIST_ENTRY (dev_descr) entry; int busnum; char devpath[40]; int configuration; int interfaceno; char port[80]; }; typedef AST_LIST_HEAD_NOLOCK(, dev_descr) dev_list_t; static const char sys_driver[] = "/sys/bus/usb/drivers"; static const char port_number[] = "port_number"; #/* */ char * read_result(int fd) { unsigned total = 0; char buf[4096]; char * found; int read_bytes; while(1) { read_bytes = read(fd, buf + total, sizeof(buf) - total); if(read_bytes <= 0) return NULL; total += read_bytes; // fprintf(stdout, "%*s", read_bytes, buf); if((found = memmem(buf, total, "\r\nOK\r\n", 6)) != NULL) { found[0] = 0; return strdup(buf); } else if((found = memmem(buf, total, "\r\nERROR\r\n", 9)) != NULL) { return NULL; } } return NULL; } #/* */ unsigned count_lines(const char * lines) { unsigned lno = 1; const char * str = lines; while(1) { const char * x = strstr(str, "\r\n"); if(x == NULL) break; str = x + 2; lno++; } return lno; } #/* */ char ** read_results(int fd, int * argc) { int arg; char * str; char * x; char ** argv; int lno; char * lines = read_result(fd); if(!lines) { argc = 0; return NULL; } lno = count_lines(lines); argv = malloc((lno + 1) * sizeof(lines)); for(arg = 0, str = lines; arg < lno; ) { x = strstr(str, "\r\n"); if(x == NULL) break; x[0] = 0; if(str[0] != 0) argv[arg++] = strdup(str); str = x + 2; } free(lines); argv[arg] = NULL; *argc = arg; return argv; } #/* */ void free_results(char ** argv) { if(argv) { unsigned idx; for(idx = 0; argv[idx]; idx++) { free(argv[idx]); } free(argv); } } #/* */ int discovery_port(struct dev_descr * descr, const char * name) { char pname[PATH_MAX]; struct dirent * entry; struct stat statb; DIR * dir = opendir(name); if(dir) { while((entry = readdir(dir)) != NULL) { snprintf(pname, sizeof(pname), "%s/%s/%s", name, entry->d_name, port_number); if(stat(pname, &statb) == 0) { snprintf(descr->port, sizeof(descr->port), "/dev/%s", entry->d_name); return 1; } } closedir(dir); } return 0; } #/* */ char * get_info_item(char ** argv, const char * name, unsigned len) { for(; argv[0]; argv++) { if(strncmp(argv[0], name, len) == 0) { char * found = argv[0] + len; while(found[0] == ' ') found++; return strdup(found); } } return NULL; } #/* */ int get_info(const char * port, char ** manu, char ** model, char ** imei, char ** imsi) { int fd = opentty(port); *manu = *model = *imei = *imsi = 0; if(fd >= 0) { static const char ati[] = "ATI\r"; static const char cimi[] = "AT+CIMI\r"; char **argv; int argc; write_all(fd, ati, STRLEN(ati)); argv = read_results(fd, &argc); if(argv) { static const char s_manufactorer[] = "Manufacturer:"; static const char s_model[] = "Model:"; static const char s_imei[] = "IMEI:"; *manu = get_info_item(argv, s_manufactorer, STRLEN(s_manufactorer)); *model = get_info_item(argv, s_model, STRLEN(s_model)); *imei = get_info_item(argv, s_imei, STRLEN(s_imei)); free_results(argv); } write_all(fd, cimi, STRLEN(cimi)); argv = read_results(fd, &argc); if(argv) { int x = 0; if(strncmp(argv[x], cimi, STRLEN(cimi)) == 0) x++; *imsi = strdup(argv[x]); free_results(argv); } closetty(port, fd); } return *manu || *model || *imei || *imsi; } #/* */ int discovery_all(dev_list_t * devs) { struct dev_descr * dev; AST_LIST_TRAVERSE(devs, dev, entry) { if(dev->interfaceno == 0) { char * manu, * model, * imei, * imsi; fprintf(stdout, "Bus: %d Dev: %s Conf: %d\n", dev->busnum, dev->devpath, dev->configuration); if(get_info(dev->port, &manu, &model, &imei, &imsi)) { fprintf(stdout, "Manufacturer: %s Model: %s IMEI: %s IMSI: %s\n", manu, model, imei, imsi); free(manu); free(model); free(imei); free(imsi); } } fprintf(stdout, "\tInterface: %d Port: %s\n", dev->interfaceno, dev->port); } return 0; } /* * /sys/bus/usb/drivers/option * 1-1:1.0 * 1-1:1.1 * 1-1:1.2 * */ #/* */ void discovery_driver(const char * driver) { char realname[PATH_MAX]; char name[PATH_MAX]; char * name2; DIR * dir; struct dirent * entry; int len; dev_list_t devs; len = snprintf(name, sizeof(name), "%s/%s", sys_driver, driver); dir = opendir(name); if(dir) { while((entry = readdir(dir)) != NULL) { struct dev_descr * descr = malloc(sizeof(*descr)); /* check numbers */ // if(entry->d_type == && sscanf(entry->d_name, "%u:%u-%u:%u", &id1, &id2, &id3, &id4) == 4) if(sscanf(entry->d_name, "%d-%39[^:]:%d.%d", &descr->busnum, descr->devpath, &descr->configuration, &descr->interfaceno) == 4) { // fprintf(stdout, "device %s\n", entry->d_name); snprintf(name + len, sizeof(name) - len, "/%s", entry->d_name); if(realpath(name, realname) != NULL) name2 = realname; else { name2 = name; } if(discovery_port(descr, name2)) { AST_LIST_INSERT_TAIL(&devs, descr, entry); continue; } } free(descr); } closedir(dir); } discovery_all(&devs); } #/* */ int main(int argc, char * argv[]) { int arg; discovery_driver("option"); for(arg = 1; arg < argc; ++arg) discovery_driver(argv[arg]); return 0; }