| Isaac Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 1 | /* |
| 2 | * lspci - written by Isaac Dunham |
| 3 | |
| Isaac Dunham | 17ea564 | 2013-08-07 11:51:26 -0500 | [diff] [blame^] | 4 | USE_LSPCI(NEWTOY(lspci, "emkn@", TOYFLAG_USR|TOYFLAG_BIN)) |
| Isaac Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 5 | |
| 6 | config LSPCI |
| 7 | bool "lspci" |
| 8 | default n |
| 9 | help |
| Isaac Dunham | 17ea564 | 2013-08-07 11:51:26 -0500 | [diff] [blame^] | 10 | usage: lspci [-ekmn@] |
| Isaac Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 11 | |
| 12 | List PCI devices. |
| Felix Janda | f97cc9f | 2013-07-26 22:49:05 -0500 | [diff] [blame] | 13 | -e Print all 6 digits in class (like elspci) |
| Isaac Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 14 | -k Print kernel driver |
| 15 | -m Machine parseable format |
| Isaac Dunham | 17ea564 | 2013-08-07 11:51:26 -0500 | [diff] [blame^] | 16 | -n Numeric output |
| 17 | |
| 18 | config 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 Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 25 | */ |
| 26 | #define FOR_lspci |
| 27 | #include "toys.h" |
| Isaac Dunham | 17ea564 | 2013-08-07 11:51:26 -0500 | [diff] [blame^] | 28 | extern int find_in_db(char * , char * , FILE * , char * , char * ); |
| 29 | |
| 30 | GLOBALS( |
| 31 | long numeric; |
| 32 | |
| 33 | FILE * db; |
| 34 | ) |
| 35 | |
| 36 | char * 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 | */ |
| 57 | int 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 Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 76 | |
| 77 | int do_lspci(struct dirtree *new) |
| 78 | { |
| Isaac Dunham | 17ea564 | 2013-08-07 11:51:26 -0500 | [diff] [blame^] | 79 | int alen = 8, dirfd, res = 2; //no textual descriptions read |
| Isaac Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 80 | char *dname = dirtree_path(new, &alen); |
| Isaac Dunham | 17ea564 | 2013-08-07 11:51:26 -0500 | [diff] [blame^] | 81 | memset(toybuf, 0, 4096); |
| Felix Janda | f97cc9f | 2013-07-26 22:49:05 -0500 | [diff] [blame] | 82 | struct { |
| Isaac Dunham | 17ea564 | 2013-08-07 11:51:26 -0500 | [diff] [blame^] | 83 | char class[16], vendor[16], device[16], module[256], |
| 84 | vname[256], devname[256]; |
| Felix Janda | f97cc9f | 2013-07-26 22:49:05 -0500 | [diff] [blame] | 85 | } *bufs = (void*)(toybuf + 2); |
| 86 | |
| 87 | if (!strcmp("/sys/bus/pci/devices", dname)) return DIRTREE_RECURSE; |
| Isaac Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 88 | errno = 0; |
| Felix Janda | f97cc9f | 2013-07-26 22:49:05 -0500 | [diff] [blame] | 89 | dirfd = open(dname, O_RDONLY); |
| Isaac Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 90 | if (dirfd > 0) { |
| Felix Janda | f97cc9f | 2013-07-26 22:49:05 -0500 | [diff] [blame] | 91 | 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 Janda | e3a6c4e | 2013-07-27 09:45:40 +0200 | [diff] [blame] | 97 | size = ((toys.optflags & FLAG_e) && (p == toybuf)) ? 8 : 6; |
| Felix Janda | f97cc9f | 2013-07-26 22:49:05 -0500 | [diff] [blame] | 98 | p[read(fd, p, size)] = '\0'; |
| 99 | close(fd); |
| 100 | } |
| 101 | |
| Isaac Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 102 | close(dirfd); |
| 103 | if (!errno) { |
| 104 | char *driver = ""; |
| Felix Janda | f97cc9f | 2013-07-26 22:49:05 -0500 | [diff] [blame] | 105 | char *fmt = toys.optflags & FLAG_m ? "%s, \"%s\" \"%s\" \"%s\" \"%s\"\n" |
| 106 | : "%s Class %s: %s:%s %s\n"; |
| 107 | |
| Isaac Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 108 | if (toys.optflags & FLAG_k) { |
| Isaac Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 109 | strcat(dname, "/driver"); |
| Felix Janda | f97cc9f | 2013-07-26 22:49:05 -0500 | [diff] [blame] | 110 | if (readlink(dname, bufs->module, sizeof(bufs->module)) != -1) |
| 111 | driver = basename(bufs->module); |
| Isaac Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 112 | } |
| Isaac Dunham | 17ea564 | 2013-08-07 11:51:26 -0500 | [diff] [blame^] | 113 | 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 Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 129 | } |
| 130 | } |
| Isaac Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 131 | return 0; |
| 132 | } |
| 133 | |
| 134 | void lspci_main(void) |
| 135 | { |
| Isaac Dunham | 17ea564 | 2013-08-07 11:51:26 -0500 | [diff] [blame^] | 136 | 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 Janda | f97cc9f | 2013-07-26 22:49:05 -0500 | [diff] [blame] | 144 | dirtree_read("/sys/bus/pci/devices", do_lspci); |
| Isaac Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 145 | } |