upload tizen1.0 source
[framework/system/usbutils.git] / lsusb.c
1 /*****************************************************************************/
2
3 /*
4  *      lsusb.c  --  lspci like utility for the USB bus
5  *
6  *      Copyright (C) 1999-2001, 2003
7  *        Thomas Sailer (t.sailer@alumni.ethz.ch)
8  *      Copyright (C) 2003-2005 David Brownell
9  *
10  *      This program is free software; you can redistribute it and/or modify
11  *      it under the terms of the GNU General Public License as published by
12  *      the Free Software Foundation; either version 2 of the License, or
13  *      (at your option) any later version.
14  *
15  *      This program is distributed in the hope that it will be useful,
16  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *      GNU General Public License for more details.
19  *
20  *      You should have received a copy of the GNU General Public License
21  *      along with this program; if not, write to the Free Software
22  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24
25 /*****************************************************************************/
26
27 #include "config.h"
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 #include <string.h>
32 #include <errno.h>
33 #include <stdio.h>
34 #include <stdarg.h>
35 #include <byteswap.h>
36 #include <usb.h>
37
38 #include "names.h"
39 #include "devtree.h"
40 #include "usbmisc.h"
41
42 #include <getopt.h>
43
44 #if (__BYTE_ORDER == __LITTLE_ENDIAN)
45   #define le16_to_cpu(x) (x)
46 #elif (__BYTE_ORDER == __BIG_ENDIAN)
47   #define le16_to_cpu(x) bswap_16(x)
48 #else
49   #error missing BYTE_ORDER
50 #endif
51
52 /* from USB 2.0 spec and updates */
53 #define USB_DT_DEVICE_QUALIFIER         0x06
54 #define USB_DT_OTHER_SPEED_CONFIG       0x07
55 #define USB_DT_OTG                      0x09
56 #define USB_DT_DEBUG                    0x0a
57 #define USB_DT_INTERFACE_ASSOCIATION    0x0b
58 #define USB_DT_SECURITY                 0x0c
59 #define USB_DT_KEY                      0x0d
60 #define USB_DT_ENCRYPTION_TYPE          0x0e
61 #define USB_DT_BOS                      0x0f
62 #define USB_DT_DEVICE_CAPABILITY        0x10
63 #define USB_DT_WIRELESS_ENDPOINT_COMP   0x11
64 #define USB_DT_WIRE_ADAPTER             0x21
65 #define USB_DT_RPIPE                    0x22
66
67 #define USB_DT_RC_INTERFACE             0x23
68
69 /* Conventional codes for class-specific descriptors.  The convention is
70  * defined in the USB "Common Class" Spec (3.11).  Individual class specs
71  * are authoritative for their usage, not the "common class" writeup.
72  */
73 #define USB_DT_CS_DEVICE                (USB_TYPE_CLASS | USB_DT_DEVICE)
74 #define USB_DT_CS_CONFIG                (USB_TYPE_CLASS | USB_DT_CONFIG)
75 #define USB_DT_CS_STRING                (USB_TYPE_CLASS | USB_DT_STRING)
76 #define USB_DT_CS_INTERFACE             (USB_TYPE_CLASS | USB_DT_INTERFACE)
77 #define USB_DT_CS_ENDPOINT              (USB_TYPE_CLASS | USB_DT_ENDPOINT)
78
79 #ifndef USB_CLASS_CCID
80 #define USB_CLASS_CCID                  0x0b
81 #endif
82
83 #ifndef USB_CLASS_VIDEO
84 #define USB_CLASS_VIDEO                 0x0e
85 #endif
86
87 #ifndef USB_CLASS_APPLICATION
88 #define USB_CLASS_APPLICATION           0xfe
89 #endif
90
91 #define VERBLEVEL_DEFAULT 0     /* 0 gives lspci behaviour; 1, lsusb-0.9 */
92
93 #define CTRL_RETRIES     2
94 #define CTRL_TIMEOUT    (5*1000)        /* milliseconds */
95
96 #define HUB_STATUS_BYTELEN      3       /* max 3 bytes status = hub + 23 ports */
97
98 extern int lsusb_t(void);
99 static const char *procbususb = "/proc/bus/usb";
100 static unsigned int verblevel = VERBLEVEL_DEFAULT;
101 static int do_report_desc = 1;
102 static const char *encryption_type[] = {"UNSECURE", "WIRED", "CCM_1", "RSA_1", "RESERVED"};
103
104 static void dump_interface(struct usb_dev_handle *dev, struct usb_interface *interface);
105 static void dump_endpoint(struct usb_dev_handle *dev, struct usb_interface_descriptor *interface, struct usb_endpoint_descriptor *endpoint);
106 static void dump_audiocontrol_interface(struct usb_dev_handle *dev, unsigned char *buf);
107 static void dump_audiostreaming_interface(unsigned char *buf);
108 static void dump_midistreaming_interface(struct usb_dev_handle *dev, unsigned char *buf);
109 static void dump_videocontrol_interface(struct usb_dev_handle *dev, unsigned char *buf);
110 static void dump_videostreaming_interface(unsigned char *buf);
111 static void dump_dfu_interface(unsigned char *buf);
112 static char *dump_comm_descriptor(struct usb_dev_handle *dev, unsigned char *buf, char *indent);
113 static void dump_hid_device(struct usb_dev_handle *dev, struct usb_interface_descriptor *interface, unsigned char *buf);
114 static void dump_audiostreaming_endpoint(unsigned char *buf);
115 static void dump_midistreaming_endpoint(unsigned char *buf);
116 static void dump_hub(char *prefix, unsigned char *p, int has_tt);
117 static void dump_ccid_device(unsigned char *buf);
118
119 /* ---------------------------------------------------------------------- */
120
121 static unsigned int convert_le_u32 (const unsigned char *buf)
122 {
123         return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
124 }
125
126 /* ---------------------------------------------------------------------- */
127
128 /* workaround libusb API goofs:  "byte" should never be sign extended;
129  * using "char" is trouble.  Likewise, sizes should never be negative.
130  */
131
132 static inline int typesafe_control_msg(usb_dev_handle *dev,
133         unsigned char requesttype, unsigned char request,
134         int value, int index,
135         unsigned char *bytes, unsigned size, int timeout)
136 {
137         return usb_control_msg(dev, requesttype, request, value, index,
138                 (char *) bytes, (int) size, timeout);
139 }
140
141 #define usb_control_msg         typesafe_control_msg
142
143 /* ---------------------------------------------------------------------- */
144
145 int lprintf(unsigned int vl, const char *format, ...)
146 {
147         va_list ap;
148         int r;
149
150         if (vl > verblevel)
151                 return 0;
152         va_start(ap, format);
153         r = vfprintf(stderr, format, ap);
154         va_end(ap);
155         if (!vl)
156                 exit(1);
157         return r;
158 }
159
160 /* ---------------------------------------------------------------------- */
161
162 static int get_string(struct usb_dev_handle *dev, char* buf, size_t size, u_int8_t id)
163 {
164         int ret;
165
166         if (!dev) {
167                 buf[0] = 0;
168                 return 0;
169         }
170
171         if (id) {
172                 ret = usb_get_string_simple(dev, id, buf, size);
173                 if (ret <= 0) {
174                         buf[0] = 0;
175                         return 0;
176                 }
177                 else
178                         return ret;
179
180         }
181         else {
182                 buf[0] = 0;
183                 return 0;
184         }
185 }
186
187 static int get_vendor_string(char *buf, size_t size, u_int16_t vid)
188 {
189         const char *cp;
190
191         if (size < 1)
192                 return 0;
193         *buf = 0;
194         if (!(cp = names_vendor(vid)))
195                 return 0;
196         return snprintf(buf, size, "%s", cp);
197 }
198
199 static int get_product_string(char *buf, size_t size, u_int16_t vid, u_int16_t pid)
200 {
201         const char *cp;
202
203         if (size < 1)
204                 return 0;
205         *buf = 0;
206         if (!(cp = names_product(vid, pid)))
207                 return 0;
208         return snprintf(buf, size, "%s", cp);
209 }
210
211 static int get_class_string(char *buf, size_t size, u_int8_t cls)
212 {
213         const char *cp;
214
215         if (size < 1)
216                 return 0;
217         *buf = 0;
218         if (!(cp = names_class(cls)))
219                 return 0;
220         return snprintf(buf, size, "%s", cp);
221 }
222
223 static int get_subclass_string(char *buf, size_t size, u_int8_t cls, u_int8_t subcls)
224 {
225         const char *cp;
226
227         if (size < 1)
228                 return 0;
229         *buf = 0;
230         if (!(cp = names_subclass(cls, subcls)))
231                 return 0;
232         return snprintf(buf, size, "%s", cp);
233 }
234
235 static int get_protocol_string(char *buf, size_t size, u_int8_t cls, u_int8_t subcls, u_int8_t proto)
236 {
237         const char *cp;
238
239         if (size < 1)
240                 return 0;
241         *buf = 0;
242         if (!(cp = names_protocol(cls, subcls, proto)))
243                 return 0;
244         return snprintf(buf, size, "%s", cp);
245 }
246
247 static int get_audioterminal_string(char *buf, size_t size, u_int16_t termt)
248 {
249         const char *cp;
250
251         if (size < 1)
252                 return 0;
253         *buf = 0;
254         if (!(cp = names_audioterminal(termt)))
255                 return 0;
256         return snprintf(buf, size, "%s", cp);
257 }
258
259 static int get_videoterminal_string(char *buf, size_t size, u_int16_t termt)
260 {
261         const char *cp;
262
263         if (size < 1)
264                 return 0;
265         *buf = 0;
266         if (!(cp = names_videoterminal(termt)))
267                 return 0;
268         return snprintf(buf, size, "%s", cp);
269 }
270
271 static const char *get_guid(unsigned char *buf)
272 {
273         static char guid[39];
274
275         /* NOTE:  see RFC 4122 for more information about GUID/UUID
276          * structure.  The first fields fields are historically big
277          * endian numbers, dating from Apollo mc68000 workstations.
278          */
279         sprintf(guid, "{%02x%02x%02x%02x"
280                         "-%02x%02x"
281                         "-%02x%02x"
282                         "-%02x%02x"
283                         "-%02x%02x%02x%02x%02x%02x}",
284                buf[0], buf[1], buf[2], buf[3],
285                buf[4], buf[5],
286                buf[6], buf[7],
287                buf[8], buf[9],
288                buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]);
289         return guid;
290 }
291
292 /* ---------------------------------------------------------------------- */
293
294 static void dump_bytes(unsigned char *buf, unsigned int len)
295 {
296         unsigned int i;
297
298         for (i = 0; i < len; i++)
299                 printf(" %02x", buf[i]);
300         printf("\n");
301 }
302
303 static void dump_junk(unsigned char *buf, const char *indent, unsigned int len)
304 {
305         unsigned int i;
306
307         if (buf[0] <= len)
308                 return;
309         printf("%sjunk at descriptor end:", indent);
310         for (i = len; i < buf[0]; i++)
311                 printf(" %02x", buf[i]);
312         printf("\n");
313 }
314
315 /*
316  * General config descriptor dump
317  */
318
319 static void dump_device(
320         struct usb_dev_handle *dev,
321         struct usb_device_descriptor *descriptor
322 )
323 {
324         char vendor[128], product[128];
325         char cls[128], subcls[128], proto[128];
326         char mfg[128], prod[128], serial[128];
327
328         get_vendor_string(vendor, sizeof(vendor), descriptor->idVendor);
329         get_product_string(product, sizeof(product),
330                         descriptor->idVendor, descriptor->idProduct);
331         get_class_string(cls, sizeof(cls), descriptor->bDeviceClass);
332         get_subclass_string(subcls, sizeof(subcls),
333                         descriptor->bDeviceClass, descriptor->bDeviceSubClass);
334         get_protocol_string(proto, sizeof(proto), descriptor->bDeviceClass,
335                         descriptor->bDeviceSubClass, descriptor->bDeviceProtocol);
336         get_string(dev, mfg, sizeof(mfg), descriptor->iManufacturer);
337         get_string(dev, prod, sizeof(prod), descriptor->iProduct);
338         get_string(dev, serial, sizeof(serial), descriptor->iSerialNumber);
339         printf("Device Descriptor:\n"
340                "  bLength             %5u\n"
341                "  bDescriptorType     %5u\n"
342                "  bcdUSB              %2x.%02x\n"
343                "  bDeviceClass        %5u %s\n"
344                "  bDeviceSubClass     %5u %s\n"
345                "  bDeviceProtocol     %5u %s\n"
346                "  bMaxPacketSize0     %5u\n"
347                "  idVendor           0x%04x %s\n"
348                "  idProduct          0x%04x %s\n"
349                "  bcdDevice           %2x.%02x\n"
350                "  iManufacturer       %5u %s\n"
351                "  iProduct            %5u %s\n"
352                "  iSerial             %5u %s\n"
353                "  bNumConfigurations  %5u\n",
354                descriptor->bLength, descriptor->bDescriptorType,
355                descriptor->bcdUSB >> 8, descriptor->bcdUSB & 0xff,
356                descriptor->bDeviceClass, cls,
357                descriptor->bDeviceSubClass, subcls,
358                descriptor->bDeviceProtocol, proto,
359                descriptor->bMaxPacketSize0,
360                descriptor->idVendor, vendor, descriptor->idProduct, product,
361                descriptor->bcdDevice >> 8, descriptor->bcdDevice & 0xff,
362                descriptor->iManufacturer, mfg,
363                descriptor->iProduct, prod,
364                descriptor->iSerialNumber, serial,
365                descriptor->bNumConfigurations);
366 }
367
368 static void dump_wire_adapter(unsigned char *buf)
369 {
370
371         printf( "      Wire Adapter Class Descriptor:\n"
372                 "        bLength             %5u\n"
373                 "        bDescriptorType     %5u\n"
374                 "        bcdWAVersion        %2x.%02x\n"
375                 "        bNumPorts           %5u\n"
376                 "        bmAttributes        %5u\n"
377                 "        wNumRPRipes         %5u\n"
378                 "        wRPipeMaxBlock      %5u\n"
379                 "        bRPipeBlockSize     %5u\n"
380                 "        bPwrOn2PwrGood      %5u\n"
381                 "        bNumMMCIEs          %5u\n"
382                 "        DeviceRemovable     %5u\n",
383                 buf[0], buf[1], buf[3],
384                 buf[2], buf[4], buf[5],
385                 ( buf[6] | buf[7] << 8 ),
386                 ( buf[8] | buf[9] << 8 ),
387                 buf[10], buf[11], buf[12], buf[13]);
388 }
389
390 static void dump_rc_interface(unsigned char *buf)
391 {
392         printf( "      Radio Control Interface Class Descriptor:\n"
393                 "        bLength             %5u\n"
394                 "        bDescriptorType     %5u\n"
395                 "        bcdRCIVersion       %2x.%02x\n",
396                 buf[0], buf[1], buf[3], buf[2]);
397
398 }
399
400 static void dump_security(unsigned char *buf)
401 {
402         printf( "    Security Descriptor:\n"
403                 "      bLength             %5u\n"
404                 "      bDescriptorType     %5u\n"
405                 "      wTotalLength        %5u\n"
406                 "      bNumEncryptionTypes %5u\n",
407                 buf[0], buf[1],
408                 (buf[3]<< 8 | buf[2]),
409                 buf[4]);
410 }
411
412 static void dump_encryption_type(unsigned char *buf)
413 {
414         int b_encryption_type = buf[2] & 0x4;
415
416         printf( "    Encryption Type Descriptor:\n"
417                 "      bLength             %5u\n"
418                 "      bDescriptorType     %5u\n"
419                 "      bEncryptionType     %5u %s\n"
420                 "      bEncryptionValue    %5u\n"
421                 "      bAuthKeyIndex       %5u\n",
422                 buf[0], buf[1],
423                 buf[2], encryption_type[b_encryption_type],
424                 buf[3], buf[4]);
425 }
426
427 static void dump_association(struct usb_dev_handle *dev, unsigned char *buf)
428 {
429         char cls[128], subcls[128], proto[128];
430         char func[128];
431
432         get_class_string(cls, sizeof(cls), buf[4]);
433         get_subclass_string(subcls, sizeof(subcls), buf[4], buf[5]);
434         get_protocol_string(proto, sizeof(proto), buf[4], buf[5], buf[6]);
435         get_string(dev, func, sizeof(func), buf[7]);
436         printf("    Interface Association:\n"
437                "      bLength             %5u\n"
438                "      bDescriptorType     %5u\n"
439                "      bFirstInterface     %5u\n"
440                "      bInterfaceCount     %5u\n"
441                "      bFunctionClass      %5u %s\n"
442                "      bFunctionSubClass   %5u %s\n"
443                "      bFunctionProtocol   %5u %s\n"
444                "      iFunction           %5u %s\n",
445                buf[0], buf[1],
446                buf[2], buf[3],
447                buf[4], cls,
448                buf[5], subcls,
449                buf[6], proto,
450                buf[7], func);
451 }
452
453 static void dump_config(struct usb_dev_handle *dev, struct usb_config_descriptor *config)
454 {
455         char cfg[128];
456         int i;
457
458         get_string(dev, cfg, sizeof(cfg), config->iConfiguration);
459         printf("  Configuration Descriptor:\n"
460                "    bLength             %5u\n"
461                "    bDescriptorType     %5u\n"
462                "    wTotalLength        %5u\n"
463                "    bNumInterfaces      %5u\n"
464                "    bConfigurationValue %5u\n"
465                "    iConfiguration      %5u %s\n"
466                "    bmAttributes         0x%02x\n",
467                config->bLength, config->bDescriptorType,
468                le16_to_cpu(config->wTotalLength),
469                config->bNumInterfaces, config->bConfigurationValue,
470                config->iConfiguration,
471                cfg, config->bmAttributes);
472         if (!(config->bmAttributes & 0x80))
473                 printf("      (Missing must-be-set bit!)\n");
474         if (config->bmAttributes & 0x40)
475                 printf("      Self Powered\n");
476         else
477                 printf("      (Bus Powered)\n");
478         if (config->bmAttributes & 0x20)
479                 printf("      Remote Wakeup\n");
480         if (config->bmAttributes & 0x10)
481                 printf("      Battery Powered\n");
482         printf("    MaxPower            %5umA\n", config->MaxPower * 2);
483
484         /* avoid re-ordering or hiding descriptors for display */
485         if (config->extralen) {
486                 int             size = config->extralen;
487                 unsigned char   *buf = config->extra;
488
489                 while (size >= 2) {
490                         if (buf[0] < 2) {
491                                 dump_junk(buf, "        ", size);
492                                 break;
493                         }
494                         switch (buf[1]) {
495                         case USB_DT_OTG:
496                                 /* handled separately */
497                                 break;
498                         case USB_DT_INTERFACE_ASSOCIATION:
499                                 dump_association(dev, buf);
500                                 break;
501                         case USB_DT_SECURITY:
502                                 dump_security(buf);
503                                 break;
504                         case USB_DT_ENCRYPTION_TYPE:
505                                 dump_encryption_type(buf);
506                                 break;
507                         default:
508                                 /* often a misplaced class descriptor */
509                                 printf("    ** UNRECOGNIZED: ");
510                                 dump_bytes(buf, buf[0]);
511                                 break;
512                         }
513                         size -= buf[0];
514                         buf += buf[0];
515                 }
516         }
517         for (i = 0 ; i < config->bNumInterfaces ; i++)
518                 dump_interface(dev, &config->interface[i]);
519 }
520
521 static void dump_altsetting(struct usb_dev_handle *dev, struct usb_interface_descriptor *interface)
522 {
523         char cls[128], subcls[128], proto[128];
524         char ifstr[128];
525
526         unsigned char *buf;
527         unsigned size, i;
528
529         get_class_string(cls, sizeof(cls), interface->bInterfaceClass);
530         get_subclass_string(subcls, sizeof(subcls), interface->bInterfaceClass, interface->bInterfaceSubClass);
531         get_protocol_string(proto, sizeof(proto), interface->bInterfaceClass, interface->bInterfaceSubClass, interface->bInterfaceProtocol);
532         get_string(dev, ifstr, sizeof(ifstr), interface->iInterface);
533         printf("    Interface Descriptor:\n"
534                "      bLength             %5u\n"
535                "      bDescriptorType     %5u\n"
536                "      bInterfaceNumber    %5u\n"
537                "      bAlternateSetting   %5u\n"
538                "      bNumEndpoints       %5u\n"
539                "      bInterfaceClass     %5u %s\n"
540                "      bInterfaceSubClass  %5u %s\n"
541                "      bInterfaceProtocol  %5u %s\n"
542                "      iInterface          %5u %s\n",
543                interface->bLength, interface->bDescriptorType, interface->bInterfaceNumber,
544                interface->bAlternateSetting, interface->bNumEndpoints, interface->bInterfaceClass, cls,
545                interface->bInterfaceSubClass, subcls, interface->bInterfaceProtocol, proto,
546                interface->iInterface, ifstr);
547
548         /* avoid re-ordering or hiding descriptors for display */
549         if (interface->extralen)
550         {
551                 size = interface->extralen;
552                 buf = interface->extra;
553                 while (size >= 2 * sizeof(u_int8_t))
554                 {
555                         if (buf[0] < 2) {
556                                 dump_junk(buf, "      ", size);
557                                 break;
558                         }
559
560                         switch (buf[1]) {
561
562                         /* This is the polite way to provide class specific
563                          * descriptors: explicitly tagged, using common class
564                          * spec conventions.
565                          */
566                         case USB_DT_CS_DEVICE:
567                         case USB_DT_CS_INTERFACE:
568                                 switch (interface->bInterfaceClass) {
569                                 case USB_CLASS_AUDIO:
570                                         switch (interface->bInterfaceSubClass) {
571                                         case 1:
572                                                 dump_audiocontrol_interface(dev, buf);
573                                                 break;
574                                         case 2:
575                                                 dump_audiostreaming_interface(buf);
576                                                 break;
577                                         case 3:
578                                                 dump_midistreaming_interface(dev, buf);
579                                                 break;
580                                         default:
581                                                 goto dump;
582                                         }
583                                         break;
584                                 case USB_CLASS_COMM:
585                                         dump_comm_descriptor(dev, buf,
586                                                 "      ");
587                                         break;
588                                 case USB_CLASS_VIDEO:
589                                         switch (interface->bInterfaceSubClass) {
590                                         case 1:
591                                                 dump_videocontrol_interface(dev, buf);
592                                                 break;
593                                         case 2:
594                                                 dump_videostreaming_interface(buf);
595                                                 break;
596                                         default:
597                                                 goto dump;
598                                         }
599                                         break;
600                                 case USB_CLASS_APPLICATION:
601                                         switch (interface->bInterfaceSubClass) {
602                                         case 1:
603                                                 dump_dfu_interface(buf);
604                                                 break;
605                                         default:
606                                                 goto dump;
607                                         }
608                                         break;
609                                 case USB_CLASS_HID:
610                                         dump_hid_device(dev, interface, buf);
611                                         break;
612                                 case USB_CLASS_CCID:
613                                         dump_ccid_device(buf);
614                                         break;
615                                 default:
616                                         goto dump;
617                                 }
618                                 break;
619
620                         /* This is the ugly way:  implicitly tagged,
621                          * each class could redefine the type IDs.
622                          */
623                         default:
624                                 switch (interface->bInterfaceClass) {
625                                 case USB_CLASS_HID:
626                                         dump_hid_device(dev, interface, buf);
627                                         break;
628                                 case USB_CLASS_CCID:
629                                         dump_ccid_device(buf);
630                                         break;
631                                 case 0xe0:      /* wireless */
632                                         switch (interface->bInterfaceSubClass) {
633                                         case 1:
634                                                 switch (interface->bInterfaceProtocol) {
635                                                 case 2:
636                                                         dump_rc_interface(buf);
637                                                         break;
638                                                 default:
639                                                         goto dump;
640                                                 }
641                                                 break;
642                                         case 2:
643                                                 dump_wire_adapter(buf);
644                                                 break;
645                                         default:
646                                                 goto dump;
647                                         }
648                                         break;
649                                 default:
650                                         /* ... not everything is class-specific */
651                                         switch (buf[1]) {
652                                         case USB_DT_OTG:
653                                                 /* handled separately */
654                                                 break;
655                                         case USB_DT_INTERFACE_ASSOCIATION:
656                                                 dump_association(dev, buf);
657                                                 break;
658                                         default:
659 dump:
660                                                 /* often a misplaced class descriptor */
661                                                 printf("      ** UNRECOGNIZED: ");
662                                                 dump_bytes(buf, buf[0]);
663                                                 break;
664                                         }
665                                 }
666                         }
667                         size -= buf[0];
668                         buf += buf[0];
669                 }
670         }
671
672         for (i = 0 ; i < interface->bNumEndpoints ; i++)
673                 dump_endpoint(dev, interface, &interface->endpoint[i]);
674 }
675
676 static void dump_interface(struct usb_dev_handle *dev, struct usb_interface *interface)
677 {
678         int i;
679
680         for (i = 0; i < interface->num_altsetting; i++)
681                 dump_altsetting(dev, &interface->altsetting[i]);
682 }
683
684 static void dump_endpoint(struct usb_dev_handle *dev, struct usb_interface_descriptor *interface, struct usb_endpoint_descriptor *endpoint)
685 {
686         static const char *typeattr[] = { "Control", "Isochronous", "Bulk", "Interrupt" };
687         static const char *syncattr[] = { "None", "Asynchronous", "Adaptive", "Synchronous" };
688         static const char *usage[] = { "Data", "Feedback", "Implicit feedback Data", "(reserved)" };
689         static const char *hb[] = { "1x", "2x", "3x", "(?\?)" };
690         unsigned char *buf;
691         unsigned size;
692         unsigned wmax = le16_to_cpu(endpoint->wMaxPacketSize);
693
694         printf("      Endpoint Descriptor:\n"
695                "        bLength             %5u\n"
696                "        bDescriptorType     %5u\n"
697                "        bEndpointAddress     0x%02x  EP %u %s\n"
698                "        bmAttributes        %5u\n"
699                "          Transfer Type            %s\n"
700                "          Synch Type               %s\n"
701                "          Usage Type               %s\n"
702                "        wMaxPacketSize     0x%04x  %s %d bytes\n"
703                "        bInterval           %5u\n",
704                endpoint->bLength, endpoint->bDescriptorType, endpoint->bEndpointAddress, endpoint->bEndpointAddress & 0x0f,
705                (endpoint->bEndpointAddress & 0x80) ? "IN" : "OUT", endpoint->bmAttributes,
706                typeattr[endpoint->bmAttributes & 3], syncattr[(endpoint->bmAttributes >> 2) & 3],
707                usage[(endpoint->bmAttributes >> 4) & 3],
708                wmax, hb[(wmax >> 11) & 3], wmax & 0x7ff,
709                endpoint->bInterval);
710         /* only for audio endpoints */
711         if (endpoint->bLength == 9)
712         printf("        bRefresh            %5u\n"
713                "        bSynchAddress       %5u\n",
714                endpoint->bRefresh, endpoint->bSynchAddress);
715
716         /* avoid re-ordering or hiding descriptors for display */
717         if (endpoint->extralen)
718         {
719                 size = endpoint->extralen;
720                 buf = endpoint->extra;
721                 while (size >= 2 * sizeof(u_int8_t))
722                 {
723                         if (buf[0] < 2) {
724                                 dump_junk(buf, "        ", size);
725                                 break;
726                         }
727                         switch (buf[1]) {
728                         case USB_DT_CS_ENDPOINT:
729                                 if (interface->bInterfaceClass == 1 && interface->bInterfaceSubClass == 2)
730                                         dump_audiostreaming_endpoint(buf);
731                                 else if (interface->bInterfaceClass == 1 && interface->bInterfaceSubClass == 3)
732                                         dump_midistreaming_endpoint(buf);
733                                 break;
734                         case USB_DT_CS_INTERFACE:
735                                 /* MISPLACED DESCRIPTOR ... less indent */
736                                 switch (interface->bInterfaceClass) {
737                                 case USB_CLASS_COMM:
738                                 case USB_CLASS_DATA:    // comm data
739                                         dump_comm_descriptor(dev, buf,
740                                                 "      ");
741                                         break;
742                                 default:
743                                         printf("        INTERFACE CLASS: ");
744                                         dump_bytes(buf, buf[0]);
745                                 }
746                                 break;
747                         case USB_DT_OTG:
748                                 /* handled separately */
749                                 break;
750                         case USB_DT_INTERFACE_ASSOCIATION:
751                                 dump_association(dev, buf);
752                                 break;
753                         default:
754                                 /* often a misplaced class descriptor */
755                                 printf("        ** UNRECOGNIZED: ");
756                                 dump_bytes(buf, buf[0]);
757                                 break;
758                         }
759                         size -= buf[0];
760                         buf += buf[0];
761                 }
762         }
763 }
764
765 static void dump_unit(unsigned int data, unsigned int len)
766 {
767         char *systems[5] = { "None", "SI Linear", "SI Rotation",
768                         "English Linear", "English Rotation" };
769
770         char *units[5][8] = {
771                 { "None", "None", "None", "None", "None",
772                                 "None", "None", "None" },
773                 { "None", "Centimeter", "Gram", "Seconds", "Kelvin",
774                                 "Ampere", "Candela", "None" },
775                 { "None", "Radians",    "Gram", "Seconds", "Kelvin",
776                                 "Ampere", "Candela", "None" },
777                 { "None", "Inch",       "Slug", "Seconds", "Fahrenheit",
778                                 "Ampere", "Candela", "None" },
779                 { "None", "Degrees",    "Slug", "Seconds", "Fahrenheit",
780                                 "Ampere", "Candela", "None" },
781         };
782
783         unsigned int i;
784         unsigned int sys;
785         int earlier_unit = 0;
786
787         /* First nibble tells us which system we're in. */
788         sys = data & 0xf;
789         data >>= 4;
790
791         if(sys > 4) {
792                 if(sys == 0xf)
793                         printf("System: Vendor defined, Unit: (unknown)\n");
794                 else
795                         printf("System: Reserved, Unit: (unknown)\n");
796                 return;
797         } else {
798                 printf("System: %s, Unit: ", systems[sys]);
799         }
800         for (i=1 ; i<len*2 ; i++) {
801                 char nibble = data & 0xf;
802                 data >>= 4;
803                 if (nibble != 0) {
804                         if(earlier_unit++ > 0)
805                                 printf("*");
806                         printf("%s", units[sys][i]);
807                         if(nibble != 1) {
808                                 /* This is a _signed_ nibble(!) */
809
810                                 int val = nibble & 0x7;
811                                 if(nibble & 0x08)
812                                         val = -((0x7 & ~val) +1);
813                                 printf("^%d", val);
814                         }
815                 }
816         }
817         if(earlier_unit == 0)
818                 printf("(None)");
819         printf("\n");
820 }
821
822 /* ---------------------------------------------------------------------- */
823
824 /*
825  * Audio Class descriptor dump
826  */
827
828 static void dump_audiocontrol_interface(struct usb_dev_handle *dev, unsigned char *buf)
829 {
830         static const char *chconfig[] = {
831                 "Left Front (L)", "Right Front (R)", "Center Front (C)", "Low Freqency Enhancement (LFE)",
832                 "Left Surround (LS)", "Right Surround (RS)", "Left of Center (LC)", "Right of Center (RC)",
833                 "Surround (S)", "Side Left (SL)", "Side Right (SR)", "Top (T)"
834         };
835         static const char *chftrcontrols[] = {
836                 "Mute", "Volume", "Bass", "Mid", "Treble", "Graphic Equalizer", "Automatic Gain", "Delay", "Bass Boost", "Loudness"
837         };
838         unsigned int i, chcfg, j, k, N, termt;
839         char chnames[128], term[128], termts[128];
840
841         if (buf[1] != USB_DT_CS_INTERFACE)
842                 printf("      Warning: Invalid descriptor\n");
843         else if (buf[0] < 3)
844                 printf("      Warning: Descriptor too short\n");
845         printf("      AudioControl Interface Descriptor:\n"
846                "        bLength             %5u\n"
847                "        bDescriptorType     %5u\n"
848                "        bDescriptorSubtype  %5u ",
849                buf[0], buf[1], buf[2]);
850         switch (buf[2]) {
851         case 0x01:  /* HEADER */
852                 printf("(HEADER)\n");
853                 if (buf[0] < 8+buf[7])
854                         printf("      Warning: Descriptor too short\n");
855                 printf("        bcdADC              %2x.%02x\n"
856                        "        wTotalLength        %5u\n"
857                        "        bInCollection       %5u\n",
858                        buf[4], buf[3], buf[5] | (buf[6] << 8), buf[7]);
859                 for(i = 0; i < buf[7]; i++)
860                         printf("        baInterfaceNr(%2u)   %5u\n", i, buf[8+i]);
861                 dump_junk(buf, "        ", 8+buf[7]);
862                 break;
863
864         case 0x02:  /* INPUT_TERMINAL */
865                 printf("(INPUT_TERMINAL)\n");
866                 get_string(dev, chnames, sizeof(chnames), buf[10]);
867                 get_string(dev, term, sizeof(term), buf[11]);
868                 termt = buf[4] | (buf[5] << 8);
869                 get_audioterminal_string(termts, sizeof(termts), termt);
870                 if (buf[0] < 12)
871                         printf("      Warning: Descriptor too short\n");
872                 chcfg = buf[8] | (buf[9] << 8);
873                 printf("        bTerminalID         %5u\n"
874                        "        wTerminalType      0x%04x %s\n"
875                        "        bAssocTerminal      %5u\n"
876                        "        bNrChannels         %5u\n"
877                        "        wChannelConfig     0x%04x\n",
878                        buf[3], termt, termts, buf[6], buf[7], chcfg);
879                 for (i = 0; i < 12; i++)
880                         if ((chcfg >> i) & 1)
881                                 printf("          %s\n", chconfig[i]);
882                 printf("        iChannelNames       %5u %s\n"
883                        "        iTerminal           %5u %s\n",
884                        buf[10], chnames, buf[11], term);
885                 dump_junk(buf, "        ", 12);
886                 break;
887
888         case 0x03:  /* OUTPUT_TERMINAL */
889                 printf("(OUTPUT_TERMINAL)\n");
890                 get_string(dev, term, sizeof(term), buf[8]);
891                 termt = buf[4] | (buf[5] << 8);
892                 get_audioterminal_string(termts, sizeof(termts), termt);
893                 if (buf[0] < 9)
894                         printf("      Warning: Descriptor too short\n");
895                 printf("        bTerminalID         %5u\n"
896                        "        wTerminalType      0x%04x %s\n"
897                        "        bAssocTerminal      %5u\n"
898                        "        bSourceID           %5u\n"
899                        "        iTerminal           %5u %s\n",
900                        buf[3], termt, termts, buf[6], buf[7], buf[8], term);
901                 dump_junk(buf, "        ", 9);
902                 break;
903
904         case 0x04:  /* MIXER_UNIT */
905                 printf("(MIXER_UNIT)\n");
906                 j = buf[4];
907                 k = buf[j+5];
908                 if (j == 0 || k == 0) {
909                   printf("      Warning: mixer with %5u input and %5u output channels.\n", j, k);
910                   N = 0;
911                 } else {
912                   N = 1+(j*k-1)/8;
913                 }
914                 get_string(dev, chnames, sizeof(chnames), buf[8+j]);
915                 get_string(dev, term, sizeof(term), buf[9+j+N]);
916                 if (buf[0] < 10+j+N)
917                         printf("      Warning: Descriptor too short\n");
918                 chcfg = buf[6+j] | (buf[7+j] << 8);
919                 printf("        bUnitID             %5u\n"
920                        "        bNrInPins           %5u\n",
921                        buf[3], buf[4]);
922                 for (i = 0; i < j; i++)
923                         printf("        baSourceID(%2u)      %5u\n", i, buf[5+i]);
924                 printf("        bNrChannels         %5u\n"
925                        "        wChannelConfig     0x%04x\n",
926                        buf[5+j], chcfg);
927                 for (i = 0; i < 12; i++)
928                         if ((chcfg >> i) & 1)
929                                 printf("          %s\n", chconfig[i]);
930                 printf("        iChannelNames       %5u %s\n",
931                        buf[8+j], chnames);
932                 for (i = 0; i < N; i++)
933                         printf("        bmControls         0x%02x\n", buf[9+j+i]);
934                 printf("        iMixer              %5u %s\n", buf[9+j+N], term);
935                 dump_junk(buf, "        ", 10+j+N);
936                 break;
937
938         case 0x05:  /* SELECTOR_UNIT */
939                 printf("(SELECTOR_UNIT)\n");
940                 if (buf[0] < 6+buf[4])
941                         printf("      Warning: Descriptor too short\n");
942                 get_string(dev, term, sizeof(term), buf[5+buf[4]]);
943
944                 printf("        bUnitID             %5u\n"
945                        "        bNrInPins           %5u\n",
946                        buf[3], buf[4]);
947                 for (i = 0; i < buf[4]; i++)
948                         printf("        baSource(%2u)        %5u\n", i, buf[5+i]);
949                 printf("        iSelector           %5u %s\n",
950                        buf[5+buf[4]], term);
951                 dump_junk(buf, "        ", 6+buf[4]);
952                 break;
953
954         case 0x06:  /* FEATURE_UNIT */
955                 printf("(FEATURE_UNIT)\n");
956                 j = buf[5];
957                 if (!j)
958                         j = 1;
959                 k = (buf[0] - 7) / j;
960                 if (buf[0] < 7+buf[5]*k)
961                         printf("      Warning: Descriptor too short\n");
962                 get_string(dev, term, sizeof(term), buf[6+buf[5]*k]);
963                 printf("        bUnitID             %5u\n"
964                        "        bSourceID           %5u\n"
965                        "        bControlSize        %5u\n",
966                        buf[3], buf[4], buf[5]);
967                 for (i = 0; i < k; i++) {
968                         chcfg = buf[6+buf[5]*i];
969                         if (buf[5] > 1)
970                                 chcfg |= (buf[7+buf[5]*i] << 8);
971                         for (j = 0; j < buf[5]; j++)
972                                 printf("        bmaControls(%2u)      0x%02x\n", i, buf[6+buf[5]*i+j]);
973                         for (j = 0; j < 10; j++)
974                                 if ((chcfg >> j) & 1)
975                                         printf("          %s\n", chftrcontrols[j]);
976                 }
977                 printf("        iFeature            %5u %s\n", buf[6+buf[5]*k], term);
978                 dump_junk(buf, "        ", 7+buf[5]*k);
979                 break;
980
981         case 0x07:  /* PROCESSING_UNIT */
982                 printf("(PROCESSING_UNIT)\n");
983                 j = buf[6];
984                 k = buf[11+j];
985                 get_string(dev, chnames, sizeof(chnames), buf[10+j]);
986                 get_string(dev, term, sizeof(term), buf[12+j+k]);
987                 chcfg = buf[8+j] | (buf[9+j] << 8);
988                 if (buf[0] < 13+j+k)
989                         printf("      Warning: Descriptor too short\n");
990                 printf("        bUnitID             %5u\n"
991                        "        wProcessType        %5u\n"
992                        "        bNrPins             %5u\n",
993                        buf[3], buf[4] | (buf[5] << 8), buf[6]);
994                 for (i = 0; i < j; i++)
995                         printf("        baSourceID(%2u)      %5u\n", i, buf[7+i]);
996                 printf("        bNrChannels         %5u\n"
997                        "        wChannelConfig     0x%04x\n", buf[7+j], chcfg);
998                 for (i = 0; i < 12; i++)
999                         if ((chcfg >> i) & 1)
1000                                 printf("          %s\n", chconfig[i]);
1001                 printf("        iChannelNames       %5u %s\n"
1002                        "        bControlSize        %5u\n", buf[10+j], chnames, buf[11+j]);
1003                 for (i = 0; i < k; i++)
1004                         printf("        bmControls(%2u)       0x%02x\n", i, buf[12+j+i]);
1005                 if (buf[12+j] & 1)
1006                         printf("          Enable Processing\n");
1007                 printf("        iProcessing         %5u %s\n"
1008                        "        Process-Specific    ", buf[12+j+k], term);
1009                 dump_bytes(buf+(13+j+k), buf[0]-(13+j+k));
1010                 break;
1011
1012         case 0x08:  /* EXTENSION_UNIT */
1013                 printf("(EXTENSION_UNIT)\n");
1014                 j = buf[6];
1015                 k = buf[11+j];
1016                 get_string(dev, chnames, sizeof(chnames), buf[10+j]);
1017                 get_string(dev, term, sizeof(term), buf[12+j+k]);
1018                 chcfg = buf[8+j] | (buf[9+j] << 8);
1019                 if (buf[0] < 13+j+k)
1020                         printf("      Warning: Descriptor too short\n");
1021                 printf("        bUnitID             %5u\n"
1022                        "        wExtensionCode      %5u\n"
1023                        "        bNrPins             %5u\n",
1024                        buf[3], buf[4] | (buf[5] << 8), buf[6]);
1025                 for (i = 0; i < j; i++)
1026                         printf("        baSourceID(%2u)      %5u\n", i, buf[7+i]);
1027                 printf("        bNrChannels         %5u\n"
1028                        "        wChannelConfig      %5u\n", buf[7+j], chcfg);
1029                 for (i = 0; i < 12; i++)
1030                         if ((chcfg >> i) & 1)
1031                                 printf("          %s\n", chconfig[i]);
1032                 printf("        iChannelNames       %5u %s\n"
1033                        "        bControlSize        %5u\n", buf[10+j], chnames, buf[11+j]);
1034                 for (i = 0; i < k; i++)
1035                         printf("        bmControls(%2u)       0x%02x\n", i, buf[12+j+i]);
1036                 if (buf[12+j] & 1)
1037                         printf("          Enable Processing\n");
1038                 printf("        iExtension          %5u %s\n",
1039                        buf[12+j+k], term);
1040                 dump_junk(buf, "        ", 13+j+k);
1041                 break;
1042
1043         default:
1044                 printf("(unknown)\n"
1045                        "        Invalid desc subtype:");
1046                 dump_bytes(buf+3, buf[0]-3);
1047                 break;
1048         }
1049 }
1050
1051 static void dump_audiostreaming_interface(unsigned char *buf)
1052 {
1053         static const char *fmtItag[] = {
1054                 "TYPE_I_UNDEFINED", "PCM", "PCM8", "IEEE_FLOAT", "ALAW", "MULAW" };
1055         static const char *fmtIItag[] = { "TYPE_II_UNDEFINED", "MPEG", "AC-3" };
1056         static const char *fmtIIItag[] = {
1057                 "TYPE_III_UNDEFINED", "IEC1937_AC-3", "IEC1937_MPEG-1_Layer1",
1058                 "IEC1937_MPEG-Layer2/3/NOEXT", "IEC1937_MPEG-2_EXT",
1059                 "IEC1937_MPEG-2_Layer1_LS", "IEC1937_MPEG-2_Layer2/3_LS" };
1060         unsigned int i, j, fmttag;
1061         const char *fmtptr = "undefined";
1062
1063         if (buf[1] != USB_DT_CS_INTERFACE)
1064                 printf("      Warning: Invalid descriptor\n");
1065         else if (buf[0] < 3)
1066                 printf("      Warning: Descriptor too short\n");
1067         printf("      AudioStreaming Interface Descriptor:\n"
1068                "        bLength             %5u\n"
1069                "        bDescriptorType     %5u\n"
1070                "        bDescriptorSubtype  %5u ",
1071                buf[0], buf[1], buf[2]);
1072         switch (buf[2]) {
1073         case 0x01: /* AS_GENERAL */
1074                 printf("(AS_GENERAL)\n");
1075                 if (buf[0] < 7)
1076                         printf("      Warning: Descriptor too short\n");
1077                 fmttag = buf[5] | (buf[6] << 8);
1078                 if (fmttag <= 5)
1079                         fmtptr = fmtItag[fmttag];
1080                 else if (fmttag >= 0x1000 && fmttag <= 0x1002)
1081                         fmtptr = fmtIItag[fmttag & 0xfff];
1082                 else if (fmttag >= 0x2000 && fmttag <= 0x2006)
1083                         fmtptr = fmtIIItag[fmttag & 0xfff];
1084                 printf("        bTerminalLink       %5u\n"
1085                        "        bDelay              %5u frames\n"
1086                        "        wFormatTag          %5u %s\n",
1087                        buf[3], buf[4], fmttag, fmtptr);
1088                 dump_junk(buf, "        ", 7);
1089                 break;
1090
1091         case 0x02: /* FORMAT_TYPE */
1092                 printf("(FORMAT_TYPE)\n");
1093                 if (buf[0] < 8)
1094                         printf("      Warning: Descriptor too short\n");
1095                 printf("        bFormatType         %5u ", buf[3]);
1096                 switch (buf[3]) {
1097                 case 0x01: /* FORMAT_TYPE_I */
1098                         printf("(FORMAT_TYPE_I)\n");
1099                         j = buf[7] ? (buf[7]*3+8) : 14;
1100                         if (buf[0] < j)
1101                                 printf("      Warning: Descriptor too short\n");
1102                         printf("        bNrChannels         %5u\n"
1103                                "        bSubframeSize       %5u\n"
1104                                "        bBitResolution      %5u\n"
1105                                "        bSamFreqType        %5u %s\n",
1106                                buf[4], buf[5], buf[6], buf[7], buf[7] ? "Discrete" : "Continuous");
1107                         if (!buf[7])
1108                                 printf("        tLowerSamFreq     %7u\n"
1109                                        "        tUpperSamFreq     %7u\n",
1110                                        buf[8] | (buf[9] << 8) | (buf[10] << 16), buf[11] | (buf[12] << 8) | (buf[13] << 16));
1111                         else
1112                                 for (i = 0; i < buf[7]; i++)
1113                                         printf("        tSamFreq[%2u]      %7u\n", i,
1114                                                buf[8+3*i] | (buf[9+3*i] << 8) | (buf[10+3*i] << 16));
1115                         dump_junk(buf, "        ", j);
1116                         break;
1117
1118                 case 0x02: /* FORMAT_TYPE_II */
1119                         printf("(FORMAT_TYPE_II)\n");
1120                         j = buf[8] ? (buf[7]*3+9) : 15;
1121                         if (buf[0] < j)
1122                                 printf("      Warning: Descriptor too short\n");
1123                         printf("        wMaxBitRate         %5u\n"
1124                                "        wSamplesPerFrame    %5u\n"
1125                                "        bSamFreqType        %5u %s\n",
1126                                buf[4] | (buf[5] << 8), buf[6] | (buf[7] << 8), buf[8], buf[8] ? "Discrete" : "Continuous");
1127                         if (!buf[8])
1128                                 printf("        tLowerSamFreq     %7u\n"
1129                                        "        tUpperSamFreq     %7u\n",
1130                                        buf[9] | (buf[10] << 8) | (buf[11] << 16), buf[12] | (buf[13] << 8) | (buf[14] << 16));
1131                         else
1132                                 for (i = 0; i < buf[8]; i++)
1133                                         printf("        tSamFreq[%2u]      %7u\n", i,
1134                                                buf[9+3*i] | (buf[10+3*i] << 8) | (buf[11+3*i] << 16));
1135                         dump_junk(buf, "        ", j);
1136                         break;
1137
1138                 case 0x03: /* FORMAT_TYPE_III */
1139                         printf("(FORMAT_TYPE_III)\n");
1140                         j = buf[7] ? (buf[7]*3+8) : 14;
1141                         if (buf[0] < j)
1142                                 printf("      Warning: Descriptor too short\n");
1143                         printf("        bNrChannels         %5u\n"
1144                                "        bSubframeSize       %5u\n"
1145                                "        bBitResolution      %5u\n"
1146                                "        bSamFreqType        %5u %s\n",
1147                                buf[4], buf[5], buf[6], buf[7], buf[7] ? "Discrete" : "Continuous");
1148                         if (!buf[7])
1149                                 printf("        tLowerSamFreq     %7u\n"
1150                                        "        tUpperSamFreq     %7u\n",
1151                                        buf[8] | (buf[9] << 8) | (buf[10] << 16), buf[11] | (buf[12] << 8) | (buf[13] << 16));
1152                         else
1153                                 for (i = 0; i < buf[7]; i++)
1154                                         printf("        tSamFreq[%2u]      %7u\n", i,
1155                                                buf[8+3*i] | (buf[9+3*i] << 8) | (buf[10+3*i] << 16));
1156                         dump_junk(buf, "        ", j);
1157                         break;
1158
1159                 default:
1160                         printf("(unknown)\n"
1161                                "        Invalid desc format type:");
1162                         dump_bytes(buf+4, buf[0]-4);
1163                 }
1164                 break;
1165
1166         case 0x03: /* FORMAT_SPECIFIC */
1167                 printf("(FORMAT_SPECIFIC)\n");
1168                 if (buf[0] < 5)
1169                         printf("      Warning: Descriptor too short\n");
1170                 fmttag = buf[3] | (buf[4] << 8);
1171                 if (fmttag <= 5)
1172                         fmtptr = fmtItag[fmttag];
1173                 else if (fmttag >= 0x1000 && fmttag <= 0x1002)
1174                         fmtptr = fmtIItag[fmttag & 0xfff];
1175                 else if (fmttag >= 0x2000 && fmttag <= 0x2006)
1176                         fmtptr = fmtIIItag[fmttag & 0xfff];
1177                 printf("        wFormatTag          %5u %s\n", fmttag, fmtptr);
1178                 switch (fmttag) {
1179                 case 0x1001: /* MPEG */
1180                         if (buf[0] < 8)
1181                                 printf("      Warning: Descriptor too short\n");
1182                         printf("        bmMPEGCapabilities 0x%04x\n",
1183                                buf[5] | (buf[6] << 8));
1184                         if (buf[5] & 0x01)
1185                                 printf("          Layer I\n");
1186                         if (buf[5] & 0x02)
1187                                 printf("          Layer II\n");
1188                         if (buf[5] & 0x04)
1189                                 printf("          Layer III\n");
1190                         if (buf[5] & 0x08)
1191                                 printf("          MPEG-1 only\n");
1192                         if (buf[5] & 0x10)
1193                                 printf("          MPEG-1 dual-channel\n");
1194                         if (buf[5] & 0x20)
1195                                 printf("          MPEG-2 second stereo\n");
1196                         if (buf[5] & 0x40)
1197                                 printf("          MPEG-2 7.1 channel augmentation\n");
1198                         if (buf[5] & 0x80)
1199                                 printf("          Adaptive multi-channel prediction\n");
1200                         printf("          MPEG-2 multilingual support: ");
1201                         switch (buf[6] & 3) {
1202                         case 0:
1203                                 printf("Not supported\n");
1204                                 break;
1205
1206                         case 1:
1207                                 printf("Supported at Fs\n");
1208                                 break;
1209
1210                         case 2:
1211                                 printf("Reserved\n");
1212                                 break;
1213
1214                         default:
1215                                 printf("Supported at Fs and 1/2Fs\n");
1216                                 break;
1217                         }
1218                         printf("        bmMPEGFeatures       0x%02x\n", buf[7]);
1219                         printf("          Internal Dynamic Range Control: ");
1220                         switch ((buf[7] << 4) & 3) {
1221                         case 0:
1222                                 printf("not supported\n");
1223                                 break;
1224
1225                         case 1:
1226                                 printf("supported but not scalable\n");
1227                                 break;
1228
1229                         case 2:
1230                                 printf("scalable, common boost and cut scaling value\n");
1231                                 break;
1232
1233                         default:
1234                                 printf("scalable, separate boost and cut scaling value\n");
1235                                 break;
1236                         }
1237                         dump_junk(buf, "        ", 8);
1238                         break;
1239
1240                 case 0x1002: /* AC-3 */
1241                         if (buf[0] < 10)
1242                                 printf("      Warning: Descriptor too short\n");
1243                         printf("        bmBSID         0x%08x\n"
1244                                "        bmAC3Features        0x%02x\n",
1245                                buf[5] | (buf[6] << 8) | (buf[7] << 16) | (buf[8] << 24), buf[9]);
1246                         if (buf[9] & 0x0)
1247                                 printf("          RF mode\n");
1248                         if (buf[9] & 0x0)
1249                                 printf("          Line mode\n");
1250                         if (buf[9] & 0x0)
1251                                 printf("          Custom0 mode\n");
1252                         if (buf[9] & 0x0)
1253                                 printf("          Custom1 mode\n");
1254                         printf("          Internal Dynamic Range Control: ");
1255                         switch ((buf[9] >> 4) & 3) {
1256                         case 0:
1257                                 printf("not supported\n");
1258                                 break;
1259
1260                         case 1:
1261                                 printf("supported but not scalable\n");
1262                                 break;
1263
1264                         case 2:
1265                                 printf("scalable, common boost and cut scaling value\n");
1266                                 break;
1267
1268                         default:
1269                                 printf("scalable, separate boost and cut scaling value\n");
1270                                 break;
1271                         }
1272                         dump_junk(buf, "        ", 8);
1273                         break;
1274
1275                 default:
1276                         printf("(unknown)\n"
1277                                "        Invalid desc format type:");
1278                         dump_bytes(buf+4, buf[0]-4);
1279                 }
1280                 break;
1281
1282         default:
1283                 printf("        Invalid desc subtype:");
1284                 dump_bytes(buf+3, buf[0]-3);
1285                 break;
1286         }
1287 }
1288
1289 static void dump_audiostreaming_endpoint(unsigned char *buf)
1290 {
1291         static const char *lockdelunits[] = { "Undefined", "Milliseconds", "Decoded PCM samples", "Reserved" };
1292         unsigned int lckdelidx;
1293
1294         if (buf[1] != USB_DT_CS_ENDPOINT)
1295                 printf("      Warning: Invalid descriptor\n");
1296         else if (buf[0] < 7)
1297                 printf("      Warning: Descriptor too short\n");
1298         printf("        AudioControl Endpoint Descriptor:\n"
1299                "          bLength             %5u\n"
1300                "          bDescriptorType     %5u\n"
1301                "          bDescriptorSubtype  %5u (%s)\n"
1302                "          bmAttributes         0x%02x\n",
1303                buf[0], buf[1], buf[2], buf[2] == 1 ? "EP_GENERAL" : "invalid", buf[3]);
1304         if (buf[3] & 1)
1305                 printf("            Sampling Frequency\n");
1306         if (buf[3] & 2)
1307                 printf("            Pitch\n");
1308         if (buf[3] & 128)
1309                 printf("            MaxPacketsOnly\n");
1310         lckdelidx = buf[4];
1311         if (lckdelidx > 3)
1312                 lckdelidx = 3;
1313         printf("          bLockDelayUnits     %5u %s\n"
1314                "          wLockDelay          %5u %s\n",
1315                buf[4], lockdelunits[lckdelidx], buf[5] | (buf[6] << 8), lockdelunits[lckdelidx]);
1316         dump_junk(buf, "        ", 7);
1317 }
1318
1319 static void dump_midistreaming_interface(struct usb_dev_handle *dev, unsigned char *buf)
1320 {
1321         static const char *jacktypes[] = {"Undefined", "Embedded", "External"};
1322         char jackstr[128];
1323         unsigned int j, tlength, capssize;
1324         unsigned long caps;
1325
1326         if (buf[1] != USB_DT_CS_INTERFACE)
1327                 printf("      Warning: Invalid descriptor\n");
1328         else if (buf[0] < 3)
1329                 printf("      Warning: Descriptor too short\n");
1330         printf( "      MIDIStreaming Interface Descriptor:\n"
1331                 "        bLength             %5u\n"
1332                 "        bDescriptorType     %5u\n"
1333                 "        bDescriptorSubtype  %5u ",
1334                 buf[0], buf[1], buf[2]);
1335         switch (buf[2]) {
1336         case 0x01:
1337                 printf("(HEADER)\n");
1338                 if (buf[0] < 7)
1339                         printf("      Warning: Descriptor too short\n");
1340                 tlength = buf[5] | (buf[6] << 8);
1341                 printf( "        bcdADC              %2x.%02x\n"
1342                         "        wTotalLength        %5u\n",
1343                         buf[4], buf[3], tlength);
1344                 dump_junk(buf, "        ", 7);
1345                 break;
1346
1347         case 0x02:
1348                 printf("(MIDI_IN_JACK)\n");
1349                 if (buf[0] < 6)
1350                         printf("      Warning: Descriptor too short\n");
1351                 get_string(dev, jackstr, sizeof(jackstr), buf[5]);
1352                 printf( "        bJackType           %5u %s\n"
1353                         "        bJackID             %5u\n"
1354                         "        iJack               %5u %s\n",
1355                         buf[3], buf[3] < 3 ? jacktypes[buf[3]] : "Invalid",
1356                         buf[4], buf[5], jackstr);
1357                 dump_junk(buf, "        ", 6);
1358                 break;
1359
1360         case 0x03:
1361                 printf("(MIDI_OUT_JACK)\n");
1362                 if (buf[0] < 9)
1363                         printf("      Warning: Descriptor too short\n");
1364                 printf( "        bJackType           %5u %s\n"
1365                         "        bJackID             %5u\n"
1366                         "        bNrInputPins        %5u\n",
1367                         buf[3], buf[3] < 3 ? jacktypes[buf[3]] : "Invalid",
1368                         buf[4], buf[5]);
1369                 for (j=0; j < buf[5]; j++) {
1370                         printf( "        baSourceID(%2u)      %5u\n"
1371                                 "        BaSourcePin(%2u)     %5u\n",
1372                                 j, buf[2*j+6], j, buf[2*j+7]);
1373                 }
1374                 j = 6+buf[5]*2; /* midi10.pdf says, incorrectly: 5+2*p */
1375                 get_string(dev, jackstr, sizeof(jackstr), buf[j]);
1376                 printf( "        iJack               %5u %s\n",
1377                         buf[j], jackstr);
1378                 dump_junk(buf, "        ", j+1);
1379                 break;
1380
1381         case 0x04:
1382                 printf("(ELEMENT)\n");
1383                 if (buf[0] < 12)
1384                         printf("      Warning: Descriptor too short\n");
1385                 printf( "        bElementID          %5u\n"
1386                         "        bNrInputPins        %5u\n",
1387                         buf[3], buf[4]);
1388                 for(j=0; j < buf[4]; j++) {
1389                 printf( "        baSourceID(%2u)      %5u\n"
1390                         "        BaSourcePin(%2u)     %5u\n",
1391                         j, buf[2*j+5], j, buf[2*j+6]);
1392                 }
1393                 j = 5+buf[4]*2;
1394                 printf( "        bNrOutputPins       %5u\n"
1395                         "        bInTerminalLink     %5u\n"
1396                         "        bOutTerminalLink    %5u\n"
1397                         "        bElCapsSize         %5u\n",
1398                         buf[j], buf[j+1], buf[j+2], buf[j+3]);
1399                 capssize = buf[j+3];
1400                 caps = 0;
1401                 for(j=0; j < capssize; j++) {
1402                         caps |= (buf[j+9+buf[4]*2] << (8*j));
1403                 }
1404                 printf( "        bmElementCaps  0x%08lx\n", caps);
1405                 if (caps & 0x01)
1406                         printf( "          Undefined\n");
1407                 if (caps & 0x02)
1408                         printf( "          MIDI Clock\n");
1409                 if (caps & 0x04)
1410                         printf( "          MTC (MIDI Time Code)\n");
1411                 if (caps & 0x08)
1412                         printf( "          MMC (MIDI Machine Control)\n");
1413                 if (caps & 0x10)
1414                         printf( "          GM1 (General MIDI v.1)\n");
1415                 if (caps & 0x20)
1416                         printf( "          GM2 (General MIDI v.2)\n");
1417                 if (caps & 0x40)
1418                         printf( "          GS MIDI Extension\n");
1419                 if (caps & 0x80)
1420                         printf( "          XG MIDI Extension\n");
1421                 if (caps & 0x100)
1422                         printf( "          EFX\n");
1423                 if (caps & 0x200)
1424                         printf( "          MIDI Patch Bay\n");
1425                 if (caps & 0x400)
1426                         printf( "          DLS1 (Downloadable Sounds Level 1)\n");
1427                 if (caps & 0x800)
1428                         printf( "          DLS2 (Downloadable Sounds Level 2)\n");
1429                 j = 9+2*buf[4]+capssize;
1430                 get_string(dev, jackstr, sizeof(jackstr), buf[j]);
1431                 printf( "        iElement            %5u %s\n", buf[j], jackstr);
1432                 dump_junk(buf, "        ", j+1);
1433                 break;
1434
1435         default:
1436                 printf("\n        Invalid desc subtype: ");
1437                 dump_bytes(buf+3, buf[0]-3);
1438                 break;
1439         }
1440 }
1441
1442 static void dump_midistreaming_endpoint(unsigned char *buf)
1443 {
1444         unsigned int j;
1445
1446         if (buf[1] != USB_DT_CS_ENDPOINT)
1447                 printf("      Warning: Invalid descriptor\n");
1448         else if (buf[0] < 5)
1449                 printf("      Warning: Descriptor too short\n");
1450         printf("        MIDIStreaming Endpoint Descriptor:\n"
1451                "          bLength             %5u\n"
1452                "          bDescriptorType     %5u\n"
1453                "          bDescriptorSubtype  %5u (%s)\n"
1454                "          bNumEmbMIDIJack     %5u\n",
1455                buf[0], buf[1], buf[2], buf[2] == 1 ? "GENERAL" : "Invalid", buf[3]);
1456         for (j=0; j<buf[3]; j++) {
1457                 printf("          baAssocJackID(%2u)   %5u\n", j, buf[4+j]);
1458         }
1459         dump_junk(buf, "          ", 4+buf[3]);
1460 }
1461
1462 /*
1463  * Video Class descriptor dump
1464  */
1465
1466 static void dump_videocontrol_interface(struct usb_dev_handle *dev, unsigned char *buf)
1467 {
1468         static const char *ctrlnames[] = {
1469                 "Brightness", "Contrast", "Hue", "Saturation", "Sharpness", "Gamma",
1470                 "White Balance Temperature", "White Balance Component", "Backlight Compensation",
1471                 "Gain", "Power Line Frequency", "Hue, Auto", "White Balance Temperature, Auto",
1472                 "White Balance Component, Auto", "Digital Multiplier", "Digital Multiplier Limit",
1473                 "Analog Video Standard", "Analog Video Lock Status"
1474         };
1475         static const char *camctrlnames[] = {
1476                 "Scanning Mode", "Auto-Exposure Mode", "Auto-Exposure Priority",
1477                 "Exposure Time (Absolute)", "Exposure Time (Relative)", "Focus (Absolute)",
1478                 "Focus (Relative)", "Iris (Absolute)", "Iris (Relative)", "Zoom (Absolute)",
1479                 "Zoom (Relative)", "PanTilt (Absolute)", "PanTilt (Relative)",
1480                 "Roll (Absolute)", "Roll (Relative)", "Reserved", "Reserved", "Focus, Auto",
1481                 "Privacy"
1482         };
1483         static const char *stdnames[] = {
1484                 "None", "NTSC - 525/60", "PAL - 625/50", "SECAM - 625/50",
1485                 "NTSC - 625/50", "PAL - 525/60" };
1486         unsigned int i, ctrls, stds, n, p, termt, freq;
1487         char term[128], termts[128];
1488
1489         if (buf[1] != USB_DT_CS_INTERFACE)
1490                 printf("      Warning: Invalid descriptor\n");
1491         else if (buf[0] < 3)
1492                 printf("      Warning: Descriptor too short\n");
1493         printf("      VideoControl Interface Descriptor:\n"
1494                "        bLength             %5u\n"
1495                "        bDescriptorType     %5u\n"
1496                "        bDescriptorSubtype  %5u ",
1497                buf[0], buf[1], buf[2]);
1498         switch (buf[2]) {
1499         case 0x01:  /* HEADER */
1500                 printf("(HEADER)\n");
1501                 n = buf[11];
1502                 if (buf[0] < 12+n)
1503                         printf("      Warning: Descriptor too short\n");
1504                 freq = buf[7] | (buf[8] << 8) | (buf[9] << 16) | (buf[10] << 24);
1505                 printf("        bcdUVC              %2x.%02x\n"
1506                        "        wTotalLength        %5u\n"
1507                        "        dwClockFrequency    %5u.%06uMHz\n"
1508                        "        bInCollection       %5u\n",
1509                        buf[4], buf[3], buf[5] | (buf[6] << 8), freq / 1000000,
1510                        freq % 1000000, n);
1511                 for(i = 0; i < n; i++)
1512                         printf("        baInterfaceNr(%2u)   %5u\n", i, buf[12+i]);
1513                 dump_junk(buf, "        ", 12+n);
1514                 break;
1515
1516         case 0x02:  /* INPUT_TERMINAL */
1517                 printf("(INPUT_TERMINAL)\n");
1518                 get_string(dev, term, sizeof(term), buf[7]);
1519                 termt = buf[4] | (buf[5] << 8);
1520                 n = termt == 0x0201 ? 7 : 0;
1521                 get_videoterminal_string(termts, sizeof(termts), termt);
1522                 if (buf[0] < 8 + n)
1523                         printf("      Warning: Descriptor too short\n");
1524                 printf("        bTerminalID         %5u\n"
1525                        "        wTerminalType      0x%04x %s\n"
1526                        "        bAssocTerminal      %5u\n",
1527                        buf[3], termt, termts, buf[6]);
1528                 printf("        iTerminal           %5u %s\n",
1529                        buf[7], term);
1530                 if (termt == 0x0201) {
1531                         n += buf[14];
1532                         printf("        wObjectiveFocalLengthMin  %5u\n"
1533                                "        wObjectiveFocalLengthMax  %5u\n"
1534                                "        wOcularFocalLength        %5u\n"
1535                                "        bControlSize              %5u\n",
1536                                buf[8] | (buf[9] << 8), buf[10] | (buf[11] << 8),
1537                                buf[12] | (buf[13] << 8), buf[14]);
1538                         ctrls = 0;
1539                         for (i = 0; i < 3 && i < buf[14]; i++)
1540                                 ctrls = (ctrls << 8) | buf[8+n-i-1];
1541                         printf("        bmControls           0x%08x\n", ctrls);
1542                         for (i = 0; i < 19; i++)
1543                                 if ((ctrls >> i) & 1)
1544                                         printf("          %s\n", camctrlnames[i]);
1545                 }
1546                 dump_junk(buf, "        ", 8+n);
1547                 break;
1548
1549         case 0x03:  /* OUTPUT_TERMINAL */
1550                 printf("(OUTPUT_TERMINAL)\n");
1551                 get_string(dev, term, sizeof(term), buf[8]);
1552                 termt = buf[4] | (buf[5] << 8);
1553                 get_audioterminal_string(termts, sizeof(termts), termt);
1554                 if (buf[0] < 9)
1555                         printf("      Warning: Descriptor too short\n");
1556                 printf("        bTerminalID         %5u\n"
1557                        "        wTerminalType      0x%04x %s\n"
1558                        "        bAssocTerminal      %5u\n"
1559                        "        bSourceID           %5u\n"
1560                        "        iTerminal           %5u %s\n",
1561                        buf[3], termt, termts, buf[6], buf[7], buf[8], term);
1562                 dump_junk(buf, "        ", 9);
1563                 break;
1564
1565         case 0x04:  /* SELECTOR_UNIT */
1566                 printf("(SELECTOR_UNIT)\n");
1567                 p = buf[4];
1568                 if (buf[0] < 6+p)
1569                         printf("      Warning: Descriptor too short\n");
1570                 get_string(dev, term, sizeof(term), buf[5+p]);
1571
1572                 printf("        bUnitID             %5u\n"
1573                        "        bNrInPins           %5u\n",
1574                        buf[3], p);
1575                 for (i = 0; i < p; i++)
1576                         printf("        baSource(%2u)        %5u\n", i, buf[5+i]);
1577                 printf("        iSelector           %5u %s\n",
1578                        buf[5+p], term);
1579                 dump_junk(buf, "        ", 6+p);
1580                 break;
1581
1582         case 0x05:  /* PROCESSING_UNIT */
1583                 printf("(PROCESSING_UNIT)\n");
1584                 n = buf[7];
1585                 get_string(dev, term, sizeof(term), buf[8+n]);
1586                 if (buf[0] < 10+n)
1587                         printf("      Warning: Descriptor too short\n");
1588                 printf("        bUnitID             %5u\n"
1589                        "        bSourceID           %5u\n"
1590                        "        wMaxMultiplier      %5u\n"
1591                        "        bControlSize        %5u\n",
1592                        buf[3], buf[4], buf[5] | (buf[6] << 8), n);
1593                 ctrls = 0;
1594                 for (i = 0; i < 3 && i < n; i++)
1595                         ctrls = (ctrls << 8) | buf[8+n-i-1];
1596                 printf("        bmControls     0x%08x\n", ctrls);
1597                 for (i = 0; i < 18; i++)
1598                         if ((ctrls >> i) & 1)
1599                                 printf("          %s\n", ctrlnames[i]);
1600                 stds = buf[9+n];
1601                 printf("        iProcessing         %5u %s\n"
1602                        "        bmVideoStandards     0x%2x\n", buf[8+n], term, stds);
1603                 for (i = 0; i < 6; i++)
1604                         if ((stds >> i) & 1)
1605                                 printf("          %s\n", stdnames[i]);
1606                 break;
1607
1608         case 0x06:  /* EXTENSION_UNIT */
1609                 printf("(EXTENSION_UNIT)\n");
1610                 p = buf[21];
1611                 n = buf[22+p];
1612                 get_string(dev, term, sizeof(term), buf[23+p+n]);
1613                 if (buf[0] < 24+p+n)
1614                         printf("      Warning: Descriptor too short\n");
1615                 printf("        bUnitID             %5u\n"
1616                        "        guidExtensionCode         %s\n"
1617                        "        bNumControl         %5u\n"
1618                        "        bNrPins             %5u\n",
1619                        buf[3], get_guid(&buf[4]), buf[20], buf[21]);
1620                 for (i = 0; i < p; i++)
1621                         printf("        baSourceID(%2u)      %5u\n", i, buf[22+i]);
1622                 printf("        bControlSize        %5u\n", buf[22+p]);
1623                 for (i = 0; i < n; i++)
1624                         printf("        bmControls(%2u)       0x%02x\n", i, buf[23+p+i]);
1625                 printf("        iExtension          %5u %s\n",
1626                        buf[23+p+n], term);
1627                 dump_junk(buf, "        ", 24+p+n);
1628                 break;
1629
1630         default:
1631                 printf("(unknown)\n"
1632                        "        Invalid desc subtype:");
1633                 dump_bytes(buf+3, buf[0]-3);
1634                 break;
1635         }
1636 }
1637
1638 static void dump_videostreaming_interface(unsigned char *buf)
1639 {
1640         static const char *colorPrims[] = { "Unspecified", "BT.709,sRGB",
1641                 "BT.470-2 (M)", "BT.470-2 (B,G)", "SMPTE 170M", "SMPTE 240M" };
1642         static const char *transferChars[] = { "Unspecified", "BT.709",
1643                 "BT.470-2 (M)", "BT.470-2 (B,G)", "SMPTE 170M", "SMPTE 240M",
1644                 "Linear", "sRGB"};
1645         static const char *matrixCoeffs[] = { "Unspecified", "BT.709",
1646                 "FCC", "BT.470-2 (B,G)", "SMPTE 170M (BT.601)", "SMPTE 240M" };
1647         unsigned int i, m, n, p, flags, len;
1648
1649         if (buf[1] != USB_DT_CS_INTERFACE)
1650                 printf("      Warning: Invalid descriptor\n");
1651         else if (buf[0] < 3)
1652                 printf("      Warning: Descriptor too short\n");
1653         printf("      VideoStreaming Interface Descriptor:\n"
1654                "        bLength                         %5u\n"
1655                "        bDescriptorType                 %5u\n"
1656                "        bDescriptorSubtype              %5u ",
1657                buf[0], buf[1], buf[2]);
1658         switch (buf[2]) {
1659         case 0x01: /* INPUT_HEADER */
1660                 printf("(INPUT_HEADER)\n");
1661                 p = buf[3];
1662                 n = buf[12];
1663                 if (buf[0] < 13+p*n)
1664                         printf("      Warning: Descriptor too short\n");
1665                 printf("        bNumFormats                     %5u\n"
1666                        "        wTotalLength                    %5u\n"
1667                        "        bEndPointAddress                %5u\n"
1668                        "        bmInfo                          %5u\n"
1669                        "        bTerminalLink                   %5u\n"
1670                        "        bStillCaptureMethod             %5u\n"
1671                        "        bTriggerSupport                 %5u\n"
1672                        "        bTriggerUsage                   %5u\n"
1673                        "        bControlSize                    %5u\n",
1674                        p, buf[4] | (buf[5] << 8), buf[6], buf[7], buf[8],
1675                        buf[9], buf[10], buf[11], n);
1676                 for(i = 0; i < p; i++)
1677                         printf(
1678                         "        bmaControls(%2u)                 %5u\n",
1679                                 i, buf[13+p*n]);
1680                 dump_junk(buf, "        ", 13+p*n);
1681                 break;
1682
1683         case 0x02: /* OUTPUT_HEADER */
1684                 printf("(OUTPUT_HEADER)\n");
1685                 p = buf[3];
1686                 n = buf[8];
1687                 if (buf[0] < 9+p*n)
1688                         printf("      Warning: Descriptor too short\n");
1689                 printf("        bNumFormats                 %5u\n"
1690                        "        wTotalLength                %5u\n"
1691                        "        bEndpointAddress            %5u\n"
1692                        "        bTerminalLink               %5u\n"
1693                        "        bControlSize                %5u\n",
1694                        p, buf[4] | (buf[5] << 8), buf[6], buf[7], n);
1695                 for(i = 0; i < p; i++)
1696                         printf(
1697                         "        bmaControls(%2u)             %5u\n",
1698                                 i, buf[9+p*n]);
1699                 dump_junk(buf, "        ", 9+p*n);
1700                 break;
1701
1702         case 0x03: /* STILL_IMAGE_FRAME */
1703                 printf("(STILL_IMAGE_FRAME)\n");
1704                 n = buf[4];
1705                 m = buf[5+4*n];
1706                 if (buf[0] < 6+4*n+m)
1707                         printf("      Warning: Descriptor too short\n");
1708                 printf("        bEndpointAddress                %5u\n"
1709                        "        bNumImageSizePatterns             %3u\n",
1710                        buf[3], n);
1711                 for (i = 0; i < n; i++)
1712                         printf("        wWidth(%2u)                      %5u\n"
1713                                "        wHeight(%2u)                     %5u\n",
1714                                i, buf[5+4*i] | (buf[6+4*i] << 8),
1715                                i, buf[7+4*i] | (buf[8+4*i] << 8));
1716                 printf("        bNumCompressionPatterns           %3u\n", n);
1717                 for (i = 0; i < m; i++)
1718                         printf("        bCompression(%2u)                %5u\n",
1719                                i, buf[6+4*n+i]);
1720                 dump_junk(buf, "        ", 6+4*n+m);
1721                 break;
1722
1723         case 0x04: /* FORMAT_UNCOMPRESSED */
1724                 printf("(FORMAT_UNCOMPRESSED)\n");
1725                 if (buf[0] < 27)
1726                         printf("      Warning: Descriptor too short\n");
1727                 flags = buf[25];
1728                 printf("        bFormatIndex                    %5u\n"
1729                        "        bNumFrameDescriptors            %5u\n"
1730                        "        guidFormat                            %s\n"
1731                        "        bBitsPerPixel                   %5u\n"
1732                        "        bDefaultFrameIndex              %5u\n"
1733                        "        bAspectRatioX                   %5u\n"
1734                        "        bAspectRatioY                   %5u\n"
1735                        "        bmInterlaceFlags                 0x%02x\n",
1736                        buf[3], buf[4], get_guid(&buf[5]), buf[21], buf[22],
1737                        buf[23], buf[24], flags);
1738                 printf("          Interlaced stream or variable: %s\n",
1739                        (flags & (1 << 0)) ? "Yes" : "No");
1740                 printf("          Fields per frame: %u fields\n",
1741                        (flags & (1 << 1)) ? 2 : 1);
1742                 printf("          Field 1 first: %s\n",
1743                        (flags & (1 << 2)) ? "Yes" : "No");
1744                 printf("          Field pattern: ");
1745                 switch((flags >> 4) & 0x03)
1746                 {
1747                 case 0:
1748                         printf("Field 1 only\n");
1749                         break;
1750                 case 1:
1751                         printf("Field 2 only\n");
1752                         break;
1753                 case 2:
1754                         printf("Regular pattern of fields 1 and 2\n");
1755                         break;
1756                 case 3:
1757                         printf("Random pattern of fields 1 and 2\n");
1758                         break;
1759                 }
1760                 printf("          bCopyProtect                  %5u\n", buf[26]);
1761                 dump_junk(buf, "        ", 27);
1762                 break;
1763
1764         case 0x05: /* FRAME UNCOMPRESSED */
1765         case 0x07: /* FRAME_MJPEG */
1766                 if (buf[2] == 0x05)
1767                         printf("(FRAME_UNCOMPRESSED)\n");
1768                 else
1769                         printf("(FRAME_MJPEG)\n");
1770                 len = (buf[25] != 0) ? (26+buf[25]*4) : 38;
1771                 if (buf[0] < len)
1772                         printf("      Warning: Descriptor too short\n");
1773                 flags = buf[4];
1774                 printf("        bFrameIndex                     %5u\n"
1775                        "        bmCapabilities                   0x%02x\n",
1776                        buf[3], flags);
1777                 printf("          Still image %ssupported\n",
1778                        (flags & (1 << 0)) ? "" : "un");
1779                 if (flags & (1 << 1))
1780                 printf("          Fixed frame-rate\n");
1781                 printf("        wWidth                          %5u\n"
1782                        "        wHeight                         %5u\n"
1783                        "        dwMinBitRate                %9u\n"
1784                        "        dwMaxBitRate                %9u\n"
1785                        "        dwMaxVideoFrameBufferSize   %9u\n"
1786                        "        dwDefaultFrameInterval      %9u\n"
1787                        "        bFrameIntervalType              %5u\n",
1788                        buf[5] | (buf[6] <<  8), buf[7] | (buf[8] << 8),
1789                        buf[9] | (buf[10] << 8) | (buf[11] << 16) | (buf[12] << 24),
1790                        buf[13] | (buf[14] << 8) | (buf[15] << 16) | (buf[16] << 24),
1791                        buf[17] | (buf[18] << 8) | (buf[19] << 16) | (buf[20] << 24),
1792                        buf[21] | (buf[22] << 8) | (buf[23] << 16) | (buf[24] << 24),
1793                        buf[25]);
1794                 if (buf[25] == 0)
1795                         printf("        dwMinFrameInterval          %9u\n"
1796                                "        dwMaxFrameInterval          %9u\n"
1797                                "        dwFrameIntervalStep         %9u\n",
1798                                buf[26] | (buf[27] << 8) | (buf[28] << 16) | (buf[29] << 24),
1799                                buf[30] | (buf[31] << 8) | (buf[32] << 16) | (buf[33] << 24),
1800                                buf[34] | (buf[35] << 8) | (buf[36] << 16) | (buf[37] << 24));
1801                 else
1802                         for (i = 0; i < buf[25]; i++)
1803                                 printf("        dwFrameInterval(%2u)         %9u\n",
1804                                        i, buf[26+4*i] | (buf[27+4*i] << 8) |
1805                                        (buf[28+4*i] << 16) | (buf[29+4*i] << 24));
1806                 dump_junk(buf, "        ", len);
1807                 break;
1808
1809         case 0x06: /* FORMAT_MJPEG */
1810                 printf("(FORMAT_MJPEG)\n");
1811                 if (buf[0] < 11)
1812                         printf("      Warning: Descriptor too short\n");
1813                 flags = buf[5];
1814                 printf("        bFormatIndex                    %5u\n"
1815                        "        bNumFrameDescriptors            %5u\n"
1816                        "        bFlags                          %5u\n",
1817                        buf[3], buf[4], flags);
1818                 printf("          Fixed-size samples: %s\n",
1819                        (flags & (1 << 0)) ? "Yes" : "No");
1820                 flags = buf[9];
1821                 printf("        bDefaultFrameIndex              %5u\n"
1822                        "        bAspectRatioX                   %5u\n"
1823                        "        bAspectRatioY                   %5u\n"
1824                        "        bmInterlaceFlags                 0x%02x\n",
1825                        buf[6], buf[7], buf[8], flags);
1826                 printf("          Interlaced stream or variable: %s\n",
1827                        (flags & (1 << 0)) ? "Yes" : "No");
1828                 printf("          Fields per frame: %u fields\n",
1829                        (flags & (1 << 1)) ? 2 : 1);
1830                 printf("          Field 1 first: %s\n",
1831                        (flags & (1 << 2)) ? "Yes" : "No");
1832                 printf("          Field pattern: ");
1833                 switch((flags >> 4) & 0x03)
1834                 {
1835                 case 0:
1836                         printf("Field 1 only\n");
1837                         break;
1838                 case 1:
1839                         printf("Field 2 only\n");
1840                         break;
1841                 case 2:
1842                         printf("Regular pattern of fields 1 and 2\n");
1843                         break;
1844                 case 3:
1845                         printf("Random pattern of fields 1 and 2\n");
1846                         break;
1847                 }
1848                 printf("          bCopyProtect                  %5u\n", buf[10]);
1849                 dump_junk(buf, "        ", 11);
1850                 break;
1851
1852         case 0x0d: /* COLORFORMAT */
1853                 printf("(COLORFORMAT)\n");
1854                 if (buf[0] < 6)
1855                         printf("      Warning: Descriptor too short\n");
1856                 printf("        bColorPrimaries                 %5u (%s)\n",
1857                        buf[3], (buf[3] <= 5) ? colorPrims[buf[3]] : "Unknown");
1858                 printf("        bTransferCharacteristics        %5u (%s)\n",
1859                        buf[4], (buf[4] <= 7) ? transferChars[buf[4]] : "Unknown");
1860                 printf("        bMatrixCoefficients             %5u (%s)\n",
1861                        buf[5], (buf[5] <= 5) ? matrixCoeffs[buf[5]] : "Unknown");
1862                 dump_junk(buf, "        ", 6);
1863                 break;
1864
1865         default:
1866                 printf("        Invalid desc subtype:");
1867                 dump_bytes(buf+3, buf[0]-3);
1868                 break;
1869         }
1870 }
1871
1872 static void dump_dfu_interface(unsigned char *buf)
1873 {
1874         if (buf[1] != USB_DT_CS_DEVICE)
1875                 printf("      Warning: Invalid descriptor\n");
1876         else if (buf[0] < 7)
1877                 printf("      Warning: Descriptor too short\n");
1878         printf("      Device Firmware Upgrade Interface Descriptor:\n"
1879                "        bLength                         %5u\n"
1880                "        bDescriptorType                 %5u\n"
1881                "        bmAttributes                    %5u\n",
1882                buf[0], buf[1], buf[2]);
1883         if (buf[2] & 0xf0)
1884                 printf("          (unknown attributes!)\n");
1885         printf("          Will %sDetach\n", (buf[2] & 0x08) ? "" : "Not ");
1886         printf("          Manifestation %s\n", (buf[2] & 0x04) ? "Tolerant" : "Intolerant");
1887         printf("          Upload %s\n", (buf[2] & 0x02) ? "Supported" : "Unsupported");
1888         printf("          Download %s\n", (buf[2] & 0x01) ? "Supported" : "Unsupported");
1889         printf("        wDetachTimeout                  %5u milliseconds\n"
1890                "        wTransferSize                   %5u bytes\n",
1891                buf[3] | (buf[4] << 8), buf[5] | (buf[6] << 8));
1892
1893         /* DFU 1.0 defines no version code, DFU 1.1 does */
1894         if (buf[0] < 9)
1895                 return;
1896         printf("        bcdDFUVersion                   %x.%02x\n",
1897                         buf[7], buf[8]);
1898 }
1899
1900 static void dump_hub(char *prefix, unsigned char *p, int has_tt)
1901 {
1902         unsigned int l, i, j;
1903         unsigned int wHubChar = (p[4] << 8) | p[3];
1904
1905         printf("%sHub Descriptor:\n", prefix);
1906         printf("%s  bLength             %3u\n", prefix, p[0]);
1907         printf("%s  bDescriptorType     %3u\n", prefix, p[1]);
1908         printf("%s  nNbrPorts           %3u\n", prefix, p[2]);
1909         printf("%s  wHubCharacteristic 0x%04x\n", prefix, wHubChar);
1910         switch (wHubChar & 0x03) {
1911         case 0:
1912                 printf("%s    Ganged power switching\n", prefix);
1913                 break;
1914         case 1:
1915                 printf("%s    Per-port power switching\n", prefix);
1916                 break;
1917         default:
1918                 printf("%s    No power switching (usb 1.0)\n", prefix);
1919                 break;
1920         }
1921         if (wHubChar & 0x04)
1922                 printf("%s    Compound device\n", prefix);
1923         switch ((wHubChar >> 3) & 0x03) {
1924         case 0:
1925                 printf("%s    Ganged overcurrent protection\n", prefix);
1926                 break;
1927         case 1:
1928                 printf("%s    Per-port overcurrent protection\n", prefix);
1929                 break;
1930         default:
1931                 printf("%s    No overcurrent protection\n", prefix);
1932                 break;
1933         }
1934         if (has_tt) {
1935                 l = (wHubChar >> 5) & 0x03;
1936                 printf("%s    TT think time %d FS bits\n", prefix, (l + 1) * 8);
1937         }
1938         if (wHubChar & (1<<7))
1939                 printf("%s    Port indicators\n", prefix);
1940         printf("%s  bPwrOn2PwrGood      %3u * 2 milli seconds\n", prefix, p[5]);
1941         printf("%s  bHubContrCurrent    %3u milli Ampere\n", prefix, p[6]);
1942         l= (p[2] >> 3) + 1; /* this determines the variable number of bytes following */
1943         if (l > HUB_STATUS_BYTELEN)
1944                 l = HUB_STATUS_BYTELEN;
1945         printf("%s  DeviceRemovable   ", prefix);
1946         for(i = 0; i < l; i++)
1947                 printf(" 0x%02x", p[7+i]);
1948         printf("\n%s  PortPwrCtrlMask   ", prefix);
1949         for(j = 0; j < l; j++)
1950                 printf(" 0x%02x", p[7+i+j]);
1951         printf("\n");
1952 }
1953
1954 static void dump_ccid_device(unsigned char *buf)
1955 {
1956         unsigned int us;
1957
1958         if (buf[0] < 54) {
1959                 printf("      Warning: Descriptor too short\n");
1960                 return;
1961         }
1962         printf("      ChipCard Interface Descriptor:\n"
1963                "        bLength             %5u\n"
1964                "        bDescriptorType     %5u\n"
1965                "        bcdCCID             %2x.%02x",
1966                buf[0], buf[1], buf[3], buf[2]);
1967         if (buf[3] != 1 || buf[2] != 0)
1968                 fputs("  (Warning: Only accurate for version 1.0)", stdout);
1969         putchar('\n');
1970
1971         printf("        nMaxSlotIndex       %5u\n"
1972                 "        bVoltageSupport     %5u  %s%s%s\n",
1973                 buf[4],
1974                 buf[5],
1975                (buf[5] & 1) ? "5.0V " : "",
1976                (buf[5] & 2) ? "3.0V " : "",
1977                (buf[5] & 4) ? "1.8V " : "");
1978
1979         us = convert_le_u32 (buf+6);
1980         printf("        dwProtocols         %5u ", us);
1981         if ((us & 1))
1982                 fputs(" T=0", stdout);
1983         if ((us & 2))
1984                 fputs(" T=1", stdout);
1985         if ((us & ~3))
1986                 fputs(" (Invalid values detected)", stdout);
1987         putchar('\n');
1988
1989         us = convert_le_u32(buf+10);
1990         printf("        dwDefaultClock      %5u\n", us);
1991         us = convert_le_u32(buf+14);
1992         printf("        dwMaxiumumClock     %5u\n", us);
1993         printf("        bNumClockSupported  %5u\n", buf[18]);
1994         us = convert_le_u32(buf+19);
1995         printf("        dwDataRate        %7u bps\n", us);
1996         us = convert_le_u32(buf+23);
1997         printf("        dwMaxDataRate     %7u bps\n", us);
1998         printf("        bNumDataRatesSupp.  %5u\n", buf[27]);
1999
2000         us = convert_le_u32(buf+28);
2001         printf("        dwMaxIFSD           %5u\n", us);
2002
2003         us = convert_le_u32(buf+32);
2004         printf("        dwSyncProtocols  %08X ", us);
2005         if ((us&1))
2006                 fputs(" 2-wire", stdout);
2007         if ((us&2))
2008                 fputs(" 3-wire", stdout);
2009         if ((us&4))
2010                 fputs(" I2C", stdout);
2011         putchar('\n');
2012
2013         us = convert_le_u32(buf+36);
2014         printf("        dwMechanical     %08X ", us);
2015         if ((us & 1))
2016                 fputs(" accept", stdout);
2017         if ((us & 2))
2018                 fputs(" eject", stdout);
2019         if ((us & 4))
2020                 fputs(" capture", stdout);
2021         if ((us & 8))
2022                 fputs(" lock", stdout);
2023         putchar('\n');
2024
2025         us = convert_le_u32(buf+40);
2026         printf("        dwFeatures       %08X\n", us);
2027         if ((us & 0x0002))
2028                 fputs("          Auto configuration based on ATR\n",stdout);
2029         if ((us & 0x0004))
2030                 fputs("          Auto activation on insert\n",stdout);
2031         if ((us & 0x0008))
2032                 fputs("          Auto voltage selection\n",stdout);
2033         if ((us & 0x0010))
2034                 fputs("          Auto clock change\n",stdout);
2035         if ((us & 0x0020))
2036                 fputs("          Auto baud rate change\n",stdout);
2037         if ((us & 0x0040))
2038                 fputs("          Auto parameter negotation made by CCID\n",stdout);
2039         else if ((us & 0x0080))
2040                 fputs("          Auto PPS made by CCID\n",stdout);
2041         else if ((us & (0x0040 | 0x0080)))
2042                 fputs("        WARNING: conflicting negotation features\n",stdout);
2043
2044         if ((us & 0x0100))
2045                 fputs("          CCID can set ICC in clock stop mode\n",stdout);
2046         if ((us & 0x0200))
2047                 fputs("          NAD value other than 0x00 accpeted\n",stdout);
2048         if ((us & 0x0400))
2049                 fputs("          Auto IFSD exchange\n",stdout);
2050
2051         if ((us & 0x00010000))
2052                 fputs("          TPDU level exchange\n",stdout);
2053         else if ((us & 0x00020000))
2054                 fputs("          Short APDU level exchange\n",stdout);
2055         else if ((us & 0x00040000))
2056                 fputs("          Short and extended APDU level exchange\n",stdout);
2057         else if ((us & 0x00070000))
2058                 fputs("        WARNING: conflicting exchange levels\n",stdout);
2059
2060         us = convert_le_u32(buf+44);
2061         printf("        dwMaxCCIDMsgLen     %5u\n", us);
2062
2063         printf("        bClassGetResponse    ");
2064         if (buf[48] == 0xff)
2065                 fputs("echo\n", stdout);
2066         else
2067                 printf("  %02X\n", buf[48]);
2068
2069         printf("        bClassEnvelope       ");
2070         if (buf[49] == 0xff)
2071                 fputs("echo\n", stdout);
2072         else
2073                 printf("  %02X\n", buf[48]);
2074
2075         printf("        wlcdLayout           ");
2076         if (!buf[50] && !buf[51])
2077                 fputs("none\n", stdout);
2078         else
2079                 printf("%u cols %u lines\n", buf[50], buf[51]);
2080
2081         printf("        bPINSupport         %5u ", buf[52]);
2082         if ((buf[52] & 1))
2083                 fputs(" verification", stdout);
2084         if ((buf[52] & 2))
2085                 fputs(" modification", stdout);
2086         putchar('\n');
2087
2088         printf("        bMaxCCIDBusySlots   %5u\n", buf[53]);
2089
2090         if (buf[0] > 54) {
2091                 fputs("        junk             ", stdout);
2092                 dump_bytes(buf+54, buf[0]-54);
2093         }
2094 }
2095
2096 /* ---------------------------------------------------------------------- */
2097
2098 /*
2099  * HID descriptor
2100  */
2101
2102 static void dump_report_desc(unsigned char *b, int l)
2103 {
2104         unsigned int t, j, bsize, btag, btype, data = 0xffff, hut = 0xffff;
2105         int i;
2106         char *types[4] = { "Main", "Global", "Local", "reserved" };
2107         char indent[] = "                            ";
2108
2109         printf("          Report Descriptor: (length is %d)\n", l);
2110         for(i = 0; i < l; ) {
2111                 t = b[i];
2112                 bsize = b[i] & 0x03;
2113                 if (bsize == 3)
2114                         bsize = 4;
2115                 btype = b[i] & (0x03 << 2);
2116                 btag = b[i] & ~0x03; /* 2 LSB bits encode length */
2117                 printf("            Item(%-6s): %s, data=", types[btype>>2],
2118                                 names_reporttag(btag));
2119                 if (bsize > 0) {
2120                         printf(" [ ");
2121                         data = 0;
2122                         for(j = 0; j < bsize; j++) {
2123                                 printf("0x%02x ", b[i+1+j]);
2124                                 data += (b[i+1+j] << (8*j));
2125                         }
2126                         printf("] %d", data);
2127                 } else
2128                         printf("none");
2129                 printf("\n");
2130                 switch(btag) {
2131                 case 0x04 : /* Usage Page */
2132                         printf("%s%s\n", indent, names_huts(data));
2133                         hut = data;
2134                         break;
2135
2136                 case 0x08 : /* Usage */
2137                 case 0x18 : /* Usage Minimum */
2138                 case 0x28 : /* Usage Maximum */
2139                         printf("%s%s\n", indent,
2140                                         names_hutus((hut << 16) + data));
2141                         break;
2142
2143                 case 0x54 : /* Unit Exponent */
2144                         printf("%sUnit Exponent: %i\n", indent,
2145                                         (signed char)data);
2146                         break;
2147
2148                 case 0x64 : /* Unit */
2149                         printf("%s", indent);
2150                         dump_unit(data, bsize);
2151                         break;
2152
2153                 case 0xa0 : /* Collection */
2154                         printf("%s", indent);
2155                         switch (data) {
2156                         case 0x00:
2157                                 printf("Physical\n");
2158                                 break;
2159
2160                         case 0x01:
2161                                 printf("Application\n");
2162                                 break;
2163
2164                         case 0x02:
2165                                 printf("Logical\n");
2166                                 break;
2167
2168                         case 0x03:
2169                                 printf("Report\n");
2170                                 break;
2171
2172                         case 0x04:
2173                                 printf("Named Array\n");
2174                                 break;
2175
2176                         case 0x05:
2177                                 printf("Usage Switch\n");
2178                                 break;
2179
2180                         case 0x06:
2181                                 printf("Usage Modifier\n");
2182                                 break;
2183
2184                         default:
2185                                 if(data & 0x80)
2186                                         printf("Vendor defined\n");
2187                                 else
2188                                         printf("Reserved for future use.\n");
2189                         }
2190                         break;
2191                 case 0x80: /* Input */
2192                 case 0x90: /* Output */
2193                 case 0xb0: /* Feature */
2194                         printf("%s%s %s %s %s %s\n%s%s %s %s %s\n",
2195                                indent,
2196                                data & 0x01 ? "Constant": "Data",
2197                                data & 0x02 ? "Variable": "Array",
2198                                data & 0x04 ? "Relative": "Absolute",
2199                                data & 0x08 ? "Wrap" : "No_Wrap",
2200                                data & 0x10 ? "Non_Linear": "Linear",
2201                                indent,
2202                                data & 0x20 ? "No_Preferred_State": "Preferred_State",
2203                                data & 0x40 ? "Null_State": "No_Null_Position",
2204                                data & 0x80 ? "Volatile": "Non_Volatile",
2205                                data &0x100 ? "Buffered Bytes": "Bitfield"
2206                         );
2207                         break;
2208                 }
2209                 i += 1 + bsize;
2210         }
2211 }
2212
2213 static void dump_hid_device(struct usb_dev_handle *dev, struct usb_interface_descriptor *interface, unsigned char *buf)
2214 {
2215         unsigned int i, len;
2216         int n;
2217         unsigned char dbuf[8192];
2218
2219         if (buf[1] != USB_DT_HID)
2220                 printf("      Warning: Invalid descriptor\n");
2221         else if (buf[0] < 6+3*buf[5])
2222                 printf("      Warning: Descriptor too short\n");
2223         printf("        HID Device Descriptor:\n"
2224                "          bLength             %5u\n"
2225                "          bDescriptorType     %5u\n"
2226                "          bcdHID              %2x.%02x\n"
2227                "          bCountryCode        %5u %s\n"
2228                "          bNumDescriptors     %5u\n",
2229                buf[0], buf[1], buf[3], buf[2], buf[4],
2230                names_countrycode(buf[4]) ? : "Unknown", buf[5]);
2231         for (i = 0; i < buf[5]; i++)
2232                 printf("          bDescriptorType     %5u %s\n"
2233                        "          wDescriptorLength   %5u\n",
2234                        buf[6+3*i], names_hid(buf[6+3*i]),
2235                        buf[7+3*i] | (buf[8+3*i] << 8));
2236         dump_junk(buf, "        ", 6+3*buf[5]);
2237         if (!do_report_desc)
2238                 return;
2239
2240         if (!dev) {
2241                 printf( "         Report Descriptors: \n"
2242                         "           ** UNAVAILABLE **\n");
2243                 return;
2244         }
2245
2246         for (i = 0; i < buf[5]; i++) {
2247                 /* we are just interested in report descriptors*/
2248                 if (buf[6+3*i] != USB_DT_REPORT)
2249                         continue;
2250                 len = buf[7+3*i] | (buf[8+3*i] << 8);
2251                 if (len > sizeof(dbuf)) {
2252                         printf("report descriptor too long\n");
2253                         continue;
2254                 }
2255                 if (usb_claim_interface(dev, interface->bInterfaceNumber) == 0) {
2256                         int retries = 4;
2257                         n = 0;
2258                         while (n < len && retries--)
2259                                 n = usb_control_msg(dev,
2260                                          USB_ENDPOINT_IN | USB_TYPE_STANDARD
2261                                                 | USB_RECIP_INTERFACE,
2262                                          USB_REQ_GET_DESCRIPTOR,
2263                                          (USB_DT_REPORT << 8),
2264                                          interface->bInterfaceNumber,
2265                                          dbuf, len,
2266                                          CTRL_TIMEOUT);
2267
2268                         if (n > 0) {
2269                                 if (n < len)
2270                                         printf("          Warning: incomplete report descriptor\n");
2271                                 dump_report_desc(dbuf, n);
2272                         }
2273                         usb_release_interface(dev, interface->bInterfaceNumber);
2274                 } else {
2275                         /* recent Linuxes require claim() for RECIP_INTERFACE,
2276                          * so "rmmod hid" will often make these available.
2277                          */
2278                         printf( "         Report Descriptors: \n"
2279                                 "           ** UNAVAILABLE **\n");
2280                 }
2281         }
2282 }
2283
2284 static char *
2285 dump_comm_descriptor(struct usb_dev_handle *dev, unsigned char *buf, char *indent)
2286 {
2287         int             tmp;
2288         char            str [128];
2289         char            *type;
2290
2291         switch (buf[2]) {
2292         case 0:
2293                 type = "Header";
2294                 if (buf[0] != 5)
2295                         goto bad;
2296                 printf("%sCDC Header:\n"
2297                        "%s  bcdCDC               %x.%02x\n",
2298                        indent,
2299                        indent, buf[4], buf[3]);
2300                 break;
2301         case 0x01:              /* call management functional desc */
2302                 type = "Call Management";
2303                 if (buf [0] != 5)
2304                         goto bad;
2305                 printf("%sCDC Call Management:\n"
2306                        "%s  bmCapabilities       0x%02x\n",
2307                        indent,
2308                        indent, buf[3]);
2309                 if (buf[3] & 0x01)
2310                         printf("%s    call management\n", indent);
2311                 if (buf[3] & 0x02)
2312                         printf("%s    use DataInterface\n", indent);
2313                 printf("%s  bDataInterface          %d\n", indent, buf[4]);
2314                 break;
2315         case 0x02:              /* acm functional desc */
2316                 type = "ACM";
2317                 if (buf [0] != 4)
2318                         goto bad;
2319                 printf("%sCDC ACM:\n"
2320                        "%s  bmCapabilities       0x%02x\n",
2321                        indent,
2322                        indent, buf[3]);
2323                 if (buf[3] & 0x08)
2324                         printf("%s    connection notifications\n", indent);
2325                 if (buf[3] & 0x04)
2326                         printf("%s    sends break\n", indent);
2327                 if (buf[3] & 0x02)
2328                         printf("%s    line coding and serial state\n", indent);
2329                 if (buf[3] & 0x01)
2330                         printf("%s    get/set/clear comm features\n", indent);
2331                 break;
2332         // case 0x03:           /* direct line management */
2333         // case 0x04:           /* telephone ringer */
2334         // case 0x05:           /* telephone call and line state reporting */
2335         case 0x06:              /* union desc */
2336                 type = "Union";
2337                 if (buf [0] < 5)
2338                         goto bad;
2339                 printf("%sCDC Union:\n"
2340                        "%s  bMasterInterface        %d\n"
2341                        "%s  bSlaveInterface         ",
2342                        indent,
2343                        indent, buf [3],
2344                        indent);
2345                 for (tmp = 4; tmp < buf [0]; tmp++)
2346                         printf("%d ", buf [tmp]);
2347                 printf("\n");
2348                 break;
2349         case 0x07:              /* country selection functional desc */
2350                 type = "Country Selection";
2351                 if (buf [0] < 6 || (buf[0] & 1) != 0)
2352                         goto bad;
2353                 get_string(dev, str, sizeof str, buf[3]);
2354                 printf("%sCountry Selection:\n"
2355                        "%s  iCountryCodeRelDate     %4d %s\n",
2356                        indent,
2357                        indent, buf[3], (buf[3] && *str) ? str : "(?\?)");
2358                 for (tmp = 4; tmp < buf [0]; tmp += 2) {
2359                         printf("%s  wCountryCode          0x%02x%02x\n",
2360                                 indent, buf[tmp], buf[tmp + 1]);
2361                 }
2362                 break;
2363         case 0x08:              /* telephone operational modes */
2364                 type = "Telephone Operations";
2365                 if (buf [0] != 4)
2366                         goto bad;
2367                 printf("%sCDC Telephone operations:\n"
2368                        "%s  bmCapabilities       0x%02x\n",
2369                        indent,
2370                        indent, buf[3]);
2371                 if (buf[3] & 0x04)
2372                         printf("%s    computer centric mode\n", indent);
2373                 if (buf[3] & 0x02)
2374                         printf("%s    standalone mode\n", indent);
2375                 if (buf[3] & 0x01)
2376                         printf("%s    simple mode\n", indent);
2377                 break;
2378         // case 0x09:           /* USB terminal */
2379         case 0x0a:              /* network channel terminal */
2380                 type = "Network Channel Terminal";
2381                 if (buf [0] != 7)
2382                         goto bad;
2383                 get_string(dev, str, sizeof str, buf[4]);
2384                 printf("%sNetwork Channel Terminal:\n"
2385                        "%s  bEntityId               %3d\n"
2386                        "%s  iName                   %3d %s\n"
2387                        "%s  bChannelIndex           %3d\n"
2388                        "%s  bPhysicalInterface      %3d\n",
2389                        indent,
2390                        indent, buf[3],
2391                        indent, buf[4], str,
2392                        indent, buf[5],
2393                        indent, buf[6]);
2394                 break;
2395         // case 0x0b:           /* protocol unit */
2396         // case 0x0c:           /* extension unit */
2397         // case 0x0d:           /* multi-channel management */
2398         // case 0x0e:           /* CAPI control management*/
2399         case 0x0f:              /* ethernet functional desc */
2400                 type = "Ethernet";
2401                 if (buf [0] != 13)
2402                         goto bad;
2403                 get_string(dev, str, sizeof str, buf[3]);
2404                 tmp = buf [7] << 8;
2405                 tmp |= buf [6]; tmp <<= 8;
2406                 tmp |= buf [5]; tmp <<= 8;
2407                 tmp |= buf [4];
2408                 printf("%sCDC Ethernet:\n"
2409                        "%s  iMacAddress             %10d %s\n"
2410                        "%s  bmEthernetStatistics    0x%08x\n",
2411                        indent,
2412                        indent, buf[3], (buf[3] && *str) ? str : "(?\?)",
2413                        indent, tmp);
2414                 /* FIXME dissect ALL 28 bits */
2415                 printf("%s  wMaxSegmentSize         %10d\n"
2416                        "%s  wNumberMCFilters            0x%04x\n"
2417                        "%s  bNumberPowerFilters     %10d\n",
2418                        indent, (buf[9]<<8)|buf[8],
2419                        indent, (buf[11]<<8)|buf[10],
2420                        indent, buf[12]);
2421                 break;
2422         // case 0x10:           /* ATM networking */
2423         case 0x11:              /* WHCM functional desc */
2424                 type = "WHCM version";
2425                 if (buf[0] != 5)
2426                         goto bad;
2427                 printf("%sCDC WHCM:\n"
2428                        "%s  bcdVersion           %x.%02x\n",
2429                        indent,
2430                        indent, buf[4], buf[3]);
2431                 break;
2432         case 0x12:              /* MDLM functional desc */
2433                 type = "MDLM";
2434                 if (buf [0] != 21)
2435                         goto bad;
2436                 printf("%sCDC MDLM:\n"
2437                        "%s  bcdCDC               %x.%02x\n"
2438                        "%s  bGUID               %s\n",
2439                        indent,
2440                        indent, buf[4], buf[3],
2441                        indent, get_guid(buf + 5));
2442                 break;
2443         case 0x13:              /* MDLM detail desc */
2444                 type = "MDLM detail";
2445                 if (buf [0] < 5)
2446                         goto bad;
2447                 printf("%sCDC MDLM detail:\n"
2448                        "%s  bGuidDescriptorType  %02x\n"
2449                        "%s  bDetailData         ",
2450                        indent,
2451                        indent, buf[3],
2452                        indent);
2453                 dump_bytes(buf + 4, buf[0] - 4);
2454                 break;
2455         case 0x14:              /* device management functional desc */
2456                 type = "Device Management";
2457                 if (buf[0] != 7)
2458                         goto bad;
2459                 printf("%sCDC Device Management:\n"
2460                        "%s  bcdVersion           %x.%02x\n"
2461                        "%s  wMaxCommand          %d\n",
2462                        indent,
2463                        indent, buf[4], buf[3],
2464                        indent, (buf[6]<<8)| buf[5]);
2465                 break;
2466         case 0x15:              /* OBEX functional desc */
2467                 type = "OBEX";
2468                 if (buf[0] != 5)
2469                         goto bad;
2470                 printf("%sCDC OBEX:\n"
2471                        "%s  bcdVersion           %x.%02x\n",
2472                        indent,
2473                        indent, buf[4], buf[3]);
2474                 break;
2475         // case 0x16:           /* command set functional desc */
2476         // case 0x17:           /* command set detail desc */
2477         // case 0x18:           /* telephone control model functional desc */
2478         default:
2479                 /* FIXME there are about a dozen more descriptor types */
2480                 printf("%sUNRECOGNIZED CDC: ", indent);
2481                 dump_bytes(buf, buf[0]);
2482                 return "unrecognized comm descriptor";
2483         }
2484         return 0;
2485
2486 bad:
2487         printf("%sINVALID CDC (%s): ", indent, type);
2488         dump_bytes(buf, buf[0]);
2489         return "corrupt comm descriptor";
2490 }
2491
2492 /* ---------------------------------------------------------------------- */
2493
2494 static void do_hub(struct usb_dev_handle *fd, unsigned has_tt)
2495 {
2496         unsigned char buf [7 /* base descriptor */
2497                         + 2 /* bitmasks */ * HUB_STATUS_BYTELEN ];
2498         int i, ret;
2499
2500         ret = usb_control_msg(fd,
2501                         USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_DEVICE,
2502                         USB_REQ_GET_DESCRIPTOR,
2503                         0x29 << 8, 0,
2504                         buf, sizeof buf, CTRL_TIMEOUT);
2505         if (ret < 9 /* at least one port's bitmasks */) {
2506                 if (ret >= 0)
2507                         fprintf(stderr,
2508                                 "incomplete hub descriptor, %d bytes\n",
2509                                 ret);
2510                 /* Linux returns EHOSTUNREACH for suspended devices */
2511                 else if (errno != EHOSTUNREACH)
2512                         perror ("can't get hub descriptor");
2513                 return;
2514         }
2515         dump_hub("", buf, has_tt);
2516
2517         printf(" Hub Port Status:\n");
2518         for (i = 0; i < buf[2]; i++) {
2519                 unsigned char stat [4];
2520
2521                 ret = usb_control_msg(fd,
2522                                 USB_ENDPOINT_IN | USB_TYPE_CLASS
2523                                         | USB_RECIP_OTHER,
2524                                 USB_REQ_GET_STATUS,
2525                                 0, i + 1,
2526                                 stat, sizeof stat,
2527                                 CTRL_TIMEOUT);
2528                 if (ret < 0) {
2529                         fprintf(stderr,
2530                                 "cannot read port %d status, %s (%d)\n",
2531                                 i + 1, strerror(errno), errno);
2532                         break;
2533                 }
2534
2535                 printf("   Port %d: %02x%02x.%02x%02x", i + 1,
2536                         stat[3], stat [2],
2537                         stat[1], stat [0]);
2538                 /* CAPS are used to highlight "transient" states */
2539                 printf("%s%s%s%s%s",
2540                         (stat[2] & 0x10) ? " C_RESET" : "",
2541                         (stat[2] & 0x08) ? " C_OC" : "",
2542                         (stat[2] & 0x04) ? " C_SUSPEND" : "",
2543                         (stat[2] & 0x02) ? " C_ENABLE" : "",
2544                         (stat[2] & 0x01) ? " C_CONNECT" : "");
2545                 printf("%s%s%s%s%s%s%s%s%s%s\n",
2546                         (stat[1] & 0x10) ? " indicator" : "",
2547                         (stat[1] & 0x08) ? " test" : "",
2548                         (stat[1] & 0x04) ? " highspeed" : "",
2549                         (stat[1] & 0x02) ? " lowspeed" : "",
2550                         (stat[1] & 0x01) ? " power" : "",
2551                         (stat[0] & 0x10) ? " RESET" : "",
2552                         (stat[0] & 0x08) ? " oc" : "",
2553                         (stat[0] & 0x04) ? " suspend" : "",
2554                         (stat[0] & 0x02) ? " enable" : "",
2555                         (stat[0] & 0x01) ? " connect" : "");
2556         }
2557 }
2558
2559 static void do_dualspeed(struct usb_dev_handle *fd)
2560 {
2561         unsigned char buf [10];
2562         char cls[128], subcls[128], proto[128];
2563         int ret;
2564
2565         ret = usb_control_msg(fd,
2566                         USB_ENDPOINT_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
2567                         USB_REQ_GET_DESCRIPTOR,
2568                         USB_DT_DEVICE_QUALIFIER << 8, 0,
2569                         buf, sizeof buf, CTRL_TIMEOUT);
2570         if (ret < 0 && errno != EPIPE)
2571                 perror ("can't get device qualifier");
2572
2573         /* all dual-speed devices have a qualifier */
2574         if (ret != sizeof buf
2575                         || buf[0] != ret
2576                         || buf[1] != USB_DT_DEVICE_QUALIFIER)
2577                 return;
2578
2579         get_class_string(cls, sizeof(cls),
2580                         buf[4]);
2581         get_subclass_string(subcls, sizeof(subcls),
2582                         buf[4], buf[5]);
2583         get_protocol_string(proto, sizeof(proto),
2584                         buf[4], buf[5], buf[6]);
2585         printf("Device Qualifier (for other device speed):\n"
2586                "  bLength             %5u\n"
2587                "  bDescriptorType     %5u\n"
2588                "  bcdUSB              %2x.%02x\n"
2589                "  bDeviceClass        %5u %s\n"
2590                "  bDeviceSubClass     %5u %s\n"
2591                "  bDeviceProtocol     %5u %s\n"
2592                "  bMaxPacketSize0     %5u\n"
2593                "  bNumConfigurations  %5u\n",
2594                buf[0], buf[1],
2595                buf[3], buf[2],
2596                buf[4], cls,
2597                buf[5], subcls,
2598                buf[6], proto,
2599                buf[7], buf[8]);
2600
2601         /* FIXME also show the OTHER_SPEED_CONFIG descriptors */
2602 }
2603
2604 static void do_debug(struct usb_dev_handle *fd)
2605 {
2606         unsigned char buf [4];
2607         int ret;
2608
2609         ret = usb_control_msg(fd,
2610                         USB_ENDPOINT_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
2611                         USB_REQ_GET_DESCRIPTOR,
2612                         USB_DT_DEBUG << 8, 0,
2613                         buf, sizeof buf, CTRL_TIMEOUT);
2614         if (ret < 0 && errno != EPIPE)
2615                 perror ("can't get debug descriptor");
2616
2617         /* some high speed devices are also "USB2 debug devices", meaning
2618          * you can use them with some EHCI implementations as another kind
2619          * of system debug channel:  like JTAG, RS232, or a console.
2620          */
2621         if (ret != sizeof buf
2622                         || buf[0] != ret
2623                         || buf[1] != USB_DT_DEBUG)
2624                 return;
2625
2626         printf("Debug descriptor:\n"
2627                "  bLength              %4u\n"
2628                "  bDescriptorType      %4u\n"
2629                "  bDebugInEndpoint     0x%02x\n"
2630                "  bDebugOutEndpoint    0x%02x\n",
2631                buf[0], buf[1],
2632                buf[2], buf[3]);
2633 }
2634
2635 static unsigned char *find_otg(unsigned char *buf, int buflen)
2636 {
2637         if (!buf)
2638                 return 0;
2639         while (buflen >= 3) {
2640                 if (buf[0] == 3 && buf[1] == USB_DT_OTG)
2641                         return buf;
2642                 if (buf[0] > buflen)
2643                         return 0;
2644                 buflen -= buf[0];
2645                 buf += buf[0];
2646         }
2647         return 0;
2648 }
2649
2650 static int do_otg(struct usb_config_descriptor *config)
2651 {
2652         unsigned        i, k;
2653         int             j;
2654         unsigned char   *desc;
2655
2656         /* each config of an otg device has an OTG descriptor */
2657         desc = find_otg(config->extra, config->extralen);
2658         for (i = 0; !desc && i < config->bNumInterfaces; i++) {
2659                 struct usb_interface *intf;
2660
2661                 intf = &config->interface [i];
2662                 for (j = 0; !desc && j < intf->num_altsetting; j++) {
2663                         struct usb_interface_descriptor *alt;
2664
2665                         alt = &intf->altsetting[j];
2666                         desc = find_otg(alt->extra, alt->extralen);
2667                         for (k = 0; !desc && k < alt->bNumEndpoints; k++) {
2668                                 struct usb_endpoint_descriptor *ep;
2669
2670                                 ep = &alt->endpoint[k];
2671                                 desc = find_otg(ep->extra, ep->extralen);
2672                         }
2673                 }
2674         }
2675         if (!desc)
2676                 return 0;
2677
2678         printf("OTG Descriptor:\n"
2679                 "  bLength               %3u\n"
2680                 "  bDescriptorType       %3u\n"
2681                 "  bmAttributes         0x%02x\n"
2682                 "%s%s",
2683                 desc[0], desc[1], desc[2],
2684                 (desc[2] & 0x01)
2685                         ? "    SRP (Session Request Protocol)\n" : "",
2686                 (desc[2] & 0x02)
2687                         ? "    HNP (Host Negotiation Protocol)\n" : "");
2688         return 1;
2689 }
2690
2691 static void
2692 dump_device_status(struct usb_dev_handle *fd, int otg, int wireless)
2693 {
2694         unsigned char status[8];
2695         int ret;
2696
2697         ret = usb_control_msg(fd, USB_ENDPOINT_IN | USB_TYPE_STANDARD
2698                                 | USB_RECIP_DEVICE,
2699                         USB_REQ_GET_STATUS,
2700                         0, 0,
2701                         status, 2,
2702                         CTRL_TIMEOUT);
2703         if (ret < 0) {
2704                 fprintf(stderr,
2705                         "cannot read device status, %s (%d)\n",
2706                         strerror(errno), errno);
2707                 return;
2708         }
2709
2710         printf("Device Status:     0x%02x%02x\n",
2711                         status[1], status[0]);
2712         if (status[0] & (1 << 0))
2713                 printf("  Self Powered\n");
2714         else
2715                 printf("  (Bus Powered)\n");
2716         if (status[0] & (1 << 1))
2717                 printf("  Remote Wakeup Enabled\n");
2718         if (status[0] & (1 << 2)) {
2719                 /* for high speed devices */
2720                 if (!wireless)
2721                         printf("  Test Mode\n");
2722                 /* for devices with Wireless USB support */
2723                 else
2724                         printf("  Battery Powered\n");
2725         }
2726         /* if both HOST and DEVICE support OTG */
2727         if (otg) {
2728                 if (status[0] & (1 << 3))
2729                         printf("  HNP Enabled\n");
2730                 if (status[0] & (1 << 4))
2731                         printf("  HNP Capable\n");
2732                 if (status[0] & (1 << 5))
2733                         printf("  ALT port is HNP Capable\n");
2734         }
2735         /* for high speed devices with debug descriptors */
2736         if (status[0] & (1 << 6))
2737                 printf("  Debug Mode\n");
2738
2739         if (!wireless)
2740                 return;
2741
2742         /* Wireless USB exposes FIVE different types of device status,
2743          * accessed by distinct wIndex values.
2744          */
2745         ret = usb_control_msg(fd, USB_ENDPOINT_IN | USB_TYPE_STANDARD
2746                                 | USB_RECIP_DEVICE,
2747                         USB_REQ_GET_STATUS,
2748                         0, 1 /* wireless status */,
2749                         status, 1,
2750                         CTRL_TIMEOUT);
2751         if (ret < 0) {
2752                 fprintf(stderr,
2753                         "cannot read wireless %s, %s (%d)\n",
2754                         "status",
2755                         strerror(errno), errno);
2756                 return;
2757         }
2758         printf("Wireless Status:     0x%02x\n", status[0]);
2759         if (status[0] & (1 << 0))
2760                 printf("  TX Drp IE\n");
2761         if (status[0] & (1 << 1))
2762                 printf("  Transmit Packet\n");
2763         if (status[0] & (1 << 2))
2764                 printf("  Count Packets\n");
2765         if (status[0] & (1 << 3))
2766                 printf("  Capture Packet\n");
2767
2768         ret = usb_control_msg(fd, USB_ENDPOINT_IN | USB_TYPE_STANDARD
2769                                 | USB_RECIP_DEVICE,
2770                         USB_REQ_GET_STATUS,
2771                         0, 2 /* Channel Info */,
2772                         status, 1,
2773                         CTRL_TIMEOUT);
2774         if (ret < 0) {
2775                 fprintf(stderr,
2776                         "cannot read wireless %s, %s (%d)\n",
2777                         "channel info",
2778                         strerror(errno), errno);
2779                 return;
2780         }
2781         printf("Channel Info:        0x%02x\n", status[0]);
2782
2783         /* 3=Received data: many bytes, for count packets or capture packet */
2784
2785         ret = usb_control_msg(fd, USB_ENDPOINT_IN | USB_TYPE_STANDARD
2786                                 | USB_RECIP_DEVICE,
2787                         USB_REQ_GET_STATUS,
2788                         0, 3 /* MAS Availability */,
2789                         status, 8,
2790                         CTRL_TIMEOUT);
2791         if (ret < 0) {
2792                 fprintf(stderr,
2793                         "cannot read wireless %s, %s (%d)\n",
2794                         "MAS info",
2795                         strerror(errno), errno);
2796                 return;
2797         }
2798         printf("MAS Availability:    ");
2799         dump_bytes(status, 8);
2800
2801         ret = usb_control_msg(fd, USB_ENDPOINT_IN | USB_TYPE_STANDARD
2802                                 | USB_RECIP_DEVICE,
2803                         USB_REQ_GET_STATUS,
2804                         0, 5 /* Current Transmit Power */,
2805                         status, 2,
2806                         CTRL_TIMEOUT);
2807         if (ret < 0) {
2808                 fprintf(stderr,
2809                         "cannot read wireless %s, %s (%d)\n",
2810                         "transmit power",
2811                         strerror(errno), errno);
2812                 return;
2813         }
2814         printf("Transmit Power:\n");
2815         printf(" TxNotification:     0x%02x\n", status[0]);
2816         printf(" TxBeacon:     :     0x%02x\n", status[1]);
2817 }
2818
2819 static int do_wireless(struct usb_dev_handle *fd)
2820 {
2821         /* FIXME fetch and dump BOS etc */
2822         if (fd)
2823                 return 0;
2824         return 0;
2825 }
2826
2827 static void dumpdev(struct usb_device *dev)
2828 {
2829         struct usb_dev_handle *udev;
2830         int i;
2831         int otg, wireless;
2832
2833         otg = wireless = 0;
2834         udev = usb_open(dev);
2835         if (!udev)
2836                 fprintf(stderr, "Couldn't open device, some information "
2837                         "will be missing\n");
2838
2839         dump_device(udev, &dev->descriptor);
2840         if (dev->descriptor.bcdUSB >= 0x0250)
2841                 wireless = do_wireless(udev);
2842         if (dev->config) {
2843                 otg = do_otg(&dev->config[0]) || otg;
2844                 for (i = 0; i < dev->descriptor.bNumConfigurations;
2845                                 i++) {
2846                         dump_config(udev, &dev->config[i]);
2847                 }
2848         }
2849         if (!udev)
2850                 return;
2851
2852         if (dev->descriptor.bDeviceClass == USB_CLASS_HUB)
2853                 do_hub(udev, dev->descriptor.bDeviceProtocol);
2854         if (dev->descriptor.bcdUSB >= 0x0200) {
2855                 do_dualspeed(udev);
2856                 do_debug(udev);
2857         }
2858         dump_device_status(udev, otg, wireless);
2859         usb_close(udev);
2860 }
2861
2862 /* ---------------------------------------------------------------------- */
2863
2864 static int dump_one_device(const char *path)
2865 {
2866         struct usb_device *dev;
2867         char vendor[128], product[128];
2868
2869         dev = get_usb_device(path);
2870         if (!dev) {
2871                 fprintf(stderr, "Cannot open %s\n", path);
2872                 return 1;
2873         }
2874         get_vendor_string(vendor, sizeof(vendor), dev->descriptor.idVendor);
2875         get_product_string(product, sizeof(product), dev->descriptor.idVendor, dev->descriptor.idProduct);
2876         printf("Device: ID %04x:%04x %s %s\n", dev->descriptor.idVendor,
2877                                                dev->descriptor.idProduct,
2878                                                vendor,
2879                                                product);
2880         dumpdev(dev);
2881         return 0;
2882 }
2883
2884 static int list_devices(int busnum, int devnum, int vendorid, int productid)
2885 {
2886         struct usb_bus *bus;
2887         struct usb_device *dev;
2888         char vendor[128], product[128];
2889         int status;
2890
2891         status=1; /* 1 device not found, 0 device found */
2892
2893         for (bus = usb_busses; bus; bus = bus->next) {
2894                 if (busnum != -1 && strtol(bus->dirname, NULL, 10) != busnum)
2895                         continue;
2896                 for (dev = bus->devices; dev; dev = dev->next) {
2897                         if (devnum != -1 && strtol(dev->filename, NULL, 10)
2898                                         != devnum)
2899                                 continue;
2900                         if ((vendorid != -1 && vendorid
2901                                                 != dev->descriptor.idVendor)
2902                                         || (productid != -1 && productid
2903                                                 != dev->descriptor.idProduct))
2904                                 continue;
2905                         status = 0;
2906                         get_vendor_string(vendor, sizeof(vendor),
2907                                         dev->descriptor.idVendor);
2908                         get_product_string(product, sizeof(product),
2909                                         dev->descriptor.idVendor,
2910                                         dev->descriptor.idProduct);
2911                         if (verblevel > 0)
2912                                 printf("\n");
2913                         printf("Bus %s Device %s: ID %04x:%04x %s %s\n",
2914                                         bus->dirname, dev->filename,
2915                                         dev->descriptor.idVendor,
2916                                         dev->descriptor.idProduct,
2917                                         vendor, product);
2918                         if (verblevel > 0)
2919                                 dumpdev(dev);
2920                 }
2921         }
2922         return(status);
2923 }
2924
2925 /* ---------------------------------------------------------------------- */
2926
2927 void devtree_busconnect(struct usbbusnode *bus)
2928 {
2929         bus = bus;      /* reduce compiler warnings */
2930 }
2931
2932 void devtree_busdisconnect(struct usbbusnode *bus)
2933 {
2934         bus = bus;      /* reduce compiler warnings */
2935 }
2936
2937 void devtree_devconnect(struct usbdevnode *dev)
2938 {
2939         dev = dev;      /* reduce compiler warnings */
2940 }
2941
2942 void devtree_devdisconnect(struct usbdevnode *dev)
2943 {
2944         dev = dev;      /* reduce compiler warnings */
2945 }
2946
2947 static int treedump(void)
2948 {
2949         int fd;
2950         char buf[512];
2951
2952         snprintf(buf, sizeof(buf), "%s/devices", procbususb);
2953         if (access(buf, R_OK) < 0)
2954                 return lsusb_t();
2955         if ((fd = open(buf, O_RDONLY)) == -1) {
2956                 fprintf(stderr, "cannot open %s, %s (%d)\n", buf, strerror(errno), errno);
2957                 return(1);
2958         }
2959         devtree_parsedevfile(fd);
2960         close(fd);
2961         devtree_dump();
2962         return(0);
2963 }
2964
2965 /* ---------------------------------------------------------------------- */
2966
2967 int main(int argc, char *argv[])
2968 {
2969         static const struct option long_options[] = {
2970                 { "version", 0, 0, 'V' },
2971                 { "verbose", 0, 0, 'v' },
2972                 { 0, 0, 0, 0 }
2973         };
2974         int c, err = 0;
2975         unsigned int allowctrlmsg = 0, treemode = 0;
2976         int bus = -1, devnum = -1, vendor = -1, product = -1;
2977         const char *devdump = NULL;
2978         char *cp;
2979         int status;
2980
2981         while ((c = getopt_long(argc, argv, "D:vxtP:p:s:d:V",
2982                         long_options, NULL)) != EOF) {
2983                 switch(c) {
2984                 case 'V':
2985                         printf("lsusb (" PACKAGE ") " VERSION "\n");
2986                         exit(0);
2987
2988                 case 'v':
2989                         verblevel++;
2990                         break;
2991
2992                 case 'x':
2993                         allowctrlmsg = 1;
2994                         break;
2995
2996                 case 't':
2997                         treemode = 1;
2998                         break;
2999
3000                 case 's':
3001                         cp = strchr(optarg, ':');
3002                         if (cp) {
3003                                 *cp++ = 0;
3004                                 if (*optarg)
3005                                         bus = strtoul(optarg, NULL, 10);
3006                                 if (*cp)
3007                                         devnum = strtoul(cp, NULL, 10);
3008                         } else {
3009                                 if (*optarg)
3010                                         devnum = strtoul(optarg, NULL, 10);
3011                         }
3012                         break;
3013
3014                 case 'd':
3015                         cp = strchr(optarg, ':');
3016                         if (!cp) {
3017                                 err++;
3018                                 break;
3019                         }
3020                         *cp++ = 0;
3021                         if (*optarg)
3022                                 vendor = strtoul(optarg, NULL, 16);
3023                         if (*cp)
3024                                 product = strtoul(cp, NULL, 16);
3025                         break;
3026
3027                 case 'D':
3028                         devdump = optarg;
3029                         break;
3030
3031                 case '?':
3032                 default:
3033                         err++;
3034                         break;
3035                 }
3036         }
3037         if (err || argc > optind) {
3038                 fprintf(stderr, "Usage: lsusb [options]...\n"
3039                         "List USB devices\n"
3040                         "  -v, --verbose\n"
3041                         "      Increase verbosity (show descriptors)\n"
3042                         "  -s [[bus]:][devnum]\n"
3043                         "      Show only devices with specified device and/or\n"
3044                         "      bus numbers (in decimal)\n"
3045                         "  -d vendor:[product]\n"
3046                         "      Show only devices with the specified vendor and\n"
3047                         "      product ID numbers (in hexadecimal)\n"
3048                         "  -D device\n"
3049                         "      Selects which device lsusb will examine\n"
3050                         "  -t\n"
3051                         "      Dump the physical USB device hierarchy as a tree\n"
3052                         "  -V, --version\n"
3053                         "      Show version of program\n"
3054                         );
3055                 exit(1);
3056         }
3057
3058         /* by default, print names as well as numbers */
3059         err = names_init(DATADIR "/usb.ids");
3060 #ifdef HAVE_LIBZ
3061         if (err != 0)
3062                 err = names_init(DATADIR "/usb.ids.gz");
3063 #endif
3064         if (err != 0)
3065                 fprintf(stderr, "%s: cannot open \"%s\", %s\n",
3066                                 argv[0],
3067                                 DATADIR "/usb.ids",
3068                                 strerror(err));
3069         status = 0;
3070
3071         usb_init();
3072
3073         usb_find_busses();
3074         usb_find_devices();
3075
3076         if (treemode) {
3077                 /* treemode requires at least verblevel 1 */
3078                 verblevel += 1 - VERBLEVEL_DEFAULT;
3079                 status = treedump();
3080         } else if (devdump)
3081                 status = dump_one_device(devdump);
3082         else
3083                 status = list_devices(bus, devnum, vendor, product);
3084         return status;
3085 }