Added Packet struct and beginnings of packet reading
This commit is contained in:
parent
95ca1be001
commit
d0f5792028
4 changed files with 193 additions and 0 deletions
|
|
@ -54,4 +54,13 @@ pub mod socketn {
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,23 @@ pub trait Socket {
|
|||
block!(bus.transfer_frame(self.register(), socketn::SOURCE_PORT, true, &mut data))?;
|
||||
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 = (
|
||||
|
|
|
|||
101
src/udp/mod.rs
101
src/udp/mod.rs
|
|
@ -1,11 +1,15 @@
|
|||
mod inactive_udp_socket;
|
||||
mod packet;
|
||||
|
||||
use byteorder::{BigEndian, ByteOrder};
|
||||
use crate::IpAddress;
|
||||
use crate::bus::ActiveBus;
|
||||
use crate::network::Network;
|
||||
use crate::socket::OwnedSockets;
|
||||
use crate::socket::Socket;
|
||||
use crate::udp::inactive_udp_socket::InactiveUdpSocket;
|
||||
use crate::w5500::W5500;
|
||||
use crate::udp::packet::UdpPacket;
|
||||
use register::socketn;
|
||||
|
||||
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(
|
||||
self,
|
||||
) -> (
|
||||
|
|
|
|||
66
src/udp/packet.rs
Normal file
66
src/udp/packet.rs
Normal 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
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue