Arturia MCC SysEx Protocol — Reverse-Engineered¶
Captured 2026-04-12 by sniffing MCC ↔ MiniLab 3 USB traffic (USBPcap + tshark). Full bidirectional capture.
Common manufacturer framing¶
00 20 6B— Arturia manufacturer SysEx ID (3 bytes).<DEV_HI> <DEV_LO>— 2-byte product identifier. Observed:- MiniLab 3:
7F 42 - MatrixBrute:
06 01(per MBPV decompilation)
Opcode table (decoded from MiniLab 3)¶
| Opcode | Direction(s) | Frame size | Purpose |
|---|---|---|---|
03 00 20 3F |
host→device | 11 bytes | Query current preset info |
04 00 20 <ASCII> 00 |
host→device | variable | Store preset with ASCII name (timestamp auto-generated) |
20 <SEC> 40 <ID> 00 |
host→device | 12 bytes | GET parameter (read) |
21 <SEC> 40 <ID> <MSB> <LSB> |
both | 13 bytes | SET parameter (write or reply) |
GET / SET framing (the core protocol)¶
GET (host → device, 12 bytes):
F0 00 20 6B <DEV_HI> <DEV_LO> 20 <SEC> 40 <PARAM_ID> 00 F7
SET (either direction, 13 bytes):
F0 00 20 6B <DEV_HI> <DEV_LO> 21 <SEC> 40 <PARAM_ID> <VAL_MSB> <VAL_LSB> F7
<SEC>— section / bank (7-bit). Observed:03,08. Each section holds up to 128 parameters.<PARAM_ID>— parameter index within section (0..127).<VAL_MSB> <VAL_LSB>— 14-bit value (0..16383 effective).
When MCC opens a session, it iterates over all parameter IDs in each known section, sending a GET and expecting a SET reply. That's the "dump" seen as 371 SysEx messages in 24s.
When the user drags a control in MCC, MCC sends a single SET with the new value — live per-parameter SysEx write confirmed.
Store preset (opcode 04)¶
Observed payload: ?User 1 2026_04_12 18.43.00 (leading ? = 0x3F, MCC-generated timestamp form YYYY_MM_DD HH.MM.SS).
Query preset (opcode 03)¶
Trailing 3F = ? (literal byte). Likely "give me current preset name/info" — the device is expected to reply with an 04-opcode message containing the ASCII name.
Live performance: not SysEx¶
Physical knobs / pads emit standard MIDI CC on the Minilab3 MIDI port — not SysEx. Consistent with the PencilResearch CSV for MatrixBrute: live control = CC, config/edit = SysEx.
USB-MIDI 1.0 packet framing¶
Over USB, each SysEx byte stream is fragmented into 4-byte USB-MIDI packets:
CIN values seen:
- 4 = SysEx starts/continues, 3 valid payload bytes
- 5 = SysEx ends with 1 valid byte
- 6 = SysEx ends with 2 valid bytes
- 7 = SysEx ends with 3 valid bytes
Known sections on MiniLab 3¶
| Section | Observed params | Probable content |
|---|---|---|
03 |
0..7F (full sweep) | Main controls (128 params) |
08 |
0..19 observed | Secondary bank (pads/keys/etc.) |
Section meanings to be confirmed by targeted MCC-edit experiments (task #8).
Implications for MatrixBrute driver¶
- Live per-parameter SysEx is feasible. The
21 <sec> 40 <id> <msb> <lsb>frame, sent host→device, is how MCC modifies individual params on the MiniLab. MatrixBrute should behave the same way (same protocol family). - Mod matrix control becomes plausible. The 256-button matrix could be 1-2 sections of param writes. Needs verification when hardware arrives.
- No 7↔8bit bulk encoding required for most driver operations — just bidirectional mapping of OSC addresses ↔
(SEC, PARAM_ID, value)tuples. - Device ID for MatrixBrute SET:
F0 00 20 6B 06 01 21 <sec> 40 <id> <msb> <lsb> F7. To be tested live.
Raw captures archived¶
captures/minilab3_usb/mcc_minilab.pcap— MCC↔MiniLab 3, both directions, recall + edit + store.captures/minilab3/session1.log— MCC→MiniLab 3, legacy loopMIDI attempt (device→host only).