mirror of
https://github.com/hathach/tinyusb.git
synced 2025-03-29 19:20:22 +00:00
correct midi stream read behavior to read until user buffer is full or no more data from usb fifo
This commit is contained in:
parent
350eb11277
commit
48bb96f507
@ -52,6 +52,12 @@ typedef struct
|
|||||||
uint8_t ep_in;
|
uint8_t ep_in;
|
||||||
uint8_t ep_out;
|
uint8_t ep_out;
|
||||||
|
|
||||||
|
// For Stream read()/write() API
|
||||||
|
// Messages are always 4 bytes long, queue them for reading and writing so the
|
||||||
|
// callers can use the Stream interface with single-byte read/write calls.
|
||||||
|
midid_stream_t stream_write;
|
||||||
|
midid_stream_t stream_read;
|
||||||
|
|
||||||
/*------------- From this point, data is not cleared by bus reset -------------*/
|
/*------------- From this point, data is not cleared by bus reset -------------*/
|
||||||
// FIFO
|
// FIFO
|
||||||
tu_fifo_t rx_ff;
|
tu_fifo_t rx_ff;
|
||||||
@ -64,12 +70,6 @@ typedef struct
|
|||||||
osal_mutex_def_t tx_ff_mutex;
|
osal_mutex_def_t tx_ff_mutex;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// For Stream read()/write() API
|
|
||||||
// Messages are always 4 bytes long, queue them for reading and writing so the
|
|
||||||
// callers can use the Stream interface with single-byte read/write calls.
|
|
||||||
midid_stream_t stream_write;
|
|
||||||
midid_stream_t stream_read;
|
|
||||||
|
|
||||||
// Endpoint Transfer buffer
|
// Endpoint Transfer buffer
|
||||||
CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_MIDI_EP_BUFSIZE];
|
CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_MIDI_EP_BUFSIZE];
|
||||||
CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_MIDI_EP_BUFSIZE];
|
CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_MIDI_EP_BUFSIZE];
|
||||||
@ -127,58 +127,71 @@ uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num)
|
|||||||
uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize)
|
uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize)
|
||||||
{
|
{
|
||||||
(void) cable_num;
|
(void) cable_num;
|
||||||
|
TU_VERIFY(bufsize, 0);
|
||||||
|
|
||||||
|
uint8_t* buf8 = (uint8_t*) buffer;
|
||||||
|
|
||||||
midid_interface_t* midi = &_midid_itf[itf];
|
midid_interface_t* midi = &_midid_itf[itf];
|
||||||
midid_stream_t* stream = &midi->stream_read;
|
midid_stream_t* stream = &midi->stream_read;
|
||||||
|
|
||||||
TU_VERIFY(bufsize, 0);
|
uint32_t total_read = 0;
|
||||||
|
while( bufsize )
|
||||||
// Get new packet from fifo
|
|
||||||
if ( stream->total == 0 )
|
|
||||||
{
|
{
|
||||||
TU_VERIFY(tud_midi_n_packet_read(itf, stream->buffer), 0);
|
// Get new packet from fifo, then set packet expected bytes
|
||||||
|
if ( stream->total == 0 )
|
||||||
uint8_t const code_index = stream->buffer[0] & 0x0f;
|
|
||||||
|
|
||||||
// MIDI 1.0 Table 4-1: Code Index Number Classifications
|
|
||||||
switch(code_index)
|
|
||||||
{
|
{
|
||||||
case MIDI_CIN_MISC:
|
// return if there is no more data from fifo
|
||||||
case MIDI_CIN_CABLE_EVENT:
|
if ( !tud_midi_n_packet_read(itf, stream->buffer) ) return total_read;
|
||||||
// These are reserved and unused, possibly issue somewhere, skip this packet
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MIDI_CIN_SYSEX_END_1BYTE:
|
uint8_t const code_index = stream->buffer[0] & 0x0f;
|
||||||
case MIDI_CIN_1BYTE_DATA:
|
|
||||||
stream->total = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MIDI_CIN_SYSCOM_2BYTE :
|
// MIDI 1.0 Table 4-1: Code Index Number Classifications
|
||||||
case MIDI_CIN_SYSEX_END_2BYTE :
|
switch(code_index)
|
||||||
case MIDI_CIN_PROGRAM_CHANGE :
|
{
|
||||||
case MIDI_CIN_CHANNEL_PRESSURE :
|
case MIDI_CIN_MISC:
|
||||||
stream->total = 2;
|
case MIDI_CIN_CABLE_EVENT:
|
||||||
break;
|
// These are reserved and unused, possibly issue somewhere, skip this packet
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
case MIDI_CIN_SYSEX_END_1BYTE:
|
||||||
stream->total = 3;
|
case MIDI_CIN_1BYTE_DATA:
|
||||||
break;
|
stream->total = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MIDI_CIN_SYSCOM_2BYTE :
|
||||||
|
case MIDI_CIN_SYSEX_END_2BYTE :
|
||||||
|
case MIDI_CIN_PROGRAM_CHANGE :
|
||||||
|
case MIDI_CIN_CHANNEL_PRESSURE :
|
||||||
|
stream->total = 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
stream->total = 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy data up to bufsize
|
||||||
|
uint32_t const count = tu_min32(stream->total - stream->index, bufsize);
|
||||||
|
|
||||||
|
// Skip the header (1st byte) in the buffer
|
||||||
|
memcpy(buf8, stream->buffer + 1 + stream->index, count);
|
||||||
|
|
||||||
|
total_read += count;
|
||||||
|
stream->index += count;
|
||||||
|
buf8 += count;
|
||||||
|
bufsize -= count;
|
||||||
|
|
||||||
|
// complete current event packet, reset stream
|
||||||
|
if ( stream->total == stream->index )
|
||||||
|
{
|
||||||
|
stream->index = 0;
|
||||||
|
stream->total = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t const n = tu_min32(stream->total - stream->index, bufsize);
|
return total_read;
|
||||||
|
|
||||||
// Skip the header (1st byte) in the buffer
|
|
||||||
memcpy(buffer, stream->buffer + 1 + stream->index, n);
|
|
||||||
stream->index += n;
|
|
||||||
|
|
||||||
if ( stream->total == stream->index )
|
|
||||||
{
|
|
||||||
stream->index = 0;
|
|
||||||
stream->total = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4])
|
bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4])
|
||||||
@ -224,7 +237,7 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const*
|
|||||||
|
|
||||||
midid_stream_t* stream = &midi->stream_write;
|
midid_stream_t* stream = &midi->stream_write;
|
||||||
|
|
||||||
uint32_t written = 0;
|
uint32_t total_written = 0;
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
while ( i < bufsize )
|
while ( i < bufsize )
|
||||||
{
|
{
|
||||||
@ -296,7 +309,7 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const*
|
|||||||
{
|
{
|
||||||
// On-going (buffering) packet
|
// On-going (buffering) packet
|
||||||
|
|
||||||
TU_ASSERT(stream->index < 4, written);
|
TU_ASSERT(stream->index < 4, total_written);
|
||||||
stream->buffer[stream->index] = data;
|
stream->buffer[stream->index] = data;
|
||||||
stream->index++;
|
stream->index++;
|
||||||
|
|
||||||
@ -316,14 +329,14 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const*
|
|||||||
|
|
||||||
uint16_t const count = tu_fifo_write_n(&midi->tx_ff, stream->buffer, 4);
|
uint16_t const count = tu_fifo_write_n(&midi->tx_ff, stream->buffer, 4);
|
||||||
|
|
||||||
// reset buffer
|
// complete current event packet, reset stream
|
||||||
stream->index = stream->total = 0;
|
stream->index = stream->total = 0;
|
||||||
|
|
||||||
// fifo overflow, here we assume FIFO is multiple of 4 and didn't check remaining before writing
|
// fifo overflow, here we assume FIFO is multiple of 4 and didn't check remaining before writing
|
||||||
if ( count != 4 ) break;
|
if ( count != 4 ) break;
|
||||||
|
|
||||||
// updated written if succeeded
|
// updated written if succeeded
|
||||||
written = i;
|
total_written = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
@ -331,7 +344,7 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const*
|
|||||||
|
|
||||||
write_flush(midi);
|
write_flush(midi);
|
||||||
|
|
||||||
return written;
|
return total_written;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4])
|
bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user