aboutsummaryrefslogtreecommitdiff
path: root/examples/rp
diff options
context:
space:
mode:
authorkalkyl <[email protected]>2023-11-07 09:05:10 +0100
committerkalkyl <[email protected]>2023-11-07 09:05:10 +0100
commitdb4cd73894f13cf63114c42db6b82f0904070ffb (patch)
tree85ce5839283f7fa4d6326beab2b79c8a6f6af5a9 /examples/rp
parent74f70dc7b4db7ea9e10800384602bed48efe96b2 (diff)
rp: Add USB raw example + msos descriptor to examples and usb-logger
Diffstat (limited to 'examples/rp')
-rw-r--r--examples/rp/Cargo.toml4
-rw-r--r--examples/rp/src/bin/usb_ethernet.rs1
-rw-r--r--examples/rp/src/bin/usb_hid_keyboard.rs4
-rw-r--r--examples/rp/src/bin/usb_midi.rs1
-rw-r--r--examples/rp/src/bin/usb_raw.rs149
-rw-r--r--examples/rp/src/bin/usb_serial.rs1
6 files changed, 156 insertions, 4 deletions
diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml
index fbe7acae1..5ff505e86 100644
--- a/examples/rp/Cargo.toml
+++ b/examples/rp/Cargo.toml
@@ -11,11 +11,11 @@ embassy-sync = { version = "0.4.0", path = "../../embassy-sync", features = ["de
11embassy-executor = { version = "0.3.1", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.3.1", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime"] } 12embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime"] }
13embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver", "critical-section-impl"] } 13embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver", "critical-section-impl"] }
14embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } 14embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt", "msos-descriptor"] }
15embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "udp", "dhcpv4", "medium-ethernet"] } 15embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "udp", "dhcpv4", "medium-ethernet"] }
16embassy-net-wiznet = { version = "0.1.0", path = "../../embassy-net-wiznet", features = ["defmt"] } 16embassy-net-wiznet = { version = "0.1.0", path = "../../embassy-net-wiznet", features = ["defmt"] }
17embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 17embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
18embassy-usb-logger = { version = "0.1.0", path = "../../embassy-usb-logger" } 18embassy-usb-logger = { version = "0.1.0", path = "../../embassy-usb-logger", features = ["msos-descriptor"]}
19embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["time", "defmt"] } 19embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["time", "defmt"] }
20lora-phy = { version = "2" } 20lora-phy = { version = "2" }
21lorawan-device = { version = "0.11.0", default-features = false, features = ["async", "external-lora-phy"] } 21lorawan-device = { version = "0.11.0", default-features = false, features = ["async", "external-lora-phy"] }
diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs
index 6c2f27acf..aea9e6481 100644
--- a/examples/rp/src/bin/usb_ethernet.rs
+++ b/examples/rp/src/bin/usb_ethernet.rs
@@ -71,6 +71,7 @@ async fn main(spawner: Spawner) {
71 &mut make_static!([0; 256])[..], 71 &mut make_static!([0; 256])[..],
72 &mut make_static!([0; 256])[..], 72 &mut make_static!([0; 256])[..],
73 &mut make_static!([0; 256])[..], 73 &mut make_static!([0; 256])[..],
74 &mut make_static!([0; 0])[..],
74 &mut make_static!([0; 128])[..], 75 &mut make_static!([0; 128])[..],
75 ); 76 );
76 77
diff --git a/examples/rp/src/bin/usb_hid_keyboard.rs b/examples/rp/src/bin/usb_hid_keyboard.rs
index cc2090d22..569c9b12b 100644
--- a/examples/rp/src/bin/usb_hid_keyboard.rs
+++ b/examples/rp/src/bin/usb_hid_keyboard.rs
@@ -41,7 +41,7 @@ async fn main(_spawner: Spawner) {
41 let mut config_descriptor = [0; 256]; 41 let mut config_descriptor = [0; 256];
42 let mut bos_descriptor = [0; 256]; 42 let mut bos_descriptor = [0; 256];
43 // You can also add a Microsoft OS descriptor. 43 // You can also add a Microsoft OS descriptor.
44 // let mut msos_descriptor = [0; 256]; 44 let mut msos_descriptor = [0; 256];
45 let mut control_buf = [0; 64]; 45 let mut control_buf = [0; 64];
46 let request_handler = MyRequestHandler {}; 46 let request_handler = MyRequestHandler {};
47 let mut device_handler = MyDeviceHandler::new(); 47 let mut device_handler = MyDeviceHandler::new();
@@ -54,7 +54,7 @@ async fn main(_spawner: Spawner) {
54 &mut device_descriptor, 54 &mut device_descriptor,
55 &mut config_descriptor, 55 &mut config_descriptor,
56 &mut bos_descriptor, 56 &mut bos_descriptor,
57 // &mut msos_descriptor, 57 &mut msos_descriptor,
58 &mut control_buf, 58 &mut control_buf,
59 ); 59 );
60 60
diff --git a/examples/rp/src/bin/usb_midi.rs b/examples/rp/src/bin/usb_midi.rs
index f0b03c81b..3ba34c806 100644
--- a/examples/rp/src/bin/usb_midi.rs
+++ b/examples/rp/src/bin/usb_midi.rs
@@ -58,6 +58,7 @@ async fn main(_spawner: Spawner) {
58 &mut device_descriptor, 58 &mut device_descriptor,
59 &mut config_descriptor, 59 &mut config_descriptor,
60 &mut bos_descriptor, 60 &mut bos_descriptor,
61 &mut [],
61 &mut control_buf, 62 &mut control_buf,
62 ); 63 );
63 64
diff --git a/examples/rp/src/bin/usb_raw.rs b/examples/rp/src/bin/usb_raw.rs
new file mode 100644
index 000000000..e0e5daa54
--- /dev/null
+++ b/examples/rp/src/bin/usb_raw.rs
@@ -0,0 +1,149 @@
1//! This example shows how to use USB (Universal Serial Bus) in the RP2040 chip.
2//!
3//! This creates a USB serial port that echos.
4
5#![no_std]
6#![no_main]
7#![feature(type_alias_impl_trait)]
8
9use defmt::info;
10use embassy_executor::Spawner;
11use embassy_rp::bind_interrupts;
12use embassy_rp::peripherals::USB;
13use embassy_rp::usb::{Driver, InterruptHandler};
14use embassy_usb::control::{InResponse, OutResponse, Recipient, Request, RequestType};
15use embassy_usb::msos::{self, windows_version};
16use embassy_usb::types::InterfaceNumber;
17use embassy_usb::{Builder, Config, Handler};
18use {defmt_rtt as _, panic_probe as _};
19
20// This is a randomly generated GUID to allow clients on Windows to find our device
21const DEVICE_INTERFACE_GUIDS: &[&str] = &["{AFB9A6FB-30BA-44BC-9232-806CFC875321}"];
22
23bind_interrupts!(struct Irqs {
24 USBCTRL_IRQ => InterruptHandler<USB>;
25});
26
27#[embassy_executor::main]
28async fn main(_spawner: Spawner) {
29 info!("Hello there!");
30
31 let p = embassy_rp::init(Default::default());
32
33 // Create the driver, from the HAL.
34 let driver = Driver::new(p.USB, Irqs);
35
36 // Create embassy-usb Config
37 let mut config = Config::new(0xc0de, 0xcafe);
38 config.manufacturer = Some("Embassy");
39 config.product = Some("USB raw example");
40 config.serial_number = Some("12345678");
41 config.max_power = 100;
42 config.max_packet_size_0 = 64;
43
44 // // Required for windows compatibility.
45 // // https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/kconfig/CONFIG_CDC_ACM_IAD.html#help
46 config.device_class = 0xEF;
47 config.device_sub_class = 0x02;
48 config.device_protocol = 0x01;
49 config.composite_with_iads = true;
50
51 // Create embassy-usb DeviceBuilder using the driver and config.
52 // It needs some buffers for building the descriptors.
53 let mut device_descriptor = [0; 256];
54 let mut config_descriptor = [0; 256];
55 let mut bos_descriptor = [0; 256];
56 let mut msos_descriptor = [0; 256];
57 let mut control_buf = [0; 64];
58
59 let mut handler = ControlHandler {
60 if_num: InterfaceNumber(0),
61 };
62
63 let mut builder = Builder::new(
64 driver,
65 config,
66 &mut device_descriptor,
67 &mut config_descriptor,
68 &mut bos_descriptor,
69 &mut msos_descriptor,
70 &mut control_buf,
71 );
72
73 builder.msos_descriptor(windows_version::WIN8_1, 0);
74 builder.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", ""));
75 builder.msos_feature(msos::RegistryPropertyFeatureDescriptor::new(
76 "DeviceInterfaceGUIDs",
77 msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS),
78 ));
79
80 // Add a vendor-specific function (class 0xFF), and corresponding interface,
81 // that uses our custom handler.
82 let mut function = builder.function(0xFF, 0, 0);
83 let mut interface = function.interface();
84 let _alt = interface.alt_setting(0xFF, 0, 0, None);
85 handler.if_num = interface.interface_number();
86 drop(function);
87 builder.handler(&mut handler);
88
89 // Build the builder.
90 let mut usb = builder.build();
91
92 // Run the USB device.
93 usb.run().await;
94}
95
96/// Handle CONTROL endpoint requests and responses. For many simple requests and responses
97/// you can get away with only using the control endpoint.
98struct ControlHandler {
99 if_num: InterfaceNumber,
100}
101
102impl Handler for ControlHandler {
103 /// Respond to HostToDevice control messages, where the host sends us a command and
104 /// optionally some data, and we can only acknowledge or reject it.
105 fn control_out<'a>(&'a mut self, req: Request, buf: &'a [u8]) -> Option<OutResponse> {
106 // Log the request before filtering to help with debugging.
107 info!("Got control_out, request={}, buf={:a}", req, buf);
108
109 // Only handle Vendor request types to an Interface.
110 if req.request_type != RequestType::Vendor || req.recipient != Recipient::Interface {
111 return None;
112 }
113
114 // Ignore requests to other interfaces.
115 if req.index != self.if_num.0 as u16 {
116 return None;
117 }
118
119 // Accept request 100, value 200, reject others.
120 if req.request == 100 && req.value == 200 {
121 Some(OutResponse::Accepted)
122 } else {
123 Some(OutResponse::Rejected)
124 }
125 }
126
127 /// Respond to DeviceToHost control messages, where the host requests some data from us.
128 fn control_in<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> Option<InResponse<'a>> {
129 info!("Got control_in, request={}", req);
130
131 // Only handle Vendor request types to an Interface.
132 if req.request_type != RequestType::Vendor || req.recipient != Recipient::Interface {
133 return None;
134 }
135
136 // Ignore requests to other interfaces.
137 if req.index != self.if_num.0 as u16 {
138 return None;
139 }
140
141 // Respond "hello" to request 101, value 201, when asked for 5 bytes, otherwise reject.
142 if req.request == 101 && req.value == 201 && req.length == 5 {
143 buf[..5].copy_from_slice(b"hello");
144 Some(InResponse::Accepted(&buf[..5]))
145 } else {
146 Some(InResponse::Rejected)
147 }
148 }
149}
diff --git a/examples/rp/src/bin/usb_serial.rs b/examples/rp/src/bin/usb_serial.rs
index 164e2052d..0d0317cda 100644
--- a/examples/rp/src/bin/usb_serial.rs
+++ b/examples/rp/src/bin/usb_serial.rs
@@ -60,6 +60,7 @@ async fn main(_spawner: Spawner) {
60 &mut device_descriptor, 60 &mut device_descriptor,
61 &mut config_descriptor, 61 &mut config_descriptor,
62 &mut bos_descriptor, 62 &mut bos_descriptor,
63 &mut [],
63 &mut control_buf, 64 &mut control_buf,
64 ); 65 );
65 66