200 lines
6.4 KiB
C
200 lines
6.4 KiB
C
/** @file router_transport.c
|
|
*
|
|
*
|
|
* Copyright (C) Cambridge Silicon Radio Ltd 2006-2010. All rights reserved.
|
|
*
|
|
* Refer to LICENSE.txt included with this source code for details on
|
|
* the license terms.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include "unifi_priv.h"
|
|
|
|
#include "csr_sched.h"
|
|
#include "csr_msgconv.h"
|
|
|
|
#include "sme_userspace.h"
|
|
|
|
#include "csr_wifi_hostio_prim.h"
|
|
#include "csr_wifi_router_lib.h"
|
|
#include "csr_wifi_router_sef.h"
|
|
#include "csr_wifi_router_converter_init.h"
|
|
#include "csr_wifi_router_ctrl_lib.h"
|
|
#include "csr_wifi_router_ctrl_sef.h"
|
|
#include "csr_wifi_router_ctrl_converter_init.h"
|
|
#include "csr_wifi_sme_prim.h"
|
|
#include "csr_wifi_sme_sef.h"
|
|
#include "csr_wifi_sme_converter_init.h"
|
|
#ifdef CSR_SUPPORT_WEXT
|
|
#ifdef CSR_SUPPORT_WEXT_AP
|
|
#include "csr_wifi_nme_ap_prim.h"
|
|
#include "csr_wifi_nme_ap_sef.h"
|
|
#include "csr_wifi_nme_ap_converter_init.h"
|
|
#endif
|
|
#endif
|
|
|
|
static unifi_priv_t *drvpriv = NULL;
|
|
void CsrWifiRouterTransportInit(unifi_priv_t *priv)
|
|
{
|
|
unifi_trace(priv, UDBG1, "CsrWifiRouterTransportInit: \n");
|
|
|
|
drvpriv = priv;
|
|
(void)CsrMsgConvInit();
|
|
CsrWifiRouterConverterInit();
|
|
CsrWifiRouterCtrlConverterInit();
|
|
CsrWifiSmeConverterInit();
|
|
#ifdef CSR_SUPPORT_WEXT
|
|
#ifdef CSR_SUPPORT_WEXT_AP
|
|
CsrWifiNmeApConverterInit();
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
void CsrWifiRouterTransportRecv(unifi_priv_t *priv, u8* buffer, size_t bufferLength)
|
|
{
|
|
CsrMsgConvMsgEntry* msgEntry;
|
|
u16 primType;
|
|
CsrSchedQid src;
|
|
CsrSchedQid dest;
|
|
u16 msgType;
|
|
size_t offset = 0;
|
|
CsrWifiFsmEvent* msg;
|
|
|
|
/* Decode the prim and message type */
|
|
CsrUint16Des(&primType, buffer, &offset);
|
|
CsrUint16Des(&src, buffer, &offset);
|
|
CsrUint16Des(&dest, buffer, &offset);
|
|
CsrUint16Des(&msgType, buffer, &offset);
|
|
offset -= 2; /* Adjust as the Deserialise Function will read this as well */
|
|
|
|
unifi_trace(priv, UDBG4, "CsrWifiRouterTransportRecv: primType=0x%.4X, msgType=0x%.4X, bufferLength=%d\n",
|
|
primType, msgType, bufferLength);
|
|
|
|
/* Special handling for HOSTIO messages.... */
|
|
if (primType == CSR_WIFI_HOSTIO_PRIM)
|
|
{
|
|
CsrWifiRouterCtrlHipReq req = {{CSR_WIFI_ROUTER_CTRL_HIP_REQ, CSR_WIFI_ROUTER_CTRL_PRIM, dest, src, NULL}, 0, NULL, 0, NULL, 0, NULL};
|
|
|
|
req.mlmeCommandLength = bufferLength;
|
|
req.mlmeCommand = buffer;
|
|
|
|
offset += 8;/* Skip the id, src, dest and slot number */
|
|
CsrUint16Des(&req.dataRef1Length, buffer, &offset);
|
|
offset += 2; /* Skip the slot number */
|
|
CsrUint16Des(&req.dataRef2Length, buffer, &offset);
|
|
|
|
if (req.dataRef1Length)
|
|
{
|
|
u16 dr1Offset = (bufferLength - req.dataRef2Length) - req.dataRef1Length;
|
|
req.dataRef1 = &buffer[dr1Offset];
|
|
}
|
|
|
|
if (req.dataRef2Length)
|
|
{
|
|
u16 dr2Offset = bufferLength - req.dataRef2Length;
|
|
req.dataRef2 = &buffer[dr2Offset];
|
|
}
|
|
|
|
/* Copy the hip data but strip off the prim type */
|
|
req.mlmeCommandLength -= (req.dataRef1Length + req.dataRef2Length + 6);
|
|
req.mlmeCommand = &buffer[6];
|
|
|
|
CsrWifiRouterCtrlHipReqHandler(priv, &req.common);
|
|
return;
|
|
}
|
|
|
|
msgEntry = CsrMsgConvFindEntry(primType, msgType);
|
|
if (!msgEntry)
|
|
{
|
|
unifi_error(priv, "CsrWifiRouterTransportDeserialiseAndSend can not process the message. primType=0x%.4X, msgType=0x%.4X\n",
|
|
primType, msgType);
|
|
dump(buffer, bufferLength);
|
|
return;
|
|
}
|
|
|
|
msg = (CsrWifiFsmEvent*)(msgEntry->deserFunc)(&buffer[offset], bufferLength - offset);
|
|
|
|
msg->primtype = primType;
|
|
msg->type = msgType;
|
|
msg->source = src;
|
|
msg->destination = dest;
|
|
|
|
switch(primType)
|
|
{
|
|
case CSR_WIFI_ROUTER_CTRL_PRIM:
|
|
CsrWifiRouterCtrlDownstreamStateHandlers[msg->type - CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST](priv, msg);
|
|
CsrWifiRouterCtrlFreeDownstreamMessageContents(CSR_WIFI_ROUTER_CTRL_PRIM, msg);
|
|
break;
|
|
case CSR_WIFI_ROUTER_PRIM:
|
|
CsrWifiRouterDownstreamStateHandlers[msg->type - CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_LOWEST](priv, msg);
|
|
CsrWifiRouterFreeDownstreamMessageContents(CSR_WIFI_ROUTER_PRIM, msg);
|
|
break;
|
|
case CSR_WIFI_SME_PRIM:
|
|
CsrWifiSmeUpstreamStateHandlers[msg->type - CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST](priv, msg);
|
|
CsrWifiSmeFreeUpstreamMessageContents(CSR_WIFI_SME_PRIM, msg);
|
|
break;
|
|
#ifdef CSR_SUPPORT_WEXT
|
|
#ifdef CSR_SUPPORT_WEXT_AP
|
|
case CSR_WIFI_NME_AP_PRIM:
|
|
CsrWifiNmeApUpstreamStateHandlers(priv, msg);
|
|
CsrWifiNmeApFreeUpstreamMessageContents(CSR_WIFI_NME_AP_PRIM, msg);
|
|
break;
|
|
#endif
|
|
#endif
|
|
default:
|
|
unifi_error(priv, "CsrWifiRouterTransportDeserialiseAndSend unhandled prim type 0x%.4X\n", primType);
|
|
break;
|
|
}
|
|
kfree(msg);
|
|
}
|
|
|
|
static void CsrWifiRouterTransportSerialiseAndSend(u16 primType, void* msg)
|
|
{
|
|
CsrWifiFsmEvent* evt = (CsrWifiFsmEvent*)msg;
|
|
CsrMsgConvMsgEntry* msgEntry;
|
|
size_t msgSize;
|
|
size_t encodeBufferLen = 0;
|
|
size_t offset = 0;
|
|
u8* encodeBuffer;
|
|
|
|
unifi_trace(drvpriv, UDBG4, "CsrWifiRouterTransportSerialiseAndSend: primType=0x%.4X, msgType=0x%.4X\n",
|
|
primType, evt->type);
|
|
|
|
msgEntry = CsrMsgConvFindEntry(primType, evt->type);
|
|
if (!msgEntry)
|
|
{
|
|
unifi_error(drvpriv, "CsrWifiRouterTransportSerialiseAndSend can not process the message. primType=0x%.4X, msgType=0x%.4X\n",
|
|
primType, evt->type);
|
|
return;
|
|
}
|
|
|
|
msgSize = 6 + (msgEntry->sizeofFunc)((void*)msg);
|
|
|
|
encodeBuffer = kmalloc(msgSize, GFP_KERNEL);
|
|
|
|
/* Encode PrimType */
|
|
CsrUint16Ser(encodeBuffer, &encodeBufferLen, primType);
|
|
CsrUint16Ser(encodeBuffer, &encodeBufferLen, evt->source);
|
|
CsrUint16Ser(encodeBuffer, &encodeBufferLen, evt->destination);
|
|
|
|
(void)(msgEntry->serFunc)(&encodeBuffer[encodeBufferLen], &offset, msg);
|
|
encodeBufferLen += offset;
|
|
|
|
uf_sme_queue_message(drvpriv, encodeBuffer, encodeBufferLen);
|
|
|
|
/* Do not use msgEntry->freeFunc because the memory is owned by the driver */
|
|
kfree(msg);
|
|
}
|
|
|
|
#if defined(CSR_LOG_ENABLE) && defined(CSR_LOG_INCLUDE_FILE_NAME_AND_LINE_NUMBER)
|
|
void CsrSchedMessagePutStringLog(CsrSchedQid q, u16 mi, void *mv, u32 line, char *file)
|
|
#else
|
|
void CsrSchedMessagePut(CsrSchedQid q, u16 mi, void *mv)
|
|
#endif
|
|
{
|
|
CsrWifiFsmEvent* evt = (CsrWifiFsmEvent*)mv;
|
|
evt->destination = q;
|
|
CsrWifiRouterTransportSerialiseAndSend(mi, mv);
|
|
}
|
|
|