2020-06-24 14:17:07 +08:00
|
|
|
use crate::{
|
|
|
|
EthController, rx, tx
|
|
|
|
};
|
2020-12-29 11:43:55 +08:00
|
|
|
use core::cell;
|
2020-06-24 14:17:07 +08:00
|
|
|
use smoltcp::{
|
|
|
|
phy::{Device, DeviceCapabilities, RxToken, TxToken},
|
|
|
|
time::Instant,
|
|
|
|
Error
|
|
|
|
};
|
|
|
|
|
2020-12-29 11:43:55 +08:00
|
|
|
pub struct SmoltcpDevice<EC: EthController> {
|
|
|
|
pub eth_controller: cell::RefCell<EC>,
|
2020-06-24 14:17:07 +08:00
|
|
|
rx_packet_buf: [u8; rx::RAW_FRAME_LENGTH_MAX],
|
|
|
|
tx_packet_buf: [u8; tx::RAW_FRAME_LENGTH_MAX]
|
|
|
|
}
|
|
|
|
|
2020-12-29 11:43:55 +08:00
|
|
|
impl<EC: EthController> SmoltcpDevice<EC> {
|
|
|
|
pub fn new(eth_controller: EC) -> Self {
|
2020-06-24 14:17:07 +08:00
|
|
|
SmoltcpDevice {
|
2020-12-29 11:43:55 +08:00
|
|
|
eth_controller: cell::RefCell::new(eth_controller),
|
2020-06-24 14:17:07 +08:00
|
|
|
rx_packet_buf: [0; rx::RAW_FRAME_LENGTH_MAX],
|
|
|
|
tx_packet_buf: [0; tx::RAW_FRAME_LENGTH_MAX]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-29 11:43:55 +08:00
|
|
|
impl<'a, EC: 'a + EthController> Device<'a> for SmoltcpDevice<EC> {
|
2020-06-24 14:17:07 +08:00
|
|
|
type RxToken = EthRxToken<'a>;
|
2020-12-29 11:43:55 +08:00
|
|
|
type TxToken = EthTxToken<'a, EC>;
|
2020-06-24 14:17:07 +08:00
|
|
|
|
|
|
|
fn capabilities(&self) -> DeviceCapabilities {
|
|
|
|
DeviceCapabilities::default()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
|
2020-12-29 11:43:55 +08:00
|
|
|
let self_p = (&mut *self) as *mut SmoltcpDevice<EC>;
|
|
|
|
match self.eth_controller.borrow_mut().receive_next(false) {
|
2020-06-24 14:17:07 +08:00
|
|
|
Ok(rx_packet) => {
|
|
|
|
// Write received packet to RX packet buffer
|
|
|
|
rx_packet.write_frame_to(&mut self.rx_packet_buf);
|
|
|
|
// Construct a RxToken
|
|
|
|
let rx_token = EthRxToken {
|
|
|
|
buf: &mut self.rx_packet_buf,
|
|
|
|
len: rx_packet.get_frame_length()
|
|
|
|
};
|
|
|
|
// Construct a blank TxToken
|
|
|
|
let tx_token = EthTxToken {
|
|
|
|
buf: &mut self.tx_packet_buf,
|
2020-12-29 11:43:55 +08:00
|
|
|
dev: self_p
|
2020-06-24 14:17:07 +08:00
|
|
|
};
|
|
|
|
Some((rx_token, tx_token))
|
|
|
|
},
|
|
|
|
Err(_) => None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn transmit(&'a mut self) -> Option<Self::TxToken> {
|
2020-12-29 11:43:55 +08:00
|
|
|
let self_p = (&mut *self) as *mut SmoltcpDevice<EC>;
|
2020-06-24 14:17:07 +08:00
|
|
|
// Construct a blank TxToken
|
|
|
|
let tx_token = EthTxToken {
|
|
|
|
buf: &mut self.tx_packet_buf,
|
2020-12-29 11:43:55 +08:00
|
|
|
dev: self_p
|
2020-06-24 14:17:07 +08:00
|
|
|
};
|
|
|
|
Some(tx_token)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct EthRxToken<'a> {
|
|
|
|
buf: &'a mut [u8],
|
|
|
|
len: usize
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> RxToken for EthRxToken<'a> {
|
|
|
|
fn consume<R, F>(self, _timestamp: Instant, f: F) -> Result<R, Error>
|
|
|
|
where
|
|
|
|
F: FnOnce(&mut [u8]) -> Result<R, Error>,
|
|
|
|
{
|
|
|
|
f(&mut self.buf[..self.len])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-29 11:43:55 +08:00
|
|
|
pub struct EthTxToken<'a, EC: EthController> {
|
2020-06-24 14:17:07 +08:00
|
|
|
buf: &'a mut [u8],
|
2020-12-29 11:43:55 +08:00
|
|
|
dev: *mut SmoltcpDevice<EC>
|
2020-06-24 14:17:07 +08:00
|
|
|
}
|
|
|
|
|
2020-12-29 11:43:55 +08:00
|
|
|
impl<'a, EC: 'a + EthController> TxToken for EthTxToken<'a, EC> {
|
2020-06-24 14:17:07 +08:00
|
|
|
fn consume<R, F>(self, _timestamp: Instant, len: usize, f: F) -> Result<R, Error>
|
|
|
|
where
|
|
|
|
F: FnOnce(&mut [u8]) -> Result<R, Error>,
|
|
|
|
{
|
|
|
|
let result = f(&mut self.buf[..len]);
|
|
|
|
// Construct a TxPacket
|
|
|
|
let mut tx_packet = tx::TxPacket::new();
|
|
|
|
// Update frame length and write frame bytes
|
|
|
|
tx_packet.update_frame(&mut self.buf[..len], len);
|
|
|
|
// Send the packet as raw
|
|
|
|
let eth_controller = unsafe {
|
|
|
|
&mut (*self.dev).eth_controller
|
|
|
|
};
|
2020-12-29 11:43:55 +08:00
|
|
|
match eth_controller.borrow_mut().send_raw_packet(&tx_packet) {
|
2020-06-24 14:17:07 +08:00
|
|
|
Ok(_) => { result },
|
|
|
|
Err(_) => Err(Error::Exhausted)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|