aboutsummaryrefslogtreecommitdiff
path: root/hardinfo/usb_util.c
diff options
context:
space:
mode:
authorbigbear <ns@bigbear.dk>2024-02-08 19:52:52 +0100
committerbigbear <ns@bigbear.dk>2024-02-08 19:52:52 +0100
commit9a05f56e1bf36abab41d12f92f2c75266c44bd4a (patch)
treef9ac600d137939dd484732515363a2337bdc6535 /hardinfo/usb_util.c
parent0f5dea06fa62062c7e98b36945a63aae7835a80a (diff)
Clean - HARDINFO2 BASE
Diffstat (limited to 'hardinfo/usb_util.c')
-rw-r--r--hardinfo/usb_util.c553
1 files changed, 0 insertions, 553 deletions
diff --git a/hardinfo/usb_util.c b/hardinfo/usb_util.c
deleted file mode 100644
index 6f9f9ef8..00000000
--- a/hardinfo/usb_util.c
+++ /dev/null
@@ -1,553 +0,0 @@
-/*
- * HardInfo - Displays System Information
- * Copyright (C) 2003-2017 L. A. F. Pereira <l@tia.mat.br>
- * 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
- * the Free Software Foundation, version 2.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#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);
-}
-
-void usbi_free(usbi *s) {
- if (s) {
- g_free(s->if_label);
- 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);
- }
-}
-
-void usbi_list_free(usbi *s) {
- usbi *n;
- while(s != NULL) {
- n = s->next;
- usbi_free(s);
- s = n;
- }
-}
-
-usbd *usbd_new() {
- return g_new0(usbd, 1);
-}
-
-void usbd_free(usbd *s) {
- if (s) {
- usbi_list_free(s->if_list);
- vendor_list_free(s->vendors);
- 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->serial);
- g_free(s->dev_class_str);
- g_free(s->dev_subclass_str);
- g_free(s->dev_protocol_str);
- g_free(s);
- }
-}
-
-void usbd_list_free(usbd *s) {
- usbd *n;
- while(s != NULL) {
- n = s->next;
- usbd_free(s);
- s = n;
- }
-}
-
-/* returns number of items after append */
-static int usbd_list_append(usbd *l, usbd *n) {
- int c = 0;
- while(l != NULL) {
- c++;
- if (l->next == NULL) {
- if (n != NULL) {
- l->next = n;
- c++;
- }
- break;
- }
- l = l->next;
- }
- return c;
-}
-
-/* returns new top of the list */
-static usbd *usbd_list_append_sorted(usbd *l, usbd *n) {
- usbd *b = NULL;
- usbd *t = l;
-
- if (n == NULL)
- return l;
-
- while(l != NULL) {
- if ((n->bus > l->bus) ||
- ((n->bus == l->bus) && (n->dev >= l->dev))) {
- if (l->next == NULL) {
- l->next = n;
- break;
- }
- b = l;
- l = l->next;
- }
- else {
- if (b == NULL) {
- t = n;
- n->next = l;
- }
- else {
- b->next = n;
- n->next = l;
- }
- break;
- }
- }
-
- return t;
-}
-
-gboolean usbd_append_interface(usbd *dev, usbi *new_if){
- usbi *curr_if;
- if (dev->if_list == NULL){
- dev->if_list = new_if;
- return TRUE;
- }
-
- if (dev->if_list->if_number == new_if->if_number)
- return FALSE;
-
- curr_if = dev->if_list;
- while(curr_if->next != NULL) {
- curr_if = curr_if->next;
- if (curr_if->if_number == new_if->if_number)
- return FALSE;
- }
- curr_if->next = new_if;
- return TRUE;
-}
-
-int usbd_list_count(usbd *s) {
- return usbd_list_append(s, NULL);
-}
-
-static char *lsusb_line_value(char *line, const char *prefix) {
- if (g_str_has_prefix(line, prefix)) {
- line += strlen(prefix) + 1;
- return g_strstrip(line);
- } else
- return NULL;
-}
-
-static gboolean usb_get_device_lsusb(int bus, int dev, usbd *s) {
- gboolean spawned;
- gchar *out, *err, *p, *l, *t, *next_nl;
- gchar *lsusb_cmd = g_strdup_printf("lsusb -s %d:%d -v", bus, dev);
- usbi *curr_if = NULL; // do not free
-
- s->bus = bus;
- s->dev = dev;
-
- spawned = hardinfo_spawn_command_line_sync(lsusb_cmd,
- &out, &err, NULL, NULL);
- g_free(lsusb_cmd);
- if (spawned) {
- if (strstr(err, "information will be missing")) {
- s->user_scan = TRUE;
- }
- p = out;
- while(next_nl = strchr(p, '\n')) {
- strend(p, '\n');
- g_strstrip(p);
-
- // device info
- if (l = lsusb_line_value(p, "idVendor")) {
- s->vendor_id = strtol(l, NULL, 0);
- if (t = strchr(l, ' '))
- s->vendor = g_strdup(t + 1);
- } else if (l = lsusb_line_value(p, "idProduct")) {
- s->product_id = strtol(l, NULL, 0);
- if (t = strchr(l, ' '))
- s->product = g_strdup(t + 1);
- } else if (l = lsusb_line_value(p, "MaxPower")) {
- s->max_curr_ma = atoi(l);
- } else if (l = lsusb_line_value(p, "bcdUSB")) {
- s->usb_version = g_strdup(l);
- } else if (l = lsusb_line_value(p, "bcdDevice")) {
- s->device_version = g_strdup(l);
- } else if (l = lsusb_line_value(p, "bDeviceClass")) {
- s->dev_class = atoi(l);
- if (t = strchr(l, ' '))
- s->dev_class_str = g_strdup(t + 1);
- } else if (l = lsusb_line_value(p, "bDeviceSubClass")) {
- 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")) {
- curr_if = usbi_new();
- curr_if->if_number = atoi(l);
-
- // This may parse same interface multiple times when there
- // are multiple Configuration descriptors per device
- // As a workaround usbd_append_interface appends interface
- // with same if_number only once
- if (!usbd_append_interface(s, curr_if)){
- usbi_free(curr_if);
- curr_if = NULL;
- }
- } else if (l = lsusb_line_value(p, "bInterfaceClass")) {
- if (curr_if != NULL){
- curr_if->if_class = atoi(l);
- if (t = strchr(l, ' '))
- curr_if->if_class_str = g_strdup(t + 1);
- }
- } else if (l = lsusb_line_value(p, "bInterfaceSubClass")) {
- if (curr_if != NULL){
- curr_if->if_subclass = atoi(l);
- if (t = strchr(l, ' '))
- curr_if->if_subclass_str = g_strdup(t + 1);
- }
- } else if (l = lsusb_line_value(p, "bInterfaceProtocol")) {
- if (curr_if != NULL){
- curr_if->if_protocol = atoi(l);
- if (t = strchr(l, ' '))
- curr_if->if_protocol_str = g_strdup(t + 1);
- }
- } else if (l = lsusb_line_value(p, "iInterface")) {
- if (curr_if != NULL){
- if (t = strchr(l, ' '))
- curr_if->if_label = g_strdup(t + 1);
- }
- }
-
- p = next_nl + 1;
- }
- g_free(out);
- g_free(err);
- return TRUE;
- }
- return FALSE;
-}
-
-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)){
- 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");
-
- 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;
-}
-
-static 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]);
- }
-}
-
-void usb_lookup_ids_vendor_product_str(gint vendor_id, gint product_id,
- gchar **vendor_str, gchar **product_str) {
- ids_query_result result = {};
- gchar *qpath;
-
- if (!usb_ids_file)
- find_usb_ids_file();
- if (!usb_ids_file)
- return;
-
- qpath = g_strdup_printf("%04x/%04x", vendor_id, product_id);
- scan_ids_file(usb_ids_file, qpath, &result, -1);
- if (result.results[0])
- *vendor_str = g_strdup(result.results[0]);
- if (result.results[1])
- *product_str = g_strdup(result.results[1]);
- g_free(qpath);
-}
-
-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, 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");
- 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->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++){
- intf = usbi_new();
- ok = usb_get_interface_sysfs(conf, i, sysfspath, intf);
- if (ok){
- if (!usbd_append_interface(s, intf)){
- usbi_free(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 sysfs */
- 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;
- }
- }
- return s;
-}
-
-static usbd *usb_get_device_list_lsusb() {
- gboolean spawned;
- gchar *out, *err, *p, *next_nl;
- usbd *head = NULL, *nd;
- int bus, dev, vend, prod, ec;
-
- spawned = hardinfo_spawn_command_line_sync("lsusb",
- &out, &err, NULL, NULL);
- if (spawned) {
- p = out;
- while(next_nl = strchr(p, '\n')) {
- 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, NULL);
- if (head == NULL) {
- head = nd;
- } else {
- usbd_list_append(head, nd);
- }
- }
- p = next_nl + 1;
- }
- g_free(out);
- g_free(err);
- }
- 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 {
- head = usbd_list_append_sorted(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() {
- usbd *lst, *l;
-
- lst = usb_get_device_list_sysfs();
- if (lst == NULL)
- lst = usb_get_device_list_lsusb();
-
- l = lst;
- while(l) {
- l->vendors = vendor_list_remove_duplicates_deep(vendors_match(l->vendor, l->manufacturer, NULL));
- l = l->next;
- }
-
- return lst;
-}