esp_wifi/compat/
misc.rs

1use crate::compat::malloc::malloc;
2
3// these are not called but needed for linking
4#[unsafe(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#[unsafe(no_mangle)]
10unsafe extern "C" fn fopen(filename: *const u8, mode: *const u8) -> *const () {
11    todo!("fopen {:?} {:?}", filename, mode)
12}
13
14#[unsafe(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#[unsafe(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#[unsafe(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#[unsafe(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 unsafe { str.add(idx).read() } as u8 == b' ' {
55        idx += 1;
56    }
57
58    // check sign
59    let c = unsafe { 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 = unsafe { 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// We cannot just use the ROM function since it calls `__getreent`
87//
88// From docs: The __getreent() function returns a per-task pointer to struct
89// _reent in newlib libc. This structure is allocated on the TCB of each task.
90// i.e. it assumes a FreeRTOS task calling it.
91#[unsafe(no_mangle)]
92pub unsafe extern "C" fn strcasecmp(
93    s1: *const core::ffi::c_char,
94    s2: *const core::ffi::c_char,
95) -> i32 {
96    let mut i = 0;
97    loop {
98        unsafe {
99            let s1_i = s1.add(i);
100            let s2_i = s2.add(i);
101
102            let val = (*s1_i).to_ascii_lowercase() as i32 - (*s2_i).to_ascii_lowercase() as i32;
103            if val != 0 || *s1_i == 0 {
104                return val;
105            }
106        }
107
108        i += 1;
109    }
110}
111
112#[derive(Debug, Copy, Clone)]
113#[repr(C)]
114struct Tm {
115    tm_sec: u32,   // seconds after the minute - [0, 60] including leap second
116    tm_min: u32,   // minutes after the hour - [0, 59]
117    tm_hour: u32,  // hours since midnight - [0, 23]
118    tm_mday: u32,  // day of the month - [1, 31]
119    tm_mon: u32,   // months since January - [0, 11]
120    tm_year: u32,  // years since 1900
121    tm_wday: u32,  // days since Sunday - [0, 6]
122    tm_yday: u32,  // days since January 1 - [0, 365]
123    tm_isdst: u32, // daylight savings time flag
124}
125
126#[unsafe(no_mangle)]
127unsafe extern "C" fn mktime(time: *const Tm) -> i64 {
128    trace!("mktime {:?}", time);
129    let time = unsafe { *time };
130
131    // Simplified implementation, ignoring time zones, leap seconds, and other
132    // complexities
133    let mut days_in_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
134
135    let is_leap_year = |year: u32| year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
136
137    let mut days = 0;
138    let year = time.tm_year + 1900;
139    for y in 1970..year {
140        days += if is_leap_year(y) { 366 } else { 365 };
141    }
142
143    if is_leap_year(year) {
144        days_in_month[1] = 29;
145    }
146
147    for m in 0..time.tm_mon {
148        days += days_in_month[m as usize];
149    }
150    days += time.tm_mday - 1;
151
152    let seconds = days * 24 * 60 * 60 + time.tm_hour * 60 * 60 + time.tm_min * 60 + time.tm_sec;
153
154    seconds as i64
155}