esp-hal/examples/src/bin/wifi_80211_tx.rs
Juraj Sadel 0fbbe2d22c
esp-wifi: Add unstable feature, mark ble, esp-now, csi, sniffer, and smoltcp features and APIs as unstable (#3865)
* esp-wifi: Add unstable feature, mark ble, esp-now and csi features and APIs as unstable

* changelog

* fix hils

* rebase and reviews

* rebase

* Make at least wifi_embassy_dhcp work without unstable feature

* remove rand_core

* rebase

* Check if a feature is selected which needs unstable

* reviews and fix ci

* reviews
2025-07-31 07:59:05 +00:00

114 lines
3.8 KiB
Rust

//! WiFi frame injection example
//!
//! Periodically transmits a beacon frame.
//% FEATURES: esp-radio esp-radio/wifi esp-radio/sniffer esp-radio/unstable esp-hal/unstable
//% CHIPS: esp32 esp32s2 esp32s3 esp32c2 esp32c3 esp32c6
#![no_std]
#![no_main]
use core::marker::PhantomData;
use esp_alloc as _;
use esp_backtrace as _;
use esp_hal::{clock::CpuClock, delay::Delay, main, time::Duration, timer::timg::TimerGroup};
use esp_println::println;
use esp_radio::wifi;
use ieee80211::{
common::{CapabilitiesInformation, FCFFlags},
element_chain,
elements::{DSSSParameterSetElement, RawIEEE80211Element, SSIDElement},
mgmt_frame::{BeaconFrame, body::BeaconBody, header::ManagementFrameHeader},
scroll::Pwrite,
supported_rates,
};
esp_bootloader_esp_idf::esp_app_desc!();
const SSID: &str = "esp-radio 802.11 injection";
/// This is an arbitrary MAC address, used for the fake beacon frames.
const MAC_ADDRESS: [u8; 6] = [0x00, 0x80, 0x41, 0x13, 0x37, 0x42];
#[main]
fn main() -> ! {
esp_println::logger::init_logger_from_env();
let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
let peripherals = esp_hal::init(config);
esp_alloc::heap_allocator!(size: 72 * 1024);
let delay = Delay::new();
let timg0 = TimerGroup::new(peripherals.TIMG0);
esp_radio_preempt_baremetal::init(timg0.timer0);
let esp_radio_ctrl = esp_radio::init().unwrap();
// We must initialize some kind of interface and start it.
let (mut controller, interfaces) =
esp_radio::wifi::new(&esp_radio_ctrl, peripherals.WIFI).unwrap();
controller.set_mode(wifi::WifiMode::Sta).unwrap();
controller.start().unwrap();
let mut sniffer = interfaces.sniffer;
// Create a buffer, which can hold the enitre serialized beacon frame.
let mut beacon = [0u8; 300];
let length = beacon
.pwrite(
BeaconFrame {
header: ManagementFrameHeader {
fcf_flags: FCFFlags::new(),
duration: 0,
receiver_address: [0xff; 6].into(),
transmitter_address: MAC_ADDRESS.into(),
bssid: MAC_ADDRESS.into(),
..Default::default()
},
body: BeaconBody {
timestamp: 0,
// We transmit a beacon every 100 ms/TUs
beacon_interval: 100,
capabilities_info: CapabilitiesInformation::new().with_is_ess(true),
elements: element_chain! {
SSIDElement::new(SSID).unwrap(),
// These are known good values.
supported_rates![
1 B,
2 B,
5.5 B,
11 B,
6,
9,
12,
18
],
DSSSParameterSetElement {
current_channel: 1,
},
// This contains the Traffic Indication Map(TIM), for which `ieee80211-rs` currently lacks support.
RawIEEE80211Element {
tlv_type: 5,
slice: [0x01, 0x02, 0x00, 0x00].as_slice(),
_phantom: PhantomData
}
},
_phantom: PhantomData,
},
},
0,
)
.unwrap();
// Only use the actually written bytes.
let beacon = &beacon[..length];
println!("Scan for WiFi networks and find `esp-radio 802.11 injection`");
loop {
sniffer.send_raw_frame(true, beacon, false).unwrap();
delay.delay(Duration::from_millis(100));
}
}