use super::*;
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
enum UsbHidKeyboardHandlerState {
Idle,
KeyDown,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct UsbHidKeyboardHandler {
pub report_descriptor: Vec<u8>,
pub pending_key_events: VecDeque<UsbHidKeyboardReport>,
state: UsbHidKeyboardHandlerState,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct UsbHidKeyboardReport {
pub modifier: u8,
pub keys: [u8; 6],
}
impl UsbHidKeyboardReport {
pub fn from_ascii(ascii: u8) -> UsbHidKeyboardReport {
let (modifier, key) = match ascii {
b'a'..=b'z' => (0, ascii - b'a' + 4),
b'A'..=b'Z' => (0x02, ascii - b'A' + 4), b'1'..=b'9' => (0, ascii - b'1' + 30),
b'0' => (0, 39),
b'\r' | b'\n' => (0, 40),
b' ' => (0, 44), _ => unimplemented!("Unrecognized ascii {}", ascii),
};
UsbHidKeyboardReport {
modifier,
keys: [key, 0, 0, 0, 0, 0],
}
}
}
impl UsbHidKeyboardHandler {
pub fn new_keyboard() -> Self {
Self {
pending_key_events: VecDeque::new(),
state: UsbHidKeyboardHandlerState::Idle,
report_descriptor: vec![
0x05, 0x01, 0x09, 0x06, 0xA1, 0x01, 0x05, 0x07, 0x19, 0xE0, 0x29, 0xE7, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x95, 0x01, 0x75, 0x08, 0x81, 0x01, 0x95, 0x06, 0x75, 0x08, 0x15, 0x00, 0x25, 0x65, 0x05, 0x07, 0x19, 0x00, 0x29, 0x65, 0x81, 0x00, 0xC0, ],
}
}
}
impl UsbInterfaceHandler for UsbHidKeyboardHandler {
fn handle_urb(
&mut self,
_interface: &UsbInterface,
ep: UsbEndpoint,
_transfer_buffer_length: u32,
setup: SetupPacket,
_req: &[u8],
) -> Result<Vec<u8>> {
if ep.is_ep0() {
match (setup.request_type, setup.request) {
(0b10000001, 0x06) => {
match FromPrimitive::from_u16(setup.value >> 8) {
Some(HidDescriptorType::Report) => {
return Ok(self.report_descriptor.clone());
}
_ => unimplemented!("hid descriptor {:?}", setup),
}
}
(0b00100001, 0x0A) => {
return Ok(vec![]);
}
_ => unimplemented!("hid request {:?}", setup),
}
} else {
if let Direction::In = ep.direction() {
match self.state {
UsbHidKeyboardHandlerState::Idle => {
if let Some(report) = self.pending_key_events.pop_front() {
let mut resp = vec![report.modifier, 0];
resp.extend_from_slice(&report.keys);
info!("HID key down");
self.state = UsbHidKeyboardHandlerState::KeyDown;
return Ok(resp);
}
}
UsbHidKeyboardHandlerState::KeyDown => {
let resp = vec![0; 6];
info!("HID key up");
self.state = UsbHidKeyboardHandlerState::Idle;
return Ok(resp);
}
}
}
}
Ok(vec![])
}
fn get_class_specific_descriptor(&self) -> Vec<u8> {
vec![
0x09, HidDescriptorType::Hid as u8, 0x11,
0x01, 0x00, 0x01, HidDescriptorType::Report as u8, self.report_descriptor.len() as u8,
(self.report_descriptor.len() >> 8) as u8, ]
}
fn as_any(&mut self) -> &mut dyn Any {
self
}
}
#[derive(Copy, Clone, Debug, FromPrimitive)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum HidDescriptorType {
Hid = 0x21,
Report = 0x22,
Physical = 0x23,
}
#[cfg(test)]
mod tests {
use crate::util::tests::*;
use super::*;
#[test]
fn desc_verify() {
setup_test_logger();
let handler = UsbHidKeyboardHandler::new_keyboard();
verify_descriptor(&handler.get_class_specific_descriptor());
}
}