toybox/toys/other/lspci.c
<<
>>
Prefs
   1/*
   2 * lspci - written by Isaac Dunham
   3
   4USE_LSPCI(NEWTOY(lspci, "emkn"USE_LSPCI_TEXT("@i:"), TOYFLAG_USR|TOYFLAG_BIN))
   5
   6config 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 parseable format
  17
  18config 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
  33GLOBALS(
  34  char *i;
  35  long n;
  36
  37  FILE *db;
  38)
  39
  40static 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 (toys.optflags & FLAG_k)
  55    readlinkat0(dirfd, "driver", driver, sizeof(driver));
  56
  57  for (fields = (char*[]){"class", "vendor", "device", 0}; *fields; fields++) {
  58    int fd, size = 6 + 2*((toys.optflags & FLAG_e) && p == toybuf);
  59    *p = 0;
  60
  61    if (-1 == (fd = openat(dirfd, *fields, O_RDONLY))) {
  62      close(dirfd);
  63      return 0;
  64    }
  65    xreadall(fd, p, size);
  66    memmove(p, p+2, size -= 2);
  67    p[size] = 0;
  68    close(fd);
  69    p += 9;
  70  }
  71
  72  close(dirfd);
  73
  74  // Lookup/display data from pci.ids?
  75
  76  if (CFG_LSPCI_TEXT && TT.db) {
  77    if (TT.n != 1) {
  78      char *s;
  79
  80      fseek(TT.db, 0, SEEK_SET);
  81      while (!vbig || !dbig) {
  82        s = p;
  83        if (!fgets(s, sizeof(toybuf)-(p-toybuf)-1, TT.db)) break;
  84        while (isspace(*s)) s++;
  85        if (*s == '#') continue;
  86        if (vbig && s == p) break;
  87        if (strstart(&s, vbig ? device : vendor)) {
  88          if (vbig) dbig = s+2;
  89          else vbig = s+2;
  90          s += strlen(s);
  91          s[-1] = 0; // trim ending newline
  92          p = s + 1;
  93        }
  94      }
  95    }
  96
  97    if (TT.n > 1) {
  98      printf((toys.optflags & FLAG_m)
  99        ? "%s, \"%s\" \"%s [%s]\" \"%s [%s]\""
 100        : "%s Class %s: %s [%s] %s [%s]",
 101        new->name+5, toybuf, vbig ? vbig : "", vendor,
 102        dbig ? dbig : "", device);
 103
 104      goto driver;
 105    }
 106  }
 107
 108  printf((toys.optflags & FLAG_m) ? "%s \"%s\" \"%s\" \"%s\""
 109    : "%s Class %s: %s:%s", new->name+5, toybuf, 
 110    vbig ? vbig : vendor, dbig ? dbig : device);
 111
 112driver:
 113  if (*driver)
 114    printf((toys.optflags & FLAG_m) ? " \"%s\"" : " %s", basename(driver));
 115  xputc('\n');
 116
 117  return 0;
 118}
 119
 120void lspci_main(void)
 121{
 122  if (CFG_LSPCI_TEXT && TT.n != 1) {
 123    if (!TT.i) TT.i = "/usr/share/misc/pci.ids";
 124    if (!(TT.db = fopen(TT.i, "r"))) perror_msg("%s", TT.i);
 125  }
 126
 127  dirtree_read("/sys/bus/pci/devices", do_lspci);
 128}
 129