esp_wifi/compat/
misc.rs

1use crate::compat::malloc::malloc;
2
3// these are not called but needed for linking
4#[no_mangle]
5unsafe extern "C" fn fwrite(ptr: *const (), size: usize, count: usize, stream: *const ()) -> usize {
6    todo!("fwrite {:?} {} {} {:?}", ptr, size, count, stream)
7}
8
9#[no_mangle]
10unsafe extern "C" fn fopen(filename: *const u8, mode: *const u8) -> *const () {
11    todo!("fopen {:?} {:?}", filename, mode)
12}
13
14#[no_mangle]
15unsafe extern "C" fn fgets(str: *const u8, count: u32, file: *const ()) -> *const u8 {
16    todo!("fgets {:?} {} {:?}", str, count, file)
17}
18
19#[no_mangle]
20unsafe extern "C" fn fclose(stream: *const ()) -> i32 {
21    todo!("fclose {:?}", stream);
22}
23
24// We cannot just use the ROM function since it needs to allocate memory
25#[no_mangle]
26unsafe extern "C" fn strdup(str: *const core::ffi::c_char) -> *const core::ffi::c_char {
27    trace!("strdup {:?}", str);
28
29    unsafe {
30        let s = core::ffi::CStr::from_ptr(str);
31        let len = s.count_bytes() + 1;
32        let p = malloc(len);
33        if !p.is_null() {
34            core::ptr::copy_nonoverlapping(str, p.cast(), len);
35        }
36        p.cast()
37    }
38}
39
40// We cannot just use the ROM function since it calls `__getreent`
41//
42// From docs: The __getreent() function returns a per-task pointer to struct
43// _reent in newlib libc. This structure is allocated on the TCB of each task.
44// i.e. it assumes a FreeRTOS task calling it.
45#[no_mangle]
46unsafe extern "C" fn atoi(str: *const i8) -> i32 {
47    trace!("atoi {:?}", str);
48
49    let mut sign: i32 = 1;
50    let mut res: i32 = 0;
51    let mut idx = 0;
52
53    // skip leading spaces
54    while str.add(idx).read() as u8 == b' ' {
55        idx += 1;
56    }
57
58    // check sign
59    let c = str.add(idx).read() as u8;
60    if c == b'-' || c == b'+' {
61        if c == b'-' {
62            sign = -1;
63        }
64        idx += 1;
65    }
66
67    // parse number digit by digit
68    loop {
69        let c = str.add(idx).read() as u8;
70
71        if !c.is_ascii_digit() {
72            break;
73        }
74
75        // if the result would exceed the bounds - return max-value
76        if res > i32::MAX / 10 || (res == i32::MAX / 10 && c - b'0' > 7) {
77            return if sign == 1 { i32::MAX } else { i32::MIN };
78        }
79
80        res = 10 * res + (c - b'0') as i32;
81        idx += 1;
82    }
83    res * sign
84}
85
86#[derive(Debug, Copy, Clone)]
87#[repr(C)]
88struct Tm {
89    tm_sec: u32,   // seconds after the minute - [0, 60] including leap second
90    tm_min: u32,   // minutes after the hour - [0, 59]
91    tm_hour: u32,  // hours since midnight - [0, 23]
92    tm_mday: u32,  // day of the month - [1, 31]
93    tm_mon: u32,   // months since January - [0, 11]
94    tm_year: u32,  // years since 1900
95    tm_wday: u32,  // days since Sunday - [0, 6]
96    tm_yday: u32,  // days since January 1 - [0, 365]
97    tm_isdst: u32, // daylight savings time flag
98}
99
100#[no_mangle]
101unsafe extern "C" fn mktime(time: *const Tm) -> i64 {
102    trace!("mktime {:?}", time);
103    let time = *time;
104
105    // Simplified implementation, ignoring time zones, leap seconds, and other
106    // complexities
107    let mut days_in_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
108
109    let is_leap_year = |year: u32| year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
110
111    let mut days = 0;
112    let year = time.tm_year + 1900;
113    for y in 1970..year {
114        days += if is_leap_year(y) { 366 } else { 365 };
115    }
116
117    if is_leap_year(year) {
118        days_in_month[1] = 29;
119    }
120
121    for m in 0..time.tm_mon {
122        days += days_in_month[m as usize];
123    }
124    days += time.tm_mday - 1;
125
126    let seconds = days * 24 * 60 * 60 + time.tm_hour * 60 * 60 + time.tm_min * 60 + time.tm_sec;
127
128    seconds as i64
129}