blob: 53f583f82371182a7e08cd80c88be0a7efadc939 [file] [log] [blame]
/*
* assocSM.c
*
* Copyright(c) 1998 - 2009 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 assocSM.c
* \brief 802.11 association SM source
*
* \see assocSM.h
*/
/***************************************************************************/
/* */
/* MODULE: assocSM.c */
/* PURPOSE: 802.11 association SM source */
/* */
/***************************************************************************/
#define __FILE_ID__ FILE_ID_63
#include "osApi.h"
#include "paramOut.h"
#include "rate.h"
#include "timer.h"
#include "fsm.h"
#include "report.h"
#include "DataCtrl_Api.h"
#include "siteMgrApi.h"
#include "rsnApi.h"
#include "regulatoryDomainApi.h"
#include "mlmeBuilder.h"
#include "mlmeApi.h"
#include "AssocSM.h"
#include "qosMngr_API.h"
#ifdef XCC_MODULE_INCLUDED
#include "XCCRMMngr.h"
#include "XCCMngr.h"
#endif
#include "apConn.h"
#include "TWDriver.h"
#include "DrvMainModules.h"
#include "StaCap.h"
#include "smeApi.h"
/* Constants */
/** number of states in the state machine */
#define ASSOC_SM_NUM_STATES 3
/** number of events in the state machine */
#define ASSOC_SM_NUM_EVENTS 6
/* Enumerations */
/* Typedefs */
/* Structures */
/* External data definitions */
/* External functions definitions */
/* Global variables */
/* Local function prototypes */
/* functions */
/* state machine functions */
TI_STATUS assoc_smEvent(assoc_t *pAssoc, TI_UINT8 event, void *pData);
void assoc_smTimeout(TI_HANDLE hAssoc, TI_BOOL bTwdInitOccured);
TI_STATUS assoc_smStartIdle(assoc_t *pAssoc);
TI_STATUS assoc_smStopWait(assoc_t *pAssoc);
TI_STATUS assoc_smSuccessWait(assoc_t *pAssoc);
TI_STATUS assoc_smFailureWait(assoc_t *pAssoc);
TI_STATUS assoc_smTimeoutWait(assoc_t *pAssoc);
TI_STATUS assoc_smMaxRetryWait(assoc_t *pAssoc);
TI_STATUS assoc_smStopAssoc(assoc_t *pAssoc);
TI_STATUS assoc_smActionUnexpected(assoc_t *pAssoc);
TI_STATUS assoc_smResetRetry(assoc_t *pAssoc);
TI_STATUS assoc_smIncRetry(assoc_t *pAssoc);
TI_STATUS assoc_smReportSuccess(assoc_t *pAssoc);
TI_STATUS assoc_smReportFailure(assoc_t *pAssoc, TI_UINT16 uStatusCode);
TI_STATUS assoc_smSendAssocReq(assoc_t *pAssoc);
TI_STATUS assoc_smStartTimer(assoc_t *pAssoc);
TI_STATUS assoc_smStopTimer(assoc_t *pAssoc);
TI_STATUS assoc_smCapBuild(assoc_t *pCtx, TI_UINT16 *cap);
TI_STATUS assoc_smSSIDBuild(assoc_t *pCtx, TI_UINT8 *pSSID, TI_UINT32 *ssidLen);
TI_STATUS assoc_smRatesBuild(assoc_t *pCtx, TI_UINT8 *pRates, TI_UINT32 *ratesLen);
TI_STATUS assoc_smRequestBuild(assoc_t *pCtx, TI_UINT8* reqBuf, TI_UINT32* reqLen);
TI_STATUS assoc_saveAssocReqMessage(assoc_t *pAssocSm, TI_UINT8 *pAssocBuffer, TI_UINT32 length);
TI_STATUS assoc_sendDisAssoc(assoc_t *pAssocSm, mgmtStatus_e reason);
/**
*
* assoc_create - allocate memory for association SM
*
* \b Description:
*
* Allocate memory for association SM. \n
* Allocates memory for Association context. \n
* Allocates memory for association SM matrix. \n
*
* \b ARGS:
*
* I - hOs - OS context \n
*
* \b RETURNS:
*
* TI_OK if successful, TI_NOK otherwise.
*
* \sa rsn_mainSecSmKeysOnlyStop()
*/
TI_HANDLE assoc_create(TI_HANDLE hOs)
{
assoc_t *pHandle;
TI_STATUS status;
/* allocate association context memory */
pHandle = (assoc_t*)os_memoryAlloc(hOs, sizeof(assoc_t));
if (pHandle == NULL)
{
return NULL;
}
os_memoryZero(hOs, pHandle, sizeof(assoc_t));
pHandle->hOs = hOs;
/* allocate memory for association state machine */
status = fsm_Create(hOs, &pHandle->pAssocSm, ASSOC_SM_NUM_STATES, ASSOC_SM_NUM_EVENTS);
if (status != TI_OK)
{
os_memoryFree(hOs, pHandle, sizeof(assoc_t));
return NULL;
}
return pHandle;
}
/**
*
* assocunload - unload association SM from memory
*
* \b Description:
*
* Unload association SM from memory
*
* \b ARGS:
*
* I - hAssoc - association SM context \n
*
* \b RETURNS:
*
* TI_OK if successful, TI_NOK otherwise.
*
* \sa rsn_mainSecSmKeysOnlyStop()
*/
TI_STATUS assoc_unload(TI_HANDLE hAssoc)
{
TI_STATUS status;
assoc_t *pHandle;
pHandle = (assoc_t*)hAssoc;
status = fsm_Unload(pHandle->hOs, pHandle->pAssocSm);
if (status != TI_OK)
{
/* report failure but don't stop... */
TRACE0(pHandle->hReport, REPORT_SEVERITY_ERROR, "ASSOC_SM: Error releasing FSM memory \n");
}
if (pHandle->hAssocSmTimer)
{
tmr_DestroyTimer (pHandle->hAssocSmTimer);
}
os_memoryFree(pHandle->hOs, hAssoc, sizeof(assoc_t));
return TI_OK;
}
/**
*
* assoc_config - configure a new association SM
*
* \b Description:
*
* Configure a new association SM.
*
* \b RETURNS:
*
* void
*
* \sa assoc_Create, assoc_Unload
*/
void assoc_init (TStadHandlesList *pStadHandles)
{
assoc_t *pHandle = (assoc_t*)(pStadHandles->hAssoc);
/** Main 802.1X State Machine matrix */
fsm_actionCell_t assoc_smMatrix[ASSOC_SM_NUM_STATES][ASSOC_SM_NUM_EVENTS] =
{
/* next state and actions for IDLE state */
{{ASSOC_SM_STATE_WAIT, (fsm_Action_t)assoc_smStartIdle},
{ASSOC_SM_STATE_IDLE, (fsm_Action_t)assoc_smActionUnexpected},
{ASSOC_SM_STATE_IDLE, (fsm_Action_t)assoc_smActionUnexpected},
{ASSOC_SM_STATE_IDLE, (fsm_Action_t)assoc_smActionUnexpected},
{ASSOC_SM_STATE_IDLE, (fsm_Action_t)assoc_smActionUnexpected},
{ASSOC_SM_STATE_IDLE, (fsm_Action_t)assoc_smActionUnexpected}
},
/* next state and actions for WAIT state */
{{ASSOC_SM_STATE_WAIT, (fsm_Action_t)assoc_smActionUnexpected},
{ASSOC_SM_STATE_IDLE, (fsm_Action_t)assoc_smStopWait},
{ASSOC_SM_STATE_ASSOC, (fsm_Action_t)assoc_smSuccessWait},
{ASSOC_SM_STATE_IDLE, (fsm_Action_t)assoc_smFailureWait},
{ASSOC_SM_STATE_WAIT, (fsm_Action_t)assoc_smTimeoutWait},
{ASSOC_SM_STATE_IDLE, (fsm_Action_t)assoc_smMaxRetryWait}
},
/* next state and actions for ASSOC state */
{{ASSOC_SM_STATE_ASSOC, (fsm_Action_t)assoc_smActionUnexpected},
{ASSOC_SM_STATE_IDLE, (fsm_Action_t)assoc_smStopAssoc},
{ASSOC_SM_STATE_ASSOC, (fsm_Action_t)assoc_smActionUnexpected},
{ASSOC_SM_STATE_ASSOC, (fsm_Action_t)assoc_smActionUnexpected},
{ASSOC_SM_STATE_ASSOC, (fsm_Action_t)assoc_smActionUnexpected},
{ASSOC_SM_STATE_ASSOC, (fsm_Action_t)assoc_smActionUnexpected}
}};
/* configure state machine */
fsm_Config (pHandle->pAssocSm, &assoc_smMatrix[0][0], ASSOC_SM_NUM_STATES, ASSOC_SM_NUM_EVENTS, NULL, pStadHandles->hOs);
pHandle->assocRejectCount = 0;
pHandle->assocTimeoutCount = 0;
pHandle->currentState = ASSOC_SM_STATE_IDLE;
pHandle->hMlme = pStadHandles->hMlmeSm;
pHandle->hRegulatoryDomain = pStadHandles->hRegulatoryDomain;
pHandle->hSiteMgr = pStadHandles->hSiteMgr;
pHandle->hCtrlData = pStadHandles->hCtrlData;
pHandle->hTWD = pStadHandles->hTWD;
pHandle->hRsn = pStadHandles->hRsn;
pHandle->hReport = pStadHandles->hReport;
pHandle->hOs = pStadHandles->hOs;
pHandle->hXCCMngr = pStadHandles->hXCCMngr;
pHandle->hQosMngr = pStadHandles->hQosMngr;
pHandle->hMeasurementMgr = pStadHandles->hMeasurementMgr;
pHandle->hApConn = pStadHandles->hAPConnection;
pHandle->hTimer = pStadHandles->hTimer;
pHandle->hStaCap = pStadHandles->hStaCap;
pHandle->hSme = pStadHandles->hSme;
}
TI_STATUS assoc_SetDefaults (TI_HANDLE hAssoc, assocInitParams_t *pAssocInitParams)
{
assoc_t *pHandle = (assoc_t*)hAssoc;
pHandle->timeout = pAssocInitParams->assocResponseTimeout;
pHandle->maxCount = pAssocInitParams->assocMaxRetryCount;
/* allocate OS timer memory */
pHandle->hAssocSmTimer = tmr_CreateTimer (pHandle->hTimer);
if (pHandle->hAssocSmTimer == NULL)
{
TRACE0(pHandle->hReport, REPORT_SEVERITY_ERROR, "assoc_SetDefaults(): Failed to create hAssocSmTimer!\n");
return TI_NOK;
}
return TI_OK;
}
/**
*
* assoc_start - Start event for the association SM
*
* \b Description:
*
* Start event for the association SM
*
* \b ARGS:
*
* I - hAssoc - Association SM context \n
*
* \b RETURNS:
*
* TI_OK if successful, TI_NOK otherwise.
*
* \sa assoc_Stop, assoc_Recv
*/
TI_STATUS assoc_start(TI_HANDLE hAssoc)
{
TI_STATUS status;
assoc_t *pHandle;
pHandle = (assoc_t*)hAssoc;
if (pHandle == NULL)
{
return TI_NOK;
}
pHandle->reAssoc = TI_FALSE;
pHandle->disAssoc = TI_FALSE;
status = assoc_smEvent(pHandle, ASSOC_SM_EVENT_START, hAssoc);
return status;
}
/**
*
* assoc_start - Start event for the association SM
*
* \b Description:
*
* Start event for the association SM - for Re-assoc request
*
* \b ARGS:
*
* I - hAssoc - Association SM context \n
*
* \b RETURNS:
*
* TI_OK if successful, TI_NOK otherwise.
*
* \sa assoc_Stop, assoc_Recv
*/
TI_STATUS reassoc_start(TI_HANDLE hAssoc)
{
TI_STATUS status;
assoc_t *pHandle;
pHandle = (assoc_t*)hAssoc;
if (pHandle == NULL)
{
return TI_NOK;
}
pHandle->reAssoc = TI_TRUE;
status = assoc_smEvent(pHandle, ASSOC_SM_EVENT_START, hAssoc);
return status;
}
/**
*
* assoc_stop - Stop event for the association SM
*
* \b Description:
*
* Stop event for the association SM
*
* \b ARGS:
*
* I - hAssoc - Association SM context \n
*
* \b RETURNS:
*
* TI_OK if successful, TI_NOK otherwise.
*
* \sa assoc_Start, assoc_Recv
*/
TI_STATUS assoc_stop(TI_HANDLE hAssoc)
{
TI_STATUS status;
assoc_t *pHandle;
pHandle = (assoc_t*)hAssoc;
if (pHandle == NULL)
{
return TI_NOK;
}
status = assoc_smEvent(pHandle, ASSOC_SM_EVENT_STOP, hAssoc);
return status;
}
TI_STATUS assoc_setDisAssocFlag(TI_HANDLE hAssoc, TI_BOOL disAsoccFlag)
{
assoc_t *pHandle;
pHandle = (assoc_t*)hAssoc;
pHandle->disAssoc = disAsoccFlag;
return TI_OK;
}
/**
*
* assoc_recv - Recive a message from the AP
*
* \b Description:
*
* Parse a message form the AP and perform the appropriate event.
*
* \b ARGS:
*
* I - hAssoc - Association SM context \n
* I - pFrame - Frame recieved \n
*
* \b RETURNS:
*
* TI_OK if successful, TI_NOK otherwise.
*
* \sa assoc_Start, assoc_Stop
*/
TI_STATUS assoc_recv(TI_HANDLE hAssoc, mlmeFrameInfo_t *pFrame)
{
TI_STATUS status;
assoc_t *pHandle = (assoc_t*)hAssoc;
TTwdParamInfo tTwdParam;
TI_UINT16 rspStatus;
if (pHandle == NULL)
{
return TI_NOK;
}
/* ensure that the SM is waiting for assoc response */
if(pHandle->currentState != ASSOC_SM_STATE_WAIT)
return TI_OK;
if ((pFrame->subType != ASSOC_RESPONSE) && (pFrame->subType != RE_ASSOC_RESPONSE))
{
return TI_NOK;
}
/* check response status */
rspStatus = pFrame->content.assocRsp.status;
if (rspStatus == 0)
{
TRsnData rsnData;
dot11_RSN_t *pRsnIe;
TI_UINT8 curRsnData[255];
TI_UINT8 rsnAssocIeLen;
TI_UINT8 length = 0;
TRACE0(pHandle->hReport, REPORT_SEVERITY_SM, "ASSOC_SM: DEBUG Success associating to AP \n");
/* set AID to HAL */
tTwdParam.paramType = TWD_AID_PARAM_ID;
tTwdParam.content.halCtrlAid = pFrame->content.assocRsp.aid;
TWD_SetParam (pHandle->hTWD, &tTwdParam);
/* Get the RSN IE data */
pRsnIe = pFrame->content.assocRsp.pRsnIe;
while (length < pFrame->content.assocRsp.rsnIeLen && (pFrame->content.assocRsp.rsnIeLen < 255))
{
curRsnData[0+length] = pRsnIe->hdr[0];
curRsnData[1+length] = pRsnIe->hdr[1];
os_memoryCopy(pHandle->hOs, &curRsnData[2+length], (void *)pRsnIe->rsnIeData, pRsnIe->hdr[1]);
length += pRsnIe->hdr[1] + 2;
pRsnIe += 1;
}
if (pFrame->content.assocRsp.rsnIeLen != 0)
{
rsnData.pIe = curRsnData;
rsnData.ieLen = pFrame->content.assocRsp.rsnIeLen;
rsnData.privacy = ((pFrame->content.assocRsp.capabilities >> CAP_PRIVACY_SHIFT) & CAP_PRIVACY_MASK) ? TI_TRUE : TI_FALSE;
rsn_setSite(pHandle->hRsn, &rsnData, NULL, &rsnAssocIeLen);
}
/* update siteMgr with capabilities and whether we are connected to Cisco AP */
siteMgr_assocReport(pHandle->hSiteMgr,
pFrame->content.assocRsp.capabilities, pFrame->content.assocRsp.ciscoIEPresent);
/* update QoS Manager - it the QOS active protocol is NONE, or no WME IE present, it will return TI_OK */
/* if configured by AP, update MSDU lifetime */
status = qosMngr_setSite(pHandle->hQosMngr, &pFrame->content.assocRsp);
if(status != TI_OK)
{
TRACE0(pHandle->hReport, REPORT_SEVERITY_ERROR, "ASSOC_SM: DEBUG - Association failed : qosMngr_setSite error \n");
/* in case we wanted to work with qosAP and failed to connect to qos AP we want to reassociated again
to another one */
status = assoc_smEvent(pHandle, ASSOC_SM_EVENT_FAIL, hAssoc);
}
else
{
status = assoc_smEvent(pHandle, ASSOC_SM_EVENT_SUCCESS, hAssoc);
}
}
else
{
pHandle->assocRejectCount++;
/* If there was attempt to renegotiate voice settings, update QoS Manager */
qosMngr_checkTspecRenegResults(pHandle->hQosMngr, &pFrame->content.assocRsp);
/* check failure reason */
switch (rspStatus)
{
case 0:
break;
case 1:
/* print debug message */
TRACE0(pHandle->hReport, REPORT_SEVERITY_SM, "ASSOC_SM: DEBUG - Association denied: Unspecified error \n");
break;
case 10:
/* print debug message */
TRACE0(pHandle->hReport, REPORT_SEVERITY_SM, "ASSOC_SM: DEBUG - Association denied: Cannot support all requested capabilities in the Capability Information field \n");
break;
case 11:
/* print debug message */
TRACE0(pHandle->hReport, REPORT_SEVERITY_SM, "ASSOC_SM: DEBUG - Association denied: Reassociation denied due to inability to confirm that association exists \n");
break;
case 12:
/* print debug message */
TRACE0(pHandle->hReport, REPORT_SEVERITY_SM, "ASSOC_SM: DEBUG - Association denied: Association denied due to reason outside the scope of this standard \n");
rsn_reportAuthFailure(pHandle->hRsn, RSN_AUTH_STATUS_INVALID_TYPE);
break;
case 13:
TRACE0(pHandle->hReport, REPORT_SEVERITY_SM, "ASSOC_SM: DEBUG - Association denied: Association denied due to wrong authentication algorithm \n");
rsn_reportAuthFailure(pHandle->hRsn, RSN_AUTH_STATUS_INVALID_TYPE);
break;
case 17:
/* print debug message */
TRACE0(pHandle->hReport, REPORT_SEVERITY_SM, "ASSOC_SM: DEBUG - Association denied: Association denied because AP is unable to handle additional associated stations \n");
break;
case 18:
/* print debug message */
TRACE0(pHandle->hReport, REPORT_SEVERITY_SM, "ASSOC_SM: DEBUG - Association denied: Association denied due to requesting station not supporting all of the data rates in the BSSBasicRateSet parameter \n");
break;
default:
/* print error message on wrong error code for association response */
TRACE1(pHandle->hReport, REPORT_SEVERITY_ERROR, "ASSOC_SM: ERROR - Association denied: error code (%d) irrelevant \n", rspStatus);
break;
}
status = assoc_smEvent(pHandle, ASSOC_SM_EVENT_FAIL, hAssoc);
}
return status;
}
/**
*
* assoc_getParam - Get a specific parameter from the association SM
*
* \b Description:
*
* Get a specific parameter from the association SM.
*
* \b ARGS:
*
* I - hAssoc - Association SM context \n
* I/O - pParam - Parameter \n
*
* \b RETURNS:
*
* TI_OK if successful, TI_NOK otherwise.
*
* \sa assoc_Start, assoc_Stop
*/
TI_STATUS assoc_getParam(TI_HANDLE hAssoc, paramInfo_t *pParam)
{
assoc_t *pHandle = (assoc_t *)hAssoc;
if ((pHandle == NULL) || (pParam == NULL))
{
return TI_NOK;
}
/* serch parameter type */
switch (pParam->paramType)
{
case ASSOC_RESPONSE_TIMEOUT_PARAM:
pParam->content.assocResponseTimeout = pHandle->timeout;
break;
case ASSOC_COUNTERS_PARAM:
pParam->content.siteMgrTiWlanCounters.AssocRejects = pHandle->assocRejectCount;
pParam->content.siteMgrTiWlanCounters.AssocTimeouts = pHandle->assocTimeoutCount;
break;
case ASSOC_ASSOCIATION_REQ_PARAM:
pParam->content.assocReqBuffer.buffer = pHandle->assocReqBuffer;
pParam->content.assocReqBuffer.bufferSize = pHandle->assocReqLen;
pParam->content.assocReqBuffer.reAssoc = pHandle->reAssoc;
break;
case ASSOC_ASSOCIATION_RESP_PARAM:
pParam->content.assocReqBuffer.buffer = pHandle->assocRespBuffer;
pParam->content.assocReqBuffer.bufferSize = pHandle->assocRespLen;
pParam->content.assocReqBuffer.reAssoc = pHandle->reAssocResp;
break;
case ASSOC_ASSOCIATION_INFORMATION_PARAM:
{
TI_UINT8 reqBuffIEOffset, respBuffIEOffset;
TI_UINT32 RequestIELength = 0;
TI_UINT32 ResponseIELength = 0;
paramInfo_t *lParam;
ScanBssType_enum bssType;
TRACE0(pHandle->hReport, REPORT_SEVERITY_SM, "ASSOC_SM: DEBUG - Association Information Get: \n");
lParam = (paramInfo_t *)os_memoryAlloc(pHandle->hOs, sizeof(paramInfo_t));
if (!lParam)
return TI_NOK;
/* Assoc exists only in Infrastructure */
lParam->paramType = CTRL_DATA_CURRENT_BSS_TYPE_PARAM;
ctrlData_getParam(pHandle->hCtrlData, lParam);
bssType = lParam->content.ctrlDataCurrentBssType;
os_memoryFree(pHandle->hOs, lParam, sizeof(paramInfo_t));
if (bssType != BSS_INFRASTRUCTURE)
{
TRACE0(pHandle->hReport, REPORT_SEVERITY_ERROR, "Not in Infrastructure BSS, No ASSOC Info for GET ASSOC_ASSOCIATION_INFORMATION_PARAM\n");
return TI_NOK;
}
/* Init the result buffer to 0 */
os_memoryZero(pHandle->hOs ,&pParam->content, sizeof(OS_802_11_ASSOCIATION_INFORMATION));
reqBuffIEOffset = 4; /* In Assoc request frame IEs are located from byte 4 */
respBuffIEOffset = 6; /* In Assoc response frame the IEs are located from byte 6 */
/* If the last associate was re-associciation, the current AP MAC address */
/* is placed before the IEs. Copy it to the result parameters. */
if (pHandle->reAssoc)
{
MAC_COPY (pParam->content.assocAssociationInformation.RequestFixedIEs.CurrentAPAddress,
&pHandle->assocReqBuffer[reqBuffIEOffset]);
reqBuffIEOffset += MAC_ADDR_LEN;
}
/* Calculate length of Info elements in assoc request and response frames */
if(pHandle->assocReqLen > reqBuffIEOffset)
RequestIELength = pHandle->assocReqLen - reqBuffIEOffset;
if(pHandle->assocRespLen > respBuffIEOffset)
ResponseIELength = pHandle->assocRespLen - respBuffIEOffset;
/* Copy the association request information */
pParam->content.assocAssociationInformation.Length = sizeof(OS_802_11_ASSOCIATION_INFORMATION);
pParam->content.assocAssociationInformation.AvailableRequestFixedIEs = OS_802_11_AI_REQFI_CAPABILITIES | OS_802_11_AI_REQFI_LISTENINTERVAL;
pParam->content.assocAssociationInformation.RequestFixedIEs.Capabilities = *(TI_UINT16*)&(pHandle->assocReqBuffer[0]);
pParam->content.assocAssociationInformation.RequestFixedIEs.ListenInterval = *(TI_UINT16*)(&pHandle->assocReqBuffer[2]);
pParam->content.assocAssociationInformation.RequestIELength = RequestIELength;
pParam->content.assocAssociationInformation.OffsetRequestIEs = 0;
if (RequestIELength > 0)
{
pParam->content.assocAssociationInformation.OffsetRequestIEs = (TI_UINT32)&pHandle->assocReqBuffer[reqBuffIEOffset];
}
/* Copy the association response information */
pParam->content.assocAssociationInformation.AvailableResponseFixedIEs =
OS_802_11_AI_RESFI_CAPABILITIES | OS_802_11_AI_RESFI_STATUSCODE | OS_802_11_AI_RESFI_ASSOCIATIONID;
pParam->content.assocAssociationInformation.ResponseFixedIEs.Capabilities = *(TI_UINT16*)&(pHandle->assocRespBuffer[0]);
pParam->content.assocAssociationInformation.ResponseFixedIEs.StatusCode = *(TI_UINT16*)&(pHandle->assocRespBuffer[2]);
pParam->content.assocAssociationInformation.ResponseFixedIEs.AssociationId = *(TI_UINT16*)&(pHandle->assocRespBuffer[4]);
pParam->content.assocAssociationInformation.ResponseIELength = ResponseIELength;
pParam->content.assocAssociationInformation.OffsetResponseIEs = 0;
if (ResponseIELength > 0)
{
pParam->content.assocAssociationInformation.OffsetResponseIEs = (TI_UINT32)&pHandle->assocRespBuffer[respBuffIEOffset];
}
}
break;
default:
return TI_NOK;
}
return TI_OK;
}
/**
*
* assoc_setParam - Set a specific parameter to the association SM
*
* \b Description:
*
* Set a specific parameter to the association SM.
*
* \b ARGS:
*
* I - hAssoc - Association SM context \n
* I/O - pParam - Parameter \n
*
* \b RETURNS:
*
* TI_OK if successful, TI_NOK otherwise.
*
* \sa assoc_Start, assoc_Stop
*/
TI_STATUS assoc_setParam(TI_HANDLE hAssoc, paramInfo_t *pParam)
{
assoc_t *pHandle;
pHandle = (assoc_t*)hAssoc;
if ((pHandle == NULL) || (pParam == NULL))
{
return TI_NOK;
}
switch (pParam->paramType)
{
case ASSOC_RESPONSE_TIMEOUT_PARAM:
/* check bounds */
if ((pParam->content.assocResponseTimeout >= ASSOC_RESPONSE_TIMEOUT_MIN) &&
(pParam->content.assocResponseTimeout <= ASSOC_RESPONSE_TIMEOUT_MAX))
{
pHandle->timeout = pParam->content.assocResponseTimeout;
} else {
return TI_NOK;
}
break;
default:
return TI_NOK;
}
return TI_OK;
}
/**
*
* assoc_smTimeout - Time out event activation function
*
* \b Description:
*
* Time out event activation function.
*
* \b ARGS:
*
* I - hAssoc - Association SM context \n
*
* \b RETURNS:
*
* TI_OK if successful, TI_NOK otherwise.
*
* \sa assoc_Start, assoc_Stop
*/
void assoc_smTimeout(TI_HANDLE hAssoc, TI_BOOL bTwdInitOccured)
{
assoc_t *pHandle;
pHandle = (assoc_t*)hAssoc;
if (pHandle == NULL)
{
return;
}
pHandle->assocTimeoutCount++;
assoc_smEvent(pHandle, ASSOC_SM_EVENT_TIMEOUT, hAssoc);
}
/**
*
* assoc_smEvent - Perform an event on the association SM
*
* \b Description:
*
* Perform an event on the association SM.
*
* \b ARGS:
*
* I - pAssoc - Association SM context \n
* I - event - Current event \n
* I - pData - event related data
*
* \b RETURNS:
*
* TI_OK if successful, TI_NOK otherwise.
*
* \sa
*/
TI_STATUS assoc_smEvent(assoc_t *pAssoc, TI_UINT8 event, void *pData)
{
TI_STATUS status;
TI_UINT8 nextState;
status = fsm_GetNextState(pAssoc->pAssocSm, pAssoc->currentState, event, &nextState);
if (status != TI_OK)
{
TRACE0(pAssoc->hReport, REPORT_SEVERITY_ERROR, "ASSOC_SM: ERROR - failed getting next state \n");
return(TI_NOK);
}
TRACE3( pAssoc->hReport, REPORT_SEVERITY_INFORMATION, "assoc_smEvent: <currentState = %d, event = %d> --> nextState = %d\n", pAssoc->currentState, event, nextState);
status = fsm_Event(pAssoc->pAssocSm, &pAssoc->currentState, event, pData);
return(status);
}
/* state machine functions */
TI_STATUS assoc_smStartIdle(assoc_t *pAssoc)
{
TI_STATUS status;
status = assoc_smResetRetry(pAssoc);
status = assoc_smSendAssocReq(pAssoc);
status = assoc_smStartTimer(pAssoc);
status = assoc_smIncRetry(pAssoc);
return status;
}
TI_STATUS assoc_smStopWait(assoc_t *pAssoc)
{
TI_STATUS status;
status = assoc_smStopTimer(pAssoc);
return status;
}
TI_STATUS assoc_smSuccessWait(assoc_t *pAssoc)
{
TI_STATUS status;
status = assoc_smStopTimer(pAssoc);
status = assoc_smReportSuccess(pAssoc);
return status;
}
TI_STATUS assoc_smFailureWait(assoc_t *pAssoc)
{
TI_STATUS status;
TI_UINT16 uRspStatus = *(TI_UINT16*)&(pAssoc->assocRespBuffer[2]);
status = assoc_smStopTimer(pAssoc);
/* Sanity check. If the Response status is indeed not 0 */
if (uRspStatus)
{
status = assoc_smReportFailure(pAssoc, uRspStatus);
}
else /* (uRspStatus == 0) how did we get here ? */
{
TRACE0(pAssoc->hReport, REPORT_SEVERITY_ERROR, "while Response status is OK (0) !!! \n");
status = assoc_smReportFailure(pAssoc, (TI_UINT16)TI_NOK);
}
return status;
}
TI_STATUS assoc_smTimeoutWait(assoc_t *pAssoc)
{
TI_STATUS status;
status = assoc_smSendAssocReq(pAssoc);
status = assoc_smStartTimer(pAssoc);
status = assoc_smIncRetry(pAssoc);
return status;
}
TI_STATUS assoc_smMaxRetryWait(assoc_t *pAssoc)
{
TI_STATUS status;
status = assoc_smStopTimer(pAssoc);
status = assoc_smReportFailure(pAssoc, STATUS_PACKET_REJ_TIMEOUT);
return status;
}
TI_STATUS assoc_smSendAssocReq(assoc_t *pAssoc)
{
TI_UINT8 *assocMsg;
TI_UINT32 msgLen;
TI_STATUS status;
dot11MgmtSubType_e assocType=ASSOC_REQUEST;
assocMsg = os_memoryAlloc(pAssoc->hOs, MAX_ASSOC_MSG_LENGTH);
if (!assocMsg)
return TI_NOK;
if (pAssoc->reAssoc)
{
assocType = RE_ASSOC_REQUEST;
}
status = assoc_smRequestBuild(pAssoc, assocMsg, &msgLen);
if (status == TI_OK) {
/* Save the association request message */
assoc_saveAssocReqMessage(pAssoc, assocMsg, msgLen);
status = mlmeBuilder_sendFrame(pAssoc->hMlme, assocType, assocMsg, msgLen, 0);
}
os_memoryFree(pAssoc->hOs, assocMsg, MAX_ASSOC_MSG_LENGTH);
return status;
}
TI_STATUS assoc_smStopAssoc(assoc_t *pAssoc)
{
if (pAssoc->disAssoc) {
assoc_sendDisAssoc(pAssoc, STATUS_UNSPECIFIED);
}
return TI_OK;
}
TI_STATUS assoc_smActionUnexpected(assoc_t *pAssoc)
{
return TI_OK;
}
/* local functions */
TI_STATUS assoc_smResetRetry(assoc_t *pAssoc)
{
if (pAssoc == NULL)
{
return TI_NOK;
}
pAssoc->retryCount = 0;
return TI_OK;
}
TI_STATUS assoc_smIncRetry(assoc_t *pAssoc)
{
TI_STATUS status;
if (pAssoc == NULL)
{
return TI_NOK;
}
pAssoc->retryCount++;
if (pAssoc->retryCount > pAssoc->maxCount)
{
status = assoc_smEvent(pAssoc, ASSOC_SM_EVENT_MAX_RETRY, pAssoc);
return status;
}
return TI_OK;
}
TI_STATUS assoc_smReportSuccess(assoc_t *pAssoc)
{
TI_STATUS status;
if (pAssoc == NULL)
{
return TI_NOK;
}
status = mlme_reportAssocStatus(pAssoc->hMlme, (TI_UINT16)TI_OK);
return status;
}
TI_STATUS assoc_smReportFailure(assoc_t *pAssoc, TI_UINT16 uStatusCode)
{
TI_STATUS status;
if (pAssoc == NULL)
{
return TI_NOK;
}
status = mlme_reportAssocStatus(pAssoc->hMlme, uStatusCode);
return status;
}
TI_STATUS assoc_smStartTimer(assoc_t *pAssoc)
{
if (pAssoc == NULL)
{
return TI_NOK;
}
tmr_StartTimer (pAssoc->hAssocSmTimer,
assoc_smTimeout,
(TI_HANDLE)pAssoc,
pAssoc->timeout,
TI_FALSE);
return TI_OK;
}
TI_STATUS assoc_smStopTimer(assoc_t *pAssoc)
{
if (pAssoc == NULL)
{
return TI_NOK;
}
tmr_StopTimer (pAssoc->hAssocSmTimer);
return TI_OK;
}
/*****************************************************************************
**
** Association messages builder/Parser
**
*****************************************************************************/
TI_STATUS assoc_smCapBuild(assoc_t *pCtx, TI_UINT16 *cap)
{
paramInfo_t param;
TI_STATUS status;
EDot11Mode mode;
TI_UINT32 rateSuppMask, rateBasicMask;
TI_UINT8 ratesBuf[DOT11_MAX_SUPPORTED_RATES];
TI_UINT32 len = 0, ofdmIndex = 0;
TI_BOOL b11nEnable, bWmeEnable;
*cap = 0;
/* Bss type */
param.paramType = CTRL_DATA_CURRENT_BSS_TYPE_PARAM;
status = ctrlData_getParam(pCtx->hCtrlData, &param);
if (status == TI_OK)
{
if (param.content.ctrlDataCurrentBssType == BSS_INFRASTRUCTURE)
{
*cap |= DOT11_CAPS_ESS;
} else {
*cap |= DOT11_CAPS_IBSS;
}
} else {
return TI_NOK;
}
/* Privacy */
param.paramType = RSN_ENCRYPTION_STATUS_PARAM;
status = rsn_getParam(pCtx->hRsn, &param);
if (status == TI_OK)
{
if (param.content.rsnEncryptionStatus != TWD_CIPHER_NONE)
{
*cap |= DOT11_CAPS_PRIVACY;
}
} else {
return TI_NOK;
}
/* Preamble */
param.paramType = SITE_MGR_DESIRED_PREAMBLE_TYPE_PARAM;
status = siteMgr_getParam(pCtx->hSiteMgr, &param);
if (status == TI_OK)
{
if (param.content.siteMgrCurrentPreambleType == PREAMBLE_SHORT)
*cap |= DOT11_CAPS_SHORT_PREAMBLE;
} else {
return TI_NOK;
}
/* Pbcc */
param.paramType = SITE_MGR_CURRENT_RATE_PAIR_PARAM;
status = siteMgr_getParam(pCtx->hSiteMgr, &param);
if (status == TI_OK)
{
if(param.content.siteMgrCurrentRateMask.supportedRateMask & DRV_RATE_MASK_22_PBCC)
*cap |= DOT11_CAPS_PBCC;
} else {
return TI_NOK;
}
/* Checking if the station supports Spectrum Management (802.11h) */
param.paramType = REGULATORY_DOMAIN_MANAGEMENT_CAPABILITY_ENABLED_PARAM;
status = regulatoryDomain_getParam(pCtx->hRegulatoryDomain, &param);
if (status == TI_OK )
{
if( param.content.spectrumManagementEnabled)
*cap |= DOT11_SPECTRUM_MANAGEMENT;
}
else
{
return TI_NOK;
}
/* slot time */
param.paramType = SITE_MGR_OPERATIONAL_MODE_PARAM;
status = siteMgr_getParam(pCtx->hSiteMgr, &param);
if(status == TI_OK)
{
mode = param.content.siteMgrDot11OperationalMode;
}
else
return TI_NOK;
if(mode == DOT11_G_MODE)
{
/* new requirement: the short slot time should be set only
if the AP's modulation is OFDM (highest rate) */
/* get Rates */
param.paramType = SITE_MGR_CURRENT_RATE_PAIR_PARAM;
status = siteMgr_getParam(pCtx->hSiteMgr, &param);
if (status == TI_OK)
{
rateBasicMask = param.content.siteMgrCurrentRateMask.basicRateMask;
rateSuppMask = param.content.siteMgrCurrentRateMask.supportedRateMask;
} else {
return TI_NOK;
}
/* convert the bit map to the rates array */
rate_DrvBitmapToNetStr (rateSuppMask, rateBasicMask, ratesBuf, &len, &ofdmIndex);
if(ofdmIndex < len)
*cap |= DOT11_CAPS_SHORT_SLOT_TIME;
/*
param.paramType = SITE_MGR_CURRENT_MODULATION_TYPE_PARAM;
status = siteMgr_getParam(pCtx->hSiteMgr, &param);
if(param.content.siteMgrCurrentModulationType == DRV_MODULATION_OFDM)
*cap |= DOT11_CAPS_SHORT_SLOT_TIME;
*/
}
/* Immediate Block Ack subfield - (is WME on?) AND (is HT Enable?) */
/* verify 11n_Enable and Chip type */
StaCap_IsHtEnable (pCtx->hStaCap, &b11nEnable);
/* verify that WME flag enable */
qosMngr_GetWmeEnableFlag (pCtx->hQosMngr, &bWmeEnable);
if ((b11nEnable != TI_FALSE) && (bWmeEnable != TI_FALSE))
{
*cap |= DOT11_CAPS_IMMEDIATE_BA;
}
return TI_OK;
}
TI_STATUS assoc_smSSIDBuild(assoc_t *pCtx, TI_UINT8 *pSSID, TI_UINT32 *ssidLen)
{
paramInfo_t param;
TI_STATUS status;
dot11_SSID_t *pDot11Ssid;
pDot11Ssid = (dot11_SSID_t*)pSSID;
/* set SSID element id */
pDot11Ssid->hdr[0] = SSID_IE_ID;
/* get SSID */
param.paramType = SME_DESIRED_SSID_ACT_PARAM;
status = sme_GetParam(pCtx->hSme, &param);
if (status != TI_OK)
{
return status;
}
/* check for ANY ssid */
if (param.content.smeDesiredSSID.len != 0)
{
pDot11Ssid->hdr[1] = param.content.smeDesiredSSID.len;
os_memoryCopy(pCtx->hOs,
(void *)pDot11Ssid->serviceSetId,
(void *)param.content.smeDesiredSSID.str,
param.content.smeDesiredSSID.len);
} else {
/* if ANY ssid is configured, use the current SSID */
param.paramType = SITE_MGR_CURRENT_SSID_PARAM;
status = siteMgr_getParam(pCtx->hSiteMgr, &param);
if (status != TI_OK)
{
return status;
}
pDot11Ssid->hdr[1] = param.content.siteMgrCurrentSSID.len;
os_memoryCopy(pCtx->hOs,
(void *)pDot11Ssid->serviceSetId,
(void *)param.content.siteMgrCurrentSSID.str,
param.content.siteMgrCurrentSSID.len);
}
*ssidLen = pDot11Ssid->hdr[1] + sizeof(dot11_eleHdr_t);
return TI_OK;
}
TI_STATUS assoc_smRatesBuild(assoc_t *pCtx, TI_UINT8 *pRates, TI_UINT32 *ratesLen)
{
paramInfo_t param;
TI_STATUS status;
TI_UINT32 rateSuppMask, rateBasicMask;
dot11_RATES_t *pDot11Rates;
TI_UINT32 len = 0, ofdmIndex = 0;
TI_UINT8 ratesBuf[DOT11_MAX_SUPPORTED_RATES];
EDot11Mode mode;
TI_UINT32 suppRatesLen, extSuppRatesLen, i;
pDot11Rates = (dot11_RATES_t*)pRates;
/* get Rates */
param.paramType = SITE_MGR_CURRENT_RATE_PAIR_PARAM;
status = siteMgr_getParam(pCtx->hSiteMgr, &param);
if (status == TI_OK)
{
rateBasicMask = param.content.siteMgrCurrentRateMask.basicRateMask;
rateSuppMask = param.content.siteMgrCurrentRateMask.supportedRateMask;
}
else
{
return TI_NOK;
}
/* get operational mode */
param.paramType = SITE_MGR_OPERATIONAL_MODE_PARAM;
status = siteMgr_getParam(pCtx->hSiteMgr, &param);
if(status == TI_OK)
mode = param.content.siteMgrDot11OperationalMode;
else
return TI_NOK;
/* convert the bit map to the rates array */
/* remove MCS rates from Extended Supported Rates IE */
rateSuppMask &= ~(DRV_RATE_MASK_MCS_0_OFDM |
DRV_RATE_MASK_MCS_1_OFDM |
DRV_RATE_MASK_MCS_2_OFDM |
DRV_RATE_MASK_MCS_3_OFDM |
DRV_RATE_MASK_MCS_4_OFDM |
DRV_RATE_MASK_MCS_5_OFDM |
DRV_RATE_MASK_MCS_6_OFDM |
DRV_RATE_MASK_MCS_7_OFDM );
rate_DrvBitmapToNetStr (rateSuppMask, rateBasicMask, ratesBuf, &len, &ofdmIndex);
if(mode != DOT11_G_MODE || ofdmIndex == len )
{
pDot11Rates->hdr[0] = SUPPORTED_RATES_IE_ID;
pDot11Rates->hdr[1] = len;
os_memoryCopy(NULL, (void *)pDot11Rates->rates, ratesBuf, len);
*ratesLen = pDot11Rates->hdr[1] + sizeof(dot11_eleHdr_t);
}
else
{
/* fill in the supported rates */
pDot11Rates->hdr[0] = SUPPORTED_RATES_IE_ID;
pDot11Rates->hdr[1] = ofdmIndex;
os_memoryCopy(NULL, (void *)pDot11Rates->rates, ratesBuf, pDot11Rates->hdr[1]);
suppRatesLen = pDot11Rates->hdr[1] + sizeof(dot11_eleHdr_t);
/* fill in the extended supported rates */
pDot11Rates = (dot11_RATES_t*)(pRates + suppRatesLen);
pDot11Rates->hdr[0] = EXT_SUPPORTED_RATES_IE_ID;
pDot11Rates->hdr[1] = len - ofdmIndex;
os_memoryCopy(NULL, (void *)pDot11Rates->rates, &ratesBuf[ofdmIndex], pDot11Rates->hdr[1]);
extSuppRatesLen = pDot11Rates->hdr[1] + sizeof(dot11_eleHdr_t);
*ratesLen = suppRatesLen + extSuppRatesLen;
}
TRACE3(pCtx->hReport, REPORT_SEVERITY_INFORMATION, "ASSOC_SM: ASSOC_REQ - bitmapSupp= 0x%X,bitMapBasic = 0x%X, len = %d\n", rateSuppMask,rateBasicMask,len);
for(i=0; i<len; i++)
{
TRACE2(pCtx->hReport, REPORT_SEVERITY_INFORMATION, "ASSOC_SM: ASSOC_REQ - ratesBuf[%d] = 0x%X\n", i, ratesBuf[i]);
}
return TI_OK;
}
TI_STATUS assoc_powerCapabilityBuild(assoc_t *pCtx, TI_UINT8 *pPowerCapability, TI_UINT32 *powerCapabilityLen)
{
paramInfo_t param;
TI_STATUS status;
dot11_CAPABILITY_t *pDot11PowerCapability;
pDot11PowerCapability = (dot11_CAPABILITY_t*)pPowerCapability;
/* set Power Capability element id */
pDot11PowerCapability->hdr[0] = DOT11_CAPABILITY_ELE_ID;
pDot11PowerCapability->hdr[1] = DOT11_CAPABILITY_ELE_LEN;
/* get power capability */
param.paramType = REGULATORY_DOMAIN_POWER_CAPABILITY_PARAM;
status = regulatoryDomain_getParam(pCtx->hRegulatoryDomain, &param);
if (status == TI_OK)
{
pDot11PowerCapability->minTxPower = param.content.powerCapability.minTxPower;
pDot11PowerCapability->maxTxPower = param.content.powerCapability.maxTxPower;
*powerCapabilityLen = pDot11PowerCapability->hdr[1] + sizeof(dot11_eleHdr_t);
}
else
*powerCapabilityLen = 0;
return TI_OK;
}
TI_STATUS assoc_smRequestBuild(assoc_t *pCtx, TI_UINT8* reqBuf, TI_UINT32* reqLen)
{
TI_STATUS status;
TI_UINT8 *pRequest;
TI_UINT32 len;
paramInfo_t param;
TTwdParamInfo tTwdParam;
TI_UINT16 capabilities;
pRequest = reqBuf;
*reqLen = 0;
/* insert capabilities */
status = assoc_smCapBuild(pCtx, &capabilities);
if (status == TI_OK)
{
*(TI_UINT16*)pRequest = capabilities;
}
else
return TI_NOK;
pRequest += 2;
*reqLen += 2;
/* insert listen interval */
tTwdParam.paramType = TWD_LISTEN_INTERVAL_PARAM_ID;
status = TWD_GetParam (pCtx->hTWD, &tTwdParam);
if (status == TI_OK)
{
*(TI_UINT16*)pRequest = ENDIAN_HANDLE_WORD((TI_UINT16)tTwdParam.content.halCtrlListenInterval);
} else {
return TI_NOK;
}
pRequest += 2;
*reqLen += 2;
if (pCtx->reAssoc)
{ /* Insert currentAPAddress element only in reassoc request*/
param.paramType = SITE_MGR_PREV_SITE_BSSID_PARAM;
status = siteMgr_getParam(pCtx->hSiteMgr, &param);
if (status == TI_OK)
{
MAC_COPY (pRequest, param.content.siteMgrDesiredBSSID);
TRACE6(pCtx->hReport, REPORT_SEVERITY_INFORMATION, "ASSOC_SM: ASSOC_REQ - prev AP = %x-%x-%x-%x-%x-%x\n", param.content.siteMgrDesiredBSSID[0], param.content.siteMgrDesiredBSSID[1], param.content.siteMgrDesiredBSSID[2], param.content.siteMgrDesiredBSSID[3], param.content.siteMgrDesiredBSSID[4], param.content.siteMgrDesiredBSSID[5]);
pRequest += MAC_ADDR_LEN;
*reqLen += MAC_ADDR_LEN;
}
else
{
TRACE0(pCtx->hReport, REPORT_SEVERITY_ERROR, "ASSOC_SM: ASSOC_REQ - No prev AP \n");
return status;
}
}
/* insert SSID element */
status = assoc_smSSIDBuild(pCtx, pRequest, &len);
if (status != TI_OK)
{
return TI_NOK;
}
pRequest += len;
*reqLen += len;
/* insert Rates element */
status = assoc_smRatesBuild(pCtx, pRequest, &len);
if (status != TI_OK)
{
return TI_NOK;
}
pRequest += len;
*reqLen += len;
/* Checking if the station supports Spectrum Management (802.11h) */
param.paramType = REGULATORY_DOMAIN_MANAGEMENT_CAPABILITY_ENABLED_PARAM;
status = regulatoryDomain_getParam(pCtx->hRegulatoryDomain,&param);
if( (status == TI_OK) && param.content.spectrumManagementEnabled)
{
/* Checking the selected AP capablities */
param.paramType = SITE_MGR_SITE_CAPABILITY_PARAM;
status = siteMgr_getParam(pCtx->hSiteMgr,&param);
if(status == TI_OK && ((param.content.siteMgrSiteCapability & DOT11_SPECTRUM_MANAGEMENT) != 0))
{
/* insert Power capability element */
status = assoc_powerCapabilityBuild(pCtx, pRequest, &len);
if (status != TI_OK)
{
return TI_NOK;
}
pRequest += len;
*reqLen += len;
#if 0
/* insert Supported Channels element */
status = assoc_supportedChannelBuild(pCtx, pRequest, &len);
if (status != TI_OK)
{
return TI_NOK;
}
pRequest += len;
*reqLen += len;
#endif
}
}
status = qosMngr_getQosCapabiltyInfeElement(pCtx->hQosMngr,pRequest,&len);
if (status != TI_OK)
{
return TI_NOK;
}
pRequest += len;
*reqLen += len;
#ifdef XCC_MODULE_INCLUDED
status = rsn_getXCCExtendedInfoElement(pCtx->hRsn, pRequest, (TI_UINT8*)&len);
if (status != TI_OK)
{
return TI_NOK;
}
pRequest += len;
*reqLen += len;
if (pCtx->reAssoc)
{ /* insert CCKM information element only in reassoc */
status = XCCMngr_getCckmInfoElement(pCtx->hXCCMngr, pRequest, (TI_UINT8*)&len);
if (status != TI_OK)
{
return TI_NOK;
}
pRequest += len;
*reqLen += len;
}
status = XCCMngr_getXCCVersionInfoElement(pCtx->hXCCMngr, pRequest, (TI_UINT8*)&len);
if (status != TI_OK)
{
return TI_NOK;
}
pRequest += len;
*reqLen += len;
/* Insert Radio Mngt Capability IE */
status = measurementMgr_radioMngtCapabilityBuild(pCtx->hMeasurementMgr, pRequest, (TI_UINT8*)&len);
if (status != TI_OK)
{
return TI_NOK;
}
pRequest += len;
*reqLen += len;
#endif
/* Get Simple-Config state */
param.paramType = SITE_MGR_SIMPLE_CONFIG_MODE;
status = siteMgr_getParam(pCtx->hSiteMgr, &param);
if (param.content.siteMgrWSCMode.WSCMode == TIWLN_SIMPLE_CONFIG_OFF)
{
/* insert RSN information elements */
status = rsn_getInfoElement(pCtx->hRsn, pRequest, &len);
if (status != TI_OK)
{
return TI_NOK;
}
pRequest += len;
*reqLen += len;
}
/* Primary Site support HT ? */
param.paramType = SITE_MGR_PRIMARY_SITE_HT_SUPPORT;
siteMgr_getParam(pCtx->hSiteMgr, &param);
if(TI_TRUE == param.content.bPrimarySiteHtSupport)
{
status = StaCap_GetHtCapabilitiesIe (pCtx->hStaCap, pRequest, &len);
if (status != TI_OK)
{
return TI_NOK;
}
pRequest += len;
*reqLen += len;
}
status = qosMngr_assocReqBuild(pCtx->hQosMngr,pRequest,&len);
if (status != TI_OK)
{
return TI_NOK;
}
pRequest += len;
*reqLen += len;
status = apConn_getVendorSpecificIE(pCtx->hApConn, pRequest, &len);
if (status != TI_OK)
{
return TI_NOK;
}
pRequest += len;
*reqLen += len;
if (*reqLen>=MAX_ASSOC_MSG_LENGTH)
{
return TI_NOK;
}
return TI_OK;
}
TI_STATUS assoc_saveAssocRespMessage(assoc_t *pAssocSm, TI_UINT8 *pAssocBuffer, TI_UINT32 length)
{
if ((pAssocSm==NULL) || (pAssocBuffer==NULL) || (length>=MAX_ASSOC_MSG_LENGTH))
{
return TI_NOK;
}
os_memoryCopy(pAssocSm->hOs, pAssocSm->assocRespBuffer, pAssocBuffer, length);
pAssocSm->assocRespLen = length;
TRACE1(pAssocSm->hReport, REPORT_SEVERITY_INFORMATION, "assoc_saveAssocRespMessage: length=%ld \n",length);
return TI_OK;
}
TI_STATUS assoc_saveAssocReqMessage(assoc_t *pAssocSm, TI_UINT8 *pAssocBuffer, TI_UINT32 length)
{
if ((pAssocSm==NULL) || (pAssocBuffer==NULL) || (length>=MAX_ASSOC_MSG_LENGTH))
{
return TI_NOK;
}
os_memoryCopy(pAssocSm->hOs, pAssocSm->assocReqBuffer, pAssocBuffer, length);
pAssocSm->assocReqLen = length;
TRACE1(pAssocSm->hReport, REPORT_SEVERITY_INFORMATION, "assoc_saveAssocReqMessage: length=%ld \n",length);
return TI_OK;
}
TI_STATUS assoc_sendDisAssoc(assoc_t *pAssocSm, mgmtStatus_e reason)
{
TI_STATUS status;
disAssoc_t disAssoc;
if (reason == STATUS_SUCCESSFUL)
{
disAssoc.reason = ENDIAN_HANDLE_WORD(STATUS_UNSPECIFIED);
} else {
disAssoc.reason = ENDIAN_HANDLE_WORD(reason);
}
status = mlmeBuilder_sendFrame(pAssocSm->hMlme, DIS_ASSOC, (TI_UINT8*)&disAssoc, sizeof(disAssoc_t), 0);
return status;
}