From 34b818175362f824efeec532639bd94ce371bdee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Tue, 31 Oct 2023 10:43:43 +0100 Subject: [PATCH] Move syslog out of common, implement `%ll{u,d}` (#317) * Move syslog out of common * Handle escaped percent sign (%%) * Handle long longs --- esp-wifi/src/common_adapter/mod.rs | 3 +- esp-wifi/src/compat/common.rs | 183 --------------------------- esp-wifi/src/compat/mod.rs | 1 + esp-wifi/src/compat/syslog.rs | 194 +++++++++++++++++++++++++++++ esp-wifi/src/wifi/os_adapter.rs | 2 +- 5 files changed, 198 insertions(+), 185 deletions(-) create mode 100644 esp-wifi/src/compat/syslog.rs diff --git a/esp-wifi/src/common_adapter/mod.rs b/esp-wifi/src/common_adapter/mod.rs index 3f84579b..849116c4 100644 --- a/esp-wifi/src/common_adapter/mod.rs +++ b/esp-wifi/src/common_adapter/mod.rs @@ -4,6 +4,7 @@ use crate::binary::include::esp_timer_get_time; use crate::binary::include::esp_timer_handle_t; use crate::compat::common::*; +use crate::compat::syslog::syslog; use crate::compat::timer_compat::*; use crate::hal; @@ -222,7 +223,7 @@ pub unsafe extern "C" fn sprintf(dst: *mut u8, format: *const u8, args: ...) -> let str = str_from_c(format); trace!("sprintf format: {}", str); - let len = crate::compat::common::vsnprintf(dst, 512, format, args); + let len = crate::compat::syslog::vsnprintf(dst, 512, format, args); let s = str_from_c(dst); trace!("sprintf result: {}", s); diff --git a/esp-wifi/src/compat/common.rs b/esp-wifi/src/compat/common.rs index 5aa7a75e..cea404c6 100644 --- a/esp-wifi/src/compat/common.rs +++ b/esp-wifi/src/compat/common.rs @@ -37,194 +37,11 @@ static mut MUTEX_IDX_CURRENT: usize = 0; static mut FAKE_WIFI_QUEUE: &SimpleQueue<[u8; 8], 200> = unsafe { &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 -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(()) - } -} - pub unsafe fn str_from_c<'a>(s: *const u8) -> &'a str { let c_str = core::ffi::CStr::from_ptr(s.cast()); core::str::from_utf8_unchecked(c_str.to_bytes()) } -pub unsafe extern "C" fn syslog(_priority: u32, format: *const u8, mut args: VaListImpl) { - #[cfg(feature = "wifi-logs")] - cfg_if::cfg_if! { - if #[cfg(any(target_arch = "riscv32", all(target_arch = "xtensa", xtensa_has_vaarg)))] - { - let mut buf = [0u8; 512]; - vsnprintf(&mut buf as *mut u8, 512, format, args); - let res_str = str_from_c(&buf as *const u8); - info!("{}", res_str); - } - else - { - let res_str = str_from_c(format); - info!("{}", res_str); - } - } -} - -/// 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 = false; - let mut found = false; - for c in s.chars().into_iter() { - 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' => { - // FIXME: This is sus - both branches have the same impl - 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 = str_from_c(v); - res_str.append(vbuf); - } - - 'c' => { - let v = args.arg::(); - if v != 0 { - res_str.append_byte(v); - } - } - - _ => { - write!(res_str, "", format_char).ok(); - } - } - - format_char = ' '; - found = false; - is_long = false; - } - } - - 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 -} - #[no_mangle] unsafe extern "C" fn strnlen(chars: *const u8, maxlen: usize) -> usize { let mut len = 0; diff --git a/esp-wifi/src/compat/mod.rs b/esp-wifi/src/compat/mod.rs index e0f18acf..443525f5 100644 --- a/esp-wifi/src/compat/mod.rs +++ b/esp-wifi/src/compat/mod.rs @@ -1,5 +1,6 @@ pub mod common; pub mod malloc; +pub mod syslog; pub mod task_runner; pub mod timer_compat; diff --git a/esp-wifi/src/compat/syslog.rs b/esp-wifi/src/compat/syslog.rs new file mode 100644 index 00000000..0849152b --- /dev/null +++ b/esp-wifi/src/compat/syslog.rs @@ -0,0 +1,194 @@ +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(()) + } +} + +pub unsafe extern "C" fn syslog(_priority: u32, _format: *const u8, _args: VaListImpl) { + #[cfg(feature = "wifi-logs")] + cfg_if::cfg_if! { + if #[cfg(any(target_arch = "riscv32", all(target_arch = "xtensa", xtensa_has_vaarg)))] + { + let mut buf = [0u8; 512]; + vsnprintf(&mut buf as *mut u8, 512, _format, _args); + let res_str = str_from_c(&buf as *const u8); + info!("{}", res_str); + } + else + { + let res_str = str_from_c(_format); + info!("{}", res_str); + } + } +} + +/// 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().into_iter() { + 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 = 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/wifi/os_adapter.rs b/esp-wifi/src/wifi/os_adapter.rs index 71848e3d..819490e1 100644 --- a/esp-wifi/src/wifi/os_adapter.rs +++ b/esp-wifi/src/wifi/os_adapter.rs @@ -28,7 +28,7 @@ use crate::{ timer::yield_task, }; -use crate::compat::common::syslog; +use crate::compat::syslog::syslog; use super::WifiEvent;