/** @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); }