@typecad/framework-zephyr 1.0.0-alpha.14 → 1.0.0-alpha.16
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 +22 -47
- package/dist/as-built.d.ts +33 -0
- package/dist/as-built.js +188 -0
- package/dist/async/timer-polyfill.js +1 -1
- package/dist/boardgen.d.ts +128 -0
- package/dist/boardgen.js +1366 -0
- package/dist/chips/board-overrides.d.ts +7 -0
- package/dist/chips/board-overrides.js +11 -0
- package/dist/chips/esp32s3.js +49 -0
- package/dist/chips/index.d.ts +6 -12
- package/dist/chips/index.js +18 -34
- package/dist/chips/resolve.d.ts +16 -2
- package/dist/chips/resolve.js +267 -10
- package/dist/chips/soc/.d.ts +2 -0
- package/dist/chips/soc/.js +129 -0
- package/dist/chips/soc/esp32.d.ts +2 -0
- package/dist/chips/soc/esp32.js +120 -0
- package/dist/chips/soc/esp32c3.d.ts +2 -0
- package/dist/chips/soc/esp32c3.js +90 -0
- package/dist/chips/soc/esp32c6.d.ts +2 -0
- package/dist/chips/soc/esp32c6.js +109 -0
- package/dist/chips/soc/esp32s3.d.ts +2 -0
- package/dist/chips/soc/esp32s3.js +189 -0
- package/dist/chips/soc/index.d.ts +2 -0
- package/dist/chips/soc/index.js +23 -0
- package/dist/chips/soc/nrf52840.d.ts +2 -0
- package/dist/chips/soc/nrf52840.js +130 -0
- package/dist/chips/soc/rp2040.d.ts +2 -0
- package/dist/chips/soc/rp2040.js +141 -0
- package/dist/chips/soc/rp2350a.d.ts +2 -0
- package/dist/chips/soc/rp2350a.js +145 -0
- package/dist/chips/soc/samd21g18a.d.ts +2 -0
- package/dist/chips/soc/samd21g18a.js +143 -0
- package/dist/chips/soc/stm32f411xe.d.ts +2 -0
- package/dist/chips/soc/stm32f411xe.js +251 -0
- package/dist/chips/types.d.ts +319 -0
- package/dist/chips/xiao-ble.js +21 -0
- package/dist/display/profiles.js +1 -1
- package/dist/doctor.js +38 -4
- package/dist/dt-config/custom-board.d.ts +23 -0
- package/dist/dt-config/custom-board.js +227 -0
- package/dist/dt-config/kconfig.d.ts +72 -1
- package/dist/dt-config/kconfig.js +115 -26
- package/dist/dt-config/overlay.js +548 -28
- package/dist/framework.manifest.d.ts +3 -3
- package/dist/framework.manifest.js +122 -185
- package/dist/index.d.ts +4 -1
- package/dist/index.js +8 -2
- package/dist/lowering/adc.d.ts +20 -2
- package/dist/lowering/adc.js +121 -29
- package/dist/lowering/ble.js +31 -28
- package/dist/lowering/dac.js +9 -9
- package/dist/lowering/fs.js +18 -10
- package/dist/lowering/gpio.d.ts +2 -0
- package/dist/lowering/gpio.js +82 -5
- package/dist/lowering/http.js +39 -14
- package/dist/lowering/hwtimer.d.ts +4 -0
- package/dist/lowering/hwtimer.js +35 -10
- package/dist/lowering/i2c.js +46 -54
- package/dist/lowering/index.d.ts +5 -5
- package/dist/lowering/index.js +15 -16
- package/dist/lowering/interrupts.d.ts +22 -5
- package/dist/lowering/interrupts.js +104 -22
- package/dist/lowering/mqtt.js +3 -5
- package/dist/lowering/power.js +0 -4
- package/dist/lowering/preferences.js +49 -77
- package/dist/lowering/pulse.js +0 -31
- package/dist/lowering/pwm.d.ts +12 -1
- package/dist/lowering/pwm.js +78 -14
- package/dist/lowering/random.js +3 -3
- package/dist/lowering/sensor.d.ts +37 -0
- package/dist/lowering/sensor.js +119 -0
- package/dist/lowering/spi.d.ts +12 -0
- package/dist/lowering/spi.js +65 -40
- package/dist/lowering/thread.d.ts +14 -0
- package/dist/lowering/thread.js +55 -0
- package/dist/lowering/timing.js +20 -46
- package/dist/lowering/tone.js +16 -4
- package/dist/lowering/uart.d.ts +13 -0
- package/dist/lowering/uart.js +72 -51
- package/dist/lowering/usb.d.ts +34 -0
- package/dist/lowering/usb.js +206 -0
- package/dist/lowering/wdt.d.ts +1 -1
- package/dist/lowering/wdt.js +17 -7
- package/dist/lowering/wifi.d.ts +3 -2
- package/dist/lowering/wifi.js +97 -111
- package/dist/sdk/board-catalog-sync.d.ts +16 -0
- package/dist/sdk/board-catalog-sync.js +41 -0
- package/dist/sdk/board-data.generated.d.ts +2 -0
- package/dist/sdk/board-data.generated.js +4 -0
- package/dist/sdk/catalog-walker.d.ts +90 -0
- package/dist/sdk/catalog-walker.js +682 -0
- package/dist/sdk/dts-reader.d.ts +83 -0
- package/dist/sdk/dts-reader.js +596 -0
- package/dist/strategy.d.ts +136 -17
- package/dist/strategy.js +839 -222
- package/dist/toolchain/bossac-touch.d.ts +18 -0
- package/dist/toolchain/bossac-touch.js +88 -0
- package/dist/toolchain/compat.d.ts +2 -2
- package/dist/toolchain/compat.js +8 -3
- package/dist/toolchain/debug-config.d.ts +21 -26
- package/dist/toolchain/debug-config.js +226 -76
- package/dist/toolchain/env-check.d.ts +4 -4
- package/dist/toolchain/env-check.js +5 -5
- package/dist/toolchain/index.d.ts +115 -1
- package/dist/toolchain/index.js +680 -71
- package/dist/toolchain/scaffold.js +39 -7
- package/dist/toolchain/west-discover.d.ts +4 -0
- package/dist/toolchain/west-discover.js +17 -6
- package/installer/CHANGELOG.md +473 -0
- package/installer/README.md +328 -0
- package/installer/environment.yml +46 -0
- package/installer/etc/conda/activate.d/zephyr.bat +7 -0
- package/installer/etc/conda/activate.d/zephyr.ps1 +12 -0
- package/installer/etc/conda/activate.d/zephyr.sh +20 -0
- package/installer/etc/conda/deactivate.d/zephyr.bat +6 -0
- package/installer/etc/conda/deactivate.d/zephyr.ps1 +6 -0
- package/installer/etc/conda/deactivate.d/zephyr.sh +4 -0
- package/installer/install.mjs +580 -0
- package/installer/install.ps1 +619 -0
- package/installer/install.sh +310 -0
- package/installer/lib/detect-platform.sh +62 -0
- package/installer/lib/fetch-sdk.sh +304 -0
- package/installer/lib/init-workspace.sh +153 -0
- package/installer/lib/write-activation.sh +76 -0
- package/installer/patches/tfm-c-include-separators.patch +19 -0
- package/installer/patches/zephyr-tfm-nordic-zephyr-include.patch +24 -0
- package/installer/templates/project/.typecad/activate-zephyr.ps1 +31 -0
- package/installer/templates/project/.typecad/activate-zephyr.sh +31 -0
- package/installer/templates/project/.vscode/settings.json +30 -0
- package/installer/templates/project/README.md +58 -0
- package/installer/versions.env +110 -0
- package/package.json +15 -15
- package/src/as-built.ts +206 -0
- package/src/boardgen.ts +1428 -0
- package/src/chips/index.ts +35 -54
- package/src/chips/resolve.ts +285 -10
- package/src/chips/types.ts +325 -1
- package/src/display/profiles.ts +1 -1
- package/src/doctor.ts +110 -77
- package/src/dt-config/custom-board.ts +325 -0
- package/src/dt-config/kconfig.ts +165 -18
- package/src/dt-config/overlay.ts +537 -25
- package/src/framework.manifest.ts +123 -185
- package/src/index.ts +57 -41
- package/src/lowering/adc.ts +222 -118
- package/src/lowering/ble.ts +32 -28
- package/src/lowering/dac.ts +82 -82
- package/src/lowering/fs.ts +18 -10
- package/src/lowering/gpio.ts +242 -155
- package/src/lowering/http.ts +512 -488
- package/src/lowering/hwtimer.ts +139 -101
- package/src/lowering/i2c.ts +116 -126
- package/src/lowering/index.ts +91 -93
- package/src/lowering/interrupts.ts +113 -21
- package/src/lowering/mqtt.ts +3 -5
- package/src/lowering/preferences.ts +327 -354
- package/src/lowering/pwm.ts +167 -99
- package/src/lowering/random.ts +3 -3
- package/src/lowering/sensor.ts +155 -0
- package/src/lowering/spi.ts +164 -124
- package/src/lowering/thread.ts +63 -0
- package/src/lowering/timing.ts +46 -72
- package/src/lowering/uart.ts +73 -51
- package/src/lowering/usb.ts +221 -0
- package/src/lowering/wdt.ts +95 -84
- package/src/lowering/wifi.ts +97 -112
- package/src/sdk/board-catalog-sync.ts +62 -0
- package/src/strategy.ts +848 -237
- package/src/toolchain/bossac-touch.ts +112 -0
- package/src/toolchain/compat.ts +8 -3
- package/src/toolchain/debug-config.ts +676 -522
- package/src/toolchain/env-check.ts +9 -9
- package/src/toolchain/index.ts +1359 -645
- package/src/toolchain/scaffold.ts +38 -7
- package/src/toolchain/west-discover.ts +19 -6
- package/src/async/timer-polyfill.ts +0 -107
- package/src/chips/esp32.ts +0 -74
- package/src/chips/esp32s3.ts +0 -57
- package/src/chips/xiao-ble.ts +0 -82
- package/src/lowering/power.ts +0 -70
- package/src/lowering/pulse.ts +0 -93
- package/src/lowering/tone.ts +0 -60
- package/src/lowering/worker-backing.ts +0 -94
- package/src/lowering/worker.ts +0 -17
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// USB CDC-ACM serial lowering — Zephyr "next" USB device stack
|
|
3
|
+
//
|
|
4
|
+
// A CDC-ACM instance (cdc_acm_uart<N>, composed in the generated overlay as a
|
|
5
|
+
// child of the UDC controller node) registers as a UART-class device, so the
|
|
6
|
+
// lowering drives it with the plain uart_* API — the same per-byte poll_out
|
|
7
|
+
// loops as lowering/uart.ts. The differences from a hardware UART:
|
|
8
|
+
// - usb.begin must start the device stack (usbdDeviceLines' one-shot
|
|
9
|
+
// __tc_usbd_start) before the port carries traffic;
|
|
10
|
+
// - "connected" is a real query (DTR line ctrl), not a constant;
|
|
11
|
+
// - baud is a line-coding hint — recorded, but CDC has no wire baud.
|
|
12
|
+
//
|
|
13
|
+
// If the chip descriptor declares no `usb`, every op throws with a clear
|
|
14
|
+
// "board does not expose USB" message (the diagnostic contract the framework
|
|
15
|
+
// manifest's board-gated support entry promises).
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
import { parseControllerIndex } from './util.js';
|
|
18
|
+
import { renderWrite } from './uart.js';
|
|
19
|
+
/** Render a HAL field: pass through (already rendered by the resolver). */
|
|
20
|
+
function s(v) {
|
|
21
|
+
return String(v);
|
|
22
|
+
}
|
|
23
|
+
/** The C variable prefix for a CDC instance's state. */
|
|
24
|
+
function prefix(idx) {
|
|
25
|
+
return `__tc_usb${idx}`;
|
|
26
|
+
}
|
|
27
|
+
/** Instance N resolves to the DT nodelabel the overlay generator emits. */
|
|
28
|
+
function nodeLabel(idx) {
|
|
29
|
+
return `cdc_acm_uart${idx}`;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Emit the shared USB device context (USBD_DEVICE_DEFINE + string/config
|
|
33
|
+
* descriptors + configuration + class registration + usbd_enable). Emitted
|
|
34
|
+
* ONCE per program when the chip declares `usb` — the next stack has one
|
|
35
|
+
* device context on the UDC controller, regardless of how many CDC instances
|
|
36
|
+
* hang off it.
|
|
37
|
+
*
|
|
38
|
+
* VID/PID default to the Zephyr-project testing IDs (0x2fe3/0x0001); a board
|
|
39
|
+
* overrides via `zephyr.usb.vid`/`zephyr.usb.pid`. Full-speed only — the
|
|
40
|
+
* boards this framework targets (STM32 OTG_FS, nRF USBD) are FS controllers,
|
|
41
|
+
* and the HS path would need a second USBD_CONFIGURATION_DEFINE.
|
|
42
|
+
*
|
|
43
|
+
* Symbol/API shapes verified against Zephyr 4.3:
|
|
44
|
+
* subsys/usb/device_next/Kconfig, include/zephyr/usb/usbd.h, and
|
|
45
|
+
* samples/subsys/usb/common/sample_usbd_init.c.
|
|
46
|
+
*/
|
|
47
|
+
export function usbdDeviceLines(chip) {
|
|
48
|
+
if (!chip.usb)
|
|
49
|
+
return [];
|
|
50
|
+
const vid = chip.usb.vid ?? '0x2fe3';
|
|
51
|
+
const pid = chip.usb.pid ?? '0x0001';
|
|
52
|
+
// 1200-baud touch-to-reset (BOSSA-bootloader boards): a usbd message
|
|
53
|
+
// callback that reboots into the bootloader when the host sets the CDC
|
|
54
|
+
// baud rate to 1200. Zephyr's CDC-ACM class publishes
|
|
55
|
+
// USBD_MSG_CDC_ACM_LINE_CODING on every host SET_LINE_CODING (the message
|
|
56
|
+
// carries the CDC uart device; its line coding is readable via
|
|
57
|
+
// uart_cfg_get). The reboot writes the bootloader's stay-resident magic
|
|
58
|
+
// (Arduino SAMD scheme: the bootloader checks the last word of SRAM after
|
|
59
|
+
// reset) so the board waits in the bootloader instead of booting the app.
|
|
60
|
+
const touch = chip.usb.touchReset;
|
|
61
|
+
const touchLines = touch
|
|
62
|
+
? [
|
|
63
|
+
`// 1200-baud touch-to-reset: reboot into the bootloader (flag 0x${touch.magic.toString(16)} @ 0x${touch.flagAddress.toString(16)}).`,
|
|
64
|
+
'static void __tc_usbd_msg_cb(struct usbd_context* ctx, const struct usbd_msg* msg) {',
|
|
65
|
+
' (void)ctx;',
|
|
66
|
+
' if (msg->type != USBD_MSG_CDC_ACM_LINE_CODING) { return; }',
|
|
67
|
+
' struct uart_config __tc_cfg;',
|
|
68
|
+
' if (uart_config_get(msg->dev, &__tc_cfg) == 0 && __tc_cfg.baudrate == 1200) {',
|
|
69
|
+
' // Delay the reboot so the host touch (which applies 1200 as part',
|
|
70
|
+
' // of opening the port) can close its handle first — resetting under',
|
|
71
|
+
' // an open host handle can wedge the Windows usbser driver and block',
|
|
72
|
+
' // re-enumeration until a physical replug.',
|
|
73
|
+
' k_msleep(250);',
|
|
74
|
+
` *(volatile uint32_t*)0x${touch.flagAddress.toString(16)} = 0x${touch.magic.toString(16)};`,
|
|
75
|
+
' NVIC_SystemReset();',
|
|
76
|
+
' }',
|
|
77
|
+
'}',
|
|
78
|
+
]
|
|
79
|
+
: [];
|
|
80
|
+
const touchRegister = touch
|
|
81
|
+
? [' usbd_msg_register_cb(&__tc_usbd, __tc_usbd_msg_cb);']
|
|
82
|
+
: [];
|
|
83
|
+
return [
|
|
84
|
+
'// CUTTLEFISH_USBD_BEGIN',
|
|
85
|
+
'USBD_DEVICE_DEFINE(__tc_usbd,',
|
|
86
|
+
` DEVICE_DT_GET(DT_NODELABEL(${chip.usb.controller})),`,
|
|
87
|
+
` ${vid}, ${pid});`,
|
|
88
|
+
'USBD_DESC_LANG_DEFINE(__tc_usbd_lang);',
|
|
89
|
+
'USBD_DESC_MANUFACTURER_DEFINE(__tc_usbd_mfr, "typecad");',
|
|
90
|
+
'USBD_DESC_PRODUCT_DEFINE(__tc_usbd_product, "cuttlefish app");',
|
|
91
|
+
// Serial number from hwinfo: Windows keys USB devnodes without a serial
|
|
92
|
+
// on the physical port, so flash-cycle re-enumerations reuse stale
|
|
93
|
+
// port-keyed nodes (the "access denied" open wedge). Identity-based
|
|
94
|
+
// instance paths are stable across ports and never hit that pool.
|
|
95
|
+
'USBD_DESC_SERIAL_NUMBER_DEFINE(__tc_usbd_sn);',
|
|
96
|
+
'USBD_DESC_CONFIG_DEFINE(__tc_usbd_cfg_desc, "cuttlefish");',
|
|
97
|
+
'USBD_CONFIGURATION_DEFINE(__tc_usbd_cfg, 0, 250, &__tc_usbd_cfg_desc);',
|
|
98
|
+
'static bool __tc_usbd_started = false;',
|
|
99
|
+
...touchLines,
|
|
100
|
+
'static void __tc_usbd_start(void) {',
|
|
101
|
+
' if (__tc_usbd_started) { return; }',
|
|
102
|
+
' __tc_usbd_started = true;',
|
|
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; }',
|
|
105
|
+
' err = usbd_add_descriptor(&__tc_usbd, &__tc_usbd_sn);',
|
|
106
|
+
' if (err != 0) { printk("cuttlefish usb: serial descriptor failed: %d\\n", err); return; }',
|
|
107
|
+
' err = usbd_add_descriptor(&__tc_usbd, &__tc_usbd_mfr);',
|
|
108
|
+
' if (err != 0) { printk("cuttlefish usb: manufacturer descriptor failed: %d\\n", err); return; }',
|
|
109
|
+
' err = usbd_add_descriptor(&__tc_usbd, &__tc_usbd_product);',
|
|
110
|
+
' if (err != 0) { printk("cuttlefish usb: product descriptor failed: %d\\n", err); return; }',
|
|
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; }',
|
|
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; }',
|
|
115
|
+
// Registered before usbd_init so no line-coding event can be missed.
|
|
116
|
+
...touchRegister,
|
|
117
|
+
// usbd_init builds the descriptor tables from the registered
|
|
118
|
+
// configuration/classes and marks the context initialized — usbd_enable
|
|
119
|
+
// refuses with -EPERM ("not initialized") without it (sample_usbd_init.c
|
|
120
|
+
// calls it between setup and enable).
|
|
121
|
+
' err = usbd_init(&__tc_usbd);',
|
|
122
|
+
' if (err != 0) { printk("cuttlefish usb: init failed: %d\\n", err); return; }',
|
|
123
|
+
// Boards with VBUS detection start on the VBUS event in the Zephyr
|
|
124
|
+
// sample, via a message callback we do not register; enabling
|
|
125
|
+
// unconditionally (and reporting the error) is the sample's own path
|
|
126
|
+
// for boards without detection (STM32 OTG_FS).
|
|
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");',
|
|
130
|
+
'}',
|
|
131
|
+
'// CUTTLEFISH_USBD_END',
|
|
132
|
+
];
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Emit the per-instance CDC device + init helper. Called from shimLines when
|
|
136
|
+
* the program uses USB and the chip declares `usb`; must be paired with one
|
|
137
|
+
* usbdDeviceLines() block. The init starts the device stack (guarded) and
|
|
138
|
+
* applies the line coding.
|
|
139
|
+
*/
|
|
140
|
+
export function usbInitLines(chip, instanceIndex) {
|
|
141
|
+
if (!chip.usb)
|
|
142
|
+
return [];
|
|
143
|
+
const p = prefix(instanceIndex);
|
|
144
|
+
const dev = `${p}_dev`;
|
|
145
|
+
return [
|
|
146
|
+
'// CUTTLEFISH_USB_BEGIN',
|
|
147
|
+
`static const struct device* ${dev} = DEVICE_DT_GET(DT_NODELABEL(${nodeLabel(instanceIndex)}));`,
|
|
148
|
+
`static void ${p}_init(void) {`,
|
|
149
|
+
` __tc_usbd_start(); // CDC line coding is the host's business`,
|
|
150
|
+
`}`,
|
|
151
|
+
'// CUTTLEFISH_USB_END',
|
|
152
|
+
];
|
|
153
|
+
}
|
|
154
|
+
/** Throw the board-capability diagnostic. Centralized so every op reads identically. */
|
|
155
|
+
function requireUsb(chip, op) {
|
|
156
|
+
if (!chip.usb) {
|
|
157
|
+
throw new Error(`framework-zephyr: \`${op}\` needs a USB device stack, but this board's chip data declares no \`zephyr.usb\` ` +
|
|
158
|
+
`(controller + cdcInstances). Boards whose Zephyr DTS has no enabled UDC controller node ` +
|
|
159
|
+
`(zephyr_udc0) cannot provide USB CDC serial.`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Resolve a HAL usb.* op to Zephyr C++.
|
|
164
|
+
* Returns `{ code }` for statement ops, `{ expression }` for value-returning ops.
|
|
165
|
+
*/
|
|
166
|
+
export function lowerUsb(op, chip) {
|
|
167
|
+
requireUsb(chip, op.operation);
|
|
168
|
+
const o = op;
|
|
169
|
+
const idx = parseControllerIndex(o.port);
|
|
170
|
+
if (chip.usb && idx >= chip.usb.cdcInstances) {
|
|
171
|
+
throw new Error(`framework-zephyr: usb port "${o.port}" (instance ${idx}) is out of range — this board composes ` +
|
|
172
|
+
`${chip.usb.cdcInstances} CDC-ACM instance(s) (USB0..USB${chip.usb.cdcInstances - 1}).`);
|
|
173
|
+
}
|
|
174
|
+
const p = prefix(idx);
|
|
175
|
+
const dev = `${p}_dev`;
|
|
176
|
+
switch (op.operation) {
|
|
177
|
+
case 'usb.begin':
|
|
178
|
+
return { code: `${p}_init();` };
|
|
179
|
+
case 'usb.wait_ready': {
|
|
180
|
+
// Bounded DTR poll, sliced in the shim-side expression (no user-code
|
|
181
|
+
// busy loop). timeoutMs 0 = wait forever.
|
|
182
|
+
return { expression: `({ bool __ok = false; uint32_t __t = 0U; while (true) { uint32_t __dtr = 0U; if ((uart_line_ctrl_get(${dev}, UART_LINE_CTRL_DTR, &__dtr) == 0) && (__dtr != 0U)) { __ok = true; break; } if ((${s(o.timeoutMs ?? 0)}) != 0 && __t >= (uint32_t)(${s(o.timeoutMs ?? 0)})) { break; } k_msleep(10); __t += 10U; } __ok; })` };
|
|
183
|
+
}
|
|
184
|
+
case 'usb.end':
|
|
185
|
+
// CDC has no per-port disable short of tearing down the device stack
|
|
186
|
+
// (which would drop every other instance); make end observable but safe.
|
|
187
|
+
return { code: `(void)${dev};` };
|
|
188
|
+
case 'usb.print':
|
|
189
|
+
return { code: renderWrite(dev, o.value, false) };
|
|
190
|
+
case 'usb.println':
|
|
191
|
+
return { code: renderWrite(dev, o.value, true) };
|
|
192
|
+
case 'usb.read':
|
|
193
|
+
// Same poll semantics as uart.read: the byte or -1 if none available.
|
|
194
|
+
return { expression: `({ unsigned char __b = 0; (uart_poll_in(${dev}, &__b) == 0) ? (int)__b : -1; })` };
|
|
195
|
+
case 'usb.available':
|
|
196
|
+
// uart_poll_in reports only "one byte ready" and probing would drain it;
|
|
197
|
+
// same honest limitation as uart.available.
|
|
198
|
+
return { expression: '(0)' };
|
|
199
|
+
case 'usb.connected':
|
|
200
|
+
// DTR asserted = the host actually opened the port.
|
|
201
|
+
return { expression: `({ uint32_t __dtr = 0; (uart_line_ctrl_get(${dev}, UART_LINE_CTRL_DTR, &__dtr) == 0) && (__dtr != 0); })` };
|
|
202
|
+
default:
|
|
203
|
+
throw new Error(`framework-zephyr does not yet support HAL op \`${op.operation}\`. ` +
|
|
204
|
+
`Open an issue or use rawCpp() to emit it manually.`);
|
|
205
|
+
}
|
|
206
|
+
}
|
package/dist/lowering/wdt.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export declare function wdtInitLines(chip: ZephyrChipDescriptor): string[];
|
|
|
9
9
|
* Resolve a HAL wdt.* op to Zephyr C++.
|
|
10
10
|
* Returns `{ code }` for statement ops, `{ expression }` for value-returning ops.
|
|
11
11
|
*/
|
|
12
|
-
export declare function lowerWdt(op: HALOpIR): {
|
|
12
|
+
export declare function lowerWdt(op: HALOpIR, chip: ZephyrChipDescriptor): {
|
|
13
13
|
code?: string;
|
|
14
14
|
expression?: string;
|
|
15
15
|
};
|
package/dist/lowering/wdt.js
CHANGED
|
@@ -10,12 +10,15 @@
|
|
|
10
10
|
// constant or a number; we parse to ms in the lowering.
|
|
11
11
|
// ---------------------------------------------------------------------------
|
|
12
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)
|
|
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). */
|
|
14
16
|
function timeoutToMs(timeout) {
|
|
15
17
|
if (typeof timeout === 'number')
|
|
16
18
|
return timeout;
|
|
17
19
|
if (!timeout)
|
|
18
20
|
return 1000; // default 1s when absent (e.g. the validator probe)
|
|
21
|
+
timeout = timeout.replace(/^['"]|['"]$/g, '');
|
|
19
22
|
// Arduino WDTO_* constants.
|
|
20
23
|
const wdto = {
|
|
21
24
|
WDTO_15MS: 15, WDTO_30MS: 30, WDTO_60MS: 60, WDTO_120MS: 120,
|
|
@@ -51,13 +54,20 @@ export function wdtInitLines(chip) {
|
|
|
51
54
|
* Resolve a HAL wdt.* op to Zephyr C++.
|
|
52
55
|
* Returns `{ code }` for statement ops, `{ expression }` for value-returning ops.
|
|
53
56
|
*/
|
|
54
|
-
export function lowerWdt(op) {
|
|
57
|
+
export function lowerWdt(op, chip) {
|
|
55
58
|
const o = op;
|
|
59
|
+
// No watchdog node on this target (e.g. SAM D21 — Zephyr's samd21 dtsi
|
|
60
|
+
// exposes none). Comment + (in profileDiagnostics) a clear error, mirroring
|
|
61
|
+
// the hwtimer unavailable pattern. Without this the wdt_* calls reference
|
|
62
|
+
// the shim vars that wdtInitLines (gated on chip.wdt) never emitted.
|
|
63
|
+
if (!chip.wdt) {
|
|
64
|
+
return { code: `/* ${op.operation}: no watchdog device on ${chip.id} */` };
|
|
65
|
+
}
|
|
56
66
|
switch (op.operation) {
|
|
57
|
-
case 'wdt.
|
|
58
|
-
|
|
59
|
-
//
|
|
60
|
-
|
|
67
|
+
case 'wdt.setup': {
|
|
68
|
+
// Same install+setup sequence as wdt.enable, but the timeout is a
|
|
69
|
+
// plain ms number from construction — no WDTO_*/string parsing.
|
|
70
|
+
const ms = Number(o.timeoutMs ?? 1000);
|
|
61
71
|
return {
|
|
62
72
|
code: [
|
|
63
73
|
`if (!__tc_wdt_setup_done) {`,
|
|
@@ -69,7 +79,7 @@ export function lowerWdt(op) {
|
|
|
69
79
|
].join(' '),
|
|
70
80
|
};
|
|
71
81
|
}
|
|
72
|
-
case 'wdt.
|
|
82
|
+
case 'wdt.feed':
|
|
73
83
|
return { code: `if (__tc_wdt_channel >= 0) { wdt_feed(__tc_wdt_dev, __tc_wdt_channel); }` };
|
|
74
84
|
case 'wdt.disable':
|
|
75
85
|
return { code: `wdt_disable(__tc_wdt_dev); __tc_wdt_setup_done = false;` };
|
package/dist/lowering/wifi.d.ts
CHANGED
|
@@ -5,8 +5,9 @@ import type { HALOpIR } from '@typecad/cuttlefish/api/shared';
|
|
|
5
5
|
*
|
|
6
6
|
* State is driven by two net_mgmt event handlers:
|
|
7
7
|
* - L4 connectivity (NET_EVENT_L4_CONNECTED/DISCONNECTED) → connected flag.
|
|
8
|
-
* This reflects IP connectivity (post-DHCP
|
|
9
|
-
* events are raised by conn_mgr's monitoring
|
|
8
|
+
* This reflects IP connectivity (post-DHCP, or right after static IPv4
|
|
9
|
+
* facts are applied) — the events are raised by conn_mgr's monitoring
|
|
10
|
+
* layer (conn_mgr_monitor.c).
|
|
10
11
|
* - WiFi scan (NET_EVENT_WIFI_SCAN_RESULT/SCAN_DONE) → scan_results pool.
|
|
11
12
|
*/
|
|
12
13
|
export declare function wifiInitLines(): string[];
|
package/dist/lowering/wifi.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
|
-
// WiFi lowering — net_mgmt (
|
|
2
|
+
// WiFi lowering — net_mgmt (join/scan/radio) + conn_mgr monitor (L4 events)
|
|
3
3
|
//
|
|
4
|
-
// Hybrid: the WiFi
|
|
4
|
+
// Hybrid: the WiFi join/disconnect/scan/radio-query requests go directly
|
|
5
5
|
// through net_mgmt + wifi_mgmt.h (NET_REQUEST_WIFI_CONNECT/DISCONNECT/SCAN/...),
|
|
6
6
|
// taking the iface admin-up with net_if_up first. IP-level connectivity is
|
|
7
7
|
// still signaled by conn_mgr's monitoring layer (conn_mgr_monitor.c raises
|
|
@@ -23,8 +23,9 @@ function s(v) {
|
|
|
23
23
|
*
|
|
24
24
|
* State is driven by two net_mgmt event handlers:
|
|
25
25
|
* - L4 connectivity (NET_EVENT_L4_CONNECTED/DISCONNECTED) → connected flag.
|
|
26
|
-
* This reflects IP connectivity (post-DHCP
|
|
27
|
-
* events are raised by conn_mgr's monitoring
|
|
26
|
+
* This reflects IP connectivity (post-DHCP, or right after static IPv4
|
|
27
|
+
* facts are applied) — the events are raised by conn_mgr's monitoring
|
|
28
|
+
* layer (conn_mgr_monitor.c).
|
|
28
29
|
* - WiFi scan (NET_EVENT_WIFI_SCAN_RESULT/SCAN_DONE) → scan_results pool.
|
|
29
30
|
*/
|
|
30
31
|
export function wifiInitLines() {
|
|
@@ -35,12 +36,12 @@ export function wifiInitLines() {
|
|
|
35
36
|
`// ── core (always needed when wifi.* is used) ────────────────────────────`,
|
|
36
37
|
`// CUTTLEFISH_WIFI_CORE_BEGIN`,
|
|
37
38
|
`// WiFi event callback signature (wifi.on_event). One slot per supported`,
|
|
38
|
-
`// event — a second registration overwrites the first
|
|
39
|
+
`// event — a second registration overwrites the first.`,
|
|
39
40
|
`typedef void (*__tc_wifi_cb_t)(void);`,
|
|
40
41
|
``,
|
|
41
42
|
`// WiFi state. connected reflects IP connectivity (L4), not just link —`,
|
|
42
|
-
`//
|
|
43
|
-
`// the L4 event once DHCP completes
|
|
43
|
+
`// join takes the iface admin-up (net_if_up) and conn_mgr_monitor raises`,
|
|
44
|
+
`// the L4 event once DHCP completes (or the static-IPv4 facts are applied).`,
|
|
44
45
|
`static struct {`,
|
|
45
46
|
` bool inited; // net_mgmt handlers registered + iface resolved`,
|
|
46
47
|
` bool connected; // set by NET_EVENT_L4_CONNECTED/DISCONNECTED`,
|
|
@@ -71,15 +72,15 @@ export function wifiInitLines() {
|
|
|
71
72
|
` __tc_wifi.connected = true;`,
|
|
72
73
|
` } else if (mgmt_event == NET_EVENT_L4_DISCONNECTED) {`,
|
|
73
74
|
` __tc_wifi.connected = false;`,
|
|
74
|
-
` // Defer
|
|
75
|
-
` // typically
|
|
76
|
-
` //
|
|
75
|
+
` // Defer on_drop via k_work_submit so the user callback (which`,
|
|
76
|
+
` // typically re-joins) runs outside the net_mgmt event chain.`,
|
|
77
|
+
` // Calling NET_REQUEST_WIFI_CONNECT from within the disconnect`,
|
|
77
78
|
` // callback causes re-entrancy that prevents re-association.`,
|
|
78
79
|
` if (__tc_wifi.on_disconnect != nullptr) {`,
|
|
79
80
|
` (void)k_work_submit(&__tc_wifi.disconnect_work);`,
|
|
80
81
|
` }`,
|
|
81
82
|
` } else if (mgmt_event == NET_EVENT_IPV4_ADDR_ADD) {`,
|
|
82
|
-
` //
|
|
83
|
+
` // An IPv4 address was assigned — the true "got IP" signal. Fires`,
|
|
83
84
|
` // after NET_EVENT_L4_CONNECTED on a successful DHCP join.`,
|
|
84
85
|
` if (__tc_wifi.on_connect != nullptr) __tc_wifi.on_connect();`,
|
|
85
86
|
` } else if (mgmt_event == NET_EVENT_WIFI_SCAN_RESULT) {`,
|
|
@@ -129,8 +130,8 @@ export function wifiInitLines() {
|
|
|
129
130
|
`// duration. Each wait slice sleeps 20ms and, in the entry TU of a UI build`,
|
|
130
131
|
`// (the only TU carrying the ui_tick definition), pumps one frame so`,
|
|
131
132
|
`// animations and touch stay live during the wait. Constraint: do NOT call`,
|
|
132
|
-
`//
|
|
133
|
-
`//
|
|
133
|
+
`// join() from inside UI event handlers — that re-enters ui_tick mid-tick;`,
|
|
134
|
+
`// use joinStart() + linked() there.`,
|
|
134
135
|
`#ifdef CUTTLEFISH_ENTRY_UI_TU`,
|
|
135
136
|
`static void ui_tick(uint16_t deltaMs); // defined by the UI runtime header`,
|
|
136
137
|
`#endif`,
|
|
@@ -147,17 +148,20 @@ export function wifiInitLines() {
|
|
|
147
148
|
`}`,
|
|
148
149
|
`// CUTTLEFISH_WIFI_CORE_END`,
|
|
149
150
|
``,
|
|
150
|
-
`// ──
|
|
151
|
+
`// ── join / leave (net_mgmt — conn_mgr monitor supplies L4 events) ────────`,
|
|
151
152
|
`// CUTTLEFISH_WIFI_CONNECT_BEGIN`,
|
|
152
153
|
`// SSID/PSK are staged into static buffers (wifi_connect_req_params.ssid/psk`,
|
|
153
154
|
`// are const uint8_t* — they point at caller-owned storage that must outlive`,
|
|
154
155
|
`// the request), then net_if_up takes the iface admin-up and NET_REQUEST_WIFI_CONNECT`,
|
|
155
|
-
`// is issued
|
|
156
|
+
`// is issued with the station's construction facts (security/band/channel).`,
|
|
157
|
+
`// conn_mgr_monitor raises the L4 event once DHCP completes.`,
|
|
156
158
|
`static struct wifi_connect_req_params __tc_wifi_conn_params;`,
|
|
157
159
|
`static uint8_t __tc_wifi_ssid_buf[33]; // SSID ≤32 + slack`,
|
|
158
160
|
`static uint8_t __tc_wifi_psk_buf[64]; // PSK ≤63 + slack`,
|
|
159
161
|
``,
|
|
160
|
-
`static void __tc_wifi_stage_creds(const char* ssid, const char* password
|
|
162
|
+
`static void __tc_wifi_stage_creds(const char* ssid, const char* password,`,
|
|
163
|
+
` enum wifi_security_type security, int32_t channel,`,
|
|
164
|
+
` enum wifi_frequency_bands band) {`,
|
|
161
165
|
` __tc_wifi_ensure_init();`,
|
|
162
166
|
` if (__tc_wifi.iface == nullptr) return;`,
|
|
163
167
|
` uint32_t ssid_len = strlen(ssid);`,
|
|
@@ -174,15 +178,16 @@ export function wifiInitLines() {
|
|
|
174
178
|
` } else {`,
|
|
175
179
|
` __tc_wifi_conn_params.psk_length = 0U;`,
|
|
176
180
|
` }`,
|
|
177
|
-
` __tc_wifi_conn_params.security =
|
|
178
|
-
` __tc_wifi_conn_params.channel = WIFI_CHANNEL_ANY;`,
|
|
179
|
-
` __tc_wifi_conn_params.band =
|
|
180
|
-
` // Stage the connection request (wifi_connect). The L4 handler sets`,
|
|
181
|
-
` // \`connected\` once DHCP completes.`,
|
|
181
|
+
` __tc_wifi_conn_params.security = security;`,
|
|
182
|
+
` __tc_wifi_conn_params.channel = (channel > 0) ? static_cast<uint8_t>(channel) : WIFI_CHANNEL_ANY;`,
|
|
183
|
+
` __tc_wifi_conn_params.band = band;`,
|
|
182
184
|
` (void)net_mgmt(NET_REQUEST_WIFI_CONNECT, __tc_wifi.iface,`,
|
|
183
185
|
` &__tc_wifi_conn_params, sizeof(__tc_wifi_conn_params));`,
|
|
184
186
|
`}`,
|
|
185
187
|
``,
|
|
188
|
+
`// joinStart(): stage the association without waiting — poll linked() or`,
|
|
189
|
+
`// await join() in an async function (the async machinery splits it into`,
|
|
190
|
+
`// this + the is_connected poll).`,
|
|
186
191
|
`static void __tc_wifi_connect_start(const char* ssid, const char* password) {`,
|
|
187
192
|
` __tc_wifi_ensure_init();`,
|
|
188
193
|
` if (__tc_wifi.iface == nullptr) {`,
|
|
@@ -190,21 +195,58 @@ export function wifiInitLines() {
|
|
|
190
195
|
` return;`,
|
|
191
196
|
` }`,
|
|
192
197
|
` net_if_up(__tc_wifi.iface);`,
|
|
193
|
-
` __tc_wifi_stage_creds(ssid, password);`,
|
|
198
|
+
` __tc_wifi_stage_creds(ssid, password, WIFI_SECURITY_TYPE_PSK, 0, WIFI_FREQ_BAND_2_4_GHZ);`,
|
|
194
199
|
` __tc_wifi.connected = false;`,
|
|
195
200
|
` printk("tc-wifi: connecting to %s\\n", ssid);`,
|
|
196
201
|
`}`,
|
|
197
202
|
``,
|
|
198
|
-
`//
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
`
|
|
202
|
-
`
|
|
203
|
+
`// join(): the thin station verb — associate from the construction facts,`,
|
|
204
|
+
`// apply the optional static-IPv4 / power-save facts, then bounded-wait for`,
|
|
205
|
+
`// IP connectivity. Returns whether the link came up (boolean, no exceptions).`,
|
|
206
|
+
`static bool __tc_wifi_join(const char* ssid, const char* psk,`,
|
|
207
|
+
` enum wifi_security_type security, int32_t channel,`,
|
|
208
|
+
` enum wifi_frequency_bands band, int32_t timeout_ms,`,
|
|
209
|
+
` bool ps_off, const char* ip_addr, const char* gateway,`,
|
|
210
|
+
` const char* netmask) {`,
|
|
211
|
+
` __tc_wifi_ensure_init();`,
|
|
212
|
+
` if (__tc_wifi.iface == nullptr) {`,
|
|
213
|
+
` printk("tc-wifi: no WiFi iface found\\n");`,
|
|
214
|
+
` return false;`,
|
|
215
|
+
` }`,
|
|
216
|
+
` net_if_up(__tc_wifi.iface);`,
|
|
217
|
+
` __tc_wifi_stage_creds(ssid, psk, security, channel, band);`,
|
|
218
|
+
` __tc_wifi.connected = false;`,
|
|
219
|
+
` if (ip_addr != nullptr && gateway != nullptr && netmask != nullptr) {`,
|
|
220
|
+
` // Static IPv4 facts: stop DHCP, configure the address manually. The`,
|
|
221
|
+
` // addr-add raises the events conn_mgr_monitor listens for, so`,
|
|
222
|
+
` // \`connected\` flips without a lease.`,
|
|
223
|
+
` net_dhcpv4_stop(__tc_wifi.iface);`,
|
|
224
|
+
` struct in_addr addr = { 0 }, gw = { 0 }, mask = { 0 };`,
|
|
225
|
+
` if (net_addr_pton(AF_INET, ip_addr, &addr) == 0`,
|
|
226
|
+
` && net_addr_pton(AF_INET, netmask, &mask) == 0`,
|
|
227
|
+
` && net_addr_pton(AF_INET, gateway, &gw) == 0) {`,
|
|
228
|
+
` (void)net_if_ipv4_addr_add(__tc_wifi.iface, &addr, NET_ADDR_MANUAL, 0);`,
|
|
229
|
+
` // set_netmask() is __deprecated on Zephyr >= 4.3 — the`,
|
|
230
|
+
` // by-addr form carries the prefix it belongs to.`,
|
|
231
|
+
` (void)net_if_ipv4_set_netmask_by_addr(__tc_wifi.iface, &addr, &mask);`,
|
|
232
|
+
` (void)net_if_ipv4_set_gw(__tc_wifi.iface, &gw);`,
|
|
233
|
+
` } else {`,
|
|
234
|
+
` printk("tc-wifi: bad static ipv4 facts, falling back to DHCP\\n");`,
|
|
235
|
+
` net_dhcpv4_start(__tc_wifi.iface);`,
|
|
236
|
+
` }`,
|
|
237
|
+
` }`,
|
|
238
|
+
` if (ps_off) {`,
|
|
239
|
+
` // WiFi.PS_OFF — disable the radio's modem sleep (wifi_ps_params).`,
|
|
240
|
+
` struct wifi_ps_params ps = {}; // value-init: first member is an enum`,
|
|
241
|
+
` ps.enabled = WIFI_PS_DISABLED;`,
|
|
242
|
+
` (void)net_mgmt(NET_REQUEST_WIFI_PS_CONFIG, __tc_wifi.iface, &ps, sizeof(ps));`,
|
|
243
|
+
` }`,
|
|
244
|
+
` printk("tc-wifi: joining %s\\n", ssid);`,
|
|
203
245
|
` int32_t waited = 0;`,
|
|
204
246
|
` while (!__tc_wifi.connected && waited < timeout_ms) { __tc_wifi_wait_slice(20); waited += 20; }`,
|
|
205
|
-
` printk("tc-wifi:
|
|
247
|
+
` printk("tc-wifi: join %s after %dms\\n", __tc_wifi.connected ? "ok" : "timeout", waited);`,
|
|
248
|
+
` return __tc_wifi.connected;`,
|
|
206
249
|
`}`,
|
|
207
|
-
`// CUTTLEFISH_WIFI_CONNECT_BLOCKING_END`,
|
|
208
250
|
``,
|
|
209
251
|
`static void __tc_wifi_disconnect(void) {`,
|
|
210
252
|
` __tc_wifi_ensure_init();`,
|
|
@@ -217,10 +259,6 @@ export function wifiInitLines() {
|
|
|
217
259
|
``,
|
|
218
260
|
`// ── status / radio queries ───────────────────────────────────────────────`,
|
|
219
261
|
`// CUTTLEFISH_WIFI_QUERY_BEGIN`,
|
|
220
|
-
`static int32_t __tc_wifi_status(void) {`,
|
|
221
|
-
` return __tc_wifi.connected ? 3 : 0; // 3=Connected in the HAL status enum`,
|
|
222
|
-
`}`,
|
|
223
|
-
``,
|
|
224
262
|
`static const char* __tc_wifi_local_ip(void) {`,
|
|
225
263
|
` __tc_wifi_ensure_init();`,
|
|
226
264
|
` if (__tc_wifi.iface == nullptr || !__tc_wifi.connected) return "0.0.0.0";`,
|
|
@@ -247,7 +285,7 @@ export function wifiInitLines() {
|
|
|
247
285
|
` struct wifi_iface_status status = { 0 };`,
|
|
248
286
|
` (void)net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, __tc_wifi.iface,`,
|
|
249
287
|
` &status, sizeof(status));`,
|
|
250
|
-
` // Pack the 6 MAC bytes (status.bssid) into a uint64 (HAL returns a number).`,
|
|
288
|
+
` // Pack the 6 MAC bytes (status.bssid) into a uint64 (the HAL returns a number).`,
|
|
251
289
|
` uint64_t m = 0;`,
|
|
252
290
|
` for (int32_t b = 0; b < 6; b++) { m = (m << 8) | static_cast<uint64_t>(status.bssid[b]); }`,
|
|
253
291
|
` return m;`,
|
|
@@ -291,61 +329,12 @@ export function wifiInitLines() {
|
|
|
291
329
|
`}`,
|
|
292
330
|
`// CUTTLEFISH_WIFI_SCAN_END`,
|
|
293
331
|
``,
|
|
294
|
-
`// ── config ───────────────────────────────────────────────────────────────`,
|
|
295
|
-
`// CUTTLEFISH_WIFI_CONFIG_BEGIN`,
|
|
296
|
-
`// NOTE: wifi.set_tx_power is intentionally NOT lowered here. The Zephyr esp32`,
|
|
297
|
-
`// WiFi driver owns esp_wifi_start/esp_wifi_connect, and calling`,
|
|
298
|
-
`// esp_wifi_set_max_tx_power from this shim fights the driver for control of`,
|
|
299
|
-
`// the radio (brownout). The compile-time PHY ceiling (ESP_PHY_MAX_WIFI_TX_POWER`,
|
|
300
|
-
`// in ESP-IDF's components/esp_phy/Kconfig) is NOT sourced into Zephyr's Kconfig`,
|
|
301
|
-
`// tree, so it cannot be lowered via prj.conf either (zephyr#45580). TX power`,
|
|
302
|
-
`// stays at its default until a Zephyr-native surface exists.`,
|
|
303
|
-
`static void __tc_wifi_set_hostname(const char* name) {`,
|
|
304
|
-
` // Best-effort: Zephyr has no net_if_set_hostname; the system hostname`,
|
|
305
|
-
` // comes from the hostname subsystem (net_hostname.h) + CONFIG_NET_HOSTNAME.`,
|
|
306
|
-
` // The interface name is set via net_if_set_name, which is not the same as`,
|
|
307
|
-
` // a DHCP hostname. No-op until the hostname subsystem is wired.`,
|
|
308
|
-
` (void)name;`,
|
|
309
|
-
` (void)__tc_wifi;`,
|
|
310
|
-
`}`,
|
|
311
|
-
``,
|
|
312
|
-
`// ── power save (NET_REQUEST_WIFI_PS_CONFIG) ─────────────────────────────`,
|
|
313
|
-
`// wifi.set_power_save: HAL modes are "default" (enabled) / "none" (disabled).`,
|
|
314
|
-
`// The Zephyr esp32 driver implements esp32_wifi_set_power_save, so this is a`,
|
|
315
|
-
`// real net_mgmt request — not a no-op like set_hostname above.`,
|
|
316
|
-
`static void __tc_wifi_set_power_save(const char* mode) {`,
|
|
317
|
-
` __tc_wifi_ensure_init();`,
|
|
318
|
-
` if (__tc_wifi.iface == nullptr) return;`,
|
|
319
|
-
` struct wifi_ps_params ps = { 0 };`,
|
|
320
|
-
` ps.type = WIFI_PS_PARAM_TYPE_ENABLED;`,
|
|
321
|
-
` // HAL mode "default" → power save on; "none" → off. (The full HAL surface`,
|
|
322
|
-
` // only exposes those two; deeper ps_mode/wakeup tuning isn't exposed.)`,
|
|
323
|
-
` bool on = (mode != nullptr && strcmp(mode, "none") != 0);`,
|
|
324
|
-
` ps.enabled = on ? WIFI_PS_ENABLED : WIFI_PS_DISABLED;`,
|
|
325
|
-
` (void)net_mgmt(NET_REQUEST_WIFI_PS_CONFIG, __tc_wifi.iface,`,
|
|
326
|
-
` &ps, sizeof(ps));`,
|
|
327
|
-
`}`,
|
|
328
|
-
``,
|
|
329
|
-
`// ── waits (block on the L4 connectivity flag) ───────────────────────────`,
|
|
330
|
-
`// wifi.wait_connected / wait_disconnected: poll __tc_wifi.connected (set by`,
|
|
331
|
-
`// the L4 net_mgmt handler) with a deadline. Same blocking pattern as`,
|
|
332
|
-
`// __tc_wifi_connect.`,
|
|
333
|
-
`static void __tc_wifi_wait_connected(int32_t timeout_ms) {`,
|
|
334
|
-
` __tc_wifi_ensure_init();`,
|
|
335
|
-
` int32_t waited = 0;`,
|
|
336
|
-
` while (!__tc_wifi.connected && waited < timeout_ms) { __tc_wifi_wait_slice(20); waited += 20; }`,
|
|
337
|
-
`}`,
|
|
338
|
-
`static void __tc_wifi_wait_disconnected(void) {`,
|
|
339
|
-
` __tc_wifi_ensure_init();`,
|
|
340
|
-
` // No timeout in the HAL surface — block until the L4 handler clears the flag.`,
|
|
341
|
-
` while (__tc_wifi.connected) { __tc_wifi_wait_slice(20); }`,
|
|
342
|
-
`}`,
|
|
343
|
-
``,
|
|
344
332
|
`// ── AP mode (NET_REQUEST_WIFI_AP_ENABLE / DISABLE) ──────────────────────`,
|
|
345
|
-
`//
|
|
346
|
-
`//
|
|
347
|
-
`//
|
|
348
|
-
`//
|
|
333
|
+
`// CUTTLEFISH_WIFI_CONFIG_BEGIN`,
|
|
334
|
+
`// WiFiAP.start()/stop(): bring the iface up as an AP. The esp32 driver's`,
|
|
335
|
+
`// ap_enable takes the same struct as join (ssid/psk/channel/security).`,
|
|
336
|
+
`// hidden/maxClients have no driver hook — the thin WiFiAP facts carry only`,
|
|
337
|
+
`// what the driver honors.`,
|
|
349
338
|
`static struct wifi_connect_req_params __tc_wifi_ap_params;`,
|
|
350
339
|
`static uint8_t __tc_wifi_ap_ssid_buf[33];`,
|
|
351
340
|
`static uint8_t __tc_wifi_ap_psk_buf[64];`,
|
|
@@ -396,15 +385,21 @@ export function wifiInitLines() {
|
|
|
396
385
|
export function lowerWifi(op) {
|
|
397
386
|
const o = op;
|
|
398
387
|
switch (op.operation) {
|
|
399
|
-
// ──
|
|
400
|
-
case 'wifi.
|
|
401
|
-
|
|
388
|
+
// ── Station ──
|
|
389
|
+
case 'wifi.join': {
|
|
390
|
+
// Token → Zephyr enum mapping (WiFi.OPEN/WPA2/WPA3/WPA2_WPA3).
|
|
391
|
+
const sec = Number(o.security ?? 1);
|
|
392
|
+
const secEnum = sec === 0 ? 'WIFI_SECURITY_TYPE_NONE'
|
|
393
|
+
: sec === 2 ? 'WIFI_SECURITY_TYPE_SAE'
|
|
394
|
+
: sec === 3 ? 'WIFI_SECURITY_TYPE_PSK_SAE'
|
|
395
|
+
: 'WIFI_SECURITY_TYPE_PSK';
|
|
396
|
+
const bandEnum = Number(o.band ?? 0) === 1 ? 'WIFI_FREQ_BAND_5_GHZ' : 'WIFI_FREQ_BAND_2_4_GHZ';
|
|
397
|
+
return { expression: `__tc_wifi_join(${s(o.ssid)}, ${o.psk != null ? s(o.psk) : 'nullptr'}, ${secEnum}, ${s(o.channel ?? 0)}, ${bandEnum}, ${s(o.timeoutMs ?? 15000)}, ${Number(o.ps ?? 0) !== 0 ? 'true' : 'false'}, ${o.ipAddr != null ? s(o.ipAddr) : 'nullptr'}, ${o.gateway != null ? s(o.gateway) : 'nullptr'}, ${o.netmask != null ? s(o.netmask) : 'nullptr'})` };
|
|
398
|
+
}
|
|
402
399
|
case 'wifi.connect_start':
|
|
403
|
-
return { code: `__tc_wifi_connect_start(${s(o.ssid)}, ${s(o.password
|
|
400
|
+
return { code: `__tc_wifi_connect_start(${s(o.ssid)}, ${o.password != null ? s(o.password) : 'nullptr'});` };
|
|
404
401
|
case 'wifi.disconnect':
|
|
405
402
|
return { code: `__tc_wifi_disconnect();` };
|
|
406
|
-
case 'wifi.status':
|
|
407
|
-
return { expression: `__tc_wifi_status()` };
|
|
408
403
|
case 'wifi.is_connected':
|
|
409
404
|
return { expression: `(__tc_wifi.connected)` };
|
|
410
405
|
case 'wifi.local_ip':
|
|
@@ -416,6 +411,8 @@ export function lowerWifi(op) {
|
|
|
416
411
|
// ── Scan ──
|
|
417
412
|
case 'wifi.scan':
|
|
418
413
|
return { code: `__tc_wifi_scan_blocking();` };
|
|
414
|
+
// Async split of wifi.scan (synthesized by the async tier's netWaitInfo —
|
|
415
|
+
// no TS-facing method maps here). Kick without waiting; poll scan_done.
|
|
419
416
|
case 'wifi.scan_start':
|
|
420
417
|
return { code: `__tc_wifi_scan_start();` };
|
|
421
418
|
case 'wifi.scan_done':
|
|
@@ -432,14 +429,9 @@ export function lowerWifi(op) {
|
|
|
432
429
|
: '__tc_wifi_scan_channel';
|
|
433
430
|
return { expression: `${helper}(${s(o.index ?? 0)})` };
|
|
434
431
|
}
|
|
435
|
-
// ──
|
|
436
|
-
case 'wifi.set_hostname':
|
|
437
|
-
return { code: `__tc_wifi_set_hostname(${s(o.name)});` };
|
|
438
|
-
case 'wifi.set_power_save':
|
|
439
|
-
// HAL modes are "default" (on) / "none" (off) — see the shim's note.
|
|
440
|
-
return { code: `__tc_wifi_set_power_save(${s(o.mode)});` };
|
|
432
|
+
// ── Events ──
|
|
441
433
|
case 'wifi.on_event': {
|
|
442
|
-
//
|
|
434
|
+
// 'disconnect' and 'connect' are the supported events.
|
|
443
435
|
if (o.event === 'disconnect') {
|
|
444
436
|
return { code: `__tc_wifi.on_disconnect = ${s(o.handler)};` };
|
|
445
437
|
}
|
|
@@ -448,11 +440,6 @@ export function lowerWifi(op) {
|
|
|
448
440
|
}
|
|
449
441
|
return undefined;
|
|
450
442
|
}
|
|
451
|
-
// ── Waits (block on the L4 connectivity flag) ──
|
|
452
|
-
case 'wifi.wait_connected':
|
|
453
|
-
return { code: `__tc_wifi_wait_connected(${s(o.timeoutMs ?? 15000)});` };
|
|
454
|
-
case 'wifi.wait_disconnected':
|
|
455
|
-
return { code: `__tc_wifi_wait_disconnected();` };
|
|
456
443
|
// ── AP mode (esp32 driver: ap_enable/ap_disable wired; only ssid/psk/channel
|
|
457
444
|
// honored — hidden/maxClients have no driver hook). ──
|
|
458
445
|
case 'wifi.ap_start':
|
|
@@ -460,11 +447,10 @@ export function lowerWifi(op) {
|
|
|
460
447
|
case 'wifi.ap_stop':
|
|
461
448
|
return { code: `__tc_wifi_ap_stop();` };
|
|
462
449
|
default:
|
|
463
|
-
// Out of scope (genuinely not lowered):
|
|
464
|
-
//
|
|
465
|
-
//
|
|
466
|
-
//
|
|
467
|
-
// 'unsupported' declaration is honest (the validator probes these).
|
|
450
|
+
// Out of scope (genuinely not lowered): each remaining wifi.* kind has no
|
|
451
|
+
// driver/Kconfig hook on Zephyr — see the manifest's per-op reasons.
|
|
452
|
+
// Return undefined so the resolver falls back and the 'unsupported'
|
|
453
|
+
// declaration is honest (the validator probes these).
|
|
468
454
|
return undefined;
|
|
469
455
|
}
|
|
470
456
|
}
|