From c0ec86f5ec4428543ae18af941c7e3ef6877a369 Mon Sep 17 00:00:00 2001 From: Brian Cully Date: Sat, 19 Nov 2022 14:05:18 -0500 Subject: usb: add mousewheel hid implementation --- src/bin/luchie.rs | 74 +++++++++++++++++++++++++++++++++++++++++++++---------- src/cirque.rs | 10 ++++---- 2 files changed, 66 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/bin/luchie.rs b/src/bin/luchie.rs index 7dedc8d..7d25a00 100755 --- a/src/bin/luchie.rs +++ b/src/bin/luchie.rs @@ -3,6 +3,8 @@ //extern crate panic_semihosting; +use core::cmp; + use luchie::{ cirque::Cirque, log, logger, logln, @@ -22,6 +24,10 @@ use stm32f1xx_hal::{ usb::{self, UsbBus}, }; use usb_device::prelude::*; +use usbd_human_interface_device::{ + prelude::*, + device::mouse::{WheelMouseInterface, WheelMouseReport}, +}; use usbd_serial::{SerialPort, USB_CLASS_CDC}; #[entry] @@ -35,15 +41,11 @@ fn main() -> ! { .cfgr .use_hse(8.MHz()) .sysclk(72.MHz()) // TODO: gd32 can get up to 120MHz - // .pclk1(24.MHz()) // TODO: causes issues with gd32 usb (dropped packets) and garbled usart1 output + .pclk1(24.MHz()) // TODO: causes issues with gd32 usb (dropped packets) and garbled usart1 output .freeze(&mut flash.acr); assert!(clocks.usbclk_valid()); - let mut gpiob = dp.GPIOB.split(); - let mut led = gpiob.pb2.into_push_pull_output(&mut gpiob.crl); - led.set_low(); - let mut afio = dp.AFIO.constrain(); let mut gpioa = dp.GPIOA.split(); @@ -117,6 +119,11 @@ fn main() -> ! { let mut serial = SerialPort::new(&usb_bus); + let mut mouse_report = WheelMouseReport::default(); + let mut mouse = UsbHidClassBuilder::new() + .add_interface(WheelMouseInterface::default_config()) + .build(&usb_bus); + let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0xdead, 0xbeef)) .manufacturer("Fake company") .product("Serial port") @@ -124,17 +131,23 @@ fn main() -> ! { .device_class(USB_CLASS_CDC) .build(); + while usb_dev.state() != UsbDeviceState::Configured { + usb_dev.poll(&mut [&mut serial, &mut mouse]); + } + + logln!("💡 init led"); + let mut gpiob = dp.GPIOB.split(); + let mut led = gpiob.pb2.into_push_pull_output(&mut gpiob.crl); + led.set_low(); + logln!("🎉 luchie started!"); + + let mut is_pressed = false; + let mut last_x = 0u16; + let mut last_y = 0u16; loop { // logln!("."); - if let Ok(mut td) = cirque.poll(&mut spi) { - td.scale_to(1920, 1080); - logln!("td: {:?}", td); - } - - if !usb_dev.poll(&mut [&mut serial]) { - continue; - } + usb_dev.poll(&mut [&mut serial, &mut mouse]); let mut buf = [0u8; 64]; @@ -162,6 +175,41 @@ fn main() -> ! { } _ => {} } + + if let Ok(td) = cirque.poll(&mut spi) { + logln!("td: {:?}", td); + if td.is_pressed { + if is_pressed { + /* + * The trackpad's actual valid return values are + * only about 2^11, so overflow isn't possible + * when converting to signed 16 bit integers. + */ + let s_x: i16 = td.x as i16 - last_x as i16; + let s_y: i16 = td.y as i16 - last_y as i16; + + // Clamp to i8 range. + let raw_x = cmp::max(i8::MIN as i16, cmp::min(i8::MAX as i16, s_x)); + let raw_y = cmp::max(i8::MIN as i16, cmp::min(i8::MAX as i16, s_y)); + mouse_report.x = raw_x as i8; + mouse_report.y = raw_y as i8; + } + is_pressed = true; + last_x = td.x; + last_y = td.y; + } else { + mouse_report.x = 0; + mouse_report.y = 0; + is_pressed = false; + } + match mouse.interface().write_report(&mouse_report) { + Err(UsbHidError::WouldBlock) => {}, + Err(e) => { + panic!("couldn't write mouse report: {:?}", e) + }, + _ => {}, + } + } } } diff --git a/src/cirque.rs b/src/cirque.rs index 23df15b..0f40c51 100644 --- a/src/cirque.rs +++ b/src/cirque.rs @@ -98,11 +98,11 @@ where #[allow(unused)] #[derive(Debug)] pub struct TouchData { - x: u16, - y: u16, - z: u8, - buttons: u8, - is_pressed: bool, + pub x: u16, + pub y: u16, + pub z: u8, + pub buttons: u8, + pub is_pressed: bool, } impl TouchData { -- cgit v1.2.3