143 lines
3.3 KiB
Rust
143 lines
3.3 KiB
Rust
use crate::{
|
|
serial::{Commands, Serial},
|
|
MouseInfoSender,
|
|
};
|
|
|
|
use rp_pico as bsp;
|
|
|
|
use bsp::{
|
|
hal::{
|
|
clocks::ClocksManager,
|
|
pac,
|
|
pac::{interrupt, Interrupt},
|
|
rom_data::reset_to_usb_boot,
|
|
usb::UsbBus,
|
|
},
|
|
pac::{RESETS, USBCTRL_DPRAM, USBCTRL_REGS},
|
|
};
|
|
|
|
use usb_device::{class_prelude::*, prelude::*};
|
|
use usbd_hid::descriptor::MouseReport;
|
|
|
|
static mut USB_BUS: Option<UsbBusAllocator<UsbBus>> = None;
|
|
static mut USB_SERIAL: Option<Serial> = None;
|
|
static mut USB_DEVICE: Option<UsbDevice<UsbBus>> = None;
|
|
|
|
pub fn serial() -> &'static mut Serial<'static> {
|
|
unsafe { USB_SERIAL.as_mut().unwrap() }
|
|
}
|
|
|
|
pub struct CustomHID {
|
|
c: u32,
|
|
}
|
|
|
|
impl CustomHID {
|
|
pub fn new(
|
|
usbctrl_reg: USBCTRL_REGS,
|
|
usbctrl_dpram: USBCTRL_DPRAM,
|
|
resets: &mut RESETS,
|
|
clocks: ClocksManager,
|
|
poll_ms: u8,
|
|
) -> Self {
|
|
// Set up the USB driver
|
|
unsafe {
|
|
USB_BUS = Some(UsbBusAllocator::new(UsbBus::new(
|
|
usbctrl_reg,
|
|
usbctrl_dpram,
|
|
clocks.usb_clock,
|
|
true,
|
|
resets,
|
|
)))
|
|
};
|
|
|
|
unsafe {
|
|
USB_SERIAL = Some(Serial::new(USB_BUS.as_ref().unwrap()));
|
|
}
|
|
|
|
unsafe {
|
|
USB_DEVICE = Some(
|
|
UsbDeviceBuilder::new(USB_BUS.as_ref().unwrap(), UsbVidPid(0x16c0, 0x27dd))
|
|
.manufacturer("Fake company")
|
|
.product("Serial port")
|
|
.serial_number("TEST")
|
|
.device_class(2) // from: https://www.usb.org/defined-class-codes
|
|
.build(),
|
|
);
|
|
}
|
|
|
|
unsafe {
|
|
pac::NVIC::unmask(Interrupt::USBCTRL_IRQ);
|
|
pac::NVIC::unmask(Interrupt::SW0_IRQ);
|
|
};
|
|
|
|
Self { c: 0 }
|
|
}
|
|
|
|
pub fn serial<F>(&mut self, mut f: F)
|
|
where
|
|
F: FnMut(&mut Serial),
|
|
{
|
|
critical_section::with(|_| {
|
|
f(serial());
|
|
})
|
|
}
|
|
}
|
|
|
|
impl MouseInfoSender for CustomHID {
|
|
fn send(&mut self, x: i8, y: i8, buttons: u8, wheel: i8, pan: i8) {
|
|
push_mouse_movement(MouseReport {
|
|
x,
|
|
y,
|
|
buttons,
|
|
wheel,
|
|
pan,
|
|
})
|
|
}
|
|
|
|
fn heart_beat(&mut self) {
|
|
self.c += 1;
|
|
|
|
if self.c == 1_000_000 {
|
|
self.c = 0;
|
|
|
|
if !(pac::NVIC::is_pending(Interrupt::SW0_IRQ)) {
|
|
pac::NVIC::pend(Interrupt::SW0_IRQ);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// with interrupts disabled, to avoid a race hazard with the USB IRQ.
|
|
fn push_mouse_movement(report: MouseReport) {
|
|
critical_section::with(|_| {
|
|
let serial = serial();
|
|
|
|
serial.send_text("x");
|
|
serial.send_number(report.x, 10);
|
|
|
|
serial.send_text("y");
|
|
serial.send_number(report.y, 10);
|
|
});
|
|
}
|
|
|
|
#[allow(non_snake_case)]
|
|
#[interrupt]
|
|
unsafe fn USBCTRL_IRQ() {
|
|
// Handle USB request
|
|
let usb_dev = USB_DEVICE.as_mut().unwrap();
|
|
let usb_hid = serial();
|
|
|
|
if usb_dev.poll(&mut [usb_hid]) {
|
|
if let Some(command) = usb_hid.read() {
|
|
match command {
|
|
Commands::Reset => reset_to_usb_boot(0, 0),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[allow(non_snake_case)]
|
|
#[interrupt]
|
|
unsafe fn SW0_IRQ() {
|
|
serial().send_text("heartbeat (IRQ)");
|
|
}
|