#![deny(unused_must_use)] use core::cell::RefCell; use core::task::Context; use embassy_net_driver::{Capabilities, HardwareAddress, LinkState}; use embassy_sync::blocking_mutex; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::channel::Channel; use embassy_sync::mutex::Mutex; use embassy_sync::waitqueue::AtomicWaker; use crate::mac::event::MacEvent; use crate::mac::indications::{write_frame_from_beacon_indication, write_frame_from_data_indication}; use crate::mac::runner::{BUF_SIZE, ZeroCopyPubSub}; use crate::mac::{Control, MTU, Runner}; use crate::sub::mac::{Mac, MacRx, MacTx}; pub struct NetworkState { pub mac_addr: [u8; 8], pub short_addr: [u8; 2], pub pan_id: [u8; 2], pub link_state: LinkState, pub link_waker: AtomicWaker, } impl NetworkState { pub const fn new() -> Self { Self { mac_addr: [0u8; 8], short_addr: [0u8; 2], pan_id: [0u8; 2], link_state: LinkState::Down, link_waker: AtomicWaker::new(), } } } pub struct DriverState<'d> { pub mac_tx: Mutex>, pub mac_rx: MacRx<'d>, pub rx_event_channel: ZeroCopyPubSub>, pub rx_data_channel: Channel, 1>, pub tx_data_channel: Channel, pub tx_buf_channel: Channel, pub tx_buf_queue: [[u8; MTU]; BUF_SIZE], pub network_state: blocking_mutex::Mutex>, } impl<'d> DriverState<'d> { pub const fn new(mac: Mac<'d>) -> Self { let (mac_rx, mac_tx) = mac.split(); let mac_tx = Mutex::new(mac_tx); Self { mac_tx, mac_rx, rx_event_channel: ZeroCopyPubSub::new(RefCell::new(None)), rx_data_channel: Channel::new(), tx_data_channel: Channel::new(), tx_buf_channel: Channel::new(), tx_buf_queue: [[0u8; MTU]; BUF_SIZE], network_state: blocking_mutex::Mutex::new(RefCell::new(NetworkState::new())), } } } pub struct Driver<'d> { tx_data_channel: &'d Channel, tx_buf_channel: &'d Channel, rx_data_channel: &'d Channel, 1>, network_state: &'d blocking_mutex::Mutex>, } impl<'d> Driver<'d> { pub fn new( driver_state: &'d mut DriverState<'d>, short_address: [u8; 2], mac_address: [u8; 8], ) -> (Self, Runner<'d>, Control<'d>) { ( Self { tx_data_channel: &driver_state.tx_data_channel, tx_buf_channel: &driver_state.tx_buf_channel, rx_data_channel: &driver_state.rx_data_channel, network_state: &driver_state.network_state, }, Runner::new( &driver_state.rx_event_channel, &driver_state.rx_data_channel, &mut driver_state.mac_rx, &driver_state.tx_data_channel, &driver_state.tx_buf_channel, &driver_state.mac_tx, &mut driver_state.tx_buf_queue, &driver_state.network_state, short_address, mac_address, ), Control::new( &driver_state.rx_event_channel, &driver_state.mac_tx, &driver_state.network_state, ), ) } } impl<'d> embassy_net_driver::Driver for Driver<'d> { // type RxToken<'a> = RxToken<'a, 'd> where Self: 'a; // type TxToken<'a> = TxToken<'a, 'd> where Self: 'a; type RxToken<'a> = RxToken<'d> where Self: 'a; type TxToken<'a> = TxToken<'d> where Self: 'a; fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { if self.rx_data_channel.poll_ready_to_receive(cx).is_ready() && self.tx_buf_channel.poll_ready_to_receive(cx).is_ready() { Some(( RxToken { rx: self.rx_data_channel, }, TxToken { tx: self.tx_data_channel, tx_buf: self.tx_buf_channel, }, )) } else { None } } fn transmit(&mut self, cx: &mut Context) -> Option> { if self.tx_buf_channel.poll_ready_to_receive(cx).is_ready() { Some(TxToken { tx: self.tx_data_channel, tx_buf: self.tx_buf_channel, }) } else { None } } fn capabilities(&self) -> Capabilities { let mut caps = Capabilities::default(); caps.max_transmission_unit = MTU; // caps.max_burst_size = Some(self.tx.len()); caps } fn link_state(&mut self, cx: &mut Context) -> LinkState { critical_section::with(|cs| { let network_state = self.network_state.borrow(cs).borrow_mut(); // Unconditionally register the waker to avoid a race network_state.link_waker.register(cx.waker()); network_state.link_state }) } fn hardware_address(&self) -> HardwareAddress { HardwareAddress::Ieee802154(critical_section::with(|cs| { self.network_state.borrow(cs).borrow().mac_addr })) } } pub struct RxToken<'d> { rx: &'d Channel, 1>, } impl<'d> embassy_net_driver::RxToken for RxToken<'d> { fn consume(self, f: F) -> R where F: FnOnce(&mut [u8]) -> R, { let mut buffer = [0u8; MTU]; match self.rx.try_receive().unwrap() { MacEvent::McpsDataInd(data_event) => write_frame_from_data_indication(data_event, &mut buffer), MacEvent::MlmeBeaconNotifyInd(data_event) => write_frame_from_beacon_indication(data_event, &mut buffer), _ => {} }; f(&mut buffer[..]) } } pub struct TxToken<'d> { tx: &'d Channel, tx_buf: &'d Channel, } impl<'d> embassy_net_driver::TxToken for TxToken<'d> { fn consume(self, len: usize, f: F) -> R where F: FnOnce(&mut [u8]) -> R, { // Only valid tx buffers should be put into the queue let buf = self.tx_buf.try_receive().unwrap(); let r = f(&mut buf[..len]); // The tx channel should always be of equal capacity to the tx_buf channel self.tx.try_send((buf, len)).unwrap(); r } }