diff --git a/components/bt/bt.c b/components/bt/bt.c index 4943b9acbf..e8f4204ef4 100644 --- a/components/bt/bt.c +++ b/components/bt/bt.c @@ -78,7 +78,7 @@ struct osi_funcs_t { void *(*_mutex_create)(void); int32_t (*_mutex_lock)(void *mutex); int32_t (*_mutex_unlock)(void *mutex); - esp_err_t (* _read_efuse_mac)(uint8_t mac[6]); + int32_t (* _read_efuse_mac)(uint8_t mac[6]); }; /* Static variable declare */ @@ -129,6 +129,11 @@ static int32_t IRAM_ATTR mutex_unlock_wrapper(void *mutex) return (int32_t)xSemaphoreGive(mutex); } +static int32_t IRAM_ATTR read_mac_wrapper(uint8_t mac[6]) +{ + return esp_read_mac(mac, ESP_MAC_BT); +} + static struct osi_funcs_t osi_funcs = { ._set_isr = xt_set_interrupt_handler, ._ints_on = xt_ints_on, @@ -141,7 +146,7 @@ static struct osi_funcs_t osi_funcs = { ._mutex_create = mutex_create_wrapper, ._mutex_lock = mutex_lock_wrapper, ._mutex_unlock = mutex_unlock_wrapper, - ._read_efuse_mac = esp_efuse_read_mac, + ._read_efuse_mac = read_mac_wrapper }; bool esp_vhci_host_check_send_available(void) diff --git a/components/bt/lib b/components/bt/lib index 9f9f6a004e..9a4bb1d528 160000 --- a/components/bt/lib +++ b/components/bt/lib @@ -1 +1 @@ -Subproject commit 9f9f6a004e42519f54555c42a037b8ef25bf2238 +Subproject commit 9a4bb1d5287572664f170f9df4dbfd71babdfc68 diff --git a/components/esp32/Kconfig b/components/esp32/Kconfig index 8aa0ed3b5f..eea04a3327 100644 --- a/components/esp32/Kconfig +++ b/components/esp32/Kconfig @@ -105,6 +105,28 @@ config MEMMAP_SPISRAM main memory map. Enable this if you have this hardware and want to use it in the same way as on-chip RAM. +choice NUMBER_OF_MAC_ADDRESS_GENERATED_FROM_EFUSE + bool "Number of MAC address generated from the hardware MAC address in efuse" + default FOUR_MAC_ADDRESS_FROM_EFUSE + help + Config the number of MAC address which is generated from the hardware MAC address in efuse. + If the number is two, the MAC addresses of WiFi station and bluetooth are generated from + the hardware MAC address in efuse. The MAC addresses of WiFi softap and ethernet are derived + from that of WiFi station and bluetooth respectively. + If the number is four, the MAC addresses of WiFi station, WiFi softap, bluetooth and ethernet + are all generated from the hardware MAC address in efuse. + +config TWO_MAC_ADDRESS_FROM_EFUSE + bool "Two" +config FOUR_MAC_ADDRESS_FROM_EFUSE + bool "Four" +endchoice + +config NUMBER_OF_MAC_ADDRESS_GENERATED_FROM_EFUSE + int + default 2 if TWO_MAC_ADDRESS_FROM_EFUSE + default 4 if FOUR_MAC_ADDRESS_FROM_EFUSE + config SYSTEM_EVENT_QUEUE_SIZE int "System event queue size" default 32 diff --git a/components/esp32/include/esp_system.h b/components/esp32/include/esp_system.h index 30701761ad..9a88743b80 100644 --- a/components/esp32/include/esp_system.h +++ b/components/esp32/include/esp_system.h @@ -24,6 +24,17 @@ extern "C" { #endif +typedef enum { + ESP_MAC_WIFI_STA, + ESP_MAC_WIFI_SOFTAP, + ESP_MAC_BT, + ESP_MAC_ETH, +} esp_mac_type_t; + +#define TWO_MAC_ADDRESS_FROM_EFUSE 2 +#define FOUR_MAC_ADDRESS_FROM_EFUSE 4 +#define NUM_MAC_ADDRESS_FROM_EFUSE CONFIG_NUMBER_OF_MAC_ADDRESS_GENERATED_FROM_EFUSE + /** * @attention application don't need to call this function anymore. It do nothing and will * be removed in future version. @@ -115,6 +126,47 @@ esp_err_t esp_efuse_read_mac(uint8_t* mac); */ esp_err_t system_efuse_read_mac(uint8_t mac[6]) __attribute__ ((deprecated)); +/** + * @brief Read hardware MAC address and set MAC address of the interface. + * + * This function first reads hardware MAC address from efuse. Then set the MAC address of the interface + * including wifi station, wifi softap, bluetooth and ethernet. + * + * @param mac MAC address of the interface, length: 6 bytes. + * @param type type of MAC address, 0:wifi station, 1:wifi softap, 2:bluetooth, 3:ethernet. + * + * @return ESP_OK on success + */ +esp_err_t esp_read_mac(uint8_t* mac, esp_mac_type_t type); + +/** + * @brief Derive MAC address. + * + * This function derives a local MAC address from an universal MAC address. + * Addresses can either be universally administered addresses or locally administered addresses. + * A universally administered address is uniquely assigned to a device by its manufacturer. + * The first three octets (in transmission order) identify the organization that issued the identifier + * and are known as the Organizationally Unique Identifier (OUI).[4] The remainder of the address + * (three octets for MAC-48 and EUI-48 or five for EUI-64) are assigned by that organization in nearly + * any manner they please, subject to the constraint of uniqueness. A locally administered address is + * assigned to a device by a network administrator, overriding the burned-in address. + * Universally administered and locally administered addresses are distinguished by setting + * the second-least-significant bit of the first octet of the address. This bit is also referred to + * as the U/L bit, short for Universal/Local, which identifies how the address is administered. + * If the bit is 0, the address is universally administered. If it is 1, the address is locally administered. + * In the example address 06-00-00-00-00-00 the first octet is 06 (hex), the binary form of which is 00000110, + * where the second-least-significant bit is 1. Therefore, it is a locally administered address.[7] Consequently, + * this bit is 0 in all OUIs. + * In ESP32, universal MAC address is generated from the hardware MAC address in efuse. + * Local MAC address is derived from the universal MAC address. + * + * @param dst_mac Derived local MAC address, length: 6 bytes. + * @param src_mac Source universal MAC address, length: 6 bytes. + * + * @return ESP_OK on success + */ +esp_err_t esp_derive_mac(uint8_t* dst_mac, const uint8_t* src_mac); + /** * Get SDK version * diff --git a/components/esp32/lib b/components/esp32/lib index 7b06303c0f..e22ec1a514 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit 7b06303c0fa416aea7f86b7596e84db367189066 +Subproject commit e22ec1a5140dca2bb44f9bfb3147911fa4ebb8fe diff --git a/components/esp32/system_api.c b/components/esp32/system_api.c index 60e3d85983..79ec1a3963 100644 --- a/components/esp32/system_api.c +++ b/components/esp32/system_api.c @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include + #include "esp_system.h" #include "esp_attr.h" #include "esp_wifi.h" @@ -72,6 +74,87 @@ esp_err_t esp_efuse_read_mac(uint8_t* mac) esp_err_t system_efuse_read_mac(uint8_t mac[6]) __attribute__((alias("esp_efuse_read_mac"))); +esp_err_t esp_derive_mac(uint8_t* dst_mac, const uint8_t* src_mac) +{ + uint8_t idx; + + if (dst_mac == NULL || src_mac == NULL) { + ESP_LOGE(TAG, "mac address param is NULL"); + return ESP_ERR_INVALID_ARG; + } + + memcpy(dst_mac, src_mac, 6); + for (idx = 0; idx < 64; idx++) { + dst_mac[0] = src_mac[0] | 0x02; + dst_mac[0] ^= idx << 2; + + if (memcmp(dst_mac, src_mac, 6)) { + break; + } + } + + return ESP_OK; +} + +esp_err_t esp_read_mac(uint8_t* mac, esp_mac_type_t type) +{ + uint8_t efuse_mac[6]; + + if (mac == NULL) { + ESP_LOGE(TAG, "mac address param is NULL"); + return ESP_ERR_INVALID_ARG; + } + + if (type < ESP_MAC_WIFI_STA || type > ESP_MAC_ETH) { + ESP_LOGE(TAG, "mac type is incorrect"); + return ESP_ERR_INVALID_ARG; + } + + _Static_assert(NUM_MAC_ADDRESS_FROM_EFUSE == FOUR_MAC_ADDRESS_FROM_EFUSE \ + || NUM_MAC_ADDRESS_FROM_EFUSE == TWO_MAC_ADDRESS_FROM_EFUSE, \ + "incorrect NUM_MAC_ADDRESS_FROM_EFUSE value"); + + esp_efuse_read_mac(efuse_mac); + + switch (type) { + case ESP_MAC_WIFI_STA: + memcpy(mac, efuse_mac, 6); + break; + case ESP_MAC_WIFI_SOFTAP: + if (NUM_MAC_ADDRESS_FROM_EFUSE == FOUR_MAC_ADDRESS_FROM_EFUSE) { + memcpy(mac, efuse_mac, 6); + mac[5] += 1; + } + else if (NUM_MAC_ADDRESS_FROM_EFUSE == TWO_MAC_ADDRESS_FROM_EFUSE) { + esp_derive_mac(mac, efuse_mac); + } + break; + case ESP_MAC_BT: + memcpy(mac, efuse_mac, 6); + if (NUM_MAC_ADDRESS_FROM_EFUSE == FOUR_MAC_ADDRESS_FROM_EFUSE) { + mac[5] += 2; + } + else if (NUM_MAC_ADDRESS_FROM_EFUSE == TWO_MAC_ADDRESS_FROM_EFUSE) { + mac[5] += 1; + } + break; + case ESP_MAC_ETH: + if (NUM_MAC_ADDRESS_FROM_EFUSE == FOUR_MAC_ADDRESS_FROM_EFUSE) { + memcpy(mac, efuse_mac, 6); + mac[5] += 3; + } + else if (NUM_MAC_ADDRESS_FROM_EFUSE == TWO_MAC_ADDRESS_FROM_EFUSE) { + efuse_mac[5] += 1; + esp_derive_mac(mac, efuse_mac); + } + break; + default: + ESP_LOGW(TAG, "incorrect mac type"); + break; + } + + return ESP_OK; +} void esp_restart_noos() __attribute__ ((noreturn)); diff --git a/components/ethernet/emac_main.c b/components/ethernet/emac_main.c index 5479ec399e..8c93a1830e 100644 --- a/components/ethernet/emac_main.c +++ b/components/ethernet/emac_main.c @@ -75,8 +75,7 @@ esp_err_t emac_post(emac_sig_t sig, emac_par_t par); static void emac_macaddr_init(void) { - esp_efuse_read_mac(&(emac_config.macaddr[0])); - emac_config.macaddr[5] = emac_config.macaddr[5] + 3; + esp_read_mac(&(emac_config.macaddr[0]), ESP_MAC_ETH); } void esp_eth_get_mac(uint8_t mac[6])