tmedicci commented on code in PR #12337: URL: https://github.com/apache/nuttx/pull/12337#discussion_r1599803370
########## arch/risc-v/src/common/espressif/esp_wifi_utils.c: ########## @@ -0,0 +1,643 @@ +/**************************************************************************** + * arch/risc-v/src/common/espressif/esp_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 <nuttx/config.h> + +#include <assert.h> +#include <errno.h> +#include <debug.h> +#include <netinet/arp.h> +#include <sys/param.h> + +#include <nuttx/kmalloc.h> +#include <nuttx/wireless/wireless.h> + +#include "esp_wifi_adapter.h" + +#include "esp_log.h" +#include "esp_mac.h" +#include "esp_private/phy.h" +#include "esp_private/wifi.h" +#include "esp_random.h" +#include "esp_timer.h" +#include "esp_wpa.h" +#include "rom/ets_sys.h" +#include "soc/soc_caps.h" + +#include "esp_wifi_utils.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_ESPRESSIF_WIFI_SCAN_RESULT_SIZE +# define WIFI_SCAN_RESULT_SIZE CONFIG_ESPRESSIF_WIFI_SCAN_RESULT_SIZE +#else +# define WIFI_SCAN_RESULT_SIZE (4096) +#endif + +#define SCAN_TIME_SEC (5) + +/* Maximum number of channels for Wi-Fi 2.4Ghz */ + +#define CHANNEL_MAX_NUM (14) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +enum scan_status_e +{ + ESP_SCAN_DISABLED = 0, + ESP_SCAN_RUN, + ESP_SCAN_DONE +}; + +/* Wi-Fi 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 = +{ + .scan_signal = SEM_INITIALIZER(0), +}; +static uint8_t g_channel_num = 0; +static uint8_t g_channel_list[CHANNEL_MAX_NUM]; + +/**************************************************************************** + * 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; + struct iw_scan_req *req; + int ret = 0; + int i; + uint8_t target_mac[MAC_LEN]; + uint8_t target_ssid[SSID_MAX_LEN + 1]; + memset(target_ssid, 0x0, sizeof(SSID_MAX_LEN + 1)); + + if (iwr == NULL) + { + wlerr("ERROR: Invalid ioctl cmd.\n"); + return -EINVAL; + } + + if (g_scan_priv.scan_status != ESP_SCAN_DISABLED) + { + return OK; + } + + config = kmm_calloc(1, sizeof(wifi_scan_config_t)); + if (config == NULL) + { + wlerr("ERROR: Cannot allocate result buffer\n"); + return -ENOMEM; + } + + g_channel_num = 0; + memset(g_channel_list, 0x0, CHANNEL_MAX_NUM); + + 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 */ + + config->show_hidden = true; + config->bssid = NULL; + memcpy(&target_ssid[0], req->essid, req->essid_len); + config->ssid = &target_ssid[0]; + config->ssid[req->essid_len] = '\0'; + } + + if (iwr->u.data.flags & IW_SCAN_THIS_FREQ && + req->num_channels > 0) + { + /* Scan specific channels */ + + DEBUGASSERT(req->num_channels <= CHANNEL_MAX_NUM); + g_channel_num = req->num_channels; + if (req->num_channels == 1) + { + config->channel = req->channel_list[0].m; + } + else + { + for (i = 0; i < req->num_channels; i++) + { + g_channel_list[i] = req->channel_list[i].m; + } + } + } + + memset(target_mac, 0xff, MAC_LEN); + if (memcmp(req->bssid.sa_data, target_mac, MAC_LEN) != 0) + { + /* Scan specific bssid */ + + memcpy(target_mac, req->bssid.sa_data, MAC_LEN); + config->bssid = &target_mac[0]; + } + } + else + { + /* Default scan parameters */ + + wlinfo("INFO: Use default scan parameters\n"); + config->scan_type = WIFI_SCAN_TYPE_ACTIVE; /* Active scan */ + } + + esp_wifi_start(); + 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; + static bool scan_block = false; + struct wifi_scan_result *priv = &g_scan_priv; + + if (g_scan_priv.scan_status == ESP_SCAN_RUN) + { + irqstate_t irqstate = enter_critical_section(); + if (scan_block == false) + { + scan_block = true; + leave_critical_section(irqstate); + nxsem_tickwait(&priv->scan_signal, SEC2TICK(SCAN_TIME_SEC)); + scan_block = false; + } + else + { + leave_critical_section(irqstate); + ret = -EINVAL; + goto exit_failed; + } + } + else if (g_scan_priv.scan_status == ESP_SCAN_DISABLED) + { + return -EINVAL; + } + + if ((iwr == NULL) || (g_scan_priv.scan_status != ESP_SCAN_DONE)) + { + ret = -EINVAL; + goto exit_failed; + } + + if (priv->scan_result == NULL) + { + /* 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; Review Comment: In the current implementation, it returns before being overridden (and it makes sense to provide the upper layers how big it was): ``` 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; return ret; } ``` -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
