Skip to content

Commit 4bdd25b

Browse files
committed
Merge pull request #734 from fadushin/esp-get_mac
Add support for `esp:get_mac/1` These changes are made under both the "Apache 2.0" and the "GNU Lesser General Public License 2.1 or later" license terms (dual license). SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
2 parents 6dd47da + c98ebb8 commit 4bdd25b

File tree

3 files changed

+85
-2
lines changed

3 files changed

+85
-2
lines changed

doc/src/programmers-guide.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -968,6 +968,13 @@ The return type is a list of tuples, each of which contains the partition id (as
968968
969969
For information about the encoding of partition types and sub-types, see the IDF SDK partition [type definitions](https://docs.espressif.com/projects/esp-idf/en/v4.4.5/esp32/api-reference/storage/spi_flash.html?highlight=esp_partition_get#id13).
970970

971+
* `esp:get_mac/1`
972+
973+
The `esp:get_mac/1` function can be used to retrieve the network Media Access Control ([MAC](https://en.wikipedia.org/wiki/MAC_address)) address for a given interface, `wifi_sta` or `wifi_softap`. The return value is a 6-byte binary, in accordance with the [IEEE 802](https://en.wikipedia.org/wiki/IEEE_802) family of specifications.
974+
975+
%% erlang
976+
MacAddress = esp:get_mac(wifi_sta)
977+
971978
## Peripherals
972979

973980
The AtomVM virtual machine and libraries support APIs for interfacing with peripheral devices connected to the ESP32. This section provides information about these APIs.

libs/eavmlib/src/esp.erl

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@
4040
partition_list/0,
4141
rtc_slow_get_binary/0,
4242
rtc_slow_set_binary/1,
43-
freq_hz/0
43+
freq_hz/0,
44+
get_mac/1
4445
]).
4546

4647
-type esp_reset_reason() ::
@@ -84,6 +85,9 @@
8485
esp_partition_props()
8586
}.
8687

88+
-type interface() :: wifi_sta | wifi_softap.
89+
-type mac() :: binary().
90+
8791
-define(ATOMVM_NVS_NS, atomvm).
8892

8993
%%-----------------------------------------------------------------------------
@@ -287,3 +291,16 @@ rtc_slow_set_binary(Bin) when is_binary(Bin) ->
287291
-spec freq_hz() -> non_neg_integer().
288292
freq_hz() ->
289293
erlang:nif_error(undefined).
294+
295+
%%-----------------------------------------------------------------------------
296+
%% @param Interface the ESP32 network interface
297+
%% @returns The network MAC address of the specified interface
298+
%% @doc Return the network MAC address of the specified interface.
299+
%%
300+
%% The mac address is returned as a 6-byte binary, per the
301+
%% IEEE 802 family of specifications.
302+
%% @end
303+
%%-----------------------------------------------------------------------------
304+
-spec get_mac(Interface :: interface()) -> mac().
305+
get_mac(_Interface) ->
306+
erlang:nif_error(undefined).

src/platforms/esp32/components/avm_sys/platform_nifs.c

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
#include "platform_defaultatoms.h"
3232
#include "term.h"
3333

34+
#include "esp_log.h"
35+
#include "esp_mac.h"
3436
#include <esp_partition.h>
3537
#include <esp_sleep.h>
3638
#include <esp_system.h>
@@ -62,6 +64,8 @@
6264
//#define ENABLE_TRACE
6365
#include "trace.h"
6466

67+
#define TAG "atomvm"
68+
6569
#define MD5_DIGEST_LENGTH 16
6670

6771
static const char *const esp_rst_unknown_atom = "\xF" "esp_rst_unknown";
@@ -77,6 +81,18 @@ static const char *const esp_rst_brownout = "\x10" "esp_rst_brownout";
7781
static const char *const esp_rst_sdio = "\xC" "esp_rst_sdio";
7882
// 123456789ABCDEF01
7983

84+
enum NetworkInterface {
85+
WifiSTAInterface,
86+
WifiSoftAPInterface,
87+
InvalidInterface
88+
};
89+
90+
static const AtomStringIntPair interface_table[] = {
91+
{ ATOM_STR("\x8", "wifi_sta"), WifiSTAInterface },
92+
{ ATOM_STR("\xB", "wifi_softap"), WifiSoftAPInterface },
93+
SELECT_INT_DEFAULT(InvalidInterface)
94+
};
95+
8096
//
8197
// NIFs
8298
//
@@ -450,8 +466,42 @@ static term nif_atomvm_platform(Context *ctx, int argc, term argv[])
450466
return ESP32_ATOM;
451467
}
452468

469+
static term nif_esp_get_mac(Context *ctx, int argc, term argv[])
470+
{
471+
UNUSED(argc);
472+
473+
GlobalContext *global = ctx->global;
474+
475+
int network_interface = interop_atom_term_select_int(interface_table, argv[0], global);
476+
esp_mac_type_t interface;
477+
switch (network_interface) {
478+
case WifiSTAInterface:
479+
interface = ESP_MAC_WIFI_STA;
480+
break;
481+
case WifiSoftAPInterface:
482+
interface = ESP_MAC_WIFI_SOFTAP;
483+
break;
484+
default:
485+
// TODO add support for BT, ETH, etc
486+
RAISE_ERROR(BADARG_ATOM);
487+
}
488+
489+
uint8_t mac[6];
490+
esp_err_t err = esp_read_mac(mac, interface);
491+
if (err != ESP_OK) {
492+
ESP_LOGE(TAG, "Unable to read mac. err=%i", err);
493+
RAISE_ERROR(BADARG_ATOM);
494+
}
495+
496+
if (UNLIKELY(memory_ensure_free(ctx, term_binary_heap_size(6)) != MEMORY_GC_OK)) {
497+
RAISE_ERROR(OUT_OF_MEMORY_ATOM);
498+
}
499+
500+
return term_from_literal_binary(mac, 6, &ctx->heap, ctx->global);
501+
}
502+
453503
//
454-
// NIF structures and distpatch
504+
// NIF structures and dispatch
455505
//
456506

457507
static const struct Nif esp_random_nif =
@@ -526,6 +576,11 @@ static const struct Nif atomvm_platform_nif =
526576
.base.type = NIFFunctionType,
527577
.nif_ptr = nif_atomvm_platform
528578
};
579+
static const struct Nif esp_get_mac_nif =
580+
{
581+
.base.type = NIFFunctionType,
582+
.nif_ptr = nif_esp_get_mac
583+
};
529584

530585
const struct Nif *platform_nifs_get_nif(const char *nifname)
531586
{
@@ -591,6 +646,10 @@ const struct Nif *platform_nifs_get_nif(const char *nifname)
591646
TRACE("Resolved platform nif %s ...\n", nifname);
592647
return &atomvm_platform_nif;
593648
}
649+
if (strcmp("esp:get_mac/1", nifname) == 0) {
650+
TRACE("Resolved platform nif %s ...\n", nifname);
651+
return &esp_get_mac_nif;
652+
}
594653
const struct Nif *nif = nif_collection_resolve_nif(nifname);
595654
if (nif) {
596655
return nif;

0 commit comments

Comments
 (0)