MiniLab 3 — Definitive SysEx surface¶
Combined result of static firmware RE (Ghidra) + empirical black-box fuzzing.
Method¶
- Firmware: MiniLab3 fw 1.2.0 (
MiniLab3_fw_1__fw1_2_0_1466__2024_12_16.bin, STM32G0B0RET6, ARM Thumb, unencrypted, load address0x08008800). - Static RE: Ghidra headless auto-analysis + scripted XRef and decompilation of the MCC SysEx dispatcher (
0x08017952) and its callees. - Empirical fuzz:
mb-driver fuzz-sysexsweptF0 00 20 6B 7F 42 20 <SEC> 40 <ID> 00 F7forSEC ∈ 0x00..0xEF,ID ∈ 0x00..0x7F— 30 720 GETs total, all replies captured.
Result: exactly 768 SysEx parameters exposed¶
Reply distribution:
| Section | Params replying | Purpose (inferred) |
|---|---|---|
0x03 |
128 | Preset slot 1 (User 1) |
0x04 |
128 | Preset slot 2 (User 2) |
0x05 |
128 | Preset slot 3 (User 3) |
0x06 |
128 | Preset slot 4 (User 4) |
0x07 |
128 | Preset slot 5 (User 5) |
0x08 |
128 | Alternate slot (Arturia / DAW — values differ from User slots) |
0x00..0x02 |
0 | No reply |
0x09..0xEF |
0 | No reply |
Sections 0x03-0x07 return identical payloads in shape and range — confirming they are 5 interchangeable preset banks, consistent with the UI strings User 1..User 5 observed in the firmware. Section 0x08 has a different layout, matching the Arturia/DAW string cluster.
Exactly matches the sysex-controls reverse-engineered parameter set (~264 distinct logical controls, each appearing once per preset slot = 264×~3 and an additional shared subset ≈ 768).
What is NOT exposed via SysEx¶
Confirmed by concordance of static RE and empirical fuzz:
- Arpeggiator (7 params: Mode, Division, Swing, Gate, Rate, Sync, Octave) — present on device (labels + init function at
0x0802023C), routed only from local UI menu handler (FUN_080203FC). Arp method-ptr table at0x080340ACis consulted exclusively fromFUN_0802023C, never from the MCC dispatcher call graph. - Chord mode (Fifth, sus2/4, Maj7/9/11, min7/9/11, User) — implementation at
0x080219F8, toggled only via UI command code 8 routed through0x08012CE4(which is a UI event dispatcher, not a SysEx handler). - Hold mode (
Hold mode ON/OFFstrings) — only referenced from UI callbacks. - Scale quantizer — no evidence it's addressable externally.
- Velocity curves (sysex-controls marked this as [AMBIGUOUS]) — confirmed absent from the 768 reachable params.
MCC dispatcher semantics (decoded)¶
Entry function 0x08017952. Buffer byte[0] = opcode; opcode & 0x60 selects category:
| Mask | Opcode range | Handler |
|---|---|---|
0x00 (& 0x60 == 0x00) |
0x01-0x1F | Switch on buffer[1]: cases 0x01, 0x06, 0x0A, 0x0B — non-parameter commands |
0x20 (& 0x60 == 0x20) |
0x20-0x3F | GET/SET with section at buffer[1]. Sections 0x03-0x08 → param read via FUN_08018252 → FUN_08018704 → FUN_0801A840 (40-byte-entry table). Section 1 / 0x81 / 0xF2 are special-case fall-throughs (kept for compat, partial decoding not consequential). |
0x40 / 0x60 |
0x40+ | Not routed — fall through to exit |
Other opcodes observed in traffic (not tested in fuzz)¶
These were captured in the MCC ↔ MiniLab USB sniff but are not read/write:
- 0x03 00 20 3F — "query preset info" (returns name)
- 0x04 00 20 <ASCII> — "store preset with ASCII name"
These don't live in the 0x20-0x3F GET/SET path; they flow through the other branch of the MCC_Dispatcher switch (cases 0x06, 0x0A, 0x0B we haven't fully decoded, but they clearly do not expose arp/chord either by the FUN_0801A840 evidence).
Bottom line for driver scope¶
- Expose 768 × 14-bit values via OSC via
/minilab3/param/*path, already implemented. - 264 of these have human-friendly OSC routes (from sysex-controls reverse) in
minilab3_params.rs. - Arp/Chord/Hold must be implemented client-side in SuperCollider/BPscript — they are not pilotable via MCC SysEx on firmware 1.2.0 (and there is no evidence Arturia plans to expose them).
- Pad colors and display are exposed via different opcodes (0x02 16 … / 0x04 02 60 …) — those ARE implemented in the driver.