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 readable 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
GLOBALS(char * i;long n;FILE * db;)33 GLOBALS(
34 char *i;
35 long n;
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 (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
109 driver:
110 if (*driver) printf(FLAG(m) ? " \"%s\"" : " %s", basename(driver));
111 xputc('\n');
112
113 return 0;
114 }
115
lspci_main(void)116 void 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