blob: 4dd2a7d0ef3dbc050e6414b04f598616554a709e [file] [log] [blame]
/****************************************************************************
* arch/risc-v/src/esp32c6/esp_wifi_adapter.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <inttypes.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <debug.h>
#include <pthread.h>
#include <fcntl.h>
#include <unistd.h>
#include <math.h>
#include <clock/clock.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <irq/irq.h>
#include <nuttx/kmalloc.h>
#include <nuttx/mqueue.h>
#include <nuttx/spinlock.h>
#include <nuttx/irq.h>
#include <nuttx/mutex.h>
#include <nuttx/kthread.h>
#include <nuttx/wdog.h>
#include <nuttx/wqueue.h>
#include <nuttx/sched.h>
#include <nuttx/signal.h>
#include <nuttx/arch.h>
#include <nuttx/wireless/wireless.h>
#include <nuttx/tls.h>
#include "esp_irq.h"
#include "esp_hr_timer.h"
#include "esp_types.h"
#include "esp_random.h"
#include "esp_mac.h"
#include "esp_intr_alloc.h"
#include "esp_attr.h"
#include "esp_log.h"
#include "esp_event.h"
#include "esp_timer.h"
#include "esp_private/esp_modem_clock.h"
#include "esp_private/wifi_os_adapter.h"
#include "esp_private/wifi.h"
#include "esp_phy_init.h"
#include "soc/rtc_cntl_periph.h"
#include "esp_private/periph_ctrl.h"
#include "esp_private/esp_clk.h"
#include "os.h"
#include "esp_smartconfig.h"
#include "esp_coexist_internal.h"
#include "rom/ets_sys.h"
#include "esp_modem_wrapper.h"
#if SOC_PM_MODEM_RETENTION_BY_REGDMA
#include "esp_private/esp_regdma.h"
#include "esp_private/sleep_retention.h"
#endif
#include "esp_wlan.h"
#include "esp_wifi_adapter.h"
#include "esp_wifi_utils.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define PHY_RF_MASK ((1 << PHY_BT_MODULE) | (1 << PHY_WIFI_MODULE))
#define WIFI_CONNECT_TIMEOUT CONFIG_ESPRESSIF_WIFI_CONNECT_TIMEOUT
#define ESP_WIFI_11B_MAX_BITRATE 11
#define ESP_WIFI_11G_MAX_BITRATE 54
#define ESP_WIFI_11N_MCS7_HT20_BITRATE 72
#define ESP_WIFI_11N_MCS7_HT40_BITRATE 150
#ifndef CONFIG_EXAMPLE_WIFI_LISTEN_INTERVAL
#define CONFIG_EXAMPLE_WIFI_LISTEN_INTERVAL 3
#endif
#define DEFAULT_LISTEN_INTERVAL CONFIG_EXAMPLE_WIFI_LISTEN_INTERVAL
#define RTC_CLK_CAL_FRACT 19 //!< Number of fractional bits in values returned by rtc_clk_cal
#define ets_timer _ETSTIMER_
/* CONFIG_POWER_SAVE_MODEM */
#if defined(CONFIG_ESP_POWER_SAVE_MIN_MODEM)
# define DEFAULT_PS_MODE WIFI_PS_MIN_MODEM
#elif defined(CONFIG_ESP_POWER_SAVE_MAX_MODEM)
# define DEFAULT_PS_MODE WIFI_PS_MAX_MODEM
#elif defined(CONFIG_ESP_POWER_SAVE_NONE)
# define DEFAULT_PS_MODE WIFI_PS_NONE
#else
# define DEFAULT_PS_MODE WIFI_PS_NONE
#endif
#define ESP_MAX_PRIORITIES (25)
/****************************************************************************
* Private Types
****************************************************************************/
/* Wi-Fi event ID */
enum wifi_adpt_evt_e
{
WIFI_ADPT_EVT_SCAN_DONE = 0,
WIFI_ADPT_EVT_STA_START,
WIFI_ADPT_EVT_STA_CONNECT,
WIFI_ADPT_EVT_STA_DISCONNECT,
WIFI_ADPT_EVT_STA_AUTHMODE_CHANGE,
WIFI_ADPT_EVT_STA_STOP,
WIFI_ADPT_EVT_AP_START,
WIFI_ADPT_EVT_AP_STOP,
WIFI_ADPT_EVT_AP_STACONNECTED,
WIFI_ADPT_EVT_AP_STADISCONNECTED,
WIFI_ADPT_EVT_MAX,
};
/* Wi-Fi Station state */
enum wifi_sta_state
{
WIFI_STA_STATE_NULL,
WIFI_STA_STATE_START,
WIFI_STA_STATE_CONNECT,
WIFI_STA_STATE_DISCONNECT,
WIFI_STA_STATE_STOP
};
/* Wi-Fi interrupt adapter private data */
struct irq_adpt
{
void (*func)(void *arg); /* Interrupt callback function */
void *arg; /* Interrupt private data */
};
/* Wi-Fi message queue private data */
struct mq_adpt
{
struct file mq; /* Message queue handle */
uint32_t msgsize; /* Message size */
char name[16]; /* Message queue name */
};
/* Wi-Fi time private data */
struct time_adpt
{
time_t sec; /* Second value */
suseconds_t usec; /* Micro second value */
};
/* Wi-Fi event private data */
struct evt_adpt
{
sq_entry_t entry; /* Sequence entry */
int32_t id; /* Event ID */
uint8_t buf[0]; /* Event private data */
};
/* Wi-Fi event notification private data */
struct wifi_notify
{
bool assigned; /* Flag indicate if it is used */
pid_t pid; /* Signal's target thread PID */
struct sigevent event; /* Signal event private data */
struct sigwork_s work; /* Signal work private data */
};
/* Wi-Fi NVS private data */
struct nvs_adpt
{
char *index_name;
};
/* Wi-Fi event callback function */
typedef void (*wifi_evt_cb_t)(void *p);
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/* Private functions order is defined as:
* - A first block containing the functions in the same order as of the
* ESP-IDF' corresponding `esp_adapter.c` to ease comparison;
* - A second block of auxiliary functions block ordered by ascending;
*/
/* First block of functions */
static void *wifi_zalloc_wrapper(size_t size);
static void *wifi_create_queue(int queue_len, int item_size);
static void wifi_delete_queue(wifi_static_queue_t *queue);
static void *wifi_create_queue_wrapper(int queue_len, int item_size);
static void wifi_delete_queue_wrapper(void *queue);
static void set_intr_wrapper(int32_t cpu_no, uint32_t intr_source,
uint32_t intr_num, int32_t intr_prio);
static void clear_intr_wrapper(uint32_t intr_source, uint32_t intr_num);
static void set_isr_wrapper(int32_t n, void *f, void *arg);
static void enable_intr_wrapper(uint32_t intr_mask);
static void disable_intr_wrapper(uint32_t intr_mask);
static bool is_from_isr_wrapper(void);
static void wifi_thread_semphr_free(void *data);
static void *wifi_thread_semphr_get_wrapper(void);
static void *recursive_mutex_create_wrapper(void);
static void *mutex_create_wrapper(void);
static void mutex_delete_wrapper(void *mutex);
static int32_t mutex_lock_wrapper(void *mutex);
static int32_t mutex_unlock_wrapper(void *mutex);
static void *queue_create_wrapper(uint32_t queue_len, uint32_t item_size);
static int32_t queue_send_wrapper(void *queue,
void *item,
uint32_t block_time_tick);
static int32_t queue_send_from_isr_wrapper(void *queue,
void *item,
void *hptw);
static int32_t queue_send_to_back_wrapper(void *queue,
void *item,
uint32_t block_time_tick);
static int32_t queue_send_to_front_wrapper(void *queue,
void *item,
uint32_t block_time_tick);
static int32_t queue_recv_wrapper(void *queue,
void *item,
uint32_t block_time_tick);
static uint32_t event_group_wait_bits_wrapper(void *event,
uint32_t bits_to_wait_for,
int clear_on_exit,
int wait_for_all_bits,
uint32_t block_time_tick);
static int32_t task_create_pinned_to_core_wrapper(void *task_func,
const char *name,
uint32_t stack_depth,
void *param,
uint32_t prio,
void *task_handle,
uint32_t core_id);
static int32_t task_create_wrapper(void *task_func,
const char *name,
uint32_t stack_depth,
void *param,
uint32_t prio,
void *task_handle);
static int32_t task_ms_to_tick_wrapper(uint32_t ms);
static int32_t task_get_max_priority_wrapper(void);
int32_t esp_event_post_wrapper(const char *event_base,
int32_t event_id,
void *event_data,
size_t event_data_size,
uint32_t ticks);
static void wifi_apb80m_request_wrapper(void);
static void wifi_apb80m_release_wrapper(void);
static void timer_arm_wrapper(void *timer, uint32_t tmout, bool repeat);
static void wifi_reset_mac_wrapper(void);
static void wifi_clock_enable_wrapper(void);
static void wifi_clock_disable_wrapper(void);
static int get_time_wrapper(void *t);
static void *realloc_internal_wrapper(void *ptr, size_t size);
static void *calloc_internal_wrapper(size_t n, size_t size);
static void *zalloc_internal_wrapper(size_t size);
static int nvs_open_wrapper(const char *name, unsigned int open_mode,
uint32_t *out_handle);
static void esp_log_writev_wrapper(unsigned int level,
const char *tag,
const char *format,
va_list args);
static void esp_log_write_wrapper(unsigned int level,
const char *tag,
const char *format, ...);
static int esp_read_mac_wrapper(uint8_t *mac, unsigned int type);
static int coex_init_wrapper(void);
static void coex_deinit_wrapper(void);
static int coex_enable_wrapper(void);
static void coex_disable_wrapper(void);
static uint32_t coex_status_get_wrapper(void);
static int coex_wifi_request_wrapper(uint32_t event,
uint32_t latency,
uint32_t duration);
static int coex_wifi_release_wrapper(uint32_t event);
static int coex_wifi_channel_set_wrapper(uint8_t primary,
uint8_t secondary);
static int coex_event_duration_get_wrapper(uint32_t event,
uint32_t *duration);
static int coex_pti_get_wrapper(uint32_t event, uint8_t *pti);
static void coex_schm_status_bit_clear_wrapper(uint32_t type,
uint32_t status);
static void coex_schm_status_bit_set_wrapper(uint32_t type,
uint32_t status);
static int coex_schm_interval_set_wrapper(uint32_t interval);
static uint32_t coex_schm_interval_get_wrapper(void);
static uint8_t coex_schm_curr_period_get_wrapper(void);
static void *coex_schm_curr_phase_get_wrapper(void);
static int coex_register_start_cb_wrapper(int (* cb)(void));
static int coex_schm_process_restart_wrapper(void);
static int coex_schm_register_cb_wrapper(int type, int(*cb)(int));
static void esp_empty_wrapper(void);
/* Second block of functions
* These functions are auxiliary functions that are used by the first block
* of functions or software adapters for the Wi-Fi driver
*/
static int esp_event_id_map(int event_id);
static void esp_evt_work_cb(void *arg);
static int esp_freq_to_channel(uint16_t freq);
static uint32_t esp_get_free_heap_size(void);
static void *event_group_create_wrapper(void);
static void event_group_delete_wrapper(void *event);
static uint32_t event_group_set_bits_wrapper(void *event, uint32_t bits);
static uint32_t event_group_clear_bits_wrapper(void *event, uint32_t bits);
static int esp_int_adpt_cb(int irq, void *context, void *arg);
static int esp_nvs_commit(uint32_t handle);
static int esp_nvs_erase_key(uint32_t handle, const char *key);
static int esp_nvs_get_blob(uint32_t handle,
const char *key,
void *out_value,
size_t *length);
static int esp_nvs_set_blob(uint32_t handle,
const char *key,
const void *value,
size_t length);
static int esp_nvs_get_i8(uint32_t handle,
const char *key,
int8_t *out_value);
static int esp_nvs_set_i8(uint32_t handle, const char *key, int8_t value);
static int esp_nvs_get_u8(uint32_t handle,
const char *key,
uint8_t *out_value);
static int esp_nvs_set_u8(uint32_t handle, const char *key, uint8_t value);
static int esp_nvs_get_u16(uint32_t handle,
const char *key,
uint16_t *out_value);
static int esp_nvs_set_u16(uint32_t handle, const char *key, uint16_t value);
static void esp_nvs_close(uint32_t handle);
static void esp_update_time(struct timespec *timespec, uint32_t ticks);
static int esp_wifi_auth_trans(uint32_t wifi_auth);
static int esp_wifi_cipher_trans(uint32_t wifi_cipher);
static int esp_wifi_lock(bool lock);
static uint32_t queue_msg_waiting_wrapper(void *queue);
static void task_delay_wrapper(uint32_t tick);
static void task_delete_wrapper(void *task_handle);
static void *task_get_current_task_wrapper(void);
static void vqueue_delete_adapter(void *queue);
static void vsemaphore_delete_adapter(void *semphr);
static void *xqueue_create_adapter(uint32_t queue_len, uint32_t item_size);
static int32_t xqueue_send_adapter(void *queue,
void *item,
uint32_t ticks,
int prio);
void *xsemaphore_create_counting_adapter(uint32_t max, uint32_t init);
#ifdef CONFIG_PM
extern void wifi_apb80m_request(void);
extern void wifi_apb80m_release(void);
#endif
/****************************************************************************
* Private Data
****************************************************************************/
/* Wi-Fi event private data */
static struct work_s g_wifi_evt_work;
static sq_queue_t g_wifi_evt_queue;
static struct wifi_notify g_wifi_notify[WIFI_ADPT_EVT_MAX];
static mutex_t g_wifiexcl_lock = NXMUTEX_INITIALIZER;
/* Wi-Fi adapter reference */
static int g_wifi_ref;
#ifdef ESP_WLAN_HAS_STA
/* If reconnect automatically */
static bool g_sta_reconnect;
/* If Wi-Fi sta starts */
static bool g_sta_started;
/* If Wi-Fi sta connected */
static bool g_sta_connected;
/* Wi-Fi interface configuration */
static wifi_config_t g_sta_wifi_cfg;
#endif /* ESP_WLAN_HAS_STA */
#ifdef ESP_WLAN_HAS_SOFTAP
/* If Wi-Fi SoftAP starts */
static bool g_softap_started;
/* Wi-Fi interface configuration */
static wifi_config_t g_softap_wifi_cfg;
#endif /* ESP_WLAN_HAS_SOFTAP */
/* Device specific lock */
static spinlock_t g_lock;
/****************************************************************************
* Public Data
****************************************************************************/
/* Wi-Fi OS adapter data */
wifi_osi_funcs_t g_wifi_osi_funcs =
{
._version = ESP_WIFI_OS_ADAPTER_VERSION,
._env_is_chip = esp_coex_common_env_is_chip_wrapper,
._set_intr = set_intr_wrapper,
._clear_intr = clear_intr_wrapper,
._set_isr = set_isr_wrapper,
._ints_on = enable_intr_wrapper,
._ints_off = disable_intr_wrapper,
._is_from_isr = is_from_isr_wrapper,
._spin_lock_create = esp_coex_common_spin_lock_create_wrapper,
._spin_lock_delete = free,
._wifi_int_disable = esp_coex_common_int_disable_wrapper,
._wifi_int_restore = esp_coex_common_int_restore_wrapper,
._task_yield_from_isr = esp_coex_common_task_yield_from_isr_wrapper,
._semphr_create = esp_coex_common_semphr_create_wrapper,
._semphr_delete = esp_coex_common_semphr_delete_wrapper,
._semphr_take = esp_coex_common_semphr_take_wrapper,
._semphr_give = esp_coex_common_semphr_give_wrapper,
._wifi_thread_semphr_get = wifi_thread_semphr_get_wrapper,
._mutex_create = mutex_create_wrapper,
._recursive_mutex_create = recursive_mutex_create_wrapper,
._mutex_delete = mutex_delete_wrapper,
._mutex_lock = mutex_lock_wrapper,
._mutex_unlock = mutex_unlock_wrapper,
._queue_create = queue_create_wrapper,
._queue_delete = vqueue_delete_adapter,
._queue_send = queue_send_wrapper,
._queue_send_from_isr = queue_send_from_isr_wrapper,
._queue_send_to_back = queue_send_to_back_wrapper,
._queue_send_to_front = queue_send_to_front_wrapper,
._queue_recv = queue_recv_wrapper,
._queue_msg_waiting = queue_msg_waiting_wrapper,
._event_group_create = event_group_create_wrapper,
._event_group_delete = event_group_delete_wrapper,
._event_group_set_bits = event_group_set_bits_wrapper,
._event_group_clear_bits = event_group_clear_bits_wrapper,
._event_group_wait_bits = event_group_wait_bits_wrapper,
._task_create_pinned_to_core = task_create_pinned_to_core_wrapper,
._task_create = task_create_wrapper,
._task_delete = task_delete_wrapper,
._task_delay = task_delay_wrapper,
._task_ms_to_tick = task_ms_to_tick_wrapper,
._task_get_current_task = task_get_current_task_wrapper,
._task_get_max_priority = task_get_max_priority_wrapper,
._malloc = malloc,
._free = free,
._event_post = esp_event_post_wrapper,
._get_free_heap_size = esp_get_free_heap_size,
._rand = esp_random,
._dport_access_stall_other_cpu_start_wrap =
esp_empty_wrapper,
._dport_access_stall_other_cpu_end_wrap =
esp_empty_wrapper,
._wifi_apb80m_request = wifi_apb80m_request_wrapper,
._wifi_apb80m_release = wifi_apb80m_release_wrapper,
._phy_disable = esp_phy_disable,
._phy_enable = esp_phy_enable,
._phy_update_country_info = esp_phy_update_country_info,
._read_mac = esp_read_mac_wrapper,
._timer_arm = timer_arm_wrapper,
._timer_disarm = esp_coex_common_timer_disarm_wrapper,
._timer_done = esp_coex_common_timer_done_wrapper,
._timer_setfn = esp_coex_common_timer_setfn_wrapper,
._timer_arm_us = esp_coex_common_timer_arm_us_wrapper,
._wifi_reset_mac = wifi_reset_mac_wrapper,
._wifi_clock_enable = wifi_clock_enable_wrapper,
._wifi_clock_disable = wifi_clock_disable_wrapper,
._wifi_rtc_enable_iso = esp_empty_wrapper,
._wifi_rtc_disable_iso = esp_empty_wrapper,
._esp_timer_get_time = (int64_t(*)(void))esp_hr_timer_time_us,
._nvs_set_i8 = esp_nvs_set_i8,
._nvs_get_i8 = esp_nvs_get_i8,
._nvs_set_u8 = esp_nvs_set_u8,
._nvs_get_u8 = esp_nvs_get_u8,
._nvs_set_u16 = esp_nvs_set_u16,
._nvs_get_u16 = esp_nvs_get_u16,
._nvs_open = nvs_open_wrapper,
._nvs_close = esp_nvs_close,
._nvs_commit = esp_nvs_commit,
._nvs_set_blob = esp_nvs_set_blob,
._nvs_get_blob = esp_nvs_get_blob,
._nvs_erase_key = esp_nvs_erase_key,
._get_random = os_get_random,
._get_time = get_time_wrapper,
._random = os_random,
._slowclk_cal_get = esp_coex_common_clk_slowclk_cal_get_wrapper,
._log_write = esp_log_write_wrapper,
._log_writev = esp_log_writev_wrapper,
._log_timestamp = esp_log_timestamp,
._malloc_internal = esp_coex_common_malloc_internal_wrapper,
._realloc_internal = realloc_internal_wrapper,
._calloc_internal = calloc_internal_wrapper,
._zalloc_internal = zalloc_internal_wrapper,
._wifi_malloc = wifi_malloc,
._wifi_realloc = wifi_realloc,
._wifi_calloc = wifi_calloc,
._wifi_zalloc = wifi_zalloc_wrapper,
._wifi_create_queue = wifi_create_queue_wrapper,
._wifi_delete_queue = wifi_delete_queue_wrapper,
._coex_init = coex_init_wrapper,
._coex_deinit = coex_deinit_wrapper,
._coex_enable = coex_enable_wrapper,
._coex_disable = coex_disable_wrapper,
._coex_status_get = coex_status_get_wrapper,
._coex_wifi_request = coex_wifi_request_wrapper,
._coex_wifi_release = coex_wifi_release_wrapper,
._coex_wifi_channel_set = coex_wifi_channel_set_wrapper,
._coex_event_duration_get = coex_event_duration_get_wrapper,
._coex_pti_get = coex_pti_get_wrapper,
._coex_schm_status_bit_clear = coex_schm_status_bit_clear_wrapper,
._coex_schm_status_bit_set = coex_schm_status_bit_set_wrapper,
._coex_schm_interval_set = coex_schm_interval_set_wrapper,
._coex_schm_interval_get = coex_schm_interval_get_wrapper,
._coex_schm_curr_period_get = coex_schm_curr_period_get_wrapper,
._coex_schm_curr_phase_get = coex_schm_curr_phase_get_wrapper,
._coex_register_start_cb = coex_register_start_cb_wrapper,
._coex_schm_process_restart = coex_schm_process_restart_wrapper,
._coex_schm_register_cb = coex_schm_register_cb_wrapper,
._magic = ESP_WIFI_OS_ADAPTER_MAGIC,
};
/****************************************************************************
* Private Functions
****************************************************************************/
/* Private functions order is defined as:
* - A first block containing the functions in the same order as of the
* ESP-IDF' corresponding `esp_adapter.c` to ease comparison;
* - A second block of auxiliary functions block ordered by ascending;
*/
/* First block of functions */
/****************************************************************************
* Name: wifi_zalloc_wrapper
*
* Description:
* Applications allocate a block of memory and clear it with 0
*
* Input Parameters:
* size - memory size
*
* Returned Value:
* New memory pointer
*
****************************************************************************/
static IRAM_ATTR void *wifi_zalloc_wrapper(size_t size)
{
return zalloc(size);
}
/****************************************************************************
* Name: wifi_create_queue
*
* Description:
* Create Wi-Fi static message queue
*
* Input Parameters:
* queue_len - queue message number
* item_size - message size
*
* Returned Value:
* Wi-Fi static message queue data pointer
*
****************************************************************************/
static void *wifi_create_queue(int queue_len, int item_size)
{
wifi_static_queue_t *wifi_queue;
wifi_queue = kmm_malloc(sizeof(wifi_static_queue_t));
if (!wifi_queue)
{
wlerr("Failed to kmm_malloc\n");
return NULL;
}
wifi_queue->handle = xqueue_create_adapter(queue_len, item_size);
if (!wifi_queue->handle)
{
wlerr("Failed to create queue\n");
kmm_free(wifi_queue);
return NULL;
}
return wifi_queue;
}
/****************************************************************************
* Name: wifi_delete_queue
*
* Description:
* Delete message queue
*
* Input Parameters:
* queue - Message queue data pointer
*
* Returned Value:
* None
*
****************************************************************************/
static void wifi_delete_queue(wifi_static_queue_t *queue)
{
if (queue)
{
vqueue_delete_adapter(queue->handle);
kmm_free(queue);
}
}
/****************************************************************************
* Name: wifi_create_queue_wrapper
*
* Description:
* This function creates a new queue for Wi-Fi operations. It is a wrapper
* around the wifi_create_queue function, providing a consistent interface
* for the Wi-Fi module.
*
* Input Parameters:
* queue_len - The maximum number of items that the queue can hold.
* item_size - The size of each item in the queue.
*
* Returned Value:
* A pointer to the newly created queue, or NULL if the operation failed.
*
****************************************************************************/
static void *wifi_create_queue_wrapper(int queue_len, int item_size)
{
return wifi_create_queue(queue_len, item_size);
}
/****************************************************************************
* Name: wifi_delete_queue_wrapper
*
* Description:
* Delete Wi-Fi static message queue
*
* Input Parameters:
* queue - Wi-Fi static message queue data pointer
*
* Returned Value:
* None
*
****************************************************************************/
static void wifi_delete_queue_wrapper(void *queue)
{
wifi_delete_queue(queue);
}
/****************************************************************************
* Name: set_intr_wrapper
*
* Description:
* Do nothing
*
* Input Parameters:
* cpu_no - The CPU which the interrupt number belongs.
* intr_source - The interrupt hardware source number.
* intr_num - The interrupt number CPU.
* intr_prio - The interrupt priority.
*
* Returned Value:
* None
*
****************************************************************************/
static void set_intr_wrapper(int32_t cpu_no, uint32_t intr_source,
uint32_t intr_num, int32_t intr_prio)
{
wlinfo("cpu_no=%" PRId32 ", intr_source=%" PRIu32
", intr_num=%" PRIu32 ", intr_prio=%" PRId32 "\n",
cpu_no, intr_source, intr_num, intr_prio);
esp_route_intr(intr_source, intr_num, intr_prio, ESP_IRQ_TRIGGER_LEVEL);
esp_set_irq(ESP_SOURCE2IRQ(intr_source), intr_num);
}
/****************************************************************************
* Name: clear_intr_wrapper
*
* Description:
* This function is intended to clear a specific interrupt. However, this
* functionality is not supported in the current implementation.
*
* Input Parameters:
* intr_source - The source of the interrupt.
* intr_num - The number of the interrupt.
*
* Returned Value:
* None
*
****************************************************************************/
static void IRAM_ATTR clear_intr_wrapper(uint32_t intr_source,
uint32_t intr_num)
{
}
/****************************************************************************
* Name: set_isr_wrapper
*
* Description:
* Register interrupt function
*
* Input Parameters:
* n - CPU interrupt number
* f - Interrupt function
* arg - Function private data
*
* Returned Value:
* None
*
****************************************************************************/
static void set_isr_wrapper(int32_t n, void *f, void *arg)
{
int ret;
uint32_t tmp;
struct irq_adpt *adapter;
int irq = esp_get_irq(n);
wlinfo("n=%ld f=%p arg=%p irq=%d\n", n, f, arg, irq);
if (g_irqvector[irq].handler &&
g_irqvector[irq].handler != irq_unexpected_isr)
{
wlinfo("irq=%d has been set handler=%p\n", irq,
g_irqvector[irq].handler);
return;
}
tmp = sizeof(struct irq_adpt);
adapter = kmm_malloc(tmp);
if (!adapter)
{
wlerr("Failed to alloc %ld memory\n", tmp);
PANIC();
return;
}
adapter->func = f;
adapter->arg = arg;
ret = irq_attach(irq, esp_int_adpt_cb, adapter);
if (ret)
{
wlerr("Failed to attach IRQ %d\n", irq);
PANIC();
return;
}
}
/****************************************************************************
* Name: enable_intr_wrapper
*
* Description:
* Enable a specific Wi-Fi interrupt.
*
* Input Parameters:
* intr_mask - A mask where the bit corresponding to the interrupt to be
* enabled is set.
*
* Returned Value:
* None
*
****************************************************************************/
static void enable_intr_wrapper(uint32_t intr_mask)
{
int cpuint = __builtin_ffs(intr_mask) - 1;
int irq = esp_get_irq(cpuint);
wlinfo("intr_mask=%08lx cpuint=%d irq=%d\n", intr_mask, cpuint, irq);
up_enable_irq(irq);
}
/****************************************************************************
* Name: disable_intr_wrapper
*
* Description:
* Disable a specific Wi-Fi interrupt.
*
* Input Parameters:
* intr_mask - A mask where the bit corresponding to the interrupt to be
* disabled is set.
*
* Returned Value:
* None
*
****************************************************************************/
static void disable_intr_wrapper(uint32_t intr_mask)
{
int cpuint = __builtin_ffs(intr_mask) - 1;
int irq = esp_get_irq(cpuint);
wlinfo("intr_mask=%08lx cpuint=%d irq=%d\n", intr_mask, cpuint, irq);
up_disable_irq(irq);
}
/****************************************************************************
* Name: is_from_isr_wrapper
*
* Description:
* Check current is in interrupt
*
* Input Parameters:
* None
*
* Returned Value:
* true if in interrupt or false if not
*
****************************************************************************/
static bool IRAM_ATTR is_from_isr_wrapper(void)
{
return up_interrupt_context();
}
/****************************************************************************
* Name: wifi_thread_semphr_free
*
* Description:
* Delete thread self's semaphore
*
* Input Parameters:
* data - Semaphore data pointer
*
* Returned Value:
* None
*
****************************************************************************/
static void wifi_thread_semphr_free(void *data)
{
void *sem = (void *)data;
if (sem)
{
vsemaphore_delete_adapter(sem);
}
}
/****************************************************************************
* Name: wifi_thread_semphr_get_wrapper
*
* Description:
* Get thread self's semaphore
*
* Input Parameters:
* None
*
* Returned Value:
* Semaphore data pointer
*
****************************************************************************/
static void *wifi_thread_semphr_get_wrapper(void)
{
static int wifi_task_key = -1;
int ret;
void *sem;
if (wifi_task_key < 0)
{
ret = task_tls_alloc(wifi_thread_semphr_free);
if (ret < 0)
{
wlerr("Failed to create task local key\n");
return NULL;
}
wifi_task_key = ret;
}
sem = (void *)task_tls_get_value(wifi_task_key);
if (sem == NULL)
{
sem = xsemaphore_create_counting_adapter(1, 0);
if (!sem)
{
wlerr("Failed to create semaphore\n");
return NULL;
}
ret = task_tls_set_value(wifi_task_key, (uintptr_t)sem);
if (ret != OK)
{
wlerr("Failed to save semaphore on task local storage: %d\n", ret);
vsemaphore_delete_adapter(sem);
return NULL;
}
}
return sem;
}
/****************************************************************************
* Name: recursive_mutex_create_wrapper
*
* Description:
* Create recursive mutex
*
* Input Parameters:
* None
*
* Returned Value:
* Recursive mutex data pointer
*
****************************************************************************/
static void *recursive_mutex_create_wrapper(void)
{
int ret;
pthread_mutex_t *mutex;
pthread_mutexattr_t attr;
int tmp;
ret = pthread_mutexattr_init(&attr);
if (ret)
{
wlerr("Failed to initialize attr error=%d\n", ret);
return NULL;
}
ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
if (ret)
{
wlerr("Failed to set attr type error=%d\n", ret);
return NULL;
}
tmp = sizeof(pthread_mutex_t);
mutex = kmm_malloc(tmp);
if (!mutex)
{
wlerr("Failed to alloc %d memory\n", tmp);
return NULL;
}
ret = pthread_mutex_init(mutex, &attr);
if (ret)
{
wlerr("Failed to initialize mutex error=%d\n", ret);
kmm_free(mutex);
return NULL;
}
return mutex;
}
/****************************************************************************
* Name: mutex_create_wrapper
*
* Description:
* Create mutex
*
* Input Parameters:
* None
*
* Returned Value:
* Mutex data pointer
*
****************************************************************************/
static void *mutex_create_wrapper(void)
{
int ret;
pthread_mutex_t *mutex;
int tmp;
tmp = sizeof(pthread_mutex_t);
mutex = kmm_malloc(tmp);
if (!mutex)
{
wlerr("Failed to alloc %d memory\n", tmp);
return NULL;
}
ret = pthread_mutex_init(mutex, NULL);
if (ret)
{
wlerr("Failed to initialize mutex error=%d\n", ret);
kmm_free(mutex);
return NULL;
}
return mutex;
}
/****************************************************************************
* Name: mutex_delete_wrapper
*
* Description:
* Delete mutex
*
* Input Parameters:
* mutex - mutex data pointer
*
* Returned Value:
* None
*
****************************************************************************/
static void mutex_delete_wrapper(void *mutex)
{
pthread_mutex_t *mutex_data = (pthread_mutex_t *)mutex;
pthread_mutex_destroy(mutex_data);
kmm_free(mutex_data);
}
/****************************************************************************
* Name: mutex_lock_wrapper
*
* Description:
* Lock mutex
*
* Input Parameters:
* mutex - mutex data pointer
*
* Returned Value:
* True if success or false if fail
*
****************************************************************************/
static int32_t IRAM_ATTR mutex_lock_wrapper(void *mutex)
{
int ret;
pthread_mutex_t *mutex_data = (pthread_mutex_t *)mutex;
ret = pthread_mutex_lock(mutex_data);
if (ret)
{
wlerr("Failed to lock mutex error=%d\n", ret);
}
return nuttx_err_to_freertos(ret);
}
/****************************************************************************
* Name: mutex_unlock_wrapper
*
* Description:
* Unlock mutex
*
* Input Parameters:
* mutex - mutex data pointer
*
* Returned Value:
* True if success or false if fail
*
****************************************************************************/
static int32_t IRAM_ATTR mutex_unlock_wrapper(void *mutex)
{
int ret;
pthread_mutex_t *mutex_data = (pthread_mutex_t *)mutex;
ret = pthread_mutex_unlock(mutex_data);
if (ret)
{
wlerr("Failed to unlock mutex error=%d\n", ret);
}
return nuttx_err_to_freertos(ret);
}
/****************************************************************************
* Name: queue_create_wrapper
*
* Description:
* This function creates a new queue adapter with the specified length and
* item size. It is a wrapper around the xqueue_create_adapter function.
*
* Input Parameters:
* queue_len - The maximum number of items that the queue can hold.
* item_size - The size of each item in the queue.
*
* Returned Value:
* A pointer to the newly created queue adapter, or NULL if the operation
* failed.
*
****************************************************************************/
static void *queue_create_wrapper(uint32_t queue_len, uint32_t item_size)
{
return xqueue_create_adapter(queue_len, item_size);
}
/****************************************************************************
* Name: queue_send_wrapper
*
* Description:
* Send message of low priority to queue within a certain period of time
*
* Input Parameters:
* queue - Message queue data pointer
* item - Message data pointer
* ticks - Wait ticks
*
* Returned Value:
* True if success or false if fail
*
****************************************************************************/
static int32_t queue_send_wrapper(void *queue, void *item, uint32_t ticks)
{
return xqueue_send_adapter(queue, item, ticks, 0);
}
/****************************************************************************
* Name: queue_send_from_isr_wrapper
*
* Description:
* Send message of low priority to queue in ISR within
* a certain period of time
*
* Input Parameters:
* queue - Message queue data pointer
* item - Message data pointer
* hptw - Unused.
*
* Returned Value:
* True if success or false if fail
*
****************************************************************************/
static int32_t IRAM_ATTR queue_send_from_isr_wrapper(void *queue,
void *item,
void *hptw)
{
*(int *)hptw = 0;
return xqueue_send_adapter(queue, item, 0, 0);
}
/****************************************************************************
* Name: queue_send_to_back_wrapper
*
* Description:
* Send message of low priority to queue within a certain period of time
*
* Input Parameters:
* queue - Message queue data pointer
* item - Message data pointer
* ticks - Wait ticks
*
* Returned Value:
* True if success or false if fail
*
****************************************************************************/
static int32_t queue_send_to_back_wrapper(void *queue,
void *item,
uint32_t ticks)
{
return xqueue_send_adapter(queue, item, ticks, 0);
}
/****************************************************************************
* Name: queue_send_to_front_wrapper
*
* Description:
* Send message of high priority to queue within a certain period of time
*
* Input Parameters:
* queue - Message queue data pointer
* item - Message data pointer
* ticks - Wait ticks
*
* Returned Value:
* True if success or false if fail
*
****************************************************************************/
static int32_t queue_send_to_front_wrapper(void *queue,
void *item,
uint32_t ticks)
{
return xqueue_send_adapter(queue, item, ticks, 1);
}
/****************************************************************************
* Name: queue_recv_wrapper
*
* Description:
* Receive message from queue within a certain period of time
*
* Input Parameters:
* queue - Message queue data pointer
* item - Message data pointer
* ticks - Wait ticks
*
* Returned Value:
* True if success or false if fail
*
****************************************************************************/
static int32_t queue_recv_wrapper(void *queue, void *item, uint32_t ticks)
{
ssize_t ret;
struct timespec timeout;
unsigned int prio;
struct mq_adpt *mq_adpt = (struct mq_adpt *)queue;
if (ticks == OSI_FUNCS_TIME_BLOCKING)
{
ret = file_mq_receive(&mq_adpt->mq, (char *)item,
mq_adpt->msgsize, &prio);
if (ret < 0)
{
wlerr("Failed to receive from mqueue error=%d\n", ret);
}
}
else
{
ret = clock_gettime(CLOCK_REALTIME, &timeout);
if (ret < 0)
{
wlerr("Failed to get time\n");
return false;
}
if (ticks)
{
esp_update_time(&timeout, ticks);
}
ret = file_mq_timedreceive(&mq_adpt->mq, (char *)item,
mq_adpt->msgsize, &prio, &timeout);
if (ret < 0)
{
wlerr("Failed to timedreceive from mqueue error=%d\n",
ret);
}
}
return ret > 0 ? true : false;
}
/****************************************************************************
* Name: event_group_wait_bits_wrapper
*
* Description:
* Don't support
*
****************************************************************************/
static uint32_t event_group_wait_bits_wrapper(void *event,
uint32_t bits_to_wait_for,
int clear_on_exit,
int wait_for_all_bits,
uint32_t block_time_tick)
{
DEBUGPANIC();
return false;
}
/****************************************************************************
* Name: task_create_pinned_to_core_wrapper
*
* Description:
* Create task and bind it to target CPU, the task will run when it
* is created
*
* Input Parameters:
* entry - Task entry
* name - Task name
* stack_depth - Task stack size
* param - Task private data
* prio - Task priority
* task_handle - Task handle pointer which is used to pause, resume
* and delete the task
* core_id - CPU which the task runs in
*
* Returned Value:
* True if success or false if fail
*
****************************************************************************/
static int32_t task_create_pinned_to_core_wrapper(void *entry,
const char *name,
uint32_t stack_depth,
void *param,
uint32_t prio,
void *task_handle,
uint32_t core_id)
{
int pid;
#ifdef CONFIG_SMP
int ret;
cpu_set_t cpuset;
#endif
uint32_t target_prio = prio;
if (target_prio < ESP_MAX_PRIORITIES)
{
target_prio += task_get_max_priority_wrapper() - ESP_MAX_PRIORITIES;
}
pid = kthread_create(name, target_prio, stack_depth, entry,
(char * const *)param);
if (pid > 0)
{
if (task_handle != NULL)
{
*((int *)task_handle) = pid;
}
#ifdef CONFIG_SMP
if (core_id < CONFIG_SMP_NCPUS)
{
CPU_ZERO(&cpuset);
CPU_SET(core_id, &cpuset);
ret = nxsched_set_affinity(pid, sizeof(cpuset), &cpuset);
if (ret)
{
wlerr("Failed to set affinity error=%d\n", ret);
return false;
}
}
#endif
}
else
{
wlerr("Failed to create task\n");
}
return pid > 0;
}
/****************************************************************************
* Name: task_create_wrapper
*
* Description:
* Create task and the task will run when it is created
*
* Input Parameters:
* entry - Task entry
* name - Task name
* stack_depth - Task stack size
* param - Task private data
* prio - Task priority
* task_handle - Task handle pointer which is used to pause, resume
* and delete the task
*
* Returned Value:
* True if success or false if fail
*
****************************************************************************/
static int32_t task_create_wrapper(void *entry,
const char *name,
uint32_t stack_depth,
void *param,
uint32_t prio,
void *task_handle)
{
return task_create_pinned_to_core_wrapper(entry,
name,
stack_depth,
param,
prio,
task_handle,
UINT32_MAX);
}
/****************************************************************************
* Name: task_ms_to_tick_wrapper
*
* Description:
* This function converts a duration from milliseconds to system ticks.
* It is a wrapper around the NuttX MSEC2TICK macro.
*
* Input Parameters:
* ms - The duration in milliseconds.
*
* Returned Value:
* The duration in system ticks.
*
****************************************************************************/
static int32_t task_ms_to_tick_wrapper(uint32_t ms)
{
return MSEC2TICK(ms);
}
/****************************************************************************
* Name: task_get_max_priority_wrapper
*
* Description:
* Get OS task maximum priority
*
* Input Parameters:
* None
*
* Returned Value:
* Task maximum priority
*
****************************************************************************/
static int32_t task_get_max_priority_wrapper(void)
{
return SCHED_PRIORITY_MAX;
}
/****************************************************************************
* Name: esp_event_post_wrapper
*
* Description:
* Active work queue and let the work to process the cached event
*
* Input Parameters:
* event_base - Event set name
* event_id - Event ID
* event_data - Event private data
* event_data_size - Event data size
* ticks - Waiting system ticks
*
* Returned Value:
* 0 if success or -1 if fail
*
****************************************************************************/
int32_t esp_event_post_wrapper(const char *event_base,
int32_t event_id,
void *event_data,
size_t event_data_size,
uint32_t ticks)
{
size_t size;
int32_t id;
irqstate_t flags;
struct evt_adpt *evt_adpt;
wlinfo("Event: base=%s id=%ld data=%p data_size=%d ticks=%lu\n",
event_base, event_id, event_data, event_data_size, ticks);
id = esp_event_id_map(event_id);
if (id < 0)
{
wlinfo("No process event %ld\n", event_id);
return -1;
}
size = event_data_size + sizeof(struct evt_adpt);
evt_adpt = kmm_malloc(size);
if (!evt_adpt)
{
wlerr("Failed to alloc %d memory\n", size);
return -1;
}
evt_adpt->id = id;
memcpy(evt_adpt->buf, event_data, event_data_size);
flags = spin_lock_irqsave(&g_lock);
sq_addlast(&evt_adpt->entry, &g_wifi_evt_queue);
spin_unlock_irqrestore(&g_lock, flags);
work_queue(LPWORK, &g_wifi_evt_work, esp_evt_work_cb, NULL, 0);
return 0;
}
/****************************************************************************
* Name: wifi_apb80m_request_wrapper
*
* Description:
* This function acquires the Wi-Fi lock in auto-sleep mode.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
static void IRAM_ATTR wifi_apb80m_request_wrapper(void)
{
#ifdef CONFIG_PM
wifi_apb80m_request();
#endif
}
/****************************************************************************
* Name: wifi_apb80m_release_wrapper
*
* Description:
* This function releases the Wi-Fi lock in auto-sleep mode.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
static void IRAM_ATTR wifi_apb80m_release_wrapper(void)
{
#ifdef CONFIG_PM
wifi_apb80m_release();
#endif
}
/****************************************************************************
* Name: timer_arm_wrapper
*
* Description:
* Set timer timeout period and repeat flag
*
* Input Parameters:
* ptimer - timer data pointer
* ms - millim seconds
* repeat - true: run cycle, false: run once
*
* Returned Value:
* None
*
****************************************************************************/
static void IRAM_ATTR timer_arm_wrapper(void *ptimer,
uint32_t tmout,
bool repeat)
{
ets_timer_arm(ptimer, tmout, repeat);
}
/****************************************************************************
* Name: wifi_reset_mac_wrapper
*
* Description:
* Reset Wi-Fi hardware MAC
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
static void wifi_reset_mac_wrapper(void)
{
modem_clock_module_mac_reset(PERIPH_WIFI_MODULE);
}
/****************************************************************************
* Name: wifi_clock_enable_wrapper
*
* Description:
* Enable Wi-Fi clock
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
static void wifi_clock_enable_wrapper(void)
{
wifi_module_enable();
}
/****************************************************************************
* Name: wifi_clock_disable_wrapper
*
* Description:
* Disable Wi-Fi clock
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
static void wifi_clock_disable_wrapper(void)
{
wifi_module_disable();
}
/****************************************************************************
* Name: get_time_wrapper
*
* Description:
* Get std C time
*
* Input Parameters:
* t - buffer to store time of type timeval
*
* Returned Value:
* Zero (OK) on success; -1 is returned on failure with the errno variable
* set appropriately.
*
****************************************************************************/
static int get_time_wrapper(void *t)
{
return os_get_time(t);
}
/****************************************************************************
* Name: realloc_internal_wrapper
*
* Description:
* Drivers allocate a block of memory by old memory block
*
* Input Parameters:
* ptr - old memory pointer
* size - memory size
*
* Returned Value:
* New memory pointer
*
****************************************************************************/
static IRAM_ATTR void *realloc_internal_wrapper(void *ptr, size_t size)
{
return kmm_realloc(ptr, size);
}
/****************************************************************************
* Name: calloc_internal_wrapper
*
* Description:
* Drivers allocate some continuous blocks of memory
*
* Input Parameters:
* n - memory block number
* size - memory block size
*
* Returned Value:
* New memory pointer
*
****************************************************************************/
static IRAM_ATTR void *calloc_internal_wrapper(size_t n, size_t size)
{
return kmm_calloc(n, size);
}
/****************************************************************************
* Name: zalloc_internal_wrapper
*
* Description:
* Drivers allocate a block of memory and clear it with 0
*
* Input Parameters:
* size - memory size
*
* Returned Value:
* New memory pointer
*
****************************************************************************/
static IRAM_ATTR void *zalloc_internal_wrapper(size_t size)
{
return kmm_zalloc(size);
}
/****************************************************************************
* Name: nvs_open_wrapper
*
* Description:
* Create a file system storage data object
*
* Input Parameters:
* name - Storage index
* open_mode - Storage mode
* out_handle - Storage handle
*
* Returned Value:
* 0 if success or -1 if fail
*
****************************************************************************/
static int nvs_open_wrapper(const char *name,
unsigned int open_mode,
uint32_t *out_handle)
{
DEBUGPANIC();
return -1;
}
/****************************************************************************
* Name: esp_log_writev_wrapper
*
* Description:
* Output log with by format string and its arguments
*
* Input Parameters:
* level - log level, no mean here
* tag - log TAG, no mean here
* format - format string
* args - arguments list
*
* Returned Value:
* None
*
****************************************************************************/
static void esp_log_writev_wrapper(unsigned int level,
const char *tag,
const char *format,
va_list args)
{
esp_log_level_t max_level;
#if defined (CONFIG_DEBUG_WIRELESS_INFO)
max_level = ESP_LOG_VERBOSE;
#elif defined (CONFIG_DEBUG_WIRELESS_WARN)
max_level = ESP_LOG_WARN;
#elif defined (CONFIG_DEBUG_WIRELESS_ERROR)
max_level = ESP_LOG_ERROR;
#else
max_level = ESP_LOG_NONE;
#endif
if (level <= max_level)
{
esp_log_writev(level, tag, format, args);
}
}
/****************************************************************************
* Name: esp_log_write_wrapper
*
* Description:
* Output log with by format string and its arguments
*
* Input Parameters:
* level - log level, no mean here
* tag - log TAG, no mean here
* format - format string
*
* Returned Value:
* None
*
****************************************************************************/
static void esp_log_write_wrapper(unsigned int level,
const char *tag,
const char *format, ...)
{
esp_log_level_t max_level;
#if defined (CONFIG_DEBUG_WIRELESS_INFO)
max_level = ESP_LOG_VERBOSE;
#elif defined (CONFIG_DEBUG_WIRELESS_WARN)
max_level = ESP_LOG_WARN;
#elif defined (CONFIG_DEBUG_WIRELESS_ERROR)
max_level = ESP_LOG_ERROR;
#else
max_level = ESP_LOG_NONE;
#endif
if (level <= max_level)
{
va_list list;
va_start(list, format);
esp_log_writev(level, tag, format, list);
va_end(list);
}
}
/****************************************************************************
* Name: esp_read_mac_wrapper
*
* Description:
* Read MAC address from efuse
*
* Input Parameters:
* mac - MAC address buffer pointer
* type - MAC address type
*
* Returned Value:
* 0 if success or -1 if fail
*
****************************************************************************/
static int esp_read_mac_wrapper(uint8_t *mac, unsigned int type)
{
return esp_read_mac(mac, type);
}
/****************************************************************************
* Name: coex_init_wrapper
*
* Description:
* Init software coexist
*
* Input Parameters:
* None
*
* Returned Value:
* Zero (OK) is returned on success. A negated errno value is returned
* on failure.
*
****************************************************************************/
static int coex_init_wrapper(void)
{
#if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE
return coex_init();
#else
return 0;
#endif
}
/****************************************************************************
* Name: coex_deinit_wrapper
*
* Description:
* De-init software coexist
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
static void coex_deinit_wrapper(void)
{
#if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE
coex_deinit();
#endif
}
/****************************************************************************
* Name: coex_enable_wrapper
*
* Description:
* Enable software coexist
*
* Input Parameters:
* None
*
* Returned Value:
* Zero (OK) is returned on success. A negated errno value is returned
* on failure.
*
****************************************************************************/
static int coex_enable_wrapper(void)
{
#if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE
return coex_enable();
#else
return 0;
#endif
}
/****************************************************************************
* Name: coex_disable_wrapper
*
* Description:
* Disable software coexist
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
static void coex_disable_wrapper(void)
{
#if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE
coex_disable();
#endif
}
/****************************************************************************
* Name: coex_status_get_wrapper
*
* Description:
* Get software coexist status.
*
* Input Parameters:
* None
*
* Returned Value:
* Zero (OK) is returned on success. A negated errno value is returned
* on failure.
*
****************************************************************************/
static IRAM_ATTR uint32_t coex_status_get_wrapper(void)
{
#if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE
return coex_status_get();
#else
return 0;
#endif
}
/****************************************************************************
* Name: coex_wifi_request_wrapper
*
* Description:
* Request Wi-Fi coexistence.
*
* Input Parameters:
* event - WiFi event
* latency - WiFi will request coexistence after latency
* duration - duration for WiFi to request coexistence
*
* Returned Value:
* Zero (OK) is returned on success. A negated errno value is returned
* on failure.
*
****************************************************************************/
static int coex_wifi_request_wrapper(uint32_t event,
uint32_t latency,
uint32_t duration)
{
#if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE
return coex_wifi_request(event, latency, duration);
#else
return 0;
#endif
}
/****************************************************************************
* Name: coex_wifi_release_wrapper
*
* Description:
* Release Wi-Fi coexistence.
*
* Input Parameters:
* event - WiFi event
*
* Returned Value:
* Zero (OK) is returned on success. A negated errno value is returned
* on failure.
*
****************************************************************************/
static IRAM_ATTR int coex_wifi_release_wrapper(uint32_t event)
{
#if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE
return coex_wifi_release(event);
#else
return 0;
#endif
}
/****************************************************************************
* Name: coex_wifi_channel_set_wrapper
*
* Description:
* Set Wi-Fi channel to coexistence module.
*
* Input Parameters:
* primary - WiFi primary channel
* secondary - WiFi secondary channel
*
* Returned Value:
* Zero (OK) is returned on success. A negated errno value is returned
* on failure.
*
****************************************************************************/
static int coex_wifi_channel_set_wrapper(uint8_t primary, uint8_t secondary)
{
#if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE
return coex_wifi_channel_set(primary, secondary);
#else
return 0;
#endif
}
/****************************************************************************
* Name: coex_event_duration_get_wrapper
*
* Description:
* Get coexistence event duration.
*
* Input Parameters:
* event - Coexistence event
* duration - Coexistence event duration
*
* Returned Value:
* Zero (OK) is returned on success. A negated errno value is returned
* on failure.
*
****************************************************************************/
static IRAM_ATTR int coex_event_duration_get_wrapper(uint32_t event,
uint32_t *duration)
{
#if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE
return coex_event_duration_get(event, duration);
#else
return 0;
#endif
}
/****************************************************************************
* Name: coex_pti_get_wrapper
*
* Description:
* Get coexistence event priority.
*
* Input Parameters:
* event - Coexistence event
* pti - Coexistence event priority
*
* Returned Value:
* Zero (OK) is returned on success. A negated errno value is returned
* on failure.
*
****************************************************************************/
static int coex_pti_get_wrapper(uint32_t event, uint8_t *pti)
{
#if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE
return coex_pti_get(event, pti);
#else
return 0;
#endif
}
/****************************************************************************
* Name: coex_schm_status_bit_clear_wrapper
*
* Description:
* Clear coexistence status.
*
* Input Parameters:
* type - Coexistence status type
* status - Coexistence status
*
* Returned Value:
* None
*
****************************************************************************/
static void coex_schm_status_bit_clear_wrapper(uint32_t type,
uint32_t status)
{
#if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE
coex_schm_status_bit_clear(type, status);
#endif
}
/****************************************************************************
* Name: coex_schm_status_bit_set_wrapper
*
* Description:
* Set coexistence status.
*
* Input Parameters:
* type - Coexistence status type
* status - Coexistence status
*
* Returned Value:
* None
*
****************************************************************************/
static void coex_schm_status_bit_set_wrapper(uint32_t type, uint32_t status)
{
#if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE
coex_schm_status_bit_set(type, status);
#endif
}
/****************************************************************************
* Name: coex_schm_interval_set_wrapper
*
* Description:
* Set coexistence scheme interval.
*
* Input Parameters:
* interval - Coexistence scheme interval
*
* Returned Value:
* Zero (OK) is returned on success. A negated errno value is returned
* on failure.
*
****************************************************************************/
static IRAM_ATTR int coex_schm_interval_set_wrapper(uint32_t interval)
{
#if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE
return coex_schm_interval_set(interval);
#else
return 0;
#endif
}
/****************************************************************************
* Name: coex_schm_interval_get_wrapper
*
* Description:
* Get coexistence scheme interval.
*
* Input Parameters:
* None
*
* Returned Value:
* Coexistence scheme interval
*
****************************************************************************/
static uint32_t coex_schm_interval_get_wrapper(void)
{
#if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE
return coex_schm_interval_get();
#else
return 0;
#endif
}
/****************************************************************************
* Name: coex_schm_curr_period_get_wrapper
*
* Description:
* Get current coexistence scheme period.
*
* Input Parameters:
* None
*
* Returned Value:
* Coexistence scheme period
*
****************************************************************************/
static uint8_t coex_schm_curr_period_get_wrapper(void)
{
#if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE
return coex_schm_curr_period_get();
#else
return 0;
#endif
}
/****************************************************************************
* Name: coex_schm_curr_phase_get_wrapper
*
* Description:
* Get current coexistence scheme phase.
*
* Input Parameters:
* None
*
* Returned Value:
* Coexistence scheme phase
*
****************************************************************************/
static void *coex_schm_curr_phase_get_wrapper(void)
{
#if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE
return coex_schm_curr_phase_get();
#else
return NULL;
#endif
}
/****************************************************************************
* Name: coex_register_start_cb_wrapper
*
* Description:
* Register Wi-Fi callback for coexistence starts.
*
* Input Parameters:
* cb - WiFi callback
*
* Returned Value:
* Zero (OK) is returned on success. A negated errno value is returned
* on failure.
*
****************************************************************************/
static int coex_register_start_cb_wrapper(int (* cb)(void))
{
#if CONFIG_SW_COEXIST_ENABLE
return coex_register_start_cb(cb);
#else
return 0;
#endif
}
/****************************************************************************
* Name: coex_schm_process_restart_wrapper
*
* Description:
* Restart current coexistence scheme.
*
* Input Parameters:
* None
*
* Returned Value:
* Zero (OK) is returned on success. A negated errno value is returned
* on failure.
*
****************************************************************************/
static int coex_schm_process_restart_wrapper(void)
{
#if CONFIG_SW_COEXIST_ENABLE
return coex_schm_process_restart();
#else
return 0;
#endif
}
/****************************************************************************
* Name: coex_schm_register_cb_wrapper
*
* Description:
* Register callback for coexistence scheme.
*
* Input Parameters:
* type - callback type
* cb - callback
*
* Returned Value:
* Zero (OK) is returned on success. A negated errno value is returned
* on failure.
*
****************************************************************************/
static int coex_schm_register_cb_wrapper(int type, int(*cb)(int))
{
#if CONFIG_SW_COEXIST_ENABLE
return coex_schm_register_callback(type, cb);
#else
return 0;
#endif
}
/****************************************************************************
* Name: esp_empty_wrapper
*
* Description:
* This function is an empty wrapper, designed to be used where a function
* pointer is required but no operation is needed.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
static void IRAM_ATTR esp_empty_wrapper(void)
{
}
/* Second block of functions
* These functions are auxiliary functions that are used by the first block
* of functions or software adapters for the Wi-Fi driver
*/
/****************************************************************************
* Name: esp_event_id_map
*
* Description:
* Transform from esp-idf event ID to Wi-Fi adapter event ID
*
* Input Parameters:
* event_id - esp-idf event ID
*
* Returned Value:
* Wi-Fi adapter event ID
*
****************************************************************************/
static int esp_event_id_map(int event_id)
{
int id;
switch (event_id)
{
case WIFI_EVENT_SCAN_DONE:
id = WIFI_ADPT_EVT_SCAN_DONE;
break;
#ifdef ESP_WLAN_HAS_STA
case WIFI_EVENT_STA_START:
id = WIFI_ADPT_EVT_STA_START;
break;
case WIFI_EVENT_STA_CONNECTED:
id = WIFI_ADPT_EVT_STA_CONNECT;
break;
case WIFI_EVENT_STA_DISCONNECTED:
id = WIFI_ADPT_EVT_STA_DISCONNECT;
break;
case WIFI_EVENT_STA_AUTHMODE_CHANGE:
id = WIFI_ADPT_EVT_STA_AUTHMODE_CHANGE;
break;
case WIFI_EVENT_STA_STOP:
id = WIFI_ADPT_EVT_STA_STOP;
break;
#endif /* ESP_WLAN_HAS_STA */
#ifdef ESP_WLAN_HAS_SOFTAP
case WIFI_EVENT_AP_START:
id = WIFI_ADPT_EVT_AP_START;
break;
case WIFI_EVENT_AP_STOP:
id = WIFI_ADPT_EVT_AP_STOP;
break;
case WIFI_EVENT_AP_STACONNECTED:
id = WIFI_ADPT_EVT_AP_STACONNECTED;
break;
case WIFI_EVENT_AP_STADISCONNECTED:
id = WIFI_ADPT_EVT_AP_STADISCONNECTED;
break;
#endif /* ESP_WLAN_HAS_SOFTAP */
default:
return -1;
}
return id;
}
/****************************************************************************
* Name: esp_evt_work_cb
*
* Description:
* Process the cached event
*
* Input Parameters:
* arg - No mean
*
* Returned Value:
* None
*
****************************************************************************/
static void esp_evt_work_cb(void *arg)
{
int ret;
irqstate_t flags;
struct evt_adpt *evt_adpt;
struct wifi_notify *notify;
wifi_ps_type_t ps_type = DEFAULT_PS_MODE;
while (1)
{
flags = spin_lock_irqsave(&g_lock);
evt_adpt = (struct evt_adpt *)sq_remfirst(&g_wifi_evt_queue);
spin_unlock_irqrestore(&g_lock, flags);
if (!evt_adpt)
{
break;
}
esp_wifi_lock(true);
switch (evt_adpt->id)
{
case WIFI_ADPT_EVT_SCAN_DONE:
esp_wifi_scan_event_parse();
break;
#ifdef ESP_WLAN_HAS_STA
case WIFI_ADPT_EVT_STA_START:
wlinfo("Wi-Fi sta start\n");
g_sta_connected = false;
ret = esp_wifi_set_ps(ps_type);
if (ret)
{
wlerr("Failed to set power save type\n");
break;
}
else
{
wlinfo("INFO: Set ps type=%d\n", ps_type);
}
ret = esp_wifi_get_config(WIFI_IF_STA, &g_sta_wifi_cfg);
if (ret)
{
wlerr("Failed to get Wi-Fi config data ret=%d\n", ret);
}
break;
case WIFI_ADPT_EVT_STA_CONNECT:
wlinfo("Wi-Fi sta connect\n");
g_sta_connected = true;
ret = esp_wlan_sta_set_linkstatus(true);
if (ret < 0)
{
wlerr("ERROR: Failed to set Wi-Fi station link status\n");
}
break;
case WIFI_ADPT_EVT_STA_DISCONNECT:
wlinfo("Wi-Fi sta disconnect\n");
g_sta_connected = false;
ret = esp_wlan_sta_set_linkstatus(false);
if (ret < 0)
{
wlerr("ERROR: Failed to set Wi-Fi station link status\n");
}
if (g_sta_reconnect)
{
ret = esp_wifi_connect();
if (ret)
{
wlerr("Failed to connect AP error=%d\n", ret);
}
}
break;
case WIFI_ADPT_EVT_STA_STOP:
wlinfo("Wi-Fi sta stop\n");
g_sta_connected = false;
break;
#endif /* ESP_WLAN_HAS_STA */
#ifdef ESP_WLAN_HAS_SOFTAP
case WIFI_ADPT_EVT_AP_START:
wlinfo("INFO: Wi-Fi softap start\n");
ret = esp_wifi_set_ps(ps_type);
if (ret)
{
wlerr("Failed to set power save type\n");
break;
}
else
{
wlinfo("INFO: Set ps type=%d\n", ps_type);
}
ret = esp_wifi_get_config(WIFI_IF_AP, &g_softap_wifi_cfg);
if (ret)
{
wlerr("Failed to get Wi-Fi config data ret=%d\n", ret);
}
break;
case WIFI_ADPT_EVT_AP_STOP:
wlinfo("INFO: Wi-Fi softap stop\n");
break;
case WIFI_ADPT_EVT_AP_STACONNECTED:
wlinfo("INFO: Wi-Fi station join\n");
break;
case WIFI_ADPT_EVT_AP_STADISCONNECTED:
wlinfo("INFO: Wi-Fi station leave\n");
break;
#endif /* ESP_WLAN_HAS_SOFTAP */
default:
break;
}
notify = &g_wifi_notify[evt_adpt->id];
if (notify->assigned)
{
notify->event.sigev_value.sival_ptr = evt_adpt->buf;
ret = nxsig_notification(notify->pid, &notify->event,
SI_QUEUE, &notify->work);
if (ret < 0)
{
wlwarn("nxsig_notification event ID=%ld failed: %d\n",
evt_adpt->id, ret);
}
}
esp_wifi_lock(false);
kmm_free(evt_adpt);
}
}
/****************************************************************************
* Name: esp_freq_to_channel
*
* Description:
* Converts Wi-Fi frequency to channel.
*
* Input Parameters:
* freq - Wi-Fi frequency
*
* Returned Value:
* Wi-Fi channel
*
****************************************************************************/
static int esp_freq_to_channel(uint16_t freq)
{
int channel = 0;
if (freq >= 2412 && freq <= 2484)
{
if (freq == 2484)
{
channel = 14;
}
else
{
channel = freq - 2407;
if (channel % 5)
{
return 0;
}
channel /= 5;
}
return channel;
}
if (freq >= 5005 && freq < 5900)
{
if (freq % 5)
{
return 0;
}
channel = (freq - 5000) / 5;
return channel;
}
if (freq >= 4905 && freq < 5000)
{
if (freq % 5)
{
return 0;
}
channel = (freq - 4000) / 5;
return channel;
}
return 0;
}
/****************************************************************************
* Name: esp_get_free_heap_size
*
* Description:
* Get free heap size by byte
*
* Input Parameters:
* None
*
* Returned Value:
* Free heap size
*
****************************************************************************/
static uint32_t esp_get_free_heap_size(void)
{
struct mallinfo info;
info = kmm_mallinfo();
return info.fordblks;
}
/****************************************************************************
* Name: event_group_create_wrapper
*
* Description:
* Don't support
*
****************************************************************************/
static void *event_group_create_wrapper(void)
{
DEBUGPANIC();
return NULL;
}
/****************************************************************************
* Name: event_group_delete_wrapper
*
* Description:
* Don't support
*
****************************************************************************/
static void event_group_delete_wrapper(void *event)
{
DEBUGPANIC();
}
/****************************************************************************
* Name: event_group_set_bits_wrapper
*
* Description:
* Don't support
*
****************************************************************************/
static uint32_t event_group_set_bits_wrapper(void *event, uint32_t bits)
{
DEBUGPANIC();
return false;
}
/****************************************************************************
* Name: event_group_clear_bits_wrapper
*
* Description:
* Don't support
*
****************************************************************************/
static uint32_t event_group_clear_bits_wrapper(void *event, uint32_t bits)
{
DEBUGPANIC();
return false;
}
/****************************************************************************
* Name: esp_int_adpt_cb
*
* Description:
* This is the callback function for the Wi-Fi interrupt adapter. It
* retrieves the adapter from the argument, then calls the function
* stored in the adapter with its argument.
*
* Input Parameters:
* irq - The IRQ number that caused this interrupt.
* context - The register context at the time of the interrupt.
* arg - A pointer to the interrupt adapter's private data.
*
* Returned Value:
* Always returns 0.
*
****************************************************************************/
static int esp_int_adpt_cb(int irq, void *context, void *arg)
{
struct irq_adpt *adapter = (struct irq_adpt *)arg;
adapter->func(adapter->arg);
return 0;
}
/****************************************************************************
* Name: esp_nvs_commit
*
* Description:
* This function has no practical effect
*
****************************************************************************/
static int esp_nvs_commit(uint32_t handle)
{
return 0;
}
/****************************************************************************
* Name: esp_nvs_erase_key
*
* Description:
* Read a block of data from file system
*
* Input Parameters:
* handle - NVS handle
* key - Data index
*
* Returned Value:
* 0 if success or -1 if fail
*
****************************************************************************/
static int esp_nvs_erase_key(uint32_t handle, const char *key)
{
DEBUGPANIC();
return -1;
}
/****************************************************************************
* Name: esp_nvs_get_blob
*
* Description:
* Read a block of data from file system
*
* Input Parameters:
* handle - NVS handle
* key - Data index
* out_value - Read buffer pointer
* length - Buffer length
*
* Returned Value:
* 0 if success or -1 if fail
*
****************************************************************************/
static int esp_nvs_get_blob(uint32_t handle,
const char *key,
void *out_value,
size_t *length)
{
DEBUGPANIC();
return -1;
}
/****************************************************************************
* Name: esp_nvs_set_blob
*
* Description:
* Save a block of data into file system
*
* Input Parameters:
* handle - NVS handle
* key - Data index
* value - Stored buffer pointer
* length - Buffer length
*
* Returned Value:
* 0 if success or -1 if fail
*
****************************************************************************/
static int esp_nvs_set_blob(uint32_t handle,
const char *key,
const void *value,
size_t length)
{
DEBUGPANIC();
return -1;
}
/****************************************************************************
* Name: esp_nvs_get_i8
*
* Description:
* Read data of type int8_t from file system
*
* Input Parameters:
* handle - NVS handle
* key - Data index
* out_value - Read buffer pointer
*
* Returned Value:
* 0 if success or -1 if fail
*
****************************************************************************/
static int esp_nvs_get_i8(uint32_t handle,
const char *key,
int8_t *out_value)
{
DEBUGPANIC();
return -1;
}
/****************************************************************************
* Name: esp_nvs_set_i8
*
* Description:
* Save data of type int8_t into file system
*
* Input Parameters:
* handle - NVS handle
* key - Data index
* value - Stored data
*
* Returned Value:
* 0 if success or -1 if fail
*
****************************************************************************/
static int esp_nvs_set_i8(uint32_t handle,
const char *key,
int8_t value)
{
DEBUGPANIC();
return -1;
}
/****************************************************************************
* Name: esp_nvs_get_u8
*
* Description:
* Read data of type uint8_t from file system
*
* Input Parameters:
* handle - NVS handle
* key - Data index
* out_value - Read buffer pointer
*
* Returned Value:
* 0 if success or -1 if fail
*
****************************************************************************/
static int esp_nvs_get_u8(uint32_t handle,
const char *key,
uint8_t *out_value)
{
DEBUGPANIC();
return -1;
}
/****************************************************************************
* Name: esp_nvs_set_u8
*
* Description:
* Save data of type uint8_t into file system
*
* Input Parameters:
* handle - NVS handle
* key - Data index
* value - Stored data
*
* Returned Value:
* 0 if success or -1 if fail
*
****************************************************************************/
static int esp_nvs_set_u8(uint32_t handle,
const char *key,
uint8_t value)
{
DEBUGPANIC();
return -1;
}
/****************************************************************************
* Name: esp_nvs_get_u16
*
* Description:
* Read data of type uint16_t from file system
*
* Input Parameters:
* handle - NVS handle
* key - Data index
* out_value - Read buffer pointer
*
* Returned Value:
* 0 if success or -1 if fail
*
****************************************************************************/
static int esp_nvs_get_u16(uint32_t handle,
const char *key,
uint16_t *out_value)
{
DEBUGPANIC();
return -1;
}
/****************************************************************************
* Name: esp_nvs_set_u16
*
* Description:
* Save data of type uint16_t into file system
*
* Input Parameters:
* handle - NVS handle
* key - Data index
* value - Stored data
*
* Returned Value:
* 0 if success or -1 if fail
*
****************************************************************************/
static int esp_nvs_set_u16(uint32_t handle,
const char *key,
uint16_t value)
{
DEBUGPANIC();
return -1;
}
/****************************************************************************
* Name: esp_nvs_close
*
* Description:
* Close storage data object and free resource
*
* Input Parameters:
* handle - NVS handle
*
* Returned Value:
* 0 if success or -1 if fail
*
****************************************************************************/
static void esp_nvs_close(uint32_t handle)
{
DEBUGPANIC();
}
/****************************************************************************
* Name: esp_update_time
*
* Description:
* Transform ticks to time and add this time to timespec value
*
* Input Parameters:
* timespec - Input timespec data pointer
* ticks - System ticks
*
* Returned Value:
* None
*
****************************************************************************/
static void esp_update_time(struct timespec *timespec, uint32_t ticks)
{
uint32_t tmp;
tmp = TICK2SEC(ticks);
timespec->tv_sec += tmp;
ticks -= SEC2TICK(tmp);
tmp = TICK2NSEC(ticks);
timespec->tv_nsec += tmp;
}
#ifdef ESP_WLAN_HAS_STA
/****************************************************************************
* Name: esp_wifi_auth_trans
*
* Description:
* Converts a ESP32-C6 authenticate mode values to WEXT authenticate mode.
*
* Input Parameters:
* wifi_auth - ESP32-C6 authenticate mode
*
* Returned Value:
* authenticate mode
*
****************************************************************************/
static int esp_wifi_auth_trans(uint32_t wifi_auth)
{
int auth_mode = IW_AUTH_WPA_VERSION_DISABLED;
switch (wifi_auth)
{
case WIFI_AUTH_OPEN:
auth_mode = IW_AUTH_WPA_VERSION_DISABLED;
break;
case WIFI_AUTH_WPA_PSK:
auth_mode = IW_AUTH_WPA_VERSION_WPA;
break;
case WIFI_AUTH_WPA2_PSK:
case WIFI_AUTH_WPA_WPA2_PSK:
auth_mode = IW_AUTH_WPA_VERSION_WPA2;
break;
case WIFI_AUTH_WPA3_PSK:
case WIFI_AUTH_WPA2_WPA3_PSK:
auth_mode = IW_AUTH_WPA_VERSION_WPA3;
break;
default:
wlerr("Failed to transfer wireless authmode: %ld", wifi_auth);
break;
}
return auth_mode;
}
/****************************************************************************
* Name: esp_wifi_cipher_trans
*
* Description:
* Converts a ESP32-C6 cipher type values to WEXT cipher type values.
*
* Input Parameters:
* wifi_cipher - ESP32-C6 cipher type
*
* Returned Value:
* cipher type
*
****************************************************************************/
static int esp_wifi_cipher_trans(uint32_t wifi_cipher)
{
int cipher_mode = IW_AUTH_CIPHER_NONE;
switch (wifi_cipher)
{
case WIFI_CIPHER_TYPE_NONE:
cipher_mode = IW_AUTH_CIPHER_NONE;
break;
case WIFI_CIPHER_TYPE_WEP40:
cipher_mode = IW_AUTH_CIPHER_WEP40;
break;
case WIFI_CIPHER_TYPE_WEP104:
cipher_mode = IW_AUTH_CIPHER_WEP104;
break;
case WIFI_CIPHER_TYPE_TKIP:
cipher_mode = IW_AUTH_CIPHER_TKIP;
break;
case WIFI_CIPHER_TYPE_CCMP:
case WIFI_CIPHER_TYPE_TKIP_CCMP:
cipher_mode = IW_AUTH_CIPHER_CCMP;
break;
case WIFI_CIPHER_TYPE_AES_CMAC128:
cipher_mode = IW_AUTH_CIPHER_AES_CMAC;
break;
default:
wlerr("Failed to transfer wireless authmode: %ld",
wifi_cipher);
break;
}
return cipher_mode;
}
#endif /* ESP_WLAN_HAS_STA */
/****************************************************************************
* Name: esp_wifi_lock
*
* Description:
* Lock or unlock the event process
*
* Input Parameters:
* lock - true: Lock event process, false: unlock event process
*
* Returned Value:
* The result of lock or unlock the event process
*
****************************************************************************/
static int esp_wifi_lock(bool lock)
{
int ret;
if (lock)
{
ret = nxmutex_lock(&g_wifiexcl_lock);
if (ret < 0)
{
wlinfo("Failed to lock Wi-Fi ret=%d\n", ret);
}
}
else
{
ret = nxmutex_unlock(&g_wifiexcl_lock);
if (ret < 0)
{
wlinfo("Failed to unlock Wi-Fi ret=%d\n", ret);
}
}
return ret;
}
/****************************************************************************
* Name: queue_msg_waiting_wrapper
*
* Description:
* Get message number in the message queue
*
* Input Parameters:
* queue - Message queue data pointer
*
* Returned Value:
* Message number
*
****************************************************************************/
static uint32_t queue_msg_waiting_wrapper(void *queue)
{
int ret;
struct mq_attr attr;
struct mq_adpt *mq_adpt = (struct mq_adpt *)queue;
ret = file_mq_getattr(&mq_adpt->mq, &attr);
if (ret < 0)
{
wlerr("Failed to get attr from mqueue error=%d\n", ret);
return 0;
}
return attr.mq_curmsgs;
}
/****************************************************************************
* Name: task_delay_wrapper
*
* Description:
* Current task wait for some ticks
*
* Input Parameters:
* tick - Waiting ticks
*
* Returned Value:
* None
*
****************************************************************************/
static void task_delay_wrapper(uint32_t tick)
{
useconds_t us = TICK2USEC(tick);
nxsig_usleep(us);
}
/****************************************************************************
* Name: task_delete_wrapper
*
* Description:
* Delete the target task
*
* Input Parameters:
* task_handle - Task handle pointer which is used to pause, resume
* and delete the task
*
* Returned Value:
* None
*
****************************************************************************/
static void task_delete_wrapper(void *task_handle)
{
pid_t pid = (pid_t)((uintptr_t)task_handle);
kthread_delete(pid);
}
/****************************************************************************
* Name: task_get_current_task_wrapper
*
* Description:
* This function gets the current task's PID and returns it as a void
* pointer. This is a wrapper around the NuttX function nxsched_gettid.
*
* Input Parameters:
* None
*
* Returned Value:
* The current task's PID as a void pointer.
*
****************************************************************************/
static void *task_get_current_task_wrapper(void)
{
pid_t pid = nxsched_gettid();
return (void *)((uintptr_t)pid);
}
/****************************************************************************
* Name: vqueue_delete_adapter
*
* Description:
* This function deletes a queue adapter. It closes the message queue,
* unlinks it, and then frees the memory allocated for the queue adapter.
*
* Input Parameters:
* queue - A pointer to the queue adapter to be deleted.
*
* Returned Value:
* None
*
****************************************************************************/
static void vqueue_delete_adapter(void *queue)
{
struct mq_adpt *mq_adpt = (struct mq_adpt *)queue;
file_mq_close(&mq_adpt->mq);
file_mq_unlink(mq_adpt->name);
kmm_free(mq_adpt);
}
/****************************************************************************
* Name: vsemaphore_delete_adapter
*
* Description:
* Delete semaphore
*
* Input Parameters:
* semphr - Semaphore data pointer
*
* Returned Value:
* None
*
****************************************************************************/
static void vsemaphore_delete_adapter(void *semphr)
{
sem_t *sem = (sem_t *)semphr;
nxsem_destroy(sem);
kmm_free(sem);
}
/****************************************************************************
* Name: xqueue_create_adapter
*
* Description:
* Create message queue
*
* Input Parameters:
* queue_len - queue message number
* item_size - message size
*
* Returned Value:
* Message queue data pointer
*
****************************************************************************/
static void *xqueue_create_adapter(uint32_t queue_len, uint32_t item_size)
{
struct mq_attr attr;
struct mq_adpt *mq_adpt;
int ret;
mq_adpt = kmm_malloc(sizeof(struct mq_adpt));
if (!mq_adpt)
{
wlerr("Failed to kmm_malloc\n");
return NULL;
}
snprintf(mq_adpt->name, sizeof(mq_adpt->name),
"/tmp/%p", mq_adpt);
attr.mq_maxmsg = queue_len;
attr.mq_msgsize = item_size;
attr.mq_curmsgs = 0;
attr.mq_flags = 0;
ret = file_mq_open(&mq_adpt->mq, mq_adpt->name,
O_RDWR | O_CREAT, 0644, &attr);
if (ret < 0)
{
wlerr("Failed to create mqueue\n");
kmm_free(mq_adpt);
return NULL;
}
mq_adpt->msgsize = item_size;
return (void *)mq_adpt;
}
/****************************************************************************
* Name: xqueue_send_adapter
*
* Description:
* Generic send message to queue within a certain period of time
*
* Input Parameters:
* queue - Message queue data pointer
* item - Message data pointer
* ticks - Wait ticks
* prio - Message priority
*
* Returned Value:
* True if success or false if fail
*
****************************************************************************/
static int32_t xqueue_send_adapter(void *queue,
void *item,
uint32_t ticks,
int prio)
{
int ret;
struct timespec timeout;
struct mq_adpt *mq_adpt = (struct mq_adpt *)queue;
if (ticks == OSI_FUNCS_TIME_BLOCKING || ticks == 0)
{
/* Wi-Fi interrupt function will call this adapter function to send
* message to message queue, so here we should call kernel API
* instead of application API
*/
ret = file_mq_send(&mq_adpt->mq, (const char *)item,
mq_adpt->msgsize, prio);
if (ret < 0)
{
wlerr("Failed to send message to mqueue error=%d\n",
ret);
}
}
else
{
ret = clock_gettime(CLOCK_REALTIME, &timeout);
if (ret < 0)
{
wlerr("Failed to get time\n");
return false;
}
if (ticks)
{
esp_update_time(&timeout, ticks);
}
ret = file_mq_timedsend(&mq_adpt->mq, (const char *)item,
mq_adpt->msgsize, prio, &timeout);
if (ret < 0)
{
wlerr("Failed to timedsend message to mqueue error=%d\n",
ret);
}
}
return nuttx_err_to_freertos(ret);
}
/****************************************************************************
* Name: xsemaphore_create_counting_adapter
*
* Description:
* Create and initialize semaphore
*
* Input Parameters:
* max - No meanining for NuttX
* init - semaphore initialization value
*
* Returned Value:
* Semaphore data pointer
*
****************************************************************************/
void *xsemaphore_create_counting_adapter(uint32_t max, uint32_t init)
{
int ret;
sem_t *sem;
int tmp;
tmp = sizeof(sem_t);
sem = kmm_malloc(tmp);
if (!sem)
{
wlerr("Failed to alloc %d memory\n", tmp);
return NULL;
}
ret = nxsem_init(sem, 0, init);
if (ret)
{
wlerr("Failed to initialize sem error=%d\n", ret);
kmm_free(sem);
return NULL;
}
return sem;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: wifi_malloc
*
* Description:
* Applications allocate a block of memory
*
* Input Parameters:
* size - memory size
*
* Returned Value:
* Memory pointer
*
****************************************************************************/
IRAM_ATTR void *wifi_malloc(size_t size)
{
return malloc(size);
}
/****************************************************************************
* Name: wifi_realloc
*
* Description:
* Applications allocate a block of memory by old memory block
*
* Input Parameters:
* ptr - old memory pointer
* size - memory size
*
* Returned Value:
* New memory pointer
*
****************************************************************************/
IRAM_ATTR void *wifi_realloc(void *ptr, size_t size)
{
return realloc(ptr, size);
}
/****************************************************************************
* Name: wifi_calloc
*
* Description:
* Applications allocate some continuous blocks of memory
*
* Input Parameters:
* n - memory block number
* size - memory block size
*
* Returned Value:
* New memory pointer
*
****************************************************************************/
IRAM_ATTR void *wifi_calloc(size_t n, size_t size)
{
return calloc(n, size);
}
/****************************************************************************
* Name: esp_wifi_notify_subscribe
*
* Description:
* Enable event notification
*
* Input Parameters:
* pid - Task PID
* event - Signal event data pointer
*
* Returned Value:
* 0 if success or -1 if fail
*
****************************************************************************/
int esp_wifi_notify_subscribe(pid_t pid, struct sigevent *event)
{
int id;
struct wifi_notify *notify;
int ret = -1;
wlinfo("PID=%d event=%p\n", pid, event);
esp_wifi_lock(true);
if (event->sigev_notify == SIGEV_SIGNAL)
{
id = esp_event_id_map(event->sigev_signo);
if (id < 0)
{
wlerr("No process event %d\n", event->sigev_signo);
}
else
{
notify = &g_wifi_notify[id];
if (notify->assigned)
{
wlerr("sigev_signo %d has subscribed\n",
event->sigev_signo);
}
else
{
if (pid == 0)
{
pid = nxsched_gettid();
wlinfo("Actual PID=%d\n", pid);
}
notify->pid = pid;
notify->event = *event;
notify->assigned = true;
ret = 0;
}
}
}
else if (event->sigev_notify == SIGEV_NONE)
{
id = esp_event_id_map(event->sigev_signo);
if (id < 0)
{
wlerr("No process event %d\n", event->sigev_signo);
}
else
{
notify = &g_wifi_notify[id];
if (!notify->assigned)
{
wlerr("sigev_signo %d has not subscribed\n",
event->sigev_signo);
}
else
{
notify->assigned = false;
ret = 0;
}
}
}
else
{
wlerr("sigev_notify %d is invalid\n", event->sigev_signo);
}
esp_wifi_lock(false);
return ret;
}
/****************************************************************************
* Name: esp_wifi_adapter_init
*
* Description:
* Initialize ESP32-C6 Wi-Fi adapter
*
* Input Parameters:
* None
*
* Returned Value:
* 0 if success or -1 if fail
*
****************************************************************************/
int esp_wifi_adapter_init(void)
{
int ret;
wifi_init_config_t wifi_cfg = WIFI_INIT_CONFIG_DEFAULT();
esp_wifi_lock(true);
if (g_wifi_ref)
{
wlinfo("Wi-Fi adapter is already initialized\n");
g_wifi_ref++;
esp_wifi_lock(false);
return OK;
}
sq_init(&g_wifi_evt_queue);
wifi_cfg.nvs_enable = 0;
#ifdef CONFIG_ESPRESSIF_WIFI_AMPDU_TX_ENABLED
wifi_cfg.ampdu_tx_enable = 1;
#else
wifi_cfg.ampdu_tx_enable = 0;
#endif
#ifdef CONFIG_ESPRESSIF_WIFI_AMPDU_RX_ENABLED
wifi_cfg.ampdu_rx_enable = 1;
#else
wifi_cfg.ampdu_rx_enable = 0;
#endif
#ifdef CONFIG_ESPRESSIF_WIFI_STA_DISCONNECT_PM
wifi_cfg.sta_disconnected_pm = true;
#else
wifi_cfg.sta_disconnected_pm = false;
#endif
wifi_cfg.rx_ba_win = CONFIG_ESPRESSIF_WIFI_TX_BA_WIN;
wifi_cfg.static_rx_buf_num = CONFIG_ESPRESSIF_WIFI_STATIC_RX_BUFFER_NUM;
wifi_cfg.dynamic_rx_buf_num = CONFIG_ESPRESSIF_WIFI_DYNAMIC_RX_BUFFER_NUM;
wifi_cfg.dynamic_tx_buf_num = CONFIG_ESPRESSIF_WIFI_DYNAMIC_TX_BUFFER_NUM;
ret = esp_wifi_init(&wifi_cfg);
if (ret)
{
wlerr("Failed to initialize Wi-Fi error=%d\n", ret);
ret = esp_wifi_to_errno(ret);
goto errout_init_wifi;
}
ret = esp_wifi_set_tx_done_cb(esp_wifi_tx_done_cb);
if (ret)
{
wlerr("Failed to register TX done callback ret=%d\n", ret);
ret = esp_wifi_to_errno(ret);
goto errout_init_txdone;
}
g_wifi_ref++;
wlinfo("OK to initialize Wi-Fi adapter\n");
esp_wifi_lock(false);
return OK;
errout_init_txdone:
esp_wifi_deinit();
errout_init_wifi:
esp_wifi_lock(false);
return ret;
}
/****************************************************************************
* Station functions
****************************************************************************/
#ifdef ESP_WLAN_HAS_STA
/****************************************************************************
* Name: esp_wifi_sta_start
*
* Description:
* Start Wi-Fi station.
*
* Input Parameters:
* None
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_sta_start(void)
{
int ret;
wifi_mode_t mode;
esp_wifi_lock(true);
ret = esp_wifi_stop();
if (ret)
{
wlinfo("Failed to stop Wi-Fi ret=%d\n", ret);
}
#ifdef ESP_WLAN_HAS_SOFTAP
if (g_softap_started)
{
mode = WIFI_MODE_APSTA;
}
else
#endif /* ESP_WLAN_HAS_SOFTAP */
{
mode = WIFI_MODE_STA;
}
ret = esp_wifi_set_mode(mode);
if (ret)
{
wlerr("Failed to set Wi-Fi mode=%d ret=%d\n", mode, ret);
ret = esp_wifi_to_errno(ret);
goto errout;
}
ret = esp_wifi_start();
if (ret)
{
wlerr("Failed to start Wi-Fi with mode=%d ret=%d\n", mode, ret);
ret = esp_wifi_to_errno(ret);
goto errout;
}
g_sta_started = true;
wlinfo("OK to start Wi-Fi station\n");
errout:
esp_wifi_lock(false);
return ret;
}
/****************************************************************************
* Name: esp_wifi_sta_stop
*
* Description:
* Stop Wi-Fi station.
*
* Input Parameters:
* None
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_sta_stop(void)
{
int ret;
esp_wifi_lock(true);
ret = esp_wifi_stop();
if (ret)
{
wlinfo("Failed to stop Wi-Fi ret=%d\n", ret);
}
g_sta_started = false;
#ifdef ESP_WLAN_HAS_SOFTAP
if (g_softap_started)
{
ret = esp_wifi_set_mode(WIFI_MODE_AP);
if (ret)
{
wlerr("Failed to set Wi-Fi AP mode ret=%d\n", ret);
ret = esp_wifi_to_errno(ret);
goto errout;
}
ret = esp_wifi_start();
if (ret)
{
wlerr("Failed to start Wi-Fi AP ret=%d\n", ret);
ret = esp_wifi_to_errno(ret);
goto errout;
}
}
#endif /* ESP_WLAN_HAS_SOFTAP */
wlinfo("OK to stop Wi-Fi station\n");
#ifdef ESP_WLAN_HAS_SOFTAP
errout:
#endif /* ESP_WLAN_HAS_SOFTAP */
esp_wifi_lock(false);
return ret;
}
/****************************************************************************
* Name: esp_wifi_sta_send_data
*
* Description:
* Use Wi-Fi station interface to send 802.3 frame
*
* Input Parameters:
* pbuf - Packet buffer pointer
* len - Packet length
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_sta_send_data(void *pbuf, size_t len)
{
int ret;
ret = esp_wifi_internal_tx(WIFI_IF_STA, pbuf, len);
return esp_wifi_to_errno(ret);
}
/****************************************************************************
* Name: esp_wifi_set_password
*
* Description:
* Set/Get Wi-Fi station password
*
* Input Parameters:
* iwr - The argument of the ioctl cmd
* set - true: set data; false: get data
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_sta_password(struct iwreq *iwr, bool set)
{
int ret;
int size;
wifi_config_t wifi_cfg;
struct iw_encode_ext *ext = iwr->u.encoding.pointer;
uint8_t *pdata;
uint8_t len;
#ifdef CONFIG_DEBUG_WIRELESS_INFO
char buf[PWD_MAX_LEN + 1];
#endif
DEBUGASSERT(ext != NULL);
pdata = ext->key;
wifi_cfg = g_sta_wifi_cfg;
if (set)
{
len = ext->key_len;
if (len > PWD_MAX_LEN)
{
return -EINVAL;
}
memset(wifi_cfg.sta.password, 0x0, PWD_MAX_LEN);
if (ext->alg != IW_ENCODE_ALG_NONE)
{
memcpy(wifi_cfg.sta.password, pdata, len);
}
wifi_cfg.sta.pmf_cfg.capable = true;
if (g_sta_connected)
{
ret = esp_wifi_sta_disconnect();
if (ret)
{
wlerr("Failed to disconnect from Wi-Fi AP ret=%d\n", ret);
return ret;
}
ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg);
if (ret)
{
wlerr("Failed to set Wi-Fi config data ret=%d\n", ret);
return esp_wifi_to_errno(ret);
}
ret = esp_wifi_sta_connect();
if (ret)
{
wlerr("Failed to connect to Wi-Fi AP ret=%d\n", ret);
return ret;
}
}
g_sta_wifi_cfg = wifi_cfg;
}
else
{
len = iwr->u.encoding.length - sizeof(*ext);
size = strnlen((char *)wifi_cfg.sta.password, PWD_MAX_LEN);
if (len < size)
{
return -EINVAL;
}
else
{
ext->key_len = size;
memcpy(pdata, wifi_cfg.sta.password, ext->key_len);
}
if (g_sta_connected)
{
wifi_ap_record_t ap_info;
ret = esp_wifi_sta_get_ap_info(&ap_info);
if (ret)
{
wlerr("Failed to get AP record ret=%d", ret);
return esp_wifi_to_errno(ret);
}
switch (ap_info.pairwise_cipher)
{
case WIFI_CIPHER_TYPE_NONE:
ext->alg = IW_ENCODE_ALG_NONE;
break;
case WIFI_CIPHER_TYPE_WEP40:
case WIFI_CIPHER_TYPE_WEP104:
ext->alg = IW_ENCODE_ALG_WEP;
break;
case WIFI_CIPHER_TYPE_TKIP:
ext->alg = IW_ENCODE_ALG_TKIP;
break;
case WIFI_CIPHER_TYPE_CCMP:
case WIFI_CIPHER_TYPE_TKIP_CCMP:
ext->alg = IW_ENCODE_ALG_CCMP;
break;
case WIFI_CIPHER_TYPE_AES_CMAC128:
ext->alg = IW_ENCODE_ALG_AES_CMAC;
break;
default:
wlerr("Failed to transfer wireless authmode: %d",
ap_info.pairwise_cipher);
return -EIO;
}
}
}
#ifdef CONFIG_DEBUG_WIRELESS_INFO
memcpy(buf, pdata, len);
buf[len] = 0;
wlinfo("Wi-Fi station password=%s len=%d\n", buf, len);
#endif
return OK;
}
/****************************************************************************
* Name: esp_wifi_sta_essid
*
* Description:
* Set/Get Wi-Fi station ESSID
*
* Input Parameters:
* iwr - The argument of the ioctl cmd
* set - true: set data; false: get data
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_sta_essid(struct iwreq *iwr, bool set)
{
int ret;
int size;
wifi_config_t wifi_cfg;
struct iw_point *essid = &iwr->u.essid;
uint8_t *pdata;
uint8_t len;
#ifdef CONFIG_DEBUG_WIRELESS_INFO
char buf[SSID_MAX_LEN + 1];
#endif
DEBUGASSERT(essid != NULL);
pdata = essid->pointer;
len = essid->length;
if (set && len > SSID_MAX_LEN)
{
return -EINVAL;
}
wifi_cfg = g_sta_wifi_cfg;
if (set)
{
memset(wifi_cfg.sta.ssid, 0x0, SSID_MAX_LEN);
memcpy(wifi_cfg.sta.ssid, pdata, len);
memset(wifi_cfg.sta.sae_h2e_identifier, 0x0, SAE_H2E_IDENTIFIER_LEN);
wifi_cfg.sta.sae_pwe_h2e = WPA3_SAE_PWE_BOTH;
if (g_sta_connected)
{
ret = esp_wifi_sta_disconnect();
if (ret)
{
wlerr("Failed to disconnect from Wi-Fi AP ret=%d\n", ret);
return ret;
}
ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg);
if (ret)
{
wlerr("Failed to set Wi-Fi config data ret=%d\n", ret);
return esp_wifi_to_errno(ret);
}
ret = esp_wifi_sta_connect();
if (ret)
{
wlerr("Failed to connect to Wi-Fi AP ret=%d\n", ret);
return ret;
}
}
g_sta_wifi_cfg = wifi_cfg;
}
else
{
size = strnlen((char *)wifi_cfg.sta.ssid, SSID_MAX_LEN);
if (len < size)
{
return -EINVAL;
}
else
{
len = size;
memcpy(pdata, wifi_cfg.sta.ssid, len);
}
if (g_sta_connected)
{
essid->flags = IW_ESSID_ON;
}
else
{
essid->flags = IW_ESSID_OFF;
}
}
#ifdef CONFIG_DEBUG_WIRELESS_INFO
memcpy(buf, pdata, len);
buf[len] = 0;
wlinfo("Wi-Fi station ssid=%s len=%d\n", buf, len);
#endif
return OK;
}
/****************************************************************************
* Name: esp_wifi_sta_bssid
*
* Description:
* Set/Get Wi-Fi station BSSID
*
* Input Parameters:
* iwr - The argument of the ioctl cmd
* set - true: set data; false: get data
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_sta_bssid(struct iwreq *iwr, bool set)
{
int ret;
wifi_config_t wifi_cfg;
struct sockaddr *sockaddr;
char *pdata;
sockaddr = &iwr->u.ap_addr;
pdata = sockaddr->sa_data;
wifi_cfg = g_sta_wifi_cfg;
if (set)
{
wifi_cfg.sta.bssid_set = true;
memcpy(wifi_cfg.sta.bssid, pdata, MAC_LEN);
if (g_sta_connected)
{
ret = esp_wifi_sta_disconnect();
if (ret)
{
wlerr("Failed to disconnect from Wi-Fi AP ret=%d\n", ret);
return ret;
}
ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg);
if (ret)
{
wlerr("Failed to set Wi-Fi config data ret=%d\n", ret);
return esp_wifi_to_errno(ret);
}
ret = esp_wifi_sta_connect();
if (ret)
{
wlerr("Failed to connect to Wi-Fi AP ret=%d\n", ret);
return ret;
}
}
g_sta_wifi_cfg = wifi_cfg;
}
else
{
memcpy(pdata, wifi_cfg.sta.bssid, MAC_LEN);
}
return OK;
}
/****************************************************************************
* Name: esp_wifi_sta_connect
*
* Description:
* Trigger Wi-Fi station connection action
*
* Input Parameters:
* None
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_sta_connect(void)
{
int ret;
uint32_t ticks;
esp_wifi_lock(true);
if (g_sta_connected)
{
wlinfo("Wi-Fi has connected AP\n");
esp_wifi_lock(false);
return OK;
}
g_sta_reconnect = true;
ret = esp_wifi_set_config(WIFI_IF_STA, &g_sta_wifi_cfg);
if (ret)
{
wlerr("Failed to set Wi-Fi config data ret=%d\n", ret);
return esp_wifi_to_errno(ret);
}
ret = esp_wifi_connect();
if (ret)
{
wlerr("Failed to connect ret=%d\n", ret);
ret = esp_wifi_to_errno(ret);
goto errout;
}
esp_wifi_lock(false);
ticks = SEC2TICK(WIFI_CONNECT_TIMEOUT);
do
{
if (g_sta_connected)
{
break;
}
task_delay_wrapper(1);
}
while (ticks--);
if (!g_sta_connected)
{
g_sta_reconnect = false;
wlinfo("Failed to connect to AP\n");
return -1;
}
return OK;
errout:
g_sta_reconnect = false;
esp_wifi_lock(false);
return ret;
}
/****************************************************************************
* Name: esp_wifi_sta_disconnect
*
* Description:
* Trigger Wi-Fi station disconnection action
*
* Input Parameters:
* None
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_sta_disconnect(void)
{
int ret;
esp_wifi_lock(true);
g_sta_reconnect = false;
ret = esp_wifi_disconnect();
if (ret)
{
wlerr("Failed to disconnect ret=%d\n", ret);
ret = esp_wifi_to_errno(ret);
}
else
{
wlinfo("OK to disconnect Wi-Fi station\n");
}
esp_wifi_lock(false);
return ret;
}
/****************************************************************************
* Name: esp_wifi_sta_mode
*
* Description:
* Set/Get Wi-Fi Station mode code.
*
* Input Parameters:
* iwr - The argument of the ioctl cmd
* set - true: set data; false: get data
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_sta_mode(struct iwreq *iwr, bool set)
{
if (set == false)
{
iwr->u.mode = IW_MODE_INFRA;
}
return OK;
}
/****************************************************************************
* Name: esp_wifi_sta_auth
*
* Description:
* Set/Get station authentication mode params.
*
* Input Parameters:
* iwr - The argument of the ioctl cmd
* set - true: set data; false: get data
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_sta_auth(struct iwreq *iwr, bool set)
{
int ret;
int cmd;
wifi_config_t wifi_cfg;
wifi_ap_record_t ap_info;
wifi_cfg = g_sta_wifi_cfg;
if (set)
{
cmd = iwr->u.param.flags & IW_AUTH_INDEX;
switch (cmd)
{
case IW_AUTH_WPA_VERSION:
{
switch (iwr->u.param.value)
{
case IW_AUTH_WPA_VERSION_DISABLED:
wifi_cfg.sta.threshold.authmode = WIFI_AUTH_OPEN;
break;
case IW_AUTH_WPA_VERSION_WPA:
wifi_cfg.sta.threshold.authmode = WIFI_AUTH_WPA_PSK;
break;
case IW_AUTH_WPA_VERSION_WPA2:
wifi_cfg.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK;
break;
case IW_AUTH_WPA_VERSION_WPA3:
wifi_cfg.sta.threshold.authmode = WIFI_AUTH_WPA3_PSK;
break;
default:
wlerr("Invalid wpa version %" PRId32 "\n",
iwr->u.param.value);
return -EINVAL;
}
}
break;
case IW_AUTH_CIPHER_PAIRWISE:
case IW_AUTH_CIPHER_GROUP:
{
switch (iwr->u.param.value)
{
case IW_AUTH_CIPHER_NONE:
wifi_cfg.sta.threshold.authmode = WIFI_AUTH_OPEN;
break;
case IW_AUTH_CIPHER_WEP40:
case IW_AUTH_CIPHER_WEP104:
wifi_cfg.sta.threshold.authmode = WIFI_AUTH_WEP;
break;
case IW_AUTH_CIPHER_TKIP:
case IW_AUTH_CIPHER_CCMP:
case IW_AUTH_CIPHER_AES_CMAC:
break;
default:
wlerr("Invalid cipher mode %" PRId32 "\n",
iwr->u.param.value);
return -EINVAL;
}
}
break;
case IW_AUTH_KEY_MGMT:
case IW_AUTH_TKIP_COUNTERMEASURES:
case IW_AUTH_DROP_UNENCRYPTED:
case IW_AUTH_80211_AUTH_ALG:
case IW_AUTH_WPA_ENABLED:
case IW_AUTH_RX_UNENCRYPTED_EAPOL:
case IW_AUTH_ROAMING_CONTROL:
case IW_AUTH_PRIVACY_INVOKED:
default:
wlerr("Unknown cmd %d\n", cmd);
return -EINVAL;
}
size_t password_len = strlen((const char *)wifi_cfg.sta.password);
wifi_auth_mode_t authmode = wifi_cfg.sta.threshold.authmode;
if (g_sta_connected &&
((password_len > 0 && authmode != WIFI_AUTH_OPEN) ||
(password_len == 0 && authmode == WIFI_AUTH_OPEN)))
{
ret = esp_wifi_sta_disconnect();
if (ret)
{
wlerr("Failed to disconnect from Wi-Fi AP ret=%d\n", ret);
return ret;
}
ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg);
if (ret)
{
wlerr("Failed to set Wi-Fi config data ret=%d\n", ret);
return esp_wifi_to_errno(ret);
}
ret = esp_wifi_sta_connect();
if (ret)
{
wlerr("Failed to connect to Wi-Fi AP ret=%d\n", ret);
return ret;
}
}
g_sta_wifi_cfg = wifi_cfg;
}
else
{
if (g_sta_connected == false)
{
return -ENOTCONN;
}
ret = esp_wifi_sta_get_ap_info(&ap_info);
if (ret)
{
wlerr("Failed to get AP record ret=%d\n", ret);
return esp_wifi_to_errno(ret);
}
cmd = iwr->u.param.flags & IW_AUTH_INDEX;
switch (cmd)
{
case IW_AUTH_WPA_VERSION:
iwr->u.param.value = esp_wifi_auth_trans(ap_info.authmode);
break;
case IW_AUTH_CIPHER_PAIRWISE:
iwr->u.param.value =
esp_wifi_cipher_trans(ap_info.pairwise_cipher);
break;
case IW_AUTH_CIPHER_GROUP:
iwr->u.param.value = esp_wifi_cipher_trans(ap_info.group_cipher);
break;
case IW_AUTH_KEY_MGMT:
case IW_AUTH_TKIP_COUNTERMEASURES:
case IW_AUTH_DROP_UNENCRYPTED:
case IW_AUTH_80211_AUTH_ALG:
case IW_AUTH_WPA_ENABLED:
case IW_AUTH_RX_UNENCRYPTED_EAPOL:
case IW_AUTH_ROAMING_CONTROL:
case IW_AUTH_PRIVACY_INVOKED:
default:
wlerr("Unknown cmd %d\n", cmd);
return -ENOSYS;
}
}
return OK;
}
/****************************************************************************
* Name: esp_wifi_sta_freq
*
* Description:
* Set/Get station frequency.
*
* Input Parameters:
* iwr - The argument of the ioctl cmd
* set - true: set data; false: get data
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_sta_freq(struct iwreq *iwr, bool set)
{
int ret;
if (set && (iwr->u.freq.flags == IW_FREQ_FIXED))
{
wifi_config_t wifi_cfg = g_sta_wifi_cfg;
wifi_cfg.sta.channel = esp_freq_to_channel(iwr->u.freq.m);
if (g_sta_connected)
{
ret = esp_wifi_sta_disconnect();
if (ret)
{
wlerr("Failed to disconnect from Wi-Fi AP ret=%d\n", ret);
return ret;
}
ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg);
if (ret)
{
wlerr("Failed to set Wi-Fi config data ret=%d\n", ret);
return esp_wifi_to_errno(ret);
}
ret = esp_wifi_sta_connect();
if (ret)
{
wlerr("Failed to connect to Wi-Fi AP ret=%d\n", ret);
return ret;
}
}
g_sta_wifi_cfg = wifi_cfg;
}
else
{
if (g_sta_connected)
{
wifi_ap_record_t ap_info;
ret = esp_wifi_sta_get_ap_info(&ap_info);
if (ret)
{
wlerr("Failed to get AP record ret=%d\n", ret);
return esp_wifi_to_errno(ret);
}
iwr->u.freq.flags = IW_FREQ_FIXED;
iwr->u.freq.e = 0;
iwr->u.freq.m = 2407 + 5 * ap_info.primary;
}
else
{
iwr->u.freq.flags = IW_FREQ_AUTO;
iwr->u.freq.e = 0;
iwr->u.freq.m = 2412;
}
}
return OK;
}
/****************************************************************************
* Name: esp_wifi_sta_bitrate
*
* Description:
* Get station default bit rate (Mbps).
*
* Input Parameters:
* iwr - The argument of the ioctl cmd
* set - true: set data; false: get data
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_sta_bitrate(struct iwreq *iwr, bool set)
{
int ret;
wifi_ap_record_t ap_info;
if (set)
{
return -ENOSYS;
}
else
{
if (g_sta_connected == false)
{
iwr->u.bitrate.fixed = IW_FREQ_AUTO;
return OK;
}
ret = esp_wifi_sta_get_ap_info(&ap_info);
if (ret)
{
wlerr("Failed to get AP record ret=%d\n", ret);
return esp_wifi_to_errno(ret);
}
iwr->u.bitrate.fixed = IW_FREQ_FIXED;
if (ap_info.phy_11n)
{
if (ap_info.second)
{
iwr->u.bitrate.value = ESP_WIFI_11N_MCS7_HT40_BITRATE;
}
else
{
iwr->u.bitrate.value = ESP_WIFI_11N_MCS7_HT20_BITRATE;
}
}
else if (ap_info.phy_11g)
{
iwr->u.bitrate.value = ESP_WIFI_11G_MAX_BITRATE;
}
else if (ap_info.phy_11b)
{
iwr->u.bitrate.value = ESP_WIFI_11B_MAX_BITRATE;
}
else
{
return -EIO;
}
}
return OK;
}
#endif /* ESP_WLAN_HAS_STA */
/****************************************************************************
* Name: esp_wifi_sta_get_txpower
*
* Description:
* Get station transmit power (dBm).
*
* Input Parameters:
* iwr - The argument of the ioctl cmd
* set - true: set data; false: get data
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_sta_txpower(struct iwreq *iwr, bool set)
{
int ret;
int8_t power;
double power_dbm;
if (set)
{
if (iwr->u.txpower.flags == IW_TXPOW_RELATIVE)
{
power = (int8_t)iwr->u.txpower.value;
}
else
{
if (iwr->u.txpower.flags == IW_TXPOW_MWATT)
{
power_dbm = ceil(10 * log10(iwr->u.txpower.value));
}
else
{
power_dbm = iwr->u.txpower.value;
}
power = (int8_t)(power_dbm * 4);
}
/* The value set by this API will be mapped to the max_tx_power
* of the structure wifi_country_t variable. Param power unit is
* 0.25dBm, range is [8, 84] corresponding to 2dBm - 20dBm.
* Relationship between set value and actual value.
* As follows: {set value range, actual value} =
* {{[8, 19],8}, {[20, 27],20}, {[28, 33],28},
* {[34, 43],34}, {[44, 51],44}, {[52, 55],52},
* {[56, 59],56}, {[60, 65],60}, {[66, 71],66},
* {[72, 79],72}, {[80, 84],80}}.
*/
if (power < 8 || power > 84)
{
wlerr("Failed to set transmit power =%d\n", power);
return -ENOSYS;
}
esp_wifi_set_max_tx_power(power);
return OK;
}
else
{
ret = esp_wifi_get_max_tx_power(&power);
if (ret)
{
wlerr("Failed to get transmit power ret=%d\n", ret);
return esp_wifi_to_errno(ret);
}
iwr->u.txpower.disabled = 0;
iwr->u.txpower.flags = IW_TXPOW_DBM;
iwr->u.txpower.value = power / 4;
}
return OK;
}
/****************************************************************************
* Name: esp_wifi_sta_channel
*
* Description:
* Get station range of channel parameters.
*
* Input Parameters:
* iwr - The argument of the ioctl cmd
* set - true: set data; false: get data
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_sta_channel(struct iwreq *iwr, bool set)
{
int ret;
int k;
wifi_country_t country;
struct iw_range *range;
if (set)
{
return -ENOSYS;
}
else
{
ret = esp_wifi_get_country(&country);
if (ret)
{
wlerr("Failed to get country info ret=%d\n", ret);
return esp_wifi_to_errno(ret);
}
range = (struct iw_range *)iwr->u.data.pointer;
range->num_frequency = country.nchan;
for (k = 1; k <= range->num_frequency; k++)
{
range->freq[k - 1].i = k;
range->freq[k - 1].e = 0;
range->freq[k - 1].m = 2407 + 5 * k;
}
}
return OK;
}
/****************************************************************************
* Name: esp_wifi_sta_country
*
* Description:
* Configure country info.
*
* Input Parameters:
* iwr - The argument of the ioctl cmd
* set - true: set data; false: get data
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_sta_country(struct iwreq *iwr, bool set)
{
int ret;
char *country_code;
wifi_country_t country;
if (set)
{
memset(&country, 0x00, sizeof(wifi_country_t));
country.schan = 1;
country.policy = 0;
country_code = (char *)iwr->u.data.pointer;
if (strlen(country_code) != 2)
{
wlerr("Invalid input arguments\n");
return -EINVAL;
}
if (strncmp(country_code, "US", 3) == 0 ||
strncmp(country_code, "CA", 3) == 0)
{
country.nchan = 11;
}
else if(strncmp(country_code, "JP", 3) == 0)
{
country.nchan = 14;
}
else
{
country.nchan = 13;
}
memcpy(country.cc, country_code, 2);
ret = esp_wifi_set_country(&country);
if (ret)
{
wlerr("Failed to Configure country ret=%d\n", ret);
return esp_wifi_to_errno(ret);
}
}
else
{
return -ENOSYS;
}
return OK;
}
#ifdef ESP_WLAN_HAS_STA
/****************************************************************************
* Name: esp_wifi_sta_rssi
*
* Description:
* Get Wi-Fi sensitivity (dBm).
*
* Input Parameters:
* iwr - The argument of the ioctl cmd
* set - true: set data; false: get data
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_sta_rssi(struct iwreq *iwr, bool set)
{
int ret;
wifi_ap_record_t ap_info;
if (set)
{
return -ENOSYS;
}
else
{
if (g_sta_connected == false)
{
iwr->u.sens.value = 128;
return OK;
}
ret = esp_wifi_sta_get_ap_info(&ap_info);
if (ret)
{
wlerr("Failed to get AP record ret=%d\n", ret);
return esp_wifi_to_errno(ret);
}
iwr->u.sens.value = -(ap_info.rssi);
}
return OK;
}
#endif /* ESP_WLAN_HAS_STA */
/****************************************************************************
* SoftAP functions
****************************************************************************/
#ifdef ESP_WLAN_HAS_SOFTAP
/****************************************************************************
* Name: esp_wifi_softap_start
*
* Description:
* Start Wi-Fi SoftAP.
*
* Input Parameters:
* None
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_softap_start(void)
{
int ret;
wifi_mode_t mode;
esp_wifi_lock(true);
ret = esp_wifi_stop();
if (ret)
{
wlinfo("Failed to stop Wi-Fi ret=%d\n", ret);
}
#ifdef ESP_WLAN_HAS_STA
if (g_sta_started)
{
mode = WIFI_MODE_APSTA;
}
else
#endif /* ESP_WLAN_HAS_STA */
{
mode = WIFI_MODE_AP;
}
ret = esp_wifi_set_mode(mode);
if (ret)
{
wlerr("Failed to set Wi-Fi mode=%d ret=%d\n", mode, ret);
ret = esp_wifi_to_errno(ret);
goto errout;
}
ret = esp_wifi_start();
if (ret)
{
wlerr("Failed to start Wi-Fi with mode=%d ret=%d\n", mode, ret);
ret = esp_wifi_to_errno(ret);
goto errout;
}
g_softap_started = true;
wlinfo("OK to start Wi-Fi SoftAP\n");
errout:
esp_wifi_lock(false);
return ret;
}
/****************************************************************************
* Name: esp_wifi_softap_stop
*
* Description:
* Stop Wi-Fi SoftAP.
*
* Input Parameters:
* None
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_softap_stop(void)
{
int ret;
esp_wifi_lock(true);
ret = esp_wifi_stop();
if (ret)
{
wlinfo("Failed to stop Wi-Fi ret=%d\n", ret);
}
g_softap_started = false;
#ifdef ESP_WLAN_HAS_STA
if (g_sta_started)
{
ret = esp_wifi_set_mode(WIFI_MODE_STA);
if (ret)
{
wlerr("Failed to set Wi-Fi AP mode ret=%d\n", ret);
ret = esp_wifi_to_errno(ret);
goto errout;
}
ret = esp_wifi_start();
if (ret)
{
wlerr("Failed to start Wi-Fi STA ret=%d\n", ret);
ret = esp_wifi_to_errno(ret);
goto errout;
}
}
#endif /* ESP_WLAN_HAS_STA */
wlinfo("OK to stop Wi-Fi SoftAP\n");
#ifdef ESP_WLAN_HAS_STA
errout:
#endif /* ESP_WLAN_HAS_STA */
esp_wifi_lock(false);
return ret;
}
/****************************************************************************
* Name: esp_wifi_softap_send_data
*
* Description:
* Use Wi-Fi SoftAP interface to send 802.3 frame
*
* Input Parameters:
* pbuf - Packet buffer pointer
* len - Packet length
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_softap_send_data(void *pbuf, size_t len)
{
int ret;
ret = esp_wifi_internal_tx(WIFI_IF_AP, pbuf, len);
return esp_wifi_to_errno(ret);
}
/****************************************************************************
* Name: esp_wifi_softap_password
*
* Description:
* Set/Get Wi-Fi SoftAP password
*
* Input Parameters:
* iwr - The argument of the ioctl cmd
* set - true: set data; false: get data
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_softap_password(struct iwreq *iwr, bool set)
{
int ret;
int size;
wifi_config_t wifi_cfg;
struct iw_encode_ext *ext = iwr->u.encoding.pointer;
uint8_t *pdata;
uint8_t len;
#ifdef CONFIG_DEBUG_WIRELESS_INFO
char buf[PWD_MAX_LEN + 1];
#endif
DEBUGASSERT(ext != NULL);
pdata = ext->key;
len = ext->key_len;
if (set && len > PWD_MAX_LEN)
{
return -EINVAL;
}
pdata = ext->key;
len = ext->key_len;
wifi_cfg = g_softap_wifi_cfg;
if (set)
{
/* Clear the password field and copy the user password to it */
memset(wifi_cfg.ap.password, 0x0, PWD_MAX_LEN);
if (ext->alg != IW_ENCODE_ALG_NONE)
{
memcpy(wifi_cfg.sta.password, pdata, len);
}
if (g_softap_started)
{
ret = esp_wifi_set_config(WIFI_IF_AP, &wifi_cfg);
if (ret)
{
wlerr("Failed to set Wi-Fi config data ret=%d\n", ret);
return esp_wifi_to_errno(ret);
}
}
g_softap_wifi_cfg = wifi_cfg;
}
else
{
size = strnlen((char *)wifi_cfg.ap.password, PWD_MAX_LEN);
if (len < size)
{
return -EINVAL;
}
else
{
len = size;
memcpy(pdata, wifi_cfg.ap.password, len);
}
}
#ifdef CONFIG_DEBUG_WIRELESS_INFO
memcpy(buf, pdata, len);
buf[len] = 0;
wlinfo("Wi-Fi SoftAP password=%s len=%d\n", buf, len);
#endif
return OK;
}
/****************************************************************************
* Name: esp_wifi_softap_essid
*
* Description:
* Set/Get Wi-Fi SoftAP ESSID
*
* Input Parameters:
* iwr - The argument of the ioctl cmd
* set - true: set data; false: get data
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_softap_essid(struct iwreq *iwr, bool set)
{
int ret;
int size;
wifi_config_t wifi_cfg;
struct iw_point *essid = &iwr->u.essid;
uint8_t *pdata;
uint8_t len;
#ifdef CONFIG_DEBUG_WIRELESS_INFO
char buf[SSID_MAX_LEN + 1];
#endif
DEBUGASSERT(essid != NULL);
pdata = essid->pointer;
len = essid->length;
if (set && len > SSID_MAX_LEN)
{
return -EINVAL;
}
wifi_cfg = g_softap_wifi_cfg;
if (set)
{
memset(wifi_cfg.ap.ssid, 0x0, SSID_MAX_LEN);
memcpy(wifi_cfg.ap.ssid, pdata, len);
wifi_cfg.ap.ssid_len = len;
if (g_softap_started)
{
ret = esp_wifi_set_config(WIFI_IF_AP, &wifi_cfg);
if (ret)
{
wlerr("Failed to set Wi-Fi config data ret=%d\n", ret);
return esp_wifi_to_errno(ret);
}
}
g_softap_wifi_cfg = wifi_cfg;
}
else
{
size = strnlen((char *)wifi_cfg.ap.ssid, SSID_MAX_LEN);
if (len < size)
{
return -EINVAL;
}
else
{
len = size;
memcpy(pdata, wifi_cfg.ap.ssid, len);
}
}
#ifdef CONFIG_DEBUG_WIRELESS_INFO
memcpy(buf, pdata, len);
buf[len] = 0;
wlinfo("Wi-Fi SoftAP ssid=%s len=%d\n", buf, len);
#endif
return OK;
}
/****************************************************************************
* Name: esp_wifi_softap_bssid
*
* Description:
* Set/Get Wi-Fi softAP BSSID
*
* Input Parameters:
* iwr - The argument of the ioctl cmd
* set - true: set data; false: get data
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_softap_bssid(struct iwreq *iwr, bool set)
{
return -ENOSYS;
}
/****************************************************************************
* Name: esp_wifi_softap_connect
*
* Description:
* Trigger Wi-Fi SoftAP accept connection action
*
* Input Parameters:
* None
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_softap_connect(void)
{
int ret;
ret = esp_wifi_set_config(WIFI_IF_AP, &g_softap_wifi_cfg);
if (ret)
{
wlerr("Failed to set Wi-Fi config data ret=%d\n", ret);
return esp_wifi_to_errno(ret);
}
return OK;
}
/****************************************************************************
* Name: esp_wifi_softap_disconnect
*
* Description:
* Trigger Wi-Fi SoftAP drop connection action
*
* Input Parameters:
* None
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_softap_disconnect(void)
{
return OK;
}
/****************************************************************************
* Name: esp_wifi_softap_mode
*
* Description:
* Set/Get Wi-Fi SoftAP mode code.
*
* Input Parameters:
* iwr - The argument of the ioctl cmd
* set - true: set data; false: get data
*
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_softap_mode(struct iwreq *iwr, bool set)
{
if (set == false)
{
iwr->u.mode = IW_MODE_MASTER;
}
return OK;
}
/****************************************************************************
* Name: esp_wifi_softap_auth
*
* Description:
* Set/get authentication mode params.
*
* Input Parameters:
* iwr - The argument of the ioctl cmd
* set - true: set data; false: get data
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_softap_auth(struct iwreq *iwr, bool set)
{
int ret;
int cmd;
wifi_config_t wifi_cfg;
wifi_cfg = g_softap_wifi_cfg;
if (set)
{
cmd = iwr->u.param.flags & IW_AUTH_INDEX;
switch (cmd)
{
case IW_AUTH_WPA_VERSION:
{
switch (iwr->u.param.value)
{
case IW_AUTH_WPA_VERSION_DISABLED:
wifi_cfg.ap.authmode = WIFI_AUTH_OPEN;
break;
case IW_AUTH_WPA_VERSION_WPA:
wifi_cfg.ap.authmode = WIFI_AUTH_WPA_PSK;
break;
case IW_AUTH_WPA_VERSION_WPA2:
wifi_cfg.ap.authmode = WIFI_AUTH_WPA2_PSK;
break;
case IW_AUTH_WPA_VERSION_WPA3:
wifi_cfg.ap.pmf_cfg.required = true;
wifi_cfg.ap.pmf_cfg.capable = false;
wifi_cfg.ap.sae_pwe_h2e = WPA3_SAE_PWE_BOTH;
wifi_cfg.ap.authmode = WIFI_AUTH_WPA3_PSK;
break;
default:
wlerr("Invalid wpa version %" PRId32 "\n",
iwr->u.param.value);
return -EINVAL;
}
}
break;
case IW_AUTH_CIPHER_PAIRWISE:
case IW_AUTH_CIPHER_GROUP:
{
switch (iwr->u.param.value)
{
case IW_AUTH_CIPHER_NONE:
wifi_cfg.ap.authmode = WIFI_AUTH_OPEN;
break;
case IW_AUTH_CIPHER_WEP40:
case IW_AUTH_CIPHER_WEP104:
wifi_cfg.ap.authmode = WIFI_AUTH_WEP;
break;
case IW_AUTH_CIPHER_TKIP:
case IW_AUTH_CIPHER_CCMP:
case IW_AUTH_CIPHER_AES_CMAC:
break;
default:
wlerr("Invalid cipher mode %" PRId32 "\n",
iwr->u.param.value);
return -EINVAL;
}
}
break;
case IW_AUTH_KEY_MGMT:
case IW_AUTH_TKIP_COUNTERMEASURES:
case IW_AUTH_DROP_UNENCRYPTED:
case IW_AUTH_80211_AUTH_ALG:
case IW_AUTH_WPA_ENABLED:
case IW_AUTH_RX_UNENCRYPTED_EAPOL:
case IW_AUTH_ROAMING_CONTROL:
case IW_AUTH_PRIVACY_INVOKED:
default:
wlerr("Unknown cmd %d\n", cmd);
return -EINVAL;
}
size_t password_len = strlen((const char *)wifi_cfg.ap.password);
if (g_softap_started &&
((password_len > 0 && wifi_cfg.ap.authmode != WIFI_AUTH_OPEN) ||
(password_len == 0 && wifi_cfg.ap.authmode == WIFI_AUTH_OPEN)))
{
ret = esp_wifi_set_config(WIFI_IF_AP, &wifi_cfg);
if (ret)
{
wlerr("Failed to set Wi-Fi config data ret=%d\n", ret);
return esp_wifi_to_errno(ret);
}
}
g_softap_wifi_cfg = wifi_cfg;
}
else
{
return -ENOSYS;
}
return OK;
}
/****************************************************************************
* Name: esp_wifi_softap_freq
*
* Description:
* Set/Get SoftAP frequency.
*
* Input Parameters:
* iwr - The argument of the ioctl cmd
* set - true: set data; false: get data
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_softap_freq(struct iwreq *iwr, bool set)
{
int ret;
wifi_config_t wifi_cfg;
wifi_cfg = g_softap_wifi_cfg;
if (set)
{
int channel = esp_freq_to_channel(iwr->u.freq.m);
wifi_cfg.ap.channel = channel;
if (g_softap_started)
{
ret = esp_wifi_set_config(WIFI_IF_AP, &wifi_cfg);
if (ret)
{
wlerr("Failed to set Wi-Fi config data ret=%d\n", ret);
return esp_wifi_to_errno(ret);
}
}
g_softap_wifi_cfg = wifi_cfg;
}
else
{
iwr->u.freq.flags = IW_FREQ_FIXED;
iwr->u.freq.e = 0;
iwr->u.freq.m = 2407 + 5 * wifi_cfg.ap.channel;
}
return OK;
}
/****************************************************************************
* Name: esp_wifi_softap_get_bitrate
*
* Description:
* Get SoftAP default bit rate (Mbps).
*
* Input Parameters:
* iwr - The argument of the ioctl cmd
* set - true: set data; false: get data
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_softap_bitrate(struct iwreq *iwr, bool set)
{
return -ENOSYS;
}
/****************************************************************************
* Name: esp_wifi_softap_txpower
*
* Description:
* Get SoftAP transmit power (dBm).
*
* Input Parameters:
* iwr - The argument of the ioctl cmd
* set - true: set data; false: get data
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_softap_txpower(struct iwreq *iwr, bool set)
{
return esp_wifi_sta_txpower(iwr, set);
}
/****************************************************************************
* Name: esp_wifi_softap_channel
*
* Description:
* Get SoftAP range of channel parameters.
*
* Input Parameters:
* iwr - The argument of the ioctl cmd
* set - true: set data; false: get data
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_softap_channel(struct iwreq *iwr, bool set)
{
return esp_wifi_sta_channel(iwr, set);
}
/****************************************************************************
* Name: esp_wifi_softap_country
*
* Description:
* Configure country info.
*
* Input Parameters:
* iwr - The argument of the ioctl cmd
* set - true: set data; false: get data
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_softap_country(struct iwreq *iwr, bool set)
{
return esp_wifi_sta_country(iwr, set);
}
/****************************************************************************
* Name: esp_wifi_softap_rssi
*
* Description:
* Get Wi-Fi sensitivity (dBm).
*
* Input Parameters:
* iwr - The argument of the ioctl cmd
* set - true: set data; false: get data
*
* Returned Value:
* OK on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
int esp_wifi_softap_rssi(struct iwreq *iwr, bool set)
{
return -ENOSYS;
}
#endif /* ESP_WLAN_HAS_SOFTAP */