| /* |
| * roamingMngr_autoSM.c |
| * |
| * Copyright(c) 1998 - 2010 Texas Instruments. All rights reserved. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name Texas Instruments nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| /** \file roamingMngr_autoSM.c |
| * \brief Roaming Manager |
| * |
| * \see roamingMngr_autoSM.h |
| */ |
| |
| /**************************************************************************** |
| * * |
| * MODULE: Roaming Manager * |
| * PURPOSE: * |
| * Roaming manager is responsible to receive Roaming triggers and try |
| * to select a better AP. |
| * The Roaming triggers are: Low RSSI, PER, consecutive No ACK on TX, |
| * beacon Missed or External request. |
| * In each Internal Roaming request, scan is performed and selection for |
| * better AP. Better AP is defined as a different AP with better RSSI, |
| * and similar SSID and security settings. |
| * If better AP is found, there is a check for fast-roaming via the |
| * Supplicant. Then connection to the new AP is invoked. |
| * * |
| ****************************************************************************/ |
| |
| #define __FILE_ID__ FILE_ID_135 |
| #include "osApi.h" |
| |
| #include "paramOut.h" |
| #include "report.h" |
| #include "scanMngrApi.h" |
| #include "roamingMngrApi.h" |
| #include "apConnApi.h" |
| #include "roamingMngrTypes.h" |
| #include "bssTypes.h" |
| #include "DrvMainModules.h" |
| #include "TWDriver.h" |
| #include "siteMgrApi.h" |
| #include "GenSM.h" |
| #include "roamingMngr_autoSM.h" |
| |
| |
| /***************************************************************************** |
| ** Private Function section ** |
| *****************************************************************************/ |
| /* SM functions */ |
| |
| static void roamingMngr_smStartIdle(TI_HANDLE hRoamingMngr); |
| static void roamingMngr_smRoamTrigger(TI_HANDLE hRoamingMngr); |
| static void roamingMngr_smInvokeScan(TI_HANDLE hRoamingMngr); |
| static void roamingMngr_smSelection(TI_HANDLE hRoamingMngr); |
| static void roamingMngr_smHandover(TI_HANDLE hRoamingMngr); |
| static void roamingMngr_smSuccHandover(TI_HANDLE hRoamingMngr); |
| static void roamingMngr_smFailHandover(TI_HANDLE hRoamingMngr); |
| static void roamingMngr_smScanFailure(TI_HANDLE hRoamingMngr); |
| static void roamingMngr_smDisconnectWhileConnecting(TI_HANDLE hRoamingMngr); |
| |
| /*static TI_STATUS roamingMngr_smUnexpected(TI_HANDLE hRoamingMngr); |
| static TI_STATUS roamingMngr_smNop(TI_HANDLE hRoamingMngr); |
| static TI_STATUS roamingMngr_smStopWhileScanning(TI_HANDLE hRoamingMngr); |
| */ |
| |
| typedef enum |
| { |
| REASSOC_RESP_SUCCESS =0, |
| REASSOC_RESP_FAILURE, |
| REASSOC_RESP_REJECT |
| } reassociationResp_e; |
| |
| |
| /*-----------*/ |
| /* Constants */ |
| /*-----------*/ |
| |
| TGenSM_actionCell roamingMngrAuto_matrix[ROAMING_MNGR_NUM_STATES][ROAMING_MNGR_NUM_EVENTS] = |
| { |
| /* next state and actions for IDLE state */ |
| { {ROAMING_STATE_WAIT_4_TRIGGER, roamingMngr_smStartIdle}, /* START */ |
| {ROAMING_STATE_IDLE, roamingMngr_smNop}, /* STOP */ |
| {ROAMING_STATE_IDLE, roamingMngr_smNop}, /* ROAM_TRIGGER */ |
| {ROAMING_STATE_IDLE, roamingMngr_smUnexpected}, /* SCAN */ |
| {ROAMING_STATE_IDLE, roamingMngr_smUnexpected}, /* SELECT */ |
| {ROAMING_STATE_IDLE, roamingMngr_smUnexpected}, /* REQ_HANDOVER */ |
| {ROAMING_STATE_IDLE, roamingMngr_smUnexpected}, /* ROAM_SUCCESS */ |
| {ROAMING_STATE_IDLE, roamingMngr_smUnexpected} /* FAILURE */ |
| }, |
| |
| /* next state and actions for WAIT_4_TRIGGER state */ |
| { {ROAMING_STATE_WAIT_4_TRIGGER, roamingMngr_smUnexpected}, /* START */ |
| {ROAMING_STATE_IDLE, roamingMngr_smStop}, /* STOP */ |
| {ROAMING_STATE_WAIT_4_CMD, roamingMngr_smRoamTrigger}, /* ROAM_TRIGGER */ |
| {ROAMING_STATE_WAIT_4_TRIGGER, roamingMngr_smUnexpected}, /* SCAN */ |
| {ROAMING_STATE_WAIT_4_TRIGGER, roamingMngr_smUnexpected}, /* SELECT */ |
| {ROAMING_STATE_WAIT_4_TRIGGER, roamingMngr_smUnexpected}, /* REQ_HANDOVER */ |
| {ROAMING_STATE_WAIT_4_TRIGGER, roamingMngr_smUnexpected}, /* ROAM_SUCCESS */ |
| {ROAMING_STATE_WAIT_4_TRIGGER, roamingMngr_smUnexpected} /* FAILURE */ |
| }, |
| |
| /* next state and actions for WAIT_4_CMD state */ |
| { {ROAMING_STATE_WAIT_4_CMD, roamingMngr_smUnexpected}, /* START */ |
| {ROAMING_STATE_WAIT_4_CMD, roamingMngr_smUnexpected}, /* STOP */ |
| {ROAMING_STATE_WAIT_4_CMD, roamingMngr_smUnexpected}, /* ROAM_TRIGGER */ |
| {ROAMING_STATE_SCANNING, roamingMngr_smInvokeScan}, /* SCAN */ |
| {ROAMING_STATE_SELECTING, roamingMngr_smSelection}, /* SELECT */ |
| {ROAMING_STATE_WAIT_4_CMD, roamingMngr_smUnexpected}, /* REQ_HANDOVER */ |
| {ROAMING_STATE_WAIT_4_CMD, roamingMngr_smUnexpected}, /* ROAM_SUCCESS */ |
| {ROAMING_STATE_WAIT_4_CMD, roamingMngr_smUnexpected} /* FAILURE */ |
| }, |
| |
| /* next state and actions for SCANNING state */ |
| { {ROAMING_STATE_SCANNING, roamingMngr_smUnexpected}, /* START */ |
| {ROAMING_STATE_IDLE, roamingMngr_smStopWhileScanning}, /* STOP */ |
| {ROAMING_STATE_SCANNING, roamingMngr_smNop}, /* ROAM_TRIGGER */ |
| {ROAMING_STATE_SCANNING, roamingMngr_smInvokeScan}, /* SCAN */ |
| {ROAMING_STATE_SELECTING, roamingMngr_smSelection}, /* SELECT */ |
| {ROAMING_STATE_SCANNING, roamingMngr_smUnexpected}, /* REQ_HANDOVER */ |
| {ROAMING_STATE_SCANNING, roamingMngr_smUnexpected}, /* ROAM_SUCCESS */ |
| {ROAMING_STATE_IDLE, roamingMngr_smScanFailure} /* FAILURE */ |
| |
| }, |
| |
| /* next state and actions for SELECTING state */ |
| { {ROAMING_STATE_SELECTING, roamingMngr_smUnexpected}, /* START */ |
| {ROAMING_STATE_SELECTING, roamingMngr_smUnexpected}, /* STOP */ |
| {ROAMING_STATE_SELECTING, roamingMngr_smUnexpected}, /* ROAM_TRIGGER */ |
| {ROAMING_STATE_SELECTING, roamingMngr_smUnexpected}, /* SCAN */ |
| {ROAMING_STATE_SELECTING, roamingMngr_smUnexpected}, /* SELECT */ |
| {ROAMING_STATE_CONNECTING, roamingMngr_smHandover}, /* REQ_HANDOVER */ |
| {ROAMING_STATE_SELECTING, roamingMngr_smUnexpected}, /* ROAM_SUCCESS */ |
| {ROAMING_STATE_SELECTING, roamingMngr_smUnexpected} /* FAILURE */ |
| |
| }, |
| |
| /* next state and actions for CONNECTING state */ |
| { {ROAMING_STATE_CONNECTING, roamingMngr_smUnexpected}, /* START */ |
| {ROAMING_STATE_IDLE, roamingMngr_smStop}, /* STOP */ |
| {ROAMING_STATE_IDLE, roamingMngr_smDisconnectWhileConnecting}, /* ROAM_TRIGGER */ |
| {ROAMING_STATE_CONNECTING, roamingMngr_smUnexpected}, /* SCAN, */ |
| {ROAMING_STATE_CONNECTING, roamingMngr_smUnexpected}, /* SELECT */ |
| {ROAMING_STATE_CONNECTING, roamingMngr_smHandover}, /* REQ_HANDOVER */ |
| {ROAMING_STATE_WAIT_4_TRIGGER, roamingMngr_smSuccHandover} , /* ROAM_SUCCESS */ |
| {ROAMING_STATE_IDLE, roamingMngr_smFailHandover} /* FAILURE */ |
| |
| } |
| }; |
| |
| |
| TI_INT8* AutoRoamStateDescription[] = |
| { |
| "IDLE", |
| "WAIT_4_TRIGGER", |
| "WAIT_4_CMD", |
| "SCANNING", |
| "SELECTING", |
| "CONNECTING" |
| }; |
| |
| TI_INT8* AutoRoamEventDescription[] = |
| { |
| "START", |
| "STOP", |
| "ROAM_TRIGGER", |
| "SCAN", |
| "SELECT", |
| "REQ_HANDOVER", |
| "ROAM_SUCCESS", |
| "FAILURE" |
| }; |
| |
| /** |
| * |
| * roamingMngr_smRoamTrigger |
| * |
| * \b Description: |
| * |
| * This procedure is called when an Roaming event occurs: BSS LOSS, LOW Quality etc. |
| * Performs the following: |
| * - If Roaming is disabled, ignore. |
| * - Indicate Driver that Roaming process is starting |
| * - Get the BSS list from the Scan Manager. |
| * - If the list is not empty, start SELECTION |
| * - If the list is empty, start SCANNING. The type of scan is decided |
| * according to the Neigbor APs existence. |
| * |
| * \b ARGS: |
| * |
| * I - hRoamingMngr - roamingMngr SM context \n |
| * |
| * \b RETURNS: |
| * |
| * TI_OK if successful, TI_NOK otherwise. |
| * |
| * |
| */ |
| static void roamingMngr_smRoamTrigger(TI_HANDLE hRoamingMngr) |
| { |
| roamingMngr_t *pRoamingMngr; |
| roamingMngr_smEvents roamingEvent; |
| |
| pRoamingMngr = (roamingMngr_t*)hRoamingMngr; |
| TRACE1(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smRoamTrigger, enableDisable = %d\n",pRoamingMngr->roamingMngrConfig.enableDisable); |
| |
| if (!pRoamingMngr->roamingMngrConfig.enableDisable) |
| { |
| /* Ignore any other Roaming event when Roaming is disabled */ |
| TRACE0(pRoamingMngr->hReport, REPORT_SEVERITY_ERROR, "roamingMngr_smRoamTrigger, when Roaming is disabled\n"); |
| return; |
| } |
| /* Indicate the driver that Roaming process is starting */ |
| apConn_prepareToRoaming(pRoamingMngr->hAPConnection, pRoamingMngr->roamingTrigger); |
| |
| /* Get the current BSSIDs from ScanMngr */ |
| pRoamingMngr->pListOfAPs = scanMngr_getBSSList(pRoamingMngr->hScanMngr); |
| if ((pRoamingMngr->pListOfAPs != NULL) && (pRoamingMngr->pListOfAPs->numOfEntries > 0)) |
| { /* No need to SCAN, start SELECTING */ |
| roamingEvent = ROAMING_EVENT_SELECT; |
| } |
| else |
| { /* check if list of APs exists in order to verify which scan to start */ |
| roamingEvent = ROAMING_EVENT_SCAN; |
| if (pRoamingMngr->neighborApsExist) |
| { /* Scan only Neighbor APs */ |
| pRoamingMngr->scanType = ROAMING_PARTIAL_SCAN; |
| } |
| else |
| { /* Scan all channels */ |
| pRoamingMngr->scanType = ROAMING_FULL_SCAN; |
| } |
| } |
| TRACE1(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smRoamTrigger, scanType = %d\n", pRoamingMngr->scanType); |
| |
| roamingMngr_smEvent(roamingEvent, pRoamingMngr); |
| } |
| |
| /** |
| * |
| * roamingMngr_smInvokeScan |
| * |
| * \b Description: |
| * |
| * This procedure is called when scan should be performed in order |
| * to select an AP to roam to. |
| * This can be the first scan, a second scan after partail scan, |
| * or scan after previous scan was failed. |
| * In any case, the scan can either be: |
| * partail, on list of channles or |
| * full on all channels. |
| * |
| * \b ARGS: |
| * |
| * I - hRoamingMngr - roamingMngr SM context \n |
| * |
| * \b RETURNS: |
| * |
| * TI_OK if successful, TI_NOK otherwise. |
| * |
| * |
| */ |
| static void roamingMngr_smInvokeScan(TI_HANDLE hRoamingMngr) |
| { |
| roamingMngr_t *pRoamingMngr; |
| scan_mngrResultStatus_e scanResult; |
| |
| pRoamingMngr = (roamingMngr_t*)hRoamingMngr; |
| |
| /* check which scan should be performed: Partial on list of channels, or full scan */ |
| if ((pRoamingMngr->scanType == ROAMING_PARTIAL_SCAN) || |
| (pRoamingMngr->scanType == ROAMING_PARTIAL_SCAN_RETRY)) |
| { |
| scanResult = scanMngr_startImmediateScan (pRoamingMngr->hScanMngr, TI_TRUE); |
| } |
| else |
| { /* Scan all channels */ |
| scanResult = scanMngr_startImmediateScan (pRoamingMngr->hScanMngr, TI_FALSE); |
| } |
| |
| if (scanResult != SCAN_MRS_SCAN_RUNNING) |
| { /* the scan failed, immitate scan complete event */ |
| TRACE1(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smInvokeScan, scanResult = %d\n", scanResult); |
| roamingMngr_immediateScanComplete(pRoamingMngr, scanResult); |
| } |
| } |
| |
| /** |
| * |
| * roamingMngr_smSelection |
| * |
| * \b Description: |
| * |
| * This procedure is called when selection should be performed. |
| * It perform the following: |
| * Prepare the candidate APs to roam according to: |
| * - Priority APs |
| * - Pre-Authenticated APs |
| * If the candidate AP list is empty, only the current AP can be re-selected |
| * Select one AP and trigger REQ_HANDOVER event. |
| * |
| * \b ARGS: |
| * |
| * I - hRoamingMngr - roamingMngr SM context \n |
| * |
| * \b RETURNS: |
| * |
| * TI_OK if successful, TI_NOK otherwise. |
| * |
| * |
| */ |
| static void roamingMngr_smSelection(TI_HANDLE hRoamingMngr) |
| { |
| roamingMngr_t *pRoamingMngr; |
| TI_UINT32 index; |
| |
| |
| pRoamingMngr = (roamingMngr_t*)hRoamingMngr; |
| pRoamingMngr->listOfCandidateAps.numOfNeighborBSS = 0; |
| pRoamingMngr->listOfCandidateAps.numOfPreAuthBSS = 0; |
| pRoamingMngr->listOfCandidateAps.numOfRegularBSS = 0; |
| |
| pRoamingMngr->candidateApIndex = INVALID_CANDIDATE_INDEX; |
| |
| if ((pRoamingMngr->pListOfAPs == NULL) || |
| (pRoamingMngr->pListOfAPs->numOfEntries == 0)) |
| { /* Error, there cannot be selection */ |
| TRACE0(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smSelection pListOfAPs is empty \n"); |
| roamingMngr_smEvent(ROAMING_EVENT_REQ_HANDOVER, pRoamingMngr); |
| return; |
| } |
| |
| /* Build the candidate AP list */ |
| for (index=0; index<pRoamingMngr->pListOfAPs->numOfEntries; index++ ) |
| { |
| if ( (pRoamingMngr->roamingTrigger <= ROAMING_TRIGGER_LOW_QUALITY_GROUP) && |
| (pRoamingMngr->pListOfAPs->BSSList[index].RSSI < pRoamingMngr->roamingMngrConfig.apQualityThreshold)) |
| { /* Do not insert APs with low quality to the selection table, |
| if the Roaming Trigger was low Quality */ |
| TRACE8(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "candidate AP %x-%x-%x-%x-%x-%x with RSSI too low =%d, Quality=%d \n", pRoamingMngr->pListOfAPs->BSSList[index].BSSID[0], pRoamingMngr->pListOfAPs->BSSList[index].BSSID[1], pRoamingMngr->pListOfAPs->BSSList[index].BSSID[2], pRoamingMngr->pListOfAPs->BSSList[index].BSSID[3], pRoamingMngr->pListOfAPs->BSSList[index].BSSID[4], pRoamingMngr->pListOfAPs->BSSList[index].BSSID[5], pRoamingMngr->pListOfAPs->BSSList[index].RSSI, pRoamingMngr->roamingMngrConfig.apQualityThreshold); |
| |
| continue; |
| } |
| |
| if (apConn_isSiteBanned(pRoamingMngr->hAPConnection, &pRoamingMngr->pListOfAPs->BSSList[index].BSSID) == TI_TRUE) |
| { |
| TRACE6(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, ": Candidate AP %02X-%02X-%02X-%02X-%02X-%02X is banned!\n", pRoamingMngr->pListOfAPs->BSSList[index].BSSID[0], pRoamingMngr->pListOfAPs->BSSList[index].BSSID[1], pRoamingMngr->pListOfAPs->BSSList[index].BSSID[2], pRoamingMngr->pListOfAPs->BSSList[index].BSSID[3], pRoamingMngr->pListOfAPs->BSSList[index].BSSID[4], pRoamingMngr->pListOfAPs->BSSList[index].BSSID[5]); |
| continue; |
| } |
| |
| if (pRoamingMngr->pListOfAPs->BSSList[index].bNeighborAP) |
| { /* The AP is a neighbor AP, insert its index to the neighbor APs list */ |
| pRoamingMngr->listOfCandidateAps.neighborBSSList[pRoamingMngr->listOfCandidateAps.numOfNeighborBSS] = index; |
| pRoamingMngr->listOfCandidateAps.numOfNeighborBSS++; |
| } |
| else if (apConn_getPreAuthAPStatus(pRoamingMngr->hAPConnection, |
| &pRoamingMngr->pListOfAPs->BSSList[index].BSSID)) |
| { /* This AP is a pre-auth AP */ |
| pRoamingMngr->listOfCandidateAps.preAuthBSSList[pRoamingMngr->listOfCandidateAps.numOfPreAuthBSS] = index; |
| pRoamingMngr->listOfCandidateAps.numOfPreAuthBSS++; |
| } |
| else |
| { /* This AP is not Neighbor nor Pre-Auth */ |
| pRoamingMngr->listOfCandidateAps.regularBSSList[pRoamingMngr->listOfCandidateAps.numOfRegularBSS] = index; |
| pRoamingMngr->listOfCandidateAps.numOfRegularBSS++; |
| } |
| } |
| |
| #ifdef TI_DBG |
| { /* for debug */ |
| paramInfo_t param; |
| |
| param.paramType = ROAMING_MNGR_PRINT_CANDIDATE_TABLE; |
| roamingMngr_getParam(pRoamingMngr, ¶m); |
| |
| } |
| #endif |
| roamingMngr_smEvent(ROAMING_EVENT_REQ_HANDOVER, pRoamingMngr); |
| |
| } |
| |
| /** |
| * |
| * roamingMngr_smHandover |
| * |
| * \b Description: |
| * |
| * This procedure is called when handover should be invoked. |
| * Go over the candidate APs and start handover to each of them. |
| * If there's no candidate APs, disconnect. |
| * Handover to the current AP is allowed only if the trigger is |
| * low quality. |
| * |
| * \b ARGS: |
| * |
| * I - hRoamingMngr - roamingMngr SM context \n |
| * |
| * \b RETURNS: |
| * |
| * TI_OK if successful, TI_NOK otherwise. |
| * |
| * |
| */ |
| static void roamingMngr_smHandover(TI_HANDLE hRoamingMngr) |
| { |
| roamingMngr_t *pRoamingMngr; |
| bssEntry_t *pApToConnect; |
| apConn_connRequest_t requestToApConn; |
| |
| pRoamingMngr = (roamingMngr_t*)hRoamingMngr; |
| |
| if ((pRoamingMngr->handoverWasPerformed) && (pRoamingMngr->candidateApIndex == CURRENT_AP_INDEX)) |
| { /* Handover with the current AP already failed, Disconnect */ |
| roamingMngr_smEvent(ROAMING_EVENT_FAILURE, pRoamingMngr); |
| return; |
| } |
| if (pRoamingMngr->listOfCandidateAps.numOfNeighborBSS > 0) |
| { /* Neighbor APs are the highest priority to Roam */ |
| pRoamingMngr->candidateApIndex = |
| pRoamingMngr->listOfCandidateAps.neighborBSSList[pRoamingMngr->listOfCandidateAps.numOfNeighborBSS-1]; |
| pRoamingMngr->listOfCandidateAps.numOfNeighborBSS--; |
| } |
| else if (pRoamingMngr->listOfCandidateAps.numOfPreAuthBSS > 0) |
| { /* Pre-Auth APs are the second priority to Roam */ |
| pRoamingMngr->candidateApIndex = |
| pRoamingMngr->listOfCandidateAps.preAuthBSSList[pRoamingMngr->listOfCandidateAps.numOfPreAuthBSS-1]; |
| pRoamingMngr->listOfCandidateAps.numOfPreAuthBSS--; |
| } |
| else if (pRoamingMngr->listOfCandidateAps.numOfRegularBSS > 0) |
| { /* Regular APs are APs that are not pre-authenticated and not Neighbor */ |
| pRoamingMngr->candidateApIndex = |
| pRoamingMngr->listOfCandidateAps.regularBSSList[pRoamingMngr->listOfCandidateAps.numOfRegularBSS-1]; |
| pRoamingMngr->listOfCandidateAps.numOfRegularBSS--; |
| } |
| else |
| { /* No Candidate APs */ |
| pRoamingMngr->candidateApIndex = INVALID_CANDIDATE_INDEX; |
| } |
| |
| TRACE1(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smHandover, candidateApIndex=%d \n", pRoamingMngr->candidateApIndex); |
| |
| |
| if (pRoamingMngr->candidateApIndex == INVALID_CANDIDATE_INDEX) |
| { /* No cnadidate to Roam to, only the current AP is candidate */ |
| if (pRoamingMngr->roamingTrigger <= ROAMING_TRIGGER_LOW_QUALITY_GROUP) |
| { /* If the trigger to Roam is low quality, and there are no candidate APs |
| to roam to, retain connected to the current AP */ |
| requestToApConn.requestType = (pRoamingMngr->handoverWasPerformed) ? AP_CONNECT_RECONNECT_CURR_AP : AP_CONNECT_RETAIN_CURR_AP; |
| pRoamingMngr->candidateApIndex = CURRENT_AP_INDEX; |
| } |
| else |
| { /* Disconnect the BSS, there are no more APs to roam to */ |
| roamingMngr_smEvent(ROAMING_EVENT_FAILURE, pRoamingMngr); |
| return; |
| } |
| } |
| else |
| { /* There is a valid candidate AP */ |
| if (pRoamingMngr->roamingTrigger > ROAMING_TRIGGER_FAST_CONNECT_GROUP) |
| { /* Full re-connection should be perfromed */ |
| requestToApConn.requestType = AP_CONNECT_FULL_TO_AP; |
| } |
| else |
| { /* Fast re-connection should be perfromed */ |
| requestToApConn.requestType = AP_CONNECT_FAST_TO_AP; |
| } |
| } |
| #ifdef TI_DBG |
| /* For debug */ |
| if (!pRoamingMngr->handoverWasPerformed) |
| { /* Take the time before the first handover started */ |
| pRoamingMngr->roamingHandoverStartedTimestamp = os_timeStampMs(pRoamingMngr->hOs); |
| } |
| #endif |
| |
| if (pRoamingMngr->candidateApIndex == CURRENT_AP_INDEX) |
| { /* get the current AP */ |
| pApToConnect = apConn_getBSSParams(pRoamingMngr->hAPConnection); |
| } |
| else |
| { /* get the candidate AP */ |
| pRoamingMngr->handoverWasPerformed = TI_TRUE; |
| pApToConnect = &pRoamingMngr->pListOfAPs->BSSList[pRoamingMngr->candidateApIndex]; |
| } |
| TRACE3(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smHandover, candidateApIndex=%d, requestType = %d, channel=%d \n", pRoamingMngr->candidateApIndex, requestToApConn.requestType, pApToConnect->channel); |
| |
| requestToApConn.dataBufLength = 0; |
| |
| #ifdef XCC_MODULE_INCLUDED |
| apConn_connectToAP(pRoamingMngr->hAPConnection, pApToConnect, &requestToApConn, pRoamingMngr->bSendTspecInReassPkt); |
| #else |
| apConn_connectToAP(pRoamingMngr->hAPConnection, pApToConnect, &requestToApConn, TI_TRUE); |
| #endif |
| } |
| |
| /** |
| * |
| * roamingMngr_smDisconnectWhileConnecting |
| * |
| * \b Description: |
| * |
| * This procedure is called when the Station is in the process of connection, |
| * and the AP disconnects the station. |
| * |
| * \b ARGS: |
| * |
| * I - hRoamingMngr - roamingMngr SM context \n |
| * |
| * \b RETURNS: |
| * |
| * TI_OK if successful, TI_NOK otherwise. |
| * |
| * |
| */ |
| static void roamingMngr_smDisconnectWhileConnecting(TI_HANDLE hRoamingMngr) |
| { |
| roamingMngr_t *pRoamingMngr; |
| |
| pRoamingMngr = (roamingMngr_t*)hRoamingMngr; |
| |
| TRACE1(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smDisconnectWhileConnecting, candidateApIndex=%d \n", pRoamingMngr->candidateApIndex); |
| |
| if (pRoamingMngr->roamingTrigger > ROAMING_TRIGGER_FAST_CONNECT_GROUP) |
| { /* If the trigger is from the Full Connect group, then stop the connection. */ |
| /* clean intenal variables */ |
| pRoamingMngr->maskRoamingEvents = TI_TRUE; |
| pRoamingMngr->roamingTrigger = ROAMING_TRIGGER_NONE; |
| |
| scanMngr_stopContScan(pRoamingMngr->hScanMngr); |
| #ifdef TI_DBG |
| pRoamingMngr->roamingFailedHandoverNum++; |
| #endif |
| apConn_disconnect(pRoamingMngr->hAPConnection); |
| |
| } |
| } |
| |
| /** |
| * |
| * roamingMngr_smSuccHandover |
| * |
| * \b Description: |
| * |
| * This procedure is called when handover succeeded. |
| * Inform Scan Manager about the new AP. |
| * UnMask Roaming Triggers. |
| * |
| * \b ARGS: |
| * |
| * I - hRoamingMngr - roamingMngr SM context \n |
| * |
| * \b RETURNS: |
| * |
| * TI_OK if successful, TI_NOK otherwise. |
| * |
| * |
| */ |
| static void roamingMngr_smSuccHandover(TI_HANDLE hRoamingMngr) |
| { |
| roamingMngr_t *pRoamingMngr; |
| bssEntry_t *pNewConnectedAp; |
| |
| pRoamingMngr = (roamingMngr_t*)hRoamingMngr; |
| |
| TRACE1(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smSuccHandover, candidateApIndex=%d \n", pRoamingMngr->candidateApIndex); |
| |
| if (pRoamingMngr->handoverWasPerformed && |
| (pRoamingMngr->pListOfAPs != NULL) && |
| (pRoamingMngr->pListOfAPs->numOfEntries>0)) |
| { |
| if (pRoamingMngr->candidateApIndex == CURRENT_AP_INDEX) |
| { |
| /* get the current AP */ |
| pNewConnectedAp = apConn_getBSSParams(pRoamingMngr->hAPConnection); |
| } |
| else |
| { |
| /* get the candidate AP */ |
| pNewConnectedAp = &pRoamingMngr->pListOfAPs->BSSList[pRoamingMngr->candidateApIndex]; |
| } |
| |
| scanMngr_handoverDone(pRoamingMngr->hScanMngr, |
| &pNewConnectedAp->BSSID, |
| pNewConnectedAp->band); |
| } |
| pRoamingMngr->maskRoamingEvents = TI_FALSE; |
| pRoamingMngr->candidateApIndex = INVALID_CANDIDATE_INDEX; |
| pRoamingMngr->handoverWasPerformed = TI_FALSE; |
| pRoamingMngr->roamingTrigger = ROAMING_TRIGGER_NONE; |
| |
| /* Start pre-authentication in order to set PMKID |
| for the current AP */ |
| if (pRoamingMngr->staCapabilities.authMode==os802_11AuthModeWPA2) |
| { |
| /* No Pre-Auth is required */ |
| bssList_t *pBssList; |
| |
| pBssList = os_memoryAlloc(pRoamingMngr->hOs, sizeof(bssList_t)); |
| if (!pBssList) |
| { |
| return; |
| } |
| pBssList->numOfEntries = 0; |
| apConn_preAuthenticate(pRoamingMngr->hAPConnection, pBssList); |
| os_memoryFree(pRoamingMngr->hOs, pBssList, sizeof(bssList_t)); |
| } |
| } |
| |
| /** |
| * |
| * roamingMngr_smFailHandover |
| * |
| * \b Description: |
| * |
| * This procedure is called when handover failed and there are no more |
| * APs to roam to. Disconnect the BSS and retrun to IDLE state. |
| * |
| * \b ARGS: |
| * |
| * I - hRoamingMngr - roamingMngr SM context \n |
| * |
| * \b RETURNS: |
| * |
| * TI_OK if successful, TI_NOK otherwise. |
| * |
| * |
| */ |
| static void roamingMngr_smFailHandover(TI_HANDLE hRoamingMngr) |
| { |
| roamingMngr_t *pRoamingMngr; |
| |
| pRoamingMngr = (roamingMngr_t*)hRoamingMngr; |
| TRACE0(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smFailHandover \n"); |
| |
| /* clean intenal variables */ |
| pRoamingMngr->maskRoamingEvents = TI_TRUE; |
| pRoamingMngr->roamingTrigger = ROAMING_TRIGGER_NONE; |
| |
| scanMngr_stopContScan(pRoamingMngr->hScanMngr); |
| #ifdef TI_DBG |
| pRoamingMngr->roamingFailedHandoverNum++; |
| #endif |
| apConn_disconnect(pRoamingMngr->hAPConnection); |
| } |
| |
| /** |
| * |
| * roamingMngr_smScanFailure |
| * |
| * \b Description: |
| * |
| * This procedure is called when all scan attempts failed. |
| * Send Disconnect event and return to IDLE state. |
| * |
| * |
| * \b ARGS: |
| * |
| * I - hRoamingMngr - roamingMngr SM context \n |
| * |
| * \b RETURNS: |
| * |
| * TI_OK if successful, TI_NOK otherwise. |
| * |
| * |
| */ |
| static void roamingMngr_smScanFailure(TI_HANDLE hRoamingMngr) |
| { |
| roamingMngr_t *pRoamingMngr; |
| |
| pRoamingMngr = (roamingMngr_t*)hRoamingMngr; |
| TRACE0(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smScanFailure \n"); |
| |
| /* clean intenal variables */ |
| pRoamingMngr->maskRoamingEvents = TI_TRUE; |
| pRoamingMngr->roamingTrigger = ROAMING_TRIGGER_NONE; |
| |
| scanMngr_stopContScan(pRoamingMngr->hScanMngr); |
| |
| apConn_disconnect(pRoamingMngr->hAPConnection); |
| } |
| |
| #if 0 |
| /** |
| * |
| * roamingMngr_smCmdFailure |
| * |
| * \b Description: |
| * |
| * This procedure is called when all the driver failed to prepare to Roaming. |
| * Mask all future Roaming triggers. |
| * |
| * |
| * \b ARGS: |
| * |
| * I - hRoamingMngr - roamingMngr SM context \n |
| * |
| * \b RETURNS: |
| * |
| * TI_OK if successful, TI_NOK otherwise. |
| * |
| * |
| */ |
| static void roamingMngr_smCmdFailure(TI_HANDLE hRoamingMngr) |
| { |
| roamingMngr_t *pRoamingMngr; |
| |
| pRoamingMngr = (roamingMngr_t*)hRoamingMngr; |
| TRACE0(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smCmdFailure \n"); |
| |
| /* clean intenal variables */ |
| pRoamingMngr->maskRoamingEvents = TI_TRUE; |
| pRoamingMngr->roamingTrigger = ROAMING_TRIGGER_NONE; |
| } |
| #endif |
| |
| /** |
| * |
| * roamingMngr_smStartIdle - Start event when in Idle state |
| * |
| * \b Description: |
| * |
| * Start event when in Idle state. |
| * This function is called when the station becomes CONNECTED. |
| * Perform the following: |
| * - The current state becomes WAIT_4_TRIGGER |
| * - Unmask Roaming events |
| * - Set handoverWasPerformed to TI_FALSE |
| * - Start the Scan Manager |
| * |
| * \b ARGS: |
| * |
| * I - pData - pointer to the roamingMngr SM context \n |
| * |
| * \b RETURNS: |
| * |
| * TI_OK if successful, TI_NOK otherwise. |
| * |
| * |
| */ |
| static void roamingMngr_smStartIdle(void *pData) |
| { |
| roamingMngr_t *pRoamingMngr; |
| bssEntry_t *pCurBssEntry; |
| |
| pRoamingMngr = (roamingMngr_t*)pData; |
| TRACE0(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smStartIdle, Unmask Roaming events and start continuos scan \n"); |
| |
| pRoamingMngr->maskRoamingEvents = TI_FALSE; |
| pRoamingMngr->handoverWasPerformed = TI_FALSE; |
| pRoamingMngr->roamingTrigger = ROAMING_TRIGGER_NONE; |
| |
| pCurBssEntry = apConn_getBSSParams(pRoamingMngr->hAPConnection); |
| scanMngr_startContScan(pRoamingMngr->hScanMngr, &pCurBssEntry->BSSID, pCurBssEntry->band); |
| |
| /* Start pre-authentication in order to set PMKID |
| for the current AP */ |
| if (pRoamingMngr->staCapabilities.authMode==os802_11AuthModeWPA2) |
| { /* No Pre-Auth is required */ |
| bssList_t *pBssList; |
| |
| TRACE0(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smStartIdle, Pre-Auth to cur AP\n"); |
| pBssList = os_memoryAlloc(pRoamingMngr->hOs, sizeof(bssList_t)); |
| if (!pBssList) |
| { |
| return; |
| } |
| |
| pBssList->numOfEntries = 0; |
| apConn_preAuthenticate(pRoamingMngr->hAPConnection, pBssList); |
| os_memoryFree(pRoamingMngr->hOs, pBssList, sizeof(bssList_t)); |
| } |
| } |
| |