MIDI Devices
Engine talks to its control surface, wheel displays, mixer and motor boards as MIDI devices — over USB for most hardware, or over a UART for some (see Transports). This page collects where all of that lives in the firmware: payload paths, version metadata, detection rules and the flashing mechanism.
Control mappings are a separate topic — see Controller Assignments.
Where things live
What | Where |
|---|---|
MCU firmware payloads |
|
Firmware version + payload filename |
|
Device detection / MIDI identity |
|
Control mappings |
|
Flashing tool |
|
Device enumeration helper |
|
UART control-surface ALSA node |
|
Firmware payloads
One directory per flashable board, named <HWID> <Role>. Roles seen so far: Controller (the control surface), Display (platter/wheel display), Mixer, Motor, and on some consoles Left Display MCU/Right Display MCU.
Each directory holds exactly two things — the payload and its descriptor:
firmware.json
The version is stored here, as a string, alongside the payload filename.
This layout is remarkably stable. Across all 48 non-beta releases from 1.3.1 to 5.0.4 — 822 descriptors in total — the path never moves, every single subdirectory of Firmware/ has a firmware.json, all of them parse as JSON, and version, filename and type are present in every one and are always strings. Reading a board's version needs no version-specific handling.
The rest of the schema does drift, though — see Schema drift.
Three payload types exist and the descriptor shape differs between them.
rbin — the in-house format, used for control surfaces:
dfu — standard USB DFU, used for STM32-based boards:
bin — a raw blob, used for the mixer DSP and the motor boards on the motorised players:
Key | Type | Meaning |
|---|---|---|
| string | Firmware version. |
| string | Payload file, relative to the same directory |
| string |
|
| string | Which attached device this targets — see below |
| string | Matches the |
| string | Lowest running firmware version that can be updated directly, for staged upgrades |
| list | ( |
| list | SysEx that puts the board into update mode before flashing |
| string | ( |
| string | (retired) SysEx to begin a serial-port transfer |
| bool | (retired) the only non-string, non-list value in the whole schema |
deviceToFlash is a string in every release that has it — 1.5.3 is the sole release where the key is absent entirely. Some values are a plain role name like "Controller", others are colon-delimited, e.g. "Control Surface:Control Surface 16:0" or "PRIME 4 Left Wheel Display:PRIME 4 Left Wheel Display MIDI 24:0", where the last two fields look like a MIDI port name and an index. Some name the marketing product rather than the role.
Schema drift
Eight distinct key sets appear across the history, so a parser should treat everything except version, filename and type as optional:
Key | Present in |
|---|---|
| every release, |
| every release |
| every release except |
| every release except |
|
|
|
|
|
|
The type values arrived in stages too: dfu and bin from the beginning, rbin only from 1.6.0.
rbin payload format
Starts with a !Rbn magic and an inline copyright string, then a device identifier:
The u32 at 0x24 is little-endian and its low byte is the device's MIDI SysEx identity byte — 0x11 for JP20, 0x12 for JP21, 0x3f for NH08. The upper bytes are close to but not identical to the device ID in the update container's device table (see Signed Firmware Layout), so don't assume they match.
dfu payload format
Standard DFU files with the usual UFD suffix at the end, so dfu-util and dfu-suffix read them directly. The alt-names strings are the target's DFU interface descriptors — @Internal Flash /0x08000000/04*016Kg,01*064Kg,01*128Kg describes an STM32 internal flash map, and the base address 0x08000000 matches the one in stop-command. Where several alt-names are listed, the same payload covers boards fitted with different flash sizes.
Device detection
/usr/Engine/Content/KnownDevices.vfsb is a VFS bundle — a small container holding one KnownDevices.xml fragment per product code, keyed by that code. Engine loads the fragment matching the product code it was launched with (see Engine) and uses it to recognise what is plugged in.
Each fragment opens with the MIDI identity request Engine sends to probe a device:
and then declares the devices it expects to find:
Property | Meaning |
|---|---|
| Expected reply to the identity request, with |
| Which directory under |
| Which directory under |
| Flashing order when a product has several updatable boards |
| Parse the reported version as an |
| Present on only a few entries — purpose not yet established |
|
|
Note realName is the role (Controller, Display, Mixer, …), which is what ties an entry to both its assignment directory and its firmware directory.
Transports
Two ways a control surface attaches, and it differs by hardware generation:
USB MIDI — the surface enumerates as a USB MIDI device and is matched via
KnownDevices.vfsb. This is the common case.UART /
serial-midi— some devices wire the surface to a SoC UART instead, declared in the device tree as aserial-midichild of the serial node withlabel = "Control Surface". ALSA exposes it at/dev/snd/by-path/platform-ff190000.serial, and/usr/Engine/Scripts/enginetalks to it directly withamidion shutdown, e.g.amidi -p hw:/dev/snd/by-path/platform-ff190000.serial -S 'F0 00 01 3F 00 3F 7F 00 00 F7'
A device also has a USB MIDI gadget mode — f_midi-0 — used to present itself as a controller to a host computer. Its mapping lives beside the normal one, as f_midi-0_Assignments.qml/f_midi-0_Device.qml.
Flashing
/usr/Engine/FirmwareUpdater does the work. It is not run directly by the user — Engine exits with a quit reason and the wrapper script dispatches, from /usr/Engine/Scripts/engine:
$PRODUCTCODE is the device-tree product code with a trailing S stripped, so S-suffixed variants share their parent's firmware set. See Firmware Updater.
SysEx
inMusic's manufacturer prefix is 00 02 0B for Denon DJ and 00 01 3F for Numark. The byte after it is the device identity byte — the same value as the low byte of the device ID.
Commands observed so far, from the _Device.qml mappings and the firmware descriptors:
Command byte | Meaning |
|---|---|
| Query absolute control positions |
| Request power-on button state / test-mode entry |
| Enter DFU mode ( |
| Keep-alive / shutdown |
See also
Controller Assignments — the QML control mappings themselves
Test App — SysEx identity bytes per device, and entering test mode
Firmware Updater — the updater application
MIDI Device Scanner — the enumeration helper