diff --git a/arch/xtensa/include/esp32/irq.h b/arch/xtensa/include/esp32/irq.h index b2d1c9e964..b8e794be4c 100644 --- a/arch/xtensa/include/esp32/irq.h +++ b/arch/xtensa/include/esp32/irq.h @@ -383,6 +383,7 @@ #define ESP32_CPUINT_NNMIPERIPHS 1 #define EPS32_CPUINT_NMISET 0x00004000 +#define ESP32_CPUINT_MAC 0 #define ESP32_CPUINT_TIMER0 6 #define ESP32_CPUINT_SOFTWARE0 7 #define ESP32_CPUINT_PROFILING 11 diff --git a/arch/xtensa/src/esp32/Kconfig b/arch/xtensa/src/esp32/Kconfig index 9922dc130e..e3f0e10ead 100644 --- a/arch/xtensa/src/esp32/Kconfig +++ b/arch/xtensa/src/esp32/Kconfig @@ -852,6 +852,21 @@ endmenu # ESP32_EMAC menu "WiFi configuration" depends on ESP32_WIRELESS +choice + prompt "ESP32 WiFi mode" + default ESP32_WIFI_STATION + +config ESP32_WIFI_STATION + bool "Station mode" + +config ESP32_WIFI_SOFTAP + bool "SoftAP mode" + +config ESP32_WIFI_STATION_SOFTAP_COEXISTENCE + bool "Station + SoftAP coexistence" + +endchoice # ESP32 WiFi mode + config ESP32_WIFI_STATIC_RXBUF_NUM int "WiFi static RX buffer number" default 10 @@ -876,8 +891,8 @@ config ESP32_WIFI_RXBA_AMPDU_WZ int "WiFi RX BA AMPDU windown size" default 6 -config ESP32_WLAN_RXBUF_NUM - int "WLAN netcard RX buffer number" +config ESP32_WLAN_PKTBUF_NUM + int "WLAN netcard packet buffer number per netcard" default 16 config ESP32_WIFI_CONNECT_TIMEOUT diff --git a/arch/xtensa/src/esp32/esp32_cpuint.c b/arch/xtensa/src/esp32/esp32_cpuint.c index 67eb0f0c2e..8ab86afa9a 100644 --- a/arch/xtensa/src/esp32/esp32_cpuint.c +++ b/arch/xtensa/src/esp32/esp32_cpuint.c @@ -150,6 +150,12 @@ #define ESP32_MAX_PRIORITY 5 #define ESP32_PRIO_INDEX(p) ((p) - ESP32_MIN_PRIORITY) +#ifdef CONFIG_ESP32_WIRELESS +# define ESP32_WIRELESS_RESERVE_INT (1 << ESP32_CPUINT_MAC) +#else +# define ESP32_WIRELESS_RESERVE_INT 0 +#endif + /**************************************************************************** * Public Data ****************************************************************************/ @@ -179,9 +185,11 @@ static uint32_t g_intenable[1]; * devices. */ -static uint32_t g_cpu0_freeints = EPS32_CPUINT_PERIPHSET; +static uint32_t g_cpu0_freeints = EPS32_CPUINT_PERIPHSET & + (~ESP32_WIRELESS_RESERVE_INT); #ifdef CONFIG_SMP -static uint32_t g_cpu1_freeints = EPS32_CPUINT_PERIPHSET; +static uint32_t g_cpu1_freeints = EPS32_CPUINT_PERIPHSET & + (~ESP32_WIRELESS_RESERVE_INT); #endif /* Bitsets for each interrupt priority 1-5 */ @@ -374,6 +382,7 @@ int esp32_cpuint_initialize(void) * * CPU interrupt bit IRQ number * --------------------------- --------------------- + * ESP32_CPUINT_MAC 0 ESP32_IRQ_MAC 4 * ESP32_CPUINT_TIMER0 6 XTENSA_IRQ_TIMER0 0 * ESP32_CPUINT_SOFTWARE0 7 Not yet defined * ESP32_CPUINT_PROFILING 11 Not yet defined @@ -385,6 +394,13 @@ int esp32_cpuint_initialize(void) intmap[ESP32_CPUINT_TIMER0] = XTENSA_IRQ_TIMER0; intmap[ESP32_CPUINT_TIMER1] = XTENSA_IRQ_TIMER1; intmap[ESP32_CPUINT_TIMER2] = XTENSA_IRQ_TIMER2; + + /* Reserve CPU interrupt for some special drivers */ + +#ifdef CONFIG_ESP32_WIRELESS + intmap[ESP32_CPUINT_MAC] = ESP32_IRQ_MAC; +#endif + return OK; } diff --git a/arch/xtensa/src/esp32/esp32_wifi_adapter.c b/arch/xtensa/src/esp32/esp32_wifi_adapter.c index 71c488824e..ccce8d3176 100644 --- a/arch/xtensa/src/esp32/esp32_wifi_adapter.c +++ b/arch/xtensa/src/esp32/esp32_wifi_adapter.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "nuttx/kmalloc.h" #include #include "nuttx/spinlock.h" @@ -82,6 +83,26 @@ * Private Types ****************************************************************************/ +/* WiFi Station state */ + +enum wifi_sta_state +{ + WIFI_STA_STATE_NULL, + WIFI_STA_STATE_START, + WIFI_STA_STATE_CONNECT, + WIFI_STA_STATE_DISCONNECT, + WIFI_STA_STATE_STOP +}; + +/* WiFi SoftAP state */ + +enum wifi_softap_state +{ + WIFI_SOFTAP_STATE_NULL, + WIFI_SOFTAP_STATE_START, + WIFI_SOFTAP_STATE_STOP +}; + /* WiFi interrupt adapter private data */ struct irq_adpt @@ -303,15 +324,12 @@ 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); +void intr_matrix_set(int cpu_no, uint32_t model_num, uint32_t intr_num); /**************************************************************************** * Private Data ****************************************************************************/ -/* WiFi interrupt private data */ - -static int g_wifi_irq = -1; - /* WiFi thread private data */ static pthread_key_t g_wifi_thread_key; @@ -336,19 +354,46 @@ static uint32_t g_common_clock_disable_time; static struct work_s g_wifi_evt_work; static sq_queue_t g_wifi_evt_queue; static struct wifi_notify g_wifi_notify[WIFI_ADPT_EVT_MAX]; -static sem_t g_evtexcl_sem = SEM_INITIALIZER(1); -static sem_t g_connect_sem = SEM_INITIALIZER(0); -static bool g_connected; - -static uint8_t g_ssid[32]; -static uint8_t g_password[64]; -static uint8_t g_ssid_len; -static uint8_t g_password_len; +static sem_t g_wifiexcl_sem = SEM_INITIALIZER(1); /* Callback function to update WiFi MAC time */ wifi_mac_time_update_cb_t g_wifi_mac_time_update_cb; +/* WiFi adapter reference */ + +static int g_wifi_ref; + +#ifdef ESP32_WLAN_HAS_STA + +/* If reconnect automatically */ + +static bool g_sta_reconnect; + +/* If WiFi sta starts */ + +static bool g_sta_started; + +/* If WiFi sta connected */ + +static bool g_sta_connected; + +/* WiFi station TX done callback function */ + +static wifi_txdone_cb_t g_sta_txdone_cb; +#endif + +#ifdef ESP32_WLAN_HAS_SOFTAP + +/* If WiFi SoftAP starts */ + +static bool g_softap_started; + +/* WiFi SoftAP TX done callback function */ + +static wifi_txdone_cb_t g_softap_txdone_cb; +#endif + /**************************************************************************** * Public Data ****************************************************************************/ @@ -491,10 +536,10 @@ ESP_EVENT_DEFINE_BASE(WIFI_EVENT); ****************************************************************************/ /**************************************************************************** - * Name: esp_errno_trans + * Name: osi_errno_trans * * Description: - * Transform from nuttx error code to WiFi adapter error code + * Transform from nuttx Os error code to WiFi adapter error code * * Input Parameters: * ret - NuttX error code @@ -504,7 +549,7 @@ ESP_EVENT_DEFINE_BASE(WIFI_EVENT); * ****************************************************************************/ -static inline int32_t esp_errno_trans(int ret) +static inline int32_t osi_errno_trans(int ret) { if (!ret) { @@ -516,6 +561,70 @@ static inline int32_t esp_errno_trans(int ret) } } +/**************************************************************************** + * Name: osi_errno_trans + * + * Description: + * Transform from ESP WiFi error code to NuttX error code + * + * Input Parameters: + * ret - ESP WiFi error code + * + * Returned Value: + * NuttX error code + * + ****************************************************************************/ + +static int32_t wifi_errno_trans(int ret) +{ + int wifierr; + + /* Unmask component error bits */ + + wifierr = ret & 0xfff; + + if (wifierr == ESP_OK) + { + return OK; + } + else if (wifierr == ESP_ERR_NO_MEM) + { + return -ENOMEM; + } + else if (wifierr == ESP_ERR_INVALID_ARG) + { + return -EINVAL; + } + else if (wifierr == ESP_ERR_INVALID_STATE) + { + return -EIO; + } + else if (wifierr == ESP_ERR_INVALID_SIZE) + { + return -EINVAL; + } + else if (wifierr == ESP_ERR_NOT_FOUND) + { + return -ENOSYS; + } + else if (wifierr == ESP_ERR_NOT_SUPPORTED) + { + return -ENOSYS; + } + else if (wifierr == ESP_ERR_TIMEOUT) + { + return -ETIMEDOUT; + } + else if (wifierr == ESP_ERR_INVALID_MAC) + { + return -EINVAL; + } + else + { + return ERROR; + } +} + /**************************************************************************** * Name: esp_int_adpt_cb * @@ -590,7 +699,7 @@ static void esp_update_time(struct timespec *timespec, uint32_t ticks) } /**************************************************************************** - * Name: esp_event_lock + * Name: esp_wifi_lock * * Description: * Lock or unlock the event process @@ -603,17 +712,25 @@ static void esp_update_time(struct timespec *timespec, uint32_t ticks) * ****************************************************************************/ -static int esp_event_lock(bool lock) +static int esp_wifi_lock(bool lock) { int ret; if (lock) { - ret = nxsem_wait_uninterruptible(&g_evtexcl_sem); + ret = nxsem_wait_uninterruptible(&g_wifiexcl_sem); + if (ret < 0) + { + wlinfo("INFO: Failed to lock WiFi ret=%d\n", ret); + } } else { - ret = nxsem_post(&g_evtexcl_sem); + ret = nxsem_post(&g_wifiexcl_sem); + if (ret < 0) + { + wlinfo("INFO: Failed to unlock WiFi ret=%d\n", ret); + } } return ret; @@ -638,26 +755,20 @@ static int esp_event_lock(bool lock) static void esp_set_isr(int32_t n, void *f, void *arg) { int ret; + uint32_t tmp; struct irq_adpt *adapter; - int irq; - int cpu = 0; - int tmp; + int irq = n + XTENSA_IRQ_FIRSTPERIPH; - if (g_wifi_irq >= 0) + wlinfo("INFO: n=%d f=%p arg=%p irq=%d\n", n, f, arg, irq); + + if (g_irqvector[irq].handler && + g_irqvector[irq].handler != irq_unexpected_isr) { + wlinfo("INFO: irq=%d has been set handler=%p\n", irq, + g_irqvector[irq].handler); return ; } - 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) @@ -670,18 +781,13 @@ static void esp_set_isr(int32_t n, void *f, void *arg) adapter->func = f; adapter->arg = arg; - tmp = n + XTENSA_IRQ_FIRSTPERIPH; - ret = irq_attach(tmp, esp_int_adpt_cb, adapter); + ret = irq_attach(irq, esp_int_adpt_cb, adapter); if (ret) { - wlerr("ERROR: Failed to attach IRQ %d\n", tmp); + wlerr("ERROR: Failed to attach IRQ %d\n", irq); assert(0); return ; } - - esp32_attach_peripheral(cpu, n, irq); - - g_wifi_irq = irq; } /**************************************************************************** @@ -700,7 +806,11 @@ static void esp_set_isr(int32_t n, void *f, void *arg) static void esp32_ints_on(uint32_t mask) { - up_enable_irq(g_wifi_irq); + int irq = __builtin_ffs(mask) - 1; + + wlinfo("INFO mask=%08x irq=%d\n", mask, irq); + + up_enable_irq(irq); } /**************************************************************************** @@ -719,7 +829,11 @@ static void esp32_ints_on(uint32_t mask) static void esp32_ints_off(uint32_t mask) { - up_disable_irq(g_wifi_irq); + uint32_t irq = __builtin_ffs(mask) - 1; + + wlinfo("INFO mask=%08x irq=%d\n", mask, irq); + + up_disable_irq(irq); } /**************************************************************************** @@ -988,7 +1102,7 @@ static int32_t esp_semphr_take(void *semphr, uint32_t ticks) } } - return esp_errno_trans(ret); + return osi_errno_trans(ret); } /**************************************************************************** @@ -1016,7 +1130,7 @@ static int32_t esp_semphr_give(void *semphr) wlerr("ERROR: Failed to post sem error=%d\n", ret); } - return esp_errno_trans(ret); + return osi_errno_trans(ret); } /**************************************************************************** @@ -1212,7 +1326,7 @@ static int32_t esp_mutex_lock(void *mutex_data) wlerr("ERROR: Failed to lock mutex error=%d\n", ret); } - return esp_errno_trans(ret); + return osi_errno_trans(ret); } /**************************************************************************** @@ -1240,7 +1354,7 @@ static int32_t esp_mutex_unlock(void *mutex_data) wlerr("ERROR: Failed to unlock mutex error=%d\n", ret); } - return esp_errno_trans(ret); + return osi_errno_trans(ret); } /**************************************************************************** @@ -1378,7 +1492,7 @@ static int32_t esp_queue_send_generic(void *queue, void *item, } } - return esp_errno_trans(ret); + return osi_errno_trans(ret); } /**************************************************************************** @@ -1898,6 +2012,7 @@ static int esp_event_id_map(int event_id) switch (event_id) { +#ifdef ESP32_WLAN_HAS_STA case WIFI_EVENT_STA_START: id = WIFI_ADPT_EVT_STA_START; break; @@ -1913,6 +2028,7 @@ static int esp_event_id_map(int event_id) case WIFI_EVENT_STA_STOP: id = WIFI_ADPT_EVT_STA_STOP; break; +#endif default: return -1; } @@ -1951,42 +2067,50 @@ static void esp_evt_work_cb(FAR void *arg) break; } + esp_wifi_lock(true); + switch (evt_adpt->id) { +#ifdef ESP32_WLAN_HAS_STA case WIFI_ADPT_EVT_STA_START: + wlinfo("INFO: WiFi sta start\n"); + + g_sta_connected = false; ret = esp_wifi_set_ps(WIFI_PS_NONE); if (ret) { wlerr("ERROR: Failed to close PS\n"); } - ret = esp_wifi_connect(); - if (ret) - { - wlerr("ERROR: Failed to connect\n"); - } + break; case WIFI_ADPT_EVT_STA_CONNECT: - g_connected = true; - ret = nxsem_post(&g_connect_sem); - if (ret) - { - wlerr("ERROR: Failed to post sem error=%d\n", ret); - } + wlinfo("INFO: WiFi sta connect\n"); + + g_sta_connected = true; break; case WIFI_ADPT_EVT_STA_DISCONNECT: - g_connected = false; - ret = esp_wifi_connect(); - if (ret) + wlinfo("INFO: WiFi sta disconnect\n"); + + g_sta_connected = false; + if (g_sta_reconnect) { - wlerr("ERROR: Failed to connect\n"); + ret = esp_wifi_connect(); + if (ret) + { + wlerr("ERROR: Failed to connect AP error=%d\n", ret); + } } break; + case WIFI_ADPT_EVT_STA_STOP: + wlinfo("INFO: WiFi sta stop\n"); + + g_sta_connected = false; + break; +#endif default: break; } - esp_event_lock(true); - notify = &g_wifi_notify[evt_adpt->id]; if (notify->assigned) { @@ -2001,7 +2125,7 @@ static void esp_evt_work_cb(FAR void *arg) } } - esp_event_lock(false); + esp_wifi_lock(false); kmm_free(evt_adpt); } @@ -2044,8 +2168,12 @@ static void wifi_set_intr(int32_t cpu_no, uint32_t intr_source, uint32_t intr_num, int32_t intr_prio) { wlinfo("cpu_no=%" PRId32 ", intr_source=%" PRIu32 - ", intr_num=%" PRIu32 ", intr_prio=%" PRId32, + ", intr_num=%" PRIu32 ", intr_prio=%" PRId32 "\n", cpu_no, intr_source, intr_num, intr_prio); + + /* Force to bind WiFi interrupt to CPU0 */ + + intr_matrix_set(0, intr_source, intr_num); } /**************************************************************************** @@ -2096,7 +2224,7 @@ int32_t esp_event_post(esp_event_base_t event_base, id = esp_event_id_map(event_id); if (id < 0) { - wlerr("ERROR: No process event %d\n", event_id); + wlinfo("INFO: No process event %d\n", event_id); return -1; } @@ -2467,7 +2595,7 @@ int32_t esp_read_mac(uint8_t *mac, esp_mac_type_t type) if (i >= 64) { - wlerr("ERROR: Failed to generate softAP MAC\n"); + wlerr("ERROR: Failed to generate SoftAP MAC\n"); return -1; } } @@ -3960,6 +4088,47 @@ static unsigned long esp_random_ulong(void) return esp_random(); } +/**************************************************************************** + * Name: esp_wifi_tx_done_cb + * + * Description: + * WiFi TX done callback function. + * + ****************************************************************************/ + +static IRAM_ATTR void esp_wifi_tx_done_cb(uint8_t ifidx, uint8_t *data, + uint16_t *len, bool txstatus) +{ +#if 0 + wlinfo("INFO: ifidx=%d data=%p *len=%p txstatus=%d\n", + ifidx, data, len, txstatus); +#endif + +#ifdef ESP32_WLAN_HAS_STA + if (ifidx == ESP_IF_WIFI_STA) + { + if (g_sta_txdone_cb) + { + g_sta_txdone_cb(data, len, txstatus); + } + } + else +#endif +#ifdef ESP32_WLAN_HAS_SOFTAP + if (ifidx == ESP_IF_WIFI_AP) + { + if (g_softap_txdone_cb) + { + g_softap_txdone_cb(data, len, txstatus); + } + } + else +#endif + { + wlerr("ERROR: ifidx=%d is error\n", ifidx); + } +} + /**************************************************************************** * Functions needed by libphy.a ****************************************************************************/ @@ -3971,10 +4140,10 @@ static unsigned long esp_random_ulong(void) * Read regitser value safely in SMP * * Input Parameters: - * reg - Regitser address + * reg - Register address * * Returned Value: - * Regitser value + * Register value * ****************************************************************************/ @@ -4333,7 +4502,7 @@ int32_t esp_wifi_init(const wifi_init_config_t *config) if (ret) { wlerr("ERROR: Failed to initialize WiFi error=%d\n", ret); - return -1; + return ret; } ret = esp_supplicant_init(); @@ -4341,7 +4510,7 @@ int32_t esp_wifi_init(const wifi_init_config_t *config) { wlerr("ERROR: Failed to initialize WPA supplicant error=%d\n", ret); esp_wifi_deinit_internal(); - return -1; + return ret; } return 0; @@ -4382,74 +4551,6 @@ int32_t esp_wifi_deinit(void) 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 * @@ -4492,7 +4593,7 @@ int esp_wifi_notify_subscribe(pid_t pid, FAR struct sigevent *event) wlinfo("PID=%d event=%p\n", pid, event); - esp_event_lock(true); + esp_wifi_lock(true); if (event->sigev_notify == SIGEV_SIGNAL) { @@ -4555,7 +4656,7 @@ int esp_wifi_notify_subscribe(pid_t pid, FAR struct sigevent *event) wlerr("ERROR: sigev_notify %d is invalid\n", event->sigev_signo); } - esp_event_lock(false); + esp_wifi_lock(false); return ret; } @@ -4579,13 +4680,25 @@ int esp_wifi_adapter_init(void) int ret; wifi_init_config_t wifi_cfg = WIFI_INIT_CONFIG_DEFAULT(); + esp_wifi_lock(true); + + if (g_wifi_ref) + { + wlinfo("INFO: WiFi adapter is already initialized\n"); + g_wifi_ref++; + esp_wifi_lock(false); + return OK; + } + ret = esp32_rt_timer_init(); if (ret < 0) { wlerr("ERROR: Failed to initialize RT timer error=%d\n", ret); - return -1; + goto errout_init_timer; } + sq_init(&g_wifi_evt_queue); + #ifdef CONFIG_ESP32_WIFI_SAVE_PARAM wifi_cfg.nvs_enable = 1; #else @@ -4613,20 +4726,258 @@ int esp_wifi_adapter_init(void) if (ret) { wlerr("ERROR: Failed to initialize WiFi error=%d\n", ret); - esp32_rt_timer_deinit(); - return -1; + ret = wifi_errno_trans(ret); + goto errout_init_wifi; } - sq_init(&g_wifi_evt_queue); + ret = esp_wifi_set_tx_done_cb(esp_wifi_tx_done_cb); + if (ret) + { + wlerr("ERROR: Failed to register TX done callback ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout_init_txdone; + } - return 0; + g_wifi_ref++; + + wlinfo("INFO: OK to initialize WiFi adapter\n"); + + esp_wifi_lock(false); + + return OK; + +errout_init_txdone: + esp_wifi_deinit(); +errout_init_wifi: + esp32_rt_timer_deinit(); +errout_init_timer: + esp_wifi_lock(false); + return ret; +} + +/**************************************************************************** + * Station functions + ****************************************************************************/ + +#ifdef ESP32_WLAN_HAS_STA + +/**************************************************************************** + * Name: esp_wifi_sta_start + * + * Description: + * Start WiFi station. + * + * Input Parameters: + * None + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_sta_start(void) +{ + int ret; + wifi_mode_t mode; + + esp_wifi_lock(true); + + ret = esp_wifi_stop(); + if (ret) + { + wlinfo("INFO: Failed to stop WiFi ret=%d\n", ret); + } + +#ifdef ESP32_WLAN_HAS_SOFTAP + if (g_softap_started) + { + mode = WIFI_MODE_APSTA; + } +#else + mode = WIFI_MODE_STA; +#endif + + ret = esp_wifi_set_mode(mode); + if (ret) + { + wlerr("ERROR: Failed to set WiFi mode=%d ret=%d\n", mode, ret); + ret = wifi_errno_trans(ret); + goto errout_set_mode; + } + + ret = esp_wifi_start(); + if (ret) + { + wlerr("ERROR: Failed to start WiFi with mode=%d ret=%d\n", mode, ret); + ret = wifi_errno_trans(ret); + goto errout_set_mode; + } + + g_sta_started = true; + + wlinfo("INFO: OK to start WiFi station\n"); + + esp_wifi_lock(false); + return OK; + +errout_set_mode: + esp_wifi_lock(false); + return ret; +} + +/**************************************************************************** + * Name: esp_wifi_sta_stop + * + * Description: + * Stop WiFi station. + * + * Input Parameters: + * None + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_sta_stop(void) +{ + int ret; + + esp_wifi_lock(true); + + ret = esp_wifi_stop(); + if (ret) + { + wlinfo("INFO: Failed to stop WiFi ret=%d\n", ret); + } + + g_sta_started = false; + +#ifdef ESP32_WLAN_HAS_SOFTAP + if (g_softap_started) + { + ret = esp_wifi_set_mode(WIFI_MODE_AP); + if (ret) + { + wlerr("ERROR: Failed to set WiFi AP mode ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout_set_mode; + } + + ret = esp_wifi_start(); + if (ret) + { + wlerr("ERROR: Failed to start WiFi AP ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout_set_mode; + } + } +#endif + + wlinfo("INFO: OK to stop WiFi station\n"); + + esp_wifi_lock(false); + return OK; + +#ifdef ESP32_WLAN_HAS_SOFTAP +errout_set_mode: + esp_wifi_lock(true); + return ret; +#endif +} + +/**************************************************************************** + * 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 wifi_errno_trans(ret); +} + +/**************************************************************************** + * Name: esp_wifi_sta_register_recv_cb + * + * Description: + * Register WiFi station receive packet callback function + * + * Input Parameters: + * recv_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 wifi_errno_trans(ret); +} + +/**************************************************************************** + * Name: esp_wifi_sta_register_txdone_cb + * + * Description: + * Register the station TX done callback function. + * + * Input Parameters: + * cb - The callback function + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_wifi_sta_register_txdone_cb(wifi_txdone_cb_t cb) +{ + g_sta_txdone_cb = cb; +} + +/**************************************************************************** + * 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_set_password * * Description: - * Set WiFi password + * Set WiFi station password * * Input Parameters: * pdata - Password buffer pointer @@ -4637,19 +4988,60 @@ int esp_wifi_adapter_init(void) * ****************************************************************************/ -int esp_wifi_set_password(const uint8_t *pdata, uint8_t len) +int esp_wifi_sta_set_password(const uint8_t *pdata, uint8_t len) { - memcpy(g_password, pdata, len); - g_password_len = len; + int ret; + wifi_config_t wifi_cfg; +#ifdef CONFIG_DEBUG_WIRELESS_INFO + char buf[65]; +#endif - return 0; + if (len > 64) + { + return -EINVAL; + } + + esp_wifi_lock(true); + + ret = esp_wifi_get_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to get WiFi config data ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout_get_config; + } + + memcpy(wifi_cfg.sta.password, pdata, len); + + wifi_cfg.sta.pmf_cfg.capable = true; + + ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to set WiFi config data ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout_get_config; + } + +#ifdef CONFIG_DEBUG_WIRELESS_INFO + memcpy(buf, pdata, len); + buf[len] = 0; + wlinfo("INFO: OK to set WiFi station password=%s len=%d\n", buf, len); +#endif + + esp_wifi_lock(false); + return OK; + +errout_get_config: + esp_wifi_lock(false); + return ret; } /**************************************************************************** - * Name: esp_wifi_set_ssid + * Name: esp_wifi_sta_set_ssid * * Description: - * Set WiFi SSID + * Set WiFi station SSID * * Input Parameters: * pdata - SSID buffer pointer @@ -4660,19 +5052,58 @@ int esp_wifi_set_password(const uint8_t *pdata, uint8_t len) * ****************************************************************************/ -int esp_wifi_set_ssid(const uint8_t *pdata, uint8_t len) +int esp_wifi_sta_set_ssid(const uint8_t *pdata, uint8_t len) { - memcpy(g_ssid, pdata, len); - g_ssid_len = len; + int ret; + wifi_config_t wifi_cfg; +#ifdef CONFIG_DEBUG_WIRELESS_INFO + char buf[33]; +#endif - return 0; + if (len > 32) + { + return -EINVAL; + } + + esp_wifi_lock(true); + + ret = esp_wifi_get_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to get WiFi config data ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout_get_config; + } + + memcpy(wifi_cfg.sta.ssid, pdata, len); + + ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to set WiFi config data ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout_get_config; + } + +#ifdef CONFIG_DEBUG_WIRELESS_INFO + memcpy(buf, pdata, len); + buf[len] = 0; + wlinfo("INFO: OK to set WiFi station ssid=%s len=%d\n", buf, len); +#endif + + esp_wifi_lock(false); + return OK; + +errout_get_config: + esp_wifi_lock(false); + return ret; } /**************************************************************************** - * Name: esp_wifi_connect_internal + * Name: esp_wifi_sta_connect * * Description: - * Trigger WiFi connection action + * Trigger WiFi station connection action * * Input Parameters: * None @@ -4682,82 +5113,474 @@ int esp_wifi_set_ssid(const uint8_t *pdata, uint8_t len) * ****************************************************************************/ -int esp_wifi_connect_internal(void) +int esp_wifi_sta_connect(void) { int ret; - wifi_config_t wifi_cfg; - struct timespec timeout; + uint32_t ticks; - if (g_connected) + esp_wifi_lock(true); + + if (g_sta_connected) { wlinfo("INFO: WiFi has connected AP\n"); - return 0; + esp_wifi_lock(false); + return OK; } - ret = esp_wifi_set_mode(WIFI_MODE_STA); + g_sta_reconnect = true; + + ret = esp_wifi_connect(); if (ret) { - wlerr("ERROR: Failed to set station mode error=%d\n", ret); - esp_wifi_deinit(); - return -1; + wlerr("ERROR: Failed to connect ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout_wifi_connect; } - memset(&wifi_cfg, 0, sizeof(wifi_config_t)); - memcpy((char *)wifi_cfg.sta.ssid, g_ssid, g_ssid_len); - memcpy((char *)wifi_cfg.sta.password, g_password, g_password_len); + esp_wifi_lock(false); - wifi_cfg.sta.pmf_cfg.capable = true; - - ret = esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_cfg); - if (ret) + ticks = SEC2TICK(WIFI_CONNECT_TIMEOUT); + do { - wlerr("ERROR: Failed to set WiFi config error=%d\n", ret); - return -1; - } + if (g_sta_connected) + { + break; + } - ret = esp_wifi_start(); - if (ret) + esp_task_delay(1); + } + while (ticks--); + + if (!g_sta_connected) { - wlerr("ERROR: Failed to set start config error=%d\n", ret); + g_sta_reconnect = false; + wlinfo("INFO: Failed to connect to AP\n"); return -1; } - clock_gettime(CLOCK_REALTIME, &timeout); - timeout.tv_sec += WIFI_CONNECT_TIMEOUT; + return OK; - ret = nxsem_timedwait(&g_connect_sem, &timeout); - if (ret) - { - wlerr("ERROR: Failed to wait sem error=%d\n", ret); - esp_wifi_stop(); - return -1; - } - - if (!g_connected) - { - wlerr("ERROR: Process connection error\n"); - esp_wifi_stop(); - return -1; - } - - return 0; +errout_wifi_connect: + g_sta_reconnect = false; + esp_wifi_lock(false); + return ret; } /**************************************************************************** - * Name: esp_wifi_sta_register_txdone_cb + * Name: esp_wifi_sta_disconnect * * Description: - * Register the txDone callback function of type wifi_tx_done_cb_t + * Trigger WiFi station disconnection action * * Input Parameters: - * callback - The callback function + * None * * Returned Value: * 0 if success or -1 if fail * ****************************************************************************/ -int esp_wifi_sta_register_txdone_cb(void *callback) +int esp_wifi_sta_disconnect(void) { - return esp_wifi_set_tx_done_cb((wifi_tx_done_cb_t)callback); + int ret; + + esp_wifi_lock(true); + + g_sta_reconnect = false; + + ret = esp_wifi_disconnect(); + if (ret) + { + wlerr("ERROR: Failed to disconnect ret=%d\n", ret); + ret = wifi_errno_trans(ret); + } + else + { + wlinfo("INFO: OK to disconnect WiFi station\n"); + } + + esp_wifi_lock(false); + return ret; } +#endif + +/**************************************************************************** + * SoftAP functions + ****************************************************************************/ + +#ifdef ESP32_WLAN_HAS_SOFTAP + +/**************************************************************************** + * Name: esp_wifi_softap_start + * + * Description: + * Start WiFi SoftAP. + * + * Input Parameters: + * None + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_softap_start(void) +{ + int ret; + wifi_mode_t mode; + + esp_wifi_lock(true); + + ret = esp_wifi_stop(); + if (ret) + { + wlinfo("INFO: Failed to stop WiFi ret=%d\n", ret); + } + +#ifdef ESP32_WLAN_HAS_STA + if (g_sta_started) + { + mode = WIFI_MODE_APSTA; + } +#else + mode = WIFI_MODE_AP; +#endif + + ret = esp_wifi_set_mode(mode); + if (ret) + { + wlerr("ERROR: Failed to set WiFi mode=%d ret=%d\n", mode, ret); + ret = wifi_errno_trans(ret); + goto errout_set_mode; + } + + ret = esp_wifi_start(); + if (ret) + { + wlerr("ERROR: Failed to start WiFi with mode=%d ret=%d\n", mode, ret); + ret = wifi_errno_trans(ret); + goto errout_set_mode; + } + + g_softap_started = true; + + wlinfo("INFO: OK to start WiFi SoftAP\n"); + + esp_wifi_lock(false); + return OK; + +errout_set_mode: + esp_wifi_lock(false); + return ret; +} + +/**************************************************************************** + * Name: esp_wifi_softap_stop + * + * Description: + * Stop WiFi SoftAP. + * + * Input Parameters: + * None + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_softap_stop(void) +{ + int ret; + + esp_wifi_lock(true); + + ret = esp_wifi_stop(); + if (ret) + { + wlinfo("INFO: Failed to stop WiFi ret=%d\n", ret); + } + + g_softap_started = false; + +#ifdef ESP32_WLAN_HAS_STA + if (g_sta_started) + { + ret = esp_wifi_set_mode(WIFI_MODE_STA); + if (ret) + { + wlerr("ERROR: Failed to set WiFi AP mode ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout_set_mode; + } + + ret = esp_wifi_start(); + if (ret) + { + wlerr("ERROR: Failed to start WiFi AP ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout_set_mode; + } + } +#endif + + wlinfo("INFO: OK to stop WiFi SoftAP\n"); + + esp_wifi_lock(false); + return OK; + +#ifdef ESP32_WLAN_HAS_STA +errout_set_mode: + esp_wifi_lock(true); + return ret; +#endif +} + +/**************************************************************************** + * Name: esp_wifi_softap_send_data + * + * Description: + * Use WiFi SoftAP 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_softap_send_data(void *pbuf, uint32_t len) +{ + int ret; + + ret = esp_wifi_internal_tx(WIFI_IF_AP, pbuf, len); + + return wifi_errno_trans(ret); +} + +/**************************************************************************** + * Name: esp_wifi_softap_register_recv_cb + * + * Description: + * Register WiFi SoftAP receive packet callback function + * + * Input Parameters: + * recv_cb - Receive callback function + * + * Returned Value: + * 0 if success or others if fail + * + ****************************************************************************/ + +int esp_wifi_softap_register_recv_cb(int (*recv_cb)(void *buffer, + uint16_t len, + void *eb)) +{ + int ret; + + ret = esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_AP, (wifi_rxcb_t)recv_cb); + + return wifi_errno_trans(ret); +} + +/**************************************************************************** + * Name: esp_wifi_softap_register_txdone_cb + * + * Description: + * Register the SoftAP TX done callback function. + * + * Input Parameters: + * cb - The callback function + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_wifi_softap_register_txdone_cb(wifi_txdone_cb_t cb) +{ + g_softap_txdone_cb = cb; +} + +/**************************************************************************** + * Name: esp_wifi_softap_read_mac + * + * Description: + * Read SoftAP interface MAC address from efuse + * + * Input Parameters: + * mac - MAC address buffer pointer + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_softap_read_mac(uint8_t *mac) +{ + return esp_read_mac(mac, ESP_MAC_WIFI_SOFTAP); +} + +/**************************************************************************** + * Name: esp_wifi_softap_set_password + * + * Description: + * Set WiFi SoftAP password + * + * Input Parameters: + * pdata - Password buffer pointer + * len - Password length + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_softap_set_password(const uint8_t *pdata, uint8_t len) +{ + int ret; + wifi_config_t wifi_cfg; +#ifdef CONFIG_DEBUG_WIRELESS_INFO + char buf[65]; +#endif + + if (len > 64) + { + return -EINVAL; + } + + esp_wifi_lock(true); + + ret = esp_wifi_get_config(WIFI_IF_AP, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to get WiFi config data ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout_get_config; + } + + memcpy(wifi_cfg.ap.password, pdata, len); + + ret = esp_wifi_set_config(WIFI_IF_AP, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to set WiFi config data ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout_get_config; + } + +#ifdef CONFIG_DEBUG_WIRELESS_INFO + memcpy(buf, pdata, len); + buf[len] = 0; + wlinfo("INFO: OK to set WiFi SoftAP password=%s len=%d\n", buf, len); +#endif + + esp_wifi_lock(false); + return OK; + +errout_get_config: + esp_wifi_lock(false); + return ret; +} + +/**************************************************************************** + * Name: esp_wifi_softap_set_ssid + * + * Description: + * Set WiFi SoftAP SSID + * + * Input Parameters: + * pdata - SSID buffer pointer + * len - SSID length + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_softap_set_ssid(const uint8_t *pdata, uint8_t len) +{ + int ret; + wifi_config_t wifi_cfg; +#ifdef CONFIG_DEBUG_WIRELESS_INFO + char buf[33]; +#endif + + if (len > 32) + { + return -EINVAL; + } + + esp_wifi_lock(true); + + ret = esp_wifi_get_config(WIFI_IF_AP, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to get WiFi config data ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout_get_config; + } + + memcpy(wifi_cfg.ap.ssid, pdata, len); + + ret = esp_wifi_set_config(WIFI_IF_AP, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to set WiFi config data ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout_get_config; + } + +#ifdef CONFIG_DEBUG_WIRELESS_INFO + memcpy(buf, pdata, len); + buf[len] = 0; + wlinfo("INFO: OK to set WiFi SoftAP ssid=%s len=%d\n", buf, len); +#endif + + esp_wifi_lock(false); + return OK; + +errout_get_config: + esp_wifi_lock(false); + return ret; +} + +/**************************************************************************** + * Name: esp_wifi_softap_connect + * + * Description: + * Trigger WiFi SoftAP accept connection action + * + * Input Parameters: + * None + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_softap_connect(void) +{ + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_softap_disconnect + * + * Description: + * Trigger WiFi SoftAP drop connection action + * + * Input Parameters: + * None + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_softap_disconnect(void) +{ + return OK; +} +#endif diff --git a/arch/xtensa/src/esp32/esp32_wifi_adapter.h b/arch/xtensa/src/esp32/esp32_wifi_adapter.h index 5a66d2c002..2de0d5dcb9 100644 --- a/arch/xtensa/src/esp32/esp32_wifi_adapter.h +++ b/arch/xtensa/src/esp32/esp32_wifi_adapter.h @@ -44,6 +44,22 @@ extern "C" * Pre-processor Definitions ****************************************************************************/ +#if defined(CONFIG_ESP32_WIFI_STATION) +# define ESP32_WLAN_HAS_STA +# define ESP32_WLAN_STA_DEVNO 0 +# define ESP32_WLAN_DEVS 1 +#elif defined(CONFIG_ESP32_WIFI_SOFTAP) +# define ESP32_WLAN_HAS_SOFTAP +# define ESP32_WLAN_SOFTAP_DEVNO 0 +# define ESP32_WLAN_DEVS 1 +#elif defined(CONFIG_ESP32_WIFI_STATION_SOFTAP_COEXISTENCE) +# define ESP32_WLAN_HAS_STA +# define ESP32_WLAN_HAS_SOFTAP +# define ESP32_WLAN_STA_DEVNO 0 +# define ESP32_WLAN_SOFTAP_DEVNO 1 +# define ESP32_WLAN_DEVS 2 +#endif + /* WiFi event ID */ enum wifi_adpt_evt_e @@ -60,8 +76,9 @@ enum wifi_adpt_evt_e typedef void (*wifi_evt_cb_t)(void *p); -typedef void (* wifi_tx_done_cb_t)(uint8_t ifidx, uint8_t *data, - uint16_t *len, bool txstatus); +/* WiFi TX done callback function */ + +typedef void (*wifi_txdone_cb_t)(uint8_t *data, uint16_t *len, bool status); /**************************************************************************** * Public Function Prototypes @@ -83,6 +100,22 @@ typedef void (* wifi_tx_done_cb_t)(uint8_t ifidx, uint8_t *data, int esp_wifi_adapter_init(void); +/**************************************************************************** + * 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); + /**************************************************************************** * Name: esp_wifi_notify_subscribe * @@ -100,6 +133,40 @@ int esp_wifi_adapter_init(void); int esp_wifi_notify_subscribe(pid_t pid, FAR struct sigevent *event); +#ifdef ESP32_WLAN_HAS_STA + +/**************************************************************************** + * Name: esp_wifi_sta_start + * + * Description: + * Start WiFi station. + * + * Input Parameters: + * None + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_sta_start(void); + +/**************************************************************************** + * Name: esp_wifi_sta_stop + * + * Description: + * Stop WiFi station. + * + * Input Parameters: + * None + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_sta_stop(void); + /**************************************************************************** * Name: esp_wifi_sta_send_data * @@ -121,10 +188,10 @@ int esp_wifi_sta_send_data(void *pbuf, uint32_t len); * Name: esp_wifi_sta_register_recv_cb * * Description: - * Regitser WiFi receive packet callback function + * Regitser WiFi station receive packet callback function * * Input Parameters: - * input_cb - Receive callback function + * recv_cb - Receive callback function * * Returned Value: * 0 if success or others if fail @@ -135,6 +202,22 @@ int esp_wifi_sta_register_recv_cb(int (*recv_cb)(void *buffer, uint16_t len, void *eb)); +/**************************************************************************** + * Name: esp_wifi_sta_register_txdone_cb + * + * Description: + * Register the station TX done callback function. + * + * Input Parameters: + * cb - The callback function + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_wifi_sta_register_txdone_cb(wifi_txdone_cb_t cb); + /**************************************************************************** * Name: esp_wifi_sta_read_mac * @@ -151,27 +234,11 @@ int esp_wifi_sta_register_recv_cb(int (*recv_cb)(void *buffer, int esp_wifi_sta_read_mac(uint8_t *mac); -/**************************************************************************** - * 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); - /**************************************************************************** * Name: esp_wifi_set_password * * Description: - * Set WiFi password + * Set WiFi station password * * Input Parameters: * pdata - Password buffer pointer @@ -182,13 +249,13 @@ void esp_wifi_free_eb(void *eb); * ****************************************************************************/ -int esp_wifi_set_password(const uint8_t *pdata, uint8_t len); +int esp_wifi_sta_set_password(const uint8_t *pdata, uint8_t len); /**************************************************************************** * Name: esp_wifi_set_ssid * * Description: - * Set WiFi SSID + * Set WiFi station SSID * * Input Parameters: * pdata - SSID buffer pointer @@ -199,13 +266,13 @@ int esp_wifi_set_password(const uint8_t *pdata, uint8_t len); * ****************************************************************************/ -int esp_wifi_set_ssid(const uint8_t *pdata, uint8_t len); +int esp_wifi_sta_set_ssid(const uint8_t *pdata, uint8_t len); /**************************************************************************** - * Name: esp_wifi_connect_internal + * Name: esp_wifi_sta_connect * * Description: - * Trigger WiFi connection action + * Trigger WiFi station connection action * * Input Parameters: * None @@ -215,23 +282,192 @@ int esp_wifi_set_ssid(const uint8_t *pdata, uint8_t len); * ****************************************************************************/ -int esp_wifi_connect_internal(void); +int esp_wifi_sta_connect(void); /**************************************************************************** - * Name: esp_wifi_sta_register_txdone_cb + * Name: esp_wifi_sta_disconnect * * Description: - * Register the txDone callback function of type wifi_tx_done_cb_t + * Trigger WiFi station disconnection action * * Input Parameters: - * callback - The callback function + * None * * Returned Value: * 0 if success or -1 if fail * ****************************************************************************/ -int esp_wifi_sta_register_txdone_cb(void *callback); +int esp_wifi_sta_disconnect(void); +#endif + +#ifdef ESP32_WLAN_HAS_SOFTAP + +/**************************************************************************** + * Name: esp_wifi_softap_start + * + * Description: + * Start WiFi softAP. + * + * Input Parameters: + * None + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_softap_start(void); + +/**************************************************************************** + * Name: esp_wifi_softap_stop + * + * Description: + * Stop WiFi softAP. + * + * Input Parameters: + * None + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_softap_stop(void); + +/**************************************************************************** + * Name: esp_wifi_softap_send_data + * + * Description: + * Use WiFi softAP 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_softap_send_data(void *pbuf, uint32_t len); + +/**************************************************************************** + * Name: esp_wifi_softap_register_recv_cb + * + * Description: + * Regitser WiFi softAP receive packet callback function + * + * Input Parameters: + * recv_cb - Receive callback function + * + * Returned Value: + * 0 if success or others if fail + * + ****************************************************************************/ + +int esp_wifi_softap_register_recv_cb(int (*recv_cb)(void *buffer, + uint16_t len, + void *eb)); + +/**************************************************************************** + * Name: esp_wifi_softap_register_txdone_cb + * + * Description: + * Register the softAP TX done callback function. + * + * Input Parameters: + * cb - The callback function + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_wifi_softap_register_txdone_cb(wifi_txdone_cb_t cb); + +/**************************************************************************** + * Name: esp_wifi_softap_read_mac + * + * Description: + * Read softAP interface MAC address from efuse + * + * Input Parameters: + * mac - MAC address buffer pointer + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_softap_read_mac(uint8_t *mac); + +/**************************************************************************** + * Name: esp_wifi_softap_set_password + * + * Description: + * Set WiFi softAP password + * + * Input Parameters: + * pdata - Password buffer pointer + * len - Password length + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_softap_set_password(const uint8_t *pdata, uint8_t len); + +/**************************************************************************** + * Name: esp_wifi_softap_set_ssid + * + * Description: + * Set WiFi softAP SSID + * + * Input Parameters: + * pdata - SSID buffer pointer + * len - SSID length + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_softap_set_ssid(const uint8_t *pdata, uint8_t len); + +/**************************************************************************** + * Name: esp_wifi_softap_connect + * + * Description: + * Trigger WiFi softAP accept connection action + * + * Input Parameters: + * None + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_softap_connect(void); + +/**************************************************************************** + * Name: esp_wifi_softap_disconnect + * + * Description: + * Trigger WiFi softAP drop connection action + * + * Input Parameters: + * None + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_softap_disconnect(void); +#endif #ifdef __cplusplus } diff --git a/arch/xtensa/src/esp32/esp32_wlan.c b/arch/xtensa/src/esp32/esp32_wlan.c index 6dd7fe9a29..40ed44ea12 100644 --- a/arch/xtensa/src/esp32/esp32_wlan.c +++ b/arch/xtensa/src/esp32/esp32_wlan.c @@ -43,16 +43,12 @@ # include #endif -#include "esp32_wifi_adapter.h" +#include "esp32_wlan.h" /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ -/* WLAN station device ID */ - -#define WLAN_STA_DEVNO (0) - /* TX poll delay = 1 seconds. * CLK_TCK is the number of clock ticks per second */ @@ -79,9 +75,9 @@ #define WLAN_BUF_SIZE (CONFIG_NET_ETH_PKTSIZE) -/* WiFi receive buffer number */ +/* WLAN packet buffer number */ -#define WLAN_RXBUF_NUM (CONFIG_ESP32_WLAN_RXBUF_NUM) +#define WLAN_PKTBUF_NUM (CONFIG_ESP32_WLAN_PKTBUF_NUM) /* Receive threshold which allows the receive function to trigger a scheduler * to activate the application if possible. @@ -98,9 +94,9 @@ * Private Types ****************************************************************************/ -/* Receive buffer */ +/* WLAN packet buffer */ -struct wlan_rxbuf +struct wlan_pktbuf { sq_entry_t entry; /* Queue entry */ @@ -110,12 +106,35 @@ struct wlan_rxbuf uint16_t len; /* Packet data length */ }; +/* WLAN operations */ + +struct wlan_ops +{ + int (*start)(void); + + int (*send)(void *pdata, size_t n); + + int (*ssid)(const uint8_t *pdata, uint8_t n); + + int (*passwd)(const uint8_t *pdata, uint8_t n); + + int (*connect)(void); + + int (*disconnect)(void); + + int (*event)(pid_t pid, FAR struct sigevent *event); + + int (*stop)(void); +}; + /* The wlan_priv_s encapsulates all state information for a single * hardware interface */ struct wlan_priv_s { + bool ref; /* Referernce count */ + bool ifup; /* true:ifup false:ifdown */ struct wdog_s txpoll; /* TX poll timer */ @@ -126,27 +145,25 @@ struct wlan_priv_s struct work_s pollwork; /* Poll work */ struct work_s toutwork; /* Send packet timeout work */ + const struct wlan_ops *ops; /* WLAN operations */ + /* This holds the information visible to the NuttX network */ struct net_driver_s dev; - /* TX buffer */ + /* Packet buffer cache */ - uint8_t txbuf[WLAN_BUF_SIZE]; + struct wlan_pktbuf pktbuf[WLAN_PKTBUF_NUM]; - /* Rest of the data in the TX buffer that need to be sent */ - - uint8_t txrst; - - /* RX buffer cache */ - - struct wlan_rxbuf rxbuf[WLAN_RXBUF_NUM]; - - /* RX buffer queue */ + /* RX packet queue */ sq_queue_t rxb; - /* Free buffer queue */ + /* TX ready packet queue */ + + sq_queue_t txb; + + /* Free packet buffer queue */ sq_queue_t freeb; }; @@ -155,7 +172,35 @@ struct wlan_priv_s * Private Data ****************************************************************************/ -static struct wlan_priv_s g_wlan_priv; +static struct wlan_priv_s g_wlan_priv[ESP32_WLAN_DEVS]; + +#ifdef ESP32_WLAN_HAS_STA +static const struct wlan_ops g_sta_ops = +{ + .start = esp_wifi_sta_start, + .send = esp_wifi_sta_send_data, + .ssid = esp_wifi_sta_set_ssid, + .passwd = esp_wifi_sta_set_password, + .connect = esp_wifi_sta_connect, + .disconnect = esp_wifi_sta_disconnect, + .event = esp_wifi_notify_subscribe, + .stop = esp_wifi_sta_stop +}; +#endif + +#ifdef ESP32_WLAN_HAS_SOFTAP +static const struct wlan_ops g_softap_ops = +{ + .start = esp_wifi_softap_start, + .send = esp_wifi_softap_send_data, + .ssid = esp_wifi_softap_set_ssid, + .passwd = esp_wifi_softap_set_password, + .connect = esp_wifi_softap_connect, + .disconnect = esp_wifi_softap_disconnect, + .event = esp_wifi_notify_subscribe, + .stop = esp_wifi_softap_stop +}; +#endif /**************************************************************************** * Private Function Prototypes @@ -163,7 +208,7 @@ static struct wlan_priv_s g_wlan_priv; /* Common TX logic */ -static int wlan_transmit(FAR struct wlan_priv_s *priv); +static void wlan_transmit(FAR struct wlan_priv_s *priv); static void wlan_rxpoll(FAR void *arg); static int wlan_txpoll(FAR struct net_driver_s *dev); static void wlan_dopoll(FAR struct wlan_priv_s *priv); @@ -197,11 +242,6 @@ static int wlan_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg); #endif -static void wlan_tx_done(uint8_t ifidx, uint8_t *data, - uint16_t *len, bool txstatus); -static int wlan_rx_done(void *buffer, uint16_t len, void *eb); -static int esp32_net_initialize(unsigned int devno); - /**************************************************************************** * Private Functions ****************************************************************************/ @@ -237,17 +277,16 @@ static inline void wlan_init_buffer(struct wlan_priv_s *priv) flags = enter_critical_section(); - priv->txrst = 0; - priv->dev.d_buf = NULL; priv->dev.d_len = 0; sq_init(&priv->freeb); sq_init(&priv->rxb); + sq_init(&priv->txb); - for (i = 0; i < WLAN_RXBUF_NUM; i++) + for (i = 0; i < WLAN_PKTBUF_NUM; i++) { - sq_addlast(&priv->rxbuf[i].entry, &priv->freeb); + sq_addlast(&priv->pktbuf[i].entry, &priv->freeb); } leave_critical_section(flags); @@ -267,23 +306,23 @@ static inline void wlan_init_buffer(struct wlan_priv_s *priv) * ****************************************************************************/ -static inline struct wlan_rxbuf *wlan_alloc_buffer(struct wlan_priv_s *priv) +static inline struct wlan_pktbuf *wlan_alloc_buffer(struct wlan_priv_s *priv) { sq_entry_t *entry; irqstate_t flags; - struct wlan_rxbuf *rxbuf = NULL; + struct wlan_pktbuf *pktbuf = NULL; flags = enter_critical_section(); entry = sq_remfirst(&priv->freeb); if (entry) { - rxbuf = container_of(entry, struct wlan_rxbuf, entry); + pktbuf = container_of(entry, struct wlan_pktbuf, entry); } leave_critical_section(flags); - return rxbuf; + return pktbuf; } /**************************************************************************** @@ -294,7 +333,7 @@ static inline struct wlan_rxbuf *wlan_alloc_buffer(struct wlan_priv_s *priv) * * Input Parameters: * priv - Reference to the driver state structure - * buffer - A pointer to the buffer to be freed + * buffer - A pointer to the packet buffer to be freed * * Returned Value: * None @@ -304,133 +343,173 @@ static inline struct wlan_rxbuf *wlan_alloc_buffer(struct wlan_priv_s *priv) static inline void wlan_free_buffer(struct wlan_priv_s *priv, uint8_t *buffer) { - struct wlan_rxbuf *rxbuf; + struct wlan_pktbuf *pktbuf; irqstate_t flags; flags = enter_critical_section(); - rxbuf = container_of(buffer, struct wlan_rxbuf, buffer); - sq_addlast(&rxbuf->entry, &priv->freeb); + pktbuf = container_of(buffer, struct wlan_pktbuf, buffer); + sq_addlast(&pktbuf->entry, &priv->freeb); leave_critical_section(flags); } /**************************************************************************** - * Name: wifi_tx_available + * Function: wlan_cache_txpkt_tail * * Description: - * Check if WiFi can send data. This function will re-send the rest of the - * data that we failed to send. + * Cache packet from dev->d_buf into tail of TX ready queue. * * Input Parameters: * priv - Reference to the driver state structure * * Returned Value: - * true if available or false if unavailable + * None * ****************************************************************************/ -static bool wifi_tx_available(FAR struct wlan_priv_s *priv) +static inline void wlan_cache_txpkt_tail(struct wlan_priv_s *priv) { - int ret; + struct wlan_pktbuf *pktbuf; + irqstate_t flags; + struct net_driver_s *dev = &priv->dev; - if (priv->txrst) - { - ret = esp_wifi_sta_send_data(priv->txbuf, priv->txrst); - if (ret) - { - ninfo("ERROR: Failed to transmit the rest of the frame\n"); - return false; - } - else - { - priv->txrst = 0; - } - } + pktbuf = container_of(dev->d_buf, struct wlan_pktbuf, buffer); + pktbuf->len = dev->d_len; - return true; + flags = enter_critical_section(); + sq_addlast(&pktbuf->entry, &priv->txb); + leave_critical_section(flags); + + dev->d_buf = NULL; + dev->d_len = 0; } /**************************************************************************** - * Name: wlan_transmit + * Function: wlan_add_txpkt_head * * Description: - * Send the data to WiFi driver. If this sending fails, cache the data - * and re-send it when TX done callback or timer poll function triggers. + * Add packet into head of TX ready queue. * * Input Parameters: * priv - Reference to the driver state structure * * Returned Value: - * OK on success; a negated errno on failure + * None * ****************************************************************************/ -static int wlan_transmit(FAR struct wlan_priv_s *priv) +static inline void wlan_add_txpkt_head(struct wlan_priv_s *priv, + struct wlan_pktbuf *pktbuf) { - int ret; - struct net_driver_s *dev = &priv->dev; - void *buffer = dev->d_buf; - uint32_t len = dev->d_len; + irqstate_t flags; - if (!wifi_tx_available(priv)) - { - return -ENOBUFS; - } - - ret = esp_wifi_sta_send_data(buffer, len); - if (ret) - { - priv->txrst = len; - if (buffer != priv->txbuf) - { - memcpy(priv->txbuf, buffer, len); - } - - wd_start(&priv->txtimeout, WLAN_TXTOUT, - wlan_txtimeout_expiry, (uint32_t)priv); - - return -EIO; - } - else - { - priv->txrst = 0; - } - - return OK; + flags = enter_critical_section(); + sq_addfirst(&pktbuf->entry, &priv->txb); + leave_critical_section(flags); } /**************************************************************************** * Function: wlan_recvframe * * Description: - * Try to receive RX buffer from RX done buffer queue. + * Try to receive RX packet from RX done packet queue. * * Input Parameters: * priv - Reference to the driver state structure * * Returned Value: - * RX buffer if success or NULl if no buffer in queue. + * RX packet if success or NULl if no packet in queue. * ****************************************************************************/ -static struct wlan_rxbuf *wlan_recvframe(FAR struct wlan_priv_s *priv) +static struct wlan_pktbuf *wlan_recvframe(FAR struct wlan_priv_s *priv) { irqstate_t flags; sq_entry_t *entry; - struct wlan_rxbuf *rxbuf = NULL; + struct wlan_pktbuf *pktbuf = NULL; flags = enter_critical_section(); entry = sq_remfirst(&priv->rxb); if (entry) { - rxbuf = container_of(entry, struct wlan_rxbuf, entry); + pktbuf = container_of(entry, struct wlan_pktbuf, entry); } leave_critical_section(flags); - return rxbuf; + return pktbuf; +} + +/**************************************************************************** + * Function: wlan_txframe + * + * Description: + * Try to receive TX buffer from TX ready buffer queue. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * TX packets buffer if success or NULL if no packet in queue. + * + ****************************************************************************/ + +static struct wlan_pktbuf *wlan_txframe(FAR struct wlan_priv_s *priv) +{ + irqstate_t flags; + sq_entry_t *entry; + struct wlan_pktbuf *pktbuf = NULL; + + flags = enter_critical_section(); + + entry = sq_remfirst(&priv->txb); + if (entry) + { + pktbuf = container_of(entry, struct wlan_pktbuf, entry); + } + + leave_critical_section(flags); + + return pktbuf; +} + +/**************************************************************************** + * Name: wlan_transmit + * + * Description: + * Try to send all TX packets in TX ready queue to WiFi driver. If this + * sending fails, then breaks loop and returns. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wlan_transmit(FAR struct wlan_priv_s *priv) +{ + struct wlan_pktbuf *pktbuf; + int ret; + + while ((pktbuf = wlan_txframe(priv))) + { + ret = priv->ops->send(pktbuf->buffer, pktbuf->len); + if (ret < 0) + { + wlan_add_txpkt_head(priv, pktbuf); + wd_start(&priv->txtimeout, WLAN_TXTOUT, + wlan_txtimeout_expiry, (uint32_t)priv); + break; + } + else + { + wlan_free_buffer(priv, pktbuf->buffer); + } + } } /**************************************************************************** @@ -441,21 +520,15 @@ static struct wlan_rxbuf *wlan_recvframe(FAR struct wlan_priv_s *priv) * next packet. * * Input Parameters: - * ifidx - The interface id that the tx callback has been triggered from. - * data - Pointer to the data transmitted. - * len - Length of the data transmitted. - * status - True if data was transmitted successfully or false if failed. + * priv - Reference to the driver state structure * * Returned Value: * None * ****************************************************************************/ -static void wlan_tx_done(uint8_t ifidx, uint8_t *data, - uint16_t *len, bool status) +static void wlan_tx_done(FAR struct wlan_priv_s *priv) { - FAR struct wlan_priv_s *priv = &g_wlan_priv; - wd_cancel(&priv->txtimeout); wlan_txavail(&priv->dev); @@ -469,6 +542,7 @@ static void wlan_tx_done(uint8_t ifidx, uint8_t *data, * packet. * * Input Parameters: + * priv - Reference to the driver state structure * buffer - WiFi received packet buffer * len - Length of received packet * eb - WiFi receive callback input eb pointer @@ -478,11 +552,11 @@ static void wlan_tx_done(uint8_t ifidx, uint8_t *data, * ****************************************************************************/ -static int wlan_rx_done(void *buffer, uint16_t len, void *eb) +static int wlan_rx_done(FAR struct wlan_priv_s *priv, void *buffer, + uint16_t len, void *eb) { - struct wlan_rxbuf *rxbuf; + struct wlan_pktbuf *pktbuf; irqstate_t flags; - FAR struct wlan_priv_s *priv = &g_wlan_priv; int ret = 0; if (!priv->ifup) @@ -498,15 +572,15 @@ static int wlan_rx_done(void *buffer, uint16_t len, void *eb) goto out; } - rxbuf = wlan_alloc_buffer(priv); - if (!rxbuf) + pktbuf = wlan_alloc_buffer(priv); + if (!pktbuf) { ret = -ENOBUFS; goto out; } - memcpy(rxbuf->buffer, buffer, len); - rxbuf->len = len; + memcpy(pktbuf->buffer, buffer, len); + pktbuf->len = len; if (eb) { @@ -514,7 +588,7 @@ static int wlan_rx_done(void *buffer, uint16_t len, void *eb) } flags = enter_critical_section(); - sq_addlast(&rxbuf->entry, &priv->rxb); + sq_addlast(&pktbuf->entry, &priv->rxb); leave_critical_section(flags); if (work_available(&priv->rxwork)) @@ -550,7 +624,7 @@ out: static void wlan_rxpoll(FAR void *arg) { - struct wlan_rxbuf *rxbuf; + struct wlan_pktbuf *pktbuf; struct eth_hdr_s *eth_hdr; FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)arg; FAR struct net_driver_s *dev = &priv->dev; @@ -558,19 +632,23 @@ static void wlan_rxpoll(FAR void *arg) uint32_t rbytes = 0; #endif + /* Try to send all cached TX packets for TX ack and so on */ + + wlan_transmit(priv); + /* Loop while while wlan_recvframe() successfully retrieves valid * Ethernet frames. */ net_lock(); - while ((rxbuf = wlan_recvframe(priv)) != NULL) + while ((pktbuf = wlan_recvframe(priv)) != NULL) { - dev->d_buf = rxbuf->buffer; - dev->d_len = rxbuf->len; + dev->d_buf = pktbuf->buffer; + dev->d_len = pktbuf->len; #ifdef WLAN_RX_THRESHOLD - rbytes += rxbuf->len; + rbytes += pktbuf->len; #endif #ifdef CONFIG_NET_PKT @@ -642,7 +720,7 @@ static void wlan_rxpoll(FAR void *arg) /* And send the packet */ - wlan_transmit(priv); + wlan_cache_txpkt_tail(priv); } } else @@ -680,7 +758,7 @@ static void wlan_rxpoll(FAR void *arg) /* And send the packet */ - wlan_transmit(priv); + wlan_cache_txpkt_tail(priv); } } else @@ -701,7 +779,7 @@ static void wlan_rxpoll(FAR void *arg) if (priv->dev.d_len > 0) { - wlan_transmit(priv); + wlan_cache_txpkt_tail(priv); } } else @@ -740,7 +818,11 @@ static void wlan_rxpoll(FAR void *arg) #endif } - net_unlock(); + /* Try to send all cached TX packets */ + + wlan_transmit(priv); + + net_unlock(); } /**************************************************************************** @@ -751,7 +833,7 @@ static void wlan_rxpoll(FAR void *arg) * packets ready to send. This is a callback from devif_poll(). * devif_poll() may be called: * - * 1. When the preceding TX packet send times out and the interface is + * 1. When the preceding TX packets send times out and the interface is * reset * 2. During normal TX polling * @@ -765,6 +847,7 @@ static void wlan_rxpoll(FAR void *arg) static int wlan_txpoll(FAR struct net_driver_s *dev) { + struct wlan_pktbuf *pktbuf; FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)dev->d_private; DEBUGASSERT(dev->d_buf != NULL); @@ -797,11 +880,16 @@ static int wlan_txpoll(FAR struct net_driver_s *dev) } #endif /* CONFIG_NET_IPv6 */ - int ret = wlan_transmit(priv); - if (ret) + wlan_cache_txpkt_tail(priv); + + pktbuf = wlan_alloc_buffer(priv); + if (!pktbuf) { - return -EBUSY; + return -ENOMEM; } + + dev->d_buf = pktbuf->buffer; + dev->d_len = WLAN_BUF_SIZE; } /* If zero is returned, the polling will continue until @@ -833,19 +921,40 @@ static int wlan_txpoll(FAR struct net_driver_s *dev) static void wlan_dopoll(FAR struct wlan_priv_s *priv) { FAR struct net_driver_s *dev = &priv->dev; + struct wlan_pktbuf *pktbuf; + uint8_t *txbuf; + int ret; - if (!wifi_tx_available(priv)) + pktbuf = wlan_alloc_buffer(priv); + if (!pktbuf) { return ; } - dev->d_buf = priv->txbuf; + dev->d_buf = pktbuf->buffer; + dev->d_len = WLAN_BUF_SIZE; - /* If so, then poll the network for new XMIT data */ + /* Try to let TCP/IP to send all packets to netcard driver */ - devif_timer(dev, 0, wlan_txpoll); + do + { + txbuf = dev->d_buf; + ret = devif_poll(dev, wlan_txpoll); + } + while ((ret == 0) && + (dev->d_buf != txbuf)); - dev->d_buf = NULL; + if (dev->d_buf) + { + wlan_free_buffer(priv, dev->d_buf); + + dev->d_buf = NULL; + dev->d_len = 0; + } + + /* Try to send all cached TX packets */ + + wlan_transmit(priv); } /**************************************************************************** @@ -866,6 +975,10 @@ static void wlan_txtimeout_work(void *arg) { struct wlan_priv_s *priv = (struct wlan_priv_s *)arg; + /* Try to send all cached TX packets */ + + wlan_transmit(priv); + net_lock(); wlan_ifdown(&priv->dev); @@ -928,6 +1041,7 @@ static void wlan_poll_work(FAR void *arg) int32_t delay = WLAN_WDDELAY; FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)arg; struct net_driver_s *dev = &priv->dev; + struct wlan_pktbuf *pktbuf; /* Lock the network and serialize driver operations if necessary. * NOTE: Serialization is only required in the case where the driver work @@ -937,30 +1051,41 @@ static void wlan_poll_work(FAR void *arg) net_lock(); - /* Check if there is room in the send another TX packet. We cannot perform + pktbuf = wlan_alloc_buffer(priv); + if (!pktbuf) + { + delay = 1; + goto exit; + } + + dev->d_buf = pktbuf->buffer; + dev->d_len = WLAN_BUF_SIZE; + + /* Check if there is room in the send another TX packets. We cannot perform * the TX poll if he are unable to accept another packet for transmission. * * If there is no room, we should reset the timeout value to be 1 to * trigger the timer as soon as possible. */ - if (!wifi_tx_available(priv)) - { - delay = 1; - goto exit; - } - - dev->d_buf = priv->txbuf; - /* Update TCP timing states and poll the network for new XMIT data. */ devif_timer(&priv->dev, delay, wlan_txpoll); - dev->d_buf = NULL; + if (dev->d_buf) + { + wlan_free_buffer(priv, dev->d_buf); + + dev->d_buf = NULL; + dev->d_len = 0; + } + + /* Try to send all cached TX packets */ + + wlan_transmit(priv); exit: wd_start(&priv->txpoll, delay, wlan_poll_expiry, (wdparm_t)priv); - net_unlock(); } @@ -1010,6 +1135,10 @@ static void wlan_txavail_work(FAR void *arg) { FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)arg; + /* Try to send all cached TX packets even if net is down */ + + wlan_transmit(priv); + /* Lock the network and serialize driver operations if necessary. * NOTE: Serialization is only required in the case where the driver work * is performed on an LP worker thread and where more than one LP worker @@ -1047,6 +1176,7 @@ static void wlan_txavail_work(FAR void *arg) static int wlan_ifup(FAR struct net_driver_s *dev) { + int ret; FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)dev->d_private; #ifdef CONFIG_NET_IPv4 @@ -1069,6 +1199,14 @@ static int wlan_ifup(FAR struct net_driver_s *dev) return OK; } + ret = priv->ops->start(); + if (ret < 0) + { + net_unlock(); + nerr("ERROR: Failed to start WiFi ret=%d\n", ret); + return ret; + } + #ifdef CONFIG_NET_ICMPv6 /* Set up IPv6 multicast address filtering */ @@ -1105,6 +1243,7 @@ static int wlan_ifup(FAR struct net_driver_s *dev) static int wlan_ifdown(FAR struct net_driver_s *dev) { + int ret; FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)dev->d_private; net_lock(); @@ -1124,6 +1263,12 @@ static int wlan_ifdown(FAR struct net_driver_s *dev) priv->ifup = false; + ret = priv->ops->stop(); + if (ret < 0) + { + nerr("ERROR: Failed to stop WiFi ret=%d\n", ret); + } + net_unlock(); return OK; @@ -1308,9 +1453,9 @@ static int wlan_ioctl(FAR struct net_driver_s *dev, unsigned long arg) { int ret; - struct iw_point *essid; - struct iw_encode_ext *ext; struct iwreq *iwr = (struct iwreq *)arg; + struct wlan_priv_s *priv = (struct wlan_priv_s *)dev->d_private; + const struct wlan_ops *ops = priv->ops; /* Decode and dispatch the driver-specific IOCTL command */ @@ -1321,8 +1466,8 @@ static int wlan_ioctl(FAR struct net_driver_s *dev, case SIOCMIINOTIFY: /* Set up for PHY event notifications */ { struct mii_ioctl_notify_s *req = (struct mii_ioctl_notify_s *)arg; - ret = esp_wifi_notify_subscribe(req->pid, &req->event); - if (ret) + ret = ops->event(req->pid, &req->event); + if (ret < 0) { nerr("ERROR: Failed to subscribe event\n"); } @@ -1333,9 +1478,9 @@ static int wlan_ioctl(FAR struct net_driver_s *dev, case SIOCSIWENCODEEXT: { - ext = iwr->u.encoding.pointer; - ret = esp_wifi_set_password(ext->key, ext->key_len); - if (ret) + struct iw_encode_ext *ext = iwr->u.encoding.pointer; + ret = ops->passwd(ext->key, ext->key_len); + if (ret < 0) { nerr("ERROR: Failed to set password\n"); } @@ -1343,20 +1488,31 @@ static int wlan_ioctl(FAR struct net_driver_s *dev, break; case SIOCSIWESSID: { - iwr = (struct iwreq *)arg; - essid = &iwr->u.essid; - ret = esp_wifi_set_ssid(essid->pointer, essid->length); - if (ret) + struct iw_point *essid = &iwr->u.essid; + if (essid->length) { - nerr("ERROR: Failed to set SSID\n"); - break; - } + ret = ops->ssid(essid->pointer, essid->length); + if (ret < 0) + { + nerr("ERROR: Failed to set SSID\n"); + break; + } - ret = esp_wifi_connect_internal(); - if (ret) + ret = ops->connect(); + if (ret < 0) + { + nerr("ERROR: Failed to connect\n"); + break; + } + } + else { - nerr("ERROR: Failed to start connecting\n"); - break; + ret = ops->disconnect(); + if (ret < 0) + { + nerr("ERROR: Failed to connect\n"); + break; + } } } break; @@ -1386,86 +1542,169 @@ static int wlan_ioctl(FAR struct net_driver_s *dev, * Initialize the esp32 driver * * Input Parameters: - * devno - The device number. + * devno - The device number + * mac_addr - MAC address * * Returned Value: * OK on success; Negated errno on failure. * ****************************************************************************/ -static int esp32_net_initialize(unsigned int devno) +static int esp32_net_initialize(int devno, uint8_t *mac_addr, + const struct wlan_ops *ops) { int ret; - uint8_t eth_mac[6]; FAR struct wlan_priv_s *priv; + FAR struct net_driver_s *netdev; - /* Get the interface structure associated with this interface number. */ + priv = &g_wlan_priv[devno]; + if (priv->ref) + { + priv->ref++; + return OK; + } - priv = &g_wlan_priv; + netdev = &priv->dev; /* Initialize the driver structure */ memset(priv, 0, sizeof(struct wlan_priv_s)); - priv->dev.d_ifup = wlan_ifup; /* I/F down callback */ - priv->dev.d_ifdown = wlan_ifdown; /* I/F up (new IP address) callback */ - priv->dev.d_txavail = wlan_txavail; /* New TX data callback */ + netdev->d_ifup = wlan_ifup; /* I/F down callback */ + netdev->d_ifdown = wlan_ifdown; /* I/F up (new IP address) callback */ + netdev->d_txavail = wlan_txavail; /* New TX data callback */ #ifdef CONFIG_NET_MCASTGROUP - priv->dev.d_addmac = wlan_addmac; /* Add multicast MAC address */ - priv->dev.d_rmmac = wlan_rmmac; /* Remove multicast MAC address */ + netdev->d_addmac = wlan_addmac; /* Add multicast MAC address */ + netdev->d_rmmac = wlan_rmmac; /* Remove multicast MAC address */ #endif #ifdef CONFIG_NETDEV_IOCTL - priv->dev.d_ioctl = wlan_ioctl; /* Handle network IOCTL commands */ + netdev->d_ioctl = wlan_ioctl; /* Handle network IOCTL commands */ #endif /* Used to recover private state from dev */ - priv->dev.d_private = (void *)&g_wlan_priv; + netdev->d_private = (void *)priv; - /* Create a watchdog for timing polling for and timing of transmissions */ + memcpy(netdev->d_mac.ether.ether_addr_octet, mac_addr, 6); - esp_wifi_sta_read_mac(eth_mac); - - memcpy(priv->dev.d_mac.ether.ether_addr_octet, eth_mac, sizeof(eth_mac)); - - ninfo("%02X:%02X:%02X:%02X:%02X:%02X \r\n", - eth_mac[0], eth_mac[1], eth_mac[2], - eth_mac[3], eth_mac[4], eth_mac[5]); - - /* Put the interface in the down state. */ - - wlan_ifdown(&priv->dev); - - ret = netdev_register(&priv->dev, NET_LL_IEEE80211); - if (ret) + ret = netdev_register(netdev, NET_LL_IEEE80211); + if (ret < 0) { nerr("ERROR: Initialization of Ethernet block failed: %d\n", ret); return ret; } - ret = esp_wifi_adapter_init(); - if (ret) - { - nerr("ERROR: Initialize WiFi adapter error: %d\n", ret); - netdev_unregister(&priv->dev); - return ret; - } + priv->ops = ops; - ret = esp_wifi_sta_register_recv_cb(wlan_rx_done); - if (ret) - { - DEBUGASSERT(0); - } + priv->ref++; - ret = esp_wifi_sta_register_txdone_cb(wlan_tx_done); - if (ret) - { - DEBUGASSERT(0); - } + ninfo("INFO: Initialize WiFi adapter No.%d success\n", devno); return OK; } +/**************************************************************************** + * Function: wlan_sta_rx_done + * + * Description: + * WiFi station RX done callback function. If this is called, it means + * station receiveing packet. + * + * Input Parameters: + * buffer - WiFi received packet buffer + * len - Length of received packet + * eb - WiFi receive callback input eb pointer + * + * Returned Value: + * 0 on success or a negated errno on failure + * + ****************************************************************************/ + +#ifdef ESP32_WLAN_HAS_STA +static int wlan_sta_rx_done(void *buffer, uint16_t len, void *eb) +{ + FAR struct wlan_priv_s *priv = &g_wlan_priv[ESP32_WLAN_STA_DEVNO]; + + return wlan_rx_done(priv, buffer, len, eb); +} + +/**************************************************************************** + * Name: wlan_sta_tx_done + * + * Description: + * WiFi station TX done callback function. If this is called, it means + * station sending next packet. + * + * Input Parameters: + * ifidx - The interface id that the tx callback has been triggered from. + * data - Pointer to the data transmitted. + * len - Length of the data transmitted. + * status - True if data was transmitted successfully or false if failed. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wlan_sta_tx_done(uint8_t *data, uint16_t *len, bool status) +{ + FAR struct wlan_priv_s *priv = &g_wlan_priv[ESP32_WLAN_STA_DEVNO]; + + wlan_tx_done(priv); +} +#endif + +/**************************************************************************** + * Function: wlan_softap_rx_done + * + * Description: + * WiFi softAP RX done callback function. If this is called, it means + * softAP receiveing packet. + * + * Input Parameters: + * buffer - WiFi received packet buffer + * len - Length of received packet + * eb - WiFi receive callback input eb pointer + * + * Returned Value: + * 0 on success or a negated errno on failure + * + ****************************************************************************/ + +#ifdef ESP32_WLAN_HAS_SOFTAP +static int wlan_softap_rx_done(void *buffer, uint16_t len, void *eb) +{ + FAR struct wlan_priv_s *priv = &g_wlan_priv[ESP32_WLAN_SOFTAP_DEVNO]; + + return wlan_rx_done(priv, buffer, len, eb); +} + +/**************************************************************************** + * Name: wlan_softap_tx_done + * + * Description: + * WiFi softAP TX done callback function. If this is called, it means + * softAP sending next packet. + * + * Input Parameters: + * ifidx - The interface id that the tx callback has been triggered from. + * data - Pointer to the data transmitted. + * len - Length of the data transmitted. + * status - True if data was transmitted successfully or false if failed. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wlan_softap_tx_done(uint8_t *data, uint16_t *len, bool status) +{ + FAR struct wlan_priv_s *priv = &g_wlan_priv[ESP32_WLAN_SOFTAP_DEVNO]; + + wlan_tx_done(priv); +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -1484,9 +1723,111 @@ static int esp32_net_initialize(unsigned int devno) * ****************************************************************************/ +#ifdef ESP32_WLAN_HAS_STA int esp32_wlan_sta_initialize(void) { - return esp32_net_initialize(WLAN_STA_DEVNO); + int ret; + uint8_t eth_mac[6]; + + ret = esp_wifi_adapter_init(); + if (ret < 0) + { + nerr("ERROR: Initialize WiFi adapter error: %d\n", ret); + return ret; + } + + ret = esp_wifi_sta_read_mac(eth_mac); + if (ret < 0) + { + nerr("ERROR: Failed to read MAC address\n"); + return ret; + } + + ninfo("WiFi station MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", + eth_mac[0], eth_mac[1], eth_mac[2], + eth_mac[3], eth_mac[4], eth_mac[5]); + + ret = esp32_net_initialize(ESP32_WLAN_STA_DEVNO, eth_mac, &g_sta_ops); + if (ret < 0) + { + nerr("ERROR: Failed to initialize net\n"); + return ret; + } + + ret = esp_wifi_sta_register_recv_cb(wlan_sta_rx_done); + if (ret < 0) + { + nerr("ERROR: Failed to register RX callback\n"); + return ret; + } + + esp_wifi_sta_register_txdone_cb(wlan_sta_tx_done); + + ninfo("INFO: Initialize WiFi station success net\n"); + + return OK; } +#endif + +/**************************************************************************** + * Name: esp32_wlan_softap_initialize + * + * Description: + * Initialize the esp32 WLAN softAP netcard driver + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +#ifdef ESP32_WLAN_HAS_SOFTAP +int esp32_wlan_softap_initialize(void) +{ + int ret; + uint8_t eth_mac[6]; + + ret = esp_wifi_adapter_init(); + if (ret < 0) + { + nerr("ERROR: Initialize WiFi adapter error: %d\n", ret); + return ret; + } + + ret = esp_wifi_softap_read_mac(eth_mac); + if (ret < 0) + { + nerr("ERROR: Failed to read MAC address\n"); + return ret; + } + + ninfo("WiFi softAP MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", + eth_mac[0], eth_mac[1], eth_mac[2], + eth_mac[3], eth_mac[4], eth_mac[5]); + + ret = esp32_net_initialize(ESP32_WLAN_SOFTAP_DEVNO, eth_mac, + &g_softap_ops); + if (ret < 0) + { + nerr("ERROR: Failed to initialize net\n"); + return ret; + } + + ret = esp_wifi_softap_register_recv_cb(wlan_softap_rx_done); + if (ret < 0) + { + nerr("ERROR: Failed to register RX callback\n"); + return ret; + } + + esp_wifi_softap_register_txdone_cb(wlan_softap_tx_done); + + ninfo("INFO: Initialize WiFi softAP net success\n"); + + return OK; +} +#endif #endif /* CONFIG_ESP32_WIRELESS */ diff --git a/arch/xtensa/src/esp32/esp32_wlan.h b/arch/xtensa/src/esp32/esp32_wlan.h index ce492272bc..9ba5b04711 100644 --- a/arch/xtensa/src/esp32/esp32_wlan.h +++ b/arch/xtensa/src/esp32/esp32_wlan.h @@ -27,6 +27,8 @@ #include +#include "esp32_wifi_adapter.h" + #ifndef __ASSEMBLY__ #undef EXTERN @@ -58,7 +60,27 @@ extern "C" * ****************************************************************************/ +#ifdef ESP32_WLAN_HAS_STA int esp32_wlan_sta_initialize(void); +#endif + +/**************************************************************************** + * Name: esp32_wlan_softap_initialize + * + * Description: + * Initialize the esp32 WLAN softAP netcard driver + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +#ifdef ESP32_WLAN_HAS_SOFTAP +int esp32_wlan_softap_initialize(void); +#endif #endif /* CONFIG_ESP32_WIRELESS */ #ifdef __cplusplus diff --git a/boards/xtensa/esp32/esp32-devkitc/configs/sta_softap/defconfig b/boards/xtensa/esp32/esp32-devkitc/configs/sta_softap/defconfig new file mode 100644 index 0000000000..f7fc520de4 --- /dev/null +++ b/boards/xtensa/esp32/esp32-devkitc/configs/sta_softap/defconfig @@ -0,0 +1,85 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_LEDS is not set +# CONFIG_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +# CONFIG_NSH_CMDPARMS is not set +# CONFIG_NSH_NETINIT is not set +CONFIG_ARCH="xtensa" +CONFIG_ARCH_BOARD="esp32-devkitc" +CONFIG_ARCH_BOARD_ESP32_DEVKITC=y +CONFIG_ARCH_CHIP="esp32" +CONFIG_ARCH_CHIP_ESP32=y +CONFIG_ARCH_CHIP_ESP32WROVER=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARCH_XTENSA=y +CONFIG_BOARD_LOOPSPERMSEC=16717 +CONFIG_BUILTIN=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_ERROR=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_WARN=y +CONFIG_DEBUG_WIRELESS=y +CONFIG_DEBUG_WIRELESS_ERROR=y +CONFIG_DRIVERS_IEEE80211=y +CONFIG_DRIVERS_WIRELESS=y +CONFIG_ESP32_MTD_SIZE=0x80000 +CONFIG_ESP32_SPIFLASH=y +CONFIG_ESP32_UART0=y +CONFIG_ESP32_WIFI_SAVE_PARAM=y +CONFIG_ESP32_WIFI_STATION_SOFTAP_COEXISTENCE=y +CONFIG_ESP32_WIRELESS=y +CONFIG_EXAMPLES_DHCPD=y +CONFIG_EXPERIMENTAL=y +CONFIG_FS_PROCFS=y +CONFIG_FS_SPIFFS=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_IDLETHREAD_STACKSIZE=3072 +CONFIG_INTELHEX_BINARY=y +CONFIG_MAX_TASKS=16 +CONFIG_MM_REGIONS=2 +CONFIG_NETDB_DNSCLIENT=y +CONFIG_NETDEV_LATEINIT=y +CONFIG_NETDEV_PHY_IOCTL=y +CONFIG_NETDEV_WIRELESS_IOCTL=y +CONFIG_NETUTILS_DHCPD=y +CONFIG_NET_BROADCAST=y +CONFIG_NET_ETH_PKTSIZE=1514 +CONFIG_NET_ICMP=y +CONFIG_NET_ICMP_SOCKET=y +CONFIG_NET_SOCKOPTS=y +CONFIG_NET_UDP=y +CONFIG_NFILE_DESCRIPTORS=8 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_PTHREAD_MUTEX_TYPES=y +CONFIG_RAM_SIZE=114688 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_SDCLONE_DISABLE=y +CONFIG_SIG_DEFAULT=y +CONFIG_SPIFFS_NAME_MAX=48 +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_SYSTEM_DHCPC_RENEW=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_PING=y +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_USER_ENTRYPOINT="nsh_main" +CONFIG_WIRELESS=y +CONFIG_WIRELESS_WAPI=y +CONFIG_WIRELESS_WAPI_CMDTOOL=y diff --git a/boards/xtensa/esp32/esp32-devkitc/src/esp32_bringup.c b/boards/xtensa/esp32/esp32-devkitc/src/esp32_bringup.c index 195bbf5621..f12193aa7f 100644 --- a/boards/xtensa/esp32/esp32-devkitc/src/esp32_bringup.c +++ b/boards/xtensa/esp32/esp32-devkitc/src/esp32_bringup.c @@ -230,14 +230,25 @@ int esp32_bringup(void) #endif #ifdef CONFIG_NET +#ifdef ESP32_WLAN_HAS_STA ret = esp32_wlan_sta_initialize(); if (ret) { - syslog(LOG_ERR, "ERROR: Failed to initialize WiFi\n"); + syslog(LOG_ERR, "ERROR: Failed to initialize WiFi station\n"); return ret; } #endif +#ifdef ESP32_WLAN_HAS_SOFTAP + ret = esp32_wlan_softap_initialize(); + if (ret) + { + syslog(LOG_ERR, "ERROR: Failed to initialize WiFi softAP\n"); + return ret; + } +#endif +#endif + #endif #ifdef CONFIG_TIMER diff --git a/boards/xtensa/esp32/esp32-ethernet-kit/src/esp32_bringup.c b/boards/xtensa/esp32/esp32-ethernet-kit/src/esp32_bringup.c index a858258554..12bc61c910 100644 --- a/boards/xtensa/esp32/esp32-ethernet-kit/src/esp32_bringup.c +++ b/boards/xtensa/esp32/esp32-ethernet-kit/src/esp32_bringup.c @@ -190,14 +190,25 @@ int esp32_bringup(void) #endif #ifdef CONFIG_NET +#ifdef ESP32_WLAN_HAS_STA ret = esp32_wlan_sta_initialize(); if (ret) { - syslog(LOG_ERR, "ERROR: Failed to initialize WiFi\n"); + syslog(LOG_ERR, "ERROR: Failed to initialize WiFi station\n"); return ret; } #endif +#ifdef ESP32_WLAN_HAS_SOFTAP + ret = esp32_wlan_softap_initialize(); + if (ret) + { + syslog(LOG_ERR, "ERROR: Failed to initialize WiFi softAP\n"); + return ret; + } +#endif +#endif + #endif #ifdef CONFIG_TIMER diff --git a/boards/xtensa/esp32/esp32-wrover-kit/src/esp32_bringup.c b/boards/xtensa/esp32/esp32-wrover-kit/src/esp32_bringup.c index 7d2d05a1a3..06e374b407 100644 --- a/boards/xtensa/esp32/esp32-wrover-kit/src/esp32_bringup.c +++ b/boards/xtensa/esp32/esp32-wrover-kit/src/esp32_bringup.c @@ -199,14 +199,25 @@ int esp32_bringup(void) #endif #ifdef CONFIG_NET +#ifdef ESP32_WLAN_HAS_STA ret = esp32_wlan_sta_initialize(); if (ret) { - syslog(LOG_ERR, "ERROR: Failed to initialize WiFi\n"); + syslog(LOG_ERR, "ERROR: Failed to initialize WiFi station\n"); return ret; } #endif +#ifdef ESP32_WLAN_HAS_SOFTAP + ret = esp32_wlan_softap_initialize(); + if (ret) + { + syslog(LOG_ERR, "ERROR: Failed to initialize WiFi softAP\n"); + return ret; + } +#endif +#endif + #endif #ifdef CONFIG_TIMER