Add UDP listen + receive
This commit is contained in:
parent
f28b948dac
commit
3343dc190d
1 changed files with 108 additions and 28 deletions
136
src/lib.rs
136
src/lib.rs
|
|
@ -95,36 +95,10 @@ impl<E, S: FullDuplex<u8, Error=E> + Sized, O: OutputPin> W5500<E, S, O> {
|
||||||
|
|
||||||
self.set_mac(&MacAddress::new(0x00, 0x08, 0xDC, 0x01, 0x02, 0x03))?;
|
self.set_mac(&MacAddress::new(0x00, 0x08, 0xDC, 0x01, 0x02, 0x03))?;
|
||||||
|
|
||||||
|
|
||||||
self.set_ip(&IpAddress::new(192, 168, 3, 222))?;
|
self.set_ip(&IpAddress::new(192, 168, 3, 222))?;
|
||||||
self.set_subnet(&IpAddress::new(255, 255, 255, 0))?;
|
self.set_subnet(&IpAddress::new(255, 255, 255, 0))?;
|
||||||
self.set_gateway(&IpAddress::new(192, 168, 3, 1))?;
|
self.set_gateway(&IpAddress::new(192, 168, 3, 1))?;
|
||||||
|
|
||||||
// socket 0 with udp
|
|
||||||
|
|
||||||
self.write_to(
|
|
||||||
Register::Socket0Register(0x00_00),
|
|
||||||
&[
|
|
||||||
0b0000_0010, // UDP
|
|
||||||
0x01 // OPEN / initialize
|
|
||||||
]
|
|
||||||
);
|
|
||||||
self.write_to(
|
|
||||||
Register::Socket0Register(0x00_04),
|
|
||||||
&[
|
|
||||||
0, 50, // local port u16
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // destination mac
|
|
||||||
192, 168, 3, 55, // target IP
|
|
||||||
0x14, 0xEA, // destination port (5354)
|
|
||||||
]
|
|
||||||
)?;
|
|
||||||
|
|
||||||
self.write_to(
|
|
||||||
Register::Socket0Register(0x00_01),
|
|
||||||
&[
|
|
||||||
0x20 // SEND
|
|
||||||
]
|
|
||||||
)?;
|
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -208,8 +182,8 @@ impl<E, S: FullDuplex<u8, Error=E> + Sized, O: OutputPin> W5500<E, S, O> {
|
||||||
self.write_to(
|
self.write_to(
|
||||||
socket.register_at(0x00_00),
|
socket.register_at(0x00_00),
|
||||||
&[
|
&[
|
||||||
0b0000_0010, // UDP
|
Protocol::UDP as u8, // Socket Mode Register
|
||||||
0x01 // OPEN / initialize
|
SocketCommand::Open as u8 // Socket Command Regsiter
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -256,6 +230,80 @@ impl<E, S: FullDuplex<u8, Error=E> + Sized, O: OutputPin> W5500<E, S, O> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn listen_udp(&mut self, socket: Socket, port: u16) -> Result<(), E> {
|
||||||
|
self.write_u16(
|
||||||
|
socket.register_at(0x00_04),
|
||||||
|
port
|
||||||
|
)?;
|
||||||
|
self.write_to(
|
||||||
|
socket.register_at(0x00_00),
|
||||||
|
&[
|
||||||
|
Protocol::UDP as u8, // Socket Mode Register
|
||||||
|
SocketCommand::Open as u8 // Socket Command Regsiter
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// TODO destination buffer has to be as large as the receive buffer or complete read is not guaranteed
|
||||||
|
pub fn try_receive_udp(&mut self, socket: Socket, destination: &mut [u8]) -> Result<Option<(IpAddress, u16, usize)>, E> {
|
||||||
|
if self.read_u8(socket.register_at(0x00_2c))? & 0x04 == 0 {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
let receive_size = loop {
|
||||||
|
let s0 = self.read_u16(socket.register_at(0x00_26))?;
|
||||||
|
let s1 = self.read_u16(socket.register_at(0x00_26))?;
|
||||||
|
if s0 == s1 {
|
||||||
|
break s0 as usize;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if receive_size > 8 {
|
||||||
|
let read_pointer = self.read_u16(socket.register_at(0x00_28))?;
|
||||||
|
|
||||||
|
// |<-- read_pointer read_pointer + received_size -->|
|
||||||
|
// |Destination IP Address | Destination Port | Byte Size of DATA | Actual DATA ... |
|
||||||
|
// | --- 4 Bytes --- | --- 2 Bytes --- | --- 2 Bytes --- | .... |
|
||||||
|
|
||||||
|
let ip = self.read_ip(socket.rx_register_at(read_pointer))?;
|
||||||
|
let port = self.read_u16(socket.rx_register_at(read_pointer+4))?;
|
||||||
|
let data_length = destination.len().min(self.read_u16(socket.rx_register_at(read_pointer+6))? as usize);
|
||||||
|
|
||||||
|
self.read_from(
|
||||||
|
socket.rx_register_at(read_pointer+8),
|
||||||
|
&mut destination[..data_length]
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// self.read_from(socket.register_at(0x00_0C), &mut ip.address)?;
|
||||||
|
// self.read_u16(socket.register_at(0x00_10))?;
|
||||||
|
|
||||||
|
// reset
|
||||||
|
self.write_u16(socket.register_at(0x00_28), read_pointer + receive_size as u16)?;
|
||||||
|
self.write_u8(socket.register_at(0x00_01), SocketCommand::Recv as u8)?;
|
||||||
|
|
||||||
|
Ok(Some((ip, port, data_length)))
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_u8(&mut self, register: Register) -> Result<u8, E> {
|
||||||
|
let mut buffer = [0u8; 1];
|
||||||
|
self.read_from(register, &mut buffer)?;
|
||||||
|
Ok(buffer[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_u16(&mut self, register: Register) -> Result<u16, E> {
|
||||||
|
let mut buffer = [0u8; 2];
|
||||||
|
self.read_from(register, &mut buffer)?;
|
||||||
|
Ok(BigEndian::read_u16(&buffer))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_ip(&mut self, register: Register) -> Result<IpAddress, E> {
|
||||||
|
let mut ip = IpAddress::default();
|
||||||
|
self.read_from(register, &mut ip.address)?;
|
||||||
|
Ok(ip)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn read_from(&mut self, register: Register, target: &mut [u8]) -> Result<(), E> {
|
pub fn read_from(&mut self, register: Register, target: &mut [u8]) -> Result<(), E> {
|
||||||
self.chip_select();
|
self.chip_select();
|
||||||
let mut request = [0_u8, 0_u8, register.control_byte() | COMMAND_READ | VARIABLE_DATA_LENGTH];
|
let mut request = [0_u8, 0_u8, register.control_byte() | COMMAND_READ | VARIABLE_DATA_LENGTH];
|
||||||
|
|
@ -267,6 +315,16 @@ impl<E, S: FullDuplex<u8, Error=E> + Sized, O: OutputPin> W5500<E, S, O> {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn write_u8(&mut self, register: Register, value: u8) -> Result<(), E> {
|
||||||
|
self.write_to(register, &[value])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_u16(&mut self, register: Register, value: u16) -> Result<(), E> {
|
||||||
|
let mut data = [0u8; 2];
|
||||||
|
BigEndian::write_u16(&mut data, value);
|
||||||
|
self.write_to(register, &data)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn write_to(&mut self, register: Register, data: &[u8]) -> Result<(), E> {
|
pub fn write_to(&mut self, register: Register, data: &[u8]) -> Result<(), E> {
|
||||||
self.chip_select();
|
self.chip_select();
|
||||||
let mut request = [0_u8, 0_u8, register.control_byte() | COMMAND_WRITE | VARIABLE_DATA_LENGTH];
|
let mut request = [0_u8, 0_u8, register.control_byte() | COMMAND_WRITE | VARIABLE_DATA_LENGTH];
|
||||||
|
|
@ -320,6 +378,28 @@ fn u16_to_be_bytes(u16: u16) -> [u8; 2] {
|
||||||
bytes
|
bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(u8)]
|
||||||
|
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||||
|
pub enum Protocol {
|
||||||
|
TCP = 0b0001,
|
||||||
|
UDP = 0b0010,
|
||||||
|
MACRAW = 0b0100,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(u8)]
|
||||||
|
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||||
|
pub enum SocketCommand {
|
||||||
|
Open = 0x01,
|
||||||
|
Listen = 0x02,
|
||||||
|
Connect = 0x04,
|
||||||
|
Disconnect = 0x08,
|
||||||
|
Close = 0x10,
|
||||||
|
Send = 0x20,
|
||||||
|
SendMac = 0x21,
|
||||||
|
SendKeep = 0x22,
|
||||||
|
Recv = 0x40,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
|
#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
|
||||||
pub enum Socket {
|
pub enum Socket {
|
||||||
Socket0,
|
Socket0,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue