aboutsummaryrefslogtreecommitdiff
path: root/hardinfo/usb_util.c
diff options
context:
space:
mode:
authorBurt P <pburt0@gmail.com>2017-08-18 02:14:47 -0500
committerLeandro A. F. Pereira <leandro@hardinfo.org>2018-03-12 09:20:16 -0700
commitfdb1a05b6b5c84b67e3df107288f5046b763647e (patch)
tree57a18f80dac7cd11b5a571eef0d3a69ae096edcc /hardinfo/usb_util.c
parent9154a9ab51a62180298dbd71c3cdac3f07f7b2a1 (diff)
usb_util.c
A set of functions for getting information for a single USB device, or a list of all devices. The only implemented method is using `lsusb`, which is slow. A method using sysfs would be much better. The existing sysfs and procfs methods in devices/usb.c do not appear to work, so it would have to be something new. devices/usb.c modified to use usb_util, but all the old code is still there. Signed-off-by: Burt P <pburt0@gmail.com>
Diffstat (limited to 'hardinfo/usb_util.c')
-rw-r--r--hardinfo/usb_util.c185
1 files changed, 185 insertions, 0 deletions
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 */
+}