Skip to content
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ set(CORE_SRCS
cores/esp32/libb64/cdecode.c
cores/esp32/libb64/cencode.c
cores/esp32/main.cpp
cores/esp32/MacAddress.cpp
cores/esp32/MacAddress8.cpp
cores/esp32/MD5Builder.cpp
cores/esp32/Print.cpp
cores/esp32/stdlib_noniso.c
Expand Down
146 changes: 146 additions & 0 deletions cores/esp32/MacAddress.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
#include <MacAddress.h>
#include <stdio.h>
#include <Print.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));
}

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];
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<sizeof(_mac.bytes); i++) {
token = strtok((i==0) ? cs : NULL, ":"); //Find first or next token
if(!token) { //No more tokens found
return false;
}
_mac.bytes[i] = strtol(token, &next, 16);
}
return true;
}

//Parse user entered string into MAC address
bool MacAddress::fromString(const String &macstr) {
return fromCStr(macstr.c_str());
}

//Copy MAC into 6 byte array
void MacAddress::toBytes(uint8_t *buf) {
memcpy(buf, _mac.bytes, sizeof(_mac.bytes));
}

//Print MAC address into a C string.
//MAC: Buffer must be at least 18 chars
int MacAddress::toCStr(char *buf) {
return sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
_mac.bytes[0], _mac.bytes[1], _mac.bytes[2],
_mac.bytes[3], _mac.bytes[4], _mac.bytes[5]);
}

String MacAddress::toString() const {
char buf[18];
sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
_mac.bytes[0], _mac.bytes[1], _mac.bytes[2],
_mac.bytes[3], _mac.bytes[4], _mac.bytes[5]);
return String(buf);
}

uint64_t MacAddress::Value() {
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];
}

//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;
}

//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 *macbytearray) const {
return !memcmp(_mac.bytes, macbytearray, sizeof(_mac.bytes));
}

//Allow comparing value of two classes
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;
}
73 changes: 73 additions & 0 deletions cores/esp32/MacAddress.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//-----------------------------------------------------------------------------
// MacAddress.h - class to make it easier to handle BSSID and MAC addresses.
//
// Copyright 2022 David McCurley
// Licensed under the Apache License, Version 2.0 (the "License").
// You may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//-----------------------------------------------------------------------------

#ifndef MacAddress_h
#define MacAddress_h

#include <stdint.h>
#include <WString.h>
#include <Printable.h>

// A class to make it easier to handle and pass around 6-byte BSSID and MAC addresses.
class MacAddress : public Printable {
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);
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);
void toBytes(uint8_t *buf);
int toCStr(char *buf);
String toString() const;
uint64_t Value();

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 *macbytearray) const;
bool operator==(const MacAddress& mac2) const;
operator uint64_t() const;
operator const uint8_t*() const;
operator const uint64_t*() const;

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
147 changes: 147 additions & 0 deletions cores/esp32/MacAddress8.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
#include <MacAddress8.h>
#include <stdio.h>
#include <Print.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));
}

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];
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<sizeof(_mac.bytes); i++) {
token = strtok((i==0) ? cs : NULL, ":"); //Find first or next token
if(!token) { //No more tokens found
return false;
}
_mac.bytes[i] = strtol(token, &next, 16);
}
return true;
}

//Parse user entered string into MAC address
bool MacAddress8::fromString(const String &macstr) {
return fromCStr(macstr.c_str());
}

//Copy MAC into 8 byte array
void MacAddress8::toBytes(uint8_t *buf) {
memcpy(buf, _mac.bytes, sizeof(_mac.bytes));
}

//Print MAC address into a C string.
//EUI-64: Buffer must be at least 24 chars
int MacAddress8::toCStr(char *buf) {
return sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",
_mac.bytes[0], _mac.bytes[1], _mac.bytes[2], _mac.bytes[3],
_mac.bytes[4], _mac.bytes[5], _mac.bytes[6], _mac.bytes[7]);
}

String MacAddress8::toString() const {
char buf[24];
sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",
_mac.bytes[0], _mac.bytes[1], _mac.bytes[2], _mac.bytes[3],
_mac.bytes[4], _mac.bytes[5], _mac.bytes[6], _mac.bytes[7]);
return String(buf);
}

uint64_t MacAddress8::Value() {
return _mac.val;
}

uint8_t MacAddress8::operator[](int index) const {
index = EnforceIndexBounds(index);
return _mac.bytes[index];
}

//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;
}

//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 *macbytearray) const {
return !memcmp(_mac.bytes, macbytearray, sizeof(_mac.bytes));
}

//Allow comparing value of two classes
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;
}
Loading