use super::{
IdRevision, Lan9514, Rx, Tx, BMSR_LINK_UP, HW_CFG_BIR, LED_GPIO_CFG_FDX_LED,
LED_GPIO_CFG_LNK_LED, LED_GPIO_CFG_SPD_LED, MAC_CR_RCVOWN, MAC_CR_RXEN, MAC_CR_TXEN, MII_BUSY,
MII_TIMEOUT_US, PHY_ID_INTERNAL, PHY_REG_STATUS, READ_REGISTER, REG_ADDRH, REG_ADDRL,
REG_HW_CFG, REG_ID_REV, REG_LED_GPIO_CFG, REG_MAC_CR, REG_MII_ADDR, REG_MII_DATA, REG_TX_CFG,
TX_CFG_ON, WRITE_REGISTER,
};
use crate::timer::Timer;
use crate::usb::control::{vendor_in_async, vendor_out_async};
use crate::usb::dwc2::{Channel, ControlEndpoint, TransferError};
pub struct Lan9514Rx<'a> {
endpoint: ControlEndpoint,
rx: &'a mut Rx,
}
pub struct Lan9514Tx<'a> {
endpoint: ControlEndpoint,
tx: &'a mut Tx,
}
impl Rx {
async fn receive_async(
&mut self,
device: ControlEndpoint,
channel: &mut Channel<'_>,
timer: &Timer,
) -> Result<Option<&[u8]>, TransferError> {
let endpoint = self.endpoint(device);
let number = self.bulk_in.number;
let received = match channel
.bulk_in_async(
endpoint,
number,
&mut self.bulk_in.toggle,
&mut self.buffer.0,
timer,
)
.await
{
Ok(received) => received,
Err(TransferError::Nak) => return Ok(None),
Err(error) => return Err(error),
};
Ok(self.frame(received))
}
}
impl Tx {
async fn send_async(
&mut self,
device: ControlEndpoint,
channel: &mut Channel<'_>,
timer: &Timer,
frame: &[u8],
) -> Result<(), TransferError> {
let staged = self.stage(frame);
let endpoint = self.endpoint(device);
let number = self.bulk_out.number;
channel
.bulk_out_async(
endpoint,
number,
&mut self.bulk_out.toggle,
&self.buffer.0[..staged],
timer,
)
.await?;
Ok(())
}
}
impl Lan9514Rx<'_> {
pub async fn receive_frame_async(
&mut self,
channel: &mut Channel<'_>,
timer: &Timer,
) -> Result<Option<&[u8]>, TransferError> {
self.rx.receive_async(self.endpoint, channel, timer).await
}
}
impl Lan9514Tx<'_> {
pub async fn send_frame_async(
&mut self,
channel: &mut Channel<'_>,
timer: &Timer,
frame: &[u8],
) -> Result<(), TransferError> {
self.tx
.send_async(self.endpoint, channel, timer, frame)
.await
}
}
impl Lan9514 {
pub async fn read_register_async(
&self,
channel: &mut Channel<'_>,
timer: &Timer,
register: u16,
) -> Result<u32, TransferError> {
let mut value = [0u8; 4];
vendor_in_async(
channel,
timer,
self.endpoint,
READ_REGISTER,
0,
register,
&mut value,
)
.await?;
Ok(u32::from_le_bytes(value))
}
pub async fn write_register_async(
&self,
channel: &mut Channel<'_>,
timer: &Timer,
register: u16,
value: u32,
) -> Result<(), TransferError> {
vendor_out_async(
channel,
timer,
self.endpoint,
WRITE_REGISTER,
0,
register,
&value.to_le_bytes(),
)
.await
}
pub async fn id_revision_async(
&self,
channel: &mut Channel<'_>,
timer: &Timer,
) -> Result<IdRevision, TransferError> {
let value = self.read_register_async(channel, timer, REG_ID_REV).await?;
Ok(IdRevision {
id: (value >> 16) as u16,
revision: (value & 0xFFFF) as u16,
})
}
pub async fn set_mac_address_async(
&self,
channel: &mut Channel<'_>,
timer: &Timer,
mac: [u8; 6],
) -> Result<(), TransferError> {
let low = u32::from_le_bytes([mac[0], mac[1], mac[2], mac[3]]);
let high = u16::from_le_bytes([mac[4], mac[5]]) as u32;
self.write_register_async(channel, timer, REG_ADDRL, low)
.await?;
self.write_register_async(channel, timer, REG_ADDRH, high)
.await?;
Ok(())
}
pub async fn mac_address_async(
&self,
channel: &mut Channel<'_>,
timer: &Timer,
) -> Result<[u8; 6], TransferError> {
let low = self
.read_register_async(channel, timer, REG_ADDRL)
.await?
.to_le_bytes();
let high = self
.read_register_async(channel, timer, REG_ADDRH)
.await?
.to_le_bytes();
Ok([low[0], low[1], low[2], low[3], high[0], high[1]])
}
pub async fn start_async(
&mut self,
channel: &mut Channel<'_>,
timer: &Timer,
mac: [u8; 6],
) -> Result<(), TransferError> {
self.set_mac_address_async(channel, timer, mac).await?;
let hw_cfg = self.read_register_async(channel, timer, REG_HW_CFG).await?;
self.write_register_async(channel, timer, REG_HW_CFG, hw_cfg | HW_CFG_BIR)
.await?;
self.write_register_async(
channel,
timer,
REG_LED_GPIO_CFG,
LED_GPIO_CFG_SPD_LED | LED_GPIO_CFG_LNK_LED | LED_GPIO_CFG_FDX_LED,
)
.await?;
self.write_register_async(
channel,
timer,
REG_MAC_CR,
MAC_CR_RCVOWN | MAC_CR_TXEN | MAC_CR_RXEN,
)
.await?;
self.write_register_async(channel, timer, REG_TX_CFG, TX_CFG_ON)
.await?;
Ok(())
}
pub async fn is_link_up_async(
&self,
channel: &mut Channel<'_>,
timer: &Timer,
) -> Result<bool, TransferError> {
Ok(self.phy_read_async(channel, timer, PHY_REG_STATUS).await? & BMSR_LINK_UP != 0)
}
pub fn split(&mut self) -> (Lan9514Rx<'_>, Lan9514Tx<'_>) {
let endpoint = self.endpoint;
(
Lan9514Rx {
endpoint,
rx: &mut self.rx,
},
Lan9514Tx {
endpoint,
tx: &mut self.tx,
},
)
}
pub async fn send_frame_async(
&mut self,
channel: &mut Channel<'_>,
timer: &Timer,
frame: &[u8],
) -> Result<(), TransferError> {
self.tx
.send_async(self.endpoint, channel, timer, frame)
.await
}
pub async fn receive_frame_async(
&mut self,
channel: &mut Channel<'_>,
timer: &Timer,
) -> Result<Option<&[u8]>, TransferError> {
self.rx.receive_async(self.endpoint, channel, timer).await
}
async fn phy_read_async(
&self,
channel: &mut Channel<'_>,
timer: &Timer,
index: u8,
) -> Result<u16, TransferError> {
self.phy_wait_not_busy_async(channel, timer).await?;
let mii_address = (PHY_ID_INTERNAL << 11) | ((index as u32) << 6);
self.write_register_async(channel, timer, REG_MII_ADDR, mii_address | MII_BUSY)
.await?;
self.phy_wait_not_busy_async(channel, timer).await?;
Ok(self
.read_register_async(channel, timer, REG_MII_DATA)
.await? as u16)
}
async fn phy_wait_not_busy_async(
&self,
channel: &mut Channel<'_>,
timer: &Timer,
) -> Result<(), TransferError> {
let start = timer.now_micros();
while self
.read_register_async(channel, timer, REG_MII_ADDR)
.await?
& MII_BUSY
!= 0
{
if timer.now_micros() - start > MII_TIMEOUT_US {
return Err(TransferError::Timeout);
}
}
Ok(())
}
}