aboutsummaryrefslogtreecommitdiff
path: root/embassy-usb/src/class/cdc_ncm/mod.rs
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-01-31 22:27:19 +0100
committerDario Nieuwenhuis <[email protected]>2023-01-31 22:27:19 +0100
commitca10fe7135d10084e38038f3cd433da39e505bea (patch)
tree075aca4a76caccd1bba95869c64bbb838969c8b1 /embassy-usb/src/class/cdc_ncm/mod.rs
parent4c1946454874597c358e7c7d5bf555b687376a5b (diff)
usb: docs
Diffstat (limited to 'embassy-usb/src/class/cdc_ncm/mod.rs')
-rw-r--r--embassy-usb/src/class/cdc_ncm/mod.rs51
1 files changed, 35 insertions, 16 deletions
diff --git a/embassy-usb/src/class/cdc_ncm/mod.rs b/embassy-usb/src/class/cdc_ncm/mod.rs
index 4954a65bc..5e59b72fe 100644
--- a/embassy-usb/src/class/cdc_ncm/mod.rs
+++ b/embassy-usb/src/class/cdc_ncm/mod.rs
@@ -1,18 +1,19 @@
1/// CDC-NCM, aka Ethernet over USB. 1//! CDC-NCM class implementation, aka Ethernet over USB.
2/// 2//!
3/// # Compatibility 3//! # Compatibility
4/// 4//!
5/// Windows: NOT supported in Windows 10. Supported in Windows 11. 5//! Windows: NOT supported in Windows 10 (though there's apparently a driver you can install?). Supported out of the box in Windows 11.
6/// 6//!
7/// Linux: Well-supported since forever. 7//! Linux: Well-supported since forever.
8/// 8//!
9/// Android: Support for CDC-NCM is spotty and varies across manufacturers. 9//! Android: Support for CDC-NCM is spotty and varies across manufacturers.
10/// 10//!
11/// - On Pixel 4a, it refused to work on Android 11, worked on Android 12. 11//! - On Pixel 4a, it refused to work on Android 11, worked on Android 12.
12/// - if the host's MAC address has the "locally-administered" bit set (bit 1 of first byte), 12//! - if the host's MAC address has the "locally-administered" bit set (bit 1 of first byte),
13/// it doesn't work! The "Ethernet tethering" option in settings doesn't get enabled. 13//! it doesn't work! The "Ethernet tethering" option in settings doesn't get enabled.
14/// This is due to regex spaghetti: https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-mainline-12.0.0_r84/core/res/res/values/config.xml#417 14//! This is due to regex spaghetti: https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-mainline-12.0.0_r84/core/res/res/values/config.xml#417
15/// and this nonsense in the linux kernel: https://github.com/torvalds/linux/blob/c00c5e1d157bec0ef0b0b59aa5482eb8dc7e8e49/drivers/net/usb/usbnet.c#L1751-L1757 15//! and this nonsense in the linux kernel: https://github.com/torvalds/linux/blob/c00c5e1d157bec0ef0b0b59aa5482eb8dc7e8e49/drivers/net/usb/usbnet.c#L1751-L1757
16
16use core::intrinsics::copy_nonoverlapping; 17use core::intrinsics::copy_nonoverlapping;
17use core::mem::{size_of, MaybeUninit}; 18use core::mem::{size_of, MaybeUninit};
18 19
@@ -114,6 +115,7 @@ fn byteify<T>(buf: &mut [u8], data: T) -> &[u8] {
114 &buf[..len] 115 &buf[..len]
115} 116}
116 117
118/// Internal state for the CDC-NCM class.
117pub struct State<'a> { 119pub struct State<'a> {
118 comm_control: MaybeUninit<CommControl<'a>>, 120 comm_control: MaybeUninit<CommControl<'a>>,
119 data_control: MaybeUninit<DataControl>, 121 data_control: MaybeUninit<DataControl>,
@@ -121,6 +123,7 @@ pub struct State<'a> {
121} 123}
122 124
123impl<'a> State<'a> { 125impl<'a> State<'a> {
126 /// Create a new `State`.
124 pub fn new() -> Self { 127 pub fn new() -> Self {
125 Self { 128 Self {
126 comm_control: MaybeUninit::uninit(), 129 comm_control: MaybeUninit::uninit(),
@@ -223,6 +226,7 @@ impl ControlHandler for DataControl {
223 } 226 }
224} 227}
225 228
229/// CDC-NCM class
226pub struct CdcNcmClass<'d, D: Driver<'d>> { 230pub struct CdcNcmClass<'d, D: Driver<'d>> {
227 _comm_if: InterfaceNumber, 231 _comm_if: InterfaceNumber,
228 comm_ep: D::EndpointIn, 232 comm_ep: D::EndpointIn,
@@ -235,6 +239,7 @@ pub struct CdcNcmClass<'d, D: Driver<'d>> {
235} 239}
236 240
237impl<'d, D: Driver<'d>> CdcNcmClass<'d, D> { 241impl<'d, D: Driver<'d>> CdcNcmClass<'d, D> {
242 /// Create a new CDC NCM class.
238 pub fn new( 243 pub fn new(
239 builder: &mut Builder<'d, D>, 244 builder: &mut Builder<'d, D>,
240 state: &'d mut State<'d>, 245 state: &'d mut State<'d>,
@@ -319,6 +324,9 @@ impl<'d, D: Driver<'d>> CdcNcmClass<'d, D> {
319 } 324 }
320 } 325 }
321 326
327 /// Split the class into a sender and receiver.
328 ///
329 /// This allows concurrently sending and receiving packets from separate tasks.
322 pub fn split(self) -> (Sender<'d, D>, Receiver<'d, D>) { 330 pub fn split(self) -> (Sender<'d, D>, Receiver<'d, D>) {
323 ( 331 (
324 Sender { 332 Sender {
@@ -334,12 +342,18 @@ impl<'d, D: Driver<'d>> CdcNcmClass<'d, D> {
334 } 342 }
335} 343}
336 344
345/// CDC NCM class packet sender.
346///
347/// You can obtain a `Sender` with [`CdcNcmClass::split`]
337pub struct Sender<'d, D: Driver<'d>> { 348pub struct Sender<'d, D: Driver<'d>> {
338 write_ep: D::EndpointIn, 349 write_ep: D::EndpointIn,
339 seq: u16, 350 seq: u16,
340} 351}
341 352
342impl<'d, D: Driver<'d>> Sender<'d, D> { 353impl<'d, D: Driver<'d>> Sender<'d, D> {
354 /// Write a packet.
355 ///
356 /// This waits until the packet is succesfully stored in the CDC-NCM endpoint buffers.
343 pub async fn write_packet(&mut self, data: &[u8]) -> Result<(), EndpointError> { 357 pub async fn write_packet(&mut self, data: &[u8]) -> Result<(), EndpointError> {
344 let seq = self.seq; 358 let seq = self.seq;
345 self.seq = self.seq.wrapping_add(1); 359 self.seq = self.seq.wrapping_add(1);
@@ -393,6 +407,9 @@ impl<'d, D: Driver<'d>> Sender<'d, D> {
393 } 407 }
394} 408}
395 409
410/// CDC NCM class packet receiver.
411///
412/// You can obtain a `Receiver` with [`CdcNcmClass::split`]
396pub struct Receiver<'d, D: Driver<'d>> { 413pub struct Receiver<'d, D: Driver<'d>> {
397 data_if: InterfaceNumber, 414 data_if: InterfaceNumber,
398 comm_ep: D::EndpointIn, 415 comm_ep: D::EndpointIn,
@@ -400,7 +417,9 @@ pub struct Receiver<'d, D: Driver<'d>> {
400} 417}
401 418
402impl<'d, D: Driver<'d>> Receiver<'d, D> { 419impl<'d, D: Driver<'d>> Receiver<'d, D> {
403 /// Reads a single packet from the OUT endpoint. 420 /// Write a network packet.
421 ///
422 /// This waits until a packet is succesfully received from the endpoint buffers.
404 pub async fn read_packet(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError> { 423 pub async fn read_packet(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError> {
405 // Retry loop 424 // Retry loop
406 loop { 425 loop {