aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOndrej Čerman <ondrej.cerman@gmail.com>2019-07-20 23:07:56 +0200
committerLeandro A. F. Pereira <leandro@hardinfo.org>2019-07-29 19:44:04 -0700
commit5f620001a8f9017449d15b1a4aafdb9a61a44d4d (patch)
tree1900083d1506905f6dbe4af523f5351f656dc599
parent08a74ce10aedafd1a9e2f3c411e5eeea3658f71d (diff)
usb: added info from sysfs
-rw-r--r--hardinfo/usb_util.c148
-rw-r--r--hardinfo/util.c16
-rw-r--r--includes/hardinfo.h1
-rw-r--r--includes/usb_util.h7
-rw-r--r--modules/devices/usb.c32
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);