diff --git a/components/esp32/cpu_start.c b/components/esp32/cpu_start.c index e66ed10cb..e1a5f027b 100644 --- a/components/esp32/cpu_start.c +++ b/components/esp32/cpu_start.c @@ -198,7 +198,7 @@ static void do_global_ctors(void) { (*p)(); } -extern esp_err_t app_main(); +extern esp_err_t app_main(void *ctx); void user_start_cpu0(void) { ets_setup_syscalls(); @@ -214,16 +214,16 @@ void user_start_cpu0(void) { system_init(); - esp_event_init(NULL); + esp_event_init(NULL, NULL); tcpip_adapter_init(); #endif #if CONFIG_WIFI_ENABLED && CONFIG_WIFI_AUTO_STARTUP #include "esp_wifi.h" - esp_wifi_startup(app_main); + esp_wifi_startup(app_main, NULL); #else - app_main(); + app_main(NULL); #endif ets_printf("Starting scheduler on PRO CPU.\n"); diff --git a/components/esp32/event.c b/components/esp32/event.c index 92b751038..53ffd642e 100644 --- a/components/esp32/event.c +++ b/components/esp32/event.c @@ -11,6 +11,7 @@ // 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. + #include #include #include @@ -29,10 +30,13 @@ #define ESP32_WORKAROUND 1 #if CONFIG_WIFI_ENABLED +static bool event_init_flag = false; static xQueueHandle g_event_handler = NULL; -static system_event_cb_t g_event_handler_cb; -#define WIFI_DEBUG(...) +static system_event_cb_t g_event_handler_cb; +static void *g_event_ctx; + +#define WIFI_DEBUG(...) #define WIFI_API_CALL_CHECK(info, api_call, ret) \ do{\ esp_err_t __err = (api_call);\ @@ -43,6 +47,7 @@ do{\ } while(0) typedef esp_err_t (*system_event_handle_fn_t)(system_event_t *e); + typedef struct { system_event_id_t event_id; system_event_handle_fn_t event_handle; @@ -55,7 +60,7 @@ static esp_err_t system_event_sta_start_handle_default(system_event_t *event); static esp_err_t system_event_sta_stop_handle_default(system_event_t *event); static esp_err_t system_event_sta_connected_handle_default(system_event_t *event); static esp_err_t system_event_sta_disconnected_handle_default(system_event_t *event); -static esp_err_t system_event_sta_gotip_default(system_event_t *event); +static esp_err_t system_event_sta_got_ip_default(system_event_t *event); static system_event_handle_t g_system_event_handle_table[] = { {SYSTEM_EVENT_WIFI_READY, NULL}, @@ -65,7 +70,7 @@ static system_event_handle_t g_system_event_handle_table[] = { {SYSTEM_EVENT_STA_CONNECTED, system_event_sta_connected_handle_default}, {SYSTEM_EVENT_STA_DISCONNECTED, system_event_sta_disconnected_handle_default}, {SYSTEM_EVENT_STA_AUTHMODE_CHANGE, NULL}, - {SYSTEM_EVENT_STA_GOTIP, system_event_sta_gotip_default}, + {SYSTEM_EVENT_STA_GOT_IP, system_event_sta_got_ip_default}, {SYSTEM_EVENT_AP_START, system_event_ap_start_handle_default}, {SYSTEM_EVENT_AP_STOP, system_event_ap_stop_handle_default}, {SYSTEM_EVENT_AP_STACONNECTED, NULL}, @@ -74,15 +79,15 @@ static system_event_handle_t g_system_event_handle_table[] = { {SYSTEM_EVENT_MAX, NULL}, }; -static esp_err_t system_event_sta_gotip_default(system_event_t *event) +static esp_err_t system_event_sta_got_ip_default(system_event_t *event) { extern esp_err_t esp_wifi_set_sta_ip(void); WIFI_API_CALL_CHECK("esp_wifi_set_sta_ip", esp_wifi_set_sta_ip(), ESP_OK); printf("ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR "\n", - IP2STR(&event->event_info.got_ip.ip_info.ip), - IP2STR(&event->event_info.got_ip.ip_info.netmask), - IP2STR(&event->event_info.got_ip.ip_info.gw)); + IP2STR(&event->event_info.got_ip.ip_info.ip), + IP2STR(&event->event_info.got_ip.ip_info.netmask), + IP2STR(&event->event_info.got_ip.ip_info.gw)); return ESP_OK; } @@ -132,7 +137,7 @@ esp_err_t system_event_sta_stop_handle_default(system_event_t *event) esp_err_t system_event_sta_connected_handle_default(system_event_t *event) { tcpip_adapter_dhcp_status_t status; - + WIFI_API_CALL_CHECK("esp_wifi_reg_rxcb", esp_wifi_reg_rxcb(WIFI_IF_STA, (wifi_rxcb_t)tcpip_adapter_sta_input), ESP_OK); tcpip_adapter_up(TCPIP_ADAPTER_IF_STA); @@ -150,7 +155,7 @@ esp_err_t system_event_sta_connected_handle_default(system_event_t *event) system_event_t evt; //notify event - evt.event_id = SYSTEM_EVENT_STA_GOTIP; + evt.event_id = SYSTEM_EVENT_STA_GOT_IP; memcpy(&evt.event_info.got_ip.ip_info, &sta_ip, sizeof(tcpip_adapter_ip_info_t)); esp_event_send(&evt); @@ -172,7 +177,7 @@ esp_err_t system_event_sta_disconnected_handle_default(system_event_t *event) static esp_err_t esp_wifi_post_event_to_user(system_event_t *event) { if (g_event_handler_cb) { - return (*g_event_handler_cb)(event); + return (*g_event_handler_cb)(g_event_ctx, event); } return ESP_OK; @@ -187,102 +192,88 @@ static esp_err_t esp_system_event_debug(system_event_t *event) WIFI_DEBUG("received event: "); switch (event->event_id) { - case SYSTEM_EVENT_WIFI_READY: - { - WIFI_DEBUG("SYSTEM_EVENT_WIFI_READY\n"); - break; - } - case SYSTEM_EVENT_SCAN_DONE: - { - system_event_sta_scan_done_t *scan_done; - scan_done = &event->event_info.scan_done; - WIFI_DEBUG("SYSTEM_EVENT_SCAN_DONE\nstatus:%d, number:%d\n", scan_done->status, scan_done->number); - break; - } - case SYSTEM_EVENT_STA_START: - { - WIFI_DEBUG("SYSTEM_EVENT_STA_START\n"); - break; - } - case SYSTEM_EVENT_STA_STOP: - { - WIFI_DEBUG("SYSTEM_EVENT_STA_STOP\n"); - break; - } - case SYSTEM_EVENT_STA_CONNECTED: - { - system_event_sta_connected_t *connected; - connected = &event->event_info.connected; - WIFI_DEBUG("SYSTEM_EVENT_STA_CONNECTED\nssid:%s, ssid_len:%d, bssid:%02x:%02x:%02x:%02x:%02x:%02x, channel:%d, authmode:%d\n", \ - connected->ssid, connected->ssid_len, connected->bssid[0], connected->bssid[0], connected->bssid[1], \ - connected->bssid[3], connected->bssid[4], connected->bssid[5], connected->channel, connected->authmode); - break; - } - case SYSTEM_EVENT_STA_DISCONNECTED: - { - system_event_sta_disconnected_t *disconnected; - disconnected = &event->event_info.disconnected; - WIFI_DEBUG("SYSTEM_EVENT_STA_DISCONNECTED\nssid:%s, ssid_len:%d, bssid:%02x:%02x:%02x:%02x:%02x:%02x, reason:%d\n", \ - disconnected->ssid, disconnected->ssid_len, disconnected->bssid[0], disconnected->bssid[0], disconnected->bssid[1], \ - disconnected->bssid[3], disconnected->bssid[4], disconnected->bssid[5], disconnected->reason); - break; - } - case SYSTEM_EVENT_STA_AUTHMODE_CHANGE: - { - system_event_sta_authmode_change_t *auth_change; - auth_change = &event->event_info.auth_change; - WIFI_DEBUG("SYSTEM_EVENT_STA_AUTHMODE_CHNAGE\nold_mode:%d, new_mode:%d\n", auth_change->old_mode, auth_change->new_mode); - break; - } - case SYSTEM_EVENT_STA_GOTIP: - { - system_event_sta_got_ip_t *got_ip; - got_ip = &event->event_info.got_ip; - WIFI_DEBUG("SYSTEM_EVENT_STA_GOTIP\n"); - break; - } - case SYSTEM_EVENT_AP_START: - { - WIFI_DEBUG("SYSTEM_EVENT_AP_START\n"); - break; - } - case SYSTEM_EVENT_AP_STOP: - { - WIFI_DEBUG("SYSTEM_EVENT_AP_STOP\n"); - break; - } - case SYSTEM_EVENT_AP_STACONNECTED: - { - system_event_ap_staconnected_t *staconnected; - staconnected = &event->event_info.sta_connected; - WIFI_DEBUG("SYSTEM_EVENT_AP_STACONNECTED\nmac:%02x:%02x:%02x:%02x:%02x:%02x, aid:%d\n", \ - staconnected->mac[0], staconnected->mac[0], staconnected->mac[1], \ - staconnected->mac[3], staconnected->mac[4], staconnected->mac[5], staconnected->aid); - break; - } - case SYSTEM_EVENT_AP_STADISCONNECTED: - { - system_event_ap_stadisconnected_t *stadisconnected; - stadisconnected = &event->event_info.sta_disconnected; - WIFI_DEBUG("SYSTEM_EVENT_AP_STADISCONNECTED\nmac:%02x:%02x:%02x:%02x:%02x:%02x, aid:%d\n", \ - stadisconnected->mac[0], stadisconnected->mac[0], stadisconnected->mac[1], \ - stadisconnected->mac[3], stadisconnected->mac[4], stadisconnected->mac[5], stadisconnected->aid); - break; - } - case SYSTEM_EVENT_AP_PROBEREQRECVED: - { - system_event_ap_probe_req_rx_t *ap_probereqrecved; - ap_probereqrecved = &event->event_info.ap_probereqrecved; - WIFI_DEBUG("SYSTEM_EVENT_AP_PROBEREQRECVED\nrssi:%d, mac:%02x:%02x:%02x:%02x:%02x:%02x\n", \ - ap_probereqrecved->rssi, ap_probereqrecved->mac[0], ap_probereqrecved->mac[0], ap_probereqrecved->mac[1], \ - ap_probereqrecved->mac[3], ap_probereqrecved->mac[4], ap_probereqrecved->mac[5]); - break; - } - default: - { - printf("Error: no such kind of event!\n"); - break; - } + case SYSTEM_EVENT_WIFI_READY: { + WIFI_DEBUG("SYSTEM_EVENT_WIFI_READY\n"); + break; + } + case SYSTEM_EVENT_SCAN_DONE: { + system_event_sta_scan_done_t *scan_done; + scan_done = &event->event_info.scan_done; + WIFI_DEBUG("SYSTEM_EVENT_SCAN_DONE\nstatus:%d, number:%d\n", scan_done->status, scan_done->number); + break; + } + case SYSTEM_EVENT_STA_START: { + WIFI_DEBUG("SYSTEM_EVENT_STA_START\n"); + break; + } + case SYSTEM_EVENT_STA_STOP: { + WIFI_DEBUG("SYSTEM_EVENT_STA_STOP\n"); + break; + } + case SYSTEM_EVENT_STA_CONNECTED: { + system_event_sta_connected_t *connected; + connected = &event->event_info.connected; + WIFI_DEBUG("SYSTEM_EVENT_STA_CONNECTED\nssid:%s, ssid_len:%d, bssid:%02x:%02x:%02x:%02x:%02x:%02x, channel:%d, authmode:%d\n", \ + connected->ssid, connected->ssid_len, connected->bssid[0], connected->bssid[0], connected->bssid[1], \ + connected->bssid[3], connected->bssid[4], connected->bssid[5], connected->channel, connected->authmode); + break; + } + case SYSTEM_EVENT_STA_DISCONNECTED: { + system_event_sta_disconnected_t *disconnected; + disconnected = &event->event_info.disconnected; + WIFI_DEBUG("SYSTEM_EVENT_STA_DISCONNECTED\nssid:%s, ssid_len:%d, bssid:%02x:%02x:%02x:%02x:%02x:%02x, reason:%d\n", \ + disconnected->ssid, disconnected->ssid_len, disconnected->bssid[0], disconnected->bssid[0], disconnected->bssid[1], \ + disconnected->bssid[3], disconnected->bssid[4], disconnected->bssid[5], disconnected->reason); + break; + } + case SYSTEM_EVENT_STA_AUTHMODE_CHANGE: { + system_event_sta_authmode_change_t *auth_change; + auth_change = &event->event_info.auth_change; + WIFI_DEBUG("SYSTEM_EVENT_STA_AUTHMODE_CHNAGE\nold_mode:%d, new_mode:%d\n", auth_change->old_mode, auth_change->new_mode); + break; + } + case SYSTEM_EVENT_STA_GOT_IP: { + system_event_sta_got_ip_t *got_ip; + got_ip = &event->event_info.got_ip; + WIFI_DEBUG("SYSTEM_EVENT_STA_GOTIP\n"); + break; + } + case SYSTEM_EVENT_AP_START: { + WIFI_DEBUG("SYSTEM_EVENT_AP_START\n"); + break; + } + case SYSTEM_EVENT_AP_STOP: { + WIFI_DEBUG("SYSTEM_EVENT_AP_STOP\n"); + break; + } + case SYSTEM_EVENT_AP_STACONNECTED: { + system_event_ap_staconnected_t *staconnected; + staconnected = &event->event_info.sta_connected; + WIFI_DEBUG("SYSTEM_EVENT_AP_STACONNECTED\nmac:%02x:%02x:%02x:%02x:%02x:%02x, aid:%d\n", \ + staconnected->mac[0], staconnected->mac[0], staconnected->mac[1], \ + staconnected->mac[3], staconnected->mac[4], staconnected->mac[5], staconnected->aid); + break; + } + case SYSTEM_EVENT_AP_STADISCONNECTED: { + system_event_ap_stadisconnected_t *stadisconnected; + stadisconnected = &event->event_info.sta_disconnected; + WIFI_DEBUG("SYSTEM_EVENT_AP_STADISCONNECTED\nmac:%02x:%02x:%02x:%02x:%02x:%02x, aid:%d\n", \ + stadisconnected->mac[0], stadisconnected->mac[0], stadisconnected->mac[1], \ + stadisconnected->mac[3], stadisconnected->mac[4], stadisconnected->mac[5], stadisconnected->aid); + break; + } + case SYSTEM_EVENT_AP_PROBEREQRECVED: { + system_event_ap_probe_req_rx_t *ap_probereqrecved; + ap_probereqrecved = &event->event_info.ap_probereqrecved; + WIFI_DEBUG("SYSTEM_EVENT_AP_PROBEREQRECVED\nrssi:%d, mac:%02x:%02x:%02x:%02x:%02x:%02x\n", \ + ap_probereqrecved->rssi, ap_probereqrecved->mac[0], ap_probereqrecved->mac[0], ap_probereqrecved->mac[1], \ + ap_probereqrecved->mac[3], ap_probereqrecved->mac[4], ap_probereqrecved->mac[5]); + break; + } + default: { + printf("Error: no such kind of event!\n"); + break; + } } return ESP_OK; @@ -296,8 +287,8 @@ static esp_err_t esp_system_event_handler(system_event_t *event) } esp_system_event_debug(event); - if ((event->event_id < SYSTEM_EVENT_MAX) && (event->event_id == g_system_event_handle_table[event->event_id].event_id)){ - if (g_system_event_handle_table[event->event_id].event_handle){ + if ((event->event_id < SYSTEM_EVENT_MAX) && (event->event_id == g_system_event_handle_table[event->event_id].event_id)) { + if (g_system_event_handle_table[event->event_id].event_handle) { WIFI_DEBUG("enter default callback\n"); g_system_event_handle_table[event->event_id].event_handle(event); WIFI_DEBUG("exit default callback\n"); @@ -317,42 +308,57 @@ static void esp_system_event_task(void *pvParameters) while (1) { if (xQueueReceive(g_event_handler, &evt, portMAX_DELAY) == pdPASS) { ret = esp_system_event_handler(&evt); - if (ret == ESP_FAIL) + if (ret == ESP_FAIL) { printf("esp wifi post event to user fail!\n"); + } } } } -system_event_cb_t esp_event_set_cb(system_event_cb_t cb) +system_event_cb_t esp_event_set_cb(system_event_cb_t cb, void *ctx) { system_event_cb_t old_cb = g_event_handler_cb; + g_event_handler_cb = cb; + g_event_ctx = ctx; + return old_cb; } esp_err_t esp_event_send(system_event_t *event) { portBASE_TYPE ret; - + ret = xQueueSendToBack((xQueueHandle)g_event_handler, event, 0); - if (pdPASS != ret){ - if (event) printf("e=%d f\n", event->event_id); - else printf("e null\n"); + + if (pdPASS != ret) { + if (event) { + printf("e=%d f\n", event->event_id); + } else { + printf("e null\n"); + } return ESP_FAIL; } return ESP_OK; } -void* esp_event_get_handler(void) +void *esp_event_get_handler(void) { - return (void*)g_event_handler; + return (void *)g_event_handler; } -esp_err_t esp_event_init(system_event_cb_t cb) +esp_err_t esp_event_init(system_event_cb_t cb, void *ctx) { - g_event_handler_cb = (system_event_cb_t)cb; + if (event_init_flag) { + return ESP_FAIL; + } + + g_event_handler_cb = cb; + g_event_ctx = ctx; + g_event_handler = xQueueCreate(CONFIG_WIFI_ENENT_QUEUE_SIZE, sizeof(system_event_t)); + xTaskCreatePinnedToCore(esp_system_event_task, "eventTask", CONFIG_WIFI_EVENT_TASK_STACK_SIZE, NULL, 5, NULL, 0); // TODO: rearrange task priority return ESP_OK; } diff --git a/components/esp32/include/esp_event.h b/components/esp32/include/esp_event.h old mode 100755 new mode 100644 index 04a53636b..0b61b7021 --- a/components/esp32/include/esp_event.h +++ b/components/esp32/include/esp_event.h @@ -28,24 +28,24 @@ extern "C" { #endif typedef enum { - SYSTEM_EVENT_WIFI_READY = 0, /**< ESP32 wifi ready */ + SYSTEM_EVENT_WIFI_READY = 0, /**< ESP32 WiFi ready */ SYSTEM_EVENT_SCAN_DONE, /**< ESP32 finish scanning AP */ SYSTEM_EVENT_STA_START, /**< ESP32 station start */ - SYSTEM_EVENT_STA_STOP, /**< ESP32 station start */ + SYSTEM_EVENT_STA_STOP, /**< ESP32 station stop */ SYSTEM_EVENT_STA_CONNECTED, /**< ESP32 station connected to AP */ - SYSTEM_EVENT_STA_DISCONNECTED, /**< ESP32 station disconnected to AP */ + SYSTEM_EVENT_STA_DISCONNECTED, /**< ESP32 station disconnected from AP */ SYSTEM_EVENT_STA_AUTHMODE_CHANGE, /**< the auth mode of AP connected by ESP32 station changed */ - SYSTEM_EVENT_STA_GOTIP, /**< ESP32 station received IP address */ - SYSTEM_EVENT_AP_START, /**< ESP32 softap start */ - SYSTEM_EVENT_AP_STOP, /**< ESP32 softap start */ + SYSTEM_EVENT_STA_GOT_IP, /**< ESP32 station got IP from connected AP */ + SYSTEM_EVENT_AP_START, /**< ESP32 soft-AP start */ + SYSTEM_EVENT_AP_STOP, /**< ESP32 soft-AP stop */ SYSTEM_EVENT_AP_STACONNECTED, /**< a station connected to ESP32 soft-AP */ - SYSTEM_EVENT_AP_STADISCONNECTED, /**< a station disconnected to ESP32 soft-AP */ + SYSTEM_EVENT_AP_STADISCONNECTED, /**< a station disconnected from ESP32 soft-AP */ SYSTEM_EVENT_AP_PROBEREQRECVED, /**< Receive probe request packet in soft-AP interface */ SYSTEM_EVENT_MAX } system_event_id_t; typedef struct { - uint32_t status; /**< status of scanning APs*/ + uint32_t status; /**< status of scanning APs */ uint8_t number; uint8_t scan_id; } system_event_sta_scan_done_t; @@ -94,10 +94,10 @@ typedef union { system_event_sta_disconnected_t disconnected; /**< ESP32 station disconnected to AP */ system_event_sta_scan_done_t scan_done; /**< ESP32 station scan (APs) done */ system_event_sta_authmode_change_t auth_change; /**< the auth mode of AP ESP32 station connected to changed */ - system_event_sta_got_ip_t got_ip; + system_event_sta_got_ip_t got_ip; /**< ESP32 station got IP */ system_event_ap_staconnected_t sta_connected; /**< a station connected to ESP32 soft-AP */ system_event_ap_stadisconnected_t sta_disconnected; /**< a station disconnected to ESP32 soft-AP */ - system_event_ap_probe_req_rx_t ap_probereqrecved; /**< ESP32 softAP receive probe request packet */ + system_event_ap_probe_req_rx_t ap_probereqrecved; /**< ESP32 soft-AP receive probe request packet */ } system_event_info_t; typedef struct { @@ -105,11 +105,65 @@ typedef struct { system_event_info_t event_info; /**< event information */ } system_event_t; -typedef esp_err_t (*system_event_cb_t)(system_event_t *event); -system_event_cb_t esp_event_set_cb(system_event_cb_t cb); -esp_err_t esp_event_send(system_event_t * event); -void* esp_event_get_handler(void); -esp_err_t esp_event_init(system_event_cb_t cb); +/** + * @brief Application specified event callback function + * + * @param void *ctx : reserved for user + * @param system_event_t *event : event type defined in this file + * + * @return ESP_OK : succeed + * @return others : fail + */ +typedef esp_err_t (*system_event_cb_t)(void *ctx, system_event_t *event); + +/** + * @brief Set application specified event callback function + * + * @attention 1. If cb is NULL, means application don't need to handle + * If cb is not NULL, it will be call when an event is received, after the default event callback is completed + * + * @param system_event_cb_t cb : callback + * @param void *ctx : reserved for user + * + * @return system_event_cb_t : old callback + */ +system_event_cb_t esp_event_set_cb(system_event_cb_t cb, void *ctx); + +/** + * @brief Send a event to event task + * + * @attention 1. Other task/modules, such as the TCPIP module, can call this API to send an event to event task + * + * @param system_event_t * event : event + * + * @return ESP_OK : succeed + * @return others : fail + */ +esp_err_t esp_event_send(system_event_t *event); + +/** + * @brief Get the event handler + * + * @attention : currently this API returns event queue handler, by this event queue, + * users can notice when WiFi has done something like scanning done, connected to AP or disconnected from AP. + * + * @param null + * + * @return void * : event queue pointer + */ +void *esp_event_get_handler(void); + +/** + * @brief Init the event module + * Create the event handler and task + * + * @param system_event_cb_t cb : application specified event callback, it can be modified by call esp_event_set_cb + * @param void *ctx : reserved for user + * + * @return ESP_OK : succeed + * @return others : fail + */ +esp_err_t esp_event_init(system_event_cb_t cb, void *ctx); #ifdef __cplusplus } diff --git a/components/esp32/include/esp_wifi.h b/components/esp32/include/esp_wifi.h old mode 100755 new mode 100644 index d21eb1b85..19ba856de --- a/components/esp32/include/esp_wifi.h +++ b/components/esp32/include/esp_wifi.h @@ -12,6 +12,48 @@ // See the License for the specific language governing permissions and // limitations under the License. + +/* Notes about WiFi Programming + * + * The esp32 WiFi programming model can be depicted as following picture: + * + * + * default handler user handler + * ------------- --------------- --------------- + * | | event | | callback or | | + * | tcpip | ---------> | event | ----------> | application | + * | stack | | task | event | task | + * |-----------| |-------------| |-------------| + * /|\ | + * | | + * event | | + * | | + * | | + * --------------- | + * | | | + * | WiFi Driver |/__________________| + * | |\ API call + * | | + * |-------------| + * + * The WiFi driver can be consider as black box, it knows nothing about the high layer code, such as + * TCPIP stack, application task, event task etc, all it can do is to receive API call from high layer + * or post event queue to a specified Queue, which is initialized by API esp_wifi_init(). + * + * The event task is a daemon task, which receives events from WiFi driver or from other subsystem, such + * as TCPIP stack, event task will call the default callback function on receiving the event. For example, + * on receiving event SYSTEM_EVENT_STA_CONNECTED, it will call tcpip_adapter_start() to start the DHCP + * client in it's default handler. + * + * Application can register it's own event callback function by API esp_event_init, then the application callback + * function will be called after the default callback. Also, if application doesn't want to execute the callback + * in the event task, what it needs to do is to post the related event to application task in the application callback function. + * + * The application task (code) generally mixes all these thing together, it calls APIs to init the system/WiFi and + * handle the events when necessary. + * + */ + #ifndef __ESP_WIFI_H__ #define __ESP_WIFI_H__ @@ -40,10 +82,10 @@ typedef enum { } wifi_interface_t; typedef enum { - WIFI_COUNTRY_CN = 0, - WIFI_COUNTRY_JP, - WIFI_COUNTRY_US, - WIFI_COUNTRY_EU, + WIFI_COUNTRY_CN = 0, /**< country China, channel range [1, 14] */ + WIFI_COUNTRY_JP, /**< country Japan, channel range [1, 14] */ + WIFI_COUNTRY_US, /**< country USA, channel range [1, 11] */ + WIFI_COUNTRY_EU, /**< country Europe, channel range [1, 13] */ WIFI_COUNTRY_MAX } wifi_country_t; @@ -89,54 +131,205 @@ enum { }; typedef enum { - WIFI_SECOND_CHAN_NONE = 0, - WIFI_SECOND_CHAN_ABOVE, - WIFI_SECOND_CHAN_BELOW, + WIFI_SECOND_CHAN_NONE = 0, /**< the channel width is HT20 */ + WIFI_SECOND_CHAN_ABOVE, /**< the channel width is HT40 and the second channel is above the primary channel */ + WIFI_SECOND_CHAN_BELOW, /**< the channel width is HT40 and the second channel is below the primary channel */ } wifi_second_chan_t; -typedef esp_err_t (* wifi_startup_cb_t)(void); +/** + * @brief startup WiFi driver and register application specific callback function + * + * @attention 1. This API should be called in application startup code to init WiFi driver + * @attention 2. The callback function is used to provide application specific WiFi configuration, + * such as, set the WiFi mode, register the event callback, set AP SSID etc before + * WiFi is startup + * @attention 3. Avoid to create application task in the callback, otherwise you may get wrong behavior + * @attention 4. If the callback return is not ESP_OK, the startup will fail! + * @attention 5. Before this API can be called, system_init()/esp_event_init()/tcpip_adapter_init() should + * be called firstly + * + * @param wifi_startup_cb_t cb : application specific callback function + * @param void *ctx : reserved for user + * + * @return ESP_OK : succeed + * @return others : fail + */ +typedef esp_err_t (* wifi_startup_cb_t)(void *ctx); -void esp_wifi_startup(wifi_startup_cb_t cb); +esp_err_t esp_wifi_startup(wifi_startup_cb_t cb, void *ctx); typedef struct { - void *event_q; + void *event_q; /**< WiFi event q handler, it's a freeRTOS queue */ uint8_t rx_ba_win; /**< TBC */ uint8_t tx_ba_win; /**< TBC */ uint8_t rx_buf_cnt; /**< TBC */ uint8_t tx_buf_cnt; /**< TBC */ } wifi_init_config_t; +/** + * @brief Init WiFi + * Alloc resource for WiFi driver, such as WiFi control structure, RX/TX buffer, + * WiFi NVS structure etc, this WiFi also start WiFi task + * + * @attention 1. This API must be called before all other WiFi API can be called + * @attention 2. Generally we should init event_q in *config, WiFi driver will post the event + * to this queue when event happens, such as, when station connects to WiFi, WiFi driver + * will post station connected event to this queue. If the queue is not initialized, WiFi + * will not post any events + * @attention 3. For other parameters, currently it's not ready, just ignore it. + * + * @param wifi_init_config_t *config : provide WiFi init configuration + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_init(wifi_init_config_t *config); +/** + * @brief Deinit WiFi + * Free all resource allocated in esp_wifi_init and stop WiFi task + * + * @attention 1. This API should be called if you want to remove WiFi driver from the system + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_deinit(void); +/** + * @brief Set the WiFi operating mode + * + * Set the WiFi operating mode as station, soft-AP or station+soft-AP, + * The default mode is soft-AP mode. + * + * @param wifi_mode_t mode : WiFi operating modes: + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_set_mode(wifi_mode_t mode); +/** + * @brief Get current operating mode of WiFi + * + * @param wifi_mode_t *mode : store current WiFi mode + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_get_mode(wifi_mode_t *mode); +/** + * @brief Start WiFi according to current configuration + * If mode is WIFI_MODE_STA, it create station control block and start station + * If mode is WIFI_MODE_AP, it create soft-AP control block and start soft-AP + * If mode is WIFI_MODE_APSTA, it create soft-AP and station control block and start soft-AP and station + * + * @param null + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_start(void); +/** + * @brief Stop WiFi + If mode is WIFI_MODE_STA, it stop station and free station control block + * If mode is WIFI_MODE_AP, it stop soft-AP and free soft-AP control block + * If mode is WIFI_MODE_APSTA, it stop station/soft-AP and free station/soft-AP control block + * + * @param null + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_stop(void); +/** + * @brief Connect the ESP32 WiFi station to the AP. + * + * @attention 1. This API only impact WIFI_MODE_STA or WIFI_MODE_APSTA mode + * @attention 2. If the ESP32 is connected to an AP, call esp_wifi_disconnect to disconnect. + * + * @param null + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_connect(void); +/** + * @brief Disconnect the ESP32 WiFi station from the AP. + * + * @param null + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_disconnect(void); +/** + * @brief Currently this API is just an stub API + * + * @param null + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_clear_fast_connect(void); +/** + * @brief Kick the all station or associated id equals to aid + * + * @param uint16_t aid : when aid is 0, kick all stations, otherwise kick station whose associated id is aid + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_kick_station(uint16_t aid); typedef struct { char *ssid; /**< SSID of AP */ uint8_t *bssid; /**< MAC address of AP */ uint8_t channel; /**< channel, scan the specific channel */ - bool show_hidden; /**< enable to scan AP whose SSID is hidden */ + bool show_hidden; /**< enable to scan AP whose SSID is hidden */ } wifi_scan_config_t; +/** + * @brief Scan all available APs. + * + * @attention If this API is called, the found APs are stored in WiFi driver dynamic allocated memory and the + * will be freed in esp_wifi_get_ap_list, so generally, call esp_wifi_get_ap_list to cause + * the memory to be freed once the scan is done + * + * @param struct scan_config *config : configuration of scanning + * @param bool block : if block is true, this API will block the caller until the scan is done, otherwise + * it will return immediately + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_scan_start(wifi_scan_config_t *conf, bool block); +/** + * @brief Stop the scan in process + * + * @param null + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_scan_stop(void); +/** + * @brief Get number of APs found in last scan + * + * @param uint16_t *number : store number of APIs found in last scan + * + * @attention This API can only be called when the scan is completed, otherwise it may get wrong value + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_get_ap_num(uint16_t *number); typedef struct { @@ -144,58 +337,226 @@ typedef struct { uint8_t ssid[32]; /**< SSID of AP */ uint8_t primary; /**< channel of AP */ wifi_second_chan_t second; /**< second channel of AP */ - signed char rssi; /**< signal strength of AP */ + int8_t rssi; /**< signal strength of AP */ wifi_auth_mode_t authmode; /**< authmode of AP */ -}wifi_ap_list_t; +} wifi_ap_list_t; +/** + * @brief Get AP list found in last scan + * + * @param uint16_t *number : as input param, it stores max AP number ap_list can hold, as output param, it store + the actual AP number this API returns + * @param wifi_ap_list_t *ap_list : a list to hold the found APs + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_get_ap_list(uint16_t *number, wifi_ap_list_t *ap_list); typedef enum { - WIFI_PS_NONE, - WIFI_PS_MODEM, - WIFI_PS_LIGHT, - WIFI_PS_MAC, + WIFI_PS_NONE, /**< No power save */ + WIFI_PS_MODEM, /**< Modem power save */ + WIFI_PS_LIGHT, /**< Light power save */ + WIFI_PS_MAC, /**< MAC power save */ } wifi_ps_type_t; +/** + * @brief Set current power save type + * + * @param wifi_ps_type_t type : power save type + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_set_ps(wifi_ps_type_t type); +/** + * @brief Get current power save type + * + * @param wifi_ps_type_t *type : store current power save type + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_get_ps(wifi_ps_type_t *type); #define WIFI_PROTOCOL_11B 1 #define WIFI_PROTOCOL_11G 2 #define WIFI_PROTOCOL_11N 4 -esp_err_t esp_wifi_set_protocol(wifi_interface_t ifx, uint8_t protocol); +/** + * @brief Set protocol type of specified interface + * The default protocol is (WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N) + * + * @attention Currently we only support 802.11b or 802.11bg or 802.11bgn mode + * + * @param wifi_interface_t ifx : interfaces + * @param uint8_t protocol : WiFi protocol bitmap + * + * @return ESP_OK : succeed + * @return others : fail + */ +esp_err_t esp_wifi_set_protocol(wifi_interface_t ifx, uint8_t protocol_bitmap); -esp_err_t esp_wifi_get_protocol(wifi_interface_t ifx, uint8_t *protocol); +/** + * @brief Get the current protocol bitmap of specified ifx + * + * @param wifi_interface_t ifx : interfaces + * @param uint8_t protocol : store current WiFi protocol bitmap of interface ifx + * + * @return ESP_OK : succeed + * @return others : fail + */ +esp_err_t esp_wifi_get_protocol(wifi_interface_t ifx, uint8_t *protocol_bitmap); typedef enum { - WIFI_BW_HT20 = 0, - WIFI_BW_HT40, + WIFI_BW_HT20 = 0, /* Bandwidth is HT20 */ + WIFI_BW_HT40, /* Bandwidth is HT40 */ } wifi_bandwidth_t; +/** + * @brief Set the bandwidth of ESP32 specified interface + * + * @attention 1. API return false if try to configure a interface that is not enable + * @attention 2. WIFI_BW_HT40 is supported only when the interface support 11N + * + * @param wifi_interface_t ifx : interface to be configured + * @param wifi_bandwidth_t bw : bandwidth + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_set_bandwidth(wifi_interface_t ifx, wifi_bandwidth_t bw); +/** + * @brief Get the bandwidth of ESP32 specified interface + * + * @attention 1. API return false if try to get a interface that is not enable + * + * @param wifi_interface_t ifx : interface to be configured + * @param wifi_bandwidth_t *bw : store bandwidth of interface ifx + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_get_bandwidth(wifi_interface_t ifx, wifi_bandwidth_t *bw); +/** + * @brief Set primary/second channel of ESP32 + * + * @attention 1. This is a special API for sniffer + * + * @param uint8_t primary : for HT20, primary is the channel number, for HT40, primary is the primary channel + * @param wifi_second_chan_t second : for HT20, second is ignored, for HT40, second is the second channel + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_set_channel(uint8_t primary, wifi_second_chan_t second); +/** + * @brief Get the primary/second channel of ESP32 + * + * @attention 1. API return false if try to get a interface that is not enable + * + * @param uint8_t *primary : store current primary channel + * @param wifi_second_chan_t *second : store current second channel + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_get_channel(uint8_t *primary, wifi_second_chan_t *second); +/** + * @brief Set country code + * The default value is WIFI_COUNTRY_CN + * + * @param wifi_country_t country : country type + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_set_country(wifi_country_t country); +/** + * @brief Get country code + * + * @param wifi_country_t country : store current country + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_get_country(wifi_country_t *country); +/** + * @brief Set MAC address of the ESP32 WiFi station or the soft-AP interface. + * + * @attention 1. This API can only be called when the interface is disabled + * @attention 2. ESP32 soft-AP and station have different MAC addresses, do not set them to be the same. + * - The bit0 of the first byte of ESP32 MAC address can not be 1. For example, the MAC address + * can set to be "1a:XX:XX:XX:XX:XX", but can not be "15:XX:XX:XX:XX:XX". + * + * @param wifi_interface_t ifx : interface + * @param uint8 mac[6]: the MAC address. + * + * @return true : succeed + * @return false : fail + */ esp_err_t esp_wifi_set_mac(wifi_interface_t ifx, uint8_t mac[6]); +/** + * @brief Get mac of specified interface + * + * @param uint8_t mac[6] : store mac of this interface ifx + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_get_mac(wifi_interface_t ifx, uint8_t mac[6]); +/** + * @brief The RX callback function in the promiscuous mode. + * + * Each time a packet is received, the callback function will be called. + * + * @param void *buf : the data received + * @param uint16_t len : data length + * + * @return ESP_OK : succeed + * @return others : fail + */ typedef void (* wifi_promiscuous_cb_t)(void *buf, uint16_t len); +/** + * @brief Register the RX callback function in the promiscuous mode. + * + * Each time a packet is received, the registered callback function will be called. + * + * @param wifi_promiscuous_cb_t cb : callback + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_set_promiscuous_rx_cb(wifi_promiscuous_cb_t cb); +/** + * @brief Enable the promiscuous mode. + * + * @param uint8 promiscuous : 0 - disable / 1 - enable + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_set_promiscuous(uint8_t enable); +/** + * @brief Get the promiscuous mode. + * + * @param uint8 *enable : store the current status of promiscuous mode + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_get_promiscuous(uint8_t *enable); typedef struct { @@ -206,7 +567,7 @@ typedef struct { wifi_auth_mode_t authmode; /**< Auth mode of ESP32 soft-AP. Do not support AUTH_WEP in soft-AP mode */ uint8_t ssid_hidden; /**< Broadcast SSID or not, default 0, broadcast the SSID */ uint8_t max_connection; /**< Max number of stations allowed to connect in, default 4, max 4 */ - uint16_t beacon_interval; /**< Beacon interval, 100 ~ 60000 ms, default 100 */ + uint16_t beacon_interval; /**< Beacon interval, 100 ~ 60000 ms, default 100 ms */ } wifi_ap_config_t; typedef struct { @@ -217,12 +578,35 @@ typedef struct { } wifi_sta_config_t; typedef union { - wifi_ap_config_t ap; - wifi_sta_config_t sta; + wifi_ap_config_t ap; /**< configuration of AP */ + wifi_sta_config_t sta; /**< configuration of STA */ } wifi_config_t; +/** + * @brief Set the configuration of the ESP32 STA or AP + * + * @attention 1. This API can be called only when specified interface is enabled, otherwise, API fail + * @attention 2. For station configuration, bssid_set needs to be 0; and it needs to be 1 only when users need to check the MAC address of the AP. + * @attention 3. ESP32 is limited to only one channel, so when in the soft-AP+station mode, the soft-AP will adjust its channel automatically to be the same as + * the channel of the ESP32 station. + * + * @param wifi_interface_t ifx : interface + * @param wifi_config_t *conf : station or soft-AP configuration + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_set_config(wifi_interface_t ifx, wifi_config_t *conf); +/** + * @brief Get configuration of specified interface + * + * @param wifi_interface_t ifx : interface + * @param wifi_config_t *conf : station or soft-AP configuration + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_get_config(wifi_interface_t ifx, wifi_config_t *conf); struct station_info { @@ -230,23 +614,79 @@ struct station_info { uint8_t bssid[6]; }; +/** + * @brief Get STAs associated with soft-AP + * + * @attention SSC only API + * + * @param struct station_info **station : station list + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_get_station_list(struct station_info **station); esp_err_t esp_wifi_free_station_list(void); typedef enum { - WIFI_STORAGE_FLASH, - WIFI_STORAGE_RAM, + WIFI_STORAGE_FLASH, /**< all configuration will strore in both memory and flash */ + WIFI_STORAGE_RAM, /**< all configuration will only store in the memory */ } wifi_storage_t; +/** + * @brief Set the WiFi API configuration storage type + * + * @attention 1. The default value is WIFI_STORAGE_FLASH + * + * @param wifi_storage_t storage : storage type + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_set_storage(wifi_storage_t storage); -typedef esp_err_t (*wifi_rxcb_t)(void *buffer, uint16_t len, void* eb); +/** + * @brief The WiFi RX callback function + * + * Each time the WiFi need to forward the packets to high layer, the callback function will be called + * + */ +typedef esp_err_t (*wifi_rxcb_t)(void *buffer, uint16_t len, void *eb); +/** + * @brief Set the WiFi RX callback + * + * @attention 1. Currently we support only one RX callback for each interface + * + * @param wifi_interface_t ifx : interface + * @param wifi_rxcb_t fn : WiFi RX callback + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_reg_rxcb(wifi_interface_t ifx, wifi_rxcb_t fn); +/** + * @brief Set auto connect + * The default value is true + * + * @attention 1. + * + * @param bool en : true - enable auto connect / false - disable auto connect + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_set_auto_connect(bool en); +/** + * @brief Get the auto connect flag + * + * @param bool *en : store current auto connect configuration + * + * @return ESP_OK : succeed + * @return others : fail + */ esp_err_t esp_wifi_get_auto_connect(bool *en); #ifdef __cplusplus diff --git a/components/esp32/wifi.c b/components/esp32/wifi.c index 5ac3c990b..990006975 100644 --- a/components/esp32/wifi.c +++ b/components/esp32/wifi.c @@ -11,6 +11,7 @@ // 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. + #include #include #include @@ -26,9 +27,12 @@ #if CONFIG_WIFI_ENABLED -static wifi_startup_cb_t startup_cb; +static bool wifi_startup_flag = false; -#define WIFI_DEBUG(...) +static wifi_startup_cb_t startup_cb; +static void *startup_ctx; + +#define WIFI_DEBUG(...) #define WIFI_API_CALL_CHECK(info, api_call, ret) \ do{\ esp_err_t __err = (api_call);\ @@ -54,7 +58,7 @@ static void esp_wifi_task(void *pvParameters) } if (startup_cb) { - err = (*startup_cb)(); + err = (*startup_cb)(startup_ctx); if (err != ESP_OK) { WIFI_DEBUG("startup_cb fail, ret=%d\n", err); break; @@ -71,7 +75,7 @@ static void esp_wifi_task(void *pvParameters) wifi_mode_t mode; bool auto_connect; err = esp_wifi_get_mode(&mode); - if (err != ESP_OK){ + if (err != ESP_OK) { WIFI_DEBUG("esp_wifi_get_mode fail, ret=%d\n", err); } @@ -94,9 +98,17 @@ static void esp_wifi_task(void *pvParameters) vTaskDelete(NULL); } -void esp_wifi_startup(wifi_startup_cb_t cb) +esp_err_t esp_wifi_startup(wifi_startup_cb_t cb, void *ctx) { + if (wifi_startup_flag) { + return ESP_FAIL; + } + startup_cb = cb; + startup_ctx = ctx; + xTaskCreatePinnedToCore(esp_wifi_task, "wifiTask", 4096, NULL, 5, NULL, 0);// TODO: rearrange task priority + + return ESP_OK; } #endif diff --git a/components/lwip/core/ipv4/dhcp.c b/components/lwip/core/ipv4/dhcp.c index cd780d00a..1f3758fa9 100755 --- a/components/lwip/core/ipv4/dhcp.c +++ b/components/lwip/core/ipv4/dhcp.c @@ -712,10 +712,10 @@ void dhcp_cleanup(struct netif *netif) /* Espressif add start. */ -/** Set callback for dhcp, reversed parameter for future use. +/** Set callback for dhcp, reserved parameter for future use. * * @param netif the netif from which to remove the struct dhcp - * @param cb callback for chcp + * @param cb callback for dhcp */ void dhcp_set_cb(struct netif *netif, void (*cb)(void)) { diff --git a/components/tcpip_adapter/tcpip_adapter_lwip.c b/components/tcpip_adapter/tcpip_adapter_lwip.c index 2facea578..0f681d913 100644 --- a/components/tcpip_adapter/tcpip_adapter_lwip.c +++ b/components/tcpip_adapter/tcpip_adapter_lwip.c @@ -454,7 +454,7 @@ static void tcpip_adapter_dhcpc_cb(void) ip4_addr_set(&ip_info->gw, ip_2_ip4(&netif->gw)); //notify event - evt.event_id = SYSTEM_EVENT_STA_GOTIP; + evt.event_id = SYSTEM_EVENT_STA_GOT_IP; memcpy(&evt.event_info.got_ip.ip_info, ip_info, sizeof(tcpip_adapter_ip_info_t)); esp_event_send(&evt);