aboutsummaryrefslogtreecommitdiff
path: root/hardinfo/usb_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'hardinfo/usb_util.c')
-rw-r--r--hardinfo/usb_util.c101
1 files changed, 96 insertions, 5 deletions
diff --git a/hardinfo/usb_util.c b/hardinfo/usb_util.c
index cc839b9a..a758026f 100644
--- a/hardinfo/usb_util.c
+++ b/hardinfo/usb_util.c
@@ -21,9 +21,12 @@
#include "hardinfo.h"
#include "usb_util.h"
+#include "util_ids.h"
#define SYSFS_DIR_USB_DEVICES "/sys/bus/usb/devices"
+gchar *usb_ids_file = NULL;
+
usbi *usbi_new() {
return g_new0(usbi, 1);
}
@@ -61,8 +64,10 @@ void usbd_free(usbd *s) {
g_free(s->device);
g_free(s->usb_version);
g_free(s->device_version);
+ g_free(s->serial);
g_free(s->dev_class_str);
g_free(s->dev_subclass_str);
+ g_free(s->dev_protocol_str);
g_free(s);
}
}
@@ -203,6 +208,19 @@ static gboolean usb_get_device_lsusb(int bus, int dev, usbd *s) {
s->dev_subclass = atoi(l);
if (t = strchr(l, ' '))
s->dev_subclass_str = g_strdup(t + 1);
+ } else if (l = lsusb_line_value(p, "bDeviceProtocol")) {
+ s->dev_protocol = atoi(l);
+ if (t = strchr(l, ' '))
+ s->dev_protocol_str = g_strdup(t + 1);
+ } else if (l = lsusb_line_value(p, "iManufacturer")) {
+ if (t = strchr(l, ' '))
+ s->manufacturer = g_strdup(t + 1);
+ } else if (l = lsusb_line_value(p, "iProduct")) {
+ if (t = strchr(l, ' '))
+ s->device = g_strdup(t + 1);
+ } else if (l = lsusb_line_value(p, "iSerial")) {
+ if (t = strchr(l, ' '))
+ s->serial = g_strdup(t + 1);
// interface info
} else if (l = lsusb_line_value(p, "bInterfaceNumber")) {
@@ -254,6 +272,7 @@ static gboolean usb_get_device_lsusb(int bus, int dev, usbd *s) {
static gboolean usb_get_interface_sysfs(int conf, int number,
const char* devpath, usbi *intf){
gchar *ifpath, *drvpath, *tmp;
+ ids_query_result result = {};
ifpath = g_strdup_printf("%s:%d.%d", devpath, conf, number);
if (!g_file_test(ifpath, G_FILE_TEST_EXISTS)){
@@ -279,17 +298,53 @@ static gboolean usb_get_interface_sysfs(int conf, int number,
if (intf->if_label == NULL)
intf->if_label = h_sysfs_read_string(ifpath, "interface");
+ if (intf->if_class_str == NULL && intf->if_subclass_str == NULL
+ && intf->if_protocol_str == NULL) {
+ tmp = g_strdup_printf("C %02x/%02x/%02x", intf->if_class,
+ intf->if_subclass, intf->if_protocol);
+ scan_ids_file(usb_ids_file, tmp, &result, -1);
+ if (result.results[0])
+ intf->if_class_str = g_strdup(result.results[0]);
+ if (result.results[1])
+ intf->if_subclass_str = g_strdup(result.results[1]);
+ if (result.results[2])
+ intf->if_protocol_str = g_strdup(result.results[2]);
+ g_free(tmp);
+ }
+
g_free(ifpath);
return TRUE;
}
+void find_usb_ids_file() {
+ if (usb_ids_file) return;
+ char *file_search_order[] = {
+ g_build_filename(g_get_user_config_dir(), "hardinfo", "usb.ids", NULL),
+ g_build_filename(params.path_data, "usb.ids", NULL),
+ NULL
+ };
+ int n;
+ for(n = 0; file_search_order[n]; n++) {
+ if (!usb_ids_file && !access(file_search_order[n], R_OK))
+ usb_ids_file = file_search_order[n];
+ else
+ g_free(file_search_order[n]);
+ }
+}
+
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;
+ int i, if_count = 0, conf = 0, ver;
+ ids_query_result result = {};
+ gchar *qpath;
+
if (sysfspath == NULL)
return FALSE;
+ if (!usb_ids_file)
+ find_usb_ids_file();
+
s->bus = bus;
s->dev = dev;
s->dev_class = h_sysfs_read_hex(sysfspath, "bDeviceClass");
@@ -300,13 +355,48 @@ static gboolean usb_get_device_sysfs(int bus, int dev, const char* sysfspath, us
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->dev_protocol = h_sysfs_read_hex(sysfspath, "bDeviceProtocol");
s->speed_mbs = h_sysfs_read_int(sysfspath, "speed");
+ if (s->product == NULL && s->vendor == NULL) {
+ qpath = g_strdup_printf("%04x/%04x", s->vendor_id, s->product_id);
+ scan_ids_file(usb_ids_file, qpath, &result, -1);
+ if (result.results[0])
+ s->vendor = g_strdup(result.results[0]);
+ if (result.results[1])
+ s->product = g_strdup(result.results[1]);
+ g_free(qpath);
+ }
+
+ if (s->dev_class_str == NULL && s->dev_subclass_str == NULL
+ && s->dev_protocol_str == NULL) {
+ qpath = g_strdup_printf("C %02x/%02x/%02x", s->dev_class,
+ s->dev_subclass, s->dev_protocol);
+ scan_ids_file(usb_ids_file, qpath, &result, -1);
+ if (result.results[0])
+ s->dev_class_str = g_strdup(result.results[0]);
+ if (result.results[1])
+ s->dev_subclass_str = g_strdup(result.results[1]);
+ if (result.results[2])
+ s->dev_protocol_str = g_strdup(result.results[2]);
+ g_free(qpath);
+ }
+
conf = h_sysfs_read_hex(sysfspath, "bConfigurationValue");
if (s->usb_version == NULL)
s->usb_version = h_sysfs_read_string(sysfspath, "version");
+ if (s->serial == NULL)
+ s->serial = h_sysfs_read_string(sysfspath, "serial");
+
+ if (s->device_version == NULL) {
+ ver = h_sysfs_read_int(sysfspath, "bcdDevice");
+ if (ver > 0){
+ s->device_version = g_strdup_printf("%d.%02d", ver/100, ver%100);
+ }
+ }
+
if (s->if_list == NULL){ // create interfaces list
if_count = h_sysfs_read_int(sysfspath, "bNumInterfaces");
for (i = 0; i <= if_count; i++){
@@ -337,11 +427,12 @@ 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);
/* try sysfs */
- ok |= usb_get_device_sysfs(bus, dev, sysfspath, s);
-
+ ok = usb_get_device_sysfs(bus, dev, sysfspath, s);
+ if (!ok) {
+ /* try lsusb */
+ ok = usb_get_device_lsusb(bus, dev, s);
+ }
if (!ok) {
usbd_free(s);
s = NULL;