summaryrefslogtreecommitdiff
path: root/src/class/midi/midi2_device.c
diff options
context:
space:
mode:
authorSaulo VerĂ­ssimo <[email protected]>2026-05-16 12:59:44 -0300
committerSaulo VerĂ­ssimo <[email protected]>2026-05-16 12:59:44 -0300
commit840f3e0a628e69a2b7fb4136b2dca8ab5b350f83 (patch)
treed1bd9c4b2d6fb8a8d54d630f7b613611ded70ca1 /src/class/midi/midi2_device.c
parent0af0665ed65ef9574a4c3c2da83c1c502cb713de (diff)
midi2: prevent UMP packet split across USB transfers
The edpt_stream auto-flush is byte-oriented and could cut an UMP message in half when the FIFO reached wMaxPacketSize, corrupting the peer's RX context. Pre-flush whole packets before writing one that would cross the boundary on both device (tud_midi2_n_ump_write) and host (tuh_midi2_ump_write) paths. Host write also becomes packet-aware instead of word-by-word. Ref #3571
Diffstat (limited to 'src/class/midi/midi2_device.c')
-rw-r--r--src/class/midi/midi2_device.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/src/class/midi/midi2_device.c b/src/class/midi/midi2_device.c
index f7d338ede..a005c8e51 100644
--- a/src/class/midi/midi2_device.c
+++ b/src/class/midi/midi2_device.c
@@ -347,11 +347,20 @@ uint32_t tud_midi2_n_ump_write(uint8_t itf, const uint32_t* words, uint32_t coun
while (written < count) {
uint8_t mt = (uint8_t)((words[written] >> 28) & 0x0F);
uint8_t pkt_words = midi2_ump_word_count(mt);
+ uint32_t pkt_bytes = (uint32_t)pkt_words * 4;
if (written + pkt_words > count) break;
- if (tu_edpt_stream_write_available(ep_tx) < pkt_words * 4) break;
+ if (tu_edpt_stream_write_available(ep_tx) < pkt_bytes) break;
+
+ // Flush whole packets already queued before adding one that would cross
+ // the wMaxPacketSize boundary. Prevents an UMP message from being split
+ // across two USB transfers, which would corrupt the host RX context.
+ uint16_t ff_count = tu_fifo_count(&ep_tx->ff);
+ if (ff_count > 0 && ff_count + pkt_bytes > ep_tx->mps) {
+ tu_edpt_stream_write_xfer(ep_tx);
+ }
- tu_edpt_stream_write(ep_tx, &words[written], pkt_words * 4);
+ tu_edpt_stream_write(ep_tx, &words[written], pkt_bytes);
written += pkt_words;
}