summaryrefslogtreecommitdiff
path: root/src/class/midi/midi_host.c
diff options
context:
space:
mode:
authorHiFiPhile <[email protected]>2026-06-22 21:30:58 +0200
committerHiFiPhile <[email protected]>2026-06-22 21:30:58 +0200
commit693cdce08e14833f26f4e8a1f26e4fd546be4c35 (patch)
tree7667d2223dc32d9f21b5b60ab200e64ed46e3e20 /src/class/midi/midi_host.c
parent41e9eaa65a935136085d78ec4b99c81ff991b560 (diff)
parentcd3561bf158afd5a5718904b8139a338d1e3b67c (diff)
Merge remote-tracking branch 'tinyusb/master' into pr-osal-spin-deinit
Signed-off-by: HiFiPhile <[email protected]>
Diffstat (limited to 'src/class/midi/midi_host.c')
-rw-r--r--src/class/midi/midi_host.c144
1 files changed, 76 insertions, 68 deletions
diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c
index e6ace316c..a53546404 100644
--- a/src/class/midi/midi_host.c
+++ b/src/class/midi/midi_host.c
@@ -57,10 +57,7 @@ typedef struct {
uint8_t daddr;
uint8_t bInterfaceNumber; // interface number of MIDI streaming
uint8_t iInterface;
- uint8_t itf_count; // number of interface including Audio Control + MIDI streaming
-
- uint8_t ep_in; // IN endpoint address
- uint8_t ep_out; // OUT endpoint address
+ uint8_t itf_count; // number of interfaces including Audio Control + MIDI streaming
uint8_t rx_cable_count; // IN endpoint CS descriptor bNumEmbMIDIJack value
uint8_t tx_cable_count; // OUT endpoint CS descriptor bNumEmbMIDIJack value
@@ -86,8 +83,8 @@ typedef struct {
}midih_interface_t;
typedef struct {
- TUH_EPBUF_DEF(tx, TUH_EPSIZE_BULK_MPS);
- TUH_EPBUF_DEF(rx, TUH_EPSIZE_BULK_MPS);
+ TUH_EPBUF_DEF(tx, TUH_EPSIZE_BULK_MAX);
+ TUH_EPBUF_DEF(rx, TUH_EPSIZE_BULK_MAX);
} midih_epbuf_t;
static midih_interface_t _midi_host[CFG_TUH_MIDI];
@@ -124,9 +121,9 @@ bool midih_init(void) {
for (int inst = 0; inst < CFG_TUH_MIDI; inst++) {
midih_interface_t *p_midi_host = &_midi_host[inst];
tu_edpt_stream_init(&p_midi_host->ep_stream.rx, true, false, false,
- p_midi_host->ep_stream.rx_ff_buf, CFG_TUH_MIDI_RX_BUFSIZE, _midi_epbuf->rx, TUH_EPSIZE_BULK_MPS);
+ p_midi_host->ep_stream.rx_ff_buf, CFG_TUH_MIDI_RX_BUFSIZE, _midi_epbuf[inst].rx);
tu_edpt_stream_init(&p_midi_host->ep_stream.tx, true, true, false,
- p_midi_host->ep_stream.tx_ff_buf, CFG_TUH_MIDI_TX_BUFSIZE, _midi_epbuf->tx, TUH_EPSIZE_BULK_MPS);
+ p_midi_host->ep_stream.tx_ff_buf, CFG_TUH_MIDI_TX_BUFSIZE, _midi_epbuf[inst].tx);
}
return true;
}
@@ -147,8 +144,6 @@ void midih_close(uint8_t daddr) {
TU_LOG_DRV(" MIDI close addr = %u index = %u\r\n", daddr, idx);
tuh_midi_umount_cb(idx);
- p_midi->ep_in = 0;
- p_midi->ep_out = 0;
p_midi->bInterfaceNumber = 0;
p_midi->rx_cable_count = 0;
p_midi->tx_cable_count = 0;
@@ -169,23 +164,25 @@ bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint
const uint8_t idx = get_idx_by_ep_addr(dev_addr, ep_addr);
TU_VERIFY(idx < CFG_TUH_MIDI);
midih_interface_t *p_midi = &_midi_host[idx];
+ tu_edpt_stream_t *ep_str_rx = &p_midi->ep_stream.rx;
+ tu_edpt_stream_t *ep_str_tx = &p_midi->ep_stream.tx;
- if (ep_addr == p_midi->ep_stream.rx.ep_addr) {
+ if (ep_addr == ep_str_rx->ep_addr) {
// receive new data, put it into FIFO and invoke callback if available
// Note: some devices send back all zero packets even if there is no data ready
- if (xferred_bytes && !tu_mem_is_zero(p_midi->ep_stream.rx.ep_buf, xferred_bytes)) {
- tu_edpt_stream_read_xfer_complete(&p_midi->ep_stream.rx, xferred_bytes);
+ if (xferred_bytes && !tu_mem_is_zero(ep_str_rx->ep_buf, xferred_bytes)) {
+ tu_edpt_stream_read_xfer_complete(ep_str_rx, xferred_bytes);
tuh_midi_rx_cb(idx, xferred_bytes);
}
- tu_edpt_stream_read_xfer(dev_addr, &p_midi->ep_stream.rx); // prepare for next transfer
- } else if (ep_addr == p_midi->ep_stream.tx.ep_addr) {
+ tu_edpt_stream_read_xfer(ep_str_rx); // prepare for next transfer
+ } else if (ep_addr == ep_str_tx->ep_addr) {
tuh_midi_tx_cb(idx, xferred_bytes);
- if (0 == tu_edpt_stream_write_xfer(dev_addr, &p_midi->ep_stream.tx)) {
+ if (0 == tu_edpt_stream_write_xfer(ep_str_tx)) {
// If there is no data left, a ZLP should be sent if
// xferred_bytes is multiple of EP size and not zero
- tu_edpt_stream_write_zlp_if_needed(dev_addr, &p_midi->ep_stream.tx, xferred_bytes);
+ tu_edpt_stream_write_zlp_if_needed(ep_str_tx, xferred_bytes);
}
}
@@ -195,15 +192,16 @@ bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint
//--------------------------------------------------------------------+
// Enumeration
//--------------------------------------------------------------------+
-bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) {
+uint16_t midih_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_interface_t *desc_itf, uint16_t max_len) {
(void) rhport;
- TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass);
- const uint8_t *p_end = ((const uint8_t *) desc_itf) + max_len;
- const uint8_t *p_desc = (const uint8_t *) desc_itf;
+ TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass, 0);
+ const uint8_t *desc_start = (const uint8_t *)desc_itf;
+ const uint8_t *p_desc = desc_start;
+ const uint8_t *desc_end = desc_start + max_len;
const uint8_t idx = find_new_midi_index();
- TU_VERIFY(idx < CFG_TUH_MIDI);
+ TU_VERIFY(idx < CFG_TUH_MIDI, 0);
midih_interface_t *p_midi = &_midi_host[idx];
p_midi->itf_count = 0;
@@ -220,29 +218,30 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d
// 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));
-
+ TU_VERIFY(max_len > 2 * sizeof(tusb_desc_interface_t) + sizeof(midi10_desc_cs_ac_interface_t), 0);
p_desc = tu_desc_next(p_desc);
TU_VERIFY(tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE &&
- tu_desc_subtype(p_desc) == AUDIO_CS_AC_INTERFACE_HEADER);
+ tu_desc_subtype(p_desc) == AUDIO10_CS_AC_INTERFACE_HEADER,
+ 0);
desc_cb.desc_audio_control = desc_itf;
p_desc = tu_desc_next(p_desc);
desc_itf = (const tusb_desc_interface_t *)p_desc;
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))) {
+ while (tu_desc_in_bounds(p_desc, desc_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;
+ desc_itf = (const tusb_desc_interface_t *)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(p_desc < desc_end, 0);
+ TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass, 0);
}
- TU_VERIFY(AUDIO_SUBCLASS_MIDI_STREAMING == desc_itf->bInterfaceSubClass);
+ TU_VERIFY(AUDIO_SUBCLASS_MIDI_STREAMING == desc_itf->bInterfaceSubClass, 0);
TU_LOG_DRV("MIDI opening Interface %u (addr = %u)\r\n", desc_itf->bInterfaceNumber, dev_addr);
p_midi->bInterfaceNumber = desc_itf->bInterfaceNumber;
@@ -250,10 +249,12 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d
p_midi->itf_count++;
desc_cb.desc_midi = desc_itf;
- p_desc = tu_desc_next(p_desc); // next to CS Header
-
bool found_new_interface = false;
- while (tu_desc_in_bounds(p_desc, p_end) && !found_new_interface) {
+ do {
+ p_desc = tu_desc_next(p_desc);
+ if (!tu_desc_in_bounds(p_desc, desc_end)) {
+ break;
+ }
switch (tu_desc_type(p_desc)) {
case TUSB_DESC_INTERFACE:
found_new_interface = true;
@@ -290,39 +291,39 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d
case TUSB_DESC_ENDPOINT: {
const tusb_desc_endpoint_t *p_ep = (const tusb_desc_endpoint_t *) p_desc;
+
p_desc = tu_desc_next(p_desc); // next to CS endpoint
- TU_VERIFY(p_desc < p_end && tu_desc_next(p_desc) <= p_end);
+ TU_VERIFY(tu_desc_in_bounds(p_desc, desc_end), 0);
const midi_desc_cs_endpoint_t *p_csep = (const midi_desc_cs_endpoint_t *) p_desc;
TU_LOG_DRV(" Endpoint and CS_Endpoint descriptor %02x\r\n", p_ep->bEndpointAddress);
+ tu_edpt_stream_t *ep_stream;
if (tu_edpt_dir(p_ep->bEndpointAddress) == TUSB_DIR_OUT) {
- p_midi->ep_out = p_ep->bEndpointAddress;
p_midi->tx_cable_count = p_csep->bNumEmbMIDIJack;
desc_cb.desc_epout = p_ep;
-
- TU_ASSERT(tuh_edpt_open(dev_addr, p_ep));
- tu_edpt_stream_open(&p_midi->ep_stream.tx, p_ep);
+ ep_stream = &p_midi->ep_stream.tx;
} else {
- p_midi->ep_in = p_ep->bEndpointAddress;
p_midi->rx_cable_count = p_csep->bNumEmbMIDIJack;
- desc_cb.desc_epin = p_ep;
-
- TU_ASSERT(tuh_edpt_open(dev_addr, p_ep));
- tu_edpt_stream_open(&p_midi->ep_stream.rx, p_ep);
+ desc_cb.desc_epin = p_ep;
+ ep_stream = &p_midi->ep_stream.rx;
}
+ TU_ASSERT(tuh_edpt_open(dev_addr, p_ep), 0);
+ tu_edpt_stream_open(ep_stream, dev_addr, p_ep, tu_edpt_packet_size(p_ep));
+ tu_edpt_stream_clear(ep_stream);
+
break;
}
default: break; // skip unknown descriptor
}
- p_desc = tu_desc_next(p_desc);
- }
- desc_cb.desc_midi_total_len = (uint16_t) ((uintptr_t)p_desc - (uintptr_t) desc_itf);
+ } while (!found_new_interface);
+
+ desc_cb.desc_midi_total_len = (uint16_t)((uintptr_t)p_desc - (uintptr_t)desc_start);
p_midi->daddr = dev_addr;
tuh_midi_descriptor_cb(idx, &desc_cb);
- return true;
+ return desc_cb.desc_midi_total_len;
}
bool midih_set_config(uint8_t dev_addr, uint8_t itf_num) {
@@ -333,13 +334,13 @@ bool midih_set_config(uint8_t dev_addr, uint8_t itf_num) {
const tuh_midi_mount_cb_t mount_cb_data = {
.daddr = dev_addr,
- .bInterfaceNumber = itf_num,
+ .bInterfaceNumber = p_midi->bInterfaceNumber,
.rx_cable_count = p_midi->rx_cable_count,
.tx_cable_count = p_midi->tx_cable_count,
};
tuh_midi_mount_cb(idx, &mount_cb_data);
- tu_edpt_stream_read_xfer(dev_addr, &p_midi->ep_stream.rx); // prepare for incoming data
+ tu_edpt_stream_read_xfer(&p_midi->ep_stream.rx); // prepare for incoming data
// No special config things to do for MIDI
usbh_driver_set_config_complete(dev_addr, p_midi->bInterfaceNumber);
@@ -379,8 +380,14 @@ bool tuh_midi_itf_get_info(uint8_t idx, tuh_itf_info_t* info) {
desc->bDescriptorType = TUSB_DESC_INTERFACE;
desc->bInterfaceNumber = p_midi->bInterfaceNumber;
- desc->bAlternateSetting = 0;
- desc->bNumEndpoints = (uint8_t)((p_midi->ep_in != 0 ? 1:0) + (p_midi->ep_out != 0 ? 1:0));
+ desc->bAlternateSetting = 0;
+ desc->bNumEndpoints = 0;
+ if (tu_edpt_stream_is_opened(&p_midi->ep_stream.tx)) {
+ desc->bNumEndpoints++;
+ }
+ if (tu_edpt_stream_is_opened(&p_midi->ep_stream.rx)) {
+ desc->bNumEndpoints++;
+ }
desc->bInterfaceClass = TUSB_CLASS_AUDIO;
desc->bInterfaceSubClass = AUDIO_SUBCLASS_MIDI_STREAMING;
desc->bInterfaceProtocol = 0;
@@ -412,7 +419,7 @@ uint32_t tuh_midi_read_available(uint8_t idx) {
uint32_t tuh_midi_write_flush(uint8_t idx) {
TU_VERIFY(idx < CFG_TUH_MIDI);
midih_interface_t *p_midi = &_midi_host[idx];
- return tu_edpt_stream_write_xfer(p_midi->daddr, &p_midi->ep_stream.tx);
+ return tu_edpt_stream_write_xfer(&p_midi->ep_stream.tx);
}
//--------------------------------------------------------------------+
@@ -425,7 +432,7 @@ uint32_t tuh_midi_packet_read_n(uint8_t idx, uint8_t* buffer, uint32_t bufsize)
uint32_t count4 = tu_min32(bufsize, tu_edpt_stream_read_available(&p_midi->ep_stream.rx));
count4 = tu_align4(count4); // round down to multiple of 4
TU_VERIFY(count4 > 0, 0);
- return tu_edpt_stream_read(p_midi->daddr, &p_midi->ep_stream.rx, buffer, count4);
+ return tu_edpt_stream_read(&p_midi->ep_stream.rx, buffer, count4);
}
uint32_t tuh_midi_packet_write_n(uint8_t idx, const uint8_t* buffer, uint32_t bufsize) {
@@ -434,7 +441,7 @@ uint32_t tuh_midi_packet_write_n(uint8_t idx, const uint8_t* buffer, uint32_t bu
const uint32_t bufsize4 = tu_align4(bufsize);
TU_VERIFY(bufsize4 > 0, 0);
- return tu_edpt_stream_write(p_midi->daddr, &p_midi->ep_stream.tx, buffer, bufsize4);
+ return tu_edpt_stream_write(&p_midi->ep_stream.tx, buffer, bufsize4);
}
//--------------------------------------------------------------------+
@@ -448,17 +455,17 @@ uint32_t tuh_midi_stream_write(uint8_t idx, uint8_t cable_num, uint8_t const *bu
midi_driver_stream_t *stream = &p_midi->stream_write;
uint32_t byte_count = 0;
- while ((byte_count < bufsize) && (tu_edpt_stream_write_available(p_midi->daddr, &p_midi->ep_stream.tx) >= 4)) {
- uint8_t const data = buffer[byte_count];
+ while ((byte_count < bufsize) && (tu_edpt_stream_write_available(&p_midi->ep_stream.tx) >= 4)) {
+ const uint8_t data = buffer[byte_count];
byte_count++;
if (data >= MIDI_STATUS_SYSREAL_TIMING_CLOCK) {
// real-time messages need to be sent right away
midi_driver_stream_t streamrt;
- streamrt.buffer[0] = MIDI_CIN_SYSEX_END_1BYTE;
+ streamrt.buffer[0] = (uint8_t)((cable_num << 4) | MIDI_CIN_SYSEX_END_1BYTE);
streamrt.buffer[1] = data;
streamrt.index = 2;
streamrt.total = 2;
- uint32_t const count = tu_edpt_stream_write(p_midi->daddr, &p_midi->ep_stream.tx, streamrt.buffer, 4);
+ const uint32_t count = tu_edpt_stream_write(&p_midi->ep_stream.tx, streamrt.buffer, 4);
TU_ASSERT(count == 4, byte_count); // Check FIFO overflown, since we already check fifo remaining. It is probably race condition
} else if (stream->index == 0) {
//------------- New event packet -------------//
@@ -469,9 +476,9 @@ uint32_t tuh_midi_stream_write(uint8_t idx, uint8_t cable_num, uint8_t const *bu
stream->buffer[1] = data;
// Check to see if we're still in a SysEx transmit.
- if (stream->buffer[0] == MIDI_CIN_SYSEX_START) {
+ if ((stream->buffer[0] & 0xF) == MIDI_CIN_SYSEX_START) {
if (data == MIDI_STATUS_SYSEX_END) {
- stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE;
+ stream->buffer[0] = (uint8_t)((cable_num << 4) | MIDI_CIN_SYSEX_END_1BYTE);
stream->total = 2;
} else {
stream->total = 4;
@@ -499,6 +506,7 @@ uint32_t tuh_midi_stream_write(uint8_t idx, uint8_t cable_num, uint8_t const *bu
stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE;
stream->total = 2;
}
+ stream->buffer[0] |= (uint8_t)(cable_num << 4);
} else {
// Pack individual bytes if we don't support packing them into words.
stream->buffer[0] = (uint8_t) (cable_num << 4 | 0xf);
@@ -513,8 +521,8 @@ uint32_t tuh_midi_stream_write(uint8_t idx, uint8_t cable_num, uint8_t const *bu
stream->buffer[stream->index] = data;
stream->index++;
// See if this byte ends a SysEx.
- if (stream->buffer[0] == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END) {
- stream->buffer[0] = MIDI_CIN_SYSEX_START + (stream->index - 1);
+ if ((stream->buffer[0] & 0xF) == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END) {
+ stream->buffer[0] = (uint8_t)((cable_num << 4) | (MIDI_CIN_SYSEX_START + (stream->index - 1)));
stream->total = stream->index;
}
}
@@ -527,7 +535,7 @@ uint32_t tuh_midi_stream_write(uint8_t idx, uint8_t cable_num, uint8_t const *bu
}
TU_LOG3_MEM(stream->buffer, 4, 2);
- const uint32_t count = tu_edpt_stream_write(p_midi->daddr, &p_midi->ep_stream.tx, stream->buffer, 4);
+ const uint32_t count = tu_edpt_stream_write(&p_midi->ep_stream.tx, stream->buffer, 4);
// complete current event packet, reset stream
stream->index = 0;
@@ -549,7 +557,7 @@ uint32_t tuh_midi_stream_read(uint8_t idx, uint8_t *p_cable_num, uint8_t *p_buff
return 0;
}
*p_cable_num = (one_byte >> 4) & 0xf;
- uint32_t nread = tu_edpt_stream_read(p_midi->daddr, &p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4);
+ uint32_t nread = tu_edpt_stream_read(&p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4);
static uint16_t cable_sysex_in_progress;// bit i is set if received MIDI_STATUS_SYSEX_START but not MIDI_STATUS_SYSEX_END
while (nread == 4 && bytes_buffered < bufsize) {
*p_cable_num = (p_midi->stream_read.buffer[0] >> 4) & 0x0f;
@@ -577,7 +585,7 @@ 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);
+ nread = tu_edpt_stream_read(&p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4);
continue;
}
} else if (status < MIDI_STATUS_SYSEX_START) {
@@ -624,7 +632,7 @@ 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);
+ nread = tu_edpt_stream_read(&p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4);
continue;
}
@@ -637,7 +645,7 @@ uint32_t tuh_midi_stream_read(uint8_t idx, uint8_t *p_cable_num, uint8_t *p_buff
uint8_t new_cable = (one_byte >> 4) & 0xf;
if (new_cable == *p_cable_num) {
// still on the same cable. Continue reading the stream
- nread = tu_edpt_stream_read(p_midi->daddr, &p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4);
+ nread = tu_edpt_stream_read(&p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4);
}
}
}