@typecad/framework-zephyr 1.0.0-alpha.15 → 1.0.0-alpha.18

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.
Files changed (132) hide show
  1. package/LICENSE +202 -21
  2. package/README.md +49 -87
  3. package/dist/as-built.d.ts +2 -2
  4. package/dist/as-built.js +2 -2
  5. package/dist/boardgen.d.ts +1 -9
  6. package/dist/boardgen.js +228 -45
  7. package/dist/chips/types.d.ts +1 -1
  8. package/dist/debug-codegen.js +1 -1
  9. package/dist/display/touch-adapter.js +1 -1
  10. package/dist/display/ui-adapter.js +549 -549
  11. package/dist/doctor.js +4 -4
  12. package/dist/dt-config/custom-board.js +2 -2
  13. package/dist/dt-config/kconfig.js +18 -12
  14. package/dist/dt-config/overlay.d.ts +2 -2
  15. package/dist/dt-config/overlay.js +2 -2
  16. package/dist/framework.manifest.d.ts +3 -3
  17. package/dist/framework.manifest.js +10 -7
  18. package/dist/index.js +5 -5
  19. package/dist/licenses.d.ts +2 -2
  20. package/dist/licenses.js +8 -8
  21. package/dist/lowering/fs.js +1 -1
  22. package/dist/lowering/gpio.js +0 -32
  23. package/dist/lowering/http.js +264 -32
  24. package/dist/lowering/i2c.js +0 -8
  25. package/dist/lowering/interrupts.js +6 -0
  26. package/dist/lowering/mqtt.js +110 -8
  27. package/dist/lowering/usb.js +11 -11
  28. package/dist/lowering/wdt.js +2 -29
  29. package/dist/sdk/board-catalog-sync.d.ts +1 -3
  30. package/dist/sdk/board-catalog-sync.js +4 -10
  31. package/dist/strategy.d.ts +22 -44
  32. package/dist/strategy.js +152 -155
  33. package/dist/tmp-probe.d.ts +2 -0
  34. package/dist/tmp-probe.js +9 -0
  35. package/dist/toolchain/debug-config.d.ts +50 -90
  36. package/dist/toolchain/debug-config.js +241 -502
  37. package/dist/toolchain/env-check.d.ts +1 -3
  38. package/dist/toolchain/env-check.js +2 -7
  39. package/dist/toolchain/index.d.ts +65 -2
  40. package/dist/toolchain/index.js +432 -55
  41. package/dist/toolchain/runners.d.ts +16 -0
  42. package/dist/toolchain/runners.js +75 -0
  43. package/dist/toolchain/scaffold.d.ts +1 -1
  44. package/dist/toolchain/scaffold.js +12 -12
  45. package/dist/toolchain/west-discover.d.ts +6 -0
  46. package/dist/toolchain/west-discover.js +36 -13
  47. package/dist/toolchain/west-spawn.js +8 -2
  48. package/installer/README.md +328 -328
  49. package/installer/install.sh +2 -2
  50. package/installer/templates/project/.typecad/activate-zephyr.ps1 +1 -1
  51. package/installer/templates/project/.typecad/activate-zephyr.sh +1 -1
  52. package/installer/templates/project/.vscode/settings.json +1 -1
  53. package/installer/templates/project/README.md +2 -2
  54. package/package.json +5 -5
  55. package/src/as-built.ts +206 -206
  56. package/src/boardgen.ts +214 -48
  57. package/src/chips/types.ts +567 -567
  58. package/src/display/touch-adapter.ts +204 -204
  59. package/src/display/ui-adapter.ts +781 -781
  60. package/src/doctor.ts +4 -4
  61. package/src/dt-config/custom-board.ts +2 -2
  62. package/src/dt-config/kconfig.ts +18 -12
  63. package/src/dt-config/overlay.ts +1058 -1058
  64. package/src/framework.manifest.ts +538 -535
  65. package/src/index.ts +5 -5
  66. package/src/licenses.ts +425 -425
  67. package/src/lowering/fs.ts +135 -135
  68. package/src/lowering/gpio.ts +0 -33
  69. package/src/lowering/http.ts +264 -32
  70. package/src/lowering/i2c.ts +0 -9
  71. package/src/lowering/interrupts.ts +6 -0
  72. package/src/lowering/mqtt.ts +109 -8
  73. package/src/lowering/usb.ts +221 -221
  74. package/src/lowering/wdt.ts +2 -25
  75. package/src/sdk/board-catalog-sync.ts +4 -25
  76. package/src/strategy.ts +2265 -2309
  77. package/src/toolchain/debug-config.ts +264 -514
  78. package/src/toolchain/env-check.ts +279 -285
  79. package/src/toolchain/index.ts +1703 -1286
  80. package/src/toolchain/runners.ts +80 -0
  81. package/src/toolchain/scaffold.ts +296 -296
  82. package/src/toolchain/west-discover.ts +35 -13
  83. package/src/toolchain/west-spawn.ts +174 -168
  84. package/dist/async/timer-polyfill.d.ts +0 -10
  85. package/dist/async/timer-polyfill.js +0 -95
  86. package/dist/chips/board-overrides.d.ts +0 -7
  87. package/dist/chips/board-overrides.js +0 -11
  88. package/dist/chips/esp32.d.ts +0 -2
  89. package/dist/chips/esp32.js +0 -71
  90. package/dist/chips/esp32s3.d.ts +0 -2
  91. package/dist/chips/esp32s3.js +0 -103
  92. package/dist/chips/soc/.d.ts +0 -2
  93. package/dist/chips/soc/.js +0 -129
  94. package/dist/chips/soc/esp32.d.ts +0 -2
  95. package/dist/chips/soc/esp32.js +0 -120
  96. package/dist/chips/soc/esp32c3.d.ts +0 -2
  97. package/dist/chips/soc/esp32c3.js +0 -90
  98. package/dist/chips/soc/esp32c6.d.ts +0 -2
  99. package/dist/chips/soc/esp32c6.js +0 -109
  100. package/dist/chips/soc/esp32s3.d.ts +0 -2
  101. package/dist/chips/soc/esp32s3.js +0 -189
  102. package/dist/chips/soc/index.d.ts +0 -2
  103. package/dist/chips/soc/index.js +0 -23
  104. package/dist/chips/soc/nrf52840.d.ts +0 -2
  105. package/dist/chips/soc/nrf52840.js +0 -130
  106. package/dist/chips/soc/rp2040.d.ts +0 -2
  107. package/dist/chips/soc/rp2040.js +0 -141
  108. package/dist/chips/soc/rp2350a.d.ts +0 -2
  109. package/dist/chips/soc/rp2350a.js +0 -145
  110. package/dist/chips/soc/samd21g18a.d.ts +0 -2
  111. package/dist/chips/soc/samd21g18a.js +0 -143
  112. package/dist/chips/soc/stm32f411xe.d.ts +0 -2
  113. package/dist/chips/soc/stm32f411xe.js +0 -251
  114. package/dist/chips/xiao-ble.d.ts +0 -2
  115. package/dist/chips/xiao-ble.js +0 -100
  116. package/dist/lowering/power.d.ts +0 -9
  117. package/dist/lowering/power.js +0 -60
  118. package/dist/lowering/pulse.d.ts +0 -7
  119. package/dist/lowering/pulse.js +0 -51
  120. package/dist/lowering/tone.d.ts +0 -10
  121. package/dist/lowering/tone.js +0 -63
  122. package/dist/lowering/worker-backing.d.ts +0 -14
  123. package/dist/lowering/worker-backing.js +0 -79
  124. package/dist/lowering/worker.d.ts +0 -6
  125. package/dist/lowering/worker.js +0 -14
  126. package/dist/sdk/board-data.generated.d.ts +0 -2
  127. package/dist/sdk/board-data.generated.js +0 -4
  128. package/dist/sdk/catalog-walker.d.ts +0 -90
  129. package/dist/sdk/catalog-walker.js +0 -682
  130. package/dist/sdk/dts-reader.d.ts +0 -83
  131. package/dist/sdk/dts-reader.js +0 -596
  132. package/src/debug-codegen.ts +0 -207
@@ -13,7 +13,11 @@
13
13
  // shim getaddrinfo-resolves the broker host itself (like the HTTP shim).
14
14
  // URI scheme: mqtt:// → 1883 plain TCP, mqtts:// → 8883 TLS
15
15
  // (MQTT_TRANSPORT_SECURE + mqtt_sec_config, reusing the same mbedTLS matrix
16
- // the HTTP TLS path established).
16
+ // the HTTP TLS path established). caCert pins the broker's CA — the PEM is
17
+ // DER-decoded at emit time and registered via tls_credential_add as a
18
+ // CA_CERTIFICATE sec tag with TLS_PEER_VERIFY_REQUIRED (verified TLS, the
19
+ // MQTT analogue of Request's caCert); mqtts:// without a CA stays
20
+ // encrypted-but-unverified (TLS_PEER_VERIFY_NONE).
17
21
  //
18
22
  // One client slot (HAL singleton). on_message callbacks are dispatched on the
19
23
  // poll thread.
@@ -45,6 +49,8 @@ export function mqttInitLines() {
45
49
  `// at connect time; host drives both DNS resolution and the TLS SNI/hostname.`,
46
50
  `// on_message is the user callback (set via mqtt.on_message); it fires on the`,
47
51
  `// poll thread for every incoming PUBLISH on a subscribed topic.`,
52
+ `// ca_der is the pinned CA (DER, user-owned from the caCert fact); nullptr`,
53
+ `// means mqtts:// runs encrypted-but-unverified.`,
48
54
  `typedef void (*__tc_mqtt_msg_cb_t)(const char* topic, const char* payload);`,
49
55
  `static struct {`,
50
56
  ` struct mqtt_client client;`,
@@ -55,6 +61,16 @@ export function mqttInitLines() {
55
61
  ` uint16_t port; // 1883 / 8883 unless overridden in the URI`,
56
62
  ` char client_id[64];`,
57
63
  ` bool tls; // scheme == "mqtts"`,
64
+ ` const uint8_t* ca_der; // pinned CA (DER), nullptr = no CA`,
65
+ ` size_t ca_der_len;`,
66
+ ` // What this shim last registered under __TC_MQTT_SEC_TAG (DER arrays`,
67
+ ` // are function-static, so pointer identity is stable). Zephyr's`,
68
+ ` // credential store never REPLACES a tag — repeats are skipped, a`,
69
+ ` // different CA at an occupied tag is reported, not silent.`,
70
+ ` const uint8_t* ca_added;`,
71
+ ` size_t ca_added_len;`,
72
+ ` bool ca_added_set;`,
73
+ ` sec_tag_t sec_tags[1]; // backs tls.config.sec_tag_list (static lifetime)`,
58
74
  ` volatile bool connected;`,
59
75
  ` volatile bool stop_poll; // set by disconnect to terminate the poll thread`,
60
76
  ` __tc_mqtt_msg_cb_t on_message;`,
@@ -196,6 +212,35 @@ export function mqttInitLines() {
196
212
  ` return host_len > 0U;`,
197
213
  `}`,
198
214
  ``,
215
+ `// Strict IPv4 dotted-quad predicate: exactly four 0-255 groups. A`,
216
+ `// digit-and-dot scan would also swallow numeric-only DNS names ("123"),`,
217
+ `// silently skipping the TLS hostname check for them (same helper as the`,
218
+ `// HTTP shim).`,
219
+ `static bool __tc_mqtt_host_is_ipv4(const char* h) {`,
220
+ ` uint32_t quads = 0U;`,
221
+ ` uint32_t val = 0U;`,
222
+ ` uint32_t digits = 0U;`,
223
+ ` for (const char* p = h; ; p++) {`,
224
+ ` if (*p >= '0' && *p <= '9') {`,
225
+ ` val = (val * 10U) + static_cast<uint32_t>(*p - '0');`,
226
+ ` digits++;`,
227
+ ` if (digits > 3U || val > 255U) return false;`,
228
+ ` } else if (*p == '.') {`,
229
+ ` if (digits == 0U || quads >= 3U) return false;`,
230
+ ` quads++;`,
231
+ ` val = 0U;`,
232
+ ` digits = 0U;`,
233
+ ` } else if (*p == '\\0') {`,
234
+ ` if (digits == 0U) return false;`,
235
+ ` quads++;`,
236
+ ` break;`,
237
+ ` } else {`,
238
+ ` return false;`,
239
+ ` }`,
240
+ ` }`,
241
+ ` return quads == 4U;`,
242
+ `}`,
243
+ ``,
199
244
  `// ── connect ─────────────────────────────────────────────────────────────`,
200
245
  `// Parse URI → resolve broker → init client → mqtt_connect → spawn poll thread.`,
201
246
  `// Blocks until CONNACK (the poll thread isn't running yet, so we drive a few`,
@@ -244,14 +289,47 @@ export function mqttInitLines() {
244
289
  ` __tc_mqtt.client.transport.type = MQTT_TRANSPORT_SECURE;`,
245
290
  ` struct mqtt_sec_config* tls_cfg = &__tc_mqtt.client.transport.tls.config;`,
246
291
  ` (void)memset(tls_cfg, 0, sizeof(*tls_cfg));`,
247
- ` // The HAL MQTT surface has no CA-pinning op (unlike HTTP's caCert), so`,
248
- ` // there is no way to register a trusted CA here. Verify-NONE keeps the`,
249
- ` // TLS session encrypted but skips identity verification — the strongest`,
250
- ` // the current surface can express. A future mqtt.set_ca_cert op would`,
251
- ` // flip this to REQUIRED + a registered sec_tag (like the HTTPS path).`,
252
- ` tls_cfg->peer_verify = TLS_PEER_VERIFY_NONE;`,
292
+ ` if (__tc_mqtt.ca_der != nullptr) {`,
293
+ ` // Pinned CA (the caCert construction fact): register it as a`,
294
+ ` // CA_CERTIFICATE sec tag and REQUIRE peer verification — the MQTT`,
295
+ ` // analogue of the HTTPS caCert path. Zephyr's credential store`,
296
+ ` // never REPLACES a tag+type pair: re-registering the same DER`,
297
+ ` // (pointer identity — the arrays are function-static) is skipped`,
298
+ ` // silently; a DIFFERENT CA hitting an occupied tag is reported so`,
299
+ ` // a wrong-CA verify is never silent; any other failure keeps the`,
300
+ ` // tag list empty and verification required — fail closed.`,
301
+ ` if (!__tc_mqtt.ca_added_set || __tc_mqtt.ca_added != __tc_mqtt.ca_der`,
302
+ ` || __tc_mqtt.ca_added_len != __tc_mqtt.ca_der_len) {`,
303
+ ` int cred_rc = tls_credential_add(__TC_MQTT_SEC_TAG,`,
304
+ ` TLS_CREDENTIAL_CA_CERTIFICATE,`,
305
+ ` __tc_mqtt.ca_der, __tc_mqtt.ca_der_len);`,
306
+ ` __tc_mqtt.ca_added = __tc_mqtt.ca_der;`,
307
+ ` __tc_mqtt.ca_added_len = __tc_mqtt.ca_der_len;`,
308
+ ` __tc_mqtt.ca_added_set = true;`,
309
+ ` if (cred_rc == -17 /* -EEXIST */) {`,
310
+ ` printk("tc-mqtt: sec tag %d already holds a CA; the first one stays active (rc=%d)\\n", __TC_MQTT_SEC_TAG, cred_rc);`,
311
+ ` } else if (cred_rc != 0) {`,
312
+ ` printk("tc-mqtt: CA registration failed (rc=%d) - verifying against no credentials\\n", cred_rc);`,
313
+ ` }`,
314
+ ` }`,
315
+ ` if (__tc_mqtt.ca_added_set) {`,
316
+ ` __tc_mqtt.sec_tags[0] = __TC_MQTT_SEC_TAG;`,
317
+ ` tls_cfg->sec_tag_list = __tc_mqtt.sec_tags;`,
318
+ ` tls_cfg->sec_tag_count = 1U;`,
319
+ ` }`,
320
+ ` tls_cfg->peer_verify = TLS_PEER_VERIFY_REQUIRED;`,
321
+ ` } else {`,
322
+ ` // No CA pinned: the session is encrypted but the broker's identity`,
323
+ ` // is not verified — the strongest the no-caCert form can express.`,
324
+ ` tls_cfg->peer_verify = TLS_PEER_VERIFY_NONE;`,
325
+ ` }`,
253
326
  ` tls_cfg->cipher_list = nullptr;`,
254
- ` tls_cfg->hostname = __tc_mqtt.host;`,
327
+ ` // mbedtls does not match IP literals against SAN entries — set the`,
328
+ ` // hostname (SNI + identity check) only for name hosts; IP brokers`,
329
+ ` // verify chain-only (same policy as the HTTPS path).`,
330
+ ` if (!__tc_mqtt_host_is_ipv4(__tc_mqtt.host)) {`,
331
+ ` tls_cfg->hostname = __tc_mqtt.host;`,
332
+ ` }`,
255
333
  `#else`,
256
334
  ` printk("tc-mqtt: mqtts:// requested but CONFIG_MQTT_LIB_TLS is off\\n");`,
257
335
  ` return;`,
@@ -303,6 +381,10 @@ export function mqttInitLines() {
303
381
  ` __tc_mqtt.on_message = fn;`,
304
382
  `}`,
305
383
  ``,
384
+ `// ca_cert is the DER-decoded PEM from the caCert construction fact`,
385
+ `// (user-owned static array; nullptr = no pinned CA).`,
386
+ `static inline void __tc_mqtt_set_ca_cert_der(const uint8_t* der, size_t len) { __tc_mqtt.ca_der = der; __tc_mqtt.ca_der_len = len; }`,
387
+ ``,
306
388
  `static inline void __tc_mqtt_subscribe(const char* topic) {`,
307
389
  ` static struct mqtt_topic topics[4];`,
308
390
  ` static uint16_t msg_id = 1;`,
@@ -356,6 +438,26 @@ export function lowerMqtt(op) {
356
438
  switch (op.operation) {
357
439
  case 'mqtt.connect':
358
440
  return { code: `__tc_mqtt_connect(${s(o.brokerUri)}, ${s(o.clientId)});` };
441
+ case 'mqtt.set_ca_cert': {
442
+ // PEM → DER at emit time (this tree's tf-psa-crypto mbedTLS has no PEM
443
+ // parser — same decode as http.set_ca_cert; tls_credential_add takes
444
+ // the DER directly).
445
+ const pem = String(o.pem ?? '').replace(/^"|"$/g, '').replace(/\\n/g, '\n');
446
+ if (pem.replace(/\s+/g, '') === '') {
447
+ // No-CA sentinel (Mqtt always emits the op from connect(); opts.caCert
448
+ // defaults to '') — elide silently so plain-mqtt:// carries no comment.
449
+ return { code: '' };
450
+ }
451
+ const b64 = pem.replace(/-----[A-Z ]+-----/g, '').replace(/\s+/g, '');
452
+ const der = Buffer.from(b64, 'base64');
453
+ // Every X.509 DER starts with the ASN.1 SEQUENCE tag (0x30); a long
454
+ // but non-cert payload fails here instead of at a confusing handshake
455
+ // error on the target (same check as http.set_ca_cert).
456
+ if (der.length < 100 || der[0] !== 0x30)
457
+ return { code: `// tc-mqtt: caCert PEM failed to decode` };
458
+ const hex = [...der].map((b) => `0x${b.toString(16).padStart(2, '0')}`).join(', ');
459
+ return { code: `{ static const uint8_t __tc_mqtt_ca_der[] = { ${hex} }; __tc_mqtt_set_ca_cert_der(__tc_mqtt_ca_der, sizeof(__tc_mqtt_ca_der)); }` };
460
+ }
359
461
  case 'mqtt.on_message':
360
462
  return { code: `__tc_mqtt_set_on_message(${s(o.handler)});` };
361
463
  case 'mqtt.subscribe':
@@ -87,13 +87,13 @@ export function usbdDeviceLines(chip) {
87
87
  ` ${vid}, ${pid});`,
88
88
  'USBD_DESC_LANG_DEFINE(__tc_usbd_lang);',
89
89
  'USBD_DESC_MANUFACTURER_DEFINE(__tc_usbd_mfr, "typecad");',
90
- 'USBD_DESC_PRODUCT_DEFINE(__tc_usbd_product, "cuttlefish app");',
90
+ 'USBD_DESC_PRODUCT_DEFINE(__tc_usbd_product, "typecad-hal app");',
91
91
  // Serial number from hwinfo: Windows keys USB devnodes without a serial
92
92
  // on the physical port, so flash-cycle re-enumerations reuse stale
93
93
  // port-keyed nodes (the "access denied" open wedge). Identity-based
94
94
  // instance paths are stable across ports and never hit that pool.
95
95
  'USBD_DESC_SERIAL_NUMBER_DEFINE(__tc_usbd_sn);',
96
- 'USBD_DESC_CONFIG_DEFINE(__tc_usbd_cfg_desc, "cuttlefish");',
96
+ 'USBD_DESC_CONFIG_DEFINE(__tc_usbd_cfg_desc, "typecad-hal");',
97
97
  'USBD_CONFIGURATION_DEFINE(__tc_usbd_cfg, 0, 250, &__tc_usbd_cfg_desc);',
98
98
  'static bool __tc_usbd_started = false;',
99
99
  ...touchLines,
@@ -101,17 +101,17 @@ export function usbdDeviceLines(chip) {
101
101
  ' if (__tc_usbd_started) { return; }',
102
102
  ' __tc_usbd_started = true;',
103
103
  ' int err = usbd_add_descriptor(&__tc_usbd, &__tc_usbd_lang);',
104
- ' if (err != 0) { printk("cuttlefish usb: lang descriptor failed: %d\\n", err); return; }',
104
+ ' if (err != 0) { printk("typecad-hal usb: lang descriptor failed: %d\\n", err); return; }',
105
105
  ' err = usbd_add_descriptor(&__tc_usbd, &__tc_usbd_sn);',
106
- ' if (err != 0) { printk("cuttlefish usb: serial descriptor failed: %d\\n", err); return; }',
106
+ ' if (err != 0) { printk("typecad-hal usb: serial descriptor failed: %d\\n", err); return; }',
107
107
  ' err = usbd_add_descriptor(&__tc_usbd, &__tc_usbd_mfr);',
108
- ' if (err != 0) { printk("cuttlefish usb: manufacturer descriptor failed: %d\\n", err); return; }',
108
+ ' if (err != 0) { printk("typecad-hal usb: manufacturer descriptor failed: %d\\n", err); return; }',
109
109
  ' err = usbd_add_descriptor(&__tc_usbd, &__tc_usbd_product);',
110
- ' if (err != 0) { printk("cuttlefish usb: product descriptor failed: %d\\n", err); return; }',
110
+ ' if (err != 0) { printk("typecad-hal usb: product descriptor failed: %d\\n", err); return; }',
111
111
  ' err = usbd_add_configuration(&__tc_usbd, USBD_SPEED_FS, &__tc_usbd_cfg);',
112
- ' if (err != 0) { printk("cuttlefish usb: add configuration failed: %d\\n", err); return; }',
112
+ ' if (err != 0) { printk("typecad-hal usb: add configuration failed: %d\\n", err); return; }',
113
113
  ' err = usbd_register_all_classes(&__tc_usbd, USBD_SPEED_FS, 1, NULL);',
114
- ' if (err != 0) { printk("cuttlefish usb: register classes failed: %d\\n", err); return; }',
114
+ ' if (err != 0) { printk("typecad-hal usb: register classes failed: %d\\n", err); return; }',
115
115
  // Registered before usbd_init so no line-coding event can be missed.
116
116
  ...touchRegister,
117
117
  // usbd_init builds the descriptor tables from the registered
@@ -119,14 +119,14 @@ export function usbdDeviceLines(chip) {
119
119
  // refuses with -EPERM ("not initialized") without it (sample_usbd_init.c
120
120
  // calls it between setup and enable).
121
121
  ' err = usbd_init(&__tc_usbd);',
122
- ' if (err != 0) { printk("cuttlefish usb: init failed: %d\\n", err); return; }',
122
+ ' if (err != 0) { printk("typecad-hal usb: init failed: %d\\n", err); return; }',
123
123
  // Boards with VBUS detection start on the VBUS event in the Zephyr
124
124
  // sample, via a message callback we do not register; enabling
125
125
  // unconditionally (and reporting the error) is the sample's own path
126
126
  // for boards without detection (STM32 OTG_FS).
127
127
  ' err = usbd_enable(&__tc_usbd);',
128
- ' if (err != 0) { printk("cuttlefish usb: enable failed: %d\\n", err); return; }',
129
- ' printk("cuttlefish usb: device enabled\\n");',
128
+ ' if (err != 0) { printk("typecad-hal usb: enable failed: %d\\n", err); return; }',
129
+ ' printk("typecad-hal usb: device enabled\\n");',
130
130
  '}',
131
131
  '// CUTTLEFISH_USBD_END',
132
132
  ];
@@ -6,36 +6,9 @@
6
6
  // wdt_install_timeout in a static var so wdt.reset can feed it.
7
7
  //
8
8
  // enable(timeout): wdt_install_timeout + wdt_setup. Zephyr expects the timeout
9
- // in milliseconds (wdt_window.max). The HAL passes a "250ms" string or WDTO_*
10
- // constant or a number; we parse to ms in the lowering.
9
+ // in milliseconds (wdt_window.max); the thin Watchdog (hal/watchdog.ts)
10
+ // construction already carries a plain timeoutMs number.
11
11
  // ---------------------------------------------------------------------------
12
- /** Parse a HAL wdt timeout ("250ms", WDTO_2S, or a bare number) to ms.
13
- * Tolerates undefined (the manifest validator's probe sends a minimal op)
14
- * and quote-wrapped strings (resolveSemanticArg can hand the literal's
15
- * quoted source text through). */
16
- function timeoutToMs(timeout) {
17
- if (typeof timeout === 'number')
18
- return timeout;
19
- if (!timeout)
20
- return 1000; // default 1s when absent (e.g. the validator probe)
21
- timeout = timeout.replace(/^['"]|['"]$/g, '');
22
- // Arduino WDTO_* constants.
23
- const wdto = {
24
- WDTO_15MS: 15, WDTO_30MS: 30, WDTO_60MS: 60, WDTO_120MS: 120,
25
- WDTO_250MS: 250, WDTO_500MS: 500, WDTO_1S: 1000, WDTO_2S: 2000,
26
- WDTO_4S: 4000, WDTO_8S: 8000,
27
- };
28
- if (wdto[timeout])
29
- return wdto[timeout];
30
- const m = timeout.match(/^(\d+)\s*ms$/i);
31
- if (m)
32
- return parseInt(m[1], 10);
33
- const s = timeout.match(/^(\d+)\s*s$/i);
34
- if (s)
35
- return parseInt(s[1], 10) * 1000;
36
- const n = parseInt(timeout, 10);
37
- return isNaN(n) ? 1000 : n;
38
- }
39
12
  /**
40
13
  * Emit the WDT device + channel state. Called from shimLines when the program
41
14
  * uses the watchdog.
@@ -2,7 +2,7 @@ import * as catalog from '@typecad/cuttlefish/board-catalog';
2
2
  export type BoardCatalogSyncReport = catalog.BoardCatalogSyncReport;
3
3
  export type BoardCatalogEnsureResult = catalog.BoardCatalogEnsureResult;
4
4
  export type BoardCatalogOverlay = catalog.BoardCatalogOverlay;
5
- export declare const GENERATOR_REV: number, isZephyrBase: typeof catalog.isZephyrBase, locateZephyrBaseCheap: typeof catalog.locateZephyrBaseCheap, overlayPathFor: typeof catalog.overlayPathFor, readBoardCatalogOverlayFile: typeof catalog.readBoardCatalogOverlayFile, loadBoardCatalogOverlay: typeof catalog.loadBoardCatalogOverlay, resetBoardCatalogOverlayCache: typeof catalog.resetBoardCatalogOverlayCache, isOverlayStale: typeof catalog.isOverlayStale, diffBoardCatalogs: typeof catalog.diffBoardCatalogs, boardRecordFingerprint: typeof catalog.boardRecordFingerprint, findBoardInCatalog: typeof catalog.findBoardInCatalog, activeBoardCatalog: typeof catalog.activeBoardCatalog, resetActiveBoardCatalog: typeof catalog.resetActiveBoardCatalog;
5
+ export declare const loadBoardCatalogOverlay: typeof catalog.loadBoardCatalogOverlay, resetBoardCatalogOverlayCache: typeof catalog.resetBoardCatalogOverlayCache;
6
6
  /** Sync with the full west discovery cascade behind it (the CLI's path):
7
7
  * falls back through spawn-based discovery when the cheap fs probes find
8
8
  * nothing. */
@@ -12,5 +12,3 @@ export declare function syncBoardCatalog(opts?: {
12
12
  /** The build-path pre-step: refresh a stale overlay before a regen
13
13
  * (fs-only discovery — no spawns during builds). */
14
14
  export declare function ensureFreshBoardCatalog(): catalog.BoardCatalogEnsureResult;
15
- /** Locate a Zephyr tree by any means (spawn cascade included). */
16
- export declare function locateZephyrBaseFull(): string | undefined;
@@ -5,13 +5,14 @@
5
5
  // @typecad/cuttlefish/board-catalog — the create flow needs it before any
6
6
  // framework is installed. This module adds the one thing the framework owns
7
7
  // — the full spawn-based west discovery cascade for an explicit
8
- // `cuttlefish board sync` — and re-exports the store for the strategy's
9
- // import surface.
8
+ // `typecad-hal board sync`. Consumers pull the rest of the store's surface
9
+ // from @typecad/cuttlefish/board-catalog directly.
10
10
  // ----------------------------------------------------------------------------
11
11
  import path from 'node:path';
12
12
  import * as catalog from '@typecad/cuttlefish/board-catalog';
13
13
  import { discoverWest } from '../toolchain/west-discover.js';
14
- export const { GENERATOR_REV, isZephyrBase, locateZephyrBaseCheap, overlayPathFor, readBoardCatalogOverlayFile, loadBoardCatalogOverlay, resetBoardCatalogOverlayCache, isOverlayStale, diffBoardCatalogs, boardRecordFingerprint, findBoardInCatalog, activeBoardCatalog, resetActiveBoardCatalog, } = catalog;
14
+ // Re-exported for the package index's board-sync surface.
15
+ export const { loadBoardCatalogOverlay, resetBoardCatalogOverlayCache } = catalog;
15
16
  /** Sync with the full west discovery cascade behind it (the CLI's path):
16
17
  * falls back through spawn-based discovery when the cheap fs probes find
17
18
  * nothing. */
@@ -32,10 +33,3 @@ export function syncBoardCatalog(opts = {}) {
32
33
  export function ensureFreshBoardCatalog() {
33
34
  return catalog.ensureFreshBoardCatalog();
34
35
  }
35
- /** Locate a Zephyr tree by any means (spawn cascade included). */
36
- export function locateZephyrBaseFull() {
37
- const install = discoverWest();
38
- return install?.zephyrBase && catalog.isZephyrBase(install.zephyrBase)
39
- ? path.resolve(install.zephyrBase)
40
- : undefined;
41
- }
@@ -88,15 +88,6 @@ export declare class ZephyrStrategy implements PlatformStrategy {
88
88
  boardJson: string;
89
89
  };
90
90
  private resolveChip;
91
- /**
92
- * Resolve the debug mode for the active target from the platform context.
93
- * Mirrors resolveChip's target extraction so shimLines/forcedIncludes can
94
- * gate the printf halt shim + console UART include to printf builds only
95
- * (gdb builds use VS Code native breakpoints + #line markers, so the
96
- * __tc_debug_wait_for_continue shim and its <zephyr/drivers/uart.h> include
97
- * are dead code there).
98
- */
99
- private resolveDebugMode;
100
91
  forcedIncludes(_program?: ProgramIR, ctx?: PlatformContext): string[];
101
92
  symbolAliases(): Record<string, string>;
102
93
  /**
@@ -110,15 +101,27 @@ export declare class ZephyrStrategy implements PlatformStrategy {
110
101
  */
111
102
  private programUsesAsyncRuntime;
112
103
  /** Pins referenced by gpio.* hal-ops in the program IR. lowerGpio routes a
113
- * pin to its devicetree spec by pin NUMBER, so the structured hal-op pins
114
- * are the authoritative signal for which __tc_dt_* specs are needed —
115
- * regardless of when the final call text is rendered. */
104
+ * pin to its devicetree spec by pin NUMBER, so the structured hal-op pins
105
+ * are the authoritative signal for which __tc_dt_* specs are needed —
106
+ * regardless of when the final call text is rendered.
107
+ *
108
+ * A gpio op interpolated into another HAL call's template literal
109
+ * (`USB0.writeLine(\`led: ${led.get()}\`)`) never becomes an IR node —
110
+ * resolveHALExprToText lowers it to C++ text while building the IR and bakes
111
+ * it into an __EMIT__ snprintf prelude, so the walk cannot see its pin. The
112
+ * spec NAME it references is still in that text; collectRawMatches finds it
113
+ * there, or the spec goes undeclared and the build fails on `__tc_dt_led0
114
+ * was not declared in this scope`. */
116
115
  private collectGpioPinUsage;
117
116
  /** Run `re` (global) against every raw string in the IR — raw expression
118
- * values plus raw hal-op codes — returning capture group 1 of each match
119
- * (the full match when the regex has no group). This is how references the
120
- * text scanners must see but that never appear as IR call nodes (e.g. a
121
- * rawCpp() escape hatch naming `__tc_dt_sw0` directly) are discovered. */
117
+ * values plus raw hal-op codes — returning capture group 1 of each match
118
+ * (the full match when the regex has no group). This is how references the
119
+ * text scanners must see but that never appear as IR call nodes are
120
+ * discovered: a rawCpp() escape hatch naming `__tc_dt_sw0` directly, and —
121
+ * the reason every string LEAF is scanned, not just raw nodes — the
122
+ * pre-lowered C++ text of a HAL call inlined into another HAL call's
123
+ * template literal, which the IR builder bakes into plain `string` payloads
124
+ * (__EMIT__ snprintf preludes, op data fields) rather than raw nodes. */
122
125
  private collectRawMatches;
123
126
  /** Whether the wiring-compat GPIO read surface (__tc_gpio_read definition,
124
127
  * __tc_gpio_dev dispatcher, and the wiring_compat polyfill's digitalRead /
@@ -210,14 +213,14 @@ export declare class ZephyrStrategy implements PlatformStrategy {
210
213
  } | undefined;
211
214
  /**
212
215
  * Regenerate the board catalog overlay from the user's own Zephyr tree —
213
- * `cuttlefish board sync`. After a `west update`, this is how new/changed/
216
+ * `typecad-hal board sync`. After a `west update`, this is how new/changed/
214
217
  * removed boards reach projects without a cuttlefish release. See
215
218
  * src/sdk/board-catalog-sync.ts.
216
219
  */
217
220
  syncBoardCatalog(zephyrBase?: string): BoardCatalogSyncReport;
218
221
  /**
219
222
  * Refresh the overlay only when it is stale (provenance no longer matches
220
- * the tree) — the pre-step `cuttlefish board regen` runs so a regen after
223
+ * the tree) — the pre-step `typecad-hal board regen` runs so a regen after
221
224
  * `west update` picks up the tree's boards automatically. Tree walk only
222
225
  * happens when there is actual refreshing to do.
223
226
  */
@@ -282,30 +285,5 @@ export declare class ZephyrStrategy implements PlatformStrategy {
282
285
  getProfileRegistry(): Map<string, DisplayProfile>;
283
286
  colorFormat(): 'rgb565' | 'rgb666' | 'rgb888' | 'mono';
284
287
  graphicsCapacity(): GraphicsCapacity;
285
- debugMode(target?: string): 'gdb' | 'printf';
286
- generateDebugInitCode(): string[];
287
- generateDebugBreakpointCode(params: {
288
- fileName: string;
289
- lineNum: number;
290
- originalLine: string;
291
- variables: Array<{
292
- name: string;
293
- isFunction?: boolean;
294
- cppType?: 'bool' | 'int' | 'long' | 'float' | 'string' | 'unknown';
295
- }>;
296
- normalizedCondition?: string;
297
- breakpointId?: number;
298
- }): string[];
299
- generateDebugLogpointCode(params: {
300
- fileName: string;
301
- lineNum: number;
302
- parts: Array<{
303
- type: 'text' | 'variable';
304
- value: string;
305
- }>;
306
- variables: Array<{
307
- name: string;
308
- isFunction?: boolean;
309
- }>;
310
- }): string[];
288
+ debugMode(target?: string): 'gdb' | 'none';
311
289
  }