diff --git a/devices/CHANGELOG.md b/devices/CHANGELOG.md index 4863405..766b051 100644 --- a/devices/CHANGELOG.md +++ b/devices/CHANGELOG.md @@ -4,6 +4,10 @@ This file records changes to public protocol behavior, shared vectors, SDK surfa ## Unreleased +- Add the first ILX MultiPad case guide with pinned upstream source, public + adapter integration, key mapping, build separation, and SWD/serial evidence + rules. + ### Added - A source-first ILX MultiPad USB CDC developer binding that reuses the portable diff --git a/devices/README.md b/devices/README.md index 91bf258..37f6c07 100644 --- a/devices/README.md +++ b/devices/README.md @@ -23,6 +23,7 @@ The device does not run the Agent session and does not receive Agent credentials | Get ideas for what to build | [Browse the use cases](docs/use-cases.md) | | Build and flash a supported board | [Run the first approval](docs/first-approval.md), then use the [reference-board track](docs/implementation-tracks.md#track-1-run-a-reference-board) | | Prepare an ILX MultiPad USB device | Read the [MultiPad USB guide](docs/multipad-usb.md); confirm the PCB before any flash write | +| Reproduce the first public hardware case | Follow the [ILX MultiPad case](docs/cases/multipad-first-case.md); build the upstream firmware before adding Nexting | | Add a physical control surface to a Host/App | [Browse every public interface](docs/interfaces.md), then use the [Host integration track](docs/implementation-tracks.md#track-2-integrate-a-host-or-app) | | Port a new MCU, RTOS, or chip family | [Build the public foundation](docs/foundation-development.md), then use the [MCU port track](docs/implementation-tracks.md#track-3-port-a-new-mcu-or-rtos) | | Implement another language SDK | Use the [language SDK track](docs/implementation-tracks.md#track-4-maintain-a-new-language-sdk) | diff --git a/devices/SHA256SUMS b/devices/SHA256SUMS index c2da75d..78cc35a 100644 --- a/devices/SHA256SUMS +++ b/devices/SHA256SUMS @@ -1,30 +1,31 @@ 5e79c3b2a9dc997d6faa762fa3d420da27243c27a60726a5b4d94dabfdfcfb17 AGENTS.md -b2e88419dcda506677dd44af32faca468de0f852305eb6c6b3892f1bd10b0f86 CHANGELOG.md +362a3eea47663c7cb770739dba81e86818624b0874d448b6136873156521a2eb CHANGELOG.md 0905c822fd9d85cb05d05539ca0b41ce807109621f06e5d18792505a78fc270f CONTRIBUTING.md f0e5a3b3fc8d8d664d76be452f1631a296ef89566acb58440354da31af2074bd docs/board-verification.md +06a0f796634a47af9fb8628b11206a91120505e0a0d0fd6757915ef44f961f47 docs/cases/multipad-first-case.md bdfc3ae27b547003179322577ca28a03e8d06bb46815625ec1270ff3142b50da docs/conformance.md 92b35fee2f0ae4195fc31614a01b1aeba3b2bdc24b8f59c38e46a2c0c537dcc2 docs/development.md b6b2a3bc464d167d920f143c71ffde52c51d264f5cc71c0e8928f95986fa0e2b docs/first-approval.md e27b38c5b92c32d3f0028996516b027fb842183730dae8c7ba3c87e5be882329 docs/foundation-development.md 253e7aff8894704a280e9a588e0181da98a9bd825fd506625b9325e357f6e419 docs/hardware-support.md -8436fcbbfb8554f5c2549d06b329f6f3f7631ed3437ec51f1bb7454798491b00 docs/implementation-tracks.md +1cb75f130268edcf545e5525a08c948f2f470a6cdc23a0734dc0766d0f1e932b docs/implementation-tracks.md 16815c4d5e0ae09b8502f0109a0a4e38b64b467a4b0a82b029905093b63310af docs/interfaces.md 026b3ce7d5970d2a34d64862de12882f8da9e014d2ef9ab4a9c3d5e99af31b1b docs/migration-0.1-to-0.2.md -18c71c1d3da6a2a9bb66912832916594c672d268fa1c014b66c4decdce9fe11a docs/multipad-usb.md +74f60bf30d5940a6cb2f71b208abb48196249a0f1195eb7ac7f6eeb125c3e573 docs/multipad-usb.md 36f7151ddbf307f8ff4cf5487d094930882b78b7ee91d241adf2eff53753ac55 docs/porting-guide.md -8ba7a254ecd348f19215dedc11eeb561f22c74cf3417b47d414dfaab5675c4ed docs/project-status.md -dc9e38145477ae5c9f9818ad3567d7d57f9bd31f264279014b30ffec097b22e7 docs/README.md +e0200e8dbcd3d758ae6fea3b608a3e648291877f7c5de284ea902ca1170062bf docs/project-status.md +dd62331e63b11b15874989474836fdff06b0282eca3340555554e0614ba266ef docs/README.md 5b04ce5083234a4137fad6eee987946b55bfe7a758220394eb127b804aa4f873 docs/use-cases.md cddf6aec5d4750dc34c9a6f642c604c8786ba89018082b96db8a7b6fe716b7b5 examples/macos-device-simulator/main.swift 85a7b0f0976f7b43099629335e9b61be625a77ce548e438956dbf3a5e1de2e27 examples/macos-device-simulator/README.md -3f56b901400960503a304e6c0f8f4a6aa0ab5467b8f097737b3a2d99dda6e5d0 firmware/multipad/bringup-status.md +445fd02928f57ec5cb23b15c6fd4617cff6348e2df991736d04bad5d4ae8ec90 firmware/multipad/bringup-status.md e93dad280dad39b252d5d0edaf549cf9db8a8833eb009bc2b089da8ebfb181d2 firmware/multipad/CMakeLists.txt -e86c924b3b6cdd85fcf311dba4d85804cdf70a3fbeb554c4215d4617e37b9850 firmware/multipad/hw-review-findings.md +58edf13b1bbc8c855432f921eab5ac74befe9a78ac8254c9040eeef4b0704c52 firmware/multipad/hw-review-findings.md d40be2000fae5697e0d40abebfc833d31c8568679c66c3f1b1cbb85744dac7d4 firmware/multipad/nexting_multipad_adapter.c f4bab39e2320ae1f171eca78005cdfd355848dda5690020f2201de4a96d37587 firmware/multipad/nexting_multipad_adapter.h 55e8c889cfe9b62dcc62c591880aba2f9826a6a1353d7a89213916efd27c0bce firmware/multipad/nexting-multipad-device-info.template.json -b077373089e8bc8100b9dbb003fafb6e9bd97b2d471df84c0dc8a990e4e2c680 firmware/multipad/pin-function-map.md -38103d0b2ed11139f1a1d3cfae91daccc6c57514086621a1ef49ca9e8d1d0270 firmware/multipad/README.md +732ad9fa55a9055e2d8c1c701489fa09608634bda4b89a2e1d601dff5e75e013 firmware/multipad/pin-function-map.md +2c743c98200d48a611fc9cb5994e11372b9daa3dc944570c3d48e55bf88be7ba firmware/multipad/README.md 49d3bf8fc0756bf4c69eb6d5af3b7cfe788c2c56822f000ba05adcad8d16e7c7 firmware/multipad/tests/test_adapter.c a111d8e0484745a126069df990273171181a61caa5a3a751043974cc52f43f00 firmware/multipad/tools/flash-multipad.sh 4c27437ae7b7c5555a8a21eb763785e8600682ad71f0b12f29304e56cf132d5f firmware/multipad/tools/multipad-cdc-smoke.py @@ -45,7 +46,7 @@ faab06a4630dfc7b7e5c1fc7ecef24ae6ca0c0040f3b71f3d112d1a816a410b9 NOTICE af1ea5c4627d67b21afd238f48b7eb4931655894bd899450b16fc802d8cdcf68 protocol/vectors/approval-v1.json eb2a6b125d123a5644a0773593c2eee730339f2809e51605f2f82eb518dde1d4 protocol/vectors/device-info-v1.json 3523ce906d597735ed9de66d79923b12de284595566c556725c10bf726ba84b0 protocol/vectors/status-v1.json -e568a17b0b64eb50fd147981ad6d58127127022774075acdc8d07f93df14d895 README.md +7ed0ffa1a546c198a2008f9fc9a1325035248c3fd4ccad3cce667790e579ddb9 README.md 83c03d7b5779aaf86471945890b5e699cba1171fe3064b58942a3784c4efa9d6 reference/js/package.json 18374cf8708c75abce5a22d6d445cf5ab48b6b62774ecf3af8f780693d1cf45e reference/js/README.md d1daccb45aebdf6a6ff524abe07ba34833a83266c433178596840c00a7fb3ee8 reference/js/src/device-info.mjs @@ -63,8 +64,8 @@ dd94f6782ad7f3f8ab102806ac2b32555a8f61ef6da04eca504250591f43d697 reference/js/t 707046c2762b923fcc0add6465f23a504a93f48502c55c24155c7367fcbfe4ae scripts/check-naming.mjs e3f347b6e98e6a1ca3f9f842a6c2f1245f0f6953680a685ecbdd42d17dd1e1ed scripts/check-public-boundary.mjs 8d7aad1d02044e2762835d765a6bad5fc41c454e15d75111f957db45bc72348c scripts/check-public-boundary.test.mjs -2ff5e27e3ce3c7d4e0623d1b66d5ff7fb24c2edf8308e35ba7b5fcdb59e76e4d scripts/documentation-contract.test.mjs -222cee57ac6ec97208cea67a6e3e7cf8672000f10acfd60a09d6f21af4b0b10f scripts/export-manifest.json +72e5a1d62ee49c9ca32dc026cf1d16bd1b55269cd10d00d0ad8c67efa01eb99a scripts/documentation-contract.test.mjs +2e6e8e0d3577700cc2e68aab5b034cffca7598474d54250ab9536eef25a7c6ad scripts/export-manifest.json f461f2683632c7fb38a5c04b2fa03a0293fe791571b1b173982514530cc793d6 scripts/export-nexting-devices.mjs 85f681344b04754999e17a4ec472dfae1ed1c2daa49f065d77bacdb223ea57fe scripts/export-nexting-devices.test.mjs a7120b95b63f5c7004f5099fcd9bf073fd34e167cef6e6382258d869f6faa2ac scripts/public-workflows/nexting-devices-ci.yml diff --git a/devices/docs/README.md b/devices/docs/README.md index 19b36c0..892a19c 100644 --- a/devices/docs/README.md +++ b/devices/docs/README.md @@ -27,6 +27,7 @@ Choose the task you are trying to complete. - [JavaScript reference](../reference/js/README.md): readable protocol, framing, and relay behavior. - [Zephyr reference firmware](../firmware/zephyr/README.md): shared Nordic and Espressif adapter. - [MultiPad USB CDC guide](multipad-usb.md): open-source STM32 adapter, board variant check, and fail-closed flash preparation. +- [First case: ILX MultiPad](cases/multipad-first-case.md): reproduce the upstream build, add the public adapter, map the first two keys, and verify the flash path. - [Port a chip](porting-guide.md): platform contract and adapter rules. ## Verify and make claims diff --git a/devices/docs/cases/multipad-first-case.md b/devices/docs/cases/multipad-first-case.md new file mode 100644 index 0000000..417600d --- /dev/null +++ b/devices/docs/cases/multipad-first-case.md @@ -0,0 +1,147 @@ +# 第一个案例:ILX MultiPad 接入 Nexting Devices + +ILX MultiPad 是 Nexting Devices 的第一个完整硬件案例。它不是一块 +Nexting 量产板,而是一块已经开源、已经能作为键盘使用的 STM32F103VET6 +USB HID + CDC 设备。这个案例的目标是说明:如何保留原作者的键盘功能, +只增加一层可验证的 Nexting 设备协议适配。 + +## 这个案例到底交付什么 + +| 层 | 案例交付物 | 证据等级 | +| -------------- | -------------------------------------------------------------------- | ------------------ | +| 上游固件 | `iLx11/multi-pad`,固定到 `78c1ee533a7f513e9f390741c4f5eed1e0aa91b3` | 源码可审计 | +| Nexting 设备核 | `sdk/c` 的固定缓冲 C99 协议、流式拼帧和审批状态机 | Core tested | +| MultiPad 适配 | `firmware/multipad/nexting_multipad_adapter.c/.h` | CMake 合约测试通过 | +| 兼容入口 | 原有 `AA BB xx` 保留,只有换行 JSON 帧进入 Nexting 适配器 | 主机测试通过 | +| 烧录路径 | Module 版走串口路径(仅当看到 SERIAL/BOOT/RESET);FPC 版走 SWD | 由拆机证据决定 | +| Host 边界 | Host 负责授权、Agent 路由和最终回答;固件不保存凭证 | 公开契约 | + +当前公开 SDK 不提供一个可以误称为“已经适配所有版本”的 HEX。上游工程中 +的 `leden.hex` 是原版固件(原作者固件);接入 Nexting 适配器后必须重新构建并单独保存 +新的 HEX。不能把原固件误当作 Nexting 固件烧进去。 + +## 上游工程与版本 + +使用下面两个公开仓库,不要把上位机仓库当成下位机固件: + +- 下位机固件:[iLx11/multi-pad](https://github.com/iLx11/multi-pad) +- 上位机:[iLx11/key-pad-application](https://github.com/iLx11/key-pad-application) + +本案例只接入下位机仓库。上游工程本身已经证明了这些事实: + +- `STM32F103VET6`、Cortex-M3; +- USB HID + USB CDC composite; +- 2 × 4 矩阵按键和 3 个旋钮模块; +- `PA13 = SWDIO`、`PA14 = SWCLK`; +- `PA9/PA10 = USART1_TX/RX`; +- 工程没有 DFU、IAP 或应用侧 USB bootloader; +- 上游许可证为 GPL-3.0。 + +烧录配置在上游的 `Config/stlink.cfg`,不是 Nexting App 的配置。普通 Type-C +枚举出来的 CDC 端口只能证明应用正在运行,不能证明它已经进入 bootloader。 +Type-C 不能直接烧录,除非先确认对应的 bootloader 路径。 + +## 第一个可运行映射 + +这个案例只承诺一个小而明确的映射,不把未来能力提前写成已支持: + +| MultiPad 控件 | Nexting 公共接口 | 案例行为 | +| ----------------- | ---------------------------------- | ----------------------------------------------- | +| 第一个矩阵键 | `approval/1` → Allow | 批准当前唯一待决请求 | +| 第二个矩阵键 | `approval/1` → Deny | 拒绝当前唯一待决请求 | +| 现有 CDC 接收回调 | `nexting_multipad_receive()` | 接收 `present`、`resolved`、`status` | +| 现有 CDC 发送函数 | `nexting_multipad_write_frame()` | 回传 `answer` | +| 板上屏幕/指示器 | `render_approval`、`render_status` | 只渲染回调收到的状态 | +| 其他按键和旋钮 | 保留原厂行为 | 等 `keys/1`、`rotary/1` 等 profile 发布后再映射 | + +适配器不会解析 Agent 会话,也不会把 Claude Code、Codex、账户或云地址写入 +设备。显示摘要、倒计时和状态的具体排版属于板级回调,不属于协议核。 + +## 从上游源码到案例固件 + +### 1. 固定上游源码并先构建原版 + +```sh +git clone https://github.com/iLx11/multi-pad.git +cd multi-pad +git checkout 78c1ee533a7f513e9f390741c4f5eed1e0aa91b3 + +# 上游工程要求 arm-none-eabi-gcc、CMake 和 STM32 工具链 +cmake -S . -B build +cmake --build build +sha256sum build/leden.hex +``` + +先保存这个原版产物和哈希。它只用于恢复原厂功能,不能标记为 Nexting 固件。 + +### 2. 加入公开 Nexting 源码 + +从 `Nexting-ai/nexting/devices/` 取下面的公开文件,复制到上游工程的独立 +目录(例如 `USER/Nexting/`),不要修改公共 SDK 的语义: + +```text +devices/sdk/c/include/nexting_device.h +devices/sdk/c/src/nexting_device.c +devices/firmware/multipad/nexting_multipad_adapter.h +devices/firmware/multipad/nexting_multipad_adapter.c +``` + +把这四个文件加入上游 CMake target,并把 `sdk/c/include` 加入 include path。 +上游 `USER/Usb/usb_user.c` 的 CDC 回调先判断 Nexting 帧,再落回原有分支: + +```c +if (nexting_multipad_accepts(&nexting_adapter, Buf, *Len)) { + (void)nexting_multipad_receive(&nexting_adapter, Buf, *Len); + return USBD_OK; +} + +/* 原有 AA BB CC / AA BB AA / AA BB DD / AA BB EE / AA BB FF 分支继续保留。 */ +``` + +初始化时提供四个板级回调:单调时钟、CDC 发送、审批渲染、状态渲染。主循环 +调用 `nexting_multipad_tick()`;USB 断连调用 +`nexting_multipad_disconnect()`;前两个审批键分别调用 +`nexting_multipad_choose(...ALLOW)` 和 +`nexting_multipad_choose(...DENY)`。回调失败时不要伪造成功 UI。 + +### 3. 构建、备份、烧录 + +重新构建后,对新的 `leden.hex` 计算哈希,并把原版备份、Nexting 版本和日志 +放在不同文件名下。根据硬件版本选择路径: + +| 版本 | 写入方式 | 关键条件 | +| ---------- | -------------------------- | ------------------------------------------ | +| Module PCB | 上游串口路径(待实板确认) | 必须看到 SERIAL、BOOT、RESET 路径 | +| FPC PCB | ST-Link/J-Link SWD | `3V3`、`GND`、`SWDIO(PA13)`、`SWCLK(PA14)` | + +在确认 bootloader 之后,才可以使用本目录的 +`firmware/multipad/tools/flash-multipad.sh`。脚本要求显式的端口、HEX、 +`--confirm --allow-write`,且不会覆盖原始备份。 + +### 4. 一次只验证一个行为 + +1. 先用 `multipad-cdc-smoke.py` 验证原有 `AA BB CC` 回显。 +2. 发送一个 `present`,确认屏幕或指示器只显示当前请求。 +3. 按 Allow,确认收到同一个 `id` 的 `answer`。 +4. 确认 Host 成功后发送 `resolved`,设备清掉待决状态。 +5. 单独测试超时和 USB 断连;两者都必须清空审批和状态,不能留下旧提示。 + +在没有这些逐项证据前,只能写“适配器测试通过”,不能写“MultiPad 真板已 +兼容”或“Type-C 可直接烧录”。 + +## 这个案例与 Nexting App 的关系 + +MultiPad USB 是公开的开发者案例,不是现有 BLE App 自动支持的 USB 变体。 +Host 必须自己拥有 USB 权限、端口选择、授权状态和 Agent 最终回答操作; +设备只接收有界的公共消息。未来如果 Nexting App 开放 USB transport,需要 +另行发布 Host 支持、授权测试和断连策略,不能由这份固件文档推断出来。 + +## 完成定义 + +- 上游工程能在固定 commit 上复现构建; +- 原版 HEX 已备份并有哈希; +- Nexting HEX 由明确的适配源码生成并有哈希; +- `npm run test:multipad`、C99 合约测试和 CDC smoke 通过; +- `present → answer → resolved`、超时、断连分别有记录; +- `Device Info` 只声明实际存在的按键、旋钮、显示和电量能力; +- GitHub README 只链接本案例,不把实验性 USB 路径写成量产承诺。 diff --git a/devices/docs/implementation-tracks.md b/devices/docs/implementation-tracks.md index 3a6eb6d..955e1a7 100644 --- a/devices/docs/implementation-tracks.md +++ b/devices/docs/implementation-tracks.md @@ -127,6 +127,11 @@ and not automatic Nexting App USB enrollment. The Host still owns USB authorization, Agent routing, and final action sinks. The device sees only bounded public frames and never receives credentials. +The [first MultiPad case](cases/multipad-first-case.md) is the reproducible +walkthrough for this track. It pins the upstream commit, separates the original +HEX from the Nexting build, maps the first two keys to Allow/Deny, and records +the evidence required before calling the board compatible. + ## Track 5: Maintain a new language SDK This is the language SDK route formerly listed as **Track 4: Maintain a new language SDK**; diff --git a/devices/docs/multipad-usb.md b/devices/docs/multipad-usb.md index 8c3c021..8673287 100644 --- a/devices/docs/multipad-usb.md +++ b/devices/docs/multipad-usb.md @@ -5,6 +5,9 @@ 通道接收配置和 Nexting JSON。它不直接连接 Claude Code、Codex 或 Nexting 云;Host/App 仍然负责授权、会话和最终动作。 +如果这是你第一次把公开硬件接入 Nexting,请先读[第一个案例:ILX MultiPad](cases/multipad-first-case.md)。 +本页是硬件路径和风险清单;案例页是从上游源码到新 HEX 的完整开发顺序。 + ## 先知道你手上的硬件是哪一版 先看[上游仓库](https://github.com/iLx11/multi-pad)与 @@ -19,6 +22,11 @@ Nexting 适配层,不复制上游 GPL 固件。 | FPC PCB | 移除串口和按键 | 需要 SWD/J-Link | | App bootloader | 上游源码没有 DFU/IAP/应用 bootloader | 烧错后不能指望 USB 自救 | +上游工程的烧录配置是 `Config/stlink.cfg`:ST-Link 使用 SWD,目标是 STM32F1。 +`leden.ioc` 明确把 `PA13` 配为 `SWDIO`、`PA14` 配为 `SWCLK`,但上游仓库没有 +原理图或焊盘坐标文件,所以不能从仓库臆造物理焊盘顺序。看到焊盘后按丝印或 +万用表确认 `3V3/GND/SWDIO/SWCLK`,不要把 Type-C CDC 当作烧录器。 + 拆机前不要猜显示屏、电池、序列号或开关位置。请先拔掉 Type-C,拆下四个 背面螺丝,拿起后盖时不要拉扯屏幕排线,并拍下 MCU、PCB 版本、BOOT/RESET 和 SERIAL 标记。本目录的 diff --git a/devices/docs/project-status.md b/devices/docs/project-status.md index e6dec39..992d1aa 100644 --- a/devices/docs/project-status.md +++ b/devices/docs/project-status.md @@ -10,22 +10,22 @@ identify its module/FPC boot path before any write. ## Current evidence -| Area | Evidence | Status | -| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | -| Wire and vectors | `approval/1`, `status/1`, bounded Device Info 0.2, JSON Schema, valid and hostile vectors | Passing; wire major remains `1` | -| JavaScript reference | Protocol, framing, relay, Device Info, documentation, simulator, and export tests | Passing | -| Swift Host SDK | Codec, Device Info, authorization, relay, coordinator, CoreBluetooth, and SwiftPM tests | Passing | -| Kotlin Host SDK | Bounded Device Info and protocol codecs used directly by Android | Passing | -| Portable C99 SDK | Fixed-buffer protocol, state, Device Info, ASan/UBSan suites | Passing | -| iOS App integration | Explicit enrollment/revocation, secure remembered devices, one active lease, battery, continuous information table, metadata sync, independent Claude Code/Codex adapters | iOS Simulator build and integration contracts pass | -| Android App integration | Public Kotlin SDK, BLE enrollment, encrypted authorization storage, battery, continuous information table, metadata sync, independent Claude Code/Codex adapters | Debug APK, unit tests, and lint pass | -| Cloud metadata | Account-owned custom name, optional number, and notes by stable instance key; owner-only RLS | Route/service tests pass | -| Public export | Allowlisted deterministic `devices/` export, root SwiftPM package, README marker block, SHA-256 manifest, hostile-path/content/symlink tests | Passing | -| nRF52840 DK | Pinned Zephyr 4.3.0 / SDK 0.17.4 workflow artifact | Build verified; physical checklist pending | -| XIAO nRF52840 / Sense | Pinned Zephyr 4.3.0 / SDK 0.17.4 workflow artifact | Build verified; physical checklist pending | -| XIAO ESP32-C3 | Pinned Zephyr 4.3.0 / SDK 0.17.4 workflow artifact | Build verified; physical checklist pending | -| XIAO ESP32-S3 | Pinned Zephyr 4.3.0 / SDK 0.17.4 workflow artifact | Build verified; physical checklist pending | -| ILX MultiPad | STM32F103VET6 USB HID + CDC upstream source; portable C99 adapter and contract test | Adapter test passing; PCB and boot-path evidence pending | +| Area | Evidence | Status | +| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | +| Wire and vectors | `approval/1`, `status/1`, bounded Device Info 0.2, JSON Schema, valid and hostile vectors | Passing; wire major remains `1` | +| JavaScript reference | Protocol, framing, relay, Device Info, documentation, simulator, and export tests | Passing | +| Swift Host SDK | Codec, Device Info, authorization, relay, coordinator, CoreBluetooth, and SwiftPM tests | Passing | +| Kotlin Host SDK | Bounded Device Info and protocol codecs used directly by Android | Passing | +| Portable C99 SDK | Fixed-buffer protocol, state, Device Info, ASan/UBSan suites | Passing | +| iOS App integration | Explicit enrollment/revocation, secure remembered devices, one active lease, battery, continuous information table, metadata sync, independent Claude Code/Codex adapters | iOS Simulator build and integration contracts pass | +| Android App integration | Public Kotlin SDK, BLE enrollment, encrypted authorization storage, battery, continuous information table, metadata sync, independent Claude Code/Codex adapters | Debug APK, unit tests, and lint pass | +| Cloud metadata | Account-owned custom name, optional number, and notes by stable instance key; owner-only RLS | Route/service tests pass | +| Public export | Allowlisted deterministic `devices/` export, root SwiftPM package, README marker block, SHA-256 manifest, hostile-path/content/symlink tests | Passing | +| nRF52840 DK | Pinned Zephyr 4.3.0 / SDK 0.17.4 workflow artifact | Build verified; physical checklist pending | +| XIAO nRF52840 / Sense | Pinned Zephyr 4.3.0 / SDK 0.17.4 workflow artifact | Build verified; physical checklist pending | +| XIAO ESP32-C3 | Pinned Zephyr 4.3.0 / SDK 0.17.4 workflow artifact | Build verified; physical checklist pending | +| XIAO ESP32-S3 | Pinned Zephyr 4.3.0 / SDK 0.17.4 workflow artifact | Build verified; physical checklist pending | +| ILX MultiPad | STM32F103VET6 USB HID + CDC upstream source; portable C99 adapter, first-case guide, and contract test | Adapter test passing; board integration and boot-path evidence pending | ## What 0.2 adds diff --git a/devices/firmware/multipad/README.md b/devices/firmware/multipad/README.md index 93a44f3..5b6a933 100644 --- a/devices/firmware/multipad/README.md +++ b/devices/firmware/multipad/README.md @@ -4,6 +4,11 @@ This directory is the public, source-first integration layer for the open-source [ILX MultiPad](https://github.com/iLx11/multi-pad). It is intentionally **not** a copy of the vendor repository and it is not Nexting production firmware. +The [first-case walkthrough](../../docs/cases/multipad-first-case.md) is the +canonical path for applying this adapter to the pinned upstream firmware. This +directory supplies the public protocol binding and tests; the upstream project +supplies the board build and remains separately licensed. + ## What is verified before opening the enclosure The upstream application is an STM32F103VET6 composite USB device: @@ -22,6 +27,11 @@ PCB** (SWD/J-Link is required). Do not assume the external Type-C connector is a bootloader. The included `nexting-multipad-device-info.template.json` keeps unknown display, serial, and battery fields absent until that check is done. +The upstream repository exposes firmware facts, not a PCB drawing. Its +`Config/stlink.cfg` selects ST-Link/SWD and its `leden.ioc` maps `PA13` to +`SWDIO` and `PA14` to `SWCLK`; physical pad order must be read from the actual +board before attaching a probe. + ## What this adapter does `nexting_multipad_adapter.c` reuses the public portable C99 SDK. It adds no diff --git a/devices/firmware/multipad/bringup-status.md b/devices/firmware/multipad/bringup-status.md index 106e884..1175306 100644 --- a/devices/firmware/multipad/bringup-status.md +++ b/devices/firmware/multipad/bringup-status.md @@ -8,17 +8,17 @@ has been performed. ## Current state -| Phase | Step | Status | Evidence | -| --- | --- | --- | --- | -| 0 | Upstream source audit | ✅ complete | STM32F103VET6, USB HID + CDC, commit `78c1ee533a7f513e9f390741c4f5eed1e0aa91b3` | -| 0 | Portable adapter build | ✅ complete | `npm run test:multipad`, CMake + ctest pass | -| 0 | Host CDC application path | ✅ complete | Connected `MultiPad_Device` CDC endpoint echoed `AA BB CC` byte-for-byte on 2026-07-31 | -| 0 | PCB variant identification | ⏳ blocked on enclosure opening | Module vs FPC is not visible from the outside | -| 0 | Original flash backup | ⏳ not started | Must identify the boot path first | -| 1 | Serial bootloader write | ⏳ not started | Only possible if the module serial path is present | -| 1 | SWD recovery/write | ⏳ not started | Required fallback for FPC or failed serial path | -| 2 | Nexting present/answer/resolved | ⏳ not started | Requires adapter firmware on the exact board | -| 2 | Status rendering | ⏳ not started | Display/indicator wiring must be photographed and mapped | +| Phase | Step | Status | Evidence | +| ----- | ------------------------------- | ------------------------------- | -------------------------------------------------------------------------------------- | +| 0 | Upstream source audit | ✅ complete | STM32F103VET6, USB HID + CDC, commit `78c1ee533a7f513e9f390741c4f5eed1e0aa91b3` | +| 0 | Portable adapter build | ✅ complete | `npm run test:multipad`, CMake + ctest pass | +| 0 | Host CDC application path | ✅ complete | Connected `MultiPad_Device` CDC endpoint echoed `AA BB CC` byte-for-byte on 2026-07-31 | +| 0 | PCB variant identification | ⏳ blocked on enclosure opening | Module vs FPC is not visible from the outside | +| 0 | Original flash backup | ⏳ not started | Must identify the boot path first | +| 1 | Serial bootloader write | ⏳ not started | Only possible if the module serial path is present | +| 1 | SWD recovery/write | ⏳ not started | Required fallback for FPC or failed serial path | +| 2 | Nexting present/answer/resolved | ⏳ not started | Requires adapter firmware on the exact board | +| 2 | Status rendering | ⏳ not started | Display/indicator wiring must be photographed and mapped | ## Bring-up order after opening diff --git a/devices/firmware/multipad/hw-review-findings.md b/devices/firmware/multipad/hw-review-findings.md index 5323430..77efd4a 100644 --- a/devices/firmware/multipad/hw-review-findings.md +++ b/devices/firmware/multipad/hw-review-findings.md @@ -4,12 +4,12 @@ Last updated: 2026-07-31 ## Findings -| ID | Finding | Impact | Next action | -| --- | --- | --- | --- | -| MP-01 | The outside photo does not identify Module PCB vs FPC PCB. | Type-C serial flashing cannot be selected safely. | Open the enclosure and photograph the PCB labels. | -| MP-02 | Upstream source contains USB HID + CDC application code but no DFU/IAP path. | Ordinary CDC enumeration cannot be used as recovery evidence. | Use the module serial boot sequence or SWD/J-Link. | -| MP-03 | Upstream source exposes matrix and encoder modules, but the purchased unit's exact display/connector revision is unverified. | Device Info must not claim battery/display details yet. | Map traces and connectors after opening. | -| MP-04 | The live device echoed `AA BB CC` over CDC before any write. | Confirms the application CDC endpoint, not a bootloader. | Keep this as the baseline regression check. | +| ID | Finding | Impact | Next action | +| ----- | ---------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | -------------------------------------------------- | +| MP-01 | The outside photo does not identify Module PCB vs FPC PCB. | Type-C serial flashing cannot be selected safely. | Open the enclosure and photograph the PCB labels. | +| MP-02 | Upstream source contains USB HID + CDC application code but no DFU/IAP path. | Ordinary CDC enumeration cannot be used as recovery evidence. | Use the module serial boot sequence or SWD/J-Link. | +| MP-03 | Upstream source exposes matrix and encoder modules, but the purchased unit's exact display/connector revision is unverified. | Device Info must not claim battery/display details yet. | Map traces and connectors after opening. | +| MP-04 | The live device echoed `AA BB CC` over CDC before any write. | Confirms the application CDC endpoint, not a bootloader. | Keep this as the baseline regression check. | No electrical anomaly has been observed because the enclosure has not been opened. Any mismatch with the source or schematic must be added here before diff --git a/devices/firmware/multipad/pin-function-map.md b/devices/firmware/multipad/pin-function-map.md index 8034f7d..c757d0f 100644 --- a/devices/firmware/multipad/pin-function-map.md +++ b/devices/firmware/multipad/pin-function-map.md @@ -8,36 +8,36 @@ board. The Nexting adapter itself is pin-agnostic and does not add a pin claim. ## Pin mappings visible in upstream source -| Pin | MCU function | Hardware connection | Function | Driver/source | Verification | Notes | -| --- | --- | --- | --- | --- | --- | --- | -| PB10 | GPIO output | matrix row 0 | key matrix row | upstream `KEY` module | ⏳ physical pending | source-level only | -| PB11 | GPIO output | matrix row 1 | key matrix row | upstream `KEY` module | ⏳ physical pending | source-level only | -| PE12 | GPIO input | matrix column 0 | key matrix column | upstream `KEY` module | ⏳ physical pending | source-level only | -| PE13 | GPIO input | matrix column 1 | key matrix column | upstream `KEY` module | ⏳ physical pending | source-level only | -| PE14 | GPIO input | matrix column 2 | key matrix column | upstream `KEY` module | ⏳ physical pending | source-level only | -| PE15 | GPIO input | matrix column 3 | key matrix column | upstream `KEY` module | ⏳ physical pending | source-level only | -| PA9 | USART1 TX | serial module path | bootloader/UART TX | upstream `USART1` init | ⏳ physical pending | only module PCB exposes this path | -| PA10 | USART1 RX | serial module path | bootloader/UART RX | upstream `USART1` init | ⏳ physical pending | only module PCB exposes this path | -| SWDIO | debug pad | MCU SWD header/pads | recovery/program data | ST-Link/J-Link | ⏳ physical pending | pad location unknown | -| SWCLK | debug pad | MCU SWD header/pads | recovery/program clock | ST-Link/J-Link | ⏳ physical pending | pad location unknown | +| Pin | MCU function | Hardware connection | Function | Driver/source | Verification | Notes | +| ----- | ------------ | ------------------- | ---------------------- | ---------------------- | ------------------- | --------------------------------- | +| PB10 | GPIO output | matrix row 0 | key matrix row | upstream `KEY` module | ⏳ physical pending | source-level only | +| PB11 | GPIO output | matrix row 1 | key matrix row | upstream `KEY` module | ⏳ physical pending | source-level only | +| PE12 | GPIO input | matrix column 0 | key matrix column | upstream `KEY` module | ⏳ physical pending | source-level only | +| PE13 | GPIO input | matrix column 1 | key matrix column | upstream `KEY` module | ⏳ physical pending | source-level only | +| PE14 | GPIO input | matrix column 2 | key matrix column | upstream `KEY` module | ⏳ physical pending | source-level only | +| PE15 | GPIO input | matrix column 3 | key matrix column | upstream `KEY` module | ⏳ physical pending | source-level only | +| PA9 | USART1 TX | serial module path | bootloader/UART TX | upstream `USART1` init | ⏳ physical pending | only module PCB exposes this path | +| PA10 | USART1 RX | serial module path | bootloader/UART RX | upstream `USART1` init | ⏳ physical pending | only module PCB exposes this path | +| SWDIO | debug pad | MCU SWD header/pads | recovery/program data | ST-Link/J-Link | ⏳ physical pending | pad location unknown | +| SWCLK | debug pad | MCU SWD header/pads | recovery/program clock | ST-Link/J-Link | ⏳ physical pending | pad location unknown | ## Functions needing an enclosure photograph -| Function | Expected source evidence | Physical evidence required | Status | -| --- | --- | --- | --- | -| 8 key matrix | 2 rows × 4 columns | trace/connector and switch orientation | ⏳ | -| 3 rotary encoders | `encoder1`, `encoder2`, `encoder3` modules | exact A/B/SW pins and pull-ups | ⏳ | -| Displays | upstream OLED/LCD modules | module/FPC variant, bus pins, dimensions | ⏳ | -| USB HID + CDC | STM32 USB device stack | connector wiring and stable enumeration | ✅ host CDC echo only | -| BOOT/RESET | module PCB documentation | buttons and switch labels | ⏳ | -| Battery | no battery service found in upstream source | battery/charger IC and ADC trace | ⏳ / do not declare | +| Function | Expected source evidence | Physical evidence required | Status | +| ----------------- | ------------------------------------------- | ---------------------------------------- | --------------------- | +| 8 key matrix | 2 rows × 4 columns | trace/connector and switch orientation | ⏳ | +| 3 rotary encoders | `encoder1`, `encoder2`, `encoder3` modules | exact A/B/SW pins and pull-ups | ⏳ | +| Displays | upstream OLED/LCD modules | module/FPC variant, bus pins, dimensions | ⏳ | +| USB HID + CDC | STM32 USB device stack | connector wiring and stable enumeration | ✅ host CDC echo only | +| BOOT/RESET | module PCB documentation | buttons and switch labels | ⏳ | +| Battery | no battery service found in upstream source | battery/charger IC and ADC trace | ⏳ / do not declare | ## Reverse index -| Goal | Pins/peripheral | Preconditions | Status | -| --- | --- | --- | --- | -| Preserve keyboard HID | USB device stack | device still enumerates | ✅ before flash | -| Read original flash | PA9/PA10 serial or SWD | confirmed PCB path | ⏳ | -| Nexting CDC frames | USB CDC RX/TX | adapter image + CDC callback hook | ⏳ | -| Approval keys | key matrix + encoder/button map | exact input wiring | ⏳ | -| Status rendering | displays/LEDs | exact display map | ⏳ | +| Goal | Pins/peripheral | Preconditions | Status | +| --------------------- | ------------------------------- | --------------------------------- | --------------- | +| Preserve keyboard HID | USB device stack | device still enumerates | ✅ before flash | +| Read original flash | PA9/PA10 serial or SWD | confirmed PCB path | ⏳ | +| Nexting CDC frames | USB CDC RX/TX | adapter image + CDC callback hook | ⏳ | +| Approval keys | key matrix + encoder/button map | exact input wiring | ⏳ | +| Status rendering | displays/LEDs | exact display map | ⏳ | diff --git a/devices/scripts/documentation-contract.test.mjs b/devices/scripts/documentation-contract.test.mjs index 7a43cd4..4d6beb3 100644 --- a/devices/scripts/documentation-contract.test.mjs +++ b/devices/scripts/documentation-contract.test.mjs @@ -150,6 +150,36 @@ test("reader entry points link the public documentation system", async () => { assert.doesNotMatch(development, /ESP32 builds.*pending/i); }); +test("the first MultiPad case pins its source and keeps flash claims honest", async () => { + const [caseGuide, multipad] = await Promise.all([ + read("docs/cases/multipad-first-case.md"), + read("docs/multipad-usb.md"), + ]); + + for (const marker of [ + "iLx11/multi-pad", + "78c1ee533a7f513e9f390741c4f5eed1e0aa91b3", + "PA13 = SWDIO", + "PA14 = SWCLK", + "nexting_multipad_adapter.c/.h", + "AA BB xx", + "present → answer → resolved", + "Module PCB", + "FPC PCB", + "原版固件", + "Nexting HEX", + ]) { + assert.ok( + caseGuide.includes(marker), + "case guide missing marker: " + marker, + ); + } + + assert.match(caseGuide, /不能把原固件误当作 Nexting 固件/); + assert.match(caseGuide, /不能.*直接 Type-C 烧录|Type-C.*bootloader/); + assert.match(multipad, /cases\/multipad-first-case\.md/); +}); + test("use-case guide maps scenarios to real profiles and limits", async () => { const useCases = await read("docs/use-cases.md"); diff --git a/devices/scripts/export-manifest.json b/devices/scripts/export-manifest.json index e67d735..fff0455 100644 --- a/devices/scripts/export-manifest.json +++ b/devices/scripts/export-manifest.json @@ -13,6 +13,7 @@ "SPEC.md", "docs/README.md", "docs/board-verification.md", + "docs/cases/multipad-first-case.md", "docs/conformance.md", "docs/development.md", "docs/first-approval.md",