# HG changeset patch # User Isaac Dunham # Date 1375894286 18000 # Node ID 8caeba551a28d864bc93f46b969cb6c5e3fb7561 # Parent 8ff8b1befcdf88e912a441c4efab4072d3479558 This is the preliminary version of lspci text output support (the location of pci.ids is hard-coded to /usr/share/misc/pci.ids, as found on Debian/Ubuntu). +88 lines in two files, including reformatting, comments, whitespace, and build configuration as well as new code. The changes: -Add library code to look up descriptions. -Add a counter for -n (for the sake of -nn) -Add the file stream "db" to GLOBALS and open it conditionally -Add name fields to bufs -Look up text if enabled and -n is passed never or twice -Print text if lookup succeeded diff -r 8ff8b1befcdf -r 8caeba551a28 toys/pending/lspci.c --- a/toys/pending/lspci.c Mon Aug 05 13:16:03 2013 -0500 +++ b/toys/pending/lspci.c Wed Aug 07 11:51:26 2013 -0500 @@ -1,29 +1,87 @@ /* * lspci - written by Isaac Dunham -USE_LSPCI(NEWTOY(lspci, "emkns:", TOYFLAG_USR|TOYFLAG_BIN)) +USE_LSPCI(NEWTOY(lspci, "emkn@", TOYFLAG_USR|TOYFLAG_BIN)) config LSPCI bool "lspci" default n help - usage: lspci [-ekmn] + usage: lspci [-ekmn@] List PCI devices. -e Print all 6 digits in class (like elspci) -k Print kernel driver -m Machine parseable format - -n Numeric output (default) + -n Numeric output + +config LSPCI_TEXT + bool "lspci readable output" + depends on LSPCI + default n + help + lspci without -n prints readable descriptions; + lspci -nn prints both readable and numeric description */ #define FOR_lspci #include "toys.h" +extern int find_in_db(char * , char * , FILE * , char * , char * ); + +GLOBALS( +long numeric; + +FILE * db; +) + +char * id_check_match(char * id, char * buf) +{ + int i = 0; + while (id[i]) { + if (id[i] == buf[i]) { + i++; + } else { + return (char *)0L; + } + } + return (buf + i + 2); +} + +/* + * In: vendid, devid, fil + * Out: vname, devname + * Out must be zeroed before use. + * vmame and devname must be char[256], zeroed out + * Returns (2 - number of IDs matched): vendor must be matched for + * dev to be matched + */ +int find_in_db(char * vendid, char * devid, FILE * fil, + char * vname, char * devname) +{ + fseek(fil, 0, SEEK_SET); + char buf[256], *vtext = 0L, *dtext = 0L; + while (!(vname[0])) { + //loop through + if (fgets(buf, 255, fil)==NULL) return 2; + if ((vtext = id_check_match(vendid, buf))) + strncpy(vname, vtext, strlen(vtext) - 1); + } + while (!(devname[0])) { + if ((fgets(buf, 255, fil)==NULL) || (buf[0] != '\t' )) + return 1; + if ((dtext = id_check_match(devid, buf + 1))) + strncpy(devname, dtext, strlen(dtext) - 1); + } + return 0; /* Succeeded in matching both */ +} int do_lspci(struct dirtree *new) { - int alen = 8, dirfd; + int alen = 8, dirfd, res = 2; //no textual descriptions read char *dname = dirtree_path(new, &alen); + memset(toybuf, 0, 4096); struct { - char class[16], vendor[16], device[16], module[256]; + char class[16], vendor[16], device[16], module[256], + vname[256], devname[256]; } *bufs = (void*)(toybuf + 2); if (!strcmp("/sys/bus/pci/devices", dname)) return DIRTREE_RECURSE; @@ -52,8 +110,22 @@ if (readlink(dname, bufs->module, sizeof(bufs->module)) != -1) driver = basename(bufs->module); } - printf(fmt, new->name + 5, bufs->class, bufs->vendor, bufs->device, - driver); + if (CFG_LSPCI_TEXT && (TT.numeric != 1)) { + res = find_in_db(bufs->vendor, bufs->device, TT.db, + bufs->vname, bufs->devname); + } + if (CFG_LSPCI_TEXT && (TT.numeric == 2)) { + fmt = toys.optflags & FLAG_m + ? "%s, \"%s\" \"%s [%s]\" \"%s [%s]\" \"%s\"\n" + : "%s Class %s: %s [%s] %s [%s] %s\n"; + printf(fmt, new->name + 5, bufs->class, bufs->vname, bufs->vendor, + bufs->devname, bufs->device, driver); + } else { + printf(fmt, new->name + 5, bufs->class, + (res < 2) ? bufs->vname : bufs->vendor, + !(res) ? bufs->devname : bufs->device, driver); + } + } } return 0; @@ -61,5 +133,13 @@ void lspci_main(void) { + if (CFG_LSPCI_TEXT && (TT.numeric != 1)) { + TT.db = fopen("/usr/share/misc/pci.ids", "r"); + if (errno) { + TT.numeric = 1; + error_msg("could not open PCI ID db"); + } + } + dirtree_read("/sys/bus/pci/devices", do_lspci); }