1/* 2 * lspci - written by Isaac Dunham 3 4USE_LSPCI(NEWTOY(lspci, "emkn"USE_LSPCI_TEXT("@i:"), TOYFLAG_USR|TOYFLAG_BIN)) 5 6config 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 readable format 17 18config 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 33GLOBALS( 34 char *i; 35 long n; 36 37 FILE *db; 38) 39 40static 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 (FLAG(k)) readlinkat0(dirfd, "driver", driver, sizeof(driver)); 55 56 for (fields = (char*[]){"class", "vendor", "device", 0}; *fields; fields++) { 57 int fd, size = 6 + 2*(FLAG(e) && p == toybuf); 58 *p = 0; 59 60 if (-1 == (fd = openat(dirfd, *fields, O_RDONLY))) { 61 close(dirfd); 62 return 0; 63 } 64 xreadall(fd, p, size); 65 memmove(p, p+2, size -= 2); 66 p[size] = 0; 67 close(fd); 68 p += 9; 69 } 70 71 close(dirfd); 72 73 // Lookup/display data from pci.ids? 74 75 if (CFG_LSPCI_TEXT && TT.db) { 76 if (TT.n != 1) { 77 char *s; 78 79 fseek(TT.db, 0, SEEK_SET); 80 while (!vbig || !dbig) { 81 s = p; 82 if (!fgets(s, sizeof(toybuf)-(p-toybuf)-1, TT.db)) break; 83 while (isspace(*s)) s++; 84 if (*s == '#') continue; 85 if (vbig && s == p) break; 86 if (strstart(&s, vbig ? device : vendor)) { 87 if (vbig) dbig = s+2; 88 else vbig = s+2; 89 s += strlen(s); 90 s[-1] = 0; // trim ending newline 91 p = s + 1; 92 } 93 } 94 } 95 96 if (TT.n > 1) { 97 printf(FLAG(m) ? "%s, \"%s\" \"%s [%s]\" \"%s [%s]\"" 98 : "%s Class %s: %s [%s] %s [%s]", 99 new->name+5, toybuf, vbig ? vbig : "", vendor, 100 dbig ? dbig : "", device); 101 102 goto driver; 103 } 104 } 105 106 printf(FLAG(m) ? "%s \"%s\" \"%s\" \"%s\"" : "%s Class %s: %s:%s", 107 new->name+5, toybuf, vbig ? vbig : vendor, dbig ? dbig : device); 108 109driver: 110 if (*driver) printf(FLAG(m) ? " \"%s\"" : " %s", basename(driver)); 111 xputc('\n'); 112 113 return 0; 114} 115 116void lspci_main(void) 117{ 118 if (CFG_LSPCI_TEXT && TT.n != 1) { 119 if (!TT.i) TT.i = "/usr/share/misc/pci.ids"; 120 if (!(TT.db = fopen(TT.i, "r"))) perror_msg("%s", TT.i); 121 } 122 123 dirtree_read("/sys/bus/pci/devices", do_lspci); 124} 125