Proof of concept working
This commit is contained in:
parent
352e52852f
commit
eadc04539c
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue