use core::num::NonZeroU8;
use crate::bmrequesttype::{bmRequestType, Direction, Recipient};
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Request {
pub interface: u8,
pub kind: Kind,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Kind {
SetIdle {
duration: Option<NonZeroU8>,
report_id: Option<NonZeroU8>,
},
GetDescriptor {
length: u16,
descriptor: GetDescriptor,
},
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum GetDescriptor {
Report {
index: u8,
},
}
const DESC_TYPE_HID: u8 = 0x21;
const DESC_TYPE_REPORT: u8 = 0x22;
impl Request {
pub(crate) fn parse2(
bmRequestType {
direction,
recipient,
..
}: bmRequestType,
brequest: u8,
wvalue: u16,
windex: u16,
wlength: u16,
) -> Result<Self, ()> {
const SET_IDLE: u8 = 10;
const GET_DESCRIPTOR: u8 = 6;
if brequest == SET_IDLE
&& recipient == Recipient::Interface
&& direction == Direction::HostToDevice
&& wlength == 0
{
let duration = NonZeroU8::new((wvalue >> 8) as u8);
let report_id = NonZeroU8::new(wvalue as u8);
let interface = crate::windex2interface(windex)?;
Ok(Request {
interface,
kind: Kind::SetIdle {
duration,
report_id,
},
})
} else if brequest == GET_DESCRIPTOR
&& recipient == Recipient::Interface
&& direction == Direction::DeviceToHost
{
let desc_ty = (wvalue >> 8) as u8;
let index = wvalue as u8;
let interface = crate::windex2interface(windex)?;
let length = wlength;
if desc_ty == DESC_TYPE_REPORT {
Ok(Request {
interface,
kind: Kind::GetDescriptor {
length,
descriptor: GetDescriptor::Report { index },
},
})
} else {
Err(())
}
} else {
Err(())
}
}
}
pub struct Class;
impl Class {
pub fn class(&self) -> NonZeroU8 {
unsafe { NonZeroU8::new_unchecked(3) }
}
pub fn subclass(&self) -> u8 {
0
}
pub fn protocol(&self) -> u8 {
0
}
}
pub struct Descriptor {
pub bCountryCode: Country,
pub wDescriptorLength: u16,
}
#[derive(Clone, Copy, PartialEq)]
pub enum Country {
NotSupported = 0,
Arabic = 1,
Belgian = 2,
CanadianBilingual = 3,
CanadianFrench = 4,
CzechRepublic = 5,
Danish = 6,
Finnish = 7,
French = 8,
German = 9,
Greek = 10,
Hebrew = 11,
Hungary = 12,
InternationalISO = 13,
Italian = 14,
JapanKatakana = 15,
Korean = 16,
LatinAmerican = 17,
NetherlandsDutch = 18,
Norwegian = 19,
PersianFarsi = 20,
Poland = 21,
Portuguese = 22,
Russia = 23,
Slovakia = 24,
Spanish = 25,
Swedish = 26,
SwissFrench = 27,
SwissGerman = 28,
Switzerland = 29,
Taiwan = 30,
TurkishQ = 31,
Uk = 32,
Us = 33,
Yugoslavia = 34,
TurkishF = 35,
}
#[allow(non_upper_case_globals)]
const bcdHID: u16 = 0x01_00;
impl Descriptor {
pub const SIZE: u8 = 9;
pub fn bytes(&self) -> [u8; Self::SIZE as usize] {
[
Self::SIZE,
DESC_TYPE_HID,
bcdHID as u8,
(bcdHID >> 8) as u8,
self.bCountryCode as u8,
1,
DESC_TYPE_REPORT,
self.wDescriptorLength as u8,
(self.wDescriptorLength >> 8) as u8,
]
}
}
#[cfg(test)]
mod tests {
use crate::Request;
#[test]
fn get_descriptor() {
assert_eq!(
Request::parse(129, 6, 8704, 2, 64),
Ok(Request::Hid(super::Request {
interface: 2,
kind: super::Kind::GetDescriptor {
length: 64,
descriptor: super::GetDescriptor::Report { index: 0 },
}
}))
);
}
}