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