usbd_human_interface_device/device/
multiaxis.rs1use crate::usb_class::prelude::*;
3use core::default::Default;
4use fugit::ExtU32;
5use packed_struct::prelude::*;
6use usb_device::bus::UsbBus;
7use usb_device::class_prelude::UsbBusAllocator;
8
9#[rustfmt::skip]
10pub const MULTIAXIS_DESCRIPTOR: &[u8] = &[
11 0x05, 0x01, 0x09, 0x08, 0xa1, 0x01, 0x09, 0x01, 0xa1, 0x00, 0x09, 0x30, 0x09, 0x31, 0x09, 0x32, 0x09, 0x33, 0x09, 0x34, 0x09, 0x35, 0x15, 0x81, 0x25, 0x7f, 0x75, 0x08, 0x95, 0x06, 0x81, 0x02, 0xc0, 0x05, 0x09, 0x19, 0x01, 0x29, 0x08, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0xc0, ];
38
39#[cfg_attr(feature = "defmt", derive(defmt::Format))]
40#[derive(Clone, Copy, Debug, Eq, PartialEq, Default, PackedStruct)]
41#[packed_struct(endian = "lsb", size_bytes = "7")]
42pub struct MultiaxisReport {
43 #[packed_field]
44 pub x: i8,
45 #[packed_field]
46 pub y: i8,
47 #[packed_field]
48 pub z: i8,
49 #[packed_field]
50 pub rx: i8,
51 #[packed_field]
52 pub ry: i8,
53 #[packed_field]
54 pub rz: i8,
55 #[packed_field]
56 pub buttons: u8,
57}
58
59pub struct Multiaxis<'a, B: UsbBus> {
60 interface: Interface<'a, B, InBytes8, OutNone, ReportSingle>,
61}
62
63impl<B: UsbBus> Multiaxis<'_, B> {
64 pub fn write_report(&mut self, report: &MultiaxisReport) -> Result<(), UsbHidError> {
65 let data = report.pack().map_err(|_| {
66 error!("Error packing MultiaxisReport");
67 UsbHidError::SerializationError
68 })?;
69 self.interface
70 .write_report(&data)
71 .map(|_| ())
72 .map_err(UsbHidError::from)
73 }
74}
75
76impl<'a, B: UsbBus> DeviceClass<'a> for Multiaxis<'a, B> {
77 type I = Interface<'a, B, InBytes8, OutNone, ReportSingle>;
78
79 fn interface(&mut self) -> &mut Self::I {
80 &mut self.interface
81 }
82
83 fn reset(&mut self) {}
84
85 fn tick(&mut self) -> Result<(), UsbHidError> {
86 Ok(())
87 }
88}
89
90pub struct MultiaxisConfig<'a> {
91 interface: InterfaceConfig<'a, InBytes8, OutNone, ReportSingle>,
92}
93
94impl Default for MultiaxisConfig<'_> {
95 fn default() -> Self {
96 Self::new(
97 unwrap!(unwrap!(InterfaceBuilder::new(MULTIAXIS_DESCRIPTOR))
98 .boot_device(InterfaceProtocol::None)
99 .description("Multi-axis Controller")
100 .in_endpoint(10.millis()))
101 .without_out_endpoint()
102 .build(),
103 )
104 }
105}
106
107impl<'a> MultiaxisConfig<'a> {
108 #[must_use]
109 pub fn new(interface: InterfaceConfig<'a, InBytes8, OutNone, ReportSingle>) -> Self {
110 Self { interface }
111 }
112}
113
114impl<'a, B: UsbBus + 'a> UsbAllocatable<'a, B> for MultiaxisConfig<'a> {
115 type Allocated = Multiaxis<'a, B>;
116
117 fn allocate(self, usb_alloc: &'a UsbBusAllocator<B>) -> Self::Allocated {
118 Self::Allocated {
119 interface: Interface::new(usb_alloc, self.interface),
120 }
121 }
122}