-
Notifications
You must be signed in to change notification settings - Fork 7.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feature: New Class MacAddress similar to IPAddress (#9304)
* Added new classes MacAddress and MacAddress8 In the same style as class IPAddress. Based on Apache License. * Update MacAddress8.h * Added Printable, constructor and extra operators Added a few changes to make it closer to IPAddress Class implementation. * Added construtor and Printable Makes it closer to IPAddress Class implementation * Fixes include Printable * Update MacAddress.cpp * Update MacAddress.h * Update MacAddress.cpp * Added Printable * Added Printble and some more operators * Cleanup and bounds checking Moved implementation details .h->.cpp. Added bounds checking on index operators. Added constructor to MacAddress8 to match MacAddress. * Fixed printTo Chars must be uppercase to match toString() and pass test * feat(MAC): Rework API to support both 6+8 bytes MacAddress * feat(MAC): Remove MacAddress8.h file * fix(MAC): Remove comment + reorder lines * Update toString function with single buf and return * Fix buffer size for toString --------- Co-authored-by: David McCurley <[email protected]> Co-authored-by: David McCurley <[email protected]> Co-authored-by: Rodrigo Garcia <[email protected]> Co-authored-by: Lucas Saavedra Vaz <[email protected]>
- Loading branch information
1 parent
82a6348
commit c17a688
Showing
3 changed files
with
331 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,229 @@ | ||
#include <MacAddress.h> | ||
#include <stdio.h> | ||
#include <Print.h> | ||
|
||
//Default constructor, blank mac address. | ||
MacAddress::MacAddress() : MacAddress(MAC6){} | ||
|
||
MacAddress::MacAddress(MACType mac_type){ | ||
_type = mac_type; | ||
memset(_mac.bytes, 0, sizeof(_mac.bytes)); | ||
} | ||
MacAddress::MacAddress(MACType mac_type, uint64_t mac) { | ||
_type = mac_type; | ||
_mac.val = mac; | ||
} | ||
|
||
MacAddress::MacAddress(MACType mac_type, const uint8_t *macbytearray) { | ||
_type = mac_type; | ||
memset(_mac.bytes, 0, sizeof(_mac.bytes)); | ||
if(_type == MAC6) { | ||
memcpy(_mac.bytes, macbytearray, 6); | ||
} else { | ||
memcpy(_mac.bytes, macbytearray, 8); | ||
} | ||
} | ||
|
||
MacAddress::MacAddress(const char *macstr){ | ||
fromString(macstr); | ||
} | ||
|
||
MacAddress::MacAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6) { | ||
_type = MAC6; | ||
memset(_mac.bytes, 0, sizeof(_mac.bytes)); | ||
_mac.bytes[0] = b1; | ||
_mac.bytes[1] = b2; | ||
_mac.bytes[2] = b3; | ||
_mac.bytes[3] = b4; | ||
_mac.bytes[4] = b5; | ||
_mac.bytes[5] = b6; | ||
} | ||
|
||
MacAddress::MacAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6, uint8_t b7, uint8_t b8) { | ||
_type = MAC8; | ||
_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 MacAddress::fromString(const char *buf) { | ||
if(strlen(buf) == 17) { | ||
return fromString6(buf); | ||
} else if(strlen(buf) == 23) { | ||
return fromString8(buf); | ||
} | ||
return false; | ||
} | ||
|
||
//Parse user entered string into MAC address | ||
bool MacAddress::fromString6(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 < 6; 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); | ||
} | ||
_type = MAC6; | ||
return true; | ||
} | ||
|
||
bool MacAddress::fromString8(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 < 8; 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); | ||
} | ||
_type = MAC8; | ||
return true; | ||
} | ||
|
||
//Copy MAC into byte array | ||
void MacAddress::toBytes(uint8_t *buf) { | ||
if(_type == MAC6) { | ||
memcpy(buf, _mac.bytes, 6); | ||
} else { | ||
memcpy(buf, _mac.bytes, sizeof(_mac.bytes)); | ||
} | ||
} | ||
|
||
//Print MAC address into a C string. | ||
//MAC: Buffer must be at least 18 chars | ||
int MacAddress::toString(char *buf) { | ||
if(_type == MAC6) { | ||
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]); | ||
} else { | ||
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 MacAddress::toString() const { | ||
uint8_t bytes = (_type == MAC6) ? 18 : 24; | ||
char buf[bytes]; | ||
if(_type == MAC6) { | ||
snprintf(buf, sizeof(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]); | ||
} else { | ||
snprintf(buf, sizeof(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 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) { | ||
// 6-bytes MacAddress only | ||
_type = MAC6; | ||
memset(_mac.bytes, 0, sizeof(_mac.bytes)); | ||
memcpy(_mac.bytes, macbytearray, 6); | ||
return *this; | ||
} | ||
|
||
//Overloaded copy operator: init MacAddress object from uint64_t | ||
MacAddress& MacAddress::operator=(uint64_t macval) { | ||
// 6-bytes MacAddress only | ||
_type = MAC6; | ||
_mac.val = macval; | ||
return *this; | ||
} | ||
|
||
//Compare class to byte array | ||
bool MacAddress::operator==(const uint8_t *macbytearray) const { | ||
return !memcmp(_mac.bytes, macbytearray, 6); | ||
} | ||
|
||
//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 | ||
{ | ||
uint8_t bytes = (_type == MAC6) ? 6 : 8; | ||
size_t n = 0; | ||
for(int i = 0; i < bytes; 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(_type == MAC6) { | ||
if(i >= 6) { | ||
return 5; | ||
} | ||
} else { | ||
if(i >= 8) { | ||
return 7; | ||
} | ||
} | ||
return i; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
//----------------------------------------------------------------------------- | ||
// MacAddress.h - class to make it easier to handle BSSID and MAC addresses. | ||
// | ||
// Copyright 2022 David McCurley | ||
// Modified by Espressif Systems 2024 | ||
// | ||
// 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> | ||
|
||
enum MACType { | ||
MAC6, | ||
MAC8 | ||
}; | ||
|
||
// A class to make it easier to handle and pass around MAC addresses, supporting both 6-byte and 8-byte MAC addresses. | ||
class MacAddress : public Printable { | ||
private: | ||
union { | ||
uint8_t bytes[8]; | ||
uint64_t val; | ||
} _mac; | ||
MACType _type; | ||
|
||
public: | ||
//Default MAC6 | ||
MacAddress(); | ||
|
||
MacAddress(MACType mac_type); | ||
MacAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6); | ||
MacAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6, uint8_t b7, uint8_t b8); | ||
|
||
MacAddress(MACType mac_type, uint64_t mac); | ||
MacAddress(MACType mac_type, const uint8_t *macbytearray); | ||
|
||
//Default MAC6 | ||
MacAddress(uint64_t mac) : MacAddress(MAC6, mac) {} | ||
MacAddress(const uint8_t *macbytearray) : MacAddress(MAC6, macbytearray) {} | ||
|
||
MacAddress(const char *macstr); | ||
|
||
virtual ~MacAddress() {} | ||
|
||
bool fromString(const char *buf); | ||
bool fromString(const String &macstr) { return fromString(macstr.c_str()); } | ||
|
||
void toBytes(uint8_t *buf); | ||
int toString(char *buf); | ||
String toString() const; | ||
uint64_t Value(); | ||
|
||
uint8_t operator[](int index) const; | ||
uint8_t& operator[](int index); | ||
|
||
//MAC6 only | ||
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; | ||
*/ | ||
|
||
protected: | ||
bool fromString6(const char *buf); | ||
bool fromString8(const char *buf); | ||
|
||
private: | ||
int EnforceIndexBounds(int i) const; | ||
}; | ||
|
||
#endif |