From e9219405ca04e23b6543fb841fd97df54cf72f94 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 7 Dec 2022 16:03:03 +0100 Subject: usb/cdc-ncm: add embassy-net Device implementation. --- examples/nrf/Cargo.toml | 2 +- examples/nrf/src/bin/usb_ethernet.rs | 139 ++++-------------------------- examples/rp/Cargo.toml | 2 +- examples/rp/src/bin/usb_ethernet.rs | 140 ++++--------------------------- examples/stm32l5/Cargo.toml | 2 +- examples/stm32l5/src/bin/usb_ethernet.rs | 140 ++++--------------------------- 6 files changed, 54 insertions(+), 371 deletions(-) (limited to 'examples') diff --git a/examples/nrf/Cargo.toml b/examples/nrf/Cargo.toml index 8b95ac3a6..a980a505c 100644 --- a/examples/nrf/Cargo.toml +++ b/examples/nrf/Cargo.toml @@ -16,7 +16,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-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-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"], optional = true } +embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt", "embassy-net"], optional = true } embedded-io = "0.4.0" embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx126x", "time", "defmt"], optional = true } diff --git a/examples/nrf/src/bin/usb_ethernet.rs b/examples/nrf/src/bin/usb_ethernet.rs index de93a2b45..e5f704524 100644 --- a/examples/nrf/src/bin/usb_ethernet.rs +++ b/examples/nrf/src/bin/usb_ethernet.rs @@ -3,19 +3,16 @@ #![feature(type_alias_impl_trait)] use core::mem; -use core::sync::atomic::{AtomicBool, Ordering}; -use core::task::Waker; use defmt::*; use embassy_executor::Spawner; use embassy_net::tcp::TcpSocket; -use embassy_net::{PacketBox, PacketBoxExt, PacketBuf, Stack, StackResources}; +use embassy_net::{Stack, StackResources}; use embassy_nrf::rng::Rng; use embassy_nrf::usb::{Driver, PowerUsb}; use embassy_nrf::{interrupt, pac, peripherals}; -use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; -use embassy_sync::channel::Channel; -use embassy_usb::class::cdc_ncm::{CdcNcmClass, Receiver, Sender, State}; +use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; +use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; use embassy_usb::{Builder, Config, UsbDevice}; use embedded_io::asynch::Write; use static_cell::StaticCell; @@ -27,56 +24,25 @@ macro_rules! singleton { ($val:expr) => {{ type T = impl Sized; static STATIC_CELL: StaticCell = StaticCell::new(); - STATIC_CELL.init_with(move || $val) + let (x,) = STATIC_CELL.init(($val,)); + x }}; } +const MTU: usize = 1514; + #[embassy_executor::task] async fn usb_task(mut device: UsbDevice<'static, MyDriver>) -> ! { device.run().await } #[embassy_executor::task] -async fn usb_ncm_rx_task(mut class: Receiver<'static, MyDriver>) { - loop { - warn!("WAITING for connection"); - LINK_UP.store(false, Ordering::Relaxed); - - class.wait_connection().await.unwrap(); - - warn!("Connected"); - LINK_UP.store(true, Ordering::Relaxed); - - loop { - let mut p = unwrap!(PacketBox::new(embassy_net::Packet::new())); - let n = match class.read_packet(&mut p[..]).await { - Ok(n) => n, - Err(e) => { - warn!("error reading packet: {:?}", e); - break; - } - }; - - let buf = p.slice(0..n); - if RX_CHANNEL.try_send(buf).is_err() { - warn!("Failed pushing rx'd packet to channel."); - } - } - } -} - -#[embassy_executor::task] -async fn usb_ncm_tx_task(mut class: Sender<'static, MyDriver>) { - loop { - let pkt = TX_CHANNEL.recv().await; - if let Err(e) = class.write_packet(&pkt[..]).await { - warn!("Failed to TX packet: {:?}", e); - } - } +async fn usb_ncm_task(class: Runner<'static, MyDriver, MTU>) -> ! { + class.run().await } #[embassy_executor::task] -async fn net_task(stack: &'static Stack) -> ! { +async fn net_task(stack: &'static Stack>) -> ! { stack.run().await } @@ -108,55 +74,32 @@ async fn main(spawner: Spawner) { config.device_sub_class = 0x02; config.device_protocol = 0x01; - struct Resources { - device_descriptor: [u8; 256], - config_descriptor: [u8; 256], - bos_descriptor: [u8; 256], - control_buf: [u8; 128], - serial_state: State<'static>, - } - let res: &mut Resources = singleton!(Resources { - device_descriptor: [0; 256], - config_descriptor: [0; 256], - bos_descriptor: [0; 256], - control_buf: [0; 128], - serial_state: State::new(), - }); - // Create embassy-usb DeviceBuilder using the driver and config. let mut builder = Builder::new( driver, config, - &mut res.device_descriptor, - &mut res.config_descriptor, - &mut res.bos_descriptor, - &mut res.control_buf, + &mut singleton!([0; 256])[..], + &mut singleton!([0; 256])[..], + &mut singleton!([0; 256])[..], + &mut singleton!([0; 128])[..], None, ); - // WARNINGS for Android ethernet tethering: - // - On Pixel 4a, it refused to work on Android 11, worked on Android 12. - // - if the host's MAC address has the "locally-administered" bit set (bit 1 of first byte), - // it doesn't work! The "Ethernet tethering" option in settings doesn't get enabled. - // 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 - // and this nonsense in the linux kernel: https://github.com/torvalds/linux/blob/c00c5e1d157bec0ef0b0b59aa5482eb8dc7e8e49/drivers/net/usb/usbnet.c#L1751-L1757 - // Our MAC addr. let our_mac_addr = [0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC]; // Host's MAC addr. This is the MAC the host "thinks" its USB-to-ethernet adapter has. let host_mac_addr = [0x88, 0x88, 0x88, 0x88, 0x88, 0x88]; // Create classes on the builder. - let class = CdcNcmClass::new(&mut builder, &mut res.serial_state, host_mac_addr, 64); + let class = CdcNcmClass::new(&mut builder, singleton!(State::new()), host_mac_addr, 64); // Build the builder. let usb = builder.build(); unwrap!(spawner.spawn(usb_task(usb))); - let (tx, rx) = class.split(); - unwrap!(spawner.spawn(usb_ncm_rx_task(rx))); - unwrap!(spawner.spawn(usb_ncm_tx_task(tx))); + let (runner, device) = class.into_embassy_net_device::(singleton!(NetState::new()), our_mac_addr); + unwrap!(spawner.spawn(usb_ncm_task(runner))); let config = embassy_net::ConfigStrategy::Dhcp; //let config = embassy_net::ConfigStrategy::Static(embassy_net::Config { @@ -172,7 +115,6 @@ async fn main(spawner: Spawner) { let seed = u64::from_le_bytes(seed); // Init network stack - let device = Device { mac_addr: our_mac_addr }; let stack = &*singleton!(Stack::new( device, config, @@ -225,50 +167,3 @@ async fn main(spawner: Spawner) { } } } - -static TX_CHANNEL: Channel = Channel::new(); -static RX_CHANNEL: Channel = Channel::new(); -static LINK_UP: AtomicBool = AtomicBool::new(false); - -struct Device { - mac_addr: [u8; 6], -} - -impl embassy_net::Device for Device { - fn register_waker(&mut self, waker: &Waker) { - // loopy loopy wakey wakey - waker.wake_by_ref() - } - - fn link_state(&mut self) -> embassy_net::LinkState { - match LINK_UP.load(Ordering::Relaxed) { - true => embassy_net::LinkState::Up, - false => embassy_net::LinkState::Down, - } - } - - fn capabilities(&self) -> embassy_net::DeviceCapabilities { - let mut caps = embassy_net::DeviceCapabilities::default(); - caps.max_transmission_unit = 1514; // 1500 IP + 14 ethernet header - caps.medium = embassy_net::Medium::Ethernet; - caps - } - - fn is_transmit_ready(&mut self) -> bool { - true - } - - fn transmit(&mut self, pkt: PacketBuf) { - if TX_CHANNEL.try_send(pkt).is_err() { - warn!("TX failed") - } - } - - fn receive<'a>(&mut self) -> Option { - RX_CHANNEL.try_recv().ok() - } - - fn ethernet_address(&self) -> [u8; 6] { - self.mac_addr - } -} diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index dfbc26426..31a08cfb6 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -10,7 +10,7 @@ embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["de embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } 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", "pio", "critical-section-impl"] } -embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt", "embassy-net"] } 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-usb-logger = { version = "0.1.0", path = "../../embassy-usb-logger" } diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs index 1057fe7fd..d0aec874a 100644 --- a/examples/rp/src/bin/usb_ethernet.rs +++ b/examples/rp/src/bin/usb_ethernet.rs @@ -2,18 +2,14 @@ #![no_main] #![feature(type_alias_impl_trait)] -use core::sync::atomic::{AtomicBool, Ordering}; -use core::task::Waker; - use defmt::*; use embassy_executor::Spawner; use embassy_net::tcp::TcpSocket; -use embassy_net::{PacketBox, PacketBoxExt, PacketBuf, Stack, StackResources}; +use embassy_net::{Stack, StackResources}; use embassy_rp::usb::Driver; use embassy_rp::{interrupt, peripherals}; -use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; -use embassy_sync::channel::Channel; -use embassy_usb::class::cdc_ncm::{CdcNcmClass, Receiver, Sender, State}; +use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; +use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; use embassy_usb::{Builder, Config, UsbDevice}; use embedded_io::asynch::Write; use static_cell::StaticCell; @@ -25,56 +21,25 @@ macro_rules! singleton { ($val:expr) => {{ type T = impl Sized; static STATIC_CELL: StaticCell = StaticCell::new(); - STATIC_CELL.init_with(move || $val) + let (x,) = STATIC_CELL.init(($val,)); + x }}; } +const MTU: usize = 1514; + #[embassy_executor::task] async fn usb_task(mut device: UsbDevice<'static, MyDriver>) -> ! { device.run().await } #[embassy_executor::task] -async fn usb_ncm_rx_task(mut class: Receiver<'static, MyDriver>) { - loop { - warn!("WAITING for connection"); - LINK_UP.store(false, Ordering::Relaxed); - - class.wait_connection().await.unwrap(); - - warn!("Connected"); - LINK_UP.store(true, Ordering::Relaxed); - - loop { - let mut p = unwrap!(PacketBox::new(embassy_net::Packet::new())); - let n = match class.read_packet(&mut p[..]).await { - Ok(n) => n, - Err(e) => { - warn!("error reading packet: {:?}", e); - break; - } - }; - - let buf = p.slice(0..n); - if RX_CHANNEL.try_send(buf).is_err() { - warn!("Failed pushing rx'd packet to channel."); - } - } - } -} - -#[embassy_executor::task] -async fn usb_ncm_tx_task(mut class: Sender<'static, MyDriver>) { - loop { - let pkt = TX_CHANNEL.recv().await; - if let Err(e) = class.write_packet(&pkt[..]).await { - warn!("Failed to TX packet: {:?}", e); - } - } +async fn usb_ncm_task(class: Runner<'static, MyDriver, MTU>) -> ! { + class.run().await } #[embassy_executor::task] -async fn net_task(stack: &'static Stack) -> ! { +async fn net_task(stack: &'static Stack>) -> ! { stack.run().await } @@ -100,55 +65,32 @@ async fn main(spawner: Spawner) { config.device_sub_class = 0x02; config.device_protocol = 0x01; - struct Resources { - device_descriptor: [u8; 256], - config_descriptor: [u8; 256], - bos_descriptor: [u8; 256], - control_buf: [u8; 128], - serial_state: State<'static>, - } - let res: &mut Resources = singleton!(Resources { - device_descriptor: [0; 256], - config_descriptor: [0; 256], - bos_descriptor: [0; 256], - control_buf: [0; 128], - serial_state: State::new(), - }); - // Create embassy-usb DeviceBuilder using the driver and config. let mut builder = Builder::new( driver, config, - &mut res.device_descriptor, - &mut res.config_descriptor, - &mut res.bos_descriptor, - &mut res.control_buf, + &mut singleton!([0; 256])[..], + &mut singleton!([0; 256])[..], + &mut singleton!([0; 256])[..], + &mut singleton!([0; 128])[..], None, ); - // WARNINGS for Android ethernet tethering: - // - On Pixel 4a, it refused to work on Android 11, worked on Android 12. - // - if the host's MAC address has the "locally-administered" bit set (bit 1 of first byte), - // it doesn't work! The "Ethernet tethering" option in settings doesn't get enabled. - // 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 - // and this nonsense in the linux kernel: https://github.com/torvalds/linux/blob/c00c5e1d157bec0ef0b0b59aa5482eb8dc7e8e49/drivers/net/usb/usbnet.c#L1751-L1757 - // Our MAC addr. let our_mac_addr = [0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC]; // Host's MAC addr. This is the MAC the host "thinks" its USB-to-ethernet adapter has. let host_mac_addr = [0x88, 0x88, 0x88, 0x88, 0x88, 0x88]; // Create classes on the builder. - let class = CdcNcmClass::new(&mut builder, &mut res.serial_state, host_mac_addr, 64); + let class = CdcNcmClass::new(&mut builder, singleton!(State::new()), host_mac_addr, 64); // Build the builder. let usb = builder.build(); unwrap!(spawner.spawn(usb_task(usb))); - let (tx, rx) = class.split(); - unwrap!(spawner.spawn(usb_ncm_rx_task(rx))); - unwrap!(spawner.spawn(usb_ncm_tx_task(tx))); + let (runner, device) = class.into_embassy_net_device::(singleton!(NetState::new()), our_mac_addr); + unwrap!(spawner.spawn(usb_ncm_task(runner))); let config = embassy_net::ConfigStrategy::Dhcp; //let config = embassy_net::ConfigStrategy::Static(embassy_net::Config { @@ -161,7 +103,6 @@ async fn main(spawner: Spawner) { let seed = 1234; // guaranteed random, chosen by a fair dice roll // Init network stack - let device = Device { mac_addr: our_mac_addr }; let stack = &*singleton!(Stack::new( device, config, @@ -214,50 +155,3 @@ async fn main(spawner: Spawner) { } } } - -static TX_CHANNEL: Channel = Channel::new(); -static RX_CHANNEL: Channel = Channel::new(); -static LINK_UP: AtomicBool = AtomicBool::new(false); - -struct Device { - mac_addr: [u8; 6], -} - -impl embassy_net::Device for Device { - fn register_waker(&mut self, waker: &Waker) { - // loopy loopy wakey wakey - waker.wake_by_ref() - } - - fn link_state(&mut self) -> embassy_net::LinkState { - match LINK_UP.load(Ordering::Relaxed) { - true => embassy_net::LinkState::Up, - false => embassy_net::LinkState::Down, - } - } - - fn capabilities(&self) -> embassy_net::DeviceCapabilities { - let mut caps = embassy_net::DeviceCapabilities::default(); - caps.max_transmission_unit = 1514; // 1500 IP + 14 ethernet header - caps.medium = embassy_net::Medium::Ethernet; - caps - } - - fn is_transmit_ready(&mut self) -> bool { - true - } - - fn transmit(&mut self, pkt: PacketBuf) { - if TX_CHANNEL.try_send(pkt).is_err() { - warn!("TX failed") - } - } - - fn receive<'a>(&mut self) -> Option { - RX_CHANNEL.try_recv().ok() - } - - fn ethernet_address(&self) -> [u8; 6] { - self.mac_addr - } -} diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml index 73ad50787..bb8515312 100644 --- a/examples/stm32l5/Cargo.toml +++ b/examples/stm32l5/Cargo.toml @@ -11,7 +11,7 @@ embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["de embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } 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-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt", "embassy-net"] } 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" } usbd-hid = "0.6.0" diff --git a/examples/stm32l5/src/bin/usb_ethernet.rs b/examples/stm32l5/src/bin/usb_ethernet.rs index 4f36d3f5a..b49329ea4 100644 --- a/examples/stm32l5/src/bin/usb_ethernet.rs +++ b/examples/stm32l5/src/bin/usb_ethernet.rs @@ -2,20 +2,16 @@ #![no_main] #![feature(type_alias_impl_trait)] -use core::sync::atomic::{AtomicBool, Ordering}; -use core::task::Waker; - use defmt::*; use embassy_executor::Spawner; use embassy_net::tcp::TcpSocket; -use embassy_net::{PacketBox, PacketBoxExt, PacketBuf, Stack, StackResources}; +use embassy_net::{Stack, StackResources}; use embassy_stm32::rcc::*; use embassy_stm32::rng::Rng; use embassy_stm32::usb::Driver; use embassy_stm32::{interrupt, Config}; -use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; -use embassy_sync::channel::Channel; -use embassy_usb::class::cdc_ncm::{CdcNcmClass, Receiver, Sender, State}; +use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; +use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; use embassy_usb::{Builder, UsbDevice}; use embedded_io::asynch::Write; use rand_core::RngCore; @@ -28,56 +24,25 @@ macro_rules! singleton { ($val:expr) => {{ type T = impl Sized; static STATIC_CELL: StaticCell = StaticCell::new(); - STATIC_CELL.init_with(move || $val) + let (x,) = STATIC_CELL.init(($val,)); + x }}; } +const MTU: usize = 1514; + #[embassy_executor::task] async fn usb_task(mut device: UsbDevice<'static, MyDriver>) -> ! { device.run().await } #[embassy_executor::task] -async fn usb_ncm_rx_task(mut class: Receiver<'static, MyDriver>) { - loop { - warn!("WAITING for connection"); - LINK_UP.store(false, Ordering::Relaxed); - - class.wait_connection().await.unwrap(); - - warn!("Connected"); - LINK_UP.store(true, Ordering::Relaxed); - - loop { - let mut p = unwrap!(PacketBox::new(embassy_net::Packet::new())); - let n = match class.read_packet(&mut p[..]).await { - Ok(n) => n, - Err(e) => { - warn!("error reading packet: {:?}", e); - break; - } - }; - - let buf = p.slice(0..n); - if RX_CHANNEL.try_send(buf).is_err() { - warn!("Failed pushing rx'd packet to channel."); - } - } - } -} - -#[embassy_executor::task] -async fn usb_ncm_tx_task(mut class: Sender<'static, MyDriver>) { - loop { - let pkt = TX_CHANNEL.recv().await; - if let Err(e) = class.write_packet(&pkt[..]).await { - warn!("Failed to TX packet: {:?}", e); - } - } +async fn usb_ncm_task(class: Runner<'static, MyDriver, MTU>) -> ! { + class.run().await } #[embassy_executor::task] -async fn net_task(stack: &'static Stack) -> ! { +async fn net_task(stack: &'static Stack>) -> ! { stack.run().await } @@ -106,55 +71,32 @@ async fn main(spawner: Spawner) { config.device_sub_class = 0x02; config.device_protocol = 0x01; - struct Resources { - device_descriptor: [u8; 256], - config_descriptor: [u8; 256], - bos_descriptor: [u8; 256], - control_buf: [u8; 128], - serial_state: State<'static>, - } - let res: &mut Resources = singleton!(Resources { - device_descriptor: [0; 256], - config_descriptor: [0; 256], - bos_descriptor: [0; 256], - control_buf: [0; 128], - serial_state: State::new(), - }); - // Create embassy-usb DeviceBuilder using the driver and config. let mut builder = Builder::new( driver, config, - &mut res.device_descriptor, - &mut res.config_descriptor, - &mut res.bos_descriptor, - &mut res.control_buf, + &mut singleton!([0; 256])[..], + &mut singleton!([0; 256])[..], + &mut singleton!([0; 256])[..], + &mut singleton!([0; 128])[..], None, ); - // WARNINGS for Android ethernet tethering: - // - On Pixel 4a, it refused to work on Android 11, worked on Android 12. - // - if the host's MAC address has the "locally-administered" bit set (bit 1 of first byte), - // it doesn't work! The "Ethernet tethering" option in settings doesn't get enabled. - // 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 - // and this nonsense in the linux kernel: https://github.com/torvalds/linux/blob/c00c5e1d157bec0ef0b0b59aa5482eb8dc7e8e49/drivers/net/usb/usbnet.c#L1751-L1757 - // Our MAC addr. let our_mac_addr = [0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC]; // Host's MAC addr. This is the MAC the host "thinks" its USB-to-ethernet adapter has. let host_mac_addr = [0x88, 0x88, 0x88, 0x88, 0x88, 0x88]; // Create classes on the builder. - let class = CdcNcmClass::new(&mut builder, &mut res.serial_state, host_mac_addr, 64); + let class = CdcNcmClass::new(&mut builder, singleton!(State::new()), host_mac_addr, 64); // Build the builder. let usb = builder.build(); unwrap!(spawner.spawn(usb_task(usb))); - let (tx, rx) = class.split(); - unwrap!(spawner.spawn(usb_ncm_rx_task(rx))); - unwrap!(spawner.spawn(usb_ncm_tx_task(tx))); + let (runner, device) = class.into_embassy_net_device::(singleton!(NetState::new()), our_mac_addr); + unwrap!(spawner.spawn(usb_ncm_task(runner))); let config = embassy_net::ConfigStrategy::Dhcp; //let config = embassy_net::ConfigStrategy::Static(embassy_net::Config { @@ -168,7 +110,6 @@ async fn main(spawner: Spawner) { let seed = rng.next_u64(); // Init network stack - let device = Device { mac_addr: our_mac_addr }; let stack = &*singleton!(Stack::new( device, config, @@ -221,50 +162,3 @@ async fn main(spawner: Spawner) { } } } - -static TX_CHANNEL: Channel = Channel::new(); -static RX_CHANNEL: Channel = Channel::new(); -static LINK_UP: AtomicBool = AtomicBool::new(false); - -struct Device { - mac_addr: [u8; 6], -} - -impl embassy_net::Device for Device { - fn register_waker(&mut self, waker: &Waker) { - // loopy loopy wakey wakey - waker.wake_by_ref() - } - - fn link_state(&mut self) -> embassy_net::LinkState { - match LINK_UP.load(Ordering::Relaxed) { - true => embassy_net::LinkState::Up, - false => embassy_net::LinkState::Down, - } - } - - fn capabilities(&self) -> embassy_net::DeviceCapabilities { - let mut caps = embassy_net::DeviceCapabilities::default(); - caps.max_transmission_unit = 1514; // 1500 IP + 14 ethernet header - caps.medium = embassy_net::Medium::Ethernet; - caps - } - - fn is_transmit_ready(&mut self) -> bool { - true - } - - fn transmit(&mut self, pkt: PacketBuf) { - if TX_CHANNEL.try_send(pkt).is_err() { - warn!("TX failed") - } - } - - fn receive<'a>(&mut self) -> Option { - RX_CHANNEL.try_recv().ok() - } - - fn ethernet_address(&self) -> [u8; 6] { - self.mac_addr - } -} -- cgit