You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by je...@apache.org on 2026/10/12 09:39:27 UTC
(mynewt-core) branch master updated (b0811ad5b -> 8253df5ed)
This is an automated email from the ASF dual-hosted git repository.
kasjer pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
from b0811ad5b mcu/stm32h5: Fix pin definitions
new 0ee2be5d7 tinyusb: Update TinyUSB from 0.18.0 to 0.21.0
new 567628552 tinyusb/std_descriptors: Add USB Audio Class 2.0 function
new e6af8f439 apps/usb_headset: Add USB Audio Class 2.0 headset example
new 8e56daa56 tinyusb: Move audio endpoint defaults to port tusb_hw.h
new 6e5cca39a tinyusb/nrf5x: Enable nrfx CLOCK driver required by TinyUSB
new 8253df5ed ci: Set placeholder VID/PID for usb_headset app build
The 6 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.github/test_build_apps.sh | 9 +
apps/{rust_blinky => usb_headset}/pkg.yml | 18 +-
apps/usb_headset/src/main.c | 123 +++++++
apps/usb_headset/src/usb_audio.c | 345 ++++++++++++++++++
apps/usb_headset/src/usb_headset.h | 71 ++++
apps/usb_headset/syscfg.yml | 48 +++
hw/usb/tinyusb/da146xx/include/tusb_hw.h | 23 ++
hw/usb/tinyusb/lpc55/include/tusb_hw.h | 22 ++
hw/usb/tinyusb/nrf53/include/tusb_hw.h | 23 ++
hw/usb/tinyusb/nrf5x/include/tusb_hw.h | 23 ++
.../usb/tinyusb/nrf5x}/syscfg.yml | 4 +-
hw/usb/tinyusb/pic32mz/include/tusb_hw.h | 22 ++
.../tinyusb/std_descriptors/include/tusb_config.h | 82 +++++
.../std_descriptors/include/usbd_audio_desc.h | 398 +++++++++++++++++++++
.../tinyusb/std_descriptors/src/std_descriptors.c | 34 +-
hw/usb/tinyusb/std_descriptors/syscfg.yml | 114 ++++++
hw/usb/tinyusb/stm32_fsdev/include/tusb_hw.h | 22 ++
.../tinyusb/stm32_fsdev/stm32f3/include/tusb_hw.h | 22 ++
.../tinyusb/stm32_fsdev/stm32g0/include/tusb_hw.h | 22 ++
.../tinyusb/stm32_fsdev/stm32g4/include/tusb_hw.h | 22 ++
.../tinyusb/stm32_fsdev/stm32h5/include/tusb_hw.h | 22 ++
.../tinyusb/stm32_fsdev/stm32l0/include/tusb_hw.h | 22 ++
.../stm32_fsdev/stm32wb55/include/tusb_hw.h | 22 ++
hw/usb/tinyusb/synopsys/include/tusb_hw.h | 24 ++
hw/usb/tinyusb/tinyusb_sdk/pkg.yml | 2 +-
25 files changed, 1530 insertions(+), 9 deletions(-)
copy apps/{rust_blinky => usb_headset}/pkg.yml (69%)
create mode 100644 apps/usb_headset/src/main.c
create mode 100644 apps/usb_headset/src/usb_audio.c
create mode 100644 apps/usb_headset/src/usb_headset.h
create mode 100644 apps/usb_headset/syscfg.yml
copy {.github/targets/nordic_pca10095_btshell => hw/usb/tinyusb/nrf5x}/syscfg.yml (84%)
create mode 100644 hw/usb/tinyusb/std_descriptors/include/usbd_audio_desc.h
(mynewt-core) 06/06: ci: Set placeholder VID/PID for usb_headset app build
Posted by je...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
kasjer pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 8253df5ed050afa0d2947215aeea29fa6769e23c
Author: Jerzy Kasenberg <je...@codecoup.pl>
AuthorDate: Fri Oct 9 10:22:23 2026 +0200
ci: Set placeholder VID/PID for usb_headset app build
apps/usb_headset deliberately leaves USBD_VID and USBD_PID to the
target, so nobody ships the example with a made up pair. The "Build
all apps" job creates its own targets and failed on the std_descriptors
restriction that both must be set.
Add a per-app syscfg table to test_build_apps.sh and give usb_headset
the obviously fake 0xFFFF/0xFFFF for the build check only.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Jerzy Kasenberg <je...@codecoup.pl>
---
.github/test_build_apps.sh | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/.github/test_build_apps.sh b/.github/test_build_apps.sh
index 9a3e3152a..bacdecd10 100755
--- a/.github/test_build_apps.sh
+++ b/.github/test_build_apps.sh
@@ -25,6 +25,12 @@ APPS=$(basename -a `ls -d repos/apache-mynewt-core/apps/*/`)
IGNORED_APPS="ffs2native fs_test hash_test lora_app_shell loraping lorashell\
pwm_test rust_blinky lvgl_demo"
+# Apps that deliberately leave some settings to the target. Values used
+# here are placeholders good enough for a build check.
+declare -A APP_SYSCFG=(
+ [usb_headset]="USBD_VID=0xFFFF:USBD_PID=0xFFFF"
+)
+
for app in ${APPS}; do
# NOTE: do not remove the spaces around IGNORED_APPS; it's required to
# match against the first and last entries
@@ -42,6 +48,9 @@ for app in ${APPS}; do
newt target create -s $target
newt target set -s $target bsp="@apache-mynewt-core/hw/bsp/nordic_pca10056"
newt target set -s $target app="@apache-mynewt-core/apps/$app"
+ if [[ -n "${APP_SYSCFG[$app]}" ]]; then
+ newt target set -s $target syscfg="${APP_SYSCFG[$app]}"
+ fi
newt build -q $target
rc=$?
(mynewt-core) 01/06: tinyusb: Update TinyUSB from 0.18.0 to 0.21.0
Posted by je...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
kasjer pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 0ee2be5d736ee6d9a1822357388cd059dcc89d04
Author: Jerzy Kasenberg <je...@codecoup.pl>
AuthorDate: Fri Oct 9 10:48:10 2026 +0200
tinyusb: Update TinyUSB from 0.18.0 to 0.21.0
USB Audio Class 2.0 support in std_descriptors and apps/usb_headset
use the audio API as renamed in TinyUSB 0.20.0 (TUD_AUDIO20_*,
audio20_* types) and no longer provide the CFG_TUD_AUDIO_FUNC_1_*
descriptor length and interface count macros that older releases
demanded. CI building with 0.18.0 failed on exactly those macros.
Only apps/usb_headset in core pulls in TinyUSB, no BSP or bootloader
does, and the nRF5x port already enables the nrfx CLOCK driver that
the 0.21.0 device driver needs.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Jerzy Kasenberg <je...@codecoup.pl>
---
hw/usb/tinyusb/tinyusb_sdk/pkg.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/usb/tinyusb/tinyusb_sdk/pkg.yml b/hw/usb/tinyusb/tinyusb_sdk/pkg.yml
index e80809a85..2458f2aa9 100644
--- a/hw/usb/tinyusb/tinyusb_sdk/pkg.yml
+++ b/hw/usb/tinyusb/tinyusb_sdk/pkg.yml
@@ -41,6 +41,6 @@ pkg.source_dirs:
repository.tinyusb:
type: github
branch: master
- vers: 0.18.0-commit
+ vers: 0.21.0-commit
user: hathach
repo: tinyusb
(mynewt-core) 03/06: apps/usb_headset: Add USB Audio Class 2.0 headset example
Posted by je...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
kasjer pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit e6af8f43941bc8bb868d63c546abf0338f01711e
Author: Jerzy Kasenberg <je...@codecoup.pl>
AuthorDate: Wed Oct 7 14:55:12 2026 +0200
apps/usb_headset: Add USB Audio Class 2.0 headset example
Headset with stereo speaker and mono microphone, 48 kHz 16-bit PCM,
built on tinyusb/std_descriptors audio support. Stereo data received
on the speaker endpoint is mixed to mono and sent back on the
microphone endpoint, so the function can be tested without any audio
hardware.
Clock source, speaker and microphone feature unit requests are
handled in usb_audio.c. Master mute and volume of both feature units
are applied as a Q15 gain to the mixed signal. Streaming interface
numbers are found by walking the configuration descriptor, so the
application keeps working when a target adds a CDC console in front
of the audio function.
Speaker endpoint is adaptive (no feedback endpoint). VID, PID and
strings are left to the target.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Jerzy Kasenberg <je...@codecoup.pl>
---
apps/usb_headset/pkg.yml | 43 +++++
apps/usb_headset/src/main.c | 123 +++++++++++++
apps/usb_headset/src/usb_audio.c | 345 +++++++++++++++++++++++++++++++++++++
apps/usb_headset/src/usb_headset.h | 71 ++++++++
apps/usb_headset/syscfg.yml | 48 ++++++
5 files changed, 630 insertions(+)
diff --git a/apps/usb_headset/pkg.yml b/apps/usb_headset/pkg.yml
new file mode 100644
index 000000000..3e448b560
--- /dev/null
+++ b/apps/usb_headset/pkg.yml
@@ -0,0 +1,43 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+pkg.name: apps/usb_headset
+pkg.type: app
+pkg.description: >
+ USB Audio Class 2.0 headset example. Stereo audio received from host
+ (speaker) is mixed to mono and sent back to host (microphone).
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+ - usb
+ - audio
+ - uac2
+ - headset
+
+# Application overrides weak TinyUSB audio callbacks, make sure its objects
+# are always linked in.
+pkg.whole_archive: true
+
+pkg.deps:
+ - "@apache-mynewt-core/kernel/os"
+ - "@apache-mynewt-core/hw/hal"
+ - "@apache-mynewt-core/sys/console"
+ - "@apache-mynewt-core/sys/log"
+ - "@apache-mynewt-core/hw/usb/tinyusb"
+ - "@apache-mynewt-core/hw/usb/tinyusb/std_descriptors"
diff --git a/apps/usb_headset/src/main.c b/apps/usb_headset/src/main.c
new file mode 100644
index 000000000..5086c9b54
--- /dev/null
+++ b/apps/usb_headset/src/main.c
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * USB headset example: stereo samples received from host on speaker
+ * endpoint are mixed to mono and sent back to host on microphone endpoint.
+ */
+
+#include <string.h>
+#include <os/mynewt.h>
+#include <console/console.h>
+#include <tusb.h>
+#include <class/audio/audio_device.h>
+#include <tinyusb/tinyusb.h>
+
+#include "usb_headset.h"
+
+#if USBD_AUDIO_BYTES_PER_SAMPLE != 2
+#error This application mixes 16 bit samples only
+#endif
+#if USBD_AUDIO_OUT_CHANNELS != 2 || USBD_AUDIO_IN_CHANNELS != 1
+#error This application mixes stereo speaker to mono microphone only
+#endif
+
+/* Speaker frame: one sample for each channel. */
+#define FRAME_BYTES (USBD_AUDIO_BYTES_PER_SAMPLE * USBD_AUDIO_OUT_CHANNELS)
+/* Process up to 2 ms of audio at a time. */
+#define CHUNK_FRAMES (2 * (USBD_AUDIO_SAMPLE_RATE / 1000))
+
+static int16_t spk_buf[CHUNK_FRAMES * USBD_AUDIO_OUT_CHANNELS];
+static int16_t mic_buf[CHUNK_FRAMES];
+
+static void pump_ev_cb(struct os_event *ev);
+
+static struct os_event pump_ev = {
+ .ev_cb = pump_ev_cb,
+};
+
+void
+usb_headset_data_ready(void)
+{
+ if (!OS_EVENT_QUEUED(&pump_ev)) {
+ os_eventq_put(os_eventq_dflt_get(), &pump_ev);
+ }
+}
+
+/*
+ * Mix left and right channel to mono applying master gain.
+ * (left + right) * gain_q15 >> 16 averages two channels and scales
+ * them in one step; values fit in 32 bits for full scale input.
+ */
+static void
+mix_to_mono(const int16_t *stereo, int16_t *mono, uint16_t frames,
+ int32_t gain)
+{
+ uint16_t i;
+ int32_t sum;
+
+ for (i = 0; i < frames; ++i) {
+ sum = (int32_t)stereo[2 * i] + stereo[2 * i + 1];
+ mono[i] = (int16_t)((sum * gain) >> 16);
+ }
+}
+
+static void
+pump_ev_cb(struct os_event *ev)
+{
+ uint16_t available;
+ uint16_t bytes;
+ uint16_t frames;
+
+ (void)ev;
+
+ while ((available = tud_audio_available()) >= FRAME_BYTES) {
+ bytes = min(available, sizeof(spk_buf));
+ bytes -= bytes % FRAME_BYTES;
+ bytes = tud_audio_read(spk_buf, bytes);
+ frames = bytes / FRAME_BYTES;
+
+ mix_to_mono(spk_buf, mic_buf, frames, usb_headset.gain_q15);
+
+ /* Microphone FIFO is only consumed when host streams from it. */
+ if (usb_headset.mic_alt != 0) {
+ tud_audio_write(mic_buf, frames * sizeof(mic_buf[0]));
+ }
+ }
+}
+
+int
+mynewt_main(int argc, char **argv)
+{
+ (void)argc;
+ (void)argv;
+
+ sysinit();
+
+ usb_audio_init();
+ tinyusb_start();
+
+ console_printf("USB headset started\n");
+
+ while (1) {
+ os_eventq_run(os_eventq_dflt_get());
+ }
+
+ return 0;
+}
diff --git a/apps/usb_headset/src/usb_audio.c b/apps/usb_headset/src/usb_audio.c
new file mode 100644
index 000000000..9248643e3
--- /dev/null
+++ b/apps/usb_headset/src/usb_audio.c
@@ -0,0 +1,345 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * TinyUSB audio class callbacks: clock source and feature unit requests,
+ * alternate setting tracking and speaker data notification.
+ * Descriptors come from hw/usb/tinyusb/std_descriptors.
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <syscfg/syscfg.h>
+#include <os/mynewt.h>
+#include <tusb.h>
+#include <class/audio/audio_device.h>
+#include <usbd_audio_desc.h>
+
+#include "usb_headset.h"
+
+struct usb_headset usb_headset;
+
+/* Q15 gain for 0, -1, ... -5 dB; every further 6 dB halves the value. */
+static const uint16_t gain_q15_table[6] = {
+ 32768, 29205, 26029, 23198, 20675, 18427
+};
+
+static uint16_t
+db_to_gain_q15(int db)
+{
+ int attenuation = -db;
+
+ if (attenuation < 0) {
+ attenuation = 0;
+ }
+
+ return gain_q15_table[attenuation % 6] >> (attenuation / 6);
+}
+
+/*
+ * Only master channel controls of both feature units are applied to the
+ * mixed signal. Per channel values are stored and reported back to host.
+ */
+static void
+update_gain(void)
+{
+ uint32_t gain;
+
+ if (usb_headset.spk.mute[0] || usb_headset.mic.mute[0]) {
+ gain = 0;
+ } else {
+ gain = db_to_gain_q15(usb_headset.spk.volume[0] / 256);
+ gain = (gain * db_to_gain_q15(usb_headset.mic.volume[0] / 256)) >> 15;
+ }
+
+ usb_headset.gain_q15 = (uint16_t)gain;
+}
+
+static bool
+clock_get(uint8_t rhport, const tusb_control_request_t *req)
+{
+ uint8_t selector = TU_U16_HIGH(req->wValue);
+ audio20_control_cur_4_t cur_freq;
+ audio20_control_range_4_n_t(1) range_freq;
+ audio20_control_cur_1_t cur_valid;
+
+ if (selector == AUDIO20_CS_CTRL_SAM_FREQ) {
+ if (req->bRequest == AUDIO20_CS_REQ_CUR) {
+ cur_freq.bCur = (int32_t)tu_htole32(USBD_AUDIO_SAMPLE_RATE);
+ return tud_audio_buffer_and_schedule_control_xfer(
+ rhport, req, &cur_freq, sizeof(cur_freq));
+ } else if (req->bRequest == AUDIO20_CS_REQ_RANGE) {
+ /*
+ * Host may first ask for 2 bytes to learn number of subranges,
+ * TinyUSB truncates reply to wLength.
+ */
+ range_freq.wNumSubRanges = tu_htole16(1);
+ range_freq.subrange[0].bMin = (int32_t)tu_htole32(USBD_AUDIO_SAMPLE_RATE);
+ range_freq.subrange[0].bMax = (int32_t)tu_htole32(USBD_AUDIO_SAMPLE_RATE);
+ range_freq.subrange[0].bRes = 0;
+ return tud_audio_buffer_and_schedule_control_xfer(
+ rhport, req, &range_freq, sizeof(range_freq));
+ }
+ } else if (selector == AUDIO20_CS_CTRL_CLK_VALID &&
+ req->bRequest == AUDIO20_CS_REQ_CUR) {
+ cur_valid.bCur = 1;
+ return tud_audio_buffer_and_schedule_control_xfer(rhport, req, &cur_valid,
+ sizeof(cur_valid));
+ }
+
+ return false;
+}
+
+/*
+ * Clock frequency is read-only in descriptors, accept only request
+ * that does not change it.
+ */
+static bool
+clock_set(const tusb_control_request_t *req, const uint8_t *buf)
+{
+ uint32_t freq;
+
+ if (TU_U16_HIGH(req->wValue) == AUDIO20_CS_CTRL_SAM_FREQ &&
+ req->bRequest == AUDIO20_CS_REQ_CUR &&
+ req->wLength == sizeof(audio20_control_cur_4_t)) {
+ memcpy(&freq, buf, sizeof(freq));
+ return tu_le32toh(freq) == USBD_AUDIO_SAMPLE_RATE;
+ }
+
+ return false;
+}
+
+static bool
+fu_get(uint8_t rhport, const tusb_control_request_t *req,
+ const struct usb_headset_fu *fu, uint8_t channels)
+{
+ uint8_t selector = TU_U16_HIGH(req->wValue);
+ uint8_t channel = TU_U16_LOW(req->wValue);
+ audio20_control_cur_1_t cur_mute;
+ audio20_control_cur_2_t cur_vol;
+ audio20_control_range_2_n_t(1) range_vol;
+
+ if (channel > channels) {
+ return false;
+ }
+
+ if (selector == AUDIO20_FU_CTRL_MUTE && req->bRequest == AUDIO20_CS_REQ_CUR) {
+ cur_mute.bCur = fu->mute[channel];
+ return tud_audio_buffer_and_schedule_control_xfer(rhport, req,
+ &cur_mute,
+ sizeof(cur_mute));
+ } else if (selector == AUDIO20_FU_CTRL_VOLUME) {
+ if (req->bRequest == AUDIO20_CS_REQ_CUR) {
+ cur_vol.bCur = (int16_t)tu_htole16(fu->volume[channel]);
+ return tud_audio_buffer_and_schedule_control_xfer(rhport, req, &cur_vol,
+ sizeof(cur_vol));
+ } else if (req->bRequest == AUDIO20_CS_REQ_RANGE) {
+ range_vol.wNumSubRanges = tu_htole16(1);
+ range_vol.subrange[0].bMin =
+ (int16_t)tu_htole16(USB_HEADSET_VOLUME_MIN_DB * 256);
+ range_vol.subrange[0].bMax =
+ (int16_t)tu_htole16(USB_HEADSET_VOLUME_MAX_DB * 256);
+ range_vol.subrange[0].bRes = tu_htole16(256);
+ return tud_audio_buffer_and_schedule_control_xfer(
+ rhport, req, &range_vol, sizeof(range_vol));
+ }
+ }
+
+ return false;
+}
+
+static bool
+fu_set(const tusb_control_request_t *req, const uint8_t *buf,
+ struct usb_headset_fu *fu, uint8_t channels)
+{
+ uint8_t selector = TU_U16_HIGH(req->wValue);
+ uint8_t channel = TU_U16_LOW(req->wValue);
+ int16_t volume;
+
+ if (channel > channels || req->bRequest != AUDIO20_CS_REQ_CUR) {
+ return false;
+ }
+
+ if (selector == AUDIO20_FU_CTRL_MUTE) {
+ if (req->wLength != sizeof(audio20_control_cur_1_t)) {
+ return false;
+ }
+ fu->mute[channel] = buf[0] != 0;
+ } else if (selector == AUDIO20_FU_CTRL_VOLUME) {
+ if (req->wLength != sizeof(audio20_control_cur_2_t)) {
+ return false;
+ }
+ memcpy(&volume, buf, sizeof(volume));
+ volume = (int16_t)tu_le16toh((uint16_t)volume);
+ if (volume < USB_HEADSET_VOLUME_MIN_DB * 256) {
+ volume = USB_HEADSET_VOLUME_MIN_DB * 256;
+ } else if (volume > USB_HEADSET_VOLUME_MAX_DB * 256) {
+ volume = USB_HEADSET_VOLUME_MAX_DB * 256;
+ }
+ fu->volume[channel] = volume;
+ } else {
+ return false;
+ }
+
+ update_gain();
+
+ return true;
+}
+
+bool
+tud_audio_get_req_entity_cb(uint8_t rhport, const tusb_control_request_t *req)
+{
+ switch (TU_U16_HIGH(req->wIndex)) {
+ case USBD_AUDIO_ENTITY_CLOCK:
+ return clock_get(rhport, req);
+ case USBD_AUDIO_ENTITY_SPK_FEATURE_UNIT:
+ return fu_get(rhport, req, &usb_headset.spk, USBD_AUDIO_OUT_CHANNELS);
+ case USBD_AUDIO_ENTITY_MIC_FEATURE_UNIT:
+ return fu_get(rhport, req, &usb_headset.mic, USBD_AUDIO_IN_CHANNELS);
+ default:
+ /* Not supported request, TinyUSB stalls it. */
+ return false;
+ }
+}
+
+bool
+tud_audio_set_req_entity_cb(uint8_t rhport, const tusb_control_request_t *req,
+ uint8_t *buf)
+{
+ (void)rhport;
+
+ switch (TU_U16_HIGH(req->wIndex)) {
+ case USBD_AUDIO_ENTITY_CLOCK:
+ return clock_set(req, buf);
+ case USBD_AUDIO_ENTITY_SPK_FEATURE_UNIT:
+ return fu_set(req, buf, &usb_headset.spk, USBD_AUDIO_OUT_CHANNELS);
+ case USBD_AUDIO_ENTITY_MIC_FEATURE_UNIT:
+ return fu_set(req, buf, &usb_headset.mic, USBD_AUDIO_IN_CHANNELS);
+ default:
+ return false;
+ }
+}
+
+static void
+set_alt(const tusb_control_request_t *req)
+{
+ uint8_t itf = TU_U16_LOW(req->wIndex);
+ uint8_t alt = TU_U16_LOW(req->wValue);
+
+ if (itf == usb_headset.spk_itf) {
+ usb_headset.spk_alt = alt;
+ } else if (itf == usb_headset.mic_itf) {
+ usb_headset.mic_alt = alt;
+ }
+}
+
+/* Called when streaming alternate setting is selected. */
+bool
+tud_audio_set_itf_cb(uint8_t rhport, const tusb_control_request_t *req)
+{
+ (void)rhport;
+
+ set_alt(req);
+
+ return true;
+}
+
+/* Called when alternate setting 0 (no streaming) is selected. */
+bool
+tud_audio_set_itf_close_ep_cb(uint8_t rhport, const tusb_control_request_t *req)
+{
+ (void)rhport;
+
+ set_alt(req);
+
+ return true;
+}
+
+/* Speaker packet was received and stored in TinyUSB FIFO. */
+bool
+tud_audio_rx_done_isr(uint8_t rhport, uint16_t n_bytes_received,
+ uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting)
+{
+ (void)rhport;
+ (void)n_bytes_received;
+ (void)func_id;
+ (void)ep_out;
+ (void)cur_alt_setting;
+
+ usb_headset_data_ready();
+
+ return true;
+}
+
+/*
+ * Find audio streaming interface numbers in configuration descriptor.
+ * Streaming alternate setting has endpoint whose direction tells whether
+ * it is speaker (OUT) or microphone (IN) interface. This way application
+ * does not depend on other functions (like CDC) placed before audio.
+ */
+static void
+find_streaming_interfaces(void)
+{
+ const uint8_t *desc = tud_descriptor_configuration_cb(0);
+ const tusb_desc_configuration_t *cfg = (const void *)desc;
+ const uint8_t *end = desc + tu_le16toh(cfg->wTotalLength);
+ const tusb_desc_interface_t *itf;
+ const tusb_desc_endpoint_t *ep;
+ const uint8_t *p;
+ const uint8_t *q;
+
+ for (p = tu_desc_next(desc); p < end; p = tu_desc_next(p)) {
+ if (tu_desc_type(p) != TUSB_DESC_INTERFACE) {
+ continue;
+ }
+ itf = (const void *)p;
+ if (itf->bInterfaceClass != TUSB_CLASS_AUDIO ||
+ itf->bInterfaceSubClass != AUDIO_SUBCLASS_STREAMING ||
+ itf->bNumEndpoints == 0) {
+ continue;
+ }
+ /* First endpoint of this alternate setting */
+ for (q = tu_desc_next(p); q < end && tu_desc_type(q) != TUSB_DESC_INTERFACE;
+ q = tu_desc_next(q)) {
+ if (tu_desc_type(q) == TUSB_DESC_ENDPOINT) {
+ ep = (const void *)q;
+ if (tu_edpt_dir(ep->bEndpointAddress) == TUSB_DIR_OUT) {
+ usb_headset.spk_itf = itf->bInterfaceNumber;
+ } else {
+ usb_headset.mic_itf = itf->bInterfaceNumber;
+ }
+ break;
+ }
+ }
+ }
+}
+
+void
+usb_audio_init(void)
+{
+ /* Unmuted, 0 dB on all channels. */
+ memset(&usb_headset, 0, sizeof(usb_headset));
+ usb_headset.spk_itf = 0xFF;
+ usb_headset.mic_itf = 0xFF;
+ update_gain();
+
+ find_streaming_interfaces();
+ assert(usb_headset.spk_itf != 0xFF);
+ assert(usb_headset.mic_itf != 0xFF);
+}
diff --git a/apps/usb_headset/src/usb_headset.h b/apps/usb_headset/src/usb_headset.h
new file mode 100644
index 000000000..b1ff03e72
--- /dev/null
+++ b/apps/usb_headset/src/usb_headset.h
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_USB_HEADSET_
+#define H_USB_HEADSET_
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <syscfg/syscfg.h>
+#include <tusb.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Volume range exposed to host, 1 dB steps. */
+#define USB_HEADSET_VOLUME_MIN_DB (-60)
+#define USB_HEADSET_VOLUME_MAX_DB 0
+
+/* Feature units in descriptors support up to 8 channels plus master. */
+#define USB_HEADSET_FU_MAX_CHANNELS 8
+
+/* Mute and volume state of one feature unit, index 0 is master channel. */
+struct usb_headset_fu {
+ uint8_t mute[USB_HEADSET_FU_MAX_CHANNELS + 1];
+ /* Volume in 1/256 dB units as used by USB Audio Class. */
+ int16_t volume[USB_HEADSET_FU_MAX_CHANNELS + 1];
+};
+
+struct usb_headset {
+ struct usb_headset_fu spk;
+ struct usb_headset_fu mic;
+ /* Audio streaming interface numbers, found in configuration descriptor. */
+ uint8_t spk_itf;
+ uint8_t mic_itf;
+ /* Current alternate settings, 0 means stream is not active. */
+ volatile uint8_t spk_alt;
+ volatile uint8_t mic_alt;
+ /* Gain applied to mixed signal, Q15, 0 when muted. */
+ volatile uint16_t gain_q15;
+};
+
+extern struct usb_headset usb_headset;
+
+/* Initialize state and find interface numbers (usb_audio.c). */
+void usb_audio_init(void);
+
+/* Called when new speaker data is available in TinyUSB FIFO (main.c). */
+void usb_headset_data_ready(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_USB_HEADSET_ */
diff --git a/apps/usb_headset/syscfg.yml b/apps/usb_headset/syscfg.yml
new file mode 100644
index 000000000..98b3e6771
--- /dev/null
+++ b/apps/usb_headset/syscfg.yml
@@ -0,0 +1,48 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# USBD_VID, USBD_PID, USBD_VENDOR_STRING and USBD_PRODUCT_STRING are left
+# to the target.
+syscfg.vals:
+ USBD_STD_DESCRIPTORS: 1
+ # Audio function uses Interface Association Descriptor, device descriptor
+ # has to use composite device class (MISC/COMMON/IAD).
+ USBD_COMPOSITE_DEVICE: 1
+ # USB stack is started from main() after application is initialized.
+ TINYUSB_AUTO_START: 0
+
+ USBD_AUDIO: IN_OUT
+ USBD_AUDIO_DESCRIPTOR_STRING: '"Headset"'
+ USBD_AUDIO_SAMPLE_RATE: 48000
+ USBD_AUDIO_SAMPLE_SIZE: 16
+ USBD_AUDIO_OUT_CHANNELS: 2
+ USBD_AUDIO_IN_CHANNELS: 1
+ USBD_AUDIO_OUT_TERMINAL_TYPE: AUDIO_TERM_TYPE_OUT_HEADPHONES
+ USBD_AUDIO_IN_TERMINAL_TYPE: AUDIO_TERM_TYPE_IN_PERSONAL_MIC
+ USBD_AUDIO_VOLUME_CONTROL: 1
+ USBD_AUDIO_FEEDBACK: 0
+ # TinyUSB IN flow control needs FIFO of at least 4 packets, 8 gives
+ # headroom for event queue latency.
+ USBD_AUDIO_IN_BUFFER_PACKETS: 8
+ USBD_AUDIO_OUT_BUFFER_PACKETS: 4
+
+ USBD_STACK_SIZE: 600
+
+ # Application does not log, satisfy log API with stub.
+ LOG_IMPLEMENTATION: stub
(mynewt-core) 02/06: tinyusb/std_descriptors: Add USB Audio Class 2.0 function
Posted by je...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
kasjer pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 567628552c660aa3d5a4f07b24055440612c64cf
Author: Jerzy Kasenberg <je...@codecoup.pl>
AuthorDate: Wed Oct 7 14:55:12 2026 +0200
tinyusb/std_descriptors: Add USB Audio Class 2.0 function
Add UAC2 descriptors to the standard descriptor set, selected and
shaped by syscfg:
- USBD_AUDIO: NONE, IN (microphone), OUT (speaker) or IN_OUT
(headset). Function category and default terminal types follow
the selection, USBD_AUDIO_IN/OUT_TERMINAL_TYPE override them.
- USBD_AUDIO_SAMPLE_RATE, USBD_AUDIO_SAMPLE_SIZE and
USBD_AUDIO_BYTES_PER_SAMPLE describe the single Type I PCM format.
- USBD_AUDIO_IN_CHANNELS and USBD_AUDIO_OUT_CHANNELS are independent,
feature units expose mute and optionally volume per channel.
- USBD_AUDIO_FEEDBACK switches speaker endpoint from adaptive to
asynchronous with feedback endpoint.
- Endpoint numbers, optional interrupt endpoint and FIFO depths are
configurable; isochronous endpoints default to 8 on nRF5x.
Descriptor pieces live in usbd_audio_desc.h so that std_descriptors.c
only adds interface numbers, string index and total length. A static
assert verifies the composed descriptor length. The audio function
uses an IAD, so the device qualifier reports MISC/COMMON/IAD and
applications should set USBD_COMPOSITE_DEVICE.
TinyUSB's TUD_AUDIO_EP_SIZE cannot be used in #if before usbd.h is
included, a local USBD_AUDIO_EP_SIZE provides the same formula.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Jerzy Kasenberg <je...@codecoup.pl>
---
.../tinyusb/std_descriptors/include/tusb_config.h | 99 +++++
.../std_descriptors/include/usbd_audio_desc.h | 398 +++++++++++++++++++++
.../tinyusb/std_descriptors/src/std_descriptors.c | 34 +-
hw/usb/tinyusb/std_descriptors/syscfg.yml | 115 ++++++
4 files changed, 644 insertions(+), 2 deletions(-)
diff --git a/hw/usb/tinyusb/std_descriptors/include/tusb_config.h b/hw/usb/tinyusb/std_descriptors/include/tusb_config.h
index 8cbe04e54..e2dab3951 100755
--- a/hw/usb/tinyusb/std_descriptors/include/tusb_config.h
+++ b/hw/usb/tinyusb/std_descriptors/include/tusb_config.h
@@ -242,6 +242,105 @@ extern "C" {
#define CFG_TUD_DFU_DETACH_TIMEOUT 1000
#endif
+/* ------------- Audio (USB Audio Class 2.0) ------------- */
+#if MYNEWT_VAL_CHOICE(USBD_AUDIO, IN)
+#define CFG_TUD_AUDIO_ENABLE_EP_IN 1
+#define CFG_TUD_AUDIO_ENABLE_EP_OUT 0
+#elif MYNEWT_VAL_CHOICE(USBD_AUDIO, OUT)
+#define CFG_TUD_AUDIO_ENABLE_EP_IN 0
+#define CFG_TUD_AUDIO_ENABLE_EP_OUT 1
+#elif MYNEWT_VAL_CHOICE(USBD_AUDIO, IN_OUT)
+#define CFG_TUD_AUDIO_ENABLE_EP_IN 1
+#define CFG_TUD_AUDIO_ENABLE_EP_OUT 1
+#else
+#define CFG_TUD_AUDIO_ENABLE_EP_IN 0
+#define CFG_TUD_AUDIO_ENABLE_EP_OUT 0
+#endif
+#define CFG_TUD_AUDIO \
+ (CFG_TUD_AUDIO_ENABLE_EP_IN || CFG_TUD_AUDIO_ENABLE_EP_OUT)
+
+#if CFG_TUD_AUDIO
+#define USBD_AUDIO_SAMPLE_RATE MYNEWT_VAL(USBD_AUDIO_SAMPLE_RATE)
+/* Valid bits in sample (bit resolution) */
+#define USBD_AUDIO_SAMPLE_SIZE MYNEWT_VAL(USBD_AUDIO_SAMPLE_SIZE)
+/* Bytes used by sample in USB packet (subslot size) */
+#if MYNEWT_VAL(USBD_AUDIO_BYTES_PER_SAMPLE)
+#define USBD_AUDIO_BYTES_PER_SAMPLE MYNEWT_VAL(USBD_AUDIO_BYTES_PER_SAMPLE)
+#else
+#define USBD_AUDIO_BYTES_PER_SAMPLE ((USBD_AUDIO_SAMPLE_SIZE + 7) / 8)
+#endif
+
+#define USBD_AUDIO_IN_CHANNELS MYNEWT_VAL(USBD_AUDIO_IN_CHANNELS)
+#define USBD_AUDIO_OUT_CHANNELS MYNEWT_VAL(USBD_AUDIO_OUT_CHANNELS)
+
+/* Endpoint addresses, isochronous endpoints on nRF5x are fixed to 8 */
+#if MYNEWT_VAL(USBD_AUDIO_OUT_EP)
+#define USBD_AUDIO_OUT_EP MYNEWT_VAL(USBD_AUDIO_OUT_EP)
+#elif CFG_TUSB_MCU == OPT_MCU_NRF5X
+#define USBD_AUDIO_OUT_EP 8
+#else
+#define USBD_AUDIO_OUT_EP 1
+#endif
+
+#if MYNEWT_VAL(USBD_AUDIO_IN_EP)
+#define USBD_AUDIO_IN_EP (0x80 | MYNEWT_VAL(USBD_AUDIO_IN_EP))
+#elif CFG_TUSB_MCU == OPT_MCU_NRF5X
+#define USBD_AUDIO_IN_EP (0x80 | 8)
+#else
+#define USBD_AUDIO_IN_EP (0x80 | 1)
+#endif
+
+#if MYNEWT_VAL(USBD_AUDIO_FEEDBACK_EP)
+#define USBD_AUDIO_FEEDBACK_EP \
+ (0x80 | MYNEWT_VAL(USBD_AUDIO_FEEDBACK_EP))
+#elif CFG_TUSB_MCU == OPT_MCU_NRF5X
+#define USBD_AUDIO_FEEDBACK_EP (0x80 | 8)
+#else
+#define USBD_AUDIO_FEEDBACK_EP (0x80 | 2)
+#endif
+
+#if MYNEWT_VAL(USBD_AUDIO_FEEDBACK) && CFG_TUD_AUDIO_ENABLE_EP_OUT
+#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 1
+#else
+#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0
+#endif
+
+#if MYNEWT_VAL(USBD_AUDIO_INT_EP)
+#define CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP 1
+#define USBD_AUDIO_INT_EP (0x80 | MYNEWT_VAL(USBD_AUDIO_INT_EP))
+#else
+#define CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP 0
+#endif
+
+/*
+ * Endpoint sizes for 1 ms packets (one extra sample for rates that are not
+ * multiple of 1 kHz and for asynchronous streams). Same packet size is used
+ * for full and high speed, high speed endpoints use interval of 8
+ * microframes.
+ * Same formula as TUD_AUDIO_EP_SIZE(false, ...), written out here because
+ * TinyUSB evaluates these values in #if before usbd.h is included.
+ */
+#define USBD_AUDIO_EP_SIZE(_rate, _bytes, _nch) \
+ (((((_rate) + 999) / 1000) + 1) * (_bytes) * (_nch))
+#define USBD_AUDIO_EP_IN_SZ \
+ USBD_AUDIO_EP_SIZE(USBD_AUDIO_SAMPLE_RATE, USBD_AUDIO_BYTES_PER_SAMPLE, \
+ USBD_AUDIO_IN_CHANNELS)
+#define USBD_AUDIO_EP_OUT_SZ \
+ USBD_AUDIO_EP_SIZE(USBD_AUDIO_SAMPLE_RATE, USBD_AUDIO_BYTES_PER_SAMPLE, \
+ USBD_AUDIO_OUT_CHANNELS)
+
+#if CFG_TUD_AUDIO_ENABLE_EP_IN
+#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX USBD_AUDIO_EP_IN_SZ
+#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ \
+ (MYNEWT_VAL(USBD_AUDIO_IN_BUFFER_PACKETS) * USBD_AUDIO_EP_IN_SZ)
+#endif
+#if CFG_TUD_AUDIO_ENABLE_EP_OUT
+#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX USBD_AUDIO_EP_OUT_SZ
+#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ \
+ (MYNEWT_VAL(USBD_AUDIO_OUT_BUFFER_PACKETS) * USBD_AUDIO_EP_OUT_SZ)
+#endif
+#endif /* CFG_TUD_AUDIO */
+
#ifdef __cplusplus
}
#endif
diff --git a/hw/usb/tinyusb/std_descriptors/include/usbd_audio_desc.h b/hw/usb/tinyusb/std_descriptors/include/usbd_audio_desc.h
new file mode 100644
index 000000000..72f412ee8
--- /dev/null
+++ b/hw/usb/tinyusb/std_descriptors/include/usbd_audio_desc.h
@@ -0,0 +1,398 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_USBD_AUDIO_DESC_
+#define H_USBD_AUDIO_DESC_
+
+#include <syscfg/syscfg.h>
+#include <tusb.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * USB Audio Class 2.0 function descriptors built from syscfg values:
+ *
+ * USBD_AUDIO IN (mic), OUT (speaker), IN_OUT (headset)
+ * USBD_AUDIO_SAMPLE_RATE sampling frequency in Hz
+ * USBD_AUDIO_SAMPLE_SIZE bits per sample
+ * USBD_AUDIO_BYTES_PER_SAMPLE bytes per sample (subslot size)
+ * USBD_AUDIO_IN_CHANNELS number of microphone channels
+ * USBD_AUDIO_OUT_CHANNELS number of speaker channels
+ * USBD_AUDIO_IN_TERMINAL_TYPE microphone input terminal type
+ * (AUDIO_TERM_TYPE_IN_*)
+ * USBD_AUDIO_OUT_TERMINAL_TYPE speaker output terminal type
+ * (AUDIO_TERM_TYPE_OUT_*)
+ * USBD_AUDIO_VOLUME_CONTROL feature unit with mute and volume controls
+ * USBD_AUDIO_FEEDBACK feedback endpoint for speaker path
+ * USBD_AUDIO_INT_EP interrupt endpoint for control changes
+ *
+ * Function has one clock source shared by all terminals, one alternate
+ * setting with audio data per streaming interface and PCM type I format.
+ * Layout of the function:
+ *
+ * Interface N Audio Control:
+ * Clock Source (4)
+ * Speaker path:
+ * Input Terminal (1) -> [Feature Unit (2)] ->
+ * Output Terminal (3)
+ * Microphone path:
+ * Input Terminal (0x11) -> [Feature Unit (0x12)] ->
+ * Output Terminal (0x13)
+ * [Interrupt endpoint]
+ * Interface N+1 Audio Streaming OUT (speaker),
+ * alternate 0 (idle) and 1 (streaming)
+ * Interface N+2 Audio Streaming IN (microphone),
+ * alternate 0 (idle) and 1 (streaming)
+ *
+ * Only descriptors are provided here, application has to implement TinyUSB
+ * audio class callbacks (tud_audio_*_cb). Entity IDs below are needed to
+ * handle requests passed to tud_audio_get_req_entity_cb() and
+ * tud_audio_set_req_entity_cb().
+ */
+#define USBD_AUDIO_ENTITY_CLOCK 0x04
+/* Speaker path (host -> device) */
+#define USBD_AUDIO_ENTITY_SPK_INPUT_TERMINAL 0x01
+#define USBD_AUDIO_ENTITY_SPK_FEATURE_UNIT 0x02
+#define USBD_AUDIO_ENTITY_SPK_OUTPUT_TERMINAL 0x03
+/* Microphone path (device -> host) */
+#define USBD_AUDIO_ENTITY_MIC_INPUT_TERMINAL 0x11
+#define USBD_AUDIO_ENTITY_MIC_FEATURE_UNIT 0x12
+#define USBD_AUDIO_ENTITY_MIC_OUTPUT_TERMINAL 0x13
+
+#if CFG_TUD_AUDIO
+
+#if MYNEWT_VAL(USBD_AUDIO_VOLUME_CONTROL) && \
+ (CFG_TUD_AUDIO_ENABLE_EP_OUT && USBD_AUDIO_OUT_CHANNELS > 8 || \
+ CFG_TUD_AUDIO_ENABLE_EP_IN && USBD_AUDIO_IN_CHANNELS > 8)
+#error USBD_AUDIO_VOLUME_CONTROL supports up to 8 channels
+#endif
+
+/* Number of USB interfaces used by audio function (AC + AS interfaces). */
+#define USBD_AUDIO_ITF_COUNT \
+ (1 + CFG_TUD_AUDIO_ENABLE_EP_OUT + CFG_TUD_AUDIO_ENABLE_EP_IN)
+
+/* Endpoint interval resulting in 1 ms packets for full and high speed. */
+#define USBD_AUDIO_EP_INTERVAL \
+ ((USBD_RHPORT_MODE & OPT_MODE_HIGH_SPEED) ? 4 : 1)
+
+/* Function category and default terminal types depend on direction(s). */
+#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_EP_IN
+#define USBD_AUDIO_FUNCTION_CATEGORY AUDIO20_FUNC_HEADSET
+#define USBD_AUDIO_SPK_TERMINAL_DEFAULT AUDIO_TERM_TYPE_OUT_HEADPHONES
+/* Terminals of both paths are associated with each other. */
+#define USBD_AUDIO_SPK_IT_ASSOC USBD_AUDIO_ENTITY_MIC_OUTPUT_TERMINAL
+#define USBD_AUDIO_MIC_OT_ASSOC USBD_AUDIO_ENTITY_SPK_INPUT_TERMINAL
+#elif CFG_TUD_AUDIO_ENABLE_EP_OUT
+#define USBD_AUDIO_FUNCTION_CATEGORY AUDIO20_FUNC_DESKTOP_SPEAKER
+#define USBD_AUDIO_SPK_TERMINAL_DEFAULT AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER
+#define USBD_AUDIO_SPK_IT_ASSOC 0x00
+#else
+#define USBD_AUDIO_FUNCTION_CATEGORY AUDIO20_FUNC_MICROPHONE
+#define USBD_AUDIO_MIC_OT_ASSOC 0x00
+#endif
+#define USBD_AUDIO_MIC_TERMINAL_DEFAULT AUDIO_TERM_TYPE_IN_GENERIC_MIC
+
+/* Terminal types, from syscfg when set (AUDIO_TERM_TYPE_* name or number). */
+#if defined(MYNEWT_VAL_USBD_AUDIO_OUT_TERMINAL_TYPE)
+#define USBD_AUDIO_SPK_TERMINAL_TYPE MYNEWT_VAL(USBD_AUDIO_OUT_TERMINAL_TYPE)
+#else
+#define USBD_AUDIO_SPK_TERMINAL_TYPE USBD_AUDIO_SPK_TERMINAL_DEFAULT
+#endif
+#if defined(MYNEWT_VAL_USBD_AUDIO_IN_TERMINAL_TYPE)
+#define USBD_AUDIO_MIC_TERMINAL_TYPE MYNEWT_VAL(USBD_AUDIO_IN_TERMINAL_TYPE)
+#else
+#define USBD_AUDIO_MIC_TERMINAL_TYPE USBD_AUDIO_MIC_TERMINAL_DEFAULT
+#endif
+
+/*
+ * Spatial location of channels: mono - front center, stereo - left and
+ * right, other - not specified.
+ */
+#define USBD_AUDIO_CHANNEL_CONFIG(_nch) \
+ ((_nch) == 1 ? AUDIO20_CHANNEL_CONFIG_FRONT_CENTER : \
+ (_nch) == 2 ? (AUDIO20_CHANNEL_CONFIG_FRONT_LEFT | AUDIO20_CHANNEL_CONFIG_FRONT_RIGHT) : \
+ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED)
+
+/*
+ * Feature unit controls: mute and volume, read/write, for master channel
+ * (first) and every logical channel. USBD_AUDIO_FU_CTRLS_n expands to
+ * n + 1 values.
+ * Channel counts come from syscfg as parenthesized values, so they can not be
+ * pasted into macro names and #if ladders are used to select the list.
+ */
+#define USBD_AUDIO_FU_CTRL \
+ ((AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_MUTE_POS) | \
+ (AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_VOLUME_POS))
+#define USBD_AUDIO_FU_CTRLS_1 USBD_AUDIO_FU_CTRL, USBD_AUDIO_FU_CTRL
+#define USBD_AUDIO_FU_CTRLS_2 USBD_AUDIO_FU_CTRLS_1, USBD_AUDIO_FU_CTRL
+#define USBD_AUDIO_FU_CTRLS_3 USBD_AUDIO_FU_CTRLS_2, USBD_AUDIO_FU_CTRL
+#define USBD_AUDIO_FU_CTRLS_4 USBD_AUDIO_FU_CTRLS_3, USBD_AUDIO_FU_CTRL
+#define USBD_AUDIO_FU_CTRLS_5 USBD_AUDIO_FU_CTRLS_4, USBD_AUDIO_FU_CTRL
+#define USBD_AUDIO_FU_CTRLS_6 USBD_AUDIO_FU_CTRLS_5, USBD_AUDIO_FU_CTRL
+#define USBD_AUDIO_FU_CTRLS_7 USBD_AUDIO_FU_CTRLS_6, USBD_AUDIO_FU_CTRL
+#define USBD_AUDIO_FU_CTRLS_8 USBD_AUDIO_FU_CTRLS_7, USBD_AUDIO_FU_CTRL
+
+#if USBD_AUDIO_OUT_CHANNELS == 1
+#define USBD_AUDIO_SPK_FU_CTRLS USBD_AUDIO_FU_CTRLS_1
+#elif USBD_AUDIO_OUT_CHANNELS == 2
+#define USBD_AUDIO_SPK_FU_CTRLS USBD_AUDIO_FU_CTRLS_2
+#elif USBD_AUDIO_OUT_CHANNELS == 3
+#define USBD_AUDIO_SPK_FU_CTRLS USBD_AUDIO_FU_CTRLS_3
+#elif USBD_AUDIO_OUT_CHANNELS == 4
+#define USBD_AUDIO_SPK_FU_CTRLS USBD_AUDIO_FU_CTRLS_4
+#elif USBD_AUDIO_OUT_CHANNELS == 5
+#define USBD_AUDIO_SPK_FU_CTRLS USBD_AUDIO_FU_CTRLS_5
+#elif USBD_AUDIO_OUT_CHANNELS == 6
+#define USBD_AUDIO_SPK_FU_CTRLS USBD_AUDIO_FU_CTRLS_6
+#elif USBD_AUDIO_OUT_CHANNELS == 7
+#define USBD_AUDIO_SPK_FU_CTRLS USBD_AUDIO_FU_CTRLS_7
+#else
+#define USBD_AUDIO_SPK_FU_CTRLS USBD_AUDIO_FU_CTRLS_8
+#endif
+
+#if USBD_AUDIO_IN_CHANNELS == 1
+#define USBD_AUDIO_MIC_FU_CTRLS USBD_AUDIO_FU_CTRLS_1
+#elif USBD_AUDIO_IN_CHANNELS == 2
+#define USBD_AUDIO_MIC_FU_CTRLS USBD_AUDIO_FU_CTRLS_2
+#elif USBD_AUDIO_IN_CHANNELS == 3
+#define USBD_AUDIO_MIC_FU_CTRLS USBD_AUDIO_FU_CTRLS_3
+#elif USBD_AUDIO_IN_CHANNELS == 4
+#define USBD_AUDIO_MIC_FU_CTRLS USBD_AUDIO_FU_CTRLS_4
+#elif USBD_AUDIO_IN_CHANNELS == 5
+#define USBD_AUDIO_MIC_FU_CTRLS USBD_AUDIO_FU_CTRLS_5
+#elif USBD_AUDIO_IN_CHANNELS == 6
+#define USBD_AUDIO_MIC_FU_CTRLS USBD_AUDIO_FU_CTRLS_6
+#elif USBD_AUDIO_IN_CHANNELS == 7
+#define USBD_AUDIO_MIC_FU_CTRLS USBD_AUDIO_FU_CTRLS_7
+#else
+#define USBD_AUDIO_MIC_FU_CTRLS USBD_AUDIO_FU_CTRLS_8
+#endif
+
+#if MYNEWT_VAL(USBD_AUDIO_VOLUME_CONTROL)
+#define USBD_AUDIO_FU_LEN(_nch) TUD_AUDIO20_DESC_FEATURE_UNIT_LEN(_nch)
+#define USBD_AUDIO_FU_DESC(_unitid, _srcid, _ctrls) \
+ /* Feature Unit Descriptor(4.7.2.8) */ \
+ , TUD_AUDIO20_DESC_FEATURE_UNIT(_unitid, _srcid, 0x00, _ctrls)
+#define USBD_AUDIO_SPK_OT_SOURCE USBD_AUDIO_ENTITY_SPK_FEATURE_UNIT
+#define USBD_AUDIO_MIC_OT_SOURCE USBD_AUDIO_ENTITY_MIC_FEATURE_UNIT
+#else
+#define USBD_AUDIO_FU_LEN(_nch) 0
+#define USBD_AUDIO_FU_DESC(_unitid, _srcid, _ctrls)
+#define USBD_AUDIO_SPK_OT_SOURCE USBD_AUDIO_ENTITY_SPK_INPUT_TERMINAL
+#define USBD_AUDIO_MIC_OT_SOURCE USBD_AUDIO_ENTITY_MIC_INPUT_TERMINAL
+#endif
+
+/*
+ * Optional parts of the descriptor are defined as macros that expand to
+ * nothing when the part is not needed. Each part starts with a comma so
+ * it can follow the previous one.
+ */
+
+/* Audio Control entities of speaker path */
+#if CFG_TUD_AUDIO_ENABLE_EP_OUT
+#define USBD_AUDIO_AC_SPK_ENTITIES_LEN \
+ (TUD_AUDIO20_DESC_INPUT_TERM_LEN + USBD_AUDIO_FU_LEN(USBD_AUDIO_OUT_CHANNELS) + \
+ TUD_AUDIO20_DESC_OUTPUT_TERM_LEN)
+#define USBD_AUDIO_AC_SPK_ENTITIES \
+ /* Input Terminal Descriptor(4.7.2.4) - USB stream from host */ \
+ , TUD_AUDIO20_DESC_INPUT_TERM(USBD_AUDIO_ENTITY_SPK_INPUT_TERMINAL, AUDIO_TERM_TYPE_USB_STREAMING, \
+ USBD_AUDIO_SPK_IT_ASSOC, USBD_AUDIO_ENTITY_CLOCK, USBD_AUDIO_OUT_CHANNELS, \
+ USBD_AUDIO_CHANNEL_CONFIG(USBD_AUDIO_OUT_CHANNELS), 0x00, 0x0000, 0x00) \
+ USBD_AUDIO_FU_DESC(USBD_AUDIO_ENTITY_SPK_FEATURE_UNIT, USBD_AUDIO_ENTITY_SPK_INPUT_TERMINAL, \
+ USBD_AUDIO_SPK_FU_CTRLS) \
+ /* Output Terminal Descriptor(4.7.2.5) - speaker */ \
+ , TUD_AUDIO20_DESC_OUTPUT_TERM(USBD_AUDIO_ENTITY_SPK_OUTPUT_TERMINAL, USBD_AUDIO_SPK_TERMINAL_TYPE, 0x00, \
+ USBD_AUDIO_SPK_OT_SOURCE, USBD_AUDIO_ENTITY_CLOCK, 0x0000, 0x00)
+#else
+#define USBD_AUDIO_AC_SPK_ENTITIES_LEN 0
+#define USBD_AUDIO_AC_SPK_ENTITIES
+#endif
+
+/* Audio Control entities of microphone path */
+#if CFG_TUD_AUDIO_ENABLE_EP_IN
+#define USBD_AUDIO_AC_MIC_ENTITIES_LEN \
+ (TUD_AUDIO20_DESC_INPUT_TERM_LEN + USBD_AUDIO_FU_LEN(USBD_AUDIO_IN_CHANNELS) + \
+ TUD_AUDIO20_DESC_OUTPUT_TERM_LEN)
+#define USBD_AUDIO_AC_MIC_ENTITIES \
+ /* Input Terminal Descriptor(4.7.2.4) - microphone */ \
+ , TUD_AUDIO20_DESC_INPUT_TERM(USBD_AUDIO_ENTITY_MIC_INPUT_TERMINAL, USBD_AUDIO_MIC_TERMINAL_TYPE, \
+ 0x00, USBD_AUDIO_ENTITY_CLOCK, USBD_AUDIO_IN_CHANNELS, \
+ USBD_AUDIO_CHANNEL_CONFIG(USBD_AUDIO_IN_CHANNELS), 0x00, 0x0000, 0x00) \
+ USBD_AUDIO_FU_DESC(USBD_AUDIO_ENTITY_MIC_FEATURE_UNIT, USBD_AUDIO_ENTITY_MIC_INPUT_TERMINAL, \
+ USBD_AUDIO_MIC_FU_CTRLS) \
+ /* Output Terminal Descriptor(4.7.2.5) - USB stream to host */ \
+ , TUD_AUDIO20_DESC_OUTPUT_TERM(USBD_AUDIO_ENTITY_MIC_OUTPUT_TERMINAL, AUDIO_TERM_TYPE_USB_STREAMING, \
+ USBD_AUDIO_MIC_OT_ASSOC, USBD_AUDIO_MIC_OT_SOURCE, USBD_AUDIO_ENTITY_CLOCK, \
+ 0x0000, 0x00)
+#else
+#define USBD_AUDIO_AC_MIC_ENTITIES_LEN 0
+#define USBD_AUDIO_AC_MIC_ENTITIES
+#endif
+
+#define USBD_AUDIO_AC_ENTITIES_LEN \
+ (TUD_AUDIO20_DESC_CLK_SRC_LEN + USBD_AUDIO_AC_SPK_ENTITIES_LEN + USBD_AUDIO_AC_MIC_ENTITIES_LEN)
+
+/* Audio Control interrupt endpoint */
+#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
+#define USBD_AUDIO_AC_INT_EP_LEN TUD_AUDIO20_DESC_STD_AC_INT_EP_LEN
+#define USBD_AUDIO_AC_INT_EP \
+ /* Standard AC Interrupt Endpoint Descriptor(4.8.2.1) */ \
+ , TUD_AUDIO20_DESC_STD_AC_INT_EP(USBD_AUDIO_INT_EP, USBD_AUDIO_EP_INTERVAL)
+#else
+#define USBD_AUDIO_AC_INT_EP_LEN 0
+#define USBD_AUDIO_AC_INT_EP
+#endif
+
+/* Audio Streaming interface of speaker path */
+#if CFG_TUD_AUDIO_ENABLE_EP_OUT
+#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
+/* Rate is driven by device clock, host adjusts to feedback. */
+#define USBD_AUDIO_EP_OUT_SYNC TUSB_ISO_EP_ATT_ASYNCHRONOUS
+#define USBD_AUDIO_AS_OUT_FB_EP_LEN TUD_AUDIO20_DESC_STD_AS_ISO_FB_EP_LEN
+#define USBD_AUDIO_AS_OUT_FB_EP \
+ /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */ \
+ , TUD_AUDIO20_DESC_STD_AS_ISO_FB_EP(USBD_AUDIO_FEEDBACK_EP, 4, USBD_AUDIO_EP_INTERVAL)
+#else
+/* Device adapts to the rate host sends data at. */
+#define USBD_AUDIO_EP_OUT_SYNC TUSB_ISO_EP_ATT_ADAPTIVE
+#define USBD_AUDIO_AS_OUT_FB_EP_LEN 0
+#define USBD_AUDIO_AS_OUT_FB_EP
+#endif
+#define USBD_AUDIO_AS_OUT_DESC_LEN \
+ (2 * 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 + USBD_AUDIO_AS_OUT_FB_EP_LEN)
+#define USBD_AUDIO_AS_OUT_DESC(_itfnum) \
+ /* Standard AS Interface Descriptor(4.9.1), alternate 0 - no bandwidth */ \
+ , TUD_AUDIO20_DESC_STD_AS_INT(_itfnum, 0x00, 0x00, 0x00) \
+ /* Standard AS Interface Descriptor(4.9.1), alternate 1 - streaming */ \
+ , TUD_AUDIO20_DESC_STD_AS_INT(_itfnum, 0x01, 1 + CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP, 0x00) \
+ /* Class-Specific AS Interface Descriptor(4.9.2) */ \
+ , TUD_AUDIO20_DESC_CS_AS_INT(USBD_AUDIO_ENTITY_SPK_INPUT_TERMINAL, AUDIO20_CTRL_NONE, \
+ AUDIO20_FORMAT_TYPE_I, AUDIO20_DATA_FORMAT_TYPE_I_PCM, USBD_AUDIO_OUT_CHANNELS, \
+ USBD_AUDIO_CHANNEL_CONFIG(USBD_AUDIO_OUT_CHANNELS), 0x00) \
+ /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */ \
+ , TUD_AUDIO20_DESC_TYPE_I_FORMAT(USBD_AUDIO_BYTES_PER_SAMPLE, USBD_AUDIO_SAMPLE_SIZE) \
+ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */ \
+ , TUD_AUDIO20_DESC_STD_AS_ISO_EP(USBD_AUDIO_OUT_EP, \
+ (uint8_t)(TUSB_XFER_ISOCHRONOUS | USBD_AUDIO_EP_OUT_SYNC | TUSB_ISO_EP_ATT_DATA), \
+ USBD_AUDIO_EP_OUT_SZ, USBD_AUDIO_EP_INTERVAL) \
+ /* Class-Specific AS Isochronous Data Endpoint Descriptor(4.10.1.2) */ \
+ , TUD_AUDIO20_DESC_CS_AS_ISO_EP(AUDIO20_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, AUDIO20_CTRL_NONE, \
+ AUDIO20_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC, 0x0001) \
+ USBD_AUDIO_AS_OUT_FB_EP
+#else
+#define USBD_AUDIO_AS_OUT_DESC_LEN 0
+#define USBD_AUDIO_AS_OUT_DESC(_itfnum)
+#endif
+
+/* Audio Streaming interface of microphone path */
+#if CFG_TUD_AUDIO_ENABLE_EP_IN
+#define USBD_AUDIO_AS_IN_DESC_LEN \
+ (2 * 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 USBD_AUDIO_AS_IN_DESC(_itfnum) \
+ /* Standard AS Interface Descriptor(4.9.1), alternate 0 - no bandwidth */ \
+ , TUD_AUDIO20_DESC_STD_AS_INT(_itfnum, 0x00, 0x00, 0x00) \
+ /* Standard AS Interface Descriptor(4.9.1), alternate 1 - streaming */ \
+ , TUD_AUDIO20_DESC_STD_AS_INT(_itfnum, 0x01, 0x01, 0x00) \
+ /* Class-Specific AS Interface Descriptor(4.9.2) */ \
+ , TUD_AUDIO20_DESC_CS_AS_INT(USBD_AUDIO_ENTITY_MIC_OUTPUT_TERMINAL, AUDIO20_CTRL_NONE, \
+ AUDIO20_FORMAT_TYPE_I, AUDIO20_DATA_FORMAT_TYPE_I_PCM, USBD_AUDIO_IN_CHANNELS, \
+ USBD_AUDIO_CHANNEL_CONFIG(USBD_AUDIO_IN_CHANNELS), 0x00) \
+ /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */ \
+ , TUD_AUDIO20_DESC_TYPE_I_FORMAT(USBD_AUDIO_BYTES_PER_SAMPLE, USBD_AUDIO_SAMPLE_SIZE) \
+ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */ \
+ , TUD_AUDIO20_DESC_STD_AS_ISO_EP(USBD_AUDIO_IN_EP, \
+ (uint8_t)(TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), \
+ USBD_AUDIO_EP_IN_SZ, USBD_AUDIO_EP_INTERVAL) \
+ /* Class-Specific AS Isochronous Data Endpoint Descriptor(4.10.1.2) */ \
+ , TUD_AUDIO20_DESC_CS_AS_ISO_EP(AUDIO20_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, AUDIO20_CTRL_NONE, \
+ AUDIO20_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, 0x0000)
+#else
+#define USBD_AUDIO_AS_IN_DESC_LEN 0
+#define USBD_AUDIO_AS_IN_DESC(_itfnum)
+#endif
+
+/* Total length of audio function descriptors. */
+#define USBD_AUDIO_DESC_LEN \
+ (TUD_AUDIO20_DESC_IAD_LEN + TUD_AUDIO20_DESC_STD_AC_LEN + TUD_AUDIO20_DESC_CS_AC_LEN + \
+ USBD_AUDIO_AC_ENTITIES_LEN + USBD_AUDIO_AC_INT_EP_LEN + \
+ USBD_AUDIO_AS_OUT_DESC_LEN + USBD_AUDIO_AS_IN_DESC_LEN)
+
+/*
+ * Audio function descriptors.
+ * _itfnum - number of Audio Control interface, streaming interfaces follow it
+ * (OUT first when both are present).
+ * _stridx - string descriptor index of Audio Control interface.
+ */
+#define USBD_AUDIO20_DESCRIPTOR(_itfnum, _stridx) \
+ /* Standard Interface Association Descriptor (IAD) */ \
+ TUD_AUDIO20_DESC_IAD(_itfnum, USBD_AUDIO_ITF_COUNT, 0x00), \
+ /* Standard AC Interface Descriptor(4.7.1) */ \
+ TUD_AUDIO20_DESC_STD_AC(_itfnum, CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP, _stridx), \
+ /* Class-Specific AC Interface Header Descriptor(4.7.2) */ \
+ TUD_AUDIO20_DESC_CS_AC(0x0200, USBD_AUDIO_FUNCTION_CATEGORY, USBD_AUDIO_AC_ENTITIES_LEN, AUDIO20_CTRL_NONE), \
+ /* Clock Source Descriptor(4.7.2.1), fixed frequency readable by host */ \
+ TUD_AUDIO20_DESC_CLK_SRC(USBD_AUDIO_ENTITY_CLOCK, AUDIO20_CLOCK_SOURCE_ATT_INT_FIX_CLK, \
+ (AUDIO20_CTRL_R << AUDIO20_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), 0x00, 0x00) \
+ USBD_AUDIO_AC_SPK_ENTITIES \
+ USBD_AUDIO_AC_MIC_ENTITIES \
+ USBD_AUDIO_AC_INT_EP \
+ USBD_AUDIO_AS_OUT_DESC((_itfnum) + 1) \
+ USBD_AUDIO_AS_IN_DESC((_itfnum) + 1 + CFG_TUD_AUDIO_ENABLE_EP_OUT)
+
+#else /* CFG_TUD_AUDIO */
+
+#define USBD_AUDIO_ITF_COUNT 0
+#define USBD_AUDIO_DESC_LEN 0
+
+#endif /* CFG_TUD_AUDIO */
+
+// 5.2.2 Control Request Layout - was removed from TinyUSB
+typedef struct TU_ATTR_PACKED {
+ union {
+ struct TU_ATTR_PACKED {
+ uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t.
+ uint8_t type : 2; ///< Request type tusb_request_type_t.
+ uint8_t direction : 1; ///< Direction type. tusb_dir_t
+ } bmRequestType_bit;
+
+ uint8_t bmRequestType;
+ };
+
+ uint8_t bRequest; ///< Request type audio_cs_req_t
+ uint8_t bChannelNumber;
+ uint8_t bControlSelector;
+ union {
+ uint8_t bInterface;
+ uint8_t bEndpoint;
+ };
+ uint8_t bEntityID;
+ uint16_t wLength;
+} audio_control_request_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_USBD_AUDIO_DESC_ */
diff --git a/hw/usb/tinyusb/std_descriptors/src/std_descriptors.c b/hw/usb/tinyusb/std_descriptors/src/std_descriptors.c
index 79cdd57f7..0e37bff99 100755
--- a/hw/usb/tinyusb/std_descriptors/src/std_descriptors.c
+++ b/hw/usb/tinyusb/std_descriptors/src/std_descriptors.c
@@ -32,6 +32,7 @@
#include <os/util.h>
#include <console/console.h>
#include <hal/hal_gpio.h>
+#include <usbd_audio_desc.h>
#define USBD_PRODUCT_RELEASE_NUMBER MYNEWT_VAL(USBD_PRODUCT_RELEASE_NUMBER)
@@ -73,6 +74,11 @@ enum usb_desc_ix {
#else
#define BTH_IF_STR_IX 0
#endif
+#if defined MYNEWT_VAL_USBD_AUDIO_DESCRIPTOR_STRING
+ AUDIO_IF_STR_IX,
+#else
+#define AUDIO_IF_STR_IX 0
+#endif
#if defined MYNEWT_VAL_USBD_DFU_SLOT_NAME
DFU_SLOT_NAME_IF_STR_IX,
#endif
@@ -208,9 +214,9 @@ tusb_desc_device_qualifier_t const desc_device_qualifier = {
.bDeviceClass = TUD_BT_APP_CLASS,
.bDeviceSubClass = TUD_BT_APP_SUBCLASS,
.bDeviceProtocol = TUD_BT_PROTOCOL_PRIMARY_CONTROLLER,
-#elif CFG_TUD_CDC
+#elif CFG_TUD_CDC || CFG_TUD_AUDIO
/*
- * Use Interface Association Descriptor (IAD) for CDC
+ * Use Interface Association Descriptor (IAD) for CDC and Audio
* As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
*/
.bDeviceClass = TUSB_CLASS_MISC,
@@ -286,6 +292,16 @@ enum {
ITF_NUM_HID,
#endif
+#if CFG_TUD_AUDIO
+ ITF_NUM_AUDIO_CONTROL,
+#if CFG_TUD_AUDIO_ENABLE_EP_OUT
+ ITF_NUM_AUDIO_STREAMING_OUT,
+#endif
+#if CFG_TUD_AUDIO_ENABLE_EP_IN
+ ITF_NUM_AUDIO_STREAMING_IN,
+#endif
+#endif
+
#if CFG_TUD_DFU
ITF_NUM_DFU,
#endif
@@ -304,6 +320,7 @@ enum {
CFG_TUD_MSC * TUD_MSC_DESC_LEN + \
CFG_TUD_HID * TUD_HID_DESC_LEN + \
CFG_TUD_BTH * TUD_BTH_DESC_LEN + \
+ USBD_AUDIO_DESC_LEN + \
CFG_TUD_DFU * TUD_DFU_DESC_LEN(1) + \
CFG_TUD_DFU_RUNTIME * TUD_DFU_RT_DESC_LEN + \
0)
@@ -348,6 +365,10 @@ const uint8_t desc_configuration[] = {
USBD_HID_REPORT_EP, USBD_HID_REPORT_EP_SIZE, USBD_HID_REPORT_EP_INTERVAL),
#endif
+#if CFG_TUD_AUDIO
+ USBD_AUDIO20_DESCRIPTOR(ITF_NUM_AUDIO_CONTROL, AUDIO_IF_STR_IX),
+#endif
+
#if CFG_TUD_DFU
TUD_DFU_DESCRIPTOR(ITF_NUM_DFU, 1, DFU_SLOT_NAME_IF_STR_IX, DFU_ATTR_CAN_DOWNLOAD,
CFG_TUD_DFU_DETACH_TIMEOUT, CFG_TUD_DFU_XFER_BUFSIZE),
@@ -359,6 +380,12 @@ const uint8_t desc_configuration[] = {
#endif
};
+#if CFG_TUD_AUDIO
+/* Audio descriptor has many parts, make sure declared length matches. */
+TU_VERIFY_STATIC(sizeof(desc_configuration) == CONFIG_TOTAL_LEN,
+ "Configuration descriptor length mismatch");
+#endif
+
/**
* Invoked when received GET CONFIGURATION DESCRIPTOR
* Application return pointer to descriptor
@@ -393,6 +420,9 @@ const char *string_desc_arr[] = {
#if defined MYNEWT_VAL_USBD_BTH_DESCRIPTOR_STRING
MYNEWT_VAL(USBD_BTH_DESCRIPTOR_STRING),
#endif
+#if defined MYNEWT_VAL_USBD_AUDIO_DESCRIPTOR_STRING
+ MYNEWT_VAL(USBD_AUDIO_DESCRIPTOR_STRING),
+#endif
#if defined MYNEWT_VAL_USBD_DFU_SLOT_NAME
MYNEWT_VAL(USBD_DFU_SLOT_NAME),
#endif
diff --git a/hw/usb/tinyusb/std_descriptors/syscfg.yml b/hw/usb/tinyusb/std_descriptors/syscfg.yml
index 8e6ea2cb7..b0650215a 100644
--- a/hw/usb/tinyusb/std_descriptors/syscfg.yml
+++ b/hw/usb/tinyusb/std_descriptors/syscfg.yml
@@ -223,6 +223,121 @@ syscfg.defs:
description: MSC data endpoint buffer size
value:
+ USBD_AUDIO:
+ description: >
+ Enable USB Audio Class 2.0 function in TinyUSB stack.
+ IN - microphone (device sends audio to host),
+ OUT - speaker (host sends audio to device),
+ IN_OUT - headset (both directions, single clock source),
+ NONE - no audio function.
+ This adds descriptors to USB configuration, application has to
+ implement TinyUSB audio class callbacks (tud_audio_*_cb).
+ Entity IDs used in descriptors are defined in usbd_audio_desc.h.
+ value: NONE
+ choices:
+ - NONE
+ - IN
+ - OUT
+ - IN_OUT
+ USBD_AUDIO_DESCRIPTOR_STRING:
+ description: String for Audio Control interface
+ value:
+ USBD_AUDIO_SAMPLE_RATE:
+ description: >
+ Audio sampling frequency in Hz, same for microphone and speaker.
+ value: 48000
+ USBD_AUDIO_SAMPLE_SIZE:
+ description: >
+ Number of valid bits in each audio sample (bit resolution).
+ value: 16
+ range: 8..32
+ USBD_AUDIO_BYTES_PER_SAMPLE:
+ description: >
+ Number of bytes each sample occupies in USB packet (subslot size,
+ 1-4). Leave empty to use smallest size that fits
+ USBD_AUDIO_SAMPLE_SIZE. Set to 4 for 24 bit samples in 32 bit
+ slots.
+ value:
+ USBD_AUDIO_IN_CHANNELS:
+ description: >
+ Number of microphone (IN) channels. Values 1 and 2 are reported
+ to host as mono and stereo, other values as channels without
+ spatial location.
+ value: 1
+ range: 1..32
+ USBD_AUDIO_OUT_CHANNELS:
+ description: >
+ Number of speaker (OUT) channels. Values 1 and 2 are reported
+ to host as mono and stereo, other values as channels without
+ spatial location.
+ value: 2
+ range: 1..32
+ USBD_AUDIO_IN_TERMINAL_TYPE:
+ description: >
+ Terminal type of microphone input terminal, as AUDIO_TERM_TYPE_IN_*
+ constant from TinyUSB audio.h or numeric value from USB Audio
+ Terminal Types specification (0x0201 - generic microphone,
+ 0x0202 - desktop, 0x0203 - personal, 0x0204 - omni-directional,
+ 0x0205 - microphone array).
+ Empty for AUDIO_TERM_TYPE_IN_GENERIC_MIC.
+ value:
+ USBD_AUDIO_OUT_TERMINAL_TYPE:
+ description: >
+ Terminal type of speaker output terminal, as AUDIO_TERM_TYPE_OUT_*
+ constant from TinyUSB audio.h or numeric value from USB Audio
+ Terminal Types specification (0x0301 - generic speaker,
+ 0x0302 - headphones, 0x0304 - desktop speaker, 0x0305 - room
+ speaker, 0x0306 - communication speaker, 0x0307 - LFE speaker).
+ Empty for AUDIO_TERM_TYPE_OUT_HEADPHONES when USBD_AUDIO is IN_OUT
+ and AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER otherwise.
+ value:
+ USBD_AUDIO_VOLUME_CONTROL:
+ description: >
+ Add feature unit with mute and volume controls (master and per
+ channel) to microphone and speaker path. Application has to
+ handle requests for USBD_AUDIO_ENTITY_SPK_FEATURE_UNIT and
+ USBD_AUDIO_ENTITY_MIC_FEATURE_UNIT. Supports up to 8 channels.
+ value: 1
+ USBD_AUDIO_FEEDBACK:
+ description: >
+ Add feedback endpoint to speaker path. Speaker endpoint is then
+ asynchronous and device reports its actual sampling rate to host
+ (see tud_audio_feedback_params_cb()). Without feedback endpoint
+ speaker endpoint is adaptive and device has to follow host's rate.
+ value: 0
+ USBD_AUDIO_OUT_EP:
+ description: >
+ Speaker (OUT) isochronous endpoint number.
+ Empty for default: 8 on nRF5x (only isochronous endpoint),
+ 1 otherwise.
+ value:
+ USBD_AUDIO_IN_EP:
+ description: >
+ Microphone (IN) isochronous endpoint number.
+ Empty for default: 8 on nRF5x (only isochronous endpoint),
+ 1 otherwise.
+ value:
+ USBD_AUDIO_FEEDBACK_EP:
+ description: >
+ Feedback (IN) isochronous endpoint number, must differ from
+ USBD_AUDIO_IN_EP when both are used.
+ Empty for default: 8 on nRF5x, 2 otherwise.
+ value:
+ USBD_AUDIO_INT_EP:
+ description: >
+ Audio Control interrupt (IN) endpoint number used to notify host
+ about control changes. Empty for no interrupt endpoint.
+ value:
+ USBD_AUDIO_IN_BUFFER_PACKETS:
+ description: >
+ Size of TinyUSB software FIFO for microphone data in 1 ms
+ packets. TinyUSB flow control for IN endpoint requires at least 4.
+ value: 4
+ USBD_AUDIO_OUT_BUFFER_PACKETS:
+ description: >
+ Size of TinyUSB software FIFO for speaker data in 1 ms packets.
+ value: 4
+
USBD_WINDOWS_COMP_ID:
description: >
Add Windows compatibility descriptor.
(mynewt-core) 04/06: tinyusb: Move audio endpoint defaults to port tusb_hw.h
Posted by je...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
kasjer pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 8e56daa56cf8ed029a29f88e70e5a71ab2ad7d22
Author: Jerzy Kasenberg <je...@codecoup.pl>
AuthorDate: Thu Oct 8 07:57:16 2026 +0200
tinyusb: Move audio endpoint defaults to port tusb_hw.h
Audio isochronous endpoint defaults lived in std_descriptors
tusb_config.h as 1/0x81 (8 on nRF5x) and collided with CDC defaults
of every port as soon as USB console was enabled together with audio.
Define USBD_AUDIO_OUT_EP, USBD_AUDIO_IN_EP and USBD_AUDIO_FEEDBACK_EP
in each port's tusb_hw.h next to CDC, HID and MSC endpoints, with
numbers that stay clear of those where the controller has enough
endpoints:
- stm32_fsdev, pic32mz: 0x04/0x84/0x85
- synopsys, lpc55: 0x03/0x83/0x84, OTG_FS and LPC55 full speed
controllers have too few endpoints to avoid HID and MSC defaults
- da146xx: 0x03/0x83, feedback endpoint shares the IN endpoint
- nrf5x, nrf53: 0x08/0x88, the only isochronous endpoint pair
Syscfg values are now full endpoint addresses (0x8n for IN), same as
for other classes, and std_descriptors fails the build when a port
does not provide the defaults.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Jerzy Kasenberg <je...@codecoup.pl>
---
hw/usb/tinyusb/da146xx/include/tusb_hw.h | 23 ++++++++++++++
hw/usb/tinyusb/lpc55/include/tusb_hw.h | 22 ++++++++++++++
hw/usb/tinyusb/nrf53/include/tusb_hw.h | 23 ++++++++++++++
hw/usb/tinyusb/nrf5x/include/tusb_hw.h | 23 ++++++++++++++
hw/usb/tinyusb/pic32mz/include/tusb_hw.h | 22 ++++++++++++++
.../tinyusb/std_descriptors/include/tusb_config.h | 35 ++++++----------------
hw/usb/tinyusb/std_descriptors/syscfg.yml | 21 +++++++------
hw/usb/tinyusb/stm32_fsdev/include/tusb_hw.h | 22 ++++++++++++++
.../tinyusb/stm32_fsdev/stm32f3/include/tusb_hw.h | 22 ++++++++++++++
.../tinyusb/stm32_fsdev/stm32g0/include/tusb_hw.h | 22 ++++++++++++++
.../tinyusb/stm32_fsdev/stm32g4/include/tusb_hw.h | 22 ++++++++++++++
.../tinyusb/stm32_fsdev/stm32h5/include/tusb_hw.h | 22 ++++++++++++++
.../tinyusb/stm32_fsdev/stm32l0/include/tusb_hw.h | 22 ++++++++++++++
.../stm32_fsdev/stm32wb55/include/tusb_hw.h | 22 ++++++++++++++
hw/usb/tinyusb/synopsys/include/tusb_hw.h | 24 +++++++++++++++
15 files changed, 310 insertions(+), 37 deletions(-)
diff --git a/hw/usb/tinyusb/da146xx/include/tusb_hw.h b/hw/usb/tinyusb/da146xx/include/tusb_hw.h
index 54c48602f..518ecc819 100644
--- a/hw/usb/tinyusb/da146xx/include/tusb_hw.h
+++ b/hw/usb/tinyusb/da146xx/include/tusb_hw.h
@@ -126,4 +126,27 @@ void tusb_vbus_changed(bool present);
#define USBD_BTH_DATA_EP_SIZE 0x40
#endif
+/*
+ * Audio class isochronous endpoints. Controller has four endpoints,
+ * 3 is the last one free when CDC is present. Feedback endpoint shares
+ * the IN endpoint, so it can not be used together with microphone.
+ */
+#if defined(MYNEWT_VAL_USBD_AUDIO_OUT_EP)
+#define USBD_AUDIO_OUT_EP MYNEWT_VAL(USBD_AUDIO_OUT_EP)
+#else
+#define USBD_AUDIO_OUT_EP 0x03
+#endif
+
+#if defined(MYNEWT_VAL_USBD_AUDIO_IN_EP)
+#define USBD_AUDIO_IN_EP MYNEWT_VAL(USBD_AUDIO_IN_EP)
+#else
+#define USBD_AUDIO_IN_EP 0x83
+#endif
+
+#if defined(MYNEWT_VAL_USBD_AUDIO_FEEDBACK_EP)
+#define USBD_AUDIO_FEEDBACK_EP MYNEWT_VAL(USBD_AUDIO_FEEDBACK_EP)
+#else
+#define USBD_AUDIO_FEEDBACK_EP 0x83
+#endif
+
#endif
diff --git a/hw/usb/tinyusb/lpc55/include/tusb_hw.h b/hw/usb/tinyusb/lpc55/include/tusb_hw.h
index 27aa2a67f..45ed8093c 100644
--- a/hw/usb/tinyusb/lpc55/include/tusb_hw.h
+++ b/hw/usb/tinyusb/lpc55/include/tusb_hw.h
@@ -89,4 +89,26 @@
#define USBD_MSC_DATA_OUT_EP 0x04
#endif
+/*
+ * Audio class isochronous endpoints. Full speed controller has five
+ * endpoints, defaults are shared with HID (0x83) and MSC (0x84).
+ */
+#if defined(MYNEWT_VAL_USBD_AUDIO_OUT_EP)
+#define USBD_AUDIO_OUT_EP MYNEWT_VAL(USBD_AUDIO_OUT_EP)
+#else
+#define USBD_AUDIO_OUT_EP 0x03
+#endif
+
+#if defined(MYNEWT_VAL_USBD_AUDIO_IN_EP)
+#define USBD_AUDIO_IN_EP MYNEWT_VAL(USBD_AUDIO_IN_EP)
+#else
+#define USBD_AUDIO_IN_EP 0x83
+#endif
+
+#if defined(MYNEWT_VAL_USBD_AUDIO_FEEDBACK_EP)
+#define USBD_AUDIO_FEEDBACK_EP MYNEWT_VAL(USBD_AUDIO_FEEDBACK_EP)
+#else
+#define USBD_AUDIO_FEEDBACK_EP 0x84
+#endif
+
#endif
diff --git a/hw/usb/tinyusb/nrf53/include/tusb_hw.h b/hw/usb/tinyusb/nrf53/include/tusb_hw.h
index b7199e2cf..0268b592a 100644
--- a/hw/usb/tinyusb/nrf53/include/tusb_hw.h
+++ b/hw/usb/tinyusb/nrf53/include/tusb_hw.h
@@ -122,4 +122,27 @@
#define USBD_BTH_DATA_EP_SIZE 0x40
#endif
+/*
+ * Audio class isochronous endpoints, 8 is the only isochronous
+ * endpoint pair. Feedback endpoint shares the IN endpoint, so it can
+ * not be used together with microphone.
+ */
+#if defined(MYNEWT_VAL_USBD_AUDIO_OUT_EP)
+#define USBD_AUDIO_OUT_EP MYNEWT_VAL(USBD_AUDIO_OUT_EP)
+#else
+#define USBD_AUDIO_OUT_EP 0x08
+#endif
+
+#if defined(MYNEWT_VAL_USBD_AUDIO_IN_EP)
+#define USBD_AUDIO_IN_EP MYNEWT_VAL(USBD_AUDIO_IN_EP)
+#else
+#define USBD_AUDIO_IN_EP 0x88
+#endif
+
+#if defined(MYNEWT_VAL_USBD_AUDIO_FEEDBACK_EP)
+#define USBD_AUDIO_FEEDBACK_EP MYNEWT_VAL(USBD_AUDIO_FEEDBACK_EP)
+#else
+#define USBD_AUDIO_FEEDBACK_EP 0x88
+#endif
+
#endif
diff --git a/hw/usb/tinyusb/nrf5x/include/tusb_hw.h b/hw/usb/tinyusb/nrf5x/include/tusb_hw.h
index f4af8be16..075445d57 100755
--- a/hw/usb/tinyusb/nrf5x/include/tusb_hw.h
+++ b/hw/usb/tinyusb/nrf5x/include/tusb_hw.h
@@ -140,4 +140,27 @@
#define USBD_VENDOR_EP_SIZE 0x40
#endif
+/*
+ * Audio class isochronous endpoints, 8 is the only isochronous
+ * endpoint pair. Feedback endpoint shares the IN endpoint, so it can
+ * not be used together with microphone.
+ */
+#if defined(MYNEWT_VAL_USBD_AUDIO_OUT_EP)
+#define USBD_AUDIO_OUT_EP MYNEWT_VAL(USBD_AUDIO_OUT_EP)
+#else
+#define USBD_AUDIO_OUT_EP 0x08
+#endif
+
+#if defined(MYNEWT_VAL_USBD_AUDIO_IN_EP)
+#define USBD_AUDIO_IN_EP MYNEWT_VAL(USBD_AUDIO_IN_EP)
+#else
+#define USBD_AUDIO_IN_EP 0x88
+#endif
+
+#if defined(MYNEWT_VAL_USBD_AUDIO_FEEDBACK_EP)
+#define USBD_AUDIO_FEEDBACK_EP MYNEWT_VAL(USBD_AUDIO_FEEDBACK_EP)
+#else
+#define USBD_AUDIO_FEEDBACK_EP 0x88
+#endif
+
#endif
diff --git a/hw/usb/tinyusb/pic32mz/include/tusb_hw.h b/hw/usb/tinyusb/pic32mz/include/tusb_hw.h
index 8a8ae0c07..9dc67b475 100644
--- a/hw/usb/tinyusb/pic32mz/include/tusb_hw.h
+++ b/hw/usb/tinyusb/pic32mz/include/tusb_hw.h
@@ -91,4 +91,26 @@
#define USBD_MSC_DATA_OUT_EP 0x06
#endif
+/*
+ * Audio class isochronous endpoints, default numbers do not collide
+ * with CDC, HID and MSC defaults.
+ */
+#if defined(MYNEWT_VAL_USBD_AUDIO_OUT_EP)
+#define USBD_AUDIO_OUT_EP MYNEWT_VAL(USBD_AUDIO_OUT_EP)
+#else
+#define USBD_AUDIO_OUT_EP 0x04
+#endif
+
+#if defined(MYNEWT_VAL_USBD_AUDIO_IN_EP)
+#define USBD_AUDIO_IN_EP MYNEWT_VAL(USBD_AUDIO_IN_EP)
+#else
+#define USBD_AUDIO_IN_EP 0x84
+#endif
+
+#if defined(MYNEWT_VAL_USBD_AUDIO_FEEDBACK_EP)
+#define USBD_AUDIO_FEEDBACK_EP MYNEWT_VAL(USBD_AUDIO_FEEDBACK_EP)
+#else
+#define USBD_AUDIO_FEEDBACK_EP 0x85
+#endif
+
#endif
diff --git a/hw/usb/tinyusb/std_descriptors/include/tusb_config.h b/hw/usb/tinyusb/std_descriptors/include/tusb_config.h
index e2dab3951..6df605298 100755
--- a/hw/usb/tinyusb/std_descriptors/include/tusb_config.h
+++ b/hw/usb/tinyusb/std_descriptors/include/tusb_config.h
@@ -273,30 +273,13 @@ extern "C" {
#define USBD_AUDIO_IN_CHANNELS MYNEWT_VAL(USBD_AUDIO_IN_CHANNELS)
#define USBD_AUDIO_OUT_CHANNELS MYNEWT_VAL(USBD_AUDIO_OUT_CHANNELS)
-/* Endpoint addresses, isochronous endpoints on nRF5x are fixed to 8 */
-#if MYNEWT_VAL(USBD_AUDIO_OUT_EP)
-#define USBD_AUDIO_OUT_EP MYNEWT_VAL(USBD_AUDIO_OUT_EP)
-#elif CFG_TUSB_MCU == OPT_MCU_NRF5X
-#define USBD_AUDIO_OUT_EP 8
-#else
-#define USBD_AUDIO_OUT_EP 1
-#endif
-
-#if MYNEWT_VAL(USBD_AUDIO_IN_EP)
-#define USBD_AUDIO_IN_EP (0x80 | MYNEWT_VAL(USBD_AUDIO_IN_EP))
-#elif CFG_TUSB_MCU == OPT_MCU_NRF5X
-#define USBD_AUDIO_IN_EP (0x80 | 8)
-#else
-#define USBD_AUDIO_IN_EP (0x80 | 1)
-#endif
-
-#if MYNEWT_VAL(USBD_AUDIO_FEEDBACK_EP)
-#define USBD_AUDIO_FEEDBACK_EP \
- (0x80 | MYNEWT_VAL(USBD_AUDIO_FEEDBACK_EP))
-#elif CFG_TUSB_MCU == OPT_MCU_NRF5X
-#define USBD_AUDIO_FEEDBACK_EP (0x80 | 8)
-#else
-#define USBD_AUDIO_FEEDBACK_EP (0x80 | 2)
+/*
+ * Isochronous endpoint addresses are selected in port specific tusb_hw.h,
+ * where they can be kept apart from other classes' defaults.
+ */
+#if !defined(USBD_AUDIO_OUT_EP) || !defined(USBD_AUDIO_IN_EP) || \
+ !defined(USBD_AUDIO_FEEDBACK_EP)
+#error "USB port tusb_hw.h does not define audio endpoints"
#endif
#if MYNEWT_VAL(USBD_AUDIO_FEEDBACK) && CFG_TUD_AUDIO_ENABLE_EP_OUT
@@ -305,9 +288,9 @@ extern "C" {
#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0
#endif
-#if MYNEWT_VAL(USBD_AUDIO_INT_EP)
+#if defined(MYNEWT_VAL_USBD_AUDIO_INT_EP)
#define CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP 1
-#define USBD_AUDIO_INT_EP (0x80 | MYNEWT_VAL(USBD_AUDIO_INT_EP))
+#define USBD_AUDIO_INT_EP MYNEWT_VAL(USBD_AUDIO_INT_EP)
#else
#define CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP 0
#endif
diff --git a/hw/usb/tinyusb/std_descriptors/syscfg.yml b/hw/usb/tinyusb/std_descriptors/syscfg.yml
index b0650215a..bd8ec07b3 100644
--- a/hw/usb/tinyusb/std_descriptors/syscfg.yml
+++ b/hw/usb/tinyusb/std_descriptors/syscfg.yml
@@ -307,26 +307,25 @@ syscfg.defs:
value: 0
USBD_AUDIO_OUT_EP:
description: >
- Speaker (OUT) isochronous endpoint number.
- Empty for default: 8 on nRF5x (only isochronous endpoint),
- 1 otherwise.
+ Speaker (OUT) isochronous endpoint address (e.g. 0x04).
+ Empty for USB port default from tusb_hw.h.
value:
USBD_AUDIO_IN_EP:
description: >
- Microphone (IN) isochronous endpoint number.
- Empty for default: 8 on nRF5x (only isochronous endpoint),
- 1 otherwise.
+ Microphone (IN) isochronous endpoint address (e.g. 0x84).
+ Empty for USB port default from tusb_hw.h.
value:
USBD_AUDIO_FEEDBACK_EP:
description: >
- Feedback (IN) isochronous endpoint number, must differ from
- USBD_AUDIO_IN_EP when both are used.
- Empty for default: 8 on nRF5x, 2 otherwise.
+ Feedback (IN) isochronous endpoint address (e.g. 0x85), must
+ differ from USBD_AUDIO_IN_EP when both are used.
+ Empty for USB port default from tusb_hw.h.
value:
USBD_AUDIO_INT_EP:
description: >
- Audio Control interrupt (IN) endpoint number used to notify host
- about control changes. Empty for no interrupt endpoint.
+ Audio Control interrupt (IN) endpoint address (e.g. 0x86) used
+ to notify host about control changes. Empty for no interrupt
+ endpoint.
value:
USBD_AUDIO_IN_BUFFER_PACKETS:
description: >
diff --git a/hw/usb/tinyusb/stm32_fsdev/include/tusb_hw.h b/hw/usb/tinyusb/stm32_fsdev/include/tusb_hw.h
index c13a4ca32..f94ed9d97 100755
--- a/hw/usb/tinyusb/stm32_fsdev/include/tusb_hw.h
+++ b/hw/usb/tinyusb/stm32_fsdev/include/tusb_hw.h
@@ -86,4 +86,26 @@
#define USBD_MSC_DATA_OUT_EP 0x06
#endif
+/*
+ * Audio class isochronous endpoints, default numbers do not collide
+ * with CDC, HID and MSC defaults.
+ */
+#if defined(MYNEWT_VAL_USBD_AUDIO_OUT_EP)
+#define USBD_AUDIO_OUT_EP MYNEWT_VAL(USBD_AUDIO_OUT_EP)
+#else
+#define USBD_AUDIO_OUT_EP 0x04
+#endif
+
+#if defined(MYNEWT_VAL_USBD_AUDIO_IN_EP)
+#define USBD_AUDIO_IN_EP MYNEWT_VAL(USBD_AUDIO_IN_EP)
+#else
+#define USBD_AUDIO_IN_EP 0x84
+#endif
+
+#if defined(MYNEWT_VAL_USBD_AUDIO_FEEDBACK_EP)
+#define USBD_AUDIO_FEEDBACK_EP MYNEWT_VAL(USBD_AUDIO_FEEDBACK_EP)
+#else
+#define USBD_AUDIO_FEEDBACK_EP 0x85
+#endif
+
#endif
diff --git a/hw/usb/tinyusb/stm32_fsdev/stm32f3/include/tusb_hw.h b/hw/usb/tinyusb/stm32_fsdev/stm32f3/include/tusb_hw.h
index edc8aae55..94e4d8ab4 100644
--- a/hw/usb/tinyusb/stm32_fsdev/stm32f3/include/tusb_hw.h
+++ b/hw/usb/tinyusb/stm32_fsdev/stm32f3/include/tusb_hw.h
@@ -86,4 +86,26 @@
#define USBD_MSC_DATA_OUT_EP 0x06
#endif
+/*
+ * Audio class isochronous endpoints, default numbers do not collide
+ * with CDC, HID and MSC defaults.
+ */
+#if defined(MYNEWT_VAL_USBD_AUDIO_OUT_EP)
+#define USBD_AUDIO_OUT_EP MYNEWT_VAL(USBD_AUDIO_OUT_EP)
+#else
+#define USBD_AUDIO_OUT_EP 0x04
+#endif
+
+#if defined(MYNEWT_VAL_USBD_AUDIO_IN_EP)
+#define USBD_AUDIO_IN_EP MYNEWT_VAL(USBD_AUDIO_IN_EP)
+#else
+#define USBD_AUDIO_IN_EP 0x84
+#endif
+
+#if defined(MYNEWT_VAL_USBD_AUDIO_FEEDBACK_EP)
+#define USBD_AUDIO_FEEDBACK_EP MYNEWT_VAL(USBD_AUDIO_FEEDBACK_EP)
+#else
+#define USBD_AUDIO_FEEDBACK_EP 0x85
+#endif
+
#endif
diff --git a/hw/usb/tinyusb/stm32_fsdev/stm32g0/include/tusb_hw.h b/hw/usb/tinyusb/stm32_fsdev/stm32g0/include/tusb_hw.h
index 006253947..76e5cc65b 100644
--- a/hw/usb/tinyusb/stm32_fsdev/stm32g0/include/tusb_hw.h
+++ b/hw/usb/tinyusb/stm32_fsdev/stm32g0/include/tusb_hw.h
@@ -86,4 +86,26 @@
#define USBD_MSC_DATA_OUT_EP 0x06
#endif
+/*
+ * Audio class isochronous endpoints, default numbers do not collide
+ * with CDC, HID and MSC defaults.
+ */
+#if defined(MYNEWT_VAL_USBD_AUDIO_OUT_EP)
+#define USBD_AUDIO_OUT_EP MYNEWT_VAL(USBD_AUDIO_OUT_EP)
+#else
+#define USBD_AUDIO_OUT_EP 0x04
+#endif
+
+#if defined(MYNEWT_VAL_USBD_AUDIO_IN_EP)
+#define USBD_AUDIO_IN_EP MYNEWT_VAL(USBD_AUDIO_IN_EP)
+#else
+#define USBD_AUDIO_IN_EP 0x84
+#endif
+
+#if defined(MYNEWT_VAL_USBD_AUDIO_FEEDBACK_EP)
+#define USBD_AUDIO_FEEDBACK_EP MYNEWT_VAL(USBD_AUDIO_FEEDBACK_EP)
+#else
+#define USBD_AUDIO_FEEDBACK_EP 0x85
+#endif
+
#endif
diff --git a/hw/usb/tinyusb/stm32_fsdev/stm32g4/include/tusb_hw.h b/hw/usb/tinyusb/stm32_fsdev/stm32g4/include/tusb_hw.h
index 8d2c6c1ce..a27bbc38c 100644
--- a/hw/usb/tinyusb/stm32_fsdev/stm32g4/include/tusb_hw.h
+++ b/hw/usb/tinyusb/stm32_fsdev/stm32g4/include/tusb_hw.h
@@ -86,4 +86,26 @@
#define USBD_MSC_DATA_OUT_EP 0x06
#endif
+/*
+ * Audio class isochronous endpoints, default numbers do not collide
+ * with CDC, HID and MSC defaults.
+ */
+#if defined(MYNEWT_VAL_USBD_AUDIO_OUT_EP)
+#define USBD_AUDIO_OUT_EP MYNEWT_VAL(USBD_AUDIO_OUT_EP)
+#else
+#define USBD_AUDIO_OUT_EP 0x04
+#endif
+
+#if defined(MYNEWT_VAL_USBD_AUDIO_IN_EP)
+#define USBD_AUDIO_IN_EP MYNEWT_VAL(USBD_AUDIO_IN_EP)
+#else
+#define USBD_AUDIO_IN_EP 0x84
+#endif
+
+#if defined(MYNEWT_VAL_USBD_AUDIO_FEEDBACK_EP)
+#define USBD_AUDIO_FEEDBACK_EP MYNEWT_VAL(USBD_AUDIO_FEEDBACK_EP)
+#else
+#define USBD_AUDIO_FEEDBACK_EP 0x85
+#endif
+
#endif
diff --git a/hw/usb/tinyusb/stm32_fsdev/stm32h5/include/tusb_hw.h b/hw/usb/tinyusb/stm32_fsdev/stm32h5/include/tusb_hw.h
index 163c7bebc..2043dfe5c 100644
--- a/hw/usb/tinyusb/stm32_fsdev/stm32h5/include/tusb_hw.h
+++ b/hw/usb/tinyusb/stm32_fsdev/stm32h5/include/tusb_hw.h
@@ -86,4 +86,26 @@
#define USBD_MSC_DATA_OUT_EP 0x06
#endif
+/*
+ * Audio class isochronous endpoints, default numbers do not collide
+ * with CDC, HID and MSC defaults.
+ */
+#if defined(MYNEWT_VAL_USBD_AUDIO_OUT_EP)
+#define USBD_AUDIO_OUT_EP MYNEWT_VAL(USBD_AUDIO_OUT_EP)
+#else
+#define USBD_AUDIO_OUT_EP 0x04
+#endif
+
+#if defined(MYNEWT_VAL_USBD_AUDIO_IN_EP)
+#define USBD_AUDIO_IN_EP MYNEWT_VAL(USBD_AUDIO_IN_EP)
+#else
+#define USBD_AUDIO_IN_EP 0x84
+#endif
+
+#if defined(MYNEWT_VAL_USBD_AUDIO_FEEDBACK_EP)
+#define USBD_AUDIO_FEEDBACK_EP MYNEWT_VAL(USBD_AUDIO_FEEDBACK_EP)
+#else
+#define USBD_AUDIO_FEEDBACK_EP 0x85
+#endif
+
#endif
diff --git a/hw/usb/tinyusb/stm32_fsdev/stm32l0/include/tusb_hw.h b/hw/usb/tinyusb/stm32_fsdev/stm32l0/include/tusb_hw.h
index 889c02e50..6079f0999 100644
--- a/hw/usb/tinyusb/stm32_fsdev/stm32l0/include/tusb_hw.h
+++ b/hw/usb/tinyusb/stm32_fsdev/stm32l0/include/tusb_hw.h
@@ -86,4 +86,26 @@
#define USBD_MSC_DATA_OUT_EP 0x06
#endif
+/*
+ * Audio class isochronous endpoints, default numbers do not collide
+ * with CDC, HID and MSC defaults.
+ */
+#if defined(MYNEWT_VAL_USBD_AUDIO_OUT_EP)
+#define USBD_AUDIO_OUT_EP MYNEWT_VAL(USBD_AUDIO_OUT_EP)
+#else
+#define USBD_AUDIO_OUT_EP 0x04
+#endif
+
+#if defined(MYNEWT_VAL_USBD_AUDIO_IN_EP)
+#define USBD_AUDIO_IN_EP MYNEWT_VAL(USBD_AUDIO_IN_EP)
+#else
+#define USBD_AUDIO_IN_EP 0x84
+#endif
+
+#if defined(MYNEWT_VAL_USBD_AUDIO_FEEDBACK_EP)
+#define USBD_AUDIO_FEEDBACK_EP MYNEWT_VAL(USBD_AUDIO_FEEDBACK_EP)
+#else
+#define USBD_AUDIO_FEEDBACK_EP 0x85
+#endif
+
#endif
diff --git a/hw/usb/tinyusb/stm32_fsdev/stm32wb55/include/tusb_hw.h b/hw/usb/tinyusb/stm32_fsdev/stm32wb55/include/tusb_hw.h
index 7de145950..9200c851e 100644
--- a/hw/usb/tinyusb/stm32_fsdev/stm32wb55/include/tusb_hw.h
+++ b/hw/usb/tinyusb/stm32_fsdev/stm32wb55/include/tusb_hw.h
@@ -86,4 +86,26 @@
#define USBD_MSC_DATA_OUT_EP 0x06
#endif
+/*
+ * Audio class isochronous endpoints, default numbers do not collide
+ * with CDC, HID and MSC defaults.
+ */
+#if defined(MYNEWT_VAL_USBD_AUDIO_OUT_EP)
+#define USBD_AUDIO_OUT_EP MYNEWT_VAL(USBD_AUDIO_OUT_EP)
+#else
+#define USBD_AUDIO_OUT_EP 0x04
+#endif
+
+#if defined(MYNEWT_VAL_USBD_AUDIO_IN_EP)
+#define USBD_AUDIO_IN_EP MYNEWT_VAL(USBD_AUDIO_IN_EP)
+#else
+#define USBD_AUDIO_IN_EP 0x84
+#endif
+
+#if defined(MYNEWT_VAL_USBD_AUDIO_FEEDBACK_EP)
+#define USBD_AUDIO_FEEDBACK_EP MYNEWT_VAL(USBD_AUDIO_FEEDBACK_EP)
+#else
+#define USBD_AUDIO_FEEDBACK_EP 0x85
+#endif
+
#endif
diff --git a/hw/usb/tinyusb/synopsys/include/tusb_hw.h b/hw/usb/tinyusb/synopsys/include/tusb_hw.h
index 7cd7ccb9e..325fc7600 100755
--- a/hw/usb/tinyusb/synopsys/include/tusb_hw.h
+++ b/hw/usb/tinyusb/synopsys/include/tusb_hw.h
@@ -100,4 +100,28 @@
#define USBD_MSC_DATA_OUT_EP 0x03
#endif
+/*
+ * Audio class isochronous endpoints. OTG_FS cores have only four
+ * endpoints, 3 is the last one free when CDC is present and IN endpoint
+ * is shared with HID and MSC defaults. Feedback endpoint default
+ * requires OTG_HS core.
+ */
+#if defined(MYNEWT_VAL_USBD_AUDIO_OUT_EP)
+#define USBD_AUDIO_OUT_EP MYNEWT_VAL(USBD_AUDIO_OUT_EP)
+#else
+#define USBD_AUDIO_OUT_EP 0x03
+#endif
+
+#if defined(MYNEWT_VAL_USBD_AUDIO_IN_EP)
+#define USBD_AUDIO_IN_EP MYNEWT_VAL(USBD_AUDIO_IN_EP)
+#else
+#define USBD_AUDIO_IN_EP 0x83
+#endif
+
+#if defined(MYNEWT_VAL_USBD_AUDIO_FEEDBACK_EP)
+#define USBD_AUDIO_FEEDBACK_EP MYNEWT_VAL(USBD_AUDIO_FEEDBACK_EP)
+#else
+#define USBD_AUDIO_FEEDBACK_EP 0x84
+#endif
+
#endif
(mynewt-core) 05/06: tinyusb/nrf5x: Enable nrfx CLOCK driver required by TinyUSB
Posted by je...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
kasjer pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 6e5cca39a2d30183fa2bf8ded481091defefaec3
Author: Jerzy Kasenberg <je...@codecoup.pl>
AuthorDate: Thu Oct 8 08:43:28 2026 +0200
tinyusb/nrf5x: Enable nrfx CLOCK driver required by TinyUSB
TinyUSB nRF5x device driver (dcd_nrf5x.c) includes nrfx_clock.h
unconditionally and nrfx refuses that header unless its CLOCK or
POWER driver is enabled:
nrfx_power_clock.h:57:6: error: #error "This code is not supposed
to be compiled when neither POWER nor CLOCK is enabled."
nRF5340 MCU package enables NRFX_CLOCK by default so nrf53 port was
not affected, nRF52 packages do not. Enable it from the USB port
package so every nRF52 target with USB builds without touching its
own syscfg.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Jerzy Kasenberg <je...@codecoup.pl>
---
hw/usb/tinyusb/nrf5x/syscfg.yml | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/hw/usb/tinyusb/nrf5x/syscfg.yml b/hw/usb/tinyusb/nrf5x/syscfg.yml
new file mode 100644
index 000000000..ee962854d
--- /dev/null
+++ b/hw/usb/tinyusb/nrf5x/syscfg.yml
@@ -0,0 +1,23 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# TinyUSB nRF5x device driver includes nrfx_clock.h, which nrfx accepts
+# only when its CLOCK (or POWER) driver is enabled.
+syscfg.vals:
+ NRFX_CLOCK_ENABLED: 1