Fork fix: the SDIO wedge is FIXED (esp-hosted-mcu #167)
Root cause (verified against our exact IDF tree, not the community guess): the "258" in "sdio_write_task: Failed to send data: 258" is NOT a timeout (that is 263). 258 = 0x102 = ESP_ERR_INVALID_ARG. On the ESP32-P4, block- mode CMD53 writes require the SOURCE buffer to be 64-byte (cache-line) aligned; the IDF sdmmc driver rejects a misaligned source with INVALID_ARG BEFORE any bus activity. esp_hosts write loop then declares "Unrecoverable host sdio state" and reboots the whole P4. The audio TX payload is not 64-aligned, so streaming mic audio wedged on the very FIRST frame (which is exactly what we saw: listening -> instant Failed to send -> reboot). This also explains why buffer/queue/clock/retry tuning all did nothing: the write never reached the bus. And why our symptom was instant, not after ~100 writes (the community block-mode-desync theory) — it is the first misaligned buffer, every time. Fix: vendored esp_hosted 2.12.11 as an editable local component (overrides the registry copy) and bounce a misaligned TX payload through one aligned DMA scratch buffer in hosted_sdio_write_block (port_esp_hosted_host_sdio.c). TX is serialized by the bus lock so a single static bounce buffer is safe; freed in hosted_sdio_deinit. Host-only change — no C6 reflash. VERIFIED ON HARDWARE (autonomous self-test): 40s of continuous mic-audio upstream streaming — the traffic that previously wedged on the first frame — ran clean, zero timeouts, zero reboots. A guarded SDIO_TX_SELFTEST harness is kept (compiled out) for future SDIO stress testing. Credit: root cause + patch designed via multi-agent investigation; the precise 258=INVALID_ARG decode (correcting the upstream community timeout assumption) came from checking our actual esp_err.h. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/** prevent recursive inclusion **/
|
||||
#ifndef __ESP_HOSTED_API_TYPES_H__
|
||||
#define __ESP_HOSTED_API_TYPES_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint32_t major1;
|
||||
uint32_t minor1;
|
||||
uint32_t patch1;
|
||||
int32_t revision;
|
||||
int32_t prerelease;
|
||||
int32_t build;
|
||||
} esp_hosted_coprocessor_fwver_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file esp_hosted_cp_ext_coex.h
|
||||
* @brief External Coexistence API for ESP-Hosted Co-Processor
|
||||
*
|
||||
* Platform-agnostic APIs to configure external coexistence GPIO pins on
|
||||
* the ESP-Hosted co-processor from the host MCU. Also compatible with non-ESP
|
||||
* hosts (e.g. STM32, nRF) that do not use ESP-IDF.
|
||||
*/
|
||||
|
||||
#ifndef __ESP_HOSTED_CP_EXT_COEX_H__
|
||||
#define __ESP_HOSTED_CP_EXT_COEX_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_HOSTED_EXT_COEX_WIRE_1 0
|
||||
#define ESP_HOSTED_EXT_COEX_WIRE_2 1
|
||||
#define ESP_HOSTED_EXT_COEX_WIRE_3 2
|
||||
#define ESP_HOSTED_EXT_COEX_WIRE_4 3
|
||||
|
||||
typedef enum {
|
||||
ESP_HOSTED_EXT_COEX_LEADER_ROLE = 0,
|
||||
ESP_HOSTED_EXT_COEX_FOLLOWER_ROLE = 2,
|
||||
ESP_HOSTED_EXT_COEX_UNKNOWN_ROLE,
|
||||
} esp_hosted_ext_coex_work_mode_t;
|
||||
|
||||
typedef struct {
|
||||
int32_t request;
|
||||
int32_t priority;
|
||||
int32_t grant;
|
||||
int32_t tx_line;
|
||||
} esp_hosted_ext_coex_gpio_set_t;
|
||||
|
||||
#if defined(CONFIG_ESP_HOSTED_CP_EXT_COEX) && CONFIG_ESP_HOSTED_CP_EXT_COEX
|
||||
|
||||
/**
|
||||
* @brief Host-side API to set the work mode for external coexistence
|
||||
* on the co-processor connected to the host.
|
||||
*
|
||||
* @param work_mode Work mode to be set
|
||||
*
|
||||
* @return ESP_OK on success, otherwise an error code
|
||||
*/
|
||||
esp_err_t esp_hosted_cp_ext_coex_set_work_mode(esp_hosted_ext_coex_work_mode_t work_mode);
|
||||
|
||||
/**
|
||||
* @brief Host-side API to configure GPIO pins for external coexistence
|
||||
* on the co-processor connected to the host.
|
||||
*
|
||||
* @param wire_type Wire type for which the GPIO pins are configured
|
||||
* @param gpio_pins GPIO pin configuration to be set
|
||||
*
|
||||
* @return ESP_OK on success, otherwise an error code
|
||||
*/
|
||||
esp_err_t esp_hosted_cp_ext_coex_set_gpio_pin(uint32_t wire_type,
|
||||
const esp_hosted_ext_coex_gpio_set_t *gpio_pins);
|
||||
|
||||
#if defined(CONFIG_ESP_HOSTED_CP_EXT_COEX_ADVANCE) && CONFIG_ESP_HOSTED_CP_EXT_COEX_ADVANCE
|
||||
/**
|
||||
* @brief Host-side API to set the grant delay for external coexistence
|
||||
* on the co-processor connected to the host.
|
||||
*
|
||||
* @param delay_us Grant delay to be set
|
||||
*
|
||||
* @return ESP_OK on success, otherwise an error code
|
||||
*/
|
||||
esp_err_t esp_hosted_cp_ext_coex_set_grant_delay(uint8_t delay_us);
|
||||
|
||||
/**
|
||||
* @brief Host-side API to set the validate high for external coexistence
|
||||
* on the co-processor connected to the host.
|
||||
*
|
||||
* @param is_high_valid Validate high to be set
|
||||
*
|
||||
* @return ESP_OK on success, otherwise an error code
|
||||
*/
|
||||
esp_err_t esp_hosted_cp_ext_coex_set_validate_high(bool is_high_valid);
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Host-side API to disable external coexistence
|
||||
* on the co-processor connected to the host.
|
||||
*
|
||||
* @return ESP_OK on success, otherwise an error code
|
||||
*/
|
||||
esp_err_t esp_hosted_cp_ext_coex_disable(void);
|
||||
|
||||
#endif /* CONFIG_ESP_HOSTED_CP_EXT_COEX */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ESP_HOSTED_CP_EXT_COEX_H__ */
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __ESP_HOSTED_CP_GPIO_H__
|
||||
#define __ESP_HOSTED_CP_GPIO_H__
|
||||
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t pin_bit_mask; /*!< GPIO pin: set with bit mask, each bit maps to a GPIO */
|
||||
uint32_t mode; /*!< GPIO mode: set input/output mode */
|
||||
uint32_t pull_up_en; /*!< GPIO pull-up */
|
||||
uint32_t pull_down_en; /*!< GPIO pull-down */
|
||||
uint32_t intr_type; /*!< GPIO interrupt type */
|
||||
} esp_hosted_cp_gpio_config_t;
|
||||
|
||||
#define H_BIT0 (1ULL << 0)
|
||||
#define H_BIT1 (1ULL << 1)
|
||||
#define H_BIT2 (1ULL << 2)
|
||||
|
||||
#define H_CP_GPIO_MODE_DEF_DISABLE (0)
|
||||
#define H_CP_GPIO_MODE_DEF_INPUT (H_BIT0) ///< bit mask for input
|
||||
#define H_CP_GPIO_MODE_DEF_OUTPUT (H_BIT1) ///< bit mask for output
|
||||
#define H_CP_GPIO_MODE_DEF_OD (H_BIT2) ///< bit mask for OD mode
|
||||
|
||||
enum {
|
||||
H_CP_GPIO_MODE_DISABLE = H_CP_GPIO_MODE_DEF_DISABLE, /*!< GPIO mode : disable input and output */
|
||||
H_CP_GPIO_MODE_INPUT = H_CP_GPIO_MODE_DEF_INPUT, /*!< GPIO mode : input only */
|
||||
H_CP_GPIO_MODE_OUTPUT = H_CP_GPIO_MODE_DEF_OUTPUT, /*!< GPIO mode : output only mode */
|
||||
H_CP_GPIO_MODE_OUTPUT_OD = ((H_CP_GPIO_MODE_DEF_OUTPUT) | (H_CP_GPIO_MODE_DEF_OD)), /*!< GPIO mode : output only with open-drain mode */
|
||||
H_CP_GPIO_MODE_INPUT_OUTPUT_OD = ((H_CP_GPIO_MODE_DEF_INPUT) | (H_CP_GPIO_MODE_DEF_OUTPUT) | (H_CP_GPIO_MODE_DEF_OD)), /*!< GPIO mode : output and input with open-drain mode*/
|
||||
H_CP_GPIO_MODE_INPUT_OUTPUT = ((H_CP_GPIO_MODE_DEF_INPUT) | (H_CP_GPIO_MODE_DEF_OUTPUT)), /*!< GPIO mode : output and input mode */
|
||||
};
|
||||
|
||||
#define H_CP_GPIO_PULL_UP (1)
|
||||
#define H_CP_GPIO_PULL_DOWN (0)
|
||||
|
||||
esp_err_t esp_hosted_cp_gpio_config(const esp_hosted_cp_gpio_config_t *pGPIOConfig);
|
||||
esp_err_t esp_hosted_cp_gpio_reset_pin(uint32_t gpio_num);
|
||||
esp_err_t esp_hosted_cp_gpio_set_level(uint32_t gpio_num, uint32_t level);
|
||||
esp_err_t esp_hosted_cp_gpio_get_level(uint32_t gpio_num, int *level);
|
||||
esp_err_t esp_hosted_cp_gpio_set_direction(uint32_t gpio_num, uint32_t mode);
|
||||
esp_err_t esp_hosted_cp_gpio_input_enable(uint32_t gpio_num);
|
||||
esp_err_t esp_hosted_cp_gpio_set_pull_mode(uint32_t gpio_num, uint32_t pull_mode);
|
||||
|
||||
#endif /*__ESP_HOSTED_CP_GPIO_H__*/
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __ESP_HOSTED_OPENTHREAD_H__
|
||||
#define __ESP_HOSTED_OPENTHREAD_H__
|
||||
|
||||
typedef enum {
|
||||
HOSTED_OPENTHREAD_TRANSPORT_UART,
|
||||
HOSTED_OPENTHREAD_TRANSPORT_MAX,
|
||||
} esp_hosted_openthread_radio_transport_t;
|
||||
|
||||
typedef enum {
|
||||
HOSTED_OPENTHREAD_QUERY_CONFIGURED,
|
||||
HOSTED_OPENTHREAD_QUERY_INITED,
|
||||
HOSTED_OPENTHREAD_QUERY_ENABLED,
|
||||
HOSTED_OPENTHREAD_QUERY_READY,
|
||||
} esp_hosted_openthread_query_t;
|
||||
|
||||
typedef struct {
|
||||
int port;
|
||||
int baud_rate;
|
||||
int data_bits;
|
||||
int parity;
|
||||
int stop_bits;
|
||||
int flow_ctrl;
|
||||
int rx_flow_ctrl_thresh;
|
||||
int source_clk;
|
||||
int rx_pin;
|
||||
int tx_pin;
|
||||
} esp_hosted_openthread_uart_config_t;
|
||||
|
||||
typedef struct {
|
||||
esp_hosted_openthread_radio_transport_t type;
|
||||
union {
|
||||
esp_hosted_openthread_uart_config_t radio_uart_config;
|
||||
};
|
||||
} esp_hosted_openthread_radio_config_t;
|
||||
|
||||
/**
|
||||
* @brief Gets the current Hosted OpenThread Radio Config
|
||||
*
|
||||
* Caller responsible for filling OT implementation dependent radio configuration
|
||||
* from the returned info
|
||||
*
|
||||
* @param config ESP-Hosted Radio Config
|
||||
*
|
||||
* @return 0 on success
|
||||
*/
|
||||
int esp_hosted_openthread_get_radio_config(esp_hosted_openthread_radio_config_t *config);
|
||||
|
||||
int esp_hosted_openthread_rcp_init(void);
|
||||
int esp_hosted_openthread_rcp_deinit(void);
|
||||
int esp_hosted_openthread_rcp_start(void);
|
||||
int esp_hosted_openthread_rcp_stop(void);
|
||||
|
||||
// query the RCP on its state: configured, inited, enabled or ready
|
||||
int esp_hosted_openthread_rcp_query(esp_hosted_openthread_query_t query);
|
||||
#endif
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* APIs to do OTA updates of the co-processor
|
||||
*
|
||||
* Note: This API is platform dependent
|
||||
*
|
||||
* Add additional APIs as required based on how the OTA binary is to
|
||||
* be fetched.
|
||||
*
|
||||
* Source for the API should be in host/port/<platform>/...
|
||||
*
|
||||
* Procedure used by APIs to do OTA update:
|
||||
* 1. Fetch and prepare OTA binary
|
||||
* 2. Call rpc_ota_begin() to start OTA
|
||||
* 3. Repeatedly call rpc_ota_write() with a continuous chunk of OTA data
|
||||
* 4. Call rpc_ota_end()
|
||||
*
|
||||
* @deprecated This API is deprecated. Use the new OTA examples in examples/host_slave_ota/
|
||||
* and examples/host_self_ota/ which provide more flexible OTA implementations.
|
||||
* These examples demonstrate how to use the low-level esp_hosted_ota_begin(),
|
||||
* esp_hosted_ota_write(), and esp_hosted_ota_end() APIs directly.
|
||||
*/
|
||||
|
||||
#ifndef __ESP_HOSTED_OTA_H__
|
||||
#define __ESP_HOSTED_OTA_H__
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
enum {
|
||||
ESP_HOSTED_SLAVE_OTA_ACTIVATED,
|
||||
ESP_HOSTED_SLAVE_OTA_COMPLETED,
|
||||
ESP_HOSTED_SLAVE_OTA_NOT_REQUIRED,
|
||||
ESP_HOSTED_SLAVE_OTA_NOT_STARTED,
|
||||
ESP_HOSTED_SLAVE_OTA_IN_PROGRESS,
|
||||
ESP_HOSTED_SLAVE_OTA_FAILED,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Fetch OTA image from a web server (image_url)
|
||||
* @deprecated Use the examples in examples/host_slave_ota/ for new implementations
|
||||
* @param image_url URL of the OTA image
|
||||
* @return esp_err_t ESP_OK on success, error code on failure
|
||||
*/
|
||||
esp_err_t esp_hosted_slave_ota(const char* image_url) __attribute__((deprecated("Use examples/host_slave_ota/ for new OTA implementations")));
|
||||
|
||||
/* --------- OTA APIs --------- */
|
||||
/**
|
||||
* @brief Begin OTA update on the remote coprocessor device
|
||||
*
|
||||
* @return esp_err_t ESP_OK on success, error code on failure
|
||||
*/
|
||||
esp_err_t esp_hosted_slave_ota_begin(void);
|
||||
|
||||
/**
|
||||
* @brief Write OTA data chunk to the remote coprocessor device
|
||||
*
|
||||
* @param ota_data Pointer to OTA data chunk
|
||||
* @param ota_data_len Length of OTA data chunk
|
||||
* @return esp_err_t ESP_OK on success, error code on failure
|
||||
*/
|
||||
esp_err_t esp_hosted_slave_ota_write(uint8_t* ota_data, uint32_t ota_data_len);
|
||||
|
||||
/**
|
||||
* @brief End OTA update on the remote coprocessor device
|
||||
*
|
||||
* @return esp_err_t ESP_OK on success, error code on failure
|
||||
*/
|
||||
esp_err_t esp_hosted_slave_ota_end(void);
|
||||
|
||||
/**
|
||||
* @brief Activate OTA update on the remote coprocessor device. This would also reboot the remote coprocessor.
|
||||
*
|
||||
* @return esp_err_t ESP_OK on success, error code on failure
|
||||
*/
|
||||
esp_err_t esp_hosted_slave_ota_activate(void);
|
||||
|
||||
|
||||
#endif /*__ESP_HOSTED_OTA_H__*/
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ESP_HOSTED_POWER_SAVE_API_H
|
||||
#define ESP_HOSTED_POWER_SAVE_API_H
|
||||
|
||||
typedef enum {
|
||||
HOSTED_WAKEUP_UNDEFINED = 0,
|
||||
HOSTED_WAKEUP_NORMAL_REBOOT,
|
||||
HOSTED_WAKEUP_DEEP_SLEEP,
|
||||
} esp_hosted_wakeup_reason_t;
|
||||
|
||||
typedef enum {
|
||||
HOSTED_POWER_SAVE_TYPE_NONE = 0,
|
||||
HOSTED_POWER_SAVE_TYPE_LIGHT_SLEEP,
|
||||
HOSTED_POWER_SAVE_TYPE_DEEP_SLEEP,
|
||||
} esp_hosted_power_save_type_t;
|
||||
|
||||
/*
|
||||
* @brief Initializes the power save driver.
|
||||
* This function is typically called automatically during esp_hosted_init().
|
||||
*/
|
||||
int esp_hosted_power_save_init(void);
|
||||
|
||||
/*
|
||||
* @brief Deinitializes the power save driver.
|
||||
* This function is typically called automatically during esp_hosted_deinit().
|
||||
*/
|
||||
int esp_hosted_power_save_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief Checks if the host power save feature is enabled in Kconfig.
|
||||
*
|
||||
* @return int Returns 1 if the feature is enabled, 0 otherwise.
|
||||
*/
|
||||
int esp_hosted_power_save_enabled(void);
|
||||
|
||||
/**
|
||||
* @brief Determines if the host rebooted due to deep sleep.
|
||||
*
|
||||
* @return int Returns 1 if the host rebooted due to deep sleep, 0 otherwise.
|
||||
*/
|
||||
int esp_hosted_woke_from_power_save(void);
|
||||
|
||||
/**
|
||||
* @brief Checks if the host is currently in power saving mode.
|
||||
*
|
||||
* @return int Returns 1 if the host is in power saving mode, 0 otherwise.
|
||||
*/
|
||||
int esp_hosted_power_saving(void);
|
||||
|
||||
/**
|
||||
* @brief Initiates the host power save mode (deep sleep).
|
||||
* @note This function does not return. The host will enter deep sleep
|
||||
* and reboot upon wake-up.
|
||||
*
|
||||
* @param power_save_type The type of power save mode to enter.
|
||||
* Currently, only HOSTED_POWER_SAVE_TYPE_DEEP_SLEEP is supported.
|
||||
* @return int Returns 0 on success, or a nonzero value on failure (e.g., if the feature is disabled).
|
||||
*/
|
||||
int esp_hosted_power_save_start(esp_hosted_power_save_type_t power_save_type);
|
||||
|
||||
/**
|
||||
* @brief Starts a timer that will place the host into deep sleep upon expiration.
|
||||
*
|
||||
* @param time_ms The duration in milliseconds after which the host will enter deep sleep.
|
||||
* @return int Returns 0 on success or a nonzero value on failure.
|
||||
*/
|
||||
int esp_hosted_power_save_timer_start(uint32_t time_ms);
|
||||
|
||||
/**
|
||||
* @brief Stops the host power save timer.
|
||||
*
|
||||
* @return int Returns 0 on success or a nonzero value on failure.
|
||||
*/
|
||||
int esp_hosted_power_save_timer_stop(void);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __ESP_HOSTED_TRANSPORT_CONFIG_H__
|
||||
#define __ESP_HOSTED_TRANSPORT_CONFIG_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
typedef enum {
|
||||
ESP_TRANSPORT_OK = ESP_OK,
|
||||
ESP_TRANSPORT_ERR_INVALID_ARG = ESP_ERR_INVALID_ARG,
|
||||
ESP_TRANSPORT_ERR_ALREADY_SET = ESP_ERR_NOT_ALLOWED,
|
||||
ESP_TRANSPORT_ERR_INVALID_STATE = ESP_ERR_INVALID_STATE,
|
||||
} esp_hosted_transport_err_t;
|
||||
|
||||
/* GPIO pin configuration structure */
|
||||
typedef struct {
|
||||
void *port;
|
||||
int pin;
|
||||
} gpio_pin_t;
|
||||
|
||||
/* New Configuration Structures */
|
||||
struct esp_hosted_sdio_config {
|
||||
uint32_t clock_freq_khz;
|
||||
uint8_t bus_width;
|
||||
uint8_t slot;
|
||||
gpio_pin_t pin_clk;
|
||||
gpio_pin_t pin_cmd;
|
||||
gpio_pin_t pin_d0;
|
||||
gpio_pin_t pin_d1;
|
||||
gpio_pin_t pin_d2;
|
||||
gpio_pin_t pin_d3;
|
||||
gpio_pin_t pin_reset;
|
||||
uint8_t rx_mode;
|
||||
bool block_mode;
|
||||
bool iomux_enable;
|
||||
uint16_t tx_queue_size;
|
||||
uint16_t rx_queue_size;
|
||||
};
|
||||
|
||||
struct esp_hosted_spi_hd_config {
|
||||
/* Number of lines used */
|
||||
uint8_t num_data_lines;
|
||||
|
||||
/* SPI HD pins */
|
||||
gpio_pin_t pin_cs;
|
||||
gpio_pin_t pin_clk;
|
||||
gpio_pin_t pin_data_ready;
|
||||
gpio_pin_t pin_d0;
|
||||
gpio_pin_t pin_d1;
|
||||
gpio_pin_t pin_d2;
|
||||
gpio_pin_t pin_d3;
|
||||
gpio_pin_t pin_reset;
|
||||
|
||||
/* SPI HD configuration */
|
||||
uint32_t clk_mhz;
|
||||
uint8_t mode;
|
||||
uint16_t tx_queue_size;
|
||||
uint16_t rx_queue_size;
|
||||
bool checksum_enable;
|
||||
uint8_t num_command_bits;
|
||||
uint8_t num_address_bits;
|
||||
uint8_t num_dummy_bits;
|
||||
};
|
||||
|
||||
struct esp_hosted_spi_config {
|
||||
/* SPI Full Duplex pins */
|
||||
gpio_pin_t pin_mosi;
|
||||
gpio_pin_t pin_miso;
|
||||
gpio_pin_t pin_sclk;
|
||||
gpio_pin_t pin_cs;
|
||||
gpio_pin_t pin_handshake;
|
||||
gpio_pin_t pin_data_ready;
|
||||
gpio_pin_t pin_reset;
|
||||
|
||||
/* SPI Full Duplex configuration */
|
||||
uint16_t tx_queue_size;
|
||||
uint16_t rx_queue_size;
|
||||
uint8_t mode;
|
||||
uint32_t clk_mhz;
|
||||
};
|
||||
|
||||
struct esp_hosted_uart_config {
|
||||
/* UART bus number */
|
||||
uint8_t port;
|
||||
|
||||
/* UART pins */
|
||||
gpio_pin_t pin_tx;
|
||||
gpio_pin_t pin_rx;
|
||||
gpio_pin_t pin_reset;
|
||||
|
||||
/* UART configuration */
|
||||
uint8_t num_data_bits;
|
||||
uint8_t parity;
|
||||
uint8_t stop_bits;
|
||||
uint8_t flow_ctrl;
|
||||
uint8_t clk_src;
|
||||
bool checksum_enable;
|
||||
uint32_t baud_rate;
|
||||
uint16_t tx_queue_size;
|
||||
uint16_t rx_queue_size;
|
||||
};
|
||||
|
||||
struct esp_hosted_transport_config {
|
||||
uint8_t transport_in_use;
|
||||
union {
|
||||
struct esp_hosted_sdio_config sdio;
|
||||
struct esp_hosted_spi_hd_config spi_hd;
|
||||
struct esp_hosted_spi_config spi;
|
||||
struct esp_hosted_uart_config uart;
|
||||
} u;
|
||||
};
|
||||
|
||||
/* Default configuration functions - implemented by port layer */
|
||||
struct esp_hosted_sdio_config esp_hosted_get_default_sdio_config(void);
|
||||
struct esp_hosted_sdio_config esp_hosted_get_default_sdio_iomux_config(void);
|
||||
struct esp_hosted_spi_hd_config esp_hosted_get_default_spi_hd_config(void);
|
||||
struct esp_hosted_spi_config esp_hosted_get_default_spi_config(void);
|
||||
struct esp_hosted_uart_config esp_hosted_get_default_uart_config(void);
|
||||
|
||||
/* Convenience macros for backward compatibility and ease of use */
|
||||
#define INIT_DEFAULT_HOST_SDIO_CONFIG() esp_hosted_get_default_sdio_config()
|
||||
#define INIT_DEFAULT_HOST_SDIO_IOMUX_CONFIG() esp_hosted_get_default_sdio_iomux_config()
|
||||
#define INIT_DEFAULT_HOST_SPI_HD_CONFIG() esp_hosted_get_default_spi_hd_config()
|
||||
#define INIT_DEFAULT_HOST_SPI_CONFIG() esp_hosted_get_default_spi_config()
|
||||
#define INIT_DEFAULT_HOST_UART_CONFIG() esp_hosted_get_default_uart_config()
|
||||
|
||||
/***
|
||||
* Generic Transport APIs
|
||||
***/
|
||||
esp_err_t esp_hosted_set_default_config(void);
|
||||
bool esp_hosted_is_config_valid(void);
|
||||
|
||||
/* Configuration get/set functions */
|
||||
esp_hosted_transport_err_t esp_hosted_transport_set_default_config(void);
|
||||
esp_hosted_transport_err_t esp_hosted_transport_get_config(struct esp_hosted_transport_config **config);
|
||||
esp_hosted_transport_err_t esp_hosted_transport_get_reset_config(gpio_pin_t *pin_config);
|
||||
|
||||
bool esp_hosted_transport_is_config_valid(void);
|
||||
|
||||
/***
|
||||
* Transport dependent APIs.
|
||||
* Can only be used with the configured host transport
|
||||
***/
|
||||
/* SDIO functions */
|
||||
esp_hosted_transport_err_t esp_hosted_sdio_get_config(struct esp_hosted_sdio_config **config);
|
||||
esp_hosted_transport_err_t esp_hosted_sdio_set_config(struct esp_hosted_sdio_config *config) __attribute__((warn_unused_result));
|
||||
|
||||
esp_hosted_transport_err_t esp_hosted_sdio_iomux_set_config(struct esp_hosted_sdio_config *config) __attribute__((warn_unused_result));
|
||||
|
||||
/* SPI Half Duplex functions */
|
||||
esp_hosted_transport_err_t esp_hosted_spi_hd_get_config(struct esp_hosted_spi_hd_config **config);
|
||||
esp_hosted_transport_err_t esp_hosted_spi_hd_set_config(struct esp_hosted_spi_hd_config *config) __attribute__((warn_unused_result));
|
||||
|
||||
esp_hosted_transport_err_t esp_hosted_spi_hd_2lines_get_config(struct esp_hosted_spi_hd_config **config);
|
||||
esp_hosted_transport_err_t esp_hosted_spi_hd_2lines_set_config(struct esp_hosted_spi_hd_config *config) __attribute__((warn_unused_result));
|
||||
|
||||
/* SPI Full Duplex functions */
|
||||
esp_hosted_transport_err_t esp_hosted_spi_get_config(struct esp_hosted_spi_config **config);
|
||||
esp_hosted_transport_err_t esp_hosted_spi_set_config(struct esp_hosted_spi_config *config) __attribute__((warn_unused_result));
|
||||
|
||||
/* UART functions */
|
||||
esp_hosted_transport_err_t esp_hosted_uart_get_config(struct esp_hosted_uart_config **config);
|
||||
esp_hosted_transport_err_t esp_hosted_uart_set_config(struct esp_hosted_uart_config *config) __attribute__((warn_unused_result));
|
||||
|
||||
#endif /* __ESP_HOSTED_TRANSPORT_CONFIG_H__ */
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __ESP_HOSTED_WIFI_REMOTE_GLUE_H__
|
||||
#define __ESP_HOSTED_WIFI_REMOTE_GLUE_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp_hosted_interface.h"
|
||||
#include "esp_wifi_remote.h"
|
||||
#include "esp_wifi.h"
|
||||
|
||||
struct esp_remote_channel_config {
|
||||
esp_hosted_if_type_t if_type;
|
||||
bool secure;
|
||||
};
|
||||
|
||||
typedef struct esp_remote_channel_config * esp_remote_channel_config_t;
|
||||
|
||||
/* Transport/Channel related data structures and macros */
|
||||
#define ESP_HOSTED_CHANNEL_CONFIG_DEFAULT() { \
|
||||
.secure = true, \
|
||||
}
|
||||
|
||||
/* Function pointer types for channel callbacks */
|
||||
typedef esp_err_t (*esp_remote_channel_rx_fn_t)(void *h, void *buffer,
|
||||
void *buff_to_free, size_t len);
|
||||
typedef esp_err_t (*esp_remote_channel_tx_fn_t)(void *h, void *buffer, size_t len);
|
||||
|
||||
/* Transport/Channel Management API Functions - use managed component typedef */
|
||||
esp_remote_channel_t esp_hosted_add_channel(esp_remote_channel_config_t config,
|
||||
esp_remote_channel_tx_fn_t *tx, const esp_remote_channel_rx_fn_t rx);
|
||||
esp_err_t esp_hosted_remove_channel(esp_remote_channel_t channel);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ESP_HOSTED_WIFI_REMOTE_GLUE_H__ */
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* prevent recursive inclusion */
|
||||
#ifndef __ESP_HOSTED_API_PRIV_H__
|
||||
#define __ESP_HOSTED_API_PRIV_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes */
|
||||
#include "stdbool.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_wifi_remote.h"
|
||||
#include "esp_hosted_api_types.h"
|
||||
#include "port_esp_hosted_host_wifi_config.h"
|
||||
|
||||
|
||||
#if H_WIFI_ENTERPRISE_SUPPORT
|
||||
#include "esp_eap_client.h"
|
||||
#endif
|
||||
|
||||
#if H_DPP_SUPPORT
|
||||
#include "esp_dpp.h"
|
||||
#endif
|
||||
|
||||
/* Remote WiFi API Functions - Port/Implementation Specific */
|
||||
esp_err_t esp_wifi_remote_init(const wifi_init_config_t *arg);
|
||||
esp_err_t esp_wifi_remote_deinit(void);
|
||||
esp_err_t esp_wifi_remote_set_mode(wifi_mode_t mode);
|
||||
esp_err_t esp_wifi_remote_get_mode(wifi_mode_t* mode);
|
||||
esp_err_t esp_wifi_remote_start(void);
|
||||
esp_err_t esp_wifi_remote_stop(void);
|
||||
esp_err_t esp_wifi_remote_connect(void);
|
||||
esp_err_t esp_wifi_remote_disconnect(void);
|
||||
esp_err_t esp_wifi_remote_set_config(wifi_interface_t interface, wifi_config_t *conf);
|
||||
esp_err_t esp_wifi_remote_get_config(wifi_interface_t interface, wifi_config_t *conf);
|
||||
esp_err_t esp_wifi_remote_get_mac(wifi_interface_t mode, uint8_t mac[6]);
|
||||
esp_err_t esp_wifi_remote_set_mac(wifi_interface_t mode, const uint8_t mac[6]);
|
||||
|
||||
esp_err_t esp_wifi_remote_scan_start(const wifi_scan_config_t *config, bool block);
|
||||
esp_err_t esp_wifi_remote_set_scan_parameters(const wifi_scan_default_params_t *config);
|
||||
esp_err_t esp_wifi_remote_get_scan_parameters(wifi_scan_default_params_t *config);
|
||||
esp_err_t esp_wifi_remote_scan_stop(void);
|
||||
esp_err_t esp_wifi_remote_scan_get_ap_num(uint16_t *number);
|
||||
esp_err_t esp_wifi_remote_scan_get_ap_record(wifi_ap_record_t *ap_record);
|
||||
esp_err_t esp_wifi_remote_scan_get_ap_records(uint16_t *number, wifi_ap_record_t *ap_records);
|
||||
esp_err_t esp_wifi_remote_clear_ap_list(void);
|
||||
esp_err_t esp_wifi_remote_restore(void);
|
||||
esp_err_t esp_wifi_remote_clear_fast_connect(void);
|
||||
esp_err_t esp_wifi_remote_deauth_sta(uint16_t aid);
|
||||
esp_err_t esp_wifi_remote_sta_get_ap_info(wifi_ap_record_t *ap_info);
|
||||
esp_err_t esp_wifi_remote_set_ps(wifi_ps_type_t type);
|
||||
esp_err_t esp_wifi_remote_get_ps(wifi_ps_type_t *type);
|
||||
esp_err_t esp_wifi_remote_set_storage(wifi_storage_t storage);
|
||||
esp_err_t esp_wifi_remote_set_bandwidth(wifi_interface_t ifx, wifi_bandwidth_t bw);
|
||||
esp_err_t esp_wifi_remote_get_bandwidth(wifi_interface_t ifx, wifi_bandwidth_t *bw);
|
||||
esp_err_t esp_wifi_remote_set_channel(uint8_t primary, wifi_second_chan_t second);
|
||||
esp_err_t esp_wifi_remote_get_channel(uint8_t *primary, wifi_second_chan_t *second);
|
||||
esp_err_t esp_wifi_remote_set_country_code(const char *country, bool ieee80211d_enabled);
|
||||
esp_err_t esp_wifi_remote_get_country_code(char *country);
|
||||
esp_err_t esp_wifi_remote_set_country(const wifi_country_t *country);
|
||||
esp_err_t esp_wifi_remote_get_country(wifi_country_t *country);
|
||||
esp_err_t esp_wifi_remote_ap_get_sta_list(wifi_sta_list_t *sta);
|
||||
esp_err_t esp_wifi_remote_ap_get_sta_aid(const uint8_t mac[6], uint16_t *aid);
|
||||
esp_err_t esp_wifi_remote_sta_get_rssi(int *rssi);
|
||||
esp_err_t esp_wifi_remote_set_protocol(wifi_interface_t ifx, uint8_t protocol_bitmap);
|
||||
esp_err_t esp_wifi_remote_get_protocol(wifi_interface_t ifx, uint8_t *protocol_bitmap);
|
||||
esp_err_t esp_wifi_remote_set_max_tx_power(int8_t power);
|
||||
esp_err_t esp_wifi_remote_get_max_tx_power(int8_t *power);
|
||||
esp_err_t esp_wifi_remote_sta_get_negotiated_phymode(wifi_phy_mode_t *phymode);
|
||||
esp_err_t esp_wifi_remote_sta_get_aid(uint16_t *aid);
|
||||
esp_err_t esp_wifi_remote_set_inactive_time(wifi_interface_t ifx, uint16_t sec);
|
||||
esp_err_t esp_wifi_remote_get_inactive_time(wifi_interface_t ifx, uint16_t *sec);
|
||||
esp_err_t esp_wifi_remote_disable_pmf_config(wifi_interface_t ifx);
|
||||
|
||||
#if H_WIFI_HE_SUPPORT
|
||||
esp_err_t esp_wifi_remote_sta_twt_config(wifi_twt_config_t *config);
|
||||
#if H_WIFI_HE_GREATER_THAN_ESP_IDF_5_3
|
||||
esp_err_t esp_wifi_remote_sta_itwt_setup(wifi_itwt_setup_config_t *setup_config);
|
||||
#else
|
||||
esp_err_t esp_wifi_remote_sta_itwt_setup(wifi_twt_setup_config_t *setup_config);
|
||||
#endif
|
||||
esp_err_t esp_wifi_remote_sta_itwt_teardown(int flow_id);
|
||||
esp_err_t esp_wifi_remote_sta_itwt_suspend(int flow_id, int suspend_time_ms);
|
||||
esp_err_t esp_wifi_remote_sta_itwt_get_flow_id_status(int *flow_id_bitmap);
|
||||
esp_err_t esp_wifi_remote_sta_itwt_send_probe_req(int timeout_ms);
|
||||
esp_err_t esp_wifi_remote_sta_itwt_set_target_wake_time_offset(int timeout_us);
|
||||
#endif
|
||||
|
||||
#if H_WIFI_DUALBAND_SUPPORT
|
||||
/* Dual-band WiFi API (Depends upon co-processor used) */
|
||||
esp_err_t esp_wifi_remote_set_band(wifi_band_t band);
|
||||
esp_err_t esp_wifi_remote_get_band(wifi_band_t *band);
|
||||
esp_err_t esp_wifi_remote_set_band_mode(wifi_band_mode_t band_mode);
|
||||
esp_err_t esp_wifi_remote_get_band_mode(wifi_band_mode_t *band_mode);
|
||||
esp_err_t esp_wifi_remote_set_protocols(wifi_interface_t ifx, wifi_protocols_t *protocols);
|
||||
esp_err_t esp_wifi_remote_get_protocols(wifi_interface_t ifx, wifi_protocols_t *protocols);
|
||||
esp_err_t esp_wifi_remote_set_bandwidths(wifi_interface_t ifx, wifi_bandwidths_t *bw);
|
||||
esp_err_t esp_wifi_remote_get_bandwidths(wifi_interface_t ifx, wifi_bandwidths_t *bw);
|
||||
#endif
|
||||
|
||||
#if H_WIFI_ENTERPRISE_SUPPORT
|
||||
esp_err_t esp_wifi_remote_sta_enterprise_enable(void);
|
||||
esp_err_t esp_wifi_remote_sta_enterprise_disable(void);
|
||||
esp_err_t esp_eap_client_remote_set_identity(const unsigned char *identity, int len);
|
||||
esp_err_t esp_eap_client_remote_clear_identity(void);
|
||||
esp_err_t esp_eap_client_remote_set_username(const unsigned char *username, int len);
|
||||
esp_err_t esp_eap_client_remote_clear_username(void);
|
||||
esp_err_t esp_eap_client_remote_set_password(const unsigned char *password, int len);
|
||||
esp_err_t esp_eap_client_remote_clear_password(void);
|
||||
esp_err_t esp_eap_client_remote_set_new_password(const unsigned char *new_password, int len);
|
||||
esp_err_t esp_eap_client_remote_clear_new_password(void);
|
||||
esp_err_t esp_eap_client_remote_set_ca_cert(const unsigned char *ca_cert, int ca_cert_len);
|
||||
esp_err_t esp_eap_client_remote_clear_ca_cert(void);
|
||||
esp_err_t esp_eap_client_remote_clear_certificate_and_key(void);
|
||||
esp_err_t esp_eap_client_remote_set_disable_time_check(bool disable);
|
||||
esp_err_t esp_eap_client_remote_get_disable_time_check(bool *disable);
|
||||
esp_err_t esp_eap_client_remote_set_ttls_phase2_method(esp_eap_ttls_phase2_types type);
|
||||
esp_err_t esp_eap_client_remote_set_suiteb_192bit_certification(bool enable);
|
||||
esp_err_t esp_eap_client_remote_set_pac_file(const unsigned char *pac_file, int pac_file_len);
|
||||
esp_err_t esp_eap_client_remote_set_fast_params(esp_eap_fast_config config);
|
||||
esp_err_t esp_eap_client_remote_use_default_cert_bundle(bool use_default_bundle);
|
||||
esp_err_t esp_wifi_remote_set_okc_support(bool enable);
|
||||
esp_err_t esp_eap_client_remote_set_domain_name(const char *domain_name);
|
||||
esp_err_t esp_eap_client_remote_set_certificate_and_key(const unsigned char *client_cert, int client_cert_len,
|
||||
const unsigned char *private_key, int private_key_len,
|
||||
const unsigned char *private_key_password, int private_key_passwd_len);
|
||||
#if H_GOT_SET_EAP_METHODS_API
|
||||
esp_err_t esp_eap_client_remote_set_eap_methods(esp_eap_method_t methods);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if H_DPP_SUPPORT
|
||||
#if H_SUPP_DPP_SUPPORT
|
||||
esp_err_t esp_supp_remote_dpp_init(esp_supp_dpp_event_cb_t evt_cb);
|
||||
#else
|
||||
esp_err_t esp_supp_remote_dpp_init(void);
|
||||
#endif
|
||||
esp_err_t esp_supp_remote_dpp_deinit(void);
|
||||
esp_err_t esp_supp_remote_dpp_bootstrap_gen(const char *chan_list,
|
||||
esp_supp_dpp_bootstrap_t type,
|
||||
const char *key, const char *info);
|
||||
esp_err_t esp_supp_remote_dpp_start_listen(void);
|
||||
esp_err_t esp_supp_remote_dpp_stop_listen(void);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ESP_HOSTED_API_PRIV_H__ */
|
||||
@@ -0,0 +1,988 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Includes **/
|
||||
#include "esp_hosted_transport_config.h"
|
||||
#include "esp_hosted_api_priv.h"
|
||||
#include "esp_hosted_wifi_remote_glue.h"
|
||||
#include "port_esp_hosted_host_wifi_config.h"
|
||||
#include "port_esp_hosted_host_openthread.h"
|
||||
#include "port_esp_hosted_host_os.h"
|
||||
#include "esp_hosted_misc.h"
|
||||
#include "esp_check.h"
|
||||
#include "transport_drv.h"
|
||||
#include "rpc_wrap.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_hosted_event.h"
|
||||
|
||||
#if H_DPP_SUPPORT
|
||||
#include "esp_dpp.h"
|
||||
#endif
|
||||
|
||||
#if H_HOST_OT_ENABLE
|
||||
#include "esp_hosted_openthread.h"
|
||||
#endif
|
||||
|
||||
/** Macros **/
|
||||
static const char *TAG="H_API";
|
||||
|
||||
static uint8_t esp_hosted_init_done;
|
||||
static uint8_t esp_hosted_transport_up;
|
||||
|
||||
|
||||
#define check_transport_up() \
|
||||
do { \
|
||||
if (!(esp_hosted_transport_up)) { \
|
||||
ESP_LOGE(TAG, "ESP-Hosted link not yet up"); \
|
||||
return ESP_FAIL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
||||
/** Exported variables **/
|
||||
struct esp_remote_channel {
|
||||
transport_channel_t *t_chan;
|
||||
};
|
||||
|
||||
//static semaphore_handle_t transport_up_sem;
|
||||
|
||||
/** Inline functions **/
|
||||
|
||||
/** Exported Functions **/
|
||||
static void transport_active_cb(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Transport active");
|
||||
esp_hosted_transport_up = 1;
|
||||
g_h.funcs->_h_event_post(ESP_HOSTED_EVENT,
|
||||
ESP_HOSTED_EVENT_TRANSPORT_UP,
|
||||
NULL, 0, HOSTED_BLOCK_MAX);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void create_esp_hosted_transport_up_sem(void)
|
||||
{
|
||||
if (!transport_up_sem) {
|
||||
transport_up_sem = g_h.funcs->_h_create_semaphore(1);
|
||||
assert(transport_up_sem);
|
||||
/* clear semaphore */
|
||||
g_h.funcs->_h_get_semaphore(transport_up_sem, 0);
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t esp_hosted_setup(void)
|
||||
{
|
||||
create_esp_hosted_transport_up_sem();
|
||||
g_h.funcs->_h_get_semaphore(transport_up_sem, HOSTED_BLOCK_MAX);
|
||||
g_h.funcs->_h_post_semaphore(transport_up_sem);
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static esp_remote_channel_t sta_ch = NULL;
|
||||
static esp_remote_channel_t ap_ch = NULL;
|
||||
|
||||
static esp_err_t add_esp_wifi_remote_channels(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "** %s **", __func__);
|
||||
esp_remote_channel_tx_fn_t tx_cb;
|
||||
|
||||
/* Add an RPC channel with default config (i.e. secure=true) */
|
||||
struct esp_remote_channel_config config = ESP_HOSTED_CHANNEL_CONFIG_DEFAULT();
|
||||
config.if_type = ESP_SERIAL_IF;
|
||||
/*TODO: add rpc channel from here
|
||||
ch = esp_hosted_add_channel(&config, &tx_cb, esp_wifi_remote_rpc_channel_rx);
|
||||
esp_wifi_remote_rpc_channel_set(ch, tx_cb); */
|
||||
|
||||
/* Add two other channels for the two WiFi interfaces (STA, softAP) in plain text */
|
||||
config.secure = false;
|
||||
config.if_type = ESP_STA_IF;
|
||||
sta_ch = esp_hosted_add_channel(&config, &tx_cb, esp_wifi_remote_channel_rx);
|
||||
esp_wifi_remote_channel_set(WIFI_IF_STA, sta_ch, tx_cb);
|
||||
|
||||
|
||||
config.secure = false;
|
||||
config.if_type = ESP_AP_IF;
|
||||
ap_ch = esp_hosted_add_channel(&config, &tx_cb, esp_wifi_remote_channel_rx);
|
||||
esp_wifi_remote_channel_set(WIFI_IF_AP, ap_ch, tx_cb);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t remove_esp_wifi_remote_channels(void)
|
||||
{
|
||||
if (sta_ch) {
|
||||
esp_hosted_remove_channel(sta_ch);
|
||||
sta_ch = NULL;
|
||||
}
|
||||
if (ap_ch) {
|
||||
esp_hosted_remove_channel(ap_ch);
|
||||
ap_ch = NULL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void set_host_modules_log_level(void)
|
||||
{
|
||||
esp_log_level_set("rpc_core", ESP_LOG_WARN);
|
||||
esp_log_level_set("rpc_rsp", ESP_LOG_WARN);
|
||||
esp_log_level_set("rpc_evt", ESP_LOG_WARN);
|
||||
}
|
||||
int esp_hosted_init(void)
|
||||
{
|
||||
if (esp_hosted_init_done)
|
||||
return ESP_OK;
|
||||
|
||||
set_host_modules_log_level();
|
||||
|
||||
//create_esp_hosted_transport_up_sem();
|
||||
ESP_LOGI(TAG, "ESP-Hosted starting. Hosted_Tasks: prio:%u, stack: %u RPC_task_stack: %u",
|
||||
DFLT_TASK_PRIO, DFLT_TASK_STACK_SIZE, RPC_TASK_STACK_SIZE);
|
||||
if (esp_hosted_is_config_valid()) {
|
||||
ESP_LOGW(TAG, "ESP-Hosted config valid; reuse existing config");
|
||||
} else {
|
||||
ESP_ERROR_CHECK(esp_hosted_set_default_config());
|
||||
}
|
||||
ESP_ERROR_CHECK(add_esp_wifi_remote_channels());
|
||||
ESP_ERROR_CHECK(setup_transport(transport_active_cb));
|
||||
ESP_ERROR_CHECK(rpc_init());
|
||||
rpc_register_event_callbacks();
|
||||
|
||||
esp_hosted_init_done = 1;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int esp_hosted_deinit(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "ESP-Hosted deinit\n");
|
||||
rpc_unregister_event_callbacks();
|
||||
ESP_ERROR_CHECK(rpc_deinit());
|
||||
ESP_ERROR_CHECK(remove_esp_wifi_remote_channels());
|
||||
ESP_ERROR_CHECK(teardown_transport());
|
||||
esp_hosted_init_done = 0;
|
||||
esp_hosted_transport_up = 0;
|
||||
g_h.funcs->_h_event_post(ESP_HOSTED_EVENT,
|
||||
ESP_HOSTED_EVENT_TRANSPORT_DOWN,
|
||||
NULL, 0, HOSTED_BLOCK_MAX);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t esp_hosted_reconfigure(void)
|
||||
{
|
||||
if (!esp_hosted_is_config_valid()) {
|
||||
ESP_LOGE(TAG, "Transport not initialized, call esp_hosted_init() first");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK_WITHOUT_ABORT(transport_drv_reconfigure());
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int esp_hosted_connect_to_slave(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "ESP-Hosted Try to communicate with ESP-Hosted slave\n");
|
||||
return esp_hosted_reconfigure();
|
||||
}
|
||||
|
||||
esp_remote_channel_t esp_hosted_add_channel(esp_remote_channel_config_t config,
|
||||
esp_remote_channel_tx_fn_t *tx, const esp_remote_channel_rx_fn_t rx)
|
||||
{
|
||||
transport_channel_t *t_chan = NULL;
|
||||
esp_remote_channel_t eh_chan = NULL;
|
||||
|
||||
eh_chan = g_h.funcs->_h_calloc(sizeof(struct esp_remote_channel), 1);
|
||||
assert(eh_chan);
|
||||
|
||||
t_chan = transport_drv_add_channel(eh_chan, config->if_type, config->secure, tx, rx);
|
||||
if (t_chan) {
|
||||
*tx = t_chan->tx;
|
||||
eh_chan->t_chan = t_chan;
|
||||
return eh_chan;
|
||||
} else {
|
||||
HOSTED_FREE(eh_chan);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
esp_err_t esp_hosted_remove_channel(esp_remote_channel_t eh_chan)
|
||||
{
|
||||
if (eh_chan && eh_chan->t_chan) {
|
||||
transport_drv_remove_channel(eh_chan->t_chan);
|
||||
HOSTED_FREE(eh_chan);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_init(const wifi_init_config_t *arg)
|
||||
{
|
||||
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_hosted_reconfigure());
|
||||
check_transport_up();
|
||||
return rpc_wifi_init(arg);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_deinit(void)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_deinit();
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_set_mode(wifi_mode_t mode)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_set_mode(mode);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_get_mode(wifi_mode_t* mode)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_get_mode(mode);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_start(void)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_start();
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_stop(void)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_stop();
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_connect(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "%s",__func__);
|
||||
check_transport_up();
|
||||
return rpc_wifi_connect();
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_disconnect(void)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_disconnect();
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_set_config(wifi_interface_t interface, wifi_config_t *conf)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_set_config(interface, conf);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_get_config(wifi_interface_t interface, wifi_config_t *conf)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_get_config(interface, conf);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_get_mac(wifi_interface_t mode, uint8_t mac[6])
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_get_mac(mode, mac);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_set_mac(wifi_interface_t mode, const uint8_t mac[6])
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_set_mac(mode, mac);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_scan_start(const wifi_scan_config_t *config, bool block)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_scan_start(config, block);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_set_scan_parameters(const wifi_scan_default_params_t *config)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_set_scan_parameters(config);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_get_scan_parameters(wifi_scan_default_params_t *config)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_get_scan_parameters(config);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_scan_stop(void)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_scan_stop();
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_scan_get_ap_num(uint16_t *number)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_scan_get_ap_num(number);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_scan_get_ap_record(wifi_ap_record_t *ap_record)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_scan_get_ap_record(ap_record);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_scan_get_ap_records(uint16_t *number, wifi_ap_record_t *ap_records)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_scan_get_ap_records(number, ap_records);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_clear_ap_list(void)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_clear_ap_list();
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_restore(void)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_restore();
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_clear_fast_connect(void)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_clear_fast_connect();
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_deauth_sta(uint16_t aid)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_deauth_sta(aid);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_sta_get_ap_info(wifi_ap_record_t *ap_info)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_sta_get_ap_info(ap_info);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_set_ps(wifi_ps_type_t type)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_set_ps(type);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_get_ps(wifi_ps_type_t *type)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_get_ps(type);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_set_storage(wifi_storage_t storage)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_set_storage(storage);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_set_bandwidth(wifi_interface_t ifx, wifi_bandwidth_t bw)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_set_bandwidth(ifx, bw);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_get_bandwidth(wifi_interface_t ifx, wifi_bandwidth_t *bw)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_get_bandwidth(ifx, bw);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_set_channel(uint8_t primary, wifi_second_chan_t second)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_set_channel(primary, second);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_get_channel(uint8_t *primary, wifi_second_chan_t *second)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_get_channel(primary, second);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_set_country_code(const char *country, bool ieee80211d_enabled)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_set_country_code(country, ieee80211d_enabled);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_get_country_code(char *country)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_get_country_code(country);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_set_country(const wifi_country_t *country)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_set_country(country);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_get_country(wifi_country_t *country)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_get_country(country);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_ap_get_sta_list(wifi_sta_list_t *sta)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_ap_get_sta_list(sta);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_ap_get_sta_aid(const uint8_t mac[6], uint16_t *aid)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_ap_get_sta_aid(mac, aid);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_sta_get_rssi(int *rssi)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_sta_get_rssi(rssi);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_set_protocol(wifi_interface_t ifx, uint8_t protocol_bitmap)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_set_protocol(ifx, protocol_bitmap);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_get_protocol(wifi_interface_t ifx, uint8_t *protocol_bitmap)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_get_protocol(ifx, protocol_bitmap);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_set_max_tx_power(int8_t power)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_set_max_tx_power(power);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_get_max_tx_power(int8_t *power)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_get_max_tx_power(power);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_sta_get_negotiated_phymode(wifi_phy_mode_t *phymode)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_sta_get_negotiated_phymode(phymode);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_sta_get_aid(uint16_t *aid)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_sta_get_aid(aid);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_set_inactive_time(wifi_interface_t ifx, uint16_t sec)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_set_inactive_time(ifx, sec);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_get_inactive_time(wifi_interface_t ifx, uint16_t *sec)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_get_inactive_time(ifx, sec);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_disable_pmf_config(wifi_interface_t ifx)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_disable_pmf_config(ifx);
|
||||
}
|
||||
|
||||
#if H_WIFI_HE_SUPPORT
|
||||
esp_err_t esp_wifi_remote_sta_twt_config(wifi_twt_config_t *config)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_sta_twt_config(config);
|
||||
}
|
||||
|
||||
#if H_WIFI_HE_GREATER_THAN_ESP_IDF_5_3
|
||||
esp_err_t esp_wifi_remote_sta_itwt_setup(wifi_itwt_setup_config_t *setup_config)
|
||||
#else
|
||||
esp_err_t esp_wifi_remote_sta_itwt_setup(wifi_twt_setup_config_t *setup_config)
|
||||
#endif
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_sta_itwt_setup(setup_config);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_sta_itwt_teardown(int flow_id)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_sta_itwt_teardown(flow_id);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_sta_itwt_suspend(int flow_id, int suspend_time_ms)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_sta_itwt_suspend(flow_id, suspend_time_ms);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_sta_itwt_get_flow_id_status(int *flow_id_bitmap)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_sta_itwt_get_flow_id_status(flow_id_bitmap);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_sta_itwt_send_probe_req(int timeout_ms)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_sta_itwt_send_probe_req(timeout_ms);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_sta_itwt_set_target_wake_time_offset(int offset_us)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_sta_itwt_set_target_wake_time_offset(offset_us);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if H_WIFI_DUALBAND_SUPPORT
|
||||
/* Dual-band WiFi API - always available at high level, but returns ESP_ERR_NOT_SUPPORTED when co-processor do not support */
|
||||
esp_err_t esp_wifi_remote_set_band(wifi_band_t band)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_set_band(band);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_get_band(wifi_band_t *band)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_get_band(band);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_set_band_mode(wifi_band_mode_t band_mode)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_set_band_mode(band_mode);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_get_band_mode(wifi_band_mode_t *band_mode)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_get_band_mode(band_mode);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_set_protocols(wifi_interface_t ifx, wifi_protocols_t *protocols)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_set_protocols(ifx, protocols);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_get_protocols(wifi_interface_t ifx, wifi_protocols_t *protocols)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_get_protocols(ifx, protocols);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_set_bandwidths(wifi_interface_t ifx, wifi_bandwidths_t *bw)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_set_bandwidths(ifx, bw);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_get_bandwidths(wifi_interface_t ifx, wifi_bandwidths_t *bw)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_get_bandwidths(ifx, bw);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if H_DPP_SUPPORT
|
||||
#if H_SUPP_DPP_SUPPORT
|
||||
esp_err_t esp_supp_remote_dpp_init(esp_supp_dpp_event_cb_t evt_cb)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_supp_dpp_init(evt_cb);
|
||||
}
|
||||
#else
|
||||
esp_err_t esp_supp_remote_dpp_init(void)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_supp_dpp_init();
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_err_t esp_supp_remote_dpp_deinit(void)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_supp_dpp_deinit();
|
||||
}
|
||||
|
||||
esp_err_t esp_supp_remote_dpp_bootstrap_gen(const char *chan_list,
|
||||
esp_supp_dpp_bootstrap_t type,
|
||||
const char *key, const char *info)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_supp_dpp_bootstrap_gen(chan_list, type, key, info);
|
||||
}
|
||||
|
||||
esp_err_t esp_supp_remote_dpp_start_listen(void)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_supp_dpp_start_listen();
|
||||
}
|
||||
|
||||
esp_err_t esp_supp_remote_dpp_stop_listen(void)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_supp_dpp_stop_listen();
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_err_t esp_hosted_get_coprocessor_fwversion(esp_hosted_coprocessor_fwver_t *ver_info)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_get_coprocessor_fwversion(ver_info);
|
||||
}
|
||||
|
||||
esp_err_t esp_hosted_get_cp_info(uint32_t *cp_chip_id, char *cp_target_name,
|
||||
size_t cp_target_name_len)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_get_cp_info(cp_chip_id, cp_target_name, cp_target_name_len);
|
||||
}
|
||||
|
||||
#if H_WIFI_ENTERPRISE_SUPPORT
|
||||
esp_err_t esp_wifi_remote_sta_enterprise_enable(void)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_sta_enterprise_enable();
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_sta_enterprise_disable(void)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_sta_enterprise_disable();
|
||||
}
|
||||
|
||||
esp_err_t esp_eap_client_remote_set_identity(const unsigned char *identity, int len)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_eap_client_set_identity(identity, len);
|
||||
}
|
||||
|
||||
esp_err_t esp_eap_client_remote_clear_identity(void)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_eap_client_clear_identity();
|
||||
}
|
||||
|
||||
esp_err_t esp_eap_client_remote_set_username(const unsigned char *username, int len)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_eap_client_set_username(username, len);
|
||||
}
|
||||
|
||||
esp_err_t esp_eap_client_remote_clear_username(void)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_eap_client_clear_username();
|
||||
}
|
||||
|
||||
esp_err_t esp_eap_client_remote_set_password(const unsigned char *password, int len)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_eap_client_set_password(password, len);
|
||||
}
|
||||
|
||||
esp_err_t esp_eap_client_remote_clear_password(void)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_eap_client_clear_password();
|
||||
}
|
||||
|
||||
esp_err_t esp_eap_client_remote_set_new_password(const unsigned char *new_password, int len)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_eap_client_set_new_password(new_password, len);
|
||||
}
|
||||
|
||||
esp_err_t esp_eap_client_remote_clear_new_password(void)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_eap_client_clear_new_password();
|
||||
}
|
||||
|
||||
esp_err_t esp_eap_client_remote_set_ca_cert(const unsigned char *ca_cert, int ca_cert_len)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_eap_client_set_ca_cert(ca_cert, ca_cert_len);
|
||||
}
|
||||
|
||||
esp_err_t esp_eap_client_remote_clear_ca_cert(void)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_eap_client_clear_ca_cert();
|
||||
}
|
||||
|
||||
esp_err_t esp_eap_client_remote_set_certificate_and_key(const unsigned char *client_cert,
|
||||
int client_cert_len,
|
||||
const unsigned char *private_key,
|
||||
int private_key_len,
|
||||
const unsigned char *private_key_password,
|
||||
int private_key_passwd_len)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_eap_client_set_certificate_and_key(client_cert, client_cert_len, private_key,
|
||||
private_key_len, private_key_password, private_key_passwd_len);
|
||||
}
|
||||
|
||||
esp_err_t esp_eap_client_remote_clear_certificate_and_key(void)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_eap_client_clear_certificate_and_key();
|
||||
}
|
||||
|
||||
esp_err_t esp_eap_client_remote_set_disable_time_check(bool disable)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_eap_client_set_disable_time_check(disable);
|
||||
}
|
||||
|
||||
esp_err_t esp_eap_client_remote_get_disable_time_check(bool *disable)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_eap_client_get_disable_time_check(disable);
|
||||
}
|
||||
|
||||
esp_err_t esp_eap_client_remote_set_ttls_phase2_method(esp_eap_ttls_phase2_types type)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_eap_client_set_ttls_phase2_method(type);
|
||||
}
|
||||
|
||||
esp_err_t esp_eap_client_remote_set_suiteb_192bit_certification(bool enable)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_eap_client_set_suiteb_192bit_certification(enable);
|
||||
}
|
||||
|
||||
esp_err_t esp_eap_client_remote_set_pac_file(const unsigned char *pac_file, int pac_file_len)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_eap_client_set_pac_file(pac_file, pac_file_len);
|
||||
}
|
||||
|
||||
esp_err_t esp_eap_client_remote_set_fast_params(esp_eap_fast_config config)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_eap_client_set_fast_params(config);
|
||||
}
|
||||
|
||||
esp_err_t esp_eap_client_remote_use_default_cert_bundle(bool use_default_bundle)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_eap_client_use_default_cert_bundle(use_default_bundle);
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_set_okc_support(bool enable)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_wifi_set_okc_support(enable);
|
||||
}
|
||||
|
||||
esp_err_t esp_eap_client_remote_set_domain_name(const char *domain_name)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_eap_client_set_domain_name(domain_name);
|
||||
}
|
||||
|
||||
#if H_GOT_SET_EAP_METHODS_API
|
||||
esp_err_t esp_eap_client_remote_set_eap_methods(esp_eap_method_t methods)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_eap_client_set_eap_methods(methods);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
esp_err_t esp_hosted_bt_controller_init(void)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_bt_controller_init();
|
||||
}
|
||||
|
||||
esp_err_t esp_hosted_bt_controller_deinit(bool mem_release)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_bt_controller_deinit(mem_release);
|
||||
}
|
||||
|
||||
esp_err_t esp_hosted_bt_controller_enable(void)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_bt_controller_enable();
|
||||
}
|
||||
|
||||
esp_err_t esp_hosted_bt_controller_disable(void)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_bt_controller_disable();
|
||||
}
|
||||
|
||||
static bool check_mac_len(size_t mac_len, esp_mac_type_t type)
|
||||
{
|
||||
if (((type == ESP_MAC_IEEE802154) && (mac_len == 8)) ||
|
||||
((type == ESP_MAC_EFUSE_EXT) && (mac_len == 2)) ||
|
||||
(mac_len == 6)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
esp_err_t esp_hosted_iface_mac_addr_set(uint8_t *mac, size_t mac_len, esp_mac_type_t type)
|
||||
{
|
||||
// check that incoming mac_len is correct for the provided type
|
||||
if (!check_mac_len(mac_len, type)) {
|
||||
ESP_LOGE(TAG, "Invalid mac length for provided MAC type");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
check_transport_up();
|
||||
return rpc_iface_mac_addr_set_get(true, mac, mac_len, type);
|
||||
}
|
||||
|
||||
esp_err_t esp_hosted_iface_mac_addr_get(uint8_t *mac, size_t mac_len, esp_mac_type_t type)
|
||||
{
|
||||
// check that incoming mac_len is correct for the provided type
|
||||
if (!check_mac_len(mac_len, type)) {
|
||||
ESP_LOGE(TAG, "Invalid mac length for provided MAC type");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
check_transport_up();
|
||||
return rpc_iface_mac_addr_set_get(false, mac, mac_len, type);
|
||||
}
|
||||
|
||||
size_t esp_hosted_iface_mac_addr_len_get(esp_mac_type_t type)
|
||||
{
|
||||
// NOTE: this API returns size_t, not esp_err_t
|
||||
// to match size_t esp_mac_addr_len_get(esp_mac_type_t type)
|
||||
size_t len;
|
||||
|
||||
check_transport_up();
|
||||
if (ESP_OK != rpc_iface_mac_addr_len_get(&len, type)) {
|
||||
return 0;
|
||||
} else {
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t esp_hosted_get_coprocessor_app_desc(esp_hosted_app_desc_t *app_desc)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_iface_get_coprocessor_app_desc(app_desc);
|
||||
}
|
||||
|
||||
esp_err_t esp_hosted_configure_heartbeat(bool enable, int duration_sec)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_iface_configure_heartbeat(enable, duration_sec);
|
||||
}
|
||||
|
||||
#if H_MEM_MONITOR
|
||||
esp_err_t esp_hosted_set_mem_monitor(esp_hosted_config_mem_monitor_t *config, esp_hosted_curr_mem_info_t *curr_mem_info)
|
||||
{
|
||||
check_transport_up();
|
||||
if (!config || !curr_mem_info) {
|
||||
ESP_LOGE(TAG, "%s: got NULL pointer(s)", __func__);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return rpc_iface_set_mem_monitor(config, curr_mem_info);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if H_HOST_OT_ENABLE
|
||||
esp_err_t esp_hosted_openthread_rcp_init(void)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_iface_openthread_rcp_init();
|
||||
}
|
||||
|
||||
esp_err_t esp_hosted_openthread_rcp_deinit(void)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_iface_openthread_rcp_deinit();
|
||||
}
|
||||
|
||||
esp_err_t esp_hosted_openthread_rcp_start(void)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_iface_openthread_rcp_start();
|
||||
}
|
||||
|
||||
esp_err_t esp_hosted_openthread_rcp_stop(void)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_iface_openthread_rcp_stop();
|
||||
}
|
||||
|
||||
esp_err_t esp_hosted_openthread_rcp_query(esp_hosted_openthread_query_t query)
|
||||
{
|
||||
check_transport_up();
|
||||
return rpc_iface_openthread_rcp_query(query);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* esp_err_t esp_wifi_remote_scan_get_ap_record(wifi_ap_record_t *ap_record)
|
||||
esp_err_t esp_wifi_remote_set_csi(_Bool en)
|
||||
esp_err_t esp_wifi_remote_set_csi_rx_cb(wifi_csi_cb_t cb, void *ctx)
|
||||
esp_err_t esp_wifi_remote_set_csi_config(const wifi_csi_config_t *config)
|
||||
esp_err_t esp_wifi_remote_set_vendor_ie(_Bool enable, wifi_vendor_ie_type_t type, wifi_vendor_ie_id_t idx, const void *vnd_ie)
|
||||
esp_err_t esp_wifi_remote_set_vendor_ie_cb(esp_vendor_ie_cb_t cb, void *ctx)
|
||||
|
||||
esp_err_t esp_wifi_remote_sta_get_aid(uint16_t *aid)
|
||||
esp_err_t esp_wifi_remote_set_ant_gpio(const wifi_ant_gpio_config_t *config)
|
||||
esp_err_t esp_wifi_remote_get_ant_gpio(wifi_ant_gpio_config_t *config)
|
||||
esp_err_t esp_wifi_remote_set_ant(const wifi_ant_config_t *config)
|
||||
esp_err_t esp_wifi_remote_get_ant(wifi_ant_config_t *config)
|
||||
int64_t esp_wifi_remote_get_tsf_time(wifi_interface_t interface)
|
||||
esp_err_t esp_wifi_remote_set_inactive_time(wifi_interface_t ifx, uint16_t sec)
|
||||
esp_err_t esp_wifi_remote_get_inactive_time(wifi_interface_t ifx, uint16_t *sec)
|
||||
esp_err_t esp_wifi_remote_statis_dump(uint32_t modules)
|
||||
esp_err_t esp_wifi_remote_set_rssi_threshold(int32_t rssi)
|
||||
esp_err_t esp_wifi_remote_ftm_initiate_session(wifi_ftm_initiator_cfg_t *cfg)
|
||||
esp_err_t esp_wifi_remote_ftm_end_session(void)
|
||||
esp_err_t esp_wifi_remote_ftm_resp_set_offset(int16_t offset_cm)
|
||||
esp_err_t esp_wifi_remote_ftm_get_report(wifi_ftm_report_entry_t *report, uint8_t num_entries)
|
||||
esp_err_t esp_wifi_remote_config_11b_rate(wifi_interface_t ifx, _Bool disable)
|
||||
esp_err_t esp_wifi_remote_connectionless_module_set_wake_interval(uint16_t wake_interval)
|
||||
esp_err_t esp_wifi_remote_force_wakeup_acquire(void)
|
||||
esp_err_t esp_wifi_remote_force_wakeup_release(void)
|
||||
esp_err_t esp_wifi_remote_set_event_mask(uint32_t mask)
|
||||
esp_err_t esp_wifi_remote_get_event_mask(uint32_t *mask)
|
||||
esp_err_t esp_wifi_remote_80211_tx(wifi_interface_t ifx, const void *buffer, int len, _Bool en_sys_seq)
|
||||
esp_err_t esp_wifi_remote_set_promiscuous_rx_cb(wifi_promiscuous_cb_t cb)
|
||||
esp_err_t esp_wifi_remote_set_promiscuous(_Bool en)
|
||||
esp_err_t esp_wifi_remote_get_promiscuous(_Bool *en)
|
||||
esp_err_t esp_wifi_remote_set_promiscuous_filter(const wifi_promiscuous_filter_t *filter)
|
||||
esp_err_t esp_wifi_remote_get_promiscuous_filter(wifi_promiscuous_filter_t *filter)
|
||||
esp_err_t esp_wifi_remote_set_promiscuous_ctrl_filter(const wifi_promiscuous_filter_t *filter)
|
||||
esp_err_t esp_wifi_remote_get_promiscuous_ctrl_filter(wifi_promiscuous_filter_t *filter)
|
||||
|
||||
esp_err_t esp_wifi_remote_config_80211_tx_rate(wifi_interface_t ifx, wifi_phy_rate_t rate)
|
||||
esp_err_t esp_wifi_remote_sta_get_negotiated_phymode(wifi_phy_mode_t *phymode)
|
||||
esp_err_t esp_wifi_remote_set_dynamic_cs(_Bool enabled) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_hosted.h"
|
||||
#include "esp_log.h"
|
||||
#include "rpc_wrap.h"
|
||||
#include "esp_hosted_os_abstraction.h"
|
||||
|
||||
static const char* TAG = "esp_hosted_ota";
|
||||
|
||||
esp_err_t esp_hosted_slave_ota_begin(void)
|
||||
{
|
||||
ESP_LOGD(TAG, "Starting OTA on slave device");
|
||||
return rpc_ota_begin();
|
||||
}
|
||||
|
||||
esp_err_t esp_hosted_slave_ota_write(uint8_t* ota_data, uint32_t ota_data_len)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
if (!ota_data || ota_data_len == 0) {
|
||||
ESP_LOGE(TAG, "Invalid OTA data parameters");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "Writing %ld bytes of OTA data", ota_data_len);
|
||||
ret = rpc_ota_write(ota_data, ota_data_len);
|
||||
g_h.funcs->_h_msleep(10);
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_hosted_slave_ota_end(void)
|
||||
{
|
||||
ESP_LOGD(TAG, "Ending OTA on slave device");
|
||||
return rpc_ota_end();
|
||||
}
|
||||
|
||||
esp_err_t esp_hosted_slave_ota_activate(void)
|
||||
{
|
||||
ESP_LOGD(TAG, "Activating OTA on slave device");
|
||||
return rpc_ota_activate();
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "port_esp_hosted_host_config.h"
|
||||
#include "esp_hosted_transport_config.h"
|
||||
|
||||
static const char *TAG = "esp_hosted_transport_config";
|
||||
|
||||
/* Static configurations */
|
||||
static struct esp_hosted_transport_config s_transport_config = { 0 };
|
||||
|
||||
/* Flags to track if configs were set */
|
||||
static bool esp_hosted_transport_config_set;
|
||||
|
||||
bool esp_hosted_transport_is_config_valid(void) {
|
||||
return esp_hosted_transport_config_set;
|
||||
}
|
||||
|
||||
esp_err_t esp_hosted_set_default_config(void) {
|
||||
return esp_hosted_transport_set_default_config();
|
||||
}
|
||||
|
||||
bool esp_hosted_is_config_valid(void) {
|
||||
return esp_hosted_transport_is_config_valid();
|
||||
}
|
||||
|
||||
esp_hosted_transport_err_t esp_hosted_transport_set_default_config(void)
|
||||
{
|
||||
memset(&s_transport_config, 0, sizeof(s_transport_config));
|
||||
|
||||
#if H_TRANSPORT_IN_USE == H_TRANSPORT_SDIO
|
||||
ESP_ERROR_CHECK(esp_hosted_sdio_set_config(NULL));
|
||||
#elif H_TRANSPORT_IN_USE == H_TRANSPORT_SPI_HD
|
||||
ESP_ERROR_CHECK(esp_hosted_spi_hd_set_config(NULL));
|
||||
#elif H_TRANSPORT_IN_USE == H_TRANSPORT_SPI
|
||||
ESP_ERROR_CHECK(esp_hosted_spi_set_config(NULL));
|
||||
#elif H_TRANSPORT_IN_USE == H_TRANSPORT_UART
|
||||
ESP_ERROR_CHECK(esp_hosted_uart_set_config(NULL));
|
||||
#else
|
||||
return ESP_TRANSPORT_ERR_INVALID_STATE;
|
||||
#endif
|
||||
|
||||
return ESP_TRANSPORT_OK;
|
||||
}
|
||||
|
||||
esp_hosted_transport_err_t esp_hosted_transport_get_config(struct esp_hosted_transport_config **config)
|
||||
{
|
||||
if (!config) {
|
||||
return ESP_TRANSPORT_ERR_INVALID_ARG;
|
||||
}
|
||||
*config = &s_transport_config;
|
||||
return ESP_TRANSPORT_OK;
|
||||
}
|
||||
|
||||
esp_hosted_transport_err_t esp_hosted_transport_get_reset_config(gpio_pin_t *pin_config)
|
||||
{
|
||||
if (!pin_config) {
|
||||
return ESP_TRANSPORT_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
switch(s_transport_config.transport_in_use) {
|
||||
case H_TRANSPORT_SDIO:
|
||||
pin_config->port = s_transport_config.u.sdio.pin_reset.port;
|
||||
pin_config->pin = s_transport_config.u.sdio.pin_reset.pin;
|
||||
break;
|
||||
case H_TRANSPORT_SPI_HD:
|
||||
pin_config->port = s_transport_config.u.spi_hd.pin_reset.port;
|
||||
pin_config->pin = s_transport_config.u.spi_hd.pin_reset.pin;
|
||||
break;
|
||||
case H_TRANSPORT_SPI:
|
||||
pin_config->port = s_transport_config.u.spi.pin_reset.port;
|
||||
pin_config->pin = s_transport_config.u.spi.pin_reset.pin;
|
||||
break;
|
||||
case H_TRANSPORT_UART:
|
||||
pin_config->port = s_transport_config.u.uart.pin_reset.port;
|
||||
pin_config->pin = s_transport_config.u.uart.pin_reset.pin;
|
||||
break;
|
||||
case H_TRANSPORT_NONE: // drop through to default case
|
||||
default:
|
||||
// transport config not yet initialised. Use default Reset pin config
|
||||
pin_config->port = H_GPIO_PORT_RESET;
|
||||
pin_config->pin = H_GPIO_PIN_RESET;
|
||||
break;
|
||||
}
|
||||
|
||||
return ESP_TRANSPORT_OK;
|
||||
}
|
||||
|
||||
#if H_TRANSPORT_IN_USE == H_TRANSPORT_SDIO
|
||||
/* SDIO functions */
|
||||
esp_hosted_transport_err_t esp_hosted_sdio_get_config(struct esp_hosted_sdio_config **config)
|
||||
{
|
||||
if (!config) {
|
||||
return ESP_TRANSPORT_ERR_INVALID_ARG;
|
||||
}
|
||||
*config = &s_transport_config.u.sdio;
|
||||
return ESP_TRANSPORT_OK;
|
||||
}
|
||||
|
||||
esp_hosted_transport_err_t esp_hosted_sdio_set_config(struct esp_hosted_sdio_config *config)
|
||||
{
|
||||
struct esp_hosted_sdio_config new_config = config ? *config : INIT_DEFAULT_HOST_SDIO_CONFIG();
|
||||
|
||||
if (esp_hosted_transport_config_set) {
|
||||
if (memcmp(&s_transport_config.u.sdio, &new_config, sizeof(new_config)) == 0) {
|
||||
return ESP_TRANSPORT_OK;
|
||||
}
|
||||
ESP_LOGE(TAG, "Transport already initialized (through constructor?), reconfiguring not allowed");
|
||||
return ESP_TRANSPORT_ERR_ALREADY_SET;
|
||||
}
|
||||
|
||||
s_transport_config.u.sdio = new_config;
|
||||
esp_hosted_transport_config_set = true;
|
||||
s_transport_config.transport_in_use = H_TRANSPORT_SDIO;
|
||||
return ESP_TRANSPORT_OK;
|
||||
}
|
||||
|
||||
esp_hosted_transport_err_t esp_hosted_sdio_iomux_set_config(struct esp_hosted_sdio_config *config)
|
||||
{
|
||||
struct esp_hosted_sdio_config new_config = config ? *config : INIT_DEFAULT_HOST_SDIO_IOMUX_CONFIG();
|
||||
new_config.iomux_enable = true;
|
||||
|
||||
if (esp_hosted_transport_config_set) {
|
||||
if (memcmp(&s_transport_config.u.sdio, &new_config, sizeof(new_config)) == 0) {
|
||||
return ESP_TRANSPORT_OK;
|
||||
}
|
||||
ESP_LOGE(TAG, "Transport already initialized (through constructor?), reconfiguring not allowed");
|
||||
return ESP_TRANSPORT_ERR_ALREADY_SET;
|
||||
}
|
||||
|
||||
s_transport_config.u.sdio = new_config;
|
||||
esp_hosted_transport_config_set = true;
|
||||
s_transport_config.transport_in_use = H_TRANSPORT_SDIO;
|
||||
return ESP_TRANSPORT_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if H_TRANSPORT_IN_USE == H_TRANSPORT_SPI_HD
|
||||
/* SPI Half Duplex functions */
|
||||
esp_hosted_transport_err_t esp_hosted_spi_hd_get_config(struct esp_hosted_spi_hd_config **config)
|
||||
{
|
||||
if (!config) {
|
||||
return ESP_TRANSPORT_ERR_INVALID_ARG;
|
||||
}
|
||||
*config = &s_transport_config.u.spi_hd;
|
||||
return ESP_TRANSPORT_OK;
|
||||
}
|
||||
|
||||
esp_hosted_transport_err_t esp_hosted_spi_hd_set_config(struct esp_hosted_spi_hd_config *config)
|
||||
{
|
||||
struct esp_hosted_spi_hd_config new_config = config ? *config : INIT_DEFAULT_HOST_SPI_HD_CONFIG();
|
||||
|
||||
if (esp_hosted_transport_config_set) {
|
||||
if (memcmp(&s_transport_config.u.spi_hd, &new_config, sizeof(new_config)) == 0) {
|
||||
return ESP_TRANSPORT_OK;
|
||||
}
|
||||
ESP_LOGE(TAG, "Transport already initialized (through constructor?), reconfiguring not allowed");
|
||||
return ESP_TRANSPORT_ERR_ALREADY_SET;
|
||||
}
|
||||
|
||||
s_transport_config.u.spi_hd = new_config;
|
||||
esp_hosted_transport_config_set = true;
|
||||
s_transport_config.transport_in_use = H_TRANSPORT_SPI_HD;
|
||||
return ESP_TRANSPORT_OK;
|
||||
}
|
||||
|
||||
esp_hosted_transport_err_t esp_hosted_spi_hd_2lines_get_config(struct esp_hosted_spi_hd_config **config)
|
||||
{
|
||||
if (!config) {
|
||||
return ESP_TRANSPORT_ERR_INVALID_ARG;
|
||||
}
|
||||
*config = &s_transport_config.u.spi_hd;
|
||||
s_transport_config.u.spi_hd.num_data_lines = 2;
|
||||
return ESP_TRANSPORT_OK;
|
||||
}
|
||||
|
||||
esp_hosted_transport_err_t esp_hosted_spi_hd_2lines_set_config(struct esp_hosted_spi_hd_config *config)
|
||||
{
|
||||
struct esp_hosted_spi_hd_config new_config = config ? *config : INIT_DEFAULT_HOST_SPI_HD_CONFIG();
|
||||
new_config.num_data_lines = 2;
|
||||
|
||||
if (esp_hosted_transport_config_set) {
|
||||
if (memcmp(&s_transport_config.u.spi_hd, &new_config, sizeof(new_config)) == 0) {
|
||||
return ESP_TRANSPORT_OK;
|
||||
}
|
||||
ESP_LOGE(TAG, "Transport already initialized (through constructor?), reconfiguring not allowed");
|
||||
return ESP_TRANSPORT_ERR_ALREADY_SET;
|
||||
}
|
||||
|
||||
s_transport_config.u.spi_hd = new_config;
|
||||
esp_hosted_transport_config_set = true;
|
||||
s_transport_config.transport_in_use = H_TRANSPORT_SPI_HD;
|
||||
return ESP_TRANSPORT_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if H_TRANSPORT_IN_USE == H_TRANSPORT_SPI
|
||||
/* SPI Full Duplex functions */
|
||||
esp_hosted_transport_err_t esp_hosted_spi_get_config(struct esp_hosted_spi_config **config)
|
||||
{
|
||||
if (!config) {
|
||||
return ESP_TRANSPORT_ERR_INVALID_ARG;
|
||||
}
|
||||
*config = &s_transport_config.u.spi;
|
||||
return ESP_TRANSPORT_OK;
|
||||
}
|
||||
|
||||
esp_hosted_transport_err_t esp_hosted_spi_set_config(struct esp_hosted_spi_config *config)
|
||||
{
|
||||
struct esp_hosted_spi_config new_config = config ? *config : INIT_DEFAULT_HOST_SPI_CONFIG();
|
||||
|
||||
if (esp_hosted_transport_config_set) {
|
||||
if (memcmp(&s_transport_config.u.spi, &new_config, sizeof(new_config)) == 0) {
|
||||
return ESP_TRANSPORT_OK;
|
||||
}
|
||||
ESP_LOGE(TAG, "Transport already initialized (through constructor?), reconfiguring not allowed");
|
||||
return ESP_TRANSPORT_ERR_ALREADY_SET;
|
||||
}
|
||||
|
||||
s_transport_config.u.spi = new_config;
|
||||
esp_hosted_transport_config_set = true;
|
||||
s_transport_config.transport_in_use = H_TRANSPORT_SPI;
|
||||
return ESP_TRANSPORT_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if H_TRANSPORT_IN_USE == H_TRANSPORT_UART
|
||||
/* UART functions */
|
||||
esp_hosted_transport_err_t esp_hosted_uart_get_config(struct esp_hosted_uart_config **config)
|
||||
{
|
||||
if (!config) {
|
||||
return ESP_TRANSPORT_ERR_INVALID_ARG;
|
||||
}
|
||||
*config = &s_transport_config.u.uart;
|
||||
return ESP_TRANSPORT_OK;
|
||||
}
|
||||
|
||||
esp_hosted_transport_err_t esp_hosted_uart_set_config(struct esp_hosted_uart_config *config)
|
||||
{
|
||||
struct esp_hosted_uart_config new_config = config ? *config : INIT_DEFAULT_HOST_UART_CONFIG();
|
||||
|
||||
if (esp_hosted_transport_config_set) {
|
||||
if (memcmp(&s_transport_config.u.uart, &new_config, sizeof(new_config)) == 0) {
|
||||
return ESP_TRANSPORT_OK;
|
||||
}
|
||||
ESP_LOGE(TAG, "Transport already initialized (through constructor?), reconfiguring not allowed");
|
||||
return ESP_TRANSPORT_ERR_ALREADY_SET;
|
||||
}
|
||||
|
||||
s_transport_config.u.uart = new_config;
|
||||
esp_hosted_transport_config_set = true;
|
||||
s_transport_config.transport_in_use = H_TRANSPORT_UART;
|
||||
return ESP_TRANSPORT_OK;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,505 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Weak version of esp_wifi API.
|
||||
*
|
||||
* Used when WiFi-Remote does not provide required esp_wifi calls
|
||||
*/
|
||||
|
||||
#include "esp_hosted_api_priv.h"
|
||||
#include "port_esp_hosted_host_config.h"
|
||||
#include "port_esp_hosted_host_wifi_config.h"
|
||||
|
||||
#if H_DPP_SUPPORT
|
||||
#include "esp_dpp.h"
|
||||
#endif
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_init(const wifi_init_config_t *config)
|
||||
{
|
||||
return esp_wifi_remote_init(config);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_deinit(void)
|
||||
{
|
||||
return esp_wifi_remote_deinit();
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_set_mode(wifi_mode_t mode)
|
||||
{
|
||||
return esp_wifi_remote_set_mode(mode);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_get_mode(wifi_mode_t *mode)
|
||||
{
|
||||
return esp_wifi_remote_get_mode(mode);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_start(void)
|
||||
{
|
||||
return esp_wifi_remote_start();
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_stop(void)
|
||||
{
|
||||
return esp_wifi_remote_stop();
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_restore(void)
|
||||
{
|
||||
return esp_wifi_remote_restore();
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_connect(void)
|
||||
{
|
||||
return esp_wifi_remote_connect();
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_disconnect(void)
|
||||
{
|
||||
return esp_wifi_remote_disconnect();
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_clear_fast_connect(void)
|
||||
{
|
||||
return esp_wifi_remote_clear_fast_connect();
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_deauth_sta(uint16_t aid)
|
||||
{
|
||||
return esp_wifi_remote_deauth_sta(aid);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_scan_start(const wifi_scan_config_t *config, bool block)
|
||||
{
|
||||
return esp_wifi_remote_scan_start(config, block);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_set_scan_parameters(const wifi_scan_default_params_t *config)
|
||||
{
|
||||
return esp_wifi_remote_set_scan_parameters(config);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_get_scan_parameters(wifi_scan_default_params_t *config)
|
||||
{
|
||||
return esp_wifi_remote_get_scan_parameters(config);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_scan_stop(void)
|
||||
{
|
||||
return esp_wifi_remote_scan_stop();
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_scan_get_ap_num(uint16_t *number)
|
||||
{
|
||||
return esp_wifi_remote_scan_get_ap_num(number);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_scan_get_ap_record(wifi_ap_record_t *ap_record)
|
||||
{
|
||||
return esp_wifi_remote_scan_get_ap_record(ap_record);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_scan_get_ap_records(uint16_t *number, wifi_ap_record_t *ap_records)
|
||||
{
|
||||
return esp_wifi_remote_scan_get_ap_records(number, ap_records);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_clear_ap_list(void)
|
||||
{
|
||||
return esp_wifi_remote_clear_ap_list();
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_sta_get_ap_info(wifi_ap_record_t *ap_info)
|
||||
{
|
||||
return esp_wifi_remote_sta_get_ap_info(ap_info);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_set_ps(wifi_ps_type_t type)
|
||||
{
|
||||
return esp_wifi_remote_set_ps(type);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_get_ps(wifi_ps_type_t *type)
|
||||
{
|
||||
return esp_wifi_remote_get_ps(type);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_set_protocol(wifi_interface_t ifx, uint8_t protocol_bitmap)
|
||||
{
|
||||
return esp_wifi_remote_set_protocol(ifx, protocol_bitmap);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_get_protocol(wifi_interface_t ifx, uint8_t *protocol_bitmap)
|
||||
{
|
||||
return esp_wifi_remote_get_protocol(ifx, protocol_bitmap);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_set_bandwidth(wifi_interface_t ifx, wifi_bandwidth_t bw)
|
||||
{
|
||||
return esp_wifi_remote_set_bandwidth(ifx, bw);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_get_bandwidth(wifi_interface_t ifx, wifi_bandwidth_t *bw)
|
||||
{
|
||||
return esp_wifi_remote_get_bandwidth(ifx, bw);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_set_channel(uint8_t primary, wifi_second_chan_t second)
|
||||
{
|
||||
return esp_wifi_remote_set_channel(primary, second);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_get_channel(uint8_t *primary, wifi_second_chan_t *second)
|
||||
{
|
||||
return esp_wifi_remote_get_channel(primary, second);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_set_country(const wifi_country_t *country)
|
||||
{
|
||||
return esp_wifi_remote_set_country(country);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_get_country(wifi_country_t *country)
|
||||
{
|
||||
return esp_wifi_remote_get_country(country);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_set_mac(wifi_interface_t ifx, const uint8_t mac[6])
|
||||
{
|
||||
return esp_wifi_remote_set_mac(ifx, mac);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_get_mac(wifi_interface_t ifx, uint8_t mac[6])
|
||||
{
|
||||
return esp_wifi_remote_get_mac(ifx, mac);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_set_config(wifi_interface_t interface, wifi_config_t *conf)
|
||||
{
|
||||
return esp_wifi_remote_set_config(interface, conf);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_get_config(wifi_interface_t interface, wifi_config_t *conf)
|
||||
{
|
||||
return esp_wifi_remote_get_config(interface, conf);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_ap_get_sta_list(wifi_sta_list_t *sta)
|
||||
{
|
||||
return esp_wifi_remote_ap_get_sta_list(sta);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_ap_get_sta_aid(const uint8_t mac[6], uint16_t *aid)
|
||||
{
|
||||
return esp_wifi_remote_ap_get_sta_aid(mac, aid);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_set_storage(wifi_storage_t storage)
|
||||
{
|
||||
return esp_wifi_remote_set_storage(storage);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_set_max_tx_power(int8_t power)
|
||||
{
|
||||
return esp_wifi_remote_set_max_tx_power(power);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_get_max_tx_power(int8_t *power)
|
||||
{
|
||||
return esp_wifi_remote_get_max_tx_power(power);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_set_country_code(const char *country, bool ieee80211d_enabled)
|
||||
{
|
||||
return esp_wifi_remote_set_country_code(country, ieee80211d_enabled);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_get_country_code(char *country)
|
||||
{
|
||||
return esp_wifi_remote_get_country_code(country);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_sta_get_negotiated_phymode(wifi_phy_mode_t *phymode)
|
||||
{
|
||||
return esp_wifi_remote_sta_get_negotiated_phymode(phymode);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_sta_get_aid(uint16_t *aid)
|
||||
{
|
||||
return esp_wifi_remote_sta_get_aid(aid);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_sta_get_rssi(int *rssi)
|
||||
{
|
||||
return esp_wifi_remote_sta_get_rssi(rssi);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_set_inactive_time(wifi_interface_t ifx, uint16_t sec)
|
||||
{
|
||||
return esp_wifi_remote_set_inactive_time(ifx, sec);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_get_inactive_time(wifi_interface_t ifx, uint16_t *sec)
|
||||
{
|
||||
return esp_wifi_remote_get_inactive_time(ifx, sec);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_disable_pmf_config(wifi_interface_t ifx)
|
||||
{
|
||||
return esp_wifi_remote_disable_pmf_config(ifx);
|
||||
}
|
||||
|
||||
#if H_WIFI_HE_SUPPORT
|
||||
H_WEAK_REF esp_err_t esp_wifi_sta_twt_config(wifi_twt_config_t *config)
|
||||
{
|
||||
return esp_wifi_remote_sta_twt_config(config);
|
||||
}
|
||||
|
||||
#if H_WIFI_HE_GREATER_THAN_ESP_IDF_5_3
|
||||
H_WEAK_REF esp_err_t esp_wifi_sta_itwt_setup(wifi_itwt_setup_config_t *setup_config)
|
||||
#else
|
||||
H_WEAK_REF esp_err_t esp_wifi_sta_itwt_setup(wifi_twt_setup_config_t *setup_config)
|
||||
#endif
|
||||
{
|
||||
return esp_wifi_remote_sta_itwt_setup(setup_config);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_sta_itwt_teardown(int flow_id)
|
||||
{
|
||||
return esp_wifi_remote_sta_itwt_teardown(flow_id);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_sta_itwt_suspend(int flow_id, int suspend_time_ms)
|
||||
{
|
||||
return esp_wifi_remote_sta_itwt_suspend(flow_id, suspend_time_ms);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_sta_itwt_get_flow_id_status(int *flow_id_bitmap)
|
||||
{
|
||||
return esp_wifi_remote_sta_itwt_get_flow_id_status(flow_id_bitmap);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_sta_itwt_send_probe_req(int timeout_ms)
|
||||
{
|
||||
return esp_wifi_remote_sta_itwt_send_probe_req(timeout_ms);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_sta_itwt_set_target_wake_time_offset(int offset_us)
|
||||
{
|
||||
return esp_wifi_remote_sta_itwt_set_target_wake_time_offset(offset_us);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if H_WIFI_DUALBAND_SUPPORT
|
||||
H_WEAK_REF esp_err_t esp_wifi_set_band(wifi_band_t band)
|
||||
{
|
||||
return esp_wifi_remote_set_band(band);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_get_band(wifi_band_t *band)
|
||||
{
|
||||
return esp_wifi_remote_get_band(band);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_set_band_mode(wifi_band_mode_t band_mode)
|
||||
{
|
||||
return esp_wifi_remote_set_band_mode(band_mode);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_get_band_mode(wifi_band_mode_t *band_mode)
|
||||
{
|
||||
return esp_wifi_remote_get_band_mode(band_mode);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_set_protocols(wifi_interface_t ifx, wifi_protocols_t *protocols)
|
||||
{
|
||||
return esp_wifi_remote_set_protocols(ifx, protocols);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_get_protocols(wifi_interface_t ifx, wifi_protocols_t *protocols)
|
||||
{
|
||||
return esp_wifi_remote_get_protocols(ifx, protocols);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_set_bandwidths(wifi_interface_t ifx, wifi_bandwidths_t *bw)
|
||||
{
|
||||
return esp_wifi_remote_set_bandwidths(ifx, bw);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_get_bandwidths(wifi_interface_t ifx, wifi_bandwidths_t *bw)
|
||||
{
|
||||
return esp_wifi_remote_get_bandwidths(ifx, bw);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if H_WIFI_ENTERPRISE_SUPPORT
|
||||
H_WEAK_REF esp_err_t esp_wifi_sta_enterprise_enable(void)
|
||||
{
|
||||
return esp_wifi_remote_sta_enterprise_enable();
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_wifi_sta_enterprise_disable(void)
|
||||
{
|
||||
return esp_wifi_remote_sta_enterprise_disable();
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_eap_client_set_identity(const unsigned char *identity, int len)
|
||||
{
|
||||
return esp_eap_client_remote_set_identity(identity, len);
|
||||
}
|
||||
|
||||
H_WEAK_REF void esp_eap_client_clear_identity(void)
|
||||
{
|
||||
esp_eap_client_remote_clear_identity();
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_eap_client_set_username(const unsigned char *username, int len)
|
||||
{
|
||||
return esp_eap_client_remote_set_username(username, len);
|
||||
}
|
||||
|
||||
H_WEAK_REF void esp_eap_client_clear_username(void)
|
||||
{
|
||||
esp_eap_client_remote_clear_username();
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_eap_client_set_password(const unsigned char *password, int len)
|
||||
{
|
||||
return esp_eap_client_remote_set_password(password, len);
|
||||
}
|
||||
|
||||
H_WEAK_REF void esp_eap_client_clear_password(void)
|
||||
{
|
||||
esp_eap_client_remote_clear_password();
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_eap_client_set_new_password(const unsigned char *new_password, int len)
|
||||
{
|
||||
return esp_eap_client_remote_set_new_password(new_password, len);
|
||||
}
|
||||
|
||||
H_WEAK_REF void esp_eap_client_clear_new_password(void)
|
||||
{
|
||||
esp_eap_client_remote_clear_new_password();
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_eap_client_set_ca_cert(const unsigned char *ca_cert, int ca_cert_len)
|
||||
{
|
||||
return esp_eap_client_remote_set_ca_cert(ca_cert, ca_cert_len);
|
||||
}
|
||||
|
||||
H_WEAK_REF void esp_eap_client_clear_ca_cert(void)
|
||||
{
|
||||
esp_eap_client_remote_clear_ca_cert();
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_eap_client_set_certificate_and_key(const unsigned char *client_cert, int client_cert_len,
|
||||
const unsigned char *private_key, int private_key_len,
|
||||
const unsigned char *private_key_password, int private_key_passwd_len)
|
||||
{
|
||||
return esp_eap_client_remote_set_certificate_and_key(client_cert, client_cert_len,
|
||||
private_key, private_key_len,
|
||||
private_key_password, private_key_passwd_len);
|
||||
}
|
||||
|
||||
H_WEAK_REF void esp_eap_client_clear_certificate_and_key(void)
|
||||
{
|
||||
esp_eap_client_remote_clear_certificate_and_key();
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_eap_client_set_disable_time_check(bool disable)
|
||||
{
|
||||
return esp_eap_client_remote_set_disable_time_check(disable);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_eap_client_get_disable_time_check(bool *disable)
|
||||
{
|
||||
return esp_eap_client_remote_get_disable_time_check(disable);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_eap_client_set_ttls_phase2_method(esp_eap_ttls_phase2_types type)
|
||||
{
|
||||
return esp_eap_client_remote_set_ttls_phase2_method(type);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_eap_client_set_suiteb_192bit_certification(bool enable)
|
||||
{
|
||||
return esp_eap_client_remote_set_suiteb_192bit_certification(enable);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_eap_client_set_pac_file(const unsigned char *pac_file, int pac_file_len)
|
||||
{
|
||||
return esp_eap_client_remote_set_pac_file(pac_file, pac_file_len);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_eap_client_set_fast_params(esp_eap_fast_config config)
|
||||
{
|
||||
return esp_eap_client_remote_set_fast_params(config);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_eap_client_use_default_cert_bundle(bool use_default_bundle)
|
||||
{
|
||||
return esp_eap_client_remote_use_default_cert_bundle(use_default_bundle);
|
||||
}
|
||||
|
||||
H_WEAK_REF void esp_wifi_set_okc_support(bool enable)
|
||||
{
|
||||
esp_wifi_remote_set_okc_support(enable);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_eap_client_set_domain_name(const char *domain_name)
|
||||
{
|
||||
return esp_eap_client_remote_set_domain_name(domain_name);
|
||||
}
|
||||
|
||||
#if H_GOT_SET_EAP_METHODS_API
|
||||
H_WEAK_REF esp_err_t esp_eap_client_set_eap_methods(esp_eap_method_t methods)
|
||||
{
|
||||
return esp_eap_client_remote_set_eap_methods(methods);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if H_DPP_SUPPORT
|
||||
/**
|
||||
* Weak version of esp_dpp API
|
||||
*/
|
||||
#if H_SUPP_DPP_SUPPORT
|
||||
H_WEAK_REF esp_err_t esp_supp_dpp_init(esp_supp_dpp_event_cb_t evt_cb)
|
||||
{
|
||||
return esp_supp_remote_dpp_init(evt_cb);
|
||||
}
|
||||
#else
|
||||
H_WEAK_REF esp_err_t esp_supp_dpp_init(void)
|
||||
{
|
||||
return esp_supp_remote_dpp_init();
|
||||
}
|
||||
#endif
|
||||
|
||||
H_WEAK_REF esp_err_t esp_supp_dpp_deinit(void)
|
||||
{
|
||||
return esp_supp_remote_dpp_deinit();
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_supp_dpp_bootstrap_gen(const char *chan_list,
|
||||
esp_supp_dpp_bootstrap_t type,
|
||||
const char *key, const char *info)
|
||||
{
|
||||
return esp_supp_remote_dpp_bootstrap_gen(chan_list, type, key, info);
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_supp_dpp_start_listen(void)
|
||||
{
|
||||
return esp_supp_remote_dpp_start_listen();
|
||||
}
|
||||
|
||||
H_WEAK_REF esp_err_t esp_supp_dpp_stop_listen(void)
|
||||
{
|
||||
return esp_supp_remote_dpp_stop_listen();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __HOSTED_HCI_DRV_H
|
||||
#define __HOSTED_HCI_DRV_H
|
||||
|
||||
#include "port_esp_hosted_host_bt_config.h"
|
||||
|
||||
void hci_drv_init(void);
|
||||
|
||||
void hci_drv_show_configuration(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "hci_drv.h"
|
||||
|
||||
#include "esp_hosted_log.h"
|
||||
static const char TAG[] = "hci_stub_drv";
|
||||
|
||||
#if H_BT_HOST_ESP_NIMBLE
|
||||
#include "host/ble_hs_mbuf.h"
|
||||
#include "nimble/transport.h"
|
||||
#endif
|
||||
|
||||
#include "esp_hosted_bt.h"
|
||||
#include "port_esp_hosted_host_os.h"
|
||||
|
||||
#if H_BT_HOST_ESP_BLUEDROID
|
||||
#include "esp_hosted_bluedroid.h"
|
||||
#endif
|
||||
|
||||
#define WEAK __attribute__((weak))
|
||||
|
||||
H_WEAK_REF int hci_rx_handler(uint8_t *buf, size_t buf_len)
|
||||
{
|
||||
/* Hosted transport received BT packets, but Hosted was not
|
||||
* configured to handle BT packets. Drop them.
|
||||
*/
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void hci_drv_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void hci_drv_show_configuration(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Host BT Support: Disabled");
|
||||
}
|
||||
|
||||
#if H_BT_HOST_ESP_NIMBLE
|
||||
/**
|
||||
* ESP NimBLE expects these interfaces for Tx
|
||||
*
|
||||
* There are marked as weak references:
|
||||
*
|
||||
* - to allow ESP NimBLE BT Host code to override the functions if
|
||||
* NimBLE BT Host is configured to act as the HCI transport
|
||||
*
|
||||
* - to allow the User to use their own ESP NimBLE HCI transport code
|
||||
* without causing linker errors from Hosted
|
||||
*
|
||||
* - to allow Hosted code to build without linker errors if ESP NimBLE
|
||||
* BT Host is enabled, but Hosted is not configured as HCI transport
|
||||
* and there is no other ESP NimBLE HCI transport code being
|
||||
* used. In this case, the stub functions are used and drops the
|
||||
* incoming data.
|
||||
*/
|
||||
|
||||
WEAK void ble_transport_ll_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
WEAK void ble_transport_ll_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
WEAK int ble_transport_to_ll_acl_impl(struct os_mbuf *om)
|
||||
{
|
||||
os_mbuf_free_chain(om);
|
||||
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
WEAK int ble_transport_to_ll_cmd_impl(void *buf)
|
||||
{
|
||||
ble_transport_free(buf);
|
||||
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif // H_BT_HOST_ESP_NIMBLE
|
||||
|
||||
#if H_BT_HOST_ESP_BLUEDROID
|
||||
WEAK void hosted_hci_bluedroid_open(void)
|
||||
{
|
||||
}
|
||||
|
||||
WEAK void hosted_hci_bluedroid_close(void)
|
||||
{
|
||||
}
|
||||
|
||||
WEAK void hosted_hci_bluedroid_send(uint8_t *data, uint16_t len)
|
||||
{
|
||||
}
|
||||
|
||||
WEAK bool hosted_hci_bluedroid_check_send_available(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
WEAK esp_err_t hosted_hci_bluedroid_register_host_callback(const esp_bluedroid_hci_driver_callbacks_t *callback)
|
||||
{
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif // H_BT_HOST_ESP_BLUEDROID
|
||||
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "esp_hosted_transport.h"
|
||||
#include "esp_hosted_os_abstraction.h"
|
||||
#include "transport_drv.h"
|
||||
#include "port_esp_hosted_host_os.h"
|
||||
#include "hci_drv.h"
|
||||
|
||||
#ifndef __WEAK__
|
||||
# if defined(__GNUC__) || defined(__clang__)
|
||||
# define __WEAK__ __attribute__((weak))
|
||||
# elif defined(_MSC_VER)
|
||||
# define __WEAK__ __declspec(selectany)
|
||||
# else
|
||||
# define __WEAK__
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#if H_BT_HOST_ESP_NIMBLE
|
||||
#include "host/ble_hs_mbuf.h"
|
||||
#include "os/os_mbuf.h"
|
||||
#include "nimble/transport.h"
|
||||
#include "nimble/transport/hci_h4.h"
|
||||
#include "nimble/hci_common.h"
|
||||
#endif
|
||||
|
||||
#include "esp_hosted_bt.h"
|
||||
|
||||
#if H_BT_HOST_ESP_BLUEDROID
|
||||
#include "esp_hosted_bluedroid.h"
|
||||
#endif
|
||||
|
||||
#include "esp_hosted_log.h"
|
||||
static const char TAG[] = "vhci_drv";
|
||||
|
||||
#if H_BT_HOST_ESP_NIMBLE
|
||||
#define BLE_HCI_EVENT_HDR_LEN (2)
|
||||
#define BLE_HCI_CMD_HDR_LEN (3)
|
||||
#endif
|
||||
|
||||
void hci_drv_init(void)
|
||||
{
|
||||
// do nothing for VHCI: underlying transport should be ready
|
||||
}
|
||||
|
||||
void hci_drv_show_configuration(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Host BT Support: Enabled");
|
||||
ESP_LOGI(TAG, "\tBT Transport Type: VHCI");
|
||||
}
|
||||
|
||||
#if H_BT_HOST_ESP_NIMBLE
|
||||
/**
|
||||
* HCI_H4_xxx is the first byte of the received data
|
||||
*/
|
||||
H_WEAK_REF int hci_rx_handler(uint8_t *buf, size_t buf_len)
|
||||
{
|
||||
uint8_t * data = buf;
|
||||
uint32_t len_total_read = buf_len;
|
||||
|
||||
int rc;
|
||||
|
||||
if (data[0] == HCI_H4_EVT) {
|
||||
uint8_t *evbuf;
|
||||
int totlen;
|
||||
|
||||
totlen = BLE_HCI_EVENT_HDR_LEN + data[2];
|
||||
if (totlen > UINT8_MAX + BLE_HCI_EVENT_HDR_LEN) {
|
||||
ESP_LOGE(TAG, "Rx: len[%d] > max INT [%d], drop",
|
||||
totlen, UINT8_MAX + BLE_HCI_EVENT_HDR_LEN);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (totlen > MYNEWT_VAL(BLE_TRANSPORT_EVT_SIZE)) {
|
||||
ESP_LOGE(TAG, "Rx: len[%d] > max BLE [%d], drop",
|
||||
totlen, MYNEWT_VAL(BLE_TRANSPORT_EVT_SIZE));
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (data[1] == BLE_HCI_EVCODE_HW_ERROR) {
|
||||
ESP_LOGE(TAG, "Rx: HW_ERROR");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* Allocate LE Advertising Report Event from lo pool only */
|
||||
if ((data[1] == BLE_HCI_EVCODE_LE_META) &&
|
||||
(data[3] == BLE_HCI_LE_SUBEV_ADV_RPT || data[3] == BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) {
|
||||
evbuf = ble_transport_alloc_evt(1);
|
||||
/* Skip advertising report if we're out of memory */
|
||||
if (!evbuf) {
|
||||
ESP_LOGW(TAG, "Rx: Drop ADV Report Event: NimBLE OOM (not fatal)");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
} else {
|
||||
evbuf = ble_transport_alloc_evt(0);
|
||||
if (!evbuf) {
|
||||
ESP_LOGE(TAG, "Rx: failed transport_alloc_evt(0)");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
memset(evbuf, 0, sizeof * evbuf);
|
||||
memcpy(evbuf, &data[1], totlen);
|
||||
|
||||
rc = ble_transport_to_hs_evt(evbuf);
|
||||
if (rc) {
|
||||
ESP_LOGE(TAG, "Rx: transport_to_hs_evt failed");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
} else if (data[0] == HCI_H4_ACL) {
|
||||
struct os_mbuf *m = NULL;
|
||||
|
||||
m = ble_transport_alloc_acl_from_ll();
|
||||
if (!m) {
|
||||
ESP_LOGE(TAG, "Rx: alloc_acl_from_ll failed");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if ((rc = os_mbuf_append(m, &data[1], len_total_read - 1)) != 0) {
|
||||
ESP_LOGE(TAG, "Rx: failed os_mbuf_append; rc = %d", rc);
|
||||
os_mbuf_free_chain(m);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ble_transport_to_hs_acl(m);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* ESP NimBLE expects these interfaces for Tx
|
||||
*
|
||||
* For doing non-zero copy:
|
||||
* - transport expects the HCI_H4_xxx type to be the first byte of the
|
||||
* data stream
|
||||
*
|
||||
* For doing zero copy:
|
||||
* - fill in esp_paylod_header and payload data
|
||||
* - HCI_H4_xxx type should be set in esp_payload_header.hci_pkt_type
|
||||
*/
|
||||
|
||||
#if H_BT_ENABLE_LL_INIT
|
||||
void ble_transport_ll_init(void)
|
||||
{
|
||||
ESP_ERROR_CHECK(transport_drv_reconfigure());
|
||||
}
|
||||
|
||||
void ble_transport_ll_deinit(void)
|
||||
{
|
||||
// transport may still be in used for other data (serial, Wi-Fi, ...)
|
||||
}
|
||||
#endif
|
||||
|
||||
int ble_transport_to_ll_acl_impl(struct os_mbuf *om)
|
||||
{
|
||||
// TODO: zerocopy version
|
||||
|
||||
// calculate data length from the incoming data
|
||||
int data_len = OS_MBUF_PKTLEN(om) + 1;
|
||||
|
||||
uint8_t * data = NULL;
|
||||
int res;
|
||||
|
||||
data = g_h.funcs->_h_malloc_align(data_len, HOSTED_MEM_ALIGNMENT_64);
|
||||
if (!data) {
|
||||
ESP_LOGE(TAG, "Tx %s: malloc failed", __func__);
|
||||
res = ESP_FAIL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
data[0] = HCI_H4_ACL;
|
||||
res = ble_hs_mbuf_to_flat(om, &data[1], OS_MBUF_PKTLEN(om), NULL);
|
||||
if (res) {
|
||||
ESP_LOGE(TAG, "Tx: Error copying HCI_H4_ACL data %d", res);
|
||||
os_mbuf_free_chain(om);
|
||||
g_h.funcs->_h_free_align(data);
|
||||
res = ESP_FAIL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
res = esp_hosted_tx(ESP_HCI_IF, 0, data, data_len, H_BUFF_NO_ZEROCOPY, data, H_DEFLT_FREE_FUNC, 0);
|
||||
|
||||
exit:
|
||||
os_mbuf_free_chain(om);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int ble_transport_to_ll_cmd_impl(void *buf)
|
||||
{
|
||||
// TODO: zerocopy version
|
||||
|
||||
// calculate data length from the incoming data
|
||||
int buf_len = 3 + ((uint8_t *)buf)[2] + 1;
|
||||
|
||||
uint8_t * data = NULL;
|
||||
int res;
|
||||
|
||||
data = g_h.funcs->_h_malloc_align(buf_len, HOSTED_MEM_ALIGNMENT_64);
|
||||
if (!data) {
|
||||
ESP_LOGE(TAG, "Tx %s: malloc failed", __func__);
|
||||
res = ESP_FAIL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
data[0] = HCI_H4_CMD;
|
||||
memcpy(&data[1], buf, buf_len - 1);
|
||||
|
||||
res = esp_hosted_tx(ESP_HCI_IF, 0, data, buf_len, H_BUFF_NO_ZEROCOPY, data, H_DEFLT_FREE_FUNC, 0);
|
||||
|
||||
exit:
|
||||
ble_transport_free(buf);
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif // H_BT_HOST_ESP_NIMBLE
|
||||
|
||||
#if H_BT_HOST_ESP_BLUEDROID
|
||||
static esp_bluedroid_hci_driver_callbacks_t s_callback = { 0 };
|
||||
|
||||
H_WEAK_REF int hci_rx_handler(uint8_t *buf, size_t buf_len)
|
||||
{
|
||||
uint8_t * data = buf;
|
||||
uint32_t len_total_read = buf_len;
|
||||
|
||||
if (s_callback.notify_host_recv) {
|
||||
s_callback.notify_host_recv(data, len_total_read);
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void hosted_hci_bluedroid_open(void)
|
||||
{
|
||||
ESP_ERROR_CHECK(transport_drv_reconfigure());
|
||||
}
|
||||
|
||||
void hosted_hci_bluedroid_close(void)
|
||||
{
|
||||
}
|
||||
|
||||
esp_err_t hosted_hci_bluedroid_register_host_callback(const esp_bluedroid_hci_driver_callbacks_t *callback)
|
||||
{
|
||||
s_callback.notify_host_send_available = callback->notify_host_send_available;
|
||||
s_callback.notify_host_recv = callback->notify_host_recv;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void hosted_hci_bluedroid_send(uint8_t *data, uint16_t len)
|
||||
{
|
||||
int res;
|
||||
uint8_t * ptr = NULL;
|
||||
|
||||
ptr = g_h.funcs->_h_malloc_align(len, HOSTED_MEM_ALIGNMENT_64);
|
||||
if (!ptr) {
|
||||
ESP_LOGE(TAG, "%s: malloc failed", __func__);
|
||||
return;
|
||||
}
|
||||
memcpy(ptr, data, len);
|
||||
|
||||
res = esp_hosted_tx(ESP_HCI_IF, 0, ptr, len, H_BUFF_NO_ZEROCOPY, ptr, H_DEFLT_FREE_FUNC, 0);
|
||||
|
||||
if (res) {
|
||||
ESP_LOGE(TAG, "%s: Tx failed", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
bool hosted_hci_bluedroid_check_send_available(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // H_BT_HOST_ESP_BLUEDROID
|
||||
@@ -0,0 +1,387 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/** Includes **/
|
||||
#include "esp_log.h"
|
||||
#include "esp_hosted_log.h"
|
||||
#include "power_save_drv.h"
|
||||
#include "stats.h"
|
||||
#include "transport_drv.h"
|
||||
#include "port_esp_hosted_host_config.h"
|
||||
#include "port_esp_hosted_host_os.h"
|
||||
#include "esp_hosted_power_save.h"
|
||||
#include "esp_hosted_transport_config.h"
|
||||
#include "esp_hosted_misc.h"
|
||||
|
||||
static const char TAG[] = "H_power_save";
|
||||
|
||||
static uint8_t power_save_on;
|
||||
|
||||
static uint8_t power_save_drv_init_done;
|
||||
|
||||
/* Add state tracking */
|
||||
static volatile bool reset_in_progress = false;
|
||||
static volatile uint32_t last_gpio_event_time = 0;
|
||||
static volatile uint32_t last_wakeup_time = 0;
|
||||
#if H_HOST_PS_ALLOWED && H_HOST_WAKEUP_GPIO != -1
|
||||
/* ISR handler for wakeup GPIO */
|
||||
static void IRAM_ATTR wakeup_gpio_isr_handler(void* arg)
|
||||
{
|
||||
uint32_t current_time = g_h.funcs->_h_get_time_ms(); // ms
|
||||
|
||||
/* Ignore ISR triggers immediately after wake-up to prevent glitches */
|
||||
if (current_time - last_wakeup_time < 500) { // 500ms grace period after wake-up
|
||||
return;
|
||||
}
|
||||
|
||||
if (!power_save_on && !reset_in_progress) {
|
||||
|
||||
int current_level = g_h.funcs->_h_read_gpio(H_HOST_WAKEUP_GPIO_PORT, H_HOST_WAKEUP_GPIO);
|
||||
|
||||
/* Double check GPIO level and state before reset */
|
||||
if (current_level == H_HOST_WAKEUP_GPIO_LEVEL) {
|
||||
ESP_EARLY_LOGW(TAG, "Slave reset detected via wakeup GPIO, level: %d", current_level);
|
||||
ESP_EARLY_LOGE(TAG, "------------------ Resetting host -----------------");
|
||||
|
||||
/* Set flag to prevent re-entry */
|
||||
reset_in_progress = true;
|
||||
|
||||
/* Disable interrupt and remove handler before reset */
|
||||
g_h.funcs->_h_teardown_gpio_interrupt(H_HOST_WAKEUP_GPIO_PORT, H_HOST_WAKEUP_GPIO);
|
||||
|
||||
/* Force power save off and trigger reset */
|
||||
g_h.funcs->_h_restart_host();
|
||||
}
|
||||
} else {
|
||||
ESP_EARLY_LOGW(TAG, "Power save is on or reset in progress");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if H_HOST_PS_ALLOWED
|
||||
#if H_HOST_WAKEUP_GPIO
|
||||
static int register_slave_reboot_callback(void *gpio_port, uint32_t gpio_num, int level)
|
||||
{
|
||||
int ret = g_h.funcs->_h_config_gpio_as_interrupt(gpio_port, gpio_num, level, wakeup_gpio_isr_handler, NULL);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to add GPIO ISR handler, err %d", ret);
|
||||
return -1;
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Initialized host_wakeup/slave_reset GPIO %" PRIu32 , gpio_num);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Initialize power save driver and configure GPIO for slave reset detection */
|
||||
int esp_hosted_power_save_init(void)
|
||||
{
|
||||
|
||||
if (power_save_drv_init_done) {
|
||||
ESP_LOGI(TAG, "Power save driver already initialized");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if H_HOST_PS_ALLOWED
|
||||
#if H_HOST_WAKEUP_GPIO
|
||||
|
||||
uint32_t gpio_num = H_HOST_WAKEUP_GPIO;
|
||||
void *gpio_port = H_HOST_WAKEUP_GPIO_PORT;
|
||||
int level = H_HOST_WAKEUP_GPIO_LEVEL;
|
||||
|
||||
ESP_LOGI(TAG, "power_save_drv_init with gpio_num: %" PRIu32, gpio_num);
|
||||
|
||||
/* Reset state flags */
|
||||
power_save_on = 0;
|
||||
reset_in_progress = false;
|
||||
|
||||
/* Configure wakeup GPIO as input for deep sleep wakeup */
|
||||
g_h.funcs->_h_config_gpio(gpio_port, gpio_num, H_GPIO_MODE_DEF_INPUT);
|
||||
|
||||
int initial_level = g_h.funcs->_h_read_gpio(gpio_port, gpio_num);
|
||||
ESP_LOGI(TAG, "Power save wakeup GPIO initial level: %d", initial_level);
|
||||
|
||||
g_h.funcs->_h_write_gpio(gpio_port, gpio_num, !level);
|
||||
g_h.funcs->_h_msleep(200); /* to stabilize the level */
|
||||
|
||||
ESP_LOGI(TAG, "Initialized power save wakeup GPIO %" PRIu32, gpio_num);
|
||||
|
||||
/* Only proceed with ISR setup if conditions are right */
|
||||
if (!power_save_on) {
|
||||
register_slave_reboot_callback(gpio_port, gpio_num, level);
|
||||
}
|
||||
#else
|
||||
ESP_LOGI(TAG, "power save driver not enabled at host/slave");
|
||||
return -1;
|
||||
#endif
|
||||
power_save_drv_init_done = 1;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int esp_hosted_power_save_deinit(void)
|
||||
{
|
||||
#if H_HOST_PS_ALLOWED
|
||||
if (power_save_on) {
|
||||
ESP_LOGE(TAG, "Power save is on, cannot deinit");
|
||||
return -1;
|
||||
}
|
||||
power_save_drv_init_done = 0;
|
||||
#endif
|
||||
|
||||
#if H_HOST_PS_ALLOWED && H_HOST_WAKEUP_GPIO != -1
|
||||
g_h.funcs->_h_teardown_gpio_interrupt(H_HOST_WAKEUP_GPIO_PORT, H_HOST_WAKEUP_GPIO);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int esp_hosted_power_save_enabled(void)
|
||||
{
|
||||
#if H_HOST_PS_ALLOWED
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int esp_hosted_woke_from_power_save(void)
|
||||
{
|
||||
#if H_HOST_PS_ALLOWED
|
||||
int reason = g_h.funcs->_h_get_host_wakeup_or_reboot_reason();
|
||||
if (reason == HOSTED_WAKEUP_DEEP_SLEEP) {
|
||||
ESP_LOGI(TAG, "Wakeup from power save");
|
||||
return 1;
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Wakeup using reason: %d", reason);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int esp_hosted_power_saving(void)
|
||||
{
|
||||
#if H_HOST_PS_ALLOWED
|
||||
return power_save_on;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#include "esp_hosted_transport_init.h"
|
||||
#include "sdio_drv.h"
|
||||
esp_err_t sdio_generate_slave_intr(uint8_t intr_no);
|
||||
|
||||
#if H_HOST_PS_ALLOWED
|
||||
static int notify_slave_host_power_save_start(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Inform slave: Host PS start");
|
||||
return bus_inform_slave_host_power_save_start();
|
||||
}
|
||||
|
||||
|
||||
static int notify_slave_host_power_save_stop(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Inform slave: Host PS stop");
|
||||
return bus_inform_slave_host_power_save_stop();
|
||||
}
|
||||
#endif
|
||||
|
||||
int hold_slave_reset_gpio_pre_power_save(void)
|
||||
{
|
||||
#if H_HOST_PS_ALLOWED
|
||||
gpio_pin_t reset_pin = { .port = H_GPIO_PORT_RESET, .pin = H_GPIO_PIN_RESET };
|
||||
|
||||
if (ESP_TRANSPORT_OK != esp_hosted_transport_get_reset_config(&reset_pin)) {
|
||||
ESP_LOGE(TAG, "Unable to get RESET config for transport");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(reset_pin.pin == -1) {
|
||||
ESP_LOGE(TAG, "RESET pin is not configured");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return g_h.funcs->_h_hold_gpio(reset_pin.port, reset_pin.pin, H_ENABLE);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int release_slave_reset_gpio_post_wakeup(void)
|
||||
{
|
||||
#if H_HOST_PS_ALLOWED
|
||||
gpio_pin_t reset_pin = { .port = H_GPIO_PORT_RESET, .pin = H_GPIO_PIN_RESET };
|
||||
|
||||
if (ESP_TRANSPORT_OK != esp_hosted_transport_get_reset_config(&reset_pin)) {
|
||||
ESP_LOGE(TAG, "Unable to get RESET config for transport");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(reset_pin.pin == -1) {
|
||||
ESP_LOGE(TAG, "RESET pin is not configured");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return g_h.funcs->_h_hold_gpio(reset_pin.port, reset_pin.pin, H_DISABLE);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int esp_hosted_power_save_start(esp_hosted_power_save_type_t power_save_type)
|
||||
{
|
||||
|
||||
if (power_save_on)
|
||||
return 0;
|
||||
|
||||
if (!power_save_drv_init_done) {
|
||||
ESP_LOGE(TAG, "Power save driver not initialized, might be disabled at host/slave");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if H_HOST_PS_ALLOWED
|
||||
void* sleep_gpio_port = H_HOST_WAKEUP_GPIO_PORT;
|
||||
int sleep_gpio = H_HOST_WAKEUP_GPIO;
|
||||
int ret = 0;
|
||||
|
||||
if (power_save_type != HOSTED_POWER_SAVE_TYPE_DEEP_SLEEP) {
|
||||
ESP_LOGE(TAG, "Invalid or not supported power save type: %d", power_save_type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Inform slave, host power save is started */
|
||||
if (notify_slave_host_power_save_start()) {
|
||||
ESP_LOGE(TAG, "Failed to notify slave, host power save is started");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (reset_in_progress) {
|
||||
ESP_LOGE(TAG, "Reset in progress is set");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Clear prior configured interrupt */
|
||||
g_h.funcs->_h_teardown_gpio_interrupt(sleep_gpio_port, sleep_gpio);
|
||||
|
||||
/* Hold reset pin of slave */
|
||||
if (hold_slave_reset_gpio_pre_power_save()) {
|
||||
ESP_LOGE(TAG, "Failed to hold reset pin of slave");
|
||||
return -1;
|
||||
}
|
||||
|
||||
g_h.funcs->_h_msleep(50);
|
||||
|
||||
/* Configure GPIO for deep sleep wakeup */
|
||||
ret = g_h.funcs->_h_config_host_power_save_hal_impl(power_save_type, sleep_gpio_port, sleep_gpio, H_HOST_WAKEUP_GPIO_LEVEL);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "Failed to enable deep sleep wakeup for GPIO %d", sleep_gpio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Lower GPIO to non-sleepable edge */
|
||||
if (sleep_gpio != -1) {
|
||||
g_h.funcs->_h_write_gpio(sleep_gpio_port, sleep_gpio, !H_HOST_WAKEUP_GPIO_LEVEL);
|
||||
}
|
||||
|
||||
/* Disable pull-up and configure pull-down based on wakeup level */
|
||||
if (H_HOST_WAKEUP_GPIO_LEVEL) {
|
||||
g_h.funcs->_h_pull_gpio(sleep_gpio_port, sleep_gpio, H_GPIO_PULL_UP, H_DISABLE);
|
||||
g_h.funcs->_h_pull_gpio(sleep_gpio_port, sleep_gpio, H_GPIO_PULL_DOWN, H_ENABLE);
|
||||
} else {
|
||||
g_h.funcs->_h_pull_gpio(sleep_gpio_port, sleep_gpio, H_GPIO_PULL_DOWN, H_DISABLE);
|
||||
g_h.funcs->_h_pull_gpio(sleep_gpio_port, sleep_gpio, H_GPIO_PULL_UP, H_ENABLE);
|
||||
}
|
||||
|
||||
power_save_on = 1;
|
||||
|
||||
/* Start host power save with port layer */
|
||||
g_h.funcs->_h_start_host_power_save_hal_impl(power_save_type);
|
||||
|
||||
|
||||
while (1) {
|
||||
g_h.funcs->_h_msleep(1000);
|
||||
/* dead loop */
|
||||
}
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
int stop_host_power_save(void)
|
||||
{
|
||||
|
||||
#if H_HOST_PS_ALLOWED
|
||||
/* Inform slave, host power save is stopped */
|
||||
if (notify_slave_host_power_save_stop()) {
|
||||
ESP_LOGE(TAG, "Failed to notify slave, host power save is stopped");
|
||||
return -1;
|
||||
}
|
||||
|
||||
power_save_on = 0;
|
||||
last_wakeup_time = g_h.funcs->_h_get_time_ms(); // Record wake-up time
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if H_HOST_PS_ALLOWED
|
||||
static esp_timer_handle_t timer_handle = NULL;
|
||||
|
||||
static void power_save_timer_callback(void *arg)
|
||||
{
|
||||
ESP_LOGI(TAG, "Firing power save as timer expiry");
|
||||
esp_hosted_power_save_start(HOSTED_POWER_SAVE_TYPE_DEEP_SLEEP);
|
||||
}
|
||||
#endif
|
||||
int esp_hosted_power_save_timer_start(uint32_t time_ms)
|
||||
{
|
||||
|
||||
#if H_HOST_PS_ALLOWED
|
||||
int err = 0;
|
||||
|
||||
if (time_ms == 0) {
|
||||
ESP_LOGE(TAG, "Timer duration is 0, not starting timer");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (timer_handle) {
|
||||
ESP_LOGW(TAG, "Timer already exists");
|
||||
err = g_h.funcs->_h_timer_stop(timer_handle);
|
||||
if (err != 0) {
|
||||
ESP_LOGE(TAG, "Failed to stop timer");
|
||||
}
|
||||
timer_handle = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
timer_handle = g_h.funcs->_h_timer_start("power_save_timer", time_ms, H_TIMER_TYPE_ONESHOT, power_save_timer_callback, NULL);
|
||||
if (err != 0) {
|
||||
ESP_LOGE(TAG, "Failed to start timer");
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int esp_hosted_power_save_timer_stop(void)
|
||||
{
|
||||
#if H_HOST_PS_ALLOWED
|
||||
int err = 0;
|
||||
if (!timer_handle) {
|
||||
ESP_LOGW(TAG, "No timer exists");
|
||||
return -1;
|
||||
}
|
||||
err = g_h.funcs->_h_timer_stop(timer_handle);
|
||||
if (err != 0) {
|
||||
ESP_LOGE(TAG, "Failed to stop timer");
|
||||
return err;
|
||||
}
|
||||
timer_handle = NULL;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* This file is internal to ESP-Hosted */
|
||||
|
||||
#ifndef __POWER_SAVE_DRV_H
|
||||
#define __POWER_SAVE_DRV_H
|
||||
|
||||
/**
|
||||
* @brief Stops the host power save mode.
|
||||
* @note This is an internal function called during the wake-up sequence.
|
||||
*
|
||||
* @return int Returns 0 on success, or a nonzero value on failure.
|
||||
*/
|
||||
int stop_host_power_save(void);
|
||||
|
||||
/**
|
||||
* @brief Holds the slave reset GPIO before deep sleep.
|
||||
* @note Holding the slave reset GPIO before deep sleep is required,
|
||||
* to ensure that the slave doesn't reset during deep sleep.
|
||||
* However, this would consume some power.
|
||||
*
|
||||
* @return int Returns 0 on success, or a nonzero value on failure.
|
||||
*/
|
||||
int hold_slave_reset_gpio_pre_deep_sleep(void);
|
||||
|
||||
/**
|
||||
* @brief Releases the slave reset GPIO after wakeup from deep sleep.
|
||||
*
|
||||
* @return int Returns 0 on success, or a nonzero value on failure.
|
||||
*/
|
||||
int release_slave_reset_gpio_post_wakeup(void);
|
||||
|
||||
#endif /* __POWER_SAVE_DRV_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __RPC_CORE_H
|
||||
#define __RPC_CORE_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "transport_drv.h"
|
||||
#include "rpc_slave_if.h"
|
||||
#include "port_esp_hosted_host_log.h"
|
||||
#include "port_esp_hosted_host_config.h"
|
||||
|
||||
#ifndef BIT
|
||||
#define BIT(n) (1UL << (n))
|
||||
#endif
|
||||
|
||||
#define MAX_SSID_LENGTH 32
|
||||
#define MIN_PWD_LENGTH 8
|
||||
#define MAX_PWD_LENGTH 64
|
||||
#define MIN_CHNL_NO 1
|
||||
#define MAX_CHNL_NO 11
|
||||
#define MIN_CONN_NO 1
|
||||
#define MAX_CONN_NO 10
|
||||
|
||||
#define CLEANUP_APP_MSG(app_msg) do { \
|
||||
if (app_msg) { \
|
||||
if (app_msg->app_free_buff_hdl) { \
|
||||
if (app_msg->app_free_buff_func) { \
|
||||
app_msg->app_free_buff_func(app_msg->app_free_buff_hdl); \
|
||||
app_msg->app_free_buff_hdl = NULL; \
|
||||
} \
|
||||
} \
|
||||
HOSTED_FREE(app_msg); \
|
||||
} \
|
||||
} while(0);
|
||||
|
||||
#define RPC_FAIL_ON_NULL_PRINT(msGparaM, prinTmsG) \
|
||||
if (!msGparaM) { \
|
||||
ESP_LOGE(TAG, prinTmsG"\n"); \
|
||||
goto fail_parse_rpc_msg; \
|
||||
}
|
||||
|
||||
#define RPC_FAIL_ON_NULL(msGparaM) \
|
||||
if (!rpc_msg->msGparaM) { \
|
||||
ESP_LOGE(TAG, "Failed to process rx data\n"); \
|
||||
goto fail_parse_rpc_msg; \
|
||||
}
|
||||
|
||||
|
||||
#define RPC_FREE_BUFFS() { \
|
||||
uint8_t idx = 0; \
|
||||
for (idx=0;idx<app_req->n_rpc_free_buff_hdls; idx++) \
|
||||
HOSTED_FREE(app_req->rpc_free_buff_hdls[idx]); \
|
||||
}
|
||||
|
||||
typedef struct q_element {
|
||||
void *buf;
|
||||
int buf_len;
|
||||
} esp_queue_elem_t;
|
||||
|
||||
//g_h.funcs->_h_memcpy(DsT.data, SrC, len_to_cp);
|
||||
|
||||
#if 0
|
||||
#define RPC_REQ_COPY_BYTES(DsT,SrC,SizE) { \
|
||||
if (SizE && SrC) { \
|
||||
DsT.data = (uint8_t *) g_h.funcs->_h_calloc(1, SizE); \
|
||||
if (!DsT.data) { \
|
||||
hosted_log("Failed to allocate memory for req.%s\n",#DsT); \
|
||||
failure_status = RPC_ERR_MEMORY_FAILURE; \
|
||||
goto fail_req; \
|
||||
} \
|
||||
buff_to_free[num_buff_to_free++] = (uint8_t*)DsT.data; \
|
||||
g_h.funcs->_h_memcpy(DsT.data, SrC, SizE); \
|
||||
DsT.len = SizE; \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
#define RPC_REQ_COPY_BYTES(DsT,SrC,SizE) { \
|
||||
if (SizE && SrC) { \
|
||||
DsT.data = SrC; \
|
||||
DsT.len = SizE; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define RPC_REQ_COPY_STR(DsT,SrC,MaxSizE) { \
|
||||
if (SrC) { \
|
||||
RPC_REQ_COPY_BYTES(DsT, SrC, H_MIN(strlen((char*)SrC)+1,MaxSizE)); \
|
||||
} \
|
||||
}
|
||||
|
||||
int rpc_core_init(void);
|
||||
int rpc_core_start(void);
|
||||
int rpc_core_stop(void);
|
||||
int rpc_core_deinit(void);
|
||||
/*
|
||||
* Allows user app to create low level protobuf request
|
||||
* returns SUCCESS(0) or FAILURE(-1)
|
||||
*/
|
||||
int rpc_send_req(ctrl_cmd_t *app_req);
|
||||
|
||||
/* When request is sent without an async callback, this function will be called
|
||||
* It will wait for control response or timeout for control response
|
||||
* This is only used in synchrounous control path
|
||||
*
|
||||
* Input:
|
||||
* > req - control request from user
|
||||
*
|
||||
* Returns: control response or NULL in case of timeout
|
||||
*
|
||||
**/
|
||||
ctrl_cmd_t * rpc_wait_and_parse_sync_resp(ctrl_cmd_t *req);
|
||||
|
||||
|
||||
/* Checks if async control response callback is available
|
||||
* in argument passed of type control request
|
||||
*
|
||||
* Input:
|
||||
* > req - control request from user
|
||||
*
|
||||
* Returns:
|
||||
* > CALLBACK_AVAILABLE - if a non NULL asynchronous control response
|
||||
* callback is available
|
||||
* In case of failures -
|
||||
* > MSG_ID_OUT_OF_ORDER - if request msg id is unsupported
|
||||
* > CALLBACK_NOT_REGISTERED - if aync callback is not available
|
||||
**/
|
||||
int compose_rpc_req(Rpc *req, ctrl_cmd_t *app_req, int32_t *failure_status);
|
||||
|
||||
int is_event_callback_registered(int event);
|
||||
|
||||
int rpc_parse_evt(Rpc *rpc_msg, ctrl_cmd_t *app_ntfy);
|
||||
|
||||
int rpc_parse_rsp(Rpc *rpc_msg, ctrl_cmd_t *app_resp);
|
||||
|
||||
#if H_PEER_DATA_TRANSFER
|
||||
int rpc_evt_register_custom_callback(uint32_t msg_id_exp,
|
||||
void (*callback)(uint32_t msg_id_recvd, const uint8_t *data_recvd, size_t data_len_recvd, void *local_context),
|
||||
void *local_context);
|
||||
#endif
|
||||
|
||||
#endif /* __RPC_CORE_H */
|
||||
@@ -0,0 +1,505 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "rpc_core.h"
|
||||
#include "rpc_utils.h"
|
||||
#include "rpc_slave_if.h"
|
||||
#include "esp_hosted_transport.h"
|
||||
#include "port_esp_hosted_host_log.h"
|
||||
#include "port_esp_hosted_host_config.h"
|
||||
#include "port_esp_hosted_host_os.h"
|
||||
#include "esp_hosted_bitmasks.h"
|
||||
#include "esp_hosted_os_abstraction.h"
|
||||
|
||||
DEFINE_LOG_TAG(rpc_evt);
|
||||
|
||||
#ifdef H_PEER_DATA_TRANSFER
|
||||
#define MAX_CUSTOM_CALLBACKS H_MAX_CUSTOM_MSG_HANDLERS
|
||||
/* Callback slots (empty slot has callback = NULL, msg_id = -1 is invalid sentinel) */
|
||||
static struct {
|
||||
uint32_t msg_id;
|
||||
void (*callback)(uint32_t msg_id_recvd, const uint8_t *data_recvd, size_t data_len_recvd, void *local_context);
|
||||
void *local_context;
|
||||
} custom_callbacks[MAX_CUSTOM_CALLBACKS] = {
|
||||
[0 ... (MAX_CUSTOM_CALLBACKS - 1)] = {
|
||||
.msg_id = (uint32_t)-1,
|
||||
.callback = NULL
|
||||
}
|
||||
};
|
||||
|
||||
static void* custom_callbacks_mutex = NULL;
|
||||
|
||||
|
||||
/* Register callback for specific message ID */
|
||||
int rpc_evt_register_custom_callback(uint32_t msg_id_exp,
|
||||
void (*callback)(uint32_t msg_id_recvd, const uint8_t *data_recvd, size_t data_len_recvd, void *local_context),
|
||||
void *local_context)
|
||||
{
|
||||
/* Validate message ID (-1/0xFFFFFFFF is invalid) */
|
||||
if (msg_id_exp == (uint32_t)-1) {
|
||||
ESP_LOGE(TAG, "Invalid message ID 0xFFFFFFFF");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/* Initialize mutex on first use */
|
||||
if (!custom_callbacks_mutex) {
|
||||
custom_callbacks_mutex = g_h.funcs->_h_create_mutex();
|
||||
if (!custom_callbacks_mutex) {
|
||||
ESP_LOGE(TAG, "Failed to create mutex");
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
g_h.funcs->_h_lock_mutex(custom_callbacks_mutex, HOSTED_BLOCK_MAX);
|
||||
|
||||
/* First, check if this msg_id_exp is already registered */
|
||||
for (int i = 0; i < MAX_CUSTOM_CALLBACKS; i++) {
|
||||
if (custom_callbacks[i].msg_id == msg_id_exp) {
|
||||
/* Found existing registration */
|
||||
if (callback == NULL) {
|
||||
/* Deregister: clean up this entry */
|
||||
custom_callbacks[i].msg_id = (uint32_t)-1; /* Mark as invalid */
|
||||
custom_callbacks[i].callback = NULL;
|
||||
custom_callbacks[i].local_context = NULL;
|
||||
ESP_LOGD(TAG, "Deregistered callback for msg_id %" PRIu32, msg_id_exp);
|
||||
g_h.funcs->_h_unlock_mutex(custom_callbacks_mutex);
|
||||
return SUCCESS;
|
||||
} else {
|
||||
/* Update existing callback */
|
||||
custom_callbacks[i].callback = callback;
|
||||
custom_callbacks[i].local_context = local_context;
|
||||
ESP_LOGD(TAG, "Updated callback for msg_id %" PRIu32, msg_id_exp);
|
||||
g_h.funcs->_h_unlock_mutex(custom_callbacks_mutex);
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* msg_id_exp not found - need to register new */
|
||||
if (callback == NULL) {
|
||||
/* Cannot deregister what doesn't exist */
|
||||
ESP_LOGD(TAG, "Cannot deregister msg_id %" PRIu32 " - not registered", msg_id_exp);
|
||||
g_h.funcs->_h_unlock_mutex(custom_callbacks_mutex);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/* Find empty slot for new registration */
|
||||
for (int i = 0; i < MAX_CUSTOM_CALLBACKS; i++) {
|
||||
if (custom_callbacks[i].callback == NULL) {
|
||||
custom_callbacks[i].msg_id = msg_id_exp;
|
||||
custom_callbacks[i].callback = callback;
|
||||
custom_callbacks[i].local_context = local_context;
|
||||
ESP_LOGD(TAG, "Registered callback for msg_id %" PRIu32, msg_id_exp);
|
||||
g_h.funcs->_h_unlock_mutex(custom_callbacks_mutex);
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGW(TAG, "No space for callback (max %d)", MAX_CUSTOM_CALLBACKS);
|
||||
g_h.funcs->_h_unlock_mutex(custom_callbacks_mutex);
|
||||
return FAILURE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* For new RPC event (from ESP to host), add up switch case for your message
|
||||
* In general, it is better to subscribe all events or notifications
|
||||
* at slave side & selective subscribe the events at host side.
|
||||
* This way, all the events reach at host and host will decide
|
||||
* if incoming event is expected to be entertained or dropped
|
||||
*
|
||||
* If you are concerned over battery usage, it is code further could be
|
||||
* optimized that only selective events are subscribed at slave and host both sides
|
||||
*
|
||||
* This function will copy rpc event from `Rpc` into
|
||||
* app structure `ctrl_cmd_t`
|
||||
* This function is called after
|
||||
* 1. Protobuf decoding is successful
|
||||
* 2. There is non NULL event callback is available
|
||||
**/
|
||||
int rpc_parse_evt(Rpc *rpc_msg, ctrl_cmd_t *app_ntfy)
|
||||
{
|
||||
if (!rpc_msg || !app_ntfy) {
|
||||
ESP_LOGE(TAG, "NULL rpc event or App struct\n");
|
||||
goto fail_parse_rpc_msg;
|
||||
}
|
||||
|
||||
app_ntfy->msg_type = RPC_TYPE__Event;
|
||||
app_ntfy->msg_id = rpc_msg->msg_id;
|
||||
app_ntfy->resp_event_status = SUCCESS;
|
||||
|
||||
switch (rpc_msg->msg_id) {
|
||||
|
||||
case RPC_ID__Event_ESPInit: {
|
||||
ESP_LOGI(TAG, "EVENT: ESP INIT\n");
|
||||
RPC_FAIL_ON_NULL(event_esp_init);
|
||||
app_ntfy->u.e_init.cp_reset_reason = rpc_msg->event_esp_init->cp_reset_reason;
|
||||
break;
|
||||
} case RPC_ID__Event_Heartbeat: {
|
||||
ESP_LOGD(TAG, "EVENT: Heartbeat\n");
|
||||
RPC_FAIL_ON_NULL(event_heartbeat);
|
||||
app_ntfy->u.e_heartbeat.hb_num = rpc_msg->event_heartbeat->hb_num;
|
||||
break;
|
||||
} case RPC_ID__Event_AP_StaConnected: {
|
||||
wifi_event_ap_staconnected_t * p_a = &(app_ntfy->u.e_wifi_ap_staconnected);
|
||||
RpcEventAPStaConnected * p_c = rpc_msg->event_ap_sta_connected;
|
||||
|
||||
RPC_FAIL_ON_NULL(event_ap_sta_connected);
|
||||
app_ntfy->resp_event_status = p_c->resp;
|
||||
|
||||
if(SUCCESS==app_ntfy->resp_event_status) {
|
||||
RPC_FAIL_ON_NULL_PRINT(p_c->mac.data, "NULL mac");
|
||||
g_h.funcs->_h_memcpy(p_a->mac, p_c->mac.data, p_c->mac.len);
|
||||
ESP_LOGI(TAG, "EVENT: AP -> sta connected mac[" MACSTR "] (len:%u)",
|
||||
MAC2STR(p_a->mac), p_c->mac.len);
|
||||
}
|
||||
p_a->aid = p_c->aid;
|
||||
p_a->is_mesh_child = p_c->is_mesh_child;
|
||||
|
||||
break;
|
||||
} case RPC_ID__Event_AP_StaDisconnected: {
|
||||
wifi_event_ap_stadisconnected_t * p_a = &(app_ntfy->u.e_wifi_ap_stadisconnected);
|
||||
RpcEventAPStaDisconnected * p_c = rpc_msg->event_ap_sta_disconnected;
|
||||
|
||||
ESP_LOGD(TAG, "EVENT: AP -> sta disconnected");
|
||||
RPC_FAIL_ON_NULL(event_ap_sta_disconnected);
|
||||
app_ntfy->resp_event_status = p_c->resp;
|
||||
|
||||
if(SUCCESS==app_ntfy->resp_event_status) {
|
||||
RPC_FAIL_ON_NULL_PRINT(p_c->mac.data, "NULL mac");
|
||||
g_h.funcs->_h_memcpy(p_a->mac, p_c->mac.data, p_c->mac.len);
|
||||
ESP_LOGI(TAG, "EVENT: AP -> sta DISconnected mac[" MACSTR "] (len:%u)",
|
||||
MAC2STR(p_a->mac), p_c->mac.len);
|
||||
}
|
||||
|
||||
p_a->aid = p_c->aid;
|
||||
p_a->is_mesh_child = p_c->is_mesh_child;
|
||||
p_a->reason = p_c->reason;
|
||||
|
||||
break;
|
||||
#if H_WIFI_HE_SUPPORT
|
||||
} case RPC_ID__Event_StaItwtSetup: {
|
||||
wifi_event_sta_itwt_setup_t * p_a = &(app_ntfy->u.e_wifi_sta_itwt_setup);
|
||||
RpcEventStaItwtSetup * p_c = rpc_msg->event_sta_itwt_setup;
|
||||
|
||||
ESP_LOGD(TAG, "EVENT: iTWT -> setup");
|
||||
RPC_FAIL_ON_NULL(event_sta_itwt_setup);
|
||||
app_ntfy->resp_event_status = p_c->resp;
|
||||
|
||||
p_a->config.setup_cmd = p_c->config->setup_cmd;
|
||||
p_a->config.trigger = H_GET_BIT(WIFI_ITWT_CONFIG_1_trigger_BIT, p_c->config->bitmask_1);
|
||||
p_a->config.flow_type = H_GET_BIT(WIFI_ITWT_CONFIG_1_flow_type_BIT, p_c->config->bitmask_1);
|
||||
// WIFI_ITWT_CONFIG_1_flow_id_BIT is three bits wide
|
||||
p_a->config.flow_id = (p_c->config->bitmask_1 >> WIFI_ITWT_CONFIG_1_flow_id_BIT) & 0x07;
|
||||
// WIFI_ITWT_CONFIG_1_wake_invl_expn_BIT is five bits wide
|
||||
p_a->config.wake_invl_expn = (p_c->config->bitmask_1 >> WIFI_ITWT_CONFIG_1_wake_invl_expn_BIT) & 0x1F;
|
||||
p_a->config.wake_duration_unit = H_GET_BIT(WIFI_ITWT_CONFIG_1_wake_duration_unit_BIT, p_c->config->bitmask_1);
|
||||
#if H_DECODE_WIFI_RESERVED_FIELD
|
||||
p_a->config.reserved = (p_c->config->bitmask_1 >> WIFI_ITWT_CONFIG_1_MAX_USED_BIT) & WIFI_ITWT_CONFIG_1_RESERVED_BITMASK;
|
||||
#endif
|
||||
p_a->config.min_wake_dura = p_c->config->min_wake_dura;
|
||||
p_a->config.wake_invl_mant = p_c->config->wake_invl_mant;
|
||||
p_a->config.twt_id = p_c->config->twt_id;
|
||||
p_a->config.timeout_time_ms = p_c->config->timeout_time_ms;
|
||||
p_a->status = p_c->status;
|
||||
p_a->reason = p_c->reason;
|
||||
p_a->target_wake_time = p_c->target_wake_time;
|
||||
|
||||
break;
|
||||
} case RPC_ID__Event_StaItwtTeardown: {
|
||||
wifi_event_sta_itwt_teardown_t * p_a = &(app_ntfy->u.e_wifi_sta_itwt_teardown);
|
||||
RpcEventStaItwtTeardown * p_c = rpc_msg->event_sta_itwt_teardown;
|
||||
|
||||
ESP_LOGD(TAG, "EVENT: iTWT -> teardown");
|
||||
RPC_FAIL_ON_NULL(event_sta_itwt_teardown);
|
||||
app_ntfy->resp_event_status = p_c->resp;
|
||||
|
||||
p_a->flow_id = p_c->flow_id;
|
||||
p_a->status = p_c->status;
|
||||
|
||||
break;
|
||||
} case RPC_ID__Event_StaItwtSuspend: {
|
||||
wifi_event_sta_itwt_suspend_t * p_a = &(app_ntfy->u.e_wifi_sta_itwt_suspend);
|
||||
RpcEventStaItwtSuspend * p_c = rpc_msg->event_sta_itwt_suspend;
|
||||
int num_elements = sizeof(p_a->actual_suspend_time_ms) / sizeof(p_a->actual_suspend_time_ms[0]);
|
||||
int i;
|
||||
|
||||
ESP_LOGD(TAG, "EVENT: iTWT -> suspend");
|
||||
RPC_FAIL_ON_NULL(event_sta_itwt_suspend);
|
||||
app_ntfy->resp_event_status = p_c->resp;
|
||||
|
||||
p_a->status = p_c->status;
|
||||
p_a->flow_id_bitmap = p_c->flow_id_bitmap;
|
||||
|
||||
memset(p_a->actual_suspend_time_ms, 0, sizeof(p_a->actual_suspend_time_ms));
|
||||
for (i = 0; i < H_MIN(num_elements, p_c->n_actual_suspend_time_ms); i++) {
|
||||
p_a->actual_suspend_time_ms[i] = p_c->actual_suspend_time_ms[i];
|
||||
}
|
||||
|
||||
break;
|
||||
} case RPC_ID__Event_StaItwtProbe: {
|
||||
wifi_event_sta_itwt_probe_t * p_a = &(app_ntfy->u.e_wifi_sta_itwt_probe);
|
||||
RpcEventStaItwtProbe * p_c = rpc_msg->event_sta_itwt_probe;
|
||||
|
||||
ESP_LOGD(TAG, "EVENT: iTWT -> probe");
|
||||
RPC_FAIL_ON_NULL(event_sta_itwt_probe);
|
||||
app_ntfy->resp_event_status = p_c->resp;
|
||||
|
||||
p_a->status = p_c->status;
|
||||
p_a->reason = p_c->reason;
|
||||
|
||||
break;
|
||||
#endif
|
||||
} case RPC_ID__Event_WifiEventNoArgs: {
|
||||
RPC_FAIL_ON_NULL(event_wifi_event_no_args);
|
||||
app_ntfy->resp_event_status = rpc_msg->event_wifi_event_no_args->resp;
|
||||
ESP_LOGI(TAG, "Event [0x%" PRIx32 "] received", rpc_msg->event_wifi_event_no_args->event_id);
|
||||
app_ntfy->u.e_wifi_simple.wifi_event_id = rpc_msg->event_wifi_event_no_args->event_id;
|
||||
|
||||
switch (rpc_msg->event_wifi_event_no_args->event_id) {
|
||||
/* basic events populated, not all */
|
||||
case WIFI_EVENT_WIFI_READY:
|
||||
ESP_LOGI(TAG, "EVT rcvd: Wi-Fi Ready");
|
||||
break;
|
||||
case WIFI_EVENT_SCAN_DONE:
|
||||
ESP_LOGI(TAG, "EVT rcvd: Wi-Fi scan done");
|
||||
break;
|
||||
case WIFI_EVENT_STA_START:
|
||||
ESP_LOGI(TAG, "EVT rcvd: Wi-Fi Start");
|
||||
break;
|
||||
case WIFI_EVENT_STA_STOP:
|
||||
ESP_LOGI(TAG, "EVT rcvd: Wi-Fi Stop");
|
||||
break;
|
||||
case WIFI_EVENT_STA_CONNECTED:
|
||||
ESP_LOGI(TAG, "EVT rcvd: Wi-Fi Connected");
|
||||
break;
|
||||
case WIFI_EVENT_STA_DISCONNECTED:
|
||||
ESP_LOGI(TAG, "EVT rcvd: Wi-Fi Disconnected");
|
||||
break;
|
||||
case WIFI_EVENT_STA_AUTHMODE_CHANGE:
|
||||
ESP_LOGI(TAG, "EVT rcvd: Wi-Fi AuthMode change");
|
||||
break;
|
||||
case WIFI_EVENT_AP_START:
|
||||
ESP_LOGI(TAG, "EVT rcvd: Wi-Fi AP Start");
|
||||
break;
|
||||
case WIFI_EVENT_AP_STOP:
|
||||
ESP_LOGI(TAG, "EVT rcvd: Wi-Fi AP stop");
|
||||
break;
|
||||
case WIFI_EVENT_HOME_CHANNEL_CHANGE:
|
||||
ESP_LOGI(TAG, "EVT rcvd: Wi-Fi Home channel change");
|
||||
break;
|
||||
default:
|
||||
ESP_LOGI(TAG, "EVT rcvd: Wi-Fi Event[%" PRId32 "] ignored", rpc_msg->event_wifi_event_no_args->event_id);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
} case RPC_ID__Event_StaScanDone: {
|
||||
RpcEventStaScanDone *p_c = rpc_msg->event_sta_scan_done;
|
||||
wifi_event_sta_scan_done_t *p_a = &app_ntfy->u.e_wifi_sta_scan_done;
|
||||
RPC_FAIL_ON_NULL(event_sta_scan_done);
|
||||
app_ntfy->resp_event_status = p_c->resp;
|
||||
ESP_LOGI(TAG, "Event Scan Done, %" PRIu32 " items", rpc_msg->event_sta_scan_done->scan_done->number);
|
||||
p_a->status = p_c->scan_done->status;
|
||||
p_a->number = p_c->scan_done->number;
|
||||
p_a->scan_id = p_c->scan_done->scan_id;
|
||||
break;
|
||||
} case RPC_ID__Event_StaConnected: {
|
||||
RPC_FAIL_ON_NULL(event_sta_connected);
|
||||
RPC_FAIL_ON_NULL(event_sta_connected->sta_connected);
|
||||
WifiEventStaConnected *p_c = rpc_msg->event_sta_connected->sta_connected;
|
||||
wifi_event_sta_connected_t *p_a = &app_ntfy->u.e_wifi_sta_connected;
|
||||
app_ntfy->resp_event_status = rpc_msg->event_sta_connected->resp;
|
||||
if (SUCCESS == app_ntfy->resp_event_status) {
|
||||
RPC_FAIL_ON_NULL_PRINT(p_c->ssid.data, "NULL SSID");
|
||||
g_h.funcs->_h_memcpy(p_a->ssid, p_c->ssid.data, p_c->ssid.len);
|
||||
p_a->ssid_len = p_c->ssid_len;
|
||||
RPC_FAIL_ON_NULL_PRINT(p_c->bssid.data, "NULL BSSID");
|
||||
g_h.funcs->_h_memcpy(p_a->bssid, p_c->bssid.data, p_c->bssid.len);
|
||||
p_a->channel = p_c->channel;
|
||||
p_a->authmode = p_c->authmode;
|
||||
p_a->aid = p_c->aid;
|
||||
}
|
||||
break;
|
||||
} case RPC_ID__Event_StaDisconnected: {
|
||||
RPC_FAIL_ON_NULL(event_sta_disconnected);
|
||||
RPC_FAIL_ON_NULL(event_sta_disconnected->sta_disconnected);
|
||||
WifiEventStaDisconnected *p_c = rpc_msg->event_sta_disconnected->sta_disconnected;
|
||||
wifi_event_sta_disconnected_t *p_a = &app_ntfy->u.e_wifi_sta_disconnected;
|
||||
app_ntfy->resp_event_status = rpc_msg->event_sta_connected->resp;
|
||||
if (SUCCESS == app_ntfy->resp_event_status) {
|
||||
RPC_FAIL_ON_NULL_PRINT(p_c->ssid.data, "NULL SSID");
|
||||
g_h.funcs->_h_memcpy(p_a->ssid, p_c->ssid.data, p_c->ssid.len);
|
||||
p_a->ssid_len = p_c->ssid_len;
|
||||
RPC_FAIL_ON_NULL_PRINT(p_c->bssid.data, "NULL BSSID");
|
||||
g_h.funcs->_h_memcpy(p_a->bssid, p_c->bssid.data, p_c->bssid.len);
|
||||
p_a->reason = p_c->reason;
|
||||
p_a->rssi = p_c->rssi;
|
||||
}
|
||||
break;
|
||||
} case RPC_ID__Event_DhcpDnsStatus: {
|
||||
RPC_FAIL_ON_NULL(event_dhcp_dns);
|
||||
RpcEventDhcpDnsStatus *p_c = rpc_msg->event_dhcp_dns;
|
||||
rpc_set_dhcp_dns_status_t* p_a = &app_ntfy->u.slave_dhcp_dns_status;
|
||||
app_ntfy->resp_event_status = rpc_msg->event_dhcp_dns->resp;
|
||||
|
||||
p_a->iface = p_c->iface;
|
||||
p_a->dhcp_up = p_c->dhcp_up;
|
||||
p_a->dns_up = p_c->dns_up;
|
||||
p_a->dns_type = p_c->dns_type;
|
||||
p_a->net_link_up = p_c->net_link_up;
|
||||
|
||||
g_h.funcs->_h_memcpy(p_a->dhcp_ip, p_c->dhcp_ip.data, p_c->dhcp_ip.len);
|
||||
g_h.funcs->_h_memcpy(p_a->dhcp_nm, p_c->dhcp_nm.data, p_c->dhcp_nm.len);
|
||||
g_h.funcs->_h_memcpy(p_a->dhcp_gw, p_c->dhcp_gw.data, p_c->dhcp_gw.len);
|
||||
g_h.funcs->_h_memcpy(p_a->dns_ip, p_c->dns_ip.data, p_c->dns_ip.len);
|
||||
|
||||
break;
|
||||
#if H_MEM_MONITOR
|
||||
} case RPC_ID__Event_MemMonitor: {
|
||||
RPC_FAIL_ON_NULL(event_mem_monitor);
|
||||
RPC_FAIL_ON_NULL(event_mem_monitor->curr_internal);
|
||||
RPC_FAIL_ON_NULL(event_mem_monitor->curr_internal->mem_dma);
|
||||
RPC_FAIL_ON_NULL(event_mem_monitor->curr_internal->mem_8bit);
|
||||
RPC_FAIL_ON_NULL(event_mem_monitor->curr_external);
|
||||
RPC_FAIL_ON_NULL(event_mem_monitor->curr_external->mem_dma);
|
||||
RPC_FAIL_ON_NULL(event_mem_monitor->curr_external->mem_8bit);
|
||||
|
||||
RpcEventMemMonitor *p_c = rpc_msg->event_mem_monitor;
|
||||
esp_hosted_event_mem_info_t *p_a = &app_ntfy->u.e_mem_info;
|
||||
|
||||
p_a->curr_total_free_heap_size = p_c->curr_total_free_heap_size;
|
||||
p_a->curr_min_free_heap_size = p_c->curr_min_free_heap_size;
|
||||
p_a->curr_internal.cap_dma.free_size = p_c->curr_internal->mem_dma->free_size;
|
||||
p_a->curr_internal.cap_dma.largest_free_block = p_c->curr_internal->mem_dma->largest_free_block;
|
||||
p_a->curr_internal.cap_8bit.free_size = p_c->curr_internal->mem_8bit->free_size;
|
||||
p_a->curr_internal.cap_8bit.largest_free_block = p_c->curr_internal->mem_8bit->largest_free_block;
|
||||
p_a->curr_external.cap_dma.free_size = p_c->curr_external->mem_dma->free_size;
|
||||
p_a->curr_external.cap_dma.largest_free_block = p_c->curr_external->mem_dma->largest_free_block;
|
||||
p_a->curr_external.cap_8bit.free_size = p_c->curr_external->mem_8bit->free_size;
|
||||
p_a->curr_external.cap_8bit.largest_free_block = p_c->curr_external->mem_8bit->largest_free_block;
|
||||
break;
|
||||
#endif
|
||||
#if H_SUPP_DPP_SUPPORT
|
||||
}
|
||||
case RPC_ID__Event_SuppDppUriReady: {
|
||||
RpcEventSuppDppUriReady *p_c = rpc_msg->event_supp_dpp_uri_ready;
|
||||
supp_wifi_event_dpp_uri_ready_t *p_a = &app_ntfy->u.e_dpp_uri_ready;
|
||||
app_ntfy->resp_event_status = rpc_msg->event_supp_dpp_uri_ready->resp;
|
||||
|
||||
g_h.funcs->_h_memset(p_a->uri, 0, DPP_URI_LEN_MAX);
|
||||
|
||||
p_a->uri_data_len = p_c->qrcode.len;
|
||||
if (p_a->uri_data_len <= DPP_URI_LEN_MAX) {
|
||||
g_h.funcs->_h_memcpy(p_a->uri, p_c->qrcode.data, p_a->uri_data_len);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Incoming URI is too long (over %d bytes). Increase Kconfig ESP_HOSTED_DPP_URI_LEN_MAX for proper operation", DPP_URI_LEN_MAX - 1);
|
||||
p_a->uri_data_len = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RPC_ID__Event_SuppDppCfgRecvd: {
|
||||
RpcEventSuppDppCfgRecvd *p_c = rpc_msg->event_supp_dpp_cfg_recvd;
|
||||
supp_wifi_event_dpp_config_received_t *p_a = &app_ntfy->u.e_dpp_config_received;
|
||||
app_ntfy->resp_event_status = rpc_msg->event_supp_dpp_uri_ready->resp;
|
||||
|
||||
rpc_copy_wifi_sta_config(&p_a->wifi_cfg.sta, p_c->cfg->sta);
|
||||
break;
|
||||
}
|
||||
case RPC_ID__Event_SuppDppFail: {
|
||||
RpcEventSuppDppFail *p_c = rpc_msg->event_supp_dpp_fail;
|
||||
supp_wifi_event_dpp_failed_t *p_a = &app_ntfy->u.e_dpp_failed;
|
||||
app_ntfy->resp_event_status = rpc_msg->event_supp_dpp_fail->resp;
|
||||
|
||||
p_a->failure_reason = p_c->reason;
|
||||
break;
|
||||
#endif // H_SUPP_DPP_SUPPORT
|
||||
#if H_WIFI_DPP_SUPPORT
|
||||
}
|
||||
case RPC_ID__Event_WifiDppUriReady: {
|
||||
RpcEventWifiDppUriReady *p_c = rpc_msg->event_wifi_dpp_uri_ready;
|
||||
supp_wifi_event_dpp_uri_ready_t *p_a = &app_ntfy->u.e_dpp_uri_ready;
|
||||
app_ntfy->resp_event_status = rpc_msg->event_supp_dpp_uri_ready->resp;
|
||||
|
||||
g_h.funcs->_h_memset(p_a->uri, 0, DPP_URI_LEN_MAX);
|
||||
|
||||
p_a->uri_data_len = p_c->qrcode.len;
|
||||
if (p_a->uri_data_len <= DPP_URI_LEN_MAX) {
|
||||
g_h.funcs->_h_memcpy(p_a->uri, p_c->qrcode.data, p_a->uri_data_len);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Incoming URI is too long (over %d bytes). Increase Kconfig ESP_HOSTED_DPP_URI_LEN_MAX for proper operation", DPP_URI_LEN_MAX - 1);
|
||||
p_a->uri_data_len = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RPC_ID__Event_WifiDppCfgRecvd: {
|
||||
RpcEventWifiDppCfgRecvd *p_c = rpc_msg->event_wifi_dpp_cfg_recvd;
|
||||
supp_wifi_event_dpp_config_received_t *p_a = &app_ntfy->u.e_dpp_config_received;
|
||||
app_ntfy->resp_event_status = rpc_msg->event_supp_dpp_uri_ready->resp;
|
||||
|
||||
rpc_copy_wifi_sta_config(&p_a->wifi_cfg.sta, p_c->cfg->sta);
|
||||
break;
|
||||
}
|
||||
case RPC_ID__Event_WifiDppFail: {
|
||||
RpcEventWifiDppFail *p_c = rpc_msg->event_wifi_dpp_fail;
|
||||
supp_wifi_event_dpp_failed_t *p_a = &app_ntfy->u.e_dpp_failed;
|
||||
app_ntfy->resp_event_status = rpc_msg->event_supp_dpp_fail->resp;
|
||||
|
||||
p_a->failure_reason = p_c->reason;
|
||||
break;
|
||||
#endif // H_WIFI_DPP_SUPPORT
|
||||
#ifdef H_PEER_DATA_TRANSFER
|
||||
} case RPC_ID__Event_CustomRpc: {
|
||||
RpcEventCustomRpc *p_c = rpc_msg->event_custom_rpc;
|
||||
RPC_FAIL_ON_NULL(event_custom_rpc);
|
||||
app_ntfy->resp_event_status = p_c->resp;
|
||||
|
||||
/* Get message ID from protobuf field (not from data payload) */
|
||||
uint32_t msg_id = p_c->custom_event_id;
|
||||
|
||||
/* Route to callback with pure user data */
|
||||
const uint8_t *payload = p_c->data.data;
|
||||
size_t payload_len = p_c->data.len;
|
||||
|
||||
bool callback_found = false;
|
||||
void (*cb)(uint32_t, const uint8_t *, size_t, void *) = NULL;
|
||||
void *cb_local_context = NULL;
|
||||
|
||||
/* Find callback under mutex protection */
|
||||
if (custom_callbacks_mutex) {
|
||||
g_h.funcs->_h_lock_mutex(custom_callbacks_mutex, HOSTED_BLOCK_MAX);
|
||||
for (int i = 0; i < MAX_CUSTOM_CALLBACKS; i++) {
|
||||
if (custom_callbacks[i].msg_id == msg_id && custom_callbacks[i].callback) {
|
||||
cb = custom_callbacks[i].callback;
|
||||
cb_local_context = custom_callbacks[i].local_context;
|
||||
callback_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_h.funcs->_h_unlock_mutex(custom_callbacks_mutex);
|
||||
}
|
||||
|
||||
/* Invoke callback outside mutex to avoid deadlock */
|
||||
if (callback_found && cb) {
|
||||
cb(msg_id, payload, payload_len, cb_local_context);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "No callback registered for message ID %" PRIu32 ", ignore", msg_id);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
} default: {
|
||||
ESP_LOGE(TAG, "Invalid/unsupported event[%u] received\n",rpc_msg->msg_id);
|
||||
goto fail_parse_rpc_msg;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
|
||||
fail_parse_rpc_msg:
|
||||
app_ntfy->resp_event_status = FAILURE;
|
||||
return FAILURE;
|
||||
}
|
||||
@@ -0,0 +1,993 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "rpc_core.h"
|
||||
#include "rpc_slave_if.h"
|
||||
#include "esp_hosted_rpc.h"
|
||||
#include "port_esp_hosted_host_wifi_config.h"
|
||||
#include "esp_hosted_transport.h"
|
||||
#include "esp_hosted_bitmasks.h"
|
||||
#include "esp_idf_version.h"
|
||||
#include "port_esp_hosted_host_log.h"
|
||||
#include "esp_hosted_os_abstraction.h"
|
||||
|
||||
DEFINE_LOG_TAG(rpc_req);
|
||||
|
||||
#define ADD_RPC_BUFF_TO_FREE_LATER(BuFf) { \
|
||||
assert((app_req->n_rpc_free_buff_hdls+1)<=MAX_FREE_BUFF_HANDLES); \
|
||||
app_req->rpc_free_buff_hdls[app_req->n_rpc_free_buff_hdls++] = BuFf; \
|
||||
}
|
||||
|
||||
#define RPC_ALLOC_ASSIGN(TyPe,MsG_StRuCt,InItFuNc) \
|
||||
TyPe *req_payload = (TyPe *) \
|
||||
g_h.funcs->_h_calloc(1, sizeof(TyPe)); \
|
||||
if (!req_payload) { \
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for req->%s\n",#MsG_StRuCt); \
|
||||
*failure_status = RPC_ERR_MEMORY_FAILURE; \
|
||||
return FAILURE; \
|
||||
} \
|
||||
req->MsG_StRuCt = req_payload; \
|
||||
InItFuNc(req_payload); \
|
||||
ADD_RPC_BUFF_TO_FREE_LATER((uint8_t*)req_payload);
|
||||
|
||||
//TODO: How this is different in slave_control.c
|
||||
#define RPC_ALLOC_ELEMENT(TyPe,MsG_StRuCt,InIt_FuN) { \
|
||||
TyPe *NeW_AllocN = (TyPe *) g_h.funcs->_h_calloc(1, sizeof(TyPe)); \
|
||||
if (!NeW_AllocN) { \
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for req->%s\n",#MsG_StRuCt); \
|
||||
*failure_status = RPC_ERR_MEMORY_FAILURE; \
|
||||
return FAILURE; \
|
||||
} \
|
||||
ADD_RPC_BUFF_TO_FREE_LATER((uint8_t*)NeW_AllocN); \
|
||||
MsG_StRuCt = NeW_AllocN; \
|
||||
InIt_FuN(MsG_StRuCt); \
|
||||
}
|
||||
|
||||
/* RPC request is simple remote function invocation at slave from host
|
||||
*
|
||||
* For new RPC request, add up switch case for your message
|
||||
* If the RPC function to be invoked does not carry any arguments, just add
|
||||
* case in the top with intentional fall through
|
||||
* If any arguments are needed, you may have to add union for your message
|
||||
* in Ctrl_cmd_t in rpc_api.h and fill the request in new case
|
||||
*
|
||||
* For altogether new RPC function addition, please check
|
||||
* esp_hosted_fg/common/proto/esp_hosted_config.proto
|
||||
*/
|
||||
int compose_rpc_req(Rpc *req, ctrl_cmd_t *app_req, int32_t *failure_status)
|
||||
{
|
||||
switch(req->msg_id) {
|
||||
|
||||
case RPC_ID__Req_GetWifiMode:
|
||||
//case RPC_ID__Req_GetAPConfig:
|
||||
//case RPC_ID__Req_DisconnectAP:
|
||||
//case RPC_ID__Req_GetSoftAPConfig:
|
||||
//case RPC_ID__Req_GetSoftAPConnectedSTAList:
|
||||
//case RPC_ID__Req_StopSoftAP:
|
||||
case RPC_ID__Req_WifiGetPs:
|
||||
case RPC_ID__Req_OTABegin:
|
||||
case RPC_ID__Req_OTAEnd:
|
||||
case RPC_ID__Req_OTAActivate:
|
||||
case RPC_ID__Req_WifiDeinit:
|
||||
case RPC_ID__Req_WifiStart:
|
||||
case RPC_ID__Req_WifiStop:
|
||||
case RPC_ID__Req_WifiConnect:
|
||||
case RPC_ID__Req_WifiDisconnect:
|
||||
case RPC_ID__Req_WifiScanStop:
|
||||
case RPC_ID__Req_WifiScanGetApNum:
|
||||
case RPC_ID__Req_WifiClearApList:
|
||||
case RPC_ID__Req_WifiRestore:
|
||||
case RPC_ID__Req_WifiClearFastConnect:
|
||||
case RPC_ID__Req_WifiStaGetApInfo:
|
||||
case RPC_ID__Req_WifiGetMaxTxPower:
|
||||
case RPC_ID__Req_WifiGetChannel:
|
||||
case RPC_ID__Req_WifiGetCountryCode:
|
||||
case RPC_ID__Req_WifiGetCountry:
|
||||
case RPC_ID__Req_WifiApGetStaList:
|
||||
case RPC_ID__Req_WifiStaGetRssi:
|
||||
case RPC_ID__Req_WifiStaGetNegotiatedPhymode:
|
||||
case RPC_ID__Req_WifiStaGetAid:
|
||||
case RPC_ID__Req_WifiGetBand:
|
||||
case RPC_ID__Req_WifiGetBandMode:
|
||||
case RPC_ID__Req_AppGetDesc:
|
||||
#if H_WIFI_ENTERPRISE_SUPPORT
|
||||
case RPC_ID__Req_WifiStaEnterpriseEnable:
|
||||
case RPC_ID__Req_WifiStaEnterpriseDisable:
|
||||
case RPC_ID__Req_EapClearIdentity:
|
||||
case RPC_ID__Req_EapClearUsername:
|
||||
case RPC_ID__Req_EapClearPassword:
|
||||
case RPC_ID__Req_EapClearNewPassword:
|
||||
case RPC_ID__Req_EapClearCaCert:
|
||||
case RPC_ID__Req_EapClearCertificateAndKey:
|
||||
#endif
|
||||
#if H_DPP_SUPPORT
|
||||
case RPC_ID__Req_SuppDppDeinit:
|
||||
case RPC_ID__Req_SuppDppStartListen:
|
||||
case RPC_ID__Req_SuppDppStopListen:
|
||||
#endif
|
||||
case RPC_ID__Req_WifiScanGetApRecord: {
|
||||
/* Intentional fallthrough & empty */
|
||||
break;
|
||||
} case RPC_ID__Req_GetMACAddress: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqGetMacAddress, req_get_mac_address,
|
||||
rpc__req__get_mac_address__init);
|
||||
|
||||
req_payload->mode = app_req->u.wifi_mac.mode;
|
||||
|
||||
break;
|
||||
} case RPC_ID__Req_SetMacAddress: {
|
||||
wifi_mac_t * p = &app_req->u.wifi_mac;
|
||||
RPC_ALLOC_ASSIGN(RpcReqSetMacAddress, req_set_mac_address,
|
||||
rpc__req__set_mac_address__init);
|
||||
|
||||
req_payload->mode = p->mode;
|
||||
RPC_REQ_COPY_BYTES(req_payload->mac, p->mac, BSSID_BYTES_SIZE);
|
||||
|
||||
break;
|
||||
} case RPC_ID__Req_SetWifiMode: {
|
||||
hosted_mode_t * p = &app_req->u.wifi_mode;
|
||||
RPC_ALLOC_ASSIGN(RpcReqSetMode, req_set_wifi_mode,
|
||||
rpc__req__set_mode__init);
|
||||
|
||||
if ((p->mode < WIFI_MODE_NULL) || (p->mode >= WIFI_MODE_MAX)) {
|
||||
ESP_LOGE(TAG, "Invalid wifi mode\n");
|
||||
*failure_status = RPC_ERR_INCORRECT_ARG;
|
||||
return FAILURE;
|
||||
}
|
||||
req_payload->mode = p->mode;
|
||||
break;
|
||||
} case RPC_ID__Req_WifiSetPs: {
|
||||
wifi_power_save_t * p = &app_req->u.wifi_ps;
|
||||
RPC_ALLOC_ASSIGN(RpcReqSetPs, req_wifi_set_ps,
|
||||
rpc__req__set_ps__init);
|
||||
|
||||
req_payload->type = p->ps_mode;
|
||||
break;
|
||||
} case RPC_ID__Req_OTAWrite: {
|
||||
ota_write_t *p = & app_req->u.ota_write;
|
||||
RPC_ALLOC_ASSIGN(RpcReqOTAWrite, req_ota_write,
|
||||
rpc__req__otawrite__init);
|
||||
|
||||
if (!p->ota_data || (p->ota_data_len == 0)) {
|
||||
ESP_LOGE(TAG, "Invalid parameter\n");
|
||||
*failure_status = RPC_ERR_INCORRECT_ARG;
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
req_payload->ota_data.data = p->ota_data;
|
||||
req_payload->ota_data.len = p->ota_data_len;
|
||||
break;
|
||||
} case RPC_ID__Req_WifiSetMaxTxPower: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiSetMaxTxPower,
|
||||
req_set_wifi_max_tx_power,
|
||||
rpc__req__wifi_set_max_tx_power__init);
|
||||
req_payload->power = app_req->u.wifi_tx_power.power;
|
||||
break;
|
||||
} case RPC_ID__Req_ConfigHeartbeat: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqConfigHeartbeat, req_config_heartbeat,
|
||||
rpc__req__config_heartbeat__init);
|
||||
req_payload->enable = app_req->u.e_heartbeat.enable;
|
||||
req_payload->duration = app_req->u.e_heartbeat.duration;
|
||||
if (req_payload->enable) {
|
||||
ESP_LOGD(TAG, "Enable heartbeat with duration %ld", (long int)req_payload->duration);
|
||||
if (CALLBACK_AVAILABLE != is_event_callback_registered(RPC_ID__Event_Heartbeat))
|
||||
ESP_LOGD(TAG, "Note: ** Subscribe heartbeat event to get notification **");
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Disable Heartbeat");
|
||||
}
|
||||
break;
|
||||
} case RPC_ID__Req_WifiInit: {
|
||||
wifi_init_config_t * p_a = &app_req->u.wifi_init_config;
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiInit, req_wifi_init,
|
||||
rpc__req__wifi_init__init);
|
||||
RPC_ALLOC_ELEMENT(WifiInitConfig, req_payload->cfg, wifi_init_config__init);
|
||||
|
||||
req_payload->cfg->static_rx_buf_num = p_a->static_rx_buf_num ;
|
||||
req_payload->cfg->dynamic_rx_buf_num = p_a->dynamic_rx_buf_num ;
|
||||
req_payload->cfg->tx_buf_type = p_a->tx_buf_type ;
|
||||
req_payload->cfg->static_tx_buf_num = p_a->static_tx_buf_num ;
|
||||
req_payload->cfg->dynamic_tx_buf_num = p_a->dynamic_tx_buf_num ;
|
||||
req_payload->cfg->rx_mgmt_buf_type = p_a->rx_mgmt_buf_type ;
|
||||
req_payload->cfg->rx_mgmt_buf_num = p_a->rx_mgmt_buf_num ;
|
||||
req_payload->cfg->cache_tx_buf_num = p_a->cache_tx_buf_num ;
|
||||
req_payload->cfg->csi_enable = p_a->csi_enable ;
|
||||
req_payload->cfg->ampdu_rx_enable = p_a->ampdu_rx_enable ;
|
||||
req_payload->cfg->ampdu_tx_enable = p_a->ampdu_tx_enable ;
|
||||
req_payload->cfg->amsdu_tx_enable = p_a->amsdu_tx_enable ;
|
||||
req_payload->cfg->nvs_enable = p_a->nvs_enable ;
|
||||
req_payload->cfg->nano_enable = p_a->nano_enable ;
|
||||
req_payload->cfg->rx_ba_win = p_a->rx_ba_win ;
|
||||
req_payload->cfg->wifi_task_core_id = p_a->wifi_task_core_id ;
|
||||
req_payload->cfg->beacon_max_len = p_a->beacon_max_len ;
|
||||
req_payload->cfg->feature_caps = p_a->feature_caps ;
|
||||
req_payload->cfg->mgmt_sbuf_num = p_a->mgmt_sbuf_num ;
|
||||
req_payload->cfg->sta_disconnected_pm = p_a->sta_disconnected_pm ;
|
||||
req_payload->cfg->espnow_max_encrypt_num = p_a->espnow_max_encrypt_num ;
|
||||
req_payload->cfg->tx_hetb_queue_num = p_a->tx_hetb_queue_num ;
|
||||
req_payload->cfg->dump_hesigb_enable = p_a->dump_hesigb_enable ;
|
||||
req_payload->cfg->magic = p_a->magic ;
|
||||
|
||||
/* uint64 - TODO: portable? */
|
||||
req_payload->cfg->feature_caps = p_a->feature_caps ;
|
||||
break;
|
||||
} case RPC_ID__Req_WifiGetConfig: {
|
||||
wifi_cfg_t * p_a = &app_req->u.wifi_config;
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiGetConfig, req_wifi_get_config,
|
||||
rpc__req__wifi_get_config__init);
|
||||
|
||||
req_payload->iface = p_a->iface;
|
||||
break;
|
||||
} case RPC_ID__Req_WifiScanParams: {
|
||||
rpc_wifi_scan_params_t *p_a = &app_req->u.wifi_scan_params;
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiScanParams, req_wifi_scan_params,
|
||||
rpc__req__wifi_scan_params__init);
|
||||
|
||||
req_payload->cmd = p_a->cmd;
|
||||
if (!p_a->is_config_null) {
|
||||
RPC_ALLOC_ELEMENT(WifiScanDefaultParams, req_payload->config, wifi_scan_default_params__init);
|
||||
RPC_ALLOC_ELEMENT(WifiScanTime, req_payload->config->scan_time, wifi_scan_time__init);
|
||||
RPC_ALLOC_ELEMENT(WifiActiveScanTime, req_payload->config->scan_time->active, wifi_active_scan_time__init);
|
||||
|
||||
req_payload->config->scan_time->passive = p_a->config.scan_time.passive;
|
||||
req_payload->config->scan_time->active->min = p_a->config.scan_time.active.min;
|
||||
req_payload->config->scan_time->active->max = p_a->config.scan_time.active.max;
|
||||
req_payload->config->home_chan_dwell_time = p_a->config.home_chan_dwell_time;
|
||||
req_payload->is_config_null = false;
|
||||
} else {
|
||||
req_payload->is_config_null = true;
|
||||
}
|
||||
break;
|
||||
} case RPC_ID__Req_WifiSetConfig: {
|
||||
wifi_cfg_t * p_a = &app_req->u.wifi_config;
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiSetConfig, req_wifi_set_config,
|
||||
rpc__req__wifi_set_config__init);
|
||||
|
||||
req_payload->iface = p_a->iface;
|
||||
|
||||
RPC_ALLOC_ELEMENT(WifiConfig, req_payload->cfg, wifi_config__init);
|
||||
|
||||
switch(req_payload->iface) {
|
||||
|
||||
case WIFI_IF_STA: {
|
||||
req_payload->cfg->u_case = WIFI_CONFIG__U_STA;
|
||||
|
||||
wifi_sta_config_t *p_a_sta = &p_a->u.sta;
|
||||
RPC_ALLOC_ELEMENT(WifiStaConfig, req_payload->cfg->sta, wifi_sta_config__init);
|
||||
WifiStaConfig *p_c_sta = req_payload->cfg->sta;
|
||||
RPC_REQ_COPY_STR(p_c_sta->ssid, p_a_sta->ssid, SSID_LENGTH);
|
||||
|
||||
RPC_REQ_COPY_STR(p_c_sta->password, p_a_sta->password, PASSWORD_LENGTH);
|
||||
|
||||
p_c_sta->scan_method = p_a_sta->scan_method;
|
||||
p_c_sta->bssid_set = p_a_sta->bssid_set;
|
||||
|
||||
if (p_a_sta->bssid_set)
|
||||
RPC_REQ_COPY_BYTES(p_c_sta->bssid, p_a_sta->bssid, BSSID_BYTES_SIZE);
|
||||
|
||||
p_c_sta->channel = p_a_sta->channel;
|
||||
p_c_sta->listen_interval = p_a_sta->listen_interval;
|
||||
p_c_sta->sort_method = p_a_sta->sort_method;
|
||||
RPC_ALLOC_ELEMENT(WifiScanThreshold, p_c_sta->threshold, wifi_scan_threshold__init);
|
||||
p_c_sta->threshold->rssi = p_a_sta->threshold.rssi;
|
||||
p_c_sta->threshold->authmode = p_a_sta->threshold.authmode;
|
||||
#if H_PRESENT_IN_ESP_IDF_5_4_0
|
||||
p_c_sta->threshold->rssi_5g_adjustment = p_a_sta->threshold.rssi_5g_adjustment;
|
||||
#endif
|
||||
RPC_ALLOC_ELEMENT(WifiPmfConfig, p_c_sta->pmf_cfg, wifi_pmf_config__init);
|
||||
p_c_sta->pmf_cfg->capable = p_a_sta->pmf_cfg.capable;
|
||||
p_c_sta->pmf_cfg->required = p_a_sta->pmf_cfg.required;
|
||||
|
||||
if (p_a_sta->rm_enabled)
|
||||
H_SET_BIT(WIFI_STA_CONFIG_1_rm_enabled, p_c_sta->bitmask);
|
||||
|
||||
if (p_a_sta->btm_enabled)
|
||||
H_SET_BIT(WIFI_STA_CONFIG_1_btm_enabled, p_c_sta->bitmask);
|
||||
|
||||
if (p_a_sta->mbo_enabled)
|
||||
H_SET_BIT(WIFI_STA_CONFIG_1_mbo_enabled, p_c_sta->bitmask);
|
||||
|
||||
if (p_a_sta->ft_enabled)
|
||||
H_SET_BIT(WIFI_STA_CONFIG_1_ft_enabled, p_c_sta->bitmask);
|
||||
|
||||
if (p_a_sta->owe_enabled)
|
||||
H_SET_BIT(WIFI_STA_CONFIG_1_owe_enabled, p_c_sta->bitmask);
|
||||
|
||||
if (p_a_sta->transition_disable)
|
||||
H_SET_BIT(WIFI_STA_CONFIG_1_transition_disable, p_c_sta->bitmask);
|
||||
|
||||
#if H_DECODE_WIFI_RESERVED_FIELD
|
||||
#if H_WIFI_NEW_RESERVED_FIELD_NAMES
|
||||
WIFI_STA_CONFIG_2_SET_RESERVED_VAL(p_a_sta->reserved2, p_c_sta->he_bitmask);
|
||||
#else
|
||||
WIFI_STA_CONFIG_2_SET_RESERVED_VAL(p_a_sta->he_reserved, p_c_sta->he_bitmask);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
p_c_sta->sae_pwe_h2e = p_a_sta->sae_pwe_h2e;
|
||||
p_c_sta->sae_pk_mode = p_a_sta->sae_pk_mode;
|
||||
p_c_sta->failure_retry_cnt = p_a_sta->failure_retry_cnt;
|
||||
|
||||
if (p_a_sta->he_dcm_set)
|
||||
H_SET_BIT(WIFI_STA_CONFIG_2_he_dcm_set_BIT, p_c_sta->he_bitmask);
|
||||
|
||||
// WIFI_HE_STA_CONFIG_he_dcm_max_constellation_tx is two bits wide
|
||||
if (p_a_sta->he_dcm_max_constellation_tx)
|
||||
p_c_sta->he_bitmask |= ((p_a_sta->he_dcm_max_constellation_tx & 0x03) << WIFI_STA_CONFIG_2_he_dcm_max_constellation_tx_BITS);
|
||||
|
||||
// WIFI_HE_STA_CONFIG_he_dcm_max_constellation_rx is two bits wide
|
||||
if (p_a_sta->he_dcm_max_constellation_rx)
|
||||
p_c_sta->he_bitmask |= ((p_a_sta->he_dcm_max_constellation_rx & 0x03) << WIFI_STA_CONFIG_2_he_dcm_max_constellation_rx_BITS);
|
||||
|
||||
if (p_a_sta->he_mcs9_enabled)
|
||||
H_SET_BIT(WIFI_STA_CONFIG_2_he_mcs9_enabled_BIT, p_c_sta->he_bitmask);
|
||||
|
||||
if (p_a_sta->he_su_beamformee_disabled)
|
||||
H_SET_BIT(WIFI_STA_CONFIG_2_he_su_beamformee_disabled_BIT, p_c_sta->he_bitmask);
|
||||
|
||||
if (p_a_sta->he_trig_su_bmforming_feedback_disabled)
|
||||
H_SET_BIT(WIFI_STA_CONFIG_2_he_trig_su_bmforming_feedback_disabled_BIT, p_c_sta->he_bitmask);
|
||||
|
||||
if (p_a_sta->he_trig_mu_bmforming_partial_feedback_disabled)
|
||||
H_SET_BIT(WIFI_STA_CONFIG_2_he_trig_mu_bmforming_partial_feedback_disabled_BIT, p_c_sta->he_bitmask);
|
||||
|
||||
if (p_a_sta->he_trig_cqi_feedback_disabled)
|
||||
H_SET_BIT(WIFI_STA_CONFIG_2_he_trig_cqi_feedback_disabled_BIT, p_c_sta->he_bitmask);
|
||||
|
||||
#if H_PRESENT_IN_ESP_IDF_5_5_0
|
||||
if (p_a_sta->vht_su_beamformee_disabled)
|
||||
H_SET_BIT(WIFI_STA_CONFIG_2_vht_su_beamformee_disabled, p_c_sta->he_bitmask);
|
||||
|
||||
if (p_a_sta->vht_mu_beamformee_disabled)
|
||||
H_SET_BIT(WIFI_STA_CONFIG_2_vht_mu_beamformee_disabled, p_c_sta->he_bitmask);
|
||||
|
||||
if (p_a_sta->vht_mcs8_enabled)
|
||||
H_SET_BIT(WIFI_STA_CONFIG_2_vht_mcs8_enabled, p_c_sta->he_bitmask);
|
||||
#endif
|
||||
|
||||
#if H_DECODE_WIFI_RESERVED_FIELD
|
||||
#if H_WIFI_NEW_RESERVED_FIELD_NAMES
|
||||
WIFI_STA_CONFIG_2_SET_RESERVED_VAL(p_a_sta->reserved2, p_c_sta->he_bitmask);
|
||||
#else
|
||||
WIFI_STA_CONFIG_2_SET_RESERVED_VAL(p_a_sta->he_reserved, p_c_sta->he_bitmask);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
RPC_REQ_COPY_BYTES(p_c_sta->sae_h2e_identifier, p_a_sta->sae_h2e_identifier, SAE_H2E_IDENTIFIER_LEN);
|
||||
break;
|
||||
} case WIFI_IF_AP: {
|
||||
req_payload->cfg->u_case = WIFI_CONFIG__U_AP;
|
||||
|
||||
wifi_ap_config_t * p_a_ap = &p_a->u.ap;
|
||||
RPC_ALLOC_ELEMENT(WifiApConfig, req_payload->cfg->ap, wifi_ap_config__init);
|
||||
WifiApConfig * p_c_ap = req_payload->cfg->ap;
|
||||
|
||||
RPC_REQ_COPY_STR(p_c_ap->ssid, p_a_ap->ssid, SSID_LENGTH);
|
||||
RPC_REQ_COPY_STR(p_c_ap->password, p_a_ap->password, PASSWORD_LENGTH);
|
||||
p_c_ap->ssid_len = p_a_ap->ssid_len;
|
||||
p_c_ap->channel = p_a_ap->channel;
|
||||
p_c_ap->authmode = p_a_ap->authmode;
|
||||
p_c_ap->ssid_hidden = p_a_ap->ssid_hidden;
|
||||
p_c_ap->max_connection = p_a_ap->max_connection;
|
||||
p_c_ap->beacon_interval = p_a_ap->beacon_interval;
|
||||
p_c_ap->csa_count = p_a_ap->csa_count;
|
||||
p_c_ap->dtim_period = p_a_ap->dtim_period;
|
||||
p_c_ap->pairwise_cipher = p_a_ap->pairwise_cipher;
|
||||
p_c_ap->ftm_responder = p_a_ap->ftm_responder;
|
||||
RPC_ALLOC_ELEMENT(WifiPmfConfig, p_c_ap->pmf_cfg, wifi_pmf_config__init);
|
||||
p_c_ap->pmf_cfg->capable = p_a_ap->pmf_cfg.capable;
|
||||
p_c_ap->pmf_cfg->required = p_a_ap->pmf_cfg.required;
|
||||
p_c_ap->sae_pwe_h2e = p_a_ap->sae_pwe_h2e;
|
||||
#if H_GOT_AP_CONFIG_PARAM_TRANSITION_DISABLE
|
||||
p_c_ap->transition_disable = p_a_ap->transition_disable;
|
||||
#endif
|
||||
#if H_PRESENT_IN_ESP_IDF_5_5_0
|
||||
p_c_ap->sae_ext = p_a_ap->sae_ext;
|
||||
RPC_ALLOC_ELEMENT(WifiBssMaxIdleConfig, p_c_ap->bss_max_idle_cfg, wifi_bss_max_idle_config__init);
|
||||
p_c_ap->bss_max_idle_cfg->period = p_a_ap->bss_max_idle_cfg.period;
|
||||
p_c_ap->bss_max_idle_cfg->protected_keep_alive = p_a_ap->bss_max_idle_cfg.protected_keep_alive;
|
||||
p_c_ap->gtk_rekey_interval = p_a_ap->gtk_rekey_interval;
|
||||
#endif
|
||||
break;
|
||||
} default: {
|
||||
ESP_LOGE(TAG, "unexpected wifi iface [%u]\n", p_a->iface);
|
||||
break;
|
||||
}
|
||||
|
||||
} /* switch */
|
||||
break;
|
||||
|
||||
} case RPC_ID__Req_WifiScanStart: {
|
||||
wifi_scan_config_t * p_a = &app_req->u.wifi_scan_config.cfg;
|
||||
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiScanStart, req_wifi_scan_start,
|
||||
rpc__req__wifi_scan_start__init);
|
||||
|
||||
req_payload->block = app_req->u.wifi_scan_config.block;
|
||||
if (app_req->u.wifi_scan_config.cfg_set) {
|
||||
|
||||
RPC_ALLOC_ELEMENT(WifiScanConfig, req_payload->config, wifi_scan_config__init);
|
||||
|
||||
RPC_ALLOC_ELEMENT(WifiScanTime , req_payload->config->scan_time, wifi_scan_time__init);
|
||||
RPC_ALLOC_ELEMENT(WifiActiveScanTime, req_payload->config->scan_time->active, wifi_active_scan_time__init);
|
||||
ESP_LOGD(TAG, "scan start4\n");
|
||||
|
||||
WifiScanConfig *p_c = req_payload->config;
|
||||
WifiScanTime *p_c_st = NULL;
|
||||
wifi_scan_time_t *p_a_st = &p_a->scan_time;
|
||||
|
||||
RPC_REQ_COPY_STR(p_c->ssid, p_a->ssid, SSID_LENGTH);
|
||||
RPC_REQ_COPY_STR(p_c->bssid, p_a->bssid, MAC_SIZE_BYTES);
|
||||
p_c->channel = p_a->channel;
|
||||
p_c->show_hidden = p_a->show_hidden;
|
||||
p_c->scan_type = p_a->scan_type;
|
||||
|
||||
p_c_st = p_c->scan_time;
|
||||
|
||||
p_c_st->passive = p_a_st->passive;
|
||||
p_c_st->active->min = p_a_st->active.min ;
|
||||
p_c_st->active->max = p_a_st->active.max ;
|
||||
|
||||
p_c->home_chan_dwell_time = p_a->home_chan_dwell_time;
|
||||
|
||||
RPC_ALLOC_ELEMENT(WifiScanChannelBitmap, p_c->channel_bitmap, wifi_scan_channel_bitmap__init);
|
||||
p_c->channel_bitmap->ghz_2_channels = p_a->channel_bitmap.ghz_2_channels;
|
||||
p_c->channel_bitmap->ghz_5_channels = p_a->channel_bitmap.ghz_5_channels;
|
||||
|
||||
req_payload->config_set = 1;
|
||||
}
|
||||
ESP_LOGI(TAG, "Scan start Req\n");
|
||||
|
||||
break;
|
||||
|
||||
} case RPC_ID__Req_WifiScanGetApRecords: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiScanGetApRecords, req_wifi_scan_get_ap_records,
|
||||
rpc__req__wifi_scan_get_ap_records__init);
|
||||
req_payload->number = app_req->u.wifi_scan_ap_list.number;
|
||||
break;
|
||||
} case RPC_ID__Req_WifiDeauthSta: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiDeauthSta, req_wifi_deauth_sta,
|
||||
rpc__req__wifi_deauth_sta__init);
|
||||
req_payload->aid = app_req->u.wifi_deauth_sta.aid;
|
||||
break;
|
||||
} case RPC_ID__Req_WifiSetStorage: {
|
||||
wifi_storage_t * p = &app_req->u.wifi_storage;
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiSetStorage, req_wifi_set_storage,
|
||||
rpc__req__wifi_set_storage__init);
|
||||
req_payload->storage = *p;
|
||||
break;
|
||||
} case RPC_ID__Req_WifiSetBandwidth: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiSetBandwidth, req_wifi_set_bandwidth,
|
||||
rpc__req__wifi_set_bandwidth__init);
|
||||
req_payload->ifx = app_req->u.wifi_bandwidth.ifx;
|
||||
req_payload->bw = app_req->u.wifi_bandwidth.bw;
|
||||
break;
|
||||
} case RPC_ID__Req_WifiGetBandwidth: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiGetBandwidth, req_wifi_get_bandwidth,
|
||||
rpc__req__wifi_get_bandwidth__init);
|
||||
req_payload->ifx = app_req->u.wifi_bandwidth.ifx;
|
||||
break;
|
||||
} case RPC_ID__Req_WifiSetChannel: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiSetChannel, req_wifi_set_channel,
|
||||
rpc__req__wifi_set_channel__init);
|
||||
req_payload->primary = app_req->u.wifi_channel.primary;
|
||||
req_payload->second = app_req->u.wifi_channel.second;
|
||||
break;
|
||||
} case RPC_ID__Req_WifiSetCountryCode: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiSetCountryCode, req_wifi_set_country_code,
|
||||
rpc__req__wifi_set_country_code__init);
|
||||
RPC_REQ_COPY_BYTES(req_payload->country, (uint8_t *)&app_req->u.wifi_country_code.cc[0], sizeof(app_req->u.wifi_country_code.cc));
|
||||
req_payload->ieee80211d_enabled = app_req->u.wifi_country_code.ieee80211d_enabled;
|
||||
break;
|
||||
} case RPC_ID__Req_WifiSetCountry: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiSetCountry, req_wifi_set_country,
|
||||
rpc__req__wifi_set_country__init);
|
||||
|
||||
RPC_ALLOC_ELEMENT(WifiCountry, req_payload->country, wifi_country__init);
|
||||
RPC_REQ_COPY_BYTES(req_payload->country->cc, (uint8_t *)&app_req->u.wifi_country.cc[0], sizeof(app_req->u.wifi_country.cc));
|
||||
req_payload->country->schan = app_req->u.wifi_country.schan;
|
||||
req_payload->country->nchan = app_req->u.wifi_country.nchan;
|
||||
req_payload->country->max_tx_power = app_req->u.wifi_country.max_tx_power;
|
||||
req_payload->country->policy = app_req->u.wifi_country.policy;
|
||||
break;
|
||||
} case RPC_ID__Req_WifiApGetStaAid: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiApGetStaAid, req_wifi_ap_get_sta_aid,
|
||||
rpc__req__wifi_ap_get_sta_aid__init);
|
||||
|
||||
uint8_t * p = &app_req->u.wifi_ap_get_sta_aid.mac[0];
|
||||
RPC_REQ_COPY_BYTES(req_payload->mac, p, MAC_SIZE_BYTES);
|
||||
break;
|
||||
} case RPC_ID__Req_WifiSetProtocol: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiSetProtocol, req_wifi_set_protocol,
|
||||
rpc__req__wifi_set_protocol__init);
|
||||
req_payload->ifx = app_req->u.wifi_protocol.ifx;
|
||||
req_payload->protocol_bitmap = app_req->u.wifi_protocol.protocol_bitmap;
|
||||
break;
|
||||
} case RPC_ID__Req_WifiGetProtocol: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiGetProtocol, req_wifi_get_protocol,
|
||||
rpc__req__wifi_get_protocol__init);
|
||||
req_payload->ifx = app_req->u.wifi_protocol.ifx;
|
||||
break;
|
||||
} case RPC_ID__Req_GetCoprocessorFwVersion: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqGetCoprocessorFwVersion, req_get_coprocessor_fwversion,
|
||||
rpc__req__get_coprocessor_fw_version__init);
|
||||
break;
|
||||
} case RPC_ID__Req_WifiSetInactiveTime: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiSetInactiveTime, req_wifi_set_inactive_time,
|
||||
rpc__req__wifi_set_inactive_time__init);
|
||||
req_payload->ifx = app_req->u.wifi_inactive_time.ifx;
|
||||
req_payload->sec = app_req->u.wifi_inactive_time.sec;
|
||||
break;
|
||||
} case RPC_ID__Req_WifiGetInactiveTime: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiGetInactiveTime, req_wifi_get_inactive_time,
|
||||
rpc__req__wifi_get_inactive_time__init);
|
||||
req_payload->ifx = app_req->u.wifi_inactive_time.ifx;
|
||||
break;
|
||||
} case RPC_ID__Req_WifiDisablePmfConfig: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiDisablePmfConfig, req_wifi_disable_pmf_config,
|
||||
rpc__req__wifi_disable_pmf_config__init);
|
||||
req_payload->ifx = app_req->u.wifi_disable_pmf_config.ifx;
|
||||
break;
|
||||
#if H_WIFI_HE_SUPPORT
|
||||
} case RPC_ID__Req_WifiStaTwtConfig: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiStaTwtConfig, req_wifi_sta_twt_config,
|
||||
rpc__req__wifi_sta_twt_config__init);
|
||||
RPC_ALLOC_ELEMENT(WifiTwtConfig, req_payload->config, wifi_twt_config__init);
|
||||
req_payload->config->post_wakeup_event = app_req->u.wifi_twt_config.post_wakeup_event;
|
||||
#if H_GOT_TWT_ENABLE_KEEP_ALIVE
|
||||
req_payload->config->twt_enable_keep_alive = app_req->u.wifi_twt_config.twt_enable_keep_alive;
|
||||
#endif
|
||||
break;
|
||||
} case RPC_ID__Req_WifiStaItwtSetup: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiStaItwtSetup, req_wifi_sta_itwt_setup,
|
||||
rpc__req__wifi_sta_itwt_setup__init);
|
||||
RPC_ALLOC_ELEMENT(WifiItwtSetupConfig, req_payload->setup_config, wifi_itwt_setup_config__init);
|
||||
#if H_WIFI_HE_GREATER_THAN_ESP_IDF_5_3
|
||||
wifi_itwt_setup_config_t * p_a_cfg = &app_req->u.wifi_itwt_setup_config;
|
||||
#else
|
||||
wifi_twt_setup_config_t * p_a_cfg = &app_req->u.wifi_twt_setup_config;
|
||||
#endif
|
||||
WifiItwtSetupConfig * p_c_cfg = req_payload->setup_config;
|
||||
|
||||
p_c_cfg->setup_cmd = p_a_cfg->setup_cmd;
|
||||
if (p_a_cfg->trigger)
|
||||
H_SET_BIT(WIFI_ITWT_CONFIG_1_trigger_BIT, p_c_cfg->bitmask_1);
|
||||
|
||||
if (p_a_cfg->flow_type)
|
||||
H_SET_BIT(WIFI_ITWT_CONFIG_1_flow_type_BIT, p_c_cfg->bitmask_1);
|
||||
|
||||
// WIFI_ITWT_CONFIG_1_flow_id_BIT is three bits wide
|
||||
if (p_a_cfg->flow_id)
|
||||
p_c_cfg->bitmask_1 |= ((p_a_cfg->flow_id & 0x07) << WIFI_ITWT_CONFIG_1_flow_id_BIT);
|
||||
|
||||
// WIFI_ITWT_CONFIG_1_wake_invl_expn_BIT is five bits wide
|
||||
if (p_a_cfg->wake_invl_expn)
|
||||
p_c_cfg->bitmask_1 |= ((p_a_cfg->wake_invl_expn & 0x1F) << WIFI_ITWT_CONFIG_1_wake_invl_expn_BIT);
|
||||
|
||||
if (p_a_cfg->wake_duration_unit)
|
||||
H_SET_BIT(WIFI_ITWT_CONFIG_1_wake_duration_unit_BIT, p_c_cfg->bitmask_1);
|
||||
|
||||
#if H_DECODE_WIFI_RESERVED_FIELD
|
||||
WIFI_ITWT_CONFIG_1_SET_RESERVED_VAL(p_a_cfg->reserved, p_c_cfg->bitmask_1);
|
||||
#endif
|
||||
p_c_cfg->min_wake_dura = p_a_cfg->min_wake_dura;
|
||||
p_c_cfg->wake_invl_mant = p_a_cfg->wake_invl_mant;
|
||||
p_c_cfg->twt_id = p_a_cfg->twt_id;
|
||||
p_c_cfg->timeout_time_ms = p_a_cfg->timeout_time_ms;
|
||||
|
||||
break;
|
||||
} case RPC_ID__Req_WifiStaItwtTeardown: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiStaItwtTeardown, req_wifi_sta_itwt_teardown,
|
||||
rpc__req__wifi_sta_itwt_teardown__init);
|
||||
|
||||
req_payload->flow_id = app_req->u.wifi_itwt_flow_id;
|
||||
break;
|
||||
} case RPC_ID__Req_WifiStaItwtSuspend: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiStaItwtSuspend, req_wifi_sta_itwt_suspend,
|
||||
rpc__req__wifi_sta_itwt_suspend__init);
|
||||
|
||||
req_payload->flow_id = app_req->u.wifi_itwt_suspend.flow_id;
|
||||
req_payload->suspend_time_ms = app_req->u.wifi_itwt_suspend.suspend_time_ms;
|
||||
break;
|
||||
} case RPC_ID__Req_WifiStaItwtGetFlowIdStatus: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiStaItwtGetFlowIdStatus, req_wifi_sta_itwt_get_flow_id_status,
|
||||
rpc__req__wifi_sta_itwt_get_flow_id_status__init);
|
||||
break;
|
||||
} case RPC_ID__Req_WifiStaItwtSendProbeReq: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiStaItwtSendProbeReq, req_wifi_sta_itwt_send_probe_req,
|
||||
rpc__req__wifi_sta_itwt_send_probe_req__init);
|
||||
req_payload->timeout_ms = app_req->u.wifi_itwt_probe_req_timeout_ms;
|
||||
break;
|
||||
} case RPC_ID__Req_WifiStaItwtSetTargetWakeTimeOffset: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiStaItwtSetTargetWakeTimeOffset, req_wifi_sta_itwt_set_target_wake_time_offset,
|
||||
rpc__req__wifi_sta_itwt_set_target_wake_time_offset__init);
|
||||
req_payload->offset_us = app_req->u.wifi_itwt_set_target_wake_time_offset_us;
|
||||
break;
|
||||
#endif // H_WIFI_HE_SUPPORT
|
||||
#if H_WIFI_DUALBAND_SUPPORT
|
||||
} case RPC_ID__Req_WifiSetProtocols: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiSetProtocols, req_wifi_set_protocols,
|
||||
rpc__req__wifi_set_protocols__init);
|
||||
req_payload->ifx = app_req->u.wifi_protocols.ifx;
|
||||
|
||||
RPC_ALLOC_ELEMENT(WifiProtocols, req_payload->protocols, wifi_protocols__init);
|
||||
req_payload->protocols->ghz_2g = app_req->u.wifi_protocols.ghz_2g;
|
||||
req_payload->protocols->ghz_5g = app_req->u.wifi_protocols.ghz_5g;
|
||||
break;
|
||||
} case RPC_ID__Req_WifiGetProtocols: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiGetProtocols, req_wifi_get_protocols,
|
||||
rpc__req__wifi_get_protocols__init);
|
||||
req_payload->ifx = app_req->u.wifi_protocols.ifx;
|
||||
break;
|
||||
} case RPC_ID__Req_WifiSetBandwidths: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiSetBandwidths, req_wifi_set_bandwidths,
|
||||
rpc__req__wifi_set_bandwidths__init);
|
||||
req_payload->ifx = app_req->u.wifi_bandwidths.ifx;
|
||||
|
||||
RPC_ALLOC_ELEMENT(WifiBandwidths, req_payload->bandwidths, wifi_bandwidths__init);
|
||||
req_payload->bandwidths->ghz_2g = app_req->u.wifi_bandwidths.ghz_2g;
|
||||
req_payload->bandwidths->ghz_5g = app_req->u.wifi_bandwidths.ghz_5g;
|
||||
break;
|
||||
} case RPC_ID__Req_WifiGetBandwidths: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiGetBandwidths, req_wifi_get_bandwidths,
|
||||
rpc__req__wifi_get_bandwidths__init);
|
||||
req_payload->ifx = app_req->u.wifi_bandwidths.ifx;
|
||||
break;
|
||||
} case RPC_ID__Req_WifiSetBand: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiSetBand, req_wifi_set_band,
|
||||
rpc__req__wifi_set_band__init);
|
||||
req_payload->band = app_req->u.wifi_band;
|
||||
break;
|
||||
} case RPC_ID__Req_WifiSetBandMode: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiSetBandMode, req_wifi_set_bandmode,
|
||||
rpc__req__wifi_set_band_mode__init);
|
||||
req_payload->bandmode = app_req->u.wifi_band_mode;
|
||||
break;
|
||||
#endif // H_WIFI_DUALBAND_SUPPORT
|
||||
} case RPC_ID__Req_IfaceMacAddrSetGet: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqIfaceMacAddrSetGet, req_iface_mac_addr_set_get,
|
||||
rpc__req__iface_mac_addr_set_get__init);
|
||||
req_payload->set = app_req->u.iface_mac.set;
|
||||
req_payload->type = app_req->u.iface_mac.type;
|
||||
if (req_payload->set) {
|
||||
RPC_REQ_COPY_BYTES(req_payload->mac, app_req->u.iface_mac.mac,
|
||||
app_req->u.iface_mac.mac_len);
|
||||
}
|
||||
break;
|
||||
} case RPC_ID__Req_FeatureControl: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqFeatureControl, req_feature_control,
|
||||
rpc__req__feature_control__init);
|
||||
// convert from rpc_slave_if.h enums to proto enums
|
||||
switch (app_req->u.feature_control.feature) {
|
||||
case FEATURE_BT:
|
||||
req_payload->feature = RPC_FEATURE__Feature_Bluetooth;
|
||||
break;
|
||||
case FEATURE_OPENTHREAD_RCP:
|
||||
req_payload->feature = RPC_FEATURE__Feature_Openthread_Rcp;
|
||||
break;
|
||||
default:
|
||||
req_payload->feature = RPC_FEATURE__Feature_None;
|
||||
break;
|
||||
}
|
||||
switch (app_req->u.feature_control.command) {
|
||||
case FEATURE_COMMAND_BT_INIT:
|
||||
req_payload->command = RPC_FEATURE_COMMAND__Feature_Command_BT_Init;
|
||||
break;
|
||||
case FEATURE_COMMAND_BT_DEINIT:
|
||||
req_payload->command = RPC_FEATURE_COMMAND__Feature_Command_BT_Deinit;
|
||||
break;
|
||||
case FEATURE_COMMAND_BT_ENABLE:
|
||||
req_payload->command = RPC_FEATURE_COMMAND__Feature_Command_BT_Enable;
|
||||
break;
|
||||
case FEATURE_COMMAND_BT_DISABLE:
|
||||
req_payload->command = RPC_FEATURE_COMMAND__Feature_Command_BT_Disable;
|
||||
break;
|
||||
case FEATURE_COMMAND_INIT:
|
||||
req_payload->command = RPC_FEATURE_COMMAND__Feature_Command_Init;
|
||||
break;
|
||||
case FEATURE_COMMAND_DEINIT:
|
||||
req_payload->command = RPC_FEATURE_COMMAND__Feature_Command_Deinit;
|
||||
break;
|
||||
case FEATURE_COMMAND_ENABLE:
|
||||
req_payload->command = RPC_FEATURE_COMMAND__Feature_Command_Enable;
|
||||
break;
|
||||
case FEATURE_COMMAND_DISABLE:
|
||||
req_payload->command = RPC_FEATURE_COMMAND__Feature_Command_Disable;
|
||||
break;
|
||||
case FEATURE_COMMAND_QUERY:
|
||||
req_payload->command = RPC_FEATURE_COMMAND__Feature_Command_Query;
|
||||
break;
|
||||
default:
|
||||
req_payload->command = RPC_FEATURE_COMMAND__Feature_Command_None;
|
||||
break;
|
||||
}
|
||||
switch (app_req->u.feature_control.option) {
|
||||
case FEATURE_OPTION_BT_DEINIT_RELEASE_MEMORY:
|
||||
req_payload->option = RPC_FEATURE_OPTION__Feature_Option_BT_Deinit_Release_Memory;
|
||||
break;
|
||||
case FEATURE_OPTION_QUERY_CONFIGURED:
|
||||
req_payload->option = RPC_FEATURE_OPTION__Feature_Option_Query_Configured;
|
||||
break;
|
||||
case FEATURE_OPTION_QUERY_INITED:
|
||||
req_payload->option = RPC_FEATURE_OPTION__Feature_Option_Query_Inited;
|
||||
break;
|
||||
case FEATURE_OPTION_QUERY_ENABLED:
|
||||
req_payload->option = RPC_FEATURE_OPTION__Feature_Option_Query_Enabled;
|
||||
break;
|
||||
case FEATURE_OPTION_QUERY_READY:
|
||||
req_payload->option = RPC_FEATURE_OPTION__Feature_Option_Query_Ready;
|
||||
break;
|
||||
default:
|
||||
req_payload->option = RPC_FEATURE_OPTION__Feature_Option_None;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
} case RPC_ID__Req_IfaceMacAddrLenGet: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqIfaceMacAddrLenGet, req_iface_mac_addr_len_get,
|
||||
rpc__req__iface_mac_addr_len_get__init);
|
||||
req_payload->type = app_req->u.iface_mac_len.type;
|
||||
break;
|
||||
} case RPC_ID__Req_SetDhcpDnsStatus: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqSetDhcpDnsStatus, req_set_dhcp_dns,
|
||||
rpc__req__set_dhcp_dns_status__init);
|
||||
RpcReqSetDhcpDnsStatus *p_c = req_payload;
|
||||
rpc_set_dhcp_dns_status_t* p_a = &app_req->u.slave_dhcp_dns_status;
|
||||
|
||||
p_c->iface = p_a->iface;
|
||||
p_c->dhcp_up = p_a->dhcp_up;
|
||||
p_c->dns_up = p_a->dns_up;
|
||||
p_c->dns_type = p_a->dns_type;
|
||||
p_c->net_link_up = p_a->net_link_up;
|
||||
|
||||
RPC_REQ_COPY_STR(p_c->dhcp_ip, p_a->dhcp_ip, 64);
|
||||
RPC_REQ_COPY_STR(p_c->dhcp_nm, p_a->dhcp_nm, 64);
|
||||
RPC_REQ_COPY_STR(p_c->dhcp_gw, p_a->dhcp_gw, 64);
|
||||
RPC_REQ_COPY_STR(p_c->dns_ip, p_a->dns_ip, 64);
|
||||
break;
|
||||
#if H_MEM_MONITOR
|
||||
} case RPC_ID__Req_MemMonitor: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqMemMonitor, req_mem_monitor,
|
||||
rpc__req__mem_monitor__init);
|
||||
RPC_ALLOC_ELEMENT(HeapSizeThreshold, req_payload->internal, heap_size_threshold__init);
|
||||
RPC_ALLOC_ELEMENT(HeapSizeThreshold, req_payload->external, heap_size_threshold__init);
|
||||
|
||||
RpcReqMemMonitor *p_c = req_payload;
|
||||
esp_hosted_config_mem_monitor_t *p_a = &app_req->u.config_mem_monitor;
|
||||
|
||||
if (p_a->config == ESP_HOSTED_MEMMONITOR_NO_CHANGE) {
|
||||
p_c->config = RPC__MEM_MONITOR_CONFIG__MEMMONITOR_NO_CHANGE;
|
||||
} else if (p_a->config == ESP_HOSTED_MEMMONITOR_DISABLE) {
|
||||
p_c->config = RPC__MEM_MONITOR_CONFIG__MEMMONITOR_DISABLE;
|
||||
} else if (p_a->config == ESP_HOSTED_MEMMONITOR_ENABLE) {
|
||||
p_c->config = RPC__MEM_MONITOR_CONFIG__MEMMONITOR_ENABLE;
|
||||
}
|
||||
p_c->report_always = p_a->report_always;
|
||||
p_c->interval_sec = p_a->interval_sec;
|
||||
p_c->internal->threshold_mem_dma = p_a->internal_mem.threshold_mem_dma;
|
||||
p_c->internal->threshold_mem_8bit = p_a->internal_mem.threshold_mem_8bit;
|
||||
p_c->external->threshold_mem_dma = p_a->external_mem.threshold_mem_dma;
|
||||
p_c->external->threshold_mem_8bit = p_a->external_mem.threshold_mem_8bit;
|
||||
break;
|
||||
#endif
|
||||
#if H_WIFI_ENTERPRISE_SUPPORT
|
||||
} case RPC_ID__Req_EapSetIdentity: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqEapSetIdentity, req_eap_set_identity,
|
||||
rpc__req__eap_set_identity__init);
|
||||
RPC_REQ_COPY_BYTES(req_payload->identity, (uint8_t *)app_req->u.eap_identity.identity, app_req->u.eap_identity.len);
|
||||
req_payload->len = app_req->u.eap_identity.len;
|
||||
break;
|
||||
} case RPC_ID__Req_EapSetUsername: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqEapSetUsername, req_eap_set_username,
|
||||
rpc__req__eap_set_username__init);
|
||||
RPC_REQ_COPY_BYTES(req_payload->username, (uint8_t *)app_req->u.eap_username.username, app_req->u.eap_username.len);
|
||||
req_payload->len = app_req->u.eap_username.len;
|
||||
break;
|
||||
} case RPC_ID__Req_EapSetPassword: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqEapSetPassword, req_eap_set_password,
|
||||
rpc__req__eap_set_password__init);
|
||||
RPC_REQ_COPY_BYTES(req_payload->password, (uint8_t *)app_req->u.eap_password.password, app_req->u.eap_password.len);
|
||||
req_payload->len = app_req->u.eap_password.len;
|
||||
break;
|
||||
} case RPC_ID__Req_EapSetNewPassword: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqEapSetNewPassword, req_eap_set_new_password,
|
||||
rpc__req__eap_set_new_password__init);
|
||||
RPC_REQ_COPY_BYTES(req_payload->new_password, (uint8_t *)app_req->u.eap_password.password, app_req->u.eap_password.len);
|
||||
req_payload->len = app_req->u.eap_password.len;
|
||||
break;
|
||||
} case RPC_ID__Req_EapSetCaCert: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqEapSetCaCert, req_eap_set_ca_cert,
|
||||
rpc__req__eap_set_ca_cert__init);
|
||||
RPC_REQ_COPY_BYTES(req_payload->ca_cert, (uint8_t *)app_req->u.eap_ca_cert.ca_cert, app_req->u.eap_ca_cert.len);
|
||||
req_payload->ca_cert_len = app_req->u.eap_ca_cert.len;
|
||||
break;
|
||||
} case RPC_ID__Req_EapSetCertificateAndKey: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqEapSetCertificateAndKey, req_eap_set_certificate_and_key,
|
||||
rpc__req__eap_set_certificate_and_key__init);
|
||||
RPC_REQ_COPY_BYTES(req_payload->client_cert, (uint8_t *)app_req->u.eap_cert_key.client_cert, app_req->u.eap_cert_key.client_cert_len);
|
||||
req_payload->client_cert_len = app_req->u.eap_cert_key.client_cert_len;
|
||||
RPC_REQ_COPY_BYTES(req_payload->private_key, (uint8_t *)app_req->u.eap_cert_key.private_key, app_req->u.eap_cert_key.private_key_len);
|
||||
req_payload->private_key_len = app_req->u.eap_cert_key.private_key_len;
|
||||
RPC_REQ_COPY_BYTES(req_payload->private_key_password, (uint8_t *)app_req->u.eap_cert_key.private_key_password, app_req->u.eap_cert_key.private_key_passwd_len);
|
||||
req_payload->private_key_passwd_len = app_req->u.eap_cert_key.private_key_passwd_len;
|
||||
break;
|
||||
} case RPC_ID__Req_EapSetDisableTimeCheck: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqEapSetDisableTimeCheck, req_eap_set_disable_time_check,
|
||||
rpc__req__eap_set_disable_time_check__init);
|
||||
req_payload->disable = app_req->u.eap_disable_time_check.disable;
|
||||
break;
|
||||
} case RPC_ID__Req_EapSetTtlsPhase2Method: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqEapSetTtlsPhase2Method, req_eap_set_ttls_phase2_method,
|
||||
rpc__req__eap_set_ttls_phase2_method__init);
|
||||
req_payload->type = app_req->u.eap_ttls_phase2;
|
||||
break;
|
||||
} case RPC_ID__Req_EapSetSuitebCertification: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqEapSetSuiteb192bitCertification, req_eap_set_suiteb_certification,
|
||||
rpc__req__eap_set_suiteb192bit_certification__init);
|
||||
req_payload->enable = app_req->u.eap_suiteb_192bit.enable;
|
||||
break;
|
||||
} case RPC_ID__Req_EapSetPacFile: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqEapSetPacFile, req_eap_set_pac_file,
|
||||
rpc__req__eap_set_pac_file__init);
|
||||
RPC_REQ_COPY_BYTES(req_payload->pac_file, (uint8_t *)app_req->u.eap_pac_file.pac_file, app_req->u.eap_pac_file.len);
|
||||
req_payload->pac_file_len = app_req->u.eap_pac_file.len;
|
||||
break;
|
||||
} case RPC_ID__Req_EapSetFastParams: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqEapSetFastParams, req_eap_set_fast_params,
|
||||
rpc__req__eap_set_fast_params__init);
|
||||
RPC_ALLOC_ELEMENT(EapFastConfig, req_payload->eap_fast_config, eap_fast_config__init);
|
||||
req_payload->eap_fast_config->fast_provisioning = app_req->u.eap_fast_config.fast_provisioning;
|
||||
req_payload->eap_fast_config->fast_max_pac_list_len = app_req->u.eap_fast_config.fast_max_pac_list_len;
|
||||
req_payload->eap_fast_config->fast_pac_format_binary = app_req->u.eap_fast_config.fast_pac_format_binary;
|
||||
break;
|
||||
} case RPC_ID__Req_EapUseDefaultCertBundle: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqEapUseDefaultCertBundle, req_eap_use_default_cert_bundle,
|
||||
rpc__req__eap_use_default_cert_bundle__init);
|
||||
req_payload->use_default_bundle = app_req->u.eap_default_cert_bundle.use_default;
|
||||
break;
|
||||
#if H_GOT_EAP_OKC_SUPPORT
|
||||
} case RPC_ID__Req_WifiSetOkcSupport: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqWifiSetOkcSupport, req_wifi_set_okc_support,
|
||||
rpc__req__wifi_set_okc_support__init);
|
||||
req_payload->enable = app_req->u.wifi_okc_support.enable;
|
||||
break;
|
||||
#endif
|
||||
#if H_GOT_EAP_SET_DOMAIN_NAME
|
||||
} case RPC_ID__Req_EapSetDomainName: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqEapSetDomainName, req_eap_set_domain_name,
|
||||
rpc__req__eap_set_domain_name__init);
|
||||
|
||||
RPC_REQ_COPY_BYTES(req_payload->domain_name, (uint8_t *)app_req->u.eap_domain_name.domain_name, strlen(app_req->u.eap_domain_name.domain_name) + 1);
|
||||
break;
|
||||
#endif
|
||||
#if H_GOT_SET_EAP_METHODS_API
|
||||
} case RPC_ID__Req_EapSetEapMethods: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqEapSetEapMethods, req_eap_set_eap_methods,
|
||||
rpc__req__eap_set_eap_methods__init);
|
||||
req_payload->methods = app_req->u.methods;
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
#if H_DPP_SUPPORT
|
||||
} case RPC_ID__Req_SuppDppInit: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqSuppDppInit,req_supp_dpp_init,
|
||||
rpc__req__supp_dpp_init__init);
|
||||
req_payload->cb = app_req->u.dpp_enable_cb;
|
||||
break;
|
||||
} case RPC_ID__Req_SuppDppBootstrapGen: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqSuppDppBootstrapGen,req_supp_dpp_bootstrap_gen,
|
||||
rpc__req__supp_dpp_bootstrap_gen__init);
|
||||
int str_len;
|
||||
RpcReqSuppDppBootstrapGen *p_c = req_payload;
|
||||
rpc_supp_dpp_bootstrap_gen_t* p_a = &app_req->u.dpp_bootstrap_gen;
|
||||
|
||||
p_c->type = p_a->type;
|
||||
|
||||
// chan_list: copy terminating NULL
|
||||
str_len = strlen(p_a->chan_list);
|
||||
RPC_REQ_COPY_BYTES(p_c->chan_list, (uint8_t *)p_a->chan_list, str_len + 1);
|
||||
|
||||
// key is a fixed length (if provided)
|
||||
if (p_a->key) {
|
||||
RPC_REQ_COPY_BYTES(p_c->key, (uint8_t *)p_a->key, DPP_BOOTSTRAP_GEN_KEY_LEN);
|
||||
}
|
||||
|
||||
// info: copy terminating NULL
|
||||
if (p_a->info) {
|
||||
str_len = strlen(p_a->info);
|
||||
RPC_REQ_COPY_BYTES(p_c->info, (uint8_t *)p_a->info, str_len + 1);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef H_PEER_DATA_TRANSFER
|
||||
} case RPC_ID__Req_CustomRpc: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqCustomRpc, req_custom_rpc,
|
||||
rpc__req__custom_rpc__init);
|
||||
esp_hosted_rpc_data_t *custom_data = &app_req->u.custom_rpc;
|
||||
req_payload->custom_msg_id = custom_data->custom_msg_id;
|
||||
if (custom_data->data && custom_data->data_len > 0) {
|
||||
req_payload->data.data = custom_data->data;
|
||||
req_payload->data.len = custom_data->data_len;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if H_GPIO_EXPANDER_SUPPORT
|
||||
} case RPC_ID__Req_GpioConfig: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqGpioConfig, req_gpio_config,
|
||||
rpc__req__gpio_config__init);
|
||||
RPC_ALLOC_ELEMENT(RpcGpioConfig, req_payload->config, rpc__gpio_config__init);
|
||||
|
||||
req_payload->config->pin_bit_mask = app_req->u.gpio_config.pin_bit_mask;
|
||||
req_payload->config->intr_type = app_req->u.gpio_config.intr_type;
|
||||
req_payload->config->mode = app_req->u.gpio_config.mode;
|
||||
req_payload->config->pull_up_en = app_req->u.gpio_config.pull_up_en;
|
||||
req_payload->config->pull_down_en = app_req->u.gpio_config.pull_down_en;
|
||||
break;
|
||||
} case RPC_ID__Req_GpioResetPin: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqGpioResetPin, req_gpio_reset_pin,
|
||||
rpc__req__gpio_reset_pin__init);
|
||||
req_payload->gpio_num = app_req->u.gpio_num;
|
||||
break;
|
||||
} case RPC_ID__Req_GpioSetLevel: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqGpioSetLevel, req_gpio_set_level,
|
||||
rpc__req__gpio_set_level__init);
|
||||
|
||||
req_payload->gpio_num = app_req->u.gpio_set_level.gpio_num;
|
||||
req_payload->level = app_req->u.gpio_set_level.level;
|
||||
break;
|
||||
} case RPC_ID__Req_GpioGetLevel: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqGpioGetLevel, req_gpio_get_level,
|
||||
rpc__req__gpio_get_level__init);
|
||||
|
||||
req_payload->gpio_num = app_req->u.gpio_num;
|
||||
break;
|
||||
} case RPC_ID__Req_GpioSetDirection: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqGpioSetDirection, req_gpio_set_direction,
|
||||
rpc__req__gpio_set_direction__init);
|
||||
|
||||
req_payload->gpio_num = app_req->u.gpio_set_direction.gpio_num;
|
||||
req_payload->mode = app_req->u.gpio_set_direction.mode;
|
||||
break;
|
||||
} case RPC_ID__Req_GpioInputEnable: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqGpioInputEnable, req_gpio_input_enable,
|
||||
rpc__req__gpio_input_enable__init);
|
||||
|
||||
req_payload->gpio_num = app_req->u.gpio_num;
|
||||
break;
|
||||
} case RPC_ID__Req_GpioSetPullMode: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqGpioSetPullMode, req_gpio_set_pull_mode,
|
||||
rpc__req__gpio_set_pull_mode__init);
|
||||
|
||||
req_payload->gpio_num = app_req->u.gpio_set_pull_mode.gpio_num;
|
||||
req_payload->pull = app_req->u.gpio_set_pull_mode.pull_mode;
|
||||
break;
|
||||
#endif
|
||||
#if H_EXT_COEX_SUPPORT
|
||||
} case RPC_ID__Req_ExtCoex: {
|
||||
RPC_ALLOC_ASSIGN(RpcReqExtCoex, req_ext_coex,
|
||||
rpc__req__ext_coex__init);
|
||||
|
||||
req_payload->cmd = app_req->u.ext_coex.cmd;
|
||||
req_payload->set_gpio_wire_type = app_req->u.ext_coex.set_gpio_wire_type;
|
||||
req_payload->set_gpio_request_pin = app_req->u.ext_coex.set_gpio_request_pin;
|
||||
req_payload->set_gpio_priority_pin = app_req->u.ext_coex.set_gpio_priority_pin;
|
||||
req_payload->set_gpio_grant_pin = app_req->u.ext_coex.set_gpio_grant_pin;
|
||||
req_payload->set_gpio_tx_line_pin = app_req->u.ext_coex.set_gpio_tx_line_pin;
|
||||
req_payload->set_work_mode = app_req->u.ext_coex.set_work_mode;
|
||||
req_payload->set_grant_delay_us = app_req->u.ext_coex.set_grant_delay_us;
|
||||
req_payload->set_validate_high = app_req->u.ext_coex.set_validate_high;
|
||||
break;
|
||||
#endif
|
||||
} default: {
|
||||
*failure_status = RPC_ERR_UNSUPPORTED_MSG;
|
||||
ESP_LOGE(TAG, "Unsupported RPC Req[%u]",req->msg_id);
|
||||
return FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
} /* switch */
|
||||
return SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,918 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "rpc_core.h"
|
||||
#include "rpc_utils.h"
|
||||
#include "rpc_slave_if.h"
|
||||
#include "esp_hosted_transport.h"
|
||||
#include "esp_hosted_bitmasks.h"
|
||||
#include "esp_idf_version.h"
|
||||
#include "port_esp_hosted_host_config.h"
|
||||
#include "port_esp_hosted_host_wifi_config.h"
|
||||
#include "port_esp_hosted_host_log.h"
|
||||
#include "esp_hosted_os_abstraction.h"
|
||||
|
||||
DEFINE_LOG_TAG(rpc_rsp);
|
||||
|
||||
/* RPC response is result of remote function invocation at slave from host
|
||||
* The response will contain the return values of the RPC procedure
|
||||
* Return values typically will be simple integer return value of rpc call
|
||||
* for simple procedures. For function call with return value as a parameter,
|
||||
* RPC will contain full structure returned for that parameter and wrapper
|
||||
* level above will return these in expected pointer
|
||||
*
|
||||
* Responses will typically have two levels:
|
||||
* 1. protobuf level response received
|
||||
* 2. parse the response so that Ctrl_cmd_t app structure will be populated
|
||||
* or parsed from protobuf level response.
|
||||
*
|
||||
* For new RPC request, add up switch case for your message
|
||||
* For altogether new RPC function addition, please check
|
||||
* esp_hosted_fg/common/proto/esp_hosted_config.proto as a start point
|
||||
*/
|
||||
|
||||
#define RPC_ERR_IN_RESP(msGparaM) \
|
||||
if (rpc_msg->msGparaM->resp) { \
|
||||
app_resp->resp_event_status = rpc_msg->msGparaM->resp; \
|
||||
ESP_LOGW(TAG, "Hosted RPC_Resp [0x%"PRIx16"], uid [%"PRIu32"], resp code [%"PRIi32"]", \
|
||||
app_resp->msg_id, app_resp->uid, app_resp->resp_event_status); \
|
||||
goto fail_parse_rpc_msg; \
|
||||
}
|
||||
|
||||
#define RPC_RSP_COPY_BYTES(dst,src) { \
|
||||
if (src.data && src.len) { \
|
||||
g_h.funcs->_h_memcpy(dst, src.data, src.len); \
|
||||
} \
|
||||
}
|
||||
|
||||
// copy the rpc record info to the wifi record info
|
||||
static int rpc_copy_ap_record(wifi_ap_record_t *ap_record, WifiApRecord *rpc_ap_record)
|
||||
{
|
||||
RPC_RSP_COPY_BYTES(ap_record->ssid, rpc_ap_record->ssid);
|
||||
RPC_RSP_COPY_BYTES(ap_record->bssid, rpc_ap_record->bssid);
|
||||
|
||||
ap_record->primary = rpc_ap_record->primary;
|
||||
ap_record->second = rpc_ap_record->second;
|
||||
ap_record->rssi = rpc_ap_record->rssi;
|
||||
ap_record->authmode = rpc_ap_record->authmode;
|
||||
ap_record->pairwise_cipher = rpc_ap_record->pairwise_cipher;
|
||||
ap_record->group_cipher = rpc_ap_record->group_cipher;
|
||||
ap_record->ant = rpc_ap_record->ant;
|
||||
|
||||
ap_record->phy_11b = H_GET_BIT(WIFI_SCAN_AP_REC_phy_11b_BIT, rpc_ap_record->bitmask);
|
||||
ap_record->phy_11g = H_GET_BIT(WIFI_SCAN_AP_REC_phy_11g_BIT, rpc_ap_record->bitmask);
|
||||
ap_record->phy_11n = H_GET_BIT(WIFI_SCAN_AP_REC_phy_11n_BIT, rpc_ap_record->bitmask);
|
||||
ap_record->phy_lr = H_GET_BIT(WIFI_SCAN_AP_REC_phy_lr_BIT, rpc_ap_record->bitmask);
|
||||
ap_record->phy_11a = H_GET_BIT(WIFI_SCAN_AP_REC_phy_11a_BIT, rpc_ap_record->bitmask);
|
||||
ap_record->phy_11ac = H_GET_BIT(WIFI_SCAN_AP_REC_phy_11ac_BIT, rpc_ap_record->bitmask);
|
||||
ap_record->phy_11ax = H_GET_BIT(WIFI_SCAN_AP_REC_phy_11ax_BIT, rpc_ap_record->bitmask);
|
||||
ap_record->wps = H_GET_BIT(WIFI_SCAN_AP_REC_wps_BIT, rpc_ap_record->bitmask);
|
||||
ap_record->ftm_responder = H_GET_BIT(WIFI_SCAN_AP_REC_ftm_responder_BIT, rpc_ap_record->bitmask);
|
||||
ap_record->ftm_initiator = H_GET_BIT(WIFI_SCAN_AP_REC_ftm_initiator_BIT, rpc_ap_record->bitmask);
|
||||
ap_record->reserved = WIFI_SCAN_AP_GET_RESERVED_VAL(rpc_ap_record->bitmask);
|
||||
|
||||
RPC_RSP_COPY_BYTES(ap_record->country.cc, rpc_ap_record->country->cc);
|
||||
ap_record->country.schan = rpc_ap_record->country->schan;
|
||||
ap_record->country.nchan = rpc_ap_record->country->nchan;
|
||||
ap_record->country.max_tx_power = rpc_ap_record->country->max_tx_power;
|
||||
ap_record->country.policy = rpc_ap_record->country->policy;
|
||||
|
||||
ESP_LOGD(TAG, "SSID: %s BSSid: " MACSTR, ap_record->ssid, MAC2STR(ap_record->bssid));
|
||||
ESP_LOGD(TAG, "Primary: %u Second: %u RSSI: %d Authmode: %u",
|
||||
ap_record->primary, ap_record->second,
|
||||
ap_record->rssi, ap_record->authmode
|
||||
);
|
||||
ESP_LOGD(TAG, "PairwiseCipher: %u Groupcipher: %u Ant: %u",
|
||||
ap_record->pairwise_cipher, ap_record->group_cipher,
|
||||
ap_record->ant
|
||||
);
|
||||
ESP_LOGD(TAG, "Bitmask: 11b:%u g:%u n:%u ax: %u lr:%u wps:%u ftm_resp:%u ftm_ini:%u res: %u",
|
||||
ap_record->phy_11b, ap_record->phy_11g,
|
||||
ap_record->phy_11n, ap_record->phy_11ax, ap_record->phy_lr,
|
||||
ap_record->wps, ap_record->ftm_responder,
|
||||
ap_record->ftm_initiator, ap_record->reserved
|
||||
);
|
||||
ESP_LOGD(TAG, "Country cc:%c%c schan: %u nchan: %u max_tx_pow: %d policy: %u",
|
||||
ap_record->country.cc[0], ap_record->country.cc[1], ap_record->country.schan,
|
||||
ap_record->country.nchan, ap_record->country.max_tx_power,
|
||||
ap_record->country.policy);
|
||||
|
||||
WifiHeApInfo *p_c_he_ap = rpc_ap_record->he_ap;
|
||||
wifi_he_ap_info_t *p_a_he_ap = &ap_record->he_ap;
|
||||
// six bits
|
||||
p_a_he_ap->bss_color = p_c_he_ap->bitmask & 0x3F;
|
||||
p_a_he_ap->partial_bss_color = H_GET_BIT(WIFI_HE_AP_INFO_partial_bss_color_BIT, p_c_he_ap->bitmask);
|
||||
p_a_he_ap->bss_color_disabled = H_GET_BIT(WIFI_HE_AP_INFO_bss_color_disabled_BIT, p_c_he_ap->bitmask);
|
||||
|
||||
ESP_LOGD(TAG, "HE_AP: bss_color %d, partial_bss_color %d, bss_color_disabled %d",
|
||||
p_a_he_ap->bss_color, p_a_he_ap->bss_color_disabled, p_a_he_ap->bss_color_disabled);
|
||||
|
||||
ap_record->bandwidth = rpc_ap_record->bandwidth;
|
||||
ap_record->vht_ch_freq1 = rpc_ap_record->vht_ch_freq1;
|
||||
ap_record->vht_ch_freq2 = rpc_ap_record->vht_ch_freq2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This will copy rpc response from `Rpc` into
|
||||
* application structure `ctrl_cmd_t`
|
||||
* This function is called after protobuf decoding is successful
|
||||
**/
|
||||
int rpc_parse_rsp(Rpc *rpc_msg, ctrl_cmd_t *app_resp)
|
||||
{
|
||||
uint16_t i = 0;
|
||||
|
||||
/* 1. Check non NULL */
|
||||
if (!rpc_msg || !app_resp) {
|
||||
ESP_LOGE(TAG, "NULL rpc resp or NULL App Resp");
|
||||
goto fail_parse_rpc_msg;
|
||||
}
|
||||
|
||||
/* 2. update basic fields */
|
||||
app_resp->msg_type = RPC_TYPE__Resp;
|
||||
app_resp->msg_id = rpc_msg->msg_id;
|
||||
app_resp->uid = rpc_msg->uid;
|
||||
ESP_LOGI(TAG, " --> RPC_Resp [0x%x], uid %ld", app_resp->msg_id, app_resp->uid);
|
||||
|
||||
/* 3. parse Rpc into ctrl_cmd_t */
|
||||
switch (rpc_msg->msg_id) {
|
||||
case RPC_ID__Resp_Base : {
|
||||
// RPC Request not supported
|
||||
app_resp->resp_event_status = ESP_ERR_NOT_SUPPORTED;
|
||||
goto fail_parse_rpc_msg;
|
||||
}
|
||||
case RPC_ID__Resp_GetMACAddress : {
|
||||
RPC_FAIL_ON_NULL(resp_get_mac_address);
|
||||
RPC_ERR_IN_RESP(resp_get_mac_address);
|
||||
RPC_FAIL_ON_NULL(resp_get_mac_address->mac.data);
|
||||
|
||||
RPC_RSP_COPY_BYTES(app_resp->u.wifi_mac.mac, rpc_msg->resp_get_mac_address->mac);
|
||||
ESP_LOGD(TAG, "Mac addr: "MACSTR, MAC2STR(app_resp->u.wifi_mac.mac));
|
||||
break;
|
||||
} case RPC_ID__Resp_SetMacAddress : {
|
||||
RPC_FAIL_ON_NULL(resp_set_mac_address);
|
||||
RPC_ERR_IN_RESP(resp_set_mac_address);
|
||||
break;
|
||||
} case RPC_ID__Resp_GetWifiMode : {
|
||||
RPC_FAIL_ON_NULL(resp_get_wifi_mode);
|
||||
RPC_ERR_IN_RESP(resp_get_wifi_mode);
|
||||
|
||||
app_resp->u.wifi_mode.mode = rpc_msg->resp_get_wifi_mode->mode;
|
||||
break;
|
||||
} case RPC_ID__Resp_SetWifiMode : {
|
||||
RPC_FAIL_ON_NULL(resp_set_wifi_mode);
|
||||
RPC_ERR_IN_RESP(resp_set_wifi_mode);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiSetPs: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_set_ps);
|
||||
RPC_ERR_IN_RESP(resp_wifi_set_ps);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiGetPs : {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_get_ps);
|
||||
RPC_ERR_IN_RESP(resp_wifi_get_ps);
|
||||
app_resp->u.wifi_ps.ps_mode = rpc_msg->resp_wifi_get_ps->type;
|
||||
break;
|
||||
} case RPC_ID__Resp_OTABegin : {
|
||||
RPC_FAIL_ON_NULL(resp_ota_begin);
|
||||
RPC_ERR_IN_RESP(resp_ota_begin);
|
||||
break;
|
||||
} case RPC_ID__Resp_OTAWrite : {
|
||||
RPC_FAIL_ON_NULL(resp_ota_write);
|
||||
RPC_ERR_IN_RESP(resp_ota_write);
|
||||
break;
|
||||
} case RPC_ID__Resp_OTAEnd: {
|
||||
RPC_FAIL_ON_NULL(resp_ota_end);
|
||||
RPC_ERR_IN_RESP(resp_ota_end);
|
||||
break;
|
||||
} case RPC_ID__Resp_OTAActivate: {
|
||||
RPC_FAIL_ON_NULL(resp_ota_activate);
|
||||
RPC_ERR_IN_RESP(resp_ota_activate);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiSetMaxTxPower: {
|
||||
RPC_FAIL_ON_NULL(resp_set_wifi_max_tx_power);
|
||||
RPC_ERR_IN_RESP(resp_set_wifi_max_tx_power);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiGetMaxTxPower: {
|
||||
RPC_FAIL_ON_NULL(resp_get_wifi_max_tx_power);
|
||||
RPC_ERR_IN_RESP(resp_get_wifi_max_tx_power);
|
||||
app_resp->u.wifi_tx_power.power =
|
||||
rpc_msg->resp_get_wifi_max_tx_power->power;
|
||||
break;
|
||||
} case RPC_ID__Resp_ConfigHeartbeat: {
|
||||
RPC_FAIL_ON_NULL(resp_config_heartbeat);
|
||||
RPC_ERR_IN_RESP(resp_config_heartbeat);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiInit: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_init);
|
||||
RPC_ERR_IN_RESP(resp_wifi_init);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiDeinit: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_deinit);
|
||||
RPC_ERR_IN_RESP(resp_wifi_deinit);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiStart: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_start);
|
||||
RPC_ERR_IN_RESP(resp_wifi_start);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiStop: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_stop);
|
||||
RPC_ERR_IN_RESP(resp_wifi_stop);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiConnect: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_connect);
|
||||
RPC_ERR_IN_RESP(resp_wifi_connect);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiDisconnect: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_disconnect);
|
||||
RPC_ERR_IN_RESP(resp_wifi_disconnect);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiSetConfig: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_set_config);
|
||||
RPC_ERR_IN_RESP(resp_wifi_set_config);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiScanParams: {
|
||||
rpc_wifi_scan_params_t *p_a = &app_resp->u.wifi_scan_params;
|
||||
WifiScanDefaultParams *p_c = rpc_msg->resp_wifi_scan_params->config;
|
||||
|
||||
RPC_FAIL_ON_NULL(resp_wifi_scan_params);
|
||||
RPC_ERR_IN_RESP(resp_wifi_scan_params);
|
||||
|
||||
if (p_c) {
|
||||
p_a->config.scan_time.passive = p_c->scan_time->passive;
|
||||
p_a->config.scan_time.active.min = p_c->scan_time->active->min;
|
||||
p_a->config.scan_time.active.max = p_c->scan_time->active->max;
|
||||
p_a->config.home_chan_dwell_time = p_c->home_chan_dwell_time;
|
||||
}
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiGetConfig: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_set_config);
|
||||
RPC_ERR_IN_RESP(resp_wifi_set_config);
|
||||
|
||||
app_resp->u.wifi_config.iface = rpc_msg->resp_wifi_get_config->iface;
|
||||
|
||||
switch (app_resp->u.wifi_config.iface) {
|
||||
|
||||
case WIFI_IF_STA: {
|
||||
wifi_sta_config_t * p_a_sta = &(app_resp->u.wifi_config.u.sta);
|
||||
WifiStaConfig * p_c_sta = rpc_msg->resp_wifi_get_config->cfg->sta;
|
||||
rpc_copy_wifi_sta_config(p_a_sta, p_c_sta);
|
||||
break;
|
||||
}
|
||||
case WIFI_IF_AP: {
|
||||
wifi_ap_config_t * p_a_ap = &(app_resp->u.wifi_config.u.ap);
|
||||
WifiApConfig * p_c_ap = rpc_msg->resp_wifi_get_config->cfg->ap;
|
||||
|
||||
RPC_RSP_COPY_BYTES(p_a_ap->ssid, p_c_ap->ssid);
|
||||
RPC_RSP_COPY_BYTES(p_a_ap->password, p_c_ap->password);
|
||||
p_a_ap->ssid_len = p_c_ap->ssid_len;
|
||||
p_a_ap->channel = p_c_ap->channel;
|
||||
p_a_ap->authmode = p_c_ap->authmode;
|
||||
p_a_ap->ssid_hidden = p_c_ap->ssid_hidden;
|
||||
p_a_ap->max_connection = p_c_ap->max_connection;
|
||||
p_a_ap->beacon_interval = p_c_ap->beacon_interval;
|
||||
p_a_ap->csa_count = p_c_ap->csa_count;
|
||||
p_a_ap->dtim_period = p_c_ap->dtim_period;
|
||||
p_a_ap->pairwise_cipher = p_c_ap->pairwise_cipher;
|
||||
p_a_ap->ftm_responder = p_c_ap->ftm_responder;
|
||||
if (p_c_ap->pmf_cfg) {
|
||||
p_a_ap->pmf_cfg.capable = p_c_ap->pmf_cfg->capable;
|
||||
p_a_ap->pmf_cfg.required = p_c_ap->pmf_cfg->required;
|
||||
}
|
||||
p_a_ap->sae_pwe_h2e = p_c_ap->sae_pwe_h2e;
|
||||
#if H_GOT_AP_CONFIG_PARAM_TRANSITION_DISABLE
|
||||
p_a_ap->transition_disable = p_c_ap->transition_disable;
|
||||
#endif
|
||||
#if H_PRESENT_IN_ESP_IDF_5_5_0
|
||||
p_a_ap->sae_ext = p_c_ap->sae_ext;
|
||||
if (p_c_ap->bss_max_idle_cfg) {
|
||||
p_a_ap->bss_max_idle_cfg.period = p_c_ap->bss_max_idle_cfg->period;
|
||||
p_a_ap->bss_max_idle_cfg.protected_keep_alive = p_c_ap->bss_max_idle_cfg->protected_keep_alive;
|
||||
}
|
||||
p_a_ap->gtk_rekey_interval = p_c_ap->gtk_rekey_interval;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ESP_LOGE(TAG, "Unsupported WiFi interface[%u]", app_resp->u.wifi_config.iface);
|
||||
} //switch
|
||||
|
||||
break;
|
||||
|
||||
} case RPC_ID__Resp_WifiScanStart: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_scan_start);
|
||||
RPC_ERR_IN_RESP(resp_wifi_scan_start);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiScanStop: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_scan_stop);
|
||||
RPC_ERR_IN_RESP(resp_wifi_scan_stop);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiScanGetApNum: {
|
||||
wifi_scan_ap_list_t *p_a = &(app_resp->u.wifi_scan_ap_list);
|
||||
RPC_FAIL_ON_NULL(resp_wifi_scan_get_ap_num);
|
||||
RPC_ERR_IN_RESP(resp_wifi_scan_get_ap_num);
|
||||
|
||||
p_a->number = rpc_msg->resp_wifi_scan_get_ap_num->number;
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiScanGetApRecord: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_scan_get_ap_records);
|
||||
RPC_ERR_IN_RESP(resp_wifi_scan_get_ap_records);
|
||||
|
||||
rpc_copy_ap_record(&(app_resp->u.wifi_ap_record),
|
||||
rpc_msg->resp_wifi_scan_get_ap_record->ap_record);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiScanGetApRecords: {
|
||||
wifi_scan_ap_list_t *p_a = &(app_resp->u.wifi_scan_ap_list);
|
||||
wifi_ap_record_t *list = NULL;
|
||||
WifiApRecord **p_c_list = NULL;
|
||||
|
||||
RPC_FAIL_ON_NULL(resp_wifi_scan_get_ap_records);
|
||||
RPC_ERR_IN_RESP(resp_wifi_scan_get_ap_records);
|
||||
p_c_list = rpc_msg->resp_wifi_scan_get_ap_records->ap_records;
|
||||
|
||||
p_a->number = rpc_msg->resp_wifi_scan_get_ap_records->number;
|
||||
|
||||
if (!p_a->number) {
|
||||
ESP_LOGI(TAG, "No AP found");
|
||||
goto fail_parse_rpc_msg;
|
||||
}
|
||||
ESP_LOGD(TAG, "Num AP records: %u",
|
||||
app_resp->u.wifi_scan_ap_list.number);
|
||||
|
||||
RPC_FAIL_ON_NULL(resp_wifi_scan_get_ap_records->ap_records);
|
||||
|
||||
list = (wifi_ap_record_t*)g_h.funcs->_h_calloc(p_a->number,
|
||||
sizeof(wifi_ap_record_t));
|
||||
p_a->out_list = list;
|
||||
|
||||
RPC_FAIL_ON_NULL_PRINT(list, "Malloc Failed");
|
||||
|
||||
app_resp->app_free_buff_func = g_h.funcs->_h_free;
|
||||
app_resp->app_free_buff_hdl = list;
|
||||
|
||||
ESP_LOGD(TAG, "Number of available APs is %d", p_a->number);
|
||||
for (i=0; i<p_a->number; i++) {
|
||||
rpc_copy_ap_record(&list[i], p_c_list[i]);
|
||||
}
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiStaGetApInfo: {
|
||||
WifiApRecord *p_c = NULL;
|
||||
wifi_ap_record_t *ap_info = NULL;
|
||||
wifi_scan_ap_list_t *p_a = &(app_resp->u.wifi_scan_ap_list);
|
||||
|
||||
RPC_FAIL_ON_NULL(resp_wifi_sta_get_ap_info);
|
||||
RPC_ERR_IN_RESP(resp_wifi_sta_get_ap_info);
|
||||
p_c = rpc_msg->resp_wifi_sta_get_ap_info->ap_record;
|
||||
|
||||
p_a->number = 1;
|
||||
|
||||
RPC_FAIL_ON_NULL(resp_wifi_sta_get_ap_info->ap_record);
|
||||
|
||||
ap_info = (wifi_ap_record_t*)g_h.funcs->_h_calloc(p_a->number,
|
||||
sizeof(wifi_ap_record_t));
|
||||
p_a->out_list = ap_info;
|
||||
|
||||
RPC_FAIL_ON_NULL_PRINT(ap_info, "Malloc Failed");
|
||||
|
||||
app_resp->app_free_buff_func = g_h.funcs->_h_free;
|
||||
app_resp->app_free_buff_hdl = ap_info;
|
||||
|
||||
rpc_copy_ap_record(ap_info, p_c);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiClearApList: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_clear_ap_list);
|
||||
RPC_ERR_IN_RESP(resp_wifi_clear_ap_list);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiRestore: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_restore);
|
||||
RPC_ERR_IN_RESP(resp_wifi_restore);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiClearFastConnect: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_clear_fast_connect);
|
||||
RPC_ERR_IN_RESP(resp_wifi_clear_fast_connect);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiDeauthSta: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_deauth_sta);
|
||||
RPC_ERR_IN_RESP(resp_wifi_deauth_sta);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiSetStorage: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_set_storage);
|
||||
RPC_ERR_IN_RESP(resp_wifi_set_storage);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiSetBandwidth: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_set_bandwidth);
|
||||
RPC_ERR_IN_RESP(resp_wifi_set_bandwidth);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiGetBandwidth: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_get_bandwidth);
|
||||
RPC_ERR_IN_RESP(resp_wifi_get_bandwidth);
|
||||
app_resp->u.wifi_bandwidth.bw =
|
||||
rpc_msg->resp_wifi_get_bandwidth->bw;
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiSetChannel: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_set_channel);
|
||||
RPC_ERR_IN_RESP(resp_wifi_set_channel);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiGetChannel: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_get_channel);
|
||||
RPC_ERR_IN_RESP(resp_wifi_get_channel);
|
||||
app_resp->u.wifi_channel.primary =
|
||||
rpc_msg->resp_wifi_get_channel->primary;
|
||||
app_resp->u.wifi_channel.second =
|
||||
rpc_msg->resp_wifi_get_channel->second;
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiSetCountryCode: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_set_country_code);
|
||||
RPC_ERR_IN_RESP(resp_wifi_set_country_code);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiGetCountryCode: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_get_country_code);
|
||||
RPC_ERR_IN_RESP(resp_wifi_get_country_code);
|
||||
|
||||
RPC_RSP_COPY_BYTES(&app_resp->u.wifi_country_code.cc[0],
|
||||
rpc_msg->resp_wifi_get_country_code->country);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiSetCountry: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_set_country);
|
||||
RPC_ERR_IN_RESP(resp_wifi_set_country);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiGetCountry: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_get_country);
|
||||
RPC_ERR_IN_RESP(resp_wifi_get_country);
|
||||
|
||||
RPC_RSP_COPY_BYTES(&app_resp->u.wifi_country.cc[0],
|
||||
rpc_msg->resp_wifi_get_country->country->cc);
|
||||
app_resp->u.wifi_country.schan = rpc_msg->resp_wifi_get_country->country->schan;
|
||||
app_resp->u.wifi_country.nchan = rpc_msg->resp_wifi_get_country->country->nchan;
|
||||
app_resp->u.wifi_country.max_tx_power = rpc_msg->resp_wifi_get_country->country->max_tx_power;
|
||||
app_resp->u.wifi_country.policy = rpc_msg->resp_wifi_get_country->country->policy;
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiApGetStaList: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_ap_get_sta_list);
|
||||
RPC_ERR_IN_RESP(resp_wifi_ap_get_sta_list);
|
||||
|
||||
// handle case where slave's num is bigger than our ESP_WIFI_MAX_CONN_NUM
|
||||
uint32_t num_stations = rpc_msg->resp_wifi_ap_get_sta_list->sta_list->num;
|
||||
if (num_stations > ESP_WIFI_MAX_CONN_NUM) {
|
||||
ESP_LOGW(TAG, "Slave returned %ld connected stations, but we can only accept %d items", num_stations, ESP_WIFI_MAX_CONN_NUM);
|
||||
num_stations = ESP_WIFI_MAX_CONN_NUM;
|
||||
}
|
||||
|
||||
WifiStaInfo ** p_c_sta_list = rpc_msg->resp_wifi_ap_get_sta_list->sta_list->sta;
|
||||
|
||||
for (int i = 0; i < num_stations; i++) {
|
||||
wifi_sta_info_t * p_a_sta = &app_resp->u.wifi_ap_sta_list.sta[i];
|
||||
|
||||
RPC_RSP_COPY_BYTES(p_a_sta->mac, p_c_sta_list[i]->mac);
|
||||
p_a_sta->rssi = p_c_sta_list[i]->rssi;
|
||||
|
||||
p_a_sta->phy_11b = H_GET_BIT(WIFI_STA_INFO_phy_11b_BIT, p_c_sta_list[i]->bitmask);
|
||||
p_a_sta->phy_11g = H_GET_BIT(WIFI_STA_INFO_phy_11g_BIT, p_c_sta_list[i]->bitmask);
|
||||
p_a_sta->phy_11n = H_GET_BIT(WIFI_STA_INFO_phy_11n_BIT, p_c_sta_list[i]->bitmask);
|
||||
p_a_sta->phy_lr = H_GET_BIT(WIFI_STA_INFO_phy_lr_BIT, p_c_sta_list[i]->bitmask);
|
||||
p_a_sta->phy_11ax = H_GET_BIT(WIFI_STA_INFO_phy_11ax_BIT, p_c_sta_list[i]->bitmask);
|
||||
p_a_sta->is_mesh_child = H_GET_BIT(WIFI_STA_INFO_is_mesh_child_BIT, p_c_sta_list[i]->bitmask);
|
||||
p_a_sta->reserved = WIFI_STA_INFO_GET_RESERVED_VAL(p_c_sta_list[i]->bitmask);
|
||||
}
|
||||
|
||||
app_resp->u.wifi_ap_sta_list.num = rpc_msg->resp_wifi_ap_get_sta_list->sta_list->num;
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiApGetStaAid: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_ap_get_sta_aid);
|
||||
RPC_ERR_IN_RESP(resp_wifi_ap_get_sta_aid);
|
||||
|
||||
app_resp->u.wifi_ap_get_sta_aid.aid = rpc_msg->resp_wifi_ap_get_sta_aid->aid;
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiStaGetRssi: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_sta_get_rssi);
|
||||
RPC_ERR_IN_RESP(resp_wifi_sta_get_rssi);
|
||||
|
||||
app_resp->u.wifi_sta_get_rssi.rssi = rpc_msg->resp_wifi_sta_get_rssi->rssi;
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiSetProtocol: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_set_protocol);
|
||||
RPC_ERR_IN_RESP(resp_wifi_set_protocol);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiGetProtocol: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_get_protocol);
|
||||
RPC_ERR_IN_RESP(resp_wifi_get_protocol);
|
||||
app_resp->u.wifi_protocol.protocol_bitmap =
|
||||
rpc_msg->resp_wifi_get_protocol->protocol_bitmap;
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiStaGetNegotiatedPhymode: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_sta_get_negotiated_phymode);
|
||||
RPC_ERR_IN_RESP(resp_wifi_sta_get_negotiated_phymode);
|
||||
app_resp->u.wifi_sta_get_negotiated_phymode.phymode =
|
||||
rpc_msg->resp_wifi_sta_get_negotiated_phymode->phymode;
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiStaGetAid: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_sta_get_aid);
|
||||
RPC_ERR_IN_RESP(resp_wifi_sta_get_aid);
|
||||
app_resp->u.wifi_sta_get_aid.aid =
|
||||
rpc_msg->resp_wifi_sta_get_aid->aid;
|
||||
break;
|
||||
} case RPC_ID__Resp_GetCoprocessorFwVersion: {
|
||||
RPC_FAIL_ON_NULL(resp_get_coprocessor_fwversion);
|
||||
RPC_ERR_IN_RESP(resp_get_coprocessor_fwversion);
|
||||
app_resp->u.coprocessor_fwversion.major1 =
|
||||
rpc_msg->resp_get_coprocessor_fwversion->major1;
|
||||
app_resp->u.coprocessor_fwversion.minor1 =
|
||||
rpc_msg->resp_get_coprocessor_fwversion->minor1;
|
||||
app_resp->u.coprocessor_fwversion.patch1 =
|
||||
rpc_msg->resp_get_coprocessor_fwversion->patch1;
|
||||
|
||||
// ensure revision, prerelease and build are -1 if not found (0)
|
||||
app_resp->u.coprocessor_fwversion.revision =
|
||||
(rpc_msg->resp_get_coprocessor_fwversion->revision) ?
|
||||
rpc_msg->resp_get_coprocessor_fwversion->revision : -1;
|
||||
app_resp->u.coprocessor_fwversion.prerelease =
|
||||
(rpc_msg->resp_get_coprocessor_fwversion->prerelease) ?
|
||||
rpc_msg->resp_get_coprocessor_fwversion->prerelease : -1;
|
||||
app_resp->u.coprocessor_fwversion.build =
|
||||
(rpc_msg->resp_get_coprocessor_fwversion->build) ?
|
||||
rpc_msg->resp_get_coprocessor_fwversion->build : -1;
|
||||
|
||||
app_resp->u.coprocessor_fwversion.chip_id =
|
||||
rpc_msg->resp_get_coprocessor_fwversion->chip_id;
|
||||
int copy_size = H_MIN(rpc_msg->resp_get_coprocessor_fwversion->idf_target.len,
|
||||
(sizeof(app_resp->u.coprocessor_fwversion.idf_target) - 1));
|
||||
if (copy_size) {
|
||||
g_h.funcs->_h_memcpy(app_resp->u.coprocessor_fwversion.idf_target,
|
||||
rpc_msg->resp_get_coprocessor_fwversion->idf_target.data,
|
||||
copy_size);
|
||||
}
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiSetInactiveTime: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_set_inactive_time);
|
||||
RPC_ERR_IN_RESP(resp_wifi_set_inactive_time);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiGetInactiveTime: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_get_inactive_time);
|
||||
RPC_ERR_IN_RESP(resp_wifi_get_inactive_time);
|
||||
app_resp->u.wifi_inactive_time.sec =
|
||||
rpc_msg->resp_wifi_get_inactive_time->sec;
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiDisablePmfConfig: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_disable_pmf_config);
|
||||
RPC_ERR_IN_RESP(resp_wifi_disable_pmf_config);
|
||||
app_resp->u.wifi_disable_pmf_config.ifx =
|
||||
rpc_msg->resp_wifi_disable_pmf_config->ifx;
|
||||
break;
|
||||
#if H_WIFI_HE_SUPPORT
|
||||
} case RPC_ID__Resp_WifiStaTwtConfig: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_sta_twt_config);
|
||||
RPC_ERR_IN_RESP(resp_wifi_sta_twt_config);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiStaItwtSetup: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_sta_itwt_setup);
|
||||
RPC_ERR_IN_RESP(resp_wifi_sta_itwt_setup);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiStaItwtTeardown: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_sta_itwt_teardown);
|
||||
RPC_ERR_IN_RESP(resp_wifi_sta_itwt_teardown);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiStaItwtSuspend: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_sta_itwt_suspend);
|
||||
RPC_ERR_IN_RESP(resp_wifi_sta_itwt_suspend);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiStaItwtGetFlowIdStatus: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_sta_itwt_get_flow_id_status);
|
||||
RPC_ERR_IN_RESP(resp_wifi_sta_itwt_get_flow_id_status);
|
||||
app_resp->u.wifi_itwt_flow_id_bitmap =
|
||||
rpc_msg->resp_wifi_sta_itwt_get_flow_id_status->flow_id_bitmap;
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiStaItwtSendProbeReq: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_sta_itwt_suspend);
|
||||
RPC_ERR_IN_RESP(resp_wifi_sta_itwt_suspend);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiStaItwtSetTargetWakeTimeOffset: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_sta_itwt_set_target_wake_time_offset);
|
||||
RPC_ERR_IN_RESP(resp_wifi_sta_itwt_set_target_wake_time_offset);
|
||||
break;
|
||||
#endif // H_WIFI_HE_SUPPORT
|
||||
#if H_WIFI_DUALBAND_SUPPORT
|
||||
} case RPC_ID__Resp_WifiSetProtocols: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_set_protocols);
|
||||
RPC_ERR_IN_RESP(resp_wifi_set_protocols);
|
||||
app_resp->u.wifi_protocols.ifx =
|
||||
rpc_msg->resp_wifi_set_protocols->ifx;
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiGetProtocols: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_get_protocols);
|
||||
RPC_ERR_IN_RESP(resp_wifi_get_protocols);
|
||||
app_resp->u.wifi_protocols.ifx =
|
||||
rpc_msg->resp_wifi_get_protocols->ifx;
|
||||
app_resp->u.wifi_protocols.ghz_2g =
|
||||
rpc_msg->resp_wifi_get_protocols->protocols->ghz_2g;
|
||||
app_resp->u.wifi_protocols.ghz_5g =
|
||||
rpc_msg->resp_wifi_get_protocols->protocols->ghz_5g;
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiSetBandwidths: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_set_bandwidths);
|
||||
RPC_ERR_IN_RESP(resp_wifi_set_bandwidths);
|
||||
app_resp->u.wifi_bandwidths.ifx =
|
||||
rpc_msg->resp_wifi_set_bandwidths->ifx;
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiGetBandwidths: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_get_bandwidths);
|
||||
RPC_ERR_IN_RESP(resp_wifi_get_bandwidths);
|
||||
app_resp->u.wifi_bandwidths.ifx =
|
||||
rpc_msg->resp_wifi_get_bandwidths->ifx;
|
||||
app_resp->u.wifi_bandwidths.ghz_2g =
|
||||
rpc_msg->resp_wifi_get_bandwidths->bandwidths->ghz_2g;
|
||||
app_resp->u.wifi_bandwidths.ghz_5g =
|
||||
rpc_msg->resp_wifi_get_bandwidths->bandwidths->ghz_5g;
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiSetBand: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_set_country_code);
|
||||
RPC_ERR_IN_RESP(resp_wifi_set_country_code);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiGetBand: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_get_band);
|
||||
RPC_ERR_IN_RESP(resp_wifi_get_band);
|
||||
app_resp->u.wifi_band =
|
||||
rpc_msg->resp_wifi_get_band->band;
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiSetBandMode: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_set_country_code);
|
||||
RPC_ERR_IN_RESP(resp_wifi_set_country_code);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiGetBandMode: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_get_bandmode);
|
||||
RPC_ERR_IN_RESP(resp_wifi_get_bandmode);
|
||||
app_resp->u.wifi_band_mode =
|
||||
rpc_msg->resp_wifi_get_bandmode->bandmode;
|
||||
break;
|
||||
#endif // H_WIFI_DUALBAND_SUPPORT
|
||||
} case RPC_ID__Resp_IfaceMacAddrSetGet: {
|
||||
RPC_FAIL_ON_NULL(resp_iface_mac_addr_set_get);
|
||||
RPC_ERR_IN_RESP(resp_iface_mac_addr_set_get);
|
||||
RPC_RSP_COPY_BYTES(app_resp->u.iface_mac.mac, rpc_msg->resp_iface_mac_addr_set_get->mac);
|
||||
break;
|
||||
} case RPC_ID__Resp_IfaceMacAddrLenGet: {
|
||||
RPC_FAIL_ON_NULL(resp_iface_mac_addr_len_get);
|
||||
RPC_ERR_IN_RESP(resp_iface_mac_addr_len_get);
|
||||
app_resp->u.iface_mac_len.type =
|
||||
rpc_msg->resp_iface_mac_addr_len_get->type;
|
||||
app_resp->u.iface_mac_len.len =
|
||||
rpc_msg->resp_iface_mac_addr_len_get->len;
|
||||
break;
|
||||
} case RPC_ID__Resp_FeatureControl: {
|
||||
RPC_FAIL_ON_NULL(resp_feature_control);
|
||||
RPC_ERR_IN_RESP(resp_feature_control);
|
||||
break;
|
||||
#ifdef H_PEER_DATA_TRANSFER
|
||||
} case RPC_ID__Resp_CustomRpc: {
|
||||
RPC_FAIL_ON_NULL(resp_custom_rpc);
|
||||
RPC_ERR_IN_RESP(resp_custom_rpc);
|
||||
ESP_LOGD(TAG, "Custom RPC response received: %zu bytes", rpc_msg->resp_custom_rpc->data.len);
|
||||
app_resp->u.custom_rpc.custom_msg_id = rpc_msg->resp_custom_rpc->custom_msg_id;
|
||||
if (rpc_msg->resp_custom_rpc->data.data && rpc_msg->resp_custom_rpc->data.len > 0) {
|
||||
/* Allocate memory for response data */
|
||||
app_resp->u.custom_rpc.data = (uint8_t *)g_h.funcs->_h_malloc(rpc_msg->resp_custom_rpc->data.len);
|
||||
|
||||
RPC_FAIL_ON_NULL_PRINT(app_resp->u.custom_rpc.data, "Malloc Failed");
|
||||
|
||||
if (app_resp->u.custom_rpc.data) {
|
||||
g_h.funcs->_h_memcpy(app_resp->u.custom_rpc.data, rpc_msg->resp_custom_rpc->data.data, rpc_msg->resp_custom_rpc->data.len);
|
||||
app_resp->u.custom_rpc.data_len = rpc_msg->resp_custom_rpc->data.len;
|
||||
app_resp->u.custom_rpc.free_func = g_h.funcs->_h_free; /* Default free function */
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
} case RPC_ID__Resp_AppGetDesc: {
|
||||
RPC_FAIL_ON_NULL(resp_app_get_desc);
|
||||
RPC_ERR_IN_RESP(resp_app_get_desc);
|
||||
RPC_FAIL_ON_NULL(resp_app_get_desc->app_desc);
|
||||
// copy over the app descriptor elements
|
||||
esp_hosted_app_desc_t *p_a = &app_resp->u.app_desc;
|
||||
EspAppDesc *p_c = rpc_msg->resp_app_get_desc->app_desc;
|
||||
p_a->magic_word = p_c->magic_word;
|
||||
p_a->secure_version = p_c->secure_version;
|
||||
RPC_RSP_COPY_BYTES(p_a->version, p_c->version);
|
||||
RPC_RSP_COPY_BYTES(p_a->project_name, p_c->project_name);
|
||||
RPC_RSP_COPY_BYTES(p_a->time, p_c->time);
|
||||
RPC_RSP_COPY_BYTES(p_a->date, p_c->date);
|
||||
RPC_RSP_COPY_BYTES(p_a->idf_ver, p_c->idf_ver);
|
||||
RPC_RSP_COPY_BYTES(p_a->app_elf_sha256, p_c->app_elf_sha256);
|
||||
p_a->min_efuse_blk_rev_full = p_c->min_efuse_blk_rev_full;
|
||||
p_a->max_efuse_blk_rev_full = p_c->max_efuse_blk_rev_full;
|
||||
p_a->mmu_page_size = p_c->mmu_page_size;
|
||||
break;
|
||||
} case RPC_ID__Resp_SetDhcpDnsStatus: {
|
||||
RPC_FAIL_ON_NULL(resp_set_dhcp_dns);
|
||||
RPC_ERR_IN_RESP(resp_set_dhcp_dns);
|
||||
break;
|
||||
#if H_MEM_MONITOR
|
||||
} case RPC_ID__Resp_MemMonitor: {
|
||||
RPC_FAIL_ON_NULL(resp_mem_monitor);
|
||||
RPC_ERR_IN_RESP(resp_mem_monitor);
|
||||
RPC_FAIL_ON_NULL(resp_mem_monitor->curr_internal);
|
||||
RPC_FAIL_ON_NULL(resp_mem_monitor->curr_internal->mem_dma);
|
||||
RPC_FAIL_ON_NULL(resp_mem_monitor->curr_internal->mem_8bit);
|
||||
RPC_FAIL_ON_NULL(resp_mem_monitor->curr_external);
|
||||
RPC_FAIL_ON_NULL(resp_mem_monitor->curr_external->mem_dma);
|
||||
RPC_FAIL_ON_NULL(resp_mem_monitor->curr_external->mem_8bit);
|
||||
|
||||
// copy over the response
|
||||
esp_hosted_curr_mem_info_t *p_a = &app_resp->u.curr_mem_info;
|
||||
RpcRespMemMonitor *p_c = rpc_msg->resp_mem_monitor;
|
||||
|
||||
if (p_c->config == RPC__MEM_MONITOR_CONFIG__MEMMONITOR_NO_CHANGE) {
|
||||
p_a->config = ESP_HOSTED_MEMMONITOR_NO_CHANGE;
|
||||
} else if (p_c->config == RPC__MEM_MONITOR_CONFIG__MEMMONITOR_DISABLE) {
|
||||
p_a->config = ESP_HOSTED_MEMMONITOR_DISABLE;
|
||||
} else if (p_c->config == RPC__MEM_MONITOR_CONFIG__MEMMONITOR_ENABLE) {
|
||||
p_a->config = ESP_HOSTED_MEMMONITOR_ENABLE;
|
||||
}
|
||||
p_a->report_always = p_c->report_always;
|
||||
p_a->interval_sec = p_c->interval_sec;
|
||||
p_a->curr_total_heap_size = p_c->curr_total_heap_size;
|
||||
p_a->curr_internal.cap_dma.free_size = p_c->curr_internal->mem_dma->free_size;
|
||||
p_a->curr_internal.cap_dma.largest_free_block = p_c->curr_internal->mem_dma->largest_free_block;
|
||||
p_a->curr_internal.cap_8bit.free_size = p_c->curr_internal->mem_8bit->free_size;
|
||||
p_a->curr_internal.cap_8bit.largest_free_block = p_c->curr_internal->mem_8bit->largest_free_block;
|
||||
p_a->curr_external.cap_dma.free_size = p_c->curr_external->mem_dma->free_size;
|
||||
p_a->curr_external.cap_dma.largest_free_block = p_c->curr_external->mem_dma->largest_free_block;
|
||||
p_a->curr_external.cap_8bit.free_size = p_c->curr_external->mem_8bit->free_size;
|
||||
p_a->curr_external.cap_8bit.largest_free_block = p_c->curr_external->mem_8bit->largest_free_block;
|
||||
break;
|
||||
#endif
|
||||
#if H_WIFI_ENTERPRISE_SUPPORT
|
||||
} case RPC_ID__Resp_WifiStaEnterpriseEnable: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_sta_enterprise_enable);
|
||||
RPC_ERR_IN_RESP(resp_wifi_sta_enterprise_enable);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiStaEnterpriseDisable: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_sta_enterprise_disable);
|
||||
RPC_ERR_IN_RESP(resp_wifi_sta_enterprise_disable);
|
||||
break;
|
||||
} case RPC_ID__Resp_EapSetIdentity: {
|
||||
RPC_FAIL_ON_NULL(resp_eap_set_identity);
|
||||
RPC_ERR_IN_RESP(resp_eap_set_identity);
|
||||
break;
|
||||
} case RPC_ID__Resp_EapClearIdentity: {
|
||||
RPC_FAIL_ON_NULL(resp_eap_clear_identity);
|
||||
RPC_ERR_IN_RESP(resp_eap_clear_identity);
|
||||
break;
|
||||
} case RPC_ID__Resp_EapSetUsername: {
|
||||
RPC_FAIL_ON_NULL(resp_eap_set_username);
|
||||
RPC_ERR_IN_RESP(resp_eap_set_username);
|
||||
break;
|
||||
} case RPC_ID__Resp_EapClearUsername: {
|
||||
RPC_FAIL_ON_NULL(resp_eap_clear_username);
|
||||
RPC_ERR_IN_RESP(resp_eap_clear_username);
|
||||
break;
|
||||
} case RPC_ID__Resp_EapSetPassword: {
|
||||
RPC_FAIL_ON_NULL(resp_eap_set_password);
|
||||
RPC_ERR_IN_RESP(resp_eap_set_password);
|
||||
break;
|
||||
} case RPC_ID__Resp_EapClearPassword: {
|
||||
RPC_FAIL_ON_NULL(resp_eap_clear_password);
|
||||
RPC_ERR_IN_RESP(resp_eap_clear_password);
|
||||
break;
|
||||
} case RPC_ID__Resp_EapSetNewPassword: {
|
||||
RPC_FAIL_ON_NULL(resp_eap_set_new_password);
|
||||
RPC_ERR_IN_RESP(resp_eap_set_new_password);
|
||||
break;
|
||||
} case RPC_ID__Resp_EapClearNewPassword: {
|
||||
RPC_FAIL_ON_NULL(resp_eap_clear_new_password);
|
||||
RPC_ERR_IN_RESP(resp_eap_clear_new_password);
|
||||
break;
|
||||
} case RPC_ID__Resp_EapSetCaCert: {
|
||||
RPC_FAIL_ON_NULL(resp_eap_set_ca_cert);
|
||||
RPC_ERR_IN_RESP(resp_eap_set_ca_cert);
|
||||
break;
|
||||
} case RPC_ID__Resp_EapClearCaCert: {
|
||||
RPC_FAIL_ON_NULL(resp_eap_clear_ca_cert);
|
||||
RPC_ERR_IN_RESP(resp_eap_clear_ca_cert);
|
||||
break;
|
||||
} case RPC_ID__Resp_EapSetCertificateAndKey: {
|
||||
RPC_FAIL_ON_NULL(resp_eap_set_certificate_and_key);
|
||||
RPC_ERR_IN_RESP(resp_eap_set_certificate_and_key);
|
||||
break;
|
||||
} case RPC_ID__Resp_EapClearCertificateAndKey: {
|
||||
RPC_FAIL_ON_NULL(resp_eap_clear_certificate_and_key);
|
||||
RPC_ERR_IN_RESP(resp_eap_clear_certificate_and_key);
|
||||
break;
|
||||
} case RPC_ID__Resp_EapGetDisableTimeCheck: {
|
||||
RPC_FAIL_ON_NULL(resp_eap_get_disable_time_check);
|
||||
RPC_ERR_IN_RESP(resp_eap_get_disable_time_check);
|
||||
app_resp->u.eap_disable_time_check.disable = rpc_msg->resp_eap_get_disable_time_check->disable;
|
||||
break;
|
||||
} case RPC_ID__Resp_EapSetTtlsPhase2Method: {
|
||||
RPC_FAIL_ON_NULL(resp_eap_set_ttls_phase2_method);
|
||||
RPC_ERR_IN_RESP(resp_eap_set_ttls_phase2_method);
|
||||
break;
|
||||
} case RPC_ID__Resp_EapSetSuitebCertification: {
|
||||
RPC_FAIL_ON_NULL(resp_eap_set_suiteb_certification);
|
||||
RPC_ERR_IN_RESP(resp_eap_set_suiteb_certification);
|
||||
break;
|
||||
} case RPC_ID__Resp_EapSetPacFile: {
|
||||
RPC_FAIL_ON_NULL(resp_eap_set_pac_file);
|
||||
RPC_ERR_IN_RESP(resp_eap_set_pac_file);
|
||||
break;
|
||||
} case RPC_ID__Resp_EapSetFastParams: {
|
||||
RPC_FAIL_ON_NULL(resp_eap_set_fast_params);
|
||||
RPC_ERR_IN_RESP(resp_eap_set_fast_params);
|
||||
break;
|
||||
} case RPC_ID__Resp_EapUseDefaultCertBundle: {
|
||||
RPC_FAIL_ON_NULL(resp_eap_use_default_cert_bundle);
|
||||
RPC_ERR_IN_RESP(resp_eap_use_default_cert_bundle);
|
||||
break;
|
||||
} case RPC_ID__Resp_WifiSetOkcSupport: {
|
||||
RPC_FAIL_ON_NULL(resp_wifi_set_okc_support);
|
||||
RPC_ERR_IN_RESP(resp_wifi_set_okc_support);
|
||||
break;
|
||||
} case RPC_ID__Resp_EapSetDomainName: {
|
||||
RPC_FAIL_ON_NULL(resp_eap_set_domain_name);
|
||||
RPC_ERR_IN_RESP(resp_eap_set_domain_name);
|
||||
break;
|
||||
} case RPC_ID__Resp_EapSetDisableTimeCheck: {
|
||||
RPC_FAIL_ON_NULL(resp_eap_set_disable_time_check);
|
||||
RPC_ERR_IN_RESP(resp_eap_set_disable_time_check);
|
||||
break;
|
||||
} case RPC_ID__Resp_EapSetEapMethods: {
|
||||
RPC_FAIL_ON_NULL(resp_eap_set_eap_methods);
|
||||
RPC_ERR_IN_RESP(resp_eap_set_eap_methods);
|
||||
break;
|
||||
#endif
|
||||
#if H_DPP_SUPPORT
|
||||
} case RPC_ID__Resp_SuppDppInit: {
|
||||
RPC_FAIL_ON_NULL(resp_supp_dpp_init);
|
||||
RPC_ERR_IN_RESP(resp_supp_dpp_init);
|
||||
break;
|
||||
} case RPC_ID__Resp_SuppDppDeinit: {
|
||||
RPC_FAIL_ON_NULL(resp_supp_dpp_deinit);
|
||||
RPC_ERR_IN_RESP(resp_supp_dpp_deinit);
|
||||
break;
|
||||
} case RPC_ID__Resp_SuppDppBootstrapGen: {
|
||||
RPC_FAIL_ON_NULL(resp_supp_dpp_bootstrap_gen);
|
||||
RPC_ERR_IN_RESP(resp_supp_dpp_bootstrap_gen);
|
||||
break;
|
||||
} case RPC_ID__Resp_SuppDppStartListen: {
|
||||
RPC_FAIL_ON_NULL(resp_supp_dpp_start_listen);
|
||||
RPC_ERR_IN_RESP(resp_supp_dpp_start_listen);
|
||||
break;
|
||||
} case RPC_ID__Resp_SuppDppStopListen: {
|
||||
RPC_FAIL_ON_NULL(resp_supp_dpp_stop_listen);
|
||||
RPC_ERR_IN_RESP(resp_supp_dpp_stop_listen);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if H_GPIO_EXPANDER_SUPPORT
|
||||
} case RPC_ID__Resp_GpioConfig: {
|
||||
RPC_FAIL_ON_NULL(resp_gpio_config);
|
||||
RPC_ERR_IN_RESP(resp_gpio_config);
|
||||
break;
|
||||
} case RPC_ID__Resp_GpioResetPin: {
|
||||
RPC_FAIL_ON_NULL(resp_gpio_reset);
|
||||
RPC_ERR_IN_RESP(resp_gpio_reset);
|
||||
break;
|
||||
} case RPC_ID__Resp_GpioSetLevel: {
|
||||
RPC_FAIL_ON_NULL(resp_gpio_set_level);
|
||||
RPC_ERR_IN_RESP(resp_gpio_set_level);
|
||||
break;
|
||||
} case RPC_ID__Resp_GpioGetLevel: {
|
||||
RPC_FAIL_ON_NULL(resp_gpio_get_level);
|
||||
RPC_ERR_IN_RESP(resp_gpio_get_level);
|
||||
app_resp->u.gpio_get_level = rpc_msg->resp_gpio_get_level->level;
|
||||
break;
|
||||
} case RPC_ID__Resp_GpioSetDirection: {
|
||||
RPC_FAIL_ON_NULL(resp_gpio_set_direction);
|
||||
RPC_ERR_IN_RESP(resp_gpio_set_direction);
|
||||
break;
|
||||
} case RPC_ID__Resp_GpioInputEnable: {
|
||||
RPC_FAIL_ON_NULL(resp_gpio_input_enable);
|
||||
RPC_ERR_IN_RESP(resp_gpio_input_enable);
|
||||
break;
|
||||
} case RPC_ID__Resp_GpioSetPullMode: {
|
||||
RPC_FAIL_ON_NULL(resp_gpio_set_pull_mode);
|
||||
RPC_ERR_IN_RESP(resp_gpio_set_pull_mode);
|
||||
break;
|
||||
#endif
|
||||
#if H_EXT_COEX_SUPPORT
|
||||
} case RPC_ID__Resp_ExtCoex: {
|
||||
RPC_FAIL_ON_NULL(resp_ext_coex);
|
||||
RPC_ERR_IN_RESP(resp_ext_coex);
|
||||
break;
|
||||
#endif
|
||||
} default: {
|
||||
ESP_LOGE(TAG, "Unsupported rpc Resp[%u]", rpc_msg->msg_id);
|
||||
goto fail_parse_rpc_msg;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
app_resp->resp_event_status = SUCCESS;
|
||||
return SUCCESS;
|
||||
|
||||
/* 5. Free up buffers in failure cases */
|
||||
fail_parse_rpc_msg:
|
||||
return SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "rpc_utils.h"
|
||||
#include "rpc_core.h"
|
||||
#include "esp_hosted_bitmasks.h"
|
||||
#include "esp_hosted_os_abstraction.h"
|
||||
|
||||
#include "port_esp_hosted_host_wifi_config.h"
|
||||
#include "port_esp_hosted_host_log.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
DEFINE_LOG_TAG(rpc_utils);
|
||||
|
||||
#define RPC_UTILS_COPY_BYTES(dst,src) { \
|
||||
if (src.data && src.len) { \
|
||||
g_h.funcs->_h_memcpy(dst, src.data, src.len); \
|
||||
} \
|
||||
}
|
||||
|
||||
esp_err_t rpc_copy_wifi_sta_config(wifi_sta_config_t *dst, WifiStaConfig *src)
|
||||
{
|
||||
wifi_sta_config_t * p_a_sta = dst;
|
||||
WifiStaConfig * p_c_sta = src;
|
||||
|
||||
ESP_LOGW(TAG, "Event: SSID %s", p_c_sta->ssid.data);
|
||||
RPC_UTILS_COPY_BYTES(p_a_sta->ssid, p_c_sta->ssid);
|
||||
RPC_UTILS_COPY_BYTES(p_a_sta->password, p_c_sta->password);
|
||||
p_a_sta->scan_method = p_c_sta->scan_method;
|
||||
p_a_sta->bssid_set = p_c_sta->bssid_set;
|
||||
RPC_UTILS_COPY_BYTES(p_a_sta->bssid, p_c_sta->bssid);
|
||||
p_a_sta->channel = p_c_sta->channel;
|
||||
p_a_sta->listen_interval = p_c_sta->listen_interval;
|
||||
p_a_sta->sort_method = p_c_sta->sort_method;
|
||||
if (p_c_sta->threshold) {
|
||||
p_a_sta->threshold.rssi = p_c_sta->threshold->rssi;
|
||||
p_a_sta->threshold.authmode = p_c_sta->threshold->authmode;
|
||||
#if H_PRESENT_IN_ESP_IDF_5_4_0
|
||||
p_a_sta->threshold.rssi_5g_adjustment = p_c_sta->threshold->rssi_5g_adjustment;
|
||||
#endif
|
||||
}
|
||||
//p_a_sta->ssid_hidden = p_c_sta->ssid_hidden;
|
||||
//p_a_sta->max_connections = p_c_sta->max_connections;
|
||||
if (p_c_sta->pmf_cfg) {
|
||||
p_a_sta->pmf_cfg.capable = p_c_sta->pmf_cfg->capable;
|
||||
p_a_sta->pmf_cfg.required = p_c_sta->pmf_cfg->required;
|
||||
}
|
||||
p_a_sta->rm_enabled = H_GET_BIT(WIFI_STA_CONFIG_1_rm_enabled, p_c_sta->bitmask);
|
||||
p_a_sta->btm_enabled = H_GET_BIT(WIFI_STA_CONFIG_1_btm_enabled, p_c_sta->bitmask);
|
||||
p_a_sta->mbo_enabled = H_GET_BIT(WIFI_STA_CONFIG_1_mbo_enabled, p_c_sta->bitmask);
|
||||
p_a_sta->ft_enabled = H_GET_BIT(WIFI_STA_CONFIG_1_ft_enabled, p_c_sta->bitmask);
|
||||
p_a_sta->owe_enabled = H_GET_BIT(WIFI_STA_CONFIG_1_owe_enabled, p_c_sta->bitmask);
|
||||
p_a_sta->transition_disable = H_GET_BIT(WIFI_STA_CONFIG_1_transition_disable, p_c_sta->bitmask);
|
||||
|
||||
#if H_DECODE_WIFI_RESERVED_FIELD
|
||||
#if H_WIFI_NEW_RESERVED_FIELD_NAMES
|
||||
p_a_sta->reserved1 = WIFI_STA_CONFIG_1_GET_RESERVED_VAL(p_c_sta->bitmask);
|
||||
#else
|
||||
p_a_sta->reserved = WIFI_STA_CONFIG_1_GET_RESERVED_VAL(p_c_sta->bitmask);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
p_a_sta->sae_pwe_h2e = p_c_sta->sae_pwe_h2e;
|
||||
p_a_sta->sae_pk_mode = p_c_sta->sae_pk_mode;
|
||||
p_a_sta->failure_retry_cnt = p_c_sta->failure_retry_cnt;
|
||||
|
||||
p_a_sta->he_dcm_set = H_GET_BIT(WIFI_STA_CONFIG_2_he_dcm_set_BIT, p_c_sta->he_bitmask);
|
||||
|
||||
// WIFI_HE_STA_CONFIG_he_dcm_max_constellation_tx is two bits wide
|
||||
p_a_sta->he_dcm_max_constellation_tx = (p_c_sta->he_bitmask >> WIFI_STA_CONFIG_2_he_dcm_max_constellation_tx_BITS) & 0x03;
|
||||
// WIFI_HE_STA_CONFIG_he_dcm_max_constellation_rx is two bits wide
|
||||
p_a_sta->he_dcm_max_constellation_rx = (p_c_sta->he_bitmask >> WIFI_STA_CONFIG_2_he_dcm_max_constellation_rx_BITS) & 0x03;
|
||||
p_a_sta->he_mcs9_enabled = H_GET_BIT(WIFI_STA_CONFIG_2_he_mcs9_enabled_BIT, p_c_sta->he_bitmask);
|
||||
p_a_sta->he_su_beamformee_disabled = H_GET_BIT(WIFI_STA_CONFIG_2_he_su_beamformee_disabled_BIT, p_c_sta->he_bitmask);
|
||||
p_a_sta->he_trig_su_bmforming_feedback_disabled = H_GET_BIT(WIFI_STA_CONFIG_2_he_trig_su_bmforming_feedback_disabled_BIT, p_c_sta->bitmask);
|
||||
p_a_sta->he_trig_mu_bmforming_partial_feedback_disabled = H_GET_BIT(WIFI_STA_CONFIG_2_he_trig_mu_bmforming_partial_feedback_disabled_BIT, p_c_sta->bitmask);
|
||||
p_a_sta->he_trig_cqi_feedback_disabled = H_GET_BIT(WIFI_STA_CONFIG_2_he_trig_cqi_feedback_disabled_BIT, p_c_sta->bitmask);
|
||||
|
||||
#if H_PRESENT_IN_ESP_IDF_5_5_0
|
||||
p_a_sta->vht_su_beamformee_disabled = H_GET_BIT(WIFI_STA_CONFIG_2_vht_su_beamformee_disabled, p_c_sta->he_bitmask);
|
||||
p_a_sta->vht_mu_beamformee_disabled = H_GET_BIT(WIFI_STA_CONFIG_2_vht_mu_beamformee_disabled, p_c_sta->he_bitmask);
|
||||
p_a_sta->vht_mcs8_enabled = H_GET_BIT(WIFI_STA_CONFIG_2_vht_mcs8_enabled, p_c_sta->he_bitmask);
|
||||
#endif
|
||||
|
||||
#if H_DECODE_WIFI_RESERVED_FIELD
|
||||
#if H_WIFI_NEW_RESERVED_FIELD_NAMES
|
||||
p_a_sta->reserved2 = WIFI_STA_CONFIG_2_GET_RESERVED_VAL(p_c_sta->he_bitmask);
|
||||
#else
|
||||
p_a_sta->he_reserved = WIFI_STA_CONFIG_2_GET_RESERVED_VAL(p_c_sta->he_bitmask);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return ESP_FAIL;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* Common functions used by rpc code */
|
||||
|
||||
#ifndef __RPC_UTILS_H
|
||||
#define __RPC_UTILS_H
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_wifi.h"
|
||||
|
||||
#include "rpc_slave_if.h"
|
||||
|
||||
esp_err_t rpc_copy_wifi_sta_config(wifi_sta_config_t *dst, WifiStaConfig *src);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,744 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "rpc_slave_if.h"
|
||||
#include "rpc_core.h"
|
||||
#include "port_esp_hosted_host_wifi_config.h"
|
||||
#include "port_esp_hosted_host_log.h"
|
||||
|
||||
DEFINE_LOG_TAG(rpc_api);
|
||||
|
||||
#define RPC_SEND_REQ(msGiD) do { \
|
||||
assert(req); \
|
||||
req->msg_id = msGiD; \
|
||||
if(SUCCESS != rpc_send_req(req)) { \
|
||||
ESP_LOGE(TAG,"Failed to send control req 0x%x\n", req->msg_id); \
|
||||
return NULL; \
|
||||
} \
|
||||
} while(0);
|
||||
|
||||
#define RPC_DECODE_RSP_IF_NOT_ASYNC() do { \
|
||||
if (req->rpc_rsp_cb) \
|
||||
return NULL; \
|
||||
return rpc_wait_and_parse_sync_resp(req); \
|
||||
} while(0);
|
||||
|
||||
|
||||
int rpc_slaveif_init(void)
|
||||
{
|
||||
ESP_LOGD(TAG, "%s", __func__);
|
||||
return rpc_core_init();
|
||||
}
|
||||
|
||||
int rpc_slaveif_start(void)
|
||||
{
|
||||
ESP_LOGD(TAG, "%s", __func__);
|
||||
return rpc_core_start();
|
||||
}
|
||||
|
||||
int rpc_slaveif_stop(void)
|
||||
{
|
||||
ESP_LOGD(TAG, "%s", __func__);
|
||||
return rpc_core_stop();
|
||||
}
|
||||
|
||||
int rpc_slaveif_deinit(void)
|
||||
{
|
||||
ESP_LOGD(TAG, "%s", __func__);
|
||||
return rpc_core_deinit();
|
||||
}
|
||||
|
||||
/** Control Req->Resp APIs **/
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_mac(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_GetMACAddress);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_mac(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_SetMacAddress);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_mode(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_GetWifiMode);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_mode(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_SetWifiMode);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_ps(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiSetPs);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_ps(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiGetPs);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_max_tx_power(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiSetMaxTxPower);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_max_tx_power(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiGetMaxTxPower);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_config_heartbeat(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_ConfigHeartbeat);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_ota_begin(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_OTABegin);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_ota_write(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_OTAWrite);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_ota_end(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_OTAEnd);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_ota_activate(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_OTAActivate);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_init(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiInit);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_deinit(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiDeinit);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_start(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiStart);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_stop(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiStop);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_connect(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiConnect);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_disconnect(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiDisconnect);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_config(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiGetConfig);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_config(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiSetConfig);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_scan_params(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiScanParams);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_scan_start(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiScanStart);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_scan_stop(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiScanStop);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_scan_get_ap_num(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiScanGetApNum);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_scan_get_ap_record(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiScanGetApRecord);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_scan_get_ap_records(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiScanGetApRecords);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_clear_ap_list(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiClearApList);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_restore(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiRestore);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_clear_fast_connect(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiClearFastConnect);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_deauth_sta(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiDeauthSta);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_sta_get_ap_info(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiStaGetApInfo);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_storage(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiSetStorage);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_bandwidth(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiSetBandwidth);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_bandwidth(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiGetBandwidth);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_channel(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiSetChannel);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_channel(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiGetChannel);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_country_code(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiSetCountryCode);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_country_code(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiGetCountryCode);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_country(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiSetCountry);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_country(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiGetCountry);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_ap_get_sta_list(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiApGetStaList);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_ap_get_sta_aid(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiApGetStaAid);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_sta_get_rssi(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiStaGetRssi);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_protocol(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiSetProtocol);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_protocol(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiGetProtocol);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_sta_get_negotiated_phymode(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiStaGetNegotiatedPhymode);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_sta_get_aid(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiStaGetAid);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_protocols(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiSetProtocols);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_inactive_time(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiSetInactiveTime);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_inactive_time(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiGetInactiveTime);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_disable_pmf_config(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiDisablePmfConfig);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
#if H_WIFI_HE_SUPPORT
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_sta_twt_config(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiStaTwtConfig);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_sta_itwt_setup(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiStaItwtSetup);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_sta_itwt_teardown(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiStaItwtTeardown);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_sta_itwt_suspend(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiStaItwtSuspend);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_sta_itwt_get_flow_id_status(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiStaItwtGetFlowIdStatus);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_sta_itwt_send_probe_req(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiStaItwtSendProbeReq);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_sta_itwt_set_target_wake_time_offset(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiStaItwtSetTargetWakeTimeOffset);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
#endif
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_get_coprocessor_fwversion(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_GetCoprocessorFwVersion);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_iface_mac_addr_set_get(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_IfaceMacAddrSetGet);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_feature_control(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_FeatureControl);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_get_coprocessor_app_desc(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_AppGetDesc);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_iface_mac_addr_len_get(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_IfaceMacAddrLenGet);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
#if H_WIFI_DUALBAND_SUPPORT
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_protocols(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiGetProtocols);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_bandwidths(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiSetBandwidths);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_bandwidths(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiGetBandwidths);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_band(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiSetBand);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_band(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiGetBand);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_band_mode(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiSetBandMode);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_band_mode(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiGetBandMode);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
#endif
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_set_slave_dhcp_dns_status(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_SetDhcpDnsStatus);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
|
||||
#if H_WIFI_ENTERPRISE_SUPPORT
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_sta_enterprise_enable(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiStaEnterpriseEnable);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_sta_enterprise_disable(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiStaEnterpriseDisable);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_eap_set_identity(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_EapSetIdentity);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_eap_clear_identity(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_EapClearIdentity);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_eap_set_username(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_EapSetUsername);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_eap_clear_username(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_EapClearUsername);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_eap_set_password(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_EapSetPassword);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_eap_clear_password(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_EapClearPassword);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_eap_set_new_password(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_EapSetNewPassword);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_eap_clear_new_password(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_EapClearNewPassword);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_eap_set_ca_cert(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_EapSetCaCert);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_eap_clear_ca_cert(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_EapClearCaCert);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_eap_set_certificate_and_key(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_EapSetCertificateAndKey);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_eap_clear_certificate_and_key(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_EapClearCertificateAndKey);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_eap_get_disable_time_check(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_EapGetDisableTimeCheck);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_eap_set_ttls_phase2_method(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_EapSetTtlsPhase2Method);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_eap_set_suiteb_certification(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_EapSetSuitebCertification);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_eap_set_pac_file(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_EapSetPacFile);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_eap_set_fast_params(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_EapSetFastParams);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_eap_use_default_cert_bundle(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_EapUseDefaultCertBundle);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_okc_support(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_WifiSetOkcSupport);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_eap_set_domain_name(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_EapSetDomainName);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_eap_set_disable_time_check(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_EapSetDisableTimeCheck);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
#if H_GOT_SET_EAP_METHODS_API
|
||||
ctrl_cmd_t * rpc_slaveif_eap_set_eap_methods(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_EapSetEapMethods);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#if H_DPP_SUPPORT
|
||||
ctrl_cmd_t * rpc_slaveif_supp_dpp_init(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_SuppDppInit);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_supp_dpp_deinit(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_SuppDppDeinit);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_supp_dpp_bootstrap_gen(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_SuppDppBootstrapGen);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_supp_dpp_start_listen(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_SuppDppStartListen);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_supp_dpp_stop_listen(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_SuppDppStopListen);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if H_MEM_MONITOR
|
||||
ctrl_cmd_t * rpc_slave_iface_set_mem_monitor(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_MemMonitor);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef H_PEER_DATA_TRANSFER
|
||||
int rpc_slaveif_register_custom_callback(uint32_t msg_id_exp,
|
||||
void (*callback)(uint32_t msg_id_recvd, const uint8_t *data_recvd, size_t data_len_recvd, void *local_context),
|
||||
void *local_context)
|
||||
{
|
||||
return rpc_evt_register_custom_callback(msg_id_exp, callback, local_context);
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_custom_rpc(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_CustomRpc);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if H_GPIO_EXPANDER_SUPPORT
|
||||
ctrl_cmd_t * rpc_slaveif_gpio_config(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_GpioConfig);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_gpio_reset_pin(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_GpioResetPin);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_gpio_set_level(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_GpioSetLevel);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_gpio_get_level(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_GpioGetLevel);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_gpio_set_direction(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_GpioSetDirection);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_gpio_input_enable(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_GpioInputEnable);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_gpio_set_pull_mode(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_GpioSetPullMode);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if H_EXT_COEX_SUPPORT
|
||||
ctrl_cmd_t * rpc_slaveif_ext_coex(ctrl_cmd_t *req)
|
||||
{
|
||||
RPC_SEND_REQ(RPC_ID__Req_ExtCoex);
|
||||
RPC_DECODE_RSP_IF_NOT_ASYNC();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,924 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/** prevent recursive inclusion **/
|
||||
#ifndef __RPC_SLAVE_IF_H
|
||||
#define __RPC_SLAVE_IF_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "esp_hosted_rpc.pb-c.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_mac.h"
|
||||
#include "esp_wifi_types.h"
|
||||
#include "esp_hosted_misc.h"
|
||||
#include "esp_hosted_misc_types.h"
|
||||
#include "port_esp_hosted_host_config.h"
|
||||
#include "port_esp_hosted_host_wifi_config.h"
|
||||
|
||||
#if H_WIFI_ENTERPRISE_SUPPORT
|
||||
#include "esp_eap_client.h"
|
||||
#endif
|
||||
#if H_DPP_SUPPORT
|
||||
#include "esp_dpp.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SSID_LENGTH 32
|
||||
#define BSSID_BYTES_SIZE 6
|
||||
#define PASSWORD_LENGTH 64
|
||||
#define STATUS_LENGTH 14
|
||||
#define VENDOR_OUI_BUF 3
|
||||
|
||||
#define IFACE_MAC_SIZE 8 // 6 for MAC-48, 8 for EIU-64, 2 for EFUSE_EXT
|
||||
#define IDF_TARGET_SIZE 20 // increase as required if CONFIG_IDF_TARGET gets larger
|
||||
|
||||
/*
|
||||
#define SUCCESS 0
|
||||
#define FAILURE -1
|
||||
*/
|
||||
|
||||
#define CALLBACK_SET_SUCCESS 0
|
||||
#define CALLBACK_AVAILABLE 0
|
||||
#define CALLBACK_NOT_REGISTERED -1
|
||||
#define MSG_ID_OUT_OF_ORDER -2
|
||||
|
||||
#define MAX_FREE_BUFF_HANDLES 20
|
||||
|
||||
#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
|
||||
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
|
||||
|
||||
/* If request is already being served and
|
||||
* another request is pending, time period for
|
||||
* which new request will wait in seconds
|
||||
* */
|
||||
//#define WAIT_TIME_B2B_RPC_REQ 5
|
||||
#define DEFAULT_RPC_RSP_TIMEOUT 5
|
||||
#define DEFAULT_RPC_RSP_SCAN_TIMEOUT 30
|
||||
|
||||
#define SUCCESS_STR "success"
|
||||
#define FAILURE_STR "failure"
|
||||
#define NOT_CONNECTED_STR "not_connected"
|
||||
|
||||
#define RPC_RX_QUEUE_SIZE 3
|
||||
#define RPC_TX_QUEUE_SIZE 5
|
||||
|
||||
typedef enum {
|
||||
FEATURE_NONE,
|
||||
FEATURE_BT,
|
||||
FEATURE_OPENTHREAD_RCP,
|
||||
// add additional features here
|
||||
} rpc_feature;
|
||||
|
||||
typedef enum {
|
||||
FEATURE_COMMAND_NONE,
|
||||
FEATURE_COMMAND_BT_INIT,
|
||||
FEATURE_COMMAND_BT_DEINIT,
|
||||
FEATURE_COMMAND_BT_ENABLE,
|
||||
FEATURE_COMMAND_BT_DISABLE,
|
||||
// these can apply to any generic feature
|
||||
FEATURE_COMMAND_INIT,
|
||||
FEATURE_COMMAND_DEINIT,
|
||||
FEATURE_COMMAND_ENABLE,
|
||||
FEATURE_COMMAND_DISABLE,
|
||||
FEATURE_COMMAND_QUERY,
|
||||
// add additional feature commands here
|
||||
} rpc_feature_command;
|
||||
|
||||
typedef enum {
|
||||
FEATURE_OPTION_NONE,
|
||||
FEATURE_OPTION_BT_DEINIT_RELEASE_MEMORY,
|
||||
FEATURE_OPTION_QUERY_CONFIGURED,
|
||||
FEATURE_OPTION_QUERY_INITED,
|
||||
FEATURE_OPTION_QUERY_ENABLED,
|
||||
FEATURE_OPTION_QUERY_READY,
|
||||
// add additional feature options here
|
||||
} rpc_feature_option;
|
||||
|
||||
/*---- Control structures ----*/
|
||||
|
||||
typedef struct {
|
||||
rpc_feature feature;
|
||||
rpc_feature_command command;
|
||||
rpc_feature_option option;
|
||||
} rcp_feature_control_t;
|
||||
|
||||
typedef struct {
|
||||
int mode;
|
||||
uint8_t mac[BSSID_BYTES_SIZE];
|
||||
} wifi_mac_t;
|
||||
|
||||
typedef struct {
|
||||
int mode;
|
||||
} hosted_mode_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t iface;
|
||||
wifi_config_t u;
|
||||
} wifi_cfg_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
wifi_scan_time_t scan_time;
|
||||
uint8_t home_chan_dwell_time;
|
||||
} rpc_wifi_scan_default_params_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t cmd;
|
||||
rpc_wifi_scan_default_params_t config;
|
||||
bool is_config_null;
|
||||
} rpc_wifi_scan_params_t;
|
||||
|
||||
/** @brief Parameters for an SSID scan. */
|
||||
typedef struct {
|
||||
bool block;
|
||||
wifi_scan_config_t cfg;
|
||||
uint8_t cfg_set;
|
||||
} wifi_scan_cfg_t;
|
||||
|
||||
typedef struct {
|
||||
//int count;
|
||||
int number;
|
||||
/* dynamic size */
|
||||
//wifi_scanlist_t *out_list;
|
||||
wifi_ap_record_t *out_list;
|
||||
} wifi_scan_ap_list_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t aid;
|
||||
} wifi_deauth_sta_t;
|
||||
|
||||
typedef struct {
|
||||
int ps_mode;
|
||||
} wifi_power_save_t;
|
||||
|
||||
typedef struct {
|
||||
bool enable;
|
||||
wifi_vendor_ie_type_t type;
|
||||
wifi_vendor_ie_id_t idx;
|
||||
vendor_ie_data_t vnd_ie;
|
||||
} wifi_softap_vendor_ie_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t *ota_data;
|
||||
uint32_t ota_data_len;
|
||||
} ota_write_t;
|
||||
|
||||
typedef struct {
|
||||
int power;
|
||||
} wifi_tx_power_t;
|
||||
|
||||
typedef struct {
|
||||
wifi_interface_t ifx;
|
||||
wifi_bandwidth_t bw;
|
||||
} rpc_wifi_bandwidth_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t primary;
|
||||
wifi_second_chan_t second;
|
||||
} rpc_wifi_channel_t;
|
||||
|
||||
typedef struct {
|
||||
char cc[3];
|
||||
bool ieee80211d_enabled;
|
||||
} rpc_wifi_country_code;
|
||||
|
||||
typedef struct {
|
||||
wifi_interface_t ifx;
|
||||
uint8_t protocol_bitmap;
|
||||
} rpc_wifi_protocol;
|
||||
|
||||
typedef struct {
|
||||
uint8_t mac[6];
|
||||
uint16_t aid;
|
||||
} rpc_wifi_ap_get_sta_aid_t;
|
||||
|
||||
typedef struct {
|
||||
int rssi;
|
||||
} rpc_wifi_sta_get_rssi_t;
|
||||
|
||||
typedef struct {
|
||||
wifi_phy_mode_t phymode;
|
||||
} rpc_wifi_sta_get_negotiated_phymode_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t aid;
|
||||
} rpc_wifi_sta_get_aid_t;
|
||||
|
||||
typedef struct {
|
||||
wifi_interface_t ifx;
|
||||
uint16_t ghz_2g;
|
||||
uint16_t ghz_5g;
|
||||
} rpc_wifi_protocols_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t major1;
|
||||
uint32_t minor1;
|
||||
uint32_t patch1;
|
||||
int32_t revision;
|
||||
int32_t prerelease;
|
||||
int32_t build;
|
||||
uint32_t chip_id;
|
||||
char idf_target[IDF_TARGET_SIZE];
|
||||
} rpc_coprocessor_fwversion_t;
|
||||
|
||||
typedef struct {
|
||||
wifi_interface_t ifx;
|
||||
wifi_bandwidth_t ghz_2g;
|
||||
wifi_bandwidth_t ghz_5g;
|
||||
} rpc_wifi_bandwidths_t;
|
||||
|
||||
typedef struct {
|
||||
int iface;
|
||||
int net_link_up;
|
||||
int dhcp_up;
|
||||
uint8_t dhcp_ip[64];
|
||||
uint8_t dhcp_nm[64];
|
||||
uint8_t dhcp_gw[64];
|
||||
int dns_up;
|
||||
uint8_t dns_ip[64];
|
||||
int dns_type;
|
||||
} rpc_set_dhcp_dns_status_t;
|
||||
|
||||
typedef struct {
|
||||
bool set;
|
||||
esp_mac_type_t type;
|
||||
size_t mac_len;
|
||||
uint8_t mac[IFACE_MAC_SIZE];
|
||||
} rpc_iface_mac_t;
|
||||
|
||||
typedef struct {
|
||||
size_t len;
|
||||
esp_mac_type_t type;
|
||||
} rpc_iface_mac_len_t;
|
||||
|
||||
typedef struct {
|
||||
wifi_interface_t ifx;
|
||||
uint16_t sec;
|
||||
} rpc_wifi_inactive_time_t;
|
||||
|
||||
typedef struct {
|
||||
wifi_interface_t ifx;
|
||||
} rpc_wifi_disable_pmf_config_t;
|
||||
|
||||
#if H_WIFI_HE_SUPPORT
|
||||
typedef struct {
|
||||
int flow_id;
|
||||
int suspend_time_ms;
|
||||
} rpc_wifi_itwt_suspend_t;
|
||||
#endif
|
||||
|
||||
#if H_DPP_SUPPORT
|
||||
// current length of the optional bootstrap gen key length
|
||||
// see documentation for `esp_supp_dpp_bootstrap_gen()`
|
||||
#define DPP_BOOTSTRAP_GEN_KEY_LEN (32)
|
||||
|
||||
#define DPP_URI_LEN_MAX (H_DPP_URI_LEN_MAX + 1) // include NULL at end of string
|
||||
|
||||
typedef struct {
|
||||
const char *chan_list;
|
||||
esp_supp_dpp_bootstrap_t type;
|
||||
const char *key;
|
||||
const char *info;
|
||||
} rpc_supp_dpp_bootstrap_gen_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t uri_data_len; /**< URI data length including null termination */
|
||||
char uri[DPP_URI_LEN_MAX]; /**< URI data */
|
||||
} supp_wifi_event_dpp_uri_ready_t;
|
||||
|
||||
typedef struct {
|
||||
wifi_config_t wifi_cfg; /**< Received WIFI config in DPP */
|
||||
} supp_wifi_event_dpp_config_received_t;
|
||||
|
||||
typedef struct {
|
||||
int failure_reason; /**< Failure reason */
|
||||
} supp_wifi_event_dpp_failed_t;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint32_t cp_reset_reason;
|
||||
} event_init_t;
|
||||
|
||||
typedef struct {
|
||||
/* event */
|
||||
uint32_t hb_num;
|
||||
/* Req */
|
||||
uint8_t enable;
|
||||
uint32_t duration;
|
||||
} event_heartbeat_t;
|
||||
|
||||
typedef struct {
|
||||
int32_t wifi_event_id;
|
||||
} event_wifi_simple_t;
|
||||
|
||||
|
||||
#if H_WIFI_ENTERPRISE_SUPPORT
|
||||
typedef struct {
|
||||
const unsigned char *identity;
|
||||
int len;
|
||||
} rpc_eap_identity_t;
|
||||
|
||||
typedef struct {
|
||||
const unsigned char *username;
|
||||
int len;
|
||||
} rpc_eap_username_t;
|
||||
|
||||
typedef struct {
|
||||
const unsigned char *password;
|
||||
int len;
|
||||
} rpc_eap_password_t;
|
||||
|
||||
typedef struct {
|
||||
const unsigned char *ca_cert;
|
||||
int len;
|
||||
} rpc_eap_ca_cert_t;
|
||||
|
||||
typedef struct {
|
||||
const unsigned char *client_cert;
|
||||
int client_cert_len;
|
||||
const unsigned char *private_key;
|
||||
int private_key_len;
|
||||
const unsigned char *private_key_password;
|
||||
int private_key_passwd_len;
|
||||
} rpc_eap_cert_key_t;
|
||||
|
||||
typedef struct {
|
||||
bool disable;
|
||||
} rpc_eap_disable_time_check_t;
|
||||
|
||||
typedef struct {
|
||||
bool enable;
|
||||
} rpc_eap_suiteb_192bit_t;
|
||||
|
||||
typedef struct {
|
||||
const unsigned char *pac_file;
|
||||
int len;
|
||||
} rpc_eap_pac_file_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
bool use_default;
|
||||
} rpc_eap_default_cert_bundle_t;
|
||||
|
||||
typedef struct {
|
||||
bool enable;
|
||||
} rpc_wifi_okc_support_t;
|
||||
|
||||
typedef struct {
|
||||
const char *domain_name;
|
||||
} rpc_eap_domain_name_t;
|
||||
#endif
|
||||
|
||||
#ifdef H_PEER_DATA_TRANSFER
|
||||
typedef struct {
|
||||
uint32_t custom_msg_id; /* Not used - kept for struct compatibility */
|
||||
uint8_t *data; /* Pointer to raw data */
|
||||
size_t data_len; /* Length of data */
|
||||
void (*free_func)(void *); /* Optional: function to free data after use */
|
||||
} esp_hosted_rpc_data_t;
|
||||
#endif
|
||||
|
||||
#if H_GPIO_EXPANDER_SUPPORT
|
||||
typedef struct {
|
||||
uint64_t pin_bit_mask; /*!< GPIO pin: set with bit mask, each bit maps to a GPIO */
|
||||
uint32_t mode; /*!< GPIO mode: set input/output mode */
|
||||
uint32_t pull_up_en; /*!< GPIO pull-up */
|
||||
uint32_t pull_down_en; /*!< GPIO pull-down */
|
||||
uint32_t intr_type; /*!< GPIO interrupt type */
|
||||
//#if SOC_GPIO_SUPPORT_PIN_HYS_FILTER
|
||||
// uint32_t hys_ctrl_mode; /*!< GPIO hysteresis: hysteresis filter on slope input */
|
||||
//#endif
|
||||
} rpc_gpio_config_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t gpio_num;
|
||||
uint32_t level;
|
||||
} rpc_gpio_set_level_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t gpio_num;
|
||||
uint32_t mode;
|
||||
} rpc_gpio_set_direction_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t gpio_num;
|
||||
uint32_t pull_mode;
|
||||
} rpc_gpio_set_pull_mode_t;
|
||||
#endif
|
||||
|
||||
#if H_EXT_COEX_SUPPORT
|
||||
typedef struct {
|
||||
uint32_t cmd;
|
||||
uint32_t set_gpio_wire_type;
|
||||
int32_t set_gpio_request_pin;
|
||||
int32_t set_gpio_priority_pin;
|
||||
int32_t set_gpio_grant_pin;
|
||||
int32_t set_gpio_tx_line_pin;
|
||||
uint32_t set_work_mode;
|
||||
uint32_t set_grant_delay_us;
|
||||
bool set_validate_high;
|
||||
} rpc_ext_coex_t;
|
||||
#endif
|
||||
|
||||
typedef struct Ctrl_cmd_t {
|
||||
/* msg type could be 1. req 2. resp 3. notification */
|
||||
uint8_t msg_type;
|
||||
|
||||
/* control path protobuf msg number */
|
||||
uint16_t msg_id;
|
||||
|
||||
/* uid of request / response */
|
||||
uint32_t uid;
|
||||
|
||||
/* statusof response or notification */
|
||||
int32_t resp_event_status;
|
||||
|
||||
void * rx_sem;
|
||||
|
||||
union {
|
||||
wifi_init_config_t wifi_init_config;
|
||||
wifi_cfg_t wifi_config;
|
||||
rpc_wifi_scan_params_t wifi_scan_params;
|
||||
wifi_mac_t wifi_mac;
|
||||
hosted_mode_t wifi_mode;
|
||||
|
||||
wifi_softap_vendor_ie_t wifi_softap_vendor_ie;
|
||||
//wifi_softap_conn_sta_list_t wifi_softap_con_sta;
|
||||
|
||||
wifi_power_save_t wifi_ps;
|
||||
|
||||
ota_write_t ota_write;
|
||||
|
||||
wifi_tx_power_t wifi_tx_power;
|
||||
|
||||
wifi_scan_cfg_t wifi_scan_config;
|
||||
|
||||
wifi_ap_record_t wifi_ap_record;
|
||||
|
||||
wifi_scan_ap_list_t wifi_scan_ap_list;
|
||||
|
||||
wifi_deauth_sta_t wifi_deauth_sta;
|
||||
|
||||
wifi_storage_t wifi_storage;
|
||||
|
||||
rpc_wifi_bandwidth_t wifi_bandwidth;
|
||||
|
||||
rpc_wifi_channel_t wifi_channel;
|
||||
|
||||
rpc_wifi_country_code wifi_country_code;
|
||||
|
||||
wifi_country_t wifi_country;
|
||||
|
||||
wifi_sta_list_t wifi_ap_sta_list;
|
||||
|
||||
rpc_wifi_ap_get_sta_aid_t wifi_ap_get_sta_aid;
|
||||
|
||||
rpc_wifi_sta_get_rssi_t wifi_sta_get_rssi;
|
||||
|
||||
rpc_wifi_protocol wifi_protocol;
|
||||
|
||||
rpc_wifi_sta_get_negotiated_phymode_t wifi_sta_get_negotiated_phymode;
|
||||
rpc_wifi_sta_get_aid_t wifi_sta_get_aid;
|
||||
|
||||
rpc_wifi_inactive_time_t wifi_inactive_time;
|
||||
|
||||
rpc_wifi_disable_pmf_config_t wifi_disable_pmf_config;
|
||||
|
||||
rpc_coprocessor_fwversion_t coprocessor_fwversion;
|
||||
|
||||
rpc_iface_mac_t iface_mac;
|
||||
|
||||
rpc_iface_mac_len_t iface_mac_len;
|
||||
|
||||
bool bt_mem_release;
|
||||
|
||||
rcp_feature_control_t feature_control;
|
||||
|
||||
#if H_MEM_MONITOR
|
||||
esp_hosted_config_mem_monitor_t config_mem_monitor;
|
||||
|
||||
esp_hosted_curr_mem_info_t curr_mem_info;
|
||||
#endif
|
||||
|
||||
#ifdef H_PEER_DATA_TRANSFER
|
||||
esp_hosted_rpc_data_t custom_rpc;
|
||||
#endif
|
||||
|
||||
esp_hosted_app_desc_t app_desc;
|
||||
#if H_WIFI_HE_SUPPORT
|
||||
wifi_twt_config_t wifi_twt_config;
|
||||
|
||||
#if H_WIFI_HE_GREATER_THAN_ESP_IDF_5_3
|
||||
wifi_itwt_setup_config_t wifi_itwt_setup_config;
|
||||
#else
|
||||
wifi_twt_setup_config_t wifi_twt_setup_config;
|
||||
#endif
|
||||
|
||||
int wifi_itwt_flow_id;
|
||||
|
||||
rpc_wifi_itwt_suspend_t wifi_itwt_suspend;
|
||||
|
||||
int wifi_itwt_flow_id_bitmap;
|
||||
|
||||
int wifi_itwt_probe_req_timeout_ms;
|
||||
|
||||
int wifi_itwt_set_target_wake_time_offset_us;
|
||||
#endif
|
||||
|
||||
#if H_WIFI_DUALBAND_SUPPORT
|
||||
rpc_wifi_protocols_t wifi_protocols;
|
||||
|
||||
rpc_wifi_bandwidths_t wifi_bandwidths;
|
||||
|
||||
wifi_band_t wifi_band;
|
||||
|
||||
wifi_band_mode_t wifi_band_mode;
|
||||
#endif
|
||||
|
||||
rpc_set_dhcp_dns_status_t slave_dhcp_dns_status;
|
||||
|
||||
#if H_DPP_SUPPORT
|
||||
bool dpp_enable_cb;
|
||||
|
||||
rpc_supp_dpp_bootstrap_gen_t dpp_bootstrap_gen;
|
||||
#endif
|
||||
|
||||
event_init_t e_init;
|
||||
|
||||
event_heartbeat_t e_heartbeat;
|
||||
|
||||
event_wifi_simple_t e_wifi_simple;
|
||||
|
||||
esp_hosted_event_mem_info_t e_mem_info;
|
||||
|
||||
wifi_event_ap_staconnected_t e_wifi_ap_staconnected;
|
||||
|
||||
wifi_event_ap_stadisconnected_t e_wifi_ap_stadisconnected;
|
||||
|
||||
wifi_event_sta_scan_done_t e_wifi_sta_scan_done;
|
||||
|
||||
wifi_event_sta_connected_t e_wifi_sta_connected;
|
||||
|
||||
wifi_event_sta_disconnected_t e_wifi_sta_disconnected;
|
||||
|
||||
#if H_WIFI_HE_SUPPORT
|
||||
wifi_event_sta_itwt_setup_t e_wifi_sta_itwt_setup;
|
||||
|
||||
wifi_event_sta_itwt_teardown_t e_wifi_sta_itwt_teardown;
|
||||
|
||||
wifi_event_sta_itwt_suspend_t e_wifi_sta_itwt_suspend;
|
||||
|
||||
wifi_event_sta_itwt_probe_t e_wifi_sta_itwt_probe;
|
||||
#endif
|
||||
#if H_WIFI_ENTERPRISE_SUPPORT
|
||||
rpc_eap_identity_t eap_identity;
|
||||
|
||||
rpc_eap_username_t eap_username;
|
||||
|
||||
rpc_eap_password_t eap_password;
|
||||
|
||||
rpc_eap_ca_cert_t eap_ca_cert;
|
||||
|
||||
rpc_eap_cert_key_t eap_cert_key;
|
||||
|
||||
rpc_eap_disable_time_check_t eap_disable_time_check;
|
||||
|
||||
esp_eap_ttls_phase2_types eap_ttls_phase2;
|
||||
|
||||
rpc_eap_suiteb_192bit_t eap_suiteb_192bit;
|
||||
|
||||
rpc_eap_pac_file_t eap_pac_file;
|
||||
|
||||
esp_eap_fast_config eap_fast_config;
|
||||
|
||||
rpc_eap_default_cert_bundle_t eap_default_cert_bundle;
|
||||
|
||||
rpc_wifi_okc_support_t wifi_okc_support;
|
||||
|
||||
rpc_eap_domain_name_t eap_domain_name;
|
||||
|
||||
#if H_GOT_SET_EAP_METHODS_API
|
||||
esp_eap_method_t methods;
|
||||
#endif
|
||||
#endif
|
||||
#if H_DPP_SUPPORT
|
||||
supp_wifi_event_dpp_uri_ready_t e_dpp_uri_ready;
|
||||
|
||||
supp_wifi_event_dpp_config_received_t e_dpp_config_received;
|
||||
|
||||
supp_wifi_event_dpp_failed_t e_dpp_failed;
|
||||
#endif
|
||||
|
||||
#if H_GPIO_EXPANDER_SUPPORT
|
||||
rpc_gpio_config_t gpio_config;
|
||||
|
||||
uint32_t gpio_num;
|
||||
|
||||
rpc_gpio_set_level_t gpio_set_level;
|
||||
|
||||
int gpio_get_level;
|
||||
|
||||
rpc_gpio_set_direction_t gpio_set_direction;
|
||||
|
||||
rpc_gpio_set_pull_mode_t gpio_set_pull_mode;
|
||||
#endif
|
||||
#if H_EXT_COEX_SUPPORT
|
||||
rpc_ext_coex_t ext_coex;
|
||||
#endif
|
||||
}u;
|
||||
|
||||
/* By default this callback is set to NULL.
|
||||
* When this callback is set by app while triggering request,
|
||||
* it will be automatically called asynchronously
|
||||
* by hosted control lib on receiving control response
|
||||
* in this case app will not be waiting for response.
|
||||
*
|
||||
* Whereas, when this is not set i.e. is NULL, it is understood
|
||||
* as synchronous response, and app after sending request,
|
||||
* will wait till getting a response
|
||||
*/
|
||||
int (*rpc_rsp_cb)(struct Ctrl_cmd_t *data);
|
||||
|
||||
/* Wait for timeout duration, if response not received,
|
||||
* it will send timeout response.
|
||||
* Default value for this time out is DEFAULT_RPC_RESP_TIMEOUT */
|
||||
int rsp_timeout_sec;
|
||||
|
||||
/* rpc takes only one request at a time.
|
||||
* If new request comes before previous command execution,
|
||||
* wait for previous command execution for these many seconds, else return failure.
|
||||
* Default: WAIT_TIME_B2B_RPC_REQ */
|
||||
int wait_prev_cmd_completion;
|
||||
|
||||
/* assign the data pointer to free by lower layer.
|
||||
* Ignored if assigned as NULL */
|
||||
void *app_free_buff_hdl;
|
||||
|
||||
/* free handle to be registered
|
||||
* Ignored if assigned as NULL */
|
||||
void (*app_free_buff_func)(void *app_free_buff_hdl);
|
||||
|
||||
void *rpc_free_buff_hdls[MAX_FREE_BUFF_HANDLES];
|
||||
uint8_t n_rpc_free_buff_hdls;
|
||||
} ctrl_cmd_t;
|
||||
|
||||
|
||||
/* resp callback */
|
||||
typedef int (*rpc_rsp_cb_t) (ctrl_cmd_t * resp);
|
||||
|
||||
/* event callback */
|
||||
typedef int (*rpc_evt_cb_t) (ctrl_cmd_t * event);
|
||||
|
||||
|
||||
/*---- Control API Function ----*/
|
||||
|
||||
|
||||
/* This file contains hosted control library exposed APIs.
|
||||
* For detailed documentation, Please refer `../../../docs/common/ctrl_apis.md`
|
||||
*
|
||||
* As important note, application using these APIs, should clean
|
||||
* 1. allocated buffer within library are saved in `app_resp->app_free_buff_hdl`
|
||||
* Please use `app_resp->app_free_buff_func` for freeing them.
|
||||
* 2. Response `ctrl_cmd_t *app_resp` is also allocated from library,
|
||||
* need to free using g_h.funcs->_h_free() function.
|
||||
**/
|
||||
|
||||
/* Set control event callback
|
||||
*
|
||||
* when user sets event callback, user provided function pointer
|
||||
* will be registered with user function
|
||||
* If user does not register event callback,
|
||||
* events received from ESP32 will be dropped
|
||||
*
|
||||
* Inputs:
|
||||
* > event - Control Event ID
|
||||
* > event_cb - NULL - resets event callback
|
||||
* Function pointer - Registers event callback
|
||||
* Returns:
|
||||
* > MSG_ID_OUT_OF_ORDER - If event is not registered with hosted control lib
|
||||
* > CALLBACK_SET_SUCCESS - Callback is set successful
|
||||
**/
|
||||
int set_event_callback(int event, rpc_rsp_cb_t event_cb);
|
||||
|
||||
/* Reset control event callback
|
||||
*
|
||||
* when user sets event callback, user provided function pointer
|
||||
* will be registered with user function
|
||||
* If user does not register event callback,
|
||||
* events received from ESP32 will be dropped
|
||||
*
|
||||
* Inputs:
|
||||
* > event - Control Event ID
|
||||
*
|
||||
* Returns:
|
||||
* > MSG_ID_OUT_OF_ORDER - If event is not registered with hosted control lib
|
||||
* > CALLBACK_SET_SUCCESS - Callback is set successful
|
||||
**/
|
||||
int reset_event_callback(int event);
|
||||
|
||||
|
||||
/* Initialize hosted control library
|
||||
*
|
||||
* This is first step for application while using control path
|
||||
* This will allocate and instantiate hosted control library
|
||||
*
|
||||
* Returns:
|
||||
* > SUCCESS - 0
|
||||
* > FAILURE - -1
|
||||
**/
|
||||
int rpc_slaveif_init(void);
|
||||
|
||||
/* De-initialize hosted control library
|
||||
*
|
||||
* This is last step for application while using control path
|
||||
* This will deallocate and cleanup hosted control library
|
||||
*
|
||||
* Returns:
|
||||
* > SUCCESS - 0
|
||||
* > FAILURE - -1
|
||||
**/
|
||||
int rpc_slaveif_deinit(void);
|
||||
|
||||
int rpc_slaveif_start(void);
|
||||
|
||||
int rpc_slaveif_stop(void);
|
||||
|
||||
/* Get the MAC address of station or softAP interface of ESP32 */
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_mac(ctrl_cmd_t *req);
|
||||
|
||||
/* Set MAC address of ESP32 interface for given wifi mode */
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_mac(ctrl_cmd_t *req);
|
||||
|
||||
/* Get Wi-Fi mode of ESP32 */
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_mode(ctrl_cmd_t *req);
|
||||
|
||||
/* Set the Wi-Fi mode of ESP32 */
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_mode(ctrl_cmd_t *req);
|
||||
|
||||
/* Sets maximum WiFi transmitting power at ESP32 */
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_max_tx_power(ctrl_cmd_t *req);
|
||||
|
||||
/* Gets maximum WiFi transmitting power at ESP32 */
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_max_tx_power(ctrl_cmd_t *req);
|
||||
|
||||
/* Configure heartbeat event. Be default heartbeat is not enabled.
|
||||
* To enable heartbeats, user need to use this API in addition
|
||||
* to setting event callback for heartbeat event */
|
||||
ctrl_cmd_t * rpc_slaveif_config_heartbeat(ctrl_cmd_t *req);
|
||||
|
||||
/* Performs an OTA begin operation for ESP32 which erases and
|
||||
* prepares existing flash partition for new flash writing */
|
||||
ctrl_cmd_t * rpc_slaveif_ota_begin(ctrl_cmd_t *req);
|
||||
|
||||
/* Performs an OTA write operation for ESP32, It writes bytes from `ota_data`
|
||||
* buffer with `ota_data_len` number of bytes to OTA partition in flash. Number
|
||||
* of bytes can be small than size of complete binary to be flashed. In that
|
||||
* case, this caller is expected to repeatedly call this function till
|
||||
* total size written equals size of complete binary */
|
||||
ctrl_cmd_t * rpc_slaveif_ota_write(ctrl_cmd_t *req);
|
||||
|
||||
/* Performs an OTA end operation for ESP32, It validates written OTA image,
|
||||
* sets newly written OTA partition as boot partition for next boot,
|
||||
* Creates timer which reset ESP32 after 5 sec */
|
||||
ctrl_cmd_t * rpc_slaveif_ota_end(ctrl_cmd_t *req);
|
||||
|
||||
/* Performs an OTA activate operation for ESP32, It reboots the ESP32
|
||||
* to activate the newly written OTA partition */
|
||||
ctrl_cmd_t * rpc_slaveif_ota_activate(ctrl_cmd_t *req);
|
||||
|
||||
/* Gets the co-processor FW Version */
|
||||
ctrl_cmd_t * rpc_slaveif_get_coprocessor_fwversion(ctrl_cmd_t *req);
|
||||
|
||||
/* TODO: add descriptions */
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_init(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_deinit(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_start(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_stop(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_connect(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_disconnect(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_config(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_config(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_scan_params(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_scan_start(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_scan_stop(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_scan_get_ap_num(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_scan_get_ap_record(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_scan_get_ap_records(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_clear_ap_list(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_restore(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_clear_fast_connect(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_deauth_sta(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_sta_get_ap_info(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_ps(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_ps(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_storage(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_bandwidth(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_bandwidth(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_channel(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_channel(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_country_code(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_country_code(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_country(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_country(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_ap_get_sta_list(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_ap_get_sta_aid(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_sta_get_rssi(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_protocol(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_protocol(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_sta_get_negotiated_phymode(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_sta_get_aid(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_protocols(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_protocols(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_bandwidths(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_bandwidths(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_band(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_band(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_band_mode(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_band_mode(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_set_slave_dhcp_dns_status(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_iface_mac_addr_set_get(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_feature_control(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_get_coprocessor_app_desc(ctrl_cmd_t *req);
|
||||
|
||||
#if H_MEM_MONITOR
|
||||
ctrl_cmd_t * rpc_slave_iface_set_mem_monitor(ctrl_cmd_t *req);
|
||||
#endif
|
||||
|
||||
ctrl_cmd_t * rpc_slaveif_iface_mac_addr_set_get(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slave_feature_command(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_iface_mac_addr_len_get(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_inactive_time(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_get_inactive_time(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_disable_pmf_config(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_sta_twt_config(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_sta_itwt_setup(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_sta_itwt_teardown(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_sta_itwt_suspend(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_sta_itwt_get_flow_id_status(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_sta_itwt_send_probe_req(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_sta_itwt_set_target_wake_time_offset(ctrl_cmd_t *req);
|
||||
|
||||
#if H_WIFI_ENTERPRISE_SUPPORT
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_sta_enterprise_enable(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_sta_enterprise_disable(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_eap_set_identity(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_eap_clear_identity(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_eap_set_username(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_eap_clear_username(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_eap_set_password(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_eap_clear_password(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_eap_set_new_password(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_eap_clear_new_password(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_eap_set_ca_cert(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_eap_clear_ca_cert(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_eap_set_certificate_and_key(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_eap_clear_certificate_and_key(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_eap_set_disable_time_check(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_eap_get_disable_time_check(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_eap_set_ttls_phase2_method(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_eap_set_suiteb_certification(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_eap_set_pac_file(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_eap_set_fast_params(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_eap_use_default_cert_bundle(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_wifi_set_okc_support(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_eap_set_domain_name(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_eap_set_eap_methods(ctrl_cmd_t *req);
|
||||
#endif
|
||||
#if H_DPP_SUPPORT
|
||||
ctrl_cmd_t * rpc_slaveif_supp_dpp_init(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_supp_dpp_deinit(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_supp_dpp_bootstrap_gen(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_supp_dpp_start_listen(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_supp_dpp_stop_listen(ctrl_cmd_t *req);
|
||||
#endif
|
||||
|
||||
#ifdef H_PEER_DATA_TRANSFER
|
||||
ctrl_cmd_t * rpc_slaveif_custom_rpc(ctrl_cmd_t *req);
|
||||
int rpc_slaveif_register_custom_callback(uint32_t msg_id_exp,
|
||||
void (*callback)(uint32_t msg_id_recvd, const uint8_t *data_recvd, size_t data_len_recvd, void *local_context),
|
||||
void *local_context);
|
||||
#endif
|
||||
|
||||
#if H_GPIO_EXPANDER_SUPPORT
|
||||
ctrl_cmd_t * rpc_slaveif_gpio_config(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_gpio_reset_pin(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_gpio_set_level(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_gpio_get_level(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_gpio_set_direction(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_gpio_input_enable(ctrl_cmd_t *req);
|
||||
ctrl_cmd_t * rpc_slaveif_gpio_set_pull_mode(ctrl_cmd_t *req);
|
||||
#endif
|
||||
#if H_EXT_COEX_SUPPORT
|
||||
ctrl_cmd_t * rpc_slaveif_ext_coex(ctrl_cmd_t *req);
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/** prevent recursive inclusion **/
|
||||
#ifndef __RPC_WRAP_H__
|
||||
#define __RPC_WRAP_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Includes **/
|
||||
#include "esp_wifi.h"
|
||||
#include "port_esp_hosted_host_wifi_config.h"
|
||||
#include "port_esp_hosted_host_config.h"
|
||||
#include "port_esp_hosted_host_openthread.h"
|
||||
#include "esp_mac.h"
|
||||
#include "esp_hosted_api_types.h"
|
||||
#include "esp_hosted_misc.h"
|
||||
#include "esp_hosted_misc_types.h"
|
||||
|
||||
#if H_WIFI_ENTERPRISE_SUPPORT
|
||||
#include "esp_eap_client.h"
|
||||
#endif
|
||||
#if H_DPP_SUPPORT
|
||||
#include "esp_dpp.h"
|
||||
#endif
|
||||
#if H_GPIO_EXPANDER_SUPPORT
|
||||
#include "esp_hosted_cp_gpio.h"
|
||||
#endif
|
||||
#if H_EXT_COEX_SUPPORT
|
||||
#include "esp_hosted_cp_ext_coex.h"
|
||||
#endif
|
||||
#if H_HOST_OT_ENABLE
|
||||
#include "esp_hosted_openthread.h"
|
||||
#endif
|
||||
/** Exported variables **/
|
||||
|
||||
/** Inline functions **/
|
||||
|
||||
/** Exported Functions **/
|
||||
esp_err_t rpc_init(void);
|
||||
esp_err_t rpc_start(void);
|
||||
esp_err_t rpc_stop(void);
|
||||
esp_err_t rpc_deinit(void);
|
||||
esp_err_t rpc_unregister_event_callbacks(void);
|
||||
esp_err_t rpc_register_event_callbacks(void);
|
||||
|
||||
esp_err_t rpc_wifi_init(const wifi_init_config_t *arg);
|
||||
esp_err_t rpc_wifi_deinit(void);
|
||||
esp_err_t rpc_wifi_set_mode(wifi_mode_t mode);
|
||||
esp_err_t rpc_wifi_get_mode(wifi_mode_t* mode);
|
||||
esp_err_t rpc_wifi_start(void);
|
||||
esp_err_t rpc_wifi_stop(void);
|
||||
esp_err_t rpc_wifi_connect(void);
|
||||
esp_err_t rpc_wifi_disconnect(void);
|
||||
esp_err_t rpc_wifi_set_config(wifi_interface_t interface, wifi_config_t *conf);
|
||||
esp_err_t rpc_wifi_get_config(wifi_interface_t interface, wifi_config_t *conf);
|
||||
esp_err_t rpc_wifi_get_mac(wifi_interface_t mode, uint8_t mac[6]);
|
||||
esp_err_t rpc_wifi_set_mac(wifi_interface_t mode, const uint8_t mac[6]);
|
||||
esp_err_t rpc_wifi_set_scan_parameters(const wifi_scan_default_params_t *config);
|
||||
esp_err_t rpc_wifi_get_scan_parameters(wifi_scan_default_params_t *config);
|
||||
|
||||
esp_err_t rpc_wifi_scan_start(const wifi_scan_config_t *config, bool block);
|
||||
esp_err_t rpc_wifi_scan_stop(void);
|
||||
esp_err_t rpc_wifi_scan_get_ap_num(uint16_t *number);
|
||||
esp_err_t rpc_wifi_scan_get_ap_record(wifi_ap_record_t *ap_record);
|
||||
esp_err_t rpc_wifi_scan_get_ap_records(uint16_t *number, wifi_ap_record_t *ap_records);
|
||||
esp_err_t rpc_wifi_clear_ap_list(void);
|
||||
esp_err_t rpc_wifi_restore(void);
|
||||
esp_err_t rpc_wifi_clear_fast_connect(void);
|
||||
esp_err_t rpc_wifi_deauth_sta(uint16_t aid);
|
||||
esp_err_t rpc_wifi_sta_get_ap_info(wifi_ap_record_t *ap_info);
|
||||
esp_err_t rpc_wifi_set_ps(wifi_ps_type_t type);
|
||||
esp_err_t rpc_wifi_get_ps(wifi_ps_type_t *type);
|
||||
esp_err_t rpc_wifi_set_storage(wifi_storage_t storage);
|
||||
esp_err_t rpc_wifi_set_bandwidth(wifi_interface_t ifx, wifi_bandwidth_t bw);
|
||||
esp_err_t rpc_wifi_get_bandwidth(wifi_interface_t ifx, wifi_bandwidth_t *bw);
|
||||
esp_err_t rpc_wifi_set_channel(uint8_t primary, wifi_second_chan_t second);
|
||||
esp_err_t rpc_wifi_get_channel(uint8_t *primary, wifi_second_chan_t *second);
|
||||
esp_err_t rpc_wifi_set_country_code(const char *country, bool ieee80211d_enabled);
|
||||
esp_err_t rpc_wifi_get_country_code(char *country);
|
||||
esp_err_t rpc_wifi_set_country(const wifi_country_t *country);
|
||||
esp_err_t rpc_wifi_get_country(wifi_country_t *country);
|
||||
esp_err_t rpc_wifi_ap_get_sta_list(wifi_sta_list_t *sta);
|
||||
esp_err_t rpc_wifi_ap_get_sta_aid(const uint8_t mac[6], uint16_t *aid);
|
||||
esp_err_t rpc_wifi_sta_get_rssi(int *rssi);
|
||||
esp_err_t rpc_wifi_set_protocol(wifi_interface_t ifx, uint8_t protocol_bitmap);
|
||||
esp_err_t rpc_wifi_get_protocol(wifi_interface_t ifx, uint8_t *protocol_bitmap);
|
||||
esp_err_t rpc_wifi_set_max_tx_power(int8_t power);
|
||||
esp_err_t rpc_wifi_get_max_tx_power(int8_t *power);
|
||||
esp_err_t rpc_wifi_sta_get_negotiated_phymode(wifi_phy_mode_t *phymode);
|
||||
esp_err_t rpc_wifi_sta_get_aid(uint16_t *aid);
|
||||
esp_err_t rpc_wifi_set_inactive_time(wifi_interface_t ifx, uint16_t sec);
|
||||
esp_err_t rpc_wifi_get_inactive_time(wifi_interface_t ifx, uint16_t *sec);
|
||||
esp_err_t rpc_wifi_disable_pmf_config(wifi_interface_t ifx);
|
||||
esp_err_t rpc_get_coprocessor_fwversion(esp_hosted_coprocessor_fwver_t *ver_info);
|
||||
esp_err_t rpc_get_cp_info(uint32_t *cp_chip_id, char *cp_target_name, size_t cp_target_name_len);
|
||||
|
||||
esp_err_t rpc_bt_controller_init(void);
|
||||
esp_err_t rpc_bt_controller_deinit(bool mem_release);
|
||||
esp_err_t rpc_bt_controller_enable(void);
|
||||
esp_err_t rpc_bt_controller_disable(void);
|
||||
|
||||
esp_err_t rpc_iface_mac_addr_set_get(bool set, uint8_t *mac, size_t mac_len, esp_mac_type_t type);
|
||||
esp_err_t rpc_iface_mac_addr_len_get(size_t *len, esp_mac_type_t type);
|
||||
|
||||
esp_err_t rpc_iface_get_coprocessor_app_desc(esp_hosted_app_desc_t *app_desc);
|
||||
esp_err_t rpc_iface_configure_heartbeat(bool enable, int duration_sec);
|
||||
|
||||
#if H_MEM_MONITOR
|
||||
esp_err_t rpc_iface_set_mem_monitor(esp_hosted_config_mem_monitor_t *config, esp_hosted_curr_mem_info_t *curr_mem_info);
|
||||
#endif
|
||||
|
||||
#if H_HOST_OT_ENABLE
|
||||
esp_err_t rpc_iface_openthread_rcp_init(void);
|
||||
esp_err_t rpc_iface_openthread_rcp_deinit(void);
|
||||
esp_err_t rpc_iface_openthread_rcp_start(void);
|
||||
esp_err_t rpc_iface_openthread_rcp_stop(void);
|
||||
esp_err_t rpc_iface_openthread_rcp_query(esp_hosted_openthread_query_t query);
|
||||
#endif
|
||||
|
||||
esp_err_t rpc_ota_begin(void);
|
||||
esp_err_t rpc_ota_write(uint8_t* ota_data, uint32_t ota_data_len);
|
||||
esp_err_t rpc_ota_end(void);
|
||||
esp_err_t rpc_ota_activate(void);
|
||||
|
||||
#if H_WIFI_HE_SUPPORT
|
||||
esp_err_t rpc_wifi_sta_twt_config(wifi_twt_config_t *config);
|
||||
#if H_WIFI_HE_GREATER_THAN_ESP_IDF_5_3
|
||||
esp_err_t rpc_wifi_sta_itwt_setup(wifi_itwt_setup_config_t *setup_config);
|
||||
#else
|
||||
esp_err_t rpc_wifi_sta_itwt_setup(wifi_twt_setup_config_t *setup_config);
|
||||
#endif
|
||||
esp_err_t rpc_wifi_sta_itwt_teardown(int flow_id);
|
||||
esp_err_t rpc_wifi_sta_itwt_suspend(int flow_id, int suspend_time_ms);
|
||||
esp_err_t rpc_wifi_sta_itwt_get_flow_id_status(int *flow_id_bitmap);
|
||||
esp_err_t rpc_wifi_sta_itwt_send_probe_req(int timeout_ms);
|
||||
esp_err_t rpc_wifi_sta_itwt_set_target_wake_time_offset(int offset_us);
|
||||
#endif
|
||||
|
||||
#if H_WIFI_DUALBAND_SUPPORT
|
||||
esp_err_t rpc_wifi_set_band(wifi_band_t band);
|
||||
esp_err_t rpc_wifi_get_band(wifi_band_t *band);
|
||||
esp_err_t rpc_wifi_set_band_mode(wifi_band_mode_t band_mode);
|
||||
esp_err_t rpc_wifi_get_band_mode(wifi_band_mode_t *band_mode);
|
||||
esp_err_t rpc_wifi_set_protocols(wifi_interface_t ifx, wifi_protocols_t *protocols);
|
||||
esp_err_t rpc_wifi_get_protocols(wifi_interface_t ifx, wifi_protocols_t *protocols);
|
||||
esp_err_t rpc_wifi_set_bandwidths(wifi_interface_t ifx, wifi_bandwidths_t *bw);
|
||||
esp_err_t rpc_wifi_get_bandwidths(wifi_interface_t ifx, wifi_bandwidths_t *bw);
|
||||
#endif
|
||||
|
||||
esp_err_t rpc_set_dhcp_dns_status(wifi_interface_t interface, uint8_t link_up,
|
||||
uint8_t dhcp_up, char *dhcp_ip, char *dhcp_nm, char *dhcp_gw,
|
||||
uint8_t dns_up, char *dns_ip, uint8_t dns_type);
|
||||
|
||||
#if H_WIFI_ENTERPRISE_SUPPORT
|
||||
esp_err_t rpc_wifi_sta_enterprise_enable(void);
|
||||
esp_err_t rpc_wifi_sta_enterprise_disable(void);
|
||||
esp_err_t rpc_eap_client_set_identity(const unsigned char *identity, int len);
|
||||
esp_err_t rpc_eap_client_clear_identity(void);
|
||||
esp_err_t rpc_eap_client_set_username(const unsigned char *username, int len);
|
||||
esp_err_t rpc_eap_client_clear_username(void);
|
||||
esp_err_t rpc_eap_client_set_password(const unsigned char *password, int len);
|
||||
esp_err_t rpc_eap_client_clear_password(void);
|
||||
esp_err_t rpc_eap_client_set_new_password(const unsigned char *new_password, int len);
|
||||
esp_err_t rpc_eap_client_clear_new_password(void);
|
||||
esp_err_t rpc_eap_client_set_ca_cert(const unsigned char *ca_cert, int ca_cert_len);
|
||||
esp_err_t rpc_eap_client_clear_ca_cert(void);
|
||||
|
||||
esp_err_t rpc_eap_client_set_certificate_and_key(const unsigned char *client_cert, int client_cert_len,
|
||||
const unsigned char *private_key, int private_key_len,
|
||||
const unsigned char *private_key_password, int private_key_passwd_len);
|
||||
esp_err_t rpc_eap_client_clear_certificate_and_key(void);
|
||||
esp_err_t rpc_eap_client_set_disable_time_check(bool disable);
|
||||
esp_err_t rpc_eap_client_get_disable_time_check(bool *disable);
|
||||
esp_err_t rpc_eap_client_set_ttls_phase2_method(esp_eap_ttls_phase2_types type);
|
||||
esp_err_t rpc_eap_client_set_suiteb_192bit_certification(bool enable);
|
||||
esp_err_t rpc_eap_client_set_pac_file(const unsigned char *pac_file, int pac_file_len);
|
||||
esp_err_t rpc_eap_client_set_fast_params(esp_eap_fast_config config);
|
||||
esp_err_t rpc_eap_client_use_default_cert_bundle(bool use_default_bundle);
|
||||
esp_err_t rpc_wifi_set_okc_support(bool enable);
|
||||
esp_err_t rpc_eap_client_set_domain_name(const char *domain_name);
|
||||
#if H_GOT_SET_EAP_METHODS_API
|
||||
esp_err_t rpc_eap_client_set_eap_methods(esp_eap_method_t methods);
|
||||
#endif
|
||||
#endif
|
||||
#if H_DPP_SUPPORT
|
||||
#if H_SUPP_DPP_SUPPORT
|
||||
esp_err_t rpc_supp_dpp_init(esp_supp_dpp_event_cb_t evt_cb);
|
||||
#else
|
||||
esp_err_t rpc_supp_dpp_init(void);
|
||||
#endif
|
||||
esp_err_t rpc_supp_dpp_deinit(void);
|
||||
esp_err_t rpc_supp_dpp_bootstrap_gen(const char *chan_list,
|
||||
esp_supp_dpp_bootstrap_t type,
|
||||
const char *key, const char *info);
|
||||
esp_err_t rpc_supp_dpp_start_listen(void);
|
||||
esp_err_t rpc_supp_dpp_stop_listen(void);
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "serial_if.h"
|
||||
#include "serial_ll_if.h"
|
||||
#include "esp_hosted_log.h"
|
||||
#include "port_esp_hosted_host_log.h"
|
||||
|
||||
DEFINE_LOG_TAG(serial);
|
||||
|
||||
struct serial_drv_handle_t {
|
||||
int handle; /* dummy variable */
|
||||
};
|
||||
|
||||
static serial_ll_handle_t * serial_ll_if_g;
|
||||
static void * readSemaphore;
|
||||
|
||||
|
||||
static void rpc_rx_indication(void);
|
||||
|
||||
/* Global serial handle - shared by RPC RX and TX threads */
|
||||
static struct serial_drv_handle_t* g_serial_drv_handle = NULL;
|
||||
|
||||
/* -------- Serial Drv ---------- */
|
||||
struct serial_drv_handle_t* serial_drv_open(const char *transport)
|
||||
{
|
||||
if (!transport) {
|
||||
ESP_LOGE(TAG, "Invalid parameter in open");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Return existing handle if already opened */
|
||||
if(g_serial_drv_handle) {
|
||||
ESP_LOGD(TAG, "Serial already open, returning existing handle");
|
||||
return g_serial_drv_handle;
|
||||
}
|
||||
|
||||
/* Allocate new handle */
|
||||
g_serial_drv_handle = (struct serial_drv_handle_t*) g_h.funcs->_h_calloc
|
||||
(1,sizeof(struct serial_drv_handle_t));
|
||||
if (!g_serial_drv_handle) {
|
||||
ESP_LOGE(TAG, "Failed to allocate memory \n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Serial handle allocated");
|
||||
return g_serial_drv_handle;
|
||||
}
|
||||
|
||||
int serial_drv_write (struct serial_drv_handle_t* serial_drv_handle,
|
||||
uint8_t* buf, int in_count, int* out_count)
|
||||
{
|
||||
int ret = 0;
|
||||
if (!serial_drv_handle || !buf || !in_count || !out_count) {
|
||||
ESP_LOGE(TAG,"Invalid parameters in write\n\r");
|
||||
return RET_INVALID;
|
||||
}
|
||||
|
||||
if( (!serial_ll_if_g) ||
|
||||
(!serial_ll_if_g->fops) ||
|
||||
(!serial_ll_if_g->fops->write)) {
|
||||
ESP_LOGE(TAG,"serial interface not valid\n\r");
|
||||
return RET_INVALID;
|
||||
}
|
||||
|
||||
ESP_HEXLOGV("serial_write", buf, in_count, 32);
|
||||
ret = serial_ll_if_g->fops->write(serial_ll_if_g, buf, in_count);
|
||||
if (ret != RET_OK) {
|
||||
*out_count = 0;
|
||||
ESP_LOGE(TAG,"Failed to write data\n\r");
|
||||
return RET_FAIL;
|
||||
}
|
||||
|
||||
*out_count = in_count;
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
|
||||
uint8_t * serial_drv_read(struct serial_drv_handle_t *serial_drv_handle,
|
||||
uint32_t *out_nbyte)
|
||||
{
|
||||
uint16_t init_read_len = 0;
|
||||
uint16_t rx_buf_len = 0;
|
||||
uint8_t* read_buf = NULL;
|
||||
int ret = 0;
|
||||
/* Any of `RPC_EP_NAME_EVT` and `RPC_EP_NAME_RSP` could be used,
|
||||
* as both have same strlen in esp_hosted_transport.h */
|
||||
const char* ep_name = RPC_EP_NAME_RSP;
|
||||
uint8_t *buf = NULL;
|
||||
uint32_t buf_len = 0;
|
||||
|
||||
|
||||
if (!serial_drv_handle || !out_nbyte) {
|
||||
ESP_LOGE(TAG,"Invalid parameters in read\n\r");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*out_nbyte = 0;
|
||||
|
||||
if(!readSemaphore) {
|
||||
ESP_LOGE(TAG,"Semaphore not initialized\n\r");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "Wait for serial_ll_semaphore");
|
||||
g_h.funcs->_h_get_semaphore(readSemaphore, HOSTED_BLOCK_MAX);
|
||||
|
||||
if( (!serial_ll_if_g) ||
|
||||
(!serial_ll_if_g->fops) ||
|
||||
(!serial_ll_if_g->fops->read)) {
|
||||
ESP_LOGE(TAG,"serial interface refusing to read\n\r");
|
||||
return NULL;
|
||||
}
|
||||
ESP_LOGV(TAG, "Starting serial_ll read");
|
||||
|
||||
/* Get buffer from serial interface */
|
||||
read_buf = serial_ll_if_g->fops->read(serial_ll_if_g, &rx_buf_len);
|
||||
if ((!read_buf) || (!rx_buf_len)) {
|
||||
ESP_LOGE(TAG,"serial read failed\n\r");
|
||||
return NULL;
|
||||
}
|
||||
ESP_HEXLOGV("serial_read", read_buf, rx_buf_len, 32);
|
||||
|
||||
/*
|
||||
* Read Operation happens in two steps because total read length is unknown
|
||||
* at first read.
|
||||
* 1) Read fixed length of RX data
|
||||
* 2) Read variable length of RX data
|
||||
*
|
||||
* (1) Read fixed length of RX data :
|
||||
* Read fixed length of received data in below format:
|
||||
* ----------------------------------------------------------------------------
|
||||
* Endpoint Type | Endpoint Length | Endpoint Value | Data Type | Data Length
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Bytes used per field as follows:
|
||||
* ---------------------------------------------------------------------------
|
||||
* 1 | 2 | Endpoint Length | 1 | 2 |
|
||||
* ---------------------------------------------------------------------------
|
||||
*
|
||||
* int_read_len = 1 + 2 + Endpoint length + 1 + 2
|
||||
*/
|
||||
|
||||
init_read_len = SIZE_OF_TYPE + SIZE_OF_LENGTH + strlen(ep_name) +
|
||||
SIZE_OF_TYPE + SIZE_OF_LENGTH;
|
||||
|
||||
if(rx_buf_len < init_read_len) {
|
||||
HOSTED_FREE(read_buf);
|
||||
ESP_LOGE(TAG,"Incomplete serial buff, return\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HOSTED_CALLOC(uint8_t,buf,init_read_len,free_bufs);
|
||||
|
||||
g_h.funcs->_h_memcpy(buf, read_buf, init_read_len);
|
||||
|
||||
/* parse_tlv function returns variable payload length
|
||||
* of received data in buf_len
|
||||
**/
|
||||
ret = parse_tlv(buf, &buf_len);
|
||||
if (ret || !buf_len) {
|
||||
HOSTED_FREE(buf);
|
||||
ESP_LOGE(TAG,"Failed to parse RX data \n\r");
|
||||
goto free_bufs;
|
||||
}
|
||||
ESP_LOGV(TAG, "TLV parsed");
|
||||
|
||||
if (rx_buf_len < (init_read_len + buf_len)) {
|
||||
ESP_LOGE(TAG,"Buf read on serial iface is smaller than expected len\n");
|
||||
HOSTED_FREE(buf);
|
||||
goto free_bufs;
|
||||
}
|
||||
|
||||
if (rx_buf_len > (init_read_len + buf_len)) {
|
||||
ESP_LOGE(TAG,"Buf read on serial iface is smaller than expected len\n");
|
||||
}
|
||||
|
||||
HOSTED_FREE(buf);
|
||||
/*
|
||||
* (2) Read variable length of RX data:
|
||||
*/
|
||||
HOSTED_CALLOC(uint8_t,buf,buf_len,free_bufs);
|
||||
|
||||
g_h.funcs->_h_memcpy((buf), read_buf+init_read_len, buf_len);
|
||||
|
||||
HOSTED_FREE(read_buf);
|
||||
|
||||
*out_nbyte = buf_len;
|
||||
ESP_LOGV(TAG, "Serial payload size(after removing TLV): %" PRIu32, *out_nbyte);
|
||||
return buf;
|
||||
|
||||
free_bufs:
|
||||
HOSTED_FREE(read_buf);
|
||||
HOSTED_FREE(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int serial_drv_close(struct serial_drv_handle_t** serial_drv_handle)
|
||||
{
|
||||
if (!serial_drv_handle || !(*serial_drv_handle)) {
|
||||
ESP_LOGE(TAG,"Invalid parameter in close \n\r");
|
||||
return RET_INVALID;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Freeing serial handle");
|
||||
HOSTED_FREE(*serial_drv_handle);
|
||||
*serial_drv_handle = NULL;
|
||||
g_serial_drv_handle = NULL; /* Clear global so next open allocates fresh */
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int rpc_platform_init(void)
|
||||
{
|
||||
/* rpc semaphore */
|
||||
readSemaphore = g_h.funcs->_h_create_semaphore(H_MAX_SYNC_RPC_REQUESTS +
|
||||
H_MAX_ASYNC_RPC_REQUESTS);
|
||||
assert(readSemaphore);
|
||||
|
||||
/* grab the semaphore, so that task will be mandated to wait on semaphore */
|
||||
g_h.funcs->_h_get_semaphore(readSemaphore, 0);
|
||||
|
||||
serial_ll_if_g = serial_ll_init(rpc_rx_indication);
|
||||
if (!serial_ll_if_g) {
|
||||
ESP_LOGE(TAG,"Serial interface creation failed\n\r");
|
||||
assert(serial_ll_if_g);
|
||||
return RET_FAIL;
|
||||
}
|
||||
if (RET_OK != serial_ll_if_g->fops->open(serial_ll_if_g)) {
|
||||
ESP_LOGE(TAG,"Serial interface open failed\n\r");
|
||||
return RET_FAIL;
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
/* TODO: Why this is not called in transport_pserial_close() */
|
||||
int rpc_platform_deinit(void)
|
||||
{
|
||||
if (serial_ll_if_g) {
|
||||
if (RET_OK != serial_ll_if_g->fops->close(serial_ll_if_g)) {
|
||||
ESP_LOGE(TAG,"Serial interface close failed\n\r");
|
||||
return RET_FAIL;
|
||||
}
|
||||
/* serial_ll_close frees the handle, NULL our pointer */
|
||||
serial_ll_if_g = NULL;
|
||||
}
|
||||
|
||||
if (readSemaphore) {
|
||||
g_h.funcs->_h_destroy_semaphore(readSemaphore);
|
||||
readSemaphore = NULL;
|
||||
}
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
static void rpc_rx_indication(void)
|
||||
{
|
||||
/* heads up to rpc for read */
|
||||
if(readSemaphore) {
|
||||
g_h.funcs->_h_post_semaphore(readSemaphore);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*prevent recursive inclusion */
|
||||
#ifndef __SERIAL_DRV_H
|
||||
#define __SERIAL_DRV_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** includes **/
|
||||
#include "serial_ll_if.h"
|
||||
|
||||
/** Exported Functions **/
|
||||
/*
|
||||
* rpc_platform_init function initializes the rpc
|
||||
* path data structures
|
||||
* Input parameter
|
||||
* None
|
||||
* Returns
|
||||
* SUCCESS(0) or FAILURE(-1) of above operation
|
||||
*/
|
||||
int rpc_platform_init(void);
|
||||
|
||||
/*
|
||||
* rpc_platform_deinit function cleans up the rpc
|
||||
* path library data structure
|
||||
* Input parameter
|
||||
* None
|
||||
* Returns
|
||||
* SUCCESS(0) or FAILURE(-1) of above operation
|
||||
*/
|
||||
int rpc_platform_deinit(void);
|
||||
|
||||
/*
|
||||
* serial_drv_open function opens driver interface.
|
||||
*
|
||||
* Input parameter
|
||||
* transport : Pointer to transport driver
|
||||
* Returns
|
||||
* serial_drv_handle : Driver Handle
|
||||
*/
|
||||
struct serial_drv_handle_t* serial_drv_open (const char* transport);
|
||||
|
||||
/*
|
||||
* serial_drv_write function writes in_count bytes
|
||||
* from buffer to driver interface
|
||||
*
|
||||
* Input parameter
|
||||
* serial_drv_handle : Driver Handler
|
||||
* buf : Data Buffer (Data written from buf to
|
||||
* driver interface)
|
||||
* in_count : Number of Bytes to be written
|
||||
* Output parameter
|
||||
* out_count : Number of Bytes written
|
||||
*
|
||||
* Returns
|
||||
* SUCCESS(0) or FAILURE(-1) of above operation
|
||||
*/
|
||||
int serial_drv_write (struct serial_drv_handle_t* serial_drv_handle,
|
||||
uint8_t* buf, int in_count, int* out_count);
|
||||
|
||||
/*
|
||||
* serial_drv_read function gets buffer from serial driver
|
||||
* after TLV parsing. output buffer is protobuf encoded
|
||||
*
|
||||
* Input parameter
|
||||
* serial_drv_handle : Driver Handle
|
||||
* Output parameter
|
||||
* out_nbyte : Size of TLV parsed buffer
|
||||
* Returns
|
||||
* buf : Protocol encoded data Buffer
|
||||
* caller will decode the protobuf
|
||||
*/
|
||||
|
||||
uint8_t * serial_drv_read(struct serial_drv_handle_t *serial_drv_handle,
|
||||
uint32_t *out_nbyte);
|
||||
|
||||
/*
|
||||
* serial_drv_close function closes driver interface.
|
||||
*
|
||||
* Input parameter
|
||||
* serial_drv_handle : Driver Handle
|
||||
* Returns
|
||||
* SUCCESS(0) or FAILURE(-1) of above operation
|
||||
*/
|
||||
|
||||
int serial_drv_close (struct serial_drv_handle_t** serial_drv_handle);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,417 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/** Includes **/
|
||||
#include "string.h"
|
||||
#include "serial_ll_if.h"
|
||||
#include "transport_drv.h"
|
||||
#include "esp_hosted_transport.h"
|
||||
#include "esp_hosted_header.h"
|
||||
#include "port_esp_hosted_host_log.h"
|
||||
#include "esp_hosted_log.h"
|
||||
|
||||
DEFINE_LOG_TAG(serial_ll);
|
||||
|
||||
/** Macros / Constants **/
|
||||
#define MAX_SERIAL_INTF 2
|
||||
#define TO_SERIAL_INFT_QUEUE_SIZE 10
|
||||
|
||||
typedef enum {
|
||||
INIT,
|
||||
ACTIVE,
|
||||
DESTROY
|
||||
} serial_ll_state_e;
|
||||
|
||||
static struct rx_data {
|
||||
int len;
|
||||
uint8_t *data;
|
||||
} r;
|
||||
|
||||
/* data structures needed for serial driver */
|
||||
static queue_handle_t to_serial_ll_intf_queue[MAX_SERIAL_INTF];
|
||||
static serial_ll_handle_t * interface_handle_g[MAX_SERIAL_INTF] = {NULL};
|
||||
static uint8_t conn_num = 0;
|
||||
|
||||
/** Function Declarations **/
|
||||
static int serial_ll_open (serial_ll_handle_t *serial_ll_hdl);
|
||||
static uint8_t * serial_ll_read (const serial_ll_handle_t * serial_ll_hdl,
|
||||
uint16_t * rlen);
|
||||
static int serial_ll_write (const serial_ll_handle_t * serial_ll_hdl,
|
||||
uint8_t * wbuffer, const uint16_t wlen);
|
||||
static int serial_ll_close (serial_ll_handle_t * serial_ll_hdl);
|
||||
|
||||
|
||||
/* define serial interface */
|
||||
static struct serial_ll_operations serial_ll_fops = {
|
||||
.open = serial_ll_open,
|
||||
.read = serial_ll_read,
|
||||
.write = serial_ll_write,
|
||||
.close = serial_ll_close,
|
||||
};
|
||||
|
||||
/** function definition **/
|
||||
|
||||
/** Local Functions **/
|
||||
|
||||
/**
|
||||
* @brief Open new Serial interface
|
||||
* @param serial_ll_hdl - handle of serial interface
|
||||
* @retval 0 if success, -1 on failure
|
||||
*/
|
||||
static int serial_ll_open(serial_ll_handle_t *serial_ll_hdl)
|
||||
{
|
||||
if (! serial_ll_hdl) {
|
||||
ESP_LOGE(TAG, "serial invalid hdr");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (serial_ll_hdl->queue) {
|
||||
/* clean up earlier queue */
|
||||
ESP_LOGW(TAG, "Flush existing serial queue");
|
||||
g_h.funcs->_h_destroy_queue(serial_ll_hdl->queue);
|
||||
}
|
||||
|
||||
/* Queue - serial rx */
|
||||
serial_ll_hdl->queue = g_h.funcs->_h_create_queue(TO_SERIAL_INFT_QUEUE_SIZE,
|
||||
sizeof(interface_buffer_handle_t));
|
||||
|
||||
if (! serial_ll_hdl->queue) {
|
||||
serial_ll_close(serial_ll_hdl);
|
||||
return -1;
|
||||
}
|
||||
|
||||
serial_ll_hdl->state = ACTIVE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get serial handle for iface_num
|
||||
* @param iface_num - serial connection number
|
||||
* @retval serial_ll_hdl - output handle of serial interface
|
||||
*/
|
||||
static serial_ll_handle_t * get_serial_ll_handle(const uint8_t iface_num)
|
||||
{
|
||||
if ((iface_num < MAX_SERIAL_INTF) &&
|
||||
(interface_handle_g[iface_num]) &&
|
||||
(interface_handle_g[iface_num]->state == ACTIVE)) {
|
||||
|
||||
return interface_handle_g[iface_num];
|
||||
}
|
||||
ESP_LOGD(TAG, "%s Failed to get interface handle", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Close serial interface
|
||||
* @param serial_ll_hdl - handle
|
||||
* @retval rbuffer - ready buffer read on serial interface
|
||||
*/
|
||||
static int serial_ll_close(serial_ll_handle_t * serial_ll_hdl)
|
||||
{
|
||||
serial_ll_hdl->state = DESTROY;
|
||||
|
||||
if (serial_ll_hdl->queue) {
|
||||
ESP_LOGI(TAG, "Clean-up serial queue");
|
||||
|
||||
interface_buffer_handle_t buf_handle;
|
||||
while (g_h.funcs->_h_dequeue_item(serial_ll_hdl->queue, &buf_handle, 0) == 0) {
|
||||
/* Free buffer using the provided free function */
|
||||
if (buf_handle.priv_buffer_handle && buf_handle.free_buf_handle) {
|
||||
buf_handle.free_buf_handle(buf_handle.priv_buffer_handle);
|
||||
}
|
||||
}
|
||||
|
||||
g_h.funcs->_h_destroy_queue(serial_ll_hdl->queue);
|
||||
serial_ll_hdl->queue = NULL;
|
||||
}
|
||||
|
||||
/* reset connection */
|
||||
if (conn_num > 0) {
|
||||
interface_handle_g[--conn_num] = NULL;
|
||||
}
|
||||
|
||||
if (serial_ll_hdl) {
|
||||
g_h.funcs->_h_free(serial_ll_hdl);
|
||||
serial_ll_hdl = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Serial interface read non blocking
|
||||
* @param serial_ll_hdl - handle
|
||||
* rlen - output param, number of bytes read
|
||||
* @retval rbuffer - ready buffer read on serial interface
|
||||
*/
|
||||
static uint8_t * serial_ll_read(const serial_ll_handle_t * serial_ll_hdl,
|
||||
uint16_t * rlen)
|
||||
{
|
||||
/* This is a non-blocking call */
|
||||
interface_buffer_handle_t buf_handle = {0};
|
||||
|
||||
/* Initial value */
|
||||
*rlen = 0 ;
|
||||
|
||||
/* check if serial interface valid */
|
||||
if ((! serial_ll_hdl) || (serial_ll_hdl->state != ACTIVE)) {
|
||||
ESP_LOGE(TAG, "serial invalid interface");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* This is **blocking** receive.
|
||||
*
|
||||
* Although not needed in normal circumstances,
|
||||
* User can convert it to non blocking using below steps:
|
||||
*
|
||||
* To make it non blocking:
|
||||
* As an another design option, serial_rx_callback can also be
|
||||
* thought of incoming data indication, i.e. asynchronous rx
|
||||
* indication, which can be used by higher layer in separate
|
||||
* dedicated rx task to receive and process rx data.
|
||||
*
|
||||
* In our example, first approach of blocking read is used.
|
||||
*/
|
||||
ESP_LOGV(TAG, "before deQ for ll_read");
|
||||
if (g_h.funcs->_h_dequeue_item(serial_ll_hdl->queue, &buf_handle, HOSTED_BLOCK_MAX)) {
|
||||
ESP_LOGE(TAG, "serial queue recv failed ");
|
||||
return NULL;
|
||||
}
|
||||
ESP_LOGV(TAG, "after deQ for ll_read");
|
||||
|
||||
/* proceed only if payload and length are sane */
|
||||
if (!buf_handle.payload || !buf_handle.payload_len) {
|
||||
ESP_LOGE(TAG, "%s: Dequeue result in empty buffer",__func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*rlen = buf_handle.payload_len;
|
||||
|
||||
ESP_HEXLOGV("ll_read", buf_handle.payload, buf_handle.payload_len, 32);
|
||||
|
||||
return buf_handle.payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Serial interface write
|
||||
* @param serial_ll_hdl - handle
|
||||
* wlen - number of bytes to write
|
||||
* wbuffer - buffer to send
|
||||
* @retval 0 on success, -1 on failure
|
||||
*/
|
||||
static int serial_ll_write(const serial_ll_handle_t * serial_ll_hdl,
|
||||
uint8_t * wbuffer, const uint16_t wlen)
|
||||
{
|
||||
|
||||
if ((! serial_ll_hdl) || (serial_ll_hdl->state != ACTIVE)) {
|
||||
ESP_LOGE(TAG, "serial invalid interface for write");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!wbuffer || !wlen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (wlen > MAX_FRAGMENTABLE_PAYLOAD_SIZE) {
|
||||
ESP_LOGE(TAG, "Payload too large: %u bytes (max allowed: %u)", wlen, MAX_FRAGMENTABLE_PAYLOAD_SIZE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint16_t offset = 0;
|
||||
uint16_t remaining_len = wlen;
|
||||
void (*free_func)(void *) = NULL;
|
||||
uint8_t *buf_to_free = NULL;
|
||||
|
||||
while (remaining_len > 0) {
|
||||
uint16_t frag_len = (remaining_len > MAX_PAYLOAD_SIZE) ? MAX_PAYLOAD_SIZE : remaining_len;
|
||||
uint8_t *frag_ptr = wbuffer + offset;
|
||||
|
||||
uint8_t flags = 0;
|
||||
if (remaining_len > MAX_PAYLOAD_SIZE) {
|
||||
flags |= MORE_FRAGMENT;
|
||||
}
|
||||
else {
|
||||
// FRAGMENTATION COMPLETED
|
||||
buf_to_free = wbuffer;
|
||||
free_func = H_DEFLT_FREE_FUNC;
|
||||
}
|
||||
|
||||
int ret = esp_hosted_tx(serial_ll_hdl->if_type,
|
||||
serial_ll_hdl->if_num,
|
||||
frag_ptr,
|
||||
frag_len,
|
||||
H_BUFF_NO_ZEROCOPY,
|
||||
buf_to_free, free_func,
|
||||
flags);
|
||||
if (ret != ESP_OK) {
|
||||
if (flags & MORE_FRAGMENT) {
|
||||
H_FREE_PTR_WITH_FUNC(H_DEFLT_FREE_FUNC, wbuffer);
|
||||
}
|
||||
ESP_LOGE(TAG, "esp_hosted_tx failed at offset=%u len=%u", offset, frag_len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
offset += frag_len;
|
||||
remaining_len -= frag_len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Serial rx handler is called by spi driver when there
|
||||
* is incoming data with interface type is Serial.
|
||||
* @param if_num - interface instance
|
||||
* rxbuff - buffer from spi driver
|
||||
* rx_len - size of rxbuff
|
||||
* seq_num - serial sequence number
|
||||
* flag_more_frags - Flags for fragmentation
|
||||
* @retval 0 on success, else failure
|
||||
*/
|
||||
int serial_ll_rx_handler(interface_buffer_handle_t * buf_handle)
|
||||
{
|
||||
|
||||
#define SERIAL_ALLOC_REALLOC_RDATA() \
|
||||
do { \
|
||||
if(!r.data) { \
|
||||
r.data = (uint8_t *)g_h.funcs->_h_malloc(buf_handle->payload_len); \
|
||||
} else { \
|
||||
r.data = (uint8_t *)g_h.funcs->_h_realloc(r.data, r.len + buf_handle->payload_len); \
|
||||
} \
|
||||
if (!r.data) { \
|
||||
ESP_LOGE(TAG, "Failed to allocate serial data"); \
|
||||
goto serial_buff_cleanup; \
|
||||
} \
|
||||
} while(0);
|
||||
|
||||
serial_ll_handle_t * serial_ll_hdl = NULL;
|
||||
uint8_t *serial_buf = NULL;
|
||||
interface_buffer_handle_t new_buf_handle = {0};
|
||||
|
||||
/* Check valid handle and length */
|
||||
if (!buf_handle || !buf_handle->payload_len) {
|
||||
ESP_LOGE(TAG, "%s:%u Invalid parameters", __func__, __LINE__);
|
||||
goto serial_buff_cleanup;
|
||||
}
|
||||
|
||||
serial_ll_hdl = get_serial_ll_handle(buf_handle->if_num);
|
||||
|
||||
/* Is serial interface up */
|
||||
if ((! serial_ll_hdl) || (serial_ll_hdl->state != ACTIVE)) {
|
||||
ESP_LOGD(TAG, "Serial interface not active (possibly shutting down), discarding packet");
|
||||
goto serial_buff_cleanup_silent;
|
||||
}
|
||||
|
||||
|
||||
/* Accumulate fragments */
|
||||
if (buf_handle->flag & MORE_FRAGMENT) {
|
||||
|
||||
ESP_LOGD(TAG, "Fragment!!!");
|
||||
SERIAL_ALLOC_REALLOC_RDATA();
|
||||
|
||||
g_h.funcs->_h_memcpy((r.data + r.len), buf_handle->payload, buf_handle->payload_len);
|
||||
r.len += buf_handle->payload_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SERIAL_ALLOC_REALLOC_RDATA();
|
||||
|
||||
/* No or last fragment */
|
||||
g_h.funcs->_h_memcpy((r.data + r.len), buf_handle->payload, buf_handle->payload_len);
|
||||
r.len += buf_handle->payload_len;
|
||||
|
||||
serial_buf = (uint8_t *)g_h.funcs->_h_malloc(r.len);
|
||||
if(!serial_buf) {
|
||||
ESP_LOGE(TAG, "Malloc failed, drop pkt");
|
||||
goto serial_buff_cleanup;
|
||||
}
|
||||
g_h.funcs->_h_memcpy(serial_buf, r.data, r.len);
|
||||
|
||||
/* form new buf handle for processing of serial msg */
|
||||
new_buf_handle.if_type = ESP_SERIAL_IF;
|
||||
new_buf_handle.if_num = buf_handle->if_num;
|
||||
new_buf_handle.payload_len = r.len;
|
||||
new_buf_handle.payload = serial_buf;
|
||||
new_buf_handle.priv_buffer_handle = serial_buf;
|
||||
new_buf_handle.free_buf_handle = g_h.funcs->_h_free;
|
||||
|
||||
/* clear old buf handle */
|
||||
//H_FREE_PTR_WITH_FUNC(buf_handle->free_buf_handle, buf_handle->priv_buffer_handle);
|
||||
|
||||
|
||||
r.len = 0;
|
||||
g_h.funcs->_h_free(r.data);
|
||||
r.data = NULL;
|
||||
|
||||
ESP_LOGV(TAG, "before ENQ for ll_read");
|
||||
/* send to serial queue */
|
||||
if (g_h.funcs->_h_queue_item(serial_ll_hdl->queue,
|
||||
&new_buf_handle, HOSTED_BLOCK_MAX)) {
|
||||
ESP_LOGE(TAG, "Failed send serialif queue[%u]", new_buf_handle.if_num);
|
||||
goto serial_buff_cleanup;
|
||||
}
|
||||
ESP_LOGV(TAG, "after ENQ for ll_read");
|
||||
|
||||
/* Indicate higher layer about data ready for consumption */
|
||||
if (serial_ll_hdl->serial_rx_callback) {
|
||||
(*serial_ll_hdl->serial_rx_callback) ();
|
||||
} else {
|
||||
goto serial_buff_cleanup;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
serial_buff_cleanup:
|
||||
ESP_LOGE(TAG, "Err occurred, discard current buffer");
|
||||
|
||||
serial_buff_cleanup_silent:
|
||||
/* Common cleanup path - used for both errors and expected shutdown */
|
||||
H_FREE_PTR_WITH_FUNC(buf_handle->free_buf_handle, buf_handle->priv_buffer_handle);
|
||||
|
||||
r.len = 0;
|
||||
|
||||
H_FREE_PTR_WITH_FUNC(new_buf_handle.free_buf_handle, new_buf_handle.priv_buffer_handle);
|
||||
|
||||
g_h.funcs->_h_free(r.data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** Exported Functions **/
|
||||
|
||||
/**
|
||||
* @brief create and return new serial interface
|
||||
* @param serial_rx_callback - callback to be invoked on rx data
|
||||
* @retval serial_ll_hdl - output handle of serial interface
|
||||
*/
|
||||
serial_ll_handle_t * serial_ll_init(void(*serial_rx_callback)(void))
|
||||
{
|
||||
serial_ll_handle_t * serial_ll_hdl = NULL;
|
||||
|
||||
/* Check if more serial interfaces be created */
|
||||
if ((conn_num+1) < MAX_SERIAL_INTF) {
|
||||
|
||||
serial_ll_hdl = (serial_ll_handle_t *)g_h.funcs->_h_malloc(sizeof(serial_ll_handle_t));
|
||||
if (! serial_ll_hdl) {
|
||||
ESP_LOGE(TAG, "Serial interface - malloc failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
serial_ll_hdl->if_type = ESP_SERIAL_IF;
|
||||
serial_ll_hdl->if_num = conn_num;
|
||||
serial_ll_hdl->queue = to_serial_ll_intf_queue[conn_num];
|
||||
serial_ll_hdl->state = INIT;
|
||||
serial_ll_hdl->fops = &serial_ll_fops;
|
||||
serial_ll_hdl->serial_rx_callback = serial_rx_callback;
|
||||
interface_handle_g[conn_num] = serial_ll_hdl;
|
||||
conn_num++;
|
||||
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Number of serial interface connections overflow");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return serial_ll_hdl;
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*prevent recursive inclusion */
|
||||
#ifndef __SERIAL_LL_IF_H
|
||||
#define __SERIAL_LL_IF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** includes **/
|
||||
#include "transport_drv.h"
|
||||
#include "port_esp_hosted_host_os.h"
|
||||
|
||||
struct serial_ll_operations;
|
||||
|
||||
/* serial interface handle */
|
||||
typedef struct serial_handle_s {
|
||||
queue_handle_t queue;
|
||||
uint8_t if_type;
|
||||
uint8_t if_num;
|
||||
struct serial_ll_operations *fops;
|
||||
uint8_t state;
|
||||
void (*serial_rx_callback) (void);
|
||||
} serial_ll_handle_t;
|
||||
|
||||
/* serial interface */
|
||||
struct serial_ll_operations {
|
||||
/**
|
||||
* @brief Open new Serial interface
|
||||
* @param serial_ll_hdl - handle of serial interface
|
||||
* @retval 0 if success, -1 on failure
|
||||
*/
|
||||
int (*open) (serial_ll_handle_t *serial_ll_hdl);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Serial interface read non blocking
|
||||
* This is non blocking receive
|
||||
* In case higher layer using serial interface needs to make
|
||||
* blocking read, it should register serial_rx_callback through
|
||||
* serial_ll_init.
|
||||
*
|
||||
* serial_rx_callback is notification mechanism to implementer of
|
||||
* serial interface. Higher layer would understand there is data
|
||||
* is ready through this notification. Then higher layer should do
|
||||
* serial_read API to receive actual data.
|
||||
*
|
||||
* As an another design option, serial_rx_callback can also be
|
||||
* thought of incoming data indication, i.e. asynchronous rx
|
||||
* indication, which can be used by higher layer in separate
|
||||
* dedicated rx task to receive and process rx data.
|
||||
*
|
||||
* @param serial_ll_hdl - handle
|
||||
* rlen - output param, number of bytes read
|
||||
*
|
||||
* @retval rbuffer - ready buffer read on serial interface
|
||||
*/
|
||||
uint8_t * (*read) (const serial_ll_handle_t * serial_ll_hdl,
|
||||
uint16_t * rlen);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Serial interface write
|
||||
* @param serial_ll_hdl - handle
|
||||
* wlen - number of bytes to write
|
||||
* wbuffer - buffer to send
|
||||
* @retval 0 on success, -1 on failure
|
||||
*/
|
||||
int (*write) (const serial_ll_handle_t * serial_ll_hdl,
|
||||
uint8_t * wbuffer, const uint16_t wlen);
|
||||
|
||||
|
||||
/**
|
||||
* @brief close - Close serial interface
|
||||
* @param serial_ll_hdl - handle
|
||||
* @retval rbuffer - ready buffer read on serial interface
|
||||
*/
|
||||
int (*close) (serial_ll_handle_t * serial_ll_hdl);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief serial_ll_init - create and return new serial interface
|
||||
* @param serial_rx_callback - callback to be invoked on rx data
|
||||
* @retval serial_ll_hdl - output handle of serial interface
|
||||
*/
|
||||
serial_ll_handle_t * serial_ll_init(void(*rx_data_ind)(void));
|
||||
|
||||
int serial_ll_rx_handler(interface_buffer_handle_t * buf_handle);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SERIAL_LL_IF_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/** prevent recursive inclusion **/
|
||||
#ifndef __SDIO_DRV_H
|
||||
#define __SDIO_DRV_H
|
||||
|
||||
/** Includes **/
|
||||
|
||||
/** Constants/Macros **/
|
||||
|
||||
/** Exported Structures **/
|
||||
|
||||
/** Exported variables **/
|
||||
|
||||
/** Inline functions **/
|
||||
|
||||
/** Exported Functions **/
|
||||
|
||||
#endif /* __SDIO_DRV_H */
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __SDIO_REG_H
|
||||
#define __SDIO_REG_H
|
||||
|
||||
/** Includes **/
|
||||
#include "port_esp_hosted_host_config.h"
|
||||
|
||||
/** constants/macros **/
|
||||
#define SD_IO_CCCR_FN_ENABLE 0x02
|
||||
#define SD_IO_CCCR_FN_READY 0x03
|
||||
#define SD_IO_CCCR_INT_ENABLE 0x04
|
||||
#define SD_IO_CCCR_BUS_WIDTH 0x07
|
||||
|
||||
#define CCCR_BUS_WIDTH_ECSI (1<<5)
|
||||
|
||||
#define SD_IO_CCCR_BLKSIZEL 0x10
|
||||
#define SD_IO_CCCR_BLKSIZEH 0x11
|
||||
|
||||
/* Interrupt Status */
|
||||
#define ESP_SLAVE_BIT0_INT BIT(0)
|
||||
#define ESP_SLAVE_BIT1_INT BIT(1)
|
||||
#define ESP_SLAVE_BIT2_INT BIT(2)
|
||||
#define ESP_SLAVE_BIT3_INT BIT(3)
|
||||
#define ESP_SLAVE_BIT4_INT BIT(4)
|
||||
#define ESP_SLAVE_BIT5_INT BIT(5)
|
||||
#define ESP_SLAVE_BIT6_INT BIT(6)
|
||||
#define ESP_SLAVE_BIT7_INT BIT(7)
|
||||
#define ESP_SLAVE_RX_UNDERFLOW_INT BIT(16)
|
||||
#define ESP_SLAVE_TX_OVERFLOW_INT BIT(17)
|
||||
#define ESP_SLAVE_RX_NEW_PACKET_INT BIT(23)
|
||||
|
||||
#define ESP_SLAVE_CMD53_END_ADDR 0x1F800
|
||||
#define ESP_SLAVE_LEN_MASK 0xFFFFF
|
||||
#define ESP_BLOCK_SIZE 512
|
||||
#define ESP_RX_BYTE_MAX 0x100000
|
||||
#define ESP_RX_BUFFER_SIZE 1536
|
||||
|
||||
#define ESP_TX_BUFFER_MASK 0xFFF
|
||||
#define ESP_TX_BUFFER_MAX 0x1000
|
||||
#define ESP_MAX_BUF_CNT 10
|
||||
|
||||
#define ESP_SLAVE_SLCHOST_BASE 0x3FF55000
|
||||
|
||||
#define HOST_TO_SLAVE_INTR ESP_SLAVE_SCRATCH_REG_7
|
||||
/* SLAVE registers */
|
||||
/* Interrupt Registers */
|
||||
#define ESP_SLAVE_INT_RAW_REG (ESP_SLAVE_SLCHOST_BASE + 0x50)
|
||||
#define ESP_SLAVE_INT_ST_REG (ESP_SLAVE_SLCHOST_BASE + 0x58)
|
||||
#define ESP_SLAVE_INT_CLR_REG (ESP_SLAVE_SLCHOST_BASE + 0xD4)
|
||||
#define ESP_HOST_INT_ENA_REG (ESP_SLAVE_SLCHOST_BASE + 0xDC)
|
||||
|
||||
/* Host side interrupts for ESP_HOST_INT_ENA_REG */
|
||||
#if H_SLAVE_TARGET_ESP32 || H_SLAVE_TARGET_ESP32C6 || H_SLAVE_TARGET_ESP32C5 || H_SLAVE_TARGET_ESP32C61
|
||||
#define SDIO_INT_NEW_PACKET (23)
|
||||
#define SDIO_INT_START_THROTTLE (7)
|
||||
#define SDIO_INT_STOP_THROTTLE (6)
|
||||
#else
|
||||
#error "SDIO New Packet Intr Bit not defined for Hosted Slave"
|
||||
#endif
|
||||
|
||||
/* Data path registers*/
|
||||
#define ESP_SLAVE_PACKET_LEN_REG (ESP_SLAVE_SLCHOST_BASE + 0x60)
|
||||
#define ESP_SLAVE_TOKEN_RDATA (ESP_SLAVE_SLCHOST_BASE + 0x44)
|
||||
|
||||
/* Scratch registers*/
|
||||
#define ESP_SLAVE_SCRATCH_REG_0 (ESP_SLAVE_SLCHOST_BASE + 0x6C)
|
||||
#define ESP_SLAVE_SCRATCH_REG_1 (ESP_SLAVE_SLCHOST_BASE + 0x70)
|
||||
#define ESP_SLAVE_SCRATCH_REG_2 (ESP_SLAVE_SLCHOST_BASE + 0x74)
|
||||
#define ESP_SLAVE_SCRATCH_REG_3 (ESP_SLAVE_SLCHOST_BASE + 0x78)
|
||||
#define ESP_SLAVE_SCRATCH_REG_4 (ESP_SLAVE_SLCHOST_BASE + 0x7C)
|
||||
#define ESP_SLAVE_SCRATCH_REG_6 (ESP_SLAVE_SLCHOST_BASE + 0x88)
|
||||
#define ESP_SLAVE_SCRATCH_REG_7 (ESP_SLAVE_SLCHOST_BASE + 0x8C)
|
||||
#define ESP_SLAVE_SCRATCH_REG_8 (ESP_SLAVE_SLCHOST_BASE + 0x9C)
|
||||
#define ESP_SLAVE_SCRATCH_REG_9 (ESP_SLAVE_SLCHOST_BASE + 0xA0)
|
||||
#define ESP_SLAVE_SCRATCH_REG_10 (ESP_SLAVE_SLCHOST_BASE + 0xA4)
|
||||
#define ESP_SLAVE_SCRATCH_REG_11 (ESP_SLAVE_SLCHOST_BASE + 0xA8)
|
||||
#define ESP_SLAVE_SCRATCH_REG_12 (ESP_SLAVE_SLCHOST_BASE + 0xAC)
|
||||
#define ESP_SLAVE_SCRATCH_REG_13 (ESP_SLAVE_SLCHOST_BASE + 0xB0)
|
||||
#define ESP_SLAVE_SCRATCH_REG_14 (ESP_SLAVE_SLCHOST_BASE + 0xB4)
|
||||
#define ESP_SLAVE_SCRATCH_REG_15 (ESP_SLAVE_SLCHOST_BASE + 0xB8)
|
||||
|
||||
#define ESP_ADDRESS_MASK (0x3FF)
|
||||
|
||||
#define ESP_VENDOR_ID (0x6666)
|
||||
#define ESP_DEVICE_ID_1 (0x2222)
|
||||
#define ESP_DEVICE_ID_2 (0x3333)
|
||||
|
||||
|
||||
#define SDIO_REG(x) ((x)&ESP_ADDRESS_MASK)
|
||||
|
||||
#define SDIO_FUNC_0 (0)
|
||||
#define SDIO_FUNC_1 (1)
|
||||
|
||||
#define ESP_SDIO_CONF_OFFSET (0)
|
||||
#define ESP_SDIO_SEND_OFFSET (16)
|
||||
|
||||
#endif /* __SDIO_REG_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/** prevent recursive inclusion **/
|
||||
#ifndef __SPI_DRV_H
|
||||
#define __SPI_DRV_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Includes **/
|
||||
#include "transport_drv.h"
|
||||
|
||||
/** Constants/Macros **/
|
||||
#define TO_SLAVE_QUEUE_SIZE 20
|
||||
#define FROM_SLAVE_QUEUE_SIZE 20
|
||||
|
||||
/** Exported Structures **/
|
||||
|
||||
/** Exported variables **/
|
||||
|
||||
/** Inline functions **/
|
||||
|
||||
/** Exported Functions **/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/** prevent recursive inclusion **/
|
||||
#ifndef __SPI_HD_DRV_H
|
||||
#define __SPI_HD_DRV_H
|
||||
|
||||
#endif /* __SPI_HD_DRV_H */
|
||||
@@ -0,0 +1,957 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/** Includes **/
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "esp_wifi.h"
|
||||
#include "transport_drv.h"
|
||||
#include "esp_hosted_transport.h"
|
||||
#include "esp_hosted_transport_init.h"
|
||||
#include "esp_hosted_transport_config.h"
|
||||
#include "esp_hosted_host_fw_ver.h"
|
||||
#include "stats.h"
|
||||
#include "esp_hosted_log.h"
|
||||
#include "serial_drv.h"
|
||||
#include "serial_ll_if.h"
|
||||
#include "stats.h"
|
||||
#include "errno.h"
|
||||
#include "hci_drv.h"
|
||||
#include "port_esp_hosted_host_config.h"
|
||||
#include "port_esp_hosted_host_log.h"
|
||||
#include "esp_hosted_power_save.h"
|
||||
|
||||
#include "mempool.h"
|
||||
#include "transport_util.h"
|
||||
|
||||
#include "esp_hosted_cli.h"
|
||||
#include "rpc_wrap.h"
|
||||
#include "esp_private/wifi.h"
|
||||
|
||||
/**
|
||||
* @brief Slave capabilities are parsed
|
||||
* Currently no added functionality to that
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
|
||||
#define MEMPOOL_ALIGNED(VAL, BYTES) ((VAL) + (BYTES) - \
|
||||
((VAL) & (BYTES - 1)))
|
||||
#define MEMPOOL_ALIGNMENT_BYTES 64
|
||||
#define MEMPOOL_PADDING 5 // to cater for possible peak tx requests
|
||||
|
||||
DEFINE_LOG_TAG(transport);
|
||||
static char chip_type = ESP_PRIV_FIRMWARE_CHIP_UNRECOGNIZED;
|
||||
void(*transport_esp_hosted_up_cb)(void) = NULL;
|
||||
transport_channel_t *chan_arr[ESP_MAX_IF];
|
||||
volatile uint8_t wifi_tx_throttling;
|
||||
void *bus_handle = NULL;
|
||||
|
||||
|
||||
static volatile uint8_t transport_state = TRANSPORT_INACTIVE;
|
||||
|
||||
static void process_event(uint8_t *evt_buf, uint16_t len);
|
||||
static int process_init_event(uint8_t *evt_buf, uint16_t len);
|
||||
|
||||
#if H_USE_MEMPOOL
|
||||
static hosted_mempool_t * transport_drv_common_mempool_create(void);
|
||||
static void transport_drv_common_mempool_destroy(hosted_mempool_t * param);
|
||||
#endif
|
||||
|
||||
#if H_HOST_RESTART_NO_COMMUNICATION_WITH_SLAVE && H_HOST_RESTART_NO_COMMUNICATION_WITH_SLAVE_TIMEOUT_MS != -1
|
||||
static void *init_timeout_timer = NULL;
|
||||
|
||||
static void init_timeout_cb(void *arg)
|
||||
{
|
||||
ESP_LOGE(TAG, "Init event not received within timeout, Resetting myself");
|
||||
g_h.funcs->_h_restart_host();
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t is_transport_rx_ready(void)
|
||||
{
|
||||
return (transport_state >= TRANSPORT_RX_ACTIVE);
|
||||
}
|
||||
|
||||
uint8_t is_transport_tx_ready(void)
|
||||
{
|
||||
return (transport_state >= TRANSPORT_TX_ACTIVE);
|
||||
}
|
||||
|
||||
static void transport_driver_event_handler(uint8_t event)
|
||||
{
|
||||
switch(event)
|
||||
{
|
||||
case TRANSPORT_TX_ACTIVE:
|
||||
{
|
||||
/* Initiate control path now */
|
||||
ESP_LOGI(TAG, "Base transport is set-up, TRANSPORT_TX_ACTIVE");
|
||||
if (transport_esp_hosted_up_cb)
|
||||
transport_esp_hosted_up_cb();
|
||||
transport_state = TRANSPORT_TX_ACTIVE;
|
||||
break;
|
||||
}
|
||||
|
||||
case TRANSPORT_INACTIVE:
|
||||
case TRANSPORT_RX_ACTIVE:
|
||||
transport_state = event;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void set_transport_state(uint8_t state)
|
||||
{
|
||||
ESP_LOGI(TAG, "set_transport_state: %u", state);
|
||||
transport_driver_event_handler(state);
|
||||
}
|
||||
|
||||
static void transport_drv_init(void)
|
||||
{
|
||||
bus_handle = bus_init_internal();
|
||||
ESP_LOGD(TAG, "Bus handle: %p", bus_handle);
|
||||
assert(bus_handle);
|
||||
#if H_NETWORK_SPLIT_ENABLED
|
||||
ESP_LOGI(TAG, "Network split enabled. Port ranges- Host:TCP(%d-%d), UDP(%d-%d), Slave:TCP(%d-%d), UDP(%d-%d)",
|
||||
H_HOST_TCP_LOCAL_PORT_RANGE_START, H_HOST_TCP_LOCAL_PORT_RANGE_END,
|
||||
H_HOST_UDP_LOCAL_PORT_RANGE_START, H_HOST_UDP_LOCAL_PORT_RANGE_END,
|
||||
H_SLAVE_TCP_REMOTE_PORT_RANGE_START, H_SLAVE_TCP_REMOTE_PORT_RANGE_END,
|
||||
H_SLAVE_UDP_REMOTE_PORT_RANGE_START, H_SLAVE_UDP_REMOTE_PORT_RANGE_END);
|
||||
#endif
|
||||
hci_drv_init();
|
||||
}
|
||||
|
||||
esp_err_t teardown_transport(void)
|
||||
{
|
||||
#if H_HOST_RESTART_NO_COMMUNICATION_WITH_SLAVE && H_HOST_RESTART_NO_COMMUNICATION_WITH_SLAVE_TIMEOUT_MS != -1
|
||||
/* Stop and cleanup init timeout timer if still active */
|
||||
if (init_timeout_timer) {
|
||||
g_h.funcs->_h_timer_stop(init_timeout_timer);
|
||||
init_timeout_timer = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Stop CLI before tearing down transport */
|
||||
#ifdef H_ESP_HOSTED_CLI_ENABLED
|
||||
esp_hosted_cli_stop();
|
||||
#endif
|
||||
|
||||
if (bus_handle) {
|
||||
bus_deinit_internal(bus_handle);
|
||||
}
|
||||
ESP_LOGI(TAG, "TRANSPORT_INACTIVE");
|
||||
transport_state = TRANSPORT_INACTIVE;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t setup_transport(void(*esp_hosted_up_cb)(void))
|
||||
{
|
||||
g_h.funcs->_h_hosted_init_hook();
|
||||
transport_drv_init();
|
||||
transport_esp_hosted_up_cb = esp_hosted_up_cb;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t transport_drv_reconfigure(void)
|
||||
{
|
||||
static int retry_slave_connection = 0;
|
||||
|
||||
ESP_LOGI(TAG, "Attempt connection with slave: retry[%u]", retry_slave_connection);
|
||||
|
||||
#if H_HOST_RESTART_NO_COMMUNICATION_WITH_SLAVE && H_HOST_RESTART_NO_COMMUNICATION_WITH_SLAVE_TIMEOUT_MS != -1
|
||||
/* Start init timeout timer if not already started */
|
||||
if (!init_timeout_timer) {
|
||||
init_timeout_timer = g_h.funcs->_h_timer_start("slave_unresponsive_timer", H_HOST_RESTART_NO_COMMUNICATION_WITH_SLAVE_TIMEOUT_MS, H_TIMER_TYPE_ONESHOT, init_timeout_cb, NULL);
|
||||
if (!init_timeout_timer) {
|
||||
ESP_LOGE(TAG, "Failed to create init timeout timer");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
ESP_LOGI(TAG, "Started host communication init timer of %u millisec", H_HOST_RESTART_NO_COMMUNICATION_WITH_SLAVE_TIMEOUT_MS);
|
||||
}
|
||||
#endif
|
||||
|
||||
int retry_power_save_recover = 5;
|
||||
if (esp_hosted_woke_from_power_save()) {
|
||||
ESP_LOGI(TAG, "Waiting for power save to be off");
|
||||
g_h.funcs->_h_msleep(700);
|
||||
|
||||
while (retry_power_save_recover) {
|
||||
if (is_transport_tx_ready()) {
|
||||
break;
|
||||
}
|
||||
retry_power_save_recover--;
|
||||
}
|
||||
}
|
||||
|
||||
/* This would come into picture, only if the host has
|
||||
* reset pin connected to slave's 'EN' or 'RST' GPIO */
|
||||
if (!is_transport_tx_ready()) {
|
||||
if (ESP_OK != ensure_slave_bus_ready(bus_handle)) {
|
||||
ESP_LOGE(TAG, "ensure_slave_bus_ready failed");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
transport_state = TRANSPORT_RX_ACTIVE;
|
||||
ESP_LOGI(TAG, "Waiting for esp_hosted slave to be ready");
|
||||
while (!is_transport_tx_ready()) {
|
||||
if (retry_slave_connection < MAX_RETRY_TRANSPORT_ACTIVE) {
|
||||
retry_slave_connection++;
|
||||
if (retry_slave_connection%50==0) {
|
||||
ESP_LOGI(TAG, "Not able to connect with ESP-Hosted slave device");
|
||||
if (ESP_OK != ensure_slave_bus_ready(bus_handle)) {
|
||||
ESP_LOGE(TAG, "ensure_slave_bus_ready failed");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Failed to get ESP_Hosted slave transport up");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
g_h.funcs->_h_msleep(200);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Transport is already up");
|
||||
}
|
||||
|
||||
retry_slave_connection = 0;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t transport_drv_remove_channel(transport_channel_t *channel)
|
||||
{
|
||||
if (!channel)
|
||||
return ESP_FAIL;
|
||||
|
||||
switch (channel->if_type) {
|
||||
case ESP_AP_IF:
|
||||
case ESP_STA_IF:
|
||||
/* Unregister RX callback to prevent memory leak */
|
||||
esp_wifi_internal_reg_rxcb(channel->if_type, NULL);
|
||||
break;
|
||||
case ESP_SERIAL_IF:
|
||||
/* TODO */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
assert(chan_arr[channel->if_type] == channel);
|
||||
|
||||
#if H_USE_MEMPOOL
|
||||
transport_drv_common_mempool_destroy(channel->memp);
|
||||
#endif
|
||||
chan_arr[channel->if_type] = NULL;
|
||||
HOSTED_FREE(channel);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if H_USE_MEMPOOL
|
||||
/*
|
||||
* Use a common mempool for all tx channels to optimise memory usage
|
||||
* instead of separate mempools for STA and AP tx.
|
||||
*
|
||||
* If user does not use AP, for example, separate mempool allocated
|
||||
* for AP will be unused.
|
||||
*/
|
||||
|
||||
// reference count mempool allocations
|
||||
static int ref_count_mempool = 0;
|
||||
static hosted_mempool_t * mempool_common = NULL;
|
||||
|
||||
static hosted_mempool_t * transport_drv_common_mempool_create(void)
|
||||
{
|
||||
if (!ref_count_mempool) {
|
||||
// create mempool once only
|
||||
hosted_mempool_config_t config = {
|
||||
.pre_allocated_mem = NULL,
|
||||
.pre_allocated_mem_size = 0,
|
||||
.num_blocks = H_TRANSPORT_QUEUE_SIZE + MEMPOOL_PADDING,
|
||||
.block_size = ESP_TRANSPORT_MAX_BUF_SIZE,
|
||||
.alignment_in_bytes = HOSTED_MEM_ALIGNMENT_64,
|
||||
.malloc = transport_util_malloc,
|
||||
.calloc = transport_util_calloc,
|
||||
.memset = g_h.funcs->_h_memset,
|
||||
.free = g_h.funcs->_h_free,
|
||||
};
|
||||
mempool_common = hosted_mempool_create(&config);
|
||||
assert(mempool_common);
|
||||
}
|
||||
|
||||
// increment ref count
|
||||
ref_count_mempool++;
|
||||
|
||||
return mempool_common;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if H_USE_MEMPOOL
|
||||
static void transport_drv_common_mempool_destroy(hosted_mempool_t * param)
|
||||
{
|
||||
// decrement ref count
|
||||
ref_count_mempool--;
|
||||
if (ref_count_mempool == 0) {
|
||||
// destroy the mempool
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void transport_sta_free_cb(void *buf)
|
||||
{
|
||||
MEMPOOL_FREE(chan_arr[ESP_STA_IF]->memp, buf);
|
||||
}
|
||||
|
||||
static void transport_ap_free_cb(void *buf)
|
||||
{
|
||||
MEMPOOL_FREE(chan_arr[ESP_AP_IF]->memp, buf);
|
||||
}
|
||||
|
||||
static void transport_serial_free_cb(void *buf)
|
||||
{
|
||||
MEMPOOL_FREE(chan_arr[ESP_SERIAL_IF]->memp, buf);
|
||||
}
|
||||
|
||||
static inline void *mempool_alloc(hosted_mempool_t * mempool, size_t size, uint need_memset)
|
||||
{
|
||||
MEMPOOL_ALLOC(mempool, size, need_memset);
|
||||
}
|
||||
|
||||
static esp_err_t transport_drv_sta_tx(void *h, void *buffer, size_t len)
|
||||
{
|
||||
void * copy_buff = NULL;
|
||||
|
||||
if (!buffer || !len)
|
||||
return ESP_OK;
|
||||
|
||||
/* Transport state check */
|
||||
if (!is_transport_tx_ready() || !chan_arr[ESP_STA_IF]) {
|
||||
ESP_LOGE(TAG, "Transport TX not ready or STA channel is not available, drop pkt");
|
||||
#if defined(ESP_ERR_ESP_NETIF_TX_FAILED)
|
||||
return ESP_ERR_ESP_NETIF_TX_FAILED;
|
||||
#else
|
||||
return ESP_ERR_ESP_NETIF_NO_MEM;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (unlikely(wifi_tx_throttling)) {
|
||||
#if ESP_PKT_STATS
|
||||
pkt_stats.sta_tx_flowctrl_drop++;
|
||||
#endif
|
||||
errno = -ENOBUFS;
|
||||
//return ESP_ERR_NO_BUFFS;
|
||||
#if defined(ESP_ERR_ESP_NETIF_TX_FAILED)
|
||||
return ESP_ERR_ESP_NETIF_TX_FAILED;
|
||||
#else
|
||||
return ESP_ERR_ESP_NETIF_NO_MEM;
|
||||
#endif
|
||||
}
|
||||
|
||||
assert(h && h==chan_arr[ESP_STA_IF]->api_chan);
|
||||
|
||||
/* Prepare transport buffer directly consumable */
|
||||
copy_buff = mempool_alloc(chan_arr[ESP_STA_IF]->memp, MAX_TRANSPORT_BUFFER_SIZE, true);
|
||||
if (!copy_buff) {
|
||||
ESP_LOGW(TAG, "STA TX: mempool_alloc failed, dropping pkt (len=%u)", len);
|
||||
#if defined(ESP_ERR_ESP_NETIF_TX_FAILED)
|
||||
return ESP_ERR_ESP_NETIF_TX_FAILED;
|
||||
#else
|
||||
return ESP_ERR_ESP_NETIF_NO_MEM;
|
||||
#endif
|
||||
}
|
||||
g_h.funcs->_h_memcpy(copy_buff+H_ESP_PAYLOAD_HEADER_OFFSET, buffer, len);
|
||||
|
||||
return esp_hosted_tx(ESP_STA_IF, 0, copy_buff, len, H_BUFF_ZEROCOPY, copy_buff, transport_sta_free_cb, 0);
|
||||
}
|
||||
|
||||
static esp_err_t transport_drv_ap_tx(void *h, void *buffer, size_t len)
|
||||
{
|
||||
void * copy_buff = NULL;
|
||||
|
||||
if (!buffer || !len)
|
||||
return ESP_OK;
|
||||
|
||||
/* Transport state check */
|
||||
if (!is_transport_tx_ready() || !chan_arr[ESP_AP_IF]) {
|
||||
ESP_LOGE(TAG, "Transport TX not ready or AP channel is not available, drop pkt");
|
||||
|
||||
#if defined(ESP_ERR_ESP_NETIF_TX_FAILED)
|
||||
return ESP_ERR_ESP_NETIF_TX_FAILED;
|
||||
#else
|
||||
return ESP_ERR_ESP_NETIF_NO_MEM;
|
||||
#endif
|
||||
}
|
||||
|
||||
assert(h && h==chan_arr[ESP_AP_IF]->api_chan);
|
||||
|
||||
/* Prepare transport buffer directly consumable */
|
||||
copy_buff = mempool_alloc(chan_arr[ESP_AP_IF]->memp, MAX_TRANSPORT_BUFFER_SIZE, true);
|
||||
if (!copy_buff) {
|
||||
ESP_LOGW(TAG, "AP TX: mempool_alloc failed, dropping pkt (len=%u)", len);
|
||||
#if defined(ESP_ERR_ESP_NETIF_TX_FAILED)
|
||||
return ESP_ERR_ESP_NETIF_TX_FAILED;
|
||||
#else
|
||||
return ESP_ERR_ESP_NETIF_NO_MEM;
|
||||
#endif
|
||||
}
|
||||
g_h.funcs->_h_memcpy(copy_buff+H_ESP_PAYLOAD_HEADER_OFFSET, buffer, len);
|
||||
|
||||
return esp_hosted_tx(ESP_AP_IF, 0, copy_buff, len, H_BUFF_ZEROCOPY, copy_buff, transport_ap_free_cb, 0);
|
||||
}
|
||||
|
||||
esp_err_t transport_drv_serial_tx(void *h, void *buffer, size_t len)
|
||||
{
|
||||
/* TODO */
|
||||
/* Transport state check */
|
||||
if (!is_transport_tx_ready() || !chan_arr[ESP_SERIAL_IF]) {
|
||||
|
||||
ESP_LOGE(TAG, "Transport TX not ready or serial channel is not available, drop pkt");
|
||||
|
||||
#if defined(ESP_ERR_ESP_NETIF_TX_FAILED)
|
||||
return ESP_ERR_ESP_NETIF_TX_FAILED;
|
||||
#else
|
||||
return ESP_ERR_ESP_NETIF_NO_MEM;
|
||||
#endif
|
||||
}
|
||||
assert(h && h==chan_arr[ESP_SERIAL_IF]->api_chan);
|
||||
return esp_hosted_tx(ESP_SERIAL_IF, 0, buffer, len, H_BUFF_NO_ZEROCOPY, buffer, transport_serial_free_cb, 0);
|
||||
}
|
||||
|
||||
|
||||
transport_channel_t *transport_drv_add_channel(void *api_chan,
|
||||
esp_hosted_if_type_t if_type, uint8_t secure,
|
||||
transport_channel_tx_fn_t *tx, const transport_channel_rx_fn_t rx)
|
||||
{
|
||||
ESP_LOGD(TAG, "Adding channel IF[%u]: S[%u] Tx[%p] Rx[%p]", if_type, secure, tx, rx);
|
||||
transport_channel_t *channel = NULL;
|
||||
|
||||
ESP_ERROR_CHECK(if_type >= ESP_MAX_IF);
|
||||
|
||||
if (!tx || !rx) {
|
||||
ESP_LOGE(TAG, "%s fail for IF[%u]: tx or rx is NULL", __func__, if_type );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (chan_arr[if_type]) {
|
||||
ESP_LOGW(TAG, "Channel [%u] already created, replacing with new callbacks", if_type);
|
||||
|
||||
if (chan_arr[if_type]->memp) {
|
||||
#if H_USE_MEMPOOL
|
||||
transport_drv_common_mempool_destroy(chan_arr[if_type]->memp);
|
||||
#endif
|
||||
}
|
||||
HOSTED_FREE(chan_arr[if_type]);
|
||||
chan_arr[if_type] = NULL;
|
||||
}
|
||||
|
||||
|
||||
chan_arr[if_type] = g_h.funcs->_h_calloc(sizeof(transport_channel_t), 1);
|
||||
assert(chan_arr[if_type]);
|
||||
channel = chan_arr[if_type];
|
||||
|
||||
switch (if_type) {
|
||||
|
||||
case ESP_STA_IF:
|
||||
*tx = transport_drv_sta_tx;
|
||||
break;
|
||||
|
||||
case ESP_AP_IF:
|
||||
*tx = transport_drv_ap_tx;
|
||||
break;
|
||||
|
||||
case ESP_SERIAL_IF:
|
||||
*tx = transport_drv_serial_tx;
|
||||
break;
|
||||
|
||||
default:
|
||||
//*tx = transport_drv_tx;
|
||||
ESP_LOGW(TAG, "Not yet supported ESP_Hosted interface for if_type[%u]", if_type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
channel->api_chan = api_chan;
|
||||
channel->if_type = if_type;
|
||||
channel->secure = secure;
|
||||
channel->tx = *tx;
|
||||
channel->rx = rx;
|
||||
|
||||
/* Need to change size wrt transport */
|
||||
#if H_USE_MEMPOOL
|
||||
channel->memp = transport_drv_common_mempool_create();
|
||||
#endif
|
||||
|
||||
ESP_LOGD(TAG, "Add ESP-Hosted channel IF[%u]: S[%u] Tx[%p] Rx[%p]",
|
||||
if_type, secure, *tx, rx);
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
static void process_capabilities(uint8_t cap)
|
||||
{
|
||||
ESP_LOGI(TAG, "capabilities: 0x%x",cap);
|
||||
}
|
||||
|
||||
static uint32_t process_ext_capabilities(uint8_t * ptr)
|
||||
{
|
||||
// ptr address may be not be 32-bit aligned
|
||||
uint32_t cap;
|
||||
|
||||
cap = (uint32_t)ptr[0] +
|
||||
((uint32_t)ptr[1] << 8) +
|
||||
((uint32_t)ptr[2] << 16) +
|
||||
((uint32_t)ptr[3] << 24);
|
||||
ESP_LOGI(TAG, "extended capabilities: 0x%"PRIx32,cap);
|
||||
|
||||
return cap;
|
||||
}
|
||||
|
||||
void process_priv_communication(interface_buffer_handle_t *buf_handle)
|
||||
{
|
||||
if (!buf_handle || !buf_handle->payload || !buf_handle->payload_len)
|
||||
return;
|
||||
|
||||
process_event(buf_handle->payload, buf_handle->payload_len);
|
||||
}
|
||||
|
||||
static void print_capabilities(uint32_t cap)
|
||||
{
|
||||
ESP_LOGI(TAG, "Features supported are:");
|
||||
if (cap & ESP_WLAN_SDIO_SUPPORT)
|
||||
ESP_LOGI(TAG, "\t * WLAN");
|
||||
if (cap & ESP_BT_UART_SUPPORT)
|
||||
ESP_LOGI(TAG, "\t - HCI over UART");
|
||||
if (cap & ESP_BT_SDIO_SUPPORT)
|
||||
ESP_LOGI(TAG, "\t - HCI over SDIO");
|
||||
if (cap & ESP_BT_SPI_SUPPORT)
|
||||
ESP_LOGI(TAG, "\t - HCI over SPI");
|
||||
if ((cap & ESP_BLE_ONLY_SUPPORT) && (cap & ESP_BR_EDR_ONLY_SUPPORT))
|
||||
ESP_LOGI(TAG, "\t - BT/BLE dual mode");
|
||||
else if (cap & ESP_BLE_ONLY_SUPPORT)
|
||||
ESP_LOGI(TAG, "\t - BLE only");
|
||||
else if (cap & ESP_BR_EDR_ONLY_SUPPORT)
|
||||
ESP_LOGI(TAG, "\t - BR EDR only");
|
||||
}
|
||||
|
||||
static void print_ext_capabilities(uint8_t * ptr)
|
||||
{
|
||||
// ptr address may be not be 32-bit aligned
|
||||
uint32_t cap;
|
||||
|
||||
cap = (uint32_t)ptr[0] +
|
||||
((uint32_t)ptr[1] << 8) +
|
||||
((uint32_t)ptr[2] << 16) +
|
||||
((uint32_t)ptr[3] << 24);
|
||||
|
||||
ESP_LOGI(TAG, "Extended Features supported: [%" PRIX32 "]", cap);;
|
||||
#if H_SPI_HD_HOST_INTERFACE
|
||||
if (cap & ESP_SPI_HD_INTERFACE_SUPPORT_1_DATA_LINE)
|
||||
ESP_LOGI(TAG, "\t * SPI HD 1 data line interface");
|
||||
if (cap & ESP_SPI_HD_INTERFACE_SUPPORT_2_DATA_LINES)
|
||||
ESP_LOGI(TAG, "\t * SPI HD 2 data lines interface");
|
||||
if (cap & ESP_SPI_HD_INTERFACE_SUPPORT_4_DATA_LINES)
|
||||
ESP_LOGI(TAG, "\t * SPI HD 4 data lines interface");
|
||||
if (cap & ESP_WLAN_SUPPORT)
|
||||
ESP_LOGI(TAG, "\t * WLAN");
|
||||
if (cap & ESP_BT_INTERFACE_SUPPORT)
|
||||
ESP_LOGI(TAG, "\t * BT/BLE");
|
||||
#elif H_UART_HOST_TRANSPORT
|
||||
if (cap & ESP_WLAN_UART_SUPPORT)
|
||||
ESP_LOGI(TAG, "\t * WLAN over UART");
|
||||
if (cap & ESP_BT_VHCI_UART_SUPPORT)
|
||||
ESP_LOGI(TAG, "\t * BT over UART (VHCI)");
|
||||
#endif
|
||||
#if H_HOST_OT_ENABLE
|
||||
if (cap & ESP_OT_SUPPORT)
|
||||
ESP_LOGI(TAG, "\t * OpenThread");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void process_event(uint8_t *evt_buf, uint16_t len)
|
||||
{
|
||||
int ret = 0;
|
||||
struct esp_priv_event *event;
|
||||
|
||||
if (!evt_buf || !len)
|
||||
return;
|
||||
|
||||
event = (struct esp_priv_event *) evt_buf;
|
||||
|
||||
if (event->event_type == ESP_PRIV_EVENT_INIT) {
|
||||
|
||||
ESP_LOGI(TAG, "Received INIT event from ESP32 peripheral");
|
||||
ESP_HEXLOGD("Slave_init_evt", event->event_data, event->event_len, 32);
|
||||
|
||||
ret = process_init_event(event->event_data, event->event_len);
|
||||
if (ret) {
|
||||
ESP_LOGE(TAG, "failed to init event\n\r");
|
||||
} else {
|
||||
|
||||
#if H_HOST_PS_ALLOWED && H_HOST_WAKEUP_GPIO
|
||||
esp_hosted_power_save_init();
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Drop unknown event\n\r");
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t get_chip_str_from_id(int chip_id, char* chip_str)
|
||||
{
|
||||
int ret = ESP_OK;
|
||||
assert(chip_str);
|
||||
|
||||
switch(chip_id) {
|
||||
case ESP_PRIV_FIRMWARE_CHIP_ESP32:
|
||||
strcpy(chip_str, "esp32");
|
||||
break;
|
||||
case ESP_PRIV_FIRMWARE_CHIP_ESP32C2:
|
||||
strcpy(chip_str, "esp32c2");
|
||||
break;
|
||||
case ESP_PRIV_FIRMWARE_CHIP_ESP32C3:
|
||||
strcpy(chip_str, "esp32c3");
|
||||
break;
|
||||
case ESP_PRIV_FIRMWARE_CHIP_ESP32C6:
|
||||
strcpy(chip_str, "esp32c6");
|
||||
break;
|
||||
case ESP_PRIV_FIRMWARE_CHIP_ESP32S2:
|
||||
strcpy(chip_str, "esp32s2");
|
||||
break;
|
||||
case ESP_PRIV_FIRMWARE_CHIP_ESP32S3:
|
||||
strcpy(chip_str, "esp32s3");
|
||||
break;
|
||||
case ESP_PRIV_FIRMWARE_CHIP_ESP32C5:
|
||||
strcpy(chip_str, "esp32c5");
|
||||
break;
|
||||
case ESP_PRIV_FIRMWARE_CHIP_ESP32C61:
|
||||
strcpy(chip_str, "esp32c61");
|
||||
break;
|
||||
case ESP_PRIV_FIRMWARE_CHIP_ESP32H2:
|
||||
strcpy(chip_str, "esp32h2");
|
||||
break;
|
||||
case ESP_PRIV_FIRMWARE_CHIP_ESP32H4:
|
||||
strcpy(chip_str, "esp32h4");
|
||||
break;
|
||||
default:
|
||||
ESP_LOGW(TAG, "Unsupported chip id: %u", chip_id);
|
||||
strcpy(chip_str, "unsupported");
|
||||
ret = ESP_FAIL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void verify_host_config_for_slave(uint8_t chip_type)
|
||||
{
|
||||
uint8_t exp_chip_id = 0xff;
|
||||
|
||||
|
||||
#if H_SLAVE_TARGET_ESP32
|
||||
exp_chip_id = ESP_PRIV_FIRMWARE_CHIP_ESP32;
|
||||
#elif H_SLAVE_TARGET_ESP32C2
|
||||
exp_chip_id = ESP_PRIV_FIRMWARE_CHIP_ESP32C2;
|
||||
#elif H_SLAVE_TARGET_ESP32C3
|
||||
exp_chip_id = ESP_PRIV_FIRMWARE_CHIP_ESP32C3;
|
||||
#elif H_SLAVE_TARGET_ESP32C6
|
||||
exp_chip_id = ESP_PRIV_FIRMWARE_CHIP_ESP32C6;
|
||||
#elif H_SLAVE_TARGET_ESP32S2
|
||||
exp_chip_id = ESP_PRIV_FIRMWARE_CHIP_ESP32S2;
|
||||
#elif H_SLAVE_TARGET_ESP32S3
|
||||
exp_chip_id = ESP_PRIV_FIRMWARE_CHIP_ESP32S3;
|
||||
#elif H_SLAVE_TARGET_ESP32C5
|
||||
exp_chip_id = ESP_PRIV_FIRMWARE_CHIP_ESP32C5;
|
||||
#elif H_SLAVE_TARGET_ESP32C61
|
||||
exp_chip_id = ESP_PRIV_FIRMWARE_CHIP_ESP32C61;
|
||||
#elif H_SLAVE_TARGET_ESP32H2
|
||||
exp_chip_id = ESP_PRIV_FIRMWARE_CHIP_ESP32H2;
|
||||
#elif H_SLAVE_TARGET_ESP32H4
|
||||
exp_chip_id = ESP_PRIV_FIRMWARE_CHIP_ESP32H4;
|
||||
#else
|
||||
ESP_LOGW(TAG, "Incorrect host config for ESP slave chipset[%x]", chip_type);
|
||||
#endif
|
||||
char slave_str[20] = {0};
|
||||
get_chip_str_from_id(chip_type, slave_str);
|
||||
|
||||
if (chip_type!=exp_chip_id) {
|
||||
char exp_str[20] = {0};
|
||||
get_chip_str_from_id(exp_chip_id, exp_str);
|
||||
ESP_LOGE(TAG, "Identified slave [%s] != Expected [%s]\n\t\trun 'idf.py menuconfig' at host to reselect the slave?\n\t\tAborting.. ", slave_str, exp_str);
|
||||
g_h.funcs->_h_sleep(10);
|
||||
assert(0!=0);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Identified slave [%s]", slave_str);
|
||||
check_if_max_freq_used(chip_type);
|
||||
}
|
||||
}
|
||||
|
||||
/** return values:
|
||||
* - 0 if versions as the same
|
||||
* - -1 if host version is smaller than slave version
|
||||
* - 1 if host version is bigger than slave version
|
||||
*/
|
||||
static int compare_fw_version(uint32_t slave_version)
|
||||
{
|
||||
uint32_t host_version = ESP_HOSTED_VERSION_VAL(ESP_HOSTED_VERSION_MAJOR_1,
|
||||
ESP_HOSTED_VERSION_MINOR_1,
|
||||
ESP_HOSTED_VERSION_PATCH_1);
|
||||
|
||||
// mask out patch level
|
||||
// compare major.minor only
|
||||
slave_version &= 0xFFFFFF00;
|
||||
host_version &= 0xFFFFFF00;
|
||||
|
||||
if (host_version == slave_version) {
|
||||
// versions match
|
||||
return 0;
|
||||
} else if (host_version > slave_version) {
|
||||
// host version > slave version
|
||||
#ifndef CONFIG_ESP_HOSTED_FW_VERSION_MISMATCH_WARNING_SUPPRESS
|
||||
ESP_LOGW(TAG, "Version mismatch: Host [%u.%u.%u] > Co-proc [%u.%u.%u] ==> Upgrade co-proc to avoid RPC timeouts",
|
||||
ESP_HOSTED_VERSION_PRINTF_ARGS(host_version), ESP_HOSTED_VERSION_PRINTF_ARGS(slave_version));
|
||||
#endif
|
||||
return -1;
|
||||
} else {
|
||||
// host version < slave version
|
||||
#ifndef CONFIG_ESP_HOSTED_FW_VERSION_MISMATCH_WARNING_SUPPRESS
|
||||
ESP_LOGW(TAG, "Version mismatch: Host [%u.%u.%u] < Co-proc [%u.%u.%u] ==> Upgrade host to avoid compatibility issues",
|
||||
ESP_HOSTED_VERSION_PRINTF_ARGS(host_version), ESP_HOSTED_VERSION_PRINTF_ARGS(slave_version));
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t send_slave_config(uint8_t host_cap, uint8_t firmware_chip_id,
|
||||
uint8_t raw_tp_direction, uint8_t low_thr_thesh, uint8_t high_thr_thesh)
|
||||
{
|
||||
#define LENGTH_1_BYTE 1
|
||||
struct esp_priv_event *event = NULL;
|
||||
uint8_t *pos = NULL;
|
||||
uint16_t len = 0;
|
||||
uint8_t *sendbuf = NULL;
|
||||
|
||||
sendbuf = g_h.funcs->_h_malloc_align(MEMPOOL_ALIGNED(256, 64), MEMPOOL_ALIGNMENT_BYTES);
|
||||
assert(sendbuf);
|
||||
|
||||
/* Populate event data */
|
||||
//event = (struct esp_priv_event *) (sendbuf + sizeof(struct esp_payload_header)); //ZeroCopy
|
||||
event = (struct esp_priv_event *) (sendbuf);
|
||||
|
||||
event->event_type = ESP_PRIV_EVENT_INIT;
|
||||
|
||||
/* Populate TLVs for event */
|
||||
pos = event->event_data;
|
||||
|
||||
/* TLVs start */
|
||||
|
||||
/* TLV - Board type */
|
||||
ESP_LOGI(TAG, "Slave chip Id[%x]", ESP_PRIV_FIRMWARE_CHIP_ID);
|
||||
*pos = HOST_CAPABILITIES; pos++;len++;
|
||||
*pos = LENGTH_1_BYTE; pos++;len++;
|
||||
*pos = host_cap; pos++;len++;
|
||||
|
||||
/* TLV - Capability */
|
||||
*pos = RCVD_ESP_FIRMWARE_CHIP_ID; pos++;len++;
|
||||
*pos = LENGTH_1_BYTE; pos++;len++;
|
||||
*pos = firmware_chip_id; pos++;len++;
|
||||
|
||||
*pos = SLV_CONFIG_TEST_RAW_TP; pos++;len++;
|
||||
*pos = LENGTH_1_BYTE; pos++;len++;
|
||||
*pos = raw_tp_direction; pos++;len++;
|
||||
|
||||
*pos = SLV_CONFIG_THROTTLE_HIGH_THRESHOLD; pos++;len++;
|
||||
*pos = LENGTH_1_BYTE; pos++;len++;
|
||||
*pos = high_thr_thesh; pos++;len++;
|
||||
|
||||
*pos = SLV_CONFIG_THROTTLE_LOW_THRESHOLD; pos++;len++;
|
||||
*pos = LENGTH_1_BYTE; pos++;len++;
|
||||
*pos = low_thr_thesh; pos++;len++;
|
||||
|
||||
ESP_LOGI(TAG, "raw_tp_dir[%s], flow_ctrl: low[%u] high[%u]",
|
||||
raw_tp_direction == ESP_TEST_RAW_TP__HOST_TO_ESP? "h2s":
|
||||
raw_tp_direction == ESP_TEST_RAW_TP__ESP_TO_HOST? "s2h":
|
||||
raw_tp_direction == ESP_TEST_RAW_TP__BIDIRECTIONAL? "bi-dir":
|
||||
"-", low_thr_thesh, high_thr_thesh);
|
||||
|
||||
/* TLVs end */
|
||||
|
||||
event->event_len = len;
|
||||
|
||||
/* payload len = Event len + sizeof(event type) + sizeof(event len) */
|
||||
len += 2;
|
||||
|
||||
return esp_hosted_tx(ESP_PRIV_IF, 0, sendbuf, len, H_BUFF_NO_ZEROCOPY, sendbuf, g_h.funcs->_h_free, 0);
|
||||
}
|
||||
|
||||
static int transport_delayed_init(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "transport_delayed_init");
|
||||
rpc_start();
|
||||
/* Add up cli */
|
||||
#ifdef H_ESP_HOSTED_CLI_ENABLED
|
||||
esp_hosted_cli_start();
|
||||
#endif
|
||||
create_debugging_tasks();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int process_init_event(uint8_t *evt_buf, uint16_t len)
|
||||
{
|
||||
uint8_t len_left = len, tag_len;
|
||||
uint8_t *pos;
|
||||
uint8_t raw_tp_config = H_TEST_RAW_TP_DIR;
|
||||
uint32_t ext_cap = 0;
|
||||
uint32_t slave_fw_version = 0;
|
||||
|
||||
if (!evt_buf)
|
||||
return ESP_FAIL;
|
||||
|
||||
#if H_HOST_RESTART_NO_COMMUNICATION_WITH_SLAVE && H_HOST_RESTART_NO_COMMUNICATION_WITH_SLAVE_TIMEOUT_MS != -1
|
||||
/* Stop and delete the init timeout timer since we received the init event */
|
||||
if (init_timeout_timer) {
|
||||
g_h.funcs->_h_timer_stop(init_timeout_timer);
|
||||
init_timeout_timer = NULL;
|
||||
ESP_LOGI(TAG, "Init event received within timeout, cleared timer");
|
||||
}
|
||||
#endif
|
||||
|
||||
pos = evt_buf;
|
||||
ESP_LOGD(TAG, "Init event length: %u", len);
|
||||
if (len > 64) {
|
||||
ESP_LOGE(TAG, "Init event length: %u", len);
|
||||
#if H_TRANSPORT_IN_USE == H_TRANSPORT_SPI
|
||||
ESP_LOGE(TAG, "Seems incompatible SPI mode try changing SPI mode. Asserting for now.");
|
||||
#endif
|
||||
assert(len < 64);
|
||||
}
|
||||
|
||||
while (len_left) {
|
||||
tag_len = *(pos + 1);
|
||||
|
||||
if (*pos == ESP_PRIV_CAPABILITY) {
|
||||
ESP_LOGI(TAG, "EVENT: %2x", *pos);
|
||||
process_capabilities(*(pos + 2));
|
||||
print_capabilities(*(pos + 2));
|
||||
} else if (*pos == ESP_PRIV_CAP_EXT) {
|
||||
ESP_LOGI(TAG, "EVENT: %2x", *pos);
|
||||
ext_cap = process_ext_capabilities(pos + 2);
|
||||
print_ext_capabilities(pos + 2);
|
||||
} else if (*pos == ESP_PRIV_FIRMWARE_CHIP_ID) {
|
||||
ESP_LOGI(TAG, "EVENT: %2x", *pos);
|
||||
chip_type = *(pos+2);
|
||||
verify_host_config_for_slave(chip_type);
|
||||
} else if (*pos == ESP_PRIV_TEST_RAW_TP) {
|
||||
ESP_LOGI(TAG, "EVENT: %2x", *pos);
|
||||
#if TEST_RAW_TP
|
||||
process_test_capabilities(*(pos + 2));
|
||||
#else
|
||||
if (*(pos + 2))
|
||||
ESP_LOGW(TAG, "Slave enabled Raw Throughput Testing, but not enabled on Host");
|
||||
#endif
|
||||
} else if (*pos == ESP_PRIV_RX_Q_SIZE) {
|
||||
ESP_LOGD(TAG, "slave rx queue size: %u", *(pos + 2));
|
||||
} else if (*pos == ESP_PRIV_TX_Q_SIZE) {
|
||||
ESP_LOGD(TAG, "slave tx queue size: %u", *(pos + 2));
|
||||
} else if (*pos == ESP_PRIV_FIRMWARE_VERSION) {
|
||||
// fw_version sent as a little-endian uint32_t
|
||||
slave_fw_version =
|
||||
*(pos + 2) |
|
||||
(*(pos + 3) << 8) |
|
||||
(*(pos + 4) << 16) |
|
||||
(*(pos + 5) << 24);
|
||||
ESP_LOGD(TAG, "slave fw version: 0x%08" PRIx32, slave_fw_version);
|
||||
} else if (*pos == ESP_PRIV_TRANS_SDIO_MODE) {
|
||||
#if H_TRANSPORT_IN_USE == H_TRANSPORT_SDIO
|
||||
uint8_t slave_sdio_mode = *(pos + 2);
|
||||
#if H_SDIO_HOST_RX_MODE == H_SDIO_HOST_STREAMING_MODE
|
||||
uint8_t host_sdio_mode = 1;
|
||||
#else
|
||||
uint8_t host_sdio_mode = 0;
|
||||
#endif
|
||||
ESP_LOGI(TAG, "SDIO mode: slave: %s, host: %s",
|
||||
slave_sdio_mode ? "streaming" : "packet",
|
||||
host_sdio_mode ? "streaming" : "packet");
|
||||
|
||||
if (slave_sdio_mode && !host_sdio_mode) {
|
||||
ESP_LOGE(TAG, "SDIO mode mismatch: slave is in streaming mode, but host is in packet mode. Aborting.");
|
||||
assert(0);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Unsupported EVENT: %2x", *pos);
|
||||
}
|
||||
pos += (tag_len+2);
|
||||
len_left -= (tag_len+2);
|
||||
}
|
||||
|
||||
// if ESP_PRIV_FIRMWARE_VERSION was not received, slave version will be 0.0.0
|
||||
compare_fw_version(slave_fw_version);
|
||||
|
||||
if ((chip_type != ESP_PRIV_FIRMWARE_CHIP_ESP32) &&
|
||||
(chip_type != ESP_PRIV_FIRMWARE_CHIP_ESP32S2) &&
|
||||
(chip_type != ESP_PRIV_FIRMWARE_CHIP_ESP32S3) &&
|
||||
(chip_type != ESP_PRIV_FIRMWARE_CHIP_ESP32C2) &&
|
||||
(chip_type != ESP_PRIV_FIRMWARE_CHIP_ESP32C3) &&
|
||||
(chip_type != ESP_PRIV_FIRMWARE_CHIP_ESP32C6) &&
|
||||
(chip_type != ESP_PRIV_FIRMWARE_CHIP_ESP32C5) &&
|
||||
(chip_type != ESP_PRIV_FIRMWARE_CHIP_ESP32C61) &&
|
||||
(chip_type != ESP_PRIV_FIRMWARE_CHIP_ESP32H2) &&
|
||||
(chip_type != ESP_PRIV_FIRMWARE_CHIP_ESP32H4)) {
|
||||
ESP_LOGI(TAG, "ESP board type is not mentioned, ignoring [%d]\n\r", chip_type);
|
||||
chip_type = ESP_PRIV_FIRMWARE_CHIP_UNRECOGNIZED;
|
||||
return -1;
|
||||
} else {
|
||||
ESP_LOGI(TAG, "ESP board type is : %d \n\r", chip_type);
|
||||
}
|
||||
|
||||
if (ext_cap) {
|
||||
#if H_SPI_HD_HOST_INTERFACE
|
||||
// reconfigure SPI_HD interface based on host and slave capabilities
|
||||
if (H_SPI_HD_HOST_NUM_DATA_LINES == 4) {
|
||||
if (ext_cap & ESP_SPI_HD_INTERFACE_SUPPORT_4_DATA_LINES) {
|
||||
ESP_LOGI(TAG, "configure SPI_HD interface to use 4 data lines");
|
||||
g_h.funcs->_h_spi_hd_set_data_lines(H_SPI_HD_CONFIG_4_DATA_LINES);
|
||||
} else if (ext_cap & ESP_SPI_HD_INTERFACE_SUPPORT_2_DATA_LINES) {
|
||||
ESP_LOGI(TAG, "slave supports 2 data lines, downgrading from 4");
|
||||
g_h.funcs->_h_spi_hd_set_data_lines(H_SPI_HD_CONFIG_2_DATA_LINES);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "slave supports 1 data line, downgrading from 4");
|
||||
g_h.funcs->_h_spi_hd_set_data_lines(H_SPI_HD_CONFIG_1_DATA_LINE);
|
||||
}
|
||||
} else if (H_SPI_HD_HOST_NUM_DATA_LINES == 2) {
|
||||
if (ext_cap & ESP_SPI_HD_INTERFACE_SUPPORT_4_DATA_LINES) {
|
||||
ESP_LOGI(TAG, "slave supports 4 data lines, downgrading to 2");
|
||||
g_h.funcs->_h_spi_hd_set_data_lines(H_SPI_HD_CONFIG_2_DATA_LINES);
|
||||
} else if (ext_cap & ESP_SPI_HD_INTERFACE_SUPPORT_2_DATA_LINES) {
|
||||
ESP_LOGI(TAG, "configure SPI_HD interface to use 2 data lines");
|
||||
g_h.funcs->_h_spi_hd_set_data_lines(H_SPI_HD_CONFIG_2_DATA_LINES);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "slave supports 1 data line, downgrading from 2");
|
||||
g_h.funcs->_h_spi_hd_set_data_lines(H_SPI_HD_CONFIG_1_DATA_LINE);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGI(TAG, "configure SPI_HD interface to use 1 data line");
|
||||
g_h.funcs->_h_spi_hd_set_data_lines(H_SPI_HD_CONFIG_1_DATA_LINE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
transport_driver_event_handler(TRANSPORT_TX_ACTIVE);
|
||||
|
||||
ESP_ERROR_CHECK(send_slave_config(0, chip_type, raw_tp_config,
|
||||
H_WIFI_TX_DATA_THROTTLE_LOW_THRESHOLD,
|
||||
H_WIFI_TX_DATA_THROTTLE_HIGH_THRESHOLD));
|
||||
|
||||
transport_delayed_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int serial_rx_handler(interface_buffer_handle_t * buf_handle)
|
||||
{
|
||||
return serial_ll_rx_handler(buf_handle);
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/** prevent recursive inclusion **/
|
||||
#ifndef __TRANSPORT_DRV_H
|
||||
#define __TRANSPORT_DRV_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Includes **/
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
#include "esp_hosted_transport.h"
|
||||
#include "esp_hosted_api_types.h"
|
||||
#include "esp_hosted_interface.h"
|
||||
#include "esp_hosted_header.h"
|
||||
|
||||
#include "port_esp_hosted_host_config.h"
|
||||
#include "mempool.h"
|
||||
|
||||
#if H_TRANSPORT_IN_USE == H_TRANSPORT_SPI
|
||||
#include "port_esp_hosted_host_spi.h"
|
||||
#elif H_TRANSPORT_IN_USE == H_TRANSPORT_SDIO
|
||||
#include "port_esp_hosted_host_sdio.h"
|
||||
#elif H_TRANSPORT_IN_USE == H_TRANSPORT_SPI_HD
|
||||
#include "port_esp_hosted_host_spi_hd.h"
|
||||
#elif H_TRANSPORT_IN_USE == H_TRANSPORT_UART
|
||||
#include "port_esp_hosted_host_uart.h"
|
||||
#endif
|
||||
|
||||
/* ESP in sdkconfig has CONFIG_IDF_FIRMWARE_CHIP_ID entry.
|
||||
* supported values of CONFIG_IDF_FIRMWARE_CHIP_ID are - */
|
||||
#define ESP_PRIV_FIRMWARE_CHIP_UNRECOGNIZED (0xff)
|
||||
#define ESP_PRIV_FIRMWARE_CHIP_ESP32 (0x0)
|
||||
#define ESP_PRIV_FIRMWARE_CHIP_ESP32S2 (0x2)
|
||||
#define ESP_PRIV_FIRMWARE_CHIP_ESP32C3 (0x5)
|
||||
#define ESP_PRIV_FIRMWARE_CHIP_ESP32S3 (0x9)
|
||||
#define ESP_PRIV_FIRMWARE_CHIP_ESP32C2 (0xC)
|
||||
#define ESP_PRIV_FIRMWARE_CHIP_ESP32C6 (0xD)
|
||||
#define ESP_PRIV_FIRMWARE_CHIP_ESP32C5 (0x17)
|
||||
#define ESP_PRIV_FIRMWARE_CHIP_ESP32C61 (0x14)
|
||||
#define ESP_PRIV_FIRMWARE_CHIP_ESP32H2 (0x10)
|
||||
#define ESP_PRIV_FIRMWARE_CHIP_ESP32H4 (0x1C)
|
||||
|
||||
#define MAX_SPI_BUFFER_SIZE ESP_TRANSPORT_SPI_MAX_BUF_SIZE
|
||||
#define MAX_SDIO_BUFFER_SIZE ESP_TRANSPORT_SDIO_MAX_BUF_SIZE
|
||||
#define MAX_SPI_HD_BUFFER_SIZE ESP_TRANSPORT_SPI_HD_MAX_BUF_SIZE
|
||||
#define MAX_UART_BUFFER_SIZE ESP_TRANSPORT_UART_MAX_BUF_SIZE
|
||||
|
||||
#ifndef BIT
|
||||
#define BIT(x) (1UL << (x))
|
||||
#endif
|
||||
|
||||
#ifndef BIT64
|
||||
#define BIT64(nr) (1ULL << (nr))
|
||||
#endif
|
||||
|
||||
#define H_MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
#define MHZ_TO_HZ(x) (1000000*(x))
|
||||
|
||||
#define H_FREE_PTR_WITH_FUNC(FreeFunc, FreePtr) do { \
|
||||
if (FreeFunc && FreePtr) { \
|
||||
FreeFunc(FreePtr); \
|
||||
FreePtr = NULL; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define SUCCESS 0
|
||||
#define FAILURE -1
|
||||
|
||||
typedef enum {
|
||||
TRANSPORT_INACTIVE, /* No transport activity */
|
||||
TRANSPORT_RX_ACTIVE, /* RX ready, TX not ready */
|
||||
TRANSPORT_TX_ACTIVE, /* Both TX and RX active */
|
||||
} transport_drv_events_e;
|
||||
|
||||
/* interface header */
|
||||
typedef struct {
|
||||
union {
|
||||
void *priv_buffer_handle;
|
||||
};
|
||||
uint8_t if_type;
|
||||
uint8_t if_num;
|
||||
uint8_t *payload;
|
||||
uint8_t flag;
|
||||
uint16_t payload_len;
|
||||
uint16_t seq_num;
|
||||
/* no need of memcpy at different layers */
|
||||
uint8_t payload_zcopy;
|
||||
|
||||
void (*free_buf_handle)(void *buf_handle);
|
||||
} interface_buffer_handle_t;
|
||||
|
||||
struct esp_private {
|
||||
uint8_t if_type;
|
||||
uint8_t if_num;
|
||||
void *netdev;
|
||||
};
|
||||
|
||||
struct hosted_transport_context_t {
|
||||
uint8_t *tx_buf;
|
||||
uint32_t tx_buf_size;
|
||||
uint8_t *rx_buf;
|
||||
};
|
||||
|
||||
extern volatile uint8_t wifi_tx_throttling;
|
||||
|
||||
typedef int (*hosted_rxcb_t)(void *buffer, uint16_t len, void *free_buff_hdl);
|
||||
|
||||
typedef void (transport_free_cb_t)(void* buffer);
|
||||
typedef esp_err_t (*transport_channel_tx_fn_t)(void *h, void *buffer, size_t len);
|
||||
typedef esp_err_t (*transport_channel_rx_fn_t)(void *h, void *buffer, void * buff_to_free, size_t len);
|
||||
|
||||
typedef struct {
|
||||
void * api_chan;
|
||||
esp_hosted_if_type_t if_type;
|
||||
uint8_t secure;
|
||||
transport_channel_tx_fn_t tx;
|
||||
transport_channel_rx_fn_t rx;
|
||||
hosted_mempool_t *memp;
|
||||
} transport_channel_t;
|
||||
|
||||
|
||||
esp_err_t setup_transport(void(*esp_hosted_up_cb)(void));
|
||||
esp_err_t teardown_transport(void);
|
||||
esp_err_t transport_drv_reconfigure(void);
|
||||
transport_channel_t *transport_drv_add_channel(void *api_chan,
|
||||
esp_hosted_if_type_t if_type, uint8_t secure,
|
||||
transport_channel_tx_fn_t *tx, const transport_channel_rx_fn_t rx);
|
||||
esp_err_t transport_drv_remove_channel(transport_channel_t *channel);
|
||||
|
||||
|
||||
void *bus_init_internal(void);
|
||||
void bus_deinit_internal(void *bus_handle);
|
||||
|
||||
void process_priv_communication(interface_buffer_handle_t *buf_handle);
|
||||
|
||||
esp_err_t send_slave_config(uint8_t host_cap, uint8_t firmware_chip_id,
|
||||
uint8_t raw_tp_direction, uint8_t low_thr_thesh, uint8_t high_thr_thesh);
|
||||
|
||||
uint8_t is_transport_rx_ready(void);
|
||||
uint8_t is_transport_tx_ready(void);
|
||||
|
||||
#define H_BUFF_NO_ZEROCOPY 0
|
||||
#define H_BUFF_ZEROCOPY 1
|
||||
|
||||
#define H_DEFLT_FREE_FUNC g_h.funcs->_h_free
|
||||
|
||||
#define MAX_RETRY_TRANSPORT_ACTIVE 100
|
||||
|
||||
|
||||
int esp_hosted_tx(uint8_t iface_type, uint8_t iface_num,
|
||||
uint8_t *payload_buf, uint16_t payload_len, uint8_t buff_zerocopy,
|
||||
uint8_t *buffer_to_free, void (*free_buf_func)(void *ptr), uint8_t flags);
|
||||
|
||||
int serial_rx_handler(interface_buffer_handle_t * buf_handle);
|
||||
void set_transport_state(uint8_t state);
|
||||
|
||||
int ensure_slave_bus_ready(void *bus_handle);
|
||||
void check_if_max_freq_used(uint8_t chip_type);
|
||||
|
||||
int bus_inform_slave_host_power_save_start(void);
|
||||
int bus_inform_slave_host_power_save_stop(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_hosted_os_abstraction.h"
|
||||
#include "port_esp_hosted_host_os.h"
|
||||
#include "transport_util.h"
|
||||
|
||||
void * transport_util_malloc(size_t size, hosted_mem_cap_t cap)
|
||||
{
|
||||
if (cap == HOSTED_MEM_CAP_DMA) {
|
||||
return g_h.funcs->_h_malloc_align(size, HOSTED_MEM_ALIGNMENT_64);
|
||||
} else {
|
||||
return g_h.funcs->_h_malloc(size);
|
||||
}
|
||||
}
|
||||
|
||||
void * transport_util_calloc(size_t num_elem, size_t size_elem, hosted_mem_cap_t cap)
|
||||
{
|
||||
if (cap == HOSTED_MEM_CAP_NONE ) {
|
||||
return calloc(num_elem, size_elem);
|
||||
} else {
|
||||
// malloc DMA capable memory, then clear it
|
||||
size_t size = num_elem * size_elem;
|
||||
void *ptr = heap_caps_malloc(size, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA | MALLOC_CAP_8BIT);
|
||||
if (ptr)
|
||||
memset(ptr, 0, size);
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __SLAVE_UTIL_H__
|
||||
#define __SLAVE_UTIL_H__
|
||||
|
||||
#include "esp_hosted_os_abstraction.h"
|
||||
#include "mempool.h"
|
||||
|
||||
#if H_USE_MEMPOOL
|
||||
|
||||
#define MEMPOOL_ALLOC(pool, nbytes, need_memset) return hosted_mempool_alloc(pool, nbytes, need_memset);
|
||||
|
||||
#define MEMPOOL_FREE(pool, buf) hosted_mempool_free(pool, buf)
|
||||
|
||||
#else // H_USE_MEMPOOL
|
||||
|
||||
#define MEMPOOL_ALLOC(pool, nbytes, need_memset) do { \
|
||||
void *ptr = g_h.funcs->_h_malloc_align(nbytes, \
|
||||
HOSTED_MEM_ALIGNMENT_64); \
|
||||
if (ptr && need_memset) \
|
||||
g_h.funcs->_h_memset(ptr, 0, nbytes); \
|
||||
return ptr; \
|
||||
} while (0);
|
||||
|
||||
#define MEMPOOL_FREE(pool, buf) do { \
|
||||
if (buf) g_h.funcs->_h_free(buf); \
|
||||
} while (0);
|
||||
|
||||
#endif // H_USE_MEMPOOL
|
||||
|
||||
/*
|
||||
* contains common util functions
|
||||
*/
|
||||
|
||||
// memory functions used by ESP-Hosted common mempool
|
||||
void * transport_util_malloc(size_t size, hosted_mem_cap_t cap);
|
||||
void * transport_util_calloc(size_t num_elem, size_t size_elem, hosted_mem_cap_t cap);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,807 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/** Includes **/
|
||||
|
||||
#include "drivers/bt/hci_drv.h"
|
||||
|
||||
#include "endian.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_hosted_log.h"
|
||||
#include "transport_drv.h"
|
||||
#include "stats.h"
|
||||
#include "esp_hosted_power_save.h"
|
||||
#include "esp_hosted_transport_config.h"
|
||||
#include "power_save_drv.h"
|
||||
#include "esp_hosted_bt.h"
|
||||
#include "port_esp_hosted_host_os.h"
|
||||
|
||||
#include "mempool.h"
|
||||
#include "transport_util.h"
|
||||
|
||||
static const char TAG[] = "H_UART_DRV";
|
||||
|
||||
#if H_USE_MEMPOOL
|
||||
/*
|
||||
* Tx is expected to be mainly zerocopy tx of packets allocated in transport_drv,
|
||||
* so a minimal Tx mempool is required to handle that, plus serial and bt data
|
||||
*
|
||||
* Rx needs a larger mempool based on expected Rx packets of:
|
||||
* - network data (largest user)
|
||||
* - serial data (minimal)
|
||||
* - bt data (minimal)
|
||||
*/
|
||||
|
||||
#define MIN_MEMPOOL_BT_PACKETS 3
|
||||
#define MIN_MEMPOOL_SERIAL_PACKETS 3
|
||||
#define MIN_MEMPOOL_NET_PACKETS 5
|
||||
|
||||
#define MIN_MEMPOOL_REQ (MIN_MEMPOOL_BT_PACKETS + MIN_MEMPOOL_SERIAL_PACKETS + MIN_MEMPOOL_NET_PACKETS)
|
||||
#endif
|
||||
|
||||
// UART is low throughput, so throttling should not be needed
|
||||
#define USE_DATA_THROTTLING (0)
|
||||
|
||||
static void h_uart_write_task(void const* pvParameters);
|
||||
static void h_uart_read_task(void const* pvParameters);
|
||||
#if USE_DATA_THROTTLING
|
||||
static int update_flow_ctrl(uint8_t *rxbuff);
|
||||
#endif
|
||||
|
||||
/* TODO to move this in transport drv */
|
||||
extern transport_channel_t *chan_arr[ESP_MAX_IF];
|
||||
|
||||
static void * h_uart_write_task_info;
|
||||
static void * h_uart_read_task_info;
|
||||
static void * h_uart_process_rx_task_info;
|
||||
|
||||
static void * uart_handle = NULL;
|
||||
|
||||
static queue_handle_t to_slave_queue[MAX_PRIORITY_QUEUES];
|
||||
static semaphore_handle_t sem_to_slave_queue;
|
||||
static queue_handle_t from_slave_queue[MAX_PRIORITY_QUEUES];
|
||||
static semaphore_handle_t sem_from_slave_queue;
|
||||
|
||||
// one-time trigger to start write thread
|
||||
static bool uart_start_write_thread = false;
|
||||
|
||||
#if H_USE_MEMPOOL
|
||||
/* Create mempool for cache mallocs */
|
||||
static struct hosted_mempool_t * buf_mp_g;
|
||||
#endif
|
||||
|
||||
static inline void h_uart_mempool_create(int tx_q_size, int rx_q_size)
|
||||
{
|
||||
#if H_USE_MEMPOOL
|
||||
MEM_DUMP("h_uart_mempool_create");
|
||||
hosted_mempool_config_t config = {
|
||||
.pre_allocated_mem = NULL,
|
||||
.pre_allocated_mem_size = 0,
|
||||
// allocate enough blocks to handle full RX and possible peak tx requests
|
||||
.num_blocks = rx_q_size + MIN_MEMPOOL_REQ,
|
||||
.block_size = MAX_UART_BUFFER_SIZE,
|
||||
.alignment_in_bytes = HOSTED_MEM_ALIGNMENT_64,
|
||||
.malloc = transport_util_malloc,
|
||||
.calloc = transport_util_calloc,
|
||||
.memset = g_h.funcs->_h_memset,
|
||||
.free = g_h.funcs->_h_free,
|
||||
};
|
||||
buf_mp_g = hosted_mempool_create(&config);
|
||||
assert(buf_mp_g);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void h_uart_mempool_destroy(void)
|
||||
{
|
||||
#if H_USE_MEMPOOL
|
||||
hosted_mempool_destroy(buf_mp_g);
|
||||
buf_mp_g = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void *h_uart_buffer_alloc(uint need_memset)
|
||||
{
|
||||
MEMPOOL_ALLOC(buf_mp_g, MAX_UART_BUFFER_SIZE, need_memset);
|
||||
}
|
||||
|
||||
static inline void h_uart_buffer_free(void *buf)
|
||||
{
|
||||
MEMPOOL_FREE(buf_mp_g, buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a packet to the UART bus
|
||||
* Returns ESP_OK on success, ESP_FAIL on failure
|
||||
*/
|
||||
static int h_uart_write_packet(interface_buffer_handle_t *buf_handle)
|
||||
{
|
||||
uint16_t len = 0;
|
||||
uint8_t *sendbuf = NULL;
|
||||
void (*free_func)(void* ptr) = NULL;
|
||||
uint8_t * payload = NULL;
|
||||
struct esp_payload_header * payload_header = NULL;
|
||||
int tx_len_to_send;
|
||||
int tx_len;
|
||||
int result = ESP_OK;
|
||||
|
||||
if (unlikely(!buf_handle))
|
||||
return ESP_FAIL;
|
||||
|
||||
len = buf_handle->payload_len;
|
||||
|
||||
if (unlikely(!buf_handle->flag && !len)) {
|
||||
ESP_LOGE(TAG, "%s: Empty len", __func__);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (!buf_handle->payload_zcopy) {
|
||||
sendbuf = h_uart_buffer_alloc(MEMSET_REQUIRED);
|
||||
if (!sendbuf) {
|
||||
ESP_LOGE(TAG, "uart buff malloc failed");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
free_func = h_uart_buffer_free;
|
||||
} else {
|
||||
sendbuf = buf_handle->payload;
|
||||
free_func = buf_handle->free_buf_handle;
|
||||
}
|
||||
|
||||
if (buf_handle->payload_len > MAX_UART_BUFFER_SIZE - sizeof(struct esp_payload_header)) {
|
||||
ESP_LOGE(TAG, "Pkt len [%u] > Max [%u]. Drop",
|
||||
buf_handle->payload_len, MAX_UART_BUFFER_SIZE - sizeof(struct esp_payload_header));
|
||||
result = ESP_FAIL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Form Tx header */
|
||||
payload_header = (struct esp_payload_header *) sendbuf;
|
||||
payload = sendbuf + sizeof(struct esp_payload_header);
|
||||
|
||||
payload_header->len = htole16(len);
|
||||
payload_header->offset = htole16(sizeof(struct esp_payload_header));
|
||||
payload_header->if_type = buf_handle->if_type;
|
||||
payload_header->if_num = buf_handle->if_num;
|
||||
payload_header->seq_num = htole16(buf_handle->seq_num);
|
||||
payload_header->flags = buf_handle->flag;
|
||||
|
||||
if (payload_header->if_type == ESP_HCI_IF) {
|
||||
// special handling for HCI
|
||||
if (!buf_handle->payload_zcopy) {
|
||||
// copy first byte of payload into header
|
||||
payload_header->hci_pkt_type = buf_handle->payload[0];
|
||||
// adjust actual payload len
|
||||
len -= 1;
|
||||
payload_header->len = htole16(len);
|
||||
g_h.funcs->_h_memcpy(payload, &buf_handle->payload[1], len);
|
||||
}
|
||||
} else {
|
||||
if (!buf_handle->payload_zcopy) {
|
||||
g_h.funcs->_h_memcpy(payload, buf_handle->payload, len);
|
||||
}
|
||||
}
|
||||
|
||||
#if H_UART_CHECKSUM
|
||||
payload_header->checksum = htole16(compute_checksum(sendbuf,
|
||||
sizeof(struct esp_payload_header) + len));
|
||||
#endif
|
||||
|
||||
tx_len_to_send = len + sizeof(struct esp_payload_header);
|
||||
tx_len = g_h.funcs->_h_uart_write(uart_handle, sendbuf, tx_len_to_send);
|
||||
if (tx_len != tx_len_to_send) {
|
||||
ESP_LOGE(TAG, "failed to send uart data");
|
||||
result = ESP_FAIL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
#if ESP_PKT_STATS
|
||||
if (buf_handle->if_type == ESP_STA_IF)
|
||||
pkt_stats.sta_tx_out++;
|
||||
#endif
|
||||
|
||||
done:
|
||||
if (len && !buf_handle->payload_zcopy) {
|
||||
/* free allocated buffer, only if zerocopy is not requested */
|
||||
H_FREE_PTR_WITH_FUNC(buf_handle->free_buf_handle, buf_handle->priv_buffer_handle);
|
||||
}
|
||||
H_FREE_PTR_WITH_FUNC(free_func, sendbuf);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void h_uart_write_task(void const* pvParameters)
|
||||
{
|
||||
interface_buffer_handle_t buf_handle = {0};
|
||||
uint8_t tx_needed = 1;
|
||||
|
||||
while (!uart_start_write_thread)
|
||||
g_h.funcs->_h_msleep(10);
|
||||
|
||||
ESP_LOGD(TAG, "h_uart_write_task: write thread started");
|
||||
|
||||
while (1) {
|
||||
/* Check if higher layers have anything to transmit */
|
||||
g_h.funcs->_h_get_semaphore(sem_to_slave_queue, HOSTED_BLOCK_MAX);
|
||||
|
||||
/* Tx msg is present as per sem */
|
||||
if (g_h.funcs->_h_dequeue_item(to_slave_queue[PRIO_Q_SERIAL], &buf_handle, 0))
|
||||
if (g_h.funcs->_h_dequeue_item(to_slave_queue[PRIO_Q_BT], &buf_handle, 0))
|
||||
if (g_h.funcs->_h_dequeue_item(to_slave_queue[PRIO_Q_OTHERS], &buf_handle, 0)) {
|
||||
tx_needed = 0; /* No Tx msg */
|
||||
}
|
||||
|
||||
if (!tx_needed)
|
||||
continue;
|
||||
|
||||
/* Send the packet */
|
||||
h_uart_write_packet(&buf_handle);
|
||||
}
|
||||
}
|
||||
|
||||
#if USE_DATA_THROTTLING
|
||||
static int update_flow_ctrl(uint8_t *rxbuff)
|
||||
{
|
||||
struct esp_payload_header * h = (struct esp_payload_header *)rxbuff;
|
||||
if (h->throttle_cmd) {
|
||||
if (h->throttle_cmd == H_FLOW_CTRL_ON) {
|
||||
wifi_tx_throttling = 1;
|
||||
}
|
||||
if (h->throttle_cmd == H_FLOW_CTRL_OFF) {
|
||||
wifi_tx_throttling = 0;
|
||||
}
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void h_uart_process_rx_task(void const* pvParameters)
|
||||
{
|
||||
interface_buffer_handle_t buf_handle_l = {0};
|
||||
interface_buffer_handle_t *buf_handle = NULL;
|
||||
int ret = 0;
|
||||
|
||||
struct esp_priv_event *event = NULL;
|
||||
|
||||
while (true) {
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
if (is_transport_rx_ready()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (1) {
|
||||
g_h.funcs->_h_get_semaphore(sem_from_slave_queue, HOSTED_BLOCK_MAX);
|
||||
|
||||
if (g_h.funcs->_h_dequeue_item(from_slave_queue[PRIO_Q_SERIAL], &buf_handle_l, 0))
|
||||
if (g_h.funcs->_h_dequeue_item(from_slave_queue[PRIO_Q_BT], &buf_handle_l, 0))
|
||||
if (g_h.funcs->_h_dequeue_item(from_slave_queue[PRIO_Q_OTHERS], &buf_handle_l, 0)) {
|
||||
ESP_LOGI(TAG, "No element in any queue found");
|
||||
continue;
|
||||
}
|
||||
|
||||
buf_handle = &buf_handle_l;
|
||||
|
||||
ESP_HEXLOGV("h_uart_rx", buf_handle->payload, buf_handle->payload_len, 32);
|
||||
|
||||
if (buf_handle->if_type == ESP_SERIAL_IF) {
|
||||
/* serial interface path */
|
||||
serial_rx_handler(buf_handle);
|
||||
} else if((buf_handle->if_type == ESP_STA_IF) ||
|
||||
(buf_handle->if_type == ESP_AP_IF)) {
|
||||
#if 1
|
||||
if (chan_arr[buf_handle->if_type] && chan_arr[buf_handle->if_type]->rx) {
|
||||
/* TODO : Need to abstract heap_caps_malloc */
|
||||
uint8_t * copy_payload = (uint8_t *)g_h.funcs->_h_malloc(buf_handle->payload_len);
|
||||
assert(copy_payload);
|
||||
assert(buf_handle->payload_len);
|
||||
assert(buf_handle->payload);
|
||||
memcpy(copy_payload, buf_handle->payload, buf_handle->payload_len);
|
||||
H_FREE_PTR_WITH_FUNC(buf_handle->free_buf_handle, buf_handle->priv_buffer_handle);
|
||||
|
||||
ret = chan_arr[buf_handle->if_type]->rx(chan_arr[buf_handle->if_type]->api_chan,
|
||||
copy_payload, copy_payload, buf_handle->payload_len);
|
||||
#ifndef ESP_WIFI_REMOTE_VERSION // not defined in older versions of wifi-remote
|
||||
if (unlikely(ret))
|
||||
HOSTED_FREE(copy_payload);
|
||||
#else
|
||||
#if ESP_WIFI_REMOTE_VERSION < ESP_WIFI_REMOTE_VERSION_VAL(1,3,1)
|
||||
if (unlikely(ret))
|
||||
HOSTED_FREE(copy_payload);
|
||||
#else
|
||||
(void)ret; // to silence 'unused variable' warning
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
if (chan_arr[buf_handle->if_type] && chan_arr[buf_handle->if_type]->rx) {
|
||||
chan_arr[buf_handle->if_type]->rx(chan_arr[buf_handle->if_type]->api_chan,
|
||||
buf_handle->payload, NULL, buf_handle->payload_len);
|
||||
}
|
||||
#endif
|
||||
} else if (buf_handle->if_type == ESP_PRIV_IF) {
|
||||
process_priv_communication(buf_handle);
|
||||
hci_drv_show_configuration();
|
||||
/* priv transaction received */
|
||||
ESP_LOGI(TAG, "Received INIT event");
|
||||
uart_start_write_thread = true;
|
||||
|
||||
event = (struct esp_priv_event *) (buf_handle->payload);
|
||||
if (event->event_type != ESP_PRIV_EVENT_INIT) {
|
||||
/* User can reuse this type of transaction */
|
||||
}
|
||||
} else if (buf_handle->if_type == ESP_HCI_IF) {
|
||||
hci_rx_handler(buf_handle->payload, buf_handle->payload_len);
|
||||
} else if (buf_handle->if_type == ESP_TEST_IF) {
|
||||
#if TEST_RAW_TP
|
||||
update_test_raw_tp_rx_len(buf_handle->payload_len +
|
||||
H_ESP_PAYLOAD_HEADER_OFFSET);
|
||||
#endif
|
||||
} else {
|
||||
ESP_LOGW(TAG, "unknown type %d ", buf_handle->if_type);
|
||||
}
|
||||
|
||||
#if ESP_PKT_STATS
|
||||
if (buf_handle->if_type == ESP_STA_IF)
|
||||
pkt_stats.sta_rx_out++;
|
||||
#endif
|
||||
|
||||
/* Free buffer handle */
|
||||
/* When buffer offloaded to other module, that module is
|
||||
* responsible for freeing buffer. In case not offloaded or
|
||||
* failed to offload, buffer should be freed here.
|
||||
*/
|
||||
if (!buf_handle->payload_zcopy) {
|
||||
H_FREE_PTR_WITH_FUNC(buf_handle->free_buf_handle,
|
||||
buf_handle->priv_buffer_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pushes received packet data on to rx queue
|
||||
static esp_err_t push_to_rx_queue(uint8_t * rxbuff, uint16_t len, uint16_t offset)
|
||||
{
|
||||
uint8_t pkt_prio = PRIO_Q_OTHERS;
|
||||
struct esp_payload_header *h= NULL;
|
||||
interface_buffer_handle_t buf_handle;
|
||||
|
||||
h = (struct esp_payload_header *)rxbuff;
|
||||
|
||||
memset(&buf_handle, 0, sizeof(interface_buffer_handle_t));
|
||||
|
||||
buf_handle.priv_buffer_handle = rxbuff;
|
||||
buf_handle.free_buf_handle = h_uart_buffer_free;
|
||||
buf_handle.payload_len = len;
|
||||
buf_handle.if_type = h->if_type;
|
||||
buf_handle.if_num = h->if_num;
|
||||
buf_handle.payload = rxbuff + offset;
|
||||
buf_handle.seq_num = le16toh(h->seq_num);
|
||||
buf_handle.flag = h->flags;
|
||||
|
||||
if (buf_handle.if_type == ESP_SERIAL_IF)
|
||||
pkt_prio = PRIO_Q_SERIAL;
|
||||
else if (buf_handle.if_type == ESP_HCI_IF)
|
||||
pkt_prio = PRIO_Q_BT;
|
||||
/* else OTHERS by default */
|
||||
|
||||
g_h.funcs->_h_queue_item(from_slave_queue[pkt_prio], &buf_handle, HOSTED_BLOCK_MAX);
|
||||
g_h.funcs->_h_post_semaphore(sem_from_slave_queue);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static int is_valid_uart_rx_packet(uint8_t *rxbuff_a, uint16_t *len_a, uint16_t *offset_a)
|
||||
{
|
||||
struct esp_payload_header * h = (struct esp_payload_header *)rxbuff_a;
|
||||
uint16_t len = 0, offset = 0;
|
||||
#if H_UART_CHECKSUM
|
||||
uint16_t rx_checksum = 0, checksum = 0;
|
||||
#endif
|
||||
|
||||
if (!h || !len_a || !offset_a)
|
||||
return 0;
|
||||
|
||||
/* Fetch length and offset from payload header */
|
||||
len = le16toh(h->len);
|
||||
offset = le16toh(h->offset);
|
||||
|
||||
if ((!len) ||
|
||||
(len > MAX_PAYLOAD_SIZE) ||
|
||||
(offset != sizeof(struct esp_payload_header))) {
|
||||
|
||||
/* Free up buffer, as one of following -
|
||||
* 1. no payload to process
|
||||
* 2. input packet size > driver capacity
|
||||
* 3. payload header size mismatch,
|
||||
* wrong header/bit packing?
|
||||
* */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if H_UART_CHECKSUM
|
||||
rx_checksum = le16toh(h->checksum);
|
||||
h->checksum = 0;
|
||||
checksum = compute_checksum((uint8_t*)h, len + offset);
|
||||
|
||||
if (checksum != rx_checksum) {
|
||||
ESP_LOGE(TAG, "UART RX rx_chksum[%u] != checksum[%u]. Drop.",
|
||||
checksum, rx_checksum);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ESP_PKT_STATS
|
||||
if (h->if_type == ESP_STA_IF)
|
||||
pkt_stats.sta_rx_in++;
|
||||
#endif
|
||||
|
||||
*len_a = len;
|
||||
*offset_a = offset;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uint8_t * uart_scratch_buf = NULL;
|
||||
|
||||
static void h_uart_read_task(void const* pvParameters)
|
||||
{
|
||||
struct esp_payload_header *header = NULL;
|
||||
uint16_t len = 0, offset = 0;
|
||||
#if HOSTED_UART_CHECKSUM
|
||||
uint16_t rx_checksum = 0, checksum = 0;
|
||||
#endif
|
||||
int bytes_read;
|
||||
int total_len;
|
||||
uint8_t * rxbuff = NULL;
|
||||
|
||||
// wait for transport to be in ready
|
||||
while (true) {
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
if (is_transport_rx_ready()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
create_debugging_tasks();
|
||||
|
||||
if (!uart_scratch_buf) {
|
||||
uart_scratch_buf = malloc(MAX_UART_BUFFER_SIZE);
|
||||
assert(uart_scratch_buf);
|
||||
}
|
||||
|
||||
header = (struct esp_payload_header *)uart_scratch_buf;
|
||||
|
||||
while (1) {
|
||||
// get the header
|
||||
bytes_read = g_h.funcs->_h_uart_read(uart_handle, uart_scratch_buf,
|
||||
sizeof(struct esp_payload_header));
|
||||
ESP_LOGD(TAG, "Read %d bytes (header)", bytes_read);
|
||||
if (bytes_read < sizeof(struct esp_payload_header)) {
|
||||
ESP_LOGE(TAG, "Failed to read header");
|
||||
continue;
|
||||
}
|
||||
|
||||
len = le16toh(header->len);
|
||||
offset = le16toh(header->offset);
|
||||
if (offset != sizeof(struct esp_payload_header)) {
|
||||
ESP_LOGE(TAG, "invalid offset in header");
|
||||
continue;
|
||||
}
|
||||
total_len = len + sizeof(struct esp_payload_header);
|
||||
if (total_len > MAX_UART_BUFFER_SIZE) {
|
||||
ESP_LOGE(TAG, "incoming data too big: %d", total_len);
|
||||
continue;
|
||||
}
|
||||
|
||||
// get the data, if any
|
||||
if (len) {
|
||||
bytes_read = g_h.funcs->_h_uart_read(uart_handle, &uart_scratch_buf[offset], len);
|
||||
ESP_LOGD(TAG, "Read %d bytes (payload)", bytes_read);
|
||||
if (bytes_read < len) {
|
||||
ESP_LOGE(TAG, "Failed to read payload");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
rxbuff = h_uart_buffer_alloc(MEMSET_REQUIRED);
|
||||
assert(rxbuff);
|
||||
|
||||
// copy data to the buffer
|
||||
memcpy(rxbuff, uart_scratch_buf, total_len);
|
||||
|
||||
#if USE_DATA_THROTTLING
|
||||
if (update_flow_ctrl(rxbuff)) {
|
||||
// detected and updated flow control
|
||||
// no need to further process the packet
|
||||
h_uart_buffer_free(rxbuff);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Drop packet if no processing needed */
|
||||
if (!is_valid_uart_rx_packet(rxbuff, &len, &offset)) {
|
||||
/* Free up buffer, as one of following -
|
||||
* 1. no payload to process
|
||||
* 2. input packet size > driver capacity
|
||||
* 3. payload header size mismatch,
|
||||
* wrong header/bit packing?
|
||||
* */
|
||||
ESP_LOGE(TAG, "Dropping packet");
|
||||
h_uart_buffer_free(rxbuff);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (push_to_rx_queue(rxbuff, len, offset)) {
|
||||
ESP_LOGE(TAG, "Failed to push Rx packet to queue");
|
||||
h_uart_buffer_free(rxbuff);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *bus_init_internal(void)
|
||||
{
|
||||
uint8_t prio_q_idx = 0;
|
||||
|
||||
sem_to_slave_queue = g_h.funcs->_h_create_semaphore(H_UART_TX_QUEUE_SIZE*MAX_PRIORITY_QUEUES);
|
||||
assert(sem_to_slave_queue);
|
||||
g_h.funcs->_h_get_semaphore(sem_to_slave_queue, 0);
|
||||
|
||||
sem_from_slave_queue = g_h.funcs->_h_create_semaphore(H_UART_RX_QUEUE_SIZE*MAX_PRIORITY_QUEUES);
|
||||
assert(sem_from_slave_queue);
|
||||
g_h.funcs->_h_get_semaphore(sem_from_slave_queue, 0);
|
||||
|
||||
for (prio_q_idx=0; prio_q_idx<MAX_PRIORITY_QUEUES;prio_q_idx++) {
|
||||
/* Queue - rx */
|
||||
from_slave_queue[prio_q_idx] = g_h.funcs->_h_create_queue(H_UART_RX_QUEUE_SIZE, sizeof(interface_buffer_handle_t));
|
||||
assert(from_slave_queue[prio_q_idx]);
|
||||
|
||||
/* Queue - tx */
|
||||
to_slave_queue[prio_q_idx] = g_h.funcs->_h_create_queue(H_UART_TX_QUEUE_SIZE, sizeof(interface_buffer_handle_t));
|
||||
assert(to_slave_queue[prio_q_idx]);
|
||||
}
|
||||
|
||||
h_uart_mempool_create(H_UART_TX_QUEUE_SIZE, H_UART_RX_QUEUE_SIZE);
|
||||
|
||||
uart_handle = g_h.funcs->_h_bus_init();
|
||||
if (!uart_handle) {
|
||||
ESP_LOGE(TAG, "could not create uart handle, exiting\n");
|
||||
assert(uart_handle);
|
||||
}
|
||||
|
||||
h_uart_process_rx_task_info = g_h.funcs->_h_thread_create("uart_process_rx",
|
||||
DFLT_TASK_PRIO, DFLT_TASK_STACK_SIZE, h_uart_process_rx_task, NULL);
|
||||
|
||||
h_uart_read_task_info = g_h.funcs->_h_thread_create("uart_rx",
|
||||
DFLT_TASK_PRIO, DFLT_TASK_STACK_SIZE, h_uart_read_task, NULL);
|
||||
|
||||
h_uart_write_task_info = g_h.funcs->_h_thread_create("uart_tx",
|
||||
DFLT_TASK_PRIO, DFLT_TASK_STACK_SIZE, h_uart_write_task, NULL);
|
||||
|
||||
return uart_handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send to slave
|
||||
* @param iface_type -type of interface
|
||||
* iface_num - interface number
|
||||
* payload_buf - tx buffer
|
||||
* payload_len - size of tx buffer
|
||||
* buffer_to_free - buffer to be freed after tx
|
||||
* free_buf_func - function used to free buffer_to_free
|
||||
* flags - flags to set
|
||||
* @retval int - ESP_OK or ESP_FAIL
|
||||
*/
|
||||
int esp_hosted_tx(uint8_t iface_type, uint8_t iface_num,
|
||||
uint8_t *payload_buf, uint16_t payload_len, uint8_t buff_zcopy,
|
||||
uint8_t *buffer_to_free, void (*free_buf_func)(void *ptr), uint8_t flags)
|
||||
{
|
||||
interface_buffer_handle_t buf_handle = {0};
|
||||
void (*free_func)(void* ptr) = NULL;
|
||||
uint8_t pkt_prio = PRIO_Q_OTHERS;
|
||||
uint8_t transport_up = is_transport_tx_ready();
|
||||
|
||||
if (free_buf_func)
|
||||
free_func = free_buf_func;
|
||||
|
||||
if ((flags == 0 || flags == MORE_FRAGMENT) &&
|
||||
(!payload_buf || !payload_len || (payload_len > MAX_PAYLOAD_SIZE) || !transport_up)) {
|
||||
ESP_LOGE(TAG, "tx fail: NULL buff, invalid len (%u) or len > max len (%u), transport_up(%u))",
|
||||
payload_len, MAX_PAYLOAD_SIZE, transport_up);
|
||||
H_FREE_PTR_WITH_FUNC(free_func, buffer_to_free);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
buf_handle.payload_zcopy = buff_zcopy;
|
||||
buf_handle.if_type = iface_type;
|
||||
buf_handle.if_num = iface_num;
|
||||
buf_handle.payload_len = payload_len;
|
||||
buf_handle.payload = payload_buf;
|
||||
buf_handle.priv_buffer_handle = buffer_to_free;
|
||||
buf_handle.free_buf_handle = free_func;
|
||||
buf_handle.flag = flags;
|
||||
|
||||
if (buf_handle.if_type == ESP_SERIAL_IF)
|
||||
pkt_prio = PRIO_Q_SERIAL;
|
||||
else if (buf_handle.if_type == ESP_HCI_IF)
|
||||
pkt_prio = PRIO_Q_BT;
|
||||
|
||||
g_h.funcs->_h_queue_item(to_slave_queue[pkt_prio], &buf_handle, HOSTED_BLOCK_MAX);
|
||||
g_h.funcs->_h_post_semaphore(sem_to_slave_queue);
|
||||
|
||||
#if ESP_PKT_STATS
|
||||
if (buf_handle.if_type == ESP_STA_IF)
|
||||
pkt_stats.sta_tx_in_pass++;
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void bus_deinit_internal(void *bus_handle)
|
||||
{
|
||||
uint8_t prio_q_idx = 0;
|
||||
|
||||
/* Stop threads */
|
||||
if (h_uart_write_task_info) {
|
||||
g_h.funcs->_h_thread_cancel(h_uart_write_task_info);
|
||||
h_uart_write_task_info = NULL;
|
||||
}
|
||||
|
||||
if (h_uart_read_task_info) {
|
||||
g_h.funcs->_h_thread_cancel(h_uart_read_task_info);
|
||||
h_uart_read_task_info = NULL;
|
||||
}
|
||||
|
||||
if (h_uart_process_rx_task_info) {
|
||||
g_h.funcs->_h_thread_cancel(h_uart_process_rx_task_info);
|
||||
h_uart_process_rx_task_info = NULL;
|
||||
}
|
||||
|
||||
/* Clean up queues */
|
||||
for (prio_q_idx = 0; prio_q_idx < MAX_PRIORITY_QUEUES; prio_q_idx++) {
|
||||
if (from_slave_queue[prio_q_idx]) {
|
||||
g_h.funcs->_h_destroy_queue(from_slave_queue[prio_q_idx]);
|
||||
from_slave_queue[prio_q_idx] = NULL;
|
||||
}
|
||||
|
||||
if (to_slave_queue[prio_q_idx]) {
|
||||
g_h.funcs->_h_destroy_queue(to_slave_queue[prio_q_idx]);
|
||||
to_slave_queue[prio_q_idx] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clean up semaphores */
|
||||
if (sem_to_slave_queue) {
|
||||
g_h.funcs->_h_destroy_semaphore(sem_to_slave_queue);
|
||||
sem_to_slave_queue = NULL;
|
||||
}
|
||||
|
||||
if (sem_from_slave_queue) {
|
||||
g_h.funcs->_h_destroy_semaphore(sem_from_slave_queue);
|
||||
sem_from_slave_queue = NULL;
|
||||
}
|
||||
|
||||
/* Deinitialize the UART bus */
|
||||
if (uart_handle) {
|
||||
ESP_LOGI(TAG, "Deinitializing UART bus");
|
||||
if (bus_handle) {
|
||||
g_h.funcs->_h_bus_deinit(bus_handle);
|
||||
}
|
||||
uart_handle = NULL;
|
||||
}
|
||||
|
||||
h_uart_mempool_destroy();
|
||||
}
|
||||
|
||||
int ensure_slave_bus_ready(void *bus_handle)
|
||||
{
|
||||
esp_err_t res = ESP_OK;
|
||||
gpio_pin_t reset_pin = { .port = H_GPIO_PORT_RESET, .pin = H_GPIO_PIN_RESET };
|
||||
|
||||
if (ESP_TRANSPORT_OK != esp_hosted_transport_get_reset_config(&reset_pin)) {
|
||||
ESP_LOGE(TAG, "Unable to get RESET config for transport");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
assert(reset_pin.pin != -1);
|
||||
|
||||
release_slave_reset_gpio_post_wakeup();
|
||||
|
||||
if (!esp_hosted_woke_from_power_save()) {
|
||||
/* Reset the slave */
|
||||
ESP_LOGI(TAG, "Resetting slave on UART bus with pin %d", reset_pin.pin);
|
||||
g_h.funcs->_h_config_gpio(reset_pin.port, reset_pin.pin, H_GPIO_MODE_DEF_OUTPUT);
|
||||
g_h.funcs->_h_write_gpio(reset_pin.port, reset_pin.pin, H_RESET_VAL_ACTIVE);
|
||||
g_h.funcs->_h_msleep(10);
|
||||
g_h.funcs->_h_write_gpio(reset_pin.port, reset_pin.pin, H_RESET_VAL_INACTIVE);
|
||||
g_h.funcs->_h_msleep(10);
|
||||
g_h.funcs->_h_write_gpio(reset_pin.port, reset_pin.pin, H_RESET_VAL_ACTIVE);
|
||||
// flush input
|
||||
if (uart_handle) {
|
||||
g_h.funcs->_h_uart_flush_input(uart_handle);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "uart handle is NULL: cannot flush");
|
||||
}
|
||||
g_h.funcs->_h_msleep(1500);
|
||||
} else {
|
||||
stop_host_power_save();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int bus_inform_slave_host_power_save_start(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Inform slave, host power save is started");
|
||||
int ret = ESP_OK;
|
||||
|
||||
/*
|
||||
* If the write thread is not started yet (which happens after receiving INIT event),
|
||||
* we need to send the power save message directly to avoid deadlock.
|
||||
* Otherwise, use the normal queue mechanism.
|
||||
*/
|
||||
if (!uart_start_write_thread) {
|
||||
interface_buffer_handle_t buf_handle = {0};
|
||||
|
||||
buf_handle.payload_zcopy = H_BUFF_NO_ZEROCOPY;
|
||||
buf_handle.if_type = ESP_SERIAL_IF;
|
||||
buf_handle.if_num = 0;
|
||||
buf_handle.payload_len = 0;
|
||||
buf_handle.payload = NULL;
|
||||
buf_handle.priv_buffer_handle = NULL;
|
||||
buf_handle.free_buf_handle = NULL;
|
||||
buf_handle.flag = FLAG_POWER_SAVE_STARTED;
|
||||
|
||||
ESP_LOGI(TAG, "Sending power save start message directly");
|
||||
ret = h_uart_write_packet(&buf_handle);
|
||||
} else {
|
||||
/* Use normal queue mechanism */
|
||||
ret = esp_hosted_tx(ESP_SERIAL_IF, 0, NULL, 0,
|
||||
H_BUFF_NO_ZEROCOPY, NULL, NULL, FLAG_POWER_SAVE_STARTED);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bus_inform_slave_host_power_save_stop(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Inform slave, host power save is stopped");
|
||||
int ret = ESP_OK;
|
||||
|
||||
|
||||
/*
|
||||
* If the write thread is not started yet (which happens after receiving INIT event),
|
||||
* we need to send the power save message directly to avoid deadlock.
|
||||
* Otherwise, use the normal queue mechanism.
|
||||
*/
|
||||
if (!uart_start_write_thread) {
|
||||
interface_buffer_handle_t buf_handle = {0};
|
||||
|
||||
buf_handle.payload_zcopy = H_BUFF_NO_ZEROCOPY;
|
||||
buf_handle.if_type = ESP_SERIAL_IF;
|
||||
buf_handle.if_num = 0;
|
||||
buf_handle.payload_len = 0;
|
||||
buf_handle.payload = NULL;
|
||||
buf_handle.priv_buffer_handle = NULL;
|
||||
buf_handle.free_buf_handle = NULL;
|
||||
buf_handle.flag = FLAG_POWER_SAVE_STOPPED;
|
||||
|
||||
ESP_LOGI(TAG, "Sending power save start message directly");
|
||||
ret = h_uart_write_packet(&buf_handle);
|
||||
} else {
|
||||
/* Use normal queue mechanism */
|
||||
ret = esp_hosted_tx(ESP_SERIAL_IF, 0, NULL, 0,
|
||||
H_BUFF_NO_ZEROCOPY, NULL, NULL, FLAG_POWER_SAVE_STOPPED);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void check_if_max_freq_used(uint8_t chip_type)
|
||||
{
|
||||
/* TODO: Implement */
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/** Includes **/
|
||||
#include <string.h>
|
||||
#include "serial_if.h"
|
||||
#include "serial_drv.h"
|
||||
#include "port_esp_hosted_host_log.h"
|
||||
|
||||
DEFINE_LOG_TAG(serial_if);
|
||||
|
||||
/** Constants/Macros **/
|
||||
#define SUCCESS 0
|
||||
#define FAILURE -1
|
||||
|
||||
|
||||
#define PROTO_PSER_TLV_T_EPNAME 0x01
|
||||
#define PROTO_PSER_TLV_T_DATA 0x02
|
||||
|
||||
|
||||
/** Exported variables **/
|
||||
struct serial_drv_handle_t* serial_handle = NULL;
|
||||
|
||||
/*
|
||||
* The data written on serial driver file, `SERIAL_IF_FILE` from esp_hosted_transport.h
|
||||
* In TLV i.e. Type Length Value format, to transfer data between host and ESP32
|
||||
* | type | length | value |
|
||||
* Types are 0x01 : for endpoint name
|
||||
* 0x02 : for data
|
||||
* length is respective value field's data length in 16 bits
|
||||
* value is actual data to be transferred
|
||||
*/
|
||||
|
||||
uint16_t compose_tlv(uint8_t* buf, uint8_t* data, uint16_t data_length)
|
||||
{
|
||||
const char* ep_name = RPC_EP_NAME_RSP;
|
||||
uint16_t ep_length = strlen(ep_name);
|
||||
uint16_t count = 0;
|
||||
uint8_t idx;
|
||||
|
||||
buf[count] = PROTO_PSER_TLV_T_EPNAME;
|
||||
count++;
|
||||
buf[count] = (ep_length & 0xFF);
|
||||
count++;
|
||||
buf[count] = ((ep_length >> 8) & 0xFF);
|
||||
count++;
|
||||
|
||||
for (idx = 0; idx < ep_length; idx++) {
|
||||
buf[count] = ep_name[idx];
|
||||
count++;
|
||||
}
|
||||
|
||||
buf[count]= PROTO_PSER_TLV_T_DATA;
|
||||
count++;
|
||||
buf[count] = (data_length & 0xFF);
|
||||
count++;
|
||||
buf[count] = ((data_length >> 8) & 0xFF);
|
||||
count++;
|
||||
g_h.funcs->_h_memcpy(&buf[count], data, data_length);
|
||||
count = count + data_length;
|
||||
return count;
|
||||
}
|
||||
|
||||
uint8_t parse_tlv(uint8_t* data, uint32_t* pro_len)
|
||||
{
|
||||
const char* ep_name = RPC_EP_NAME_RSP;
|
||||
const char* ep_name2 = RPC_EP_NAME_EVT;
|
||||
uint64_t len = 0;
|
||||
uint16_t val_len = 0;
|
||||
if (data[len] == PROTO_PSER_TLV_T_EPNAME) {
|
||||
len++;
|
||||
val_len = data[len];
|
||||
len++;
|
||||
val_len = (data[len] << 8) + val_len;
|
||||
len++;
|
||||
/* Both RPC_EP_NAME_RSP and RPC_EP_NAME_EvT
|
||||
* are expected to have exactly same length
|
||||
**/
|
||||
if (val_len == strlen(ep_name)) {
|
||||
if ((strncmp((char* )&data[len],ep_name,strlen(ep_name)) == 0) ||
|
||||
(strncmp((char* )&data[len],ep_name2,strlen(ep_name2)) == 0)) {
|
||||
len = len + strlen(ep_name);
|
||||
if (data[len] == PROTO_PSER_TLV_T_DATA) {
|
||||
len++;
|
||||
val_len = data[len];
|
||||
len++;
|
||||
val_len = (data[len] << 8) + val_len;
|
||||
len++;
|
||||
*pro_len = val_len;
|
||||
return SUCCESS;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Data Type not matched, exp %d, recvd %d\n",
|
||||
PROTO_PSER_TLV_T_DATA, data[len]);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Endpoint Name not matched, exp [%s] or [%s], recvd [%s]\n",
|
||||
ep_name, ep_name2, (char* )&data[len]);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Endpoint length not matched, exp [For %s, %lu OR For %s, %lu], recvd %d\n",
|
||||
ep_name, (long unsigned int)(strlen(ep_name)),
|
||||
ep_name2, (long unsigned int)(strlen(ep_name2)), val_len);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Endpoint type not matched, exp %d, recvd %d\n",
|
||||
PROTO_PSER_TLV_T_EPNAME, data[len]);
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
int transport_pserial_close(void)
|
||||
{
|
||||
int ret = SUCCESS;
|
||||
|
||||
ret = rpc_platform_deinit();
|
||||
if (ret != SUCCESS) {
|
||||
ESP_LOGE(TAG, "Platform deinit failed\n");
|
||||
}
|
||||
|
||||
ret = serial_drv_close(&serial_handle);
|
||||
|
||||
if (ret) {
|
||||
ESP_LOGE(TAG, "Failed to close driver interface\n");
|
||||
return FAILURE;
|
||||
}
|
||||
serial_handle = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int transport_pserial_open(void)
|
||||
{
|
||||
int ret = SUCCESS;
|
||||
const char* transport = SERIAL_IF_FILE;
|
||||
|
||||
if (serial_handle) {
|
||||
printf("Already opened returned\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
serial_handle = serial_drv_open(transport);
|
||||
if (!serial_handle) {
|
||||
printf("serial interface open failed, Is the driver loaded?\n");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
ret = rpc_platform_init();
|
||||
if (ret != SUCCESS) {
|
||||
printf("Platform init failed\n");
|
||||
transport_pserial_close();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int transport_pserial_send(uint8_t* data, uint16_t data_length)
|
||||
{
|
||||
const char* ep_name = RPC_EP_NAME_RSP;
|
||||
int count = 0, ret = 0;
|
||||
uint16_t buf_len = 0;
|
||||
uint8_t *write_buf = NULL;
|
||||
|
||||
if (!data || !data_length) {
|
||||
ESP_LOGW(TAG, "Empty RPC data, ignored");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* TLV (Type - Length - Value) structure is as follows:
|
||||
* --------------------------------------------------------------------------------------------
|
||||
* Endpoint Type | Endpoint Length | Endpoint Value | Data Type | Data Length | Data Value |
|
||||
* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
* Bytes used per field as follows:
|
||||
* --------------------------------------------------------------------------------------------
|
||||
* 1 | 2 | Endpoint length | 1 | 2 | Data length |
|
||||
* --------------------------------------------------------------------------------------------
|
||||
*/
|
||||
buf_len = SIZE_OF_TYPE + SIZE_OF_LENGTH + strlen(ep_name) +
|
||||
SIZE_OF_TYPE + SIZE_OF_LENGTH + data_length;
|
||||
|
||||
HOSTED_CALLOC(uint8_t,write_buf,buf_len,free_bufs2);
|
||||
|
||||
if (!serial_handle) {
|
||||
ESP_LOGE(TAG, "Serial connection closed?\n");
|
||||
goto free_bufs1;
|
||||
}
|
||||
|
||||
count = compose_tlv(write_buf, data, data_length);
|
||||
if (!count) {
|
||||
ESP_LOGE(TAG, "Failed to compose TX data\n");
|
||||
goto free_bufs1;
|
||||
}
|
||||
|
||||
ret = serial_drv_write(serial_handle, write_buf, count, &count);
|
||||
if (ret != SUCCESS) {
|
||||
ESP_LOGE(TAG, "Failed to write TX data\n");
|
||||
goto free_bufs2;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
free_bufs1:
|
||||
HOSTED_FREE(write_buf);
|
||||
free_bufs2:
|
||||
/* write_buf is supposed to be freed by serial_drv_write() */
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
uint8_t * transport_pserial_read(uint32_t *out_nbyte)
|
||||
{
|
||||
/* Two step parsing TLV is moved in serial_drv_read */
|
||||
return serial_drv_read(serial_handle, out_nbyte);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/** prevent recursive inclusion **/
|
||||
#ifndef __SERIAL_IF_H
|
||||
#define __SERIAL_IF_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "esp_hosted_transport.h"
|
||||
|
||||
#define SIZE_OF_TYPE 1
|
||||
#define SIZE_OF_LENGTH 2
|
||||
|
||||
/*
|
||||
* The data written on serial driver file, `SERIAL_IF_FILE` from esp_hosted_transport.h
|
||||
* In TLV i.e. Type Length Value format, to transfer data between host and ESP32
|
||||
* | type | length | value |
|
||||
* Types are 0x01 : for endpoint name
|
||||
* 0x02 : for data
|
||||
* length is respective value field's data length in 16 bits
|
||||
* value is actual data to be transferred
|
||||
*/
|
||||
uint16_t compose_tlv(uint8_t* buf, uint8_t* data, uint16_t data_length);
|
||||
|
||||
/* Parse the protobuf encoded data in format of tag, length and value
|
||||
* This will help application to decode protobuf payload and payload length
|
||||
**/
|
||||
uint8_t parse_tlv(uint8_t* data, uint32_t* pro_len);
|
||||
|
||||
/* Open the serial driver for serial operations
|
||||
**/
|
||||
int transport_pserial_open(void);
|
||||
|
||||
/* Close the serial driver for serial operations
|
||||
**/
|
||||
int transport_pserial_close(void);
|
||||
|
||||
/* Send buffer with length as argument on transport as serial interface type
|
||||
**/
|
||||
int transport_pserial_send(uint8_t* data, uint16_t data_length);
|
||||
|
||||
/* Read and return number of bytes and buffer from serial interface
|
||||
**/
|
||||
uint8_t * transport_pserial_read(uint32_t *out_nbyte);
|
||||
#endif
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __ESP_HOSTED_H__
|
||||
#define __ESP_HOSTED_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp_hosted_os_abstraction.h"
|
||||
#include "esp_hosted_api_types.h"
|
||||
#include "esp_hosted_host_fw_ver.h"
|
||||
#include "esp_hosted_misc.h"
|
||||
#include "esp_hosted_ota.h"
|
||||
#include "esp_hosted_event.h"
|
||||
#include "esp_hosted_cp_gpio.h"
|
||||
#include "esp_hosted_cp_ext_coex.h"
|
||||
|
||||
typedef struct esp_hosted_transport_config esp_hosted_config_t;
|
||||
|
||||
/* --------- Hosted Minimal APIs --------- */
|
||||
int esp_hosted_init(void);
|
||||
int esp_hosted_deinit(void);
|
||||
|
||||
int esp_hosted_connect_to_slave(void);
|
||||
int esp_hosted_get_coprocessor_fwversion(esp_hosted_coprocessor_fwver_t *ver_info);
|
||||
int esp_hosted_get_cp_info(uint32_t *cp_chip_id, char *cp_target_name, size_t cp_target_name_len);
|
||||
|
||||
/* --------- Exhaustive API list --------- */
|
||||
/*
|
||||
* 1. All Wi-Fi supported APIs
|
||||
* File: host/api/src/esp_wifi_weak.c
|
||||
*
|
||||
* 2. Communication Bus APIs (Set and get transport config)
|
||||
* File : host/api/include/esp_hosted_transport_config.h
|
||||
*
|
||||
* 3. Co-Processor OTA API
|
||||
* File : host/api/include/esp_hosted_ota.h
|
||||
*
|
||||
* 4. Hosted Event API
|
||||
* File : host/api/include/esp_hosted_event.h
|
||||
*
|
||||
* 5. GPIO Expander API
|
||||
* File : host/api/include/esp_hosted_cp_gpio.h
|
||||
*
|
||||
* 6. External Coexistence API
|
||||
* File : host/api/include/esp_hosted_cp_ext_coex.h
|
||||
*
|
||||
* 7. Host Power Save API
|
||||
* File : host/api/include/esp_hosted_power_save.h
|
||||
*
|
||||
* 8. OpenThread RCP API
|
||||
* File : host/api/include/esp_hosted_openthread.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ESP_HOSTED_H__ */
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __ESP_HOSTED_BLUEDROID_H
|
||||
#define __ESP_HOSTED_BLUEDROID_H
|
||||
|
||||
// ESP-Hosted Bluedroid interface for Host
|
||||
// Only include if using ESP-IDF Bluedroid
|
||||
|
||||
#include "esp_hosted_bt.h"
|
||||
#include "esp_bluedroid_hci.h"
|
||||
|
||||
// BT Bluedroid interface for Host
|
||||
void hosted_hci_bluedroid_open(void);
|
||||
void hosted_hci_bluedroid_close(void);
|
||||
void hosted_hci_bluedroid_send(uint8_t *data, uint16_t len);
|
||||
bool hosted_hci_bluedroid_check_send_available(void);
|
||||
esp_err_t hosted_hci_bluedroid_register_host_callback(const esp_bluedroid_hci_driver_callbacks_t *callback);
|
||||
|
||||
#endif // __ESP_HOSTED_BLUEDROID_H
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __ESP_HOSTED_BT_H
|
||||
#define __ESP_HOSTED_BT_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
// Handles BT Rx
|
||||
int hci_rx_handler(uint8_t *buf, size_t buf_len);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __ESP_HOSTED_EVENT_H__
|
||||
#define __ESP_HOSTED_EVENT_H__
|
||||
|
||||
#include "esp_event.h"
|
||||
#include "esp_system.h"
|
||||
|
||||
ESP_EVENT_DECLARE_BASE(ESP_HOSTED_EVENT);
|
||||
|
||||
/**
|
||||
* @brief ESP-Hosted event declarations
|
||||
*/
|
||||
enum {
|
||||
ESP_HOSTED_EVENT_CP_INIT = 0,
|
||||
ESP_HOSTED_EVENT_CP_HEARTBEAT,
|
||||
ESP_HOSTED_EVENT_TRANSPORT_FAILURE,
|
||||
ESP_HOSTED_EVENT_TRANSPORT_UP,
|
||||
ESP_HOSTED_EVENT_TRANSPORT_DOWN,
|
||||
ESP_HOSTED_EVENT_MEM_MONITOR,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Argument structure for ESP_HOSTED_EVENT_CP_INIT event
|
||||
*/
|
||||
typedef struct {
|
||||
esp_reset_reason_t reason; /**< Reset reason from co-proprocessor */
|
||||
} esp_hosted_event_init_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Argument structure for ESP_HOSTED_EVENT_CP_HEARTBEAT event
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t heartbeat; /**< Current co-processor heartbeat number */
|
||||
} esp_hosted_event_heartbeat_t;
|
||||
|
||||
#endif /* __ESP_HOSTED_EVENT_H__ */
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* DO NOT MODIFY THIS FILE.
|
||||
*
|
||||
* tools/check_fw_versions.py generated this file.
|
||||
*
|
||||
* This file is autogenerated by a pre-commit hook.
|
||||
* Version info here is populated from idf_component.yml
|
||||
*/
|
||||
#ifndef __ESP_HOSTED_HOST_FW_VERSION_H__
|
||||
#define __ESP_HOSTED_HOST_FW_VERSION_H__
|
||||
|
||||
#define ESP_HOSTED_VERSION_MAJOR_1 2
|
||||
#define ESP_HOSTED_VERSION_MINOR_1 12
|
||||
#define ESP_HOSTED_VERSION_PATCH_1 11
|
||||
|
||||
/**
|
||||
* Macro to convert version number into an integer
|
||||
*/
|
||||
#define ESP_HOSTED_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
|
||||
|
||||
/* Extract version components from version value */
|
||||
#define ESP_HOSTED_VERSION_MAJOR(ver) (((ver) >> 16) & 0xFF)
|
||||
#define ESP_HOSTED_VERSION_MINOR(ver) (((ver) >> 8) & 0xFF)
|
||||
#define ESP_HOSTED_VERSION_PATCH(ver) ((ver) & 0xFF)
|
||||
|
||||
/* Format version tuple for printing */
|
||||
#define ESP_HOSTED_VERSION_PRINTF_ARGS(ver) \
|
||||
(unsigned int)ESP_HOSTED_VERSION_MAJOR(ver), \
|
||||
(unsigned int)ESP_HOSTED_VERSION_MINOR(ver), \
|
||||
(unsigned int)ESP_HOSTED_VERSION_PATCH(ver)
|
||||
|
||||
#define ESP_HOSTED_VERSION_PRINTF_FMT "%u.%u.%u"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __ESP_HOSTED_MISC_H__
|
||||
#define __ESP_HOSTED_MISC_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "esp_mac.h"
|
||||
|
||||
#include "esp_hosted_misc_types.h"
|
||||
|
||||
#define ESP_HOSTED_APP_DESC_MAGIC_WORD (0xABCD5432) /*!< The magic word for the esp_hosted_app_desc structure */
|
||||
|
||||
/**
|
||||
* @brief Description about ESP-Hosted application on co-processor.
|
||||
*
|
||||
* @note Some fields may be empty if config to enable full app descriptor
|
||||
* is not enabled on the co-processor
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t magic_word; /*!< Magic word ESP_HOSTED_APP_DESC_MAGIC_WORD */
|
||||
uint32_t secure_version; /*!< Secure version */
|
||||
uint32_t reserv1[2]; /*!< reserv1 */
|
||||
char version[32]; /*!< Application version */
|
||||
char project_name[32]; /*!< Project name */
|
||||
char time[16]; /*!< Compile time */
|
||||
char date[16]; /*!< Compile date*/
|
||||
char idf_ver[32]; /*!< Version IDF */
|
||||
uint8_t app_elf_sha256[32]; /*!< sha256 of elf file */
|
||||
uint16_t min_efuse_blk_rev_full; /*!< Minimal eFuse block revision supported by image, in format: major * 100 + minor */
|
||||
uint16_t max_efuse_blk_rev_full; /*!< Maximal eFuse block revision supported by image, in format: major * 100 + minor */
|
||||
uint8_t mmu_page_size; /*!< MMU page size in log base 2 format */
|
||||
uint8_t reserv3[3]; /*!< reserv3 */
|
||||
uint32_t reserv2[18]; /*!< reserv2 */
|
||||
} esp_hosted_app_desc_t;
|
||||
|
||||
/**
|
||||
* @brief Initialise the BT Controller on the co-processor
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_hosted_bt_controller_init(void);
|
||||
|
||||
/**
|
||||
* @brief Deinitialise the BT Controller on the co-processor
|
||||
*
|
||||
* @param mem_release. Also releases memory used by controller. Once released, the BT controller cannot reuse the memory and cannot be initialised
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_hosted_bt_controller_deinit(bool mem_release);
|
||||
|
||||
/**
|
||||
* @brief Enables the BT Controller on the co-processor. Call only after initialising the BT controller.
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_hosted_bt_controller_enable(void);
|
||||
|
||||
/**
|
||||
* @brief Disables the BT Controller on the co-processor. Call before deinitialising the BT controller.
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_hosted_bt_controller_disable(void);
|
||||
|
||||
/**
|
||||
* @brief Set custom MAC address of the interface.
|
||||
*
|
||||
* This function allows you to overwrite the MAC addresses of the
|
||||
* interfaces set by the base MAC address.
|
||||
*
|
||||
* @param mac MAC address, length: 6 bytes/8 bytes.
|
||||
* length: 6 bytes for MAC-48
|
||||
* 8 bytes for EUI-64(used for ESP_MAC_IEEE802154 type)
|
||||
* @param mac_len Length of the mac array
|
||||
* @param type Type of MAC address
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_hosted_iface_mac_addr_set(uint8_t *mac, size_t mac_len, esp_mac_type_t type);
|
||||
|
||||
/**
|
||||
* @brief Read MAC address of the interface.
|
||||
*
|
||||
* @param mac base MAC address, length: 6 bytes/8 bytes.
|
||||
* length: 6 bytes for MAC-48
|
||||
* 8 bytes for EUI-64(used for IEEE 802.15.4)
|
||||
* @param mac_len Length of the mac array
|
||||
* @param type Type of MAC address
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_hosted_iface_mac_addr_get(uint8_t *mac, size_t mac_len, esp_mac_type_t type);
|
||||
|
||||
/**
|
||||
* @brief Return the size of the MAC type in bytes.
|
||||
*
|
||||
* @param type Type of MAC address
|
||||
*
|
||||
* @return 0 MAC type not found (not supported)
|
||||
* 6 bytes for MAC-48.
|
||||
* 8 bytes for EUI-64.
|
||||
*/
|
||||
size_t esp_hosted_iface_mac_addr_len_get(esp_mac_type_t type);
|
||||
|
||||
/**
|
||||
* @brief Return the co-processor application descriptor
|
||||
*
|
||||
* @param app_desc Pointer to Application Descriptor structure to fill
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_hosted_get_coprocessor_app_desc(esp_hosted_app_desc_t *app_desc);
|
||||
|
||||
/**
|
||||
* @brief Send custom data to co-processor
|
||||
*
|
||||
* @param msg_id Message ID (any uint32_t except 0xFFFFFFFF which is reserved)
|
||||
* @param data Data buffer to send
|
||||
* @param data_len Length of data buffer
|
||||
*
|
||||
* @return ESP_OK on success, ESP_ERR_* on failure
|
||||
*/
|
||||
esp_err_t esp_hosted_send_custom_data(uint32_t msg_id_to_send, const uint8_t *data_to_send, size_t data_len_to_send);
|
||||
|
||||
/**
|
||||
* @brief Register callback for custom data reception
|
||||
*
|
||||
* @param msg_id_exp Message ID to listen for (any uint32_t except 0xFFFFFFFF)
|
||||
* @param callback Function called when data with matching msg_id is received (NULL to deregister)
|
||||
* @param local_context Opaque pointer returned as-is to the callback on every invocation.
|
||||
* May be NULL. Caller is responsible for ensuring the pointed-to object
|
||||
* remains valid until the callback is deregistered.
|
||||
*
|
||||
* @return ESP_OK on success, ESP_ERR_* on failure
|
||||
*/
|
||||
esp_err_t esp_hosted_register_custom_callback(uint32_t msg_id_exp,
|
||||
void (*callback)(uint32_t msg_id_recvd, const uint8_t *data_recvd, size_t data_len_recvd, void *local_context),
|
||||
void *local_context);
|
||||
|
||||
/**
|
||||
* @brief Configure the co-processor heartbeat
|
||||
*
|
||||
* @param enable Enable or disable co-processor heartbeat
|
||||
* @param duration_sec Duration between heartbeats (in secs)
|
||||
*
|
||||
* @return ESP_OK on success, ESP_ERR_INVALID_ARG if duration is out of range
|
||||
*
|
||||
* @note Minimum heartbeat interval is 1 secs, maximum is 24 hours
|
||||
*/
|
||||
esp_err_t esp_hosted_configure_heartbeat(bool enable, int duration_sec);
|
||||
|
||||
/**
|
||||
* @brief Configure the co-processor memory monitor
|
||||
*
|
||||
* @param config Configures the memory monitor
|
||||
* @param curr_mem_info Current heap memory info of co-processor after configuration succeeds
|
||||
*
|
||||
* @return ESP_OK on success, ESP_ERR_INVALID_ARG if an argument is invalid
|
||||
*
|
||||
* @note 1. To do a one-time query:
|
||||
* - set `enable` to `false` (this will also disable any on-going memory reporting)
|
||||
* 2. To get periodic reports:
|
||||
* - set `enable` to `true`
|
||||
* - set `report_always` to `true`
|
||||
* - set `interval_sec` to the reporting interval (in secs)
|
||||
* 3. To get periodic reports only when heap memory falls below a threshold value
|
||||
* - set `enable` to `true`
|
||||
* - set `report_always` to `false`
|
||||
* - set `interval_sec` to the reporting interval (in secs)
|
||||
* - set required threshold values in `internal_mem` and/or `external_mem`
|
||||
*/
|
||||
esp_err_t esp_hosted_set_mem_monitor(esp_hosted_config_mem_monitor_t *config, esp_hosted_curr_mem_info_t *curr_mem_info);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __ESP_HOSTED_MISC_TYPES_H__
|
||||
#define __ESP_HOSTED_MISC_TYPES_H__
|
||||
|
||||
typedef enum {
|
||||
ESP_HOSTED_MEMMONITOR_NO_CHANGE = 0, // don't change the monitor configuration. Used to query current heap values
|
||||
ESP_HOSTED_MEMMONITOR_DISABLE = 1, // disable the monitor
|
||||
ESP_HOSTED_MEMMONITOR_ENABLE = 2, // (re)enable the monitor with new configuration
|
||||
} esp_hosted_mem_monitor_config_t;
|
||||
|
||||
/**
|
||||
* @brief Structures related to memory monitor
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t threshold_mem_dma; /*!< heap memory threshold for DMA capable memory */
|
||||
uint32_t threshold_mem_8bit; /*!< heap memory threshold for 8/16...-bit capable memory */
|
||||
} esp_hosted_mem_monitor_threshold_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t free_size; /*!< free size of heap */
|
||||
uint32_t largest_free_block; /*!< largest free block that can be allocated from the heap */
|
||||
} esp_hosted_mem_info_t;
|
||||
|
||||
typedef struct {
|
||||
esp_hosted_mem_info_t cap_dma; /*!< DMA capable memory */
|
||||
esp_hosted_mem_info_t cap_8bit; /*!< 8/16...-bit capable memory */
|
||||
} esp_hosted_cap_info_t;
|
||||
|
||||
// structure to configure memory monitoring
|
||||
typedef struct {
|
||||
esp_hosted_mem_monitor_config_t config; /*!< configure the memory monitor */
|
||||
bool report_always; /*!< if true, a memory report event is sent every interval_sec */
|
||||
uint32_t interval_sec; /*!< interval between memory checks on the co-processor and sending a report */
|
||||
esp_hosted_mem_monitor_threshold_t internal_mem; /*!< thresholds for internal memory */
|
||||
esp_hosted_mem_monitor_threshold_t external_mem; /*!< thresholds for external memory */
|
||||
} esp_hosted_config_mem_monitor_t;
|
||||
|
||||
// current memory info returned in response to configure memory monitoring
|
||||
typedef struct {
|
||||
esp_hosted_mem_monitor_config_t config; /*!< current memory monitor configuration */
|
||||
bool report_always; /*!< if true, a memory report event is sent every interval_sec */
|
||||
uint32_t interval_sec; /*!< interval between memory checks on the co-processor and sending a report */
|
||||
uint32_t curr_total_heap_size; /*!< current total heap size on co-processor */
|
||||
esp_hosted_cap_info_t curr_internal; /*!< current internal heap sizes */
|
||||
esp_hosted_cap_info_t curr_external; /*!< current external heap sized */
|
||||
} esp_hosted_curr_mem_info_t;
|
||||
|
||||
// memory monitoring event info
|
||||
typedef struct {
|
||||
uint32_t curr_total_free_heap_size; /*!< current total free heap size */
|
||||
uint32_t curr_min_free_heap_size; /*!< current minimum free heap size since boot up */
|
||||
esp_hosted_cap_info_t curr_internal; /*!< current internal heap sizes */
|
||||
esp_hosted_cap_info_t curr_external; /*!< current external heap sizes */
|
||||
} esp_hosted_event_mem_info_t;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef __ESP_HOSTED_OS_ABSTRACTION_H__
|
||||
#define __ESP_HOSTED_OS_ABSTRACTION_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include "esp_event_base.h"
|
||||
|
||||
typedef struct {
|
||||
/* Memory */
|
||||
/* 1 */ void* (*_h_memcpy)(void* dest, const void* src, uint32_t size);
|
||||
/* 2 */ void* (*_h_memset)(void* buf, int val, size_t len);
|
||||
/* 3 */ void* (*_h_malloc)(size_t size);
|
||||
/* 4 */ void* (*_h_calloc)(size_t blk_no, size_t size);
|
||||
/* 5 */ void (*_h_free)(void* ptr);
|
||||
/* 6 */ void* (*_h_realloc)(void *mem, size_t newsize);
|
||||
/* 7 */ void* (*_h_malloc_align)(size_t size, size_t align);
|
||||
/* 8 */ void (*_h_free_align)(void* ptr);
|
||||
|
||||
/* Thread */
|
||||
/* 11 */ void* (*_h_thread_create)(const char *tname, uint32_t tprio, uint32_t tstack_size, void (*start_routine)(void const *), void *sr_arg);
|
||||
/* 12 */ int (*_h_thread_cancel)(void *thread_handle);
|
||||
void (*_h_thread_yield)(void);
|
||||
|
||||
/* Sleeps */
|
||||
/* 13 */ unsigned int (*_h_msleep)(unsigned int mseconds);
|
||||
/* 14 */ unsigned int (*_h_usleep)(unsigned int useconds);
|
||||
/* 15 */ unsigned int (*_h_sleep)(unsigned int seconds);
|
||||
|
||||
/* Blocking non-sleepable delay */
|
||||
/* 16 */ unsigned int (*_h_blocking_delay)(unsigned int number);
|
||||
|
||||
/* Queue */
|
||||
/* 17 */ int (*_h_queue_item)(void * queue_handle, void *item, int timeout);
|
||||
/* 18 */ void* (*_h_create_queue)(uint32_t qnum_elem, uint32_t qitem_size);
|
||||
/* 19 */ int (*_h_dequeue_item)(void * queue_handle, void *item, int timeout);
|
||||
/* 20 */ int (*_h_queue_msg_waiting)(void * queue_handle);
|
||||
/* 21 */ int (*_h_destroy_queue)(void * queue_handle);
|
||||
/* 22 */ int (*_h_reset_queue)(void * queue_handle);
|
||||
|
||||
/* Mutex */
|
||||
/* 23 */ int (*_h_unlock_mutex)(void * mutex_handle);
|
||||
/* 24 */ void* (*_h_create_mutex)(void);
|
||||
/* 25 */ int (*_h_lock_mutex)(void * mutex_handle, int timeout_ms);
|
||||
/* 26 */ int (*_h_destroy_mutex)(void * mutex_handle);
|
||||
|
||||
/* Semaphore */
|
||||
/* 27 */ int (*_h_post_semaphore)(void * semaphore_handle);
|
||||
/* 28 */ int (*_h_post_semaphore_from_isr)(void * semaphore_handle);
|
||||
/* 29 */ void* (*_h_create_semaphore)(int maxCount);
|
||||
/* 30 */ int (*_h_get_semaphore)(void * semaphore_handle, int timeout_ms);
|
||||
/* 31 */ int (*_h_destroy_semaphore)(void * semaphore_handle);
|
||||
|
||||
/* Timer */
|
||||
/* 32 */ int (*_h_timer_stop)(void *timer_handle);
|
||||
/* 33 */ void* (*_h_timer_start)(const char *name, int duration_ms, int type, void (*timeout_handler)(void *), void *arg);
|
||||
/* 34 */ uint64_t (*_h_get_time_ms)(void); /* Get current time in milliseconds */
|
||||
|
||||
/* Mempool */
|
||||
#ifdef H_USE_MEMPOOL
|
||||
/* 34 */ void* (*_h_create_lock_mempool)(void);
|
||||
/* 35 */ void (*_h_lock_mempool)(void *lock_handle);
|
||||
/* 36 */ void (*_h_unlock_mempool)(void *lock_handle);
|
||||
/* 37 */ void (*_h_destroy_lock_mempool)(void *lock_handle);
|
||||
#endif
|
||||
|
||||
/* GPIO */
|
||||
/* 37 */ int (*_h_config_gpio)(void* gpio_port, uint32_t gpio_num, uint32_t mode);
|
||||
/* 38 */ int (*_h_config_gpio_as_interrupt)(void* gpio_port, uint32_t gpio_num, uint32_t intr_type, void (*gpio_isr_handler)(void* arg), void *arg);
|
||||
/* 39 */ int (*_h_teardown_gpio_interrupt)(void* gpio_port, uint32_t gpio_num);
|
||||
/* 39 */ int (*_h_read_gpio)(void* gpio_port, uint32_t gpio_num);
|
||||
/* 40 */ int (*_h_write_gpio)(void* gpio_port, uint32_t gpio_num, uint32_t value);
|
||||
/* 40 */ int (*_h_pull_gpio)(void* gpio_port, uint32_t gpio_num, uint32_t pull_value, uint32_t enable);
|
||||
/* 41 */ int (*_h_hold_gpio)(void* gpio_port, uint32_t gpio_num, uint32_t hold_value);
|
||||
/* 42 */ int (*_h_get_host_wakeup_or_reboot_reason)(void);
|
||||
/* All Transports - Init */
|
||||
/* 41 */ void * (*_h_bus_init)(void);
|
||||
/* 42 */ int (*_h_bus_deinit)(void*);
|
||||
/* Transport - SPI */
|
||||
/* 43 */ int (*_h_do_bus_transfer)(void *transfer_context);
|
||||
/* 44 */ int (*_h_event_wifi_post)(int32_t event_id, void* event_data, size_t event_data_size, uint32_t ticks_to_wait);
|
||||
// 45 - int (*_h_event_ip_post)(int32_t event_id, void* event_data, size_t event_data_size, uint32_t ticks_to_wait);
|
||||
/* 45 */ void (*_h_printf)(int level, const char *tag, const char *format, ...);
|
||||
/* 46 */ void (*_h_hosted_init_hook)(void);
|
||||
|
||||
/* Transport - SDIO */
|
||||
/* 47 */ int (*_h_sdio_card_init)(void *ctx, bool show_config);
|
||||
/* 48 */ int (*_h_sdio_card_deinit)(void*ctx);
|
||||
/* 49 */ int (*_h_sdio_read_reg)(void *ctx, uint32_t reg, uint8_t *data, uint16_t size, bool lock_required);
|
||||
/* 50 */ int (*_h_sdio_write_reg)(void *ctx, uint32_t reg, uint8_t *data, uint16_t size, bool lock_required);
|
||||
/* 51 */ int (*_h_sdio_read_block)(void *ctx, uint32_t reg, uint8_t *data, uint16_t size, bool lock_required);
|
||||
/* 52 */ int (*_h_sdio_write_block)(void *ctx, uint32_t reg, uint8_t *data, uint16_t size, bool lock_required);
|
||||
/* 53 */ int (*_h_sdio_wait_slave_intr)(void *ctx, uint32_t ticks_to_wait);
|
||||
|
||||
/* Transport - SPI HD */
|
||||
/* 54 */ int (*_h_spi_hd_read_reg)(uint32_t reg, uint32_t *data, int poll, bool lock_required);
|
||||
/* 55 */ int (*_h_spi_hd_write_reg)(uint32_t reg, uint32_t *data, bool lock_required);
|
||||
/* 56 */ int (*_h_spi_hd_read_dma)(uint8_t *data, uint16_t size, bool lock_required);
|
||||
/* 57 */ int (*_h_spi_hd_write_dma)(uint8_t *data, uint16_t size, bool lock_required);
|
||||
/* 58 */ int (*_h_spi_hd_set_data_lines)(uint32_t data_lines);
|
||||
/* 59 */ int (*_h_spi_hd_send_cmd9)(void);
|
||||
|
||||
/* Transport - UART */
|
||||
/* 60 */ int (*_h_uart_read)(void *ctx, uint8_t *data, uint16_t size);
|
||||
/* 61 */ int (*_h_uart_write)(void *ctx, uint8_t *data, uint16_t size);
|
||||
/* 62 */ int (*_h_uart_flush_input)(void *ctx);
|
||||
|
||||
/* 63 */ int (*_h_restart_host)(void);
|
||||
|
||||
/* 64 */ int (*_h_config_host_power_save_hal_impl)(uint32_t power_save_type, void* gpio_port, uint32_t gpio_num, int level);
|
||||
/* 65 */ int (*_h_start_host_power_save_hal_impl)(uint32_t power_save_type);
|
||||
/* 66 */ int (*_h_event_post)(esp_event_base_t event_base, int32_t event_id, void* event_data, size_t event_data_size, uint32_t ticks_to_wait);
|
||||
} hosted_osi_funcs_t;
|
||||
|
||||
struct hosted_config_t {
|
||||
hosted_osi_funcs_t *funcs;
|
||||
};
|
||||
|
||||
extern hosted_osi_funcs_t g_hosted_osi_funcs;
|
||||
|
||||
#define HOSTED_CONFIG_INIT_DEFAULT() { \
|
||||
.funcs = &g_hosted_osi_funcs, \
|
||||
}
|
||||
|
||||
extern struct hosted_config_t g_h;
|
||||
|
||||
#endif
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __PORT_ESP_HOSTED_HOST_BT_CONFIG_H__
|
||||
#define __PORT_ESP_HOSTED_HOST_BT_CONFIG_H__
|
||||
|
||||
#include "esp_idf_version.h"
|
||||
|
||||
// check: if co-processor SOC is ESP32, only BT BLE 4.2 is supported
|
||||
#if CONFIG_ESP_HOSTED_CP_TARGET_ESP32
|
||||
#if CONFIG_BT_BLE_50_FEATURES_SUPPORTED || CONFIG_BT_NIMBLE_50_FEATURE_SUPPORT
|
||||
#error "ESP32 co-processor only supports BLE 4.2"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Hosted BT defines for NimBLE
|
||||
#if CONFIG_ESP_HOSTED_ENABLE_BT_NIMBLE
|
||||
#define H_BT_HOST_ESP_NIMBLE 1
|
||||
#else
|
||||
#define H_BT_HOST_ESP_NIMBLE 0
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP_HOSTED_NIMBLE_HCI_VHCI
|
||||
#define H_BT_USE_VHCI 1
|
||||
#else
|
||||
#define H_BT_USE_VHCI 0
|
||||
#endif
|
||||
|
||||
// Hosted BT defines for BlueDroid
|
||||
#if CONFIG_ESP_HOSTED_ENABLE_BT_BLUEDROID
|
||||
#define H_BT_HOST_ESP_BLUEDROID 1
|
||||
#else
|
||||
#define H_BT_HOST_ESP_BLUEDROID 0
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP_HOSTED_BLUEDROID_HCI_VHCI
|
||||
#define H_BT_BLUEDROID_USE_VHCI 1
|
||||
#else
|
||||
#define H_BT_BLUEDROID_USE_VHCI 1
|
||||
#endif
|
||||
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0)
|
||||
// ll_init required
|
||||
#define H_BT_ENABLE_LL_INIT 1
|
||||
#else
|
||||
#define H_BT_ENABLE_LL_INIT 0
|
||||
#endif
|
||||
|
||||
// check: only one BT host stack can be enabled at a time
|
||||
#if H_BT_HOST_ESP_NIMBLE && H_BT_HOST_ESP_BLUEDROID
|
||||
#error "Enable only NimBLE or BlueDroid, not both"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+714
@@ -0,0 +1,714 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __PORT_ESP_HOSTED_HOST_CONFIG_H__
|
||||
#define __PORT_ESP_HOSTED_HOST_CONFIG_H__
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_task.h"
|
||||
#include "esp_idf_version.h"
|
||||
|
||||
#include "esp_idf_version.h"
|
||||
#include "esp_wifi_remote.h"
|
||||
|
||||
#ifdef CONFIG_ESP_HOSTED_ENABLED
|
||||
#define H_ESP_HOSTED_HOST 1
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP_HOSTED_DFLT_TASK_STACK
|
||||
#define H_ESP_HOSTED_DFLT_TASK_STACK CONFIG_ESP_HOSTED_DFLT_TASK_STACK
|
||||
#endif
|
||||
#ifdef CONFIG_ESP_HOSTED_DFLT_TASK_FROM_SPIRAM
|
||||
#define H_DFLT_TASK_FROM_SPIRAM (1)
|
||||
#else
|
||||
#define H_DFLT_TASK_FROM_SPIRAM (0)
|
||||
#endif
|
||||
|
||||
// to allow external code to override Hosted Functions if required
|
||||
#define H_WEAK_REF __attribute__((weak))
|
||||
|
||||
#define H_TRANSPORT_NONE 0
|
||||
#define H_TRANSPORT_SDIO 1
|
||||
#define H_TRANSPORT_SPI_HD 2
|
||||
#define H_TRANSPORT_SPI 3
|
||||
#define H_TRANSPORT_UART 4
|
||||
|
||||
#ifdef CONFIG_ESP_HOSTED_UART_HOST_INTERFACE
|
||||
#include "hal/uart_types.h"
|
||||
#endif
|
||||
|
||||
/* This file is to tune the main ESP-Hosted configurations.
|
||||
* In case you are not sure of some value, Let it be default.
|
||||
**/
|
||||
|
||||
#define H_GPIO_LOW 0
|
||||
#define H_GPIO_HIGH 1
|
||||
|
||||
#define H_ENABLE 1
|
||||
#define H_DISABLE 0
|
||||
|
||||
enum {
|
||||
H_GPIO_INTR_DISABLE = 0, /*!< Disable GPIO interrupt */
|
||||
H_GPIO_INTR_POSEDGE = 1, /*!< GPIO interrupt type : rising edge */
|
||||
H_GPIO_INTR_NEGEDGE = 2, /*!< GPIO interrupt type : falling edge */
|
||||
H_GPIO_INTR_ANYEDGE = 3, /*!< GPIO interrupt type : both rising and falling edge */
|
||||
H_GPIO_INTR_LOW_LEVEL = 4, /*!< GPIO interrupt type : input low level trigger */
|
||||
H_GPIO_INTR_HIGH_LEVEL = 5, /*!< GPIO interrupt type : input high level trigger */
|
||||
H_GPIO_INTR_MAX,
|
||||
};
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#if CONFIG_ESP_HOSTED_CP_TARGET_ESP32
|
||||
#define H_SLAVE_TARGET_ESP32 1
|
||||
#endif
|
||||
#if CONFIG_ESP_HOSTED_CP_TARGET_ESP32S2
|
||||
#define H_SLAVE_TARGET_ESP32S2 1
|
||||
#endif
|
||||
#if CONFIG_ESP_HOSTED_CP_TARGET_ESP32C3
|
||||
#define H_SLAVE_TARGET_ESP32C3 1
|
||||
#endif
|
||||
#if CONFIG_ESP_HOSTED_CP_TARGET_ESP32S3
|
||||
#define H_SLAVE_TARGET_ESP32S3 1
|
||||
#endif
|
||||
#if CONFIG_ESP_HOSTED_CP_TARGET_ESP32C2
|
||||
#define H_SLAVE_TARGET_ESP32C2 1
|
||||
#endif
|
||||
#if CONFIG_ESP_HOSTED_CP_TARGET_ESP32C6
|
||||
#define H_SLAVE_TARGET_ESP32C6 1
|
||||
#endif
|
||||
#if CONFIG_ESP_HOSTED_CP_TARGET_ESP32C5
|
||||
#define H_SLAVE_TARGET_ESP32C5 1
|
||||
#endif
|
||||
#if CONFIG_ESP_HOSTED_CP_TARGET_ESP32C61
|
||||
#define H_SLAVE_TARGET_ESP32C61 1
|
||||
#endif
|
||||
#if CONFIG_ESP_HOSTED_CP_TARGET_ESP32H2
|
||||
#define H_SLAVE_TARGET_ESP32H2 1
|
||||
#endif
|
||||
#if CONFIG_ESP_HOSTED_CP_TARGET_ESP32H4
|
||||
#define H_SLAVE_TARGET_ESP32H4 1
|
||||
#endif
|
||||
#else // ESP_PLATFORM
|
||||
/* For non ESP Host, use manual selection.
|
||||
* Uncomment ONLY ONE target below
|
||||
*/
|
||||
|
||||
// #define H_SLAVE_TARGET_ESP32 1
|
||||
// #define H_SLAVE_TARGET_ESP32S2 1
|
||||
// #define H_SLAVE_TARGET_ESP32C3 1
|
||||
// #define H_SLAVE_TARGET_ESP32S3 1
|
||||
// #define H_SLAVE_TARGET_ESP32C2 1
|
||||
// #define H_SLAVE_TARGET_ESP32C6 1
|
||||
// #define H_SLAVE_TARGET_ESP32C5 1
|
||||
// #define H_SLAVE_TARGET_ESP32C61 1
|
||||
// #define H_SLAVE_TARGET_ESP32H2 1
|
||||
// #define H_SLAVE_TARGET_ESP32H4 1
|
||||
#endif // ESP_PLATFORM
|
||||
|
||||
// check that only one slave target is set
|
||||
#if defined(H_SLAVE_TARGET_ESP32) + \
|
||||
defined(H_SLAVE_TARGET_ESP32S2) + \
|
||||
defined(H_SLAVE_TARGET_ESP32C3) + \
|
||||
defined(H_SLAVE_TARGET_ESP32S3) + \
|
||||
defined(H_SLAVE_TARGET_ESP32C2) + \
|
||||
defined(H_SLAVE_TARGET_ESP32C6) + \
|
||||
defined(H_SLAVE_TARGET_ESP32C5) + \
|
||||
defined(H_SLAVE_TARGET_ESP32C61) + \
|
||||
defined(H_SLAVE_TARGET_ESP32H2) + \
|
||||
defined(H_SLAVE_TARGET_ESP32H4) != 1
|
||||
#error "No Slave Target or more than one Slave Target was defined."
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP_HOSTED_USE_MEMPOOL
|
||||
#define H_USE_MEMPOOL 1
|
||||
#else
|
||||
#define H_USE_MEMPOOL 0
|
||||
#endif
|
||||
|
||||
#define H_MAX_SYNC_RPC_REQUESTS CONFIG_ESP_HOSTED_MAX_SIMULTANEOUS_SYNC_RPC_REQUESTS
|
||||
#define H_MAX_ASYNC_RPC_REQUESTS CONFIG_ESP_HOSTED_MAX_SIMULTANEOUS_ASYNC_RPC_REQUESTS
|
||||
|
||||
#undef H_TRANSPORT_IN_USE
|
||||
|
||||
#ifdef CONFIG_ESP_HOSTED_SPI_HOST_INTERFACE
|
||||
#define H_TRANSPORT_IN_USE H_TRANSPORT_SPI
|
||||
/* -------------------------- SPI Master Config start ---------------------- */
|
||||
/* Pins in use. The SPI Master can use the GPIO mux,
|
||||
so feel free to change these if needed.
|
||||
*/
|
||||
|
||||
|
||||
/* SPI config */
|
||||
|
||||
#ifdef CONFIG_ESP_HOSTED_HS_ACTIVE_LOW
|
||||
#define H_HANDSHAKE_ACTIVE_HIGH 0
|
||||
#else
|
||||
/* Default HS: Active High */
|
||||
#define H_HANDSHAKE_ACTIVE_HIGH 1
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP_HOSTED_DR_ACTIVE_LOW
|
||||
#define H_DATAREADY_ACTIVE_HIGH 0
|
||||
#else
|
||||
/* Default DR: Active High */
|
||||
#define H_DATAREADY_ACTIVE_HIGH 1
|
||||
#endif
|
||||
|
||||
#if H_HANDSHAKE_ACTIVE_HIGH
|
||||
#define H_HS_VAL_ACTIVE H_GPIO_HIGH
|
||||
#define H_HS_VAL_INACTIVE H_GPIO_LOW
|
||||
#define H_HS_INTR_EDGE H_GPIO_INTR_POSEDGE
|
||||
#else
|
||||
#define H_HS_VAL_ACTIVE H_GPIO_LOW
|
||||
#define H_HS_VAL_INACTIVE H_GPIO_HIGH
|
||||
#define H_HS_INTR_EDGE H_GPIO_INTR_NEGEDGE
|
||||
#endif
|
||||
|
||||
#if H_DATAREADY_ACTIVE_HIGH
|
||||
#define H_DR_VAL_ACTIVE H_GPIO_HIGH
|
||||
#define H_DR_VAL_INACTIVE H_GPIO_LOW
|
||||
#define H_DR_INTR_EDGE H_GPIO_INTR_POSEDGE
|
||||
#else
|
||||
#define H_DR_VAL_ACTIVE H_GPIO_LOW
|
||||
#define H_DR_VAL_INACTIVE H_GPIO_HIGH
|
||||
#define H_DR_INTR_EDGE H_GPIO_INTR_NEGEDGE
|
||||
#endif
|
||||
|
||||
#define H_GPIO_HANDSHAKE_Port NULL
|
||||
#define H_GPIO_HANDSHAKE_Pin CONFIG_ESP_HOSTED_SPI_GPIO_HANDSHAKE
|
||||
#define H_GPIO_DATA_READY_Port NULL
|
||||
#define H_GPIO_DATA_READY_Pin CONFIG_ESP_HOSTED_SPI_GPIO_DATA_READY
|
||||
|
||||
|
||||
|
||||
#define H_GPIO_MOSI_Port NULL
|
||||
#define H_GPIO_MOSI_Pin CONFIG_ESP_HOSTED_SPI_GPIO_MOSI
|
||||
#define H_GPIO_MISO_Port NULL
|
||||
#define H_GPIO_MISO_Pin CONFIG_ESP_HOSTED_SPI_GPIO_MISO
|
||||
#define H_GPIO_SCLK_Port NULL
|
||||
#define H_GPIO_SCLK_Pin CONFIG_ESP_HOSTED_SPI_GPIO_CLK
|
||||
#define H_GPIO_CS_Port NULL
|
||||
#define H_GPIO_CS_Pin CONFIG_ESP_HOSTED_SPI_GPIO_CS
|
||||
|
||||
#define H_SPI_TX_Q CONFIG_ESP_HOSTED_SPI_TX_Q_SIZE
|
||||
#define H_SPI_RX_Q CONFIG_ESP_HOSTED_SPI_RX_Q_SIZE
|
||||
|
||||
#define H_SPI_MODE CONFIG_ESP_HOSTED_SPI_MODE
|
||||
#define H_SPI_FD_CLK_MHZ CONFIG_ESP_HOSTED_SPI_CLK_FREQ
|
||||
|
||||
// used by transport_drv to determine the mempool size
|
||||
#define H_TRANSPORT_QUEUE_SIZE CONFIG_ESP_HOSTED_SPI_TX_Q_SIZE
|
||||
|
||||
/* -------------------------- SPI Master Config end ------------------------ */
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP_HOSTED_SDIO_HOST_INTERFACE
|
||||
#define H_TRANSPORT_IN_USE H_TRANSPORT_SDIO
|
||||
/* -------------------------- SDIO Host Config start ----------------------- */
|
||||
|
||||
#ifdef CONFIG_SOC_SDMMC_USE_GPIO_MATRIX
|
||||
#define H_SDIO_SOC_USE_GPIO_MATRIX
|
||||
#endif
|
||||
|
||||
#define H_SDIO_CLOCK_FREQ_KHZ CONFIG_ESP_HOSTED_SDIO_CLOCK_FREQ_KHZ
|
||||
#define H_SDIO_BUS_WIDTH CONFIG_ESP_HOSTED_SDIO_BUS_WIDTH
|
||||
#define H_SDMMC_HOST_SLOT CONFIG_ESP_HOSTED_SDIO_SLOT
|
||||
|
||||
#define H_SDIO_PORT_CLK NULL
|
||||
#define H_SDIO_PORT_CMD NULL
|
||||
#define H_SDIO_PORT_D0 NULL
|
||||
#define H_SDIO_PORT_D1 NULL
|
||||
#define H_SDIO_PORT_D2 NULL
|
||||
#define H_SDIO_PORT_D3 NULL
|
||||
|
||||
#ifdef H_SDIO_SOC_USE_GPIO_MATRIX
|
||||
#define H_SDIO_PIN_CLK CONFIG_ESP_HOSTED_SDIO_PIN_CLK
|
||||
#define H_SDIO_PIN_CMD CONFIG_ESP_HOSTED_SDIO_PIN_CMD
|
||||
#define H_SDIO_PIN_D0 CONFIG_ESP_HOSTED_SDIO_PIN_D0
|
||||
#define H_SDIO_PIN_D1 CONFIG_ESP_HOSTED_SDIO_PIN_D1
|
||||
#if (H_SDIO_BUS_WIDTH == 4)
|
||||
#define H_SDIO_PIN_D2 CONFIG_ESP_HOSTED_SDIO_PIN_D2
|
||||
#define H_SDIO_PIN_D3 CONFIG_ESP_HOSTED_SDIO_PIN_D3
|
||||
#else
|
||||
#define H_SDIO_PIN_D2 -1
|
||||
#define H_SDIO_PIN_D3 -1
|
||||
#endif
|
||||
#else
|
||||
#define H_SDIO_PIN_CLK -1
|
||||
#define H_SDIO_PIN_CMD -1
|
||||
#define H_SDIO_PIN_D0 -1
|
||||
#define H_SDIO_PIN_D1 -1
|
||||
#if (H_SDIO_BUS_WIDTH == 4)
|
||||
#define H_SDIO_PIN_D2 -1
|
||||
#define H_SDIO_PIN_D3 -1
|
||||
#else
|
||||
#define H_SDIO_PIN_D2 -1
|
||||
#define H_SDIO_PIN_D3 -1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define H_SDIO_TX_Q CONFIG_ESP_HOSTED_SDIO_TX_Q_SIZE
|
||||
#define H_SDIO_RX_Q CONFIG_ESP_HOSTED_SDIO_RX_Q_SIZE
|
||||
|
||||
#define H_SDIO_CHECKSUM CONFIG_ESP_HOSTED_SDIO_CHECKSUM
|
||||
|
||||
#define H_SDIO_HOST_STREAMING_MODE 1
|
||||
#define H_SDIO_ALWAYS_HOST_RX_MAX_TRANSPORT_SIZE 2
|
||||
#define H_SDIO_OPTIMIZATION_RX_NONE 3
|
||||
|
||||
#ifdef CONFIG_ESP_HOSTED_SDIO_OPTIMIZATION_RX_STREAMING_MODE
|
||||
#define H_SDIO_HOST_RX_MODE H_SDIO_HOST_STREAMING_MODE
|
||||
#elif defined(CONFIG_ESP_HOSTED_SDIO_OPTIMIZATION_RX_MAX_SIZE)
|
||||
#define H_SDIO_HOST_RX_MODE H_SDIO_ALWAYS_HOST_RX_MAX_TRANSPORT_SIZE
|
||||
#else
|
||||
/* Use this if unsure */
|
||||
#define H_SDIO_HOST_RX_MODE H_SDIO_OPTIMIZATION_RX_NONE
|
||||
#endif
|
||||
|
||||
// Pad transfer len for host operation
|
||||
#define H_SDIO_TX_LEN_TO_TRANSFER(x) ((x + 3) & (~3))
|
||||
#define H_SDIO_RX_LEN_TO_TRANSFER(x) ((x + 3) & (~3))
|
||||
|
||||
/* Do Block Mode only transfers
|
||||
*
|
||||
* When enabled, SDIO only uses block mode transfers for higher
|
||||
* throughput. Data lengths are padded to multiples of ESP_BLOCK_SIZE.
|
||||
*
|
||||
* This is safe for the SDIO slave:
|
||||
* - for Host Tx: slave will ignore extra data sent by Host
|
||||
* - for Host Rx: slave will send extra 0 data, ignored by Host
|
||||
*/
|
||||
#define H_SDIO_TX_BLOCK_ONLY_XFER (1)
|
||||
#define H_SDIO_RX_BLOCK_ONLY_XFER (1)
|
||||
|
||||
// workarounds for some SDIO transfer errors that may occur
|
||||
#if 0
|
||||
/* Below workarounds could be enabled for non-ESP MCUs to test first
|
||||
* Once everything is stable, can disable workarounds and test again
|
||||
* */
|
||||
#define H_SDIO_TX_LIMIT_XFER_SIZE_WORKAROUND // limit transfer to one ESP_BLOCK_SIZE at a time
|
||||
#define H_SDIO_RX_LIMIT_XFER_SIZE_WORKDAROUND // limit transfer to one ESP_BLOCK_SIZE at a time
|
||||
#endif
|
||||
|
||||
#if defined(H_SDIO_TX_LIMIT_XFER_SIZE_WORKAROUND)
|
||||
#define H_SDIO_TX_BLOCKS_TO_TRANSFER(x) (1)
|
||||
#else
|
||||
#define H_SDIO_TX_BLOCKS_TO_TRANSFER(x) (x / ESP_BLOCK_SIZE)
|
||||
#endif
|
||||
|
||||
#if defined(H_SDIO_RX_LIMIT_XFER_SIZE_WORKDAROUND)
|
||||
#define H_SDIO_RX_BLOCKS_TO_TRANSFER(x) (1)
|
||||
#else
|
||||
#define H_SDIO_RX_BLOCKS_TO_TRANSFER(x) (x / ESP_BLOCK_SIZE)
|
||||
#endif
|
||||
|
||||
// used by transport_drv to determine the mempool size
|
||||
#define H_TRANSPORT_QUEUE_SIZE CONFIG_ESP_HOSTED_SDIO_TX_Q_SIZE
|
||||
|
||||
/* -------------------------- SDIO Host Config end ------------------------- */
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP_HOSTED_SPI_HD_HOST_INTERFACE
|
||||
#define H_TRANSPORT_IN_USE H_TRANSPORT_SPI_HD
|
||||
/* -------------------------- SPI_HD Host Config start ----------------------- */
|
||||
|
||||
#define H_SPI_HD_HOST_INTERFACE 1
|
||||
|
||||
enum {
|
||||
H_SPI_HD_CONFIG_1_DATA_LINE,
|
||||
H_SPI_HD_CONFIG_2_DATA_LINES,
|
||||
H_SPI_HD_CONFIG_4_DATA_LINES,
|
||||
};
|
||||
|
||||
#if CONFIG_ESP_HOSTED_SPI_HD_DR_ACTIVE_HIGH
|
||||
#define H_SPI_HD_DATAREADY_ACTIVE_HIGH 1
|
||||
#else
|
||||
#define H_SPI_HD_DATAREADY_ACTIVE_HIGH 0
|
||||
#endif
|
||||
|
||||
#if H_SPI_HD_DATAREADY_ACTIVE_HIGH
|
||||
#define H_SPI_HD_DR_VAL_ACTIVE H_GPIO_HIGH
|
||||
#define H_SPI_HD_DR_VAL_INACTIVE H_GPIO_LOW
|
||||
#define H_SPI_HD_DR_INTR_EDGE H_GPIO_INTR_POSEDGE
|
||||
#else
|
||||
#define H_SPI_HD_DR_VAL_ACTIVE H_GPIO_LOW
|
||||
#define H_SPI_HD_DR_VAL_INACTIVE H_GPIO_HIGH
|
||||
#define H_SPI_HD_DR_INTR_EDGE H_GPIO_INTR_NEGEDGE
|
||||
#endif
|
||||
|
||||
#define H_SPI_HD_HOST_NUM_DATA_LINES CONFIG_ESP_HOSTED_SPI_HD_INTERFACE_NUM_DATA_LINES
|
||||
|
||||
#if (H_SPI_HD_HOST_NUM_DATA_LINES == 1) && (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(6,1,0))
|
||||
#error "1-bit SPI-HD mode only supported in ESP-IDF v6.1 and above"
|
||||
#endif
|
||||
|
||||
#define H_SPI_HD_PORT_D0 NULL
|
||||
#define H_SPI_HD_PORT_D1 NULL
|
||||
#define H_SPI_HD_PORT_D2 NULL
|
||||
#define H_SPI_HD_PORT_D3 NULL
|
||||
#define H_SPI_HD_PORT_CS NULL
|
||||
#define H_SPI_HD_PORT_CLK NULL
|
||||
|
||||
#define H_SPI_HD_PIN_D0 CONFIG_ESP_HOSTED_SPI_HD_GPIO_D0
|
||||
#if (CONFIG_ESP_HOSTED_SPI_HD_INTERFACE_NUM_DATA_LINES >= 2)
|
||||
#define H_SPI_HD_PIN_D1 CONFIG_ESP_HOSTED_SPI_HD_GPIO_D1
|
||||
#else
|
||||
#define H_SPI_HD_PIN_D1 -1
|
||||
#endif
|
||||
#if (CONFIG_ESP_HOSTED_SPI_HD_INTERFACE_NUM_DATA_LINES == 4)
|
||||
#define H_SPI_HD_PIN_D2 CONFIG_ESP_HOSTED_SPI_HD_GPIO_D2
|
||||
#define H_SPI_HD_PIN_D3 CONFIG_ESP_HOSTED_SPI_HD_GPIO_D3
|
||||
#else
|
||||
#define H_SPI_HD_PIN_D2 -1
|
||||
#define H_SPI_HD_PIN_D3 -1
|
||||
#endif
|
||||
|
||||
#define H_SPI_HD_PIN_CS CONFIG_ESP_HOSTED_SPI_HD_GPIO_CS
|
||||
#define H_SPI_HD_PIN_CLK CONFIG_ESP_HOSTED_SPI_HD_GPIO_CLK
|
||||
#define H_SPI_HD_PORT_DATA_READY NULL
|
||||
#ifdef CONFIG_ESP_HOSTED_SPI_HD_DATA_READY_ENABLED
|
||||
#define H_SPI_HD_PIN_DATA_READY CONFIG_ESP_HOSTED_SPI_HD_GPIO_DATA_READY
|
||||
#define H_SPI_HD_DATA_READY_ENABLED 1
|
||||
#else
|
||||
#define H_SPI_HD_PIN_DATA_READY -1
|
||||
#define H_SPI_HD_DATA_READY_ENABLED 0
|
||||
#define H_SPI_HD_POLL_INTERVAL_MS CONFIG_ESP_HOSTED_SPI_HD_POLL_INTERVAL_MS
|
||||
#endif
|
||||
|
||||
#define H_SPI_HD_CLK_MHZ CONFIG_ESP_HOSTED_SPI_HD_CLK_FREQ
|
||||
#define H_SPI_HD_MODE CONFIG_ESP_HOSTED_SPI_HD_MODE
|
||||
#define H_SPI_HD_TX_QUEUE_SIZE CONFIG_ESP_HOSTED_SPI_HD_TX_Q_SIZE
|
||||
#define H_SPI_HD_RX_QUEUE_SIZE CONFIG_ESP_HOSTED_SPI_HD_RX_Q_SIZE
|
||||
|
||||
#define H_SPI_HD_CHECKSUM CONFIG_ESP_HOSTED_SPI_HD_CHECKSUM
|
||||
|
||||
#define H_SPI_HD_NUM_COMMAND_BITS 8
|
||||
#define H_SPI_HD_NUM_ADDRESS_BITS 8
|
||||
#define H_SPI_HD_NUM_DUMMY_BITS 8
|
||||
|
||||
// used by transport_drv to determine the mempool size
|
||||
#define H_TRANSPORT_QUEUE_SIZE CONFIG_ESP_HOSTED_SPI_HD_TX_Q_SIZE
|
||||
|
||||
/* -------------------------- SPI_HD Host Config end ------------------------- */
|
||||
#else
|
||||
#define H_SPI_HD_HOST_INTERFACE 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP_HOSTED_UART_HOST_INTERFACE
|
||||
#define H_TRANSPORT_IN_USE H_TRANSPORT_UART
|
||||
/* -------------------------- UART Host Config start ------------------------- */
|
||||
|
||||
#define H_UART_HOST_TRANSPORT 1
|
||||
|
||||
#define H_UART_PORT CONFIG_ESP_HOSTED_UART_PORT
|
||||
#define H_UART_NUM_DATA_BITS CONFIG_ESP_HOSTED_UART_NUM_DATA_BITS
|
||||
#define H_UART_PARITY CONFIG_ESP_HOSTED_UART_PARITY
|
||||
#define H_UART_START_BITS 1
|
||||
#define H_UART_STOP_BITS CONFIG_ESP_HOSTED_UART_STOP_BITS
|
||||
#define H_UART_FLOWCTRL UART_HW_FLOWCTRL_DISABLE
|
||||
#define H_UART_CLK_SRC UART_SCLK_DEFAULT
|
||||
|
||||
#define H_UART_CHECKSUM CONFIG_ESP_HOSTED_UART_CHECKSUM
|
||||
#define H_UART_BAUD_RATE CONFIG_ESP_HOSTED_UART_BAUDRATE
|
||||
#define H_UART_PIN_TX CONFIG_ESP_HOSTED_UART_PIN_TX
|
||||
#define H_UART_PORT_TX NULL
|
||||
#define H_UART_PIN_RX CONFIG_ESP_HOSTED_UART_PIN_RX
|
||||
#define H_UART_PORT_RX NULL
|
||||
#define H_UART_TX_QUEUE_SIZE CONFIG_ESP_HOSTED_UART_TX_Q_SIZE
|
||||
#define H_UART_RX_QUEUE_SIZE CONFIG_ESP_HOSTED_UART_RX_Q_SIZE
|
||||
|
||||
// used by transport_drv to determine the mempool size
|
||||
#define H_TRANSPORT_QUEUE_SIZE CONFIG_ESP_HOSTED_UART_TX_Q_SIZE
|
||||
|
||||
/* -------------------------- UART Host Config end ------------------------- */
|
||||
#else
|
||||
#define H_UART_HOST_TRANSPORT 0
|
||||
#endif
|
||||
|
||||
/* Generic reset pin config */
|
||||
#define H_GPIO_PIN_RESET CONFIG_ESP_HOSTED_GPIO_SLAVE_RESET_SLAVE
|
||||
#define H_GPIO_PORT_RESET NULL
|
||||
|
||||
/* If Reset pin is Enable, it is Active High.
|
||||
* If it is RST, active low */
|
||||
#ifdef CONFIG_ESP_HOSTED_RESET_GPIO_ACTIVE_LOW
|
||||
#define H_RESET_ACTIVE_HIGH 0
|
||||
#else
|
||||
#define H_RESET_ACTIVE_HIGH 1
|
||||
#endif
|
||||
|
||||
#if H_RESET_ACTIVE_HIGH
|
||||
#define H_RESET_VAL_ACTIVE H_GPIO_HIGH
|
||||
#define H_RESET_VAL_INACTIVE H_GPIO_LOW
|
||||
#else
|
||||
#define H_RESET_VAL_ACTIVE H_GPIO_LOW
|
||||
#define H_RESET_VAL_INACTIVE H_GPIO_HIGH
|
||||
#endif
|
||||
|
||||
/* --------------------- Common slave reset strategy ------------------- */
|
||||
|
||||
#if defined(CONFIG_ESP_HOSTED_TRANSPORT_RESTART_ON_FAILURE)
|
||||
#define H_TRANSPORT_RESTART_ON_FAILURE 1
|
||||
#else
|
||||
#define H_TRANSPORT_RESTART_ON_FAILURE 0
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ESP_HOSTED_SLAVE_RESET_ON_EVERY_HOST_BOOTUP)
|
||||
/* Always reset the slave when host boots up
|
||||
* This ensures a clean transport state and prevents any inconsistent states,
|
||||
* but causes the slave to reboot every time the host boots up
|
||||
*/
|
||||
#define H_SLAVE_RESET_ON_EVERY_HOST_BOOTUP 1
|
||||
#define H_SLAVE_RESET_ONLY_IF_NECESSARY 0
|
||||
#elif defined(CONFIG_ESP_HOSTED_SLAVE_RESET_ONLY_IF_NECESSARY)
|
||||
/* Only reset the slave if initialization fails
|
||||
* This reduces slave reboots but assumes the slave interface is in a consistent state.
|
||||
* If initialization fails, the host will assume the slave is in an inconsistent
|
||||
* or deinitialized state and will reset it.
|
||||
*/
|
||||
#define H_SLAVE_RESET_ON_EVERY_HOST_BOOTUP 0
|
||||
#define H_SLAVE_RESET_ONLY_IF_NECESSARY 1
|
||||
#else
|
||||
/* Default to always reset for backward compatibility */
|
||||
#define H_SLAVE_RESET_ON_EVERY_HOST_BOOTUP 1
|
||||
#define H_SLAVE_RESET_ONLY_IF_NECESSARY 0
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_ESP_SDIO_HOST_INTERFACE) && H_SLAVE_RESET_ONLY_IF_NECESSARY
|
||||
#error "Invalid combination. H_SLAVE_RESET_ONLY_IF_NECESSARY is only supported for SDIO host interface, for now"
|
||||
#endif
|
||||
|
||||
/* Auto-restart on communication failure */
|
||||
#ifdef CONFIG_ESP_HOSTED_HOST_RESTART_NO_COMMUNICATION_WITH_SLAVE
|
||||
/* Enable host auto-restart if communication with slave is lost
|
||||
* When enabled, the host will reset itself to recover the connection
|
||||
* if the slave becomes non-responsive for the configured timeout period.
|
||||
* This acts as a safeguard in case the slave does not issue the first event.
|
||||
*/
|
||||
#define H_HOST_RESTART_NO_COMMUNICATION_WITH_SLAVE 1
|
||||
#else
|
||||
/* Disable host auto-restart on communication failure */
|
||||
#define H_HOST_RESTART_NO_COMMUNICATION_WITH_SLAVE 0
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ESP_HOSTED_HOST_RESTART_NO_COMMUNICATION_WITH_SLAVE_TIMEOUT)
|
||||
/* Timeout in milliseconds before host restarts due to no communication
|
||||
* Maximum time that the host will wait for a response from the slave
|
||||
* before triggering an automatic restart.
|
||||
*/
|
||||
#define H_HOST_RESTART_NO_COMMUNICATION_WITH_SLAVE_TIMEOUT_MS (CONFIG_ESP_HOSTED_HOST_RESTART_NO_COMMUNICATION_WITH_SLAVE_TIMEOUT * 1000)
|
||||
#else
|
||||
/* Default timeout value (-1 means disabled) */
|
||||
#define H_HOST_RESTART_NO_COMMUNICATION_WITH_SLAVE_TIMEOUT_MS -1
|
||||
#endif
|
||||
|
||||
#if H_HOST_RESTART_NO_COMMUNICATION_WITH_SLAVE && H_HOST_RESTART_NO_COMMUNICATION_WITH_SLAVE_TIMEOUT_MS == -1
|
||||
#error "Invalid combination. Host Restart No Communication With Slave is enabled but timeout is not configured"
|
||||
#endif
|
||||
|
||||
#if H_SLAVE_RESET_ON_EVERY_HOST_BOOTUP && H_SLAVE_RESET_ONLY_IF_NECESSARY
|
||||
#error "Invalid combination. Reset on every boot-up and reset only if necessary cannot be enabled at the same time"
|
||||
#endif
|
||||
|
||||
#if H_SLAVE_RESET_ON_EVERY_HOST_BOOTUP && H_HOST_RESTART_NO_COMMUNICATION_WITH_SLAVE
|
||||
#error "Invalid combination. H_HOST_RESTART_NO_COMMUNICATION_WITH_SLAVE should not be logically required if H_SLAVE_RESET_ONLY_IF_NECESSARY is enabled"
|
||||
#endif
|
||||
|
||||
|
||||
#define TIMEOUT_PSERIAL_RESP 30
|
||||
|
||||
|
||||
#define PRE_FORMAT_NEWLINE_CHAR ""
|
||||
#define POST_FORMAT_NEWLINE_CHAR "\n"
|
||||
|
||||
#define USE_STD_C_LIB_MALLOC 0
|
||||
|
||||
#ifdef CONFIG_HOST_TO_ESP_WIFI_DATA_THROTTLE
|
||||
#define H_WIFI_TX_DATA_THROTTLE_LOW_THRESHOLD CONFIG_ESP_HOSTED_TO_WIFI_DATA_THROTTLE_LOW_THRESHOLD
|
||||
#define H_WIFI_TX_DATA_THROTTLE_HIGH_THRESHOLD CONFIG_ESP_HOSTED_TO_WIFI_DATA_THROTTLE_HIGH_THRESHOLD
|
||||
#else
|
||||
#define H_WIFI_TX_DATA_THROTTLE_LOW_THRESHOLD 0
|
||||
#define H_WIFI_TX_DATA_THROTTLE_HIGH_THRESHOLD 0
|
||||
#endif
|
||||
|
||||
/* Raw Throughput Testing */
|
||||
#define H_TEST_RAW_TP CONFIG_ESP_HOSTED_RAW_THROUGHPUT_TRANSPORT
|
||||
|
||||
#if H_TEST_RAW_TP
|
||||
|
||||
#define H_RAW_TP_REPORT_INTERVAL CONFIG_ESP_HOSTED_RAW_TP_REPORT_INTERVAL
|
||||
#define H_RAW_TP_PKT_LEN CONFIG_ESP_HOSTED_RAW_TP_HOST_TO_ESP_PKT_LEN
|
||||
|
||||
#if CONFIG_ESP_HOSTED_RAW_THROUGHPUT_TX_TO_SLAVE
|
||||
#define H_TEST_RAW_TP_DIR (ESP_TEST_RAW_TP__HOST_TO_ESP)
|
||||
#elif CONFIG_ESP_HOSTED_RAW_THROUGHPUT_RX_FROM_SLAVE
|
||||
#define H_TEST_RAW_TP_DIR (ESP_TEST_RAW_TP__ESP_TO_HOST)
|
||||
#elif CONFIG_ESP_HOSTED_RAW_THROUGHPUT_BIDIRECTIONAL
|
||||
#define H_TEST_RAW_TP_DIR (ESP_TEST_RAW_TP__BIDIRECTIONAL)
|
||||
#else
|
||||
#error Test Raw TP direction not defined
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define H_TEST_RAW_TP_DIR (ESP_TEST_RAW_TP_NONE)
|
||||
#endif
|
||||
|
||||
/* ---------------------- Enable memory monitor ------------------------------ */
|
||||
|
||||
#ifdef CONFIG_ESP_HOSTED_MEM_MONITOR
|
||||
#define H_MEM_MONITOR 1
|
||||
#else
|
||||
#define H_MEM_MONITOR 0
|
||||
#endif
|
||||
|
||||
/* ----------------------- Enable packet stats ------------------------------- */
|
||||
|
||||
#ifdef CONFIG_ESP_HOSTED_PKT_STATS
|
||||
#define ESP_PKT_STATS 1
|
||||
#define ESP_PKT_STATS_REPORT_INTERVAL CONFIG_ESP_HOSTED_PKT_STATS_INTERVAL_SEC
|
||||
#endif
|
||||
|
||||
/* ----------------- Host to slave Wi-Fi flow control ------------------------ */
|
||||
/* Bit0: slave request host to enable flow control */
|
||||
#define H_EVTGRP_BIT_FC_ALLOW_WIFI BIT(0)
|
||||
|
||||
|
||||
/* --------------------- Host Power saving ----------------------------------- */
|
||||
|
||||
#if defined(CONFIG_ESP_HOSTED_HOST_POWER_SAVE_ENABLED)
|
||||
#if defined(CONFIG_ESP_HOSTED_HOST_DEEP_SLEEP_ALLOWED)
|
||||
#define H_HOST_PS_ALLOWED 1
|
||||
#define H_HOST_PS_ALLOWED_LIGHT_SLEEP 0
|
||||
#else
|
||||
#define H_HOST_PS_ALLOWED 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* In IDF 6.0.0 and above,
|
||||
* esp_deep_sleep_enable_gpio_wakeup() is now
|
||||
* esp_sleep_enable_gpio_wakeup_on_hp_periph_powerdown()
|
||||
*/
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0)
|
||||
#define H_HOST_USE_HP_PERIPH_POWERDOWN 1
|
||||
#else
|
||||
#define H_HOST_USE_HP_PERIPH_POWERDOWN 0
|
||||
#endif
|
||||
/* Amend later for light sleep */
|
||||
#else
|
||||
#define H_HOST_PS_ALLOWED 0
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ESP_HOSTED_HOST_WAKEUP_GPIO)
|
||||
#define H_HOST_WAKEUP_GPIO_PORT NULL
|
||||
#define H_HOST_WAKEUP_GPIO CONFIG_ESP_HOSTED_HOST_WAKEUP_GPIO
|
||||
#else
|
||||
#define H_HOST_WAKEUP_GPIO -1
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ESP_HOSTED_HOST_WAKEUP_GPIO_LEVEL)
|
||||
#define H_HOST_WAKEUP_GPIO_LEVEL CONFIG_ESP_HOSTED_HOST_WAKEUP_GPIO_LEVEL
|
||||
#else
|
||||
#define H_HOST_WAKEUP_GPIO_LEVEL 1 /* High */
|
||||
#endif
|
||||
|
||||
// adjust this value if co-processor needs more time to be ready
|
||||
// after reset from host
|
||||
#if CONFIG_ESP_HOSTED_SDIO_RESET_DELAY_MS
|
||||
#define H_HOST_SDIO_RESET_DELAY_MS CONFIG_ESP_HOSTED_SDIO_RESET_DELAY_MS
|
||||
#else
|
||||
#define H_HOST_SDIO_RESET_DELAY_MS 1500
|
||||
#endif
|
||||
|
||||
/* Conflict checks for host power save configuration */
|
||||
#if (H_HOST_PS_ALLOWED == 1)
|
||||
#if (H_HOST_WAKEUP_GPIO == -1)
|
||||
#error "Conflict: Host wake-up GPIO is mandatory when deep sleep is allowed"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* --------------------- Host CLI -------------------------------------------- */
|
||||
#ifdef CONFIG_ESP_HOSTED_CLI_ENABLED
|
||||
#define H_ESP_HOSTED_CLI_ENABLED 1
|
||||
#endif
|
||||
|
||||
/* ---------------------- ESP-IDF Specific Config start -------------------- */
|
||||
/* This section is for ESP-IDF specific support.
|
||||
* Can be ignored on other hosts MCUs.
|
||||
*/
|
||||
|
||||
/* Controls whether an Internal LDO powers the SDIO connection */
|
||||
#if CONFIG_ESP_HOSTED_SD_PWR_CTRL_LDO_INTERNAL_IO
|
||||
#define H_SDIO_PWR_CTRL_LDO 1
|
||||
#define H_SDIO_PWR_CTRL_LDO_ID CONFIG_ESP_HOSTED_SD_PWR_CTRL_LDO_IO_ID
|
||||
#else
|
||||
#define H_SDIO_PWR_CTRL_LDO 0
|
||||
#endif
|
||||
|
||||
/* ---------------------- ESP-IDF Specific Config end ---------------------- */
|
||||
|
||||
/* --------------------- Custom RPC ----------------------------------------- */
|
||||
#ifdef CONFIG_ESP_HOSTED_ENABLE_PEER_DATA_TRANSFER
|
||||
#define H_PEER_DATA_TRANSFER 1
|
||||
|
||||
#ifdef CONFIG_ESP_HOSTED_MAX_CUSTOM_MSG_HANDLERS
|
||||
#define H_MAX_CUSTOM_MSG_HANDLERS CONFIG_ESP_HOSTED_MAX_CUSTOM_MSG_HANDLERS
|
||||
#endif
|
||||
#else
|
||||
#define H_PEER_DATA_TRANSFER 0
|
||||
#endif
|
||||
|
||||
/* --------------------- Network Split -------------------------------------- */
|
||||
#ifdef CONFIG_ESP_HOSTED_NETWORK_SPLIT_ENABLED
|
||||
#define H_NETWORK_SPLIT_ENABLED 1
|
||||
#else
|
||||
#define H_NETWORK_SPLIT_ENABLED 0
|
||||
#endif
|
||||
|
||||
#if H_NETWORK_SPLIT_ENABLED
|
||||
#if !defined(CONFIG_LWIP_TCP_LOCAL_PORT_RANGE_START) || \
|
||||
!defined(CONFIG_LWIP_TCP_LOCAL_PORT_RANGE_END) || \
|
||||
!defined(CONFIG_LWIP_UDP_LOCAL_PORT_RANGE_START) || \
|
||||
!defined(CONFIG_LWIP_UDP_LOCAL_PORT_RANGE_END)
|
||||
#error "LWIP ports at host need to configured, ensure they are exclusive and different from slave"
|
||||
#endif
|
||||
|
||||
#define H_HOST_TCP_LOCAL_PORT_RANGE_START CONFIG_LWIP_TCP_LOCAL_PORT_RANGE_START
|
||||
#define H_HOST_TCP_LOCAL_PORT_RANGE_END CONFIG_LWIP_TCP_LOCAL_PORT_RANGE_END
|
||||
#define H_HOST_UDP_LOCAL_PORT_RANGE_START CONFIG_LWIP_UDP_LOCAL_PORT_RANGE_START
|
||||
#define H_HOST_UDP_LOCAL_PORT_RANGE_END CONFIG_LWIP_UDP_LOCAL_PORT_RANGE_END
|
||||
|
||||
#define H_SLAVE_TCP_REMOTE_PORT_RANGE_START CONFIG_LWIP_TCP_REMOTE_PORT_RANGE_START
|
||||
#define H_SLAVE_TCP_REMOTE_PORT_RANGE_END CONFIG_LWIP_TCP_REMOTE_PORT_RANGE_END
|
||||
#define H_SLAVE_UDP_REMOTE_PORT_RANGE_START CONFIG_LWIP_UDP_REMOTE_PORT_RANGE_START
|
||||
#define H_SLAVE_UDP_REMOTE_PORT_RANGE_END CONFIG_LWIP_UDP_REMOTE_PORT_RANGE_END
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define H_HOST_USES_STATIC_NETIF 0 /* yet unsupported */
|
||||
|
||||
esp_err_t esp_hosted_set_default_config(void);
|
||||
bool esp_hosted_is_config_valid(void);
|
||||
|
||||
#if CONFIG_ESP_HOSTED_ENABLE_GPIO_EXPANDER
|
||||
#define H_GPIO_EXPANDER_SUPPORT 1
|
||||
#else
|
||||
#define H_GPIO_EXPANDER_SUPPORT 0
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP_HOSTED_CP_EXT_COEX
|
||||
#define H_EXT_COEX_SUPPORT 1
|
||||
#else
|
||||
#define H_EXT_COEX_SUPPORT 0
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP_HOSTED_CP_EXT_COEX_ADVANCE
|
||||
#define H_EXT_COEX_ADVANCE_SUPPORT 1
|
||||
#else
|
||||
#define H_EXT_COEX_ADVANCE_SUPPORT 0
|
||||
#endif
|
||||
|
||||
#endif /*__ESP_HOSTED_CONFIG_H__*/
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __PORT_ESP_HOSTED_HOST_LOG_H
|
||||
#define __PORT_ESP_HOSTED_HOST_LOG_H
|
||||
|
||||
#include "esp_log.h"
|
||||
|
||||
#ifndef DEFINE_LOG_TAG
|
||||
#define DEFINE_LOG_TAG(sTr) static const char TAG[] = #sTr
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* Wrapper interfaces for SDMMC to communicated with slave using SDIO */
|
||||
|
||||
#ifndef __PORT_ESP_HOSTED_HOST_OPENTHREAD_H_
|
||||
#define __PORT_ESP_HOSTED_HOST_OPENTHREAD_H_
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if CONFIG_ESP_HOSTED_HOST_OT_ENABLE
|
||||
#define H_HOST_OT_ENABLE 1
|
||||
#else
|
||||
#define H_HOST_OT_ENABLE 0
|
||||
#endif
|
||||
|
||||
// if enabled, a dedicated UART transport is used for OpenThread
|
||||
#if CONFIG_ESP_HOSTED_OT_TRANSPORT_UART
|
||||
#define H_OT_TRANSPORT_UART_DEDICATED 1
|
||||
#else
|
||||
#define H_OT_TRANSPORT_UART_DEDICATED 0
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP_HOSTED_OT_TRANSPORT_HOSTED
|
||||
#define H_OT_TRANSPORT_HOSTED 1
|
||||
#else
|
||||
#define H_OT_TRANSPORT_HOSTED 0
|
||||
#endif
|
||||
|
||||
// defines valid only for OpenThread UART Transport
|
||||
#if H_OT_TRANSPORT_UART_DEDICATED
|
||||
#define H_OT_UART_PORT CONFIG_ESP_HOSTED_OT_UART_PORT
|
||||
#define H_OT_PIN_TO_RCP_TX CONFIG_ESP_HOSTED_OT_PIN_TO_RCP_TX
|
||||
#define H_OT_PIN_TO_RCP_RX CONFIG_ESP_HOSTED_OT_PIN_TO_RCP_RX
|
||||
#define H_OT_UART_BAUDRATE CONFIG_ESP_HOSTED_OT_UART_BAUDRATE
|
||||
#define H_OT_UART_NUM_DATA_BITS CONFIG_ESP_HOSTED_OT_UART_NUM_DATA_BITS
|
||||
#define H_OT_UART_PARITY CONFIG_ESP_HOSTED_OT_UART_PARITY
|
||||
#define H_OT_UART_STOP_BITS CONFIG_ESP_HOSTED_OT_UART_STOP_BITS
|
||||
#endif //H_OT_TRANSPORT_UART_DEDICATED
|
||||
|
||||
#endif
|
||||
+163
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __PORT_ESP_HOSTED_HOST_OS_H
|
||||
#define __PORT_ESP_HOSTED_HOST_OS_H
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/event_groups.h"
|
||||
|
||||
#include "esp_task.h"
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "port_esp_hosted_host_config.h"
|
||||
#include "esp_hosted_os_abstraction.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_netif_types.h"
|
||||
#include "esp_wifi_types.h"
|
||||
#include "esp_wifi_default.h"
|
||||
|
||||
ESP_EVENT_DECLARE_BASE(WIFI_EVENT);
|
||||
#define MCU_SYS 1
|
||||
|
||||
#include "esp_dma_utils.h"
|
||||
|
||||
#define MAX_PAYLOAD_SIZE (MAX_TRANSPORT_BUFFER_SIZE-H_ESP_PAYLOAD_HEADER_OFFSET)
|
||||
|
||||
|
||||
typedef enum {
|
||||
H_TIMER_TYPE_ONESHOT = 0,
|
||||
H_TIMER_TYPE_PERIODIC = 1,
|
||||
} esp_hosted_timer_type_t;
|
||||
|
||||
|
||||
#define HOSTED_BLOCKING -1
|
||||
#define HOSTED_NON_BLOCKING 0
|
||||
|
||||
#define thread_handle_t TaskHandle_t
|
||||
#define queue_handle_t QueueHandle_t
|
||||
#define semaphore_handle_t SemaphoreHandle_t
|
||||
#define mutex_handle_t SemaphoreHandle_t
|
||||
|
||||
#define spinlock_handle_t portMUX_TYPE
|
||||
#define gpio_port_handle_t (void*)
|
||||
|
||||
#define FAST_RAM_ATTR IRAM_ATTR
|
||||
/* this is needed when there is no gpio port being used */
|
||||
#define H_GPIO_PORT_DEFAULT -1
|
||||
|
||||
#define gpio_pin_state_t int
|
||||
|
||||
#define HOSTED_BLOCK_MAX portMAX_DELAY
|
||||
|
||||
#define RPC_TASK_STACK_SIZE (5*1024)
|
||||
#define RPC_TASK_PRIO 23
|
||||
#define DFLT_TASK_STACK_SIZE (5*1024)
|
||||
#define DFLT_TASK_PRIO 23
|
||||
|
||||
|
||||
|
||||
#define H_GPIO_MODE_DEF_DISABLE (0)
|
||||
#define H_GPIO_MODE_DEF_INPUT (BIT0) ///< bit mask for input
|
||||
#define H_GPIO_MODE_DEF_OUTPUT (BIT1) ///< bit mask for output
|
||||
#define H_GPIO_MODE_DEF_OD (BIT2) ///< bit mask for OD mode
|
||||
enum {
|
||||
H_GPIO_MODE_DISABLE = H_GPIO_MODE_DEF_DISABLE, /*!< GPIO mode : disable input and output */
|
||||
H_GPIO_MODE_INPUT = H_GPIO_MODE_DEF_INPUT, /*!< GPIO mode : input only */
|
||||
H_GPIO_MODE_OUTPUT = H_GPIO_MODE_DEF_OUTPUT, /*!< GPIO mode : output only mode */
|
||||
H_GPIO_MODE_OUTPUT_OD = ((H_GPIO_MODE_DEF_OUTPUT) | (H_GPIO_MODE_DEF_OD)), /*!< GPIO mode : output only with open-drain mode */
|
||||
H_GPIO_MODE_INPUT_OUTPUT_OD = ((H_GPIO_MODE_DEF_INPUT) | (H_GPIO_MODE_DEF_OUTPUT) | (H_GPIO_MODE_DEF_OD)), /*!< GPIO mode : output and input with open-drain mode*/
|
||||
H_GPIO_MODE_INPUT_OUTPUT = ((H_GPIO_MODE_DEF_INPUT) | (H_GPIO_MODE_DEF_OUTPUT)), /*!< GPIO mode : output and input mode */
|
||||
};
|
||||
|
||||
#define H_GPIO_PULL_UP (1)
|
||||
#define H_GPIO_PULL_DOWN (0)
|
||||
|
||||
#define RET_OK 0
|
||||
#define RET_FAIL -1
|
||||
#define RET_INVALID -2
|
||||
#define RET_FAIL_MEM -3
|
||||
#define RET_FAIL4 -4
|
||||
#define RET_FAIL_TIMEOUT -5
|
||||
|
||||
#define HOSTED_MEM_ALIGNMENT_4 4
|
||||
#define HOSTED_MEM_ALIGNMENT_32 32
|
||||
#define HOSTED_MEM_ALIGNMENT_64 64
|
||||
|
||||
/** Enumeration **/
|
||||
enum hardware_type_e {
|
||||
HARDWARE_TYPE_ESP32,
|
||||
HARDWARE_TYPE_OTHER_ESP_CHIPSETS,
|
||||
HARDWARE_TYPE_INVALID,
|
||||
};
|
||||
|
||||
//TODO: redesign common code over
|
||||
|
||||
|
||||
|
||||
|
||||
#define MILLISEC_TO_SEC 1000
|
||||
#define TICKS_PER_SEC(x) (1000*(x) / portTICK_PERIOD_MS)
|
||||
#define SEC_TO_MILLISEC(x) (1000*(x))
|
||||
#define SEC_TO_MICROSEC(x) (1000*1000*(x))
|
||||
#define MILLISEC_TO_MICROSEC(x) (1000*(x))
|
||||
|
||||
#define MEM_DUMP(s) \
|
||||
ESP_LOGD(TAG, "%s free:%lu min-free:%lu lfb-def:%u lfb-8bit:%u", s, \
|
||||
(unsigned long int)esp_get_free_heap_size(), (unsigned long int)esp_get_minimum_free_heap_size(), \
|
||||
heap_caps_get_largest_free_block(MALLOC_CAP_DEFAULT), \
|
||||
heap_caps_get_largest_free_block(MALLOC_CAP_8BIT))
|
||||
|
||||
|
||||
/* -------- Create handle ------- */
|
||||
#define HOSTED_CREATE_HANDLE(tYPE, hANDLE) { \
|
||||
hANDLE = (tYPE *)g_h.funcs->_h_malloc(sizeof(tYPE)); \
|
||||
if (!hANDLE) { \
|
||||
ESP_LOGE(TAG, "%s:%u Mem alloc fail while create handle", __func__,__LINE__); \
|
||||
return NULL; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define HOSTED_FREE_HANDLE(handle) { \
|
||||
if (handle) { \
|
||||
g_h.funcs->_h_free(handle); \
|
||||
handle = NULL; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* -------- Calloc, Free handle ------- */
|
||||
#define HOSTED_FREE(buff) if (buff) { g_h.funcs->_h_free(buff); buff = NULL; }
|
||||
#define HOSTED_CALLOC(struct_name, buff, nbytes, gotosym) do { \
|
||||
buff = (struct_name *)g_h.funcs->_h_calloc(1, nbytes); \
|
||||
if (!buff) { \
|
||||
ESP_LOGE(TAG, "%s, Failed to allocate memory", __func__); \
|
||||
goto gotosym; \
|
||||
} \
|
||||
} while(0);
|
||||
|
||||
#define HOSTED_MALLOC(struct_name, buff, nbytes, gotosym) do { \
|
||||
buff = (struct_name *)g_h.funcs->_h_malloc(nbytes); \
|
||||
if (!buff) { \
|
||||
ESP_LOGE(TAG, "%s, Failed to allocate memory", __func__); \
|
||||
goto gotosym; \
|
||||
} \
|
||||
} while(0);
|
||||
|
||||
/* Driver Handle */
|
||||
struct serial_drv_handle_t;
|
||||
|
||||
/* Timer handle */
|
||||
struct timer_handle_t;
|
||||
extern struct mempool * nw_mp_g;
|
||||
|
||||
#endif
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* Wrapper interfaces for SDMMC to communicated with slave using SDIO */
|
||||
|
||||
#ifndef __PORT_ESP_HOSTED_HOST_SDIO_H_
|
||||
#define __PORT_ESP_HOSTED_HOST_SDIO_H_
|
||||
|
||||
#include "esp_check.h"
|
||||
#include "sdmmc_cmd.h"
|
||||
|
||||
#define MAX_TRANSPORT_BUFFER_SIZE MAX_SDIO_BUFFER_SIZE
|
||||
#define ESP_HOSTED_SDIO_UNRESPONSIVE_CODE 0x107
|
||||
|
||||
/* Hosted init function to init the SDIO host
|
||||
* returns a pointer to the sdio context */
|
||||
void * hosted_sdio_init(void);
|
||||
|
||||
/* Hosted SDIO deinit function
|
||||
* expects a pointer to the sdio context */
|
||||
int hosted_sdio_deinit(void *ctx);
|
||||
|
||||
/* Hosted SDIO to initialise the SDIO card */
|
||||
int hosted_sdio_card_init(void *ctx, bool show_config);
|
||||
|
||||
/* Hosted SDIO to deinitialise the SDIO card */
|
||||
int hosted_sdio_card_deinit(void *ctx);
|
||||
|
||||
/* Hosted SDIO functions to read / write to slave scratch registers
|
||||
* and to read / write block data
|
||||
* If lock_required is true, call will hold a mutex for the duration of the call */
|
||||
int hosted_sdio_read_reg(void *ctx, uint32_t reg, uint8_t *data, uint16_t size, bool lock_required);
|
||||
int hosted_sdio_write_reg(void *ctx, uint32_t reg, uint8_t *data, uint16_t size, bool lock_required);
|
||||
int hosted_sdio_read_block(void *ctx, uint32_t reg, uint8_t *data, uint16_t size, bool lock_required);
|
||||
int hosted_sdio_write_block(void *ctx, uint32_t reg, uint8_t *data, uint16_t size, bool lock_required);
|
||||
|
||||
/* Hosted SDIO function that will block waiting for a SDIO interrupt from the slave
|
||||
* returns when there is an interrupt or timeout */
|
||||
int hosted_sdio_wait_slave_intr(void *ctx, uint32_t ticks_to_wait);
|
||||
|
||||
#endif
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* Wrapper interfaces for SPI to communicated with slave using SDIO */
|
||||
|
||||
#ifndef __PORT_ESP_HOSTED_HOST_SPI_H_
|
||||
#define __PORT_ESP_HOSTED_HOST_SPI_H_
|
||||
|
||||
#define MAX_TRANSPORT_BUFFER_SIZE MAX_SPI_BUFFER_SIZE
|
||||
/* Hosted SPI init function
|
||||
* returns a pointer to the spi context */
|
||||
void * hosted_spi_init(void);
|
||||
|
||||
/* Hosted SPI deinit function */
|
||||
int hosted_spi_deinit(void *handle);
|
||||
|
||||
/* Hosted SPI transfer function */
|
||||
int hosted_do_spi_transfer(void *trans);
|
||||
|
||||
#endif
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* Wrapper interfaces for SDMMC to communicated with slave using SDIO */
|
||||
|
||||
#ifndef __PORT_ESP_HOSTED_HOST_SPI_HD_H_
|
||||
#define __PORT_ESP_HOSTED_HOST_SPI_HD_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "esp_check.h"
|
||||
|
||||
#define MAX_TRANSPORT_BUFFER_SIZE MAX_SPI_HD_BUFFER_SIZE
|
||||
|
||||
/* Hosted init function to init the SPI HD host
|
||||
* returns a pointer to the sdio context */
|
||||
void * hosted_spi_hd_init(void);
|
||||
|
||||
/* Hosted SPI_HD deinit function
|
||||
* expects a pointer to the spi_hd context */
|
||||
esp_err_t hosted_spi_hd_deinit(void *ctx);
|
||||
|
||||
/* Hosted SPI_HD functions to read from / write to 32-bit slave shared registers.
|
||||
* If poll > 0, call will read the register up to poll times until the value is stable
|
||||
* this will return an error if value is not stable at the end
|
||||
* (slave register value may change during SPI read)
|
||||
* If lock_required is true, call will hold a mutex for the duration of the call */
|
||||
int hosted_spi_hd_read_reg(uint32_t reg, uint32_t *data, int poll, bool lock_required);
|
||||
int hosted_spi_hd_write_reg(uint32_t reg, uint32_t *data, bool lock_required);
|
||||
|
||||
/* Hosted SPI_HD functions to read / write data from / to slave using DMA */
|
||||
int hosted_spi_hd_read_dma(uint8_t *data, uint16_t size, bool lock_required);
|
||||
int hosted_spi_hd_write_dma(uint8_t *data, uint16_t size, bool lock_required);
|
||||
|
||||
/* Hosted SPI_HD function to reconfigure the number of data lines used */
|
||||
int hosted_spi_hd_set_data_lines(uint32_t data_lines);
|
||||
|
||||
/* Hosted SPI_HD function to send CMD9 (host interrupt to slave) */
|
||||
int hosted_spi_hd_send_cmd9(void);
|
||||
|
||||
#endif
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* Wrapper interfaces for UART to communicated with slave using UART */
|
||||
|
||||
#ifndef __PORT_ESP_HOSTED_HOST_UART_H_
|
||||
#define __PORT_ESP_HOSTED_HOST_UART_H_
|
||||
|
||||
#define MAX_TRANSPORT_BUFFER_SIZE MAX_UART_BUFFER_SIZE
|
||||
|
||||
/* Hosted init function to init the UART interface
|
||||
* returns a pointer to the UART context */
|
||||
void * hosted_uart_init(void);
|
||||
|
||||
/* Hosted UART deinit function
|
||||
* expects a pointer to the UART context */
|
||||
esp_err_t hosted_uart_deinit(void *ctx);
|
||||
|
||||
/* Hosted UART functions to read / write
|
||||
* Returns -1 (error) or number of bytes read / written */
|
||||
int hosted_uart_read(void *ctx, uint8_t *data, uint16_t size);
|
||||
int hosted_uart_write(void *ctx, uint8_t *data, uint16_t size);
|
||||
int hosted_uart_flush_input(void * ctx);
|
||||
|
||||
/* Hosted UART function to wait until there is Rx data
|
||||
* Returns -1 (error) or number of bytes to read */
|
||||
int hosted_wait_rx_data(uint32_t ticks_to_wait);
|
||||
#endif
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __PORT_ESP_HOSTED_HOST_WIFI_CONFIG_H__
|
||||
#define __PORT_ESP_HOSTED_HOST_WIFI_CONFIG_H__
|
||||
|
||||
#include "esp_idf_version.h"
|
||||
|
||||
#if CONFIG_ESP_HOSTED_ENABLE_ITWT && CONFIG_SLAVE_SOC_WIFI_HE_SUPPORT
|
||||
#define H_WIFI_HE_SUPPORT 1
|
||||
#else
|
||||
#define H_WIFI_HE_SUPPORT 0
|
||||
#endif
|
||||
|
||||
// HE support (structs, API) changed after ESP-IDF v5.3
|
||||
#if H_WIFI_HE_SUPPORT && (ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(5, 3, 0))
|
||||
#define H_WIFI_HE_GREATER_THAN_ESP_IDF_5_3 1
|
||||
#else
|
||||
#define H_WIFI_HE_GREATER_THAN_ESP_IDF_5_3 0
|
||||
#endif
|
||||
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 0)
|
||||
/* dual band API support available */
|
||||
#define H_WIFI_DUALBAND_SUPPORT 1
|
||||
#else
|
||||
#define H_WIFI_DUALBAND_SUPPORT 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP_WIFI_REMOTE_EAP_ENABLED
|
||||
#define H_WIFI_ENTERPRISE_SUPPORT 1
|
||||
#else
|
||||
#define H_WIFI_ENTERPRISE_SUPPORT 0
|
||||
#endif
|
||||
|
||||
/* ESP-IDF 5.5.0 breaking change: reserved/he_reserved renamed to reserved1/reserved2 */
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0)
|
||||
#define H_WIFI_NEW_RESERVED_FIELD_NAMES 1
|
||||
#define H_PRESENT_IN_ESP_IDF_5_5_0 1
|
||||
#else
|
||||
#define H_WIFI_NEW_RESERVED_FIELD_NAMES 0
|
||||
#define H_PRESENT_IN_ESP_IDF_5_5_0 0
|
||||
#endif
|
||||
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 0)
|
||||
#define H_PRESENT_IN_ESP_IDF_5_4_0 1
|
||||
#else
|
||||
#define H_PRESENT_IN_ESP_IDF_5_4_0 0
|
||||
#endif
|
||||
|
||||
/* User-controllable reserved field decoding - works regardless of IDF version */
|
||||
#ifdef CONFIG_ESP_HOSTED_DECODE_WIFI_RESERVED_FIELD
|
||||
#define H_DECODE_WIFI_RESERVED_FIELD 1
|
||||
#else
|
||||
#define H_DECODE_WIFI_RESERVED_FIELD 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* wifi_twt_config_t::twt_enable_keep_alive only found in
|
||||
* IDF v5.3.2 and above
|
||||
*/
|
||||
#if ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(5, 3, 1)
|
||||
#define H_GOT_TWT_ENABLE_KEEP_ALIVE 1
|
||||
#else
|
||||
#define H_GOT_TWT_ENABLE_KEEP_ALIVE 0
|
||||
#endif
|
||||
|
||||
/* wifi_ap_config_t::transition_disable only found in
|
||||
* IDF v5.3.3 and above, or
|
||||
* IDF v5.4.1 and above
|
||||
*/
|
||||
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 3) && ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 0)) || \
|
||||
(ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 1))
|
||||
#define H_GOT_AP_CONFIG_PARAM_TRANSITION_DISABLE 1
|
||||
#else
|
||||
#define H_GOT_AP_CONFIG_PARAM_TRANSITION_DISABLE 0
|
||||
#endif
|
||||
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0)
|
||||
#define H_PRESENT_IN_ESP_IDF_6_0_0 1
|
||||
#else
|
||||
#define H_PRESENT_IN_ESP_IDF_6_0_0 0
|
||||
#endif
|
||||
|
||||
#if ((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 4) && ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 0)) || \
|
||||
(ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 3) && ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 5, 0)) || \
|
||||
(ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 1)))
|
||||
#define H_GOT_SET_EAP_METHODS_API 1
|
||||
#else
|
||||
#define H_GOT_SET_EAP_METHODS_API 0
|
||||
#endif
|
||||
|
||||
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 4) && ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 0)) || \
|
||||
(ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 3))
|
||||
#define H_GOT_EAP_SET_DOMAIN_NAME 1
|
||||
#else
|
||||
#define H_GOT_EAP_SET_DOMAIN_NAME 0
|
||||
#endif
|
||||
|
||||
#if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 3))
|
||||
#define H_GOT_EAP_OKC_SUPPORT 0
|
||||
#else
|
||||
#define H_GOT_EAP_OKC_SUPPORT 1
|
||||
#endif
|
||||
/**
|
||||
* Wi-Fi Easy Connect (DPP) events is returned to user via
|
||||
* Supplicant Callback or Wi-Fi DPP events,
|
||||
* depending on IDF version
|
||||
*
|
||||
* IDF v6.0 and above only support Wi-Fi DPP events
|
||||
* IDF v5.5 support Wi-Fi and Supplicant DPP events
|
||||
* earlier versions support only Supplicant DPP events
|
||||
*/
|
||||
// Supplicant Callback DPP Events: still available, but deprecated
|
||||
#if CONFIG_ESP_HOSTED_ENABLE_DPP && (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(6, 0, 0))
|
||||
#define H_SUPP_DPP_SUPPORT 1
|
||||
#else
|
||||
#define H_SUPP_DPP_SUPPORT 0
|
||||
#endif
|
||||
|
||||
// Wi-Fi DPP Events: only in IDF v5.5 and above
|
||||
#if CONFIG_ESP_HOSTED_ENABLE_DPP && (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0))
|
||||
#define H_WIFI_DPP_SUPPORT 1
|
||||
#else
|
||||
#define H_WIFI_DPP_SUPPORT 0
|
||||
#endif
|
||||
|
||||
// for generic DPP support
|
||||
#if H_SUPP_DPP_SUPPORT || H_WIFI_DPP_SUPPORT
|
||||
#define H_DPP_SUPPORT 1
|
||||
#else
|
||||
#define H_DPP_SUPPORT 0
|
||||
#endif
|
||||
|
||||
// this sets the maximum length of the URI we can receive to generate
|
||||
// the QR code
|
||||
#if H_DPP_SUPPORT
|
||||
#define H_DPP_URI_LEN_MAX CONFIG_ESP_HOSTED_DPP_URI_LEN_MAX
|
||||
#endif
|
||||
|
||||
#endif /* __ESP_HOSTED_WIFI_CONFIG_H__ */
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "esp_hosted.h"
|
||||
|
||||
#include "port_esp_hosted_host_log.h"
|
||||
|
||||
#include "esp_private/startup_internal.h"
|
||||
|
||||
DEFINE_LOG_TAG(host_init);
|
||||
|
||||
//ESP_SYSTEM_INIT_FN(esp_hosted_host_init, BIT(0), 120)
|
||||
static void __attribute__((constructor)) esp_hosted_host_init(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "ESP Hosted : Host chip_ip[%d]", CONFIG_IDF_FIRMWARE_CHIP_ID);
|
||||
ESP_ERROR_CHECK(esp_hosted_init());
|
||||
}
|
||||
|
||||
static void __attribute__((destructor)) esp_hosted_host_deinit(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "ESP Hosted deinit");
|
||||
esp_hosted_deinit();
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "driver/uart.h"
|
||||
|
||||
#include "esp_hosted_openthread.h"
|
||||
#include "port_esp_hosted_host_config.h"
|
||||
#include "port_esp_hosted_host_openthread.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
static const char TAG[] = "h_ot_util";
|
||||
|
||||
esp_err_t esp_hosted_openthread_get_radio_config(esp_hosted_openthread_radio_config_t *config)
|
||||
{
|
||||
if (!config)
|
||||
return ESP_FAIL;
|
||||
|
||||
#if H_OT_TRANSPORT_UART_DEDICATED
|
||||
ESP_LOGD(TAG, "returning dedicated OpenThread UART config");
|
||||
config->type = HOSTED_OPENTHREAD_TRANSPORT_UART;
|
||||
esp_hosted_openthread_uart_config_t *uart_config = &config->radio_uart_config;
|
||||
|
||||
uart_config->port = H_OT_UART_PORT;
|
||||
uart_config->baud_rate = H_OT_UART_BAUDRATE;
|
||||
uart_config->data_bits = H_OT_UART_NUM_DATA_BITS;
|
||||
uart_config->parity = H_OT_UART_PARITY;
|
||||
uart_config->stop_bits = H_OT_UART_STOP_BITS;
|
||||
uart_config->flow_ctrl = UART_HW_FLOWCTRL_DISABLE;
|
||||
uart_config->rx_flow_ctrl_thresh = 0;
|
||||
uart_config->source_clk = UART_SCLK_DEFAULT;
|
||||
uart_config->rx_pin = H_OT_PIN_TO_RCP_TX;
|
||||
uart_config->tx_pin = H_OT_PIN_TO_RCP_RX;
|
||||
|
||||
return ESP_OK;
|
||||
#endif
|
||||
#if H_OT_TRANSPORT_HOSTED
|
||||
#error OpenThread over ESP-Hosted transport not yet supported
|
||||
return ESP_FAIL;
|
||||
#endif
|
||||
}
|
||||
+628
@@ -0,0 +1,628 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_idf_version.h"
|
||||
#include "driver/sdmmc_defs.h"
|
||||
#include "driver/sdmmc_host.h"
|
||||
|
||||
#include "port_esp_hosted_host_os.h"
|
||||
#include "sdio_reg.h"
|
||||
#include "port_esp_hosted_host_sdio.h"
|
||||
#include "esp_hosted_transport_config.h"
|
||||
#include "port_esp_hosted_host_config.h"
|
||||
#include "port_esp_hosted_host_log.h"
|
||||
|
||||
#if H_SDIO_PWR_CTRL_LDO
|
||||
#include "sd_pwr_ctrl_by_on_chip_ldo.h"
|
||||
#endif
|
||||
|
||||
#include "soc/sdmmc_pins.h"
|
||||
#include "hal/sdmmc_ll.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "esp_heap_caps.h"
|
||||
DEFINE_LOG_TAG(sdio_wrapper);
|
||||
|
||||
#define CIS_BUFFER_SIZE 256
|
||||
#define FUNC1_EN_MASK (BIT(1))
|
||||
#define SDIO_INIT_MAX_RETRY 10 // max number of times we try to init SDIO FN 1
|
||||
|
||||
#define SDIO_FAIL_IF_NULL(x) do { \
|
||||
if (!x) return ESP_FAIL; \
|
||||
} while (0);
|
||||
|
||||
#define SDIO_LOCK(x) do { \
|
||||
if (x) g_h.funcs->_h_lock_mutex(sdio_bus_lock, HOSTED_BLOCK_MAX); \
|
||||
} while (0);
|
||||
|
||||
#define SDIO_UNLOCK(x) do { \
|
||||
if (x) g_h.funcs->_h_unlock_mutex(sdio_bus_lock); \
|
||||
} while (0);
|
||||
|
||||
typedef struct {
|
||||
sdmmc_card_t *card;
|
||||
struct esp_hosted_sdio_config config;
|
||||
} sdmmc_context_t;
|
||||
|
||||
static sdmmc_context_t context = { 0 };
|
||||
|
||||
static void * sdio_bus_lock;
|
||||
|
||||
/* DeskLock fork fix (#167): aligned bounce buffer for misaligned TX payloads.
|
||||
* See hosted_sdio_write_block. TX is serialized by the bus lock -> one is safe. */
|
||||
static uint8_t *s_tx_bounce_buf;
|
||||
static size_t s_tx_bounce_sz;
|
||||
|
||||
// workarounds for known ESP-IDF SDMMC issues
|
||||
static void hosted_sdio_workaround(int slot, sdmmc_slot_config_t *slot_config)
|
||||
{
|
||||
if (slot == 0) {
|
||||
#if !SDMMC_LL_SLOT_SUPPORT_GPIO_MATRIX(0)
|
||||
/* workaround for 1-bit mode on Slot 0 with IOMUX only pins:
|
||||
* set gpio pins D2, D3 to pass sdmmc_host.c->sdmmc_host_init_slot() IOMUX GPIO checking
|
||||
*/
|
||||
if (slot_config->width == 1) {
|
||||
ESP_LOGW(TAG, "workaround: setting D2-D3 in 1 bit mode for slot %d", slot);
|
||||
slot_config->d2 = SDMMC_SLOT0_IOMUX_PIN_NUM_D2;
|
||||
slot_config->d3 = SDMMC_SLOT0_IOMUX_PIN_NUM_D3;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static bool hosted_sdio_enable_ldo(sdmmc_host_t *config)
|
||||
{
|
||||
#if H_SDIO_PWR_CTRL_LDO
|
||||
// enable LDO Power for slot, if required
|
||||
sd_pwr_ctrl_ldo_config_t ldo_config = {
|
||||
.ldo_chan_id = H_SDIO_PWR_CTRL_LDO_ID,
|
||||
};
|
||||
sd_pwr_ctrl_handle_t pwr_ctrl_handle = NULL;
|
||||
|
||||
esp_err_t ret = sd_pwr_ctrl_new_on_chip_ldo(&ldo_config, &pwr_ctrl_handle);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to create a new on-chip LDO power control driver");
|
||||
return false;
|
||||
}
|
||||
config->pwr_ctrl_handle = pwr_ctrl_handle;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
static esp_err_t hosted_sdio_print_cis_information(sdmmc_card_t* card)
|
||||
{
|
||||
uint8_t cis_buffer[CIS_BUFFER_SIZE];
|
||||
size_t cis_data_len = 1024; //specify maximum searching range to avoid infinite loop
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
SDIO_FAIL_IF_NULL(card);
|
||||
|
||||
ret = sdmmc_io_get_cis_data(card, cis_buffer, CIS_BUFFER_SIZE, &cis_data_len);
|
||||
if (ret == ESP_ERR_INVALID_SIZE) {
|
||||
int temp_buf_size = cis_data_len;
|
||||
uint8_t* temp_buf = g_h.funcs->_h_malloc(temp_buf_size);
|
||||
assert(temp_buf);
|
||||
|
||||
ESP_LOGW(TAG, "CIS data longer than expected, temporary buffer allocated.");
|
||||
ret = sdmmc_io_get_cis_data(card, temp_buf, temp_buf_size, &cis_data_len);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "failed to get CIS data.");
|
||||
HOSTED_FREE(temp_buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
sdmmc_io_print_cis_info(temp_buf, cis_data_len, NULL);
|
||||
|
||||
HOSTED_FREE(temp_buf);
|
||||
} else if (ret == ESP_OK) {
|
||||
sdmmc_io_print_cis_info(cis_buffer, cis_data_len, NULL);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "failed to get CIS data.");
|
||||
return ret;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t hosted_sdio_set_blocksize(sdmmc_card_t *card, uint8_t fn, uint16_t value)
|
||||
{
|
||||
size_t offset = SD_IO_FBR_START * fn;
|
||||
const uint8_t *bs_u8 = (const uint8_t *) &value;
|
||||
uint16_t bs_read = 0;
|
||||
uint8_t *bs_read_u8 = (uint8_t *) &bs_read;
|
||||
|
||||
// Set and read back block size
|
||||
ESP_ERROR_CHECK(sdmmc_io_write_byte(card, SDIO_FUNC_0, offset + SD_IO_CCCR_BLKSIZEL, bs_u8[0], NULL));
|
||||
ESP_ERROR_CHECK(sdmmc_io_write_byte(card, SDIO_FUNC_0, offset + SD_IO_CCCR_BLKSIZEH, bs_u8[1], NULL));
|
||||
ESP_ERROR_CHECK(sdmmc_io_read_byte(card, SDIO_FUNC_0, offset + SD_IO_CCCR_BLKSIZEL, &bs_read_u8[0]));
|
||||
ESP_ERROR_CHECK(sdmmc_io_read_byte(card, SDIO_FUNC_0, offset + SD_IO_CCCR_BLKSIZEH, &bs_read_u8[1]));
|
||||
ESP_LOGI(TAG, "Function %d Blocksize: %d", fn, (unsigned int) bs_read);
|
||||
|
||||
if (bs_read == value)
|
||||
return ESP_OK;
|
||||
else
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
static esp_err_t hosted_sdio_card_fn_init(sdmmc_card_t *card)
|
||||
{
|
||||
uint8_t ioe = 0;
|
||||
uint8_t ior = 0;
|
||||
uint8_t ie = 0;
|
||||
uint8_t bus_width = 0;
|
||||
uint16_t bs = 0;
|
||||
int i = 0;
|
||||
|
||||
SDIO_FAIL_IF_NULL(card);
|
||||
|
||||
/** initial register reads may fail if SDIO device is not yet ready
|
||||
* return ESP_FAIL to let upper layers retry card init
|
||||
*/
|
||||
if (ESP_OK != sdmmc_io_read_byte(card, SDIO_FUNC_0, SD_IO_CCCR_FN_ENABLE, &ioe))
|
||||
return ESP_FAIL;
|
||||
|
||||
ESP_LOGD(TAG, "IOE: 0x%02x", ioe);
|
||||
|
||||
if (ESP_OK != sdmmc_io_read_byte(card, SDIO_FUNC_0, SD_IO_CCCR_FN_READY, &ior))
|
||||
return ESP_FAIL;
|
||||
|
||||
ESP_LOGD(TAG, "IOR: 0x%02x", ior);
|
||||
|
||||
// enable function 1
|
||||
ioe |= FUNC1_EN_MASK;
|
||||
if (ESP_OK != sdmmc_io_write_byte(card, SDIO_FUNC_0, SD_IO_CCCR_FN_ENABLE, ioe, &ioe))
|
||||
return ESP_FAIL;
|
||||
ESP_LOGD(TAG, "IOE: 0x%02x", ioe);
|
||||
|
||||
if (ESP_OK != sdmmc_io_read_byte(card, SDIO_FUNC_0, SD_IO_CCCR_FN_ENABLE, &ioe))
|
||||
return ESP_FAIL;
|
||||
ESP_LOGD(TAG, "IOE: 0x%02x", ioe);
|
||||
|
||||
// wait for the card to become ready
|
||||
ior = 0;
|
||||
for (i = 0; i < SDIO_INIT_MAX_RETRY; i++) {
|
||||
if (ESP_OK != sdmmc_io_read_byte(card, SDIO_FUNC_0, SD_IO_CCCR_FN_READY, &ior))
|
||||
return ESP_FAIL;
|
||||
ESP_LOGD(TAG, "IOR: 0x%02x", ior);
|
||||
if (ior & FUNC1_EN_MASK) {
|
||||
break;
|
||||
} else {
|
||||
usleep(10 * 1000);
|
||||
}
|
||||
}
|
||||
if (i >= SDIO_INIT_MAX_RETRY) {
|
||||
// card failed to become ready
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// get interrupt status
|
||||
ESP_ERROR_CHECK(sdmmc_io_read_byte(card, SDIO_FUNC_0, SD_IO_CCCR_INT_ENABLE, &ie));
|
||||
ESP_LOGD(TAG, "IE: 0x%02x", ie);
|
||||
|
||||
// enable interrupts for function 1 and master enable
|
||||
ie |= BIT(0) | FUNC1_EN_MASK;
|
||||
ESP_ERROR_CHECK(sdmmc_io_write_byte(card, SDIO_FUNC_0, SD_IO_CCCR_INT_ENABLE, ie, NULL));
|
||||
|
||||
ESP_ERROR_CHECK(sdmmc_io_read_byte(card, SDIO_FUNC_0, SD_IO_CCCR_INT_ENABLE, &ie));
|
||||
ESP_LOGD(TAG, "IE: 0x%02x", ie);
|
||||
|
||||
// get bus width register
|
||||
ESP_ERROR_CHECK(sdmmc_io_read_byte(card, SDIO_FUNC_0, SD_IO_CCCR_BUS_WIDTH, &bus_width));
|
||||
ESP_LOGD(TAG, "BUS_WIDTH: 0x%02x", bus_width);
|
||||
|
||||
// skip enable of continuous SPI interrupts
|
||||
|
||||
// set FN0 block size to 512
|
||||
bs = 512;
|
||||
ESP_ERROR_CHECK(hosted_sdio_set_blocksize(card, SDIO_FUNC_0, bs));
|
||||
|
||||
// set FN1 block size to 512
|
||||
bs = 512;
|
||||
ESP_ERROR_CHECK(hosted_sdio_set_blocksize(card, SDIO_FUNC_1, bs));
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t sdio_read_fromio(sdmmc_card_t *card, uint32_t function, uint32_t addr,
|
||||
uint8_t *data, uint16_t size)
|
||||
{
|
||||
uint16_t remainder = size;
|
||||
uint16_t blocks;
|
||||
esp_err_t res;
|
||||
uint8_t *ptr = data;
|
||||
|
||||
// do block mode transfer
|
||||
while (remainder >= ESP_BLOCK_SIZE) {
|
||||
blocks = H_SDIO_RX_BLOCKS_TO_TRANSFER(remainder);
|
||||
size = blocks * ESP_BLOCK_SIZE;
|
||||
res = sdmmc_io_read_blocks(card, function, addr, ptr, size);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
remainder -= size;
|
||||
ptr += size;
|
||||
addr += size;
|
||||
}
|
||||
|
||||
// transfer remainder using byte mode
|
||||
while (remainder > 0) {
|
||||
size = remainder;
|
||||
res = sdmmc_io_read_bytes(card, function, addr, ptr, size);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
remainder -= size;
|
||||
ptr += size;
|
||||
addr += size;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t sdio_write_toio(sdmmc_card_t *card, uint32_t function, uint32_t addr,
|
||||
uint8_t *data, uint16_t size)
|
||||
{
|
||||
uint16_t remainder = size;
|
||||
uint16_t blocks;
|
||||
esp_err_t res;
|
||||
uint8_t *ptr = data;
|
||||
|
||||
// do block mode transfer
|
||||
while (remainder >= ESP_BLOCK_SIZE) {
|
||||
blocks = H_SDIO_TX_BLOCKS_TO_TRANSFER(remainder);
|
||||
size = blocks * ESP_BLOCK_SIZE;
|
||||
res = sdmmc_io_write_blocks(card, function, addr, ptr, size);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
remainder -= size;
|
||||
ptr += size;
|
||||
addr += size;
|
||||
}
|
||||
|
||||
// transfer remainder using byte mode
|
||||
while (remainder > 0) {
|
||||
size = remainder;
|
||||
res = sdmmc_io_write_bytes(card, function, addr, ptr, size);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
remainder -= size;
|
||||
ptr += size;
|
||||
addr += size;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int hosted_sdio_deinit(void* ctx)
|
||||
{
|
||||
SDIO_FAIL_IF_NULL(ctx);
|
||||
|
||||
sdmmc_context_t *context = (sdmmc_context_t *)ctx;
|
||||
|
||||
if (s_tx_bounce_buf) {
|
||||
heap_caps_free(s_tx_bounce_buf);
|
||||
s_tx_bounce_buf = NULL;
|
||||
s_tx_bounce_sz = 0;
|
||||
}
|
||||
|
||||
HOSTED_FREE(context->card);
|
||||
|
||||
if (sdio_bus_lock) {
|
||||
g_h.funcs->_h_destroy_mutex(sdio_bus_lock);
|
||||
sdio_bus_lock = NULL;
|
||||
}
|
||||
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 0)
|
||||
sdmmc_host_deinit_slot(context->config.slot);
|
||||
#else
|
||||
/* slot-scoped deinit added in IDF v5.4 */
|
||||
sdmmc_host_deinit();
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void * hosted_sdio_init(void)
|
||||
{
|
||||
esp_err_t res;
|
||||
bool got_valid_config = false;
|
||||
|
||||
/* Guard against multiple initialization */
|
||||
if (sdio_bus_lock) {
|
||||
ESP_LOGW(TAG, "SDIO already initialized, skipping");
|
||||
return (void *)&context;
|
||||
}
|
||||
|
||||
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
|
||||
|
||||
if (esp_hosted_transport_is_config_valid()) {
|
||||
// copy sdio config if valid
|
||||
struct esp_hosted_transport_config *pconfig;
|
||||
|
||||
if (ESP_TRANSPORT_OK == esp_hosted_transport_get_config(&pconfig)) {
|
||||
if (pconfig->transport_in_use == H_TRANSPORT_SDIO) {
|
||||
struct esp_hosted_sdio_config *psdio_config;
|
||||
|
||||
if (ESP_TRANSPORT_OK == esp_hosted_sdio_get_config(&psdio_config)) {
|
||||
// copy transport config
|
||||
g_h.funcs->_h_memcpy(&context.config, psdio_config, sizeof(struct esp_hosted_sdio_config));
|
||||
got_valid_config = true;
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "transport config is not for SDIO: ignoring");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!got_valid_config) {
|
||||
// no valid transport config: use values from esp_hosted_config.h
|
||||
context.config.clock_freq_khz = H_SDIO_CLOCK_FREQ_KHZ;
|
||||
context.config.bus_width = H_SDIO_BUS_WIDTH;
|
||||
context.config.slot = H_SDMMC_HOST_SLOT;
|
||||
context.config.pin_clk.pin = H_SDIO_PIN_CLK;
|
||||
context.config.pin_cmd.pin = H_SDIO_PIN_CMD;
|
||||
context.config.pin_d0.pin = H_SDIO_PIN_D0;
|
||||
context.config.pin_d1.pin = H_SDIO_PIN_D1;
|
||||
context.config.pin_d2.pin = H_SDIO_PIN_D2;
|
||||
context.config.pin_d3.pin = H_SDIO_PIN_D3;
|
||||
}
|
||||
|
||||
// initialise SDMMC host
|
||||
res = sdmmc_host_init();
|
||||
if (res != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to initialize SDMMC host");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// configure SDIO interface and slot
|
||||
slot_config.width = context.config.bus_width;
|
||||
#if defined(H_SDIO_SOC_USE_GPIO_MATRIX)
|
||||
slot_config.clk = context.config.pin_clk.pin;
|
||||
slot_config.cmd = context.config.pin_cmd.pin;
|
||||
slot_config.d0 = context.config.pin_d0.pin;
|
||||
slot_config.d1 = context.config.pin_d1.pin;
|
||||
slot_config.d2 = context.config.pin_d2.pin;
|
||||
slot_config.d3 = context.config.pin_d3.pin;
|
||||
#endif
|
||||
|
||||
hosted_sdio_workaround(context.config.slot, &slot_config);
|
||||
|
||||
res = sdmmc_host_init_slot(context.config.slot, &slot_config);
|
||||
if (res != ESP_OK) {
|
||||
ESP_LOGE(TAG, "init SDMMC Host slot %d failed", H_SDMMC_HOST_SLOT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// initialise connected SDIO card/slave
|
||||
context.card = (sdmmc_card_t *)g_h.funcs->_h_malloc(sizeof(sdmmc_card_t));
|
||||
if (!context.card) {
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for SDMMC card");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// initialise mutex for bus locking
|
||||
sdio_bus_lock = g_h.funcs->_h_create_mutex();
|
||||
assert(sdio_bus_lock);
|
||||
|
||||
return (void *)&context;
|
||||
}
|
||||
|
||||
int hosted_sdio_card_init(void *ctx, bool show_config)
|
||||
{
|
||||
SDIO_FAIL_IF_NULL(ctx);
|
||||
|
||||
sdmmc_context_t *context = (sdmmc_context_t *)ctx;
|
||||
|
||||
struct esp_hosted_sdio_config *sdio_config = &context->config;
|
||||
SDIO_FAIL_IF_NULL(sdio_config);
|
||||
SDIO_FAIL_IF_NULL(context->card);
|
||||
|
||||
sdmmc_host_t config = SDMMC_HOST_DEFAULT();
|
||||
config.slot = sdio_config->slot; // override default slot set
|
||||
|
||||
if (!hosted_sdio_enable_ldo(&config)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
config.max_freq_khz = sdio_config->clock_freq_khz;
|
||||
if (show_config) {
|
||||
ESP_LOGI(TAG, "SDIO master: Slot %d, Data-Lines: %d-bit Freq(KHz)[%u KHz]",
|
||||
config.slot,
|
||||
sdio_config->bus_width==4? 4:1,
|
||||
config.max_freq_khz);
|
||||
if (sdio_config->bus_width == 4) {
|
||||
ESP_LOGI(TAG, "GPIOs: CLK[%u] CMD[%u] D0[%u] D1[%u] D2[%u] D3[%u] Slave_Reset[%u]",
|
||||
sdio_config->pin_clk.pin, sdio_config->pin_cmd.pin,
|
||||
sdio_config->pin_d0.pin, sdio_config->pin_d1.pin,
|
||||
sdio_config->pin_d2.pin, sdio_config->pin_d3.pin,
|
||||
sdio_config->pin_reset.pin);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "GPIOs: CLK[%u] CMD[%u] D0[%u] D1[%u] Slave_Reset[%u]",
|
||||
sdio_config->pin_clk.pin, sdio_config->pin_cmd.pin,
|
||||
sdio_config->pin_d0.pin, sdio_config->pin_d1.pin,
|
||||
sdio_config->pin_reset.pin);
|
||||
}
|
||||
ESP_LOGI(TAG, "Queues: Tx[%u] Rx[%u] SDIO-Rx-Mode[%u]",
|
||||
sdio_config->tx_queue_size, sdio_config->rx_queue_size,
|
||||
sdio_config->rx_mode);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32P4
|
||||
// Set this flag to allocate aligned buffer of 512 bytes to meet
|
||||
// DMA's requirements for CMD53 byte mode. Mandatory when any
|
||||
// buffer is behind the cache, or not aligned to 4 byte boundary.
|
||||
config.flags |= SDMMC_HOST_FLAG_ALLOC_ALIGNED_BUF;
|
||||
#endif
|
||||
|
||||
if (sdmmc_card_init(&config, context->card) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "sdmmc_card_init failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (esp_log_level_get(TAG) >= ESP_LOG_DEBUG) {
|
||||
// output CIS info from the slave
|
||||
sdmmc_card_print_info(stdout, context->card);
|
||||
|
||||
if (hosted_sdio_print_cis_information(context->card) != ESP_OK) {
|
||||
ESP_LOGW(TAG, "failed to print card info");
|
||||
}
|
||||
}
|
||||
|
||||
// initialise the card functions
|
||||
if (hosted_sdio_card_fn_init(context->card) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "sdio_card_fn_init failed");
|
||||
goto fail;
|
||||
}
|
||||
return ESP_OK;
|
||||
|
||||
fail:
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int hosted_sdio_card_deinit(void *ctx)
|
||||
{
|
||||
SDIO_FAIL_IF_NULL(ctx);
|
||||
|
||||
sdmmc_context_t *context = (sdmmc_context_t *)ctx;
|
||||
|
||||
/* Free the DMA aligned buffer allocated by sdmmc_allocate_aligned_buf()
|
||||
* ESP-IDF allocates this in sdmmc_card_init() but doesn't provide cleanup API */
|
||||
if (context->card && context->card->host.dma_aligned_buffer) {
|
||||
free(context->card->host.dma_aligned_buffer);
|
||||
context->card->host.dma_aligned_buffer = NULL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int hosted_sdio_read_reg(void *ctx, uint32_t reg, uint8_t *data, uint16_t size, bool lock_required)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
SDIO_FAIL_IF_NULL(ctx);
|
||||
|
||||
sdmmc_context_t *context = (sdmmc_context_t *)ctx;
|
||||
sdmmc_card_t *card = context->card;
|
||||
SDIO_FAIL_IF_NULL(card);
|
||||
|
||||
/* Need to apply address mask when reading/writing slave registers */
|
||||
reg &= ESP_ADDRESS_MASK;
|
||||
ESP_LOGV(TAG, "%s: reg[0x%" PRIx32"] size[%u]", __func__, reg, size);
|
||||
|
||||
SDIO_LOCK(lock_required);
|
||||
if (size <= 1) {
|
||||
res = sdmmc_io_read_byte(card, SDIO_FUNC_1, reg, data);
|
||||
} else {
|
||||
res = sdmmc_io_read_bytes(card, SDIO_FUNC_1, reg, data, size);
|
||||
}
|
||||
SDIO_UNLOCK(lock_required);
|
||||
return res;
|
||||
}
|
||||
|
||||
int hosted_sdio_write_reg(void *ctx, uint32_t reg, uint8_t *data, uint16_t size, bool lock_required)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
SDIO_FAIL_IF_NULL(ctx);
|
||||
|
||||
sdmmc_context_t *context = (sdmmc_context_t *)ctx;
|
||||
sdmmc_card_t *card = context->card;
|
||||
|
||||
/* Need to apply address mask when reading/writing slave registers */
|
||||
reg &= ESP_ADDRESS_MASK;
|
||||
ESP_LOGV(TAG, "%s: reg[0x%" PRIx32"] size[%u]", __func__, reg, size);
|
||||
|
||||
SDIO_LOCK(lock_required);
|
||||
if (size <= 1) {
|
||||
res = sdmmc_io_write_byte(card, SDIO_FUNC_1, reg, *data, NULL);
|
||||
} else {
|
||||
res = sdmmc_io_write_bytes(card, SDIO_FUNC_1, reg, data, size);
|
||||
}
|
||||
SDIO_UNLOCK(lock_required);
|
||||
return res;
|
||||
}
|
||||
|
||||
int hosted_sdio_read_block(void *ctx, uint32_t reg, uint8_t *data, uint16_t size, bool lock_required)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
SDIO_FAIL_IF_NULL(ctx);
|
||||
|
||||
sdmmc_context_t *context = (sdmmc_context_t *)ctx;
|
||||
sdmmc_card_t *card = context->card;
|
||||
SDIO_FAIL_IF_NULL(card);
|
||||
ESP_LOGV(TAG, "%s: reg[0x%" PRIx32"] size[%u]", __func__, reg, size);
|
||||
|
||||
SDIO_LOCK(lock_required);
|
||||
if (size <= 1) {
|
||||
res = sdmmc_io_read_byte(card, SDIO_FUNC_1, reg, data);
|
||||
} else {
|
||||
res = sdio_read_fromio(card, SDIO_FUNC_1, reg, data, H_SDIO_RX_LEN_TO_TRANSFER(size));
|
||||
}
|
||||
SDIO_UNLOCK(lock_required);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* DeskLock fork fix (esp-hosted-mcu #167): on the ESP32-P4, block-mode CMD53
|
||||
* writes require the source buffer to be cache-line (64 B) aligned. The IDF
|
||||
* sdmmc driver rejects a misaligned source with ESP_ERR_INVALID_ARG (0x102=258)
|
||||
* BEFORE any bus activity -> esp_hosted's write loop declares "Unrecoverable
|
||||
* host sdio state" and reboots the whole P4. The audio TX path can hand us a
|
||||
* non-64-aligned payload, so streaming mic audio wedges on the very first frame.
|
||||
* Bounce a misaligned buffer through one aligned DMA scratch buffer. TX is
|
||||
* serialized by the driver bus lock, so a single static bounce buffer is safe. */
|
||||
int hosted_sdio_write_block(void *ctx, uint32_t reg, uint8_t *data, uint16_t size, bool lock_required)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
SDIO_FAIL_IF_NULL(ctx);
|
||||
|
||||
sdmmc_context_t *context = (sdmmc_context_t *)ctx;
|
||||
sdmmc_card_t *card = context->card;
|
||||
SDIO_FAIL_IF_NULL(card);
|
||||
ESP_LOGV(TAG, "%s: reg[0x%" PRIx32"] size[%u]", __func__, reg, size);
|
||||
|
||||
uint8_t *src = data;
|
||||
uint32_t xfer = H_SDIO_TX_LEN_TO_TRANSFER(size);
|
||||
if (size > 1 && card->host.check_buffer_alignment &&
|
||||
!card->host.check_buffer_alignment(card->host.slot, data, xfer)) {
|
||||
if (s_tx_bounce_sz < xfer) {
|
||||
if (s_tx_bounce_buf) {
|
||||
heap_caps_free(s_tx_bounce_buf);
|
||||
}
|
||||
s_tx_bounce_buf = heap_caps_aligned_alloc(64, xfer, MALLOC_CAP_DMA | MALLOC_CAP_8BIT);
|
||||
s_tx_bounce_sz = s_tx_bounce_buf ? xfer : 0;
|
||||
}
|
||||
if (!s_tx_bounce_buf) {
|
||||
ESP_LOGE(TAG, "%s: tx bounce alloc %" PRIu32 " failed", __func__, xfer);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
memcpy(s_tx_bounce_buf, data, size);
|
||||
src = s_tx_bounce_buf;
|
||||
}
|
||||
|
||||
SDIO_LOCK(lock_required);
|
||||
if (size <= 1) {
|
||||
res = sdmmc_io_write_byte(card, SDIO_FUNC_1, reg, *data, NULL);
|
||||
} else {
|
||||
res = sdio_write_toio(card, SDIO_FUNC_1, reg, src, xfer);
|
||||
}
|
||||
SDIO_UNLOCK(lock_required);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Blocking fn call. Returns when SDIO slave device generates a SDIO interrupt */
|
||||
int hosted_sdio_wait_slave_intr(void *ctx, uint32_t ticks_to_wait)
|
||||
{
|
||||
SDIO_FAIL_IF_NULL(ctx);
|
||||
|
||||
sdmmc_context_t *context = (sdmmc_context_t *)ctx;
|
||||
sdmmc_card_t *card = context->card;
|
||||
|
||||
SDIO_FAIL_IF_NULL(card);
|
||||
|
||||
return sdmmc_io_wait_int(card, ticks_to_wait);
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_check.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "driver/spi_master.h"
|
||||
|
||||
#include "transport_drv.h"
|
||||
#include "port_esp_hosted_host_spi.h"
|
||||
#include "port_esp_hosted_host_os.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "port_esp_hosted_host_log.h"
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32P4
|
||||
/* Enable workaround if got SPI Read Errors on ESP32-P4 due to caching */
|
||||
#define SPI_WORKAROUND (0)
|
||||
#else
|
||||
#define SPI_WORKAROUND (0)
|
||||
#endif
|
||||
|
||||
#if SPI_WORKAROUND
|
||||
#include "esp_cache.h"
|
||||
#endif
|
||||
|
||||
DEFINE_LOG_TAG(spi_wrapper);
|
||||
|
||||
extern void * spi_handle;
|
||||
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
#define SENDER_HOST HSPI_HOST
|
||||
#else
|
||||
#define SENDER_HOST SPI2_HOST
|
||||
#endif
|
||||
|
||||
void * hosted_spi_init(void)
|
||||
{
|
||||
esp_err_t ret;
|
||||
ESP_LOGI(TAG, "Transport: SPI, Mode:%u Freq:%uMHz TxQ:%u RxQ:%u\n GPIOs: CLK:%u MOSI:%u MISO:%u CS:%u HS:%u DR:%u SlaveReset:%u",
|
||||
H_SPI_MODE, H_SPI_FD_CLK_MHZ, H_SPI_TX_Q, H_SPI_RX_Q,
|
||||
H_GPIO_SCLK_Pin, H_GPIO_MOSI_Pin, H_GPIO_MISO_Pin,
|
||||
H_GPIO_CS_Pin, H_GPIO_HANDSHAKE_Pin, H_GPIO_DATA_READY_Pin,
|
||||
H_GPIO_PIN_RESET);
|
||||
|
||||
HOSTED_CREATE_HANDLE(spi_device_handle_t, spi_handle);
|
||||
assert(spi_handle);
|
||||
|
||||
|
||||
//Configuration for the SPI bus
|
||||
spi_bus_config_t buscfg={
|
||||
.mosi_io_num=H_GPIO_MOSI_Pin,
|
||||
.miso_io_num=H_GPIO_MISO_Pin,
|
||||
.sclk_io_num=H_GPIO_SCLK_Pin,
|
||||
.quadwp_io_num=-1,
|
||||
.quadhd_io_num=-1
|
||||
};
|
||||
|
||||
//Configuration for the SPI device on the other side of the bus
|
||||
spi_device_interface_config_t devcfg={
|
||||
.command_bits=0,
|
||||
.address_bits=0,
|
||||
.dummy_bits=0,
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32P4
|
||||
.clock_source = SPI_CLK_SRC_SPLL,
|
||||
#endif
|
||||
.clock_speed_hz=MHZ_TO_HZ(H_SPI_FD_CLK_MHZ),
|
||||
.duty_cycle_pos=128, //50% duty cycle
|
||||
.mode=H_SPI_MODE,
|
||||
.spics_io_num=H_GPIO_CS_Pin,
|
||||
.cs_ena_posttrans=3, //Keep the CS low 3 cycles after transaction, to stop slave from missing the last bit when CS has less propagation delay than CLK
|
||||
.queue_size=3
|
||||
};
|
||||
|
||||
//Initialize the SPI bus and add the device we want to send stuff to.
|
||||
ret=spi_bus_initialize(SENDER_HOST, &buscfg, SPI_DMA_CH_AUTO);
|
||||
assert(ret==ESP_OK);
|
||||
ret=spi_bus_add_device(SENDER_HOST, &devcfg, spi_handle);
|
||||
assert(ret==ESP_OK);
|
||||
|
||||
//Assume the slave is ready for the first transmission: if the slave started up before us, we will not detect
|
||||
//positive edge on the handshake line.
|
||||
gpio_set_drive_capability(H_GPIO_CS_Pin, GPIO_DRIVE_CAP_3);
|
||||
gpio_set_drive_capability(H_GPIO_SCLK_Pin, GPIO_DRIVE_CAP_3);
|
||||
return spi_handle;
|
||||
}
|
||||
|
||||
int hosted_spi_deinit(void *handle)
|
||||
{
|
||||
if (!handle) {
|
||||
ESP_LOGE(TAG, "Invalid handle for SPI deinit");
|
||||
return -1;
|
||||
}
|
||||
|
||||
spi_device_handle_t *spi_dev_handle = (spi_device_handle_t *)handle;
|
||||
|
||||
/* Remove device from SPI bus */
|
||||
esp_err_t ret = spi_bus_remove_device(*spi_dev_handle);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to remove SPI device: %d", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Free the SPI bus */
|
||||
ret = spi_bus_free(SENDER_HOST);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to free SPI bus: %d", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Free the handle */
|
||||
HOSTED_FREE_HANDLE(handle);
|
||||
spi_handle = NULL;
|
||||
|
||||
ESP_LOGI(TAG, "SPI deinitialized");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int hosted_do_spi_transfer(void *trans)
|
||||
{
|
||||
spi_transaction_t t = {0};
|
||||
struct hosted_transport_context_t * spi_trans = trans;
|
||||
|
||||
#if SPI_WORKAROUND
|
||||
/* this ensures RX DMA data in cache is sync to memory */
|
||||
assert(ESP_OK == esp_cache_msync((void *)spi_trans->rx_buf, spi_trans->tx_buf_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
|
||||
#endif
|
||||
|
||||
t.length=spi_trans->tx_buf_size*8;
|
||||
t.tx_buffer=spi_trans->tx_buf;
|
||||
t.rx_buffer=spi_trans->rx_buf;
|
||||
/* tell lower layer that we have manually aligned buffers for dma */
|
||||
t.flags |= SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL;
|
||||
|
||||
return spi_device_transmit(*((spi_device_handle_t *)spi_handle), &t);
|
||||
}
|
||||
+565
@@ -0,0 +1,565 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "esp_memory_utils.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include "hal/spi_ll.h"
|
||||
|
||||
#include "port_esp_hosted_host_config.h"
|
||||
#include "port_esp_hosted_host_spi_hd.h"
|
||||
#include "port_esp_hosted_host_os.h"
|
||||
#include "transport_drv.h"
|
||||
|
||||
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||
/* Use DMA Aligned Buffers for reg reads, buf read / writes */
|
||||
#define USE_DMA_ALIGNED_BUF (1)
|
||||
#else
|
||||
#define USE_DMA_ALIGNED_BUF (0)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32P4
|
||||
/* Enable workaround if got SPI Read Errors on ESP32-P4 due to caching */
|
||||
#define SPI_WORKAROUND (0)
|
||||
#else
|
||||
#define SPI_WORKAROUND (0)
|
||||
#endif
|
||||
|
||||
#if SPI_WORKAROUND
|
||||
#include "esp_cache.h"
|
||||
#endif
|
||||
|
||||
/* SPI_WORKAROUND requires DMA Aligned Buffers to be used */
|
||||
#if SPI_WORKAROUND && !USE_DMA_ALIGNED_BUF
|
||||
#error SPI_WORKAROUND and USE_DMA_ALIGNED_BUF must be enabled together
|
||||
#endif
|
||||
|
||||
#include "esp_log.h"
|
||||
static const char TAG[] = "spi_hd_wrapper";
|
||||
|
||||
#define MASTER_HOST SPI2_HOST // only SPI2 can be used in Half-duplex mode
|
||||
#define DMA_CHAN SPI_DMA_CH_AUTO
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#define SPI_QUAD 1
|
||||
#define SPI_DUAL 0
|
||||
#define SPI_MONO 0
|
||||
|
||||
// num data lines used in each phase: cmd = 1, addr = 4, dummy = 1, data = 4
|
||||
#define SPI_QUAD_FLAGS (SPI_TRANS_MODE_QIO | SPI_TRANS_MULTILINE_ADDR)
|
||||
|
||||
// num data lines used in each phase: cmd = 1, addr = 2, dummy = 1, data = 2
|
||||
#define SPI_DUAL_FLAGS (SPI_TRANS_MODE_DIO | SPI_TRANS_MULTILINE_ADDR)
|
||||
|
||||
// num data lines used in each phase: cmd = 1, addr = 1, dummy = 1, data = 1
|
||||
#define SPI_SINGLE_FLAGS (0)
|
||||
|
||||
#define SPI_HD_FAIL_IF_NULL(x) do { \
|
||||
if (!x) return ESP_FAIL; \
|
||||
} while (0);
|
||||
|
||||
#define SPI_HD_LOCK(x) do { \
|
||||
if (x) g_h.funcs->_h_lock_mutex(spi_hd_bus_lock, HOSTED_BLOCK_MAX); \
|
||||
} while (0);
|
||||
|
||||
#define SPI_HD_UNLOCK(x) do { \
|
||||
if (x) g_h.funcs->_h_unlock_mutex(spi_hd_bus_lock); \
|
||||
} while (0);
|
||||
|
||||
// spi_hd context structure
|
||||
typedef struct spi_hd_ctx_t {
|
||||
spi_device_handle_t handle;
|
||||
} spi_hd_ctx_t;
|
||||
|
||||
static spi_hd_ctx_t * ctx = NULL;
|
||||
static void * spi_hd_bus_lock;
|
||||
|
||||
#if USE_DMA_ALIGNED_BUF
|
||||
/* we use 64-bit DMA aligned buffer for reading register data */
|
||||
|
||||
#define DMA_ALIGNED_BUF_LEN 64 // ESP32-P4 requires 64 byte aligned buffers
|
||||
DRAM_DMA_ALIGNED_ATTR static uint8_t dma_data_buf[DMA_ALIGNED_BUF_LEN];
|
||||
#endif
|
||||
|
||||
// initially we start off using 2 or 1 data lines
|
||||
// reconfigure later depending on number of data lines co-processor supports
|
||||
#if (H_SPI_HD_HOST_NUM_DATA_LINES == 4)
|
||||
static uint32_t spi_hd_rx_tx_flags = SPI_DUAL_FLAGS;
|
||||
#elif (H_SPI_HD_HOST_NUM_DATA_LINES == 2)
|
||||
static uint32_t spi_hd_rx_tx_flags = SPI_DUAL_FLAGS;
|
||||
#else
|
||||
static uint32_t spi_hd_rx_tx_flags = SPI_SINGLE_FLAGS;
|
||||
#endif
|
||||
|
||||
// returns the spi command to send based on the provided mode flags
|
||||
static uint16_t spi_hd_get_hd_command(spi_command_t cmd_t, uint32_t flags)
|
||||
{
|
||||
spi_line_mode_t line_mode = {
|
||||
.cmd_lines = 1,
|
||||
};
|
||||
|
||||
if (flags & SPI_TRANS_MODE_DIO) {
|
||||
line_mode.data_lines = 2;
|
||||
if (flags & SPI_TRANS_MODE_DIOQIO_ADDR) {
|
||||
line_mode.addr_lines = 2;
|
||||
} else {
|
||||
line_mode.addr_lines = 1;
|
||||
}
|
||||
} else if (flags & SPI_TRANS_MODE_QIO) {
|
||||
line_mode.data_lines = 4;
|
||||
if (flags & SPI_TRANS_MODE_DIOQIO_ADDR) {
|
||||
line_mode.addr_lines = 4;
|
||||
} else {
|
||||
line_mode.addr_lines = 1;
|
||||
}
|
||||
} else {
|
||||
line_mode.data_lines = 1;
|
||||
line_mode.addr_lines = 1;
|
||||
}
|
||||
|
||||
return spi_ll_get_slave_hd_command(cmd_t, line_mode);
|
||||
}
|
||||
|
||||
// get number of dummy bits for the SPI transaction
|
||||
static int spi_hd_get_hd_dummy_bits(uint32_t flags)
|
||||
{
|
||||
spi_line_mode_t line_mode = {};
|
||||
|
||||
if (flags & SPI_TRANS_MODE_DIO) {
|
||||
line_mode.data_lines = 2;
|
||||
} else if (flags & SPI_TRANS_MODE_QIO) {
|
||||
line_mode.data_lines = 4;
|
||||
} else {
|
||||
line_mode.data_lines = 1;
|
||||
}
|
||||
|
||||
return spi_ll_get_slave_hd_dummy_bits(line_mode);
|
||||
}
|
||||
|
||||
static esp_err_t spi_hd_read_reg(uint32_t addr, uint8_t *out_data, int len, uint32_t flags)
|
||||
{
|
||||
spi_transaction_ext_t t = {
|
||||
.base = {
|
||||
.cmd = spi_hd_get_hd_command(SPI_CMD_HD_RDBUF, flags),
|
||||
.addr = addr % 72,
|
||||
.rxlength = len * 8,
|
||||
.rx_buffer = out_data,
|
||||
.flags = flags | SPI_TRANS_VARIABLE_DUMMY,
|
||||
},
|
||||
.dummy_bits = spi_hd_get_hd_dummy_bits(flags),
|
||||
};
|
||||
|
||||
#if USE_DMA_ALIGNED_BUF
|
||||
/* tell lower layer that we have manually aligned buffer for dma */
|
||||
t.base.flags |= SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL;
|
||||
#endif
|
||||
|
||||
return spi_device_transmit(ctx->handle, (spi_transaction_t *)&t);
|
||||
}
|
||||
|
||||
static esp_err_t spi_hd_wrcmd9(uint32_t flags)
|
||||
{
|
||||
spi_transaction_t t = {
|
||||
.cmd = spi_hd_get_hd_command(SPI_CMD_HD_INT1, flags),
|
||||
.flags = flags,
|
||||
};
|
||||
|
||||
return spi_device_transmit(ctx->handle, &t);
|
||||
}
|
||||
|
||||
static esp_err_t spi_hd_write_reg(const uint8_t *data, int addr, int len, uint32_t flags)
|
||||
{
|
||||
spi_transaction_ext_t t = {
|
||||
.base = {
|
||||
.cmd = spi_hd_get_hd_command(SPI_CMD_HD_WRBUF, flags),
|
||||
.addr = addr % 72,
|
||||
.length = len * 8,
|
||||
.tx_buffer = data,
|
||||
.flags = flags | SPI_TRANS_VARIABLE_DUMMY,
|
||||
},
|
||||
.dummy_bits = spi_hd_get_hd_dummy_bits(flags),
|
||||
};
|
||||
|
||||
return spi_device_transmit(ctx->handle, (spi_transaction_t *)&t);
|
||||
}
|
||||
|
||||
static esp_err_t spi_hd_rddma_seg(uint8_t *out_data, int seg_len, uint32_t flags)
|
||||
{
|
||||
#if USE_DMA_ALIGNED_BUF
|
||||
/* Note: this only works if data is read in one segment, which is
|
||||
* what is currently done
|
||||
* incoming mempool allocated buffer's actual size is MAX_SPI_HD_BUFFER_SIZE,
|
||||
* so this padded length should be okay */
|
||||
uint32_t padded_len = ((seg_len + DMA_ALIGNED_BUF_LEN - 1) / DMA_ALIGNED_BUF_LEN) * DMA_ALIGNED_BUF_LEN;
|
||||
#endif
|
||||
|
||||
#if SPI_WORKAROUND
|
||||
/* this ensures RX DMA data in cache is sync to memory */
|
||||
assert(ESP_OK == esp_cache_msync((void *)out_data, padded_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
|
||||
#endif
|
||||
|
||||
spi_transaction_ext_t t = {
|
||||
.base = {
|
||||
.cmd = spi_hd_get_hd_command(SPI_CMD_HD_RDDMA, flags),
|
||||
#if USE_DMA_ALIGNED_BUF
|
||||
.rxlength = padded_len * 8,
|
||||
/* tell lower layer that we have manually aligned buffer for dma */
|
||||
.flags = flags | (SPI_TRANS_VARIABLE_DUMMY | SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL),
|
||||
#else
|
||||
.rxlength = seg_len * 8,
|
||||
.flags = flags | SPI_TRANS_VARIABLE_DUMMY,
|
||||
#endif
|
||||
.rx_buffer = out_data,
|
||||
},
|
||||
.dummy_bits = spi_hd_get_hd_dummy_bits(flags),
|
||||
};
|
||||
|
||||
return spi_device_transmit(ctx->handle, (spi_transaction_t *)&t);
|
||||
}
|
||||
|
||||
static esp_err_t spi_hd_rddma_done(uint32_t flags)
|
||||
{
|
||||
spi_transaction_t end_t = {
|
||||
.cmd = spi_hd_get_hd_command(SPI_CMD_HD_INT0, flags),
|
||||
.flags = flags,
|
||||
};
|
||||
return spi_device_transmit(ctx->handle, &end_t);
|
||||
}
|
||||
|
||||
static esp_err_t spi_hd_rddma(uint8_t *out_data, int len, int seg_len, uint32_t flags)
|
||||
{
|
||||
if (!esp_ptr_dma_capable(out_data) || ((intptr_t)out_data % 4) != 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
seg_len = (seg_len > 0) ? seg_len : len;
|
||||
|
||||
uint8_t *read_ptr = out_data;
|
||||
esp_err_t ret = ESP_OK;
|
||||
while (len > 0) {
|
||||
int send_len = MIN(seg_len, len);
|
||||
|
||||
ret = spi_hd_rddma_seg(read_ptr, send_len, flags);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
len -= send_len;
|
||||
read_ptr += send_len;
|
||||
}
|
||||
return spi_hd_rddma_done(flags);
|
||||
}
|
||||
|
||||
static esp_err_t spi_hd_wrdma_seg(const uint8_t *data, int seg_len, uint32_t flags)
|
||||
{
|
||||
#if USE_DMA_ALIGNED_BUF
|
||||
/* Note: this only works if data is written in one segment, which is
|
||||
* what is currently done
|
||||
* incoming mempool allocated buffer's actual size is MAX_SPI_HD_BUFFER_SIZE,
|
||||
* so this padded length should be okay */
|
||||
uint32_t padded_len = ((seg_len + DMA_ALIGNED_BUF_LEN - 1) / DMA_ALIGNED_BUF_LEN) * DMA_ALIGNED_BUF_LEN;
|
||||
#endif
|
||||
|
||||
spi_transaction_ext_t t = {
|
||||
.base = {
|
||||
.cmd = spi_hd_get_hd_command(SPI_CMD_HD_WRDMA, flags),
|
||||
#if USE_DMA_ALIGNED_BUF
|
||||
.length = padded_len * 8,
|
||||
/* tell lower layer that we have manually aligned buffer for dma */
|
||||
.flags = flags | (SPI_TRANS_VARIABLE_DUMMY | SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL),
|
||||
#else
|
||||
.length = seg_len * 8,
|
||||
.flags = flags | SPI_TRANS_VARIABLE_DUMMY,
|
||||
#endif
|
||||
.tx_buffer = data,
|
||||
},
|
||||
.dummy_bits = spi_hd_get_hd_dummy_bits(flags),
|
||||
};
|
||||
return spi_device_transmit(ctx->handle, (spi_transaction_t *)&t);
|
||||
}
|
||||
|
||||
static esp_err_t spi_hd_wrdma_done(uint32_t flags)
|
||||
{
|
||||
spi_transaction_t end_t = {
|
||||
.cmd = spi_hd_get_hd_command(SPI_CMD_HD_WR_END, flags),
|
||||
.flags = flags,
|
||||
};
|
||||
return spi_device_transmit(ctx->handle, &end_t);
|
||||
}
|
||||
|
||||
static esp_err_t spi_hd_wrdma(const uint8_t *data, int len, int seg_len, uint32_t flags)
|
||||
{
|
||||
if (!esp_ptr_dma_capable(data)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
seg_len = (seg_len > 0) ? seg_len : len;
|
||||
|
||||
while (len > 0) {
|
||||
int send_len = MIN(seg_len, len);
|
||||
|
||||
esp_err_t ret = spi_hd_wrdma_seg(data, send_len, flags);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
len -= send_len;
|
||||
data += send_len;
|
||||
}
|
||||
|
||||
return spi_hd_wrdma_done(flags);
|
||||
}
|
||||
|
||||
void * hosted_spi_hd_init(void)
|
||||
{
|
||||
// initialise bus and device in ctx
|
||||
spi_bus_config_t buscfg = {
|
||||
.data0_io_num = H_SPI_HD_PIN_D0,
|
||||
.data1_io_num = H_SPI_HD_PIN_D1,
|
||||
.data2_io_num = H_SPI_HD_PIN_D2,
|
||||
.data3_io_num = H_SPI_HD_PIN_D3,
|
||||
/** set other data pins to -1 to prevent warnings about gpio
|
||||
* conflict in ESP-IDF spi_common.c
|
||||
*/
|
||||
.data4_io_num = -1,
|
||||
.data5_io_num = -1,
|
||||
.data6_io_num = -1,
|
||||
.data7_io_num = -1,
|
||||
|
||||
.sclk_io_num = H_SPI_HD_PIN_CLK,
|
||||
.max_transfer_sz = MAX_SPI_HD_BUFFER_SIZE,
|
||||
#if (H_SPI_HD_HOST_NUM_DATA_LINES == 4)
|
||||
.flags = (SPICOMMON_BUSFLAG_MASTER | SPICOMMON_BUSFLAG_QUAD),
|
||||
#elif (H_SPI_HD_HOST_NUM_DATA_LINES == 2)
|
||||
.flags = (SPICOMMON_BUSFLAG_MASTER | SPICOMMON_BUSFLAG_DUAL),
|
||||
#else
|
||||
.flags = SPICOMMON_BUSFLAG_MASTER,
|
||||
#endif
|
||||
.intr_flags = 0,
|
||||
};
|
||||
|
||||
spi_device_interface_config_t devcfg = {
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32P4
|
||||
.clock_source = SPI_CLK_SRC_SPLL,
|
||||
#endif
|
||||
.clock_speed_hz = H_SPI_HD_CLK_MHZ * 1000 * 1000,
|
||||
.mode = H_SPI_HD_MODE,
|
||||
.spics_io_num = H_SPI_HD_PIN_CS,
|
||||
.cs_ena_pretrans = 0,
|
||||
.cs_ena_posttrans = 0,
|
||||
.command_bits = H_SPI_HD_NUM_COMMAND_BITS,
|
||||
.address_bits = H_SPI_HD_NUM_ADDRESS_BITS,
|
||||
.dummy_bits = H_SPI_HD_NUM_DUMMY_BITS,
|
||||
.queue_size = 16,
|
||||
#if H_SPI_HD_HOST_NUM_DATA_LINES > 1
|
||||
.flags = SPI_DEVICE_HALFDUPLEX,
|
||||
#else
|
||||
.flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_3WIRE, // enable 1-bit mode support
|
||||
#endif
|
||||
.duty_cycle_pos = 128, // 50% duty cycle
|
||||
.input_delay_ns = 0,
|
||||
.pre_cb = NULL,
|
||||
.post_cb = NULL,
|
||||
};
|
||||
|
||||
ctx = calloc(1, sizeof(spi_hd_ctx_t));
|
||||
assert(ctx);
|
||||
|
||||
// initialize bus
|
||||
if (spi_bus_initialize(MASTER_HOST, &buscfg, DMA_CHAN)) {
|
||||
ESP_LOGE(TAG, "spi_bus_initialize FAILED");
|
||||
goto err_bus_initialize;
|
||||
}
|
||||
|
||||
// initialize device
|
||||
if (spi_bus_add_device(MASTER_HOST, &devcfg, &ctx->handle)) {
|
||||
ESP_LOGE(TAG, "spi_bus_add_device FAILED");
|
||||
goto err_add_device;
|
||||
}
|
||||
|
||||
gpio_set_drive_capability(H_SPI_HD_PIN_CS, GPIO_DRIVE_CAP_3);
|
||||
gpio_set_drive_capability(H_SPI_HD_PIN_CLK, GPIO_DRIVE_CAP_3);
|
||||
|
||||
// initialise mutex for bus locking
|
||||
spi_hd_bus_lock = g_h.funcs->_h_create_mutex();
|
||||
assert(spi_hd_bus_lock);
|
||||
|
||||
return ctx;
|
||||
|
||||
err_add_device:
|
||||
spi_bus_free(MASTER_HOST);
|
||||
// fallthrough
|
||||
|
||||
err_bus_initialize:
|
||||
free(ctx);
|
||||
ctx = NULL;
|
||||
|
||||
ESP_LOGE(TAG, "error %s", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int hosted_spi_hd_deinit(void *ctx)
|
||||
{
|
||||
spi_hd_ctx_t * qsp_ctx;
|
||||
spi_device_handle_t * handle;
|
||||
|
||||
g_h.funcs->_h_destroy_mutex(spi_hd_bus_lock);
|
||||
|
||||
if (!ctx)
|
||||
return ESP_FAIL;
|
||||
|
||||
qsp_ctx = (spi_hd_ctx_t *)ctx;
|
||||
handle = &qsp_ctx->handle;
|
||||
|
||||
spi_bus_remove_device(*handle);
|
||||
spi_bus_free(MASTER_HOST);
|
||||
free(ctx);
|
||||
ctx = NULL;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int hosted_spi_hd_read_reg(uint32_t reg, uint32_t *data, int poll, bool lock_required)
|
||||
{
|
||||
int res = 0;
|
||||
uint32_t read_data;
|
||||
uint32_t temp_data;
|
||||
int i = 0;
|
||||
|
||||
SPI_HD_FAIL_IF_NULL(ctx);
|
||||
|
||||
SPI_HD_LOCK(lock_required);
|
||||
|
||||
#if SPI_WORKAROUND
|
||||
/* this ensures RX DMA data in cache is sync to memory */
|
||||
assert(ESP_OK == esp_cache_msync((void *)dma_data_buf, DMA_ALIGNED_BUF_LEN, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
|
||||
#endif
|
||||
|
||||
#if USE_DMA_ALIGNED_BUF
|
||||
/* use aligned buffer to read data */
|
||||
res = spi_hd_read_reg(reg, (uint8_t *)dma_data_buf, DMA_ALIGNED_BUF_LEN, spi_hd_rx_tx_flags);
|
||||
read_data = *(uint32_t *)dma_data_buf;
|
||||
#else
|
||||
res = spi_hd_read_reg(reg, (uint8_t *)&read_data, sizeof(uint32_t), spi_hd_rx_tx_flags);
|
||||
#endif
|
||||
|
||||
if (res != ESP_OK)
|
||||
goto err;
|
||||
|
||||
// reread until value is stable
|
||||
for (i = 0; i < poll; i++) {
|
||||
#if SPI_WORKAROUND
|
||||
/* this ensures RX DMA data in cache is sync to memory */
|
||||
assert(ESP_OK == esp_cache_msync((void *)dma_data_buf, DMA_ALIGNED_BUF_LEN, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
|
||||
#endif
|
||||
|
||||
#if USE_DMA_ALIGNED_BUF
|
||||
/* use aligned buffer to read data */
|
||||
res = spi_hd_read_reg(reg, (uint8_t *)dma_data_buf, DMA_ALIGNED_BUF_LEN, spi_hd_rx_tx_flags);
|
||||
temp_data = *(uint32_t *)dma_data_buf;
|
||||
#else
|
||||
res = spi_hd_read_reg(reg, (uint8_t *)&temp_data, sizeof(uint32_t), spi_hd_rx_tx_flags);
|
||||
#endif
|
||||
|
||||
if (res != ESP_OK)
|
||||
goto err;
|
||||
|
||||
if (temp_data == read_data) {
|
||||
break;
|
||||
}
|
||||
read_data = temp_data;
|
||||
}
|
||||
|
||||
if (i && (i == poll)) {
|
||||
// we didn't get a stable value at the end
|
||||
res = ESP_FAIL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
*data = read_data;
|
||||
|
||||
err:
|
||||
SPI_HD_UNLOCK(lock_required);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int hosted_spi_hd_write_reg(uint32_t reg, uint32_t *data, bool lock_required)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
SPI_HD_FAIL_IF_NULL(ctx);
|
||||
|
||||
SPI_HD_LOCK(lock_required);
|
||||
|
||||
res = spi_hd_write_reg((uint8_t *)data, reg, sizeof(uint32_t), spi_hd_rx_tx_flags);
|
||||
|
||||
SPI_HD_UNLOCK(lock_required);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int hosted_spi_hd_read_dma(uint8_t *data, uint16_t size, bool lock_required)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
SPI_HD_FAIL_IF_NULL(ctx);
|
||||
|
||||
SPI_HD_LOCK(lock_required);
|
||||
|
||||
res = spi_hd_rddma(data, size, -1, spi_hd_rx_tx_flags);
|
||||
|
||||
SPI_HD_UNLOCK(lock_required);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int hosted_spi_hd_write_dma(uint8_t *data, uint16_t size, bool lock_required)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
SPI_HD_FAIL_IF_NULL(ctx);
|
||||
|
||||
SPI_HD_LOCK(lock_required);
|
||||
|
||||
res = spi_hd_wrdma(data, size, -1, spi_hd_rx_tx_flags);
|
||||
|
||||
SPI_HD_UNLOCK(lock_required);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int hosted_spi_hd_set_data_lines(uint32_t data_lines)
|
||||
{
|
||||
if (data_lines == H_SPI_HD_CONFIG_4_DATA_LINES) {
|
||||
ESP_LOGI(TAG, "use 4 data lines");
|
||||
spi_hd_rx_tx_flags = SPI_QUAD_FLAGS;
|
||||
} else if (data_lines == H_SPI_HD_CONFIG_2_DATA_LINES) {
|
||||
ESP_LOGI(TAG, "use 2 data lines");
|
||||
spi_hd_rx_tx_flags = SPI_DUAL_FLAGS;
|
||||
} else if (data_lines == H_SPI_HD_CONFIG_1_DATA_LINE) {
|
||||
ESP_LOGI(TAG, "use 1 data line");
|
||||
spi_hd_rx_tx_flags = SPI_SINGLE_FLAGS;
|
||||
} else {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int hosted_spi_hd_send_cmd9(void)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
SPI_HD_FAIL_IF_NULL(ctx);
|
||||
|
||||
res = spi_hd_wrcmd9(spi_hd_rx_tx_flags);
|
||||
|
||||
return res;
|
||||
}
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_hosted_transport_config.h"
|
||||
#include "port_esp_hosted_host_config.h"
|
||||
|
||||
#ifdef CONFIG_ESP_HOSTED_SDIO_HOST_INTERFACE
|
||||
struct esp_hosted_sdio_config esp_hosted_get_default_sdio_config(void)
|
||||
{
|
||||
return (struct esp_hosted_sdio_config) {
|
||||
.clock_freq_khz = H_SDIO_CLOCK_FREQ_KHZ,
|
||||
.bus_width = H_SDIO_BUS_WIDTH,
|
||||
.slot = H_SDMMC_HOST_SLOT,
|
||||
.pin_clk = {.port = H_SDIO_PORT_CLK, .pin = H_SDIO_PIN_CLK},
|
||||
.pin_cmd = {.port = H_SDIO_PORT_CMD, .pin = H_SDIO_PIN_CMD},
|
||||
.pin_d0 = {.port = H_SDIO_PORT_D0, .pin = H_SDIO_PIN_D0},
|
||||
.pin_d1 = {.port = H_SDIO_PORT_D1, .pin = H_SDIO_PIN_D1},
|
||||
.pin_d2 = {.port = H_SDIO_PORT_D2, .pin = H_SDIO_PIN_D2},
|
||||
.pin_d3 = {.port = H_SDIO_PORT_D3, .pin = H_SDIO_PIN_D3},
|
||||
.pin_reset = {.port = H_GPIO_PORT_RESET, .pin = H_GPIO_PIN_RESET},
|
||||
.rx_mode = H_SDIO_HOST_RX_MODE,
|
||||
.block_mode = H_SDIO_TX_BLOCK_ONLY_XFER && H_SDIO_RX_BLOCK_ONLY_XFER,
|
||||
.iomux_enable = false,
|
||||
.tx_queue_size = H_SDIO_TX_Q,
|
||||
.rx_queue_size = H_SDIO_RX_Q,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
struct esp_hosted_sdio_config esp_hosted_get_default_sdio_iomux_config(void)
|
||||
{
|
||||
return (struct esp_hosted_sdio_config) {
|
||||
.clock_freq_khz = H_SDIO_CLOCK_FREQ_KHZ,
|
||||
.bus_width = H_SDIO_BUS_WIDTH,
|
||||
.slot = H_SDMMC_HOST_SLOT,
|
||||
.rx_mode = H_SDIO_HOST_RX_MODE,
|
||||
.block_mode = H_SDIO_TX_BLOCK_ONLY_XFER && H_SDIO_RX_BLOCK_ONLY_XFER,
|
||||
.iomux_enable = true,
|
||||
.tx_queue_size = H_SDIO_TX_Q,
|
||||
.rx_queue_size = H_SDIO_RX_Q,
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP_HOSTED_SPI_HD_HOST_INTERFACE
|
||||
struct esp_hosted_spi_hd_config esp_hosted_get_default_spi_hd_config(void)
|
||||
{
|
||||
return (struct esp_hosted_spi_hd_config) {
|
||||
.num_data_lines = H_SPI_HD_HOST_NUM_DATA_LINES,
|
||||
.pin_cs = {.port = H_SPI_HD_PORT_CS, .pin = H_SPI_HD_PIN_CS},
|
||||
.pin_clk = {.port = H_SPI_HD_PORT_CLK, .pin = H_SPI_HD_PIN_CLK},
|
||||
.pin_data_ready = {.port = H_SPI_HD_PORT_DATA_READY, .pin = H_SPI_HD_PIN_DATA_READY},
|
||||
.pin_d0 = {.port = H_SPI_HD_PORT_D0, .pin = H_SPI_HD_PIN_D0},
|
||||
.pin_d1 = {.port = H_SPI_HD_PORT_D1, .pin = H_SPI_HD_PIN_D1},
|
||||
.pin_d2 = {.port = H_SPI_HD_PORT_D2, .pin = H_SPI_HD_PIN_D2},
|
||||
.pin_d3 = {.port = H_SPI_HD_PORT_D3, .pin = H_SPI_HD_PIN_D3},
|
||||
.pin_reset = {.port = H_GPIO_PORT_RESET, .pin = H_GPIO_PIN_RESET},
|
||||
.clk_mhz = H_SPI_HD_CLK_MHZ,
|
||||
.mode = H_SPI_HD_MODE,
|
||||
.tx_queue_size = H_SPI_HD_TX_QUEUE_SIZE,
|
||||
.rx_queue_size = H_SPI_HD_RX_QUEUE_SIZE,
|
||||
.checksum_enable = H_SPI_HD_CHECKSUM,
|
||||
.num_command_bits = H_SPI_HD_NUM_COMMAND_BITS,
|
||||
.num_address_bits = H_SPI_HD_NUM_ADDRESS_BITS,
|
||||
.num_dummy_bits = H_SPI_HD_NUM_DUMMY_BITS,
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP_HOSTED_SPI_HOST_INTERFACE
|
||||
struct esp_hosted_spi_config esp_hosted_get_default_spi_config(void)
|
||||
{
|
||||
return (struct esp_hosted_spi_config) {
|
||||
.pin_mosi = {.port = H_GPIO_MOSI_Port, .pin = H_GPIO_MOSI_Pin},
|
||||
.pin_miso = {.port = H_GPIO_MISO_Port, .pin = H_GPIO_MISO_Pin},
|
||||
.pin_sclk = {.port = H_GPIO_SCLK_Port, .pin = H_GPIO_SCLK_Pin},
|
||||
.pin_cs = {.port = H_GPIO_CS_Port, .pin = H_GPIO_CS_Pin},
|
||||
.pin_handshake = {.port = H_GPIO_HANDSHAKE_Port, .pin = H_GPIO_HANDSHAKE_Pin},
|
||||
.pin_data_ready = {.port = H_GPIO_DATA_READY_Port, .pin = H_GPIO_DATA_READY_Pin},
|
||||
.pin_reset = {.port = H_GPIO_PORT_RESET, .pin = H_GPIO_PIN_RESET},
|
||||
.tx_queue_size = H_SPI_TX_Q,
|
||||
.rx_queue_size = H_SPI_RX_Q,
|
||||
.mode = H_SPI_MODE,
|
||||
.clk_mhz = H_SPI_FD_CLK_MHZ,
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP_HOSTED_UART_HOST_INTERFACE
|
||||
struct esp_hosted_uart_config esp_hosted_get_default_uart_config(void)
|
||||
{
|
||||
return (struct esp_hosted_uart_config) {
|
||||
.port = H_UART_PORT,
|
||||
.pin_tx = {.port = H_UART_PORT_TX, .pin = H_UART_PIN_TX},
|
||||
.pin_rx = {.port = H_UART_PORT_RX, .pin = H_UART_PIN_RX},
|
||||
.pin_reset = {.port = H_GPIO_PORT_RESET, .pin = H_GPIO_PIN_RESET},
|
||||
.num_data_bits = H_UART_NUM_DATA_BITS,
|
||||
.parity = H_UART_PARITY,
|
||||
.stop_bits = H_UART_STOP_BITS,
|
||||
.flow_ctrl = H_UART_FLOWCTRL,
|
||||
.clk_src = H_UART_CLK_SRC,
|
||||
.checksum_enable = H_UART_CHECKSUM,
|
||||
.baud_rate = H_UART_BAUD_RATE,
|
||||
.tx_queue_size = H_UART_TX_QUEUE_SIZE,
|
||||
.rx_queue_size = H_UART_RX_QUEUE_SIZE,
|
||||
};
|
||||
}
|
||||
#endif
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#include "driver/uart.h"
|
||||
|
||||
#include "transport_drv.h"
|
||||
#include "port_esp_hosted_host_os.h"
|
||||
#include "port_esp_hosted_host_uart.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
static const char TAG[] = "uart_wrapper";
|
||||
|
||||
#if H_UART_START_BITS != 1
|
||||
#error "UART Start Bits must be 1 to communicate with ESP co-processor"
|
||||
#endif
|
||||
|
||||
#if H_UART_FLOWCTRL
|
||||
#error "UART Flow Control must be disabled to communicate with ESP co-processor"
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP_CONSOLE_UART
|
||||
#if CONFIG_ESP_CONSOLE_UART_NUM == H_UART_PORT
|
||||
#error "ESP Console UART and Hosted UART are the same. Select another UART port."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define UART_FAIL_IF_NULL_CTX(x) do { \
|
||||
if (!x) return ESP_FAIL; \
|
||||
} while (0);
|
||||
|
||||
// UART context structure
|
||||
typedef struct uart_ctx_t {
|
||||
int uart_port;
|
||||
} uart_ctx_t;
|
||||
|
||||
static uart_ctx_t * ctx = NULL;
|
||||
|
||||
int hosted_uart_read(void * ctx, uint8_t *data, uint16_t size)
|
||||
{
|
||||
uart_ctx_t * pctx;
|
||||
|
||||
UART_FAIL_IF_NULL_CTX(ctx);
|
||||
|
||||
pctx = (uart_ctx_t *)ctx;
|
||||
|
||||
return uart_read_bytes(pctx->uart_port, data, size, portMAX_DELAY);
|
||||
}
|
||||
|
||||
int hosted_uart_write(void * ctx, uint8_t *data, uint16_t size)
|
||||
{
|
||||
uart_ctx_t * pctx;
|
||||
|
||||
UART_FAIL_IF_NULL_CTX(ctx);
|
||||
|
||||
pctx = (uart_ctx_t *)ctx;
|
||||
|
||||
return uart_write_bytes(pctx->uart_port, (const char*)data, size);
|
||||
}
|
||||
|
||||
int hosted_uart_flush_input(void * ctx)
|
||||
{
|
||||
uart_ctx_t * pctx;
|
||||
|
||||
UART_FAIL_IF_NULL_CTX(ctx);
|
||||
|
||||
pctx = (uart_ctx_t *)ctx;
|
||||
|
||||
return uart_flush_input(pctx->uart_port);
|
||||
}
|
||||
|
||||
void * hosted_uart_init(void)
|
||||
{
|
||||
ctx = (uart_ctx_t*)g_h.funcs->_h_malloc(sizeof(uart_ctx_t));
|
||||
assert(ctx);
|
||||
|
||||
// initialise bus and device in ctx
|
||||
const uart_config_t uart_config = {
|
||||
.baud_rate = H_UART_BAUD_RATE,
|
||||
.data_bits = H_UART_NUM_DATA_BITS,
|
||||
.parity = H_UART_PARITY,
|
||||
.stop_bits = H_UART_STOP_BITS,
|
||||
.flow_ctrl = H_UART_FLOWCTRL,
|
||||
.source_clk = H_UART_CLK_SRC,
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(uart_driver_install(H_UART_PORT, MAX_UART_BUFFER_SIZE, MAX_UART_BUFFER_SIZE,
|
||||
0, NULL, 0));
|
||||
ESP_ERROR_CHECK(uart_param_config(H_UART_PORT, &uart_config));
|
||||
ESP_ERROR_CHECK(uart_set_pin(H_UART_PORT, H_UART_PIN_TX, H_UART_PIN_RX,
|
||||
UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
|
||||
|
||||
ESP_LOGI(TAG, "UART GPIOs: Tx: %"PRIu16 ", Rx: %"PRIu16 ", Baud Rate %i",
|
||||
H_UART_PIN_TX, H_UART_PIN_RX, H_UART_BAUD_RATE);
|
||||
|
||||
ctx->uart_port = H_UART_PORT;
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
esp_err_t hosted_uart_deinit(void *ctx)
|
||||
{
|
||||
esp_err_t ret;
|
||||
uart_ctx_t * pctx;
|
||||
|
||||
UART_FAIL_IF_NULL_CTX(ctx);
|
||||
|
||||
pctx = (uart_ctx_t *)ctx;
|
||||
|
||||
ret = uart_flush_input(pctx->uart_port);
|
||||
if (ret != ESP_OK)
|
||||
ESP_LOGE(TAG, "%s: Failed to flush uart Rx", __func__);
|
||||
ret = uart_wait_tx_done(pctx->uart_port, 100); // wait 100 RTOS ticks for Tx to be empty
|
||||
if (ret != ESP_OK)
|
||||
ESP_LOGE(TAG, "%s: Failed to flush uart Tx", __func__);
|
||||
uart_driver_delete(pctx->uart_port);
|
||||
|
||||
g_h.funcs->_h_free(ctx);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/** Includes **/
|
||||
|
||||
#include "stats.h"
|
||||
#if TEST_RAW_TP
|
||||
#include "transport_drv.h"
|
||||
#endif
|
||||
#include "esp_log.h"
|
||||
#include "esp_hosted_transport_init.h"
|
||||
#include "esp_hosted_os_abstraction.h"
|
||||
#include "port_esp_hosted_host_os.h"
|
||||
|
||||
// use mempool and zero copy for Tx
|
||||
#include "mempool.h"
|
||||
|
||||
#if ESP_PKT_STATS
|
||||
struct pkt_stats_t pkt_stats;
|
||||
void *pkt_stats_thread = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef ESP_PKT_NUM_DEBUG
|
||||
struct dbg_stats_t dbg_stats;
|
||||
#endif
|
||||
|
||||
#if ESP_PKT_STATS || TEST_RAW_TP
|
||||
static const char *TAG = "stats";
|
||||
#endif
|
||||
|
||||
/** Constants/Macros **/
|
||||
#define RAW_TP_TX_TASK_STACK_SIZE 2048
|
||||
|
||||
/** Exported variables **/
|
||||
|
||||
/** Function declaration **/
|
||||
|
||||
/** Exported Functions **/
|
||||
|
||||
// disable usage of mempool for now
|
||||
#define DISABLE_MEMPOOL 1
|
||||
|
||||
#if TEST_RAW_TP
|
||||
static int test_raw_tp = 0;
|
||||
static uint8_t log_raw_tp_stats_timer_running = 0;
|
||||
static uint32_t raw_tp_timer_count = 0;
|
||||
void *hosted_timer_handler = NULL;
|
||||
static void * raw_tp_tx_task_id = 0;
|
||||
static uint64_t test_raw_tx_len = 0;
|
||||
static uint64_t test_raw_rx_len = 0;
|
||||
|
||||
#if !DISABLE_MEMPOOL
|
||||
static struct mempool * buf_mp_g = NULL;
|
||||
#endif
|
||||
|
||||
void stats_mempool_free(void* ptr)
|
||||
{
|
||||
#if DISABLE_MEMPOOL
|
||||
g_h.funcs->_h_free(ptr);
|
||||
#else
|
||||
mempool_free(buf_mp_g, ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_raw_tp_cleanup(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (log_raw_tp_stats_timer_running) {
|
||||
ret = g_h.funcs->_h_timer_stop(hosted_timer_handler);
|
||||
if (!ret) {
|
||||
log_raw_tp_stats_timer_running = 0;
|
||||
}
|
||||
raw_tp_timer_count = 0;
|
||||
}
|
||||
|
||||
if (raw_tp_tx_task_id) {
|
||||
ret = g_h.funcs->_h_thread_cancel(raw_tp_tx_task_id);
|
||||
raw_tp_tx_task_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void raw_tp_timer_func(void * arg)
|
||||
{
|
||||
#if USE_FLOATING_POINT
|
||||
double actual_bandwidth_tx = 0;
|
||||
double actual_bandwidth_rx = 0;
|
||||
#else
|
||||
uint64_t actual_bandwidth_tx = 0;
|
||||
uint64_t actual_bandwidth_rx = 0;
|
||||
#endif
|
||||
int32_t div = 1024;
|
||||
|
||||
actual_bandwidth_tx = (test_raw_tx_len*8)/TEST_RAW_TP__TIMEOUT;
|
||||
actual_bandwidth_rx = (test_raw_rx_len*8)/TEST_RAW_TP__TIMEOUT;
|
||||
#if USE_FLOATING_POINT
|
||||
ESP_LOGI(TAG, "%lu-%lu sec Tx:%.2f Rx:%.2f kbps\n\r", raw_tp_timer_count, raw_tp_timer_count + TEST_RAW_TP__TIMEOUT, actual_bandwidth_tx/div, actual_bandwidth_rx/div);
|
||||
#else
|
||||
ESP_LOGI(TAG, "%lu-%lu sec Tx:%lu Rx:%lu Kbps", raw_tp_timer_count, raw_tp_timer_count + TEST_RAW_TP__TIMEOUT, (unsigned long)actual_bandwidth_tx/div, (unsigned long)actual_bandwidth_rx/div);
|
||||
#endif
|
||||
raw_tp_timer_count+=TEST_RAW_TP__TIMEOUT;
|
||||
test_raw_tx_len = test_raw_rx_len = 0;
|
||||
}
|
||||
|
||||
static void raw_tp_tx_task(void const* pvParameters)
|
||||
{
|
||||
int ret;
|
||||
static uint16_t seq_num = 0;
|
||||
uint8_t *raw_tp_tx_buf = NULL;
|
||||
uint32_t *ptr = NULL;
|
||||
uint32_t i = 0;
|
||||
g_h.funcs->_h_sleep(5);
|
||||
|
||||
#if !DISABLE_MEMPOOL
|
||||
buf_mp_g = mempool_create(MAX_TRANSPORT_BUFFER_SIZE);
|
||||
#ifdef H_USE_MEMPOOL
|
||||
assert(buf_mp_g);
|
||||
#endif
|
||||
#endif // !DISABLE_MEMPOOL
|
||||
|
||||
while (1) {
|
||||
|
||||
#if CONFIG_H_LOWER_MEMCOPY
|
||||
raw_tp_tx_buf = (uint8_t*)g_h.funcs->_h_calloc(1, MAX_TRANSPORT_BUFFER_SIZE);
|
||||
|
||||
ptr = (uint32_t*) raw_tp_tx_buf;
|
||||
for (i=0; i<(TEST_RAW_TP__BUF_SIZE/4-1); i++, ptr++)
|
||||
*ptr = 0xBAADF00D;
|
||||
|
||||
ret = esp_hosted_tx(ESP_TEST_IF, 0, raw_tp_tx_buf, TEST_RAW_TP__BUF_SIZE, H_BUFF_ZEROCOPY, raw_tp_tx_buf, H_DEFLT_FREE_FUNC, 0);
|
||||
|
||||
#else
|
||||
#if DISABLE_MEMPOOL
|
||||
raw_tp_tx_buf = g_h.funcs->_h_malloc_align(MAX_TRANSPORT_BUFFER_SIZE, HOSTED_MEM_ALIGNMENT_64);
|
||||
g_h.funcs->_h_memset(raw_tp_tx_buf, 0, MAX_TRANSPORT_BUFFER_SIZE);
|
||||
#else
|
||||
raw_tp_tx_buf = mempool_alloc(buf_mp_g, MAX_TRANSPORT_BUFFER_SIZE, true);
|
||||
#endif
|
||||
ptr = (uint32_t*) (raw_tp_tx_buf + H_ESP_PAYLOAD_HEADER_OFFSET);
|
||||
for (i=0; i<(TEST_RAW_TP__BUF_SIZE/4-1); i++, ptr++)
|
||||
*ptr = 0xBAADF00D;
|
||||
|
||||
ret = esp_hosted_tx(ESP_TEST_IF, 0, raw_tp_tx_buf, TEST_RAW_TP__BUF_SIZE, H_BUFF_ZEROCOPY, raw_tp_tx_buf, stats_mempool_free, 0);
|
||||
#endif
|
||||
if (ret) {
|
||||
ESP_LOGE(TAG, "Failed to send to queue\n");
|
||||
continue;
|
||||
}
|
||||
#if CONFIG_H_LOWER_MEMCOPY
|
||||
g_h.funcs->_h_free(raw_tp_tx_buf);
|
||||
#endif
|
||||
test_raw_tx_len += (TEST_RAW_TP__BUF_SIZE);
|
||||
seq_num++;
|
||||
}
|
||||
}
|
||||
|
||||
static void process_raw_tp_flags(uint8_t cap)
|
||||
{
|
||||
test_raw_tp_cleanup();
|
||||
|
||||
if (test_raw_tp) {
|
||||
hosted_timer_handler = g_h.funcs->_h_timer_start("raw_tp_timer", SEC_TO_MILLISEC(TEST_RAW_TP__TIMEOUT),
|
||||
H_TIMER_TYPE_PERIODIC, raw_tp_timer_func, NULL);
|
||||
if (!hosted_timer_handler) {
|
||||
ESP_LOGE(TAG, "Failed to create timer\n\r");
|
||||
return;
|
||||
}
|
||||
log_raw_tp_stats_timer_running = 1;
|
||||
|
||||
ESP_LOGD(TAG, "capabilities: %d", cap);
|
||||
if ((cap & ESP_TEST_RAW_TP__HOST_TO_ESP) ||
|
||||
(cap & ESP_TEST_RAW_TP__BIDIRECTIONAL)) {
|
||||
raw_tp_tx_task_id = g_h.funcs->_h_thread_create("raw_tp_tx", DFLT_TASK_PRIO,
|
||||
RAW_TP_TX_TASK_STACK_SIZE, raw_tp_tx_task, NULL);
|
||||
assert(raw_tp_tx_task_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void start_test_raw_tp(void)
|
||||
{
|
||||
test_raw_tp = 1;
|
||||
}
|
||||
|
||||
static void stop_test_raw_tp(void)
|
||||
{
|
||||
test_raw_tp = 0;
|
||||
}
|
||||
|
||||
void process_test_capabilities(uint8_t cap)
|
||||
{
|
||||
ESP_LOGI(TAG, "ESP peripheral capabilities: 0x%x", cap);
|
||||
if ((cap & ESP_TEST_RAW_TP) == ESP_TEST_RAW_TP) {
|
||||
start_test_raw_tp();
|
||||
ESP_LOGI(TAG, "***** Host Raw throughput Testing (report per %u sec) *****\n\r",TEST_RAW_TP__TIMEOUT);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Raw Throughput testing not enabled on slave. Stopping test.");
|
||||
stop_test_raw_tp();
|
||||
}
|
||||
process_raw_tp_flags(H_TEST_RAW_TP_DIR);
|
||||
}
|
||||
|
||||
void update_test_raw_tp_rx_len(uint16_t len)
|
||||
{
|
||||
test_raw_rx_len+=(len);
|
||||
}
|
||||
|
||||
#endif
|
||||
#if H_MEM_STATS
|
||||
struct mem_stats h_stats_g;
|
||||
#endif
|
||||
|
||||
#if ESP_PKT_STATS
|
||||
void stats_timer_func(void * arg)
|
||||
{
|
||||
ESP_LOGI(TAG, "STA: s2h{in[%lu] out[%lu]} h2s{in(flowctrl_drop[%lu] in[%lu or %lu]) out(ok[%lu] drop[%lu])} flwctl{on[%lu] off[%lu]}",
|
||||
pkt_stats.sta_rx_in,pkt_stats.sta_rx_out,
|
||||
pkt_stats.sta_tx_flowctrl_drop, pkt_stats.sta_tx_in_pass, pkt_stats.sta_tx_trans_in, pkt_stats.sta_tx_out, pkt_stats.sta_tx_out_drop,
|
||||
pkt_stats.sta_flow_ctrl_on, pkt_stats.sta_flow_ctrl_off);
|
||||
ESP_LOGI(TAG, "internal: free %d l-free %d min-free %d, psram: free %d l-free %d min-free %d",
|
||||
heap_caps_get_free_size(MALLOC_CAP_8BIT) - heap_caps_get_free_size(MALLOC_CAP_SPIRAM),
|
||||
heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL),
|
||||
heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL),
|
||||
heap_caps_get_free_size(MALLOC_CAP_SPIRAM),
|
||||
heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM),
|
||||
heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM));
|
||||
}
|
||||
#endif
|
||||
|
||||
void create_debugging_tasks(void)
|
||||
{
|
||||
#if ESP_PKT_STATS
|
||||
ESP_LOGI(TAG, "Start Pkt_stats reporting thread [timer: %u sec]", ESP_PKT_STATS_REPORT_INTERVAL);
|
||||
pkt_stats_thread = g_h.funcs->_h_timer_start("pkt_stats_timer", SEC_TO_MILLISEC(ESP_PKT_STATS_REPORT_INTERVAL),
|
||||
H_TIMER_TYPE_PERIODIC, stats_timer_func, NULL);
|
||||
assert(pkt_stats_thread);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __STATS__H
|
||||
#define __STATS__H
|
||||
|
||||
#include "port_esp_hosted_host_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Stats CONFIG:
|
||||
*
|
||||
* 1. TEST_RAW_TP
|
||||
* These are debug stats which show the raw throughput
|
||||
* performance of transport like SPI or SDIO
|
||||
* (a) TEST_RAW_TP__ESP_TO_HOST
|
||||
* When this enabled, throughput will be measured from ESP to Host
|
||||
*
|
||||
* (b) TEST_RAW_TP__HOST_TO_ESP
|
||||
* This is opposite of TEST_RAW_TP__ESP_TO_HOST. when (a) TEST_RAW_TP__ESP_TO_HOST
|
||||
* is disabled, it will automatically mean throughput to be measured from host to ESP
|
||||
*/
|
||||
#define TEST_RAW_TP H_TEST_RAW_TP
|
||||
|
||||
/* TEST_RAW_TP is disabled on production.
|
||||
* This is only to test the throughout over transport
|
||||
* like SPI or SDIO. In this testing, dummy task will
|
||||
* push the packets over transport.
|
||||
* Currently this testing is possible on one direction
|
||||
* at a time
|
||||
*/
|
||||
|
||||
#if TEST_RAW_TP
|
||||
|
||||
#define TEST_RAW_TP__TIMEOUT H_RAW_TP_REPORT_INTERVAL
|
||||
|
||||
void update_test_raw_tp_rx_len(uint16_t len);
|
||||
void process_test_capabilities(uint8_t cap);
|
||||
|
||||
/* Please note, this size is to assess transport speed,
|
||||
* so kept maximum possible for that transport
|
||||
*
|
||||
* If you want to compare maximum network throughput and
|
||||
* relevance with max transport speed, Plz lower this value to
|
||||
* UDP: 1460 - H_ESP_PAYLOAD_HEADER_OFFSET = 1460-12=1448
|
||||
* TCP: Find MSS in nodes
|
||||
* H_ESP_PAYLOAD_HEADER_OFFSET is header size, which is not included in calcs
|
||||
*/
|
||||
#define TEST_RAW_TP__BUF_SIZE H_RAW_TP_PKT_LEN
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#if H_MEM_STATS
|
||||
struct mempool_stats
|
||||
{
|
||||
uint32_t num_fresh_alloc;
|
||||
uint32_t num_reuse;
|
||||
uint32_t num_free;
|
||||
};
|
||||
|
||||
struct spi_stats
|
||||
{
|
||||
int rx_alloc;
|
||||
int rx_freed;
|
||||
int tx_alloc;
|
||||
int tx_dummy_alloc;
|
||||
int tx_freed;
|
||||
};
|
||||
|
||||
struct nw_stats
|
||||
{
|
||||
int tx_alloc;
|
||||
int tx_freed;
|
||||
};
|
||||
|
||||
struct others_stats {
|
||||
int tx_others_freed;
|
||||
};
|
||||
|
||||
struct mem_stats {
|
||||
struct mempool_stats mp_stats;
|
||||
struct spi_stats spi_mem_stats;
|
||||
struct nw_stats nw_mem_stats;
|
||||
struct others_stats others;
|
||||
};
|
||||
|
||||
extern struct mem_stats h_stats_g;
|
||||
#endif /*H_MEM_STATS*/
|
||||
|
||||
#ifdef ESP_PKT_NUM_DEBUG
|
||||
struct dbg_stats_t {
|
||||
uint16_t tx_pkt_num;
|
||||
uint16_t exp_rx_pkt_num;
|
||||
};
|
||||
|
||||
extern struct dbg_stats_t dbg_stats;
|
||||
#define UPDATE_HEADER_TX_PKT_NO(h) h->pkt_num = htole16(dbg_stats.tx_pkt_num++)
|
||||
#define UPDATE_HEADER_RX_PKT_NO(h) \
|
||||
do { \
|
||||
uint16_t rcvd_pkt_num = le16toh(h->pkt_num); \
|
||||
if (dbg_stats.exp_rx_pkt_num != rcvd_pkt_num) { \
|
||||
ESP_LOGI(TAG, "exp_pkt_num[%u], rx_pkt_num[%u]", \
|
||||
dbg_stats.exp_rx_pkt_num, rcvd_pkt_num); \
|
||||
dbg_stats.exp_rx_pkt_num = rcvd_pkt_num; \
|
||||
} \
|
||||
dbg_stats.exp_rx_pkt_num++; \
|
||||
} while(0);
|
||||
|
||||
#else /*ESP_PKT_NUM_DEBUG*/
|
||||
|
||||
#define UPDATE_HEADER_TX_PKT_NO(h)
|
||||
#define UPDATE_HEADER_RX_PKT_NO(h)
|
||||
|
||||
#endif /*ESP_PKT_NUM_DEBUG*/
|
||||
|
||||
#if ESP_PKT_STATS
|
||||
struct pkt_stats_t {
|
||||
uint32_t sta_rx_in;
|
||||
uint32_t sta_rx_out;
|
||||
uint32_t sta_tx_in_pass;
|
||||
uint32_t sta_tx_trans_in;
|
||||
uint32_t sta_tx_flowctrl_drop;
|
||||
uint32_t sta_tx_out;
|
||||
uint32_t sta_tx_out_drop;
|
||||
uint32_t sta_flow_ctrl_on;
|
||||
uint32_t sta_flow_ctrl_off;
|
||||
};
|
||||
|
||||
extern struct pkt_stats_t pkt_stats;
|
||||
#endif /*ESP_PKT_STATS*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
void create_debugging_tasks(void);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user