Provisioning and revocation

Provisioning writes a set's secrets over USB; flashing only installs firmware. Run these commands from the repository root in the container. Flash each device with its proper partition table first.

cargo provision mac --port /dev/ttyACM0  # repeat for each device
cargo provision new-set --tower <TOWER_MAC> --left <LEFT_MAC> --right <RIGHT_MAC> --out ./set1
cargo provision inspect ./set1/tower-pairing.bin  # keys are redacted
espflash write-bin --port /dev/ttyACM0 0x350000 ./set1/tower-pairing.bin
espflash write-bin --port /dev/ttyACM1 0x350000 ./set1/cat-left-link.bin
espflash write-bin --port /dev/ttyACM2 0x350000 ./set1/cat-right-link.bin

Match each port to the intended board; the numbers above are examples. Test boards need none of this: ./lx link-test <tower> <cat> writes them a throwaway set by the MACs in .board-config.toml and deletes it (build guide). new-set also accepts --flash-tower, --flash-left, --flash-right ports. It refuses to overwrite a set directory. That directory contains secrets: keep it privately or delete it, and never commit it. Git ignores set<N>/ at the repository root (.gitignore); name another place and it is yours to keep out.

A towerless pair

Two cats without a tower: one is built coordinator and holds the pairing table, the other is an ordinary Satellite whose record names the Coordinator cat as its tower. --coordinator takes the place of --tower and needs both cats:

cargo provision new-set --coordinator left --left <LEFT_MAC> --right <RIGHT_MAC> --out ./set2
espflash write-bin --port /dev/ttyACM1 0x350000 ./set2/cat-left-pairing.bin
espflash write-bin --port /dev/ttyACM2 0x350000 ./set2/cat-right-link.bin

A Coordinator cat in download mode (BOOT held while plugging in) or in service mode (SVC held 2 s) takes its image like any board. A Coordinator alone needs no set; without a usable pairing table its radio stays off. It refuses a table that pairs a Satellite on its own hand.

Power-cycle after writing. A provisioned cat logs session … established in N ms. UNPROVISIONED and cat LED 1 solid red mean a missing or invalid record, or one made for another board or side: a cat record names the MAC it was made for. Check the build's Config: line, partition table and record before retrying. (LED 2 blinking red is not pairing: the mouse sensor failed its start, slots::bottom::SENSOR_OFFLINE.) Records survive normal firmware reflashes; old incompatible records need re-provisioning. Record definitions and addresses are owned by provision.

To erase a cat's record, hold only the two bottom-corner finger keys at power-on: index i7 (0,0) and pinky p5 (0,5), the bottom keys of the outer index and outer pinky columns (Li7/Lp5, Ri7/Rp5 in the key table). The boot log must report link record ERASED; it then remains unprovisioned until another USB write. This forgets the tower locally; it does not revoke the cat at the tower. A Coordinator cat has no revocation chord: write a new set over it, or erase its sector with espflash erase-region --port <PORT> 0x350000 0x1000.

For a lost cat or a compromised set, generate a new set without that cat and write the new records to the Coordinator and remaining cats. The Coordinator never changes its own table: provisioning is the only way in or out. See security constraints.

Settings

settings reads the Coordinator's user-settings sector, prints it, and with changes writes it back, keeping everything it is not told to change (the radio channel, the colours, the keymap profile). The Coordinator must show its port: its SVC key held for 2 s (service mode), or BOOT held while plugging in. --device names its kind, whose sector it is; a sector holding something else is refused.

cargo provision settings --port /dev/ttyACM0 --device tower
cargo provision settings --port /dev/ttyACM0 --device cat --mouse-speed 5 --gyro-left while-held

Without changes it only shows what is stored and resets the chip into its firmware; --stay keeps it in its bootloader instead, for a write without service mode's 2-minute limit. --json <file> also writes what the sector holds afterwards, in a setup manifest's [settings] words: the setup page's Read from the Coordinator (--stay) and its saves read it back.

A sector holding an older record version belongs to firmware older than the checkout: the firmware writes an older record as the current version at its first start, and older firmware cannot read the current one, so it would start on the defaults (radio channel, trims, keymap profile). A write over it is refused: reflash the Coordinator, let it start once, then write.

The setup page writes its Sensors and LEDs step this way, before the Coordinator's firmware (--stay --before-firmware). --before-firmware says that firmware follows the write, so it may replace an older record, or a sector that holds no settings at all (a tower's sector is a cat's SROM partition, on a board that was a PMW3389 cat). The flags and the settings are in cargo provision without arguments and in Vial settings.