diff --git a/src/device.rs b/src/device.rs index 0807899..15cb749 100644 --- a/src/device.rs +++ b/src/device.rs @@ -1,4 +1,4 @@ -use bit_field::BitArray; +use bit_field::BitField; use crate::bus::{Bus, FourWire, ThreeWire}; use crate::host::Host; @@ -23,35 +23,93 @@ impl From for ResetError { } } +pub trait State { + type Host: Host; + + fn socket(&mut self) -> Option; + fn release_socket(&mut self, socket: Socket); + fn any_allocated(&self) -> bool; + fn host(&self) -> &Self::Host; +} + #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DeviceState { host: HostImpl, - sockets: [u8; 1], + sockets: u8, } -pub struct Device { - pub(crate) bus: SpiBus, - state: DeviceState, -} - -impl Device { - pub(crate) fn new(bus: SpiBus, host: HostImpl) -> Self { - Device { - bus, - state: DeviceState { - host, - sockets: [0b11111111], - }, +impl DeviceState { + pub fn new(host: HostImpl) -> Self { + Self { + sockets: 0xFF, + host, } } +} - pub fn get_state(&self) -> &DeviceState { +impl State for DeviceState { + type Host = HostImpl; + + fn socket(&mut self) -> Option { + for index in 0..8 { + if self.sockets.get_bit(index) { + self.sockets.set_bit(index, false); + return Some(Socket::new(index as u8)); + } + } + None + } + + fn release_socket(&mut self, socket: Socket) { + self.sockets.set_bit(socket.index.into(), true); + } + + fn host(&self) -> &Self::Host { + &self.host + } + + fn any_allocated(&self) -> bool { + self.sockets != 0xFF + } +} + +impl<'a, T: State> State for &'a mut T { + type Host = T::Host; + + fn socket(&mut self) -> Option { + T::socket(self) + } + + fn release_socket(&mut self, socket: Socket) { + T::release_socket(self, socket) + } + + fn host(&self) -> &Self::Host { + T::host(self) + } + + fn any_allocated(&self) -> bool { + T::any_allocated(self) + } +} + +pub struct Device { + pub(crate) bus: SpiBus, + state: StateImpl, +} + +impl Device { + pub(crate) fn new(bus: SpiBus, state: StateImpl) -> Self { + Device { bus, state } + } + + pub fn get_state(&self) -> &StateImpl { &self.state } pub fn reset(mut self) -> Result, ResetError> { - if self.state.sockets != [0b11111111] { + if self.state.any_allocated() { Err(ResetError::SocketsNotReleased) } else { self.reset_device()?; @@ -59,23 +117,17 @@ impl Device { } } - pub fn release(self) -> (SpiBus, HostImpl) { - (self.bus, self.state.host) + pub fn release(self) -> (SpiBus, StateImpl) { + (self.bus, self.state) } pub fn take_socket(&mut self) -> Option { // TODO maybe return Future that resolves when release_socket invoked - for index in 0..8 { - if self.state.sockets.get_bit(index) { - self.state.sockets.set_bit(index, false); - return Some(Socket::new(index as u8)); - } - } - None + self.state.socket() } pub fn release_socket(&mut self, socket: Socket) { - self.state.sockets.set_bit(socket.index.into(), true); + self.state.release_socket(socket) } pub fn gateway(&mut self) -> Result { @@ -230,18 +282,25 @@ impl Device { Ok(retry_count_register[0]) } - pub fn deactivate(self) -> (SpiBus, InactiveDevice) { + pub fn deactivate(self) -> (SpiBus, InactiveDevice) { (self.bus, InactiveDevice(self.state)) } } #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub struct InactiveDevice(DeviceState); +pub struct InactiveDevice(StateImpl); -impl InactiveDevice { +impl InactiveDevice { /// Activates the device by taking ownership - pub fn activate(self, bus: SpiBus) -> Device { + pub fn activate(self, bus: SpiBus) -> Device { Device { bus, state: self.0 } } + + pub fn activate_ref(&mut self, bus: SpiBus) -> Device { + Device { + bus, + state: &mut self.0, + } + } } diff --git a/src/tcp.rs b/src/tcp.rs index 47cfb24..4fb1311 100644 --- a/src/tcp.rs +++ b/src/tcp.rs @@ -1,4 +1,9 @@ -use crate::{bus::Bus, device::Device, host::Host, register::socketn, socket::Socket}; +use crate::{ + bus::Bus, + device::{Device, State}, + register::socketn, + socket::Socket, +}; use embedded_nal::{nb, IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4, TcpClientStack}; @@ -200,7 +205,7 @@ impl TcpSocket { } } -impl TcpClientStack for Device { +impl TcpClientStack for Device { type TcpSocket = TcpSocket; type Error = TcpSocketError; diff --git a/src/udp.rs b/src/udp.rs index a7a2d15..8e8ed4b 100644 --- a/src/udp.rs +++ b/src/udp.rs @@ -4,8 +4,7 @@ use embedded_nal::{nb, IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4, UdpClientStac use crate::{ bus::Bus, - device::Device, - host::Host, + device::{Device, State}, register::socketn::{self, Status}, socket::Socket, }; @@ -470,10 +469,10 @@ impl From> for nb::Error { } } -impl UdpClientStack for Device +impl UdpClientStack for Device where SpiBus: Bus, - HostImpl: Host, + StateImpl: State, { type UdpSocket = UdpSocket; type Error = UdpSocketError; @@ -521,10 +520,10 @@ where } } -impl UdpFullStack for Device +impl UdpFullStack for Device where SpiBus: Bus, - HostImpl: Host, + StateImpl: State, { fn bind(&mut self, socket: &mut Self::UdpSocket, local_port: u16) -> Result<(), Self::Error> { socket.set_port(&mut self.bus, local_port)?; diff --git a/src/uninitialized_device.rs b/src/uninitialized_device.rs index 899b963..d2eb971 100644 --- a/src/uninitialized_device.rs +++ b/src/uninitialized_device.rs @@ -2,7 +2,7 @@ use embedded_hal::spi::SpiDevice; use embedded_nal::Ipv4Addr; use crate::bus::{Bus, FourWire, ThreeWire}; -use crate::device::Device; +use crate::device::{Device, DeviceState}; use crate::host::{Dhcp, Host, Manual}; use crate::raw_device::RawDevice; use crate::{ @@ -54,7 +54,7 @@ impl UninitializedDevice { self, mac: MacAddress, mode_options: Mode, - ) -> Result, InitializeError> { + ) -> Result>, InitializeError> { let host = Dhcp::new(mac); self.initialize_with_host(host, mode_options) } @@ -67,7 +67,7 @@ impl UninitializedDevice { mac: MacAddress, ip: Ipv4Addr, mode_options: Mode, - ) -> Result, InitializeError> { + ) -> Result>, InitializeError> { let mut ip_bytes = ip.octets(); ip_bytes[3] = 1; let gateway = Ipv4Addr::from(ip_bytes); @@ -82,7 +82,7 @@ impl UninitializedDevice { gateway: Ipv4Addr, subnet: Ipv4Addr, mode_options: Mode, - ) -> Result, InitializeError> { + ) -> Result>, InitializeError> { let host = Manual::new(mac, ip, gateway, subnet); self.initialize_with_host(host, mode_options) } @@ -91,7 +91,7 @@ impl UninitializedDevice { mut self, mut host: HostImpl, mode_options: Mode, - ) -> Result, InitializeError> { + ) -> Result>, InitializeError> { #[cfg(not(feature = "no-chip-version-assertion"))] self.assert_chip_version(0x4)?; @@ -100,7 +100,7 @@ impl UninitializedDevice { self.set_mode(mode_options)?; host.refresh(&mut self.bus)?; - Ok(Device::new(self.bus, host)) + Ok(Device::new(self.bus, DeviceState::new(host))) } pub fn initialize_macraw(