summaryrefslogtreecommitdiffstats
path: root/usb-db
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2009-02-26 01:59:45 +0100
committerLennart Poettering <lennart@poettering.net>2009-02-26 03:18:22 +0100
commit4cbf05876a0dd309e7e617bc2a14a463d083fefa (patch)
treed6a691f69f709c61dd944fef259a663c892fc329 /usb-db
parent460dfb712078121fff0a25ec7b91bbaf069a14c8 (diff)
add usb-db for reading usb vendor/product data from usb.ids
Diffstat (limited to 'usb-db')
-rw-r--r--usb-db/.gitignore1
-rw-r--r--usb-db/Makefile.am11
-rw-r--r--usb-db/usb-db.c222
3 files changed, 234 insertions, 0 deletions
diff --git a/usb-db/.gitignore b/usb-db/.gitignore
new file mode 100644
index 0000000..156b3fc
--- /dev/null
+++ b/usb-db/.gitignore
@@ -0,0 +1 @@
+usb-db
diff --git a/usb-db/Makefile.am b/usb-db/Makefile.am
new file mode 100644
index 0000000..46c5abb
--- /dev/null
+++ b/usb-db/Makefile.am
@@ -0,0 +1,11 @@
+include $(top_srcdir)/Makefile.am.inc
+
+udevhomedir = $(udev_prefix)/lib/udev
+udevhome_PROGRAMS = usb-db
+
+usb_db_SOURCES = usb-db.c
+usb_db_CPPFLAGS = $(AM_CPPFLAGS) $(LIBUDEV_CFLAGS) -DUSB_DATABASE=\"/usr/share/hwdata/usb.ids\"
+usb_db_LDADD = $(LIBUDEV_LIBS)
+
+#udevrulesdir = $(udev_prefix)/lib/udev/rules.d
+#dist_udevrules_DATA = 77-probe-modem-capabilities.rules
diff --git a/usb-db/usb-db.c b/usb-db/usb-db.c
new file mode 100644
index 0000000..58713ee
--- /dev/null
+++ b/usb-db/usb-db.c
@@ -0,0 +1,222 @@
+/*-*- linux-c -*-*/
+
+/*
+ * Copyright (C) 2009 Lennart Poettering <lennart@poettering.net>
+ *
+ * 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; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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:
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <inttypes.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+#include <libudev.h>
+
+static int get_vid_pid(
+ struct udev_device *usb,
+ uint16_t *vid,
+ uint16_t *pid) {
+
+ const char *t;
+
+ if ((t = udev_device_get_sysattr_value(usb, "idVendor"))) {
+ unsigned u;
+
+ if (sscanf(t, "%04x", &u) != 1 || u <= 0 || u > 0xFFFFU) {
+ fprintf(stderr, "Failed to parse idVendor on %s.\n", udev_device_get_syspath(usb));
+ return -1;
+ }
+
+ *vid = (uint16_t) u;
+ }
+
+ if ((t = udev_device_get_sysattr_value(usb, "idProduct"))) {
+ unsigned u;
+
+ if (sscanf(t, "%04x", &u) != 1 || u > 0xFFFFU) {
+ fprintf(stderr, "Failed to parse idProduct on %s.\n", udev_device_get_syspath(usb));
+ return -1;
+ }
+
+ *pid = (uint16_t) u;
+ }
+
+ return 0;
+}
+
+static void rstrip(char *n) {
+ size_t i;
+
+ for (i = strlen(n); i > 0 && isspace(n[i-1]); i--)
+ n[i-1] = 0;
+}
+
+#define HEXCHARS "0123456789abcdefABCDEF"
+#define WHITESPACE " \t\n\r"
+
+static int lookup_vid_pid(
+ uint16_t vid,
+ uint16_t pid,
+ char **vendor,
+ char **product) {
+
+ FILE *f;
+ int ret = -1;
+ int found_vendor = 0;
+ char *line = NULL;
+
+ *vendor = *product = NULL;
+
+ if (!(f = fopen(USB_DATABASE, "r"))) {
+ fprintf(stderr, "Failed to open database file "USB_DATABASE": %s", strerror(errno));
+ return -1;
+ }
+
+ for (;;) {
+ size_t n;
+
+ if (line) {
+ free(line);
+ line = NULL;
+ }
+
+ if (getline(&line, &n, f) < 0)
+ break;
+
+ rstrip(line);
+
+ if (line[0] == '#' || line[0] == 0)
+ continue;
+
+ if (strspn(line, HEXCHARS) == 4) {
+ unsigned u;
+
+ if (found_vendor)
+ break;
+
+ if (sscanf(line, "%04x", &u) == 1 && u == vid) {
+ char *t;
+
+ t = line+4;
+ t += strspn(t, WHITESPACE);
+
+ if (!(*vendor = strdup(t))) {
+ fprintf(stderr, "Out of memory.\n");
+ goto finish;
+ }
+
+ found_vendor = 1;
+ }
+
+ continue;
+ }
+
+ if (found_vendor && line[0] == '\t' && strspn(line+1, HEXCHARS) == 4) {
+ unsigned u;
+
+ if (sscanf(line+1, "%04x", &u) == 1 && u == pid) {
+ char *t;
+
+ t = line+5;
+ t += strspn(t, WHITESPACE);
+
+ if (!(*product = strdup(t))) {
+ fprintf(stderr, "Out of memory.\n");
+ goto finish;
+ }
+
+ break;
+ }
+ }
+ }
+
+ ret = 0;
+
+finish:
+ free(line);
+
+ fclose(f);
+
+ if (ret < 0) {
+ free(*product);
+ free(*vendor);
+
+ *product = *vendor = NULL;
+ }
+
+ return ret;
+}
+
+int main(int argc, char*argv[]) {
+
+ struct udev *udev = NULL;
+ int ret = 1;
+ char *sp;
+ struct udev_device *dev = NULL, *usb = NULL;
+ uint16_t vid = 0, pid = 0;
+ char *vendor = NULL, *product = NULL;
+
+ if (argc < 2) {
+ fprintf(stderr, "Need to pass sysfs path.\n");
+ goto finish;
+ }
+
+ if (!(udev = udev_new()))
+ goto finish;
+
+ if (asprintf(&sp, "%s/%s", udev_get_sys_path(udev), argv[1]) < 0) {
+ fprintf(stderr, "Failed to allocate sysfs path.\n");
+ goto finish;
+ }
+
+ dev = udev_device_new_from_syspath(udev, sp);
+ free(sp);
+
+ if (!dev) {
+ fprintf(stderr, "Failed to access %s.\n", argv[1]);
+ goto finish;
+ }
+
+ if (!(usb = udev_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_device"))) {
+ fprintf(stderr, "Failed to find usb_device.\n");
+ goto finish;
+ }
+
+ if (get_vid_pid(usb, &vid, &pid) < 0)
+ goto finish;
+
+ if (lookup_vid_pid(vid, pid, &vendor, &product) < 0)
+ goto finish;
+
+ if (vendor)
+ printf("ID_VENDOR_FROM_DATABASE=%s\n", vendor);
+
+ if (product)
+ printf("ID_MODEL_FROM_DATABASE=%s\n", product);
+
+ ret = 0;
+
+finish:
+ if (dev)
+ udev_device_unref(dev);
+
+ if (udev)
+ udev_unref(udev);
+
+ free(vendor);
+ free(product);
+
+ return ret;
+
+}