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 <dirbaio@dirbaio.net>
This commit is contained in:
		| @@ -10,8 +10,9 @@ use cortex_m::peripheral::NVIC; | |||||||
| use embassy_hal_common::{into_ref, PeripheralRef}; | use embassy_hal_common::{into_ref, PeripheralRef}; | ||||||
| use embassy_sync::waitqueue::AtomicWaker; | use embassy_sync::waitqueue::AtomicWaker; | ||||||
| pub use embassy_usb; | pub use embassy_usb; | ||||||
| use embassy_usb::driver::{self, EndpointError, Event, Unsupported}; | use embassy_usb::driver::{ | ||||||
| use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection}; |     self, Direction, EndpointAddress, EndpointError, EndpointInfo, EndpointType, Event, Unsupported, | ||||||
|  | }; | ||||||
| use pac::usbd::RegisterBlock; | use pac::usbd::RegisterBlock; | ||||||
|  |  | ||||||
| use crate::interrupt::{Interrupt, InterruptExt}; | use crate::interrupt::{Interrupt, InterruptExt}; | ||||||
| @@ -243,7 +244,7 @@ impl<'d, T: Instance, P: UsbSupply + 'd> driver::Driver<'d> for Driver<'d, T, P> | |||||||
|         interval: u8, |         interval: u8, | ||||||
|     ) -> Result<Self::EndpointIn, driver::EndpointAllocError> { |     ) -> Result<Self::EndpointIn, driver::EndpointAllocError> { | ||||||
|         let index = self.alloc_in.allocate(ep_type)?; |         let index = self.alloc_in.allocate(ep_type)?; | ||||||
|         let ep_addr = EndpointAddress::from_parts(index, UsbDirection::In); |         let ep_addr = EndpointAddress::from_parts(index, Direction::In); | ||||||
|         Ok(Endpoint::new(EndpointInfo { |         Ok(Endpoint::new(EndpointInfo { | ||||||
|             addr: ep_addr, |             addr: ep_addr, | ||||||
|             ep_type, |             ep_type, | ||||||
| @@ -259,7 +260,7 @@ impl<'d, T: Instance, P: UsbSupply + 'd> driver::Driver<'d> for Driver<'d, T, P> | |||||||
|         interval: u8, |         interval: u8, | ||||||
|     ) -> Result<Self::EndpointOut, driver::EndpointAllocError> { |     ) -> Result<Self::EndpointOut, driver::EndpointAllocError> { | ||||||
|         let index = self.alloc_out.allocate(ep_type)?; |         let index = self.alloc_out.allocate(ep_type)?; | ||||||
|         let ep_addr = EndpointAddress::from_parts(index, UsbDirection::Out); |         let ep_addr = EndpointAddress::from_parts(index, Direction::Out); | ||||||
|         Ok(Endpoint::new(EndpointInfo { |         Ok(Endpoint::new(EndpointInfo { | ||||||
|             addr: ep_addr, |             addr: ep_addr, | ||||||
|             ep_type, |             ep_type, | ||||||
| @@ -428,8 +429,8 @@ impl<'d, T: Instance, P: UsbSupply> driver::Bus for Bus<'d, T, P> { | |||||||
|         let regs = T::regs(); |         let regs = T::regs(); | ||||||
|         let i = ep_addr.index(); |         let i = ep_addr.index(); | ||||||
|         match ep_addr.direction() { |         match ep_addr.direction() { | ||||||
|             UsbDirection::Out => regs.halted.epout[i].read().getstatus().is_halted(), |             Direction::Out => regs.halted.epout[i].read().getstatus().is_halted(), | ||||||
|             UsbDirection::In => regs.halted.epin[i].read().getstatus().is_halted(), |             Direction::In => regs.halted.epin[i].read().getstatus().is_halted(), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -442,7 +443,7 @@ impl<'d, T: Instance, P: UsbSupply> driver::Bus for Bus<'d, T, P> { | |||||||
|         debug!("endpoint_set_enabled {:?} {}", ep_addr, enabled); |         debug!("endpoint_set_enabled {:?} {}", ep_addr, enabled); | ||||||
|  |  | ||||||
|         match ep_addr.direction() { |         match ep_addr.direction() { | ||||||
|             UsbDirection::In => { |             Direction::In => { | ||||||
|                 let mut was_enabled = false; |                 let mut was_enabled = false; | ||||||
|                 regs.epinen.modify(|r, w| { |                 regs.epinen.modify(|r, w| { | ||||||
|                     let mut bits = r.bits(); |                     let mut bits = r.bits(); | ||||||
| @@ -466,7 +467,7 @@ impl<'d, T: Instance, P: UsbSupply> driver::Bus for Bus<'d, T, P> { | |||||||
|  |  | ||||||
|                 In::waker(i).wake(); |                 In::waker(i).wake(); | ||||||
|             } |             } | ||||||
|             UsbDirection::Out => { |             Direction::Out => { | ||||||
|                 regs.epouten.modify(|r, w| { |                 regs.epouten.modify(|r, w| { | ||||||
|                     let mut bits = r.bits(); |                     let mut bits = r.bits(); | ||||||
|                     if enabled { |                     if enabled { | ||||||
|   | |||||||
| @@ -7,8 +7,9 @@ use core::task::Poll; | |||||||
| use atomic_polyfill::compiler_fence; | use atomic_polyfill::compiler_fence; | ||||||
| use embassy_hal_common::into_ref; | use embassy_hal_common::into_ref; | ||||||
| use embassy_sync::waitqueue::AtomicWaker; | use embassy_sync::waitqueue::AtomicWaker; | ||||||
| use embassy_usb::driver::{self, EndpointAllocError, EndpointError, Event, Unsupported}; | use embassy_usb::driver::{ | ||||||
| use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection}; |     self, Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointInfo, EndpointType, Event, Unsupported, | ||||||
|  | }; | ||||||
|  |  | ||||||
| use crate::interrupt::{Interrupt, InterruptExt}; | use crate::interrupt::{Interrupt, InterruptExt}; | ||||||
| use crate::{pac, peripherals, Peripheral, RegExt}; | use crate::{pac, peripherals, Peripheral, RegExt}; | ||||||
| @@ -204,8 +205,8 @@ impl<'d, T: Instance> Driver<'d, T> { | |||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         let alloc = match D::dir() { |         let alloc = match D::dir() { | ||||||
|             UsbDirection::Out => &mut self.ep_out, |             Direction::Out => &mut self.ep_out, | ||||||
|             UsbDirection::In => &mut self.ep_in, |             Direction::In => &mut self.ep_in, | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|         let index = alloc.iter_mut().enumerate().find(|(i, ep)| { |         let index = alloc.iter_mut().enumerate().find(|(i, ep)| { | ||||||
| @@ -254,7 +255,7 @@ impl<'d, T: Instance> Driver<'d, T> { | |||||||
|         }; |         }; | ||||||
|  |  | ||||||
|         match D::dir() { |         match D::dir() { | ||||||
|             UsbDirection::Out => unsafe { |             Direction::Out => unsafe { | ||||||
|                 T::dpram().ep_out_control(index - 1).write(|w| { |                 T::dpram().ep_out_control(index - 1).write(|w| { | ||||||
|                     w.set_enable(false); |                     w.set_enable(false); | ||||||
|                     w.set_buffer_address(addr); |                     w.set_buffer_address(addr); | ||||||
| @@ -262,7 +263,7 @@ impl<'d, T: Instance> Driver<'d, T> { | |||||||
|                     w.set_endpoint_type(ep_type_reg); |                     w.set_endpoint_type(ep_type_reg); | ||||||
|                 }) |                 }) | ||||||
|             }, |             }, | ||||||
|             UsbDirection::In => unsafe { |             Direction::In => unsafe { | ||||||
|                 T::dpram().ep_in_control(index - 1).write(|w| { |                 T::dpram().ep_in_control(index - 1).write(|w| { | ||||||
|                     w.set_enable(false); |                     w.set_enable(false); | ||||||
|                     w.set_buffer_address(addr); |                     w.set_buffer_address(addr); | ||||||
| @@ -429,14 +430,14 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||||||
|  |  | ||||||
|         let n = ep_addr.index(); |         let n = ep_addr.index(); | ||||||
|         match ep_addr.direction() { |         match ep_addr.direction() { | ||||||
|             UsbDirection::In => unsafe { |             Direction::In => unsafe { | ||||||
|                 T::dpram().ep_in_control(n - 1).modify(|w| w.set_enable(enabled)); |                 T::dpram().ep_in_control(n - 1).modify(|w| w.set_enable(enabled)); | ||||||
|                 T::dpram().ep_in_buffer_control(ep_addr.index()).write(|w| { |                 T::dpram().ep_in_buffer_control(ep_addr.index()).write(|w| { | ||||||
|                     w.set_pid(0, true); // first packet is DATA0, but PID is flipped before |                     w.set_pid(0, true); // first packet is DATA0, but PID is flipped before | ||||||
|                 }); |                 }); | ||||||
|                 EP_IN_WAKERS[n].wake(); |                 EP_IN_WAKERS[n].wake(); | ||||||
|             }, |             }, | ||||||
|             UsbDirection::Out => unsafe { |             Direction::Out => unsafe { | ||||||
|                 T::dpram().ep_out_control(n - 1).modify(|w| w.set_enable(enabled)); |                 T::dpram().ep_out_control(n - 1).modify(|w| w.set_enable(enabled)); | ||||||
|  |  | ||||||
|                 T::dpram().ep_out_buffer_control(ep_addr.index()).write(|w| { |                 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> { | |||||||
| } | } | ||||||
|  |  | ||||||
| trait Dir { | trait Dir { | ||||||
|     fn dir() -> UsbDirection; |     fn dir() -> Direction; | ||||||
|     fn waker(i: usize) -> &'static AtomicWaker; |     fn waker(i: usize) -> &'static AtomicWaker; | ||||||
| } | } | ||||||
|  |  | ||||||
| pub enum In {} | pub enum In {} | ||||||
| impl Dir for In { | impl Dir for In { | ||||||
|     fn dir() -> UsbDirection { |     fn dir() -> Direction { | ||||||
|         UsbDirection::In |         Direction::In | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     #[inline] |     #[inline] | ||||||
| @@ -492,8 +493,8 @@ impl Dir for In { | |||||||
|  |  | ||||||
| pub enum Out {} | pub enum Out {} | ||||||
| impl Dir for Out { | impl Dir for Out { | ||||||
|     fn dir() -> UsbDirection { |     fn dir() -> Direction { | ||||||
|         UsbDirection::Out |         Direction::Out | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     #[inline] |     #[inline] | ||||||
|   | |||||||
| @@ -9,8 +9,9 @@ use atomic_polyfill::{AtomicBool, AtomicU8}; | |||||||
| use embassy_hal_common::into_ref; | use embassy_hal_common::into_ref; | ||||||
| use embassy_sync::waitqueue::AtomicWaker; | use embassy_sync::waitqueue::AtomicWaker; | ||||||
| use embassy_time::{block_for, Duration}; | use embassy_time::{block_for, Duration}; | ||||||
| use embassy_usb::driver::{self, EndpointAllocError, EndpointError, Event, Unsupported}; | use embassy_usb::driver::{ | ||||||
| use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection}; |     self, Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointInfo, EndpointType, Event, Unsupported, | ||||||
|  | }; | ||||||
| use pac::common::{Reg, RW}; | use pac::common::{Reg, RW}; | ||||||
| use pac::usb::vals::{EpType, Stat}; | use pac::usb::vals::{EpType, Stat}; | ||||||
|  |  | ||||||
| @@ -279,8 +280,8 @@ impl<'d, T: Instance> Driver<'d, T> { | |||||||
|             } |             } | ||||||
|             let used = ep.used_out || ep.used_in; |             let used = ep.used_out || ep.used_in; | ||||||
|             let used_dir = match D::dir() { |             let used_dir = match D::dir() { | ||||||
|                 UsbDirection::Out => ep.used_out, |                 Direction::Out => ep.used_out, | ||||||
|                 UsbDirection::In => ep.used_in, |                 Direction::In => ep.used_in, | ||||||
|             }; |             }; | ||||||
|             !used || (ep.ep_type == ep_type && !used_dir) |             !used || (ep.ep_type == ep_type && !used_dir) | ||||||
|         }); |         }); | ||||||
| @@ -293,7 +294,7 @@ impl<'d, T: Instance> Driver<'d, T> { | |||||||
|         ep.ep_type = ep_type; |         ep.ep_type = ep_type; | ||||||
|  |  | ||||||
|         let buf = match D::dir() { |         let buf = match D::dir() { | ||||||
|             UsbDirection::Out => { |             Direction::Out => { | ||||||
|                 assert!(!ep.used_out); |                 assert!(!ep.used_out); | ||||||
|                 ep.used_out = true; |                 ep.used_out = true; | ||||||
|  |  | ||||||
| @@ -312,7 +313,7 @@ impl<'d, T: Instance> Driver<'d, T> { | |||||||
|                     _phantom: PhantomData, |                     _phantom: PhantomData, | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             UsbDirection::In => { |             Direction::In => { | ||||||
|                 assert!(!ep.used_in); |                 assert!(!ep.used_in); | ||||||
|                 ep.used_in = true; |                 ep.used_in = true; | ||||||
|  |  | ||||||
| @@ -504,7 +505,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||||||
|         // This can race, so do a retry loop. |         // This can race, so do a retry loop. | ||||||
|         let reg = T::regs().epr(ep_addr.index() as _); |         let reg = T::regs().epr(ep_addr.index() as _); | ||||||
|         match ep_addr.direction() { |         match ep_addr.direction() { | ||||||
|             UsbDirection::In => { |             Direction::In => { | ||||||
|                 loop { |                 loop { | ||||||
|                     let r = unsafe { reg.read() }; |                     let r = unsafe { reg.read() }; | ||||||
|                     match r.stat_tx() { |                     match r.stat_tx() { | ||||||
| @@ -523,7 +524,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||||||
|                 } |                 } | ||||||
|                 EP_IN_WAKERS[ep_addr.index()].wake(); |                 EP_IN_WAKERS[ep_addr.index()].wake(); | ||||||
|             } |             } | ||||||
|             UsbDirection::Out => { |             Direction::Out => { | ||||||
|                 loop { |                 loop { | ||||||
|                     let r = unsafe { reg.read() }; |                     let r = unsafe { reg.read() }; | ||||||
|                     match r.stat_rx() { |                     match r.stat_rx() { | ||||||
| @@ -549,8 +550,8 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||||||
|         let regs = T::regs(); |         let regs = T::regs(); | ||||||
|         let epr = unsafe { regs.epr(ep_addr.index() as _).read() }; |         let epr = unsafe { regs.epr(ep_addr.index() as _).read() }; | ||||||
|         match ep_addr.direction() { |         match ep_addr.direction() { | ||||||
|             UsbDirection::In => epr.stat_tx() == Stat::STALL, |             Direction::In => epr.stat_tx() == Stat::STALL, | ||||||
|             UsbDirection::Out => epr.stat_rx() == Stat::STALL, |             Direction::Out => epr.stat_rx() == Stat::STALL, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -560,7 +561,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||||||
|         let reg = T::regs().epr(ep_addr.index() as _); |         let reg = T::regs().epr(ep_addr.index() as _); | ||||||
|         trace!("EPR before: {:04x}", unsafe { reg.read() }.0); |         trace!("EPR before: {:04x}", unsafe { reg.read() }.0); | ||||||
|         match ep_addr.direction() { |         match ep_addr.direction() { | ||||||
|             UsbDirection::In => { |             Direction::In => { | ||||||
|                 loop { |                 loop { | ||||||
|                     let want_stat = match enabled { |                     let want_stat = match enabled { | ||||||
|                         false => Stat::DISABLED, |                         false => Stat::DISABLED, | ||||||
| @@ -576,7 +577,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||||||
|                 } |                 } | ||||||
|                 EP_IN_WAKERS[ep_addr.index()].wake(); |                 EP_IN_WAKERS[ep_addr.index()].wake(); | ||||||
|             } |             } | ||||||
|             UsbDirection::Out => { |             Direction::Out => { | ||||||
|                 loop { |                 loop { | ||||||
|                     let want_stat = match enabled { |                     let want_stat = match enabled { | ||||||
|                         false => Stat::DISABLED, |                         false => Stat::DISABLED, | ||||||
| @@ -616,14 +617,14 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||||||
| } | } | ||||||
|  |  | ||||||
| trait Dir { | trait Dir { | ||||||
|     fn dir() -> UsbDirection; |     fn dir() -> Direction; | ||||||
|     fn waker(i: usize) -> &'static AtomicWaker; |     fn waker(i: usize) -> &'static AtomicWaker; | ||||||
| } | } | ||||||
|  |  | ||||||
| pub enum In {} | pub enum In {} | ||||||
| impl Dir for In { | impl Dir for In { | ||||||
|     fn dir() -> UsbDirection { |     fn dir() -> Direction { | ||||||
|         UsbDirection::In |         Direction::In | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     #[inline] |     #[inline] | ||||||
| @@ -634,8 +635,8 @@ impl Dir for In { | |||||||
|  |  | ||||||
| pub enum Out {} | pub enum Out {} | ||||||
| impl Dir for Out { | impl Dir for Out { | ||||||
|     fn dir() -> UsbDirection { |     fn dir() -> Direction { | ||||||
|         UsbDirection::Out |         Direction::Out | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     #[inline] |     #[inline] | ||||||
|   | |||||||
| @@ -1,17 +1,16 @@ | |||||||
| [package] | [package] | ||||||
| name = "embassy-usb-ncm" | name = "embassy-usb-driver" | ||||||
| version = "0.1.0" | version = "0.1.0" | ||||||
| edition = "2021" | edition = "2021" | ||||||
| 
 | 
 | ||||||
|  | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||||||
|  | 
 | ||||||
| [package.metadata.embassy_docs] | [package.metadata.embassy_docs] | ||||||
| src_base = "https://github.com/embassy-rs/embassy/blob/embassy-usb-ncm-v$VERSION/embassy-usb-ncm/src/" | src_base = "https://github.com/embassy-rs/embassy/blob/embassy-usb-driver-v$VERSION/embassy-usb/src/" | ||||||
| src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-usb-ncm/src/" | src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-usb-driver/src/" | ||||||
| features = ["defmt"] | features = ["defmt"] | ||||||
| target = "thumbv7em-none-eabi" | target = "thumbv7em-none-eabi" | ||||||
| 
 | 
 | ||||||
| [dependencies] | [dependencies] | ||||||
| embassy-sync = { version = "0.1.0", path = "../embassy-sync" } |  | ||||||
| embassy-usb = { version = "0.1.0", path = "../embassy-usb" } |  | ||||||
| 
 |  | ||||||
| defmt = { version = "0.3", optional = true } | defmt = { version = "0.3", optional = true } | ||||||
| log = { version = "0.4.14", optional = true } | log = { version = "0.4.14", optional = true } | ||||||
| @@ -1,6 +1,104 @@ | |||||||
|  | #![no_std] | ||||||
|  | 
 | ||||||
| use core::future::Future; | use core::future::Future; | ||||||
| 
 | 
 | ||||||
| use super::types::*; | /// Direction of USB traffic. Note that in the USB standard the direction is always indicated from
 | ||||||
|  | /// the perspective of the host, which is backward for devices, but the standard directions are used
 | ||||||
|  | /// for consistency.
 | ||||||
|  | ///
 | ||||||
|  | /// The values of the enum also match the direction bit used in endpoint addresses and control
 | ||||||
|  | /// request types.
 | ||||||
|  | #[derive(Copy, Clone, Eq, PartialEq, Debug)] | ||||||
|  | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||||||
|  | pub enum Direction { | ||||||
|  |     /// Host to device (OUT)
 | ||||||
|  |     Out, | ||||||
|  |     /// Device to host (IN)
 | ||||||
|  |     In, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// USB endpoint transfer type. The values of this enum can be directly cast into `u8` to get the
 | ||||||
|  | /// transfer bmAttributes transfer type bits.
 | ||||||
|  | #[repr(u8)] | ||||||
|  | #[derive(Copy, Clone, Eq, PartialEq, Debug)] | ||||||
|  | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||||||
|  | pub enum EndpointType { | ||||||
|  |     /// Control endpoint. Used for device management. Only the host can initiate requests. Usually
 | ||||||
|  |     /// used only endpoint 0.
 | ||||||
|  |     Control = 0b00, | ||||||
|  |     /// Isochronous endpoint. Used for time-critical unreliable data. Not implemented yet.
 | ||||||
|  |     Isochronous = 0b01, | ||||||
|  |     /// Bulk endpoint. Used for large amounts of best-effort reliable data.
 | ||||||
|  |     Bulk = 0b10, | ||||||
|  |     /// Interrupt endpoint. Used for small amounts of time-critical reliable data.
 | ||||||
|  |     Interrupt = 0b11, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Type-safe endpoint address.
 | ||||||
|  | #[derive(Debug, Clone, Copy, Eq, PartialEq)] | ||||||
|  | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||||||
|  | pub struct EndpointAddress(u8); | ||||||
|  | 
 | ||||||
|  | impl From<u8> for EndpointAddress { | ||||||
|  |     #[inline] | ||||||
|  |     fn from(addr: u8) -> EndpointAddress { | ||||||
|  |         EndpointAddress(addr) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl From<EndpointAddress> for u8 { | ||||||
|  |     #[inline] | ||||||
|  |     fn from(addr: EndpointAddress) -> u8 { | ||||||
|  |         addr.0 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl EndpointAddress { | ||||||
|  |     const INBITS: u8 = Direction::In as u8; | ||||||
|  | 
 | ||||||
|  |     /// Constructs a new EndpointAddress with the given index and direction.
 | ||||||
|  |     #[inline] | ||||||
|  |     pub fn from_parts(index: usize, dir: Direction) -> Self { | ||||||
|  |         EndpointAddress(index as u8 | dir as u8) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Gets the direction part of the address.
 | ||||||
|  |     #[inline] | ||||||
|  |     pub fn direction(&self) -> Direction { | ||||||
|  |         if (self.0 & Self::INBITS) != 0 { | ||||||
|  |             Direction::In | ||||||
|  |         } else { | ||||||
|  |             Direction::Out | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Returns true if the direction is IN, otherwise false.
 | ||||||
|  |     #[inline] | ||||||
|  |     pub fn is_in(&self) -> bool { | ||||||
|  |         (self.0 & Self::INBITS) != 0 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Returns true if the direction is OUT, otherwise false.
 | ||||||
|  |     #[inline] | ||||||
|  |     pub fn is_out(&self) -> bool { | ||||||
|  |         (self.0 & Self::INBITS) == 0 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Gets the index part of the endpoint address.
 | ||||||
|  |     #[inline] | ||||||
|  |     pub fn index(&self) -> usize { | ||||||
|  |         (self.0 & !Self::INBITS) as usize | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Copy, Clone, Eq, PartialEq, Debug)] | ||||||
|  | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||||||
|  | pub struct EndpointInfo { | ||||||
|  |     pub addr: EndpointAddress, | ||||||
|  |     pub ep_type: EndpointType, | ||||||
|  |     pub max_packet_size: u16, | ||||||
|  |     pub interval: u8, | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| /// Driver for a specific USB peripheral. Implement this to add support for a new hardware
 | /// Driver for a specific USB peripheral. Implement this to add support for a new hardware
 | ||||||
| /// platform.
 | /// platform.
 | ||||||
| @@ -1,24 +0,0 @@ | |||||||
| [package] |  | ||||||
| name = "embassy-usb-hid" |  | ||||||
| version = "0.1.0" |  | ||||||
| edition = "2021" |  | ||||||
|  |  | ||||||
| [package.metadata.embassy_docs] |  | ||||||
| src_base = "https://github.com/embassy-rs/embassy/blob/embassy-usb-hid-v$VERSION/embassy-usb-hid/src/" |  | ||||||
| src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-usb-hid/src/" |  | ||||||
| features = ["defmt"] |  | ||||||
| target = "thumbv7em-none-eabi" |  | ||||||
|  |  | ||||||
| [features] |  | ||||||
| default = ["usbd-hid"] |  | ||||||
| usbd-hid = ["dep:usbd-hid", "ssmarshal"] |  | ||||||
|  |  | ||||||
| [dependencies] |  | ||||||
| embassy-sync = { version = "0.1.0", path = "../embassy-sync" } |  | ||||||
| embassy-usb = { version = "0.1.0", path = "../embassy-usb" } |  | ||||||
|  |  | ||||||
| defmt = { version = "0.3", optional = true } |  | ||||||
| log = { version = "0.4.14", optional = true } |  | ||||||
| usbd-hid = { version = "0.6.0", optional = true } |  | ||||||
| ssmarshal = { version = "1.0", default-features = false, optional = true } |  | ||||||
| futures-util = { version = "0.3.21", default-features = false } |  | ||||||
| @@ -1,225 +0,0 @@ | |||||||
| #![macro_use] |  | ||||||
| #![allow(unused_macros)] |  | ||||||
|  |  | ||||||
| #[cfg(all(feature = "defmt", feature = "log"))] |  | ||||||
| compile_error!("You may not enable both `defmt` and `log` features."); |  | ||||||
|  |  | ||||||
| macro_rules! assert { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(not(feature = "defmt"))] |  | ||||||
|             ::core::assert!($($x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::assert!($($x)*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! assert_eq { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(not(feature = "defmt"))] |  | ||||||
|             ::core::assert_eq!($($x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::assert_eq!($($x)*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! assert_ne { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(not(feature = "defmt"))] |  | ||||||
|             ::core::assert_ne!($($x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::assert_ne!($($x)*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! debug_assert { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(not(feature = "defmt"))] |  | ||||||
|             ::core::debug_assert!($($x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::debug_assert!($($x)*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! debug_assert_eq { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(not(feature = "defmt"))] |  | ||||||
|             ::core::debug_assert_eq!($($x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::debug_assert_eq!($($x)*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! debug_assert_ne { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(not(feature = "defmt"))] |  | ||||||
|             ::core::debug_assert_ne!($($x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::debug_assert_ne!($($x)*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! todo { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(not(feature = "defmt"))] |  | ||||||
|             ::core::todo!($($x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::todo!($($x)*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! unreachable { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(not(feature = "defmt"))] |  | ||||||
|             ::core::unreachable!($($x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::unreachable!($($x)*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! panic { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(not(feature = "defmt"))] |  | ||||||
|             ::core::panic!($($x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::panic!($($x)*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! trace { |  | ||||||
|     ($s:literal $(, $x:expr)* $(,)?) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(feature = "log")] |  | ||||||
|             ::log::trace!($s $(, $x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::trace!($s $(, $x)*); |  | ||||||
|             #[cfg(not(any(feature = "log", feature="defmt")))] |  | ||||||
|             let _ = ($( & $x ),*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! debug { |  | ||||||
|     ($s:literal $(, $x:expr)* $(,)?) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(feature = "log")] |  | ||||||
|             ::log::debug!($s $(, $x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::debug!($s $(, $x)*); |  | ||||||
|             #[cfg(not(any(feature = "log", feature="defmt")))] |  | ||||||
|             let _ = ($( & $x ),*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! info { |  | ||||||
|     ($s:literal $(, $x:expr)* $(,)?) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(feature = "log")] |  | ||||||
|             ::log::info!($s $(, $x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::info!($s $(, $x)*); |  | ||||||
|             #[cfg(not(any(feature = "log", feature="defmt")))] |  | ||||||
|             let _ = ($( & $x ),*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! warn { |  | ||||||
|     ($s:literal $(, $x:expr)* $(,)?) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(feature = "log")] |  | ||||||
|             ::log::warn!($s $(, $x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::warn!($s $(, $x)*); |  | ||||||
|             #[cfg(not(any(feature = "log", feature="defmt")))] |  | ||||||
|             let _ = ($( & $x ),*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! error { |  | ||||||
|     ($s:literal $(, $x:expr)* $(,)?) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(feature = "log")] |  | ||||||
|             ::log::error!($s $(, $x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::error!($s $(, $x)*); |  | ||||||
|             #[cfg(not(any(feature = "log", feature="defmt")))] |  | ||||||
|             let _ = ($( & $x ),*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #[cfg(feature = "defmt")] |  | ||||||
| macro_rules! unwrap { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         ::defmt::unwrap!($($x)*) |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #[cfg(not(feature = "defmt"))] |  | ||||||
| macro_rules! unwrap { |  | ||||||
|     ($arg:expr) => { |  | ||||||
|         match $crate::fmt::Try::into_result($arg) { |  | ||||||
|             ::core::result::Result::Ok(t) => t, |  | ||||||
|             ::core::result::Result::Err(e) => { |  | ||||||
|                 ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
|     ($arg:expr, $($msg:expr),+ $(,)? ) => { |  | ||||||
|         match $crate::fmt::Try::into_result($arg) { |  | ||||||
|             ::core::result::Result::Ok(t) => t, |  | ||||||
|             ::core::result::Result::Err(e) => { |  | ||||||
|                 ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #[derive(Debug, Copy, Clone, Eq, PartialEq)] |  | ||||||
| pub struct NoneError; |  | ||||||
|  |  | ||||||
| pub trait Try { |  | ||||||
|     type Ok; |  | ||||||
|     type Error; |  | ||||||
|     fn into_result(self) -> Result<Self::Ok, Self::Error>; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| impl<T> Try for Option<T> { |  | ||||||
|     type Ok = T; |  | ||||||
|     type Error = NoneError; |  | ||||||
|  |  | ||||||
|     #[inline] |  | ||||||
|     fn into_result(self) -> Result<T, NoneError> { |  | ||||||
|         self.ok_or(NoneError) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| impl<T, E> Try for Result<T, E> { |  | ||||||
|     type Ok = T; |  | ||||||
|     type Error = E; |  | ||||||
|  |  | ||||||
|     #[inline] |  | ||||||
|     fn into_result(self) -> Self { |  | ||||||
|         self |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,225 +0,0 @@ | |||||||
| #![macro_use] |  | ||||||
| #![allow(unused_macros)] |  | ||||||
|  |  | ||||||
| #[cfg(all(feature = "defmt", feature = "log"))] |  | ||||||
| compile_error!("You may not enable both `defmt` and `log` features."); |  | ||||||
|  |  | ||||||
| macro_rules! assert { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(not(feature = "defmt"))] |  | ||||||
|             ::core::assert!($($x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::assert!($($x)*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! assert_eq { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(not(feature = "defmt"))] |  | ||||||
|             ::core::assert_eq!($($x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::assert_eq!($($x)*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! assert_ne { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(not(feature = "defmt"))] |  | ||||||
|             ::core::assert_ne!($($x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::assert_ne!($($x)*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! debug_assert { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(not(feature = "defmt"))] |  | ||||||
|             ::core::debug_assert!($($x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::debug_assert!($($x)*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! debug_assert_eq { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(not(feature = "defmt"))] |  | ||||||
|             ::core::debug_assert_eq!($($x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::debug_assert_eq!($($x)*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! debug_assert_ne { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(not(feature = "defmt"))] |  | ||||||
|             ::core::debug_assert_ne!($($x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::debug_assert_ne!($($x)*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! todo { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(not(feature = "defmt"))] |  | ||||||
|             ::core::todo!($($x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::todo!($($x)*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! unreachable { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(not(feature = "defmt"))] |  | ||||||
|             ::core::unreachable!($($x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::unreachable!($($x)*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! panic { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(not(feature = "defmt"))] |  | ||||||
|             ::core::panic!($($x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::panic!($($x)*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! trace { |  | ||||||
|     ($s:literal $(, $x:expr)* $(,)?) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(feature = "log")] |  | ||||||
|             ::log::trace!($s $(, $x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::trace!($s $(, $x)*); |  | ||||||
|             #[cfg(not(any(feature = "log", feature="defmt")))] |  | ||||||
|             let _ = ($( & $x ),*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! debug { |  | ||||||
|     ($s:literal $(, $x:expr)* $(,)?) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(feature = "log")] |  | ||||||
|             ::log::debug!($s $(, $x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::debug!($s $(, $x)*); |  | ||||||
|             #[cfg(not(any(feature = "log", feature="defmt")))] |  | ||||||
|             let _ = ($( & $x ),*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! info { |  | ||||||
|     ($s:literal $(, $x:expr)* $(,)?) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(feature = "log")] |  | ||||||
|             ::log::info!($s $(, $x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::info!($s $(, $x)*); |  | ||||||
|             #[cfg(not(any(feature = "log", feature="defmt")))] |  | ||||||
|             let _ = ($( & $x ),*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! warn { |  | ||||||
|     ($s:literal $(, $x:expr)* $(,)?) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(feature = "log")] |  | ||||||
|             ::log::warn!($s $(, $x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::warn!($s $(, $x)*); |  | ||||||
|             #[cfg(not(any(feature = "log", feature="defmt")))] |  | ||||||
|             let _ = ($( & $x ),*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! error { |  | ||||||
|     ($s:literal $(, $x:expr)* $(,)?) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(feature = "log")] |  | ||||||
|             ::log::error!($s $(, $x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::error!($s $(, $x)*); |  | ||||||
|             #[cfg(not(any(feature = "log", feature="defmt")))] |  | ||||||
|             let _ = ($( & $x ),*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #[cfg(feature = "defmt")] |  | ||||||
| macro_rules! unwrap { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         ::defmt::unwrap!($($x)*) |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #[cfg(not(feature = "defmt"))] |  | ||||||
| macro_rules! unwrap { |  | ||||||
|     ($arg:expr) => { |  | ||||||
|         match $crate::fmt::Try::into_result($arg) { |  | ||||||
|             ::core::result::Result::Ok(t) => t, |  | ||||||
|             ::core::result::Result::Err(e) => { |  | ||||||
|                 ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
|     ($arg:expr, $($msg:expr),+ $(,)? ) => { |  | ||||||
|         match $crate::fmt::Try::into_result($arg) { |  | ||||||
|             ::core::result::Result::Ok(t) => t, |  | ||||||
|             ::core::result::Result::Err(e) => { |  | ||||||
|                 ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #[derive(Debug, Copy, Clone, Eq, PartialEq)] |  | ||||||
| pub struct NoneError; |  | ||||||
|  |  | ||||||
| pub trait Try { |  | ||||||
|     type Ok; |  | ||||||
|     type Error; |  | ||||||
|     fn into_result(self) -> Result<Self::Ok, Self::Error>; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| impl<T> Try for Option<T> { |  | ||||||
|     type Ok = T; |  | ||||||
|     type Error = NoneError; |  | ||||||
|  |  | ||||||
|     #[inline] |  | ||||||
|     fn into_result(self) -> Result<T, NoneError> { |  | ||||||
|         self.ok_or(NoneError) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| impl<T, E> Try for Result<T, E> { |  | ||||||
|     type Ok = T; |  | ||||||
|     type Error = E; |  | ||||||
|  |  | ||||||
|     #[inline] |  | ||||||
|     fn into_result(self) -> Self { |  | ||||||
|         self |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,17 +0,0 @@ | |||||||
| [package] |  | ||||||
| name = "embassy-usb-serial" |  | ||||||
| version = "0.1.0" |  | ||||||
| edition = "2021" |  | ||||||
|  |  | ||||||
| [package.metadata.embassy_docs] |  | ||||||
| src_base = "https://github.com/embassy-rs/embassy/blob/embassy-usb-serial-v$VERSION/embassy-usb-serial/src/" |  | ||||||
| src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-usb-serial/src/" |  | ||||||
| features = ["defmt"] |  | ||||||
| target = "thumbv7em-none-eabi" |  | ||||||
|  |  | ||||||
| [dependencies] |  | ||||||
| embassy-sync = { version = "0.1.0", path = "../embassy-sync" } |  | ||||||
| embassy-usb = { version = "0.1.0", path = "../embassy-usb" } |  | ||||||
|  |  | ||||||
| defmt = { version = "0.3", optional = true } |  | ||||||
| log = { version = "0.4.14", optional = true } |  | ||||||
| @@ -1,225 +0,0 @@ | |||||||
| #![macro_use] |  | ||||||
| #![allow(unused_macros)] |  | ||||||
|  |  | ||||||
| #[cfg(all(feature = "defmt", feature = "log"))] |  | ||||||
| compile_error!("You may not enable both `defmt` and `log` features."); |  | ||||||
|  |  | ||||||
| macro_rules! assert { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(not(feature = "defmt"))] |  | ||||||
|             ::core::assert!($($x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::assert!($($x)*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! assert_eq { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(not(feature = "defmt"))] |  | ||||||
|             ::core::assert_eq!($($x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::assert_eq!($($x)*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! assert_ne { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(not(feature = "defmt"))] |  | ||||||
|             ::core::assert_ne!($($x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::assert_ne!($($x)*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! debug_assert { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(not(feature = "defmt"))] |  | ||||||
|             ::core::debug_assert!($($x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::debug_assert!($($x)*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! debug_assert_eq { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(not(feature = "defmt"))] |  | ||||||
|             ::core::debug_assert_eq!($($x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::debug_assert_eq!($($x)*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! debug_assert_ne { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(not(feature = "defmt"))] |  | ||||||
|             ::core::debug_assert_ne!($($x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::debug_assert_ne!($($x)*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! todo { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(not(feature = "defmt"))] |  | ||||||
|             ::core::todo!($($x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::todo!($($x)*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! unreachable { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(not(feature = "defmt"))] |  | ||||||
|             ::core::unreachable!($($x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::unreachable!($($x)*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! panic { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(not(feature = "defmt"))] |  | ||||||
|             ::core::panic!($($x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::panic!($($x)*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! trace { |  | ||||||
|     ($s:literal $(, $x:expr)* $(,)?) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(feature = "log")] |  | ||||||
|             ::log::trace!($s $(, $x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::trace!($s $(, $x)*); |  | ||||||
|             #[cfg(not(any(feature = "log", feature="defmt")))] |  | ||||||
|             let _ = ($( & $x ),*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! debug { |  | ||||||
|     ($s:literal $(, $x:expr)* $(,)?) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(feature = "log")] |  | ||||||
|             ::log::debug!($s $(, $x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::debug!($s $(, $x)*); |  | ||||||
|             #[cfg(not(any(feature = "log", feature="defmt")))] |  | ||||||
|             let _ = ($( & $x ),*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! info { |  | ||||||
|     ($s:literal $(, $x:expr)* $(,)?) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(feature = "log")] |  | ||||||
|             ::log::info!($s $(, $x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::info!($s $(, $x)*); |  | ||||||
|             #[cfg(not(any(feature = "log", feature="defmt")))] |  | ||||||
|             let _ = ($( & $x ),*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! warn { |  | ||||||
|     ($s:literal $(, $x:expr)* $(,)?) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(feature = "log")] |  | ||||||
|             ::log::warn!($s $(, $x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::warn!($s $(, $x)*); |  | ||||||
|             #[cfg(not(any(feature = "log", feature="defmt")))] |  | ||||||
|             let _ = ($( & $x ),*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| macro_rules! error { |  | ||||||
|     ($s:literal $(, $x:expr)* $(,)?) => { |  | ||||||
|         { |  | ||||||
|             #[cfg(feature = "log")] |  | ||||||
|             ::log::error!($s $(, $x)*); |  | ||||||
|             #[cfg(feature = "defmt")] |  | ||||||
|             ::defmt::error!($s $(, $x)*); |  | ||||||
|             #[cfg(not(any(feature = "log", feature="defmt")))] |  | ||||||
|             let _ = ($( & $x ),*); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #[cfg(feature = "defmt")] |  | ||||||
| macro_rules! unwrap { |  | ||||||
|     ($($x:tt)*) => { |  | ||||||
|         ::defmt::unwrap!($($x)*) |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #[cfg(not(feature = "defmt"))] |  | ||||||
| macro_rules! unwrap { |  | ||||||
|     ($arg:expr) => { |  | ||||||
|         match $crate::fmt::Try::into_result($arg) { |  | ||||||
|             ::core::result::Result::Ok(t) => t, |  | ||||||
|             ::core::result::Result::Err(e) => { |  | ||||||
|                 ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
|     ($arg:expr, $($msg:expr),+ $(,)? ) => { |  | ||||||
|         match $crate::fmt::Try::into_result($arg) { |  | ||||||
|             ::core::result::Result::Ok(t) => t, |  | ||||||
|             ::core::result::Result::Err(e) => { |  | ||||||
|                 ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #[derive(Debug, Copy, Clone, Eq, PartialEq)] |  | ||||||
| pub struct NoneError; |  | ||||||
|  |  | ||||||
| pub trait Try { |  | ||||||
|     type Ok; |  | ||||||
|     type Error; |  | ||||||
|     fn into_result(self) -> Result<Self::Ok, Self::Error>; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| impl<T> Try for Option<T> { |  | ||||||
|     type Ok = T; |  | ||||||
|     type Error = NoneError; |  | ||||||
|  |  | ||||||
|     #[inline] |  | ||||||
|     fn into_result(self) -> Result<T, NoneError> { |  | ||||||
|         self.ok_or(NoneError) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| impl<T, E> Try for Result<T, E> { |  | ||||||
|     type Ok = T; |  | ||||||
|     type Error = E; |  | ||||||
|  |  | ||||||
|     #[inline] |  | ||||||
|     fn into_result(self) -> Self { |  | ||||||
|         self |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -9,9 +9,20 @@ src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-usb/s | |||||||
| features = ["defmt"] | features = ["defmt"] | ||||||
| target = "thumbv7em-none-eabi" | target = "thumbv7em-none-eabi" | ||||||
|  |  | ||||||
|  | [features] | ||||||
|  | defmt = ["dep:defmt", "embassy-usb-driver/defmt"] | ||||||
|  | usbd-hid = ["dep:usbd-hid", "dep:ssmarshal"] | ||||||
|  | default = ["usbd-hid"] | ||||||
|  |  | ||||||
| [dependencies] | [dependencies] | ||||||
| embassy-futures = { version = "0.1.0", path = "../embassy-futures" } | embassy-futures = { version = "0.1.0", path = "../embassy-futures" } | ||||||
|  | embassy-usb-driver = { version = "0.1.0", path = "../embassy-usb-driver" } | ||||||
|  | embassy-sync = { version = "0.1.0", path = "../embassy-sync" } | ||||||
|  |  | ||||||
| defmt = { version = "0.3", optional = true } | defmt = { version = "0.3", optional = true } | ||||||
| log = { version = "0.4.14", optional = true } | log = { version = "0.4.14", optional = true } | ||||||
| heapless = "0.7.10" | heapless = "0.7.10" | ||||||
|  |  | ||||||
|  | # for HID | ||||||
|  | usbd-hid = { version = "0.6.0", optional = true } | ||||||
|  | ssmarshal = { version = "1.0", default-features = false, optional = true } | ||||||
|   | |||||||
| @@ -1,11 +1,10 @@ | |||||||
| use heapless::Vec; | use heapless::Vec; | ||||||
|  |  | ||||||
| use super::control::ControlHandler; | use crate::control::ControlHandler; | ||||||
| use super::descriptor::{BosWriter, DescriptorWriter}; | use crate::descriptor::{BosWriter, DescriptorWriter}; | ||||||
| use super::driver::{Driver, Endpoint}; | use crate::driver::{Driver, Endpoint, EndpointType}; | ||||||
| use super::types::*; | use crate::types::*; | ||||||
| use super::{DeviceStateHandler, UsbDevice, MAX_INTERFACE_COUNT}; | use crate::{DeviceStateHandler, Interface, UsbDevice, MAX_INTERFACE_COUNT, STRING_INDEX_CUSTOM_START}; | ||||||
| use crate::{Interface, STRING_INDEX_CUSTOM_START}; |  | ||||||
|  |  | ||||||
| #[derive(Debug, Copy, Clone)] | #[derive(Debug, Copy, Clone)] | ||||||
| #[cfg_attr(feature = "defmt", derive(defmt::Format))] | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||||||
|   | |||||||
| @@ -1,18 +1,13 @@ | |||||||
| #![no_std] |  | ||||||
| #![feature(type_alias_impl_trait)] |  | ||||||
| 
 |  | ||||||
| // This mod MUST go first, so that the others see its macros.
 |  | ||||||
| pub(crate) mod fmt; |  | ||||||
| 
 |  | ||||||
| use core::cell::Cell; | use core::cell::Cell; | ||||||
| use core::mem::{self, MaybeUninit}; | use core::mem::{self, MaybeUninit}; | ||||||
| use core::sync::atomic::{AtomicBool, Ordering}; | use core::sync::atomic::{AtomicBool, Ordering}; | ||||||
| 
 | 
 | ||||||
| use embassy_sync::blocking_mutex::CriticalSectionMutex; | use embassy_sync::blocking_mutex::CriticalSectionMutex; | ||||||
| use embassy_usb::control::{self, ControlHandler, InResponse, OutResponse, Request}; | 
 | ||||||
| use embassy_usb::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; | use crate::control::{self, ControlHandler, InResponse, OutResponse, Request}; | ||||||
| use embassy_usb::types::*; | use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; | ||||||
| use embassy_usb::Builder; | use crate::types::*; | ||||||
|  | use crate::Builder; | ||||||
| 
 | 
 | ||||||
| /// This should be used as `device_class` when building the `UsbDevice`.
 | /// This should be used as `device_class` when building the `UsbDevice`.
 | ||||||
| pub const USB_CLASS_CDC: u8 = 0x02; | pub const USB_CLASS_CDC: u8 = 0x02; | ||||||
| @@ -1,15 +1,10 @@ | |||||||
| #![no_std] |  | ||||||
| 
 |  | ||||||
| // This mod MUST go first, so that the others see its macros.
 |  | ||||||
| pub(crate) mod fmt; |  | ||||||
| 
 |  | ||||||
| use core::intrinsics::copy_nonoverlapping; | use core::intrinsics::copy_nonoverlapping; | ||||||
| use core::mem::{size_of, MaybeUninit}; | use core::mem::{size_of, MaybeUninit}; | ||||||
| 
 | 
 | ||||||
| use embassy_usb::control::{self, ControlHandler, InResponse, OutResponse, Request}; | use crate::control::{self, ControlHandler, InResponse, OutResponse, Request}; | ||||||
| use embassy_usb::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; | use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; | ||||||
| use embassy_usb::types::*; | use crate::types::*; | ||||||
| use embassy_usb::Builder; | use crate::Builder; | ||||||
| 
 | 
 | ||||||
| /// This should be used as `device_class` when building the `UsbDevice`.
 | /// This should be used as `device_class` when building the `UsbDevice`.
 | ||||||
| pub const USB_CLASS_CDC: u8 = 0x02; | pub const USB_CLASS_CDC: u8 = 0x02; | ||||||
| @@ -1,23 +1,16 @@ | |||||||
| #![no_std] |  | ||||||
| #![feature(type_alias_impl_trait)] |  | ||||||
| 
 |  | ||||||
| //! Implements HID functionality for a usb-device device.
 |  | ||||||
| 
 |  | ||||||
| // This mod MUST go first, so that the others see its macros.
 |  | ||||||
| pub(crate) mod fmt; |  | ||||||
| 
 |  | ||||||
| use core::mem::MaybeUninit; | use core::mem::MaybeUninit; | ||||||
| use core::ops::Range; | use core::ops::Range; | ||||||
| use core::sync::atomic::{AtomicUsize, Ordering}; | use core::sync::atomic::{AtomicUsize, Ordering}; | ||||||
| 
 | 
 | ||||||
| use embassy_usb::control::{ControlHandler, InResponse, OutResponse, Request, RequestType}; |  | ||||||
| use embassy_usb::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; |  | ||||||
| use embassy_usb::Builder; |  | ||||||
| #[cfg(feature = "usbd-hid")] | #[cfg(feature = "usbd-hid")] | ||||||
| use ssmarshal::serialize; | use ssmarshal::serialize; | ||||||
| #[cfg(feature = "usbd-hid")] | #[cfg(feature = "usbd-hid")] | ||||||
| use usbd_hid::descriptor::AsInputReport; | use usbd_hid::descriptor::AsInputReport; | ||||||
| 
 | 
 | ||||||
|  | use crate::control::{ControlHandler, InResponse, OutResponse, Request, RequestType}; | ||||||
|  | use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; | ||||||
|  | use crate::Builder; | ||||||
|  | 
 | ||||||
| const USB_CLASS_HID: u8 = 0x03; | const USB_CLASS_HID: u8 = 0x03; | ||||||
| const USB_SUBCLASS_NONE: u8 = 0x00; | const USB_SUBCLASS_NONE: u8 = 0x00; | ||||||
| const USB_PROTOCOL_NONE: u8 = 0x00; | const USB_PROTOCOL_NONE: u8 = 0x00; | ||||||
| @@ -204,9 +197,9 @@ pub enum ReadError { | |||||||
|     Sync(Range<usize>), |     Sync(Range<usize>), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl From<embassy_usb::driver::EndpointError> for ReadError { | impl From<EndpointError> for ReadError { | ||||||
|     fn from(val: embassy_usb::driver::EndpointError) -> Self { |     fn from(val: EndpointError) -> Self { | ||||||
|         use embassy_usb::driver::EndpointError::*; |         use EndpointError::*; | ||||||
|         match val { |         match val { | ||||||
|             BufferOverflow => ReadError::BufferOverflow, |             BufferOverflow => ReadError::BufferOverflow, | ||||||
|             Disabled => ReadError::Disabled, |             Disabled => ReadError::Disabled, | ||||||
| @@ -437,7 +430,7 @@ impl<'d> ControlHandler for Control<'d> { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn control_out(&mut self, req: embassy_usb::control::Request, data: &[u8]) -> OutResponse { |     fn control_out(&mut self, req: Request, data: &[u8]) -> OutResponse { | ||||||
|         trace!("HID control_out {:?} {=[u8]:x}", req, data); |         trace!("HID control_out {:?} {=[u8]:x}", req, data); | ||||||
|         if let RequestType::Class = req.request_type { |         if let RequestType::Class = req.request_type { | ||||||
|             match req.request { |             match req.request { | ||||||
							
								
								
									
										3
									
								
								embassy-usb/src/class/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								embassy-usb/src/class/mod.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | pub mod cdc_acm; | ||||||
|  | pub mod cdc_ncm; | ||||||
|  | pub mod hid; | ||||||
| @@ -1,7 +1,8 @@ | |||||||
| //! USB control data types. | //! USB control data types. | ||||||
| use core::mem; | use core::mem; | ||||||
|  |  | ||||||
| use super::types::*; | use crate::driver::Direction; | ||||||
|  | use crate::types::StringIndex; | ||||||
|  |  | ||||||
| /// Control request type. | /// Control request type. | ||||||
| #[repr(u8)] | #[repr(u8)] | ||||||
| @@ -42,7 +43,7 @@ pub enum Recipient { | |||||||
| #[cfg_attr(feature = "defmt", derive(defmt::Format))] | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||||||
| pub struct Request { | pub struct Request { | ||||||
|     /// Direction of the request. |     /// Direction of the request. | ||||||
|     pub direction: UsbDirection, |     pub direction: Direction, | ||||||
|     /// Type of the request. |     /// Type of the request. | ||||||
|     pub request_type: RequestType, |     pub request_type: RequestType, | ||||||
|     /// Recipient of the request. |     /// Recipient of the request. | ||||||
| @@ -105,7 +106,7 @@ impl Request { | |||||||
|         let recipient = rt & 0b11111; |         let recipient = rt & 0b11111; | ||||||
|  |  | ||||||
|         Request { |         Request { | ||||||
|             direction: rt.into(), |             direction: if rt & 0x80 == 0 { Direction::Out } else { Direction::In }, | ||||||
|             request_type: unsafe { mem::transmute((rt >> 5) & 0b11) }, |             request_type: unsafe { mem::transmute((rt >> 5) & 0b11) }, | ||||||
|             recipient: if recipient <= 3 { |             recipient: if recipient <= 3 { | ||||||
|                 unsafe { mem::transmute(recipient) } |                 unsafe { mem::transmute(recipient) } | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| use super::builder::Config; | use crate::builder::Config; | ||||||
| use super::types::*; | use crate::driver::EndpointInfo; | ||||||
| use super::CONFIGURATION_VALUE; | use crate::types::*; | ||||||
|  | use crate::CONFIGURATION_VALUE; | ||||||
|  |  | ||||||
| /// Standard descriptor types | /// Standard descriptor types | ||||||
| #[allow(missing_docs)] | #[allow(missing_docs)] | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| use crate::descriptor::descriptor_type; | use crate::descriptor::descriptor_type; | ||||||
| use crate::types::EndpointAddress; | use crate::driver::EndpointAddress; | ||||||
|  |  | ||||||
| #[derive(Copy, Clone, PartialEq, Eq, Debug)] | #[derive(Copy, Clone, PartialEq, Eq, Debug)] | ||||||
| #[cfg_attr(feature = "defmt", derive(defmt::Format))] | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||||||
|   | |||||||
| @@ -4,23 +4,24 @@ | |||||||
| // This mod MUST go first, so that the others see its macros. | // This mod MUST go first, so that the others see its macros. | ||||||
| pub(crate) mod fmt; | pub(crate) mod fmt; | ||||||
|  |  | ||||||
|  | pub use embassy_usb_driver as driver; | ||||||
|  |  | ||||||
| mod builder; | mod builder; | ||||||
|  | pub mod class; | ||||||
| pub mod control; | pub mod control; | ||||||
| pub mod descriptor; | pub mod descriptor; | ||||||
| mod descriptor_reader; | mod descriptor_reader; | ||||||
| pub mod driver; |  | ||||||
| pub mod types; | pub mod types; | ||||||
|  |  | ||||||
| use embassy_futures::select::{select, Either}; | use embassy_futures::select::{select, Either}; | ||||||
| use heapless::Vec; | use heapless::Vec; | ||||||
|  |  | ||||||
| pub use self::builder::{Builder, Config}; | pub use crate::builder::{Builder, Config}; | ||||||
| use self::control::*; | use crate::control::*; | ||||||
| use self::descriptor::*; | use crate::descriptor::*; | ||||||
| use self::driver::{Bus, Driver, Event}; |  | ||||||
| use self::types::*; |  | ||||||
| use crate::descriptor_reader::foreach_endpoint; | use crate::descriptor_reader::foreach_endpoint; | ||||||
| use crate::driver::ControlPipe; | use crate::driver::{Bus, ControlPipe, Direction, Driver, EndpointAddress, Event}; | ||||||
|  | use crate::types::*; | ||||||
|  |  | ||||||
| /// The global state of the USB device. | /// The global state of the USB device. | ||||||
| /// | /// | ||||||
| @@ -250,8 +251,8 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||||||
|         trace!("control request: {:?}", req); |         trace!("control request: {:?}", req); | ||||||
|  |  | ||||||
|         match req.direction { |         match req.direction { | ||||||
|             UsbDirection::In => self.handle_control_in(req).await, |             Direction::In => self.handle_control_in(req).await, | ||||||
|             UsbDirection::Out => self.handle_control_out(req).await, |             Direction::Out => self.handle_control_out(req).await, | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if self.inner.set_address_pending { |         if self.inner.set_address_pending { | ||||||
|   | |||||||
| @@ -1,108 +1,3 @@ | |||||||
| /// Direction of USB traffic. Note that in the USB standard the direction is always indicated from |  | ||||||
| /// the perspective of the host, which is backward for devices, but the standard directions are used |  | ||||||
| /// for consistency. |  | ||||||
| /// |  | ||||||
| /// The values of the enum also match the direction bit used in endpoint addresses and control |  | ||||||
| /// request types. |  | ||||||
| #[repr(u8)] |  | ||||||
| #[derive(Copy, Clone, Eq, PartialEq, Debug)] |  | ||||||
| #[cfg_attr(feature = "defmt", derive(defmt::Format))] |  | ||||||
| pub enum UsbDirection { |  | ||||||
|     /// Host to device (OUT) |  | ||||||
|     Out = 0x00, |  | ||||||
|     /// Device to host (IN) |  | ||||||
|     In = 0x80, |  | ||||||
| } |  | ||||||
|  |  | ||||||
| impl From<u8> for UsbDirection { |  | ||||||
|     fn from(value: u8) -> Self { |  | ||||||
|         unsafe { core::mem::transmute(value & 0x80) } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// USB endpoint transfer type. The values of this enum can be directly cast into `u8` to get the |  | ||||||
| /// transfer bmAttributes transfer type bits. |  | ||||||
| #[repr(u8)] |  | ||||||
| #[derive(Copy, Clone, Eq, PartialEq, Debug)] |  | ||||||
| #[cfg_attr(feature = "defmt", derive(defmt::Format))] |  | ||||||
| pub enum EndpointType { |  | ||||||
|     /// Control endpoint. Used for device management. Only the host can initiate requests. Usually |  | ||||||
|     /// used only endpoint 0. |  | ||||||
|     Control = 0b00, |  | ||||||
|     /// Isochronous endpoint. Used for time-critical unreliable data. Not implemented yet. |  | ||||||
|     Isochronous = 0b01, |  | ||||||
|     /// Bulk endpoint. Used for large amounts of best-effort reliable data. |  | ||||||
|     Bulk = 0b10, |  | ||||||
|     /// Interrupt endpoint. Used for small amounts of time-critical reliable data. |  | ||||||
|     Interrupt = 0b11, |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// Type-safe endpoint address. |  | ||||||
| #[derive(Debug, Clone, Copy, Eq, PartialEq)] |  | ||||||
| #[cfg_attr(feature = "defmt", derive(defmt::Format))] |  | ||||||
| pub struct EndpointAddress(u8); |  | ||||||
|  |  | ||||||
| impl From<u8> for EndpointAddress { |  | ||||||
|     #[inline] |  | ||||||
|     fn from(addr: u8) -> EndpointAddress { |  | ||||||
|         EndpointAddress(addr) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| impl From<EndpointAddress> for u8 { |  | ||||||
|     #[inline] |  | ||||||
|     fn from(addr: EndpointAddress) -> u8 { |  | ||||||
|         addr.0 |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| impl EndpointAddress { |  | ||||||
|     const INBITS: u8 = UsbDirection::In as u8; |  | ||||||
|  |  | ||||||
|     /// Constructs a new EndpointAddress with the given index and direction. |  | ||||||
|     #[inline] |  | ||||||
|     pub fn from_parts(index: usize, dir: UsbDirection) -> Self { |  | ||||||
|         EndpointAddress(index as u8 | dir as u8) |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// Gets the direction part of the address. |  | ||||||
|     #[inline] |  | ||||||
|     pub fn direction(&self) -> UsbDirection { |  | ||||||
|         if (self.0 & Self::INBITS) != 0 { |  | ||||||
|             UsbDirection::In |  | ||||||
|         } else { |  | ||||||
|             UsbDirection::Out |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// Returns true if the direction is IN, otherwise false. |  | ||||||
|     #[inline] |  | ||||||
|     pub fn is_in(&self) -> bool { |  | ||||||
|         (self.0 & Self::INBITS) != 0 |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// Returns true if the direction is OUT, otherwise false. |  | ||||||
|     #[inline] |  | ||||||
|     pub fn is_out(&self) -> bool { |  | ||||||
|         (self.0 & Self::INBITS) == 0 |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// Gets the index part of the endpoint address. |  | ||||||
|     #[inline] |  | ||||||
|     pub fn index(&self) -> usize { |  | ||||||
|         (self.0 & !Self::INBITS) as usize |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #[derive(Copy, Clone, Eq, PartialEq, Debug)] |  | ||||||
| #[cfg_attr(feature = "defmt", derive(defmt::Format))] |  | ||||||
| pub struct EndpointInfo { |  | ||||||
|     pub addr: EndpointAddress, |  | ||||||
|     pub ep_type: EndpointType, |  | ||||||
|     pub max_packet_size: u16, |  | ||||||
|     pub interval: u8, |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// A handle for a USB interface that contains its number. | /// A handle for a USB interface that contains its number. | ||||||
| #[derive(Copy, Clone, Eq, PartialEq)] | #[derive(Copy, Clone, Eq, PartialEq)] | ||||||
| #[cfg_attr(feature = "defmt", derive(defmt::Format))] | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ version = "0.1.0" | |||||||
|  |  | ||||||
| [features] | [features] | ||||||
| default = ["nightly"] | default = ["nightly"] | ||||||
| nightly = ["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"] | nightly = ["embassy-executor/nightly", "embassy-nrf/nightly", "embassy-net/nightly", "embassy-nrf/unstable-traits", "embassy-usb", "embedded-io/async", "embassy-net"] | ||||||
|  |  | ||||||
| [dependencies] | [dependencies] | ||||||
| embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | ||||||
| @@ -15,9 +15,6 @@ embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["de | |||||||
| embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } | embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } | ||||||
| embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "pool-16"], optional = true } | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "pool-16"], optional = true } | ||||||
| embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"], optional = true } | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"], optional = true } | ||||||
| embassy-usb-serial = { version = "0.1.0", path = "../../embassy-usb-serial", features = ["defmt"], optional = true } |  | ||||||
| embassy-usb-hid = { version = "0.1.0", path = "../../embassy-usb-hid", features = ["defmt"], optional = true } |  | ||||||
| embassy-usb-ncm = { version = "0.1.0", path = "../../embassy-usb-ncm", features = ["defmt"], optional = true } |  | ||||||
| embedded-io = "0.3.0" | embedded-io = "0.3.0" | ||||||
|  |  | ||||||
| defmt = "0.3" | defmt = "0.3" | ||||||
|   | |||||||
| @@ -15,8 +15,8 @@ use embassy_nrf::usb::{Driver, PowerUsb}; | |||||||
| use embassy_nrf::{interrupt, pac, peripherals}; | use embassy_nrf::{interrupt, pac, peripherals}; | ||||||
| use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; | ||||||
| use embassy_sync::channel::Channel; | use embassy_sync::channel::Channel; | ||||||
|  | use embassy_usb::class::cdc_ncm::{CdcNcmClass, Receiver, Sender, State}; | ||||||
| use embassy_usb::{Builder, Config, UsbDevice}; | use embassy_usb::{Builder, Config, UsbDevice}; | ||||||
| use embassy_usb_ncm::{CdcNcmClass, Receiver, Sender, State}; |  | ||||||
| use embedded_io::asynch::Write; | use embedded_io::asynch::Write; | ||||||
| use static_cell::StaticCell; | use static_cell::StaticCell; | ||||||
| use {defmt_rtt as _, panic_probe as _}; | use {defmt_rtt as _, panic_probe as _}; | ||||||
|   | |||||||
| @@ -14,9 +14,9 @@ use embassy_nrf::usb::{Driver, PowerUsb}; | |||||||
| use embassy_nrf::{interrupt, pac}; | use embassy_nrf::{interrupt, pac}; | ||||||
| use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | ||||||
| use embassy_sync::signal::Signal; | use embassy_sync::signal::Signal; | ||||||
|  | use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; | ||||||
| use embassy_usb::control::OutResponse; | use embassy_usb::control::OutResponse; | ||||||
| use embassy_usb::{Builder, Config, DeviceStateHandler}; | use embassy_usb::{Builder, Config, DeviceStateHandler}; | ||||||
| use embassy_usb_hid::{HidReaderWriter, ReportId, RequestHandler, State}; |  | ||||||
| use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; | ||||||
| use {defmt_rtt as _, panic_probe as _}; | use {defmt_rtt as _, panic_probe as _}; | ||||||
|  |  | ||||||
| @@ -67,7 +67,7 @@ async fn main(_spawner: Spawner) { | |||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     // Create classes on the builder. |     // Create classes on the builder. | ||||||
|     let config = embassy_usb_hid::Config { |     let config = embassy_usb::class::hid::Config { | ||||||
|         report_descriptor: KeyboardReport::desc(), |         report_descriptor: KeyboardReport::desc(), | ||||||
|         request_handler: Some(&request_handler), |         request_handler: Some(&request_handler), | ||||||
|         poll_ms: 60, |         poll_ms: 60, | ||||||
|   | |||||||
| @@ -10,9 +10,9 @@ use embassy_futures::join::join; | |||||||
| use embassy_nrf::usb::{Driver, PowerUsb}; | use embassy_nrf::usb::{Driver, PowerUsb}; | ||||||
| use embassy_nrf::{interrupt, pac}; | use embassy_nrf::{interrupt, pac}; | ||||||
| use embassy_time::{Duration, Timer}; | use embassy_time::{Duration, Timer}; | ||||||
|  | use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State}; | ||||||
| use embassy_usb::control::OutResponse; | use embassy_usb::control::OutResponse; | ||||||
| use embassy_usb::{Builder, Config}; | use embassy_usb::{Builder, Config}; | ||||||
| use embassy_usb_hid::{HidWriter, ReportId, RequestHandler, State}; |  | ||||||
| use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; | ||||||
| use {defmt_rtt as _, panic_probe as _}; | use {defmt_rtt as _, panic_probe as _}; | ||||||
|  |  | ||||||
| @@ -59,7 +59,7 @@ async fn main(_spawner: Spawner) { | |||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     // Create classes on the builder. |     // Create classes on the builder. | ||||||
|     let config = embassy_usb_hid::Config { |     let config = embassy_usb::class::hid::Config { | ||||||
|         report_descriptor: MouseReport::desc(), |         report_descriptor: MouseReport::desc(), | ||||||
|         request_handler: Some(&request_handler), |         request_handler: Some(&request_handler), | ||||||
|         poll_ms: 60, |         poll_ms: 60, | ||||||
|   | |||||||
| @@ -9,9 +9,9 @@ use embassy_executor::Spawner; | |||||||
| use embassy_futures::join::join; | use embassy_futures::join::join; | ||||||
| use embassy_nrf::usb::{Driver, Instance, PowerUsb, UsbSupply}; | use embassy_nrf::usb::{Driver, Instance, PowerUsb, UsbSupply}; | ||||||
| use embassy_nrf::{interrupt, pac}; | use embassy_nrf::{interrupt, pac}; | ||||||
|  | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | ||||||
| use embassy_usb::driver::EndpointError; | use embassy_usb::driver::EndpointError; | ||||||
| use embassy_usb::{Builder, Config}; | use embassy_usb::{Builder, Config}; | ||||||
| use embassy_usb_serial::{CdcAcmClass, State}; |  | ||||||
| use {defmt_rtt as _, panic_probe as _}; | use {defmt_rtt as _, panic_probe as _}; | ||||||
|  |  | ||||||
| #[embassy_executor::main] | #[embassy_executor::main] | ||||||
|   | |||||||
| @@ -8,9 +8,9 @@ use defmt::{info, panic, unwrap}; | |||||||
| use embassy_executor::Spawner; | use embassy_executor::Spawner; | ||||||
| use embassy_nrf::usb::{Driver, PowerUsb}; | use embassy_nrf::usb::{Driver, PowerUsb}; | ||||||
| use embassy_nrf::{interrupt, pac, peripherals}; | use embassy_nrf::{interrupt, pac, peripherals}; | ||||||
|  | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | ||||||
| use embassy_usb::driver::EndpointError; | use embassy_usb::driver::EndpointError; | ||||||
| use embassy_usb::{Builder, Config, UsbDevice}; | use embassy_usb::{Builder, Config, UsbDevice}; | ||||||
| use embassy_usb_serial::{CdcAcmClass, State}; |  | ||||||
| use static_cell::StaticCell; | use static_cell::StaticCell; | ||||||
| use {defmt_rtt as _, panic_probe as _}; | use {defmt_rtt as _, panic_probe as _}; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -10,9 +10,7 @@ embassy-executor = { version = "0.1.0", path = "../../embassy-executor", feature | |||||||
| embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | ||||||
| embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver"] } | embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver"] } | ||||||
| embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } | ||||||
| embassy-usb-serial = { version = "0.1.0", path = "../../embassy-usb-serial", features = ["defmt"] } |  | ||||||
| embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "pool-16"] } | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "pool-16"] } | ||||||
| embassy-usb-ncm = { version = "0.1.0", path = "../../embassy-usb-ncm", features = ["defmt"] } |  | ||||||
| embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | ||||||
|  |  | ||||||
| defmt = "0.3" | defmt = "0.3" | ||||||
|   | |||||||
| @@ -13,8 +13,8 @@ use embassy_rp::usb::Driver; | |||||||
| use embassy_rp::{interrupt, peripherals}; | use embassy_rp::{interrupt, peripherals}; | ||||||
| use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; | ||||||
| use embassy_sync::channel::Channel; | use embassy_sync::channel::Channel; | ||||||
|  | use embassy_usb::class::cdc_ncm::{CdcNcmClass, Receiver, Sender, State}; | ||||||
| use embassy_usb::{Builder, Config, UsbDevice}; | use embassy_usb::{Builder, Config, UsbDevice}; | ||||||
| use embassy_usb_ncm::{CdcNcmClass, Receiver, Sender, State}; |  | ||||||
| use embedded_io::asynch::Write; | use embedded_io::asynch::Write; | ||||||
| use static_cell::StaticCell; | use static_cell::StaticCell; | ||||||
| use {defmt_rtt as _, panic_probe as _}; | use {defmt_rtt as _, panic_probe as _}; | ||||||
|   | |||||||
| @@ -7,9 +7,9 @@ use embassy_executor::Spawner; | |||||||
| use embassy_futures::join::join; | use embassy_futures::join::join; | ||||||
| use embassy_rp::interrupt; | use embassy_rp::interrupt; | ||||||
| use embassy_rp::usb::{Driver, Instance}; | use embassy_rp::usb::{Driver, Instance}; | ||||||
|  | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | ||||||
| use embassy_usb::driver::EndpointError; | use embassy_usb::driver::EndpointError; | ||||||
| use embassy_usb::{Builder, Config}; | use embassy_usb::{Builder, Config}; | ||||||
| use embassy_usb_serial::{CdcAcmClass, State}; |  | ||||||
| use {defmt_rtt as _, panic_probe as _}; | use {defmt_rtt as _, panic_probe as _}; | ||||||
|  |  | ||||||
| #[embassy_executor::main] | #[embassy_executor::main] | ||||||
|   | |||||||
| @@ -9,7 +9,6 @@ embassy-executor = { version = "0.1.0", path = "../../embassy-executor", feature | |||||||
| embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | ||||||
| embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any"]  } | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any"]  } | ||||||
| embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } | ||||||
| embassy-usb-serial = { version = "0.1.0", path = "../../embassy-usb-serial", features = ["defmt"] } |  | ||||||
| embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | ||||||
|  |  | ||||||
| defmt = "0.3" | defmt = "0.3" | ||||||
|   | |||||||
| @@ -10,9 +10,9 @@ use embassy_stm32::time::Hertz; | |||||||
| use embassy_stm32::usb::{Driver, Instance}; | use embassy_stm32::usb::{Driver, Instance}; | ||||||
| use embassy_stm32::{interrupt, Config}; | use embassy_stm32::{interrupt, Config}; | ||||||
| use embassy_time::{Duration, Timer}; | use embassy_time::{Duration, Timer}; | ||||||
|  | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | ||||||
| use embassy_usb::driver::EndpointError; | use embassy_usb::driver::EndpointError; | ||||||
| use embassy_usb::Builder; | use embassy_usb::Builder; | ||||||
| use embassy_usb_serial::{CdcAcmClass, State}; |  | ||||||
| use {defmt_rtt as _, panic_probe as _}; | use {defmt_rtt as _, panic_probe as _}; | ||||||
|  |  | ||||||
| #[embassy_executor::main] | #[embassy_executor::main] | ||||||
|   | |||||||
| @@ -9,8 +9,6 @@ embassy-executor = { version = "0.1.0", path = "../../embassy-executor", feature | |||||||
| embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | ||||||
| embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-any", "exti"]  } | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-any", "exti"]  } | ||||||
| embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } | ||||||
| embassy-usb-serial = { version = "0.1.0", path = "../../embassy-usb-serial", features = ["defmt"] } |  | ||||||
| embassy-usb-hid = { version = "0.1.0", path = "../../embassy-usb-hid", features = ["defmt"] } |  | ||||||
| embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | ||||||
|  |  | ||||||
| defmt = "0.3" | defmt = "0.3" | ||||||
|   | |||||||
| @@ -10,9 +10,9 @@ use embassy_stm32::time::mhz; | |||||||
| use embassy_stm32::usb::{Driver, Instance}; | use embassy_stm32::usb::{Driver, Instance}; | ||||||
| use embassy_stm32::{interrupt, Config}; | use embassy_stm32::{interrupt, Config}; | ||||||
| use embassy_time::{Duration, Timer}; | use embassy_time::{Duration, Timer}; | ||||||
|  | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | ||||||
| use embassy_usb::driver::EndpointError; | use embassy_usb::driver::EndpointError; | ||||||
| use embassy_usb::Builder; | use embassy_usb::Builder; | ||||||
| use embassy_usb_serial::{CdcAcmClass, State}; |  | ||||||
| use {defmt_rtt as _, panic_probe as _}; | use {defmt_rtt as _, panic_probe as _}; | ||||||
|  |  | ||||||
| #[embassy_executor::main] | #[embassy_executor::main] | ||||||
|   | |||||||
| @@ -11,9 +11,6 @@ embassy-executor = { version = "0.1.0", path = "../../embassy-executor", feature | |||||||
| embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | ||||||
| embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "unstable-traits", "memory-x"]  } | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "unstable-traits", "memory-x"]  } | ||||||
| embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } | ||||||
| embassy-usb-serial = { version = "0.1.0", path = "../../embassy-usb-serial", features = ["defmt"] } |  | ||||||
| embassy-usb-hid = { version = "0.1.0", path = "../../embassy-usb-hid", features = ["defmt"] } |  | ||||||
| embassy-usb-ncm = { version = "0.1.0", path = "../../embassy-usb-ncm", features = ["defmt"] } |  | ||||||
| embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "pool-16"] } | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "pool-16"] } | ||||||
| embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | ||||||
| usbd-hid = "0.6.0" | usbd-hid = "0.6.0" | ||||||
|   | |||||||
| @@ -15,8 +15,8 @@ use embassy_stm32::usb::Driver; | |||||||
| use embassy_stm32::{interrupt, Config}; | use embassy_stm32::{interrupt, Config}; | ||||||
| use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; | ||||||
| use embassy_sync::channel::Channel; | use embassy_sync::channel::Channel; | ||||||
|  | use embassy_usb::class::cdc_ncm::{CdcNcmClass, Receiver, Sender, State}; | ||||||
| use embassy_usb::{Builder, UsbDevice}; | use embassy_usb::{Builder, UsbDevice}; | ||||||
| use embassy_usb_ncm::{CdcNcmClass, Receiver, Sender, State}; |  | ||||||
| use embedded_io::asynch::Write; | use embedded_io::asynch::Write; | ||||||
| use rand_core::RngCore; | use rand_core::RngCore; | ||||||
| use static_cell::StaticCell; | use static_cell::StaticCell; | ||||||
|   | |||||||
| @@ -9,9 +9,9 @@ use embassy_stm32::rcc::*; | |||||||
| use embassy_stm32::usb::Driver; | use embassy_stm32::usb::Driver; | ||||||
| use embassy_stm32::{interrupt, Config}; | use embassy_stm32::{interrupt, Config}; | ||||||
| use embassy_time::{Duration, Timer}; | use embassy_time::{Duration, Timer}; | ||||||
|  | use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State}; | ||||||
| use embassy_usb::control::OutResponse; | use embassy_usb::control::OutResponse; | ||||||
| use embassy_usb::Builder; | use embassy_usb::Builder; | ||||||
| use embassy_usb_hid::{HidWriter, ReportId, RequestHandler, State}; |  | ||||||
| use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; | ||||||
| use {defmt_rtt as _, panic_probe as _}; | use {defmt_rtt as _, panic_probe as _}; | ||||||
|  |  | ||||||
| @@ -55,7 +55,7 @@ async fn main(_spawner: Spawner) { | |||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     // Create classes on the builder. |     // Create classes on the builder. | ||||||
|     let config = embassy_usb_hid::Config { |     let config = embassy_usb::class::hid::Config { | ||||||
|         report_descriptor: MouseReport::desc(), |         report_descriptor: MouseReport::desc(), | ||||||
|         request_handler: Some(&request_handler), |         request_handler: Some(&request_handler), | ||||||
|         poll_ms: 60, |         poll_ms: 60, | ||||||
|   | |||||||
| @@ -8,9 +8,9 @@ use embassy_futures::join::join; | |||||||
| use embassy_stm32::rcc::*; | use embassy_stm32::rcc::*; | ||||||
| use embassy_stm32::usb::{Driver, Instance}; | use embassy_stm32::usb::{Driver, Instance}; | ||||||
| use embassy_stm32::{interrupt, Config}; | use embassy_stm32::{interrupt, Config}; | ||||||
|  | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | ||||||
| use embassy_usb::driver::EndpointError; | use embassy_usb::driver::EndpointError; | ||||||
| use embassy_usb::Builder; | use embassy_usb::Builder; | ||||||
| use embassy_usb_serial::{CdcAcmClass, State}; |  | ||||||
| use {defmt_rtt as _, panic_probe as _}; | use {defmt_rtt as _, panic_probe as _}; | ||||||
|  |  | ||||||
| #[embassy_executor::main] | #[embassy_executor::main] | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user