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 to
286 * the hardware engine and assumes the chip performs CCMP in-line for
287 * UNICAST frames (wpa_hw_crypto == true; software TX encap / RX decap
288 * skipped for unicast). HYBRID: the GTK stays in software - group frames
289 * are software-CCMP-encapped/decapped on TX/RX even in this mode, because
290 * chip group-key decrypt proved unreliable on some APs. Leaving crypto_ops
291 * (or install_key) NULL selects the built-in software CCMP fallback.
292 *
293 * install_key : program a key. key_idx 0 + pairwise == the unicast TK;
294 * key_idx 1..3 + !pairwise == a GTK. `mac` is the peer for
295 * pairwise keys, NULL for group keys.
296 * `done` is called when the register script finishes; the
297 * caller may be in an EDA or interrupt context, so
298 * install_key MUST NOT block. Returns VSF_ERR_NONE on
299 * successful submission.
300 * encrypt/decrypt : reserved per-frame overrides for chips that still need
301 * wifi-layer framing with a chip-specific tweak; NULL means
302 * "use the built-in software CCMP".
303 */
304typedef struct vsf_wifi_crypto_ops_t {
305 vsf_err_t (*install_key)(vsf_wifi_t *wifi, uint8_t key_idx, bool pairwise,
306 const uint8_t *key, uint8_t key_len,
307 const uint8_t *mac, vsf_wifi_done_t done);
309 uint16_t *len, uint16_t cap);
310 vsf_err_t (*decrypt) (vsf_wifi_t *wifi, uint8_t *dot11, uint16_t *len);
312#endif
313
315 const char *name;
316
317 /* Chip capability flags (e.g. VSF_WIFI_CHIP_FLAG_FULLMAC). */
319
320 /* Optional firmware uploader (rt2870.bin etc.). Invoked once before
321 * init() during attach. Pure ops can use vsf_wifi_reg_run_script; bulk
322 * blob uploads call vsf_wifi_reg_run_blob. Leave NULL when the chip needs
323 * no firmware. */
326 void (*fini) (vsf_wifi_t *wifi);
327
328 union {
329 /* SoftMAC hooks. Used when VSF_WIFI_CHIP_FLAG_FULLMAC is NOT set.
330 * The wifi core owns the MLME state machine. */
331 struct {
333 vsf_wifi_done_t done);
335 vsf_wifi_done_t done);
336 vsf_err_t (*set_mac_addr) (vsf_wifi_t *wifi, const uint8_t mac[6],
337 vsf_wifi_done_t done);
339 vsf_wifi_done_t done);
341 const vsf_wifi_auth_cfg_t *cfg,
342 vsf_wifi_done_t done);
344 const uint8_t bssid[6], const uint8_t *ssid,
345 uint8_t ssid_len, uint8_t channel,
346 vsf_wifi_done_t done);
349 vsf_wifi_link_info_t *info); /* sync */
350
351 /* Optional RX-frame parser used during scan. When non-NULL and
352 * the driver is currently scanning, the wifi layer routes incoming
353 * frames here instead of vsf_wifi_on_rx; the chip code extracts
354 * beacons / probe responses and emits vsf_wifi_on_scan_result(). */
355 void (*parse_rx) (vsf_wifi_t *wifi, uint8_t *frame, uint16_t len);
356
357 /* Optional TX-descriptor builder. */
358 uint16_t (*build_tx) (vsf_wifi_t *wifi, uint8_t *dst, uint16_t dst_cap,
359 const uint8_t *frame, uint16_t frame_len);
361
362 /* FullMAC hooks. Used when VSF_WIFI_CHIP_FLAG_FULLMAC IS set.
363 * The firmware owns MLME; the core only translates user API calls into
364 * chip-specific commands and waits for callbacks. */
365 struct {
367 const uint8_t *channels,
368 uint8_t num_channels, uint16_t dwell_ms,
369 vsf_wifi_done_t done);
370 vsf_err_t (*connect) (vsf_wifi_t *wifi,
371 const uint8_t bssid[6], const uint8_t *ssid,
372 uint8_t ssid_len, uint8_t channel,
373 vsf_wifi_done_t done);
376 vsf_wifi_link_info_t *info); /* sync */
378 };
379
380 /* Frame transmit hook. The wifi layer routes all outbound frames through
381 * this hook. REQUIRED; NULL returns VSF_ERR_NOT_SUPPORT from vsf_wifi_tx.
382 *
383 * For SoftMAC chips `frame` is a raw 802.11 MPDU.
384 * For FullMAC chips the meaning is chip-specific (e.g. an Ethernet frame or
385 * a chip-specific descriptor + payload). */
386 vsf_err_t (*tx) (vsf_wifi_t *wifi, const uint8_t *frame, uint16_t len);
387
388#if VSF_WIFI_USE_WPA == ENABLED
389 /* Optional hardware crypto backend (see vsf_wifi_crypto_ops_t above).
390 * NULL selects the software CCMP fallback. */
392#endif
393
394 /* Optional raw WiFi radio backend. NULL means the chip only supports
395 * the standard 802.11 station-mode interface. */
397};
398
399/*============================ APPLICATION CALLBACKS =========================*
400 *
401 * Weak hooks supplied by the application. All run in the bus driver's EDA
402 * context (not from ISR). Default no-op implementations live in vsf_wifi.c.
403 *==========================================================================*/
404
405extern void vsf_wifi_on_new (vsf_wifi_t *wifi);
406extern void vsf_wifi_on_del (vsf_wifi_t *wifi);
407extern void vsf_wifi_on_rx (vsf_wifi_t *wifi,
408 uint8_t *frame, uint16_t len);
409extern void vsf_wifi_on_ready (vsf_wifi_t *wifi);
410extern void vsf_wifi_on_scan_result(vsf_wifi_t *wifi,
411 const vsf_wifi_scan_result_t *result);
412extern void vsf_wifi_on_scan_done (vsf_wifi_t *wifi);
413extern void vsf_wifi_on_link_up (vsf_wifi_t *wifi,
414 const vsf_wifi_link_info_t *info);
415extern void vsf_wifi_on_link_down (vsf_wifi_t *wifi, uint8_t reason);
416
417/*============================ NETIF BINDING ================================*
418 *
419 * Runtime binding for a network-stack adapter (e.g. the lwIP netdrv driver
420 * in vsf_wifi_netdrv.c). Once a backend is attached via
421 * vsf_wifi_netdrv_attach(), the core delivers decrypted RX data frames to
422 * its on_rx (replacing the weak vsf_wifi_on_rx hook), and additionally
423 * delivers link up/down events to its on_link_up / on_link_down. Link
424 * events still also fire the weak vsf_wifi_on_link_up / vsf_wifi_on_link_down
425 * hooks: those are control-plane notifications (e.g. unblocking a connect
426 * command) and run alongside the backend's data-plane handling. With no
427 * backend attached only the weak hooks are used (back-compat with the
428 * diagnostic commands). All callbacks run in the bus driver's EDA context,
429 * exactly like the weak hooks. `on_rx` receives a naked, decrypted 802.11
430 * data frame (FC .. payload); the backend is responsible for any 802.11 <->
431 * Ethernet framing. */
432typedef struct vsf_wifi_netif_ops_t {
433 void (*on_rx) (void *param, vsf_wifi_t *wifi,
434 uint8_t *frame, uint16_t len);
435 void (*on_link_up) (void *param, vsf_wifi_t *wifi,
436 const vsf_wifi_link_info_t *info);
437 void (*on_link_down)(void *param, vsf_wifi_t *wifi, uint8_t reason);
439
440/* Register / unregister a netif backend. `ops` (and the storage it points
441 * at) must stay valid until detach; `param` is passed back verbatim to each
442 * callback. Passing ops == NULL is equivalent to detach. */
444 const vsf_wifi_netif_ops_t *ops, void *param);
446
447/*============================ USER API ======================================*/
448
449/* Inspection. */
451const char * vsf_wifi_get_chip_name(vsf_wifi_t *wifi);
452bool vsf_wifi_is_ready (vsf_wifi_t *wifi);
453
454/* BSS Max Idle Period advertised by the AP in the assoc-resp (IE 90).
455 * Returned in units of 1000 TU; 0 means the AP did not advertise it. */
457
458/* Per-device MAC address discovered during chip bring-up (eFuse / EEPROM
459 * read). Returns a pointer to a 6-byte array inside the wifi struct;
460 * all-zero until the chip driver finishes its EEPROM stage. The pointer
461 * stays valid for the lifetime of the wifi instance. */
462const uint8_t * vsf_wifi_get_mac (vsf_wifi_t *wifi);
463
464/* Mutation. Calls return VSF_ERR_NOT_READY before vsf_wifi_on_ready,
465 * VSF_ERR_NOT_AVAILABLE while a scan is in progress, and the chip driver's
466 * own error otherwise. All async — completion is signalled by either the
467 * relevant on_xxx callback or by the next observable side effect (RSSI,
468 * link_info, etc.). */
469void vsf_wifi_set_channel (vsf_wifi_t *wifi, uint8_t channel);
470vsf_err_t vsf_wifi_set_mac (vsf_wifi_t *wifi, const uint8_t mac[6]);
473 const vsf_wifi_auth_cfg_t *cfg);
474
475/*
476 * Active scan: hop through the supplied channel list, dwelling `dwell_ms`
477 * milliseconds on each channel. Beacon / probe-response frames are routed
478 * to the chip parser (drv->parse_rx) which feeds vsf_wifi_on_scan_result.
479 * vsf_wifi_on_scan_done() is fired exactly once when every channel has
480 * been visited. dwell_ms == 0 falls back to a sensible default (120 ms).
481 */
483 const uint8_t *channels,
484 uint8_t num_channels, uint16_t dwell_ms);
486
487/* Channel bandwidth hints used by set_channel / connect. Not all chip
488 * drivers support 40/80 MHz; unsupported values fall back to 20 MHz. */
489#define WIFI_BW_20MHZ 0
490#define WIFI_BW_40MHZ_PLUS 1 /* primary lower, extension above */
491#define WIFI_BW_40MHZ_MINUS 2 /* primary upper, extension below */
492#define WIFI_BW_80MHZ 3
493
495
497 const uint8_t bssid[6],
498 const uint8_t *ssid, uint8_t ssid_len,
499 uint8_t channel);
501
502/* Enable/disable automatic reconnection: when a linked session is torn down
503 * by an over-the-air deauth/disassoc, the MLME re-issues connect to the same
504 * target after VSF_WIFI_CFG_AUTO_RECONNECT_DELAY_MS (up to
505 * VSF_WIFI_CFG_AUTO_RECONNECT_RETRIES attempts; the budget resets on a fresh
506 * vsf_wifi_connect or link-up). User-initiated disconnects never trigger
507 * it. Enabled by default via VSF_WIFI_CFG_AUTO_RECONNECT. */
508void vsf_wifi_set_auto_reconnect(vsf_wifi_t *wifi, bool auto_reconnect);
511
512/*
513 * Transmit a raw 802.11 frame. The chip driver (drv->tx) is responsible for
514 * building the on-wire TX descriptor and shipping it over the bus. Returns
515 * VSF_ERR_NOT_READY before vsf_wifi_on_ready, VSF_ERR_NOT_SUPPORTED when the
516 * chip driver has no tx hook, or a bus-level error. Fire-and-forget: there
517 * is no per-frame completion callback (chip drivers use TX_STA_FIFO /
518 * TX_STA_CNT to inspect results). */
520 const uint8_t *frame, uint16_t len);
521
522/*============================ REGISTER-BUS LAYER API =========================*
523 *
524 * These are exported so a bus driver can drive the wifi state machine.
525 * Application code does not call them directly.
526 *==========================================================================*/
527
528/*
529 * One-shot construction. After this call:
530 * - wifi->drv is bound;
531 * - wifi->reg_bus is bound (may be NULL for non-register-based chips);
532 * - all state fields are zero / cleared;
533 * - scan timer is initialised but not armed;
534 * - the wifi is NOT started yet (call vsf_wifi_start when ready).
535 *
536 * `post_eda` is the EDA on which the wifi layer will post follow-up events
537 * (scan-hop callbacks). Typically the bus driver passes its own EDA so
538 * that timer-driven hops are handled in the same context as bus completions.
539 */
540void vsf_wifi_init(vsf_wifi_t *wifi,
541 const vsf_wifi_chip_drv_t *drv,
542 const vsf_wifi_reg_bus_t *reg_bus,
543 vsf_eda_t *post_eda);
544
545/*
546 * Kick off the chip bring-up chain (firmware_load -> init -> set_rx_filter).
547 * On success vsf_wifi_on_ready fires when the chain finishes; on any error
548 * the bus driver's `on_attach_fail` (passed via vsf_wifi_set_attach_fail)
549 * is invoked so it can tear down the device.
550 *
551 * Must be called from the bus driver's EDA context, typically on
552 * VSF_EVT_INIT.
553 */
554void vsf_wifi_start(vsf_wifi_t *wifi);
555
556/*
557 * Bus driver tear-down. Cancels pending scans / scripts, marks the wifi
558 * as disconnecting so no further callbacks fire, and invokes the chip
559 * driver's fini hook. After this call the wifi struct can be freed.
560 */
561void vsf_wifi_fini(vsf_wifi_t *wifi);
562
563/*
564 * Set a callback that the wifi layer invokes when the bring-up chain or a
565 * scan reports an unrecoverable error. The bus driver typically removes
566 * the device interface from inside this hook. Default: NULL (errors are
567 * logged but otherwise ignored).
568 */
569typedef void (*vsf_wifi_attach_fail_t)(vsf_wifi_t *wifi, vsf_err_t err);
571
572/* Bus driver hands an inbound RX frame to the wifi layer; the layer routes
573 * it to drv->parse_rx (during scan) or vsf_wifi_on_rx (otherwise). */
574void vsf_wifi_on_rx_internal(vsf_wifi_t *wifi, uint8_t *frame, uint16_t len);
575
576/* MLME management-frame entry point. The chip parser (drv->parse_rx) calls
577 * this with a de-descriptored, naked 802.11 management frame (starting at
578 * the FC field) when its subtype is auth / assoc-resp / deauth / disassoc.
579 * The wifi-layer MLME state machine advances the OPEN-system connection. */
580void vsf_wifi_mlme_rx(vsf_wifi_t *wifi, const uint8_t *dot11, uint16_t len);
581
582/* Data-frame entry point. The chip parser (drv->parse_rx) calls this with a
583 * de-descriptored, naked 802.11 data frame (starting at the FC field) once
584 * the link is associated (mlme_state RUN / 4WAY). The wifi layer parses the
585 * data header, detects EAPOL (LLC/SNAP + ethertype 0x888E) for the 4-way
586 * handshake, and forwards decrypted business payloads to vsf_wifi_on_rx. */
587void vsf_wifi_data_rx(vsf_wifi_t *wifi, const uint8_t *dot11, uint16_t len);
588
589#if VSF_WIFI_USE_WPA == ENABLED
590/* Helpers exported to the WPA 4-way handshake (vsf_wifi_wpa.c). The wifi
591 * layer owns the MLME state, the retry timer and the chip TX path; the WPA
592 * module owns EAPOL-Key parsing / building and key derivation, and drives
593 * the connection through these calls:
594 * - mlme_tx : transmit a fully formed 802.11 frame (EAPOL).
595 * - mlme_arm_timer : (re)arm the handshake timeout.
596 * - handshake_done : keys installed -> state RUN + vsf_wifi_on_link_up.
597 * - handshake_fail : abort the handshake -> link down with `reason`. */
598vsf_err_t vsf_wifi_mlme_tx(vsf_wifi_t *wifi, const uint8_t *frame, uint16_t len);
602#endif
603
604/* Bus driver invokes this from its EDA when the wifi-posted scan-hop event
605 * lands; the wifi layer advances to the next channel or finishes the scan. */
607
608/* Bus driver invokes this from its EDA when the wifi-posted MLME-retry event
609 * lands; the wifi layer retransmits the current handshake frame (auth-req /
610 * assoc-req) or declares a link-down timeout once retries are exhausted.
611 * Bounced through the bus EDA (like scan-hop) so the TX runs in the same
612 * context as bus completions. */
614
615/* Custom EDA event used by vsf_wifi to trigger a scan hop on the bus EDA.
616 * The bus driver's evt-handler must dispatch this value to
617 * vsf_wifi_on_scan_hop_evt(). */
618#define VSF_WIFI_EVT_SCAN_HOP (VSF_EVT_USER + 0x40)
619
620/* Custom EDA event used by vsf_wifi to trigger an MLME handshake retransmit
621 * on the bus EDA. The bus driver's evt-handler must dispatch this value to
622 * vsf_wifi_on_mlme_retry_evt(). */
623#define VSF_WIFI_EVT_MLME_RETRY (VSF_EVT_USER + 0x41)
624
625/*============================ CHIP <-> WIFI INTERNAL API ====================*/
626
627/*
628 * Run a sequence of register writes asynchronously.
629 *
630 * ops : array of (reg, val) pairs. May point to .rodata or to
631 * wifi->scratch_ops. Caller MUST keep `ops` valid until
632 * `done` fires.
633 * count : number of ops to execute (must be > 0 for a real submission).
634 * done : completion callback (NULL = fire-and-forget).
635 *
636 * Returns VSF_ERR_NONE on accepted submission (completion via `done`),
637 * VSF_ERR_NOT_AVAILABLE when another script / blob is in flight, or a bus-
638 * level synchronous error otherwise.
639 */
641 const vsf_wifi_reg_op_t *ops, uint16_t count,
642 vsf_wifi_done_t done);
643
644/*
645 * Stream a contiguous register-block payload. Internally calls
646 * reg_bus->reg_block_write when available; otherwise decomposes into
647 * ceil(len / 4) reg_write calls.
648 *
649 * Same concurrency rules as vsf_wifi_reg_run_script: at most one script /
650 * blob in flight per wifi.
651 */
653 const vsf_wifi_reg_blob_t *blob,
654 vsf_wifi_done_t done);
655
656/*
657 * Periodically read `reg` until `match(val)` returns true.
658 *
659 * reg : MAC register to poll.
660 * match : predicate; the read value is fed in on every iteration.
661 * max_retry : upper bound on read attempts (>= 1). The first read
662 * counts as attempt #1.
663 * interval_ms : delay between consecutive reads. 0 means "re-issue
664 * immediately on completion" (use only if the bus already
665 * paces reads, e.g. USB ep0 vendor request).
666 * done : completion callback.
667 * VSF_ERR_NONE : predicate matched.
668 * VSF_ERR_TIMEOUT : retries exhausted without match.
669 * other : bus-level error.
670 *
671 * Same single-flight constraint as run_script / run_blob.
672 */
674 vsf_wifi_reg_match_fn_t match, void *match_ctx,
675 uint16_t max_retry, uint16_t interval_ms,
676 vsf_wifi_done_t done);
677
678/*
679 * Single 32-bit register read. The result is stored at *out before
680 * `done` fires; caller must keep `out` valid until then. Same single-
681 * flight constraint as run_script / run_blob / run_read_poll.
682 */
684 vsf_wifi_done_t done);
685
686#if VSF_WIFI_USE_WPA == ENABLED
687/* CCMP software-encapsulate a plaintext 802.11 data frame `frame` (length
688 * `len`) into `out` (capacity `cap`). The 8-byte CCMP header is inserted
689 * immediately after the 802.11 header; the Protected Frame bit is set.
690 * `pn` is the 48-bit packet number used for this MPDU (little-endian);
691 * pass NULL to use the per-wifi TX PN counter.
692 * Returns the encrypted MPDU length, or 0 on failure.
693 *
694 * This is a public helper for chip drivers that need to software-encrypt
695 * specific frames even when hardware crypto is enabled (e.g. MT76 multicast
696 * frames). */
698 const uint8_t *frame, uint16_t len, uint8_t *out, uint16_t cap,
699 uint8_t pn[6]);
700#endif
701
702/* Per-wifi scratch op buffer (shared by parameterised chip ops). */
704
705/*============================ CHIP-SPECIFIC HEADERS =========================*
706 *
707 * Concrete chip families live in chip/xxx/ and expose their own firmware
708 * symbols, logging helpers and (if needed) public constants. The generic
709 * wifi header only pulls in the chips that are enabled at compile time.
710 *===========================================================================*/
711
712#if VSF_WIFI_USE_RT28XX == ENABLED
714#endif
715
716#if VSF_WIFI_USE_MT76 == ENABLED
718#endif
719
720#if VSF_WIFI_USE_AIC8800D == ENABLED
722#endif
723
724/*============================ LOGGING HELPERS ===============================*
725 *
726 * Compile-time log level gates for the WiFi subsystem and its sub-modules.
727 * Levels are defined in vsf_wifi_cfg.h; sub-module macros fall back to the
728 * global VSF_WIFI_CFG_LOG_LEVEL when not explicitly set.
729 *==========================================================================*/
730
731#if VSF_WIFI_CFG_LOG_LEVEL >= 1
732# define vsf_wifi_trace_error(...) vsf_trace_error(__VA_ARGS__)
733#else
734# define vsf_wifi_trace_error(...) ((void)0)
735#endif
736
737#if VSF_WIFI_CFG_LOG_LEVEL >= 2
738# define vsf_wifi_trace_info(...) vsf_trace_info(__VA_ARGS__)
739#else
740# define vsf_wifi_trace_info(...) ((void)0)
741#endif
742
743#if VSF_WIFI_CFG_LOG_LEVEL >= 4
744# define vsf_wifi_trace_debug(...) vsf_trace_info(__VA_ARGS__)
745#else
746# define vsf_wifi_trace_debug(...) ((void)0)
747#endif
748
749
750#ifdef __cplusplus
751}
752#endif
753
754#endif // VSF_USE_WIFI
755#endif // __VSF_WIFI_H__
vsf_err_t
Definition __type.h:42
bool
Definition type.h:60
The event-driven task (TCB); every VSF task is an eda at the bottom. Tasks share stacks and only occu...
Definition vsf_eda.h:1838
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:314
vsf_err_t(* set_channel)(vsf_wifi_t *wifi, uint8_t channel, vsf_wifi_done_t done)
Definition vsf_wifi.h:332
vsf_err_t(* disconnect)(vsf_wifi_t *wifi, vsf_wifi_done_t done)
Definition vsf_wifi.h:347
uint32_t flags
Definition vsf_wifi.h:318
struct vsf_wifi_chip_drv_t::@347::@350 fullmac
void(* parse_rx)(vsf_wifi_t *wifi, uint8_t *frame, uint16_t len)
Definition vsf_wifi.h:355
vsf_err_t(* set_bssid)(vsf_wifi_t *wifi, const uint8_t bssid[6], vsf_wifi_done_t done)
Definition vsf_wifi.h:338
const vsf_wifi_radio_ops_t * radio_ops
Definition vsf_wifi.h:396
vsf_err_t(* get_link_info)(vsf_wifi_t *wifi, vsf_wifi_link_info_t *info)
Definition vsf_wifi.h:348
void(* fini)(vsf_wifi_t *wifi)
Definition vsf_wifi.h:326
vsf_err_t(* tx)(vsf_wifi_t *wifi, const uint8_t *frame, uint16_t len)
Definition vsf_wifi.h:386
vsf_err_t(* set_mac_addr)(vsf_wifi_t *wifi, const uint8_t mac[6], vsf_wifi_done_t done)
Definition vsf_wifi.h:336
const char * name
Definition vsf_wifi.h:315
const vsf_wifi_crypto_ops_t * crypto_ops
Definition vsf_wifi.h:391
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:343
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:358
struct vsf_wifi_chip_drv_t::@347::@349 softmac
vsf_err_t(* firmware_load)(vsf_wifi_t *wifi, vsf_wifi_done_t done)
Definition vsf_wifi.h:324
vsf_err_t(* init)(vsf_wifi_t *wifi, vsf_wifi_done_t done)
Definition vsf_wifi.h:325
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:340
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:366
vsf_err_t(* set_rx_filter)(vsf_wifi_t *wifi, uint32_t mask, vsf_wifi_done_t done)
Definition vsf_wifi.h:334
Definition vsf_wifi.h:304
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:305
vsf_err_t(* encrypt)(vsf_wifi_t *wifi, uint8_t *dot11, uint16_t *len, uint16_t cap)
Definition vsf_wifi.h:308
vsf_err_t(* decrypt)(vsf_wifi_t *wifi, uint8_t *dot11, uint16_t *len)
Definition vsf_wifi.h:310
Definition vsf_wifi.h:432
void(* on_link_down)(void *param, vsf_wifi_t *wifi, uint8_t reason)
Definition vsf_wifi.h:437
void(* on_rx)(void *param, vsf_wifi_t *wifi, uint8_t *frame, uint16_t len)
Definition vsf_wifi.h:433
void(* on_link_up)(void *param, vsf_wifi_t *wifi, const vsf_wifi_link_info_t *info)
Definition vsf_wifi.h:435
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:1886
void vsf_wifi_on_del(vsf_wifi_t *wifi)
Definition vsf_wifi.c:103
void vsf_wifi_on_ready(vsf_wifi_t *wifi)
Definition vsf_wifi.c:110
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:1062
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:349
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:1979
vsf_err_t vsf_wifi_disconnect(vsf_wifi_t *wifi)
Definition vsf_wifi.c:2100
@ 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
void vsf_wifi_on_rx_internal(vsf_wifi_t *wifi, uint8_t *frame, uint16_t len)
Definition vsf_wifi.c:782
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:1901
struct vsf_wifi_netif_ops_t vsf_wifi_netif_ops_t
void vsf_wifi_set_auto_reconnect(vsf_wifi_t *wifi, bool auto_reconnect)
Definition vsf_wifi.c:742
void vsf_wifi_mlme_handshake_fail(vsf_wifi_t *wifi, uint8_t reason)
Definition vsf_wifi.c:2385
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:428
vsf_err_t vsf_wifi_set_bssid(vsf_wifi_t *wifi, const uint8_t bssid[6])
Definition vsf_wifi.c:1944
void vsf_wifi_start(vsf_wifi_t *wifi)
Definition vsf_wifi.c:656
uint8_t vsf_wifi_get_channel(vsf_wifi_t *wifi)
Definition vsf_wifi.c:1891
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:552
@ 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
const char * vsf_wifi_get_chip_name(vsf_wifi_t *wifi)
Definition vsf_wifi.c:1896
void vsf_wifi_on_mlme_retry_evt(vsf_wifi_t *wifi)
Definition vsf_wifi.c:1717
void vsf_wifi_mlme_rx(vsf_wifi_t *wifi, const uint8_t *dot11, uint16_t len)
Definition vsf_wifi.c:1753
void vsf_wifi_on_link_down(vsf_wifi_t *wifi, uint8_t reason)
Definition vsf_wifi.c:125
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:2221
vsf_err_t vsf_wifi_set_auth_mode(vsf_wifi_t *wifi, const vsf_wifi_auth_cfg_t *cfg)
Definition vsf_wifi.c:1954
void vsf_wifi_on_rx(vsf_wifi_t *wifi, uint8_t *frame, uint16_t len)
Definition vsf_wifi.c:106
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:135
void vsf_wifi_set_channel(vsf_wifi_t *wifi, uint8_t channel)
Definition vsf_wifi.c:1911
void vsf_wifi_mlme_arm_timer(vsf_wifi_t *wifi, uint16_t ms)
Definition vsf_wifi.c:2226
vsf_wifi_reg_op_t * vsf_wifi_reg_get_scratch_ops(vsf_wifi_t *wifi)
Definition vsf_wifi.c:471
void vsf_wifi_fini(vsf_wifi_t *wifi)
Definition vsf_wifi.c:752
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:599
void vsf_wifi_on_link_up(vsf_wifi_t *wifi, const vsf_wifi_link_info_t *info)
Definition vsf_wifi.c:121
void vsf_wifi_netdrv_detach(vsf_wifi_t *wifi)
Definition vsf_wifi.c:142
void vsf_wifi_on_scan_result(vsf_wifi_t *wifi, const vsf_wifi_scan_result_t *result)
Definition vsf_wifi.c:113
vsf_err_t vsf_wifi_get_link_info(vsf_wifi_t *wifi, vsf_wifi_link_info_t *info)
Definition vsf_wifi.c:2133
void vsf_wifi_on_new(vsf_wifi_t *wifi)
Definition vsf_wifi.c:100
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:118
void vsf_wifi_set_attach_fail(vsf_wifi_t *wifi, vsf_wifi_attach_fail_t hook)
Definition vsf_wifi.c:651
vsf_err_t vsf_wifi_tx(vsf_wifi_t *wifi, const uint8_t *frame, uint16_t len)
Definition vsf_wifi.c:2187
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:2038
@ 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
@ 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:1906
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:1926
void vsf_wifi_mlme_handshake_done(vsf_wifi_t *wifi)
Definition vsf_wifi.c:2355
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:622
vsf_err_t vsf_wifi_scan_stop(vsf_wifi_t *wifi)
Definition vsf_wifi.c:2025
vsf_err_t vsf_wifi_set_mac(vsf_wifi_t *wifi, const uint8_t mac[6])
Definition vsf_wifi.c:1934
void(* vsf_wifi_attach_fail_t)(vsf_wifi_t *wifi, vsf_err_t err)
Definition vsf_wifi.h:569
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:966
Generated from commit: vsfteam/vsf@a5104db