blob: 16fd0f6022ad64cdaa24951e7b547da346a14710 [file] [log] [blame]
Isaac Dunhamfe03a1f2013-07-26 15:41:31 -05001/*
2 * lspci - written by Isaac Dunham
3
Isaac Dunham17ea5642013-08-07 11:51:26 -05004USE_LSPCI(NEWTOY(lspci, "emkn@", TOYFLAG_USR|TOYFLAG_BIN))
Isaac Dunhamfe03a1f2013-07-26 15:41:31 -05005
6config LSPCI
7 bool "lspci"
8 default n
9 help
Isaac Dunham17ea5642013-08-07 11:51:26 -050010 usage: lspci [-ekmn@]
Isaac Dunhamfe03a1f2013-07-26 15:41:31 -050011
12 List PCI devices.
Felix Jandaf97cc9f2013-07-26 22:49:05 -050013 -e Print all 6 digits in class (like elspci)
Isaac Dunhamfe03a1f2013-07-26 15:41:31 -050014 -k Print kernel driver
15 -m Machine parseable format
Isaac Dunham17ea5642013-08-07 11:51:26 -050016 -n Numeric output
17
18config LSPCI_TEXT
19 bool "lspci readable output"
20 depends on LSPCI
21 default n
22 help
23 lspci without -n prints readable descriptions;
24 lspci -nn prints both readable and numeric description
Isaac Dunhamfe03a1f2013-07-26 15:41:31 -050025*/
26#define FOR_lspci
27#include "toys.h"
Isaac Dunham17ea5642013-08-07 11:51:26 -050028extern int find_in_db(char * , char * , FILE * , char * , char * );
29
30GLOBALS(
31long numeric;
32
33FILE * db;
34)
35
36char * id_check_match(char * id, char * buf)
37{
38 int i = 0;
39 while (id[i]) {
40 if (id[i] == buf[i]) {
41 i++;
42 } else {
43 return (char *)0L;
44 }
45 }
46 return (buf + i + 2);
47}
48
49/*
50 * In: vendid, devid, fil
51 * Out: vname, devname
52 * Out must be zeroed before use.
53 * vmame and devname must be char[256], zeroed out
54 * Returns (2 - number of IDs matched): vendor must be matched for
55 * dev to be matched
56 */
57int find_in_db(char * vendid, char * devid, FILE * fil,
58 char * vname, char * devname)
59{
60 fseek(fil, 0, SEEK_SET);
61 char buf[256], *vtext = 0L, *dtext = 0L;
62 while (!(vname[0])) {
63 //loop through
64 if (fgets(buf, 255, fil)==NULL) return 2;
65 if ((vtext = id_check_match(vendid, buf)))
66 strncpy(vname, vtext, strlen(vtext) - 1);
67 }
68 while (!(devname[0])) {
69 if ((fgets(buf, 255, fil)==NULL) || (buf[0] != '\t' ))
70 return 1;
71 if ((dtext = id_check_match(devid, buf + 1)))
72 strncpy(devname, dtext, strlen(dtext) - 1);
73 }
74 return 0; /* Succeeded in matching both */
75}
Isaac Dunhamfe03a1f2013-07-26 15:41:31 -050076
77int do_lspci(struct dirtree *new)
78{
Isaac Dunham17ea5642013-08-07 11:51:26 -050079 int alen = 8, dirfd, res = 2; //no textual descriptions read
Isaac Dunhamfe03a1f2013-07-26 15:41:31 -050080 char *dname = dirtree_path(new, &alen);
Isaac Dunham17ea5642013-08-07 11:51:26 -050081 memset(toybuf, 0, 4096);
Felix Jandaf97cc9f2013-07-26 22:49:05 -050082 struct {
Isaac Dunham17ea5642013-08-07 11:51:26 -050083 char class[16], vendor[16], device[16], module[256],
84 vname[256], devname[256];
Felix Jandaf97cc9f2013-07-26 22:49:05 -050085 } *bufs = (void*)(toybuf + 2);
86
87 if (!strcmp("/sys/bus/pci/devices", dname)) return DIRTREE_RECURSE;
Isaac Dunhamfe03a1f2013-07-26 15:41:31 -050088 errno = 0;
Felix Jandaf97cc9f2013-07-26 22:49:05 -050089 dirfd = open(dname, O_RDONLY);
Isaac Dunhamfe03a1f2013-07-26 15:41:31 -050090 if (dirfd > 0) {
Felix Jandaf97cc9f2013-07-26 22:49:05 -050091 char *p, **fields = (char*[]){"class", "vendor", "device", ""};
92
93 for (p = toybuf; **fields; p+=16, fields++) {
94 int fd, size;
95
96 if ((fd = openat(dirfd, *fields, O_RDONLY)) < 0) continue;
Felix Jandae3a6c4e2013-07-27 09:45:40 +020097 size = ((toys.optflags & FLAG_e) && (p == toybuf)) ? 8 : 6;
Felix Jandaf97cc9f2013-07-26 22:49:05 -050098 p[read(fd, p, size)] = '\0';
99 close(fd);
100 }
101
Isaac Dunhamfe03a1f2013-07-26 15:41:31 -0500102 close(dirfd);
103 if (!errno) {
104 char *driver = "";
Felix Jandaf97cc9f2013-07-26 22:49:05 -0500105 char *fmt = toys.optflags & FLAG_m ? "%s, \"%s\" \"%s\" \"%s\" \"%s\"\n"
106 : "%s Class %s: %s:%s %s\n";
107
Isaac Dunhamfe03a1f2013-07-26 15:41:31 -0500108 if (toys.optflags & FLAG_k) {
Isaac Dunhamfe03a1f2013-07-26 15:41:31 -0500109 strcat(dname, "/driver");
Felix Jandaf97cc9f2013-07-26 22:49:05 -0500110 if (readlink(dname, bufs->module, sizeof(bufs->module)) != -1)
111 driver = basename(bufs->module);
Isaac Dunhamfe03a1f2013-07-26 15:41:31 -0500112 }
Isaac Dunham17ea5642013-08-07 11:51:26 -0500113 if (CFG_LSPCI_TEXT && (TT.numeric != 1)) {
114 res = find_in_db(bufs->vendor, bufs->device, TT.db,
115 bufs->vname, bufs->devname);
116 }
117 if (CFG_LSPCI_TEXT && (TT.numeric == 2)) {
118 fmt = toys.optflags & FLAG_m
119 ? "%s, \"%s\" \"%s [%s]\" \"%s [%s]\" \"%s\"\n"
120 : "%s Class %s: %s [%s] %s [%s] %s\n";
121 printf(fmt, new->name + 5, bufs->class, bufs->vname, bufs->vendor,
122 bufs->devname, bufs->device, driver);
123 } else {
124 printf(fmt, new->name + 5, bufs->class,
125 (res < 2) ? bufs->vname : bufs->vendor,
126 !(res) ? bufs->devname : bufs->device, driver);
127 }
128
Isaac Dunhamfe03a1f2013-07-26 15:41:31 -0500129 }
130 }
Isaac Dunhamfe03a1f2013-07-26 15:41:31 -0500131 return 0;
132}
133
134void lspci_main(void)
135{
Isaac Dunham17ea5642013-08-07 11:51:26 -0500136 if (CFG_LSPCI_TEXT && (TT.numeric != 1)) {
137 TT.db = fopen("/usr/share/misc/pci.ids", "r");
138 if (errno) {
139 TT.numeric = 1;
140 error_msg("could not open PCI ID db");
141 }
142 }
143
Felix Jandaf97cc9f2013-07-26 22:49:05 -0500144 dirtree_read("/sys/bus/pci/devices", do_lspci);
Isaac Dunhamfe03a1f2013-07-26 15:41:31 -0500145}