driverge-mcp 0.0.1 โ 0.1.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +138 -113
- package/dist/codegen/esp32.js +7 -7
- package/dist/codegen/esp32.js.map +1 -1
- package/dist/codegen/ident.d.ts +9 -0
- package/dist/codegen/ident.js +11 -0
- package/dist/codegen/ident.js.map +1 -1
- package/dist/codegen/portable-cpp.js +15 -13
- package/dist/codegen/portable-cpp.js.map +1 -1
- package/dist/codegen/portable.js +26 -20
- package/dist/codegen/portable.js.map +1 -1
- package/dist/codegen/stm32.js +14 -10
- package/dist/codegen/stm32.js.map +1 -1
- package/dist/mcp/cache.js +1 -1
- package/dist/mcp/cache.js.map +1 -1
- package/dist/mcp/register.js +41 -4
- package/dist/mcp/register.js.map +1 -1
- package/dist/pdf/command.d.ts +21 -0
- package/dist/pdf/command.js +105 -10
- package/dist/pdf/command.js.map +1 -1
- package/dist/pdf/extract.js +27 -1
- package/dist/pdf/extract.js.map +1 -1
- package/dist/pdf/part.js +2 -0
- package/dist/pdf/part.js.map +1 -1
- package/dist/pdf/register-table.d.ts +4 -0
- package/dist/pdf/register-table.js +4 -2
- package/dist/pdf/register-table.js.map +1 -1
- package/dist/pdf/ti-command-byte.d.ts +7 -0
- package/dist/pdf/ti-command-byte.js +165 -0
- package/dist/pdf/ti-command-byte.js.map +1 -0
- package/dist/schema/assemble.js +7 -0
- package/dist/schema/assemble.js.map +1 -1
- package/dist/schema/validate.js +30 -1
- package/dist/schema/validate.js.map +1 -1
- package/dist/server.js +5 -0
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,16 +7,24 @@
|
|
|
7
7
|
<a href="https://www.npmjs.com/package/driverge-mcp"><img alt="npm" src="https://img.shields.io/npm/v/driverge-mcp"></a>
|
|
8
8
|
<a href="https://github.com/MehmetTopuz/driverge-mcp/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/MehmetTopuz/driverge-mcp/actions/workflows/ci.yml/badge.svg"></a>
|
|
9
9
|
<a href="LICENSE"><img alt="license" src="https://img.shields.io/badge/license-MIT-blue"></a>
|
|
10
|
-
<img alt="status" src="https://img.shields.io/badge/status-
|
|
10
|
+
<img alt="status" src="https://img.shields.io/badge/status-closed%20beta-orange">
|
|
11
11
|
<img alt="mcp" src="https://img.shields.io/badge/MCP-server-black">
|
|
12
12
|
</p>
|
|
13
13
|
|
|
14
|
-
>
|
|
15
|
-
>
|
|
16
|
-
> JSON schema may still change before
|
|
14
|
+
> ๐งช **Closed beta** โ install with **`npm i driverge-mcp@beta`** or run directly
|
|
15
|
+
> with `npx -y driverge-mcp@beta`. Generated drivers are reviewed *drafts*, not
|
|
16
|
+
> hardware-certified firmware, and the JSON schema may still change before the
|
|
17
|
+
> stable **v0.1.0** โ see [Maturity & status](#maturity--status), and
|
|
18
|
+
> [BETA.md](BETA.md) if you're testing.
|
|
17
19
|
|
|
18
20
|
---
|
|
19
21
|
|
|
22
|
+
**Contents:** [What is Driverge?](#what-is-driverge) ยท
|
|
23
|
+
[Quick start](#quick-start) ยท [Why Driverge?](#why-driverge) ยท
|
|
24
|
+
[What it does](#what-it-does) ยท [Maturity & status](#maturity--status) ยท
|
|
25
|
+
[Concepts](#concepts-behind-driverge) ยท [Installation](#installation) ยท
|
|
26
|
+
[Usage](#usage) ยท [Troubleshooting](#troubleshooting) ยท [Roadmap](#roadmap)
|
|
27
|
+
|
|
20
28
|
## What is Driverge?
|
|
21
29
|
|
|
22
30
|
**Driverge is a client-agnostic [MCP](https://modelcontextprotocol.io) server**
|
|
@@ -24,10 +32,14 @@ that turns an IC datasheet PDF into an embedded C/C++ driver. It plugs into any
|
|
|
24
32
|
MCP-capable host โ Claude Desktop, Claude Code (VS Code), Cursor, and others.
|
|
25
33
|
|
|
26
34
|
Its guiding principle: **deterministic code parses and validates; the host AI
|
|
27
|
-
reasons.** Driverge
|
|
28
|
-
TypeScript pipeline extracts a *validated, structured JSON* model of the chip,
|
|
29
|
-
the host AI you're already talking to fills in the reasoning-heavy parts
|
|
30
|
-
sequence, vendor quirks, docs). Your datasheet never leaves your machine.
|
|
35
|
+
reasons.** Driverge contains **no internal LLM and needs no API keys** โ a
|
|
36
|
+
TypeScript pipeline extracts a *validated, structured JSON* model of the chip,
|
|
37
|
+
and the host AI you're already talking to fills in the reasoning-heavy parts
|
|
38
|
+
(init sequence, vendor quirks, docs). Your datasheet never leaves your machine.
|
|
39
|
+
|
|
40
|
+
<p align="center">
|
|
41
|
+
<img src="assets/driverge-flow.png" alt="How Driverge works: a datasheet PDF flows through the deterministic analyze โ frozen JSON โ generate โ validate pipeline; the host AI fills the TODO(driverge) gaps and the loop repeats until validation passes, producing driver.c/.h" width="760">
|
|
42
|
+
</p>
|
|
31
43
|
|
|
32
44
|
## Quick start
|
|
33
45
|
|
|
@@ -54,30 +66,22 @@ That's it โ no clone, no build, no API key. Details in
|
|
|
54
66
|
|
|
55
67
|
Bringing up a new sensor or IC means hand-transcribing dozens of register
|
|
56
68
|
addresses, bit-field masks, and command codes out of a 40-page PDF โ slow work,
|
|
57
|
-
and a classic source of silent bugs (one wrong mask
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
- **No hallucinated register maps.** Addresses,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
(Claude Desktop, Claude Code, Cursor, โฆ) and reasons with the model you're
|
|
68
|
-
already paying for โ no separate subscription or service.
|
|
69
|
-
- **Private & offline.** The datasheet is parsed locally and never uploaded โ safe
|
|
70
|
-
for NDA'd or unreleased parts.
|
|
69
|
+
and a classic source of silent bugs (one wrong mask and the driver "works" but
|
|
70
|
+
reads garbage). Driverge does that mechanical part deterministically and leaves
|
|
71
|
+
the judgment to the AI you already use.
|
|
72
|
+
|
|
73
|
+
- **No hallucinated register maps.** Addresses, masks, and command codes are
|
|
74
|
+
*extracted from the datasheet and validated* โ not guessed. Invalid or
|
|
75
|
+
incomplete data is rejected before it can become code.
|
|
76
|
+
- **Bring your own client โ private by design.** A plain MCP server with no
|
|
77
|
+
embedded LLM: it reasons with the model you're already paying for, and the
|
|
78
|
+
datasheet is parsed locally, never uploaded โ safe for NDA'd parts.
|
|
71
79
|
- **Deterministic & reproducible.** The same PDF always yields the same JSON and
|
|
72
|
-
the same driver skeleton โ reviewable, diff-able, and testable
|
|
73
|
-
black box.
|
|
80
|
+
the same driver skeleton โ reviewable, diff-able, and testable.
|
|
74
81
|
- **Portable by construction.** One driver core targets any platform through a
|
|
75
|
-
tiny per-bus thin-HAL seam
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
init-sequence ordering, timing quirks, and compensation math need judgment.
|
|
79
|
-
Driverge marks exactly those spots with `TODO(driverge)` and a `fill_in_brief`,
|
|
80
|
-
the host AI completes them, then `validate_driver` checks the result.
|
|
82
|
+
tiny per-bus thin-HAL seam; native targets (STM32, ESP32) pre-fill it. The AI
|
|
83
|
+
completes only the marked `TODO(driverge)` gaps, and `validate_driver` checks
|
|
84
|
+
the result.
|
|
81
85
|
|
|
82
86
|
**Good for:** quickly evaluating a new sensor, prototyping, porting an existing
|
|
83
87
|
driver to a different MCU, or just learning an unfamiliar chip's register map.
|
|
@@ -89,41 +93,38 @@ driver to a different MCU, or just learning an unfamiliar chip's register map.
|
|
|
89
93
|
commands + CRC) and the bus protocol into a **frozen JSON contract**, gated by
|
|
90
94
|
a validator.
|
|
91
95
|
2. **Generate** a driver for a target platform, in C or C++: a deterministic
|
|
92
|
-
**thin-HAL skeleton** โ register/bit-field constants, the per-bus
|
|
93
|
-
|
|
94
|
-
telling the host AI exactly what to complete.
|
|
95
|
-
3. **Validate** the completed driver: thin-HAL purity, no leftover TODOs,
|
|
96
|
-
references exist, bit-field masks match the JSON.
|
|
96
|
+
**thin-HAL skeleton** โ register/bit-field constants, the per-bus seam,
|
|
97
|
+
function stubs โ with every reasoning gap marked `TODO(driverge)` plus a
|
|
98
|
+
`fill_in_brief` telling the host AI exactly what to complete.
|
|
99
|
+
3. **Validate** the completed driver: thin-HAL purity, no leftover TODOs,
|
|
100
|
+
register references exist, bit-field masks match the JSON.
|
|
97
101
|
|
|
98
102
|
### Supported targets
|
|
99
103
|
|
|
100
|
-
Every target specializes the same portable
|
|
101
|
-
seam โ
|
|
104
|
+
Every target specializes the same portable
|
|
105
|
+
**[thin-HAL](https://en.wikipedia.org/wiki/Hardware_abstraction_layer)** seam โ
|
|
106
|
+
the driver core is identical across platforms; only the seam implementation
|
|
102
107
|
changes.
|
|
103
108
|
|
|
104
|
-
| Target | Bus binding | Buses | Language |
|
|
109
|
+
| Target | Bus binding | Buses | Language | Maturity |
|
|
105
110
|
|---|---|---|---|---|
|
|
106
|
-
| **Portable (thin-HAL)** | user-implemented `hal_*` seam | IยฒC, SPI, UART, CAN | C / C++ |
|
|
107
|
-
| **ESP32** | ESP-IDF (`i2c_master_*`, `spi_master`, `uart`, TWAI) | IยฒC, SPI, UART, CAN | C / C++ |
|
|
108
|
-
| **STM32** | CubeHAL (`HAL_I2C_*`, `HAL_SPI_*` + GPIO CS, `HAL_UART_*`) | IยฒC, SPI, UART | C / C++ |
|
|
109
|
-
| **Arduino** | `Wire` / `SPI` | โ | C++ |
|
|
111
|
+
| **Portable (thin-HAL)** | user-implemented `hal_*` seam | IยฒC, SPI, UART, CAN | C / C++ | **Beta** โ host-tested, gcc-compiled in CI; not yet on hardware |
|
|
112
|
+
| **ESP32** | ESP-IDF (`i2c_master_*`, `spi_master`, `uart`, TWAI) | IยฒC, SPI, UART, CAN | C / C++ | **Experimental** โ one informal IยฒC bring-up; SPI/UART/CAN never on hardware |
|
|
113
|
+
| **STM32** | CubeHAL (`HAL_I2C_*`, `HAL_SPI_*` + GPIO CS, `HAL_UART_*`) | IยฒC, SPI, UART | C / C++ | **Experimental** โ never on hardware |
|
|
114
|
+
| **Arduino** | `Wire` / `SPI` | โ | C++ | not implemented |
|
|
110
115
|
|
|
111
|
-
STM32 CAN is planned (the bxCAN/FDCAN family split needs its own pass); asking
|
|
112
|
-
|
|
116
|
+
STM32 CAN is planned (the bxCAN/FDCAN family split needs its own pass); asking a
|
|
117
|
+
target for a bus it doesn't support fails fast with a clear
|
|
113
118
|
`UnsupportedBusError` rather than emitting a wrong seam. Pass
|
|
114
119
|
`language: "cpp"` to `generate_driver` for a class-based C++ driver
|
|
115
120
|
(`.hpp`/`.cpp`) instead of the default C output โ same registers, same seam,
|
|
116
|
-
same validation.
|
|
117
|
-
|
|
118
|
-
> โ ๏ธ **Generated code is a strong draft, not a certified driver.** Init sequences,
|
|
119
|
-
> compensation formulas, and timing quirks are completed by the host AI and
|
|
120
|
-
> **must be reviewed** before use on hardware. Not safety-certified.
|
|
121
|
+
same validation. What "Beta" and "Experimental" mean exactly is spelled out in
|
|
122
|
+
[Maturity & status](#maturity--status).
|
|
121
123
|
|
|
122
124
|
### Verified parts
|
|
123
125
|
|
|
124
126
|
The extraction pipeline is regression-tested against real datasheets from
|
|
125
|
-
**12 manufacturers**. Parts with fully automatic extraction
|
|
126
|
-
bit-fields, or a clean command set):
|
|
127
|
+
**12 manufacturers**. Parts with fully automatic extraction:
|
|
127
128
|
|
|
128
129
|
| Part | Manufacturer | Kind | Extracted |
|
|
129
130
|
|---|---|---|---|
|
|
@@ -137,44 +138,52 @@ bit-fields, or a clean command set):
|
|
|
137
138
|
|
|
138
139
|
Other tested parts (ADXL345, MLX90614, AEAT-8811, PCA9685, VL53L3CX, TLE5014)
|
|
139
140
|
extract **partially** or **defer** to the host AI โ the pipeline says so
|
|
140
|
-
explicitly instead of guessing,
|
|
141
|
-
what to complete. The full, always-current matrix lives in the
|
|
141
|
+
explicitly instead of guessing. The full, always-current matrix lives in the
|
|
142
142
|
[coverage scorecard](tests/scorecard/scorecard.snap.md).
|
|
143
143
|
|
|
144
|
+
## Maturity & status
|
|
145
|
+
|
|
146
|
+
Driverge is in **closed beta** (`0.1.0-beta.x`, npm `beta` dist-tag).
|
|
147
|
+
|
|
148
|
+
**Proven today (host-level):**
|
|
149
|
+
- The full deterministic test suite is green (440-plus tests) on a clean
|
|
150
|
+
TypeScript build, and the **portable** driver is compiled by a real `gcc`
|
|
151
|
+
gate in CI.
|
|
152
|
+
- The extraction pipeline is regression-tested against **13 real datasheets**
|
|
153
|
+
and reports its own coverage honestly โ 7 fully extracted, 3 partial, 3
|
|
154
|
+
deferred (see the [coverage scorecard](tests/scorecard/scorecard.snap.md)).
|
|
155
|
+
|
|
156
|
+
**Not yet proven โ this is the beta โ v0.1.0 gate:**
|
|
157
|
+
- **On-hardware behavior is not gated.** Only one informal ESP32 bring-up has
|
|
158
|
+
run (MPU-9250, hand-completed); there is no clean, repeatable hardware pass
|
|
159
|
+
yet, and STM32 has never run on silicon.
|
|
160
|
+
- The native ESP32/STM32 seams are not yet built by an automated compile gate
|
|
161
|
+
(ESP-IDF / CubeIDE) โ only the portable target is.
|
|
162
|
+
- Only one MCP client has been exercised end-to-end.
|
|
163
|
+
|
|
164
|
+
> โ ๏ธ Treat every generated driver as a **reviewed draft**: check register
|
|
165
|
+
> addresses, the init sequence, and any compensation math against the datasheet
|
|
166
|
+
> before you flash it. Driverge is not safety-certified.
|
|
167
|
+
|
|
168
|
+
**Testing the beta?** [BETA.md](BETA.md) has the identity-register smoke test to
|
|
169
|
+
run and how to send a field report.
|
|
170
|
+
|
|
144
171
|
## Concepts behind Driverge
|
|
145
172
|
|
|
146
173
|
Driverge splits driver-writing into two kinds of work: the **mechanical part**
|
|
147
174
|
(register addresses, masks, command tables โ extracted and checked by
|
|
148
175
|
deterministic code) and the **judgment part** (init ordering, timing quirks,
|
|
149
176
|
compensation math โ completed by the host AI). Everything below exists to keep
|
|
150
|
-
that boundary sharp
|
|
151
|
-
|
|
152
|
-
```mermaid
|
|
153
|
-
flowchart LR
|
|
154
|
-
PDF["Datasheet PDF"]
|
|
155
|
-
subgraph D["Driverge โ deterministic, no LLM"]
|
|
156
|
-
A["analyze_datasheet<br>L1โL5 parse + validate"]
|
|
157
|
-
J[("frozen JSON<br>cached under a ref")]
|
|
158
|
-
G["generate_driver<br>thin-HAL skeleton +<br>TODO(driverge) markers"]
|
|
159
|
-
V["validate_driver<br>static lint"]
|
|
160
|
-
end
|
|
161
|
-
subgraph H["Host AI โ reasoning"]
|
|
162
|
-
F["fill the TODOs: init sequence,<br>quirks, compensation docs"]
|
|
163
|
-
end
|
|
164
|
-
OUT["driver.c / driver.h"]
|
|
165
|
-
PDF --> A --> J --> G --> F --> V
|
|
166
|
-
V -->|pass| OUT
|
|
167
|
-
V -->|fail| F
|
|
168
|
-
```
|
|
177
|
+
that boundary sharp; the diagram at the top of this page shows how the pieces
|
|
178
|
+
connect.
|
|
169
179
|
|
|
170
180
|
### Deterministic core, reasoning at the edge
|
|
171
181
|
|
|
172
182
|
Register geometry is mechanical: an address is right or wrong, a mask either
|
|
173
183
|
matches the datasheet or it doesn't. Driverge handles that part with plain
|
|
174
|
-
TypeScript โ no
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
is left to the host AI you're already talking to.
|
|
184
|
+
TypeScript โ no sampling, so the output is the same on every run. What genuinely
|
|
185
|
+
needs judgment (in what order to poke the registers, which timing quirk applies)
|
|
186
|
+
is left to the host AI.
|
|
178
187
|
|
|
179
188
|
### The frozen JSON contract
|
|
180
189
|
|
|
@@ -206,12 +215,13 @@ else:
|
|
|
206
215
|
| UART | `hal_uart_write`, `hal_uart_read` |
|
|
207
216
|
| CAN | `hal_can_transfer` (one call = one frame exchange) |
|
|
208
217
|
|
|
209
|
-
The
|
|
210
|
-
(
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
218
|
+
The transfer seams return `int` โ **`0` on success, non-zero on a bus error**
|
|
219
|
+
(NACK, timeout) โ and the generated register accessors propagate that status
|
|
220
|
+
instead of swallowing it; native seams (ESP32, STM32) return their vendor
|
|
221
|
+
status, which is already `0` on success. `validate_driver` enforces seam
|
|
222
|
+
purity: a driver that calls a vendor peripheral API outside the seam fails the
|
|
223
|
+
lint. Buses with no universal register-access primitive (UART, CAN) get their
|
|
224
|
+
device-specific framing as a marked `TODO(driverge)` gap, completed by the host
|
|
215
225
|
AI and then linted.
|
|
216
226
|
|
|
217
227
|
### The fill-in loop
|
|
@@ -226,28 +236,17 @@ matching the JSON โ and the loop repeats until it passes.
|
|
|
226
236
|
|
|
227
237
|
**Prerequisites:** Node.js LTS (โฅ 18; CI-tested on Node 20 & 22).
|
|
228
238
|
|
|
229
|
-
|
|
230
|
-
[npx](https://docs.npmjs.com/cli/commands/npx) fetches and runs it):
|
|
239
|
+
Install the beta from npm:
|
|
231
240
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
{
|
|
235
|
-
"mcpServers": {
|
|
236
|
-
"driverge": { "command": "npx", "args": ["-y", "driverge-mcp"] }
|
|
237
|
-
}
|
|
238
|
-
}
|
|
241
|
+
```bash
|
|
242
|
+
npm i driverge-mcp@beta
|
|
239
243
|
```
|
|
240
244
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
"driverge": { "command": "npx", "args": ["-y", "driverge-mcp"] }
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
```
|
|
245
|
+
Or skip the install entirely โ the config below launches Driverge via
|
|
246
|
+
[npx](https://docs.npmjs.com/cli/commands/npx), which downloads it from npm on
|
|
247
|
+
first run, caches it, and starts it automatically each time the client does
|
|
248
|
+
(`-y` skips npx's install prompt). Add one entry to your MCP client's config:
|
|
249
249
|
|
|
250
|
-
**Cursor** โ `.cursor/mcp.json`:
|
|
251
250
|
```json
|
|
252
251
|
{
|
|
253
252
|
"mcpServers": {
|
|
@@ -256,15 +255,22 @@ Add Driverge to your MCP client (no build step โ
|
|
|
256
255
|
}
|
|
257
256
|
```
|
|
258
257
|
|
|
259
|
-
|
|
260
|
-
|
|
258
|
+
| Client | Config file |
|
|
259
|
+
|---|---|
|
|
260
|
+
| Claude Desktop | `claude_desktop_config.json` |
|
|
261
|
+
| Claude Code (VS Code) | `.mcp.json` in your workspace root |
|
|
262
|
+
| Cursor | `.cursor/mcp.json` |
|
|
263
|
+
| Others (Codex, Gemini CLI, โฆ) | same `command` + `args` pair in their own MCP config |
|
|
261
264
|
|
|
262
|
-
**
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
the
|
|
265
|
+
> **Beta testers:** pin the beta channel explicitly with `["-y",
|
|
266
|
+
> "driverge-mcp@beta"]` as the `args`. Plain `driverge-mcp` resolves the npm
|
|
267
|
+
> `latest` tag, which deliberately lags the beta during closed beta.
|
|
268
|
+
|
|
269
|
+
You never run the server by hand โ to confirm it's wired up, ask your client to
|
|
270
|
+
run the `ping` tool, which replies `pong`. On Windows, prefer writing the
|
|
271
|
+
config file directly over `claude mcp add` โ see
|
|
272
|
+
[Troubleshooting](#troubleshooting). Cloning the repo (below) is only for
|
|
273
|
+
development.
|
|
268
274
|
|
|
269
275
|
### Configuration
|
|
270
276
|
|
|
@@ -329,6 +335,13 @@ Give your MCP client a datasheet and ask it to build a driver. The typical flow:
|
|
|
329
335
|
|
|
330
336
|
Reusing the same `ref` with a different `target` re-renders with **no re-parse**.
|
|
331
337
|
|
|
338
|
+
**Completing a `deferred` datasheet.** When `analyze_datasheet` reports
|
|
339
|
+
`extraction: deferred`, the host AI reconstructs the register map from the
|
|
340
|
+
`driverge://datasheet/<ref>` resource and persists it back with
|
|
341
|
+
`validate_datasheet({ "ref": "โฆ", "json": { โฆ } })` โ passing **both** `ref` and
|
|
342
|
+
the completed `json` overwrites the cached datasheet under that `ref`, so the
|
|
343
|
+
next `generate_driver` renders the real registers instead of a TODO stub.
|
|
344
|
+
|
|
332
345
|
### Worked example โ BME280 โ portable driver
|
|
333
346
|
|
|
334
347
|
> "Analyze the datasheet at `C:/ds/bme280.pdf` with driverge, then generate a
|
|
@@ -371,7 +384,7 @@ datasheet prose, and `validate_driver` checks the result.
|
|
|
371
384
|
| Tool | `analyze_datasheet` | PDF โ validated JSON, cached under a `ref` |
|
|
372
385
|
| Tool | `generate_driver` | `ref` + `target` โ driver skeleton + `fill_in_brief` |
|
|
373
386
|
| Tool | `validate_driver` | static-lint a completed driver against its `ref` |
|
|
374
|
-
| Tool | `validate_datasheet` | re-run the
|
|
387
|
+
| Tool | `validate_datasheet` | re-run the validator over a `ref` or JSON; passing **both** persists the completed datasheet under that `ref` |
|
|
375
388
|
| Tool | `ping` | health check โ confirms the server is running |
|
|
376
389
|
| Resource | `driverge://datasheet/<ref>` | full parsed JSON for an analyzed datasheet |
|
|
377
390
|
| Resource | `driverge://schema` | the frozen datasheet JSON-Schema contract |
|
|
@@ -395,15 +408,27 @@ datasheet prose, and `validate_driver` checks the result.
|
|
|
395
408
|
- **`UnsupportedBusError` on a native target.** The target doesn't support that
|
|
396
409
|
part's bus yet (today that means CAN on STM32, or a bus the parser couldn't
|
|
397
410
|
identify). Generate the **portable** target instead and implement its seam.
|
|
411
|
+
- **Windows: prefer editing the config file over the `claude mcp add` CLI.**
|
|
412
|
+
`claude mcp add โฆ -- npx -y driverge-mcp` can eat the `-y` itself (`unknown
|
|
413
|
+
option '-y'`), and PowerShell 5.1 mangles the nested quotes in `claude mcp
|
|
414
|
+
add-json`. Writing the JSON block directly into `.mcp.json` /
|
|
415
|
+
`claude_desktop_config.json` sidesteps both.
|
|
416
|
+
- **Windows: spawning the server from your own script.** Launching `npx.cmd`
|
|
417
|
+
from Node needs `shell: true` (otherwise `spawn EINVAL`). MCP clients handle
|
|
418
|
+
this for you; it only bites custom smoke-test scripts.
|
|
419
|
+
- **"Pending approval" in `claude mcp list`.** A project-scope `.mcp.json` may
|
|
420
|
+
show as `โธ Pending approval` in a separate `claude mcp list` process while
|
|
421
|
+
the `driverge` tools are already callable in your active session โ the
|
|
422
|
+
listing lags the running session.
|
|
398
423
|
|
|
399
424
|
## Roadmap
|
|
400
425
|
|
|
401
426
|
- **v0.x** โ one reference sensor (BME280), portable thin-HAL core, MCP surface,
|
|
402
427
|
multiple clients. โ
|
|
403
|
-
- **v0.y** โ native
|
|
404
|
-
multi-manufacturer extraction โ
|
|
405
|
-
[Verified parts](#verified-parts)); multi-bus seam families
|
|
406
|
-
CAN) โ
; C or C++ output โ
. *(current)*
|
|
428
|
+
- **v0.y** โ native codegen: ESP32 โ
, STM32 โ
*(on-hardware verification is the
|
|
429
|
+
beta โ v0.1.0 gate)*, Arduino (next); multi-manufacturer extraction โ
|
|
430
|
+
(12 vendors โ see [Verified parts](#verified-parts)); multi-bus seam families
|
|
431
|
+
(IยฒC, SPI, UART, CAN) โ
; C or C++ output โ
. *(current)*
|
|
407
432
|
- **v1.0** โ broader vendor/part coverage, STM32 CAN (bxCAN/FDCAN), and a
|
|
408
433
|
stable, versioned JSON schema.
|
|
409
434
|
|
package/dist/codegen/esp32.js
CHANGED
|
@@ -66,20 +66,20 @@ function halImplI2c(name, prefix, language) {
|
|
|
66
66
|
` return i2c_master_bus_add_device(bus, &cfg, &s_${name}_dev);`,
|
|
67
67
|
"}",
|
|
68
68
|
"",
|
|
69
|
-
"
|
|
69
|
+
"int hal_i2c_write(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len) {",
|
|
70
70
|
" uint8_t buf[33];",
|
|
71
71
|
" (void)addr; /* the device handle already encodes the bus address */",
|
|
72
72
|
" if ((size_t)len + 1u > sizeof buf) {",
|
|
73
|
-
" return;",
|
|
73
|
+
" return ESP_ERR_INVALID_SIZE;",
|
|
74
74
|
" }",
|
|
75
75
|
" buf[0] = reg;",
|
|
76
76
|
" memcpy(&buf[1], data, len);",
|
|
77
|
-
` i2c_master_transmit(s_${name}_dev, buf, (size_t)len + 1u, ${prefix}_I2C_TIMEOUT_MS);`,
|
|
77
|
+
` return i2c_master_transmit(s_${name}_dev, buf, (size_t)len + 1u, ${prefix}_I2C_TIMEOUT_MS);`,
|
|
78
78
|
"}",
|
|
79
79
|
"",
|
|
80
|
-
"
|
|
80
|
+
"int hal_i2c_read(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len) {",
|
|
81
81
|
" (void)addr;",
|
|
82
|
-
` i2c_master_transmit_receive(s_${name}_dev, ®, 1, data, len, ${prefix}_I2C_TIMEOUT_MS);`,
|
|
82
|
+
` return i2c_master_transmit_receive(s_${name}_dev, ®, 1, data, len, ${prefix}_I2C_TIMEOUT_MS);`,
|
|
83
83
|
"}",
|
|
84
84
|
"",
|
|
85
85
|
"void hal_delay_ms(uint32_t ms) {",
|
|
@@ -123,14 +123,14 @@ function halImplSpi(name, prefix, language) {
|
|
|
123
123
|
` return spi_bus_add_device(host, &cfg, &s_${name}_dev);`,
|
|
124
124
|
"}",
|
|
125
125
|
"",
|
|
126
|
-
"
|
|
126
|
+
"int hal_spi_transfer(const uint8_t *tx, uint16_t tx_len, uint8_t *rx, uint16_t rx_len) {",
|
|
127
127
|
" spi_transaction_t t;",
|
|
128
128
|
" memset(&t, 0, sizeof t);",
|
|
129
129
|
" t.length = 8 * tx_len;",
|
|
130
130
|
" t.rxlength = 8 * rx_len;",
|
|
131
131
|
" t.tx_buffer = tx;",
|
|
132
132
|
" t.rx_buffer = rx;",
|
|
133
|
-
` spi_device_polling_transmit(s_${name}_dev, &t);`,
|
|
133
|
+
` return spi_device_polling_transmit(s_${name}_dev, &t);`,
|
|
134
134
|
"}",
|
|
135
135
|
"",
|
|
136
136
|
"void hal_delay_ms(uint32_t ms) {",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"esp32.js","sourceRoot":"","sources":["../../src/codegen/esp32.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,kFAAkF;AAClF,sEAAsE;AACtE,iFAAiF;AACjF,gFAAgF;AAChF,4DAA4D;AAC5D,EAAE;AACF,+EAA+E;AAC/E,gFAAgF;AAChF,iFAAiF;AACjF,4EAA4E;AAC5E,yEAAyE;AACzE,8EAA8E;AAC9E,8EAA8E;AAC9E,6BAA6B;AAG7B,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAGjD,yEAAyE;AACzE,gEAAgE;AAChE,oEAAoE;AACpE,wEAAwE;AACxE,mEAAmE;AACnE,sEAAsE;AACtE,8EAA8E;AAC9E,6EAA6E;AAC7E,2EAA2E;AAC3E,oBAAoB;AACpB,SAAS,WAAW,CAAC,IAAY,EAAE,QAAyB;IAC1D,OAAO,aAAa,IAAI,IAAI,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;AAClE,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY,EAAE,QAAyB;IACvD,OAAO,GAAG,IAAI,cAAc,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;AACjE,CAAC;AAED,SAAS,UAAU,CAAC,IAAY,EAAE,MAAc,EAAE,QAAyB;IACzE,MAAM,OAAO,GAAG;QACd,IAAI;QACJ,MAAM,MAAM,0EAA0E;QACtF,IAAI;QACJ,4EAA4E;QAC5E,6EAA6E;QAC7E,4DAA4D,IAAI,eAAe;QAC/E,gFAAgF;QAChF,KAAK;QACL,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC;QAC3B,qBAAqB;QACrB,gCAAgC;QAChC,gCAAgC;QAChC,4BAA4B;QAC5B,EAAE;QACF,WAAW,MAAM,iBAAiB;QAClC,WAAW,MAAM,sBAAsB;QACvC,QAAQ;QACR,EAAE;QACF,oCAAoC,IAAI,OAAO;QAC/C,EAAE;QACF,yBAAyB,MAAM,mDAAmD;QAClF,6EAA6E;QAC7E,aAAa,IAAI,mEAAmE;QACpF,iCAAiC;QACjC,gDAAgD;QAChD,6BAA6B,MAAM,YAAY;QAC/C,uCAAuC;QACvC,QAAQ;QACR,sDAAsD,IAAI,QAAQ;QAClE,GAAG;QACH,EAAE;QACF,
|
|
1
|
+
{"version":3,"file":"esp32.js","sourceRoot":"","sources":["../../src/codegen/esp32.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,kFAAkF;AAClF,sEAAsE;AACtE,iFAAiF;AACjF,gFAAgF;AAChF,4DAA4D;AAC5D,EAAE;AACF,+EAA+E;AAC/E,gFAAgF;AAChF,iFAAiF;AACjF,4EAA4E;AAC5E,yEAAyE;AACzE,8EAA8E;AAC9E,8EAA8E;AAC9E,6BAA6B;AAG7B,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAGjD,yEAAyE;AACzE,gEAAgE;AAChE,oEAAoE;AACpE,wEAAwE;AACxE,mEAAmE;AACnE,sEAAsE;AACtE,8EAA8E;AAC9E,6EAA6E;AAC7E,2EAA2E;AAC3E,oBAAoB;AACpB,SAAS,WAAW,CAAC,IAAY,EAAE,QAAyB;IAC1D,OAAO,aAAa,IAAI,IAAI,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;AAClE,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY,EAAE,QAAyB;IACvD,OAAO,GAAG,IAAI,cAAc,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;AACjE,CAAC;AAED,SAAS,UAAU,CAAC,IAAY,EAAE,MAAc,EAAE,QAAyB;IACzE,MAAM,OAAO,GAAG;QACd,IAAI;QACJ,MAAM,MAAM,0EAA0E;QACtF,IAAI;QACJ,4EAA4E;QAC5E,6EAA6E;QAC7E,4DAA4D,IAAI,eAAe;QAC/E,gFAAgF;QAChF,KAAK;QACL,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC;QAC3B,qBAAqB;QACrB,gCAAgC;QAChC,gCAAgC;QAChC,4BAA4B;QAC5B,EAAE;QACF,WAAW,MAAM,iBAAiB;QAClC,WAAW,MAAM,sBAAsB;QACvC,QAAQ;QACR,EAAE;QACF,oCAAoC,IAAI,OAAO;QAC/C,EAAE;QACF,yBAAyB,MAAM,mDAAmD;QAClF,6EAA6E;QAC7E,aAAa,IAAI,mEAAmE;QACpF,iCAAiC;QACjC,gDAAgD;QAChD,6BAA6B,MAAM,YAAY;QAC/C,uCAAuC;QACvC,QAAQ;QACR,sDAAsD,IAAI,QAAQ;QAClE,GAAG;QACH,EAAE;QACF,6EAA6E;QAC7E,sBAAsB;QACtB,yEAAyE;QACzE,0CAA0C;QAC1C,sCAAsC;QACtC,OAAO;QACP,mBAAmB;QACnB,iCAAiC;QACjC,oCAAoC,IAAI,gCAAgC,MAAM,mBAAmB;QACjG,GAAG;QACH,EAAE;QACF,4EAA4E;QAC5E,iBAAiB;QACjB,4CAA4C,IAAI,6BAA6B,MAAM,mBAAmB;QACtG,GAAG;QACH,EAAE;QACF,kCAAkC;QAClC,oCAAoC;QACpC,GAAG;QACH,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACb,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;AACrD,CAAC;AAED,SAAS,UAAU,CAAC,IAAY,EAAE,MAAc,EAAE,QAAyB;IACzE,MAAM,OAAO,GAAG;QACd,IAAI;QACJ,MAAM,MAAM,0EAA0E;QACtF,IAAI;QACJ,4EAA4E;QAC5E,2EAA2E;QAC3E,oEAAoE;QACpE,iEAAiE;QACjE,MAAM,IAAI,mEAAmE;QAC7E,4BAA4B;QAC5B,KAAK;QACL,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC;QAC3B,qBAAqB;QACrB,gCAAgC;QAChC,gCAAgC;QAChC,4BAA4B;QAC5B,EAAE;QACF,gCAAgC,IAAI,OAAO;QAC3C,EAAE;QACF,2EAA2E;QAC3E,2EAA2E;QAC3E,4EAA4E;QAC5E,aAAa,IAAI,kEAAkE;QACnF,2CAA2C;QAC3C,yCAAyC;QACzC,kCAAkC;QAClC,qCAAqC;QACrC,oFAAoF;QACpF,0BAA0B;QAC1B,QAAQ;QACR,gDAAgD,IAAI,QAAQ;QAC5D,GAAG;QACH,EAAE;QACF,0FAA0F;QAC1F,0BAA0B;QAC1B,8BAA8B;QAC9B,4BAA4B;QAC5B,8BAA8B;QAC9B,uBAAuB;QACvB,uBAAuB;QACvB,4CAA4C,IAAI,YAAY;QAC5D,GAAG;QACH,EAAE;QACF,kCAAkC;QAClC,oCAAoC;QACpC,GAAG;QACH,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACb,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;AACrD,CAAC;AAED,SAAS,WAAW,CAAC,IAAY,EAAE,MAAc,EAAE,QAAyB;IAC1E,MAAM,OAAO,GAAG;QACd,IAAI;QACJ,MAAM,MAAM,oEAAoE;QAChF,IAAI;QACJ,4EAA4E;QAC5E,+EAA+E;QAC/E,6EAA6E;QAC7E,uCAAuC,IAAI,qCAAqC;QAChF,8DAA8D;QAC9D,kEAAkE;QAClE,KAAK;QACL,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC;QAC3B,0BAA0B;QAC1B,gCAAgC;QAChC,4BAA4B;QAC5B,EAAE;QACF,wBAAwB,IAAI,QAAQ;QACpC,EAAE;QACF,8EAA8E;QAC9E,gEAAgE;QAChE,QAAQ,IAAI,iCAAiC;QAC7C,SAAS,IAAI,eAAe;QAC5B,GAAG;QACH,EAAE;QACF,0DAA0D;QAC1D,0BAA0B,IAAI,kCAAkC;QAChE,GAAG;QACH,EAAE;QACF,4EAA4E;QAC5E,iCAAiC,IAAI,+CAA+C;QACpF,kBAAkB;QAClB,mBAAmB;QACnB,OAAO;QACP,yBAAyB;QACzB,GAAG;QACH,EAAE;QACF,kCAAkC;QAClC,oCAAoC;QACpC,GAAG;QACH,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACb,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;AACrD,CAAC;AAED,SAAS,UAAU,CAAC,IAAY,EAAE,MAAc,EAAE,QAAyB;IACzE,MAAM,OAAO,GAAG;QACd,IAAI;QACJ,MAAM,MAAM,oEAAoE;QAChF,IAAI;QACJ,4EAA4E;QAC5E,uEAAuE;QACvE,uEAAuE;QACvE,4EAA4E;QAC5E,yBAAyB,IAAI,6CAA6C;QAC1E,sDAAsD;QACtD,2EAA2E;QAC3E,IAAI;QACJ,MAAM,IAAI,oEAAoE;QAC9E,yEAAyE;QACzE,4EAA4E;QAC5E,0EAA0E;QAC1E,qDAAqD;QACrD,KAAK;QACL,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC;QAC3B,qBAAqB;QACrB,0BAA0B;QAC1B,gCAAgC;QAChC,4BAA4B;QAC5B,EAAE;QACF,qEAAqE;QACrE,2CAA2C;QAC3C,QAAQ,IAAI,qBAAqB;QACjC,GAAG;QACH,EAAE;QACF,2HAA2H;QAC3H,4BAA4B;QAC5B,wCAAwC;QACxC,6BAA6B;QAC7B,uCAAuC;QACvC,qCAAqC;QACrC,0CAA0C;QAC1C,OAAO;QACP,wEAAwE;QACxE,oBAAoB;QACpB,OAAO;QACP,yDAAyD;QACzD,mBAAmB;QACnB,OAAO;QACP,4BAA4B;QAC5B,uEAAuE;QACvE,oBAAoB;QACpB,OAAO;QACP,0CAA0C;QAC1C,wBAAwB;QACxB,sBAAsB;QACtB,OAAO;QACP,iCAAiC;QACjC,kBAAkB;QAClB,eAAe;QACf,GAAG;QACH,EAAE;QACF,kCAAkC;QAClC,oCAAoC;QACpC,GAAG;QACH,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACb,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;AACrD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CACjC,IAAmB,EACnB,OAAuC,EAAE;IAEzC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;IAC9B,IAAI,GAAG,KAAK,KAAK,IAAI,GAAG,KAAK,KAAK,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;QACtE,MAAM,IAAI,mBAAmB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAC9C,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,GAAG,CAAC;IACtC,MAAM,IAAI,GAAG,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;IAEjG,MAAM,GAAG,GACP,GAAG,KAAK,KAAK;QACX,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC;QACpC,CAAC,CAAC,GAAG,KAAK,MAAM;YACd,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC;YACrC,CAAC,CAAC,GAAG,KAAK,KAAK;gBACb,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC;gBACpC,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC7C,MAAM,cAAc,GAClB,GAAG,KAAK,KAAK;QACX,CAAC,CAAC,uGAAuG,IAAI,wKAAwK;QACrR,CAAC,CAAC,GAAG,KAAK,MAAM;YACd,CAAC,CAAC,uMAAuM,IAAI,iDAAiD;YAC9P,CAAC,CAAC,GAAG,KAAK,KAAK;gBACb,CAAC,CAAC,yPAAyP,IAAI,6CAA6C;gBAC5S,CAAC,CAAC,wGAAwG,IAAI,+DAA+D,MAAM,4BAA4B,CAAC;IAExN,OAAO;QACL,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC;QAC3B,aAAa,EAAE;YACb,GAAG,IAAI,CAAC,aAAa;YACrB,cAAc;SACf;KACF,CAAC;AACJ,CAAC"}
|
package/dist/codegen/ident.d.ts
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
export declare const HEX_ONLY: RegExp;
|
|
2
|
+
/**
|
|
3
|
+
* Returns `s` unchanged iff it is a well-formed hex literal (HEX_ONLY),
|
|
4
|
+
* otherwise `undefined`. Used at the codegen boundary (defense-in-depth,
|
|
5
|
+
* alongside the schema/validate.ts validator gate) to stop a non-hex,
|
|
6
|
+
* newline-embedded free-text value (e.g. a poisoned protocol.addresses[0] or
|
|
7
|
+
* command crc.poly/init) from ever being spliced verbatim into a generated
|
|
8
|
+
* `#define` line โ see the define-injection security fix.
|
|
9
|
+
*/
|
|
10
|
+
export declare function hexOrUndefined(s: string | undefined): string | undefined;
|
|
2
11
|
/** Lower-snake identifier safe for filenames/symbols; "device" when empty. */
|
|
3
12
|
export declare function slug(part: string): string;
|
|
4
13
|
/** UPPER token safe for a macro fragment. */
|
package/dist/codegen/ident.js
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
// Shared naming/geometry helpers so codegen and the driver lint agree on exactly
|
|
2
2
|
// how a part name and its fields become C identifiers and mask values.
|
|
3
3
|
export const HEX_ONLY = /^0x[0-9a-f]+$/i;
|
|
4
|
+
/**
|
|
5
|
+
* Returns `s` unchanged iff it is a well-formed hex literal (HEX_ONLY),
|
|
6
|
+
* otherwise `undefined`. Used at the codegen boundary (defense-in-depth,
|
|
7
|
+
* alongside the schema/validate.ts validator gate) to stop a non-hex,
|
|
8
|
+
* newline-embedded free-text value (e.g. a poisoned protocol.addresses[0] or
|
|
9
|
+
* command crc.poly/init) from ever being spliced verbatim into a generated
|
|
10
|
+
* `#define` line โ see the define-injection security fix.
|
|
11
|
+
*/
|
|
12
|
+
export function hexOrUndefined(s) {
|
|
13
|
+
return s !== undefined && HEX_ONLY.test(s) ? s : undefined;
|
|
14
|
+
}
|
|
4
15
|
/** Lower-snake identifier safe for filenames/symbols; "device" when empty. */
|
|
5
16
|
export function slug(part) {
|
|
6
17
|
const s = part
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ident.js","sourceRoot":"","sources":["../../src/codegen/ident.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,uEAAuE;AAEvE,MAAM,CAAC,MAAM,QAAQ,GAAG,gBAAgB,CAAC;AAEzC,8EAA8E;AAC9E,MAAM,UAAU,IAAI,CAAC,IAAY;IAC/B,MAAM,CAAC,GAAG,IAAI;SACX,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC3B,OAAO,CAAC,IAAI,QAAQ,CAAC;AACvB,CAAC;AAED,6CAA6C;AAC7C,MAAM,UAAU,KAAK,CAAC,CAAS;IAC7B,OAAO,CAAC;SACL,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AAC7B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,GAAW,EAAE,GAAW,EAAE,QAAQ,GAAG,CAAC;IAC9D,MAAM,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;IAC3B,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC;IACxC,OAAO,IAAI,GAAG,CAAC,IAAI,QAAQ,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,CAAS;IAC5B,OAAO,KAAK,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;AAC9D,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,OAAO,CAAC,CAAS,EAAE,QAAQ,GAAG,CAAC;IAC7C,OAAO,KAAK,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,QAAQ,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;AACzE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,CAAS;IACnC,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;AAC3D,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,CAAS;IAClC,OAAO,CAAC;SACL,KAAK,CAAC,GAAG,CAAC;SACV,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAC3D,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC"}
|
|
1
|
+
{"version":3,"file":"ident.js","sourceRoot":"","sources":["../../src/codegen/ident.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,uEAAuE;AAEvE,MAAM,CAAC,MAAM,QAAQ,GAAG,gBAAgB,CAAC;AAEzC;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,CAAqB;IAClD,OAAO,CAAC,KAAK,SAAS,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7D,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,IAAI,CAAC,IAAY;IAC/B,MAAM,CAAC,GAAG,IAAI;SACX,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC3B,OAAO,CAAC,IAAI,QAAQ,CAAC;AACvB,CAAC;AAED,6CAA6C;AAC7C,MAAM,UAAU,KAAK,CAAC,CAAS;IAC7B,OAAO,CAAC;SACL,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AAC7B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,GAAW,EAAE,GAAW,EAAE,QAAQ,GAAG,CAAC;IAC9D,MAAM,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;IAC3B,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC;IACxC,OAAO,IAAI,GAAG,CAAC,IAAI,QAAQ,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,CAAS;IAC5B,OAAO,KAAK,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;AAC9D,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,OAAO,CAAC,CAAS,EAAE,QAAQ,GAAG,CAAC;IAC7C,OAAO,KAAK,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,QAAQ,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;AACzE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,CAAS;IACnC,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;AAC3D,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,CAAS;IAClC,OAAO,CAAC;SACL,KAAK,CAAC,GAAG,CAAC;SACV,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAC3D,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC"}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
// becomes a method readRegister(reg, uint8_t &value) with no dev pointer to
|
|
18
18
|
// null-check.
|
|
19
19
|
import { registerWidth } from "../pdf/types.js";
|
|
20
|
-
import { commentSafe, macro, pascalCase, slug } from "./ident.js";
|
|
20
|
+
import { commentSafe, hexOrUndefined, macro, pascalCase, slug } from "./ident.js";
|
|
21
21
|
import { AUTOGEN, BUS_SEAM, COMMAND_INIT_TODO, I2C_COMMAND_FRAME_NOTE, bitFieldMacros, canFramingBody, commandBrief, commandReadDataTodo, commandSetTodo, crc8Body, makeFiles, registerBrief, registerConstants, registerInitTodo, registerMapTodo, registerMapTodoText, seamBusFor, uartFramingBody, } from "./portable.js";
|
|
22
22
|
const CPP_EXT = { header: "hpp", source: "cpp" };
|
|
23
23
|
/** extern "C" wrapper note โ explains why the seam stays linkable from a
|
|
@@ -34,21 +34,20 @@ function cppBusSeam(busKind, prefix) {
|
|
|
34
34
|
return {
|
|
35
35
|
member: [" uint8_t i2c_addr_;"],
|
|
36
36
|
initMember: [` i2c_addr_ = ${prefix}_I2C_ADDR;`],
|
|
37
|
-
readBody: [" hal_i2c_read(i2c_addr_, reg, &value, 1);"
|
|
38
|
-
writeBody: [" hal_i2c_write(i2c_addr_, reg, &value, 1);"
|
|
37
|
+
readBody: [" return hal_i2c_read(i2c_addr_, reg, &value, 1);"],
|
|
38
|
+
writeBody: [" return hal_i2c_write(i2c_addr_, reg, &value, 1);"],
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
41
|
if (busKind === "SPI") {
|
|
42
42
|
return {
|
|
43
43
|
member: [],
|
|
44
44
|
initMember: [],
|
|
45
|
-
readBody: [" hal_spi_transfer(®, 1, &value, 1);"
|
|
45
|
+
readBody: [" return hal_spi_transfer(®, 1, &value, 1);"],
|
|
46
46
|
writeBody: [
|
|
47
47
|
" uint8_t frame[2];",
|
|
48
48
|
" frame[0] = reg;",
|
|
49
49
|
" frame[1] = value;",
|
|
50
|
-
" hal_spi_transfer(frame, 2, nullptr, 0);",
|
|
51
|
-
" return 0;",
|
|
50
|
+
" return hal_spi_transfer(frame, 2, nullptr, 0);",
|
|
52
51
|
],
|
|
53
52
|
};
|
|
54
53
|
}
|
|
@@ -77,7 +76,7 @@ function registerDriverCpp(json, registers, name, prefix) {
|
|
|
77
76
|
const can = busKind === "CAN";
|
|
78
77
|
const seam = BUS_SEAM[busKind];
|
|
79
78
|
const cppSeam = cppBusSeam(busKind, prefix);
|
|
80
|
-
const addr = json.protocol.addresses?.[0];
|
|
79
|
+
const addr = hexOrUndefined(json.protocol.addresses?.[0]);
|
|
81
80
|
const guard = `${prefix}_HPP`;
|
|
82
81
|
const className = pascalCase(name);
|
|
83
82
|
const hpp = [
|
|
@@ -152,7 +151,7 @@ function commandDriverCpp(json, commands, name, prefix) {
|
|
|
152
151
|
const uart = json.protocol.bus === "UART";
|
|
153
152
|
const can = json.protocol.bus === "CAN";
|
|
154
153
|
const noAddrBus = uart || can;
|
|
155
|
-
const addr = json.protocol.addresses?.[0];
|
|
154
|
+
const addr = hexOrUndefined(json.protocol.addresses?.[0]);
|
|
156
155
|
const crc = commands.find((c) => c.crc)?.crc;
|
|
157
156
|
const guard = `${prefix}_HPP`;
|
|
158
157
|
const className = pascalCase(name);
|
|
@@ -197,7 +196,10 @@ function commandDriverCpp(json, commands, name, prefix) {
|
|
|
197
196
|
: line);
|
|
198
197
|
}
|
|
199
198
|
}
|
|
200
|
-
|
|
199
|
+
// See portable.ts commandDriver's identical comment: a non-hex crc.poly/init
|
|
200
|
+
// must never reach a #define as a live value (define-injection fix) โ only
|
|
201
|
+
// emit the block when both are well-formed hex literals.
|
|
202
|
+
if (crc && hexOrUndefined(crc.poly) && hexOrUndefined(crc.init)) {
|
|
201
203
|
hpp.push("", `/* CRC-${crc.width} checksum parameters. */`, `#define ${prefix}_CRC_POLY ${crc.poly}`, `#define ${prefix}_CRC_INIT ${crc.init}`);
|
|
202
204
|
}
|
|
203
205
|
hpp.push("", ...EXTERN_C_NOTE, 'extern "C" {', ...(uart
|
|
@@ -205,8 +207,9 @@ function commandDriverCpp(json, commands, name, prefix) {
|
|
|
205
207
|
: can
|
|
206
208
|
? BUS_SEAM.CAN.decl
|
|
207
209
|
: [
|
|
208
|
-
"
|
|
209
|
-
"
|
|
210
|
+
"/* Return 0 on success, non-zero on a bus error (e.g. NACK). */",
|
|
211
|
+
"int hal_i2c_write(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len);",
|
|
212
|
+
"int hal_i2c_read (uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len);",
|
|
210
213
|
]), "void hal_delay_ms (uint32_t ms);", "}", "", `class ${className} {`, "public:", " int init();", " int sendCommand(uint16_t command);", " int readData(uint8_t *buffer, uint16_t len);", ...(crc ? [" uint8_t crc8(const uint8_t *data, uint16_t len);"] : []));
|
|
211
214
|
if (!noAddrBus) {
|
|
212
215
|
hpp.push("", "private:", " uint8_t i2c_addr_;");
|
|
@@ -232,8 +235,7 @@ function commandDriverCpp(json, commands, name, prefix) {
|
|
|
232
235
|
" msb = (uint8_t)(command >> 8);",
|
|
233
236
|
" lsb = (uint8_t)(command & 0xFF);",
|
|
234
237
|
...I2C_COMMAND_FRAME_NOTE,
|
|
235
|
-
" hal_i2c_write(i2c_addr_, msb, &lsb, 1);",
|
|
236
|
-
" return 0;",
|
|
238
|
+
" return hal_i2c_write(i2c_addr_, msb, &lsb, 1);",
|
|
237
239
|
]),
|
|
238
240
|
"}",
|
|
239
241
|
"",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"portable-cpp.js","sourceRoot":"","sources":["../../src/codegen/portable-cpp.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,2EAA2E;AAC3E,+EAA+E;AAC/E,8EAA8E;AAC9E,8EAA8E;AAC9E,EAAE;AACF,gFAAgF;AAChF,gFAAgF;AAChF,+EAA+E;AAC/E,uEAAuE;AACvE,+EAA+E;AAC/E,gFAAgF;AAChF,EAAE;AACF,sEAAsE;AACtE,6EAA6E;AAC7E,2EAA2E;AAC3E,4EAA4E;AAC5E,cAAc;AAEd,OAAO,EAAE,aAAa,EAAiB,MAAM,iBAAiB,CAAC;AAE/D,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"portable-cpp.js","sourceRoot":"","sources":["../../src/codegen/portable-cpp.ts"],"names":[],"mappings":"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"}
|