From f96b8d69648f264f32dba1ba2b57970d179bceba Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Sun, 18 Dec 2022 19:55:44 +0000 Subject: [PATCH 1/5] WifiDevice refactor - Move svc impls to the WifiDevice itself - This way any stack can be uses once connection is handled - Added compat impl for Wifi which forwards to the WifiDevice impls - Added internal wifi error enum and upgraded the basic wifi error enum --- Cargo.toml | 2 + examples/dhcp.rs | 4 +- src/wifi/mod.rs | 256 +++++++++++++++++++++++++++++++++++++++++- src/wifi_interface.rs | 208 +++++----------------------------- 4 files changed, 285 insertions(+), 185 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index aeecfc58..7b65e376 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,8 @@ linked_list_allocator = { version = "0.10.3", default-features = false, features embedded-io = "0.3.1" fugit = "0.3.6" heapless = { version = "0.7.14", default-features = false } +num-derive = { version = "0.3", features = ["full-syntax"] } +num-traits = { version = "0.2", default-features = false } [build-dependencies] riscv-target = { version = "0.1.2", optional = true } diff --git a/examples/dhcp.rs b/examples/dhcp.rs index 3f8cd5c5..068b4ae5 100644 --- a/examples/dhcp.rs +++ b/examples/dhcp.rs @@ -21,8 +21,8 @@ use embedded_svc::wifi::{AccessPointInfo, ClientConfiguration, Configuration, Wi use esp_backtrace as _; use esp_println::logger::init_logger; use esp_println::{print, println}; -use esp_wifi::wifi::utils::create_network_interface; -use esp_wifi::wifi_interface::{Network, WifiError}; +use esp_wifi::wifi::{WifiError, utils::create_network_interface}; +use esp_wifi::wifi_interface::Network; use esp_wifi::{create_network_stack_storage, network_stack_storage}; use esp_wifi::{current_millis, initialize}; use hal::clock::{ClockControl, CpuClock}; diff --git a/src/wifi/mod.rs b/src/wifi/mod.rs index f6493ce4..e4adc5ab 100644 --- a/src/wifi/mod.rs +++ b/src/wifi/mod.rs @@ -6,6 +6,11 @@ use core::{cell::RefCell, marker::PhantomData}; use crate::common_adapter::*; use critical_section::Mutex; +use embedded_svc::wifi::{AccessPointInfo, AuthMethod, SecondaryChannel}; +use enumset::EnumSet; +use num_derive::FromPrimitive; +use num_traits::FromPrimitive; + #[doc(hidden)] pub use os_adapter::*; use smoltcp::phy::{Device, DeviceCapabilities, RxToken, TxToken}; @@ -89,8 +94,55 @@ pub(crate) static DATA_QUEUE_TX: Mutex>> = #[derive(Debug, Clone, Copy)] pub enum WifiError { - General(i32), + InternalError(InternalWifiError), WrongClockConfig, + Disconnected, +} + +#[repr(i32)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(FromPrimitive)] +pub enum InternalWifiError { + ///WiFi driver was not installed by esp_wifi_init */ + EspErrWifiNotInit = 0x3001, + ///WiFi driver was not started by esp_wifi_start */ + EspErrWifiNotStarted = 0x3002, + ///WiFi driver was not stopped by esp_wifi_stop */ + EspErrWifiNotStopped = 0x3003, + ///WiFi interface error */ + EspErrWifiIf = 0x3004, + ///WiFi mode error */ + EspErrWifiMode = 0x3005, + ///WiFi internal state error */ + EspErrWifiState = 0x3006, + ///WiFi internal control block of station or soft-AP error */ + EspErrWifiConn = 0x3007, + ///WiFi internal NVS module error */ + EspErrWifiNvs = 0x3008, + ///MAC address is invalid */ + EspErrWifiMac = 0x3009, + ///SSID is invalid */ + EspErrWifiSsid = 0x300A, + ///Password is invalid */ + EspErrWifiPassword = 0x300B, + ///Timeout error */ + EspErrWifiTimeout = 0x300C, + ///WiFi is in sleep state(RF closed) and wakeup fail */ + EspErrWifiWakeFail = 0x300D, + ///The caller would block */ + EspErrWifiWouldBlock = 0x300E, + ///Station still in disconnect status */ + EspErrWifiNotConnect = 0x300F, + ///Failed to post the event to WiFi task */ + EspErrWifiPost = 0x3012, + ///Invalid WiFi state when init/deinit is called */ + EspErrWifiInitState = 0x3013, + ///Returned when WiFi is stopping */ + EspErrWifiStopState = 0x3014, + ///The WiFi connection is not associated */ + EspErrWifiNotAssoc = 0x3015, + ///The WiFi TX is disallowed */ + EspErrWifiTxDisallow = 0x3016, } #[cfg(all(feature = "esp32c3", coex))] @@ -636,11 +688,19 @@ pub fn wifi_stop() -> i32 { } /// A wifi device implementing smoltcp's Device trait. -pub struct WifiDevice {} +pub struct WifiDevice { + config: embedded_svc::wifi::Configuration, +} impl WifiDevice { + pub fn new_with_config(config: embedded_svc::wifi::Configuration) -> WifiDevice { + WifiDevice { config } + } + pub fn new() -> WifiDevice { - WifiDevice {} + Self { + config: Default::default() + } } } @@ -752,6 +812,196 @@ pub fn send_data_if_needed() { }); } +impl embedded_svc::wifi::Wifi for WifiDevice { + type Error = WifiError; + + /// This currently only supports the `Client` capability. + fn get_capabilities(&self) -> Result, Self::Error> { + // for now we only support STA mode + let mut caps = EnumSet::empty(); + caps.insert(embedded_svc::wifi::Capability::Client); + Ok(caps) + } + + /// A blocking wifi network scan. + fn scan_n( + &mut self, + ) -> Result<(heapless::Vec, usize), Self::Error> { + let res = crate::wifi::wifi_start_scan(); + if res != 0 { + return Err(WifiError::InternalError(FromPrimitive::from_i32(res).unwrap())); + } + + let mut scanned = heapless::Vec::::new(); + let mut bss_total: u16 = N as u16; + + unsafe { + crate::binary::include::esp_wifi_scan_get_ap_num(&mut bss_total); + if bss_total as usize > N { + bss_total = N as u16; + } + + let mut records = [crate::binary::include::wifi_ap_record_t { + bssid: [0u8; 6], + ssid: [0u8; 33], + primary: 0u8, + second: 0u32, + rssi: 0i8, + authmode: 0u32, + pairwise_cipher: 0u32, + group_cipher: 0u32, + ant: 0u32, + _bitfield_align_1: [0u32; 0], + _bitfield_1: crate::binary::include::__BindgenBitfieldUnit::new([0u8; 4usize]), + country: crate::binary::include::wifi_country_t { + cc: [0; 3], + schan: 0u8, + nchan: 0u8, + max_tx_power: 0i8, + policy: 0u32, + }, + }; N]; + + crate::binary::include::esp_wifi_scan_get_ap_records( + &mut bss_total, + &mut records as *mut crate::binary::include::wifi_ap_record_t, + ); + + for i in 0..bss_total { + let record = records[i as usize]; + let ssid_strbuf = crate::compat::common::StrBuf::from(&record.ssid as *const u8); + + let auth_method = match record.authmode { + crate::binary::include::wifi_auth_mode_t_WIFI_AUTH_OPEN => AuthMethod::None, + crate::binary::include::wifi_auth_mode_t_WIFI_AUTH_WEP => AuthMethod::WEP, + crate::binary::include::wifi_auth_mode_t_WIFI_AUTH_WPA_PSK => AuthMethod::WPA, + crate::binary::include::wifi_auth_mode_t_WIFI_AUTH_WPA2_PSK => { + AuthMethod::WPA2Personal + } + crate::binary::include::wifi_auth_mode_t_WIFI_AUTH_WPA_WPA2_PSK => { + AuthMethod::WPAWPA2Personal + } + crate::binary::include::wifi_auth_mode_t_WIFI_AUTH_WPA2_ENTERPRISE => { + AuthMethod::WPA2Enterprise + } + crate::binary::include::wifi_auth_mode_t_WIFI_AUTH_WPA3_PSK => { + AuthMethod::WPA3Personal + } + crate::binary::include::wifi_auth_mode_t_WIFI_AUTH_WPA2_WPA3_PSK => { + AuthMethod::WPA2WPA3Personal + } + crate::binary::include::wifi_auth_mode_t_WIFI_AUTH_WAPI_PSK => { + AuthMethod::WAPIPersonal + } + _ => panic!(), + }; + + let mut ssid = heapless::String::<32>::new(); + ssid.push_str(ssid_strbuf.as_str_ref()).ok(); + + let ap_info = AccessPointInfo { + ssid: ssid, + bssid: record.bssid, + channel: record.primary, + secondary_channel: match record.second { + crate::binary::include::wifi_second_chan_t_WIFI_SECOND_CHAN_NONE => { + SecondaryChannel::None + } + crate::binary::include::wifi_second_chan_t_WIFI_SECOND_CHAN_ABOVE => { + SecondaryChannel::Above + } + crate::binary::include::wifi_second_chan_t_WIFI_SECOND_CHAN_BELOW => { + SecondaryChannel::Below + } + _ => panic!(), + }, + signal_strength: record.rssi, + protocols: EnumSet::empty(), // TODO + auth_method: auth_method, + }; + + scanned.push(ap_info).ok(); + } + } + + Ok((scanned, bss_total as usize)) + } + + /// Get the currently used configuration. + fn get_configuration(&self) -> Result { + Ok(self.config.clone()) + } + + /// Set the configuration, you need to use Wifi::connect() for connecting + /// Currently only `ssid` and `password` is used. Trying anything but `Configuration::Client` will result in a panic! + fn set_configuration( + &mut self, + conf: &embedded_svc::wifi::Configuration, + ) -> Result<(), Self::Error> { + self.config = conf.clone(); + + match conf { + embedded_svc::wifi::Configuration::None => panic!(), + embedded_svc::wifi::Configuration::Client(_) => {} + embedded_svc::wifi::Configuration::AccessPoint(_) => panic!(), + embedded_svc::wifi::Configuration::Mixed(_, _) => panic!(), + }; + + Ok(()) + } + + fn start(&mut self) -> Result<(), Self::Error> { + let res = crate::wifi::wifi_start(); + if res != 0 { + return Err(WifiError::InternalError(FromPrimitive::from_i32(res).unwrap())); + } + Ok(()) + } + + fn stop(&mut self) -> Result<(), Self::Error> { + let res = crate::wifi::wifi_stop(); + if res != 0 { + return Err(WifiError::InternalError(FromPrimitive::from_i32(res).unwrap())); + } + Ok(()) + } + + fn connect(&mut self) -> Result<(), Self::Error> { + if let embedded_svc::wifi::Configuration::Client(config) = &self.config { + let res = crate::wifi::wifi_connect(&config.ssid, &config.password); + if res != 0 { + return Err(WifiError::InternalError(FromPrimitive::from_i32(res).unwrap())); + } + } else { + panic!(); + } + Ok(()) + } + + fn disconnect(&mut self) -> Result<(), Self::Error> { + //FIXME: Is there a way to disconnect from Wifi? + Ok(()) + } + + fn is_started(&self) -> Result { + match crate::wifi::get_wifi_state() { + crate::wifi::WifiState::StaStart => Ok(true), + crate::wifi::WifiState::StaConnected => Ok(true), + //FIXME: Should any of the enum values trigger an error instead of returning false? + _ => Ok(false), + } + } + + fn is_connected(&self) -> Result { + match crate::wifi::get_wifi_state() { + crate::wifi::WifiState::StaConnected => Ok(true), + crate::wifi::WifiState::StaDisconnected => Err(WifiError::Disconnected), + //FIXME: Should any other enum value trigger an error instead of returning false? + _ => Ok(false), + } + } +} + fn dump_packet_info(buffer: &[u8]) { if !DUMP_PACKETS { return; diff --git a/src/wifi_interface.rs b/src/wifi_interface.rs index 73857e9e..cceef32a 100644 --- a/src/wifi_interface.rs +++ b/src/wifi_interface.rs @@ -4,7 +4,7 @@ use embedded_io::blocking::{Read, Write}; use embedded_io::Io; use embedded_svc::ipv4; -use embedded_svc::wifi::{AccessPointInfo, AuthMethod, SecondaryChannel}; +use embedded_svc::wifi::AccessPointInfo; use enumset::EnumSet; use smoltcp::iface::{Interface, SocketHandle}; use smoltcp::socket::{Dhcpv4Socket, TcpSocket}; @@ -18,7 +18,6 @@ use crate::wifi::WifiDevice; /// An implementation of `embedded-svc`'s wifi trait. pub struct Wifi<'a> { network_interface: Interface<'a, WifiDevice>, - current_config: embedded_svc::wifi::Configuration, pub(crate) network_config: ipv4::Configuration, pub(crate) ip_info: Option, dhcp_socket_handle: Option, @@ -38,7 +37,6 @@ impl<'a> Wifi<'a> { Wifi { network_interface, - current_config: embedded_svc::wifi::Configuration::default(), network_config: ipv4::Configuration::Client(ipv4::ClientConfiguration::DHCP( ipv4::DHCPClientSettings { //FIXME: smoltcp currently doesn't have a way of giving a hostname through DHCP @@ -56,7 +54,7 @@ impl<'a> Wifi<'a> { } /// Convenience function to poll the DHCP socket. - pub fn poll_dhcp(&mut self) -> Result<(), WifiError> { + pub fn poll_dhcp(&mut self) -> Result<(), WifiStackError> { if let Some(dhcp_handle) = self.dhcp_socket_handle { let dhcp_socket = self .network_interface @@ -119,219 +117,69 @@ impl<'a> Wifi<'a> { } #[derive(Debug, Copy, Clone)] -pub enum WifiError { +pub enum WifiStackError { Unknown(i32), SmolTcpError(smoltcp::Error), InitializationError(crate::InitializationError), + DeviceError(crate::wifi::WifiError), MissingIp, - Disconnected, } -impl From for WifiError { +impl From for WifiStackError { fn from(error: smoltcp::Error) -> Self { - WifiError::SmolTcpError(error) + WifiStackError::SmolTcpError(error) } } -impl Display for WifiError { +impl Display for WifiStackError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "{:?}", self) } } -impl<'a> embedded_svc::wifi::Wifi for Wifi<'a> { - type Error = WifiError; +impl embedded_svc::wifi::Wifi for Wifi<'_> { + type Error = crate::wifi::WifiError; - /// This currently only supports the `Client` capability. fn get_capabilities(&self) -> Result, Self::Error> { - // for now we only support STA mode - let mut caps = EnumSet::empty(); - caps.insert(embedded_svc::wifi::Capability::Client); - Ok(caps) + self.network_interface.device().get_capabilities() } - /// A blocking wifi network scan. - fn scan_n( - &mut self, - ) -> Result<(heapless::Vec, usize), Self::Error> { - crate::wifi::wifi_start_scan(); - - let mut scanned = heapless::Vec::::new(); - let mut bss_total: u16 = N as u16; - - unsafe { - crate::binary::include::esp_wifi_scan_get_ap_num(&mut bss_total); - if bss_total as usize > N { - bss_total = N as u16; - } - - let mut records = [crate::binary::include::wifi_ap_record_t { - bssid: [0u8; 6], - ssid: [0u8; 33], - primary: 0u8, - second: 0u32, - rssi: 0i8, - authmode: 0u32, - pairwise_cipher: 0u32, - group_cipher: 0u32, - ant: 0u32, - _bitfield_align_1: [0u32; 0], - _bitfield_1: crate::binary::include::__BindgenBitfieldUnit::new([0u8; 4usize]), - country: crate::binary::include::wifi_country_t { - cc: [0; 3], - schan: 0u8, - nchan: 0u8, - max_tx_power: 0i8, - policy: 0u32, - }, - he_ap: crate::binary::include::wifi_he_ap_info_t { - _bitfield_align_1: [0u8; 0], - _bitfield_1: crate::binary::include::wifi_he_ap_info_t::new_bitfield_1(0, 0, 0), - bssid_index: 0, - }, - }; N]; - - crate::binary::include::esp_wifi_scan_get_ap_records( - &mut bss_total, - &mut records as *mut crate::binary::include::wifi_ap_record_t, - ); - - for i in 0..bss_total { - let record = records[i as usize]; - let ssid_strbuf = crate::compat::common::StrBuf::from(&record.ssid as *const u8); - - let auth_method = match record.authmode { - crate::binary::include::wifi_auth_mode_t_WIFI_AUTH_OPEN => AuthMethod::None, - crate::binary::include::wifi_auth_mode_t_WIFI_AUTH_WEP => AuthMethod::WEP, - crate::binary::include::wifi_auth_mode_t_WIFI_AUTH_WPA_PSK => AuthMethod::WPA, - crate::binary::include::wifi_auth_mode_t_WIFI_AUTH_WPA2_PSK => { - AuthMethod::WPA2Personal - } - crate::binary::include::wifi_auth_mode_t_WIFI_AUTH_WPA_WPA2_PSK => { - AuthMethod::WPAWPA2Personal - } - crate::binary::include::wifi_auth_mode_t_WIFI_AUTH_WPA2_ENTERPRISE => { - AuthMethod::WPA2Enterprise - } - crate::binary::include::wifi_auth_mode_t_WIFI_AUTH_WPA3_PSK => { - AuthMethod::WPA3Personal - } - crate::binary::include::wifi_auth_mode_t_WIFI_AUTH_WPA2_WPA3_PSK => { - AuthMethod::WPA2WPA3Personal - } - crate::binary::include::wifi_auth_mode_t_WIFI_AUTH_WAPI_PSK => { - AuthMethod::WAPIPersonal - } - _ => panic!(), - }; - - let mut ssid = heapless::String::<32>::new(); - ssid.push_str(ssid_strbuf.as_str_ref()).ok(); - - let ap_info = AccessPointInfo { - ssid: ssid, - bssid: record.bssid, - channel: record.primary, - secondary_channel: match record.second { - crate::binary::include::wifi_second_chan_t_WIFI_SECOND_CHAN_NONE => { - SecondaryChannel::None - } - crate::binary::include::wifi_second_chan_t_WIFI_SECOND_CHAN_ABOVE => { - SecondaryChannel::Above - } - crate::binary::include::wifi_second_chan_t_WIFI_SECOND_CHAN_BELOW => { - SecondaryChannel::Below - } - _ => panic!(), - }, - signal_strength: record.rssi, - protocols: EnumSet::empty(), // TODO - auth_method: auth_method, - }; - - scanned.push(ap_info).ok(); - } - } - - Ok((scanned, bss_total as usize)) - } - - /// Get the currently used configuration. fn get_configuration(&self) -> Result { - Ok(self.current_config.clone()) + self.network_interface.device().get_configuration() } - /// Set the configuration, you need to use Wifi::connect() for connecting - /// Currently only `ssid` and `password` is used. Trying anything but `Configuration::Client` will result in a panic! - fn set_configuration( - &mut self, - conf: &embedded_svc::wifi::Configuration, - ) -> Result<(), Self::Error> { - self.current_config = conf.clone(); - - match conf { - embedded_svc::wifi::Configuration::None => panic!(), - embedded_svc::wifi::Configuration::Client(_) => {} - embedded_svc::wifi::Configuration::AccessPoint(_) => panic!(), - embedded_svc::wifi::Configuration::Mixed(_, _) => panic!(), - }; - - Ok(()) + fn set_configuration(&mut self, conf: &embedded_svc::wifi::Configuration) -> Result<(), Self::Error> { + self.network_interface.device_mut().set_configuration(conf) } fn start(&mut self) -> Result<(), Self::Error> { - let res = crate::wifi::wifi_start(); - if res != 0 { - return Err(WifiError::InitializationError( - crate::InitializationError::General(res), - )); - } - Ok(()) + self.network_interface.device_mut().start() } fn stop(&mut self) -> Result<(), Self::Error> { - let res = crate::wifi::wifi_stop(); - if res != 0 { - return Err(WifiError::InitializationError( - crate::InitializationError::General(res), - )); - } - Ok(()) + self.network_interface.device_mut().stop() } fn connect(&mut self) -> Result<(), Self::Error> { - if let embedded_svc::wifi::Configuration::Client(config) = &self.current_config { - let res = crate::wifi::wifi_connect(&config.ssid, &config.password); - if res != 0 { - return Err(WifiError::Unknown(res)); - } - } else { - panic!(); - } - Ok(()) + self.network_interface.device_mut().connect() } fn disconnect(&mut self) -> Result<(), Self::Error> { - //FIXME: Is there a way to disconnect from Wifi? - Ok(()) + self.network_interface.device_mut().disconnect() } fn is_started(&self) -> Result { - match crate::wifi::get_wifi_state() { - crate::wifi::WifiState::StaStart => Ok(true), - crate::wifi::WifiState::StaConnected => Ok(true), - //FIXME: Should any of the enum values trigger an error instead of returning false? - _ => Ok(false), - } + self.network_interface.device().is_started() } fn is_connected(&self) -> Result { - match crate::wifi::get_wifi_state() { - crate::wifi::WifiState::StaConnected => Ok(true), - crate::wifi::WifiState::StaDisconnected => Err(WifiError::Disconnected), - //FIXME: Should any other enum value trigger an error instead of returning false? - _ => Ok(false), - } + self.network_interface.device().is_connected() + } + + fn scan_n( + &mut self, + ) -> Result<(heapless::Vec, usize), Self::Error> { + self.network_interface.device_mut().scan_n::() } } @@ -369,7 +217,7 @@ impl<'a> Network<'a> { f(&mut interface) } - pub fn poll_dhcp(&self) -> Result<(), WifiError> { + pub fn poll_dhcp(&self) -> Result<(), WifiStackError> { self.with_interface(|i| i.poll_dhcp()) } @@ -443,7 +291,7 @@ impl<'a> Network<'a> { } impl<'a> ipv4::Interface for Network<'a> { - type Error = WifiError; + type Error = WifiStackError; fn get_iface_configuration(&self) -> Result { Ok(self.interface.borrow().network_config.clone()) @@ -459,7 +307,7 @@ impl<'a> ipv4::Interface for Network<'a> { } fn get_ip_info(&self) -> Result { - self.interface.borrow().ip_info.ok_or(WifiError::MissingIp) + self.interface.borrow().ip_info.ok_or(WifiStackError::MissingIp) } } From d8b96787cbaef67bce55cd761e263d3a76345bb3 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Thu, 22 Dec 2022 12:25:20 +0000 Subject: [PATCH 2/5] add wifi event --- src/wifi/mod.rs | 28 ++++++++++++++++++++++++++++ src/wifi/os_adapter.rs | 6 +++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/wifi/mod.rs b/src/wifi/mod.rs index e4adc5ab..ba276995 100644 --- a/src/wifi/mod.rs +++ b/src/wifi/mod.rs @@ -98,6 +98,34 @@ pub enum WifiError { WrongClockConfig, Disconnected, } +#[repr(i32)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(FromPrimitive)] +pub enum WifiEvent { + WifiEventWifiReady = 0, + WifiEventScanDone, + WifiEventStaStart, + WifiEventStaStop, + WifiEventStaConnected, + WifiEventStaDisconnected, + WifiEventStaAuthmodeChange, + WifiEventStaWpsErSuccess, + WifiEventStaWpsErFailed, + WifiEventStaWpsErTimeout, + WifiEventStaWpsErPin, + WifiEventStaWpsErPbcOverlap, + WifiEventApStart, + WifiEventApStop, + WifiEventApStaconnected, + WifiEventApStadisconnected, + WifiEventApProbereqrecved, + WifiEventFtmReport, + WifiEventStaBssRssiLow, + WifiEventActionTxStatus, + WifiEventRocDone, + WifiEventStaBeaconTimeout, + WifiEventMax, +} #[repr(i32)] #[derive(Copy, Clone, Debug, PartialEq, Eq)] diff --git a/src/wifi/os_adapter.rs b/src/wifi/os_adapter.rs index 3fae5cc8..4391607e 100644 --- a/src/wifi/os_adapter.rs +++ b/src/wifi/os_adapter.rs @@ -905,7 +905,11 @@ pub unsafe extern "C" fn event_post( wifi_event_t_WIFI_EVENT_STA_STOP => true, wifi_event_t_WIFI_EVENT_STA_CONNECTED => true, wifi_event_t_WIFI_EVENT_STA_DISCONNECTED => true, - _ => false, + _ => { + use num_traits::FromPrimitive; + log::info!("Unhandled event: {:?}", crate::wifi::WifiEvent::from_i32(event_id)); + false + }, }; if take_state { From fc02b5498b38278983c0db4eccfa57eabf5f9ba8 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Thu, 2 Feb 2023 00:17:01 +0000 Subject: [PATCH 3/5] Add missing fields in scan --- src/wifi/mod.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/wifi/mod.rs b/src/wifi/mod.rs index ba276995..021abde0 100644 --- a/src/wifi/mod.rs +++ b/src/wifi/mod.rs @@ -888,6 +888,11 @@ impl embedded_svc::wifi::Wifi for WifiDevice { max_tx_power: 0i8, policy: 0u32, }, + he_ap: crate::binary::include::wifi_he_ap_info_t { + _bitfield_align_1: [0u8; 0], + _bitfield_1: crate::binary::include::wifi_he_ap_info_t::new_bitfield_1(0, 0, 0), + bssid_index: 0, + }, }; N]; crate::binary::include::esp_wifi_scan_get_ap_records( From 3e8dec9ee3395a1b5f8ae794f556a1a8db3d8574 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Thu, 2 Feb 2023 12:05:10 +0000 Subject: [PATCH 4/5] Rework errors in wifi module to return a result --- src/lib.rs | 28 ++++++------ src/wifi/mod.rs | 111 +++++++++++++++++------------------------------- 2 files changed, 51 insertions(+), 88 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 89b8b85c..08d525df 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,6 +27,7 @@ use hal::*; use fugit::MegahertzU32; use hal::clock::Clocks; use linked_list_allocator::Heap; +use wifi::WifiError; use crate::common_adapter::init_rng; use crate::tasks::init_tasks; @@ -135,14 +136,8 @@ pub fn initialize( { log::debug!("wifi init"); // wifi init - let res = crate::wifi::wifi_init(); - if res != 0 { - return Err(InitializationError::General(res)); - } - let res = crate::wifi::wifi_start(); - if res != 0 { - return Err(InitializationError::General(res)); - } + crate::wifi::wifi_init()?; + crate::wifi::wifi_start()?; } #[cfg(feature = "ble")] @@ -160,9 +155,16 @@ pub fn initialize( #[derive(Debug, Clone, Copy)] pub enum InitializationError { General(i32), + WifiError(WifiError), WrongClockConfig, } +impl From for InitializationError { + fn from(value: WifiError) -> Self { + InitializationError::WifiError(value) + } +} + #[cfg(any(feature = "esp32", feature = "esp32s3", feature = "esp32s2"))] /// Initialize for using WiFi / BLE /// This will initialize internals and also initialize WiFi and BLE @@ -206,14 +208,8 @@ pub fn initialize( #[cfg(feature = "wifi")] { log::debug!("wifi init"); - let res = crate::wifi::wifi_init(); - if res != 0 { - return Err(InitializationError::General(res)); - } - let res = crate::wifi::wifi_start(); - if res != 0 { - return Err(InitializationError::General(res)); - } + crate::wifi::wifi_init()?; + crate::wifi::wifi_start()?; } #[cfg(feature = "ble")] diff --git a/src/wifi/mod.rs b/src/wifi/mod.rs index 021abde0..1da1f7a5 100644 --- a/src/wifi/mod.rs +++ b/src/wifi/mod.rs @@ -10,6 +10,7 @@ use embedded_svc::wifi::{AccessPointInfo, AuthMethod, SecondaryChannel}; use enumset::EnumSet; use num_derive::FromPrimitive; use num_traits::FromPrimitive; +use crate::esp_wifi_result; #[doc(hidden)] pub use os_adapter::*; @@ -493,7 +494,7 @@ pub fn get_sta_mac(mac: &mut [u8; 6]) { } } -pub fn wifi_init() -> i32 { +pub fn wifi_init() -> Result<(), WifiError> { unsafe { G_CONFIG.wpa_crypto_funcs = g_wifi_default_wpa_crypto_funcs; G_CONFIG.feature_caps = g_wifi_feature_caps; @@ -509,21 +510,12 @@ pub fn wifi_init() -> i32 { } } - let res = esp_wifi_init_internal(&G_CONFIG); - if res != 0 { - return res; - } + esp_wifi_result!(esp_wifi_init_internal(&G_CONFIG))?; crate::wifi_set_log_verbose(); - let res = esp_supplicant_init(); - if res != 0 { - return res; - } + esp_wifi_result!(esp_supplicant_init())?; - let res = esp_wifi_set_mode(wifi_mode_t_WIFI_MODE_STA); - if res != 0 { - return res; - } + esp_wifi_result!(esp_wifi_set_mode(wifi_mode_t_WIFI_MODE_STA))?; let mut cfg = wifi_config_t { sta: wifi_sta_config_t { @@ -552,20 +544,11 @@ pub fn wifi_init() -> i32 { __bindgen_padding_0: 0u16, }, }; - let res = esp_wifi_set_config(wifi_interface_t_WIFI_IF_STA, &mut cfg); - if res != 0 { - return res; - } + esp_wifi_result!(esp_wifi_set_config(wifi_interface_t_WIFI_IF_STA, &mut cfg))?; - let res = esp_wifi_set_tx_done_cb(Some(esp_wifi_tx_done_cb)); - if res != 0 { - return res; - } + esp_wifi_result!(esp_wifi_set_tx_done_cb(Some(esp_wifi_tx_done_cb)))?; - let res = esp_wifi_internal_reg_rxcb(esp_interface_t_ESP_IF_WIFI_STA, Some(recv_cb)); - if res != 0 { - return res; - } + esp_wifi_result!(esp_wifi_internal_reg_rxcb(esp_interface_t_ESP_IF_WIFI_STA, Some(recv_cb)))?; #[cfg(any(feature = "esp32", feature = "esp32s3"))] { @@ -574,7 +557,7 @@ pub fn wifi_init() -> i32 { &NVS_STRUCT as *const _ as *const u32 as u32; } - 0 + Ok(()) } } @@ -607,22 +590,15 @@ unsafe extern "C" fn esp_wifi_tx_done_cb( debug!("esp_wifi_tx_done_cb"); } -pub fn wifi_start() -> i32 { +pub fn wifi_start() -> Result<(), WifiError> { unsafe { - let res = esp_wifi_start(); - if res != 0 { - return res; - } + esp_wifi_result!(esp_wifi_start())?; #[cfg(any(coex, feature = "ps_min_modem"))] - let res = esp_wifi_set_ps(crate::binary::include::wifi_ps_type_t_WIFI_PS_MIN_MODEM); + esp_wifi_result!(esp_wifi_set_ps(crate::binary::include::wifi_ps_type_t_WIFI_PS_MIN_MODEM))?; #[cfg(not(any(coex, feature = "ps_min_modem")))] - let res = esp_wifi_set_ps(crate::binary::include::wifi_ps_type_t_WIFI_PS_NONE); - - if res != 0 { - return res; - } + esp_wifi_result!(esp_wifi_set_ps(crate::binary::include::wifi_ps_type_t_WIFI_PS_NONE))?; let cntry_code = [b'C', b'N', 0]; let country = wifi_country_t { @@ -632,13 +608,10 @@ pub fn wifi_start() -> i32 { max_tx_power: 20, policy: wifi_country_policy_t_WIFI_COUNTRY_POLICY_MANUAL, }; - let res = esp_wifi_set_country(&country); - if res != 0 { - return res; - } + esp_wifi_result!(esp_wifi_set_country(&country))?; } - 0 + Ok(()) } unsafe extern "C" fn coex_register_start_cb( @@ -669,7 +642,7 @@ pub fn wifi_start_scan() -> i32 { unsafe { esp_wifi_scan_start(&scan_config, true) } } -pub fn wifi_connect(ssid: &str, password: &str) -> i32 { +pub fn wifi_connect(ssid: &str, password: &str) -> Result<(), WifiError> { unsafe { let mut cfg = wifi_config_t { sta: wifi_sta_config_t { @@ -702,17 +675,14 @@ pub fn wifi_connect(ssid: &str, password: &str) -> i32 { cfg.sta.ssid[0..(ssid.len())].copy_from_slice(ssid.as_bytes()); cfg.sta.password[0..(password.len())].copy_from_slice(password.as_bytes()); - let res = esp_wifi_set_config(wifi_interface_t_WIFI_IF_STA, &mut cfg); - if res != 0 { - return res; - } - - esp_wifi_connect() + esp_wifi_result!(esp_wifi_set_config(wifi_interface_t_WIFI_IF_STA, &mut cfg))?; + + esp_wifi_result!(esp_wifi_connect()) } } -pub fn wifi_stop() -> i32 { - unsafe { esp_wifi_stop() } +pub fn wifi_stop() -> Result<(), WifiError> { + unsafe { esp_wifi_result!(esp_wifi_stop()) } } /// A wifi device implementing smoltcp's Device trait. @@ -855,16 +825,13 @@ impl embedded_svc::wifi::Wifi for WifiDevice { fn scan_n( &mut self, ) -> Result<(heapless::Vec, usize), Self::Error> { - let res = crate::wifi::wifi_start_scan(); - if res != 0 { - return Err(WifiError::InternalError(FromPrimitive::from_i32(res).unwrap())); - } + esp_wifi_result!(crate::wifi::wifi_start_scan())?; let mut scanned = heapless::Vec::::new(); let mut bss_total: u16 = N as u16; unsafe { - crate::binary::include::esp_wifi_scan_get_ap_num(&mut bss_total); + esp_wifi_result!(crate::binary::include::esp_wifi_scan_get_ap_num(&mut bss_total))?; if bss_total as usize > N { bss_total = N as u16; } @@ -895,10 +862,10 @@ impl embedded_svc::wifi::Wifi for WifiDevice { }, }; N]; - crate::binary::include::esp_wifi_scan_get_ap_records( + esp_wifi_result!(crate::binary::include::esp_wifi_scan_get_ap_records( &mut bss_total, &mut records as *mut crate::binary::include::wifi_ap_record_t, - ); + ))?; for i in 0..bss_total { let record = records[i as usize]; @@ -984,27 +951,16 @@ impl embedded_svc::wifi::Wifi for WifiDevice { } fn start(&mut self) -> Result<(), Self::Error> { - let res = crate::wifi::wifi_start(); - if res != 0 { - return Err(WifiError::InternalError(FromPrimitive::from_i32(res).unwrap())); - } - Ok(()) + crate::wifi::wifi_start() } fn stop(&mut self) -> Result<(), Self::Error> { - let res = crate::wifi::wifi_stop(); - if res != 0 { - return Err(WifiError::InternalError(FromPrimitive::from_i32(res).unwrap())); - } - Ok(()) + crate::wifi::wifi_stop() } fn connect(&mut self) -> Result<(), Self::Error> { if let embedded_svc::wifi::Configuration::Client(config) = &self.config { - let res = crate::wifi::wifi_connect(&config.ssid, &config.password); - if res != 0 { - return Err(WifiError::InternalError(FromPrimitive::from_i32(res).unwrap())); - } + crate::wifi::wifi_connect(&config.ssid, &config.password)?; } else { panic!(); } @@ -1090,3 +1046,14 @@ fn dump_packet_info(buffer: &[u8]) { smoltcp::wire::EthernetProtocol::Unknown(_) => {} } } + +#[macro_export] +macro_rules! esp_wifi_result { + ($value:expr) => { + if $value != crate::binary::include::ESP_OK as i32 { + Err(WifiError::InternalError(FromPrimitive::from_i32($value).unwrap())) + } else { + core::result::Result::<(), WifiError>::Ok(()) + } + } +} From 9c315180e519b9f90ed77d535659170a5305ce38 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Thu, 2 Feb 2023 12:14:14 +0000 Subject: [PATCH 5/5] Fix examples --- examples/coex.rs | 3 +-- examples/static_ip.rs | 4 ++-- src/lib.rs | 3 +++ src/wifi/mod.rs | 6 +----- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/examples/coex.rs b/examples/coex.rs index b4f99bf5..d79abea8 100644 --- a/examples/coex.rs +++ b/examples/coex.rs @@ -27,8 +27,7 @@ use embedded_svc::wifi::{AccessPointInfo, ClientConfiguration, Configuration, Wi use esp_backtrace as _; use esp_println::{logger::init_logger, print, println}; use esp_wifi::initialize; -use esp_wifi::wifi::utils::create_network_interface; -use esp_wifi::wifi_interface::WifiError; +use esp_wifi::wifi::{WifiError, utils::create_network_interface}; use esp_wifi::{create_network_stack_storage, network_stack_storage}; use hal::{ clock::{ClockControl, CpuClock}, diff --git a/examples/static_ip.rs b/examples/static_ip.rs index 05bdef98..7a511bc0 100644 --- a/examples/static_ip.rs +++ b/examples/static_ip.rs @@ -21,8 +21,8 @@ use embedded_svc::wifi::{AccessPointInfo, ClientConfiguration, Configuration, Wi use esp_backtrace as _; use esp_println::logger::init_logger; use esp_println::{print, println}; -use esp_wifi::wifi::utils::create_network_interface; -use esp_wifi::wifi_interface::{Network, WifiError}; +use esp_wifi::wifi::{WifiError, utils::create_network_interface}; +use esp_wifi::wifi_interface::Network; use esp_wifi::{create_network_stack_storage, network_stack_storage}; use esp_wifi::{current_millis, initialize}; use hal::clock::{ClockControl, CpuClock}; diff --git a/src/lib.rs b/src/lib.rs index 08d525df..a9365358 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,6 +27,7 @@ use hal::*; use fugit::MegahertzU32; use hal::clock::Clocks; use linked_list_allocator::Heap; +#[cfg(feature = "wifi")] use wifi::WifiError; use crate::common_adapter::init_rng; @@ -155,10 +156,12 @@ pub fn initialize( #[derive(Debug, Clone, Copy)] pub enum InitializationError { General(i32), + #[cfg(feature = "wifi")] WifiError(WifiError), WrongClockConfig, } +#[cfg(feature = "wifi")] impl From for InitializationError { fn from(value: WifiError) -> Self { InitializationError::WifiError(value) diff --git a/src/wifi/mod.rs b/src/wifi/mod.rs index 1da1f7a5..55e709e8 100644 --- a/src/wifi/mod.rs +++ b/src/wifi/mod.rs @@ -503,11 +503,7 @@ pub fn wifi_init() -> Result<(), WifiError> { #[cfg(coex)] { - let res = coex_init(); - if res != 0 { - log::error!("coex_init failed"); - return res; - } + esp_wifi_result!(coex_init())?; } esp_wifi_result!(esp_wifi_init_internal(&G_CONFIG))?;