VSF Documented
vsf_wifi.h
Go to the documentation of this file.
1/*****************************************************************************
2 * Copyright(C)2009-2022 by VSF Team *
3 * *
4 * Licensed under the Apache License, Version 2.0 (the "License"); *
5 * you may not use this file except in compliance with the License. *
6 * You may obtain a copy of the License at *
7 * *
8 * http://www.apache.org/licenses/LICENSE-2.0 *
9 * *
10 * Unless required by applicable law or agreed to in writing, software *
11 * distributed under the License is distributed on an "AS IS" BASIS, *
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
13 * See the License for the specific language governing permissions and *
14 * limitations under the License. *
15 * *
16 ****************************************************************************/
17
18#ifndef __VSF_WIFI_H__
19#define __VSF_WIFI_H__
20
21/*============================ INCLUDES ======================================*/
22
23#include "./vsf_wifi_cfg.h"
24
25#if VSF_USE_WIFI == ENABLED
26
27#include "kernel/vsf_kernel.h"
28#include "./vsf_wifi_radio.h"
29
30#ifdef __cplusplus
31extern "C" {
32#endif
33
34/*============================ MACROS ========================================*/
35
36/*
37 * Auth / cipher constants (kept stable across chips so the application can
38 * pass a single vsf_wifi_auth_cfg_t regardless of the underlying NIC).
39 */
40enum {
47};
48
49enum {
56};
57
58#define WIFI_LINK_FLAG_CONNECTED (1 << 0)
59#define WIFI_LINK_FLAG_AUTHORIZED (1 << 1)
60
61#define WIFI_SCAN_FLAG_PRIVACY (1 << 0)
62#define WIFI_SCAN_FLAG_WPS (1 << 1)
63#define WIFI_SCAN_FLAG_WPA (1 << 2)
64#define WIFI_SCAN_FLAG_WPA2 (1 << 3)
65
66/*
67 * MLME connection state (OPEN-system auth + association). Driven entirely
68 * by the wifi layer; the chip layer only strips RX descriptors and routes
69 * mgmt frames to vsf_wifi_mlme_rx().
70 */
71enum {
72 WIFI_MLME_IDLE = 0, /* not connecting / disconnected */
73 WIFI_MLME_AUTH = 1, /* auth-req sent, awaiting auth-resp */
74 WIFI_MLME_ASSOC = 2, /* assoc-req sent, awaiting assoc-resp */
75 WIFI_MLME_4WAY = 4, /* associated, WPA2 4-way handshake running */
76 WIFI_MLME_RUN = 3, /* associated (link up) */
77 WIFI_MLME_KEY_INSTALL = 5, /* hardware key install in progress */
78 WIFI_MLME_RAW_RADIO = 6, /* raw radio mode active */
79};
80
81/*
82 * link-down reason codes passed to vsf_wifi_on_link_down(). Low values
83 * mirror common 802.11 reason codes; high values are wifi-layer specific.
84 */
85enum {
87 WIFI_REASON_AUTH_LEAVING = 3, /* deauth: STA is leaving */
88 WIFI_REASON_MIC_FAILURE = 14, /* EAPOL-Key MIC verification failed */
89 WIFI_REASON_DISASSOC_LEAVING= 8, /* disassoc: STA is leaving */
90 WIFI_REASON_LOCAL_TIMEOUT = 200, /* handshake retries exhausted */
91 WIFI_REASON_AUTH_REJECTED = 201, /* auth-resp status != 0 */
92 WIFI_REASON_ASSOC_REJECTED = 202, /* assoc-resp status != 0 */
93 WIFI_REASON_LOCAL_DISCONNECT= 203, /* user-requested disconnect */
94};
95
96/*
97 * Scratch op buffer size — caps how many ep0 register writes a parameterised
98 * chip op (set_channel / connect / disconnect ...) can issue. Static const
99 * scripts (e.g. the chip init table) are not bounded by this.
100 *
101 * Worst case today is MT76 hardware-CCMP key install: 8 WCID key + 2 WCID IV +
102 * 1 WCID attr + 8 shared key + 1 SKEY_MODE = 20 ops. Default 24 leaves headroom.
103 */
104#ifndef VSF_WIFI_CFG_SCRATCH_OPS
105# define VSF_WIFI_CFG_SCRATCH_OPS 24
106#endif
107
108/* Maximum number of channels in a single active scan (2.4 GHz + 5 GHz). */
109#ifndef VSF_WIFI_CFG_SCAN_MAX_CHANNELS
110# define VSF_WIFI_CFG_SCAN_MAX_CHANNELS 40
111#endif
112
113/*============================ TYPES =========================================*/
114
115typedef struct vsf_wifi_t vsf_wifi_t;
118
119/*
120 * Asynchronous-completion callback. Invoked exactly once per async request
121 * (script / blob / single bus op). err == VSF_ERR_NONE on success.
122 */
123typedef void (*vsf_wifi_done_t)(vsf_wifi_t *wifi, vsf_err_t err);
124
125/*
126 * Predicate used by vsf_wifi_reg_read_poll to decide whether the value just
127 * read from a register satisfies the wait condition. Called from the bus
128 * driver's EDA on every poll iteration; must be cheap and side-effect free.
129 */
130typedef bool (*vsf_wifi_reg_match_fn_t)(void *ctx, uint32_t val);
131
140 uint8_t wmm; /* 1 if the BSS advertises a WMM/WME IE */
141 /* Security parsed from the RSN IE (tag 48). auth_mode == WIFI_AUTH_OPEN
142 * means no RSN IE was present (open network / WEP). Only WPA2-PSK is
143 * recognised; pairwise/group are WIFI_CIPHER_xxx. */
147 uint16_t rsn_cap; /* RSN capabilities from AP RSN IE */
148 uint8_t ht40_width; /* 0 = 20 MHz, 1 = 40 MHz (from HT Operation IE) */
149 uint8_t ht40_plus; /* 1 = secondary channel above, 0 = below/none */
151
160
168
169/*
170 * One unit of register-access work — write `val` (LE32) to register `reg`.
171 *
172 * BBP / RF indirect writes are NOT a separate op type: chip backends pre-
173 * encode them (see RT_OP_BBP / RT_OP_RF in chip/rt28xx/vsf_wifi_rt28xx.c).
174 * This keeps the wifi state machine free of chip-specific knowledge.
175 */
180
181/*
182 * Bulk register-block payload (firmware blob, calibration table, etc.).
183 * Each chunk is shipped via reg_bus->reg_block_write (or, when the bus
184 * lacks that primitive, decomposed into multiple reg_write calls by the
185 * generic layer). `data` MUST stay valid until the completion callback
186 * fires — pointing at .rodata is fine on every supported bus.
187 */
194
195/*============================ REGISTER BUS OPS ==============================*
196 *
197 * Optional register-access abstraction for register-based WiFi chips (e.g.
198 * Ralink RT2X00). This vtable describes the chip's register semantics, NOT
199 * the underlying physical bus. It therefore MUST NOT contain bus-specific
200 * primitives such as USB ep0 vendor requests; those belong in a chip-private
201 * bus-operations structure (placed in wifi->bus_ops) when a chip really needs
202 * them.
203 *
204 * Chips that do NOT speak a register protocol — such as MediaTek mt76, which
205 * uses firmware commands over bulk/interrupt endpoints — can leave
206 * wifi->reg_bus NULL and implement their own transport inside drv->tx /
207 * drv->init / etc.
208 *
209 * Concurrency contract: at most one reg_bus call may be in flight at any
210 * time. Issuing a second call before the previous `done` callback has
211 * fired is a programming error; the bus driver MAY return VSF_ERR_NOT_
212 * AVAILABLE in that case.
213 *==========================================================================*/
214
216 /* Single-register 32-bit write. REQUIRED.
217 *
218 * Returns VSF_ERR_NONE if the write was queued; completion is delivered
219 * later via `done`. `done` may be NULL for fire-and-forget. Synchronous
220 * errors (resource exhaustion, bus busy) are returned directly without
221 * invoking `done`.
222 */
224 vsf_wifi_done_t done);
225
226 /* Single-register 32-bit read. REQUIRED.
227 *
228 * `out` is written before `done` fires; caller must keep it valid until
229 * then. Same async / error semantics as reg_write.
230 */
232 vsf_wifi_done_t done);
233
234 /* Contiguous register-block write (firmware upload / calibration table
235 * / TX descriptor RAM). OPTIONAL — when NULL the generic layer falls
236 * back to a sequence of reg_write calls.
237 *
238 * `base` is the starting register/memory address; the bus implementation
239 * is free to fragment the payload internally (USB ep0 picks 64-byte
240 * vendor-request chunks, SDIO CMD53 picks block size, etc.). `data`
241 * must stay valid until `done` fires.
242 */
244 const uint8_t *data, uint32_t len,
245 vsf_wifi_done_t done);
246
247 /* Bus-layer ready notification. OPTIONAL — called when the wifi init
248 * chain completes successfully (before vsf_wifi_on_ready). The bus
249 * driver uses this to enable the data path (e.g. submit bulk RX URBs).
250 */
251 void (*on_ready)(vsf_wifi_t *wifi);
252
253 /* Bulk data-frame transmit for register-based buses that also have a
254 * bulk data endpoint. OPTIONAL — NULL when the register bus has no data
255 * endpoint (pure ep0) or when the chip drv->tx handles data transmission
256 * itself. `data` points at a fully chip-encoded TX payload; `len` is its
257 * total length. Fire-and-forget: the bus driver owns completion internally
258 * (TX URB pool). Returns VSF_ERR_NONE when the frame was queued. */
260};
261
262/*============================ CHIP DRIVER VTABLE ============================*
263 *
264 * All chip operations are async: the chip driver builds an op-script (static
265 * .rodata or wifi->scratch_ops) and submits it via vsf_wifi_reg_run_script. The
266 * outer `done` callback fires when the entire register script has been ACKed by the
267 * device. Returning VSF_ERR_NONE from these hooks means the script was
268 * successfully queued; actual completion arrives later via `done`.
269 *
270 * The wifi layer never calls reg_bus directly — it always goes through the
271 * chip vtable. Register-based chips use the helpers vsf_wifi_reg_run_script /
272 * run_blob / reg_read / reg_read_poll; command-based chips ignore reg_bus.
273 *
274 * Two chip families are supported:
275 * - SoftMAC: the wifi core owns auth/assoc/4-way and probes each channel.
276 * - FullMAC: the firmware owns MLME; the core only forwards scan/connect and
277 * receives link-up / scan-result callbacks from the chip driver.
278 *==========================================================================*/
279
280#define VSF_WIFI_CHIP_FLAG_FULLMAC (1 << 0)
281
282#if VSF_WIFI_USE_WPA == ENABLED
283/*
284 * Optional hardware crypto backend. When a chip driver supplies crypto_ops
285 * with a non-NULL install_key, the wifi layer hands the negotiated PTK.TK /
286 * GTK to the hardware engine and assumes the chip performs CCMP in-line; the
287 * software CCMP path (wpa_hw_crypto == false) is then skipped on both TX and
288 * RX. Leaving crypto_ops (or install_key) NULL selects the built-in software
289 * CCMP fallback.
290 *
291 * install_key : program a key. key_idx 0 + pairwise == the unicast TK;
292 * key_idx 1..3 + !pairwise == a GTK. `mac` is the peer for
293 * pairwise keys, NULL for group keys.
294 * `done` is called when the register script finishes; the
295 * caller may be in an EDA or interrupt context, so
296 * install_key MUST NOT block. Returns VSF_ERR_NONE on
297 * successful submission.
298 * encrypt/decrypt : reserved per-frame overrides for chips that still need
299 * wifi-layer framing with a chip-specific tweak; NULL means
300 * "use the built-in software CCMP".
301 */
302typedef struct vsf_wifi_crypto_ops_t {
303 vsf_err_t (*install_key)(vsf_wifi_t *wifi, uint8_t key_idx, bool pairwise,
304 const uint8_t *key, uint8_t key_len,
305 const uint8_t *mac, vsf_wifi_done_t done);
307 uint16_t *len, uint16_t cap);
308 vsf_err_t (*decrypt) (vsf_wifi_t *wifi, uint8_t *dot11, uint16_t *len);
310#endif
311
313 const char *name;
314
315 /* Chip capability flags (e.g. VSF_WIFI_CHIP_FLAG_FULLMAC). */
317
318 /* Optional firmware uploader (rt2870.bin etc.). Invoked once before
319 * init() during attach. Pure ops can use vsf_wifi_reg_run_script; bulk
320 * blob uploads call vsf_wifi_reg_run_blob. Leave NULL when the chip needs
321 * no firmware. */
324 void (*fini) (vsf_wifi_t *wifi);
325
326 union {
327 /* SoftMAC hooks. Used when VSF_WIFI_CHIP_FLAG_FULLMAC is NOT set.
328 * The wifi core owns the MLME state machine. */
329 struct {
331 vsf_wifi_done_t done);
333 vsf_wifi_done_t done);
334 vsf_err_t (*set_mac_addr) (vsf_wifi_t *wifi, const uint8_t mac[6],
335 vsf_wifi_done_t done);
337 vsf_wifi_done_t done);
339 const vsf_wifi_auth_cfg_t *cfg,
340 vsf_wifi_done_t done);
342 const uint8_t bssid[6], const uint8_t *ssid,
343 uint8_t ssid_len, uint8_t channel,
344 vsf_wifi_done_t done);
347 vsf_wifi_link_info_t *info); /* sync */
348
349 /* Optional RX-frame parser used during scan. When non-NULL and
350 * the driver is currently scanning, the wifi layer routes incoming
351 * frames here instead of vsf_wifi_on_rx; the chip code extracts
352 * beacons / probe responses and emits vsf_wifi_on_scan_result(). */
353 void (*parse_rx) (vsf_wifi_t *wifi, uint8_t *frame, uint16_t len);
354
355 /* Optional TX-descriptor builder. */
356 uint16_t (*build_tx) (vsf_wifi_t *wifi, uint8_t *dst, uint16_t dst_cap,
357 const uint8_t *frame, uint16_t frame_len);
359
360 /* FullMAC hooks. Used when VSF_WIFI_CHIP_FLAG_FULLMAC IS set.
361 * The firmware owns MLME; the core only translates user API calls into
362 * chip-specific commands and waits for callbacks. */
363 struct {
365 const uint8_t *channels,
366 uint8_t num_channels, uint16_t dwell_ms,
367 vsf_wifi_done_t done);
368 vsf_err_t (*connect) (vsf_wifi_t *wifi,
369 const uint8_t bssid[6], const uint8_t *ssid,
370 uint8_t ssid_len, uint8_t channel,
371 vsf_wifi_done_t done);
374 vsf_wifi_link_info_t *info); /* sync */
376 };
377
378 /* Frame transmit hook. The wifi layer routes all outbound frames through
379 * this hook. REQUIRED; NULL returns VSF_ERR_NOT_SUPPORT from vsf_wifi_tx.
380 *
381 * For SoftMAC chips `frame` is a raw 802.11 MPDU.
382 * For FullMAC chips the meaning is chip-specific (e.g. an Ethernet frame or
383 * a chip-specific descriptor + payload). */
384 vsf_err_t (*tx) (vsf_wifi_t *wifi, const uint8_t *frame, uint16_t len);
385
386#if VSF_WIFI_USE_WPA == ENABLED
387 /* Optional hardware crypto backend (see vsf_wifi_crypto_ops_t above).
388 * NULL selects the software CCMP fallback. */
390#endif
391
392 /* Optional raw WiFi radio backend. NULL means the chip only supports
393 * the standard 802.11 station-mode interface. */
395};
396
397/*============================ APPLICATION CALLBACKS =========================*
398 *
399 * Weak hooks supplied by the application. All run in the bus driver's EDA
400 * context (not from ISR). Default no-op implementations live in vsf_wifi.c.
401 *==========================================================================*/
402
403extern void vsf_wifi_on_new (vsf_wifi_t *wifi);
404extern void vsf_wifi_on_del (vsf_wifi_t *wifi);
405extern void vsf_wifi_on_rx (vsf_wifi_t *wifi,
406 uint8_t *frame, uint16_t len);
407extern void vsf_wifi_on_ready (vsf_wifi_t *wifi);
408extern void vsf_wifi_on_scan_result(vsf_wifi_t *wifi,
409 const vsf_wifi_scan_result_t *result);
410extern void vsf_wifi_on_scan_done (vsf_wifi_t *wifi);
411extern void vsf_wifi_on_link_up (vsf_wifi_t *wifi,
412 const vsf_wifi_link_info_t *info);
413extern void vsf_wifi_on_link_down (vsf_wifi_t *wifi, uint8_t reason);
414
415/*============================ NETIF BINDING ================================*
416 *
417 * Runtime binding for a network-stack adapter (e.g. the lwIP netdrv driver
418 * in vsf_wifi_netdrv.c). Once a backend is attached via
419 * vsf_wifi_netdrv_attach(), the core delivers decrypted RX data frames to
420 * its on_rx (replacing the weak vsf_wifi_on_rx hook), and additionally
421 * delivers link up/down events to its on_link_up / on_link_down. Link
422 * events still also fire the weak vsf_wifi_on_link_up / vsf_wifi_on_link_down
423 * hooks: those are control-plane notifications (e.g. unblocking a connect
424 * command) and run alongside the backend's data-plane handling. With no
425 * backend attached only the weak hooks are used (back-compat with the
426 * diagnostic commands). All callbacks run in the bus driver's EDA context,
427 * exactly like the weak hooks. `on_rx` receives a naked, decrypted 802.11
428 * data frame (FC .. payload); the backend is responsible for any 802.11 <->
429 * Ethernet framing. */
430typedef struct vsf_wifi_netif_ops_t {
431 void (*on_rx) (void *param, vsf_wifi_t *wifi,
432 uint8_t *frame, uint16_t len);
433 void (*on_link_up) (void *param, vsf_wifi_t *wifi,
434 const vsf_wifi_link_info_t *info);
435 void (*on_link_down)(void *param, vsf_wifi_t *wifi, uint8_t reason);
437
438/* Register / unregister a netif backend. `ops` (and the storage it points
439 * at) must stay valid until detach; `param` is passed back verbatim to each
440 * callback. Passing ops == NULL is equivalent to detach. */
442 const vsf_wifi_netif_ops_t *ops, void *param);
444
445/*============================ USER API ======================================*/
446
447/* Inspection. */
449const char * vsf_wifi_get_chip_name(vsf_wifi_t *wifi);
450bool vsf_wifi_is_ready (vsf_wifi_t *wifi);
451
452/* BSS Max Idle Period advertised by the AP in the assoc-resp (IE 90).
453 * Returned in units of 1000 TU; 0 means the AP did not advertise it. */
455
456/* Per-device MAC address discovered during chip bring-up (eFuse / EEPROM
457 * read). Returns a pointer to a 6-byte array inside the wifi struct;
458 * all-zero until the chip driver finishes its EEPROM stage. The pointer
459 * stays valid for the lifetime of the wifi instance. */
460const uint8_t * vsf_wifi_get_mac (vsf_wifi_t *wifi);
461
462/* Mutation. Calls return VSF_ERR_NOT_READY before vsf_wifi_on_ready,
463 * VSF_ERR_NOT_AVAILABLE while a scan is in progress, and the chip driver's
464 * own error otherwise. All async — completion is signalled by either the
465 * relevant on_xxx callback or by the next observable side effect (RSSI,
466 * link_info, etc.). */
467void vsf_wifi_set_channel (vsf_wifi_t *wifi, uint8_t channel);
468vsf_err_t vsf_wifi_set_mac (vsf_wifi_t *wifi, const uint8_t mac[6]);
471 const vsf_wifi_auth_cfg_t *cfg);
472
473/*
474 * Active scan: hop through the supplied channel list, dwelling `dwell_ms`
475 * milliseconds on each channel. Beacon / probe-response frames are routed
476 * to the chip parser (drv->parse_rx) which feeds vsf_wifi_on_scan_result.
477 * vsf_wifi_on_scan_done() is fired exactly once when every channel has
478 * been visited. dwell_ms == 0 falls back to a sensible default (120 ms).
479 */
481 const uint8_t *channels,
482 uint8_t num_channels, uint16_t dwell_ms);
484
485/* Channel bandwidth hints used by set_channel / connect. Not all chip
486 * drivers support 40/80 MHz; unsupported values fall back to 20 MHz. */
487#define WIFI_BW_20MHZ 0
488#define WIFI_BW_40MHZ_PLUS 1 /* primary lower, extension above */
489#define WIFI_BW_40MHZ_MINUS 2 /* primary upper, extension below */
490#define WIFI_BW_80MHZ 3
491
493
495 const uint8_t bssid[6],
496 const uint8_t *ssid, uint8_t ssid_len,
497 uint8_t channel);
501
502/*
503 * Transmit a raw 802.11 frame. The chip driver (drv->tx) is responsible for
504 * building the on-wire TX descriptor and shipping it over the bus. Returns
505 * VSF_ERR_NOT_READY before vsf_wifi_on_ready, VSF_ERR_NOT_SUPPORTED when the
506 * chip driver has no tx hook, or a bus-level error. Fire-and-forget: there
507 * is no per-frame completion callback (chip drivers use TX_STA_FIFO /
508 * TX_STA_CNT to inspect results). */
510 const uint8_t *frame, uint16_t len);
511
512/*============================ REGISTER-BUS LAYER API =========================*
513 *
514 * These are exported so a bus driver can drive the wifi state machine.
515 * Application code does not call them directly.
516 *==========================================================================*/
517
518/*
519 * One-shot construction. After this call:
520 * - wifi->drv is bound;
521 * - wifi->reg_bus is bound (may be NULL for non-register-based chips);
522 * - all state fields are zero / cleared;
523 * - scan timer is initialised but not armed;
524 * - the wifi is NOT started yet (call vsf_wifi_start when ready).
525 *
526 * `post_eda` is the EDA on which the wifi layer will post follow-up events
527 * (scan-hop callbacks). Typically the bus driver passes its own EDA so
528 * that timer-driven hops are handled in the same context as bus completions.
529 */
530void vsf_wifi_init(vsf_wifi_t *wifi,
531 const vsf_wifi_chip_drv_t *drv,
532 const vsf_wifi_reg_bus_t *reg_bus,
533 vsf_eda_t *post_eda);
534
535/*
536 * Kick off the chip bring-up chain (firmware_load -> init -> set_rx_filter).
537 * On success vsf_wifi_on_ready fires when the chain finishes; on any error
538 * the bus driver's `on_attach_fail` (passed via vsf_wifi_set_attach_fail)
539 * is invoked so it can tear down the device.
540 *
541 * Must be called from the bus driver's EDA context, typically on
542 * VSF_EVT_INIT.
543 */
544void vsf_wifi_start(vsf_wifi_t *wifi);
545
546/*
547 * Bus driver tear-down. Cancels pending scans / scripts, marks the wifi
548 * as disconnecting so no further callbacks fire, and invokes the chip
549 * driver's fini hook. After this call the wifi struct can be freed.
550 */
551void vsf_wifi_fini(vsf_wifi_t *wifi);
552
553/*
554 * Set a callback that the wifi layer invokes when the bring-up chain or a
555 * scan reports an unrecoverable error. The bus driver typically removes
556 * the device interface from inside this hook. Default: NULL (errors are
557 * logged but otherwise ignored).
558 */
559typedef void (*vsf_wifi_attach_fail_t)(vsf_wifi_t *wifi, vsf_err_t err);
561
562/* Bus driver hands an inbound RX frame to the wifi layer; the layer routes
563 * it to drv->parse_rx (during scan) or vsf_wifi_on_rx (otherwise). */
564void vsf_wifi_on_rx_internal(vsf_wifi_t *wifi, uint8_t *frame, uint16_t len);
565
566/* MLME management-frame entry point. The chip parser (drv->parse_rx) calls
567 * this with a de-descriptored, naked 802.11 management frame (starting at
568 * the FC field) when its subtype is auth / assoc-resp / deauth / disassoc.
569 * The wifi-layer MLME state machine advances the OPEN-system connection. */
570void vsf_wifi_mlme_rx(vsf_wifi_t *wifi, const uint8_t *dot11, uint16_t len);
571
572/* Data-frame entry point. The chip parser (drv->parse_rx) calls this with a
573 * de-descriptored, naked 802.11 data frame (starting at the FC field) once
574 * the link is associated (mlme_state RUN / 4WAY). The wifi layer parses the
575 * data header, detects EAPOL (LLC/SNAP + ethertype 0x888E) for the 4-way
576 * handshake, and forwards decrypted business payloads to vsf_wifi_on_rx. */
577void vsf_wifi_data_rx(vsf_wifi_t *wifi, const uint8_t *dot11, uint16_t len);
578
579#if VSF_WIFI_USE_WPA == ENABLED
580/* Helpers exported to the WPA 4-way handshake (vsf_wifi_wpa.c). The wifi
581 * layer owns the MLME state, the retry timer and the chip TX path; the WPA
582 * module owns EAPOL-Key parsing / building and key derivation, and drives
583 * the connection through these calls:
584 * - mlme_tx : transmit a fully formed 802.11 frame (EAPOL).
585 * - mlme_arm_timer : (re)arm the handshake timeout.
586 * - handshake_done : keys installed -> state RUN + vsf_wifi_on_link_up.
587 * - handshake_fail : abort the handshake -> link down with `reason`. */
588vsf_err_t vsf_wifi_mlme_tx(vsf_wifi_t *wifi, const uint8_t *frame, uint16_t len);
592#endif
593
594/* Bus driver invokes this from its EDA when the wifi-posted scan-hop event
595 * lands; the wifi layer advances to the next channel or finishes the scan. */
597
598/* Bus driver invokes this from its EDA when the wifi-posted MLME-retry event
599 * lands; the wifi layer retransmits the current handshake frame (auth-req /
600 * assoc-req) or declares a link-down timeout once retries are exhausted.
601 * Bounced through the bus EDA (like scan-hop) so the TX runs in the same
602 * context as bus completions. */
604
605/* Custom EDA event used by vsf_wifi to trigger a scan hop on the bus EDA.
606 * The bus driver's evt-handler must dispatch this value to
607 * vsf_wifi_on_scan_hop_evt(). */
608#define VSF_WIFI_EVT_SCAN_HOP (VSF_EVT_USER + 0x40)
609
610/* Custom EDA event used by vsf_wifi to trigger an MLME handshake retransmit
611 * on the bus EDA. The bus driver's evt-handler must dispatch this value to
612 * vsf_wifi_on_mlme_retry_evt(). */
613#define VSF_WIFI_EVT_MLME_RETRY (VSF_EVT_USER + 0x41)
614
615/*============================ CHIP <-> WIFI INTERNAL API ====================*/
616
617/*
618 * Run a sequence of register writes asynchronously.
619 *
620 * ops : array of (reg, val) pairs. May point to .rodata or to
621 * wifi->scratch_ops. Caller MUST keep `ops` valid until
622 * `done` fires.
623 * count : number of ops to execute (must be > 0 for a real submission).
624 * done : completion callback (NULL = fire-and-forget).
625 *
626 * Returns VSF_ERR_NONE on accepted submission (completion via `done`),
627 * VSF_ERR_NOT_AVAILABLE when another script / blob is in flight, or a bus-
628 * level synchronous error otherwise.
629 */
631 const vsf_wifi_reg_op_t *ops, uint16_t count,
632 vsf_wifi_done_t done);
633
634/*
635 * Stream a contiguous register-block payload. Internally calls
636 * reg_bus->reg_block_write when available; otherwise decomposes into
637 * ceil(len / 4) reg_write calls.
638 *
639 * Same concurrency rules as vsf_wifi_reg_run_script: at most one script /
640 * blob in flight per wifi.
641 */
643 const vsf_wifi_reg_blob_t *blob,
644 vsf_wifi_done_t done);
645
646/*
647 * Periodically read `reg` until `match(val)` returns true.
648 *
649 * reg : MAC register to poll.
650 * match : predicate; the read value is fed in on every iteration.
651 * max_retry : upper bound on read attempts (>= 1). The first read
652 * counts as attempt #1.
653 * interval_ms : delay between consecutive reads. 0 means "re-issue
654 * immediately on completion" (use only if the bus already
655 * paces reads, e.g. USB ep0 vendor request).
656 * done : completion callback.
657 * VSF_ERR_NONE : predicate matched.
658 * VSF_ERR_TIMEOUT : retries exhausted without match.
659 * other : bus-level error.
660 *
661 * Same single-flight constraint as run_script / run_blob.
662 */
664 vsf_wifi_reg_match_fn_t match, void *match_ctx,
665 uint16_t max_retry, uint16_t interval_ms,
666 vsf_wifi_done_t done);
667
668/*
669 * Single 32-bit register read. The result is stored at *out before
670 * `done` fires; caller must keep `out` valid until then. Same single-
671 * flight constraint as run_script / run_blob / run_read_poll.
672 */
674 vsf_wifi_done_t done);
675
676#if VSF_WIFI_USE_WPA == ENABLED
677/* CCMP software-encapsulate a plaintext 802.11 data frame `frame` (length
678 * `len`) into `out` (capacity `cap`). The 8-byte CCMP header is inserted
679 * immediately after the 802.11 header; the Protected Frame bit is set.
680 * `pn` is the 48-bit packet number used for this MPDU (little-endian);
681 * pass NULL to use the per-wifi TX PN counter.
682 * Returns the encrypted MPDU length, or 0 on failure.
683 *
684 * This is a public helper for chip drivers that need to software-encrypt
685 * specific frames even when hardware crypto is enabled (e.g. MT76 multicast
686 * frames). */
688 const uint8_t *frame, uint16_t len, uint8_t *out, uint16_t cap,
689 uint8_t pn[6]);
690#endif
691
692/* Per-wifi scratch op buffer (shared by parameterised chip ops). */
694
695/*============================ CHIP-SPECIFIC HEADERS =========================*
696 *
697 * Concrete chip families live in chip/xxx/ and expose their own firmware
698 * symbols, logging helpers and (if needed) public constants. The generic
699 * wifi header only pulls in the chips that are enabled at compile time.
700 *===========================================================================*/
701
702#if VSF_WIFI_USE_RT28XX == ENABLED
704#endif
705
706#if VSF_WIFI_USE_MT76 == ENABLED
708#endif
709
710#if VSF_WIFI_USE_AIC8800D == ENABLED
712#endif
713
714/*============================ LOGGING HELPERS ===============================*
715 *
716 * Compile-time log level gates for the WiFi subsystem and its sub-modules.
717 * Levels are defined in vsf_wifi_cfg.h; sub-module macros fall back to the
718 * global VSF_WIFI_CFG_LOG_LEVEL when not explicitly set.
719 *==========================================================================*/
720
721#if VSF_WIFI_CFG_LOG_LEVEL >= 1
722# define vsf_wifi_trace_error(...) vsf_trace_error(__VA_ARGS__)
723#else
724# define vsf_wifi_trace_error(...) ((void)0)
725#endif
726
727#if VSF_WIFI_CFG_LOG_LEVEL >= 2
728# define vsf_wifi_trace_info(...) vsf_trace_info(__VA_ARGS__)
729#else
730# define vsf_wifi_trace_info(...) ((void)0)
731#endif
732
733#if VSF_WIFI_CFG_LOG_LEVEL >= 4
734# define vsf_wifi_trace_debug(...) vsf_trace_info(__VA_ARGS__)
735#else
736# define vsf_wifi_trace_debug(...) ((void)0)
737#endif
738
739
740#ifdef __cplusplus
741}
742#endif
743
744#endif // VSF_USE_WIFI
745#endif // __VSF_WIFI_H__
vsf_err_t
Definition __type.h:42
bool
Definition type.h:60
Definition vsf_eda.h:769
struct ieee80211_ext_chansw_ie data
Definition ieee80211.h:80
u8 bssid[ETH_ALEN]
Definition ieee80211.h:2
unsigned short uint16_t
Definition stdint.h:7
unsigned uint32_t
Definition stdint.h:9
unsigned char uint8_t
Definition stdint.h:5
signed char int8_t
Definition stdint.h:4
Definition vsf_wifi.h:161
uint8_t pairwise_cipher
Definition vsf_wifi.h:163
uint8_t psk[32]
Definition vsf_wifi.h:165
uint8_t psk_len
Definition vsf_wifi.h:166
uint8_t group_cipher
Definition vsf_wifi.h:164
uint8_t auth_mode
Definition vsf_wifi.h:162
Definition vsf_wifi.h:312
vsf_err_t(* set_channel)(vsf_wifi_t *wifi, uint8_t channel, vsf_wifi_done_t done)
Definition vsf_wifi.h:330
vsf_err_t(* disconnect)(vsf_wifi_t *wifi, vsf_wifi_done_t done)
Definition vsf_wifi.h:345
uint32_t flags
Definition vsf_wifi.h:316
void(* parse_rx)(vsf_wifi_t *wifi, uint8_t *frame, uint16_t len)
Definition vsf_wifi.h:353
vsf_err_t(* set_bssid)(vsf_wifi_t *wifi, const uint8_t bssid[6], vsf_wifi_done_t done)
Definition vsf_wifi.h:336
const vsf_wifi_radio_ops_t * radio_ops
Definition vsf_wifi.h:394
struct vsf_wifi_chip_drv_t::@344::@347 fullmac
vsf_err_t(* get_link_info)(vsf_wifi_t *wifi, vsf_wifi_link_info_t *info)
Definition vsf_wifi.h:346
void(* fini)(vsf_wifi_t *wifi)
Definition vsf_wifi.h:324
vsf_err_t(* tx)(vsf_wifi_t *wifi, const uint8_t *frame, uint16_t len)
Definition vsf_wifi.h:384
vsf_err_t(* set_mac_addr)(vsf_wifi_t *wifi, const uint8_t mac[6], vsf_wifi_done_t done)
Definition vsf_wifi.h:334
const char * name
Definition vsf_wifi.h:313
const vsf_wifi_crypto_ops_t * crypto_ops
Definition vsf_wifi.h:389
vsf_err_t(* connect)(vsf_wifi_t *wifi, const uint8_t bssid[6], const uint8_t *ssid, uint8_t ssid_len, uint8_t channel, vsf_wifi_done_t done)
Definition vsf_wifi.h:341
uint16_t(* build_tx)(vsf_wifi_t *wifi, uint8_t *dst, uint16_t dst_cap, const uint8_t *frame, uint16_t frame_len)
Definition vsf_wifi.h:356
struct vsf_wifi_chip_drv_t::@344::@346 softmac
vsf_err_t(* firmware_load)(vsf_wifi_t *wifi, vsf_wifi_done_t done)
Definition vsf_wifi.h:322
vsf_err_t(* init)(vsf_wifi_t *wifi, vsf_wifi_done_t done)
Definition vsf_wifi.h:323
vsf_err_t(* set_auth_mode)(vsf_wifi_t *wifi, const vsf_wifi_auth_cfg_t *cfg, vsf_wifi_done_t done)
Definition vsf_wifi.h:338
vsf_err_t(* scan)(vsf_wifi_t *wifi, const uint8_t *channels, uint8_t num_channels, uint16_t dwell_ms, vsf_wifi_done_t done)
Definition vsf_wifi.h:364
vsf_err_t(* set_rx_filter)(vsf_wifi_t *wifi, uint32_t mask, vsf_wifi_done_t done)
Definition vsf_wifi.h:332
Definition vsf_wifi.h:302
vsf_err_t(* install_key)(vsf_wifi_t *wifi, uint8_t key_idx, bool pairwise, const uint8_t *key, uint8_t key_len, const uint8_t *mac, vsf_wifi_done_t done)
Definition vsf_wifi.h:303
vsf_err_t(* encrypt)(vsf_wifi_t *wifi, uint8_t *dot11, uint16_t *len, uint16_t cap)
Definition vsf_wifi.h:306
vsf_err_t(* decrypt)(vsf_wifi_t *wifi, uint8_t *dot11, uint16_t *len)
Definition vsf_wifi.h:308
Definition vsf_wifi.h:430
void(* on_link_down)(void *param, vsf_wifi_t *wifi, uint8_t reason)
Definition vsf_wifi.h:435
void(* on_rx)(void *param, vsf_wifi_t *wifi, uint8_t *frame, uint16_t len)
Definition vsf_wifi.h:431
void(* on_link_up)(void *param, vsf_wifi_t *wifi, const vsf_wifi_link_info_t *info)
Definition vsf_wifi.h:433
Definition vsf_wifi_radio.h:59
Definition vsf_wifi.h:188
uint16_t chunk_size
Definition vsf_wifi.h:192
uint32_t base_reg
Definition vsf_wifi.h:191
uint32_t len
Definition vsf_wifi.h:190
const uint8_t * data
Definition vsf_wifi.h:189
Definition vsf_wifi.h:215
vsf_err_t(* reg_read)(vsf_wifi_t *wifi, uint32_t reg, uint32_t *out, vsf_wifi_done_t done)
Definition vsf_wifi.h:231
vsf_err_t(* reg_block_write)(vsf_wifi_t *wifi, uint32_t base, const uint8_t *data, uint32_t len, vsf_wifi_done_t done)
Definition vsf_wifi.h:243
vsf_err_t(* data_tx)(vsf_wifi_t *wifi, uint8_t *data, uint16_t len)
Definition vsf_wifi.h:259
vsf_err_t(* reg_write)(vsf_wifi_t *wifi, uint32_t reg, uint32_t val, vsf_wifi_done_t done)
Definition vsf_wifi.h:223
void(* on_ready)(vsf_wifi_t *wifi)
Definition vsf_wifi.h:251
Definition vsf_wifi.h:176
uint32_t reg
Definition vsf_wifi.h:177
uint32_t val
Definition vsf_wifi.h:178
Definition vsf_wifi.h:132
int8_t rssi
Definition vsf_wifi.h:137
uint16_t rsn_cap
Definition vsf_wifi.h:147
uint8_t ssid[33]
Definition vsf_wifi.h:134
uint8_t ht40_width
Definition vsf_wifi.h:148
uint8_t ht40_plus
Definition vsf_wifi.h:149
uint16_t capability
Definition vsf_wifi.h:138
uint8_t auth_mode
Definition vsf_wifi.h:144
uint8_t wmm
Definition vsf_wifi.h:140
uint8_t group_cipher
Definition vsf_wifi.h:146
uint8_t channel
Definition vsf_wifi.h:136
uint8_t bssid[6]
Definition vsf_wifi.h:133
uint8_t pairwise_cipher
Definition vsf_wifi.h:145
uint8_t flags
Definition vsf_wifi.h:139
uint8_t ssid_len
Definition vsf_wifi.h:135
Definition vsf_wifi_priv.h:57
class vsf_$ * reg
bool vsf_wifi_is_ready(vsf_wifi_t *wifi)
Definition vsf_wifi.c:1824
void vsf_wifi_on_del(vsf_wifi_t *wifi)
Definition vsf_wifi.c:101
void vsf_wifi_on_ready(vsf_wifi_t *wifi)
Definition vsf_wifi.c:108
bool(* vsf_wifi_reg_match_fn_t)(void *ctx, uint32_t val)
Definition vsf_wifi.h:130
void vsf_wifi_data_rx(vsf_wifi_t *wifi, const uint8_t *dot11, uint16_t len)
Definition vsf_wifi.c:1053
vsf_err_t vsf_wifi_reg_run_script(vsf_wifi_t *wifi, const vsf_wifi_reg_op_t *ops, uint16_t count, vsf_wifi_done_t done)
Definition vsf_wifi.c:354
vsf_err_t vsf_wifi_scan(vsf_wifi_t *wifi, const uint8_t *channels, uint8_t num_channels, uint16_t dwell_ms)
Definition vsf_wifi.c:1917
@ WIFI_CIPHER_TKIP
Definition vsf_wifi.h:53
@ WIFI_CIPHER_TKIP_CCMP
Definition vsf_wifi.h:55
@ WIFI_CIPHER_CCMP
Definition vsf_wifi.h:54
@ WIFI_CIPHER_NONE
Definition vsf_wifi.h:50
@ WIFI_CIPHER_WEP40
Definition vsf_wifi.h:51
@ WIFI_CIPHER_WEP104
Definition vsf_wifi.h:52
vsf_err_t vsf_wifi_disconnect(vsf_wifi_t *wifi)
Definition vsf_wifi.c:2036
void vsf_wifi_on_rx_internal(vsf_wifi_t *wifi, uint8_t *frame, uint16_t len)
Definition vsf_wifi.c:773
struct vsf_wifi_link_info_t vsf_wifi_link_info_t
const uint8_t * vsf_wifi_get_mac(vsf_wifi_t *wifi)
Definition vsf_wifi.c:1839
struct vsf_wifi_netif_ops_t vsf_wifi_netif_ops_t
void vsf_wifi_mlme_handshake_fail(vsf_wifi_t *wifi, uint8_t reason)
Definition vsf_wifi.c:2298
struct vsf_wifi_scan_result_t vsf_wifi_scan_result_t
vsf_err_t vsf_wifi_reg_run_blob(vsf_wifi_t *wifi, const vsf_wifi_reg_blob_t *blob, vsf_wifi_done_t done)
Definition vsf_wifi.c:433
vsf_err_t vsf_wifi_set_bssid(vsf_wifi_t *wifi, const uint8_t bssid[6])
Definition vsf_wifi.c:1882
void vsf_wifi_start(vsf_wifi_t *wifi)
Definition vsf_wifi.c:658
uint8_t vsf_wifi_get_channel(vsf_wifi_t *wifi)
Definition vsf_wifi.c:1829
vsf_err_t vsf_wifi_reg_read_poll(vsf_wifi_t *wifi, uint32_t reg, vsf_wifi_reg_match_fn_t match, void *match_ctx, uint16_t max_retry, uint16_t interval_ms, vsf_wifi_done_t done)
Definition vsf_wifi.c:557
const char * vsf_wifi_get_chip_name(vsf_wifi_t *wifi)
Definition vsf_wifi.c:1834
void vsf_wifi_on_mlme_retry_evt(vsf_wifi_t *wifi)
Definition vsf_wifi.c:1664
void vsf_wifi_mlme_rx(vsf_wifi_t *wifi, const uint8_t *dot11, uint16_t len)
Definition vsf_wifi.c:1700
void vsf_wifi_on_link_down(vsf_wifi_t *wifi, uint8_t reason)
Definition vsf_wifi.c:123
void vsf_wifi_on_scan_hop_evt(vsf_wifi_t *wifi)
Definition vsf_wifi.c:1301
vsf_err_t vsf_wifi_mlme_tx(vsf_wifi_t *wifi, const uint8_t *frame, uint16_t len)
Definition vsf_wifi.c:2138
vsf_err_t vsf_wifi_set_auth_mode(vsf_wifi_t *wifi, const vsf_wifi_auth_cfg_t *cfg)
Definition vsf_wifi.c:1892
void vsf_wifi_on_rx(vsf_wifi_t *wifi, uint8_t *frame, uint16_t len)
Definition vsf_wifi.c:104
struct vsf_wifi_auth_cfg_t vsf_wifi_auth_cfg_t
void vsf_wifi_netdrv_attach(vsf_wifi_t *wifi, const vsf_wifi_netif_ops_t *ops, void *param)
Definition vsf_wifi.c:133
void vsf_wifi_set_channel(vsf_wifi_t *wifi, uint8_t channel)
Definition vsf_wifi.c:1849
void vsf_wifi_mlme_arm_timer(vsf_wifi_t *wifi, uint16_t ms)
Definition vsf_wifi.c:2143
vsf_wifi_reg_op_t * vsf_wifi_reg_get_scratch_ops(vsf_wifi_t *wifi)
Definition vsf_wifi.c:476
void vsf_wifi_fini(vsf_wifi_t *wifi)
Definition vsf_wifi.c:744
vsf_err_t vsf_wifi_reg_read(vsf_wifi_t *wifi, uint32_t reg, uint32_t *out, vsf_wifi_done_t done)
Definition vsf_wifi.c:604
void vsf_wifi_on_link_up(vsf_wifi_t *wifi, const vsf_wifi_link_info_t *info)
Definition vsf_wifi.c:119
void vsf_wifi_netdrv_detach(vsf_wifi_t *wifi)
Definition vsf_wifi.c:140
void vsf_wifi_on_scan_result(vsf_wifi_t *wifi, const vsf_wifi_scan_result_t *result)
Definition vsf_wifi.c:111
vsf_err_t vsf_wifi_get_link_info(vsf_wifi_t *wifi, vsf_wifi_link_info_t *info)
Definition vsf_wifi.c:2063
void vsf_wifi_on_new(vsf_wifi_t *wifi)
Definition vsf_wifi.c:98
struct vsf_wifi_reg_blob_t vsf_wifi_reg_blob_t
void vsf_wifi_on_scan_done(vsf_wifi_t *wifi)
Definition vsf_wifi.c:116
void vsf_wifi_set_attach_fail(vsf_wifi_t *wifi, vsf_wifi_attach_fail_t hook)
Definition vsf_wifi.c:653
vsf_err_t vsf_wifi_tx(vsf_wifi_t *wifi, const uint8_t *frame, uint16_t len)
Definition vsf_wifi.c:2109
void(* vsf_wifi_done_t)(vsf_wifi_t *wifi, vsf_err_t err)
Definition vsf_wifi.h:123
vsf_err_t vsf_wifi_connect(vsf_wifi_t *wifi, const uint8_t bssid[6], const uint8_t *ssid, uint8_t ssid_len, uint8_t channel)
Definition vsf_wifi.c:1976
@ WIFI_REASON_DISASSOC_LEAVING
Definition vsf_wifi.h:89
@ WIFI_REASON_AUTH_REJECTED
Definition vsf_wifi.h:91
@ WIFI_REASON_LOCAL_TIMEOUT
Definition vsf_wifi.h:90
@ WIFI_REASON_ASSOC_REJECTED
Definition vsf_wifi.h:92
@ WIFI_REASON_MIC_FAILURE
Definition vsf_wifi.h:88
@ WIFI_REASON_UNSPECIFIED
Definition vsf_wifi.h:86
@ WIFI_REASON_LOCAL_DISCONNECT
Definition vsf_wifi.h:93
@ WIFI_REASON_AUTH_LEAVING
Definition vsf_wifi.h:87
uint16_t vsf_wifi_get_bss_max_idle_period(vsf_wifi_t *wifi)
Definition vsf_wifi.c:1844
struct vsf_wifi_reg_op_t vsf_wifi_reg_op_t
struct vsf_wifi_crypto_ops_t vsf_wifi_crypto_ops_t
void vsf_wifi_set_channel_bw(vsf_wifi_t *wifi, uint8_t bw)
Definition vsf_wifi.c:1864
void vsf_wifi_mlme_handshake_done(vsf_wifi_t *wifi)
Definition vsf_wifi.c:2268
@ WIFI_AUTH_WPA2_PSK
Definition vsf_wifi.h:44
@ WIFI_AUTH_WPA_WPA2_PSK
Definition vsf_wifi.h:45
@ WIFI_AUTH_WEP
Definition vsf_wifi.h:42
@ WIFI_AUTH_WPA2_ENTERPRISE
Definition vsf_wifi.h:46
@ WIFI_AUTH_WPA_PSK
Definition vsf_wifi.h:43
@ WIFI_AUTH_OPEN
Definition vsf_wifi.h:41
void vsf_wifi_init(vsf_wifi_t *wifi, const vsf_wifi_chip_drv_t *drv, const vsf_wifi_reg_bus_t *reg_bus, vsf_eda_t *post_eda)
Definition vsf_wifi.c:627
vsf_err_t vsf_wifi_scan_stop(vsf_wifi_t *wifi)
Definition vsf_wifi.c:1963
@ WIFI_MLME_ASSOC
Definition vsf_wifi.h:74
@ WIFI_MLME_IDLE
Definition vsf_wifi.h:72
@ WIFI_MLME_AUTH
Definition vsf_wifi.h:73
@ WIFI_MLME_KEY_INSTALL
Definition vsf_wifi.h:77
@ WIFI_MLME_RUN
Definition vsf_wifi.h:76
@ WIFI_MLME_4WAY
Definition vsf_wifi.h:75
@ WIFI_MLME_RAW_RADIO
Definition vsf_wifi.h:78
vsf_err_t vsf_wifi_set_mac(vsf_wifi_t *wifi, const uint8_t mac[6])
Definition vsf_wifi.c:1872
void(* vsf_wifi_attach_fail_t)(vsf_wifi_t *wifi, vsf_err_t err)
Definition vsf_wifi.h:559
uint16_t vsf_wifi_ccmp_encap_with_pn(vsf_wifi_t *wifi, const uint8_t *frame, uint16_t len, uint8_t *out, uint16_t cap, uint8_t pn[6])
Definition vsf_wifi.c:957
Generated from commit: vsfteam/vsf@5de27dd