diff options
| author | Burt P <pburt0@gmail.com> | 2019-12-31 21:34:54 -0600 | 
|---|---|---|
| committer | Leandro A. F. Pereira <leandro@hardinfo.org> | 2020-01-03 09:33:24 -0800 | 
| commit | 1afd683fea89d759ea05a65194e05e4eed38847c (patch) | |
| tree | e18c5c18d1b0b85693c81929d79c23df200351c1 | |
| parent | 55eb5de05921238cb7992fe76334553356bd3d9a (diff) | |
pci: get list from sysfs without using lscpi/pciutils
The lspci-using code is still there as fallback.
Signed-off-by: Burt P <pburt0@gmail.com>
| -rw-r--r-- | hardinfo/pci_util.c | 64 | 
1 files changed, 55 insertions, 9 deletions
| diff --git a/hardinfo/pci_util.c b/hardinfo/pci_util.c index 6db14136..11c9b32f 100644 --- a/hardinfo/pci_util.c +++ b/hardinfo/pci_util.c @@ -62,13 +62,14 @@ char *pci_lookup_ids_vendor_str(uint32_t id) {      return ret;  } -static void pci_lookup_ids(pcid *d) { +static gboolean pci_lookup_ids(pcid *d) { +    gboolean ret = FALSE;      ids_query_result result = {};      gchar *qpath;      if (!pci_ids_file)          find_pci_ids_file(); -    if (!pci_ids_file) return; +    if (!pci_ids_file) return FALSE;      /* lookup vendor, device, sub device */      qpath = g_strdup_printf("%04x/%04x/%04x %04x", @@ -77,14 +78,17 @@ static void pci_lookup_ids(pcid *d) {      if (result.results[0]) {          if (d->vendor_id_str) g_free(d->vendor_id_str);          d->vendor_id_str = g_strdup(result.results[0]); +        ret = TRUE;      }      if (result.results[1]) {          if (d->device_id_str) g_free(d->device_id_str);          d->device_id_str = g_strdup(result.results[1]); +        ret = TRUE;      }      if (result.results[2]) {          if (d->sub_device_id_str) g_free(d->sub_device_id_str);          d->sub_device_id_str = g_strdup(result.results[2]); +        ret = TRUE;      }      g_free(qpath); @@ -94,8 +98,10 @@ static void pci_lookup_ids(pcid *d) {      if (result.results[0]) {          if (d->sub_vendor_id_str) g_free(d->sub_vendor_id_str);          d->sub_vendor_id_str = g_strdup(result.results[0]); -    } +        ret = TRUE; +    };      g_free(qpath); +    return ret;  }  pcid *pcid_new() { @@ -339,9 +345,11 @@ pcid *pci_get_device(uint32_t dom, uint32_t bus, uint32_t dev, uint32_t func) {      gboolean ok = FALSE;      if (s) {          ok = pci_get_device_sysfs(dom, bus, dev, func, s); -        ok |= pci_get_device_lspci(dom, bus, dev, func, s); -        /* TODO: other methods */ - +        if (ok) { +            ok |= pci_lookup_ids(s); +            if (!ok) +                ok |= pci_get_device_lspci(dom, bus, dev, func, s); +        }          if (!ok) {              pcid_free(s);              s = NULL; @@ -386,9 +394,47 @@ static pcid *pci_get_device_list_lspci(uint32_t class_min, uint32_t class_max) {      return head;  } +static pcid *pci_get_device_list_sysfs(uint32_t class_min, uint32_t class_max) { +    pcid *head = NULL, *nd; +    uint32_t dom, bus, dev, func, cls; +    int ec; + +    if (class_max == 0) class_max = 0xffff; + +    const gchar *f = NULL; +    GDir *d = g_dir_open("/sys/bus/pci/devices", 0, NULL); +    if (!d) return 0; + +    while((f = g_dir_read_name(d))) { +        ec = sscanf(f, "%x:%x:%x.%x", &dom, &bus, &dev, &func); +        if (ec == 4) { +            gchar *cf = g_strdup_printf("/sys/bus/pci/devices/%s/class", f); +            gchar *cstr = NULL; +            if (g_file_get_contents(cf, &cstr, NULL, NULL) ) { +                cls = strtoul(cstr, NULL, 16) >> 8; +                if (cls >= class_min && cls <= class_max) { +                    nd = pci_get_device(dom, bus, dev, func); +                    pci_fill_details(nd); +                    if (head == NULL) { +                        head = nd; +                    } else { +                        pcid_list_append(head, nd); +                    } +                } +            } +            g_free(cstr); +            g_free(cf); +        } +    } +    g_dir_close(d); +    return head; +} +  pcid *pci_get_device_list(uint32_t class_min, uint32_t class_max) { -    /* try lspci */ -    return pci_get_device_list_lspci(class_min, class_max); -    /* TODO: other methods */ +    pcid *ret = NULL; +    ret = pci_get_device_list_sysfs(class_min, class_max); +    if (!ret) +        ret = pci_get_device_list_lspci(class_min, class_max); +    return ret;  } | 
