summaryrefslogtreecommitdiff
path: root/examples/device/uac2_speaker_fb
diff options
context:
space:
mode:
authorHiFiPhile <[email protected]>2026-06-23 23:12:51 +0200
committerHiFiPhile <[email protected]>2026-06-23 23:12:51 +0200
commit033dc6bb77e8a9e1c1172d74d47707848b5c5bf5 (patch)
treee7672f9bda54aa1a243b2a1c0f74a48055569c63 /examples/device/uac2_speaker_fb
parentb5e63ca44c846813ece9ad9df684cae0d1d5b542 (diff)
parentcd3561bf158afd5a5718904b8139a338d1e3b67c (diff)
Merge remote-tracking branch 'tinyusb/master' into fix-stm32-usbc
Diffstat (limited to 'examples/device/uac2_speaker_fb')
-rw-r--r--examples/device/uac2_speaker_fb/skip.txt1
-rw-r--r--examples/device/uac2_speaker_fb/src/main.c132
-rw-r--r--examples/device/uac2_speaker_fb/src/usb_descriptors.c15
3 files changed, 80 insertions, 68 deletions
diff --git a/examples/device/uac2_speaker_fb/skip.txt b/examples/device/uac2_speaker_fb/skip.txt
index 234f1ebed..0c7339c65 100644
--- a/examples/device/uac2_speaker_fb/skip.txt
+++ b/examples/device/uac2_speaker_fb/skip.txt
@@ -6,3 +6,4 @@ mcu:SAME5X
mcu:SAMG
board:stm32l052dap52
family:broadcom_64bit
+mcu:CH583
diff --git a/examples/device/uac2_speaker_fb/src/main.c b/examples/device/uac2_speaker_fb/src/main.c
index c3e97bb28..7e4d27f1c 100644
--- a/examples/device/uac2_speaker_fb/src/main.c
+++ b/examples/device/uac2_speaker_fb/src/main.c
@@ -315,16 +315,16 @@ const uint32_t sample_rates[] = {44100, 48000, 88200, 96000};
#define N_SAMPLE_RATES TU_ARRAY_SIZE(sample_rates)
-static bool audio20_clock_get_request(uint8_t rhport, audio20_control_request_t const *request) {
- TU_ASSERT(request->bEntityID == UAC2_ENTITY_CLOCK);
+static bool audio20_clock_get_request(uint8_t rhport, tusb_control_request_t const *p_request) {
+ uint8_t const ctrl_sel = TU_U16_HIGH(p_request->wValue);
- if (request->bControlSelector == AUDIO20_CS_CTRL_SAM_FREQ) {
- if (request->bRequest == AUDIO20_CS_REQ_CUR) {
+ if (ctrl_sel == AUDIO20_CS_CTRL_SAM_FREQ) {
+ if (p_request->bRequest == AUDIO20_CS_REQ_CUR) {
TU_LOG1("Clock get current freq %" PRIu32 "\r\n", current_sample_rate);
audio20_control_cur_4_t curf = {(int32_t) tu_htole32(current_sample_rate)};
- return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &curf, sizeof(curf));
- } else if (request->bRequest == AUDIO20_CS_REQ_RANGE) {
+ return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &curf, sizeof(curf));
+ } else if (p_request->bRequest == AUDIO20_CS_REQ_RANGE) {
audio20_control_range_4_n_t(N_SAMPLE_RATES) rangef =
{
.wNumSubRanges = tu_htole16(N_SAMPLE_RATES)};
@@ -336,25 +336,26 @@ static bool audio20_clock_get_request(uint8_t rhport, audio20_control_request_t
TU_LOG1("Range %d (%d, %d, %d)\r\n", i, (int) rangef.subrange[i].bMin, (int) rangef.subrange[i].bMax, (int) rangef.subrange[i].bRes);
}
- return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &rangef, sizeof(rangef));
+ return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &rangef, sizeof(rangef));
}
- } else if (request->bControlSelector == AUDIO20_CS_CTRL_CLK_VALID &&
- request->bRequest == AUDIO20_CS_REQ_CUR) {
+ } else if (ctrl_sel == AUDIO20_CS_CTRL_CLK_VALID &&
+ p_request->bRequest == AUDIO20_CS_REQ_CUR) {
audio20_control_cur_1_t cur_valid = {.bCur = 1};
TU_LOG1("Clock get is valid %u\r\n", cur_valid.bCur);
- return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &cur_valid, sizeof(cur_valid));
+ return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &cur_valid, sizeof(cur_valid));
}
- TU_LOG1("Clock get request not supported, entity = %u, selector = %u, request = %u\r\n",
- request->bEntityID, request->bControlSelector, request->bRequest);
+ TU_LOG1("Clock get request not supported, selector = %u, request = %u\r\n",
+ ctrl_sel, p_request->bRequest);
return false;
}
-static bool audio20_clock_set_request(audio20_control_request_t const *request, uint8_t const *buf) {
- TU_ASSERT(request->bEntityID == UAC2_ENTITY_CLOCK);
- TU_VERIFY(request->bRequest == AUDIO20_CS_REQ_CUR);
+static bool audio20_clock_set_request(tusb_control_request_t const *p_request, uint8_t const *buf) {
+ uint8_t const ctrl_sel = TU_U16_HIGH(p_request->wValue);
- if (request->bControlSelector == AUDIO20_CS_CTRL_SAM_FREQ) {
- TU_VERIFY(request->wLength == sizeof(audio20_control_cur_4_t));
+ TU_VERIFY(p_request->bRequest == AUDIO20_CS_REQ_CUR);
+
+ if (ctrl_sel == AUDIO20_CS_CTRL_SAM_FREQ) {
+ TU_VERIFY(p_request->wLength == sizeof(audio20_control_cur_4_t));
current_sample_rate = (uint32_t) ((audio20_control_cur_4_t const *) buf)->bCur;
@@ -362,89 +363,92 @@ static bool audio20_clock_set_request(audio20_control_request_t const *request,
return true;
} else {
- TU_LOG1("Clock set request not supported, entity = %u, selector = %u, request = %u\r\n",
- request->bEntityID, request->bControlSelector, request->bRequest);
+ TU_LOG1("Clock set request not supported, selector = %u, request = %u\r\n",
+ ctrl_sel, p_request->bRequest);
return false;
}
}
-static bool audio20_feature_unit_get_request(uint8_t rhport, audio20_control_request_t const *request) {
- TU_ASSERT(request->bEntityID == UAC2_ENTITY_FEATURE_UNIT);
+static bool audio20_feature_unit_get_request(uint8_t rhport, tusb_control_request_t const *p_request) {
+ uint8_t const ctrl_sel = TU_U16_HIGH(p_request->wValue);
+ uint8_t const channel_num = TU_U16_LOW(p_request->wValue);
- if (request->bControlSelector == AUDIO20_FU_CTRL_MUTE && request->bRequest == AUDIO20_CS_REQ_CUR) {
- audio20_control_cur_1_t mute1 = {.bCur = mute[request->bChannelNumber]};
- TU_LOG1("Get channel %u mute %d\r\n", request->bChannelNumber, mute1.bCur);
- return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &mute1, sizeof(mute1));
- } else if (request->bControlSelector == AUDIO20_FU_CTRL_VOLUME) {
- if (request->bRequest == AUDIO20_CS_REQ_RANGE) {
+ if (ctrl_sel == AUDIO20_FU_CTRL_MUTE && p_request->bRequest == AUDIO20_CS_REQ_CUR) {
+ audio20_control_cur_1_t mute1 = {.bCur = mute[channel_num]};
+ TU_LOG1("Get channel %u mute %d\r\n", channel_num, mute1.bCur);
+ return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &mute1, sizeof(mute1));
+ } else if (ctrl_sel == AUDIO20_FU_CTRL_VOLUME) {
+ if (p_request->bRequest == AUDIO20_CS_REQ_RANGE) {
audio20_control_range_2_n_t(1) range_vol = {
.wNumSubRanges = tu_htole16(1),
.subrange[0] = {.bMin = tu_htole16(-VOLUME_CTRL_50_DB), tu_htole16(VOLUME_CTRL_0_DB), tu_htole16(256)}};
- TU_LOG1("Get channel %u volume range (%d, %d, %u) dB\r\n", request->bChannelNumber,
+ TU_LOG1("Get channel %u volume range (%d, %d, %u) dB\r\n", channel_num,
range_vol.subrange[0].bMin / 256, range_vol.subrange[0].bMax / 256, range_vol.subrange[0].bRes / 256);
- return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &range_vol, sizeof(range_vol));
- } else if (request->bRequest == AUDIO20_CS_REQ_CUR) {
- audio20_control_cur_2_t cur_vol = {.bCur = tu_htole16(volume[request->bChannelNumber])};
- TU_LOG1("Get channel %u volume %d dB\r\n", request->bChannelNumber, cur_vol.bCur / 256);
- return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &cur_vol, sizeof(cur_vol));
+ return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &range_vol, sizeof(range_vol));
+ } else if (p_request->bRequest == AUDIO20_CS_REQ_CUR) {
+ audio20_control_cur_2_t cur_vol = {.bCur = tu_htole16(volume[channel_num])};
+ TU_LOG1("Get channel %u volume %d dB\r\n", channel_num, cur_vol.bCur / 256);
+ return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &cur_vol, sizeof(cur_vol));
}
}
- TU_LOG1("Feature unit get request not supported, entity = %u, selector = %u, request = %u\r\n",
- request->bEntityID, request->bControlSelector, request->bRequest);
+ TU_LOG1("Feature unit get request not supported, selector = %u, request = %u\r\n",
+ ctrl_sel, p_request->bRequest);
return false;
}
-static bool audio20_feature_unit_set_request(audio20_control_request_t const *request, uint8_t const *buf) {
- TU_ASSERT(request->bEntityID == UAC2_ENTITY_FEATURE_UNIT);
- TU_VERIFY(request->bRequest == AUDIO20_CS_REQ_CUR);
+static bool audio20_feature_unit_set_request(tusb_control_request_t const *p_request, uint8_t const *buf) {
+ uint8_t const ctrl_sel = TU_U16_HIGH(p_request->wValue);
+ uint8_t const channel_num = TU_U16_LOW(p_request->wValue);
+
+ TU_VERIFY(p_request->bRequest == AUDIO20_CS_REQ_CUR);
- if (request->bControlSelector == AUDIO20_FU_CTRL_MUTE) {
- TU_VERIFY(request->wLength == sizeof(audio20_control_cur_1_t));
+ if (ctrl_sel == AUDIO20_FU_CTRL_MUTE) {
+ TU_VERIFY(p_request->wLength == sizeof(audio20_control_cur_1_t));
- mute[request->bChannelNumber] = ((audio20_control_cur_1_t const *) buf)->bCur;
+ mute[channel_num] = ((audio20_control_cur_1_t const *) buf)->bCur;
- TU_LOG1("Set channel %d Mute: %d\r\n", request->bChannelNumber, mute[request->bChannelNumber]);
+ TU_LOG1("Set channel %d Mute: %d\r\n", channel_num, mute[channel_num]);
return true;
- } else if (request->bControlSelector == AUDIO20_FU_CTRL_VOLUME) {
- TU_VERIFY(request->wLength == sizeof(audio20_control_cur_2_t));
+ } else if (ctrl_sel == AUDIO20_FU_CTRL_VOLUME) {
+ TU_VERIFY(p_request->wLength == sizeof(audio20_control_cur_2_t));
- volume[request->bChannelNumber] = ((audio20_control_cur_2_t const *) buf)->bCur;
+ volume[channel_num] = ((audio20_control_cur_2_t const *) buf)->bCur;
- TU_LOG1("Set channel %d volume: %d dB\r\n", request->bChannelNumber, volume[request->bChannelNumber] / 256);
+ TU_LOG1("Set channel %d volume: %d dB\r\n", channel_num, volume[channel_num] / 256);
return true;
} else {
- TU_LOG1("Feature unit set request not supported, entity = %u, selector = %u, request = %u\r\n",
- request->bEntityID, request->bControlSelector, request->bRequest);
+ TU_LOG1("Feature unit set request not supported, selector = %u, request = %u\r\n",
+ ctrl_sel, p_request->bRequest);
return false;
}
}
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;
+ uint8_t const entity_id = TU_U16_HIGH(p_request->wIndex);
- if (request->bEntityID == UAC2_ENTITY_CLOCK)
- return audio20_clock_get_request(rhport, request);
- if (request->bEntityID == UAC2_ENTITY_FEATURE_UNIT)
- return audio20_feature_unit_get_request(rhport, request);
+ if (entity_id == UAC2_ENTITY_CLOCK)
+ return audio20_clock_get_request(rhport, p_request);
+ if (entity_id == UAC2_ENTITY_FEATURE_UNIT)
+ return audio20_feature_unit_get_request(rhport, p_request);
else {
TU_LOG1("Get request not handled, entity = %d, selector = %d, request = %d\r\n",
- request->bEntityID, request->bControlSelector, request->bRequest);
+ entity_id, TU_U16_HIGH(p_request->wValue), p_request->bRequest);
}
return false;
}
static bool audio20_set_req_entity(tusb_control_request_t const *p_request, uint8_t *buf) {
- audio20_control_request_t const *request = (audio20_control_request_t const *) p_request;
+ uint8_t const entity_id = TU_U16_HIGH(p_request->wIndex);
- if (request->bEntityID == UAC2_ENTITY_FEATURE_UNIT)
- return audio20_feature_unit_set_request(request, buf);
- if (request->bEntityID == UAC2_ENTITY_CLOCK)
- return audio20_clock_set_request(request, buf);
+ if (entity_id == UAC2_ENTITY_FEATURE_UNIT)
+ return audio20_feature_unit_set_request(p_request, buf);
+ if (entity_id == UAC2_ENTITY_CLOCK)
+ return audio20_clock_set_request(p_request, buf);
TU_LOG1("Set request not handled, entity = %d, selector = %d, request = %d\r\n",
- request->bEntityID, request->bControlSelector, request->bRequest);
+ entity_id, TU_U16_HIGH(p_request->wValue), p_request->bRequest);
return false;
}
@@ -457,8 +461,8 @@ static bool audio20_set_req_entity(tusb_control_request_t const *p_request, uint
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));
+ uint8_t const itf = tu_u16_low(p_request->wIndex);
+ uint8_t const alt = tu_u16_low(p_request->wValue);
TU_LOG2("Set interface %d alt %d\r\n", itf, alt);
if (ITF_NUM_AUDIO_STREAMING == itf && alt != 0)
@@ -531,8 +535,8 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p
bool tud_audio_set_itf_close_ep_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));
+ uint8_t const itf = tu_u16_low(p_request->wIndex);
+ uint8_t const alt = tu_u16_low(p_request->wValue);
if (ITF_NUM_AUDIO_STREAMING == itf && alt == 0) {
blink_interval_ms = BLINK_MOUNTED;
diff --git a/examples/device/uac2_speaker_fb/src/usb_descriptors.c b/examples/device/uac2_speaker_fb/src/usb_descriptors.c
index c5a161a1e..f0c780e38 100644
--- a/examples/device/uac2_speaker_fb/src/usb_descriptors.c
+++ b/examples/device/uac2_speaker_fb/src/usb_descriptors.c
@@ -115,12 +115,19 @@ uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf) {
#define EPNUM_AUDIO_FB 0x08
#define EPNUM_DEBUG 0x01
-#elif defined(TUD_ENDPOINT_ONE_DIRECTION_ONLY)
+#elif CFG_TUD_ENDPOINT_ONE_DIRECTION_ONLY
// MCUs that don't support a same endpoint number with different direction IN and OUT defined in tusb_mcu.h
// e.g EP1 OUT & EP1 IN cannot exist together
- #define EPNUM_AUDIO 0x02
- #define EPNUM_AUDIO_FB 0x01
- #define EPNUM_DEBUG 0x03
+ #if TU_CHECK_MCU(OPT_MCU_MAX32650, OPT_MCU_MAX32666, OPT_MCU_MAX32690, OPT_MCU_MAX78002)
+ // Put audio iso on EP10/11 so the 4096-byte FIFOs can back double packet buffering
+ #define EPNUM_AUDIO 0x0A
+ #define EPNUM_AUDIO_FB 0x0B
+ #define EPNUM_DEBUG 0x01
+ #else
+ #define EPNUM_AUDIO 0x02
+ #define EPNUM_AUDIO_FB 0x01
+ #define EPNUM_DEBUG 0x03
+ #endif
#else
#define EPNUM_AUDIO 0x01