Add HID Boot Protocol support to the BLE keyboard (E5)
Today the HID-over-GATT keyboard only implements the Report Protocol, so it
cannot type into hosts that require Boot Protocol (BIOS/UEFI setup, many KVM
switches, and pre-OS / bootloader environments with a minimal HID stack). E5
(research F1 + N8) adds Boot Protocol alongside the existing report path.
GATT additions to the HID service (0x1812):
- Boot Keyboard Input Report (0x2A22, READ|NOTIFY) — notify handle captured in
s_bootInputReportHandle; boot reports carry no Report Reference descriptor.
- Boot Keyboard Output Report (0x2A32, WRITE/WRITE_NO_RSP) — LED write sink.
Both carry the same per-characteristic security posture as the report values
(R1/E3): _READ/_WRITE_ENC + _READ/_WRITE_AUTHEN and the 16-byte min_key_size
floor, so the stack rejects an unencrypted/unauthenticated peer before any
access callback runs.
Protocol Mode (0x2A4E) is now wired: the host writes 0x00 = Boot, 0x01 =
Report. s_protocolMode becomes a cross-core atomic (written by the NimBLE host
task, read by the typing worker). sendReport() routes each keystroke to the
boot input report handle in Boot mode and to the report char in Report mode,
checking the matching CCCD subscription. Each connection and BLE bring-up
resets the mode to Report (the HOGP default), so boot is used only when a host
explicitly selects it.
The 8-byte boot payload [modifier][reserved][keycode×6] is built by the new
pure helper ble/profile/hid_boot_report.h, which produces bytes identical to
the report-protocol path; report-mode typing into phones/PCs is byte-identical
and only the notify target handle differs. The helper also owns the
boot-vs-report path selection, both unit-tested on the host
(test/ble/test_hid_boot_report, 8 cases) since the BLE harnesses drive report
protocol only. protocolMode() is surfaced through the port/shim/facade and the
BLE_HID debug line (proto_mode=0x00(boot)/0x01(report)) for QA.
Verified: native 1146/1146, sticks3_debug (S3) + m5stickc_plus2_debug (classic)
build clean, variant + conditional guards OK.
Claude-Session: https://claude.ai/code/session_01Y7Cy1HetRp6TZAUAeekN8X