Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions doc/src/programmers-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -968,6 +968,13 @@ The return type is a list of tuples, each of which contains the partition id (as

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).

* `esp:get_mac/1`

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.

%% erlang
MacAddress = esp:get_mac(wifi_sta)

## Peripherals

The AtomVM virtual machine and libraries support APIs for interfacing with peripheral devices connected to the ESP32. This section provides information about these APIs.
Expand Down
19 changes: 18 additions & 1 deletion libs/eavmlib/src/esp.erl
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
partition_list/0,
rtc_slow_get_binary/0,
rtc_slow_set_binary/1,
freq_hz/0
freq_hz/0,
get_mac/1
]).

-type esp_reset_reason() ::
Expand Down Expand Up @@ -84,6 +85,9 @@
esp_partition_props()
}.

-type interface() :: wifi_sta | wifi_softap.
-type mac() :: binary().

-define(ATOMVM_NVS_NS, atomvm).

%%-----------------------------------------------------------------------------
Expand Down Expand Up @@ -287,3 +291,16 @@ rtc_slow_set_binary(Bin) when is_binary(Bin) ->
-spec freq_hz() -> non_neg_integer().
freq_hz() ->
erlang:nif_error(undefined).

%%-----------------------------------------------------------------------------
%% @param Interface the ESP32 network interface
%% @returns The network MAC address of the specified interface
%% @doc Return the network MAC address of the specified interface.
%%
%% The mac address is returned as a 6-byte binary, per the
%% IEEE 802 family of specifications.
%% @end
%%-----------------------------------------------------------------------------
-spec get_mac(Interface :: interface()) -> mac().
get_mac(_Interface) ->
erlang:nif_error(undefined).
61 changes: 60 additions & 1 deletion src/platforms/esp32/components/avm_sys/platform_nifs.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#include "platform_defaultatoms.h"
#include "term.h"

#include "esp_log.h"
#include "esp_mac.h"
#include <esp_partition.h>
#include <esp_sleep.h>
#include <esp_system.h>
Expand Down Expand Up @@ -62,6 +64,8 @@
//#define ENABLE_TRACE
#include "trace.h"

#define TAG "atomvm"

#define MD5_DIGEST_LENGTH 16

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

enum NetworkInterface {
WifiSTAInterface,
WifiSoftAPInterface,
InvalidInterface
};

static const AtomStringIntPair interface_table[] = {
{ ATOM_STR("\x8", "wifi_sta"), WifiSTAInterface },
{ ATOM_STR("\xB", "wifi_softap"), WifiSoftAPInterface },
SELECT_INT_DEFAULT(InvalidInterface)
};

//
// NIFs
//
Expand Down Expand Up @@ -450,8 +466,42 @@ static term nif_atomvm_platform(Context *ctx, int argc, term argv[])
return ESP32_ATOM;
}

static term nif_esp_get_mac(Context *ctx, int argc, term argv[])
{
UNUSED(argc);

GlobalContext *global = ctx->global;

int network_interface = interop_atom_term_select_int(interface_table, argv[0], global);
esp_mac_type_t interface;
switch (network_interface) {
case WifiSTAInterface:
interface = ESP_MAC_WIFI_STA;
break;
case WifiSoftAPInterface:
interface = ESP_MAC_WIFI_SOFTAP;
break;
default:
// TODO add support for BT, ETH, etc
RAISE_ERROR(BADARG_ATOM);
}

uint8_t mac[6];
esp_err_t err = esp_read_mac(mac, interface);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Unable to read mac. err=%i", err);
RAISE_ERROR(BADARG_ATOM);
}

if (UNLIKELY(memory_ensure_free(ctx, term_binary_heap_size(6)) != MEMORY_GC_OK)) {
RAISE_ERROR(OUT_OF_MEMORY_ATOM);
}

return term_from_literal_binary(mac, 6, &ctx->heap, ctx->global);
}

//
// NIF structures and distpatch
// NIF structures and dispatch
//

static const struct Nif esp_random_nif =
Expand Down Expand Up @@ -526,6 +576,11 @@ static const struct Nif atomvm_platform_nif =
.base.type = NIFFunctionType,
.nif_ptr = nif_atomvm_platform
};
static const struct Nif esp_get_mac_nif =
{
.base.type = NIFFunctionType,
.nif_ptr = nif_esp_get_mac
};

const struct Nif *platform_nifs_get_nif(const char *nifname)
{
Expand Down Expand Up @@ -591,6 +646,10 @@ const struct Nif *platform_nifs_get_nif(const char *nifname)
TRACE("Resolved platform nif %s ...\n", nifname);
return &atomvm_platform_nif;
}
if (strcmp("esp:get_mac/1", nifname) == 0) {
TRACE("Resolved platform nif %s ...\n", nifname);
return &esp_get_mac_nif;
}
const struct Nif *nif = nif_collection_resolve_nif(nifname);
if (nif) {
return nif;
Expand Down