4 patches were added to revert the libudev changes as the libudev wrapper in 
OpenWrt is not good enough.

Signed-off-by: Rosen Penev <ros...@gmail.com>
---
 package/utils/usbutils/Makefile                    |   8 +-
 .../patches/010-remove-python-usbids.patch         |  68 ++
 .../patches/020-revert-removal-of-usb.ids.patch    | 897 +++++++++++++++++++++
 .../usbutils/patches/030-revert-port-to-hwdb.patch | 549 +++++++++++++
 .../patches/040-add-back-update-usbids.patch       |  77 ++
 5 files changed, 1596 insertions(+), 3 deletions(-)
 create mode 100644 
package/utils/usbutils/patches/010-remove-python-usbids.patch
 create mode 100644 
package/utils/usbutils/patches/020-revert-removal-of-usb.ids.patch
 create mode 100644 package/utils/usbutils/patches/030-revert-port-to-hwdb.patch
 create mode 100644 
package/utils/usbutils/patches/040-add-back-update-usbids.patch

diff --git a/package/utils/usbutils/Makefile b/package/utils/usbutils/Makefile
index 7f798954ae..3fbc4e0b50 100644
--- a/package/utils/usbutils/Makefile
+++ b/package/utils/usbutils/Makefile
@@ -8,15 +8,17 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=usbutils
-PKG_VERSION:=007
-PKG_RELEASE:=7
+PKG_VERSION:=009
+PKG_RELEASE:=1
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
 PKG_SOURCE_URL:=@KERNEL/linux/utils/usb/usbutils
-PKG_HASH:=7593a01724bbc0fd9fe48e62bc721ceb61c76654f1d7b231b3c65f6dfbbaefa4
+PKG_HASH:=8bbff0e54cb5f65a52be4feb9162fc0b022a97eb841b44784f7a89a9ea567160
 PKG_LICENSE:=GPL-2.0
 PKG_LICENSE_FILES:=COPYING
 
+PKG_FIXUP:=autoreconf
+
 PKG_BUILD_PARALLEL:=1
 PKG_INSTALL:=1
 
diff --git a/package/utils/usbutils/patches/010-remove-python-usbids.patch 
b/package/utils/usbutils/patches/010-remove-python-usbids.patch
new file mode 100644
index 0000000000..19e3cc1dd3
--- /dev/null
+++ b/package/utils/usbutils/patches/010-remove-python-usbids.patch
@@ -0,0 +1,68 @@
+From a1c2fd7bbd5b2e26f8f752fd3386a953b3b1ec37 Mon Sep 17 00:00:00 2001
+From: Rosen Penev <ros...@gmail.com>
+Date: Fri, 9 Mar 2018 10:31:09 -0800
+Subject: [PATCH] Revert "substitute usb.id location in lsusb Python script"
+
+This reverts commit 199756013624bfa497865eb498bf7331eb07ef56.
+---
+ Makefile.am             | 7 +------
+ lsusb.py.in => lsusb.py | 4 ++--
+ 3 files changed, 3 insertions(+), 9 deletions(-)
+ rename lsusb.py.in => lsusb.py (99%)
+ mode change 100644 => 100755
+
+diff --git a/Makefile.am b/Makefile.am
+index b18ff69..67def60 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -39,13 +39,9 @@ EXTRA_DIST = \
+       lsusb.8.in \
+       usb-devices.1.in \
+       usb-devices \
+-      lsusb.py.in \
++      lsusb.py \
+       usbutils.pc.in
+ 
+-lsusb.py: $(srcdir)/lsusb.py.in
+-      sed 's|VERSION|$(VERSION)|g;s|@usbids@|$(datadir)/usb.ids|g' $< >$@
+-      chmod 755 $@
+-
+ lsusb.8: $(srcdir)/lsusb.8.in
+       sed 's|VERSION|$(VERSION)|g;s|@usbids@|$(datadir)/usb.ids|g' $< >$@
+ 
+@@ -59,7 +55,6 @@ usbutils.pc: $(srcdir)/usbutils.pc.in
+       sed 's|@usbids@|$(datadir)/usb.ids|g;s|@VERSION[@]|$(VERSION)|g' $< >$@
+ 
+ DISTCLEANFILES = \
+-      lsusb.py \
+       lsusb.8 \
+       usb-devices.1 \
+       usbutils.pc
+diff --git a/lsusb.py.in b/lsusb.py
+old mode 100644
+new mode 100755
+similarity index 99%
+rename from lsusb.py.in
+rename to lsusb.py
+index db2e1e0..aa410fc
+--- a/lsusb.py.in
++++ b/lsusb.py
+@@ -1,5 +1,5 @@
+ #!/usr/bin/env python
+-# lsusb-VERSION.py
++# lsusb.py
+ # Displays your USB devices in reasonable form.
+ # (c) Kurt Garloff <garl...@suse.de>, 2/2009, GPL v2 or v3.
+ # (c) Kurt Garloff <k...@garloff.de>, 9/2013, GPL v2 or v3.
+@@ -18,7 +18,7 @@ warnsort = False
+ showeps = False
+ 
+ prefix = "/sys/bus/usb/devices/"
+-usbids = "@usbids@"
++usbids = "/usr/share/usb.ids"
+ 
+ esc = chr(27)
+ norm = esc + "[0;0m"
+-- 
+2.16.2
+
diff --git a/package/utils/usbutils/patches/020-revert-removal-of-usb.ids.patch 
b/package/utils/usbutils/patches/020-revert-removal-of-usb.ids.patch
new file mode 100644
index 0000000000..bdf9f9f7d4
--- /dev/null
+++ b/package/utils/usbutils/patches/020-revert-removal-of-usb.ids.patch
@@ -0,0 +1,897 @@
+From 2bfca703b324e21aee2fabbe4f998aa663f03a15 Mon Sep 17 00:00:00 2001
+From: Rosen Penev <ros...@gmail.com>
+Date: Fri, 9 Mar 2018 10:31:24 -0800
+Subject: [PATCH] Revert "drop dependency on usb.ids"
+
+This reverts commit 5d7ea40bc94cbf3069a25beba3146de13bcdcf02.
+
+commit 5d7ea40bc94cbf3069a25beba3146de13bcdcf02
+Author: Tom Gundersen <t...@jklm.no>
+Date:   Wed Sep 4 14:47:08 2013 +0200
+
+    drop dependency on usb.ids
+    
+    Also remove usb.ids from the repository. [Note that these were probably
+    never used by distributions regarless, as most distros ship the usb.ids
+    directly from upstream.]
+    
+    Hardcode the usb-spec information that used to be in usb.ids,
+    but which was not moved to hwdb.
+    
+    Increase the size of tha hash table from 16 to 512, though using a
+    hash at all is probably overkill at this point.
+    
+    Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>
+---
+ Makefile.am  |    27 +-
+ configure.ac |    12 +
+ lsusb.c      |    13 +-
+ names.c      |   600 +-
+ names.h      |     2 +-
+ 5 files changed, 18559 insertions(+), 1775 deletions(-)
+ delete mode 100644 usb-spec.h
+ create mode 100644 usb.ids
+
+diff --git a/Makefile.am b/Makefile.am
+index 67def60..31afb20 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -20,7 +20,6 @@ lsusb_SOURCES = \
+       lsusb-t.c \
+       list.h \
+       names.c names.h \
+-      usb-spec.h \
+       usbmisc.c usbmisc.h
+ 
+ lsusb_CPPFLAGS = \
+@@ -31,17 +30,41 @@ lsusb_LDADD = \
+       $(LIBUSB_LIBS) \
+       $(UDEV_LIBS)
+ 
++if HAVE_ZLIB
++lsusb_CPPFLAGS += -DHAVE_LIBZ
++lsusb_LDADD += -lz
++endif
++
+ man_MANS = \
+       lsusb.8 \
+       usb-devices.1
+ 
+ EXTRA_DIST = \
++      usb.ids \
++      update-usbids.sh.in \
+       lsusb.8.in \
+       usb-devices.1.in \
+       usb-devices \
+       lsusb.py \
+       usbutils.pc.in
+ 
++if INSTALL_USBIDS
++data_DATA += usb.ids
++
++if HAVE_ZLIB
++data_DATA += usb.ids.gz
++endif
++
++sbin_SCRIPTS += update-usbids.sh
++
++usb.ids.gz: $(srcdir)/usb.ids
++      gzip -c -9 $< > $@
++
++update-usbids.sh: $(srcdir)/update-usbids.sh.in
++      sed 's|@usbids@|$(datadir)/usb.ids|g' $< >$@
++      chmod 755 $@
++endif
++
+ lsusb.8: $(srcdir)/lsusb.8.in
+       sed 's|VERSION|$(VERSION)|g;s|@usbids@|$(datadir)/usb.ids|g' $< >$@
+ 
+@@ -55,8 +78,10 @@ usbutils.pc: $(srcdir)/usbutils.pc.in
+       sed 's|@usbids@|$(datadir)/usb.ids|g;s|@VERSION[@]|$(VERSION)|g' $< >$@
+ 
+ DISTCLEANFILES = \
++      usb.ids.gz \
+       lsusb.8 \
+       usb-devices.1 \
++      update-usbids.sh \
+       usbutils.pc
+ 
+ distclean-local:
+diff --git a/configure.ac b/configure.ac
+index a62748c..89d62f9 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -12,6 +12,18 @@ AC_SYS_LARGEFILE
+ AC_CHECK_HEADERS([byteswap.h])
+ AC_CHECK_FUNCS([nl_langinfo iconv])
+ 
++AC_ARG_ENABLE(zlib,
++      AS_HELP_STRING(--disable-zlib,disable support for zlib))
++
++HAVE_ZLIB=no
++AS_IF([test "x$enable_zlib" != "xno"],
++      [AC_CHECK_LIB(z, inflateEnd, HAVE_ZLIB=yes)])
++AM_CONDITIONAL(HAVE_ZLIB, [test "$HAVE_ZLIB" = "yes"])
++
++AC_ARG_ENABLE(usbids,
++      AS_HELP_STRING(--disable-usbids, [disable installing usb.ids 
@<:@default=install@:>@]))
++AM_CONDITIONAL([INSTALL_USBIDS], [test "x$enable_usbids" != "xno"])
++
+ PKG_CHECK_MODULES(LIBUSB, libusb-1.0 >= 1.0.9)
+ 
+ PKG_CHECK_MODULES(UDEV, libudev >= 196)
+diff --git a/lsusb.c b/lsusb.c
+index f611f2e..969997c 100644
+--- a/lsusb.c
++++ b/lsusb.c
+@@ -4340,9 +4340,16 @@ int main(int argc, char *argv[])
+ 
+ 
+       /* by default, print names as well as numbers */
+-      if (names_init() < 0)
+-              fprintf(stderr, "unable to initialize usb spec");
+-
++      err = names_init(DATADIR "/usb.ids");
++#ifdef HAVE_LIBZ
++      if (err != 0)
++              err = names_init(DATADIR "/usb.ids.gz");
++#endif
++      if (err != 0)
++              fprintf(stderr, "%s: cannot open \"%s\", %s\n",
++                              argv[0],
++                              DATADIR "/usb.ids",
++                              strerror(err));
+       status = 0;
+ 
+       if (treemode) {
+diff --git a/names.c b/names.c
+index a151484..f543240 100644
+--- a/names.c
++++ b/names.c
+@@ -37,13 +37,47 @@
+ 
+ #include <libudev.h>
+ 
+-#include "usb-spec.h"
++#ifdef HAVE_LIBZ
++#include <zlib.h>
++#define       usb_file                        gzFile
++#define       usb_fopen(path, mode)           gzopen(path, mode)
++#define       usb_fgets(s, size, stream)      gzgets(stream, s, size)
++#define       usb_close(f)                    gzclose(f)
++#else
++#define       usb_file                        FILE *
++#define       usb_fopen(path, mode)           fopen(path, mode)
++#define       usb_fgets(s, size, stream)      fgets(s, size, stream)
++#define       usb_close(f)                    fclose(f)
++#endif
++
+ #include "names.h"
+ 
+ 
++/* ---------------------------------------------------------------------- */
++
++struct audioterminal {
++      struct audioterminal *next;
++      u_int16_t termt;
++      char name[1];
++};
++
++struct videoterminal {
++      struct videoterminal *next;
++      u_int16_t termt;
++      char name[1];
++};
++
++struct genericstrtable {
++      struct genericstrtable *next;
++      unsigned int num;
++      char name[1];
++};
++
++/* ---------------------------------------------------------------------- */
++
+ #define HASH1  0x10
+ #define HASH2  0x02
+-#define HASHSZ 512
++#define HASHSZ 16
+ 
+ static unsigned int hashnum(unsigned int num)
+ {
+@@ -59,16 +93,16 @@ static unsigned int hashnum(unsigned int num)
+ 
+ static struct udev *udev = NULL;
+ static struct udev_hwdb *hwdb = NULL;
+-static struct audioterminal *audioterminals_hash[HASHSZ] = { NULL, };
+-static struct videoterminal *videoterminals_hash[HASHSZ] = { NULL, };
+-static struct genericstrtable *hiddescriptors_hash[HASHSZ] = { NULL, };
+-static struct genericstrtable *reports_hash[HASHSZ] = { NULL, };
+-static struct genericstrtable *huts_hash[HASHSZ] = { NULL, };
+-static struct genericstrtable *biass_hash[HASHSZ] = { NULL, };
+-static struct genericstrtable *physdess_hash[HASHSZ] = { NULL, };
+-static struct genericstrtable *hutus_hash[HASHSZ] = { NULL, };
+-static struct genericstrtable *langids_hash[HASHSZ] = { NULL, };
+-static struct genericstrtable *countrycodes_hash[HASHSZ] = { NULL, };
++static struct audioterminal *audioterminals[HASHSZ] = { NULL, };
++static struct videoterminal *videoterminals[HASHSZ] = { NULL, };
++static struct genericstrtable *hiddescriptors[HASHSZ] = { NULL, };
++static struct genericstrtable *reports[HASHSZ] = { NULL, };
++static struct genericstrtable *huts[HASHSZ] = { NULL, };
++static struct genericstrtable *biass[HASHSZ] = { NULL, };
++static struct genericstrtable *physdess[HASHSZ] = { NULL, };
++static struct genericstrtable *hutus[HASHSZ] = { NULL, };
++static struct genericstrtable *langids[HASHSZ] = { NULL, };
++static struct genericstrtable *countrycodes[HASHSZ] = { NULL, };
+ 
+ /* ---------------------------------------------------------------------- */
+ 
+@@ -85,42 +119,42 @@ static const char *names_genericstrtable(struct 
genericstrtable *t[HASHSZ],
+ 
+ const char *names_hid(u_int8_t hidd)
+ {
+-      return names_genericstrtable(hiddescriptors_hash, hidd);
++      return names_genericstrtable(hiddescriptors, hidd);
+ }
+ 
+ const char *names_reporttag(u_int8_t rt)
+ {
+-      return names_genericstrtable(reports_hash, rt);
++      return names_genericstrtable(reports, rt);
+ }
+ 
+ const char *names_huts(unsigned int data)
+ {
+-      return names_genericstrtable(huts_hash, data);
++      return names_genericstrtable(huts, data);
+ }
+ 
+ const char *names_hutus(unsigned int data)
+ {
+-      return names_genericstrtable(hutus_hash, data);
++      return names_genericstrtable(hutus, data);
+ }
+ 
+ const char *names_langid(u_int16_t langid)
+ {
+-      return names_genericstrtable(langids_hash, langid);
++      return names_genericstrtable(langids, langid);
+ }
+ 
+ const char *names_physdes(u_int8_t ph)
+ {
+-      return names_genericstrtable(physdess_hash, ph);
++      return names_genericstrtable(physdess, ph);
+ }
+ 
+ const char *names_bias(u_int8_t b)
+ {
+-      return names_genericstrtable(biass_hash, b);
++      return names_genericstrtable(biass, b);
+ }
+ 
+ const char *names_countrycode(unsigned int countrycode)
+ {
+-      return names_genericstrtable(countrycodes_hash, countrycode);
++      return names_genericstrtable(countrycodes, countrycode);
+ }
+ 
+ static const char *hwdb_get(const char *modalias, const char *key)
+@@ -178,7 +212,7 @@ const char *names_audioterminal(u_int16_t termt)
+ {
+       struct audioterminal *at;
+ 
+-      at = audioterminals_hash[hashnum(termt)];
++      at = audioterminals[hashnum(termt)];
+       for (; at; at = at->next)
+               if (at->termt == termt)
+                       return at->name;
+@@ -189,7 +223,7 @@ const char *names_videoterminal(u_int16_t termt)
+ {
+       struct videoterminal *vt;
+ 
+-      vt = videoterminals_hash[hashnum(termt)];
++      vt = videoterminals[hashnum(termt)];
+       for (; vt; vt = vt->next)
+               if (vt->termt == termt)
+                       return vt->name;
+@@ -248,189 +282,446 @@ int get_subclass_string(char *buf, size_t size, 
u_int8_t cls, u_int8_t subcls)
+ 
+ /* ---------------------------------------------------------------------- */
+ 
+-static int hash_audioterminal(struct audioterminal *at)
++static int new_audioterminal(const char *name, u_int16_t termt)
+ {
+-      struct audioterminal *at_old;
+-      unsigned int h = hashnum(at->termt);
++      struct audioterminal *at;
++      unsigned int h = hashnum(termt);
+ 
+-      for (at_old = audioterminals_hash[h]; at_old; at_old = at_old->next)
+-              if (at_old->termt == at->termt)
++      at = audioterminals[h];
++      for (; at; at = at->next)
++              if (at->termt == termt)
+                       return -1;
+-      at->next = audioterminals_hash[h];
+-      audioterminals_hash[h] = at;
++      at = malloc(sizeof(struct audioterminal) + strlen(name));
++      if (!at)
++              return -1;
++      strcpy(at->name, name);
++      at->termt = termt;
++      at->next = audioterminals[h];
++      audioterminals[h] = at;
+       return 0;
+ }
+ 
+-static int hash_audioterminals(void)
+-{
+-      int r = 0, i, k;
+-
+-      for (i = 0; audioterminals[i].name; i++)
+-      {
+-              k = hash_audioterminal(&audioterminals[i]);
+-              if (k < 0)
+-                      r = k;
+-      }
+-
+-      return r;
+-}
+-
+-static int hash_videoterminal(struct videoterminal *vt)
++static int new_videoterminal(const char *name, u_int16_t termt)
+ {
+-      struct videoterminal *vt_old;
+-      unsigned int h = hashnum(vt->termt);
++      struct videoterminal *vt;
++      unsigned int h = hashnum(termt);
+ 
+-      for (vt_old = videoterminals_hash[h]; vt_old; vt_old = vt_old->next)
+-              if (vt_old->termt == vt->termt)
++      vt = videoterminals[h];
++      for (; vt; vt = vt->next)
++              if (vt->termt == termt)
+                       return -1;
+-      vt->next = videoterminals_hash[h];
+-      videoterminals_hash[h] = vt;
++      vt = malloc(sizeof(struct videoterminal) + strlen(name));
++      if (!vt)
++              return -1;
++      strcpy(vt->name, name);
++      vt->termt = termt;
++      vt->next = videoterminals[h];
++      videoterminals[h] = vt;
+       return 0;
+ }
+ 
+-static int hash_videoterminals(void)
+-{
+-      int r = 0, i, k;
+-
+-      for (i = 0; videoterminals[i].name; i++)
+-      {
+-              k = hash_videoterminal(&videoterminals[i]);
+-              if (k < 0)
+-                      r = k;
+-      }
+-
+-      return r;
+-}
+-
+-static int hash_genericstrtable(struct genericstrtable *t[HASHSZ],
+-                             struct genericstrtable *g)
++static int new_genericstrtable(struct genericstrtable *t[HASHSZ],
++                             const char *name, unsigned int idx)
+ {
+-      struct genericstrtable *g_old;
+-      unsigned int h = hashnum(g->num);
++      struct genericstrtable *g;
++      unsigned int h = hashnum(idx);
+ 
+-      for (g_old = t[h]; g_old; g_old = g_old->next)
+-              if (g_old->num == g->num)
++      for (g = t[h]; g; g = g->next)
++              if (g->num == idx)
+                       return -1;
++      g = malloc(sizeof(struct genericstrtable) + strlen(name));
++      if (!g)
++              return -1;
++      strcpy(g->name, name);
++      g->num = idx;
+       g->next = t[h];
+       t[h] = g;
+       return 0;
+ }
+ 
+-#define HASH_EACH(array, hash) \
+-      for (i = 0; array[i].name; i++) { \
+-              k = hash_genericstrtable(hash, &array[i]); \
+-              if (k < 0) { \
+-                      r = k; \
+-              }\
+-      }
+-
+-static int hash_tables(void)
++static int new_hid(const char *name, u_int8_t hidd)
+ {
+-      int r = 0, k, i;
+-
+-      k = hash_audioterminals();
+-      if (k < 0)
+-              r = k;
+-
+-      k = hash_videoterminals();
+-      if (k < 0)
+-              r = k;
+-
+-      HASH_EACH(hiddescriptors, hiddescriptors_hash);
+-
+-      HASH_EACH(reports, reports_hash);
+-
+-      HASH_EACH(huts, huts_hash);
++      return new_genericstrtable(hiddescriptors, name, hidd);
++}
+ 
+-      HASH_EACH(hutus, hutus_hash);
++static int new_reporttag(const char *name, u_int8_t rt)
++{
++      return new_genericstrtable(reports, name, rt);
++}
+ 
+-      HASH_EACH(langids, langids_hash);
++static int new_huts(const char *name, unsigned int data)
++{
++      return new_genericstrtable(huts, name, data);
++}
+ 
+-      HASH_EACH(physdess, physdess_hash);
++static int new_hutus(const char *name, unsigned int data)
++{
++      return new_genericstrtable(hutus, name, data);
++}
+ 
+-      HASH_EACH(biass, biass_hash);
++static int new_langid(const char *name, u_int16_t langid)
++{
++      return new_genericstrtable(langids, name, langid);
++}
+ 
+-      HASH_EACH(countrycodes, countrycodes_hash);
++static int new_physdes(const char *name, u_int8_t ph)
++{
++      return new_genericstrtable(physdess, name, ph);
++}
++static int new_bias(const char *name, u_int8_t b)
++{
++      return new_genericstrtable(biass, name, b);
++}
+ 
+-      return r;
++static int new_countrycode(const char *name, unsigned int countrycode)
++{
++      return new_genericstrtable(countrycodes, name, countrycode);
+ }
+ 
+ /* ---------------------------------------------------------------------- */
+ 
+-/*
+-static void print_tables(void)
++static void free_audioterminal(void)
+ {
++      struct audioterminal *cur, *tmp;
+       int i;
+-      struct audioterminal *at;
+-      struct videoterminal *vt;
+-      struct genericstrtable *li;
+-      struct genericstrtable *hu;
+-
+-
+-      printf("--------------------------------------------\n");
+-      printf("\t\t Audio Terminals\n");
+-      printf("--------------------------------------------\n");
+ 
+       for (i = 0; i < HASHSZ; i++) {
+-              printf("hash: %d\n", i);
+-              at = audioterminals_hash[i];
+-              for (; at; at = at->next)
+-                      printf("\tentry: %s\n", at->name);
++              cur = audioterminals[i];
++              audioterminals[i] = NULL;
++              while (cur) {
++                      tmp = cur;
++                      cur = cur->next;
++                      free(tmp);
++              }
+       }
++      return;
++}
+ 
+-      printf("--------------------------------------------\n");
+-      printf("\t\t Video Terminals\n");
+-      printf("--------------------------------------------\n");
++static void free_videoterminal(void)
++{
++      struct videoterminal *cur, *tmp;
++      int i;
+ 
+       for (i = 0; i < HASHSZ; i++) {
+-              printf("hash: %d\n", i);
+-              vt = videoterminals_hash[i];
+-              for (; vt; vt = vt->next)
+-                      printf("\tentry: %s\n", vt->name);
++              cur = videoterminals[i];
++              videoterminals[i] = NULL;
++              while (cur) {
++                      tmp = cur;
++                      cur = cur->next;
++                      free(tmp);
++              }
+       }
++}
+ 
+-      printf("--------------------------------------------\n");
+-      printf("\t\t Languages\n");
+-      printf("--------------------------------------------\n");
++static void _free_genericstrtable(struct genericstrtable *t[HASHSZ])
++{
++      struct genericstrtable *cur, *tmp;
++      int i;
+ 
+       for (i = 0; i < HASHSZ; i++) {
+-              li = langids_hash[i];
+-              if (li)
+-                      printf("hash: %d\n", i);
+-              for (; li; li = li->next)
+-                      printf("\tid: %x, entry: %s\n", li->num, li->name);
++              cur = t[i];
++              t[i] = NULL;
++              while (cur) {
++                      tmp = cur;
++                      cur = cur->next;
++                      free(tmp);
++              }
+       }
++}
+ 
+-      printf("--------------------------------------------\n");
+-      printf("\t\t Conutry Codes\n");
+-      printf("--------------------------------------------\n");
++static void free_genericstrtable(void)
++{
++      _free_genericstrtable(hiddescriptors);
++      _free_genericstrtable(reports);
++      _free_genericstrtable(huts);
++      _free_genericstrtable(biass);
++      _free_genericstrtable(physdess);
++      _free_genericstrtable(hutus);
++      _free_genericstrtable(langids);
++      _free_genericstrtable(countrycodes);
++}
+ 
+-      for (i = 0; i < HASHSZ; i++) {
+-              hu = countrycodes_hash[i];
+-              if (hu)
+-                      printf("hash: %d\n", i);
+-              for (; hu; hu = hu->next)
+-                      printf("\tid: %x, entry: %s\n", hu->num, hu->name);
+-      }
++#define DBG(x)
+ 
+-      printf("--------------------------------------------\n");
++static void parse(usb_file f)
++{
++      char buf[512], *cp;
++      unsigned int linectr = 0;
++      int lastvendor = -1;
++      int lastclass = -1;
++      int lastsubclass = -1;
++      int lasthut = -1;
++      int lastlang = -1;
++      unsigned int u;
++
++      while (usb_fgets(buf, sizeof(buf), f)) {
++              linectr++;
++              /* remove line ends */
++              cp = strchr(buf, 13);
++              if (cp)
++                      *cp = 0;
++              cp = strchr(buf, 10);
++              if (cp)
++                      *cp = 0;
++              if (buf[0] == '#' || !buf[0])
++                      continue;
++              cp = buf;
++              if (buf[0] == 'P' && buf[1] == 'H' && buf[2] == 'Y' && buf[3] 
== 'S' && buf[4] == 'D' &&
++                  buf[5] == 'E' && buf[6] == 'S' && /*isspace(buf[7])*/ 
buf[7] == ' ') {
++                      cp = buf + 8;
++                      while (isspace(*cp))
++                              cp++;
++                      if (!isxdigit(*cp)) {
++                              fprintf(stderr, "Invalid Physdes type at line 
%u\n", linectr);
++                              continue;
++                      }
++                      u = strtoul(cp, &cp, 16);
++                      while (isspace(*cp))
++                              cp++;
++                      if (!*cp) {
++                              fprintf(stderr, "Invalid Physdes type at line 
%u\n", linectr);
++                              continue;
++                      }
++                      if (new_physdes(cp, u))
++                              fprintf(stderr, "Duplicate Physdes  type spec 
at line %u terminal type %04x %s\n", linectr, u, cp);
++                      DBG(printf("line %5u physdes type %02x %s\n", linectr, 
u, cp));
++                      continue;
++
++              }
++              if (buf[0] == 'P' && buf[1] == 'H' && buf[2] == 'Y' && 
/*isspace(buf[3])*/ buf[3] == ' ') {
++                      cp = buf + 4;
++                      while (isspace(*cp))
++                              cp++;
++                      if (!isxdigit(*cp)) {
++                              fprintf(stderr, "Invalid PHY type at line 
%u\n", linectr);
++                              continue;
++                      }
++                      u = strtoul(cp, &cp, 16);
++                      while (isspace(*cp))
++                              cp++;
++                      if (!*cp) {
++                              fprintf(stderr, "Invalid PHY type at line 
%u\n", linectr);
++                              continue;
++                      }
++                      if (new_physdes(cp, u))
++                              fprintf(stderr, "Duplicate PHY type spec at 
line %u terminal type %04x %s\n", linectr, u, cp);
++                      DBG(printf("line %5u PHY type %02x %s\n", linectr, u, 
cp));
++                      continue;
++
++              }
++              if (buf[0] == 'B' && buf[1] == 'I' && buf[2] == 'A' && buf[3] 
== 'S' && /*isspace(buf[4])*/ buf[4] == ' ') {
++                      cp = buf + 5;
++                      while (isspace(*cp))
++                              cp++;
++                      if (!isxdigit(*cp)) {
++                              fprintf(stderr, "Invalid BIAS type at line 
%u\n", linectr);
++                              continue;
++                      }
++                      u = strtoul(cp, &cp, 16);
++                      while (isspace(*cp))
++                              cp++;
++                      if (!*cp) {
++                              fprintf(stderr, "Invalid BIAS type at line 
%u\n", linectr);
++                              continue;
++                      }
++                      if (new_bias(cp, u))
++                              fprintf(stderr, "Duplicate BIAS  type spec at 
line %u terminal type %04x %s\n", linectr, u, cp);
++                      DBG(printf("line %5u BIAS type %02x %s\n", linectr, u, 
cp));
++                      continue;
++
++              }
++              if (buf[0] == 'L' && /*isspace(buf[1])*/ buf[1] == ' ') {
++                      cp =  buf+2;
++                      while (isspace(*cp))
++                              cp++;
++                      if (!isxdigit(*cp)) {
++                              fprintf(stderr, "Invalid LANGID spec at line 
%u\n", linectr);
++                              continue;
++                      }
++                      u = strtoul(cp, &cp, 16);
++                      while (isspace(*cp))
++                              cp++;
++                      if (!*cp) {
++                              fprintf(stderr, "Invalid LANGID spec at line 
%u\n", linectr);
++                              continue;
++                      }
++                      if (new_langid(cp, u))
++                              fprintf(stderr, "Duplicate LANGID spec at line 
%u language-id %04x %s\n", linectr, u, cp);
++                      DBG(printf("line %5u LANGID %02x %s\n", linectr, u, 
cp));
++                      lasthut = lastclass = lastvendor = lastsubclass = -1;
++                      lastlang = u;
++                      continue;
++              }
++              if (buf[0] == 'A' && buf[1] == 'T' && isspace(buf[2])) {
++                      /* audio terminal type spec */
++                      cp = buf+3;
++                      while (isspace(*cp))
++                              cp++;
++                      if (!isxdigit(*cp)) {
++                              fprintf(stderr, "Invalid audio terminal type at 
line %u\n", linectr);
++                              continue;
++                      }
++                      u = strtoul(cp, &cp, 16);
++                      while (isspace(*cp))
++                              cp++;
++                      if (!*cp) {
++                              fprintf(stderr, "Invalid audio terminal type at 
line %u\n", linectr);
++                              continue;
++                      }
++                      if (new_audioterminal(cp, u))
++                              fprintf(stderr, "Duplicate audio terminal type 
spec at line %u terminal type %04x %s\n", linectr, u, cp);
++                      DBG(printf("line %5u audio terminal type %02x %s\n", 
linectr, u, cp));
++                      continue;
++              }
++              if (buf[0] == 'V' && buf[1] == 'T' && isspace(buf[2])) {
++                      /* video terminal type spec */
++                      cp = buf+3;
++                      while (isspace(*cp))
++                              cp++;
++                      if (!isxdigit(*cp)) {
++                              fprintf(stderr, "Invalid video terminal type at 
line %u\n", linectr);
++                              continue;
++                      }
++                      u = strtoul(cp, &cp, 16);
++                      while (isspace(*cp))
++                              cp++;
++                      if (!*cp) {
++                              fprintf(stderr, "Invalid video terminal type at 
line %u\n", linectr);
++                              continue;
++                      }
++                      if (new_videoterminal(cp, u))
++                              fprintf(stderr, "Duplicate video terminal type 
spec at line %u terminal type %04x %s\n", linectr, u, cp);
++                      DBG(printf("line %5u video terminal type %02x %s\n", 
linectr, u, cp));
++                      continue;
++              }
++              if (buf[0] == 'H' && buf[1] == 'C' && buf[2] == 'C' && 
isspace(buf[3])) {
++                      /* HID Descriptor bCountryCode */
++                      cp =  buf+3;
++                      while (isspace(*cp))
++                              cp++;
++                      if (!isxdigit(*cp)) {
++                              fprintf(stderr, "Invalid HID country code at 
line %u\n", linectr);
++                              continue;
++                      }
++                      u = strtoul(cp, &cp, 10);
++                      while (isspace(*cp))
++                              cp++;
++                      if (!*cp) {
++                              fprintf(stderr, "Invalid HID country code at 
line %u\n", linectr);
++                              continue;
++                      }
++                      if (new_countrycode(cp, u))
++                              fprintf(stderr, "Duplicate HID country code at 
line %u country %02u %s\n", linectr, u, cp);
++                      DBG(printf("line %5u keyboard country code %02u %s\n", 
linectr, u, cp));
++                      continue;
++              }
++              if (buf[0] == '\t' && isxdigit(buf[1])) {
++                      /* product or subclass spec */
++                      u = strtoul(buf+1, &cp, 16);
++                      while (isspace(*cp))
++                              cp++;
++                      if (!*cp) {
++                              fprintf(stderr, "Invalid product/subclass spec 
at line %u\n", linectr);
++                              continue;
++                      }
++                      if (lasthut != -1) {
++                              if (new_hutus(cp, (lasthut << 16)+u))
++                                      fprintf(stderr, "Duplicate HUT Usage 
Spec at line %u\n", linectr);
++                              continue;
++                      }
++                      if (lastlang != -1) {
++                              if (new_langid(cp, lastlang+(u<<10)))
++                                      fprintf(stderr, "Duplicate LANGID Usage 
Spec at line %u\n", linectr);
++                              continue;
++                      }
++                      fprintf(stderr, "Product/Subclass spec without prior 
Vendor/Class spec at line %u\n", linectr);
++                      continue;
++              }
++              if (buf[0] == 'H' && buf[1] == 'I' && buf[2] == 'D' && 
/*isspace(buf[3])*/ buf[3] == ' ') {
++                      cp = buf + 4;
++                      while (isspace(*cp))
++                              cp++;
++                      if (!isxdigit(*cp)) {
++                              fprintf(stderr, "Invalid HID type at line 
%u\n", linectr);
++                              continue;
++                      }
++                      u = strtoul(cp, &cp, 16);
++                      while (isspace(*cp))
++                              cp++;
++                      if (!*cp) {
++                              fprintf(stderr, "Invalid HID type at line 
%u\n", linectr);
++                              continue;
++                      }
++                      if (new_hid(cp, u))
++                              fprintf(stderr, "Duplicate HID type spec at 
line %u terminal type %04x %s\n", linectr, u, cp);
++                      DBG(printf("line %5u HID type %02x %s\n", linectr, u, 
cp));
++                      continue;
++
++              }
++              if (buf[0] == 'H' && buf[1] == 'U' && buf[2] == 'T' && 
/*isspace(buf[3])*/ buf[3] == ' ') {
++                      cp = buf + 4;
++                      while (isspace(*cp))
++                              cp++;
++                      if (!isxdigit(*cp)) {
++                              fprintf(stderr, "Invalid HUT type at line 
%u\n", linectr);
++                              continue;
++                      }
++                      u = strtoul(cp, &cp, 16);
++                      while (isspace(*cp))
++                              cp++;
++                      if (!*cp) {
++                              fprintf(stderr, "Invalid HUT type at line 
%u\n", linectr);
++                              continue;
++                      }
++                      if (new_huts(cp, u))
++                              fprintf(stderr, "Duplicate HUT type spec at 
line %u terminal type %04x %s\n", linectr, u, cp);
++                      lastlang = lastclass = lastvendor = lastsubclass = -1;
++                      lasthut = u;
++                      DBG(printf("line %5u HUT type %02x %s\n", linectr, u, 
cp));
++                      continue;
++
++              }
++              if (buf[0] == 'R' && buf[1] == ' ') {
++                      cp = buf + 2;
++                      while (isspace(*cp))
++                              cp++;
++                      if (!isxdigit(*cp)) {
++                              fprintf(stderr, "Invalid Report type at line 
%u\n", linectr);
++                              continue;
++                      }
++                      u = strtoul(cp, &cp, 16);
++                      while (isspace(*cp))
++                              cp++;
++                      if (!*cp) {
++                              fprintf(stderr, "Invalid Report type at line 
%u\n", linectr);
++                              continue;
++                      }
++                      if (new_reporttag(cp, u))
++                              fprintf(stderr, "Duplicate Report type spec at 
line %u terminal type %04x %s\n", linectr, u, cp);
++                      DBG(printf("line %5u Report type %02x %s\n", linectr, 
u, cp));
++                      continue;
++
++              }
++              fprintf(stderr, "Unknown line at line %u\n", linectr);
++      }
+ }
+-*/
+ 
+-int names_init(void)
++/* ---------------------------------------------------------------------- */
++
++int names_init(char *n)
+ {
+-      int r;
++      usb_file f;
++      int r = 0;
+ 
+-      udev = udev_new();
+-      if (!udev)
+-              r = -1;
+-      else {
+-              hwdb = udev_hwdb_new(udev);
+-              if (!hwdb)
+-                      r = -1;
+-      }
++      f = usb_fopen(n, "r");
++      if (!f)
++              r = errno;
+ 
+-      r = hash_tables();
++      parse(f);
++      usb_close(f);
++
++      udev = udev_new();
++      hwdb = udev_hwdb_new(udev);
+ 
+       return r;
+ }
+@@ -439,4 +730,7 @@ void names_exit(void)
+ {
+       hwdb = udev_hwdb_unref(hwdb);
+       udev = udev_unref(udev);
++      free_audioterminal();
++      free_videoterminal();
++      free_genericstrtable();
+ }
+diff --git a/names.h b/names.h
+index 32e887c..0eba890 100644
+--- a/names.h
++++ b/names.h
+@@ -49,7 +49,7 @@ extern int get_product_string(char *buf, size_t size, 
u_int16_t vid, u_int16_t p
+ extern int get_class_string(char *buf, size_t size, u_int8_t cls);
+ extern int get_subclass_string(char *buf, size_t size, u_int8_t cls, u_int8_t 
subcls);
+ 
+-extern int names_init(void);
++extern int names_init(char *n);
+ extern void names_exit(void);
+ 
+ /* ---------------------------------------------------------------------- */
+--- 
+-2.16.2
diff --git a/package/utils/usbutils/patches/030-revert-port-to-hwdb.patch 
b/package/utils/usbutils/patches/030-revert-port-to-hwdb.patch
new file mode 100644
index 0000000000..4c51373c23
--- /dev/null
+++ b/package/utils/usbutils/patches/030-revert-port-to-hwdb.patch
@@ -0,0 +1,549 @@
+From bfb94e20c8ca6eff73e8722165994a45da7cf47c Mon Sep 17 00:00:00 2001
+From: Rosen Penev <ros...@gmail.com>
+Date: Fri, 9 Mar 2018 10:33:52 -0800
+Subject: [PATCH] Revert "lsusb: port to hwdb"
+
+This reverts commit c6282a7a0e20fbb9c56837f055843635a43ba8b4.
+
+commit c6282a7a0e20fbb9c56837f055843635a43ba8b4
+Author: Tom Gundersen <t...@jklm.no>
+Date:   Wed Sep 4 14:47:07 2013 +0200
+
+    lsusb: port to hwdb
+    
+    Most of the information in usb.ids is now contained in udev's hwdb. Read 
the
+    information from the hwdb instead of usb.ids.
+    
+    This would allow distributions to no longer ship (most of) usb.ids by 
default,
+    but rather keep all the usb device information in the hwdb.
+    
+    This patch introduces a dependency on libusb >= 196.
+    
+    v2: drop support from reading data from usb.ids which is already in hwdb
+    
+    Cc: Greg Kroah-Hartman <gre...@linuxfoundation.org>
+    
+    Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>
+---
+ Makefile.am  |   5 +-
+ configure.ac |   2 -
+ names.c      | 361 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------
+ 3 files changed, 323 insertions(+), 45 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index 31afb20..60df9a0 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -23,12 +23,11 @@ lsusb_SOURCES = \
+       usbmisc.c usbmisc.h
+ 
+ lsusb_CPPFLAGS = \
+-      $(AM_CPPFLAGS) $(LIBUSB_CFLAGS) $(UDEV_CFLAGS) \
++      $(AM_CPPFLAGS) $(LIBUSB_CFLAGS) \
+       -DDATADIR=\"$(datadir)\"
+ 
+ lsusb_LDADD = \
+-      $(LIBUSB_LIBS) \
+-      $(UDEV_LIBS)
++      $(LIBUSB_LIBS)
+ 
+ if HAVE_ZLIB
+ lsusb_CPPFLAGS += -DHAVE_LIBZ
+diff --git a/configure.ac b/configure.ac
+index 89d62f9..4b86c9b 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -26,8 +26,6 @@ AM_CONDITIONAL([INSTALL_USBIDS], [test "x$enable_usbids" != 
"xno"])
+ 
+ PKG_CHECK_MODULES(LIBUSB, libusb-1.0 >= 1.0.0)
+ 
+-PKG_CHECK_MODULES(UDEV, libudev >= 196)
+-
+ AC_CONFIG_HEADERS([config.h])
+ AC_CONFIG_FILES([
+       Makefile
+diff --git a/names.c b/names.c
+index f543240..12cbd60 100644
+--- a/names.c
++++ b/names.c
+@@ -3,7 +3,6 @@
+  *      names.c  --  USB name database manipulation routines
+  *
+  *      Copyright (C) 1999, 2000  Thomas Sailer (sai...@ife.ee.ethz.ch)
+- *      Copyright (C) 2013  Tom Gundersen (t...@jklm.no)
+  *
+  *      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
+@@ -35,8 +34,6 @@
+ #include <stdio.h>
+ #include <ctype.h>
+ 
+-#include <libudev.h>
+-
+ #ifdef HAVE_LIBZ
+ #include <zlib.h>
+ #define       usb_file                        gzFile
+@@ -55,6 +52,36 @@
+ 
+ /* ---------------------------------------------------------------------- */
+ 
++struct vendor {
++      struct vendor *next;
++      u_int16_t vendorid;
++      char name[1];
++};
++
++struct product {
++      struct product *next;
++      u_int16_t vendorid, productid;
++      char name[1];
++};
++
++struct class {
++      struct class *next;
++      u_int8_t classid;
++      char name[1];
++};
++
++struct subclass {
++      struct subclass *next;
++      u_int8_t classid, subclassid;
++      char name[1];
++};
++
++struct protocol {
++      struct protocol *next;
++      u_int8_t classid, subclassid, protocolid;
++      char name[1];
++};
++
+ struct audioterminal {
+       struct audioterminal *next;
+       u_int16_t termt;
+@@ -91,8 +118,11 @@ static unsigned int hashnum(unsigned int num)
+ 
+ /* ---------------------------------------------------------------------- */
+ 
+-static struct udev *udev = NULL;
+-static struct udev_hwdb *hwdb = NULL;
++static struct vendor *vendors[HASHSZ] = { NULL, };
++static struct product *products[HASHSZ] = { NULL, };
++static struct class *classes[HASHSZ] = { NULL, };
++static struct subclass *subclasses[HASHSZ] = { NULL, };
++static struct protocol *protocols[HASHSZ] = { NULL, };
+ static struct audioterminal *audioterminals[HASHSZ] = { NULL, };
+ static struct videoterminal *videoterminals[HASHSZ] = { NULL, };
+ static struct genericstrtable *hiddescriptors[HASHSZ] = { NULL, };
+@@ -157,55 +187,59 @@ const char *names_countrycode(unsigned int countrycode)
+       return names_genericstrtable(countrycodes, countrycode);
+ }
+ 
+-static const char *hwdb_get(const char *modalias, const char *key)
+-{
+-      struct udev_list_entry *entry;
+-
+-      udev_list_entry_foreach(entry, 
udev_hwdb_get_properties_list_entry(hwdb, modalias, 0))
+-              if (strcmp(udev_list_entry_get_name(entry), key) == 0)
+-                      return udev_list_entry_get_value(entry);
+-
+-      return NULL;
+-}
+-
+ const char *names_vendor(u_int16_t vendorid)
+ {
+-      char modalias[64];
++      struct vendor *v;
+ 
+-      sprintf(modalias, "usb:v%04X*", vendorid);
+-      return hwdb_get(modalias, "ID_VENDOR_FROM_DATABASE");
++      v = vendors[hashnum(vendorid)];
++      for (; v; v = v->next)
++              if (v->vendorid == vendorid)
++                      return v->name;
++      return NULL;
+ }
+ 
+ const char *names_product(u_int16_t vendorid, u_int16_t productid)
+ {
+-      char modalias[64];
++      struct product *p;
+ 
+-      sprintf(modalias, "usb:v%04Xp%04X*", vendorid, productid);
+-      return hwdb_get(modalias, "ID_MODEL_FROM_DATABASE");
++      p = products[hashnum((vendorid << 16) | productid)];
++      for (; p; p = p->next)
++              if (p->vendorid == vendorid && p->productid == productid)
++                      return p->name;
++      return NULL;
+ }
+ 
+ const char *names_class(u_int8_t classid)
+ {
+-      char modalias[64];
++      struct class *c;
+ 
+-      sprintf(modalias, "usb:v*p*d*dc%02X*", classid);
+-      return hwdb_get(modalias, "ID_USB_CLASS_FROM_DATABASE");
++      c = classes[hashnum(classid)];
++      for (; c; c = c->next)
++              if (c->classid == classid)
++                      return c->name;
++      return NULL;
+ }
+ 
+ const char *names_subclass(u_int8_t classid, u_int8_t subclassid)
+ {
+-      char modalias[64];
++      struct subclass *s;
+ 
+-      sprintf(modalias, "usb:v*p*d*dc%02Xdsc%02X*", classid, subclassid);
+-      return hwdb_get(modalias, "ID_USB_SUBCLASS_FROM_DATABASE");
++      s = subclasses[hashnum((classid << 8) | subclassid)];
++      for (; s; s = s->next)
++              if (s->classid == classid && s->subclassid == subclassid)
++                      return s->name;
++      return NULL;
+ }
+ 
+ const char *names_protocol(u_int8_t classid, u_int8_t subclassid, u_int8_t 
protocolid)
+ {
+-      char modalias[64];
++      struct protocol *p;
+ 
+-      sprintf(modalias, "usb:v*p*d*dc%02Xdsc%02Xdp%02X*", classid, 
subclassid, protocolid);
+-      return hwdb_get(modalias, "ID_USB_PROTOCOL_FROM_DATABASE");
++      p = protocols[hashnum((classid << 16) | (subclassid << 8) | 
protocolid)];
++      for (; p; p = p->next)
++              if (p->classid == classid && p->subclassid == subclassid && 
p->protocolid == protocolid)
++                      return p->name;
++      return NULL;
+ }
+ 
+ const char *names_audioterminal(u_int16_t termt)
+@@ -282,6 +316,105 @@ int get_subclass_string(char *buf, size_t size, u_int8_t 
cls, u_int8_t subcls)
+ 
+ /* ---------------------------------------------------------------------- */
+ 
++static int new_vendor(const char *name, u_int16_t vendorid)
++{
++      struct vendor *v;
++      unsigned int h = hashnum(vendorid);
++
++      v = vendors[h];
++      for (; v; v = v->next)
++              if (v->vendorid == vendorid)
++                      return -1;
++      v = malloc(sizeof(struct vendor) + strlen(name));
++      if (!v)
++              return -1;
++      strcpy(v->name, name);
++      v->vendorid = vendorid;
++      v->next = vendors[h];
++      vendors[h] = v;
++      return 0;
++}
++
++static int new_product(const char *name, u_int16_t vendorid, u_int16_t 
productid)
++{
++      struct product *p;
++      unsigned int h = hashnum((vendorid << 16) | productid);
++
++      p = products[h];
++      for (; p; p = p->next)
++              if (p->vendorid == vendorid && p->productid == productid)
++                      return -1;
++      p = malloc(sizeof(struct product) + strlen(name));
++      if (!p)
++              return -1;
++      strcpy(p->name, name);
++      p->vendorid = vendorid;
++      p->productid = productid;
++      p->next = products[h];
++      products[h] = p;
++      return 0;
++}
++
++static int new_class(const char *name, u_int8_t classid)
++{
++      struct class *c;
++      unsigned int h = hashnum(classid);
++
++      c = classes[h];
++      for (; c; c = c->next)
++              if (c->classid == classid)
++                      return -1;
++      c = malloc(sizeof(struct class) + strlen(name));
++      if (!c)
++              return -1;
++      strcpy(c->name, name);
++      c->classid = classid;
++      c->next = classes[h];
++      classes[h] = c;
++      return 0;
++}
++
++static int new_subclass(const char *name, u_int8_t classid, u_int8_t 
subclassid)
++{
++      struct subclass *s;
++      unsigned int h = hashnum((classid << 8) | subclassid);
++
++      s = subclasses[h];
++      for (; s; s = s->next)
++              if (s->classid == classid && s->subclassid == subclassid)
++                      return -1;
++      s = malloc(sizeof(struct subclass) + strlen(name));
++      if (!s)
++              return -1;
++      strcpy(s->name, name);
++      s->classid = classid;
++      s->subclassid = subclassid;
++      s->next = subclasses[h];
++      subclasses[h] = s;
++      return 0;
++}
++
++static int new_protocol(const char *name, u_int8_t classid, u_int8_t 
subclassid, u_int8_t protocolid)
++{
++      struct protocol *p;
++      unsigned int h = hashnum((classid << 16) | (subclassid << 8) | 
protocolid);
++
++      p = protocols[h];
++      for (; p; p = p->next)
++              if (p->classid == classid && p->subclassid == subclassid && 
p->protocolid == protocolid)
++                      return -1;
++      p = malloc(sizeof(struct protocol) + strlen(name));
++      if (!p)
++              return -1;
++      strcpy(p->name, name);
++      p->classid = classid;
++      p->subclassid = subclassid;
++      p->protocolid = protocolid;
++      p->next = protocols[h];
++      protocols[h] = p;
++      return 0;
++}
++
+ static int new_audioterminal(const char *name, u_int16_t termt)
+ {
+       struct audioterminal *at;
+@@ -380,6 +513,86 @@ static int new_countrycode(const char *name, unsigned int 
countrycode)
+ 
+ /* ---------------------------------------------------------------------- */
+ 
++static void free_vendor(void)
++{
++      struct vendor *cur, *tmp;
++      int i;
++
++      for (i = 0; i < HASHSZ; i++) {
++              cur = vendors[i];
++              vendors[i] = NULL;
++              while (cur) {
++                      tmp = cur;
++                      cur = cur->next;
++                      free(tmp);
++              }
++      }
++}
++
++static void free_product(void)
++{
++      struct product *cur, *tmp;
++      int i;
++
++      for (i = 0; i < HASHSZ; i++) {
++              cur = products[i];
++              products[i] = NULL;
++              while (cur) {
++                      tmp = cur;
++                      cur = cur->next;
++                      free(tmp);
++              }
++      }
++}
++
++static void free_class(void)
++{
++      struct class *cur, *tmp;
++      int i;
++
++      for (i = 0; i < HASHSZ; i++) {
++              cur = classes[i];
++              classes[i] = NULL;
++              while (cur) {
++                      tmp = cur;
++                      cur = cur->next;
++                      free(tmp);
++              }
++      }
++}
++
++static void free_subclass(void)
++{
++      struct subclass *cur, *tmp;
++      int i;
++
++      for (i = 0; i < HASHSZ; i++) {
++              cur = subclasses[i];
++              subclasses[i] = NULL;
++              while (cur) {
++                      tmp = cur;
++                      cur = cur->next;
++                      free(tmp);
++              }
++      }
++}
++
++static void free_protocol(void)
++{
++      struct protocol *cur, *tmp;
++      int i;
++
++      for (i = 0; i < HASHSZ; i++) {
++              cur = protocols[i];
++              protocols[i] = NULL;
++              while (cur) {
++                      tmp = cur;
++                      cur = cur->next;
++                      free(tmp);
++              }
++      }
++}
++
+ static void free_audioterminal(void)
+ {
+       struct audioterminal *cur, *tmp;
+@@ -552,6 +765,29 @@ static void parse(usb_file f)
+                       lastlang = u;
+                       continue;
+               }
++              if (buf[0] == 'C' && /*isspace(buf[1])*/ buf[1] == ' ') {
++                      /* class spec */
++                      cp = buf+2;
++                      while (isspace(*cp))
++                              cp++;
++                      if (!isxdigit(*cp)) {
++                              fprintf(stderr, "Invalid class spec at line 
%u\n", linectr);
++                              continue;
++                      }
++                      u = strtoul(cp, &cp, 16);
++                      while (isspace(*cp))
++                              cp++;
++                      if (!*cp) {
++                              fprintf(stderr, "Invalid class spec at line 
%u\n", linectr);
++                              continue;
++                      }
++                      if (new_class(cp, u))
++                              fprintf(stderr, "Duplicate class spec at line 
%u class %04x %s\n", linectr, u, cp);
++                      DBG(printf("line %5u class %02x %s\n", linectr, u, cp));
++                      lasthut = lastlang = lastvendor = lastsubclass = -1;
++                      lastclass = u;
++                      continue;
++              }
+               if (buf[0] == 'A' && buf[1] == 'T' && isspace(buf[2])) {
+                       /* audio terminal type spec */
+                       cp = buf+3;
+@@ -615,6 +851,22 @@ static void parse(usb_file f)
+                       DBG(printf("line %5u keyboard country code %02u %s\n", 
linectr, u, cp));
+                       continue;
+               }
++              if (isxdigit(*cp)) {
++                      /* vendor */
++                      u = strtoul(cp, &cp, 16);
++                      while (isspace(*cp))
++                              cp++;
++                      if (!*cp) {
++                              fprintf(stderr, "Invalid vendor spec at line 
%u\n", linectr);
++                              continue;
++                      }
++                      if (new_vendor(cp, u))
++                              fprintf(stderr, "Duplicate vendor spec at line 
%u vendor %04x %s\n", linectr, u, cp);
++                      DBG(printf("line %5u vendor %04x %s\n", linectr, u, 
cp));
++                      lastvendor = u;
++                      lasthut = lastlang = lastclass = lastsubclass = -1;
++                      continue;
++              }
+               if (buf[0] == '\t' && isxdigit(buf[1])) {
+                       /* product or subclass spec */
+                       u = strtoul(buf+1, &cp, 16);
+@@ -624,6 +876,19 @@ static void parse(usb_file f)
+                               fprintf(stderr, "Invalid product/subclass spec 
at line %u\n", linectr);
+                               continue;
+                       }
++                      if (lastvendor != -1) {
++                              if (new_product(cp, lastvendor, u))
++                                      fprintf(stderr, "Duplicate product spec 
at line %u product %04x:%04x %s\n", linectr, lastvendor, u, cp);
++                              DBG(printf("line %5u product %04x:%04x %s\n", 
linectr, lastvendor, u, cp));
++                              continue;
++                      }
++                      if (lastclass != -1) {
++                              if (new_subclass(cp, lastclass, u))
++                                      fprintf(stderr, "Duplicate subclass 
spec at line %u class %02x:%02x %s\n", linectr, lastclass, u, cp);
++                              DBG(printf("line %5u subclass %02x:%02x %s\n", 
linectr, lastclass, u, cp));
++                              lastsubclass = u;
++                              continue;
++                      }
+                       if (lasthut != -1) {
+                               if (new_hutus(cp, (lasthut << 16)+u))
+                                       fprintf(stderr, "Duplicate HUT Usage 
Spec at line %u\n", linectr);
+@@ -637,6 +902,24 @@ static void parse(usb_file f)
+                       fprintf(stderr, "Product/Subclass spec without prior 
Vendor/Class spec at line %u\n", linectr);
+                       continue;
+               }
++              if (buf[0] == '\t' && buf[1] == '\t' && isxdigit(buf[2])) {
++                      /* protocol spec */
++                      u = strtoul(buf+2, &cp, 16);
++                      while (isspace(*cp))
++                              cp++;
++                      if (!*cp) {
++                              fprintf(stderr, "Invalid protocol spec at line 
%u\n", linectr);
++                              continue;
++                      }
++                      if (lastclass != -1 && lastsubclass != -1) {
++                              if (new_protocol(cp, lastclass, lastsubclass, 
u))
++                                      fprintf(stderr, "Duplicate protocol 
spec at line %u class %02x:%02x:%02x %s\n", linectr, lastclass, lastsubclass, 
u, cp);
++                              DBG(printf("line %5u protocol %02x:%02x:%02x 
%s\n", linectr, lastclass, lastsubclass, u, cp));
++                              continue;
++                      }
++                      fprintf(stderr, "Protocol spec without prior Class and 
Subclass spec at line %u\n", linectr);
++                      continue;
++              }
+               if (buf[0] == 'H' && buf[1] == 'I' && buf[2] == 'D' && 
/*isspace(buf[3])*/ buf[3] == ' ') {
+                       cp = buf + 4;
+                       while (isspace(*cp))
+@@ -711,25 +994,23 @@ static void parse(usb_file f)
+ int names_init(char *n)
+ {
+       usb_file f;
+-      int r = 0;
+ 
+       f = usb_fopen(n, "r");
+       if (!f)
+-              r = errno;
++              return errno;
+ 
+       parse(f);
+       usb_close(f);
+-
+-      udev = udev_new();
+-      hwdb = udev_hwdb_new(udev);
+-
+-      return r;
++      return 0;
+ }
+ 
+ void names_exit(void)
+ {
+-      hwdb = udev_hwdb_unref(hwdb);
+-      udev = udev_unref(udev);
++      free_vendor();
++      free_product();
++      free_class();
++      free_subclass();
++      free_protocol();
+       free_audioterminal();
+       free_videoterminal();
+       free_genericstrtable();
+-- 
+2.16.2
+
diff --git a/package/utils/usbutils/patches/040-add-back-update-usbids.patch 
b/package/utils/usbutils/patches/040-add-back-update-usbids.patch
new file mode 100644
index 0000000000..24167f5636
--- /dev/null
+++ b/package/utils/usbutils/patches/040-add-back-update-usbids.patch
@@ -0,0 +1,77 @@
+From 41ae595f349cd7ceab74f5c92727abf104be164a Mon Sep 17 00:00:00 2001
+From: Rosen Penev <ros...@gmail.com>
+Date: Fri, 9 Mar 2018 13:10:06 -0800
+Subject: [PATCH] Revert "drop unused input file for usb.ids update script"
+
+This reverts commit 15536b7ab056a960cefe0651a5d50dc558e2f66d.
+
+commit 15536b7ab056a960cefe0651a5d50dc558e2f66d
+Author: Stephan Linz <l...@li-pro.net>
+Date:   Wed Nov 23 13:20:35 2016 +0100
+
+    drop unused input file for usb.ids update script
+    
+    Based on commit 5d7ea40 "drop dependency on usb.ids" the input
+    file update-usbids.sh.in is no longer used and can be dropped.
+    
+    Signed-off-by: Stephan Linz <l...@li-pro.net>
+---
+ update-usbids.sh.in | 46 ++++++++++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 47 insertions(+)
+ create mode 100755 update-usbids.sh.in
+
+diff --git a/update-usbids.sh.in b/update-usbids.sh.in
+new file mode 100755
+index 0000000..4a487ed
+--- /dev/null
++++ b/update-usbids.sh.in
+@@ -0,0 +1,46 @@
++#!/bin/sh
++
++# see also update-pciids.sh (fancier)
++
++[ "$1" = "-q" ] && quiet="true" || quiet="false"
++
++set -e
++SRC="http://www.linux-usb.org/usb.ids";
++DEST=@usbids@
++
++# if usb.ids is read-only (because the filesystem is read-only),
++# then just skip this whole process.
++if ! touch ${DEST} >&2 >/dev/null ; then
++      ${quiet} || echo "${DEST} is read-only, exiting."
++      exit 0
++fi
++
++if which wget >/dev/null 2>&1 ; then
++      DL="wget -O $DEST.new $SRC"
++      ${quiet} && DL="$DL -q"
++elif which lynx >/dev/null 2>&1 ; then
++      DL="eval lynx -source $SRC >$DEST.new"
++else
++      echo >&2 "update-usbids: cannot find wget nor lynx"
++      exit 1
++fi
++
++if ! $DL ; then
++      echo >&2 "update-usbids: download failed"
++      rm -f $DEST.new
++      exit 1
++fi
++
++if ! grep >/dev/null "^C " $DEST.new ; then
++      echo >&2 "update-usbids: missing class info, probably truncated file"
++      exit 1
++fi
++
++if [ -f $DEST ] ; then
++      mv $DEST $DEST.old
++      # --reference is supported only by chmod from GNU file, so let's ignore 
any errors
++      chmod -f --reference=$DEST.old $DEST.new 2>/dev/null || true
++fi
++mv $DEST.new $DEST
++
++${quiet} || echo "Done."
+-- 
+2.16.2
+
-- 
2.16.2


_______________________________________________
Lede-dev mailing list
Lede-dev@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/lede-dev

Reply via email to