This gives us more consistency in handling of incorrect descriptor
buffer lengths, and improves whitespace/alignment consistency.
---
Makefile.am | 2 +
lsusb.c | 779 +++++-------------------------------------------------------
2 files changed, 63 insertions(+), 718 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 c35d92e..ac6e061 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);
+ static const char * const strings[] = { "UAC1", "UAC2" };
+ unsigned int idx = 0;
- break;
-
- 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 {
@@ -1074,21 +984,9 @@ static enum uac_interface_subtype
get_uac_interface_subtype(unsigned char c, int
return c;
}
-
-
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");
@@ -1103,515 +1001,56 @@ static void
dump_audiocontrol_interface(libusb_device_handle *dev, const unsigne
subtype = get_uac_interface_subtype(buf[2], protocol);
switch (subtype) {
- case 0x01: /* 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;
- }
+ case UAC_INTERFACE_SUBTYPE_HEADER:
+ dump_audio_subtype(dev, "HEADER", desc_audio_ac_header, buf,
protocol, 4);
break;
- case 0x02: /* 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) */
-
+ case UAC_INTERFACE_SUBTYPE_INPUT_TERMINAL:
+ dump_audio_subtype(dev, "INPUT_TERMINAL",
desc_audio_ac_input_terminal, buf, protocol, 4);
break;
- case 0x03: /* 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) */
-
+ case UAC_INTERFACE_SUBTYPE_OUTPUT_TERMINAL:
+ dump_audio_subtype(dev, "OUTPUT_TERMINAL",
desc_audio_ac_output_terminal, buf, protocol, 4);
break;
- case 0x04: /* 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) */
+ case UAC_INTERFACE_SUBTYPE_MIXER_UNIT:
+ dump_audio_subtype(dev, "MIXER_UNIT", desc_audio_ac_mixer_unit,
buf, protocol, 4);
break;
- case 0x05: /* 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) */
-
+ case UAC_INTERFACE_SUBTYPE_SELECTOR_UNIT:
+ dump_audio_subtype(dev, "SELECTOR_UNIT",
desc_audio_ac_selector_unit, buf, protocol, 4);
break;
- case 0x06: /* 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) */
-
+ case UAC_INTERFACE_SUBTYPE_FEATURE_UNIT:
+ dump_audio_subtype(dev, "FEATURE_UNIT",
desc_audio_ac_feature_unit, buf, protocol, 4);
break;
- case 0x07: /* 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) */
-
+ case UAC_INTERFACE_SUBTYPE_PROCESSING_UNIT:
+ dump_audio_subtype(dev, "PROCESSING_UNIT",
desc_audio_ac_processing_unit, buf, protocol, 4);
break;
- case 0x08: /* 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) */
-
+ case UAC_INTERFACE_SUBTYPE_EXTENSION_UNIT:
+ dump_audio_subtype(dev, "EXTENSION_UNIT",
desc_audio_ac_extension_unit, buf, protocol, 4);
break;
- case 0x0a: /* 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);
+ case UAC_INTERFACE_SUBTYPE_CLOCK_SOURCE:
+ dump_audio_subtype(dev, "CLOCK_SOURCE",
desc_audio_ac_clock_source, buf, protocol, 4);
break;
- case 0x0b: /* 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]);
+ case UAC_INTERFACE_SUBTYPE_CLOCK_SELECTOR:
+ dump_audio_subtype(dev, "CLOCK_SELECTOR",
desc_audio_ac_clock_selector, buf, protocol, 4);
break;
- case 0x0c: /* 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);
+ case UAC_INTERFACE_SUBTYPE_CLOCK_MULTIPLIER:
+ dump_audio_subtype(dev, "CLOCK_MULTIPLIER",
desc_audio_ac_clock_multiplier, buf, protocol, 4);
break;
- case 0x0d: /* SAMPLE_RATE_CONVERTER_UNIT */
- 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);
+ case UAC_INTERFACE_SUBTYPE_SAMPLE_RATE_CONVERTER:
+ dump_audio_subtype(dev, "SAMPLING_RATE_CONVERTER",
desc_audio_ac_clock_multiplier, buf, protocol, 4);
break;
- case 0xf0: /* EFFECT_UNIT - the real value is 0x07, see above for the
reason for remapping */
- 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));
+ case UAC_INTERFACE_SUBTYPE_EFFECT_UNIT:
+ dump_audio_subtype(dev, "EFFECT_UNIT",
desc_audio_ac_effect_unit, buf, protocol, 4);
break;
default:
@@ -1620,16 +1059,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)
{
@@ -1655,54 +1086,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 */
@@ -1961,62 +1345,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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html