| /* |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License version 2 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. |
| */ |
| |
| |
| /******************************************************************************* |
| * 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_STRENGTH_THRESHOLD (32) |
| #define ROAMING_NO_SWING_RCPI_STEP (10) |
| #define REPLICATED_BEACON_FRESH_PERIOD (10000) |
| #define REPLICATED_BEACON_TIME_THRESHOLD (3000) |
| |
| /******************************************************************************* |
| * D A T A T Y P E S |
| ******************************************************************************* |
| */ |
| |
| /******************************************************************************* |
| * P U B L I C D A T A |
| ******************************************************************************* |
| */ |
| /* The order of aucScanLogPrefix should be aligned the order |
| * of enum ENUM_SCAN_LOG_PREFIX |
| */ |
| const char aucScanLogPrefix[][SCAN_LOG_PREFIX_MAX_LEN] = { |
| /* Scan */ |
| "[SCN:100:K2D]", /* LOG_SCAN_REQ_K2D */ |
| "[SCN:200:D2F]", /* LOG_SCAN_REQ_D2F */ |
| "[SCN:300:F2D]", /* LOG_SCAN_RESULT_F2D */ |
| "[SCN:400:D2K]", /* LOG_SCAN_RESULT_D2K */ |
| "[SCN:500:F2D]", /* LOG_SCAN_DONE_F2D */ |
| "[SCN:600:D2K]", /* LOG_SCAN_DONE_D2K */ |
| |
| /* Sched scan */ |
| "[SCN:700:K2D]", /* LOG_SCHED_SCAN_REQ_START_K2D */ |
| "[SCN:800:D2F]", /* LOG_SCHED_SCAN_REQ_START_D2F */ |
| "[SCN:750:K2D]", /* LOG_SCHED_SCAN_REQ_STOP_K2D */ |
| "[SCN:850:D2F]", /* LOG_SCHED_SCAN_REQ_STOP_D2F */ |
| "[SCN:900:F2D]", /* LOG_SCHED_SCAN_DONE_F2D */ |
| "[SCN:1000:D2K]", /* LOG_SCHED_SCAN_DONE_D2K */ |
| |
| /* Scan abort */ |
| "[SCN:1100:K2D]", /* LOG_SCAN_ABORT_REQ_K2D */ |
| "[SCN:1200:D2F]", /* LOG_SCAN_ABORT_REQ_D2F */ |
| "[SCN:1300:D2K]", /* LOG_SCAN_ABORT_DONE_D2K */ |
| |
| /* Driver only */ |
| "[SCN:0:D2D]", /* LOG_SCAN_D2D */ |
| |
| /* Last one */ |
| "" /* LOG_SCAN_MAX */ |
| }; |
| |
| /******************************************************************************* |
| * 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 struct ADAPTER *prAdapter) |
| { |
| struct SCAN_INFO *prScanInfo; |
| struct BSS_DESC *prBSSDesc; |
| uint8_t *pucBSSBuff; |
| uint32_t i; |
| #if CFG_SUPPORT_ROAMING_SKIP_ONE_AP |
| struct ROAM_BSS_DESC *prRoamBSSDesc; |
| uint8_t *pucRoamBSSBuff; |
| #endif |
| |
| ASSERT(prAdapter); |
| |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| pucBSSBuff = &prScanInfo->aucScanBuffer[0]; |
| #if CFG_SUPPORT_ROAMING_SKIP_ONE_AP |
| pucRoamBSSBuff = &prScanInfo->aucScanRoamBuffer[0]; |
| #endif |
| |
| log_dbg(SCN, TRACE, "->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((void *) pucBSSBuff, SCN_MAX_BUFFER_SIZE); |
| #if CFG_SUPPORT_ROAMING_SKIP_ONE_AP |
| kalMemZero((void *) 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 = (struct BSS_DESC *) pucBSSBuff; |
| |
| LINK_INSERT_TAIL(&prScanInfo->rFreeBSSDescList, |
| &prBSSDesc->rLinkEntry); |
| |
| pucBSSBuff += ALIGN_4(sizeof(struct BSS_DESC)); |
| } |
| /* Check if the memory allocation consist with |
| * this initialization function |
| */ |
| ASSERT(((unsigned long) pucBSSBuff |
| - (unsigned long)&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 = (struct ROAM_BSS_DESC *) pucRoamBSSBuff; |
| |
| LINK_INSERT_TAIL(&prScanInfo->rRoamFreeBSSDescList, |
| &prRoamBSSDesc->rLinkEntry); |
| |
| pucRoamBSSBuff += ALIGN_4(sizeof(struct ROAM_BSS_DESC)); |
| } |
| ASSERT(((unsigned long) pucRoamBSSBuff |
| - (unsigned long)&prScanInfo->aucScanRoamBuffer[0]) |
| == SCN_ROAM_MAX_BUFFER_SIZE); |
| #endif |
| /* reset freest channel information */ |
| prScanInfo->fgIsSparseChannelValid = FALSE; |
| |
| prScanInfo->fgIsScanForFull2Partial = FALSE; |
| |
| /* reset Sched scan state */ |
| prScanInfo->fgSchedScanning = FALSE; |
| /*Support AP Selection */ |
| prScanInfo->u4ScanUpdateIdx = 0; |
| } /* end of scnInit() */ |
| |
| void scnFreeAllPendingScanRquests(IN struct ADAPTER *prAdapter) |
| { |
| struct SCAN_INFO *prScanInfo; |
| struct MSG_HDR *prMsgHdr; |
| struct 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, struct MSG_HDR *); |
| if (prMsgHdr) { |
| prScanReqMsg = (struct MSG_SCN_SCAN_REQ *) prMsgHdr; |
| |
| log_dbg(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 */ |
| } |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is used by SCN to uninitialize its variables |
| * |
| * @param (none) |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| void scnUninit(IN struct ADAPTER *prAdapter) |
| { |
| struct SCAN_INFO *prScanInfo; |
| |
| ASSERT(prAdapter); |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| |
| log_dbg(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 |
| */ |
| /*----------------------------------------------------------------------------*/ |
| struct BSS_DESC *scanSearchBssDescByBssid(IN struct ADAPTER *prAdapter, |
| IN uint8_t aucBSSID[]) |
| { |
| return scanSearchBssDescByBssidAndSsid(prAdapter, aucBSSID, |
| FALSE, NULL); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Check if the bit of the given bitmap is set |
| * The bitmap should be unsigned int based, which means that this function |
| * doesn't support other format bitmap, e.g. char array or short array |
| * |
| * @param[in] bit which bit to check. |
| * @param[in] bitMap bitmap array |
| * @param[in] bitMapSize bytes of bitmap |
| * |
| * @return TRUE if the bit of the given bitmap is set, FALSE otherwise |
| */ |
| /*----------------------------------------------------------------------------*/ |
| u_int8_t scanIsBitSet(IN uint32_t bit, IN uint32_t bitMap[], |
| IN uint32_t bitMapSize) |
| { |
| if (bit >= bitMapSize * BITS_OF_BYTE) { |
| log_dbg(SCN, WARN, "bit %u is out of array range(%u bits)\n", |
| bit, bitMapSize * BITS_OF_BYTE); |
| return FALSE; |
| } else { |
| return (bitMap[bit/BITS_OF_UINT] & |
| (1 << (bit % BITS_OF_UINT))) ? TRUE : FALSE; |
| } |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Set the bit of the given bitmap. |
| * The bitmap should be unsigned int based, which means that this function |
| * doesn't support other format bitmap, e.g. char array or short array |
| * |
| * @param[in] bit which bit to set. |
| * @param[out] bitMap bitmap array |
| * @param[in] bitMapSize bytes of bitmap |
| * |
| * @return void |
| */ |
| /*----------------------------------------------------------------------------*/ |
| void scanSetBit(IN uint32_t bit, OUT uint32_t bitMap[], IN uint32_t bitMapSize) |
| { |
| if (bit >= bitMapSize * BITS_OF_BYTE) { |
| log_dbg(SCN, WARN, "set bit %u to array(%u bits) failed\n", |
| bit, bitMapSize * BITS_OF_BYTE); |
| } else |
| bitMap[bit/BITS_OF_UINT] |= 1 << (bit % BITS_OF_UINT); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Return number of bit which is set to 1 in the given bitmap. |
| * The bitmap should be unsigned int based, which means that this function |
| * doesn't support other format bitmap, e.g. char array or short array |
| * |
| * @param[in] bitMap bitmap array |
| * @param[in] bitMapSize bytes of bitmap |
| * |
| * @return number of bit which is set to 1 |
| */ |
| /*----------------------------------------------------------------------------*/ |
| |
| uint32_t scanCountBits(IN uint32_t bitMap[], IN uint32_t bitMapSize) |
| { |
| uint32_t count = 0; |
| uint32_t value; |
| int32_t arrayLen = bitMapSize/sizeof(uint32_t); |
| int32_t i; |
| |
| for (i = arrayLen - 1; i >= 0; i--) { |
| value = bitMap[i]; |
| log_dbg(SCN, TRACE, "array[%d]:%08X\n", i, value); |
| while (value) { |
| count += (value & 1); |
| value >>= 1; |
| } |
| } |
| return count; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Set scan channel to scanReqMsg. |
| * |
| * @param[in] prAdapter Pointer to the Adapter structure. |
| * @param[in] u4ScanChannelNum number of input channels |
| * @param[in] arChannel channel list |
| * @param[in] fgIsOnlineScan online scan or not |
| * @param[out] prScanReqMsg scan request msg. Set channel number and |
| * channel list for output |
| * |
| * @return |
| */ |
| /*----------------------------------------------------------------------------*/ |
| void scanSetRequestChannel(IN struct ADAPTER *prAdapter, |
| IN uint32_t u4ScanChannelNum, |
| IN struct RF_CHANNEL_INFO arChannel[], |
| IN uint8_t fgIsOnlineScan, |
| OUT struct MSG_SCN_SCAN_REQ_V2 *prScanReqMsg) |
| { |
| uint32_t i, u4Channel, eBand, u4Index; |
| /*print channel info for debugging */ |
| uint32_t au4ChannelBitMap[SCAN_CHANNEL_BITMAP_ARRAY_LEN]; |
| #if CFG_SUPPORT_FULL2PARTIAL_SCAN |
| uint8_t fgIsFull2Partial = FALSE; |
| #endif /* CFG_SUPPORT_FULL2PARTIAL_SCAN */ |
| struct SCAN_INFO *prScanInfo; |
| |
| ASSERT(u4ScanChannelNum <= MAXIMUM_OPERATION_CHANNEL_LIST); |
| |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| i = u4Index = 0; |
| kalMemZero(au4ChannelBitMap, sizeof(au4ChannelBitMap)); |
| |
| #if CFG_SUPPORT_FULL2PARTIAL_SCAN |
| /* fgIsCheckingFull2Partial should be true if it's an online scan. |
| * Next, enable full2partial if channel number to scan is |
| * larger than SCAN_FULL2PARTIAL_CHANNEL_NUM |
| */ |
| if (fgIsOnlineScan && (u4ScanChannelNum == 0 || |
| u4ScanChannelNum > SCAN_FULL2PARTIAL_CHANNEL_NUM)) { |
| OS_SYSTIME rCurrentTime; |
| |
| GET_CURRENT_SYSTIME(&rCurrentTime); |
| |
| if (((prScanInfo->u4LastFullScanTime == 0) || |
| (CHECK_FOR_TIMEOUT(rCurrentTime, |
| prScanInfo->u4LastFullScanTime, |
| SEC_TO_SYSTIME(CFG_SCAN_FULL2PARTIAL_PERIOD))))) { |
| prScanInfo->fgIsScanForFull2Partial = TRUE; |
| prScanInfo->ucFull2PartialSeq = prScanReqMsg->ucSeqNum; |
| prScanInfo->u4LastFullScanTime = rCurrentTime; |
| kalMemZero(prScanInfo->au4ChannelBitMap, |
| sizeof(prScanInfo->au4ChannelBitMap)); |
| log_dbg(SCN, INFO, |
| "Full2partial: 1st full scan start\n"); |
| } else { |
| log_dbg(SCN, INFO, |
| "Full2partial: enable full2partial\n"); |
| fgIsFull2Partial = TRUE; |
| } |
| } |
| |
| if (fgIsFull2Partial && u4ScanChannelNum == 0) { |
| /* We don't have channel info when u4ScanChannelNum is 0. |
| * check full2partial bitmap and set scan channels |
| */ |
| uint32_t start = 1; |
| uint32_t end = HW_CHNL_NUM_MAX_4G_5G; |
| |
| if (prScanReqMsg->eScanChannel == SCAN_CHANNEL_2G4) |
| end = HW_CHNL_NUM_MAX_2G4; |
| else if (prScanReqMsg->eScanChannel == SCAN_CHANNEL_5G) |
| start = HW_CHNL_NUM_MAX_2G4 + 1; |
| |
| u4Index = 0; |
| for (u4Channel = start; u4Channel <= end; u4Channel++) { |
| if (scanIsBitSet(u4Channel, |
| prScanInfo->au4ChannelBitMap, |
| sizeof(prScanInfo->au4ChannelBitMap))) { |
| eBand = (u4Channel <= HW_CHNL_NUM_MAX_2G4) ? |
| BAND_2G4 : BAND_5G; |
| prScanReqMsg->arChnlInfoList[u4Index]. |
| ucChannelNum = u4Channel; |
| prScanReqMsg->arChnlInfoList[u4Index]. |
| eBand = eBand; |
| scanSetBit(u4Channel, au4ChannelBitMap, |
| sizeof(au4ChannelBitMap)); |
| u4Index++; |
| } |
| } |
| |
| prScanReqMsg->ucChannelListNum = u4Index; |
| prScanReqMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; |
| } else |
| #endif /* CFG_SUPPORT_FULL2PARTIAL_SCAN */ |
| if (u4ScanChannelNum == 0) { |
| prScanReqMsg->ucChannelListNum = 0; |
| } else { |
| u4Index = 0; |
| for (i = 0; i < u4ScanChannelNum; i++) { |
| u4Channel = arChannel[i].ucChannelNum; |
| eBand = arChannel[i].eBand; |
| if (prScanReqMsg->eScanChannel == SCAN_CHANNEL_2G4 && |
| eBand != BAND_2G4) |
| continue; |
| else if (prScanReqMsg->eScanChannel == |
| SCAN_CHANNEL_5G && eBand != BAND_5G) |
| continue; |
| #if CFG_SUPPORT_FULL2PARTIAL_SCAN |
| if (fgIsFull2Partial && !scanIsBitSet(u4Channel, |
| prScanInfo->au4ChannelBitMap, |
| sizeof(prScanInfo->au4ChannelBitMap))) |
| continue; |
| #endif /* CFG_SUPPORT_FULL2PARTIAL_SCAN */ |
| kalMemCopy(&prScanReqMsg->arChnlInfoList[u4Index], |
| &arChannel[i], |
| sizeof(struct RF_CHANNEL_INFO)); |
| scanSetBit(u4Channel, au4ChannelBitMap, |
| sizeof(au4ChannelBitMap)); |
| |
| u4Index++; |
| } |
| if (u4Index == 0) { |
| log_dbg(SCN, WARN, "No channel to scan\n"); |
| prScanReqMsg->ucChannelListNum = 0; |
| } else { |
| prScanReqMsg->ucChannelListNum = u4Index; |
| prScanReqMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; |
| } |
| } |
| |
| log_dbg(SCN, INFO, |
| "channel num(%u=>%u) %08X %08X %08X %08X %08X %08X %08X %08X\n", |
| u4ScanChannelNum, prScanReqMsg->ucChannelListNum, |
| au4ChannelBitMap[7], au4ChannelBitMap[6], |
| au4ChannelBitMap[5], au4ChannelBitMap[4], |
| au4ChannelBitMap[3], au4ChannelBitMap[2], |
| au4ChannelBitMap[1], au4ChannelBitMap[0]); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @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 |
| */ |
| /*----------------------------------------------------------------------------*/ |
| struct BSS_DESC * |
| scanSearchBssDescByBssidAndSsid(IN struct ADAPTER *prAdapter, |
| IN uint8_t aucBSSID[], |
| IN u_int8_t fgCheckSsid, |
| IN struct PARAM_SSID *prSsid) |
| { |
| struct SCAN_INFO *prScanInfo; |
| struct LINK *prBSSDescList; |
| struct BSS_DESC *prBssDesc; |
| struct BSS_DESC *prDstBssDesc = (struct BSS_DESC *) 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, struct BSS_DESC) { |
| |
| 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, (uint8_t) (prSsid->u4SsidLen)); |
| return prBssDesc; |
| } |
| } |
| |
| return prDstBssDesc; |
| |
| } /* end of scanSearchBssDescByBssid() */ |
| |
| #if CFG_SUPPORT_CFG80211_AUTH |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Find the corresponding BSS Descriptor |
| * according to given BSSID & ChanNum |
| * |
| * @param[in] prAdapter Pointer to the Adapter structure. |
| * @param[in] aucBSSID Given BSSID. |
| * @param[in] fgCheckChanNum Need to check ChanNum or not. |
| * @param[in] ucChannelNum Specified Channel Num |
| * |
| * @return Pointer to BSS Descriptor, if found. NULL, if not found |
| */ |
| /*----------------------------------------------------------------------------*/ |
| struct BSS_DESC * |
| scanSearchBssDescByBssidAndChanNum(IN struct ADAPTER *prAdapter, |
| IN uint8_t aucBSSID[], |
| IN u_int8_t fgCheckChanNum, |
| IN uint8_t ucChannelNum) |
| { |
| struct SCAN_INFO *prScanInfo; |
| struct LINK *prBSSDescList; |
| struct BSS_DESC *prBssDesc = 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, struct BSS_DESC) { |
| if (!(EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID))) |
| continue; |
| if (fgCheckChanNum == FALSE || ucChannelNum == 0) |
| return prBssDesc; |
| if (prBssDesc->ucChannelNum == ucChannelNum) |
| return prBssDesc; |
| } |
| |
| return prBssDesc; |
| } |
| #endif |
| |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @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 |
| */ |
| /*----------------------------------------------------------------------------*/ |
| struct BSS_DESC *scanSearchBssDescByTA(IN struct ADAPTER *prAdapter, |
| IN uint8_t 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 |
| */ |
| /*----------------------------------------------------------------------------*/ |
| struct BSS_DESC * |
| scanSearchBssDescByTAAndSsid(IN struct ADAPTER *prAdapter, |
| IN uint8_t aucSrcAddr[], |
| IN u_int8_t fgCheckSsid, |
| IN struct PARAM_SSID *prSsid) |
| { |
| struct SCAN_INFO *prScanInfo; |
| struct LINK *prBSSDescList; |
| struct BSS_DESC *prBssDesc; |
| struct BSS_DESC *prDstBssDesc = (struct BSS_DESC *) 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, struct BSS_DESC) { |
| |
| 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 |
| */ |
| /*----------------------------------------------------------------------------*/ |
| struct BSS_DESC * |
| scanSearchExistingBssDesc(IN struct ADAPTER *prAdapter, |
| IN enum ENUM_BSS_TYPE eBSSType, |
| IN uint8_t aucBSSID[], |
| IN uint8_t aucSrcAddr[]) |
| { |
| return scanSearchExistingBssDescWithSsid(prAdapter, eBSSType, aucBSSID, |
| aucSrcAddr, FALSE, NULL); |
| } |
| |
| #if CFG_SUPPORT_ROAMING_SKIP_ONE_AP |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief |
| * |
| * @param |
| * |
| * @return |
| */ |
| /*----------------------------------------------------------------------------*/ |
| void scanRemoveRoamBssDescsByTime(IN struct ADAPTER *prAdapter, |
| IN uint32_t u4RemoveTime) |
| { |
| struct SCAN_INFO *prScanInfo; |
| struct LINK *prRoamBSSDescList; |
| struct LINK *prRoamFreeBSSDescList; |
| struct ROAM_BSS_DESC *prRoamBssDesc; |
| struct ROAM_BSS_DESC *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, struct ROAM_BSS_DESC) { |
| |
| 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 |
| */ |
| /*----------------------------------------------------------------------------*/ |
| struct ROAM_BSS_DESC * |
| scanSearchRoamBssDescBySsid(IN struct ADAPTER *prAdapter, |
| IN struct BSS_DESC *prBssDesc) |
| { |
| struct SCAN_INFO *prScanInfo; |
| struct LINK *prRoamBSSDescList; |
| struct ROAM_BSS_DESC *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, struct ROAM_BSS_DESC) { |
| if (EQUAL_SSID(prRoamBssDesc->aucSSID, prRoamBssDesc->ucSSIDLen, |
| prBssDesc->aucSSID, prBssDesc->ucSSIDLen)) { |
| return prRoamBssDesc; |
| } |
| } |
| |
| return NULL; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief |
| * |
| * @param |
| * |
| * @return |
| */ |
| /*----------------------------------------------------------------------------*/ |
| struct ROAM_BSS_DESC *scanAllocateRoamBssDesc(IN struct ADAPTER *prAdapter) |
| { |
| struct SCAN_INFO *prScanInfo; |
| struct LINK *prRoamFreeBSSDescList; |
| struct ROAM_BSS_DESC *prRoamBssDesc = NULL; |
| |
| ASSERT(prAdapter); |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| |
| prRoamFreeBSSDescList = &prScanInfo->rRoamFreeBSSDescList; |
| |
| LINK_REMOVE_HEAD(prRoamFreeBSSDescList, prRoamBssDesc, |
| struct ROAM_BSS_DESC *); |
| |
| if (prRoamBssDesc) { |
| struct LINK *prRoamBSSDescList; |
| |
| kalMemZero(prRoamBssDesc, sizeof(struct ROAM_BSS_DESC)); |
| |
| prRoamBSSDescList = &prScanInfo->rRoamBSSDescList; |
| |
| LINK_INSERT_HEAD(prRoamBSSDescList, &prRoamBssDesc->rLinkEntry); |
| } |
| |
| return prRoamBssDesc; |
| } |
| |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief |
| * |
| * @param |
| * |
| * @return |
| */ |
| /*----------------------------------------------------------------------------*/ |
| void scanAddToRoamBssDesc(IN struct ADAPTER *prAdapter, |
| IN struct BSS_DESC *prBssDesc) |
| { |
| struct ROAM_BSS_DESC *prRoamBssDesc; |
| |
| prRoamBssDesc = scanSearchRoamBssDescBySsid(prAdapter, prBssDesc); |
| |
| if (prRoamBssDesc == NULL) { |
| uint32_t 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 struct ADAPTER *prAdapter) |
| { |
| |
| /* If only exist one same ssid AP, avoid unnecessary scan */ |
| #define SSID_ONLY_EXIST_ONE_AP 1 |
| |
| struct SCAN_INFO *prScanInfo; |
| struct LINK *prBSSDescList; |
| struct BSS_DESC *prBssDesc; |
| struct BSS_INFO *prAisBssInfo; |
| uint32_t u4SameSSIDCount = 0; |
| |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| |
| /* XXX: wlan0(AP mode) + p2p0 occurs exception. */ |
| if (prAisBssInfo == NULL) |
| return; |
| |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| prBSSDescList = &prScanInfo->rBSSDescList; |
| |
| if (prAisBssInfo->eConnectionState != PARAM_MEDIA_STATE_CONNECTED) |
| return; |
| |
| LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, |
| rLinkEntry, struct BSS_DESC) { |
| 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 |
| */ |
| /*----------------------------------------------------------------------------*/ |
| struct BSS_DESC * |
| scanSearchExistingBssDescWithSsid(IN struct ADAPTER *prAdapter, |
| IN enum ENUM_BSS_TYPE eBSSType, |
| IN uint8_t aucBSSID[], |
| IN uint8_t aucSrcAddr[], |
| IN u_int8_t fgCheckSsid, |
| IN struct PARAM_SSID *prSsid) |
| { |
| struct SCAN_INFO *prScanInfo; |
| struct BSS_DESC *prBssDesc, *prIBSSBssDesc; |
| /* CASE III */ |
| struct LINK *prBSSDescList; |
| struct LINK *prFreeBSSDescList; |
| |
| ASSERT(prAdapter); |
| ASSERT(aucSrcAddr); |
| |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| |
| switch (eBSSType) { |
| case BSS_TYPE_P2P_DEVICE: |
| fgCheckSsid = FALSE; |
| kal_fallthrough; |
| case BSS_TYPE_INFRASTRUCTURE: |
| kal_fallthrough; |
| 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 (struct BSS_DESC *) NULL; |
| |
| } /* end of scanSearchExistingBssDesc() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Delete BSS Descriptors from current list according |
| * to given Remove Policy. |
| * |
| * @param[in] u4RemovePolicy Remove Policy. |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| void scanRemoveBssDescsByPolicy(IN struct ADAPTER *prAdapter, |
| IN uint32_t u4RemovePolicy) |
| { |
| struct CONNECTION_SETTINGS *prConnSettings; |
| struct SCAN_INFO *prScanInfo; |
| struct LINK *prBSSDescList; |
| struct LINK *prFreeBSSDescList; |
| struct BSS_DESC *prBssDesc; |
| /* Support AP Selection*/ |
| struct LINK *prEssList; |
| |
| ASSERT(prAdapter); |
| |
| prConnSettings = &(prAdapter->rWifiVar.rConnSettings); |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| prBSSDescList = &prScanInfo->rBSSDescList; |
| prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; |
| /* Support AP Selection*/ |
| prEssList = &prAdapter->rWifiVar.rAisSpecificBssInfo.rCurEssLink; |
| |
| #if 0 /* TODO: Remove this */ |
| log_dbg(SCN, TRACE, ("Before Remove - Number Of SCAN Result = %ld\n", |
| prBSSDescList->u4NumElem)); |
| #endif |
| |
| if (u4RemovePolicy & SCN_RM_POLICY_TIMEOUT) { |
| struct BSS_DESC *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, struct BSS_DESC) { |
| |
| if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) |
| && (prBssDesc->fgIsConnected |
| || prBssDesc->fgIsConnecting)) { |
| /* Don't remove the one currently we |
| * are connected. |
| */ |
| continue; |
| } |
| |
| if (CHECK_FOR_TIMEOUT(rCurrentTime, |
| prBssDesc->rUpdateTime, |
| SEC_TO_SYSTIME( |
| SCN_BSS_DESC_REMOVE_TIMEOUT_SEC))) { |
| |
| #if 0 /* TODO: Remove this */ |
| log_dbg(SCN, TRACE, "Remove TIMEOUT BSS DESC(%#x):MAC: " |
| MACSTR |
| ", Current Time = %08lx, Update Time = %08lx\n", |
| prBssDesc, |
| MAC2STR(prBssDesc->aucBSSID), |
| rCurrentTime, prBssDesc->rUpdateTime)); |
| #endif |
| /* Support AP Selection */ |
| if (!prBssDesc->prBlack) |
| aisQueryBlackList(prAdapter, prBssDesc); |
| if (prBssDesc->prBlack) |
| prBssDesc->prBlack->u4DisapperTime = |
| (uint32_t)kalGetBootTime(); |
| /* end Support AP Selection */ |
| |
| /* Remove this BSS Desc from |
| * the BSS Desc list |
| */ |
| LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, |
| prBssDesc); |
| |
| /* Support AP Selection */ |
| /* Remove this BSS Desc from the Ess Desc List |
| */ |
| if (LINK_ENTRY_IS_VALID |
| (&prBssDesc->rLinkEntryEss)) |
| LINK_REMOVE_KNOWN_ENTRY(prEssList, |
| &prBssDesc->rLinkEntryEss); |
| /* end Support AP Selection */ |
| |
| /* Return this BSS Desc to the |
| * free BSS Desc list. |
| */ |
| LINK_INSERT_TAIL(prFreeBSSDescList, |
| &prBssDesc->rLinkEntry); |
| } |
| } |
| } |
| if (u4RemovePolicy & SCN_RM_POLICY_OLDEST_HIDDEN) { |
| struct BSS_DESC *prBssDescOldest = (struct BSS_DESC *) NULL; |
| |
| /* Search BSS Desc from current SCAN result list. */ |
| LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, |
| rLinkEntry, struct BSS_DESC) { |
| |
| if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) |
| && (prBssDesc->fgIsConnected |
| || prBssDesc->fgIsConnecting)) { |
| /* Don't remove the one currently |
| * we are connected. |
| */ |
| continue; |
| } |
| |
| if (!prBssDesc->fgIsHiddenSSID) |
| continue; |
| |
| if (!prBssDescOldest) { /* 1st element */ |
| prBssDescOldest = prBssDesc; |
| continue; |
| } |
| |
| if (TIME_BEFORE(prBssDesc->rUpdateTime, |
| prBssDescOldest->rUpdateTime)) |
| prBssDescOldest = prBssDesc; |
| } |
| |
| if (prBssDescOldest) { |
| #if 0 /* TODO: Remove this */ |
| log_dbg(SCN, TRACE, "Remove OLDEST HIDDEN BSS DESC(%#x): MAC: " |
| MACSTR |
| ", Update Time = %08lx\n", |
| prBssDescOldest, |
| MAC2STR(prBssDescOldest->aucBSSID), |
| prBssDescOldest->rUpdateTime); |
| #endif |
| /* Support AP Selection */ |
| if (!prBssDescOldest->prBlack) |
| aisQueryBlackList(prAdapter, prBssDescOldest); |
| if (prBssDescOldest->prBlack) |
| prBssDescOldest->prBlack->u4DisapperTime = |
| (uint32_t)kalGetBootTime(); |
| /* end Support AP Selection */ |
| |
| /* Remove this BSS Desc from the BSS Desc list */ |
| LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDescOldest); |
| |
| /* Support AP Selection */ |
| /* Remove this BSS Desc from the Ess Desc List */ |
| if (LINK_ENTRY_IS_VALID |
| (&prBssDescOldest->rLinkEntryEss)) |
| LINK_REMOVE_KNOWN_ENTRY(prEssList, |
| &prBssDescOldest->rLinkEntryEss); |
| /* end Support AP Selection */ |
| |
| /* Return this BSS Desc to the free BSS Desc list. */ |
| LINK_INSERT_TAIL(prFreeBSSDescList, |
| &prBssDescOldest->rLinkEntry); |
| } |
| } |
| if (u4RemovePolicy & SCN_RM_POLICY_SMART_WEAKEST) { |
| struct BSS_DESC *prBssDescWeakest = (struct BSS_DESC *) NULL; |
| struct BSS_DESC *prBssDescWeakestSameSSID |
| = (struct BSS_DESC *) NULL; |
| uint32_t u4SameSSIDCount = 0; |
| |
| /* Search BSS Desc from current SCAN result list. */ |
| LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, |
| rLinkEntry, struct BSS_DESC) { |
| |
| if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) |
| && (prBssDesc->fgIsConnected |
| || prBssDesc->fgIsConnecting)) { |
| /* Don't remove the one currently |
| * we are connected. |
| */ |
| 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 (u4SameSSIDCount |
| < SCN_BSS_DESC_SAME_SSID_THRESHOLD) |
| continue; |
| } |
| |
| 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) { |
| #if 0 /* TODO: Remove this */ |
| log_dbg(SCN, TRACE, "Remove WEAKEST BSS DESC(%#x): MAC: " |
| MACSTR |
| ", Update Time = %08lx\n", |
| prBssDescOldest, |
| MAC2STR(prBssDescOldest->aucBSSID), |
| prBssDescOldest->rUpdateTime); |
| #endif |
| |
| /* Support AP Selection */ |
| if (!prBssDescWeakest->prBlack) |
| aisQueryBlackList(prAdapter, prBssDescWeakest); |
| if (prBssDescWeakest->prBlack) |
| prBssDescWeakest->prBlack->u4DisapperTime = |
| (uint32_t)kalGetBootTime(); |
| /* end Support AP Selection */ |
| |
| /* Remove this BSS Desc from the BSS Desc list */ |
| LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, |
| prBssDescWeakest); |
| |
| /* Support AP Selection */ |
| /* Remove this BSS Desc from the Ess Desc List */ |
| if (LINK_ENTRY_IS_VALID |
| (&prBssDescWeakest->rLinkEntryEss)) |
| LINK_REMOVE_KNOWN_ENTRY(prEssList, |
| &prBssDescWeakest->rLinkEntryEss); |
| /* end Support AP Selection */ |
| |
| /* Return this BSS Desc to the free BSS Desc list. */ |
| LINK_INSERT_TAIL(prFreeBSSDescList, |
| &prBssDescWeakest->rLinkEntry); |
| } |
| } |
| if (u4RemovePolicy & SCN_RM_POLICY_ENTIRE) { |
| struct BSS_DESC *prBSSDescNext; |
| /* Support AP Selection */ |
| uint32_t u4Current = (uint32_t)kalGetBootTime(); |
| |
| LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, |
| prBSSDescList, rLinkEntry, struct BSS_DESC) { |
| |
| if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) |
| && (prBssDesc->fgIsConnected |
| || prBssDesc->fgIsConnecting)) { |
| /* Don't remove the one currently |
| * we are connected. |
| */ |
| continue; |
| } |
| /* Support AP Selection */ |
| if (!prBssDesc->prBlack) |
| aisQueryBlackList(prAdapter, prBssDesc); |
| if (prBssDesc->prBlack) |
| prBssDesc->prBlack->u4DisapperTime = u4Current; |
| /* end Support AP Selection */ |
| |
| /* Remove this BSS Desc from the BSS Desc list */ |
| LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); |
| |
| /* Support AP Selection */ |
| /* Remove this BSS Desc from the Ess Desc List */ |
| if (LINK_ENTRY_IS_VALID(&prBssDesc->rLinkEntryEss)) |
| LINK_REMOVE_KNOWN_ENTRY(prEssList, |
| &prBssDesc->rLinkEntryEss); |
| /* end Support AP Selection */ |
| |
| /* Return this BSS Desc to the free BSS Desc list. */ |
| LINK_INSERT_TAIL(prFreeBSSDescList, |
| &prBssDesc->rLinkEntry); |
| } |
| |
| } |
| } /* 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 struct ADAPTER *prAdapter, |
| IN uint8_t aucBSSID[]) |
| { |
| struct SCAN_INFO *prScanInfo; |
| struct LINK *prBSSDescList; |
| struct LINK *prFreeBSSDescList; |
| struct BSS_DESC *prBssDesc = (struct BSS_DESC *) NULL; |
| struct BSS_DESC *prBSSDescNext; |
| /* Support AP Selection */ |
| struct LINK *prEssList = NULL; |
| |
| ASSERT(prAdapter); |
| ASSERT(aucBSSID); |
| |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| prBSSDescList = &prScanInfo->rBSSDescList; |
| prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; |
| /* Support AP Selection */ |
| prEssList = &prAdapter->rWifiVar.rAisSpecificBssInfo.rCurEssLink; |
| |
| /* Check if such BSS Descriptor exists in a valid list */ |
| LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, |
| rLinkEntry, struct BSS_DESC) { |
| |
| if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { |
| /* Support AP Selection */ |
| if (!prBssDesc->prBlack) |
| aisQueryBlackList(prAdapter, prBssDesc); |
| if (prBssDesc->prBlack) |
| prBssDesc->prBlack->u4DisapperTime = |
| (uint32_t)kalGetBootTime(); |
| |
| /* Remove this BSS Desc from the BSS Desc list */ |
| LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); |
| |
| /* Remove this BSS Desc from the Ess Desc List */ |
| if (LINK_ENTRY_IS_VALID(&prBssDesc->rLinkEntryEss)) |
| LINK_REMOVE_KNOWN_ENTRY(prEssList, |
| &prBssDesc->rLinkEntryEss); |
| |
| /* 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 struct ADAPTER *prAdapter, |
| IN enum ENUM_BAND eBand, |
| IN uint8_t ucBssIndex) |
| { |
| struct SCAN_INFO *prScanInfo; |
| struct LINK *prBSSDescList; |
| struct LINK *prFreeBSSDescList; |
| struct BSS_DESC *prBssDesc = (struct BSS_DESC *) NULL; |
| struct BSS_DESC *prBSSDescNext; |
| u_int8_t fgToRemove; |
| |
| ASSERT(prAdapter); |
| ASSERT(eBand <= BAND_NUM); |
| ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); |
| |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| prBSSDescList = &prScanInfo->rBSSDescList; |
| prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; |
| |
| if (eBand == BAND_NULL) { |
| /* no need to do anything, keep all scan result */ |
| return; |
| } |
| |
| /* Check if such BSS Descriptor exists in a valid list */ |
| LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, |
| rLinkEntry, struct BSS_DESC) { |
| 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) { |
| /* Support AP Selection */ |
| struct LINK *prEssList = |
| &prAdapter->rWifiVar. |
| rAisSpecificBssInfo.rCurEssLink; |
| |
| if (!prBssDesc->prBlack) |
| aisQueryBlackList(prAdapter, prBssDesc); |
| if (prBssDesc->prBlack) |
| prBssDesc->prBlack->u4DisapperTime = |
| (uint32_t)kalGetBootTime(); |
| |
| /* Remove this BSS Desc from the BSS Desc list */ |
| LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); |
| |
| /* Remove this BSS Desc from the Ess Desc List */ |
| if (LINK_ENTRY_IS_VALID(&prBssDesc->rLinkEntryEss)) |
| LINK_REMOVE_KNOWN_ENTRY(prEssList, |
| &prBssDesc->rLinkEntryEss); |
| |
| /* 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 struct ADAPTER *prAdapter, |
| IN uint8_t aucBSSID[]) |
| { |
| struct SCAN_INFO *prScanInfo; |
| struct LINK *prBSSDescList; |
| struct BSS_DESC *prBssDesc = (struct BSS_DESC *) 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, struct BSS_DESC) { |
| |
| if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { |
| prBssDesc->fgIsConnected = FALSE; |
| prBssDesc->fgIsConnecting = FALSE; |
| |
| /* BSSID is not unique, so need to |
| * traverse whols link-list |
| */ |
| } |
| } |
| } /* end of scanRemoveConnectionFlagOfBssDescByBssid() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Delete All BSS Descriptors from current list.* |
| * @param[in] prAdapter Pointer to the Adapter structure.* |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| void scanRemoveAllBssDesc(IN struct ADAPTER *prAdapter) |
| { |
| struct SCAN_INFO *prScanInfo; |
| struct LINK *prBSSDescList; |
| struct LINK *prFreeBSSDescList; |
| struct BSS_DESC *prBssDesc = (struct BSS_DESC *) NULL; |
| struct BSS_DESC *prBSSDescNext; |
| /* Support AP Selection */ |
| struct LINK *prEssList = NULL; |
| |
| ASSERT(prAdapter); |
| |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| prBSSDescList = &prScanInfo->rBSSDescList; |
| prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; |
| /* Support AP Selection */ |
| prEssList = &prAdapter->rWifiVar.rAisSpecificBssInfo.rCurEssLink; |
| |
| /* Check if such BSS Descriptor exists in a valid list */ |
| LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, |
| rLinkEntry, struct BSS_DESC) { |
| |
| /* Support AP Selection */ |
| if (!prBssDesc->prBlack) |
| aisQueryBlackList(prAdapter, prBssDesc); |
| if (prBssDesc->prBlack) |
| prBssDesc->prBlack->u4DisapperTime = |
| (uint32_t)kalGetBootTime(); |
| |
| /* Remove this BSS Desc from the BSS Desc list */ |
| LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); |
| |
| /* Remove this BSS Desc from the Ess Desc List */ |
| if (LINK_ENTRY_IS_VALID(&prBssDesc->rLinkEntryEss)) |
| LINK_REMOVE_KNOWN_ENTRY(prEssList, |
| &prBssDesc->rLinkEntryEss); |
| |
| /* Return this BSS Desc to the free BSS Desc list. */ |
| LINK_INSERT_TAIL(prFreeBSSDescList, |
| &prBssDesc->rLinkEntry); |
| } |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Allocate new BSS_DESC structure |
| * |
| * @param[in] prAdapter Pointer to the Adapter structure. |
| * |
| * @return Pointer to BSS Descriptor, if has |
| * free space. NULL, if has no space. |
| */ |
| /*----------------------------------------------------------------------------*/ |
| struct BSS_DESC *scanAllocateBssDesc(IN struct ADAPTER *prAdapter) |
| { |
| struct SCAN_INFO *prScanInfo; |
| struct LINK *prFreeBSSDescList; |
| struct BSS_DESC *prBssDesc; |
| |
| ASSERT(prAdapter); |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| |
| prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; |
| |
| LINK_REMOVE_HEAD(prFreeBSSDescList, prBssDesc, struct BSS_DESC *); |
| |
| if (prBssDesc) { |
| struct LINK *prBSSDescList; |
| |
| kalMemZero(prBssDesc, sizeof(struct BSS_DESC)); |
| |
| #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 |
| * struct BSS_DESC 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 structure 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 |
| */ |
| /*----------------------------------------------------------------------------*/ |
| struct BSS_DESC *scanAddToBssDesc(IN struct ADAPTER *prAdapter, |
| IN struct SW_RFB *prSwRfb) |
| { |
| struct BSS_DESC *prBssDesc = NULL; |
| uint16_t u2CapInfo; |
| enum ENUM_BSS_TYPE eBSSType = BSS_TYPE_INFRASTRUCTURE; |
| struct BSS_INFO *prAisBssInfo; |
| uint8_t *pucIE; |
| uint16_t u2IELength; |
| uint16_t u2Offset = 0; |
| |
| struct WLAN_BEACON_FRAME *prWlanBeaconFrame |
| = (struct WLAN_BEACON_FRAME *) NULL; |
| struct IE_SSID *prIeSsid = (struct IE_SSID *) NULL; |
| struct IE_SUPPORTED_RATE_IOT *prIeSupportedRate |
| = (struct IE_SUPPORTED_RATE_IOT *) NULL; |
| struct IE_EXT_SUPPORTED_RATE *prIeExtSupportedRate |
| = (struct IE_EXT_SUPPORTED_RATE *) NULL; |
| uint8_t ucHwChannelNum = 0; |
| uint8_t ucIeDsChannelNum = 0; |
| uint8_t ucIeHtChannelNum = 0; |
| u_int8_t fgIsValidSsid = FALSE; |
| struct PARAM_SSID rSsid; |
| uint64_t u8Timestamp; |
| u_int8_t fgIsNewBssDesc = FALSE; |
| |
| uint32_t i; |
| uint8_t ucSSIDChar; |
| /* PUINT_8 pucDumpIE; */ |
| enum ENUM_BAND eHwBand = BAND_NULL; |
| u_int8_t fgBandMismatch = FALSE; |
| uint8_t ucSubtype; |
| u_int8_t fgIsProbeResp = FALSE; |
| u_int8_t ucPowerConstraint = 0; |
| struct IE_COUNTRY *prCountryIE = NULL; |
| #if CFG_SUPPORT_DISABLE_OBSS_SCAN |
| uint8_t *pucObssScanIE = NULL; |
| uint16_t u2ObssScanOffset = 0; |
| uint16_t u2ObssScanIESize = 0; |
| #endif |
| |
| if (prAdapter == NULL) { |
| DBGLOG(SCN, ERROR, "prAdapter is NULL\n"); |
| return NULL; |
| } |
| if (prSwRfb == NULL) { |
| DBGLOG(SCN, ERROR, "prSwRfb is NULL\n"); |
| return NULL; |
| } |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| if (prAisBssInfo == NULL) { |
| DBGLOG(SCN, ERROR, "prAisBssInfo is NULL\n"); |
| return NULL; |
| } |
| eHwBand = HAL_RX_STATUS_GET_RF_BAND(prSwRfb->prRxStatus); |
| prWlanBeaconFrame = (struct WLAN_BEACON_FRAME *) prSwRfb->pvHeader; |
| ucSubtype = (*(uint8_t *) (prSwRfb->pvHeader) & |
| MASK_FC_SUBTYPE) >> OFFSET_OF_FC_SUBTYPE; |
| |
| 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: |
| log_dbg(SCN, WARN, "Skip unknown bss type(%u)\n", u2CapInfo); |
| return NULL; |
| } |
| |
| /* 4 <1.1> Pre-parse SSID IE and channel info */ |
| pucIE = prWlanBeaconFrame->aucInfoElem; |
| u2IELength = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - |
| (uint16_t) OFFSET_OF(struct WLAN_BEACON_FRAME_BODY, aucInfoElem[0]); |
| |
| if (u2IELength > CFG_IE_BUFFER_SIZE) { |
| /* Give an warning msg when IE is going to be |
| * truncated. |
| */ |
| DBGLOG(SCN, ERROR, |
| "IE len(%u) > Max IE buffer size(%u), truncate IE!\n", |
| u2IELength, CFG_IE_BUFFER_SIZE); |
| u2IELength = CFG_IE_BUFFER_SIZE; |
| } |
| kalMemZero(&rSsid, sizeof(rSsid)); |
| 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); |
| } |
| } |
| 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_HT_OP: |
| if (IE_LEN(pucIE) == (sizeof(struct IE_HT_OP) - 2)) |
| ucIeHtChannelNum = ((struct IE_HT_OP *) pucIE) |
| ->ucPrimaryChannel; |
| break; |
| #if CFG_SUPPORT_DISABLE_OBSS_SCAN |
| case ELEM_ID_OBSS_SCAN_PARAMS: |
| pucObssScanIE = pucIE; |
| u2ObssScanOffset = u2Offset; |
| break; |
| #endif |
| default: |
| break; |
| } |
| } |
| |
| #if CFG_SUPPORT_DISABLE_OBSS_SCAN |
| if (pucObssScanIE) { |
| u2ObssScanIESize = IE_SIZE(pucObssScanIE); |
| /* delete the obss scan ie */ |
| if ((u2ObssScanOffset + 2 <= u2IELength) && |
| (u2ObssScanOffset + u2ObssScanIESize <= u2IELength)) { |
| kalMemCopy(pucObssScanIE, |
| pucObssScanIE + u2ObssScanIESize, |
| u2IELength - u2ObssScanOffset - u2ObssScanIESize); |
| } |
| |
| prSwRfb->u2PacketLen -= u2ObssScanIESize; |
| u2IELength -= u2ObssScanIESize; |
| DBGLOG(SCN, WARN, "Delete OBSS IE in Bcn/PrbRsp\n"); |
| } |
| #endif |
| |
| /** |
| * Set band mismatch flag if we receive Beacon/ProbeResp in 2.4G band, |
| * but the channel num in IE info is 5G, and vice versa |
| * We can get channel num from different IE info, we select |
| * ELEM_ID_DS_PARAM_SET first, and then ELEM_ID_HT_OP |
| * If we don't have any channel info, we set it as HW channel, which is |
| * the channel we get this Beacon/ProbeResp from. |
| */ |
| if (ucIeDsChannelNum > 0) { |
| if (ucIeDsChannelNum <= HW_CHNL_NUM_MAX_2G4) |
| fgBandMismatch = (eHwBand != BAND_2G4); |
| else if (ucIeDsChannelNum < HW_CHNL_NUM_MAX_4G_5G) |
| fgBandMismatch = (eHwBand != BAND_5G); |
| } else if (ucIeHtChannelNum > 0) { |
| if (ucIeHtChannelNum <= HW_CHNL_NUM_MAX_2G4) |
| fgBandMismatch = (eHwBand != BAND_2G4); |
| else if (ucIeHtChannelNum < HW_CHNL_NUM_MAX_4G_5G) |
| fgBandMismatch = (eHwBand != BAND_5G); |
| } |
| |
| if (fgBandMismatch) { |
| log_dbg(SCN, INFO, MACSTR "Band mismatch, HW band %d, DS chnl %d, HT chnl %d\n", |
| MAC2STR(prWlanBeaconFrame->aucBSSID), eHwBand, |
| ucIeDsChannelNum, ucIeHtChannelNum); |
| return NULL; |
| } |
| |
| /* 4 <1.2> Replace existing BSS_DESC structure or allocate a new one */ |
| prBssDesc = scanSearchExistingBssDescWithSsid( |
| prAdapter, |
| eBSSType, |
| (uint8_t *) prWlanBeaconFrame->aucBSSID, |
| (uint8_t *) prWlanBeaconFrame->aucSrcAddr, |
| fgIsValidSsid, fgIsValidSsid == TRUE ? &rSsid : NULL); |
| |
| log_dbg(SCN, TRACE, "Receive type %u in chnl %u %u %u (" MACSTR |
| ") valid(%u) found(%u)\n", |
| ucSubtype, ucIeDsChannelNum, ucIeHtChannelNum, |
| HAL_RX_STATUS_GET_CHNL_NUM(prSwRfb->prRxStatus), |
| MAC2STR((uint8_t *)prWlanBeaconFrame->aucBSSID), fgIsValidSsid, |
| (prBssDesc != NULL) ? 1 : 0); |
| |
| if ((prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) |
| == MAC_FRAME_PROBE_RSP) |
| fgIsProbeResp = TRUE; |
| |
| if (prBssDesc == (struct BSS_DESC *) NULL) { |
| fgIsNewBssDesc = TRUE; |
| |
| do { |
| /* check if it is a beacon frame */ |
| if (!fgIsProbeResp && !fgIsValidSsid) { |
| log_dbg(SCN, LOUD, "scanAddToBssDescssid is NULL Beacon, don't add hidden BSS(" |
| MACSTR ")\n", |
| MAC2STR((uint8_t *) |
| prWlanBeaconFrame->aucBSSID)); |
| return NULL; |
| } |
| /* 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)); |
| |
| /* 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)); |
| |
| /* 4 <1.2.5> reallocation */ |
| prBssDesc = scanAllocateBssDesc(prAdapter); |
| if (prBssDesc) |
| break; |
| /* 4 <1.2.6> no space, should not happen */ |
| log_limited_dbg(SCN, WARN, "alloc new BssDesc for " |
| MACSTR " failed\n", |
| MAC2STR((uint8_t *) |
| prWlanBeaconFrame->aucBSSID)); |
| 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) { |
| /* for signal strength is too much weaker and |
| * previous beacon is not stale |
| */ |
| uint8_t ucRcpi = 0; |
| ASSERT(prSwRfb->prRxStatusGroup3); |
| ucRcpi = nicRxGetRcpiValueFromRxv(RCPI_MODE_MAX, |
| prSwRfb); |
| if (prBssDesc->ucRCPI > ucRcpi) { |
| if ((prBssDesc->ucRCPI - ucRcpi) |
| >= REPLICATED_BEACON_STRENGTH_THRESHOLD |
| && rCurrentTime - prBssDesc->rUpdateTime |
| <= REPLICATED_BEACON_FRESH_PERIOD) { |
| log_dbg(SCN, TRACE, "rssi(%u) is too much weaker and previous one(%u) is fresh\n", |
| ucRcpi, prBssDesc->ucRCPI); |
| return prBssDesc; |
| } |
| } |
| /* for received beacons too close in time domain */ |
| else if (rCurrentTime - prBssDesc->rUpdateTime |
| <= REPLICATED_BEACON_TIME_THRESHOLD && prAisBssInfo->ucDTIMPeriod != 0) { |
| log_dbg(SCN, TRACE, "receive beacon/probe responses too soon(%u:%u)\n", |
| prBssDesc->rUpdateTime, rCurrentTime); |
| 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) { |
| u_int8_t 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) { |
| log_dbg(SCN, WARN, "Realloc BssDesc for " |
| MACSTR " failed\n", |
| MAC2STR((uint8_t *) |
| prWlanBeaconFrame->aucBSSID)); |
| return NULL; |
| } |
| |
| /* restore */ |
| if (fgIsConnected) { |
| prAdapter-> |
| rWifiVar.rAisFsmInfo.prTargetBssDesc = |
| prBssDesc; |
| DBGLOG(SCN, WARN, "Update prTargetBssDesc!\n"); |
| } |
| prBssDesc->fgIsConnected = fgIsConnected; |
| prBssDesc->fgIsConnecting = fgIsConnecting; |
| } |
| } |
| |
| prBssDesc->fgIsValidSSID = fgIsValidSsid; |
| prBssDesc->u2RawLength = prSwRfb->u2PacketLen; |
| if (prBssDesc->u2RawLength > CFG_RAW_BUFFER_SIZE) { |
| prBssDesc->u2RawLength = CFG_RAW_BUFFER_SIZE; |
| /* Give an warning msg when content is going to be |
| * truncated. |
| */ |
| DBGLOG(SCN, WARN, |
| "Pkt len(%u) > Max RAW buffer size(%u), truncate it!\n", |
| prSwRfb->u2PacketLen, CFG_RAW_BUFFER_SIZE); |
| } |
| if (fgIsProbeResp || fgIsValidSsid) { |
| kalMemCopy(prBssDesc->aucRawBuf, prWlanBeaconFrame, |
| prBssDesc->u2RawLength); |
| } |
| |
| /* NOTE: Keep consistency of Scan Record during JOIN process */ |
| /* NOTE: AP channel which has been changed may be bss update */ |
| /* like a new bss desc case */ |
| if ((fgIsNewBssDesc == FALSE) && (prBssDesc->fgIsConnecting) && |
| (prBssDesc->ucChannelNum |
| == HAL_RX_STATUS_GET_CHNL_NUM(prSwRfb->prRxStatus))) { |
| log_dbg(SCN, TRACE, "we're connecting this BSS(" |
| MACSTR ") now, don't update it\n", |
| MAC2STR(prBssDesc->aucBSSID)); |
| return prBssDesc; |
| } |
| /* 4 <2> Get information from Fixed Fields */ |
| /* Update the latest BSS type information. */ |
| prBssDesc->eBSSType = eBSSType; |
| |
| 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) - |
| (uint16_t) OFFSET_OF(struct WLAN_BEACON_FRAME_BODY, 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; |
| |
| if (fgIsProbeResp || fgIsValidSsid) { |
| 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; |
| |
| /*Reset VHT OP IE relative settings */ |
| prBssDesc->eChannelWidth = CW_20_40MHZ; |
| |
| prBssDesc->ucCenterFreqS1 = 0; |
| prBssDesc->ucCenterFreqS2 = 0; |
| |
| /* Support AP Selection */ |
| prBssDesc->fgExsitBssLoadIE = FALSE; |
| prBssDesc->fgMultiAnttenaAndSTBC = FALSE; |
| |
| if (fgIsProbeResp == FALSE) { |
| /* Probe response doesn't have TIM IE. Thus, we should |
| * reset TIM when handling beacon frame only. |
| */ |
| prBssDesc->fgTIMPresent = FALSE; |
| prBssDesc->ucDTIMPeriod = 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)) { |
| u_int8_t fgIsHiddenSSID = FALSE; |
| |
| ucSSIDChar = '\0'; |
| |
| prIeSsid = (struct IE_SSID *) 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); |
| } else if (fgIsProbeResp) { |
| /* SSID should be updated |
| * if it is ProbeResp |
| */ |
| kalMemZero(prBssDesc->aucSSID, |
| sizeof(prBssDesc->aucSSID)); |
| prBssDesc->ucSSIDLen = 0; |
| } |
| |
| } |
| 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_IOT_IE(pucIE); |
| break; |
| |
| case ELEM_ID_TIM: |
| if (IE_LEN(pucIE) <= ELEM_MAX_LEN_TIM) { |
| prBssDesc->fgTIMPresent = TRUE; |
| 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; |
| |
| case ELEM_ID_COUNTRY_INFO: |
| prCountryIE = (struct IE_COUNTRY *) pucIE; |
| break; |
| |
| 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: |
| { |
| /* Support AP Selection */ |
| struct IE_HT_CAP *prHtCap = (struct IE_HT_CAP *)pucIE; |
| uint8_t ucSpatial = 0; |
| uint8_t i = 0; |
| |
| /* end Support AP Selection */ |
| if (IE_LEN(pucIE) != (sizeof(struct IE_HT_CAP) - 2)) { |
| DBGLOG(SCN, WARN, |
| "HT_CAP wrong length(%d)->(%d)\n", |
| (sizeof(struct IE_HT_CAP) - 2), |
| IE_LEN(prHtCap)); |
| break; |
| } |
| |
| prBssDesc->fgIsHTPresent = TRUE; |
| |
| /* Support AP Selection */ |
| if (prBssDesc->fgMultiAnttenaAndSTBC) |
| break; |
| |
| for (; i < 4; i++) { |
| if (prHtCap->rSupMcsSet.aucRxMcsBitmask[i] > 0) |
| ucSpatial++; |
| } |
| |
| prBssDesc->fgMultiAnttenaAndSTBC = |
| ((ucSpatial > 1) && |
| (prHtCap->u2HtCapInfo & HT_CAP_INFO_TX_STBC)); |
| /* end Support AP Selection */ |
| |
| break; |
| } |
| case ELEM_ID_HT_OP: |
| if (IE_LEN(pucIE) != (sizeof(struct IE_HT_OP) - 2)) |
| break; |
| |
| if ((((struct IE_HT_OP *) pucIE)->ucInfo1 |
| & HT_OP_INFO1_SCO) != CHNL_EXT_RES) { |
| prBssDesc->eSco = (enum ENUM_CHNL_EXT) |
| (((struct IE_HT_OP *) pucIE)->ucInfo1 |
| & HT_OP_INFO1_SCO); |
| } |
| break; |
| case ELEM_ID_VHT_CAP: |
| { |
| /* Support AP Selection*/ |
| struct IE_VHT_CAP *prVhtCap = |
| (struct IE_VHT_CAP *)pucIE; |
| uint16_t u2TxMcsSet = 0; |
| uint8_t ucSpatial = 0; |
| uint8_t i = 0; |
| /* end Support AP Selection */ |
| |
| /* Error handling */ |
| if (IE_LEN(prVhtCap) != |
| (sizeof(struct IE_VHT_CAP) - 2)) { |
| DBGLOG(SCN, WARN, |
| "VhtCap wrong length!(%d)->(%d)\n", |
| (sizeof(struct IE_VHT_CAP) - 2), |
| IE_LEN(prVhtCap)); |
| break; |
| } |
| |
| u2TxMcsSet = prVhtCap->rVhtSupportedMcsSet.u2TxMcsMap; |
| prBssDesc->fgIsVHTPresent = TRUE; |
| #if CFG_SUPPORT_BFEE |
| #define __LOCAL_VAR__ \ |
| VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS_OFFSET |
| |
| prBssDesc->ucVhtCapNumSoundingDimensions = |
| ((((struct IE_VHT_CAP *) pucIE)->u4VhtCapInfo) |
| & VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS) |
| >> __LOCAL_VAR__; |
| #undef __LOCAL_VAR__ |
| #endif |
| /* Support AP Selection*/ |
| if (prBssDesc->fgMultiAnttenaAndSTBC) |
| break; |
| for (; i < 8; i++) { |
| if ((u2TxMcsSet & BITS(2*i, 2*i+1)) != 3) |
| ucSpatial++; |
| } |
| prBssDesc->fgMultiAnttenaAndSTBC = |
| ((ucSpatial > 1) && (prVhtCap->u4VhtCapInfo & |
| VHT_CAP_INFO_TX_STBC)); |
| /* end Support AP Selection */ |
| break; |
| } |
| case ELEM_ID_VHT_OP: |
| if (IE_LEN(pucIE) != (sizeof(struct IE_VHT_OP) - 2)) |
| break; |
| |
| prBssDesc->eChannelWidth = (enum ENUM_CHANNEL_WIDTH) |
| (((struct IE_VHT_OP *) pucIE) |
| ->ucVhtOperation[0]); |
| prBssDesc->ucCenterFreqS1 = (enum ENUM_CHANNEL_WIDTH) |
| (((struct IE_VHT_OP *) pucIE) |
| ->ucVhtOperation[1]); |
| prBssDesc->ucCenterFreqS2 = (enum ENUM_CHANNEL_WIDTH) |
| (((struct IE_VHT_OP *) pucIE) |
| ->ucVhtOperation[2]); |
| |
| /*add IEEE BW160 patch*/ |
| rlmModifyVhtBwPara(&prBssDesc->ucCenterFreqS1, |
| &prBssDesc->ucCenterFreqS2, |
| (uint8_t *)&prBssDesc->eChannelWidth); |
| |
| |
| |
| break; |
| #if CFG_SUPPORT_WAPI |
| case ELEM_ID_WAPI: |
| if (wapiParseWapiIE(WAPI_IE(pucIE), |
| &prBssDesc->rIEWAPI)) |
| prBssDesc->fgIEWAPI = TRUE; |
| break; |
| #endif |
| /* Support AP Selection */ |
| case ELEM_ID_BSS_LOAD: |
| { |
| struct IE_BSS_LOAD *prBssLoad = |
| (struct IE_BSS_LOAD *)pucIE; |
| |
| if (IE_LEN(prBssLoad) != |
| (sizeof(struct IE_BSS_LOAD) - 2)) { |
| DBGLOG(SCN, WARN, |
| "HE_CAP IE_LEN err(%d)->(%d)!\n", |
| (sizeof(struct IE_BSS_LOAD) - 2), |
| IE_LEN(prBssLoad)); |
| break; |
| } |
| |
| prBssDesc->u2StaCnt = prBssLoad->u2StaCnt; |
| prBssDesc->ucChnlUtilization = |
| prBssLoad->ucChnlUtilizaion; |
| prBssDesc->u2AvaliableAC = prBssLoad->u2AvailabeAC; |
| prBssDesc->fgExsitBssLoadIE = TRUE; |
| break; |
| } |
| /* end Support AP Selection */ |
| |
| case ELEM_ID_VENDOR: /* ELEM_ID_P2P, ELEM_ID_WMM */ |
| { |
| uint8_t ucOuiType; |
| uint16_t 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_SUPPORT_PASSPOINT |
| /* since OSEN is mutual exclusion with RSN, so |
| * we reuse RSN here |
| */ |
| if ((pucIE[1] >= 10) |
| && (kalMemCmp(pucIE+2, |
| "\x50\x6f\x9a\x12", 4) == 0) |
| && (rsnParseOsenIE(prAdapter, |
| (struct IE_WFA_OSEN *)pucIE, |
| &prBssDesc->rRSNInfo))) |
| prBssDesc->fgIEOsen = TRUE; |
| #endif |
| #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; |
| case ELEM_ID_PWR_CONSTRAINT: |
| { |
| struct IE_POWER_CONSTRAINT *prPwrConstraint = |
| (struct IE_POWER_CONSTRAINT *)pucIE; |
| |
| if (IE_LEN(pucIE) != 1) |
| break; |
| ucPowerConstraint = |
| prPwrConstraint->ucLocalPowerConstraint; |
| break; |
| } |
| case ELEM_ID_RRM_ENABLED_CAP: |
| /* RRM Capability IE is always in length 5 bytes */ |
| if (IE_LEN(pucIE) == 5) { |
| kalMemZero(prBssDesc->aucRrmCap, |
| sizeof(prBssDesc->aucRrmCap)); |
| kalMemCopy(prBssDesc->aucRrmCap, pucIE + 2, |
| sizeof(prBssDesc->aucRrmCap)); |
| } |
| 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 */ |
| { |
| struct HW_MAC_RX_DESC *prRxStatus; |
| uint8_t ucRxRCPI; |
| uint8_t ucRxRCPI0; |
| uint8_t ucRxRCPI1; |
| |
| 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 = eHwBand; |
| |
| /* 4 <4.2> Get channel and RCPI information */ |
| ucHwChannelNum = HAL_RX_STATUS_GET_CHNL_NUM(prRxStatus); |
| |
| ASSERT(prSwRfb->prRxStatusGroup3); |
| ucRxRCPI = nicRxGetRcpiValueFromRxv(RCPI_MODE_MAX, prSwRfb); |
| ucRxRCPI0 = nicRxGetRcpiValueFromRxv(RCPI_MODE_WF0, prSwRfb); |
| ucRxRCPI1 = nicRxGetRcpiValueFromRxv(RCPI_MODE_WF1, 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; |
| prBssDesc->ucRCPI0 = ucRxRCPI0; |
| prBssDesc->ucRCPI1 = ucRxRCPI1; |
| } |
| /* 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; |
| prBssDesc->ucRCPI0 = ucRxRCPI0; |
| prBssDesc->ucRCPI1 = ucRxRCPI1; |
| } |
| /* trust channel information brought by IE */ |
| prBssDesc->ucChannelNum = ucIeHtChannelNum; |
| } else { |
| prBssDesc->ucRCPI = ucRxRCPI; |
| prBssDesc->ucRCPI0 = ucRxRCPI0; |
| prBssDesc->ucRCPI1 = ucRxRCPI1; |
| |
| 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; |
| prBssDesc->ucRCPI0 = ucRxRCPI0; |
| prBssDesc->ucRCPI1 = ucRxRCPI1; |
| } |
| /* trust channel information brought by IE */ |
| prBssDesc->ucChannelNum = ucIeHtChannelNum; |
| } else { |
| /* Always update RCPI */ |
| prBssDesc->ucRCPI = ucRxRCPI; |
| prBssDesc->ucRCPI0 = ucRxRCPI0; |
| prBssDesc->ucRCPI1 = ucRxRCPI1; |
| |
| 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)) { |
| #if 0 /* TODO: Remove this */ |
| /* Dump IE Inforamtion */ |
| log_dbg(RLM, WARN, "ScanAddToBssDesc IE Information\n"); |
| log_dbg(RLM, WARN, "IE Length = %d\n", u2IELength); |
| log_mem8_dbg(RLM, WARN, pucDumpIE, u2IELength); |
| #endif |
| |
| /* 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; |
| } |
| #if CFG_SUPPORT_802_11K |
| if (prCountryIE && prCountryIE->ucLength == |
| (sizeof(struct IE_COUNTRY) - 2)) { |
| uint8_t ucRemainLen = prCountryIE->ucLength - 3; |
| struct COUNTRY_INFO_SUBBAND_TRIPLET *prSubBand = |
| &prCountryIE->arCountryStr[0]; |
| const uint8_t ucSubBandSize = |
| (uint8_t)sizeof(struct COUNTRY_INFO_SUBBAND_TRIPLET); |
| int8_t cNewPwrLimit = RLM_INVALID_POWER_LIMIT; |
| |
| /* Try to find a country subband base on our channel */ |
| while (ucRemainLen >= ucSubBandSize) { |
| if (prSubBand->ucFirstChnlNum < 201 && |
| prBssDesc->ucChannelNum >= |
| prSubBand->ucFirstChnlNum && |
| prBssDesc->ucChannelNum <= |
| (prSubBand->ucFirstChnlNum + |
| prSubBand->ucNumOfChnl - 1)) |
| break; |
| ucRemainLen -= ucSubBandSize; |
| prSubBand++; |
| } |
| /* Found a right country band */ |
| if (ucRemainLen >= ucSubBandSize) { |
| cNewPwrLimit = |
| prSubBand->cMaxTxPwrLv - ucPowerConstraint; |
| /* Limit Tx power changed */ |
| if (prBssDesc->cPowerLimit != cNewPwrLimit) { |
| prBssDesc->cPowerLimit = cNewPwrLimit; |
| DBGLOG(SCN, TRACE, |
| "LM: Old TxPwrLimit %d,New: CountryMax %d, Constraint %d\n", |
| prBssDesc->cPowerLimit, |
| prSubBand->cMaxTxPwrLv, |
| ucPowerConstraint); |
| /* should tell firmware to restrict tx power if |
| ** connected a BSS |
| */ |
| if (prBssDesc->fgIsConnected) { |
| if (prBssDesc->cPowerLimit != |
| RLM_INVALID_POWER_LIMIT) |
| rlmSetMaxTxPwrLimit( |
| prAdapter, |
| prBssDesc->cPowerLimit, |
| 1); |
| else |
| rlmSetMaxTxPwrLimit(prAdapter, |
| 0, 0); |
| } |
| } |
| } else if (prBssDesc->cPowerLimit != RLM_INVALID_POWER_LIMIT |
| && prBssDesc->fgIsConnected) { |
| prBssDesc->cPowerLimit = RLM_INVALID_POWER_LIMIT; |
| rlmSetMaxTxPwrLimit(prAdapter, 0, 0); |
| } |
| } else if (prBssDesc->cPowerLimit != RLM_INVALID_POWER_LIMIT |
| && prBssDesc->fgIsConnected) { |
| prBssDesc->cPowerLimit = RLM_INVALID_POWER_LIMIT; |
| rlmSetMaxTxPwrLimit(prAdapter, 0, 0); |
| } |
| #endif |
| |
| /* 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 or support OFDM*/ |
| if (!(prBssDesc->u2BSSBasicRateSet & RATE_SET_BIT_HT_PHY) |
| || (prBssDesc->u2BSSBasicRateSet & RATE_SET_OFDM)) { |
| /* Support 11a definitely */ |
| prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_OFDM; |
| |
| #if 0 /* TODO: Remove this */ |
| ASSERT(!(prBssDesc->u2OperationalRateSet |
| & RATE_SET_HR_DSSS)); |
| #endif |
| } |
| } |
| |
| /* Support AP Selection */ |
| /* update update-index and reset seen-probe-response */ |
| if (prBssDesc->u4UpdateIdx != |
| prAdapter->rWifiVar.rScanInfo.u4ScanUpdateIdx) { |
| prBssDesc->fgSeenProbeResp = FALSE; |
| prBssDesc->u4UpdateIdx = |
| prAdapter->rWifiVar.rScanInfo.u4ScanUpdateIdx; |
| } |
| |
| /* check if it is a probe response frame */ |
| if (fgIsProbeResp) |
| prBssDesc->fgSeenProbeResp = TRUE; |
| /* end Support AP Selection */ |
| /* 4 <7> Update BSS_DESC_T's Last Update TimeStamp. */ |
| if (fgIsProbeResp || fgIsValidSsid) |
| GET_CURRENT_SYSTIME(&prBssDesc->rUpdateTime); |
| |
| #if CFG_SUPPORT_802_11K |
| if (prBssDesc->fgIsConnected) |
| rlmUpdateBssTimeTsf(prAdapter, prBssDesc); |
| #endif |
| |
| return prBssDesc; |
| } |
| |
| /* clear all ESS scan result */ |
| void scanInitEssResult(struct ADAPTER *prAdapter) |
| { |
| prAdapter->rWlanInfo.u4ScanResultEssNum = 0; |
| prAdapter->rWlanInfo.u4ScanDbgTimes1 = 0; |
| prAdapter->rWlanInfo.u4ScanDbgTimes2 = 0; |
| prAdapter->rWlanInfo.u4ScanDbgTimes3 = 0; |
| prAdapter->rWlanInfo.u4ScanDbgTimes4 = 0; |
| kalMemZero(prAdapter->rWlanInfo.arScanResultEss, |
| sizeof(prAdapter->rWlanInfo.arScanResultEss)); |
| } |
| /* print all ESS into log system once scan done |
| * it is useful to log that, otherwise, we have no information to |
| * identify if hardware has seen a specific AP, |
| * if user complained some AP were not found in scan result list |
| */ |
| void scanLogEssResult(struct ADAPTER *prAdapter) |
| { |
| #define NUMBER_SSID_PER_LINE 16 |
| struct ESS_SCAN_RESULT_T *prEssResult |
| = &prAdapter->rWlanInfo.arScanResultEss[0]; |
| uint32_t u4ResultNum = prAdapter->rWlanInfo.u4ScanResultEssNum; |
| uint32_t u4Index = 0; |
| |
| if (u4ResultNum == 0) { |
| scanlog_dbg(LOG_SCAN_DONE_D2K, STATE, "0 Bss is found, %d, %d, %d, %d\n", |
| prAdapter->rWlanInfo.u4ScanDbgTimes1, |
| prAdapter->rWlanInfo.u4ScanDbgTimes2, |
| prAdapter->rWlanInfo.u4ScanDbgTimes3, |
| prAdapter->rWlanInfo.u4ScanDbgTimes4); |
| return; |
| } |
| |
| scanlog_dbg(LOG_SCAN_DONE_D2K, STATE, "Total:%u/%u; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s\n", |
| u4ResultNum, prAdapter->rWlanInfo.u4ScanResultNum, |
| prEssResult[0].aucSSID, prEssResult[1].aucSSID, |
| prEssResult[2].aucSSID, prEssResult[3].aucSSID, |
| prEssResult[4].aucSSID, prEssResult[5].aucSSID, |
| prEssResult[6].aucSSID, prEssResult[7].aucSSID, |
| prEssResult[8].aucSSID, prEssResult[9].aucSSID, |
| prEssResult[10].aucSSID, prEssResult[11].aucSSID, |
| prEssResult[12].aucSSID, prEssResult[13].aucSSID, |
| prEssResult[14].aucSSID, prEssResult[15].aucSSID); |
| |
| if (u4ResultNum <= NUMBER_SSID_PER_LINE) |
| return; |
| |
| u4ResultNum = u4ResultNum / NUMBER_SSID_PER_LINE; |
| if ((u4ResultNum % NUMBER_SSID_PER_LINE) != 0) |
| u4ResultNum++; |
| for (u4Index = 1; u4Index < u4ResultNum; u4Index++) { |
| struct ESS_SCAN_RESULT_T *prEss |
| = &prEssResult[NUMBER_SSID_PER_LINE*u4Index]; |
| |
| scanlog_dbg(LOG_SCAN_DONE_D2K, STATE, "%s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s\n", |
| prEss[0].aucSSID, prEss[1].aucSSID, |
| prEss[2].aucSSID, prEss[3].aucSSID, |
| prEss[4].aucSSID, prEss[5].aucSSID, |
| prEss[6].aucSSID, prEss[7].aucSSID, |
| prEss[8].aucSSID, prEss[9].aucSSID, |
| prEss[10].aucSSID, prEss[11].aucSSID, |
| prEss[12].aucSSID, prEss[13].aucSSID, |
| prEss[14].aucSSID, prEss[15].aucSSID); |
| } |
| } |
| |
| /* record all Scanned ESS, only one BSS was saved for each ESS, and AP who |
| * is hidden ssid was excluded. |
| */ |
| /* maximum we only support record 64 ESSes */ |
| static void scanAddEssResult(struct ADAPTER *prAdapter, |
| IN struct BSS_DESC *prBssDesc) |
| { |
| struct ESS_SCAN_RESULT_T *prEssResult |
| = &prAdapter->rWlanInfo.arScanResultEss[0]; |
| uint32_t u4Index = 0; |
| |
| if (prBssDesc->fgIsHiddenSSID) |
| return; |
| if (prAdapter->rWlanInfo.u4ScanResultEssNum >= CFG_MAX_NUM_BSS_LIST) |
| return; |
| for (; u4Index < prAdapter->rWlanInfo.u4ScanResultEssNum; u4Index++) { |
| if (EQUAL_SSID(prEssResult[u4Index].aucSSID, |
| (uint8_t)prEssResult[u4Index].u2SSIDLen, |
| prBssDesc->aucSSID, prBssDesc->ucSSIDLen)) |
| return; |
| } |
| |
| COPY_SSID(prEssResult[u4Index].aucSSID, prEssResult[u4Index].u2SSIDLen, |
| prBssDesc->aucSSID, prBssDesc->ucSSIDLen); |
| COPY_MAC_ADDR(prEssResult[u4Index].aucBSSID, prBssDesc->aucBSSID); |
| prAdapter->rWlanInfo.u4ScanResultEssNum++; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @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. |
| */ |
| /*----------------------------------------------------------------------------*/ |
| uint32_t scanAddScanResult(IN struct ADAPTER *prAdapter, |
| IN struct BSS_DESC *prBssDesc, |
| IN struct SW_RFB *prSwRfb) |
| { |
| struct SCAN_INFO *prScanInfo; |
| uint8_t aucRatesEx[PARAM_MAX_LEN_RATES_EX]; |
| struct WLAN_BEACON_FRAME *prWlanBeaconFrame; |
| uint8_t rMacAddr[PARAM_MAC_ADDR_LEN]; |
| struct PARAM_SSID rSsid; |
| enum ENUM_PARAM_NETWORK_TYPE eNetworkType; |
| struct PARAM_802_11_CONFIG rConfiguration; |
| enum ENUM_PARAM_OP_MODE eOpMode; |
| uint8_t ucRateLen = 0; |
| uint32_t 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) */ |
| log_dbg(SCN, INFO, "Bss Desc type is P2P\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| prWlanBeaconFrame = (struct WLAN_BEACON_FRAME *) prSwRfb->pvHeader; |
| COPY_MAC_ADDR(rMacAddr, prWlanBeaconFrame->aucBSSID); |
| COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, |
| prBssDesc->aucSSID, prBssDesc->ucSSIDLen); |
| |
| rConfiguration.u4Length = sizeof(struct PARAM_802_11_CONFIG); |
| rConfiguration.u4BeaconPeriod |
| = (uint32_t) prWlanBeaconFrame->u2BeaconInterval; |
| rConfiguration.u4ATIMWindow = prBssDesc->u2ATIMWindow; |
| rConfiguration.u4DSConfig = nicChannelNum2Freq(prBssDesc->ucChannelNum); |
| rConfiguration.rFHConfig.u4Length |
| = sizeof(struct PARAM_802_11_CONFIG_FH); |
| |
| rateGetDataRatesFromRateSet(prBssDesc->u2OperationalRateSet, |
| (uint16_t)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; |
| } |
| |
| log_dbg(SCN, TRACE, "ind %s %d %d\n", prBssDesc->aucSSID, |
| prBssDesc->ucChannelNum, prBssDesc->ucRCPI); |
| |
| scanAddEssResult(prAdapter, prBssDesc); |
| if (prAdapter->rWifiVar.rScanInfo.fgSchedScanning && |
| test_bit(SUSPEND_FLAG_CLEAR_WHEN_RESUME, |
| &prAdapter->ulSuspendFlag)) { |
| uint8_t i = 0; |
| struct BSS_DESC **pprPendBssDesc |
| = &prScanInfo->rSchedScanParam. |
| aprPendingBssDescToInd[0]; |
| |
| for (; i < SCN_SSID_MATCH_MAX_NUM; i++) { |
| if (pprPendBssDesc[i]) |
| continue; |
| log_dbg(SCN, INFO, "indicate bss[" |
| MACSTR |
| "] before wiphy resume, need to indicate again after wiphy resume\n", |
| MAC2STR(prBssDesc->aucBSSID)); |
| pprPendBssDesc[i] = prBssDesc; |
| break; |
| } |
| } |
| |
| if (prBssDesc->fgIsValidSSID) { |
| kalIndicateBssInfo(prAdapter->prGlueInfo, |
| (uint8_t *) prSwRfb->pvHeader, |
| prSwRfb->u2PacketLen, |
| prBssDesc->ucChannelNum, |
| RCPI_TO_dBm(prBssDesc->ucRCPI)); |
| } |
| |
| nicAddScanResult(prAdapter, |
| rMacAddr, |
| &rSsid, |
| prWlanBeaconFrame->u2CapInfo, |
| RCPI_TO_dBm(prBssDesc->ucRCPI), |
| eNetworkType, |
| &rConfiguration, |
| eOpMode, |
| aucRatesEx, |
| prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen, |
| (uint8_t *) ((unsigned long) (prSwRfb->pvHeader) |
| + WLAN_MAC_MGMT_HEADER_LEN)); |
| |
| return WLAN_STATUS_SUCCESS; |
| |
| } /* end of scanAddScanResult() */ |
| |
| u_int8_t scanCheckBssIsLegal(IN struct ADAPTER *prAdapter, |
| struct BSS_DESC *prBssDesc) |
| { |
| u_int8_t fgAddToScanResult = FALSE; |
| enum ENUM_BAND eBand; |
| uint8_t 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 |
| */ |
| /*----------------------------------------------------------------------------*/ |
| uint32_t scanProcessBeaconAndProbeResp(IN struct ADAPTER *prAdapter, |
| IN struct SW_RFB *prSwRfb) |
| { |
| struct SCAN_INFO *prScanInfo; |
| struct CONNECTION_SETTINGS *prConnSettings; |
| struct BSS_DESC *prBssDesc = (struct BSS_DESC *) NULL; |
| uint32_t rStatus = WLAN_STATUS_SUCCESS; |
| struct BSS_INFO *prAisBssInfo; |
| struct WLAN_BEACON_FRAME *prWlanBeaconFrame |
| = (struct WLAN_BEACON_FRAME *) NULL; |
| #if CFG_SLT_SUPPORT |
| struct SLT_INFO *prSltInfo = (struct SLT_INFO *) NULL; |
| #endif |
| |
| ASSERT(prAdapter); |
| ASSERT(prSwRfb); |
| |
| #if CFG_SUPPORT_802_11K |
| /* if beacon request measurement is on-going, collect Beacon Report */ |
| if (rlmBcnRmRunning(prAdapter)) { |
| rlmProcessBeaconAndProbeResp(prAdapter, prSwRfb); |
| return WLAN_STATUS_SUCCESS; |
| } |
| #endif |
| |
| 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)) { |
| log_dbg(SCN, ERROR, "Ignore invalid Beacon Frame\n"); |
| return rStatus; |
| } |
| |
| scanResultLog(prAdapter, prSwRfb); |
| |
| #if CFG_SLT_SUPPORT |
| prSltInfo = &prAdapter->rWifiVar.rSltInfo; |
| |
| if (prSltInfo->fgIsDUT) { |
| log_dbg(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 = (struct WLAN_BEACON_FRAME *) prSwRfb->pvHeader; |
| |
| /* 4 <1> Parse and add into BSS_DESC_T */ |
| prBssDesc = scanAddToBssDesc(prAdapter, prSwRfb); |
| prAdapter->rWlanInfo.u4ScanDbgTimes1++; |
| |
| if (prBssDesc) { |
| /* Full2Partial: save channel info for later scan */ |
| if (prScanInfo->fgIsScanForFull2Partial) { |
| log_dbg(SCN, TRACE, "Full2Partial: set channel=%d\n", |
| prBssDesc->ucChannelNum); |
| scanSetBit(prBssDesc->ucChannelNum, |
| prScanInfo->au4ChannelBitMap, |
| sizeof(prScanInfo->au4ChannelBitMap)); |
| } |
| |
| /* 4 <1.1> Beacon Change Detection for Connected BSS */ |
| if ((prAisBssInfo != NULL) && |
| (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)) { |
| #if CFG_SUPPORT_BEACON_CHANGE_DETECTION |
| u_int8_t fgNeedDisconnect = FALSE; |
| |
| /* <1.1.2> check if supported rate differs */ |
| if (prAisBssInfo->u2OperationalRateSet |
| != prBssDesc->u2OperationalRateSet) |
| fgNeedDisconnect = TRUE; |
| #endif |
| if (rsnCheckSecurityModeChanged(prAdapter, |
| prAisBssInfo, prBssDesc) |
| #if CFG_SUPPORT_WAPI |
| || (prAdapter->rWifiVar.rConnSettings |
| .fgWapiMode == TRUE && |
| !wapiPerformPolicySelection(prAdapter, |
| prBssDesc)) |
| #endif |
| ) { |
| |
| log_dbg(SCN, INFO, "Beacon security mode change detected\n"); |
| log_mem8_dbg(SCN, INFO, |
| prSwRfb->pvHeader, |
| prSwRfb->u2PacketLen); |
| #if CFG_SUPPORT_BEACON_CHANGE_DETECTION |
| fgNeedDisconnect = FALSE; |
| #endif |
| if (!prConnSettings |
| ->fgSecModeChangeStartTimer) { |
| cnmTimerStartTimer(prAdapter, |
| &prAdapter->rWifiVar |
| .rAisFsmInfo |
| .rSecModeChangeTimer, |
| SEC_TO_MSEC(3)); |
| prConnSettings |
| ->fgSecModeChangeStartTimer |
| = TRUE; |
| } |
| } else { |
| if (prConnSettings->fgSecModeChangeStartTimer) { |
| cnmTimerStopTimer(prAdapter, |
| &prAdapter->rWifiVar |
| .rAisFsmInfo |
| .rSecModeChangeTimer); |
| prConnSettings |
| ->fgSecModeChangeStartTimer |
| = FALSE; |
| } |
| } |
| |
| #if CFG_SUPPORT_BEACON_CHANGE_DETECTION |
| /* <1.1.3> beacon content change detected, |
| * disconnect immediately |
| */ |
| if (fgNeedDisconnect == TRUE) |
| aisBssBeaconTimeout(prAdapter); |
| #endif |
| } |
| /* 4 <1.1> Update AIS_BSS_INFO */ |
| if ((prAisBssInfo != NULL) && |
| ((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 |
| */ |
| log_dbg(SCN, TRACE, "DTIMPeriod[%u] Present[%u] BSSID[" |
| MACSTR "]\n", |
| prAisBssInfo->ucDTIMPeriod, |
| prAisBssInfo->fgTIMPresent, |
| MAC2STR(prBssDesc->aucBSSID)); |
| if ((!prAisBssInfo->ucDTIMPeriod) && |
| prAisBssInfo->fgTIMPresent && |
| EQUAL_MAC_ADDR(prBssDesc->aucBSSID, |
| prAisBssInfo->aucBSSID) && |
| (prAisBssInfo->eCurrentOPMode |
| == OP_MODE_INFRASTRUCTURE) && |
| ((prWlanBeaconFrame->u2FrameCtrl |
| & MASK_FRAME_TYPE) |
| == MAC_FRAME_BEACON)) { |
| prAisBssInfo->ucDTIMPeriod |
| = prBssDesc->ucDTIMPeriod; |
| prAisBssInfo->fgTIMPresent |
| = prBssDesc->fgTIMPresent; |
| |
| /* Handle No TIM IE information case */ |
| if (!prAisBssInfo->fgTIMPresent) { |
| enum PARAM_POWER_MODE ePwrMode |
| = Param_PowerModeCAM; |
| |
| log_dbg(SCN, WARN, "IE TIM absence, set to CAM mode!\n"); |
| nicConfigPowerSaveProfile( |
| prAdapter, |
| prAisBssInfo-> |
| ucBssIndex, ePwrMode, |
| FALSE, |
| PS_CALLER_NO_TIM); |
| } |
| /* 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_MAX, |
| prSwRfb)); |
| } |
| #endif /* CFG_SUPPORT_ADHOC */ |
| } |
| |
| rlmProcessBcn(prAdapter, |
| prSwRfb, |
| ((struct WLAN_BEACON_FRAME *) (prSwRfb->pvHeader)) |
| ->aucInfoElem, |
| (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - |
| (uint16_t) (OFFSET_OF(struct WLAN_BEACON_FRAME_BODY, |
| aucInfoElem[0]))); |
| |
| mqmProcessBcn(prAdapter, |
| prSwRfb, |
| ((struct WLAN_BEACON_FRAME *) (prSwRfb->pvHeader)) |
| ->aucInfoElem, |
| (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - |
| (uint16_t) (OFFSET_OF(struct WLAN_BEACON_FRAME_BODY, |
| aucInfoElem[0]))); |
| |
| prAdapter->rWlanInfo.u4ScanDbgTimes2++; |
| |
| /* 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) { |
| u_int8_t fgAddToScanResult = FALSE; |
| |
| /* for AIS, send to host */ |
| prAdapter->rWlanInfo.u4ScanDbgTimes3++; |
| if (prConnSettings->fgIsScanReqIssued |
| || prScanInfo->fgSchedScanning) { |
| fgAddToScanResult |
| = scanCheckBssIsLegal(prAdapter, |
| prBssDesc); |
| prAdapter->rWlanInfo.u4ScanDbgTimes4++; |
| |
| if (fgAddToScanResult == TRUE) { |
| rStatus = scanAddScanResult(prAdapter, |
| prBssDesc, prSwRfb); |
| } |
| } |
| if (fgAddToScanResult == FALSE) { |
| kalMemZero(prBssDesc->aucRawBuf, |
| CFG_RAW_BUFFER_SIZE); |
| prBssDesc->u2RawLength = 0; |
| } |
| } |
| #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 |
| */ |
| /*----------------------------------------------------------------------------*/ |
| struct BSS_DESC *scanSearchBssDescByPolicy( |
| IN struct ADAPTER *prAdapter, IN uint8_t ucBssIndex) |
| { |
| struct CONNECTION_SETTINGS *prConnSettings; |
| struct BSS_INFO *prBssInfo; |
| struct AIS_SPECIFIC_BSS_INFO *prAisSpecBssInfo; |
| struct SCAN_INFO *prScanInfo; |
| |
| struct LINK *prBSSDescList; |
| |
| struct BSS_DESC *prBssDesc = (struct BSS_DESC *) NULL; |
| struct BSS_DESC *prPrimaryBssDesc = (struct BSS_DESC *) NULL; |
| struct BSS_DESC *prCandidateBssDesc = (struct BSS_DESC *) NULL; |
| |
| struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; |
| struct STA_RECORD *prPrimaryStaRec; |
| struct STA_RECORD *prCandidateStaRec = (struct STA_RECORD *) NULL; |
| |
| OS_SYSTIME rCurrentTime; |
| |
| /* The first one reach the check point will be our candidate */ |
| u_int8_t fgIsFindFirst = (u_int8_t) FALSE; |
| |
| u_int8_t fgIsFindBestRSSI = (u_int8_t) FALSE; |
| #if !CFG_SUPPORT_CFG80211_AUTH |
| u_int8_t fgIsFindBestEncryptionLevel = (u_int8_t) FALSE; |
| #endif |
| /* u_int8_t fgIsFindMinChannelLoad = (u_int8_t) FALSE; */ |
| |
| /* TODO(Kevin): Support Min Channel Load */ |
| /* uint8_t aucChannelLoad[CHANNEL_NUM] = {0}; */ |
| |
| u_int8_t fgIsFixedChannel = (u_int8_t) FALSE; |
| enum ENUM_BAND eBand = BAND_2G4; |
| uint8_t ucChannel = 0; |
| uint32_t u4ScnAdhocBssDescTimeout = 0; |
| #if CFG_SUPPORT_NCHO |
| uint8_t ucRCPIStep = ROAMING_NO_SWING_RCPI_STEP; |
| #endif |
| |
| 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 |
| |
| log_dbg(SCN, INFO, "SEARCH: Bss Num: %d, Look for SSID: %s, " |
| MACSTR " Band=%d, channel=%d\n", |
| (uint32_t) prBSSDescList->u4NumElem, prConnSettings->aucSSID, |
| MAC2STR(prConnSettings->aucBSSID), eBand, ucChannel); |
| |
| /* 4 <1> The outer loop to search for a candidate. */ |
| LINK_FOR_EACH_ENTRY( |
| prBssDesc, prBSSDescList, rLinkEntry, struct BSS_DESC) { |
| |
| /* TODO(Kevin): Update Minimum Channel Load Information here */ |
| |
| #if 0 |
| log_dbg(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))) { |
| log_dbg(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) { |
| log_dbg(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)) { |
| log_dbg(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) { |
| log_dbg(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 */ |
| u4ScnAdhocBssDescTimeout = SCN_BSS_DESC_STALE_SEC; |
| #if CFG_ENABLE_WIFI_DIRECT |
| #if CFG_SUPPORT_WFD |
| if (prAdapter->rWifiVar.rWfdConfigureSettings.ucWfdEnable) |
| u4ScnAdhocBssDescTimeout = SCN_BSS_DESC_STALE_SEC_WFD; |
| #endif |
| #endif |
| if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, |
| SEC_TO_SYSTIME(u4ScnAdhocBssDescTimeout))) { |
| log_dbg(SCN, LOUD, "SEARCH: Ignore stale Bss, CurrTime[%u] BssUpdateTime[%u]\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); |
| |
| /* 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 |
| && prStaRec->u2ReasonCode != REASON_CODE_RESERVED) { |
| log_dbg(SCN, INFO, "SEARCH: Ignore BSS with previous Reason Code = %d\n", |
| prStaRec->u2ReasonCode); |
| continue; |
| } else |
| #endif |
| if (prStaRec |
| && 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; |
| } |
| |
| log_dbg(SCN, INFO, "SEARCH:Try to join BSS again,Status Code=%u(Curr=%u/Last Join=%u)\n", |
| prStaRec->u2StatusCode, rCurrentTime, |
| prStaRec->rLastJoinTime); |
| } else { |
| log_dbg(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) { |
| enum ENUM_BSS_TYPE eBSSType = |
| prBssDesc->eBSSType; |
| enum ENUM_PARAM_OP_MODE eOPMode = |
| prConnSettings->eOPMode; |
| /* 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 (eOPMode == NET_TYPE_INFRA |
| && eBSSType != BSS_TYPE_INFRASTRUCTURE) { |
| log_dbg(SCN, INFO, "SEARCH: Ignore eBSSType = IBSS\n"); |
| continue; |
| } |
| if ((eOPMode == NET_TYPE_IBSS |
| || eOPMode == NET_TYPE_DEDICATED_IBSS) |
| && eBSSType != BSS_TYPE_IBSS) { |
| log_dbg(SCN, INFO, "SEARCH: Ignore eBSSType = INFRASTRUCTURE\n"); |
| continue; |
| } |
| /* 4 <4.2> Check AP's BSSID if OID_802_11_BSSID has been |
| * set. |
| */ |
| if (prConnSettings->fgIsConnByBssidIssued && |
| eBSSType == BSS_TYPE_INFRASTRUCTURE) { |
| if (UNEQUAL_MAC_ADDR(prConnSettings->aucBSSID, |
| prBssDesc->aucBSSID)) { |
| log_dbg(SCN, TRACE, "SEARCH: Ignore due to BSSID was not matched!\n"); |
| continue; |
| } |
| } |
| #if CFG_SUPPORT_ADHOC |
| /* 4 <4.3> Check for AdHoc Mode */ |
| if (eBSSType == BSS_TYPE_IBSS) { |
| OS_SYSTIME rCurrentTime; |
| |
| u4ScnAdhocBssDescTimeout = |
| SCN_ADHOC_BSS_DESC_TIMEOUT_SEC; |
| |
| /* 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 CFG_ENABLE_WIFI_DIRECT |
| #if CFG_SUPPORT_WFD |
| if (prAdapter->rWifiVar |
| .rWfdConfigureSettings.ucWfdEnable) { |
| #define __LOCAL_VAR__ SCN_ADHOC_BSS_DESC_TIMEOUT_SEC_WFD |
| u4ScnAdhocBssDescTimeout |
| = __LOCAL_VAR__; |
| #undef __LOCAL_VAR__ |
| } |
| #endif |
| #endif |
| if (CHECK_FOR_TIMEOUT(rCurrentTime, |
| prBssDesc->rUpdateTime, |
| SEC_TO_SYSTIME( |
| u4ScnAdhocBssDescTimeout))) { |
| log_dbg(SCN, LOUD, "SEARCH: Now(%u) Skip old record of BSS Descriptor(%u) - BSSID:[" |
| MACSTR "]\n", |
| rCurrentTime, |
| prBssDesc->rUpdateTime, |
| MAC2STR(prBssDesc->aucBSSID)); |
| continue; |
| } |
| |
| /* 4 <4.3.2> Check Peer's capability */ |
| if (ibssCheckCapabilityForAdHocMode(prAdapter, |
| prBssDesc) == WLAN_STATUS_FAILURE) { |
| |
| log_dbg(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)) { |
| |
| log_dbg(SCN, LOUD, "SEARCH: prBssDesc->fgIsLargerTSF = %d\n", |
| prBssDesc->fgIsLargerTSF); |
| |
| if (!prBssDesc->fgIsLargerTSF) { |
| log_dbg(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) |
| )){ |
| log_dbg(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))) { |
| log_dbg(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) { |
| |
| log_dbg(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); |
| |
| log_dbg(SCAN, TRACE, "\n\nCurrent TSF : %08lx-%08lx\n\n", |
| rCurrentTsf.u.HighPart, |
| rCurrentTsf.u.LowPart); |
| } |
| |
| if (rCurrentTsf.QuadPart |
| > prPrimaryBssDesc |
| ->u8TimeStamp.QuadPart) { |
| log_dbg(SCAN, TRACE, "Ignore BSS DESC MAC: [" |
| MACSTR"], Current BSSID: [" |
| MACSTR "].\n", |
| MAC2STR(prPrimaryBssDesc |
| ->aucBSSID), |
| MAC2STR(prBssInfo->aucBSSID)); |
| |
| log_dbg(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 = (struct BSS_DESC *) 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; |
| |
| log_dbg(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 struct BSS_DESC |
| * 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 old dualband 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) { |
| log_dbg(SCN, LOUD, "%s: BSSID/SSID pair matched\n", |
| __func__); |
| #if CFG_SUPPORT_CFG80211_AUTH |
| if (prBssDesc->ucChannelNum == |
| prConnSettings->ucChannelNum) { |
| prPrimaryBssDesc = prBssDesc; |
| fgIsFindFirst = TRUE; |
| } |
| #else |
| prPrimaryBssDesc = prBssDesc; |
| #endif |
| } else |
| log_dbg(SCN, ERROR, "%s: BSSID/SSID pair unmatched (" |
| MACSTR |
| ")\n", __func__, |
| MAC2STR(prBssDesc->aucBSSID)); |
| } |
| 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_CFG80211_AUTH |
| #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 |
| */ |
| log_dbg(RSN, INFO, "Ignore BSS can't pass WAPI policy selection\n"); |
| continue; |
| } |
| } else |
| #endif |
| if (rsnPerformPolicySelection(prAdapter, |
| prPrimaryBssDesc)) { |
| if (prAisSpecBssInfo->fgCounterMeasure) { |
| log_dbg(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 |
| */ |
| log_dbg(RSN, INFO, "Ignore BSS can't pass Encryption Status Check\n"); |
| continue; |
| } |
| #endif |
| } 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) { |
| /* The non Hidden SSID win. */ |
| prCandidateBssDesc = prPrimaryBssDesc; |
| |
| 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. |
| */ |
| log_dbg(SCN, TRACE, "Candidate [" |
| MACSTR |
| "]: uint8_t = %d, joinFailCnt=%d, Primary [" |
| MACSTR "]: uint8_t = %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 |
| */ |
| #define __LOCAL_VAR__ \ |
| SCN_BSS_JOIN_FAIL_CNT_RESET_SEC |
| if (CHECK_FOR_TIMEOUT(rCurrentTime, |
| prBssDesc->rJoinFailTime, |
| SEC_TO_SYSTIME( |
| __LOCAL_VAR__))) { |
| #define __LOCAL_VAR2__ \ |
| SCN_BSS_JOIN_FAIL_RESET_STEP |
| |
| prBssDesc->ucJoinFailureCount |
| -= __LOCAL_VAR2__; |
| #undef __LOCAL_VAR2__ |
| |
| log_dbg(AIS, INFO, "decrease join fail count for Bss " |
| MACSTR |
| " to %u, timeout second %d\n", |
| MAC2STR( |
| prBssDesc->aucBSSID), |
| prBssDesc |
| ->ucJoinFailureCount, |
| __LOCAL_VAR__); |
| } |
| #undef __LOCAL_VAR__ |
| } |
| /* NOTE: To prevent SWING, we do roaming only |
| * if target AP has at least 5dBm larger |
| * than us. |
| */ |
| #if CFG_SUPPORT_NCHO |
| if (prAdapter->rNchoInfo.fgECHOEnabled |
| == TRUE) { |
| ucRCPIStep = 2 * prAdapter |
| ->rNchoInfo.i4RoamDelta; |
| } |
| #endif |
| 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 struct ADAPTER *prAdapter, |
| IN enum ENUM_BSS_TYPE eBSSType, |
| IN struct BSS_DESC *SpecificprBssDesc) |
| { |
| struct SCAN_INFO *prScanInfo = NULL; |
| struct LINK *prBSSDescList = NULL; |
| struct BSS_DESC *prBssDesc = NULL; |
| struct RF_CHANNEL_INFO rChannelInfo; |
| |
| ASSERT(prAdapter); |
| |
| prScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| |
| prBSSDescList = &prScanInfo->rBSSDescList; |
| |
| log_dbg(SCN, TRACE, "eBSSType: %d\n", eBSSType); |
| |
| if (SpecificprBssDesc) { |
| { |
| /* check BSSID is legal channel */ |
| if (!scanCheckBssIsLegal(prAdapter, |
| SpecificprBssDesc)) { |
| log_dbg(SCN, TRACE, |
| "Remove specific SSID[%s %d]\n", |
| SpecificprBssDesc->aucSSID, |
| SpecificprBssDesc->ucChannelNum); |
| return; |
| } |
| |
| log_dbg(SCN, TRACE, "Report specific SSID[%s] ValidSSID[%u]\n", |
| SpecificprBssDesc->aucSSID, |
| SpecificprBssDesc->fgIsValidSSID); |
| |
| if (eBSSType == BSS_TYPE_INFRASTRUCTURE) { |
| if (SpecificprBssDesc->fgIsValidSSID) { |
| kalIndicateBssInfo( |
| prAdapter->prGlueInfo, |
| (uint8_t *) |
| SpecificprBssDesc->aucRawBuf, |
| SpecificprBssDesc->u2RawLength, |
| SpecificprBssDesc->ucChannelNum, |
| RCPI_TO_dBm( |
| SpecificprBssDesc->ucRCPI)); |
| } |
| } else { |
| |
| rChannelInfo.ucChannelNum |
| = SpecificprBssDesc->ucChannelNum; |
| rChannelInfo.eBand = SpecificprBssDesc->eBand; |
| kalP2PIndicateBssInfo(prAdapter->prGlueInfo, |
| (uint8_t *) |
| 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, struct BSS_DESC) { |
| #if CFG_AUTO_CHANNEL_SEL_SUPPORT |
| /* Record channel loading with channel's AP number */ |
| uint8_t 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)) { |
| log_dbg(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 |
| ) { |
| |
| log_dbg(SCN, TRACE, "Report " MACSTR " SSID[%s %u] eBSSType[%d] ValidSSID[%u] u2RawLength[%d] fgIsP2PReport[%d]\n", |
| MAC2STR(prBssDesc->aucBSSID), |
| prBssDesc->aucSSID, |
| prBssDesc->ucChannelNum, |
| prBssDesc->eBSSType, |
| prBssDesc->fgIsValidSSID, |
| prBssDesc->u2RawLength, |
| prBssDesc->fgIsP2PReport); |
| |
| if (eBSSType == BSS_TYPE_INFRASTRUCTURE) { |
| if (prBssDesc->u2RawLength != 0 && |
| prBssDesc->fgIsValidSSID) { |
| kalIndicateBssInfo( |
| prAdapter->prGlueInfo, |
| (uint8_t *) |
| 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, |
| (uint8_t *) |
| prBssDesc->aucRawBuf, |
| prBssDesc->u2RawLength, |
| &rChannelInfo, |
| RCPI_TO_dBm( |
| prBssDesc->ucRCPI)); |
| |
| /* do not clear it then we can |
| * pass the bss in |
| * Specific report |
| */ |
| #if 0 /* TODO: Remove this */ |
| kalMemZero(prBssDesc->aucRawBuf, |
| CFG_RAW_BUFFER_SIZE); |
| #endif |
| |
| /* 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. |
| */ |
| #if 0 |
| prBssDesc->u2RawLength = 0; |
| #endif |
| |
| #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 |
| */ |
| /*----------------------------------------------------------------------------*/ |
| struct BSS_DESC *scanSearchBssDescByBssidAndLatestUpdateTime( |
| IN struct ADAPTER *prAdapter, IN uint8_t aucBSSID[]) |
| { |
| struct SCAN_INFO *prScanInfo; |
| struct LINK *prBSSDescList; |
| struct BSS_DESC *prBssDesc; |
| struct BSS_DESC *prDstBssDesc = (struct BSS_DESC *) 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, struct BSS_DESC) { |
| |
| 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(struct ADAPTER *prAdapter) |
| { |
| struct LINK *prBSSDescList = |
| &prAdapter->rWifiVar.rScanInfo.rBSSDescList; |
| struct BSS_DESC *prBssDesc = NULL; |
| struct AGPS_AP_LIST *prAgpsApList = |
| kalMemAlloc(sizeof(struct AGPS_AP_LIST), VIR_MEM_TYPE); |
| struct AGPS_AP_INFO *prAgpsInfo = &prAgpsApList->arApInfo[0]; |
| struct SCAN_INFO *prScanInfo = &prAdapter->rWifiVar.rScanInfo; |
| uint8_t ucIndex = 0; |
| |
| LINK_FOR_EACH_ENTRY( |
| prBssDesc, prBSSDescList, rLinkEntry, struct BSS_DESC) { |
| |
| 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); |
| /* log_dbg(SCN, INFO, ("num of scan list:%d\n", ucIndex)); */ |
| kalIndicateAgpsNotify(prAdapter, AGPS_EVENT_WLAN_AP_LIST, |
| (uint8_t *) prAgpsApList, sizeof(struct AGPS_AP_LIST)); |
| kalMemFree(prAgpsApList, VIR_MEM_TYPE, sizeof(struct AGPS_AP_LIST)); |
| } |
| #endif /* CFG_SUPPORT_AGPS_ASSIST */ |
| |
| void scanReqLog(struct CMD_SCAN_REQ_V2 *prCmdScanReq) |
| { |
| char *scanType; |
| char *ssidType; |
| char *channelType; |
| |
| switch (prCmdScanReq->ucScanType) { |
| case SCAN_TYPE_PASSIVE_SCAN: |
| scanType = "Passive"; |
| break; |
| case SCAN_TYPE_ACTIVE_SCAN: |
| scanType = "Active"; |
| break; |
| default: |
| scanType = "Uknown"; |
| } |
| |
| switch (prCmdScanReq->ucSSIDType) { |
| case SCAN_REQ_SSID_WILDCARD: |
| ssidType = "Wildcard"; |
| break; |
| case SCAN_REQ_SSID_P2P_WILDCARD: |
| ssidType = "P2PWildcard"; |
| break; |
| case SCAN_REQ_SSID_SPECIFIED: |
| ssidType = "Specified"; |
| break; |
| case SCAN_REQ_SSID_SPECIFIED_ONLY: |
| ssidType = "SpecifiedOnly"; |
| break; |
| default: |
| ssidType = "Uknown"; |
| } |
| |
| switch (prCmdScanReq->ucChannelType) { |
| case SCAN_CHANNEL_FULL: |
| channelType = "full"; |
| break; |
| case SCAN_CHANNEL_2G4: |
| channelType = "2G"; |
| break; |
| case SCAN_CHANNEL_5G: |
| channelType = "5G"; |
| break; |
| case SCAN_CHANNEL_P2P_SOCIAL: |
| channelType = "P2PSocial"; |
| break; |
| case SCAN_CHANNEL_SPECIFIED: |
| channelType = "Sepcified"; |
| break; |
| default: |
| channelType = "Uknown"; |
| } |
| |
| scanlog_dbg(LOG_SCAN_REQ_D2F, INFO, "Scan#%u to Q:[Scan]%s:0x%x[SSID]%s:0x%x Num=%u ExtNum=%u[Ch]%s:0x%x Num=%u ExtNum=%u DW=%u minDW=%u[Ver%u]", |
| prCmdScanReq->ucSeqNum, |
| scanType, |
| prCmdScanReq->ucScanType, |
| ssidType, |
| prCmdScanReq->ucSSIDType, |
| prCmdScanReq->ucSSIDNum, |
| prCmdScanReq->ucSSIDExtNum, |
| channelType, |
| prCmdScanReq->ucChannelType, |
| prCmdScanReq->ucChannelListNum, |
| prCmdScanReq->ucChannelListExtNum, |
| prCmdScanReq->u2ChannelDwellTime, |
| prCmdScanReq->u2ChannelMinDwellTime, |
| prCmdScanReq->auVersion[0]); |
| if (prCmdScanReq->ucSSIDNum || prCmdScanReq->ucSSIDExtNum) |
| scanReqSsidLog(prCmdScanReq, SCAN_LOG_MSG_MAX_LEN); |
| if (prCmdScanReq->ucChannelListNum || prCmdScanReq->ucChannelListExtNum) |
| scanReqChannelLog(prCmdScanReq, SCAN_LOG_MSG_MAX_LEN); |
| } |
| |
| void scanReqSsidLog(struct CMD_SCAN_REQ_V2 *prCmdScanReq, |
| const uint16_t logBufLen) |
| { |
| char *logBuf; |
| uint32_t idx = 0; |
| int i = 0; |
| u_int8_t ext = FALSE; |
| uint8_t ssidNum = 0; |
| struct PARAM_SSID *ssid = NULL; |
| |
| logBuf = kalMemAlloc(logBufLen, PHY_MEM_TYPE); |
| if (!logBuf) { |
| log_dbg(SCN, ERROR, "logBuf alloc fail\n"); |
| return; |
| } |
| |
| while (1) { |
| if (ext == FALSE) { |
| ssidNum = prCmdScanReq->ucSSIDNum; |
| ssid = prCmdScanReq->arSSID; |
| } else { |
| ssidNum = prCmdScanReq->ucSSIDExtNum; |
| ssid = prCmdScanReq->arSSIDExtend; |
| } |
| for (i = 0; i < ssidNum; ++i) { |
| uint8_t len = (uint8_t) ssid[i].u4SsidLen; |
| |
| if (len == 0) { |
| continue; |
| } else if (len+1+1 > logBufLen) { |
| scanlog_dbg(LOG_SCAN_REQ_D2F, INFO, "Need more buffer: %u\n", |
| len+1+1); |
| break; |
| } else if (idx+len+1+1 > logBufLen) { |
| logBuf[idx] = 0; /* terminating null byte */ |
| if (ext == FALSE) { |
| scanlog_dbg(LOG_SCAN_REQ_D2F, INFO, "Ssid: %s\n", |
| logBuf); |
| } else { |
| scanlog_dbg(LOG_SCAN_REQ_D2F, INFO, "Ext Ssid: %s\n", |
| logBuf); |
| } |
| idx = 0; |
| } |
| |
| kalStrnCpy(logBuf+idx, ssid[i].aucSsid, len); |
| idx = idx + len; |
| |
| kalMemCopy(logBuf+idx, " ", 1); |
| idx = idx + 1; |
| } |
| if (idx != 0) { |
| logBuf[idx] = 0; /* terminating null byte */ |
| if (ext == FALSE) { |
| scanlog_dbg(LOG_SCAN_REQ_D2F, INFO, "Ssid: %s\n", |
| logBuf); |
| } else { |
| scanlog_dbg(LOG_SCAN_REQ_D2F, INFO, "Ext Ssid: %s\n", |
| logBuf); |
| } |
| idx = 0; |
| } |
| |
| if (ext == FALSE) |
| ext = TRUE; |
| else |
| break; |
| } |
| |
| kalMemFree(logBuf, PHY_MEM_TYPE, logBufLen); |
| } |
| |
| void scanReqChannelLog(struct CMD_SCAN_REQ_V2 *prCmdScanReq, |
| const uint16_t logBufLen) |
| { |
| char *logBuf; |
| uint32_t idx = 0; |
| uint32_t i = 0; |
| u_int8_t ext = FALSE; |
| uint8_t chNum = 0; |
| struct CHANNEL_INFO *ch = NULL; |
| /* the decimal value could 0 ~ 255 */ |
| const uint8_t dataLen = 4; |
| |
| logBuf = kalMemAlloc(logBufLen, PHY_MEM_TYPE); |
| if (!logBuf) { |
| log_dbg(SCN, ERROR, "logBuf alloc fail\n"); |
| return; |
| } |
| |
| while (1) { |
| if (ext == FALSE) { |
| chNum = prCmdScanReq->ucChannelListNum; |
| ch = prCmdScanReq->arChannelList; |
| } else { |
| chNum = prCmdScanReq->ucChannelListExtNum; |
| ch = prCmdScanReq->arChannelListExtend; |
| } |
| for (i = 0; i < chNum; ++i) { |
| if (dataLen+1 > logBufLen) { |
| scanlog_dbg(LOG_SCAN_REQ_D2F, INFO, "Need buffer size %u for log\n", |
| dataLen+1); |
| break; |
| } else if (idx+dataLen+1 > logBufLen) { |
| logBuf[idx] = 0; /* terminating null byte */ |
| if (ext == FALSE) { |
| scanlog_dbg(LOG_SCAN_REQ_D2F, INFO, "Ch: %s\n", |
| logBuf); |
| } else { |
| scanlog_dbg(LOG_SCAN_REQ_D2F, INFO, "Ext Ch: %s\n", |
| logBuf); |
| } |
| idx = 0; |
| } |
| |
| /* number + terminating null byte + a space */ |
| idx += kalSnprintf(logBuf+idx, dataLen+1, "%u ", |
| ch[i].ucChannelNum); |
| } |
| if (idx != 0) { |
| logBuf[idx] = 0; /* terminating null byte */ |
| if (ext == FALSE) { |
| scanlog_dbg(LOG_SCAN_REQ_D2F, INFO, "Ch: %s\n", |
| logBuf); |
| } else { |
| scanlog_dbg(LOG_SCAN_REQ_D2F, INFO, "Ext Ch: %s\n", |
| logBuf); |
| } |
| idx = 0; |
| } |
| if (ext == FALSE) |
| ext = TRUE; |
| else |
| break; |
| } |
| |
| kalMemFree(logBuf, PHY_MEM_TYPE, logBufLen); |
| } |
| |
| void scanResultLog(struct ADAPTER *prAdapter, |
| struct SW_RFB *prSwRfb) |
| { |
| struct WLAN_BEACON_FRAME *pFrame = |
| (struct WLAN_BEACON_FRAME *) prSwRfb->pvHeader; |
| |
| scanLogCacheAddBSS( |
| &(prAdapter->rWifiVar.rScanInfo.rScanLogCache.rBSSListFW), |
| prAdapter->rWifiVar.rScanInfo.rScanLogCache.arBSSListBufFW, |
| LOG_SCAN_RESULT_F2D, |
| pFrame->aucBSSID, |
| pFrame->u2SeqCtrl); |
| } |
| |
| void scanLogCacheAddBSS(struct LINK *prList, |
| struct SCAN_LOG_ELEM_BSS *prListBuf, |
| enum ENUM_SCAN_LOG_PREFIX prefix, |
| uint8_t bssId[], uint16_t seq) |
| { |
| struct SCAN_LOG_ELEM_BSS *pSavedBss = NULL; |
| struct SCAN_LOG_ELEM_BSS *pBss = NULL; |
| |
| if (LINK_IS_INVALID(prList)) { |
| LINK_INITIALIZE(prList); |
| scanlog_dbg(prefix, INFO, "Init scan log cache\n"); |
| } |
| |
| LINK_FOR_EACH_ENTRY(pSavedBss, prList, |
| rLinkEntry, struct SCAN_LOG_ELEM_BSS) { |
| if (EQUAL_MAC_ADDR(pSavedBss->aucBSSID, bssId)) |
| return; |
| } |
| |
| if (prList->u4NumElem < SCAN_LOG_BUFF_SIZE) { |
| if (prListBuf != NULL) { |
| pBss = &(prListBuf[prList->u4NumElem]); |
| } else { |
| scanlog_dbg(prefix, INFO, "Buffer is NULL\n"); |
| return; |
| } |
| |
| kalMemZero(pBss, sizeof(struct SCAN_LOG_ELEM_BSS)); |
| } else { |
| #if SCAN_LOG_DYN_ALLOC_MEM |
| pBss = kalMemAlloc(sizeof(struct SCAN_LOG_ELEM_BSS), |
| VIR_MEM_TYPE); |
| if (pBss == NULL) { |
| scanlog_dbg(prefix, INFO, "Cannot allocate memory for scan log\n"); |
| return; |
| } |
| |
| kalMemZero(pBss, sizeof(struct SCAN_LOG_ELEM_BSS)); |
| pBss->ucDynAllocMem = TRUE; |
| scanlog_dbg(prefix, INFO, |
| "allocate memory for scan log [%p]\n", pBss); |
| #else |
| scanlog_dbg(prefix, INFO, "Need more buffer\n"); |
| return; |
| #endif |
| } |
| |
| COPY_MAC_ADDR(pBss->aucBSSID, bssId); |
| pBss->u2SeqCtrl = seq; |
| |
| LINK_INSERT_HEAD(prList, &(pBss->rLinkEntry)); |
| } |
| |
| void scanLogCacheFlushBSS(struct LINK *prList, enum ENUM_SCAN_LOG_PREFIX prefix, |
| const uint16_t logBufLen) |
| { |
| char *logBuf; |
| uint32_t idx = 0; |
| struct SCAN_LOG_ELEM_BSS *pBss = NULL; |
| #if CFG_SHOW_FULL_MACADDR |
| /* XXXXXXXXXXXX */ |
| const uint8_t dataLen = 12; |
| #else |
| /* XXXXsumXX */ |
| const uint8_t dataLen = 9; |
| #endif |
| |
| if (LINK_IS_INVALID(prList)) { |
| LINK_INITIALIZE(prList); |
| scanlog_dbg(prefix, INFO, "Init scan log cache\n"); |
| } |
| |
| if (LINK_IS_EMPTY(prList)) |
| return; |
| |
| /* The maximum characters of uint32_t could be 10. Thus, the |
| * mininum size should be 10+3 for the format "%u: ". |
| */ |
| if (logBufLen < 13 || dataLen+1 > logBufLen) { |
| scanlog_dbg(prefix, INFO, "Scan log buffer is too small.\n"); |
| while (!LINK_IS_EMPTY(prList)) { |
| LINK_REMOVE_HEAD(prList, |
| pBss, struct SCAN_LOG_ELEM_BSS *); |
| #if SCAN_LOG_DYN_ALLOC_MEM |
| if (pBss->ucDynAllocMem) { |
| scanlog_dbg(prefix, INFO, |
| "free [%p] for scan log\n", pBss); |
| kalMemFree(pBss, VIR_MEM_TYPE, |
| sizeof(struct SCAN_LOG_ELEM_BSS)); |
| } |
| #endif |
| } |
| return; |
| } |
| |
| logBuf = kalMemAlloc(logBufLen, PHY_MEM_TYPE); |
| if (!logBuf) { |
| log_dbg(SCN, ERROR, "logBuf alloc fail\n"); |
| return; |
| } |
| |
| idx += kalSnprintf(logBuf, logBufLen, "%u: ", prList->u4NumElem); |
| |
| while (!LINK_IS_EMPTY(prList)) { |
| if (idx+dataLen+1 > logBufLen) { |
| logBuf[idx] = 0; /* terminating null byte */ |
| scanlog_dbg(prefix, TRACE, "%s\n", |
| logBuf); |
| idx = 0; |
| } |
| |
| LINK_REMOVE_HEAD(prList, |
| pBss, struct SCAN_LOG_ELEM_BSS *); |
| |
| #if CFG_SHOW_FULL_MACADDR |
| idx += kalSnprintf(logBuf+idx, dataLen+1, |
| "%02x%02x%02x%02x%02x%02x", |
| ((uint8_t *)pBss->aucBSSID)[0], |
| ((uint8_t *)pBss->aucBSSID)[1], |
| ((uint8_t *)pBss->aucBSSID)[2], |
| ((uint8_t *)pBss->aucBSSID)[3], |
| ((uint8_t *)pBss->aucBSSID)[4], |
| ((uint8_t *)pBss->aucBSSID)[5]); |
| #else |
| idx += kalSnprintf(logBuf+idx, dataLen+1, |
| "%02x%02x%03x%02x", |
| ((uint8_t *)pBss->aucBSSID)[0], |
| ((uint8_t *)pBss->aucBSSID)[1], |
| ((uint8_t *)pBss->aucBSSID)[2] + |
| ((uint8_t *)pBss->aucBSSID)[3] + |
| ((uint8_t *)pBss->aucBSSID)[4], |
| ((uint8_t *)pBss->aucBSSID)[5]); |
| #endif |
| |
| #if SCAN_LOG_DYN_ALLOC_MEM |
| if (pBss->ucDynAllocMem) { |
| scanlog_dbg(prefix, INFO, |
| "free memory for scan log [%p]\n", pBss); |
| kalMemFree(pBss, VIR_MEM_TYPE, |
| sizeof(struct SCAN_LOG_ELEM_BSS)); |
| } |
| #endif |
| } |
| if (idx != 0) { |
| logBuf[idx] = 0; /* terminating null byte */ |
| scanlog_dbg(prefix, TRACE, "%s\n", |
| logBuf); |
| idx = 0; |
| } |
| |
| kalMemFree(logBuf, PHY_MEM_TYPE, logBufLen); |
| } |
| |
| void scanLogCacheFlushAll(struct SCAN_LOG_CACHE *prScanLogCache, |
| enum ENUM_SCAN_LOG_PREFIX prefix, const uint16_t logBufLen) |
| { |
| scanLogCacheFlushBSS(&(prScanLogCache->rBSSListFW), |
| prefix, logBufLen); |
| scanLogCacheFlushBSS(&(prScanLogCache->rBSSListCFG), |
| prefix, logBufLen); |
| } |