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 --- Cargo.lock | 398 +++++++++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 1 + src/bin/luchie.rs | 74 ++++++++-- src/cirque.rs | 10 +- 4 files changed, 463 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1c14cdc..118d04a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,13 +2,37 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aho-corasick" +version = "0.7.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" +dependencies = [ + "memchr", +] + +[[package]] +name = "atomic-polyfill" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c041a8d9751a520ee19656232a18971f18946a7900f1520ee4400002244dd89" +dependencies = [ + "critical-section", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + [[package]] name = "bare-metal" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" dependencies = [ - "rustc_version", + "rustc_version 0.2.3", ] [[package]] @@ -17,6 +41,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" +[[package]] +name = "bit_field" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4" + [[package]] name = "bitfield" version = "0.13.2" @@ -29,6 +59,18 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "bxcan" version = "0.6.2" @@ -40,6 +82,18 @@ dependencies = [ "vcell", ] +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "cortex-m" version = "0.7.6" @@ -72,6 +126,29 @@ dependencies = [ "syn", ] +[[package]] +name = "critical-section" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95da181745b56d4bd339530ec393508910c909c784e8962d15d722bacf0bcbcd" +dependencies = [ + "bare-metal 1.0.0", + "cfg-if", + "cortex-m", + "riscv", +] + +[[package]] +name = "delegate" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "082a24a9967533dc5d743c602157637116fc1b52806d694a5a45e6f32567fcdd" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "embedded-dma" version = "0.2.0" @@ -91,6 +168,54 @@ dependencies = [ "void", ] +[[package]] +name = "embedded-time" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7a4b4d10ac48d08bfe3db7688c402baadb244721f30a77ce360bd24c3dffe58" +dependencies = [ + "num", +] + +[[package]] +name = "frunk" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89c703bf50009f383a0873845357cc400a95fc535f836feddfe015d7df6e1e0" +dependencies = [ + "frunk_core", + "frunk_derives", +] + +[[package]] +name = "frunk_core" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a446d01a558301dca28ef43222864a9fa2bd9a2e71370f769d5d5d5ec9f3537" + +[[package]] +name = "frunk_derives" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b83164912bb4c97cfe0772913c7af7387ee2e00cb6d4636fb65a35b3d0c8f173" +dependencies = [ + "frunk_proc_macro_helpers", + "quote", + "syn", +] + +[[package]] +name = "frunk_proc_macro_helpers" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "015425591bbeb0f5b8a75593340f1789af428e9f887a4f1e36c0c471f067ef50" +dependencies = [ + "frunk_core", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "fugit" version = "0.3.6" @@ -110,6 +235,12 @@ dependencies = [ "nb 1.0.0", ] +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "gcd" version = "2.1.0" @@ -119,6 +250,53 @@ dependencies = [ "paste", ] +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "heapless" +version = "0.7.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743" +dependencies = [ + "atomic-polyfill", + "hash32", + "rustc_version 0.4.0", + "spin", + "stable_deref_trait", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + [[package]] name = "luchie" version = "0.1.0" @@ -129,10 +307,17 @@ dependencies = [ "nb 1.0.0", "stm32f1xx-hal", "usb-device", + "usbd-human-interface-device", "usbd-serial", "usbd-webusb", ] +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + [[package]] name = "nb" version = "0.1.3" @@ -148,6 +333,110 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" +[[package]] +name = "num" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f" +dependencies = [ + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_enum" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "packed_struct" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36b29691432cc9eff8b282278473b63df73bea49bc3ec5e67f31a3ae9c3ec190" +dependencies = [ + "bitvec", + "packed_struct_codegen", +] + +[[package]] +name = "packed_struct_codegen" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cd6706dfe50d53e0f6aa09e12c034c44faacd23e966ae5a209e8bdb8f179f98" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "paste" version = "1.0.9" @@ -172,15 +461,74 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "regex" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" + +[[package]] +name = "riscv" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6907ccdd7a31012b70faf2af85cd9e5ba97657cc3987c4f13f8e4d2c2a088aba" +dependencies = [ + "bare-metal 1.0.0", + "bit_field", + "riscv-target", +] + +[[package]] +name = "riscv-target" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88aa938cda42a0cf62a20cfe8d139ff1af20c2e681212b5b34adb5a58333f222" +dependencies = [ + "lazy_static", + "regex", +] + [[package]] name = "rustc_version" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" dependencies = [ - "semver", + "semver 0.9.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.14", ] +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + [[package]] name = "semver" version = "0.9.0" @@ -190,12 +538,27 @@ dependencies = [ "semver-parser", ] +[[package]] +name = "semver" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" + [[package]] name = "semver-parser" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +[[package]] +name = "spin" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09" +dependencies = [ + "lock_api", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -256,6 +619,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "unicode-ident" version = "1.0.5" @@ -268,6 +637,22 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f6cc3adc849b5292b4075fc0d5fdcf2f24866e88e336dd27a8943090a520508" +[[package]] +name = "usbd-human-interface-device" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ee948d1fb5d04ccdfac58622e6cd2692105b9ce76bcecce13b1c2f73abe5a41" +dependencies = [ + "delegate", + "embedded-time", + "frunk", + "heapless", + "log", + "num_enum", + "packed_struct", + "usb-device", +] + [[package]] name = "usbd-serial" version = "0.1.1" @@ -308,3 +693,12 @@ checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6" dependencies = [ "vcell", ] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] diff --git a/Cargo.toml b/Cargo.toml index 0af2751..db27d00 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ nb = "1.0.0" usb-device = "0.2.9" usbd-serial = "0.1.1" usbd-webusb = "1.0.2" +usbd-human-interface-device = "0.3.1" embedded-hal = "0.2.7" [dependencies.stm32f1xx-hal] 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