1 /* 2 * roamingMngr_autoSM.c 3 * 4 * Copyright(c) 1998 - 2010 Texas Instruments. All rights reserved. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name Texas Instruments nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /** \file roamingMngr_autoSM.c 35 * \brief Roaming Manager 36 * 37 * \see roamingMngr_autoSM.h 38 */ 39 40 /**************************************************************************** 41 * * 42 * MODULE: Roaming Manager * 43 * PURPOSE: * 44 * Roaming manager is responsible to receive Roaming triggers and try 45 * to select a better AP. 46 * The Roaming triggers are: Low RSSI, PER, consecutive No ACK on TX, 47 * beacon Missed or External request. 48 * In each Internal Roaming request, scan is performed and selection for 49 * better AP. Better AP is defined as a different AP with better RSSI, 50 * and similar SSID and security settings. 51 * If better AP is found, there is a check for fast-roaming via the 52 * Supplicant. Then connection to the new AP is invoked. 53 * * 54 ****************************************************************************/ 55 56 #define __FILE_ID__ FILE_ID_135 57 #include "osApi.h" 58 59 #include "paramOut.h" 60 #include "report.h" 61 #include "scanMngrApi.h" 62 #include "roamingMngrApi.h" 63 #include "apConnApi.h" 64 #include "roamingMngrTypes.h" 65 #include "bssTypes.h" 66 #include "DrvMainModules.h" 67 #include "TWDriver.h" 68 #include "siteMgrApi.h" 69 #include "GenSM.h" 70 #include "roamingMngr_autoSM.h" 71 72 73 /***************************************************************************** 74 ** Private Function section ** 75 *****************************************************************************/ 76 /* SM functions */ 77 78 static void roamingMngr_smStartIdle(TI_HANDLE hRoamingMngr); 79 static void roamingMngr_smRoamTrigger(TI_HANDLE hRoamingMngr); 80 static void roamingMngr_smInvokeScan(TI_HANDLE hRoamingMngr); 81 static void roamingMngr_smSelection(TI_HANDLE hRoamingMngr); 82 static void roamingMngr_smHandover(TI_HANDLE hRoamingMngr); 83 static void roamingMngr_smSuccHandover(TI_HANDLE hRoamingMngr); 84 static void roamingMngr_smFailHandover(TI_HANDLE hRoamingMngr); 85 static void roamingMngr_smScanFailure(TI_HANDLE hRoamingMngr); 86 static void roamingMngr_smDisconnectWhileConnecting(TI_HANDLE hRoamingMngr); 87 88 /*static TI_STATUS roamingMngr_smUnexpected(TI_HANDLE hRoamingMngr); 89 static TI_STATUS roamingMngr_smNop(TI_HANDLE hRoamingMngr); 90 static TI_STATUS roamingMngr_smStopWhileScanning(TI_HANDLE hRoamingMngr); 91 */ 92 93 typedef enum 94 { 95 REASSOC_RESP_SUCCESS =0, 96 REASSOC_RESP_FAILURE, 97 REASSOC_RESP_REJECT 98 } reassociationResp_e; 99 100 101 /*-----------*/ 102 /* Constants */ 103 /*-----------*/ 104 105 TGenSM_actionCell roamingMngrAuto_matrix[ROAMING_MNGR_NUM_STATES][ROAMING_MNGR_NUM_EVENTS] = 106 { 107 /* next state and actions for IDLE state */ 108 { {ROAMING_STATE_WAIT_4_TRIGGER, roamingMngr_smStartIdle}, /* START */ 109 {ROAMING_STATE_IDLE, roamingMngr_smNop}, /* STOP */ 110 {ROAMING_STATE_IDLE, roamingMngr_smNop}, /* ROAM_TRIGGER */ 111 {ROAMING_STATE_IDLE, roamingMngr_smUnexpected}, /* SCAN */ 112 {ROAMING_STATE_IDLE, roamingMngr_smUnexpected}, /* SELECT */ 113 {ROAMING_STATE_IDLE, roamingMngr_smUnexpected}, /* REQ_HANDOVER */ 114 {ROAMING_STATE_IDLE, roamingMngr_smUnexpected}, /* ROAM_SUCCESS */ 115 {ROAMING_STATE_IDLE, roamingMngr_smUnexpected} /* FAILURE */ 116 }, 117 118 /* next state and actions for WAIT_4_TRIGGER state */ 119 { {ROAMING_STATE_WAIT_4_TRIGGER, roamingMngr_smUnexpected}, /* START */ 120 {ROAMING_STATE_IDLE, roamingMngr_smStop}, /* STOP */ 121 {ROAMING_STATE_WAIT_4_CMD, roamingMngr_smRoamTrigger}, /* ROAM_TRIGGER */ 122 {ROAMING_STATE_WAIT_4_TRIGGER, roamingMngr_smUnexpected}, /* SCAN */ 123 {ROAMING_STATE_WAIT_4_TRIGGER, roamingMngr_smUnexpected}, /* SELECT */ 124 {ROAMING_STATE_WAIT_4_TRIGGER, roamingMngr_smUnexpected}, /* REQ_HANDOVER */ 125 {ROAMING_STATE_WAIT_4_TRIGGER, roamingMngr_smUnexpected}, /* ROAM_SUCCESS */ 126 {ROAMING_STATE_WAIT_4_TRIGGER, roamingMngr_smUnexpected} /* FAILURE */ 127 }, 128 129 /* next state and actions for WAIT_4_CMD state */ 130 { {ROAMING_STATE_WAIT_4_CMD, roamingMngr_smUnexpected}, /* START */ 131 {ROAMING_STATE_WAIT_4_CMD, roamingMngr_smUnexpected}, /* STOP */ 132 {ROAMING_STATE_WAIT_4_CMD, roamingMngr_smUnexpected}, /* ROAM_TRIGGER */ 133 {ROAMING_STATE_SCANNING, roamingMngr_smInvokeScan}, /* SCAN */ 134 {ROAMING_STATE_SELECTING, roamingMngr_smSelection}, /* SELECT */ 135 {ROAMING_STATE_WAIT_4_CMD, roamingMngr_smUnexpected}, /* REQ_HANDOVER */ 136 {ROAMING_STATE_WAIT_4_CMD, roamingMngr_smUnexpected}, /* ROAM_SUCCESS */ 137 {ROAMING_STATE_WAIT_4_CMD, roamingMngr_smUnexpected} /* FAILURE */ 138 }, 139 140 /* next state and actions for SCANNING state */ 141 { {ROAMING_STATE_SCANNING, roamingMngr_smUnexpected}, /* START */ 142 {ROAMING_STATE_IDLE, roamingMngr_smStopWhileScanning}, /* STOP */ 143 {ROAMING_STATE_SCANNING, roamingMngr_smNop}, /* ROAM_TRIGGER */ 144 {ROAMING_STATE_SCANNING, roamingMngr_smInvokeScan}, /* SCAN */ 145 {ROAMING_STATE_SELECTING, roamingMngr_smSelection}, /* SELECT */ 146 {ROAMING_STATE_SCANNING, roamingMngr_smUnexpected}, /* REQ_HANDOVER */ 147 {ROAMING_STATE_SCANNING, roamingMngr_smUnexpected}, /* ROAM_SUCCESS */ 148 {ROAMING_STATE_IDLE, roamingMngr_smScanFailure} /* FAILURE */ 149 150 }, 151 152 /* next state and actions for SELECTING state */ 153 { {ROAMING_STATE_SELECTING, roamingMngr_smUnexpected}, /* START */ 154 {ROAMING_STATE_SELECTING, roamingMngr_smUnexpected}, /* STOP */ 155 {ROAMING_STATE_SELECTING, roamingMngr_smUnexpected}, /* ROAM_TRIGGER */ 156 {ROAMING_STATE_SELECTING, roamingMngr_smUnexpected}, /* SCAN */ 157 {ROAMING_STATE_SELECTING, roamingMngr_smUnexpected}, /* SELECT */ 158 {ROAMING_STATE_CONNECTING, roamingMngr_smHandover}, /* REQ_HANDOVER */ 159 {ROAMING_STATE_SELECTING, roamingMngr_smUnexpected}, /* ROAM_SUCCESS */ 160 {ROAMING_STATE_SELECTING, roamingMngr_smUnexpected} /* FAILURE */ 161 162 }, 163 164 /* next state and actions for CONNECTING state */ 165 { {ROAMING_STATE_CONNECTING, roamingMngr_smUnexpected}, /* START */ 166 {ROAMING_STATE_IDLE, roamingMngr_smStop}, /* STOP */ 167 {ROAMING_STATE_IDLE, roamingMngr_smDisconnectWhileConnecting}, /* ROAM_TRIGGER */ 168 {ROAMING_STATE_CONNECTING, roamingMngr_smUnexpected}, /* SCAN, */ 169 {ROAMING_STATE_CONNECTING, roamingMngr_smUnexpected}, /* SELECT */ 170 {ROAMING_STATE_CONNECTING, roamingMngr_smHandover}, /* REQ_HANDOVER */ 171 {ROAMING_STATE_WAIT_4_TRIGGER, roamingMngr_smSuccHandover} , /* ROAM_SUCCESS */ 172 {ROAMING_STATE_IDLE, roamingMngr_smFailHandover} /* FAILURE */ 173 174 } 175 }; 176 177 178 TI_INT8* AutoRoamStateDescription[] = 179 { 180 "IDLE", 181 "WAIT_4_TRIGGER", 182 "WAIT_4_CMD", 183 "SCANNING", 184 "SELECTING", 185 "CONNECTING" 186 }; 187 188 TI_INT8* AutoRoamEventDescription[] = 189 { 190 "START", 191 "STOP", 192 "ROAM_TRIGGER", 193 "SCAN", 194 "SELECT", 195 "REQ_HANDOVER", 196 "ROAM_SUCCESS", 197 "FAILURE" 198 }; 199 200 /** 201 * 202 * roamingMngr_smRoamTrigger 203 * 204 * \b Description: 205 * 206 * This procedure is called when an Roaming event occurs: BSS LOSS, LOW Quality etc. 207 * Performs the following: 208 * - If Roaming is disabled, ignore. 209 * - Indicate Driver that Roaming process is starting 210 * - Get the BSS list from the Scan Manager. 211 * - If the list is not empty, start SELECTION 212 * - If the list is empty, start SCANNING. The type of scan is decided 213 * according to the Neigbor APs existence. 214 * 215 * \b ARGS: 216 * 217 * I - hRoamingMngr - roamingMngr SM context \n 218 * 219 * \b RETURNS: 220 * 221 * TI_OK if successful, TI_NOK otherwise. 222 * 223 * 224 */ 225 static void roamingMngr_smRoamTrigger(TI_HANDLE hRoamingMngr) 226 { 227 roamingMngr_t *pRoamingMngr; 228 roamingMngr_smEvents roamingEvent; 229 230 pRoamingMngr = (roamingMngr_t*)hRoamingMngr; 231 TRACE1(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smRoamTrigger, enableDisable = %d\n",pRoamingMngr->roamingMngrConfig.enableDisable); 232 233 if (!pRoamingMngr->roamingMngrConfig.enableDisable) 234 { 235 /* Ignore any other Roaming event when Roaming is disabled */ 236 TRACE0(pRoamingMngr->hReport, REPORT_SEVERITY_ERROR, "roamingMngr_smRoamTrigger, when Roaming is disabled\n"); 237 return; 238 } 239 /* Indicate the driver that Roaming process is starting */ 240 apConn_prepareToRoaming(pRoamingMngr->hAPConnection, pRoamingMngr->roamingTrigger); 241 242 /* Get the current BSSIDs from ScanMngr */ 243 pRoamingMngr->pListOfAPs = scanMngr_getBSSList(pRoamingMngr->hScanMngr); 244 if ((pRoamingMngr->pListOfAPs != NULL) && (pRoamingMngr->pListOfAPs->numOfEntries > 0)) 245 { /* No need to SCAN, start SELECTING */ 246 roamingEvent = ROAMING_EVENT_SELECT; 247 } 248 else 249 { /* check if list of APs exists in order to verify which scan to start */ 250 roamingEvent = ROAMING_EVENT_SCAN; 251 if (pRoamingMngr->neighborApsExist) 252 { /* Scan only Neighbor APs */ 253 pRoamingMngr->scanType = ROAMING_PARTIAL_SCAN; 254 } 255 else 256 { /* Scan all channels */ 257 pRoamingMngr->scanType = ROAMING_FULL_SCAN; 258 } 259 } 260 TRACE1(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smRoamTrigger, scanType = %d\n", pRoamingMngr->scanType); 261 262 roamingMngr_smEvent(roamingEvent, pRoamingMngr); 263 } 264 265 /** 266 * 267 * roamingMngr_smInvokeScan 268 * 269 * \b Description: 270 * 271 * This procedure is called when scan should be performed in order 272 * to select an AP to roam to. 273 * This can be the first scan, a second scan after partail scan, 274 * or scan after previous scan was failed. 275 * In any case, the scan can either be: 276 * partail, on list of channles or 277 * full on all channels. 278 * 279 * \b ARGS: 280 * 281 * I - hRoamingMngr - roamingMngr SM context \n 282 * 283 * \b RETURNS: 284 * 285 * TI_OK if successful, TI_NOK otherwise. 286 * 287 * 288 */ 289 static void roamingMngr_smInvokeScan(TI_HANDLE hRoamingMngr) 290 { 291 roamingMngr_t *pRoamingMngr; 292 scan_mngrResultStatus_e scanResult; 293 294 pRoamingMngr = (roamingMngr_t*)hRoamingMngr; 295 296 /* check which scan should be performed: Partial on list of channels, or full scan */ 297 if ((pRoamingMngr->scanType == ROAMING_PARTIAL_SCAN) || 298 (pRoamingMngr->scanType == ROAMING_PARTIAL_SCAN_RETRY)) 299 { 300 scanResult = scanMngr_startImmediateScan (pRoamingMngr->hScanMngr, TI_TRUE); 301 } 302 else 303 { /* Scan all channels */ 304 scanResult = scanMngr_startImmediateScan (pRoamingMngr->hScanMngr, TI_FALSE); 305 } 306 307 if (scanResult != SCAN_MRS_SCAN_RUNNING) 308 { /* the scan failed, immitate scan complete event */ 309 TRACE1(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smInvokeScan, scanResult = %d\n", scanResult); 310 roamingMngr_immediateScanComplete(pRoamingMngr, scanResult); 311 } 312 } 313 314 /** 315 * 316 * roamingMngr_smSelection 317 * 318 * \b Description: 319 * 320 * This procedure is called when selection should be performed. 321 * It perform the following: 322 * Prepare the candidate APs to roam according to: 323 * - Priority APs 324 * - Pre-Authenticated APs 325 * If the candidate AP list is empty, only the current AP can be re-selected 326 * Select one AP and trigger REQ_HANDOVER event. 327 * 328 * \b ARGS: 329 * 330 * I - hRoamingMngr - roamingMngr SM context \n 331 * 332 * \b RETURNS: 333 * 334 * TI_OK if successful, TI_NOK otherwise. 335 * 336 * 337 */ 338 static void roamingMngr_smSelection(TI_HANDLE hRoamingMngr) 339 { 340 roamingMngr_t *pRoamingMngr; 341 TI_UINT32 index; 342 343 344 pRoamingMngr = (roamingMngr_t*)hRoamingMngr; 345 pRoamingMngr->listOfCandidateAps.numOfNeighborBSS = 0; 346 pRoamingMngr->listOfCandidateAps.numOfPreAuthBSS = 0; 347 pRoamingMngr->listOfCandidateAps.numOfRegularBSS = 0; 348 349 pRoamingMngr->candidateApIndex = INVALID_CANDIDATE_INDEX; 350 351 if ((pRoamingMngr->pListOfAPs == NULL) || 352 (pRoamingMngr->pListOfAPs->numOfEntries == 0)) 353 { /* Error, there cannot be selection */ 354 TRACE0(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smSelection pListOfAPs is empty \n"); 355 roamingMngr_smEvent(ROAMING_EVENT_REQ_HANDOVER, pRoamingMngr); 356 return; 357 } 358 359 /* Build the candidate AP list */ 360 for (index=0; index<pRoamingMngr->pListOfAPs->numOfEntries; index++ ) 361 { 362 if ( (pRoamingMngr->roamingTrigger <= ROAMING_TRIGGER_LOW_QUALITY_GROUP) && 363 (pRoamingMngr->pListOfAPs->BSSList[index].RSSI < pRoamingMngr->roamingMngrConfig.apQualityThreshold)) 364 { /* Do not insert APs with low quality to the selection table, 365 if the Roaming Trigger was low Quality */ 366 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); 367 368 continue; 369 } 370 371 if (apConn_isSiteBanned(pRoamingMngr->hAPConnection, &pRoamingMngr->pListOfAPs->BSSList[index].BSSID) == TI_TRUE) 372 { 373 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]); 374 continue; 375 } 376 377 if (pRoamingMngr->pListOfAPs->BSSList[index].bNeighborAP) 378 { /* The AP is a neighbor AP, insert its index to the neighbor APs list */ 379 pRoamingMngr->listOfCandidateAps.neighborBSSList[pRoamingMngr->listOfCandidateAps.numOfNeighborBSS] = index; 380 pRoamingMngr->listOfCandidateAps.numOfNeighborBSS++; 381 } 382 else if (apConn_getPreAuthAPStatus(pRoamingMngr->hAPConnection, 383 &pRoamingMngr->pListOfAPs->BSSList[index].BSSID)) 384 { /* This AP is a pre-auth AP */ 385 pRoamingMngr->listOfCandidateAps.preAuthBSSList[pRoamingMngr->listOfCandidateAps.numOfPreAuthBSS] = index; 386 pRoamingMngr->listOfCandidateAps.numOfPreAuthBSS++; 387 } 388 else 389 { /* This AP is not Neighbor nor Pre-Auth */ 390 pRoamingMngr->listOfCandidateAps.regularBSSList[pRoamingMngr->listOfCandidateAps.numOfRegularBSS] = index; 391 pRoamingMngr->listOfCandidateAps.numOfRegularBSS++; 392 } 393 } 394 395 #ifdef TI_DBG 396 { /* for debug */ 397 paramInfo_t param; 398 399 param.paramType = ROAMING_MNGR_PRINT_CANDIDATE_TABLE; 400 roamingMngr_getParam(pRoamingMngr, ¶m); 401 402 } 403 #endif 404 roamingMngr_smEvent(ROAMING_EVENT_REQ_HANDOVER, pRoamingMngr); 405 406 } 407 408 /** 409 * 410 * roamingMngr_smHandover 411 * 412 * \b Description: 413 * 414 * This procedure is called when handover should be invoked. 415 * Go over the candidate APs and start handover to each of them. 416 * If there's no candidate APs, disconnect. 417 * Handover to the current AP is allowed only if the trigger is 418 * low quality. 419 * 420 * \b ARGS: 421 * 422 * I - hRoamingMngr - roamingMngr SM context \n 423 * 424 * \b RETURNS: 425 * 426 * TI_OK if successful, TI_NOK otherwise. 427 * 428 * 429 */ 430 static void roamingMngr_smHandover(TI_HANDLE hRoamingMngr) 431 { 432 roamingMngr_t *pRoamingMngr; 433 bssEntry_t *pApToConnect; 434 apConn_connRequest_t requestToApConn; 435 436 pRoamingMngr = (roamingMngr_t*)hRoamingMngr; 437 438 if ((pRoamingMngr->handoverWasPerformed) && (pRoamingMngr->candidateApIndex == CURRENT_AP_INDEX)) 439 { /* Handover with the current AP already failed, Disconnect */ 440 roamingMngr_smEvent(ROAMING_EVENT_FAILURE, pRoamingMngr); 441 return; 442 } 443 if (pRoamingMngr->listOfCandidateAps.numOfNeighborBSS > 0) 444 { /* Neighbor APs are the highest priority to Roam */ 445 pRoamingMngr->candidateApIndex = 446 pRoamingMngr->listOfCandidateAps.neighborBSSList[pRoamingMngr->listOfCandidateAps.numOfNeighborBSS-1]; 447 pRoamingMngr->listOfCandidateAps.numOfNeighborBSS--; 448 } 449 else if (pRoamingMngr->listOfCandidateAps.numOfPreAuthBSS > 0) 450 { /* Pre-Auth APs are the second priority to Roam */ 451 pRoamingMngr->candidateApIndex = 452 pRoamingMngr->listOfCandidateAps.preAuthBSSList[pRoamingMngr->listOfCandidateAps.numOfPreAuthBSS-1]; 453 pRoamingMngr->listOfCandidateAps.numOfPreAuthBSS--; 454 } 455 else if (pRoamingMngr->listOfCandidateAps.numOfRegularBSS > 0) 456 { /* Regular APs are APs that are not pre-authenticated and not Neighbor */ 457 pRoamingMngr->candidateApIndex = 458 pRoamingMngr->listOfCandidateAps.regularBSSList[pRoamingMngr->listOfCandidateAps.numOfRegularBSS-1]; 459 pRoamingMngr->listOfCandidateAps.numOfRegularBSS--; 460 } 461 else 462 { /* No Candidate APs */ 463 pRoamingMngr->candidateApIndex = INVALID_CANDIDATE_INDEX; 464 } 465 466 TRACE1(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smHandover, candidateApIndex=%d \n", pRoamingMngr->candidateApIndex); 467 468 469 if (pRoamingMngr->candidateApIndex == INVALID_CANDIDATE_INDEX) 470 { /* No cnadidate to Roam to, only the current AP is candidate */ 471 if (pRoamingMngr->roamingTrigger <= ROAMING_TRIGGER_LOW_QUALITY_GROUP) 472 { /* If the trigger to Roam is low quality, and there are no candidate APs 473 to roam to, retain connected to the current AP */ 474 requestToApConn.requestType = (pRoamingMngr->handoverWasPerformed) ? AP_CONNECT_RECONNECT_CURR_AP : AP_CONNECT_RETAIN_CURR_AP; 475 pRoamingMngr->candidateApIndex = CURRENT_AP_INDEX; 476 } 477 else 478 { /* Disconnect the BSS, there are no more APs to roam to */ 479 roamingMngr_smEvent(ROAMING_EVENT_FAILURE, pRoamingMngr); 480 return; 481 } 482 } 483 else 484 { /* There is a valid candidate AP */ 485 if (pRoamingMngr->roamingTrigger > ROAMING_TRIGGER_FAST_CONNECT_GROUP) 486 { /* Full re-connection should be perfromed */ 487 requestToApConn.requestType = AP_CONNECT_FULL_TO_AP; 488 } 489 else 490 { /* Fast re-connection should be perfromed */ 491 requestToApConn.requestType = AP_CONNECT_FAST_TO_AP; 492 } 493 } 494 #ifdef TI_DBG 495 /* For debug */ 496 if (!pRoamingMngr->handoverWasPerformed) 497 { /* Take the time before the first handover started */ 498 pRoamingMngr->roamingHandoverStartedTimestamp = os_timeStampMs(pRoamingMngr->hOs); 499 } 500 #endif 501 502 if (pRoamingMngr->candidateApIndex == CURRENT_AP_INDEX) 503 { /* get the current AP */ 504 pApToConnect = apConn_getBSSParams(pRoamingMngr->hAPConnection); 505 } 506 else 507 { /* get the candidate AP */ 508 pRoamingMngr->handoverWasPerformed = TI_TRUE; 509 pApToConnect = &pRoamingMngr->pListOfAPs->BSSList[pRoamingMngr->candidateApIndex]; 510 } 511 TRACE3(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smHandover, candidateApIndex=%d, requestType = %d, channel=%d \n", pRoamingMngr->candidateApIndex, requestToApConn.requestType, pApToConnect->channel); 512 513 requestToApConn.dataBufLength = 0; 514 515 #ifdef XCC_MODULE_INCLUDED 516 apConn_connectToAP(pRoamingMngr->hAPConnection, pApToConnect, &requestToApConn, pRoamingMngr->bSendTspecInReassPkt); 517 #else 518 apConn_connectToAP(pRoamingMngr->hAPConnection, pApToConnect, &requestToApConn, TI_TRUE); 519 #endif 520 } 521 522 /** 523 * 524 * roamingMngr_smDisconnectWhileConnecting 525 * 526 * \b Description: 527 * 528 * This procedure is called when the Station is in the process of connection, 529 * and the AP disconnects the station. 530 * 531 * \b ARGS: 532 * 533 * I - hRoamingMngr - roamingMngr SM context \n 534 * 535 * \b RETURNS: 536 * 537 * TI_OK if successful, TI_NOK otherwise. 538 * 539 * 540 */ 541 static void roamingMngr_smDisconnectWhileConnecting(TI_HANDLE hRoamingMngr) 542 { 543 roamingMngr_t *pRoamingMngr; 544 545 pRoamingMngr = (roamingMngr_t*)hRoamingMngr; 546 547 TRACE1(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smDisconnectWhileConnecting, candidateApIndex=%d \n", pRoamingMngr->candidateApIndex); 548 549 if (pRoamingMngr->roamingTrigger > ROAMING_TRIGGER_FAST_CONNECT_GROUP) 550 { /* If the trigger is from the Full Connect group, then stop the connection. */ 551 /* clean intenal variables */ 552 pRoamingMngr->maskRoamingEvents = TI_TRUE; 553 pRoamingMngr->roamingTrigger = ROAMING_TRIGGER_NONE; 554 555 scanMngr_stopContScan(pRoamingMngr->hScanMngr); 556 #ifdef TI_DBG 557 pRoamingMngr->roamingFailedHandoverNum++; 558 #endif 559 apConn_disconnect(pRoamingMngr->hAPConnection); 560 561 } 562 } 563 564 /** 565 * 566 * roamingMngr_smSuccHandover 567 * 568 * \b Description: 569 * 570 * This procedure is called when handover succeeded. 571 * Inform Scan Manager about the new AP. 572 * UnMask Roaming Triggers. 573 * 574 * \b ARGS: 575 * 576 * I - hRoamingMngr - roamingMngr SM context \n 577 * 578 * \b RETURNS: 579 * 580 * TI_OK if successful, TI_NOK otherwise. 581 * 582 * 583 */ 584 static void roamingMngr_smSuccHandover(TI_HANDLE hRoamingMngr) 585 { 586 roamingMngr_t *pRoamingMngr; 587 bssEntry_t *pNewConnectedAp; 588 589 pRoamingMngr = (roamingMngr_t*)hRoamingMngr; 590 591 TRACE1(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smSuccHandover, candidateApIndex=%d \n", pRoamingMngr->candidateApIndex); 592 593 if (pRoamingMngr->handoverWasPerformed && 594 (pRoamingMngr->pListOfAPs != NULL) && 595 (pRoamingMngr->pListOfAPs->numOfEntries>0)) 596 { 597 if (pRoamingMngr->candidateApIndex == CURRENT_AP_INDEX) 598 { 599 /* get the current AP */ 600 pNewConnectedAp = apConn_getBSSParams(pRoamingMngr->hAPConnection); 601 } 602 else 603 { 604 /* get the candidate AP */ 605 pNewConnectedAp = &pRoamingMngr->pListOfAPs->BSSList[pRoamingMngr->candidateApIndex]; 606 } 607 608 scanMngr_handoverDone(pRoamingMngr->hScanMngr, 609 &pNewConnectedAp->BSSID, 610 pNewConnectedAp->band); 611 } 612 pRoamingMngr->maskRoamingEvents = TI_FALSE; 613 pRoamingMngr->candidateApIndex = INVALID_CANDIDATE_INDEX; 614 pRoamingMngr->handoverWasPerformed = TI_FALSE; 615 pRoamingMngr->roamingTrigger = ROAMING_TRIGGER_NONE; 616 617 /* Start pre-authentication in order to set PMKID 618 for the current AP */ 619 if (pRoamingMngr->staCapabilities.authMode==os802_11AuthModeWPA2) 620 { 621 /* No Pre-Auth is required */ 622 bssList_t *pBssList; 623 624 pBssList = os_memoryAlloc(pRoamingMngr->hOs, sizeof(bssList_t)); 625 if (!pBssList) 626 { 627 return; 628 } 629 pBssList->numOfEntries = 0; 630 apConn_preAuthenticate(pRoamingMngr->hAPConnection, pBssList); 631 os_memoryFree(pRoamingMngr->hOs, pBssList, sizeof(bssList_t)); 632 } 633 } 634 635 /** 636 * 637 * roamingMngr_smFailHandover 638 * 639 * \b Description: 640 * 641 * This procedure is called when handover failed and there are no more 642 * APs to roam to. Disconnect the BSS and retrun to IDLE state. 643 * 644 * \b ARGS: 645 * 646 * I - hRoamingMngr - roamingMngr SM context \n 647 * 648 * \b RETURNS: 649 * 650 * TI_OK if successful, TI_NOK otherwise. 651 * 652 * 653 */ 654 static void roamingMngr_smFailHandover(TI_HANDLE hRoamingMngr) 655 { 656 roamingMngr_t *pRoamingMngr; 657 658 pRoamingMngr = (roamingMngr_t*)hRoamingMngr; 659 TRACE0(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smFailHandover \n"); 660 661 /* clean intenal variables */ 662 pRoamingMngr->maskRoamingEvents = TI_TRUE; 663 pRoamingMngr->roamingTrigger = ROAMING_TRIGGER_NONE; 664 665 scanMngr_stopContScan(pRoamingMngr->hScanMngr); 666 #ifdef TI_DBG 667 pRoamingMngr->roamingFailedHandoverNum++; 668 #endif 669 apConn_disconnect(pRoamingMngr->hAPConnection); 670 } 671 672 /** 673 * 674 * roamingMngr_smScanFailure 675 * 676 * \b Description: 677 * 678 * This procedure is called when all scan attempts failed. 679 * Send Disconnect event and return to IDLE state. 680 * 681 * 682 * \b ARGS: 683 * 684 * I - hRoamingMngr - roamingMngr SM context \n 685 * 686 * \b RETURNS: 687 * 688 * TI_OK if successful, TI_NOK otherwise. 689 * 690 * 691 */ 692 static void roamingMngr_smScanFailure(TI_HANDLE hRoamingMngr) 693 { 694 roamingMngr_t *pRoamingMngr; 695 696 pRoamingMngr = (roamingMngr_t*)hRoamingMngr; 697 TRACE0(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smScanFailure \n"); 698 699 /* clean intenal variables */ 700 pRoamingMngr->maskRoamingEvents = TI_TRUE; 701 pRoamingMngr->roamingTrigger = ROAMING_TRIGGER_NONE; 702 703 scanMngr_stopContScan(pRoamingMngr->hScanMngr); 704 705 apConn_disconnect(pRoamingMngr->hAPConnection); 706 } 707 708 #if 0 709 /** 710 * 711 * roamingMngr_smCmdFailure 712 * 713 * \b Description: 714 * 715 * This procedure is called when all the driver failed to prepare to Roaming. 716 * Mask all future Roaming triggers. 717 * 718 * 719 * \b ARGS: 720 * 721 * I - hRoamingMngr - roamingMngr SM context \n 722 * 723 * \b RETURNS: 724 * 725 * TI_OK if successful, TI_NOK otherwise. 726 * 727 * 728 */ 729 static void roamingMngr_smCmdFailure(TI_HANDLE hRoamingMngr) 730 { 731 roamingMngr_t *pRoamingMngr; 732 733 pRoamingMngr = (roamingMngr_t*)hRoamingMngr; 734 TRACE0(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smCmdFailure \n"); 735 736 /* clean intenal variables */ 737 pRoamingMngr->maskRoamingEvents = TI_TRUE; 738 pRoamingMngr->roamingTrigger = ROAMING_TRIGGER_NONE; 739 } 740 #endif 741 742 /** 743 * 744 * roamingMngr_smStartIdle - Start event when in Idle state 745 * 746 * \b Description: 747 * 748 * Start event when in Idle state. 749 * This function is called when the station becomes CONNECTED. 750 * Perform the following: 751 * - The current state becomes WAIT_4_TRIGGER 752 * - Unmask Roaming events 753 * - Set handoverWasPerformed to TI_FALSE 754 * - Start the Scan Manager 755 * 756 * \b ARGS: 757 * 758 * I - pData - pointer to the roamingMngr SM context \n 759 * 760 * \b RETURNS: 761 * 762 * TI_OK if successful, TI_NOK otherwise. 763 * 764 * 765 */ 766 static void roamingMngr_smStartIdle(void *pData) 767 { 768 roamingMngr_t *pRoamingMngr; 769 bssEntry_t *pCurBssEntry; 770 771 pRoamingMngr = (roamingMngr_t*)pData; 772 TRACE0(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smStartIdle, Unmask Roaming events and start continuos scan \n"); 773 774 pRoamingMngr->maskRoamingEvents = TI_FALSE; 775 pRoamingMngr->handoverWasPerformed = TI_FALSE; 776 pRoamingMngr->roamingTrigger = ROAMING_TRIGGER_NONE; 777 778 pCurBssEntry = apConn_getBSSParams(pRoamingMngr->hAPConnection); 779 scanMngr_startContScan(pRoamingMngr->hScanMngr, &pCurBssEntry->BSSID, pCurBssEntry->band); 780 781 /* Start pre-authentication in order to set PMKID 782 for the current AP */ 783 if (pRoamingMngr->staCapabilities.authMode==os802_11AuthModeWPA2) 784 { /* No Pre-Auth is required */ 785 bssList_t *pBssList; 786 787 TRACE0(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smStartIdle, Pre-Auth to cur AP\n"); 788 pBssList = os_memoryAlloc(pRoamingMngr->hOs, sizeof(bssList_t)); 789 if (!pBssList) 790 { 791 return; 792 } 793 794 pBssList->numOfEntries = 0; 795 apConn_preAuthenticate(pRoamingMngr->hAPConnection, pBssList); 796 os_memoryFree(pRoamingMngr->hOs, pBssList, sizeof(bssList_t)); 797 } 798 } 799 800