1 /* 2 * lspci - written by Isaac Dunham 3 4 USE_LSPCI(NEWTOY(lspci, "emkn"USE_LSPCI_TEXT("@i:"), TOYFLAG_USR|TOYFLAG_BIN)) 5 6 config LSPCI 7 bool "lspci" 8 default y 9 help 10 usage: lspci [-ekm] 11 12 List PCI devices. 13 14 -e Print all 6 digits in class 15 -k Print kernel driver 16 -m Machine parseable format 17 18 config LSPCI_TEXT 19 bool "lspci readable output" 20 depends on LSPCI 21 default y 22 help 23 usage: lspci [-n] [-i FILE ] 24 25 -n Numeric output (repeat for readable and numeric) 26 -i PCI ID database (default /usr/share/misc/pci.ids) 27 28 */ 29 30 #define FOR_lspci 31 #include "toys.h" 32 33 GLOBALS( 34 char *ids; 35 long numeric; 36 37 FILE *db; 38 ) 39 40 static int do_lspci(struct dirtree *new) 41 { 42 char *p = toybuf, *vendor = toybuf+9, *device = toybuf+18, 43 driver[256], *vbig = 0, *dbig = 0, **fields; 44 int dirfd; 45 46 if (!new->parent) return DIRTREE_RECURSE; 47 48 // Parse data out of /proc 49 50 if (-1 == (dirfd = openat(dirtree_parentfd(new), new->name, O_RDONLY))) 51 return 0; 52 53 *driver = 0; 54 if (toys.optflags & FLAG_k) 55 readlinkat0(dirfd, "driver", driver, sizeof(driver)); 56 57 for (fields = (char*[]){"class", "vendor", "device", 0}; *fields; fields++) { 58 int fd, size = 6 + 2*((toys.optflags & FLAG_e) && p == toybuf); 59 *p = 0; 60 61 if (-1 == (fd = openat(dirfd, *fields, O_RDONLY))) { 62 close(dirfd); 63 return 0; 64 } 65 xreadall(fd, p, size); 66 memmove(p, p+2, size -= 2); 67 p[size] = 0; 68 close(fd); 69 p += 9; 70 } 71 72 close(dirfd); 73 74 // Lookup/display data from pci.ids? 75 76 if (CFG_LSPCI_TEXT && TT.db) { 77 if (TT.numeric != 1) { 78 char *s; 79 80 fseek(TT.db, 0, SEEK_SET); 81 while (!vbig || !dbig) { 82 s = p; 83 if (!fgets(s, sizeof(toybuf)-(p-toybuf)-1, TT.db)) break; 84 while (isspace(*s)) s++; 85 if (*s == '#') continue; 86 if (vbig && s == p) break; 87 if (strstart(&s, vbig ? device : vendor)) { 88 if (vbig) dbig = s+2; 89 else vbig = s+2; 90 s += strlen(s); 91 s[-1] = 0; // trim ending newline 92 p = s + 1; 93 } 94 } 95 } 96 97 if (TT.numeric > 1) { 98 printf((toys.optflags & FLAG_m) 99 ? "%s, \"%s\" \"%s [%s]\" \"%s [%s]\"" 100 : "%s Class %s: %s [%s] %s [%s]", 101 new->name+5, toybuf, vbig ? vbig : "", vendor, 102 dbig ? dbig : "", device); 103 104 goto driver; 105 } 106 } 107 108 printf((toys.optflags & FLAG_m) ? "%s \"%s\" \"%s\" \"%s\"" 109 : "%s Class %s: %s:%s", new->name+5, toybuf, 110 vbig ? vbig : vendor, dbig ? dbig : device); 111 112 driver: 113 if (*driver) 114 printf((toys.optflags & FLAG_m) ? " \"%s\"" : " %s", basename(driver)); 115 xputc('\n'); 116 117 return 0; 118 } 119 120 void lspci_main(void) 121 { 122 if (CFG_LSPCI_TEXT && TT.numeric != 1) { 123 if (!TT.ids) TT.ids = "/usr/share/misc/pci.ids"; 124 if (!(TT.db = fopen(TT.ids, "r"))) perror_msg("%s", TT.ids); 125 } 126 127 dirtree_read("/sys/bus/pci/devices", do_lspci); 128 } 129