2022-12-26 02:48:07 -05:00
|
|
|
/*
|
|
|
|
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "esp_openthread_platform.h"
|
|
|
|
|
|
|
|
#include "esp_check.h"
|
|
|
|
#include "esp_err.h"
|
|
|
|
#include "esp_log.h"
|
|
|
|
#include "esp_openthread_alarm.h"
|
|
|
|
#include "esp_openthread_common_macro.h"
|
|
|
|
#include "esp_openthread_flash.h"
|
|
|
|
#include "esp_openthread_lock.h"
|
|
|
|
#include "esp_openthread_radio.h"
|
2022-11-16 03:59:57 -05:00
|
|
|
#include "esp_openthread_spi_slave.h"
|
2022-12-26 02:48:07 -05:00
|
|
|
#include "esp_openthread_task_queue.h"
|
|
|
|
#include "esp_openthread_types.h"
|
|
|
|
#include "esp_openthread_uart.h"
|
|
|
|
#include "esp_partition.h"
|
|
|
|
#include "common/code_utils.hpp"
|
|
|
|
#include "common/logging.hpp"
|
|
|
|
#include "core/common/instance.hpp"
|
|
|
|
#include "freertos/FreeRTOS.h"
|
|
|
|
#include "freertos/queue.h"
|
|
|
|
#include "openthread/cli.h"
|
|
|
|
#include "openthread/instance.h"
|
|
|
|
#include "openthread/tasklet.h"
|
|
|
|
|
|
|
|
static esp_openthread_platform_config_t s_platform_config;
|
|
|
|
static bool s_openthread_platform_initialized = false;
|
|
|
|
static esp_openthread_platform_workflow_t *s_workflow_list = NULL;
|
|
|
|
|
|
|
|
esp_err_t esp_openthread_platform_workflow_register(esp_openthread_update_func update_func,
|
|
|
|
esp_openthread_process_func process_func, const char *name)
|
|
|
|
{
|
|
|
|
uint8_t name_len = strnlen(name, WORKFLOW_MAX_NAMELEN);
|
|
|
|
esp_openthread_platform_workflow_t *current_workflow = s_workflow_list;
|
|
|
|
esp_openthread_platform_workflow_t *before_workflow = NULL;
|
|
|
|
esp_openthread_platform_workflow_t *add_workflow =
|
|
|
|
static_cast<esp_openthread_platform_workflow_t *>(malloc(sizeof(esp_openthread_platform_workflow_t)));
|
|
|
|
ESP_RETURN_ON_FALSE(add_workflow != NULL, ESP_ERR_NO_MEM, OT_PLAT_LOG_TAG,
|
|
|
|
"Failed to alloc memory for esp_openthread_workflow");
|
|
|
|
strncpy(add_workflow->name, name, name_len);
|
|
|
|
add_workflow->update_func = update_func;
|
|
|
|
add_workflow->process_func = process_func;
|
|
|
|
add_workflow->next = NULL;
|
|
|
|
while (current_workflow) {
|
|
|
|
if (strncmp(current_workflow->name, name, name_len) == 0) {
|
|
|
|
free(add_workflow);
|
|
|
|
add_workflow = NULL; // handle has be added in the list.
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
before_workflow = current_workflow;
|
|
|
|
current_workflow = current_workflow->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (add_workflow) {
|
|
|
|
if (before_workflow) {
|
|
|
|
before_workflow->next = add_workflow; // Add handle to the list end
|
|
|
|
} else {
|
|
|
|
s_workflow_list = add_workflow; // No handle in the list
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ESP_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void esp_openthread_platform_workflow_unregister(const char *name)
|
|
|
|
{
|
|
|
|
esp_openthread_platform_workflow_t *current_workflow = s_workflow_list;
|
|
|
|
esp_openthread_platform_workflow_t *before_workflow = NULL;
|
|
|
|
while (current_workflow) {
|
|
|
|
if (strncmp(current_workflow->name, name, strnlen(name, WORKFLOW_MAX_NAMELEN)) == 0) {
|
|
|
|
if (before_workflow) {
|
|
|
|
before_workflow->next = current_workflow->next;
|
|
|
|
} else {
|
|
|
|
s_workflow_list = current_workflow->next;
|
|
|
|
}
|
|
|
|
free(current_workflow);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
before_workflow = current_workflow;
|
|
|
|
current_workflow = current_workflow->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
esp_err_t esp_openthread_platform_init(const esp_openthread_platform_config_t *config)
|
|
|
|
{
|
|
|
|
ESP_RETURN_ON_FALSE(config->radio_config.radio_mode == RADIO_MODE_NATIVE ||
|
2022-11-16 03:59:57 -05:00
|
|
|
config->radio_config.radio_mode == RADIO_MODE_UART_RCP ||
|
|
|
|
config->radio_config.radio_mode == RADIO_MODE_SPI_RCP,
|
2022-12-26 02:48:07 -05:00
|
|
|
ESP_ERR_INVALID_ARG, OT_PLAT_LOG_TAG, "Radio mode not supported");
|
|
|
|
ESP_RETURN_ON_FALSE(config->host_config.host_connection_mode == HOST_CONNECTION_MODE_NONE ||
|
|
|
|
config->host_config.host_connection_mode == HOST_CONNECTION_MODE_CLI_UART ||
|
2022-11-16 03:59:57 -05:00
|
|
|
config->host_config.host_connection_mode == HOST_CONNECTION_MODE_RCP_UART ||
|
|
|
|
config->host_config.host_connection_mode == HOST_CONNECTION_MODE_RCP_SPI,
|
2022-12-26 02:48:07 -05:00
|
|
|
ESP_ERR_INVALID_ARG, OT_PLAT_LOG_TAG, "Host connection mode not supported");
|
|
|
|
ESP_RETURN_ON_FALSE(!s_openthread_platform_initialized, ESP_ERR_INVALID_STATE, OT_PLAT_LOG_TAG,
|
|
|
|
"OpenThread platform already initialized");
|
|
|
|
|
|
|
|
s_openthread_platform_initialized = true;
|
|
|
|
esp_err_t ret = ESP_OK;
|
2022-11-16 03:59:57 -05:00
|
|
|
|
|
|
|
/* Avoid to compile flash in RADIO type device */
|
|
|
|
#if !CONFIG_OPENTHREAD_RADIO
|
2022-12-26 02:48:07 -05:00
|
|
|
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");
|
2022-11-16 03:59:57 -05:00
|
|
|
esp_openthread_flash_set_partition(partition);
|
|
|
|
#endif
|
2022-12-26 02:48:07 -05:00
|
|
|
|
|
|
|
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_alarm_init(), exit, OT_PLAT_LOG_TAG, "esp_openthread_alarm_init failed");
|
2022-11-16 03:59:57 -05:00
|
|
|
|
|
|
|
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_openthread_spi_slave_init failed");
|
|
|
|
}else if (config->host_config.host_connection_mode == HOST_CONNECTION_MODE_CLI_UART ||
|
2022-12-26 02:48:07 -05:00
|
|
|
config->host_config.host_connection_mode == HOST_CONNECTION_MODE_RCP_UART) {
|
|
|
|
ESP_GOTO_ON_ERROR(esp_openthread_uart_init(config), exit, OT_PLAT_LOG_TAG, "esp_openthread_uart_init failed");
|
|
|
|
}
|
2022-11-16 03:59:57 -05:00
|
|
|
|
2022-12-26 02:48:07 -05:00
|
|
|
ESP_GOTO_ON_ERROR(esp_openthread_task_queue_init(config), exit, OT_PLAT_LOG_TAG,
|
|
|
|
"esp_openthread_task_queue_init failed");
|
|
|
|
ESP_GOTO_ON_ERROR(esp_openthread_radio_init(config), exit, OT_PLAT_LOG_TAG, "esp_openthread_radio_init failed");
|
|
|
|
|
|
|
|
exit:
|
|
|
|
if (ret != ESP_OK) {
|
|
|
|
esp_openthread_platform_deinit();
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
otInstance *esp_openthread_get_instance(void)
|
|
|
|
{
|
|
|
|
return (otInstance *)&ot::Instance::Get();
|
|
|
|
}
|
|
|
|
|
|
|
|
esp_err_t esp_openthread_platform_deinit(void)
|
|
|
|
{
|
|
|
|
ESP_RETURN_ON_FALSE(s_openthread_platform_initialized, ESP_ERR_INVALID_STATE, OT_PLAT_LOG_TAG,
|
|
|
|
"OpenThread platform not initialized");
|
|
|
|
s_openthread_platform_initialized = false;
|
|
|
|
esp_openthread_task_queue_deinit();
|
|
|
|
esp_openthread_radio_deinit();
|
2022-11-16 03:59:57 -05:00
|
|
|
|
|
|
|
if (s_platform_config.host_config.host_connection_mode == HOST_CONNECTION_MODE_RCP_SPI){
|
|
|
|
esp_openthread_spi_slave_deinit();
|
|
|
|
}else if (s_platform_config.host_config.host_connection_mode == HOST_CONNECTION_MODE_CLI_UART ||
|
|
|
|
s_platform_config.host_config.host_connection_mode == HOST_CONNECTION_MODE_RCP_UART) {
|
2022-12-26 02:48:07 -05:00
|
|
|
esp_openthread_uart_deinit();
|
|
|
|
}
|
2022-11-16 03:59:57 -05:00
|
|
|
|
2022-12-26 02:48:07 -05:00
|
|
|
esp_openthread_lock_deinit();
|
|
|
|
esp_openthread_alarm_deinit();
|
|
|
|
return ESP_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void esp_openthread_platform_update(esp_openthread_mainloop_context_t *mainloop)
|
|
|
|
{
|
|
|
|
esp_openthread_platform_workflow_t *current_workflow = s_workflow_list;
|
|
|
|
while (current_workflow) {
|
|
|
|
current_workflow->update_func(mainloop);
|
|
|
|
current_workflow = current_workflow->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
esp_err_t esp_openthread_platform_process(otInstance *instance, const esp_openthread_mainloop_context_t *mainloop)
|
|
|
|
{
|
|
|
|
esp_openthread_platform_workflow_t *current_workflow = s_workflow_list;
|
|
|
|
while (current_workflow) {
|
|
|
|
ESP_RETURN_ON_ERROR(current_workflow->process_func(instance, mainloop), OT_PLAT_LOG_TAG, "process %s failed",
|
|
|
|
current_workflow->name);
|
|
|
|
current_workflow = current_workflow->next;
|
|
|
|
}
|
|
|
|
return ESP_OK;
|
|
|
|
}
|