From 58fa5e57b67935d2a81f4fd708d6829afb8112b0 Mon Sep 17 00:00:00 2001 From: Mick Chanthaseth <mchant@users.noreply.github.com> Date: Sun, 11 Feb 2024 16:04:06 -0800 Subject: [PATCH 1/5] added usb_hid_mouse example for rp --- examples/rp/src/bin/usb_hid_mouse.rs | 183 +++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 examples/rp/src/bin/usb_hid_mouse.rs diff --git a/examples/rp/src/bin/usb_hid_mouse.rs b/examples/rp/src/bin/usb_hid_mouse.rs new file mode 100644 index 000000000..ec125a47e --- /dev/null +++ b/examples/rp/src/bin/usb_hid_mouse.rs @@ -0,0 +1,183 @@ +#![no_std] +#![no_main] + +use core::sync::atomic::{AtomicBool, Ordering}; + +use defmt::*; +use embassy_executor::Spawner; +use embassy_futures::join::join; +use embassy_rp::bind_interrupts; +use embassy_rp::clocks::RoscRng; +use embassy_rp::gpio::{Input, Pull}; +use embassy_rp::peripherals::USB; +use embassy_time::Timer; +use embassy_rp::usb::{Driver, InterruptHandler}; +use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; +use embassy_usb::control::OutResponse; +use embassy_usb::{Builder, Config, Handler}; +use rand::{Rng, RngCore}; +use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + USBCTRL_IRQ => InterruptHandler<USB>; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + // Create the driver, from the HAL. + let driver = Driver::new(p.USB, Irqs); + + // Create embassy-usb Config + let mut config = Config::new(0xc0de, 0xcafe); + config.manufacturer = Some("Embassy"); + config.product = Some("HID keyboard example"); + config.serial_number = Some("12345678"); + config.max_power = 100; + config.max_packet_size_0 = 64; + + // Create embassy-usb DeviceBuilder using the driver and config. + // It needs some buffers for building the descriptors. + let mut device_descriptor = [0; 256]; + let mut config_descriptor = [0; 256]; + let mut bos_descriptor = [0; 256]; + // You can also add a Microsoft OS descriptor. + let mut msos_descriptor = [0; 256]; + let mut control_buf = [0; 64]; + let request_handler = MyRequestHandler {}; + let mut device_handler = MyDeviceHandler::new(); + + let mut state = State::new(); + + let mut builder = Builder::new( + driver, + config, + &mut device_descriptor, + &mut config_descriptor, + &mut bos_descriptor, + &mut msos_descriptor, + &mut control_buf, + ); + + builder.handler(&mut device_handler); + + // Create classes on the builder. + let config = embassy_usb::class::hid::Config { + report_descriptor: MouseReport::desc(), + request_handler: Some(&request_handler), + poll_ms: 60, + max_packet_size: 64, + }; + let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); + + // Build the builder. + let mut usb = builder.build(); + + // Run the USB device. + let usb_fut = usb.run(); + + // Set up the signal pin that will be used to trigger the keyboard. + let mut signal_pin = Input::new(p.PIN_16, Pull::None); + + // Enable the schmitt trigger to slightly debounce. + signal_pin.set_schmitt(true); + + let (reader, mut writer) = hid.split(); + + // Do stuff with the class! + let in_fut = async { + let mut rng = RoscRng; + + loop { + // every 1 second + _ = Timer::after_secs(1).await; + let report = MouseReport{ + buttons: 0, + x: rng.gen_range(-100..100), // random small x movement + y: rng.gen_range(-100..100), // random small y movement + wheel: 0, + pan: 0, + }; + match writer.write_serialize(&report).await{ + Ok(())=>{}, + Err(e)=>{ + warn!("Failed to send report: {:?}", e); + }, + } + } + }; + + let out_fut = async { + reader.run(false, &request_handler).await; + }; + + // Run everything concurrently. + // If we had made everything `'static` above instead, we could do this using separate tasks instead. + join(usb_fut, join(in_fut, out_fut)).await; +} + +struct MyRequestHandler {} + +impl RequestHandler for MyRequestHandler { + fn get_report(&self, id: ReportId, _buf: &mut [u8]) -> Option<usize> { + info!("Get report for {:?}", id); + None + } + + fn set_report(&self, id: ReportId, data: &[u8]) -> OutResponse { + info!("Set report for {:?}: {=[u8]}", id, data); + OutResponse::Accepted + } + + fn set_idle_ms(&self, id: Option<ReportId>, dur: u32) { + info!("Set idle rate for {:?} to {:?}", id, dur); + } + + fn get_idle_ms(&self, id: Option<ReportId>) -> Option<u32> { + info!("Get idle rate for {:?}", id); + None + } +} + +struct MyDeviceHandler { + configured: AtomicBool, +} + +impl MyDeviceHandler { + fn new() -> Self { + MyDeviceHandler { + configured: AtomicBool::new(false), + } + } +} + +impl Handler for MyDeviceHandler { + fn enabled(&mut self, enabled: bool) { + self.configured.store(false, Ordering::Relaxed); + if enabled { + info!("Device enabled"); + } else { + info!("Device disabled"); + } + } + + fn reset(&mut self) { + self.configured.store(false, Ordering::Relaxed); + info!("Bus reset, the Vbus current limit is 100mA"); + } + + fn addressed(&mut self, addr: u8) { + self.configured.store(false, Ordering::Relaxed); + info!("USB address set to: {}", addr); + } + + fn configured(&mut self, configured: bool) { + self.configured.store(configured, Ordering::Relaxed); + if configured { + info!("Device configured, it may now draw up to the configured current limit from Vbus.") + } else { + info!("Device is no longer configured, the Vbus current limit is 100mA."); + } + } +} From 0097cbcfe3311ca89f52284a4a1187e19666a330 Mon Sep 17 00:00:00 2001 From: Mick Chanthaseth <mchant@users.noreply.github.com> Date: Fri, 16 Feb 2024 22:22:13 -0800 Subject: [PATCH 2/5] Update imports in usb_hid_mouse.rs --- examples/rp/src/bin/usb_hid_mouse.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/rp/src/bin/usb_hid_mouse.rs b/examples/rp/src/bin/usb_hid_mouse.rs index ec125a47e..a812b22c3 100644 --- a/examples/rp/src/bin/usb_hid_mouse.rs +++ b/examples/rp/src/bin/usb_hid_mouse.rs @@ -15,7 +15,7 @@ use embassy_rp::usb::{Driver, InterruptHandler}; use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; use embassy_usb::control::OutResponse; use embassy_usb::{Builder, Config, Handler}; -use rand::{Rng, RngCore}; +use rand::Rng; use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; use {defmt_rtt as _, panic_probe as _}; From f3b96d8ba0d5143035a03679d94a4ba14f9652ac Mon Sep 17 00:00:00 2001 From: Mick Chanthaseth <mchant@users.noreply.github.com> Date: Mon, 19 Feb 2024 15:14:28 -0800 Subject: [PATCH 3/5] Updated formatting in usb_hid_mouse.rs. --- examples/rp/src/bin/usb_hid_mouse.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/rp/src/bin/usb_hid_mouse.rs b/examples/rp/src/bin/usb_hid_mouse.rs index a812b22c3..d2c63605a 100644 --- a/examples/rp/src/bin/usb_hid_mouse.rs +++ b/examples/rp/src/bin/usb_hid_mouse.rs @@ -10,8 +10,8 @@ use embassy_rp::bind_interrupts; use embassy_rp::clocks::RoscRng; use embassy_rp::gpio::{Input, Pull}; use embassy_rp::peripherals::USB; -use embassy_time::Timer; use embassy_rp::usb::{Driver, InterruptHandler}; +use embassy_time::Timer; use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; use embassy_usb::control::OutResponse; use embassy_usb::{Builder, Config, Handler}; @@ -92,18 +92,18 @@ async fn main(_spawner: Spawner) { loop { // every 1 second _ = Timer::after_secs(1).await; - let report = MouseReport{ + let report = MouseReport { buttons: 0, x: rng.gen_range(-100..100), // random small x movement y: rng.gen_range(-100..100), // random small y movement wheel: 0, pan: 0, }; - match writer.write_serialize(&report).await{ - Ok(())=>{}, - Err(e)=>{ + match writer.write_serialize(&report).await { + Ok(()) => {}, + Err(e) => { warn!("Failed to send report: {:?}", e); - }, + } } } }; From 9c870981e3696c8afb16951c806cc6678073f7ca Mon Sep 17 00:00:00 2001 From: Mick Chanthaseth <mchant@users.noreply.github.com> Date: Mon, 19 Feb 2024 15:28:57 -0800 Subject: [PATCH 4/5] fixed formatting in usb_hid_mouse.rs --- examples/rp/src/bin/usb_hid_mouse.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/examples/rp/src/bin/usb_hid_mouse.rs b/examples/rp/src/bin/usb_hid_mouse.rs index d2c63605a..3a5201b59 100644 --- a/examples/rp/src/bin/usb_hid_mouse.rs +++ b/examples/rp/src/bin/usb_hid_mouse.rs @@ -99,11 +99,10 @@ async fn main(_spawner: Spawner) { wheel: 0, pan: 0, }; + // Send the report. match writer.write_serialize(&report).await { - Ok(()) => {}, - Err(e) => { - warn!("Failed to send report: {:?}", e); - } + Ok(()) => {} + Err(e) => warn!("Failed to send report: {:?}", e), } } }; From bae30fb3973e0c35613422b1ecff299961b0dda4 Mon Sep 17 00:00:00 2001 From: Mick Chanthaseth <mchant@users.noreply.github.com> Date: Mon, 19 Feb 2024 15:41:15 -0800 Subject: [PATCH 5/5] removed extra spaces. --- examples/rp/src/bin/usb_hid_mouse.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/rp/src/bin/usb_hid_mouse.rs b/examples/rp/src/bin/usb_hid_mouse.rs index 3a5201b59..afebd8813 100644 --- a/examples/rp/src/bin/usb_hid_mouse.rs +++ b/examples/rp/src/bin/usb_hid_mouse.rs @@ -88,7 +88,7 @@ async fn main(_spawner: Spawner) { // Do stuff with the class! let in_fut = async { let mut rng = RoscRng; - + loop { // every 1 second _ = Timer::after_secs(1).await;