summaryrefslogtreecommitdiff
path: root/profiles/midi
diff options
context:
space:
mode:
authorTedd Ho-Jeong An <tedd.an@intel.com>2020-06-19 11:34:55 -0700
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2020-06-22 10:13:31 -0700
commitb53fef50969b49f7c2a1376a11677817d3bdcf80 (patch)
tree7b2628da2f4d95c3ef68af9310100d1d90154f87 /profiles/midi
parent3cc6624dcefa9c3a804ace48694cc52c654efb19 (diff)
downloadbluez-b53fef50969b49f7c2a1376a11677817d3bdcf80.tar.gz
midi: Fix SysEx parser in MIDI plugin
The SysEx end of message parser didn't consider the fact that timestampsLow are in the stream and it might have the EOX (F7) byte as well. Fix that by always assuming the first system message byte is the timestampLow. Future work would involve support other type of system message bytes, such as real-time.
Diffstat (limited to 'profiles/midi')
-rw-r--r--profiles/midi/libmidi.c38
1 files changed, 31 insertions, 7 deletions
diff --git a/profiles/midi/libmidi.c b/profiles/midi/libmidi.c
index 4b4df799f..7d57e7335 100644
--- a/profiles/midi/libmidi.c
+++ b/profiles/midi/libmidi.c
@@ -331,6 +331,30 @@ static size_t handle_end_of_sysex(struct midi_read_parser *parser,
return sysex_length + 1; /* +1 because of timestampLow */
}
+/* Searches the end of a SysEx message that contains a timestampLow
+ * before the SysEx end byte. Returns the number of bytes of valid
+ * SysEx payload in the buffer.
+ */
+static size_t sysex_eox_len(const uint8_t *data, size_t size)
+{
+ size_t i = 0;
+
+ MIDI_ASSERT(size > 0);
+
+ if (data[i] == 0xF0)
+ i++;
+
+ /* Search for timestamp low */
+ while (i < size) {
+ if ((data[i] & 0x80)) {
+ i++;
+ break;
+ }
+ i++;
+ }
+
+ return (i < size && data[i] == 0xF7) ? i : 0;
+}
size_t midi_read_raw(struct midi_read_parser *parser, const uint8_t *data,
@@ -368,14 +392,14 @@ size_t midi_read_raw(struct midi_read_parser *parser, const uint8_t *data,
/* System Common Messages */
case 0xF0: /* SysEx Start */ {
- uint8_t *pos;
+ size_t sysex_length;
/* cleanup Running Status Message */
parser->rstatus = 0;
- /* Avoid parsing if SysEx is contained in one BLE packet */
- if ((pos = memchr(data + i, 0xF7, size - i))) {
- const size_t sysex_length = pos - (data + i);
+ sysex_length = sysex_eox_len(data + i, size - i);
+ /* Search for End of SysEx message in one BLE message */
+ if (sysex_length > 0) {
midi_size = handle_end_of_sysex(parser, ev, data + i,
sysex_length);
} else {
@@ -424,10 +448,10 @@ size_t midi_read_raw(struct midi_read_parser *parser, const uint8_t *data,
/* Check for SysEx messages */
if (parser->sysex_stream.len > 0) {
- uint8_t *pos;
+ size_t sysex_length;
- if ((pos = memchr(data + i, 0xF7, size - i))) {
- const size_t sysex_length = pos - (data + i);
+ sysex_length = sysex_eox_len(data + i, size - i);
+ if (sysex_length > 0) {
midi_size = handle_end_of_sysex(parser, ev, data + i,
sysex_length);
} else {