summaryrefslogtreecommitdiff
path: root/examples/device/audio_test_multi_rate/src
diff options
context:
space:
mode:
authorHiFiPhile <[email protected]>2026-06-22 21:30:58 +0200
committerHiFiPhile <[email protected]>2026-06-22 21:30:58 +0200
commit693cdce08e14833f26f4e8a1f26e4fd546be4c35 (patch)
tree7667d2223dc32d9f21b5b60ab200e64ed46e3e20 /examples/device/audio_test_multi_rate/src
parent41e9eaa65a935136085d78ec4b99c81ff991b560 (diff)
parentcd3561bf158afd5a5718904b8139a338d1e3b67c (diff)
Merge remote-tracking branch 'tinyusb/master' into pr-osal-spin-deinit
Signed-off-by: HiFiPhile <[email protected]>
Diffstat (limited to 'examples/device/audio_test_multi_rate/src')
-rw-r--r--examples/device/audio_test_multi_rate/src/main.c377
-rwxr-xr-xexamples/device/audio_test_multi_rate/src/plot_audio_samples.py50
-rw-r--r--examples/device/audio_test_multi_rate/src/tusb_config.h29
-rw-r--r--examples/device/audio_test_multi_rate/src/usb_descriptors.c109
-rw-r--r--examples/device/audio_test_multi_rate/src/usb_descriptors.h78
5 files changed, 452 insertions, 191 deletions
diff --git a/examples/device/audio_test_multi_rate/src/main.c b/examples/device/audio_test_multi_rate/src/main.c
index 9d467991e..a86beb415 100644
--- a/examples/device/audio_test_multi_rate/src/main.c
+++ b/examples/device/audio_test_multi_rate/src/main.c
@@ -60,7 +60,7 @@ static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
// Audio controls
// Current states
bool mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0
-uint16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// +1 for master channel 0
+int16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// +1 for master channel 0
uint32_t sampFreq;
uint8_t bytesPerSample;
uint8_t clkValid;
@@ -80,9 +80,6 @@ static const uint8_t bytesPerSampleAltList[CFG_TUD_AUDIO_FUNC_1_N_FORMATS] =
CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX,
};
-audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// Volume range state
-
-
// Audio test data
CFG_TUD_MEM_ALIGN uint8_t test_buffer_audio[(TUD_OPT_HIGH_SPEED ? 8 : 1) * CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX];
uint16_t startVal = 0;
@@ -111,9 +108,6 @@ int main(void) {
led_blinking_task();
audio_task();
}
-
-
- return 0;
}
//--------------------------------------------------------------------+
@@ -152,8 +146,10 @@ void tud_resume_cb(void) {
// In a real application, this would be replaced with actual I2S receive callback.
void audio_task(void) {
static uint32_t start_ms = 0;
- uint32_t curr_ms = board_millis();
- if (start_ms == curr_ms) return;// not enough time
+ uint32_t curr_ms = tusb_time_millis_api();
+ if (start_ms == curr_ms) {
+ return; // not enough time
+ }
start_ms = curr_ms;
// 16bit
if (bytesPerSample == 2) {
@@ -176,91 +172,204 @@ void audio_task(void) {
// Application Callback API Implementations
//--------------------------------------------------------------------+
-// Invoked when set interface is called, typically on start/stop streaming or format change
-bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request) {
- (void) rhport;
- //uint8_t const itf = tu_u16_low(tu_le16toh(p_request->wIndex));
- uint8_t const alt = tu_u16_low(tu_le16toh(p_request->wValue));
+//--------------------------------------------------------------------+
+// UAC1 Helper Functions
+//--------------------------------------------------------------------+
- // Clear buffer when streaming format is changed
- if (alt != 0) {
- bytesPerSample = bytesPerSampleAltList[alt - 1];
+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);
+
+ sampFreq = tu_unaligned_read32(pBuff) & 0x00FFFFFF;
+
+ TU_LOG2("EP set current freq: %" PRIu32 "\r\n", sampFreq);
+
+ return true;
+ }
+ break;
+
+ // Unknown/Unsupported control
+ default:
+ TU_BREAKPOINT();
+ return false;
}
- return true;
+
+ return false;
}
-// 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;
+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);
- // We do not support any set range requests here, only current value requests
- TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR);
+ 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) (sampFreq & 0xFF);
+ freq[1] = (uint8_t) ((sampFreq >> 8) & 0xFF);
+ freq[2] = (uint8_t) ((sampFreq >> 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;
+}
- // Page 91 in UAC2 specification
+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 ep = TU_U16_LOW(p_request->wIndex);
+ uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
- (void) channelNum;
- (void) ctrlSel;
- (void) ep;
+ // If request is for our feature unit (ID defined in usbd.h)
+ if (entityID == 0x02) {
+ 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);
- return false;// Yet not implemented
-}
+ mute[channelNum] = pBuff[0];
-// Invoked when audio class specific set request received for an interface
-bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) {
- (void) rhport;
- (void) pBuff;
+ TU_LOG2(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum);
+ return true;
- // We do not support any set range requests here, only current value requests
- TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR);
+ default:
+ return false; // not supported
+ }
- // Page 91 in UAC2 specification
+ 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 itf = TU_U16_LOW(p_request->wIndex);
+ uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
+
+ // If request is for our feature unit (ID defined in usbd.h)
+ if (entityID == 0x02) {
+ 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);
- (void) channelNum;
- (void) ctrlSel;
- (void) itf;
+ 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));
+ }
- return false;// Yet not implemented
+ 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;
}
-// 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 *pBuff) {
- (void) rhport;
+//--------------------------------------------------------------------+
+// UAC2 Helper Functions
+//--------------------------------------------------------------------+
+
+#if TUD_OPT_HIGH_SPEED
- // Page 91 in UAC2 specification
+static bool audio20_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 itf = TU_U16_LOW(p_request->wIndex);
uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
- (void) itf;
-
// We do not support any set range requests here, only current value requests
- TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR);
+ TU_VERIFY(p_request->bRequest == AUDIO20_CS_REQ_CUR);
// If request is for our feature unit
if (entityID == UAC2_ENTITY_FEATURE_UNIT) {
switch (ctrlSel) {
- case AUDIO_FU_CTRL_MUTE:
+ case AUDIO20_FU_CTRL_MUTE:
// Request uses format layout 1
- TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_1_t));
+ TU_VERIFY(p_request->wLength == sizeof(audio20_control_cur_1_t));
- mute[channelNum] = ((audio_control_cur_1_t *) pBuff)->bCur;
+ mute[channelNum] = ((audio20_control_cur_1_t *) pBuff)->bCur;
TU_LOG2(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum);
return true;
- case AUDIO_FU_CTRL_VOLUME:
+ case AUDIO20_FU_CTRL_VOLUME:
// Request uses format layout 2
- TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_2_t));
+ TU_VERIFY(p_request->wLength == sizeof(audio20_control_cur_2_t));
- volume[channelNum] = (uint16_t) ((audio_control_cur_2_t *) pBuff)->bCur;
+ volume[channelNum] = (int16_t) ((audio20_control_cur_2_t *) pBuff)->bCur;
TU_LOG2(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum);
return true;
@@ -275,10 +384,10 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p
// Clock Source unit
if (entityID == UAC2_ENTITY_CLOCK) {
switch (ctrlSel) {
- case AUDIO_CS_CTRL_SAM_FREQ:
- TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_4_t));
+ case AUDIO20_CS_CTRL_SAM_FREQ:
+ TU_VERIFY(p_request->wLength == sizeof(audio20_control_cur_4_t));
- sampFreq = (uint32_t) ((audio_control_cur_4_t *) pBuff)->bCur;
+ sampFreq = (uint32_t) ((audio20_control_cur_4_t *) pBuff)->bCur;
TU_LOG2("Clock set current freq: %" PRIu32 "\r\n", sampFreq);
@@ -292,59 +401,20 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p
}
}
- 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;
-
- // Page 91 in UAC2 specification
- uint8_t channelNum = TU_U16_LOW(p_request->wValue);
- uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue);
- uint8_t ep = TU_U16_LOW(p_request->wIndex);
-
- (void) channelNum;
- (void) ctrlSel;
- (void) ep;
-
- // return tud_control_xfer(rhport, p_request, &tmp, 1);
-
- return false;// Yet not implemented
-}
-
-// Invoked when audio class specific get request received for an interface
-bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request) {
- (void) rhport;
-
- // Page 91 in UAC2 specification
- uint8_t channelNum = TU_U16_LOW(p_request->wValue);
- uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue);
- uint8_t itf = TU_U16_LOW(p_request->wIndex);
-
- (void) channelNum;
- (void) ctrlSel;
- (void) itf;
-
- return false;// Yet not implemented
+ return false;
}
-// 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) {
- (void) rhport;
-
- // Page 91 in UAC2 specification
+static bool audio20_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 itf = TU_U16_LOW(p_request->wIndex); // Since we have only one audio function implemented, we do not need the itf value
uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
// Input terminal (Microphone input)
if (entityID == UAC2_ENTITY_INPUT_TERMINAL) {
switch (ctrlSel) {
- case AUDIO_TE_CTRL_CONNECTOR: {
+ case AUDIO20_TE_CTRL_CONNECTOR: {
// The terminal connector control only has a get request with only the CUR attribute.
- audio_desc_channel_cluster_t ret;
+ audio20_desc_channel_cluster_t ret;
// Those are dummy values for now
ret.bNrChannels = 1;
@@ -366,23 +436,23 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p
// Feature unit
if (entityID == UAC2_ENTITY_FEATURE_UNIT) {
switch (ctrlSel) {
- case AUDIO_FU_CTRL_MUTE:
+ case AUDIO20_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 AUDIO_FU_CTRL_VOLUME:
+ case AUDIO20_FU_CTRL_VOLUME:
switch (p_request->bRequest) {
- case AUDIO_CS_REQ_CUR:
+ case AUDIO20_CS_REQ_CUR:
TU_LOG2(" Get Volume of channel: %u\r\n", channelNum);
return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &volume[channelNum], sizeof(volume[channelNum]));
- case AUDIO_CS_REQ_RANGE:
+ case AUDIO20_CS_REQ_RANGE:
TU_LOG2(" Get Volume range of channel: %u\r\n", channelNum);
// Copy values - only for testing - better is version below
- audio_control_range_2_n_t(1)
+ audio20_control_range_2_n_t(1)
ret;
ret.wNumSubRanges = 1;
@@ -409,16 +479,16 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p
// Clock Source unit
if (entityID == UAC2_ENTITY_CLOCK) {
switch (ctrlSel) {
- case AUDIO_CS_CTRL_SAM_FREQ:
+ case AUDIO20_CS_CTRL_SAM_FREQ:
// channelNum is always zero in this case
switch (p_request->bRequest) {
- case AUDIO_CS_REQ_CUR:
+ case AUDIO20_CS_REQ_CUR:
TU_LOG2(" Get Sample Freq.\r\n");
return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq));
- case AUDIO_CS_REQ_RANGE: {
+ case AUDIO20_CS_REQ_RANGE: {
TU_LOG2(" Get Sample Freq. range\r\n");
- audio_control_range_4_n_t(N_sampleRates) rangef =
+ audio20_control_range_4_n_t(N_sampleRates) rangef =
{
.wNumSubRanges = tu_htole16(N_sampleRates)};
TU_LOG1("Clock get %d freq ranges\r\n", N_sampleRates);
@@ -437,7 +507,7 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p
}
break;
- case AUDIO_CS_CTRL_CLK_VALID:
+ case AUDIO20_CS_CTRL_CLK_VALID:
// Only cur attribute exists for this request
TU_LOG2(" Get Sample Freq. valid\r\n");
return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &clkValid, sizeof(clkValid));
@@ -449,7 +519,82 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p
}
}
- TU_LOG2(" Unsupported entity: %d\r\n", entityID);
+ return false;
+}
+
+#endif // TUD_OPT_HIGH_SPEED
+
+//--------------------------------------------------------------------+
+// Main Callback Functions
+//--------------------------------------------------------------------+
+
+// Invoked when set interface is called, typically on start/stop streaming or format change
+bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request) {
+ (void) rhport;
+ //uint8_t const itf = tu_u16_low(tu_le16toh(p_request->wIndex));
+ uint8_t const alt = tu_u16_low(p_request->wValue);
+
+ // Clear buffer when streaming format is changed
+ if (alt != 0) {
+ bytesPerSample = bytesPerSampleAltList[alt - 1];
+ }
+ return true;
+}
+
+// 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 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 *pBuff) {
+ (void) rhport;
+
+ if (tud_audio_version() == 1) {
+ return audio10_set_req_entity(p_request, pBuff);
+#if TUD_OPT_HIGH_SPEED
+ } else if (tud_audio_version() == 2) {
+ return audio20_set_req_entity(p_request, pBuff);
+#endif
+ }
+
+ 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) {
+ (void) rhport;
+
+ 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;// Yet not implemented
}
@@ -469,7 +614,9 @@ void led_blinking_task(void) {
static bool led_state = false;
// Blink every interval ms
- if (board_millis() - start_ms < blink_interval_ms) return;// not enough time
+ if (tusb_time_millis_api() - start_ms < blink_interval_ms) {
+ return; // not enough time
+ }
start_ms += blink_interval_ms;
board_led_write(led_state);
diff --git a/examples/device/audio_test_multi_rate/src/plot_audio_samples.py b/examples/device/audio_test_multi_rate/src/plot_audio_samples.py
index 1f33a003e..f35cfa311 100755
--- a/examples/device/audio_test_multi_rate/src/plot_audio_samples.py
+++ b/examples/device/audio_test_multi_rate/src/plot_audio_samples.py
@@ -5,6 +5,52 @@ import numpy as np
import platform
import csv
+
+def find_windows_input_device(name_hint, channels, preferred_apis=None):
+ """Pick a Windows input device index from query_devices() output."""
+ preferred_apis = preferred_apis or []
+ name_hint = name_hint.lower()
+ candidates = []
+
+ for index in range(len(sd.query_devices())):
+ device_info = sd.query_devices(index)
+ max_input_channels = int(device_info.get('max_input_channels', 0))
+
+ if max_input_channels < channels:
+ continue
+
+ device_name = str(device_info.get('name', '')).lower()
+ if name_hint not in device_name:
+ continue
+
+ score = 0
+
+ # Prefer exact channel matches (for example 1ch source over a 4ch source).
+ if max_input_channels == channels:
+ score += 100
+ else:
+ score += 10
+
+ hostapi_index = int(device_info.get('hostapi', -1))
+ api_name = ''
+ if hostapi_index >= 0:
+ hostapi_info = sd.query_hostapis(hostapi_index)
+ api_name = str(hostapi_info.get('name', '')).lower()
+
+ for priority, api_hint in enumerate(preferred_apis):
+ if api_hint in api_name:
+ score += 50 - priority
+ break
+
+ candidates.append((score, index))
+
+ if not candidates:
+ raise ValueError(
+ 'No input device matching hint="{}" with at least {} channels'.format(name_hint, channels)
+ )
+
+ return max(candidates, key=lambda item: item[0])[1]
+
if __name__ == '__main__':
# If you got "ValueError: No input device matching", that is because your PC name example device
@@ -15,8 +61,8 @@ if __name__ == '__main__':
duration = 100e-3 # Duration of recording
if platform.system() == 'Windows':
- # MME is needed since there are more than one MicNode device APIs (at least in Windows)
- device = 'Microphone (MicNode) MME'
+ # Match by substring to support names like "Microphone (2- MicNode)".
+ device = find_windows_input_device('micnode', channels=1, preferred_apis=['mme', 'wasapi', 'wdm-ks'])
elif platform.system() == 'Darwin':
device = 'MicNode'
else:
diff --git a/examples/device/audio_test_multi_rate/src/tusb_config.h b/examples/device/audio_test_multi_rate/src/tusb_config.h
index b48c0a0be..3587ae089 100644
--- a/examples/device/audio_test_multi_rate/src/tusb_config.h
+++ b/examples/device/audio_test_multi_rate/src/tusb_config.h
@@ -23,8 +23,8 @@
*
*/
-#ifndef _TUSB_CONFIG_H_
-#define _TUSB_CONFIG_H_
+#ifndef TUSB_CONFIG_H_
+#define TUSB_CONFIG_H_
#ifdef __cplusplus
extern "C" {
@@ -116,26 +116,31 @@ extern "C" {
#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX 2
#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_RX 16
-// 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_RX 24
// Have a look into audio_device.h for all configurations
-#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_MIC_ONE_CH_2_FORMAT_DESC_LEN
-#define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64 // Size of control request buffer
+#define CFG_TUD_AUDIO_ENABLE_EP_IN 1
+#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below - be aware: for different number of channels you need another descriptor!
-#define CFG_TUD_AUDIO_ENABLE_EP_IN 1
-#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below - be aware: for different number of channels you need another descriptor!
+// 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)
-#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN TUD_AUDIO_EP_SIZE(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(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)
+// 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)
-#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 write FIFO every 1ms, so it should be 8 times larger for HS device
+// 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))
+
+// 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))
#ifdef __cplusplus
}
#endif
-#endif /* _TUSB_CONFIG_H_ */
+#endif /* TUSB_CONFIG_H_ */
diff --git a/examples/device/audio_test_multi_rate/src/usb_descriptors.c b/examples/device/audio_test_multi_rate/src/usb_descriptors.c
index f50e70a25..b1f60dd10 100644
--- a/examples/device/audio_test_multi_rate/src/usb_descriptors.c
+++ b/examples/device/audio_test_multi_rate/src/usb_descriptors.c
@@ -34,15 +34,14 @@
* Auto ProductID layout's Bitmap:
* [MSB] AUDIO | MIDI | HID | MSC | CDC [LSB]
*/
-#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) )
-#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
- _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) )
+#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0)
+#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \
+ PID_MAP(MIDI, 3) | PID_MAP(AUDIO, 4) | PID_MAP(VENDOR, 5) )
//--------------------------------------------------------------------+
// Device Descriptors
//--------------------------------------------------------------------+
-tusb_desc_device_t const desc_device =
-{
+static tusb_desc_device_t const desc_device = {
.bLength = sizeof(tusb_desc_device_t),
.bDescriptorType = TUSB_DESC_DEVICE,
.bcdUSB = 0x0200,
@@ -67,23 +66,19 @@ tusb_desc_device_t const desc_device =
// Invoked when received GET DEVICE DESCRIPTOR
// Application return pointer to descriptor
-uint8_t const * tud_descriptor_device_cb(void)
-{
+uint8_t const * tud_descriptor_device_cb(void) {
return (uint8_t const *) &desc_device;
}
//--------------------------------------------------------------------+
// Configuration Descriptor
//--------------------------------------------------------------------+
-enum
-{
+enum {
ITF_NUM_AUDIO_CONTROL = 0,
ITF_NUM_AUDIO_STREAMING,
ITF_NUM_TOTAL
};
-#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO_MIC_ONE_CH_2_FORMAT_DESC_LEN)
-
#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX
// LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number
// 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ...
@@ -93,28 +88,93 @@ enum
// nRF5x ISO can only be endpoint 8
#define EPNUM_AUDIO 0x08
+#elif TU_CHECK_MCU(OPT_MCU_MAX32650, OPT_MCU_MAX32666, OPT_MCU_MAX32690, OPT_MCU_MAX78002)
+ // Put audio iso on EP>=8 so the 2048/4096-byte FIFOs can back double packet buffering
+ #define EPNUM_AUDIO 0x0A
+
+#elif TU_CHECK_MCU(OPT_MCU_CH32V20X, OPT_MCU_CH32V307)
+ // Only EP3 is available for ISO
+ #define EPNUM_AUDIO 0x03
+
#else
#define EPNUM_AUDIO 0x01
#endif
-uint8_t const desc_configuration[] =
-{
+#define CONFIG_UAC1_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_AUDIO10_MIC_ONE_CH_DESC_LEN(3))
+
+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, EP Out & EP In address, EP size
+ TUD_AUDIO10_MIC_ONE_CH_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ 2, /*_nBitsUsedPerSample*/ 16, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO10_FUNC_1_FORMAT_1_EP_SZ_IN, 32000, 48000, 96000)
+};
+
+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_MIC_ONE_CH_2_FORMAT_DESC_LEN)
+
+uint8_t const desc2_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_MIC_ONE_CH_2_FORMAT_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_epin*/ 0x80 | EPNUM_AUDIO)
+ TUD_AUDIO20_MIC_ONE_CH_2_FORMAT_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_epin*/ 0x80 | EPNUM_AUDIO)
};
-TU_VERIFY_STATIC(sizeof(desc_configuration) == CONFIG_TOTAL_LEN, "Incorrect size");
+TU_VERIFY_STATIC(sizeof(desc2_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 : desc2_uac2_configuration;
+}
+
+#endif// highspeed
// 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)
-{
+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 desc2_uac2_configuration;
+ }
+#else
+ return desc_uac1_configuration;
+#endif
}
//--------------------------------------------------------------------+
@@ -130,8 +190,7 @@ enum {
};
// array of pointer to string descriptors
-char const* string_desc_arr [] =
-{
+char const* string_desc_arr [] = {
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
"PaniRCorp", // 1: Manufacturer
"MicNode", // 2: Product
@@ -162,14 +221,18 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
// Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
// https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
- if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL;
+ if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) {
+ return NULL;
+ }
const char *str = string_desc_arr[index];
// Cap at max char
chr_count = strlen(str);
size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type
- if ( chr_count > max_count ) chr_count = max_count;
+ if (chr_count > max_count) {
+ chr_count = max_count;
+ }
// Convert ASCII string into UTF-16
for ( size_t i = 0; i < chr_count; i++ ) {
diff --git a/examples/device/audio_test_multi_rate/src/usb_descriptors.h b/examples/device/audio_test_multi_rate/src/usb_descriptors.h
index 8381e31f5..948a7f4ae 100644
--- a/examples/device/audio_test_multi_rate/src/usb_descriptors.h
+++ b/examples/device/audio_test_multi_rate/src/usb_descriptors.h
@@ -23,8 +23,8 @@
*
*/
-#ifndef _USB_DESCRIPTORS_H_
-#define _USB_DESCRIPTORS_H_
+#ifndef USB_DESCRIPTORS_H_
+#define USB_DESCRIPTORS_H_
// #include "tusb.h"
@@ -35,68 +35,68 @@
#define UAC2_ENTITY_FEATURE_UNIT 0x02
-#define TUD_AUDIO_MIC_ONE_CH_2_FORMAT_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\
- + TUD_AUDIO_DESC_STD_AC_LEN\
- + TUD_AUDIO_DESC_CS_AC_LEN\
- + TUD_AUDIO_DESC_CLK_SRC_LEN\
- + TUD_AUDIO_DESC_INPUT_TERM_LEN\
- + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\
- + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN\
+#define TUD_AUDIO20_MIC_ONE_CH_2_FORMAT_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\
+ + TUD_AUDIO20_DESC_INPUT_TERM_LEN\
+ + TUD_AUDIO20_DESC_OUTPUT_TERM_LEN\
+ + TUD_AUDIO20_DESC_FEATURE_UNIT_LEN(1)\
/* Interface 1, Alternate 0 */\
- + TUD_AUDIO_DESC_STD_AS_INT_LEN\
+ + TUD_AUDIO20_DESC_STD_AS_LEN\
/* Interface 1, Alternate 1 */\
- + TUD_AUDIO_DESC_STD_AS_INT_LEN\
- + TUD_AUDIO_DESC_CS_AS_INT_LEN\
- + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\
- + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\
- + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\
+ + TUD_AUDIO20_DESC_STD_AS_LEN\
+ + TUD_AUDIO20_DESC_CS_AS_INT_LEN\
+ + TUD_AUDIO20_DESC_TYPE_I_FORMAT_LEN\
+ + TUD_AUDIO20_DESC_STD_AS_ISO_EP_LEN\
+ + TUD_AUDIO20_DESC_CS_AS_ISO_EP_LEN\
/* Interface 1, Alternate 2 */\
- + TUD_AUDIO_DESC_STD_AS_INT_LEN\
- + TUD_AUDIO_DESC_CS_AS_INT_LEN\
- + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\
- + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\
- + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN)
+ + TUD_AUDIO20_DESC_STD_AS_LEN\
+ + TUD_AUDIO20_DESC_CS_AS_INT_LEN\
+ + TUD_AUDIO20_DESC_TYPE_I_FORMAT_LEN\
+ + TUD_AUDIO20_DESC_STD_AS_ISO_EP_LEN\
+ + TUD_AUDIO20_DESC_CS_AS_ISO_EP_LEN)
-#define TUD_AUDIO_MIC_ONE_CH_2_FORMAT_DESCRIPTOR(_itfnum, _stridx, _epin) \
+#define TUD_AUDIO20_MIC_ONE_CH_2_FORMAT_DESCRIPTOR(_itfnum, _stridx, _epin) \
/* Standard Interface Association Descriptor (IAD) */\
- TUD_AUDIO_DESC_IAD(/*_firstitf*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\
+ TUD_AUDIO20_DESC_IAD(/*_firstitf*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\
/* Standard AC Interface Descriptor(4.7.1) */\
- TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\
+ TUD_AUDIO20_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\
/* Class-Specific AC Interface Header Descriptor(4.7.2) */\
- TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_MICROPHONE, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\
+ TUD_AUDIO20_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO20_FUNC_MICROPHONE, /*_totallen*/ TUD_AUDIO20_DESC_CLK_SRC_LEN+TUD_AUDIO20_DESC_INPUT_TERM_LEN+TUD_AUDIO20_DESC_OUTPUT_TERM_LEN+TUD_AUDIO20_DESC_FEATURE_UNIT_LEN(1), /*_ctrl*/ AUDIO20_CS_AS_INTERFACE_CTRL_LATENCY_POS),\
/* Clock Source Descriptor(4.7.2.1) */\
- TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ UAC2_ENTITY_CLOCK, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_PRO_CLK, /*_ctrl*/ AUDIO_CTRL_RW << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS | AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_VAL_POS, /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\
+ TUD_AUDIO20_DESC_CLK_SRC(/*_clkid*/ UAC2_ENTITY_CLOCK, /*_attr*/ AUDIO20_CLOCK_SOURCE_ATT_INT_PRO_CLK, /*_ctrl*/ AUDIO20_CTRL_RW << AUDIO20_CLOCK_SOURCE_CTRL_CLK_FRQ_POS | AUDIO20_CTRL_R << AUDIO20_CLOCK_SOURCE_CTRL_CLK_VAL_POS, /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\
/* Input Terminal Descriptor(4.7.2.4) */\
- TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ UAC2_ENTITY_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ UAC2_ENTITY_OUTPUT_TERMINAL, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS, /*_stridx*/ 0x00),\
+ TUD_AUDIO20_DESC_INPUT_TERM(/*_termid*/ UAC2_ENTITY_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ UAC2_ENTITY_OUTPUT_TERMINAL, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ AUDIO20_CTRL_R << AUDIO20_IN_TERM_CTRL_CONNECTOR_POS, /*_stridx*/ 0x00),\
/* Output Terminal Descriptor(4.7.2.5) */\
- TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ UAC2_ENTITY_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ UAC2_ENTITY_INPUT_TERMINAL, /*_srcid*/ UAC2_ENTITY_FEATURE_UNIT, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\
+ TUD_AUDIO20_DESC_OUTPUT_TERM(/*_termid*/ UAC2_ENTITY_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ UAC2_ENTITY_INPUT_TERMINAL, /*_srcid*/ UAC2_ENTITY_FEATURE_UNIT, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\
/* Feature Unit Descriptor(4.7.2.8) */\
- TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ UAC2_ENTITY_FEATURE_UNIT, /*_srcid*/ 0x01, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_stridx*/ 0x00),\
+ TUD_AUDIO20_DESC_FEATURE_UNIT(/*_unitid*/ UAC2_ENTITY_FEATURE_UNIT, /*_srcid*/ 0x01, /*_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),\
/* Standard AS Interface Descriptor(4.9.1) */\
/* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\
- TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\
+ TUD_AUDIO20_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\
/* Standard AS Interface Descriptor(4.9.1) */\
/* Interface 1, Alternate 1 - alternate interface for data streaming */\
- TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\
+ TUD_AUDIO20_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\
/* Class-Specific AS Interface Descriptor(4.9.2) */\
- TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_OUTPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\
+ TUD_AUDIO20_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_OUTPUT_TERMINAL, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_formattype*/ AUDIO20_FORMAT_TYPE_I, /*_formats*/ AUDIO20_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\
/* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\
- TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_RX),\
+ TUD_AUDIO20_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_RX),\
/* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\
- TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN, /*_interval*/ 0x01),\
+ TUD_AUDIO20_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ CFG_TUD_AUDIO20_FUNC_1_FORMAT_1_EP_SZ_IN, /*_interval*/ 0x01),\
/* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\
- TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\
+ 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),\
/* Interface 1, Alternate 2 - alternate interface for data streaming */\
- TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x02, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\
+ TUD_AUDIO20_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x02, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\
/* Class-Specific AS Interface Descriptor(4.9.2) */\
- TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_OUTPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\
+ TUD_AUDIO20_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_OUTPUT_TERMINAL, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_formattype*/ AUDIO20_FORMAT_TYPE_I, /*_formats*/ AUDIO20_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\
/* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\
- TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_RX),\
+ TUD_AUDIO20_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_RX),\
/* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\
- TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN, /*_interval*/ 0x01),\
+ TUD_AUDIO20_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ CFG_TUD_AUDIO20_FUNC_1_FORMAT_2_EP_SZ_IN, /*_interval*/ 0x01),\
/* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\
- TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000)
+ 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)
#endif