summaryrefslogtreecommitdiff
path: root/src/class/midi
diff options
context:
space:
mode:
authorHiFiPhile <[email protected]>2025-09-12 15:49:40 +0200
committerHiFiPhile <[email protected]>2025-09-12 15:49:40 +0200
commitfad3dc492630a6a31a38b3340f506849ef3679ff (patch)
tree5ab1fef9daf657c1b3f1b7e238e02eb78e1b14cf /src/class/midi
parent4ae433fa6ef451cccb2b09aa3748978b46aade5f (diff)
parent2027ac246791caa9f1dc03e9727b60d90bee0f2d (diff)
Merge branch 'master' into sb-ep
Diffstat (limited to 'src/class/midi')
-rw-r--r--src/class/midi/midi_host.c33
1 files changed, 30 insertions, 3 deletions
diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c
index cd6e115ee..e6ace316c 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;
@@ -558,6 +575,11 @@ uint32_t tuh_midi_stream_read(uint8_t idx, uint8_t *p_cable_num, uint8_t *p_buff
}
}
}
+ else {
+ // bad packet discard
+ nread = tu_edpt_stream_read(p_midi->daddr, &p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4);
+ continue;
+ }
} else if (status < MIDI_STATUS_SYSEX_START) {
// then it is a channel message either three bytes or two
uint8_t fake_cin = (status & 0xf0) >> 4;
@@ -600,6 +622,11 @@ uint32_t tuh_midi_stream_read(uint8_t idx, uint8_t *p_cable_num, uint8_t *p_buff
bytes_to_add_to_stream = 1;
}
}
+ else {
+ // bad packet discard
+ nread = tu_edpt_stream_read(p_midi->daddr, &p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4);
+ continue;
+ }
for (uint8_t i = 1; i <= bytes_to_add_to_stream; i++) {
*p_buffer++ = p_midi->stream_read.buffer[i];