From cbb346889311ecf48e8d27e33678815ff6925b7c Mon Sep 17 00:00:00 2001 From: Alex M Date: Mon, 10 Aug 2020 12:28:01 -0700 Subject: [PATCH] Add constructors for network types. --- src/lib.rs | 103 ++++++++------------------------------ src/net.rs | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 166 insertions(+), 81 deletions(-) create mode 100644 src/net.rs diff --git a/src/lib.rs b/src/lib.rs index 7032976..5c38700 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,9 @@ #[macro_use(block)] extern crate nb; +pub mod net; +pub use net::{Ipv4Addr, MacAddress}; + use byteorder::BigEndian; use byteorder::ByteOrder; use embedded_hal::digital::v2::OutputPin; @@ -20,65 +23,6 @@ const FIXED_DATA_LENGTH_2_BYTES: u8 = 0b_10; #[allow(unused)] const FIXED_DATA_LENGTH_4_BYTES: u8 = 0b_11; -/// IP Address struct. Represents an IP address as a u8 array of length 4. -/// Can be instantiated with [`IpAddress::new`] -#[derive(Copy, Clone, PartialOrd, PartialEq, Eq, Default, Debug)] -pub struct IpAddress { - pub address: [u8; 4], -} - -impl IpAddress { - /// Instantiate a new IP address with u8s for each address fragment - pub fn new(a0: u8, a1: u8, a2: u8, a3: u8) -> IpAddress { - IpAddress { - address: [a0, a1, a2, a3], - } - } -} - -impl ::core::fmt::Display for IpAddress { - /// String formatter for IP addresses, useful for debugging output - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!( - f, - "{}.{}.{}.{}", - self.address[0], self.address[1], self.address[2], self.address[3], - ) - } -} - -/// MAC address struct. Represents a MAC address as a u8 array of length 6. -/// Can be instantiated with [`MacAddress::new`] -#[derive(Copy, Clone, PartialOrd, PartialEq, Default, Debug)] -pub struct MacAddress { - pub address: [u8; 6], -} - -impl MacAddress { - /// Instantiate a new MAC address with u8s for each address fragment - pub fn new(a0: u8, a1: u8, a2: u8, a3: u8, a4: u8, a5: u8) -> MacAddress { - MacAddress { - address: [a0, a1, a2, a3, a4, a5], - } - } -} - -impl ::core::fmt::Display for MacAddress { - /// String formatter for MAC addresses, useful for debugging output - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!( - f, - "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}", - self.address[0], - self.address[1], - self.address[2], - self.address[3], - self.address[4], - self.address[5], - ) - } -} - /// Error enum that represents the union between SPI hardware errors and digital IO pin errors. /// Returned as an Error type by many [`ActiveW5500`] operations that talk to the chip #[derive(Copy, Clone, Debug)] @@ -240,17 +184,17 @@ impl< /// Sets the IP address of the network gateway (your router's address) pub fn set_gateway( &mut self, - gateway: IpAddress, + gateway: Ipv4Addr, ) -> Result<(), TransferError> { - self.write_to(Register::CommonRegister(0x00_01_u16), &gateway.address) + self.write_to(Register::CommonRegister(0x00_01_u16), &gateway.octets) } /// Sets the subnet on the network (for example 255.255.255.0 for /24 subnets) pub fn set_subnet( &mut self, - subnet: IpAddress, + subnet: Ipv4Addr, ) -> Result<(), TransferError> { - self.write_to(Register::CommonRegister(0x00_05_u16), &subnet.address) + self.write_to(Register::CommonRegister(0x00_05_u16), &subnet.octets) } /// Sets the MAC address of the W5500 device on the network. @@ -271,25 +215,22 @@ impl< &mut self, mac: MacAddress, ) -> Result<(), TransferError> { - self.write_to(Register::CommonRegister(0x00_09_u16), &mac.address) + self.write_to(Register::CommonRegister(0x00_09_u16), &mac.octets) } /// Sets the IP address of the W5500 device. Must be within the range and permitted by the /// gateway or the device will not be accessible. - pub fn set_ip( - &mut self, - ip: IpAddress, - ) -> Result<(), TransferError> { - self.write_to(Register::CommonRegister(0x00_0F_u16), &ip.address) + pub fn set_ip(&mut self, ip: Ipv4Addr) -> Result<(), TransferError> { + self.write_to(Register::CommonRegister(0x00_0F_u16), &ip.octets) } - /// Reads the 4 bytes from any ip register and returns the value as an [`IpAddress`] + /// Reads the 4 bytes from any ip register and returns the value as an [`Ipv4Addr`] pub fn read_ip( &mut self, register: Register, - ) -> Result> { - let mut ip = IpAddress::default(); - self.read_from(register, &mut ip.address)?; + ) -> Result> { + let mut ip = Ipv4Addr::default(); + self.read_from(register, &mut ip.octets)?; Ok(ip) } @@ -508,11 +449,11 @@ pub trait Udp { fn receive( &mut self, target_buffer: &mut [u8], - ) -> Result, Self::Error>; + ) -> Result, Self::Error>; fn blocking_send( &mut self, - host: &IpAddress, + host: &Ipv4Addr, host_port: u16, data: &[u8], ) -> Result<(), Self::Error>; @@ -528,7 +469,7 @@ impl> Udp fn receive( &mut self, destination: &mut [u8], - ) -> Result, Self::Error> { + ) -> Result, Self::Error> { let (w5500, UdpSocket(socket)) = self; if w5500.read_u8(socket.at(SocketRegister::InterruptMask))? & 0x04 == 0 { @@ -579,7 +520,7 @@ impl> Udp /// Sends a UDP packet to the specified IP and port, and blocks until it is fully sent fn blocking_send( &mut self, - host: &IpAddress, + host: &Ipv4Addr, host_port: u16, data: &[u8], ) -> Result<(), Self::Error> { @@ -601,10 +542,10 @@ impl> Udp 0x00, 0x00, 0x00, // destination mac - host.address[0], - host.address[1], - host.address[2], - host.address[3], // target IP + host.octets[0], + host.octets[1], + host.octets[2], + host.octets[3], // target IP host_port[0], host_port[1], // destination port (5354) ], diff --git a/src/net.rs b/src/net.rs new file mode 100644 index 0000000..b8a9c1a --- /dev/null +++ b/src/net.rs @@ -0,0 +1,144 @@ +//! Networking data types. +//! +//! There may a standard for embedded networking in the future, see +//! [rust-embedded issue 348] and [RFC 2832] +//! +//! This is mostly ripped directly from [std::net]. +//! +//! [rust-embedded issue 348]: https://github.com/rust-embedded/wg/issues/348 +//! [std::net]: https://doc.rust-lang.org/std/net/index.html +//! [RFC 2832]: https://github.com/rust-lang/rfcs/pull/2832 +#![deny(unsafe_code, missing_docs, warnings)] + +/// Ipv4Addr address struct. Can be instantiated with `Ipv4Addr::new`. +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Default)] +pub struct Ipv4Addr { + /// Octets of the Ipv4Addr address. + pub octets: [u8; 4], +} + +impl Ipv4Addr { + /// Creates a new IPv4 address from four eight-bit octets. + /// + /// The result will represent the IP address `a`.`b`.`c`.`d`. + /// + /// # Examples + /// + /// ``` + /// use w5500::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::new(127, 0, 0, 1); + /// ``` + #[allow(clippy::many_single_char_names)] + pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr { + Ipv4Addr { + octets: [a, b, c, d], + } + } + + /// An IPv4 address with the address pointing to localhost: 127.0.0.1. + /// + /// # Examples + /// + /// ``` + /// use w5500::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::LOCALHOST; + /// assert_eq!(addr, Ipv4Addr::new(127, 0, 0, 1)); + /// ``` + pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1); + + /// An IPv4 address representing an unspecified address: 0.0.0.0 + /// + /// # Examples + /// + /// ``` + /// use w5500::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::UNSPECIFIED; + /// assert_eq!(addr, Ipv4Addr::new(0, 0, 0, 0)); + /// ``` + pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0); + + /// An IPv4 address representing the broadcast address: 255.255.255.255 + /// + /// # Examples + /// + /// ``` + /// use w5500::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::BROADCAST; + /// assert_eq!(addr, Ipv4Addr::new(255, 255, 255, 255)); + /// ``` + pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255); +} + +impl ::core::fmt::Display for Ipv4Addr { + /// String formatter for Ipv4Addr addresses. + fn fmt(&self, fmt: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!( + fmt, + "{}.{}.{}.{}", + self.octets[0], self.octets[1], self.octets[2], self.octets[3], + ) + } +} + +/// MAC address struct. Can be instantiated with `MacAddress::new`. +/// +/// This is an EUI-48 MAC address (previously called MAC-48). +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Default)] +pub struct MacAddress { + /// Octets of the MAC address. + pub octets: [u8; 6], +} + +impl MacAddress { + /// Creates a new EUI-48 MAC address from six eight-bit octets. + /// + /// The result will represent the EUI-48 MAC address + /// `a`:`b`:`c`:`d`:`e`:`f`. + /// + /// # Examples + /// + /// ``` + /// use w5500::net::MacAddress; + /// + /// let addr = MacAddress::new(0x00, 0x00, 0x5E, 0x00, 0x00, 0x00); + /// ``` + #[allow(clippy::many_single_char_names)] + pub const fn new(a: u8, b: u8, c: u8, d: u8, e: u8, f: u8) -> MacAddress { + MacAddress { + octets: [a, b, c, d, e, f], + } + } + + /// An EUI-48 MAC address representing an unspecified address: + /// 00:00:00:00:00:00 + /// + /// # Examples + /// + /// ``` + /// use w5500::net::MacAddress; + /// + /// let addr = MacAddress::UNSPECIFIED; + /// assert_eq!(addr, MacAddress::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00)); + /// ``` + pub const UNSPECIFIED: Self = MacAddress::new(0, 0, 0, 0, 0, 0); +} + +impl ::core::fmt::Display for MacAddress { + /// String formatter for MacAddress addresses. + fn fmt(&self, fmt: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!( + fmt, + "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}", + self.octets[0], + self.octets[1], + self.octets[2], + self.octets[3], + self.octets[4], + self.octets[5], + ) + } +}