/*
* ParsEvent.c
*
* Copyright 2001-2009 Texas Instruments, Inc. - http://www.ti.com/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/****************************************************************************
*
* MODULE: ParsEvent.c
*
* PURPOSE:
*
* DESCRIPTION:
* ============
*
*
****************************************************************************/
/* includes */
/************/
#include <stdint.h>
#include <sys/types.h>
#ifdef ANDROID
#include <net/if_ether.h>
#else
#include <netinet/if_ether.h>
#endif
#include <linux/rtnetlink.h>
#include <net/if.h>
#include <linux/wireless.h>
#include "ParsEvent.h"
#include "cu_osapi.h"
#define IW_DESCR_FLAG_NONE 0x0000
#define IW_DESCR_FLAG_DUMP 0x0001
#define IW_DESCR_FLAG_EVENT 0x0002
#define IW_DESCR_FLAG_RESTRICT 0x0004
#define IW_DESCR_FLAG_NOMAX 0x0008
#define IW_DESCR_FLAG_WAIT 0x0100
/* local types */
/***************/
static int ParsEvent_GetEventParam( unsigned short uEventCmd,
unsigned int* uEventLen,
unsigned int* pEventFlag,
unsigned short* pMaxPayload,
unsigned short* pPayloadNum,
unsigned int* bIsPoint);
/**
* \fn ParsEvent_GetEvent()
* \brief get next event from the event stream.
* support the following events that CLI uses: SIOCGIWAP, SIOCGIWESSID, SIOCGIWNAME, SIOCGIWMODE,
* SIOCGIWFREQ, IWEVQUAL, SIOCGIWENCODE, SIOCGIWRATE, IWEVCUSTOM,
* IWEVMICHAELMICFAILURE, SIOCGIWSCAN, IWEVASSOCREQIE, IWEVASSOCRESPIE,
* IWEVPMKIDCAND.
* \note
* \param pEventStream - Event stream pointer.
* \param pEvent - return Event.
* \return value > 0 meens valide event
* \sa
*/
int
ParsEvent_GetEvent(struct stream_descr* pEventStream, struct iw_event* pEvent)
{
unsigned int uStatus = 0;
char* pPtr;
unsigned int uEventLen = 1;
unsigned int uDataLen = 0;
unsigned int uEventFlag = 0;
unsigned short uMaxPayload = 0;
unsigned short uPayloadNum = 0;
unsigned int uMoreLen;
unsigned int bIsPoint = 0;
/* Check validity */
if((pEventStream->current + IW_EV_LCP_LEN) > pEventStream->end)
{
return 0;
}
/* copy tha event */
os_memcpy((char *)pEvent, pEventStream->current, IW_EV_LCP_LEN);
/* Check validity */
if(pEvent->len <= IW_EV_LCP_LEN)
{
return 0;
}
/* get event parameters */
uStatus = ParsEvent_GetEventParam(
pEvent->cmd, &uEventLen, &uEventFlag, &uMaxPayload, &uPayloadNum, &bIsPoint);
if(uEventLen <= IW_EV_LCP_LEN)
{
/* jump to next event */
pEventStream->current += pEvent->len;
return 1;
}
/* get payload */
if(pEventStream->value == NULL)
{
pPtr = pEventStream->current + IW_EV_LCP_LEN;
}
else
{
pPtr = pEventStream->value;
}
uDataLen = uEventLen - IW_EV_LCP_LEN;
/* Check validity */
if((pPtr + uDataLen) > pEventStream->end)
{
/* jump to next event */
pEventStream->current += pEvent->len;
return 0;
}
if(bIsPoint == TRUE)
{
os_memcpy((char *) pEvent + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
pPtr, uDataLen);
}
else
{
os_memcpy((char *) pEvent + IW_EV_LCP_LEN, pPtr, uDataLen);
}
/* jump to next event */
pPtr = pPtr + uDataLen;
if(bIsPoint == FALSE)
{
/* verify more values */
if((pPtr + uDataLen) > (pEventStream->current + pEvent->len))
{
pEventStream->current += pEvent->len;
pEventStream->value = NULL;
}
else
{
pEventStream->value = pPtr;
}
}
else
{
uMoreLen = pEvent->len - uEventLen;
if((uMoreLen == 0) ||
( uStatus == 0) ||
(!(uEventFlag & IW_DESCR_FLAG_NOMAX) && (pEvent->u.data.length > uMaxPayload)) ||
((pEvent->u.data.length * uPayloadNum) > uMoreLen)
)
{
pEvent->u.data.pointer = NULL;
}
else
{
pEvent->u.data.pointer = pPtr;
}
pEventStream->current += pEvent->len;
}
return 1;
}
static int ParsEvent_GetEventParam( unsigned short uEventCmd,
unsigned int* uEventLen,
unsigned int* pEventFlag,
unsigned short* pMaxPayload,
unsigned short* pPayloadNum,
unsigned int* bIsPoint)
{
switch(uEventCmd)
{
case SIOCGIWAP:
*uEventLen = IW_EV_ADDR_LEN;
*pEventFlag = IW_DESCR_FLAG_DUMP;
*bIsPoint = FALSE;
break;
case SIOCGIWESSID:
*uEventLen = IW_EV_POINT_LEN;
*pEventFlag = IW_DESCR_FLAG_DUMP;
*pMaxPayload = IW_ESSID_MAX_SIZE + 1;
*pPayloadNum = 1;
*bIsPoint = TRUE;
break;
case SIOCGIWNAME:
*uEventLen = IW_EV_CHAR_LEN;
*pEventFlag = IW_DESCR_FLAG_DUMP;
*bIsPoint = FALSE;
break;
case SIOCGIWMODE:
*uEventLen = IW_EV_UINT_LEN;
*pEventFlag = IW_DESCR_FLAG_DUMP;
*bIsPoint = FALSE;
break;
case SIOCGIWFREQ:
*uEventLen = IW_EV_FREQ_LEN;
*pEventFlag = IW_DESCR_FLAG_DUMP;
*bIsPoint = FALSE;
break;
case IWEVQUAL:
*uEventLen = IW_EV_QUAL_LEN;
*bIsPoint = FALSE;
break;
case SIOCGIWENCODE:
*uEventLen = IW_EV_POINT_LEN;
*pEventFlag = IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT;
*pMaxPayload = IW_ENCODING_TOKEN_MAX;
*pPayloadNum = 1;
*bIsPoint = TRUE;
break;
case SIOCGIWRATE:
*uEventLen = IW_EV_PARAM_LEN;
*bIsPoint = FALSE;
break;
case IWEVCUSTOM:
*uEventLen = IW_EV_POINT_LEN;
*pMaxPayload = IW_CUSTOM_MAX;
*pPayloadNum = 1;
*bIsPoint = TRUE;
break;
case IWEVMICHAELMICFAILURE:
*uEventLen = IW_EV_POINT_LEN;
*pMaxPayload = sizeof(struct iw_michaelmicfailure);
*pPayloadNum = 1;
*bIsPoint = TRUE;
break;
case SIOCGIWSCAN:
*uEventLen = IW_EV_POINT_LEN;
*pEventFlag = IW_DESCR_FLAG_NOMAX;
*pMaxPayload = IW_SCAN_MAX_DATA;
*pPayloadNum = 1;
*bIsPoint = TRUE;
break;
case IWEVASSOCREQIE:
*uEventLen = IW_EV_POINT_LEN;
*pMaxPayload = IW_GENERIC_IE_MAX;
*pPayloadNum = 1;
*bIsPoint = TRUE;
break;
case IWEVASSOCRESPIE :
*uEventLen = IW_EV_POINT_LEN;
*pMaxPayload = IW_GENERIC_IE_MAX;
*pPayloadNum = 1;
*bIsPoint = TRUE;
break;
case IWEVPMKIDCAND:
*uEventLen = IW_EV_POINT_LEN;
*pMaxPayload = sizeof(struct iw_pmkid_cand);
*pPayloadNum = 1;
*bIsPoint = TRUE;
break;
default:
return 0;
}
return 1;
}