Путь: Toys/Other, команды версии: Ver.4 Ver.9 Комментарии в файле lsusb.c : Команд: 2 lspci
lsusb
Исходный текст в файле lsusb.c #define FOR_lsusb #include "toys.h" GLOBALS( char *i; long n; void *ids, *class; int count; ) struct dev_ids { struct dev_ids *next, *child; int id; char name[]; }; struct scanloop { char *pattern; void *d1, *d2; }; // Common function to read uevent file under /proc for both pci and usb // note that %s is omitted (because pointer is into toybuf, avoiding copy). static int scan_uevent(struct dirtree *new, int len, struct scanloop *sl) { int ii, count = 0; off_t flen = sizeof(toybuf); char *ss, *yy; // Read data if (*new->name == '.') return 0; sprintf(toybuf, "%s/uevent", new->name); if (!readfileat(dirtree_parentfd(new), ss = toybuf, toybuf, &flen)) return 0; // Loop over lines while ((flen = strcspn(ss, "\n"))) { if (ss[flen]) ss[flen++] = 0; yy = ss+flen; // Try each pattern for (ii = 0; ii<len; ii++) { if (strchr(sl[ii].pattern, '%')) { if (2-!sl[ii].d2==sscanf(ss, sl[ii].pattern, sl[ii].d1, sl[ii].d2)) break; } else if (strstart(&ss, sl[ii].pattern)) { *(void **)sl[ii].d1 = ss; break; } } if (ii!=len) count++; ss = yy; } return count; } static void get_names(struct dev_ids *ids, int id1, int id2, char **name1, char **name2) { // Look up matching dev_ids (if any) *name1 = *name2 = ""; for (; ids; ids = ids->next) { if (id1 != ids->id) continue; *name1 = ids->name; for (ids = ids->child; ids; ids = ids->next) { if (id2 != ids->id) continue; *name2 = ids->name; return; } return; } } // Search for pci.ids or usb.ids and return parsed structure or NULL struct dev_ids *parse_dev_ids(char *name, struct dev_ids **and) { char *path = "/etc:/vendor:/usr/share/misc"; struct string_list *sl = 0; FILE *fp; char *s, *ss, *sss; struct dev_ids *ids = 0, *new; int fd = -1; // Open compressed or uncompressed file signal(SIGCHLD, SIG_IGN); s = TT.i; if (!s) { sprintf(toybuf, "%s.gz", name); if ((sl = find_in_path(path, toybuf)) || (sl = find_in_path(path, name))) s = sl->str; } if (s && strend(s, ".gz")) xpopen((char *[]){"zcat", sl->str, 0}, &fd, 1); else if (s) fd = xopen(s, O_RDONLY); llist_traverse(sl, free); if (fd == -1) return 0; for (fp = fdopen(fd, "r"); (s = ss = xgetline(fp)); free(s)) { // TODO parse and use third level instead of skipping it here if (s[strspn(s, " \t")]=='#' || strstart(&ss, "\t\t")) continue; // Switch to device class list? if (strstart(&ss, "C ") && and) { *and = ids; and = 0; } fd = estrtol(sss = ss, &ss, 16); if (ss>sss && *ss++==' ') { while (isspace(*ss)) ss++; new = xmalloc(sizeof(*new)+strlen(ss)+1); new->child = 0; new->id = fd; strcpy(new->name, ss); if (!ids || *s!='\t') { new->next = ids; ids = new; } else { new->next = ids->child; ids->child = new; } } } fclose(fp); return ids; } static int list_usb(struct dirtree *new) { int busnum = 0, devnum = 0, pid = 0, vid = 0; char *n1, *n2; if (!new->parent) return DIRTREE_RECURSE; if (3 == scan_uevent(new, 3, (struct scanloop[]){{"BUSNUM=%u", &busnum, 0}, {"DEVNUM=%u", &devnum, 0}, {"PRODUCT=%x/%x", &pid, &vid}})) { get_names(TT.ids, pid, vid, &n1, &n2); printf("Bus %03d Device %03d: ID %04x:%04x %s %s\n", busnum, devnum, pid, vid, n1, n2); } return 0; } void lsusb_main(void) { // Parse http://www.linux-usb.org/usb.ids file (if available) TT.ids = parse_dev_ids("usb.ids", 0); dirtree_read("/sys/bus/usb/devices/", list_usb); } #define FOR_lspci #include "generated/flags.h" // TODO: -v static int list_pci(struct dirtree *new) { char *driver = 0, buf[16], *ss, *names[3]; int cvd[3] = {0}, ii, revision = 0; off_t len = sizeof(toybuf); // Output formats: -n, -nn, -m, -nm, -nnm, -k if (!new->parent) return DIRTREE_RECURSE; if (strlen(new->name)<6) return 0; TT.count = 0; // Load revision sprintf(toybuf, "%s/revision", new->name); if (readfileat(dirtree_parentfd(new), ss = toybuf, toybuf, &len)) { strstart(&ss, "0x"); sscanf(ss, "%x", &revision); } // Load uevent data, look up names in database if (3 != scan_uevent(new, 3, (struct scanloop[]){{"DRIVER=", &driver, 0}, {"PCI_CLASS=%x", cvd, 0}, {"PCI_ID=%x:%x", cvd+1, cvd+2}})) return 0; get_names(TT.class, 255&(cvd[0]>>16), 255&(cvd[0]>>8), names, names); get_names(TT.ids, cvd[1], cvd[2], names+1, names+2); if (!FLAG(e)) cvd[0] >>= 8; // Output line according to flags printf("%s", new->name+5); for (ii = 0; ii<3; ii++) { sprintf(buf, "%0*x", 6-2*(ii||!FLAG(e)), cvd[ii]); if (!TT.n) printf(FLAG(m) ? " \"%s\"" : ": %s"+(ii!=1), names[ii] ? : buf); else if (TT.n==1) printf(FLAG(m) ? " \"%s\"" : (ii==2) ? "%s " : " %s:", buf); else if (!FLAG(m)) { // This one permutes the order, so do it all first time and abort loop printf(" %s [%s]: %s %s [%04x:%04x]", names[0], buf, names[1], names[2], cvd[1], cvd[2]); break; } else printf(" \"%s [%s]\"", names[ii], buf); } printf(FLAG(m) ? " -r%02x" : " (rev %02x)", revision); if (FLAG(k)) printf(FLAG(m) ? " \"%s\"" : " %s", driver); xputc('\n'); return 0; } void lspci_main(void) { // Parse https://pci-ids.ucw.cz/v2.2/pci.ids (if available) if (TT.n != 1) TT.class = parse_dev_ids("pci.ids", (void *)&TT.ids); dirtree_read("/sys/bus/pci/devices/", list_pci); } |