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 */
roamingMngr_smRoamTrigger(TI_HANDLE hRoamingMngr)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 */
roamingMngr_smInvokeScan(TI_HANDLE hRoamingMngr)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 */
roamingMngr_smSelection(TI_HANDLE hRoamingMngr)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 */
roamingMngr_smHandover(TI_HANDLE hRoamingMngr)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 */
roamingMngr_smDisconnectWhileConnecting(TI_HANDLE hRoamingMngr)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 */
roamingMngr_smSuccHandover(TI_HANDLE hRoamingMngr)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 */
roamingMngr_smFailHandover(TI_HANDLE hRoamingMngr)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 */
roamingMngr_smScanFailure(TI_HANDLE hRoamingMngr)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 */
roamingMngr_smStartIdle(void * pData)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