From f54aef9977efd855e1d4c19842e01b2a8aa26904 Mon Sep 17 00:00:00 2001 From: chenwen Date: Fri, 29 Jan 2021 15:31:14 +0800 Subject: [PATCH] xtensa/esp32: Support esp32 wireless ioctl cmd --- arch/xtensa/src/esp32/Kconfig | 6 + arch/xtensa/src/esp32/Make.defs | 2 +- arch/xtensa/src/esp32/esp32_wifi_adapter.c | 1388 +++++++++++++++-- arch/xtensa/src/esp32/esp32_wifi_adapter.h | 412 ++++- arch/xtensa/src/esp32/esp32_wifi_utils.c | 516 ++++++ arch/xtensa/src/esp32/esp32_wifi_utils.h | 120 ++ arch/xtensa/src/esp32/esp32_wlan.c | 230 ++- .../configs/sta_softap/defconfig | 2 +- .../esp32-devkitc/configs/wapi/defconfig | 1 + .../esp32-ethernet-kit/configs/wapi/defconfig | 1 + .../esp32-wrover-kit/configs/wapi/defconfig | 1 + include/nuttx/wireless/wireless.h | 6 + 12 files changed, 2476 insertions(+), 209 deletions(-) create mode 100644 arch/xtensa/src/esp32/esp32_wifi_utils.c create mode 100644 arch/xtensa/src/esp32/esp32_wifi_utils.h diff --git a/arch/xtensa/src/esp32/Kconfig b/arch/xtensa/src/esp32/Kconfig index 697405d836..febb1fd328 100644 --- a/arch/xtensa/src/esp32/Kconfig +++ b/arch/xtensa/src/esp32/Kconfig @@ -909,6 +909,12 @@ config ESP32_WIFI_CONNECT_TIMEOUT help Max waiting time of connecting to AP. +config ESP32_WIFI_SCAN_RESULT_SIZE + int "Scan result buffer" + default 4096 + help + Maximum scan result buffer size. + config ESP32_WIFI_SAVE_PARAM bool "Save WiFi Parameters" default n diff --git a/arch/xtensa/src/esp32/Make.defs b/arch/xtensa/src/esp32/Make.defs index dd00bd9e0a..70bffdea27 100644 --- a/arch/xtensa/src/esp32/Make.defs +++ b/arch/xtensa/src/esp32/Make.defs @@ -201,7 +201,7 @@ clean_context:: INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)include) INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)include$(DELIM)esp32) -CHIP_CSRCS += esp32_wlan.c esp32_wifi_adapter.c +CHIP_CSRCS += esp32_wlan.c esp32_wifi_utils.c esp32_wifi_adapter.c EXTRA_LIBPATHS += -L $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)libs$(DELIM)esp32 EXTRA_LIBS += -lcore -lrtc -lnet80211 -lpp -lsmartconfig -lcoexist -lespnow -lphy -lwpa_supplicant diff --git a/arch/xtensa/src/esp32/esp32_wifi_adapter.c b/arch/xtensa/src/esp32/esp32_wifi_adapter.c index ccce8d3176..c14c55dceb 100644 --- a/arch/xtensa/src/esp32/esp32_wifi_adapter.c +++ b/arch/xtensa/src/esp32/esp32_wifi_adapter.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,7 @@ #include #include #include +#include #include "xtensa.h" #include "xtensa_attr.h" @@ -56,6 +58,7 @@ #include "esp32_cpuint.h" #include "esp32_wifi_adapter.h" #include "esp32_rt_timer.h" +#include "esp32_wifi_utils.h" #include "espidf_wifi.h" @@ -79,6 +82,14 @@ #define TIMER_INITIALIZED_VAL (0x5aa5a55a) +#define ESP_WIFI_11B_MAX_BITRATE 11 +#define ESP_WIFI_11G_MAX_BITRATE 54 +#define ESP_WIFI_11N_MCS7_HT20_BITRATE 72 +#define ESP_WIFI_11N_MCS7_HT40_BITRATE 150 + +#define SSID_MAX_LEN (32) +#define PWD_MAX_LEN (64) + /**************************************************************************** * Private Types ****************************************************************************/ @@ -2012,19 +2023,27 @@ static int esp_event_id_map(int event_id) switch (event_id) { + case WIFI_EVENT_SCAN_DONE: + id = WIFI_ADPT_EVT_SCAN_DONE; + break; + #ifdef ESP32_WLAN_HAS_STA case WIFI_EVENT_STA_START: id = WIFI_ADPT_EVT_STA_START; break; + case WIFI_EVENT_STA_CONNECTED: id = WIFI_ADPT_EVT_STA_CONNECT; break; + case WIFI_EVENT_STA_DISCONNECTED: id = WIFI_ADPT_EVT_STA_DISCONNECT; break; + case WIFI_EVENT_STA_AUTHMODE_CHANGE: id = WIFI_ADPT_EVT_STA_AUTHMODE_CHANGE; break; + case WIFI_EVENT_STA_STOP: id = WIFI_ADPT_EVT_STA_STOP; break; @@ -2071,26 +2090,28 @@ static void esp_evt_work_cb(FAR void *arg) switch (evt_adpt->id) { + case WIFI_ADPT_EVT_SCAN_DONE: + esp_wifi_scan_event_parse(); + break; + #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"); } - break; + case WIFI_ADPT_EVT_STA_CONNECT: wlinfo("INFO: WiFi sta connect\n"); - g_sta_connected = true; break; + case WIFI_ADPT_EVT_STA_DISCONNECT: wlinfo("INFO: WiFi sta disconnect\n"); - g_sta_connected = false; if (g_sta_reconnect) { @@ -2101,9 +2122,9 @@ static void esp_evt_work_cb(FAR void *arg) } } break; + case WIFI_ADPT_EVT_STA_STOP: wlinfo("INFO: WiFi sta stop\n"); - g_sta_connected = false; break; #endif @@ -4129,6 +4150,163 @@ static IRAM_ATTR void esp_wifi_tx_done_cb(uint8_t ifidx, uint8_t *data, } } +/**************************************************************************** + * Name: esp_wifi_set_auth_param + * + * Description: + * Converts a ESP32 authenticate mode values to WEXT authenticate mode. + * + * Input Parameters: + * wifi_auth - ESP32 authenticate mode + * + * Returned Value: + * authenticate mode + * + ****************************************************************************/ + +static int esp_wifi_auth_trans(uint32_t wifi_auth) +{ + int auth_mode = IW_AUTH_WPA_VERSION_DISABLED; + + switch (wifi_auth) + { + case WIFI_AUTH_OPEN: + auth_mode = IW_AUTH_WPA_VERSION_DISABLED; + break; + + case WIFI_AUTH_WPA_PSK: + auth_mode = IW_AUTH_WPA_VERSION_WPA; + break; + + case WIFI_AUTH_WPA2_PSK: + case WIFI_AUTH_WPA_WPA2_PSK: + auth_mode = IW_AUTH_WPA_VERSION_WPA2; + break; + + default: + wlerr("ERROR: Failed to transfer wireless authmode: %d", wifi_auth); + break; + } + + return auth_mode; +} + +/**************************************************************************** + * Name: esp_wifi_set_auth_param + * + * Description: + * Converts a ESP32 cipher type values to WEXT cipher type values. + * + * Input Parameters: + * wifi_cipher - ESP32 cipher type + * + * Returned Value: + * cipher type + * + ****************************************************************************/ + +static int esp_wifi_cipher_trans(uint32_t wifi_cipher) +{ + int cipher_mode = IW_AUTH_CIPHER_NONE; + + switch (wifi_cipher) + { + case WIFI_CIPHER_TYPE_NONE: + cipher_mode = IW_AUTH_CIPHER_NONE; + break; + + case WIFI_CIPHER_TYPE_WEP40: + cipher_mode = IW_AUTH_CIPHER_WEP40; + break; + + case WIFI_CIPHER_TYPE_WEP104: + cipher_mode = IW_AUTH_CIPHER_WEP104; + break; + + case WIFI_CIPHER_TYPE_TKIP: + cipher_mode = IW_AUTH_CIPHER_TKIP; + break; + + case WIFI_CIPHER_TYPE_CCMP: + case WIFI_CIPHER_TYPE_TKIP_CCMP: + cipher_mode = IW_AUTH_CIPHER_CCMP; + break; + + case WIFI_CIPHER_TYPE_AES_CMAC128: + cipher_mode = IW_AUTH_CIPHER_AES_CMAC; + break; + + default: + wlerr("ERROR: Failed to transfer wireless authmode: %d", + wifi_cipher); + break; + } + + return cipher_mode; +} + +/**************************************************************************** + * Name: esp_freq_to_channel + * + * Description: + * Converts WiFi frequency to channel. + * + * Input Parameters: + * freq - WiFi frequency + * + * Returned Value: + * WiFi channel + * + ****************************************************************************/ + +static int esp_freq_to_channel(uint16_t freq) +{ + int channel = 0; + if (freq >= 2412 && freq <= 2484) + { + if (freq == 2484) + { + channel = 14; + } + else + { + channel = freq - 2407; + if (channel % 5) + { + return 0; + } + + channel /= 5; + } + + return channel; + } + + if (freq >= 5005 && freq < 5900) + { + if (freq % 5) + { + return 0; + } + + channel = (freq - 5000) / 5; + return channel; + } + + if (freq >= 4905 && freq < 5000) + { + if (freq % 5) + { + return 0; + } + + channel = (freq - 4000) / 5; + return channel; + } + + return 0; +} + /**************************************************************************** * Functions needed by libphy.a ****************************************************************************/ @@ -4771,7 +4949,8 @@ errout_init_timer: * None * * Returned Value: - * 0 if success or -1 if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ @@ -4835,7 +5014,8 @@ errout_set_mode: * None * * Returned Value: - * 0 if success or -1 if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ @@ -4897,7 +5077,8 @@ errout_set_mode: * len - Packet length * * Returned Value: - * 0 if success or others if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ @@ -4920,7 +5101,8 @@ int esp_wifi_sta_send_data(void *pbuf, uint32_t len) * recv_cb - Receive callback function * * Returned Value: - * 0 if success or others if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ @@ -4977,126 +5159,264 @@ int esp_wifi_sta_read_mac(uint8_t *mac) * Name: esp_wifi_set_password * * Description: - * Set WiFi station password + * Set/Get WiFi station password * * Input Parameters: - * pdata - Password buffer pointer - * len - Password length + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data * * Returned Value: - * 0 if success or -1 if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ -int esp_wifi_sta_set_password(const uint8_t *pdata, uint8_t len) +int esp_wifi_sta_password(struct iwreq *iwr, bool set) { int ret; + int size; wifi_config_t wifi_cfg; + struct iw_encode_ext *ext = iwr->u.encoding.pointer; + uint8_t *pdata; + uint8_t len; #ifdef CONFIG_DEBUG_WIRELESS_INFO - char buf[65]; + char buf[PWD_MAX_LEN + 1]; #endif - if (len > 64) + DEBUGASSERT(ext != NULL); + + pdata = ext->key; + len = ext->key_len; + + if (set && len > PWD_MAX_LEN) { 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; + return wifi_errno_trans(ret); } - 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) + if (set) { - wlerr("ERROR: Failed to set 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); + return wifi_errno_trans(ret); + } + } + else + { + size = strnlen((char *)wifi_cfg.sta.password, PWD_MAX_LEN); + if (len < size) + { + return -EINVAL; + } + else + { + len = size; + memcpy(pdata, wifi_cfg.sta.password, len); + } + + if (g_sta_connected) + { + wifi_ap_record_t ap_info; + + ret = esp_wifi_sta_get_ap_info(&ap_info); + if (ret) + { + wlerr("ERROR: Failed to get AP record ret=%d", ret); + return wifi_errno_trans(ret); + } + + switch (ap_info.pairwise_cipher) + { + case WIFI_CIPHER_TYPE_NONE: + ext->alg = IW_ENCODE_ALG_NONE; + break; + + case WIFI_CIPHER_TYPE_WEP40: + case WIFI_CIPHER_TYPE_WEP104: + ext->alg = IW_ENCODE_ALG_WEP; + break; + + case WIFI_CIPHER_TYPE_TKIP: + ext->alg = IW_ENCODE_ALG_TKIP; + break; + + case WIFI_CIPHER_TYPE_CCMP: + case WIFI_CIPHER_TYPE_TKIP_CCMP: + ext->alg = IW_ENCODE_ALG_CCMP; + break; + + case WIFI_CIPHER_TYPE_AES_CMAC128: + ext->alg = IW_ENCODE_ALG_AES_CMAC; + break; + + default: + wlerr("ERROR: Failed to transfer wireless authmode: %d", + ap_info.pairwise_cipher); + return -EIO; + } + } } #ifdef CONFIG_DEBUG_WIRELESS_INFO memcpy(buf, pdata, len); buf[len] = 0; - wlinfo("INFO: OK to set WiFi station password=%s len=%d\n", buf, len); + wlinfo("INFO: 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_sta_set_ssid + * Name: esp_wifi_sta_essid * * Description: - * Set WiFi station SSID + * Set/Get WiFi station ESSID * * Input Parameters: - * pdata - SSID buffer pointer - * len - SSID length + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data * * Returned Value: - * 0 if success or -1 if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ -int esp_wifi_sta_set_ssid(const uint8_t *pdata, uint8_t len) +int esp_wifi_sta_essid(struct iwreq *iwr, bool set) { int ret; + int size; wifi_config_t wifi_cfg; + struct iw_point *essid = &iwr->u.essid; + uint8_t *pdata; + uint8_t len; #ifdef CONFIG_DEBUG_WIRELESS_INFO - char buf[33]; + char buf[SSID_MAX_LEN + 1]; #endif - if (len > 32) + DEBUGASSERT(essid != NULL); + + pdata = essid->pointer; + len = essid->length; + + if (set && len > SSID_MAX_LEN) { 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; + return wifi_errno_trans(ret); } - memcpy(wifi_cfg.sta.ssid, pdata, len); - - ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); - if (ret) + if (set) { - wlerr("ERROR: Failed to set 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); + return wifi_errno_trans(ret); + } + } + else + { + size = strnlen((char *)wifi_cfg.sta.ssid, SSID_MAX_LEN); + if (len < size) + { + return -EINVAL; + } + else + { + len = size; + memcpy(pdata, wifi_cfg.sta.ssid, len); + } + + if (g_sta_connected) + { + essid->flags = IW_ESSID_ON; + } + else + { + essid->flags = IW_ESSID_OFF; + } } #ifdef CONFIG_DEBUG_WIRELESS_INFO memcpy(buf, pdata, len); buf[len] = 0; - wlinfo("INFO: OK to set WiFi station ssid=%s len=%d\n", buf, len); + wlinfo("\nINFO: 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_sta_bssid + * + * Description: + * Set/Get WiFi station BSSID + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_bssid(struct iwreq *iwr, bool set) +{ + int ret; + wifi_config_t wifi_cfg; + struct sockaddr *sockaddr; + char *pdata; + + ret = esp_wifi_get_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to get WiFi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + sockaddr = &iwr->u.ap_addr; + pdata = sockaddr->sa_data; + + if (set) + { + wifi_cfg.sta.bssid_set = true; + memcpy(wifi_cfg.sta.bssid, pdata, 6); + + ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to set WiFi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + } + else + { + memcpy(pdata, wifi_cfg.sta.bssid, 6); + } + + return OK; } /**************************************************************************** @@ -5109,7 +5429,8 @@ errout_get_config: * None * * Returned Value: - * 0 if success or -1 if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ @@ -5176,7 +5497,8 @@ errout_wifi_connect: * None * * Returned Value: - * 0 if success or -1 if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ @@ -5202,6 +5524,479 @@ int esp_wifi_sta_disconnect(void) esp_wifi_lock(false); return ret; } + +/**************************************************************************** + * Name: esp_wifi_sta_mode + * + * Description: + * Set/Get WiFi Station mode code. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_mode(struct iwreq *iwr, bool set) +{ + if (set == false) + { + iwr->u.mode = IW_MODE_INFRA; + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_sta_auth + * + * Description: + * Set/Get station authentication mode params. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_auth(struct iwreq *iwr, bool set) +{ + int ret; + int cmd; + wifi_ap_record_t ap_info; + + if (set) + { + return -ENOSYS; + } + else + { + if (g_sta_connected == false) + { + return -ENOTCONN; + } + + ret = esp_wifi_sta_get_ap_info(&ap_info); + if (ret) + { + wlerr("ERROR: Failed to get AP record ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + cmd = iwr->u.param.flags & IW_AUTH_INDEX; + switch (cmd) + { + case IW_AUTH_WPA_VERSION: + iwr->u.param.value = esp_wifi_auth_trans(ap_info.authmode); + break; + + case IW_AUTH_CIPHER_PAIRWISE: + iwr->u.param.value = + esp_wifi_cipher_trans(ap_info.pairwise_cipher); + break; + + case IW_AUTH_CIPHER_GROUP: + iwr->u.param.value = esp_wifi_cipher_trans(ap_info.group_cipher); + break; + + case IW_AUTH_KEY_MGMT: + case IW_AUTH_TKIP_COUNTERMEASURES: + case IW_AUTH_DROP_UNENCRYPTED: + case IW_AUTH_80211_AUTH_ALG: + case IW_AUTH_WPA_ENABLED: + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + case IW_AUTH_ROAMING_CONTROL: + case IW_AUTH_PRIVACY_INVOKED: + default: + wlerr("ERROR: Unknown cmd %d\n", cmd); + return -ENOSYS; + } + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_sta_freq + * + * Description: + * Set/Get station frequency. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_freq(struct iwreq *iwr, bool set) +{ + int ret; + wifi_config_t wifi_cfg; + + if (set && (iwr->u.freq.flags == IW_FREQ_FIXED)) + { + ret = esp_wifi_get_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to get WiFi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + wifi_cfg.sta.channel = esp_freq_to_channel(iwr->u.freq.m); + ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to set WiFi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + } + else + { + if (g_sta_connected) + { + wifi_ap_record_t ap_info; + + ret = esp_wifi_sta_get_ap_info(&ap_info); + if (ret) + { + wlerr("ERROR: Failed to get AP record ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + iwr->u.freq.flags = IW_FREQ_FIXED; + iwr->u.freq.e = 0; + iwr->u.freq.m = 2407 + 5 * ap_info.primary; + } + else + { + iwr->u.freq.flags = IW_FREQ_AUTO; + iwr->u.freq.e = 0; + iwr->u.freq.m = 2412; + } + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_sta_bitrate + * + * Description: + * Get station default bit rate (Mbps). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_bitrate(struct iwreq *iwr, bool set) +{ + int ret; + wifi_ap_record_t ap_info; + + if (set) + { + return -ENOSYS; + } + else + { + if (g_sta_connected == false) + { + iwr->u.bitrate.fixed = IW_FREQ_AUTO; + return OK; + } + + ret = esp_wifi_sta_get_ap_info(&ap_info); + if (ret) + { + wlerr("ERROR: Failed to get AP record ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + iwr->u.bitrate.fixed = IW_FREQ_FIXED; + if (ap_info.phy_11n) + { + if (ap_info.second) + { + iwr->u.bitrate.value = ESP_WIFI_11N_MCS7_HT40_BITRATE; + } + else + { + iwr->u.bitrate.value = ESP_WIFI_11N_MCS7_HT20_BITRATE; + } + } + else if (ap_info.phy_11g) + { + iwr->u.bitrate.value = ESP_WIFI_11G_MAX_BITRATE; + } + else if (ap_info.phy_11b) + { + iwr->u.bitrate.value = ESP_WIFI_11B_MAX_BITRATE; + } + else + { + return -EIO; + } + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_sta_get_txpower + * + * Description: + * Get station transmit power (dBm). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_txpower(struct iwreq *iwr, bool set) +{ + int ret; + int8_t power; + double power_dbm; + + if (set) + { + if (iwr->u.txpower.flags == IW_TXPOW_RELATIVE) + { + power = (int8_t)iwr->u.txpower.value; + } + else + { + if (iwr->u.txpower.flags == IW_TXPOW_MWATT) + { + power_dbm = ceil(10 * log10(iwr->u.txpower.value)); + } + else + { + power_dbm = iwr->u.txpower.value; + } + + power = (int8_t)(power_dbm * 4); + } + + /* The value set by this API will be mapped to the max_tx_power + * of the structure wifi_country_t variable. Param power unit is + * 0.25dBm, range is [8, 84] corresponding to 2dBm - 20dBm. + * Relationship between set value and actual value. + * As follows: {set value range, actual value} = + * {{[8, 19],8}, {[20, 27],20}, {[28, 33],28}, + * {[34, 43],34}, {[44, 51],44}, {[52, 55],52}, + * {[56, 59],56}, {[60, 65],60}, {[66, 71],66}, + * {[72, 79],72}, {[80, 84],80}}. + */ + + if (power < 8 || power > 84) + { + wlerr("ERROR: Failed to set transmit power =%d\n", power); + return -ENOSYS; + } + + esp_wifi_set_max_tx_power(power); + return OK; + } + else + { + ret = esp_wifi_get_max_tx_power(&power); + if (ret) + { + wlerr("ERROR: Failed to get transmit power ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + iwr->u.txpower.disabled = 0; + iwr->u.txpower.flags = IW_TXPOW_DBM; + iwr->u.txpower.value = power / 4; + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_sta_get_channel_range + * + * Description: + * Get station range of channel parameters. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_channel(struct iwreq *iwr, bool set) +{ + int ret; + int k; + wifi_country_t country; + struct iw_range *range; + + if (set) + { + return -ENOSYS; + } + else + { + ret = esp_wifi_get_country(&country); + if (ret) + { + wlerr("ERROR: Failed to get country info ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + range = (struct iw_range *)iwr->u.data.pointer; + range->num_frequency = country.nchan; + for (k = 1; k <= range->num_frequency; k++) + { + range->freq[k - 1].i = k; + range->freq[k - 1].e = 0; + range->freq[k - 1].m = 2407 + 5 * k; + } + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_sta_country + * + * Description: + * Configure country info. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_country(struct iwreq *iwr, bool set) +{ + int ret; + char *country_code; + wifi_country_t country; + + if (set) + { + memset(&country, 0x00, sizeof(wifi_country_t)); + country.schan = 1; + country.policy = 0; + + country_code = (char *)iwr->u.data.pointer; + if (strlen(country_code) != 2) + { + wlerr("ERROR: Invalid input arguments\r\n"); + return -EINVAL; + } + + if (strncmp(country_code, "US", 3) == 0 || + strncmp(country_code, "CA", 3) == 0) + { + country.nchan = 11; + } + else if(strncmp(country_code, "JP", 3) == 0) + { + country.nchan = 14; + } + else + { + country.nchan = 13; + } + + memcpy(country.cc, country_code, 2); + ret = esp_wifi_set_country(&country); + if (ret) + { + wlerr("ERROR: Failed to Configure country ret=%d\n", ret); + return wifi_errno_trans(ret); + } + } + else + { + return -ENOSYS; + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_sta_rssi + * + * Description: + * Get WiFi sensitivity (dBm). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_rssi(struct iwreq *iwr, bool set) +{ + int ret; + wifi_ap_record_t ap_info; + + if (set) + { + return -ENOSYS; + } + else + { + if (g_sta_connected == false) + { + iwr->u.sens.value = 128; + return OK; + } + + ret = esp_wifi_sta_get_ap_info(&ap_info); + if (ret) + { + wlerr("ERROR: Failed to get AP record ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + iwr->u.sens.value = -(ap_info.rssi); + } + + return OK; +} #endif /**************************************************************************** @@ -5220,7 +6015,8 @@ int esp_wifi_sta_disconnect(void) * None * * Returned Value: - * 0 if success or -1 if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ @@ -5284,7 +6080,8 @@ errout_set_mode: * None * * Returned Value: - * 0 if success or -1 if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ @@ -5346,7 +6143,8 @@ errout_set_mode: * len - Packet length * * Returned Value: - * 0 if success or others if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ @@ -5369,7 +6167,8 @@ int esp_wifi_softap_send_data(void *pbuf, uint32_t len) * recv_cb - Receive callback function * * Returned Value: - * 0 if success or others if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ @@ -5423,127 +6222,186 @@ int esp_wifi_softap_read_mac(uint8_t *mac) } /**************************************************************************** - * Name: esp_wifi_softap_set_password + * Name: esp_wifi_softap_password * * Description: - * Set WiFi SoftAP password + * Set/Get WiFi SoftAP password * * Input Parameters: - * pdata - Password buffer pointer - * len - Password length + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data * * Returned Value: - * 0 if success or -1 if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ -int esp_wifi_softap_set_password(const uint8_t *pdata, uint8_t len) +int esp_wifi_softap_password(struct iwreq *iwr, bool set) { int ret; + int size; wifi_config_t wifi_cfg; + struct iw_encode_ext *ext = iwr->u.encoding.pointer; + uint8_t *pdata; + uint8_t len; #ifdef CONFIG_DEBUG_WIRELESS_INFO - char buf[65]; + char buf[PWD_MAX_LEN + 1]; #endif - if (len > 64) + DEBUGASSERT(ext != NULL); + + pdata = ext->key; + len = ext->key_len; + + if (set && len > PWD_MAX_LEN) { 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; + return wifi_errno_trans(ret); } - memcpy(wifi_cfg.ap.password, pdata, len); + ext = iwr->u.encoding.pointer; + pdata = ext->key; + len = ext->key_len; - ret = esp_wifi_set_config(WIFI_IF_AP, &wifi_cfg); - if (ret) + if (set) { - wlerr("ERROR: Failed to set 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); + return wifi_errno_trans(ret); + } + } + else + { + size = strnlen((char *)wifi_cfg.ap.password, PWD_MAX_LEN); + if (len < size) + { + return -EINVAL; + } + else + { + len = size; + memcpy(pdata, wifi_cfg.ap.password, len); + } } #ifdef CONFIG_DEBUG_WIRELESS_INFO memcpy(buf, pdata, len); buf[len] = 0; - wlinfo("INFO: OK to set WiFi SoftAP password=%s len=%d\n", buf, len); + wlinfo("INFO: 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 + * Name: esp_wifi_softap_essid * * Description: - * Set WiFi SoftAP SSID + * Set/Get WiFi SoftAP ESSID * * Input Parameters: - * pdata - SSID buffer pointer - * len - SSID length + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data * * Returned Value: - * 0 if success or -1 if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ -int esp_wifi_softap_set_ssid(const uint8_t *pdata, uint8_t len) +int esp_wifi_softap_essid(struct iwreq *iwr, bool set) { int ret; + int size; wifi_config_t wifi_cfg; + struct iw_point *essid = &iwr->u.essid; + uint8_t *pdata; + uint8_t len; #ifdef CONFIG_DEBUG_WIRELESS_INFO - char buf[33]; + char buf[SSID_MAX_LEN + 1]; #endif - if (len > 32) + DEBUGASSERT(essid != NULL); + + pdata = essid->pointer; + len = essid->length; + + if (set && len > SSID_MAX_LEN) { 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; + return wifi_errno_trans(ret); } - memcpy(wifi_cfg.ap.ssid, pdata, len); - - ret = esp_wifi_set_config(WIFI_IF_AP, &wifi_cfg); - if (ret) + if (set) { - wlerr("ERROR: Failed to set 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); + return wifi_errno_trans(ret); + } + } + else + { + size = strnlen((char *)wifi_cfg.ap.ssid, SSID_MAX_LEN); + if (len < size) + { + return -EINVAL; + } + else + { + len = size; + memcpy(pdata, wifi_cfg.ap.ssid, len); + } } #ifdef CONFIG_DEBUG_WIRELESS_INFO memcpy(buf, pdata, len); buf[len] = 0; - wlinfo("INFO: OK to set WiFi SoftAP ssid=%s len=%d\n", buf, len); + wlinfo("INFO: 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_bssid + * + * Description: + * Set/Get WiFi softAP BSSID + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_bssid(struct iwreq *iwr, bool set) +{ + return -ENOSYS; } /**************************************************************************** @@ -5556,7 +6414,8 @@ errout_get_config: * None * * Returned Value: - * 0 if success or -1 if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ @@ -5575,7 +6434,8 @@ int esp_wifi_softap_connect(void) * None * * Returned Value: - * 0 if success or -1 if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ @@ -5583,4 +6443,302 @@ int esp_wifi_softap_disconnect(void) { return OK; } + +/**************************************************************************** + * Name: esp_wifi_softap_mode + * + * Description: + * Set/Get WiFi SoftAP mode code. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_mode(struct iwreq *iwr, bool set) +{ + if (set == false) + { + iwr->u.mode = IW_MODE_MASTER; + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_softap_auth + * + * Description: + * Set/get authentication mode params. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_auth(struct iwreq *iwr, bool set) +{ + int ret; + int cmd; + wifi_config_t wifi_cfg; + + if (set) + { + ret = esp_wifi_get_config(WIFI_IF_AP, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to get WiFi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + cmd = iwr->u.param.flags & IW_AUTH_INDEX; + switch (cmd) + { + case IW_AUTH_WPA_VERSION: + { + switch (iwr->u.param.value) + { + case IW_AUTH_WPA_VERSION_DISABLED: + wifi_cfg.ap.authmode = WIFI_AUTH_OPEN; + break; + + case IW_AUTH_WPA_VERSION_WPA: + wifi_cfg.ap.authmode = WIFI_AUTH_WPA_PSK; + break; + + case IW_AUTH_WPA_VERSION_WPA2: + wifi_cfg.ap.authmode = WIFI_AUTH_WPA2_PSK; + break; + + default: + wlerr("ERROR: Invalid wpa version %" PRId32 "\n", + iwr->u.param.value); + return -EINVAL; + } + } + + break; + case IW_AUTH_CIPHER_PAIRWISE: + case IW_AUTH_CIPHER_GROUP: + { + switch (iwr->u.param.value) + { + case IW_AUTH_CIPHER_NONE: + wifi_cfg.ap.authmode = WIFI_AUTH_OPEN; + break; + + case IW_AUTH_CIPHER_WEP40: + case IW_AUTH_CIPHER_WEP104: + wifi_cfg.ap.authmode = WIFI_AUTH_WEP; + break; + + case IW_AUTH_CIPHER_TKIP: + wifi_cfg.ap.authmode = WIFI_AUTH_WPA_PSK; + break; + + case IW_AUTH_CIPHER_CCMP: + case IW_AUTH_CIPHER_AES_CMAC: + wifi_cfg.ap.authmode = WIFI_AUTH_WPA2_PSK; + break; + + default: + wlerr("ERROR: Invalid cipher mode %" PRId32 "\n", + iwr->u.param.value); + return -EINVAL; + } + } + + break; + case IW_AUTH_KEY_MGMT: + case IW_AUTH_TKIP_COUNTERMEASURES: + case IW_AUTH_DROP_UNENCRYPTED: + case IW_AUTH_80211_AUTH_ALG: + case IW_AUTH_WPA_ENABLED: + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + case IW_AUTH_ROAMING_CONTROL: + case IW_AUTH_PRIVACY_INVOKED: + default: + wlerr("ERROR: Unknown cmd %d\n", cmd); + return -EINVAL; + } + + ret = esp_wifi_set_config(WIFI_IF_AP, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to set WiFi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + } + else + { + return -ENOSYS; + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_softap_freq + * + * Description: + * Set/Get SoftAP frequency. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_freq(struct iwreq *iwr, bool set) +{ + int ret; + wifi_config_t wifi_cfg; + + ret = esp_wifi_get_config(WIFI_IF_AP, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to get WiFi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + if (set) + { + int channel = esp_freq_to_channel(iwr->u.freq.m); + + wifi_cfg.ap.channel = channel; + + ret = esp_wifi_set_config(WIFI_IF_AP, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to set WiFi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + } + else + { + iwr->u.freq.flags = IW_FREQ_FIXED; + iwr->u.freq.e = 0; + iwr->u.freq.m = 2407 + 5 * wifi_cfg.ap.channel; + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_softap_get_bitrate + * + * Description: + * Get SoftAP default bit rate (Mbps). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_bitrate(struct iwreq *iwr, bool set) +{ + return -ENOSYS; +} + +/**************************************************************************** + * Name: esp_wifi_softap_txpower + * + * Description: + * Get SoftAP transmit power (dBm). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_txpower(struct iwreq *iwr, bool set) +{ + return esp_wifi_sta_txpower(iwr, set); +} + +/**************************************************************************** + * Name: esp_wifi_softap_channel + * + * Description: + * Get SoftAP range of channel parameters. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_channel(struct iwreq *iwr, bool set) +{ + return esp_wifi_sta_channel(iwr, set); +} + +/**************************************************************************** + * Name: esp_wifi_softap_country + * + * Description: + * Configure country info. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_country(struct iwreq *iwr, bool set) +{ + return esp_wifi_sta_country(iwr, set); +} + +/**************************************************************************** + * Name: esp_wifi_softap_rssi + * + * Description: + * Get WiFi sensitivity (dBm). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_rssi(struct iwreq *iwr, bool set) +{ + return -ENOSYS; +} #endif diff --git a/arch/xtensa/src/esp32/esp32_wifi_adapter.h b/arch/xtensa/src/esp32/esp32_wifi_adapter.h index 2de0d5dcb9..ac298d2cde 100644 --- a/arch/xtensa/src/esp32/esp32_wifi_adapter.h +++ b/arch/xtensa/src/esp32/esp32_wifi_adapter.h @@ -64,7 +64,8 @@ extern "C" enum wifi_adpt_evt_e { - WIFI_ADPT_EVT_STA_START = 0, + WIFI_ADPT_EVT_SCAN_DONE = 0, + WIFI_ADPT_EVT_STA_START, WIFI_ADPT_EVT_STA_CONNECT, WIFI_ADPT_EVT_STA_DISCONNECT, WIFI_ADPT_EVT_STA_AUTHMODE_CHANGE, @@ -145,7 +146,8 @@ int esp_wifi_notify_subscribe(pid_t pid, FAR struct sigevent *event); * None * * Returned Value: - * 0 if success or -1 if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ @@ -161,7 +163,8 @@ int esp_wifi_sta_start(void); * None * * Returned Value: - * 0 if success or -1 if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ @@ -178,7 +181,8 @@ int esp_wifi_sta_stop(void); * len - Packet length * * Returned Value: - * 0 if success or others if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ @@ -194,7 +198,8 @@ int esp_wifi_sta_send_data(void *pbuf, uint32_t len); * recv_cb - Receive callback function * * Returned Value: - * 0 if success or others if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ @@ -238,35 +243,55 @@ int esp_wifi_sta_read_mac(uint8_t *mac); * Name: esp_wifi_set_password * * Description: - * Set WiFi station password + * Set/Get WiFi station password * * Input Parameters: - * pdata - Password buffer pointer - * len - Password length + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data * * Returned Value: - * 0 if success or -1 if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ -int esp_wifi_sta_set_password(const uint8_t *pdata, uint8_t len); +int esp_wifi_sta_password(struct iwreq *iwr, bool set); /**************************************************************************** - * Name: esp_wifi_set_ssid + * Name: esp_wifi_sta_essid * * Description: - * Set WiFi station SSID + * Set/Get WiFi station ESSID * * Input Parameters: - * pdata - SSID buffer pointer - * len - SSID length + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data * * Returned Value: - * 0 if success or -1 if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ -int esp_wifi_sta_set_ssid(const uint8_t *pdata, uint8_t len); +int esp_wifi_sta_essid(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_bssid + * + * Description: + * Set/Get WiFi station BSSID + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_bssid(struct iwreq *iwr, bool set); /**************************************************************************** * Name: esp_wifi_sta_connect @@ -278,7 +303,8 @@ int esp_wifi_sta_set_ssid(const uint8_t *pdata, uint8_t len); * None * * Returned Value: - * 0 if success or -1 if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ @@ -294,11 +320,156 @@ int esp_wifi_sta_connect(void); * None * * Returned Value: - * 0 if success or -1 if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ int esp_wifi_sta_disconnect(void); + +/**************************************************************************** + * Name: esp_wifi_sta_mode + * + * Description: + * Set/Get WiFi Station mode code. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_mode(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_auth + * + * Description: + * Set/Get station authentication mode params. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_auth(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_freq + * + * Description: + * Get station frequency. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_freq(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_bitrate + * + * Description: + * Get station default bit rate (Mbps). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_bitrate(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_get_txpower + * + * Description: + * Get station transmit power (dBm). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_txpower(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_get_channel_range + * + * Description: + * Get station range of channel parameters. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_channel(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_country + * + * Description: + * Configure country info. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_country(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_rssi + * + * Description: + * Get WiFi sensitivity (dBm). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_rssi(struct iwreq *iwr, bool set); #endif #ifdef ESP32_WLAN_HAS_SOFTAP @@ -313,7 +484,8 @@ int esp_wifi_sta_disconnect(void); * None * * Returned Value: - * 0 if success or -1 if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ @@ -329,7 +501,8 @@ int esp_wifi_softap_start(void); * None * * Returned Value: - * 0 if success or -1 if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ @@ -346,7 +519,8 @@ int esp_wifi_softap_stop(void); * len - Packet length * * Returned Value: - * 0 if success or others if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ @@ -362,7 +536,8 @@ int esp_wifi_softap_send_data(void *pbuf, uint32_t len); * recv_cb - Receive callback function * * Returned Value: - * 0 if success or others if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ @@ -403,38 +578,58 @@ void esp_wifi_softap_register_txdone_cb(wifi_txdone_cb_t cb); int esp_wifi_softap_read_mac(uint8_t *mac); /**************************************************************************** - * Name: esp_wifi_softap_set_password + * Name: esp_wifi_softap_password * * Description: - * Set WiFi softAP password + * Set/Get WiFi SoftAP password * * Input Parameters: - * pdata - Password buffer pointer - * len - Password length + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data * * Returned Value: - * 0 if success or -1 if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ -int esp_wifi_softap_set_password(const uint8_t *pdata, uint8_t len); +int esp_wifi_softap_password(struct iwreq *iwr, bool set); /**************************************************************************** - * Name: esp_wifi_softap_set_ssid + * Name: esp_wifi_softap_essid * * Description: - * Set WiFi softAP SSID + * Set/Get WiFi SoftAP ESSID * * Input Parameters: - * pdata - SSID buffer pointer - * len - SSID length + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data * * Returned Value: - * 0 if success or -1 if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ -int esp_wifi_softap_set_ssid(const uint8_t *pdata, uint8_t len); +int esp_wifi_softap_essid(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_softap_bssid + * + * Description: + * Set/Get WiFi softAP BSSID + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_bssid(struct iwreq *iwr, bool set); /**************************************************************************** * Name: esp_wifi_softap_connect @@ -446,7 +641,8 @@ int esp_wifi_softap_set_ssid(const uint8_t *pdata, uint8_t len); * None * * Returned Value: - * 0 if success or -1 if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ @@ -462,11 +658,155 @@ int esp_wifi_softap_connect(void); * None * * Returned Value: - * 0 if success or -1 if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ int esp_wifi_softap_disconnect(void); + +/**************************************************************************** + * Name: esp_wifi_softap_mode + * + * Description: + * Set/Get WiFi SoftAP mode code. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_mode(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_softap_auth + * + * Description: + * Set/Get authentication mode params. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_auth(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_softap_freq + * + * Description: + * Set/Get SoftAP frequency. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_freq(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_softap_get_bitrate + * + * Description: + * Get SoftAP default bit rate (Mbps). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_bitrate(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_softap_txpower + * + * Description: + * Get SoftAP transmit power (dBm). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_txpower(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_softap_channel + * + * Description: + * Get SoftAP range of channel parameters. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_channel(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_softap_country + * + * Description: + * Configure country info. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_country(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_softap_rssi + * + * Description: + * Get WiFi sensitivity (dBm). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_rssi(struct iwreq *iwr, bool set); #endif #ifdef __cplusplus diff --git a/arch/xtensa/src/esp32/esp32_wifi_utils.c b/arch/xtensa/src/esp32/esp32_wifi_utils.c new file mode 100644 index 0000000000..62ce65b90f --- /dev/null +++ b/arch/xtensa/src/esp32/esp32_wifi_utils.c @@ -0,0 +1,516 @@ +/**************************************************************************** + * arch/xtensa/src/esp32/esp32_wifi_utils.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "esp32_wifi_adapter.h" +#include "esp32_wifi_utils.h" +#include "espidf_wifi.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Helper to get iw_event size */ + +#define ESP_IW_EVENT_SIZE(field) \ + (offsetof(struct iw_event, u) + sizeof(((union iwreq_data *)0)->field)) + +#ifdef CONFIG_ESP32_WIFI_SCAN_RESULT_SIZE +# define WIFI_SCAN_RESULT_SIZE CONFIG_ESP32_WIFI_SCAN_RESULT_SIZE +#else +# define WIFI_SCAN_RESULT_SIZE (4096) +#endif + +#define SCAN_TIME_SEC (5) +#define SSID_LEN (33) + +#ifndef MIN +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +enum scan_status_e +{ + ESP_SCAN_DISABLED = 0, + ESP_SCAN_RUN, + ESP_SCAN_DONE +}; + +/* WiFi scan result information */ + +struct wifi_scan_result +{ + enum scan_status_e scan_status; /* Scan status */ + sem_t scan_signal; /* Scan notification signal */ + uint8_t *scan_result; /* Temp buffer that holds results */ + unsigned int scan_result_size; /* Current size of temp buffer */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct wifi_scan_result g_scan_priv; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_wifi_start_scan + * + * Description: + * Scan all available APs. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_start_scan(struct iwreq *iwr) +{ + struct wifi_scan_result *priv = &g_scan_priv; + wifi_scan_config_t *config = NULL; + uint8_t target_ssid[SSID_LEN]; + struct iw_scan_req *req; + int ret = 0; + + memset(target_ssid, 0x0, sizeof(SSID_LEN)); + if (iwr == NULL) + { + wlerr("ERROR: Invalid ioctl cmd.\n"); + return -EINVAL; + } + + if (g_scan_priv.scan_status != ESP_SCAN_DISABLED) + { + return OK; + } + + config = kmm_malloc(sizeof(wifi_scan_config_t)); + if (config == NULL) + { + wlerr("ERROR: Cannot allocate result buffer\n"); + return -ENOMEM; + } + + memset(config, 0x0, sizeof(wifi_scan_config_t)); + if (iwr->u.data.pointer && + iwr->u.data.length >= sizeof(struct iw_scan_req)) + { + req = (struct iw_scan_req *)iwr->u.data.pointer; + config->scan_type = (req->scan_type == IW_SCAN_TYPE_ACTIVE ? + WIFI_SCAN_TYPE_ACTIVE : WIFI_SCAN_TYPE_PASSIVE); + if (iwr->u.data.flags & IW_SCAN_THIS_ESSID && + req->essid_len < sizeof(target_ssid)) + { + /* Scan specific ESSID */ + + memcpy(&target_ssid[0], req->essid, req->essid_len); + config->ssid = &target_ssid[0]; + config->ssid[req->essid_len] = '\0'; + } + } + else + { + /* Default scan parameters */ + + wlinfo("INFO: Use default scan parameters\n"); + config->scan_type = WIFI_SCAN_TYPE_ACTIVE; /* Active scan */ + } + + esp_wifi_start(); + + esp_wifi_scan_stop(); + ret = esp_wifi_scan_start(config, false); + if (ret != OK) + { + wlerr("ERROR: Scan error, ret: %d\n", ret); + } + else + { + /* Allocate buffer to store scan result */ + + if (priv->scan_result == NULL) + { + priv->scan_result = kmm_malloc(WIFI_SCAN_RESULT_SIZE); + if (priv->scan_result == NULL) + { + wlerr("ERROR: Cannot allocate result buffer\n"); + ret = -ENOMEM; + } + else + { + memset(priv->scan_result, 0x0, WIFI_SCAN_RESULT_SIZE); + } + } + } + + if (config) + { + kmm_free(config); + config = NULL; + wlinfo("INFO: start scan\n"); + } + + g_scan_priv.scan_status = ESP_SCAN_RUN; + + return ret; +} + +/**************************************************************************** + * Name: esp_wifi_get_scan_results + * + * Description: + * Get scan result + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_get_scan_results(struct iwreq *iwr) +{ + int ret = OK; + struct timespec abstime; + static bool scan_block = false; + struct wifi_scan_result *priv = &g_scan_priv; + + if (g_scan_priv.scan_status == ESP_SCAN_RUN) + { + if (scan_block == false) + { + scan_block = true; + clock_gettime(CLOCK_REALTIME, &abstime); + abstime.tv_sec += SCAN_TIME_SEC; + nxsem_timedwait(&priv->scan_signal, &abstime); + scan_block = false; + } + else + { + ret = -EINVAL; + goto exit_failed; + } + } + + if ((iwr == NULL) || (g_scan_priv.scan_status != ESP_SCAN_DONE)) + { + ret = -EINVAL; + goto exit_failed; + } + + if (!priv->scan_result) + { + /* Result have already been requested */ + + ret = OK; + iwr->u.data.length = 0; + goto exit_failed; + } + + if (iwr->u.data.pointer == NULL || + iwr->u.data.length < priv->scan_result_size) + { + /* Stat request, return scan_result_size */ + + ret = -E2BIG; + iwr->u.data.pointer = NULL; + iwr->u.data.length = priv->scan_result_size; + goto exit_failed; + } + + if (priv->scan_result_size <= 0) + { + ret = OK; + iwr->u.data.length = 0; + goto exit_free_buffer; + } + + /* Copy result to user buffer */ + + if (iwr->u.data.length > priv->scan_result_size) + { + iwr->u.data.length = priv->scan_result_size; + } + + memcpy(iwr->u.data.pointer, priv->scan_result, iwr->u.data.length); + +exit_free_buffer: + + /* Free scan result buffer */ + + kmm_free(priv->scan_result); + priv->scan_result = NULL; + priv->scan_result_size = 0; + g_scan_priv.scan_status = ESP_SCAN_DISABLED; + +exit_failed: + if (ret < 0) + { + iwr->u.data.length = 0; + } + + return ret; +} + +/**************************************************************************** + * Name: esp_wifi_scan_event_parse + * + * Description: + * Parse scan information + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_wifi_scan_event_parse(void) +{ + struct wifi_scan_result *priv = &g_scan_priv; + wifi_ap_record_t *ap_list_buffer = NULL; + uint16_t bss_total = 0; + uint8_t bss_count = 0; + bool parse_done = false; + + esp_wifi_scan_get_ap_num(&bss_total); + if (bss_total == 0) + { + wlinfo("INFO: None AP is scanned\n"); + return; + } + + ap_list_buffer = kmm_malloc(bss_total * sizeof(wifi_ap_record_t)); + if (ap_list_buffer == NULL) + { + wlerr("ERROR: Failed to malloc buffer to print scan results"); + return; + } + + memset(ap_list_buffer, 0x0, sizeof(ap_list_buffer)); + if (esp_wifi_scan_get_ap_records(&bss_total, + (wifi_ap_record_t *)ap_list_buffer) == OK) + { + struct iw_event *iwe; + unsigned int result_size; + size_t essid_len; + size_t essid_len_aligned; + for (bss_count = 0; bss_count < bss_total; bss_count++) + { + result_size = WIFI_SCAN_RESULT_SIZE - priv->scan_result_size; + + /* Copy BSSID */ + + if (result_size < ESP_IW_EVENT_SIZE(ap_addr)) + { + goto scan_result_full; + } + + iwe = (struct iw_event *) + &priv->scan_result[priv->scan_result_size]; + iwe->len = ESP_IW_EVENT_SIZE(ap_addr); + iwe->cmd = SIOCGIWAP; + memcpy(&iwe->u.ap_addr.sa_data, ap_list_buffer[bss_count].bssid, + sizeof(ap_list_buffer[bss_count].bssid)); + iwe->u.ap_addr.sa_family = ARPHRD_ETHER; + priv->scan_result_size += ESP_IW_EVENT_SIZE(ap_addr); + result_size -= ESP_IW_EVENT_SIZE(ap_addr); + + /* Copy ESSID */ + + essid_len = MIN(strlen((const char *) + ap_list_buffer[bss_count].ssid), 32); + essid_len_aligned = (essid_len + 3) & -4; + if (result_size < ESP_IW_EVENT_SIZE(essid)+essid_len_aligned) + { + goto scan_result_full; + } + + iwe = (struct iw_event *) + &priv->scan_result[priv->scan_result_size]; + iwe->len = ESP_IW_EVENT_SIZE(essid)+essid_len_aligned; + iwe->cmd = SIOCGIWESSID; + iwe->u.essid.flags = 0; + iwe->u.essid.length = essid_len; + + /* Special processing for iw_point, set offset in pointer field */ + + iwe->u.essid.pointer = (FAR void *)sizeof(iwe->u.essid); + memcpy(&iwe->u.essid + 1, + ap_list_buffer[bss_count].ssid, essid_len); + wlinfo("INFO: ssid %s\n", ap_list_buffer[bss_count].ssid); + priv->scan_result_size += + ESP_IW_EVENT_SIZE(essid)+essid_len_aligned; + result_size -= ESP_IW_EVENT_SIZE(essid)+essid_len_aligned; + + /* Copy link quality info */ + + if (result_size < ESP_IW_EVENT_SIZE(qual)) + { + goto scan_result_full; + } + + iwe = (struct iw_event *) + &priv->scan_result[priv->scan_result_size]; + iwe->len = ESP_IW_EVENT_SIZE(qual); + iwe->cmd = IWEVQUAL; + iwe->u.qual.qual = 0x00; + wlinfo("INFO: signal %d\n", ap_list_buffer[bss_count].rssi); + iwe->u.qual.level = ap_list_buffer[bss_count].rssi; + iwe->u.qual.noise = 0x00; + iwe->u.qual.updated = IW_QUAL_DBM | IW_QUAL_ALL_UPDATED; + + priv->scan_result_size += ESP_IW_EVENT_SIZE(qual); + result_size -= ESP_IW_EVENT_SIZE(qual); + + /* Copy AP mode */ + + if (result_size < ESP_IW_EVENT_SIZE(mode)) + { + goto scan_result_full; + } + + iwe = (struct iw_event *) + &priv->scan_result[priv->scan_result_size]; + iwe->len = ESP_IW_EVENT_SIZE(mode); + iwe->cmd = SIOCGIWMODE; + iwe->u.mode = IW_MODE_MASTER; + priv->scan_result_size += ESP_IW_EVENT_SIZE(mode); + result_size -= ESP_IW_EVENT_SIZE(mode); + + /* Copy AP encryption mode */ + + if (result_size < ESP_IW_EVENT_SIZE(data)) + { + goto scan_result_full; + } + + iwe = (struct iw_event *) + &priv->scan_result[priv->scan_result_size]; + iwe->len = ESP_IW_EVENT_SIZE(data); + iwe->cmd = SIOCGIWENCODE; + iwe->u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + iwe->u.data.length = 0; + iwe->u.essid.pointer = NULL; + + priv->scan_result_size += ESP_IW_EVENT_SIZE(data); + result_size -= ESP_IW_EVENT_SIZE(data); + + /* Copy AP channel */ + + if (result_size < ESP_IW_EVENT_SIZE(freq)) + { + goto scan_result_full; + } + + iwe = (struct iw_event *) + &priv->scan_result[priv->scan_result_size]; + iwe->len = ESP_IW_EVENT_SIZE(freq); + iwe->cmd = SIOCGIWFREQ; + iwe->u.freq.e = 0; + iwe->u.freq.m = ap_list_buffer[bss_count].primary; + + priv->scan_result_size += ESP_IW_EVENT_SIZE(freq); + result_size -= ESP_IW_EVENT_SIZE(freq); + } + + parse_done = true; + } + +scan_result_full: + + /* Continue instead of break to log dropped AP results */ + + if (parse_done == false) + { + wlerr("ERROR: No more space in scan_result buffer\n"); + } + + if (ap_list_buffer) + { + kmm_free(ap_list_buffer); + ap_list_buffer = NULL; + } + + g_scan_priv.scan_status = ESP_SCAN_DONE; + nxsem_post(&priv->scan_signal); +} + +/**************************************************************************** + * Name: esp_wifi_scan_init + * + * Description: + * Initialize ESP32 WiFi scan parameter. + * + * Input Parameters: + * None + * + * Returned Value: + * OK is returned on success. Otherwise, a negated errno value is returned. + * + ****************************************************************************/ + +int esp_wifi_scan_init(void) +{ + int ret; + struct wifi_scan_result *scan_priv = &g_scan_priv; + + /* Initialize the scan structure */ + + memset(scan_priv, 0, sizeof(*scan_priv)); + + /* Init scan signal */ + + if ((ret = nxsem_init(&scan_priv->scan_signal, 0, 0)) != OK) + { + wlerr("ERROR: Initialization scan signal failed: %d\n", ret); + return ret; + } + + if ((ret = nxsem_set_protocol(&scan_priv->scan_signal, + SEM_PRIO_NONE)) != OK) + { + wlerr("ERROR: Set semaphore protocol attribute failed: %d\n", ret); + } + + return ret; +} diff --git a/arch/xtensa/src/esp32/esp32_wifi_utils.h b/arch/xtensa/src/esp32/esp32_wifi_utils.h new file mode 100644 index 0000000000..27ca0bb5e4 --- /dev/null +++ b/arch/xtensa/src/esp32/esp32_wifi_utils.h @@ -0,0 +1,120 @@ +/**************************************************************************** + * arch/xtensa/src/esp32/esp32_wifi_utils.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#ifndef __ARCH_XTENSA_SRC_ESP32_ESP32_UTILS_H +#define __ARCH_XTENSA_SRC_ESP32_ESP32_UTILS_H + +#include +#include + +#include + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_wifi_start_scan + * + * Description: + * Scan all available APs. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_start_scan(struct iwreq *iwr); + +/**************************************************************************** + * Name: esp_wifi_get_scan_results + * + * Description: + * Get scan result + * + * Input Parameters: + * req The argument of the ioctl cmd + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_get_scan_results(struct iwreq *iwr); + +/**************************************************************************** + * Name: esp_wifi_scan_event_parse + * + * Description: + * Parse scan information + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_wifi_scan_event_parse(void); + +/**************************************************************************** + * Name: esp_wifi_scan_para + * + * Description: + * Initialize ESP32 WiFi scan parameter. + * + * Input Parameters: + * None + * + * Returned Value: + * OK is returned on success. Otherwise, a negated errno value is returned. + * + ****************************************************************************/ + +int esp_wifi_scan_init(void); + +#ifdef __cplusplus +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_XTENSA_SRC_ESP32_ESP32_UTILS_H */ diff --git a/arch/xtensa/src/esp32/esp32_wlan.c b/arch/xtensa/src/esp32/esp32_wlan.c index 40ed44ea12..ac82f2e038 100644 --- a/arch/xtensa/src/esp32/esp32_wlan.c +++ b/arch/xtensa/src/esp32/esp32_wlan.c @@ -44,6 +44,8 @@ #endif #include "esp32_wlan.h" +#include "esp32_wifi_utils.h" +#include "esp32_wifi_adapter.h" /**************************************************************************** * Pre-processor Definitions @@ -111,19 +113,21 @@ struct wlan_pktbuf 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 (*essid)(struct iwreq *iwr, bool set); + int (*bssid)(struct iwreq *iwr, bool set); + int (*passwd)(struct iwreq *iwr, bool set); + int (*mode)(struct iwreq *iwr, bool set); + int (*auth)(struct iwreq *iwr, bool set); + int (*freq)(struct iwreq *iwr, bool set); + int (*bitrate)(struct iwreq *iwr, bool set); + int (*txpower)(struct iwreq *iwr, bool set); + int (*channel)(struct iwreq *iwr, bool set); + int (*country)(struct iwreq *iwr, bool set); + int (*rssi)(struct iwreq *iwr, bool set); int (*connect)(void); - int (*disconnect)(void); - int (*event)(pid_t pid, FAR struct sigevent *event); - int (*stop)(void); }; @@ -179,8 +183,17 @@ 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, + .essid = esp_wifi_sta_essid, + .bssid = esp_wifi_sta_bssid, + .passwd = esp_wifi_sta_password, + .mode = esp_wifi_sta_mode, + .auth = esp_wifi_sta_auth, + .freq = esp_wifi_sta_freq, + .bitrate = esp_wifi_sta_bitrate, + .txpower = esp_wifi_sta_txpower, + .channel = esp_wifi_sta_channel, + .country = esp_wifi_sta_country, + .rssi = esp_wifi_sta_rssi, .connect = esp_wifi_sta_connect, .disconnect = esp_wifi_sta_disconnect, .event = esp_wifi_notify_subscribe, @@ -193,8 +206,17 @@ 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, + .essid = esp_wifi_softap_essid, + .bssid = esp_wifi_softap_bssid, + .passwd = esp_wifi_softap_password, + .mode = esp_wifi_softap_mode, + .auth = esp_wifi_softap_auth, + .freq = esp_wifi_softap_freq, + .bitrate = esp_wifi_softap_bitrate, + .txpower = esp_wifi_softap_txpower, + .channel = esp_wifi_softap_channel, + .country = esp_wifi_softap_country, + .rssi = esp_wifi_softap_rssi, .connect = esp_wifi_softap_connect, .disconnect = esp_wifi_softap_disconnect, .event = esp_wifi_notify_subscribe, @@ -1477,54 +1499,136 @@ static int wlan_ioctl(FAR struct net_driver_s *dev, #endif case SIOCSIWENCODEEXT: - { - 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"); - } - } - break; - case SIOCSIWESSID: - { - struct iw_point *essid = &iwr->u.essid; - if (essid->length) - { - ret = ops->ssid(essid->pointer, essid->length); - if (ret < 0) - { - nerr("ERROR: Failed to set SSID\n"); - break; - } + ret = ops->passwd(iwr, true); - ret = ops->connect(); - if (ret < 0) - { - nerr("ERROR: Failed to connect\n"); - break; - } - } - else - { - ret = ops->disconnect(); - if (ret < 0) - { - nerr("ERROR: Failed to connect\n"); - break; - } - } - } break; - case SIOCSIWMODE: - ret = OK; + + case SIOCGIWENCODEEXT: + ret = ops->passwd(iwr, false); break; - case SIOCSIWAUTH: - ret = OK; + + case SIOCSIWESSID: + if ((iwr->u.essid.flags == IW_ESSID_ON) || + (iwr->u.essid.flags == IW_ESSID_DELAY_ON)) + { + ret = ops->essid(iwr, true); + if (ret < 0) + { + break; + } + + if (iwr->u.essid.flags == IW_ESSID_ON) + { + ret = ops->connect(); + } + } + else + { + ret = ops->disconnect(); + } + break; - case SIOCSIWFREQ: - ret = OK; + + case SIOCGIWESSID: /* Get ESSID */ + ret = ops->essid(iwr, false); break; + + case SIOCSIWAP: /* Set access point MAC addresses */ + if (iwr->u.ap_addr.sa_data[0] != 0 && + iwr->u.ap_addr.sa_data[1] != 0 && + iwr->u.ap_addr.sa_data[2] != 0) + { + ret = ops->bssid(iwr, true); + if (ret < 0) + { + nerr("ERROR: Failed to set BSSID\n"); + break; + } + + ret = ops->connect(); + if (ret < 0) + { + nerr("ERROR: Failed to connect\n"); + break; + } + } + else + { + ret = ops->disconnect(); + if (ret < 0) + { + nerr("ERROR: Failed to connect\n"); + break; + } + } + + break; + + case SIOCGIWAP: /* Get access point MAC addresses */ + ret = ops->bssid(iwr, false); + break; + + case SIOCSIWSCAN: + ret = esp_wifi_start_scan(iwr); + break; + + case SIOCGIWSCAN: + ret = esp_wifi_get_scan_results(iwr); + break; + + case SIOCSIWCOUNTRY: /* Set country code */ + ret = ops->country(iwr, true); + break; + + case SIOCGIWSENS: /* Get sensitivity (dBm) */ + ret = ops->rssi(iwr, false); + break; + + case SIOCSIWMODE: /* Set operation mode */ + ret = ops->mode(iwr, true); + break; + + case SIOCGIWMODE: /* Get operation mode */ + ret = ops->mode(iwr, false); + break; + + case SIOCSIWAUTH: /* Set authentication mode params */ + ret = ops->auth(iwr, true); + break; + + case SIOCGIWAUTH: /* Get authentication mode params */ + ret = ops->auth(iwr, false); + break; + + case SIOCSIWFREQ: /* Set channel/frequency (MHz) */ + ret = ops->freq(iwr, true); + break; + + case SIOCGIWFREQ: /* Get channel/frequency (MHz) */ + ret = ops->freq(iwr, false); + break; + + case SIOCSIWRATE: /* Set default bit rate (Mbps) */ + wlwarn("WARNING: SIOCSIWRATE not implemented\n"); + ret = -ENOSYS; + break; + + case SIOCGIWRATE: /* Get default bit rate (Mbps) */ + ret = ops->bitrate(iwr, false); + break; + + case SIOCSIWTXPOW: /* Set transmit power (dBm) */ + ret = ops->txpower(iwr, true); + break; + + case SIOCGIWTXPOW: /* Get transmit power (dBm) */ + ret = ops->txpower(iwr, false); + break; + + case SIOCGIWRANGE: /* Get range of parameters */ + ret = ops->channel(iwr, false); + break; + default: nerr("ERROR: Unrecognized IOCTL command: %d\n", cmd); ret = -ENOTTY; /* Special return value for this case */ @@ -1747,6 +1851,13 @@ int esp32_wlan_sta_initialize(void) eth_mac[0], eth_mac[1], eth_mac[2], eth_mac[3], eth_mac[4], eth_mac[5]); + ret = esp_wifi_scan_init(); + if (ret < 0) + { + nerr("ERROR: Initialize WiFi scan parameter error: %d\n", ret); + return ret; + } + ret = esp32_net_initialize(ESP32_WLAN_STA_DEVNO, eth_mac, &g_sta_ops); if (ret < 0) { @@ -1807,6 +1918,13 @@ int esp32_wlan_softap_initialize(void) eth_mac[0], eth_mac[1], eth_mac[2], eth_mac[3], eth_mac[4], eth_mac[5]); + ret = esp_wifi_scan_init(); + if (ret < 0) + { + nerr("ERROR: Initialize WiFi scan parameter error: %d\n", ret); + return ret; + } + ret = esp32_net_initialize(ESP32_WLAN_SOFTAP_DEVNO, eth_mac, &g_softap_ops); if (ret < 0) diff --git a/boards/xtensa/esp32/esp32-devkitc/configs/sta_softap/defconfig b/boards/xtensa/esp32/esp32-devkitc/configs/sta_softap/defconfig index 7e51c9b482..7d62d88257 100644 --- a/boards/xtensa/esp32/esp32-devkitc/configs/sta_softap/defconfig +++ b/boards/xtensa/esp32/esp32-devkitc/configs/sta_softap/defconfig @@ -43,7 +43,7 @@ CONFIG_HAVE_CXXINITIALIZE=y CONFIG_IDLETHREAD_STACKSIZE=3072 CONFIG_INTELHEX_BINARY=y CONFIG_MAX_TASKS=16 -CONFIG_MM_REGIONS=2 +CONFIG_MM_REGIONS=3 CONFIG_NETDB_DNSCLIENT=y CONFIG_NETDEV_LATEINIT=y CONFIG_NETDEV_PHY_IOCTL=y diff --git a/boards/xtensa/esp32/esp32-devkitc/configs/wapi/defconfig b/boards/xtensa/esp32/esp32-devkitc/configs/wapi/defconfig index d6c4b9bf43..6ce95a34bb 100644 --- a/boards/xtensa/esp32/esp32-devkitc/configs/wapi/defconfig +++ b/boards/xtensa/esp32/esp32-devkitc/configs/wapi/defconfig @@ -32,6 +32,7 @@ CONFIG_HAVE_CXX=y CONFIG_HAVE_CXXINITIALIZE=y CONFIG_IDLETHREAD_STACKSIZE=3072 CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_FLOATINGPOINT=y CONFIG_MAX_TASKS=16 CONFIG_MM_REGIONS=3 CONFIG_NAME_MAX=48 diff --git a/boards/xtensa/esp32/esp32-ethernet-kit/configs/wapi/defconfig b/boards/xtensa/esp32/esp32-ethernet-kit/configs/wapi/defconfig index ea72d4e278..06ecfd3568 100644 --- a/boards/xtensa/esp32/esp32-ethernet-kit/configs/wapi/defconfig +++ b/boards/xtensa/esp32/esp32-ethernet-kit/configs/wapi/defconfig @@ -31,6 +31,7 @@ CONFIG_HAVE_CXX=y CONFIG_HAVE_CXXINITIALIZE=y CONFIG_IDLETHREAD_STACKSIZE=3072 CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_FLOATINGPOINT=y CONFIG_MAX_TASKS=16 CONFIG_MM_REGIONS=3 CONFIG_NAME_MAX=48 diff --git a/boards/xtensa/esp32/esp32-wrover-kit/configs/wapi/defconfig b/boards/xtensa/esp32/esp32-wrover-kit/configs/wapi/defconfig index aa7cc5cf91..f412669f2b 100644 --- a/boards/xtensa/esp32/esp32-wrover-kit/configs/wapi/defconfig +++ b/boards/xtensa/esp32/esp32-wrover-kit/configs/wapi/defconfig @@ -32,6 +32,7 @@ CONFIG_HAVE_CXX=y CONFIG_HAVE_CXXINITIALIZE=y CONFIG_IDLETHREAD_STACKSIZE=3072 CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_FLOATINGPOINT=y CONFIG_MAX_TASKS=16 CONFIG_MM_REGIONS=3 CONFIG_NAME_MAX=48 diff --git a/include/nuttx/wireless/wireless.h b/include/nuttx/wireless/wireless.h index 20e6cf0329..7b240db918 100644 --- a/include/nuttx/wireless/wireless.h +++ b/include/nuttx/wireless/wireless.h @@ -268,6 +268,12 @@ #define IW_MAX_FREQUENCIES 32 /* Max. frequencies in struct iw_range */ +/* ESSID flags */ + +#define IW_ESSID_OFF 0 /* Disconnect with access point */ +#define IW_ESSID_ON 1 /* Connect with access point */ +#define IW_ESSID_DELAY_ON 2 /* Delay the connection behavior of essid */ + /* Transmit Power flags available */ #define IW_TXPOW_TYPE 0x00ff /* Type of value */