Files
justinandClaude Opus 5.5 1fcf73ed9d Drop the brightness control, survive and explain a frozen mic
- Remove RGB brightness: firmware 2.1.2 stores the value but the LEDs
  never change, so the control did nothing. PROTOCOL.md notes why.
- Lock the device per transaction (flock) so the CLI and the web
  service can't interleave and steal each other's replies.
- Detect a mic that is plugged in but no longer answering and tell the
  user to replug it (a USB reset is not enough; settings survive).
  Seen when hardware buttons are held while settings are being written.
- Web page keeps the last known value when a poll comes back partial,
  instead of drawing unanswered settings as off.
- New screenshot.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 10:45:18 -05:00

3.0 KiB
Raw Permalink Blame History

DGM20 control protocol

These notes come from Maono Link 4.0.88 for Windows. The app loads a per-model plugin, and the plugin for USB 352f:0105 is DGM20_OLD.dll. Every value below was checked against a real mic (firmware 2.1.2) unless it is marked otherwise.

Transport

The mic has USB audio interfaces 0-2 and a HID interface 3. Interface 3 carries a vendor usage page (0xFF01) with four reports:

report direction size
0x50 out 15
0x51 out 63
0x10 in 15
0x11 in 63

The app uses only 0x51 (requests) and 0x11 (replies). On Linux the interface is a hidraw node: a 65-byte write() (the report id plus 64 data bytes) sends a request, and read() returns replies.

Packet

offset  size  field
0       1     report id: 0x51 request, 0x11 reply
1       1     0xC4
2       1     length of bytes 1..end, including the checksum
3       2     0x0000
5       1     type
6       n     payload, u16 little-endian words
6+n     2     checksum, u16 LE = -(sum of bytes 1 .. 5+n)

The rest of the 64 bytes is zero-padded.

type request payload reply
2 (reply only) write ack: status (0 = ok)
3 addr, value pairs type-2 ack. The mic also sends type-3 packets on its own when a setting changes on the hardware, such as the touch pad.
4 addr addr, value
5 addr, count, data... bulk write. The app uses it only to write the serial number; don't.
6 addr, count addr, count, values... (range read)

Registers

reg meaning values
0x0003 model name, 8 words, ASCII "DGM20"
0x000B firmware version, 3 words 2, 1, 2
0x001E serial number, up to 20 words
0x1008 DFU mode (read) 0 = normal
0x100A factory reset write 1
0x2022 mute 0 / 1
0x2026 headphone monitoring 2000 = on, 3000 = off
0x2027 noise cancellation 0 / 1
0x2028 noise cancellation strength 0-100
0x202A labelled RGB ring brightness in the app's shared code stores 0-100, but the LEDs do not change on firmware 2.1.2; not exposed
0x202C vocal enhancement 0 / 1
0x204B level-meter enable not answered by firmware 2.1.2

Maono Link reads settings once, in this order: 0x204B, then 0x2022, then a range read of 0x2027 (count 2), then 0x2026, then 0x202C. After that it relies on type-3 packets the mic sends on its own.

Present in the plugin but not used for this model

The DLL shares widgets with the PD200X plugin, so it contains EQ and RGB-colour code. That code is never instantiated for the DGM20, and the mic does not answer reads of these registers. They are listed here for anyone exploring.

  • EQ: 5 parametric bands, each 5 words, starting at 0x204D + 5·i. The HPF is at 0x2066 and the LPF at 0x206B. Each band is [enable, type, freq Hz, gain dB×10+2000, Q×100].
  • Light on/off: 0x2036. Colour index: 0x2038.