Fleshed out packet sending
This commit is contained in:
parent
63890a5d5a
commit
b9f916624b
5 changed files with 212 additions and 111 deletions
|
|
@ -49,23 +49,31 @@ pub mod socketn {
|
|||
pub const COMMAND: u16 = 0x01;
|
||||
#[repr(u8)]
|
||||
pub enum Command {
|
||||
Open = 0x01,
|
||||
Send = 0x20,
|
||||
Receive = 0x40,
|
||||
}
|
||||
|
||||
pub const INTERRUPT: u16 = 0x02;
|
||||
#[repr(u8)]
|
||||
pub enum Interrupt {
|
||||
SendOk = 0b10000u8,
|
||||
SendOk = 0b010000u8,
|
||||
Receive = 0b00100u8,
|
||||
}
|
||||
|
||||
pub const SOURCE_PORT: u16 = 0x04;
|
||||
|
||||
pub const INTERRUPT_MASK: u16 = 0x2C;
|
||||
pub mod interrupt_mask {
|
||||
pub const RECEIVE: u8 = 0b100;
|
||||
}
|
||||
pub const DESTINATION_IP: u16 = 0x0C;
|
||||
|
||||
pub const DESTINATION_PORT: u16 = 0x10;
|
||||
|
||||
pub const TX_DATA_READ_POINTER: u16 = 0x22;
|
||||
|
||||
pub const TX_DATA_WRITE_POINTER: u16 = 0x24;
|
||||
|
||||
pub const RECEIVED_SIZE: u16 = 0x26;
|
||||
|
||||
pub const RX_DATA_READ_POINTER: u16 = 0x28;
|
||||
|
||||
pub const INTERRUPT_MASK: u16 = 0x2C;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use byteorder::{BigEndian, ByteOrder};
|
|||
use crate::bus::ActiveBus;
|
||||
use crate::register;
|
||||
use crate::register::socketn;
|
||||
use crate::IpAddress;
|
||||
|
||||
pub trait Socket {
|
||||
fn is_owned_by(&self, sockets: &OwnedSockets) -> bool;
|
||||
|
|
@ -30,24 +31,79 @@ pub trait Socket {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn has_interrupt<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
code: socketn::Interrupt,
|
||||
) -> Result<bool, SpiBus::Error> {
|
||||
let mut data = [0u8];
|
||||
BigEndian::write_u16(&mut data, code as u16);
|
||||
block!(bus.transfer_frame(self.register(), socketn::INTERRUPT_MASK, true, &mut data))?;
|
||||
Ok(data[0] & socketn::Interrupt::Receive as u8 != 0)
|
||||
}
|
||||
|
||||
fn set_source_port<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
port: u16,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
let mut data = [0u8; 2];
|
||||
BigEndian::write_u16(&mut data[..], port);
|
||||
BigEndian::write_u16(&mut data, port);
|
||||
block!(bus.transfer_frame(self.register(), socketn::SOURCE_PORT, true, &mut data))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn has_received<SpiBus: ActiveBus>(
|
||||
fn set_destination_ip<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)
|
||||
ip: IpAddress,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
let mut data = ip.address;
|
||||
block!(bus.transfer_frame(self.register(), socketn::DESTINATION_IP, true, &mut data))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_destination_port<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
port: u16,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
let mut data = [0u8; 2];
|
||||
BigEndian::write_u16(&mut data, port);
|
||||
block!(bus.transfer_frame(self.register(), socketn::DESTINATION_PORT, true, &mut data))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_tx_read_pointer<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
pointer: u16,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
let mut data = [0u8; 2];
|
||||
BigEndian::write_u16(&mut data, pointer);
|
||||
block!(bus.transfer_frame(
|
||||
self.register(),
|
||||
socketn::TX_DATA_READ_POINTER,
|
||||
true,
|
||||
&mut data
|
||||
))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_tx_write_pointer<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
pointer: u16,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
let mut data = [0u8; 2];
|
||||
BigEndian::write_u16(&mut data, pointer);
|
||||
block!(bus.transfer_frame(
|
||||
self.register(),
|
||||
socketn::TX_DATA_WRITE_POINTER,
|
||||
true,
|
||||
&mut data
|
||||
))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_rx_read_pointer<SpiBus: ActiveBus>(
|
||||
|
|
@ -55,18 +111,36 @@ pub trait Socket {
|
|||
bus: &mut SpiBus,
|
||||
) -> Result<u16, SpiBus::Error> {
|
||||
let mut data = [0u8; 2];
|
||||
block!(bus.transfer_frame(self.register(), socketn::RX_DATA_READ_POINTER, true, &mut data))?;
|
||||
block!(bus.transfer_frame(
|
||||
self.register(),
|
||||
socketn::RX_DATA_READ_POINTER,
|
||||
true,
|
||||
&mut data
|
||||
))?;
|
||||
Ok(BigEndian::read_u16(&data))
|
||||
}
|
||||
|
||||
fn set_rx_read_pointer<SpiBus: ActiveBus>(&self, bus: &mut SpiBus, pointer: u16) -> Result<(), SpiBus::Error> {
|
||||
fn set_rx_read_pointer<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
pointer: u16,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
let mut data = [0u8; 2];
|
||||
BigEndian::write_u16(&mut data, pointer);
|
||||
block!(bus.transfer_frame(self.register(), socketn::RX_DATA_READ_POINTER, true, &mut data))?;
|
||||
block!(bus.transfer_frame(
|
||||
self.register(),
|
||||
socketn::RX_DATA_READ_POINTER,
|
||||
true,
|
||||
&mut data
|
||||
))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn command<SpiBus: ActiveBus>(&self, bus: &mut SpiBus, command: socketn::Command) -> Result<(), SpiBus::Error> {
|
||||
fn command<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
command: socketn::Command,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
let mut data = [0u8; 2];
|
||||
BigEndian::write_u16(&mut data, command as u16);
|
||||
block!(bus.transfer_frame(self.register(), socketn::COMMAND, true, &mut data))?;
|
||||
|
|
@ -77,9 +151,19 @@ pub trait Socket {
|
|||
loop {
|
||||
// Section 4.2 of datasheet, Sn_TX_FSR address docs indicate that read must be repeated until two sequential reads are stable
|
||||
let mut sample_0 = [0u8; 2];
|
||||
block!(bus.transfer_frame(self.register(), socketn::RECEIVED_SIZE, false, &mut sample_0))?;
|
||||
block!(bus.transfer_frame(
|
||||
self.register(),
|
||||
socketn::RECEIVED_SIZE,
|
||||
false,
|
||||
&mut sample_0
|
||||
))?;
|
||||
let mut sample_1 = [0u8; 2];
|
||||
block!(bus.transfer_frame(self.register(), socketn::RECEIVED_SIZE, false, &mut sample_1))?;
|
||||
block!(bus.transfer_frame(
|
||||
self.register(),
|
||||
socketn::RECEIVED_SIZE,
|
||||
false,
|
||||
&mut sample_1
|
||||
))?;
|
||||
if sample_0 == sample_1 && sample_0[0] >= 8 {
|
||||
break Ok(BigEndian::read_u16(&sample_0));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use byteorder::{BigEndian, ByteOrder};
|
||||
use crate::udp::UdpSocket;
|
||||
use crate::network::Network;
|
||||
use crate::bus::ActiveBus;
|
||||
use crate::socket::Socket;
|
||||
use crate::IpAddress;
|
||||
use crate::network::Network;
|
||||
use crate::register::socketn;
|
||||
use crate::socket::Socket;
|
||||
use crate::udp::UdpSocket;
|
||||
use crate::IpAddress;
|
||||
use byteorder::{BigEndian, ByteOrder};
|
||||
|
||||
pub struct IncomingPacket<UdpSocket> {
|
||||
udp_socket: UdpSocket,
|
||||
|
|
@ -14,9 +14,12 @@ pub struct IncomingPacket<UdpSocket> {
|
|||
write_pointer: u16,
|
||||
}
|
||||
|
||||
impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> IncomingPacket<UdpSocket<'a, SpiBus, NetworkImpl, SocketImpl>>
|
||||
impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket>
|
||||
IncomingPacket<UdpSocket<'a, SpiBus, NetworkImpl, SocketImpl>>
|
||||
{
|
||||
pub fn new(mut udp_socket: UdpSocket<'a, SpiBus, NetworkImpl, SocketImpl>) -> Result<Self, SpiBus::Error> {
|
||||
pub fn new(
|
||||
mut udp_socket: UdpSocket<'a, SpiBus, NetworkImpl, SocketImpl>,
|
||||
) -> Result<Self, SpiBus::Error> {
|
||||
let receive_size = udp_socket.socket.get_receive_size(&mut udp_socket.bus)?;
|
||||
|
||||
// Packet frame, as described in W5200 docs sectino 5.2.2.1
|
||||
|
|
@ -25,7 +28,12 @@ impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> IncomingPa
|
|||
// | --- 4 Bytes --- | --- 2 Bytes --- | --- 2 Bytes --- | .... |
|
||||
let read_pointer = udp_socket.socket.get_rx_read_pointer(&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))?;
|
||||
block!(udp_socket.bus.transfer_frame(
|
||||
udp_socket.socket.rx_buffer(),
|
||||
read_pointer,
|
||||
false,
|
||||
&mut header
|
||||
))?;
|
||||
Ok(Self {
|
||||
udp_socket,
|
||||
address: IpAddress::new(header[0], header[1], header[2], header[3]),
|
||||
|
|
@ -46,21 +54,31 @@ impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> IncomingPa
|
|||
// TODO add read_all method
|
||||
|
||||
pub fn done(mut self) -> Result<UdpSocket<'a, SpiBus, NetworkImpl, SocketImpl>, SpiBus::Error> {
|
||||
self.udp_socket.socket.set_rx_read_pointer(&mut self.udp_socket.bus, self.write_pointer)?;
|
||||
self.udp_socket.socket.command(&mut self.udp_socket.bus, socketn::Command::Receive)?;
|
||||
self.udp_socket
|
||||
.socket
|
||||
.set_rx_read_pointer(&mut self.udp_socket.bus, self.write_pointer)?;
|
||||
self.udp_socket
|
||||
.socket
|
||||
.command(&mut self.udp_socket.bus, socketn::Command::Receive)?;
|
||||
Ok(self.udp_socket)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> Iterator for IncomingPacket<UdpSocket<'a, SpiBus, NetworkImpl, SocketImpl>> {
|
||||
impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> Iterator
|
||||
for IncomingPacket<UdpSocket<'a, SpiBus, NetworkImpl, SocketImpl>>
|
||||
{
|
||||
type Item = Result<u8, SpiBus::Error>;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.read_pointer > self.write_pointer {
|
||||
return None;
|
||||
}
|
||||
let mut buffer = [0u8];
|
||||
let result = block!(self.udp_socket.bus.transfer_frame(self.udp_socket.socket.rx_buffer(), self.read_pointer, false, &mut buffer));
|
||||
let result = block!(self.udp_socket.bus.transfer_frame(
|
||||
self.udp_socket.socket.rx_buffer(),
|
||||
self.read_pointer,
|
||||
false,
|
||||
&mut buffer
|
||||
));
|
||||
self.read_pointer += 1;
|
||||
// TODO handle looping back?
|
||||
match result {
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ mod outgoing_packet;
|
|||
|
||||
use crate::bus::ActiveBus;
|
||||
use crate::network::Network;
|
||||
use crate::socket::{Socket, OwnedSockets};
|
||||
use crate::register::socketn;
|
||||
use crate::socket::{OwnedSockets, Socket};
|
||||
use crate::udp::inactive_udp_socket::InactiveUdpSocket;
|
||||
use crate::udp::incoming_packet::IncomingPacket;
|
||||
use crate::udp::outgoing_packet::OutgoingPacket;
|
||||
use crate::w5500::W5500;
|
||||
use crate::register::socketn;
|
||||
use crate::IpAddress;
|
||||
|
||||
pub struct UdpSocket<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> {
|
||||
|
|
@ -33,6 +33,7 @@ impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket>
|
|||
socket.reset_interrupt(&mut bus, socketn::Interrupt::SendOk)?;
|
||||
socket.set_source_port(&mut bus, port)?;
|
||||
socket.set_mode(&mut bus, socketn::Protocol::Udp)?;
|
||||
socket.command(&mut bus, socketn::Command::Open)?;
|
||||
|
||||
Ok(UdpSocket {
|
||||
bus,
|
||||
|
|
@ -44,7 +45,10 @@ 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<IncomingPacket<Self>>, SpiBus::Error> {
|
||||
if !self.socket.has_received(&mut self.bus)? {
|
||||
if !self
|
||||
.socket
|
||||
.has_interrupt(&mut self.bus, socketn::Interrupt::Receive)?
|
||||
{
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(Some(IncomingPacket::new(self)?))
|
||||
|
|
@ -52,11 +56,14 @@ impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket>
|
|||
}
|
||||
|
||||
/// Sends a UDP packet to the specified IP and port, and blocks until it is sent
|
||||
pub fn send(self, host: IpAddress, remote_port: u16) -> Result<OutgoingPacket<Self>, SpiBus::Error> {
|
||||
pub fn send(
|
||||
self,
|
||||
host: IpAddress,
|
||||
remote_port: u16,
|
||||
) -> Result<OutgoingPacket<Self>, SpiBus::Error> {
|
||||
Ok(OutgoingPacket::new(self, host, remote_port)?)
|
||||
}
|
||||
|
||||
|
||||
pub fn deactivate(
|
||||
self,
|
||||
) -> (
|
||||
|
|
|
|||
|
|
@ -1,88 +1,72 @@
|
|||
use crate::bus::ActiveBus;
|
||||
use crate::network::Network;
|
||||
use crate::register::socketn;
|
||||
use crate::socket::Socket;
|
||||
use crate::IpAddress;
|
||||
use crate::udp::UdpSocket;
|
||||
use crate::IpAddress;
|
||||
|
||||
pub struct OutgoingPacket<UdpSocket> {
|
||||
udp_socket: UdpSocket
|
||||
udp_socket: UdpSocket,
|
||||
data_length: u16,
|
||||
}
|
||||
|
||||
impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> OutgoingPacket<UdpSocket<'a, SpiBus, NetworkImpl, SocketImpl>> {
|
||||
impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket>
|
||||
OutgoingPacket<UdpSocket<'a, SpiBus, NetworkImpl, SocketImpl>>
|
||||
{
|
||||
pub fn new(
|
||||
mut udp_socket: UdpSocket<'a, SpiBus, NetworkImpl, SocketImpl>,
|
||||
host: IpAddress,
|
||||
port: u16,
|
||||
) -> Result<Self, SpiBus::Error> {
|
||||
udp_socket
|
||||
.socket
|
||||
.set_destination_ip(&mut udp_socket.bus, host)?;
|
||||
udp_socket
|
||||
.socket
|
||||
.set_destination_port(&mut udp_socket.bus, port)?;
|
||||
udp_socket
|
||||
.socket
|
||||
.set_tx_read_pointer(&mut udp_socket.bus, 0)?;
|
||||
Ok(Self {
|
||||
udp_socket,
|
||||
data_length: 0,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new(udp_socket: UdpSocket<'a, SpiBus, NetworkImpl, SocketImpl>, host: IpAddress, port: u16) -> Result<Self, SpiBus::Error> {
|
||||
Ok(Self { udp_socket })
|
||||
// let (w5500, UdpSocket(socket)) = self;
|
||||
pub fn write(&mut self, mut data: &mut [u8]) -> Result<(), SpiBus::Error> {
|
||||
block!(self.udp_socket.bus.transfer_frame(
|
||||
self.udp_socket.socket.tx_buffer(),
|
||||
self.data_length,
|
||||
true,
|
||||
&mut data
|
||||
))?;
|
||||
self.data_length += data.len() as u16;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// {
|
||||
|
||||
// // TODO set up packet destination
|
||||
// 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)
|
||||
// ],
|
||||
// )?;
|
||||
// }
|
||||
|
||||
// // TODO set read/write pointers
|
||||
// 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]],
|
||||
// );
|
||||
// }
|
||||
|
||||
// // TODO write body to buffer
|
||||
// w5500.write_to(
|
||||
// socket.tx_register_at(0x00_00),
|
||||
// &data[..data_length as usize],
|
||||
// )?;
|
||||
|
||||
// // TODO execute send command
|
||||
// w5500.write_to(
|
||||
// socket.at(SocketRegister::Command),
|
||||
// &[SocketCommand::Send as u8],
|
||||
// )?;
|
||||
|
||||
// // TODO wait until send is complete
|
||||
// for _ in 0..0xFFFF {
|
||||
// // wait until sent
|
||||
// if w5500.is_interrupt_set(*socket, Interrupt::SendOk)? {
|
||||
// w5500.reset_interrupt(*socket, Interrupt::SendOk)?;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// // TODO listen for incoming sockets
|
||||
// w5500.write_to(
|
||||
// socket.at(SocketRegister::Mode),
|
||||
// &[
|
||||
// Protocol::UDP as u8, // Socket Mode Register
|
||||
// SocketCommand::Open as u8, // Socket Command Register
|
||||
// ],
|
||||
// )?;
|
||||
// Ok(())
|
||||
pub fn send(mut self) -> Result<UdpSocket<'a, SpiBus, NetworkImpl, SocketImpl>, SpiBus::Error> {
|
||||
self.udp_socket
|
||||
.socket
|
||||
.set_tx_write_pointer(&mut self.udp_socket.bus, self.data_length)?;
|
||||
self.udp_socket
|
||||
.socket
|
||||
.command(&mut self.udp_socket.bus, socketn::Command::Send)?;
|
||||
loop {
|
||||
// wait until send is complete
|
||||
if self
|
||||
.udp_socket
|
||||
.socket
|
||||
.has_interrupt(&mut self.udp_socket.bus, socketn::Interrupt::SendOk)?
|
||||
{
|
||||
self.udp_socket
|
||||
.socket
|
||||
.reset_interrupt(&mut self.udp_socket.bus, socketn::Interrupt::SendOk)?;
|
||||
break;
|
||||
}
|
||||
}
|
||||
self.udp_socket
|
||||
.socket
|
||||
.command(&mut self.udp_socket.bus, socketn::Command::Open)?;
|
||||
Ok(self.udp_socket)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue