Proof of concept working

This commit is contained in:
Jakub Hlusička 2026-01-06 03:45:30 +01:00
parent 352e52852f
commit eadc04539c

View file

@ -31,7 +31,7 @@ use embassy_executor::Spawner;
use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex}; use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex};
use embassy_sync::channel::Channel; use embassy_sync::channel::Channel;
use embassy_sync::signal::Signal; use embassy_sync::signal::Signal;
use embassy_time::{Duration, Timer}; use embassy_time::{Duration, Instant, Timer};
use esp_alloc::{HeapRegion, MemoryCapability}; use esp_alloc::{HeapRegion, MemoryCapability};
use esp_hal::clock::CpuClock; use esp_hal::clock::CpuClock;
use esp_hal::dma::{BurstConfig, DmaDescriptor, DmaTxBuf, ExternalBurstConfig}; use esp_hal::dma::{BurstConfig, DmaDescriptor, DmaTxBuf, ExternalBurstConfig};
@ -56,6 +56,7 @@ use rmk::channel::{CONTROLLER_CHANNEL, ControllerSub};
use rmk::config::{BehaviorConfig, PositionalConfig, RmkConfig, StorageConfig, VialConfig}; use rmk::config::{BehaviorConfig, PositionalConfig, RmkConfig, StorageConfig, VialConfig};
use rmk::controller::{Controller, EventController}; use rmk::controller::{Controller, EventController};
use rmk::debounce::default_debouncer::DefaultDebouncer; use rmk::debounce::default_debouncer::DefaultDebouncer;
use rmk::descriptor::KeyboardReport;
use rmk::embassy_futures::yield_now; use rmk::embassy_futures::yield_now;
use rmk::event::{ControllerEvent, KeyboardEvent}; use rmk::event::{ControllerEvent, KeyboardEvent};
use rmk::hid::Report; use rmk::hid::Report;
@ -70,6 +71,7 @@ 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, KeyDirection};
use {esp_alloc as _, esp_backtrace as _}; use {esp_alloc as _, esp_backtrace as _};
use crate::matrix::IoeMatrix; use crate::matrix::IoeMatrix;
@ -110,7 +112,8 @@ cfg_if! {
} }
} }
const FRAME_DURATION_MIN: Duration = Duration::from_millis(40); // 25 FPS // const FRAME_DURATION_MIN: Duration = Duration::from_millis(40); // 25 FPS
const FRAME_DURATION_MIN: Duration = Duration::from_millis(100); // 10 FPS
pub static PSRAM_ALLOCATOR: esp_alloc::EspHeap = esp_alloc::EspHeap::empty(); pub static PSRAM_ALLOCATOR: esp_alloc::EspHeap = esp_alloc::EspHeap::empty();
@ -393,16 +396,13 @@ async fn main(_spawner: Spawner) {
let hid_report_proxy_task = async {}; let hid_report_proxy_task = async {};
let hid_report_proxy_task = { let hid_report_proxy_task = {
use xkbcommon::xkb::{self, Keymap}; use xkbcommon::xkb;
static KEYBOARD_REPORT_PROXY: Channel<CriticalSectionRawMutex, Report, 16> = Channel::new(); static KEYBOARD_REPORT_PROXY: Channel<CriticalSectionRawMutex, Report, 16> = Channel::new();
{ {
*rmk::channel::KEYBOARD_REPORT_SENDER.write().await = &KEYBOARD_REPORT_PROXY; *rmk::channel::KEYBOARD_REPORT_SENDER.write().await = &KEYBOARD_REPORT_PROXY;
} }
info!("HID Report Proxy Task: Waiting 1 sec...");
Timer::after_secs(1).await;
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 keymap_string_buffer = unsafe {
let allocation = PSRAM_ALLOCATOR.alloc_caps( let allocation = PSRAM_ALLOCATOR.alloc_caps(
@ -415,17 +415,77 @@ async fn main(_spawner: Spawner) {
Box::from_raw_in(slice as *mut str, &PSRAM_ALLOCATOR) Box::from_raw_in(slice as *mut str, &PSRAM_ALLOCATOR)
}; };
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!("Parsing XKB keymap...");
let keymap = Keymap::new_from_string(&context, keymap_string_buffer, xkb::KEYMAP_FORMAT_TEXT_V1, xkb::KEYMAP_COMPILE_NO_FLAGS).unwrap(); let instant_start = Instant::now();
info!("HID Report Proxy Task: bar"); let keymap = xkb::Keymap::new_from_string(&context, keymap_string_buffer, xkb::KEYMAP_FORMAT_TEXT_V1, xkb::KEYMAP_COMPILE_NO_FLAGS).unwrap();
let duration = Instant::now().duration_since(instant_start);
info!("XKB keymap parsed successfully! Took {seconds}.{millis:03} seconds.", seconds = duration.as_secs(), millis = duration.as_millis() % 1_000);
let mut state = xkb::State::new(&keymap);
let mut previous_state = KeyboardReport::default();
async { async move {
loop { loop {
let report = KEYBOARD_REPORT_PROXY.receive().await; let report = KEYBOARD_REPORT_PROXY.receive().await;
info!("Intercepted HID report: {report:?}"); if let Report::KeyboardReport(report) = &report {
// TODO: Process modifiers
for (keycode_old, &keycode_new) in core::iter::zip(&mut previous_state.keycodes, &report.keycodes) {
fn into_xkb_keycode(rmk_keycode: u8) -> xkb::Keycode {
// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/hid/hid-input.c?id=refs/tags/v6.18#n27
const UNK: u8 = 240;
#[rustfmt::skip]
const HID_KEYBOARD: [u8; 256] = [
0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3,
4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26,
27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
65, 66, 67, 68, 87, 88, 99, 70, 119, 110, 102, 104, 111, 107, 109, 106,
105, 108, 103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
72, 73, 82, 83, 86, 127, 116, 117, 183, 184, 185, 186, 187, 188, 189, 190,
191, 192, 193, 194, 134, 138, 130, 132, 128, 129, 131, 137, 133, 135, 136, 113,
115, 114, UNK, UNK, UNK, 121, UNK, 89, 93, 124, 92, 94, 95, UNK, UNK, UNK,
122, 123, 90, 91, 85, UNK, UNK, UNK, UNK, UNK, UNK, UNK, 111, UNK, UNK, UNK,
UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK,
UNK, UNK, UNK, UNK, UNK, UNK, 179, 180, UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK,
UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK,
UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, 111, UNK, UNK, UNK, UNK, UNK, UNK, UNK,
29, 42, 56, 125, 97, 54, 100, 126, 164, 166, 165, 163, 161, 115, 114, 113,
150, 158, 159, 128, 136, 177, 178, 176, 142, 152, 173, 140, UNK, UNK, UNK, UNK,
];
// https://cgit.freedesktop.org/xorg/driver/xf86-input-evdev/tree/src/evdev.c#n73
const MIN_KEYCODE: u8 = 8;
// TODO: The combination of these two operations should be precomputed
// in a const expr into a single look-up table.
xkb::Keycode::new((HID_KEYBOARD[rmk_keycode as usize] + MIN_KEYCODE) as u32)
}
if *keycode_old == 0 && keycode_new == 0 {
continue;
}
if keycode_new == 0 || ((*keycode_old != 0) && *keycode_old != keycode_new) {
warn!("Release: 0x{:02x} ({})", *keycode_old, *keycode_old);
state.update_key(into_xkb_keycode(*keycode_old), KeyDirection::Up);
}
if *keycode_old == 0 || ((keycode_new != 0) && *keycode_old != keycode_new) {
let keycode_new_xkb = into_xkb_keycode(keycode_new);
let string = state.key_get_utf8(keycode_new_xkb);
warn!("Pressed: 0x{:02x} ({})", keycode_new, keycode_new);
warn!("Print: {string}");
state.update_key(keycode_new_xkb, KeyDirection::Down);
}
// state.update_key(keycode, direction);
*keycode_old = keycode_new;
}
}
rmk::channel::KEYBOARD_REPORT_RECEIVER.send(report).await; rmk::channel::KEYBOARD_REPORT_RECEIVER.send(report).await;
} }
} }