diff --git a/esp-ieee802154/Cargo.toml b/esp-ieee802154/Cargo.toml index e8f7f37abe3..23ac3c74c71 100644 --- a/esp-ieee802154/Cargo.toml +++ b/esp-ieee802154/Cargo.toml @@ -20,7 +20,7 @@ byte = "0.2.7" critical-section = "1.1.3" document-features = "0.2.10" esp-hal = { version = "0.20.0", path = "../esp-hal" } -esp-wifi-sys = "0.4.0" +esp-wifi-sys = "0.5.0" heapless = "0.8.0" ieee802154 = "0.6.1" log = "0.4.22" diff --git a/esp-ieee802154/src/compat/mod.rs b/esp-ieee802154/src/compat/mod.rs index 8e16abca2e3..3b6238e1845 100644 --- a/esp-ieee802154/src/compat/mod.rs +++ b/esp-ieee802154/src/compat/mod.rs @@ -1,13 +1,10 @@ -#[cfg(feature = "binary-logs")] -mod str_buf; - #[cfg(feature = "binary-logs")] mod binary_logs { - use core::{ffi::VaListImpl, fmt::Write}; - use log::info; - use super::str_buf::StrBuf; + extern "C" { + fn vsnprintf(dst: *mut u8, _n: u32, format: *const u8, ...) -> i32; + } #[no_mangle] pub unsafe extern "C" fn phy_printf(_format: *const u8, _args: ...) { @@ -29,109 +26,10 @@ mod binary_logs { pub unsafe extern "C" fn syslog(format: *const u8, args: VaListImpl) { let mut buf = [0u8; 512]; vsnprintf(&mut buf as *mut u8, 511, format, args); - let res_str = StrBuf::from(&buf as *const u8); - info!("{}", res_str.as_str_ref()); - } - - pub(crate) unsafe fn vsnprintf( - dst: *mut u8, - _n: u32, - format: *const u8, - mut args: VaListImpl, - ) -> i32 { - let fmt_str_ptr = format; - - let mut res_str = StrBuf::new(); - - let strbuf = StrBuf::from(fmt_str_ptr); - let s = strbuf.as_str_ref(); - - let mut format_char = ' '; - let mut is_long = false; - let mut found = false; - for c in s.chars() { - if !found { - if c == '%' { - found = true; - } - - if !found { - res_str.append_char(c); - } - } else if c.is_numeric() || c == '-' || c == 'l' { - if c == 'l' { - is_long = true; - } - // ignore - } else { - // a format char - format_char = c; - } - - if found && format_char != ' ' { - // have to format an arg - match format_char { - 'd' => { - if is_long { - let v = args.arg::(); - write!(res_str, "{}", v).ok(); - } else { - let v = args.arg::(); - write!(res_str, "{}", v).ok(); - } - } - - 'u' => { - let v = args.arg::(); - write!(res_str, "{}", v).ok(); - } - - 'p' => { - let v = args.arg::(); - write!(res_str, "0x{:x}", v).ok(); - } - - 'X' => { - let v = args.arg::(); - write!(res_str, "{:02x}", (v & 0xff000000) >> 24).ok(); - } - - 'x' => { - let v = args.arg::(); - write!(res_str, "{:02x}", v).ok(); - } - - 's' => { - let v = args.arg::() as *const u8; - let vbuf = StrBuf::from(v); - write!(res_str, "{}", vbuf.as_str_ref()).ok(); - } - - 'c' => { - let v = args.arg::(); - if v != 0 { - write!(res_str, "{}", v as char).ok(); - } - } - - _ => { - write!(res_str, "", format_char).ok(); - } - } - - format_char = ' '; - found = false; - is_long = false; - } - } - let mut idx = 0; - res_str.as_str_ref().chars().for_each(|c| { - *(dst.offset(idx)) = c as u8; - idx += 1; - }); - *(dst.offset(idx)) = 0; - - idx as i32 + let res_str = core::ffi::CStr::from_ptr(core::ptr::addr_of!(buf).cast()) + .to_str() + .unwrap(); + info!("{}", res_str); } } diff --git a/esp-ieee802154/src/compat/str_buf.rs b/esp-ieee802154/src/compat/str_buf.rs deleted file mode 100644 index 42693c77a0e..00000000000 --- a/esp-ieee802154/src/compat/str_buf.rs +++ /dev/null @@ -1,58 +0,0 @@ -use core::fmt::Write; - -pub struct StrBuf { - buffer: [u8; 512], - len: usize, -} - -impl StrBuf { - pub fn new() -> StrBuf { - StrBuf { - buffer: [0u8; 512], - len: 0, - } - } - - pub unsafe fn from(c_str: *const u8) -> StrBuf { - let mut res = StrBuf { - buffer: [0u8; 512], - len: 0, - }; - - let mut idx: usize = 0; - while *(c_str.add(idx)) != 0 { - res.buffer[idx] = *(c_str.add(idx)); - idx += 1; - } - - res.len = idx; - res - } - - pub fn append(&mut self, s: &str) { - let mut idx: usize = self.len; - s.chars().for_each(|c| { - self.buffer[idx] = c as u8; - idx += 1; - }); - self.len = idx; - } - - pub fn append_char(&mut self, c: char) { - let mut idx: usize = self.len; - self.buffer[idx] = c as u8; - idx += 1; - self.len = idx; - } - - pub unsafe fn as_str_ref(&self) -> &str { - core::str::from_utf8_unchecked(&self.buffer[..self.len]) - } -} - -impl Write for StrBuf { - fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> { - self.append(s); - Ok(()) - } -} diff --git a/esp-wifi/CHANGELOG.md b/esp-wifi/CHANGELOG.md index e62237419bf..74f31900188 100644 --- a/esp-wifi/CHANGELOG.md +++ b/esp-wifi/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Added support for WPA2-ENTERPRISE (#2004) + ### Changed ### Fixed diff --git a/esp-wifi/Cargo.toml b/esp-wifi/Cargo.toml index 0db7eb5b3ec..5782d368576 100644 --- a/esp-wifi/Cargo.toml +++ b/esp-wifi/Cargo.toml @@ -35,7 +35,7 @@ heapless = { version = "0.8.0", default-features = false, features = [ num-derive = { version = "0.4.2" } num-traits = { version = "0.2.19", default-features = false } no-std-net = { version = "0.6.0", optional = true } -esp-wifi-sys = { version = "0.4.0" } +esp-wifi-sys = { version = "0.5.0" } embassy-sync = { version = "0.6.0", optional = true } embassy-futures = { version = "0.1.1", optional = true } embassy-net-driver = { version = "0.2.0", optional = true } diff --git a/esp-wifi/src/ble/btdm.rs b/esp-wifi/src/ble/btdm.rs index 2c613144f68..88636979b43 100644 --- a/esp-wifi/src/ble/btdm.rs +++ b/esp-wifi/src/ble/btdm.rs @@ -10,7 +10,7 @@ use crate::{ HciOutCollector, HCI_OUT_COLLECTOR, }, - compat::{common::str_from_c, queue::SimpleQueue, task_runner::spawn_task}, + compat::{common::str_from_c, queue::SimpleQueue}, hal::macros::ram, memory_fence::memory_fence, timer::yield_task, @@ -305,21 +305,15 @@ unsafe extern "C" fn task_create( core_id ); - *(handle as *mut usize) = 0; // we will run it in task 0 + let task_func = core::mem::transmute::< + *mut crate::binary::c_types::c_void, + extern "C" fn(*mut esp_wifi_sys::c_types::c_void), + >(func); - if spawn_task( - func, - name as *const i8, - stack_depth, - param, - prio, - handle, - core_id, - ) { - 1 - } else { - 0 - } + let task = crate::preempt::arch_specific::task_create(task_func, param, stack_depth as usize); + *(handle as *mut usize) = task as usize; + + 1 } unsafe extern "C" fn task_delete(_task: *const ()) { diff --git a/esp-wifi/src/ble/npl.rs b/esp-wifi/src/ble/npl.rs index 4f6cd2fc34f..fe0cc5fbf40 100644 --- a/esp-wifi/src/ble/npl.rs +++ b/esp-wifi/src/ble/npl.rs @@ -12,7 +12,7 @@ use crate::{ include::*, }, compat, - compat::{common::str_from_c, queue::SimpleQueue, task_runner::spawn_task}, + compat::{common::str_from_c, queue::SimpleQueue}, timer::yield_task, }; @@ -294,10 +294,10 @@ pub struct ext_funcs_t { hal_uart_init: Option i32>, task_create: Option< unsafe extern "C" fn( - *const c_void, + *mut c_void, *const c_char, u32, - *const c_void, + *mut c_void, u32, *const c_void, u32, @@ -352,10 +352,10 @@ unsafe extern "C" fn os_random() -> u32 { } unsafe extern "C" fn task_create( - task_func: *const c_void, + task_func: *mut c_void, name: *const c_char, stack_depth: u32, - param: *const c_void, + param: *mut c_void, prio: u32, task_handle: *const c_void, core_id: u32, @@ -374,19 +374,15 @@ unsafe extern "C" fn task_create( *(task_handle as *mut usize) = 0; // we will run it in task 0 - if spawn_task( - task_func as *mut c_void, - name as *const c_char, - stack_depth, - param as *mut c_void, - prio, - task_handle as *mut c_void, - core_id, - ) { - 1 - } else { - 0 - } + let task_func = core::mem::transmute::< + *mut crate::binary::c_types::c_void, + extern "C" fn(*mut esp_wifi_sys::c_types::c_void), + >(task_func); + + let task = crate::preempt::arch_specific::task_create(task_func, param, stack_depth as usize); + *(task_handle as *mut usize) = task as usize; + + 1 } unsafe extern "C" fn task_delete(_: *const c_void) { diff --git a/esp-wifi/src/common_adapter/mod.rs b/esp-wifi/src/common_adapter/mod.rs index 4063c94304d..5e4c708ab49 100644 --- a/esp-wifi/src/common_adapter/mod.rs +++ b/esp-wifi/src/common_adapter/mod.rs @@ -1,6 +1,6 @@ use core::ptr::addr_of; -use esp_wifi_sys::include::timespec; +use esp_wifi_sys::include::timeval; use hal::{macros::ram, rng::Rng}; use crate::{ @@ -219,48 +219,8 @@ pub unsafe extern "C" fn puts(s: *const u8) { info!("{}", cstr); } -#[cfg(any(feature = "wifi-logs", nightly))] -#[no_mangle] -pub unsafe extern "C" fn sprintf(dst: *mut u8, format: *const u8, args: ...) -> i32 { - let str = str_from_c(format); - trace!("sprintf format: {}", str); - - let len = crate::compat::syslog::vsnprintf(dst, 512, format, args); - - let s = str_from_c(dst); - trace!("sprintf result: {}", s); - - len -} - -#[cfg(all(not(feature = "wifi-logs"), not(nightly)))] -#[no_mangle] -pub unsafe extern "C" fn sprintf(dst: *mut u8, format: *const u8, _args: *const ()) -> i32 { - let str = str_from_c(format); - - let res = match str { - "ESP_%02X%02X%02X" => "ESP_0000", - "%d,%s,%s,%s" => "????", - "unknown id:%d" => "unknown id:??", - _ => { - warn!("Unexpected call to `sprintf`: {}", str); - "???" - } - }; - - dst.copy_from_nonoverlapping(res.as_ptr(), res.len()); - dst.add(res.len()).write_volatile(0); - - res.len() as i32 -} - #[cfg(feature = "wifi-logs")] mod log { - #[no_mangle] - pub unsafe extern "C" fn printf(s: *const u8, args: ...) { - crate::compat::syslog::syslog(0, s, args); - } - #[no_mangle] pub unsafe extern "C" fn rtc_printf(s: *const u8, args: ...) { crate::compat::syslog::syslog(0, s, args); @@ -289,9 +249,6 @@ mod log { #[cfg(not(feature = "wifi-logs"))] mod log { - #[no_mangle] - pub unsafe extern "C" fn printf(_s: *const u8, _args: *const ()) {} - #[no_mangle] pub unsafe extern "C" fn rtc_printf(_s: *const u8, _args: *const ()) {} @@ -381,12 +338,12 @@ pub unsafe extern "C" fn ets_timer_arm_us( } #[no_mangle] -pub unsafe extern "C" fn gettimeofday(tv: *mut timespec, _tz: *mut ()) -> i32 { +pub unsafe extern "C" fn gettimeofday(tv: *mut timeval, _tz: *mut ()) -> i32 { if !tv.is_null() { unsafe { let microseconds = esp_timer_get_time(); - (*tv).tv_sec = (microseconds / 1_000_000) as i32; - (*tv).tv_nsec = (microseconds % 1_000_000) as i32 * 1000; + (*tv).tv_sec = (microseconds / 1_000_000) as u64; + (*tv).tv_usec = (microseconds % 1_000_000) as u32; } } diff --git a/esp-wifi/src/compat/common.rs b/esp-wifi/src/compat/common.rs index c8a3781eb54..0e2e0398465 100644 --- a/esp-wifi/src/compat/common.rs +++ b/esp-wifi/src/compat/common.rs @@ -5,7 +5,9 @@ use core::{ ptr::{addr_of, addr_of_mut}, }; -use super::queue::SimpleQueue; +use esp_wifi_sys::include::malloc; + +use super::malloc::free; use crate::{ binary::{ c_types::{c_int, c_void}, @@ -16,13 +18,6 @@ use crate::{ timer::yield_task, }; -static mut CURR_SEM: [Option; 20] = [ - None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, - None, None, None, None, -]; - -static mut PER_THREAD_SEM: [Option<*mut c_void>; 4] = [None; 4]; - #[derive(Clone, Copy, Debug)] struct Mutex { locking_pid: usize, @@ -37,8 +32,66 @@ static mut MUTEXES: [Mutex; 10] = [Mutex { }; 10]; static mut MUTEX_IDX_CURRENT: usize = 0; -static mut FAKE_WIFI_QUEUE: *const SimpleQueue<[u8; 8], 200> = unsafe { addr_of!(REAL_WIFI_QUEUE) }; -static mut REAL_WIFI_QUEUE: SimpleQueue<[u8; 8], 200> = SimpleQueue::new(); // first there is a ptr to the real queue - driver checks it's not null +/// A naive and pretty much unsafe queue to back the queues used in drivers and +/// supplicant code +struct RawQueue { + count: usize, + item_size: usize, + current_read: usize, + current_write: usize, + storage: *mut u8, +} + +impl RawQueue { + fn new(count: usize, item_size: usize) -> Self { + let storage = unsafe { malloc((count * item_size) as u32) as *mut u8 }; + Self { + count, + item_size, + current_read: 0, + current_write: 0, + storage, + } + } + + fn free_storage(&mut self) { + unsafe { + free(self.storage); + } + self.storage = core::ptr::null_mut(); + } + + fn enqueue(&mut self, item: *mut c_void) -> i32 { + if (self.current_write - self.current_read) % self.count < self.count { + unsafe { + let p = self.storage.byte_add(self.item_size * self.current_write); + p.copy_from(item as *mut u8, self.item_size); + self.current_write = (self.current_write + 1) % self.count; + } + + 1 + } else { + 0 + } + } + + fn try_dequeue(&mut self, item: *mut c_void) -> bool { + if (self.current_write - self.current_read) % self.count > 0 { + unsafe { + let p = self.storage.byte_add(self.item_size * self.current_read) as *const c_void; + item.copy_from(p, self.item_size); + self.current_read = (self.current_read + 1) % self.count; + } + true + } else { + false + } + } + + fn count(&self) -> usize { + (self.current_write - self.current_read) % self.count + } +} pub unsafe fn str_from_c<'a>(s: *const u8) -> &'a str { let c_str = core::ffi::CStr::from_ptr(s.cast()); @@ -60,33 +113,31 @@ unsafe extern "C" fn strnlen(chars: *const u8, maxlen: usize) -> usize { pub fn sem_create(max: u32, init: u32) -> *mut c_void { critical_section::with(|_| unsafe { - let mut res = 0xffff; - memory_fence(); - for (i, sem) in CURR_SEM.iter().enumerate() { - memory_fence(); - if sem.is_none() { - res = i; - break; - } - } - - trace!("sem created res = {} (+1)", res); + let ptr = malloc(4) as *mut u32; + ptr.write_volatile(init); - if res != 0xffff { - memory_fence(); - CURR_SEM[res] = Some(init); - (res + 1) as *mut c_void - } else { - core::ptr::null_mut() - } + trace!("sem created res = {:?}", ptr); + ptr.cast() }) } pub fn sem_delete(semphr: *mut c_void) { trace!(">>> sem delete"); + + // TODO remove this once fixed in esp_supplicant AND we updated to the fixed - + // JIRA: WIFI-6676 + unsafe { + if semphr as usize > addr_of!(MUTEXES) as usize + && semphr as usize + <= unsafe { addr_of!(MUTEXES).byte_add(size_of_val(&*addr_of!(MUTEXES))) } as usize + { + warn!("trying to remove a mutex via sem_delete"); + return; + } + } + critical_section::with(|_| unsafe { - CURR_SEM[semphr as usize - 1] = None; - memory_fence(); + free(semphr.cast()); }) } @@ -97,18 +148,15 @@ pub fn sem_take(semphr: *mut c_void, tick: u32) -> i32 { let timeout = tick as u64; let start = crate::timer::get_systimer_count(); - let sem_idx = semphr as usize - 1; + let sem = semphr as *mut u32; 'outer: loop { let res = critical_section::with(|_| unsafe { memory_fence(); - if let Some(cnt) = CURR_SEM[sem_idx] { - if cnt > 0 { - CURR_SEM[sem_idx] = Some(cnt - 1); - 1 - } else { - 0 - } + let cnt = *sem; + if cnt > 0 { + *sem = cnt - 1; + 1 } else { 0 } @@ -132,33 +180,18 @@ pub fn sem_take(semphr: *mut c_void, tick: u32) -> i32 { pub fn sem_give(semphr: *mut c_void) -> i32 { trace!("semphr_give {:?}", semphr); - let sem_idx = semphr as usize - 1; + let sem = semphr as *mut u32; critical_section::with(|_| unsafe { - if let Some(cnt) = CURR_SEM[sem_idx] { - CURR_SEM[sem_idx] = Some(cnt + 1); - memory_fence(); - 1 - } else { - 0 - } + let cnt = *sem; + *sem = cnt + 1; + 1 }) } pub fn thread_sem_get() -> *mut c_void { trace!("wifi_thread_semphr_get"); - critical_section::with(|_| unsafe { - let tid = current_task(); - if let Some(sem) = PER_THREAD_SEM[tid] { - trace!("wifi_thread_semphr_get - return for {} {:?}", tid, sem); - sem - } else { - let sem = sem_create(1, 0); - trace!("wifi_thread_semphr_get - create for {} {:?}", tid, sem); - PER_THREAD_SEM[tid] = Some(sem); - sem - } - }) + unsafe { &mut ((*current_task()).thread_semaphore) as *mut _ as *mut c_void } } pub fn create_recursive_mutex() -> *mut c_void { @@ -177,7 +210,7 @@ pub fn lock_mutex(mutex: *mut c_void) -> i32 { trace!("mutex_lock ptr = {:?}", mutex); let ptr = mutex as *mut Mutex; - let current_task = current_task(); + let current_task = current_task() as usize; loop { let mutex_locked = critical_section::with(|_| unsafe { @@ -217,21 +250,28 @@ pub fn unlock_mutex(mutex: *mut c_void) -> i32 { }) } -pub fn create_wifi_queue(queue_len: c_int, item_size: c_int) -> *mut c_void { - trace!( - "wifi_create_queue len={} size={} ptr={:?} real-queue {:?} - not checked", - queue_len, - item_size, - unsafe { addr_of_mut!(FAKE_WIFI_QUEUE) }, - unsafe { addr_of_mut!(REAL_WIFI_QUEUE) }, - ); +pub fn create_queue(queue_len: c_int, item_size: c_int) -> *mut c_void { + trace!("wifi_create_queue len={} size={}", queue_len, item_size,); - if item_size > 8 { - // TODO: don't assume - panic!("don't expecting the wifi queue to hold items larger than 8"); + let queue = RawQueue::new(queue_len as usize, item_size as usize); + let ptr = unsafe { malloc(size_of_val(&queue) as u32) as *mut RawQueue }; + unsafe { + ptr.write(queue); } - unsafe { addr_of_mut!(FAKE_WIFI_QUEUE).cast() } + trace!("created queue @{:?}", ptr); + + ptr.cast() +} + +pub fn delete_queue(queue: *mut c_void) { + trace!("delete_queue {:?}", queue); + + let queue: *mut RawQueue = queue.cast(); + unsafe { + (*queue).free_storage(); + free(queue.cast()); + } } pub fn send_queued(queue: *mut c_void, item: *mut c_void, block_time_tick: u32) -> i32 { @@ -242,30 +282,8 @@ pub fn send_queued(queue: *mut c_void, item: *mut c_void, block_time_tick: u32) block_time_tick ); - // handle the WIFI_QUEUE - unsafe { - if queue != addr_of_mut!(REAL_WIFI_QUEUE).cast() { - warn!("Posting message to an unknown queue"); - return 0; - } - } - - let message = unsafe { - // SAFETY: we checked that our queue is used and it stores with 8 byte items - core::slice::from_raw_parts(item.cast::(), 8) - }; - let mut data: [u8; 8] = unwrap!(message.try_into()); - trace!("queue posting {:?}", data); - - critical_section::with(|_| { - if unsafe { REAL_WIFI_QUEUE.enqueue(data).is_ok() } { - memory_fence(); - 1 - } else { - warn!("queue_send failed"); - 0 - } - }) + let queue: *mut RawQueue = queue.cast(); + critical_section::with(|_| unsafe { (*queue).enqueue(item) }) } pub fn receive_queued(queue: *mut c_void, item: *mut c_void, block_time_tick: u32) -> i32 { @@ -280,23 +298,11 @@ pub fn receive_queued(queue: *mut c_void, item: *mut c_void, block_time_tick: u3 let timeout = block_time_tick as u64; let start = crate::timer::get_systimer_count(); - // handle the WIFI_QUEUE - if queue != unsafe { addr_of_mut!(REAL_WIFI_QUEUE).cast() } { - warn!("Posting message to an unknown queue"); - return 0; - } + let queue: *mut RawQueue = queue.cast(); loop { - let message = critical_section::with(|_| unsafe { REAL_WIFI_QUEUE.dequeue() }); - - if let Some(message) = message { - let out_message = unsafe { - // SAFETY: we checked that our queue is used and it stores with 8 byte items - core::slice::from_raw_parts_mut(item.cast::(), 8) - }; - out_message.copy_from_slice(&message); - trace!("received {:?}", message); - + if critical_section::with(|_| unsafe { (*queue).try_dequeue(item) }) { + trace!("received"); return 1; } @@ -308,13 +314,12 @@ pub fn receive_queued(queue: *mut c_void, item: *mut c_void, block_time_tick: u3 yield_task(); } } + pub fn number_of_messages_in_queue(queue: *const c_void) -> u32 { trace!("queue_msg_waiting {:?}", queue); - if queue != unsafe { addr_of!(REAL_WIFI_QUEUE).cast() } { - warn!("queue_msg_waiting: Unknown queue."); - return 0; - } - critical_section::with(|_| unsafe { REAL_WIFI_QUEUE.len() as u32 }) + + let queue: *const RawQueue = queue.cast(); + critical_section::with(|_| unsafe { (*queue).count() as u32 }) } /// Implementation of sleep() from newlib in esp-idf. @@ -343,6 +348,6 @@ unsafe extern "C" fn usleep(us: u32) -> crate::binary::c_types::c_int { #[no_mangle] unsafe extern "C" fn putchar(c: i32) -> crate::binary::c_types::c_int { - info!("putchar {}", c as u8 as char); + trace!("putchar {}", c as u8 as char); c } diff --git a/esp-wifi/src/compat/malloc.rs b/esp-wifi/src/compat/malloc.rs index 7fb31cda7fe..0647db0ff90 100644 --- a/esp-wifi/src/compat/malloc.rs +++ b/esp-wifi/src/compat/malloc.rs @@ -2,6 +2,7 @@ use core::alloc::Layout; use crate::HEAP; +#[no_mangle] pub unsafe extern "C" fn malloc(size: usize) -> *mut u8 { trace!("alloc {}", size); @@ -24,6 +25,7 @@ pub unsafe extern "C" fn malloc(size: usize) -> *mut u8 { ptr.offset(4) } +#[no_mangle] pub unsafe extern "C" fn free(ptr: *mut u8) { trace!("free {:?}", ptr); @@ -56,3 +58,25 @@ pub unsafe extern "C" fn calloc(number: u32, size: usize) -> *mut u8 { ptr } + +#[no_mangle] +unsafe extern "C" fn realloc(ptr: *mut u8, new_size: usize) -> *mut u8 { + trace!("realloc {:?} {}", ptr, new_size); + + extern "C" { + fn memcpy(d: *mut u8, s: *const u8, l: usize); + } + + unsafe { + let p = malloc(new_size); + if !p.is_null() && !ptr.is_null() { + let len = usize::min( + (ptr as *const u32).sub(1).read_volatile() as usize, + new_size, + ); + memcpy(p, ptr, len); + free(ptr); + } + p + } +} diff --git a/esp-wifi/src/compat/misc.rs b/esp-wifi/src/compat/misc.rs new file mode 100644 index 00000000000..1ac65abeca3 --- /dev/null +++ b/esp-wifi/src/compat/misc.rs @@ -0,0 +1,205 @@ +use crate::compat::malloc::*; + +#[no_mangle] +unsafe extern "C" fn fwrite(ptr: *const (), size: usize, count: usize, stream: *const ()) -> usize { + todo!("fwrite {:?} {} {} {:?}", ptr, size, count, stream) +} + +#[no_mangle] +unsafe extern "C" fn fopen(filename: *const u8, mode: *const u8) -> *const () { + todo!("fopen {:?} {:?}", filename, mode) +} + +#[no_mangle] +unsafe extern "C" fn fgets(str: *const u8, count: u32, file: *const ()) -> *const u8 { + todo!("fgets {:?} {} {:?}", str, count, file) +} + +#[no_mangle] +unsafe extern "C" fn fclose(stream: *const ()) -> i32 { + todo!("fclose {:?}", stream); +} + +#[no_mangle] +unsafe extern "C" fn strcat(destination: *mut u8, source: *const u8) -> *const u8 { + trace!("strcat {:?} {:?}", destination, source); + + let dst: *mut u8 = strchr(destination.cast(), 0) as *mut u8; + let len = strchr(source.cast(), 0) as usize - source as usize; + core::ptr::copy(source, dst, len); + destination +} + +#[no_mangle] +unsafe extern "C" fn strcmp(str1: *const i8, str2: *const i8) -> i32 { + trace!("strcmp {:?} {:?}", str1, str2); + + let s1 = core::ffi::CStr::from_ptr(str1).to_str().unwrap(); + let s2 = core::ffi::CStr::from_ptr(str2).to_str().unwrap(); + + let x = s1.cmp(s2); + + match x { + core::cmp::Ordering::Less => -1, + core::cmp::Ordering::Equal => 0, + core::cmp::Ordering::Greater => 1, + } +} + +#[no_mangle] +unsafe extern "C" fn strchr(str: *const i8, c: i32) -> *const i8 { + trace!("strchr {:?} {}", str, c); + + unsafe { + let mut p = str; + loop { + if *p == c as i8 { + return p; + } + + if *p == 0 { + return core::ptr::null(); + } + + p = p.add(1); + } + } +} + +#[no_mangle] +unsafe extern "C" fn strlcpy(dst: *mut u8, src: *const u8, size: usize) -> usize { + trace!("strlcpy {:?} {:?} {}", dst, src, size); + + let mut dst = dst; + let mut src = src; + let mut cnt = 0; + loop { + dst.write_volatile(0); + + let c = src.read_volatile(); + + if c == 0 || cnt >= size { + break; + } + + dst.write_volatile(c); + dst = dst.add(1); + src = src.add(1); + cnt += 1; + } + + cnt +} + +#[no_mangle] +unsafe extern "C" fn strstr(str1: *const i8, str2: *const i8) -> *const i8 { + trace!("strstr {:?} {:?}", str1, str2); + + let s1 = core::ffi::CStr::from_ptr(str1).to_str().unwrap(); + let s2 = core::ffi::CStr::from_ptr(str2).to_str().unwrap(); + + let idx = s1.find(s2); + + match idx { + Some(offset) => str1.add(offset), + None => core::ptr::null(), + } +} + +#[no_mangle] +unsafe extern "C" fn strcasecmp(str1: *const u8, str2: *const u8) -> i32 { + trace!("strcasecmp {:?} {:?}", str1, str2); + + let mut str1 = str1; + let mut str2 = str2; + + let mut c1 = *str1 as char; + let mut c2 = *str2 as char; + + while c1 != '\0' && c2 != '\0' { + c1 = c1.to_ascii_lowercase(); + c2 = c2.to_ascii_lowercase(); + + if c1 != c2 { + return c1 as i32 - c2 as i32; + } + + str1 = str1.add(1); + str2 = str2.add(1); + + c1 = *str1 as char; + c2 = *str2 as char; + } + + c1 as i32 - c2 as i32 +} + +#[no_mangle] +unsafe extern "C" fn strdup(str: *const i8) -> *const u8 { + trace!("strdup {:?}", str); + + unsafe { + let s = core::ffi::CStr::from_ptr(str); + let s = s.to_str().unwrap(); + + let p = malloc(s.len() + 1); + core::ptr::copy_nonoverlapping(str, p as *mut i8, s.len() + 1); + p as *const u8 + } +} + +#[no_mangle] +unsafe extern "C" fn atoi(str: *const i8) -> i32 { + trace!("atoi {:?}", str); + + unsafe { + let s = core::ffi::CStr::from_ptr(str); + let r = s.to_str().unwrap().parse().unwrap(); + r + } +} + +#[derive(Debug, Copy, Clone)] +#[repr(C)] +struct Tm { + tm_sec: u32, // seconds after the minute - [0, 60] including leap second + tm_min: u32, // minutes after the hour - [0, 59] + tm_hour: u32, // hours since midnight - [0, 23] + tm_mday: u32, // day of the month - [1, 31] + tm_mon: u32, // months since January - [0, 11] + tm_year: u32, // years since 1900 + tm_wday: u32, // days since Sunday - [0, 6] + tm_yday: u32, // days since January 1 - [0, 365] + tm_isdst: u32, // daylight savings time flag +} + +#[no_mangle] +unsafe extern "C" fn mktime(time: *const Tm) -> i64 { + trace!("mktime {:?}", time); + let time = *time; + + // Simplified implementation, ignoring time zones, leap seconds, and other + // complexities + let mut days_in_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + + let is_leap_year = |year: u32| year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); + + let mut days = 0; + let year = time.tm_year + 1900; + for y in 1970..year { + days += if is_leap_year(y) { 366 } else { 365 }; + } + + if is_leap_year(year) { + days_in_month[1] = 29; + } + + for m in 0..time.tm_mon { + days += days_in_month[m as usize]; + } + days += time.tm_mday - 1; + + let seconds = days * 24 * 60 * 60 + time.tm_hour * 60 * 60 + time.tm_min * 60 + time.tm_sec; + + seconds as i64 +} diff --git a/esp-wifi/src/compat/mod.rs b/esp-wifi/src/compat/mod.rs index 2a579922d0f..b694b5ebceb 100644 --- a/esp-wifi/src/compat/mod.rs +++ b/esp-wifi/src/compat/mod.rs @@ -1,10 +1,30 @@ pub mod common; pub mod malloc; +pub mod misc; #[cfg(any(feature = "wifi-logs", nightly))] pub mod syslog; -pub mod task_runner; pub mod timer_compat; pub mod queue { pub use heapless::spsc::Queue as SimpleQueue; } + +#[no_mangle] +unsafe extern "C" fn _putchar(c: u8) { + static mut BUFFER: [u8; 256] = [0u8; 256]; + static mut IDX: usize = 0; + + if c == 0 || c == b'\n' || IDX == BUFFER.len() - 1 { + if c != 0 { + BUFFER[IDX] = c; + } else { + IDX = IDX.saturating_sub(1); + } + + info!("{}", core::str::from_utf8_unchecked(&BUFFER[..IDX])); + IDX = 0; + } else { + BUFFER[IDX] = c; + IDX += 1; + } +} diff --git a/esp-wifi/src/compat/syslog.rs b/esp-wifi/src/compat/syslog.rs index e49cd92340b..ef44bd8468e 100644 --- a/esp-wifi/src/compat/syslog.rs +++ b/esp-wifi/src/compat/syslog.rs @@ -1,72 +1,4 @@ -use core::{ffi::VaListImpl, fmt::Write}; - -use super::common::str_from_c; - -pub struct StrWriter { - dst: *mut u8, - capacity: usize, - len: usize, -} - -impl StrWriter { - pub fn new(dst: *mut u8, capacity: usize) -> Self { - Self { - dst, - capacity, - len: 0, - } - } - - pub fn len(&self) -> usize { - self.len - } - - fn space(&self) -> usize { - self.capacity - self.len - } - - fn write(&mut self, byte: u8) { - unsafe { - self.dst.write(byte); - self.dst = self.dst.add(1); - } - } - - pub fn append_char(&mut self, c: char) { - let mut buf = [0u8; 4]; - let char = c.encode_utf8(&mut buf); - self.append(char); - } - - pub fn append(&mut self, s: &str) { - // Write as many bytes as possible. We're writing a c string which means we - // don't have to deal with utf8 character boundaries, so this should be - // fine. - let len = s.len().min(self.space()); - for byte in &s.as_bytes()[..len] { - self.write(*byte); - } - - // vsnprintf's semantics: it counts unwritten bytes, too - self.len += s.len(); - } - - pub fn append_byte(&mut self, b: u8) { - if self.space() >= 1 { - self.write(b); - } - - // vsnprintf's semantics: it counts unwritten bytes, too - self.len += 1; - } -} - -impl Write for StrWriter { - fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> { - self.append(s); - Ok(()) - } -} +use core::ffi::VaListImpl; #[allow(unused)] pub unsafe extern "C" fn syslog(_priority: u32, _format: *const u8, _args: VaListImpl) { @@ -86,110 +18,3 @@ pub unsafe extern "C" fn syslog(_priority: u32, _format: *const u8, _args: VaLis } } } - -/// Returns the number of character that would have been written if the buffer -/// was big enough. -pub(crate) unsafe fn vsnprintf( - dst: *mut u8, - capacity: u32, - format: *const u8, - mut args: VaListImpl, -) -> i32 { - let mut res_str = StrWriter::new(dst, capacity as usize - 1); - - let s = str_from_c(format); - - let mut format_char = ' '; - let mut is_long = 0; - let mut found = false; - for c in s.chars() { - if !found { - if c == '%' { - found = true; - } - - if !found { - res_str.append_char(c); - } - } else if c.is_numeric() || c == '-' || c == 'l' { - if c == 'l' { - is_long += 1; - } - // ignore - } else { - // a format char - format_char = c; - } - - if found && format_char != ' ' { - // have to format an arg - match format_char { - 'd' => { - if is_long < 2 { - let v = args.arg::(); - write!(res_str, "{}", v).ok(); - } else { - let v = args.arg::(); - write!(res_str, "{}", v).ok(); - } - } - - 'u' => { - if is_long < 2 { - let v = args.arg::(); - write!(res_str, "{}", v).ok(); - } else { - let v = args.arg::(); - write!(res_str, "{}", v).ok(); - } - } - - 'p' => { - let v = args.arg::(); - write!(res_str, "0x{:x}", v).ok(); - } - - 'X' => { - let v = args.arg::(); - write!(res_str, "{:02X}", v).ok(); - } - - 'x' => { - let v = args.arg::(); - write!(res_str, "{:02x}", v).ok(); - } - - 's' => { - let v = args.arg::<*const u8>(); - let vbuf = str_from_c(v); - res_str.append(vbuf); - } - - 'c' => { - let v = args.arg::(); - if v != 0 { - res_str.append_byte(v); - } - } - - '%' => { - res_str.append_char('%'); - } - - _ => { - write!(res_str, "", format_char).ok(); - } - } - - format_char = ' '; - found = false; - is_long = 0; - } - } - - let chars_written = res_str.len(); - let terminating_at = chars_written.min(capacity as usize - 1); - dst.add(terminating_at).write(0); - - chars_written as i32 -} diff --git a/esp-wifi/src/compat/task_runner.rs b/esp-wifi/src/compat/task_runner.rs deleted file mode 100644 index 4186dc443c8..00000000000 --- a/esp-wifi/src/compat/task_runner.rs +++ /dev/null @@ -1,56 +0,0 @@ -use super::queue::SimpleQueue; -use crate::{binary::c_types, compat::common::str_from_c, timer::yield_task}; - -type TaskFunc = (extern "C" fn(*mut c_types::c_void), *mut c_types::c_void); - -static mut TASK_SPAWN_QUEUE: SimpleQueue = SimpleQueue::new(); - -pub fn spawn_task( - task_func: *mut c_types::c_void, - name: *const c_types::c_char, - _stack_depth: u32, - param: *mut c_types::c_void, - prio: u32, - _task_handle: *mut c_types::c_void, - _core_id: u32, -) -> bool { - debug!( - "spawning task {}: {:?} param {:?} prio {}", - unsafe { str_from_c(name.cast()) }, - task_func, - param, - prio - ); - - // TODO: allocate a stack and insert into the task queue - - critical_section::with(|_| unsafe { - if TASK_SPAWN_QUEUE - .enqueue(( - core::mem::transmute::<*mut c_types::c_void, extern "C" fn(*mut c_types::c_void)>( - task_func, - ), - param, - )) - .is_ok() - { - true - } else { - warn!("task spawn queue full"); - false - } - }) -} - -/// This function runs a single C task started by the wifi stack. -pub(crate) extern "C" fn run_c_task() { - loop { - // Take a task and run it. - if let Some((f, p)) = critical_section::with(|_| unsafe { TASK_SPAWN_QUEUE.dequeue() }) { - debug!("task started: {:?} {:?}", f, p); - f(p); - debug!("task finished: {:?} {:?}", f, p); - } - yield_task(); - } -} diff --git a/esp-wifi/src/lib.rs b/esp-wifi/src/lib.rs index 094a6e2785b..cac6719ca92 100644 --- a/esp-wifi/src/lib.rs +++ b/esp-wifi/src/lib.rs @@ -73,6 +73,12 @@ const DEFAULT_TICK_RATE_HZ: u32 = 50; #[cfg(not(debug_assertions))] const DEFAULT_TICK_RATE_HZ: u32 = 100; +#[cfg(not(coex))] +const DEFAULT_HEAP_SIZE: usize = 81920; + +#[cfg(coex)] +const DEFAULT_HEAP_SIZE: usize = 90112; + #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[toml_cfg::toml_config] @@ -106,7 +112,7 @@ struct Config { country_code_operating_class: u8, #[default(1492)] mtu: usize, - #[default(65536)] + #[default(DEFAULT_HEAP_SIZE)] heap_size: usize, #[default(DEFAULT_TICK_RATE_HZ)] tick_rate_hz: u32, diff --git a/esp-wifi/src/preempt/mod.rs b/esp-wifi/src/preempt/mod.rs index be2d843e259..9441ec0afff 100644 --- a/esp-wifi/src/preempt/mod.rs +++ b/esp-wifi/src/preempt/mod.rs @@ -1,49 +1,112 @@ -macro_rules! sum { - ($h:expr) => ($h); - ($h:expr, $($t:expr),*) => - ($h + sum!($($t),*)); -} +#[cfg_attr(target_arch = "riscv32", path = "preempt_riscv.rs")] +#[cfg_attr(target_arch = "xtensa", path = "preempt_xtensa.rs")] +pub mod arch_specific; + +use core::cell::RefCell; + +use arch_specific::*; +use critical_section::Mutex; +use esp_wifi_sys::include::malloc; + +use crate::{compat::malloc::free, hal::trapframe::TrapFrame, memory_fence::memory_fence}; + +static mut CTX_NOW: Mutex> = Mutex::new(RefCell::new(core::ptr::null_mut())); -macro_rules! task_stack { - ($($task_stack_size:literal),+) => { - const TASK_COUNT: usize = [$($task_stack_size),+].len(); - const TASK_STACK_SIZE: [usize; TASK_COUNT] = [$($task_stack_size),+]; - const TOTAL_STACK_SIZE: usize = sum!($($task_stack_size),+); - const MAX_TASK: usize = TASK_COUNT + 1; // +1 for the user program +static mut SCHEDULED_TASK_TO_DELETE: *mut Context = core::ptr::null_mut(); - static mut TASK_STACK: [u8; TOTAL_STACK_SIZE] = [0u8; TOTAL_STACK_SIZE]; - }; +pub fn allocate_main_task() -> *mut Context { + critical_section::with(|cs| unsafe { + let mut ctx_now = CTX_NOW.borrow_ref_mut(cs); + if !(*ctx_now).is_null() { + panic!("Tried to allocate main task multiple times"); + } + + let ptr = malloc(size_of::() as u32) as *mut Context; + core::ptr::write_bytes(ptr, 0, 1); + (*ptr).next = ptr; + *ctx_now = ptr; + ptr + }) } -static mut TASK_TOP: usize = 1; -static mut CTX_NOW: usize = 0; +fn allocate_task() -> *mut Context { + critical_section::with(|cs| unsafe { + let mut ctx_now = CTX_NOW.borrow_ref_mut(cs); + if (*ctx_now).is_null() { + panic!("Called `allocate_task` before allocating main task"); + } -fn allocate_task() -> usize { - unsafe { - let i = TASK_TOP - 1; - CTX_NOW = TASK_TOP; - TASK_TOP += 1; - i - } + let ptr = malloc(size_of::() as u32) as *mut Context; + core::ptr::write_bytes(ptr, 0, 1); + (*ptr).next = (**ctx_now).next; + (**ctx_now).next = ptr; + ptr + }) } fn next_task() { + critical_section::with(|cs| unsafe { + let mut ctx_now = CTX_NOW.borrow_ref_mut(cs); + *ctx_now = (**ctx_now).next; + }); +} + +/// Delete the given task. +/// +/// This will also free the memory (stack and context) allocated for it. +fn delete_task(task: *mut Context) { + critical_section::with(|cs| unsafe { + let mut ptr = *CTX_NOW.borrow_ref_mut(cs); + let initial = ptr; + loop { + if (*ptr).next == task { + (*ptr).next = (*((*ptr).next)).next; + + free((*task).allocated_stack as *mut u8); + free(task as *mut u8); + break; + } + + ptr = (*ptr).next; + + if ptr == initial { + break; + } + } + + memory_fence(); + }); +} + +pub fn current_task() -> *mut Context { + critical_section::with(|cs| unsafe { *CTX_NOW.borrow_ref(cs) }) +} + +#[cfg(feature = "wifi")] +pub fn schedule_task_deletion(task: *mut Context) { + use crate::timer::yield_task; + unsafe { - CTX_NOW = (CTX_NOW + 1) % TASK_TOP; + SCHEDULED_TASK_TO_DELETE = task; } -} -pub fn current_task() -> usize { - unsafe { CTX_NOW } + if task == current_task() { + loop { + yield_task(); + } + } } -#[cfg(coex)] -task_stack!(8192, 8192, 8192); +pub fn task_switch(trap_frame: &mut TrapFrame) { + save_task_context(current_task(), trap_frame); -#[cfg(not(coex))] -task_stack!(8192, 8192); + unsafe { + if !SCHEDULED_TASK_TO_DELETE.is_null() { + delete_task(SCHEDULED_TASK_TO_DELETE); + SCHEDULED_TASK_TO_DELETE = core::ptr::null_mut(); + } + } -#[cfg_attr(target_arch = "riscv32", path = "preempt_riscv.rs")] -#[cfg_attr(target_arch = "xtensa", path = "preempt_xtensa.rs")] -#[allow(clippy::module_inception)] -pub mod preempt; + next_task(); + restore_task_context(current_task(), trap_frame); +} diff --git a/esp-wifi/src/preempt/preempt_riscv.rs b/esp-wifi/src/preempt/preempt_riscv.rs index 9b4a87aae42..a729fb0bf0a 100644 --- a/esp-wifi/src/preempt/preempt_riscv.rs +++ b/esp-wifi/src/preempt/preempt_riscv.rs @@ -1,165 +1,109 @@ -use core::ptr::addr_of; +use esp_wifi_sys::c_types; use super::*; use crate::hal::interrupt::TrapFrame; -#[derive(Debug, Default, Clone, Copy)] +#[derive(Debug, Clone, Copy)] pub struct Context { trap_frame: TrapFrame, - _running: bool, + pub thread_semaphore: u32, + pub next: *mut Context, + pub allocated_stack: *const u8, } -static mut CTX_TASKS: [Context; MAX_TASK] = [Context { - trap_frame: TrapFrame { - ra: 0, - t0: 0, - t1: 0, - t2: 0, - t3: 0, - t4: 0, - t5: 0, - t6: 0, - a0: 0, - a1: 0, - a2: 0, - a3: 0, - a4: 0, - a5: 0, - a6: 0, - a7: 0, - s0: 0, - s1: 0, - s2: 0, - s3: 0, - s4: 0, - s5: 0, - s6: 0, - s7: 0, - s8: 0, - s9: 0, - s10: 0, - s11: 0, - gp: 0, - tp: 0, - sp: 0, - pc: 0, - mstatus: 0, - mcause: 0, - mtval: 0, - }, - _running: false, -}; MAX_TASK]; - -pub fn task_create(task: extern "C" fn()) { +pub fn task_create( + task: extern "C" fn(*mut c_types::c_void), + param: *mut c_types::c_void, + task_stack_size: usize, +) -> *mut Context { unsafe { - let i = allocate_task(); + let ctx = allocate_task(); - CTX_TASKS[i].trap_frame.pc = task as usize; + (*ctx).trap_frame.pc = task as usize; + (*ctx).trap_frame.a0 = param as usize; - let task_stack_size = TASK_STACK_SIZE[i]; + let stack = malloc(task_stack_size as u32); + (*ctx).allocated_stack = stack.cast(); // stack must be aligned by 16 - let task_stack_ptr = - addr_of!(TASK_STACK) as usize + (task_stack_size * i) + task_stack_size - 4; + let task_stack_ptr = stack as usize + task_stack_size; let stack_ptr = task_stack_ptr - (task_stack_ptr % 0x10); - CTX_TASKS[i].trap_frame.sp = stack_ptr; + (*ctx).trap_frame.sp = stack_ptr; + + ctx } } -pub fn restore_task_context(id: usize, trap_frame: &mut TrapFrame) -> usize { +pub fn restore_task_context(ctx: *mut Context, trap_frame: &mut TrapFrame) { unsafe { - trap_frame.ra = CTX_TASKS[id].trap_frame.ra; - trap_frame.sp = CTX_TASKS[id].trap_frame.sp; - trap_frame.a0 = CTX_TASKS[id].trap_frame.a0; - trap_frame.a1 = CTX_TASKS[id].trap_frame.a1; - trap_frame.a2 = CTX_TASKS[id].trap_frame.a2; - trap_frame.a3 = CTX_TASKS[id].trap_frame.a3; - trap_frame.a4 = CTX_TASKS[id].trap_frame.a4; - trap_frame.a5 = CTX_TASKS[id].trap_frame.a5; - trap_frame.a6 = CTX_TASKS[id].trap_frame.a6; - trap_frame.a7 = CTX_TASKS[id].trap_frame.a7; - trap_frame.t0 = CTX_TASKS[id].trap_frame.t0; - trap_frame.t1 = CTX_TASKS[id].trap_frame.t1; - trap_frame.t2 = CTX_TASKS[id].trap_frame.t2; - trap_frame.t3 = CTX_TASKS[id].trap_frame.t3; - trap_frame.t4 = CTX_TASKS[id].trap_frame.t4; - trap_frame.t5 = CTX_TASKS[id].trap_frame.t5; - trap_frame.t6 = CTX_TASKS[id].trap_frame.t6; - trap_frame.s0 = CTX_TASKS[id].trap_frame.s0; - trap_frame.s1 = CTX_TASKS[id].trap_frame.s1; - trap_frame.s2 = CTX_TASKS[id].trap_frame.s2; - trap_frame.s3 = CTX_TASKS[id].trap_frame.s3; - trap_frame.s4 = CTX_TASKS[id].trap_frame.s4; - trap_frame.s5 = CTX_TASKS[id].trap_frame.s5; - trap_frame.s6 = CTX_TASKS[id].trap_frame.s6; - trap_frame.s7 = CTX_TASKS[id].trap_frame.s7; - trap_frame.s8 = CTX_TASKS[id].trap_frame.s8; - trap_frame.s9 = CTX_TASKS[id].trap_frame.s9; - trap_frame.s10 = CTX_TASKS[id].trap_frame.s10; - trap_frame.s11 = CTX_TASKS[id].trap_frame.s11; - trap_frame.gp = CTX_TASKS[id].trap_frame.gp; - trap_frame.tp = CTX_TASKS[id].trap_frame.tp; - - CTX_TASKS[id].trap_frame.pc + trap_frame.ra = (*ctx).trap_frame.ra; + trap_frame.sp = (*ctx).trap_frame.sp; + trap_frame.a0 = (*ctx).trap_frame.a0; + trap_frame.a1 = (*ctx).trap_frame.a1; + trap_frame.a2 = (*ctx).trap_frame.a2; + trap_frame.a3 = (*ctx).trap_frame.a3; + trap_frame.a4 = (*ctx).trap_frame.a4; + trap_frame.a5 = (*ctx).trap_frame.a5; + trap_frame.a6 = (*ctx).trap_frame.a6; + trap_frame.a7 = (*ctx).trap_frame.a7; + trap_frame.t0 = (*ctx).trap_frame.t0; + trap_frame.t1 = (*ctx).trap_frame.t1; + trap_frame.t2 = (*ctx).trap_frame.t2; + trap_frame.t3 = (*ctx).trap_frame.t3; + trap_frame.t4 = (*ctx).trap_frame.t4; + trap_frame.t5 = (*ctx).trap_frame.t5; + trap_frame.t6 = (*ctx).trap_frame.t6; + trap_frame.s0 = (*ctx).trap_frame.s0; + trap_frame.s1 = (*ctx).trap_frame.s1; + trap_frame.s2 = (*ctx).trap_frame.s2; + trap_frame.s3 = (*ctx).trap_frame.s3; + trap_frame.s4 = (*ctx).trap_frame.s4; + trap_frame.s5 = (*ctx).trap_frame.s5; + trap_frame.s6 = (*ctx).trap_frame.s6; + trap_frame.s7 = (*ctx).trap_frame.s7; + trap_frame.s8 = (*ctx).trap_frame.s8; + trap_frame.s9 = (*ctx).trap_frame.s9; + trap_frame.s10 = (*ctx).trap_frame.s10; + trap_frame.s11 = (*ctx).trap_frame.s11; + trap_frame.gp = (*ctx).trap_frame.gp; + trap_frame.tp = (*ctx).trap_frame.tp; + trap_frame.pc = (*ctx).trap_frame.pc; } } -pub fn save_task_context(id: usize, pc: usize, trap_frame: &TrapFrame) { +pub fn save_task_context(ctx: *mut Context, trap_frame: &TrapFrame) { unsafe { - CTX_TASKS[id].trap_frame.ra = trap_frame.ra; - CTX_TASKS[id].trap_frame.sp = trap_frame.sp; - CTX_TASKS[id].trap_frame.a0 = trap_frame.a0; - CTX_TASKS[id].trap_frame.a1 = trap_frame.a1; - CTX_TASKS[id].trap_frame.a2 = trap_frame.a2; - CTX_TASKS[id].trap_frame.a3 = trap_frame.a3; - CTX_TASKS[id].trap_frame.a4 = trap_frame.a4; - CTX_TASKS[id].trap_frame.a5 = trap_frame.a5; - CTX_TASKS[id].trap_frame.a6 = trap_frame.a6; - CTX_TASKS[id].trap_frame.a7 = trap_frame.a7; - CTX_TASKS[id].trap_frame.t0 = trap_frame.t0; - CTX_TASKS[id].trap_frame.t1 = trap_frame.t1; - CTX_TASKS[id].trap_frame.t2 = trap_frame.t2; - CTX_TASKS[id].trap_frame.t3 = trap_frame.t3; - CTX_TASKS[id].trap_frame.t4 = trap_frame.t4; - CTX_TASKS[id].trap_frame.t5 = trap_frame.t5; - CTX_TASKS[id].trap_frame.t6 = trap_frame.t6; - CTX_TASKS[id].trap_frame.s0 = trap_frame.s0; - CTX_TASKS[id].trap_frame.s1 = trap_frame.s1; - CTX_TASKS[id].trap_frame.s2 = trap_frame.s2; - CTX_TASKS[id].trap_frame.s3 = trap_frame.s3; - CTX_TASKS[id].trap_frame.s4 = trap_frame.s4; - CTX_TASKS[id].trap_frame.s5 = trap_frame.s5; - CTX_TASKS[id].trap_frame.s6 = trap_frame.s6; - CTX_TASKS[id].trap_frame.s7 = trap_frame.s7; - CTX_TASKS[id].trap_frame.s8 = trap_frame.s8; - CTX_TASKS[id].trap_frame.s9 = trap_frame.s9; - CTX_TASKS[id].trap_frame.s10 = trap_frame.s10; - CTX_TASKS[id].trap_frame.s11 = trap_frame.s11; - CTX_TASKS[id].trap_frame.gp = trap_frame.gp; - CTX_TASKS[id].trap_frame.tp = trap_frame.tp; - - CTX_TASKS[id].trap_frame.pc = pc; + (*ctx).trap_frame.ra = trap_frame.ra; + (*ctx).trap_frame.sp = trap_frame.sp; + (*ctx).trap_frame.a0 = trap_frame.a0; + (*ctx).trap_frame.a1 = trap_frame.a1; + (*ctx).trap_frame.a2 = trap_frame.a2; + (*ctx).trap_frame.a3 = trap_frame.a3; + (*ctx).trap_frame.a4 = trap_frame.a4; + (*ctx).trap_frame.a5 = trap_frame.a5; + (*ctx).trap_frame.a6 = trap_frame.a6; + (*ctx).trap_frame.a7 = trap_frame.a7; + (*ctx).trap_frame.t0 = trap_frame.t0; + (*ctx).trap_frame.t1 = trap_frame.t1; + (*ctx).trap_frame.t2 = trap_frame.t2; + (*ctx).trap_frame.t3 = trap_frame.t3; + (*ctx).trap_frame.t4 = trap_frame.t4; + (*ctx).trap_frame.t5 = trap_frame.t5; + (*ctx).trap_frame.t6 = trap_frame.t6; + (*ctx).trap_frame.s0 = trap_frame.s0; + (*ctx).trap_frame.s1 = trap_frame.s1; + (*ctx).trap_frame.s2 = trap_frame.s2; + (*ctx).trap_frame.s3 = trap_frame.s3; + (*ctx).trap_frame.s4 = trap_frame.s4; + (*ctx).trap_frame.s5 = trap_frame.s5; + (*ctx).trap_frame.s6 = trap_frame.s6; + (*ctx).trap_frame.s7 = trap_frame.s7; + (*ctx).trap_frame.s8 = trap_frame.s8; + (*ctx).trap_frame.s9 = trap_frame.s9; + (*ctx).trap_frame.s10 = trap_frame.s10; + (*ctx).trap_frame.s11 = trap_frame.s11; + (*ctx).trap_frame.gp = trap_frame.gp; + (*ctx).trap_frame.tp = trap_frame.tp; + (*ctx).trap_frame.pc = trap_frame.pc; } } - -pub fn task_switch(trap_frame: &mut TrapFrame) { - let old_mepc = trap_frame.pc; - - save_task_context(current_task(), old_mepc, trap_frame); - - next_task(); - - let new_pc = restore_task_context(current_task(), trap_frame); - trap_frame.pc = new_pc; - - // debug aid! remove when not needed anymore!!!!! - // static mut CNT: u32 = 0; - // if CTX_NOW == 0 { - // if CNT < 5_000 { - // CNT += 1; - // } else { - // CNT = 0; - // info!("@@@ Task {} PC = {:x} {:?}", CTX_NOW, new_pc, trap_frame); - // } - // } -} diff --git a/esp-wifi/src/preempt/preempt_xtensa.rs b/esp-wifi/src/preempt/preempt_xtensa.rs index 770dfacf58a..eeb43f59be0 100644 --- a/esp-wifi/src/preempt/preempt_xtensa.rs +++ b/esp-wifi/src/preempt/preempt_xtensa.rs @@ -1,68 +1,57 @@ -use core::ptr::addr_of; +use esp_wifi_sys::c_types; use super::*; use crate::hal::trapframe::TrapFrame; #[derive(Debug, Clone, Copy)] -pub struct TaskContext { +pub struct Context { trap_frame: TrapFrame, + pub thread_semaphore: u32, + pub next: *mut Context, + pub allocated_stack: *const u8, } -static mut CTX_TASKS: [TaskContext; MAX_TASK] = [TaskContext { - trap_frame: TrapFrame::new(), -}; MAX_TASK]; - -pub fn task_create(task: extern "C" fn()) { +pub fn task_create( + task: extern "C" fn(*mut c_types::c_void), + param: *mut c_types::c_void, + task_stack_size: usize, +) -> *mut Context { + trace!("task_create {:?} {:?} {}", task, param, task_stack_size); unsafe { - let i = allocate_task(); + let ctx = allocate_task(); - CTX_TASKS[i].trap_frame.PC = task as usize as u32; + (*ctx).trap_frame.PC = task as usize as u32; + (*ctx).trap_frame.A6 = param as usize as u32; - let task_stack_size = TASK_STACK_SIZE[i]; + let stack = malloc(task_stack_size as u32); + (*ctx).allocated_stack = stack.cast(); // stack must be aligned by 16 - let task_stack_ptr = - (addr_of!(TASK_STACK) as *const _ as usize + (task_stack_size * i) + task_stack_size - - 4) as u32; + let task_stack_ptr = stack as usize + task_stack_size; let stack_ptr = task_stack_ptr - (task_stack_ptr % 0x10); - CTX_TASKS[i].trap_frame.A1 = stack_ptr; + (*ctx).trap_frame.A1 = stack_ptr as u32; - CTX_TASKS[i].trap_frame.PS = 0x00040000 | (1 & 3) << 16; // For windowed ABI set WOE and CALLINC (pretend task was 'call4'd). + (*ctx).trap_frame.PS = 0x00040000 | (1 & 3) << 16; // For windowed ABI set WOE and CALLINC (pretend task was 'call4'd). - CTX_TASKS[i].trap_frame.A0 = 0; + (*ctx).trap_frame.A0 = 0; *((task_stack_ptr - 4) as *mut u32) = 0; *((task_stack_ptr - 8) as *mut u32) = 0; - *((task_stack_ptr - 12) as *mut u32) = stack_ptr; + *((task_stack_ptr - 12) as *mut u32) = stack_ptr as u32; *((task_stack_ptr - 16) as *mut u32) = 0; + + ctx } } -fn restore_task_context(id: usize, trap_frame: &mut TrapFrame) { +pub fn restore_task_context(ctx: *mut Context, trap_frame: &mut TrapFrame) { unsafe { - *trap_frame = CTX_TASKS[id].trap_frame; + *trap_frame = (*ctx).trap_frame; } } -fn save_task_context(id: usize, trap_frame: &TrapFrame) { +pub fn save_task_context(ctx: *mut Context, trap_frame: &TrapFrame) { unsafe { - CTX_TASKS[id].trap_frame = *trap_frame; + (*ctx).trap_frame = *trap_frame; } } - -pub fn task_switch(trap_frame: &mut TrapFrame) { - save_task_context(current_task(), trap_frame); - next_task(); - restore_task_context(current_task(), trap_frame); - - // debug aid! remove when not needed anymore!!!!! - // static mut CNT: u32 = 0; - // if CTX_NOW == 0 { - // if CNT < 2_000 { - // CNT += 1; - // } else { - // CNT = 0; - // info!("@@@ Task {} {:?} ", 1, CTX_TASKS[1].trap_frame.PC); - // } - // } -} diff --git a/esp-wifi/src/tasks.rs b/esp-wifi/src/tasks.rs index 73fc31d4581..51eeb5455b7 100644 --- a/esp-wifi/src/tasks.rs +++ b/esp-wifi/src/tasks.rs @@ -1,20 +1,19 @@ use crate::{ - compat::{self, queue::SimpleQueue, timer_compat::TIMERS}, + compat::{queue::SimpleQueue, timer_compat::TIMERS}, memory_fence::memory_fence, - preempt::preempt::task_create, + preempt::arch_specific::task_create, timer::{get_systimer_count, yield_task}, }; pub fn init_tasks() { - task_create(compat::task_runner::run_c_task); - task_create(timer_task); + // allocate the main task + crate::preempt::allocate_main_task(); - // if coex then we know we have ble + wifi - #[cfg(coex)] - task_create(compat::task_runner::run_c_task); + // schedule the timer task + task_create(timer_task, core::ptr::null_mut(), 8192); } -pub extern "C" fn timer_task() { +pub extern "C" fn timer_task(_param: *mut esp_wifi_sys::c_types::c_void) { loop { let mut to_run = SimpleQueue::<_, 20>::new(); diff --git a/esp-wifi/src/timer/riscv.rs b/esp-wifi/src/timer/riscv.rs index ea9837652a5..a4f0df7076a 100644 --- a/esp-wifi/src/timer/riscv.rs +++ b/esp-wifi/src/timer/riscv.rs @@ -13,7 +13,7 @@ use crate::{ peripherals::{self, Interrupt}, riscv, }, - preempt::preempt::task_switch, + preempt::task_switch, TimeBase, }; diff --git a/esp-wifi/src/timer/xtensa.rs b/esp-wifi/src/timer/xtensa.rs index 6f7443207d3..78b5891ebec 100644 --- a/esp-wifi/src/timer/xtensa.rs +++ b/esp-wifi/src/timer/xtensa.rs @@ -5,7 +5,7 @@ use esp_hal::interrupt::InterruptHandler; use crate::{ hal::{interrupt, trapframe::TrapFrame, xtensa_lx, xtensa_lx_rt}, - preempt::preempt::task_switch, + preempt::task_switch, TimeBase, }; diff --git a/esp-wifi/src/wifi/mod.rs b/esp-wifi/src/wifi/mod.rs index 9f9063e7012..f049cedbe5e 100644 --- a/esp-wifi/src/wifi/mod.rs +++ b/esp-wifi/src/wifi/mod.rs @@ -13,15 +13,25 @@ use core::{ use critical_section::{CriticalSection, Mutex}; use enumset::{EnumSet, EnumSetType}; -#[cfg(feature = "sniffer")] -use esp_wifi_sys::include::{ - esp_wifi_80211_tx, - esp_wifi_set_promiscuous, - esp_wifi_set_promiscuous_rx_cb, - wifi_promiscuous_pkt_t, - wifi_promiscuous_pkt_type_t, -}; use esp_wifi_sys::include::{ + esp_eap_client_clear_ca_cert, + esp_eap_client_clear_certificate_and_key, + esp_eap_client_clear_identity, + esp_eap_client_clear_new_password, + esp_eap_client_clear_password, + esp_eap_client_clear_username, + esp_eap_client_set_ca_cert, + esp_eap_client_set_certificate_and_key, + esp_eap_client_set_disable_time_check, + esp_eap_client_set_fast_params, + esp_eap_client_set_identity, + esp_eap_client_set_new_password, + esp_eap_client_set_pac_file, + esp_eap_client_set_password, + esp_eap_client_set_ttls_phase2_method, + esp_eap_client_set_username, + esp_eap_fast_config, + esp_wifi_sta_enterprise_enable, wifi_pkt_rx_ctrl_t, WIFI_PROTOCOL_11AX, WIFI_PROTOCOL_11B, @@ -29,6 +39,14 @@ use esp_wifi_sys::include::{ WIFI_PROTOCOL_11N, WIFI_PROTOCOL_LR, }; +#[cfg(feature = "sniffer")] +use esp_wifi_sys::include::{ + esp_wifi_80211_tx, + esp_wifi_set_promiscuous, + esp_wifi_set_promiscuous_rx_cb, + wifi_promiscuous_pkt_t, + wifi_promiscuous_pkt_type_t, +}; use num_derive::FromPrimitive; use num_traits::FromPrimitive; #[doc(hidden)] @@ -238,6 +256,114 @@ impl Default for ClientConfiguration { } } +#[derive(Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[cfg_attr(feature = "use_serde", derive(Serialize, Deserialize))] +pub struct EapFastConfig { + pub fast_provisioning: u8, + pub fast_max_pac_list_len: u8, + pub fast_pac_format_binary: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[cfg_attr(feature = "use_serde", derive(Serialize, Deserialize))] +pub enum TtlsPhase2Method { + Eap, + Mschapv2, + Mschap, + Pap, + Chap, +} + +impl TtlsPhase2Method { + fn to_raw(&self) -> u32 { + match self { + TtlsPhase2Method::Eap => { + esp_wifi_sys::include::esp_eap_ttls_phase2_types_ESP_EAP_TTLS_PHASE2_EAP + } + TtlsPhase2Method::Mschapv2 => { + esp_wifi_sys::include::esp_eap_ttls_phase2_types_ESP_EAP_TTLS_PHASE2_MSCHAPV2 + } + TtlsPhase2Method::Mschap => { + esp_wifi_sys::include::esp_eap_ttls_phase2_types_ESP_EAP_TTLS_PHASE2_MSCHAP + } + TtlsPhase2Method::Pap => { + esp_wifi_sys::include::esp_eap_ttls_phase2_types_ESP_EAP_TTLS_PHASE2_PAP + } + TtlsPhase2Method::Chap => { + esp_wifi_sys::include::esp_eap_ttls_phase2_types_ESP_EAP_TTLS_PHASE2_CHAP + } + } + } +} + +#[derive(Clone, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[cfg_attr(feature = "use_serde", derive(Serialize, Deserialize))] +pub struct EapClientConfiguration { + pub ssid: heapless::String<32>, + pub bssid: Option<[u8; 6]>, + // pub protocol: Protocol, + pub auth_method: AuthMethod, + pub identity: Option>, + pub username: Option>, + pub password: Option>, + pub new_password: Option>, + pub eap_fast_config: Option, + pub pac_file: Option<&'static [u8]>, + pub time_check: bool, + pub ca_cert: Option<&'static [u8]>, + #[allow(clippy::type_complexity)] + pub certificate_and_key: Option<(&'static [u8], &'static [u8], Option<&'static [u8]>)>, + pub ttls_phase2_method: Option, + + pub channel: Option, +} + +impl Debug for EapClientConfiguration { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("EapClientConfiguration") + .field("ssid", &self.ssid) + .field("bssid", &self.bssid) + .field("auth_method", &self.auth_method) + .field("channel", &self.channel) + .field("identity", &self.identity) + .field("username", &self.username) + .field("eap_fast_config", &self.eap_fast_config) + .field("time_check", &self.time_check) + .field("pac_file set", &self.pac_file.is_some()) + .field("ca_cert set", &self.ca_cert.is_some()) + .field( + "certificate_and_key set", + &self.certificate_and_key.is_some(), + ) + .field("ttls_phase2_method", &self.ttls_phase2_method) + .finish() + } +} + +impl Default for EapClientConfiguration { + fn default() -> Self { + EapClientConfiguration { + ssid: heapless::String::new(), + bssid: None, + auth_method: AuthMethod::WPA2Enterprise, + identity: None, + username: None, + password: None, + channel: None, + eap_fast_config: None, + time_check: false, + new_password: None, + pac_file: None, + ca_cert: None, + certificate_and_key: None, + ttls_phase2_method: None, + } + } +} + #[derive(EnumSetType, Debug, PartialOrd)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Capability { @@ -249,12 +375,14 @@ pub enum Capability { #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[derive(Default)] +#[allow(clippy::large_enum_variant)] pub enum Configuration { #[default] None, Client(ClientConfiguration), AccessPoint(AccessPointConfiguration), Mixed(ClientConfiguration, AccessPointConfiguration), + EapClient(EapClientConfiguration), } impl Configuration { @@ -638,6 +766,7 @@ impl TryFrom<&Configuration> for WifiMode { Configuration::AccessPoint(_) => Self::Ap, Configuration::Client(_) => Self::Sta, Configuration::Mixed(_, _) => Self::ApSta, + Configuration::EapClient(_) => Self::Sta, }; Ok(mode) @@ -690,6 +819,7 @@ pub enum WifiError { InternalError(InternalWifiError), Disconnected, UnknownWifiMode, + Unsupported, } /// Events generated by the WiFi driver @@ -1821,8 +1951,7 @@ pub struct RxControlInfo { pub rx_channel_estimate_len: u32, pub second: u32, pub channel: u32, - pub data_rssi: i32, - pub noise_floor: u32, + pub noise_floor: i32, pub is_group: u32, pub rxend_state: u32, pub rxmatch3: u32, @@ -1873,7 +2002,6 @@ impl RxControlInfo { rx_channel_estimate_len: (*rx_cntl).rx_channel_estimate_len(), second: (*rx_cntl).second(), channel: (*rx_cntl).channel(), - data_rssi: (*rx_cntl).data_rssi(), noise_floor: (*rx_cntl).noise_floor(), is_group: (*rx_cntl).is_group(), rxend_state: (*rx_cntl).rxend_state(), @@ -2356,6 +2484,140 @@ fn apply_sta_config(config: &ClientConfiguration) -> Result<(), WifiError> { } } +fn apply_sta_eap_config(config: &EapClientConfiguration) -> Result<(), WifiError> { + let mut cfg = wifi_config_t { + sta: wifi_sta_config_t { + ssid: [0; 32], + password: [0; 64], + scan_method: crate::CONFIG.scan_method, + bssid_set: config.bssid.is_some(), + bssid: config.bssid.unwrap_or_default(), + channel: config.channel.unwrap_or(0), + listen_interval: crate::CONFIG.listen_interval, + sort_method: wifi_sort_method_t_WIFI_CONNECT_AP_BY_SIGNAL, + threshold: wifi_scan_threshold_t { + rssi: -99, + authmode: config.auth_method.to_raw(), + }, + pmf_cfg: wifi_pmf_config_t { + capable: true, + required: false, + }, + sae_pwe_h2e: 3, + _bitfield_align_1: [0; 0], + _bitfield_1: __BindgenBitfieldUnit::new([0; 4]), + failure_retry_cnt: crate::CONFIG.failure_retry_cnt, + _bitfield_align_2: [0; 0], + _bitfield_2: __BindgenBitfieldUnit::new([0; 4]), + sae_pk_mode: 0, // ?? + sae_h2e_identifier: [0; 32], + }, + }; + + unsafe { + cfg.sta.ssid[0..(config.ssid.len())].copy_from_slice(config.ssid.as_bytes()); + esp_wifi_result!(esp_wifi_set_config(wifi_interface_t_WIFI_IF_STA, &mut cfg))?; + + if let Some(identity) = &config.identity { + esp_wifi_result!(esp_eap_client_set_identity( + identity.as_str().as_ptr(), + identity.len() as i32 + ))?; + } else { + esp_eap_client_clear_identity(); + } + + if let Some(username) = &config.username { + esp_wifi_result!(esp_eap_client_set_username( + username.as_str().as_ptr(), + username.len() as i32 + ))?; + } else { + esp_eap_client_clear_username(); + } + + if let Some(password) = &config.password { + esp_wifi_result!(esp_eap_client_set_password( + password.as_str().as_ptr(), + password.len() as i32 + ))?; + } else { + esp_eap_client_clear_password(); + } + + if let Some(new_password) = &config.new_password { + esp_wifi_result!(esp_eap_client_set_new_password( + new_password.as_str().as_ptr(), + new_password.len() as i32 + ))?; + } else { + esp_eap_client_clear_new_password(); + } + + if let Some(pac_file) = &config.pac_file { + esp_wifi_result!(esp_eap_client_set_pac_file( + pac_file.as_ptr(), + pac_file.len() as i32 + ))?; + } + + if let Some(phase2_method) = &config.ttls_phase2_method { + esp_wifi_result!(esp_eap_client_set_ttls_phase2_method( + phase2_method.to_raw() + ))?; + } + + if let Some(ca_cert) = config.ca_cert { + esp_wifi_result!(esp_eap_client_set_ca_cert( + ca_cert.as_ptr(), + ca_cert.len() as i32 + ))?; + } else { + esp_eap_client_clear_ca_cert(); + } + + if let Some((cert, key, password)) = config.certificate_and_key { + let (pwd, pwd_len) = if let Some(pwd) = password { + (pwd.as_ptr(), pwd.len() as i32) + } else { + (core::ptr::null(), 0) + }; + + esp_wifi_result!(esp_eap_client_set_certificate_and_key( + cert.as_ptr(), + cert.len() as i32, + key.as_ptr(), + key.len() as i32, + pwd, + pwd_len, + ))?; + } else { + esp_eap_client_clear_certificate_and_key(); + } + + if let Some(cfg) = &config.eap_fast_config { + let params = esp_eap_fast_config { + fast_provisioning: cfg.fast_provisioning as i32, + fast_max_pac_list_len: cfg.fast_max_pac_list_len as i32, + fast_pac_format_binary: cfg.fast_pac_format_binary, + }; + esp_wifi_result!(esp_eap_client_set_fast_params(params))?; + } + + esp_wifi_result!(esp_eap_client_set_disable_time_check(!&config.time_check))?; + + // esp_eap_client_set_suiteb_192bit_certification unsupported because we build + // without MBEDTLS + + // esp_eap_client_use_default_cert_bundle unsupported because we build without + // MBEDTLS + + esp_wifi_result!(esp_wifi_sta_enterprise_enable())?; + + Ok(()) + } +} + impl WifiController<'_> { /// Get the supported capabilities of the controller. pub fn get_capabilities(&self) -> Result, WifiError> { @@ -2366,6 +2628,7 @@ impl WifiController<'_> { Configuration::Mixed(_, _) => { Capability::Client | Capability::AccessPoint | Capability::Mixed } + Configuration::EapClient(_) => enumset::enum_set! { Capability::Client }, }; Ok(caps) @@ -2377,40 +2640,35 @@ impl WifiController<'_> { } /// Set the configuration, you need to use Wifi::connect() for connecting to - /// an AP + /// an AP. + /// + /// This will replace any previously set configuration pub fn set_configuration(&mut self, conf: &Configuration) -> Result<(), WifiError> { - match self.config { - Configuration::None => self.config = conf.clone(), // initial config - Configuration::Client(ref mut client) => { - if let Configuration::Client(conf) = conf { - *client = conf.clone(); - } else { - return Err(WifiError::InternalError( - InternalWifiError::EspErrInvalidArg, - )); - } + let wifi_mode = WifiMode::current().unwrap_or(WifiMode::Sta); + let sta_enabled = wifi_mode.is_sta(); + let ap_enabled = wifi_mode.is_ap(); + + match conf { + Configuration::Client(_) if !sta_enabled => { + return Err(WifiError::InternalError( + InternalWifiError::EspErrInvalidArg, + )) } - Configuration::AccessPoint(ref mut ap) => { - if let Configuration::AccessPoint(conf) = conf { - *ap = conf.clone(); - } else { - return Err(WifiError::InternalError( - InternalWifiError::EspErrInvalidArg, - )); - } + Configuration::AccessPoint(_) if !ap_enabled => { + return Err(WifiError::InternalError( + InternalWifiError::EspErrInvalidArg, + )) } - Configuration::Mixed(ref mut client, ref mut ap) => match conf { - Configuration::None => { - return Err(WifiError::InternalError( - InternalWifiError::EspErrInvalidArg, - )); - } - Configuration::Mixed(_, _) => self.config = conf.clone(), - Configuration::Client(conf) => *client = conf.clone(), - Configuration::AccessPoint(conf) => *ap = conf.clone(), - }, + Configuration::EapClient(_) if !sta_enabled => { + return Err(WifiError::InternalError( + InternalWifiError::EspErrInvalidArg, + )) + } + _ => (), } + self.config = conf.clone(); + match conf { Configuration::None => { return Err(WifiError::InternalError( @@ -2423,6 +2681,7 @@ impl WifiController<'_> { apply_ap_config(ap_config)?; apply_sta_config(sta_config)?; } + Configuration::EapClient(config) => apply_sta_eap_config(config)?, }; Ok(()) @@ -3037,6 +3296,7 @@ mod embedded_svc_compat { max_connections: ap.max_connections, }, ), + Configuration::EapClient(_) => panic!("EAP not supported in embedded-svc"), } } } diff --git a/esp-wifi/src/wifi/os_adapter.rs b/esp-wifi/src/wifi/os_adapter.rs index a9b44bacb6a..dbb896b1abd 100644 --- a/esp-wifi/src/wifi/os_adapter.rs +++ b/esp-wifi/src/wifi/os_adapter.rs @@ -17,8 +17,9 @@ use crate::{ common_adapter::RADIO_CLOCKS, compat::{ common::{ + create_queue, create_recursive_mutex, - create_wifi_queue, + delete_queue, lock_mutex, number_of_messages_in_queue, receive_queued, @@ -28,13 +29,14 @@ use crate::{ unlock_mutex, }, malloc::calloc, - task_runner::spawn_task, }, hal::system::{RadioClockController, RadioPeripherals}, memory_fence::memory_fence, timer::yield_task, }; +static mut QUEUE_HANDLE: *mut crate::binary::c_types::c_void = core::ptr::null_mut(); + // useful for waiting for events - clear and wait for the event bit to be set // again pub(crate) static WIFI_EVENTS: Mutex>> = @@ -377,10 +379,19 @@ pub unsafe extern "C" fn mutex_unlock(mutex: *mut crate::binary::c_types::c_void /// /// ************************************************************************* pub unsafe extern "C" fn queue_create( - _queue_len: u32, - _item_size: u32, + queue_len: u32, + item_size: u32, ) -> *mut crate::binary::c_types::c_void { - todo!("queue_create") + // TODO remove this once fixed in esp_supplicant AND we updated to the fixed + // version - JIRA: WIFI-6676 + let (queue_len, item_size) = if queue_len != 3 && item_size != 4 { + (queue_len, item_size) + } else { + warn!("Fixing queue item_size"); + (3, 8) + }; + + create_queue(queue_len as i32, item_size as i32) } /// ************************************************************************** @@ -396,8 +407,8 @@ pub unsafe extern "C" fn queue_create( /// None /// /// ************************************************************************* -pub unsafe extern "C" fn queue_delete(_queue: *mut crate::binary::c_types::c_void) { - todo!("queue_delete") +pub unsafe extern "C" fn queue_delete(queue: *mut crate::binary::c_types::c_void) { + delete_queue(queue); } /// ************************************************************************** @@ -642,21 +653,15 @@ pub unsafe extern "C" fn task_create_pinned_to_core( core_id ); - *(task_handle as *mut usize) = 0; // we will run it in task 0 + let task_func = core::mem::transmute::< + *mut crate::binary::c_types::c_void, + extern "C" fn(*mut esp_wifi_sys::c_types::c_void), + >(task_func); - if spawn_task( - task_func, - name, - stack_depth, - param, - prio, - task_handle, - core_id, - ) { - 1 - } else { - 0 - } + let task = crate::preempt::arch_specific::task_create(task_func, param, stack_depth as usize); + *(task_handle as *mut usize) = task as usize; + + 1 } /// ************************************************************************** @@ -679,14 +684,14 @@ pub unsafe extern "C" fn task_create_pinned_to_core( /// /// ************************************************************************* pub unsafe extern "C" fn task_create( - _task_func: *mut crate::binary::c_types::c_void, - _name: *const crate::binary::c_types::c_char, - _stack_depth: u32, - _param: *mut crate::binary::c_types::c_void, - _prio: u32, - _task_handle: *mut crate::binary::c_types::c_void, + task_func: *mut crate::binary::c_types::c_void, + name: *const crate::binary::c_types::c_char, + stack_depth: u32, + param: *mut crate::binary::c_types::c_void, + prio: u32, + task_handle: *mut crate::binary::c_types::c_void, ) -> i32 { - todo!("task_create"); + task_create_pinned_to_core(task_func, name, stack_depth, param, prio, task_handle, 0) } /// ************************************************************************** @@ -703,8 +708,15 @@ pub unsafe extern "C" fn task_create( /// None /// /// ************************************************************************* -pub unsafe extern "C" fn task_delete(_task_handle: *mut crate::binary::c_types::c_void) { - todo!("task_delete") +pub unsafe extern "C" fn task_delete(task_handle: *mut crate::binary::c_types::c_void) { + trace!("task delete called for {:?}", task_handle); + + let task = if task_handle.is_null() { + crate::preempt::current_task() + } else { + task_handle as *mut _ + }; + crate::preempt::schedule_task_deletion(task); } /// ************************************************************************** @@ -797,7 +809,6 @@ pub unsafe extern "C" fn task_get_max_priority() -> i32 { /// Memory pointer /// /// ************************************************************************* -#[no_mangle] pub unsafe extern "C" fn malloc(size: usize) -> *mut crate::binary::c_types::c_void { crate::compat::malloc::malloc(size).cast() } @@ -815,7 +826,6 @@ pub unsafe extern "C" fn malloc(size: usize) -> *mut crate::binary::c_types::c_v /// No /// /// ************************************************************************* -#[no_mangle] pub unsafe extern "C" fn free(p: *mut crate::binary::c_types::c_void) { crate::compat::malloc::free(p.cast()); } @@ -1652,7 +1662,10 @@ pub unsafe extern "C" fn wifi_create_queue( queue_len: crate::binary::c_types::c_int, item_size: crate::binary::c_types::c_int, ) -> *mut crate::binary::c_types::c_void { - create_wifi_queue(queue_len, item_size) + let queue = create_queue(queue_len, item_size); + QUEUE_HANDLE = queue; + + addr_of_mut!(QUEUE_HANDLE).cast() } /// ************************************************************************** @@ -1669,10 +1682,12 @@ pub unsafe extern "C" fn wifi_create_queue( /// /// ************************************************************************* pub unsafe extern "C" fn wifi_delete_queue(queue: *mut crate::binary::c_types::c_void) { - trace!( - "wifi_delete_queue {:?} - not implemented - doing nothing", - queue - ); + trace!("wifi_delete_queue {:?}", queue); + if queue == addr_of_mut!(QUEUE_HANDLE).cast() { + delete_queue(QUEUE_HANDLE); + } else { + warn!("unknown queue when trying to delete WIFI queue"); + } } /// **************************************************************************