use core::default::Default;
use fugit::ExtU32;
use packed_struct::prelude::*;
use usb_device::bus::UsbBus;
use usb_device::class_prelude::UsbBusAllocator;
use crate::hid_class::prelude::*;
use crate::interface::raw::{RawInterface, RawInterfaceConfig};
use crate::interface::{InterfaceClass, UsbAllocatable};
use crate::UsbHidError;
#[rustfmt::skip]
pub const JOYSTICK_DESCRIPTOR: &[u8] = &[
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, ];
#[derive(Clone, Copy, Debug, Eq, PartialEq, Default, PackedStruct)]
#[packed_struct(endian = "lsb", size_bytes = "3")]
pub struct JoystickReport {
#[packed_field]
pub x: i8,
#[packed_field]
pub y: i8,
#[packed_field]
pub buttons: u8,
}
pub struct JoystickInterface<'a, B: UsbBus> {
inner: RawInterface<'a, B>,
}
impl<'a, B: UsbBus> JoystickInterface<'a, B> {
pub fn write_report(&mut self, report: &JoystickReport) -> Result<(), UsbHidError> {
let data = report.pack().map_err(|_| {
error!("Error packing JoystickReport");
UsbHidError::SerializationError
})?;
self.inner
.write_report(&data)
.map(|_| ())
.map_err(UsbHidError::from)
}
}
impl<'a, B: UsbBus> InterfaceClass<'a, B> for JoystickInterface<'a, B> {
fn interface(&mut self) -> &mut RawInterface<'a, B> {
&mut self.inner
}
fn reset(&mut self) {}
}
pub struct JoystickConfig<'a> {
interface: RawInterfaceConfig<'a>,
}
impl<'a> Default for JoystickConfig<'a> {
#[must_use]
fn default() -> Self {
Self::new(
unwrap!(unwrap!(RawInterfaceBuilder::new(JOYSTICK_DESCRIPTOR))
.boot_device(InterfaceProtocol::None)
.description("Joystick")
.in_endpoint(UsbPacketSize::Bytes8, 10.millis()))
.without_out_endpoint()
.build(),
)
}
}
impl<'a> JoystickConfig<'a> {
#[must_use]
pub fn new(interface: RawInterfaceConfig<'a>) -> Self {
Self { interface }
}
}
impl<'a, B: UsbBus + 'a> UsbAllocatable<'a, B> for JoystickConfig<'a> {
type Allocated = JoystickInterface<'a, B>;
fn allocate(self, usb_alloc: &'a UsbBusAllocator<B>) -> Self::Allocated {
Self::Allocated {
inner: RawInterface::new(usb_alloc, self.interface),
}
}
}