diff options
Diffstat (limited to 'drivers/staging/csr/csr_wifi_router_transport.c')
-rw-r--r-- | drivers/staging/csr/csr_wifi_router_transport.c | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/drivers/staging/csr/csr_wifi_router_transport.c b/drivers/staging/csr/csr_wifi_router_transport.c new file mode 100644 index 000000000000..e905ead9389b --- /dev/null +++ b/drivers/staging/csr/csr_wifi_router_transport.c @@ -0,0 +1,199 @@ +/** @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); +} + |