diff options
Diffstat (limited to 'examples/nrf52840')
| -rw-r--r-- | examples/nrf52840/Cargo.toml | 2 | ||||
| -rw-r--r-- | examples/nrf52840/src/bin/usb_hid_keyboard.rs | 49 | ||||
| -rw-r--r-- | examples/nrf52840/src/bin/usb_hid_mouse.rs | 47 |
3 files changed, 76 insertions, 22 deletions
diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml index 452e83b7e..9a1fc080e 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml | |||
| @@ -28,7 +28,7 @@ cortex-m-rt = "0.7.0" | |||
| 28 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } | 28 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 29 | rand = { version = "0.9.0", default-features = false } | 29 | rand = { version = "0.9.0", default-features = false } |
| 30 | embedded-storage = "0.3.1" | 30 | embedded-storage = "0.3.1" |
| 31 | usbd-hid = "0.8.1" | 31 | usbd-hid = { version = "0.8.1", features = ["defmt"] } |
| 32 | serde = { version = "1.0.136", default-features = false } | 32 | serde = { version = "1.0.136", default-features = false } |
| 33 | embedded-hal = { version = "1.0" } | 33 | embedded-hal = { version = "1.0" } |
| 34 | embedded-hal-async = { version = "1.0" } | 34 | embedded-hal-async = { version = "1.0" } |
diff --git a/examples/nrf52840/src/bin/usb_hid_keyboard.rs b/examples/nrf52840/src/bin/usb_hid_keyboard.rs index 0f0d830c6..a4931099a 100644 --- a/examples/nrf52840/src/bin/usb_hid_keyboard.rs +++ b/examples/nrf52840/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; |
| @@ -17,6 +17,7 @@ use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; | |||
| 17 | use embassy_usb::control::OutResponse; | 17 | use embassy_usb::control::OutResponse; |
| 18 | use embassy_usb::{Builder, Config, Handler}; | 18 | use embassy_usb::{Builder, Config, Handler}; |
| 19 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; | 19 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; |
| 20 | use usbd_hid::hid_class::HidProtocolMode; | ||
| 20 | use {defmt_rtt as _, panic_probe as _}; | 21 | use {defmt_rtt as _, panic_probe as _}; |
| 21 | 22 | ||
| 22 | bind_interrupts!(struct Irqs { | 23 | bind_interrupts!(struct Irqs { |
| @@ -26,6 +27,8 @@ bind_interrupts!(struct Irqs { | |||
| 26 | 27 | ||
| 27 | static SUSPENDED: AtomicBool = AtomicBool::new(false); | 28 | static SUSPENDED: AtomicBool = AtomicBool::new(false); |
| 28 | 29 | ||
| 30 | static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8); | ||
| 31 | |||
| 29 | #[embassy_executor::main] | 32 | #[embassy_executor::main] |
| 30 | async fn main(_spawner: Spawner) { | 33 | async fn main(_spawner: Spawner) { |
| 31 | let p = embassy_nrf::init(Default::default()); | 34 | let p = embassy_nrf::init(Default::default()); |
| @@ -110,6 +113,11 @@ async fn main(_spawner: Spawner) { | |||
| 110 | if SUSPENDED.load(Ordering::Acquire) { | 113 | if SUSPENDED.load(Ordering::Acquire) { |
| 111 | info!("Triggering remote wakeup"); | 114 | info!("Triggering remote wakeup"); |
| 112 | remote_wakeup.signal(()); | 115 | remote_wakeup.signal(()); |
| 116 | } else if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { | ||
| 117 | match writer.write(&[0, 0, 4, 0, 0, 0, 0, 0]).await { | ||
| 118 | Ok(()) => {} | ||
| 119 | Err(e) => warn!("Failed to send boot report: {:?}", e), | ||
| 120 | }; | ||
| 113 | } else { | 121 | } else { |
| 114 | let report = KeyboardReport { | 122 | let report = KeyboardReport { |
| 115 | keycodes: [4, 0, 0, 0, 0, 0], | 123 | keycodes: [4, 0, 0, 0, 0, 0], |
| @@ -125,16 +133,23 @@ async fn main(_spawner: Spawner) { | |||
| 125 | 133 | ||
| 126 | button.wait_for_high().await; | 134 | button.wait_for_high().await; |
| 127 | info!("RELEASED"); | 135 | info!("RELEASED"); |
| 128 | let report = KeyboardReport { | 136 | if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { |
| 129 | keycodes: [0, 0, 0, 0, 0, 0], | 137 | match writer.write(&[0, 0, 0, 0, 0, 0, 0, 0]).await { |
| 130 | leds: 0, | 138 | Ok(()) => {} |
| 131 | modifier: 0, | 139 | Err(e) => warn!("Failed to send boot report: {:?}", e), |
| 132 | reserved: 0, | 140 | }; |
| 133 | }; | 141 | } else { |
| 134 | match writer.write_serialize(&report).await { | 142 | let report = KeyboardReport { |
| 135 | Ok(()) => {} | 143 | keycodes: [0, 0, 0, 0, 0, 0], |
| 136 | Err(e) => warn!("Failed to send report: {:?}", e), | 144 | leds: 0, |
| 137 | }; | 145 | modifier: 0, |
| 146 | reserved: 0, | ||
| 147 | }; | ||
| 148 | match writer.write_serialize(&report).await { | ||
| 149 | Ok(()) => {} | ||
| 150 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 151 | }; | ||
| 152 | } | ||
| 138 | } | 153 | } |
| 139 | }; | 154 | }; |
| 140 | 155 | ||
| @@ -160,6 +175,18 @@ impl RequestHandler for MyRequestHandler { | |||
| 160 | OutResponse::Accepted | 175 | OutResponse::Accepted |
| 161 | } | 176 | } |
| 162 | 177 | ||
| 178 | fn get_protocol(&self) -> HidProtocolMode { | ||
| 179 | let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed)); | ||
| 180 | info!("The current HID protocol mode is: {}", protocol); | ||
| 181 | protocol | ||
| 182 | } | ||
| 183 | |||
| 184 | fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse { | ||
| 185 | info!("Switching to HID protocol mode: {}", protocol); | ||
| 186 | HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed); | ||
| 187 | OutResponse::Accepted | ||
| 188 | } | ||
| 189 | |||
| 163 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { | 190 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { |
| 164 | info!("Set idle rate for {:?} to {:?}", id, dur); | 191 | info!("Set idle rate for {:?} to {:?}", id, dur); |
| 165 | } | 192 | } |
diff --git a/examples/nrf52840/src/bin/usb_hid_mouse.rs b/examples/nrf52840/src/bin/usb_hid_mouse.rs index b3d90354b..6ec8a2d33 100644 --- a/examples/nrf52840/src/bin/usb_hid_mouse.rs +++ b/examples/nrf52840/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; |
| @@ -12,6 +14,7 @@ use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State}; | |||
| 12 | use embassy_usb::control::OutResponse; | 14 | use embassy_usb::control::OutResponse; |
| 13 | use embassy_usb::{Builder, Config}; | 15 | use embassy_usb::{Builder, Config}; |
| 14 | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; | 16 | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; |
| 17 | use usbd_hid::hid_class::HidProtocolMode; | ||
| 15 | use {defmt_rtt as _, panic_probe as _}; | 18 | use {defmt_rtt as _, panic_probe as _}; |
| 16 | 19 | ||
| 17 | bind_interrupts!(struct Irqs { | 20 | bind_interrupts!(struct Irqs { |
| @@ -19,6 +22,8 @@ bind_interrupts!(struct Irqs { | |||
| 19 | CLOCK_POWER => usb::vbus_detect::InterruptHandler; | 22 | CLOCK_POWER => usb::vbus_detect::InterruptHandler; |
| 20 | }); | 23 | }); |
| 21 | 24 | ||
| 25 | static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8); | ||
| 26 | |||
| 22 | #[embassy_executor::main] | 27 | #[embassy_executor::main] |
| 23 | async fn main(_spawner: Spawner) { | 28 | async fn main(_spawner: Spawner) { |
| 24 | let p = embassy_nrf::init(Default::default()); | 29 | let p = embassy_nrf::init(Default::default()); |
| @@ -84,16 +89,26 @@ async fn main(_spawner: Spawner) { | |||
| 84 | Timer::after_millis(500).await; | 89 | Timer::after_millis(500).await; |
| 85 | 90 | ||
| 86 | y = -y; | 91 | y = -y; |
| 87 | let report = MouseReport { | 92 | |
| 88 | buttons: 0, | 93 | if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { |
| 89 | x: 0, | 94 | let buttons = 0u8; |
| 90 | y, | 95 | let x = 0i8; |
| 91 | wheel: 0, | 96 | match writer.write(&[buttons, x as u8, y as u8]).await { |
| 92 | pan: 0, | 97 | Ok(()) => {} |
| 93 | }; | 98 | Err(e) => warn!("Failed to send boot report: {:?}", e), |
| 94 | match writer.write_serialize(&report).await { | 99 | } |
| 95 | Ok(()) => {} | 100 | } else { |
| 96 | Err(e) => warn!("Failed to send report: {:?}", e), | 101 | let report = MouseReport { |
| 102 | buttons: 0, | ||
| 103 | x: 0, | ||
| 104 | y, | ||
| 105 | wheel: 0, | ||
| 106 | pan: 0, | ||
| 107 | }; | ||
| 108 | match writer.write_serialize(&report).await { | ||
| 109 | Ok(()) => {} | ||
| 110 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 111 | } | ||
| 97 | } | 112 | } |
| 98 | } | 113 | } |
| 99 | }; | 114 | }; |
| @@ -116,6 +131,18 @@ impl RequestHandler for MyRequestHandler { | |||
| 116 | OutResponse::Accepted | 131 | OutResponse::Accepted |
| 117 | } | 132 | } |
| 118 | 133 | ||
| 134 | fn get_protocol(&self) -> HidProtocolMode { | ||
| 135 | let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed)); | ||
| 136 | info!("The current HID protocol mode is: {}", protocol); | ||
| 137 | protocol | ||
| 138 | } | ||
| 139 | |||
| 140 | fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse { | ||
| 141 | info!("Switching to HID protocol mode: {}", protocol); | ||
| 142 | HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed); | ||
| 143 | OutResponse::Accepted | ||
| 144 | } | ||
| 145 | |||
| 119 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { | 146 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { |
| 120 | info!("Set idle rate for {:?} to {:?}", id, dur); | 147 | info!("Set idle rate for {:?} to {:?}", id, dur); |
| 121 | } | 148 | } |
