diff options
Diffstat (limited to 'hardinfo/usb_util.c')
-rw-r--r-- | hardinfo/usb_util.c | 101 |
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; |