summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorHiFiPhile <[email protected]>2025-10-02 23:59:24 +0200
committerHiFiPhile <[email protected]>2025-10-02 23:59:24 +0200
commitd322207441d55f636be911899f1c7928ba6b00b7 (patch)
tree9fd1c782c50e400813f73a432bd129816c6083f0 /examples
parent4ae26db4a9fb462cf871cdf585ba761f23cab6b4 (diff)
Add UAC1 support to uac2_headset example
Signed-off-by: HiFiPhile <[email protected]>
Diffstat (limited to 'examples')
-rw-r--r--examples/device/uac2_headset/src/main.c277
-rw-r--r--examples/device/uac2_headset/src/tusb_config.h42
-rw-r--r--examples/device/uac2_headset/src/usb_descriptors.c79
-rw-r--r--examples/device/uac2_headset/src/usb_descriptors.h107
4 files changed, 445 insertions, 60 deletions
diff --git a/examples/device/uac2_headset/src/main.c b/examples/device/uac2_headset/src/main.c
index 31b2f3ee3..f6d3c041d 100644
--- a/examples/device/uac2_headset/src/main.c
+++ b/examples/device/uac2_headset/src/main.c
@@ -141,8 +141,185 @@ void tud_resume_cb(void) {
blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED;
}
+//--------------------------------------------------------------------+
+// Audio Callback Functions
+//--------------------------------------------------------------------+
+
+//--------------------------------------------------------------------+
+// UAC1 Helper Functions
+//--------------------------------------------------------------------+
+
+static bool audio10_set_req_ep(tusb_control_request_t const *p_request, uint8_t *pBuff) {
+ uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue);
+
+ switch (ctrlSel) {
+ case AUDIO10_EP_CTRL_SAMPLING_FREQ:
+ if (p_request->bRequest == AUDIO10_CS_REQ_SET_CUR) {
+ // Request uses 3 bytes
+ TU_VERIFY(p_request->wLength == 3);
+
+ current_sample_rate = tu_unaligned_read32(pBuff) & 0x00FFFFFF;
+
+ TU_LOG2("EP set current freq: %" PRIu32 "\r\n", current_sample_rate);
+
+ return true;
+ }
+ break;
+
+ // Unknown/Unsupported control
+ default:
+ TU_BREAKPOINT();
+ return false;
+ }
+
+ return false;
+}
+
+static bool audio10_get_req_ep(uint8_t rhport, tusb_control_request_t const *p_request) {
+ uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue);
+
+ switch (ctrlSel) {
+ case AUDIO10_EP_CTRL_SAMPLING_FREQ:
+ if (p_request->bRequest == AUDIO10_CS_REQ_GET_CUR) {
+ TU_LOG2("EP get current freq\r\n");
+
+ uint8_t freq[3];
+ freq[0] = (uint8_t) (current_sample_rate & 0xFF);
+ freq[1] = (uint8_t) ((current_sample_rate >> 8) & 0xFF);
+ freq[2] = (uint8_t) ((current_sample_rate >> 16) & 0xFF);
+ return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, freq, sizeof(freq));
+ }
+ break;
+
+ // Unknown/Unsupported control
+ default:
+ TU_BREAKPOINT();
+ return false;
+ }
+
+ return false;
+}
+
+static bool audio10_set_req_entity(tusb_control_request_t const *p_request, uint8_t *pBuff) {
+ uint8_t channelNum = TU_U16_LOW(p_request->wValue);
+ uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue);
+ uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
+
+ // If request is for our speaker feature unit
+ if (entityID == UAC1_ENTITY_SPK_FEATURE_UNIT) {
+ switch (ctrlSel) {
+ case AUDIO10_FU_CTRL_MUTE:
+ switch (p_request->bRequest) {
+ case AUDIO10_CS_REQ_SET_CUR:
+ // Only 1st form is supported
+ TU_VERIFY(p_request->wLength == 1);
+
+ mute[channelNum] = pBuff[0];
+
+ TU_LOG2(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum);
+ return true;
+
+ default:
+ return false; // not supported
+ }
+
+ case AUDIO10_FU_CTRL_VOLUME:
+ switch (p_request->bRequest) {
+ case AUDIO10_CS_REQ_SET_CUR:
+ // Only 1st form is supported
+ TU_VERIFY(p_request->wLength == 2);
+
+ volume[channelNum] = (int16_t)tu_unaligned_read16(pBuff) / 256;
+
+ TU_LOG2(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum);
+ return true;
+
+ default:
+ return false; // not supported
+ }
+
+ // Unknown/Unsupported control
+ default:
+ TU_BREAKPOINT();
+ return false;
+ }
+ }
+
+ return false;
+}
+
+static bool audio10_get_req_entity(uint8_t rhport, tusb_control_request_t const *p_request) {
+ uint8_t channelNum = TU_U16_LOW(p_request->wValue);
+ uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue);
+ uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
+
+ // If request is for our speaker feature unit
+ if (entityID == UAC1_ENTITY_SPK_FEATURE_UNIT) {
+ switch (ctrlSel) {
+ case AUDIO10_FU_CTRL_MUTE:
+ // Audio control mute cur parameter block consists of only one byte - we thus can send it right away
+ // There does not exist a range parameter block for mute
+ TU_LOG2(" Get Mute of channel: %u\r\n", channelNum);
+ return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &mute[channelNum], 1);
+
+ case AUDIO10_FU_CTRL_VOLUME:
+ switch (p_request->bRequest) {
+ case AUDIO10_CS_REQ_GET_CUR:
+ TU_LOG2(" Get Volume of channel: %u\r\n", channelNum);
+ {
+ int16_t vol = (int16_t) volume[channelNum];
+ vol = vol * 256; // convert to 1/256 dB units
+ return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &vol, sizeof(vol));
+ }
+
+ case AUDIO10_CS_REQ_GET_MIN:
+ TU_LOG2(" Get Volume min of channel: %u\r\n", channelNum);
+ {
+ int16_t min = -90; // -90 dB
+ min = min * 256; // convert to 1/256 dB units
+ return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &min, sizeof(min));
+ }
+
+ case AUDIO10_CS_REQ_GET_MAX:
+ TU_LOG2(" Get Volume max of channel: %u\r\n", channelNum);
+ {
+ int16_t max = 30; // +30 dB
+ max = max * 256; // convert to 1/256 dB units
+ return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &max, sizeof(max));
+ }
+
+ case AUDIO10_CS_REQ_GET_RES:
+ TU_LOG2(" Get Volume res of channel: %u\r\n", channelNum);
+ {
+ int16_t res = 1; // 1 dB
+ res = res * 256; // convert to 1/256 dB units
+ return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &res, sizeof(res));
+ }
+ // Unknown/Unsupported control
+ default:
+ TU_BREAKPOINT();
+ return false;
+ }
+ break;
+
+ // Unknown/Unsupported control
+ default:
+ TU_BREAKPOINT();
+ return false;
+ }
+ }
+
+ return false;
+}
+
+//--------------------------------------------------------------------+
+// UAC2 Helper Functions
+//--------------------------------------------------------------------+
+
+#if TUD_OPT_HIGH_SPEED
+
// Helper for clock get requests
-static bool tud_audio20_clock_get_request(uint8_t rhport, audio20_control_request_t const *request) {
+static bool audio20_clock_get_request(uint8_t rhport, audio20_control_request_t const *request) {
TU_ASSERT(request->bEntityID == UAC2_ENTITY_CLOCK);
if (request->bControlSelector == AUDIO20_CS_CTRL_SAM_FREQ) {
@@ -177,7 +354,7 @@ static bool tud_audio20_clock_get_request(uint8_t rhport, audio20_control_reques
}
// Helper for clock set requests
-static bool tud_audio20_clock_set_request(uint8_t rhport, audio20_control_request_t const *request, uint8_t const *buf) {
+static bool audio20_clock_set_request(uint8_t rhport, audio20_control_request_t const *request, uint8_t const *buf) {
(void) rhport;
TU_ASSERT(request->bEntityID == UAC2_ENTITY_CLOCK);
@@ -199,7 +376,7 @@ static bool tud_audio20_clock_set_request(uint8_t rhport, audio20_control_reques
}
// Helper for feature unit get requests
-static bool tud_audio20_feature_unit_get_request(uint8_t rhport, audio20_control_request_t const *request) {
+static bool audio20_feature_unit_get_request(uint8_t rhport, audio20_control_request_t const *request) {
TU_ASSERT(request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT);
if (request->bControlSelector == AUDIO20_FU_CTRL_MUTE && request->bRequest == AUDIO20_CS_REQ_CUR) {
@@ -227,7 +404,7 @@ static bool tud_audio20_feature_unit_get_request(uint8_t rhport, audio20_control
}
// Helper for feature unit set requests
-static bool tud_audio20_feature_unit_set_request(uint8_t rhport, audio20_control_request_t const *request, uint8_t const *buf) {
+static bool audio20_feature_unit_set_request(uint8_t rhport, audio20_control_request_t const *request, uint8_t const *buf) {
(void) rhport;
TU_ASSERT(request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT);
@@ -256,25 +433,72 @@ static bool tud_audio20_feature_unit_set_request(uint8_t rhport, audio20_control
}
}
-//--------------------------------------------------------------------+
-// Application Callback API Implementations
-//--------------------------------------------------------------------+
+static bool audio20_get_req_entity(uint8_t rhport, tusb_control_request_t const *p_request) {
+ audio20_control_request_t const *request = (audio20_control_request_t const *) p_request;
+
+ if (request->bEntityID == UAC2_ENTITY_CLOCK)
+ return audio20_clock_get_request(rhport, request);
+ if (request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT)
+ return audio20_feature_unit_get_request(rhport, request);
+ else {
+ TU_LOG1("Get request not handled, entity = %d, selector = %d, request = %d\r\n",
+ request->bEntityID, request->bControlSelector, request->bRequest);
+ }
+ return false;
+}
+
+static bool audio20_set_req_entity(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *buf) {
+ audio20_control_request_t const *request = (audio20_control_request_t const *) p_request;
+
+ if (request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT)
+ return audio20_feature_unit_set_request(rhport, request, buf);
+ if (request->bEntityID == UAC2_ENTITY_CLOCK)
+ return audio20_clock_set_request(rhport, request, buf);
+ TU_LOG1("Set request not handled, entity = %d, selector = %d, request = %d\r\n",
+ request->bEntityID, request->bControlSelector, request->bRequest);
+
+ return false;
+}
+
+#endif // TUD_OPT_HIGH_SPEED
+
+// Invoked when audio class specific set request received for an EP
+bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) {
+ (void) rhport;
+ (void) pBuff;
+
+ if (tud_audio_version() == 1) {
+ return audio10_set_req_ep(p_request, pBuff);
+ } else if (tud_audio_version() == 2) {
+ // We do not support any requests here
+ }
+
+ return false;// Yet not implemented
+}
+
+// Invoked when audio class specific get request received for an EP
+bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request) {
+ (void) rhport;
+
+ if (tud_audio_version() == 1) {
+ return audio10_get_req_ep(rhport, p_request);
+ } else if (tud_audio_version() == 2) {
+ // We do not support any requests here
+ }
+
+ return false;// Yet not implemented
+}
// Invoked when audio class specific get request received for an entity
bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request) {
- if (tud_audio_version() == 1) {
- // No entity in UAC1
- } else {
- audio20_control_request_t const *request = (audio20_control_request_t const *) p_request;
+ (void) rhport;
- if (request->bEntityID == UAC2_ENTITY_CLOCK)
- return tud_audio20_clock_get_request(rhport, request);
- if (request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT)
- return tud_audio20_feature_unit_get_request(rhport, request);
- else {
- TU_LOG1("Get request not handled, entity = %d, selector = %d, request = %d\r\n",
- request->bEntityID, request->bControlSelector, request->bRequest);
- }
+ if (tud_audio_version() == 1) {
+ return audio10_get_req_entity(rhport, p_request);
+#if TUD_OPT_HIGH_SPEED
+ } else if (tud_audio_version() == 2) {
+ return audio20_get_req_entity(rhport, p_request);
+#endif
}
return false;
@@ -282,14 +506,15 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p
// Invoked when audio class specific set request received for an entity
bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *buf) {
- audio20_control_request_t const *request = (audio20_control_request_t const *) p_request;
+ (void) rhport;
- if (request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT)
- return tud_audio20_feature_unit_set_request(rhport, request, buf);
- if (request->bEntityID == UAC2_ENTITY_CLOCK)
- return tud_audio20_clock_set_request(rhport, request, buf);
- TU_LOG1("Set request not handled, entity = %d, selector = %d, request = %d\r\n",
- request->bEntityID, request->bControlSelector, request->bRequest);
+ if (tud_audio_version() == 1) {
+ return audio10_set_req_entity(p_request, buf);
+#if TUD_OPT_HIGH_SPEED
+ } else if (tud_audio_version() == 2) {
+ return audio20_set_req_entity(rhport, p_request, buf);
+#endif
+ }
return false;
}
diff --git a/examples/device/uac2_headset/src/tusb_config.h b/examples/device/uac2_headset/src/tusb_config.h
index 5e6211cc0..339fb81a6 100644
--- a/examples/device/uac2_headset/src/tusb_config.h
+++ b/examples/device/uac2_headset/src/tusb_config.h
@@ -124,37 +124,45 @@ extern "C" {
#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX 2
#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_RX 16
-#if defined(__RX__)
-// 8bit in 8bit slots
-#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX 1
-#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_TX 8
-#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX 1
-#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_RX 8
-#else
-// 24bit in 32bit slots
+// 24bit in 32bit slots (UAC2 only)
#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX 4
#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_TX 24
#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX 4
#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_RX 24
-#endif
// EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense)
#define CFG_TUD_AUDIO_ENABLE_EP_IN 1
-#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN TUD_AUDIO_EP_SIZE(TUD_OPT_HIGH_SPEED, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX)
-#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN TUD_AUDIO_EP_SIZE(TUD_OPT_HIGH_SPEED, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX)
+// UAC1 (Full-Speed) Endpoint size calculation
+#define CFG_TUD_AUDIO10_FUNC_1_FORMAT_1_EP_SZ_IN TUD_AUDIO_EP_SIZE(false, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX)
+
+// UAC2 (High-Speed) Endpoint size calculation
+#define CFG_TUD_AUDIO20_FUNC_1_FORMAT_1_EP_SZ_IN TUD_AUDIO_EP_SIZE(true, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX)
+#define CFG_TUD_AUDIO20_FUNC_1_FORMAT_2_EP_SZ_IN TUD_AUDIO_EP_SIZE(true, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX)
+
+// Maximum EP IN size for all AS alternate settings used
+#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX TU_MAX(CFG_TUD_AUDIO10_FUNC_1_FORMAT_1_EP_SZ_IN, TU_MAX(CFG_TUD_AUDIO20_FUNC_1_FORMAT_1_EP_SZ_IN, CFG_TUD_AUDIO20_FUNC_1_FORMAT_2_EP_SZ_IN))
-#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN) // Maximum EP IN size for all AS alternate settings used
-#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX // Example read FIFO every 1ms, so it should be 8 times larger for HS device
+// Tx flow control needs buffer size >= 4* EP size to work correctly
+// Example write FIFO every 1ms (8 HS frames), so buffer size should be 8 times larger for HS device
+#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ TU_MAX(4 * CFG_TUD_AUDIO10_FUNC_1_FORMAT_1_EP_SZ_IN, TU_MAX(32 * CFG_TUD_AUDIO20_FUNC_1_FORMAT_1_EP_SZ_IN, 32 * CFG_TUD_AUDIO20_FUNC_1_FORMAT_2_EP_SZ_IN))
// EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense)
#define CFG_TUD_AUDIO_ENABLE_EP_OUT 1
-#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_OUT TUD_AUDIO_EP_SIZE(TUD_OPT_HIGH_SPEED, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX)
-#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_OUT TUD_AUDIO_EP_SIZE(TUD_OPT_HIGH_SPEED, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX)
+// UAC1 (Full-Speed) Endpoint size calculation
+#define CFG_TUD_AUDIO10_FUNC_1_FORMAT_1_EP_SZ_OUT TUD_AUDIO_EP_SIZE(false, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX)
+
+// UAC2 (High-Speed) Endpoint size calculation
+#define CFG_TUD_AUDIO20_FUNC_1_FORMAT_1_EP_SZ_OUT TUD_AUDIO_EP_SIZE(true, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX)
+#define CFG_TUD_AUDIO20_FUNC_1_FORMAT_2_EP_SZ_OUT TUD_AUDIO_EP_SIZE(true, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX)
+
+// Maximum EP OUT size for all AS alternate settings used
+#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX TU_MAX(CFG_TUD_AUDIO10_FUNC_1_FORMAT_1_EP_SZ_OUT, TU_MAX(CFG_TUD_AUDIO20_FUNC_1_FORMAT_1_EP_SZ_OUT, CFG_TUD_AUDIO20_FUNC_1_FORMAT_2_EP_SZ_OUT))
-#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_OUT, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_OUT) // Maximum EP IN size for all AS alternate settings used
-#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX // Example read FIFO every 1ms, so it should be 8 times larger for HS device
+// Rx flow control needs buffer size >= 4* EP size to work correctly
+// Example read FIFO every 1ms (8 HS frames), so buffer size should be 8 times larger for HS device
+#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ TU_MAX(4 * CFG_TUD_AUDIO10_FUNC_1_FORMAT_1_EP_SZ_OUT, TU_MAX(32 * CFG_TUD_AUDIO20_FUNC_1_FORMAT_1_EP_SZ_OUT, 32 * CFG_TUD_AUDIO20_FUNC_1_FORMAT_2_EP_SZ_OUT))
// Size of control request buffer
#define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64
diff --git a/examples/device/uac2_headset/src/usb_descriptors.c b/examples/device/uac2_headset/src/usb_descriptors.c
index bc9160d5e..b7e024e9e 100644
--- a/examples/device/uac2_headset/src/usb_descriptors.c
+++ b/examples/device/uac2_headset/src/usb_descriptors.c
@@ -110,22 +110,93 @@ uint8_t const * tud_descriptor_device_cb(void)
#define EPNUM_AUDIO_INT 0x02
#endif
-uint8_t const desc_configuration[] =
+#define CONFIG_UAC1_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_AUDIO10_HEADSET_STEREO_DESC_LEN(2))
+
+uint8_t const desc_uac1_configuration[] =
+{
+ // Config number, interface count, string index, total length, attribute, power in mA
+ TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_UAC1_TOTAL_LEN, 0x00, 100),
+
+ // Interface number, string index, bytes per sample RX/TX, bits used per sample RX/TX, EP Out & EP In address, EP sizes, sample rate
+ TUD_AUDIO10_HEADSET_STEREO_DESCRIPTOR(ITF_NUM_AUDIO_CONTROL, 2, \
+ CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_RX, \
+ CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_TX, \
+ EPNUM_AUDIO_OUT, CFG_TUD_AUDIO10_FUNC_1_FORMAT_1_EP_SZ_OUT, \
+ EPNUM_AUDIO_IN | 0x80, CFG_TUD_AUDIO10_FUNC_1_FORMAT_1_EP_SZ_IN, \
+ 44100, 48000)
+};
+
+TU_VERIFY_STATIC(sizeof(desc_uac1_configuration) == CONFIG_UAC1_TOTAL_LEN, "Incorrect size");
+
+#if TUD_OPT_HIGH_SPEED
+
+#define CONFIG_UAC2_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_AUDIO20_HEADSET_STEREO_DESC_LEN)
+
+uint8_t const desc_uac2_configuration[] =
{
// Config number, interface count, string index, total length, attribute, power in mA
- TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
+ TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_UAC2_TOTAL_LEN, 0x00, 100),
// Interface number, string index, EP Out & EP In address, EP size
- TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, EPNUM_AUDIO_OUT, EPNUM_AUDIO_IN | 0x80, EPNUM_AUDIO_INT | 0x80)
+ TUD_AUDIO20_HEADSET_STEREO_DESCRIPTOR(2, EPNUM_AUDIO_OUT, EPNUM_AUDIO_IN | 0x80, EPNUM_AUDIO_INT | 0x80)
+};
+
+TU_VERIFY_STATIC(sizeof(desc_uac2_configuration) == CONFIG_UAC2_TOTAL_LEN, "Incorrect size");
+
+
+// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed
+tusb_desc_device_qualifier_t const desc_device_qualifier =
+{
+ .bLength = sizeof(tusb_desc_device_qualifier_t),
+ .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER,
+ .bcdUSB = 0x0200,
+
+ .bDeviceClass = TUSB_CLASS_MISC,
+ .bDeviceSubClass = MISC_SUBCLASS_COMMON,
+ .bDeviceProtocol = MISC_PROTOCOL_IAD,
+
+ .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
+ .bNumConfigurations = 0x01,
+ .bReserved = 0x00
};
+// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request
+// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.
+// device_qualifier descriptor describes information about a high-speed capable device that would
+// change if the device were operating at the other speed. If not highspeed capable stall this request.
+uint8_t const *tud_descriptor_device_qualifier_cb(void)
+{
+ return (uint8_t const *) &desc_device_qualifier;
+}
+
+// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request
+// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
+// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa
+uint8_t const *tud_descriptor_other_speed_configuration_cb(uint8_t index)
+{
+ (void) index; // for multiple configurations
+
+ // if link speed is high return fullspeed config, and vice versa
+ return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_uac1_configuration : desc_uac2_configuration;
+}
+#endif
+
// Invoked when received GET CONFIGURATION DESCRIPTOR
// Application return pointer to descriptor
// Descriptor contents must exist long enough for transfer to complete
uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
{
(void)index; // for multiple configurations
- return desc_configuration;
+#if TUD_OPT_HIGH_SPEED
+ // Although we are highspeed, host may be fullspeed.
+ if(tud_speed_get() == TUSB_SPEED_FULL) {
+ return desc_uac1_configuration;
+ } else {
+ return desc_uac2_configuration;
+ }
+#else
+ return desc_uac1_configuration;
+#endif
}
//--------------------------------------------------------------------+
diff --git a/examples/device/uac2_headset/src/usb_descriptors.h b/examples/device/uac2_headset/src/usb_descriptors.h
index 465fa6035..b6ebe2ae4 100644
--- a/examples/device/uac2_headset/src/usb_descriptors.h
+++ b/examples/device/uac2_headset/src/usb_descriptors.h
@@ -26,7 +26,17 @@
#ifndef _USB_DESCRIPTORS_H_
#define _USB_DESCRIPTORS_H_
-// #include "tusb.h"
+enum
+{
+ ITF_NUM_AUDIO_CONTROL = 0,
+ ITF_NUM_AUDIO_STREAMING_SPK,
+ ITF_NUM_AUDIO_STREAMING_MIC,
+ ITF_NUM_TOTAL
+};
+
+//--------------------------------------------------------------------+
+// UAC2 DESCRIPTOR TEMPLATES
+//--------------------------------------------------------------------+
// Unit numbers are arbitrary selected
#define UAC2_ENTITY_CLOCK 0x04
@@ -38,15 +48,7 @@
#define UAC2_ENTITY_MIC_INPUT_TERMINAL 0x11
#define UAC2_ENTITY_MIC_OUTPUT_TERMINAL 0x13
-enum
-{
- ITF_NUM_AUDIO_CONTROL = 0,
- ITF_NUM_AUDIO_STREAMING_SPK,
- ITF_NUM_AUDIO_STREAMING_MIC,
- ITF_NUM_TOTAL
-};
-
-#define TUD_AUDIO_HEADSET_STEREO_DESC_LEN (TUD_AUDIO20_DESC_IAD_LEN\
+#define TUD_AUDIO20_HEADSET_STEREO_DESC_LEN (TUD_AUDIO20_DESC_IAD_LEN\
+ TUD_AUDIO20_DESC_STD_AC_LEN\
+ TUD_AUDIO20_DESC_CS_AC_LEN\
+ TUD_AUDIO20_DESC_CLK_SRC_LEN\
@@ -85,7 +87,7 @@ enum
+ TUD_AUDIO20_DESC_STD_AS_ISO_EP_LEN\
+ TUD_AUDIO20_DESC_CS_AS_ISO_EP_LEN)
-#define TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(_stridx, _epout, _epin, _epint) \
+#define TUD_AUDIO20_HEADSET_STEREO_DESCRIPTOR(_stridx, _epout, _epin, _epint) \
/* Standard Interface Association Descriptor (IAD) */\
TUD_AUDIO20_DESC_IAD(/*_firstitf*/ ITF_NUM_AUDIO_CONTROL, /*_nitfs*/ ITF_NUM_TOTAL, /*_stridx*/ 0x00),\
/* Standard AC Interface Descriptor(4.7.1) */\
@@ -95,7 +97,7 @@ enum
/* Clock Source Descriptor(4.7.2.1) */\
TUD_AUDIO20_DESC_CLK_SRC(/*_clkid*/ UAC2_ENTITY_CLOCK, /*_attr*/ 3, /*_ctrl*/ 7, /*_assocTerm*/ 0x00, /*_stridx*/ 0x00), \
/* Input Terminal Descriptor(4.7.2.4) */\
- TUD_AUDIO20_DESC_INPUT_TERM(/*_termid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_nchannelslogical*/ 0x02, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO20_CTRL_R << AUDIO20_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\
+ TUD_AUDIO20_DESC_INPUT_TERM(/*_termid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_nchannelslogical*/ 0x02, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO20_CTRL_R << AUDIO20_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\
/* Feature Unit Descriptor(4.7.2.8) */\
TUD_AUDIO20_DESC_FEATURE_UNIT(/*_unitid*/ UAC2_ENTITY_SPK_FEATURE_UNIT, /*_srcid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_stridx*/ 0x00, /*_ctrlch0master*/ (AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_VOLUME_POS), /*_ctrlch1*/ (AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_VOLUME_POS), /*_ctrlch2*/ (AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_VOLUME_POS)),\
/* Output Terminal Descriptor(4.7.2.5) */\
@@ -103,7 +105,7 @@ enum
/* Input Terminal Descriptor(4.7.2.4) */\
TUD_AUDIO20_DESC_INPUT_TERM(/*_termid*/ UAC2_ENTITY_MIC_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x00, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO20_CTRL_R << AUDIO20_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\
/* Output Terminal Descriptor(4.7.2.5) */\
- TUD_AUDIO20_DESC_OUTPUT_TERM(/*_termid*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_srcid*/ UAC2_ENTITY_MIC_INPUT_TERMINAL, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\
+ TUD_AUDIO20_DESC_OUTPUT_TERM(/*_termid*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_srcid*/ UAC2_ENTITY_MIC_INPUT_TERMINAL, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\
/* Standard AC Interrupt Endpoint Descriptor(4.8.2.1) */\
TUD_AUDIO20_DESC_STD_AC_INT_EP(/*_ep*/ _epint, /*_interval*/ 0x01), \
/* Standard AS Interface Descriptor(4.9.1) */\
@@ -155,4 +157,83 @@ enum
/* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\
TUD_AUDIO20_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO20_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_lockdelayunit*/ AUDIO20_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000)
+//--------------------------------------------------------------------+
+// UAC1 DESCRIPTOR TEMPLATES
+//--------------------------------------------------------------------+
+
+// UAC1 entity IDs for speaker and microphone
+// Speaker path
+#define UAC1_ENTITY_SPK_INPUT_TERMINAL 0x01
+#define UAC1_ENTITY_SPK_FEATURE_UNIT 0x02
+#define UAC1_ENTITY_SPK_OUTPUT_TERMINAL 0x03
+// Microphone path
+#define UAC1_ENTITY_MIC_INPUT_TERMINAL 0x11
+#define UAC1_ENTITY_MIC_OUTPUT_TERMINAL 0x13
+
+#define TUD_AUDIO10_HEADSET_STEREO_DESC_LEN(_nfreqs) (\
+ +TUD_AUDIO10_DESC_STD_AC_LEN\
+ + TUD_AUDIO10_DESC_CS_AC_LEN(2)\
+ + TUD_AUDIO10_DESC_INPUT_TERM_LEN\
+ + TUD_AUDIO10_DESC_FEATURE_UNIT_LEN(2)\
+ + TUD_AUDIO10_DESC_OUTPUT_TERM_LEN\
+ + TUD_AUDIO10_DESC_INPUT_TERM_LEN\
+ + TUD_AUDIO10_DESC_OUTPUT_TERM_LEN\
+ /* Interface 1, Alternate 0 (speaker) */\
+ + TUD_AUDIO10_DESC_STD_AS_LEN\
+ /* Interface 1, Alternate 1 (speaker) */\
+ + TUD_AUDIO10_DESC_STD_AS_LEN\
+ + TUD_AUDIO10_DESC_CS_AS_INT_LEN\
+ + TUD_AUDIO10_DESC_TYPE_I_FORMAT_LEN(_nfreqs)\
+ + TUD_AUDIO10_DESC_STD_AS_ISO_EP_LEN\
+ + TUD_AUDIO10_DESC_CS_AS_ISO_EP_LEN\
+ /* Interface 2, Alternate 0 (microphone) */\
+ + TUD_AUDIO10_DESC_STD_AS_LEN\
+ /* Interface 2, Alternate 1 (microphone) */\
+ + TUD_AUDIO10_DESC_STD_AS_LEN\
+ + TUD_AUDIO10_DESC_CS_AS_INT_LEN\
+ + TUD_AUDIO10_DESC_TYPE_I_FORMAT_LEN(_nfreqs)\
+ + TUD_AUDIO10_DESC_STD_AS_ISO_EP_LEN\
+ + TUD_AUDIO10_DESC_CS_AS_ISO_EP_LEN)
+
+
+#define TUD_AUDIO10_HEADSET_STEREO_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample_RX, _nBitsUsedPerSample_RX, _nBytesPerSample_TX, _nBitsUsedPerSample_TX, _epout, _epoutsize, _epin, _epinsize, ...) \
+ /* Standard AC Interface Descriptor(4.3.1) */\
+ TUD_AUDIO10_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\
+ /* Class-Specific AC Interface Header Descriptor(4.3.2) */\
+ TUD_AUDIO10_DESC_CS_AC(/*_bcdADC*/ 0x0100, /*_totallen*/ (TUD_AUDIO10_DESC_INPUT_TERM_LEN+TUD_AUDIO10_DESC_FEATURE_UNIT_LEN(2)+TUD_AUDIO10_DESC_OUTPUT_TERM_LEN+TUD_AUDIO10_DESC_INPUT_TERM_LEN+TUD_AUDIO10_DESC_FEATURE_UNIT_LEN(1)+TUD_AUDIO10_DESC_OUTPUT_TERM_LEN), /*_itf*/ ((_itfnum)+1), ((_itfnum)+2)),\
+ /* Speaker Input Terminal Descriptor(4.3.2.1) */\
+ TUD_AUDIO10_DESC_INPUT_TERM(/*_termid*/ UAC1_ENTITY_SPK_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ UAC1_ENTITY_MIC_OUTPUT_TERMINAL, /*_nchannels*/ 0x02, /*_channelcfg*/ AUDIO10_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_stridx*/ 0x00),\
+ /* Speaker Feature Unit Descriptor(4.3.2.5) */\
+ TUD_AUDIO10_DESC_FEATURE_UNIT(/*_unitid*/ UAC1_ENTITY_SPK_FEATURE_UNIT, /*_srcid*/ UAC1_ENTITY_SPK_INPUT_TERMINAL, /*_stridx*/ 0x00, /*_ctrlmaster*/ (AUDIO10_FU_CONTROL_BM_MUTE | AUDIO10_FU_CONTROL_BM_VOLUME), /*_ctrlch1*/ (AUDIO10_FU_CONTROL_BM_MUTE | AUDIO10_FU_CONTROL_BM_VOLUME), /*_ctrlch2*/ (AUDIO10_FU_CONTROL_BM_MUTE | AUDIO10_FU_CONTROL_BM_VOLUME)),\
+ /* Speaker Output Terminal Descriptor(4.3.2.2) */\
+ TUD_AUDIO10_DESC_OUTPUT_TERM(/*_termid*/ UAC1_ENTITY_SPK_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_OUT_HEADPHONES, /*_assocTerm*/ 0x00, /*_srcid*/ UAC1_ENTITY_SPK_FEATURE_UNIT, /*_stridx*/ 0x00),\
+ /* Microphone Input Terminal Descriptor(4.3.2.1) */\
+ TUD_AUDIO10_DESC_INPUT_TERM(/*_termid*/ UAC1_ENTITY_MIC_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x00, /*_nchannels*/ 0x01, /*_channelcfg*/ AUDIO10_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_stridx*/ 0x00),\
+ /* Microphone Output Terminal Descriptor(4.3.2.2) */\
+ TUD_AUDIO10_DESC_OUTPUT_TERM(/*_termid*/ UAC1_ENTITY_MIC_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ UAC1_ENTITY_SPK_INPUT_TERMINAL, /*_srcid*/ UAC1_ENTITY_MIC_INPUT_TERMINAL, /*_stridx*/ 0x00),\
+ /* Standard AS Interface Descriptor(4.5.1) - Speaker Interface 1, Alternate 0 */\
+ TUD_AUDIO10_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x05),\
+ /* Standard AS Interface Descriptor(4.5.1) - Speaker Interface 1, Alternate 1 */\
+ TUD_AUDIO10_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x05),\
+ /* Class-Specific AS Interface Descriptor(4.5.2) */\
+ TUD_AUDIO10_DESC_CS_AS_INT(/*_termid*/ UAC1_ENTITY_SPK_INPUT_TERMINAL, /*_delay*/ 0x01, /*_formattype*/ AUDIO10_DATA_FORMAT_TYPE_I_PCM),\
+ /* Type I Format Type Descriptor(2.2.5) */\
+ TUD_AUDIO10_DESC_TYPE_I_FORMAT(/*_nrchannels*/ 0x02, /*_subframesize*/ _nBytesPerSample_RX, /*_bitresolution*/ _nBitsUsedPerSample_RX, /*_freqs*/ __VA_ARGS__),\
+ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.6.1.1) */\
+ TUD_AUDIO10_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ADAPTIVE), /*_maxEPsize*/ _epoutsize, /*_interval*/ 0x01, /*_syncep*/ 0x00),\
+ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.6.1.2) */\
+ TUD_AUDIO10_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO10_CS_AS_ISO_DATA_EP_ATT_SAMPLING_FRQ, /*_lockdelayunits*/ AUDIO10_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC, /*_lockdelay*/ 0x0001),\
+ /* Standard AS Interface Descriptor(4.5.1) - Microphone Interface 2, Alternate 0 */\
+ TUD_AUDIO10_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+2), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x04),\
+ /* Standard AS Interface Descriptor(4.5.1) - Microphone Interface 2, Alternate 1 */\
+ TUD_AUDIO10_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+2), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x04),\
+ /* Class-Specific AS Interface Descriptor(4.5.2) */\
+ TUD_AUDIO10_DESC_CS_AS_INT(/*_termid*/ UAC1_ENTITY_MIC_OUTPUT_TERMINAL, /*_delay*/ 0x01, /*_formattype*/ AUDIO10_DATA_FORMAT_TYPE_I_PCM),\
+ /* Type I Format Type Descriptor(2.2.5) */\
+ TUD_AUDIO10_DESC_TYPE_I_FORMAT(/*_nrchannels*/ 0x01, /*_subframesize*/ _nBytesPerSample_TX, /*_bitresolution*/ _nBitsUsedPerSample_TX, /*_freqs*/ __VA_ARGS__),\
+ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.6.1.1) */\
+ TUD_AUDIO10_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS), /*_maxEPsize*/ _epinsize, /*_interval*/ 0x01, /*_syncep*/ 0x00),\
+ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.6.1.2) */\
+ TUD_AUDIO10_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO10_CS_AS_ISO_DATA_EP_ATT_SAMPLING_FRQ, /*_lockdelayunits*/ AUDIO10_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC, /*_lockdelay*/ 0x0001)
+
#endif