WIP2
This commit is contained in:
parent
561be96f24
commit
352e52852f
|
|
@ -7,7 +7,7 @@ target = "xtensa-esp32s3-none-elf"
|
||||||
rustflags = [
|
rustflags = [
|
||||||
# Required to obtain backtraces (e.g. when using the "esp-backtrace" crate.)
|
# Required to obtain backtraces (e.g. when using the "esp-backtrace" crate.)
|
||||||
# NOTE: May negatively impact performance of produced code
|
# NOTE: May negatively impact performance of produced code
|
||||||
"-C", "force-frame-pointers", "-C", "link-arg=-Wl,--wrap=strncmp",
|
"-C", "force-frame-pointers",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
5
firmware2/Cargo.lock
generated
5
firmware2/Cargo.lock
generated
|
|
@ -20,6 +20,7 @@ dependencies = [
|
||||||
"embedded-cli",
|
"embedded-cli",
|
||||||
"embedded-io 0.6.1",
|
"embedded-io 0.6.1",
|
||||||
"embuild",
|
"embuild",
|
||||||
|
"enumset",
|
||||||
"esp-alloc",
|
"esp-alloc",
|
||||||
"esp-backtrace",
|
"esp-backtrace",
|
||||||
"esp-bootloader-esp-idf",
|
"esp-bootloader-esp-idf",
|
||||||
|
|
@ -6915,9 +6916,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinyrlibc"
|
name = "tinyrlibc"
|
||||||
version = "0.5.0"
|
version = "0.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5d07d242693682e46801cb0186c583858bce022f698401b3f04bbd729c9a87e7"
|
checksum = "9af8adde15cc59c61328c5d709b41b8464522a733033584d33def687b26bd009"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,8 @@ debug = []
|
||||||
trace = []
|
trace = []
|
||||||
# Development profiles
|
# Development profiles
|
||||||
develop = ["limit-fps", "alt-log"]
|
develop = ["limit-fps", "alt-log"]
|
||||||
develop-usb = ["limit-fps", "usb-log", "no-usb"]
|
develop-usb = ["limit-fps", "usb-log", "no-usb", "ble"]
|
||||||
probe = ["limit-fps", "rtt-log", "no-usb"]
|
probe = ["limit-fps", "rtt-log", "no-usb", "ble"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rmk = { version = "0.8.2", default-features = false, features = [
|
rmk = { version = "0.8.2", default-features = false, features = [
|
||||||
|
|
@ -54,7 +54,7 @@ esp-backtrace = { version = "0.18", default-features = false, features = [
|
||||||
] }
|
] }
|
||||||
esp-hal = { version = "1.0", features = ["esp32s3", "unstable", "psram", "log-04"] }
|
esp-hal = { version = "1.0", features = ["esp32s3", "unstable", "psram", "log-04"] }
|
||||||
esp-storage = { version = "0.8.0", features = ["esp32s3"] }
|
esp-storage = { version = "0.8.0", features = ["esp32s3"] }
|
||||||
esp-alloc = { version = "0.9.0" }
|
esp-alloc = { version = "0.9.0", features = ["nightly"] }
|
||||||
esp-println = { version = "0.16.0", features = ["esp32s3", "log-04"] }
|
esp-println = { version = "0.16.0", features = ["esp32s3", "log-04"] }
|
||||||
esp-radio = { version = "0.17", features = ["esp32s3", "unstable", "ble"] }
|
esp-radio = { version = "0.17", features = ["esp32s3", "unstable", "ble"] }
|
||||||
esp-rtos = { version = "0.2", features = ["esp32s3", "esp-radio", "embassy"] }
|
esp-rtos = { version = "0.2", features = ["esp32s3", "esp-radio", "embassy"] }
|
||||||
|
|
@ -79,6 +79,7 @@ panic-rtt-target = { version = "0.2.0", optional = true }
|
||||||
embedded-cli = { version = "0.2.1", default-features = false, features = ["help", "macros"] }
|
embedded-cli = { version = "0.2.1", default-features = false, features = ["help", "macros"] }
|
||||||
embedded-io = "0.6.1"
|
embedded-io = "0.6.1"
|
||||||
mutually_exclusive_features = "0.1.0"
|
mutually_exclusive_features = "0.1.0"
|
||||||
|
enumset = "1.1.10"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
xz2 = "0.1.7"
|
xz2 = "0.1.7"
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,33 @@
|
||||||
|
# ACID firmware
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
### Compiling libxkbcommon
|
||||||
|
|
||||||
|
This needs to be done on Linux or in WSL.
|
||||||
|
meson.build needs to be changed such that `pkgconfig.generate` is called with the `variables` field embedded directly, for some reason:
|
||||||
|
|
||||||
|
```meson
|
||||||
|
variables: [
|
||||||
|
f'xkb_root=@XKB_CONFIG_ROOT@',
|
||||||
|
f'xkb_extra_path=@XKB_CONFIG_EXTRA_PATH@',
|
||||||
|
],
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, the tests, fuzzes and benches need to be commented out.
|
||||||
|
Afterwards, the following command should succeed in building the static library in debug mode:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
meson setup build-debug -Denable-x11=false -Dxkb-config-root=/usr/share/X11/xkb -Dx-locale-root=/usr/share/X11/locale -Denable-wayland=false --cross-file cross-esp32s3.txt -Denable-xkbregistry=false -Denable-docs=false -Denable-tools=false --wipe --buildtype=debug
|
||||||
|
meson compile -C build-debug
|
||||||
|
```
|
||||||
|
|
||||||
|
Afterwards, a static library with redefined externally-linked symbols needs to be generated:
|
||||||
|
|
||||||
|
```
|
||||||
|
path/to/root/libxkbcommon-redefine-syms.sh build-debug/libxkbcommon{,_redefined_syms}.a
|
||||||
|
```
|
||||||
|
|
||||||
# esp32s3 BLE example
|
# esp32s3 BLE example
|
||||||
|
|
||||||
To run this example, you should have latest Rust in **esp** channel installed. The full instruction of installing esp Rust toolchain can be found [here](https://docs.esp-rs.org/book/installation/index.html).
|
To run this example, you should have latest Rust in **esp** channel installed. The full instruction of installing esp Rust toolchain can be found [here](https://docs.esp-rs.org/book/installation/index.html).
|
||||||
|
|
|
||||||
|
|
@ -35,10 +35,12 @@ fn main() {
|
||||||
println!(r#"cargo:rustc-link-search=native=C:\Users\Limeth\workspace\c\libxkbcommon-linux\build-debug"#);
|
println!(r#"cargo:rustc-link-search=native=C:\Users\Limeth\workspace\c\libxkbcommon-linux\build-debug"#);
|
||||||
|
|
||||||
// 2. Link the static library (strip the 'lib' prefix and '.a' extension)
|
// 2. Link the static library (strip the 'lib' prefix and '.a' extension)
|
||||||
println!("cargo:rustc-link-lib=static=xkbcommon");
|
// println!("cargo:rustc-link-lib=static=xkbcommon");
|
||||||
|
println!("cargo:rustc-link-lib=static=xkbcommon_redefined_syms");
|
||||||
|
|
||||||
// 3. Re-run if build.rs or the library changes
|
// 3. Re-run if build.rs or the library changes
|
||||||
println!(r#"cargo:rerun-if-changed=C:\Users\Limeth\workspace\c\libxkbcommon-linux\build-debug\libxkbcommon.a"#);
|
// println!(r#"cargo:rerun-if-changed=C:\Users\Limeth\workspace\c\libxkbcommon-linux\build-debug\libxkbcommon.a"#);
|
||||||
|
println!(r#"cargo:rerun-if-changed=C:\Users\Limeth\workspace\c\libxkbcommon-linux\build-debug\libxkbcommon_redefined_syms.a"#);
|
||||||
|
|
||||||
let slint_config = CompilerConfiguration::new()
|
let slint_config = CompilerConfiguration::new()
|
||||||
// .with_scale_factor(4.0)
|
// .with_scale_factor(4.0)
|
||||||
|
|
|
||||||
39
firmware2/cross-esp32s3.txt
Normal file
39
firmware2/cross-esp32s3.txt
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
[binaries]
|
||||||
|
c = 'xtensa-esp32s3-elf-gcc'
|
||||||
|
cpp = 'xtensa-esp32s3-elf-g++'
|
||||||
|
ar = 'xtensa-esp32s3-elf-ar'
|
||||||
|
strip = 'xtensa-esp32s3-elf-strip'
|
||||||
|
|
||||||
|
[build_machine]
|
||||||
|
system = 'linux'
|
||||||
|
cpu_family = 'x86_64'
|
||||||
|
cpu = 'x86_64'
|
||||||
|
endian = 'little'
|
||||||
|
|
||||||
|
[host_machine]
|
||||||
|
system = 'bare-metal' # Crucial: prevents Meson from assuming a POSIX environment
|
||||||
|
cpu_family = 'xtensa'
|
||||||
|
cpu = 'esp32s3'
|
||||||
|
endian = 'little'
|
||||||
|
|
||||||
|
[built-in options]
|
||||||
|
c_args = [
|
||||||
|
'-fdebug-prefix-map=@GLOBAL_SOURCE_ROOT@=C:/Users/Limeth/workspace/c/libxkbcommon-linux',
|
||||||
|
'-ffreestanding',
|
||||||
|
'-fno-builtin',
|
||||||
|
'-mlongcalls',
|
||||||
|
'-mfix-esp32-psram-cache-issue',
|
||||||
|
# Manually define the missing inttypes.h macros
|
||||||
|
'-DPRId64="lld"',
|
||||||
|
'-DPRIu64="llu"',
|
||||||
|
'-DPRIi64="lli"',
|
||||||
|
'-DPRId32="d"',
|
||||||
|
'-DPRIu32="u"',
|
||||||
|
'-DPRIx64="llx"'
|
||||||
|
]
|
||||||
|
c_link_args = [
|
||||||
|
'-nostdlib',
|
||||||
|
'-static'
|
||||||
|
]
|
||||||
|
# Ensure we only build static libraries for bare-metal
|
||||||
|
default_library = 'static'
|
||||||
1114
firmware2/keymaps/cz-small-test.xkb
Normal file
1114
firmware2/keymaps/cz-small-test.xkb
Normal file
File diff suppressed because it is too large
Load diff
28
firmware2/libxkbcommon-redefine-syms.sh
Normal file
28
firmware2/libxkbcommon-redefine-syms.sh
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
#!/bin/bash
|
||||||
|
INPUT_LIB=$1
|
||||||
|
OUTPUT_LIB=$2
|
||||||
|
PREFIX="__xkbc_"
|
||||||
|
|
||||||
|
if [ "$#" -ne 2 ]; then
|
||||||
|
echo "Usage: $0 <input_lib.a> <output_lib.a>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Redefining symbols from $INPUT_LIB into $OUTPUT_LIB..."
|
||||||
|
|
||||||
|
# We use <(...) to stream the symbol map directly into objcopy
|
||||||
|
# xtensa-esp-elf-objcopy --redefine-syms=<(
|
||||||
|
# xtensa-esp-elf-nm -u "$INPUT_LIB" |
|
||||||
|
# awk '{print $NF}' |
|
||||||
|
# sort -u |
|
||||||
|
# awk -v p="$PREFIX" '{print $1 " " p $1}'
|
||||||
|
# ) "$INPUT_LIB" "$OUTPUT_LIB"
|
||||||
|
|
||||||
|
xtensa-esp-elf-objcopy --redefine-syms=<(
|
||||||
|
comm -23 \
|
||||||
|
<(xtensa-esp-elf-nm -u "$INPUT_LIB" | awk '{print $NF}' | sort -u) \
|
||||||
|
<(xtensa-esp-elf-nm --defined-only "$INPUT_LIB" | awk '{print $NF}' | sort -u) | \
|
||||||
|
awk -v p="$PREFIX" '{print $1 " " p $1}'
|
||||||
|
) "$INPUT_LIB" "$OUTPUT_LIB"
|
||||||
|
|
||||||
|
echo "Done! Prefixed all externally linked symbols with $PREFIX."
|
||||||
|
|
@ -1,241 +0,0 @@
|
||||||
#![allow(unused)]
|
|
||||||
|
|
||||||
use core::{ffi::{CStr, VaList, c_char, c_int, c_long, c_longlong, c_size_t, c_uchar, c_void}, ptr::{null, null_mut}};
|
|
||||||
|
|
||||||
unsafe extern "C" {
|
|
||||||
fn malloc(size: c_size_t) -> *mut c_void;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn strpbrk(s: *const c_char, accept: *const c_char) -> *mut c_char {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
type c_intmax_t = c_longlong;
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn imaxabs(j: c_intmax_t) -> c_intmax_t {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn eaccess(pathname: *const c_char, mode: c_int ) -> c_int {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn vasprintf(strp: *mut *mut c_char, fmt: *const c_char, ap: VaList) -> c_int {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
type stat = c_void; // Not implemented
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn stat(path: *const c_char, buf: *mut stat) -> c_int {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn __errno() -> *mut c_int {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn strerror(errnum: c_int) -> *mut c_char {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
type DIR = c_void; // Not implemented
|
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
type dirent = c_void; // Not implemented
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn opendir(name: *const c_char) -> *mut DIR {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn readdir(dirp: *mut DIR) -> *mut dirent {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn closedir(dirp: *mut DIR) -> c_int {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn qsort(
|
|
||||||
base: *mut c_void,
|
|
||||||
num: c_size_t,
|
|
||||||
size: c_size_t,
|
|
||||||
compar: Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>,
|
|
||||||
) {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn __getreent() -> *mut c_void /*struct _reent*/ {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
#[allow(clippy::upper_case_acronyms)]
|
|
||||||
enum FILE {}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn fprintf(
|
|
||||||
stream: *mut FILE,
|
|
||||||
format: *const c_char,
|
|
||||||
...
|
|
||||||
) -> c_int {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn vfprintf(stream: *mut FILE, format: *const c_char, ap: VaList) -> c_int {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn strtol(nptr: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_long {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn secure_getenv(name: *const c_char) -> *mut c_char {
|
|
||||||
unsafe { getenv(name) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn getenv(name: *const c_char) -> *mut c_char {
|
|
||||||
null_mut()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn fseek(
|
|
||||||
stream: *mut FILE,
|
|
||||||
offset: c_long,
|
|
||||||
whence: c_int,
|
|
||||||
) -> c_int {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn ftell(stream: *mut FILE) -> c_long {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn fread(
|
|
||||||
ptr: *mut c_void,
|
|
||||||
size: c_size_t,
|
|
||||||
nobj: c_size_t,
|
|
||||||
stream: *mut FILE,
|
|
||||||
) -> c_size_t {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn open(
|
|
||||||
path: *const c_char,
|
|
||||||
oflag: c_int,
|
|
||||||
...
|
|
||||||
) -> c_int {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn fstat(fildes: c_int, buf: *mut stat) -> c_int {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn close(fd: c_int) -> c_int {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn fdopen(
|
|
||||||
fd: c_int,
|
|
||||||
mode: *const c_char,
|
|
||||||
) -> *mut FILE {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn strndup(
|
|
||||||
s: *const c_char,
|
|
||||||
n: c_size_t,
|
|
||||||
) -> *mut c_char {
|
|
||||||
let len = unsafe { strnlen(s, n) };
|
|
||||||
let new = unsafe { malloc(len + 1) } as *mut c_char;
|
|
||||||
|
|
||||||
if new.is_null() {
|
|
||||||
return null_mut();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
*new.add(len) = b'\0';
|
|
||||||
|
|
||||||
memcpy(new as *mut c_void, s as *const c_void, len) as *mut c_char
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn labs(i: c_long) -> c_long {
|
|
||||||
i.abs()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn memcpy(dest: *mut c_void, src: *const c_void, n: c_size_t) -> *mut c_void {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn strnlen(s: *const c_char, maxlen: c_size_t) -> c_size_t {
|
|
||||||
let found: *const c_char = unsafe { memchr(s as *const c_void, b'\0' as c_int, maxlen) } as *const c_char;
|
|
||||||
if !found.is_null() { unsafe { found.offset_from(s) as c_size_t } } else { maxlen }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn memchr(s: *const c_void, c: c_int, n: c_size_t) -> *mut c_void {
|
|
||||||
let mut s = s as *const c_uchar;
|
|
||||||
let c = c as c_uchar;
|
|
||||||
|
|
||||||
for _ in 0..n {
|
|
||||||
unsafe {
|
|
||||||
if *s == c {
|
|
||||||
return s as *mut c_void;
|
|
||||||
}
|
|
||||||
|
|
||||||
s = s.add(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
null_mut()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn __wrap_strncmp(
|
|
||||||
s1: *const c_char,
|
|
||||||
s2: *const c_char,
|
|
||||||
n: c_size_t,
|
|
||||||
) -> c_int {
|
|
||||||
unsafe {
|
|
||||||
for i in 0..n as isize {
|
|
||||||
let s1_i = s1.offset(i);
|
|
||||||
let s2_i = s2.offset(i);
|
|
||||||
|
|
||||||
let val = *s1_i as c_int - *s2_i as c_int;
|
|
||||||
if val != 0 || *s1_i == 0 {
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
104
firmware2/src/ffi/alloc.rs
Normal file
104
firmware2/src/ffi/alloc.rs
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
use core::{ffi::{CStr, VaList, c_char, c_int, c_long, c_longlong, c_size_t, c_uchar, c_void}, ptr::null_mut};
|
||||||
|
|
||||||
|
use core::alloc::GlobalAlloc;
|
||||||
|
|
||||||
|
use enumset::EnumSet;
|
||||||
|
use esp_alloc::EspHeap;
|
||||||
|
|
||||||
|
// Here we select the allocator to use for libxkbcommon.
|
||||||
|
static XKBC_ALLOCATOR: &EspHeap = &crate::PSRAM_ALLOCATOR;
|
||||||
|
|
||||||
|
// Implementation based on esp-alloc's `compat` feature.
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_malloc(size: c_size_t) -> *mut c_void {
|
||||||
|
unsafe { malloc_with_caps(size, EnumSet::empty()) as *mut _ }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_calloc(
|
||||||
|
number: c_size_t,
|
||||||
|
size: c_size_t,
|
||||||
|
) -> *mut c_void {
|
||||||
|
let total_size = number as usize * size;
|
||||||
|
unsafe {
|
||||||
|
let ptr = __xkbc_malloc(total_size) as *mut u8;
|
||||||
|
|
||||||
|
if !ptr.is_null() {
|
||||||
|
for i in 0..total_size as isize {
|
||||||
|
ptr.offset(i).write_volatile(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr as *mut _
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_realloc(
|
||||||
|
ptr: *mut c_void,
|
||||||
|
new_size: c_size_t,
|
||||||
|
) -> *mut c_void {
|
||||||
|
unsafe { realloc_with_caps(ptr as *mut _, new_size, EnumSet::empty()) as *mut _ }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_free(ptr: *mut c_void) {
|
||||||
|
if ptr.is_null() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let ptr = ptr.offset(-4);
|
||||||
|
let total_size = *(ptr as *const usize);
|
||||||
|
|
||||||
|
XKBC_ALLOCATOR.dealloc(
|
||||||
|
ptr as *mut u8,
|
||||||
|
core::alloc::Layout::from_size_align_unchecked(total_size, 4),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn malloc_with_caps(
|
||||||
|
size: usize,
|
||||||
|
caps: EnumSet<crate::MemoryCapability>,
|
||||||
|
) -> *mut u8 {
|
||||||
|
let total_size = size + 4;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let ptr = XKBC_ALLOCATOR.alloc_caps(
|
||||||
|
caps,
|
||||||
|
core::alloc::Layout::from_size_align_unchecked(total_size, 4),
|
||||||
|
);
|
||||||
|
|
||||||
|
if ptr.is_null() {
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(ptr as *mut usize) = total_size;
|
||||||
|
ptr.offset(4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn realloc_with_caps(
|
||||||
|
ptr: *mut u8,
|
||||||
|
new_size: usize,
|
||||||
|
caps: enumset::EnumSet<crate::MemoryCapability>,
|
||||||
|
) -> *mut u8 {
|
||||||
|
unsafe extern "C" {
|
||||||
|
fn memcpy(d: *mut u8, s: *const u8, l: usize);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let p = malloc_with_caps(new_size, caps);
|
||||||
|
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);
|
||||||
|
__xkbc_free(ptr as *mut _);
|
||||||
|
}
|
||||||
|
p
|
||||||
|
}
|
||||||
|
}
|
||||||
12
firmware2/src/ffi/gcc_runtime.rs
Normal file
12
firmware2/src/ffi/gcc_runtime.rs
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
//! https://gcc.gnu.org/onlinedocs/gcc-15.2.0/gccint/Libgcc.html
|
||||||
|
|
||||||
|
use core::{ffi::{CStr, VaList, c_char, c_int, c_long, c_longlong, c_size_t, c_uchar, c_void}, ptr::null_mut};
|
||||||
|
|
||||||
|
unsafe extern "C" {
|
||||||
|
fn __divdi3(a: c_long, b: c_long) -> c_long;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc___divdi3(a: c_long, b: c_long) -> c_long {
|
||||||
|
unsafe { __divdi3(a, b) }
|
||||||
|
}
|
||||||
25
firmware2/src/ffi/inout/dir.rs
Normal file
25
firmware2/src/ffi/inout/dir.rs
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
use core::{ffi::{CStr, VaList, c_char, c_int, c_long, c_longlong, c_size_t, c_uchar, c_void}, ptr::null_mut};
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
pub enum DIR {}
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct dirent {
|
||||||
|
// Not implemented
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_opendir(name: *const c_char) -> *mut DIR {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_readdir(dirp: *mut DIR) -> *mut dirent {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_closedir(dirp: *mut DIR) -> c_int {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
9
firmware2/src/ffi/inout/file.rs
Normal file
9
firmware2/src/ffi/inout/file.rs
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
use core::{ffi::{CStr, VaList, c_char, c_int, c_long, c_longlong, c_size_t, c_uchar, c_void}, ptr::null_mut};
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#[allow(clippy::upper_case_acronyms)]
|
||||||
|
pub enum FILE {}
|
||||||
|
|
||||||
|
pub const STDIN: *mut FILE = 0 as _;
|
||||||
|
pub const STDOUT: *mut FILE = 1 as _;
|
||||||
|
pub const STDERR: *mut FILE = 2 as _;
|
||||||
93
firmware2/src/ffi/inout/mod.rs
Normal file
93
firmware2/src/ffi/inout/mod.rs
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
//! This would've been called `io`, but rust-analyzer refuses to see
|
||||||
|
//! the submodules of this module when it's named `io`.
|
||||||
|
|
||||||
|
use core::{ffi::{CStr, VaList, c_char, c_int, c_long, c_longlong, c_size_t, c_uchar, c_void}, ptr::null_mut};
|
||||||
|
|
||||||
|
use log::info;
|
||||||
|
|
||||||
|
pub mod file;
|
||||||
|
pub mod dir;
|
||||||
|
|
||||||
|
pub use file::*;
|
||||||
|
pub use dir::*;
|
||||||
|
|
||||||
|
// File management
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_fopen(
|
||||||
|
filename: *const c_char,
|
||||||
|
mode: *const c_char,
|
||||||
|
) -> *mut FILE {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_fclose(file: *mut FILE) -> c_int {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_fseek(
|
||||||
|
stream: *mut FILE,
|
||||||
|
offset: c_long,
|
||||||
|
whence: c_int,
|
||||||
|
) -> c_int {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_ftell(stream: *mut FILE) -> c_long {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_fread(
|
||||||
|
ptr: *mut c_void,
|
||||||
|
size: c_size_t,
|
||||||
|
nobj: c_size_t,
|
||||||
|
stream: *mut FILE,
|
||||||
|
) -> c_size_t {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Printing
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_fprintf(
|
||||||
|
stream: *mut FILE,
|
||||||
|
format: *const c_char,
|
||||||
|
mut args: ...
|
||||||
|
) -> c_int {
|
||||||
|
unsafe { __xkbc_vfprintf(stream, format, args.as_va_list()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_vfprintf(stream: *mut FILE, format: *const c_char, ap: VaList) -> c_int {
|
||||||
|
if stream == STDOUT || stream == STDERR {
|
||||||
|
let string = ::alloc::format!("vfprintf({:?}, {:?}, {:?})", stream, format, ap);
|
||||||
|
info!("{}", string);
|
||||||
|
string.len() as c_int
|
||||||
|
} else {
|
||||||
|
-1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_vasprintf(strp: *mut *mut c_char, fmt: *const c_char, ap: VaList) -> c_int {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_vsnprintf(string: *mut c_char, size: c_size_t, format: *const c_char, ap: VaList) -> c_int {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_snprintf(
|
||||||
|
s: *mut c_char,
|
||||||
|
n: c_size_t,
|
||||||
|
format: *const c_char,
|
||||||
|
...
|
||||||
|
) -> c_int {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
130
firmware2/src/ffi/mod.rs
Normal file
130
firmware2/src/ffi/mod.rs
Normal file
|
|
@ -0,0 +1,130 @@
|
||||||
|
use core::{ffi::{CStr, VaList, c_char, c_int, c_long, c_longlong, c_size_t, c_uchar, c_void}, ptr::null_mut};
|
||||||
|
|
||||||
|
use alloc::__xkbc_malloc;
|
||||||
|
use inout::{FILE, STDERR, STDIN, STDOUT};
|
||||||
|
use log::info;
|
||||||
|
|
||||||
|
pub mod alloc;
|
||||||
|
pub mod string;
|
||||||
|
pub mod inout;
|
||||||
|
pub mod gcc_runtime;
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
pub type c_intmax_t = c_longlong;
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_imaxabs(j: c_intmax_t) -> c_intmax_t {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_eaccess(pathname: *const c_char, mode: c_int ) -> c_int {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
type stat = c_void; // Not implemented
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_stat(path: *const c_char, buf: *mut stat) -> c_int {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc___errno() -> *mut c_int {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_qsort(
|
||||||
|
base: *mut c_void,
|
||||||
|
num: c_size_t,
|
||||||
|
size: c_size_t,
|
||||||
|
compar: Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>,
|
||||||
|
) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An incomplete representation of Newlib's `struct _reent`.
|
||||||
|
/// https://github.com/bminor/newlib/blob/b41e3b652c4215556a62a2f47e8f8f11553fa550/newlib/libc/include/sys/reent.h#L580
|
||||||
|
#[repr(C)]
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
struct _reent {
|
||||||
|
_errno: c_int,
|
||||||
|
_stdin: *mut FILE,
|
||||||
|
_stdout: *mut FILE,
|
||||||
|
_stderr: *mut FILE,
|
||||||
|
// Rest unimplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc___getreent() -> *mut _reent {
|
||||||
|
static mut REENT: [_reent; 2] = [_reent {
|
||||||
|
_errno: 0,
|
||||||
|
_stdin: STDIN,
|
||||||
|
_stdout: STDOUT,
|
||||||
|
_stderr: STDERR,
|
||||||
|
}; 2];
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let reent = &mut REENT[esp_hal::system::Cpu::current() as usize];
|
||||||
|
reent as *mut _reent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_secure_getenv(name: *const c_char) -> *mut c_char {
|
||||||
|
unsafe { __xkbc_getenv(name) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_getenv(name: *const c_char) -> *mut c_char {
|
||||||
|
null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_open(
|
||||||
|
path: *const c_char,
|
||||||
|
oflag: c_int,
|
||||||
|
...
|
||||||
|
) -> c_int {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_fstat(fildes: c_int, buf: *mut stat) -> c_int {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_close(fd: c_int) -> c_int {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_fdopen(
|
||||||
|
fd: c_int,
|
||||||
|
mode: *const c_char,
|
||||||
|
) -> *mut FILE {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_labs(i: c_long) -> c_long {
|
||||||
|
i.abs()
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" {
|
||||||
|
fn __assert_func(file: *const c_char, line: c_int, function: *const c_char, failedExpression: *const c_char);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc___assert_func(file: *const c_char, line: c_int, function: *const c_char, failed_expression: *const c_char) {
|
||||||
|
unsafe { __assert_func(file, line, function, failed_expression); }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_atoi(s: *const c_char) -> c_int {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
193
firmware2/src/ffi/string.rs
Normal file
193
firmware2/src/ffi/string.rs
Normal file
|
|
@ -0,0 +1,193 @@
|
||||||
|
use core::{ffi::{CStr, VaList, c_char, c_int, c_long, c_longlong, c_size_t, c_uchar, c_void}, ptr::null_mut};
|
||||||
|
|
||||||
|
use super::alloc::__xkbc_malloc;
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_memset(
|
||||||
|
dest_original: *mut c_void,
|
||||||
|
c: c_int,
|
||||||
|
n: c_size_t,
|
||||||
|
) -> *mut c_void {
|
||||||
|
if dest_original == null_mut() {
|
||||||
|
if n > 0 {
|
||||||
|
panic!("Attempted to memset a nullptr.");
|
||||||
|
} else {
|
||||||
|
return null_mut();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut dest = dest_original as *mut u8;
|
||||||
|
let c = c as u8;
|
||||||
|
for _ in 0..n {
|
||||||
|
unsafe {
|
||||||
|
*dest = c;
|
||||||
|
dest = dest.add(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dest_original
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_memmove(
|
||||||
|
dst: *mut c_void,
|
||||||
|
src: *const c_void,
|
||||||
|
count: c_size_t,
|
||||||
|
) -> *mut c_void {
|
||||||
|
unsafe { core::ptr::copy(src, dst, count) };
|
||||||
|
dst
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_memcpy(dst: *mut c_void, src: *const c_void, count: c_size_t) -> *mut c_void {
|
||||||
|
unsafe { core::ptr::copy_nonoverlapping(src, dst, count); }
|
||||||
|
dst
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_memchr(s: *const c_void, c: c_int, n: c_size_t) -> *mut c_void {
|
||||||
|
let mut s = s as *const c_uchar;
|
||||||
|
let c = c as c_uchar;
|
||||||
|
|
||||||
|
for _ in 0..n {
|
||||||
|
unsafe {
|
||||||
|
if *s == c {
|
||||||
|
return s as *mut c_void;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = s.add(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_memcmp(
|
||||||
|
mut s1: *const c_char,
|
||||||
|
mut s2: *const c_char,
|
||||||
|
n: c_size_t,
|
||||||
|
) -> c_int {
|
||||||
|
unsafe {
|
||||||
|
for i in 0..n as isize {
|
||||||
|
let s1_i = s1.offset(i);
|
||||||
|
let s2_i = s2.offset(i);
|
||||||
|
let val = *s1_i as c_int - *s2_i as c_int;
|
||||||
|
|
||||||
|
if val != 0 {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_strpbrk(s: *const c_char, accept: *const c_char) -> *mut c_char {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_strerror(errnum: c_int) -> *mut c_char {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_strdup(string: *const c_char) -> *mut c_char {
|
||||||
|
strndup_inner(string, unsafe { __xkbc_strlen(string) })
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_strndup(
|
||||||
|
string: *const c_char,
|
||||||
|
max_len: c_size_t,
|
||||||
|
) -> *mut c_char {
|
||||||
|
strndup_inner(string, unsafe { __xkbc_strnlen(string, max_len) })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn strndup_inner(string: *const c_char, computed_len: c_size_t) -> *mut c_char {
|
||||||
|
let new = unsafe { __xkbc_malloc(computed_len + 1) } as *mut c_char;
|
||||||
|
|
||||||
|
if new.is_null() {
|
||||||
|
return null_mut();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
*new.add(computed_len) = b'\0';
|
||||||
|
|
||||||
|
__xkbc_memcpy(new as *mut c_void, string as *const c_void, computed_len) as *mut c_char
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_strlen(mut s: *const c_char) -> c_size_t {
|
||||||
|
let mut result = 0;
|
||||||
|
unsafe {
|
||||||
|
while *s != 0 {
|
||||||
|
s = s.offset(1);
|
||||||
|
result += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_strnlen(s: *const c_char, maxlen: c_size_t) -> c_size_t {
|
||||||
|
let found: *const c_char = unsafe { __xkbc_memchr(s as *const c_void, b'\0' as c_int, maxlen) } as *const c_char;
|
||||||
|
if !found.is_null() { unsafe { found.offset_from(s) as c_size_t } } else { maxlen }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_strncmp(
|
||||||
|
s1: *const c_char,
|
||||||
|
s2: *const c_char,
|
||||||
|
n: c_size_t,
|
||||||
|
) -> c_int {
|
||||||
|
unsafe {
|
||||||
|
for i in 0..n as isize {
|
||||||
|
let s1_i = s1.offset(i);
|
||||||
|
let s2_i = s2.offset(i);
|
||||||
|
let val = *s1_i as c_int - *s2_i as c_int;
|
||||||
|
|
||||||
|
if val != 0 || *s1_i == 0 {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_strchr(
|
||||||
|
cs: *const c_char,
|
||||||
|
c: c_int,
|
||||||
|
) -> *mut c_char {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_strcmp(
|
||||||
|
s1: *const c_char,
|
||||||
|
s2: *const c_char,
|
||||||
|
) -> c_int {
|
||||||
|
unsafe {
|
||||||
|
for i in 0_isize.. {
|
||||||
|
let s1_i = s1.offset(i);
|
||||||
|
let s2_i = s2.offset(i);
|
||||||
|
let val = *s1_i as c_int - *s2_i as c_int;
|
||||||
|
|
||||||
|
if val != 0 || *s1_i == 0 {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn __xkbc_strtol(nptr: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_long {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
//! https://esp32.com/viewtopic.php?f=12&t=26793&start=20#p95677
|
//! https://esp32.com/viewtopic.php?f=12&t=26793&start=20#p95677
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
#![feature(allocator_api)]
|
||||||
#![feature(macro_metavar_expr)]
|
#![feature(macro_metavar_expr)]
|
||||||
#![feature(c_variadic)]
|
#![feature(c_variadic)]
|
||||||
#![feature(c_size_t)]
|
#![feature(c_size_t)]
|
||||||
|
|
@ -17,9 +18,12 @@ extern crate alloc;
|
||||||
use core::alloc::Layout;
|
use core::alloc::Layout;
|
||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
use core::ffi::CStr;
|
use core::ffi::CStr;
|
||||||
|
use core::slice;
|
||||||
|
|
||||||
use alloc::string::ToString;
|
use alloc::alloc::Allocator;
|
||||||
use alloc::boxed::Box;
|
use alloc::string::{String, ToString};
|
||||||
|
use alloc::boxed::{self, Box};
|
||||||
|
use alloc::vec::Vec;
|
||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
use bt_hci::controller::ExternalController;
|
use bt_hci::controller::ExternalController;
|
||||||
use cfg_if::cfg_if;
|
use cfg_if::cfg_if;
|
||||||
|
|
@ -66,7 +70,6 @@ use slint::platform::software_renderer::Rgb565Pixel;
|
||||||
use slint::ComponentHandle;
|
use slint::ComponentHandle;
|
||||||
use static_cell::StaticCell;
|
use static_cell::StaticCell;
|
||||||
use ui::AppWindow;
|
use ui::AppWindow;
|
||||||
use xkbcommon::xkb::{self, Keymap};
|
|
||||||
use {esp_alloc as _, esp_backtrace as _};
|
use {esp_alloc as _, esp_backtrace as _};
|
||||||
|
|
||||||
use crate::matrix::IoeMatrix;
|
use crate::matrix::IoeMatrix;
|
||||||
|
|
@ -109,7 +112,7 @@ cfg_if! {
|
||||||
|
|
||||||
const FRAME_DURATION_MIN: Duration = Duration::from_millis(40); // 25 FPS
|
const FRAME_DURATION_MIN: Duration = Duration::from_millis(40); // 25 FPS
|
||||||
|
|
||||||
static PSRAM_ALLOCATOR: esp_alloc::EspHeap = esp_alloc::EspHeap::empty();
|
pub static PSRAM_ALLOCATOR: esp_alloc::EspHeap = esp_alloc::EspHeap::empty();
|
||||||
|
|
||||||
/// Used to signal that MCU is ready to submit the framebuffer to the LCD.
|
/// Used to signal that MCU is ready to submit the framebuffer to the LCD.
|
||||||
static SIGNAL_LCD_SUBMIT: Signal<CriticalSectionRawMutex, ()> = Signal::new();
|
static SIGNAL_LCD_SUBMIT: Signal<CriticalSectionRawMutex, ()> = Signal::new();
|
||||||
|
|
@ -153,6 +156,9 @@ async fn main(_spawner: Spawner) {
|
||||||
let alt_uart_rx_task = async {};
|
let alt_uart_rx_task = async {};
|
||||||
|
|
||||||
// Use the internal DRAM as the heap.
|
// Use the internal DRAM as the heap.
|
||||||
|
// TODO: Can we combine the regular link section with dram2?
|
||||||
|
// esp_alloc::heap_allocator!(size: 80 * 1024);
|
||||||
|
// esp_alloc::heap_allocator!(#[unsafe(link_section = ".dram2_uninit")] size: 72 * 1024);
|
||||||
esp_alloc::heap_allocator!(#[unsafe(link_section = ".dram2_uninit")] size: 64 * 1024);
|
esp_alloc::heap_allocator!(#[unsafe(link_section = ".dram2_uninit")] size: 64 * 1024);
|
||||||
info!("Heap initialized! {:#?}", esp_alloc::HEAP.stats());
|
info!("Heap initialized! {:#?}", esp_alloc::HEAP.stats());
|
||||||
|
|
||||||
|
|
@ -384,7 +390,10 @@ async fn main(_spawner: Spawner) {
|
||||||
|
|
||||||
info!("Second core started!");
|
info!("Second core started!");
|
||||||
|
|
||||||
|
let hid_report_proxy_task = async {};
|
||||||
|
|
||||||
let hid_report_proxy_task = {
|
let hid_report_proxy_task = {
|
||||||
|
use xkbcommon::xkb::{self, Keymap};
|
||||||
static KEYBOARD_REPORT_PROXY: Channel<CriticalSectionRawMutex, Report, 16> = Channel::new();
|
static KEYBOARD_REPORT_PROXY: Channel<CriticalSectionRawMutex, Report, 16> = Channel::new();
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
@ -395,10 +404,21 @@ async fn main(_spawner: Spawner) {
|
||||||
Timer::after_secs(1).await;
|
Timer::after_secs(1).await;
|
||||||
info!("HID Report Proxy Task: Done waiting.");
|
info!("HID Report Proxy Task: Done waiting.");
|
||||||
const KEYMAP_STRING: &str = include_str!("../keymaps/cz.xkb");
|
const KEYMAP_STRING: &str = include_str!("../keymaps/cz.xkb");
|
||||||
|
let keymap_string_buffer = unsafe {
|
||||||
|
let allocation = PSRAM_ALLOCATOR.alloc_caps(
|
||||||
|
MemoryCapability::External.into(),
|
||||||
|
Layout::from_size_align(KEYMAP_STRING.len(), 32).unwrap(),
|
||||||
|
);
|
||||||
|
let slice = str::from_utf8_unchecked_mut(slice::from_raw_parts_mut(allocation, KEYMAP_STRING.len()));
|
||||||
|
|
||||||
|
slice.as_bytes_mut().copy_from_slice(KEYMAP_STRING.as_bytes());
|
||||||
|
|
||||||
|
Box::from_raw_in(slice as *mut str, &PSRAM_ALLOCATOR)
|
||||||
|
};
|
||||||
info!("HID Report Proxy Task: test");
|
info!("HID Report Proxy Task: test");
|
||||||
let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS);
|
let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS);
|
||||||
info!("HID Report Proxy Task: foo");
|
info!("HID Report Proxy Task: foo");
|
||||||
let keymap = Keymap::new_from_string(&context, KEYMAP_STRING, xkb::KEYMAP_FORMAT_TEXT_V1, xkb::KEYMAP_COMPILE_NO_FLAGS).unwrap();
|
let keymap = Keymap::new_from_string(&context, keymap_string_buffer, xkb::KEYMAP_FORMAT_TEXT_V1, xkb::KEYMAP_COMPILE_NO_FLAGS).unwrap();
|
||||||
info!("HID Report Proxy Task: bar");
|
info!("HID Report Proxy Task: bar");
|
||||||
|
|
||||||
async {
|
async {
|
||||||
|
|
@ -472,6 +492,14 @@ impl Controller for UserController {
|
||||||
|
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
async fn run_renderer_task(backend: SlintBackend) {
|
async fn run_renderer_task(backend: SlintBackend) {
|
||||||
|
// TODO: Disable rendering because it causes crashes in allocation
|
||||||
|
loop {
|
||||||
|
SIGNAL_LCD_SUBMIT.signal(());
|
||||||
|
#[cfg(feature = "limit-fps")]
|
||||||
|
embassy_time::Timer::after(FRAME_DURATION_MIN).await;
|
||||||
|
SIGNAL_UI_RENDER.wait().await;
|
||||||
|
}
|
||||||
|
|
||||||
slint::platform::set_platform(Box::new(backend))
|
slint::platform::set_platform(Box::new(backend))
|
||||||
.expect("backend already initialized");
|
.expect("backend already initialized");
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue