usbd_human_interface_device/device/
fido.rs1use crate::usb_class::prelude::*;
3use fugit::ExtU32;
4use usb_device::bus::UsbBus;
5use usb_device::class_prelude::UsbBusAllocator;
6
7#[rustfmt::skip]
12pub const FIDO_REPORT_DESCRIPTOR: &[u8] = &[
13 0x06, 0xD0, 0xF1, 0x09, 0x01, 0xA1, 0x01, 0x09, 0x20, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, 0x08, 0x95, 0x40, 0x81, 0x02, 0x09, 0x21, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, 0x08, 0x95, 0x40, 0x91, 0x02, 0xC0, ];
30
31#[cfg_attr(feature = "defmt", derive(defmt::Format))]
32#[derive(Clone, Copy, Debug, Eq, PartialEq)]
33#[repr(C, align(8))]
34pub struct RawFidoReport {
35 pub packet: [u8; 64],
36}
37impl Default for RawFidoReport {
38 fn default() -> Self {
39 Self { packet: [0u8; 64] }
40 }
41}
42
43pub struct RawFido<'a, B: UsbBus> {
44 interface: Interface<'a, B, InBytes64, OutBytes64, ReportSingle>,
45}
46
47impl<B: UsbBus> RawFido<'_, B> {
48 pub fn write_report(&mut self, report: &RawFidoReport) -> Result<(), UsbHidError> {
49 self.interface
50 .write_report(&report.packet)
51 .map(|_| ())
52 .map_err(UsbHidError::from)
53 }
54 pub fn read_report(&mut self) -> usb_device::Result<RawFidoReport> {
55 let mut report = RawFidoReport::default();
56 match self.interface.read_report(&mut report.packet) {
57 Err(e) => Err(e),
58 Ok(_) => Ok(report),
59 }
60 }
61}
62
63impl<'a, B: UsbBus> DeviceClass<'a> for RawFido<'a, B> {
64 type I = Interface<'a, B, InBytes64, OutBytes64, ReportSingle>;
65
66 fn interface(&mut self) -> &mut Self::I {
67 &mut self.interface
68 }
69
70 fn reset(&mut self) {}
71
72 fn tick(&mut self) -> Result<(), UsbHidError> {
73 Ok(())
74 }
75}
76
77pub struct RawFidoConfig<'a> {
78 interface: InterfaceConfig<'a, InBytes64, OutBytes64, ReportSingle>,
79}
80
81impl Default for RawFidoConfig<'_> {
82 fn default() -> Self {
83 Self::new(
84 unwrap!(
85 unwrap!(unwrap!(InterfaceBuilder::new(FIDO_REPORT_DESCRIPTOR))
86 .description("U2F Token")
87 .in_endpoint(5.millis()))
88 .with_out_endpoint(5.millis())
89 )
90 .build(),
91 )
92 }
93}
94
95impl<'a> RawFidoConfig<'a> {
96 #[must_use]
97 pub fn new(interface: InterfaceConfig<'a, InBytes64, OutBytes64, ReportSingle>) -> Self {
98 Self { interface }
99 }
100}
101
102impl<'a, B: UsbBus + 'a> UsbAllocatable<'a, B> for RawFidoConfig<'a> {
103 type Allocated = RawFido<'a, B>;
104
105 fn allocate(self, usb_alloc: &'a UsbBusAllocator<B>) -> Self::Allocated {
106 Self::Allocated {
107 interface: Interface::new(usb_alloc, self.interface),
108 }
109 }
110}