This gives us more consistency in handling of incorrect descriptor buffer lengths, and improves whitespace/alignment consistency. Signed-off-by: Michael Drake <michael.drake@xxxxxxxxxxxxxxx> --- 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html