OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / system / wlan / ti / wilink_6_1 / stad / src / Application / roamingMngr_autoSM.c
1 /*
2  * roamingMngr_autoSM.c
3  *
4  * Copyright(c) 1998 - 2009 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     apConn_connectToAP(pRoamingMngr->hAPConnection, pApToConnect, &requestToApConn, TI_TRUE);
515 }
516
517 /**
518 *
519 * roamingMngr_smDisconnectWhileConnecting 
520 *
521 * \b Description: 
522 *
523 * This procedure is called when the Station is in the process of connection,
524  * and the AP disconnects the station. 
525  * 
526 * \b ARGS:
527 *
528 *  I   - hRoamingMngr - roamingMngr SM context  \n
529 *
530 * \b RETURNS:
531 *
532 *  TI_OK if successful, TI_NOK otherwise.
533 *
534
535 */
536 static void roamingMngr_smDisconnectWhileConnecting(TI_HANDLE hRoamingMngr)
537 {
538     roamingMngr_t           *pRoamingMngr;
539
540     pRoamingMngr = (roamingMngr_t*)hRoamingMngr;
541  
542     TRACE1(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smDisconnectWhileConnecting, candidateApIndex=%d \n", pRoamingMngr->candidateApIndex);
543
544     if (pRoamingMngr->roamingTrigger > ROAMING_TRIGGER_FAST_CONNECT_GROUP)
545     {   /* If the trigger is from the Full Connect group, then stop the connection. */
546         /* clean intenal variables */
547         pRoamingMngr->maskRoamingEvents = TI_TRUE;
548         pRoamingMngr->roamingTrigger = ROAMING_TRIGGER_NONE;
549
550         scanMngr_stopContScan(pRoamingMngr->hScanMngr);
551 #ifdef TI_DBG
552         pRoamingMngr->roamingFailedHandoverNum++;
553 #endif
554         apConn_disconnect(pRoamingMngr->hAPConnection);
555         
556     }
557 }
558
559 /**
560 *
561 * roamingMngr_smSuccHandover 
562 *
563 * \b Description: 
564 *
565 * This procedure is called when handover succeeded.
566  * Inform Scan Manager about the new AP.    
567  * UnMask Roaming Triggers. 
568  * 
569 * \b ARGS:
570 *
571 *  I   - hRoamingMngr - roamingMngr SM context  \n
572 *
573 * \b RETURNS:
574 *
575 *  TI_OK if successful, TI_NOK otherwise.
576 *
577
578 */
579 static void roamingMngr_smSuccHandover(TI_HANDLE hRoamingMngr)
580 {
581     roamingMngr_t           *pRoamingMngr;
582     bssEntry_t              *pNewConnectedAp;
583
584     pRoamingMngr = (roamingMngr_t*)hRoamingMngr;
585
586     TRACE1(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smSuccHandover, candidateApIndex=%d \n", pRoamingMngr->candidateApIndex);
587
588     if (pRoamingMngr->handoverWasPerformed &&
589         (pRoamingMngr->pListOfAPs != NULL) &&
590         (pRoamingMngr->pListOfAPs->numOfEntries>0))
591     {
592         if (pRoamingMngr->candidateApIndex == CURRENT_AP_INDEX)
593         {   
594                         /* get the current AP */
595             pNewConnectedAp = apConn_getBSSParams(pRoamingMngr->hAPConnection);
596         }
597         else
598         {   
599                         /* get the candidate AP */
600             pNewConnectedAp = &pRoamingMngr->pListOfAPs->BSSList[pRoamingMngr->candidateApIndex];
601         }
602
603         scanMngr_handoverDone(pRoamingMngr->hScanMngr, 
604                                                           &pNewConnectedAp->BSSID,
605                                                           pNewConnectedAp->band);
606     }
607     pRoamingMngr->maskRoamingEvents = TI_FALSE;
608     pRoamingMngr->candidateApIndex = INVALID_CANDIDATE_INDEX;
609     pRoamingMngr->handoverWasPerformed = TI_FALSE;
610     pRoamingMngr->roamingTrigger = ROAMING_TRIGGER_NONE;
611
612     /* Start pre-authentication in order to set PMKID
613         for the current AP */
614     if (pRoamingMngr->staCapabilities.authMode==os802_11AuthModeWPA2)
615     {
616                 /* No Pre-Auth is required */
617         bssList_t           *pBssList;
618
619         TRACE0(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smStartIdle, Pre-Auth to cur AP\n");
620         pBssList = os_memoryAlloc(pRoamingMngr->hOs, sizeof(bssList_t));
621         if (!pBssList)
622             return;
623         pBssList->numOfEntries = 0;
624         apConn_preAuthenticate(pRoamingMngr->hAPConnection, pBssList);
625         os_memoryFree(pRoamingMngr->hOs, pBssList, sizeof(bssList_t));
626     }
627 }
628
629 /**
630 *
631 * roamingMngr_smFailHandover 
632 *
633 * \b Description: 
634 *
635 * This procedure is called when handover failed and there are no more
636  * APs to roam to. Disconnect the BSS and retrun to IDLE state.
637
638 * \b ARGS:
639 *
640 *  I   - hRoamingMngr - roamingMngr SM context  \n
641 *
642 * \b RETURNS:
643 *
644 *  TI_OK if successful, TI_NOK otherwise.
645 *
646
647 */
648 static void roamingMngr_smFailHandover(TI_HANDLE hRoamingMngr)
649 {
650     roamingMngr_t           *pRoamingMngr;
651
652     pRoamingMngr = (roamingMngr_t*)hRoamingMngr;
653     TRACE0(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smFailHandover \n");
654
655     /* clean intenal variables */
656     pRoamingMngr->maskRoamingEvents = TI_TRUE;
657     pRoamingMngr->roamingTrigger = ROAMING_TRIGGER_NONE;
658
659     scanMngr_stopContScan(pRoamingMngr->hScanMngr);
660 #ifdef TI_DBG
661     pRoamingMngr->roamingFailedHandoverNum++;
662 #endif
663     apConn_disconnect(pRoamingMngr->hAPConnection);
664 }
665
666 /**
667 *
668 * roamingMngr_smScanFailure 
669 *
670 * \b Description: 
671 *
672 * This procedure is called when all scan attempts failed. 
673  * Send Disconnect event and return to IDLE state.
674  *
675
676 * \b ARGS:
677 *
678 *  I   - hRoamingMngr - roamingMngr SM context  \n
679 *
680 * \b RETURNS:
681 *
682 *  TI_OK if successful, TI_NOK otherwise.
683 *
684
685 */
686 static void roamingMngr_smScanFailure(TI_HANDLE hRoamingMngr)
687 {
688     roamingMngr_t           *pRoamingMngr;
689
690     pRoamingMngr = (roamingMngr_t*)hRoamingMngr;
691     TRACE0(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smScanFailure \n");
692
693     /* clean intenal variables */
694     pRoamingMngr->maskRoamingEvents = TI_TRUE;
695     pRoamingMngr->roamingTrigger = ROAMING_TRIGGER_NONE;
696
697     scanMngr_stopContScan(pRoamingMngr->hScanMngr);
698
699     apConn_disconnect(pRoamingMngr->hAPConnection);
700 }
701
702 #if 0
703 /**
704 *
705 * roamingMngr_smCmdFailure 
706 *
707 * \b Description: 
708 *
709 * This procedure is called when all the driver failed to prepare to Roaming. 
710  * Mask all future Roaming triggers.
711  *
712
713 * \b ARGS:
714 *
715 *  I   - hRoamingMngr - roamingMngr SM context  \n
716 *
717 * \b RETURNS:
718 *
719 *  TI_OK if successful, TI_NOK otherwise.
720 *
721
722 */
723 static void roamingMngr_smCmdFailure(TI_HANDLE hRoamingMngr)
724 {
725     roamingMngr_t           *pRoamingMngr;
726
727     pRoamingMngr = (roamingMngr_t*)hRoamingMngr;
728     TRACE0(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smCmdFailure \n");
729
730     /* clean intenal variables */
731     pRoamingMngr->maskRoamingEvents = TI_TRUE;
732     pRoamingMngr->roamingTrigger = ROAMING_TRIGGER_NONE; 
733 }
734 #endif
735
736 /**
737 *
738 * roamingMngr_smStartIdle - Start event when in Idle state
739 *
740 * \b Description: 
741 *
742 * Start event when in Idle state. 
743  * This function is called when the station becomes CONNECTED.
744  * Perform the following:
745  * - The current state becomes WAIT_4_TRIGGER 
746  * - Unmask Roaming events
747  * - Set handoverWasPerformed to TI_FALSE
748  * - Start the Scan Manager
749 *
750 * \b ARGS:
751 *
752 *  I   - pData - pointer to the roamingMngr SM context  \n
753 *
754 * \b RETURNS:
755 *
756 *  TI_OK if successful, TI_NOK otherwise.
757 *
758
759 */
760 static void roamingMngr_smStartIdle(void *pData)
761 {
762     roamingMngr_t       *pRoamingMngr;
763     bssEntry_t          *pCurBssEntry;
764
765     pRoamingMngr = (roamingMngr_t*)pData;
766     TRACE0(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smStartIdle, Unmask Roaming events and start continuos scan \n");
767
768     pRoamingMngr->maskRoamingEvents = TI_FALSE;
769     pRoamingMngr->handoverWasPerformed = TI_FALSE;
770     pRoamingMngr->roamingTrigger = ROAMING_TRIGGER_NONE;
771
772     pCurBssEntry = apConn_getBSSParams(pRoamingMngr->hAPConnection);
773     scanMngr_startContScan(pRoamingMngr->hScanMngr, &pCurBssEntry->BSSID, pCurBssEntry->band);
774
775     /* Start pre-authentication in order to set PMKID
776         for the current AP */
777     if (pRoamingMngr->staCapabilities.authMode==os802_11AuthModeWPA2)
778     {   /* No Pre-Auth is required */
779         bssList_t           *pBssList;
780
781         TRACE0(pRoamingMngr->hReport, REPORT_SEVERITY_INFORMATION, "roamingMngr_smStartIdle, Pre-Auth to cur AP\n");
782         pBssList = os_memoryAlloc(pRoamingMngr->hOs, sizeof(bssList_t));
783         if (!pBssList)
784             return;
785
786         pBssList->numOfEntries = 0;
787         apConn_preAuthenticate(pRoamingMngr->hAPConnection, pBssList);
788         os_memoryFree(pRoamingMngr->hOs, pBssList, sizeof(bssList_t));
789     }
790 }
791