From 7871f832eed9ad666baf8f51ec91ef4f88f503d0 Mon Sep 17 00:00:00 2001 From: Luca Date: Thu, 24 Feb 2022 15:42:53 +0100 Subject: [PATCH] Implement USB HID device --- Cargo.toml | 4 +- src/main.rs | 121 +++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 104 insertions(+), 21 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 24879ea..41818ea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,4 +10,6 @@ cortex-m = "0.7.4" cortex-m-rt = "0.7.1" nb = "1" panic-halt = "0.2.0" -stm32f0xx-hal = { version = "0.18.0", features = ["rt", "stm32f072"] } +stm32f0xx-hal = { version = "0.18.0", features = ["rt", "stm32f072", "stm32-usbd"] } +usb-device = "0.2.8" +usbd-hid = "0.5.2" diff --git a/src/main.rs b/src/main.rs index aa4a43a..cee6e7d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ /* * any key firmware - * Copyright (C) 2020 Luca Schmid + * Copyright (C) 2020-2022 Luca Schmid * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,6 +26,33 @@ use stm32f0xx_hal::pac::Peripherals; use stm32f0xx_hal::prelude::*; use stm32f0xx_hal::pwm::tim3; use stm32f0xx_hal::timers::Timer; +use stm32f0xx_hal::usb::{Peripheral, UsbBus}; +use usb_device::prelude::*; +use usbd_hid::descriptor::KeyboardReport; +use usbd_hid::descriptor::generator_prelude::*; +use usbd_hid::hid_class::HIDClass; + +enum Action { + Copy, + Paste, +} + +impl Action { + fn as_report(&self) -> KeyboardReport { + KeyboardReport { + modifier: 1, // Left Ctrl + reserved: 0, + leds: 0, + keycodes: [ + match *self { + Action::Copy => 0x6, // C + Action::Paste => 0x19, // V + }, + 0, 0, 0, 0, 0, + ], + } + } +} #[entry] fn main() -> ! { @@ -36,10 +63,13 @@ fn main() -> ! { let gpioa = p.GPIOA.split(&mut rcc); let gpiob = p.GPIOB.split(&mut rcc); - let (mut led1_b, mut led1_g, mut led1_r) = cortex_m::interrupt::free(|cs| ( + let (mut led1_b, mut led1_g, mut led1_r, btn1, usb_dm, usb_dp) = cortex_m::interrupt::free(|cs| ( gpioa.pa0.into_push_pull_output(cs), gpioa.pa1.into_push_pull_output(cs), gpioa.pa2.into_push_pull_output(cs), + gpioa.pa3, + gpioa.pa11, + gpioa.pa12, )); led1_r.set_high().ok(); // 0 @@ -62,34 +92,85 @@ fn main() -> ! { led2_r.set_duty(led2_r_max); // 0 led2_g.set_duty(led2_g_max); // 0 led2_b.set_duty(led2_b_max); // 0 - // ^ violet led2_r.enable(); led2_g.enable(); led2_b.enable(); - let mut timer = Timer::tim1(p.TIM1, 100.hz(), &mut rcc); + let usb = Peripheral { + usb: p.USB, + pin_dm: usb_dm, + pin_dp: usb_dp, + }; + let usb_bus = UsbBus::new(usb); + let mut hid = HIDClass::new(&usb_bus, KeyboardReport::desc(), 127); + + let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x2342, 0x1337)) + .manufacturer("f2o & luj0ga") + .product("anykey") + .serial_number("v1") + .device_class(3) // HID + .build(); + + let mut timer = Timer::tim1(p.TIM1, 1.khz(), &mut rcc); + + let mut action = Action::Copy; + let mut counter = 0; let mut hue = 0; + let mut prev = false; loop { - let h_i = hue / 60; - let f = hue as f32 / 60.0 - h_i as f32; - let q = 1.0 - f; + usb_dev.poll(&mut [&mut hid]); - let (r, g, b) = match h_i { - 0 => (1.0, f, 0.0), - 1 => ( q, 1.0, 0.0), - 2 => (0.0, 1.0, f), - 3 => (0.0, q, 1.0), - 4 => ( f, 0.0, 1.0), - 5 => (1.0, 0.0, q), - _ => (0.0, 0.0, 0.0), - }; - led2_r.set_duty(led2_r_max - (led2_r_max as f32 * r) as u16); - led2_g.set_duty(led2_g_max - (led2_g_max as f32 * g) as u16); - led2_b.set_duty(led2_b_max - (led2_b_max as f32 * b) as u16); + if counter == 0 { + if let Ok(btn1_pressed) = btn1.is_high() { + if btn1_pressed != prev { + prev = btn1_pressed; - hue = (hue + 1) % 360; + let report = if btn1_pressed { + led1_g.set_low().ok(); + action.as_report() + } else { + led1_g.set_high().ok(); + KeyboardReport { + modifier: 0, + reserved: 0, + leds: 0, + keycodes: [0, 0, 0, 0, 0, 0], + } + }; + cortex_m::interrupt::free(|_| hid.push_input(&report)).ok(); + + if btn1_pressed { + action = match action { + Action::Copy => Action::Paste, + Action::Paste => Action::Copy, + }; + } + } + } + + let h_i = hue / 60; + let f = hue as f32 / 60.0 - h_i as f32; + let q = 1.0 - f; + + let (r, g, b) = match h_i { + 0 => (1.0, f, 0.0), + 1 => ( q, 1.0, 0.0), + 2 => (0.0, 1.0, f), + 3 => (0.0, q, 1.0), + 4 => ( f, 0.0, 1.0), + 5 => (1.0, 0.0, q), + _ => (0.0, 0.0, 0.0), + }; + led2_r.set_duty(led2_r_max - (led2_r_max as f32 * r) as u16); + led2_g.set_duty(led2_g_max - (led2_g_max as f32 * g) as u16); + led2_b.set_duty(led2_b_max - (led2_b_max as f32 * b) as u16); + + hue = (hue + 1) % 360; + } + + counter = (counter + 1) % 10; block!(timer.wait()).ok(); }