You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/06/18 11:42:35 UTC
[incubator-nuttx] branch master updated: wireless/bcm43xxx: sort scan result by rssi
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new e6a23e7b8a wireless/bcm43xxx: sort scan result by rssi
e6a23e7b8a is described below
commit e6a23e7b8a9255c952dc43a42a667a61d9874c54
Author: chao.an <an...@xiaomi.com>
AuthorDate: Sat Jun 18 01:26:13 2022 +0800
wireless/bcm43xxx: sort scan result by rssi
1. Replace SCAN_RESULT_SIZE to SCAN_RESULT_ENTRIES
2. filter scan result with better rssi
3. Sort scan result by rssi
Signed-off-by: chao.an <an...@xiaomi.com>
---
drivers/wireless/ieee80211/bcm43xxx/Kconfig | 8 +-
drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.c | 458 +++++++++-------------
drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h | 4 +-
3 files changed, 192 insertions(+), 278 deletions(-)
diff --git a/drivers/wireless/ieee80211/bcm43xxx/Kconfig b/drivers/wireless/ieee80211/bcm43xxx/Kconfig
index d57b0e3c4c..a5a48d7be0 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/Kconfig
+++ b/drivers/wireless/ieee80211/bcm43xxx/Kconfig
@@ -125,11 +125,11 @@ config IEEE80211_BROADCOM_SCHED_PRIORITY
This parameter should be set the bcmf daemon thread
schedule priority
-config IEEE80211_BROADCOM_SCAN_RESULT_SIZE
- int "Broadcom BCMF escan result size"
- default 1024
+config IEEE80211_BROADCOM_SCAN_RESULT_ENTRIES
+ int "Broadcom BCMF escan result entries"
+ default 10
---help---
- This parameter should be set the bcmf escan result buffer size
+ This parameter should be set the bcmf escan result buffer entries
if IEEE80211_BROADCOM_FULLMAC
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.c
index c477cfc7a7..721336b645 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.c
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.c
@@ -53,10 +53,10 @@
* Pre-processor Definitions
****************************************************************************/
-#define DOT11_BSSTYPE_ANY 2
-#define BCMF_SCAN_TIMEOUT_TICK (5*CLOCKS_PER_SEC)
-#define BCMF_AUTH_TIMEOUT_MS 20000 /* was 10000 */
-#define BCMF_SCAN_RESULT_SIZE CONFIG_IEEE80211_BROADCOM_SCAN_RESULT_SIZE
+#define DOT11_BSSTYPE_ANY 2
+#define BCMF_SCAN_TIMEOUT_TICK (5*CLOCKS_PER_SEC)
+#define BCMF_AUTH_TIMEOUT_MS 20000 /* was 10000 */
+#define BCMF_SCAN_RESULT_ENTRIES CONFIG_IEEE80211_BROADCOM_SCAN_RESULT_ENTRIES
/* CLM file is cut into pieces of MAX_CHUNK_LEN.
* It is relatively small because dongles (FW) have a small maximum size
@@ -623,16 +623,19 @@ void bcmf_wl_auth_event_handler(FAR struct bcmf_dev_s *priv,
*/
void bcmf_wl_scan_event_handler(FAR struct bcmf_dev_s *priv,
- struct bcmf_event_s *event,
+ FAR struct bcmf_event_s *event,
unsigned int len)
{
- uint32_t status;
- uint32_t event_len;
- struct wl_escan_result *result;
- struct wl_bss_info *bss;
- unsigned int bss_info_len;
+ FAR struct wl_escan_result *result;
unsigned int escan_result_len;
- unsigned int bss_count = 0;
+ FAR struct wl_bss_info *curr;
+ FAR struct wl_bss_info *bss;
+ uint32_t event_len;
+ int16_t worst_rssi;
+ int worst_entry;
+ uint32_t status;
+ int i;
+ int j;
event_len = len;
@@ -666,7 +669,7 @@ void bcmf_wl_scan_event_handler(FAR struct bcmf_dev_s *priv,
/* Process escan result payload */
- result = (struct wl_escan_result *)&event[1];
+ result = (FAR struct wl_escan_result *)&event[1];
if (len < result->buflen ||
result->buflen < sizeof(struct wl_escan_result))
@@ -674,260 +677,78 @@ void bcmf_wl_scan_event_handler(FAR struct bcmf_dev_s *priv,
goto exit_invalid_frame;
}
- /* wl_escan_result structure contains a wl_bss_info field */
-
- len = result->buflen - sizeof(struct wl_escan_result)
- + sizeof(struct wl_bss_info);
-
/* Process bss_infos */
bss = result->bss_info;
- while (len > 0 && bss_count < result->bss_count)
+ for (i = 0; i < result->bss_count; i++)
{
- struct iw_event *iwe;
- unsigned int result_size;
- size_t essid_len;
- size_t essid_len_aligned;
- uint8_t *ie_buffer;
- unsigned int ie_offset;
- unsigned int check_offset;
+ worst_entry = -1;
+ worst_rssi = 0;
- result_size = BCMF_SCAN_RESULT_SIZE - priv->scan_result_size;
- bss_info_len = bss->length;
+ wlinfo("Scan result: <%.32s> "
+ "%02x:%02x:%02x:%02x:%02x:%02x "
+ "signal %d %d %d\n",
+ bss->SSID,
+ bss->BSSID.ether_addr_octet[0],
+ bss->BSSID.ether_addr_octet[1],
+ bss->BSSID.ether_addr_octet[2],
+ bss->BSSID.ether_addr_octet[3],
+ bss->BSSID.ether_addr_octet[4],
+ bss->BSSID.ether_addr_octet[5],
+ bss->RSSI, bss->phy_noise, bss->SNR);
- if (len < bss_info_len)
+ for (j = 0; j < priv->scan_result_entries; j++)
{
- wlerr("bss_len error %d %d\n", len, bss_info_len);
- goto exit_invalid_frame;
- }
-
- /* Append current bss_info to priv->scan_results
- * FIXME protect this against race conditions
- */
+ curr = &priv->scan_result[j];
- /* Check if current bss AP is not already detected */
+ /* Check if current bss AP is not already detected */
- check_offset = 0;
-
- while (priv->scan_result_size - check_offset
- >= offsetof(struct iw_event, u))
- {
- iwe = (struct iw_event *)&priv->scan_result[check_offset];
-
- if (iwe->cmd == SIOCGIWAP)
+ if (memcmp(&curr->BSSID, &bss[i].BSSID,
+ sizeof(curr->BSSID)) == 0)
{
- if (memcmp(&iwe->u.ap_addr.sa_data,
- bss->BSSID.ether_addr_octet,
- sizeof(bss->BSSID.ether_addr_octet)) == 0)
+ /* Replace the duplicate entry if rssi is
+ * better than before
+ */
+
+ if (curr->RSSI < bss[i].RSSI)
{
- goto process_next_bss;
+ memcpy(curr, bss, sizeof(*curr));
}
- }
-
- check_offset += iwe->len;
- }
-
- wlinfo("Scan result: <%.32s> %02x:%02x:%02x:%02x:%02x:%02x\n",
- bss->SSID,
- bss->BSSID.ether_addr_octet[0],
- bss->BSSID.ether_addr_octet[1],
- bss->BSSID.ether_addr_octet[2],
- bss->BSSID.ether_addr_octet[3],
- bss->BSSID.ether_addr_octet[4],
- bss->BSSID.ether_addr_octet[5]);
-
- /* Copy BSSID */
-
- if (result_size < BCMF_IW_EVENT_SIZE(ap_addr))
- {
- goto scan_result_full;
- }
-
- iwe = (struct iw_event *)&priv->scan_result[priv->scan_result_size];
- iwe->len = BCMF_IW_EVENT_SIZE(ap_addr);
- iwe->cmd = SIOCGIWAP;
- memcpy(&iwe->u.ap_addr.sa_data, bss->BSSID.ether_addr_octet,
- sizeof(bss->BSSID.ether_addr_octet));
- iwe->u.ap_addr.sa_family = ARPHRD_ETHER;
-
- priv->scan_result_size += BCMF_IW_EVENT_SIZE(ap_addr);
- result_size -= BCMF_IW_EVENT_SIZE(ap_addr);
-
- /* Copy ESSID */
-
- essid_len = min(strlen((const char *)bss->SSID), 32);
- essid_len_aligned = (essid_len + 3) & -4;
-
- if (result_size < BCMF_IW_EVENT_SIZE(essid)+essid_len_aligned)
- {
- goto scan_result_full;
- }
- iwe = (struct iw_event *)&priv->scan_result[priv->scan_result_size];
- iwe->len = BCMF_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, bss->SSID, essid_len);
-
- priv->scan_result_size += BCMF_IW_EVENT_SIZE(essid)+essid_len_aligned;
- result_size -= BCMF_IW_EVENT_SIZE(essid)+essid_len_aligned;
-
- /* Copy link quality info */
-
- if (result_size < BCMF_IW_EVENT_SIZE(qual))
- {
- goto scan_result_full;
- }
-
- iwe = (struct iw_event *)&priv->scan_result[priv->scan_result_size];
- iwe->len = BCMF_IW_EVENT_SIZE(qual);
- iwe->cmd = IWEVQUAL;
- iwe->u.qual.qual = bss->SNR;
- wlinfo("signal %d %d %d\n", bss->RSSI, bss->phy_noise, bss->SNR);
- iwe->u.qual.level = bss->RSSI;
- iwe->u.qual.noise = bss->phy_noise;
- iwe->u.qual.updated = IW_QUAL_DBM | IW_QUAL_ALL_UPDATED;
-
- priv->scan_result_size += BCMF_IW_EVENT_SIZE(qual);
- result_size -= BCMF_IW_EVENT_SIZE(qual);
-
- /* Copy AP mode */
-
- if (result_size < BCMF_IW_EVENT_SIZE(mode))
- {
- goto scan_result_full;
- }
-
- iwe = (struct iw_event *)&priv->scan_result[priv->scan_result_size];
- iwe->len = BCMF_IW_EVENT_SIZE(mode);
- iwe->cmd = SIOCGIWMODE;
- if (bss->capability & DOT11_CAP_ESS)
- {
- iwe->u.mode = IW_MODE_INFRA;
- }
- else if (bss->capability & DOT11_CAP_IBSS)
- {
- iwe->u.mode = IW_MODE_ADHOC;
- }
- else
- {
- iwe->u.mode = IW_MODE_AUTO;
- }
-
- priv->scan_result_size += BCMF_IW_EVENT_SIZE(mode);
- result_size -= BCMF_IW_EVENT_SIZE(mode);
-
- /* Copy AP encryption mode */
-
- if (result_size < BCMF_IW_EVENT_SIZE(data))
- {
- goto scan_result_full;
- }
-
- iwe = (struct iw_event *)&priv->scan_result[priv->scan_result_size];
- iwe->len = BCMF_IW_EVENT_SIZE(data);
- iwe->cmd = SIOCGIWENCODE;
- iwe->u.data.flags = bss->capability & DOT11_CAP_PRIVACY ?
- IW_ENCODE_ENABLED | IW_ENCODE_NOKEY :
- IW_ENCODE_DISABLED;
- iwe->u.data.length = 0;
- iwe->u.essid.pointer = NULL;
-
- priv->scan_result_size += BCMF_IW_EVENT_SIZE(data);
- result_size -= BCMF_IW_EVENT_SIZE(data);
-
- /* Copy relevant raw IE frame */
-
- if (bss->ie_offset >= bss_info_len ||
- bss->ie_length > bss_info_len - bss->ie_offset)
- {
- goto process_next_bss;
- }
-
- ie_offset = 0;
- ie_buffer = (uint8_t *)bss + bss->ie_offset;
-
- while (1)
- {
- size_t ie_frame_size;
-
- if (bss->ie_length - ie_offset < 2)
- {
- /* Minimum Information element size is 2 bytes */
-
- break;
+ goto process_next_bss;
}
- ie_frame_size = ie_buffer[ie_offset + 1] + 2;
+ /* Find worst rssi and mark the entry */
- if (ie_frame_size > bss->ie_length - ie_offset)
+ if (curr->RSSI < worst_rssi)
{
- /* Entry too big */
-
- break;
+ worst_entry = j;
+ worst_rssi = curr->RSSI;
}
+ }
+
+ if (priv->scan_result_entries == BCMF_SCAN_RESULT_ENTRIES)
+ {
+ /* Entries full and replace the worst entry */
- switch (ie_buffer[ie_offset])
+ if (worst_entry >= 0)
{
- case IEEE80211_ELEMID_RSN:
+ curr = &priv->scan_result[worst_entry];
+ if (curr->RSSI < bss->RSSI)
{
- size_t ie_frame_size_aligned;
- ie_frame_size_aligned = (ie_frame_size + 3) & -4;
-
- wlinfo("found RSN\n");
-
- if (result_size < BCMF_IW_EVENT_SIZE(data) +
- ie_frame_size_aligned)
- {
- break;
- }
-
- iwe = (struct iw_event *)
- &priv->scan_result[priv->scan_result_size];
-
- iwe->len = BCMF_IW_EVENT_SIZE(data)+ie_frame_size_aligned;
- iwe->cmd = IWEVGENIE;
- iwe->u.data.flags = 0;
- iwe->u.data.length = ie_frame_size;
- iwe->u.data.pointer = (FAR void *)sizeof(iwe->u.data);
- memcpy(&iwe->u.data + 1, &ie_buffer[ie_offset],
- ie_frame_size);
-
- priv->scan_result_size += BCMF_IW_EVENT_SIZE(essid) +
- ie_frame_size_aligned;
- result_size -= BCMF_IW_EVENT_SIZE(essid) +
- ie_frame_size_aligned;
- break;
+ memcpy(curr, bss, sizeof(*curr));
}
-
- default:
- break;
}
- ie_offset += ie_buffer[ie_offset + 1] + 2;
+process_next_bss:
+ continue;
}
- goto process_next_bss;
-
- scan_result_full:
-
- /* Continue instead of break to log dropped AP results */
-
- wlerr("No more space in scan_result buffer\n");
-
- process_next_bss:
-
- /* Process next bss_info */
+ curr = &priv->scan_result[priv->scan_result_entries];
+ memcpy(curr, bss, sizeof(*curr));
- len -= bss_info_len;
- bss = (struct wl_bss_info *)((uint8_t *)bss + bss_info_len);
- bss_count += 1;
+ priv->scan_result_entries++;
}
wl_escan_result_processed:
@@ -959,7 +780,124 @@ wl_escan_result_processed:
exit_invalid_frame:
wlerr("Invalid scan result event\n");
- bcmf_hexdump((uint8_t *)event, event_len, (unsigned long)event);
+ bcmf_hexdump((FAR uint8_t *)event, event_len, (unsigned long)event);
+}
+
+static int bcmf_wl_scan_format_results(FAR struct bcmf_dev_s *priv,
+ FAR struct iwreq *iwr)
+{
+ FAR wl_bss_info_t *scan_result[BCMF_SCAN_RESULT_ENTRIES];
+ FAR wl_bss_info_t *info;
+ FAR struct iw_event *iwe;
+ FAR char *pointer;
+ int len;
+ int i;
+ int j;
+
+ if (priv->scan_result_entries == 0)
+ {
+ iwr->u.data.length = 0;
+ return OK;
+ }
+
+ len = IW_EV_LEN(ap_addr) + IW_EV_LEN(qual) +
+ IW_EV_LEN(freq) + IW_EV_LEN(data) +
+ IW_EV_LEN(essid);
+
+ len *= priv->scan_result_entries;
+
+ for (i = 0; i < priv->scan_result_entries; i++)
+ {
+ scan_result[i] = &priv->scan_result[i];
+ len += (min(strlen((FAR const char *)scan_result[i]->SSID),
+ 32) + 3) & ~3;
+ }
+
+ if (iwr->u.data.pointer == NULL || iwr->u.data.length < len)
+ {
+ iwr->u.data.length = len;
+ return -E2BIG;
+ }
+
+ /* Sort list by RSSI */
+
+ for (i = 0; i < priv->scan_result_entries; i++)
+ {
+ for (j = 0; j + 1 < priv->scan_result_entries - i; j++)
+ {
+ if (scan_result[j]->RSSI < scan_result[j + 1]->RSSI)
+ {
+ info = scan_result[j];
+ scan_result[j] = scan_result[j + 1];
+ scan_result[j + 1] = info;
+ }
+ }
+ }
+
+ pointer = iwr->u.data.pointer;
+
+ /* Copy scan result */
+
+ for (i = 0; i < priv->scan_result_entries; i++)
+ {
+ info = scan_result[i];
+
+ /* Copy BSSID */
+
+ iwe = (FAR struct iw_event *)pointer;
+ iwe->cmd = SIOCGIWAP;
+ iwe->u.ap_addr.sa_family = ARPHRD_ETHER;
+ memcpy(&iwe->u.ap_addr.sa_data,
+ info->BSSID.ether_addr_octet, IFHWADDRLEN);
+ iwe->len = IW_EV_LEN(ap_addr);
+ pointer += iwe->len;
+
+ /* Copy ESSID */
+
+ iwe = (FAR struct iw_event *)pointer;
+ iwe->cmd = SIOCGIWESSID;
+ iwe->u.essid.flags = 0;
+ iwe->u.essid.length = min(strlen((FAR const char *)info->SSID), 32);
+ iwe->u.essid.pointer = (FAR void *)sizeof(iwe->u.essid);
+ memcpy(&iwe->u.essid + 1, info->SSID, iwe->u.essid.length);
+ iwe->len = IW_EV_LEN(essid) + ((iwe->u.essid.length + 3) & ~3);
+ pointer += iwe->len;
+
+ /* Copy link quality info */
+
+ iwe = (FAR struct iw_event *)pointer;
+ iwe->cmd = IWEVQUAL;
+ iwe->u.qual.qual = info->SNR;
+ iwe->u.qual.level = info->RSSI;
+ iwe->u.qual.noise = info->phy_noise;
+ iwe->u.qual.updated = IW_QUAL_DBM | IW_QUAL_ALL_UPDATED;
+ iwe->len = IW_EV_LEN(qual);
+ pointer += iwe->len;
+
+ /* Copy AP control channel */
+
+ iwe = (FAR struct iw_event *)pointer;
+ iwe->cmd = SIOCGIWFREQ;
+ iwe->u.freq.e = 0;
+ iwe->u.freq.m = info->ctl_ch;
+ iwe->len = IW_EV_LEN(freq);
+ pointer += iwe->len;
+
+ /* Copy AP encryption mode */
+
+ iwe = (FAR struct iw_event *)pointer;
+ iwe->cmd = SIOCGIWENCODE;
+ iwe->u.data.flags = info->capability & DOT11_CAP_PRIVACY ?
+ IW_ENCODE_ENABLED | IW_ENCODE_NOKEY :
+ IW_ENCODE_DISABLED;
+ iwe->u.data.length = 0;
+ iwe->u.essid.pointer = NULL;
+ iwe->len = IW_EV_LEN(data);
+ pointer += iwe->len;
+ }
+
+ iwr->u.data.length = pointer - (FAR char *)iwr->u.data.pointer;
+ return OK;
}
void bcmf_wl_scan_timeout(wdparm_t arg)
@@ -1130,7 +1068,8 @@ int bcmf_wl_start_scan(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
if (priv->scan_result == NULL)
{
- priv->scan_result = kmm_malloc(BCMF_SCAN_RESULT_SIZE);
+ priv->scan_result = kmm_malloc(sizeof(wl_bss_info_t) *
+ BCMF_SCAN_RESULT_ENTRIES);
if (priv->scan_result == NULL)
{
wlerr("Cannot allocate result buffer\n");
@@ -1141,7 +1080,7 @@ int bcmf_wl_start_scan(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
wlinfo("start scan\n");
- priv->scan_result_size = 0;
+ priv->scan_result_entries = 0;
priv->scan_status = BCMF_SCAN_RUN;
out_len = sizeof(scan_params);
@@ -1202,41 +1141,16 @@ int bcmf_wl_get_scan_results(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
goto exit_sem_post;
}
- 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_sem_post;
- }
-
- if (priv->scan_result_size <= 0)
+ ret = bcmf_wl_scan_format_results(priv, iwr);
+ if (ret == OK)
{
- ret = OK;
- iwr->u.data.length = 0;
- goto exit_free_buffer;
- }
-
- /* Copy result to user buffer */
+ /* Free scan result buffer */
- if (iwr->u.data.length > priv->scan_result_size)
- {
- iwr->u.data.length = priv->scan_result_size;
+ kmm_free(priv->scan_result);
+ priv->scan_result = NULL;
+ priv->scan_result_entries = 0;
}
- 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;
-
exit_sem_post:
nxsem_post(&priv->control_mutex);
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h b/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h
index 3a5c96d63e..1361912e1a 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h
@@ -89,8 +89,8 @@ struct bcmf_dev_s
int scan_status; /* Current scan status */
struct wdog_s scan_timeout; /* Scan timeout timer */
- FAR uint8_t *scan_result; /* Temp buffer that holds results */
- unsigned int scan_result_size; /* Current size of temp buffer */
+ FAR wl_bss_info_t *scan_result; /* Temp buffer that holds results */
+ unsigned int scan_result_entries; /* Current entries of temp buffer */
sem_t auth_signal; /* Authentication notification signal */
int auth_status; /* Authentication status */