mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'backport/openthread_feature' into 'release/v5.1'
Backport some Openthread related MR to 5.1(Backport5.1) See merge request espressif/esp-idf!24285
This commit is contained in:
commit
65bf500d29
@ -1024,6 +1024,26 @@ menu "LWIP"
|
|||||||
|
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
|
choice LWIP_HOOK_IP6_SELECT_SRC_ADDR
|
||||||
|
prompt "IPv6 source address selection Hook"
|
||||||
|
depends on LWIP_IPV6
|
||||||
|
default LWIP_HOOK_IP6_SELECT_SRC_ADDR_NONE
|
||||||
|
help
|
||||||
|
Enables custom IPv6 source address selection.
|
||||||
|
Setting this to "default" provides weak implementation
|
||||||
|
stub that could be overwritten in application code.
|
||||||
|
Setting this to "custom" provides hook's declaration
|
||||||
|
only and expects the application to implement it.
|
||||||
|
|
||||||
|
config LWIP_HOOK_IP6_SELECT_SRC_ADDR_NONE
|
||||||
|
bool "No hook declared"
|
||||||
|
config LWIP_HOOK_IP6_SELECT_SRC_ADDR_DEFAULT
|
||||||
|
bool "Default (weak) implementation"
|
||||||
|
config LWIP_HOOK_IP6_SELECT_SRC_ADDR_CUSTOM
|
||||||
|
bool "Custom implementation"
|
||||||
|
|
||||||
|
endchoice
|
||||||
|
|
||||||
choice LWIP_HOOK_NETCONN_EXTERNAL_RESOLVE
|
choice LWIP_HOOK_NETCONN_EXTERNAL_RESOLVE
|
||||||
prompt "Netconn external resolve Hook"
|
prompt "Netconn external resolve Hook"
|
||||||
default LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT if OPENTHREAD_DNS64_CLIENT
|
default LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT if OPENTHREAD_DNS64_CLIENT
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit dafc8225313a1ce00fb0b497d09f43ec7073857d
|
Subproject commit 57c29648ff40e2a19a51683717928aaf766a0495
|
@ -41,7 +41,17 @@ const ip6_addr_t *__weak lwip_hook_nd6_get_gw(struct netif *netif, const ip6_add
|
|||||||
LWIP_UNUSED_ARG(netif);
|
LWIP_UNUSED_ARG(netif);
|
||||||
LWIP_UNUSED_ARG(dest);
|
LWIP_UNUSED_ARG(dest);
|
||||||
|
|
||||||
return 0;
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_DEFAULT
|
||||||
|
const ip_addr_t *__weak lwip_hook_ip6_select_source_address(struct netif *netif, const ip6_addr_t *dest)
|
||||||
|
{
|
||||||
|
LWIP_UNUSED_ARG(netif);
|
||||||
|
LWIP_UNUSED_ARG(dest);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -43,6 +43,12 @@ const ip6_addr_t *lwip_hook_nd6_get_gw(struct netif *netif, const ip6_addr_t *de
|
|||||||
#define LWIP_HOOK_ND6_GET_GW lwip_hook_nd6_get_gw
|
#define LWIP_HOOK_ND6_GET_GW lwip_hook_nd6_get_gw
|
||||||
#endif /* CONFIG_LWIP_HOOK_ND6_GET_GATEWAY... */
|
#endif /* CONFIG_LWIP_HOOK_ND6_GET_GATEWAY... */
|
||||||
|
|
||||||
|
#if defined(CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_CUSTOM) || defined(CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_DEFAULT)
|
||||||
|
const ip_addr_t *lwip_hook_ip6_select_source_address(struct netif *netif, const ip6_addr_t *dest);
|
||||||
|
|
||||||
|
#define LWIP_HOOK_IP6_SELECT_SRC_ADDR lwip_hook_ip6_select_source_address
|
||||||
|
#endif /* CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR... */
|
||||||
|
|
||||||
#if defined(CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM) || defined(CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT)
|
#if defined(CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM) || defined(CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT)
|
||||||
int lwip_hook_netconn_external_resolve(const char *name, ip_addr_t *addr, u8_t addrtype, err_t *err);
|
int lwip_hook_netconn_external_resolve(const char *name, ip_addr_t *addr, u8_t addrtype, err_t *err);
|
||||||
|
|
||||||
|
@ -16,7 +16,8 @@ if(CONFIG_OPENTHREAD_ENABLED)
|
|||||||
"private_include")
|
"private_include")
|
||||||
|
|
||||||
set(src_dirs
|
set(src_dirs
|
||||||
"port"
|
"src"
|
||||||
|
"src/port"
|
||||||
"openthread/examples/platforms/utils"
|
"openthread/examples/platforms/utils"
|
||||||
"openthread/src/core/api"
|
"openthread/src/core/api"
|
||||||
"openthread/src/core/common"
|
"openthread/src/core/common"
|
||||||
@ -57,6 +58,7 @@ if(CONFIG_OPENTHREAD_ENABLED)
|
|||||||
"openthread/examples/apps/ncp")
|
"openthread/examples/apps/ncp")
|
||||||
|
|
||||||
list(APPEND exclude_srcs
|
list(APPEND exclude_srcs
|
||||||
|
"src/port/esp_openthread_state.c"
|
||||||
"openthread/examples/apps/ncp/main.c"
|
"openthread/examples/apps/ncp/main.c"
|
||||||
"openthread/src/core/api/backbone_router_api.cpp"
|
"openthread/src/core/api/backbone_router_api.cpp"
|
||||||
"openthread/src/core/api/child_supervision_api.cpp"
|
"openthread/src/core/api/child_supervision_api.cpp"
|
||||||
@ -113,13 +115,13 @@ if(CONFIG_OPENTHREAD_ENABLED)
|
|||||||
|
|
||||||
if(CONFIG_OPENTHREAD_RADIO_NATIVE)
|
if(CONFIG_OPENTHREAD_RADIO_NATIVE)
|
||||||
list(APPEND exclude_srcs
|
list(APPEND exclude_srcs
|
||||||
"port/esp_openthread_radio_spinel.cpp"
|
"src/port/esp_openthread_radio_spinel.cpp"
|
||||||
"port/esp_spi_spinel_interface.cpp"
|
"src/port/esp_spi_spinel_interface.cpp"
|
||||||
"port/esp_uart_spinel_interface.cpp"
|
"src/port/esp_uart_spinel_interface.cpp"
|
||||||
)
|
)
|
||||||
elseif(CONFIG_OPENTHREAD_RADIO_SPINEL_UART OR CONFIG_OPENTHREAD_RADIO_SPINEL_SPI)
|
elseif(CONFIG_OPENTHREAD_RADIO_SPINEL_UART OR CONFIG_OPENTHREAD_RADIO_SPINEL_SPI)
|
||||||
list(APPEND exclude_srcs
|
list(APPEND exclude_srcs
|
||||||
"port/esp_openthread_radio.c")
|
"src/port/esp_openthread_radio.c")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CONFIG_OPENTHREAD_BORDER_ROUTER)
|
if(CONFIG_OPENTHREAD_BORDER_ROUTER)
|
||||||
@ -135,7 +137,7 @@ if(CONFIG_OPENTHREAD_ENABLED)
|
|||||||
|
|
||||||
if(NOT CONFIG_OPENTHREAD_DNS64_CLIENT)
|
if(NOT CONFIG_OPENTHREAD_DNS64_CLIENT)
|
||||||
list(APPEND exclude_srcs
|
list(APPEND exclude_srcs
|
||||||
"port/esp_openthread_dns64.c")
|
"src/esp_openthread_dns64.c")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CONFIG_OPENTHREAD_FTD)
|
if(CONFIG_OPENTHREAD_FTD)
|
||||||
@ -173,7 +175,7 @@ idf_component_register(SRC_DIRS "${src_dirs}"
|
|||||||
REQUIRES esp_netif lwip driver
|
REQUIRES esp_netif lwip driver
|
||||||
LDFRAGMENTS linker.lf
|
LDFRAGMENTS linker.lf
|
||||||
PRIV_REQUIRES console esp_event esp_partition esp_timer
|
PRIV_REQUIRES console esp_event esp_partition esp_timer
|
||||||
ieee802154 mbedtls spi_flash)
|
ieee802154 mbedtls nvs_flash)
|
||||||
|
|
||||||
if(CONFIG_OPENTHREAD_ENABLED)
|
if(CONFIG_OPENTHREAD_ENABLED)
|
||||||
if(CONFIG_OPENTHREAD_RADIO)
|
if(CONFIG_OPENTHREAD_RADIO)
|
||||||
|
@ -34,6 +34,40 @@ menu "OpenThread"
|
|||||||
bool "Debug logs"
|
bool "Debug logs"
|
||||||
endchoice #OPENTHREAD_LOG_LEVEL
|
endchoice #OPENTHREAD_LOG_LEVEL
|
||||||
|
|
||||||
|
menu "Thread Operational Dataset"
|
||||||
|
config OPENTHREAD_NETWORK_NAME
|
||||||
|
string "OpenThread network name"
|
||||||
|
default "OpenThread-ESP"
|
||||||
|
|
||||||
|
config OPENTHREAD_NETWORK_CHANNEL
|
||||||
|
int "OpenThread network channel"
|
||||||
|
range 11 26
|
||||||
|
default 15
|
||||||
|
|
||||||
|
config OPENTHREAD_NETWORK_PANID
|
||||||
|
hex "OpenThread network pan id"
|
||||||
|
range 0 0xFFFE
|
||||||
|
default 0x1234
|
||||||
|
|
||||||
|
config OPENTHREAD_NETWORK_EXTPANID
|
||||||
|
string "OpenThread extended pan id"
|
||||||
|
default "dead00beef00cafe"
|
||||||
|
help
|
||||||
|
The OpenThread network extended pan id in hex string format
|
||||||
|
|
||||||
|
config OPENTHREAD_NETWORK_MASTERKEY
|
||||||
|
string "OpenThread network key"
|
||||||
|
default "00112233445566778899aabbccddeeff"
|
||||||
|
help
|
||||||
|
The OpenThread network network key in hex string format
|
||||||
|
|
||||||
|
config OPENTHREAD_NETWORK_PSKC
|
||||||
|
string "OpenThread pre-shared commissioner key"
|
||||||
|
default "104810e2315100afd6bc9215a6bfac53"
|
||||||
|
help
|
||||||
|
The OpenThread pre-shared commissioner key in hex string format
|
||||||
|
endmenu
|
||||||
|
|
||||||
config OPENTHREAD_LOG_LEVEL
|
config OPENTHREAD_LOG_LEVEL
|
||||||
int
|
int
|
||||||
depends on OPENTHREAD_ENABLED && !OPENTHREAD_LOG_LEVEL_DYNAMIC
|
depends on OPENTHREAD_ENABLED && !OPENTHREAD_LOG_LEVEL_DYNAMIC
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "esp_openthread_types.h"
|
#include "esp_openthread_types.h"
|
||||||
|
#include "openthread/dataset.h"
|
||||||
#include "openthread/error.h"
|
#include "openthread/error.h"
|
||||||
#include "openthread/instance.h"
|
#include "openthread/instance.h"
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
@ -32,10 +33,23 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
esp_err_t esp_openthread_init(const esp_openthread_platform_config_t *init_config);
|
esp_err_t esp_openthread_init(const esp_openthread_platform_config_t *init_config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Starts the Thread protocol operation and attaches to a Thread network.
|
||||||
|
*
|
||||||
|
* @param[in] datasetTlvs The operational dataset (TLV encoded), if it's NULL, the function will generate the dataset
|
||||||
|
* based on the configurations from kconfig.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK on success
|
||||||
|
* - ESP_FAIL on failures
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
esp_err_t esp_openthread_auto_start(otOperationalDatasetTlvs *datasetTlvs);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Launches the OpenThread main loop.
|
* @brief Launches the OpenThread main loop.
|
||||||
*
|
*
|
||||||
* @note Thie function will not return unless error happens when running the OpenThread stack.
|
* @note This function will not return unless error happens when running the OpenThread stack.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* - ESP_OK on success
|
* - ESP_OK on success
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
// The network data change callback sets the dns server address of index 0, while the CLI sets the dns server address of index 1.
|
||||||
|
#define OPENTHREAD_DNS_SERVER_INDEX 0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function initiizes the dns64 client.
|
* @brief This function initiizes the dns64 client.
|
||||||
|
@ -14,8 +14,10 @@
|
|||||||
#include "driver/gpio.h"
|
#include "driver/gpio.h"
|
||||||
#include "driver/spi_master.h"
|
#include "driver/spi_master.h"
|
||||||
#include "driver/spi_slave.h"
|
#include "driver/spi_slave.h"
|
||||||
|
#include "driver/uart.h"
|
||||||
#include "hal/gpio_types.h"
|
#include "hal/gpio_types.h"
|
||||||
#include "hal/uart_types.h"
|
#include "hal/uart_types.h"
|
||||||
|
#include "openthread/thread.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -28,6 +30,9 @@ extern "C" {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
OPENTHREAD_EVENT_START, /*!< OpenThread stack start */
|
OPENTHREAD_EVENT_START, /*!< OpenThread stack start */
|
||||||
OPENTHREAD_EVENT_STOP, /*!< OpenThread stack stop */
|
OPENTHREAD_EVENT_STOP, /*!< OpenThread stack stop */
|
||||||
|
OPENTHREAD_EVENT_DETACHED, /*!< OpenThread detached */
|
||||||
|
OPENTHREAD_EVENT_ATTACHED, /*!< OpenThread attached */
|
||||||
|
OPENTHREAD_EVENT_ROLE_CHANGED, /*!< OpenThread role changed */
|
||||||
OPENTHREAD_EVENT_IF_UP, /*!< OpenThread network interface up */
|
OPENTHREAD_EVENT_IF_UP, /*!< OpenThread network interface up */
|
||||||
OPENTHREAD_EVENT_IF_DOWN, /*!< OpenThread network interface down */
|
OPENTHREAD_EVENT_IF_DOWN, /*!< OpenThread network interface down */
|
||||||
OPENTHREAD_EVENT_GOT_IP6, /*!< OpenThread stack added IPv6 address */
|
OPENTHREAD_EVENT_GOT_IP6, /*!< OpenThread stack added IPv6 address */
|
||||||
@ -46,6 +51,15 @@ typedef enum {
|
|||||||
*/
|
*/
|
||||||
ESP_EVENT_DECLARE_BASE(OPENTHREAD_EVENT);
|
ESP_EVENT_DECLARE_BASE(OPENTHREAD_EVENT);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief OpenThread role changed event data
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
otDeviceRole previous_role; /*!< Previous Thread role */
|
||||||
|
otDeviceRole current_role; /*!< Current Thread role */
|
||||||
|
} esp_openthread_role_changed_event_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This structure represents a context for a select() based mainloop.
|
* This structure represents a context for a select() based mainloop.
|
||||||
*
|
*
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit fed28dde58d5d4a46d3acc4935a23b43fe82b320
|
Subproject commit 36cb2202e10b5ba7484654962ca9e3ceb51f6d51
|
@ -1,96 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "esp_openthread.h"
|
|
||||||
#include "esp_check.h"
|
|
||||||
#include "esp_openthread_border_router.h"
|
|
||||||
#include "esp_openthread_common_macro.h"
|
|
||||||
#include "esp_openthread_dns64.h"
|
|
||||||
#include "esp_openthread_lock.h"
|
|
||||||
#include "esp_openthread_platform.h"
|
|
||||||
#include "esp_openthread_task_queue.h"
|
|
||||||
#include "esp_openthread_types.h"
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "lwip/dns.h"
|
|
||||||
#include "openthread/instance.h"
|
|
||||||
#include "openthread/netdata.h"
|
|
||||||
#include "openthread/tasklet.h"
|
|
||||||
|
|
||||||
esp_err_t esp_openthread_init(const esp_openthread_platform_config_t *config)
|
|
||||||
{
|
|
||||||
ESP_RETURN_ON_ERROR(esp_openthread_platform_init(config), OT_PLAT_LOG_TAG,
|
|
||||||
"Failed to initialize OpenThread platform driver");
|
|
||||||
esp_openthread_lock_acquire(portMAX_DELAY);
|
|
||||||
ESP_RETURN_ON_FALSE(otInstanceInitSingle() != NULL, ESP_FAIL, OT_PLAT_LOG_TAG,
|
|
||||||
"Failed to initialize OpenThread instance");
|
|
||||||
#if CONFIG_OPENTHREAD_DNS64_CLIENT
|
|
||||||
ESP_RETURN_ON_ERROR(esp_openthread_dns64_client_init(), OT_PLAT_LOG_TAG,
|
|
||||||
"Failed to initialize OpenThread dns64 client");
|
|
||||||
#endif
|
|
||||||
esp_openthread_lock_release();
|
|
||||||
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t esp_openthread_launch_mainloop(void)
|
|
||||||
{
|
|
||||||
esp_openthread_mainloop_context_t mainloop;
|
|
||||||
otInstance *instance = esp_openthread_get_instance();
|
|
||||||
esp_err_t error = ESP_OK;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
FD_ZERO(&mainloop.read_fds);
|
|
||||||
FD_ZERO(&mainloop.write_fds);
|
|
||||||
FD_ZERO(&mainloop.error_fds);
|
|
||||||
|
|
||||||
mainloop.max_fd = -1;
|
|
||||||
mainloop.timeout.tv_sec = 10;
|
|
||||||
mainloop.timeout.tv_usec = 0;
|
|
||||||
|
|
||||||
esp_openthread_lock_acquire(portMAX_DELAY);
|
|
||||||
esp_openthread_platform_update(&mainloop);
|
|
||||||
if (otTaskletsArePending(instance)) {
|
|
||||||
mainloop.timeout.tv_sec = 0;
|
|
||||||
mainloop.timeout.tv_usec = 0;
|
|
||||||
}
|
|
||||||
esp_openthread_lock_release();
|
|
||||||
|
|
||||||
if (select(mainloop.max_fd + 1, &mainloop.read_fds, &mainloop.write_fds, &mainloop.error_fds,
|
|
||||||
&mainloop.timeout) >= 0) {
|
|
||||||
esp_openthread_lock_acquire(portMAX_DELAY);
|
|
||||||
error = esp_openthread_platform_process(instance, &mainloop);
|
|
||||||
while (otTaskletsArePending(instance)) {
|
|
||||||
otTaskletsProcess(instance);
|
|
||||||
}
|
|
||||||
esp_openthread_lock_release();
|
|
||||||
if (error != ESP_OK) {
|
|
||||||
ESP_LOGE(OT_PLAT_LOG_TAG, "esp_openthread_platform_process failed");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
error = ESP_FAIL;
|
|
||||||
ESP_LOGE(OT_PLAT_LOG_TAG, "OpenThread system polling failed");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t esp_openthread_deinit(void)
|
|
||||||
{
|
|
||||||
otInstanceFinalize(esp_openthread_get_instance());
|
|
||||||
return esp_openthread_platform_deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void stub_task(void *context)
|
|
||||||
{
|
|
||||||
// this is a empty function used for ot-task signal pending
|
|
||||||
}
|
|
||||||
|
|
||||||
void otTaskletsSignalPending(otInstance *aInstance)
|
|
||||||
{
|
|
||||||
esp_openthread_task_queue_post(stub_task, NULL);
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@ -14,15 +14,6 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The state handler to be called when OpenThread state changes
|
|
||||||
*
|
|
||||||
* @param[in] changed_flags The changed Openthread states
|
|
||||||
* @param[in] ctx A pointer to application-specific context
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void esp_openthread_netif_glue_state_callback(otChangedFlags changed_flags, void *ctx);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function updates the netif fds and timeouts to the main loop.
|
* @brief This function updates the netif fds and timeouts to the main loop.
|
||||||
*
|
*
|
||||||
|
@ -139,6 +139,13 @@ void esp_openthread_platform_update(esp_openthread_mainloop_context_t *mainloop)
|
|||||||
*/
|
*/
|
||||||
esp_err_t esp_openthread_platform_process(otInstance *instance, const esp_openthread_mainloop_context_t *mainloop);
|
esp_err_t esp_openthread_platform_process(otInstance *instance, const esp_openthread_mainloop_context_t *mainloop);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function set the OpenThread storage name
|
||||||
|
*
|
||||||
|
* @param[in] name The OpenThread storage name.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void esp_openthread_set_storage_name(const char *name);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // end of extern "C"
|
} // end of extern "C"
|
||||||
#endif
|
#endif
|
||||||
|
31
components/openthread/private_include/esp_openthread_state.h
Normal file
31
components/openthread/private_include/esp_openthread_state.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <esp_err.h>
|
||||||
|
#include <esp_openthread.h>
|
||||||
|
#include <esp_openthread_types.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function initiizes OpenThread state event post.
|
||||||
|
*
|
||||||
|
* @pram[in] instance The OpenThread instance
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK on success
|
||||||
|
* - ESP_FAIL if OpenThread state changed callback fails to be registered
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
esp_err_t esp_openthread_state_event_init(otInstance *instance);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@ -32,7 +32,7 @@
|
|||||||
* When defined to 1, the platform MUST implement the otPlatFlash* APIs instead of the otPlatSettings* APIs.
|
* When defined to 1, the platform MUST implement the otPlatFlash* APIs instead of the otPlatSettings* APIs.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#define OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE 1
|
#define OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE 0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @def OPENTHREAD_CONFIG_LOG_OUTPUT
|
* @def OPENTHREAD_CONFIG_LOG_OUTPUT
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
* When defined to 1, the platform MUST implement the otPlatFlash* APIs instead of the otPlatSettings* APIs.
|
* When defined to 1, the platform MUST implement the otPlatFlash* APIs instead of the otPlatSettings* APIs.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#define OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE 1
|
#define OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE 0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @def OPENTHREAD_CONFIG_LOG_OUTPUT
|
* @def OPENTHREAD_CONFIG_LOG_OUTPUT
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
* When defined to 1, the platform MUST implement the otPlatFlash* APIs instead of the otPlatSettings* APIs.
|
* When defined to 1, the platform MUST implement the otPlatFlash* APIs instead of the otPlatSettings* APIs.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#define OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE 1
|
#define OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE 0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @def OPENTHREAD_CONFIG_LOG_OUTPUT
|
* @def OPENTHREAD_CONFIG_LOG_OUTPUT
|
||||||
|
199
components/openthread/src/esp_openthread.cpp
Normal file
199
components/openthread/src/esp_openthread.cpp
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "esp_openthread.h"
|
||||||
|
#include "esp_check.h"
|
||||||
|
#include "esp_openthread_border_router.h"
|
||||||
|
#include "esp_openthread_common_macro.h"
|
||||||
|
#include "esp_openthread_dns64.h"
|
||||||
|
#include "esp_openthread_lock.h"
|
||||||
|
#include "esp_openthread_platform.h"
|
||||||
|
#include "esp_openthread_state.h"
|
||||||
|
#include "esp_openthread_task_queue.h"
|
||||||
|
#include "esp_openthread_types.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "lwip/dns.h"
|
||||||
|
#include "openthread/instance.h"
|
||||||
|
#include "openthread/netdata.h"
|
||||||
|
#include "openthread/tasklet.h"
|
||||||
|
#include "openthread/thread.h"
|
||||||
|
|
||||||
|
static int hex_digit_to_int(char hex)
|
||||||
|
{
|
||||||
|
if ('A' <= hex && hex <= 'F') {
|
||||||
|
return 10 + hex - 'A';
|
||||||
|
}
|
||||||
|
if ('a' <= hex && hex <= 'f') {
|
||||||
|
return 10 + hex - 'a';
|
||||||
|
}
|
||||||
|
if ('0' <= hex && hex <= '9') {
|
||||||
|
return hex - '0';
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t hex_string_to_binary(const char *hex_string, uint8_t *buf, size_t buf_size)
|
||||||
|
{
|
||||||
|
int num_char = strlen(hex_string);
|
||||||
|
|
||||||
|
if (num_char != buf_size * 2) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < num_char; i += 2) {
|
||||||
|
int digit0 = hex_digit_to_int(hex_string[i]);
|
||||||
|
int digit1 = hex_digit_to_int(hex_string[i + 1]);
|
||||||
|
|
||||||
|
if (digit0 < 0 || digit1 < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
buf[i / 2] = (digit0 << 4) + digit1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_openthread_init(const esp_openthread_platform_config_t *config)
|
||||||
|
{
|
||||||
|
ESP_RETURN_ON_ERROR(esp_openthread_platform_init(config), OT_PLAT_LOG_TAG,
|
||||||
|
"Failed to initialize OpenThread platform driver");
|
||||||
|
esp_openthread_lock_acquire(portMAX_DELAY);
|
||||||
|
ESP_RETURN_ON_FALSE(otInstanceInitSingle() != NULL, ESP_FAIL, OT_PLAT_LOG_TAG,
|
||||||
|
"Failed to initialize OpenThread instance");
|
||||||
|
#if CONFIG_OPENTHREAD_DNS64_CLIENT
|
||||||
|
ESP_RETURN_ON_ERROR(esp_openthread_dns64_client_init(), OT_PLAT_LOG_TAG,
|
||||||
|
"Failed to initialize OpenThread dns64 client");
|
||||||
|
#endif
|
||||||
|
#if !CONFIG_OPENTHREAD_RADIO
|
||||||
|
ESP_RETURN_ON_ERROR(esp_openthread_state_event_init(esp_openthread_get_instance()), OT_PLAT_LOG_TAG,
|
||||||
|
"Failed to initialize OpenThread state event");
|
||||||
|
#endif
|
||||||
|
esp_openthread_lock_release();
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_openthread_auto_start(otOperationalDatasetTlvs *datasetTlvs)
|
||||||
|
{
|
||||||
|
otInstance *instance = esp_openthread_get_instance();
|
||||||
|
|
||||||
|
if (datasetTlvs) {
|
||||||
|
ESP_RETURN_ON_FALSE(otDatasetSetActiveTlvs(instance, datasetTlvs) == OT_ERROR_NONE, ESP_FAIL, OT_PLAT_LOG_TAG,
|
||||||
|
"Failed to set OpenThread active dataset");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
otOperationalDataset dataset;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
memset(&dataset, 0, sizeof(otOperationalDataset));
|
||||||
|
|
||||||
|
// Active timestamp
|
||||||
|
dataset.mActiveTimestamp.mSeconds = 1;
|
||||||
|
dataset.mActiveTimestamp.mTicks = 0;
|
||||||
|
dataset.mActiveTimestamp.mAuthoritative = false;
|
||||||
|
dataset.mComponents.mIsActiveTimestampPresent = true;
|
||||||
|
|
||||||
|
// Channel, Pan ID, Network Name
|
||||||
|
dataset.mChannel = CONFIG_OPENTHREAD_NETWORK_CHANNEL;
|
||||||
|
dataset.mComponents.mIsChannelPresent = true;
|
||||||
|
dataset.mPanId = CONFIG_OPENTHREAD_NETWORK_PANID;
|
||||||
|
dataset.mComponents.mIsPanIdPresent = true;
|
||||||
|
len = strlen(CONFIG_OPENTHREAD_NETWORK_NAME);
|
||||||
|
assert(len <= OT_NETWORK_NAME_MAX_SIZE);
|
||||||
|
memcpy(dataset.mNetworkName.m8, CONFIG_OPENTHREAD_NETWORK_NAME, len);
|
||||||
|
dataset.mComponents.mIsNetworkNamePresent = true;
|
||||||
|
|
||||||
|
// Extended Pan ID
|
||||||
|
len = hex_string_to_binary(CONFIG_OPENTHREAD_NETWORK_EXTPANID, dataset.mExtendedPanId.m8,
|
||||||
|
sizeof(dataset.mExtendedPanId.m8));
|
||||||
|
ESP_RETURN_ON_FALSE(len == sizeof(dataset.mExtendedPanId.m8), ESP_FAIL, OT_PLAT_LOG_TAG,
|
||||||
|
"Cannot convert OpenThread extended pan id");
|
||||||
|
dataset.mComponents.mIsExtendedPanIdPresent = true;
|
||||||
|
|
||||||
|
// Network Key
|
||||||
|
len = hex_string_to_binary(CONFIG_OPENTHREAD_NETWORK_MASTERKEY, dataset.mNetworkKey.m8,
|
||||||
|
sizeof(dataset.mNetworkKey.m8));
|
||||||
|
ESP_RETURN_ON_FALSE(len == sizeof(dataset.mNetworkKey.m8), ESP_FAIL, OT_PLAT_LOG_TAG,
|
||||||
|
"Cannot convert OpenThread master key");
|
||||||
|
dataset.mComponents.mIsNetworkKeyPresent = true;
|
||||||
|
|
||||||
|
// PSKc
|
||||||
|
len = hex_string_to_binary(CONFIG_OPENTHREAD_NETWORK_PSKC, dataset.mPskc.m8, sizeof(dataset.mPskc.m8));
|
||||||
|
ESP_RETURN_ON_FALSE(len == sizeof(dataset.mPskc.m8), ESP_FAIL, OT_PLAT_LOG_TAG,
|
||||||
|
"Cannot convert OpenThread pre-shared commissioner key");
|
||||||
|
dataset.mComponents.mIsPskcPresent = true;
|
||||||
|
|
||||||
|
ESP_RETURN_ON_FALSE(otDatasetSetActive(instance, &dataset) == OT_ERROR_NONE, ESP_FAIL, OT_PLAT_LOG_TAG,
|
||||||
|
"Failed to set OpenThread active dataset");
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_RETURN_ON_FALSE(otIp6SetEnabled(instance, true) == OT_ERROR_NONE, ESP_FAIL, OT_PLAT_LOG_TAG,
|
||||||
|
"Failed to enable OpenThread IPv6 interface");
|
||||||
|
|
||||||
|
ESP_RETURN_ON_FALSE(otThreadSetEnabled(instance, true) == OT_ERROR_NONE, ESP_FAIL, OT_PLAT_LOG_TAG,
|
||||||
|
"Failed to enable OpenThread");
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_openthread_launch_mainloop(void)
|
||||||
|
{
|
||||||
|
esp_openthread_mainloop_context_t mainloop;
|
||||||
|
otInstance *instance = esp_openthread_get_instance();
|
||||||
|
esp_err_t error = ESP_OK;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
FD_ZERO(&mainloop.read_fds);
|
||||||
|
FD_ZERO(&mainloop.write_fds);
|
||||||
|
FD_ZERO(&mainloop.error_fds);
|
||||||
|
|
||||||
|
mainloop.max_fd = -1;
|
||||||
|
mainloop.timeout.tv_sec = 10;
|
||||||
|
mainloop.timeout.tv_usec = 0;
|
||||||
|
|
||||||
|
esp_openthread_lock_acquire(portMAX_DELAY);
|
||||||
|
esp_openthread_platform_update(&mainloop);
|
||||||
|
if (otTaskletsArePending(instance)) {
|
||||||
|
mainloop.timeout.tv_sec = 0;
|
||||||
|
mainloop.timeout.tv_usec = 0;
|
||||||
|
}
|
||||||
|
esp_openthread_lock_release();
|
||||||
|
|
||||||
|
if (select(mainloop.max_fd + 1, &mainloop.read_fds, &mainloop.write_fds, &mainloop.error_fds,
|
||||||
|
&mainloop.timeout) >= 0) {
|
||||||
|
esp_openthread_lock_acquire(portMAX_DELAY);
|
||||||
|
error = esp_openthread_platform_process(instance, &mainloop);
|
||||||
|
while (otTaskletsArePending(instance)) {
|
||||||
|
otTaskletsProcess(instance);
|
||||||
|
}
|
||||||
|
esp_openthread_lock_release();
|
||||||
|
if (error != ESP_OK) {
|
||||||
|
ESP_LOGE(OT_PLAT_LOG_TAG, "esp_openthread_platform_process failed");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error = ESP_FAIL;
|
||||||
|
ESP_LOGE(OT_PLAT_LOG_TAG, "OpenThread system polling failed");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_openthread_deinit(void)
|
||||||
|
{
|
||||||
|
otInstanceFinalize(esp_openthread_get_instance());
|
||||||
|
return esp_openthread_platform_deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stub_task(void *context)
|
||||||
|
{
|
||||||
|
// this is a empty function used for ot-task signal pending
|
||||||
|
}
|
||||||
|
|
||||||
|
void otTaskletsSignalPending(otInstance *aInstance)
|
||||||
|
{
|
||||||
|
esp_openthread_task_queue_post(stub_task, NULL);
|
||||||
|
}
|
@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "esp_openthread_dns64.h"
|
#include "esp_openthread_dns64.h"
|
||||||
|
#include "esp_openthread_state.h"
|
||||||
|
|
||||||
#include "esp_check.h"
|
#include "esp_check.h"
|
||||||
#include "esp_event.h"
|
#include "esp_event.h"
|
||||||
@ -16,34 +17,9 @@
|
|||||||
#include "lwip/dns.h"
|
#include "lwip/dns.h"
|
||||||
|
|
||||||
#define TAG "OT_DNS64"
|
#define TAG "OT_DNS64"
|
||||||
// The network data change callback sets the dns server address of index 0, while the CLI sets the dns server address of index 1.
|
|
||||||
#define OPENTHREAD_DNS_SERVER_INDEX 0
|
|
||||||
|
|
||||||
static void esp_openthread_netdata_change_callback(otChangedFlags changed_flags, void *ctx)
|
|
||||||
{
|
|
||||||
if (OT_CHANGED_THREAD_NETDATA & changed_flags) {
|
|
||||||
ip_addr_t dns_server_addr = *IP_ADDR_ANY;
|
|
||||||
if (esp_openthread_get_nat64_prefix(&dns_server_addr.u_addr.ip6) == ESP_OK) {
|
|
||||||
dns_server_addr.type = IPADDR_TYPE_V6;
|
|
||||||
dns_server_addr.u_addr.ip6.addr[3] = ipaddr_addr(CONFIG_OPENTHREAD_DNS_SERVER_ADDR);
|
|
||||||
const ip_addr_t *dnsserver = dns_getserver(OPENTHREAD_DNS_SERVER_INDEX);
|
|
||||||
if (memcmp(dnsserver, &dns_server_addr, sizeof(ip_addr_t)) != 0) {
|
|
||||||
ESP_LOGI(TAG, "Set dns server address: %s", ipaddr_ntoa(&dns_server_addr));
|
|
||||||
dns_setserver(OPENTHREAD_DNS_SERVER_INDEX, &dns_server_addr);
|
|
||||||
if (esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_SET_DNS_SERVER, NULL, 0, 0) != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG, "Failed to post OpenThread set DNS server event");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t esp_openthread_dns64_client_init(void)
|
esp_err_t esp_openthread_dns64_client_init(void)
|
||||||
{
|
{
|
||||||
otInstance *instance = esp_openthread_get_instance();
|
|
||||||
ESP_RETURN_ON_FALSE(otSetStateChangedCallback(instance, esp_openthread_netdata_change_callback, NULL) ==
|
|
||||||
OT_ERROR_NONE,
|
|
||||||
ESP_FAIL, TAG, "Failed to install network data change callback");
|
|
||||||
dns_setserver(OPENTHREAD_DNS_SERVER_INDEX, NULL);
|
dns_setserver(OPENTHREAD_DNS_SERVER_INDEX, NULL);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
@ -15,6 +15,7 @@
|
|||||||
#include "lwip/esp_netif_net_stack.h"
|
#include "lwip/esp_netif_net_stack.h"
|
||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
#include "lwip/pbuf.h"
|
#include "lwip/pbuf.h"
|
||||||
|
#include "lwip_default_hooks.h"
|
||||||
#include "openthread/error.h"
|
#include "openthread/error.h"
|
||||||
#include "openthread/ip6.h"
|
#include "openthread/ip6.h"
|
||||||
#include "openthread/link.h"
|
#include "openthread/link.h"
|
||||||
@ -143,3 +144,25 @@ static err_t openthread_netif_init(struct netif *netif)
|
|||||||
|
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ip_addr_t *lwip_hook_ip6_select_source_address(struct netif *netif, const ip6_addr_t *dest)
|
||||||
|
{
|
||||||
|
const ip6_addr_t *cur_addr;
|
||||||
|
uint8_t idx = 0;
|
||||||
|
// Only process with ot netif.
|
||||||
|
if (!(netif->name[0] == 'o' && netif->name[1] == 't')) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// Currently, prefer the address with the same prefix of the destination address.
|
||||||
|
// If no address found, return NULL for selection source address using the default algorithm.
|
||||||
|
for (idx = 0; idx < LWIP_IPV6_NUM_ADDRESSES; idx++) {
|
||||||
|
if (!ip6_addr_isvalid(netif_ip6_addr_state(netif, idx))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
cur_addr = netif_ip6_addr(netif, idx);
|
||||||
|
if (ip6_addr_netcmp_zoneless(cur_addr, dest)) {
|
||||||
|
return netif_ip_addr6(netif, idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@ -20,6 +20,7 @@
|
|||||||
#include "esp_openthread_lock.h"
|
#include "esp_openthread_lock.h"
|
||||||
#include "esp_openthread_netif_glue_priv.h"
|
#include "esp_openthread_netif_glue_priv.h"
|
||||||
#include "esp_openthread_platform.h"
|
#include "esp_openthread_platform.h"
|
||||||
|
#include "esp_openthread_state.h"
|
||||||
#include "esp_openthread_types.h"
|
#include "esp_openthread_types.h"
|
||||||
#include "esp_vfs_eventfd.h"
|
#include "esp_vfs_eventfd.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
@ -170,30 +171,6 @@ static esp_err_t process_thread_transmit(otInstance *instance)
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void esp_openthread_netif_glue_state_callback(otChangedFlags changed_flags, void *ctx)
|
|
||||||
{
|
|
||||||
otInstance *instance = esp_openthread_get_instance();
|
|
||||||
esp_err_t err = ESP_OK;
|
|
||||||
|
|
||||||
if (s_packet_queue != NULL && (OT_CHANGED_THREAD_NETIF_STATE & changed_flags)) {
|
|
||||||
if (otLinkIsEnabled(instance)) {
|
|
||||||
ESP_LOGI(OT_PLAT_LOG_TAG, "netif up");
|
|
||||||
if (esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_IF_UP, NULL, 0, 0) != ESP_OK) {
|
|
||||||
ESP_LOGE(OT_PLAT_LOG_TAG, "Failed to post OpenThread if up event");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ESP_LOGI(OT_PLAT_LOG_TAG, "netif down");
|
|
||||||
if (esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_IF_DOWN, NULL, 0, 0) != ESP_OK) {
|
|
||||||
ESP_LOGE(OT_PLAT_LOG_TAG, "Failed to post OpenThread if down event");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err != ESP_OK) {
|
|
||||||
ESP_LOGE(OT_PLAT_LOG_TAG, "Failed to configure netif state");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t openthread_netif_transmit(void *handle, void *buffer, size_t len)
|
static esp_err_t openthread_netif_transmit(void *handle, void *buffer, size_t len)
|
||||||
{
|
{
|
||||||
esp_err_t error = ESP_OK;
|
esp_err_t error = ESP_OK;
|
||||||
@ -298,9 +275,6 @@ void *esp_openthread_netif_glue_init(const esp_openthread_platform_config_t *con
|
|||||||
if (instance == NULL || s_packet_queue || s_openthread_netif_glue.event_fd >= 0) {
|
if (instance == NULL || s_packet_queue || s_openthread_netif_glue.event_fd >= 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ESP_RETURN_ON_FALSE(otSetStateChangedCallback(instance, esp_openthread_netif_glue_state_callback, NULL) ==
|
|
||||||
OT_ERROR_NONE,
|
|
||||||
NULL, OT_PLAT_LOG_TAG, "Failed to install netif glue state callback");
|
|
||||||
|
|
||||||
s_packet_queue = xQueueCreate(config->port_config.netif_queue_size, sizeof(otMessage *));
|
s_packet_queue = xQueueCreate(config->port_config.netif_queue_size, sizeof(otMessage *));
|
||||||
if (s_packet_queue == NULL) {
|
if (s_packet_queue == NULL) {
|
@ -102,18 +102,12 @@ esp_err_t esp_openthread_platform_init(const esp_openthread_platform_config_t *c
|
|||||||
s_openthread_platform_initialized = true;
|
s_openthread_platform_initialized = true;
|
||||||
esp_err_t ret = ESP_OK;
|
esp_err_t ret = ESP_OK;
|
||||||
|
|
||||||
/* Avoid to compile flash in RADIO type device */
|
|
||||||
#if !CONFIG_OPENTHREAD_RADIO
|
|
||||||
const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY,
|
|
||||||
config->port_config.storage_partition_name);
|
|
||||||
ESP_RETURN_ON_FALSE(partition, ESP_ERR_INVALID_ARG, OT_PLAT_LOG_TAG, "OpenThread storage partition not found");
|
|
||||||
esp_openthread_flash_set_partition(partition);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
s_platform_config = *config;
|
s_platform_config = *config;
|
||||||
ESP_GOTO_ON_ERROR(esp_openthread_lock_init(), exit, OT_PLAT_LOG_TAG, "esp_openthread_lock_init failed");
|
ESP_GOTO_ON_ERROR(esp_openthread_lock_init(), exit, OT_PLAT_LOG_TAG, "esp_openthread_lock_init failed");
|
||||||
ESP_GOTO_ON_ERROR(esp_openthread_alarm_init(), exit, OT_PLAT_LOG_TAG, "esp_openthread_alarm_init failed");
|
ESP_GOTO_ON_ERROR(esp_openthread_alarm_init(), exit, OT_PLAT_LOG_TAG, "esp_openthread_alarm_init failed");
|
||||||
|
|
||||||
|
esp_openthread_set_storage_name(config->port_config.storage_partition_name);
|
||||||
|
|
||||||
if (config->host_config.host_connection_mode == HOST_CONNECTION_MODE_RCP_SPI) {
|
if (config->host_config.host_connection_mode == HOST_CONNECTION_MODE_RCP_SPI) {
|
||||||
ESP_GOTO_ON_ERROR(esp_openthread_spi_slave_init(config), exit, OT_PLAT_LOG_TAG,
|
ESP_GOTO_ON_ERROR(esp_openthread_spi_slave_init(config), exit, OT_PLAT_LOG_TAG,
|
||||||
"esp_openthread_spi_slave_init failed");
|
"esp_openthread_spi_slave_init failed");
|
216
components/openthread/src/port/esp_openthread_settings.c
Normal file
216
components/openthread/src/port/esp_openthread_settings.c
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "nvs.h"
|
||||||
|
#include "esp_check.h"
|
||||||
|
#include "esp_openthread_common_macro.h"
|
||||||
|
#include "openthread/instance.h"
|
||||||
|
#include "openthread/platform/settings.h"
|
||||||
|
|
||||||
|
#define OT_NAMESPACE "openthread"
|
||||||
|
#define OT_PART_NAME s_storage_name
|
||||||
|
#define OT_KEY_PATTERN "OT%02x"
|
||||||
|
#define OT_KEY_INDEX_PATTERN "OT%02x%02x"
|
||||||
|
#define OT_KEY_PATTERN_LEN 5
|
||||||
|
#define OT_KEY_INDEX_PATTERN_LEN 7
|
||||||
|
static nvs_handle_t s_ot_nvs_handle;
|
||||||
|
static const char *s_storage_name;
|
||||||
|
|
||||||
|
void esp_openthread_set_storage_name(const char *name)
|
||||||
|
{
|
||||||
|
s_storage_name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t get_next_empty_index(uint16_t aKey, uint8_t *index)
|
||||||
|
{
|
||||||
|
ESP_RETURN_ON_FALSE((s_ot_nvs_handle != 0), ESP_ERR_INVALID_STATE, OT_PLAT_LOG_TAG, "OT NVS handle is invalid.");
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
static volatile uint8_t s_unused_pos = 0;
|
||||||
|
char ot_nvs_key[OT_KEY_INDEX_PATTERN_LEN] = { 0 };
|
||||||
|
nvs_iterator_t nvs_it = NULL;
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i != UINT8_MAX; i++) {
|
||||||
|
s_unused_pos++;
|
||||||
|
snprintf(ot_nvs_key, sizeof(ot_nvs_key), OT_KEY_INDEX_PATTERN, (uint8_t)aKey, s_unused_pos);
|
||||||
|
ret = nvs_entry_find(OT_PART_NAME, OT_NAMESPACE, NVS_TYPE_BLOB, &nvs_it);
|
||||||
|
while (ret == ESP_OK) {
|
||||||
|
nvs_entry_info_t info;
|
||||||
|
nvs_entry_info(nvs_it, &info);
|
||||||
|
if (memcmp(ot_nvs_key, info.key, OT_KEY_INDEX_PATTERN_LEN - 1) == 0) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ret = nvs_entry_next(&nvs_it);
|
||||||
|
}
|
||||||
|
nvs_release_iterator(nvs_it);
|
||||||
|
if (!found) {
|
||||||
|
// find an empty position, return ESP_OK
|
||||||
|
*index = s_unused_pos;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// all index was used, no memory for current data, return ESP_ERR_NOT_FOUND.
|
||||||
|
return ESP_ERR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t find_target_key_using_index(uint16_t aKey, int aIndex, char *key, size_t key_len)
|
||||||
|
{
|
||||||
|
ESP_RETURN_ON_FALSE((s_ot_nvs_handle != 0), ESP_ERR_INVALID_STATE, OT_PLAT_LOG_TAG, "OT NVS handle is invalid.");
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
nvs_iterator_t nvs_it = NULL;
|
||||||
|
int cur_index = 0;
|
||||||
|
char ot_nvs_key[OT_KEY_PATTERN_LEN] = { 0 };
|
||||||
|
|
||||||
|
ret = nvs_entry_find(OT_PART_NAME, OT_NAMESPACE, NVS_TYPE_BLOB, &nvs_it);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
snprintf(ot_nvs_key, sizeof(ot_nvs_key), OT_KEY_PATTERN, (uint8_t)aKey);
|
||||||
|
while (ret == ESP_OK) {
|
||||||
|
nvs_entry_info_t info;
|
||||||
|
nvs_entry_info(nvs_it, &info);
|
||||||
|
if (memcmp(ot_nvs_key, info.key, OT_KEY_PATTERN_LEN - 1) == 0) {
|
||||||
|
if (cur_index == aIndex) {
|
||||||
|
memcpy(key, info.key, key_len);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
cur_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = nvs_entry_next(&nvs_it);
|
||||||
|
}
|
||||||
|
nvs_release_iterator(nvs_it);
|
||||||
|
|
||||||
|
if ((cur_index != aIndex) || (ret != ESP_OK)) {
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t erase_all_key(uint16_t aKey)
|
||||||
|
{
|
||||||
|
ESP_RETURN_ON_FALSE((s_ot_nvs_handle != 0), ESP_ERR_INVALID_STATE, OT_PLAT_LOG_TAG, "OT NVS handle is invalid.");
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
nvs_iterator_t nvs_it = NULL;
|
||||||
|
char ot_nvs_key[OT_KEY_PATTERN_LEN] = { 0 };
|
||||||
|
|
||||||
|
ret = nvs_entry_find(OT_PART_NAME, OT_NAMESPACE, NVS_TYPE_BLOB, &nvs_it);
|
||||||
|
if (ret == ESP_ERR_NVS_NOT_FOUND) {
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
ESP_RETURN_ON_FALSE((ret == ESP_OK && nvs_it != NULL), ESP_FAIL, OT_PLAT_LOG_TAG, "Can not find any data in nvs flash, err: %d", ret);
|
||||||
|
while (ret == ESP_OK) {
|
||||||
|
snprintf(ot_nvs_key, sizeof(ot_nvs_key), OT_KEY_PATTERN, (uint8_t)aKey);
|
||||||
|
nvs_entry_info_t info;
|
||||||
|
nvs_entry_info(nvs_it, &info);
|
||||||
|
if (memcmp(ot_nvs_key, info.key, OT_KEY_PATTERN_LEN - 1) == 0) {
|
||||||
|
ret = nvs_erase_key(s_ot_nvs_handle, info.key);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = nvs_entry_next(&nvs_it);
|
||||||
|
}
|
||||||
|
nvs_release_iterator(nvs_it);
|
||||||
|
ret = nvs_commit(s_ot_nvs_handle);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void otPlatSettingsInit(otInstance *aInstance, const uint16_t *aSensitiveKeys, uint16_t aSensitiveKeysLength)
|
||||||
|
{
|
||||||
|
esp_err_t err = nvs_open(OT_NAMESPACE, NVS_READWRITE, &s_ot_nvs_handle);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE(OT_PLAT_LOG_TAG, "Failed to open NVS namespace (0x%x)", err);
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void otPlatSettingsDeinit(otInstance *aInstance)
|
||||||
|
{
|
||||||
|
if (s_ot_nvs_handle != 0) {
|
||||||
|
nvs_close(s_ot_nvs_handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
otError otPlatSettingsGet(otInstance *aInstance, uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength)
|
||||||
|
{
|
||||||
|
ESP_RETURN_ON_FALSE((s_ot_nvs_handle != 0), OT_ERROR_NOT_FOUND, OT_PLAT_LOG_TAG, "OT NVS handle is invalid.");
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
char ot_nvs_key[OT_KEY_INDEX_PATTERN_LEN] = { 0 };
|
||||||
|
|
||||||
|
ret = find_target_key_using_index(aKey, aIndex, ot_nvs_key, OT_KEY_INDEX_PATTERN_LEN);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
return OT_ERROR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
size_t length = *aValueLength;
|
||||||
|
ret = nvs_get_blob(s_ot_nvs_handle, ot_nvs_key, aValue, &length);
|
||||||
|
*aValueLength = (uint16_t) length;
|
||||||
|
ESP_RETURN_ON_FALSE((ret == ESP_OK), OT_ERROR_NOT_FOUND, OT_PLAT_LOG_TAG, "Data not found, err: %d", ret);
|
||||||
|
return OT_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
otError otPlatSettingsSet(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
|
||||||
|
{
|
||||||
|
ESP_RETURN_ON_FALSE((s_ot_nvs_handle != 0), OT_ERROR_NOT_FOUND, OT_PLAT_LOG_TAG, "OT NVS handle is invalid.");
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
char ot_nvs_key[OT_KEY_INDEX_PATTERN_LEN]= { 0 };
|
||||||
|
|
||||||
|
snprintf(ot_nvs_key, sizeof(ot_nvs_key), OT_KEY_INDEX_PATTERN, (uint8_t)aKey, 0);
|
||||||
|
ret = nvs_set_blob(s_ot_nvs_handle, ot_nvs_key, aValue, aValueLength);
|
||||||
|
ESP_RETURN_ON_FALSE((ret == ESP_OK), OT_ERROR_NO_BUFS, OT_PLAT_LOG_TAG, "No buffers, err: %d", ret);
|
||||||
|
ret = nvs_commit(s_ot_nvs_handle);
|
||||||
|
ESP_RETURN_ON_FALSE((ret == ESP_OK), OT_ERROR_NO_BUFS, OT_PLAT_LOG_TAG, "OT NVS handle shut down, err: %d", ret);
|
||||||
|
return OT_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
otError otPlatSettingsAdd(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
|
||||||
|
{
|
||||||
|
ESP_RETURN_ON_FALSE((s_ot_nvs_handle != 0), OT_ERROR_NOT_FOUND, OT_PLAT_LOG_TAG, "OT NVS handle is invalid.");
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
uint8_t unused_pos;
|
||||||
|
char ot_nvs_key[OT_KEY_INDEX_PATTERN_LEN] = { 0 };
|
||||||
|
|
||||||
|
ret = get_next_empty_index(aKey, &unused_pos);
|
||||||
|
ESP_RETURN_ON_FALSE((ret == ESP_OK), OT_ERROR_NO_BUFS, OT_PLAT_LOG_TAG, "No buffers, err: %d", ret);
|
||||||
|
snprintf(ot_nvs_key, sizeof(ot_nvs_key), OT_KEY_INDEX_PATTERN, (uint8_t)aKey, unused_pos);
|
||||||
|
ret = nvs_set_blob(s_ot_nvs_handle, ot_nvs_key, aValue, aValueLength);
|
||||||
|
ESP_RETURN_ON_FALSE((ret == ESP_OK), OT_ERROR_NO_BUFS, OT_PLAT_LOG_TAG, "No buffers, err: %d", ret);
|
||||||
|
ret = nvs_commit(s_ot_nvs_handle);
|
||||||
|
ESP_RETURN_ON_FALSE((ret == ESP_OK), OT_ERROR_NO_BUFS, OT_PLAT_LOG_TAG, "OT NVS handle shut down, err: %d", ret);
|
||||||
|
return OT_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
otError otPlatSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex)
|
||||||
|
{
|
||||||
|
ESP_RETURN_ON_FALSE((s_ot_nvs_handle != 0), OT_ERROR_NOT_FOUND, OT_PLAT_LOG_TAG, "OT NVS handle is invalid.");
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
|
||||||
|
if (aIndex == -1) {
|
||||||
|
ret = erase_all_key(aKey);
|
||||||
|
} else {
|
||||||
|
char ot_nvs_key[OT_KEY_INDEX_PATTERN_LEN] = { 0 };
|
||||||
|
ret = find_target_key_using_index(aKey, aIndex, ot_nvs_key, OT_KEY_INDEX_PATTERN_LEN);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
return OT_ERROR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
ret = nvs_erase_key(s_ot_nvs_handle, ot_nvs_key);
|
||||||
|
nvs_commit(s_ot_nvs_handle);
|
||||||
|
}
|
||||||
|
return OT_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void otPlatSettingsWipe(otInstance *aInstance)
|
||||||
|
{
|
||||||
|
nvs_erase_all(s_ot_nvs_handle);
|
||||||
|
}
|
109
components/openthread/src/port/esp_openthread_state.c
Normal file
109
components/openthread/src/port/esp_openthread_state.c
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <esp_check.h>
|
||||||
|
#include <esp_event.h>
|
||||||
|
#include <esp_log.h>
|
||||||
|
#include <esp_openthread_dns64.h>
|
||||||
|
#include <esp_openthread_netif_glue_priv.h>
|
||||||
|
#include <esp_openthread_state.h>
|
||||||
|
#include <lwip/dns.h>
|
||||||
|
|
||||||
|
#include <openthread/thread.h>
|
||||||
|
|
||||||
|
#define TAG "OT_STATE"
|
||||||
|
|
||||||
|
static void handle_ot_netif_state_change(otInstance* instance)
|
||||||
|
{
|
||||||
|
if (otLinkIsEnabled(instance)) {
|
||||||
|
ESP_LOGI(TAG, "netif up");
|
||||||
|
if (esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_IF_UP, NULL, 0, 0) != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Failed to post OpenThread if up event");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ESP_LOGI(TAG, "netif down");
|
||||||
|
if (esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_IF_DOWN, NULL, 0, 0) != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Failed to post OpenThread if down event");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_ot_netdata_change(void)
|
||||||
|
{
|
||||||
|
#if CONFIG_OPENTHREAD_DNS64_CLIENT
|
||||||
|
ip_addr_t dns_server_addr = *IP_ADDR_ANY;
|
||||||
|
if (esp_openthread_get_nat64_prefix(&dns_server_addr.u_addr.ip6) == ESP_OK) {
|
||||||
|
dns_server_addr.type = IPADDR_TYPE_V6;
|
||||||
|
dns_server_addr.u_addr.ip6.addr[3] = ipaddr_addr(CONFIG_OPENTHREAD_DNS_SERVER_ADDR);
|
||||||
|
const ip_addr_t* dnsserver = dns_getserver(OPENTHREAD_DNS_SERVER_INDEX);
|
||||||
|
if (memcmp(dnsserver, &dns_server_addr, sizeof(ip_addr_t)) != 0) {
|
||||||
|
ESP_LOGI(TAG, "Set dns server address: %s", ipaddr_ntoa(&dns_server_addr));
|
||||||
|
dns_setserver(OPENTHREAD_DNS_SERVER_INDEX, &dns_server_addr);
|
||||||
|
if (esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_SET_DNS_SERVER, NULL, 0, 0) != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Failed to post OpenThread set DNS server event");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_ot_role_change(otInstance* instance)
|
||||||
|
{
|
||||||
|
static otDeviceRole s_previous_role = OT_DEVICE_ROLE_DISABLED;
|
||||||
|
otDeviceRole role = otThreadGetDeviceRole(instance);
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
esp_openthread_role_changed_event_t event_data;
|
||||||
|
event_data.current_role = role;
|
||||||
|
event_data.previous_role = s_previous_role;
|
||||||
|
if (esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_ROLE_CHANGED, &event_data, sizeof(event_data), 0) != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Failed to post OPENTHREAD_EVENT_ROLE_CHANGED");
|
||||||
|
}
|
||||||
|
if (role == OT_DEVICE_ROLE_CHILD || role == OT_DEVICE_ROLE_ROUTER || role == OT_DEVICE_ROLE_LEADER) {
|
||||||
|
if (s_previous_role == OT_DEVICE_ROLE_DETACHED || s_previous_role == OT_DEVICE_ROLE_DISABLED) {
|
||||||
|
otOperationalDataset dataset;
|
||||||
|
ESP_GOTO_ON_FALSE(otDatasetGetActive(instance, &dataset) == OT_ERROR_NONE, ESP_FAIL, exit, TAG,
|
||||||
|
"Failed to get the active dataset");
|
||||||
|
ESP_GOTO_ON_ERROR(esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_ATTACHED, &dataset, sizeof(dataset), 0),
|
||||||
|
exit, TAG, "Failed to post OPENTHREAD_EVENT_ATTACHED. Err: %s", esp_err_to_name(ret));
|
||||||
|
}
|
||||||
|
} else if (role == OT_DEVICE_ROLE_DETACHED) {
|
||||||
|
if (s_previous_role != OT_DEVICE_ROLE_DISABLED) {
|
||||||
|
ESP_GOTO_ON_ERROR(
|
||||||
|
esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_DETACHED, &s_previous_role, sizeof(s_previous_role), 0),
|
||||||
|
exit, TAG, "Failed to post OPENTHREAD_EVENT_DETACHED. Err: %s", esp_err_to_name(ret));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exit:
|
||||||
|
s_previous_role = role;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ot_state_change_callback(otChangedFlags changed_flags, void* ctx)
|
||||||
|
{
|
||||||
|
OT_UNUSED_VARIABLE(ctx);
|
||||||
|
otInstance* instance = esp_openthread_get_instance();
|
||||||
|
if (!instance) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed_flags & OT_CHANGED_THREAD_ROLE) {
|
||||||
|
handle_ot_role_change(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed_flags & OT_CHANGED_THREAD_NETDATA) {
|
||||||
|
handle_ot_netdata_change();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed_flags & OT_CHANGED_THREAD_NETIF_STATE) {
|
||||||
|
handle_ot_netif_state_change(instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_openthread_state_event_init(otInstance* instance)
|
||||||
|
{
|
||||||
|
ESP_RETURN_ON_FALSE(otSetStateChangedCallback(instance, ot_state_change_callback, NULL) == OT_ERROR_NONE,
|
||||||
|
ESP_FAIL, TAG, "Failed to install state change callback");
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
@ -1,43 +1,5 @@
|
|||||||
menu "OpenThread Border Router Example"
|
menu "OpenThread Border Router Example"
|
||||||
|
|
||||||
config OPENTHREAD_NETWORK_NAME
|
|
||||||
string "OpenThread network name"
|
|
||||||
default "OpenThread"
|
|
||||||
help
|
|
||||||
The OpenThread network name for example to use
|
|
||||||
|
|
||||||
config OPENTHREAD_NETWORK_CHANNEL
|
|
||||||
int "OpenThread network channel"
|
|
||||||
range 11 26
|
|
||||||
default 15
|
|
||||||
help
|
|
||||||
The OpenThread network channel to use
|
|
||||||
|
|
||||||
config OPENTHREAD_NETWORK_PANID
|
|
||||||
hex "OpenThread network pan id"
|
|
||||||
range 0 0xFFFE
|
|
||||||
default 0x1234
|
|
||||||
help
|
|
||||||
The OpenThread network pan id to use
|
|
||||||
|
|
||||||
config OPENTHREAD_NETWORK_EXTPANID
|
|
||||||
string "OpenThread extended pan id"
|
|
||||||
default "dead00beef00cafe"
|
|
||||||
help
|
|
||||||
The OpenThread network extended pan id in hex string format
|
|
||||||
|
|
||||||
config OPENTHREAD_NETWORK_MASTERKEY
|
|
||||||
string "OpenThread master key"
|
|
||||||
default "00112233445566778899aabbccddeeff"
|
|
||||||
help
|
|
||||||
The OpenThread network master key in hex string format
|
|
||||||
|
|
||||||
config OPENTHREAD_NETWORK_PSKC
|
|
||||||
string "OpenThread pre-shared commissioner key"
|
|
||||||
default "104810e2315100afd6bc9215a6bfac53"
|
|
||||||
help
|
|
||||||
The OpenThread pre-shared commissioner key in hex string format
|
|
||||||
|
|
||||||
config OPENTHREAD_BR_AUTO_START
|
config OPENTHREAD_BR_AUTO_START
|
||||||
bool 'Enable the automatic start mode in Thread Border Router.'
|
bool 'Enable the automatic start mode in Thread Border Router.'
|
||||||
default False
|
default False
|
||||||
|
@ -20,8 +20,6 @@
|
|||||||
#include "esp_event.h"
|
#include "esp_event.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_netif.h"
|
#include "esp_netif.h"
|
||||||
#include "esp_netif_ip_addr.h"
|
|
||||||
#include "esp_netif_net_stack.h"
|
|
||||||
#include "esp_openthread.h"
|
#include "esp_openthread.h"
|
||||||
#include "esp_openthread_border_router.h"
|
#include "esp_openthread_border_router.h"
|
||||||
#include "esp_openthread_cli.h"
|
#include "esp_openthread_cli.h"
|
||||||
@ -43,122 +41,12 @@
|
|||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "hal/uart_types.h"
|
#include "hal/uart_types.h"
|
||||||
#include "openthread/backbone_router_ftd.h"
|
|
||||||
#include "openthread/border_router.h"
|
|
||||||
#include "openthread/cli.h"
|
|
||||||
#include "openthread/dataset.h"
|
|
||||||
#include "openthread/dataset_ftd.h"
|
|
||||||
#include "openthread/dataset_updater.h"
|
|
||||||
#include "openthread/error.h"
|
#include "openthread/error.h"
|
||||||
#include "openthread/instance.h"
|
|
||||||
#include "openthread/ip6.h"
|
|
||||||
#include "openthread/logging.h"
|
#include "openthread/logging.h"
|
||||||
#include "openthread/tasklet.h"
|
#include "openthread/tasklet.h"
|
||||||
#include "openthread/thread_ftd.h"
|
|
||||||
|
|
||||||
#define TAG "esp_ot_br"
|
#define TAG "esp_ot_br"
|
||||||
|
|
||||||
#if CONFIG_OPENTHREAD_BR_AUTO_START
|
|
||||||
static int hex_digit_to_int(char hex)
|
|
||||||
{
|
|
||||||
if ('A' <= hex && hex <= 'F') {
|
|
||||||
return 10 + hex - 'A';
|
|
||||||
}
|
|
||||||
if ('a' <= hex && hex <= 'f') {
|
|
||||||
return 10 + hex - 'a';
|
|
||||||
}
|
|
||||||
if ('0' <= hex && hex <= '9') {
|
|
||||||
return hex - '0';
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t hex_string_to_binary(const char *hex_string, uint8_t *buf, size_t buf_size)
|
|
||||||
{
|
|
||||||
int num_char = strlen(hex_string);
|
|
||||||
|
|
||||||
if (num_char != buf_size * 2) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
for (size_t i = 0; i < num_char; i += 2) {
|
|
||||||
int digit0 = hex_digit_to_int(hex_string[i]);
|
|
||||||
int digit1 = hex_digit_to_int(hex_string[i + 1]);
|
|
||||||
|
|
||||||
if (digit0 < 0 || digit1 < 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
buf[i / 2] = (digit0 << 4) + digit1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return buf_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void create_config_network(otInstance *instance)
|
|
||||||
{
|
|
||||||
otOperationalDataset dataset;
|
|
||||||
|
|
||||||
if (otDatasetGetActive(instance, &dataset) == OT_ERROR_NONE) {
|
|
||||||
ESP_LOGI(TAG, "Already has network, skip configuring OpenThread network.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t network_name_len = strlen(CONFIG_OPENTHREAD_NETWORK_NAME);
|
|
||||||
|
|
||||||
assert(network_name_len <= OT_NETWORK_NAME_MAX_SIZE);
|
|
||||||
|
|
||||||
if (otDatasetCreateNewNetwork(instance, &dataset) != OT_ERROR_NONE) {
|
|
||||||
ESP_LOGE(TAG, "Failed to create OpenThread network dataset.");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
dataset.mChannel = CONFIG_OPENTHREAD_NETWORK_CHANNEL;
|
|
||||||
dataset.mComponents.mIsChannelPresent = true;
|
|
||||||
dataset.mPanId = CONFIG_OPENTHREAD_NETWORK_PANID;
|
|
||||||
dataset.mComponents.mIsPanIdPresent = true;
|
|
||||||
memcpy(dataset.mNetworkName.m8, CONFIG_OPENTHREAD_NETWORK_NAME, network_name_len);
|
|
||||||
dataset.mComponents.mIsNetworkNamePresent = true;
|
|
||||||
if (hex_string_to_binary(CONFIG_OPENTHREAD_NETWORK_EXTPANID, dataset.mExtendedPanId.m8,
|
|
||||||
sizeof(dataset.mExtendedPanId.m8)) != sizeof(dataset.mExtendedPanId.m8)) {
|
|
||||||
ESP_LOGE(TAG, "Cannot convert OpenThread extended pan id. Please double-check your config.");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
dataset.mComponents.mIsExtendedPanIdPresent = true;
|
|
||||||
if (hex_string_to_binary(CONFIG_OPENTHREAD_NETWORK_MASTERKEY, dataset.mNetworkKey.m8,
|
|
||||||
sizeof(dataset.mNetworkKey.m8)) != sizeof(dataset.mNetworkKey.m8)) {
|
|
||||||
ESP_LOGE(TAG, "Cannot convert OpenThread master key. Please double-check your config.");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
dataset.mComponents.mIsNetworkKeyPresent = true;
|
|
||||||
if (hex_string_to_binary(CONFIG_OPENTHREAD_NETWORK_PSKC, dataset.mPskc.m8, sizeof(dataset.mPskc.m8)) !=
|
|
||||||
sizeof(dataset.mPskc.m8)) {
|
|
||||||
ESP_LOGE(TAG, "Cannot convert OpenThread pre-shared commissioner key. Please double-check your config.");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
dataset.mComponents.mIsPskcPresent = true;
|
|
||||||
if (otDatasetSetActive(instance, &dataset) != OT_ERROR_NONE) {
|
|
||||||
ESP_LOGE(TAG, "Failed to set OpenThread active dataset.");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void launch_openthread_network(otInstance *instance)
|
|
||||||
{
|
|
||||||
if (otIp6SetEnabled(instance, true) != OT_ERROR_NONE) {
|
|
||||||
ESP_LOGE(TAG, "Failed to enable OpenThread IP6 link");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
if (otThreadSetEnabled(instance, true) != OT_ERROR_NONE) {
|
|
||||||
ESP_LOGE(TAG, "Failed to enable OpenThread");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
if (otBorderRouterRegister(instance) != OT_ERROR_NONE) {
|
|
||||||
ESP_LOGE(TAG, "Failed to register border router.");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
otBackboneRouterSetEnabled(instance, true);
|
|
||||||
}
|
|
||||||
#endif // CONFIG_OPENTHREAD_BR_AUTO_START
|
|
||||||
|
|
||||||
static void ot_task_worker(void *aContext)
|
static void ot_task_worker(void *aContext)
|
||||||
{
|
{
|
||||||
esp_openthread_platform_config_t config = {
|
esp_openthread_platform_config_t config = {
|
||||||
@ -170,8 +58,8 @@ static void ot_task_worker(void *aContext)
|
|||||||
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_OPENTHREAD();
|
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_OPENTHREAD();
|
||||||
esp_netif_t *openthread_netif = esp_netif_new(&cfg);
|
esp_netif_t *openthread_netif = esp_netif_new(&cfg);
|
||||||
assert(openthread_netif != NULL);
|
assert(openthread_netif != NULL);
|
||||||
// Initialize the OpenThread stack
|
|
||||||
|
|
||||||
|
// Initialize the OpenThread stack
|
||||||
ESP_ERROR_CHECK(esp_openthread_init(&config));
|
ESP_ERROR_CHECK(esp_openthread_init(&config));
|
||||||
|
|
||||||
// Initialize border routing features
|
// Initialize border routing features
|
||||||
@ -180,11 +68,12 @@ static void ot_task_worker(void *aContext)
|
|||||||
|
|
||||||
(void)otLoggingSetLevel(CONFIG_LOG_DEFAULT_LEVEL);
|
(void)otLoggingSetLevel(CONFIG_LOG_DEFAULT_LEVEL);
|
||||||
esp_openthread_cli_init();
|
esp_openthread_cli_init();
|
||||||
|
|
||||||
#if CONFIG_OPENTHREAD_BR_AUTO_START
|
#if CONFIG_OPENTHREAD_BR_AUTO_START
|
||||||
ESP_ERROR_CHECK(esp_openthread_border_router_init());
|
ESP_ERROR_CHECK(esp_openthread_border_router_init());
|
||||||
create_config_network(esp_openthread_get_instance());
|
ESP_ERROR_CHECK(esp_openthread_auto_start(NULL));
|
||||||
launch_openthread_network(esp_openthread_get_instance());
|
|
||||||
#endif // CONFIG_OPENTHREAD_BR_AUTO_START
|
#endif // CONFIG_OPENTHREAD_BR_AUTO_START
|
||||||
|
|
||||||
esp_cli_custom_command_init();
|
esp_cli_custom_command_init();
|
||||||
esp_openthread_lock_release();
|
esp_openthread_lock_release();
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@
|
|||||||
|
|
||||||
#define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \
|
#define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \
|
||||||
{ \
|
{ \
|
||||||
.storage_partition_name = "ot_storage", \
|
.storage_partition_name = "nvs", \
|
||||||
.netif_queue_size = 10, \
|
.netif_queue_size = 10, \
|
||||||
.task_queue_size = 10, \
|
.task_queue_size = 10, \
|
||||||
}
|
}
|
||||||
|
@ -3,4 +3,3 @@
|
|||||||
nvs, data, nvs, 0x9000, 0x6000,
|
nvs, data, nvs, 0x9000, 0x6000,
|
||||||
phy_init, data, phy, 0xf000, 0x1000,
|
phy_init, data, phy, 0xf000, 0x1000,
|
||||||
factory, app, factory, 0x10000, 1600K,
|
factory, app, factory, 0x10000, 1600K,
|
||||||
ot_storage, data, 0x3a, , 0x2000,
|
|
||||||
|
|
@ -43,6 +43,7 @@ CONFIG_LWIP_NETIF_STATUS_CALLBACK=y
|
|||||||
CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT=y
|
CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT=y
|
||||||
CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT=y
|
CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT=y
|
||||||
CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM=y
|
CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM=y
|
||||||
|
CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_CUSTOM=y
|
||||||
CONFIG_LWIP_IPV6_AUTOCONFIG=y
|
CONFIG_LWIP_IPV6_AUTOCONFIG=y
|
||||||
# end of lwIP
|
# end of lwIP
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@
|
|||||||
|
|
||||||
#define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \
|
#define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \
|
||||||
{ \
|
{ \
|
||||||
.storage_partition_name = "ot_storage", \
|
.storage_partition_name = "nvs", \
|
||||||
.netif_queue_size = 10, \
|
.netif_queue_size = 10, \
|
||||||
.task_queue_size = 10, \
|
.task_queue_size = 10, \
|
||||||
}
|
}
|
||||||
|
@ -3,4 +3,3 @@
|
|||||||
nvs, data, nvs, 0x9000, 0x6000,
|
nvs, data, nvs, 0x9000, 0x6000,
|
||||||
phy_init, data, phy, 0xf000, 0x1000,
|
phy_init, data, phy, 0xf000, 0x1000,
|
||||||
factory, app, factory, 0x10000, 0x120000,
|
factory, app, factory, 0x10000, 0x120000,
|
||||||
ot_storage, data, 0x3a, , 0x2000,
|
|
||||||
|
|
@ -4,8 +4,6 @@
|
|||||||
CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y
|
CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y
|
||||||
# end of libsodium
|
# end of libsodium
|
||||||
|
|
||||||
CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=2048
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Partition Table
|
# Partition Table
|
||||||
#
|
#
|
||||||
@ -19,10 +17,6 @@ CONFIG_PARTITION_TABLE_MD5=y
|
|||||||
#
|
#
|
||||||
# mbedTLS
|
# mbedTLS
|
||||||
#
|
#
|
||||||
# ESP32H2-TODO: enable HW acceleration
|
|
||||||
CONFIG_MBEDTLS_HARDWARE_AES=n
|
|
||||||
CONFIG_MBEDTLS_HARDWARE_MPI=n
|
|
||||||
CONFIG_MBEDTLS_HARDWARE_SHA=n
|
|
||||||
CONFIG_MBEDTLS_CMAC_C=y
|
CONFIG_MBEDTLS_CMAC_C=y
|
||||||
CONFIG_MBEDTLS_SSL_PROTO_DTLS=y
|
CONFIG_MBEDTLS_SSL_PROTO_DTLS=y
|
||||||
CONFIG_MBEDTLS_KEY_EXCHANGE_ECJPAKE=y
|
CONFIG_MBEDTLS_KEY_EXCHANGE_ECJPAKE=y
|
||||||
@ -43,6 +37,7 @@ CONFIG_OPENTHREAD_DNS64_CLIENT=y
|
|||||||
CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=4096
|
CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=4096
|
||||||
CONFIG_LWIP_IPV6_NUM_ADDRESSES=8
|
CONFIG_LWIP_IPV6_NUM_ADDRESSES=8
|
||||||
CONFIG_LWIP_MULTICAST_PING=y
|
CONFIG_LWIP_MULTICAST_PING=y
|
||||||
|
CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_CUSTOM=y
|
||||||
# end of lwIP
|
# end of lwIP
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -75,7 +75,7 @@
|
|||||||
|
|
||||||
#define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \
|
#define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \
|
||||||
{ \
|
{ \
|
||||||
.storage_partition_name = "ot_storage", \
|
.storage_partition_name = "nvs", \
|
||||||
.netif_queue_size = 10, \
|
.netif_queue_size = 10, \
|
||||||
.task_queue_size = 10, \
|
.task_queue_size = 10, \
|
||||||
}
|
}
|
||||||
|
@ -3,4 +3,3 @@
|
|||||||
nvs, data, nvs, 0x9000, 0x6000,
|
nvs, data, nvs, 0x9000, 0x6000,
|
||||||
phy_init, data, phy, , 0x1000,
|
phy_init, data, phy, , 0x1000,
|
||||||
factory, app, factory, 0x10000, 1M,
|
factory, app, factory, 0x10000, 1M,
|
||||||
ot_storage, data, 0x3a, , 0x2000,
|
|
||||||
|
|
@ -14,18 +14,6 @@ CONFIG_PARTITION_TABLE_OFFSET=0x8000
|
|||||||
CONFIG_PARTITION_TABLE_MD5=y
|
CONFIG_PARTITION_TABLE_MD5=y
|
||||||
# end of Partition Table
|
# end of Partition Table
|
||||||
|
|
||||||
#
|
|
||||||
# mbedTLS
|
|
||||||
#
|
|
||||||
|
|
||||||
CONFIG_MBEDTLS_CMAC_C=y
|
|
||||||
CONFIG_MBEDTLS_SSL_PROTO_DTLS=y
|
|
||||||
CONFIG_MBEDTLS_KEY_EXCHANGE_ECJPAKE=y
|
|
||||||
# end of TLS Key Exchange Methods
|
|
||||||
|
|
||||||
CONFIG_MBEDTLS_ECJPAKE_C=y
|
|
||||||
# end of mbedTLS
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# OpenThread
|
# OpenThread
|
||||||
#
|
#
|
||||||
|
Loading…
Reference in New Issue
Block a user