summaryrefslogtreecommitdiff
path: root/src/class/midi
diff options
context:
space:
mode:
authorKay Sievers <[email protected]>2020-01-16 10:06:52 +0100
committerKay Sievers <[email protected]>2020-01-16 10:11:37 +0100
commit73228a67efd122915e43ed445ddaec8285786d28 (patch)
treecdb8fbddd3b2f68c36e0a59ef32eace8569eb442 /src/class/midi
parent4daeb3818571b9f1bf356f13c65e47af91e4ad79 (diff)
MIDI: Add packet interface
This changes the internal buffering to the raw 4-byte messages. The conversion of the messages to a byte-stream moved to the read/write methods. It adds a raw packet interface to send and retrieve the raw 4-byte USB MIDI message: static inline bool tud_midi_receive (uint8_t packet[4]); static inline bool tud_midi_send (uint8_t const packet[4]); MIDI USB packets carry virtual cable/wire/plug data in the packet header, which cannot be exported in the byte-stream interface. The raw packet interface allows to send and and receive the complete USB message.
Diffstat (limited to 'src/class/midi')
-rw-r--r--src/class/midi/midi_device.c145
-rw-r--r--src/class/midi/midi_device.h15
2 files changed, 106 insertions, 54 deletions
diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c
index 312405621..82ceba87f 100644
--- a/src/class/midi/midi_device.c
+++ b/src/class/midi/midi_device.c
@@ -56,11 +56,15 @@ typedef struct
osal_mutex_def_t tx_ff_mutex;
#endif
- // We need to pack messages into words before queueing their transmission so buffer across write
- // calls.
- uint8_t message_buffer[4];
- uint8_t message_buffer_length;
- uint8_t message_target_length;
+ // 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.
+ uint8_t write_buffer[4];
+ uint8_t write_buffer_length;
+ uint8_t write_target_length;
+
+ uint8_t read_buffer[4];
+ uint8_t read_buffer_length;
+ uint8_t read_target_length;
// Endpoint Transfer buffer
CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_MIDI_EPSIZE];
@@ -93,24 +97,14 @@ uint32_t tud_midi_n_available(uint8_t itf, uint8_t jack_id)
uint32_t tud_midi_n_read(uint8_t itf, uint8_t jack_id, void* buffer, uint32_t bufsize)
{
(void) jack_id;
- return tu_fifo_read_n(&_midid_itf[itf].rx_ff, buffer, bufsize);
-}
-
-void tud_midi_n_read_flush (uint8_t itf, uint8_t jack_id)
-{
- (void) jack_id;
- tu_fifo_clear(&_midid_itf[itf].rx_ff);
-}
+ midid_interface_t* midi = &_midid_itf[itf];
-void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bufsize) {
- if (bufsize % 4 != 0) {
- return;
- }
+ // Fill empty buffer
+ if (midi->read_buffer_length == 0) {
+ if (!tud_midi_n_receive(itf, midi->read_buffer))
+ return 0;
- for(uint32_t i=0; i<bufsize; i += 4) {
- uint8_t header = buffer[i];
- // uint8_t cable_number = (header & 0xf0) >> 4;
- uint8_t code_index = header & 0x0f;
+ uint8_t code_index = midi->read_buffer[0] & 0x0f;
// We always copy over the first byte.
uint8_t count = 1;
// Ignore subsequent bytes based on the code.
@@ -120,10 +114,40 @@ void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bu
count = 3;
}
}
- tu_fifo_write_n(&midi->rx_ff, &buffer[i + 1], count);
+
+ midi->read_buffer_length = count;
+ }
+
+ uint32_t n = midi->read_buffer_length - midi->read_target_length;
+ if (bufsize < n)
+ n = bufsize;
+
+ // Skip the header in the buffer
+ memcpy(buffer, midi->read_buffer + 1 + midi->read_target_length, n);
+ midi->read_target_length += n;
+
+ if (midi->read_target_length == midi->read_buffer_length) {
+ midi->read_buffer_length = 0;
+ midi->read_target_length = 0;
}
+
+ return n;
+}
+
+void tud_midi_n_read_flush (uint8_t itf, uint8_t jack_id)
+{
+ (void) jack_id;
+ tu_fifo_clear(&_midid_itf[itf].rx_ff);
+}
+
+bool tud_midi_n_receive (uint8_t itf, uint8_t packet[4])
+{
+ return tu_fifo_read_n(&_midid_itf[itf].rx_ff, packet, 4);
}
+void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bufsize) {
+ tu_fifo_write_n(&midi->rx_ff, buffer, bufsize);
+}
//--------------------------------------------------------------------+
// WRITE API
@@ -154,62 +178,59 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, u
uint32_t i = 0;
while (i < bufsize) {
uint8_t data = buffer[i];
- if (midi->message_buffer_length == 0) {
+ if (midi->write_buffer_length == 0) {
uint8_t msg = data >> 4;
- midi->message_buffer[1] = data;
- midi->message_buffer_length = 2;
+ midi->write_buffer[1] = data;
+ midi->write_buffer_length = 2;
// Check to see if we're still in a SysEx transmit.
- if (midi->message_buffer[0] == 0x4) {
+ if (midi->write_buffer[0] == 0x4) {
if (data == 0xf7) {
- midi->message_buffer[0] = 0x5;
+ midi->write_buffer[0] = 0x5;
} else {
- midi->message_buffer_length = 4;
+ midi->write_buffer_length = 4;
}
} else if ((msg >= 0x8 && msg <= 0xB) || msg == 0xE) {
- midi->message_buffer[0] = jack_id << 4 | msg;
- midi->message_target_length = 4;
- } else if (msg == 0xC || msg == 0xD) {
- midi->message_buffer[0] = jack_id << 4 | msg;
- midi->message_target_length = 3;
+ midi->write_buffer[0] = jack_id << 4 | msg;
+ midi->write_target_length = 4;
} else if (msg == 0xf) {
if (data == 0xf0) {
- midi->message_buffer[0] = 0x4;
- midi->message_target_length = 4;
+ midi->write_buffer[0] = 0x4;
+ midi->write_target_length = 4;
} else if (data == 0xf1 || data == 0xf3) {
- midi->message_buffer[0] = 0x2;
- midi->message_target_length = 3;
+ midi->write_buffer[0] = 0x2;
+ midi->write_target_length = 3;
} else if (data == 0xf2) {
- midi->message_buffer[0] = 0x3;
- midi->message_target_length = 4;
+ midi->write_buffer[0] = 0x3;
+ midi->write_target_length = 4;
} else {
- midi->message_buffer[0] = 0x5;
- midi->message_target_length = 2;
+ midi->write_buffer[0] = 0x5;
+ midi->write_target_length = 2;
}
} else {
// Pack individual bytes if we don't support packing them into words.
- midi->message_buffer[0] = jack_id << 4 | 0xf;
- midi->message_buffer[2] = 0;
- midi->message_buffer[3] = 0;
- midi->message_buffer_length = 2;
- midi->message_target_length = 2;
+ midi->write_buffer[0] = jack_id << 4 | 0xf;
+ midi->write_buffer[2] = 0;
+ midi->write_buffer[3] = 0;
+ midi->write_buffer_length = 2;
+ midi->write_target_length = 2;
}
} else {
- midi->message_buffer[midi->message_buffer_length] = data;
- midi->message_buffer_length += 1;
+ midi->write_buffer[midi->write_buffer_length] = data;
+ midi->write_buffer_length += 1;
// See if this byte ends a SysEx.
- if (midi->message_buffer[0] == 0x4 && data == 0xf7) {
- midi->message_buffer[0] = 0x4 + (midi->message_buffer_length - 1);
- midi->message_target_length = midi->message_buffer_length;
+ if (midi->write_buffer[0] == 0x4 && data == 0xf7) {
+ midi->write_buffer[0] = 0x4 + (midi->write_buffer_length - 1);
+ midi->write_target_length = midi->write_buffer_length;
}
}
- if (midi->message_buffer_length == midi->message_target_length) {
- uint16_t written = tu_fifo_write_n(&midi->tx_ff, midi->message_buffer, 4);
+ if (midi->write_buffer_length == midi->write_target_length) {
+ uint16_t written = tu_fifo_write_n(&midi->tx_ff, midi->write_buffer, 4);
if (written < 4) {
TU_ASSERT( written == 0 );
break;
}
- midi->message_buffer_length = 0;
+ midi->write_buffer_length = 0;
}
i++;
}
@@ -218,6 +239,22 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, u
return i;
}
+bool tud_midi_n_send (uint8_t itf, uint8_t const packet[4])
+{
+ midid_interface_t* midi = &_midid_itf[itf];
+ if (midi->itf_num == 0) {
+ return 0;
+ }
+
+ if (tu_fifo_remaining(&midi->tx_ff) < 4)
+ return false;
+
+ tu_fifo_write_n(&midi->tx_ff, packet, 4);
+ maybe_transmit(midi, itf);
+
+ return true;
+}
+
//--------------------------------------------------------------------+
// USBD Driver API
//--------------------------------------------------------------------+
diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h
index fbf4bce0b..e4d4f9d51 100644
--- a/src/class/midi/midi_device.h
+++ b/src/class/midi/midi_device.h
@@ -62,6 +62,9 @@ uint32_t tud_midi_n_write (uint8_t itf, uint8_t jack_id, uint8_t const* buf
static inline
uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t jack_id, uint8_t b1, uint8_t b2, uint8_t b3);
+bool tud_midi_n_receive (uint8_t itf, uint8_t packet[4]);
+bool tud_midi_n_send (uint8_t itf, uint8_t const packet[4]);
+
//--------------------------------------------------------------------+
// Application API (Interface0)
//--------------------------------------------------------------------+
@@ -71,6 +74,8 @@ static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize);
static inline void tud_midi_read_flush (void);
static inline uint32_t tud_midi_write (uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize);
static inline uint32_t tudi_midi_write24 (uint8_t jack_id, uint8_t b1, uint8_t b2, uint8_t b3);
+static inline bool tud_midi_receive (uint8_t packet[4]);
+static inline bool tud_midi_send (uint8_t const packet[4]);
//--------------------------------------------------------------------+
// Application Callback API (weak is optional)
@@ -118,6 +123,16 @@ static inline uint32_t tudi_midi_write24 (uint8_t jack_id, uint8_t b1, uint8_t b
return tud_midi_write(jack_id, msg, 3);
}
+static inline bool tud_midi_receive (uint8_t packet[4])
+{
+ return tud_midi_n_receive(0, packet);
+}
+
+static inline bool tud_midi_send (uint8_t const packet[4])
+{
+ return tud_midi_n_send(0, packet);
+}
+
//--------------------------------------------------------------------+
// Internal Class Driver API
//--------------------------------------------------------------------+