blob: 9e0d5426b2dcbd21945fd221021e1c276938b245 [file] [log] [blame]
/*
* sme.c
*
* Copyright(c) 1998 - 2010 Texas Instruments. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Texas Instruments nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** \file sme.c
* \brief SME implementation
*
* \see sme.h, smeSm.c smePrivate.h
*/
#define __FILE_ID__ FILE_ID_41
#include "smePrivate.h"
#include "GenSM.h"
#include "scanResultTable.h"
#include "smeSm.h"
#include "siteMgrApi.h"
#include "regulatoryDomainApi.h"
#include "connApi.h"
/**
* \fn sme_Create
* \brief Creates the SME module. Allocates system resources
*
* Creates the SME module. Allocates system resources
*
* \param hOS - handle to the OS adaptation layer
* \return Handle to the SME object
* \sa sme_Init, sme_SetDefaults, sme_Destroy
*/
TI_HANDLE sme_Create (TI_HANDLE hOS)
{
TSme *pSme;
/* allocate space for the SME object */
pSme = (TSme*)os_memoryAlloc (hOS, sizeof (TSme));
if (NULL == pSme)
{
WLAN_OS_REPORT (("sme_Create: unable to allocate memor yfor SME object. SME craetion failed\n"));
return NULL;
}
/* nullify SME object */
os_memoryZero (hOS, (void*)pSme, sizeof (TSme));
/* store OS handle */
pSme->hOS = hOS;
/* Create SME generic state-machine */
pSme->hSmeSm = genSM_Create (hOS);
if (NULL == pSme->hSmeSm)
{
WLAN_OS_REPORT (("sme_Create: unable to create SME generic SM. SME creation failed\n"));
sme_Destroy ((TI_HANDLE)pSme);
return NULL;
}
/* Create SME scan result table */
pSme->hSmeScanResultTable = scanResultTable_Create (hOS, SME_SCAN_TABLE_ENTRIES);
if (NULL == pSme->hSmeScanResultTable)
{
WLAN_OS_REPORT (("sme_Create: unable to create scan result table. SME creation failed\n"));
sme_Destroy ((TI_HANDLE)pSme);
return NULL;
}
return (TI_HANDLE)pSme;
}
/**
* \fn sme_Init
* \brief Initializes the SME object. Store module handles
*
* Initializes the SME object. Store module handles
*
* \param pStadHandles - pointer to the handles structure
* \return None
* \sa sme_Create, sme_SetDefaults
*/
void sme_Init (TStadHandlesList *pStadHandles)
{
TSme *pSme = pStadHandles->hSme;
/* Store object handles */
pSme->hReport = pStadHandles->hReport;
pSme->hScanCncn = pStadHandles->hScanCncn;
pSme->hApConn = pStadHandles->hAPConnection;
pSme->hConn = pStadHandles->hConn;
pSme->hScr = pStadHandles->hSCR;
pSme->hRegDomain = pStadHandles->hRegulatoryDomain;
pSme->hEvHandler = pStadHandles->hEvHandler;
pSme->hSiteMgr = pStadHandles->hSiteMgr;
pSme->hRsn = pStadHandles->hRsn;
pSme->hDrvMain = pStadHandles->hDrvMain;
pSme->hTwd = pStadHandles->hTWD;
/* Initialize the scan result table object */
scanResultTable_Init (pSme->hSmeScanResultTable, pStadHandles, SCAN_RESULT_TABLE_CLEAR);
/* Initialize the SME state-machine object */
genSM_Init (pSme->hSmeSm, pStadHandles->hReport);
}
/**
* \fn sme_SetDefaults
* \brief Set default values to the SME (and the SM and scan result table)
*
* Set default values to the SME (and the SM and scan result table)
*
* \param hSme - handle to the SME object
* \param pInitParams - values read from registry / ini file
* \return None
* \sa sme_Create, sme_Init
*/
void sme_SetDefaults (TI_HANDLE hSme, TSmeModifiedInitParams *pModifiedInitParams, TSmeInitParams *pInitParams)
{
TSme *pSme = (TSme*)hSme;
/* copy init params */
os_memoryCopy (pSme->hOS, &(pSme->tInitParams), pInitParams, sizeof (TSmeInitParams));
/* initialize SME varaibles */
pSme->bRadioOn = pModifiedInitParams->bRadioOn;
pSme->eConnectMode = pModifiedInitParams->eConnectMode;
if (CONNECT_MODE_AUTO == pSme->eConnectMode)
{
pSme->hScanResultTable = pSme->hSmeScanResultTable;
}
else if (CONNECT_MODE_MANUAL == pSme->eConnectMode)
{
pSme->hScanResultTable = pSme->hScanCncnScanResulTable;
}
pSme->eBssType = pModifiedInitParams->eDesiredBssType;
MAC_COPY (pSme->tBssid, pModifiedInitParams->tDesiredBssid);
pSme->tSsid.len = pModifiedInitParams->tDesiredSsid.len;
if ( pSme->tSsid.len > MAX_SSID_LEN )
{
TRACE2( pSme->hReport, REPORT_SEVERITY_ERROR, "sme_SetDefaults. pSme->tSsid.len=%d exceeds the limit %d\n", pSme->tSsid.len, MAX_SSID_LEN);
pSme->tSsid.len = MAX_SSID_LEN;
}
os_memoryCopy (pSme->hOS, &(pSme->tSsid.str[ 0 ]), &(pModifiedInitParams->tDesiredSsid.str[ 0 ]), pSme->tSsid.len);
if (OS_802_11_SSID_JUNK (pSme->tSsid.str, pSme->tSsid.len))
{
pSme->eSsidType = SSID_TYPE_INVALID;
pSme->bConnectRequired = TI_FALSE;
}
else if (0 == pSme->tSsid.len)
{
pSme->eSsidType = SSID_TYPE_ANY;
pSme->bConnectRequired = TI_TRUE;
}
else
{
pSme->eSsidType = SSID_TYPE_SPECIFIC;
pSme->bConnectRequired = TI_TRUE;
}
pSme->eLastConnectMode = CONNECT_MODE_AUTO;
pSme->bAuthSent = TI_FALSE;
pSme->bReselect = TI_FALSE;
pSme->uScanCount = 0;
pSme->bRunning = TI_FALSE;
/* Initialize the SME state-machine */
genSM_SetDefaults (pSme->hSmeSm, SME_SM_NUMBER_OF_STATES, SME_SM_NUMBER_OF_EVENTS, (TGenSM_matrix)tSmMatrix,
SME_SM_STATE_IDLE, "SME SM", uStateDescription, uEventDescription, __FILE_ID__);
/* register scan conecntrator CB */
scanCncn_RegisterScanResultCB (pSme->hScanCncn, SCAN_SCC_DRIVER, sme_ScanResultCB, hSme);
}
/**
* \fn sme_setScanResultTable
* \brief Sets the scanResultTable pointer for the manual mode.
* \param hSme - handle to the SME object
* \param hScanResultTable - pointer to ScanResultTable
* \return none
*/
void sme_SetScanResultTable(TI_HANDLE hSme, TI_HANDLE hScanResultTable)
{
TSme *pSme = (TSme*)hSme;
pSme->hScanCncnScanResulTable = hScanResultTable;
if (CONNECT_MODE_MANUAL == pSme->eConnectMode)
{
pSme->hScanResultTable = pSme->hScanCncnScanResulTable;
}
}
/**
* \fn sme_Destroy
* \brief Destroys the SME object. De-allocates system resources
*
* Destroys the SME object. De-allocates system resources
*
* \param hSme - handle to the SME object
* \return None
* \sa sme_Create
*/
void sme_Destroy (TI_HANDLE hSme)
{
TSme *pSme = (TSme*)hSme;
/* destroy the scan result table */
if (NULL != pSme->hSmeScanResultTable)
{
scanResultTable_Destroy (pSme->hSmeScanResultTable);
}
/* destroy the SME generic state machine */
if (NULL != pSme->hSmeSm)
{
genSM_Unload (pSme->hSmeSm);
}
/* free the SME object */
os_memoryFree (pSme->hOS, hSme, sizeof (TSme));
}
/**
* \fn sme_Start
* \brief Starts SME operation
*
* Starts SME operation. Send probe request templates and send a start event to the SM.
* Only the DrvMain module could & is call that function !!!
*
* \param hSme - handle to the SME object
* \return None
* \sa sme_Stop
*/
void sme_Start (TI_HANDLE hSme)
{
TSme *pSme = (TSme*)hSme;
TRACE1(pSme->hReport, REPORT_SEVERITY_INFORMATION , "sme_Start: called, bRadioOn = %d\n", pSme->bRadioOn);
pSme->bRunning = TI_TRUE;
/*
* call setDefaultProbeReqTemplate at sme_Start() due to the fact in order to set prob req template
* all moudules need to be set already
*/
setDefaultProbeReqTemplate (pSme->hSiteMgr);
/* if radio is on, start the SM */
if (TI_TRUE == pSme->bRadioOn)
{
sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_START, hSme);
}
}
/**
* \fn sme_Stop
* \brief Stops the driver (shuts-down the radio)
*
* Stops the driver (shuts-down the radio)
*
* \param hSme - handle to the SME object
* \param pCBFunc - callback function to be called when stop operation is doen
* \param hCBHanlde - handle to supply to the callback function
* \return None
* \sa sme_Start
*/
void sme_Stop (TI_HANDLE hSme)
{
TSme *pSme = (TSme*)hSme;
TRACE0(pSme->hReport, REPORT_SEVERITY_INFORMATION , "sme_Stop called\n");
pSme->bRunning = TI_FALSE;
/* mark that running flag is send a stop event to the SM */
sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_STOP, hSme);
}
/**
* \fn sme_Restart
* \brief Called due to a paramter value change in site mgr. Triggers a disconnect.
*
* Called due to a paramter value change in site mgr. Triggers a disconnect.
*
* \param hSme - handle to the SME object
* \param eReason - the reason for restarting the SME
* \return None
*/
void sme_Restart (TI_HANDLE hSme)
{
TSme *pSme = (TSme*)hSme;
TRACE0(pSme->hReport, REPORT_SEVERITY_INFORMATION , "sme_Restart called.\n");
pSme->uScanCount = 0;
sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_DISCONNECT, hSme);
}
/**
* \fn sme_SetParam
* \brief Set parameters values
*
* Set parameters values
*
* \note Note is indicated here
* \param hSme - handle to the SME object
* \param pParam - pointer to the param to set
* \return PARAM_NOT_SUPPORTED for an unrecognized parameter, TI_OK if successfull.
* \sa sme_GetParam
*/
TI_STATUS sme_SetParam (TI_HANDLE hSme, paramInfo_t *pParam)
{
TSme *pSme = (TSme*)hSme;
TRACE1(pSme->hReport, REPORT_SEVERITY_INFORMATION , "sme_SetParam: param type is 0x%x\n", pParam->paramType);
switch (pParam->paramType)
{
case SME_RADIO_ON_PARAM:
/* if new value is different than current one */
if (pSme->bRadioOn != pParam->content.smeRadioOn)
{
/* set new radio on value and send an event to the state-machine accordingly */
pSme->bRadioOn = pParam->content.smeRadioOn;
if (TI_TRUE == pSme->bRadioOn)
{
if(TI_TRUE == pSme->bRunning)
{
sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_START, hSme);
}
}
else
{
sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_STOP, hSme);
}
}
break;
case SME_DESIRED_SSID_PARAM:
if (pParam->content.smeDesiredSSID.len > MAX_SSID_LEN)
{
return PARAM_VALUE_NOT_VALID; /* SSID length is out of range */
}
/* if new value is different than current one */
if ((pSme->tSsid.len != pParam->content.smeDesiredSSID.len) ||
(0 != os_memoryCompare (pSme->hOS, (TI_UINT8 *)&(pSme->tSsid.str[ 0 ]),
(TI_UINT8 *)&(pParam->content.smeDesiredSSID.str[ 0 ]), pSme->tSsid.len)))
{
/* set new desired SSID */
os_memoryCopy (pSme->hOS, &(pSme->tSsid.str[ 0 ]), &(pParam->content.smeDesiredSSID.str[ 0 ]), pParam->content.smeDesiredSSID.len);
pSme->tSsid.len = pParam->content.smeDesiredSSID.len;
pSme->uScanCount = 0;
/* now send a disconnect event */
sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_DISCONNECT, hSme);
}
break;
case SME_DESIRED_SSID_ACT_PARAM:
if (pParam->content.smeDesiredSSID.len > MAX_SSID_LEN)
{
return PARAM_VALUE_NOT_VALID; /* SSID length is out of range */
}
pSme->bRadioOn = TI_TRUE;
/* if new value is different than current one */
if ((pSme->tSsid.len != pParam->content.smeDesiredSSID.len) ||
(0 != os_memoryCompare (pSme->hOS, (TI_UINT8 *)&(pSme->tSsid.str[ 0 ]),
(TI_UINT8 *)&(pParam->content.smeDesiredSSID.str[ 0 ]), pSme->tSsid.len)))
{
/* set new desired SSID */
os_memoryCopy (pSme->hOS, &(pSme->tSsid.str[ 0 ]), &(pParam->content.smeDesiredSSID.str[ 0 ]), pParam->content.smeDesiredSSID.len);
pSme->tSsid.len = pParam->content.smeDesiredSSID.len;
}
/* also set SSID type and connect required flag */
if (OS_802_11_SSID_JUNK (pSme->tSsid.str, pSme->tSsid.len))
{
pSme->eSsidType = SSID_TYPE_INVALID;
pSme->bConnectRequired = TI_FALSE;
}
else if (0 == pSme->tSsid.len)
{
pSme->eSsidType = SSID_TYPE_ANY;
pSme->bConnectRequired = TI_TRUE;
}
else
{
pSme->eSsidType = SSID_TYPE_SPECIFIC;
pSme->bConnectRequired = TI_TRUE;
}
pSme->uScanCount = 0;
/* if junk SSID */
if(TI_FALSE == pSme->bConnectRequired)
{
pSme->bConstantScan = TI_FALSE;
}
/* now send a disconnect event */
sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_DISCONNECT, hSme);
break;
case SME_DESIRED_BSSID_PARAM:
/* if new value is different than current one */
if (TI_FALSE == MAC_EQUAL (pSme->tBssid, pParam->content.smeDesiredBSSID))
{
/* set new BSSID */
MAC_COPY (pSme->tBssid, pParam->content.smeDesiredBSSID);
pSme->uScanCount = 0;
/* now send a disconnect event */
sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_DISCONNECT, hSme);
}
break;
case SME_CONNECTION_MODE_PARAM:
/* if new value is different than current one */
if (pSme->eConnectMode != pParam->content.smeConnectionMode)
{
/* set new connection mode */
pSme->eConnectMode = pParam->content.smeConnectionMode;
pSme->uScanCount = 0;
if (CONNECT_MODE_AUTO == pSme->eConnectMode)
{
pSme->hScanResultTable = pSme->hSmeScanResultTable;
}
else if (CONNECT_MODE_MANUAL == pSme->eConnectMode)
{
pSme->hScanResultTable = pSme->hScanCncnScanResulTable;
}
/* now send a disconnect event */
sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_DISCONNECT, hSme);
}
break;
case SME_DESIRED_BSS_TYPE_PARAM:
/* if new value is different than current one */
if (pSme->eBssType != pParam->content.smeDesiredBSSType)
{
/* set new BSS type */
pSme->eBssType = pParam->content.smeDesiredBSSType;
pSme->uScanCount = 0;
/* now send a disconnect event */
sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_DISCONNECT, hSme);
}
break;
case SME_WSC_PB_MODE_PARAM:
if (pParam->content.siteMgrWSCMode.WSCMode != TIWLN_SIMPLE_CONFIG_OFF)
{
pSme->bConstantScan = TI_TRUE;
pSme->uScanCount = 0;
/* now send a disconnect event */
sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_DISCONNECT, hSme);
}
else
{
pSme->bConstantScan = TI_FALSE;
}
break;
default:
TRACE1(pSme->hReport, REPORT_SEVERITY_ERROR , "sme_SetParam: unrecognized param type %d\n", pParam->paramType);
return PARAM_NOT_SUPPORTED;
/* break;*/
}
return TI_OK;
}
/**
* \fn sme_GetParam
* \brief Retrieves a parameter from the SME
*
* Retrieves a parameter from the SME
*
* \param hSme - handle to the SME object
* \param pParam - pointer to the param to retrieve
* \return PARAM_NOT_SUPPORTED for an unrecognized parameter, TI_OK if successfull.
* \sa sme_SetParam
*/
TI_STATUS sme_GetParam (TI_HANDLE hSme, paramInfo_t *pParam)
{
TSme *pSme = (TSme*)hSme;
TRACE1(pSme->hReport, REPORT_SEVERITY_INFORMATION , "sme_GetParam: param type is 0x%x\n", pParam->paramType);
switch (pParam->paramType)
{
case SME_RADIO_ON_PARAM:
pParam->content.smeRadioOn = pSme->bRadioOn;
break;
case SME_DESIRED_SSID_ACT_PARAM:
pParam->content.smeDesiredSSID.len = pSme->tSsid.len;
os_memoryCopy (pSme->hOS, &(pParam->content.smeDesiredSSID.str[ 0 ]),
&(pSme->tSsid.str[ 0 ]), pSme->tSsid.len);
break;
case SME_DESIRED_BSSID_PARAM:
MAC_COPY (pParam->content.smeDesiredBSSID, pSme->tBssid);
break;
case SME_CONNECTION_MODE_PARAM:
pParam->content.smeConnectionMode = pSme->eConnectMode;
break;
case SME_DESIRED_BSS_TYPE_PARAM:
pParam->content.smeDesiredBSSType = pSme->eBssType;
break;
case SME_CONNECTION_STATUS_PARAM:
switch (genSM_GetCurrentState (pSme->hSmeSm))
{
case SME_SM_STATE_IDLE:
pParam->content.smeSmConnectionStatus = eDot11RadioDisabled;
break;
case SME_SM_STATE_WAIT_CONNECT:
pParam->content.smeSmConnectionStatus = eDot11Disassociated;
break;
case SME_SM_STATE_SCANNING:
pParam->content.smeSmConnectionStatus = eDot11Scaning;
break;
case SME_SM_STATE_CONNECTING:
pParam->content.smeSmConnectionStatus = eDot11Connecting;
break;
case SME_SM_STATE_CONNECTED:
pParam->content.smeSmConnectionStatus = eDot11Associated;
break;
case SME_SM_STATE_DISCONNECTING:
pParam->content.smeSmConnectionStatus = eDot11Disassociated;
break;
}
break;
default:
TRACE1(pSme->hReport, REPORT_SEVERITY_ERROR , "sme_GetParam: unrecognized param type %d\n", pParam->paramType);
return PARAM_NOT_SUPPORTED;
/* break;*/
}
return TI_OK;
}
/**
* \fn sme_ScanResultCB
* \brief Callback function from scan concentrator for results and scan complete indications
*
* Callback function from scan concentrator for results and scan complete indications
*
* \param hSme - handle to the SME object
* \param eStatus - the reason for calling the CB
* \param pFrameInfo - frame information (if the CB is called due to received frame)
* \param uSPSStatus - SPS attened channels (if the CB is called to inidcate an SPS scan complete)
* \return None
*/
void sme_ScanResultCB (TI_HANDLE hSme, EScanCncnResultStatus eStatus,
TScanFrameInfo* pFrameInfo, TI_UINT16 uSPSStatus)
{
TSme *pSme = (TSme*)hSme;
paramInfo_t param;
switch (eStatus)
{
/* a frame was received - update the scan result table */
case SCAN_CRS_RECEIVED_FRAME:
TRACE6(pSme->hReport, REPORT_SEVERITY_INFORMATION , "sme_ScanResultCB: received frame from BSSID %02x:%02x:%02x:%02x:%02x:%02x\n", (*pFrameInfo->bssId)[ 0 ], (*pFrameInfo->bssId)[ 1 ], (*pFrameInfo->bssId)[ 2 ], (*pFrameInfo->bssId)[ 3 ], (*pFrameInfo->bssId)[ 4 ], (*pFrameInfo->bssId)[ 5 ]);
/*
* in auto mode in order to find country IE only !!!
* filter frames according to desired SSID, in case we are also trying to find
* country IE in passive scan, to avoid a table overflow (in manual mode, the SME table must be equal to the app
* table, the app is responsible to decide which SSIDs to use for scan)
*/
if (CONNECT_MODE_AUTO == pSme->eConnectMode)
{
if (SSID_TYPE_SPECIFIC == pSme->eSsidType)
{
#ifndef XCC_MODULE_INCLUDED
if ((pSme->tSsid.len == pFrameInfo->parsedIEs->content.iePacket.pSsid->hdr[ 1 ]) &&
(0 == os_memoryCompare (pSme->hOS, (TI_UINT8 *)&(pSme->tSsid.str[ 0 ]),
(TI_UINT8 *)&(pFrameInfo->parsedIEs->content.iePacket.pSsid->serviceSetId[ 0 ]),
pSme->tSsid.len)))
#endif
{
if (TI_OK != scanResultTable_UpdateEntry (pSme->hScanResultTable, pFrameInfo->bssId, pFrameInfo))
{
TRACE6(pSme->hReport, REPORT_SEVERITY_ERROR , "sme_ScanResultCB: unable to update specific entry for BSSID %02x:%02x:%02x:%02x:%02x:%02x\n", (*pFrameInfo->bssId)[ 0 ], (*pFrameInfo->bssId)[ 1 ], (*pFrameInfo->bssId)[ 2 ], (*pFrameInfo->bssId)[ 3 ], (*pFrameInfo->bssId)[ 4 ], (*pFrameInfo->bssId)[ 5 ]);
}
}
}
else
{
if (TI_OK != scanResultTable_UpdateEntry (pSme->hScanResultTable, pFrameInfo->bssId, pFrameInfo))
{
TRACE6(pSme->hReport, REPORT_SEVERITY_ERROR , "sme_ScanResultCB: unable to update entry for BSSID %02x:%02x:%02x:%02x:%02x:%02x because table is full\n", (*pFrameInfo->bssId)[ 0 ], (*pFrameInfo->bssId)[ 1 ], (*pFrameInfo->bssId)[ 2 ], (*pFrameInfo->bssId)[ 3 ], (*pFrameInfo->bssId)[ 4 ], (*pFrameInfo->bssId)[ 5 ]);
}
}
}
else
/* manual mode */
{
if (TI_OK != scanResultTable_UpdateEntry (pSme->hSmeScanResultTable, pFrameInfo->bssId, pFrameInfo))
{
TRACE6(pSme->hReport, REPORT_SEVERITY_ERROR , "sme_ScanResultCB: unable to update application scan entry for BSSID %02x:%02x:%02x:%02x:%02x:%02x\n", (*pFrameInfo->bssId)[ 0 ], (*pFrameInfo->bssId)[ 1 ], (*pFrameInfo->bssId)[ 2 ], (*pFrameInfo->bssId)[ 3 ], (*pFrameInfo->bssId)[ 4 ], (*pFrameInfo->bssId)[ 5 ]);
}
}
break;
/* scan was completed successfully */
case SCAN_CRS_SCAN_COMPLETE_OK:
/* an error occured, try selecting a site anyway */
case SCAN_CRS_SCAN_ABORTED_FW_RESET:
case SCAN_CRS_SCAN_ABORTED_HIGHER_PRIORITY:
case SCAN_CRS_SCAN_FAILED:
case SCAN_CRS_TSF_ERROR:
TRACE1(pSme->hReport, REPORT_SEVERITY_INFORMATION , "sme_ScanResultCB: received scan complete indication with status %d\n", eStatus);
/* stablizie the scan result table - delete its contenst if no results were recived during last scan */
scanResultTable_SetStableState (pSme->hScanResultTable);
if (CONNECT_MODE_AUTO == pSme->eConnectMode)
{
/* try to select a site */
pSme->pCandidate = sme_Select (hSme);
/* if no matching site was found */
if (NULL == pSme->pCandidate)
{
/* for IBSS or any, if no entries where found, add the self site */
if (pSme->eBssType == BSS_INFRASTRUCTURE)
{
TRACE0(pSme->hReport, REPORT_SEVERITY_INFORMATION , "sme_ScanResultCB: No candidate available, sending connect failure\n");
sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_CONNECT_FAILURE, hSme);
break;
}
{
TI_UINT8 uDesiredChannel;
param.paramType = SITE_MGR_DESIRED_CHANNEL_PARAM;
siteMgr_getParam(pSme->hSiteMgr, &param);
uDesiredChannel = param.content.siteMgrDesiredChannel;
if (uDesiredChannel >= SITE_MGR_CHANNEL_A_MIN)
{
param.content.channelCapabilityReq.band = RADIO_BAND_5_0_GHZ;
}
else
{
param.content.channelCapabilityReq.band = RADIO_BAND_2_4_GHZ;
}
/*
update the regulatory domain with the selected band
*/
/* Check if the selected channel is valid according to regDomain */
param.paramType = REGULATORY_DOMAIN_GET_SCAN_CAPABILITIES;
param.content.channelCapabilityReq.scanOption = ACTIVE_SCANNING;
param.content.channelCapabilityReq.channelNum = uDesiredChannel;
regulatoryDomain_getParam (pSme->hRegDomain,&param);
if (!param.content.channelCapabilityRet.channelValidity)
{
TRACE0(pSme->hReport, REPORT_SEVERITY_INFORMATION , "IBSS SELECT FAILURE - No channel !!!\n\n");
sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_CONNECT_FAILURE, hSme);
break;
}
pSme->pCandidate = (TSiteEntry *)addSelfSite(pSme->hSiteMgr);
if (pSme->pCandidate == NULL)
{
TRACE0(pSme->hReport, REPORT_SEVERITY_ERROR , "IBSS SELECT FAILURE - could not open self site !!!\n\n");
sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_CONNECT_FAILURE, hSme);
break;
}
#ifdef REPORT_LOG
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]);
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]));
#endif
}
}
/* a connection candidate is available, send a connect event */
sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_CONNECT, hSme);
}
break;
/*
* scan was stopped according to SME request (should happen when moving to disconnecting from scanning), send a
* connect failure event to move out of disconnecting
*/
case SCAN_CRS_SCAN_STOPPED:
TRACE0(pSme->hReport, REPORT_SEVERITY_INFORMATION , "sme_ScanResultCB: received scan stopped indication\n");
sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_CONNECT_FAILURE, hSme);
break;
default:
TRACE1(pSme->hReport, REPORT_SEVERITY_ERROR , "sme_ScanResultCB: received unrecognized status %d\n", eStatus);
break;
}
}
/**
* \fn sme_MeansurementScanResult
* \brief Callback function from Meansurement for results
*
* Callback function from Meansurement for results used for scans wehen the SME is in Meansurement.
*
* \param hSme - handle to the SME object
* \param pFrameInfo - frame information (if the CB is called due to received frame)
* \return None
*/
void sme_MeansurementScanResult (TI_HANDLE hSme, EScanCncnResultStatus eStatus, TScanFrameInfo* pFrameInfo)
{
TSme *pSme = (TSme*)hSme;
switch (eStatus)
{
/* a frame was received - update the scan result table */
case SCAN_CRS_RECEIVED_FRAME:
TRACE6(pSme->hReport, REPORT_SEVERITY_INFORMATION , "sme_MeansurementScanResult: received frame from BSSID %02x:%02x:%02x:%02x:%02x:%02x\n", (*pFrameInfo->bssId)[ 0 ], (*pFrameInfo->bssId)[ 1 ], (*pFrameInfo->bssId)[ 2 ], (*pFrameInfo->bssId)[ 3 ], (*pFrameInfo->bssId)[ 4 ], (*pFrameInfo->bssId)[ 5 ]);
if (TI_OK != scanResultTable_UpdateEntry (pSme->hSmeScanResultTable, pFrameInfo->bssId, pFrameInfo))
{
TRACE6(pSme->hReport, REPORT_SEVERITY_ERROR , "sme_MeansurementScanResult: unable to update entry for BSSID %02x:%02x:%02x:%02x:%02x:%02x because table is full\n", (*pFrameInfo->bssId)[ 0 ], (*pFrameInfo->bssId)[ 1 ], (*pFrameInfo->bssId)[ 2 ], (*pFrameInfo->bssId)[ 3 ], (*pFrameInfo->bssId)[ 4 ], (*pFrameInfo->bssId)[ 5 ]);
}
break;
/* scan was completed successfully */
case SCAN_CRS_SCAN_COMPLETE_OK:
/* an error occured, try selecting a site anyway */
case SCAN_CRS_SCAN_ABORTED_FW_RESET:
case SCAN_CRS_SCAN_STOPPED:
case SCAN_CRS_SCAN_ABORTED_HIGHER_PRIORITY:
case SCAN_CRS_SCAN_FAILED:
case SCAN_CRS_TSF_ERROR:
TRACE1(pSme->hReport, REPORT_SEVERITY_INFORMATION , "sme_MeansurementScanResult: received scan complete indication with status %d\n", eStatus);
/* stablizie the scan result table - delete its contenst if no results were recived during last scan */
scanResultTable_SetStableState (pSme->hSmeScanResultTable);
break;
default:
TRACE1(pSme->hReport, REPORT_SEVERITY_ERROR , "sme_AppScanResult: received unrecognized status %d\n", eStatus);
break;
}
}
/**
* \fn Function declaration
* \brief Function brief description goes here
*
* Function detailed description goes here
*
* \note Note is indicated here
* \param Parameter name - parameter description
* \param …
* \return Return code is detailed here
* \sa Reference to other relevant functions
*/
void sme_ReportConnStatus (TI_HANDLE hSme, mgmtStatus_e eStatusType, TI_UINT32 uStatusCode)
{
TSme *pSme = (TSme*)hSme;
TRACE2(pSme->hReport, REPORT_SEVERITY_INFORMATION , "sme_ReportConnStatus: statusType = %d, uStatusCode = %d\n", eStatusType, uStatusCode);
/* Act according to status */
switch (eStatusType)
{
/* connection was successful */
case STATUS_SUCCESSFUL:
pSme->bAuthSent = TI_TRUE;
sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_CONNECT_SUCCESS, hSme);
break;
case STATUS_ASSOC_REJECT:
case STATUS_SECURITY_FAILURE:
case STATUS_AP_DEAUTHENTICATE:
case STATUS_AP_DISASSOCIATE:
case STATUS_ROAMING_TRIGGER:
case STATUS_AUTH_REJECT:
/* Indicate the authentication and/or association was sent to the AP */
pSme->bAuthSent = TI_TRUE;
/* keep the disassociation status and code, for sending event to user-mode */
pSme->tDisAssoc.eMgmtStatus = eStatusType;
pSme->tDisAssoc.uStatusCode = uStatusCode;
/* try to find the next connection candidate */
pSme->pCandidate = sme_Select (hSme);
/* if the next connection candidate exists */
if (NULL != pSme->pCandidate)
{
sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_CONNECT, hSme);
}
else
{
sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_CONNECT_FAILURE, hSme);
}
break;
/* Note that in case of unspecified status we won't update the status. This is done since this function could be called twice */
/* for example: apConn called this function and than SME called conn_stop and this function is called again */
/* we use this status at SME, if != 0 means that assoc frame sent */
case STATUS_UNSPECIFIED:
pSme->bAuthSent = TI_TRUE;
sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_CONNECT_FAILURE, hSme);
break;
default:
TRACE1(pSme->hReport, REPORT_SEVERITY_ERROR , "sme_ReportConnStatus: unknown statusType = %d\n", eStatusType);
break;
}
}
/**
* \fn sme_ReportApConnStatus
* \brief Used by AP connection (and Soft-gemini) modules to report connection status
*
* Used by AP connection (and Soft-gemini) modules to report connection status
*
* \param hSme - handle to the SME object
* \param eStatusType - connection status
* \param uStatus code - extended status information (if available)
* \return None
* \sa sme_ReportConnStatus
*/
void sme_ReportApConnStatus (TI_HANDLE hSme, mgmtStatus_e eStatusType, TI_UINT32 uStatusCode)
{
TSme *pSme = (TSme*)hSme;
TRACE2(pSme->hReport, REPORT_SEVERITY_INFORMATION , "sme_ReportApConnStatus: statusType = %d, uStatusCode = %d\n", eStatusType, uStatusCode);
/* Act according to status */
switch (eStatusType)
{
/* SG re-select */
case STATUS_SG_RESELECT:
pSme->bReselect = TI_TRUE;
pSme->bConnectRequired = TI_TRUE;
sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_CONNECT_FAILURE, hSme);
break;
/* shouldn't happen (not from AP conn) */
case STATUS_SUCCESSFUL:
TRACE0(pSme->hReport, REPORT_SEVERITY_ERROR , "sme_ReportApConnStatus: received STATUS_SUCCESSFUL\n");
break;
case STATUS_UNSPECIFIED:
case STATUS_AUTH_REJECT:
case STATUS_ASSOC_REJECT:
case STATUS_SECURITY_FAILURE:
case STATUS_AP_DEAUTHENTICATE:
case STATUS_AP_DISASSOCIATE:
case STATUS_ROAMING_TRIGGER:
/* keep the disassociation status and code, for sending event to user-mode */
pSme->tDisAssoc.eMgmtStatus = eStatusType;
pSme->tDisAssoc.uStatusCode = uStatusCode;
sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_CONNECT_FAILURE, hSme);
break;
case STATUS_DISCONNECT_DURING_CONNECT:
sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_DISCONNECT, hSme);
break;
default:
TRACE1(pSme->hReport, REPORT_SEVERITY_ERROR , "sme_ReportApConnStatus: received unrecognized status: %d\n", eStatusType);
}
}
/**
* \fn sme_ConnectScanReport
* \brief get the handler to the Scan Result Table used for connection to AP.
*
* \param hSme - handle to the SME object
* \param uStatus code - extended status information (if available)
* \return None
*/
void sme_ConnectScanReport (TI_HANDLE hSme, TI_HANDLE *hScanResultTable)
{
TSme *pSme = (TSme*)hSme;
*hScanResultTable = pSme->hScanResultTable;
}
/**
* \fn sme_MeasureScanReport
* \brief get the handler to the Sme Scan Result Table.
*
* \param hSme - handle to the SME object
* \param uStatus code - extended status information (if available)
* \return None
*/
void sme_MeasureScanReport (TI_HANDLE hSme, TI_HANDLE *hScanResultTable)
{
TSme *pSme = (TSme*)hSme;
*hScanResultTable = pSme->hSmeScanResultTable;
}
/**
* \fn SME_ConnectRequired
* \brief start connection sequence by set the flag ConnectRequired and issue DISCONNECT event.
* called by CommandDispatcher in OSE OS.
*
* \param hSme - handle to the SME object
* \return None
* \sa SME_Disconnect
*/
void SME_ConnectRequired (TI_HANDLE hSme)
{
TSme *pSme = (TSme*)hSme;
pSme->bRadioOn = TI_TRUE;
pSme->uScanCount = 0;
pSme->bConnectRequired = TI_TRUE;
/* now send a disconnect event */
sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_DISCONNECT, hSme);
}
/**
* \fn SME_Disconnect
* \brief perform disconnect by clear the flag ConnectRequired and issue DISCONNECT event.
*
* \param hSme - handle to the SME object
* \return None
* \sa SME_ConnectRequired
*/
void SME_Disconnect (TI_HANDLE hSme)
{
TSme *pSme = (TSme*)hSme;
pSme->bConnectRequired = TI_FALSE;
/* turn off WSC PB mode */
pSme->bConstantScan = TI_FALSE;
/* now send a disconnect event */
sme_SmEvent (pSme->hSmeSm, SME_SM_EVENT_DISCONNECT, hSme);
}
void sme_SmEvent(TI_HANDLE hGenSm, TI_UINT32 uEvent, void* pData)
{
TSme *pSme = (TSme*)pData;
TGenSM *pGenSM = (TGenSM*)hGenSm;
TRACE2(pSme->hReport, REPORT_SEVERITY_INFORMATION, "sme_SmEvent: Current State = %d, sending event %d\n", (pGenSM->uCurrentState), (uEvent));
genSM_Event(pGenSM, uEvent, pData);
}