1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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
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
75
76 if (CFG_LSPCI_TEXT && TT.db) {
77 if (TT.n != 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;
92 p = s + 1;
93 }
94 }
95 }
96
97 if (TT.n > 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
112driver:
113 if (*driver)
114 printf((toys.optflags & FLAG_m) ? " \"%s\"" : " %s", basename(driver));
115 xputc('\n');
116
117 return 0;
118}
119
120void lspci_main(void)
121{
122 if (CFG_LSPCI_TEXT && TT.n != 1) {
123 if (!TT.i) TT.i = "/usr/share/misc/pci.ids";
124 if (!(TT.db = fopen(TT.i, "r"))) perror_msg("%s", TT.i);
125 }
126
127 dirtree_read("/sys/bus/pci/devices", do_lspci);
128}
129