usbd_human_interface_device/device/
joystick.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 JOYSTICK_DESCRIPTOR: &[u8] = &[
11 0x05, 0x01, 0x09, 0x04, 0xa1, 0x01, 0x09, 0x01, 0xa1, 0x00, 0x09, 0x30, 0x09, 0x31, 0x15, 0x81, 0x25, 0x7f, 0x75, 0x08, 0x95, 0x02, 0x81, 0x02, 0xc0, 0x05, 0x09, 0x19, 0x01, 0x29, 0x08, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0xc0, ];
34
35#[cfg_attr(feature = "defmt", derive(defmt::Format))]
36#[derive(Clone, Copy, Debug, Eq, PartialEq, Default, PackedStruct)]
37#[packed_struct(endian = "lsb", size_bytes = "3")]
38pub struct JoystickReport {
39 #[packed_field]
40 pub x: i8,
41 #[packed_field]
42 pub y: i8,
43 #[packed_field]
44 pub buttons: u8,
45}
46
47pub struct Joystick<'a, B: UsbBus> {
48 interface: Interface<'a, B, InBytes8, OutNone, ReportSingle>,
49}
50
51impl<B: UsbBus> Joystick<'_, B> {
52 pub fn write_report(&mut self, report: &JoystickReport) -> Result<(), UsbHidError> {
53 let data = report.pack().map_err(|_| {
54 error!("Error packing JoystickReport");
55 UsbHidError::SerializationError
56 })?;
57 self.interface
58 .write_report(&data)
59 .map(|_| ())
60 .map_err(UsbHidError::from)
61 }
62}
63
64impl<'a, B: UsbBus> DeviceClass<'a> for Joystick<'a, B> {
65 type I = Interface<'a, B, InBytes8, OutNone, ReportSingle>;
66
67 fn interface(&mut self) -> &mut Self::I {
68 &mut self.interface
69 }
70
71 fn reset(&mut self) {}
72
73 fn tick(&mut self) -> Result<(), UsbHidError> {
74 Ok(())
75 }
76}
77
78pub struct JoystickConfig<'a> {
79 interface: InterfaceConfig<'a, InBytes8, OutNone, ReportSingle>,
80}
81
82impl Default for JoystickConfig<'_> {
83 fn default() -> Self {
84 Self::new(
85 unwrap!(unwrap!(InterfaceBuilder::new(JOYSTICK_DESCRIPTOR))
86 .boot_device(InterfaceProtocol::None)
87 .description("Joystick")
88 .in_endpoint(10.millis()))
89 .without_out_endpoint()
90 .build(),
91 )
92 }
93}
94
95impl<'a> JoystickConfig<'a> {
96 #[must_use]
97 pub fn new(interface: InterfaceConfig<'a, InBytes8, OutNone, ReportSingle>) -> Self {
98 Self { interface }
99 }
100}
101
102impl<'a, B: UsbBus + 'a> UsbAllocatable<'a, B> for JoystickConfig<'a> {
103 type Allocated = Joystick<'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}