diff --git a/src/udp/packet.rs b/src/udp/incoming_packet.rs similarity index 84% rename from src/udp/packet.rs rename to src/udp/incoming_packet.rs index a64318b..8375fd8 100644 --- a/src/udp/packet.rs +++ b/src/udp/incoming_packet.rs @@ -6,7 +6,7 @@ use crate::socket::Socket; use crate::IpAddress; use crate::register::socketn; -pub struct UdpPacket { +pub struct IncomingPacket { udp_socket: UdpSocket, address: IpAddress, remote_port: u16, @@ -14,7 +14,7 @@ pub struct UdpPacket { write_pointer: u16, } -impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> UdpPacket> +impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> IncomingPacket> { pub fn new(mut udp_socket: UdpSocket<'a, SpiBus, NetworkImpl, SocketImpl>) -> Result { let receive_size = udp_socket.socket.get_receive_size(&mut udp_socket.bus)?; @@ -26,7 +26,7 @@ impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> UdpPacket< 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))?; - Ok(UdpPacket { + Ok(Self { udp_socket, address: IpAddress::new(header[0], header[1], header[2], header[3]), remote_port: BigEndian::read_u16(&header[4..5]), @@ -43,11 +43,7 @@ impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> UdpPacket< self.address } - pub fn read(&mut self) -> Result { - let mut buffer = [0u8]; - block!(self.udp_socket.bus.transfer_frame(self.udp_socket.socket.rx_buffer(), self.read_pointer, false, &mut buffer))?; - Ok(buffer[0]) - } + // TODO add read_all method pub fn done(mut self) -> Result, SpiBus::Error> { self.udp_socket.socket.set_rx_read_pointer(&mut self.udp_socket.bus, self.write_pointer)?; @@ -57,7 +53,7 @@ impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> UdpPacket< } -impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> Iterator for UdpPacket> { +impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> Iterator for IncomingPacket> { type Item = Result; fn next(&mut self) -> Option { if self.read_pointer > self.write_pointer { @@ -66,6 +62,7 @@ impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> Iterator f 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)); self.read_pointer += 1; + // TODO handle looping back? match result { Ok(_) => Some(Ok(buffer[0])), Result::Err(error) => Some(Err(error)), diff --git a/src/udp/mod.rs b/src/udp/mod.rs index 76a8fcb..498d82d 100644 --- a/src/udp/mod.rs +++ b/src/udp/mod.rs @@ -1,13 +1,16 @@ mod inactive_udp_socket; -mod packet; +mod incoming_packet; +mod outgoing_packet; use crate::bus::ActiveBus; use crate::network::Network; use crate::socket::{Socket, OwnedSockets}; use crate::udp::inactive_udp_socket::InactiveUdpSocket; -use crate::udp::packet::UdpPacket; +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> { bus: SpiBus, @@ -40,88 +43,18 @@ 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>, SpiBus::Error> { + pub fn receive(mut self) -> Result>, SpiBus::Error> { if !self.socket.has_received(&mut self.bus)? { Ok(None) } else { - Ok(Some(UdpPacket::new(self)?)) + Ok(Some(IncomingPacket::new(self)?)) } } -// /// 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(()) -// } + /// 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, SpiBus::Error> { + Ok(OutgoingPacket::new(self, host, remote_port)?) + } pub fn deactivate( diff --git a/src/udp/outgoing_packet.rs b/src/udp/outgoing_packet.rs new file mode 100644 index 0000000..952ddc0 --- /dev/null +++ b/src/udp/outgoing_packet.rs @@ -0,0 +1,88 @@ +use crate::bus::ActiveBus; +use crate::network::Network; +use crate::socket::Socket; +use crate::IpAddress; +use crate::udp::UdpSocket; + +pub struct OutgoingPacket { + udp_socket: UdpSocket +} + +impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> OutgoingPacket> { + + pub fn new(udp_socket: UdpSocket<'a, SpiBus, NetworkImpl, SocketImpl>, host: IpAddress, port: u16) -> Result { + Ok(Self { udp_socket }) +// let (w5500, UdpSocket(socket)) = self; + +// { + +// // 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(()) + } +}