blob: 2c300116d98a2ea4c3cc308b247eaaf9e21d64e6 [file] [log] [blame]
/*
* connIbss.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 connIbss.c
* \brief IBSS connection implementation
*
* \see connIbss.h
*/
/***************************************************************************/
/* */
/* MODULE: connIbss.c */
/* PURPOSE: IBSS connection implementation */
/* */
/***************************************************************************/
#define __FILE_ID__ FILE_ID_26
#include "tidef.h"
#include "report.h"
#include "osApi.h"
#include "conn.h"
#include "connIbss.h"
#include "timer.h"
#include "fsm.h"
#include "siteMgrApi.h"
#include "sme.h"
#include "rsnApi.h"
#include "DataCtrl_Api.h"
#include "paramOut.h"
#include "connApi.h"
#include "EvHandler.h"
#include "currBss.h"
#include "TrafficMonitorAPI.h"
#include "healthMonitor.h"
#include "TWDriver.h"
/* Local functions prototypes */
/* Local functions prototypes */
static TI_STATUS waitDisconnToCmplt_to_idle (void *pData);
static TI_STATUS idle_to_selfWait(void *pData);
static TI_STATUS idle_to_rsnWait(void *pData);
static TI_STATUS selfWait_to_waitToDisconnCmplt(void *pData);
static TI_STATUS rsnWait_to_waitToDisconnCmplt(void *pData);
static TI_STATUS connected_to_waitToDisconnCmplt(void *pData);
static TI_STATUS selfWait_to_rsnWait(void *pData);
static TI_STATUS rsnWait_to_connected(void *pData);
static TI_STATUS actionUnexpected(void *pData);
static TI_STATUS actionNop(void *pData);
static TI_STATUS selfw_merge_rsnw(void *pData);
static TI_STATUS rsnw_merge_rsnw(void *pData);
static TI_STATUS conn_merge_conn(void *pData);
/********************************************/
/* Functions Implementations */
/********************************************/
/***********************************************************************
* conn_ibssConfig
***********************************************************************
DESCRIPTION: IBSS Connection configuration function, called by the conection set param function
in the selection phase. Configures the connection state machine to IBSS connection mode
INPUT: hConn - Connection handle.
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
TI_STATUS conn_ibssConfig(conn_t *pConn)
{
fsm_actionCell_t smMatrix[CONN_IBSS_NUM_STATES][CONN_IBSS_NUM_EVENTS] =
{
/* next state and actions for IDLE state */
{ {STATE_CONN_IBSS_SELF_WAIT, idle_to_selfWait }, /* CONN_IBSS_CREATE */
{STATE_CONN_IBSS_RSN_WAIT, idle_to_rsnWait }, /* CONN_IBSS_CONNECT */
{STATE_CONN_IBSS_IDLE, actionNop }, /* CONN_IBSS_DISCONNECT */
{STATE_CONN_IBSS_IDLE, actionUnexpected }, /* CONN_IBSS_RSN_SUCC */
{STATE_CONN_IBSS_IDLE, actionUnexpected }, /* CONN_IBSS_STA_JOINED */
{STATE_CONN_IBSS_IDLE, actionUnexpected }, /* CONN_IBSS_MERGE */
{STATE_CONN_IBSS_IDLE, actionUnexpected } /* CONN_IBSS_DISCONN_COMPLETE */
},
/* next state and actions for SELF_WAIT state */
{ {STATE_CONN_IBSS_SELF_WAIT, actionUnexpected }, /* CONN_IBSS_CREATE */
{STATE_CONN_IBSS_SELF_WAIT, actionUnexpected }, /* CONN_IBSS_CONNECT */
{STATE_CONN_IBSS_WAIT_DISCONN_CMPLT, selfWait_to_waitToDisconnCmplt }, /* CONN_IBSS_DISCONNECT */
{STATE_CONN_IBSS_SELF_WAIT, actionUnexpected }, /* CONN_IBSS_RSN_SUCC */
{STATE_CONN_IBSS_RSN_WAIT, selfWait_to_rsnWait }, /* CONN_IBSS_STA_JOINED */
{STATE_CONN_IBSS_RSN_WAIT, selfw_merge_rsnw }, /* CONN_IBSS_MERGE */
{STATE_CONN_IBSS_SELF_WAIT, actionUnexpected } /* CONN_IBSS_DISCONN_COMPLETE */
},
/* next state and actions for RSN_WAIT state */
{ {STATE_CONN_IBSS_RSN_WAIT, actionUnexpected }, /* CONN_IBSS_CREATE */
{STATE_CONN_IBSS_RSN_WAIT, actionUnexpected }, /* CONN_IBSS_CONNECT */
{STATE_CONN_IBSS_WAIT_DISCONN_CMPLT, rsnWait_to_waitToDisconnCmplt }, /* CONN_IBSS_DISCONNECT */
{STATE_CONN_IBSS_CONNECTED, rsnWait_to_connected }, /* CONN_IBSS_RSN_SUCC */
{STATE_CONN_IBSS_RSN_WAIT, actionUnexpected }, /* CONN_IBSS_STA_JOINED */
{STATE_CONN_IBSS_RSN_WAIT, rsnw_merge_rsnw }, /* CONN_IBSS_MERGE */
{STATE_CONN_IBSS_RSN_WAIT, actionUnexpected } /* CONN_IBSS_DISCONN_COMPLETE */
},
/* next state and actions for CONNECTED state */
{ {STATE_CONN_IBSS_CONNECTED, actionUnexpected }, /* CONN_IBSS_CREATE */
{STATE_CONN_IBSS_CONNECTED, actionUnexpected }, /* CONN_IBSS_CONNECT */
{STATE_CONN_IBSS_WAIT_DISCONN_CMPLT, connected_to_waitToDisconnCmplt }, /* CONN_IBSS_DISCONNECT */
{STATE_CONN_IBSS_CONNECTED, actionUnexpected }, /* CONN_IBSS_RSN_SUCC */
{STATE_CONN_IBSS_CONNECTED, actionUnexpected }, /* CONN_IBSS_STA_JOINED */
{STATE_CONN_IBSS_CONNECTED, conn_merge_conn }, /* CONN_IBSS_MERGE */
{STATE_CONN_IBSS_CONNECTED, actionUnexpected } /* CONN_IBSS_DISCONN_COMPLETE */
},
/* next state and actions for STATE_CONN_IBSS_WAIT_DISCONN_CMPLT state */
{ {STATE_CONN_IBSS_WAIT_DISCONN_CMPLT, actionUnexpected }, /* CONN_IBSS_CREATE */
{STATE_CONN_IBSS_WAIT_DISCONN_CMPLT, actionUnexpected }, /* CONN_IBSS_CONNECT */
{STATE_CONN_IBSS_WAIT_DISCONN_CMPLT, actionUnexpected }, /* CONN_IBSS_DISCONNECT */
{STATE_CONN_IBSS_WAIT_DISCONN_CMPLT, actionUnexpected }, /* CONN_IBSS_RSN_SUCC */
{STATE_CONN_IBSS_WAIT_DISCONN_CMPLT, actionUnexpected }, /* CONN_IBSS_STA_JOINED */
{STATE_CONN_IBSS_WAIT_DISCONN_CMPLT, actionUnexpected }, /* CONN_IBSS_MERGE */
{STATE_CONN_IBSS_IDLE, waitDisconnToCmplt_to_idle } /* CONN_IBSS_DISCONN_COMPLETE */
}
};
return fsm_Config(pConn->ibss_pFsm, (fsm_Matrix_t)smMatrix, CONN_IBSS_NUM_STATES, CONN_IBSS_NUM_EVENTS, conn_ibssSMEvent, pConn->hOs);
}
/***********************************************************************
* conn_ibssSMEvent
***********************************************************************
DESCRIPTION: IBSS Connection SM event processing function, called by the connection API
Perform the following:
- Print the state movement as a result from the event
- Calls the generic state machine event processing function which preform the following:
- Calls the correspoding callback function
- Move to next state
INPUT: currentState - Pointer to the connection current state.
event - Received event
pConn - Connection handle
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
TI_STATUS conn_ibssSMEvent(TI_UINT8 *currentState, TI_UINT8 event, TI_HANDLE hConn)
{
conn_t *pConn = (conn_t *)hConn;
TI_STATUS status;
TI_UINT8 nextState;
status = fsm_GetNextState(pConn->ibss_pFsm, *currentState, event, &nextState);
if (status != TI_OK)
{
TRACE0(pConn->hReport, REPORT_SEVERITY_SM, "IBSS State machine error, failed getting next state\n");
return(TI_NOK);
}
TRACE3( pConn->hReport, REPORT_SEVERITY_INFORMATION, "conn_ibssSMEvent: <currentState = %d, event = %d> --> nextState = %d\n", *currentState, event, nextState);
status = fsm_Event(pConn->ibss_pFsm, currentState, event, (void *)pConn);
return status;
}
void connIbss_DisconnectComplete (conn_t *pConn, TI_UINT8 *data, TI_UINT8 dataLength)
{
/* send an DISCONNECT COMPLETE event to the SM */
conn_ibssSMEvent(&pConn->state, CONN_IBSS_DISCONN_COMPLETE, (TI_HANDLE) pConn);
}
/************************************************************************************************************/
/* In the following section are listed the callback function used by the IBSS connection state machine */
/************************************************************************************************************/
/***********************************************************************
* selfWait_to_rsnWait
***********************************************************************
DESCRIPTION:
INPUT:
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
static TI_STATUS selfWait_to_rsnWait (void *pData)
{
conn_t *pConn = (conn_t *)pData;
paramInfo_t param;
tmr_StopTimer (pConn->hConnTimer);
param.paramType = RX_DATA_PORT_STATUS_PARAM;
param.content.rxDataPortStatus = OPEN_EAPOL;
rxData_setParam (pConn->hRxData, &param);
/* Update TxMgmtQueue SM to enable EAPOL packets. */
txMgmtQ_SetConnState (pConn->hTxMgmtQ, TX_CONN_STATE_EAPOL);
return rsn_start (pConn->hRsn);
}
/***********************************************************************
* rsnWait_to_connected
***********************************************************************
DESCRIPTION:
INPUT:
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
static TI_STATUS rsnWait_to_connected(void *pData)
{
paramInfo_t param;
conn_t *pConn=(conn_t *)pData;
TrafficMonitor_Start( pConn->hTrafficMonitor );
healthMonitor_setState(pConn->hHealthMonitor, HEALTH_MONITOR_STATE_CONNECTED);
siteMgr_start(pConn->hSiteMgr);
param.paramType = RX_DATA_PORT_STATUS_PARAM;
param.content.rxDataPortStatus = OPEN;
rxData_setParam(((conn_t *)pData)->hRxData, &param);
/* Update TxMgmtQueue SM to open Tx path to all packets. */
txMgmtQ_SetConnState (((conn_t *)pData)->hTxMgmtQ, TX_CONN_STATE_OPEN);
/* Update current BSS connection type and mode */
currBSS_updateConnectedState(pConn->hCurrBss, TI_TRUE, BSS_INDEPENDENT);
sme_ReportConnStatus(((conn_t *)pData)->hSmeSm, STATUS_SUCCESSFUL, 0);
return TI_OK;
}
static TI_STATUS selfw_merge_rsnw(void *pData)
{
conn_t *pConn=(conn_t *)pData;
paramInfo_t param;
os_printf("IBSS selfw_merge_rsnw!!!!!!!!!!\n");
tmr_StopTimer (pConn->hConnTimer);
siteMgr_join(pConn->hSiteMgr);
param.paramType = RX_DATA_PORT_STATUS_PARAM;
param.content.rxDataPortStatus = OPEN_EAPOL;
rxData_setParam (pConn->hRxData, &param);
/* Update TxMgmtQueue SM to enable EAPOL packets. */
txMgmtQ_SetConnState (pConn->hTxMgmtQ, TX_CONN_STATE_EAPOL);
return rsn_start (pConn->hRsn);
}
static TI_STATUS rsnw_merge_rsnw(void *pData)
{
conn_t *pConn=(conn_t *)pData;
os_printf("IBSS rsnw_merge_rsnw!!!!!!!!!!\n");
siteMgr_join(pConn->hSiteMgr);
return TI_OK;
}
static TI_STATUS conn_merge_conn(void *pData)
{
conn_t *pConn=(conn_t *)pData;
os_printf("IBSS conn_merge_conn!!!!!!!!!!\n");
siteMgr_join(pConn->hSiteMgr);
return TI_OK;
}
static TI_STATUS waitDisconnToCmplt_to_idle (void *pData)
{
conn_t *pConn = (conn_t *)pData;
/* Inform the SME about the connection lost */
/* we use this status at SME, if != 0 means that assoc frame sent */
sme_ReportConnStatus(pConn->hSmeSm, STATUS_UNSPECIFIED, 1);
return TI_OK;
}
/***********************************************************************
* actionUnexpected
***********************************************************************
DESCRIPTION:
INPUT:
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
static TI_STATUS actionUnexpected(void *pData)
{
#ifdef TI_DBG
conn_t *pConn = (conn_t *)pData;
TRACE0(pConn->hReport, REPORT_SEVERITY_SM, "State machine error, unexpected Event\n\n");
#endif /*TI_DBG*/
return TI_OK;
}
/***********************************************************************
* actionNop
***********************************************************************
DESCRIPTION:
INPUT:
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
static TI_STATUS actionNop(void *pData)
{
return TI_OK;
}
/***********************************************************************
* selfWait_to_waitToDisconnCmplt
***********************************************************************
DESCRIPTION:
INPUT:
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
static TI_STATUS selfWait_to_waitToDisconnCmplt (void *pData)
{
conn_t *pConn = (conn_t *)pData;
paramInfo_t param;
tmr_StopTimer (pConn->hConnTimer);
siteMgr_removeSelfSite(pConn->hSiteMgr);
/* Update current BSS connection type and mode */
currBSS_updateConnectedState(pConn->hCurrBss, TI_FALSE, BSS_INDEPENDENT);
/* stop beacon generation */
param.paramType = RX_DATA_PORT_STATUS_PARAM;
param.content.rxDataPortStatus = CLOSE;
rxData_setParam(pConn->hRxData, &param);
/* Update TxMgmtQueue SM to close Tx path. */
txMgmtQ_SetConnState (pConn->hTxMgmtQ, TX_CONN_STATE_CLOSE);
TWD_CmdFwDisconnect (pConn->hTWD, DISCONNECT_IMMEDIATE, STATUS_UNSPECIFIED);
return TI_OK;
}
/***********************************************************************
* rsnWait_to_waitToDisconnCmplt
***********************************************************************
DESCRIPTION:
INPUT:
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
static TI_STATUS rsnWait_to_waitToDisconnCmplt(void *pData)
{
paramInfo_t param;
TI_STATUS tStatus;
tStatus = rsn_stop(((conn_t *)pData)->hRsn, TI_FALSE);
param.paramType = RX_DATA_PORT_STATUS_PARAM;
param.content.rxDataPortStatus = CLOSE;
rxData_setParam(((conn_t *)pData)->hRxData, &param);
/* Update TxMgmtQueue SM to close Tx path. */
txMgmtQ_SetConnState (((conn_t *)pData)->hTxMgmtQ, TX_CONN_STATE_CLOSE);
/* Update current BSS connection type and mode */
currBSS_updateConnectedState(((conn_t *)pData)->hCurrBss, TI_FALSE, BSS_INDEPENDENT);
/* Stop beacon generation */
TWD_CmdFwDisconnect (((conn_t *)pData)->hTWD, DISCONNECT_IMMEDIATE, STATUS_UNSPECIFIED);
return tStatus;
}
/***********************************************************************
* connected_to_waitToDisconnCmplt
***********************************************************************
DESCRIPTION:
INPUT:
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
static TI_STATUS connected_to_waitToDisconnCmplt(void *pData)
{
conn_t *pConn=(conn_t *)pData;
TrafficMonitor_Stop(pConn->hTrafficMonitor);
healthMonitor_setState(pConn->hHealthMonitor, HEALTH_MONITOR_STATE_DISCONNECTED);
/* The logic of this action is identical to rsnWait_to_idle */
return rsnWait_to_waitToDisconnCmplt(pConn);
}
/***********************************************************************
* idle_to_selfWait
***********************************************************************
DESCRIPTION:
INPUT:
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
static TI_STATUS idle_to_selfWait (void *pData)
{
conn_t *pConn = (conn_t *)pData;
TI_UINT16 randomTime;
siteMgr_join (pConn->hSiteMgr);
/* get a randomTime that is constructed of the lower 13 bits ot the system time to
get a MS random time of ~8000 ms */
randomTime = os_timeStampMs (pConn->hOs) & 0x1FFF;
/* Update current BSS connection type and mode */
currBSS_updateConnectedState (pConn->hCurrBss, TI_TRUE, BSS_INDEPENDENT);
tmr_StartTimer (pConn->hConnTimer,
conn_timeout,
(TI_HANDLE)pConn,
pConn->timeout + randomTime,
TI_FALSE);
/* Notify that the driver is associated to the supplicant\IP stack. */
EvHandlerSendEvent (pConn->hEvHandler, IPC_EVENT_ASSOCIATED, NULL, 0);
return TI_OK;
}
/***********************************************************************
* idle_to_rsnWait
***********************************************************************
DESCRIPTION:
INPUT:
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
static TI_STATUS idle_to_rsnWait(void *pData)
{
paramInfo_t param;
siteMgr_join(((conn_t *)pData)->hSiteMgr);
param.paramType = RX_DATA_PORT_STATUS_PARAM;
param.content.rxDataPortStatus = OPEN_EAPOL;
rxData_setParam(((conn_t *)pData)->hRxData, &param);
/* Update TxMgmtQueue SM to enable EAPOL packets. */
txMgmtQ_SetConnState (((conn_t *)pData)->hTxMgmtQ, TX_CONN_STATE_EAPOL);
/*
* Notify that the driver is associated to the supplicant\IP stack.
*/
EvHandlerSendEvent(((conn_t *)pData)->hEvHandler, IPC_EVENT_ASSOCIATED, NULL,0);
/* Update current BSS connection type and mode */
currBSS_updateConnectedState(((conn_t *)pData)->hCurrBss, TI_TRUE, BSS_INDEPENDENT);
return rsn_start(((conn_t *)pData)->hRsn);
}