use core::ops::RangeInclusive;
use crate::{
key::LogiKey,
keycode::KeyCode,
translate::Translated,
};
#[allow(dead_code)]
#[rustfmt::skip]
const BOOT_DESC: &[u8] = &[
0x05, 0x01, 0x09, 0x06, 0xa1, 0x01, 0x75, 0x01, 0x95, 0x08, 0x05, 0x07, 0x19, 0xe0, 0x29, 0xe7, 0x15, 0x00, 0x25, 0x01, 0x81, 0x02, 0x95, 0x01, 0x75, 0x08, 0x81, 0x03, 0x95, 0x05, 0x75, 0x01, 0x05, 0x08, 0x19, 0x01, 0x29, 0x05, 0x91, 0x02, 0x95, 0x01, 0x75, 0x03, 0x91, 0x03, 0x95, 0x06, 0x75, 0x08, 0x15, 0x00, 0x25, 0x68, 0x05, 0x07, 0x19, 0x00, 0x29, 0x68, 0x81, 0x00, 0xc0 ];
const USB_FIRST_KEY_BIT: u8 = 1;
const USB_LAST_KEY_BIT: u8 = 0xA4;
const USB_NUM_KEY_BITS: u8 = USB_LAST_KEY_BIT - USB_FIRST_KEY_BIT + 1;
const USB_NUM_KEY_BIT_BYTES: u8 = (USB_NUM_KEY_BITS + 7) / 8;
const USB_NUM_PADDING_KEY_BITS: u8 = 8 * USB_NUM_KEY_BIT_BYTES - USB_NUM_KEY_BITS;
const USB_REPORT_SIZE: u8 = USB_NUM_KEY_BIT_BYTES + 8;
#[rustfmt::skip]
const SOARER_DESC: &[u8] = &[
0x05, 0x01, 0x09, 0x06, 0xA1, 0x01,
0x75, 0x01, 0x95, 0x08, 0x05, 0x07, 0x19, 0xE0, 0x29, 0xE7, 0x15, 0x00, 0x25, 0x01, 0x81, 0x02, 0xC0,
0x05, 0x0C, 0x09, 0x01, 0xA1, 0x01, 0x05, 0x0C, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x09, 0xB5, 0x09, 0xB6, 0x09, 0xB7, 0x09, 0xB8, 0x09, 0xCD, 0x09, 0xE2, 0x09, 0xE9, 0x09, 0xEA, 0x81, 0x02, 0xC0,
0x05, 0x01, 0x09, 0x06, 0xA1, 0x01,
0x95, 0x05, 0x75, 0x01, 0x05, 0x08, 0x19, 0x01, 0x29, 0x05, 0x91, 0x02,
0x95, 0x01, 0x75, 0x03, 0x91, 0x03,
0x95, 0x06, 0x75, 0x08, 0x81, 0x03,
0x75, 0x01, 0x95, USB_NUM_KEY_BITS, 0x05, 0x07, 0x19, USB_FIRST_KEY_BIT, 0x29, USB_LAST_KEY_BIT, 0x15, 0x00, 0x25, 0x01, 0x81, 0x02,
0x95, USB_NUM_PADDING_KEY_BITS, 0x75, 0x01, 0x81, 0x03,
0xC0, ];
pub struct Reporter {
report: [u8; USB_REPORT_SIZE as usize],
}
impl Reporter {
pub const fn new() -> Self {
Reporter {
report: [0; USB_REPORT_SIZE as usize],
}
}
pub fn update_report(&mut self, event: Translated) {
match event {
Translated::Single(event) => {
self.update_report_single(event);
}
Translated::Multi(event) => {
for code in event.codes {
self.update_report_single(LogiKey {
code: *code,
state: event.state,
});
}
}
_ => {}
}
}
fn update_report_single(&mut self, event: LogiKey) {
if self.update_modifier(event) {
return;
}
if self.update_media(event) {
return;
}
self.update_boot_report(event);
self.update_full_report(event);
}
fn update_full_report(&mut self, event: LogiKey) {
use KeyCode::*;
self.update_bitfield(8, KbErrRollover..=KbExSel, event);
}
fn update_boot_report(&mut self, event: LogiKey) {
let state = *event.state;
let key = event.code;
let (find, replace) = if state {
(0u8, key as u8)
} else {
(key as u8, 0u8)
};
if let Some(b) = self.report[2..8].iter_mut().find(|b| **b == find) {
*b = replace;
}
}
fn update_bitfield(
&mut self,
offset: usize,
range: RangeInclusive<KeyCode>,
event: LogiKey,
) -> bool {
if range.contains(&event.code) {
let bit = (event.code as u8) - (*range.start() as u8);
let byte = offset + bit as usize / 8;
if byte >= self.report.len() {
return false;
}
let byte = &mut self.report[byte];
let sub_bit = bit % 8;
let mask = 0x01 << sub_bit;
if *event.state {
*byte |= mask;
} else {
*byte &= !mask;
}
true
} else {
false
}
}
fn update_modifier(&mut self, event: LogiKey) -> bool {
use KeyCode::*;
self.update_bitfield(0, KbLCtrl..=KbRGui, event)
}
fn update_media(&mut self, event: LogiKey) -> bool {
use KeyCode::*;
self.update_bitfield(1, MediaNext..=MediaVolDown, event)
}
pub fn get_desc(&self) -> &'static [u8] {
SOARER_DESC
}
pub fn get_boot_desc(&self) -> &'static [u8] {
BOOT_DESC
}
pub fn get_report(&self) -> &[u8] {
&self.report[..]
}
pub fn get_boot_report(&self) -> &[u8] {
&self.report[..8]
}
pub fn report_len(&self) -> usize {
self.get_report().len()
}
}