summaryrefslogtreecommitdiff
path: root/src/class/audio
diff options
context:
space:
mode:
authorHiFiPHile <[email protected]>2026-08-27 03:10:37 +0200
committerHiFiPHile <[email protected]>2026-08-27 10:34:33 +0200
commit6019e538125e9863a4fa4bcf0b026d3e639a1a4d (patch)
tree97f68c9da21ed50ee57626ccfa6f3109363e2a74 /src/class/audio
parent0782fb796d7981c36a3d2a11485596f288dd6bd5 (diff)
audio: harden streaming descriptor parsing
Validate descriptor lengths before typed access, keep supported alternate settings when neighboring formats are unsupported, and reject MIDI 1.0 and 2.0 streaming interfaces from the Audio host parser. Extend parser coverage for malformed and mixed descriptor layouts. Signed-off-by: HiFiPHile <[email protected]>
Diffstat (limited to 'src/class/audio')
-rw-r--r--src/class/audio/audio_host.c295
1 files changed, 152 insertions, 143 deletions
diff --git a/src/class/audio/audio_host.c b/src/class/audio/audio_host.c
index 82d725329..ad2fd677f 100644
--- a/src/class/audio/audio_host.c
+++ b/src/class/audio/audio_host.c
@@ -874,8 +874,6 @@ bool audioh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uin
// Enumeration
//--------------------------------------------------------------------+
- #define AUDIOH_MAX_AC_ENTITIES TUH_AUDIO_STREAM_DIRECTION_COUNT
-
typedef struct {
uint8_t id;
uint8_t source_id;
@@ -896,13 +894,9 @@ typedef struct {
} audioh_clock_info_t;
typedef struct {
- audioh_terminal_info_t terminal[AUDIOH_MAX_AC_ENTITIES];
- audioh_fu_info_t feature_unit[AUDIOH_MAX_AC_ENTITIES];
- audioh_clock_info_t clock[AUDIOH_MAX_AC_ENTITIES];
- uint8_t terminal_count;
- uint8_t feature_unit_count;
- uint8_t clock_count;
-} audioh_ac_map_t;
+ const uint8_t *desc_start;
+ const uint8_t *desc_end;
+} audioh_ac_desc_range_t;
#if CFG_TUH_AUDIO_PROTOCOLS & TUH_AUDIO_PROTOCOL_UAC2
static uint8_t audioh_uac2_control_access(uint32_t controls, uint8_t position) {
@@ -923,156 +917,173 @@ static bool audioh_as_rate_fits(const audioh_interface_t *p_audio, const tuh_aud
(stream->dir != TUSB_DIR_OUT || (packet_bytes <= epbuf_size && packet_bytes <= CFG_TUH_AUDIO_STREAM_BUFSIZE));
}
-static void audioh_ac_terminal_add(audioh_ac_map_t *map, uint8_t id, uint8_t source_id, uint8_t clock_id,
- tusb_dir_t stream_dir) {
- if (map->terminal_count < TU_ARRAY_SIZE(map->terminal)) {
- map->terminal[map->terminal_count++] =
- (audioh_terminal_info_t){.id = id, .source_id = source_id, .clock_id = clock_id, .stream_dir = stream_dir};
- }
-}
-
-static void audioh_ac_feature_unit_add(audioh_ac_map_t *map, uint8_t id, uint8_t source_id, uint8_t mute_access,
- uint8_t volume_access) {
- if ((mute_access != AUDIOH_CTRL_NONE || volume_access != AUDIOH_CTRL_NONE) &&
- map->feature_unit_count < TU_ARRAY_SIZE(map->feature_unit)) {
- map->feature_unit[map->feature_unit_count++] =
- (audioh_fu_info_t){.id = id, .source_id = source_id, .mute_access = mute_access, .volume_access = volume_access};
- }
-}
-
-static const audioh_terminal_info_t *audioh_ac_terminal_find(const audioh_ac_map_t *map, uint8_t id) {
- for (uint8_t i = 0; i < map->terminal_count; i++) {
- if (map->terminal[i].id == id) {
- return &map->terminal[i];
+static bool audioh_ac_entity_valid(const audioh_interface_t *p_audio, const uint8_t *p_desc) {
+ switch (p_audio->protocol) {
+ #if CFG_TUH_AUDIO_PROTOCOLS & TUH_AUDIO_PROTOCOL_UAC1
+ case AUDIO_INT_PROTOCOL_CODE_V1: {
+ switch (tu_desc_subtype(p_desc)) {
+ case AUDIO10_CS_AC_INTERFACE_INPUT_TERMINAL:
+ return TUH_VALIDATE_BASIC(tu_desc_len(p_desc) >= sizeof(audio10_desc_input_terminal_t));
+ case AUDIO10_CS_AC_INTERFACE_OUTPUT_TERMINAL:
+ return TUH_VALIDATE_BASIC(tu_desc_len(p_desc) >= sizeof(audio10_desc_output_terminal_t));
+ case AUDIO10_CS_AC_INTERFACE_FEATURE_UNIT: {
+ TU_VERIFY(TUH_VALIDATE_BASIC(tu_desc_len(p_desc) >= 7), false);
+ const uint8_t control_size = p_desc[5];
+ return TUH_VALIDATE_BASIC(control_size > 0) &&
+ TUH_VALIDATE_BASIC(control_size <= (uint8_t)(tu_desc_len(p_desc) - 7));
+ }
+ default:
+ return true;
+ }
}
+ #endif
+ #if CFG_TUH_AUDIO_PROTOCOLS & TUH_AUDIO_PROTOCOL_UAC2
+ case AUDIO_INT_PROTOCOL_CODE_V2:
+ switch (tu_desc_subtype(p_desc)) {
+ case AUDIO20_CS_AC_INTERFACE_INPUT_TERMINAL:
+ return TUH_VALIDATE_BASIC(tu_desc_len(p_desc) >= sizeof(audio20_desc_input_terminal_t));
+ case AUDIO20_CS_AC_INTERFACE_OUTPUT_TERMINAL:
+ return TUH_VALIDATE_BASIC(tu_desc_len(p_desc) >= sizeof(audio20_desc_output_terminal_t));
+ case AUDIO20_CS_AC_INTERFACE_FEATURE_UNIT:
+ return TUH_VALIDATE_BASIC(tu_desc_len(p_desc) >= 10);
+ case AUDIO20_CS_AC_INTERFACE_CLOCK_SOURCE:
+ return TUH_VALIDATE_BASIC(tu_desc_len(p_desc) >= sizeof(audio20_desc_clock_source_t));
+ default:
+ return true;
+ }
+ #endif
+ default:
+ return false;
}
- return NULL;
}
+static bool audioh_ac_terminal_find(const audioh_interface_t *p_audio, const audioh_ac_desc_range_t *range, uint8_t id,
+ audioh_terminal_info_t *info) {
+ for (const uint8_t *p_desc = range->desc_start; p_desc < range->desc_end; p_desc = tu_desc_next(p_desc)) {
+ if (tu_desc_type(p_desc) != TUSB_DESC_CS_INTERFACE || tu_desc_len(p_desc) < 4 || p_desc[3] != id) {
+ continue;
+ }
+ switch (p_audio->protocol) {
+ #if CFG_TUH_AUDIO_PROTOCOLS & TUH_AUDIO_PROTOCOL_UAC1
+ case AUDIO_INT_PROTOCOL_CODE_V1:
+ if (tu_desc_subtype(p_desc) == AUDIO10_CS_AC_INTERFACE_INPUT_TERMINAL) {
+ const audio10_desc_input_terminal_t *terminal = (const audio10_desc_input_terminal_t *)p_desc;
+ if (tu_le16toh(terminal->wTerminalType) == AUDIO_TERM_TYPE_USB_STREAMING) {
+ *info = (audioh_terminal_info_t){.id = id, .stream_dir = TUSB_DIR_OUT};
+ return true;
+ }
+ } else if (tu_desc_subtype(p_desc) == AUDIO10_CS_AC_INTERFACE_OUTPUT_TERMINAL) {
+ const audio10_desc_output_terminal_t *terminal = (const audio10_desc_output_terminal_t *)p_desc;
+ if (tu_le16toh(terminal->wTerminalType) == AUDIO_TERM_TYPE_USB_STREAMING) {
+ *info = (audioh_terminal_info_t){.id = id, .source_id = terminal->bSourceID, .stream_dir = TUSB_DIR_IN};
+ return true;
+ }
+ }
+ break;
+ #endif
#if CFG_TUH_AUDIO_PROTOCOLS & TUH_AUDIO_PROTOCOL_UAC2
-static const audioh_clock_info_t *audioh_ac_clock_find(const audioh_ac_map_t *map, uint8_t id) {
- for (uint8_t i = 0; i < map->clock_count; i++) {
- if (map->clock[i].id == id) {
- return &map->clock[i];
+ case AUDIO_INT_PROTOCOL_CODE_V2:
+ if (tu_desc_subtype(p_desc) == AUDIO20_CS_AC_INTERFACE_INPUT_TERMINAL) {
+ const audio20_desc_input_terminal_t *terminal = (const audio20_desc_input_terminal_t *)p_desc;
+ if (tu_le16toh(terminal->wTerminalType) == AUDIO_TERM_TYPE_USB_STREAMING) {
+ *info = (audioh_terminal_info_t){.id = id, .clock_id = terminal->bCSourceID, .stream_dir = TUSB_DIR_OUT};
+ return true;
+ }
+ } else if (tu_desc_subtype(p_desc) == AUDIO20_CS_AC_INTERFACE_OUTPUT_TERMINAL) {
+ const audio20_desc_output_terminal_t *terminal = (const audio20_desc_output_terminal_t *)p_desc;
+ if (tu_le16toh(terminal->wTerminalType) == AUDIO_TERM_TYPE_USB_STREAMING) {
+ *info = (audioh_terminal_info_t){.id = id,
+ .source_id = terminal->bSourceID,
+ .clock_id = terminal->bCSourceID,
+ .stream_dir = TUSB_DIR_IN};
+ return true;
+ }
+ }
+ break;
+ #endif
+ default:
+ return false;
}
}
- return NULL;
+ return false;
}
- #endif
+static bool audioh_ac_feature_unit_parse(const audioh_interface_t *p_audio, const uint8_t *p_desc,
+ audioh_fu_info_t *info) {
+ if (tu_desc_type(p_desc) != TUSB_DESC_CS_INTERFACE) {
+ return false;
+ }
+ switch (p_audio->protocol) {
#if CFG_TUH_AUDIO_PROTOCOLS & TUH_AUDIO_PROTOCOL_UAC1
-static bool audioh_uac1_parse_ac_entity(audioh_ac_map_t *map, const uint8_t *p_desc) {
- switch (tu_desc_subtype(p_desc)) {
- case AUDIO10_CS_AC_INTERFACE_INPUT_TERMINAL: {
- TU_VERIFY(TUH_VALIDATE_BASIC(tu_desc_len(p_desc) >= sizeof(audio10_desc_input_terminal_t)), false);
- const audio10_desc_input_terminal_t *terminal = (const audio10_desc_input_terminal_t *)p_desc;
- if (tu_le16toh(terminal->wTerminalType) == AUDIO_TERM_TYPE_USB_STREAMING) {
- audioh_ac_terminal_add(map, terminal->bTerminalID, 0, 0, TUSB_DIR_OUT);
+ case AUDIO_INT_PROTOCOL_CODE_V1:
+ if (tu_desc_subtype(p_desc) == AUDIO10_CS_AC_INTERFACE_FEATURE_UNIT) {
+ const uint8_t controls = p_desc[6];
+ *info = (audioh_fu_info_t){.id = p_desc[3],
+ .source_id = p_desc[4],
+ .mute_access = (controls & AUDIO10_FU_CONTROL_BM_MUTE) ? AUDIOH_CTRL_READ_WRITE
+ : AUDIOH_CTRL_NONE,
+ .volume_access = (controls & AUDIO10_FU_CONTROL_BM_VOLUME) ? AUDIOH_CTRL_READ_WRITE
+ : AUDIOH_CTRL_NONE};
+ return info->mute_access != AUDIOH_CTRL_NONE || info->volume_access != AUDIOH_CTRL_NONE;
}
break;
- }
- case AUDIO10_CS_AC_INTERFACE_OUTPUT_TERMINAL: {
- TU_VERIFY(TUH_VALIDATE_BASIC(tu_desc_len(p_desc) >= sizeof(audio10_desc_output_terminal_t)), false);
- const audio10_desc_output_terminal_t *terminal = (const audio10_desc_output_terminal_t *)p_desc;
- if (tu_le16toh(terminal->wTerminalType) == AUDIO_TERM_TYPE_USB_STREAMING) {
- audioh_ac_terminal_add(map, terminal->bTerminalID, terminal->bSourceID, 0, TUSB_DIR_IN);
+ #endif
+ #if CFG_TUH_AUDIO_PROTOCOLS & TUH_AUDIO_PROTOCOL_UAC2
+ case AUDIO_INT_PROTOCOL_CODE_V2:
+ if (tu_desc_subtype(p_desc) == AUDIO20_CS_AC_INTERFACE_FEATURE_UNIT) {
+ const uint32_t controls = tu_le32toh(tu_unaligned_read32(&p_desc[5]));
+ *info =
+ (audioh_fu_info_t){.id = p_desc[3],
+ .source_id = p_desc[4],
+ .mute_access = audioh_uac2_control_access(controls, AUDIO20_FEATURE_UNIT_CTRL_MUTE_POS),
+ .volume_access =
+ audioh_uac2_control_access(controls, AUDIO20_FEATURE_UNIT_CTRL_VOLUME_POS)};
+ return info->mute_access != AUDIOH_CTRL_NONE || info->volume_access != AUDIOH_CTRL_NONE;
}
break;
- }
- case AUDIO10_CS_AC_INTERFACE_FEATURE_UNIT: {
- TU_VERIFY(TUH_VALIDATE_BASIC(tu_desc_len(p_desc) >= 7), false);
- const uint8_t control_size = p_desc[5];
- TU_VERIFY(TUH_VALIDATE_BASIC(control_size > 0), false);
- TU_VERIFY(TUH_VALIDATE_BASIC(control_size <= (uint8_t)(tu_desc_len(p_desc) - 7)), false);
- const uint8_t controls = p_desc[6];
- audioh_ac_feature_unit_add(map, p_desc[3], p_desc[4],
- (controls & AUDIO10_FU_CONTROL_BM_MUTE) ? AUDIOH_CTRL_READ_WRITE : AUDIOH_CTRL_NONE,
- (controls & AUDIO10_FU_CONTROL_BM_VOLUME) ? AUDIOH_CTRL_READ_WRITE : AUDIOH_CTRL_NONE);
- break;
- }
+ #endif
default:
break;
}
- return true;
+ return false;
}
- #endif
#if CFG_TUH_AUDIO_PROTOCOLS & TUH_AUDIO_PROTOCOL_UAC2
-static bool audioh_uac2_parse_ac_entity(audioh_ac_map_t *map, const uint8_t *p_desc) {
- switch (tu_desc_subtype(p_desc)) {
- case AUDIO20_CS_AC_INTERFACE_INPUT_TERMINAL: {
- TU_VERIFY(TUH_VALIDATE_BASIC(tu_desc_len(p_desc) >= sizeof(audio20_desc_input_terminal_t)), false);
- const audio20_desc_input_terminal_t *terminal = (const audio20_desc_input_terminal_t *)p_desc;
- if (tu_le16toh(terminal->wTerminalType) == AUDIO_TERM_TYPE_USB_STREAMING) {
- audioh_ac_terminal_add(map, terminal->bTerminalID, 0, terminal->bCSourceID, TUSB_DIR_OUT);
- }
- break;
- }
- case AUDIO20_CS_AC_INTERFACE_OUTPUT_TERMINAL: {
- TU_VERIFY(TUH_VALIDATE_BASIC(tu_desc_len(p_desc) >= sizeof(audio20_desc_output_terminal_t)), false);
- const audio20_desc_output_terminal_t *terminal = (const audio20_desc_output_terminal_t *)p_desc;
- if (tu_le16toh(terminal->wTerminalType) == AUDIO_TERM_TYPE_USB_STREAMING) {
- audioh_ac_terminal_add(map, terminal->bTerminalID, terminal->bSourceID, terminal->bCSourceID, TUSB_DIR_IN);
- }
- break;
- }
- case AUDIO20_CS_AC_INTERFACE_FEATURE_UNIT: {
- TU_VERIFY(TUH_VALIDATE_BASIC(tu_desc_len(p_desc) >= 10), false);
- const uint32_t controls = tu_le32toh(tu_unaligned_read32(&p_desc[5]));
- audioh_ac_feature_unit_add(map, p_desc[3], p_desc[4],
- audioh_uac2_control_access(controls, AUDIO20_FEATURE_UNIT_CTRL_MUTE_POS),
- audioh_uac2_control_access(controls, AUDIO20_FEATURE_UNIT_CTRL_VOLUME_POS));
- break;
- }
- case AUDIO20_CS_AC_INTERFACE_CLOCK_SOURCE: {
- TU_VERIFY(TUH_VALIDATE_BASIC(tu_desc_len(p_desc) >= sizeof(audio20_desc_clock_source_t)), false);
+static bool audioh_ac_clock_find(const audioh_ac_desc_range_t *range, uint8_t id, audioh_clock_info_t *info) {
+ for (const uint8_t *p_desc = range->desc_start; p_desc < range->desc_end; p_desc = tu_desc_next(p_desc)) {
+ if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE &&
+ tu_desc_subtype(p_desc) == AUDIO20_CS_AC_INTERFACE_CLOCK_SOURCE && p_desc[3] == id) {
const audio20_desc_clock_source_t *clock = (const audio20_desc_clock_source_t *)p_desc;
- if (map->clock_count < TU_ARRAY_SIZE(map->clock)) {
- map->clock[map->clock_count++] =
- (audioh_clock_info_t){.id = clock->bClockID,
- .frequency_access =
- audioh_uac2_control_access(clock->bmControls, AUDIO20_CLOCK_SOURCE_CTRL_CLK_FRQ_POS)};
- }
- break;
+ *info =
+ (audioh_clock_info_t){.id = id,
+ .frequency_access =
+ audioh_uac2_control_access(clock->bmControls, AUDIO20_CLOCK_SOURCE_CTRL_CLK_FRQ_POS)};
+ return true;
}
- default:
- break;
}
- return true;
+ return false;
}
#endif
-static bool audioh_parse_ac_entity(audioh_interface_t *p_audio, audioh_ac_map_t *map, const uint8_t *p_desc) {
- switch (p_audio->protocol) {
- #if CFG_TUH_AUDIO_PROTOCOLS & TUH_AUDIO_PROTOCOL_UAC1
- case AUDIO_INT_PROTOCOL_CODE_V1:
- return audioh_uac1_parse_ac_entity(map, p_desc);
- #endif
- #if CFG_TUH_AUDIO_PROTOCOLS & TUH_AUDIO_PROTOCOL_UAC2
- case AUDIO_INT_PROTOCOL_CODE_V2:
- return audioh_uac2_parse_ac_entity(map, p_desc);
- #endif
- default:
- return false;
- }
-}
-
-static void audioh_link_feature_units(audioh_interface_t *p_audio, const audioh_ac_map_t *map) {
+static void audioh_link_feature_units(audioh_interface_t *p_audio, const audioh_ac_desc_range_t *range) {
for (uint8_t direction = TUSB_DIR_OUT; direction <= TUSB_DIR_IN; direction++) {
tuh_audio_stream_t *stream = audioh_get_stream(p_audio, (tusb_dir_t)direction);
if (stream == NULL || stream->as_count == 0) {
continue;
}
- const audioh_terminal_info_t *terminal = audioh_ac_terminal_find(map, stream->as[0].terminal_id);
- if (terminal == NULL || terminal->stream_dir != direction) {
+ audioh_terminal_info_t terminal;
+ if (!audioh_ac_terminal_find(p_audio, range, stream->as[0].terminal_id, &terminal) ||
+ terminal.stream_dir != direction) {
continue;
}
- for (uint8_t i = 0; i < map->feature_unit_count; i++) {
- const audioh_fu_info_t *fu = &map->feature_unit[i];
- const bool linked =
- (direction == TUSB_DIR_OUT) ? (fu->source_id == terminal->id) : (fu->id == terminal->source_id);
+ for (const uint8_t *p_desc = range->desc_start; p_desc < range->desc_end; p_desc = tu_desc_next(p_desc)) {
+ audioh_fu_info_t fu;
+ if (!audioh_ac_feature_unit_parse(p_audio, p_desc, &fu)) {
+ continue;
+ }
+ const bool linked = (direction == TUSB_DIR_OUT) ? (fu.source_id == terminal.id) : (fu.id == terminal.source_id);
if (linked) {
- audioh_stream_set_feature_unit(stream, fu->id, fu->mute_access, fu->volume_access);
+ audioh_stream_set_feature_unit(stream, fu.id, fu.mute_access, fu.volume_access);
break;
}
}
@@ -1170,17 +1181,17 @@ static bool audioh_parse_as_interface(audioh_interface_t *p_audio, const uint8_t
}
#if CFG_TUH_AUDIO_PROTOCOLS & TUH_AUDIO_PROTOCOL_UAC2
-static int8_t audioh_uac2_rate_source_get(audioh_interface_t *p_audio, const audioh_ac_map_t *map,
+static int8_t audioh_uac2_rate_source_get(audioh_interface_t *p_audio, const audioh_ac_desc_range_t *range,
const audioh_terminal_info_t *terminal) {
if (terminal->clock_id == 0) {
return -1;
}
- const audioh_clock_info_t *clock = audioh_ac_clock_find(map, terminal->clock_id);
- if (clock == NULL || clock->frequency_access == AUDIOH_CTRL_NONE) {
+ audioh_clock_info_t clock;
+ if (!audioh_ac_clock_find(range, terminal->clock_id, &clock) || clock.frequency_access == AUDIOH_CTRL_NONE) {
return -1;
}
for (uint8_t i = 0; i < p_audio->rate_source_count; i++) {
- if (p_audio->rate_source[i].control_id == clock->id) {
+ if (p_audio->rate_source[i].control_id == clock.id) {
return (int8_t)i;
}
}
@@ -1189,7 +1200,7 @@ static int8_t audioh_uac2_rate_source_get(audioh_interface_t *p_audio, const aud
}
const uint8_t idx = p_audio->rate_source_count++;
p_audio->rate_source[idx] =
- (audioh_rate_source_t){.control_id = clock->id, .frequency_access = clock->frequency_access};
+ (audioh_rate_source_t){.control_id = clock.id, .frequency_access = clock.frequency_access};
return (int8_t)idx;
}
#endif
@@ -1217,12 +1228,9 @@ static bool audioh_uac1_rates_store(const audioh_interface_t *p_audio, const tuh
// Parse one Audio Streaming interface alternate setting and register its
// supported configurations into the matching stream. Returns the descriptor
// pointer of the next interface.
-static const uint8_t *audioh_parse_as(audioh_interface_t *p_audio, const audioh_ac_map_t *ac_map,
+static const uint8_t *audioh_parse_as(audioh_interface_t *p_audio, const audioh_ac_desc_range_t *ac_desc,
const tusb_desc_interface_t *desc_itf, const uint8_t *p_desc,
const uint8_t *desc_end) {
- #if !(CFG_TUH_AUDIO_PROTOCOLS & TUH_AUDIO_PROTOCOL_UAC2)
- (void)ac_map;
- #endif
TU_VERIFY(audioh_desc_valid(p_desc, desc_end, sizeof(tusb_desc_interface_t)), NULL);
const uint8_t itf_num = desc_itf->bInterfaceNumber;
@@ -1392,8 +1400,9 @@ static const uint8_t *audioh_parse_as(audioh_interface_t *p_audio, const audioh_
const audioh_ep_info_t *ep = &ep_info;
tuh_audio_stream_t *stream = audioh_get_stream(p_audio, tu_edpt_dir(ep->ep_addr));
TU_ASSERT(stream != NULL, p_desc);
- const audioh_terminal_info_t *terminal = audioh_ac_terminal_find(ac_map, class_info.terminal_id);
- if (terminal == NULL || terminal->stream_dir != stream->dir) {
+ audioh_terminal_info_t terminal;
+ if (!audioh_ac_terminal_find(p_audio, ac_desc, class_info.terminal_id, &terminal) ||
+ terminal.stream_dir != stream->dir) {
TU_LOG_DRV(" AUDIO AS itf %u alt %u: terminal %u does not match endpoint direction\r\n", itf_num, alt,
class_info.terminal_id);
return p_desc;
@@ -1439,7 +1448,7 @@ static const uint8_t *audioh_parse_as(audioh_interface_t *p_audio, const audioh_
#endif
#if CFG_TUH_AUDIO_PROTOCOLS & TUH_AUDIO_PROTOCOL_UAC2
case AUDIO_INT_PROTOCOL_CODE_V2: {
- const int8_t rate_source_idx = audioh_uac2_rate_source_get(p_audio, ac_map, terminal);
+ const int8_t rate_source_idx = audioh_uac2_rate_source_get(p_audio, ac_desc, &terminal);
if (rate_source_idx < 0) {
TU_LOG_DRV(" AUDIO AS itf %u alt %u: direct Clock Source not found\r\n", itf_num, alt);
return p_desc;
@@ -1514,9 +1523,8 @@ uint16_t audioh_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_interface
TU_LOG_DRV("AUDIO opening AC Interface %u (addr = %u)\r\n", desc_itf->bInterfaceNumber, dev_addr);
- audioh_ac_map_t ac_map = {0};
-
- p_desc = tu_desc_next(p_desc);
+ p_desc = tu_desc_next(p_desc);
+ audioh_ac_desc_range_t ac_desc = {.desc_start = p_desc};
while (p_desc < desc_end) {
if (!audioh_desc_valid(p_desc, desc_end, 2)) {
goto open_failed;
@@ -1529,12 +1537,13 @@ uint16_t audioh_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_interface
if (!audioh_desc_valid(p_desc, desc_end, 3)) {
goto open_failed;
}
- if (!audioh_parse_ac_entity(p_audio, &ac_map, p_desc)) {
+ if (!audioh_ac_entity_valid(p_audio, p_desc)) {
goto open_failed;
}
}
p_desc = tu_desc_next(p_desc);
}
+ ac_desc.desc_end = p_desc;
// Parse the contiguous Audio Streaming interfaces of this audio function.
while (p_desc < desc_end) {
@@ -1558,13 +1567,13 @@ uint16_t audioh_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_interface
TU_LOG_DRV(" Found AS Interface %u (alt = %u)\r\n", desc_interface->bInterfaceNumber,
desc_interface->bAlternateSetting);
- p_desc = audioh_parse_as(p_audio, &ac_map, desc_interface, p_desc, desc_end);
+ p_desc = audioh_parse_as(p_audio, &ac_desc, desc_interface, p_desc, desc_end);
if (p_desc == NULL) {
goto open_failed;
}
}
- audioh_link_feature_units(p_audio, &ac_map);
+ audioh_link_feature_units(p_audio, &ac_desc);
// UAC2 configurations receive their rates asynchronously during mount.
// Release the tentative instance when no supported AS alternate was found.