1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//! The raw sounding frame an emitter injects, and the injection call itself.
//!
//! The frame is deliberately **rate-agnostic**: it is a plain, well-formed
//! non-QoS data frame, and the interface's forced TX rate decides which PPDU
//! format carries it. That is what lets one frame builder serve every
//! bandwidth/format an emitter can be configured for.
use WifiError;
use Sniffer;
/// Broadcast address — the default injection destination.
pub const BROADCAST: = ;
/// Header + payload length of the frame built by [`build_probe_frame`].
///
/// Non-QoS Data MAC header (24 bytes) plus a short payload. `esp_wifi_80211_tx`
/// accepts only beacon / probe req/resp / action / **non-QoS** data frames — QoS
/// Data (`0x88`) is rejected with `ESP_ERR_INVALID_ARG`. The CSI engine reports
/// the channel estimate from the PPDU preamble, so the body only has to make the
/// frame well-formed; its contents are irrelevant.
pub const PROBE_FRAME_LEN: usize = 24 + 8;
/// Build a minimal well-formed 802.11 **non-QoS Data** frame for injection.
///
/// No DS bits are set, so the address layout is Addr1 = destination, Addr2 =
/// source (the transmitter address a receiver's CSI callback reports as
/// [`crate::csi::CSIDataPacket::mac`]), Addr3 = BSSID. Give each emitter a
/// distinct `src_mac` — its own interface MAC is the obvious choice — and a
/// single collector can separate emitters by that field.
///
/// The sequence-control field is left zero: pair this with the driver's internal
/// sequence numbering in [`inject_probe_once`] so each frame gets an
/// incrementing sequence number, which is what lets a collector de-duplicate
/// per-MAC.
///
/// Returns the number of bytes written, or `0` if `buf` is shorter than
/// [`PROBE_FRAME_LEN`].
/// Inject one raw frame at the interface's currently-forced TX rate.
///
/// Once the interface has been forced to a PHY mode (see
/// [`super::phy`]), every frame sent here goes out in that PPDU format with no
/// association required. `use_sta_if` selects the STA (`true`) or AP (`false`)
/// interface and must match the interface the forced rate was applied to.