| Isaac Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 1 | /* |
| 2 | * lspci - written by Isaac Dunham |
| 3 | |
| Felix Janda | f97cc9f | 2013-07-26 22:49:05 -0500 | [diff] [blame] | 4 | USE_LSPCI(NEWTOY(lspci, "emkns:", 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 |
| Felix Janda | f97cc9f | 2013-07-26 22:49:05 -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 |
| 16 | -n Numeric output (default) |
| 17 | */ |
| 18 | #define FOR_lspci |
| 19 | #include "toys.h" |
| Isaac Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 20 | |
| 21 | int do_lspci(struct dirtree *new) |
| 22 | { |
| Felix Janda | f97cc9f | 2013-07-26 22:49:05 -0500 | [diff] [blame] | 23 | int alen = 8, dirfd; |
| Isaac Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 24 | char *dname = dirtree_path(new, &alen); |
| Felix Janda | f97cc9f | 2013-07-26 22:49:05 -0500 | [diff] [blame] | 25 | struct { |
| 26 | char class[16], vendor[16], device[16], module[256]; |
| 27 | } *bufs = (void*)(toybuf + 2); |
| 28 | |
| 29 | if (!strcmp("/sys/bus/pci/devices", dname)) return DIRTREE_RECURSE; |
| Isaac Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 30 | errno = 0; |
| Felix Janda | f97cc9f | 2013-07-26 22:49:05 -0500 | [diff] [blame] | 31 | dirfd = open(dname, O_RDONLY); |
| Isaac Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 32 | if (dirfd > 0) { |
| Felix Janda | f97cc9f | 2013-07-26 22:49:05 -0500 | [diff] [blame] | 33 | char *p, **fields = (char*[]){"class", "vendor", "device", ""}; |
| 34 | |
| 35 | for (p = toybuf; **fields; p+=16, fields++) { |
| 36 | int fd, size; |
| 37 | |
| 38 | if ((fd = openat(dirfd, *fields, O_RDONLY)) < 0) continue; |
| Felix Janda | e3a6c4e | 2013-07-27 09:45:40 +0200 | [diff] [blame] | 39 | size = ((toys.optflags & FLAG_e) && (p == toybuf)) ? 8 : 6; |
| Felix Janda | f97cc9f | 2013-07-26 22:49:05 -0500 | [diff] [blame] | 40 | p[read(fd, p, size)] = '\0'; |
| 41 | close(fd); |
| 42 | } |
| 43 | |
| Isaac Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 44 | close(dirfd); |
| 45 | if (!errno) { |
| 46 | char *driver = ""; |
| Felix Janda | f97cc9f | 2013-07-26 22:49:05 -0500 | [diff] [blame] | 47 | char *fmt = toys.optflags & FLAG_m ? "%s, \"%s\" \"%s\" \"%s\" \"%s\"\n" |
| 48 | : "%s Class %s: %s:%s %s\n"; |
| 49 | |
| Isaac Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 50 | if (toys.optflags & FLAG_k) { |
| Isaac Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 51 | strcat(dname, "/driver"); |
| Felix Janda | f97cc9f | 2013-07-26 22:49:05 -0500 | [diff] [blame] | 52 | if (readlink(dname, bufs->module, sizeof(bufs->module)) != -1) |
| 53 | driver = basename(bufs->module); |
| Isaac Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 54 | } |
| Felix Janda | f97cc9f | 2013-07-26 22:49:05 -0500 | [diff] [blame] | 55 | printf(fmt, new->name + 5, bufs->class, bufs->vendor, bufs->device, |
| Isaac Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 56 | driver); |
| Isaac Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 57 | } |
| 58 | } |
| Isaac Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 59 | return 0; |
| 60 | } |
| 61 | |
| 62 | void lspci_main(void) |
| 63 | { |
| Felix Janda | f97cc9f | 2013-07-26 22:49:05 -0500 | [diff] [blame] | 64 | dirtree_read("/sys/bus/pci/devices", do_lspci); |
| Isaac Dunham | fe03a1f | 2013-07-26 15:41:31 -0500 | [diff] [blame] | 65 | } |