diff options
| author | matteo <email> | 2025-10-01 18:56:38 +0200 |
|---|---|---|
| committer | matteo <email> | 2025-10-01 18:56:38 +0200 |
| commit | 176649e71ad442ca9856af6c11989b0b2f228c4b (patch) | |
| tree | b425294213a520f09c24dd215c00efadfad69149 /examples/stm32f4 | |
| parent | d79d433d02ab154e5f8570392fd0ca1ffdf9cac1 (diff) | |
update hid mouse and keyboard examples
Diffstat (limited to 'examples/stm32f4')
| -rw-r--r-- | examples/stm32f4/src/bin/usb_hid_keyboard.rs | 78 | ||||
| -rw-r--r-- | examples/stm32f4/src/bin/usb_hid_mouse.rs | 50 |
2 files changed, 93 insertions, 35 deletions
diff --git a/examples/stm32f4/src/bin/usb_hid_keyboard.rs b/examples/stm32f4/src/bin/usb_hid_keyboard.rs index 5521a8240..86b6fa95f 100644 --- a/examples/stm32f4/src/bin/usb_hid_keyboard.rs +++ b/examples/stm32f4/src/bin/usb_hid_keyboard.rs | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::sync::atomic::{AtomicBool, Ordering}; | 4 | use core::sync::atomic::{AtomicBool, AtomicU8, Ordering}; |
| 5 | 5 | ||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| @@ -11,7 +11,9 @@ use embassy_stm32::gpio::Pull; | |||
| 11 | use embassy_stm32::time::Hertz; | 11 | use embassy_stm32::time::Hertz; |
| 12 | use embassy_stm32::usb::Driver; | 12 | use embassy_stm32::usb::Driver; |
| 13 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; | 13 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; |
| 14 | use embassy_usb::class::hid::{HidBootProtocol, HidReaderWriter, HidSubclass, ReportId, RequestHandler, State}; | 14 | use embassy_usb::class::hid::{ |
| 15 | HidBootProtocol, HidProtocolMode, HidReaderWriter, HidSubclass, ReportId, RequestHandler, State, | ||
| 16 | }; | ||
| 15 | use embassy_usb::control::OutResponse; | 17 | use embassy_usb::control::OutResponse; |
| 16 | use embassy_usb::{Builder, Handler}; | 18 | use embassy_usb::{Builder, Handler}; |
| 17 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; | 19 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; |
| @@ -21,6 +23,8 @@ bind_interrupts!(struct Irqs { | |||
| 21 | OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>; | 23 | OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>; |
| 22 | }); | 24 | }); |
| 23 | 25 | ||
| 26 | static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8); | ||
| 27 | |||
| 24 | // If you are trying this and your USB device doesn't connect, the most | 28 | // If you are trying this and your USB device doesn't connect, the most |
| 25 | // common issues are the RCC config and vbus_detection | 29 | // common issues are the RCC config and vbus_detection |
| 26 | // | 30 | // |
| @@ -127,32 +131,46 @@ async fn main(_spawner: Spawner) { | |||
| 127 | button.wait_for_rising_edge().await; | 131 | button.wait_for_rising_edge().await; |
| 128 | // signal_pin.wait_for_high().await; | 132 | // signal_pin.wait_for_high().await; |
| 129 | info!("Button pressed!"); | 133 | info!("Button pressed!"); |
| 130 | // Create a report with the A key pressed. (no shift modifier) | 134 | if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { |
| 131 | let report = KeyboardReport { | 135 | match writer.write(&[0, 0, 4, 0, 0, 0, 0, 0]).await { |
| 132 | keycodes: [4, 0, 0, 0, 0, 0], | 136 | Ok(()) => {} |
| 133 | leds: 0, | 137 | Err(e) => warn!("Failed to send boot report: {:?}", e), |
| 134 | modifier: 0, | 138 | }; |
| 135 | reserved: 0, | 139 | } else { |
| 136 | }; | 140 | // Create a report with the A key pressed. (no shift modifier) |
| 137 | // Send the report. | 141 | let report = KeyboardReport { |
| 138 | match writer.write_serialize(&report).await { | 142 | keycodes: [4, 0, 0, 0, 0, 0], |
| 139 | Ok(()) => {} | 143 | leds: 0, |
| 140 | Err(e) => warn!("Failed to send report: {:?}", e), | 144 | modifier: 0, |
| 141 | }; | 145 | reserved: 0, |
| 146 | }; | ||
| 147 | // Send the report. | ||
| 148 | match writer.write_serialize(&report).await { | ||
| 149 | Ok(()) => {} | ||
| 150 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 151 | }; | ||
| 152 | } | ||
| 142 | 153 | ||
| 143 | button.wait_for_falling_edge().await; | 154 | button.wait_for_falling_edge().await; |
| 144 | // signal_pin.wait_for_low().await; | 155 | // signal_pin.wait_for_low().await; |
| 145 | info!("Button released!"); | 156 | info!("Button released!"); |
| 146 | let report = KeyboardReport { | 157 | if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { |
| 147 | keycodes: [0, 0, 0, 0, 0, 0], | 158 | match writer.write(&[0, 0, 0, 0, 0, 0, 0, 0]).await { |
| 148 | leds: 0, | 159 | Ok(()) => {} |
| 149 | modifier: 0, | 160 | Err(e) => warn!("Failed to send boot report: {:?}", e), |
| 150 | reserved: 0, | 161 | }; |
| 151 | }; | 162 | } else { |
| 152 | match writer.write_serialize(&report).await { | 163 | let report = KeyboardReport { |
| 153 | Ok(()) => {} | 164 | keycodes: [0, 0, 0, 0, 0, 0], |
| 154 | Err(e) => warn!("Failed to send report: {:?}", e), | 165 | leds: 0, |
| 155 | }; | 166 | modifier: 0, |
| 167 | reserved: 0, | ||
| 168 | }; | ||
| 169 | match writer.write_serialize(&report).await { | ||
| 170 | Ok(()) => {} | ||
| 171 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 172 | }; | ||
| 173 | } | ||
| 156 | } | 174 | } |
| 157 | }; | 175 | }; |
| 158 | 176 | ||
| @@ -178,6 +196,18 @@ impl RequestHandler for MyRequestHandler { | |||
| 178 | OutResponse::Accepted | 196 | OutResponse::Accepted |
| 179 | } | 197 | } |
| 180 | 198 | ||
| 199 | fn get_protocol(&self) -> HidProtocolMode { | ||
| 200 | let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed)); | ||
| 201 | info!("The current HID protocol mode is: {}", protocol); | ||
| 202 | protocol | ||
| 203 | } | ||
| 204 | |||
| 205 | fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse { | ||
| 206 | info!("Switching to HID protocol mode: {}", protocol); | ||
| 207 | HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed); | ||
| 208 | OutResponse::Accepted | ||
| 209 | } | ||
| 210 | |||
| 181 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { | 211 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { |
| 182 | info!("Set idle rate for {:?} to {:?}", id, dur); | 212 | info!("Set idle rate for {:?} to {:?}", id, dur); |
| 183 | } | 213 | } |
diff --git a/examples/stm32f4/src/bin/usb_hid_mouse.rs b/examples/stm32f4/src/bin/usb_hid_mouse.rs index 5cfa0aec4..977db4c15 100644 --- a/examples/stm32f4/src/bin/usb_hid_mouse.rs +++ b/examples/stm32f4/src/bin/usb_hid_mouse.rs | |||
| @@ -1,6 +1,8 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::sync::atomic::{AtomicU8, Ordering}; | ||
| 5 | |||
| 4 | use defmt::*; | 6 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 6 | use embassy_futures::join::join; | 8 | use embassy_futures::join::join; |
| @@ -8,7 +10,9 @@ use embassy_stm32::time::Hertz; | |||
| 8 | use embassy_stm32::usb::Driver; | 10 | use embassy_stm32::usb::Driver; |
| 9 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; | 11 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; |
| 10 | use embassy_time::Timer; | 12 | use embassy_time::Timer; |
| 11 | use embassy_usb::class::hid::{HidBootProtocol, HidSubclass, HidWriter, ReportId, RequestHandler, State}; | 13 | use embassy_usb::class::hid::{ |
| 14 | HidBootProtocol, HidProtocolMode, HidSubclass, HidWriter, ReportId, RequestHandler, State, | ||
| 15 | }; | ||
| 12 | use embassy_usb::control::OutResponse; | 16 | use embassy_usb::control::OutResponse; |
| 13 | use embassy_usb::Builder; | 17 | use embassy_usb::Builder; |
| 14 | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; | 18 | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; |
| @@ -18,6 +22,8 @@ bind_interrupts!(struct Irqs { | |||
| 18 | OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>; | 22 | OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>; |
| 19 | }); | 23 | }); |
| 20 | 24 | ||
| 25 | static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8); | ||
| 26 | |||
| 21 | // If you are trying this and your USB device doesn't connect, the most | 27 | // If you are trying this and your USB device doesn't connect, the most |
| 22 | // common issues are the RCC config and vbus_detection | 28 | // common issues are the RCC config and vbus_detection |
| 23 | // | 29 | // |
| @@ -114,16 +120,26 @@ async fn main(_spawner: Spawner) { | |||
| 114 | Timer::after_millis(500).await; | 120 | Timer::after_millis(500).await; |
| 115 | 121 | ||
| 116 | y = -y; | 122 | y = -y; |
| 117 | let report = MouseReport { | 123 | |
| 118 | buttons: 0, | 124 | if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { |
| 119 | x: 0, | 125 | let buttons = 0u8; |
| 120 | y, | 126 | let x = 0i8; |
| 121 | wheel: 0, | 127 | match writer.write(&[buttons, x as u8, y as u8]).await { |
| 122 | pan: 0, | 128 | Ok(()) => {} |
| 123 | }; | 129 | Err(e) => warn!("Failed to send boot report: {:?}", e), |
| 124 | match writer.write_serialize(&report).await { | 130 | } |
| 125 | Ok(()) => {} | 131 | } else { |
| 126 | Err(e) => warn!("Failed to send report: {:?}", e), | 132 | let report = MouseReport { |
| 133 | buttons: 0, | ||
| 134 | x: 0, | ||
| 135 | y, | ||
| 136 | wheel: 0, | ||
| 137 | pan: 0, | ||
| 138 | }; | ||
| 139 | match writer.write_serialize(&report).await { | ||
| 140 | Ok(()) => {} | ||
| 141 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 142 | } | ||
| 127 | } | 143 | } |
| 128 | } | 144 | } |
| 129 | }; | 145 | }; |
| @@ -146,6 +162,18 @@ impl RequestHandler for MyRequestHandler { | |||
| 146 | OutResponse::Accepted | 162 | OutResponse::Accepted |
| 147 | } | 163 | } |
| 148 | 164 | ||
| 165 | fn get_protocol(&self) -> HidProtocolMode { | ||
| 166 | let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed)); | ||
| 167 | info!("The current HID protocol mode is: {}", protocol); | ||
| 168 | protocol | ||
| 169 | } | ||
| 170 | |||
| 171 | fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse { | ||
| 172 | info!("Switching to HID protocol mode: {}", protocol); | ||
| 173 | HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed); | ||
| 174 | OutResponse::Accepted | ||
| 175 | } | ||
| 176 | |||
| 149 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { | 177 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { |
| 150 | info!("Set idle rate for {:?} to {:?}", id, dur); | 178 | info!("Set idle rate for {:?} to {:?}", id, dur); |
| 151 | } | 179 | } |
