summaryrefslogtreecommitdiff
path: root/usbutils
diff options
context:
space:
mode:
authorChris Larson <clarson@kergoth.com>2004-11-25 10:19:50 +0000
committerChris Larson <clarson@kergoth.com>2004-11-25 10:19:50 +0000
commit119b59cd0df00269bfe51d906657193217b8c884 (patch)
treebe4bc7f812a9df2c6b3f17e6c3cc9bfafad07253 /usbutils
parentc985a77fad25302d576fbcf92149c983887bc0b9 (diff)
Remove the EOLN_NATIVE flag from a ton of files (patches & the like for which line ending conversions can break things).
BKrev: 41a5b1c6eA2OPeQrDQEgEwAmKXvQJg
Diffstat (limited to 'usbutils')
-rw-r--r--usbutils/usbutils-0.11+cvs20041108/usbutils-0.11+cvs20041108.patch7817
1 files changed, 7817 insertions, 0 deletions
diff --git a/usbutils/usbutils-0.11+cvs20041108/usbutils-0.11+cvs20041108.patch b/usbutils/usbutils-0.11+cvs20041108/usbutils-0.11+cvs20041108.patch
index e69de29bb2..1898eaef4b 100644
--- a/usbutils/usbutils-0.11+cvs20041108/usbutils-0.11+cvs20041108.patch
+++ b/usbutils/usbutils-0.11+cvs20041108/usbutils-0.11+cvs20041108.patch
@@ -0,0 +1,7817 @@
+
+#
+# Patch managed by http://www.holgerschurig.de/patcher.html
+#
+
+--- usbutils-0.11/ChangeLog~usbutils-0.11+cvs20041108
++++ usbutils-0.11/ChangeLog
+@@ -1,3 +1,30 @@
++2004-10-20 David Brownell <dbrownell@users.sourceforge.net>
++ * lsusb.c: minor formatting updates; add a warning when those HID
++ descriptors aren't available.
++
++2004-10-20 Aurelien Jarno <aurelien@aurel32.net>
++ * lsusb.c: bugfixes for reading HID descriptors
++
++2004-10-15 David Brownell <dbrownell@users.sourceforge.net>
++ * lsusb.c: USB 2.0 updates for dual-speed and OTG devices, hubs.
++ Display all descriptors in the right sequence, and dump ones
++ we don't (yet) recognize. Minor cleanups.
++ * usb.ids: update to current version
++
++2004-02-20 Thomas Sailer <sailer@eldrich.ee.ethz.ch>
++ Move to CVS at linux-usb.sf.net
++ Label as version 0.12.
++
++2003-12-06 Aurelien Jarno <aurelien@aurel32.net>
++ Update Debian with libusb based version.
++
++2003-08-31 David Brownell <dbrownell@users.sourceforge.net>
++ * lsusb.c: (against 0.11) recognize CDC descriptors, USB 2.0 updates,
++ string handling updates,
++
++2003-??-?? Aurelien Jarno <aurelien@aurel32.net>
++ Convert to latest libusb, supporting BSD and Darwin.
++
+ 2000-11-06 Thomas Sailer <sailer@eldrich.ee.ethz.ch>
+
+ * names.c, lsusb.c: Fixup of Gunther Mayer's patch; do not export
+--- usbutils-0.11/Makefile.am~usbutils-0.11+cvs20041108
++++ usbutils-0.11/Makefile.am
+@@ -1,19 +1,20 @@
+-SUBDIRS = libusb
++SUBDIRS =
+
+ INCLUDES =
+
+ sbin_PROGRAMS = lsusb usbmodules
++sbin_SCRIPTS = update-usbids
+
+-noinst_HEADERS = names.h usb.h usbdevice_fs.h devtree.h list.h usbmodules.h
++noinst_HEADERS = names.h usbdevice_fs.h devtree.h list.h usbmodules.h usbmisc.h
+
+-lsusb_SOURCES = lsusb.c names.c devtree.c
++lsusb_SOURCES = lsusb.c names.c devtree.c usbmisc.c
+ lsusb_LDADD = @LIBOBJS@
+
+-usbmodules_SOURCES = usbmodules.c
++usbmodules_SOURCES = usbmodules.c usbmisc.c
+ usbmodules_LDADD = @LIBOBJS@
+
+ data_DATA = usb.ids
+
+-man_MANS = lsusb.8 usbmodules.8
++man_MANS = lsusb.8 usbmodules.8 update-usbids.8
+
+ EXTRA_DIST = $(man_MANS) $(data_DATA) usbutils.spec getopt.h getopt.c getopt1.c
+--- usbutils-0.11/NEWS~usbutils-0.11+cvs20041108
++++ usbutils-0.11/NEWS
+@@ -1 +1,2 @@
+-Created :)
++Thanks to a patch from Aurelien Jarno, usbutils now uses libusb to
++access USB devices
+--- usbutils-0.11/configure.in~usbutils-0.11+cvs20041108
++++ usbutils-0.11/configure.in
+@@ -1,40 +1,75 @@
+-AC_INIT(lsusb.c)
+-AC_CANONICAL_SYSTEM
++dnl Process this file with autoconf to produce a configure script.
+
+-AM_INIT_AUTOMAKE(usbutils, 0.11)
++# Initialization
++AC_INIT(Makefile.am)
+ AM_CONFIG_HEADER(config.h)
+
+-dnl AC_CHECK_TOOL()
++AM_INIT_AUTOMAKE(usbutils, 0.12)
+
+-AC_PROG_MAKE_SET
+-AC_ISC_POSIX
++# determine the system type
++AC_CANONICAL_HOST
++
++# build time sanity check...
++AM_SANITY_CHECK
++
++# checks for programs
+ AC_PROG_CC
+-AM_PROG_CC_STDC
+-dnl AC_PROG_RANLIB
++AC_PROG_RANLIB
++AC_PROG_LN_S
++AC_PROG_INSTALL
++
++# checks for header files
++AC_HEADER_STDC
++AC_CHECK_HEADERS(getopt.h sys/ioctl.h syslog.h errno.h)
++
++# checks for typedefs, structures, and compiler characteristics
+ AC_C_CONST
+ AC_C_INLINE
+-AC_HEADER_STDC
++AC_STRUCT_TM
+
+-AC_CHECK_PROG(RANLIB, ranlib, ranlib, :)
+-AC_CHECK_PROG(DLLTOOL, dlltool, dlltool, dlltool)
+-AC_CHECK_PROG(AS, as, as, as, as)
+-AC_CHECK_PROG(AR, ar, ar, ar, ar)
++# checks for library functions
++AC_CHECK_FUNCS([getopt_long],,[AC_LIBOBJ([getopt]) AC_LIBOBJ([getopt1])])
+
+-AC_CHECK_HEADERS(getopt.h sys/ioctl.h syslog.h errno.h linux/usb.h linux/usbdevice_fs.h)
+-AC_CHECK_FUNCS(getopt_long,,LIBOBJS="$LIBOBJS getopt.o getopt1.o")
++dnl checks for libusb-config
++AC_CHECK_PROG(LIBUSB_CONFIG, libusb-config, yes, no)
++if test "$LIBUSB_CONFIG" = "yes"; then
++ LIBUSB_LDFLAGS=`libusb-config --libs`
++ LIBUSB_CFLAGS=`libusb-config --cflags`
++ LIBUSB_VERSION=`libusb-config --version`
++else
++ AC_MSG_ERROR([libusb not found!])
++fi
++
+
+ dnl set USBIDS_FILE in config.h.
+ if test "x${datadir}" = 'x${prefix}/share'; then
+ if test "x${prefix}" = "xNONE"; then
+- AC_DEFINE_UNQUOTED(USBIDS_FILE, "${ac_default_prefix}/share/usb.ids")
++ AC_DEFINE_UNQUOTED(USBIDS_FILE, "${ac_default_prefix}/share/usb.ids", [location of usb.ids])
+ else
+- AC_DEFINE_UNQUOTED(USBIDS_FILE, "${prefix}/share/usb.ids")
++ AC_DEFINE_UNQUOTED(USBIDS_FILE, "${prefix}/share/usb.ids", [location of usb.ids])
+ fi
+ else
+- AC_DEFINE_UNQUOTED(USBIDS_FILE, "${datadir}/usb.ids")
++ AC_DEFINE_UNQUOTED(USBIDS_FILE, "${datadir}/usb.ids", [location of usb.ids])
+ fi
+
+-AC_CONFIG_SUBDIRS([libusb])
++# some extra flags
++CFLAGS="$CFLAGS -Wall $LIBUSB_CFLAGS"
++LDFLAGS="$LDFLAGS $LIBUSB_LDFLAGS"
++
++# pass flags
++AC_SUBST(CFLAGS)
++AC_SUBST(LDFLAGS)
+
+-AC_SUBST(LIBOBJS)
+ AC_OUTPUT([Makefile])
++
++AC_MSG_RESULT([
++
++usbutils-$VERSION is now configured for $canonical_host_type
++
++ Build: $build
++ Host: $host
++ Source directory: $srcdir
++ Installation prefix: $prefix
++ C compiler: $CC $CFLAGS
++
++])
+--- usbutils-0.11/lsusb.8~usbutils-0.11+cvs20041108
++++ usbutils-0.11/lsusb.8
+@@ -1,4 +1,4 @@
+-.TH lsusb 8 "14 September 1999" "usbutils-0.9" "Linux USB Utilities"
++.TH lsusb 8 "19 November 2003" "usbutils-0.11" "Linux USB Utilities"
+ .IX lsusb
+ .SH NAME
+ lsusb \- list all USB devices
+@@ -29,7 +29,7 @@
+ Tells
+ .I lsusb
+ to be very verbose and display even more information (actually everything the
+-PCI device is able to tell).
++USB device is able to tell).
+ You must be root for this to work.
+ .TP
+ \fB\-s\fP [[\fIbus\fP]\fB:\fP][\fIdevnum\fP]
+@@ -39,13 +39,9 @@
+ .I devnum.
+ Both ID's are given in hexadecimal and may be omitted.
+ .TP
+-\fB\-d\fP \fIvendor\fP\fB:\fP[\fIproduct\fP]
++\fB\-d\fP [\fIvendor\fP]\fB:\fP[\fIproduct\fP]
+ Show only devices with the specified vendor and product ID.
+-Both ID's are given in hexadecimal;
+-the product ID may be omitted, but the vendor ID must be given.
+-.TP
+-.B \-p \fIprocpath\fP
+-Use another path instead of /proc/bus/usb.
++Both ID's are given in hexadecimal.
+ .TP
+ .B \-D \fIdevice\fP
+ Do not scan the /proc/bus/usb directory,
+@@ -80,7 +76,7 @@
+
+ .SH FILES
+ .TP
+-.B /usr/share/usb.ids
++.B /usr/share/misc/usb.ids
+ A list of all known USB ID's (vendors, products, classes, subclasses and protocols).
+ .TP
+ .B /proc/bus/usb
+--- usbutils-0.11/lsusb.c~usbutils-0.11+cvs20041108
++++ usbutils-0.11/lsusb.c
+@@ -3,7 +3,8 @@
+ /*
+ * lsusb.c -- lspci like utility for the USB bus
+ *
+- * Copyright (C) 1999, 2000, 2001 Thomas Sailer (sailer@ife.ee.ethz.ch)
++ * Copyright (C) 1999, 2000, 2001, 2003
++ * Thomas Sailer (t.sailer@alumni.ethz.ch)
+ *
+ * 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
+@@ -24,57 +25,65 @@
+
+ /*****************************************************************************/
+
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++
+ #include <sys/types.h>
+ #include <sys/stat.h>
+-#include <sys/ioctl.h>
+ #include <fcntl.h>
+-#include <dirent.h>
+ #include <string.h>
+ #include <errno.h>
+-#include <stdlib.h>
+-#include <unistd.h>
+ #include <stdio.h>
+ #include <stdarg.h>
+-
+-#include <linux/types.h>
+-#ifdef HAVE_LINUX_USBDEVICE_FS_H
+-#include <linux/usbdevice_fs.h>
+-#else
+-#include "usbdevice_fs.h"
+-#endif
+-#ifdef HAVE_LINUX_USB_H
+-#include <linux/usb.h>
+-#else
+-#include "usb.h"
+-#endif
+-
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif
++#include <usb.h>
+
+ #include "names.h"
+ #include "devtree.h"
++#include "usbmisc.h"
+
+ #define _GNU_SOURCE
+ #include <getopt.h>
+
+-#define CTRL_RETRIES 50
+-#define CTRL_TIMEOUT 100 /* milliseconds */
+
+-#define USB_DT_CS_DEVICE 0x21
+-#define USB_DT_CS_CONFIG 0x22
+-#define USB_DT_CS_STRING 0x23
++/* from USB 2.0 spec and updates */
++#define USB_DT_DEVICE_QUALIFIER 0x06
++#define USB_DT_OTHER_SPEED_CONFIG 0x07
++#define USB_DT_OTG 0x09
++#define USB_DT_DEBUG 0x0a
++#define USB_DT_INTERFACE_ASSOCIATION 0x0b
++
++/* convention suggested by common class spec */
+ #define USB_DT_CS_INTERFACE 0x24
+ #define USB_DT_CS_ENDPOINT 0x25
+
+ #define VERBLEVEL_DEFAULT 0 /* 0 gives lspci behaviour; 1, lsusb-0.9 */
+
++#define CTRL_RETRIES 2
++#define CTRL_TIMEOUT (5*1000) /* milliseconds */
++
+ static const char *procbususb = "/proc/bus/usb";
+ static unsigned int verblevel = VERBLEVEL_DEFAULT;
+ static int do_report_desc = 1;
+-static int open_mode = O_RDONLY;
+
+-static void dump_junk2(unsigned char *, unsigned int);
++static void dump_interface(struct usb_dev_handle *dev, struct usb_interface *interface);
++static void dump_endpoint(struct usb_dev_handle *dev, struct usb_interface_descriptor *interface, struct usb_endpoint_descriptor *endpoint);
++static void dump_audiocontrol_interface(struct usb_dev_handle *dev, unsigned char *buf);
++static void dump_audiostreaming_interface(struct usb_dev_handle *dev, unsigned char *buf);
++static void dump_midistreaming_interface(struct usb_dev_handle *dev, unsigned char *buf);
++static char *dump_comm_descriptor(struct usb_dev_handle *dev, unsigned char *buf, char *indent);
++static void dump_hid_device(struct usb_dev_handle *dev, struct usb_interface_descriptor *interface, unsigned char *buf);
++static void dump_audiostreaming_endpoint(struct usb_dev_handle *dev, unsigned char *buf);
++static void dump_midistreaming_endpoint(struct usb_dev_handle *dev, unsigned char *buf);
++static void dump_hub(char *prefix, unsigned char *p, int has_tt);
++static void dump_ccid_device(unsigned char *buf);
++
++/* ---------------------------------------------------------------------- */
++
++static unsigned int convert_le_u32 (const unsigned char *buf)
++{
++ return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
++}
+
+ /* ---------------------------------------------------------------------- */
+
+@@ -95,66 +104,24 @@
+
+ /* ---------------------------------------------------------------------- */
+
+-static int usb_control_msg(int fd, u_int8_t requesttype, u_int8_t request, u_int16_t value,
+- u_int16_t index, unsigned int size, void *data)
+-{
+- struct usbdevfs_ctrltransfer ctrl;
+- int result, try;
+-
+- ctrl.requesttype = requesttype;
+- ctrl.request = request;
+- ctrl.value = value;
+- ctrl.index = index;
+- ctrl.length = size;
+- ctrl.timeout = 1000;
+- ctrl.data = data;
+- ctrl.timeout = CTRL_TIMEOUT;
+- try = 0;
+- do {
+- result = ioctl(fd, USBDEVFS_CONTROL, &ctrl);
+- try++;
+- } while (try < CTRL_RETRIES && result == -1 && errno == ETIMEDOUT);
+- return result;
+-}
+-
+-/* ---------------------------------------------------------------------- */
+-
+-static int get_string(int fd, char *buf, size_t size, u_int8_t id, u_int16_t lang)
++static int get_string(struct usb_dev_handle *dev, char* buf, size_t size, u_int8_t id)
+ {
+- unsigned char b[256];
+- wchar_t w[128];
+- unsigned int i;
+ int ret;
+-
+- if (size < 1)
+- return 0;
+- *buf = 0;
+- /* string ID 0 means no string */
+- if (!id || fd == -1)
+- return 0;
+-
+- b[0] = b[1] = 0xbf;
+- ret = usb_control_msg(fd, USB_DIR_IN, USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) | id, 0, sizeof(b), b);
+- if (ret < 0) {
+- if (open_mode == O_RDWR)
+- fprintf(stderr, "cannot get string descriptor %d, error = %s(%d)\n", id, strerror(errno), errno);
+- return 0;
+- }
+- if (ret < 2 || b[0] < 2 || b[1] != USB_DT_STRING) {
+- fprintf(stderr, "string descriptor %d invalid (%02x %02x; len=%d)\n", id, b[0], b[1], ret);
++
++ if (id) {
++ ret = usb_get_string_simple(dev, id, buf, size);
++ if (ret <= 0) {
++ buf[0] = 0;
++ return 0;
++ }
++ else
++ return ret;
++
++ }
++ else {
++ buf[0] = 0;
+ return 0;
+ }
+-#if 0
+- for (i = 0; i < ((b[0] - 2) / 2); i++)
+- w[i] = b[2+2*i] | (b[3+2*i] << 8);
+- w[i] = 0;
+- return wcstombs(buf, w, size);
+-#else
+- for (i = 0; i < ((b[0] - 2) / 2); i++)
+- buf[i] = b[2+2*i];
+- buf[i] = 0;
+- return i;
+-#endif
+ }
+
+ static int get_vendor_string(char *buf, size_t size, u_int16_t vid)
+@@ -231,7 +198,7 @@
+
+ /* ---------------------------------------------------------------------- */
+
+-static void dump_junk2(unsigned char *buf, unsigned int len)
++static void dump_bytes(unsigned char *buf, unsigned int len)
+ {
+ unsigned int i;
+
+@@ -256,27 +223,20 @@
+ * General config descriptor dump
+ */
+
+-static void dump_device(int fd, unsigned char *buf, u_int16_t lang)
++static void dump_device(struct usb_dev_handle *dev, struct usb_device_descriptor *descriptor, unsigned int flags)
+ {
+- unsigned int vid, pid;
+ char vendor[128], product[128];
+ char cls[128], subcls[128], proto[128];
+ char mfg[128], prod[128], serial[128];
+
+- if (buf[1] != USB_DT_DEVICE)
+- printf(" Warning: Invalid descriptor\n");
+- else if (buf[0] < 18)
+- printf(" Warning: Descriptor too short\n");
+- vid = buf[8] | (buf[9] << 8);
+- pid = buf[10] | (buf[11] << 8);
+- get_vendor_string(vendor, sizeof(vendor), vid);
+- get_product_string(product, sizeof(product), vid, pid);
+- get_class_string(cls, sizeof(cls), buf[4]);
+- get_subclass_string(subcls, sizeof(subcls), buf[4], buf[5]);
+- get_protocol_string(proto, sizeof(proto), buf[4], buf[5], buf[6]);
+- get_string(fd, mfg, sizeof(mfg), buf[14], lang);
+- get_string(fd, prod, sizeof(prod), buf[15], lang);
+- get_string(fd, serial, sizeof(serial), buf[16], lang);
++ get_vendor_string(vendor, sizeof(vendor), descriptor->idVendor);
++ get_product_string(product, sizeof(product), descriptor->idVendor, descriptor->idProduct);
++ get_class_string(cls, sizeof(cls), descriptor->bDeviceClass);
++ get_subclass_string(subcls, sizeof(subcls), descriptor->bDeviceClass, descriptor->bDeviceSubClass);
++ get_protocol_string(proto, sizeof(proto), descriptor->bDeviceClass, descriptor->bDeviceSubClass, descriptor->bDeviceProtocol);
++ get_string(dev, mfg, sizeof(mfg), descriptor->iManufacturer);
++ get_string(dev, prod, sizeof(prod), descriptor->iProduct);
++ get_string(dev, serial, sizeof(serial), descriptor->iSerialNumber);
+ printf("Device Descriptor:\n"
+ " bLength %5u\n"
+ " bDescriptorType %5u\n"
+@@ -292,47 +252,76 @@
+ " iProduct %5u %s\n"
+ " iSerial %5u %s\n"
+ " bNumConfigurations %5u\n",
+- buf[0], buf[1], buf[3], buf[2], buf[4], cls, buf[5], subcls, buf[6], proto, buf[7],
+- vid, vendor, pid, product, buf[13], buf[12], buf[14], mfg, buf[15], prod, buf[16], serial, buf[17]);
+- dump_junk(buf, " ", 18);
++ descriptor->bLength, descriptor->bDescriptorType, descriptor->bcdUSB >> 8, descriptor->bcdUSB & 0xff,
++ descriptor->bDeviceClass, cls, descriptor->bDeviceSubClass, subcls, descriptor->bDeviceProtocol, proto,
++ descriptor->bMaxPacketSize0, descriptor->idVendor, vendor, descriptor->idProduct, product,
++ descriptor->bcdDevice >> 8, descriptor->bcdDevice & 0xff, descriptor->iManufacturer, mfg,
++ descriptor->iProduct, prod, descriptor->iSerialNumber, serial, descriptor->bNumConfigurations);
+ }
+
+-static void dump_config(int fd, unsigned char *buf)
++static void dump_config(struct usb_dev_handle *dev, struct usb_config_descriptor *config)
+ {
+- if (buf[1] != USB_DT_CONFIG)
+- printf(" Warning: Invalid descriptor\n");
+- else if (buf[0] < 9)
+- printf(" Warning: Descriptor too short\n");
++ char cfg[128];
++ int i;
++
++ get_string(dev, cfg, sizeof(cfg), config->iConfiguration);
+ printf(" Configuration Descriptor:\n"
+ " bLength %5u\n"
+ " bDescriptorType %5u\n"
+ " wTotalLength %5u\n"
+ " bNumInterfaces %5u\n"
+ " bConfigurationValue %5u\n"
+- " iConfiguration %5u\n"
++ " iConfiguration %5u %s\n"
+ " bmAttributes 0x%02x\n",
+- buf[0], buf[1], buf[2] | (buf[3] << 8), buf[4], buf[5], buf[6], buf[7]);
+- if (buf[7] & 0x40)
++ config->bLength, config->bDescriptorType, config->wTotalLength,
++ config->bNumInterfaces, config->bConfigurationValue, config->iConfiguration,
++ cfg, config->bmAttributes);
++ if (config->bmAttributes & 0x40)
+ printf(" Self Powered\n");
+- if (buf[7] & 0x20)
++ if (config->bmAttributes & 0x20)
+ printf(" Remote Wakeup\n");
+- printf(" MaxPower %5umA\n", buf[8] * 2);
+- dump_junk(buf, " ", 9);
++ printf(" MaxPower %5umA\n", config->MaxPower * 2);
++
++ /* avoid re-ordering or hiding descriptors for display */
++ if (config->extralen) {
++ int size = config->extralen;
++ unsigned char *buf = config->extra;
++
++ while (size >= 2) {
++ if (buf[0] < 2) {
++ dump_junk(" ", buf, size);
++ break;
++ }
++ switch (buf[1]) {
++ case USB_DT_OTG:
++ /* handled separately */
++ break;
++ default:
++ /* often a misplaced class descriptor */
++ printf(" UNRECOGNIZED: ");
++ dump_bytes(buf, size);
++ break;
++ }
++ size -= buf[0];
++ buf += buf[0];
++ }
++ }
++ for (i = 0 ; i < config->bNumInterfaces ; i++)
++ dump_interface(dev, &config->interface[i]);
+ }
+
+-static void dump_interface(int fd, unsigned char *buf, u_int16_t lang)
++static void dump_altsetting(struct usb_dev_handle *dev, struct usb_interface_descriptor *interface)
+ {
+ char cls[128], subcls[128], proto[128];
+ char ifstr[128];
++
++ char *buf;
++ int size, i;
+
+- if (buf[1] != USB_DT_INTERFACE)
+- printf(" Warning: Invalid descriptor\n");
+- else if (buf[0] < 9)
+- printf(" Warning: Descriptor too short\n");
+- get_class_string(cls, sizeof(cls), buf[5]);
+- get_subclass_string(subcls, sizeof(subcls), buf[5], buf[6]);
+- get_protocol_string(proto, sizeof(proto), buf[5], buf[6], buf[7]);
+- get_string(fd, ifstr, sizeof(ifstr), buf[8], lang);
++ get_class_string(cls, sizeof(cls), interface->bInterfaceClass);
++ get_subclass_string(subcls, sizeof(subcls), interface->bInterfaceClass, interface->bInterfaceSubClass);
++ get_protocol_string(proto, sizeof(proto), interface->bInterfaceClass, interface->bInterfaceSubClass, interface->bInterfaceProtocol);
++ get_string(dev, ifstr, sizeof(ifstr), interface->iInterface);
+ printf(" Interface Descriptor:\n"
+ " bLength %5u\n"
+ " bDescriptorType %5u\n"
+@@ -343,20 +332,84 @@
+ " bInterfaceSubClass %5u %s\n"
+ " bInterfaceProtocol %5u %s\n"
+ " iInterface %5u %s\n",
+- buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], cls,
+- buf[6], subcls, buf[7], proto, buf[8], ifstr);
+- dump_junk(buf, " ", 9);
++ interface->bLength, interface->bDescriptorType, interface->bInterfaceNumber,
++ interface->bAlternateSetting, interface->bNumEndpoints, interface->bInterfaceClass, cls,
++ interface->bInterfaceSubClass, subcls, interface->bInterfaceProtocol, proto,
++ interface->iInterface, ifstr);
++
++ /* avoid re-ordering or hiding descriptors for display */
++ if (interface->extralen)
++ {
++ size = interface->extralen;
++ buf = interface->extra;
++ while (size >= 2 * sizeof(u_int8_t))
++ {
++ if (buf[0] < 2) {
++ dump_junk(" ", buf, size);
++ break;
++ }
++ switch (buf[1]) {
++ case USB_DT_CS_INTERFACE:
++ switch(interface->bInterfaceClass) {
++ case USB_CLASS_AUDIO:
++ switch(interface->bInterfaceSubClass) {
++ case 1:
++ dump_audiocontrol_interface(dev, buf);
++ break;
++ case 2:
++ dump_audiostreaming_interface(dev, buf);
++ break;
++ case 3:
++ dump_midistreaming_interface(dev, buf);
++ break;
++ }
++ break;
++ case USB_CLASS_COMM:
++ dump_comm_descriptor(dev, buf,
++ " ");
++ break;
++ }
++ break;
++ case USB_DT_HID:
++ if (interface->bInterfaceClass == USB_CLASS_HID)
++ dump_hid_device(dev, interface, buf);
++ if (interface->bInterfaceClass == 0x0b)
++ dump_ccid_device(buf);
++ break;
++ case USB_DT_OTG:
++ /* handled separately */
++ break;
++ default:
++ /* often a misplaced class descriptor */
++ printf(" UNRECOGNIZED: ");
++ dump_bytes(buf, size);
++ break;
++ }
++ size -= buf[0];
++ buf += buf[0];
++ }
++ }
++ for (i = 0 ; i < interface->bNumEndpoints ; i++)
++ dump_endpoint(dev, interface, &interface->endpoint[i]);
+ }
+
+-static void dump_endpoint(int fd, unsigned char *buf)
++static void dump_interface(struct usb_dev_handle *dev, struct usb_interface *interface)
++{
++ int i;
++
++ for (i = 0; i < interface->num_altsetting; i++)
++ dump_altsetting(dev, &interface->altsetting[i]);
++}
++
++static void dump_endpoint(struct usb_dev_handle *dev, struct usb_interface_descriptor *interface, struct usb_endpoint_descriptor *endpoint)
+ {
+ static const char *typeattr[] = { "Control", "Isochronous", "Bulk", "Interrupt" };
+- static const char *syncattr[] = { "none", "Asynchronous", "Adaptive", "Synchronous" };
++ static const char *syncattr[] = { "None", "Asynchronous", "Adaptive", "Synchronous" };
++ static const char *usage[] = { "Data", "Feedback", "Implicit feedback Data", "(reserved)" };
++ static const char *hb[] = { "1x", "2x", "3x", "(?\?)" };
++ char *buf;
++ int size;
+
+- if (buf[1] != USB_DT_ENDPOINT)
+- printf(" Warning: Invalid descriptor\n");
+- else if (buf[0] < 7)
+- printf(" Warning: Descriptor too short\n");
+ printf(" Endpoint Descriptor:\n"
+ " bLength %5u\n"
+ " bDescriptorType %5u\n"
+@@ -364,19 +417,53 @@
+ " bmAttributes %5u\n"
+ " Transfer Type %s\n"
+ " Synch Type %s\n"
+- " wMaxPacketSize %5u\n"
++ " Usage Type %s\n"
++ " wMaxPacketSize 0x%04x %s %d bytes\n"
+ " bInterval %5u\n",
+- buf[0], buf[1], buf[2], buf[2] & 15, (buf[2] & 0x80) ? "IN" : "OUT",
+- buf[3], typeattr[buf[3] & 3], syncattr[(buf[3] >> 2) & 3],
+- buf[4] | (buf[5] << 8), buf[6]);
+- if (buf[0] < 9) {
+- dump_junk(buf, " ", 7);
+- return;
+- }
++ endpoint->bLength, endpoint->bDescriptorType, endpoint->bEndpointAddress, endpoint->bEndpointAddress & 0x0f,
++ (endpoint->bEndpointAddress & 0x80) ? "IN" : "OUT", endpoint->bmAttributes,
++ typeattr[endpoint->bmAttributes & 3], syncattr[(endpoint->bmAttributes >> 2) & 3],
++ usage[(endpoint->bmAttributes >> 4) & 3], endpoint->wMaxPacketSize,
++ hb[(endpoint->wMaxPacketSize >> 11) & 3],
++ endpoint->wMaxPacketSize & 0x3ff,
++ endpoint->bInterval);
++ /* only for audio endpoints */
++ if (endpoint->bLength == 9)
+ printf(" bRefresh %5u\n"
+ " bSynchAddress %5u\n",
+- buf[7], buf[8]);
+- dump_junk(buf, " ", 9);
++ endpoint->bRefresh, endpoint->bSynchAddress);
++
++ /* avoid re-ordering or hiding descriptors for display */
++ if (endpoint->extralen)
++ {
++ size = endpoint->extralen;
++ buf = endpoint->extra;
++ while (size >= 2 * sizeof(u_int8_t))
++ {
++ if (buf[0] < 2) {
++ dump_junk(" ", buf, size);
++ break;
++ }
++ switch (buf[1]) {
++ case USB_DT_CS_ENDPOINT:
++ if (interface->bInterfaceClass == 1 && interface->bInterfaceSubClass == 2)
++ dump_audiostreaming_endpoint(dev, buf);
++ else if (interface->bInterfaceClass == 1 && interface->bInterfaceSubClass == 3)
++ dump_midistreaming_endpoint(dev, buf);
++ break;
++ case USB_DT_OTG:
++ /* handled separately */
++ break;
++ default:
++ /* often a misplaced class descriptor */
++ printf(" UNRECOGNIZED: ");
++ dump_bytes(buf, size);
++ break;
++ }
++ size -= buf[0];
++ buf += buf[0];
++ }
++ }
+ }
+
+ /* ---------------------------------------------------------------------- */
+@@ -385,7 +472,7 @@
+ * Audio Class descriptor dump
+ */
+
+-static void dump_audiocontrol_interface(int fd, unsigned char *buf, u_int16_t lang)
++static void dump_audiocontrol_interface(struct usb_dev_handle *dev, unsigned char *buf)
+ {
+ static const char *chconfig[] = {
+ "Left Front (L)", "Right Front (R)", "Center Front (C)", "Low Freqency Enhancement (LFE)",
+@@ -423,8 +510,8 @@
+
+ case 0x02: /* INPUT_TERMINAL */
+ printf("(INPUT_TERMINAL)\n");
+- get_string(fd, chnames, sizeof(chnames), buf[10], lang);
+- get_string(fd, term, sizeof(term), buf[11], lang);
++ get_string(dev, chnames, sizeof(chnames), buf[10]);
++ get_string(dev, term, sizeof(term), buf[11]);
+ termt = buf[4] | (buf[5] << 8);
+ get_audioterminal_string(termts, sizeof(termts), termt);
+ if (buf[0] < 12)
+@@ -447,7 +534,7 @@
+
+ case 0x03: /* OUTPUT_TERMINAL */
+ printf("(OUTPUT_TERMINAL)\n");
+- get_string(fd, term, sizeof(term), buf[8], lang);
++ get_string(dev, term, sizeof(term), buf[8]);
+ termt = buf[4] | (buf[5] << 8);
+ get_audioterminal_string(termts, sizeof(termts), termt);
+ if (buf[0] < 9)
+@@ -471,8 +558,8 @@
+ } else {
+ N = 1+(j*k-1)/8;
+ }
+- get_string(fd, chnames, sizeof(chnames), buf[8+j], lang);
+- get_string(fd, term, sizeof(term), buf[9+j+N], lang);
++ get_string(dev, chnames, sizeof(chnames), buf[8+j]);
++ get_string(dev, term, sizeof(term), buf[9+j+N]);
+ if (buf[0] < 10+j+N)
+ printf(" Warning: Descriptor too short\n");
+ chcfg = buf[6+j] | (buf[7+j] << 8);
+@@ -499,7 +586,7 @@
+ printf("(SELECTOR_UNIT)\n");
+ if (buf[0] < 6+buf[4])
+ printf(" Warning: Descriptor too short\n");
+- get_string(fd, term, sizeof(term), buf[5+buf[4]], lang);
++ get_string(dev, term, sizeof(term), buf[5+buf[4]]);
+
+ printf(" bUnitID %5u\n"
+ " bNrInPins %5u\n",
+@@ -519,7 +606,7 @@
+ k = (buf[0] - 7) / j;
+ if (buf[0] < 7+buf[5]*k)
+ printf(" Warning: Descriptor too short\n");
+- get_string(fd, term, sizeof(term), buf[6+buf[5]*k], lang);
++ get_string(dev, term, sizeof(term), buf[6+buf[5]*k]);
+ printf(" bUnitID %5u\n"
+ " bSourceID %5u\n"
+ " bControlSize %5u\n",
+@@ -529,7 +616,7 @@
+ if (buf[5] > 1)
+ chcfg |= (buf[7+buf[5]*i] << 8);
+ for (j = 0; j < buf[5]; j++)
+- printf(" bmaControls(%2u) 0x%02x\n", j, buf[6+buf[5]*i+j]);
++ printf(" bmaControls(%2u) 0x%02x\n", i, buf[6+buf[5]*i+j]);
+ for (j = 0; j < 10; j++)
+ if ((chcfg >> j) & 1)
+ printf(" %s\n", chftrcontrols[j]);
+@@ -542,8 +629,8 @@
+ printf("(PROCESSING_UNIT)\n");
+ j = buf[6];
+ k = buf[11+j];
+- get_string(fd, chnames, sizeof(chnames), buf[10+j], lang);
+- get_string(fd, term, sizeof(term), buf[12+j+k], lang);
++ get_string(dev, chnames, sizeof(chnames), buf[10+j]);
++ get_string(dev, term, sizeof(term), buf[12+j+k]);
+ chcfg = buf[8+j] | (buf[9+j] << 8);
+ if (buf[0] < 13+j+k)
+ printf(" Warning: Descriptor too short\n");
+@@ -566,15 +653,15 @@
+ printf(" Enable Processing\n");
+ printf(" iProcessing %5u %s\n"
+ " Process-Specific ", buf[12+j+k], term);
+- dump_junk2(buf+(13+j+k), buf[0]-(13+j+k));
++ dump_bytes(buf+(13+j+k), buf[0]-(13+j+k));
+ break;
+
+ case 0x08: /* EXTENSION_UNIT */
+ printf("(EXTENSION_UNIT)\n");
+ j = buf[6];
+ k = buf[11+j];
+- get_string(fd, chnames, sizeof(chnames), buf[10+j], lang);
+- get_string(fd, term, sizeof(term), buf[12+j+k], lang);
++ get_string(dev, chnames, sizeof(chnames), buf[10+j]);
++ get_string(dev, term, sizeof(term), buf[12+j+k]);
+ chcfg = buf[8+j] | (buf[9+j] << 8);
+ if (buf[0] < 13+j+k)
+ printf(" Warning: Descriptor too short\n");
+@@ -603,12 +690,12 @@
+ default:
+ printf("(unknown)\n"
+ " Invalid desc subtype:");
+- dump_junk2(buf+3, buf[0]-3);
++ dump_bytes(buf+3, buf[0]-3);
+ break;
+ }
+ }
+
+-static void dump_audiostreaming_interface(int fd, unsigned char *buf)
++static void dump_audiostreaming_interface(struct usb_dev_handle *dev, unsigned char *buf)
+ {
+ static const char *fmtItag[] = { "TYPE_I_UNDEFINED", "PCM", "PCM8", "IEEE_FLOAT", "ALAW", "MULAW" };
+ static const char *fmtIItag[] = { "TYPE_II_UNDEFINED", "MPEG", "AC-3" };
+@@ -622,7 +709,7 @@
+ printf(" Warning: Invalid descriptor\n");
+ else if (buf[0] < 3)
+ printf(" Warning: Descriptor too short\n");
+- printf(" AudioControl Interface Descriptor:\n"
++ printf(" AudioStreaming Interface Descriptor:\n"
+ " bLength %5u\n"
+ " bDescriptorType %5u\n"
+ " bDescriptorSubtype %5u ",
+@@ -717,7 +804,7 @@
+ default:
+ printf("(unknown)\n"
+ " Invalid desc format type:");
+- dump_junk2(buf+4, buf[0]-4);
++ dump_bytes(buf+4, buf[0]-4);
+ }
+ break;
+
+@@ -833,18 +920,18 @@
+ default:
+ printf("(unknown)\n"
+ " Invalid desc format type:");
+- dump_junk2(buf+4, buf[0]-4);
++ dump_bytes(buf+4, buf[0]-4);
+ }
+ break;
+
+ default:
+ printf(" Invalid desc subtype:");
+- dump_junk2(buf+3, buf[0]-3);
++ dump_bytes(buf+3, buf[0]-3);
+ break;
+ }
+ }
+
+-static void dump_audiostreaming_endpoint(int fd, unsigned char *buf)
++static void dump_audiostreaming_endpoint(struct usb_dev_handle *dev, unsigned char *buf)
+ {
+ static const char *lockdelunits[] = { "Undefined", "Milliseconds", "Decoded PCM samples", "Reserved" };
+ unsigned int lckdelidx;
+@@ -874,7 +961,7 @@
+ dump_junk(buf, " ", 7);
+ }
+
+-static void dump_midistreaming_interface(int fd, unsigned char *buf, u_int16_t lang)
++static void dump_midistreaming_interface(struct usb_dev_handle *dev, unsigned char *buf)
+ {
+ static const char *jacktypes[] = {"Undefined", "Embedded", "External"};
+ char jackstr[128];
+@@ -906,7 +993,7 @@
+ printf("(MIDI_IN_JACK)\n");
+ if (buf[0] < 6)
+ printf(" Warning: Descriptor too short\n");
+- get_string(fd, jackstr, sizeof(jackstr), buf[5], lang);
++ get_string(dev, jackstr, sizeof(jackstr), buf[5]);
+ printf( " bJackType %5u %s\n"
+ " bJackID %5u\n"
+ " iJack %5u %s\n",
+@@ -930,7 +1017,7 @@
+ j, buf[2*j+6], j, buf[2*j+7]);
+ }
+ j = 6+buf[5]*2; /* midi10.pdf says, incorrectly: 5+2*p */
+- get_string(fd, jackstr, sizeof(jackstr), buf[j], lang);
++ get_string(dev, jackstr, sizeof(jackstr), buf[j]);
+ printf( " iJack %5u %s\n",
+ buf[j], jackstr);
+ dump_junk(buf, " ", j+1);
+@@ -985,19 +1072,19 @@
+ if (caps & 0x800)
+ printf( " DLS2 (Downloadable Sounds Level 2)\n");
+ j = 9+2*buf[4]+capssize;
+- get_string(fd, jackstr, sizeof(jackstr), buf[j], lang);
++ get_string(dev, jackstr, sizeof(jackstr), buf[j]);
+ printf( " iElement %5u %s\n", buf[j], jackstr);
+ dump_junk(buf, " ", j+1);
+ break;
+
+ default:
+ printf("\n Invalid desc subtype: ");
+- dump_junk2(buf+3, buf[0]-3);
++ dump_bytes(buf+3, buf[0]-3);
+ break;
+ }
+ }
+
+-static void dump_midistreaming_endpoint(int fd, unsigned char *buf)
++static void dump_midistreaming_endpoint(struct usb_dev_handle *dev, unsigned char *buf)
+ {
+ unsigned int j;
+
+@@ -1017,26 +1104,196 @@
+ dump_junk(buf, " ", 4+buf[3]);
+ }
+
+-
+-static void dump_hub(char *p)
++static void dump_hub(char *prefix, unsigned char *p, int has_tt)
+ {
+ unsigned int l, i, j;
++ unsigned int wHubChar = (p[4] << 8) | p[3];
+
+- printf(" Hub Descriptor:\n");
+- printf(" bLength %3u\n",p[0]);
+- printf(" bDesriptorType %3u\n",p[1]);
+- printf(" nNbrPorts %3u\n",p[2]);
+- printf(" wHubCharacteristic 0x%02x 0x%02x\n", p[3],p[4]);
+- printf(" bPwrOn2PwrGood %3u * 2 milli seconds\n",p[5]);
+- printf(" bHubContrCurrent %3u milli Ampere\n",p[6]);
++ printf("%sHub Descriptor:\n", prefix);
++ printf("%s bLength %3u\n", prefix, p[0]);
++ printf("%s bDescriptorType %3u\n", prefix, p[1]);
++ printf("%s nNbrPorts %3u\n", prefix, p[2]);
++ printf("%s wHubCharacteristic 0x%04x\n", prefix, wHubChar);
++ switch (wHubChar & 0x03) {
++ case 0:
++ printf("%s Ganged power switching\n", prefix);
++ break;
++ case 1:
++ printf("%s Per-port power switching\n", prefix);
++ break;
++ default:
++ printf("%s No power switching (usb 1.0)\n", prefix);
++ break;
++ }
++ if (wHubChar & 0x04)
++ printf("%s Compound device\n", prefix);
++ switch ((wHubChar >> 3) & 0x03) {
++ case 0:
++ printf("%s Ganged overcurrent protection\n", prefix);
++ break;
++ case 1:
++ printf("%s Per-port overcurrent protection\n", prefix);
++ break;
++ default:
++ printf("%s No overcurrent protection\n", prefix);
++ break;
++ }
++ if (has_tt) {
++ l = (wHubChar >> 5) & 0x03;
++ printf("%s TT think time %d FS bits\n", prefix, (l + 1) * 8);
++ }
++ if (wHubChar & (1<<7))
++ printf("%s Port indicators\n", prefix);
++ printf("%s bPwrOn2PwrGood %3u * 2 milli seconds\n", prefix, p[5]);
++ printf("%s bHubContrCurrent %3u milli Ampere\n", prefix, p[6]);
+ l= (p[2] >> 3) + 1; /* this determines the variable number of bytes following */
+- printf(" DeviceRemovable ");
++ printf("%s DeviceRemovable ", prefix);
+ for(i = 0; i < l; i++)
+ printf(" 0x%02x", p[7+i]);
+- printf("\n PortPwrCtrlMask ");
+- for(j = 0; j < l; j++)
+- printf(" 0x%02x ", p[7+i+j]);
+- printf("\n");
++ printf("\n%s PortPwrCtrlMask ", prefix);
++ for(j = 0; j < l; j++)
++ printf(" 0x%02x ", p[7+i+j]);
++ printf("\n");
++}
++
++static void dump_ccid_device(unsigned char *buf)
++{
++ unsigned int us;
++
++ if (buf[0] < 54) {
++ printf(" Warning: Descriptor too short\n");
++ return;
++ }
++ printf(" ChipCard Interface Descriptor:\n"
++ " bLength %5u\n"
++ " bDescriptorType %5u\n"
++ " bcdCCID %2x.%02x",
++ buf[0], buf[1], buf[3], buf[2]);
++ if (buf[3] != 1 || buf[2] != 0)
++ fputs(" (Warning: Only accurate for version 1.0)", stdout);
++ putchar('\n');
++
++ printf(" nMaxSlotIndex %5u\n"
++ " bVoltageSupport %5u %s\n",
++ buf[4],
++ buf[5], (buf[5] == 1? "5.0V" : buf[5] == 2? "3.0V"
++ : buf[5] == 3? "1.8V":"?"));
++
++ us = convert_le_u32 (buf+6);
++ printf(" dwProtocols %5u ", us);
++ if ((us & 1))
++ fputs(" T=0", stdout);
++ if ((us & 2))
++ fputs(" T=1", stdout);
++ if ((us & ~3))
++ fpu