10f66f451Sopenharmony_ci/* 20f66f451Sopenharmony_ci * lspci - written by Isaac Dunham 30f66f451Sopenharmony_ci 40f66f451Sopenharmony_ciUSE_LSPCI(NEWTOY(lspci, "emkn"USE_LSPCI_TEXT("@i:"), TOYFLAG_USR|TOYFLAG_BIN)) 50f66f451Sopenharmony_ci 60f66f451Sopenharmony_ciconfig LSPCI 70f66f451Sopenharmony_ci bool "lspci" 80f66f451Sopenharmony_ci default y 90f66f451Sopenharmony_ci help 100f66f451Sopenharmony_ci usage: lspci [-ekm] 110f66f451Sopenharmony_ci 120f66f451Sopenharmony_ci List PCI devices. 130f66f451Sopenharmony_ci 140f66f451Sopenharmony_ci -e Print all 6 digits in class 150f66f451Sopenharmony_ci -k Print kernel driver 160f66f451Sopenharmony_ci -m Machine readable format 170f66f451Sopenharmony_ci 180f66f451Sopenharmony_ciconfig LSPCI_TEXT 190f66f451Sopenharmony_ci bool "lspci readable output" 200f66f451Sopenharmony_ci depends on LSPCI 210f66f451Sopenharmony_ci default y 220f66f451Sopenharmony_ci help 230f66f451Sopenharmony_ci usage: lspci [-n] [-i FILE ] 240f66f451Sopenharmony_ci 250f66f451Sopenharmony_ci -n Numeric output (repeat for readable and numeric) 260f66f451Sopenharmony_ci -i PCI ID database (default /usr/share/misc/pci.ids) 270f66f451Sopenharmony_ci 280f66f451Sopenharmony_ci*/ 290f66f451Sopenharmony_ci 300f66f451Sopenharmony_ci#define FOR_lspci 310f66f451Sopenharmony_ci#include "toys.h" 320f66f451Sopenharmony_ci 330f66f451Sopenharmony_ciGLOBALS( 340f66f451Sopenharmony_ci char *i; 350f66f451Sopenharmony_ci long n; 360f66f451Sopenharmony_ci 370f66f451Sopenharmony_ci FILE *db; 380f66f451Sopenharmony_ci) 390f66f451Sopenharmony_ci 400f66f451Sopenharmony_cistatic int do_lspci(struct dirtree *new) 410f66f451Sopenharmony_ci{ 420f66f451Sopenharmony_ci char *p = toybuf, *vendor = toybuf+9, *device = toybuf+18, 430f66f451Sopenharmony_ci driver[256], *vbig = 0, *dbig = 0, **fields; 440f66f451Sopenharmony_ci int dirfd; 450f66f451Sopenharmony_ci 460f66f451Sopenharmony_ci if (!new->parent) return DIRTREE_RECURSE; 470f66f451Sopenharmony_ci 480f66f451Sopenharmony_ci // Parse data out of /proc 490f66f451Sopenharmony_ci 500f66f451Sopenharmony_ci if (-1 == (dirfd = openat(dirtree_parentfd(new), new->name, O_RDONLY))) 510f66f451Sopenharmony_ci return 0; 520f66f451Sopenharmony_ci 530f66f451Sopenharmony_ci *driver = 0; 540f66f451Sopenharmony_ci if (FLAG(k)) readlinkat0(dirfd, "driver", driver, sizeof(driver)); 550f66f451Sopenharmony_ci 560f66f451Sopenharmony_ci for (fields = (char*[]){"class", "vendor", "device", 0}; *fields; fields++) { 570f66f451Sopenharmony_ci int fd, size = 6 + 2*(FLAG(e) && p == toybuf); 580f66f451Sopenharmony_ci *p = 0; 590f66f451Sopenharmony_ci 600f66f451Sopenharmony_ci if (-1 == (fd = openat(dirfd, *fields, O_RDONLY))) { 610f66f451Sopenharmony_ci close(dirfd); 620f66f451Sopenharmony_ci return 0; 630f66f451Sopenharmony_ci } 640f66f451Sopenharmony_ci xreadall(fd, p, size); 650f66f451Sopenharmony_ci memmove(p, p+2, size -= 2); 660f66f451Sopenharmony_ci p[size] = 0; 670f66f451Sopenharmony_ci close(fd); 680f66f451Sopenharmony_ci p += 9; 690f66f451Sopenharmony_ci } 700f66f451Sopenharmony_ci 710f66f451Sopenharmony_ci close(dirfd); 720f66f451Sopenharmony_ci 730f66f451Sopenharmony_ci // Lookup/display data from pci.ids? 740f66f451Sopenharmony_ci 750f66f451Sopenharmony_ci if (CFG_LSPCI_TEXT && TT.db) { 760f66f451Sopenharmony_ci if (TT.n != 1) { 770f66f451Sopenharmony_ci char *s; 780f66f451Sopenharmony_ci 790f66f451Sopenharmony_ci fseek(TT.db, 0, SEEK_SET); 800f66f451Sopenharmony_ci while (!vbig || !dbig) { 810f66f451Sopenharmony_ci s = p; 820f66f451Sopenharmony_ci if (!fgets(s, sizeof(toybuf)-(p-toybuf)-1, TT.db)) break; 830f66f451Sopenharmony_ci while (isspace(*s)) s++; 840f66f451Sopenharmony_ci if (*s == '#') continue; 850f66f451Sopenharmony_ci if (vbig && s == p) break; 860f66f451Sopenharmony_ci if (strstart(&s, vbig ? device : vendor)) { 870f66f451Sopenharmony_ci if (vbig) dbig = s+2; 880f66f451Sopenharmony_ci else vbig = s+2; 890f66f451Sopenharmony_ci s += strlen(s); 900f66f451Sopenharmony_ci s[-1] = 0; // trim ending newline 910f66f451Sopenharmony_ci p = s + 1; 920f66f451Sopenharmony_ci } 930f66f451Sopenharmony_ci } 940f66f451Sopenharmony_ci } 950f66f451Sopenharmony_ci 960f66f451Sopenharmony_ci if (TT.n > 1) { 970f66f451Sopenharmony_ci printf(FLAG(m) ? "%s, \"%s\" \"%s [%s]\" \"%s [%s]\"" 980f66f451Sopenharmony_ci : "%s Class %s: %s [%s] %s [%s]", 990f66f451Sopenharmony_ci new->name+5, toybuf, vbig ? vbig : "", vendor, 1000f66f451Sopenharmony_ci dbig ? dbig : "", device); 1010f66f451Sopenharmony_ci 1020f66f451Sopenharmony_ci goto driver; 1030f66f451Sopenharmony_ci } 1040f66f451Sopenharmony_ci } 1050f66f451Sopenharmony_ci 1060f66f451Sopenharmony_ci printf(FLAG(m) ? "%s \"%s\" \"%s\" \"%s\"" : "%s Class %s: %s:%s", 1070f66f451Sopenharmony_ci new->name+5, toybuf, vbig ? vbig : vendor, dbig ? dbig : device); 1080f66f451Sopenharmony_ci 1090f66f451Sopenharmony_cidriver: 1100f66f451Sopenharmony_ci if (*driver) printf(FLAG(m) ? " \"%s\"" : " %s", basename(driver)); 1110f66f451Sopenharmony_ci xputc('\n'); 1120f66f451Sopenharmony_ci 1130f66f451Sopenharmony_ci return 0; 1140f66f451Sopenharmony_ci} 1150f66f451Sopenharmony_ci 1160f66f451Sopenharmony_civoid lspci_main(void) 1170f66f451Sopenharmony_ci{ 1180f66f451Sopenharmony_ci if (CFG_LSPCI_TEXT && TT.n != 1) { 1190f66f451Sopenharmony_ci if (!TT.i) TT.i = "/usr/share/misc/pci.ids"; 1200f66f451Sopenharmony_ci if (!(TT.db = fopen(TT.i, "r"))) perror_msg("%s", TT.i); 1210f66f451Sopenharmony_ci } 1220f66f451Sopenharmony_ci 1230f66f451Sopenharmony_ci dirtree_read("/sys/bus/pci/devices", do_lspci); 1240f66f451Sopenharmony_ci} 125