/**************************************************************************** * arch/xtensa/src/esp32/esp32_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 #include #include #include #include #include #include #include #include #include #include #include #include #include "nuttx/kmalloc.h" #include "nuttx/spinlock.h" #include #include #include #include #include #include #include #include "xtensa.h" #include "xtensa_attr.h" #include "hardware/esp32_dport.h" #include "hardware/esp32_emac.h" #include "esp32_cpuint.h" #include "esp32_wifi_adapter.h" #include "espidf_wifi.h" /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ #define PHY_RF_MASK ((1 << PHY_BT_MODULE) | (1 << PHY_WIFI_MODULE)) #ifdef CONFIG_ESP32_WIFI_SAVE_PARAM # define NVS_FS_PREFIX CONFIG_ESP32_WIFI_FS_MOUNTPT # define NVS_DIR_BASE NVS_FS_PREFIX"/wifi." # define NVS_FILE_MODE 0777 #endif #define WIFI_CONNECT_TIMEOUT CONFIG_ESP32_WIFI_CONNECT_TIMEOUT /**************************************************************************** * Private Types ****************************************************************************/ /* WiFi interrupt adapter private data */ struct irq_adpt { void (*func)(void *arg); /* Interrupt callback function */ void *arg; /* Interrupt private data */ }; /* WiFi message queue private data */ struct mq_adpt { mqd_t mq; /* Message queue handle */ uint32_t msgsize; /* Message size */ char name[16]; /* Message queue name */ }; /* WiFi time private data */ struct time_adpt { time_t sec; /* Second value */ suseconds_t usec; /* Micro second value */ }; /* WiFi timer private data */ struct timer_adpt { struct wdog_s wdog; /* Timer handle */ struct work_s work; /* Work private data */ bool repeat; /* Flags indicate if it is cycle */ uint32_t delay; /* Timeout ticks */ /* Timer callback function */ void (*func)(void *priv); void *priv; /* Timer private data */ }; /* WiFi event private data */ struct evt_adpt { sq_entry_t entry; /* Sequence entry */ int32_t id; /* Event ID */ uint8_t buf[0]; /* Event private data */ }; /* WiFi 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 */ }; /* WiFi NVS private data */ struct nvs_adpt { char *index_name; }; /**************************************************************************** * Private Function Prototypes ****************************************************************************/ static void esp_set_isr(int32_t n, void *f, void *arg); static void esp32_ints_on(uint32_t mask); static void esp32_ints_off(uint32_t mask); static void *esp_spin_lock_create(void); static void esp_spin_lock_delete(void *lock); static uint32_t esp_wifi_int_disable(void *wifi_int_mux); static void esp_wifi_int_restore(void *wifi_int_mux, uint32_t tmp); static void IRAM_ATTR esp_task_yield_from_isr(void); static void *esp_semphr_create(uint32_t max, uint32_t init); static void esp_semphr_delete(void *semphr); static int32_t esp_semphr_take(void *semphr, uint32_t block_time_tick); static int32_t esp_semphr_give(void *semphr); static void *esp_thread_semphr_get(void); static void *esp_mutex_create(void); static void *esp_recursive_mutex_create(void); static void esp_mutex_delete(void *mutex_data); static int32_t esp_mutex_lock(void *mutex_data); static int32_t esp_mutex_unlock(void *mutex_data); static void *esp_queue_create(uint32_t queue_len, uint32_t item_size); static void esp_queue_delete(void *queue); static int32_t esp_queue_send(void *queue, void *item, uint32_t block_time_tick); static int32_t esp_queue_send_from_isr(void *queue, void *item, void *hptw); static int32_t esp_queue_send_to_back(void *queue, void *item, uint32_t block_time_tick); static int32_t esp_queue_send_to_front(void *queue, void *item, uint32_t block_time_tick); static int32_t esp_queue_recv(void *queue, void *item, uint32_t block_time_tick); static uint32_t esp_queue_msg_waiting(void *queue); static void *esp_event_group_create(void); static void esp_event_group_delete(void *event); static uint32_t esp_event_group_set_bits(void *event, uint32_t bits); static uint32_t esp_event_group_clear_bits(void *event, uint32_t bits); static uint32_t esp_event_group_wait_bits(void *event, uint32_t bits_to_wait_for, int32_t clear_on_exit, int32_t wait_for_all_bits, uint32_t block_time_tick); static int32_t esp_task_create_pinned_to_core(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 esp_task_create(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle); static void esp_task_delete(void *task_handle); static void esp_task_delay(uint32_t tick); static int32_t esp_task_ms_to_tick(uint32_t ms); static void *esp_task_get_current_task(void); static int32_t esp_task_get_max_priority(void); static void *esp_malloc(uint32_t size); static uint32_t esp_rand(void); static void esp_dport_access_stall_other_cpu_start(void); static void esp_dport_access_stall_other_cpu_end(void); static int32_t esp_phy_deinit_rf(uint32_t module); static void esp_phy_init(uint32_t module); static void esp_phy_enable_clock(void); static void esp_phy_disable_clock(void); static int32_t esp_wifi_read_mac(uint8_t *mac, uint32_t type); static void esp_timer_arm(void *timer, uint32_t tmout, bool repeat); static void esp_timer_disarm(void *timer); static void esp32_timer_done(void *timer); static void esp_timer_setfn(void *timer, void *pfunction, void *parg); static void esp_timer_cb(wdparm_t parm); static void esp_timer_arm_us(void *timer, uint32_t us, bool repeat); static void esp_periph_module_enable(uint32_t periph); static void esp_periph_module_disable(uint32_t periph); static int32_t esp_nvs_set_i8(uint32_t handle, const char *key, int8_t value); static int32_t esp_nvs_get_i8(uint32_t handle, const char *key, int8_t *out_value); static int32_t esp_nvs_set_u8(uint32_t handle, const char *key, uint8_t value); static int32_t esp_nvs_get_u8(uint32_t handle, const char *key, uint8_t *out_value); static int32_t esp_nvs_set_u16(uint32_t handle, const char *key, uint16_t value); static int32_t esp_nvs_get_u16(uint32_t handle, const char *key, uint16_t *out_value); static int32_t esp_nvs_open(const char *name, uint32_t open_mode, uint32_t *out_handle); static void esp_nvs_close(uint32_t handle); static int32_t esp_nvs_commit(uint32_t handle); static int32_t esp_nvs_set_blob(uint32_t handle, const char *key, const void *value, size_t length); static int32_t esp_nvs_get_blob(uint32_t handle, const char *key, void *out_value, size_t *length); static int32_t esp_nvs_erase_key(uint32_t handle, const char *key); static int32_t esp_get_random(uint8_t *buf, size_t len); static int32_t esp_get_time(void *t); static void esp_log_writev(uint32_t level, const char *tag, const char *format, va_list args); static void *esp_malloc_internal(size_t size); static void *esp_realloc_internal(void *ptr, size_t size); static void *esp_calloc_internal(size_t n, size_t size); static void *esp_zalloc_internal(size_t size); static void *esp_wifi_malloc(size_t size); static void *esp_wifi_realloc(void *ptr, size_t size); static void *esp_wifi_calloc(size_t n, size_t size); static void *esp_wifi_zalloc(size_t size); static int32_t esp_modem_enter_sleep(uint32_t module); static int32_t esp_modem_exit_sleep(uint32_t module); static int32_t esp_modem_register_sleep(uint32_t module); static int32_t esp_modem_deregister_sleep(uint32_t module); static void *esp_wifi_create_queue(int32_t queue_len, int32_t item_size); static void esp_wifi_delete_queue(void *queue); static uint32_t esp_coex_status_get(void); static void esp_coex_condition_set(uint32_t type, bool dissatisfy); static int32_t esp_coex_wifi_request(uint32_t event, uint32_t latency, uint32_t duration); static int32_t esp_coex_wifi_release(uint32_t event); /**************************************************************************** * Public Functions declaration ****************************************************************************/ int64_t esp_timer_get_time(void); void esp_fill_random(void *buf, size_t len); void esp_log_write(uint32_t level, const char *tag, const char *format, ...); uint32_t esp_log_timestamp(void); uint8_t esp_crc8(const uint8_t *p, uint32_t len); /**************************************************************************** * Private Data ****************************************************************************/ /* WiFi interrupt private data */ static int s_wifi_irq; /* WiFi thread private data */ static pthread_key_t s_wifi_thread_key; static bool s_wifi_tkey_init; /* WiFi sleep private data */ static uint32_t s_esp32_module_mask; static uint32_t s_esp32_module_sleep; static bool s_esp32_sleep; static uint32_t s_phy_clk_en_cnt = 0; static bool s_esp23_phy_en; static uint32_t s_esp32_phy_init_mask; static int64_t s_esp32_phy_rf_stop_tm; /* WiFi event private data */ static struct work_s s_wifi_evt_work; static sq_queue_t s_wifi_evt_queue; static struct wifi_notify s_wifi_notify[WIFI_ADPT_EVT_MAX]; static sem_t s_connect_sem; static bool s_connected; static uint8_t s_ssid[32]; static uint8_t s_password[64]; static uint8_t s_ssid_len; static uint8_t s_password_len; /**************************************************************************** * Public Data ****************************************************************************/ /* WiFi OS adapter data */ wifi_osi_funcs_t g_wifi_osi_funcs = { ._version = ESP_WIFI_OS_ADAPTER_VERSION, ._set_isr = esp_set_isr, ._ints_on = esp32_ints_on, ._ints_off = esp32_ints_off, ._spin_lock_create = esp_spin_lock_create, ._spin_lock_delete = esp_spin_lock_delete, ._wifi_int_disable = esp_wifi_int_disable, ._wifi_int_restore = esp_wifi_int_restore, ._task_yield_from_isr = esp_task_yield_from_isr, ._semphr_create = esp_semphr_create, ._semphr_delete = esp_semphr_delete, ._semphr_take = esp_semphr_take, ._semphr_give = esp_semphr_give, ._wifi_thread_semphr_get = esp_thread_semphr_get, ._mutex_create = esp_mutex_create, ._recursive_mutex_create = esp_recursive_mutex_create, ._mutex_delete = esp_mutex_delete, ._mutex_lock = esp_mutex_lock, ._mutex_unlock = esp_mutex_unlock, ._queue_create = esp_queue_create, ._queue_delete = esp_queue_delete, ._queue_send = esp_queue_send, ._queue_send_from_isr = esp_queue_send_from_isr, ._queue_send_to_back = esp_queue_send_to_back, ._queue_send_to_front = esp_queue_send_to_front, ._queue_recv = esp_queue_recv, ._queue_msg_waiting = esp_queue_msg_waiting, ._event_group_create = esp_event_group_create, ._event_group_delete = esp_event_group_delete, ._event_group_set_bits = esp_event_group_set_bits, ._event_group_clear_bits = esp_event_group_clear_bits, ._event_group_wait_bits = esp_event_group_wait_bits, ._task_create_pinned_to_core = esp_task_create_pinned_to_core, ._task_create = esp_task_create, ._task_delete = esp_task_delete, ._task_delay = esp_task_delay, ._task_ms_to_tick = esp_task_ms_to_tick, ._task_get_current_task = esp_task_get_current_task, ._task_get_max_priority = esp_task_get_max_priority, ._malloc = esp_malloc, ._free = free, ._event_post = esp_event_post, ._get_free_heap_size = esp_get_free_heap_size, ._rand = esp_rand, ._dport_access_stall_other_cpu_start_wrap = esp_dport_access_stall_other_cpu_start, ._dport_access_stall_other_cpu_end_wrap = esp_dport_access_stall_other_cpu_end, ._phy_rf_deinit = esp_phy_deinit_rf, ._phy_load_cal_and_init = esp_phy_init, ._phy_common_clock_enable = esp_phy_enable_clock, ._phy_common_clock_disable = esp_phy_disable_clock, ._read_mac = esp_wifi_read_mac, ._timer_arm = esp_timer_arm, ._timer_disarm = esp_timer_disarm, ._timer_done = esp32_timer_done, ._timer_setfn = esp_timer_setfn, ._timer_arm_us = esp_timer_arm_us, ._periph_module_enable = esp_periph_module_enable, ._periph_module_disable = esp_periph_module_disable, ._esp_timer_get_time = esp_timer_get_time, ._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 = esp_nvs_open, ._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 = esp_get_random, ._get_time = esp_get_time, ._random = esp_random, ._log_write = esp_log_write, ._log_writev = esp_log_writev, ._log_timestamp = esp_log_timestamp, ._malloc_internal = esp_malloc_internal, ._realloc_internal = esp_realloc_internal, ._calloc_internal = esp_calloc_internal, ._zalloc_internal = esp_zalloc_internal, ._wifi_malloc = esp_wifi_malloc, ._wifi_realloc = esp_wifi_realloc, ._wifi_calloc = esp_wifi_calloc, ._wifi_zalloc = esp_wifi_zalloc, ._wifi_create_queue = esp_wifi_create_queue, ._wifi_delete_queue = esp_wifi_delete_queue, ._modem_sleep_enter = esp_modem_enter_sleep, ._modem_sleep_exit = esp_modem_exit_sleep, ._modem_sleep_register = esp_modem_register_sleep, ._modem_sleep_deregister = esp_modem_deregister_sleep, ._coex_status_get = esp_coex_status_get, ._coex_condition_set = esp_coex_condition_set, ._coex_wifi_request = esp_coex_wifi_request, ._coex_wifi_release = esp_coex_wifi_release, ._magic = ESP_WIFI_OS_ADAPTER_MAGIC, }; /* WiFi feature capacity data */ uint64_t g_wifi_feature_caps; /* WiFi TAG string data */ ESP_EVENT_DEFINE_BASE(WIFI_EVENT); /**************************************************************************** * Private Functions and Public Functions only used by libraries ****************************************************************************/ /**************************************************************************** * Name: esp_errno_trans * * Description: * Transform from nuttx error code to WiFi adapter error code * * Input Parameters: * ret - Nuttx error code * * Returned Value: * WiFi adapter error code * ****************************************************************************/ static inline int32_t esp_errno_trans(int ret) { if (!ret) { return true; } else { return false; } } /**************************************************************************** * Name: esp_int_adpt_cb * * Description: * WiFi interrupt adapter callback function * * Input Parameters: * arg - interrupt adapter private data * * Returned Value: * 0 on success * ****************************************************************************/ static int esp_int_adpt_cb(int irq, void *context, FAR void *arg) { struct irq_adpt *adapter = (struct irq_adpt *)arg; adapter->func(adapter->arg); return 0; } /**************************************************************************** * Name: esp_thread_semphr_free * * Description: * Delete thread self's semaphore * * Input Parameters: * semphr - Semphore data pointer * * Returned Value: * None * ****************************************************************************/ static void esp_thread_semphr_free(void *semphr) { if (semphr) { esp_semphr_delete(semphr); } } /**************************************************************************** * 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; } /**************************************************************************** * Name: esp_set_isr * * Description: * Register interrupt function * * Input Parameters: * n - Interrupt ID * f - Interrupt function * arg - Function private data * * Returned Value: * None * ****************************************************************************/ static void esp_set_isr(int32_t n, void *f, void *arg) { int ret; struct irq_adpt *adapter; int irq; int cpu = 0; int tmp; irq = esp32_alloc_levelint(1); if (irq < 0) { wlerr("ERROR: Failed to alloc interrupt\n"); assert(0); return ; } up_disable_irq(irq); tmp = sizeof(struct irq_adpt); adapter = kmm_malloc(tmp); if (!adapter) { wlerr("ERROR: Failed to alloc %d memory\n", tmp); assert(0); return ; } adapter->func = f; adapter->arg = arg; tmp = n + XTENSA_IRQ_FIRSTPERIPH; ret = irq_attach(tmp, esp_int_adpt_cb, adapter); if (ret) { wlerr("ERROR: Failed to attach IRQ %d\n", tmp); assert(0); return ; } esp32_attach_peripheral(cpu, n, irq); s_wifi_irq = irq; } /**************************************************************************** * Name: esp32_ints_on * * Description: * Enable WiFi interrupt * * Input Parameters: * mask - No mean * * Returned Value: * None * ****************************************************************************/ static void esp32_ints_on(uint32_t mask) { up_enable_irq(s_wifi_irq); } /**************************************************************************** * Name: esp32_ints_on * * Description: * Disable WiFi interrupt * * Input Parameters: * mask - No mean * * Returned Value: * None * ****************************************************************************/ static void esp32_ints_off(uint32_t mask) { up_disable_irq(s_wifi_irq); } /**************************************************************************** * Name: esp_spin_lock_create * * Description: * Create spin lock in SMP mode * * Input Parameters: * None * * Returned Value: * Spin lock data pointer * ****************************************************************************/ static void *esp_spin_lock_create(void) { #ifdef CONFIG_SMP spinlock_t *lock; int tmp; tmp = sizeof(struct spinlock_t); lock = kmm_malloc(tmp); if (!lock) { wlerr("ERROR: Failed to alloc %d memory\n", tmp); DEBUGASSERT(0); } spin_initialize(lock, SP_UNLOCKED); return lock; #else /* If return NULL, code may check fail */ return (void *)1; #endif } /**************************************************************************** * Name: esp_spin_lock_delete * * Description: * Delete spin lock * * Input Parameters: * lock - Spin lock data pointer * * Returned Value: * None * ****************************************************************************/ static void esp_spin_lock_delete(void *lock) { #ifdef CONFIG_SMP kmm_free(lock); #else DEBUGASSERT((int)lock == 1); #endif } /**************************************************************************** * Name: esp_wifi_int_disable * * Description: * Enter critical by disable interrup, and take spin lock if * in SMP mode * * Input Parameters: * wifi_int_mux - Spin lock data pointer * * Returned Value: * CPU PS value. * ****************************************************************************/ static uint32_t IRAM_ATTR esp_wifi_int_disable(void *wifi_int_mux) { irqstate_t flags; flags = enter_critical_section(); #ifdef CONFIG_SMP spin_lock((volatile spinlock_t *)wifi_int_mux); #endif return (uint32_t)flags; } /**************************************************************************** * Name: esp_wifi_int_restore * * Description: * Exit from critical by enable interrup, and release spin * lock if in SMP mode * * Input Parameters: * wifi_int_mux - Spin lock data pointer * tmp - CPU PS value. * * Returned Value: * None * ****************************************************************************/ static void IRAM_ATTR esp_wifi_int_restore(void *wifi_int_mux, uint32_t tmp) { irqstate_t flags = (irqstate_t)tmp; #ifdef CONFIG_SMP spin_unlock((volatile spinlock_t *)wifi_int_mux); #endif leave_critical_section(flags); } /**************************************************************************** * Name: esp_task_yield_from_isr * * Description: * Do nothing in Nuttx * * Input Parameters: * None * * Returned Value: * None * ****************************************************************************/ static void IRAM_ATTR esp_task_yield_from_isr(void) { /* Do nothing */ } /**************************************************************************** * Name: esp_semphr_create * * Description: * Create and initialize semaphore * * Input Parameters: * max - No mean * init - semaphore initialization value * * Returned Value: * Semphore data pointer * ****************************************************************************/ static void *esp_semphr_create(uint32_t max, uint32_t init) { int ret; sem_t *sem; int tmp; tmp = sizeof(sem_t); sem = kmm_malloc(tmp); if (!sem) { wlerr("ERROR: Failed to alloc %d memory\n", tmp); return NULL; } ret = sem_init(sem, 0, init); if (ret) { wlerr("ERROR: Failed to initialize sem error=%d\n", ret); kmm_free(sem); return NULL; } return sem; } /**************************************************************************** * Name: esp_semphr_delete * * Description: * Delete semaphore * * Input Parameters: * semphr - Semphore data pointer * * Returned Value: * None * ****************************************************************************/ static void esp_semphr_delete(void *semphr) { sem_t *sem = (sem_t *)semphr; sem_destroy(sem); kmm_free(sem); } /**************************************************************************** * Name: esp_semphr_take * * Description: * Wait semaphore within a certain period of time * * Input Parameters: * semphr - Semphore data pointer * ticks - Wait system ticks * * Returned Value: * True if success or false if fail * ****************************************************************************/ static int32_t esp_semphr_take(void *semphr, uint32_t ticks) { int ret; struct timespec timeout; sem_t *sem = (sem_t *)semphr; if (ticks == OSI_FUNCS_TIME_BLOCKING) { ret = sem_wait(sem); if (ret) { wlerr("ERROR: Failed to wait sem\n"); } } else { ret = clock_gettime(CLOCK_REALTIME, &timeout); if (ret < 0) { wlerr("ERROR: Failed to get time\n"); return false; } if (ticks) { esp_update_time(&timeout, ticks); } ret = sem_timedwait(sem, &timeout); if (ret) { wlerr("ERROR: Failed to wait sem in %d ticks\n", ticks); } } return esp_errno_trans(ret); } /**************************************************************************** * Name: esp_semphr_give * * Description: * Post semaphore * * Input Parameters: * semphr - Semphore data pointer * * Returned Value: * True if success or false if fail * ****************************************************************************/ static int32_t esp_semphr_give(void *semphr) { int ret; sem_t *sem = (sem_t *)semphr; ret = sem_post(sem); if (ret) { wlerr("ERROR: Failed to post sem error=%d\n", ret); } return esp_errno_trans(ret); } /**************************************************************************** * Name: esp_thread_semphr_get * * Description: * Get thread self's semaphore * * Input Parameters: * None * * Returned Value: * Semphore data pointer * ****************************************************************************/ static void *esp_thread_semphr_get(void) { int ret; void *sem; if (s_wifi_tkey_init) { ret = pthread_key_create(&s_wifi_thread_key, esp_thread_semphr_free); if (ret) { wlerr("ERROR: Failed to create pthread key\n"); return NULL; } s_wifi_tkey_init = true; } sem = pthread_getspecific(s_wifi_thread_key); if (!sem) { sem = esp_semphr_create(1, 0); if (!sem) { wlerr("ERROR: Failed to create semaphore\n"); return NULL; } ret = pthread_setspecific(s_wifi_thread_key, sem); if (ret) { wlerr("ERROR: Failed to set specific\n"); esp_semphr_delete(sem); return NULL; } } return sem; } /**************************************************************************** * Name: esp_mutex_create * * Description: * Create mutex * * Input Parameters: * None * * Returned Value: * Mutex data pointer * ****************************************************************************/ static void *esp_mutex_create(void) { int ret; pthread_mutex_t *mutex; int tmp; tmp = sizeof(pthread_mutex_t); mutex = kmm_malloc(tmp); if (!mutex) { wlerr("ERROR: Failed to alloc %d memory\n", tmp); return NULL; } ret = pthread_mutex_init(mutex, NULL); if (ret) { wlerr("ERROR: Failed to initialize mutex error=%d\n", ret); kmm_free(mutex); return NULL; } return mutex; } /**************************************************************************** * Name: esp_recursive_mutex_create * * Description: * Create recursive mutex * * Input Parameters: * None * * Returned Value: * Recursive mutex data pointer * ****************************************************************************/ static void *esp_recursive_mutex_create(void) { int ret; pthread_mutex_t *mutex; pthread_mutexattr_t attr; int tmp; ret = pthread_mutexattr_init(&attr); if (ret) { wlerr("ERROR: Failed to initialize attr error=%d\n", ret); return NULL; } ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); if (ret) { wlerr("ERROR: Failed to set attr type error=%d\n", ret); return NULL; } tmp = sizeof(pthread_mutex_t); mutex = kmm_malloc(tmp); if (!mutex) { wlerr("ERROR: Failed to alloc %d memory\n", tmp); return NULL; } ret = pthread_mutex_init(mutex, &attr); if (ret) { wlerr("ERROR: Failed to initialize mutex error=%d\n", ret); kmm_free(mutex); return NULL; } return mutex; } /**************************************************************************** * Name: esp_mutex_delete * * Description: * Delete mutex * * Input Parameters: * mutex_data - mutex data pointer * * Returned Value: * None * ****************************************************************************/ static void esp_mutex_delete(void *mutex_data) { pthread_mutex_t *mutex = (pthread_mutex_t *)mutex_data; pthread_mutex_destroy(mutex); kmm_free(mutex); } /**************************************************************************** * Name: esp_mutex_lock * * Description: * Lock mutex * * Input Parameters: * mutex_data - mutex data pointer * * Returned Value: * True if success or false if fail * ****************************************************************************/ static int32_t esp_mutex_lock(void *mutex_data) { int ret; pthread_mutex_t *mutex = (pthread_mutex_t *)mutex_data; ret = pthread_mutex_lock(mutex); if (ret) { wlerr("ERROR: Failed to lock mutex error=%d\n", ret); } return esp_errno_trans(ret); } /**************************************************************************** * Name: esp_mutex_unlock * * Description: * Unlock mutex * * Input Parameters: * mutex_data - mutex data pointer * * Returned Value: * True if success or false if fail * ****************************************************************************/ static int32_t esp_mutex_unlock(void *mutex_data) { int ret; pthread_mutex_t *mutex = (pthread_mutex_t *)mutex_data; ret = pthread_mutex_unlock(mutex); if (ret) { wlerr("ERROR: Failed to unlock mutex error=%d\n", ret); } return esp_errno_trans(ret); } /**************************************************************************** * Name: esp_queue_create * * Description: * Create message queue * * Input Parameters: * queue_len - queue message number * item_size - message size * * Returned Value: * Message queue data pointer * ****************************************************************************/ static void *esp_queue_create(uint32_t queue_len, uint32_t item_size) { struct mq_attr attr; mqd_t mq; struct mq_adpt *mq_adpt; mq_adpt = kmm_malloc(sizeof(struct mq_adpt)); if (!mq_adpt) { wlerr("ERROR: Failed to malloc\n"); return NULL; } snprintf(mq_adpt->name, sizeof(mq_adpt->name), "/tmp/%X", mq_adpt); attr.mq_maxmsg = queue_len; attr.mq_msgsize = item_size; attr.mq_curmsgs = 0; attr.mq_flags = 0; mq = mq_open(mq_adpt->name, O_RDWR | O_CREAT, 0644, &attr); if (!mq) { wlerr("ERROR: Failed to create mqueue\n"); kmm_free(mq_adpt); return NULL; } mq_adpt->mq = mq; mq_adpt->msgsize = item_size; return (void *)mq_adpt; } /**************************************************************************** * Name: esp_queue_delete * * Description: * Delete message queue * * Input Parameters: * queue - Message queue data pointer * * Returned Value: * None * ****************************************************************************/ static void esp_queue_delete(void *queue) { struct mq_adpt *mq_adpt = (struct mq_adpt *)queue; mq_close(mq_adpt->mq); mq_unlink(mq_adpt->name); kmm_free(mq_adpt); } /**************************************************************************** * Name: esp_queue_send_generic * * 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 esp_queue_send_generic(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) { /** * WiFi 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 = nxmq_send(mq_adpt->mq, (const char *)item, mq_adpt->msgsize, prio); if (ret < 0) { wlerr("ERROR: Failed to send message to mqueue error=%d\n", ret); } } else { ret = clock_gettime(CLOCK_REALTIME, &timeout); if (ret < 0) { wlerr("ERROR: Failed to get time\n"); return false; } if (ticks) { esp_update_time(&timeout, ticks); } ret = mq_timedsend(mq_adpt->mq, (const char *)item, mq_adpt->msgsize, prio, &timeout); if (ret < 0) { wlerr("ERROR: Failed to timedsend message to mqueue error=%d\n", ret); } } return esp_errno_trans(ret); } /**************************************************************************** * Name: esp_queue_send * * 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 esp_queue_send(void *queue, void *item, uint32_t ticks) { return esp_queue_send_generic(queue, item, ticks, 0); } /**************************************************************************** * Name: esp_queue_send_from_isr * * 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 - No mean * * Returned Value: * True if success or false if fail * ****************************************************************************/ static int32_t esp_queue_send_from_isr(void *queue, void *item, void *hptw) { /* Force to set the value to be false */ *((int *)hptw) = false; return esp_queue_send_generic(queue, item, 0, 0); } /**************************************************************************** * Name: esp_queue_send_to_back * * 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 esp_queue_send_to_back(void *queue, void *item, uint32_t ticks) { return esp_queue_send_generic(queue, item, ticks, 0); } /**************************************************************************** * Name: esp_queue_send_from_isr * * 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 esp_queue_send_to_front(void *queue, void *item, uint32_t ticks) { return esp_queue_send_generic(queue, item, ticks, 1); } /**************************************************************************** * Name: esp_queue_recv * * 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 esp_queue_recv(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 = mq_receive(mq_adpt->mq, (char *)item, mq_adpt->msgsize, &prio); if (ret < 0) { wlerr("ERROR: Failed to receive from mqueue error=%d\n", ret); } } else { ret = clock_gettime(CLOCK_REALTIME, &timeout); if (ret < 0) { wlerr("ERROR: Failed to get time\n"); return false; } if (ticks) { esp_update_time(&timeout, ticks); } ret = mq_timedreceive(mq_adpt->mq, (char *)item, mq_adpt->msgsize, &prio, &timeout); if (ret < 0) { wlerr("ERROR: Failed to timedreceive from mqueue error=%d\n", ret); } } return ret > 0 ? true : false; } /**************************************************************************** * Name: esp_queue_msg_waiting * * Description: * Get message number in the message queue * * Input Parameters: * queue - Message queue data pointer * * Returned Value: * Message number * ****************************************************************************/ static uint32_t esp_queue_msg_waiting(void *queue) { int ret; struct mq_attr attr; struct mq_adpt *mq_adpt = (struct mq_adpt *)queue; ret = mq_getattr(mq_adpt->mq, &attr); if (ret < 0) { wlerr("ERROR: Failed to get attr from mqueue error=%d\n", ret); return 0; } return attr.mq_curmsgs; } /**************************************************************************** * Name: esp_event_group_create * * Description: * Don't support * ****************************************************************************/ static void *esp_event_group_create(void) { DEBUGASSERT(0); return NULL; } /**************************************************************************** * Name: esp_event_group_delete * * Description: * Don't support * ****************************************************************************/ static void esp_event_group_delete(void *event) { DEBUGASSERT(0); } /**************************************************************************** * Name: esp_event_group_set_bits * * Description: * Don't support * ****************************************************************************/ static uint32_t esp_event_group_set_bits(void *event, uint32_t bits) { DEBUGASSERT(0); return false; } /**************************************************************************** * Name: esp_event_group_clear_bits * * Description: * Don't support * ****************************************************************************/ static uint32_t esp_event_group_clear_bits(void *event, uint32_t bits) { DEBUGASSERT(0); return false; } /**************************************************************************** * Name: esp_event_group_wait_bits * * Description: * Don't support * ****************************************************************************/ static uint32_t esp_event_group_wait_bits(void *event, uint32_t bits_to_wait_for, int32_t clear_on_exit, int32_t wait_for_all_bits, uint32_t block_time_tick) { DEBUGASSERT(0); return false; } /**************************************************************************** * Name: esp_task_create_pinned_to_core * * 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 esp_task_create_pinned_to_core(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 pid = kthread_create(name, prio, stack_depth, entry, (char * const *)param); if (pid > 0) { *((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("ERROR: Failed to set affinity error=%d\n", ret); return false; } } #endif } else { wlerr("ERROR: Failed to create task\n"); } return pid > 0 ? true : false; } /**************************************************************************** * Name: esp_task_create * * 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 esp_task_create(void *entry, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle) { return esp_task_create_pinned_to_core(entry, name, stack_depth, param, prio, task_handle, UINT32_MAX); } /**************************************************************************** * Name: esp_task_delete * * 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 esp_task_delete(void *task_handle) { pid_t pid = (pid_t)((uintptr_t)task_handle); kthread_delete(pid); } /**************************************************************************** * Name: esp_task_delay * * Description: * Current task wait for some ticks * * Input Parameters: * tick - Waiting ticks * * Returned Value: * None * ****************************************************************************/ static void esp_task_delay(uint32_t tick) { useconds_t us = TICK2USEC(tick); usleep(us); } /**************************************************************************** * Name: esp_task_ms_to_tick * * Description: * Transform from millim seconds to system ticks * * Input Parameters: * ms - Millim seconds * * Returned Value: * System ticks * ****************************************************************************/ static int32_t esp_task_ms_to_tick(uint32_t ms) { return MSEC2TICK(ms); } /**************************************************************************** * Name: esp_task_get_current_task * * Description: * Transform from millim seconds to system ticks * * Input Parameters: * ms - Millim seconds * * Returned Value: * System ticks * ****************************************************************************/ static void *esp_task_get_current_task(void) { pid_t pid = getpid(); return (void *)((uintptr_t)pid); } /**************************************************************************** * Name: esp_task_get_current_task * * Description: * Get OS task maxium priority * * Input Parameters: * None * * Returned Value: * Task maxium priority * ****************************************************************************/ static int32_t esp_task_get_max_priority(void) { return SCHED_PRIORITY_MAX; } /**************************************************************************** * Name: esp_malloc_internal * * Description: * Allocate a block of memory * * Input Parameters: * size - memory size * * Returned Value: * Memory pointer * ****************************************************************************/ static void *esp_malloc(uint32_t size) { return malloc(size); } /**************************************************************************** * Name: esp_event_id_map * * Description: * Transform from esp-idf event ID to WiFi adapter event ID * * Input Parameters: * event_id - esp-idf event ID * * Returned Value: * WiFi adapter event ID * ****************************************************************************/ static int esp_event_id_map(int event_id) { int id; switch (event_id) { 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; 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(FAR void *arg) { int ret; irqstate_t flags; struct evt_adpt *evt_adpt; struct wifi_notify *notify; while (1) { flags = enter_critical_section(); evt_adpt = (struct evt_adpt *)sq_remfirst(&s_wifi_evt_queue); leave_critical_section(flags); if (!evt_adpt) { break; } switch (evt_adpt->id) { case WIFI_ADPT_EVT_STA_START: ret = esp_wifi_connect(); if (ret) { wlerr("ERROR: Failed to connect\n"); } break; case WIFI_ADPT_EVT_STA_CONNECT: s_connected = true; ret = sem_post(&s_connect_sem); if (ret) { wlerr("ERROR: Failed to post sem error=%d\n", errno); } break; case WIFI_ADPT_EVT_STA_DISCONNECT: s_connected = false; ret = esp_wifi_connect(); if (ret) { wlerr("ERROR: Failed to connect\n"); } break; default: break; } notify = &s_wifi_notify[evt_adpt->id]; if (notify->assigned) { notify->event.sigev_value.sival_ptr = evt_adpt->buf; ret = nxsig_notification(notify->pid, ¬ify->event, SI_QUEUE, ¬ify->work); if (ret < 0) { wlwarn("ERROR: nxsig_notification event ID=%d failed: %d\n", evt_adpt->id, ret); } } free(evt_adpt); } } /**************************************************************************** * Name: esp_event_post * * 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(esp_event_base_t 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=%d data=%p data_size=%d ticks=%u\n", event_base, event_id, event_data, event_data_size, ticks); id = esp_event_id_map(event_id); if (id < 0) { wlerr("ERROR: No process event %d\n", event_id); return -1; } size = event_data_size + sizeof(struct evt_adpt); evt_adpt = malloc(size); if (!evt_adpt) { wlerr("ERROR: Failed to alloc %d memory\n", size); return -1; } evt_adpt->id = id; memcpy(evt_adpt->buf, event_data, event_data_size); flags = enter_critical_section(); sq_addlast(&evt_adpt->entry, &s_wifi_evt_queue); leave_critical_section(flags); work_queue(LPWORK, &s_wifi_evt_work, esp_evt_work_cb, NULL, 0); return 0; } /**************************************************************************** * Name: esp_task_get_current_task * * Description: * Get free heap size by byte * * Input Parameters: * None * * Returned Value: * Free heap size * ****************************************************************************/ uint32_t esp_get_free_heap_size(void) { int ret; struct mallinfo info; ret = mm_mallinfo(&g_mmheap, &info); if (ret) { wlerr("ERROR: Failed to create task\n"); return 0; } return info.fordblks; } /**************************************************************************** * Name: esp_dport_access_stall_other_cpu_start * * Description: * Don't support * ****************************************************************************/ static void esp_dport_access_stall_other_cpu_start(void) { #ifdef CONFIG_SMP DEBUGASSERT(0); #endif } /**************************************************************************** * Name: esp_dport_access_stall_other_cpu_end * * Description: * Don't support * ****************************************************************************/ static void esp_dport_access_stall_other_cpu_end(void) { #ifdef CONFIG_SMP DEBUGASSERT(0); #endif } /**************************************************************************** * Name: esp_phy_rf_init * * Description: * Initialize PHY hardware with given parameters * * Input Parameters: * init_data - PHY hardware initialization parameters * mode - PHY RF calculation mode * calibration_data - PHY RF calculation parameters * module - PHY mode which is to be initialized * * Returned Value: * 0 if success or -1 if fail * ****************************************************************************/ int32_t esp_phy_rf_init(const esp_phy_init_data_t *init_data, esp_phy_calibration_mode_t mode, esp_phy_calibration_data_t *calibration_data, phy_rf_module_t module) { irqstate_t flags; int64_t time; bool enable = false; if (module >= PHY_MODULE_COUNT) { return -1; } flags = enter_critical_section(); s_esp32_phy_init_mask |= 1 << module; if (s_esp23_phy_en) { leave_critical_section(flags); return 0; } if (module == PHY_MODEM_MODULE) { if (s_esp32_phy_init_mask & PHY_RF_MASK) { enable = true; } } else if (module == PHY_WIFI_MODULE || module == PHY_BT_MODULE) { enable = true; } if (enable) { if (s_esp32_phy_rf_stop_tm) { time = esp_timer_get_time() - s_esp32_phy_rf_stop_tm; esp_wifi_internal_update_mac_time((uint32_t)time); s_esp32_phy_rf_stop_tm = 0; } esp_phy_enable_clock(); phy_set_wifi_mode_only(0); register_chipv7_phy(init_data, calibration_data, mode); s_esp23_phy_en = true; } leave_critical_section(flags); return 0; } /**************************************************************************** * Name: esp_phy_deinit_rf * * Description: * Deinitialize PHY hardware * * Input Parameters: * module - PHY mode which is to be deinitialized * * Returned Value: * 0 if success or -1 if fail * ****************************************************************************/ static int32_t esp_phy_deinit_rf(uint32_t module) { irqstate_t flags; bool disable = false; if (module >= PHY_MODULE_COUNT) { return -1; } flags = enter_critical_section(); s_esp32_phy_init_mask |= ~(1 << module); if (!s_esp23_phy_en) { leave_critical_section(flags); return 0; } if (module == PHY_MODEM_MODULE) { disable = true; } else if (module == PHY_WIFI_MODULE || module == PHY_BT_MODULE) { if (!(s_esp32_phy_init_mask & PHY_RF_MASK)) { disable = true; } } if (disable) { phy_close_rf(); s_esp32_phy_rf_stop_tm = esp_timer_get_time(); esp_phy_disable_clock(); s_esp23_phy_en = false; } leave_critical_section(flags); return 0; } /**************************************************************************** * Name: esp_phy_init * * Description: * Initialize PHY hardware * * Input Parameters: * module - PHY mode which is to be initialized * * Returned Value: * None * ****************************************************************************/ static void esp_phy_init(uint32_t module) { int ret; esp_phy_calibration_data_t *cal_data; cal_data = kmm_zalloc(sizeof(esp_phy_calibration_data_t)); if (!cal_data) { wlerr("ERROR: Failed to malloc"); DEBUGASSERT(0); } ret = esp_phy_rf_init(&phy_init_data, PHY_RF_CAL_FULL, cal_data, module); if (ret) { wlerr("ERROR: Failed to initialize RF"); DEBUGASSERT(0); } kmm_free(cal_data); } /**************************************************************************** * Name: esp_phy_enable_clock * * Description: * Enable PHY hardware clock * * Input Parameters: * None * * Returned Value: * None * ****************************************************************************/ void esp_phy_enable_clock(void) { irqstate_t flags; flags = enter_critical_section(); if (s_phy_clk_en_cnt == 0) { modifyreg32(DPORT_WIFI_CLK_EN_REG, 0, DPORT_WIFI_CLK_WIFI_BT_COMMON_M); } s_phy_clk_en_cnt++; leave_critical_section(flags); } /**************************************************************************** * Name: esp_phy_disable_clock * * Description: * Disable PHY hardware clock * * Input Parameters: * None * * Returned Value: * None * ****************************************************************************/ void esp_phy_disable_clock(void) { irqstate_t flags; flags = enter_critical_section(); if (s_phy_clk_en_cnt) { s_phy_clk_en_cnt--; if (!s_phy_clk_en_cnt) { modifyreg32(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_WIFI_BT_COMMON_M, 0); } } leave_critical_section(flags); } /**************************************************************************** * Name: esp_read_mac * * 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 * ****************************************************************************/ int32_t esp_read_mac(uint8_t *mac, esp_mac_type_t type) { uint32_t regval[2]; uint8_t tmp; uint8_t *data = (uint8_t *)regval; uint8_t crc; int i; if (type > ESP_MAC_WIFI_SOFTAP) { wlerr("ERROR: Input type is error=%d\n", type); return -1; } regval[0] = getreg32(MAC_ADDR0_REG); regval[1] = getreg32(MAC_ADDR1_REG); crc = data[6]; for (i = 0; i < 6; i++) { mac[i] = data[5 - i]; } if (crc != esp_crc8(mac, 6)) { wlerr("ERROR: Failed to check MAC address CRC\n"); return -1; } if (type == ESP_MAC_WIFI_SOFTAP) { tmp = mac[0]; for (i = 0; i < 64; i++) { mac[0] = tmp | 0x02; mac[0] ^= i << 2; if (mac[0] != tmp) { break; } } if (i >= 64) { wlerr("ERROR: Failed to generate softAP MAC\n"); return -1; } } return 0; } /**************************************************************************** * Name: esp_wifi_read_mac * * 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 int32_t esp_wifi_read_mac(uint8_t *mac, uint32_t type) { return esp_read_mac(mac, type); } /**************************************************************************** * Name: esp_timer_arm * * 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 esp_timer_arm(void *ptimer, uint32_t ms, bool repeat) { esp_timer_arm_us(ptimer, ms * 1000, repeat); } /**************************************************************************** * Name: esp_timer_disarm * * Description: * Disable timer * * Input Parameters: * ptimer - timer data pointer * * Returned Value: * None * ****************************************************************************/ static void esp_timer_disarm(void *ptimer) { struct timer_adpt *timer_adpt; struct ets_timer *ets_timer = (struct ets_timer *)ptimer; if (ets_timer->priv) { timer_adpt = (struct timer_adpt *)ets_timer->priv; wd_cancel(&timer_adpt->wdog); work_cancel(LPWORK, &timer_adpt->work); } } /**************************************************************************** * Name: esp32_timer_done * * Description: * Disable and free timer * * Input Parameters: * ptimer - timer data pointer * * Returned Value: * None * ****************************************************************************/ static void esp32_timer_done(void *ptimer) { struct timer_adpt *timer_adpt; struct ets_timer *ets_timer = (struct ets_timer *)ptimer; if (ets_timer->priv) { timer_adpt = (struct timer_adpt *)ets_timer->priv; wd_cancel(&timer_adpt->wdog); work_cancel(LPWORK, &timer_adpt->work); kmm_free(timer_adpt); ets_timer->priv = NULL; } } /**************************************************************************** * Name: esp_timer_setfn * * Description: * Set timer callback function and private data * * Input Parameters: * ptimer - Timer data pointer * pfunction - Callback function * parg - Callback function private data * * Returned Value: * None * ****************************************************************************/ static void esp_timer_setfn(void *ptimer, void *pfunction, void *parg) { struct timer_adpt *timer_adpt; struct ets_timer *ets_timer = (struct ets_timer *)ptimer; if (ets_timer->priv) { return ; } timer_adpt = kmm_zalloc(sizeof(struct timer_adpt)); if (!timer_adpt) { wlerr("ERROR: Failed to malloc\n"); return ; } timer_adpt->func = pfunction; timer_adpt->priv = parg; ets_timer->priv = timer_adpt; } /**************************************************************************** * Name: esp_timer_work_cb * * Description: * Process timer callback function in workqueue and active * it if it has repeat flag * * Input Parameters: * arg - Timer data pointer * * Returned Value: * None * ****************************************************************************/ static void esp_timer_work_cb(FAR void *arg) { struct ets_timer *ets_timer = (struct ets_timer *)arg; struct timer_adpt *timer_adpt = (struct timer_adpt *)ets_timer->priv; timer_adpt->func(timer_adpt->priv); if (timer_adpt->repeat) { wd_start(&timer_adpt->wdog, timer_adpt->delay, esp_timer_cb, (wdparm_t)ets_timer); } } /**************************************************************************** * Name: esp_timer_cb * * Description: * Post event to work queue and let work queue to process the timer's * real callback function * * Input Parameters: * parm - Timer data pointer * * Returned Value: * None * ****************************************************************************/ static void esp_timer_cb(wdparm_t parm) { struct ets_timer *ets_timer = (struct ets_timer *)parm; struct timer_adpt *timer_adpt = (struct timer_adpt *)ets_timer->priv; work_queue(LPWORK, &timer_adpt->work, esp_timer_work_cb, ets_timer, 0); } /**************************************************************************** * Name: esp_timer_arm_us * * Description: * Set timer timeout period and repeat flag * * Input Parameters: * ptimer - timer data pointer * us - micro seconds * repeat - true: run cycle, false: run once * * Returned Value: * None * ****************************************************************************/ static void esp_timer_arm_us(void *ptimer, uint32_t us, bool repeat) { uint32_t delay; struct timer_adpt *timer_adpt; struct ets_timer *ets_timer = (struct ets_timer *)ptimer; if (ets_timer->priv) { timer_adpt = (struct timer_adpt *)ets_timer->priv; wd_cancel(&timer_adpt->wdog); work_cancel(LPWORK, &timer_adpt->work); delay = USEC2TICK(us); timer_adpt->repeat = (uint32_t)repeat; timer_adpt->delay = delay; wd_start(&timer_adpt->wdog, delay, esp_timer_cb, (wdparm_t)ets_timer); } } /**************************************************************************** * Name: esp_periph_module_enable * * Description: * Enable WiFi module clock * * Input Parameters: * periph - No mean * * Returned Value: * None * ****************************************************************************/ static void esp_periph_module_enable(uint32_t periph) { modifyreg32(DPORT_WIFI_CLK_EN_REG, 0, DPORT_WIFI_CLK_WIFI_EN_M); } /**************************************************************************** * Name: esp_periph_module_enable * * Description: * Disable WiFi module clock * * Input Parameters: * periph - No mean * * Returned Value: * None * ****************************************************************************/ static void esp_periph_module_disable(uint32_t periph) { modifyreg32(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_WIFI_EN_M, 0); } /**************************************************************************** * Name: esp_timer_get_time * * Description: * Get system time of type int64_t * * Input Parameters: * periph - No mean * * Returned Value: * System time * ****************************************************************************/ int64_t esp_timer_get_time(void) { int64_t us; struct timeval tv; int ret; ret = gettimeofday(&tv, NULL); if (!ret) { us = tv.tv_sec * (1000 * 1000) + tv.tv_usec; } else { us = 0; wlerr("ERROR: Failed to get time of day\n"); } return us; } /**************************************************************************** * 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 int32_t esp_nvs_set_i8(uint32_t handle, const char *key, int8_t value) { #ifdef CONFIG_ESP32_WIFI_SAVE_PARAM return esp_nvs_set_blob(handle, key, &value, sizeof(int8_t)); #else DEBUGASSERT(0); return -1; #endif } /**************************************************************************** * 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 int32_t esp_nvs_get_i8(uint32_t handle, const char *key, int8_t *out_value) { #ifdef CONFIG_ESP32_WIFI_SAVE_PARAM size_t len = sizeof(int8_t); return esp_nvs_get_blob(handle, key, out_value, &len); #else DEBUGASSERT(0); return -1; #endif } /**************************************************************************** * 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 int32_t esp_nvs_set_u8(uint32_t handle, const char *key, uint8_t value) { #ifdef CONFIG_ESP32_WIFI_SAVE_PARAM return esp_nvs_set_blob(handle, key, &value, sizeof(uint8_t)); #else DEBUGASSERT(0); return -1; #endif } /**************************************************************************** * 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 int32_t esp_nvs_get_u8(uint32_t handle, const char *key, uint8_t *out_value) { #ifdef CONFIG_ESP32_WIFI_SAVE_PARAM size_t len = sizeof(uint8_t); return esp_nvs_get_blob(handle, key, out_value, &len); #else DEBUGASSERT(0); return -1; #endif } /**************************************************************************** * 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 int32_t esp_nvs_set_u16(uint32_t handle, const char *key, uint16_t value) { #ifdef CONFIG_ESP32_WIFI_SAVE_PARAM return esp_nvs_set_blob(handle, key, &value, sizeof(uint16_t)); #else DEBUGASSERT(0); return -1; #endif } /**************************************************************************** * 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 int32_t esp_nvs_get_u16(uint32_t handle, const char *key, uint16_t *out_value) { #ifdef CONFIG_ESP32_WIFI_SAVE_PARAM size_t len = sizeof(uint16_t); return esp_nvs_get_blob(handle, key, out_value, &len); #else DEBUGASSERT(0); return -1; #endif } /**************************************************************************** * Name: esp_nvs_open * * 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 int32_t esp_nvs_open(const char *name, uint32_t open_mode, uint32_t *out_handle) { #ifdef CONFIG_ESP32_WIFI_SAVE_PARAM int ret; struct nvs_adpt *nvs_adpt; int tmp; char *index_name; tmp = sizeof(struct nvs_adpt); nvs_adpt = kmm_malloc(tmp); if (!nvs_adpt) { wlerr("ERROR: Failed to alloc %d memory\n", tmp); return -1; } ret = asprintf(&index_name, "%s", name); if (ret < 0) { wlerr("ERROR: Failed to create NVS index_name string\n"); kmm_free(nvs_adpt); return -1; } nvs_adpt->index_name = index_name; *out_handle = (uint32_t)nvs_adpt; return 0; #else DEBUGASSERT(0); return -1; #endif } /**************************************************************************** * 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) { #ifdef CONFIG_ESP32_WIFI_SAVE_PARAM struct nvs_adpt *nvs_adpt = (struct nvs_adpt *)handle; kmm_free(nvs_adpt->index_name); kmm_free(nvs_adpt); #else DEBUGASSERT(0); #endif } /**************************************************************************** * Name: esp_nvs_commit * * Description: * This function has no practical effect * ****************************************************************************/ static int32_t esp_nvs_commit(uint32_t handle) { return 0; } /**************************************************************************** * 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 int32_t esp_nvs_set_blob(uint32_t handle, const char *key, const void *value, size_t length) { #ifdef CONFIG_ESP32_WIFI_SAVE_PARAM int fd; int ret; char *dir; struct nvs_adpt *nvs_adpt = (struct nvs_adpt *)handle; char *index_name = nvs_adpt->index_name; ret = asprintf(&dir, NVS_DIR_BASE"%s.%s", index_name, key); if (ret < 0) { wlerr("ERROR: Failed to create NVS dir string\n"); return -1; } ret = unlink(dir); if (ret) { if (errno != ENOENT) { wlerr("ERROR: Failed to unlink %s error=%d\n", dir, errno); free(dir); return -1; } } fd = open(dir, O_WRONLY | O_CREAT, NVS_FILE_MODE); if (fd < 0) { wlerr("ERROR: Failed to set open %s\n", dir); free(dir); return -1; } ret = write(fd, value, length); if (ret < 0) { wlerr("ERROR: Failed to write to %s\n", dir); free(dir); close(fd); return -1; } free(dir); close(fd); return 0; #else DEBUGASSERT(0); return -1; #endif } /**************************************************************************** * 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 int32_t esp_nvs_get_blob(uint32_t handle, const char *key, void *out_value, size_t *length) { #ifdef CONFIG_ESP32_WIFI_SAVE_PARAM int fd; int ret; char *dir; struct nvs_adpt *nvs_adpt = (struct nvs_adpt *)handle; char *index_name = nvs_adpt->index_name; ret = asprintf(&dir, NVS_DIR_BASE"%s.%s", index_name, key); if (ret < 0) { wlerr("ERROR: Failed to create NVS dir string\n"); return -1; } fd = open(dir, O_RDONLY, NVS_FILE_MODE); if (fd < 0) { free(dir); if (errno == ENOENT) { wlinfo("INFO: No file %s\n", dir); return ESP_ERR_NVS_NOT_FOUND; } wlerr("ERROR: Failed to get open %s\n", dir); return -1; } ret = read(fd, out_value, *length); if (ret <= 0) { wlerr("ERROR: Failed to write to %s\n", dir); free(dir); close(fd); return -1; } else { *length = ret; } free(dir); close(fd); return 0; #else DEBUGASSERT(0); return -1; #endif } /**************************************************************************** * 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 int32_t esp_nvs_erase_key(uint32_t handle, const char *key) { #ifdef CONFIG_ESP32_WIFI_SAVE_PARAM int ret; char *dir; struct nvs_adpt *nvs_adpt = (struct nvs_adpt *)handle; char *index_name = nvs_adpt->index_name; ret = asprintf(&dir, NVS_DIR_BASE"%s.%s", index_name, key); if (ret < 0) { wlerr("ERROR: Failed to create NVS dir string\n"); return -1; } ret = unlink(dir); if (ret < 0) { wlerr("ERROR: Failed to delete NVS file %s\n", dir); free(dir); return -1; } free(dir); return 0; #else DEBUGASSERT(0); return -1; #endif } /**************************************************************************** * Name: esp_fill_random * * Description: * Fill random data int given buffer of given length * * Input Parameters: * buf - buffer pointer * len - buffer length * * Returned Value: * ****************************************************************************/ void esp_fill_random(void *buf, size_t len) { uint8_t *p = (uint8_t *)buf; uint32_t tmp; uint32_t n; while (len > 0) { tmp = random(); n = len < 4 ? len : 4; memcpy(p, &tmp, n); p += n; len -= n; } } /**************************************************************************** * Name: esp_get_random * * Description: * Fill random data int given buffer of given length * * Input Parameters: * buf - buffer pointer * len - buffer length * * Returned Value: * 0 if success or -1 if fail * ****************************************************************************/ static int32_t esp_get_random(uint8_t *buf, size_t len) { esp_fill_random(buf, len); return 0; } /**************************************************************************** * Name: esp_get_time * * Description: * Get std C time * * Input Parameters: * t - buffer to store time of type timeval * * Returned Value: * 0 if success or -1 if fail * ****************************************************************************/ static int32_t esp_get_time(void *t) { int ret; struct timeval tv; struct time_adpt *time_adpt = (struct time_adpt *)t; ret = gettimeofday(&tv, NULL); if (!ret) { time_adpt->sec = (time_t)tv.tv_sec; time_adpt->usec = (suseconds_t)tv.tv_usec; } else { wlerr("ERROR: Failed to get time of day\n"); } return ret; } /**************************************************************************** * Name: esp_rand * * Description: * Get random data of type uint32_t * * Input Parameters: * None * * Returned Value: * Random data * ****************************************************************************/ static uint32_t esp_rand(void) { return esp_random(); } /**************************************************************************** * Name: esp_log_writev * * 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(uint32_t level, const char *tag, const char *format, va_list args) { int pri; switch (level) { case ESP_LOG_ERROR: pri = LOG_ERR; break; case ESP_LOG_WARN: pri = LOG_WARNING; break; case ESP_LOG_INFO: pri = LOG_INFO; break; default: pri = LOG_DEBUG; break; } vsyslog(pri, format, args); } /**************************************************************************** * Name: esp_log_write * * 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 * ****************************************************************************/ void esp_log_write(uint32_t level, const char *tag, const char *format, ...) { va_list list; va_start(list, format); esp_log_writev(level, tag, format, list); va_end(list); } /**************************************************************************** * Name: esp_log_timestamp * * Description: * Get system time by millim second * * Input Parameters: * None * * Returned Value: * System time * ****************************************************************************/ uint32_t esp_log_timestamp(void) { return (uint32_t)(esp_timer_get_time() / 1000); } /**************************************************************************** * Name: esp_malloc_internal * * Description: * Drivers allocate a block of memory * * Input Parameters: * size - memory size * * Returned Value: * Memory pointer * ****************************************************************************/ static void *esp_malloc_internal(size_t size) { return kmm_malloc(size); } /**************************************************************************** * Name: esp_realloc_internal * * 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 void *esp_realloc_internal(void *ptr, size_t size) { return kmm_realloc(ptr, size); } /**************************************************************************** * Name: esp_calloc_internal * * Description: * Drivers allocate some continuous blocks of memory * * Input Parameters: * n - memory block number * size - memory block size * * Returned Value: * New memory pointer * ****************************************************************************/ static void *esp_calloc_internal(size_t n, size_t size) { return kmm_calloc(n, size); } /**************************************************************************** * Name: esp_zalloc_internal * * Description: * Drivers allocate a block of memory and clear it with 0 * * Input Parameters: * size - memory size * * Returned Value: * New memory pointer * ****************************************************************************/ static void *esp_zalloc_internal(size_t size) { return kmm_zalloc(size); } /**************************************************************************** * Name: esp_malloc_internal * * Description: * Applications allocate a block of memory * * Input Parameters: * size - memory size * * Returned Value: * Memory pointer * ****************************************************************************/ static void *esp_wifi_malloc(size_t size) { return malloc(size); } /**************************************************************************** * Name: esp_realloc_internal * * 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 * ****************************************************************************/ static void *esp_wifi_realloc(void *ptr, size_t size) { return realloc(ptr, size); } /**************************************************************************** * Name: esp_calloc_internal * * Description: * Applications allocate some continuous blocks of memory * * Input Parameters: * n - memory block number * size - memory block size * * Returned Value: * New memory pointer * ****************************************************************************/ static void *esp_wifi_calloc(size_t n, size_t size) { return calloc(n, size); } /**************************************************************************** * Name: esp_zalloc_internal * * Description: * Applications allocate a block of memory and clear it with 0 * * Input Parameters: * size - memory size * * Returned Value: * New memory pointer * ****************************************************************************/ static void *esp_wifi_zalloc(size_t size) { return zalloc(size); } /**************************************************************************** * Name: esp_wifi_create_queue * * Description: * Create WiFi static message queue * * Input Parameters: * queue_len - queue message number * item_size - message size * * Returned Value: * WiFi static message queue data pointer * ****************************************************************************/ static void *esp_wifi_create_queue(int32_t queue_len, int32_t item_size) { wifi_static_queue_t *wifi_queue; wifi_queue = kmm_malloc(sizeof(wifi_static_queue_t)); if (!wifi_queue) { wlerr("ERROR: Failed to malloc\n"); return NULL; } wifi_queue->handle = esp_queue_create(queue_len, item_size); if (!wifi_queue->handle) { wlerr("ERROR: Failed to create queue\n"); kmm_free(wifi_queue); return NULL; } return wifi_queue; } /**************************************************************************** * Name: esp_wifi_delete_queue * * Description: * Delete WiFi static message queue * * Input Parameters: * queue - WiFi static message queue data pointer * * Returned Value: * None * ****************************************************************************/ static void esp_wifi_delete_queue(void *queue) { wifi_static_queue_t *wifi_queue = (wifi_static_queue_t *)queue; esp_queue_delete(wifi_queue->handle); kmm_free(wifi_queue); } /**************************************************************************** * Name: esp_modem_enter_sleep * * Description: * Let given module to enter sleep mode * * Input Parameters: * module - hardware module ID * * Returned Value: * 0 if success or -1 if fail * ****************************************************************************/ static int32_t esp_modem_enter_sleep(uint32_t module) { int ret = 0; irqstate_t flags; uint32_t bit; if (module >= (uint32_t)MODEM_MODULE_COUNT) { return -1; } bit = 1 << module; if (!(s_esp32_module_mask & bit)) { return -1; } flags = enter_critical_section(); s_esp32_module_sleep |= bit; if (!s_esp32_sleep && (s_esp32_module_sleep == s_esp32_module_mask)) { ret = esp_phy_deinit_rf(PHY_MODEM_MODULE); if (ret) { wlerr("ERROR: Failed to close RF\n"); } else { s_esp32_sleep = true; } } leave_critical_section(flags); return ret; } /**************************************************************************** * Name: esp_modem_enter_sleep * * Description: * Let given module to exit from sleep mode * * Input Parameters: * module - hardware module ID * * Returned Value: * 0 if success or -1 if fail * ****************************************************************************/ static int32_t esp_modem_exit_sleep(uint32_t module) { int ret = 0; irqstate_t flags; uint32_t bit; if (module >= (uint32_t)MODEM_MODULE_COUNT) { return -1; } bit = 1 << module; if (!(s_esp32_module_mask & bit)) { return -1; } flags = enter_critical_section(); s_esp32_module_sleep &= ~bit; if (s_esp32_sleep) { ret = esp_phy_rf_init(NULL, PHY_RF_CAL_NONE, NULL, PHY_MODEM_MODULE); if (ret) { wlerr("ERROR: Failed to open RF\n"); } else { s_esp32_sleep = false; } } leave_critical_section(flags); return ret; } /**************************************************************************** * Name: esp_modem_register_sleep * * Description: * Regitser given module so that it can enter sleep mode * * Input Parameters: * module - hardware module ID * * Returned Value: * 0 if success or -1 if fail * ****************************************************************************/ static int32_t esp_modem_register_sleep(uint32_t module) { irqstate_t flags; uint32_t bit; if (module >= (uint32_t)MODEM_MODULE_COUNT) { return -1; } bit = 1 << module; flags = enter_critical_section(); if (s_esp32_module_mask & bit) { /* Has registered and return success */ return 0; } s_esp32_module_mask |= bit; s_esp32_module_sleep |= bit; leave_critical_section(flags); return 0; } /**************************************************************************** * Name: esp_modem_deregister_sleep * * Description: * Deregitser given module so that it can't enter sleep mode * * Input Parameters: * module - hardware module ID * * Returned Value: * 0 if success or -1 if fail * ****************************************************************************/ static int32_t esp_modem_deregister_sleep(uint32_t module) { int ret; irqstate_t flags; uint32_t bit; if (module >= (uint32_t)MODEM_MODULE_COUNT) { return -1; } bit = 1 << module; flags = enter_critical_section(); if (!(s_esp32_module_mask & bit)) { /* Has deregistered and return success */ return 0; } s_esp32_module_mask &= ~bit; s_esp32_module_sleep &= ~bit; if (!s_esp32_module_mask) { s_esp32_module_mask = 0; if (s_esp32_sleep) { s_esp32_sleep = false; ret = esp_phy_rf_init(NULL, PHY_RF_CAL_NONE, NULL, PHY_MODEM_MODULE); if (ret) { wlerr("ERROR: Failed to open RF\n"); } } } leave_critical_section(flags); return 0; } /**************************************************************************** * Name: esp_coex_status_get * * Description: * Don't support * ****************************************************************************/ static uint32_t esp_coex_status_get(void) { return 0; } /**************************************************************************** * Name: esp_coex_condition_set * * Description: * Don't support * ****************************************************************************/ static void esp_coex_condition_set(uint32_t type, bool dissatisfy) { } /**************************************************************************** * Name: esp_coex_wifi_request * * Description: * Don't support * ****************************************************************************/ static int32_t esp_coex_wifi_request(uint32_t event, uint32_t latency, uint32_t duration) { return 0; } /**************************************************************************** * Name: esp_coex_wifi_release * * Description: * Don't support * ****************************************************************************/ static int32_t esp_coex_wifi_release(uint32_t event) { return 0; } /**************************************************************************** * Functions needed by libphy.a ****************************************************************************/ /**************************************************************************** * Name: esp_dport_access_reg_read * * Description: * Read regitser value safely in SMP * * Input Parameters: * reg - Regitser address * * Returned Value: * Regitser value * ****************************************************************************/ uint32_t IRAM_ATTR esp_dport_access_reg_read(uint32_t reg) { #ifdef CONFIG_SMP DEBUGASSERT(0); #else return getreg32(reg); #endif } /**************************************************************************** * Name: phy_enter_critical * * Description: * Enter critical state * * Input Parameters: * None * * Returned Value: * CPU PS value * ****************************************************************************/ uint32_t IRAM_ATTR phy_enter_critical(void) { irqstate_t flags; flags = enter_critical_section(); return flags; } /**************************************************************************** * Name: phy_exit_critical * * Description: * Exit from critical state * * Input Parameters: * level - CPU PS value * * Returned Value: * None * ****************************************************************************/ void IRAM_ATTR phy_exit_critical(uint32_t level) { leave_critical_section(level); } /**************************************************************************** * Name: phy_printf * * Description: * Output format string and its arguments * * Input Parameters: * format - format string * * Returned Value: * 0 * ****************************************************************************/ int phy_printf(const char *format, ...) { va_list arg; va_start(arg, format); wlinfo(format, arg); va_end(arg); return 0; } /**************************************************************************** * Functions needed by libnet80211.a ****************************************************************************/ /**************************************************************************** * Name: net80211_printf * * Description: * Output format string and its arguments * * Input Parameters: * format - format string * * Returned Value: * 0 * ****************************************************************************/ int net80211_printf(const char *format, ...) { va_list arg; va_start(arg, format); vsyslog(LOG_INFO, format, arg); va_end(arg); return 0; } /**************************************************************************** * Functions needed by libwpa_supplicant.a ****************************************************************************/ /**************************************************************************** * Name: esp_timer_create * * Description: * Create timer with given arguments * * Input Parameters: * create_args - Timer arguments data pointer * out_handle - Timer handle pointer * * Returned Value: * 0 if success or -1 if fail * ****************************************************************************/ int32_t esp_timer_create(const esp_timer_create_args_t *create_args, esp_timer_handle_t *out_handle) { struct ets_timer *ets_timer; ets_timer = kmm_zalloc(sizeof(struct ets_timer)); if (!ets_timer) { wlerr("ERROR: Failed to malloc\n"); return -1; } esp_timer_setfn(ets_timer, create_args->callback, create_args->arg); if (!ets_timer->priv) { wlerr("ERROR: Failed to set timer func\n"); return -1; } *out_handle = (esp_timer_handle_t)ets_timer; return 0; } /**************************************************************************** * Name: esp_timer_start_once * * Description: * Start timer with one shot mode * * Input Parameters: * timer - Timer handle pointer * timeout_us - Timeout value by micro second * * Returned Value: * 0 if success or -1 if fail * ****************************************************************************/ int32_t esp_timer_start_once(esp_timer_handle_t timer, uint64_t timeout_us) { struct ets_timer *ets_timer = (struct ets_timer *)timer; esp_timer_arm_us(ets_timer, timeout_us, false); return 0; } /**************************************************************************** * Name: esp_timer_start_periodic * * Description: * Start timer with periodic mode * * Input Parameters: * timer - Timer handle pointer * period - Timeout value by micro second * * Returned Value: * 0 if success or -1 if fail * ****************************************************************************/ int32_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period) { struct ets_timer *ets_timer = (struct ets_timer *)timer; esp_timer_arm_us(ets_timer, period, true); return 0; } /**************************************************************************** * Name: esp_timer_stop * * Description: * Stop timer * * Input Parameters: * timer - Timer handle pointer * * Returned Value: * 0 if success or -1 if fail * ****************************************************************************/ int32_t esp_timer_stop(esp_timer_handle_t timer) { struct ets_timer *ets_timer = (struct ets_timer *)timer; esp_timer_disarm(ets_timer); return 0; } /**************************************************************************** * Name: esp_timer_delete * * Description: * Delete timer and free recource * * Input Parameters: * timer - Timer handle pointer * * Returned Value: * 0 if success or -1 if fail * ****************************************************************************/ int32_t esp_timer_delete(esp_timer_handle_t timer) { struct ets_timer *ets_timer = (struct ets_timer *)timer; esp32_timer_done(ets_timer); kmm_free(ets_timer); return 0; } /**************************************************************************** * Name: __assert_func * * Description: * Delete timer and free recource * * Input Parameters: * file - assert file * line - assert line * func - assert function * expr - assert condition * * Returned Value: * None * ****************************************************************************/ void __assert_func(const char *file, int line, const char *func, const char *expr) { wlerr("ERROR: Assert failed in %s, %s:%d (%s)", func, file, line, expr); abort(); } /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: esp_event_send_internal * * Description: * Post event message to queue * * Input Parameters: * event_base - Event set name * event_id - Event ID * event_data - Event private data * event_data_size - Event data size * ticks_to_wait - Waiting system ticks * * Returned Value: * Task maxium priority * ****************************************************************************/ int32_t esp_event_send_internal(esp_event_base_t event_base, int32_t event_id, void *event_data, size_t event_data_size, uint32_t ticks_to_wait) { int32_t ret; ret = esp_event_post(event_base, event_id, event_data, event_data_size, ticks_to_wait); return ret; } /**************************************************************************** * Name: esp_wifi_init * * Description: * Initialize WiFi * * Input Parameters: * config - Initialization config parameters * * Returned Value: * 0 if success or others if fail * ****************************************************************************/ int32_t esp_wifi_init(const wifi_init_config_t *config) { int32_t ret; ret = esp_wifi_init_internal(config); if (ret) { wlerr("ERROR: Failed to initialize WiFi error=%d\n", ret); return -1; } ret = esp_supplicant_init(); if (ret) { wlerr("ERROR: Failed to initialize WPA supplicant error=%d\n", ret); esp_wifi_deinit_internal(); return -1; } return 0; } /**************************************************************************** * Name: esp_wifi_deinit * * Description: * Deinitialize WiFi and free resource * * Input Parameters: * None * * Returned Value: * 0 if success or others if fail * ****************************************************************************/ int32_t esp_wifi_deinit(void) { int ret; ret = esp_supplicant_deinit(); if (ret) { wlerr("ERROR: Failed to deinitialize supplicant\n"); return ret; } ret = esp_wifi_deinit_internal(); if (ret != 0) { wlerr("ERROR: Failed to deinitialize WiFi\n"); return ret; } return ret; } /**************************************************************************** * Name: esp_wifi_sta_send_data * * Description: * Use WiFi station interface to send 802.3 frame * * Input Parameters: * pbuf - Packet buffer pointer * len - Packet length * * Returned Value: * 0 if success or others if fail * ****************************************************************************/ int esp_wifi_sta_send_data(void *pbuf, uint32_t len) { int ret; ret = esp_wifi_internal_tx(WIFI_IF_STA, pbuf, len); return ret; } /**************************************************************************** * Name: esp_wifi_sta_register_recv_cb * * Description: * Regitser WiFi receive packet callback function * * Input Parameters: * input_cb - Receive callback function * * Returned Value: * 0 if success or others if fail * ****************************************************************************/ int esp_wifi_sta_register_recv_cb(int (*recv_cb)(void *buffer, uint16_t len, void *eb)) { int ret; ret = esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_STA, (wifi_rxcb_t)recv_cb); return ret; } /**************************************************************************** * Name: esp_wifi_sta_read_mac * * Description: * Read station interface MAC address from efuse * * Input Parameters: * mac - MAC address buffer pointer * * Returned Value: * 0 if success or -1 if fail * ****************************************************************************/ int esp_wifi_sta_read_mac(uint8_t *mac) { return esp_read_mac(mac, ESP_MAC_WIFI_STA); } /**************************************************************************** * Name: esp_wifi_free_eb * * Description: * Free WiFi receive callback input eb pointer * * Input Parameters: * eb - WiFi receive callback input eb pointer * * Returned Value: * None * ****************************************************************************/ void esp_wifi_free_eb(void *eb) { esp_wifi_internal_free_rx_buffer(eb); } /**************************************************************************** * 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, FAR struct sigevent *event) { int id; struct wifi_notify *notify; int ret = -1; wlinfo("PID=%d event=%p\n", pid, event); if (event->sigev_notify != SIGEV_SIGNAL) { wlerr("ERROR: sigev_notify %d is invalid\n", event->sigev_signo); return -1; } id = esp_event_id_map(event->sigev_signo); if (id < 0) { wlerr("ERROR: No process event %d\n", event->sigev_signo); } else { notify = &s_wifi_notify[id]; if (notify->assigned) { wlerr("ERROR: sigev_signo %d has subscribed\n", event->sigev_signo); } else { if (pid == 0) { pid = getpid(); wlinfo("Actual PID=%d\n", pid); } notify->pid = pid; notify->event = *event; notify->assigned = true; ret = 0; } } return ret; } /**************************************************************************** * Name: esp_wifi_adapter_init * * Description: * Initialize ESP32 WiFi 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 init_cfg = WIFI_INIT_CONFIG_DEFAULT(); ret = sem_init(&s_connect_sem, 0, 0); if (ret) { wlerr("ERROR: Failed to initialize sem error=%d\n", errno); return -1; } #ifndef CONFIG_ESP32_WIFI_SAVE_PARAM init_cfg.nvs_enable = 0; #endif ret = esp_wifi_init(&init_cfg); if (ret) { wlerr("ERROR: Failed to initialize WiFi error=%d\n", ret); sem_destroy(&s_connect_sem); return -1; } ret = esp_wifi_set_ps(WIFI_PS_NONE); if (ret) { wlerr("ERROR: Failed to close power save, error=%d\n", ret); esp_wifi_deinit(); sem_destroy(&s_connect_sem); return -1; } sq_init(&s_wifi_evt_queue); return 0; } /**************************************************************************** * Name: esp_wifi_set_password * * Description: * Set WiFi password * * Input Parameters: * pdata - Password buffer pointer * len - Password length * * Returned Value: * 0 if success or -1 if fail * ****************************************************************************/ int esp_wifi_set_password(const uint8_t *pdata, uint8_t len) { memcpy(s_password, pdata, len); s_password_len = len; return 0; } /**************************************************************************** * Name: esp_wifi_set_ssid * * Description: * Set WiFi SSID * * Input Parameters: * pdata - SSID buffer pointer * len - SSID length * * Returned Value: * 0 if success or -1 if fail * ****************************************************************************/ int esp_wifi_set_ssid(const uint8_t *pdata, uint8_t len) { memcpy(s_ssid, pdata, len); s_ssid_len = len; return 0; } /**************************************************************************** * Name: esp_wifi_connect_internal * * Description: * Trigger WiFi connection action * * Input Parameters: * None * * Returned Value: * 0 if success or -1 if fail * ****************************************************************************/ int esp_wifi_connect_internal(void) { int ret; wifi_config_t wifi_cfg; struct timespec timeout; if (s_connected) { wlinfo("INFO: WiFi has connected AP\n"); return 0; } ret = esp_wifi_set_mode(WIFI_MODE_STA); if (ret) { wlerr("ERROR: Failed to set station mode error=%d\n", ret); esp_wifi_deinit(); return -1; } memset(&wifi_cfg, 0, sizeof(wifi_config_t)); memcpy((char *)wifi_cfg.sta.ssid, s_ssid, s_ssid_len); memcpy((char *)wifi_cfg.sta.password, s_password, s_password_len); ret = esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_cfg); if (ret) { wlerr("ERROR: Failed to set WiFi config error=%d\n", ret); return -1; } ret = esp_wifi_start(); if (ret) { wlerr("ERROR: Failed to set start config error=%d\n", ret); return -1; } clock_gettime(CLOCK_REALTIME, &timeout); timeout.tv_sec += WIFI_CONNECT_TIMEOUT; ret = sem_timedwait(&s_connect_sem, &timeout); if (ret) { wlerr("ERROR: Failed to wait sem error=%d\n", errno); esp_wifi_stop(); return -1; } if (!s_connected) { wlerr("ERROR: Process connection error\n"); esp_wifi_stop(); return -1; } return 0; }