1/***************************************************************************
2**+-----------------------------------------------------------------------+**
3**|                                                                       |**
4**| Copyright(c) 1998 - 2008 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****************************************************************************/
35
36/****************************************************************************
37 *                                                                          *
38 *   MODULE:  Roaming Manager                                               *
39 *   PURPOSE:                                                               *
40 *   Roaming manager is responsible to receive Roaming triggers and try
41 *      to select a better AP.
42 *      The Roaming triggers are: Low RSSI, PER, consecutive No ACK on TX,
43 *      beacon Missed or External request.
44 *      In each Internal Roaming request, scan is performed and selection for
45 *      better AP. Better AP is defined as a different AP with better RSSI,
46 *      and similar SSID and security settings.
47 *      If better AP is found, there is a check for fast-roaming via the
48 *      Supplicant. Then connection to the new AP is invoked.
49 *                                                                          *
50 ****************************************************************************/
51
52#include "osApi.h"
53
54#include "paramOut.h"
55#include "report.h"
56#include "fsm.h"
57#include "utils.h"
58
59#include "scanMngrApi.h"
60#include "roamingMngrApi.h"
61#include "apConnApi.h"
62#include "roamingMngrTypes.h"
63#include "bssTypes.h"
64
65/* Constants */
66
67/* Init bits */
68#define ROAMING_MNGR_CONTEXT_INIT_BIT       1
69#define ROAMING_MNGR_SM_INIT_BIT            2
70
71#define DEFAULT_AP_QUALITY                  (-70)
72#define DEFAULT_LOW_PASS_FILTER             (30)
73#define DEFAULT_DATA_RETRY_THRESHOLD        (20)
74#define DEFAULT_LOW_QUALITY_SCAN_COND       (-60)
75#define DEFAULT_NORMAL_QUALITY_SCAN_COND    (-50)
76#define DEFAULT_LOW_RSSI                    (-70)
77#define DEFAULT_LOW_SNR                     (0)
78#define DEFAULT_TBTT_4_BSS_LOSS             (10)
79#define DEFAULT_LOW_TX_RATE                 (2)
80
81/* Enumerations */
82
83/** state machine states */
84typedef enum
85{
86    ROAMING_STATE_IDLE                      = 0,
87    ROAMING_STATE_WAIT_4_TRIGGER    = 1,
88    ROAMING_STATE_WAIT_4_CMD        = 2,
89    ROAMING_STATE_SCANNING          = 3,
90    ROAMING_STATE_SELECTING         = 4,
91    ROAMING_STATE_CONNECTING        = 5,
92    ROAMING_STATE_LAST              = 6
93} roamingMngr_smStates;
94
95/** State machine events */
96typedef enum
97{
98    ROAMING_EVENT_START             = 0, /* CONNECTED */
99    ROAMING_EVENT_STOP              = 1, /* NOT CONNECTED */
100    ROAMING_EVENT_ROAM_TRIGGER      = 2,
101    ROAMING_EVENT_SCAN              = 3,
102    ROAMING_EVENT_SELECT            = 4,
103    ROAMING_EVENT_REQ_HANDOVER      = 5,
104    ROAMING_EVENT_ROAM_SUCCESS      = 6,
105    ROAMING_EVENT_FAILURE           = 7,
106    ROAMING_EVENT_LAST              = 8
107} roamingMngr_smEvents;
108
109/* scan types */
110typedef enum
111{
112    ROAMING_NO_SCAN,
113    ROAMING_PARTIAL_SCAN,
114    ROAMING_PARTIAL_SCAN_RETRY,
115    ROAMING_FULL_SCAN,
116    ROAMING_FULL_SCAN_RETRY
117} scan4RoamingType_e;
118
119/* Roaming Trigger groups, according to Roaming Triggers */
120typedef enum
121{
122    ROAMING_TRIGGER_BG_SCAN_GROUP = ROAMING_TRIGGER_NORMAL_QUALITY_FOR_BG_SCAN,
123    ROAMING_TRIGGER_LOW_QUALITY_GROUP = ROAMING_TRIGGER_MAX_TX_RETRIES,
124    ROAMING_TRIGGER_FAST_CONNECT_GROUP = ROAMING_TRIGGER_SWITCH_CHANNEL,
125    ROAMING_TRIGGER_FULL_CONNECT_GROUP = ROAMING_TRIGGER_SECURITY_ATTACK
126} roamingMngr_connectTypeGroup_e;
127
128
129#define ROAMING_MNGR_NUM_STATES     ROAMING_STATE_LAST
130#define ROAMING_MNGR_NUM_EVENTS     ROAMING_EVENT_LAST
131
132#define INVALID_CANDIDATE_INDEX     0xFF
133#define CURRENT_AP_INDEX            0xFE
134
135/* Typedefs */
136
137typedef struct _roamingMngr_t   roamingMngr_t;
138/* Structures */
139typedef struct
140{
141    UINT8   preAuthBSSList[MAX_SIZE_OF_BSS_TRACK_LIST];
142    UINT8   numOfPreAuthBSS;
143    UINT8   neighborBSSList[MAX_SIZE_OF_BSS_TRACK_LIST];
144    UINT8   numOfNeighborBSS;
145    UINT8   regularBSSList[MAX_SIZE_OF_BSS_TRACK_LIST];
146    UINT8   numOfRegularBSS;
147} listOfCandidateAps_t;
148
149#define MAX_ROAMING_TRIGGERS  ROAMING_TRIGGER_LAST
150
151struct _roamingMngr_t
152{
153    /*** Roaming manager parameters that can be configured externally ***/
154    roamingMngrConfig_t         roamingMngrConfig;
155    roamingMngrThresholdsConfig_t   roamingMngrThresholdsConfig;
156    UINT32                      lowPassFilterRoamingAttemptInMsec;
157
158    /*** Internal roaming parameters ***/
159    /* the roaming trigger type */
160    apConn_roamingTrigger_e     roamingTrigger;
161    /* Roaming SM current state */
162    roamingMngr_smStates        currentState;
163    /* Indicate if a trigger is already in process, and therefore the
164        other triggers will be ignored */
165    BOOL                        maskRoamingEvents;
166    /* TS to filter Too many low Quality roaming triggers */
167    UINT32                      lowQualityTriggerTimestamp;
168    /* the scan type performed for Roaming */
169    scan4RoamingType_e          scanType;
170    /* list of BSS received from Scan Manager */
171    bssList_t                   *pListOfAPs;
172    /* Indicating if Neighbor APs exist */
173    BOOL                        neighborApsExist;
174    /* a list of the candiadte APs indexes in pListOfAPs according to
175        neighbor APs, pre-auth APs and other APs */
176    listOfCandidateAps_t        listOfCandidateAps;
177    /* The current candidate AP's index to Roam to */
178    UINT8                       candidateApIndex;
179    /* Indicates whether at least one handover was performed */
180    BOOL                        handoverWasPerformed;
181    /* The station capabilities for the current Connection */
182    apConn_staCapabilities_t    staCapabilities;
183
184    /* Roaming manager SM */
185    fsm_stateMachine_t          *pRoamingSm;
186
187    /* Roaming manager handles to other objects */
188    TI_HANDLE                   hReport;
189    TI_HANDLE                   hOs;
190    TI_HANDLE                   hScanMngr;
191    TI_HANDLE                   hAPConnection;
192
193#ifdef TI_DBG
194
195    /* Debug trace for Roaming statistics */
196    UINT32                      roamingTriggerEvents[MAX_ROAMING_TRIGGERS];
197    UINT32                      roamingHandoverEvents[MAX_ROAMING_TRIGGERS];
198    UINT32                      roamingSuccesfulHandoverNum;
199    UINT32                      roamingFailedHandoverNum;
200    UINT32                      roamingTriggerTimestamp;
201    UINT32                      roamingHandoverStartedTimestamp;
202    UINT32                      roamingHandoverCompletedTimestamp;
203    UINT32                      roamingAverageSuccHandoverDuration;
204    UINT32                      roamingAverageRoamingDuration;
205#endif
206
207};
208
209/* External data definitions */
210
211/* Local functions definitions */
212
213/* Global variables */
214
215#ifdef REPORT_LOG
216
217static char *roamingMngr_stateDesc[ROAMING_MNGR_NUM_STATES] = {
218        "STATE_IDLE",
219        "STATE_WAIT_4_TRIGGER",
220        "STATE_WAIT_4_CMD",
221        "STATE_SCANNING",
222        "STATE_SELECTING",
223        "CONNECTING"
224    };
225
226static char *roamingMngr_eventDesc[ROAMING_MNGR_NUM_EVENTS] = {
227        "EVENT_START",
228        "EVENT_STOP",
229        "EVENT_ROAM_TRIGGER",
230        "EVENT_SCAN",
231        "EVENT_SELECT",
232        "EVENT_REQ_HANDOVER",
233        "EVENT_ROAM_SUCCESS",
234        "EVENT_FAILURE"
235    };
236
237#endif
238
239/* Function prototypes */
240/* SM functions */
241static TI_STATUS roamingMngr_smEvent(UINT8 *currState, UINT8 event, void* data);
242static TI_STATUS roamingMngr_smUnexpected(void *pData);
243static TI_STATUS roamingMngr_smNop(void *pData);
244static TI_STATUS roamingMngr_smStartIdle(void *pData);
245static TI_STATUS roamingMngr_smStop(void *pData);
246static TI_STATUS roamingMngr_smStopWhileScanning(void *pData);
247static TI_STATUS roamingMngr_smRoamTrigger(TI_HANDLE hRoamingMngr);
248static TI_STATUS roamingMngr_smInvokeScan(TI_HANDLE hRoamingMngr);
249static TI_STATUS roamingMngr_smSelection(TI_HANDLE hRoamingMngr);
250static TI_STATUS roamingMngr_smHandover(TI_HANDLE hRoamingMngr);
251static TI_STATUS roamingMngr_smSuccHandover(TI_HANDLE hRoamingMngr);
252static TI_STATUS roamingMngr_smFailHandover(TI_HANDLE hRoamingMngr);
253static TI_STATUS roamingMngr_smScanFailure(TI_HANDLE hRoamingMngr);
254static TI_STATUS roamingMngr_smDisconnectWhileConnecting(TI_HANDLE hRoamingMngr);
255
256
257
258/************** callback funtions called by AP Connection **************/
259/* called when a trigger for Roaming occurs */
260TI_STATUS roamingMngr_triggerRoamingCb(TI_HANDLE hRoamingMngr, void *pData);
261/* called when CONN status event occurs */
262TI_STATUS roamingMngr_connStatusCb(TI_HANDLE hRoamingMngr, void *pData);
263/* called when Neighbor APs is updated */
264TI_STATUS roamingMngr_updateNeighborApListCb(TI_HANDLE hRoamingMngr, void *pData);
265
266/* internal functions */
267static void roamingMngr_releaseModule(roamingMngr_t *pRoamingMngr, UINT32 initVec);
268
269#ifdef TI_DBG
270/* debug function */
271static void roamingMngr_printStatistics(TI_HANDLE hRoamingMngr);
272static void roamingMngr_resetStatistics(TI_HANDLE hRoamingMngr);
273#endif
274
275
276/**
277*
278* roamingMngr_create
279*
280* \b Description:
281*
282* Create the Roaming Manager context.
283*
284* \b ARGS:
285*
286*  I   - hOs - OS handler  \n
287*
288* \b RETURNS:
289*
290*  OK on success, NOK on failure.
291*
292* \sa
293*/
294TI_HANDLE roamingMngr_create(TI_HANDLE hOs)
295{
296    TI_STATUS       status;
297    roamingMngr_t   *pRoamingMngr;
298    UINT32          initVec;
299
300    initVec = 0;
301
302    pRoamingMngr = os_memoryAlloc(hOs, sizeof(roamingMngr_t));
303    if (pRoamingMngr == NULL)
304        return NULL;
305
306    initVec |= (1 << ROAMING_MNGR_CONTEXT_INIT_BIT);
307    pRoamingMngr->hOs   = hOs;
308
309    status = fsm_Create(hOs, &pRoamingMngr->pRoamingSm, ROAMING_MNGR_NUM_STATES, ROAMING_MNGR_NUM_EVENTS);
310    if (status != OK)
311    {
312        roamingMngr_releaseModule(pRoamingMngr, initVec);
313        WLAN_OS_REPORT(("FATAL ERROR: roamingMngr_create(): Error Creating pRoamingSm - Aborting\n"));
314        return NULL;
315    }
316    initVec |= (1 << ROAMING_MNGR_SM_INIT_BIT);
317
318
319    return pRoamingMngr;
320}
321
322/**
323*
324* roamingMngr_releaseModule
325*
326* \b Description:
327*
328* Called by the un load function
329* Go over the vector, for each bit that is set, release the corresponding module.
330*
331* \b ARGS:
332*
333*  I   - pRoamingMngr - Roaming Manager context  \n
334*  I   - initVec - indicates which modules should be released
335*
336* \b RETURNS:
337*
338*  OK if successful, NOK otherwise.
339*
340* \sa roamingMngr_create
341*/
342static void roamingMngr_releaseModule(roamingMngr_t *pRoamingMngr, UINT32 initVec)
343{
344
345    if (pRoamingMngr==NULL)
346    {
347        return;
348    }
349    if (initVec & (1 << ROAMING_MNGR_SM_INIT_BIT))
350    {
351        fsm_Unload(pRoamingMngr->hOs, pRoamingMngr->pRoamingSm);
352    }
353
354    if (initVec & (1 << ROAMING_MNGR_CONTEXT_INIT_BIT))
355    {
356        utils_nullMemoryFree(pRoamingMngr->hOs, pRoamingMngr, sizeof(roamingMngr_t));
357    }
358
359    initVec = 0;
360}
361
362
363/**
364*
365* roamingMngr_unload
366*
367* \b Description:
368*
369* Unload Roaming Manager module from memory
370*
371* \b ARGS:
372*
373*  I   - hAdmCtrl - Roaming Manager context  \n
374*
375* \b RETURNS:
376*
377*  OK if successful, NOK otherwise.
378*
379* \sa roamingMngr_create
380*/
381TI_STATUS roamingMngr_unload(TI_HANDLE hRoamingMngr)
382{
383    UINT32          initVec;
384
385    if (hRoamingMngr == NULL)
386    {
387        return OK;
388    }
389
390    initVec = 0xFFFF;
391    roamingMngr_releaseModule(hRoamingMngr, initVec);
392
393    return OK;
394}
395
396/**
397*
398* roamingMngr_config
399*
400* \b Description:
401*
402* Configure the Roaming Manager module.
403*
404* \b ARGS:
405*
406*  I   - hRoamingMngr - Roaming Manager context  \n
407*  I   - hReport - Report context  \n
408*  I   - hOs - OS context  \n
409*  I   - hSiteMgr - Site Manager context  \n
410*  I   - hSmeSm - SME context  \n
411*  I   - hCtrlData - Control Data context  \n
412*  I   - hPowerMgr - Power Manager context  \n
413*  I   - pRoamingParams - init roaming parameters read from the registry  \n
414*
415* \b RETURNS:
416*
417*  OK on success, NOK on failure.
418*
419* \sa
420*/
421
422TI_STATUS roamingMngr_init(TI_HANDLE hRoamingMngr,
423                      TI_HANDLE hReport,
424                      TI_HANDLE hScanMngr,
425                      TI_HANDLE hAPConnection)
426{
427    roamingMngr_t           *pRoamingMngr;
428    TI_STATUS               status;
429#ifdef ENABLE_ROAMING_BY_DEFAULT
430    roamingMngrConfigParams_t InitRoamingParams;
431    paramInfo_t             param;
432#endif
433#ifdef TI_DBG
434    UINT8                   index;
435#endif
436
437    /** Station broadcast key State Machine matrix */
438    fsm_actionCell_t    roamingMngr_matrix[ROAMING_MNGR_NUM_STATES][ROAMING_MNGR_NUM_EVENTS] =
439    {
440        /* next state and actions for IDLE state */
441        {   {ROAMING_STATE_WAIT_4_TRIGGER, roamingMngr_smStartIdle},        /* START            */
442            {ROAMING_STATE_IDLE, roamingMngr_smNop},                        /* STOP             */
443            {ROAMING_STATE_IDLE, roamingMngr_smNop},                        /* ROAM_TRIGGER     */
444            {ROAMING_STATE_IDLE, roamingMngr_smUnexpected},                 /* SCAN             */
445            {ROAMING_STATE_IDLE, roamingMngr_smUnexpected},                 /* SELECT           */
446            {ROAMING_STATE_IDLE, roamingMngr_smUnexpected},                 /* REQ_HANDOVER     */
447            {ROAMING_STATE_IDLE, roamingMngr_smUnexpected},                 /* ROAM_SUCCESS     */
448            {ROAMING_STATE_IDLE, roamingMngr_smUnexpected}                  /* FAILURE          */
449        },
450
451        /* next state and actions for WAIT_4_TRIGGER state */
452        {   {ROAMING_STATE_WAIT_4_TRIGGER, roamingMngr_smUnexpected},   /* START            */
453            {ROAMING_STATE_IDLE, roamingMngr_smStop},                   /* STOP             */
454            {ROAMING_STATE_WAIT_4_CMD, roamingMngr_smRoamTrigger},      /* ROAM_TRIGGER     */
455            {ROAMING_STATE_WAIT_4_TRIGGER, roamingMngr_smUnexpected},   /* SCAN             */
456            {ROAMING_STATE_WAIT_4_TRIGGER, roamingMngr_smUnexpected},   /* SELECT           */
457            {ROAMING_STATE_WAIT_4_TRIGGER, roamingMngr_smUnexpected},   /* REQ_HANDOVER     */
458            {ROAMING_STATE_WAIT_4_TRIGGER, roamingMngr_smUnexpected},   /* ROAM_SUCCESS     */
459            {ROAMING_STATE_WAIT_4_TRIGGER, roamingMngr_smUnexpected}    /* FAILURE          */
460        },
461
462        /* next state and actions for WAIT_4_CMD state */
463        {   {ROAMING_STATE_WAIT_4_CMD, roamingMngr_smUnexpected},               /* START            */
464            {ROAMING_STATE_WAIT_4_CMD, roamingMngr_smUnexpected},               /* STOP             */
465            {ROAMING_STATE_WAIT_4_CMD, roamingMngr_smUnexpected},               /* ROAM_TRIGGER     */
466            {ROAMING_STATE_SCANNING, roamingMngr_smInvokeScan},                 /* SCAN             */
467            {ROAMING_STATE_SELECTING, roamingMngr_smSelection},                 /* SELECT           */
468            {ROAMING_STATE_WAIT_4_CMD, roamingMngr_smUnexpected},               /* REQ_HANDOVER     */
469            {ROAMING_STATE_WAIT_4_CMD, roamingMngr_smUnexpected},               /* ROAM_SUCCESS     */
470            {ROAMING_STATE_WAIT_4_CMD, roamingMngr_smUnexpected}                /* FAILURE          */
471        },
472
473        /* next state and actions for SCANNING state */
474        {   {ROAMING_STATE_SCANNING, roamingMngr_smUnexpected},              /* START            */
475            {ROAMING_STATE_IDLE, roamingMngr_smStopWhileScanning},           /* STOP             */
476            {ROAMING_STATE_SCANNING, roamingMngr_smNop},                     /* ROAM_TRIGGER     */
477            {ROAMING_STATE_SCANNING, roamingMngr_smInvokeScan},              /* SCAN             */
478            {ROAMING_STATE_SELECTING, roamingMngr_smSelection},              /* SELECT           */
479            {ROAMING_STATE_SCANNING, roamingMngr_smUnexpected},              /* REQ_HANDOVER     */
480            {ROAMING_STATE_SCANNING, roamingMngr_smUnexpected},              /* ROAM_SUCCESS     */
481            {ROAMING_STATE_IDLE, roamingMngr_smScanFailure}                  /* FAILURE          */
482
483        },
484
485        /* next state and actions for SELECTING state */
486        {   {ROAMING_STATE_SELECTING, roamingMngr_smUnexpected},             /* START            */
487            {ROAMING_STATE_SELECTING, roamingMngr_smUnexpected},             /* STOP             */
488            {ROAMING_STATE_SELECTING, roamingMngr_smUnexpected},             /* ROAM_TRIGGER     */
489            {ROAMING_STATE_SELECTING, roamingMngr_smUnexpected},             /* SCAN             */
490            {ROAMING_STATE_SELECTING, roamingMngr_smUnexpected},             /* SELECT           */
491            {ROAMING_STATE_CONNECTING, roamingMngr_smHandover},              /* REQ_HANDOVER     */
492            {ROAMING_STATE_SELECTING, roamingMngr_smUnexpected},             /* ROAM_SUCCESS     */
493            {ROAMING_STATE_SELECTING, roamingMngr_smUnexpected}              /* FAILURE          */
494
495        },
496
497        /* next state and actions for CONNECTING state */
498        {   {ROAMING_STATE_CONNECTING, roamingMngr_smUnexpected},           /* START            */
499            {ROAMING_STATE_IDLE, roamingMngr_smStop},                       /* STOP             */
500            {ROAMING_STATE_IDLE, roamingMngr_smDisconnectWhileConnecting},      /* ROAM_TRIGGER     */
501            {ROAMING_STATE_CONNECTING, roamingMngr_smUnexpected},           /* SCAN,            */
502            {ROAMING_STATE_CONNECTING, roamingMngr_smUnexpected},           /* SELECT           */
503            {ROAMING_STATE_CONNECTING, roamingMngr_smHandover},             /* REQ_HANDOVER     */
504            {ROAMING_STATE_WAIT_4_TRIGGER, roamingMngr_smSuccHandover} ,    /* ROAM_SUCCESS     */
505            {ROAMING_STATE_IDLE, roamingMngr_smFailHandover}                /* FAILURE          */
506
507        }
508
509
510
511    };
512
513    if (hRoamingMngr == NULL)
514    {
515        return NOK;
516    }
517
518    pRoamingMngr = (roamingMngr_t*)hRoamingMngr;
519
520    /* Update handlers */
521    pRoamingMngr->hReport   = hReport;
522    pRoamingMngr->hScanMngr = hScanMngr;
523    pRoamingMngr->hAPConnection = hAPConnection;
524
525    /* Init intrenal variables */
526    pRoamingMngr->currentState = ROAMING_STATE_IDLE;
527    pRoamingMngr->roamingMngrConfig.enableDisable = ROAMING_DISABLED;
528    pRoamingMngr->roamingTrigger = ROAMING_TRIGGER_NONE;
529    pRoamingMngr->maskRoamingEvents= TRUE;
530    pRoamingMngr->scanType = ROAMING_NO_SCAN;
531    pRoamingMngr->candidateApIndex = INVALID_CANDIDATE_INDEX;
532    pRoamingMngr->handoverWasPerformed = FALSE;
533    pRoamingMngr->lowQualityTriggerTimestamp = 0;
534    pRoamingMngr->neighborApsExist = FALSE;
535    pRoamingMngr->pListOfAPs = NULL;
536    pRoamingMngr->candidateApIndex = INVALID_CANDIDATE_INDEX;
537    pRoamingMngr->listOfCandidateAps.numOfNeighborBSS = 0;
538    pRoamingMngr->listOfCandidateAps.numOfPreAuthBSS = 0;
539    pRoamingMngr->listOfCandidateAps.numOfRegularBSS = 0;
540
541#ifdef TI_DBG
542    /* debug counters */
543    pRoamingMngr->roamingSuccesfulHandoverNum = 0;
544    pRoamingMngr->roamingHandoverStartedTimestamp = 0;
545    pRoamingMngr->roamingHandoverCompletedTimestamp = 0;
546    pRoamingMngr->roamingAverageSuccHandoverDuration = 0;
547    pRoamingMngr->roamingAverageRoamingDuration = 0;
548    pRoamingMngr->roamingFailedHandoverNum = 0;
549
550    for (index=ROAMING_TRIGGER_NONE; index<ROAMING_TRIGGER_LAST; index++)
551    {
552        pRoamingMngr->roamingTriggerEvents[index] = 0;
553        pRoamingMngr->roamingHandoverEvents[index] = 0;
554    }
555#endif
556
557    /* config the FSM */
558    status = fsm_Config(pRoamingMngr->pRoamingSm,
559                        &roamingMngr_matrix[0][0],
560                        ROAMING_MNGR_NUM_STATES,
561                        ROAMING_MNGR_NUM_EVENTS,
562                        roamingMngr_smEvent, pRoamingMngr->hOs);
563#ifdef ENABLE_ROAMING_BY_DEFAULT
564	if (status != OK)
565	{
566		return status;
567	}
568
569	param.paramType = ROAMING_MNGR_APPLICATION_CONFIGURATION;
570	param.content.applicationConfigBuffer.bufferSize = sizeof(roamingMngrConfigParams_t);
571	param.content.applicationConfigBuffer.buffer = (UINT8 *)&param;
572	InitRoamingParams.roamingMngrConfig.enableDisable =  ROAMING_ENABLED;
573
574	InitRoamingParams.roamingMngrConfig.lowPassFilterRoamingAttempt = 30;
575	InitRoamingParams.roamingMngrConfig.apQualityThreshold = -70;
576
577	InitRoamingParams.roamingMngrThresholdsConfig.dataRetryThreshold = 20;
578	InitRoamingParams.roamingMngrThresholdsConfig.numExpectedTbttForBSSLoss = 10;
579	InitRoamingParams.roamingMngrThresholdsConfig.txRateThreshold = 2;
580	InitRoamingParams.roamingMngrThresholdsConfig.lowRssiThreshold = -80;
581	InitRoamingParams.roamingMngrThresholdsConfig.lowSnrThreshold = 0;
582	InitRoamingParams.roamingMngrThresholdsConfig.lowQualityForBackgroungScanCondition = -60;
583	InitRoamingParams.roamingMngrThresholdsConfig.normalQualityForBackgroungScanCondition = -50;
584	InitRoamingParams.roamingMngrThresholdsConfig.rssiFilterWeight = 10;
585	InitRoamingParams.roamingMngrThresholdsConfig.snrFilterWeight  = 10;
586
587	param.paramType = ROAMING_MNGR_APPLICATION_CONFIGURATION;
588	param.content.applicationConfigBuffer.bufferSize = sizeof(roamingMngrConfigParams_t);
589	param.content.applicationConfigBuffer.buffer = (UINT8 *)&InitRoamingParams;
590
591	roamingMngr_setParam (hRoamingMngr,&param);
592#endif
593    return status;
594}
595
596/* For debug */
597extern TI_STATUS apConn_reportRoamingEvent(TI_HANDLE hAPConnection,apConn_roamingTrigger_e roamingEventType,void *pRoamingEventData);
598
599/**
600*
601* roamingMngr_setParam - Set a specific parameter to the roamingMngr SM
602*
603* \b Description:
604*
605* Set a specific parameter to the roamingMngr SM.
606*
607* \b ARGS:
608*
609*  I   - hRoamingMngr - roamingMngr SM context  \n
610*  I/O - pParam - Parameter \n
611*
612* \b RETURNS:
613*
614*  OK if successful, NOK otherwise.
615*
616*
617*/
618TI_STATUS roamingMngr_setParam(TI_HANDLE hRoamingMngr, paramInfo_t *pParam)
619{
620    roamingMngr_t       *pRoamingMngr;
621    TI_STATUS           status=OK;
622
623    pRoamingMngr = (roamingMngr_t*)hRoamingMngr;
624
625    if ((hRoamingMngr == NULL) || (pParam == NULL))
626    {
627        return NOK;
628    }
629    WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
630                          ("roamingMngr_setParam   %X \n",
631                          pParam->paramType));
632
633
634    switch (pParam->paramType)
635    {
636
637    case ROAMING_MNGR_APPLICATION_CONFIGURATION:
638        {
639            roamingMngrConfigParams_t   *pRoamingMngrConfigParams;
640
641            if (pParam->content.applicationConfigBuffer.bufferSize < sizeof(roamingMngrConfigParams_t))
642            {
643                WLAN_REPORT_ERROR(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
644                                      ("roamingMngr_setParam bad  size = %d \n",
645                                      pParam->content.applicationConfigBuffer.bufferSize));
646                return NOK;
647            }
648
649            pRoamingMngrConfigParams = (roamingMngrConfigParams_t*)pParam->content.applicationConfigBuffer.buffer;
650
651            /* Configure the Roaming Parmeters */
652            WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,("roamingMngr_setParam Configuration: \n \
653                                   enableDisable= %d,\n  lowPassFilterRoamingAttempt=%d,\n \
654                                   apQualityThreshold=%d\n",
655                                   pRoamingMngrConfigParams->roamingMngrConfig.enableDisable,
656                                   pRoamingMngrConfigParams->roamingMngrConfig.lowPassFilterRoamingAttempt,
657                                   pRoamingMngrConfigParams->roamingMngrConfig.apQualityThreshold));
658
659            pRoamingMngr->roamingMngrConfig.apQualityThreshold = pRoamingMngrConfigParams->roamingMngrConfig.apQualityThreshold;
660            pRoamingMngr->roamingMngrConfig.lowPassFilterRoamingAttempt = pRoamingMngrConfigParams->roamingMngrConfig.lowPassFilterRoamingAttempt;
661            pRoamingMngr->lowPassFilterRoamingAttemptInMsec = pRoamingMngrConfigParams->roamingMngrConfig.lowPassFilterRoamingAttempt * 1000;
662
663            /* Configure the Roaming Trigger thresholds */
664            WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,("roamingMngr_setParam Thresholds: \n \
665                                   dataRetryThreshold= %d,\n  lowQualityForBackgroungScanCondition=%d,\n \
666                                   lowRssiThreshold=%d,\n lowSNRThreshold=%d,\n \
667                                   normalQualityForBackgroungScanCondition=%d,\n \
668                                   numExpectedTbttForBSSLoss=%d,\n txRateThreshold=%d \n \n",
669                                   pRoamingMngrConfigParams->roamingMngrThresholdsConfig.dataRetryThreshold,
670                                   pRoamingMngrConfigParams->roamingMngrThresholdsConfig.lowQualityForBackgroungScanCondition,
671                                   pRoamingMngrConfigParams->roamingMngrThresholdsConfig.lowRssiThreshold,
672                                   pRoamingMngrConfigParams->roamingMngrThresholdsConfig.lowSnrThreshold,                                  pRoamingMngrConfigParams->roamingMngrThresholdsConfig.normalQualityForBackgroungScanCondition,
673                                   pRoamingMngrConfigParams->roamingMngrThresholdsConfig.numExpectedTbttForBSSLoss,
674                                   pRoamingMngrConfigParams->roamingMngrThresholdsConfig.txRateThreshold));
675
676            os_memoryCopy(pRoamingMngr->hOs, &pRoamingMngr->roamingMngrThresholdsConfig, &pRoamingMngrConfigParams->roamingMngrThresholdsConfig, sizeof(roamingMngrThresholdsConfig_t));
677
678            status = apConn_setRoamThresholds(pRoamingMngr->hAPConnection, &pRoamingMngrConfigParams->roamingMngrThresholdsConfig);
679
680            if (pRoamingMngr->roamingMngrConfig.enableDisable &&
681                !pRoamingMngrConfigParams->roamingMngrConfig.enableDisable)
682            {   /* disable Roaming Manager */
683                apConn_unregisterRoamMngrCallb(pRoamingMngr->hAPConnection);
684                pRoamingMngr->roamingMngrConfig.enableDisable = ROAMING_DISABLED;
685                return (roamingMngr_smEvent((UINT8*)&pRoamingMngr->currentState, ROAMING_EVENT_STOP, pRoamingMngr));
686            }
687            else if (!pRoamingMngr->roamingMngrConfig.enableDisable &&
688                pRoamingMngrConfigParams->roamingMngrConfig.enableDisable)
689            {   /* enable Roaming Manager */
690                /* Save the Roaming Configuration parameters */
691                pRoamingMngr->roamingMngrConfig.enableDisable = pRoamingMngrConfigParams->roamingMngrConfig.enableDisable;
692                /* register Roaming callback */
693                apConn_registerRoamMngrCallb(pRoamingMngr->hAPConnection,
694                                             roamingMngr_triggerRoamingCb,
695                                             roamingMngr_connStatusCb,
696                                             roamingMngr_updateNeighborApListCb);
697            }
698        }
699        break;
700
701    /*********** For Debug Purposes ***********/
702
703    case ROAMING_MNGR_TRIGGER_EVENT:
704        /* Enable/disable Internal Roaming */
705        WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
706                              ("roamingMngr_setParam TRIGGER_EVENT=  %d \n",
707                              pParam->content.roamingTriggerType));
708
709		if ((apConn_roamingTrigger_e)pParam->content.roamingTriggerType == ROAMING_TRIGGER_AP_DISCONNECT)
710        {
711			/* DeAuth packet with status code of deauth/disassoc packet equal to  1 */
712			apConn_reportRoamingEventDisconnect(pRoamingMngr->hAPConnection ,1 ,TRUE);
713        }
714        else
715        {
716			apConn_reportRoamingEvent(pRoamingMngr->hAPConnection, (apConn_roamingTrigger_e)pParam->content.roamingTriggerType, NULL);
717        }
718        break;
719
720    case ROAMING_MNGR_CONN_STATUS:
721        /* External request to connect to BBSID */
722        WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
723                              ("roamingMngr_setParam CONN_STATUS=  %d \n",
724                               pParam->content.roamingConnStatus));
725        roamingMngr_connStatusCb(pRoamingMngr, &pParam->content.roamingConnStatus);
726        break;
727
728    default:
729        WLAN_REPORT_ERROR(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
730                              ("roamingMngr_setParam bad param=  %X\n",
731                              pParam->paramType));
732
733        break;
734    }
735
736
737    return status;
738}
739
740/**
741*
742* roamingMngr_getParam - Get a specific parameter from the roamingMngr SM
743*
744* \b Description:
745*
746* Get a specific parameter from the roamingMngr SM.
747*
748* \b ARGS:
749*
750*  I   - hRoamingMngr - roamingMngr SM context  \n
751*  I/O - pParam - Parameter \n
752*
753* \b RETURNS:
754*
755*  OK if successful, NOK otherwise.
756*
757*
758*/
759TI_STATUS roamingMngr_getParam(TI_HANDLE hRoamingMngr, paramInfo_t *pParam)
760{
761    roamingMngr_t       *pRoamingMngr;
762
763    pRoamingMngr = (roamingMngr_t*)hRoamingMngr;
764
765    if ((hRoamingMngr == NULL) || (pParam == NULL))
766    {
767        return NOK;
768    }
769
770    WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
771                          ("roamingMngr_getParam   %X \n",
772                          pParam->paramType));
773
774    switch (pParam->paramType)
775    {
776    case ROAMING_MNGR_APPLICATION_CONFIGURATION:
777        {
778            roamingMngrConfigParams_t   *pRoamingMngrConfigParams;
779
780            pRoamingMngrConfigParams = (roamingMngrConfigParams_t *)&pParam->content.roamingConfigBuffer;
781
782            if (pRoamingMngr->roamingMngrConfig.enableDisable == ROAMING_DISABLED)
783            {
784                pRoamingMngrConfigParams->roamingMngrConfig.enableDisable = FALSE;
785            }
786            else
787            {
788                pRoamingMngrConfigParams->roamingMngrConfig.enableDisable = TRUE;
789            }
790            pRoamingMngrConfigParams->roamingMngrConfig.apQualityThreshold = pRoamingMngr->roamingMngrConfig.apQualityThreshold;
791            pRoamingMngrConfigParams->roamingMngrConfig.lowPassFilterRoamingAttempt = pRoamingMngr->roamingMngrConfig.lowPassFilterRoamingAttempt;
792
793            apConn_getRoamThresholds(pRoamingMngr->hAPConnection, &pRoamingMngr->roamingMngrThresholdsConfig);
794            os_memoryCopy(pRoamingMngr->hOs, &pRoamingMngrConfigParams->roamingMngrThresholdsConfig, &pRoamingMngr->roamingMngrThresholdsConfig, sizeof(roamingMngrThresholdsConfig_t));
795            pParam->paramLength = sizeof(roamingMngrConfigParams_t);
796        }
797        break;
798
799    case ROAMING_MNGR_CONF_PARAM:
800        WLAN_OS_REPORT(("Roaming is: %s \n", pRoamingMngr->roamingMngrConfig.enableDisable ? "Enabled" : "Disabled"));
801        WLAN_OS_REPORT(("lowPassFilterRoamingAttempt = %d msec, apQualityThreshold = %d\n",
802               pRoamingMngr->roamingMngrConfig.lowPassFilterRoamingAttempt,
803               pRoamingMngr->roamingMngrConfig.apQualityThreshold));
804        break;
805#ifdef TI_DBG
806    case ROAMING_MNGR_PRINT_STATISTICS:
807        roamingMngr_printStatistics(pRoamingMngr);
808        break;
809
810    case ROAMING_MNGR_RESET_STATISTICS:
811        roamingMngr_resetStatistics(pRoamingMngr);
812        break;
813
814    case ROAMING_MNGR_PRINT_CURRENT_STATUS:
815        WLAN_OS_REPORT(("Roaming Current State = %s, enableDisable=%d\n, maskRoamingEvents = %d, roamingTrigger=%d \n scanType=%d, handoverWasPerformed=%d \n, candidateApIndex=%d, lowQualityTriggerTimestamp=%d \n",
816                        roamingMngr_stateDesc[pRoamingMngr->currentState],
817                        pRoamingMngr->roamingMngrConfig.enableDisable,
818                        pRoamingMngr->maskRoamingEvents,
819                        pRoamingMngr->roamingTrigger,
820                        pRoamingMngr->scanType,
821                        pRoamingMngr->handoverWasPerformed,
822                        pRoamingMngr->candidateApIndex,
823                        pRoamingMngr->lowQualityTriggerTimestamp));
824        break;
825    case ROAMING_MNGR_PRINT_CANDIDATE_TABLE:
826        {
827            UINT32      index;
828
829            if (pRoamingMngr->pListOfAPs==NULL)
830            {
831                WLAN_REPORT_INFORMATION( pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
832                                         ("Roaming Mngr the candidate AP list is invalid \n") );
833                break;
834            }
835            WLAN_REPORT_INFORMATION( pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
836                                     ("The number of candidates is %d\n",
837                                      pRoamingMngr->pListOfAPs->numOfEntries) );
838
839            WLAN_REPORT_INFORMATION( pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
840                                     ("Roaming Mngr Neighbor AP list, num of candidates = %d\n",
841                                      pRoamingMngr->listOfCandidateAps.numOfNeighborBSS) );
842
843            for (index=0; index<pRoamingMngr->listOfCandidateAps.numOfNeighborBSS; index++)
844            {
845                UINT32  candidateIndex;
846                bssEntry_t  *pBssEntry;
847
848                candidateIndex = pRoamingMngr->listOfCandidateAps.neighborBSSList[index];
849                pBssEntry = &pRoamingMngr->pListOfAPs->BSSList[candidateIndex];
850                WLAN_REPORT_INFORMATION( pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
851                                         ("candiate %d, BSSID=%x-%x-%x-%x-%x-%x, RSSI =%d \n",
852                                          candidateIndex, pBssEntry->BSSID.addr[0],
853                                          pBssEntry->BSSID.addr[1], pBssEntry->BSSID.addr[2],
854                                          pBssEntry->BSSID.addr[3], pBssEntry->BSSID.addr[4],
855                                          pBssEntry->BSSID.addr[5], pBssEntry->RSSI) );
856            }
857            WLAN_REPORT_INFORMATION( pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
858                                     ("Roaming Mngr Pre-Auth AP list, num of candidates = %d\n",
859                                      pRoamingMngr->listOfCandidateAps.numOfPreAuthBSS) );
860
861            for (index=0; index<pRoamingMngr->listOfCandidateAps.numOfPreAuthBSS; index++)
862            {
863                UINT32  candidateIndex;
864                bssEntry_t  *pBssEntry;
865
866                candidateIndex = pRoamingMngr->listOfCandidateAps.preAuthBSSList[index];
867                pBssEntry = &pRoamingMngr->pListOfAPs->BSSList[candidateIndex];
868                WLAN_REPORT_INFORMATION( pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
869                                         ("candiate %d, BSSID=%x-%x-%x-%x-%x-%x, RSSI =%d \n",
870                                          candidateIndex, pBssEntry->BSSID.addr[0],
871                                          pBssEntry->BSSID.addr[1], pBssEntry->BSSID.addr[2],
872                                          pBssEntry->BSSID.addr[3], pBssEntry->BSSID.addr[4],
873                                          pBssEntry->BSSID.addr[5], pBssEntry->RSSI) );
874            }
875            WLAN_REPORT_INFORMATION( pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
876                                     ("Roaming Mngr Regular AP list, num of candidates = %d\n",
877                                      pRoamingMngr->listOfCandidateAps.numOfRegularBSS) );
878
879            for (index=0; index<pRoamingMngr->listOfCandidateAps.numOfRegularBSS; index++)
880            {
881                UINT32  candidateIndex;
882                bssEntry_t  *pBssEntry;
883
884                candidateIndex = pRoamingMngr->listOfCandidateAps.regularBSSList[index];
885                pBssEntry = &pRoamingMngr->pListOfAPs->BSSList[candidateIndex];
886                WLAN_REPORT_INFORMATION( pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
887                                         ("candiate %d, BSSID=%x-%x-%x-%x-%x-%x, RSSI =%d \n",
888                                          candidateIndex, pBssEntry->BSSID.addr[0],
889                                          pBssEntry->BSSID.addr[1], pBssEntry->BSSID.addr[2],
890                                          pBssEntry->BSSID.addr[3], pBssEntry->BSSID.addr[4],
891                                          pBssEntry->BSSID.addr[5], pBssEntry->RSSI) );
892            }
893        }
894        break;
895
896#endif /*TI_DBG*/
897
898    default:
899        WLAN_REPORT_ERROR(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
900                              ("roamingMngr_getParam  bad paramType= %X \n",
901                              pParam->paramType));
902        return NOK;
903    }
904
905    return OK;
906}
907
908
909/**
910*
911* roamingMngr_triggerRoamingCb
912*
913* \b Description:
914*
915* This procedure is called when Roaming should be triggered
916 * due to one of apConn_roamingTrigger_e Roaming Reasons.
917 * Save the trigger and process it only if there's no other Roaming trigger
918 * in process.
919*
920* \b ARGS:
921*
922*  I   - hRoamingMngr - roamingMngr SM context  \n
923*  I   - pData - pointer to roaming trigger
924*
925* \b RETURNS:
926*
927*  OK if successful, NOK otherwise.
928*
929*
930*/
931TI_STATUS roamingMngr_triggerRoamingCb(TI_HANDLE hRoamingMngr, void *pData)
932{
933    roamingMngr_t       *pRoamingMngr;
934    apConn_roamingTrigger_e     roamingTrigger;
935    UINT32                      curTimestamp;
936
937    pRoamingMngr = (roamingMngr_t*)hRoamingMngr;
938    if ((pRoamingMngr == NULL) || (pData == NULL))
939    {
940        return NOK;
941    }
942
943    roamingTrigger = *(apConn_roamingTrigger_e *)pData;
944
945    if (roamingTrigger >= ROAMING_TRIGGER_LAST)
946    {
947        WLAN_REPORT_ERROR(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
948                          ("roamingMngr_triggerRoamingCb, bad roaming trigger = %d\n", roamingTrigger));
949        return NOK;
950    }
951#ifdef TI_DBG
952    /* save parameters for debug*/
953    pRoamingMngr->roamingTriggerEvents[pRoamingMngr->roamingTrigger]++;
954#endif
955    if (roamingTrigger <= ROAMING_TRIGGER_BG_SCAN_GROUP)
956    {
957        BOOL    lowQuality = FALSE;
958        if (roamingTrigger == ROAMING_TRIGGER_LOW_QUALITY_FOR_BG_SCAN)
959        {
960            lowQuality = TRUE;
961        }
962        WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
963                      ("roamingMngr_triggerRoamingCb, lowQuality = %d \n",
964                       lowQuality));
965        scanMngr_qualityChangeTrigger(pRoamingMngr->hScanMngr, lowQuality);
966    }
967    else
968    {
969        if (roamingTrigger > pRoamingMngr->roamingTrigger)
970        {   /* Save the highest priority roaming trigger */
971            pRoamingMngr->roamingTrigger = roamingTrigger;
972            WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
973                          ("roamingMngr_triggerRoamingCb, higher trigger = %d \n",
974                           roamingTrigger));
975
976        }
977
978        curTimestamp = os_timeStampMs(pRoamingMngr->hOs);
979
980        /* If "No BSS" trigger received, disable count of low pass filter timer */
981        if (roamingTrigger > ROAMING_TRIGGER_LOW_QUALITY_GROUP)
982        {
983            pRoamingMngr->lowQualityTriggerTimestamp = 0;
984        }
985
986        /* Do not invoke a new Roaming Trigger when a previous one is in process */
987        if (pRoamingMngr->maskRoamingEvents == FALSE)
988        {   /* No Roaming trigger is in process */
989            /* If the trigger is low quality check the low pass filter */
990            WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
991                      ("roamingMngr_triggerRoamingCb, trigger = %d \n",
992                       roamingTrigger));
993            if (roamingTrigger <= ROAMING_TRIGGER_LOW_QUALITY_GROUP)
994            {
995                UINT32 deltaTs = curTimestamp-pRoamingMngr->lowQualityTriggerTimestamp;
996
997                if ((pRoamingMngr->lowQualityTriggerTimestamp != 0) &&
998                    (deltaTs < pRoamingMngr->lowPassFilterRoamingAttemptInMsec))
999                {  /* Ignore the low quality events. till the low pass time elapses */
1000                    WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
1001                                  ("roamingMngr_triggerRoamingCb, trigger = %d Ignored!!,deltaTs=%d, curTimestamp = %d, lowQualityTriggerTimestamp = %d, lowPassFilterRoamingAttempt=%d\n",
1002                                   roamingTrigger, deltaTs, curTimestamp, pRoamingMngr->lowQualityTriggerTimestamp, pRoamingMngr->lowPassFilterRoamingAttemptInMsec));
1003                    return OK;
1004                }
1005                pRoamingMngr->lowQualityTriggerTimestamp = curTimestamp;
1006            }
1007
1008            /* Mask all future roaming events */
1009            pRoamingMngr->maskRoamingEvents = TRUE;
1010
1011#ifdef TI_DBG
1012            /* For debug */
1013            pRoamingMngr->roamingTriggerTimestamp = curTimestamp;
1014#endif
1015            return (roamingMngr_smEvent((UINT8*)&pRoamingMngr->currentState, ROAMING_EVENT_ROAM_TRIGGER, pRoamingMngr));
1016        }
1017        else if (roamingTrigger > ROAMING_TRIGGER_FAST_CONNECT_GROUP)
1018        {   /* If the trigger is from the Full Connect group, then stop the connection. */
1019            return (roamingMngr_smEvent((UINT8*)&pRoamingMngr->currentState, ROAMING_EVENT_ROAM_TRIGGER, pRoamingMngr));
1020
1021        }
1022    }
1023
1024    return OK;
1025}
1026
1027/**
1028*
1029* roamingMngr_connStatusCb
1030*
1031* \b Description:
1032*
1033* This procedure is called when the connection status event
1034 * is triggered.
1035*
1036* \b ARGS:
1037*
1038*  I   - hRoamingMngr - roamingMngr SM context  \n
1039*  I   - pData - pointer to the connection status.
1040*
1041* \b RETURNS:
1042*
1043*  OK if successful, NOK otherwise.
1044*
1045*
1046*/
1047TI_STATUS roamingMngr_connStatusCb(TI_HANDLE hRoamingMngr, void *pData)
1048{
1049    roamingMngr_t               *pRoamingMngr;
1050    apConn_connStatus_e         connStatus;
1051    roamingMngr_smEvents        roamingEvent;
1052
1053    pRoamingMngr = (roamingMngr_t*)hRoamingMngr;
1054    if ((pRoamingMngr == NULL) || (pData == NULL))
1055    {
1056        return NOK;
1057    }
1058
1059    connStatus = ((apConn_connStatus_t *)pData)->status;
1060    WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
1061                      ("roamingMngr_connStatusCb, conn status = %d\n", connStatus));
1062
1063    if (!pRoamingMngr->roamingMngrConfig.enableDisable)
1064    {
1065        WLAN_REPORT_ERROR(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
1066                              ("roamingMngr_connStatusCb, connStatus=%d was received while Roaming is disabled. Stop Roaming \n",
1067                               connStatus));
1068        return NOK;
1069    }
1070
1071    switch (connStatus)
1072    {
1073    case CONN_STATUS_CONNECTED: roamingEvent = ROAMING_EVENT_START;
1074        /* Get station capabilities */
1075        apConn_getStaCapabilities(pRoamingMngr->hAPConnection, &pRoamingMngr->staCapabilities);
1076        break;
1077    case CONN_STATUS_NOT_CONNECTED: roamingEvent = ROAMING_EVENT_STOP;
1078        break;
1079    case CONN_STATUS_HANDOVER_SUCCESS: roamingEvent = ROAMING_EVENT_ROAM_SUCCESS;
1080#ifdef TI_DBG
1081        /* For debug */
1082        pRoamingMngr->roamingSuccesfulHandoverNum++;
1083        pRoamingMngr->roamingHandoverCompletedTimestamp = os_timeStampMs(pRoamingMngr->hOs);
1084        pRoamingMngr->roamingAverageSuccHandoverDuration += os_timeStampMs(pRoamingMngr->hOs)-pRoamingMngr->roamingHandoverStartedTimestamp;
1085        pRoamingMngr->roamingAverageRoamingDuration +=  os_timeStampMs(pRoamingMngr->hOs)-pRoamingMngr->roamingTriggerTimestamp;
1086        pRoamingMngr->roamingHandoverEvents[pRoamingMngr->roamingTrigger]++;
1087#endif
1088        break;
1089    case CONN_STATUS_HANDOVER_FAILURE: roamingEvent = ROAMING_EVENT_REQ_HANDOVER;
1090#ifdef TI_DBG
1091        /* For debug */
1092        pRoamingMngr->roamingFailedHandoverNum++;
1093#endif
1094        break;
1095    default:
1096        WLAN_REPORT_ERROR(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
1097                          ("roamingMngr_connStatusCb, bad connStatus = %d\n", connStatus));
1098        return NOK;
1099/*        break; - unreachable */
1100    }
1101
1102    return (roamingMngr_smEvent((UINT8*)&pRoamingMngr->currentState, roamingEvent, pRoamingMngr));
1103
1104
1105}
1106
1107
1108
1109
1110
1111/**
1112*
1113* roamingMngr_updateNeighborApListCb
1114*
1115* \b Description:
1116*
1117* This procedure is called when Neighbor AP list is received from the AP.
1118 * Save the list, and set them in Scan Manager object.
1119*
1120* \b ARGS:
1121*
1122*  I   - hRoamingMngr - roamingMngr SM context  \n
1123*  I   - pData - pointer to the list of Neighbor APs.
1124*
1125* \b RETURNS:
1126*
1127*  OK if successful, NOK otherwise.
1128*
1129*
1130*/
1131TI_STATUS roamingMngr_updateNeighborApListCb(TI_HANDLE hRoamingMngr, void *pData)
1132{
1133    roamingMngr_t           *pRoamingMngr;
1134    neighborAPList_t        *pNeighborAPList;
1135
1136    pRoamingMngr = (roamingMngr_t*)hRoamingMngr;
1137    if ((pRoamingMngr == NULL) || (pData == NULL))
1138    {
1139        return NOK;
1140    }
1141
1142    pNeighborAPList = (neighborAPList_t *)pData;
1143    if (pNeighborAPList->numOfEntries>0)
1144    {
1145        pRoamingMngr->neighborApsExist = TRUE;
1146    }
1147    else
1148    {
1149        pRoamingMngr->neighborApsExist = FALSE;
1150    }
1151
1152    if (pRoamingMngr->roamingMngrConfig.enableDisable)
1153    {
1154        scanMngr_setNeighborAPs (pRoamingMngr->hScanMngr, pNeighborAPList);
1155    }
1156    WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
1157                      ("roamingMngr_updateNeighborApListCb, numberOfAps = %d, enableDisable=%d\n",
1158                       pNeighborAPList->numOfEntries, pRoamingMngr->roamingMngrConfig.enableDisable));
1159
1160    return OK;
1161}
1162
1163/**
1164*
1165* roamingMngr_immediateScanComplete
1166*
1167* \b Description:
1168*
1169* This procedure is called when Scan Manager completed Immediate Scan for Roaming
1170 * It performs the following:
1171 * - Partial or Full scan
1172 * - Re-try Partial or Full scan if the previous scan failed
1173 * - Full scan if the previous partial scan didn't get any APS
1174 * - Fail event if all the Scans failed
1175*
1176* \b ARGS:
1177*
1178*  I   - hRoamingMngr - roamingMngr SM context  \n
1179*  I   - scanCmpltStatus - the scan result, success or failure with different reasons
1180*
1181* \b RETURNS:
1182*
1183*  OK if successful, NOK otherwise.
1184*
1185*
1186*/
1187TI_STATUS roamingMngr_immediateScanComplete(TI_HANDLE hRoamingMngr, scan_mngrResultStatus_e scanCmpltStatus)
1188{
1189    roamingMngr_t           *pRoamingMngr;
1190    roamingMngr_smEvents    roamingEvent;
1191
1192
1193    pRoamingMngr = (roamingMngr_t*)hRoamingMngr;
1194    if (pRoamingMngr == NULL)
1195    {
1196        return NOK;
1197    }
1198
1199    WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
1200                      ("roamingMngr_immediateScanComplete, scanCmpltStatus = %d\n", scanCmpltStatus));
1201
1202    if (scanCmpltStatus == SCAN_MRS_SCAN_COMPLETE_OK)
1203    {   /* The scan completed OK, get the updated list of APs */
1204        pRoamingMngr->pListOfAPs = scanMngr_getBSSList(pRoamingMngr->hScanMngr);
1205        if ((pRoamingMngr->pListOfAPs != NULL) && (pRoamingMngr->pListOfAPs->numOfEntries > 0))
1206        {   /* APs were found, start selection */
1207            pRoamingMngr->scanType = ROAMING_NO_SCAN;
1208            roamingEvent = ROAMING_EVENT_SELECT;
1209        }
1210        else
1211        {   /* There were no APs, if the scan was partial, retry full scan */
1212            if ((pRoamingMngr->scanType == ROAMING_PARTIAL_SCAN) ||
1213                (pRoamingMngr->scanType == ROAMING_PARTIAL_SCAN_RETRY))
1214            {
1215                pRoamingMngr->scanType = ROAMING_FULL_SCAN;
1216                roamingEvent = ROAMING_EVENT_SCAN;
1217            }
1218            else
1219            {   /* No APs were found in FULL SCAN, report failure */
1220                roamingEvent = ROAMING_EVENT_SELECT;
1221            }
1222        }
1223    }
1224    else
1225    {   /* The scan failed, retry scanning according to the current scan type */
1226        pRoamingMngr->pListOfAPs = scanMngr_getBSSList(pRoamingMngr->hScanMngr);
1227        if ((pRoamingMngr->pListOfAPs != NULL) && (pRoamingMngr->pListOfAPs->numOfEntries > 0))
1228        {   /* APs were found, start selection */
1229            pRoamingMngr->scanType = ROAMING_NO_SCAN;
1230            roamingEvent = ROAMING_EVENT_SELECT;
1231        }
1232        else
1233        {   /* The scan failed, and there were no APs found.
1234                Retry scanning according to the current scan type */
1235        switch (pRoamingMngr->scanType)
1236        {
1237        case ROAMING_PARTIAL_SCAN:
1238            roamingEvent = ROAMING_EVENT_SCAN;
1239            pRoamingMngr->scanType = ROAMING_PARTIAL_SCAN_RETRY;
1240            break;
1241        case ROAMING_PARTIAL_SCAN_RETRY:
1242            roamingEvent = ROAMING_EVENT_SELECT;
1243            pRoamingMngr->scanType = ROAMING_NO_SCAN;
1244            break;
1245        case ROAMING_FULL_SCAN:
1246            roamingEvent = ROAMING_EVENT_SCAN;
1247            pRoamingMngr->scanType = ROAMING_FULL_SCAN_RETRY;
1248            break;
1249        case ROAMING_FULL_SCAN_RETRY:
1250                roamingEvent = ROAMING_EVENT_SELECT;
1251            pRoamingMngr->scanType = ROAMING_NO_SCAN;
1252            break;
1253        default:
1254            roamingEvent = ROAMING_EVENT_SELECT;
1255            WLAN_REPORT_ERROR(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
1256                              ("roamingMngr_immediateScanComplete, pRoamingMngr->scanType = %d\n", pRoamingMngr->scanType));
1257            pRoamingMngr->scanType = ROAMING_NO_SCAN;
1258            break;
1259            }
1260
1261        }
1262    }
1263
1264    WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
1265                      ("roamingMngr_immediateScanComplete, roamingEvent = %d, scanType=%d\n",
1266                       roamingEvent, pRoamingMngr->scanType));
1267
1268    return (roamingMngr_smEvent((UINT8*)&pRoamingMngr->currentState, roamingEvent, pRoamingMngr));
1269
1270
1271}
1272
1273
1274/* called by the Scan Manager when new BSSID was found */
1275/**
1276*
1277* roamingMngr_updateNewBssList
1278*
1279* \b Description:
1280*
1281* This procedure is called when Scan Manager finds new BSSIDs.
1282* These BSSIDs are sent to RSn to invoke Pre-Auth if allowed.
1283*
1284* \b ARGS:
1285*
1286*  I   - hRoamingMngr - roamingMngr SM context  \n
1287*  I   - bssList - list of BSSIDs
1288*
1289* \b RETURNS:
1290*
1291*  OK if successful, NOK otherwise.
1292*
1293*
1294*/
1295TI_STATUS roamingMngr_updateNewBssList(TI_HANDLE hRoamingMngr, bssList_t *bssList)
1296{
1297
1298    roamingMngr_t       *pRoamingMngr;
1299
1300    pRoamingMngr = (roamingMngr_t*)hRoamingMngr;
1301    if ((pRoamingMngr == NULL) || (bssList == NULL))
1302    {
1303        return NOK;
1304    }
1305
1306    WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
1307                      ("roamingMngr_updateNewBssList, number of APs = %d\n", bssList->numOfEntries));
1308
1309    if (pRoamingMngr->currentState != ROAMING_STATE_WAIT_4_TRIGGER)
1310    {
1311        WLAN_REPORT_WARNING(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
1312                          ("roamingMngr_updateNewBssList, ignore APs when not in WAIT_4_TRIGGER state \n"));
1313        return NOK;
1314    }
1315
1316
1317    if (pRoamingMngr->staCapabilities.authMode!=os802_11AuthModeWPA2)
1318    {   /* No Pre-Auth is required */
1319        WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
1320                          ("roamingMngr_updateNewBssList, No Pre-Auth is required\n"));
1321        return OK;
1322    }
1323    apConn_preAuthenticate(pRoamingMngr->hAPConnection, bssList, bssList->numOfEntries);
1324
1325    return OK;
1326
1327}
1328
1329
1330/*****************************************************************************
1331**         Private Function section                                      **
1332*****************************************************************************/
1333
1334
1335
1336/**
1337*
1338* roamingMngr_smEvent
1339*
1340* \b Description:
1341*
1342* Roaming Manager state machine transition function
1343*
1344* \b ARGS:
1345*
1346*  I/O - currentState - current state in the state machine\n
1347*  I   - event - specific event for the state machine\n
1348*  I   - pData - Data for state machine action function\n
1349*
1350* \b RETURNS:
1351*
1352*  OK on success, NOK otherwise.
1353*
1354* \sa
1355*/
1356static TI_STATUS roamingMngr_smEvent(UINT8 *currState, UINT8 event, void* data)
1357{
1358    TI_STATUS       status;
1359    UINT8           nextState;
1360    roamingMngr_t   *pRoamingMngr = (roamingMngr_t*)data;
1361
1362
1363    status = fsm_GetNextState(pRoamingMngr->pRoamingSm, *currState, event, &nextState);
1364    if (status != OK)
1365    {
1366        WLAN_REPORT_ERROR(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG, ("roamingMngr_smEvent, fsm_GetNextState error\n"));
1367        return(NOK);
1368    }
1369
1370#ifdef TI_DBG
1371    WLAN_REPORT_SM(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
1372                              ("<%s, %s> --> %s\n\n",
1373                               roamingMngr_stateDesc[*currState],
1374                               roamingMngr_eventDesc[event],
1375                               roamingMngr_stateDesc[nextState]));
1376#endif
1377
1378    status = fsm_Event(pRoamingMngr->pRoamingSm, currState, event, (void *)pRoamingMngr);
1379
1380#ifdef TI_DBG
1381    if (status != OK)
1382    {
1383        WLAN_REPORT_ERROR(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG, ("roamingMngr_smEvent fsm_Event error\n"));
1384        WLAN_REPORT_ERROR(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
1385                                  ("<%s, %s> --> %s\n\n",
1386                                   roamingMngr_stateDesc[*currState],
1387                                   roamingMngr_eventDesc[event],
1388                                   roamingMngr_stateDesc[nextState]));
1389    }
1390#endif
1391
1392    return status;
1393
1394}
1395
1396/**
1397*
1398* roamingMngr_smRoamTrigger
1399*
1400* \b Description:
1401*
1402* This procedure is called when an Roaming event occurs: BSS LOSS, LOW Quality etc.
1403 * Performs the following:
1404 * - If Roaming is disabled, ignore.
1405 * - Indicate Driver that Roaming process is starting
1406 * - Get the BSS list from the Scan Manager.
1407 * - If the list is not empty, start SELECTION
1408 * - If the list is empty, start SCANNING. The type of scan is decided
1409 *      according to the Neigbor APs existence.
1410*
1411* \b ARGS:
1412*
1413*  I   - hRoamingMngr - roamingMngr SM context  \n
1414*
1415* \b RETURNS:
1416*
1417*  OK if successful, NOK otherwise.
1418*
1419*
1420*/
1421static TI_STATUS roamingMngr_smRoamTrigger(TI_HANDLE hRoamingMngr)
1422{
1423    roamingMngr_t           *pRoamingMngr;
1424    roamingMngr_smEvents    roamingEvent;
1425
1426    pRoamingMngr = (roamingMngr_t*)hRoamingMngr;
1427    if (pRoamingMngr == NULL)
1428    {
1429        return NOK;
1430    }
1431    WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
1432                ("roamingMngr_smRoamTrigger, enableDisable = %d\n",pRoamingMngr->roamingMngrConfig.enableDisable));
1433
1434
1435    if (!pRoamingMngr->roamingMngrConfig.enableDisable)
1436    {   /* Ignore any other Roaming event when Roaming is disabled */
1437        WLAN_REPORT_ERROR(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
1438                    ("roamingMngr_smRoamTrigger, when Roaming is disabled\n"));
1439        return OK;
1440    }
1441    /* Indicate the driver that Roaming process is starting */
1442    apConn_prepareToRoaming(pRoamingMngr->hAPConnection, pRoamingMngr->roamingTrigger);
1443
1444    /* Get the current BSSIDs from ScanMngr */
1445#if 0
1446    pRoamingMngr->pListOfAPs = scanMngr_getBSSList(pRoamingMngr->hScanMngr);
1447#else
1448    pRoamingMngr->pListOfAPs = NULL; /* force immediate scan */
1449#endif
1450    if ((pRoamingMngr->pListOfAPs != NULL) && (pRoamingMngr->pListOfAPs->numOfEntries > 0))
1451    {   /* No need to SCAN, start SELECTING */
1452        roamingEvent = ROAMING_EVENT_SELECT;
1453    }
1454    else
1455    {   /* check if list of APs exists in order to verify which scan to start */
1456        roamingEvent = ROAMING_EVENT_SCAN;
1457        if (pRoamingMngr->neighborApsExist)
1458        {   /* Scan only Neighbor APs */
1459            pRoamingMngr->scanType = ROAMING_PARTIAL_SCAN;
1460        }
1461        else
1462        {   /* Scan all channels */
1463            pRoamingMngr->scanType = ROAMING_FULL_SCAN;
1464        }
1465    }
1466    WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
1467                ("roamingMngr_smRoamTrigger, scanType = %d\n", pRoamingMngr->scanType));
1468
1469    return (roamingMngr_smEvent((UINT8*)&pRoamingMngr->currentState, roamingEvent, pRoamingMngr));
1470}
1471
1472/**
1473*
1474* roamingMngr_smInvokeScan
1475*
1476* \b Description:
1477*
1478* This procedure is called when scan should be performed in order
1479 * to select an AP to roam to.
1480 * This can be the first scan, a second scan after partail scan,
1481 * or scan after previous scan was failed.
1482 * In any case, the scan can either be:
1483 *  partail, on list of channles or
1484 *  full on all channels.
1485*
1486* \b ARGS:
1487*
1488*  I   - hRoamingMngr - roamingMngr SM context  \n
1489*
1490* \b RETURNS:
1491*
1492*  OK if successful, NOK otherwise.
1493*
1494*
1495*/
1496static TI_STATUS roamingMngr_smInvokeScan(TI_HANDLE hRoamingMngr)
1497{
1498    roamingMngr_t       *pRoamingMngr;
1499    scan_mngrResultStatus_e     scanResult;
1500
1501    pRoamingMngr = (roamingMngr_t*)hRoamingMngr;
1502    if (pRoamingMngr == NULL)
1503    {
1504        return NOK;
1505    }
1506
1507    scanMngrClearBSSListEntry(pRoamingMngr->hScanMngr);
1508
1509    /* check which scan should be performed: Partial on list of channels, or full scan */
1510    if ((pRoamingMngr->scanType == ROAMING_PARTIAL_SCAN) ||
1511        (pRoamingMngr->scanType == ROAMING_PARTIAL_SCAN_RETRY))
1512    {
1513        scanResult = scanMngr_startImmediateScan (pRoamingMngr->hScanMngr, TRUE);
1514    }
1515    else
1516    {    /* Scan all channels */
1517        scanResult = scanMngr_startImmediateScan (pRoamingMngr->hScanMngr, FALSE);
1518    }
1519
1520    if (scanResult != SCAN_MRS_SCAN_RUNNING)
1521    {   /* the scan failed, immitate scan complete event */
1522        WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
1523                    ("roamingMngr_smInvokeScan, scanResult = %d\n", scanResult));
1524        roamingMngr_immediateScanComplete(pRoamingMngr, scanResult);
1525    }
1526    return OK;
1527
1528}
1529
1530/**
1531*
1532* roamingMngr_smSelection
1533*
1534* \b Description:
1535*
1536* This procedure is called when selection should be performed.
1537*   It perform the following:
1538 * Prepare the candidate APs to roam according to:
1539 *  - Priority APs
1540 *  - Pre-Authenticated APs
1541 * If the candidate AP list is empty, only the current AP can be re-selected
1542 * Select one AP and trigger REQ_HANDOVER event.
1543 *
1544* \b ARGS:
1545*
1546*  I   - hRoamingMngr - roamingMngr SM context  \n
1547*
1548* \b RETURNS:
1549*
1550*  OK if successful, NOK otherwise.
1551*
1552*
1553*/
1554static TI_STATUS roamingMngr_smSelection(TI_HANDLE hRoamingMngr)
1555{
1556    roamingMngr_t               *pRoamingMngr;
1557    UINT32                      index;
1558
1559
1560    pRoamingMngr = (roamingMngr_t*)hRoamingMngr;
1561    if (pRoamingMngr == NULL)
1562    {
1563        return NOK;
1564    }
1565
1566
1567    pRoamingMngr->listOfCandidateAps.numOfNeighborBSS = 0;
1568    pRoamingMngr->listOfCandidateAps.numOfPreAuthBSS = 0;
1569    pRoamingMngr->listOfCandidateAps.numOfRegularBSS = 0;
1570
1571    pRoamingMngr->candidateApIndex = INVALID_CANDIDATE_INDEX;
1572
1573    if ((pRoamingMngr->pListOfAPs == NULL) ||
1574        (pRoamingMngr->pListOfAPs->numOfEntries == 0))
1575    {   /* Error, there cannot be selection  */
1576        WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
1577                          ("roamingMngr_smSelection pListOfAPs is empty \n"));
1578        return (roamingMngr_smEvent((UINT8*)&pRoamingMngr->currentState, ROAMING_EVENT_REQ_HANDOVER, pRoamingMngr));
1579    }
1580
1581    /* Build the candidate AP list */
1582    for (index=0; index<pRoamingMngr->pListOfAPs->numOfEntries; index++ )
1583    {
1584        if ( (pRoamingMngr->roamingTrigger <= ROAMING_TRIGGER_LOW_QUALITY_GROUP) &&
1585            (pRoamingMngr->pListOfAPs->BSSList[index].RSSI < pRoamingMngr->roamingMngrConfig.apQualityThreshold))
1586        {   /* Do not insert APs with low quality to the selection table,
1587                if the Roaming Trigger was low Quality */
1588            WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
1589                              ("candidate AP %x-%x-%x-%x-%x-%x with RSSI too low =%d, Quality=%d  \n",
1590                               pRoamingMngr->pListOfAPs->BSSList[index].BSSID.addr[0],
1591                               pRoamingMngr->pListOfAPs->BSSList[index].BSSID.addr[1],
1592                               pRoamingMngr->pListOfAPs->BSSList[index].BSSID.addr[2],
1593                               pRoamingMngr->pListOfAPs->BSSList[index].BSSID.addr[3],
1594                               pRoamingMngr->pListOfAPs->BSSList[index].BSSID.addr[4],
1595                               pRoamingMngr->pListOfAPs->BSSList[index].BSSID.addr[5],
1596                               pRoamingMngr->pListOfAPs->BSSList[index].RSSI,
1597                               pRoamingMngr->roamingMngrConfig.apQualityThreshold));
1598
1599            continue;
1600        }
1601
1602        if (apConn_isSiteBanned(pRoamingMngr->hAPConnection, &pRoamingMngr->pListOfAPs->BSSList[index].BSSID) == TRUE)
1603        {
1604            WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
1605                    ("%s: Candidate AP %02X-%02X-%02X-%02X-%02X-%02X is banned!\n", __FUNCTION__,
1606                            pRoamingMngr->pListOfAPs->BSSList[index].BSSID.addr[0],
1607                            pRoamingMngr->pListOfAPs->BSSList[index].BSSID.addr[1],
1608                            pRoamingMngr->pListOfAPs->BSSList[index].BSSID.addr[2],
1609                            pRoamingMngr->pListOfAPs->BSSList[index].BSSID.addr[3],
1610                            pRoamingMngr->pListOfAPs->BSSList[index].BSSID.addr[4],
1611                            pRoamingMngr->pListOfAPs->BSSList[index].BSSID.addr[5]));
1612            continue;
1613        }
1614
1615        if (pRoamingMngr->pListOfAPs->BSSList[index].bNeighborAP)
1616        {   /* The AP is a neighbor AP, insert its index to the neighbor APs list */
1617            pRoamingMngr->listOfCandidateAps.neighborBSSList[pRoamingMngr->listOfCandidateAps.numOfNeighborBSS] = index;
1618            pRoamingMngr->listOfCandidateAps.numOfNeighborBSS++;
1619        }
1620        else if (apConn_getPreAuthAPStatus(pRoamingMngr->hAPConnection,
1621                        &pRoamingMngr->pListOfAPs->BSSList[index].BSSID))
1622        {   /* This AP is a pre-auth AP */
1623            pRoamingMngr->listOfCandidateAps.preAuthBSSList[pRoamingMngr->listOfCandidateAps.numOfPreAuthBSS] = index;
1624            pRoamingMngr->listOfCandidateAps.numOfPreAuthBSS++;
1625        }
1626        else
1627        {   /* This AP is not Neighbor nor Pre-Auth */
1628            pRoamingMngr->listOfCandidateAps.regularBSSList[pRoamingMngr->listOfCandidateAps.numOfRegularBSS] = index;
1629            pRoamingMngr->listOfCandidateAps.numOfRegularBSS++;
1630        }
1631    }
1632
1633#ifdef TI_DBG
1634    {   /* for debug */
1635        paramInfo_t     param;
1636
1637        param.paramType = ROAMING_MNGR_PRINT_CANDIDATE_TABLE;
1638        roamingMngr_getParam(pRoamingMngr, &param);
1639
1640    }
1641#endif
1642    return (roamingMngr_smEvent((UINT8*)&pRoamingMngr->currentState, ROAMING_EVENT_REQ_HANDOVER, pRoamingMngr));
1643
1644}
1645
1646
1647
1648/**
1649*
1650* roamingMngr_smHandover
1651*
1652* \b Description:
1653*
1654* This procedure is called when handover should be invoked.
1655*   Go over the candidate APs and start handover to each of them.
1656 * If there's no candidate APs, disconnect.
1657 * Handover to the current AP is allowed only if the trigger is
1658 * low quality.
1659 *
1660* \b ARGS:
1661*
1662*  I   - hRoamingMngr - roamingMngr SM context  \n
1663*
1664* \b RETURNS:
1665*
1666*  OK if successful, NOK otherwise.
1667*
1668*
1669*/
1670static TI_STATUS roamingMngr_smHandover(TI_HANDLE hRoamingMngr)
1671{
1672    roamingMngr_t           *pRoamingMngr;
1673    bssEntry_t              *pApToConnect;
1674    apConn_connRequest_t    requestToApConn;
1675
1676    pRoamingMngr = (roamingMngr_t*)hRoamingMngr;
1677    if (pRoamingMngr == NULL)
1678    {
1679        return NOK;
1680    }
1681
1682
1683    if ((pRoamingMngr->handoverWasPerformed) && (pRoamingMngr->candidateApIndex == CURRENT_AP_INDEX))
1684    {   /* Handover with the current AP already failed, Disconnect */
1685        return (roamingMngr_smEvent((UINT8*)&pRoamingMngr->currentState, ROAMING_EVENT_FAILURE, pRoamingMngr));
1686    }
1687    if (pRoamingMngr->listOfCandidateAps.numOfNeighborBSS > 0)
1688    {   /* Neighbor APs are the highest priority to Roam */
1689        pRoamingMngr->candidateApIndex =
1690            pRoamingMngr->listOfCandidateAps.neighborBSSList[pRoamingMngr->listOfCandidateAps.numOfNeighborBSS-1];
1691        pRoamingMngr->listOfCandidateAps.numOfNeighborBSS--;
1692    }
1693    else if (pRoamingMngr->listOfCandidateAps.numOfPreAuthBSS > 0)
1694    {   /* Pre-Auth APs are the second priority to Roam */
1695        pRoamingMngr->candidateApIndex =
1696            pRoamingMngr->listOfCandidateAps.preAuthBSSList[pRoamingMngr->listOfCandidateAps.numOfPreAuthBSS-1];
1697        pRoamingMngr->listOfCandidateAps.numOfPreAuthBSS--;
1698    }
1699    else if (pRoamingMngr->listOfCandidateAps.numOfRegularBSS > 0)
1700    {   /* Regular APs are APs that are not pre-authenticated and not Neighbor */
1701        pRoamingMngr->candidateApIndex =
1702            pRoamingMngr->listOfCandidateAps.regularBSSList[pRoamingMngr->listOfCandidateAps.numOfRegularBSS-1];
1703        pRoamingMngr->listOfCandidateAps.numOfRegularBSS--;
1704    }
1705    else
1706    {   /* No Candidate APs */
1707        pRoamingMngr->candidateApIndex = INVALID_CANDIDATE_INDEX;
1708    }
1709
1710    WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
1711                      ("roamingMngr_smHandover, candidateApIndex=%d \n", pRoamingMngr->candidateApIndex));
1712
1713
1714    if (pRoamingMngr->candidateApIndex == INVALID_CANDIDATE_INDEX)
1715    {   /* No cnadidate to Roam to, only the current AP is candidate */
1716        if (pRoamingMngr->roamingTrigger <= ROAMING_TRIGGER_LOW_QUALITY_GROUP)
1717        {   /* If the trigger to Roam is low quality, and there are no candidate APs
1718                to roam to, retain connected to the current AP */
1719            requestToApConn.requestType = (pRoamingMngr->handoverWasPerformed) ? AP_CONNECT_RECONNECT_CURR_AP : AP_CONNECT_RETAIN_CURR_AP;
1720            pRoamingMngr->candidateApIndex = CURRENT_AP_INDEX;
1721        }
1722        else
1723        {   /* Disconnect the BSS, there are no more APs to roam to */
1724            return (roamingMngr_smEvent((UINT8*)&pRoamingMngr->currentState, ROAMING_EVENT_FAILURE, pRoamingMngr));
1725        }
1726    }
1727    else
1728    {   /* There is a valid candidate AP */
1729        if (pRoamingMngr->roamingTrigger > ROAMING_TRIGGER_FAST_CONNECT_GROUP)
1730        {   /* Full re-connection should be perfromed */
1731            requestToApConn.requestType = AP_CONNECT_FULL_TO_AP;
1732        }
1733        else
1734        {   /* Fast re-connection should be perfromed */
1735            requestToApConn.requestType = AP_CONNECT_FAST_TO_AP;
1736        }
1737    }
1738#ifdef TI_DBG
1739    /* For debug */
1740    if (!pRoamingMngr->handoverWasPerformed)
1741    {   /* Take the time before the first handover started */
1742        pRoamingMngr->roamingHandoverStartedTimestamp = os_timeStampMs(pRoamingMngr->hOs);
1743    }
1744#endif
1745
1746    if (pRoamingMngr->candidateApIndex == CURRENT_AP_INDEX)
1747    {   /* get the current AP */
1748        pApToConnect = apConn_getBSSParams(pRoamingMngr->hAPConnection);
1749    }
1750    else
1751    {   /* get the candidate AP */
1752        pRoamingMngr->handoverWasPerformed = TRUE;
1753        pApToConnect = &pRoamingMngr->pListOfAPs->BSSList[pRoamingMngr->candidateApIndex];
1754    }
1755    WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
1756                      ("roamingMngr_smHandover, candidateApIndex=%d, requestType = %d, channel=%d \n",
1757                       pRoamingMngr->candidateApIndex, requestToApConn.requestType, pApToConnect->channel));
1758
1759    requestToApConn.dataBufLength = 0;
1760    return (apConn_connectToAP(pRoamingMngr->hAPConnection, pApToConnect, &requestToApConn, TRUE));
1761}
1762
1763
1764
1765/**
1766*
1767* roamingMngr_smDisconnectWhileConnecting
1768*
1769* \b Description:
1770*
1771* This procedure is called when the Station is in the process of connection,
1772 * and the AP disconnects the station.
1773 *
1774* \b ARGS:
1775*
1776*  I   - hRoamingMngr - roamingMngr SM context  \n
1777*
1778* \b RETURNS:
1779*
1780*  OK if successful, NOK otherwise.
1781*
1782*
1783*/
1784static TI_STATUS roamingMngr_smDisconnectWhileConnecting(TI_HANDLE hRoamingMngr)
1785{
1786    roamingMngr_t           *pRoamingMngr;
1787
1788    pRoamingMngr = (roamingMngr_t*)hRoamingMngr;
1789    if (pRoamingMngr == NULL)
1790    {
1791        return NOK;
1792    }
1793
1794    WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
1795                      ("roamingMngr_smDisconnectWhileConnecting, candidateApIndex=%d \n", pRoamingMngr->candidateApIndex));
1796
1797    if (pRoamingMngr->roamingTrigger > ROAMING_TRIGGER_FAST_CONNECT_GROUP)
1798    {   /* If the trigger is from the Full Connect group, then stop the connection. */
1799        /* clean intenal variables */
1800        pRoamingMngr->maskRoamingEvents = TRUE;
1801        pRoamingMngr->roamingTrigger = ROAMING_TRIGGER_NONE;
1802
1803        scanMngr_stopContScan(pRoamingMngr->hScanMngr);
1804#ifdef TI_DBG
1805        pRoamingMngr->roamingFailedHandoverNum++;
1806#endif
1807        return (apConn_disconnect(pRoamingMngr->hAPConnection));
1808
1809    }
1810
1811    return OK;
1812
1813}
1814
1815/**
1816*
1817* roamingMngr_smSuccHandover
1818*
1819* \b Description:
1820*
1821* This procedure is called when handover succeeded.
1822 * Inform Scan Manager about the new AP.
1823 * UnMask Roaming Triggers.
1824 *
1825* \b ARGS:
1826*
1827*  I   - hRoamingMngr - roamingMngr SM context  \n
1828*
1829* \b RETURNS:
1830*
1831*  OK if successful, NOK otherwise.
1832*
1833*
1834*/
1835static TI_STATUS roamingMngr_smSuccHandover(TI_HANDLE hRoamingMngr)
1836{
1837    roamingMngr_t           *pRoamingMngr;
1838    bssEntry_t              *pNewConnectedAp;
1839
1840    pRoamingMngr = (roamingMngr_t*)hRoamingMngr;
1841    if (pRoamingMngr == NULL)
1842    {
1843        return NOK;
1844    }
1845
1846    WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
1847                      ("roamingMngr_smSuccHandover, candidateApIndex=%d \n", pRoamingMngr->candidateApIndex));
1848
1849    if (pRoamingMngr->handoverWasPerformed &&
1850        (pRoamingMngr->pListOfAPs != NULL) &&
1851        (pRoamingMngr->pListOfAPs->numOfEntries>0))
1852    {
1853        if (pRoamingMngr->candidateApIndex == CURRENT_AP_INDEX)
1854        {   /* get the current AP */
1855            pNewConnectedAp = apConn_getBSSParams(pRoamingMngr->hAPConnection);
1856        }
1857        else
1858        {   /* get the candidate AP */
1859            pNewConnectedAp = &pRoamingMngr->pListOfAPs->BSSList[pRoamingMngr->candidateApIndex];
1860        }
1861
1862        scanMngr_handoverDone(pRoamingMngr->hScanMngr,
1863                          &pNewConnectedAp->BSSID,
1864                          pNewConnectedAp->band);
1865    }
1866    pRoamingMngr->maskRoamingEvents = FALSE;
1867    pRoamingMngr->candidateApIndex = INVALID_CANDIDATE_INDEX;
1868    pRoamingMngr->handoverWasPerformed = FALSE;
1869    pRoamingMngr->roamingTrigger = ROAMING_TRIGGER_NONE;
1870
1871    /* Start pre-authentication in order to set PMKID
1872        for the current AP */
1873    if (pRoamingMngr->staCapabilities.authMode==os802_11AuthModeWPA2)
1874    {   /* No Pre-Auth is required */
1875		UINT8 dummy;
1876
1877        WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
1878                          ("roamingMngr_smStartIdle, Pre-Auth to cur AP\n"));
1879        apConn_preAuthenticate(pRoamingMngr->hAPConnection, (bssList_t *)&dummy, 0);
1880    }
1881
1882    return OK;
1883}
1884
1885
1886
1887
1888/**
1889*
1890* roamingMngr_smFailHandover
1891*
1892* \b Description:
1893*
1894* This procedure is called when handover failed and there are no more
1895 * APs to roam to. Disconnect the BSS and retrun to IDLE state.
1896*
1897* \b ARGS:
1898*
1899*  I   - hRoamingMngr - roamingMngr SM context  \n
1900*
1901* \b RETURNS:
1902*
1903*  OK if successful, NOK otherwise.
1904*
1905*
1906*/
1907static TI_STATUS roamingMngr_smFailHandover(TI_HANDLE hRoamingMngr)
1908{
1909    roamingMngr_t           *pRoamingMngr;
1910
1911    pRoamingMngr = (roamingMngr_t*)hRoamingMngr;
1912    if (pRoamingMngr == NULL)
1913    {
1914        return NOK;
1915    }
1916
1917    WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
1918                      ("roamingMngr_smFailHandover \n"));
1919
1920    /* clean intenal variables */
1921    pRoamingMngr->maskRoamingEvents = TRUE;
1922    pRoamingMngr->roamingTrigger = ROAMING_TRIGGER_NONE;
1923
1924    scanMngr_stopContScan(pRoamingMngr->hScanMngr);
1925#ifdef TI_DBG
1926    pRoamingMngr->roamingFailedHandoverNum++;
1927#endif
1928    return (apConn_disconnect(pRoamingMngr->hAPConnection));
1929}
1930
1931
1932
1933
1934/**
1935*
1936* roamingMngr_smScanFailure
1937*
1938* \b Description:
1939*
1940* This procedure is called when all scan attempts failed.
1941 * Send Disconnect event and return to IDLE state.
1942 *
1943*
1944* \b ARGS:
1945*
1946*  I   - hRoamingMngr - roamingMngr SM context  \n
1947*
1948* \b RETURNS:
1949*
1950*  OK if successful, NOK otherwise.
1951*
1952*
1953*/
1954static TI_STATUS roamingMngr_smScanFailure(TI_HANDLE hRoamingMngr)
1955{
1956    roamingMngr_t           *pRoamingMngr;
1957
1958    pRoamingMngr = (roamingMngr_t*)hRoamingMngr;
1959    if (pRoamingMngr == NULL)
1960    {
1961        return NOK;
1962    }
1963
1964    WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
1965                      ("roamingMngr_smScanFailure \n"));
1966
1967    /* clean intenal variables */
1968    pRoamingMngr->maskRoamingEvents = TRUE;
1969    pRoamingMngr->roamingTrigger = ROAMING_TRIGGER_NONE;
1970
1971    scanMngr_stopContScan(pRoamingMngr->hScanMngr);
1972
1973    return (apConn_disconnect(pRoamingMngr->hAPConnection));
1974}
1975
1976#if 0
1977/**
1978*
1979* roamingMngr_smCmdFailure
1980*
1981* \b Description:
1982*
1983* This procedure is called when all the driver failed to prepare to Roaming.
1984 * Mask all future Roaming triggers.
1985 *
1986*
1987* \b ARGS:
1988*
1989*  I   - hRoamingMngr - roamingMngr SM context  \n
1990*
1991* \b RETURNS:
1992*
1993*  OK if successful, NOK otherwise.
1994*
1995*
1996*/
1997static TI_STATUS roamingMngr_smCmdFailure(TI_HANDLE hRoamingMngr)
1998{
1999    roamingMngr_t           *pRoamingMngr;
2000
2001    pRoamingMngr = (roamingMngr_t*)hRoamingMngr;
2002    if (pRoamingMngr == NULL)
2003    {
2004        return NOK;
2005    }
2006
2007    WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
2008                      ("roamingMngr_smCmdFailure \n"));
2009
2010    /* clean intenal variables */
2011    pRoamingMngr->maskRoamingEvents = TRUE;
2012    pRoamingMngr->roamingTrigger = ROAMING_TRIGGER_NONE;
2013
2014    return OK;
2015
2016}
2017#endif
2018
2019/**
2020*
2021* roamingMngr_smStartIdle - Start event when in Idle state
2022*
2023* \b Description:
2024*
2025* Start event when in Idle state.
2026 * This function is called when the station becomes CONNECTED.
2027 * Perform the following:
2028 * - The current state becomes WAIT_4_TRIGGER
2029 * - Unmask Roaming events
2030 * - Set handoverWasPerformed to FALSE
2031 * - Start the Scan Manager
2032*
2033* \b ARGS:
2034*
2035*  I   - pData - pointer to the roamingMngr SM context  \n
2036*
2037* \b RETURNS:
2038*
2039*  OK if successful, NOK otherwise.
2040*
2041*
2042*/
2043static TI_STATUS roamingMngr_smStartIdle(void *pData)
2044{
2045    roamingMngr_t       *pRoamingMngr;
2046    bssEntry_t          *pCurBssEntry;
2047
2048    pRoamingMngr = (roamingMngr_t*)pData;
2049    if (pRoamingMngr == NULL)
2050    {
2051        return NOK;
2052    }
2053    WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
2054                              ("roamingMngr_smStartIdle, Unmask Roaming events and start continuos scan \n"));
2055
2056    pRoamingMngr->maskRoamingEvents = FALSE;
2057    pRoamingMngr->handoverWasPerformed = FALSE;
2058    pRoamingMngr->roamingTrigger = ROAMING_TRIGGER_NONE;
2059
2060    pCurBssEntry = apConn_getBSSParams(pRoamingMngr->hAPConnection);
2061    scanMngr_startContScan(pRoamingMngr->hScanMngr, &pCurBssEntry->BSSID, pCurBssEntry->band);
2062
2063    /* Start pre-authentication in order to set PMKID
2064        for the current AP */
2065    if (pRoamingMngr->staCapabilities.authMode==os802_11AuthModeWPA2)
2066    {   /* No Pre-Auth is required */
2067		UINT8 				dummy;
2068        WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
2069                          ("roamingMngr_smStartIdle, Pre-Auth to cur AP\n"));
2070        apConn_preAuthenticate(pRoamingMngr->hAPConnection, (bssList_t *)&dummy, 0);
2071    }
2072
2073    return OK;
2074}
2075
2076
2077
2078/**
2079*
2080* roamingMngr_smNop - Do nothing
2081*
2082* \b Description:
2083*
2084* Do nothing in the SM.
2085*
2086* \b ARGS:
2087*
2088*  I   - pData - pointer to the roamingMngr SM context  \n
2089*
2090* \b RETURNS:
2091*
2092*  OK if successful, NOK otherwise.
2093*
2094*
2095*/
2096static TI_STATUS roamingMngr_smNop(void *pData)
2097{
2098    roamingMngr_t       *pRoamingMngr;
2099
2100    pRoamingMngr = (roamingMngr_t*)pData;
2101    if (pRoamingMngr == NULL)
2102    {
2103        return NOK;
2104    }
2105    WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
2106                (" roamingMngr_smNop\n"));
2107
2108    return OK;
2109}
2110
2111/**
2112*
2113* roamingMngr_smUnexpected - Unexpected event
2114*
2115* \b Description:
2116*
2117* Unexpected event in the SM.
2118*
2119* \b ARGS:
2120*
2121*  I   - pData - pointer to the roamingMngr SM context  \n
2122*
2123* \b RETURNS:
2124*
2125*  OK if successful, NOK otherwise.
2126*
2127*
2128*/
2129static TI_STATUS roamingMngr_smUnexpected(void *pData)
2130{
2131    roamingMngr_t       *pRoamingMngr;
2132
2133    pRoamingMngr = (roamingMngr_t*)pData;
2134    if (pRoamingMngr == NULL)
2135    {
2136        return NOK;
2137    }
2138    WLAN_REPORT_ERROR(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
2139                (" roamingMngr_smUnexpected, state = %d\n", pRoamingMngr->currentState));
2140
2141    return NOK;
2142}
2143
2144
2145
2146
2147
2148/**
2149*
2150* roamingMngr_smStop - Stop all timers and clean DB
2151*
2152* \b Description:
2153*
2154* Stop event in start state. Stop timers, clean internal vars
2155 *  and exit PS if necessary.
2156*
2157* \b ARGS:
2158*
2159*  I   - pData - pointer to the roamingMngr SM context  \n
2160*
2161* \b RETURNS:
2162*
2163*  OK if successful, NOK otherwise.
2164*
2165*
2166*/
2167static TI_STATUS roamingMngr_smStop(void *pData)
2168{
2169    roamingMngr_t       *pRoamingMngr;
2170
2171    pRoamingMngr = (roamingMngr_t*)pData;
2172    if (pRoamingMngr == NULL)
2173    {
2174        return NOK;
2175    }
2176    WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
2177                (" roamingMngr_smStop\n"));
2178
2179    scanMngr_stopContScan(pRoamingMngr->hScanMngr);
2180    /* clean intenal variables */
2181    pRoamingMngr->maskRoamingEvents = TRUE;
2182    pRoamingMngr->neighborApsExist = FALSE;
2183    pRoamingMngr->roamingTrigger = ROAMING_TRIGGER_NONE;
2184
2185    return OK;
2186}
2187/**
2188*
2189* roamingMngr_smStopWhileScanning -
2190*
2191* \b Description:
2192*
2193* Stop event means that the station is not in Connected State.
2194 * Stop continuos and immediate scans and clean internal vars.
2195*
2196* \b ARGS:
2197*
2198*  I   - pData - pointer to the roamingMngr SM context  \n
2199*
2200* \b RETURNS:
2201*
2202*  OK if successful, NOK otherwise.
2203*
2204*
2205*/
2206static TI_STATUS roamingMngr_smStopWhileScanning(void *pData)
2207{
2208    roamingMngr_t       *pRoamingMngr;
2209
2210    pRoamingMngr = (roamingMngr_t*)pData;
2211    if (pRoamingMngr == NULL)
2212    {
2213        return NOK;
2214    }
2215    WLAN_REPORT_INFORMATION(pRoamingMngr->hReport, ROAMING_MANAGER_MODULE_LOG,
2216                (" roamingMngr_smStopWhileScanning\n"));
2217
2218    scanMngr_stopImmediateScan(pRoamingMngr->hScanMngr);
2219    scanMngr_stopContScan(pRoamingMngr->hScanMngr);
2220
2221    /* clean intenal variables */
2222    pRoamingMngr->maskRoamingEvents = TRUE;
2223    pRoamingMngr->neighborApsExist = FALSE;
2224    pRoamingMngr->roamingTrigger = ROAMING_TRIGGER_NONE;
2225
2226    return OK;
2227}
2228
2229
2230#ifdef TI_DBG
2231/**
2232*
2233* roamingMngr_debugTrace
2234*
2235* \b Description:
2236*
2237* This procedure is called for debug only, to trace the roaming triggers and events
2238*
2239* \b ARGS:
2240*
2241*  I   - hRoamingMngr - roamingMngr SM context  \n
2242*
2243* \b RETURNS:
2244*
2245*  OK if successful, NOK otherwise.
2246*
2247*
2248*/
2249static void roamingMngr_printStatistics(TI_HANDLE hRoamingMngr)
2250{
2251
2252
2253    roamingMngr_t       *pRoamingMngr;
2254    UINT8               index;
2255
2256    pRoamingMngr = (roamingMngr_t*)hRoamingMngr;
2257    if (pRoamingMngr == NULL)
2258    {
2259        return;
2260    }
2261
2262    WLAN_OS_REPORT(("******** ROAMING_TRIGGERS ********\n"));
2263    for (index=ROAMING_TRIGGER_LOW_TX_RATE; index<ROAMING_TRIGGER_LAST; index++)
2264    {
2265        switch (index)
2266        {
2267        case ROAMING_TRIGGER_LOW_TX_RATE:
2268            WLAN_OS_REPORT(("- Low TX rate = %d\n",     pRoamingMngr->roamingTriggerEvents[index]));
2269            break;
2270        case ROAMING_TRIGGER_LOW_SNR:
2271            WLAN_OS_REPORT(("- Low Snr = %d\n",         pRoamingMngr->roamingTriggerEvents[index]));
2272            break;
2273        case ROAMING_TRIGGER_LOW_QUALITY:
2274            WLAN_OS_REPORT(("- Low Quality = %d\n",     pRoamingMngr->roamingTriggerEvents[index]));
2275            break;
2276        case ROAMING_TRIGGER_MAX_TX_RETRIES:
2277            WLAN_OS_REPORT(("- MAX TX retries = %d\n",  pRoamingMngr->roamingTriggerEvents[index]));
2278            break;
2279        case ROAMING_TRIGGER_BSS_LOSS:
2280            WLAN_OS_REPORT(("- BSS Loss TX = %d\n",     pRoamingMngr->roamingTriggerEvents[index]));
2281            break;
2282        case ROAMING_TRIGGER_SWITCH_CHANNEL:
2283            WLAN_OS_REPORT(("- Switch Channel = %d\n",  pRoamingMngr->roamingTriggerEvents[index]));
2284            break;
2285        case ROAMING_TRIGGER_AP_DISCONNECT:
2286            WLAN_OS_REPORT(("- AP Disconnect = %d\n",   pRoamingMngr->roamingTriggerEvents[index]));
2287            break;
2288        case ROAMING_TRIGGER_SECURITY_ATTACK:
2289            WLAN_OS_REPORT(("- SEC attack = %d\n",      pRoamingMngr->roamingTriggerEvents[index]));
2290            break;
2291        default:
2292            break;
2293        }
2294    }
2295
2296    WLAN_OS_REPORT(("******** Succ ROAMING_HANDOVERS ********\n"));
2297
2298    for (index=ROAMING_TRIGGER_LOW_QUALITY; index<ROAMING_TRIGGER_LAST; index++)
2299    {
2300        switch (index)
2301        {
2302        case ROAMING_TRIGGER_LOW_TX_RATE:
2303            WLAN_OS_REPORT(("- Low TX rate = %d\n",     pRoamingMngr->roamingHandoverEvents[index]));
2304            break;
2305        case ROAMING_TRIGGER_LOW_SNR:
2306            WLAN_OS_REPORT(("- Low Snre = %d\n",        pRoamingMngr->roamingHandoverEvents[index]));
2307            break;
2308        case ROAMING_TRIGGER_LOW_QUALITY:
2309            WLAN_OS_REPORT(("- Low Quality = %d\n",     pRoamingMngr->roamingHandoverEvents[index]));
2310            break;
2311        case ROAMING_TRIGGER_MAX_TX_RETRIES:
2312            WLAN_OS_REPORT(("- MAX TX retries = %d\n",  pRoamingMngr->roamingHandoverEvents[index]));
2313            break;
2314        case ROAMING_TRIGGER_BSS_LOSS:
2315            WLAN_OS_REPORT(("- BSS Loss TX = %d\n",     pRoamingMngr->roamingHandoverEvents[index]));
2316            break;
2317        case ROAMING_TRIGGER_SWITCH_CHANNEL:
2318            WLAN_OS_REPORT(("- Switch Channel = %d\n",   pRoamingMngr->roamingHandoverEvents[index]));
2319            break;
2320        case ROAMING_TRIGGER_AP_DISCONNECT:
2321            WLAN_OS_REPORT(("- AP Disconnect = %d\n",   pRoamingMngr->roamingHandoverEvents[index]));
2322            break;
2323        case ROAMING_TRIGGER_SECURITY_ATTACK:
2324            WLAN_OS_REPORT(("- SEC attack = %d\n",      pRoamingMngr->roamingHandoverEvents[index]));
2325            break;
2326        default:
2327            break;
2328        }
2329    }
2330
2331    WLAN_OS_REPORT(("******** ROAMING STATISTICS ********\n"));
2332    WLAN_OS_REPORT(("- Num of succesful handovers = %d\n", pRoamingMngr->roamingSuccesfulHandoverNum));
2333    WLAN_OS_REPORT(("- Num of failed handovers = %d\n", pRoamingMngr->roamingFailedHandoverNum));
2334    if (pRoamingMngr->roamingSuccesfulHandoverNum >0)
2335    {
2336        WLAN_OS_REPORT(("- Succesful average succesful handover duration = %d\n", pRoamingMngr->roamingAverageSuccHandoverDuration/pRoamingMngr->roamingSuccesfulHandoverNum));
2337        WLAN_OS_REPORT(("- Succesful average roaming duration = %d\n", pRoamingMngr->roamingAverageRoamingDuration/pRoamingMngr->roamingSuccesfulHandoverNum));
2338    }
2339
2340
2341}
2342
2343
2344/**
2345*
2346* roamingMngr_resetDebugTrace
2347*
2348* \b Description:
2349*
2350* This procedure is called for debug only, to reset Roaming debug trace
2351*
2352* \b ARGS:
2353*
2354*  I   - hRoamingMngr - roamingMngr SM context  \n
2355*
2356* \b RETURNS:
2357*
2358*  OK if successful, NOK otherwise.
2359*
2360*
2361*/
2362static void roamingMngr_resetStatistics(TI_HANDLE hRoamingMngr)
2363{
2364
2365    roamingMngr_t       *pRoamingMngr;
2366    UINT8               index;
2367
2368    pRoamingMngr = (roamingMngr_t*)hRoamingMngr;
2369    if (pRoamingMngr == NULL)
2370    {
2371        return;
2372    }
2373    WLAN_OS_REPORT(("Resetting all ROAMING_EVENTS \n"));
2374
2375    pRoamingMngr->roamingSuccesfulHandoverNum = 0;
2376    pRoamingMngr->roamingHandoverStartedTimestamp = 0;
2377    pRoamingMngr->roamingHandoverCompletedTimestamp = 0;
2378    pRoamingMngr->roamingAverageSuccHandoverDuration = 0;
2379    pRoamingMngr->roamingAverageRoamingDuration = 0;
2380    pRoamingMngr->roamingFailedHandoverNum = 0;
2381
2382    for (index=ROAMING_TRIGGER_LOW_QUALITY; index<ROAMING_TRIGGER_LAST; index++)
2383    {
2384        pRoamingMngr->roamingHandoverEvents[index] = 0;
2385        pRoamingMngr->roamingTriggerEvents[index] = 0;
2386    }
2387}
2388
2389#endif /*TI_DBG*/
2390