Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add constructors for network types. #21

Merged
merged 1 commit into from
Aug 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 22 additions & 81 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)]
Expand Down Expand Up @@ -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<SpiError, ChipSelectError>> {
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<SpiError, ChipSelectError>> {
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.
Expand All @@ -271,25 +215,22 @@ impl<
&mut self,
mac: MacAddress,
) -> Result<(), TransferError<SpiError, ChipSelectError>> {
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<SpiError, ChipSelectError>> {
self.write_to(Register::CommonRegister(0x00_0F_u16), &ip.address)
pub fn set_ip(&mut self, ip: Ipv4Addr) -> Result<(), TransferError<SpiError, ChipSelectError>> {
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<IpAddress, TransferError<SpiError, ChipSelectError>> {
let mut ip = IpAddress::default();
self.read_from(register, &mut ip.address)?;
) -> Result<Ipv4Addr, TransferError<SpiError, ChipSelectError>> {
let mut ip = Ipv4Addr::default();
self.read_from(register, &mut ip.octets)?;
Ok(ip)
}

Expand Down Expand Up @@ -508,11 +449,11 @@ pub trait Udp {
fn receive(
&mut self,
target_buffer: &mut [u8],
) -> Result<Option<(IpAddress, u16, usize)>, Self::Error>;
) -> Result<Option<(Ipv4Addr, u16, usize)>, Self::Error>;

fn blocking_send(
&mut self,
host: &IpAddress,
host: &Ipv4Addr,
host_port: u16,
data: &[u8],
) -> Result<(), Self::Error>;
Expand All @@ -528,7 +469,7 @@ impl<ChipSelect: OutputPin, Spi: FullDuplex<u8>> Udp
fn receive(
&mut self,
destination: &mut [u8],
) -> Result<Option<(IpAddress, u16, usize)>, Self::Error> {
) -> Result<Option<(Ipv4Addr, u16, usize)>, Self::Error> {
let (w5500, UdpSocket(socket)) = self;

if w5500.read_u8(socket.at(SocketRegister::InterruptMask))? & 0x04 == 0 {
Expand Down Expand Up @@ -579,7 +520,7 @@ impl<ChipSelect: OutputPin, Spi: FullDuplex<u8>> 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> {
Expand All @@ -601,10 +542,10 @@ impl<ChipSelect: OutputPin, Spi: FullDuplex<u8>> 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)
],
Expand Down
144 changes: 144 additions & 0 deletions src/net.rs
Original file line number Diff line number Diff line change
@@ -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],
)
}
}