Skip to content

Commit c17a688

Browse files
P-R-O-C-H-Ymrengineer7777SuGliderlucasssvaz
authored
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 <44048235+mrengineer7777@users.noreply.github.com> Co-authored-by: David McCurley <mrengineer02@gmail.com> Co-authored-by: Rodrigo Garcia <rodrigo.garcia@espressif.com> Co-authored-by: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com>
1 parent 82a6348 commit c17a688

File tree

3 files changed

+331
-0
lines changed

3 files changed

+331
-0
lines changed

Diff for: CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ set(CORE_SRCS
5454
cores/esp32/IPAddress.cpp
5555
cores/esp32/libb64/cdecode.c
5656
cores/esp32/libb64/cencode.c
57+
cores/esp32/MacAddress.cpp
5758
cores/esp32/main.cpp
5859
cores/esp32/MD5Builder.cpp
5960
cores/esp32/Print.cpp

Diff for: cores/esp32/MacAddress.cpp

+229
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
#include <MacAddress.h>
2+
#include <stdio.h>
3+
#include <Print.h>
4+
5+
//Default constructor, blank mac address.
6+
MacAddress::MacAddress() : MacAddress(MAC6){}
7+
8+
MacAddress::MacAddress(MACType mac_type){
9+
_type = mac_type;
10+
memset(_mac.bytes, 0, sizeof(_mac.bytes));
11+
}
12+
MacAddress::MacAddress(MACType mac_type, uint64_t mac) {
13+
_type = mac_type;
14+
_mac.val = mac;
15+
}
16+
17+
MacAddress::MacAddress(MACType mac_type, const uint8_t *macbytearray) {
18+
_type = mac_type;
19+
memset(_mac.bytes, 0, sizeof(_mac.bytes));
20+
if(_type == MAC6) {
21+
memcpy(_mac.bytes, macbytearray, 6);
22+
} else {
23+
memcpy(_mac.bytes, macbytearray, 8);
24+
}
25+
}
26+
27+
MacAddress::MacAddress(const char *macstr){
28+
fromString(macstr);
29+
}
30+
31+
MacAddress::MacAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6) {
32+
_type = MAC6;
33+
memset(_mac.bytes, 0, sizeof(_mac.bytes));
34+
_mac.bytes[0] = b1;
35+
_mac.bytes[1] = b2;
36+
_mac.bytes[2] = b3;
37+
_mac.bytes[3] = b4;
38+
_mac.bytes[4] = b5;
39+
_mac.bytes[5] = b6;
40+
}
41+
42+
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) {
43+
_type = MAC8;
44+
_mac.bytes[0] = b1;
45+
_mac.bytes[1] = b2;
46+
_mac.bytes[2] = b3;
47+
_mac.bytes[3] = b4;
48+
_mac.bytes[4] = b5;
49+
_mac.bytes[5] = b6;
50+
_mac.bytes[6] = b7;
51+
_mac.bytes[7] = b8;
52+
}
53+
54+
//Parse user entered string into MAC address
55+
bool MacAddress::fromString(const char *buf) {
56+
if(strlen(buf) == 17) {
57+
return fromString6(buf);
58+
} else if(strlen(buf) == 23) {
59+
return fromString8(buf);
60+
}
61+
return false;
62+
}
63+
64+
//Parse user entered string into MAC address
65+
bool MacAddress::fromString6(const char *buf) {
66+
char cs[18];
67+
char *token;
68+
char *next; //Unused but required
69+
int i;
70+
71+
strncpy(cs, buf, sizeof(cs)); //strtok modifies the buffer: copy to working buffer.
72+
73+
for(i = 0; i < 6; i++) {
74+
token = strtok((i==0) ? cs : NULL, ":"); //Find first or next token
75+
if(!token) { //No more tokens found
76+
return false;
77+
}
78+
_mac.bytes[i] = strtol(token, &next, 16);
79+
}
80+
_type = MAC6;
81+
return true;
82+
}
83+
84+
bool MacAddress::fromString8(const char *buf) {
85+
char cs[24];
86+
char *token;
87+
char *next; //Unused but required
88+
int i;
89+
90+
strncpy(cs, buf, sizeof(cs)); //strtok modifies the buffer: copy to working buffer.
91+
92+
for(i = 0; i < 8; i++) {
93+
token = strtok((i==0) ? cs : NULL, ":"); //Find first or next token
94+
if(!token) { //No more tokens found
95+
return false;
96+
}
97+
_mac.bytes[i] = strtol(token, &next, 16);
98+
}
99+
_type = MAC8;
100+
return true;
101+
}
102+
103+
//Copy MAC into byte array
104+
void MacAddress::toBytes(uint8_t *buf) {
105+
if(_type == MAC6) {
106+
memcpy(buf, _mac.bytes, 6);
107+
} else {
108+
memcpy(buf, _mac.bytes, sizeof(_mac.bytes));
109+
}
110+
}
111+
112+
//Print MAC address into a C string.
113+
//MAC: Buffer must be at least 18 chars
114+
int MacAddress::toString(char *buf) {
115+
if(_type == MAC6) {
116+
return sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
117+
_mac.bytes[0], _mac.bytes[1], _mac.bytes[2],
118+
_mac.bytes[3], _mac.bytes[4], _mac.bytes[5]);
119+
} else {
120+
return sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",
121+
_mac.bytes[0], _mac.bytes[1], _mac.bytes[2],
122+
_mac.bytes[3], _mac.bytes[4], _mac.bytes[5],
123+
_mac.bytes[6], _mac.bytes[7]);
124+
}
125+
}
126+
127+
String MacAddress::toString() const {
128+
uint8_t bytes = (_type == MAC6) ? 18 : 24;
129+
char buf[bytes];
130+
if(_type == MAC6) {
131+
snprintf(buf, sizeof(buf), "%02X:%02X:%02X:%02X:%02X:%02X",
132+
_mac.bytes[0], _mac.bytes[1], _mac.bytes[2],
133+
_mac.bytes[3], _mac.bytes[4], _mac.bytes[5]);
134+
} else {
135+
snprintf(buf, sizeof(buf), "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",
136+
_mac.bytes[0], _mac.bytes[1], _mac.bytes[2],
137+
_mac.bytes[3], _mac.bytes[4], _mac.bytes[5],
138+
_mac.bytes[6], _mac.bytes[7]);
139+
}
140+
return String(buf);
141+
}
142+
143+
uint64_t MacAddress::Value() {
144+
return _mac.val;
145+
}
146+
147+
//Allow getting individual octets of the address. e.g. uint8_t b0 = ma[0];
148+
uint8_t MacAddress::operator[](int index) const {
149+
index = EnforceIndexBounds(index);
150+
return _mac.bytes[index];
151+
}
152+
153+
//Allow setting individual octets of the address. e.g. ma[2] = 255;
154+
uint8_t& MacAddress::operator[](int index) {
155+
index = EnforceIndexBounds(index);
156+
return _mac.bytes[index];
157+
}
158+
159+
//Overloaded copy operator: init MacAddress object from byte array
160+
MacAddress& MacAddress::operator=(const uint8_t *macbytearray) {
161+
// 6-bytes MacAddress only
162+
_type = MAC6;
163+
memset(_mac.bytes, 0, sizeof(_mac.bytes));
164+
memcpy(_mac.bytes, macbytearray, 6);
165+
return *this;
166+
}
167+
168+
//Overloaded copy operator: init MacAddress object from uint64_t
169+
MacAddress& MacAddress::operator=(uint64_t macval) {
170+
// 6-bytes MacAddress only
171+
_type = MAC6;
172+
_mac.val = macval;
173+
return *this;
174+
}
175+
176+
//Compare class to byte array
177+
bool MacAddress::operator==(const uint8_t *macbytearray) const {
178+
return !memcmp(_mac.bytes, macbytearray, 6);
179+
}
180+
181+
//Allow comparing value of two classes
182+
bool MacAddress::operator==(const MacAddress& mac2) const {
183+
return _mac.val == mac2._mac.val;
184+
}
185+
186+
//Type converter object to uint64_t [same as .Value()]
187+
MacAddress::operator uint64_t() const {
188+
return _mac.val;
189+
}
190+
191+
//Type converter object to read only pointer to mac bytes. e.g. const uint8_t *ip_8 = ma;
192+
MacAddress::operator const uint8_t*() const {
193+
return _mac.bytes;
194+
}
195+
196+
//Type converter object to read only pointer to mac value. e.g. const uint32_t *ip_64 = ma;
197+
MacAddress::operator const uint64_t*() const {
198+
return &_mac.val;
199+
}
200+
201+
size_t MacAddress::printTo(Print& p) const
202+
{
203+
uint8_t bytes = (_type == MAC6) ? 6 : 8;
204+
size_t n = 0;
205+
for(int i = 0; i < bytes; i++) {
206+
if(i){
207+
n += p.print(':');
208+
}
209+
n += p.printf("%02X", _mac.bytes[i]);
210+
}
211+
return n;
212+
}
213+
214+
//Bounds checking
215+
int MacAddress::EnforceIndexBounds(int i) const {
216+
if(i < 0) {
217+
return 0;
218+
}
219+
if(_type == MAC6) {
220+
if(i >= 6) {
221+
return 5;
222+
}
223+
} else {
224+
if(i >= 8) {
225+
return 7;
226+
}
227+
}
228+
return i;
229+
}

Diff for: cores/esp32/MacAddress.h

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
//-----------------------------------------------------------------------------
2+
// MacAddress.h - class to make it easier to handle BSSID and MAC addresses.
3+
//
4+
// Copyright 2022 David McCurley
5+
// Modified by Espressif Systems 2024
6+
//
7+
// Licensed under the Apache License, Version 2.0 (the "License").
8+
// You may not use this file except in compliance with the License.
9+
// You may obtain a copy of the License at
10+
//
11+
// http://www.apache.org/licenses/LICENSE-2.0
12+
//
13+
// Unless required by applicable law or agreed to in writing, software
14+
// distributed under the License is distributed on an "AS IS" BASIS,
15+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
// See the License for the specific language governing permissions and
17+
// limitations under the License.
18+
//-----------------------------------------------------------------------------
19+
20+
#ifndef MacAddress_h
21+
#define MacAddress_h
22+
23+
#include <stdint.h>
24+
#include <WString.h>
25+
#include <Printable.h>
26+
27+
enum MACType {
28+
MAC6,
29+
MAC8
30+
};
31+
32+
// A class to make it easier to handle and pass around MAC addresses, supporting both 6-byte and 8-byte MAC addresses.
33+
class MacAddress : public Printable {
34+
private:
35+
union {
36+
uint8_t bytes[8];
37+
uint64_t val;
38+
} _mac;
39+
MACType _type;
40+
41+
public:
42+
//Default MAC6
43+
MacAddress();
44+
45+
MacAddress(MACType mac_type);
46+
MacAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6);
47+
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);
48+
49+
MacAddress(MACType mac_type, uint64_t mac);
50+
MacAddress(MACType mac_type, const uint8_t *macbytearray);
51+
52+
//Default MAC6
53+
MacAddress(uint64_t mac) : MacAddress(MAC6, mac) {}
54+
MacAddress(const uint8_t *macbytearray) : MacAddress(MAC6, macbytearray) {}
55+
56+
MacAddress(const char *macstr);
57+
58+
virtual ~MacAddress() {}
59+
60+
bool fromString(const char *buf);
61+
bool fromString(const String &macstr) { return fromString(macstr.c_str()); }
62+
63+
void toBytes(uint8_t *buf);
64+
int toString(char *buf);
65+
String toString() const;
66+
uint64_t Value();
67+
68+
uint8_t operator[](int index) const;
69+
uint8_t& operator[](int index);
70+
71+
//MAC6 only
72+
MacAddress& operator=(const uint8_t *macbytearray);
73+
MacAddress& operator=(uint64_t macval);
74+
75+
bool operator==(const uint8_t *macbytearray) const;
76+
bool operator==(const MacAddress& mac2) const;
77+
operator uint64_t() const;
78+
operator const uint8_t*() const;
79+
operator const uint64_t*() const;
80+
81+
virtual size_t printTo(Print& p) const;
82+
83+
// future use in Arduino Networking
84+
/*
85+
friend class EthernetClass;
86+
friend class UDP;
87+
friend class Client;
88+
friend class Server;
89+
friend class DhcpClass;
90+
friend class DNSClient;
91+
*/
92+
93+
protected:
94+
bool fromString6(const char *buf);
95+
bool fromString8(const char *buf);
96+
97+
private:
98+
int EnforceIndexBounds(int i) const;
99+
};
100+
101+
#endif

0 commit comments

Comments
 (0)