0
0
Fork 0

refactor: Move sniffer to own module

This commit is contained in:
Jannik Beyerstedt 2026-05-11 22:06:37 +02:00
commit 93f3cce9e4
3 changed files with 126 additions and 82 deletions

View file

@ -12,64 +12,14 @@ use embassy_time::{Duration, Timer};
use esp_backtrace as _;
use esp_hal::clock::CpuClock;
use esp_hal::timer::timg::TimerGroup;
use log::{debug, error, info, warn};
use esp_radio::wifi;
use log::{debug, info, warn};
extern crate alloc;
const WIFI_CHANNEL: core::ffi::c_int = 180;
mod radio;
unsafe extern "C" {
/// Changes the 802.11 PHY channel
///
/// C function signature: `void phy_change_channel(int,int,int,int)`
///
/// Options:
/// - `primary`: Channel frequency in MHz
/// - `ignored1`: Ignored (set to 1)
/// - `ignored2`: Ignored (set to 0)
/// - `ht_mode`: Probably HT mode
pub unsafe fn phy_change_channel(
primary: core::ffi::c_int,
ignored1: core::ffi::c_int,
ignored2: core::ffi::c_int,
ht_mode: core::ffi::c_int,
) -> core::ffi::c_int;
/// Enables 802.11p mode on the ESP32-C5
///
/// C function signature: `void phy_11p_set(int,int)`
///
/// Options:
/// - `enable`: Boolean option to enable 802.11p mode
/// - `zero`: Unknown, but need to be zero
pub unsafe fn phy_11p_set(enable: u8, zero: u8);
}
#[repr(u8)]
#[derive(Debug)]
#[allow(dead_code)]
enum EspWifiPromiscuousPktType {
/// Management frame, indicates 'buf' argument is wifi_promiscuous_pkt_t
MGMT = 0,
/// Control frame, indicates 'buf' argument is wifi_promiscuous_pkt_t
CTRL = 1,
/// Data frame, indicates 'buf' argument is wifi_promiscuous_pkt_t
DATA = 2,
/// Other type, such as MIMO etc. 'buf' argument is wifi_promiscuous_pkt_t but the payload is zero length.
MISC = 3,
}
impl EspWifiPromiscuousPktType {
#[allow(dead_code)]
pub fn as_repr(self) -> u8 {
self as u8
}
/// Converts to underlying type of `wifi_promiscuous_pkt_type_t` (used by `esp_radio::wifi::sniffer::PromiscuousPkt::frame_type`)
pub fn as_frame_type(self) -> core::ffi::c_uint {
(self as u8) as core::ffi::c_uint
}
}
const WIFI_CHANNEL: radio::Channel = 180;
// This creates a default app-descriptor required by the esp-idf bootloader.
// For more information see: <https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/system/app_image_format.html#application-description>
@ -115,34 +65,9 @@ async fn main(spawner: Spawner) -> ! {
.expect("Failed to initialize Wi-Fi controller");
let mut sniffer = interfaces.sniffer;
sniffer
.set_promiscuous_mode(true)
.expect("Failed to enable promiscuous mode");
radio::setup_wifi_sniffer(WIFI_CHANNEL, &mut sniffer, handle_frame)
.expect("Fatal error initializing 802.11p sniffer");
sniffer.set_receive_cb(|packet| {
// Ignore frames with errors and non-data frames
if packet.rx_cntl.rx_state != 0 {
warn!("Received frame has RX error: {}", packet.rx_cntl.rx_state);
return;
}
if packet.frame_type != EspWifiPromiscuousPktType::DATA.as_frame_type() {
debug!("Received frame is not a DATA frame: {}", packet.frame_type);
return;
}
// TODO: handle 802.11 frame
info!("Received frame with {} bytes", packet.len);
});
unsafe {
phy_11p_set(1, 0);
match phy_change_channel(5000 + (WIFI_CHANNEL * 5), 1, 0, 0) {
0 => {}
ret => {
error!("ERROR: Failed to change channel: {ret}");
}
}
}
info!("WiFi promiscuous mode on channel {WIFI_CHANNEL} running");
// TODO: Spawn some tasks
@ -154,3 +79,23 @@ async fn main(spawner: Spawner) -> ! {
Timer::after(Duration::from_secs(1)).await;
}
}
#[allow(
clippy::needless_pass_by_value,
reason = "adhering to callback interface"
)]
fn handle_frame(frame: wifi::sniffer::PromiscuousPkt<'_>) {
// Ignore frames with errors and non-data frames
if frame.rx_cntl.rx_state != 0 {
warn!("Received frame has RX error: {}", frame.rx_cntl.rx_state);
return;
}
if !radio::PromiscuousPktType::Data.matches(frame.frame_type) {
debug!("Received frame is not a DATA frame: {}", frame.frame_type);
return;
}
// TODO: handle 802.11 frame
info!("Received frame with {} bytes", frame.len);
}