• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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