Added Packet struct and beginnings of packet reading

This commit is contained in:
Jonah Dahlquist 2019-09-10 09:15:48 -05:00 committed by Jonah Dahlquist
commit d0f5792028
4 changed files with 193 additions and 0 deletions

View file

@ -54,4 +54,13 @@ pub mod socketn {
} }
pub const SOURCE_PORT: u16 = 0x04; pub const SOURCE_PORT: u16 = 0x04;
pub const INTERRUPT_MASK: u16 = 0x2C;
pub mod interrupt_mask {
pub const RECEIVE: u8 = 0b100;
}
pub const RECEIVED_SIZE: u16 = 0x26;
pub const RX_DATA_POINTER: u16 = 0x28;
} }

View file

@ -37,6 +37,23 @@ pub trait Socket {
block!(bus.transfer_frame(self.register(), socketn::SOURCE_PORT, true, &mut data))?; block!(bus.transfer_frame(self.register(), socketn::SOURCE_PORT, true, &mut data))?;
Ok(()) Ok(())
} }
fn has_received<SpiBus: ActiveBus>(
&self,
bus: &mut SpiBus,
) -> Result<bool, SpiBus::Error> {
let mut data = [0u8];
block!(bus.transfer_frame(self.register(), socketn::INTERRUPT_MASK, true, &mut data))?;
Ok(data[0] & socketn::interrupt_mask::RECEIVE != 0)
}
fn get_packet_address<SpiBus: ActiveBus>(
&self,
bus: &mut SpiBus,
) -> Result<u16, SpiBus::Error> {
let mut data = [0u8; 2];
block!(bus.transfer_frame(self.register(), socketn::RX_DATA_POINTER, true, &mut data))?;
Ok(BigEndian::read_u16(&data))
}
} }
pub type OwnedSockets = ( pub type OwnedSockets = (

View file

@ -1,11 +1,15 @@
mod inactive_udp_socket; mod inactive_udp_socket;
mod packet;
use byteorder::{BigEndian, ByteOrder};
use crate::IpAddress;
use crate::bus::ActiveBus; use crate::bus::ActiveBus;
use crate::network::Network; use crate::network::Network;
use crate::socket::OwnedSockets; use crate::socket::OwnedSockets;
use crate::socket::Socket; use crate::socket::Socket;
use crate::udp::inactive_udp_socket::InactiveUdpSocket; use crate::udp::inactive_udp_socket::InactiveUdpSocket;
use crate::w5500::W5500; use crate::w5500::W5500;
use crate::udp::packet::UdpPacket;
use register::socketn; use register::socketn;
pub struct UdpSocket<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> { pub struct UdpSocket<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> {
@ -38,6 +42,103 @@ impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket>
}) })
} }
/// Returns a UDP packet if one is available. Will return `None` if no UDP packets are in the socket's buffer
pub fn receive(mut self) -> Result<Option<UdpPacket<Self>>, SpiBus::Error> {
if !self.socket.has_received(&mut self.bus)? {
Ok(None)
} else {
Ok(Some(UdpPacket::new(self)?))
}
}
fn block_until_receive_size_known(&mut self) -> Result<u16, SpiBus::Error> {
loop {
let mut sample_0 = [0u8; 2];
block!(self.bus.transfer_frame(self.socket.register(), socketn::RECEIVED_SIZE, false, &mut sample_0))?;
let mut sample_1 = [0u8; 2];
block!(self.bus.transfer_frame(self.socket.register(), socketn::RECEIVED_SIZE, false, &mut sample_1))?;
if sample_0 == sample_1 && sample_0[0] >= 8 {
break Ok(BigEndian::read_u16(&sample_0));
}
}
}
// /// Sends a UDP packet to the specified IP and port, and blocks until it is sent
// fn blocking_send(
// &mut self,
// host: &IpAddress,
// host_port: u16,
// data: &[u8],
// ) -> Result<(), Self::Error> {
// let (w5500, UdpSocket(socket)) = self;
// {
// let local_port = w5500.read_u16(socket.at(SocketRegister::LocalPort))?;
// let local_port = local_port.to_be_bytes();
// let host_port = host_port.to_be_bytes();
// w5500.write_to(
// socket.at(SocketRegister::LocalPort),
// &[
// local_port[0],
// local_port[1], // local port u16
// 0x00,
// 0x00,
// 0x00,
// 0x00,
// 0x00,
// 0x00, // destination mac
// host.address[0],
// host.address[1],
// host.address[2],
// host.address[3], // target IP
// host_port[0],
// host_port[1], // destination port (5354)
// ],
// )?;
// }
// let data_length = data.len() as u16;
// {
// let data_length = data_length.to_be_bytes();
// // TODO why write [0x00, 0x00] at TxReadPointer at all?
// // TODO Is TxWritePointer not sufficient enough?
// w5500.write_to(
// socket.at(SocketRegister::TxReadPointer),
// &[0x00, 0x00, data_length[0], data_length[1]],
// );
// }
// w5500.write_to(
// socket.tx_register_at(0x00_00),
// &data[..data_length as usize],
// )?;
// w5500.write_to(
// socket.at(SocketRegister::Command),
// &[SocketCommand::Send as u8],
// )?;
// for _ in 0..0xFFFF {
// // wait until sent
// if w5500.is_interrupt_set(*socket, Interrupt::SendOk)? {
// w5500.reset_interrupt(*socket, Interrupt::SendOk)?;
// break;
// }
// }
// // restore listen state
// w5500.write_to(
// socket.at(SocketRegister::Mode),
// &[
// Protocol::UDP as u8, // Socket Mode Register
// SocketCommand::Open as u8, // Socket Command Register
// ],
// )?;
// Ok(())
// }
pub fn deactivate( pub fn deactivate(
self, self,
) -> ( ) -> (

66
src/udp/packet.rs Normal file
View file

@ -0,0 +1,66 @@
use crate::udp::UdpSocket;
use crate::network::Network;
use crate::bus::ActiveBus;
use crate::socket::Socket;
use crate::IpAddress;
use byteorder::{BigEndian, ByteOrder};
pub struct UdpPacket<UdpSocket> {
udp_socket: UdpSocket,
address: IpAddress,
remote_port: u16,
size: u16,
read_pointer: u16,
}
impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> UdpPacket<UdpSocket<'a, SpiBus, NetworkImpl, SocketImpl>>
{
pub fn new(mut udp_socket: UdpSocket<'a, SpiBus, NetworkImpl, SocketImpl>) -> Result<Self, SpiBus::Error> {
let receive_size = udp_socket.block_until_receive_size_known()? - 8;
// |<-- read_pointer read_pointer + received_size -->|
// |Destination IP Address | Destination Port | Byte Size of DATA | Actual DATA ... |
// | --- 4 Bytes --- | --- 2 Bytes --- | --- 2 Bytes --- | .... |
let read_pointer = udp_socket.socket.get_packet_address(&mut udp_socket.bus)?;
let mut header = [0u8; 8];
block!(udp_socket.bus.transfer_frame(udp_socket.socket.rx_buffer(), read_pointer, false, &mut header))?;
Ok(UdpPacket {
udp_socket,
address: IpAddress::new(header[0], header[1], header[2], header[3]),
remote_port: BigEndian::read_u16(&header[4..5]),
size: receive_size,
read_pointer,
})
}
pub fn get_remote_port(&self) -> u16 {
self.remote_port
}
pub fn get_address(&self) -> IpAddress {
self.address
}
pub fn read(&self) {
// TODO read a byte upon every invocation
// w5500.read_from(
// socket.rx_register_at(read_pointer + 8),
// &mut destination[..data_length],
// )?;
}
pub fn close(self) -> UdpSocket<'a, SpiBus, NetworkImpl, SocketImpl> {
// TODO reset read pointer etc
// // reset
// w5500.write_u16(
// socket.at(SocketRegister::RxReadPointer),
// read_pointer + receive_size as u16,
// )?;
// w5500.write_u8(
// socket.at(SocketRegister::Command),
// SocketCommand::Recv as u8,
// )?;
// TODO return Socket
self.udp_socket
}
}