Skip to content

Commit

Permalink
feat(core): add kbd state reader
Browse files Browse the repository at this point in the history
Signed-off-by: Haobo Gu <[email protected]>
  • Loading branch information
HaoboGu committed Feb 4, 2024
1 parent cf7e34a commit c04daf1
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 28 deletions.
26 changes: 5 additions & 21 deletions rmk/src/keyboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
use core::{cell::RefCell, convert::Infallible};
use defmt::{debug, error, warn};
use embassy_time::Timer;
use embassy_usb::{class::hid::{HidReaderWriter, HidWriter}, driver::Driver};
use embassy_usb::{class::hid::HidWriter, driver::Driver};
use embedded_hal::digital::{InputPin, OutputPin};
use embedded_storage::nor_flash::NorFlash;
use usbd_hid::descriptor::KeyboardReport;
Expand Down Expand Up @@ -137,47 +137,31 @@ impl<
output_pins: [Out; ROW],
keymap: [[[KeyAction; COL]; ROW]; NUM_LAYER],
) -> Self {
let eeprom = match storage {
Some(s) => {
let e = Eeprom::new(s, eeprom_storage_config, &keymap);
// If eeprom is initialized, read keymap from it.
match e {
Some(e) => {
e.read_keymap(&mut keymap);
Some(e)
}
None => None,
}
}
None => None,
};

Keyboard {
matrix: Matrix::new(input_pins, output_pins),
keymap: KeyMap::new(keymap),
eeprom,
keymap,
report: KeyboardReport {
modifier: 0,
reserved: 0,
leds: 0,
keycodes: [0; 6],
},
media_report: MediaKeyboardReport { usage_id: 0 },
system_control_report: SystemControlReport { usage_id: 0 },
other_report: CompositeReport::default(),
via_report: ViaReport {
input_data: [0; 32],
output_data: [0; 32],
},
need_send_key_report: false,
need_send_consumer_control_report: false,
need_send_system_control_report: false,
need_send_mouse_report: false,
}
}

/// Send hid report. The report is sent only when key state changes.
pub(crate) async fn send_report<'d, D: Driver<'d>>(
&mut self,
hid_interface: &mut HidReaderWriter<'d, D, 1, 8>,
hid_interface: &mut HidWriter<'d, D, 8>,
) {
if self.need_send_key_report {
// usb_device.send_keyboard_report(&self.report).await;
Expand Down
52 changes: 48 additions & 4 deletions rmk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#![cfg_attr(not(test), no_std)]

use core::{cell::RefCell, convert::Infallible};
use defmt::{error, info};
use embassy_futures::join::join;
use embassy_time::Timer;
use embassy_usb::driver::Driver;
Expand Down Expand Up @@ -78,6 +79,8 @@ pub async fn initialize_keyboard_with_config_and_run<
vial_keyboard_Id: &'static [u8],
vial_keyboard_def: &'static [u8],
) -> ! {
// Keyboard state defined in protocol, aka capslock/numslock/scrolllock
let keyboard_state = RefCell::new(0);
let (mut keyboard, mut usb_device, vial_service) = (
Keyboard::new(input_pins, output_pins, keymap),
KeyboardUsbDevice::new(driver, keyboard_config),
Expand All @@ -88,11 +91,31 @@ pub async fn initialize_keyboard_with_config_and_run<
let keyboard_fut = async {
loop {
let _ = keyboard.keyboard_task().await;
keyboard.send_report(&mut usb_device.keyboard_hid).await;
keyboard
.send_report(&mut usb_device.keyboard_hid_writer)
.await;
keyboard.send_other_report(&mut usb_device.other_hid).await;
}
};

let led_reader_fut = async {
let mut read_state: [u8; 1] = [0; 1];
loop {
match usb_device.keyboard_hid_reader.read(&mut read_state).await {
Ok(_) => {
info!("Read keyboard state: {}", read_state);
let mut c = keyboard_state.borrow_mut();
*c = read_state[0];
// TODO: Updating of keyboard state should trigger changing of LED, or other actions
// Option 1: Update keyboard state only, the state is checked at main loop, GPIO is updated accordingly then
// Option 2: Trigger updating of LED after read a new keyboard state value
}
Err(e) => error!("Read keyboard state error: {}", e),
};
Timer::after_millis(10).await;
}
};

let via_fut = async {
loop {
vial_service
Expand All @@ -101,7 +124,7 @@ pub async fn initialize_keyboard_with_config_and_run<
Timer::after_millis(1).await;
}
};
join(usb_fut, join(keyboard_fut, via_fut)).await;
join(usb_fut, join(join(keyboard_fut, led_reader_fut), via_fut)).await;

panic!("Keyboard service is died")
}
Expand All @@ -124,6 +147,7 @@ pub async fn initialize_keyboard_and_run<
vial_keyboard_Id: &'static [u8],
vial_keyboard_def: &'static [u8],
) -> ! {
let keyboard_state = RefCell::new(0);
let (mut keyboard, mut usb_device, vial_service) = (
Keyboard::new(input_pins, output_pins, keymap),
KeyboardUsbDevice::new(driver, KeyboardUsbConfig::default()),
Expand All @@ -134,11 +158,31 @@ pub async fn initialize_keyboard_and_run<
let keyboard_fut = async {
loop {
let _ = keyboard.keyboard_task().await;
keyboard.send_report(&mut usb_device.keyboard_hid).await;
keyboard
.send_report(&mut usb_device.keyboard_hid_writer)
.await;
keyboard.send_other_report(&mut usb_device.other_hid).await;
}
};

let led_reader_fut = async {
let mut read_state: [u8; 1] = [0; 1];
loop {
match usb_device.keyboard_hid_reader.read(&mut read_state).await {
Ok(_) => {
info!("Read keyboard state: {}", read_state);
let mut c = keyboard_state.borrow_mut();
*c = read_state[0];
// TODO: Updating of keyboard state should trigger changing of LED, or other actions
// Option 1: Update keyboard state only, the state is checked at main loop, GPIO is updated accordingly then
// Option 2: Trigger updating of LED after read a new keyboard state value
}
Err(e) => error!("Read keyboard state error: {}", e),
};
Timer::after_millis(10).await;
}
};

let via_fut = async {
loop {
vial_service
Expand All @@ -147,7 +191,7 @@ pub async fn initialize_keyboard_and_run<
Timer::after_millis(1).await;
}
};
join(usb_fut, join(keyboard_fut, via_fut)).await;
join(usb_fut, join(join(keyboard_fut, led_reader_fut), via_fut)).await;

panic!("Keyboard service is died")
}
9 changes: 6 additions & 3 deletions rmk/src/usb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pub(crate) mod descriptor;
use core::sync::atomic::{AtomicBool, Ordering};
use defmt::info;
use embassy_usb::{
class::hid::{Config, HidReaderWriter, HidWriter, ReportId, RequestHandler, State},
class::hid::{Config, HidReader, HidReaderWriter, HidWriter, ReportId, RequestHandler, State},
control::OutResponse,
driver::Driver,
Builder, Handler, UsbDevice,
Expand All @@ -25,7 +25,8 @@ static SUSPENDED: AtomicBool = AtomicBool::new(false);
// 3. Via: used to communicate with via: 2 endpoints(in/out)
pub(crate) struct KeyboardUsbDevice<'d, D: Driver<'d>> {
pub(crate) device: UsbDevice<'d, D>,
pub(crate) keyboard_hid: HidReaderWriter<'d, D, 1, 8>,
pub(crate) keyboard_hid_writer: HidWriter<'d, D, 8>,
pub(crate) keyboard_hid_reader: HidReader<'d, D, 1>,
pub(crate) other_hid: HidWriter<'d, D, 9>,
pub(crate) via_hid: HidReaderWriter<'d, D, 32, 32>,
}
Expand Down Expand Up @@ -109,9 +110,11 @@ impl<D: Driver<'static>> KeyboardUsbDevice<'static, D> {

// Build usb device
let usb = builder.build();
let (reader, writer) = keyboard_hid.split();
return Self {
device: usb,
keyboard_hid,
keyboard_hid_reader: reader,
keyboard_hid_writer: writer,
other_hid,
via_hid,
};
Expand Down

0 comments on commit c04daf1

Please sign in to comment.