ProjektMaus/src/mouse_hid.rs

116 lines
3 KiB
Rust

use rp_pico as bsp;
use bsp::{
hal::{
clocks::ClocksManager,
pac,
pac::{interrupt, Interrupt},
usb::UsbBus,
Clock,
},
pac::{RESETS, USBCTRL_DPRAM, USBCTRL_REGS},
};
use cortex_m::{delay::Delay, Peripherals as CortexPeripherals};
use usb_device::{class_prelude::*, prelude::*};
use usbd_hid::{
descriptor::{MouseReport, SerializedDescriptor},
hid_class::HIDClass,
};
/// The USB Device Driver (shared with the interrupt).
static mut USB_DEVICE: Option<UsbDevice<UsbBus>> = None;
/// The USB Bus Driver (shared with the interrupt).
static mut USB_BUS: Option<UsbBusAllocator<UsbBus>> = None;
/// The USB Human Interface Device Driver (shared with the interrupt).
static mut USB_HID: Option<HIDClass<UsbBus>> = None;
pub struct MouseHID {
delay: Delay,
}
impl MouseHID {
const PIXEL: i8 = 2;
const WAIT_TIME: u32 = 10000;
pub fn new(
usbctrl_reg: USBCTRL_REGS,
usbctrl_dpram: USBCTRL_DPRAM,
resets: &mut RESETS,
core: CortexPeripherals,
clocks: ClocksManager,
) -> Self {
unsafe {
USB_BUS = Some(UsbBusAllocator::new(UsbBus::new(
usbctrl_reg,
usbctrl_dpram,
clocks.usb_clock,
true,
resets,
)))
};
unsafe {
USB_HID = Some(HIDClass::new(
USB_BUS.as_ref().unwrap(),
MouseReport::desc(),
60,
));
}
unsafe {
USB_DEVICE = Some(
UsbDeviceBuilder::new(USB_BUS.as_ref().unwrap(), UsbVidPid(0x046d, 0x101b))
.manufacturer("Logitech")
.product("Marathon Mouse/Performance Plus M705")
.serial_number("B14D65DA")
.device_class(0)
.build(),
);
}
unsafe {
pac::NVIC::unmask(Interrupt::USBCTRL_IRQ);
}
let delay = Delay::new(core.SYST, clocks.system_clock.freq().to_Hz());
Self { delay }
}
pub fn run(&mut self) {
self.mouse_move(Self::WAIT_TIME, Self::PIXEL);
self.mouse_move(50, -Self::PIXEL);
}
fn mouse_move(&mut self, wait_time: u32, v: i8) {
self.delay.delay_ms(wait_time);
let rep = MouseReport {
x: 0,
y: v,
buttons: 0,
wheel: 0,
pan: 0,
};
push_mouse_movement(rep).unwrap_or(0);
}
}
/// with interrupts disabled, to avoid a race hazard with the USB IRQ.
fn push_mouse_movement(report: MouseReport) -> Result<usize, usb_device::UsbError> {
critical_section::with(|_| unsafe { USB_HID.as_mut().map(|hid| hid.push_input(&report)) })
.unwrap()
}
#[allow(non_snake_case)]
#[interrupt]
unsafe fn USBCTRL_IRQ() {
// Handle USB request
let usb_dev = USB_DEVICE.as_mut().unwrap();
let usb_hid = USB_HID.as_mut().unwrap();
usb_dev.poll(&mut [usb_hid]);
}