diff options
author | Ondrej Čerman <ondrej.cerman@gmail.com> | 2019-07-20 23:07:56 +0200 |
---|---|---|
committer | Leandro A. F. Pereira <leandro@hardinfo.org> | 2019-07-29 19:44:04 -0700 |
commit | 5f620001a8f9017449d15b1a4aafdb9a61a44d4d (patch) | |
tree | 1900083d1506905f6dbe4af523f5351f656dc599 | |
parent | 08a74ce10aedafd1a9e2f3c411e5eeea3658f71d (diff) |
usb: added info from sysfs
-rw-r--r-- | hardinfo/usb_util.c | 148 | ||||
-rw-r--r-- | hardinfo/util.c | 16 | ||||
-rw-r--r-- | includes/hardinfo.h | 1 | ||||
-rw-r--r-- | includes/usb_util.h | 7 | ||||
-rw-r--r-- | modules/devices/usb.c | 32 |
5 files changed, 187 insertions, 17 deletions
diff --git a/hardinfo/usb_util.c b/hardinfo/usb_util.c index 827a82c5..59ccab5c 100644 --- a/hardinfo/usb_util.c +++ b/hardinfo/usb_util.c @@ -3,6 +3,7 @@ * Copyright (C) 2003-2017 Leandro A. F. Pereira <leandro@hardinfo.org> * This file * Copyright (C) 2017 Burt P. <pburt0@gmail.com> + * Copyright (C) 2019 Ondrej Čerman * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,6 +22,8 @@ #include "hardinfo.h" #include "usb_util.h" +#define SYSFS_DIR_USB_DEVICES "/sys/bus/usb/devices" + usbi *usbi_new() { return g_new0(usbi, 1); } @@ -30,6 +33,7 @@ void usbi_free(usbi *s) { g_free(s->if_class_str); g_free(s->if_subclass_str); g_free(s->if_protocol_str); + g_free(s->driver); g_free(s); } } @@ -52,6 +56,8 @@ void usbd_free(usbd *s) { usbi_list_free(s->if_list); g_free(s->vendor); g_free(s->product); + g_free(s->manufacturer); + g_free(s->device); g_free(s->usb_version); g_free(s->device_version); g_free(s->dev_class_str); @@ -182,8 +188,6 @@ static gboolean usb_get_device_lsusb(int bus, int dev, usbd *s) { } } - /* TODO: speed_mbs, improve interfaces - * WISHLIST: drivers */ p = next_nl + 1; } g_free(out); @@ -193,14 +197,91 @@ static gboolean usb_get_device_lsusb(int bus, int dev, usbd *s) { return FALSE; } -usbd *usb_get_device(int bus, int dev) { +static gboolean usb_get_interface_sysfs(int conf, int number, + const char* devpath, usbi *intf){ + gchar *ifpath, *drvpath, *tmp; + + ifpath = g_strdup_printf("%s:%d.%d", devpath, conf, number); + if (!g_file_test(ifpath, G_FILE_TEST_EXISTS)){ + return FALSE; + } + + tmp = g_strdup_printf("%s/driver", ifpath); + drvpath = g_file_read_link(tmp, NULL); + g_free(tmp); + if (drvpath){ + intf->driver = g_path_get_basename(drvpath); + g_free(drvpath); + } + else{ + intf->driver = g_strdup(_("(None)")); + } + + intf->if_number = number; + intf->if_class = h_sysfs_read_hex(ifpath, "bInterfaceClass"); + intf->if_subclass = h_sysfs_read_hex(ifpath, "bInterfaceSubClass"); + intf->if_protocol = h_sysfs_read_hex(ifpath, "bInterfaceProtocol"); + + g_free(ifpath); + return TRUE; +} + +static gboolean usb_get_device_sysfs(int bus, int dev, const char* sysfspath, usbd *s) { + usbi *intf; + gboolean ok; + int i, if_count = 0, conf = 0; + if (sysfspath == NULL) + return FALSE; + + s->bus = bus; + s->dev = dev; + s->dev_class = h_sysfs_read_hex(sysfspath, "bDeviceClass"); + s->vendor_id = h_sysfs_read_hex(sysfspath, "idVendor"); + s->product_id = h_sysfs_read_hex(sysfspath, "idProduct"); + s->manufacturer = h_sysfs_read_string(sysfspath, "manufacturer"); + s->device = h_sysfs_read_string(sysfspath, "product"); + s->max_curr_ma = h_sysfs_read_int(sysfspath, "bMaxPower"); + s->dev_class = h_sysfs_read_hex(sysfspath, "bDeviceClass"); + s->dev_subclass = h_sysfs_read_hex(sysfspath, "bDeviceSubClass"); + s->speed_mbs = h_sysfs_read_int(sysfspath, "speed"); + + conf = h_sysfs_read_hex(sysfspath, "bConfigurationValue"); + + if (s->usb_version == NULL) + s->usb_version = h_sysfs_read_string(sysfspath, "version"); + + if (s->if_list == NULL){ // create interfaces list + if_count = h_sysfs_read_int(sysfspath, "bNumInterfaces"); + for (i = 0; i <= if_count; i++){ + intf = usbi_new(); + ok = usb_get_interface_sysfs(conf, i, sysfspath, intf); + if (ok){ + usbd_append_interface(s, intf); + } + else{ + usbi_free(intf); + } + } + } + else{ // improve existing list + intf = s->if_list; + while (intf){ + usb_get_interface_sysfs(conf, intf->if_number, sysfspath, intf); + intf = intf->next; + } + } + + return TRUE; +} + +usbd *usb_get_device(int bus, int dev, const gchar* sysfspath) { usbd *s = usbd_new(); int ok = 0; if (s) { /* try lsusb */ ok = usb_get_device_lsusb(bus, dev, s); - - /* TODO: other methods */ + /* try sysfs */ + ok |= usb_get_device_sysfs(bus, dev, sysfspath, s); if (!ok) { usbd_free(s); @@ -224,7 +305,7 @@ static usbd *usb_get_device_list_lsusb() { strend(p, '\n'); ec = sscanf(p, "Bus %d Device %d: ID %x:%x", &bus, &dev, &vend, &prod); if (ec == 4) { - nd = usb_get_device(bus, dev); + nd = usb_get_device(bus, dev, NULL); if (head == NULL) { head = nd; } else { @@ -239,9 +320,58 @@ static usbd *usb_get_device_list_lsusb() { return head; } +static usbd *usb_get_device_list_sysfs() { + GDir *dir; + GRegex *regex; + GMatchInfo *match_info; + usbd *head = NULL, *nd; + gchar *devpath; + const char *entry; + int bus, dev; + + regex = g_regex_new("^([0-9]+-[0-9]+([.][0-9]+)*)|(usb[0-9]+)$", 0, 0, NULL); + if (!regex){ + return NULL; + } + + dir = g_dir_open(SYSFS_DIR_USB_DEVICES, 0, NULL); + if (!dir){ + return NULL; + } + + while ((entry = g_dir_read_name(dir))) { + g_regex_match(regex, entry, 0, &match_info); + + if (g_match_info_matches(match_info)) { + devpath = g_build_filename(SYSFS_DIR_USB_DEVICES, entry, NULL); + bus = h_sysfs_read_int(devpath, "busnum"); + dev = h_sysfs_read_int(devpath, "devnum"); + + if (bus > 0 && dev > 0){ + nd = usb_get_device(bus, dev, devpath); + if (head == NULL) { + head = nd; + } else { + usbd_list_append(head, nd); + } + } + g_free(devpath); + } + g_match_info_free(match_info); + } + + g_dir_close(dir); + g_regex_unref(regex); + + return head; +} + usbd *usb_get_device_list() { - /* try lsusb */ - return usb_get_device_list_lsusb(); + usbd *lst; + + lst = usb_get_device_list_sysfs(); + if (lst == NULL) + lst = usb_get_device_list_lsusb(); - /* TODO: other methods */ + return lst; } diff --git a/hardinfo/util.c b/hardinfo/util.c index 964617d4..c8c99224 100644 --- a/hardinfo/util.c +++ b/hardinfo/util.c @@ -1237,6 +1237,22 @@ h_sysfs_read_int(const gchar *endpoint, const gchar *entry) return return_value; } +gint +h_sysfs_read_hex(const gchar *endpoint, const gchar *entry) +{ + gchar *tmp, *buffer; + gint return_value = 0; + + tmp = g_build_filename(endpoint, entry, NULL); + if (g_file_get_contents(tmp, &buffer, NULL, NULL)) + return_value = (gint) strtoll(buffer, NULL, 16); + + g_free(tmp); + g_free(buffer); + + return return_value; +} + gchar * h_sysfs_read_string(const gchar *endpoint, const gchar *entry) { diff --git a/includes/hardinfo.h b/includes/hardinfo.h index 8888565f..6b9e33af 100644 --- a/includes/hardinfo.h +++ b/includes/hardinfo.h @@ -163,6 +163,7 @@ gchar *module_call_method_param(gchar * method, gchar * parameter); /* Sysfs stuff */ gfloat h_sysfs_read_float(const gchar *endpoint, const gchar *entry); gint h_sysfs_read_int(const gchar *endpoint, const gchar *entry); +gint h_sysfs_read_hex(const gchar *endpoint, const gchar *entry); gchar *h_sysfs_read_string(const gchar *endpoint, const gchar *entry); #define SCAN_START() static gboolean scanned = FALSE; if (reload) scanned = FALSE; if (scanned) return; diff --git a/includes/usb_util.h b/includes/usb_util.h index 5f7ba47c..2d1398ba 100644 --- a/includes/usb_util.h +++ b/includes/usb_util.h @@ -25,6 +25,8 @@ typedef struct usbd { int vendor_id, product_id; char *vendor; char *product; + char *manufacturer; + char *device; int dev_class; int dev_subclass; @@ -36,7 +38,7 @@ typedef struct usbd { int max_curr_ma; - int speed_mbs; /* TODO: */ + int speed_mbs; gboolean user_scan; /* not scanned as root */ struct usbi *if_list; @@ -53,6 +55,7 @@ typedef struct usbi { char *if_class_str; char *if_subclass_str; char *if_protocol_str; + char *driver; struct usbi *next; } usbi; @@ -61,7 +64,7 @@ usbd *usb_get_device_list(); int usbd_list_count(usbd *); void usbd_list_free(usbd *); -usbd *usb_get_device(int bus, int dev); +usbd *usb_get_device(int bus, int dev, const gchar* sysfspath); void usbd_free(usbd *); #endif diff --git a/modules/devices/usb.c b/modules/devices/usb.c index a2fda57a..4e262fa2 100644 --- a/modules/devices/usb.c +++ b/modules/devices/usb.c @@ -98,19 +98,22 @@ static const char* get_usbdev_icon(const usbd *u) { } static void _usb_dev(const usbd *u) { - gchar *name, *key, *v_str, *label, *str; + gchar *name, *key, *v_str, *label, *str, *speed; gchar *product, *vendor, *dev_class_str, *dev_subclass_str; /* don't free */ - gchar *if_class_str, *if_subclass_str, *if_protocol_str; /* don't free */ + gchar *manufacturer, *device, *if_driver, *if_class_str; /* don't free */ + gchar *if_subclass_str, *if_protocol_str; /* don't free */ gchar *interfaces = strdup(""); usbi *i; const char* icon; vendor = UNKIFNULL_AC(u->vendor); product = UNKIFNULL_AC(u->product); + manufacturer = UNKIFNULL_AC(u->manufacturer); + device = UNKIFNULL_AC(u->device); dev_class_str = UNKIFNULL_AC(u->dev_class_str); dev_subclass_str = UNKIFNULL_AC(u->dev_subclass_str); - name = g_strdup_printf("%s %s", vendor, product); + name = g_strdup_printf("%s %s", u->vendor? vendor: manufacturer, u->product? product: device); key = g_strdup_printf("USB%03d:%03d:%03d", u->bus, u->dev, 0); label = g_strdup_printf("%03d:%03d", u->bus, u->dev); icon = get_usbdev_icon(u); @@ -126,26 +129,39 @@ static void _usb_dev(const usbd *u) { if_class_str = UNKIFNULL_AC(i->if_class_str); if_subclass_str = UNKIFNULL_AC(i->if_subclass_str); if_protocol_str = UNKIFNULL_AC(i->if_protocol_str); + if_driver = UNKIFNULL_AC(i->driver); interfaces = h_strdup_cprintf("[%s %d]\n" /* Class */ "%s=[%d] %s\n" /* Sub-class */ "%s=[%d] %s\n" - /* Protocol */ "%s=[%d] %s\n", + /* Protocol */ "%s=[%d] %s\n" + /* Driver */ "%s=%s\n", interfaces, _("Interface"), i->if_number, _("Class"), i->if_class, if_class_str, _("Sub-class"), i->if_subclass, if_subclass_str, - _("Protocol"), i->if_protocol, if_protocol_str + _("Protocol"), i->if_protocol, if_protocol_str, + _("Driver"), if_driver ); i = i->next; } } + if (u->speed_mbs > 0){ + speed = g_strdup_printf("%d %s", u->speed_mbs, _("Mb/s")); + } + else{ + speed = g_strdup(_("Unknown")); + } + str = g_strdup_printf("[%s]\n" /* Product */ "%s=[0x%04x] %s\n" - /* Manufacturer */ "%s=[0x%04x] %s\n" + /* Vendor */ "%s=[0x%04x] %s\n" + /* Device */ "%s=%s\n" + /* Manufacturer */ "%s=%s\n" /* Max Current */ "%s=%d %s\n" /* USB Version */ "%s=%s\n" + /* Speed */ "%s=%s\n" /* Class */ "%s=[%d] %s\n" /* Sub-class */ "%s=[%d] %s\n" /* Dev Version */ "%s=%s\n" @@ -156,8 +172,11 @@ static void _usb_dev(const usbd *u) { _("Device Information"), _("Product"), u->product_id, product, _("Vendor"), u->vendor_id, v_str, + _("Device"), device, + _("Manufacturer"), manufacturer, _("Max Current"), u->max_curr_ma, _("mA"), _("USB Version"), u->usb_version, + _("Speed"), speed, _("Class"), u->dev_class, dev_class_str, _("Sub-class"), u->dev_subclass, dev_subclass_str, _("Device Version"), u->device_version, @@ -169,6 +188,7 @@ static void _usb_dev(const usbd *u) { moreinfo_add_with_prefix("DEV", key, str); /* str now owned by morinfo */ + g_free(speed); g_free(v_str); g_free(name); g_free(key); |