|
|
|
@@ -45,15 +45,12 @@ typedef struct
|
|
|
|
|
uint8_t total;
|
|
|
|
|
}midi_stream_t;
|
|
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
typedef struct {
|
|
|
|
|
uint8_t dev_addr;
|
|
|
|
|
uint8_t itf_num;
|
|
|
|
|
|
|
|
|
|
uint8_t ep_in; // IN endpoint address
|
|
|
|
|
uint8_t ep_out; // OUT endpoint address
|
|
|
|
|
uint16_t ep_in_max; // min( CFG_TUH_MIDI_RX_BUFSIZE, wMaxPacketSize of the IN endpoint)
|
|
|
|
|
uint16_t ep_out_max; // min( CFG_TUH_MIDI_TX_BUFSIZE, wMaxPacketSize of the OUT endpoint)
|
|
|
|
|
|
|
|
|
|
uint8_t num_cables_rx; // IN endpoint CS descriptor bNumEmbMIDIJack value
|
|
|
|
|
uint8_t num_cables_tx; // OUT endpoint CS descriptor bNumEmbMIDIJack value
|
|
|
|
@@ -65,22 +62,14 @@ typedef struct
|
|
|
|
|
midi_stream_t stream_read;
|
|
|
|
|
|
|
|
|
|
/*------------- From this point, data is not cleared by bus reset -------------*/
|
|
|
|
|
// Endpoint FIFOs
|
|
|
|
|
tu_fifo_t rx_ff;
|
|
|
|
|
tu_fifo_t tx_ff;
|
|
|
|
|
|
|
|
|
|
// Endpoint stream
|
|
|
|
|
struct {
|
|
|
|
|
tu_edpt_stream_t tx;
|
|
|
|
|
tu_edpt_stream_t rx;
|
|
|
|
|
|
|
|
|
|
uint8_t rx_ff_buf[CFG_TUH_MIDI_RX_BUFSIZE];
|
|
|
|
|
uint8_t tx_ff_buf[CFG_TUH_MIDI_TX_BUFSIZE];
|
|
|
|
|
|
|
|
|
|
#if CFG_FIFO_MUTEX
|
|
|
|
|
osal_mutex_def_t rx_ff_mutex;
|
|
|
|
|
osal_mutex_def_t tx_ff_mutex;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// Endpoint Transfer buffer
|
|
|
|
|
CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUH_MIDI_EP_BUFSIZE];
|
|
|
|
|
CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUH_MIDI_EP_BUFSIZE];
|
|
|
|
|
} ep_stream;
|
|
|
|
|
|
|
|
|
|
bool configured;
|
|
|
|
|
|
|
|
|
@@ -109,15 +98,17 @@ typedef struct
|
|
|
|
|
#endif
|
|
|
|
|
}midih_interface_t;
|
|
|
|
|
|
|
|
|
|
static midih_interface_t _midi_host[CFG_TUH_MIDI];
|
|
|
|
|
typedef struct {
|
|
|
|
|
TUH_EPBUF_DEF(tx, TUH_EPSIZE_BULK_MPS);
|
|
|
|
|
TUH_EPBUF_DEF(rx, TUH_EPSIZE_BULK_MPS);
|
|
|
|
|
} midih_epbuf_t;
|
|
|
|
|
|
|
|
|
|
//------------- Internal prototypes -------------//
|
|
|
|
|
static uint32_t write_flush(uint8_t dev_addr, midih_interface_t* midi);
|
|
|
|
|
static midih_interface_t _midi_host[CFG_TUH_MIDI];
|
|
|
|
|
CFG_TUH_MEM_SECTION static midih_epbuf_t _midi_epbuf[CFG_TUH_MIDI];
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------+
|
|
|
|
|
// Helper
|
|
|
|
|
//--------------------------------------------------------------------+
|
|
|
|
|
|
|
|
|
|
TU_ATTR_ALWAYS_INLINE static inline midih_interface_t* find_midi_by_daddr(uint8_t dev_addr) {
|
|
|
|
|
for (uint8_t i = 0; i < CFG_TUH_MIDI; i++) {
|
|
|
|
|
if (_midi_host[i].dev_addr == dev_addr) {
|
|
|
|
@@ -131,85 +122,27 @@ TU_ATTR_ALWAYS_INLINE static inline midih_interface_t* find_new_midi(void) {
|
|
|
|
|
return find_midi_by_daddr(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------+
|
|
|
|
|
// USBH API
|
|
|
|
|
//--------------------------------------------------------------------+
|
|
|
|
|
bool midih_init(void) {
|
|
|
|
|
tu_memclr(&_midi_host, sizeof(_midi_host));
|
|
|
|
|
// config fifos
|
|
|
|
|
for (int inst = 0; inst < CFG_TUH_MIDI; inst++) {
|
|
|
|
|
midih_interface_t *p_midi_host = &_midi_host[inst];
|
|
|
|
|
tu_fifo_config(&p_midi_host->rx_ff, p_midi_host->rx_ff_buf, CFG_TUH_MIDI_RX_BUFSIZE, 1, false);// true, true
|
|
|
|
|
tu_fifo_config(&p_midi_host->tx_ff, p_midi_host->tx_ff_buf, CFG_TUH_MIDI_TX_BUFSIZE, 1, false);// OBVS.
|
|
|
|
|
|
|
|
|
|
#if CFG_FIFO_MUTEX
|
|
|
|
|
tu_fifo_config_mutex(&p_midi_host->rx_ff, NULL, osal_mutex_create(&p_midi_host->rx_ff_mutex));
|
|
|
|
|
tu_fifo_config_mutex(&p_midi_host->tx_ff, osal_mutex_create(&p_midi_host->tx_ff_mutex), NULL);
|
|
|
|
|
#endif
|
|
|
|
|
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);
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
|
|
|
|
|
{
|
|
|
|
|
(void)result;
|
|
|
|
|
midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr);
|
|
|
|
|
TU_VERIFY(p_midi_host != NULL);
|
|
|
|
|
if ( ep_addr == p_midi_host->ep_in)
|
|
|
|
|
{
|
|
|
|
|
if (0 == xferred_bytes)
|
|
|
|
|
{
|
|
|
|
|
return true; // No data to handle
|
|
|
|
|
bool midih_deinit(void) {
|
|
|
|
|
for (size_t i = 0; i < CFG_TUH_MIDI; i++) {
|
|
|
|
|
midih_interface_t* p_midi = &_midi_host[i];
|
|
|
|
|
tu_edpt_stream_deinit(&p_midi->ep_stream.rx);
|
|
|
|
|
tu_edpt_stream_deinit(&p_midi->ep_stream.tx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// receive new data if available
|
|
|
|
|
uint32_t packets_queued = 0;
|
|
|
|
|
if (xferred_bytes)
|
|
|
|
|
{
|
|
|
|
|
// put in the RX FIFO only non-zero MIDI IN 4-byte packets
|
|
|
|
|
uint8_t* buf = p_midi_host->epin_buf;
|
|
|
|
|
uint32_t npackets = xferred_bytes / 4;
|
|
|
|
|
uint32_t packet_num;
|
|
|
|
|
for (packet_num = 0; packet_num < npackets; packet_num++)
|
|
|
|
|
{
|
|
|
|
|
// some devices send back all zero packets even if there is no data ready
|
|
|
|
|
uint32_t packet = (uint32_t)((*buf)<<24) | ((uint32_t)(*(buf+1))<<16) | ((uint32_t)(*(buf+2))<<8) | ((uint32_t)(*(buf+3)));
|
|
|
|
|
if (packet != 0)
|
|
|
|
|
{
|
|
|
|
|
tu_fifo_write_n(&p_midi_host->rx_ff, buf, 4);
|
|
|
|
|
++packets_queued;
|
|
|
|
|
TU_LOG3("MIDI RX=%08x\r\n", packet);
|
|
|
|
|
}
|
|
|
|
|
buf += 4;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// invoke receive callback if available
|
|
|
|
|
if (tuh_midi_rx_cb)
|
|
|
|
|
{
|
|
|
|
|
tuh_midi_rx_cb(dev_addr, packets_queued);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if ( ep_addr == p_midi_host->ep_out )
|
|
|
|
|
{
|
|
|
|
|
if (0 == write_flush(dev_addr, p_midi_host))
|
|
|
|
|
{
|
|
|
|
|
// If there is no data left, a ZLP should be sent if
|
|
|
|
|
// xferred_bytes is multiple of EP size and not zero
|
|
|
|
|
if ( !tu_fifo_count(&p_midi_host->tx_ff) && xferred_bytes && (0 == (xferred_bytes % p_midi_host->ep_out_max)) )
|
|
|
|
|
{
|
|
|
|
|
if ( usbh_edpt_claim(dev_addr, p_midi_host->ep_out) )
|
|
|
|
|
{
|
|
|
|
|
TU_ASSERT(usbh_edpt_xfer(dev_addr, p_midi_host->ep_out, XFER_RESULT_SUCCESS, 0));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (tuh_midi_tx_cb)
|
|
|
|
|
{
|
|
|
|
|
tuh_midi_tx_cb(dev_addr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -221,26 +154,67 @@ void midih_close(uint8_t dev_addr) {
|
|
|
|
|
if (tuh_midi_umount_cb) {
|
|
|
|
|
tuh_midi_umount_cb(dev_addr, 0);
|
|
|
|
|
}
|
|
|
|
|
tu_fifo_clear(&p_midi_host->rx_ff);
|
|
|
|
|
tu_fifo_clear(&p_midi_host->tx_ff);
|
|
|
|
|
p_midi_host->ep_in = 0;
|
|
|
|
|
p_midi_host->ep_in_max = 0;
|
|
|
|
|
p_midi_host->ep_out = 0;
|
|
|
|
|
p_midi_host->ep_out_max = 0;
|
|
|
|
|
p_midi_host->itf_num = 0;
|
|
|
|
|
p_midi_host->num_cables_rx = 0;
|
|
|
|
|
p_midi_host->num_cables_tx = 0;
|
|
|
|
|
p_midi_host->dev_addr = 255; // invalid
|
|
|
|
|
p_midi_host->dev_addr = 0;
|
|
|
|
|
p_midi_host->configured = false;
|
|
|
|
|
tu_memclr(&p_midi_host->stream_read, sizeof(p_midi_host->stream_read));
|
|
|
|
|
tu_memclr(&p_midi_host->stream_write, sizeof(p_midi_host->stream_write));
|
|
|
|
|
|
|
|
|
|
tu_edpt_stream_close(&p_midi_host->ep_stream.rx);
|
|
|
|
|
tu_edpt_stream_close(&p_midi_host->ep_stream.tx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
|
|
|
|
|
(void) result;
|
|
|
|
|
midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr);
|
|
|
|
|
TU_VERIFY(p_midi_host != NULL);
|
|
|
|
|
if (ep_addr == p_midi_host->ep_stream.rx.ep_addr) {
|
|
|
|
|
// receive new data if available
|
|
|
|
|
if (xferred_bytes) {
|
|
|
|
|
// put in the RX FIFO only non-zero MIDI IN 4-byte packets
|
|
|
|
|
uint32_t packets_queued = 0;
|
|
|
|
|
uint8_t *buf = _midi_epbuf->rx;
|
|
|
|
|
const uint32_t npackets = xferred_bytes / 4;
|
|
|
|
|
for (uint32_t p = 0; p < npackets; p++) {
|
|
|
|
|
// some devices send back all zero packets even if there is no data ready
|
|
|
|
|
const uint32_t packet = tu_unaligned_read32(buf);
|
|
|
|
|
if (packet != 0) {
|
|
|
|
|
tu_edpt_stream_read_xfer_complete_with_buf(&p_midi_host->ep_stream.rx, buf, 4);
|
|
|
|
|
++packets_queued;
|
|
|
|
|
TU_LOG3("MIDI RX=%08x\r\n", packet);
|
|
|
|
|
}
|
|
|
|
|
buf += 4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (tuh_midi_rx_cb) {
|
|
|
|
|
tuh_midi_rx_cb(dev_addr, packets_queued); // invoke receive callback
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// prepare for next transfer if needed
|
|
|
|
|
tu_edpt_stream_read_xfer(dev_addr, &p_midi_host->ep_stream.rx);
|
|
|
|
|
} else if (ep_addr == p_midi_host->ep_stream.tx.ep_addr) {
|
|
|
|
|
if (tuh_midi_tx_cb) {
|
|
|
|
|
tuh_midi_tx_cb(dev_addr);
|
|
|
|
|
}
|
|
|
|
|
if (0 == tu_edpt_stream_write_xfer(dev_addr, &p_midi_host->ep_stream.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_host->ep_stream.tx, xferred_bytes);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------+
|
|
|
|
|
// Enumeration
|
|
|
|
|
//--------------------------------------------------------------------+
|
|
|
|
|
bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len)
|
|
|
|
|
{
|
|
|
|
|
bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) {
|
|
|
|
|
(void) rhport;
|
|
|
|
|
|
|
|
|
|
midih_interface_t *p_midi_host = find_new_midi();
|
|
|
|
@@ -402,20 +376,12 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d
|
|
|
|
|
TU_VERIFY(p_midi_host->ep_out == 0);
|
|
|
|
|
TU_VERIFY(p_midi_host->num_cables_tx == 0);
|
|
|
|
|
p_midi_host->ep_out = p_ep->bEndpointAddress;
|
|
|
|
|
p_midi_host->ep_out_max = p_ep->wMaxPacketSize;
|
|
|
|
|
if (p_midi_host->ep_out_max > CFG_TUH_MIDI_TX_BUFSIZE) {
|
|
|
|
|
p_midi_host->ep_out_max = CFG_TUH_MIDI_TX_BUFSIZE;
|
|
|
|
|
}
|
|
|
|
|
prev_ep_addr = p_midi_host->ep_out;
|
|
|
|
|
out_desc = p_ep;
|
|
|
|
|
} else {
|
|
|
|
|
TU_VERIFY(p_midi_host->ep_in == 0);
|
|
|
|
|
TU_VERIFY(p_midi_host->num_cables_rx == 0);
|
|
|
|
|
p_midi_host->ep_in = p_ep->bEndpointAddress;
|
|
|
|
|
p_midi_host->ep_in_max = p_ep->wMaxPacketSize;
|
|
|
|
|
if (p_midi_host->ep_in_max > CFG_TUH_MIDI_RX_BUFSIZE) {
|
|
|
|
|
p_midi_host->ep_in_max = CFG_TUH_MIDI_RX_BUFSIZE;
|
|
|
|
|
}
|
|
|
|
|
prev_ep_addr = p_midi_host->ep_in;
|
|
|
|
|
in_desc = p_ep;
|
|
|
|
|
}
|
|
|
|
@@ -439,36 +405,34 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d
|
|
|
|
|
}
|
|
|
|
|
if (in_desc) {
|
|
|
|
|
TU_ASSERT(tuh_edpt_open(dev_addr, in_desc));
|
|
|
|
|
// Some devices always return exactly the request length so transfers won't complete
|
|
|
|
|
// unless you assume every transfer is the last one.
|
|
|
|
|
// TODO usbh_edpt_force_last_buffer(dev_addr, p_midi_host->ep_in, true);
|
|
|
|
|
tu_edpt_stream_open(&p_midi_host->ep_stream.rx, in_desc);
|
|
|
|
|
}
|
|
|
|
|
if (out_desc) {
|
|
|
|
|
TU_ASSERT(tuh_edpt_open(dev_addr, out_desc));
|
|
|
|
|
tu_edpt_stream_open(&p_midi_host->ep_stream.tx, out_desc);
|
|
|
|
|
}
|
|
|
|
|
p_midi_host->dev_addr = dev_addr;
|
|
|
|
|
|
|
|
|
|
if (tuh_midi_mount_cb) {
|
|
|
|
|
tuh_midi_mount_cb(dev_addr, p_midi_host->ep_in, p_midi_host->ep_out, p_midi_host->num_cables_rx, p_midi_host->num_cables_tx);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool tuh_midi_configured(uint8_t dev_addr)
|
|
|
|
|
{
|
|
|
|
|
bool tuh_midi_configured(uint8_t dev_addr) {
|
|
|
|
|
midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr);
|
|
|
|
|
TU_VERIFY(p_midi_host != NULL);
|
|
|
|
|
return p_midi_host->configured;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool midih_set_config(uint8_t dev_addr, uint8_t itf_num)
|
|
|
|
|
{
|
|
|
|
|
bool midih_set_config(uint8_t dev_addr, uint8_t itf_num) {
|
|
|
|
|
(void) itf_num;
|
|
|
|
|
midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr);
|
|
|
|
|
TU_VERIFY(p_midi_host != NULL);
|
|
|
|
|
p_midi_host->configured = true;
|
|
|
|
|
|
|
|
|
|
// TODO I don't think there are any special config things to do for MIDI
|
|
|
|
|
if (tuh_midi_mount_cb) {
|
|
|
|
|
tuh_midi_mount_cb(dev_addr, p_midi_host->ep_in, p_midi_host->ep_out, p_midi_host->num_cables_rx, p_midi_host->num_cables_tx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// No special config things to do for MIDI
|
|
|
|
|
usbh_driver_set_config_complete(dev_addr, p_midi_host->itf_num);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
@@ -476,71 +440,32 @@ bool midih_set_config(uint8_t dev_addr, uint8_t itf_num)
|
|
|
|
|
//--------------------------------------------------------------------+
|
|
|
|
|
// Stream API
|
|
|
|
|
//--------------------------------------------------------------------+
|
|
|
|
|
static uint32_t write_flush(uint8_t dev_addr, midih_interface_t* midi) {
|
|
|
|
|
// No data to send
|
|
|
|
|
if ( !tu_fifo_count(&midi->tx_ff) ) { return 0; }
|
|
|
|
|
|
|
|
|
|
// skip if previous transfer not complete
|
|
|
|
|
TU_VERIFY( usbh_edpt_claim(dev_addr, midi->ep_out) );
|
|
|
|
|
|
|
|
|
|
uint16_t count = tu_fifo_read_n(&midi->tx_ff, midi->epout_buf, midi->ep_out_max);
|
|
|
|
|
|
|
|
|
|
if (count) {
|
|
|
|
|
TU_ASSERT(usbh_edpt_xfer(dev_addr, midi->ep_out, midi->epout_buf, count), 0);
|
|
|
|
|
return count;
|
|
|
|
|
} else {
|
|
|
|
|
// Release endpoint since we don't make any transfer
|
|
|
|
|
usbh_edpt_release(dev_addr, midi->ep_out);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool tuh_midi_read_poll(uint8_t dev_addr) {
|
|
|
|
|
midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr);
|
|
|
|
|
TU_VERIFY(p_midi_host != NULL);
|
|
|
|
|
bool result = false;
|
|
|
|
|
|
|
|
|
|
bool in_edpt_not_busy = !usbh_edpt_busy(dev_addr, p_midi_host->ep_in);
|
|
|
|
|
if (in_edpt_not_busy) {
|
|
|
|
|
TU_LOG2("Requesting poll IN endpoint %d\r\n", p_midi_host->ep_in);
|
|
|
|
|
TU_ASSERT(usbh_edpt_xfer(p_midi_host->dev_addr, p_midi_host->ep_in, p_midi_host->epin_buf, p_midi_host->ep_in_max), 0);
|
|
|
|
|
result = true;
|
|
|
|
|
} else {
|
|
|
|
|
// Maybe the IN endpoint is only busy because the RP2040 host hardware
|
|
|
|
|
// is retrying a NAK'd IN transfer forever. Try aborting the NAK'd
|
|
|
|
|
// transfer to allow other transfers to happen on the one shared
|
|
|
|
|
// epx endpoint.
|
|
|
|
|
// TODO for RP2040 USB shared endpoint: usbh_edpt_clear_in_on_nak(p_midi_host->dev_addr, p_midi_host->ep_in);
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
return tu_edpt_stream_read_xfer(dev_addr, &p_midi_host->ep_stream.rx) > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t tuh_midi_stream_write (uint8_t dev_addr, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize)
|
|
|
|
|
{
|
|
|
|
|
uint32_t tuh_midi_stream_write(uint8_t dev_addr, uint8_t cable_num, uint8_t const *buffer, uint32_t bufsize) {
|
|
|
|
|
midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr);
|
|
|
|
|
TU_VERIFY(p_midi_host != NULL);
|
|
|
|
|
TU_VERIFY(cable_num < p_midi_host->num_cables_tx);
|
|
|
|
|
midi_stream_t *stream = &p_midi_host->stream_write;
|
|
|
|
|
|
|
|
|
|
uint32_t i = 0;
|
|
|
|
|
while ( (i < bufsize) && (tu_fifo_remaining(&p_midi_host->tx_ff) >= 4) )
|
|
|
|
|
{
|
|
|
|
|
while ((i < bufsize) && (tu_edpt_stream_write_available(dev_addr, &p_midi_host->ep_stream.tx) >= 4)) {
|
|
|
|
|
uint8_t const data = buffer[i];
|
|
|
|
|
i++;
|
|
|
|
|
if (data >= MIDI_STATUS_SYSREAL_TIMING_CLOCK)
|
|
|
|
|
{
|
|
|
|
|
if (data >= MIDI_STATUS_SYSREAL_TIMING_CLOCK) {
|
|
|
|
|
// real-time messages need to be sent right away
|
|
|
|
|
midi_stream_t streamrt;
|
|
|
|
|
streamrt.buffer[0] = MIDI_CIN_SYSEX_END_1BYTE;
|
|
|
|
|
streamrt.buffer[1] = data;
|
|
|
|
|
streamrt.index = 2;
|
|
|
|
|
streamrt.total = 2;
|
|
|
|
|
uint16_t const count = tu_fifo_write_n(&p_midi_host->tx_ff, streamrt.buffer, 4);
|
|
|
|
|
// FIFO overflown, since we already check fifo remaining. It is probably race condition
|
|
|
|
|
TU_ASSERT(count == 4, i);
|
|
|
|
|
}
|
|
|
|
|
else if ( stream->index == 0 )
|
|
|
|
|
{
|
|
|
|
|
uint32_t const count = tu_edpt_stream_write(dev_addr, &p_midi_host->ep_stream.tx, streamrt.buffer, 4);
|
|
|
|
|
TU_ASSERT(count == 4, i); // Check FIFO overflown, since we already check fifo remaining. It is probably race condition
|
|
|
|
|
} else if (stream->index == 0) {
|
|
|
|
|
//------------- New event packet -------------//
|
|
|
|
|
|
|
|
|
|
uint8_t const msg = data >> 4;
|
|
|
|
@@ -549,56 +474,37 @@ uint32_t tuh_midi_stream_write (uint8_t dev_addr, uint8_t cable_num, uint8_t con
|
|
|
|
|
stream->buffer[1] = data;
|
|
|
|
|
|
|
|
|
|
// Check to see if we're still in a SysEx transmit.
|
|
|
|
|
if ( stream->buffer[0] == MIDI_CIN_SYSEX_START )
|
|
|
|
|
{
|
|
|
|
|
if ( data == MIDI_STATUS_SYSEX_END )
|
|
|
|
|
{
|
|
|
|
|
if (stream->buffer[0] == MIDI_CIN_SYSEX_START) {
|
|
|
|
|
if (data == MIDI_STATUS_SYSEX_END) {
|
|
|
|
|
stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE;
|
|
|
|
|
stream->total = 2;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
} else {
|
|
|
|
|
stream->total = 4;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if ( (msg >= 0x8 && msg <= 0xB) || msg == 0xE )
|
|
|
|
|
{
|
|
|
|
|
} else if ((msg >= 0x8 && msg <= 0xB) || msg == 0xE) {
|
|
|
|
|
// Channel Voice Messages
|
|
|
|
|
stream->buffer[0] = (uint8_t) ((cable_num << 4) | msg);
|
|
|
|
|
stream->total = 4;
|
|
|
|
|
}
|
|
|
|
|
else if ( msg == 0xC || msg == 0xD)
|
|
|
|
|
{
|
|
|
|
|
} else if (msg == 0xC || msg == 0xD) {
|
|
|
|
|
// Channel Voice Messages, two-byte variants (Program Change and Channel Pressure)
|
|
|
|
|
stream->buffer[0] = (uint8_t) ((cable_num << 4) | msg);
|
|
|
|
|
stream->total = 3;
|
|
|
|
|
}
|
|
|
|
|
else if ( msg == 0xf )
|
|
|
|
|
{
|
|
|
|
|
} else if (msg == 0xf) {
|
|
|
|
|
// System message
|
|
|
|
|
if ( data == MIDI_STATUS_SYSEX_START )
|
|
|
|
|
{
|
|
|
|
|
if (data == MIDI_STATUS_SYSEX_START) {
|
|
|
|
|
stream->buffer[0] = MIDI_CIN_SYSEX_START;
|
|
|
|
|
stream->total = 4;
|
|
|
|
|
}
|
|
|
|
|
else if ( data == MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME || data == MIDI_STATUS_SYSCOM_SONG_SELECT )
|
|
|
|
|
{
|
|
|
|
|
} else if (data == MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME || data == MIDI_STATUS_SYSCOM_SONG_SELECT) {
|
|
|
|
|
stream->buffer[0] = MIDI_CIN_SYSCOM_2BYTE;
|
|
|
|
|
stream->total = 3;
|
|
|
|
|
}
|
|
|
|
|
else if ( data == MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER )
|
|
|
|
|
{
|
|
|
|
|
} else if (data == MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER) {
|
|
|
|
|
stream->buffer[0] = MIDI_CIN_SYSCOM_3BYTE;
|
|
|
|
|
stream->total = 4;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
} else {
|
|
|
|
|
stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE;
|
|
|
|
|
stream->total = 2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
} else {
|
|
|
|
|
// Pack individual bytes if we don't support packing them into words.
|
|
|
|
|
stream->buffer[0] = (uint8_t) (cable_num << 4 | 0xf);
|
|
|
|
|
stream->buffer[2] = 0;
|
|
|
|
@@ -606,30 +512,25 @@ uint32_t tuh_midi_stream_write (uint8_t dev_addr, uint8_t cable_num, uint8_t con
|
|
|
|
|
stream->index = 2;
|
|
|
|
|
stream->total = 2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
} else {
|
|
|
|
|
//------------- On-going (buffering) packet -------------//
|
|
|
|
|
|
|
|
|
|
TU_ASSERT(stream->index < 4, i);
|
|
|
|
|
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 )
|
|
|
|
|
{
|
|
|
|
|
if (stream->buffer[0] == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END) {
|
|
|
|
|
stream->buffer[0] = MIDI_CIN_SYSEX_START + (stream->index - 1);
|
|
|
|
|
stream->total = stream->index;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Send out packet
|
|
|
|
|
if ( stream->index >= 2 && stream->index == stream->total )
|
|
|
|
|
{
|
|
|
|
|
if (stream->index >= 2 && stream->index == stream->total) {
|
|
|
|
|
// zeroes unused bytes
|
|
|
|
|
for(uint8_t idx = stream->total; idx < 4; idx++) stream->buffer[idx] = 0;
|
|
|
|
|
for (uint8_t idx = stream->total; idx < 4; idx++) { stream->buffer[idx] = 0; }
|
|
|
|
|
TU_LOG3_MEM(stream->buffer, 4, 2);
|
|
|
|
|
|
|
|
|
|
uint16_t const count = tu_fifo_write_n(&p_midi_host->tx_ff, stream->buffer, 4);
|
|
|
|
|
uint32_t const count = tu_edpt_stream_write(dev_addr, &p_midi_host->ep_stream.tx, stream->buffer, 4);
|
|
|
|
|
|
|
|
|
|
// complete current event packet, reset stream
|
|
|
|
|
stream->index = 0;
|
|
|
|
@@ -642,32 +543,16 @@ uint32_t tuh_midi_stream_write (uint8_t dev_addr, uint8_t cable_num, uint8_t con
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool tuh_midi_packet_write (uint8_t dev_addr, uint8_t const packet[4])
|
|
|
|
|
{
|
|
|
|
|
bool tuh_midi_packet_write (uint8_t dev_addr, uint8_t const packet[4]) {
|
|
|
|
|
midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr);
|
|
|
|
|
TU_VERIFY(p_midi_host != NULL);
|
|
|
|
|
|
|
|
|
|
if (tu_fifo_remaining(&p_midi_host->tx_ff) < 4)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tu_fifo_write_n(&p_midi_host->tx_ff, packet, 4);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
return 4 == tu_edpt_stream_write(dev_addr, &p_midi_host->ep_stream.tx, packet, 4);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t tuh_midi_stream_flush( uint8_t dev_addr )
|
|
|
|
|
{
|
|
|
|
|
midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr);
|
|
|
|
|
TU_VERIFY(p_midi_host != NULL);
|
|
|
|
|
|
|
|
|
|
uint32_t bytes_flushed = 0;
|
|
|
|
|
if (!usbh_edpt_busy(p_midi_host->dev_addr, p_midi_host->ep_out))
|
|
|
|
|
{
|
|
|
|
|
bytes_flushed = write_flush(dev_addr, p_midi_host);
|
|
|
|
|
}
|
|
|
|
|
return bytes_flushed;
|
|
|
|
|
uint32_t tuh_midi_stream_flush(uint8_t dev_addr) {
|
|
|
|
|
midih_interface_t *p_midi = find_midi_by_daddr(dev_addr);
|
|
|
|
|
TU_VERIFY(p_midi != NULL);
|
|
|
|
|
return tu_edpt_stream_write_xfer(p_midi->dev_addr, &p_midi->ep_stream.tx);
|
|
|
|
|
}
|
|
|
|
|
//--------------------------------------------------------------------+
|
|
|
|
|
// Helper
|
|
|
|
@@ -692,12 +577,11 @@ bool tuh_midi_packet_read (uint8_t dev_addr, uint8_t packet[4])
|
|
|
|
|
{
|
|
|
|
|
midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr);
|
|
|
|
|
TU_VERIFY(p_midi_host != NULL);
|
|
|
|
|
TU_VERIFY(tu_fifo_count(&p_midi_host->rx_ff) >= 4);
|
|
|
|
|
return tu_fifo_read_n(&p_midi_host->rx_ff, packet, 4) == 4;
|
|
|
|
|
TU_VERIFY(tu_edpt_stream_read_available(&p_midi_host->ep_stream.rx) >= 4);
|
|
|
|
|
return 4 == tu_edpt_stream_read(dev_addr, &p_midi_host->ep_stream.rx, packet, 4);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *p_buffer, uint16_t bufsize)
|
|
|
|
|
{
|
|
|
|
|
uint32_t tuh_midi_stream_read(uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *p_buffer, uint16_t bufsize) {
|
|
|
|
|
midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr);
|
|
|
|
|
TU_VERIFY(p_midi_host != NULL);
|
|
|
|
|
uint32_t bytes_buffered = 0;
|
|
|
|
@@ -705,54 +589,40 @@ uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *
|
|
|
|
|
TU_ASSERT(p_buffer);
|
|
|
|
|
TU_ASSERT(bufsize);
|
|
|
|
|
uint8_t one_byte;
|
|
|
|
|
if (!tu_fifo_peek(&p_midi_host->rx_ff, &one_byte))
|
|
|
|
|
{
|
|
|
|
|
if (!tu_edpt_stream_peek(&p_midi_host->ep_stream.rx, &one_byte)) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
*p_cable_num = (one_byte >> 4) & 0xf;
|
|
|
|
|
uint32_t nread = tu_fifo_read_n(&p_midi_host->rx_ff, p_midi_host->stream_read.buffer, 4);
|
|
|
|
|
uint32_t nread = tu_edpt_stream_read(dev_addr, &p_midi_host->ep_stream.rx, p_midi_host->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_host->stream_read.buffer[0] >> 4) & 0x0f;
|
|
|
|
|
while (nread == 4 && bytes_buffered < bufsize) {
|
|
|
|
|
*p_cable_num = (p_midi_host->stream_read.buffer[0] >> 4) & 0x0f;
|
|
|
|
|
uint8_t bytes_to_add_to_stream = 0;
|
|
|
|
|
if (*p_cable_num < p_midi_host->num_cables_rx)
|
|
|
|
|
{
|
|
|
|
|
if (*p_cable_num < p_midi_host->num_cables_rx) {
|
|
|
|
|
// ignore the CIN field; too many devices out there encode this wrong
|
|
|
|
|
uint8_t status = p_midi_host->stream_read.buffer[1];
|
|
|
|
|
uint16_t cable_mask = (uint16_t) (1 << *p_cable_num);
|
|
|
|
|
if (status <= MIDI_MAX_DATA_VAL || status == MIDI_STATUS_SYSEX_START)
|
|
|
|
|
{
|
|
|
|
|
if (status == MIDI_STATUS_SYSEX_START)
|
|
|
|
|
{
|
|
|
|
|
if (status <= MIDI_MAX_DATA_VAL || status == MIDI_STATUS_SYSEX_START) {
|
|
|
|
|
if (status == MIDI_STATUS_SYSEX_START) {
|
|
|
|
|
cable_sysex_in_progress |= cable_mask;
|
|
|
|
|
}
|
|
|
|
|
// only add the packet if a sysex message is in progress
|
|
|
|
|
if (cable_sysex_in_progress & cable_mask)
|
|
|
|
|
{
|
|
|
|
|
if (cable_sysex_in_progress & cable_mask) {
|
|
|
|
|
++bytes_to_add_to_stream;
|
|
|
|
|
uint8_t idx;
|
|
|
|
|
for (idx = 2; idx < 4; idx++)
|
|
|
|
|
{
|
|
|
|
|
if (p_midi_host->stream_read.buffer[idx] <= MIDI_MAX_DATA_VAL)
|
|
|
|
|
{
|
|
|
|
|
for (uint8_t idx = 2; idx < 4; idx++) {
|
|
|
|
|
if (p_midi_host->stream_read.buffer[idx] <= MIDI_MAX_DATA_VAL) {
|
|
|
|
|
++bytes_to_add_to_stream;
|
|
|
|
|
}
|
|
|
|
|
else if (p_midi_host->stream_read.buffer[idx] == MIDI_STATUS_SYSEX_END)
|
|
|
|
|
{
|
|
|
|
|
} else if (p_midi_host->stream_read.buffer[idx] == MIDI_STATUS_SYSEX_END) {
|
|
|
|
|
++bytes_to_add_to_stream;
|
|
|
|
|
cable_sysex_in_progress &= (uint16_t) ~cable_mask;
|
|
|
|
|
idx = 4; // force the loop to exit; I hate break statements in loops
|
|
|
|
|
idx = 4;// force the loop to exit; I hate break statements in loops
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (status < MIDI_STATUS_SYSEX_START)
|
|
|
|
|
{
|
|
|
|
|
} 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;
|
|
|
|
|
switch (fake_cin)
|
|
|
|
|
{
|
|
|
|
|
switch (fake_cin) {
|
|
|
|
|
case MIDI_CIN_NOTE_OFF:
|
|
|
|
|
case MIDI_CIN_NOTE_ON:
|
|
|
|
|
case MIDI_CIN_POLY_KEYPRESS:
|
|
|
|
@@ -765,14 +635,11 @@ uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *
|
|
|
|
|
bytes_to_add_to_stream = 2;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break; // Should not get this
|
|
|
|
|
break;// Should not get this
|
|
|
|
|
}
|
|
|
|
|
cable_sysex_in_progress &= (uint16_t)~cable_mask;
|
|
|
|
|
}
|
|
|
|
|
else if (status < MIDI_STATUS_SYSREAL_TIMING_CLOCK)
|
|
|
|
|
{
|
|
|
|
|
switch (status)
|
|
|
|
|
{
|
|
|
|
|
cable_sysex_in_progress &= (uint16_t) ~cable_mask;
|
|
|
|
|
} else if (status < MIDI_STATUS_SYSREAL_TIMING_CLOCK) {
|
|
|
|
|
switch (status) {
|
|
|
|
|
case MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME:
|
|
|
|
|
case MIDI_STATUS_SYSCOM_SONG_SELECT:
|
|
|
|
|
bytes_to_add_to_stream = 2;
|
|
|
|
@@ -786,30 +653,24 @@ uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
cable_sysex_in_progress &= (uint16_t)~cable_mask;
|
|
|
|
|
cable_sysex_in_progress &= (uint16_t) ~cable_mask;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
} else {
|
|
|
|
|
// Real-time message: can be inserted into a sysex message,
|
|
|
|
|
// so do don't clear cable_sysex_in_progress bit
|
|
|
|
|
bytes_to_add_to_stream = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
uint8_t idx;
|
|
|
|
|
for (idx = 1; idx <= bytes_to_add_to_stream; idx++)
|
|
|
|
|
{
|
|
|
|
|
for (uint8_t idx = 1; idx <= bytes_to_add_to_stream; idx++) {
|
|
|
|
|
*p_buffer++ = p_midi_host->stream_read.buffer[idx];
|
|
|
|
|
}
|
|
|
|
|
bytes_buffered += bytes_to_add_to_stream;
|
|
|
|
|
nread = 0;
|
|
|
|
|
if (tu_fifo_peek(&p_midi_host->rx_ff, &one_byte))
|
|
|
|
|
{
|
|
|
|
|
if (tu_edpt_stream_peek(&p_midi_host->ep_stream.rx, &one_byte)) {
|
|
|
|
|
uint8_t new_cable = (one_byte >> 4) & 0xf;
|
|
|
|
|
if (new_cable == *p_cable_num)
|
|
|
|
|
{
|
|
|
|
|
if (new_cable == *p_cable_num) {
|
|
|
|
|
// still on the same cable. Continue reading the stream
|
|
|
|
|
nread = tu_fifo_read_n(&p_midi_host->rx_ff, p_midi_host->stream_read.buffer, 4);
|
|
|
|
|
nread = tu_edpt_stream_read(dev_addr, &p_midi_host->ep_stream.rx, p_midi_host->stream_read.buffer, 4);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -865,19 +726,14 @@ static uint8_t find_string_index(midih_interface_t *ptr, uint8_t jack_id)
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if CFG_MIDI_HOST_DEVSTRINGS
|
|
|
|
|
uint8_t tuh_midi_get_rx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint8_t max_istrings)
|
|
|
|
|
{
|
|
|
|
|
uint8_t nstrings = 0;
|
|
|
|
|
uint8_t tuh_midi_get_rx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint8_t max_istrings) {
|
|
|
|
|
midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr);
|
|
|
|
|
TU_VERIFY(p_midi_host != NULL);
|
|
|
|
|
nstrings = p_midi_host->num_cables_rx;
|
|
|
|
|
if (nstrings > max_istrings)
|
|
|
|
|
{
|
|
|
|
|
TU_VERIFY(p_midi_host != NULL, 0);
|
|
|
|
|
uint8_t nstrings = p_midi_host->num_cables_rx;
|
|
|
|
|
if (nstrings > max_istrings) {
|
|
|
|
|
nstrings = max_istrings;
|
|
|
|
|
}
|
|
|
|
|
uint8_t jack;
|
|
|
|
|
for (jack=0; jack<nstrings; jack++)
|
|
|
|
|
{
|
|
|
|
|
for (uint8_t jack = 0; jack<nstrings; jack++) {
|
|
|
|
|
uint8_t jack_id = p_midi_host->ep_in_associated_jacks[jack];
|
|
|
|
|
istrings[jack] = find_string_index(p_midi_host, jack_id);
|
|
|
|
|
}
|
|
|
|
@@ -886,17 +742,13 @@ uint8_t tuh_midi_get_rx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint
|
|
|
|
|
|
|
|
|
|
uint8_t tuh_midi_get_tx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint8_t max_istrings)
|
|
|
|
|
{
|
|
|
|
|
uint8_t nstrings = 0;
|
|
|
|
|
midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr);
|
|
|
|
|
TU_VERIFY(p_midi_host != NULL);
|
|
|
|
|
nstrings = p_midi_host->num_cables_tx;
|
|
|
|
|
if (nstrings > max_istrings)
|
|
|
|
|
{
|
|
|
|
|
TU_VERIFY(p_midi_host != NULL, 0);
|
|
|
|
|
uint8_t nstrings = p_midi_host->num_cables_tx;
|
|
|
|
|
if (nstrings > max_istrings) {
|
|
|
|
|
nstrings = max_istrings;
|
|
|
|
|
}
|
|
|
|
|
uint8_t jack;
|
|
|
|
|
for (jack=0; jack<nstrings; jack++)
|
|
|
|
|
{
|
|
|
|
|
for (uint8_t jack = 0; jack<nstrings; jack++) {
|
|
|
|
|
uint8_t jack_id = p_midi_host->ep_out_associated_jacks[jack];
|
|
|
|
|
istrings[jack] = find_string_index(p_midi_host, jack_id);
|
|
|
|
|
}
|
|
|
|
@@ -909,8 +761,7 @@ uint8_t tuh_midi_get_all_istrings(uint8_t dev_addr, const uint8_t** istrings)
|
|
|
|
|
midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr);
|
|
|
|
|
TU_VERIFY(p_midi_host != NULL);
|
|
|
|
|
uint8_t nstrings = p_midi_host->num_string_indices;
|
|
|
|
|
if (nstrings)
|
|
|
|
|
*istrings = p_midi_host->all_string_indices;
|
|
|
|
|
if (nstrings) { *istrings = p_midi_host->all_string_indices; }
|
|
|
|
|
return nstrings;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|