ToneX librarian: decode the capture-upload path (undecoded by anyone, invariant 0 gated)
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 20/100
- Issue type
- Feature
- Clarity
- Clearly specified
- Activity status
- Quiet
- Tech stack
- python
- Domain
- embedded-iot
Research direction
Start with tools/tonex_decode.py and the 128 captured frames: implement unstuffing and CRC-CCITT validation, then verify every frame before considering transmission. Next, read the cited community project's protocol.md and implement the documented state request, checking the pedal's reply. Observe uploads passively with Wireshark and document the frame grammar, recovery path, and verified allowlist; done means all listed checks pass before any guarded replay.
Written by the indexing model from the issue text.
Description
Decode the ToneX librarian protocol, the operation that moves a capture onto the pedal. Split from #23, which covers what we can already read.
Why this is not a port
Unlike the planner backends, there is no working implementation to bring across. The community RE (vit3k/tonex_controller, built on by Builty/TonexOneController) covers the read and control surface well, and its protocol.md states plainly that preset writing/uploading and capture functionality "was not yet analyzed". So this is original work on the one operation nobody has cracked.
Worth reading that project's own warning first: a version of it "has an issue with USB that can overwrite the pedal's global settings". That is the failure mode this issue exists to avoid, on hardware that costs real money and that its owner gigs.
What is already known
From prior art, and independently confirmed against our own 128 captured frames:
- HDLC async framing,
0x7eflags opening and closing. - Byte stuffing:
0x7descapes, next byte XOR0x20. Present in 36 of our 128 captures. - CRC-CCITT over the payload, and the CRC is itself stuffed.
- Tagged objects:
0xb9/0xba/0xbccollections,0x80/0x81/0x82two-byte little-endian numerics,0x88float32 little-endian. - Decoded operations: hello/handshake with firmware version, state request, state-change notification, active slot switching, preset reassignment, individual preset retrieval.
Undecoded, and the point of this issue: writing a preset or a capture to the pedal.
Method, in order, and the order is the safety property
1. Fix our reader first (offline, no hardware). tools/tonex_decode.py ignores byte stuffing entirely and treats 0x80/0x81/0x82 as single structural bytes. Both are wrong. Implement unstuffing and CRC-CCITT validation, then re-run against the 128 captures: a frame whose CRC validates is a frame we have genuinely parsed, which is the check we have been missing. Nothing else in this issue should start before the reader is trustworthy.
2. Implement the state request (small, bounded write). This is documented prior art, not a guess, and it is the first thing we would ever transmit on that port. It also settles the pollability question honestly, which we have now been wrong about in both directions. Treat it as the pilot for the write path: one documented frame, verified by the reply, with the pedal's own state as the check.
3. Passive capture of a real upload (read-only from our side). Wireshark USB capture while the TONEX Editor loads a capture into a slot the owner nominates. We send nothing. This is the technique the community project documents and it is where the actual decode happens. Expect to repeat it: same capture into different slots, different captures into the same slot, so slot addressing and payload separate out.
4. Only then, replay. And not before there is a written recovery path.
Invariant 0 applies without exception
Nothing reaches that serial port until the operation is decoded and a documented recovery path exists. That is the same bar SENDABLE_FNS holds the FM9 to, and fm9/safety.py now carries a deny-by-default SendGuard precisely so a second device inherits it rather than reimplementing it. A ToneX writer gets a message_type_guard-style allowlist covering only frames we have decoded and verified.
Two things that make this device harder than the FM9 and should be stated rather than discovered:
- The serial channel is the one firmware travels over. On the FM9 we could separate function ids by scope; here we cannot yet tell a librarian frame from a firmware frame by inspection, and until we can, that is an argument for keeping the allowlist empty.
- The TONEX Editor holds the port exclusively (
Errno 16,lsofnames it). Any capture session has to run alongside the editor at the USB layer rather than the serial layer, because we cannot open the port while it works.
Definition of done
- Reader unstuffs and validates CRC-CCITT; all 128 existing captures verify.
- State request implemented and answered by the pedal.
- A capture upload observed end to end, with slot addressing and payload distinguished across repeated runs.
- Frame grammar for the write path documented in the ledger, with undecoded regions named rather than glossed.
- Recovery path written down and, ideally, exercised.
- Only then: a guarded writer, allowlisted to decoded frames.
Refs #17, #23. Hardware-gated, and gated further on the owner's explicit go-ahead before any frame is transmitted.
- Dominant language
- Python
- Stars
- 7
- Forks
- 3
- Avg merge
- 2h 17m
- Merged PRs (30d)
- 49
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from monzta1/ToneCommand
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
monzta1/ToneCommand#293 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 67/100
monzta1/ToneCommand#268 ·
Maintainers usually reply within 1 day
-
Difficulty 5/5 Over a week Newbie friendliness 35/100
monzta1/ToneCommand#269 ·
Maintainers usually reply within 1 day
-
bug device
Difficulty 4/5 3-5 days Newbie friendliness 12/100
monzta1/ToneCommand#250 · 1 comment ·
Maintainers usually reply within 1 day
-
bug device
Difficulty 4/5 3-5 days Newbie friendliness 18/100
monzta1/ToneCommand#241 · 2 comments ·
Maintainers usually reply within 1 day
All issues in monzta1/ToneCommand
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
Maintainers usually reply within 2 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
Maintainers usually reply within 2 days
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
developmentseed/titiler-cmr#278 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
Maintainers usually reply within 2 days