diff options
| -rw-r--r-- | CMakeLists.txt | 2 | ||||
| -rw-r--r-- | hardinfo/usb_util.c | 185 | ||||
| -rw-r--r-- | includes/usb_util.h | 35 | ||||
| -rw-r--r-- | modules/devices.c | 7 | ||||
| -rw-r--r-- | modules/devices/usb.c | 92 | 
5 files changed, 313 insertions, 8 deletions
| diff --git a/CMakeLists.txt b/CMakeLists.txt index 8038aead..bc480146 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -214,6 +214,7 @@ endif()  if (HARDINFO_GTK3)  add_executable(hardinfo +	hardinfo/usb_util.c  	hardinfo/binreloc.c  	hardinfo/expr.c          hardinfo/hardinfo.c @@ -242,6 +243,7 @@ target_link_libraries(hardinfo  )  else()  add_executable(hardinfo +	hardinfo/usb_util.c  	hardinfo/binreloc.c  	hardinfo/expr.c          hardinfo/hardinfo.c diff --git a/hardinfo/usb_util.c b/hardinfo/usb_util.c new file mode 100644 index 00000000..e1db2777 --- /dev/null +++ b/hardinfo/usb_util.c @@ -0,0 +1,185 @@ +/* + *    HardInfo - Displays System Information + *    Copyright (C) 2003-2017 Leandro A. F. Pereira <leandro@hardinfo.org> + *    This file + *    Copyright (C) 2017 Burt P. <pburt0@gmail.com> + * + *    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" + +usbd *usbd_new() { +    usbd *s = malloc(sizeof(usbd)); +    if (s) { +        memset(s, 0, sizeof(usbd)); +    } +    return s; +} + +void usbd_free(usbd *s) { +    if (s) { +        free(s->vendor); +        free(s->product); +        free(s->usb_version); +        free(s->device_version); +        free(s->dev_class_str); +        free(s->dev_subclass_str); +        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 */ +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; +} + +int usbd_list_count(usbd *s) { +    return usbd_list_append(s, NULL); +} + +char *_lsusb_lv(char *line, const char *prefix) { +    if ( g_str_has_prefix(line, prefix) ) { +        line += strlen(prefix) + 1; +        return g_strstrip(line); +    } else +        return NULL; +} + +int 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); + +    s->bus = bus; +    s->dev = dev; + +    spawned = g_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 = 1; +        } +        p = out; +        while(next_nl = strchr(p, '\n')) { +            strend(p, '\n'); +            g_strstrip(p); +            if (l = _lsusb_lv(p, "idVendor")) { +                s->vendor_id = strtol(l, NULL, 0); +                if (t = strchr(l, ' ')) +                    s->vendor = strdup(t + 1); +            } else if (l = _lsusb_lv(p, "idProduct")) { +                s->product_id = strtol(l, NULL, 0); +                if (t = strchr(l, ' ')) +                    s->product = strdup(t + 1); +            } else if (l = _lsusb_lv(p, "MaxPower")) { +                s->max_curr_ma = atoi(l); +            } else if (l = _lsusb_lv(p, "bcdUSB")) { +                s->usb_version = strdup(l); +            } else if (l = _lsusb_lv(p, "bcdDevice")) { +                s->device_version = strdup(l); +            } else if (l = _lsusb_lv(p, "bDeviceClass")) { +                s->dev_class = atoi(l); +                if (t = strchr(l, ' ')) +                    s->dev_class_str = strdup(t + 1); +            } else if (l = _lsusb_lv(p, "bDeviceSubClass")) { +                s->dev_subclass = atoi(l); +                if (t = strchr(l, ' ')) +                    s->dev_subclass_str = strdup(t + 1); +            } +            /* TODO: speed_mbs +             * WISHLIST: interfaces, drivers */ +            p = next_nl + 1; +        } +        g_free(out); +        g_free(err); +        return 1; +    } +    return 0; +} + +usbd *usb_get_device(int bus, int dev) { +    usbd *s = usbd_new(); +    int ok = 0; +    if (s) { +        /* try lsusb */ +        ok = usb_get_device_lsusb(bus, dev, s); + +        /* TODO: other methods */ + +        if (!ok) { +            usbd_free(s); +            s = NULL; +        } +    } +    return s; +} + +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 = g_spawn_command_line_sync("lsusb", +            &out, &err, NULL, NULL); +    if (spawned) { +        p = out; +        while(next_nl = strchr(p, '\n')) { +            strend(p, '\n'); +            if (ec = sscanf(p, "Bus %d Device %d: ID %x:%x", &bus, &dev, &vend, &prod) ) { +                nd = usb_get_device(bus, dev); +                if (head == NULL) { +                    head = nd; +                } else { +                    usbd_list_append(head, nd); +                } +            } +            p = next_nl + 1; +        } +        g_free(out); +        g_free(err); +    } +    return head; +} + +usbd *usb_get_device_list() { +    /* try lsusb */ +    return usb_get_device_list_lsusb(); + +    /* TODO: other methods */ +} diff --git a/includes/usb_util.h b/includes/usb_util.h new file mode 100644 index 00000000..5d7f55bf --- /dev/null +++ b/includes/usb_util.h @@ -0,0 +1,35 @@ +#ifndef __USB_UTIL_H__ +#define __USB_UTIL_H__ + +/* this is a linked list */ +typedef struct usbd { +    int bus, dev; +    int vendor_id, product_id; +    char *vendor; +    char *product; + +    int dev_class; +    int dev_subclass; +    char *dev_class_str; +    char *dev_subclass_str; + +    char *usb_version; +    char *device_version; /* bcdDevice */ + +    int max_curr_ma; + +    int speed_mbs; /* TODO: */ + +    int user_scan; /* not scanned as root */ + +    struct usbd *next; +} usbd; + +usbd *usb_get_device_list(); +int usbd_list_count(usbd *); +void usbd_list_free(usbd *); + +usbd *usb_get_device(int bus, int dev); +void usbd_free(usbd *); + +#endif diff --git a/modules/devices.c b/modules/devices.c index 152b6831..5e757c15 100644 --- a/modules/devices.c +++ b/modules/devices.c @@ -635,9 +635,10 @@ gchar *callback_input()  gchar *callback_usb()  {      return g_strdup_printf("%s" -			   "[$ShellParam$]\n" -			   "ViewType=1\n" -			   "ReloadInterval=5000\n", usb_list); +               "[$ShellParam$]\n" +               "ViewType=1\n" +               "ReloadInterval=5000\n", usb_list); +  }  ModuleEntry *hi_module_get_entries(void) diff --git a/modules/devices/usb.c b/modules/devices/usb.c index 9366c7ce..27b3c13e 100644 --- a/modules/devices/usb.c +++ b/modules/devices/usb.c @@ -24,6 +24,7 @@  #include "hardinfo.h"  #include "devices.h" +#include "usb_util.h"  gchar *usb_list = NULL; @@ -426,11 +427,92 @@ gboolean __scan_usb_lsusb(void)      return usb_device_number > 0;  } -void __scan_usb(void) -{ -    if (!__scan_usb_procfs()) { -        if (!__scan_usb_sysfs()) { -             __scan_usb_lsusb(); +#define UNKIFNULL_AC(f) (f != NULL) ? f : _("(Unknown)"); + +void _usb_dev(const usbd *u) { +    gchar *name, *key, *v_str, *str; +    gchar *product, *vendor, *dev_class_str, *dev_subclass_str; /* don't free */ + +    vendor = UNKIFNULL_AC(u->vendor); +    product = UNKIFNULL_AC(u->product); +    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); +    key = g_strdup_printf("USB%03d:%03d:%03d", u->bus, u->dev, 0); + +    usb_list = h_strdup_cprintf("$%s$%03d:%03d=%s\n", usb_list, key, u->bus, u->dev, name); + +    const gchar *v_url = vendor_get_url(vendor); +    const gchar *v_name = vendor_get_name(vendor); +    if (v_url != NULL) { +        v_str = g_strdup_printf("%s (%s)", v_name, v_url); +    } else { +        v_str = g_strdup_printf("%s", vendor ); +    } + +    str = g_strdup_printf("[%s]\n" +             /* Product */      "%s=[0x%04x] %s\n" +             /* Manufacturer */ "%s=[0x%04x] %s\n" +             /* Max Current */  "%s=%d %s\n" +             /* USB Version */ "%s=%s\n" +             /* Class */       "%s=[%d] %s\n" +             /* Sub-class */   "%s=[%d] %s\n" +             /* Dev Version */ "%s=%s\n" +                            "[%s]\n" +             /* Bus */         "%s=%03d\n" +             /* Device */      "%s=%03d\n", +                _("Device Information"), +                _("Product"), u->product_id, product, +                _("Vendor"), u->vendor_id, v_str, +                _("Max Current"), u->max_curr_ma, _("mA"), +                _("USB Version"), u->usb_version, +                _("Class"), u->dev_class, dev_class_str, +                _("Sub-class"), u->dev_subclass, dev_subclass_str, +                _("Device Version"), u->device_version, +                _("Connection"), +                _("Bus"), u->bus, +                _("Device"), u->dev +                ); + +    moreinfo_add_with_prefix("DEV", key, str); /* str now owned by morinfo */ + +    g_free(v_str); +    g_free(name); +    g_free(key); +} + +gboolean __scan_usb_util(void) { +    usbd *list = usb_get_device_list(); +    usbd *curr = list; + +    int c = usbd_list_count(list); + +    if (c > 0) { +        if (usb_list) { +            moreinfo_del_with_prefix("DEV:USB"); +            g_free(usb_list); +        } +        usb_list = g_strdup_printf("[%s]\n", _("USB Devices")); + +        while(curr) { +            //printf("USB: Bus %03d Dev %03d Ven %04x Prod %04x %s %s\n", +            //    curr->bus, curr->dev, curr->vendor_id, curr->product_id, curr->vendor, curr->product); +            _usb_dev(curr); +            c++; +            curr=curr->next;          } + +        usbd_list_free(list); +        return TRUE;      } +    return FALSE; +} + +void __scan_usb(void) +{ +    if (!__scan_usb_util()) +        if (!__scan_usb_procfs()) +            if (!__scan_usb_sysfs()) +                __scan_usb_lsusb();  } | 
