| /* |
| * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. |
| * |
| * Previously licensed under the ISC license by Qualcomm Atheros, Inc. |
| * |
| * |
| * Permission to use, copy, modify, and/or distribute this software for |
| * any purpose with or without fee is hereby granted, provided that the |
| * above copyright notice and this permission notice appear in all |
| * copies. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
| * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
| * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
| * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
| * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| * PERFORMANCE OF THIS SOFTWARE. |
| */ |
| |
| /* |
| * This file was originally distributed by Qualcomm Atheros, Inc. |
| * under proprietary terms before Copyright ownership was assigned |
| * to the Linux Foundation. |
| */ |
| |
| /** ------------------------------------------------------------------------- * |
| ------------------------------------------------------------------------- * |
| |
| |
| \file csrApiScan.c |
| |
| Implementation for the Common Scan interfaces. |
| ========================================================================== */ |
| |
| #include "aniGlobal.h" |
| |
| #include "palApi.h" |
| #include "csrInsideApi.h" |
| #include "smeInside.h" |
| #include "smsDebug.h" |
| |
| #include "csrSupport.h" |
| #include "wlan_qct_tl.h" |
| |
| #include "vos_diag_core_log.h" |
| #include "vos_diag_core_event.h" |
| |
| #include "vos_nvitem.h" |
| #include "vos_memory.h" |
| #include "wlan_qct_wda.h" |
| #include "vos_utils.h" |
| |
| #define MIN_CHN_TIME_TO_FIND_GO 100 |
| #define MAX_CHN_TIME_TO_FIND_GO 100 |
| #define DIRECT_SSID_LEN 7 |
| |
| /* |
| * Purpose of HIDDEN_TIMER |
| * When we remove hidden ssid from the profile i.e., forget the SSID via GUI |
| * that SSID shouldn't see in the profile for above requirement we used timer |
| * limit, logic is explained below timer value is initialized to current time |
| * when it receives corresponding probe response of hidden SSID |
| * (The probe request is received regularly till SSID in the profile. |
| * Once it is removed from profile probe request is not sent.) when we receive |
| * probe response for broadcast probe request, during update SSID with saved |
| * SSID we will diff current time with saved SSID time if it is greater than |
| * 1 min then we are not updating with old one. |
| */ |
| |
| #define HIDDEN_TIMER (1*60*1000) |
| |
| /* Must be less than 100, represent the percentage of new RSSI */ |
| #define CSR_SCAN_RESULT_RSSI_WEIGHT 80 |
| |
| #define CSR_PURGE_RSSI_THRESHOLD -70 |
| |
| #define MAX_ACTIVE_SCAN_FOR_ONE_CHANNEL 140 |
| #define MIN_ACTIVE_SCAN_FOR_ONE_CHANNEL 120 |
| |
| #define MAX_ACTIVE_SCAN_FOR_ONE_CHANNEL_FASTREASSOC 30 |
| #define MIN_ACTIVE_SCAN_FOR_ONE_CHANNEL_FASTREASSOC 20 |
| |
| #define CSR_SCAN_IS_OVER_BSS_LIMIT(pMac) \ |
| ( (pMac)->scan.nBssLimit <= (csrLLCount(&(pMac)->scan.scanResultList)) ) |
| |
| //*** This is temporary work around. It need to call CCM api to get to CFG later |
| /// Get string parameter value |
| extern tSirRetStatus wlan_cfgGetStr(tpAniSirGlobal, tANI_U16, tANI_U8*, tANI_U32*); |
| |
| void csrScanGetResultTimerHandler(void *); |
| static void csrPurgeScanResultByAge(void *pv); |
| void csrScanIdleScanTimerHandler(void *); |
| static void csrSetDefaultScanTiming( tpAniSirGlobal pMac, tSirScanType scanType, tCsrScanRequest *pScanRequest); |
| tANI_BOOLEAN csrIsSupportedChannel(tpAniSirGlobal pMac, tANI_U8 channelId); |
| eHalStatus csrScanChannels( tpAniSirGlobal pMac, tSmeCmd *pCommand ); |
| void csrSetCfgValidChannelList( tpAniSirGlobal pMac, tANI_U8 *pChannelList, tANI_U8 NumChannels ); |
| void csrSaveTxPowerToCfg( tpAniSirGlobal pMac, tDblLinkList *pList, tANI_U32 cfgId ); |
| void csrSetCfgCountryCode( tpAniSirGlobal pMac, tANI_U8 *countryCode ); |
| void csrPurgeChannelPower( tpAniSirGlobal pMac, tDblLinkList *pChannelList ); |
| //if bgPeriod is 0, background scan is disabled. It is in millisecond units |
| eHalStatus csrSetCfgBackgroundScanPeriod(tpAniSirGlobal pMac, tANI_U32 bgPeriod); |
| eHalStatus csrProcessSetBGScanParam(tpAniSirGlobal pMac, tSmeCmd *pCommand); |
| void csrReleaseScanCommand(tpAniSirGlobal pMac, tSmeCmd *pCommand, eCsrScanStatus scanStatus); |
| static tANI_BOOLEAN csrScanValidateScanResult( tpAniSirGlobal pMac, tANI_U8 *pChannels, |
| tANI_U8 numChn, tSirBssDescription *pBssDesc, |
| tDot11fBeaconIEs **ppIes ); |
| eHalStatus csrSetBGScanChannelList( tpAniSirGlobal pMac, tANI_U8 *pAdjustChannels, tANI_U8 NumAdjustChannels); |
| void csrReleaseCmdSingle(tpAniSirGlobal pMac, tSmeCmd *pCommand); |
| tANI_BOOLEAN csrRoamIsValidChannel( tpAniSirGlobal pMac, tANI_U8 channel ); |
| void csrPruneChannelListForMode( tpAniSirGlobal pMac, tCsrChannel *pChannelList ); |
| void csr_purge_scan_result(tpAniSirGlobal mac_ctx); |
| |
| #define CSR_IS_SOCIAL_CHANNEL(channel) (((channel) == 1) || ((channel) == 6) || ((channel) == 11) ) |
| |
| |
| |
| static void csrReleaseScanCmdPendingList(tpAniSirGlobal pMac) |
| { |
| tListElem *pEntry; |
| tSmeCmd *pCommand; |
| |
| while((pEntry = csrLLRemoveHead( &pMac->scan.scanCmdPendingList, LL_ACCESS_LOCK)) != NULL) |
| { |
| pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); |
| if ( eSmeCsrCommandMask & pCommand->command ) |
| { |
| csrAbortCommand( pMac, pCommand, eANI_BOOLEAN_TRUE ); |
| } |
| else |
| { |
| smsLog(pMac, LOGE, FL("Error: Received command : %d"),pCommand->command); |
| } |
| } |
| } |
| //pResult is invalid calling this function. |
| void csrFreeScanResultEntry( tpAniSirGlobal pMac, tCsrScanResult *pResult ) |
| { |
| if( NULL != pResult->Result.pvIes ) |
| { |
| vos_mem_free(pResult->Result.pvIes); |
| } |
| vos_mem_free(pResult); |
| } |
| |
| |
| static eHalStatus csrLLScanPurgeResult(tpAniSirGlobal pMac, tDblLinkList *pList) |
| { |
| eHalStatus status = eHAL_STATUS_SUCCESS; |
| tListElem *pEntry; |
| tCsrScanResult *pBssDesc; |
| |
| csrLLLock(pList); |
| |
| while((pEntry = csrLLRemoveHead(pList, LL_ACCESS_NOLOCK)) != NULL) |
| { |
| pBssDesc = GET_BASE_ADDR( pEntry, tCsrScanResult, Link ); |
| csrFreeScanResultEntry( pMac, pBssDesc ); |
| } |
| |
| csrLLUnlock(pList); |
| |
| return (status); |
| } |
| |
| eHalStatus csrScanOpen( tpAniSirGlobal pMac ) |
| { |
| eHalStatus status; |
| |
| do |
| { |
| csrLLOpen(pMac->hHdd, &pMac->scan.scanResultList); |
| csrLLOpen(pMac->hHdd, &pMac->scan.tempScanResults); |
| csrLLOpen(pMac->hHdd, &pMac->scan.channelPowerInfoList24); |
| csrLLOpen(pMac->hHdd, &pMac->scan.channelPowerInfoList5G); |
| #ifdef WLAN_AP_STA_CONCURRENCY |
| csrLLOpen(pMac->hHdd, &pMac->scan.scanCmdPendingList); |
| #endif |
| pMac->scan.fFullScanIssued = eANI_BOOLEAN_FALSE; |
| pMac->scan.nBssLimit = CSR_MAX_BSS_SUPPORT; |
| status = vos_timer_init(&pMac->scan.hTimerGetResult, VOS_TIMER_TYPE_SW, csrScanGetResultTimerHandler, pMac); |
| if (!HAL_STATUS_SUCCESS(status)) |
| { |
| smsLog(pMac, LOGE, FL("cannot allocate memory for getResult timer")); |
| break; |
| } |
| status = vos_timer_init(&pMac->scan.hTimerIdleScan, VOS_TIMER_TYPE_SW, csrScanIdleScanTimerHandler, pMac); |
| if (!HAL_STATUS_SUCCESS(status)) |
| { |
| smsLog(pMac, LOGE, FL("cannot allocate memory for idleScan timer")); |
| break; |
| } |
| }while(0); |
| |
| return (status); |
| } |
| |
| |
| eHalStatus csrScanClose( tpAniSirGlobal pMac ) |
| { |
| csrLLScanPurgeResult(pMac, &pMac->scan.tempScanResults); |
| csrLLScanPurgeResult(pMac, &pMac->scan.scanResultList); |
| #ifdef WLAN_AP_STA_CONCURRENCY |
| csrReleaseScanCmdPendingList(pMac); |
| #endif |
| csrLLClose(&pMac->scan.scanResultList); |
| csrLLClose(&pMac->scan.tempScanResults); |
| #ifdef WLAN_AP_STA_CONCURRENCY |
| csrLLClose(&pMac->scan.scanCmdPendingList); |
| #endif |
| csrPurgeChannelPower(pMac, &pMac->scan.channelPowerInfoList24); |
| csrPurgeChannelPower(pMac, &pMac->scan.channelPowerInfoList5G); |
| csrLLClose(&pMac->scan.channelPowerInfoList24); |
| csrLLClose(&pMac->scan.channelPowerInfoList5G); |
| csrScanDisable(pMac); |
| vos_timer_destroy(&pMac->scan.hTimerGetResult); |
| vos_timer_destroy(&pMac->scan.hTimerIdleScan); |
| return eHAL_STATUS_SUCCESS; |
| } |
| |
| |
| eHalStatus csrScanEnable( tpAniSirGlobal pMac ) |
| { |
| |
| pMac->scan.fScanEnable = eANI_BOOLEAN_TRUE; |
| pMac->scan.fRestartIdleScan = eANI_BOOLEAN_TRUE; |
| |
| return eHAL_STATUS_SUCCESS; |
| } |
| |
| |
| eHalStatus csrScanDisable( tpAniSirGlobal pMac ) |
| { |
| |
| csrScanStopTimers(pMac); |
| pMac->scan.fScanEnable = eANI_BOOLEAN_FALSE; |
| |
| return eHAL_STATUS_SUCCESS; |
| } |
| |
| |
| //Set scan timing parameters according to state of other driver sessions |
| //No validation of the parameters is performed. |
| static void csrSetDefaultScanTiming( tpAniSirGlobal pMac, tSirScanType scanType, tCsrScanRequest *pScanRequest) |
| { |
| #ifdef WLAN_AP_STA_CONCURRENCY |
| if(csrIsAnySessionConnected(pMac)) |
| { |
| /* Reset passive scan time as per ini parameter. */ |
| ccmCfgSetInt(pMac, WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME, |
| pMac->roam.configParam.nPassiveMaxChnTimeConc, |
| NULL, false); |
| //If multi-session, use the appropriate default scan times |
| if(scanType == eSIR_ACTIVE_SCAN) |
| { |
| pScanRequest->maxChnTime = pMac->roam.configParam.nActiveMaxChnTimeConc; |
| pScanRequest->minChnTime = pMac->roam.configParam.nActiveMinChnTimeConc; |
| } |
| else |
| { |
| pScanRequest->maxChnTime = pMac->roam.configParam.nPassiveMaxChnTimeConc; |
| pScanRequest->minChnTime = pMac->roam.configParam.nPassiveMinChnTimeConc; |
| } |
| |
| pScanRequest->restTime = pMac->roam.configParam.nRestTimeConc; |
| pScanRequest->min_rest_time = pMac->roam.configParam.min_rest_time_conc; |
| pScanRequest->idle_time = pMac->roam.configParam.idle_time_conc; |
| |
| |
| //Return so that fields set above will not be overwritten. |
| return; |
| } |
| #endif |
| |
| //This portion of the code executed if multi-session not supported |
| //(WLAN_AP_STA_CONCURRENCY not defined) or no multi-session. |
| //Use the "regular" (non-concurrency) default scan timing. |
| ccmCfgSetInt(pMac, WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME, |
| pMac->roam.configParam.nPassiveMaxChnTime, |
| NULL,eANI_BOOLEAN_FALSE); |
| if(pScanRequest->scanType == eSIR_ACTIVE_SCAN) |
| { |
| pScanRequest->maxChnTime = pMac->roam.configParam.nActiveMaxChnTime; |
| pScanRequest->minChnTime = pMac->roam.configParam.nActiveMinChnTime; |
| } |
| else |
| { |
| pScanRequest->maxChnTime = pMac->roam.configParam.nPassiveMaxChnTime; |
| pScanRequest->minChnTime = pMac->roam.configParam.nPassiveMinChnTime; |
| } |
| |
| #ifdef WLAN_AP_STA_CONCURRENCY |
| /* No rest time/Idle time if no sessions are connected. */ |
| pScanRequest->restTime = 0; |
| pScanRequest->min_rest_time = 0; |
| pScanRequest->idle_time = 0; |
| #endif |
| } |
| |
| #ifdef WLAN_AP_STA_CONCURRENCY |
| //Return SUCCESS is the command is queued, else returns eHAL_STATUS_FAILURE |
| eHalStatus csrQueueScanRequest(tpAniSirGlobal pMac, tANI_U8 sessionId, |
| tSmeCmd *pScanCmd) |
| { |
| eHalStatus status = eHAL_STATUS_SUCCESS; |
| |
| tANI_BOOLEAN fNoCmdPending; |
| tSmeCmd *pQueueScanCmd=NULL; |
| tSmeCmd *pSendScanCmd=NULL; |
| if (NULL == pScanCmd) |
| { |
| smsLog (pMac, LOGE, FL("Scan Req cmd is NULL")); |
| return eHAL_STATUS_FAILURE; |
| } |
| |
| if ( (csrIsStaSessionConnected(pMac) && |
| #ifdef FEATURE_WLAN_LFR |
| (csrIsConcurrentInfraConnected(pMac) || |
| ((pScanCmd->u.scanCmd.reason != eCsrScanBgScan) && |
| (pMac->roam.neighborRoamInfo[sessionId].neighborRoamState != |
| eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN))) && |
| #endif |
| (pScanCmd->u.scanCmd.u.scanRequest.p2pSearch != 1)) || |
| (csrIsP2pOrSapSessionConnected(pMac))) |
| { |
| tANI_U8 numChn = pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels; |
| tANI_BOOLEAN bMemAlloc = eANI_BOOLEAN_FALSE; |
| |
| if (numChn == 0) |
| { |
| |
| numChn = pMac->scan.baseChannels.numChannels; |
| |
| pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList = vos_mem_malloc(numChn); |
| if ( NULL == pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList ) |
| { |
| smsLog( pMac, LOGE, FL(" Failed to get memory for channel list ") ); |
| return eHAL_STATUS_FAILURE; |
| } |
| bMemAlloc = eANI_BOOLEAN_TRUE; |
| vos_mem_copy(pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList, |
| pMac->scan.baseChannels.channelList, numChn); |
| status = eHAL_STATUS_SUCCESS; |
| if( !HAL_STATUS_SUCCESS( status ) ) |
| { |
| vos_mem_free(pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList); |
| pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList = NULL; |
| smsLog( pMac, LOGE, FL(" Failed to copy memory to channel list ") ); |
| return eHAL_STATUS_FAILURE; |
| } |
| pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = numChn; |
| } |
| |
| pSendScanCmd = pScanCmd; |
| pSendScanCmd->u.scanCmd.u.scanRequest.BSSType = eCSR_BSS_TYPE_ANY; |
| //Use concurrency values for min/maxChnTime. |
| //We know csrIsAnySessionConnected(pMac) returns TRUE here |
| csrSetDefaultScanTiming(pMac, pSendScanCmd->u.scanCmd.u.scanRequest.scanType, &pSendScanCmd->u.scanCmd.u.scanRequest); |
| |
| fNoCmdPending = csrLLIsListEmpty( &pMac->scan.scanCmdPendingList, LL_ACCESS_LOCK ); |
| |
| //Logic Below is as follows |
| // If the scanCmdPendingList is empty then we directly send that command |
| // to smeCommandQueue else we buffer it in our scanCmdPendingList Queue |
| if( fNoCmdPending ) |
| { |
| if (pQueueScanCmd != NULL) |
| { |
| csrLLInsertTail( &pMac->scan.scanCmdPendingList, &pQueueScanCmd->Link, LL_ACCESS_LOCK ); |
| } |
| |
| if (pSendScanCmd != NULL) |
| { |
| return csrQueueSmeCommand(pMac, pSendScanCmd, eANI_BOOLEAN_FALSE); |
| } |
| } |
| else |
| { |
| if (pSendScanCmd != NULL) |
| { |
| csrLLInsertTail( &pMac->scan.scanCmdPendingList, &pSendScanCmd->Link, LL_ACCESS_LOCK ); |
| } |
| |
| if (pQueueScanCmd != NULL) |
| { |
| csrLLInsertTail( &pMac->scan.scanCmdPendingList, &pQueueScanCmd->Link, LL_ACCESS_LOCK ); |
| } |
| } |
| } |
| else |
| { //No concurrency case |
| smsLog( pMac, LOG2, FL("Queuing scan command (reason=%d, roamState=%d" |
| " numOfChannels=%d)"), |
| pScanCmd->u.scanCmd.reason, |
| pMac->roam.neighborRoamInfo[sessionId].neighborRoamState, |
| pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels); |
| return csrQueueSmeCommand(pMac, pScanCmd, eANI_BOOLEAN_FALSE); |
| } |
| |
| return ( status ); |
| } |
| #endif |
| |
| /** |
| * csrScan2GOnyRequest() - This function will update the scan request with |
| * only 2.4GHz valid channel list. |
| * @mac_ctx: Pointer to Global MAC structure |
| * @scan_cmd scan cmd |
| * @scan_req scan req |
| * |
| * This function will update the scan request with only 2.4GHz valid channel |
| * list. |
| * |
| * @Return: status of operation |
| */ |
| static eHalStatus csrScan2GOnyRequest(tpAniSirGlobal mac_ctx, |
| tSmeCmd *scan_cmd, |
| tCsrScanRequest *scan_req) |
| { |
| uint8_t idx, lst_sz = 0; |
| |
| VOS_ASSERT(scan_cmd && scan_req); |
| /* To silence the KW tool null check is added */ |
| if ((scan_cmd == NULL) || (scan_req == NULL)) { |
| smsLog(mac_ctx, LOGE, FL(" Scan Cmd or Scan Request is NULL ")); |
| return eHAL_STATUS_INVALID_PARAMETER; |
| } |
| |
| if (eCSR_SCAN_REQUEST_FULL_SCAN != scan_req->requestType) |
| return eHAL_STATUS_SUCCESS; |
| |
| smsLog(mac_ctx, LOG1, |
| FL("Scanning only 2G Channels during first scan")); |
| |
| /* Contsruct valid Supported 2.4 GHz Channel List */ |
| if (NULL == scan_req->ChannelInfo.ChannelList) { |
| scan_req->ChannelInfo.ChannelList = |
| vos_mem_malloc(NUM_2_4GHZ_CHANNELS); |
| if (NULL == scan_req->ChannelInfo.ChannelList) { |
| smsLog(mac_ctx, LOGE, FL("Memory allocation failed.")); |
| return eHAL_STATUS_FAILED_ALLOC; |
| } |
| for (idx = 1; idx <= NUM_2_4GHZ_CHANNELS; idx++) { |
| if (csrIsSupportedChannel(mac_ctx, idx)) { |
| scan_req->ChannelInfo.ChannelList[lst_sz] = idx; |
| lst_sz++; |
| } |
| } |
| } |
| else { |
| for (idx = 0; idx < scan_req->ChannelInfo.numOfChannels; idx++) { |
| if (scan_req->ChannelInfo.ChannelList[idx] <= VOS_24_GHZ_CHANNEL_14 |
| && csrIsSupportedChannel(mac_ctx, |
| scan_req->ChannelInfo.ChannelList[idx])) { |
| scan_req->ChannelInfo.ChannelList[lst_sz] = |
| scan_req->ChannelInfo.ChannelList[idx]; |
| lst_sz++; |
| } |
| } |
| } |
| scan_req->ChannelInfo.numOfChannels = lst_sz; |
| return eHAL_STATUS_SUCCESS; |
| } |
| |
| eHalStatus csrScanRequest(tpAniSirGlobal pMac, tANI_U16 sessionId, |
| tCsrScanRequest *pScanRequest, tANI_U32 *pScanRequestID, |
| csrScanCompleteCallback callback, void *pContext) |
| { |
| eHalStatus status = eHAL_STATUS_FAILURE; |
| tSmeCmd *pScanCmd = NULL; |
| |
| if(pScanRequest == NULL) |
| { |
| smsLog( pMac, LOGE, FL(" pScanRequest is NULL")); |
| VOS_ASSERT(0); |
| return status; |
| } |
| |
| /* During group formation, the P2P client scans for GO with the specific SSID. |
| * There will be chances of GO switching to other channels because of scan or |
| * to STA channel in case of STA+GO MCC scenario. So to increase the possibility |
| * of client to find the GO, the dwell time of scan is increased to 100ms. |
| */ |
| if(pScanRequest->p2pSearch) |
| { |
| if ((pScanRequest->SSIDs.numOfSSIDs) && (NULL != pScanRequest->SSIDs.SSIDList)) |
| { |
| //If the scan request is for specific SSId the length of SSID will be |
| //greater than 7 as SSID for p2p search contains "DIRECT-") |
| if(pScanRequest->SSIDs.SSIDList->SSID.length > DIRECT_SSID_LEN) |
| { |
| smsLog( pMac, LOG1, FL("P2P: Increasing the min and max Dwell" |
| " time to %d for specific SSID scan %.*s"), |
| MAX_CHN_TIME_TO_FIND_GO, |
| pScanRequest->SSIDs.SSIDList->SSID.length, |
| pScanRequest->SSIDs.SSIDList->SSID.ssId); |
| pScanRequest->maxChnTime = MAX_CHN_TIME_TO_FIND_GO; |
| pScanRequest->minChnTime = MIN_CHN_TIME_TO_FIND_GO; |
| } |
| } |
| } |
| |
| do |
| { |
| if(pMac->scan.fScanEnable) |
| { |
| pScanCmd = csrGetCommandBuffer(pMac); |
| if(pScanCmd) |
| { |
| vos_mem_set(&pScanCmd->u.scanCmd, sizeof(tScanCmd), 0); |
| pScanCmd->command = eSmeCommandScan; |
| pScanCmd->sessionId = sessionId; |
| if (pScanCmd->sessionId >= CSR_ROAM_SESSION_MAX) |
| smsLog( pMac, LOGE, FL("Invalid Sme Session ID = %d"), sessionId); |
| pScanCmd->u.scanCmd.callback = callback; |
| pScanCmd->u.scanCmd.pContext = pContext; |
| if(eCSR_SCAN_REQUEST_11D_SCAN == pScanRequest->requestType) |
| { |
| pScanCmd->u.scanCmd.reason = eCsrScan11d1; |
| } |
| else if((eCSR_SCAN_REQUEST_FULL_SCAN == pScanRequest->requestType) || |
| (eCSR_SCAN_P2P_DISCOVERY == pScanRequest->requestType) |
| #ifdef SOFTAP_CHANNEL_RANGE |
| ||(eCSR_SCAN_SOFTAP_CHANNEL_RANGE == pScanRequest->requestType) |
| #endif |
| ) |
| { |
| pScanCmd->u.scanCmd.reason = eCsrScanUserRequest; |
| } |
| else if(eCSR_SCAN_HO_BG_SCAN == pScanRequest->requestType) |
| { |
| pScanCmd->u.scanCmd.reason = eCsrScanBgScan; |
| } |
| else if(eCSR_SCAN_HO_PROBE_SCAN == pScanRequest->requestType) |
| { |
| pScanCmd->u.scanCmd.reason = eCsrScanProbeBss; |
| } |
| else if(eCSR_SCAN_P2P_FIND_PEER == pScanRequest->requestType) |
| { |
| pScanCmd->u.scanCmd.reason = eCsrScanP2PFindPeer; |
| } |
| else |
| { |
| pScanCmd->u.scanCmd.reason = eCsrScanIdleScan; |
| } |
| if(pScanRequest->minChnTime == 0 && pScanRequest->maxChnTime == 0) |
| { |
| //The caller doesn't set the time correctly. Set it here |
| csrSetDefaultScanTiming(pMac, pScanRequest->scanType, |
| pScanRequest); |
| smsLog(pMac, LOG1, FL("Setting default min %d and max %d" |
| " ChnTime"), pScanRequest->minChnTime, |
| pScanRequest->maxChnTime); |
| } |
| #ifdef WLAN_AP_STA_CONCURRENCY |
| if(pScanRequest->restTime == 0) |
| { |
| /* Need to set restTime/min_Ret_time/idle_time only |
| * if at least one session is connected |
| */ |
| if(csrIsAnySessionConnected(pMac)) |
| { |
| pScanRequest->restTime = pMac->roam.configParam.nRestTimeConc; |
| pScanRequest->min_rest_time = pMac->roam.configParam.min_rest_time_conc; |
| pScanRequest->idle_time = pMac->roam.configParam.idle_time_conc; |
| if(pScanRequest->scanType == eSIR_ACTIVE_SCAN) |
| { |
| pScanRequest->maxChnTime = pMac->roam.configParam.nActiveMaxChnTimeConc; |
| pScanRequest->minChnTime = pMac->roam.configParam.nActiveMinChnTimeConc; |
| } |
| else |
| { |
| pScanRequest->maxChnTime = pMac->roam.configParam.nPassiveMaxChnTimeConc; |
| pScanRequest->minChnTime = pMac->roam.configParam.nPassiveMinChnTimeConc; |
| } |
| } |
| } |
| #endif |
| /* Increase dwell time in case P2P Search and Miracast is not present*/ |
| if(pScanRequest->p2pSearch && |
| pScanRequest->ChannelInfo.numOfChannels == P2P_SOCIAL_CHANNELS |
| && (!(pMac->sme.miracast_value))) { |
| pScanRequest->maxChnTime += P2P_SEARCH_DWELL_TIME_INCREASE; |
| } |
| |
| //Need to make the following atomic |
| pScanCmd->u.scanCmd.scanID = pMac->scan.nextScanID++; //let it wrap around |
| |
| if(pScanRequestID) |
| { |
| *pScanRequestID = pScanCmd->u.scanCmd.scanID; |
| } |
| |
| // If it is the first scan request from HDD, CSR checks if it is for 11d. |
| // If it is not, CSR will save the scan request in the pending cmd queue |
| // & issue an 11d scan request to PE. |
| if (((false == pMac->first_scan_done) |
| && (eCSR_SCAN_REQUEST_11D_SCAN != pScanRequest->requestType)) |
| #ifdef SOFTAP_CHANNEL_RANGE |
| && (eCSR_SCAN_SOFTAP_CHANNEL_RANGE != pScanRequest->requestType) |
| #endif |
| && (eANI_BOOLEAN_FALSE == pMac->scan.fEnableBypass11d) |
| ) |
| { |
| tSmeCmd *p11dScanCmd; |
| tCsrScanRequest scanReq; |
| tCsrChannelInfo *pChnInfo = &scanReq.ChannelInfo; |
| |
| vos_mem_set(&scanReq, sizeof(tCsrScanRequest), 0); |
| |
| p11dScanCmd = csrGetCommandBuffer(pMac); |
| if (p11dScanCmd) |
| { |
| tANI_U32 numChn = pMac->scan.baseChannels.numChannels; |
| |
| if (numChn > WNI_CFG_VALID_CHANNEL_LIST_LEN) { |
| smsLog(pMac, LOGE, |
| FL("Invalid number of channels: %d"), numChn); |
| status = eHAL_STATUS_FAILURE; |
| break; |
| } |
| vos_mem_set(&p11dScanCmd->u.scanCmd, sizeof(tScanCmd), 0); |
| pChnInfo->ChannelList = vos_mem_malloc(numChn); |
| if ( NULL == pChnInfo->ChannelList ) |
| { |
| smsLog(pMac, LOGE, FL("Failed to allocate memory")); |
| status = eHAL_STATUS_FAILURE; |
| break; |
| } |
| vos_mem_copy(pChnInfo->ChannelList, |
| pMac->scan.baseChannels.channelList, |
| numChn); |
| |
| pChnInfo->numOfChannels = (tANI_U8)numChn; |
| p11dScanCmd->command = eSmeCommandScan; |
| p11dScanCmd->u.scanCmd.callback = pMac->scan.callback11dScanDone; |
| p11dScanCmd->u.scanCmd.pContext = NULL; |
| p11dScanCmd->u.scanCmd.scanID = pMac->scan.nextScanID++; |
| scanReq.BSSType = eCSR_BSS_TYPE_ANY; |
| |
| if ( csrIs11dSupported(pMac) ) |
| { |
| scanReq.scanType = eSIR_PASSIVE_SCAN; |
| scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN; |
| p11dScanCmd->u.scanCmd.reason = eCsrScan11d1; |
| scanReq.maxChnTime = pMac->roam.configParam.nPassiveMaxChnTime; |
| scanReq.minChnTime = pMac->roam.configParam.nPassiveMinChnTime; |
| } |
| else |
| { |
| scanReq.scanType = pScanRequest->scanType; |
| scanReq.requestType = eCSR_SCAN_IDLE_MODE_SCAN; |
| p11dScanCmd->u.scanCmd.reason = eCsrScanIdleScan; |
| scanReq.maxChnTime = pMac->roam.configParam.nActiveMaxChnTime; |
| scanReq.minChnTime = pMac->roam.configParam.nActiveMinChnTime; |
| } |
| if (pMac->roam.configParam.nInitialDwellTime) |
| { |
| scanReq.maxChnTime = |
| pMac->roam.configParam.nInitialDwellTime; |
| smsLog(pMac, LOG1, FL("11d scan, updating" |
| "dwell time for first scan %u"), |
| scanReq.maxChnTime); |
| } |
| |
| status = csrScanCopyRequest(pMac, &p11dScanCmd->u.scanCmd.u.scanRequest, &scanReq); |
| //Free the channel list |
| vos_mem_free(pChnInfo->ChannelList); |
| pChnInfo->ChannelList = NULL; |
| |
| if (HAL_STATUS_SUCCESS(status)) |
| { |
| pMac->scan.scanProfile.numOfChannels = |
| p11dScanCmd->u.scanCmd.u.scanRequest. |
| ChannelInfo.numOfChannels; |
| //Start process the command |
| #ifdef WLAN_AP_STA_CONCURRENCY |
| if (!pMac->fScanOffload) |
| status = csrQueueScanRequest(pMac, sessionId, |
| p11dScanCmd); |
| else |
| status = csrQueueSmeCommand(pMac, p11dScanCmd, |
| eANI_BOOLEAN_FALSE); |
| #else |
| status = csrQueueSmeCommand(pMac, p11dScanCmd, eANI_BOOLEAN_FALSE); |
| #endif |
| if( !HAL_STATUS_SUCCESS( status ) ) |
| { |
| smsLog( pMac, LOGE, FL(" Failed to send message" |
| " status = %d"), status); |
| break; |
| } |
| } |
| else |
| { |
| smsLog(pMac, LOGE, FL("csrScanCopyRequest failed")); |
| break; |
| } |
| } |
| else |
| { |
| //error |
| smsLog( pMac, LOGE, FL("p11dScanCmd failed") ); |
| break; |
| } |
| } |
| |
| //Scan only 2G Channels if set in ini file |
| //This is mainly to reduce the First Scan duration |
| //Once we turn on Wifi |
| if(pMac->scan.fFirstScanOnly2GChnl |
| && false == pMac->first_scan_done) { |
| status = csrScan2GOnyRequest(pMac, pScanCmd, pScanRequest); |
| if (!HAL_STATUS_SUCCESS(status)) { |
| smsLog(pMac, LOGE, FL("csrScan2GOnyRequest failed.")); |
| break; |
| } |
| } |
| |
| pMac->first_scan_done = true; |
| |
| if (pMac->roam.configParam.nInitialDwellTime) |
| { |
| pScanRequest->maxChnTime = |
| pMac->roam.configParam.nInitialDwellTime; |
| pMac->roam.configParam.nInitialDwellTime = 0; |
| smsLog(pMac, LOG1, |
| FL("updating dwell time for first scan %u"), |
| pScanRequest->maxChnTime); |
| } |
| |
| status = csrScanCopyRequest(pMac, &pScanCmd->u.scanCmd.u.scanRequest, pScanRequest); |
| /* |
| * Reset the variable after the first scan is queued after |
| * loading the driver. The purpose of this parameter is that |
| * DFS channels are skipped during the first scan after loading |
| * the driver. The above API builds the target scan request in |
| * which this variable is used. |
| */ |
| pMac->roam.configParam.initial_scan_no_dfs_chnl = 0; |
| if(HAL_STATUS_SUCCESS(status)) |
| { |
| tCsrScanRequest *pTempScanReq = |
| &pScanCmd->u.scanCmd.u.scanRequest; |
| pMac->scan.scanProfile.numOfChannels = |
| pTempScanReq->ChannelInfo.numOfChannels; |
| |
| smsLog(pMac, LOG1, FL(" SId=%d scanId=%d" |
| " Scan reason=%u numSSIDs=%d" |
| " numChan=%d P2P search=%d minCT=%d maxCT=%d" |
| " minCBtc=%d maxCBtx=%d uIEFieldLen=%d"), |
| sessionId, pScanCmd->u.scanCmd.scanID, |
| pScanCmd->u.scanCmd.reason, |
| pTempScanReq->SSIDs.numOfSSIDs, |
| pTempScanReq->ChannelInfo.numOfChannels, |
| pTempScanReq->p2pSearch, |
| pTempScanReq->minChnTime, |
| pTempScanReq->maxChnTime, |
| pTempScanReq->minChnTimeBtc, |
| pTempScanReq->maxChnTimeBtc, |
| pTempScanReq->uIEFieldLen); |
| |
| //Start process the command |
| #ifdef WLAN_AP_STA_CONCURRENCY |
| if (!pMac->fScanOffload) |
| status = csrQueueScanRequest(pMac, sessionId, pScanCmd); |
| else |
| status = csrQueueSmeCommand(pMac, pScanCmd, |
| eANI_BOOLEAN_FALSE); |
| #else |
| status = csrQueueSmeCommand(pMac, pScanCmd, eANI_BOOLEAN_FALSE); |
| #endif |
| if( !HAL_STATUS_SUCCESS( status ) ) |
| { |
| smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); |
| break; |
| } |
| } |
| else |
| { |
| smsLog( pMac, LOGE, FL(" fail to copy request status = %d"), status ); |
| break; |
| } |
| } |
| else |
| { |
| smsLog( pMac, LOGE, FL(" pScanCmd is NULL")); |
| break; |
| } |
| } |
| else |
| { |
| smsLog( pMac, LOGE, FL("SId: %d Scanning not enabled" |
| " Scan type=%u, numOfSSIDs=%d P2P search=%d"), |
| sessionId, pScanRequest->requestType, |
| pScanRequest->SSIDs.numOfSSIDs, |
| pScanRequest->p2pSearch ); |
| } |
| } while(0); |
| if(!HAL_STATUS_SUCCESS(status) && pScanCmd) |
| { |
| if( eCsrScanIdleScan == pScanCmd->u.scanCmd.reason ) |
| { |
| //Set the flag back for restarting idle scan |
| pMac->scan.fRestartIdleScan = eANI_BOOLEAN_TRUE; |
| } |
| smsLog( pMac, LOGE, FL(" SId: %d Failed with status=%d" |
| " Scan reason=%u numOfSSIDs=%d" |
| " P2P search=%d scanId=%d"), |
| sessionId, status, pScanCmd->u.scanCmd.reason, |
| pScanRequest->SSIDs.numOfSSIDs, pScanRequest->p2pSearch, |
| pScanCmd->u.scanCmd.scanID ); |
| csrReleaseCommandScan(pMac, pScanCmd); |
| } |
| |
| return (status); |
| } |
| |
| |
| eHalStatus csrScanRequestResult(tpAniSirGlobal pMac) |
| { |
| eHalStatus status = eHAL_STATUS_SUCCESS; |
| tSmeCmd *pScanCmd; |
| |
| if(pMac->scan.fScanEnable) |
| { |
| pScanCmd = csrGetCommandBuffer(pMac); |
| if(pScanCmd) |
| { |
| pScanCmd->command = eSmeCommandScan; |
| vos_mem_set(&pScanCmd->u.scanCmd, sizeof(tScanCmd), 0); |
| pScanCmd->u.scanCmd.callback = NULL; |
| pScanCmd->u.scanCmd.pContext = NULL; |
| pScanCmd->u.scanCmd.reason = eCsrScanGetResult; |
| //Need to make the following atomic |
| pScanCmd->u.scanCmd.scanID = pMac->scan.nextScanID; //let it wrap around |
| status = csrQueueSmeCommand(pMac, pScanCmd, eANI_BOOLEAN_FALSE); |
| if( !HAL_STATUS_SUCCESS( status ) ) |
| { |
| smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); |
| csrReleaseCommandScan(pMac, pScanCmd); |
| } |
| } |
| else |
| { |
| //log error |
| smsLog(pMac, LOGE, FL("can not obtain a common buffer")); |
| status = eHAL_STATUS_RESOURCES; |
| } |
| } |
| |
| return (status); |
| } |
| |
| #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD |
| eHalStatus csrScanRequestLfrResult(tpAniSirGlobal pMac, tANI_U32 sessionId, |
| csrScanCompleteCallback callback, void *pContext) |
| { |
| eHalStatus status = eHAL_STATUS_SUCCESS; |
| tSmeCmd *pScanCmd; |
| |
| if (pMac->scan.fScanEnable) |
| { |
| pScanCmd = csrGetCommandBuffer(pMac); |
| if (pScanCmd) |
| { |
| pScanCmd->command = eSmeCommandScan; |
| pScanCmd->sessionId = sessionId; |
| vos_mem_set(&pScanCmd->u.scanCmd, sizeof(tScanCmd), 0); |
| pScanCmd->u.scanCmd.callback = callback; |
| pScanCmd->u.scanCmd.pContext = pContext; |
| pScanCmd->u.scanCmd.reason = eCsrScanGetLfrResult; |
| //Need to make the following atomic |
| pScanCmd->u.scanCmd.scanID = pMac->scan.nextScanID; //let it wrap around |
| status = csrQueueSmeCommand(pMac, pScanCmd, eANI_BOOLEAN_TRUE); |
| if ( !HAL_STATUS_SUCCESS( status ) ) |
| { |
| smsLog( pMac, LOGE, FL(" fail to send message status = %d\n"), status ); |
| csrReleaseCommandScan(pMac, pScanCmd); |
| } |
| } |
| else |
| { |
| //log error |
| smsLog(pMac, LOGE, FL("can not obtain a common buffer\n")); |
| status = eHAL_STATUS_RESOURCES; |
| } |
| } |
| |
| return (status); |
| } |
| #endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD |
| |
| eHalStatus csrScanAllChannels(tpAniSirGlobal pMac, eCsrRequestType reqType) |
| { |
| eHalStatus status = eHAL_STATUS_SUCCESS; |
| tANI_U32 scanId; |
| tCsrScanRequest scanReq; |
| |
| vos_mem_set(&scanReq, sizeof(tCsrScanRequest), 0); |
| scanReq.BSSType = eCSR_BSS_TYPE_ANY; |
| scanReq.scanType = eSIR_ACTIVE_SCAN; |
| scanReq.requestType = reqType; |
| scanReq.maxChnTime = pMac->roam.configParam.nActiveMaxChnTime; |
| scanReq.minChnTime = pMac->roam.configParam.nActiveMinChnTime; |
| //Scan with invalid sessionId. |
| //This results in SME using the first available session to scan. |
| status = csrScanRequest(pMac, CSR_SESSION_ID_INVALID, &scanReq, |
| &scanId, NULL, NULL); |
| |
| return (status); |
| } |
| |
| |
| |
| |
| eHalStatus csrIssueRoamAfterLostlinkScan(tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamReason reason) |
| { |
| eHalStatus status = eHAL_STATUS_FAILURE; |
| tScanResultHandle hBSSList = NULL; |
| tCsrScanResultFilter *pScanFilter = NULL; |
| tANI_U32 roamId = 0; |
| tCsrRoamProfile *pProfile = NULL; |
| tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); |
| |
| if(!pSession) |
| { |
| smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); |
| return eHAL_STATUS_FAILURE; |
| } |
| |
| do |
| { |
| smsLog(pMac, LOG1, " csrIssueRoamAfterLostlinkScan called"); |
| if(pSession->fCancelRoaming) |
| { |
| smsLog(pMac, LOGW, " lost link roaming is canceled"); |
| csrScanStartIdleScan(pMac); |
| status = eHAL_STATUS_SUCCESS; |
| break; |
| } |
| //Here is the profile we need to connect to |
| pScanFilter = vos_mem_malloc(sizeof(tCsrScanResultFilter)); |
| if ( NULL == pScanFilter) |
| status = eHAL_STATUS_FAILURE; |
| else |
| status = eHAL_STATUS_SUCCESS; |
| if (!HAL_STATUS_SUCCESS(status)) |
| break; |
| vos_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0); |
| if(NULL == pSession->pCurRoamProfile) |
| { |
| pScanFilter->EncryptionType.numEntries = 1; |
| pScanFilter->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE; |
| } |
| else |
| { |
| //We have to make a copy of pCurRoamProfile because it will be free inside csrRoamIssueConnect |
| pProfile = vos_mem_malloc(sizeof(tCsrRoamProfile)); |
| if ( NULL == pProfile ) |
| status = eHAL_STATUS_FAILURE; |
| else |
| status = eHAL_STATUS_SUCCESS; |
| if (!HAL_STATUS_SUCCESS(status)) |
| break; |
| vos_mem_set(pProfile, sizeof(tCsrRoamProfile), 0); |
| status = csrRoamCopyProfile(pMac, pProfile, pSession->pCurRoamProfile); |
| if(!HAL_STATUS_SUCCESS(status)) |
| break; |
| status = csrRoamPrepareFilterFromProfile(pMac, pProfile, pScanFilter); |
| }//We have a profile |
| roamId = GET_NEXT_ROAM_ID(&pMac->roam); |
| if(HAL_STATUS_SUCCESS(status)) |
| { |
| status = csrScanGetResult(pMac, pScanFilter, &hBSSList); |
| if(HAL_STATUS_SUCCESS(status)) |
| { |
| if(eCsrLostLink1 == reason) |
| { |
| //we want to put the last connected BSS to the very beginning, if possible |
| csrMoveBssToHeadFromBSSID(pMac, &pSession->connectedProfile.bssid, hBSSList); |
| } |
| status = csrRoamIssueConnect(pMac, sessionId, pProfile, hBSSList, reason, |
| roamId, eANI_BOOLEAN_TRUE, eANI_BOOLEAN_TRUE); |
| if(!HAL_STATUS_SUCCESS(status)) |
| { |
| csrScanResultPurge(pMac, hBSSList); |
| } |
| }//Have scan result |
| } |
| }while(0); |
| if(pScanFilter) |
| { |
| //we need to free memory for filter if profile exists |
| csrFreeScanFilter(pMac, pScanFilter); |
| vos_mem_free(pScanFilter); |
| } |
| if(NULL != pProfile) |
| { |
| csrReleaseProfile(pMac, pProfile); |
| vos_mem_free(pProfile); |
| } |
| |
| return (status); |
| } |
| |
| |
| eHalStatus csrScanGetScanChnInfo(tpAniSirGlobal pMac, tSmeCmd *pCommand) |
| { |
| eHalStatus status = eHAL_STATUS_SUCCESS; |
| tSmeCmd *pScanCmd; |
| |
| if(pMac->scan.fScanEnable) |
| { |
| pScanCmd = csrGetCommandBuffer(pMac); |
| if(pScanCmd) |
| { |
| pScanCmd->command = eSmeCommandScan; |
| vos_mem_set(&pScanCmd->u.scanCmd, sizeof(tScanCmd), 0); |
| pScanCmd->u.scanCmd.reason = eCsrScanGetScanChnInfo; |
| /* Need to make the following atomic */ |
| pScanCmd->u.scanCmd.scanID = |
| pMac->scan.nextScanID++; /* let it wrap around */ |
| pScanCmd->sessionId = pCommand->sessionId; |
| if (eCsrScanUserRequest == pCommand->u.scanCmd.reason) |
| { |
| pScanCmd->u.scanCmd.callback = NULL; |
| pScanCmd->u.scanCmd.pContext = NULL; |
| } else { |
| pScanCmd->u.scanCmd.callback = pCommand->u.scanCmd.callback; |
| pScanCmd->u.scanCmd.pContext = pCommand->u.scanCmd.pContext; |
| pScanCmd->u.scanCmd.abort_scan_indication = |
| pCommand->u.scanCmd.abort_scan_indication; |
| } |
| status = csrQueueSmeCommand(pMac, pScanCmd, eANI_BOOLEAN_FALSE); |
| if( !HAL_STATUS_SUCCESS( status ) ) |
| { |
| smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); |
| csrReleaseCommandScan(pMac, pScanCmd); |
| } |
| } |
| else |
| { |
| //log error |
| smsLog(pMac, LOGE, FL("can not obtain a common buffer")); |
| status = eHAL_STATUS_RESOURCES; |
| } |
| } |
| |
| return (status); |
| } |
| |
| |
| eHalStatus csrScanHandleFailedLostlink1(tpAniSirGlobal pMac, tANI_U32 sessionId) |
| { |
| eHalStatus status = eHAL_STATUS_FAILURE; |
| tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); |
| |
| if(!pSession) |
| { |
| smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); |
| return eHAL_STATUS_FAILURE; |
| } |
| |
| smsLog(pMac, LOGW, "Lost link scan 1 failed"); |
| if(pSession->fCancelRoaming) |
| { |
| csrScanStartIdleScan(pMac); |
| } |
| else if(pSession->pCurRoamProfile) |
| { |
| //We fail lostlink1 but there may be other BSS in the cached result fit the profile. Give it a try first |
| if(pSession->pCurRoamProfile->SSIDs.numOfSSIDs == 0 || |
| pSession->pCurRoamProfile->SSIDs.numOfSSIDs > 1) |
| { |
| /* Try lost link scan2 */ |
| status = csrScanRequestLostLink2(pMac, sessionId); |
| } |
| else if(!pSession->pCurRoamProfile->ChannelInfo.ChannelList || |
| pSession->pCurRoamProfile->ChannelInfo.ChannelList[0] == 0) |
| { |
| /* Go straight to lost link scan3 */ |
| status = csrScanRequestLostLink3(pMac, sessionId); |
| } |
| else |
| { |
| /* We are done with lost link */ |
| if(csrRoamCompleteRoaming(pMac, sessionId, eANI_BOOLEAN_FALSE, eCSR_ROAM_RESULT_FAILURE)) |
| { |
| csrScanStartIdleScan(pMac); |
| } |
| status = eHAL_STATUS_SUCCESS; |
| } |
| } |
| else |
| { |
| status = csrScanRequestLostLink3(pMac, sessionId); |
| } |
| |
| return (status); |
| } |
| |
| |
| |
| eHalStatus csrScanHandleFailedLostlink2(tpAniSirGlobal pMac, tANI_U32 sessionId) |
| { |
| eHalStatus status = eHAL_STATUS_FAILURE; |
| tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); |
| |
| if(!pSession) |
| { |
| smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); |
| return eHAL_STATUS_FAILURE; |
| } |
| |
| smsLog(pMac, LOGW, "Lost link scan 2 failed"); |
| if(pSession->fCancelRoaming) |
| { |
| csrScanStartIdleScan(pMac); |
| } |
| else if(!pSession->pCurRoamProfile || !pSession->pCurRoamProfile->ChannelInfo.ChannelList || |
| pSession->pCurRoamProfile->ChannelInfo.ChannelList[0] == 0) |
| { |
| /* Try lost link scan3 */ |
| status = csrScanRequestLostLink3(pMac, sessionId); |
| } |
| else |
| { |
| /* We are done with lost link */ |
| if(csrRoamCompleteRoaming(pMac, sessionId, eANI_BOOLEAN_FALSE, eCSR_ROAM_RESULT_FAILURE)) |
| { |
| csrScanStartIdleScan(pMac); |
| } |
| } |
| |
| return (status); |
| } |
| |
| |
| |
| eHalStatus csrScanHandleFailedLostlink3(tpAniSirGlobal pMac, tANI_U32 sessionId) |
| { |
| eHalStatus status = eHAL_STATUS_SUCCESS; |
| |
| smsLog(pMac, LOGW, "Lost link scan 3 failed"); |
| if(eANI_BOOLEAN_TRUE == csrRoamCompleteRoaming(pMac, sessionId, eANI_BOOLEAN_FALSE, eCSR_ROAM_RESULT_FAILURE)) |
| { |
| /* We are done with lost link */ |
| csrScanStartIdleScan(pMac); |
| } |
| |
| return (status); |
| } |
| |
| |
| |
| |
| //Lostlink1 scan is to actively scan the last connected profile's SSID on all matched BSS channels. |
| //If no roam profile (it should not), it is like lostlinkscan3 |
| eHalStatus csrScanRequestLostLink1( tpAniSirGlobal pMac, tANI_U32 sessionId ) |
| { |
| eHalStatus status = eHAL_STATUS_SUCCESS; |
| tSmeCmd *pCommand = NULL; |
| tANI_U8 bAddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; |
| tCsrScanResultFilter *pScanFilter = NULL; |
| tScanResultHandle hBSSList = NULL; |
| tCsrScanResultInfo *pScanResult = NULL; |
| tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); |
| |
| if(!pSession) |
| { |
| smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); |
| return eHAL_STATUS_FAILURE; |
| } |
| |
| smsLog(pMac, LOGW, FL(" called")); |
| do |
| { |
| pCommand = csrGetCommandBuffer(pMac); |
| if(!pCommand) |
| { |
| status = eHAL_STATUS_RESOURCES; |
| break; |
| } |
| vos_mem_set(&pCommand->u.scanCmd, sizeof(tScanCmd), 0); |
| pCommand->command = eSmeCommandScan; |
| pCommand->sessionId = (tANI_U8)sessionId; |
| pCommand->u.scanCmd.reason = eCsrScanLostLink1; |
| pCommand->u.scanCmd.callback = NULL; |
| pCommand->u.scanCmd.pContext = NULL; |
| pCommand->u.scanCmd.u.scanRequest.maxChnTime = pMac->roam.configParam.nActiveMaxChnTime; |
| pCommand->u.scanCmd.u.scanRequest.minChnTime = pMac->roam.configParam.nActiveMinChnTime; |
| pCommand->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN; |
| if(pSession->connectedProfile.SSID.length) |
| { |
| pCommand->u.scanCmd.u.scanRequest.SSIDs.SSIDList = vos_mem_malloc(sizeof(tCsrSSIDInfo)); |
| if ( NULL == pCommand->u.scanCmd.u.scanRequest.SSIDs.SSIDList ) |
| status = eHAL_STATUS_FAILURE; |
| else |
| status = eHAL_STATUS_SUCCESS; |
| if(!HAL_STATUS_SUCCESS(status)) |
| { |
| break; |
| } |
| pCommand->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs = 1; |
| vos_mem_copy(&pCommand->u.scanCmd.u.scanRequest.SSIDs.SSIDList[0].SSID, |
| &pSession->connectedProfile.SSID, sizeof(tSirMacSSid)); |
| } |
| else |
| { |
| pCommand->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs = 0; |
| } |
| if(pSession->pCurRoamProfile) |
| { |
| pScanFilter = vos_mem_malloc(sizeof(tCsrScanResultFilter)); |
| if ( NULL == pScanFilter ) |
| status = eHAL_STATUS_FAILURE; |
| else |
| status = eHAL_STATUS_SUCCESS; |
| if(!HAL_STATUS_SUCCESS(status)) |
| { |
| break; |
| } |
| vos_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0); |
| status = csrRoamPrepareFilterFromProfile(pMac, pSession->pCurRoamProfile, pScanFilter); |
| if(!HAL_STATUS_SUCCESS(status)) |
| { |
| break; |
| } |
| //Don't change variable status here because whether we can get result or not, the command goes to PE. |
| //The status is also used to indicate whether the command is queued. Not success meaning not queue |
| if(HAL_STATUS_SUCCESS((csrScanGetResult(pMac, pScanFilter, &hBSSList))) && hBSSList) |
| { |
| tANI_U8 i, nChn = 0; |
| pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList = |
| vos_mem_malloc(WNI_CFG_VALID_CHANNEL_LIST_LEN); |
| if ( NULL == pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList ) |
| status = eHAL_STATUS_FAILURE; |
| else |
| status = eHAL_STATUS_SUCCESS; |
| if(!HAL_STATUS_SUCCESS(status)) |
| { |
| break; |
| } |
| while(((pScanResult = csrScanResultGetNext(pMac, hBSSList)) != NULL) && |
| nChn < WNI_CFG_VALID_CHANNEL_LIST_LEN) |
| { |
| for(i = 0; i < nChn; i++) |
| { |
| if(pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[i] == |
| pScanResult->BssDescriptor.channelId) |
| { |
| break; |
| } |
| } |
| if(i == nChn) |
| { |
| pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[nChn++] = pScanResult->BssDescriptor.channelId; |
| } |
| } |
| //Include the last connected BSS' channel |
| if(csrRoamIsChannelValid(pMac, pSession->connectedProfile.operationChannel)) |
| { |
| for(i = 0; i < nChn; i++) |
| { |
| if(pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[i] == |
| pSession->connectedProfile.operationChannel) |
| { |
| break; |
| } |
| } |
| if(i == nChn) |
| { |
| pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[nChn++] = pSession->connectedProfile.operationChannel; |
| } |
| } |
| pCommand->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = nChn; |
| } |
| else |
| { |
| if(csrRoamIsChannelValid(pMac, pSession->connectedProfile.operationChannel)) |
| { |
| pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList = vos_mem_malloc(1); |
| if ( NULL == pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList ) |
| status = eHAL_STATUS_FAILURE; |
| else |
| status = eHAL_STATUS_SUCCESS; |
| //just try the last connected channel |
| if(HAL_STATUS_SUCCESS(status)) |
| { |
| pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[0] = pSession->connectedProfile.operationChannel; |
| pCommand->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = 1; |
| } |
| else |
| { |
| break; |
| } |
| } |
| } |
| } |
| vos_mem_copy(&pCommand->u.scanCmd.u.scanRequest.bssid, bAddr, sizeof(tCsrBssid)); |
| status = csrQueueSmeCommand(pMac, pCommand, eANI_BOOLEAN_FALSE); |
| if( !HAL_STATUS_SUCCESS( status ) ) |
| { |
| smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); |
| break; |
| } |
| } while( 0 ); |
| |
| if(!HAL_STATUS_SUCCESS(status)) |
| { |
| smsLog(pMac, LOGW, " csrScanRequestLostLink1 failed with status %d", status); |
| if(pCommand) |
| { |
| csrReleaseCommandScan(pMac, pCommand); |
| } |
| status = csrScanHandleFailedLostlink1( pMac, sessionId ); |
| } |
| if(pScanFilter) |
| { |
| csrFreeScanFilter(pMac, pScanFilter); |
| vos_mem_free(pScanFilter); |
| } |
| if(hBSSList) |
| { |
| csrScanResultPurge(pMac, hBSSList); |
| } |
| |
| return( status ); |
| } |
| |
| |
| //Lostlink2 scan is to actively scan the all SSIDs of the last roaming profile's on all matched BSS channels. |
| //Since MAC doesn't support multiple SSID, we scan all SSIDs and filter them afterwards |
| eHalStatus csrScanRequestLostLink2( tpAniSirGlobal pMac, tANI_U32 sessionId ) |
| { |
| eHalStatus status = eHAL_STATUS_SUCCESS; |
| tANI_U8 bAddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; |
| tCsrScanResultFilter *pScanFilter = NULL; |
| tScanResultHandle hBSSList = NULL; |
| tCsrScanResultInfo *pScanResult = NULL; |
| tSmeCmd *pCommand = NULL; |
| tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); |
| |
| if(!pSession) |
| { |
| smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); |
| return eHAL_STATUS_FAILURE; |
| } |
| |
| smsLog(pMac, LOGW, FL(" called")); |
| do |
| { |
| pCommand = csrGetCommandBuffer(pMac); |
| if(!pCommand) |
| { |
| status = eHAL_STATUS_RESOURCES; |
| break; |
| } |
| vos_mem_set(&pCommand->u.scanCmd, sizeof(tScanCmd), 0); |
| pCommand->command = eSmeCommandScan; |
| pCommand->sessionId = (tANI_U8)sessionId; |
| pCommand->u.scanCmd.reason = eCsrScanLostLink2; |
| pCommand->u.scanCmd.callback = NULL; |
| pCommand->u.scanCmd.pContext = NULL; |
| pCommand->u.scanCmd.u.scanRequest.maxChnTime = pMac->roam.configParam.nActiveMaxChnTime; |
| pCommand->u.scanCmd.u.scanRequest.minChnTime = pMac->roam.configParam.nActiveMinChnTime; |
| pCommand->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN; |
| if(pSession->pCurRoamProfile) |
| { |
| pScanFilter = vos_mem_malloc(sizeof(tCsrScanResultFilter)); |
| if ( NULL == pScanFilter ) |
| status = eHAL_STATUS_FAILURE; |
| else |
| status = eHAL_STATUS_SUCCESS; |
| if (!HAL_STATUS_SUCCESS(status)) |
| { |
| break; |
| } |
| vos_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0); |
| status = csrRoamPrepareFilterFromProfile(pMac, pSession->pCurRoamProfile, pScanFilter); |
| if(!HAL_STATUS_SUCCESS(status)) |
| { |
| break; |
| } |
| status = csrScanGetResult(pMac, pScanFilter, &hBSSList); |
| if(!HAL_STATUS_SUCCESS(status)) |
| { |
| break; |
| } |
| if(hBSSList) |
| { |
| tANI_U8 i, nChn = 0; |
| pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList = |
| vos_mem_malloc(WNI_CFG_VALID_CHANNEL_LIST_LEN); |
| if ( NULL == pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList ) |
| status = eHAL_STATUS_FAILURE; |
| else |
| status = eHAL_STATUS_SUCCESS; |
| if (!HAL_STATUS_SUCCESS(status)) |
| { |
| break; |
| } |
| while(((pScanResult = csrScanResultGetNext(pMac, hBSSList)) != NULL) && |
| nChn < WNI_CFG_VALID_CHANNEL_LIST_LEN) |
| { |
| for(i = 0; i < nChn; i++) |
| { |
| if(pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[i] == |
| pScanResult->BssDescriptor.channelId) |
| { |
| break; |
| } |
| } |
| if(i == nChn) |
| { |
| pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[nChn++] = pScanResult->BssDescriptor.channelId; |
| } |
| } |
| pCommand->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = nChn; |
| } |
| } |
| vos_mem_copy(&pCommand->u.scanCmd.u.scanRequest.bssid, bAddr, sizeof(tCsrBssid)); |
| //Put to the head in pending queue |
| status = csrQueueSmeCommand(pMac, pCommand, eANI_BOOLEAN_TRUE); |
| if( !HAL_STATUS_SUCCESS( status ) ) |
| { |
| smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); |
| break; |
| } |
| } while( 0 ); |
| |
| if(!HAL_STATUS_SUCCESS(status)) |
| { |
| smsLog(pMac, LOGW, " csrScanRequestLostLink2 failed with status %d", status); |
| if(pCommand) |
| { |
| csrReleaseCommandScan(pMac, pCommand); |
| } |
| status = csrScanHandleFailedLostlink2( pMac, sessionId ); |
| } |
| if(pScanFilter) |
| { |
| csrFreeScanFilter(pMac, pScanFilter); |
| vos_mem_free(pScanFilter); |
| } |
| if(hBSSList) |
| { |
| csrScanResultPurge(pMac, hBSSList); |
| } |
| |
| return( status ); |
| } |
| |
| |
| //To actively scan all valid channels |
| eHalStatus csrScanRequestLostLink3( tpAniSirGlobal pMac, tANI_U32 sessionId ) |
| { |
| eHalStatus status = eHAL_STATUS_SUCCESS; |
| tSmeCmd *pCommand; |
| tANI_U8 bAddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; |
| |
| smsLog(pMac, LOGW, FL(" called")); |
| do |
| { |
| pCommand = csrGetCommandBuffer(pMac); |
| if(!pCommand) |
| { |
| status = eHAL_STATUS_RESOURCES; |
| break; |
| } |
| vos_mem_set(&pCommand->u.scanCmd, sizeof(tScanCmd), 0); |
| pCommand->command = eSmeCommandScan; |
| pCommand->sessionId = (tANI_U8)sessionId; |
| pCommand->u.scanCmd.reason = eCsrScanLostLink3; |
| pCommand->u.scanCmd.callback = NULL; |
| pCommand->u.scanCmd.pContext = NULL; |
| pCommand->u.scanCmd.u.scanRequest.maxChnTime = pMac->roam.configParam.nActiveMaxChnTime; |
| pCommand->u.scanCmd.u.scanRequest.minChnTime = pMac->roam.configParam.nActiveMinChnTime; |
| pCommand->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN; |
| vos_mem_copy(&pCommand->u.scanCmd.u.scanRequest.bssid, bAddr, sizeof(tCsrBssid)); |
| //Put to the head of pending queue |
| status = csrQueueSmeCommand(pMac, pCommand, eANI_BOOLEAN_TRUE); |
| if( !HAL_STATUS_SUCCESS( status ) ) |
| { |
| smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); |
| break; |
| } |
| } while( 0 ); |
| if(!HAL_STATUS_SUCCESS(status)) |
| { |
| smsLog(pMac, LOGW, " csrScanRequestLostLink3 failed with status %d", status); |
| if(csrRoamCompleteRoaming(pMac, sessionId, eANI_BOOLEAN_FALSE, eCSR_ROAM_RESULT_FAILURE)) |
| { |
| csrScanStartIdleScan(pMac); |
| } |
| if(pCommand) |
| { |
| csrReleaseCommandScan(pMac, pCommand); |
| } |
| } |
| |
| return( status ); |
| } |
| |
| |
| eHalStatus csrScanHandleSearchForSSID(tpAniSirGlobal pMac, tSmeCmd *pCommand) |
| { |
| eHalStatus status = eHAL_STATUS_FAILURE; |
| tScanResultHandle hBSSList = CSR_INVALID_SCANRESULT_HANDLE; |
| tCsrScanResultFilter *pScanFilter = NULL; |
| tCsrRoamProfile *pProfile = pCommand->u.scanCmd.pToRoamProfile; |
| tANI_U32 sessionId = pCommand->sessionId; |
| do |
| { |
| #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD |
| /* If this scan is for LFR */ |
| if (pMac->roam.neighborRoamInfo[sessionId].uOsRequestedHandoff) { |
| /* Notify LFR state m/c */ |
| if (eHAL_STATUS_SUCCESS != csrNeighborRoamSssidScanDone(pMac, |
| sessionId, |
| eHAL_STATUS_SUCCESS)) { |
| csrNeighborRoamStartLfrScan(pMac, sessionId); |
| } |
| status = eHAL_STATUS_SUCCESS; |
| break; |
| } |
| #endif |
| //If there is roam command waiting, ignore this roam because the newer roam command is the one to execute |
| if(csrIsRoamCommandWaitingForSession(pMac, sessionId)) |
| { |
| smsLog(pMac, LOGW, FL(" aborts because roam command waiting")); |
| break; |
| } |
| if(pProfile == NULL) |
| break; |
| pScanFilter = vos_mem_malloc(sizeof(tCsrScanResultFilter)); |
| if ( NULL == pScanFilter ) |
| status = eHAL_STATUS_FAILURE; |
| else |
| status = eHAL_STATUS_SUCCESS; |
| if (!HAL_STATUS_SUCCESS(status)) |
| break; |
| vos_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0); |
| status = csrRoamPrepareFilterFromProfile(pMac, pProfile, pScanFilter); |
| if(!HAL_STATUS_SUCCESS(status)) |
| break; |
| status = csrScanGetResult(pMac, pScanFilter, &hBSSList); |
| if(!HAL_STATUS_SUCCESS(status)) |
| break; |
| if (pMac->roam.roamSession[sessionId].connectState == |
| eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTING) { |
| smsLog(pMac, LOGE, FL("upper layer issued disconnetion")); |
| status = eHAL_STATUS_FAILURE; |
| break; |
| } |
| status = csrRoamIssueConnect(pMac, sessionId, pProfile, hBSSList, eCsrHddIssued, |
| pCommand->u.scanCmd.roamId, eANI_BOOLEAN_TRUE, eANI_BOOLEAN_TRUE); |
| if(!HAL_STATUS_SUCCESS(status)) |
| { |
| break; |
| } |
| }while(0); |
| if(!HAL_STATUS_SUCCESS(status)) |
| { |
| if(CSR_INVALID_SCANRESULT_HANDLE != hBSSList) |
| { |
| csrScanResultPurge(pMac, hBSSList); |
| } |
| //We haven't done anything to this profile |
| csrRoamCallCallback(pMac, sessionId, NULL, |
| pCommand->u.scanCmd.roamId, |
| eCSR_ROAM_ASSOCIATION_FAILURE, |
| eCSR_ROAM_RESULT_SCAN_FOR_SSID_FAILURE); |
| //In case we have nothing else to do, restart idle scan |
| if(csrIsConnStateDisconnected(pMac, sessionId) && !csrIsRoamCommandWaiting(pMac)) |
| { |
| status = csrScanStartIdleScan(pMac); |
| } |
| } |
| if (pScanFilter) |
| { |
| csrFreeScanFilter(pMac, pScanFilter); |
| vos_mem_free(pScanFilter); |
| } |
| |
| return (status); |
| } |
| |
| |
| eHalStatus csrScanHandleSearchForSSIDFailure(tpAniSirGlobal pMac, tSmeCmd *pCommand) |
| { |
| eHalStatus status = eHAL_STATUS_SUCCESS; |
| tANI_U32 sessionId = pCommand->sessionId; |
| tCsrRoamProfile *pProfile = pCommand->u.scanCmd.pToRoamProfile; |
| tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); |
| |
| if (!pSession) { |
| smsLog(pMac, LOGE, FL("Session %d not found"), sessionId); |
| return eHAL_STATUS_FAILURE; |
| } |
| |
| #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD |
| /* If this scan is for LFR */ |
| if (pMac->roam.neighborRoamInfo[sessionId].uOsRequestedHandoff) { |
| /* Notify LFR state m/c */ |
| if (eHAL_STATUS_SUCCESS != csrNeighborRoamSssidScanDone(pMac, |
| sessionId, |
| eHAL_STATUS_FAILURE)) { |
| csrNeighborRoamStartLfrScan(pMac, sessionId); |
| } |
| return eHAL_STATUS_SUCCESS; |
| } |
| #endif |
| |
| #if defined(WLAN_DEBUG) |
| if(pCommand->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs == 1) |
| { |
| char str[36]; |
| vos_mem_copy(str, |
| pCommand->u.scanCmd.u.scanRequest.SSIDs.SSIDList[0].SSID.ssId, |
| pCommand->u.scanCmd.u.scanRequest.SSIDs.SSIDList[0].SSID.length); |
| str[pCommand->u.scanCmd.u.scanRequest.SSIDs.SSIDList[0].SSID.length] = 0; |
| smsLog(pMac, LOGW, FL(" SSID = %s"), str); |
| } |
| #endif |
| //Check whether it is for start ibss. No need to do anything if it is a JOIN request |
| if(pProfile && CSR_IS_START_IBSS(pProfile)) |
| { |
| status = csrRoamIssueConnect(pMac, sessionId, pProfile, NULL, eCsrHddIssued, |
| pCommand->u.scanCmd.roamId, eANI_BOOLEAN_TRUE, eANI_BOOLEAN_TRUE); |
| if(!HAL_STATUS_SUCCESS(status)) |
| { |
| smsLog(pMac, LOGE, FL("failed to issue startIBSS command with status = 0x%08X"), status); |
| csrRoamCallCallback(pMac, sessionId, NULL, pCommand->u.scanCmd.roamId, eCSR_ROAM_FAILED, eCSR_ROAM_RESULT_FAILURE); |
| } |
| } |
| else |
| { |
| eCsrRoamResult roamResult = eCSR_ROAM_RESULT_FAILURE; |
| |
| if(csrIsConnStateDisconnected(pMac, sessionId) && |
| !csrIsRoamCommandWaitingForSession(pMac, sessionId)) |
| { |
| status = csrScanStartIdleScan(pMac); |
| } |
| if((NULL == pProfile) || !csrIsBssTypeIBSS(pProfile->BSSType)) |
| { |
| //Only indicate assoc_completion if we indicate assoc_start. |
| if(pSession->bRefAssocStartCnt > 0) |
| { |
| tCsrRoamInfo *pRoamInfo = NULL, roamInfo; |
| vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0); |
| pRoamInfo = &roamInfo; |
| if(pCommand->u.roamCmd.pRoamBssEntry) |
| { |
| tCsrScanResult *pScanResult = |
| GET_BASE_ADDR(pCommand->u.roamCmd.pRoamBssEntry, |
| tCsrScanResult, Link); |
| roamInfo.pBssDesc = &pScanResult->Result.BssDescriptor; |
| } |
| roamInfo.statusCode = pSession->joinFailStatusCode.statusCode; |
| roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode; |
| pSession->bRefAssocStartCnt--; |
| csrRoamCallCallback(pMac, sessionId, pRoamInfo, |
| pCommand->u.scanCmd.roamId, |
| eCSR_ROAM_ASSOCIATION_COMPLETION, |
| eCSR_ROAM_RESULT_SCAN_FOR_SSID_FAILURE); |
| } |
| else |
| { |
| csrRoamCallCallback(pMac, sessionId, NULL, |
| pCommand->u.scanCmd.roamId, |
| eCSR_ROAM_ASSOCIATION_FAILURE, |
| eCSR_ROAM_RESULT_SCAN_FOR_SSID_FAILURE); |
| } |
| } |
| else |
| { |
| roamResult = eCSR_ROAM_RESULT_IBSS_START_FAILED; |
| } |
| csrRoamCompletion(pMac, sessionId, NULL, pCommand, roamResult, eANI_BOOLEAN_FALSE); |
| } |
| |
| return (status); |
| } |
| |
| |
| //After scan for cap changes, issue a roaming command to either reconnect to the AP or pick another one to connect |
| eHalStatus csrScanHandleCapChangeScanComplete(tpAniSirGlobal pMac, tANI_U32 sessionId) |
| { |
| eHalStatus status = eHAL_STATUS_FAILURE; |
| tScanResultHandle hBSSList = NULL; |
| tCsrScanResultFilter *pScanFilter = NULL; |
| tANI_U32 roamId = 0; |
| tCsrRoamProfile *pProfile = NULL; |
| tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); |
| |
| do |
| { |
| //Here is the profile we need to connect to |
| pScanFilter = vos_mem_malloc(sizeof(tCsrScanResultFilter)); |
| if ( NULL == pScanFilter ) |
| status = eHAL_STATUS_FAILURE; |
| else |
| status = eHAL_STATUS_SUCCESS; |
| if (!HAL_STATUS_SUCCESS(status)) |
| break; |
| vos_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0); |
| if (NULL == pSession) break; |
| if (NULL == pSession->pCurRoamProfile) |
| { |
| pScanFilter->EncryptionType.numEntries = 1; |
| pScanFilter->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE; |
| } |
| else |
| { |
| //We have to make a copy of pCurRoamProfile because it will be free inside csrRoamIssueConnect |
| pProfile = vos_mem_malloc(sizeof(tCsrRoamProfile)); |
| if ( NULL == pProfile ) |
| status = eHAL_STATUS_FAILURE; |
| else |
| status = eHAL_STATUS_SUCCESS; |
| if(!HAL_STATUS_SUCCESS(status)) |
| break; |
| status = csrRoamCopyProfile(pMac, pProfile, pSession->pCurRoamProfile); |
| if(!HAL_STATUS_SUCCESS(status)) |
| break; |
| status = csrRoamPrepareFilterFromProfile(pMac, pProfile, pScanFilter); |
| }//We have a profile |
| roamId = GET_NEXT_ROAM_ID(&pMac->roam); |
| if(HAL_STATUS_SUCCESS(status)) |
| { |
| status = csrScanGetResult(pMac, pScanFilter, &hBSSList); |
| if(HAL_STATUS_SUCCESS(status)) |
| { |
| //we want to put the last connected BSS to the very beginning, if possible |
| csrMoveBssToHeadFromBSSID(pMac, &pSession->connectedProfile.bssid, hBSSList); |
| status = csrRoamIssueConnect(pMac, sessionId, pProfile, hBSSList, |
| eCsrCapsChange, 0, eANI_BOOLEAN_TRUE, eANI_BOOLEAN_TRUE); |
| if(!HAL_STATUS_SUCCESS(status)) |
| { |
| csrScanResultPurge(pMac, hBSSList); |
| } |
| }//Have scan result |
| else |
| { |
| smsLog(pMac, LOGW, FL("cannot find matching BSS of " |
| MAC_ADDRESS_STR), |
| MAC_ADDR_ARRAY(pSession->connectedProfile.bssid)); |
| //Disconnect |
| csrRoamDisconnectInternal(pMac, sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED); |
| } |
| } |
| }while(0); |
| if(pScanFilter) |
| { |
| csrFreeScanFilter(pMac, pScanFilter); |
| vos_mem_free(pScanFilter); |
| } |
| if(NULL != pProfile) |
| { |
| csrReleaseProfile(pMac, pProfile); |
| vos_mem_free(pProfile); |
| } |
| |
| return (status); |
| } |
| |
| |
| |
| eHalStatus csrScanResultPurge(tpAniSirGlobal pMac, tScanResultHandle hScanList) |
| { |
| eHalStatus status = eHAL_STATUS_INVALID_PARAMETER; |
| tScanResultList *pScanList = (tScanResultList *)hScanList; |
| |
| if(pScanList) |
| { |
| status = csrLLScanPurgeResult(pMac, &pScanList->List); |
| csrLLClose(&pScanList->List); |
| vos_mem_free(pScanList); |
| } |
| return (status); |
| } |
| |
| /** |
| * csr_get_altered_rssi() - Artificially increase/decrease RSSI |
| * @mac_ctx: Global MAC Context pointer. |
| * @rssi: Actual RSSI of the AP. |
| * @channel_id: Channel on which the AP is parked. |
| * @bssid: BSSID of the AP to connect to. |
| * |
| * This routine will apply the boost and penalty parameters |
| * if the channel_id is of 5G band and it will also apply |
| * the preferred bssid score if there is a match between |
| * the bssid and the global preferred bssid list. |
| * |
| * Return: The modified RSSI Value |
| */ |
| static int csr_get_altered_rssi(tpAniSirGlobal mac_ctx, int rssi, |
| uint8_t channel_id, tCsrBssid *bssid) |
| { |
| int modified_rssi; |
| int boost_factor; |
| int penalty_factor; |
| int i; |
| struct roam_ext_params *roam_params; |
| tCsrBssid local_bssid; |
| |
| modified_rssi = rssi; |
| vos_mem_set(&local_bssid, 0, VOS_MAC_ADDR_SIZE); |
| if (bssid) |
| vos_mem_copy(&local_bssid, bssid, VOS_MAC_ADDR_SIZE); |
| roam_params = &mac_ctx->roam.configParam.roam_params; |
| /* |
| * If the 5G pref feature is enabled, apply the roaming |
| * parameters to boost or penalize the rssi. |
| * Boost Factor = boost_factor * (Actual RSSI - boost Threshold) |
| * Penalty Factor = penalty factor * (penalty threshold - Actual RSSI) |
| */ |
| if (CSR_IS_SELECT_5G_PREFERRED(mac_ctx) && |
| CSR_IS_CHANNEL_5GHZ(channel_id)) { |
| if (rssi > roam_params->raise_rssi_thresh_5g) { |
| /* Check and boost the threshold*/ |
| boost_factor = roam_params->raise_factor_5g * |
| (rssi - roam_params->raise_rssi_thresh_5g); |
| /* Check and penalize the threshold */ |
| modified_rssi += CSR_MIN(roam_params->max_raise_rssi_5g, |
| boost_factor); |
| } else if(rssi < roam_params->drop_rssi_thresh_5g) { |
| penalty_factor = roam_params->drop_factor_5g * |
| (roam_params->drop_rssi_thresh_5g - rssi); |
| modified_rssi -= CSR_MAX(roam_params->max_drop_rssi_5g, |
| penalty_factor); |
| } |
| VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, |
| FL("5G BSSID("MAC_ADDRESS_STR") AR:%d, MR:%d, ch=%d"), |
| MAC_ADDR_ARRAY(local_bssid), rssi, |
| modified_rssi, channel_id); |
| } |
| /* |
| * Check if there are preferred bssid and then apply the |
| * preferred score |
| */ |
| if (roam_params->num_bssid_favored) { |
| for (i=0; i<roam_params->num_bssid_favored; i++) { |
| if (!csrIsMacAddressEqual(mac_ctx, |
| &roam_params->bssid_favored[i], bssid)) |
| continue; |
| modified_rssi += roam_params->bssid_favored_factor[i]; |
| VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, |
| FL("Pref: ("MAC_ADDRESS_STR") AR:%d, MR:%d, ch=%d"), |
| MAC_ADDR_ARRAY(local_bssid), rssi, modified_rssi, |
| channel_id); |
| } |
| } |
| return modified_rssi; |
| } |
| |
| /** |
| * csrGetBssPreferValue() - Get BSS Preference Value |
| * @pMac: Global MAC Context pointer. |
| * @rssi: Actual RSSI of the AP. |
| * @bssid: BSSID of the AP to connect to. |
| * @channel_id: Channel on which the AP is parked. |
| * |
| * |
| * This routine helps in determining the preference value |
| * of a particular BSS in the scan result which is further |
| * used in the sorting logic of the final candidate AP's. |
| * |
| * Return: The preference Value for a BSS. |
| */ |
| static tANI_U32 csrGetBssPreferValue(tpAniSirGlobal pMac, int rssi, |
| tCsrBssid *bssid, int channel_id) |
| { |
| tANI_U32 ret = 0; |
| int i, modified_rssi; |
| |
| /* |
| * The RSSI does not get modified in case the 5G |
| * preference or preferred BSSID is not applicable |
| */ |
| modified_rssi = csr_get_altered_rssi(pMac, rssi, channel_id, bssid); |
| |
| i = CSR_NUM_RSSI_CAT - 1; |
| while(i >= 0) { |
| if(modified_rssi >= pMac->roam.configParam.RSSICat[i]) { |
| ret = pMac->roam.configParam.BssPreferValue[i]; |
| break; |
| } |
| i--; |
| }; |
| return (ret); |
| } |
| |
| |
| //Return a CapValue base on the capabilities of a BSS |
| static tANI_U32 csrGetBssCapValue(tpAniSirGlobal pMac, tSirBssDescription *pBssDesc, tDot11fBeaconIEs *pIes) |
| { |
| tANI_U32 ret = CSR_BSS_CAP_VALUE_NONE; |
| #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) |
| if(CSR_IS_ROAM_PREFER_5GHZ(pMac) || CSR_IS_SELECT_5G_PREFERRED(pMac)) |
| { |
| if((pBssDesc) && CSR_IS_CHANNEL_5GHZ(pBssDesc->channelId)) |
| { |
| ret += CSR_BSS_CAP_VALUE_5GHZ; |
| } |
| } |
| #endif |
| /* if strict select 5GHz is non-zero then ignore the capability checking */ |
| if (pIes && !CSR_IS_SELECT_5GHZ_MARGIN(pMac)) |
| { |
| //We only care about 11N capability |
| if (pIes->VHTCaps.present) |
| ret += CSR_BSS_CAP_VALUE_VHT; |
| else if (pIes->HTCaps.present) |
| ret += CSR_BSS_CAP_VALUE_HT; |
| if(CSR_IS_QOS_BSS(pIes)) |
| { |
| ret += CSR_BSS_CAP_VALUE_WMM; |
| //Give advantage to UAPSD |
| if(CSR_IS_UAPSD_BSS(pIes)) |
| { |
| ret += CSR_BSS_CAP_VALUE_UAPSD; |
| } |
| } |
| } |
| |
| return (ret); |
| } |
| |
| /** |
| * csr_is_better_rssi() - Is bss1 better than bss2 |
| * @mac_ctx: Global MAC Context pointer. |
| * @bss1: Pointer to the first BSS. |
| * @bss2: Pointer to the second BSS. |
| * |
| * |
| * This routine helps in determining the preference value |
| * of a particular BSS in the scan result which is further |
| * used in the sorting logic of the final candidate AP's. |
| * |
| * Return: true, if bss1 is better than bss2 |
| * false, if bss2 is better than bss1. |
| */ |
| static bool csr_is_better_rssi(tpAniSirGlobal mac_ctx, |
| tCsrScanResult *bss1, tCsrScanResult *bss2) |
| { |
| bool ret; |
| int rssi1, rssi2; |
| |
| rssi1 = bss1->Result.BssDescriptor.rssi; |
| rssi2 = bss2->Result.BssDescriptor.rssi; |
| /* |
| * Apply the boost and penlty logic and check |
| * which is the best RSSI |
| */ |
| rssi1 = csr_get_altered_rssi(mac_ctx, rssi1, |
| bss1->Result.BssDescriptor.channelId, |
| &bss1->Result.BssDescriptor.bssId); |
| rssi2 = csr_get_altered_rssi(mac_ctx, rssi2, |
| bss2->Result.BssDescriptor.channelId, |
| &bss2->Result.BssDescriptor.bssId); |
| if (CSR_IS_BETTER_RSSI(rssi1, rssi2)) |
| ret = true; |
| else |
| ret = false; |
| return ret; |
| } |
| /* To check whether pBss1 is better than pBss2 */ |
| static tANI_BOOLEAN csrIsBetterBss(tpAniSirGlobal mac_ctx, |
| tCsrScanResult *pBss1, tCsrScanResult *pBss2) |
| { |
| tANI_BOOLEAN ret; |
| |
| if(CSR_IS_BETTER_PREFER_VALUE(pBss1->preferValue, pBss2->preferValue)) |
| ret = eANI_BOOLEAN_TRUE; |
| else if(CSR_IS_EQUAL_PREFER_VALUE |
| (pBss1->preferValue, pBss2->preferValue)) { |
| if(CSR_IS_BETTER_CAP_VALUE(pBss1->capValue, pBss2->capValue)) |
| ret = eANI_BOOLEAN_TRUE; |
| else if (CSR_IS_EQUAL_CAP_VALUE |
| (pBss1->capValue, pBss2->capValue)) { |
| if (csr_is_better_rssi(mac_ctx, pBss1, pBss2)) |
| ret = eANI_BOOLEAN_TRUE; |
| else |
| ret = eANI_BOOLEAN_FALSE; |
| } |
| else |
| ret = eANI_BOOLEAN_FALSE; |
| } |
| else |
| ret = eANI_BOOLEAN_FALSE; |
| |
| return (ret); |
| } |
| |
| |
| #ifdef FEATURE_WLAN_LFR |
| //Add the channel to the occupiedChannels array |
| static void csrScanAddToOccupiedChannels( |
| tpAniSirGlobal pMac, |
| tCsrScanResult *pResult, |
| tANI_U8 sessionId, |
| tCsrChannel *pOccupiedChannels, |
| tDot11fBeaconIEs *pIes) |
| { |
| eHalStatus status; |
| tANI_U8 channel; |
| tANI_U8 numOccupiedChannels = pOccupiedChannels->numChannels; |
| tANI_U8 *pOccupiedChannelList = pOccupiedChannels->channelList; |
| |
| channel = pResult->Result.BssDescriptor.channelId; |
| |
| if (!csrIsChannelPresentInList(pOccupiedChannelList, numOccupiedChannels, channel) |
| && csrNeighborRoamConnectedProfileMatch(pMac, sessionId, pResult, pIes)) |
| { |
| status = csrAddToChannelListFront(pOccupiedChannelList, numOccupiedChannels, channel); |
| if(HAL_STATUS_SUCCESS(status)) |
| { |
| pOccupiedChannels->numChannels++; |
| smsLog(pMac, LOG2, FL("Added channel %d to the list (count=%d)"), |
| channel, pOccupiedChannels->numChannels); |
| if (pOccupiedChannels->numChannels > CSR_BG_SCAN_OCCUPIED_CHANNEL_LIST_LEN) |
| pOccupiedChannels->numChannels = CSR_BG_SCAN_OCCUPIED_CHANNEL_LIST_LEN; |
| } |
| } |
| } |
| #endif |
| |
| //Put the BSS into the scan result list |
| //pIes can not be NULL |
| static void csrScanAddResult(tpAniSirGlobal pMac, tCsrScanResult *pResult, |
| tDot11fBeaconIEs *pIes, tANI_U32 sessionId) |
| { |
| #ifdef FEATURE_WLAN_LFR |
| tpCsrNeighborRoamControlInfo pNeighborRoamInfo = |
| &pMac->roam.neighborRoamInfo[sessionId]; |
| #endif |
| tCsrBssid *bssid = &pResult->Result.BssDescriptor.bssId; |
| uint8_t channel_id = pResult->Result.BssDescriptor.channelId; |
| pResult->preferValue = csrGetBssPreferValue(pMac, |
| (int)pResult->Result.BssDescriptor.rssi, bssid, channel_id); |
| pResult->capValue = |
| csrGetBssCapValue(pMac, &pResult->Result.BssDescriptor, pIes); |
| csrLLInsertTail( &pMac->scan.scanResultList, &pResult->Link, LL_ACCESS_LOCK ); |
| #ifdef FEATURE_WLAN_LFR |
| if(0 == pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels) |
| { |
| /* Build the occupied channel list, only if "gNeighborScanChannelList" is |
| NOT set in the cfg.ini file */ |
| csrScanAddToOccupiedChannels(pMac, pResult, sessionId, |
| &pMac->scan.occupiedChannels[sessionId], |
| pIes); |
| } |
| #endif |
| } |
| |
| |
| eHalStatus csrScanGetResult(tpAniSirGlobal pMac, tCsrScanResultFilter *pFilter, tScanResultHandle *phResult) |
| { |
| eHalStatus status; |
| tScanResultList *pRetList; |
| tCsrScanResult *pResult, *pBssDesc; |
| tANI_U32 count = 0; |
| tListElem *pEntry; |
| tANI_U32 bssLen, allocLen; |
| eCsrEncryptionType uc = eCSR_ENCRYPT_TYPE_NONE, mc = eCSR_ENCRYPT_TYPE_NONE; |
| eCsrAuthType auth = eCSR_AUTH_TYPE_OPEN_SYSTEM; |
| tDot11fBeaconIEs *pIes, *pNewIes; |
| tANI_BOOLEAN fMatch; |
| tANI_U16 i = 0; |
| struct roam_ext_params *roam_params = NULL; |
| |
| if(phResult) |
| { |
| *phResult = CSR_INVALID_SCANRESULT_HANDLE; |
| } |
| |
| if (pMac->roam.configParam.nSelect5GHzMargin || |
| CSR_IS_SELECT_5G_PREFERRED(pMac)) |
| { |
| pMac->scan.inScanResultBestAPRssi = -128; |
| roam_params = &pMac->roam.configParam.roam_params; |
| #ifdef WLAN_DEBUG_ROAM_OFFLOAD |
| VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, |
| FL("nSelect5GHzMargin")); |
| #endif |
| csrLLLock(&pMac->scan.scanResultList); |
| /* For 5G preference feature, there is no |
| * need to check the filter match and also re-program the |
| * RSSI bucket categories, since we use the RSSI values |
| * while setting the preference value for the BSS. |
| * There is no need to check the match for roaming since |
| * it is already done.*/ |
| if(!CSR_IS_SELECT_5G_PREFERRED(pMac)) { |
| /* Find out the best AP Rssi going thru the scan results */ |
| pEntry = csrLLPeekHead(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK); |
| while ( NULL != pEntry) |
| { |
| pBssDesc = GET_BASE_ADDR( pEntry, tCsrScanResult, Link ); |
| fMatch = FALSE; |
| |
| |
| if (pFilter) |
| for(i = 0; i < pFilter->SSIDs.numOfSSIDs; i++) |
| { |
| fMatch = csrIsSsidMatch( pMac, pFilter->SSIDs.SSIDList[i].SSID.ssId, pFilter->SSIDs.SSIDList[i].SSID.length, |
| pBssDesc->Result.ssId.ssId, |
| pBssDesc->Result.ssId.length, eANI_BOOLEAN_TRUE ); |
| if (fMatch) |
| { |
| pIes = (tDot11fBeaconIEs *)( pBssDesc->Result.pvIes ); |
| |
| //At this time, pBssDescription->Result.pvIes may be NULL |
| if( !pIes && (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, |
| &pBssDesc->Result.BssDescriptor, &pIes))) ) |
| { |
| continue; |
| } |
| |
| smsLog(pMac, LOG1, FL("SSID Matched")); |
| |
| if ( pFilter->bOSENAssociation ) |
| { |
| fMatch = TRUE; |
| } |
| else |
| { |
| #ifdef WLAN_FEATURE_11W |
| fMatch = csrIsSecurityMatch(pMac, &pFilter->authType, |
| &pFilter->EncryptionType, |
| &pFilter->mcEncryptionType, |
| &pFilter->MFPEnabled, |
| &pFilter->MFPRequired, |
| &pFilter->MFPCapable, |
| &pBssDesc->Result.BssDescriptor, |
| pIes, NULL, NULL, NULL ); |
| #else |
| fMatch = csrIsSecurityMatch(pMac, &pFilter->authType, |
| &pFilter->EncryptionType, |
| &pFilter->mcEncryptionType, |
| NULL, NULL, NULL, |
| &pBssDesc->Result.BssDescriptor, |
| pIes, NULL, NULL, NULL ); |
| #endif |
| } |
| if ((pBssDesc->Result.pvIes == NULL) && pIes) |
| vos_mem_free(pIes); |
| |
| if (fMatch) |
| smsLog(pMac, LOG1, FL(" Security Matched")); |
| } |
| } |
| |
| if (fMatch && (pBssDesc->Result.BssDescriptor.rssi > pMac->scan.inScanResultBestAPRssi)) |
| { |
| smsLog(pMac, LOG1, FL("Best AP Rssi changed from %d to %d"), |
| pMac->scan.inScanResultBestAPRssi, |
| pBssDesc->Result.BssDescriptor.rssi); |
| pMac->scan.inScanResultBestAPRssi = pBssDesc->Result.BssDescriptor.rssi; |
| } |
| pEntry = csrLLNext(&pMac->scan.scanResultList, pEntry, LL_ACCESS_NOLOCK); |
| } |
| } |
| |
| if ((-128 != pMac->scan.inScanResultBestAPRssi) || |
| CSR_IS_SELECT_5G_PREFERRED(pMac)) |
| { |
| smsLog(pMac, LOG1, FL("Best AP Rssi is %d"), pMac->scan.inScanResultBestAPRssi); |
| /* Modify Rssi category based on best AP Rssi */ |
| if (-128 != pMac->scan.inScanResultBestAPRssi) |
| csrAssignRssiForCategory(pMac, pMac->scan.inScanResultBestAPRssi, pMac->roam.configParam.bCatRssiOffset); |
| |
| pEntry = csrLLPeekHead(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK); |
| while ( NULL != pEntry) |
| { |
| pBssDesc = GET_BASE_ADDR( pEntry, tCsrScanResult, Link ); |
| |
| /* re-assign preference value based on (modified rssi bucket (or) |
| * prefer 5G feature.*/ |
| pBssDesc->preferValue = csrGetBssPreferValue(pMac, |
| (int)pBssDesc->Result.BssDescriptor.rssi, |
| &pBssDesc->Result.BssDescriptor.bssId, |
| pBssDesc->Result.BssDescriptor.channelId); |
| |
| smsLog(pMac, LOG2, FL("BSSID("MAC_ADDRESS_STR |
| ") Rssi(%d) Chnl(%d) PrefVal(%u) SSID=%.*s"), |
| MAC_ADDR_ARRAY(pBssDesc->Result.BssDescriptor.bssId), |
| pBssDesc->Result.BssDescriptor.rssi, |
| pBssDesc->Result.BssDescriptor.channelId, |
| pBssDesc->preferValue, |
| pBssDesc->Result.ssId.length, pBssDesc->Result.ssId.ssId); |
| |
| pEntry = csrLLNext(&pMac->scan.scanResultList, pEntry, LL_ACCESS_NOLOCK); |
| } |
| } |
| |
| csrLLUnlock(&pMac->scan.scanResultList); |
| } |
| |
| pRetList = vos_mem_malloc(sizeof(tScanResultList)); |
| if ( NULL == pRetList ) |
| status = eHAL_STATUS_FAILURE; |
| else |
| { |
| status = eHAL_STATUS_SUCCESS; |
| vos_mem_set(pRetList, sizeof(tScanResultList), 0); |
| csrLLOpen(pMac->hHdd, &pRetList->List); |
| pRetList->pCurEntry = NULL; |
| |
| csrLLLock(&pMac->scan.scanResultList); |
| pEntry = csrLLPeekHead( &pMac->scan.scanResultList, LL_ACCESS_NOLOCK ); |
| while( pEntry ) |
| { |
| pBssDesc = GET_BASE_ADDR( pEntry, tCsrScanResult, Link ); |
| pIes = (tDot11fBeaconIEs *)( pBssDesc->Result.pvIes ); |
| /* |
| * If pBssDesc->Result.pvIes is NULL, we need to free any memory |
| * allocated by csrMatchBSS for any error condition, otherwise, |
| * it will be freed later. |
| */ |
| fMatch = eANI_BOOLEAN_FALSE; |
| pNewIes = NULL; |
| |
| if(pFilter) |
| { |
| fMatch = csrMatchBSS(pMac, &pBssDesc->Result.BssDescriptor, pFilter, &auth, &uc, &mc, &pIes); |
| #ifdef WLAN_DEBUG_ROAM_OFFLOAD |
| VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, |
| FL("csrMatchBSS fmatch %d"), fMatch); |
| #endif |
| if( NULL != pIes ) |
| { |
| //Only save it when matching |
| if(fMatch) |
| { |
| if( !pBssDesc->Result.pvIes ) |
| { |
| //csrMatchBSS allocates the memory. Simply pass it and it is freed later |
| pNewIes = pIes; |
| } |
| else |
| { |
| //The pIes is allocated by someone else. make a copy |
| //Only to save parsed IEs if caller provides a filter. Most likely the caller |
| //is using to for association, hence save the parsed IEs |
| pNewIes = vos_mem_malloc(sizeof(tDot11fBeaconIEs)); |
| if ( NULL == pNewIes ) |
| status = eHAL_STATUS_FAILURE; |
| else |
| status = eHAL_STATUS_SUCCESS; |
| if ( HAL_STATUS_SUCCESS( status ) ) |
| { |
| vos_mem_copy(pNewIes, pIes, sizeof( tDot11fBeaconIEs )); |
| } |
| else |
| { |
| smsLog(pMac, LOGE, FL(" fail to allocate memory for IEs")); |
| //Need to free memory allocated by csrMatchBSS |
| if( !pBssDesc->Result.pvIes ) |
| { |
| vos_mem_free(pIes); |
| } |
| break; |
| } |
| } |
| }//fMatch |
| else if( !pBssDesc->Result.pvIes ) |
| { |
| vos_mem_free(pIes); |
| } |
| } |
| } |
| if(NULL == pFilter || fMatch) |
| { |
| bssLen = pBssDesc->Result.BssDescriptor.length + sizeof(pBssDesc->Result.BssDescriptor.length); |
| allocLen = sizeof( tCsrScanResult ) + bssLen; |
| pResult = vos_mem_malloc(allocLen); |
| if ( NULL == pResult ) |
| status = eHAL_STATUS_FAILURE; |
| else |
| status = eHAL_STATUS_SUCCESS; |
| if(!HAL_STATUS_SUCCESS(status)) |
| { |
| smsLog(pMac, LOGE, FL(" fail to allocate memory for scan result, len=%d"), allocLen); |
| if(pNewIes) |
| { |
| vos_mem_free(pNewIes); |
| } |
| break; |
| } |
| vos_mem_set(pResult, allocLen, 0); |
| pResult->capValue = pBssDesc->capValue; |
| pResult->preferValue = pBssDesc->preferValue; |
| pResult->ucEncryptionType = uc; |
| pResult->mcEncryptionType = mc; |
| pResult->authType = auth; |
| pResult->Result.ssId = pBssDesc->Result.ssId; |
| pResult->Result.timer = pBssDesc->Result.timer; |
| //save the pIes for later use |
| pResult->Result.pvIes = pNewIes; |
| //save bss description |
| vos_mem_copy(&pResult->Result.BssDescriptor, |
| &pBssDesc->Result.BssDescriptor, bssLen); |
| //No need to lock pRetList because it is locally allocated and no outside can access it at this time |
| if(csrLLIsListEmpty(&pRetList->List, LL_ACCESS_NOLOCK)) |
| { |
| csrLLInsertTail(&pRetList->List, &pResult->Link, LL_ACCESS_NOLOCK); |
| } else if(pFilter && |
| vos_mem_compare(pResult->Result.BssDescriptor.bssId, |
| pFilter->bssid_hint, VOS_MAC_ADDR_SIZE)) { |
| /* bssid hint AP should be on head */ |
| csrLLInsertHead(&pRetList->List, |
| &pResult->Link, LL_ACCESS_NOLOCK); |
| } |
| else |
| { |
| //To sort the list |
| tListElem *pTmpEntry; |
| tCsrScanResult *pTmpResult; |
| |
| pTmpEntry = csrLLPeekHead(&pRetList->List, LL_ACCESS_NOLOCK); |
| while(pTmpEntry) |
| { |
| pTmpResult = GET_BASE_ADDR( pTmpEntry, tCsrScanResult, Link ); |
| |
| /* Skip the bssid hint AP, as it should be on head */ |
| if (pFilter && |
| vos_mem_compare( |
| pTmpResult->Result.BssDescriptor.bssId, |
| pFilter->bssid_hint, VOS_MAC_ADDR_SIZE)) { |
| pTmpEntry = csrLLNext(&pRetList->List, |
| pTmpEntry, LL_ACCESS_NOLOCK); |
| continue; |
| } |
| |
| if (csrIsBetterBss(pMac, pResult, pTmpResult)) |
| { |
| csrLLInsertEntry(&pRetList->List, pTmpEntry, &pResult->Link, LL_ACCESS_NOLOCK); |
| //To indicate we are done |
| pResult = NULL; |
| break; |
| } |
| pTmpEntry = csrLLNext(&pRetList->List, pTmpEntry, LL_ACCESS_NOLOCK); |
| } |
| if(pResult != NULL) |
| { |
| /* This one is'nt better than anyone or the first one */ |
| csrLLInsertTail(&pRetList->List, &pResult->Link, LL_ACCESS_NOLOCK); |
| } |
| } |
| count++; |
| } |
| pEntry = csrLLNext( &pMac->scan.scanResultList, pEntry, LL_ACCESS_NOLOCK ); |
| }//while |
| csrLLUnlock(&pMac->scan.scanResultList); |
| |
| smsLog(pMac, LOG2, FL("return %d BSS"), csrLLCount(&pRetList->List)); |
| |
| if( !HAL_STATUS_SUCCESS(status) || (phResult == NULL) ) |
| { |
| //Fail or No one wants the result. |
| csrScanResultPurge(pMac, (tScanResultHandle)pRetList); |
| } |
| else |
| { |
| if(0 == count) |
| { |
| //We are here meaning the there is no match |
| csrLLClose(&pRetList->List); |
| vos_mem_free(pRetList); |
| status = eHAL_STATUS_E_NULL_VALUE; |
| } |
| else if(phResult) |
| { |
| *phResult = pRetList; |
| } |
| } |
| }//Allocated pRetList |
| |
| return (status); |
| } |
| |
| /* |
| * NOTE: This routine is being added to make |
| * sure that scan results are not being flushed |
| * while roaming. If the scan results are flushed, |
| * we are unable to recover from |
| * csrRoamRoamingStateDisassocRspProcessor. |
| * If it is needed to remove this routine, |
| * first ensure that we recover gracefully from |
| * csrRoamRoamingStateDisassocRspProcessor if |
| * csrScanGetResult returns with a failure because |
| * of not being able to find the roaming BSS. |
| */ |
| tANI_U8 csrScanFlushDenied(tpAniSirGlobal pMac, tANI_U8 sessionId) |
| { |
| switch(pMac->roam.neighborRoamInfo[sessionId].neighborRoamState) { |
| case eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN: |
| case eCSR_NEIGHBOR_ROAM_STATE_PREAUTHENTICATING: |
| case eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE: |
| case eCSR_NEIGHBOR_ROAM_STATE_REASSOCIATING: |
| return (pMac->roam.neighborRoamInfo[sessionId].neighborRoamState); |
| default: |
| return 0; |
| } |
| } |
| |
| eHalStatus csrScanFlushResult(tpAniSirGlobal pMac, tANI_U8 sessionId) |
| { |
| tANI_U8 isFlushDenied = csrScanFlushDenied(pMac, sessionId); |
| eHalStatus status = eHAL_STATUS_SUCCESS; |
| tSirMbMsg *pMsg; |
| tANI_U16 msgLen; |
| |
| if (isFlushDenied) { |
| smsLog(pMac, LOGW, "%s: scan flush denied in roam state %d", |
| __func__, isFlushDenied); |
| return eHAL_STATUS_FAILURE; |
| } |
| |
| /* prepare and send clear cached scan results msg to lim */ |
| msgLen = (tANI_U16)(sizeof( tSirMbMsg )); |
| pMsg = vos_mem_malloc(msgLen); |
| if ( NULL != pMsg ) { |
| vos_mem_set((void *)pMsg, msgLen, 0); |
| pMsg->type = pal_cpu_to_be16((tANI_U16)eWNI_SME_CLEAR_LIM_SCAN_CACHE); |
| pMsg->msgLen = pal_cpu_to_be16(msgLen); |
| palSendMBMessage(pMac->hHdd, pMsg); |
| } else { |
| status = eHAL_STATUS_FAILED_ALLOC; |
| } |
| |
| csrLLScanPurgeResult( pMac, &pMac->scan.tempScanResults ); |
| csrLLScanPurgeResult( pMac, &pMac->scan.scanResultList ); |
| return( status ); |
| } |
| |
| eHalStatus csrScanFlushSelectiveResult(tpAniSirGlobal pMac, v_BOOL_t flushP2P) |
| { |
| eHalStatus status = eHAL_STATUS_SUCCESS; |
| tListElem *pEntry,*pFreeElem; |
| tCsrScanResult *pBssDesc; |
| tDblLinkList *pList = &pMac->scan.scanResultList; |
| |
| csrLLLock(pList); |
| |
| pEntry = csrLLPeekHead( pList, LL_ACCESS_NOLOCK ); |
| while( pEntry != NULL) |
| { |
| pBssDesc = GET_BASE_ADDR( pEntry, tCsrScanResult, Link ); |
| if( flushP2P == vos_mem_compare( pBssDesc->Result.ssId.ssId, |
| "DIRECT-", 7) ) |
| { |
| pFreeElem = pEntry; |
| pEntry = csrLLNext(pList, pEntry, LL_ACCESS_NOLOCK); |
| csrLLRemoveEntry(pList, pFreeElem, LL_ACCESS_NOLOCK); |
| csrFreeScanResultEntry( pMac, pBssDesc ); |
| continue; |
| } |
| pEntry = csrLLNext(pList, pEntry, LL_ACCESS_NOLOCK); |
| } |
| |
| csrLLUnlock(pList); |
| |
| return (status); |
| } |
| |
| void csrScanFlushBssEntry(tpAniSirGlobal pMac, |
| tpSmeCsaOffloadInd pCsaOffloadInd) |
| { |
| tListElem *pEntry,*pFreeElem; |
| tCsrScanResult *pBssDesc; |
| tDblLinkList *pList = &pMac->scan.scanResultList; |
| |
| csrLLLock(pList); |
| |
| pEntry = csrLLPeekHead( pList, LL_ACCESS_NOLOCK ); |
| while( pEntry != NULL) |
| { |
| pBssDesc = GET_BASE_ADDR( pEntry, tCsrScanResult, Link ); |
| if( vos_mem_compare(pBssDesc->Result.BssDescriptor.bssId, |
| pCsaOffloadInd->bssId, sizeof(tSirMacAddr)) ) |
| { |
| pFreeElem = pEntry; |
| pEntry = csrLLNext(pList, pEntry, LL_ACCESS_NOLOCK); |
| csrLLRemoveEntry(pList, pFreeElem, LL_ACCESS_NOLOCK); |
| csrFreeScanResultEntry( pMac, pBssDesc ); |
| smsLog( pMac, LOG1, FL("Removed BSS entry:%pM"), |
| pCsaOffloadInd->bssId); |
| continue; |
| } |
| |
| pEntry = csrLLNext(pList, pEntry, LL_ACCESS_NOLOCK); |
| } |
| |
| csrLLUnlock(pList); |
| } |
| |
| /** |
| * csrCheck11dChannel |
| * |
| *FUNCTION: |
| * This function is called from csrScanFilterResults function and |
| * compare channel number with given channel list. |
| * |
| *LOGIC: |
| * Check Scan result channel number with CFG channel list |
| * |
| *ASSUMPTIONS: |
| * |
| * |
| *NOTE: |
| * |
| * @param channelId channel number |
| * @param pChannelList Pointer to channel list |
| * @param numChannels Number of channel in channel list |
| * |
| * @return Status |
| */ |
| |
| eHalStatus csrCheck11dChannel(tANI_U8 channelId, tANI_U8 *pChannelList, tANI_U32 numChannels) |
| { |
| eHalStatus status = eHAL_STATUS_FAILURE; |
| tANI_U8 i = 0; |
| |
| for (i = 0; i < numChannels; i++) |
| { |
| if(pChannelList[ i ] == channelId) |
| { |
| status = eHAL_STATUS_SUCCESS; |
| break; |
| } |
| } |
| return status; |
| } |
| |
| /** |
| * csrScanFilterResults |
| * |
| *FUNCTION: |
| * This function is called from csrApplyCountryInformation function and |
| * filter scan result based on valid channel list number. |
| * |
| *LOGIC: |
| * Get scan result from scan list and Check Scan result channel number |
| * with 11d channel list if channel number is found in 11d channel list |
| * then do not remove scan result entry from scan list |
| * |
| *ASSUMPTIONS: |
| * |
| * |
| *NOTE: |
| * |
| * @param pMac Pointer to Global MAC structure |
| * |
| * @return Status |
| */ |
| |
| eHalStatus csrScanFilterResults(tpAniSirGlobal pMac) |
| { |
| eHalStatus status = eHAL_STATUS_SUCCESS; |
| tListElem *pEntry,*pTempEntry; |
| tCsrScanResult *pBssDesc; |
| tANI_U32 len = sizeof(pMac->roam.validChannelList); |
| |
| /* Get valid channels list from CFG */ |
| if (!HAL_STATUS_SUCCESS(csrGetCfgValidChannels(pMac, |
| pMac->roam.validChannelList, &len))) |
| { |
| smsLog( pMac, LOGE, "Failed to get Channel list from CFG"); |
| } |
| |
| csrLLLock(&pMac->scan.scanResultList); |
| |
| pEntry = csrLLPeekHead(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK); |
| while( pEntry ) |
| { |
| pBssDesc = GET_BASE_ADDR( pEntry, tCsrScanResult, Link ); |
| pTempEntry = csrLLNext(&pMac->scan.scanResultList, pEntry, |
| LL_ACCESS_NOLOCK); |
| if(csrCheck11dChannel(pBssDesc->Result.BssDescriptor.channelId, |
| pMac->roam.validChannelList, len)) |
| { |
| /* Remove Scan result which does not have 11d channel */ |
| if( csrLLRemoveEntry(&pMac->scan.scanResultList, pEntry, |
| LL_ACCESS_NOLOCK)) |
| { |
| csrFreeScanResultEntry( pMac, pBssDesc ); |
| } |
| } |
| pEntry = pTempEntry; |
| } |
| |
| csrLLUnlock(&pMac->scan.scanResultList); |
| csrLLLock(&pMac->scan.tempScanResults); |
| |
| pEntry = csrLLPeekHead(&pMac->scan.tempScanResults, LL_ACCESS_NOLOCK); |
| while( pEntry ) |
| { |
| pBssDesc = GET_BASE_ADDR( pEntry, tCsrScanResult, Link ); |
| pTempEntry = csrLLNext(&pMac->scan.tempScanResults, pEntry, |
| LL_ACCESS_NOLOCK); |
| if(csrCheck11dChannel(pBssDesc->Result.BssDescriptor.channelId, |
| pMac->roam.validChannelList, len)) |
| { |
| /* Remove Scan result which does not have 11d channel */ |
| if(csrLLRemoveEntry(&pMac->scan.tempScanResults, pEntry, |
| LL_ACCESS_NOLOCK)) |
| { |
| csrFreeScanResultEntry( pMac, pBssDesc ); |
| } |
| } |
| else |
| { |
| smsLog( pMac, LOG1, FL("%d is a Valid channel"), |
| pBssDesc->Result.BssDescriptor.channelId); |
| } |
| pEntry = pTempEntry; |
| } |
| |
| csrLLUnlock(&pMac->scan.tempScanResults); |
| return status; |
| } |
| |
| |
| eHalStatus csrScanCopyResultList(tpAniSirGlobal pMac, tScanResultHandle hIn, tScanResultHandle *phResult) |
| { |
| eHalStatus status = eHAL_STATUS_SUCCESS; |
| tScanResultList *pRetList, *pInList = (tScanResultList *)hIn; |
| tCsrScanResult *pResult, *pScanResult; |
| tANI_U32 count = 0; |
| tListElem *pEntry; |
| tANI_U32 bssLen, allocLen; |
| |
| if(phResult) |
| { |
| *phResult = CSR_INVALID_SCANRESULT_HANDLE; |
| } |
| pRetList = vos_mem_malloc(sizeof(tScanResultList)); |
| if ( NULL == pRetList ) |
| status = eHAL_STATUS_FAILURE; |
| else |
| { |
| vos_mem_set(pRetList, sizeof(tScanResultList), 0); |
| csrLLOpen(pMac->hHdd, &pRetList->List); |
| pRetList->pCurEntry = NULL; |
| csrLLLock(&pMac->scan.scanResultList); |
| csrLLLock(&pInList->List); |
| |
| pEntry = csrLLPeekHead( &pInList->List, LL_ACCESS_NOLOCK ); |
| while( pEntry ) |
| { |
| pScanResult = GET_BASE_ADDR( pEntry, tCsrScanResult, Link ); |
| bssLen = pScanResult->Result.BssDescriptor.length + sizeof(pScanResult->Result.BssDescriptor.length); |
| allocLen = sizeof( tCsrScanResult ) + bssLen; |
| pResult = vos_mem_malloc(allocLen); |
| if ( NULL == pResult ) |
| status = eHAL_STATUS_FAILURE; |
| else |
| status = eHAL_STATUS_SUCCESS; |
| if (!HAL_STATUS_SUCCESS(status)) |
| { |
| csrScanResultPurge(pMac, (tScanResultHandle *)pRetList); |
| count = 0; |
| break; |
| } |
| vos_mem_set(pResult, allocLen , 0); |
| vos_mem_copy(&pResult->Result.BssDescriptor, &pScanResult->Result.BssDescriptor, bssLen); |
| if( pScanResult->Result.pvIes ) |
| { |
| pResult->Result.pvIes = vos_mem_malloc(sizeof( tDot11fBeaconIEs )); |
| if ( NULL == pResult->Result.pvIes ) |
| status = eHAL_STATUS_FAILURE; |
| else |
| status = eHAL_STATUS_SUCCESS; |
| if (!HAL_STATUS_SUCCESS(status)) |
| { |
| //Free the memory we allocate above first |
| vos_mem_free(pResult); |
| csrScanResultPurge(pMac, (tScanResultHandle *)pRetList); |
| count = 0; |
| break; |
| } |
| vos_mem_copy(pResult->Result.pvIes, pScanResult->Result.pvIes, |
| sizeof( tDot11fBeaconIEs )); |
| } |
| csrLLInsertTail(&pRetList->List, &pResult->Link, LL_ACCESS_LOCK); |
| count++; |
| pEntry = csrLLNext( &pInList->List, pEntry, LL_ACCESS_NOLOCK ); |
| }//while |
| csrLLUnlock(&pInList->List); |
| csrLLUnlock(&pMac->scan.scanResultList); |
| |
| if(HAL_STATUS_SUCCESS(status)) |
| { |
| if(0 == count) |
| { |
| csrLLClose(&pRetList->List); |
| vos_mem_free(pRetList); |
| status = eHAL_STATUS_E_NULL_VALUE; |
| } |
| else if(phResult) |
| { |
| *phResult = pRetList; |
| } |
| } |
| }//Allocated pRetList |
| |
| return (status); |
| } |
| |
| |
| |
| eHalStatus csrScanningStateMsgProcessor( tpAniSirGlobal pMac, void *pMsgBuf ) |
| { |
| eHalStatus status = eHAL_STATUS_SUCCESS; |
| tSirMbMsg *pMsg = (tSirMbMsg *)pMsgBuf; |
| tSirSmeDisConDoneInd *pDisConDoneInd; |
| tCsrRoamInfo roamInfo = {0}; |
| tCsrRoamSession *pSession; |
| |
| if ((eWNI_SME_SCAN_RSP == pMsg->type) || |
| (eWNI_SME_GET_SCANNED_CHANNEL_RSP == pMsg->type)) { |
| status = csrScanSmeScanResponse( pMac, pMsgBuf ); |
| } else { |
| switch (pMsg->type) { |
| case eWNI_SME_UPPER_LAYER_ASSOC_CNF: |
| { |
| tSirSmeAssocIndToUpperLayerCnf *pUpperLayerAssocCnf; |
| tCsrRoamInfo *pRoamInfo = NULL; |
| tANI_U32 sessionId; |
| eHalStatus status; |
| |
| smsLog(pMac, LOG1, |
| FL("Scanning : ASSOCIATION confirmation can be given to upper layer ")); |
| |
| pRoamInfo = &roamInfo; |
| pUpperLayerAssocCnf = |
| (tSirSmeAssocIndToUpperLayerCnf *)pMsgBuf; |
| status = csrRoamGetSessionIdFromBSSID( pMac, |
| (tCsrBssid *)pUpperLayerAssocCnf->bssId, |
| &sessionId ); |
| pSession = CSR_GET_SESSION(pMac, sessionId); |
| if(!pSession) { |
| smsLog(pMac, LOGE, |
| FL(" session %d not found "), |
| sessionId); |
| return eHAL_STATUS_FAILURE; |
| } |
| //send the status code as Success |
| pRoamInfo->statusCode = eSIR_SME_SUCCESS; |
| pRoamInfo->u.pConnectedProfile = |
| &pSession->connectedProfile; |
| pRoamInfo->staId = (tANI_U8)pUpperLayerAssocCnf->aid; |
| pRoamInfo->rsnIELen = |
| (tANI_U8)pUpperLayerAssocCnf->rsnIE.length; |
| pRoamInfo->prsnIE = |
| pUpperLayerAssocCnf->rsnIE.rsnIEdata; |
| pRoamInfo->addIELen = |
| (tANI_U8)pUpperLayerAssocCnf->addIE.length; |
| pRoamInfo->paddIE = |
| pUpperLayerAssocCnf->addIE.addIEdata; |
| vos_mem_copy(pRoamInfo->peerMac, |
| pUpperLayerAssocCnf->peerMacAddr, |
| sizeof(tSirMacAddr)); |
| vos_mem_copy(&pRoamInfo->bssid, |
| pUpperLayerAssocCnf->bssId, |
| sizeof(tCsrBssid)); |
| pRoamInfo->wmmEnabledSta = |
| pUpperLayerAssocCnf->wmmEnabledSta; |
| if (CSR_IS_INFRA_AP(pRoamInfo->u.pConnectedProfile)) { |
| pMac->roam.roamSession[sessionId].connectState = |
| eCSR_ASSOC_STATE_TYPE_INFRA_CONNECTED; |
| pRoamInfo->fReassocReq = |
| pUpperLayerAssocCnf->reassocReq; |
| status = csrRoamCallCallback(pMac, sessionId, |
| pRoamInfo, 0, |
| eCSR_ROAM_INFRA_IND, |
| eCSR_ROAM_RESULT_INFRA_ASSOCIATION_CNF); |
| } |
| if(CSR_IS_WDS_AP( pRoamInfo->u.pConnectedProfile)) { |
| vos_sleep( 100 ); |
| pMac->roam.roamSession[sessionId].connectState = |
| //Sta |
| eCSR_ASSOC_STATE_TYPE_WDS_CONNECTED; |
| status = csrRoamCallCallback(pMac, |
| sessionId, pRoamInfo, 0, |
| eCSR_ROAM_WDS_IND, |
| //Sta |
| eCSR_ROAM_RESULT_WDS_ASSOCIATION_IND); |
| } |
| break; |
| } |
| case eWNI_SME_DISCONNECT_DONE_IND: |
| pDisConDoneInd = (tSirSmeDisConDoneInd *)(pMsg); |
| |
| smsLog( pMac, LOG1, |
| FL("eWNI_SME_DISCONNECT_DONE_IND RC:%d"), |
| pDisConDoneInd->reasonCode); |
| pSession = CSR_GET_SESSION(pMac, |
| pDisConDoneInd->sessionId); |
| if (!pSession) { |
| smsLog(pMac, LOGE, FL("Invalid session")); |
| return eHAL_STATUS_FAILURE; |
| } |
| if (CSR_IS_SESSION_VALID(pMac, |
| pDisConDoneInd->sessionId)) |
| { |
| roamInfo.reasonCode = |
| pDisConDoneInd->reasonCode; |
| roamInfo.statusCode = |
| eSIR_SME_STA_DISASSOCIATED; |
| vos_mem_copy(roamInfo.peerMac, |
| pDisConDoneInd->peerMacAddr, |
| sizeof(tSirMacAddr)); |
| status = csrRoamCallCallback(pMac, |
| pDisConDoneInd->sessionId, |
| &roamInfo, 0, |
| eCSR_ROAM_LOSTLINK, |
| eCSR_ROAM_RESULT_DISASSOC_IND); |
| |
| /* |
| * Update the previous state if |
| * previous to eCSR_ROAMING_STATE_IDLE |
| * as we are disconnected and |
| * currunt state is scanning |
| */ |
| if (!CSR_IS_INFRA_AP( |
| &pSession->connectedProfile)) |
| pMac->roam.prev_state[ |
| pDisConDoneInd->sessionId] = |
| eCSR_ROAMING_STATE_IDLE; |
| } |
| else |
| { |
| smsLog(pMac, LOGE, FL("Inactive session %d"), |
| pDisConDoneInd->sessionId); |
| status = eHAL_STATUS_FAILURE; |
| } |
| break; |
| |
| default : |
| if (csrIsAnySessionInConnectState(pMac)) { |
| /* In case of we are connected, we need to check |
| * whether connect status changes because scan |
| * may also run while connected. |
| */ |
| csrRoamCheckForLinkStatusChange( pMac, |
| (tSirSmeRsp *)pMsgBuf ); |
| } else { |
| smsLog( pMac, LOGW, |
| "Message [0x%04x] received in state, when expecting Scan Response", |
| pMsg->type ); |
| } |
| } |
| } |
| return (status); |
| } |
| |
| void csrCheckNSaveWscIe(tpAniSirGlobal pMac, tSirBssDescription *pNewBssDescr, tSirBssDescription *pOldBssDescr) |
| { |
| int idx, len; |
| tANI_U8 *pbIe; |
| |
| //If failed to remove, assuming someone else got it. |
| if((pNewBssDescr->fProbeRsp != pOldBssDescr->fProbeRsp) && |
| (0 == pNewBssDescr->WscIeLen)) |
| { |
| idx = 0; |
| len = GET_IE_LEN_IN_BSS(pOldBssDescr->length) - DOT11F_IE_WSCPROBERES_MIN_LEN - 2; |
| pbIe = (tANI_U8 *)pOldBssDescr->ieFields; |
| //Save WPS IE if it exists |
| pNewBssDescr->WscIeLen = 0; |
| while(idx < len) |
| { |
| if((DOT11F_EID_WSCPROBERES == pbIe[0]) && |
| (0x00 == pbIe[2]) && (0x50 == pbIe[3]) && (0xf2 == pbIe[4]) && (0x04 == pbIe[5])) |
| { |
| /* Found it */ |
| if((DOT11F_IE_WSCPROBERES_MAX_LEN - 2) >= pbIe[1]) |
| { |
| vos_mem_copy(pNewBssDescr->WscIeProbeRsp, pbIe, pbIe[1] + 2); |
| pNewBssDescr->WscIeLen = pbIe[1] + 2; |
| } |
| break; |
| } |
| idx += pbIe[1] + 2; |
| pbIe += pbIe[1] + 2; |
| } |
| } |
| } |
| |
| |
| |
| //pIes may be NULL |
| tANI_BOOLEAN csrRemoveDupBssDescription( tpAniSirGlobal pMac, tSirBssDescription *pSirBssDescr, |
| tDot11fBeaconIEs *pIes, tAniSSID *pSsid, v_TIME_t *timer, tANI_BOOLEAN fForced ) |
| { |
| tListElem *pEntry; |
| |
| tCsrScanResult *pBssDesc; |
| tANI_BOOLEAN fRC = FALSE; |
| |
| // Walk through all the chained BssDescriptions. If we find a chained BssDescription that |
| // matches the BssID of the BssDescription passed in, then these must be duplicate scan |
| // results for this Bss. In that case, remove the 'old' Bss description from the linked list. |
| csrLLLock(&pMac->scan.scanResultList); |
| pEntry = csrLLPeekHead(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK); |
| |
| while( pEntry ) |
| { |
| pBssDesc = GET_BASE_ADDR( pEntry, tCsrScanResult, Link ); |
| |
| // we have a duplicate scan results only when BSSID, SSID, Channel and NetworkType |
| // matches |
| if ( csrIsDuplicateBssDescription( pMac, &pBssDesc->Result.BssDescriptor, |
| pSirBssDescr, pIes, fForced ) ) |
| { |
| int32_t rssi_new, rssi_old; |
| |
| rssi_new = (int32_t) pSirBssDescr->rssi; |
| rssi_old = (int32_t) pBssDesc->Result.BssDescriptor.rssi; |
| rssi_new = ((rssi_new * CSR_SCAN_RESULT_RSSI_WEIGHT) + |
| rssi_old * (100 - CSR_SCAN_RESULT_RSSI_WEIGHT)) / 100; |
| pSirBssDescr->rssi = (tANI_S8) rssi_new; |
| |
| rssi_new = (int32_t) pSirBssDescr->rssi_raw; |
| rssi_old = (int32_t) pBssDesc->Result.BssDescriptor.rssi_raw; |
| rssi_new = ((rssi_new * CSR_SCAN_RESULT_RSSI_WEIGHT) + |
| rssi_old * (100 - CSR_SCAN_RESULT_RSSI_WEIGHT)) / 100; |
| pSirBssDescr->rssi_raw = (tANI_S8) rssi_new; |
| |
| // Remove the 'old' entry from the list.... |
| if(csrLLRemoveEntry(&pMac->scan.scanResultList, pEntry, |
| LL_ACCESS_NOLOCK)) |
| { |
| // !we need to free the memory associated with this node |
| //If failed to remove, assuming someone else got it. |
| *pSsid = pBssDesc->Result.ssId; |
| *timer = pBssDesc->Result.timer; |
| csrCheckNSaveWscIe(pMac, pSirBssDescr, &pBssDesc->Result.BssDescriptor); |
| |
| csrFreeScanResultEntry( pMac, pBssDesc ); |
| } |
| else |
| { |
| smsLog( pMac, LOGW, FL( " fail to remove entry" ) ); |
| } |
| fRC = TRUE; |
| |
| // If we found a match, we can stop looking through the list. |
| break; |
| } |
| |
| pEntry = csrLLNext(&pMac->scan.scanResultList, pEntry, |
| LL_ACCESS_NOLOCK); |
| } |
| csrLLUnlock(&pMac->scan.scanResultList); |
| |
| return fRC; |
| } |
| |
| |
| eHalStatus csrAddPMKIDCandidateList( tpAniSirGlobal pMac, tANI_U32 sessionId, |
| tSirBssDescription *pBssDesc, tDot11fBeaconIEs *pIes ) |
| { |
| |