From f63a58ae079cfafd405b08890e3e8de72e5f4324 Mon Sep 17 00:00:00 2001 From: David McCurley <44048235+mrengineer7777@users.noreply.github.com> Date: Tue, 3 May 2022 13:29:41 -0500 Subject: [PATCH 1/2] Adding MacAddress, MacAddress8 Adding New Classes MacAddress, MacAddress8 in the style of IPAddress. Note I didn't include Printable, as I don't understand how that works. If someone else wants to add it later, they are welcome to do so. This is my first time contributing to this repository, so please feel free to point out any mistakes. This library originated on arduino-esp32 (https://github.com/espressif/arduino-esp32/pull/6667). It was suggested that I contribute to the Arduino core as well :) --- api/MacAddress.cpp | 95 +++++++++++++++++++++++++++++++++++++++++++++ api/MacAddress.h | 59 ++++++++++++++++++++++++++++ api/MacAddress8.cpp | 95 +++++++++++++++++++++++++++++++++++++++++++++ api/MacAddress8.h | 56 ++++++++++++++++++++++++++ 4 files changed, 305 insertions(+) create mode 100644 api/MacAddress.cpp create mode 100644 api/MacAddress.h create mode 100644 api/MacAddress8.cpp create mode 100644 api/MacAddress8.h diff --git a/api/MacAddress.cpp b/api/MacAddress.cpp new file mode 100644 index 00000000..fb021606 --- /dev/null +++ b/api/MacAddress.cpp @@ -0,0 +1,95 @@ +#include +#include "MacAddress.h" + +//Default constructor, blank mac address. +MacAddress::MacAddress() { + _mac.val = 0; +} + +MacAddress::MacAddress(uint64_t mac) { + _mac.val = mac; +} + +MacAddress::MacAddress(const uint8_t *macbytearray) { + memcpy(_mac.bytes, macbytearray, sizeof(_mac.bytes)); +} + +//Parse user entered string into MAC address +bool MacAddress::fromCStr(const char *buf) { + char cs[18]; + char *token; + char *next; //Unused but required + int i; + + strncpy(cs, buf, sizeof(cs)); //strtok modifies the buffer: copy to working buffer. + + for(i=0; i +#include "String.h" + +namespace arduino { + +// A class to make it easier to handle and pass around 6-byte BSSID and MAC addresses. +class MacAddress { +private: + union { + struct { + uint8_t align[2]; + uint8_t bytes[6]; + }; + uint64_t val; + } _mac; + +public: + MacAddress(); + MacAddress(uint64_t mac); + MacAddress(const uint8_t *macbytearray); + virtual ~MacAddress() {} + bool fromCStr(const char *buf); + bool fromString(const String &macstr); + void toBytes(uint8_t *buf); + int toCStr(char *buf); + String toString() const; + uint64_t Value(); + + operator uint64_t() const; + MacAddress& operator=(const uint8_t *mac); + MacAddress& operator=(uint64_t macval); + bool operator==(const uint8_t *mac) const; + bool operator==(const MacAddress& mac2) const; +}; + +} +using arduino::MacAddress; + +#endif diff --git a/api/MacAddress8.cpp b/api/MacAddress8.cpp new file mode 100644 index 00000000..a763970a --- /dev/null +++ b/api/MacAddress8.cpp @@ -0,0 +1,95 @@ +#include +#include "MacAddress8.h" + +//Default constructor, blank mac address. +MacAddress8::MacAddress8() { + _mac.val = 0; +} + +MacAddress8::MacAddress8(uint64_t mac) { + _mac.val = mac; +} + +MacAddress8::MacAddress8(const uint8_t *macbytearray) { + memcpy(_mac.bytes, macbytearray, sizeof(_mac.bytes)); +} + +//Parse user entered string into MAC address +bool MacAddress8::fromCStr(const char *buf) { + char cs[24]; + char *token; + char *next; //Unused but required + int i; + + strncpy(cs, buf, sizeof(cs)); //strtok modifies the buffer: copy to working buffer. + + for(i=0; i +#include "String.h" + +namespace arduino { + +// A class to make it easier to handle and pass around 8-byte EUI-64(used for IEEE 802.15.4) addresses. See . +class MacAddress8 { +private: + union { + uint8_t bytes[8]; + uint64_t val; + } _mac; + +public: + MacAddress8(); + MacAddress8(uint64_t mac); + MacAddress8(const uint8_t *macbytearray); + virtual ~MacAddress8() {} + bool fromCStr(const char *buf); + bool fromString(const String &macstr); + void toBytes(uint8_t *buf); + int toCStr(char *buf); + String toString() const; + uint64_t Value(); + + operator uint64_t() const; + MacAddress8& operator=(const uint8_t *mac); + MacAddress8& operator=(uint64_t macval); + bool operator==(const uint8_t *mac) const; + bool operator==(const MacAddress8& mac2) const; +}; + +} +using arduino::MacAddress8; + +#endif From a740b1c33edac3cb4e2c1d642a921bbd4958773f Mon Sep 17 00:00:00 2001 From: David McCurley <44048235+mrengineer7777@users.noreply.github.com> Date: Mon, 9 May 2022 08:29:25 -0500 Subject: [PATCH 2/2] Improvements from arduino-esp32 repo Added printTo(). Added index operators and type converters. See test project here: https://github.com/mrengineer7777/MA_Test. No further changes expected. --- api/MacAddress.cpp | 83 +++++++++++++++++++++++++++++++++++--------- api/MacAddress.h | 34 ++++++++++++------ api/MacAddress8.cpp | 84 ++++++++++++++++++++++++++++++++++++--------- api/MacAddress8.h | 36 +++++++++++++------ 4 files changed, 184 insertions(+), 53 deletions(-) diff --git a/api/MacAddress.cpp b/api/MacAddress.cpp index fb021606..16fc3625 100644 --- a/api/MacAddress.cpp +++ b/api/MacAddress.cpp @@ -1,5 +1,6 @@ +#include #include -#include "MacAddress.h" +#include //Default constructor, blank mac address. MacAddress::MacAddress() { @@ -14,6 +15,15 @@ MacAddress::MacAddress(const uint8_t *macbytearray) { memcpy(_mac.bytes, macbytearray, sizeof(_mac.bytes)); } +MacAddress::MacAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6) { + _mac.bytes[0] = b1; + _mac.bytes[1] = b2; + _mac.bytes[2] = b3; + _mac.bytes[3] = b4; + _mac.bytes[4] = b5; + _mac.bytes[5] = b6; +} + //Parse user entered string into MAC address bool MacAddress::fromCStr(const char *buf) { char cs[18]; @@ -63,33 +73,74 @@ uint64_t MacAddress::Value() { return _mac.val; } -//Implicit conversion object to number [same as .Value()] -MacAddress::operator uint64_t() const -{ - return _mac.val; +//Allow getting individual octets of the address. e.g. uint8_t b0 = ma[0]; +uint8_t MacAddress::operator[](int index) const { + index = EnforceIndexBounds(index); + return _mac.bytes[index]; } -//Overloaded copy operators to allow initialisation of MacAddress objects from other types -MacAddress& MacAddress::operator=(const uint8_t *mac) -{ - memcpy(_mac.bytes, mac, sizeof(_mac.bytes)); +//Allow setting individual octets of the address. e.g. ma[2] = 255; +uint8_t& MacAddress::operator[](int index) { + index = EnforceIndexBounds(index); + return _mac.bytes[index]; +} + +//Overloaded copy operator: init MacAddress object from byte array +MacAddress& MacAddress::operator=(const uint8_t *macbytearray) { + memcpy(_mac.bytes, macbytearray, sizeof(_mac.bytes)); return *this; } -MacAddress& MacAddress::operator=(uint64_t macval) -{ +//Overloaded copy operator: init MacAddress object from uint64_t +MacAddress& MacAddress::operator=(uint64_t macval) { _mac.val = macval; return *this; } //Compare class to byte array -bool MacAddress::operator==(const uint8_t *mac) const -{ - return !memcmp(_mac.bytes, mac, sizeof(_mac.bytes)); +bool MacAddress::operator==(const uint8_t *macbytearray) const { + return !memcmp(_mac.bytes, macbytearray, sizeof(_mac.bytes)); } //Allow comparing value of two classes -bool MacAddress::operator==(const MacAddress& mac2) const -{ +bool MacAddress::operator==(const MacAddress& mac2) const { return _mac.val == mac2._mac.val; } + +//Type converter object to uint64_t [same as .Value()] +MacAddress::operator uint64_t() const { + return _mac.val; +} + +//Type converter object to read only pointer to mac bytes. e.g. const uint8_t *ip_8 = ma; +MacAddress::operator const uint8_t*() const { + return _mac.bytes; +} + +//Type converter object to read only pointer to mac value. e.g. const uint32_t *ip_64 = ma; +MacAddress::operator const uint64_t*() const { + return &_mac.val; +} + +size_t MacAddress::printTo(Print& p) const +{ + size_t n = 0; + for(int i = 0; i < 6; i++) { + if(i){ + n += p.print(':'); + } + n += p.printf("%02X", _mac.bytes[i]); + } + return n; +} + +//Bounds checking +int MacAddress::EnforceIndexBounds(int i) const { + if(i < 0) { + return 0; + } + if(i >= sizeof(_mac.bytes)) { + return sizeof(_mac.bytes)-1; + } + return i; +} diff --git a/api/MacAddress.h b/api/MacAddress.h index 44ce60db..1356ab70 100644 --- a/api/MacAddress.h +++ b/api/MacAddress.h @@ -19,12 +19,11 @@ #define MacAddress_h #include -#include "String.h" - -namespace arduino { +#include +#include // A class to make it easier to handle and pass around 6-byte BSSID and MAC addresses. -class MacAddress { +class MacAddress : public Printable { private: union { struct { @@ -38,6 +37,7 @@ class MacAddress { MacAddress(); MacAddress(uint64_t mac); MacAddress(const uint8_t *macbytearray); + MacAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6); virtual ~MacAddress() {} bool fromCStr(const char *buf); bool fromString(const String &macstr); @@ -46,14 +46,28 @@ class MacAddress { String toString() const; uint64_t Value(); - operator uint64_t() const; - MacAddress& operator=(const uint8_t *mac); + uint8_t operator[](int index) const; + uint8_t& operator[](int index); + MacAddress& operator=(const uint8_t *macbytearray); MacAddress& operator=(uint64_t macval); - bool operator==(const uint8_t *mac) const; + bool operator==(const uint8_t *macbytearray) const; bool operator==(const MacAddress& mac2) const; -}; + operator uint64_t() const; + operator const uint8_t*() const; + operator const uint64_t*() const; -} -using arduino::MacAddress; + virtual size_t printTo(Print& p) const; + + // future use in Arduino Networking + friend class EthernetClass; + friend class UDP; + friend class Client; + friend class Server; + friend class DhcpClass; + friend class DNSClient; + +private: + int EnforceIndexBounds(int i) const; +}; #endif diff --git a/api/MacAddress8.cpp b/api/MacAddress8.cpp index a763970a..7406bee8 100644 --- a/api/MacAddress8.cpp +++ b/api/MacAddress8.cpp @@ -1,5 +1,6 @@ +#include #include -#include "MacAddress8.h" +#include //Default constructor, blank mac address. MacAddress8::MacAddress8() { @@ -14,6 +15,17 @@ MacAddress8::MacAddress8(const uint8_t *macbytearray) { memcpy(_mac.bytes, macbytearray, sizeof(_mac.bytes)); } +MacAddress8::MacAddress8(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6, uint8_t b7, uint8_t b8) { + _mac.bytes[0] = b1; + _mac.bytes[1] = b2; + _mac.bytes[2] = b3; + _mac.bytes[3] = b4; + _mac.bytes[4] = b5; + _mac.bytes[5] = b6; + _mac.bytes[6] = b7; + _mac.bytes[7] = b8; +} + //Parse user entered string into MAC address bool MacAddress8::fromCStr(const char *buf) { char cs[24]; @@ -63,33 +75,73 @@ uint64_t MacAddress8::Value() { return _mac.val; } -//Implicit conversion object to number [same as .Value()] -MacAddress8::operator uint64_t() const -{ - return _mac.val; +uint8_t MacAddress8::operator[](int index) const { + index = EnforceIndexBounds(index); + return _mac.bytes[index]; } -//Overloaded copy operators to allow initialisation of MacAddress objects from other types -MacAddress8& MacAddress8::operator=(const uint8_t *mac) -{ - memcpy(_mac.bytes, mac, sizeof(_mac.bytes)); +//Allow setting individual octets of the address. e.g. ma[2] = 255; +uint8_t& MacAddress8::operator[](int index) { + index = EnforceIndexBounds(index); + return _mac.bytes[index]; +} + +//Overloaded copy operator: init MacAddress object from byte array +MacAddress8& MacAddress8::operator=(const uint8_t *macbytearray) { + memcpy(_mac.bytes, macbytearray, sizeof(_mac.bytes)); return *this; } -MacAddress8& MacAddress8::operator=(uint64_t macval) -{ +//Overloaded copy operator: init MacAddress object from uint64_t +MacAddress8& MacAddress8::operator=(uint64_t macval) { _mac.val = macval; return *this; } //Compare class to byte array -bool MacAddress8::operator==(const uint8_t *mac) const -{ - return !memcmp(_mac.bytes, mac, sizeof(_mac.bytes)); +bool MacAddress8::operator==(const uint8_t *macbytearray) const { + return !memcmp(_mac.bytes, macbytearray, sizeof(_mac.bytes)); } //Allow comparing value of two classes -bool MacAddress8::operator==(const MacAddress8& mac2) const -{ +bool MacAddress8::operator==(const MacAddress8& mac2) const { return _mac.val == mac2._mac.val; } + +//Type converter object to uint64_t [same as .Value()] +MacAddress8::operator uint64_t() const { + return _mac.val; +} + +//Type converter object to read only pointer to mac bytes. e.g. const uint8_t *ip_8 = ma; +MacAddress8::operator const uint8_t*() const { + return _mac.bytes; +} + +//Type converter object to read only pointer to mac value. e.g. const uint32_t *ip_64 = ma; +MacAddress8::operator const uint64_t*() const { + return &_mac.val; +} + +size_t MacAddress8::printTo(Print& p) const +{ + size_t n = 0; + for(int i = 0; i < 8; i++) { + if(i){ + n += p.print(':'); + } + n += p.printf("%02X", _mac.bytes[i]); + } + return n; +} + +//Bounds checking +int MacAddress8::EnforceIndexBounds(int i) const { + if(i < 0) { + return 0; + } + if(i >= sizeof(_mac.bytes)) { + return sizeof(_mac.bytes)-1; + } + return i; +} diff --git a/api/MacAddress8.h b/api/MacAddress8.h index 4f3d6ad3..360ce8c9 100644 --- a/api/MacAddress8.h +++ b/api/MacAddress8.h @@ -19,12 +19,11 @@ #define MacAddress8_h #include -#include "String.h" - -namespace arduino { +#include +#include // A class to make it easier to handle and pass around 8-byte EUI-64(used for IEEE 802.15.4) addresses. See . -class MacAddress8 { +class MacAddress8 : public Printable { private: union { uint8_t bytes[8]; @@ -35,22 +34,37 @@ class MacAddress8 { MacAddress8(); MacAddress8(uint64_t mac); MacAddress8(const uint8_t *macbytearray); + MacAddress8(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6, uint8_t b7, uint8_t b8); virtual ~MacAddress8() {} bool fromCStr(const char *buf); bool fromString(const String &macstr); void toBytes(uint8_t *buf); - int toCStr(char *buf); + int toCStr(char *buf); String toString() const; uint64_t Value(); - operator uint64_t() const; - MacAddress8& operator=(const uint8_t *mac); + uint8_t operator[](int index) const; + uint8_t& operator[](int index); + MacAddress8& operator=(const uint8_t *macbytearray); MacAddress8& operator=(uint64_t macval); - bool operator==(const uint8_t *mac) const; + bool operator==(const uint8_t *macbytearray) const; bool operator==(const MacAddress8& mac2) const; -}; + operator uint64_t() const; + operator const uint8_t*() const; + operator const uint64_t*() const; -} -using arduino::MacAddress8; + virtual size_t printTo(Print& p) const; + + // future use in Arduino Networking + friend class EthernetClass; + friend class UDP; + friend class Client; + friend class Server; + friend class DhcpClass; + friend class DNSClient; + +private: + int EnforceIndexBounds(int i) const; +}; #endif