Implement USB HID device

This commit is contained in:
Luca 2022-02-24 15:42:53 +01:00
parent 57b4c79d77
commit 7871f832ee
2 changed files with 104 additions and 21 deletions

View File

@ -10,4 +10,6 @@ cortex-m = "0.7.4"
cortex-m-rt = "0.7.1" cortex-m-rt = "0.7.1"
nb = "1" nb = "1"
panic-halt = "0.2.0" 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"

View File

@ -1,6 +1,6 @@
/* /*
* any key firmware * 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 * 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 * 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::prelude::*;
use stm32f0xx_hal::pwm::tim3; use stm32f0xx_hal::pwm::tim3;
use stm32f0xx_hal::timers::Timer; 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] #[entry]
fn main() -> ! { fn main() -> ! {
@ -36,10 +63,13 @@ fn main() -> ! {
let gpioa = p.GPIOA.split(&mut rcc); let gpioa = p.GPIOA.split(&mut rcc);
let gpiob = p.GPIOB.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.pa0.into_push_pull_output(cs),
gpioa.pa1.into_push_pull_output(cs), gpioa.pa1.into_push_pull_output(cs),
gpioa.pa2.into_push_pull_output(cs), gpioa.pa2.into_push_pull_output(cs),
gpioa.pa3,
gpioa.pa11,
gpioa.pa12,
)); ));
led1_r.set_high().ok(); // 0 led1_r.set_high().ok(); // 0
@ -62,34 +92,85 @@ fn main() -> ! {
led2_r.set_duty(led2_r_max); // 0 led2_r.set_duty(led2_r_max); // 0
led2_g.set_duty(led2_g_max); // 0 led2_g.set_duty(led2_g_max); // 0
led2_b.set_duty(led2_b_max); // 0 led2_b.set_duty(led2_b_max); // 0
// ^ violet
led2_r.enable(); led2_r.enable();
led2_g.enable(); led2_g.enable();
led2_b.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 hue = 0;
let mut prev = false;
loop { loop {
let h_i = hue / 60; usb_dev.poll(&mut [&mut hid]);
let f = hue as f32 / 60.0 - h_i as f32;
let q = 1.0 - f;
let (r, g, b) = match h_i { if counter == 0 {
0 => (1.0, f, 0.0), if let Ok(btn1_pressed) = btn1.is_high() {
1 => ( q, 1.0, 0.0), if btn1_pressed != prev {
2 => (0.0, 1.0, f), prev = btn1_pressed;
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; 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(); block!(timer.wait()).ok();
} }