| /****************************************************************************** |
| * |
| * This file is provided under a dual license. When you use or |
| * distribute this software, you may choose to be licensed under |
| * version 2 of the GNU General Public License ("GPLv2 License") |
| * or BSD License. |
| * |
| * GPLv2 License |
| * |
| * Copyright(C) 2016 MediaTek Inc. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of version 2 of the GNU General Public License as |
| * published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it will be useful, but |
| * WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| * See http://www.gnu.org/licenses/gpl-2.0.html for more details. |
| * |
| * BSD LICENSE |
| * |
| * Copyright(C) 2016 MediaTek Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name of the copyright holder nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| *****************************************************************************/ |
| /* |
| ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/scan.c#4 |
| */ |
| |
| /*! \file "scan.c" |
| * \brief This file defines the scan profile and the processing function of |
| * scan result for SCAN Module. |
| * |
| * The SCAN Profile selection is part of SCAN MODULE and responsible for defining |
| * SCAN Parameters - e.g. MIN_CHANNEL_TIME, number of scan channels. |
| * In this file we also define the process of SCAN Result including adding, searching |
| * and removing SCAN record from the list. |
| */ |
| |
| |
| /******************************************************************************* |
| * C O M P I L E R F L A G S |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * E X T E R N A L R E F E R E N C E S |
| ******************************************************************************** |
| */ |
| #include "precomp.h" |
| |
| /******************************************************************************* |
| * C O N S T A N T S |
| ******************************************************************************** |
| */ |
| #define REPLICATED_BEACON_TIME_THRESHOLD (3000) |
| #define REPLICATED_BEACON_FRESH_PERIOD (10000) |
| #define REPLICATED_BEACON_STRENGTH_THRESHOLD (32) |
| |
| #define ROAMING_NO_SWING_RCPI_STEP (10) |
| |
| |
| |
| /******************************************************************************* |
| * D A T A T Y P E S |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * P U B L I C D A T A |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * P R I V A T E D A T A |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * M A C R O S |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * F U N C T I O N D E C L A R A T I O N S |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * F U N C T I O N S |
| ******************************************************************************** |
| */ |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is used by SCN to initialize its variables |
| * |
| * @param (none) |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID scnInit(IN P_ADAPTER_T prAdapter) |
| { |
| P_SCAN_INFO_T prScanInfo; |
| P_BSS_DESC_T prBSSDesc; |
| PUINT_8 pucBSSBuff; |
| UINT_32 i; |
| #if CFG_SUPPORT_ROAMING_SKIP_ONE_AP |
| P_ROAM_BSS_DESC_T prRoamBSSDesc; |
| PUINT_8 pucRoamBSSBuff; |
| #endif |
| |
| ASSERT(prAdapter); |
| |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| pucBSSBuff = &prScanInfo->aucScanBuffer[0]; |
| #if CFG_SUPPORT_ROAMING_SKIP_ONE_AP |
| pucRoamBSSBuff = &prScanInfo->aucScanRoamBuffer[0]; |
| #endif |
| |
| DBGLOG(SCN, INFO, "->scnInit()\n"); |
| |
| /* 4 <1> Reset STATE and Message List */ |
| prScanInfo->eCurrentState = SCAN_STATE_IDLE; |
| |
| prScanInfo->rLastScanCompletedTime = (OS_SYSTIME) 0; |
| |
| LINK_INITIALIZE(&prScanInfo->rPendingMsgList); |
| |
| /* 4 <2> Reset link list of BSS_DESC_T */ |
| kalMemZero((PVOID) pucBSSBuff, SCN_MAX_BUFFER_SIZE); |
| #if CFG_SUPPORT_ROAMING_SKIP_ONE_AP |
| kalMemZero((PVOID) pucRoamBSSBuff, SCN_ROAM_MAX_BUFFER_SIZE); |
| #endif |
| |
| LINK_INITIALIZE(&prScanInfo->rFreeBSSDescList); |
| LINK_INITIALIZE(&prScanInfo->rBSSDescList); |
| #if CFG_SUPPORT_ROAMING_SKIP_ONE_AP |
| LINK_INITIALIZE(&prScanInfo->rRoamFreeBSSDescList); |
| LINK_INITIALIZE(&prScanInfo->rRoamBSSDescList); |
| #endif |
| |
| for (i = 0; i < CFG_MAX_NUM_BSS_LIST; i++) { |
| |
| prBSSDesc = (P_BSS_DESC_T) pucBSSBuff; |
| |
| LINK_INSERT_TAIL(&prScanInfo->rFreeBSSDescList, &prBSSDesc->rLinkEntry); |
| |
| pucBSSBuff += ALIGN_4(sizeof(BSS_DESC_T)); |
| } |
| /* Check if the memory allocation consist with this initialization function */ |
| ASSERT(((ULONG) pucBSSBuff - (ULONG)&prScanInfo->aucScanBuffer[0]) == SCN_MAX_BUFFER_SIZE); |
| |
| #if CFG_SUPPORT_ROAMING_SKIP_ONE_AP |
| for (i = 0; i < CFG_MAX_NUM_ROAM_BSS_LIST; i++) { |
| prRoamBSSDesc = (P_ROAM_BSS_DESC_T) pucRoamBSSBuff; |
| |
| LINK_INSERT_TAIL(&prScanInfo->rRoamFreeBSSDescList, &prRoamBSSDesc->rLinkEntry); |
| |
| pucRoamBSSBuff += ALIGN_4(sizeof(ROAM_BSS_DESC_T)); |
| } |
| ASSERT(((ULONG) pucRoamBSSBuff - (ULONG)&prScanInfo->aucScanRoamBuffer[0]) == |
| SCN_ROAM_MAX_BUFFER_SIZE); |
| #endif |
| /* reset freest channel information */ |
| prScanInfo->fgIsSparseChannelValid = FALSE; |
| |
| /* reset NLO state */ |
| prScanInfo->fgNloScanning = FALSE; |
| } /* end of scnInit() */ |
| |
| VOID scnFreeAllPendingScanRquests(IN P_ADAPTER_T prAdapter) |
| { |
| P_SCAN_INFO_T prScanInfo; |
| P_MSG_HDR_T prMsgHdr; |
| P_MSG_SCN_SCAN_REQ prScanReqMsg; |
| |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| |
| /* check for pending scanning requests */ |
| while (!LINK_IS_EMPTY(&(prScanInfo->rPendingMsgList))) { |
| |
| /* load next message from pending list as scan parameters */ |
| LINK_REMOVE_HEAD(&(prScanInfo->rPendingMsgList), prMsgHdr, P_MSG_HDR_T); |
| if (prMsgHdr) { |
| prScanReqMsg = (P_MSG_SCN_SCAN_REQ) prMsgHdr; |
| DBGLOG(SCN, INFO, |
| "free scan request eMsgId[%d] ucSeqNum [%d] BSSID[%d]!!\n", prMsgHdr->eMsgId, |
| prScanReqMsg->ucSeqNum, prScanReqMsg->ucBssIndex); |
| cnmMemFree(prAdapter, prMsgHdr); |
| } else { |
| /* should not deliver to this function */ |
| ASSERT(0); |
| } |
| /* switch to next state */ |
| } |
| |
| DBGLOG(SCN, INFO, "%s()\n", __func__); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is used by SCN to uninitialize its variables |
| * |
| * @param (none) |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID scnUninit(IN P_ADAPTER_T prAdapter) |
| { |
| P_SCAN_INFO_T prScanInfo; |
| |
| ASSERT(prAdapter); |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| |
| DBGLOG(SCN, INFO, "%s()\n", __func__); |
| |
| scnFreeAllPendingScanRquests(prAdapter); |
| |
| /* 4 <1> Reset STATE and Message List */ |
| prScanInfo->eCurrentState = SCAN_STATE_IDLE; |
| |
| prScanInfo->rLastScanCompletedTime = (OS_SYSTIME) 0; |
| |
| /* NOTE(Kevin): Check rPendingMsgList ? */ |
| |
| /* 4 <2> Reset link list of BSS_DESC_T */ |
| LINK_INITIALIZE(&prScanInfo->rFreeBSSDescList); |
| LINK_INITIALIZE(&prScanInfo->rBSSDescList); |
| #if CFG_SUPPORT_ROAMING_SKIP_ONE_AP |
| LINK_INITIALIZE(&prScanInfo->rRoamFreeBSSDescList); |
| LINK_INITIALIZE(&prScanInfo->rRoamBSSDescList); |
| #endif |
| } /* end of scnUninit() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Find the corresponding BSS Descriptor according to given BSSID |
| * |
| * @param[in] prAdapter Pointer to the Adapter structure. |
| * @param[in] aucBSSID Given BSSID. |
| * |
| * @return Pointer to BSS Descriptor, if found. NULL, if not found |
| */ |
| /*----------------------------------------------------------------------------*/ |
| P_BSS_DESC_T scanSearchBssDescByBssid(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]) |
| { |
| return scanSearchBssDescByBssidAndSsid(prAdapter, aucBSSID, FALSE, NULL); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Find the corresponding BSS Descriptor according to given BSSID |
| * |
| * @param[in] prAdapter Pointer to the Adapter structure. |
| * @param[in] aucBSSID Given BSSID. |
| * @param[in] fgCheckSsid Need to check SSID or not. (for multiple SSID with single BSSID cases) |
| * @param[in] prSsid Specified SSID |
| * |
| * @return Pointer to BSS Descriptor, if found. NULL, if not found |
| */ |
| /*----------------------------------------------------------------------------*/ |
| P_BSS_DESC_T |
| scanSearchBssDescByBssidAndSsid(IN P_ADAPTER_T prAdapter, |
| IN UINT_8 aucBSSID[], IN BOOLEAN fgCheckSsid, IN P_PARAM_SSID_T prSsid) |
| { |
| P_SCAN_INFO_T prScanInfo; |
| P_LINK_T prBSSDescList; |
| P_BSS_DESC_T prBssDesc; |
| P_BSS_DESC_T prDstBssDesc = (P_BSS_DESC_T) NULL; |
| |
| ASSERT(prAdapter); |
| ASSERT(aucBSSID); |
| |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| |
| prBSSDescList = &prScanInfo->rBSSDescList; |
| |
| /* Search BSS Desc from current SCAN result list. */ |
| LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { |
| |
| if (!(EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID))) |
| continue; |
| if (fgCheckSsid == FALSE || prSsid == NULL) |
| return prBssDesc; |
| if (EQUAL_SSID(prBssDesc->aucSSID, |
| prBssDesc->ucSSIDLen, prSsid->aucSsid, prSsid->u4SsidLen)) { |
| return prBssDesc; |
| } |
| if (prDstBssDesc == NULL && prBssDesc->fgIsHiddenSSID == TRUE) { |
| prDstBssDesc = prBssDesc; |
| continue; |
| } |
| if (prBssDesc->eBSSType == BSS_TYPE_P2P_DEVICE) { |
| /* 20120206 frog: Equal BSSID but not SSID, |
| * SSID not hidden, SSID must be updated. |
| */ |
| COPY_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, prSsid->aucSsid, |
| (UINT_8) (prSsid->u4SsidLen)); |
| return prBssDesc; |
| } |
| } |
| |
| return prDstBssDesc; |
| |
| } /* end of scanSearchBssDescByBssid() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Find the corresponding BSS Descriptor according to given Transmitter Address. |
| * |
| * @param[in] prAdapter Pointer to the Adapter structure. |
| * @param[in] aucSrcAddr Given Source Address(TA). |
| * |
| * @return Pointer to BSS Descriptor, if found. NULL, if not found |
| */ |
| /*----------------------------------------------------------------------------*/ |
| P_BSS_DESC_T scanSearchBssDescByTA(IN P_ADAPTER_T prAdapter, IN UINT_8 aucSrcAddr[]) |
| { |
| return scanSearchBssDescByTAAndSsid(prAdapter, aucSrcAddr, FALSE, NULL); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Find the corresponding BSS Descriptor according to given Transmitter Address. |
| * |
| * @param[in] prAdapter Pointer to the Adapter structure. |
| * @param[in] aucSrcAddr Given Source Address(TA). |
| * @param[in] fgCheckSsid Need to check SSID or not. (for multiple SSID with single BSSID cases) |
| * @param[in] prSsid Specified SSID |
| * |
| * @return Pointer to BSS Descriptor, if found. NULL, if not found |
| */ |
| /*----------------------------------------------------------------------------*/ |
| P_BSS_DESC_T |
| scanSearchBssDescByTAAndSsid(IN P_ADAPTER_T prAdapter, |
| IN UINT_8 aucSrcAddr[], IN BOOLEAN fgCheckSsid, IN P_PARAM_SSID_T prSsid) |
| { |
| P_SCAN_INFO_T prScanInfo; |
| P_LINK_T prBSSDescList; |
| P_BSS_DESC_T prBssDesc; |
| P_BSS_DESC_T prDstBssDesc = (P_BSS_DESC_T) NULL; |
| |
| ASSERT(prAdapter); |
| ASSERT(aucSrcAddr); |
| |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| |
| prBSSDescList = &prScanInfo->rBSSDescList; |
| |
| /* Search BSS Desc from current SCAN result list. */ |
| LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { |
| |
| if (EQUAL_MAC_ADDR(prBssDesc->aucSrcAddr, aucSrcAddr)) { |
| if (fgCheckSsid == FALSE || prSsid == NULL) |
| return prBssDesc; |
| if (EQUAL_SSID(prBssDesc->aucSSID, |
| prBssDesc->ucSSIDLen, prSsid->aucSsid, prSsid->u4SsidLen)) { |
| return prBssDesc; |
| } else if (prDstBssDesc == NULL && prBssDesc->fgIsHiddenSSID == TRUE) { |
| prDstBssDesc = prBssDesc; |
| } |
| } |
| } |
| |
| return prDstBssDesc; |
| |
| } /* end of scanSearchBssDescByTA() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Find the corresponding BSS Descriptor according to |
| * given eBSSType, BSSID and Transmitter Address |
| * |
| * @param[in] prAdapter Pointer to the Adapter structure. |
| * @param[in] eBSSType BSS Type of incoming Beacon/ProbeResp frame. |
| * @param[in] aucBSSID Given BSSID of Beacon/ProbeResp frame. |
| * @param[in] aucSrcAddr Given source address (TA) of Beacon/ProbeResp frame. |
| * |
| * @return Pointer to BSS Descriptor, if found. NULL, if not found |
| */ |
| /*----------------------------------------------------------------------------*/ |
| P_BSS_DESC_T |
| scanSearchExistingBssDesc(IN P_ADAPTER_T prAdapter, |
| IN ENUM_BSS_TYPE_T eBSSType, IN UINT_8 aucBSSID[], IN UINT_8 aucSrcAddr[]) |
| { |
| return scanSearchExistingBssDescWithSsid(prAdapter, eBSSType, aucBSSID, aucSrcAddr, FALSE, NULL); |
| } |
| |
| #if CFG_SUPPORT_ROAMING_SKIP_ONE_AP |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief |
| * |
| * @param |
| * |
| * @return |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID scanRemoveRoamBssDescsByTime(IN P_ADAPTER_T prAdapter, IN UINT_32 u4RemoveTime) |
| { |
| P_SCAN_INFO_T prScanInfo; |
| P_LINK_T prRoamBSSDescList; |
| P_LINK_T prRoamFreeBSSDescList; |
| P_ROAM_BSS_DESC_T prRoamBssDesc; |
| P_ROAM_BSS_DESC_T prRoamBSSDescNext; |
| OS_SYSTIME rCurrentTime; |
| |
| ASSERT(prAdapter); |
| |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| prRoamBSSDescList = &prScanInfo->rRoamBSSDescList; |
| prRoamFreeBSSDescList = &prScanInfo->rRoamFreeBSSDescList; |
| |
| GET_CURRENT_SYSTIME(&rCurrentTime); |
| |
| LINK_FOR_EACH_ENTRY_SAFE(prRoamBssDesc, prRoamBSSDescNext, prRoamBSSDescList, rLinkEntry, |
| ROAM_BSS_DESC_T) { |
| |
| if (CHECK_FOR_TIMEOUT(rCurrentTime, prRoamBssDesc->rUpdateTime, |
| SEC_TO_SYSTIME(u4RemoveTime))) { |
| |
| LINK_REMOVE_KNOWN_ENTRY(prRoamBSSDescList, prRoamBssDesc); |
| LINK_INSERT_TAIL(prRoamFreeBSSDescList, &prRoamBssDesc->rLinkEntry); |
| } |
| } |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief |
| * |
| * @param |
| * |
| * @return |
| */ |
| /*----------------------------------------------------------------------------*/ |
| P_ROAM_BSS_DESC_T |
| scanSearchRoamBssDescBySsid(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) |
| { |
| P_SCAN_INFO_T prScanInfo; |
| P_LINK_T prRoamBSSDescList; |
| P_ROAM_BSS_DESC_T prRoamBssDesc; |
| |
| ASSERT(prAdapter); |
| |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| |
| prRoamBSSDescList = &prScanInfo->rRoamBSSDescList; |
| |
| /* Search BSS Desc from current SCAN result list. */ |
| LINK_FOR_EACH_ENTRY(prRoamBssDesc, prRoamBSSDescList, rLinkEntry, ROAM_BSS_DESC_T) { |
| if (EQUAL_SSID(prRoamBssDesc->aucSSID, prRoamBssDesc->ucSSIDLen, |
| prBssDesc->aucSSID, prBssDesc->ucSSIDLen)) { |
| return prRoamBssDesc; |
| } |
| } |
| |
| return NULL; |
| |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief |
| * |
| * @param |
| * |
| * @return |
| */ |
| /*----------------------------------------------------------------------------*/ |
| P_ROAM_BSS_DESC_T scanAllocateRoamBssDesc(IN P_ADAPTER_T prAdapter) |
| { |
| P_SCAN_INFO_T prScanInfo; |
| P_LINK_T prRoamFreeBSSDescList; |
| P_ROAM_BSS_DESC_T prRoamBssDesc = NULL; |
| |
| ASSERT(prAdapter); |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| |
| prRoamFreeBSSDescList = &prScanInfo->rRoamFreeBSSDescList; |
| |
| LINK_REMOVE_HEAD(prRoamFreeBSSDescList, prRoamBssDesc, P_ROAM_BSS_DESC_T); |
| |
| if (prRoamBssDesc) { |
| P_LINK_T prRoamBSSDescList; |
| |
| kalMemZero(prRoamBssDesc, sizeof(ROAM_BSS_DESC_T)); |
| |
| prRoamBSSDescList = &prScanInfo->rRoamBSSDescList; |
| |
| LINK_INSERT_HEAD(prRoamBSSDescList, &prRoamBssDesc->rLinkEntry); |
| } |
| |
| return prRoamBssDesc; |
| } |
| |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief |
| * |
| * @param |
| * |
| * @return |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID scanAddToRoamBssDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) |
| { |
| P_ROAM_BSS_DESC_T prRoamBssDesc; |
| |
| prRoamBssDesc = scanSearchRoamBssDescBySsid(prAdapter, prBssDesc); |
| |
| if (prRoamBssDesc == NULL) { |
| UINT_32 u4RemoveTime = REMOVE_TIMEOUT_TWO_DAY; |
| |
| do { |
| prRoamBssDesc = scanAllocateRoamBssDesc(prAdapter); |
| if (prRoamBssDesc) |
| break; |
| scanRemoveRoamBssDescsByTime(prAdapter, u4RemoveTime); |
| u4RemoveTime = u4RemoveTime / 2; |
| } while (u4RemoveTime > 0); |
| |
| if (prRoamBssDesc != NULL) |
| COPY_SSID(prRoamBssDesc->aucSSID, prRoamBssDesc->ucSSIDLen, |
| prBssDesc->aucSSID, prBssDesc->ucSSIDLen); |
| } |
| |
| if (prRoamBssDesc != NULL) |
| GET_CURRENT_SYSTIME(&prRoamBssDesc->rUpdateTime); |
| } |
| |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief |
| * |
| * @param |
| * |
| * @return |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID scanSearchBssDescOfRoamSsid(IN P_ADAPTER_T prAdapter) |
| { |
| #define SSID_ONLY_EXIST_ONE_AP 1 /* If only exist one same ssid AP, avoid unnecessary scan */ |
| |
| P_SCAN_INFO_T prScanInfo; |
| P_LINK_T prBSSDescList; |
| P_BSS_DESC_T prBssDesc; |
| P_BSS_INFO_T prAisBssInfo; |
| UINT_32 u4SameSSIDCount = 0; |
| |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| prBSSDescList = &prScanInfo->rBSSDescList; |
| |
| if (prAisBssInfo->eConnectionState != PARAM_MEDIA_STATE_CONNECTED) |
| return; |
| |
| LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { |
| if (EQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, |
| prAisBssInfo->aucSSID, prAisBssInfo->ucSSIDLen)) { |
| u4SameSSIDCount++; |
| if (u4SameSSIDCount > SSID_ONLY_EXIST_ONE_AP) { |
| scanAddToRoamBssDesc(prAdapter, prBssDesc); |
| break; |
| } |
| } |
| } |
| } |
| |
| #endif /* CFG_SUPPORT_ROAMING_SKIP_ONE_AP */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Find the corresponding BSS Descriptor according to |
| * given eBSSType, BSSID and Transmitter Address |
| * |
| * @param[in] prAdapter Pointer to the Adapter structure. |
| * @param[in] eBSSType BSS Type of incoming Beacon/ProbeResp frame. |
| * @param[in] aucBSSID Given BSSID of Beacon/ProbeResp frame. |
| * @param[in] aucSrcAddr Given source address (TA) of Beacon/ProbeResp frame. |
| * @param[in] fgCheckSsid Need to check SSID or not. (for multiple SSID with single BSSID cases) |
| * @param[in] prSsid Specified SSID |
| * |
| * @return Pointer to BSS Descriptor, if found. NULL, if not found |
| */ |
| /*----------------------------------------------------------------------------*/ |
| P_BSS_DESC_T |
| scanSearchExistingBssDescWithSsid(IN P_ADAPTER_T prAdapter, |
| IN ENUM_BSS_TYPE_T eBSSType, |
| IN UINT_8 aucBSSID[], |
| IN UINT_8 aucSrcAddr[], IN BOOLEAN fgCheckSsid, IN P_PARAM_SSID_T prSsid) |
| { |
| P_SCAN_INFO_T prScanInfo; |
| P_BSS_DESC_T prBssDesc, prIBSSBssDesc; |
| /* CASE III */ |
| P_LINK_T prBSSDescList; |
| P_LINK_T prFreeBSSDescList; |
| |
| ASSERT(prAdapter); |
| ASSERT(aucSrcAddr); |
| |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| |
| switch (eBSSType) { |
| case BSS_TYPE_P2P_DEVICE: |
| fgCheckSsid = FALSE; |
| /* fall through */ |
| case BSS_TYPE_INFRASTRUCTURE: |
| #if CFG_SUPPORT_ROAMING_SKIP_ONE_AP |
| scanSearchBssDescOfRoamSsid(prAdapter); |
| /* fall through */ |
| #endif |
| case BSS_TYPE_BOW_DEVICE: |
| prBssDesc = scanSearchBssDescByBssidAndSsid(prAdapter, aucBSSID, fgCheckSsid, prSsid); |
| |
| /* if (eBSSType == prBssDesc->eBSSType) */ |
| |
| return prBssDesc; |
| case BSS_TYPE_IBSS: |
| prIBSSBssDesc = scanSearchBssDescByBssidAndSsid(prAdapter, aucBSSID, fgCheckSsid, prSsid); |
| prBssDesc = scanSearchBssDescByTAAndSsid(prAdapter, aucSrcAddr, fgCheckSsid, prSsid); |
| |
| /* NOTE(Kevin): |
| * Rules to maintain the SCAN Result: |
| * For AdHoc - |
| * CASE I We have TA1(BSSID1), but it change its BSSID to BSSID2 |
| * -> Update TA1 entry's BSSID. |
| * CASE II We have TA1(BSSID1), and get TA1(BSSID1) again |
| * -> Update TA1 entry's contain. |
| * CASE III We have a SCAN result TA1(BSSID1), and TA2(BSSID2). Sooner or |
| * later, TA2 merge into TA1, we get TA2(BSSID1) |
| * -> Remove TA2 first and then replace TA1 entry's TA with TA2, |
| * Still have only one entry of BSSID. |
| * CASE IV We have a SCAN result TA1(BSSID1), and another TA2 also merge into BSSID1. |
| * -> Replace TA1 entry's TA with TA2, Still have only one entry. |
| * CASE V New IBSS |
| * -> Add this one to SCAN result. |
| */ |
| if (prBssDesc) { |
| if ((!prIBSSBssDesc) || /* CASE I */ |
| (prBssDesc == prIBSSBssDesc)) { /* CASE II */ |
| |
| return prBssDesc; |
| } |
| |
| |
| prBSSDescList = &prScanInfo->rBSSDescList; |
| prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; |
| |
| /* Remove this BSS Desc from the BSS Desc list */ |
| LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); |
| |
| /* Return this BSS Desc to the free BSS Desc list. */ |
| LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry); |
| |
| return prIBSSBssDesc; |
| } |
| |
| if (prIBSSBssDesc) { /* CASE IV */ |
| |
| return prIBSSBssDesc; |
| } |
| /* CASE V */ |
| break; /* Return NULL; */ |
| default: |
| break; |
| } |
| |
| return (P_BSS_DESC_T) NULL; |
| |
| } /* end of scanSearchExistingBssDesc() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief bypass BSS Descriptors from current list according to specific BSSID. |
| * |
| * @param[in] prAdapter Pointer to the Adapter structure. |
| * @param[in] aucBSSID Given BSSID. |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| BOOLEAN scanByPassRemoveBssDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) |
| { |
| P_SCAN_INFO_T prScanInfo; |
| P_SCAN_PARAM_T prScanParam; |
| UINT_8 ucIndex = 0; |
| BOOLEAN fgIsByPassRemove = FALSE; |
| |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| prScanParam = &prScanInfo->rScanParam; |
| |
| for (ucIndex = 0; ucIndex < prScanParam->ucSSIDNum; ucIndex++) { |
| if (EQUAL_SSID(prBssDesc->aucSSID, |
| prBssDesc->ucSSIDLen, |
| prScanParam->aucSpecifiedSSID[ucIndex], |
| prScanParam->ucSpecifiedSSIDLen[ucIndex])) { |
| fgIsByPassRemove = TRUE; |
| DBGLOG(INIT, INFO, "scanByPassRemoveBssDesc %s | %s\n", |
| prBssDesc->aucSSID, prScanParam->aucSpecifiedSSID[ucIndex]); |
| break; |
| } |
| } |
| return fgIsByPassRemove; |
| } |
| |
| |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Delete BSS Descriptors from current list according to given Remove Policy. |
| * |
| * @param[in] u4RemovePolicy Remove Policy. |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID scanRemoveBssDescsByPolicy(IN P_ADAPTER_T prAdapter, IN UINT_32 u4RemovePolicy) |
| { |
| P_CONNECTION_SETTINGS_T prConnSettings; |
| P_SCAN_INFO_T prScanInfo; |
| P_LINK_T prBSSDescList; |
| P_LINK_T prFreeBSSDescList; |
| P_BSS_DESC_T prBssDesc; |
| |
| ASSERT(prAdapter); |
| |
| prConnSettings = &(prAdapter->rWifiVar.rConnSettings); |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| prBSSDescList = &prScanInfo->rBSSDescList; |
| prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; |
| |
| /* DBGLOG(SCN, TRACE, ("Before Remove - Number Of SCAN Result = %ld\n", */ |
| /* prBSSDescList->u4NumElem)); */ |
| |
| if (u4RemovePolicy & SCN_RM_POLICY_TIMEOUT) { |
| P_BSS_DESC_T prBSSDescNext; |
| OS_SYSTIME rCurrentTime; |
| |
| GET_CURRENT_SYSTIME(&rCurrentTime); |
| |
| /* Search BSS Desc from current SCAN result list. */ |
| LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) { |
| |
| if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) && |
| (prBssDesc->fgIsConnected || prBssDesc->fgIsConnecting)) { |
| /* Don't remove the one currently we are connected. */ |
| continue; |
| } |
| |
| if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_SPECIFIC_SSID) && |
| scanByPassRemoveBssDesc(prAdapter, prBssDesc)) { |
| /* Don't remove the one currently we are looking for specifi SSID. */ |
| continue; |
| } |
| |
| if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, |
| SEC_TO_SYSTIME(SCN_BSS_DESC_REMOVE_TIMEOUT_SEC))) { |
| |
| /* DBGLOG(SCN, TRACE, ("Remove TIMEOUT BSS DESC(%#x): |
| * MAC: "MACSTR", Current Time = %08lx, Update Time = %08lx\n", |
| */ |
| /* prBssDesc, MAC2STR(prBssDesc->aucBSSID), rCurrentTime, prBssDesc->rUpdateTime)); */ |
| |
| /* Remove this BSS Desc from the BSS Desc list */ |
| LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); |
| |
| /* Return this BSS Desc to the free BSS Desc list. */ |
| LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry); |
| } |
| } |
| } |
| if (u4RemovePolicy & SCN_RM_POLICY_OLDEST_HIDDEN) { |
| P_BSS_DESC_T prBssDescOldest = (P_BSS_DESC_T) NULL; |
| |
| /* Search BSS Desc from current SCAN result list. */ |
| LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { |
| |
| if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) && |
| (prBssDesc->fgIsConnected || prBssDesc->fgIsConnecting)) { |
| /* Don't remove the one currently we are connected. */ |
| continue; |
| } |
| if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_SPECIFIC_SSID) && |
| scanByPassRemoveBssDesc(prAdapter, prBssDesc)) { |
| /* Don't remove the one currently we are looking for specifi SSID. */ |
| continue; |
| } |
| |
| if (!prBssDesc->fgIsHiddenSSID) |
| continue; |
| |
| if (!prBssDescOldest) { /* 1st element */ |
| prBssDescOldest = prBssDesc; |
| continue; |
| } |
| |
| if (TIME_BEFORE(prBssDesc->rUpdateTime, prBssDescOldest->rUpdateTime)) |
| prBssDescOldest = prBssDesc; |
| } |
| |
| if (prBssDescOldest) { |
| /* DBGLOG(SCN, TRACE, |
| * ("Remove OLDEST HIDDEN BSS DESC(%#x): MAC: "MACSTR", Update Time = %08lx\n", |
| */ |
| /* prBssDescOldest, MAC2STR(prBssDescOldest->aucBSSID), prBssDescOldest->rUpdateTime)); */ |
| |
| /* Remove this BSS Desc from the BSS Desc list */ |
| LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDescOldest); |
| |
| /* Return this BSS Desc to the free BSS Desc list. */ |
| LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDescOldest->rLinkEntry); |
| } |
| } |
| if (u4RemovePolicy & SCN_RM_POLICY_SMART_WEAKEST) { |
| P_BSS_DESC_T prBssDescWeakest = (P_BSS_DESC_T) NULL; |
| P_BSS_DESC_T prBssDescWeakestSameSSID = (P_BSS_DESC_T) NULL; |
| UINT_32 u4SameSSIDCount = 0; |
| |
| /* Search BSS Desc from current SCAN result list. */ |
| LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { |
| |
| if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) && |
| (prBssDesc->fgIsConnected || prBssDesc->fgIsConnecting)) { |
| /* Don't remove the one currently we are connected. */ |
| continue; |
| } |
| if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_SPECIFIC_SSID) && |
| scanByPassRemoveBssDesc(prAdapter, prBssDesc)) { |
| /* Don't remove the one currently we are looking for specifi SSID. */ |
| continue; |
| } |
| |
| if ((!prBssDesc->fgIsHiddenSSID) && |
| (EQUAL_SSID(prBssDesc->aucSSID, |
| prBssDesc->ucSSIDLen, prConnSettings->aucSSID, prConnSettings->ucSSIDLen))) { |
| |
| u4SameSSIDCount++; |
| |
| if (!prBssDescWeakestSameSSID) |
| prBssDescWeakestSameSSID = prBssDesc; |
| else if (prBssDesc->ucRCPI < prBssDescWeakestSameSSID->ucRCPI) |
| prBssDescWeakestSameSSID = prBssDesc; |
| } |
| |
| if (!prBssDescWeakest) { /* 1st element */ |
| prBssDescWeakest = prBssDesc; |
| continue; |
| } |
| |
| if (prBssDesc->ucRCPI < prBssDescWeakest->ucRCPI) |
| prBssDescWeakest = prBssDesc; |
| |
| } |
| |
| if ((u4SameSSIDCount >= SCN_BSS_DESC_SAME_SSID_THRESHOLD) && (prBssDescWeakestSameSSID)) |
| prBssDescWeakest = prBssDescWeakestSameSSID; |
| |
| if (prBssDescWeakest) { |
| |
| /* DBGLOG(SCN, TRACE, ("Remove WEAKEST BSS DESC(%#x): MAC: "MACSTR", Update Time = %08lx\n", */ |
| /* prBssDescOldest, MAC2STR(prBssDescOldest->aucBSSID), prBssDescOldest->rUpdateTime)); */ |
| |
| /* Remove this BSS Desc from the BSS Desc list */ |
| LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDescWeakest); |
| |
| /* Return this BSS Desc to the free BSS Desc list. */ |
| LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDescWeakest->rLinkEntry); |
| } |
| } |
| if (u4RemovePolicy & SCN_RM_POLICY_ENTIRE) { |
| P_BSS_DESC_T prBSSDescNext; |
| |
| LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) { |
| |
| if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) && |
| (prBssDesc->fgIsConnected || prBssDesc->fgIsConnecting)) { |
| /* Don't remove the one currently we are connected. */ |
| continue; |
| } |
| if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_SPECIFIC_SSID) && |
| scanByPassRemoveBssDesc(prAdapter, prBssDesc)) { |
| /* Don't remove the one currently we are looking for specifi SSID. */ |
| continue; |
| } |
| |
| /* Remove this BSS Desc from the BSS Desc list */ |
| LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); |
| |
| /* Return this BSS Desc to the free BSS Desc list. */ |
| LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry); |
| } |
| |
| } |
| |
| return; |
| |
| } /* end of scanRemoveBssDescsByPolicy() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Delete BSS Descriptors from current list according to given BSSID. |
| * |
| * @param[in] prAdapter Pointer to the Adapter structure. |
| * @param[in] aucBSSID Given BSSID. |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID scanRemoveBssDescByBssid(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]) |
| { |
| P_SCAN_INFO_T prScanInfo; |
| P_LINK_T prBSSDescList; |
| P_LINK_T prFreeBSSDescList; |
| P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; |
| P_BSS_DESC_T prBSSDescNext; |
| |
| ASSERT(prAdapter); |
| ASSERT(aucBSSID); |
| |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| prBSSDescList = &prScanInfo->rBSSDescList; |
| prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; |
| |
| /* Check if such BSS Descriptor exists in a valid list */ |
| LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) { |
| |
| if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { |
| |
| /* Remove this BSS Desc from the BSS Desc list */ |
| LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); |
| |
| /* Return this BSS Desc to the free BSS Desc list. */ |
| LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry); |
| |
| /* BSSID is not unique, so need to traverse whols link-list */ |
| } |
| } |
| } /* end of scanRemoveBssDescByBssid() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Delete BSS Descriptors from current list according to given band configuration |
| * |
| * @param[in] prAdapter Pointer to the Adapter structure. |
| * @param[in] eBand Given band |
| * @param[in] ucBssIndex AIS - Remove IBSS/Infrastructure BSS |
| * BOW - Remove BOW BSS |
| * P2P - Remove P2P BSS |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID scanRemoveBssDescByBandAndNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_BAND_T eBand, IN UINT_8 ucBssIndex) |
| { |
| P_SCAN_INFO_T prScanInfo; |
| P_LINK_T prBSSDescList; |
| P_LINK_T prFreeBSSDescList; |
| P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; |
| P_BSS_DESC_T prBSSDescNext; |
| BOOLEAN fgToRemove; |
| |
| ASSERT(prAdapter); |
| ASSERT(eBand <= BAND_NUM); |
| ASSERT(ucBssIndex <= MAX_BSS_INDEX); |
| |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| prBSSDescList = &prScanInfo->rBSSDescList; |
| prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; |
| |
| if (eBand == BAND_NULL) |
| return; /* no need to do anything, keep all scan result */ |
| |
| /* Check if such BSS Descriptor exists in a valid list */ |
| LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) { |
| fgToRemove = FALSE; |
| |
| if (prBssDesc->eBand == eBand) { |
| switch (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType) { |
| case NETWORK_TYPE_AIS: |
| if ((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) |
| || (prBssDesc->eBSSType == BSS_TYPE_IBSS)) { |
| fgToRemove = TRUE; |
| } |
| break; |
| |
| case NETWORK_TYPE_P2P: |
| if (prBssDesc->eBSSType == BSS_TYPE_P2P_DEVICE) |
| fgToRemove = TRUE; |
| break; |
| |
| case NETWORK_TYPE_BOW: |
| if (prBssDesc->eBSSType == BSS_TYPE_BOW_DEVICE) |
| fgToRemove = TRUE; |
| break; |
| |
| default: |
| ASSERT(0); |
| break; |
| } |
| } |
| |
| if (fgToRemove == TRUE) { |
| /* Remove this BSS Desc from the BSS Desc list */ |
| LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); |
| |
| /* Return this BSS Desc to the free BSS Desc list. */ |
| LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry); |
| } |
| } |
| } /* end of scanRemoveBssDescByBand() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Clear the CONNECTION FLAG of a specified BSS Descriptor. |
| * |
| * @param[in] aucBSSID Given BSSID. |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID scanRemoveConnFlagOfBssDescByBssid(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]) |
| { |
| P_SCAN_INFO_T prScanInfo; |
| P_LINK_T prBSSDescList; |
| P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; |
| |
| ASSERT(prAdapter); |
| ASSERT(aucBSSID); |
| |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| prBSSDescList = &prScanInfo->rBSSDescList; |
| |
| /* Search BSS Desc from current SCAN result list. */ |
| LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { |
| |
| if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { |
| prBssDesc->fgIsConnected = FALSE; |
| prBssDesc->fgIsConnecting = FALSE; |
| |
| /* BSSID is not unique, so need to traverse whols link-list */ |
| } |
| } |
| |
| return; |
| |
| } /* end of scanRemoveConnectionFlagOfBssDescByBssid() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Allocate new BSS_DESC_T |
| * |
| * @param[in] prAdapter Pointer to the Adapter structure. |
| * |
| * @return Pointer to BSS Descriptor, if has free space. NULL, if has no space. |
| */ |
| /*----------------------------------------------------------------------------*/ |
| P_BSS_DESC_T scanAllocateBssDesc(IN P_ADAPTER_T prAdapter) |
| { |
| P_SCAN_INFO_T prScanInfo; |
| P_LINK_T prFreeBSSDescList; |
| P_BSS_DESC_T prBssDesc; |
| |
| ASSERT(prAdapter); |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| |
| prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; |
| |
| LINK_REMOVE_HEAD(prFreeBSSDescList, prBssDesc, P_BSS_DESC_T); |
| |
| if (prBssDesc) { |
| P_LINK_T prBSSDescList; |
| |
| kalMemZero(prBssDesc, sizeof(BSS_DESC_T)); |
| |
| #if CFG_ENABLE_WIFI_DIRECT |
| LINK_INITIALIZE(&(prBssDesc->rP2pDeviceList)); |
| prBssDesc->fgIsP2PPresent = FALSE; |
| #endif /* CFG_ENABLE_WIFI_DIRECT */ |
| |
| prBSSDescList = &prScanInfo->rBSSDescList; |
| |
| /* NOTE(Kevin): In current design, this new empty BSS_DESC_T will be |
| * inserted to BSSDescList immediately. |
| */ |
| LINK_INSERT_TAIL(prBSSDescList, &prBssDesc->rLinkEntry); |
| } |
| |
| return prBssDesc; |
| |
| } /* end of scanAllocateBssDesc() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This API parses Beacon/ProbeResp frame and insert extracted BSS_DESC_T |
| * with IEs into prAdapter->rWifiVar.rScanInfo.aucScanBuffer |
| * |
| * @param[in] prAdapter Pointer to the Adapter structure. |
| * @param[in] prSwRfb Pointer to the receiving frame buffer. |
| * |
| * @return Pointer to BSS Descriptor |
| * NULL if the Beacon/ProbeResp frame is invalid |
| */ |
| /*----------------------------------------------------------------------------*/ |
| P_BSS_DESC_T scanAddToBssDesc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) |
| { |
| P_BSS_DESC_T prBssDesc = NULL; |
| UINT_16 u2CapInfo; |
| ENUM_BSS_TYPE_T eBSSType = BSS_TYPE_INFRASTRUCTURE; |
| |
| PUINT_8 pucIE; |
| UINT_16 u2IELength; |
| UINT_16 u2Offset = 0; |
| |
| P_WLAN_BEACON_FRAME_T prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T) NULL; |
| P_IE_SSID_T prIeSsid = (P_IE_SSID_T) NULL; |
| P_IE_SUPPORTED_RATE_T prIeSupportedRate = (P_IE_SUPPORTED_RATE_T) NULL; |
| P_IE_EXT_SUPPORTED_RATE_T prIeExtSupportedRate = (P_IE_EXT_SUPPORTED_RATE_T) NULL; |
| UINT_8 ucHwChannelNum = 0; |
| UINT_8 ucIeDsChannelNum = 0; |
| UINT_8 ucIeHtChannelNum = 0; |
| BOOLEAN fgIsValidSsid = FALSE, fgEscape = FALSE; |
| PARAM_SSID_T rSsid; |
| UINT_64 u8Timestamp; |
| BOOLEAN fgIsNewBssDesc = FALSE; |
| |
| UINT_32 i; |
| UINT_8 ucSSIDChar; |
| /* PUINT_8 pucDumpIE; */ |
| |
| ASSERT(prAdapter); |
| ASSERT(prSwRfb); |
| |
| prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T) prSwRfb->pvHeader; |
| |
| WLAN_GET_FIELD_16(&prWlanBeaconFrame->u2CapInfo, &u2CapInfo); |
| WLAN_GET_FIELD_64(&prWlanBeaconFrame->au4Timestamp[0], &u8Timestamp); |
| |
| /* decide BSS type */ |
| switch (u2CapInfo & CAP_INFO_BSS_TYPE) { |
| case CAP_INFO_ESS: |
| /* It can also be Group Owner of P2P Group. */ |
| eBSSType = BSS_TYPE_INFRASTRUCTURE; |
| break; |
| |
| case CAP_INFO_IBSS: |
| eBSSType = BSS_TYPE_IBSS; |
| break; |
| case 0: |
| /* The P2P Device shall set the ESS bit of the Capabilities field |
| * in the Probe Response fame to 0 and IBSS bit to 0. (3.1.2.1.1) |
| */ |
| eBSSType = BSS_TYPE_P2P_DEVICE; |
| break; |
| |
| #if CFG_ENABLE_BT_OVER_WIFI |
| /* @TODO: add rule to identify BOW beacons */ |
| #endif |
| |
| default: |
| return NULL; |
| } |
| |
| /* 4 <1.1> Pre-parse SSID IE */ |
| pucIE = prWlanBeaconFrame->aucInfoElem; |
| u2IELength = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - |
| (UINT_16) OFFSET_OF(WLAN_BEACON_FRAME_BODY_T, aucInfoElem[0]); |
| |
| if (u2IELength > CFG_IE_BUFFER_SIZE) { |
| u2IELength = CFG_IE_BUFFER_SIZE; |
| DBGLOG(SCN, WARN, "IE len(%u) > Max IE buffer size(%u), truncate IE!\n", |
| u2IELength, CFG_IE_BUFFER_SIZE); |
| } |
| |
| IE_FOR_EACH(pucIE, u2IELength, u2Offset) { |
| switch (IE_ID(pucIE)) { |
| case ELEM_ID_SSID: |
| if (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID) { |
| ucSSIDChar = '\0'; |
| |
| /* D-Link DWL-900AP+ */ |
| if (IE_LEN(pucIE) == 0) |
| fgIsValidSsid = FALSE; |
| /* Cisco AP1230A - (IE_LEN(pucIE) == 1) && (SSID_IE(pucIE)->aucSSID[0] == '\0') */ |
| /* Linksys WRK54G/WL520g - (IE_LEN(pucIE) == n) && |
| * (SSID_IE(pucIE)->aucSSID[0~(n-1)] == '\0') |
| */ |
| else { |
| for (i = 0; i < IE_LEN(pucIE); i++) |
| ucSSIDChar |= SSID_IE(pucIE)->aucSSID[i]; |
| |
| if (ucSSIDChar) |
| fgIsValidSsid = TRUE; |
| } |
| |
| /* Update SSID to BSS Descriptor only if SSID is not hidden. */ |
| if (fgIsValidSsid == TRUE) { |
| COPY_SSID(rSsid.aucSsid, |
| rSsid.u4SsidLen, SSID_IE(pucIE)->aucSSID, SSID_IE(pucIE)->ucLength); |
| } |
| } |
| fgEscape = TRUE; |
| break; |
| default: |
| break; |
| } |
| |
| if (fgEscape == TRUE) |
| break; |
| } |
| |
| /* 4 <1.2> Replace existing BSS_DESC_T or allocate a new one */ |
| prBssDesc = scanSearchExistingBssDescWithSsid(prAdapter, |
| eBSSType, |
| (PUINT_8) prWlanBeaconFrame->aucBSSID, |
| (PUINT_8) prWlanBeaconFrame->aucSrcAddr, |
| fgIsValidSsid, fgIsValidSsid == TRUE ? &rSsid : NULL); |
| |
| if (prBssDesc == (P_BSS_DESC_T) NULL) { |
| fgIsNewBssDesc = TRUE; |
| |
| do { |
| /* 4 <1.2.1> First trial of allocation */ |
| prBssDesc = scanAllocateBssDesc(prAdapter); |
| if (prBssDesc) |
| break; |
| /* 4 <1.2.2> Hidden is useless, remove the oldest hidden ssid. (for passive scan) */ |
| scanRemoveBssDescsByPolicy(prAdapter, |
| (SCN_RM_POLICY_EXCLUDE_CONNECTED | |
| SCN_RM_POLICY_OLDEST_HIDDEN | SCN_RM_POLICY_TIMEOUT | |
| SCN_RM_POLICY_EXCLUDE_SPECIFIC_SSID)); |
| |
| /* 4 <1.2.3> Second tail of allocation */ |
| prBssDesc = scanAllocateBssDesc(prAdapter); |
| if (prBssDesc) |
| break; |
| /* 4 <1.2.4> Remove the weakest one */ |
| /* If there are more than half of BSS which has the same ssid as connection |
| * setting, remove the weakest one from them. |
| * Else remove the weakest one. |
| */ |
| scanRemoveBssDescsByPolicy(prAdapter, |
| (SCN_RM_POLICY_EXCLUDE_CONNECTED | |
| SCN_RM_POLICY_SMART_WEAKEST | |
| SCN_RM_POLICY_EXCLUDE_SPECIFIC_SSID)); |
| |
| /* 4 <1.2.5> reallocation */ |
| prBssDesc = scanAllocateBssDesc(prAdapter); |
| if (prBssDesc) |
| break; |
| /* 4 <1.2.6> no space, should not happen */ |
| /* ASSERT(0); // still no space available ? */ |
| return NULL; |
| |
| } while (FALSE); |
| |
| } else { |
| OS_SYSTIME rCurrentTime; |
| |
| /* WCXRP00000091 */ |
| /* if the received strength is much weaker than the original one, */ |
| /* ignore it due to it might be received on the folding frequency */ |
| |
| GET_CURRENT_SYSTIME(&rCurrentTime); |
| |
| ASSERT(prSwRfb->prRxStatusGroup3); |
| |
| if (prBssDesc->eBSSType != eBSSType) { |
| prBssDesc->eBSSType = eBSSType; |
| } else if (HAL_RX_STATUS_GET_CHNL_NUM(prSwRfb->prRxStatus) != |
| prBssDesc->ucChannelNum |
| && prBssDesc->ucRCPI > nicRxGetRcpiValueFromRxv(RCPI_MODE_WF0, prSwRfb)) { |
| |
| /* for signal strength is too much weaker and previous beacon is not stale */ |
| ASSERT(prSwRfb->prRxStatusGroup3); |
| if ((prBssDesc->ucRCPI - |
| nicRxGetRcpiValueFromRxv(RCPI_MODE_WF0, prSwRfb)) >= |
| REPLICATED_BEACON_STRENGTH_THRESHOLD |
| && rCurrentTime - prBssDesc->rUpdateTime <= REPLICATED_BEACON_FRESH_PERIOD) { |
| return prBssDesc; |
| } |
| /* for received beacons too close in time domain */ |
| else if (rCurrentTime - prBssDesc->rUpdateTime <= REPLICATED_BEACON_TIME_THRESHOLD) |
| return prBssDesc; |
| } |
| |
| /* if Timestamp has been reset, re-generate BSS DESC 'cause AP should have reset itself */ |
| if (prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE && u8Timestamp < prBssDesc->u8TimeStamp.QuadPart) { |
| BOOLEAN fgIsConnected, fgIsConnecting; |
| |
| /* set flag for indicating this is a new BSS-DESC */ |
| fgIsNewBssDesc = TRUE; |
| |
| /* backup 2 flags for APs which reset timestamp unexpectedly */ |
| fgIsConnected = prBssDesc->fgIsConnected; |
| fgIsConnecting = prBssDesc->fgIsConnecting; |
| scanRemoveBssDescByBssid(prAdapter, prBssDesc->aucBSSID); |
| |
| prBssDesc = scanAllocateBssDesc(prAdapter); |
| if (!prBssDesc) |
| return NULL; |
| |
| /* restore */ |
| prBssDesc->fgIsConnected = fgIsConnected; |
| prBssDesc->fgIsConnecting = fgIsConnecting; |
| } |
| } |
| #if 1 |
| |
| if (prSwRfb->u2PacketLen > CFG_RAW_BUFFER_SIZE) { |
| DBGLOG(SCN, WARN, "Pkt len(%u) > Max RAW buffer size(%u), truncate it!\n", |
| prSwRfb->u2PacketLen, CFG_RAW_BUFFER_SIZE); |
| prBssDesc->u2RawLength = CFG_RAW_BUFFER_SIZE; |
| } else |
| prBssDesc->u2RawLength = prSwRfb->u2PacketLen; |
| kalMemCopy(prBssDesc->aucRawBuf, prWlanBeaconFrame, prBssDesc->u2RawLength); |
| #endif |
| |
| /* NOTE: Keep consistency of Scan Record during JOIN process */ |
| if (fgIsNewBssDesc == FALSE && prBssDesc->fgIsConnecting) |
| return prBssDesc; |
| /* 4 <2> Get information from Fixed Fields */ |
| prBssDesc->eBSSType = eBSSType; /* Update the latest BSS type information. */ |
| |
| COPY_MAC_ADDR(prBssDesc->aucSrcAddr, prWlanBeaconFrame->aucSrcAddr); |
| |
| COPY_MAC_ADDR(prBssDesc->aucBSSID, prWlanBeaconFrame->aucBSSID); |
| |
| prBssDesc->u8TimeStamp.QuadPart = u8Timestamp; |
| |
| WLAN_GET_FIELD_16(&prWlanBeaconFrame->u2BeaconInterval, &prBssDesc->u2BeaconInterval); |
| |
| prBssDesc->u2CapInfo = u2CapInfo; |
| |
| /* 4 <2.1> Retrieve IEs for later parsing */ |
| u2IELength = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - |
| (UINT_16) OFFSET_OF(WLAN_BEACON_FRAME_BODY_T, aucInfoElem[0]); |
| |
| if (u2IELength > CFG_IE_BUFFER_SIZE) { |
| u2IELength = CFG_IE_BUFFER_SIZE; |
| prBssDesc->fgIsIEOverflow = TRUE; |
| DBGLOG(SCN, WARN, "IE is truncated!\n"); |
| } else { |
| prBssDesc->fgIsIEOverflow = FALSE; |
| } |
| prBssDesc->u2IELength = u2IELength; |
| |
| kalMemCopy(prBssDesc->aucIEBuf, prWlanBeaconFrame->aucInfoElem, u2IELength); |
| |
| /* 4 <2.2> reset prBssDesc variables in case that AP has been reconfigured */ |
| prBssDesc->fgIsERPPresent = FALSE; |
| prBssDesc->fgIsHTPresent = FALSE; |
| prBssDesc->fgIsVHTPresent = FALSE; |
| prBssDesc->eSco = CHNL_EXT_SCN; |
| prBssDesc->fgIEWAPI = FALSE; |
| prBssDesc->fgIERSN = FALSE; |
| prBssDesc->fgIEWPA = FALSE; |
| prBssDesc->eChannelWidth = CW_20_40MHZ; /*Reset VHT OP IE relative settings */ |
| prBssDesc->ucCenterFreqS1 = 0; |
| prBssDesc->ucCenterFreqS2 = 0; |
| |
| /* 4 <3.1> Full IE parsing on SW_RFB_T */ |
| pucIE = prWlanBeaconFrame->aucInfoElem; |
| /* pucDumpIE = pucIE; */ |
| |
| IE_FOR_EACH(pucIE, u2IELength, u2Offset) { |
| |
| switch (IE_ID(pucIE)) { |
| case ELEM_ID_SSID: |
| if ((!prIeSsid) && /* NOTE(Kevin): for Atheros IOT #1 */ |
| (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) { |
| BOOLEAN fgIsHiddenSSID = FALSE; |
| |
| ucSSIDChar = '\0'; |
| |
| prIeSsid = (P_IE_SSID_T) pucIE; |
| |
| /* D-Link DWL-900AP+ */ |
| if (IE_LEN(pucIE) == 0) |
| fgIsHiddenSSID = TRUE; |
| /* Cisco AP1230A - (IE_LEN(pucIE) == 1) && (SSID_IE(pucIE)->aucSSID[0] == '\0') */ |
| /* Linksys WRK54G/WL520g - (IE_LEN(pucIE) == n) && |
| * (SSID_IE(pucIE)->aucSSID[0~(n-1)] == '\0') = |
| */ |
| else { |
| for (i = 0; i < IE_LEN(pucIE); i++) |
| ucSSIDChar |= SSID_IE(pucIE)->aucSSID[i]; |
| |
| if (!ucSSIDChar) |
| fgIsHiddenSSID = TRUE; |
| } |
| |
| /* Update SSID to BSS Descriptor only if SSID is not hidden. */ |
| if (!fgIsHiddenSSID) { |
| COPY_SSID(prBssDesc->aucSSID, |
| prBssDesc->ucSSIDLen, |
| SSID_IE(pucIE)->aucSSID, SSID_IE(pucIE)->ucLength); |
| } |
| |
| } |
| break; |
| |
| case ELEM_ID_SUP_RATES: |
| /* NOTE(Kevin): Buffalo WHR-G54S's supported rate set IE exceed 8. |
| * IE_LEN(pucIE) == 12, "1(B), 2(B), 5.5(B), 6(B), 9(B), 11(B), |
| * 12(B), 18(B), 24(B), 36(B), 48(B), 54(B)" |
| */ |
| /* TP-LINK will set extra and incorrect ie with ELEM_ID_SUP_RATES */ |
| if ((!prIeSupportedRate) && (IE_LEN(pucIE) <= RATE_NUM_SW)) |
| prIeSupportedRate = SUP_RATES_IE(pucIE); |
| break; |
| |
| case ELEM_ID_DS_PARAM_SET: |
| if (IE_LEN(pucIE) == ELEM_MAX_LEN_DS_PARAMETER_SET) |
| ucIeDsChannelNum = DS_PARAM_IE(pucIE)->ucCurrChnl; |
| break; |
| |
| case ELEM_ID_TIM: |
| if (IE_LEN(pucIE) <= ELEM_MAX_LEN_TIM) |
| prBssDesc->ucDTIMPeriod = TIM_IE(pucIE)->ucDTIMPeriod; |
| break; |
| |
| case ELEM_ID_IBSS_PARAM_SET: |
| if (IE_LEN(pucIE) == ELEM_MAX_LEN_IBSS_PARAMETER_SET) |
| prBssDesc->u2ATIMWindow = IBSS_PARAM_IE(pucIE)->u2ATIMWindow; |
| break; |
| |
| #if 0 /* CFG_SUPPORT_802_11D */ |
| case ELEM_ID_COUNTRY_INFO: |
| prBssDesc->prIECountry = (P_IE_COUNTRY_T) pucIE; |
| break; |
| #endif |
| |
| case ELEM_ID_ERP_INFO: |
| if (IE_LEN(pucIE) == ELEM_MAX_LEN_ERP) |
| prBssDesc->fgIsERPPresent = TRUE; |
| break; |
| |
| case ELEM_ID_EXTENDED_SUP_RATES: |
| if (!prIeExtSupportedRate) |
| prIeExtSupportedRate = EXT_SUP_RATES_IE(pucIE); |
| break; |
| |
| case ELEM_ID_RSN: |
| if (rsnParseRsnIE(prAdapter, RSN_IE(pucIE), &prBssDesc->rRSNInfo)) { |
| prBssDesc->fgIERSN = TRUE; |
| prBssDesc->u2RsnCap = prBssDesc->rRSNInfo.u2RsnCap; |
| if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2) |
| rsnCheckPmkidCache(prAdapter, prBssDesc); |
| } |
| break; |
| |
| case ELEM_ID_HT_CAP: |
| prBssDesc->fgIsHTPresent = TRUE; |
| break; |
| |
| case ELEM_ID_HT_OP: |
| if (IE_LEN(pucIE) != (sizeof(IE_HT_OP_T) - 2)) |
| break; |
| |
| if ((((P_IE_HT_OP_T) pucIE)->ucInfo1 & HT_OP_INFO1_SCO) != CHNL_EXT_RES) { |
| prBssDesc->eSco = (ENUM_CHNL_EXT_T) |
| (((P_IE_HT_OP_T) pucIE)->ucInfo1 & HT_OP_INFO1_SCO); |
| } |
| ucIeHtChannelNum = ((P_IE_HT_OP_T) pucIE)->ucPrimaryChannel; |
| |
| break; |
| case ELEM_ID_VHT_CAP: |
| prBssDesc->fgIsVHTPresent = TRUE; |
| #if CFG_SUPPORT_BFEE |
| prBssDesc->ucVhtCapNumSoundingDimensions = |
| ((((P_IE_VHT_CAP_T) pucIE)->u4VhtCapInfo) & VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS) |
| >> VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS_OFFSET; |
| #endif |
| break; |
| |
| case ELEM_ID_VHT_OP: |
| if (IE_LEN(pucIE) != (sizeof(IE_VHT_OP_T) - 2)) |
| break; |
| |
| prBssDesc->eChannelWidth = (ENUM_CHANNEL_WIDTH_T) (((P_IE_VHT_OP_T) pucIE)->ucVhtOperation[0]); |
| prBssDesc->ucCenterFreqS1 = (ENUM_CHANNEL_WIDTH_T) (((P_IE_VHT_OP_T) pucIE)->ucVhtOperation[1]); |
| prBssDesc->ucCenterFreqS2 = (ENUM_CHANNEL_WIDTH_T) (((P_IE_VHT_OP_T) pucIE)->ucVhtOperation[2]); |
| |
| /*add IEEE BW160 patch*/ |
| rlmModifyVhtBwPara(&prBssDesc->ucCenterFreqS1, |
| &prBssDesc->ucCenterFreqS2, |
| (PUINT_8)&prBssDesc->eChannelWidth); |
| |
| |
| |
| break; |
| #if CFG_SUPPORT_WAPI |
| case ELEM_ID_WAPI: |
| if (wapiParseWapiIE(WAPI_IE(pucIE), &prBssDesc->rIEWAPI)) |
| prBssDesc->fgIEWAPI = TRUE; |
| break; |
| #endif |
| |
| case ELEM_ID_VENDOR: /* ELEM_ID_P2P, ELEM_ID_WMM */ |
| { |
| UINT_8 ucOuiType; |
| UINT_16 u2SubTypeVersion; |
| |
| if (rsnParseCheckForWFAInfoElem(prAdapter, pucIE, &ucOuiType, &u2SubTypeVersion)) { |
| if ((ucOuiType == VENDOR_OUI_TYPE_WPA) |
| && (u2SubTypeVersion == VERSION_WPA) |
| && (rsnParseWpaIE(prAdapter, WPA_IE(pucIE), &prBssDesc->rWPAInfo))) { |
| prBssDesc->fgIEWPA = TRUE; |
| } |
| } |
| #if CFG_ENABLE_WIFI_DIRECT |
| if (prAdapter->fgIsP2PRegistered) { |
| if ((p2pFuncParseCheckForP2PInfoElem(prAdapter, pucIE, &ucOuiType)) |
| && (ucOuiType == VENDOR_OUI_TYPE_P2P)) { |
| prBssDesc->fgIsP2PPresent = TRUE; |
| } |
| } |
| #endif /* CFG_ENABLE_WIFI_DIRECT */ |
| } |
| break; |
| |
| /* no default */ |
| } |
| } |
| |
| /* 4 <3.2> Save information from IEs - SSID */ |
| /* Update Flag of Hidden SSID for used in SEARCH STATE. */ |
| |
| /* NOTE(Kevin): in current driver, the ucSSIDLen == 0 represent |
| * all cases of hidden SSID. |
| * If the fgIsHiddenSSID == TRUE, it means we didn't get the ProbeResp with |
| * valid SSID. |
| */ |
| if (prBssDesc->ucSSIDLen == 0) |
| prBssDesc->fgIsHiddenSSID = TRUE; |
| else |
| prBssDesc->fgIsHiddenSSID = FALSE; |
| |
| /* 4 <3.3> Check rate information in related IEs. */ |
| if (prIeSupportedRate || prIeExtSupportedRate) { |
| rateGetRateSetFromIEs(prIeSupportedRate, |
| prIeExtSupportedRate, |
| &prBssDesc->u2OperationalRateSet, |
| &prBssDesc->u2BSSBasicRateSet, &prBssDesc->fgIsUnknownBssBasicRate); |
| } |
| |
| /* 4 <4> Update information from HIF RX Header */ |
| { |
| P_HW_MAC_RX_DESC_T prRxStatus; |
| UINT_8 ucRxRCPI; |
| |
| prRxStatus = prSwRfb->prRxStatus; |
| ASSERT(prRxStatus); |
| |
| /* 4 <4.1> Get TSF comparison result */ |
| prBssDesc->fgIsLargerTSF = HAL_RX_STATUS_GET_TCL(prRxStatus); |
| |
| /* 4 <4.2> Get Band information */ |
| prBssDesc->eBand = HAL_RX_STATUS_GET_RF_BAND(prRxStatus); |
| |
| /* 4 <4.2> Get channel and RCPI information */ |
| ucHwChannelNum = HAL_RX_STATUS_GET_CHNL_NUM(prRxStatus); |
| |
| ASSERT(prSwRfb->prRxStatusGroup3); |
| ucRxRCPI = nicRxGetRcpiValueFromRxv(RCPI_MODE_WF0, prSwRfb); |
| if (prBssDesc->eBand == BAND_2G4) { |
| |
| /* Update RCPI if in right channel */ |
| |
| if (ucIeDsChannelNum >= 1 && ucIeDsChannelNum <= 14) { |
| |
| /* Receive Beacon/ProbeResp frame from adjacent channel. */ |
| if ((ucIeDsChannelNum == ucHwChannelNum) || (ucRxRCPI > prBssDesc->ucRCPI)) |
| prBssDesc->ucRCPI = ucRxRCPI; |
| /* trust channel information brought by IE */ |
| prBssDesc->ucChannelNum = ucIeDsChannelNum; |
| } else if (ucIeHtChannelNum >= 1 && ucIeHtChannelNum <= 14) { |
| /* Receive Beacon/ProbeResp frame from adjacent channel. */ |
| if ((ucIeHtChannelNum == ucHwChannelNum) || (ucRxRCPI > prBssDesc->ucRCPI)) |
| prBssDesc->ucRCPI = ucRxRCPI; |
| /* trust channel information brought by IE */ |
| prBssDesc->ucChannelNum = ucIeHtChannelNum; |
| } else { |
| prBssDesc->ucRCPI = ucRxRCPI; |
| |
| prBssDesc->ucChannelNum = ucHwChannelNum; |
| } |
| } |
| /* 5G Band */ |
| else { |
| if (ucIeHtChannelNum >= 1 && ucIeHtChannelNum < 200) { |
| /* Receive Beacon/ProbeResp frame from adjacent channel. */ |
| if ((ucIeHtChannelNum == ucHwChannelNum) || (ucRxRCPI > prBssDesc->ucRCPI)) |
| prBssDesc->ucRCPI = ucRxRCPI; |
| /* trust channel information brought by IE */ |
| prBssDesc->ucChannelNum = ucIeHtChannelNum; |
| } else { |
| /* Always update RCPI */ |
| prBssDesc->ucRCPI = ucRxRCPI; |
| |
| prBssDesc->ucChannelNum = ucHwChannelNum; |
| } |
| } |
| } |
| |
| /* 4 <5> Check IE information corret or not */ |
| if (!rlmDomainIsValidRfSetting(prAdapter, prBssDesc->eBand, prBssDesc->ucChannelNum, prBssDesc->eSco, |
| prBssDesc->eChannelWidth, prBssDesc->ucCenterFreqS1, |
| prBssDesc->ucCenterFreqS2)) { |
| /* Dump IE Inforamtion */ |
| /* DBGLOG(RLM, WARN, "ScanAddToBssDesc IE Information\n"); */ |
| /* DBGLOG(RLM, WARN, "IE Length = %d\n", u2IELength); */ |
| /* DBGLOG_MEM8(RLM, WARN, pucDumpIE, u2IELength); */ |
| |
| /* Error Handling for Non-predicted IE - Fixed to set 20MHz */ |
| prBssDesc->eChannelWidth = CW_20_40MHZ; |
| prBssDesc->ucCenterFreqS1 = 0; |
| prBssDesc->ucCenterFreqS2 = 0; |
| prBssDesc->eSco = CHNL_EXT_SCN; |
| } |
| |
| /* 4 <6> PHY type setting */ |
| prBssDesc->ucPhyTypeSet = 0; |
| |
| if (prBssDesc->eBand == BAND_2G4) { |
| /* check if support 11n */ |
| if (prBssDesc->fgIsHTPresent) |
| prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_HT; |
| |
| /* if not 11n only */ |
| if (!(prBssDesc->u2BSSBasicRateSet & RATE_SET_BIT_HT_PHY)) { |
| /* check if support 11g */ |
| if ((prBssDesc->u2OperationalRateSet & RATE_SET_OFDM) || prBssDesc->fgIsERPPresent) |
| prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_ERP; |
| |
| /* if not 11g only */ |
| if (!(prBssDesc->u2BSSBasicRateSet & RATE_SET_OFDM)) { |
| /* check if support 11b */ |
| if ((prBssDesc->u2OperationalRateSet & RATE_SET_HR_DSSS)) |
| prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_HR_DSSS; |
| } |
| } |
| } else { /* (BAND_5G == prBssDesc->eBande) */ |
| /* check if support 11n */ |
| if (prBssDesc->fgIsVHTPresent) |
| prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_VHT; |
| |
| if (prBssDesc->fgIsHTPresent) |
| prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_HT; |
| |
| /* if not 11n only */ |
| if (!(prBssDesc->u2BSSBasicRateSet & RATE_SET_BIT_HT_PHY)) { |
| /* Support 11a definitely */ |
| prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_OFDM; |
| |
| /* ASSERT(!(prBssDesc->u2OperationalRateSet & RATE_SET_HR_DSSS)); */ |
| } |
| } |
| |
| /* 4 <7> Update BSS_DESC_T's Last Update TimeStamp. */ |
| GET_CURRENT_SYSTIME(&prBssDesc->rUpdateTime); |
| |
| return prBssDesc; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Convert the Beacon or ProbeResp Frame in SW_RFB_T to scan result for query |
| * |
| * @param[in] prSwRfb Pointer to the receiving SW_RFB_T structure. |
| * |
| * @retval WLAN_STATUS_SUCCESS It is a valid Scan Result and been sent to the host. |
| * @retval WLAN_STATUS_FAILURE It is not a valid Scan Result. |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS scanAddScanResult(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc, IN P_SW_RFB_T prSwRfb) |
| { |
| P_SCAN_INFO_T prScanInfo; |
| UINT_8 aucRatesEx[PARAM_MAX_LEN_RATES_EX]; |
| P_WLAN_BEACON_FRAME_T prWlanBeaconFrame; |
| PARAM_MAC_ADDRESS rMacAddr; |
| PARAM_SSID_T rSsid; |
| ENUM_PARAM_NETWORK_TYPE_T eNetworkType; |
| PARAM_802_11_CONFIG_T rConfiguration; |
| ENUM_PARAM_OP_MODE_T eOpMode; |
| UINT_8 ucRateLen = 0; |
| UINT_32 i; |
| |
| ASSERT(prAdapter); |
| ASSERT(prSwRfb); |
| |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| |
| if (prBssDesc->eBand == BAND_2G4) { |
| if ((prBssDesc->u2OperationalRateSet & RATE_SET_OFDM) |
| || prBssDesc->fgIsERPPresent) { |
| eNetworkType = PARAM_NETWORK_TYPE_OFDM24; |
| } else { |
| eNetworkType = PARAM_NETWORK_TYPE_DS; |
| } |
| } else { |
| ASSERT(prBssDesc->eBand == BAND_5G); |
| eNetworkType = PARAM_NETWORK_TYPE_OFDM5; |
| } |
| |
| if (prBssDesc->eBSSType == BSS_TYPE_P2P_DEVICE) { |
| /* NOTE(Kevin): Not supported by WZC(TBD) */ |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T) prSwRfb->pvHeader; |
| COPY_MAC_ADDR(rMacAddr, prWlanBeaconFrame->aucBSSID); |
| COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); |
| |
| rConfiguration.u4Length = sizeof(PARAM_802_11_CONFIG_T); |
| rConfiguration.u4BeaconPeriod = (UINT_32) prWlanBeaconFrame->u2BeaconInterval; |
| rConfiguration.u4ATIMWindow = prBssDesc->u2ATIMWindow; |
| rConfiguration.u4DSConfig = nicChannelNum2Freq(prBssDesc->ucChannelNum); |
| rConfiguration.rFHConfig.u4Length = sizeof(PARAM_802_11_CONFIG_FH_T); |
| |
| rateGetDataRatesFromRateSet(prBssDesc->u2OperationalRateSet, 0, aucRatesEx, &ucRateLen); |
| |
| /* NOTE(Kevin): Set unused entries, if any, at the end of the array to 0. |
| * from OID_802_11_BSSID_LIST |
| */ |
| for (i = ucRateLen; i < ARRAY_SIZE(aucRatesEx); i++) |
| aucRatesEx[i] = 0; |
| |
| switch (prBssDesc->eBSSType) { |
| case BSS_TYPE_IBSS: |
| eOpMode = NET_TYPE_IBSS; |
| break; |
| |
| case BSS_TYPE_INFRASTRUCTURE: |
| case BSS_TYPE_P2P_DEVICE: |
| case BSS_TYPE_BOW_DEVICE: |
| default: |
| eOpMode = NET_TYPE_INFRA; |
| break; |
| } |
| |
| DBGLOG(SCN, TRACE, "ind %s %d %d\n", prBssDesc->aucSSID, prBssDesc->ucChannelNum, prBssDesc->ucRCPI); |
| |
| kalIndicateBssInfo(prAdapter->prGlueInfo, |
| (PUINT_8) prSwRfb->pvHeader, |
| prSwRfb->u2PacketLen, prBssDesc->ucChannelNum, RCPI_TO_dBm(prBssDesc->ucRCPI)); |
| |
| nicAddScanResult(prAdapter, |
| rMacAddr, |
| &rSsid, |
| prWlanBeaconFrame->u2CapInfo & CAP_INFO_PRIVACY ? 1 : 0, |
| RCPI_TO_dBm(prBssDesc->ucRCPI), |
| eNetworkType, |
| &rConfiguration, |
| eOpMode, |
| aucRatesEx, |
| prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen, |
| (PUINT_8) ((ULONG) (prSwRfb->pvHeader) + WLAN_MAC_MGMT_HEADER_LEN)); |
| |
| return WLAN_STATUS_SUCCESS; |
| |
| } /* end of scanAddScanResult() */ |
| |
| BOOLEAN scanCheckBssIsLegal(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc) |
| { |
| BOOLEAN fgAddToScanResult = FALSE; |
| ENUM_BAND_T eBand; |
| UINT_8 ucChannel; |
| |
| ASSERT(prAdapter); |
| /* check the channel is in the legal doamin */ |
| if (rlmDomainIsLegalChannel(prAdapter, prBssDesc->eBand, prBssDesc->ucChannelNum) == TRUE) { |
| /* check ucChannelNum/eBand for adjacement channel filtering */ |
| if (cnmAisInfraChannelFixed(prAdapter, &eBand, &ucChannel) == TRUE && |
| (eBand != prBssDesc->eBand || ucChannel != prBssDesc->ucChannelNum)) { |
| fgAddToScanResult = FALSE; |
| } else { |
| fgAddToScanResult = TRUE; |
| } |
| } |
| |
| return fgAddToScanResult; |
| |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Parse the content of given Beacon or ProbeResp Frame. |
| * |
| * @param[in] prSwRfb Pointer to the receiving SW_RFB_T structure. |
| * |
| * @retval WLAN_STATUS_SUCCESS if not report this SW_RFB_T to host |
| * @retval WLAN_STATUS_PENDING if report this SW_RFB_T to host as scan result |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS scanProcessBeaconAndProbeResp(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) |
| { |
| P_SCAN_INFO_T prScanInfo; |
| P_CONNECTION_SETTINGS_T prConnSettings; |
| P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; |
| WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; |
| P_BSS_INFO_T prAisBssInfo; |
| P_WLAN_BEACON_FRAME_T prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T) NULL; |
| #if CFG_SLT_SUPPORT |
| P_SLT_INFO_T prSltInfo = (P_SLT_INFO_T) NULL; |
| #endif |
| |
| ASSERT(prAdapter); |
| ASSERT(prSwRfb); |
| |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| |
| /* 4 <0> Ignore invalid Beacon Frame */ |
| if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < |
| (TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN)) { |
| #ifndef _lint |
| ASSERT(0); |
| #endif /* _lint */ |
| return rStatus; |
| } |
| #if CFG_SLT_SUPPORT |
| prSltInfo = &prAdapter->rWifiVar.rSltInfo; |
| |
| if (prSltInfo->fgIsDUT) { |
| DBGLOG(P2P, INFO, "\n\rBCN: RX\n"); |
| prSltInfo->u4BeaconReceiveCnt++; |
| return WLAN_STATUS_SUCCESS; |
| } else { |
| return WLAN_STATUS_SUCCESS; |
| } |
| #endif |
| |
| prConnSettings = &(prAdapter->rWifiVar.rConnSettings); |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T) prSwRfb->pvHeader; |
| |
| /* 4 <1> Parse and add into BSS_DESC_T */ |
| prBssDesc = scanAddToBssDesc(prAdapter, prSwRfb); |
| |
| if (prBssDesc) { |
| #if CFG_SUPPORT_BEACON_CHANGE_DETECTION |
| /* 4 <1.1> Beacon Change Detection for Connected BSS */ |
| if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED && |
| ((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE && prConnSettings->eOPMode != NET_TYPE_IBSS) |
| || (prBssDesc->eBSSType == BSS_TYPE_IBSS && prConnSettings->eOPMode != NET_TYPE_INFRA)) |
| && EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID) |
| && EQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, prAisBssInfo->aucSSID, |
| prAisBssInfo->ucSSIDLen)) { |
| BOOLEAN fgNeedDisconnect = FALSE; |
| |
| /* <1.1.2> check if supported rate differs */ |
| if (prAisBssInfo->u2OperationalRateSet != prBssDesc->u2OperationalRateSet) |
| fgNeedDisconnect = TRUE; |
| |
| /* <1.1.3> beacon content change detected, disconnect immediately */ |
| if (fgNeedDisconnect == TRUE) |
| aisBssBeaconTimeout(prAdapter); |
| } |
| #endif |
| /* 4 <1.1> Update AIS_BSS_INFO */ |
| if (((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE && prConnSettings->eOPMode != NET_TYPE_IBSS) |
| || (prBssDesc->eBSSType == BSS_TYPE_IBSS && prConnSettings->eOPMode != NET_TYPE_INFRA))) { |
| if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { |
| |
| /* *not* checking prBssDesc->fgIsConnected anymore, |
| * due to Linksys AP uses " " as hidden SSID, and would have different BSS descriptor |
| */ |
| if ((!prAisBssInfo->ucDTIMPeriod) && |
| EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID) && |
| (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) && |
| ((prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_BEACON)) { |
| |
| prAisBssInfo->ucDTIMPeriod = prBssDesc->ucDTIMPeriod; |
| |
| /* sync with firmware for beacon information */ |
| nicPmIndicateBssConnected(prAdapter, prAisBssInfo->ucBssIndex); |
| } |
| } |
| #if CFG_SUPPORT_ADHOC |
| if (EQUAL_SSID(prBssDesc->aucSSID, |
| prBssDesc->ucSSIDLen, |
| prConnSettings->aucSSID, |
| prConnSettings->ucSSIDLen) && |
| (prBssDesc->eBSSType == BSS_TYPE_IBSS) && (prAisBssInfo->eCurrentOPMode == OP_MODE_IBSS)) { |
| |
| ASSERT(prSwRfb->prRxStatusGroup3); |
| |
| ibssProcessMatchedBeacon(prAdapter, prAisBssInfo, prBssDesc, |
| nicRxGetRcpiValueFromRxv(RCPI_MODE_WF0, prSwRfb)); |
| } |
| #endif /* CFG_SUPPORT_ADHOC */ |
| } |
| |
| rlmProcessBcn(prAdapter, |
| prSwRfb, |
| ((P_WLAN_BEACON_FRAME_T) (prSwRfb->pvHeader))->aucInfoElem, |
| (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - |
| (UINT_16) (OFFSET_OF(WLAN_BEACON_FRAME_BODY_T, aucInfoElem[0]))); |
| |
| mqmProcessBcn(prAdapter, |
| prSwRfb, |
| ((P_WLAN_BEACON_FRAME_T) (prSwRfb->pvHeader))->aucInfoElem, |
| (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - |
| (UINT_16) (OFFSET_OF(WLAN_BEACON_FRAME_BODY_T, aucInfoElem[0]))); |
| |
| /* 4 <3> Send SW_RFB_T to HIF when we perform SCAN for HOST */ |
| if (prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE || prBssDesc->eBSSType == BSS_TYPE_IBSS) { |
| /* for AIS, send to host */ |
| if (prConnSettings->fgIsScanReqIssued) { |
| BOOLEAN fgAddToScanResult; |
| |
| fgAddToScanResult = scanCheckBssIsLegal(prAdapter, prBssDesc); |
| |
| if (fgAddToScanResult == TRUE) |
| rStatus = scanAddScanResult(prAdapter, prBssDesc, prSwRfb); |
| } |
| } |
| #if CFG_ENABLE_WIFI_DIRECT |
| if (prAdapter->fgIsP2PRegistered) |
| scanP2pProcessBeaconAndProbeResp(prAdapter, prSwRfb, &rStatus, prBssDesc, prWlanBeaconFrame); |
| #endif |
| } |
| |
| return rStatus; |
| |
| } /* end of scanProcessBeaconAndProbeResp() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief Search the Candidate of BSS Descriptor for JOIN(Infrastructure) or |
| * MERGE(AdHoc) according to current Connection Policy. |
| * |
| * \return Pointer to BSS Descriptor, if found. NULL, if not found |
| */ |
| /*----------------------------------------------------------------------------*/ |
| P_BSS_DESC_T scanSearchBssDescByPolicy(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex) |
| { |
| P_CONNECTION_SETTINGS_T prConnSettings; |
| P_BSS_INFO_T prBssInfo; |
| P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; |
| P_SCAN_INFO_T prScanInfo; |
| |
| P_LINK_T prBSSDescList; |
| |
| P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; |
| P_BSS_DESC_T prPrimaryBssDesc = (P_BSS_DESC_T) NULL; |
| P_BSS_DESC_T prCandidateBssDesc = (P_BSS_DESC_T) NULL; |
| |
| P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; |
| P_STA_RECORD_T prPrimaryStaRec; |
| P_STA_RECORD_T prCandidateStaRec = (P_STA_RECORD_T) NULL; |
| |
| OS_SYSTIME rCurrentTime; |
| |
| /* The first one reach the check point will be our candidate */ |
| BOOLEAN fgIsFindFirst = (BOOLEAN) FALSE; |
| |
| BOOLEAN fgIsFindBestRSSI = (BOOLEAN) FALSE; |
| BOOLEAN fgIsFindBestEncryptionLevel = (BOOLEAN) FALSE; |
| /* BOOLEAN fgIsFindMinChannelLoad = (BOOLEAN)FALSE; */ |
| |
| /* TODO(Kevin): Support Min Channel Load */ |
| /* UINT_8 aucChannelLoad[CHANNEL_NUM] = {0}; */ |
| |
| BOOLEAN fgIsFixedChannel; |
| ENUM_BAND_T eBand; |
| UINT_8 ucChannel; |
| |
| ASSERT(prAdapter); |
| |
| prConnSettings = &(prAdapter->rWifiVar.rConnSettings); |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); |
| |
| prAisSpecBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); |
| |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| prBSSDescList = &prScanInfo->rBSSDescList; |
| |
| GET_CURRENT_SYSTIME(&rCurrentTime); |
| |
| /* check for fixed channel operation */ |
| if (prBssInfo->eNetworkType == NETWORK_TYPE_AIS) { |
| #if CFG_SUPPORT_CHNL_CONFLICT_REVISE |
| fgIsFixedChannel = cnmAisDetectP2PChannel(prAdapter, &eBand, &ucChannel); |
| #else |
| fgIsFixedChannel = cnmAisInfraChannelFixed(prAdapter, &eBand, &ucChannel); |
| #endif |
| } else |
| fgIsFixedChannel = FALSE; |
| |
| #if DBG |
| if (prConnSettings->ucSSIDLen < ELEM_MAX_LEN_SSID) |
| prConnSettings->aucSSID[prConnSettings->ucSSIDLen] = '\0'; |
| #endif |
| |
| #if 0 |
| DBGLOG(SCN, INFO, "SEARCH: Num Of BSS_DESC_T = %d, Look for SSID: %s\n", |
| prBSSDescList->u4NumElem, prConnSettings->aucSSID); |
| #endif |
| |
| /* 4 <1> The outer loop to search for a candidate. */ |
| LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { |
| |
| /* TODO(Kevin): Update Minimum Channel Load Information here */ |
| |
| #if 0 |
| DBGLOG(SCN, INFO, "SEARCH: [" MACSTR "], SSID:%s\n", MAC2STR(prBssDesc->aucBSSID), prBssDesc->aucSSID); |
| #endif |
| |
| /* 4 <2> Check PHY Type and attributes */ |
| /* 4 <2.1> Check Unsupported BSS PHY Type */ |
| if (!(prBssDesc->ucPhyTypeSet & (prAdapter->rWifiVar.ucAvailablePhyTypeSet))) { |
| |
| DBGLOG(SCN, INFO, "SEARCH: Ignore unsupported ucPhyTypeSet = %x\n", prBssDesc->ucPhyTypeSet); |
| continue; |
| } |
| /* 4 <2.2> Check if has unknown NonHT BSS Basic Rate Set. */ |
| if (prBssDesc->fgIsUnknownBssBasicRate) { |
| DBGLOG(SCN, LOUD, "SEARCH: Ignore Unknown Bss Basic Rate\n"); |
| continue; |
| } |
| /* 4 <2.3> Check if fixed operation cases should be aware */ |
| if (fgIsFixedChannel == TRUE && (prBssDesc->eBand != eBand || prBssDesc->ucChannelNum != ucChannel)) { |
| DBGLOG(SCN, LOUD, |
| "SEARCH: Ignore BssBand[%d] != FixBand[%d] or BssCH[%d] != FixCH[%d]\n", |
| prBssDesc->eBand, eBand, prBssDesc->ucChannelNum, ucChannel); |
| continue; |
| } |
| /* 4 <2.4> Check if the channel is legal under regulatory domain */ |
| if (rlmDomainIsLegalChannel(prAdapter, prBssDesc->eBand, prBssDesc->ucChannelNum) == FALSE) { |
| DBGLOG(SCN, LOUD, "SEARCH: Ignore illegal CH Band[%d] CH[%d]\n", |
| prBssDesc->eBand, prBssDesc->ucChannelNum); |
| continue; |
| } |
| /* 4 <2.5> Check if this BSS_DESC_T is stale */ |
| if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, SEC_TO_SYSTIME(SCN_BSS_DESC_STALE_SEC))) { |
| DBGLOG(SCN, LOUD, "SEARCH: Ignore stale Bss, CurrTime[%ld] BssUpdateTime[%ld]\n", |
| rCurrentTime, prBssDesc->rUpdateTime); |
| continue; |
| } |
| /* 4 <3> Check if reach the excessive join retry limit */ |
| /* NOTE(Kevin): STA_RECORD_T is recorded by TA. */ |
| prStaRec = cnmGetStaRecByAddress(prAdapter, ucBssIndex, prBssDesc->aucSrcAddr); |
| |
| if (prStaRec) { |
| /* NOTE(Kevin): |
| * The Status Code is the result of a Previous Connection Request, |
| * we use this as SCORE for choosing a proper |
| * candidate (Also used for compare see <6>) |
| * The Reason Code is an indication of the reason why AP reject us, |
| * we use this Code for "Reject" |
| * a SCAN result to become our candidate(Like a blacklist). |
| */ |
| #if 0 /* TODO(Kevin): */ |
| if (prStaRec->u2ReasonCode != REASON_CODE_RESERVED) { |
| DBGLOG(SCN, INFO, |
| "SEARCH: Ignore BSS with previous Reason Code = %d\n", prStaRec->u2ReasonCode); |
| continue; |
| } else |
| #endif |
| if (prStaRec->u2StatusCode != STATUS_CODE_SUCCESSFUL) { |
| /* NOTE(Kevin): greedy association - after timeout, we'll still |
| * try to associate to the AP whose STATUS of conection attempt |
| * was not success. |
| * We may also use (ucJoinFailureCount x JOIN_RETRY_INTERVAL_SEC) for |
| * time bound. |
| */ |
| if ((prStaRec->ucJoinFailureCount < JOIN_MAX_RETRY_FAILURE_COUNT) || |
| (CHECK_FOR_TIMEOUT(rCurrentTime, |
| prStaRec->rLastJoinTime, |
| SEC_TO_SYSTIME(JOIN_RETRY_INTERVAL_SEC)))) { |
| |
| /* NOTE(Kevin): Every JOIN_RETRY_INTERVAL_SEC interval, we can retry |
| * JOIN_MAX_RETRY_FAILURE_COUNT times. |
| */ |
| if (prStaRec->ucJoinFailureCount >= JOIN_MAX_RETRY_FAILURE_COUNT) |
| prStaRec->ucJoinFailureCount = 0; |
| DBGLOG(SCN, INFO, |
| "SEARCH:Try to join BSS again,Status Code=%d(Curr=%ld/Last Join=%ld)\n", |
| prStaRec->u2StatusCode, rCurrentTime, prStaRec->rLastJoinTime); |
| } else { |
| DBGLOG(SCN, INFO, |
| "SEARCH: Ignore BSS which reach maximum Join Retry Count = %d\n", |
| JOIN_MAX_RETRY_FAILURE_COUNT); |
| continue; |
| } |
| |
| } |
| } |
| |
| /* 4 <4> Check for various NETWORK conditions */ |
| if (prBssInfo->eNetworkType == NETWORK_TYPE_AIS) { |
| |
| /* 4 <4.1> Check BSS Type for the corresponding Operation Mode in Connection Setting */ |
| /* NOTE(Kevin): For NET_TYPE_AUTO_SWITCH, we will always pass following check. */ |
| if (((prConnSettings->eOPMode == NET_TYPE_INFRA) && |
| (prBssDesc->eBSSType != BSS_TYPE_INFRASTRUCTURE)) || |
| ((prConnSettings->eOPMode == NET_TYPE_IBSS |
| || prConnSettings->eOPMode == NET_TYPE_DEDICATED_IBSS) |
| && (prBssDesc->eBSSType != BSS_TYPE_IBSS))) { |
| |
| DBGLOG(SCN, INFO, "SEARCH: Ignore eBSSType = %s\n", |
| ((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) ? "INFRASTRUCTURE" : "IBSS")); |
| continue; |
| } |
| /* 4 <4.2> Check AP's BSSID if OID_802_11_BSSID has been set. */ |
| if ((prConnSettings->fgIsConnByBssidIssued) && |
| (prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE)) { |
| if (UNEQUAL_MAC_ADDR(prConnSettings->aucBSSID, prBssDesc->aucBSSID)) { |
| DBGLOG(SCN, INFO, "SEARCH: Ignore due to BSSID was not matched!\n"); |
| continue; |
| } |
| } |
| #if CFG_SUPPORT_ADHOC |
| /* 4 <4.3> Check for AdHoc Mode */ |
| if (prBssDesc->eBSSType == BSS_TYPE_IBSS) { |
| OS_SYSTIME rCurrentTime; |
| |
| /* 4 <4.3.1> Check if this SCAN record has been updated recently for IBSS. */ |
| /* NOTE(Kevin): Because some STA may change its BSSID frequently after it |
| * create the IBSS - e.g. IPN2220, so we need to make sure we get the new one. |
| * For BSS, if the old record was matched, however it won't be able to pass |
| * the Join Process later. |
| */ |
| GET_CURRENT_SYSTIME(&rCurrentTime); |
| if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, |
| SEC_TO_SYSTIME(SCN_ADHOC_BSS_DESC_TIMEOUT_SEC))) { |
| DBGLOG(SCN, LOUD, |
| "SEARCH: Skip old record of BSS Descriptor - BSSID:[" |
| MACSTR "]\n\n", MAC2STR(prBssDesc->aucBSSID)); |
| continue; |
| } |
| /* 4 <4.3.2> Check Peer's capability */ |
| if (ibssCheckCapabilityForAdHocMode(prAdapter, prBssDesc) == WLAN_STATUS_FAILURE) { |
| |
| DBGLOG(SCN, INFO, |
| "SEARCH: Ignore BSS DESC MAC: " MACSTR |
| ", Capability is not supported for current AdHoc Mode.\n", |
| MAC2STR(prPrimaryBssDesc->aucBSSID)); |
| |
| continue; |
| } |
| |
| /* 4 <4.3.3> Compare TSF */ |
| if (prBssInfo->fgIsBeaconActivated && |
| UNEQUAL_MAC_ADDR(prBssInfo->aucBSSID, prBssDesc->aucBSSID)) { |
| |
| DBGLOG(SCN, LOUD, |
| "SEARCH: prBssDesc->fgIsLargerTSF = %d\n", prBssDesc->fgIsLargerTSF); |
| |
| if (!prBssDesc->fgIsLargerTSF) { |
| DBGLOG(SCN, INFO, |
| "SEARCH: Ignore BSS DESC MAC: [" MACSTR |
| "], Smaller TSF\n", MAC2STR(prBssDesc->aucBSSID)); |
| continue; |
| } |
| } |
| } |
| #endif /* CFG_SUPPORT_ADHOC */ |
| |
| } |
| #if 0 /* TODO(Kevin): For IBSS */ |
| /* 4 <2.c> Check if this SCAN record has been updated recently for IBSS. */ |
| /* NOTE(Kevin): Because some STA may change its BSSID frequently after it |
| * create the IBSS, so we need to make sure we get the new one. |
| * For BSS, if the old record was matched, however it won't be able to pass |
| * the Join Process later. |
| */ |
| if (prBssDesc->eBSSType == BSS_TYPE_IBSS) { |
| OS_SYSTIME rCurrentTime; |
| |
| GET_CURRENT_SYSTIME(&rCurrentTime); |
| if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, |
| SEC_TO_SYSTIME(BSS_DESC_TIMEOUT_SEC))) { |
| DBGLOG(SCAN, TRACE, |
| "Skip old record of BSS Descriptor - BSSID:[" MACSTR |
| "]\n\n", MAC2STR(prBssDesc->aucBSSID)); |
| continue; |
| } |
| } |
| |
| if ((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) && |
| (prAdapter->eConnectionState == MEDIA_STATE_CONNECTED)) { |
| OS_SYSTIME rCurrentTime; |
| |
| GET_CURRENT_SYSTIME(&rCurrentTime); |
| if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, |
| SEC_TO_SYSTIME(BSS_DESC_TIMEOUT_SEC))) { |
| DBGLOG(SCAN, TRACE, |
| "Skip old record of BSS Descriptor - BSSID:[" MACSTR |
| "]\n\n", MAC2STR(prBssDesc->aucBSSID)); |
| continue; |
| } |
| } |
| |
| /* 4 <4B> Check for IBSS AdHoc Mode. */ |
| /* Skip if one or more BSS Basic Rate are not supported by current AdHocMode */ |
| if (prPrimaryBssDesc->eBSSType == BSS_TYPE_IBSS) { |
| /* 4 <4B.1> Check if match the Capability of current IBSS AdHoc Mode. */ |
| if (ibssCheckCapabilityForAdHocMode(prAdapter, prPrimaryBssDesc) == WLAN_STATUS_FAILURE) { |
| |
| DBGLOG(SCAN, TRACE, |
| "Ignore BSS DESC MAC: " MACSTR |
| ", Capability is not supported for current AdHoc Mode.\n", |
| MAC2STR(prPrimaryBssDesc->aucBSSID)); |
| |
| continue; |
| } |
| |
| /* 4 <4B.2> IBSS Merge Decision Flow for SEARCH STATE. */ |
| if (prAdapter->fgIsIBSSActive && |
| UNEQUAL_MAC_ADDR(prBssInfo->aucBSSID, prPrimaryBssDesc->aucBSSID)) { |
| |
| if (!fgIsLocalTSFRead) { |
| NIC_GET_CURRENT_TSF(prAdapter, &rCurrentTsf); |
| |
| DBGLOG(SCAN, TRACE, |
| "\n\nCurrent TSF : %08lx-%08lx\n\n", |
| rCurrentTsf.u.HighPart, rCurrentTsf.u.LowPart); |
| } |
| |
| if (rCurrentTsf.QuadPart > prPrimaryBssDesc->u8TimeStamp.QuadPart) { |
| DBGLOG(SCAN, TRACE, |
| "Ignore BSS DESC MAC: [" MACSTR |
| "], Current BSSID: [" MACSTR "].\n", |
| MAC2STR(prPrimaryBssDesc->aucBSSID), MAC2STR(prBssInfo->aucBSSID)); |
| |
| DBGLOG(SCAN, TRACE, |
| "\n\nBSS's TSF : %08lx-%08lx\n\n", |
| prPrimaryBssDesc->u8TimeStamp.u.HighPart, |
| prPrimaryBssDesc->u8TimeStamp.u.LowPart); |
| |
| prPrimaryBssDesc->fgIsLargerTSF = FALSE; |
| continue; |
| } else { |
| prPrimaryBssDesc->fgIsLargerTSF = TRUE; |
| } |
| |
| } |
| } |
| /* 4 <5> Check the Encryption Status. */ |
| if (rsnPerformPolicySelection(prPrimaryBssDesc)) { |
| |
| if (prPrimaryBssDesc->ucEncLevel > 0) { |
| fgIsFindBestEncryptionLevel = TRUE; |
| |
| fgIsFindFirst = FALSE; |
| } |
| } else { |
| /* Can't pass the Encryption Status Check, get next one */ |
| continue; |
| } |
| |
| /* For RSN Pre-authentication, update the PMKID canidate list for |
| * same SSID and encrypt status |
| */ |
| /* Update PMKID candicate list. */ |
| if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2) { |
| rsnUpdatePmkidCandidateList(prPrimaryBssDesc); |
| if (prAdapter->rWifiVar.rAisBssInfo.u4PmkidCandicateCount) |
| prAdapter->rWifiVar.rAisBssInfo.fgIndicatePMKID = rsnCheckPmkidCandicate(); |
| } |
| #endif |
| |
| prPrimaryBssDesc = (P_BSS_DESC_T) NULL; |
| |
| /* 4 <6> Check current Connection Policy. */ |
| switch (prConnSettings->eConnectionPolicy) { |
| case CONNECT_BY_SSID_BEST_RSSI: |
| /* Choose Hidden SSID to join only if the `fgIsEnableJoin...` is TRUE */ |
| if (prAdapter->rWifiVar.fgEnableJoinToHiddenSSID && prBssDesc->fgIsHiddenSSID) { |
| /* NOTE(Kevin): following if () statement means that |
| * If Target is hidden, then we won't connect when user specify SSID_ANY policy. |
| */ |
| if (prConnSettings->ucSSIDLen) { |
| prPrimaryBssDesc = prBssDesc; |
| |
| fgIsFindBestRSSI = TRUE; |
| } |
| |
| } else if (EQUAL_SSID(prBssDesc->aucSSID, |
| prBssDesc->ucSSIDLen, |
| prConnSettings->aucSSID, prConnSettings->ucSSIDLen)) { |
| prPrimaryBssDesc = prBssDesc; |
| |
| fgIsFindBestRSSI = TRUE; |
| DBGLOG(SCN, LOUD, "SEARCH: Found BSS by SSID, [" MACSTR "], SSID:%s\n", |
| MAC2STR(prBssDesc->aucBSSID), prBssDesc->aucSSID); |
| } |
| break; |
| |
| case CONNECT_BY_SSID_ANY: |
| /* NOTE(Kevin): In this policy, we don't know the desired |
| * SSID from user, so we should exclude the Hidden SSID from scan list. |
| * And because we refuse to connect to Hidden SSID node at the beginning, so |
| * when the JOIN Module deal with a BSS_DESC_T which has fgIsHiddenSSID == TRUE, |
| * then the Connection Settings must be valid without doubt. |
| */ |
| if (!prBssDesc->fgIsHiddenSSID) { |
| prPrimaryBssDesc = prBssDesc; |
| |
| fgIsFindFirst = TRUE; |
| } |
| break; |
| |
| case CONNECT_BY_BSSID: |
| if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prConnSettings->aucBSSID)) { |
| /* Make sure to match with SSID if supplied. |
| * Some dual band APs share a single BSSID among different BSSes. |
| */ |
| if ((prBssDesc->ucSSIDLen > 0 && prConnSettings->ucSSIDLen > 0 && |
| EQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, |
| prConnSettings->aucSSID, prConnSettings->ucSSIDLen)) || |
| prConnSettings->ucSSIDLen == 0) |
| prPrimaryBssDesc = prBssDesc; |
| } |
| break; |
| |
| default: |
| break; |
| } |
| |
| /* Primary Candidate was not found */ |
| if (prPrimaryBssDesc == NULL) |
| continue; |
| /* 4 <7> Check the Encryption Status. */ |
| if (prPrimaryBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) { |
| #if CFG_SUPPORT_WAPI |
| if (prAdapter->rWifiVar.rConnSettings.fgWapiMode) { |
| if (wapiPerformPolicySelection(prAdapter, prPrimaryBssDesc)) { |
| fgIsFindFirst = TRUE; |
| } else { |
| /* Can't pass the Encryption Status Check, get next one */ |
| DBGLOG(RSN, INFO, "Ignore BSS can't pass WAPI policy selection\n"); |
| continue; |
| } |
| } else |
| #endif |
| if (rsnPerformPolicySelection(prAdapter, prPrimaryBssDesc)) { |
| if (prAisSpecBssInfo->fgCounterMeasure) { |
| DBGLOG(RSN, INFO, "Skip while at counter measure period!!!\n"); |
| continue; |
| } |
| |
| if (prPrimaryBssDesc->ucEncLevel > 0) { |
| fgIsFindBestEncryptionLevel = TRUE; |
| |
| fgIsFindFirst = FALSE; |
| } |
| } else { |
| /* Can't pass the Encryption Status Check, get next one */ |
| DBGLOG(RSN, INFO, "Ignore BSS can't pass Encryption Status Check\n"); |
| continue; |
| } |
| } else { |
| /* Todo:: P2P and BOW Policy Selection */ |
| } |
| |
| prPrimaryStaRec = prStaRec; |
| |
| /* 4 <8> Compare the Candidate and the Primary Scan Record. */ |
| if (!prCandidateBssDesc) { |
| prCandidateBssDesc = prPrimaryBssDesc; |
| prCandidateStaRec = prPrimaryStaRec; |
| |
| /* 4 <8.1> Condition - Get the first matched one. */ |
| if (fgIsFindFirst) |
| break; |
| } else { |
| /* 4 <6D> Condition - Visible SSID win Hidden SSID. */ |
| if (prCandidateBssDesc->fgIsHiddenSSID) { |
| if (!prPrimaryBssDesc->fgIsHiddenSSID) { |
| prCandidateBssDesc = prPrimaryBssDesc; /* The non Hidden SSID win. */ |
| prCandidateStaRec = prPrimaryStaRec; |
| continue; |
| } |
| } else { |
| if (prPrimaryBssDesc->fgIsHiddenSSID) |
| continue; |
| } |
| |
| /* 4 <6E> Condition - Choose the one with better RCPI(RSSI). */ |
| if (fgIsFindBestRSSI) { |
| /* TODO(Kevin): We shouldn't compare the actual value, we should |
| * allow some acceptable tolerance of some RSSI percentage here. |
| */ |
| DBGLOG(SCN, TRACE, |
| "Candidate [" MACSTR "]: RCPI = %d, joinFailCnt=%d, Primary [" MACSTR |
| "]: RCPI = %d, joinFailCnt=%d\n", MAC2STR(prCandidateBssDesc->aucBSSID), |
| prCandidateBssDesc->ucRCPI, prCandidateBssDesc->ucJoinFailureCount, |
| MAC2STR(prPrimaryBssDesc->aucBSSID), prPrimaryBssDesc->ucRCPI, |
| prPrimaryBssDesc->ucJoinFailureCount); |
| |
| ASSERT(!(prCandidateBssDesc->fgIsConnected && prPrimaryBssDesc->fgIsConnected)); |
| if (prPrimaryBssDesc->ucJoinFailureCount > SCN_BSS_JOIN_FAIL_THRESOLD) { |
| /* give a chance to do join if join fail before |
| * SCN_BSS_DECRASE_JOIN_FAIL_CNT_SEC seconds |
| */ |
| if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rJoinFailTime, |
| SEC_TO_SYSTIME(SCN_BSS_JOIN_FAIL_CNT_RESET_SEC))) { |
| prBssDesc->ucJoinFailureCount -= SCN_BSS_JOIN_FAIL_RESET_STEP; |
| DBGLOG(AIS, INFO, |
| "decrease join fail count for Bss " MACSTR |
| " to %u, timeout second %d\n", MAC2STR(prBssDesc->aucBSSID), |
| prBssDesc->ucJoinFailureCount, SCN_BSS_JOIN_FAIL_CNT_RESET_SEC); |
| } |
| } |
| /* NOTE: To prevent SWING, we do roaming only if target AP |
| * has at least 5dBm larger than us. |
| */ |
| if (prCandidateBssDesc->fgIsConnected) { |
| if ((prCandidateBssDesc->ucRCPI + ROAMING_NO_SWING_RCPI_STEP <= |
| prPrimaryBssDesc->ucRCPI) |
| && prPrimaryBssDesc->ucJoinFailureCount <= SCN_BSS_JOIN_FAIL_THRESOLD) { |
| |
| prCandidateBssDesc = prPrimaryBssDesc; |
| prCandidateStaRec = prPrimaryStaRec; |
| continue; |
| } |
| } else if (prPrimaryBssDesc->fgIsConnected) { |
| if ((prCandidateBssDesc->ucRCPI < |
| prPrimaryBssDesc->ucRCPI + ROAMING_NO_SWING_RCPI_STEP) |
| || (prCandidateBssDesc->ucJoinFailureCount > SCN_BSS_JOIN_FAIL_THRESOLD)) { |
| |
| prCandidateBssDesc = prPrimaryBssDesc; |
| prCandidateStaRec = prPrimaryStaRec; |
| continue; |
| } |
| } else if (prPrimaryBssDesc->ucJoinFailureCount > SCN_BSS_JOIN_FAIL_THRESOLD) |
| continue; |
| else if (prCandidateBssDesc->ucJoinFailureCount > SCN_BSS_JOIN_FAIL_THRESOLD || |
| prCandidateBssDesc->ucRCPI < prPrimaryBssDesc->ucRCPI) { |
| |
| prCandidateBssDesc = prPrimaryBssDesc; |
| prCandidateStaRec = prPrimaryStaRec; |
| continue; |
| } |
| } |
| #if 0 |
| /* If reach here, that means they have the same Encryption Score, and |
| * both RSSI value are close too. |
| */ |
| /* 4 <6F> Seek the minimum Channel Load for less interference. */ |
| if (fgIsFindMinChannelLoad) { |
| /* ToDo:: Nothing */ |
| /* TODO(Kevin): Check which one has minimum channel load in its channel */ |
| } |
| #endif |
| } |
| } |
| |
| return prCandidateBssDesc; |
| |
| } /* end of scanSearchBssDescByPolicy() */ |
| |
| VOID scanReportBss2Cfg80211(IN P_ADAPTER_T prAdapter, IN ENUM_BSS_TYPE_T eBSSType, IN P_BSS_DESC_T SpecificprBssDesc) |
| { |
| P_SCAN_INFO_T prScanInfo = NULL; |
| P_LINK_T prBSSDescList = NULL; |
| P_BSS_DESC_T prBssDesc = NULL; |
| RF_CHANNEL_INFO_T rChannelInfo; |
| |
| ASSERT(prAdapter); |
| |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| |
| prBSSDescList = &prScanInfo->rBSSDescList; |
| |
| DBGLOG(SCN, TRACE, "scanReportBss2Cfg80211\n"); |
| |
| if (SpecificprBssDesc) { |
| { |
| /* check BSSID is legal channel */ |
| if (!scanCheckBssIsLegal(prAdapter, SpecificprBssDesc)) { |
| DBGLOG(SCN, TRACE, "Remove specific SSID[%s %d]\n", |
| SpecificprBssDesc->aucSSID, SpecificprBssDesc->ucChannelNum); |
| return; |
| } |
| |
| DBGLOG(SCN, TRACE, "Report Specific SSID[%s]\n", SpecificprBssDesc->aucSSID); |
| if (eBSSType == BSS_TYPE_INFRASTRUCTURE) { |
| |
| kalIndicateBssInfo(prAdapter->prGlueInfo, |
| (PUINT_8) SpecificprBssDesc->aucRawBuf, |
| SpecificprBssDesc->u2RawLength, |
| SpecificprBssDesc->ucChannelNum, |
| RCPI_TO_dBm(SpecificprBssDesc->ucRCPI)); |
| } else { |
| |
| rChannelInfo.ucChannelNum = SpecificprBssDesc->ucChannelNum; |
| rChannelInfo.eBand = SpecificprBssDesc->eBand; |
| kalP2PIndicateBssInfo(prAdapter->prGlueInfo, |
| (PUINT_8) SpecificprBssDesc->aucRawBuf, |
| SpecificprBssDesc->u2RawLength, |
| &rChannelInfo, RCPI_TO_dBm(SpecificprBssDesc->ucRCPI)); |
| |
| } |
| |
| #if CFG_ENABLE_WIFI_DIRECT |
| SpecificprBssDesc->fgIsP2PReport = FALSE; |
| #endif |
| } |
| } else { |
| |
| #if CFG_AUTO_CHANNEL_SEL_SUPPORT |
| /* Clear old ACS data (APNum, Dirtiness, ...) and initialize the ch number */ |
| kalMemZero(&(prAdapter->rWifiVar.rChnLoadInfo), |
| sizeof(prAdapter->rWifiVar.rChnLoadInfo)); |
| wlanInitChnLoadInfoChannelList(prAdapter); |
| #endif |
| |
| /* Search BSS Desc from current SCAN result list. */ |
| LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { |
| #if CFG_AUTO_CHANNEL_SEL_SUPPORT |
| /* Record channel loading with channel's AP number */ |
| UINT_8 ucIdx = wlanGetChannelIndex(prBssDesc->ucChannelNum); |
| |
| if (ucIdx < MAX_CHN_NUM) |
| prAdapter->rWifiVar.rChnLoadInfo.rEachChnLoad[ucIdx].u2APNum++; |
| #endif |
| |
| /* check BSSID is legal channel */ |
| if (!scanCheckBssIsLegal(prAdapter, prBssDesc)) { |
| DBGLOG(SCN, TRACE, "Remove SSID[%s %d]\n", prBssDesc->aucSSID, prBssDesc->ucChannelNum); |
| continue; |
| } |
| |
| if ((prBssDesc->eBSSType == eBSSType) |
| #if CFG_ENABLE_WIFI_DIRECT |
| || ((eBSSType == BSS_TYPE_P2P_DEVICE) && |
| (prBssDesc->fgIsP2PReport == TRUE && |
| prAdapter->p2p_scan_report_all_bss)) |
| #endif |
| ) { |
| |
| DBGLOG(SCN, TRACE, "Report ALL SSID[%s %d]\n", |
| prBssDesc->aucSSID, prBssDesc->ucChannelNum); |
| |
| if (eBSSType == BSS_TYPE_INFRASTRUCTURE) { |
| if (prBssDesc->u2RawLength != 0) { |
| kalIndicateBssInfo(prAdapter->prGlueInfo, |
| (PUINT_8) prBssDesc->aucRawBuf, |
| prBssDesc->u2RawLength, |
| prBssDesc->ucChannelNum, |
| RCPI_TO_dBm(prBssDesc->ucRCPI)); |
| kalMemZero(prBssDesc->aucRawBuf, CFG_RAW_BUFFER_SIZE); |
| prBssDesc->u2RawLength = 0; |
| |
| #if CFG_ENABLE_WIFI_DIRECT |
| prBssDesc->fgIsP2PReport = FALSE; |
| #endif |
| } |
| } else { |
| #if CFG_ENABLE_WIFI_DIRECT |
| if ((prBssDesc->fgIsP2PReport == TRUE && |
| prAdapter->p2p_scan_report_all_bss) && |
| prBssDesc->u2RawLength != 0) { |
| #endif |
| rChannelInfo.ucChannelNum = prBssDesc->ucChannelNum; |
| rChannelInfo.eBand = prBssDesc->eBand; |
| |
| kalP2PIndicateBssInfo(prAdapter->prGlueInfo, |
| (PUINT_8) prBssDesc->aucRawBuf, |
| prBssDesc->u2RawLength, |
| &rChannelInfo, RCPI_TO_dBm(prBssDesc->ucRCPI)); |
| |
| /* do not clear it then we can pass the bss in Specific report */ |
| /* kalMemZero(prBssDesc->aucRawBuf,CFG_RAW_BUFFER_SIZE); */ |
| |
| /* |
| * the BSS entry will not be cleared after scan done. |
| * So if we dont receive the BSS in next scan, we cannot |
| * pass it. We use u2RawLength for the purpose. |
| */ |
| /* prBssDesc->u2RawLength=0; */ |
| #if CFG_ENABLE_WIFI_DIRECT |
| prBssDesc->fgIsP2PReport = FALSE; |
| } |
| #endif |
| } |
| } |
| |
| } |
| #if CFG_AUTO_CHANNEL_SEL_SUPPORT |
| wlanCalculateAllChannelDirtiness(prAdapter); |
| wlanSortChannel(prAdapter); |
| |
| prAdapter->rWifiVar.rChnLoadInfo.fgDataReadyBit = TRUE; |
| #endif |
| |
| } |
| |
| } |
| |
| #if CFG_SUPPORT_PASSPOINT |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Find the corresponding BSS Descriptor according to given BSSID |
| * |
| * @param[in] prAdapter Pointer to the Adapter structure. |
| * @param[in] aucBSSID Given BSSID. |
| * @param[in] fgCheckSsid Need to check SSID or not. (for multiple SSID with single BSSID cases) |
| * @param[in] prSsid Specified SSID |
| * |
| * @return Pointer to BSS Descriptor, if found. NULL, if not found |
| */ |
| /*----------------------------------------------------------------------------*/ |
| P_BSS_DESC_T scanSearchBssDescByBssidAndLatestUpdateTime(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]) |
| { |
| P_SCAN_INFO_T prScanInfo; |
| P_LINK_T prBSSDescList; |
| P_BSS_DESC_T prBssDesc; |
| P_BSS_DESC_T prDstBssDesc = (P_BSS_DESC_T) NULL; |
| OS_SYSTIME rLatestUpdateTime = 0; |
| |
| ASSERT(prAdapter); |
| ASSERT(aucBSSID); |
| |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| |
| prBSSDescList = &prScanInfo->rBSSDescList; |
| |
| /* Search BSS Desc from current SCAN result list. */ |
| LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { |
| |
| if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { |
| if (!rLatestUpdateTime || CHECK_FOR_EXPIRATION(prBssDesc->rUpdateTime, rLatestUpdateTime)) { |
| prDstBssDesc = prBssDesc; |
| COPY_SYSTIME(rLatestUpdateTime, prBssDesc->rUpdateTime); |
| } |
| } |
| } |
| |
| return prDstBssDesc; |
| |
| } /* end of scanSearchBssDescByBssid() */ |
| |
| #endif /* CFG_SUPPORT_PASSPOINT */ |
| |
| #if CFG_SUPPORT_AGPS_ASSIST |
| VOID scanReportScanResultToAgps(P_ADAPTER_T prAdapter) |
| { |
| P_LINK_T prBSSDescList = &prAdapter->rWifiVar.rScanInfo.rBSSDescList; |
| P_BSS_DESC_T prBssDesc = NULL; |
| P_AGPS_AP_LIST_T prAgpsApList = kalMemAlloc(sizeof(AGPS_AP_LIST_T), VIR_MEM_TYPE); |
| P_AGPS_AP_INFO_T prAgpsInfo = &prAgpsApList->arApInfo[0]; |
| P_SCAN_INFO_T prScanInfo = &prAdapter->rWifiVar.rScanInfo; |
| UINT_8 ucIndex = 0; |
| |
| LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { |
| if (prBssDesc->rUpdateTime < prScanInfo->rLastScanCompletedTime) |
| continue; |
| COPY_MAC_ADDR(prAgpsInfo->aucBSSID, prBssDesc->aucBSSID); |
| prAgpsInfo->ePhyType = AGPS_PHY_G; |
| prAgpsInfo->u2Channel = prBssDesc->ucChannelNum; |
| prAgpsInfo->i2ApRssi = RCPI_TO_dBm(prBssDesc->ucRCPI); |
| prAgpsInfo++; |
| ucIndex++; |
| if (ucIndex == SCN_AGPS_AP_LIST_MAX_NUM) |
| break; |
| } |
| prAgpsApList->ucNum = ucIndex; |
| GET_CURRENT_SYSTIME(&prScanInfo->rLastScanCompletedTime); |
| /* DBGLOG(SCN, INFO, ("num of scan list:%d\n", ucIndex)); */ |
| kalIndicateAgpsNotify(prAdapter, AGPS_EVENT_WLAN_AP_LIST, (PUINT_8) prAgpsApList, sizeof(AGPS_AP_LIST_T)); |
| kalMemFree(prAgpsApList, VIR_MEM_TYPE, sizeof(AGPS_AP_LIST_T)); |
| } |
| #endif /* CFG_SUPPORT_AGPS_ASSIST */ |