-
Notifications
You must be signed in to change notification settings - Fork 839
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
rp: Add USB raw example + msos descriptor to examples and usb-logger
- Loading branch information
Showing
8 changed files
with
165 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
//! This example shows how to use USB (Universal Serial Bus) in the RP2040 chip. | ||
//! | ||
//! This creates a USB serial port that echos. | ||
#![no_std] | ||
#![no_main] | ||
#![feature(type_alias_impl_trait)] | ||
|
||
use defmt::info; | ||
use embassy_executor::Spawner; | ||
use embassy_rp::bind_interrupts; | ||
use embassy_rp::peripherals::USB; | ||
use embassy_rp::usb::{Driver, InterruptHandler}; | ||
use embassy_usb::control::{InResponse, OutResponse, Recipient, Request, RequestType}; | ||
use embassy_usb::msos::{self, windows_version}; | ||
use embassy_usb::types::InterfaceNumber; | ||
use embassy_usb::{Builder, Config, Handler}; | ||
use {defmt_rtt as _, panic_probe as _}; | ||
|
||
// This is a randomly generated GUID to allow clients on Windows to find our device | ||
const DEVICE_INTERFACE_GUIDS: &[&str] = &["{AFB9A6FB-30BA-44BC-9232-806CFC875321}"]; | ||
|
||
bind_interrupts!(struct Irqs { | ||
USBCTRL_IRQ => InterruptHandler<USB>; | ||
}); | ||
|
||
#[embassy_executor::main] | ||
async fn main(_spawner: Spawner) { | ||
info!("Hello there!"); | ||
|
||
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("USB raw example"); | ||
config.serial_number = Some("12345678"); | ||
config.max_power = 100; | ||
config.max_packet_size_0 = 64; | ||
|
||
// // Required for windows compatibility. | ||
// // https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/kconfig/CONFIG_CDC_ACM_IAD.html#help | ||
config.device_class = 0xEF; | ||
config.device_sub_class = 0x02; | ||
config.device_protocol = 0x01; | ||
config.composite_with_iads = true; | ||
|
||
// 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]; | ||
let mut msos_descriptor = [0; 256]; | ||
let mut control_buf = [0; 64]; | ||
|
||
let mut handler = ControlHandler { | ||
if_num: InterfaceNumber(0), | ||
}; | ||
|
||
let mut builder = Builder::new( | ||
driver, | ||
config, | ||
&mut device_descriptor, | ||
&mut config_descriptor, | ||
&mut bos_descriptor, | ||
&mut msos_descriptor, | ||
&mut control_buf, | ||
); | ||
|
||
builder.msos_descriptor(windows_version::WIN8_1, 0); | ||
builder.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); | ||
builder.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( | ||
"DeviceInterfaceGUIDs", | ||
msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS), | ||
)); | ||
|
||
// Add a vendor-specific function (class 0xFF), and corresponding interface, | ||
// that uses our custom handler. | ||
let mut function = builder.function(0xFF, 0, 0); | ||
let mut interface = function.interface(); | ||
let _alt = interface.alt_setting(0xFF, 0, 0, None); | ||
handler.if_num = interface.interface_number(); | ||
drop(function); | ||
builder.handler(&mut handler); | ||
|
||
// Build the builder. | ||
let mut usb = builder.build(); | ||
|
||
// Run the USB device. | ||
usb.run().await; | ||
} | ||
|
||
/// Handle CONTROL endpoint requests and responses. For many simple requests and responses | ||
/// you can get away with only using the control endpoint. | ||
struct ControlHandler { | ||
if_num: InterfaceNumber, | ||
} | ||
|
||
impl Handler for ControlHandler { | ||
/// Respond to HostToDevice control messages, where the host sends us a command and | ||
/// optionally some data, and we can only acknowledge or reject it. | ||
fn control_out<'a>(&'a mut self, req: Request, buf: &'a [u8]) -> Option<OutResponse> { | ||
// Log the request before filtering to help with debugging. | ||
info!("Got control_out, request={}, buf={:a}", req, buf); | ||
|
||
// Only handle Vendor request types to an Interface. | ||
if req.request_type != RequestType::Vendor || req.recipient != Recipient::Interface { | ||
return None; | ||
} | ||
|
||
// Ignore requests to other interfaces. | ||
if req.index != self.if_num.0 as u16 { | ||
return None; | ||
} | ||
|
||
// Accept request 100, value 200, reject others. | ||
if req.request == 100 && req.value == 200 { | ||
Some(OutResponse::Accepted) | ||
} else { | ||
Some(OutResponse::Rejected) | ||
} | ||
} | ||
|
||
/// Respond to DeviceToHost control messages, where the host requests some data from us. | ||
fn control_in<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> Option<InResponse<'a>> { | ||
info!("Got control_in, request={}", req); | ||
|
||
// Only handle Vendor request types to an Interface. | ||
if req.request_type != RequestType::Vendor || req.recipient != Recipient::Interface { | ||
return None; | ||
} | ||
|
||
// Ignore requests to other interfaces. | ||
if req.index != self.if_num.0 as u16 { | ||
return None; | ||
} | ||
|
||
// Respond "hello" to request 101, value 201, when asked for 5 bytes, otherwise reject. | ||
if req.request == 101 && req.value == 201 && req.length == 5 { | ||
buf[..5].copy_from_slice(b"hello"); | ||
Some(InResponse::Accepted(&buf[..5])) | ||
} else { | ||
Some(InResponse::Rejected) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters