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