This gives us more consistency in handling of incorrect descriptor
buffer lengths, and improves whitespace/alignment consistency.

Signed-off-by: Michael Drake <michael.dr...@codethink.co.uk>
---
 Makefile.am |   2 +
 lsusb.c     | 751 ++++--------------------------------------------------------
 2 files changed, 50 insertions(+), 703 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 117e94b..46fd7b5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -19,6 +19,8 @@ lsusb_SOURCES = \
        lsusb.c lsusb.h \
        lsusb-t.c \
        list.h \
+       desc-defs.c desc-defs.h \
+       desc-dump.c desc-dump.h \
        names.c names.h \
        usb-spec.h \
        usbmisc.c usbmisc.h
diff --git a/lsusb.c b/lsusb.c
index 26df98e..fb5e6ee 100644
--- a/lsusb.c
+++ b/lsusb.c
@@ -31,6 +31,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
+#include <stdbool.h>
 
 #ifdef HAVE_BYTESWAP_H
 #include <byteswap.h>
@@ -42,6 +43,8 @@
 #include "lsusb.h"
 #include "names.h"
 #include "usbmisc.h"
+#include "desc-defs.h"
+#include "desc-dump.h"
 
 #include <getopt.h>
 
@@ -159,7 +162,7 @@ static void dump_videostreaming_interface(const unsigned 
char *buf);
 static void dump_dfu_interface(const unsigned char *buf);
 static char *dump_comm_descriptor(libusb_device_handle *dev, const unsigned 
char *buf, char *indent);
 static void dump_hid_device(libusb_device_handle *dev, const struct 
libusb_interface_descriptor *interface, const unsigned char *buf);
-static void dump_audiostreaming_endpoint(const unsigned char *buf, int 
protocol);
+static void dump_audiostreaming_endpoint(libusb_device_handle *dev, const 
unsigned char *buf, int protocol);
 static void dump_midistreaming_endpoint(const unsigned char *buf);
 static void dump_hub(const char *prefix, const unsigned char *p, int tt_type);
 static void dump_ccid_device(const unsigned char *buf);
@@ -626,7 +629,7 @@ static void dump_altsetting(libusb_device_handle *dev, 
const struct libusb_inter
                                        case USB_DT_CS_ENDPOINT:
                                                switch 
(interface->bInterfaceSubClass) {
                                                case 2:
-                                                       
dump_audiostreaming_endpoint(buf, interface->bInterfaceProtocol);
+                                                       
dump_audiostreaming_endpoint(dev, buf, interface->bInterfaceProtocol);
                                                        break;
                                                default:
                                                        goto dump;
@@ -756,7 +759,7 @@ static void dump_endpoint(libusb_device_handle *dev, const 
struct libusb_interfa
                        switch (buf[1]) {
                        case USB_DT_CS_ENDPOINT:
                                if (interface->bInterfaceClass == 1 && 
interface->bInterfaceSubClass == 2)
-                                       dump_audiostreaming_endpoint(buf, 
interface->bInterfaceProtocol);
+                                       dump_audiostreaming_endpoint(dev, buf, 
interface->bInterfaceProtocol);
                                else if (interface->bInterfaceClass == 1 && 
interface->bInterfaceSubClass == 3)
                                        dump_midistreaming_endpoint(buf);
                                break;
@@ -880,125 +883,32 @@ static void dump_unit(unsigned int data, unsigned int 
len)
  * Audio Class descriptor dump
  */
 
-struct bmcontrol {
-       const char *name;
-       unsigned int bit;
-};
-
-static const struct bmcontrol uac2_interface_header_bmcontrols[] = {
-       { "Latency control",    0 },
-       { NULL }
-};
-
-static const struct bmcontrol uac_fu_bmcontrols[] = {
-       { "Mute",               0 },
-       { "Volume",             1 },
-       { "Bass",               2 },
-       { "Mid",                3 },
-       { "Treble",             4 },
-       { "Graphic Equalizer",  5 },
-       { "Automatic Gain",     6 },
-       { "Delay",              7 },
-       { "Bass Boost",         8 },
-       { "Loudness",           9 },
-       { "Input gain",         10 },
-       { "Input gain pad",     11 },
-       { "Phase inverter",     12 },
-       { NULL }
-};
-
-static const struct bmcontrol uac2_input_term_bmcontrols[] = {
-       { "Copy Protect",       0 },
-       { "Connector",          1 },
-       { "Overload",           2 },
-       { "Cluster",            3 },
-       { "Underflow",          4 },
-       { "Overflow",           5 },
-       { NULL }
-};
-
-static const struct bmcontrol uac2_output_term_bmcontrols[] = {
-       { "Copy Protect",       0 },
-       { "Connector",          1 },
-       { "Overload",           2 },
-       { "Underflow",          3 },
-       { "Overflow",           4 },
-       { NULL }
-};
-
-static const struct bmcontrol uac2_mixer_unit_bmcontrols[] = {
-       { "Cluster",            0 },
-       { "Underflow",          1 },
-       { "Overflow",           2 },
-       { NULL }
-};
-
-static const struct bmcontrol uac2_extension_unit_bmcontrols[] = {
-       { "Enable",             0 },
-       { "Cluster",            1 },
-       { "Underflow",          2 },
-       { "Overflow",           3 },
-       { NULL }
-};
-
-static const struct bmcontrol uac2_clock_source_bmcontrols[] = {
-       { "Clock Frequency",    0 },
-       { "Clock Validity",     1 },
-       { NULL }
-};
-
-static const struct bmcontrol uac2_clock_selector_bmcontrols[] = {
-       { "Clock Selector",     0 },
-       { NULL }
-};
-
-static const struct bmcontrol uac2_clock_multiplier_bmcontrols[] = {
-       { "Clock Numerator",    0 },
-       { "Clock Denominator",  1 },
-       { NULL }
-};
-
-static const struct bmcontrol uac2_selector_bmcontrols[] = {
-       { "Selector",   0 },
-       { NULL }
-};
-
-static void dump_audio_bmcontrols(const char *prefix, int bmcontrols, const 
struct bmcontrol *list, int protocol)
+static void dump_audio_subtype(libusb_device_handle *dev,
+                               const char *name,
+                               const struct desc * const desc[3],
+                               const unsigned char *buf,
+                               int protocol,
+                               unsigned int indent)
 {
-       while (list->name) {
-               switch (protocol) {
-               case USB_AUDIO_CLASS_1:
-                       if (bmcontrols & (1 << list->bit))
-                               printf("%s%s Control\n", prefix, list->name);
-
-                       break;
+       static const char * const strings[] = { "UAC1", "UAC2" };
+       unsigned int idx = 0;
 
-               case USB_AUDIO_CLASS_2: {
-                       const char * const ctrl_type[] = { "read-only", 
"ILLEGAL (0b10)", "read/write" };
-                       int ctrl = (bmcontrols >> (list->bit * 2)) & 0x3;
-
-                       if (ctrl)
-                               printf("%s%s Control (%s)\n", prefix, 
list->name, ctrl_type[ctrl-1]);
-
-                       break;
-               }
+       switch (protocol) {
+       case USB_AUDIO_CLASS_2: idx = 1; break;
+       }
 
-               } /* switch */
+       printf("(%s)\n", name);
 
-               list++;
+       if (desc[idx] == NULL) {
+               printf("%*sWarning: %s descriptors are illegal for %s\n",
+                      indent * 2, "", name, strings[idx]);
+               return;
        }
-}
 
-static const char * const chconfig_uac2[] = {
-       "Front Left (FL)", "Front Right (FR)", "Front Center (FC)", "Low 
Frequency Effects (LFE)",
-       "Back Left (BL)", "Back Right (BR)", "Front Left of Center (FLC)", 
"Front Right of Center (FRC)", "Back Center (BC)",
-       "Side Left (SL)", "Side Right (SR)",
-       "Top Center (TC)", "Top Front Left (TFL)", "Top Front Center (TFC)", 
"Top Front Right (TFR)", "Top Back Left (TBL)",
-       "Top Back Center (TBC)", "Top Back Right (TBR)", "Top Front Left of 
Center (TFLC)", "Top Front Right of Center (TFRC)",
-       "Left Low Frequency Effects (LLFE)", "Right Low Frequency Effects 
(RLFE)",
-       "Top Side Left (TSL)", "Top Side Right (TSR)", "Bottom Center (BC)",
-       "Back Left of Center (BLC)", "Back Right of Center (BRC)"
-};
+       /* Skip the first three bytes; those common fields have already
+        * been dumped. */
+       desc_dump(dev, desc[idx], buf + 3, buf[0] - 3, indent);
+}
 
 /* USB Audio Class subtypes */
 enum uac_interface_subtype {
@@ -1081,16 +991,6 @@ static enum uac_interface_subtype 
get_uac_interface_subtype(unsigned char c, int
 static void dump_audiocontrol_interface(libusb_device_handle *dev, const 
unsigned char *buf, int protocol)
 {
        enum uac_interface_subtype subtype;
-       static const char * const chconfig[] = {
-               "Left Front (L)", "Right Front (R)", "Center Front (C)", "Low 
Frequency Enhancement (LFE)",
-               "Left Surround (LS)", "Right Surround (RS)", "Left of Center 
(LC)", "Right of Center (RC)",
-               "Surround (S)", "Side Left (SL)", "Side Right (SR)", "Top (T)"
-       };
-       static const char * const clock_source_attrs[] = {
-               "External", "Internal fixed", "Internal variable", "Internal 
programmable"
-       };
-       unsigned int i, chcfg, j, k, N, termt;
-       char *chnames = NULL, *term = NULL, termts[128];
 
        if (buf[1] != USB_DT_CS_INTERFACE)
                printf("      Warning: Invalid descriptor\n");
@@ -1106,514 +1006,55 @@ static void 
dump_audiocontrol_interface(libusb_device_handle *dev, const unsigne
 
        switch (subtype) {
        case UAC_INTERFACE_SUBTYPE_HEADER:
-               printf("(HEADER)\n");
-               switch (protocol) {
-               case USB_AUDIO_CLASS_1:
-                       if (buf[0] < 8+buf[7])
-                               printf("      Warning: Descriptor too short\n");
-                       printf("        bcdADC              %2x.%02x\n"
-                              "        wTotalLength        %5u\n"
-                              "        bInCollection       %5u\n",
-                              buf[4], buf[3], buf[5] | (buf[6] << 8), buf[7]);
-                       for (i = 0; i < buf[7]; i++)
-                               printf("        baInterfaceNr(%2u)   %5u\n", i, 
buf[8+i]);
-                       dump_junk(buf, "        ", 8+buf[7]);
-                       break;
-               case USB_AUDIO_CLASS_2:
-                       if (buf[0] < 9)
-                               printf("      Warning: Descriptor too short\n");
-                       printf("        bcdADC              %2x.%02x\n"
-                              "        bCategory           %5u\n"
-                              "        wTotalLength        %5u\n"
-                              "        bmControl            0x%02x\n",
-                              buf[4], buf[3], buf[5], buf[6] | (buf[7] << 8), 
buf[8]);
-                       dump_audio_bmcontrols("          ", buf[8], 
uac2_interface_header_bmcontrols, protocol);
-                       break;
-               }
+               dump_audio_subtype(dev, "HEADER", desc_audio_ac_header, buf, 
protocol, 4);
                break;
 
        case UAC_INTERFACE_SUBTYPE_INPUT_TERMINAL:
-               printf("(INPUT_TERMINAL)\n");
-               termt = buf[4] | (buf[5] << 8);
-               get_audioterminal_string(termts, sizeof(termts), termt);
-
-               switch (protocol) {
-               case USB_AUDIO_CLASS_1:
-                       chnames = get_dev_string(dev, buf[10]);
-                       term = get_dev_string(dev, buf[11]);
-                       if (buf[0] < 12)
-                               printf("      Warning: Descriptor too short\n");
-                       chcfg = buf[8] | (buf[9] << 8);
-                       printf("        bTerminalID         %5u\n"
-                              "        wTerminalType      0x%04x %s\n"
-                              "        bAssocTerminal      %5u\n"
-                              "        bNrChannels         %5u\n"
-                              "        wChannelConfig     0x%04x\n",
-                              buf[3], termt, termts, buf[6], buf[7], chcfg);
-                       for (i = 0; i < 12; i++)
-                               if ((chcfg >> i) & 1)
-                                       printf("          %s\n", chconfig[i]);
-                       printf("        iChannelNames       %5u %s\n"
-                              "        iTerminal           %5u %s\n",
-                              buf[10], chnames, buf[11], term);
-                       dump_junk(buf, "        ", 12);
-                       break;
-               case USB_AUDIO_CLASS_2:
-                       chnames = get_dev_string(dev, buf[13]);
-                       term = get_dev_string(dev, buf[16]);
-                       if (buf[0] < 17)
-                               printf("      Warning: Descriptor too short\n");
-                       chcfg = buf[9] | (buf[10] << 8) | (buf[11] << 16) | 
(buf[12] << 24);
-                       printf("        bTerminalID         %5u\n"
-                              "        wTerminalType      0x%04x %s\n"
-                              "        bAssocTerminal      %5u\n"
-                              "        bCSourceID          %5d\n"
-                              "        bNrChannels         %5u\n"
-                              "        bmChannelConfig   0x%08x\n",
-                              buf[3], termt, termts, buf[6], buf[7], buf[8], 
chcfg);
-                       for (i = 0; i < 26; i++)
-                               if ((chcfg >> i) & 1)
-                                       printf("          %s\n", 
chconfig_uac2[i]);
-                       printf("        bmControls    0x%04x\n", buf[14] | 
(buf[15] << 8));
-                       dump_audio_bmcontrols("          ", buf[14] | (buf[15] 
<< 8), uac2_input_term_bmcontrols, protocol);
-                       printf("        iChannelNames       %5u %s\n"
-                              "        iTerminal           %5u %s\n",
-                              buf[13], chnames, buf[16], term);
-                       dump_junk(buf, "        ", 17);
-                       break;
-               } /* switch (protocol) */
-
+               dump_audio_subtype(dev, "INPUT_TERMINAL", 
desc_audio_ac_input_terminal, buf, protocol, 4);
                break;
 
        case UAC_INTERFACE_SUBTYPE_OUTPUT_TERMINAL:
-               printf("(OUTPUT_TERMINAL)\n");
-               switch (protocol) {
-               case USB_AUDIO_CLASS_1:
-                       term = get_dev_string(dev, buf[8]);
-                       termt = buf[4] | (buf[5] << 8);
-                       get_audioterminal_string(termts, sizeof(termts), termt);
-                       if (buf[0] < 9)
-                               printf("      Warning: Descriptor too short\n");
-                       printf("        bTerminalID         %5u\n"
-                              "        wTerminalType      0x%04x %s\n"
-                              "        bAssocTerminal      %5u\n"
-                              "        bSourceID           %5u\n"
-                              "        iTerminal           %5u %s\n",
-                              buf[3], termt, termts, buf[6], buf[7], buf[8], 
term);
-                       dump_junk(buf, "        ", 9);
-                       break;
-               case USB_AUDIO_CLASS_2:
-                       term = get_dev_string(dev, buf[11]);
-                       termt = buf[4] | (buf[5] << 8);
-                       get_audioterminal_string(termts, sizeof(termts), termt);
-                       if (buf[0] < 12)
-                               printf("      Warning: Descriptor too short\n");
-                       printf("        bTerminalID         %5u\n"
-                              "        wTerminalType      0x%04x %s\n"
-                              "        bAssocTerminal      %5u\n"
-                              "        bSourceID           %5u\n"
-                              "        bCSourceID          %5u\n"
-                              "        bmControls         0x%04x\n",
-                              buf[3], termt, termts, buf[6], buf[7], buf[8], 
buf[9] | (buf[10] << 8));
-                       dump_audio_bmcontrols("          ", buf[9] | (buf[10] 
<< 8), uac2_output_term_bmcontrols, protocol);
-                       printf("        iTerminal           %5u %s\n", buf[11], 
term);
-                       dump_junk(buf, "        ", 12);
-                       break;
-               } /* switch (protocol) */
-
+               dump_audio_subtype(dev, "OUTPUT_TERMINAL", 
desc_audio_ac_output_terminal, buf, protocol, 4);
                break;
 
        case UAC_INTERFACE_SUBTYPE_MIXER_UNIT:
-               printf("(MIXER_UNIT)\n");
-
-               switch (protocol) {
-               case USB_AUDIO_CLASS_1:
-                       j = buf[4];
-                       k = buf[j+5];
-                       if (j == 0 || k == 0) {
-                               printf("      Warning: mixer with %5u input and 
%5u output channels.\n", j, k);
-                               N = 0;
-                       } else {
-                               N = 1+(j*k-1)/8;
-                       }
-                       chnames = get_dev_string(dev, buf[8+j]);
-                       term = get_dev_string(dev, buf[9+j+N]);
-                       if (buf[0] < 10+j+N)
-                               printf("      Warning: Descriptor too short\n");
-                       chcfg = buf[6+j] | (buf[7+j] << 8);
-                       printf("        bUnitID             %5u\n"
-                              "        bNrInPins           %5u\n",
-                              buf[3], buf[4]);
-                       for (i = 0; i < j; i++)
-                               printf("        baSourceID(%2u)      %5u\n", i, 
buf[5+i]);
-                       printf("        bNrChannels         %5u\n"
-                              "        wChannelConfig     0x%04x\n",
-                              buf[5+j], chcfg);
-                       for (i = 0; i < 12; i++)
-                               if ((chcfg >> i) & 1)
-                                       printf("          %s\n", chconfig[i]);
-                       printf("        iChannelNames       %5u %s\n",
-                              buf[8+j], chnames);
-                       for (i = 0; i < N; i++)
-                               printf("        bmControls         0x%02x\n", 
buf[9+j+i]);
-                       printf("        iMixer              %5u %s\n", 
buf[9+j+N], term);
-                       dump_junk(buf, "        ", 10+j+N);
-                       break;
-
-               case USB_AUDIO_CLASS_2:
-                       j = buf[4];
-                       k = buf[0] - 13 - j;
-                       chnames = get_dev_string(dev, buf[10+j]);
-                       term = get_dev_string(dev, buf[12+j+k]);
-                       chcfg =  buf[6+j] | (buf[7+j] << 8) | (buf[8+j] << 16) 
| (buf[9+j] << 24);
-
-                       printf("        bUnitID             %5u\n"
-                              "        bNrPins             %5u\n",
-                              buf[3], buf[4]);
-                       for (i = 0; i < j; i++)
-                               printf("        baSourceID(%2u)      %5u\n", i, 
buf[5+i]);
-                       printf("        bNrChannels         %5u\n"
-                              "        bmChannelConfig    0x%08x\n", buf[5+j], 
chcfg);
-                       for (i = 0; i < 26; i++)
-                               if ((chcfg >> i) & 1)
-                                       printf("          %s\n", 
chconfig_uac2[i]);
-                       printf("        iChannelNames       %5u %s\n", 
buf[10+j], chnames);
-
-                       N = 0;
-                       for (i = 0; i < k; i++)
-                               N |= buf[11+j+i] << (i * 8);
-
-                       dump_bytes(buf+11+j, k);
-
-                       printf("        bmControls         %02x\n", 
buf[11+j+k]);
-                       dump_audio_bmcontrols("          ", buf[11+j+k], 
uac2_mixer_unit_bmcontrols, protocol);
-
-                       printf("        iMixer             %5u %s\n", 
buf[12+j+k], term);
-                       dump_junk(buf, "        ", 13+j+k);
-                       break;
-               } /* switch (protocol) */
+               dump_audio_subtype(dev, "MIXER_UNIT", desc_audio_ac_mixer_unit, 
buf, protocol, 4);
                break;
 
        case UAC_INTERFACE_SUBTYPE_SELECTOR_UNIT:
-               printf("(SELECTOR_UNIT)\n");
-               switch (protocol) {
-               case USB_AUDIO_CLASS_1:
-                       if (buf[0] < 6+buf[4])
-                               printf("      Warning: Descriptor too short\n");
-                       term = get_dev_string(dev, buf[5+buf[4]]);
-
-                       printf("        bUnitID             %5u\n"
-                              "        bNrInPins           %5u\n",
-                              buf[3], buf[4]);
-                       for (i = 0; i < buf[4]; i++)
-                               printf("        baSource(%2u)        %5u\n", i, 
buf[5+i]);
-                       printf("        iSelector           %5u %s\n",
-                              buf[5+buf[4]], term);
-                       dump_junk(buf, "        ", 6+buf[4]);
-                       break;
-               case USB_AUDIO_CLASS_2:
-                       if (buf[0] < 7+buf[4])
-                               printf("      Warning: Descriptor too short\n");
-                       term = get_dev_string(dev, buf[6+buf[4]]);
-
-                       printf("        bUnitID             %5u\n"
-                              "        bNrInPins           %5u\n",
-                              buf[3], buf[4]);
-                       for (i = 0; i < buf[4]; i++)
-                               printf("        baSource(%2u)        %5u\n", i, 
buf[5+i]);
-                       printf("        bmControls           0x%02x\n", 
buf[5+buf[4]]);
-                       dump_audio_bmcontrols("          ", buf[5+buf[4]], 
uac2_selector_bmcontrols, protocol);
-                       printf("        iSelector           %5u %s\n",
-                              buf[6+buf[4]], term);
-                       dump_junk(buf, "        ", 7+buf[4]);
-                       break;
-               } /* switch (protocol) */
-
+               dump_audio_subtype(dev, "SELECTOR_UNIT", 
desc_audio_ac_selector_unit, buf, protocol, 4);
                break;
 
        case UAC_INTERFACE_SUBTYPE_FEATURE_UNIT:
-               printf("(FEATURE_UNIT)\n");
-
-               switch (protocol) {
-               case USB_AUDIO_CLASS_1:
-                       j = buf[5];
-                       if (!j)
-                               j = 1;
-                       k = (buf[0] - 7) / j;
-                       if (buf[0] < 7+buf[5]*k)
-                               printf("      Warning: Descriptor too short\n");
-                       term = get_dev_string(dev, buf[6+buf[5]*k]);
-                       printf("        bUnitID             %5u\n"
-                              "        bSourceID           %5u\n"
-                              "        bControlSize        %5u\n",
-                              buf[3], buf[4], buf[5]);
-                       for (i = 0; i < k; i++) {
-                               chcfg = buf[6+buf[5]*i];
-                               if (buf[5] > 1)
-                                       chcfg |= (buf[7+buf[5]*i] << 8);
-                               for (j = 0; j < buf[5]; j++)
-                                       printf("        bmaControls(%2u)      
0x%02x\n", i, buf[6+buf[5]*i+j]);
-
-                               dump_audio_bmcontrols("          ", chcfg, 
uac_fu_bmcontrols, protocol);
-                       }
-                       printf("        iFeature            %5u %s\n", 
buf[6+buf[5]*k], term);
-                       dump_junk(buf, "        ", 7+buf[5]*k);
-                       break;
-               case USB_AUDIO_CLASS_2:
-                       if (buf[0] < 10)
-                               printf("      Warning: Descriptor too short\n");
-                       k = (buf[0] - 6) / 4;
-                       printf("        bUnitID             %5u\n"
-                              "        bSourceID           %5u\n",
-                              buf[3], buf[4]);
-                       for (i = 0; i < k; i++) {
-                               chcfg = buf[5+(4*i)] |
-                                       buf[6+(4*i)] << 8 |
-                                       buf[7+(4*i)] << 16 |
-                                       buf[8+(4*i)] << 24;
-                               printf("        bmaControls(%2u)      
0x%08x\n", i, chcfg);
-                               dump_audio_bmcontrols("          ", chcfg, 
uac_fu_bmcontrols, protocol);
-                       }
-                       term = get_dev_string(dev, buf[5+k*4]);
-                       printf("        iFeature            %5u %s\n", 
buf[5+(k*4)], term);
-                       dump_junk(buf, "        ", 6+(k*4));
-                       break;
-               } /* switch (protocol) */
-
+               dump_audio_subtype(dev, "FEATURE_UNIT", 
desc_audio_ac_feature_unit, buf, protocol, 4);
                break;
 
        case UAC_INTERFACE_SUBTYPE_PROCESSING_UNIT:
-               printf("(PROCESSING_UNIT)\n");
-
-               switch (protocol) {
-               case USB_AUDIO_CLASS_1:
-                       j = buf[6];
-                       k = buf[11+j];
-                       chnames = get_dev_string(dev, buf[10+j]);
-                       term = get_dev_string(dev, buf[12+j+k]);
-                       chcfg = buf[8+j] | (buf[9+j] << 8);
-                       if (buf[0] < 13+j+k)
-                               printf("      Warning: Descriptor too short\n");
-                       printf("        bUnitID             %5u\n"
-                              "        wProcessType        %5u\n"
-                              "        bNrPins             %5u\n",
-                              buf[3], buf[4] | (buf[5] << 8), buf[6]);
-                       for (i = 0; i < j; i++)
-                               printf("        baSourceID(%2u)      %5u\n", i, 
buf[7+i]);
-                       printf("        bNrChannels         %5u\n"
-                              "        wChannelConfig     0x%04x\n", buf[7+j], 
chcfg);
-                       for (i = 0; i < 12; i++)
-                               if ((chcfg >> i) & 1)
-                                       printf("          %s\n", chconfig[i]);
-                       printf("        iChannelNames       %5u %s\n"
-                              "        bControlSize        %5u\n", buf[10+j], 
chnames, buf[11+j]);
-                       for (i = 0; i < k; i++)
-                               printf("        bmControls(%2u)       
0x%02x\n", i, buf[12+j+i]);
-                       if (buf[12+j] & 1)
-                               printf("          Enable Processing\n");
-                       printf("        iProcessing         %5u %s\n"
-                              "        Process-Specific    ", buf[12+j+k], 
term);
-                       dump_bytes(buf+(13+j+k), buf[0]-(13+j+k));
-                       break;
-               case USB_AUDIO_CLASS_2:
-                       j = buf[6];
-                       k = buf[0] - 17 - j;
-                       chnames = get_dev_string(dev, buf[12+j]);
-                       term = get_dev_string(dev, buf[15+j+k]);
-                       chcfg =  buf[8+j] |
-                               (buf[9+j] << 8) |
-                               (buf[10+j] << 16) |
-                               (buf[11+j] << 24);
-
-                       printf("        bUnitID             %5u\n"
-                              "        wProcessType        %5u\n"
-                              "        bNrPins             %5u\n",
-                              buf[3], buf[4] | (buf[5] << 8), buf[6]);
-                       for (i = 0; i < j; i++)
-                               printf("        baSourceID(%2u)      %5u\n", i, 
buf[5+i]);
-                       printf("        bNrChannels         %5u\n"
-                              "        bmChannelConfig    0x%08x\n", buf[7+j], 
chcfg);
-                       for (i = 0; i < 26; i++)
-                               if ((chcfg >> i) & 1)
-                                       printf("          %s\n", 
chconfig_uac2[i]);
-                       printf("        iChannelNames       %5u %s\n"
-                              "        bmControls        0x%04x\n", buf[12+j], 
chnames, buf[13+j] | (buf[14+j] << 8));
-                       if (buf[12+j] & 1)
-                               printf("          Enable Processing\n");
-                       printf("        iProcessing         %5u %s\n"
-                              "        Process-Specific    ", buf[15+j], term);
-                       dump_bytes(buf+(16+j), k);
-                       break;
-               } /* switch (protocol) */
-
+               dump_audio_subtype(dev, "PROCESSING_UNIT", 
desc_audio_ac_processing_unit, buf, protocol, 4);
                break;
 
        case UAC_INTERFACE_SUBTYPE_EXTENSION_UNIT:
-               printf("(EXTENSION_UNIT)\n");
-
-               switch (protocol) {
-               case USB_AUDIO_CLASS_1:
-                       j = buf[6];
-                       k = buf[11+j];
-                       chnames = get_dev_string(dev, buf[10+j]);
-                       term = get_dev_string(dev, buf[12+j+k]);
-                       chcfg = buf[8+j] | (buf[9+j] << 8);
-                       if (buf[0] < 13+j+k)
-                               printf("      Warning: Descriptor too short\n");
-                       printf("        bUnitID             %5u\n"
-                              "        wExtensionCode      %5u\n"
-                              "        bNrPins             %5u\n",
-                              buf[3], buf[4] | (buf[5] << 8), buf[6]);
-                       for (i = 0; i < j; i++)
-                               printf("        baSourceID(%2u)      %5u\n", i, 
buf[7+i]);
-                       printf("        bNrChannels         %5u\n"
-                              "        wChannelConfig      %5u\n", buf[7+j], 
chcfg);
-                       for (i = 0; i < 12; i++)
-                               if ((chcfg >> i) & 1)
-                                       printf("          %s\n", chconfig[i]);
-                       printf("        iChannelNames       %5u %s\n"
-                              "        bControlSize        %5u\n", buf[10+j], 
chnames, buf[11+j]);
-                       for (i = 0; i < k; i++)
-                               printf("        bmControls(%2u)       
0x%02x\n", i, buf[12+j+i]);
-                       if (buf[12+j] & 1)
-                               printf("          Enable Processing\n");
-                       printf("        iExtension          %5u %s\n",
-                              buf[12+j+k], term);
-                       dump_junk(buf, "        ", 13+j+k);
-                       break;
-               case USB_AUDIO_CLASS_2:
-                       j = buf[6];
-                       chnames = get_dev_string(dev, buf[13+j]);
-                       term = get_dev_string(dev, buf[15+j]);
-                       chcfg = buf[9+j] | (buf[10+j] << 8) | (buf[11+j] << 16) 
| (buf[12+j] << 24);
-                       if (buf[0] < 16+j)
-                               printf("      Warning: Descriptor too short\n");
-                       printf("        bUnitID             %5u\n"
-                              "        wExtensionCode      %5u\n"
-                              "        bNrPins             %5u\n",
-                              buf[3], buf[4] | (buf[5] << 8), buf[6]);
-                       for (i = 0; i < j; i++)
-                               printf("        baSourceID(%2u)      %5u\n", i, 
buf[7+i]);
-                       printf("        bNrChannels         %5u\n"
-                              "        wChannelConfig      %5u\n", buf[7+j], 
chcfg);
-                       for (i = 0; i < 12; i++)
-                               if ((chcfg >> i) & 1)
-                                       printf("          %s\n", chconfig[i]);
-                       printf("        iChannelNames       %5u %s\n"
-                              "        bmControls        0x%02x\n", buf[13+j], 
chnames, buf[14+j]);
-                       dump_audio_bmcontrols("          ", buf[14+j], 
uac2_extension_unit_bmcontrols, protocol);
-
-                       printf("        iExtension          %5u %s\n",
-                              buf[15+j], term);
-                       dump_junk(buf, "        ", 16+j);
-                       break;
-               } /* switch (protocol) */
-
+               dump_audio_subtype(dev, "EXTENSION_UNIT", 
desc_audio_ac_extension_unit, buf, protocol, 4);
                break;
 
        case UAC_INTERFACE_SUBTYPE_CLOCK_SOURCE:
-               printf ("(CLOCK_SOURCE)\n");
-               if (protocol != USB_AUDIO_CLASS_2)
-                       printf("      Warning: CLOCK_SOURCE descriptors are 
illegal for UAC1\n");
-
-               if (buf[0] < 8)
-                       printf("      Warning: Descriptor too short\n");
-
-               printf("        bClockID            %5u\n"
-                      "        bmAttributes         0x%02x %s Clock %s\n",
-                      buf[3], buf[4], clock_source_attrs[buf[4] & 3],
-                      (buf[4] & 4) ? "(synced to SOF)" : "");
-
-               printf("        bmControls           0x%02x\n", buf[5]);
-               dump_audio_bmcontrols("          ", buf[5], 
uac2_clock_source_bmcontrols, protocol);
-
-               term = get_dev_string(dev, buf[7]);
-               printf("        bAssocTerminal      %5u\n", buf[6]);
-               printf("        iClockSource        %5u %s\n", buf[7], term);
-               dump_junk(buf, "        ", 8);
+               dump_audio_subtype(dev, "CLOCK_SOURCE", 
desc_audio_ac_clock_source, buf, protocol, 4);
                break;
 
        case UAC_INTERFACE_SUBTYPE_CLOCK_SELECTOR:
-               printf("(CLOCK_SELECTOR)\n");
-               if (protocol != USB_AUDIO_CLASS_2)
-                       printf("      Warning: CLOCK_SELECTOR descriptors are 
illegal for UAC1\n");
-
-               if (buf[0] < 7+buf[4])
-                       printf("      Warning: Descriptor too short\n");
-               term = get_dev_string(dev, buf[6+buf[4]]);
-
-               printf("        bUnitID             %5u\n"
-                      "        bNrInPins           %5u\n",
-                      buf[3], buf[4]);
-               for (i = 0; i < buf[4]; i++)
-                       printf("        baCSourceID(%2u)     %5u\n", i, 
buf[5+i]);
-               printf("        bmControls           0x%02x\n", buf[5+buf[4]]);
-               dump_audio_bmcontrols("          ", buf[5+buf[4]], 
uac2_clock_selector_bmcontrols, protocol);
-
-               printf("        iClockSelector      %5u %s\n",
-                      buf[6+buf[4]], term);
-               dump_junk(buf, "        ", 7+buf[4]);
+               dump_audio_subtype(dev, "CLOCK_SELECTOR", 
desc_audio_ac_clock_selector, buf, protocol, 4);
                break;
 
        case UAC_INTERFACE_SUBTYPE_CLOCK_MULTIPLIER:
-               printf("(CLOCK_MULTIPLIER)\n");
-               if (protocol != USB_AUDIO_CLASS_2)
-                       printf("      Warning: CLOCK_MULTIPLIER descriptors are 
illegal for UAC1\n");
-
-               if (buf[0] < 7)
-                       printf("      Warning: Descriptor too short\n");
-
-               printf("        bClockID            %5u\n"
-                      "        bCSourceID          %5u\n",
-                      buf[3], buf[4]);
-
-               printf("        bmControls           0x%02x\n", buf[5]);
-               dump_audio_bmcontrols("          ", buf[5], 
uac2_clock_multiplier_bmcontrols, protocol);
-
-               term = get_dev_string(dev, buf[6]);
-               printf("        iClockMultiplier    %5u %s\n", buf[6], term);
-               dump_junk(buf, "        ", 7);
+               dump_audio_subtype(dev, "CLOCK_MULTIPLIER", 
desc_audio_ac_clock_multiplier, buf, protocol, 4);
                break;
 
        case UAC_INTERFACE_SUBTYPE_SAMPLE_RATE_CONVERTER:
-               printf("(SAMPLE_RATE_CONVERTER_UNIT)\n");
-               if (protocol != USB_AUDIO_CLASS_2)
-                       printf("      Warning: SAMPLE_RATE_CONVERTER_UNIT 
descriptors are illegal for UAC1\n");
-
-               if (buf[0] < 8)
-                       printf("      Warning: Descriptor too short\n");
-
-               term = get_dev_string(dev, buf[7]);
-               printf("        bUnitID             %5u\n"
-                      "        bSourceID           %5u\n"
-                      "        bCSourceInID        %5u\n"
-                      "        bCSourceOutID       %5u\n"
-                      "        iSRC                %5u %s\n",
-                      buf[3], buf[4], buf[5], buf[6], buf[7], term);
-               dump_junk(buf, "        ", 8);
+               dump_audio_subtype(dev, "SAMPLING_RATE_CONVERTER", 
desc_audio_ac_clock_multiplier, buf, protocol, 4);
                break;
 
        case UAC_INTERFACE_SUBTYPE_EFFECT_UNIT:
-               printf("(EFFECT_UNIT)\n");
-
-               if (buf[0] < 16)
-                       printf("      Warning: Descriptor too short\n");
-               k = (buf[0] - 16) / 4;
-               term = get_dev_string(dev, buf[15+k*4]);
-               printf("        bUnitID             %5u\n"
-                      "        wEffectType         %5u\n"
-                      "        bSourceID           %5u\n",
-                      buf[3], buf[4] | (buf[5] << 8), buf[6]);
-               for (i = 0; i < k; i++) {
-                       chcfg = buf[7+(4*i)] |
-                               buf[8+(4*i)] << 8 |
-                               buf[9+(4*i)] << 16 |
-                               buf[10+(4*i)] << 24;
-                       printf("        bmaControls(%2u)      0x%08x\n", i, 
chcfg);
-                       /* TODO: parse effect-specific controls */
-               }
-               printf("        iEffect             %5u %s\n", buf[15+(k*4)], 
term);
-               dump_junk(buf, "        ", 16+(k*4));
+               dump_audio_subtype(dev, "EFFECT_UNIT", 
desc_audio_ac_effect_unit, buf, protocol, 4);
                break;
 
        default:
@@ -1622,16 +1063,8 @@ static void 
dump_audiocontrol_interface(libusb_device_handle *dev, const unsigne
                dump_bytes(buf+3, buf[0]-3);
                break;
        }
-
-       free(chnames);
-       free(term);
 }
 
-static const struct bmcontrol uac2_as_interface_bmcontrols[] = {
-       { "Active Alternate Setting",   0 },
-       { "Valid Alternate Setting",    1 },
-       { NULL }
-};
 
 static void dump_audiostreaming_interface(libusb_device_handle *dev, const 
unsigned char *buf, int protocol)
 {
@@ -1657,54 +1090,7 @@ static void 
dump_audiostreaming_interface(libusb_device_handle *dev, const unsig
               buf[0], buf[1], buf[2]);
        switch (buf[2]) {
        case 0x01: /* AS_GENERAL */
-               printf("(AS_GENERAL)\n");
-
-               switch (protocol) {
-               case USB_AUDIO_CLASS_1:
-                       if (buf[0] < 7)
-                               printf("      Warning: Descriptor too short\n");
-                       fmttag = buf[5] | (buf[6] << 8);
-                       if (fmttag <= 5)
-                               fmtptr = fmtItag[fmttag];
-                       else if (fmttag >= 0x1000 && fmttag <= 0x1002)
-                               fmtptr = fmtIItag[fmttag & 0xfff];
-                       else if (fmttag >= 0x2000 && fmttag <= 0x2006)
-                               fmtptr = fmtIIItag[fmttag & 0xfff];
-                       printf("        bTerminalLink       %5u\n"
-                              "        bDelay              %5u frames\n"
-                              "        wFormatTag          %5u %s\n",
-                              buf[3], buf[4], fmttag, fmtptr);
-                       dump_junk(buf, "        ", 7);
-                       break;
-               case USB_AUDIO_CLASS_2:
-                       if (buf[0] < 16)
-                               printf("      Warning: Descriptor too short\n");
-                       printf("        bTerminalLink       %5u\n"
-                              "        bmControls           0x%02x\n",
-                              buf[3], buf[4]);
-                       dump_audio_bmcontrols("          ", buf[4], 
uac2_as_interface_bmcontrols, protocol);
-
-                       printf("        bFormatType         %5u\n", buf[5]);
-                       fmttag = buf[6] | (buf[7] << 8) | (buf[8] << 16) | 
(buf[9] << 24);
-                       printf("        bmFormats         0x%08x\n", fmttag);
-                       for (i=0; i<5; i++)
-                               if ((fmttag >> i) & 1)
-                                       printf("          %s\n", fmtItag[i+1]);
-
-                       j = buf[11] | (buf[12] << 8) | (buf[13] << 16) | 
(buf[14] << 24);
-                       printf("        bNrChannels         %5u\n"
-                              "        bmChannelConfig   0x%08x\n",
-                              buf[10], j);
-                       for (i = 0; i < 26; i++)
-                               if ((j >> i) & 1)
-                                       printf("          %s\n", 
chconfig_uac2[i]);
-
-                       name = get_dev_string(dev, buf[15]);
-                       printf("        iChannelNames       %5u %s\n", buf[15], 
name);
-                       dump_junk(buf, "        ", 16);
-                       break;
-               } /* switch (protocol) */
-
+               dump_audio_subtype(dev, "AS_GENERAL", desc_audio_as_interface, 
buf, protocol, 4);
                break;
 
        case 0x02: /* FORMAT_TYPE */
@@ -1963,62 +1349,21 @@ static void 
dump_audiostreaming_interface(libusb_device_handle *dev, const unsig
        free(name);
 }
 
-static const struct bmcontrol uac2_audio_endpoint_bmcontrols[] = {
-       { "Pitch",              0 },
-       { "Data Overrun",       1 },
-       { "Data Underrun",      2 },
-       { NULL }
-};
-
-static void dump_audiostreaming_endpoint(const unsigned char *buf, int 
protocol)
+static void dump_audiostreaming_endpoint(libusb_device_handle *dev, const 
unsigned char *buf, int protocol)
 {
-       static const char * const lockdelunits[] = { "Undefined", 
"Milliseconds", "Decoded PCM samples", "Reserved" };
-       unsigned int lckdelidx;
+       static const char * const subtype[] = { "invalid", "EP_GENERAL" };
 
        if (buf[1] != USB_DT_CS_ENDPOINT)
                printf("      Warning: Invalid descriptor\n");
-       else if (buf[0] < ((protocol == USB_AUDIO_CLASS_1) ? 7 : 8))
-               printf("      Warning: Descriptor too short\n");
-       printf("        AudioControl Endpoint Descriptor:\n"
+
+       printf("        AudioStreaming Endpoint Descriptor:\n"
               "          bLength             %5u\n"
               "          bDescriptorType     %5u\n"
-              "          bDescriptorSubtype  %5u (%s)\n"
-              "          bmAttributes         0x%02x\n",
-              buf[0], buf[1], buf[2], buf[2] == 1 ? "EP_GENERAL" : "invalid", 
buf[3]);
-
-       switch (protocol) {
-       case USB_AUDIO_CLASS_1:
-               if (buf[3] & 1)
-                       printf("            Sampling Frequency\n");
-               if (buf[3] & 2)
-                       printf("            Pitch\n");
-               if (buf[3] & 128)
-                       printf("            MaxPacketsOnly\n");
-               lckdelidx = buf[4];
-               if (lckdelidx > 3)
-                       lckdelidx = 3;
-               printf("          bLockDelayUnits     %5u %s\n"
-                      "          wLockDelay          %5u %s\n",
-                      buf[4], lockdelunits[lckdelidx], buf[5] | (buf[6] << 8), 
lockdelunits[lckdelidx]);
-               dump_junk(buf, "        ", 7);
-               break;
+              "          bDescriptorSubtype  %5u ",
+              buf[0], buf[1], buf[2]);
 
-       case USB_AUDIO_CLASS_2:
-               if (buf[3] & 128)
-                       printf("            MaxPacketsOnly\n");
-
-               printf("          bmControls           0x%02x\n", buf[4]);
-               dump_audio_bmcontrols("          ", buf[4], 
uac2_audio_endpoint_bmcontrols, protocol);
-
-               lckdelidx = buf[5];
-               if (lckdelidx > 3)
-                       lckdelidx = 3;
-               printf("          bLockDelayUnits     %5u %s\n"
-                      "          wLockDelay          %5u\n",
-                      buf[5], lockdelunits[lckdelidx], buf[6] | (buf[7] << 8));
-               dump_junk(buf, "        ", 8);
-               break;
-       } /* switch protocol */
+       dump_audio_subtype(dev, subtype[buf[2] == 1],
+                       desc_audio_as_isochronous_audio_data_endpoint, buf, 
protocol, 5);
 }
 
 static void dump_midistreaming_interface(libusb_device_handle *dev, const 
unsigned char *buf)
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to