OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / hardware / ti / wlan / wl1271 / stad / src / Application / roamingMngr_autoSM.c
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, &param);
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