01 — Overview: hardware, transport, software
The device
| Product | SORAN Dual Stomp Lite (same firmware family as Dual Stomp and Tiny Stomp) |
| USB IDs | VID 0x3962, PID 0x2000 |
| USB strings | Manufacturer “SORAN”, Product “JME STOMPBOX”, serial = a date-like string |
| USB speed | High-speed (480 Mb/s) |
| Firmware tested | V1.1.1 (pedal reports V1.1.1 / JME-01) |
| MCU | NXP i.MX RT10xx (Cortex-M7), per firmware strings |
| Vendor | The app and firmware are by NUX (Cherub). Bundle id com.jiyou.stompManager, NUX build paths, NUX DFU container |
USB interfaces (all class compliant)
| If | Class | Purpose | Linux driver |
|---|---|---|---|
| 0 | Audio Control (UAC2, protocol 0x20) | audio interface | snd-usb-audio |
| 1, 2 | Audio Streaming (UAC2) | playback / capture | snd-usb-audio |
| 3 | Audio Control (MIDI) | snd-usb-audio | |
| 4 | MIDI Streaming | all control traffic | snd-usb-audio → ALSA rawmidi/seq |
There is no vendor-specific interface. Everything the editor does goes over standard USB-MIDI, so on Linux you
need no kernel driver, no libusb and no udev rule beyond ALSA access. The device will show up in amidi -l /
aconnect -l as “JME STOMPBOX”.
Firmware updates are different: they use a separate NUX “Device Firmware Updater” over USB HID in DFU mode. That is out of scope here.
Bluetooth: with Wireless on, the pedal also speaks BLE-MIDI as “JME STOMPBOX” (service
03b80e5a-ede8-4b33-a751-6ce34ec4c700, characteristic 7772e5db-3868-4112-a1a9-f2669d106bf3), with exactly the
same messages as over USB, only in BLE-MIDI framing. Confirmed on V1.1.1: the full startup sync, every live control,
preset switching and acked SysEx writes (examples/ble_check.rs). Two differences: the pedal can’t take unpaced
bursts (61 CCs sent back to back froze it until a power cycle; the official app sends CCs ≥ 11 ms apart), and
replies take 40–240 ms (median 95 ms) instead of about 1 ms, so the startup sync takes about 19 s. The official app
doesn’t import NAM models or IRs over Bluetooth, but the pedal takes them: a NAM import (62 acked writes) took 10.5 s
and an IR import 12.4 s, and both slot names read back. The separate classic-Bluetooth “headset” (A2DP/AVRCP) device is the
pedal’s Bluetooth audio, not MIDI.
Protocol in one paragraph
Live control is plain MIDI: the pedal reports on channel 1 and the host commands on channel 2, with the
same CC numbers. Every module has a “head” CC = (off?0x40:0) | model plus a block of parameter CCs whose values are
the 0–100 numbers the app shows. Presets switch with Program Change. Bulk data (whole presets, names, global settings,
looper/drum/tuner records, NAM/IR uploads) goes over vendor SysEx F0 00 21 7A 70 <cmd> <dir> … F7 with
read (0) / write (1) / reply (2) / ack (3), strictly request → response. Larger records are 8-bit structs packed into
a 7-bit little-endian bitstream.
Cheat sheet
| USB | 3962:2000, class-compliant UAC2 + USB-MIDI, no vendor interface |
| Channels | Pedal → host on channel 1, host → pedal on channel 2, same CC numbers both ways |
| Head CCs | (off ? 0x40 : 0) | model: OD/FX 0x00, AMP 0x01, CAB 0x02, MOD 0x03, DLY 0x04, RVB 0x05, GATE 0x06, EQ 0x07 |
| Parameter CCs | OD/FX 0x0C–0F, GATE 0x08–09, AMP 0x12–17, CAB 0x1A–1E, EQ 0x20–2B, MOD 0x2C–2F, DLY 0x30–33, RVB 0x36–39; VOL 0x3A, page 0x3B |
| Presets | Program Change 0–98 = P01–P99 |
| SysEx | F0 00 21 7A 70 <cmd> <dir> … F7; dir 0 read, 1 write, 2 reply, 3 ack; 7E notify |
| Commands | 09 IR slot, 0B preset, 0C edit buffer, 10 IR data, 12 name, 14 settings, 15 state, 18 looper, 19 drum, 58 user amp (NAM), 6F tuner |
| Packed records | 7-bit LSB-first bitstream (126 MIDI bytes ↔ 110 struct bytes for a preset) |
| User IRs | The pedal plays only the first 384 taps (ir::PEDAL_IR_TAPS) |
The official app (what we reversed)
| App | Stomp Manager 1.0.2 (build 1), macOS universal |
| Framework | Flutter (Dart 3.12.2 AOT, obfuscated) |
| MIDI | flutter_midi_command (CoreMIDI) |
| BLE | universal_ble |
| Native libs | nux_plugins (JUCE audio-file → 48 kHz WAV for IRs), imagelib (NeuralAmpModelerCore: NAM → device format), nux_helper (trivial) |
| Linux | The dependency list includes flutter_midi_command_linux and bluez, so the vendor builds for Linux internally but doesn’t ship it |
App UI layout (for reference when building a clone):
- Left: preset list P01–P99 with save / import / export icons.
- Top: VOL slider, connection indicator, tuner, settings (wrench).
- Signal chain: GATE → OD/FX → AMP → CAB → EQ → MOD → DEL → REV → LOOP → DRUM (coloured = on).
- Edit panel: module list → model list → parameter sliders and an ON/OFF toggle.
- Settings: Input Trim, Global EQ (Bass/Mid/Treble), Wireless, LoopBack, Language, version info.
Document map
| Doc | Contents |
|---|---|
| 02-midi-cc-reference.md | Every CC/PC, all modules/models/params, looper/drum/tuner |
| 03-sysex-protocol.md | Framing, command table, handshake, encodings, captured sequences |
| 04-data-structures.md | Preset (110 B), settings, IR/NAM slot info, drum/loop/tuner records |
| 05-uploads-nam-ir.md | NAM/IR upload transport and what’s known about the conversion |
| 06-rust-linux-guide.md | Talking to the pedal from Rust and Linux: crates, architecture, protocol code |
| 07-capture-methodology.md | How the captures were made; how to make more |
| 08-static-analysis.md | Static analysis of the app binary, firmware and native libs |
| 09-open-questions.md | What is still unknown and how to find out |
| 10-library-guide.md | The open-stomp crate: API guide, engine, recipes, testing without a pedal |
| 11-python-guide.md | The Python bindings (import open_stomp) |