aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-09-26 11:32:41 +0000
committerGitHub <[email protected]>2022-09-26 11:32:41 +0000
commit49070c75b6de7581e418f00e37540a34e0bf1dab (patch)
tree2036bafea0ec082a57cd6f741b9414a025da7b61
parentdc376a23909b1def19b64f65d954995330870fe7 (diff)
parentf27a47a37b59bf3b9079f4d4d5f43caf7b7872f8 (diff)
Merge #972
972: Restructure USB crates r=Dirbaio a=Dirbaio - Split driver from `embassy-usb` to a separate crate. This allows making breaking changes to `embassy-usb` without having to bump all the crates with driver impls, such as HALs. - Merge classes into `embassy-usb`. Now that breaking changes to `embassy-usb` aren't that bad, having everything in a single crate is much easier. Co-authored-by: Dario Nieuwenhuis <[email protected]>
-rw-r--r--embassy-nrf/src/usb.rs17
-rw-r--r--embassy-rp/src/usb.rs27
-rw-r--r--embassy-stm32/src/usb/usb.rs35
-rw-r--r--embassy-usb-driver/Cargo.toml (renamed from embassy-usb-ncm/Cargo.toml)13
-rw-r--r--embassy-usb-driver/src/lib.rs (renamed from embassy-usb/src/driver.rs)100
-rw-r--r--embassy-usb-hid/Cargo.toml24
-rw-r--r--embassy-usb-hid/src/fmt.rs225
-rw-r--r--embassy-usb-ncm/src/fmt.rs225
-rw-r--r--embassy-usb-serial/Cargo.toml17
-rw-r--r--embassy-usb-serial/src/fmt.rs225
-rw-r--r--embassy-usb/Cargo.toml13
-rw-r--r--embassy-usb/src/builder.rs11
-rw-r--r--embassy-usb/src/class/cdc_acm.rs (renamed from embassy-usb-serial/src/lib.rs)15
-rw-r--r--embassy-usb/src/class/cdc_ncm.rs (renamed from embassy-usb-ncm/src/lib.rs)13
-rw-r--r--embassy-usb/src/class/hid.rs (renamed from embassy-usb-hid/src/lib.rs)23
-rw-r--r--embassy-usb/src/class/mod.rs3
-rw-r--r--embassy-usb/src/control.rs7
-rw-r--r--embassy-usb/src/descriptor.rs7
-rw-r--r--embassy-usb/src/descriptor_reader.rs2
-rw-r--r--embassy-usb/src/lib.rs19
-rw-r--r--embassy-usb/src/types.rs105
-rw-r--r--examples/nrf/Cargo.toml5
-rw-r--r--examples/nrf/src/bin/usb_ethernet.rs2
-rw-r--r--examples/nrf/src/bin/usb_hid_keyboard.rs4
-rw-r--r--examples/nrf/src/bin/usb_hid_mouse.rs4
-rw-r--r--examples/nrf/src/bin/usb_serial.rs2
-rw-r--r--examples/nrf/src/bin/usb_serial_multitask.rs2
-rw-r--r--examples/rp/Cargo.toml2
-rw-r--r--examples/rp/src/bin/usb_ethernet.rs2
-rw-r--r--examples/rp/src/bin/usb_serial.rs2
-rw-r--r--examples/stm32f1/Cargo.toml1
-rw-r--r--examples/stm32f1/src/bin/usb_serial.rs2
-rw-r--r--examples/stm32f3/Cargo.toml2
-rw-r--r--examples/stm32f3/src/bin/usb_serial.rs2
-rw-r--r--examples/stm32l5/Cargo.toml3
-rw-r--r--examples/stm32l5/src/bin/usb_ethernet.rs2
-rw-r--r--examples/stm32l5/src/bin/usb_hid_mouse.rs4
-rw-r--r--examples/stm32l5/src/bin/usb_serial.rs2
38 files changed, 218 insertions, 951 deletions
diff --git a/embassy-nrf/src/usb.rs b/embassy-nrf/src/usb.rs
index 0685d419c..20510eb49 100644
--- a/embassy-nrf/src/usb.rs
+++ b/embassy-nrf/src/usb.rs
@@ -10,8 +10,9 @@ use cortex_m::peripheral::NVIC;
10use embassy_hal_common::{into_ref, PeripheralRef}; 10use embassy_hal_common::{into_ref, PeripheralRef};
11use embassy_sync::waitqueue::AtomicWaker; 11use embassy_sync::waitqueue::AtomicWaker;
12pub use embassy_usb; 12pub use embassy_usb;
13use embassy_usb::driver::{self, EndpointError, Event, Unsupported}; 13use embassy_usb::driver::{
14use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection}; 14 self, Direction, EndpointAddress, EndpointError, EndpointInfo, EndpointType, Event, Unsupported,
15};
15use pac::usbd::RegisterBlock; 16use pac::usbd::RegisterBlock;
16 17
17use crate::interrupt::{Interrupt, InterruptExt}; 18use crate::interrupt::{Interrupt, InterruptExt};
@@ -243,7 +244,7 @@ impl<'d, T: Instance, P: UsbSupply + 'd> driver::Driver<'d> for Driver<'d, T, P>
243 interval: u8, 244 interval: u8,
244 ) -> Result<Self::EndpointIn, driver::EndpointAllocError> { 245 ) -> Result<Self::EndpointIn, driver::EndpointAllocError> {
245 let index = self.alloc_in.allocate(ep_type)?; 246 let index = self.alloc_in.allocate(ep_type)?;
246 let ep_addr = EndpointAddress::from_parts(index, UsbDirection::In); 247 let ep_addr = EndpointAddress::from_parts(index, Direction::In);
247 Ok(Endpoint::new(EndpointInfo { 248 Ok(Endpoint::new(EndpointInfo {
248 addr: ep_addr, 249 addr: ep_addr,
249 ep_type, 250 ep_type,
@@ -259,7 +260,7 @@ impl<'d, T: Instance, P: UsbSupply + 'd> driver::Driver<'d> for Driver<'d, T, P>
259 interval: u8, 260 interval: u8,
260 ) -> Result<Self::EndpointOut, driver::EndpointAllocError> { 261 ) -> Result<Self::EndpointOut, driver::EndpointAllocError> {
261 let index = self.alloc_out.allocate(ep_type)?; 262 let index = self.alloc_out.allocate(ep_type)?;
262 let ep_addr = EndpointAddress::from_parts(index, UsbDirection::Out); 263 let ep_addr = EndpointAddress::from_parts(index, Direction::Out);
263 Ok(Endpoint::new(EndpointInfo { 264 Ok(Endpoint::new(EndpointInfo {
264 addr: ep_addr, 265 addr: ep_addr,
265 ep_type, 266 ep_type,
@@ -428,8 +429,8 @@ impl<'d, T: Instance, P: UsbSupply> driver::Bus for Bus<'d, T, P> {
428 let regs = T::regs(); 429 let regs = T::regs();
429 let i = ep_addr.index(); 430 let i = ep_addr.index();
430 match ep_addr.direction() { 431 match ep_addr.direction() {
431 UsbDirection::Out => regs.halted.epout[i].read().getstatus().is_halted(), 432 Direction::Out => regs.halted.epout[i].read().getstatus().is_halted(),
432 UsbDirection::In => regs.halted.epin[i].read().getstatus().is_halted(), 433 Direction::In => regs.halted.epin[i].read().getstatus().is_halted(),
433 } 434 }
434 } 435 }
435 436
@@ -442,7 +443,7 @@ impl<'d, T: Instance, P: UsbSupply> driver::Bus for Bus<'d, T, P> {
442 debug!("endpoint_set_enabled {:?} {}", ep_addr, enabled); 443 debug!("endpoint_set_enabled {:?} {}", ep_addr, enabled);
443 444
444 match ep_addr.direction() { 445 match ep_addr.direction() {
445 UsbDirection::In => { 446 Direction::In => {
446 let mut was_enabled = false; 447 let mut was_enabled = false;
447 regs.epinen.modify(|r, w| { 448 regs.epinen.modify(|r, w| {
448 let mut bits = r.bits(); 449 let mut bits = r.bits();
@@ -466,7 +467,7 @@ impl<'d, T: Instance, P: UsbSupply> driver::Bus for Bus<'d, T, P> {
466 467
467 In::waker(i).wake(); 468 In::waker(i).wake();
468 } 469 }
469 UsbDirection::Out => { 470 Direction::Out => {
470 regs.epouten.modify(|r, w| { 471 regs.epouten.modify(|r, w| {
471 let mut bits = r.bits(); 472 let mut bits = r.bits();
472 if enabled { 473 if enabled {
diff --git a/embassy-rp/src/usb.rs b/embassy-rp/src/usb.rs
index a7ec5fb79..ce473b21d 100644
--- a/embassy-rp/src/usb.rs
+++ b/embassy-rp/src/usb.rs
@@ -7,8 +7,9 @@ use core::task::Poll;
7use atomic_polyfill::compiler_fence; 7use atomic_polyfill::compiler_fence;
8use embassy_hal_common::into_ref; 8use embassy_hal_common::into_ref;
9use embassy_sync::waitqueue::AtomicWaker; 9use embassy_sync::waitqueue::AtomicWaker;
10use embassy_usb::driver::{self, EndpointAllocError, EndpointError, Event, Unsupported}; 10use embassy_usb::driver::{
11use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection}; 11 self, Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointInfo, EndpointType, Event, Unsupported,
12};
12 13
13use crate::interrupt::{Interrupt, InterruptExt}; 14use crate::interrupt::{Interrupt, InterruptExt};
14use crate::{pac, peripherals, Peripheral, RegExt}; 15use crate::{pac, peripherals, Peripheral, RegExt};
@@ -204,8 +205,8 @@ impl<'d, T: Instance> Driver<'d, T> {
204 ); 205 );
205 206
206 let alloc = match D::dir() { 207 let alloc = match D::dir() {
207 UsbDirection::Out => &mut self.ep_out, 208 Direction::Out => &mut self.ep_out,
208 UsbDirection::In => &mut self.ep_in, 209 Direction::In => &mut self.ep_in,
209 }; 210 };
210 211
211 let index = alloc.iter_mut().enumerate().find(|(i, ep)| { 212 let index = alloc.iter_mut().enumerate().find(|(i, ep)| {
@@ -254,7 +255,7 @@ impl<'d, T: Instance> Driver<'d, T> {
254 }; 255 };
255 256
256 match D::dir() { 257 match D::dir() {
257 UsbDirection::Out => unsafe { 258 Direction::Out => unsafe {
258 T::dpram().ep_out_control(index - 1).write(|w| { 259 T::dpram().ep_out_control(index - 1).write(|w| {
259 w.set_enable(false); 260 w.set_enable(false);
260 w.set_buffer_address(addr); 261 w.set_buffer_address(addr);
@@ -262,7 +263,7 @@ impl<'d, T: Instance> Driver<'d, T> {
262 w.set_endpoint_type(ep_type_reg); 263 w.set_endpoint_type(ep_type_reg);
263 }) 264 })
264 }, 265 },
265 UsbDirection::In => unsafe { 266 Direction::In => unsafe {
266 T::dpram().ep_in_control(index - 1).write(|w| { 267 T::dpram().ep_in_control(index - 1).write(|w| {
267 w.set_enable(false); 268 w.set_enable(false);
268 w.set_buffer_address(addr); 269 w.set_buffer_address(addr);
@@ -429,14 +430,14 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> {
429 430
430 let n = ep_addr.index(); 431 let n = ep_addr.index();
431 match ep_addr.direction() { 432 match ep_addr.direction() {
432 UsbDirection::In => unsafe { 433 Direction::In => unsafe {
433 T::dpram().ep_in_control(n - 1).modify(|w| w.set_enable(enabled)); 434 T::dpram().ep_in_control(n - 1).modify(|w| w.set_enable(enabled));
434 T::dpram().ep_in_buffer_control(ep_addr.index()).write(|w| { 435 T::dpram().ep_in_buffer_control(ep_addr.index()).write(|w| {
435 w.set_pid(0, true); // first packet is DATA0, but PID is flipped before 436 w.set_pid(0, true); // first packet is DATA0, but PID is flipped before
436 }); 437 });
437 EP_IN_WAKERS[n].wake(); 438 EP_IN_WAKERS[n].wake();
438 }, 439 },
439 UsbDirection::Out => unsafe { 440 Direction::Out => unsafe {
440 T::dpram().ep_out_control(n - 1).modify(|w| w.set_enable(enabled)); 441 T::dpram().ep_out_control(n - 1).modify(|w| w.set_enable(enabled));
441 442
442 T::dpram().ep_out_buffer_control(ep_addr.index()).write(|w| { 443 T::dpram().ep_out_buffer_control(ep_addr.index()).write(|w| {
@@ -474,14 +475,14 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> {
474} 475}
475 476
476trait Dir { 477trait Dir {
477 fn dir() -> UsbDirection; 478 fn dir() -> Direction;
478 fn waker(i: usize) -> &'static AtomicWaker; 479 fn waker(i: usize) -> &'static AtomicWaker;
479} 480}
480 481
481pub enum In {} 482pub enum In {}
482impl Dir for In { 483impl Dir for In {
483 fn dir() -> UsbDirection { 484 fn dir() -> Direction {
484 UsbDirection::In 485 Direction::In
485 } 486 }
486 487
487 #[inline] 488 #[inline]
@@ -492,8 +493,8 @@ impl Dir for In {
492 493
493pub enum Out {} 494pub enum Out {}
494impl Dir for Out { 495impl Dir for Out {
495 fn dir() -> UsbDirection { 496 fn dir() -> Direction {
496 UsbDirection::Out 497 Direction::Out
497 } 498 }
498 499
499 #[inline] 500 #[inline]
diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs
index e5ee1181c..39809a3e1 100644
--- a/embassy-stm32/src/usb/usb.rs
+++ b/embassy-stm32/src/usb/usb.rs
@@ -9,8 +9,9 @@ use atomic_polyfill::{AtomicBool, AtomicU8};
9use embassy_hal_common::into_ref; 9use embassy_hal_common::into_ref;
10use embassy_sync::waitqueue::AtomicWaker; 10use embassy_sync::waitqueue::AtomicWaker;
11use embassy_time::{block_for, Duration}; 11use embassy_time::{block_for, Duration};
12use embassy_usb::driver::{self, EndpointAllocError, EndpointError, Event, Unsupported}; 12use embassy_usb::driver::{
13use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection}; 13 self, Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointInfo, EndpointType, Event, Unsupported,
14};
14use pac::common::{Reg, RW}; 15use pac::common::{Reg, RW};
15use pac::usb::vals::{EpType, Stat}; 16use pac::usb::vals::{EpType, Stat};
16 17
@@ -279,8 +280,8 @@ impl<'d, T: Instance> Driver<'d, T> {
279 } 280 }
280 let used = ep.used_out || ep.used_in; 281 let used = ep.used_out || ep.used_in;
281 let used_dir = match D::dir() { 282 let used_dir = match D::dir() {
282 UsbDirection::Out => ep.used_out, 283 Direction::Out => ep.used_out,
283 UsbDirection::In => ep.used_in, 284 Direction::In => ep.used_in,
284 }; 285 };
285 !used || (ep.ep_type == ep_type && !used_dir) 286 !used || (ep.ep_type == ep_type && !used_dir)
286 }); 287 });
@@ -293,7 +294,7 @@ impl<'d, T: Instance> Driver<'d, T> {
293 ep.ep_type = ep_type; 294 ep.ep_type = ep_type;
294 295
295 let buf = match D::dir() { 296 let buf = match D::dir() {
296 UsbDirection::Out => { 297 Direction::Out => {
297 assert!(!ep.used_out); 298 assert!(!ep.used_out);
298 ep.used_out = true; 299 ep.used_out = true;
299 300
@@ -312,7 +313,7 @@ impl<'d, T: Instance> Driver<'d, T> {
312 _phantom: PhantomData, 313 _phantom: PhantomData,
313 } 314 }
314 } 315 }
315 UsbDirection::In => { 316 Direction::In => {
316 assert!(!ep.used_in); 317 assert!(!ep.used_in);
317 ep.used_in = true; 318 ep.used_in = true;
318 319
@@ -504,7 +505,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> {
504 // This can race, so do a retry loop. 505 // This can race, so do a retry loop.
505 let reg = T::regs().epr(ep_addr.index() as _); 506 let reg = T::regs().epr(ep_addr.index() as _);
506 match ep_addr.direction() { 507 match ep_addr.direction() {
507 UsbDirection::In => { 508 Direction::In => {
508 loop { 509 loop {
509 let r = unsafe { reg.read() }; 510 let r = unsafe { reg.read() };
510 match r.stat_tx() { 511 match r.stat_tx() {
@@ -523,7 +524,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> {
523 } 524 }
524 EP_IN_WAKERS[ep_addr.index()].wake(); 525 EP_IN_WAKERS[ep_addr.index()].wake();
525 } 526 }
526 UsbDirection::Out => { 527 Direction::Out => {
527 loop { 528 loop {
528 let r = unsafe { reg.read() }; 529 let r = unsafe { reg.read() };
529 match r.stat_rx() { 530 match r.stat_rx() {
@@ -549,8 +550,8 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> {
549 let regs = T::regs(); 550 let regs = T::regs();
550 let epr = unsafe { regs.epr(ep_addr.index() as _).read() }; 551 let epr = unsafe { regs.epr(ep_addr.index() as _).read() };
551 match ep_addr.direction() { 552 match ep_addr.direction() {
552 UsbDirection::In => epr.stat_tx() == Stat::STALL, 553 Direction::In => epr.stat_tx() == Stat::STALL,
553 UsbDirection::Out => epr.stat_rx() == Stat::STALL, 554 Direction::Out => epr.stat_rx() == Stat::STALL,
554 } 555 }
555 } 556 }
556 557
@@ -560,7 +561,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> {
560 let reg = T::regs().epr(ep_addr.index() as _); 561 let reg = T::regs().epr(ep_addr.index() as _);
561 trace!("EPR before: {:04x}", unsafe { reg.read() }.0); 562 trace!("EPR before: {:04x}", unsafe { reg.read() }.0);
562 match ep_addr.direction() { 563 match ep_addr.direction() {
563 UsbDirection::In => { 564 Direction::In => {
564 loop { 565 loop {
565 let want_stat = match enabled { 566 let want_stat = match enabled {
566 false => Stat::DISABLED, 567 false => Stat::DISABLED,
@@ -576,7 +577,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> {
576 } 577 }
577 EP_IN_WAKERS[ep_addr.index()].wake(); 578 EP_IN_WAKERS[ep_addr.index()].wake();
578 } 579 }
579 UsbDirection::Out => { 580 Direction::Out => {
580 loop { 581 loop {
581 let want_stat = match enabled { 582 let want_stat = match enabled {
582 false => Stat::DISABLED, 583 false => Stat::DISABLED,
@@ -616,14 +617,14 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> {
616} 617}
617 618
618trait Dir { 619trait Dir {
619 fn dir() -> UsbDirection; 620 fn dir() -> Direction;
620 fn waker(i: usize) -> &'static AtomicWaker; 621 fn waker(i: usize) -> &'static AtomicWaker;
621} 622}
622 623
623pub enum In {} 624pub enum In {}
624impl Dir for In { 625impl Dir for In {
625 fn dir() -> UsbDirection { 626 fn dir() -> Direction {
626 UsbDirection::In 627 Direction::In
627 } 628 }
628 629
629 #[inline] 630 #[inline]
@@ -634,8 +635,8 @@ impl Dir for In {
634 635
635pub enum Out {} 636pub enum Out {}
636impl Dir for Out { 637impl Dir for Out {
637 fn dir() -> UsbDirection { 638 fn dir() -> Direction {
638 UsbDirection::Out 639 Direction::Out
639 } 640 }
640 641
641 #[inline] 642 #[inline]
diff --git a/embassy-usb-ncm/Cargo.toml b/embassy-usb-driver/Cargo.toml
index 15d3db96f..b525df337 100644
--- a/embassy-usb-ncm/Cargo.toml
+++ b/embassy-usb-driver/Cargo.toml
@@ -1,17 +1,16 @@
1[package] 1[package]
2name = "embassy-usb-ncm" 2name = "embassy-usb-driver"
3version = "0.1.0" 3version = "0.1.0"
4edition = "2021" 4edition = "2021"
5 5
6# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7
6[package.metadata.embassy_docs] 8[package.metadata.embassy_docs]
7src_base = "https://github.com/embassy-rs/embassy/blob/embassy-usb-ncm-v$VERSION/embassy-usb-ncm/src/" 9src_base = "https://github.com/embassy-rs/embassy/blob/embassy-usb-driver-v$VERSION/embassy-usb/src/"
8src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-usb-ncm/src/" 10src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-usb-driver/src/"
9features = ["defmt"] 11features = ["defmt"]
10target = "thumbv7em-none-eabi" 12target = "thumbv7em-none-eabi"
11 13
12[dependencies] 14[dependencies]
13embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
14embassy-usb = { version = "0.1.0", path = "../embassy-usb" }
15
16defmt = { version = "0.3", optional = true } 15defmt = { version = "0.3", optional = true }
17log = { version = "0.4.14", optional = true } 16log = { version = "0.4.14", optional = true } \ No newline at end of file
diff --git a/embassy-usb/src/driver.rs b/embassy-usb-driver/src/lib.rs
index 7888f1639..fc29786fc 100644
--- a/embassy-usb/src/driver.rs
+++ b/embassy-usb-driver/src/lib.rs
@@ -1,6 +1,104 @@
1#![no_std]
2
1use core::future::Future; 3use core::future::Future;
2 4
3use super::types::*; 5/// Direction of USB traffic. Note that in the USB standard the direction is always indicated from
6/// the perspective of the host, which is backward for devices, but the standard directions are used
7/// for consistency.
8///
9/// The values of the enum also match the direction bit used in endpoint addresses and control
10/// request types.
11#[derive(Copy, Clone, Eq, PartialEq, Debug)]
12#[cfg_attr(feature = "defmt", derive(defmt::Format))]
13pub enum Direction {
14 /// Host to device (OUT)
15 Out,
16 /// Device to host (IN)
17 In,
18}
19
20/// USB endpoint transfer type. The values of this enum can be directly cast into `u8` to get the
21/// transfer bmAttributes transfer type bits.
22#[repr(u8)]
23#[derive(Copy, Clone, Eq, PartialEq, Debug)]
24#[cfg_attr(feature = "defmt", derive(defmt::Format))]
25pub enum EndpointType {
26 /// Control endpoint. Used for device management. Only the host can initiate requests. Usually
27 /// used only endpoint 0.
28 Control = 0b00,
29 /// Isochronous endpoint. Used for time-critical unreliable data. Not implemented yet.
30 Isochronous = 0b01,
31 /// Bulk endpoint. Used for large amounts of best-effort reliable data.
32 Bulk = 0b10,
33 /// Interrupt endpoint. Used for small amounts of time-critical reliable data.
34 Interrupt = 0b11,
35}
36
37/// Type-safe endpoint address.
38#[derive(Debug, Clone, Copy, Eq, PartialEq)]
39#[cfg_attr(feature = "defmt", derive(defmt::Format))]
40pub struct EndpointAddress(u8);
41
42impl From<u8> for EndpointAddress {
43 #[inline]
44 fn from(addr: u8) -> EndpointAddress {
45 EndpointAddress(addr)
46 }
47}
48
49impl From<EndpointAddress> for u8 {
50 #[inline]
51 fn from(addr: EndpointAddress) -> u8 {
52 addr.0
53 }
54}
55
56impl EndpointAddress {
57 const INBITS: u8 = Direction::In as u8;
58
59 /// Constructs a new EndpointAddress with the given index and direction.
60 #[inline]
61 pub fn from_parts(index: usize, dir: Direction) -> Self {
62 EndpointAddress(index as u8 | dir as u8)
63 }
64
65 /// Gets the direction part of the address.
66 #[inline]
67 pub fn direction(&self) -> Direction {
68 if (self.0 & Self::INBITS) != 0 {
69 Direction::In
70 } else {
71 Direction::Out
72 }
73 }
74
75 /// Returns true if the direction is IN, otherwise false.
76 #[inline]
77 pub fn is_in(&self) -> bool {
78 (self.0 & Self::INBITS) != 0
79 }
80
81 /// Returns true if the direction is OUT, otherwise false.
82 #[inline]
83 pub fn is_out(&self) -> bool {
84 (self.0 & Self::INBITS) == 0
85 }
86
87 /// Gets the index part of the endpoint address.
88 #[inline]
89 pub fn index(&self) -> usize {
90 (self.0 & !Self::INBITS) as usize
91 }
92}
93
94#[derive(Copy, Clone, Eq, PartialEq, Debug)]
95#[cfg_attr(feature = "defmt", derive(defmt::Format))]
96pub struct EndpointInfo {
97 pub addr: EndpointAddress,
98 pub ep_type: EndpointType,
99 pub max_packet_size: u16,
100 pub interval: u8,
101}
4 102
5/// Driver for a specific USB peripheral. Implement this to add support for a new hardware 103/// Driver for a specific USB peripheral. Implement this to add support for a new hardware
6/// platform. 104/// platform.
diff --git a/embassy-usb-hid/Cargo.toml b/embassy-usb-hid/Cargo.toml
deleted file mode 100644
index 2f7733dc6..000000000
--- a/embassy-usb-hid/Cargo.toml
+++ /dev/null
@@ -1,24 +0,0 @@
1[package]
2name = "embassy-usb-hid"
3version = "0.1.0"
4edition = "2021"
5
6[package.metadata.embassy_docs]
7src_base = "https://github.com/embassy-rs/embassy/blob/embassy-usb-hid-v$VERSION/embassy-usb-hid/src/"
8src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-usb-hid/src/"
9features = ["defmt"]
10target = "thumbv7em-none-eabi"
11
12[features]
13default = ["usbd-hid"]
14usbd-hid = ["dep:usbd-hid", "ssmarshal"]
15
16[dependencies]
17embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
18embassy-usb = { version = "0.1.0", path = "../embassy-usb" }
19
20defmt = { version = "0.3", optional = true }
21log = { version = "0.4.14", optional = true }
22usbd-hid = { version = "0.6.0", optional = true }
23ssmarshal = { version = "1.0", default-features = false, optional = true }
24futures-util = { version = "0.3.21", default-features = false }
diff --git a/embassy-usb-hid/src/fmt.rs b/embassy-usb-hid/src/fmt.rs
deleted file mode 100644
index 066970813..000000000
--- a/embassy-usb-hid/src/fmt.rs
+++ /dev/null
@@ -1,225 +0,0 @@
1#![macro_use]
2#![allow(unused_macros)]
3
4#[cfg(all(feature = "defmt", feature = "log"))]
5compile_error!("You may not enable both `defmt` and `log` features.");
6
7macro_rules! assert {
8 ($($x:tt)*) => {
9 {
10 #[cfg(not(feature = "defmt"))]
11 ::core::assert!($($x)*);
12 #[cfg(feature = "defmt")]
13 ::defmt::assert!($($x)*);
14 }
15 };
16}
17
18macro_rules! assert_eq {
19 ($($x:tt)*) => {
20 {
21 #[cfg(not(feature = "defmt"))]
22 ::core::assert_eq!($($x)*);
23 #[cfg(feature = "defmt")]
24 ::defmt::assert_eq!($($x)*);
25 }
26 };
27}
28
29macro_rules! assert_ne {
30 ($($x:tt)*) => {
31 {
32 #[cfg(not(feature = "defmt"))]
33 ::core::assert_ne!($($x)*);
34 #[cfg(feature = "defmt")]
35 ::defmt::assert_ne!($($x)*);
36 }
37 };
38}
39
40macro_rules! debug_assert {
41 ($($x:tt)*) => {
42 {
43 #[cfg(not(feature = "defmt"))]
44 ::core::debug_assert!($($x)*);
45 #[cfg(feature = "defmt")]
46 ::defmt::debug_assert!($($x)*);
47 }
48 };
49}
50
51macro_rules! debug_assert_eq {
52 ($($x:tt)*) => {
53 {
54 #[cfg(not(feature = "defmt"))]
55 ::core::debug_assert_eq!($($x)*);
56 #[cfg(feature = "defmt")]
57 ::defmt::debug_assert_eq!($($x)*);
58 }
59 };
60}
61
62macro_rules! debug_assert_ne {
63 ($($x:tt)*) => {
64 {
65 #[cfg(not(feature = "defmt"))]
66 ::core::debug_assert_ne!($($x)*);
67 #[cfg(feature = "defmt")]
68 ::defmt::debug_assert_ne!($($x)*);
69 }
70 };
71}
72
73macro_rules! todo {
74 ($($x:tt)*) => {
75 {
76 #[cfg(not(feature = "defmt"))]
77 ::core::todo!($($x)*);
78 #[cfg(feature = "defmt")]
79 ::defmt::todo!($($x)*);
80 }
81 };
82}
83
84macro_rules! unreachable {
85 ($($x:tt)*) => {
86 {
87 #[cfg(not(feature = "defmt"))]
88 ::core::unreachable!($($x)*);
89 #[cfg(feature = "defmt")]
90 ::defmt::unreachable!($($x)*);
91 }
92 };
93}
94
95macro_rules! panic {
96 ($($x:tt)*) => {
97 {
98 #[cfg(not(feature = "defmt"))]
99 ::core::panic!($($x)*);
100 #[cfg(feature = "defmt")]
101 ::defmt::panic!($($x)*);
102 }
103 };
104}
105
106macro_rules! trace {
107 ($s:literal $(, $x:expr)* $(,)?) => {
108 {
109 #[cfg(feature = "log")]
110 ::log::trace!($s $(, $x)*);
111 #[cfg(feature = "defmt")]
112 ::defmt::trace!($s $(, $x)*);
113 #[cfg(not(any(feature = "log", feature="defmt")))]
114 let _ = ($( & $x ),*);
115 }
116 };
117}
118
119macro_rules! debug {
120 ($s:literal $(, $x:expr)* $(,)?) => {
121 {
122 #[cfg(feature = "log")]
123 ::log::debug!($s $(, $x)*);
124 #[cfg(feature = "defmt")]
125 ::defmt::debug!($s $(, $x)*);
126 #[cfg(not(any(feature = "log", feature="defmt")))]
127 let _ = ($( & $x ),*);
128 }
129 };
130}
131
132macro_rules! info {
133 ($s:literal $(, $x:expr)* $(,)?) => {
134 {
135 #[cfg(feature = "log")]
136 ::log::info!($s $(, $x)*);
137 #[cfg(feature = "defmt")]
138 ::defmt::info!($s $(, $x)*);
139 #[cfg(not(any(feature = "log", feature="defmt")))]
140 let _ = ($( & $x ),*);
141 }
142 };
143}
144
145macro_rules! warn {
146 ($s:literal $(, $x:expr)* $(,)?) => {
147 {
148 #[cfg(feature = "log")]
149 ::log::warn!($s $(, $x)*);
150 #[cfg(feature = "defmt")]
151 ::defmt::warn!($s $(, $x)*);
152 #[cfg(not(any(feature = "log", feature="defmt")))]
153 let _ = ($( & $x ),*);
154 }
155 };
156}
157
158macro_rules! error {
159 ($s:literal $(, $x:expr)* $(,)?) => {
160 {
161 #[cfg(feature = "log")]
162 ::log::error!($s $(, $x)*);
163 #[cfg(feature = "defmt")]
164 ::defmt::error!($s $(, $x)*);
165 #[cfg(not(any(feature = "log", feature="defmt")))]
166 let _ = ($( & $x ),*);
167 }
168 };
169}
170
171#[cfg(feature = "defmt")]
172macro_rules! unwrap {
173 ($($x:tt)*) => {
174 ::defmt::unwrap!($($x)*)
175 };
176}
177
178#[cfg(not(feature = "defmt"))]
179macro_rules! unwrap {
180 ($arg:expr) => {
181 match $crate::fmt::Try::into_result($arg) {
182 ::core::result::Result::Ok(t) => t,
183 ::core::result::Result::Err(e) => {
184 ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e);
185 }
186 }
187 };
188 ($arg:expr, $($msg:expr),+ $(,)? ) => {
189 match $crate::fmt::Try::into_result($arg) {
190 ::core::result::Result::Ok(t) => t,
191 ::core::result::Result::Err(e) => {
192 ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e);
193 }
194 }
195 }
196}
197
198#[derive(Debug, Copy, Clone, Eq, PartialEq)]
199pub struct NoneError;
200
201pub trait Try {
202 type Ok;
203 type Error;
204 fn into_result(self) -> Result<Self::Ok, Self::Error>;
205}
206
207impl<T> Try for Option<T> {
208 type Ok = T;
209 type Error = NoneError;
210
211 #[inline]
212 fn into_result(self) -> Result<T, NoneError> {
213 self.ok_or(NoneError)
214 }
215}
216
217impl<T, E> Try for Result<T, E> {
218 type Ok = T;
219 type Error = E;
220
221 #[inline]
222 fn into_result(self) -> Self {
223 self
224 }
225}
diff --git a/embassy-usb-ncm/src/fmt.rs b/embassy-usb-ncm/src/fmt.rs
deleted file mode 100644
index 066970813..000000000
--- a/embassy-usb-ncm/src/fmt.rs
+++ /dev/null
@@ -1,225 +0,0 @@
1#![macro_use]
2#![allow(unused_macros)]
3
4#[cfg(all(feature = "defmt", feature = "log"))]
5compile_error!("You may not enable both `defmt` and `log` features.");
6
7macro_rules! assert {
8 ($($x:tt)*) => {
9 {
10 #[cfg(not(feature = "defmt"))]
11 ::core::assert!($($x)*);
12 #[cfg(feature = "defmt")]
13 ::defmt::assert!($($x)*);
14 }
15 };
16}
17
18macro_rules! assert_eq {
19 ($($x:tt)*) => {
20 {
21 #[cfg(not(feature = "defmt"))]
22 ::core::assert_eq!($($x)*);
23 #[cfg(feature = "defmt")]
24 ::defmt::assert_eq!($($x)*);
25 }
26 };
27}
28
29macro_rules! assert_ne {
30 ($($x:tt)*) => {
31 {
32 #[cfg(not(feature = "defmt"))]
33 ::core::assert_ne!($($x)*);
34 #[cfg(feature = "defmt")]
35 ::defmt::assert_ne!($($x)*);
36 }
37 };
38}
39
40macro_rules! debug_assert {
41 ($($x:tt)*) => {
42 {
43 #[cfg(not(feature = "defmt"))]
44 ::core::debug_assert!($($x)*);
45 #[cfg(feature = "defmt")]
46 ::defmt::debug_assert!($($x)*);
47 }
48 };
49}
50
51macro_rules! debug_assert_eq {
52 ($($x:tt)*) => {
53 {
54 #[cfg(not(feature = "defmt"))]
55 ::core::debug_assert_eq!($($x)*);
56 #[cfg(feature = "defmt")]
57 ::defmt::debug_assert_eq!($($x)*);
58 }
59 };
60}
61
62macro_rules! debug_assert_ne {
63 ($($x:tt)*) => {
64 {
65 #[cfg(not(feature = "defmt"))]
66 ::core::debug_assert_ne!($($x)*);
67 #[cfg(feature = "defmt")]
68 ::defmt::debug_assert_ne!($($x)*);
69 }
70 };
71}
72
73macro_rules! todo {
74 ($($x:tt)*) => {
75 {
76 #[cfg(not(feature = "defmt"))]
77 ::core::todo!($($x)*);
78 #[cfg(feature = "defmt")]
79 ::defmt::todo!($($x)*);
80 }
81 };
82}
83
84macro_rules! unreachable {
85 ($($x:tt)*) => {
86 {
87 #[cfg(not(feature = "defmt"))]
88 ::core::unreachable!($($x)*);
89 #[cfg(feature = "defmt")]
90 ::defmt::unreachable!($($x)*);
91 }
92 };
93}
94
95macro_rules! panic {
96 ($($x:tt)*) => {
97 {
98 #[cfg(not(feature = "defmt"))]
99 ::core::panic!($($x)*);
100 #[cfg(feature = "defmt")]
101 ::defmt::panic!($($x)*);
102 }
103 };
104}
105
106macro_rules! trace {
107 ($s:literal $(, $x:expr)* $(,)?) => {
108 {
109 #[cfg(feature = "log")]
110 ::log::trace!($s $(, $x)*);
111 #[cfg(feature = "defmt")]
112 ::defmt::trace!($s $(, $x)*);
113 #[cfg(not(any(feature = "log", feature="defmt")))]
114 let _ = ($( & $x ),*);
115 }
116 };
117}
118
119macro_rules! debug {
120 ($s:literal $(, $x:expr)* $(,)?) => {
121 {
122 #[cfg(feature = "log")]
123 ::log::debug!($s $(, $x)*);
124 #[cfg(feature = "defmt")]
125 ::defmt::debug!($s $(, $x)*);
126 #[cfg(not(any(feature = "log", feature="defmt")))]
127 let _ = ($( & $x ),*);
128 }
129 };
130}
131
132macro_rules! info {
133 ($s:literal $(, $x:expr)* $(,)?) => {
134 {
135 #[cfg(feature = "log")]
136 ::log::info!($s $(, $x)*);
137 #[cfg(feature = "defmt")]
138 ::defmt::info!($s $(, $x)*);
139 #[cfg(not(any(feature = "log", feature="defmt")))]
140 let _ = ($( & $x ),*);
141 }
142 };
143}
144
145macro_rules! warn {
146 ($s:literal $(, $x:expr)* $(,)?) => {
147 {
148 #[cfg(feature = "log")]
149 ::log::warn!($s $(, $x)*);
150 #[cfg(feature = "defmt")]
151 ::defmt::warn!($s $(, $x)*);
152 #[cfg(not(any(feature = "log", feature="defmt")))]
153 let _ = ($( & $x ),*);
154 }
155 };
156}
157
158macro_rules! error {
159 ($s:literal $(, $x:expr)* $(,)?) => {
160 {
161 #[cfg(feature = "log")]
162 ::log::error!($s $(, $x)*);
163 #[cfg(feature = "defmt")]
164 ::defmt::error!($s $(, $x)*);
165 #[cfg(not(any(feature = "log", feature="defmt")))]
166 let _ = ($( & $x ),*);
167 }
168 };
169}
170
171#[cfg(feature = "defmt")]
172macro_rules! unwrap {
173 ($($x:tt)*) => {
174 ::defmt::unwrap!($($x)*)
175 };
176}
177
178#[cfg(not(feature = "defmt"))]
179macro_rules! unwrap {
180 ($arg:expr) => {
181 match $crate::fmt::Try::into_result($arg) {
182 ::core::result::Result::Ok(t) => t,
183 ::core::result::Result::Err(e) => {
184 ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e);
185 }
186 }
187 };
188 ($arg:expr, $($msg:expr),+ $(,)? ) => {
189 match $crate::fmt::Try::into_result($arg) {
190 ::core::result::Result::Ok(t) => t,
191 ::core::result::Result::Err(e) => {
192 ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e);
193 }
194 }
195 }
196}
197
198#[derive(Debug, Copy, Clone, Eq, PartialEq)]
199pub struct NoneError;
200
201pub trait Try {
202 type Ok;
203 type Error;
204 fn into_result(self) -> Result<Self::Ok, Self::Error>;
205}
206
207impl<T> Try for Option<T> {
208 type Ok = T;
209 type Error = NoneError;
210
211 #[inline]
212 fn into_result(self) -> Result<T, NoneError> {
213 self.ok_or(NoneError)
214 }
215}
216
217impl<T, E> Try for Result<T, E> {
218 type Ok = T;
219 type Error = E;
220
221 #[inline]
222 fn into_result(self) -> Self {
223 self
224 }
225}
diff --git a/embassy-usb-serial/Cargo.toml b/embassy-usb-serial/Cargo.toml
deleted file mode 100644
index 9788588e9..000000000
--- a/embassy-usb-serial/Cargo.toml
+++ /dev/null
@@ -1,17 +0,0 @@
1[package]
2name = "embassy-usb-serial"
3version = "0.1.0"
4edition = "2021"
5
6[package.metadata.embassy_docs]
7src_base = "https://github.com/embassy-rs/embassy/blob/embassy-usb-serial-v$VERSION/embassy-usb-serial/src/"
8src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-usb-serial/src/"
9features = ["defmt"]
10target = "thumbv7em-none-eabi"
11
12[dependencies]
13embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
14embassy-usb = { version = "0.1.0", path = "../embassy-usb" }
15
16defmt = { version = "0.3", optional = true }
17log = { version = "0.4.14", optional = true }
diff --git a/embassy-usb-serial/src/fmt.rs b/embassy-usb-serial/src/fmt.rs
deleted file mode 100644
index 066970813..000000000
--- a/embassy-usb-serial/src/fmt.rs
+++ /dev/null
@@ -1,225 +0,0 @@
1#![macro_use]
2#![allow(unused_macros)]
3
4#[cfg(all(feature = "defmt", feature = "log"))]
5compile_error!("You may not enable both `defmt` and `log` features.");
6
7macro_rules! assert {
8 ($($x:tt)*) => {
9 {
10 #[cfg(not(feature = "defmt"))]
11 ::core::assert!($($x)*);
12 #[cfg(feature = "defmt")]
13 ::defmt::assert!($($x)*);
14 }
15 };
16}
17
18macro_rules! assert_eq {
19 ($($x:tt)*) => {
20 {
21 #[cfg(not(feature = "defmt"))]
22 ::core::assert_eq!($($x)*);
23 #[cfg(feature = "defmt")]
24 ::defmt::assert_eq!($($x)*);
25 }
26 };
27}
28
29macro_rules! assert_ne {
30 ($($x:tt)*) => {
31 {
32 #[cfg(not(feature = "defmt"))]
33 ::core::assert_ne!($($x)*);
34 #[cfg(feature = "defmt")]
35 ::defmt::assert_ne!($($x)*);
36 }
37 };
38}
39
40macro_rules! debug_assert {
41 ($($x:tt)*) => {
42 {
43 #[cfg(not(feature = "defmt"))]
44 ::core::debug_assert!($($x)*);
45 #[cfg(feature = "defmt")]
46 ::defmt::debug_assert!($($x)*);
47 }
48 };
49}
50
51macro_rules! debug_assert_eq {
52 ($($x:tt)*) => {
53 {
54 #[cfg(not(feature = "defmt"))]
55 ::core::debug_assert_eq!($($x)*);
56 #[cfg(feature = "defmt")]
57 ::defmt::debug_assert_eq!($($x)*);
58 }
59 };
60}
61
62macro_rules! debug_assert_ne {
63 ($($x:tt)*) => {
64 {
65 #[cfg(not(feature = "defmt"))]
66 ::core::debug_assert_ne!($($x)*);
67 #[cfg(feature = "defmt")]
68 ::defmt::debug_assert_ne!($($x)*);
69 }
70 };
71}
72
73macro_rules! todo {
74 ($($x:tt)*) => {
75 {
76 #[cfg(not(feature = "defmt"))]
77 ::core::todo!($($x)*);
78 #[cfg(feature = "defmt")]
79 ::defmt::todo!($($x)*);
80 }
81 };
82}
83
84macro_rules! unreachable {
85 ($($x:tt)*) => {
86 {
87 #[cfg(not(feature = "defmt"))]
88 ::core::unreachable!($($x)*);
89 #[cfg(feature = "defmt")]
90 ::defmt::unreachable!($($x)*);
91 }
92 };
93}
94
95macro_rules! panic {
96 ($($x:tt)*) => {
97 {
98 #[cfg(not(feature = "defmt"))]
99 ::core::panic!($($x)*);
100 #[cfg(feature = "defmt")]
101 ::defmt::panic!($($x)*);
102 }
103 };
104}
105
106macro_rules! trace {
107 ($s:literal $(, $x:expr)* $(,)?) => {
108 {
109 #[cfg(feature = "log")]
110 ::log::trace!($s $(, $x)*);
111 #[cfg(feature = "defmt")]
112 ::defmt::trace!($s $(, $x)*);
113 #[cfg(not(any(feature = "log", feature="defmt")))]
114 let _ = ($( & $x ),*);
115 }
116 };
117}
118
119macro_rules! debug {
120 ($s:literal $(, $x:expr)* $(,)?) => {
121 {
122 #[cfg(feature = "log")]
123 ::log::debug!($s $(, $x)*);
124 #[cfg(feature = "defmt")]
125 ::defmt::debug!($s $(, $x)*);
126 #[cfg(not(any(feature = "log", feature="defmt")))]
127 let _ = ($( & $x ),*);
128 }
129 };
130}
131
132macro_rules! info {
133 ($s:literal $(, $x:expr)* $(,)?) => {
134 {
135 #[cfg(feature = "log")]
136 ::log::info!($s $(, $x)*);
137 #[cfg(feature = "defmt")]
138 ::defmt::info!($s $(, $x)*);
139 #[cfg(not(any(feature = "log", feature="defmt")))]
140 let _ = ($( & $x ),*);
141 }
142 };
143}
144
145macro_rules! warn {
146 ($s:literal $(, $x:expr)* $(,)?) => {
147 {
148 #[cfg(feature = "log")]
149 ::log::warn!($s $(, $x)*);
150 #[cfg(feature = "defmt")]
151 ::defmt::warn!($s $(, $x)*);
152 #[cfg(not(any(feature = "log", feature="defmt")))]
153 let _ = ($( & $x ),*);
154 }
155 };
156}
157
158macro_rules! error {
159 ($s:literal $(, $x:expr)* $(,)?) => {
160 {
161 #[cfg(feature = "log")]
162 ::log::error!($s $(, $x)*);
163 #[cfg(feature = "defmt")]
164 ::defmt::error!($s $(, $x)*);
165 #[cfg(not(any(feature = "log", feature="defmt")))]
166 let _ = ($( & $x ),*);
167 }
168 };
169}
170
171#[cfg(feature = "defmt")]
172macro_rules! unwrap {
173 ($($x:tt)*) => {
174 ::defmt::unwrap!($($x)*)
175 };
176}
177
178#[cfg(not(feature = "defmt"))]
179macro_rules! unwrap {
180 ($arg:expr) => {
181 match $crate::fmt::Try::into_result($arg) {
182 ::core::result::Result::Ok(t) => t,
183 ::core::result::Result::Err(e) => {
184 ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e);
185 }
186 }
187 };
188 ($arg:expr, $($msg:expr),+ $(,)? ) => {
189 match $crate::fmt::Try::into_result($arg) {
190 ::core::result::Result::Ok(t) => t,
191 ::core::result::Result::Err(e) => {
192 ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e);
193 }
194 }
195 }
196}
197
198#[derive(Debug, Copy, Clone, Eq, PartialEq)]
199pub struct NoneError;
200
201pub trait Try {
202 type Ok;
203 type Error;
204 fn into_result(self) -> Result<Self::Ok, Self::Error>;
205}
206
207impl<T> Try for Option<T> {
208 type Ok = T;
209 type Error = NoneError;
210
211 #[inline]
212 fn into_result(self) -> Result<T, NoneError> {
213 self.ok_or(NoneError)
214 }
215}
216
217impl<T, E> Try for Result<T, E> {
218 type Ok = T;
219 type Error = E;
220
221 #[inline]
222 fn into_result(self) -> Self {
223 self
224 }
225}
diff --git a/embassy-usb/Cargo.toml b/embassy-usb/Cargo.toml
index 8cad4d314..aad54dbaf 100644
--- a/embassy-usb/Cargo.toml
+++ b/embassy-usb/Cargo.toml
@@ -9,9 +9,20 @@ src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-usb/s
9features = ["defmt"] 9features = ["defmt"]
10target = "thumbv7em-none-eabi" 10target = "thumbv7em-none-eabi"
11 11
12[features]
13defmt = ["dep:defmt", "embassy-usb-driver/defmt"]
14usbd-hid = ["dep:usbd-hid", "dep:ssmarshal"]
15default = ["usbd-hid"]
16
12[dependencies] 17[dependencies]
13embassy-futures = { version = "0.1.0", path = "../embassy-futures" } 18embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
19embassy-usb-driver = { version = "0.1.0", path = "../embassy-usb-driver" }
20embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
14 21
15defmt = { version = "0.3", optional = true } 22defmt = { version = "0.3", optional = true }
16log = { version = "0.4.14", optional = true } 23log = { version = "0.4.14", optional = true }
17heapless = "0.7.10" \ No newline at end of file 24heapless = "0.7.10"
25
26# for HID
27usbd-hid = { version = "0.6.0", optional = true }
28ssmarshal = { version = "1.0", default-features = false, optional = true }
diff --git a/embassy-usb/src/builder.rs b/embassy-usb/src/builder.rs
index 6be88bc76..87a8333bb 100644
--- a/embassy-usb/src/builder.rs
+++ b/embassy-usb/src/builder.rs
@@ -1,11 +1,10 @@
1use heapless::Vec; 1use heapless::Vec;
2 2
3use super::control::ControlHandler; 3use crate::control::ControlHandler;
4use super::descriptor::{BosWriter, DescriptorWriter}; 4use crate::descriptor::{BosWriter, DescriptorWriter};
5use super::driver::{Driver, Endpoint}; 5use crate::driver::{Driver, Endpoint, EndpointType};
6use super::types::*; 6use crate::types::*;
7use super::{DeviceStateHandler, UsbDevice, MAX_INTERFACE_COUNT}; 7use crate::{DeviceStateHandler, Interface, UsbDevice, MAX_INTERFACE_COUNT, STRING_INDEX_CUSTOM_START};
8use crate::{Interface, STRING_INDEX_CUSTOM_START};
9 8
10#[derive(Debug, Copy, Clone)] 9#[derive(Debug, Copy, Clone)]
11#[cfg_attr(feature = "defmt", derive(defmt::Format))] 10#[cfg_attr(feature = "defmt", derive(defmt::Format))]
diff --git a/embassy-usb-serial/src/lib.rs b/embassy-usb/src/class/cdc_acm.rs
index 15c2bb0a7..09bb1cc8d 100644
--- a/embassy-usb-serial/src/lib.rs
+++ b/embassy-usb/src/class/cdc_acm.rs
@@ -1,18 +1,13 @@
1#![no_std]
2#![feature(type_alias_impl_trait)]
3
4// This mod MUST go first, so that the others see its macros.
5pub(crate) mod fmt;
6
7use core::cell::Cell; 1use core::cell::Cell;
8use core::mem::{self, MaybeUninit}; 2use core::mem::{self, MaybeUninit};
9use core::sync::atomic::{AtomicBool, Ordering}; 3use core::sync::atomic::{AtomicBool, Ordering};
10 4
11use embassy_sync::blocking_mutex::CriticalSectionMutex; 5use embassy_sync::blocking_mutex::CriticalSectionMutex;
12use embassy_usb::control::{self, ControlHandler, InResponse, OutResponse, Request}; 6
13use embassy_usb::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; 7use crate::control::{self, ControlHandler, InResponse, OutResponse, Request};
14use embassy_usb::types::*; 8use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut};
15use embassy_usb::Builder; 9use crate::types::*;
10use crate::Builder;
16 11
17/// This should be used as `device_class` when building the `UsbDevice`. 12/// This should be used as `device_class` when building the `UsbDevice`.
18pub const USB_CLASS_CDC: u8 = 0x02; 13pub const USB_CLASS_CDC: u8 = 0x02;
diff --git a/embassy-usb-ncm/src/lib.rs b/embassy-usb/src/class/cdc_ncm.rs
index e796af28f..a39b87e9b 100644
--- a/embassy-usb-ncm/src/lib.rs
+++ b/embassy-usb/src/class/cdc_ncm.rs
@@ -1,15 +1,10 @@
1#![no_std]
2
3// This mod MUST go first, so that the others see its macros.
4pub(crate) mod fmt;
5
6use core::intrinsics::copy_nonoverlapping; 1use core::intrinsics::copy_nonoverlapping;
7use core::mem::{size_of, MaybeUninit}; 2use core::mem::{size_of, MaybeUninit};
8 3
9use embassy_usb::control::{self, ControlHandler, InResponse, OutResponse, Request}; 4use crate::control::{self, ControlHandler, InResponse, OutResponse, Request};
10use embassy_usb::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; 5use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut};
11use embassy_usb::types::*; 6use crate::types::*;
12use embassy_usb::Builder; 7use crate::Builder;
13 8
14/// This should be used as `device_class` when building the `UsbDevice`. 9/// This should be used as `device_class` when building the `UsbDevice`.
15pub const USB_CLASS_CDC: u8 = 0x02; 10pub const USB_CLASS_CDC: u8 = 0x02;
diff --git a/embassy-usb-hid/src/lib.rs b/embassy-usb/src/class/hid.rs
index 8b181aec8..4d1fa995f 100644
--- a/embassy-usb-hid/src/lib.rs
+++ b/embassy-usb/src/class/hid.rs
@@ -1,23 +1,16 @@
1#![no_std]
2#![feature(type_alias_impl_trait)]
3
4//! Implements HID functionality for a usb-device device.
5
6// This mod MUST go first, so that the others see its macros.
7pub(crate) mod fmt;
8
9use core::mem::MaybeUninit; 1use core::mem::MaybeUninit;
10use core::ops::Range; 2use core::ops::Range;
11use core::sync::atomic::{AtomicUsize, Ordering}; 3use core::sync::atomic::{AtomicUsize, Ordering};
12 4
13use embassy_usb::control::{ControlHandler, InResponse, OutResponse, Request, RequestType};
14use embassy_usb::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut};
15use embassy_usb::Builder;
16#[cfg(feature = "usbd-hid")] 5#[cfg(feature = "usbd-hid")]
17use ssmarshal::serialize; 6use ssmarshal::serialize;
18#[cfg(feature = "usbd-hid")] 7#[cfg(feature = "usbd-hid")]
19use usbd_hid::descriptor::AsInputReport; 8use usbd_hid::descriptor::AsInputReport;
20 9
10use crate::control::{ControlHandler, InResponse, OutResponse, Request, RequestType};
11use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut};
12use crate::Builder;
13
21const USB_CLASS_HID: u8 = 0x03; 14const USB_CLASS_HID: u8 = 0x03;
22const USB_SUBCLASS_NONE: u8 = 0x00; 15const USB_SUBCLASS_NONE: u8 = 0x00;
23const USB_PROTOCOL_NONE: u8 = 0x00; 16const USB_PROTOCOL_NONE: u8 = 0x00;
@@ -204,9 +197,9 @@ pub enum ReadError {
204 Sync(Range<usize>), 197 Sync(Range<usize>),
205} 198}
206 199
207impl From<embassy_usb::driver::EndpointError> for ReadError { 200impl From<EndpointError> for ReadError {
208 fn from(val: embassy_usb::driver::EndpointError) -> Self { 201 fn from(val: EndpointError) -> Self {
209 use embassy_usb::driver::EndpointError::*; 202 use EndpointError::*;
210 match val { 203 match val {
211 BufferOverflow => ReadError::BufferOverflow, 204 BufferOverflow => ReadError::BufferOverflow,
212 Disabled => ReadError::Disabled, 205 Disabled => ReadError::Disabled,
@@ -437,7 +430,7 @@ impl<'d> ControlHandler for Control<'d> {
437 } 430 }
438 } 431 }
439 432
440 fn control_out(&mut self, req: embassy_usb::control::Request, data: &[u8]) -> OutResponse { 433 fn control_out(&mut self, req: Request, data: &[u8]) -> OutResponse {
441 trace!("HID control_out {:?} {=[u8]:x}", req, data); 434 trace!("HID control_out {:?} {=[u8]:x}", req, data);
442 if let RequestType::Class = req.request_type { 435 if let RequestType::Class = req.request_type {
443 match req.request { 436 match req.request {
diff --git a/embassy-usb/src/class/mod.rs b/embassy-usb/src/class/mod.rs
new file mode 100644
index 000000000..af27577a6
--- /dev/null
+++ b/embassy-usb/src/class/mod.rs
@@ -0,0 +1,3 @@
1pub mod cdc_acm;
2pub mod cdc_ncm;
3pub mod hid;
diff --git a/embassy-usb/src/control.rs b/embassy-usb/src/control.rs
index 3e5749a01..d6d0c6565 100644
--- a/embassy-usb/src/control.rs
+++ b/embassy-usb/src/control.rs
@@ -1,7 +1,8 @@
1//! USB control data types. 1//! USB control data types.
2use core::mem; 2use core::mem;
3 3
4use super::types::*; 4use crate::driver::Direction;
5use crate::types::StringIndex;
5 6
6/// Control request type. 7/// Control request type.
7#[repr(u8)] 8#[repr(u8)]
@@ -42,7 +43,7 @@ pub enum Recipient {
42#[cfg_attr(feature = "defmt", derive(defmt::Format))] 43#[cfg_attr(feature = "defmt", derive(defmt::Format))]
43pub struct Request { 44pub struct Request {
44 /// Direction of the request. 45 /// Direction of the request.
45 pub direction: UsbDirection, 46 pub direction: Direction,
46 /// Type of the request. 47 /// Type of the request.
47 pub request_type: RequestType, 48 pub request_type: RequestType,
48 /// Recipient of the request. 49 /// Recipient of the request.
@@ -105,7 +106,7 @@ impl Request {
105 let recipient = rt & 0b11111; 106 let recipient = rt & 0b11111;
106 107
107 Request { 108 Request {
108 direction: rt.into(), 109 direction: if rt & 0x80 == 0 { Direction::Out } else { Direction::In },
109 request_type: unsafe { mem::transmute((rt >> 5) & 0b11) }, 110 request_type: unsafe { mem::transmute((rt >> 5) & 0b11) },
110 recipient: if recipient <= 3 { 111 recipient: if recipient <= 3 {
111 unsafe { mem::transmute(recipient) } 112 unsafe { mem::transmute(recipient) }
diff --git a/embassy-usb/src/descriptor.rs b/embassy-usb/src/descriptor.rs
index b94a4b161..497f03196 100644
--- a/embassy-usb/src/descriptor.rs
+++ b/embassy-usb/src/descriptor.rs
@@ -1,6 +1,7 @@
1use super::builder::Config; 1use crate::builder::Config;
2use super::types::*; 2use crate::driver::EndpointInfo;
3use super::CONFIGURATION_VALUE; 3use crate::types::*;
4use crate::CONFIGURATION_VALUE;
4 5
5/// Standard descriptor types 6/// Standard descriptor types
6#[allow(missing_docs)] 7#[allow(missing_docs)]
diff --git a/embassy-usb/src/descriptor_reader.rs b/embassy-usb/src/descriptor_reader.rs
index 0a12b566c..d64bcb73b 100644
--- a/embassy-usb/src/descriptor_reader.rs
+++ b/embassy-usb/src/descriptor_reader.rs
@@ -1,5 +1,5 @@
1use crate::descriptor::descriptor_type; 1use crate::descriptor::descriptor_type;
2use crate::types::EndpointAddress; 2use crate::driver::EndpointAddress;
3 3
4#[derive(Copy, Clone, PartialEq, Eq, Debug)] 4#[derive(Copy, Clone, PartialEq, Eq, Debug)]
5#[cfg_attr(feature = "defmt", derive(defmt::Format))] 5#[cfg_attr(feature = "defmt", derive(defmt::Format))]
diff --git a/embassy-usb/src/lib.rs b/embassy-usb/src/lib.rs
index 6f58c953c..661b84119 100644
--- a/embassy-usb/src/lib.rs
+++ b/embassy-usb/src/lib.rs
@@ -4,23 +4,24 @@
4// This mod MUST go first, so that the others see its macros. 4// This mod MUST go first, so that the others see its macros.
5pub(crate) mod fmt; 5pub(crate) mod fmt;
6 6
7pub use embassy_usb_driver as driver;
8
7mod builder; 9mod builder;
10pub mod class;
8pub mod control; 11pub mod control;
9pub mod descriptor; 12pub mod descriptor;
10mod descriptor_reader; 13mod descriptor_reader;
11pub mod driver;
12pub mod types; 14pub mod types;
13 15
14use embassy_futures::select::{select, Either}; 16use embassy_futures::select::{select, Either};
15use heapless::Vec; 17use heapless::Vec;
16 18
17pub use self::builder::{Builder, Config}; 19pub use crate::builder::{Builder, Config};
18use self::control::*; 20use crate::control::*;
19use self::descriptor::*; 21use crate::descriptor::*;
20use self::driver::{Bus, Driver, Event};
21use self::types::*;
22use crate::descriptor_reader::foreach_endpoint; 22use crate::descriptor_reader::foreach_endpoint;
23use crate::driver::ControlPipe; 23use crate::driver::{Bus, ControlPipe, Direction, Driver, EndpointAddress, Event};
24use crate::types::*;
24 25
25/// The global state of the USB device. 26/// The global state of the USB device.
26/// 27///
@@ -250,8 +251,8 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
250 trace!("control request: {:?}", req); 251 trace!("control request: {:?}", req);
251 252
252 match req.direction { 253 match req.direction {
253 UsbDirection::In => self.handle_control_in(req).await, 254 Direction::In => self.handle_control_in(req).await,
254 UsbDirection::Out => self.handle_control_out(req).await, 255 Direction::Out => self.handle_control_out(req).await,
255 } 256 }
256 257
257 if self.inner.set_address_pending { 258 if self.inner.set_address_pending {
diff --git a/embassy-usb/src/types.rs b/embassy-usb/src/types.rs
index b8717ffa9..aeab063d1 100644
--- a/embassy-usb/src/types.rs
+++ b/embassy-usb/src/types.rs
@@ -1,108 +1,3 @@
1/// Direction of USB traffic. Note that in the USB standard the direction is always indicated from
2/// the perspective of the host, which is backward for devices, but the standard directions are used
3/// for consistency.
4///
5/// The values of the enum also match the direction bit used in endpoint addresses and control
6/// request types.
7#[repr(u8)]
8#[derive(Copy, Clone, Eq, PartialEq, Debug)]
9#[cfg_attr(feature = "defmt", derive(defmt::Format))]
10pub enum UsbDirection {
11 /// Host to device (OUT)
12 Out = 0x00,
13 /// Device to host (IN)
14 In = 0x80,
15}
16
17impl From<u8> for UsbDirection {
18 fn from(value: u8) -> Self {
19 unsafe { core::mem::transmute(value & 0x80) }
20 }
21}
22
23/// USB endpoint transfer type. The values of this enum can be directly cast into `u8` to get the
24/// transfer bmAttributes transfer type bits.
25#[repr(u8)]
26#[derive(Copy, Clone, Eq, PartialEq, Debug)]
27#[cfg_attr(feature = "defmt", derive(defmt::Format))]
28pub enum EndpointType {
29 /// Control endpoint. Used for device management. Only the host can initiate requests. Usually
30 /// used only endpoint 0.
31 Control = 0b00,
32 /// Isochronous endpoint. Used for time-critical unreliable data. Not implemented yet.
33 Isochronous = 0b01,
34 /// Bulk endpoint. Used for large amounts of best-effort reliable data.
35 Bulk = 0b10,
36 /// Interrupt endpoint. Used for small amounts of time-critical reliable data.
37 Interrupt = 0b11,
38}
39
40/// Type-safe endpoint address.
41#[derive(Debug, Clone, Copy, Eq, PartialEq)]
42#[cfg_attr(feature = "defmt", derive(defmt::Format))]
43pub struct EndpointAddress(u8);
44
45impl From<u8> for EndpointAddress {
46 #[inline]
47 fn from(addr: u8) -> EndpointAddress {
48 EndpointAddress(addr)
49 }
50}
51
52impl From<EndpointAddress> for u8 {
53 #[inline]
54 fn from(addr: EndpointAddress) -> u8 {
55 addr.0
56 }
57}
58
59impl EndpointAddress {
60 const INBITS: u8 = UsbDirection::In as u8;
61
62 /// Constructs a new EndpointAddress with the given index and direction.
63 #[inline]
64 pub fn from_parts(index: usize, dir: UsbDirection) -> Self {
65 EndpointAddress(index as u8 | dir as u8)
66 }
67
68 /// Gets the direction part of the address.
69 #[inline]
70 pub fn direction(&self) -> UsbDirection {
71 if (self.0 & Self::INBITS) != 0 {
72 UsbDirection::In
73 } else {
74 UsbDirection::Out
75 }
76 }
77
78 /// Returns true if the direction is IN, otherwise false.
79 #[inline]
80 pub fn is_in(&self) -> bool {
81 (self.0 & Self::INBITS) != 0
82 }
83
84 /// Returns true if the direction is OUT, otherwise false.
85 #[inline]
86 pub fn is_out(&self) -> bool {
87 (self.0 & Self::INBITS) == 0
88 }
89
90 /// Gets the index part of the endpoint address.
91 #[inline]
92 pub fn index(&self) -> usize {
93 (self.0 & !Self::INBITS) as usize
94 }
95}
96
97#[derive(Copy, Clone, Eq, PartialEq, Debug)]
98#[cfg_attr(feature = "defmt", derive(defmt::Format))]
99pub struct EndpointInfo {
100 pub addr: EndpointAddress,
101 pub ep_type: EndpointType,
102 pub max_packet_size: u16,
103 pub interval: u8,
104}
105
106/// A handle for a USB interface that contains its number. 1/// A handle for a USB interface that contains its number.
107#[derive(Copy, Clone, Eq, PartialEq)] 2#[derive(Copy, Clone, Eq, PartialEq)]
108#[cfg_attr(feature = "defmt", derive(defmt::Format))] 3#[cfg_attr(feature = "defmt", derive(defmt::Format))]
diff --git a/examples/nrf/Cargo.toml b/examples/nrf/Cargo.toml
index dbc659cda..a5d340c69 100644
--- a/examples/nrf/Cargo.toml
+++ b/examples/nrf/Cargo.toml
@@ -5,7 +5,7 @@ version = "0.1.0"
5 5
6[features] 6[features]
7default = ["nightly"] 7default = ["nightly"]
8nightly = ["embassy-executor/nightly", "embassy-nrf/nightly", "embassy-net/nightly", "embassy-nrf/unstable-traits", "embassy-usb", "embassy-usb-serial", "embassy-usb-hid", "embassy-usb-ncm", "embedded-io/async", "embassy-net"] 8nightly = ["embassy-executor/nightly", "embassy-nrf/nightly", "embassy-net/nightly", "embassy-nrf/unstable-traits", "embassy-usb", "embedded-io/async", "embassy-net"]
9 9
10[dependencies] 10[dependencies]
11embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 11embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
@@ -15,9 +15,6 @@ embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["de
15embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } 15embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] }
16embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "pool-16"], optional = true } 16embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "pool-16"], optional = true }
17embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"], optional = true } 17embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"], optional = true }
18embassy-usb-serial = { version = "0.1.0", path = "../../embassy-usb-serial", features = ["defmt"], optional = true }
19embassy-usb-hid = { version = "0.1.0", path = "../../embassy-usb-hid", features = ["defmt"], optional = true }
20embassy-usb-ncm = { version = "0.1.0", path = "../../embassy-usb-ncm", features = ["defmt"], optional = true }
21embedded-io = "0.3.0" 18embedded-io = "0.3.0"
22 19
23defmt = "0.3" 20defmt = "0.3"
diff --git a/examples/nrf/src/bin/usb_ethernet.rs b/examples/nrf/src/bin/usb_ethernet.rs
index 33ca380ff..de93a2b45 100644
--- a/examples/nrf/src/bin/usb_ethernet.rs
+++ b/examples/nrf/src/bin/usb_ethernet.rs
@@ -15,8 +15,8 @@ use embassy_nrf::usb::{Driver, PowerUsb};
15use embassy_nrf::{interrupt, pac, peripherals}; 15use embassy_nrf::{interrupt, pac, peripherals};
16use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; 16use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
17use embassy_sync::channel::Channel; 17use embassy_sync::channel::Channel;
18use embassy_usb::class::cdc_ncm::{CdcNcmClass, Receiver, Sender, State};
18use embassy_usb::{Builder, Config, UsbDevice}; 19use embassy_usb::{Builder, Config, UsbDevice};
19use embassy_usb_ncm::{CdcNcmClass, Receiver, Sender, State};
20use embedded_io::asynch::Write; 20use embedded_io::asynch::Write;
21use static_cell::StaticCell; 21use static_cell::StaticCell;
22use {defmt_rtt as _, panic_probe as _}; 22use {defmt_rtt as _, panic_probe as _};
diff --git a/examples/nrf/src/bin/usb_hid_keyboard.rs b/examples/nrf/src/bin/usb_hid_keyboard.rs
index 4eb7d37c9..76e198719 100644
--- a/examples/nrf/src/bin/usb_hid_keyboard.rs
+++ b/examples/nrf/src/bin/usb_hid_keyboard.rs
@@ -14,9 +14,9 @@ use embassy_nrf::usb::{Driver, PowerUsb};
14use embassy_nrf::{interrupt, pac}; 14use embassy_nrf::{interrupt, pac};
15use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 15use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
16use embassy_sync::signal::Signal; 16use embassy_sync::signal::Signal;
17use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State};
17use embassy_usb::control::OutResponse; 18use embassy_usb::control::OutResponse;
18use embassy_usb::{Builder, Config, DeviceStateHandler}; 19use embassy_usb::{Builder, Config, DeviceStateHandler};
19use embassy_usb_hid::{HidReaderWriter, ReportId, RequestHandler, State};
20use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; 20use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor};
21use {defmt_rtt as _, panic_probe as _}; 21use {defmt_rtt as _, panic_probe as _};
22 22
@@ -67,7 +67,7 @@ async fn main(_spawner: Spawner) {
67 ); 67 );
68 68
69 // Create classes on the builder. 69 // Create classes on the builder.
70 let config = embassy_usb_hid::Config { 70 let config = embassy_usb::class::hid::Config {
71 report_descriptor: KeyboardReport::desc(), 71 report_descriptor: KeyboardReport::desc(),
72 request_handler: Some(&request_handler), 72 request_handler: Some(&request_handler),
73 poll_ms: 60, 73 poll_ms: 60,
diff --git a/examples/nrf/src/bin/usb_hid_mouse.rs b/examples/nrf/src/bin/usb_hid_mouse.rs
index 65fbda1cf..4916a38d4 100644
--- a/examples/nrf/src/bin/usb_hid_mouse.rs
+++ b/examples/nrf/src/bin/usb_hid_mouse.rs
@@ -10,9 +10,9 @@ use embassy_futures::join::join;
10use embassy_nrf::usb::{Driver, PowerUsb}; 10use embassy_nrf::usb::{Driver, PowerUsb};
11use embassy_nrf::{interrupt, pac}; 11use embassy_nrf::{interrupt, pac};
12use embassy_time::{Duration, Timer}; 12use embassy_time::{Duration, Timer};
13use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State};
13use embassy_usb::control::OutResponse; 14use embassy_usb::control::OutResponse;
14use embassy_usb::{Builder, Config}; 15use embassy_usb::{Builder, Config};
15use embassy_usb_hid::{HidWriter, ReportId, RequestHandler, State};
16use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; 16use usbd_hid::descriptor::{MouseReport, SerializedDescriptor};
17use {defmt_rtt as _, panic_probe as _}; 17use {defmt_rtt as _, panic_probe as _};
18 18
@@ -59,7 +59,7 @@ async fn main(_spawner: Spawner) {
59 ); 59 );
60 60
61 // Create classes on the builder. 61 // Create classes on the builder.
62 let config = embassy_usb_hid::Config { 62 let config = embassy_usb::class::hid::Config {
63 report_descriptor: MouseReport::desc(), 63 report_descriptor: MouseReport::desc(),
64 request_handler: Some(&request_handler), 64 request_handler: Some(&request_handler),
65 poll_ms: 60, 65 poll_ms: 60,
diff --git a/examples/nrf/src/bin/usb_serial.rs b/examples/nrf/src/bin/usb_serial.rs
index a740b4e0a..7c9c4184b 100644
--- a/examples/nrf/src/bin/usb_serial.rs
+++ b/examples/nrf/src/bin/usb_serial.rs
@@ -9,9 +9,9 @@ use embassy_executor::Spawner;
9use embassy_futures::join::join; 9use embassy_futures::join::join;
10use embassy_nrf::usb::{Driver, Instance, PowerUsb, UsbSupply}; 10use embassy_nrf::usb::{Driver, Instance, PowerUsb, UsbSupply};
11use embassy_nrf::{interrupt, pac}; 11use embassy_nrf::{interrupt, pac};
12use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
12use embassy_usb::driver::EndpointError; 13use embassy_usb::driver::EndpointError;
13use embassy_usb::{Builder, Config}; 14use embassy_usb::{Builder, Config};
14use embassy_usb_serial::{CdcAcmClass, State};
15use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
16 16
17#[embassy_executor::main] 17#[embassy_executor::main]
diff --git a/examples/nrf/src/bin/usb_serial_multitask.rs b/examples/nrf/src/bin/usb_serial_multitask.rs
index c646c0bbd..93efc2fe6 100644
--- a/examples/nrf/src/bin/usb_serial_multitask.rs
+++ b/examples/nrf/src/bin/usb_serial_multitask.rs
@@ -8,9 +8,9 @@ use defmt::{info, panic, unwrap};
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_nrf::usb::{Driver, PowerUsb}; 9use embassy_nrf::usb::{Driver, PowerUsb};
10use embassy_nrf::{interrupt, pac, peripherals}; 10use embassy_nrf::{interrupt, pac, peripherals};
11use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
11use embassy_usb::driver::EndpointError; 12use embassy_usb::driver::EndpointError;
12use embassy_usb::{Builder, Config, UsbDevice}; 13use embassy_usb::{Builder, Config, UsbDevice};
13use embassy_usb_serial::{CdcAcmClass, State};
14use static_cell::StaticCell; 14use static_cell::StaticCell;
15use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
16 16
diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml
index 24c3cdd67..3c8f923e7 100644
--- a/examples/rp/Cargo.toml
+++ b/examples/rp/Cargo.toml
@@ -10,9 +10,7 @@ embassy-executor = { version = "0.1.0", path = "../../embassy-executor", feature
10embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 10embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
11embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver"] } 11embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver"] }
12embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } 12embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
13embassy-usb-serial = { version = "0.1.0", path = "../../embassy-usb-serial", features = ["defmt"] }
14embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "pool-16"] } 13embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "pool-16"] }
15embassy-usb-ncm = { version = "0.1.0", path = "../../embassy-usb-ncm", features = ["defmt"] }
16embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 14embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
17 15
18defmt = "0.3" 16defmt = "0.3"
diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs
index 166ffe175..1057fe7fd 100644
--- a/examples/rp/src/bin/usb_ethernet.rs
+++ b/examples/rp/src/bin/usb_ethernet.rs
@@ -13,8 +13,8 @@ use embassy_rp::usb::Driver;
13use embassy_rp::{interrupt, peripherals}; 13use embassy_rp::{interrupt, peripherals};
14use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; 14use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
15use embassy_sync::channel::Channel; 15use embassy_sync::channel::Channel;
16use embassy_usb::class::cdc_ncm::{CdcNcmClass, Receiver, Sender, State};
16use embassy_usb::{Builder, Config, UsbDevice}; 17use embassy_usb::{Builder, Config, UsbDevice};
17use embassy_usb_ncm::{CdcNcmClass, Receiver, Sender, State};
18use embedded_io::asynch::Write; 18use embedded_io::asynch::Write;
19use static_cell::StaticCell; 19use static_cell::StaticCell;
20use {defmt_rtt as _, panic_probe as _}; 20use {defmt_rtt as _, panic_probe as _};
diff --git a/examples/rp/src/bin/usb_serial.rs b/examples/rp/src/bin/usb_serial.rs
index bf92a1636..b7d6493b4 100644
--- a/examples/rp/src/bin/usb_serial.rs
+++ b/examples/rp/src/bin/usb_serial.rs
@@ -7,9 +7,9 @@ use embassy_executor::Spawner;
7use embassy_futures::join::join; 7use embassy_futures::join::join;
8use embassy_rp::interrupt; 8use embassy_rp::interrupt;
9use embassy_rp::usb::{Driver, Instance}; 9use embassy_rp::usb::{Driver, Instance};
10use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
10use embassy_usb::driver::EndpointError; 11use embassy_usb::driver::EndpointError;
11use embassy_usb::{Builder, Config}; 12use embassy_usb::{Builder, Config};
12use embassy_usb_serial::{CdcAcmClass, State};
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
15#[embassy_executor::main] 15#[embassy_executor::main]
diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml
index 895e043dd..e6553789a 100644
--- a/examples/stm32f1/Cargo.toml
+++ b/examples/stm32f1/Cargo.toml
@@ -9,7 +9,6 @@ embassy-executor = { version = "0.1.0", path = "../../embassy-executor", feature
9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
10embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any"] } 10embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any"] }
11embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } 11embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
12embassy-usb-serial = { version = "0.1.0", path = "../../embassy-usb-serial", features = ["defmt"] }
13embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 12embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
14 13
15defmt = "0.3" 14defmt = "0.3"
diff --git a/examples/stm32f1/src/bin/usb_serial.rs b/examples/stm32f1/src/bin/usb_serial.rs
index a14e728ba..ad92cdeb2 100644
--- a/examples/stm32f1/src/bin/usb_serial.rs
+++ b/examples/stm32f1/src/bin/usb_serial.rs
@@ -10,9 +10,9 @@ use embassy_stm32::time::Hertz;
10use embassy_stm32::usb::{Driver, Instance}; 10use embassy_stm32::usb::{Driver, Instance};
11use embassy_stm32::{interrupt, Config}; 11use embassy_stm32::{interrupt, Config};
12use embassy_time::{Duration, Timer}; 12use embassy_time::{Duration, Timer};
13use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
13use embassy_usb::driver::EndpointError; 14use embassy_usb::driver::EndpointError;
14use embassy_usb::Builder; 15use embassy_usb::Builder;
15use embassy_usb_serial::{CdcAcmClass, State};
16use {defmt_rtt as _, panic_probe as _}; 16use {defmt_rtt as _, panic_probe as _};
17 17
18#[embassy_executor::main] 18#[embassy_executor::main]
diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml
index 27f5c260a..f5b0b880c 100644
--- a/examples/stm32f3/Cargo.toml
+++ b/examples/stm32f3/Cargo.toml
@@ -9,8 +9,6 @@ embassy-executor = { version = "0.1.0", path = "../../embassy-executor", feature
9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
10embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-any", "exti"] } 10embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-any", "exti"] }
11embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } 11embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
12embassy-usb-serial = { version = "0.1.0", path = "../../embassy-usb-serial", features = ["defmt"] }
13embassy-usb-hid = { version = "0.1.0", path = "../../embassy-usb-hid", features = ["defmt"] }
14embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 12embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
15 13
16defmt = "0.3" 14defmt = "0.3"
diff --git a/examples/stm32f3/src/bin/usb_serial.rs b/examples/stm32f3/src/bin/usb_serial.rs
index b9fd20e2b..f6d27c860 100644
--- a/examples/stm32f3/src/bin/usb_serial.rs
+++ b/examples/stm32f3/src/bin/usb_serial.rs
@@ -10,9 +10,9 @@ use embassy_stm32::time::mhz;
10use embassy_stm32::usb::{Driver, Instance}; 10use embassy_stm32::usb::{Driver, Instance};
11use embassy_stm32::{interrupt, Config}; 11use embassy_stm32::{interrupt, Config};
12use embassy_time::{Duration, Timer}; 12use embassy_time::{Duration, Timer};
13use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
13use embassy_usb::driver::EndpointError; 14use embassy_usb::driver::EndpointError;
14use embassy_usb::Builder; 15use embassy_usb::Builder;
15use embassy_usb_serial::{CdcAcmClass, State};
16use {defmt_rtt as _, panic_probe as _}; 16use {defmt_rtt as _, panic_probe as _};
17 17
18#[embassy_executor::main] 18#[embassy_executor::main]
diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml
index 05945f6bf..9ebab6476 100644
--- a/examples/stm32l5/Cargo.toml
+++ b/examples/stm32l5/Cargo.toml
@@ -11,9 +11,6 @@ embassy-executor = { version = "0.1.0", path = "../../embassy-executor", feature
11embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 11embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
12embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "unstable-traits", "memory-x"] } 12embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "unstable-traits", "memory-x"] }
13embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } 13embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
14embassy-usb-serial = { version = "0.1.0", path = "../../embassy-usb-serial", features = ["defmt"] }
15embassy-usb-hid = { version = "0.1.0", path = "../../embassy-usb-hid", features = ["defmt"] }
16embassy-usb-ncm = { version = "0.1.0", path = "../../embassy-usb-ncm", features = ["defmt"] }
17embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "pool-16"] } 14embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "pool-16"] }
18embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 15embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
19usbd-hid = "0.6.0" 16usbd-hid = "0.6.0"
diff --git a/examples/stm32l5/src/bin/usb_ethernet.rs b/examples/stm32l5/src/bin/usb_ethernet.rs
index c96a83ead..4f36d3f5a 100644
--- a/examples/stm32l5/src/bin/usb_ethernet.rs
+++ b/examples/stm32l5/src/bin/usb_ethernet.rs
@@ -15,8 +15,8 @@ use embassy_stm32::usb::Driver;
15use embassy_stm32::{interrupt, Config}; 15use embassy_stm32::{interrupt, Config};
16use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; 16use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
17use embassy_sync::channel::Channel; 17use embassy_sync::channel::Channel;
18use embassy_usb::class::cdc_ncm::{CdcNcmClass, Receiver, Sender, State};
18use embassy_usb::{Builder, UsbDevice}; 19use embassy_usb::{Builder, UsbDevice};
19use embassy_usb_ncm::{CdcNcmClass, Receiver, Sender, State};
20use embedded_io::asynch::Write; 20use embedded_io::asynch::Write;
21use rand_core::RngCore; 21use rand_core::RngCore;
22use static_cell::StaticCell; 22use static_cell::StaticCell;
diff --git a/examples/stm32l5/src/bin/usb_hid_mouse.rs b/examples/stm32l5/src/bin/usb_hid_mouse.rs
index fa92ceae3..d38ed7496 100644
--- a/examples/stm32l5/src/bin/usb_hid_mouse.rs
+++ b/examples/stm32l5/src/bin/usb_hid_mouse.rs
@@ -9,9 +9,9 @@ use embassy_stm32::rcc::*;
9use embassy_stm32::usb::Driver; 9use embassy_stm32::usb::Driver;
10use embassy_stm32::{interrupt, Config}; 10use embassy_stm32::{interrupt, Config};
11use embassy_time::{Duration, Timer}; 11use embassy_time::{Duration, Timer};
12use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State};
12use embassy_usb::control::OutResponse; 13use embassy_usb::control::OutResponse;
13use embassy_usb::Builder; 14use embassy_usb::Builder;
14use embassy_usb_hid::{HidWriter, ReportId, RequestHandler, State};
15use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; 15use usbd_hid::descriptor::{MouseReport, SerializedDescriptor};
16use {defmt_rtt as _, panic_probe as _}; 16use {defmt_rtt as _, panic_probe as _};
17 17
@@ -55,7 +55,7 @@ async fn main(_spawner: Spawner) {
55 ); 55 );
56 56
57 // Create classes on the builder. 57 // Create classes on the builder.
58 let config = embassy_usb_hid::Config { 58 let config = embassy_usb::class::hid::Config {
59 report_descriptor: MouseReport::desc(), 59 report_descriptor: MouseReport::desc(),
60 request_handler: Some(&request_handler), 60 request_handler: Some(&request_handler),
61 poll_ms: 60, 61 poll_ms: 60,
diff --git a/examples/stm32l5/src/bin/usb_serial.rs b/examples/stm32l5/src/bin/usb_serial.rs
index 7484dc832..7562a4e96 100644
--- a/examples/stm32l5/src/bin/usb_serial.rs
+++ b/examples/stm32l5/src/bin/usb_serial.rs
@@ -8,9 +8,9 @@ use embassy_futures::join::join;
8use embassy_stm32::rcc::*; 8use embassy_stm32::rcc::*;
9use embassy_stm32::usb::{Driver, Instance}; 9use embassy_stm32::usb::{Driver, Instance};
10use embassy_stm32::{interrupt, Config}; 10use embassy_stm32::{interrupt, Config};
11use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
11use embassy_usb::driver::EndpointError; 12use embassy_usb::driver::EndpointError;
12use embassy_usb::Builder; 13use embassy_usb::Builder;
13use embassy_usb_serial::{CdcAcmClass, State};
14use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
15 15
16#[embassy_executor::main] 16#[embassy_executor::main]