Home | History | Annotate | Download | only in Connection_Managment
      1 /*
      2  * smeSm.c
      3  *
      4  * Copyright(c) 1998 - 2010 Texas Instruments. All rights reserved.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  *
     11  *  * Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  *  * Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in
     15  *    the documentation and/or other materials provided with the
     16  *    distribution.
     17  *  * Neither the name Texas Instruments nor the names of its
     18  *    contributors may be used to endorse or promote products derived
     19  *    from this software without specific prior written permission.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     24  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     25  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32  */
     33 
     34 /** \file  smeSm.c
     35  *  \brief SME state machine implementation
     36  *
     37  *  \see   smeSm.h, sme.c, sme.h
     38  */
     39 
     40 
     41 #define __FILE_ID__  FILE_ID_43
     42 #include "GenSM.h"
     43 #include "smeSm.h"
     44 #include "smePrivate.h"
     45 #include "connApi.h"
     46 #include "apConn.h"
     47 #include "ScanCncn.h"
     48 #include "scanResultTable.h"
     49 #include "EvHandler.h"
     50 #include "regulatoryDomainApi.h"
     51 #include "siteMgrApi.h"
     52 #include "DrvMain.h"
     53 
     54 
     55 static OS_802_11_DISASSOCIATE_REASON_E eDisassocConvertTable[ MGMT_STATUS_MAX_NUM +1] =
     56 {
     57     OS_DISASSOC_STATUS_UNSPECIFIED,
     58     OS_DISASSOC_STATUS_UNSPECIFIED,
     59     OS_DISASSOC_STATUS_AUTH_REJECT,
     60     OS_DISASSOC_STATUS_ASSOC_REJECT,
     61     OS_DISASSOC_STATUS_SECURITY_FAILURE,
     62     OS_DISASSOC_STATUS_AP_DEAUTHENTICATE,
     63     OS_DISASSOC_STATUS_AP_DISASSOCIATE,
     64     OS_DISASSOC_STATUS_ROAMING_TRIGGER,
     65     OS_DISASSOC_STATUS_UNSPECIFIED,
     66     OS_DISASSOC_STATUS_UNSPECIFIED,
     67     OS_DISASSOC_STATUS_UNSPECIFIED,
     68     OS_DISASSOC_STATUS_UNSPECIFIED,
     69     OS_DISASSOC_STATUS_UNSPECIFIED,
     70     OS_DISASSOC_STATUS_UNSPECIFIED,
     71     OS_DISASSOC_STATUS_UNSPECIFIED,
     72     OS_DISASSOC_STATUS_UNSPECIFIED
     73 };
     74 
     75 #define SME_CONVERT_DISASSOC_CODES(disassocReason)     (eDisassocConvertTable[ (disassocReason) ])
     76 
     77 static void smeSm_Start (TI_HANDLE hSme);
     78 static void smeSm_Stop (TI_HANDLE hSme);
     79 static void smeSm_PreConnect (TI_HANDLE hSme);
     80 static void smeSm_Connect (TI_HANDLE hSme);
     81 static void smeSm_ConnectSuccess (TI_HANDLE hSme);
     82 static void smeSm_Disconnect (TI_HANDLE hSme);
     83 static void smeSm_DisconnectDone (TI_HANDLE hSme);
     84 static void smeSm_StopScan (TI_HANDLE hSme);
     85 static void smeSm_StopConnect (TI_HANDLE hSme);
     86 static void smeSm_ConnWhenConnecting (TI_HANDLE hSme);
     87 static void smeSm_ActionUnexpected (TI_HANDLE hSme);
     88 static void smeSm_NopAction (TI_HANDLE hSme);
     89 static void smeSm_CheckStartConditions (TI_HANDLE hSme);
     90 
     91 static TI_STATUS sme_StartScan (TI_HANDLE hSme);
     92 static void sme_updateScanCycles (TI_HANDLE hSme,
     93                                   TI_BOOL bDEnabled,
     94                                   TI_BOOL bCountryValid,
     95                                   TI_BOOL bConstantScan);
     96 static void sme_CalculateCyclesNumber (TI_HANDLE hSme, TI_UINT32 uTotalTimeMs);
     97 
     98 TGenSM_actionCell tSmMatrix[ SME_SM_NUMBER_OF_STATES ][ SME_SM_NUMBER_OF_EVENTS ] =
     99     {
    100         { /* SME_SM_STATE_IDLE */
    101             { SME_SM_STATE_WAIT_CONNECT, smeSm_Start },             /* SME_SM_EVENT_START */
    102             { SME_SM_STATE_IDLE, smeSm_ActionUnexpected },          /* SME_SM_EVENT_STOP */
    103             { SME_SM_STATE_IDLE, smeSm_ActionUnexpected },          /* SME_SM_EVENT_CONNECT */
    104             { SME_SM_STATE_IDLE, smeSm_ActionUnexpected },          /* SME_SM_EVENT_CONNECT_SUCCESS */
    105             { SME_SM_STATE_IDLE, smeSm_ActionUnexpected },          /* SME_SM_EVENT_CONNECT_FAILURE */
    106             { SME_SM_STATE_IDLE, smeSm_CheckStartConditions },          /* SME_SM_EVENT_DISCONNECT */
    107         },
    108         { /* SME_SM_STATE_WAIT_CONNECT */
    109             { SME_SM_STATE_WAIT_CONNECT, smeSm_ActionUnexpected },  /* SME_SM_EVENT_START */
    110             { SME_SM_STATE_IDLE, smeSm_Stop },                      /* SME_SM_EVENT_STOP */
    111             { SME_SM_STATE_SCANNING, smeSm_PreConnect },            /* SME_SM_EVENT_CONNECT */
    112             { SME_SM_STATE_WAIT_CONNECT, smeSm_ActionUnexpected },  /* SME_SM_EVENT_CONNECT_SUCCESS */
    113             { SME_SM_STATE_WAIT_CONNECT, smeSm_ActionUnexpected },  /* SME_SM_EVENT_CONNECT_FAILURE */
    114             { SME_SM_STATE_WAIT_CONNECT, smeSm_Start },             /* SME_SM_EVENT_DISCONNECT */
    115         },
    116         { /* SME_SM_STATE_SCANNING */
    117             { SME_SM_STATE_SCANNING, smeSm_ActionUnexpected },      /* SME_SM_EVENT_START */
    118             { SME_SM_STATE_DISCONNECTING, smeSm_StopScan },         /* SME_SM_EVENT_STOP */
    119             { SME_SM_STATE_CONNECTING, smeSm_Connect },             /* SME_SM_EVENT_CONNECT */
    120             { SME_SM_STATE_SCANNING, smeSm_ActionUnexpected },      /* SME_SM_EVENT_CONNECT_SUCCESS */
    121             { SME_SM_STATE_WAIT_CONNECT, smeSm_DisconnectDone },    /* SME_SM_EVENT_CONNECT_FAILURE */
    122             { SME_SM_STATE_DISCONNECTING, smeSm_StopScan },         /* SME_SM_EVENT_DISCONNECT */
    123         },
    124         { /* SME_SM_STATE_CONNECTING */
    125             { SME_SM_STATE_CONNECTING, smeSm_ActionUnexpected },    /* SME_SM_EVENT_START */
    126             { SME_SM_STATE_DISCONNECTING, smeSm_StopConnect },      /* SME_SM_EVENT_STOP */
    127             { SME_SM_STATE_CONNECTING, smeSm_ConnWhenConnecting },  /* SME_SM_EVENT_CONNECT */
    128             { SME_SM_STATE_CONNECTED, smeSm_ConnectSuccess },       /* SME_SM_EVENT_CONNECT_SUCCESS */
    129             { SME_SM_STATE_WAIT_CONNECT, smeSm_DisconnectDone },    /* SME_SM_EVENT_CONNECT_FAILURE */
    130             { SME_SM_STATE_DISCONNECTING, smeSm_StopConnect },      /* SME_SM_EVENT_DISCONNECT */
    131         },
    132         { /* SME_SM_STATE_CONNECTED */
    133             { SME_SM_STATE_CONNECTED, smeSm_ActionUnexpected },     /* SME_SM_EVENT_START */
    134             { SME_SM_STATE_DISCONNECTING, smeSm_Disconnect },       /* SME_SM_EVENT_STOP */
    135             { SME_SM_STATE_CONNECTED, smeSm_ActionUnexpected },     /* SME_SM_EVENT_CONNECT */
    136             { SME_SM_STATE_CONNECTED, smeSm_ActionUnexpected },     /* SME_SM_EVENT_CONNECT_SUCCESS */
    137             { SME_SM_STATE_WAIT_CONNECT, smeSm_DisconnectDone },    /* SME_SM_EVENT_CONNECT_FAILURE */
    138             { SME_SM_STATE_DISCONNECTING, smeSm_Disconnect },       /* SME_SM_EVENT_DISCONNECT */
    139         },
    140         { /* SME_SM_STATE_DISCONNECTING */
    141             { SME_SM_STATE_DISCONNECTING, smeSm_ActionUnexpected }, /* SME_SM_EVENT_START */
    142             { SME_SM_STATE_DISCONNECTING, smeSm_ActionUnexpected }, /* SME_SM_EVENT_STOP */
    143             { SME_SM_STATE_DISCONNECTING, smeSm_ActionUnexpected }, /* SME_SM_EVENT_CONNECT */
    144             { SME_SM_STATE_DISCONNECTING, smeSm_ActionUnexpected }, /* SME_SM_EVENT_CONNECT_SUCCESS */
    145             { SME_SM_STATE_WAIT_CONNECT, smeSm_DisconnectDone },    /* SME_SM_EVENT_CONNECT_FAILURE */
    146             { SME_SM_STATE_DISCONNECTING, smeSm_NopAction }, /* SME_SM_EVENT_DISCONNECT */
    147         }
    148     };
    149 
    150 TI_INT8*  uStateDescription[] =
    151     {
    152         "IDLE",
    153         "WAIT_CONNECT",
    154         "SCANNING",
    155         "CONNECTING",
    156         "CONNECTED",
    157         "DISCONNECTING"
    158     };
    159 
    160 TI_INT8*  uEventDescription[] =
    161     {
    162         "START",
    163         "STOP",
    164         "CONNECT",
    165         "CONNECT_SUCCESS",
    166         "CONNECT_FAILURE",
    167         "DISCONNECT"
    168     };
    169 
    170 /**
    171  * \fn     smeSm_Start
    172  * \brief  Starts STA opeartion by moving SCR out of idle group and starting connection process
    173  *
    174  * Starts STA opeartion by moving SCR out of idle group and starting connection process
    175  *
    176  * \param  hSme - handle to the SME object
    177  * \return None
    178  * \sa     smeSm_Stop, sme_start
    179  */
    180 void smeSm_Start (TI_HANDLE hSme)
    181 {
    182     TSme    *pSme = (TSme*)hSme;
    183 
    184     /* set SCR group according to connection mode */
    185     if (CONNECT_MODE_AUTO == pSme->eConnectMode)
    186     {
    187         TRACE0(pSme->hReport, REPORT_SEVERITY_INFORMATION , "smeSm_Start: changing SCR group to DRV scan\n");
    188         scr_setGroup (pSme->hScr, SCR_GID_DRV_SCAN);
    189     }
    190     else
    191     {
    192         TRACE0(pSme->hReport, REPORT_SEVERITY_INFORMATION , "smeSm_Start: changing SCR group to APP scan\n");
    193         scr_setGroup (pSme->hScr, SCR_GID_APP_SCAN);
    194     }
    195 
    196     if ((TI_FALSE == pSme->bRadioOn) || (TI_FALSE == pSme->bRunning))
    197     {
    198         /* Radio is off so send stop event */
    199         sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_STOP, hSme);
    200     }
    201     else if (TI_TRUE == pSme->bConnectRequired)
    202     {
    203         /* if connection was required, start the process */
    204         sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_CONNECT, hSme);
    205     }
    206 }
    207 
    208 /**
    209  * \fn     smeSm_Stop
    210  * \brief  Turns off the STA
    211  *
    212  * Turns off the STA by moving the SCr to idle
    213  *
    214  * \param  hSme - handle to the SME object
    215  * \return None
    216  * \sa     smeSm_Start, sme_Stop
    217  */
    218 void smeSm_Stop (TI_HANDLE hSme)
    219 {
    220     TSme    *pSme = (TSme*)hSme;
    221 
    222     /* set SCR group to idle */
    223     scr_setGroup (pSme->hScr, SCR_GID_IDLE);
    224 
    225     if (TI_FALSE == pSme->bRunning)
    226     {
    227         /* call DrvMain */
    228         drvMain_SmeStop (pSme->hDrvMain);
    229     }
    230 }
    231 
    232 /**
    233  * \fn     smeSm_PreConnect
    234  * \brief  Initiates the connection process
    235  *
    236  * Initiates the connection process - for automatic mode, start scan, for manual mode - triggers connection
    237  *
    238  * \param  hSme - handle to the SME object
    239  * \return None
    240  * \sa     smeSm_Connect, smeSm_ConnectSuccess
    241  */
    242 void smeSm_PreConnect (TI_HANDLE hSme)
    243 {
    244     TSme *pSme = (TSme *)hSme;
    245     paramInfo_t	*pParam;
    246 
    247     /* set the connection mode with which this connection attempt is starting */
    248     pSme->eLastConnectMode = pSme->eConnectMode;
    249 
    250     /* mark that no authentication/assocaition was yet sent */
    251     pSme->bAuthSent = TI_FALSE;
    252 
    253     /* try to find a connection candidate (manual mode have already performed scann */
    254     pSme->pCandidate = sme_Select (hSme);
    255     if (NULL != pSme->pCandidate)
    256     {
    257         /* candidate is available - attempt connection */
    258         sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_CONNECT, hSme);
    259     }
    260     /* no candidate */
    261     else
    262     {
    263         if (CONNECT_MODE_AUTO == pSme->eConnectMode)
    264         {
    265             /* automatic mode - start scanning */
    266             if (TI_OK != sme_StartScan (hSme))
    267             {
    268                 TRACE0(pSme->hReport, REPORT_SEVERITY_ERROR , "smeSm_PreConnect: unable to start scan, stopping the SME\n");
    269                 pSme->bRadioOn = TI_FALSE;
    270                 sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_CONNECT_FAILURE, hSme);
    271             }
    272 
    273             /* update scan count counter */
    274             if(pSme->uScanCount < PERIODIC_SCAN_MAX_INTERVAL_NUM)
    275             {
    276                 pSme->uScanCount++;
    277             }
    278 
    279         }
    280         else		/* Manual mode */
    281         {
    282 			/* for IBSS or any, if no entries where found, add the self site */
    283 			if (pSme->eBssType == BSS_INFRASTRUCTURE)
    284             {
    285                 /* makr whether we need to stop the attempt connection in manual mode */
    286                 pSme->bConnectRequired = TI_FALSE;
    287 
    288 				TRACE0(pSme->hReport, REPORT_SEVERITY_INFORMATION , "smeSm_PreConnect: No candidate available, sending connect failure\n");
    289                 /* manual mode and no connection candidate is available - connection failed */
    290                 sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_CONNECT_FAILURE, hSme);
    291 			}
    292 
    293 			else		/* IBSS */
    294 			{
    295 				TI_UINT8    uDesiredChannel;
    296                 TI_BOOL     channelValidity;
    297 
    298 		        pSme->bConnectRequired = TI_FALSE;
    299 
    300                 pParam = (paramInfo_t *)os_memoryAlloc(pSme->hOS, sizeof(paramInfo_t));
    301                 if (!pParam)
    302                 {
    303                     return;
    304                 }
    305 
    306 				pParam->paramType = SITE_MGR_DESIRED_CHANNEL_PARAM;
    307 				siteMgr_getParam(pSme->hSiteMgr, pParam);
    308 				uDesiredChannel = pParam->content.siteMgrDesiredChannel;
    309 
    310 				if (uDesiredChannel >= SITE_MGR_CHANNEL_A_MIN)
    311 				{
    312 				   pParam->content.channelCapabilityReq.band = RADIO_BAND_5_0_GHZ;
    313 				}
    314 				else
    315 				{
    316 				   pParam->content.channelCapabilityReq.band = RADIO_BAND_2_4_GHZ;
    317 				}
    318 
    319 				/*
    320 				update the regulatory domain with the selected band
    321 				*/
    322 				/* Check if the selected channel is valid according to regDomain */
    323 				pParam->paramType = REGULATORY_DOMAIN_GET_SCAN_CAPABILITIES;
    324 				pParam->content.channelCapabilityReq.scanOption = ACTIVE_SCANNING;
    325 				pParam->content.channelCapabilityReq.channelNum = uDesiredChannel;
    326 
    327 				regulatoryDomain_getParam (pSme->hRegDomain, pParam);
    328                 channelValidity = pParam->content.channelCapabilityRet.channelValidity;
    329                 os_memoryFree(pSme->hOS, pParam, sizeof(paramInfo_t));
    330 				if (!channelValidity)
    331 				{
    332 				   TRACE0(pSme->hReport, REPORT_SEVERITY_INFORMATION , "IBSS SELECT FAILURE  - No channel !!!\n\n");
    333 
    334 				   sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_CONNECT_FAILURE, hSme);
    335 
    336 				   return;
    337 				}
    338 
    339 				pSme->pCandidate = (TSiteEntry *)addSelfSite(pSme->hSiteMgr);
    340 
    341 				if (pSme->pCandidate == NULL)
    342 				{
    343 				   TRACE0(pSme->hReport, REPORT_SEVERITY_ERROR , "IBSS SELECT FAILURE  - could not open self site !!!\n\n");
    344 
    345 				   sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_CONNECT_FAILURE, hSme);
    346 
    347 				   return;
    348 				}
    349 
    350 #ifdef REPORT_LOG
    351 				TRACE6(pSme->hReport, REPORT_SEVERITY_CONSOLE,"%%%%%%%%%%%%%%	SELF SELECT SUCCESS, bssid: %X-%X-%X-%X-%X-%X	%%%%%%%%%%%%%%\n\n", pSme->pCandidate->bssid[0], pSme->pCandidate->bssid[1], pSme->pCandidate->bssid[2], pSme->pCandidate->bssid[3], pSme->pCandidate->bssid[4], pSme->pCandidate->bssid[5]);
    352                 WLAN_OS_REPORT (("%%%%%%%%%%%%%%	SELF SELECT SUCCESS, bssid: %02x.%02x.%02x.%02x.%02x.%02x %%%%%%%%%%%%%%\n\n", pSme->pCandidate->bssid[0], pSme->pCandidate->bssid[1], pSme->pCandidate->bssid[2], pSme->pCandidate->bssid[3], pSme->pCandidate->bssid[4], pSme->pCandidate->bssid[5]));
    353 #endif
    354 				/* a connection candidate is available, send a connect event */
    355 				sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_CONNECT, hSme);
    356 			}
    357         }
    358     }
    359 }
    360 
    361 /**
    362  * \fn     smeSm_Connect
    363  * \brief  Starts a connection process with the selected network
    364  *
    365  * Starts a connection process with the selected network
    366  *
    367  * \param  hSme - handle to the SME object
    368  * \return None
    369  * \sa     smeSm_PreConnect, smeSm_ConnectSuccess
    370  */
    371 void smeSm_Connect (TI_HANDLE hSme)
    372 {
    373     TSme            *pSme = (TSme*)hSme;
    374     TI_STATUS       tStatus;
    375     paramInfo_t     *pParam;
    376 
    377     /* Sanity check - if no connection candidate was found so far */
    378     if (NULL == pSme->pCandidate)
    379     {
    380         TRACE0(pSme->hReport, REPORT_SEVERITY_ERROR , "smeSm_Connect: No candidate available, sending connect failure\n");
    381         sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_CONNECT_FAILURE, hSme);
    382     }
    383     else
    384     {
    385         pParam = (paramInfo_t *)os_memoryAlloc(pSme->hOS, sizeof(paramInfo_t));
    386         if (!pParam)
    387         {
    388             return;
    389         }
    390 
    391        /* set SCR group */
    392        if (BSS_INFRASTRUCTURE == pSme->pCandidate->bssType)
    393        {
    394            scr_setGroup (pSme->hScr, SCR_GID_CONNECT);
    395        }
    396 
    397        /***************** Config Connection *************************/
    398        pParam->paramType = CONN_TYPE_PARAM;
    399        if (BSS_INDEPENDENT == pSme->pCandidate->bssType)
    400            if (SITE_SELF == pSme->pCandidate->siteType)
    401            {
    402                pParam->content.connType = CONNECTION_SELF;
    403            }
    404            else
    405            {
    406                pParam->content.connType = CONNECTION_IBSS;
    407            }
    408        else
    409            pParam->content.connType = CONNECTION_INFRA;
    410        conn_setParam(pSme->hConn, pParam);
    411        os_memoryFree(pSme->hOS, pParam, sizeof(paramInfo_t));
    412 
    413        /* start the connection process */
    414        tStatus = conn_start (pSme->hConn, CONN_TYPE_FIRST_CONN, sme_ReportConnStatus, hSme, TI_FALSE, TI_FALSE);
    415        if (TI_OK != tStatus)
    416        {
    417            TRACE1(pSme->hReport, REPORT_SEVERITY_ERROR , "smeSm_Connect: conn_start returned status %d\n", tStatus);
    418        }
    419     }
    420 }
    421 
    422 /**
    423  * \fn     smeSm_ConnectSuccess
    424  * \brief  Handles connection success indication
    425  *
    426  * Handles connection success indication - starts AP conn and set SCR group to connected
    427  *
    428  * \param  hSme - handle to the SME object
    429  * \return None
    430  * \sa     smeSm_PreConnect, smeSm_Connect
    431  */
    432 void smeSm_ConnectSuccess (TI_HANDLE hSme)
    433 {
    434     TSme        *pSme = (TSme*)hSme;
    435 
    436     pSme->uScanCount = 0;
    437 
    438     /* connection succedded to the connection candidate - start AP connection */
    439     if (BSS_INFRASTRUCTURE == pSme->pCandidate->bssType)
    440     {
    441         /* Start the AP connection */
    442         apConn_start (pSme->hApConn,
    443                       (pSme->tSsid.len != 0) && !OS_802_11_SSID_JUNK (pSme->tSsid.str, pSme->tSsid.len));
    444     }
    445 
    446     /* Set SCR group to connected */
    447     scr_setGroup (pSme->hScr, SCR_GID_CONNECTED);
    448 }
    449 
    450 /**
    451  * \fn     smeSm_Disconnect
    452  * \brief  Starts a disconnect by calling the AP connection or connect modules
    453  *
    454  * Starts a disconnect by calling the AP connection or connect modules
    455  *
    456  * \param  hSme - handle to the SME object
    457  * \return None
    458  * \sa     smeSm_DisconnectDone
    459  */
    460 void smeSm_Disconnect (TI_HANDLE hSme)
    461 {
    462     TSme        *pSme = (TSme*)hSme;
    463     TI_STATUS   tStatus;
    464 
    465     /* set the SCr group to connecting */
    466     scr_setGroup (pSme->hScr, SCR_GID_CONNECT);
    467 
    468     if (BSS_INFRASTRUCTURE == pSme->pCandidate->bssType)
    469     {
    470 		 /* Call the AP connection to perform disconnect */
    471 		 tStatus = apConn_stop (pSme->hApConn, TI_TRUE);
    472 	}
    473 	else
    474 	{
    475 	    /* In IBSS disconnect is done directly with the connection SM */
    476 		tStatus = conn_stop(pSme->hConn, DISCONNECT_DE_AUTH, STATUS_UNSPECIFIED,
    477 						   TI_TRUE, sme_ReportConnStatus, hSme);
    478 		if (tStatus != TI_OK)
    479 		{
    480 TRACE1(pSme->hReport, REPORT_SEVERITY_ERROR , "smeSm_Disconnect: conn_stop retruned %d\n", tStatus);
    481 		}
    482     }
    483 }
    484 
    485 /**
    486  * \fn     smeSm_DisconnectDone
    487  * \brief  Finish a disconnect process
    488  *
    489  * Finish a disconnect process by sending the appropriate event and restarting the state-machine
    490  *
    491  * \param  hSme - handle to the SME object
    492  * \return None
    493  * \sa     smeSm_Disconnect
    494  */
    495 void smeSm_DisconnectDone (TI_HANDLE hSme)
    496 {
    497     TSme        *pSme = (TSme*)hSme;
    498     OS_802_11_DISASSOCIATE_REASON_T	    tEventReason;
    499 
    500     if (TI_FALSE == pSme->bReselect)
    501     {
    502         /* send an event notifying the disassocation */
    503         if (TI_TRUE == pSme->bAuthSent)
    504         {
    505             tEventReason.eDisAssocType = SME_CONVERT_DISASSOC_CODES (pSme->tDisAssoc.eMgmtStatus);
    506             tEventReason.uStatusCode = pSme->tDisAssoc.uStatusCode;
    507             EvHandlerSendEvent (pSme->hEvHandler, IPC_EVENT_DISASSOCIATED, (TI_UINT8*)&tEventReason,
    508                                 sizeof(OS_802_11_DISASSOCIATE_REASON_T));
    509         }
    510         else if (CONNECT_MODE_AUTO != pSme->eLastConnectMode)
    511         {
    512             EvHandlerSendEvent (pSme->hEvHandler, IPC_EVENT_NOT_ASSOCIATED, NULL, 0);
    513         }
    514     }
    515 
    516     siteMgr_disSelectSite (pSme->hSiteMgr);
    517 
    518     /* try to reconnect */
    519     smeSm_Start (hSme);
    520 }
    521 
    522 /**
    523  * \fn     smeSm_StopScan
    524  * \brief  Stops the SME scan operation
    525  *
    526  * Stops the SME scan operation
    527  *
    528  * \param  hSme - handle to the SME object
    529  * \return None
    530  * \sa     smeSm_PreConnect, sme_StartScan
    531  */
    532 void smeSm_StopScan (TI_HANDLE hSme)
    533 {
    534     TSme        *pSme = (TSme*)hSme;
    535 
    536     scanCncn_StopPeriodicScan (pSme->hScanCncn, SCAN_SCC_DRIVER);
    537 }
    538 
    539 /**
    540  * \fn     smeSm_StopConnect
    541  * \brief  Stops the connect module
    542  *
    543  * Stops the connect module (if the SME is stopped during a connect attempt
    544  *
    545  * \param  hSme - handle to the SME object
    546  * \return None
    547  * \sa     smeSm_Connect
    548  */
    549 void smeSm_StopConnect (TI_HANDLE hSme)
    550 {
    551     TSme        *pSme = (TSme*)hSme;
    552     TI_STATUS   tStatus;
    553 
    554     tStatus = conn_stop (pSme->hConn, DISCONNECT_DE_AUTH, STATUS_UNSPECIFIED,
    555                          TI_TRUE, sme_ReportConnStatus, hSme);
    556 
    557     if (TI_OK != tStatus)
    558     {
    559         TRACE1(pSme->hReport, REPORT_SEVERITY_ERROR , "smeSm_StopConnect: conn_stop returned status %d\n", tStatus);
    560     }
    561 }
    562 
    563 /**
    564  * \fn     smeSm_ConnWhenConnecting
    565  * \brief  Starts the connect process again
    566  *
    567  * Starts the connect process again
    568  *
    569  * \param  hSme - handle to the SME object
    570  * \return None
    571  * \sa     smeSm_Connect
    572  */
    573 void smeSm_ConnWhenConnecting (TI_HANDLE hSme)
    574 {
    575     TSme        *pSme = (TSme*)hSme;
    576     TI_STATUS   tStatus;
    577 
    578     /* start the connection process */
    579     tStatus = conn_start (pSme->hConn, CONN_TYPE_FIRST_CONN, sme_ReportConnStatus, hSme, TI_FALSE, TI_FALSE);
    580     if (TI_OK != tStatus)
    581     {
    582         TRACE1(pSme->hReport, REPORT_SEVERITY_ERROR , "smeSm_ConnWhenConnecting: conn_start returned status %d\n", tStatus);
    583     }
    584 }
    585 
    586 /**
    587  * \fn     smeSm_ActionUnexpected
    588  * \brief  Called when an unexpected event (for current state) is received
    589  *
    590  * Called when an unexpected event (for current state) is received
    591  *
    592  * \param  hSme - handle to the SME object
    593  * \return None
    594  */
    595 void smeSm_ActionUnexpected (TI_HANDLE hSme)
    596 {
    597     TSme        *pSme = (TSme*)hSme;
    598 
    599     TRACE0(pSme->hReport, REPORT_SEVERITY_ERROR , "smeSm_ActionUnexpected called\n");
    600 }
    601 
    602 /**
    603  * \fn     smeSm_NopAction
    604  * \brief  Called when event call and don't need to do nothing.
    605  *
    606  * \param  hSme - handle to the SME object
    607  * \return None
    608  */
    609 void smeSm_NopAction (TI_HANDLE hSme)
    610 {
    611     TSme        *pSme = (TSme*)hSme;
    612 
    613     TRACE0(pSme->hReport, REPORT_SEVERITY_INFORMATION , "smeSm_NopAction called\n");
    614 }
    615 
    616 void smeSm_CheckStartConditions (TI_HANDLE hSme)
    617 {
    618     TSme        *pSme = (TSme*)hSme;
    619 
    620     if ((TI_TRUE == pSme->bRunning) && (TI_TRUE == pSme->bRadioOn))
    621     {
    622         /* send a start event */
    623         sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_START, hSme);
    624     }
    625 }
    626 
    627 
    628 /* do we need to verify G only / A only / dual-band with site mgr? or rely on channels only? */
    629 
    630 /**
    631  * \fn     sme_StartScan
    632  * \brief  Set scan parameters and calls scan concnetartor to start the scan operation.
    633  *
    634  * Set scan parameters and calls scan concnetartor to start the scan operation.
    635  *
    636  * Scan parameters are set according to scan target - find country IE, find desired SSID, or both
    637  * (one on each band). To find country IE we use passive scan forever, to find the desired SSID we
    638  * use active scan until the current country IE expires. In addition, we take into account the WSC PB
    639  * mode - scan constantly for two minutes (but under the country validity and expiry constraints)
    640  *
    641  * \param  hSme - handle to the SME object
    642  * \return TI_OK if scan started successfully, TI_NOK otherwise
    643  * \sa     smeSm_PreConnect
    644  */
    645 TI_STATUS sme_StartScan (TI_HANDLE hSme)
    646 {
    647     TSme            *pSme = (TSme*)hSme;
    648     paramInfo_t     *pParam;
    649     TI_BOOL         bDEnabled, bCountryValid;
    650     TI_BOOL         bBandChannelExist[ RADIO_BAND_NUM_OF_BANDS ];
    651     TI_BOOL         bBandCountryFound[ RADIO_BAND_NUM_OF_BANDS ];
    652     TI_STATUS       tStatus;
    653     TI_UINT32       uIndex;
    654 
    655     /* get 802.11d enable state */
    656     pParam = (paramInfo_t *)os_memoryAlloc(pSme->hOS, sizeof(paramInfo_t));
    657     if (!pParam)
    658     {
    659         return TI_NOK;
    660     }
    661 
    662     pParam->paramType = REGULATORY_DOMAIN_ENABLED_PARAM;
    663     regulatoryDomain_getParam (pSme->hRegDomain, pParam);
    664     bDEnabled = pParam->content.regulatoryDomainEnabled;
    665 
    666     pParam->paramType = REGULATORY_DOMAIN_IS_COUNTRY_FOUND;
    667     /* get country validity for all bands */
    668     for (uIndex = 0; uIndex < RADIO_BAND_NUM_OF_BANDS; uIndex++)
    669     {
    670         pParam->content.eRadioBand = (ERadioBand)uIndex;
    671         regulatoryDomain_getParam (pSme->hRegDomain, pParam);
    672         bBandCountryFound[ uIndex ] = pParam->content.bIsCountryFound;
    673         /* also nullify the channel exist indication for this band */
    674         bBandChannelExist[ uIndex ] = TI_FALSE;
    675     }
    676     os_memoryFree(pSme->hOS, pParam, sizeof(paramInfo_t));
    677 
    678     /* First fill the channels */
    679     for (uIndex = 0; uIndex < pSme->tInitParams.uChannelNum; uIndex++)
    680     {
    681         /* for each channel, if country is found, set active scan */
    682         pSme->tScanParams.tChannels[ uIndex ].eBand = pSme->tInitParams.tChannelList[ uIndex ].eBand;
    683         pSme->tScanParams.tChannels[ uIndex ].uChannel = pSme->tInitParams.tChannelList[ uIndex ].uChannel;
    684         pSme->tScanParams.tChannels[ uIndex ].uMaxDwellTimeMs = pSme->tInitParams.uMaxScanDuration;
    685         pSme->tScanParams.tChannels[ uIndex ].uMinDwellTimeMs = pSme->tInitParams.uMinScanDuration;
    686         pSme->tScanParams.tChannels[ uIndex ].uTxPowerLevelDbm = DEF_TX_POWER;
    687 
    688         /* if 802.11d is disabled, or country is available for this band */
    689         if ((TI_FALSE == bDEnabled) ||
    690             (TI_TRUE == bBandCountryFound[ pSme->tInitParams.tChannelList[ uIndex ].eBand ]))
    691         {
    692             /* set active scan */
    693             pSme->tScanParams.tChannels[ uIndex ].eScanType = SCAN_TYPE_NORMAL_ACTIVE;
    694         }
    695         /* 802.11d is enabled and no country available */
    696         else
    697         {
    698             /* set passive scan */
    699             pSme->tScanParams.tChannels[ uIndex ].eScanType = SCAN_TYPE_NORMAL_PASSIVE;
    700 
    701             /*
    702              * in order to fined country set uMaxDwellTimeMs ( that at passive scan set the passiveScanDuration )
    703              * to significant value
    704              */
    705             pSme->tScanParams.tChannels[ uIndex ].uMaxDwellTimeMs = SCAN_CNCN_REGULATORY_DOMAIN_PASSIVE_DWELL_TIME_DEF;
    706         }
    707         /* mark that a channel exists for this band */
    708         bBandChannelExist[ pSme->tInitParams.tChannelList[ uIndex ].eBand ] = TI_TRUE;
    709     }
    710     /* set number of channels */
    711     pSme->tScanParams.uChannelNum = pSme->tInitParams.uChannelNum;
    712 
    713     /* now, fill global parameters */
    714     pSme->tScanParams.uProbeRequestNum = pSme->tInitParams.uProbeReqNum;
    715     pSme->tScanParams.iRssiThreshold = pSme->tInitParams.iRssiThreshold;
    716     pSme->tScanParams.iSnrThreshold = pSme->tInitParams.iSnrThreshold;
    717     pSme->tScanParams.bTerminateOnReport = TI_TRUE;
    718     pSme->tScanParams.uFrameCountReportThreshold = 1;
    719 
    720     /*
    721      * if for at least one band country is known and scan is performed on this band - means we need to
    722      * take into consideration country expiry, plus we are scanning for the desired SSID
    723      */
    724     bCountryValid = ((TI_TRUE == bBandChannelExist[ RADIO_BAND_2_4_GHZ ]) && (TI_TRUE == bBandCountryFound[ RADIO_BAND_2_4_GHZ ])) ||
    725                     ((TI_TRUE == bBandChannelExist[ RADIO_BAND_5_0_GHZ ]) && (TI_TRUE == bBandCountryFound[ RADIO_BAND_5_0_GHZ ]));
    726 
    727     /* set SSID(s) and BSS type according to 802.11d status, and country availability */
    728     /* if 802.11d is disabled */
    729     if (TI_FALSE == bDEnabled)
    730     {
    731         pSme->tScanParams.eBssType = pSme->eBssType;
    732         /* set the deisred SSID, or any SSID if this is the desired SSID */
    733         if (SSID_TYPE_ANY == pSme->eSsidType)
    734         {
    735             pSme->tScanParams.uSsidNum = 0;
    736             pSme->tScanParams.uSsidListFilterEnabled = 1;
    737         }
    738         else
    739         {
    740             pSme->tScanParams.tDesiredSsid[ 0 ].eVisability = SCAN_SSID_VISABILITY_HIDDEN;
    741             os_memoryCopy (pSme->hOS, &(pSme->tScanParams.tDesiredSsid[ 0 ].tSsid), &(pSme->tSsid), sizeof (TSsid));
    742             pSme->tScanParams.uSsidNum = 1;
    743             pSme->tScanParams.uSsidListFilterEnabled = 1;
    744 
    745 #ifdef XCC_MODULE_INCLUDED
    746             pSme->tScanParams.uSsidListFilterEnabled = (TI_UINT8)TI_FALSE;
    747             pSme->tScanParams.uSsidNum = 2;
    748             pSme->tScanParams.tDesiredSsid[ 1 ].tSsid.len = 0;
    749             pSme->tScanParams.tDesiredSsid[ 1 ].eVisability =  SCAN_SSID_VISABILITY_PUBLIC;
    750 #endif
    751 
    752         }
    753     }
    754     /* Country code exists and scan is performed on this band - take country expiry timr into account */
    755     else if (TI_TRUE == bCountryValid)
    756     {
    757         TRACE0(pSme->hReport, REPORT_SEVERITY_INFORMATION , "sme_StartScan: performing active scan to find desired SSID\n");
    758 
    759         /* we already know that at least on one band we know the country IE, so we scan for our SSID */
    760         pSme->tScanParams.tDesiredSsid[ 0 ].eVisability = SCAN_SSID_VISABILITY_HIDDEN;
    761         os_memoryCopy (pSme->hOS, &(pSme->tScanParams.tDesiredSsid[ 0 ].tSsid), &(pSme->tSsid), sizeof (TSsid));
    762         /*
    763          * if, in addition, we scan the other band to find its country, and the desired SSDI is not any SSID,
    764          * add an empty SSID
    765          */
    766         if ((SSID_TYPE_ANY != pSme->eSsidType) &&
    767             (((TI_TRUE == bBandChannelExist[ RADIO_BAND_2_4_GHZ ]) && (TI_FALSE == bBandCountryFound[ RADIO_BAND_2_4_GHZ ])) ||
    768              ((TI_TRUE == bBandChannelExist[ RADIO_BAND_5_0_GHZ ]) && (TI_FALSE == bBandCountryFound[ RADIO_BAND_5_0_GHZ ]))))
    769         {
    770             pSme->tScanParams.tDesiredSsid[ 1 ].eVisability = SCAN_SSID_VISABILITY_PUBLIC;
    771             pSme->tScanParams.tDesiredSsid[ 1 ].tSsid.len = 0;
    772             pSme->tScanParams.uSsidNum = 2;
    773             pSme->tScanParams.uSsidListFilterEnabled = 1;
    774             /*
    775              * since we are also looking for an AP with country IE (not include in IBSS), we need to make sure
    776              * the desired BSS type include infrastructure BSSes.
    777              */
    778             if (BSS_INDEPENDENT == pSme->eBssType)
    779             {
    780                 /* the desired is only IBSS - scan for any */
    781                 pSme->tScanParams.eBssType = BSS_ANY;
    782             }
    783             else
    784             {
    785                 /* the desired is either infrastructure or any - use it */
    786                 pSme->tScanParams.eBssType = pSme->eBssType;
    787             }
    788         }
    789         else
    790         {
    791             pSme->tScanParams.uSsidNum = 1;
    792             pSme->tScanParams.uSsidListFilterEnabled = 1;
    793             /* only looking for the desired SSID - set the desired BSS type */
    794             pSme->tScanParams.eBssType = pSme->eBssType;
    795         }
    796     }
    797     /* no scanned band has a counrty code - meaning all scan is passive (to find country) */
    798     else
    799     {
    800         TRACE0(pSme->hReport, REPORT_SEVERITY_INFORMATION , "sme_StartScan: performing passive scan to find country IE\n");
    801         pSme->tScanParams.eBssType = BSS_INFRASTRUCTURE; /* only an AP would transmit a country IE */
    802         pSme->tScanParams.uSsidNum = 0;
    803         pSme->tScanParams.uSsidListFilterEnabled = 1;
    804     }
    805 
    806     /* update scan cycle number and scan intervals according to 802.11d status and country availability  */
    807     sme_updateScanCycles (hSme, bDEnabled, bCountryValid, pSme->bConstantScan);
    808 
    809     /* Finally(!!!), start the scan */
    810     tStatus = scanCncn_StartPeriodicScan (pSme->hScanCncn, SCAN_SCC_DRIVER, &(pSme->tScanParams));
    811     if (SCAN_CRS_SCAN_RUNNING != tStatus)
    812     {
    813         TRACE1(pSme->hReport, REPORT_SEVERITY_ERROR , "sme_StartScan: scan concentrator returned status %d\n", tStatus);
    814         return TI_NOK;
    815     }
    816 
    817     return TI_OK;
    818 }
    819 
    820 /**
    821  * \fn     sme_updateScanCycles
    822  * \brief  Updates the scan intervals and cycle number according to 802.11d status, country availability and WSC PB mode
    823  *
    824  * Updates the scan intervals and cycle number according to 802.11d status, country availability and WSC PB mode.
    825  * Possible scenarios - D disabled - WSC PB off - scan forever with supplied intervals
    826  *                    - D enabled - country unknown - WSC PB off - scan forever with supplied intervals
    827  *                    - D disabled - WSC PB on - scan for two minutes with zero intervals
    828  *                    - D enabled - country unknown - WSC PB on - scan for two minutes with zero intervals
    829  *                    - D enabled - country known - WSC PB off - scan until country expiry with supplied intervals
    830  *                    - D enabled - country known - WSC PB on - scan for the minimu of two minutes and country expiry with zero intervals
    831  *
    832  * \param  hSme - handle to the SME object
    833  * \param  bDEnabled - TRUE if 802.11d is enabled
    834  * \param  bCountryValid - TRUE if a country IE is valid for a band on which we scan
    835  * \param  bConstantScan - TRUE if WSC PB mode is on
    836  * \return None
    837  * \sa     sme_CalculateCyclesNumber, sme_StartScan
    838  */
    839 void sme_updateScanCycles (TI_HANDLE hSme,
    840                            TI_BOOL bDEnabled,
    841                            TI_BOOL bCountryValid,
    842                            TI_BOOL bConstantScan)
    843 {
    844     TSme            *pSme = (TSme*)hSme;
    845     TI_UINT32       uIndex, uScanPeriodMs, uScanDurationMs;
    846     paramInfo_t     *pParam;
    847 
    848     /* 802.11d is disabled, or no country is valid */
    849     if ((TI_FALSE == bDEnabled) || (TI_FALSE == bCountryValid))
    850     {
    851         /* WSC PB mode is disabled */
    852         if (TI_FALSE == bConstantScan)
    853         {
    854             /*
    855              * copy intervals
    856              * In order to avoid tight loop of scan-select or scan-select-connecting operation,
    857              * the prepare scan function takes into account the value of the scan_count when setting the 16 periods in the scan command
    858              */
    859             os_memoryCopy (pSme->hOS, &(pSme->tScanParams.uCycleIntervalMsec[ 0 ]),
    860                            &(pSme->tInitParams.uScanIntervals[ pSme->uScanCount ]), sizeof (TI_UINT32) * (PERIODIC_SCAN_MAX_INTERVAL_NUM - pSme->uScanCount));
    861 
    862             for(uIndex = (PERIODIC_SCAN_MAX_INTERVAL_NUM - pSme->uScanCount); uIndex < PERIODIC_SCAN_MAX_INTERVAL_NUM; uIndex++)
    863             {
    864                 pSme->tScanParams.uCycleIntervalMsec[ uIndex ] = pSme->tInitParams.uScanIntervals[ PERIODIC_SCAN_MAX_INTERVAL_NUM - 1 ];
    865             }
    866 
    867             /* scan for default number (until a result is found) */
    868             pSme->tScanParams.uCycleNum = pSme->tInitParams.uCycleNum;
    869         }
    870         /* WSC PB mode is enabled */
    871         else
    872         {
    873 
    874             /* nullify all intervals */
    875             os_memoryZero (pSme->hOS, &(pSme->tScanParams.uCycleIntervalMsec[ 0 ]),
    876                            sizeof (TI_UINT32) * PERIODIC_SCAN_MAX_INTERVAL_NUM);
    877 
    878             /* calculate the duration of one scan cycle */
    879             uScanDurationMs = 0;
    880             for (uIndex = 0; uIndex < pSme->tScanParams.uChannelNum; uIndex++)
    881             {
    882                 uScanDurationMs += pSme->tScanParams.tChannels[ uIndex ].uMaxDwellTimeMs;
    883             }
    884 
    885             /* set the number of cycles - 2 minutes divided by one cycle duration */
    886             pSme->tScanParams.uCycleNum = (120000 / uScanDurationMs) + 1;
    887         }
    888     }
    889     /* 802.11d is enabled, and country is valid on at least one band */
    890     else
    891     {
    892         pParam = (paramInfo_t *)os_memoryAlloc(pSme->hOS, sizeof(paramInfo_t));
    893         if (!pParam)
    894         {
    895             return;
    896         }
    897 
    898         /* get country expiry time */
    899         pParam->paramType = REGULATORY_DOMAIN_TIME_TO_COUNTRY_EXPIRY;
    900         regulatoryDomain_getParam (pSme->hRegDomain, pParam);
    901 
    902         /* WSC PB mode is disabled */
    903         if (TI_FALSE == bConstantScan)
    904         {
    905             /*
    906              * copy intervals
    907              * In order to avoid tight loop of scan-select or scan-select-connecting operation,
    908              * the prepare scan function takes into account the value of the scan_count when setting the 16 periods in the scan command
    909              */
    910             os_memoryCopy (pSme->hOS, &(pSme->tScanParams.uCycleIntervalMsec[ 0 ]),
    911                            &(pSme->tInitParams.uScanIntervals[ pSme->uScanCount ]), sizeof (TI_UINT32) * (PERIODIC_SCAN_MAX_INTERVAL_NUM - pSme->uScanCount));
    912 
    913             for(uIndex = (PERIODIC_SCAN_MAX_INTERVAL_NUM - pSme->uScanCount); uIndex < PERIODIC_SCAN_MAX_INTERVAL_NUM; uIndex++)
    914             {
    915                 pSme->tScanParams.uCycleIntervalMsec[ uIndex ] = pSme->tInitParams.uScanIntervals[ PERIODIC_SCAN_MAX_INTERVAL_NUM - 1 ];
    916             }
    917 
    918             /* set cycle number according to country expiry time */
    919             sme_CalculateCyclesNumber (hSme, pParam->content.uTimeToCountryExpiryMs);
    920         }
    921         /* WSC PB mode is enabled */
    922         else
    923         {
    924             /* turn off WSC PB mode (for next scan) */
    925             pSme->bConstantScan = TI_FALSE;
    926 
    927             /* set scan period to minimum of WSC PB duration (2 minutes) and country expiry time */
    928             uScanPeriodMs = TI_MIN (120000, pParam->content.uTimeToCountryExpiryMs);
    929 
    930             /* nullify all intervals */
    931             os_memoryZero (pSme->hOS, &(pSme->tScanParams.uCycleIntervalMsec[ 0 ]),
    932                            sizeof (TI_UINT32) * PERIODIC_SCAN_MAX_INTERVAL_NUM);
    933 
    934             /* calculate the duration of one scan cycle */
    935             uScanDurationMs = 0;
    936             for (uIndex = 0; uIndex < pSme->tScanParams.uChannelNum; uIndex++)
    937             {
    938                 uScanDurationMs += pSme->tScanParams.tChannels[ uIndex ].uMaxDwellTimeMs;
    939             }
    940 
    941             if (uScanDurationMs != 0)
    942             {
    943                 /* set the number of cycles - scan period divided by one cycle duration */
    944                 pSme->tScanParams.uCycleNum = (uScanPeriodMs / uScanDurationMs) + 1;
    945             }
    946             else
    947             {
    948                 pSme->tScanParams.uCycleNum = pSme->tInitParams.uCycleNum;
    949             }
    950         }
    951         os_memoryFree(pSme->hOS, pParam, sizeof(paramInfo_t));
    952     }
    953 
    954     /* in case independent mode and to avoid supplicant send disconnect event after 60s */
    955     if (pSme->eBssType != BSS_INFRASTRUCTURE)
    956     {
    957         pSme->tScanParams.uCycleNum = 1;
    958     }
    959 }
    960 
    961 /**
    962  * \fn     sme_CalculateCyclesNumber
    963  * \brief  Calculates the cycle number required for a gicen time, according to scan intervals
    964  *
    965  * Calculates the cycle number required for a gicen time, according to scan intervals. First check the 16
    966  * different intervals, and if more time is available, find how many cycles still fit. Write the result
    967  * to the SME scan command
    968  *
    969  * \param  hSme - handle to the SME object
    970  * \param  uToTalTimeMs - the total periodic scan operation duartion
    971  * \return None
    972  * \sa     sme_updateScanCycles, sme_StartScan
    973  */
    974 void sme_CalculateCyclesNumber (TI_HANDLE hSme, TI_UINT32 uTotalTimeMs)
    975 {
    976     TSme            *pSme = (TSme*)hSme;
    977     TI_UINT32       uIndex, uCurrentTimeMs = 0;
    978 
    979     /*
    980      * the total time should exceed country code expiration by one interval (so that next scan wouldn't
    981      * have a valid country code)
    982      */
    983 
    984     /* nullify cycle number */
    985     pSme->tScanParams.uCycleNum = 0;
    986     /* now find how many cycles fit within this time. First, check if all first 16 configured intervals fit */
    987     for (uIndex = 0;
    988          (uIndex < PERIODIC_SCAN_MAX_INTERVAL_NUM) && (uCurrentTimeMs < uTotalTimeMs);
    989          uIndex++)
    990     {
    991         pSme->tScanParams.uCycleNum++;
    992         uCurrentTimeMs += pSme->tScanParams.uCycleIntervalMsec[ uIndex ];
    993     }
    994     /* now find out how many more cycles with the last interval still fits */
    995     if (uCurrentTimeMs < uTotalTimeMs)
    996     {
    997         /*
    998          * divide the reamining time (time until expiry minus the total time calculated so far)
    999          * by the last interval time, to get how many more scans would fit after the first 16 intervals
   1000          */
   1001         pSme->tScanParams.uCycleNum += (uTotalTimeMs - uCurrentTimeMs) /
   1002                                             pSme->tScanParams.uCycleIntervalMsec[ PERIODIC_SCAN_MAX_INTERVAL_NUM - 1];
   1003         /* and add one, to compensate for the reminder */
   1004         pSme->tScanParams.uCycleNum++;
   1005     }
   1006 }
   1007 
   1008