From 8368354bf282f2544d6fb5abc28f6044c09c34bf Mon Sep 17 00:00:00 2001 From: Julien Vincent Date: Mon, 9 Dec 2024 19:46:36 +0000 Subject: [PATCH] Expose src_addr and dst_addr in espnow recv cb (#525) Currently the espnow bindings for `register_recv_cb` only give a handle on the src_addr from the sending peer. This makes it impossible to determine if the frame was sent on the BROADCAST address. This change updates the first argument to the receive cb to accept a new ReceiveInfo struct containing `src_addr` and `dst_addr`. --- src/espnow.rs | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/src/espnow.rs b/src/espnow.rs index e2dd85901aa..5acf43f3f00 100644 --- a/src/espnow.rs +++ b/src/espnow.rs @@ -20,8 +20,14 @@ type Singleton = Mutex>>; pub const BROADCAST: [u8; 6] = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]; +#[derive(Debug, Clone)] +pub struct ReceiveInfo<'a> { + pub src_addr: &'a [u8; 6], + pub dst_addr: &'a [u8; 6], +} + #[allow(clippy::type_complexity)] -static RECV_CALLBACK: Singleton = Mutex::new(None); +static RECV_CALLBACK: Singleton = Mutex::new(None); #[allow(clippy::type_complexity)] static SEND_CALLBACK: Singleton = Mutex::new(None); @@ -168,12 +174,12 @@ impl<'a> EspNow<'a> { pub fn register_recv_cb(&self, callback: F) -> Result<(), EspError> where - F: FnMut(&[u8], &[u8]) + Send + 'a, + F: FnMut(&ReceiveInfo, &[u8]) + Send + 'a, { #[allow(clippy::type_complexity)] - let callback: Box = Box::new(callback); + let callback: Box = Box::new(callback); #[allow(clippy::type_complexity)] - let callback: Box = + let callback: Box = unsafe { core::mem::transmute(callback) }; *RECV_CALLBACK.lock() = Some(Box::new(callback)); @@ -223,18 +229,31 @@ impl<'a> EspNow<'a> { } extern "C" fn recv_callback( - #[cfg(esp_idf_version_major = "4")] mac_addr: *const u8, + #[cfg(esp_idf_version_major = "4")] src_addr: *const u8, #[cfg(not(esp_idf_version_major = "4"))] esp_now_info: *const esp_now_recv_info_t, data: *const u8, data_len: core::ffi::c_int, ) { #[cfg(not(any(esp_idf_version_major = "4")))] - let mac_addr = unsafe { *esp_now_info }.src_addr.cast_const(); - let c_mac = unsafe { core::slice::from_raw_parts(mac_addr, 6usize) }; + let src_addr = unsafe { *esp_now_info }.src_addr.cast_const(); + #[cfg(not(any(esp_idf_version_major = "4")))] + let dst_addr = unsafe { *esp_now_info }.des_addr.cast_const(); + let c_src_addr = unsafe { &*(src_addr as *const [u8; 6]) }; + #[cfg(not(any(esp_idf_version_major = "4")))] + let c_dst_addr = unsafe { &*(dst_addr as *const [u8; 6]) }; let c_data = unsafe { core::slice::from_raw_parts(data, data_len as usize) }; if let Some(ref mut callback) = *RECV_CALLBACK.lock() { - callback(c_mac, c_data) + callback( + &ReceiveInfo { + src_addr: c_src_addr, + #[cfg(esp_idf_version_major = "4")] + dst_addr: &[0u8; 6], + #[cfg(not(any(esp_idf_version_major = "4")))] + dst_addr: c_dst_addr, + }, + c_data, + ) } else { panic!("EspNow callback not available"); }