#![allow(dead_code)]
#![feature(drain_filter)]
#![no_std]
#![allow(clippy::needless_return, clippy::unreadable_literal)]
pub mod debug_handlers;
pub mod handlers;
mod key_codes;
mod key_stream;
pub mod premade;
pub mod test_helpers;
extern crate alloc;
extern crate no_std_compat;
extern crate spin;
pub use crate::handlers::{ProcessKeys, HandlerResult};
pub use crate::key_codes::{AcceptsKeycode, KeyCode, UserKey};
use crate::key_stream::Key;
pub use crate::key_stream::{iter_unhandled_mut, Event, EventStatus};
use core::convert::TryInto;
use no_std_compat::prelude::v1::*;
use smallbitvec::{sbvec, SmallBitVec};
#[repr(u8)]
#[derive(PartialEq, Eq, Hash, Copy, Clone)]
pub enum Modifier {
Shift = 0,
Ctrl = 1,
Alt = 2,
Gui = 3,
}
const KEYBOARD_STATE_RESERVED_BITS: usize = 5;
const ABORT_BIT: usize = 4;
#[derive(Debug, Default)]
pub struct KeyboardState {
pub unicode_mode: UnicodeSendMode,
modifiers_and_enabled_handlers: SmallBitVec,
}
impl KeyboardState {
pub fn new() -> KeyboardState {
KeyboardState {
unicode_mode: UnicodeSendMode::Linux,
modifiers_and_enabled_handlers: sbvec![false; KEYBOARD_STATE_RESERVED_BITS],
}
}
pub fn modifier(&self, modifier: Modifier) -> bool {
self.modifiers_and_enabled_handlers[modifier as usize]
}
pub fn set_modifier(&mut self, modifier: Modifier, value: bool) {
self.modifiers_and_enabled_handlers
.set(modifier as usize, value);
}
pub fn enable_handler(&mut self, no: HandlerID) {
self.modifiers_and_enabled_handlers.set(no, true);
}
pub fn disable_handler(&mut self, no: HandlerID) {
self.modifiers_and_enabled_handlers.set(no, false);
}
pub fn set_handler(&mut self, no: HandlerID, enabled: bool) {
self.modifiers_and_enabled_handlers.set(no, enabled);
}
pub fn toggle_handler(&mut self, no: HandlerID) {
self.modifiers_and_enabled_handlers
.set(no, !self.modifiers_and_enabled_handlers[no]);
}
pub fn is_handler_enabled(&self, no: HandlerID) -> bool {
self.modifiers_and_enabled_handlers[no]
}
pub fn abort_and_clear_events(&mut self) {
self.modifiers_and_enabled_handlers.set(ABORT_BIT, true);
}
fn _clear_abort(&mut self) {
self.modifiers_and_enabled_handlers.set(ABORT_BIT, false);
}
fn _aborted(&self) -> bool {
return self.modifiers_and_enabled_handlers[ABORT_BIT];
}
}
pub type HandlerID = usize;
pub struct Keyboard<'a, T: USBKeyOut> {
events: Vec<(Event, EventStatus)>,
running_number: u8,
handlers: Vec<Box<dyn ProcessKeys<T> + Send + 'a>>,
pub output: T,
}
#[allow(clippy::new_without_default)]
impl<'a, T: USBKeyOut> Keyboard<'a, T> {
pub fn new(output: T) -> Keyboard<'a, T> {
Keyboard {
events: Vec::new(),
running_number: 0,
handlers: Vec::new(),
output,
}
}
pub fn add_handler(&mut self, handler: Box<dyn ProcessKeys<T> + Send + 'a>) -> HandlerID {
self.output
.state()
.modifiers_and_enabled_handlers
.push(handler.default_enabled());
self.handlers.push(handler);
return self.output.state().modifiers_and_enabled_handlers.len() - 1;
}
pub fn future_handler_id(&self, offset: usize) -> HandlerID {
let current = self.output.ro_state().modifiers_and_enabled_handlers.len() - 1;
current + offset
}
pub fn handle_keys(&mut self) -> Result<(), ()> {
for (_e, status) in self.events.iter_mut() {
*status = EventStatus::Unhandled;
}
for (ii, h) in self.handlers.iter_mut().enumerate() {
if self.output.state().modifiers_and_enabled_handlers[ii + KEYBOARD_STATE_RESERVED_BITS] {
match h.process_keys(&mut self.events, &mut self.output) {
HandlerResult::NoOp => {},
HandlerResult::Disable => {
self.output.state().disable_handler((ii + KEYBOARD_STATE_RESERVED_BITS) as HandlerID);
}
}
if self.output.state()._aborted() {
self.output.state()._clear_abort();
self.events.clear();
break;
}
}
}
self.events.drain_filter(|(event, status)| {
(EventStatus::Handled == *status)
|| (match event {
Event::TimeOut(_) => true,
_ => false,
})
});
if self
.events
.iter()
.any(|(_e, status)| EventStatus::Unhandled == *status)
{
return Err(());
}
Ok(())
}
pub fn clear_unhandled(&mut self) {
self.events
.drain_filter(|(_event, status)| (EventStatus::Unhandled == *status));
}
pub fn add_keypress<X: AcceptsKeycode>(&mut self, keycode: X, ms_since_last: u16) {
let e = Key {
keycode: keycode.to_u32(),
original_keycode: keycode.to_u32(),
ms_since_last,
running_number: self.running_number,
flag: 0,
};
self.running_number += 1;
self.events
.push((Event::KeyPress(e), EventStatus::Unhandled));
}
pub fn add_keyrelease<X: AcceptsKeycode>(&mut self, keycode: X, ms_since_last: u16) {
let e = Key {
keycode: keycode.to_u32(),
original_keycode: keycode.to_u32(),
ms_since_last,
running_number: self.running_number,
flag: 0,
};
self.running_number += 1;
self.events
.push((Event::KeyRelease(e), EventStatus::Unhandled));
}
pub fn add_timeout(&mut self, ms_since_last: u16) {
if let Some((event, _status)) = self.events.iter().last() {
if let Event::TimeOut(_) = event {
self.events.pop();
}
}
self.events
.push((Event::TimeOut(ms_since_last), EventStatus::Unhandled));
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum UnicodeSendMode {
Linux = 1,
LinuxDvorak,
WinCompose,
WinComposeDvorak,
Debug,
}
impl Default for UnicodeSendMode {
fn default() -> UnicodeSendMode {
UnicodeSendMode::Linux
}
}
fn hex_digit_to_keycode(digit: char) -> KeyCode {
match digit {
'0' => KeyCode::Kp0,
'1' => KeyCode::Kp1,
'2' => KeyCode::Kp2,
'3' => KeyCode::Kp3,
'4' => KeyCode::Kp4,
'5' => KeyCode::Kp5,
'6' => KeyCode::Kp6,
'7' => KeyCode::Kp7,
'8' => KeyCode::Kp8,
'9' => KeyCode::Kp9,
'A' | 'a' => KeyCode::A,
'B' | 'b' => KeyCode::B,
'C' | 'c' => KeyCode::C,
'D' | 'd' => KeyCode::D,
'E' | 'e' => KeyCode::E,
'F' | 'f' => KeyCode::F,
_ => panic!("Passed more than one digit to hex_digit_to_keycode"),
}
}
fn hex_digit_to_keycode_dvorak(digit: char) -> KeyCode {
match digit {
'0' => KeyCode::Kp0,
'1' => KeyCode::Kp1,
'2' => KeyCode::Kp2,
'3' => KeyCode::Kp3,
'4' => KeyCode::Kp4,
'5' => KeyCode::Kp5,
'6' => KeyCode::Kp6,
'7' => KeyCode::Kp7,
'8' => KeyCode::Kp8,
'9' => KeyCode::Kp9,
'A' | 'a' => KeyCode::A,
'B' | 'b' => KeyCode::N,
'C' | 'c' => KeyCode::I,
'D' | 'd' => KeyCode::H,
'E' | 'e' => KeyCode::D,
'F' | 'f' => KeyCode::Y,
_ => panic!("Passed more than one digit to hex_digit_to_keycode"),
}
}
pub trait USBKeyOut {
fn send_keys(&mut self, keys: &[KeyCode]);
fn register_key(&mut self, key: KeyCode);
fn send_registered(&mut self);
fn send_empty(&mut self);
fn state(&mut self) -> &mut KeyboardState;
fn ro_state(&self) -> &KeyboardState;
fn debug(&mut self, s: &str);
fn bootloader(&mut self);
fn send_unicode(&mut self, c: char) {
match self.state().unicode_mode {
UnicodeSendMode::Linux => {
self.send_keys(&[KeyCode::LCtrl, KeyCode::LShift, KeyCode::U]);
self.send_empty();
for out_c in c.escape_unicode().skip(3).take_while(|x| *x != '}') {
self.send_keys(&[hex_digit_to_keycode(out_c)]);
self.send_empty();
}
self.send_keys(&[KeyCode::Enter]);
self.send_empty();
},
UnicodeSendMode::LinuxDvorak => {
self.send_keys(&[KeyCode::LCtrl, KeyCode::LShift, KeyCode::F]);
self.send_empty();
for out_c in c.escape_unicode().skip(3).take_while(|x| *x != '}') {
self.send_keys(&[hex_digit_to_keycode_dvorak(out_c)]);
self.send_empty();
}
self.send_keys(&[KeyCode::Enter]);
self.send_empty();
},
UnicodeSendMode::WinCompose => {
self.send_keys(&[KeyCode::RAlt]);
self.send_keys(&[KeyCode::U]);
let escaped = c.escape_unicode();
for out_c in escaped.skip(3).take_while(|x| *x != '}') {
self.send_keys(&[hex_digit_to_keycode(out_c)]);
}
self.send_keys(&[KeyCode::Enter]);
self.send_empty();
},
UnicodeSendMode::WinComposeDvorak => {
self.send_keys(&[KeyCode::RAlt]);
self.send_keys(&[KeyCode::F]);
let escaped = c.escape_unicode();
for out_c in escaped.skip(3).take_while(|x| *x != '}') {
self.send_keys(&[hex_digit_to_keycode_dvorak(out_c)]);
}
self.send_keys(&[KeyCode::Enter]);
self.send_empty();
}
UnicodeSendMode::Debug => {
let escaped = c.escape_unicode();
for out_c in escaped.skip(3).take_while(|x| *x != '}') {
self.send_keys(&[hex_digit_to_keycode(out_c)]);
}
}
}
}
fn send_string(&mut self, s: &str) {
for c in s.chars() {
self.send_unicode(c);
}
}
}
fn ascii_to_keycode(c: char, ascii_offset: u8, keycode_offset: KeyCode) -> KeyCode {
let mut ascii = [0 as u8];
c.encode_utf8(&mut ascii);
let keycode: u32 = keycode_offset.to_u32();
let keycode = keycode as u8;
let keycode = keycode + (ascii[0] - ascii_offset);
let keycode: KeyCode = keycode.try_into().unwrap();
keycode
}
#[cfg(test)]
#[macro_use]
extern crate std;
mod tests {
#[test]
fn test_hexdigit_to_keycode() {
for c in "ABCDEFHIJKLMOJPQRSTUVWYXYZabcdefghijklmnopqrstuvwxyz".chars() {
let escaped = c.escape_unicode();
for out_c in escaped.skip(3).take_while(|x| *x != '}') {
println!("{}", out_c);
}
}
}
}