Skip to content

Commit 8f46021

Browse files
authored
Merge pull request #3183 from rppicomidi/fix_3159
Fix #3159: Handle MIDI interface after audio streaming interface
2 parents 60f075d + 12a1d0e commit 8f46021

File tree

4 files changed

+59
-44
lines changed

4 files changed

+59
-44
lines changed

src/class/midi/midi_host.c

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,14 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d
211211
desc_cb.jack_num = 0;
212212

213213
// There can be just a MIDI or an Audio + MIDI interface
214-
// If there is Audio Control Interface + Audio Header descriptor, skip it
214+
// - If there is Audio Control Interface + Audio Header descriptor, then skip it.
215+
// - If there is an Audio Control Interface + Audio Streaming Interface, then ignore the Audio Streaming Interface.
216+
// Future:
217+
// Note that if this driver is used with an USB Audio Streaming host driver,
218+
// then call that driver first. If the MIDI interface comes before the
219+
// audio streaming interface, then the audio driver will have to call this
220+
// driver after parsing the audio control interface and then resume parsing
221+
// the streaming audio interface.
215222
if (AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass) {
216223
TU_VERIFY(max_len > 2*sizeof(tusb_desc_interface_t) + sizeof(audio_desc_cs_ac_interface_t));
217224

@@ -222,8 +229,18 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d
222229

223230
p_desc = tu_desc_next(p_desc);
224231
desc_itf = (const tusb_desc_interface_t *)p_desc;
225-
TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass);
226232
p_midi->itf_count = 1;
233+
// skip non-interface and non-midi streaming descriptors
234+
while (tu_desc_in_bounds(p_desc, p_end) &&
235+
(desc_itf->bDescriptorType != TUSB_DESC_INTERFACE || (desc_itf->bInterfaceClass == TUSB_CLASS_AUDIO && desc_itf->bInterfaceSubClass != AUDIO_SUBCLASS_MIDI_STREAMING))) {
236+
if (desc_itf->bDescriptorType == TUSB_DESC_INTERFACE && desc_itf->bAlternateSetting == 0) {
237+
p_midi->itf_count++;
238+
}
239+
p_desc = tu_desc_next(p_desc);
240+
desc_itf = (tusb_desc_interface_t const *)p_desc;
241+
}
242+
TU_VERIFY(p_desc < p_end); // TODO: If MIDI interface comes after Audio Streaming, then max_len did not include the MIDI interface descriptor
243+
TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass);
227244
}
228245
TU_VERIFY(AUDIO_SUBCLASS_MIDI_STREAMING == desc_itf->bInterfaceSubClass);
229246

@@ -236,7 +253,7 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d
236253
p_desc = tu_desc_next(p_desc); // next to CS Header
237254

238255
bool found_new_interface = false;
239-
while ((p_desc < p_end) && (tu_desc_next(p_desc) <= p_end) && !found_new_interface) {
256+
while (tu_desc_in_bounds(p_desc, p_end) && !found_new_interface) {
240257
switch (tu_desc_type(p_desc)) {
241258
case TUSB_DESC_INTERFACE:
242259
found_new_interface = true;

src/class/vendor/vendor_device.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uin
211211
TU_VERIFY(p_vendor, 0);
212212

213213
p_vendor->itf_num = desc_itf->bInterfaceNumber;
214-
while (tu_desc_is_valid(p_desc, desc_end)) {
214+
while (tu_desc_in_bounds(p_desc, desc_end)) {
215215
const uint8_t desc_type = tu_desc_type(p_desc);
216216
if (desc_type == TUSB_DESC_INTERFACE || desc_type == TUSB_DESC_INTERFACE_ASSOCIATION) {
217217
break; // end of this interface

src/common/tusb_common.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,44 @@ TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void *mem, uint16_
324324
+ TU_BIN8(dlsb))
325325
#endif
326326

327+
//--------------------------------------------------------------------+
328+
// Descriptor helper
329+
//--------------------------------------------------------------------+
330+
331+
// return next descriptor
332+
TU_ATTR_ALWAYS_INLINE static inline uint8_t const * tu_desc_next(void const* desc) {
333+
uint8_t const* desc8 = (uint8_t const*) desc;
334+
return desc8 + desc8[DESC_OFFSET_LEN];
335+
}
336+
337+
// get descriptor length
338+
TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_len(void const* desc) {
339+
return ((uint8_t const*) desc)[DESC_OFFSET_LEN];
340+
}
341+
342+
// get descriptor type
343+
TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_type(void const* desc) {
344+
return ((uint8_t const*) desc)[DESC_OFFSET_TYPE];
345+
}
346+
347+
// get descriptor subtype
348+
TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_subtype(void const* desc) {
349+
return ((uint8_t const*) desc)[DESC_OFFSET_SUBTYPE];
350+
}
351+
352+
TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_in_bounds(uint8_t const* p_desc, uint8_t const* desc_end) {
353+
return (p_desc < desc_end) && (tu_desc_next(p_desc) <= desc_end);
354+
}
355+
356+
// find descriptor that match byte1 (type)
357+
uint8_t const * tu_desc_find(uint8_t const* desc, uint8_t const* end, uint8_t byte1);
358+
359+
// find descriptor that match byte1 (type) and byte2
360+
uint8_t const * tu_desc_find2(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2);
361+
362+
// find descriptor that match byte1 (type) and byte2
363+
uint8_t const * tu_desc_find3(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2, uint8_t byte3);
364+
327365
#ifdef __cplusplus
328366
}
329367
#endif

src/common/tusb_types.h

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -562,46 +562,6 @@ TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_type_str(tusb_xfer_type_
562562
}
563563
#endif
564564

565-
//--------------------------------------------------------------------+
566-
// Descriptor helper
567-
//--------------------------------------------------------------------+
568-
569-
// return next descriptor
570-
TU_ATTR_ALWAYS_INLINE static inline uint8_t const * tu_desc_next(void const* desc) {
571-
uint8_t const* desc8 = (uint8_t const*) desc;
572-
return desc8 + desc8[DESC_OFFSET_LEN];
573-
}
574-
575-
// get descriptor length
576-
TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_len(void const* desc) {
577-
return ((uint8_t const*) desc)[DESC_OFFSET_LEN];
578-
}
579-
580-
// get descriptor type
581-
TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_type(void const* desc) {
582-
return ((uint8_t const*) desc)[DESC_OFFSET_TYPE];
583-
}
584-
585-
// get descriptor subtype
586-
TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_subtype(void const* desc) {
587-
return ((uint8_t const*) desc)[DESC_OFFSET_SUBTYPE];
588-
}
589-
590-
TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_is_valid(void const* desc, uint8_t const* desc_end) {
591-
const uint8_t* desc8 = (uint8_t const*) desc;
592-
return (desc8 < desc_end) && (tu_desc_next(desc) <= desc_end);
593-
}
594-
595-
596-
// find descriptor that match byte1 (type)
597-
uint8_t const * tu_desc_find(uint8_t const* desc, uint8_t const* end, uint8_t byte1);
598-
599-
// find descriptor that match byte1 (type) and byte2
600-
uint8_t const * tu_desc_find2(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2);
601-
602-
// find descriptor that match byte1 (type) and byte2
603-
uint8_t const * tu_desc_find3(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2, uint8_t byte3);
604-
605565
#ifdef __cplusplus
606566
}
607567
#endif

0 commit comments

Comments
 (0)