Skip to content

Commit

Permalink
feat(rmk): use composite report for mouse/media/system control
Browse files Browse the repository at this point in the history
Signed-off-by: Haobo Gu <[email protected]>
  • Loading branch information
HaoboGu committed Jan 31, 2024
1 parent c2a3852 commit 8f8298d
Show file tree
Hide file tree
Showing 10 changed files with 159 additions and 76 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,11 @@ A lot of todos at the list, any contributions are welcomed :)
- [x] vial support
- [x] eeprom
- [x] project template
- [ ] mouse key
- [ ] keyboard macro
- [ ] wireless
- [ ] encoder
- [ ] RGB
- [ ] cli tools
- [ ] wireless

## License

Expand Down
1 change: 1 addition & 0 deletions boards/nrf52840/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions boards/rp2040/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions boards/stm32f4/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions boards/stm32h7/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions rmk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ embassy-usb = { version = "0.1", features = [
embassy-sync = { version = "0.5", features = ["defmt"] }
embassy-futures = { version = "0.1", features = ["defmt"] }
usbd-hid = { version = "0.6.1", features = ["defmt"] }
ssmarshal = { version = "1.0", default-features = false }
defmt = "0.3"
log = "0.4"
static_cell = "2"
Expand Down
72 changes: 47 additions & 25 deletions rmk/src/keyboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ use crate::{
keycode::{KeyCode, ModifierCombination},
keymap::KeyMap,
matrix::{KeyState, Matrix},
usb::descriptor::{MyKeyboardReport, ViaReport},
usb::descriptor::{CompositeReport, CompositeReportType, ViaReport},
};
use core::{cell::RefCell, convert::Infallible};
use defmt::{error, warn};
use defmt::{debug, error, warn};
use embassy_time::Timer;
use embassy_usb::{class::hid::HidReaderWriter, driver::Driver};
use embedded_hal::digital::{InputPin, OutputPin};
use embedded_storage::nor_flash::NorFlash;
use usbd_hid::descriptor::{KeyboardReport, MediaKeyboardReport, SystemControlReport};
use usbd_hid::descriptor::KeyboardReport;

#[derive(Debug)]
pub struct KeyboardUsbConfig<'a> {
Expand Down Expand Up @@ -74,23 +74,23 @@ pub(crate) struct Keyboard<
/// Keyboard internal hid report buf
report: KeyboardReport,

/// Media internal report
media_report: MyKeyboardReport,

/// System control internal report
system_control_report: SystemControlReport,
/// Internal composite report: mouse + media(consumer) + system control
other_report: CompositeReport,

/// Via report
via_report: ViaReport,

/// Should send a new report?
/// Should send a new keyboard report?
need_send_key_report: bool,

/// Should send a consumer control report?
need_send_consumer_control_report: bool,

/// Should send a system control report?
need_send_system_control_report: bool,

/// Should send a mouse report?
need_send_mouse_report: bool,
}

impl<
Expand Down Expand Up @@ -119,15 +119,15 @@ impl<
leds: 0,
keycodes: [0; 6],
},
media_report: MyKeyboardReport::default(),
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,
}
}

Expand Down Expand Up @@ -193,21 +193,43 @@ impl<
}
}

pub(crate) async fn send_media_report<'d, D: Driver<'d>>(
pub(crate) async fn send_other_report<'d, D: Driver<'d>>(
&mut self,
hid_interface: &mut HidReaderWriter<'d, D, 1, 8>,
hid_interface: &mut HidReaderWriter<'d, D, 1, 9>,
) {
if self.need_send_consumer_control_report {
let mut buf: [u8; 9] = [0; 9];
// Report id for media(consumer)
buf[0] = 0x02;
match hid_interface.write_serialize(&self.media_report).await {
Ok(()) => {}
Err(e) => error!("Send media(consumer control) report error: {}", e),
};
self.media_report.usage_id = 0;
self.serialize_and_send_composite_report(hid_interface, CompositeReportType::Consumer)
.await;
self.other_report.media_usage_id = 0;
self.need_send_consumer_control_report = false;
}

if self.need_send_system_control_report {
self.serialize_and_send_composite_report(hid_interface, CompositeReportType::System)
.await;
self.other_report.system_usage_id = 0;
self.need_send_system_control_report = false;
}
}

async fn serialize_and_send_composite_report<'d, D: Driver<'d>>(
&mut self,
hid_interface: &mut HidReaderWriter<'d, D, 1, 9>,
report_type: CompositeReportType,
) {
let mut buf: [u8; 9] = [0; 9];
// Prepend report id
buf[0] = report_type as u8;
match self.other_report.serialize(&mut buf[1..], report_type) {
Ok(_) => {
debug!("Sending other report: {=[u8]:#X}", buf);
match hid_interface.write(&buf).await {
Ok(()) => {}
Err(e) => error!("Send other report error: {}", e),
};
}
Err(_) => error!("Serialize other report error"),
}
}

/// Main keyboard task, it scans matrix, processes active keys
Expand Down Expand Up @@ -367,10 +389,10 @@ impl<
if key.is_consumer() {
if key_state.pressed {
let media_key = key.as_consumer_control_usage_id();
self.media_report.usage_id = media_key as u16;
self.other_report.media_usage_id = media_key as u16;
self.need_send_consumer_control_report = true;
} else {
self.media_report.usage_id = 0;
self.other_report.media_usage_id = 0;
self.need_send_consumer_control_report = true;
}
}
Expand All @@ -381,11 +403,11 @@ impl<
if key.is_system() {
if key_state.pressed {
if let Some(system_key) = key.as_system_control_usage_id() {
self.system_control_report.usage_id = system_key as u8;
self.other_report.system_usage_id = system_key as u8;
self.need_send_system_control_report = true;
}
} else {
self.system_control_report.usage_id = 0;
self.other_report.system_usage_id = 0;
self.need_send_system_control_report = true;
}
}
Expand Down
4 changes: 2 additions & 2 deletions rmk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ pub async fn initialize_keyboard_with_config_and_run<
loop {
let _ = keyboard.keyboard_task().await;
keyboard.send_report(&mut usb_device.keyboard_hid).await;
keyboard.send_media_report(&mut usb_device.other_hid).await;
keyboard.send_other_report(&mut usb_device.other_hid).await;
}
};

Expand Down Expand Up @@ -135,7 +135,7 @@ pub async fn initialize_keyboard_and_run<
loop {
let _ = keyboard.keyboard_task().await;
keyboard.send_report(&mut usb_device.keyboard_hid).await;
keyboard.send_media_report(&mut usb_device.other_hid).await;
keyboard.send_other_report(&mut usb_device.other_hid).await;
}
};

Expand Down
16 changes: 9 additions & 7 deletions rmk/src/usb.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
pub(crate) mod descriptor;

use core::sync::atomic::{AtomicBool, Ordering};
use defmt::info;
use embassy_usb::{
Expand All @@ -9,13 +11,13 @@ use embassy_usb::{
use static_cell::StaticCell;
use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor};

pub(crate) mod descriptor;

use crate::{keyboard::KeyboardUsbConfig, usb::descriptor::{MyKeyboardReport, ViaReport}};
use crate::{
keyboard::KeyboardUsbConfig,
usb::descriptor::{CompositeReport, ViaReport},
};

static SUSPENDED: AtomicBool = AtomicBool::new(false);

// TODO: Use a composite hid device for Keyboard + Mouse + System control + Consumer control
// In this case, report id should be used.
// The keyboard usb device should have 3 hid instances:
// 1. Boot keyboard: 1 endpoint in
Expand All @@ -24,7 +26,7 @@ static SUSPENDED: AtomicBool = AtomicBool::new(false);
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) other_hid: HidReaderWriter<'d, D, 1, 8>,
pub(crate) other_hid: HidReaderWriter<'d, D, 1, 9>,
pub(crate) via_hid: HidReaderWriter<'d, D, 32, 32>,
}

Expand Down Expand Up @@ -76,13 +78,13 @@ impl<D: Driver<'static>> KeyboardUsbDevice<'static, D> {
);

let other_hid_config = Config {
report_descriptor: MyKeyboardReport::desc(),
report_descriptor: CompositeReport::desc(),
request_handler: Some(&request_handler),
poll_ms: 60,
max_packet_size: 64,
};
static OTHER_HID_STATE: StaticCell<State> = StaticCell::new();
let other_hid: HidReaderWriter<'_, D, 1, 8> = HidReaderWriter::new(
let other_hid: HidReaderWriter<'_, D, 1, 9> = HidReaderWriter::new(
&mut builder,
OTHER_HID_STATE.init(State::new()),
other_hid_config,
Expand Down
Loading

0 comments on commit 8f8298d

Please sign in to comment.