diff --git a/esp-wifi/src/ble/controller/mod.rs b/esp-wifi/src/ble/controller/mod.rs index a296fc2bcf0..9d2f0c861ee 100644 --- a/esp-wifi/src/ble/controller/mod.rs +++ b/esp-wifi/src/ble/controller/mod.rs @@ -5,6 +5,7 @@ use crate::EspWifiInitialization; use super::{read_hci, read_next, send_hci}; +/// A blocking HCI connector pub struct BleConnector<'d> { _device: PeripheralRef<'d, crate::hal::peripherals::BT>, } @@ -76,6 +77,7 @@ impl Write for BleConnector<'_> { } } +/// Async Interface #[cfg(feature = "async")] pub mod asynch { use core::task::Poll; @@ -95,6 +97,7 @@ pub mod asynch { HCI_WAKER.wake(); } + /// Async HCI connector pub struct BleConnector<'d> { _device: PeripheralRef<'d, crate::hal::peripherals::BT>, } diff --git a/esp-wifi/src/ble/mod.rs b/esp-wifi/src/ble/mod.rs index 2920d0bfa66..7cc8cbf11d6 100644 --- a/esp-wifi/src/ble/mod.rs +++ b/esp-wifi/src/ble/mod.rs @@ -1,3 +1,5 @@ +//! Bluetooth Low Energy HCI interface + #[cfg(any(esp32, esp32c3, esp32s3))] pub(crate) mod btdm; @@ -19,15 +21,15 @@ pub(crate) use ble::send_hci; pub mod controller; -pub unsafe extern "C" fn malloc(size: u32) -> *mut crate::binary::c_types::c_void { +pub(crate) unsafe extern "C" fn malloc(size: u32) -> *mut crate::binary::c_types::c_void { crate::compat::malloc::malloc(size as usize).cast() } -pub unsafe extern "C" fn malloc_internal(size: u32) -> *mut crate::binary::c_types::c_void { +pub(crate) unsafe extern "C" fn malloc_internal(size: u32) -> *mut crate::binary::c_types::c_void { crate::compat::malloc::malloc(size as usize).cast() } -pub unsafe extern "C" fn free(ptr: *mut crate::binary::c_types::c_void) { +pub(crate) unsafe extern "C" fn free(ptr: *mut crate::binary::c_types::c_void) { crate::compat::malloc::free(ptr.cast()) } diff --git a/esp-wifi/src/lib.rs b/esp-wifi/src/lib.rs index 84b3ca42306..04272dc04e4 100644 --- a/esp-wifi/src/lib.rs +++ b/esp-wifi/src/lib.rs @@ -164,10 +164,10 @@ fn init_heap() { } #[cfg(any(esp32c3, esp32c2, esp32c6))] -pub type EspWifiTimer = Alarm; +pub(crate) type EspWifiTimer = Alarm; #[cfg(any(esp32, esp32s3, esp32s2))] -pub type EspWifiTimer = hal::timer::Timer>; +pub(crate) type EspWifiTimer = hal::timer::Timer>; #[derive(Debug, PartialEq, PartialOrd)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] diff --git a/esp-wifi/src/wifi/mod.rs b/esp-wifi/src/wifi/mod.rs index 6a9198dc468..aeed7a841ae 100644 --- a/esp-wifi/src/wifi/mod.rs +++ b/esp-wifi/src/wifi/mod.rs @@ -1,3 +1,5 @@ +//! WiFi + pub(crate) mod os_adapter; pub(crate) mod state; @@ -103,6 +105,7 @@ impl AuthMethodExt for AuthMethod { } } +/// Wifi Mode (Sta or Ap) #[derive(Debug, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum WifiMode { @@ -118,6 +121,7 @@ impl WifiMode { WifiMode::try_from(mode) } + /// Returns true if this mode is STA pub fn is_sta(&self) -> bool { match self { WifiMode::Sta => true, @@ -125,6 +129,7 @@ impl WifiMode { } } + /// Returns true if this mode is AP pub fn is_ap(&self) -> bool { match self { WifiMode::Sta => false, @@ -192,6 +197,7 @@ const TX_QUEUE_SIZE: usize = crate::CONFIG.tx_queue_size; pub(crate) static DATA_QUEUE_RX: Mutex>> = Mutex::new(RefCell::new(SimpleQueue::new())); +/// Common errors #[derive(Debug, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum WifiError { @@ -201,6 +207,8 @@ pub enum WifiError { Disconnected, UnknownWifiMode, } + +/// Events generated by the WiFi driver #[repr(i32)] #[derive(Debug, FromPrimitive, EnumSetType)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -229,6 +237,7 @@ pub enum WifiEvent { StaBeaconTimeout, } +/// Error originating from the underlying drivers #[repr(i32)] #[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -371,7 +380,7 @@ pub(crate) fn coex_initialize() -> i32 { } } -pub unsafe extern "C" fn coex_init() -> i32 { +pub(crate) unsafe extern "C" fn coex_init() -> i32 { #[cfg(coex)] { debug!("coex-init"); @@ -591,19 +600,21 @@ static mut G_CONFIG: wifi_init_config_t = wifi_init_config_t { magic: WIFI_INIT_CONFIG_MAGIC as i32, }; +/// Get the STA MAC address pub fn get_sta_mac(mac: &mut [u8; 6]) { unsafe { read_mac(mac as *mut u8, 0); } } +/// Get the AP MAC address pub fn get_ap_mac(mac: &mut [u8; 6]) { unsafe { read_mac(mac as *mut u8, 1); } } -pub fn wifi_init() -> Result<(), WifiError> { +pub(crate) 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; @@ -695,7 +706,7 @@ unsafe extern "C" fn esp_wifi_tx_done_cb( embassy::TRANSMIT_WAKER.wake(); } -pub fn wifi_start() -> Result<(), WifiError> { +pub(crate) fn wifi_start() -> Result<(), WifiError> { unsafe { esp_wifi_result!(esp_wifi_start())?; @@ -833,7 +844,7 @@ pub struct ScanConfig<'a> { pub scan_type: ScanTypeConfig, } -pub fn wifi_start_scan( +pub(crate) fn wifi_start_scan( block: bool, ScanConfig { ssid, @@ -891,6 +902,7 @@ pub fn wifi_start_scan( unsafe { esp_wifi_scan_start(&scan_config, block) } } +/// Create a new [WifiDevice] and [WifiController] from the given config pub fn new_with_config<'d>( inited: &EspWifiInitialization, device: impl Peripheral

+ 'd, @@ -908,6 +920,7 @@ pub fn new_with_config<'d>( )) } +/// Create a new [WifiDevice] and [WifiController] for the given mode pub fn new_with_mode<'d>( inited: &EspWifiInitialization, device: impl Peripheral

+ 'd, @@ -1119,6 +1132,7 @@ impl Device for WifiDevice<'_> { } } +#[doc(hidden)] #[derive(Debug, Default)] pub struct WifiRxToken {} @@ -1131,6 +1145,7 @@ impl RxToken for WifiRxToken { } } +#[doc(hidden)] #[derive(Debug, Default)] pub struct WifiTxToken {} @@ -1199,7 +1214,7 @@ fn esp_wifi_can_send() -> bool { // FIXME data here has to be &mut because of `esp_wifi_internal_tx` signature, requiring a *mut ptr to the buffer // Casting const to mut is instant UB, even though in reality `esp_wifi_internal_tx` copies the buffer into its own memory and // does not modify -pub fn esp_wifi_send_data(interface: wifi_interface_t, data: &mut [u8]) { +pub(crate) fn esp_wifi_send_data(interface: wifi_interface_t, data: &mut [u8]) { trace!("sending... {} bytes", data.len()); dump_packet_info(data); @@ -1380,6 +1395,7 @@ fn dump_packet_info(_buffer: &[u8]) { } } +#[doc(hidden)] #[macro_export] macro_rules! esp_wifi_result { ($value:expr) => {{ diff --git a/esp-wifi/src/wifi/state.rs b/esp-wifi/src/wifi/state.rs index edab7d001fc..17c2f8b56fd 100644 --- a/esp-wifi/src/wifi/state.rs +++ b/esp-wifi/src/wifi/state.rs @@ -3,6 +3,7 @@ use super::WifiEvent; use atomic_enum::atomic_enum; use core::sync::atomic::Ordering; +/// Wifi interface state #[atomic_enum] #[derive(PartialEq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -35,10 +36,12 @@ impl From for WifiState { pub(crate) static STA_STATE: AtomicWifiState = AtomicWifiState::new(WifiState::Invalid); pub(crate) static AP_STATE: AtomicWifiState = AtomicWifiState::new(WifiState::Invalid); +/// Get the current state of the AP pub fn get_ap_state() -> WifiState { AP_STATE.load(Ordering::Relaxed) } +/// Get the current state of the STA pub fn get_sta_state() -> WifiState { STA_STATE.load(Ordering::Relaxed) } diff --git a/esp-wifi/src/wifi/utils.rs b/esp-wifi/src/wifi/utils.rs index 9fde25bfd7f..f783a2874a5 100644 --- a/esp-wifi/src/wifi/utils.rs +++ b/esp-wifi/src/wifi/utils.rs @@ -1,3 +1,5 @@ +//! Convenience utilities for non-async code + use smoltcp::{ iface::{Config, Interface, SocketSet, SocketStorage}, socket::dhcpv4::Socket as Dhcpv4Socket, diff --git a/esp-wifi/src/wifi_interface.rs b/esp-wifi/src/wifi_interface.rs index b7c4484886f..2a6e90e54d8 100644 --- a/esp-wifi/src/wifi_interface.rs +++ b/esp-wifi/src/wifi_interface.rs @@ -1,3 +1,5 @@ +//! Non-async Networking primitives for TCP/UDP communication. + use core::cell::RefCell; use core::fmt::Display; use embedded_io::ErrorType; @@ -14,6 +16,9 @@ use crate::wifi::{get_ap_mac, get_sta_mac, WifiDevice, WifiMode}; use core::borrow::BorrowMut; +/// Non-async TCP/IP network stack +/// +/// Mostly a convenience wrapper for `smoltcp` pub struct WifiStack<'a> { device: RefCell>, // TODO allow non static lifetime network_interface: RefCell, @@ -66,6 +71,7 @@ impl<'a> WifiStack<'a> { this } + /// Update the interface configuration pub fn update_iface_configuration( &self, conf: &ipv4::Configuration, @@ -121,6 +127,7 @@ impl<'a> WifiStack<'a> { Ok(()) } + /// Reset the stack pub fn reset(&self) { debug!("Reset TCP stack"); @@ -228,6 +235,7 @@ impl<'a> WifiStack<'a> { Ok(()) } + /// Create a new [Socket] pub fn get_socket<'s>( &'s self, rx_buffer: &'a mut [u8], @@ -250,6 +258,7 @@ impl<'a> WifiStack<'a> { } } + /// Create a new [UdpSocket] pub fn get_udp_socket<'s>( &'s self, rx_meta: &'a mut [smoltcp::socket::udp::PacketMetadata], @@ -274,10 +283,12 @@ impl<'a> WifiStack<'a> { } } + /// Check if DNS is configured pub fn is_dns_configured(&self) -> bool { self.dns_socket_handle.borrow().is_some() } + /// Configure DNS pub fn configure_dns( &'a self, servers: &[IpAddress], @@ -293,6 +304,7 @@ impl<'a> WifiStack<'a> { self.dns_socket_handle.replace(Some(handle)); } + /// Update the DNS servers pub fn update_dns_servers(&self, servers: &[IpAddress]) { if let Some(dns_handle) = *self.dns_socket_handle.borrow_mut() { self.with_mut(|_interface, _device, sockets| { @@ -303,6 +315,7 @@ impl<'a> WifiStack<'a> { } } + /// Perform a DNS query pub fn dns_query( &self, name: &str, @@ -354,6 +367,9 @@ impl<'a> WifiStack<'a> { } } + /// Let the stack make progress + /// + /// Make sure to regularly call this function. pub fn work(&self) { loop { if let false = self.with_mut(|interface, device, sockets| { @@ -416,6 +432,7 @@ impl<'a> WifiStack<'a> { } } +/// Errors returned by functions in this module #[derive(Debug, Copy, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum WifiStackError { @@ -434,6 +451,7 @@ impl Display for WifiStackError { } } +/// [current_millis] as an Instant pub fn timestamp() -> Instant { Instant::from_millis(current_millis() as i64) } @@ -458,12 +476,14 @@ impl<'a> ipv4::Interface for WifiStack<'a> { } } +/// A TCP socket pub struct Socket<'s, 'n: 's> { socket_handle: SocketHandle, network: &'s WifiStack<'n>, } impl<'s, 'n: 's> Socket<'s, 'n> { + /// Connect the socket pub fn open<'i>(&'i mut self, addr: IpAddress, port: u16) -> Result<(), IoError> where 's: 'i, @@ -500,6 +520,7 @@ impl<'s, 'n: 's> Socket<'s, 'n> { Ok(()) } + /// Listen on the given port. This blocks until there is a peer connected pub fn listen<'i>(&'i mut self, port: u16) -> Result<(), IoError> where 's: 'i, @@ -533,6 +554,7 @@ impl<'s, 'n: 's> Socket<'s, 'n> { Ok(()) } + /// Listen on the given port. This doesn't block pub fn listen_unblocking<'i>(&'i mut self, port: u16) -> Result<(), IoError> where 's: 'i, @@ -550,6 +572,7 @@ impl<'s, 'n: 's> Socket<'s, 'n> { Ok(()) } + /// Closes the socket pub fn close(&mut self) { self.network.with_mut(|_interface, _device, sockets| { sockets.get_mut::(self.socket_handle).close(); @@ -558,6 +581,7 @@ impl<'s, 'n: 's> Socket<'s, 'n> { self.work(); } + /// Disconnect the socket pub fn disconnect(&mut self) { self.network.with_mut(|_interface, _device, sockets| { sockets.get_mut::(self.socket_handle).abort(); @@ -566,12 +590,14 @@ impl<'s, 'n: 's> Socket<'s, 'n> { self.work(); } + /// Checks if the socket is currently open pub fn is_open(&mut self) -> bool { self.network.with_mut(|_interface, _device, sockets| { sockets.get_mut::(self.socket_handle).is_open() }) } + /// Checks if the socket is currently connected pub fn is_connected(&mut self) -> bool { self.network.with_mut(|_interface, _device, sockets| { let socket = sockets.get_mut::(self.socket_handle); @@ -580,6 +606,7 @@ impl<'s, 'n: 's> Socket<'s, 'n> { }) } + /// Delegates to [WifiStack::work] pub fn work(&mut self) { self.network.work() } @@ -592,6 +619,7 @@ impl<'s, 'n: 's> Drop for Socket<'s, 'n> { } } +/// IO Errors #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum IoError { @@ -700,12 +728,14 @@ impl<'s, 'n: 's> Write for Socket<'s, 'n> { } } +/// A UDP socket pub struct UdpSocket<'s, 'n: 's> { socket_handle: SocketHandle, network: &'s WifiStack<'n>, } impl<'s, 'n: 's> UdpSocket<'s, 'n> { + /// Binds the socket to the given port pub fn bind<'i>(&'i mut self, port: u16) -> Result<(), IoError> where 's: 'i, @@ -743,6 +773,7 @@ impl<'s, 'n: 's> UdpSocket<'s, 'n> { Ok(()) } + /// Close the socket pub fn close(&mut self) { self.network.with_mut(|_interface, _device, sockets| { sockets @@ -753,6 +784,7 @@ impl<'s, 'n: 's> UdpSocket<'s, 'n> { self.work(); } + /// Sends data on the socket to the given address pub fn send(&mut self, addr: IpAddress, port: u16, data: &[u8]) -> Result<(), IoError> { loop { self.work(); @@ -788,6 +820,7 @@ impl<'s, 'n: 's> UdpSocket<'s, 'n> { Ok(()) } + /// Receives a single datagram message on the socket pub fn receive(&mut self, data: &mut [u8]) -> Result<(usize, IpAddress, u16), IoError> { self.work(); @@ -806,6 +839,7 @@ impl<'s, 'n: 's> UdpSocket<'s, 'n> { } } + /// This function specifies a new multicast group for this socket to join pub fn join_multicast_group(&mut self, addr: IpAddress) -> Result { self.work(); @@ -822,6 +856,7 @@ impl<'s, 'n: 's> UdpSocket<'s, 'n> { res.map_err(|e| IoError::MultiCastError(e)) } + /// Delegates to [WifiStack::work] pub fn work(&mut self) { self.network.work() }