Skip to content

Fix BLE firmware flashing through USB IAP - #24

Open
hitsmaxft wants to merge 1 commit into
OpenAnnePro:masterfrom
hitsmaxft:codex/ble-iap-hardening
Open

Fix BLE firmware flashing through USB IAP#24
hitsmaxft wants to merge 1 commit into
OpenAnnePro:masterfrom
hitsmaxft:codex/ble-iap-hardening

Conversation

@hitsmaxft

@hitsmaxft hitsmaxft commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Why this change

This PR primarily fixes BLE firmware flashing through the Anne Pro 2 USB IAP firmware.

The tool was originally documented as tested only for the main MCU. Although the CLI accepted --target ble, the BLE path did not validate the IAP transaction results: it used a fixed base, read whichever HID report arrived next, ignored the device status, continued after failed chunks, and could wait forever for a missing reply. It also wrote the main-MCU AP flag after every transfer, including BLE transfers.

As a result, Flash complete only meant that USB writes had been attempted. It did not reliably mean that the BLE erase and every BLE flash chunk had been accepted by the keyboard.

This change makes the BLE path a checked request/reply transaction and was validated on a real Anne Pro 2 C18. The corrected tool transferred a complete 155,648-byte BLE 2.13 image, the BLE firmware booted, macOS connected to it, and normal keyboard input worked over Bluetooth.

The same transaction handling also makes main and LED target failures safer, but BLE flashing is the reason for and primary validated use case of this PR.

What was wrong with BLE flashing

Area Previous behavior BLE failure mode
Transport base Defaulted to CLI base 0x4000 Did not query the address reported by the keyboard's IAP firmware
Reply identity Read and printed the next HID report A stale or unrelated target/command reply could be mistaken for the BLE write reply
Device status Returned the HID write() result USB accepting a report could be mistaken for BLE IAP accepting erase/write
Chunk failure Printed a warning and continued A partially written BLE image could still end with Flash complete
Timeout Used a blocking read A missing BLE erase/write reply could hang indefinitely
Target isolation Always wrote the main-MCU AP flag Completing a BLE transfer also modified main-MCU state
Input validation Read the image while flashing An empty or unreadable image could be discovered only after erase
Process result Errors did not reliably produce a failing exit status Scripts and users could not trust the reported result

On the tested C18, the IAP-reported BLE transport base is also 0x4000. The fix is not based on claiming that this constant was wrong for that board; it removes an unchecked assumption and rejects a conflicting explicit base on other IAP layouts.

How the BLE path works after this PR

  1. Read the complete image and reject an empty image or address-span overflow before erase.
  2. Ask the keyboard IAP firmware for the main/LED/BLE layout and the selected target's IAP mode.
  3. Use the device-reported BLE base. --base is accepted only when it matches that value.
  4. Send BLE erase with a 30-second timeout.
  5. Send the image as 32-byte BLE chunks.
  6. For erase and every chunk, require a response whose destination, source target, L2 command, and IAP key match the request.
  7. Require the response status byte to be zero; stop immediately on rejection, malformed input, timeout, USB error, or file error.
  8. With --boot, restart through the main-target mode-2 transition used by ObinsKit, without the old unconditional AP-flag write.

--probe exposes the detected layout and target modes without writing flash, which makes the address and IAP state inspectable before an update.

Real-hardware validation

The BLE flashing implementation was tested on an Anne Pro 2 C18 using a 155,648-byte BLE 2.13 image:

  • the keyboard IAP reported BLE transport base 0x4000;
  • BLE erase returned a matching status-zero reply;
  • all 4,864 × 32-byte writes returned replies matching the BLE target, firmware command, write key, and status zero;
  • the BLE firmware booted and advertised;
  • macOS connected successfully;
  • normal keyboard input worked over the Bluetooth connection.

After that hardware run, the final commit added only complete-image pre-read, empty-image rejection, address-span validation, and their host tests. These checks run before erase and do not change the validated erase/write transaction sequence for a valid image.

Host-side checks on the PR head:

  • cargo fmt -- --check
  • cargo test — 10 tests passed
  • cargo clippy --all-targets -- -D warnings
  • git diff --check
  • nix flake check --no-build

Verification boundary

The IAP protocol still has no verified flash-readback command. Matching status-zero replies prove that the keyboard IAP accepted the BLE erase/write transactions; they do not prove byte-for-byte flash contents by themselves. The subsequent BLE boot, advertisement, macOS connection, and Bluetooth keyboard input provide separate runtime validation that the flashed BLE firmware worked on the tested C18.

LED-target hardware behavior has not been independently validated.

@hitsmaxft hitsmaxft changed the title Harden IAP flashing and validate BLE transfers Make multi-target IAP flashing fail safely Jul 25, 2026
@hitsmaxft hitsmaxft changed the title Make multi-target IAP flashing fail safely Fix BLE firmware flashing through USB IAP Jul 25, 2026
@hitsmaxft
hitsmaxft force-pushed the codex/ble-iap-hardening branch from bf4b8c4 to 158aa04 Compare July 25, 2026 21:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant