summaryrefslogtreecommitdiff
path: root/src/class
diff options
context:
space:
mode:
authorhathach <[email protected]>2021-04-02 15:08:36 +0700
committerhathach <[email protected]>2021-04-02 15:08:36 +0700
commit48bb96f5072a173189d9076c5c2b1f5066327bf6 (patch)
tree96621164853672e92b8838371521f2150d03edc9 /src/class
parent350eb1127755f3ee0dd3dd186cc31e9492916a0c (diff)
correct midi stream read behavior to read until user buffer is full or no more data from usb fifo
Diffstat (limited to 'src/class')
-rw-r--r--src/class/midi/midi_device.c109
1 files changed, 61 insertions, 48 deletions
diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c
index a4cc104a8..9ccbb733c 100644
--- a/src/class/midi/midi_device.c
+++ b/src/class/midi/midi_device.c
@@ -52,6 +52,12 @@ typedef struct
uint8_t ep_in;
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 -------------*/
// FIFO
tu_fifo_t rx_ff;
@@ -64,12 +70,6 @@ typedef struct
osal_mutex_def_t tx_ff_mutex;
#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
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];
@@ -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)
{
(void) cable_num;
+ TU_VERIFY(bufsize, 0);
+
+ uint8_t* buf8 = (uint8_t*) buffer;
+
midid_interface_t* midi = &_midid_itf[itf];
midid_stream_t* stream = &midi->stream_read;
- TU_VERIFY(bufsize, 0);
-
- // Get new packet from fifo
- if ( stream->total == 0 )
+ uint32_t total_read = 0;
+ while( bufsize )
{
- 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 )
+ {
+ // return if there is no more data from fifo
+ if ( !tud_midi_n_packet_read(itf, stream->buffer) ) return total_read;
- uint8_t const code_index = stream->buffer[0] & 0x0f;
+ 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:
- case MIDI_CIN_CABLE_EVENT:
- // These are reserved and unused, possibly issue somewhere, skip this packet
- return 0;
- break;
+ // MIDI 1.0 Table 4-1: Code Index Number Classifications
+ switch(code_index)
+ {
+ case MIDI_CIN_MISC:
+ case MIDI_CIN_CABLE_EVENT:
+ // These are reserved and unused, possibly issue somewhere, skip this packet
+ return 0;
+ break;
- case MIDI_CIN_SYSEX_END_1BYTE:
- case MIDI_CIN_1BYTE_DATA:
- stream->total = 1;
- break;
+ case MIDI_CIN_SYSEX_END_1BYTE:
+ case MIDI_CIN_1BYTE_DATA:
+ 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;
+ 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;
+ default:
+ stream->total = 3;
+ break;
+ }
}
- }
- uint32_t const n = tu_min32(stream->total - stream->index, bufsize);
+ // 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(buffer, stream->buffer + 1 + stream->index, n);
- stream->index += n;
+ // Skip the header (1st byte) in the buffer
+ memcpy(buf8, stream->buffer + 1 + stream->index, count);
- if ( stream->total == stream->index )
- {
- stream->index = 0;
- stream->total = 0;
+ 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;
+ }
}
- return n;
+ return total_read;
}
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;
- uint32_t written = 0;
+ uint32_t total_written = 0;
uint32_t i = 0;
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
- TU_ASSERT(stream->index < 4, written);
+ TU_ASSERT(stream->index < 4, total_written);
stream->buffer[stream->index] = data;
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);
- // reset buffer
+ // complete current event packet, reset stream
stream->index = stream->total = 0;
// fifo overflow, here we assume FIFO is multiple of 4 and didn't check remaining before writing
if ( count != 4 ) break;
// updated written if succeeded
- written = i;
+ total_written = 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);
- return written;
+ return total_written;
}
bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4])