summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHa Thach <[email protected]>2025-08-02 20:34:25 +0700
committerGitHub <[email protected]>2025-08-02 20:34:25 +0700
commit8f46021eba3a93dd95e8272ab0ac223fdfe6c881 (patch)
treefb87cfd20a01184b19ce6f586e4729123ded27b5 /src
parent60f075db6516f7d2481dd77c86237b22c50d3c3f (diff)
parent12a1d0e7ede97c793a5e11b3cce7284cdbe994c8 (diff)
Merge pull request #3183 from rppicomidi/fix_3159
Fix #3159: Handle MIDI interface after audio streaming interface
Diffstat (limited to 'src')
-rw-r--r--src/class/midi/midi_host.c23
-rw-r--r--src/class/vendor/vendor_device.c2
-rw-r--r--src/common/tusb_common.h38
-rw-r--r--src/common/tusb_types.h40
4 files changed, 59 insertions, 44 deletions
diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c
index cd6e115ee..50bda1e36 100644
--- a/src/class/midi/midi_host.c
+++ b/src/class/midi/midi_host.c
@@ -211,7 +211,14 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d
desc_cb.jack_num = 0;
// There can be just a MIDI or an Audio + MIDI interface
- // If there is Audio Control Interface + Audio Header descriptor, skip it
+ // - If there is Audio Control Interface + Audio Header descriptor, then skip it.
+ // - If there is an Audio Control Interface + Audio Streaming Interface, then ignore the Audio Streaming Interface.
+ // Future:
+ // Note that if this driver is used with an USB Audio Streaming host driver,
+ // then call that driver first. If the MIDI interface comes before the
+ // audio streaming interface, then the audio driver will have to call this
+ // driver after parsing the audio control interface and then resume parsing
+ // the streaming audio interface.
if (AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass) {
TU_VERIFY(max_len > 2*sizeof(tusb_desc_interface_t) + sizeof(audio_desc_cs_ac_interface_t));
@@ -222,8 +229,18 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d
p_desc = tu_desc_next(p_desc);
desc_itf = (const tusb_desc_interface_t *)p_desc;
- TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass);
p_midi->itf_count = 1;
+ // skip non-interface and non-midi streaming descriptors
+ while (tu_desc_in_bounds(p_desc, p_end) &&
+ (desc_itf->bDescriptorType != TUSB_DESC_INTERFACE || (desc_itf->bInterfaceClass == TUSB_CLASS_AUDIO && desc_itf->bInterfaceSubClass != AUDIO_SUBCLASS_MIDI_STREAMING))) {
+ if (desc_itf->bDescriptorType == TUSB_DESC_INTERFACE && desc_itf->bAlternateSetting == 0) {
+ p_midi->itf_count++;
+ }
+ p_desc = tu_desc_next(p_desc);
+ desc_itf = (tusb_desc_interface_t const *)p_desc;
+ }
+ TU_VERIFY(p_desc < p_end); // TODO: If MIDI interface comes after Audio Streaming, then max_len did not include the MIDI interface descriptor
+ TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass);
}
TU_VERIFY(AUDIO_SUBCLASS_MIDI_STREAMING == desc_itf->bInterfaceSubClass);
@@ -236,7 +253,7 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d
p_desc = tu_desc_next(p_desc); // next to CS Header
bool found_new_interface = false;
- while ((p_desc < p_end) && (tu_desc_next(p_desc) <= p_end) && !found_new_interface) {
+ while (tu_desc_in_bounds(p_desc, p_end) && !found_new_interface) {
switch (tu_desc_type(p_desc)) {
case TUSB_DESC_INTERFACE:
found_new_interface = true;
diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c
index 6f109c321..b0332b0fe 100644
--- a/src/class/vendor/vendor_device.c
+++ b/src/class/vendor/vendor_device.c
@@ -211,7 +211,7 @@ uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uin
TU_VERIFY(p_vendor, 0);
p_vendor->itf_num = desc_itf->bInterfaceNumber;
- while (tu_desc_is_valid(p_desc, desc_end)) {
+ while (tu_desc_in_bounds(p_desc, desc_end)) {
const uint8_t desc_type = tu_desc_type(p_desc);
if (desc_type == TUSB_DESC_INTERFACE || desc_type == TUSB_DESC_INTERFACE_ASSOCIATION) {
break; // end of this interface
diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h
index 0351a3d8f..489e09a15 100644
--- a/src/common/tusb_common.h
+++ b/src/common/tusb_common.h
@@ -324,6 +324,44 @@ TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void *mem, uint16_
+ TU_BIN8(dlsb))
#endif
+//--------------------------------------------------------------------+
+// Descriptor helper
+//--------------------------------------------------------------------+
+
+// return next descriptor
+TU_ATTR_ALWAYS_INLINE static inline uint8_t const * tu_desc_next(void const* desc) {
+ uint8_t const* desc8 = (uint8_t const*) desc;
+ return desc8 + desc8[DESC_OFFSET_LEN];
+}
+
+// get descriptor length
+TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_len(void const* desc) {
+ return ((uint8_t const*) desc)[DESC_OFFSET_LEN];
+}
+
+// get descriptor type
+TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_type(void const* desc) {
+ return ((uint8_t const*) desc)[DESC_OFFSET_TYPE];
+}
+
+// get descriptor subtype
+TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_subtype(void const* desc) {
+ return ((uint8_t const*) desc)[DESC_OFFSET_SUBTYPE];
+}
+
+TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_in_bounds(uint8_t const* p_desc, uint8_t const* desc_end) {
+ return (p_desc < desc_end) && (tu_desc_next(p_desc) <= desc_end);
+}
+
+// find descriptor that match byte1 (type)
+uint8_t const * tu_desc_find(uint8_t const* desc, uint8_t const* end, uint8_t byte1);
+
+// find descriptor that match byte1 (type) and byte2
+uint8_t const * tu_desc_find2(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2);
+
+// find descriptor that match byte1 (type) and byte2
+uint8_t const * tu_desc_find3(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2, uint8_t byte3);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h
index ee97069bd..b3ef1e9c9 100644
--- a/src/common/tusb_types.h
+++ b/src/common/tusb_types.h
@@ -562,46 +562,6 @@ TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_type_str(tusb_xfer_type_
}
#endif
-//--------------------------------------------------------------------+
-// Descriptor helper
-//--------------------------------------------------------------------+
-
-// return next descriptor
-TU_ATTR_ALWAYS_INLINE static inline uint8_t const * tu_desc_next(void const* desc) {
- uint8_t const* desc8 = (uint8_t const*) desc;
- return desc8 + desc8[DESC_OFFSET_LEN];
-}
-
-// get descriptor length
-TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_len(void const* desc) {
- return ((uint8_t const*) desc)[DESC_OFFSET_LEN];
-}
-
-// get descriptor type
-TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_type(void const* desc) {
- return ((uint8_t const*) desc)[DESC_OFFSET_TYPE];
-}
-
-// get descriptor subtype
-TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_subtype(void const* desc) {
- return ((uint8_t const*) desc)[DESC_OFFSET_SUBTYPE];
-}
-
-TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_is_valid(void const* desc, uint8_t const* desc_end) {
- const uint8_t* desc8 = (uint8_t const*) desc;
- return (desc8 < desc_end) && (tu_desc_next(desc) <= desc_end);
-}
-
-
-// find descriptor that match byte1 (type)
-uint8_t const * tu_desc_find(uint8_t const* desc, uint8_t const* end, uint8_t byte1);
-
-// find descriptor that match byte1 (type) and byte2
-uint8_t const * tu_desc_find2(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2);
-
-// find descriptor that match byte1 (type) and byte2
-uint8_t const * tu_desc_find3(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2, uint8_t byte3);
-
#ifdef __cplusplus
}
#endif