diff options
Diffstat (limited to 'wilink_6_1/stad/src/Ctrl_Interface/CmdHndlr.c')
-rw-r--r-- | wilink_6_1/stad/src/Ctrl_Interface/CmdHndlr.c | 495 |
1 files changed, 495 insertions, 0 deletions
diff --git a/wilink_6_1/stad/src/Ctrl_Interface/CmdHndlr.c b/wilink_6_1/stad/src/Ctrl_Interface/CmdHndlr.c new file mode 100644 index 0000000..b60fa34 --- /dev/null +++ b/wilink_6_1/stad/src/Ctrl_Interface/CmdHndlr.c @@ -0,0 +1,495 @@ +/* + * CmdHndlr.c + * + * Copyright(c) 1998 - 2009 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 CmdHndlr.c + * \brief The Command-Hnadler module. + * + * \see CmdHndlr.h + */ + +#define __FILE_ID__ FILE_ID_48 +#include "tidef.h" +#include "commonTypes.h" +#include "osApi.h" +#include "report.h" +#include "queue.h" +#include "context.h" +#include "CmdHndlr.h" +#include "CmdInterpret.h" +#include "DrvMainModules.h" + + +/* The queue may contain only one command per configuration application so 8 is more than enough */ +#define COMMANDS_QUE_SIZE 8 + +/* Command module internal data */ +typedef struct +{ + TI_HANDLE hOs; + TI_HANDLE hReport; + TI_HANDLE hContext; + TI_HANDLE hCmdInterpret; + + TI_HANDLE hCmdQueue; /* Handle to the commands queue */ + TI_BOOL bProcessingCmds; /* Indicates if currently processing commands */ + TI_UINT32 uContextId; /* ID allocated to this module on registration to context module */ + TConfigCommand *pCurrCmd; /* Pointer to the command currently being processed */ +} TCmdHndlrObj; + +/* External functions prototypes */ +extern void wlanDrvIf_CommandDone (TI_HANDLE hOs, void *pSignalObject, TI_UINT8 *CmdResp_p); + +/** + * \fn cmdHndlr_Create + * \brief Create the module + * + * Create the module object + * + * \note + * \param hOs - Handle to the Os Abstraction Layer + * \return Handle to the allocated module (NULL if failed) + * \sa + */ +TI_HANDLE cmdHndlr_Create (TI_HANDLE hOs, TI_HANDLE hEvHandler) +{ + TCmdHndlrObj *pCmdHndlr = (TCmdHndlrObj *) os_memoryAlloc (hOs, sizeof(TCmdHndlrObj)); + + if (pCmdHndlr == NULL) + { + return NULL; + } + + os_memoryZero (hOs, (void *)pCmdHndlr, sizeof(TCmdHndlrObj)); + + pCmdHndlr->hOs = hOs; + + pCmdHndlr->hCmdInterpret = cmdInterpret_Create (hOs); + + if (pCmdHndlr->hCmdInterpret == NULL) + { + cmdHndlr_Destroy ((TI_HANDLE) pCmdHndlr, (TI_HANDLE) hEvHandler); + return NULL; + } + + return (TI_HANDLE) pCmdHndlr; +} + + +/** + * \fn cmdHndlr_Destroy + * \brief Destroy the module object + * + * Destroy the module object. + * + * \note + * \param hCmdHndlr - The object + * \return TI_OK + * \sa + */ +TI_STATUS cmdHndlr_Destroy (TI_HANDLE hCmdHndlr, TI_HANDLE hEvHandler) +{ + TCmdHndlrObj *pCmdHndlr = (TCmdHndlrObj *)hCmdHndlr; + + if (pCmdHndlr->hCmdInterpret) + { + cmdInterpret_Destroy (pCmdHndlr->hCmdInterpret, hEvHandler); + } + + cmdHndlr_ClearQueue (hCmdHndlr); + + if (pCmdHndlr->hCmdQueue) + { + que_Destroy (pCmdHndlr->hCmdQueue); + } + + os_memoryFree (pCmdHndlr->hOs, hCmdHndlr, sizeof(TCmdHndlrObj)); + + return TI_OK; +} + + +/** + * \fn cmdHndlr_ClearQueue + * \brief Clear commands queue + * + * Dequeue and free all queued commands. + * + * \note + * \param hCmdHndlr - The object + * \return void + * \sa + */ +void cmdHndlr_ClearQueue (TI_HANDLE hCmdHndlr) +{ + TCmdHndlrObj *pCmdHndlr = (TCmdHndlrObj *)hCmdHndlr; + TConfigCommand *pCurrCmd; + + /* Dequeue and free all queued commands */ + do { + context_EnterCriticalSection (pCmdHndlr->hContext); + pCurrCmd = (TConfigCommand *)que_Dequeue(pCmdHndlr->hCmdQueue); + context_LeaveCriticalSection (pCmdHndlr->hContext); + if (pCurrCmd != NULL) { + /* Just release the semaphore. The command is freed subsequently. */ + os_SignalObjectSet (pCmdHndlr->hOs, pCurrCmd->pSignalObject); + } + } while (pCurrCmd != NULL); +} + + +/** + * \fn cmdHndlr_Init + * \brief Init required handles and registries + * + * Init required handles and module variables, create the commands-queue and + * register as the context-engine client. + * + * \note + * \param pStadHandles - The driver modules handles + * \return void + * \sa + */ +void cmdHndlr_Init (TStadHandlesList *pStadHandles) +{ + TCmdHndlrObj *pCmdHndlr = (TCmdHndlrObj *)(pStadHandles->hCmdHndlr); + TI_UINT32 uNodeHeaderOffset; + + pCmdHndlr->hReport = pStadHandles->hReport; + pCmdHndlr->hContext = pStadHandles->hContext; + + cmdInterpret_Init (pCmdHndlr->hCmdInterpret, pStadHandles); + + /* The offset of the queue-node-header from the commands structure entry is needed by the queue */ + uNodeHeaderOffset = TI_FIELD_OFFSET(TConfigCommand, tQueNodeHdr); + + /* Create and initialize the commands queue */ + pCmdHndlr->hCmdQueue = que_Create (pCmdHndlr->hOs, pCmdHndlr->hReport, COMMANDS_QUE_SIZE, uNodeHeaderOffset); + + /* Register to the context engine and get the client ID */ + pCmdHndlr->uContextId = context_RegisterClient (pCmdHndlr->hContext, + cmdHndlr_HandleCommands, + (TI_HANDLE)pCmdHndlr, + TI_FALSE, + "COMMAND", + sizeof("COMMAND")); + + if(pCmdHndlr->hReport != NULL) + { + os_setDebugOutputToLogger(TI_FALSE); + } +} + + +/** + * \fn cmdHndlr_InsertCommand + * \brief Insert a new command to the driver + * + * Insert a new command to the commands queue from user context. + * If commands are not beeing processed set a request to start processing in the driver context. + * Wait on the current command's signal until its processing is completed. + * Note that this prevents the user application from sending further commands before completion. + * + * \note + * \param hCmdHndlr - The module object + * \param cmd - User request + * \param others - The command flags, data and params + * \return TI_OK if command processed successfully, TI_NOK if failed in processing or memory allocation. + * \sa cmdHndlr_HandleCommands, cmdHndlr_Complete + */ +TI_STATUS cmdHndlr_InsertCommand (TI_HANDLE hCmdHndlr, + TI_UINT32 cmd, + TI_UINT32 flags, + void *buffer1, + TI_UINT32 buffer1_len, + void *buffer2, + TI_UINT32 buffer2_len, + TI_UINT32 *param3, + TI_UINT32 *param4) +{ + TCmdHndlrObj *pCmdHndlr = (TCmdHndlrObj *)hCmdHndlr; + TConfigCommand *pNewCmd; + TI_STATUS eStatus; + + /* Allocated command structure */ + pNewCmd = os_memoryAlloc (pCmdHndlr->hOs, sizeof (TConfigCommand)); + if (pNewCmd == NULL) + { + return TI_NOK; + } + + /* Copy user request into local structure */ + pNewCmd->cmd = cmd; + pNewCmd->flags = flags; + pNewCmd->buffer1 = buffer1; + pNewCmd->buffer1_len = buffer1_len; + pNewCmd->buffer2 = buffer2; + pNewCmd->buffer2_len = buffer2_len; + pNewCmd->param3 = param3; + pNewCmd->param4 = param4; + pNewCmd->pSignalObject = os_SignalObjectCreate (pCmdHndlr->hOs); /* initialize "complete-flag" */ + + /* If creating the signal object failed */ + if (pNewCmd->pSignalObject == NULL) + { + os_printf("cmdPerform: Failed to create signalling object\n"); + /* free allocated memory and return error */ + os_memoryFree (pCmdHndlr->hOs, pNewCmd, sizeof (TConfigCommand)); + return TI_NOK; + } + + /* Indicate the start of command process, from adding it to the queue until get return status form it */ + pNewCmd->bWaitFlag = TI_TRUE; + + /* Enter critical section to protect queue access */ + context_EnterCriticalSection (pCmdHndlr->hContext); + + /* Enqueue the command (if failed, release memory and return NOK) */ + eStatus = que_Enqueue (pCmdHndlr->hCmdQueue, (TI_HANDLE)pNewCmd); + if (eStatus != TI_OK) + { + context_LeaveCriticalSection (pCmdHndlr->hContext); /* Leave critical section */ + os_printf("cmdPerform: Failed to enqueue new command\n"); + os_SignalObjectFree (pCmdHndlr->hOs, pNewCmd->pSignalObject); + os_memoryFree (pCmdHndlr->hOs, pNewCmd, sizeof (TConfigCommand)); + return TI_NOK; + } + + /* + * Note: The bProcessingCmds flag is used for indicating if we are already processing + * the queued commands, so the context-engine shouldn't invoke cmdHndlr_HandleCommands. + * This is important because if we make this decision according to the queue being empty, + * there may be a command under processing (already dequeued) while the queue is empty. + * Note that although we are blocking the current command's originator, there may be another + * application that will issue a command. + */ + + if (pCmdHndlr->bProcessingCmds) + { + /* No need to schedule the driver (already handling commands) so just leave critical section */ + context_LeaveCriticalSection (pCmdHndlr->hContext); + } + else + { + /* Indicate that we are handling queued commands (before leaving critical section!) */ + pCmdHndlr->bProcessingCmds = TI_TRUE; + + /* Leave critical section */ + context_LeaveCriticalSection (pCmdHndlr->hContext); + + /* Request driver task schedule for command handling (after we left critical section!) */ + context_RequestSchedule (pCmdHndlr->hContext, pCmdHndlr->uContextId); + } + + /* Wait until the command is executed */ + os_SignalObjectWait (pCmdHndlr->hOs, pNewCmd->pSignalObject); + + /* After "wait" - the command has already been processed by the drivers' context */ + /* Indicate the end of command process, from adding it to the queue until get return status form it */ + pNewCmd->bWaitFlag = TI_FALSE; + + /* Copy the return code */ + eStatus = pNewCmd->return_code; + + /* Free signalling object and command structure */ + os_SignalObjectFree (pCmdHndlr->hOs, pNewCmd->pSignalObject); + + /* If command not completed in this context (Async) don't free the command memory */ + if(COMMAND_PENDING != pNewCmd->eCmdStatus) + { + os_memoryFree (pCmdHndlr->hOs, pNewCmd, sizeof (TConfigCommand)); + } + + /* Return to calling process with command return code */ + return eStatus; +} + + + +/** + * \fn cmdHndlr_HandleCommands + * \brief Handle queued commands + * + * While there are queued commands, dequeue a command and call the + * commands interpreter (OID or WEXT selected at compile time). + * If the command processing is not completed in this context (pending), we exit and + * this function is called again upon commnad completion, so it can continue processing + * further queued commands (if any). + * + * \note + * \param hCmdHndlr - The module object + * \return void + * \sa cmdHndlr_InsertCommand, cmdHndlr_Complete + */ +void cmdHndlr_HandleCommands (TI_HANDLE hCmdHndlr) +{ + TCmdHndlrObj *pCmdHndlr = (TCmdHndlrObj *)hCmdHndlr; + + while (1) + { + /* Enter critical section to protect queue access */ + context_EnterCriticalSection (pCmdHndlr->hContext); + + /* Dequeue a command */ + pCmdHndlr->pCurrCmd = (TConfigCommand *) que_Dequeue (pCmdHndlr->hCmdQueue); + + /* If we have got a command */ + if (pCmdHndlr->pCurrCmd) + { + /* Leave critical section */ + context_LeaveCriticalSection (pCmdHndlr->hContext); + + /* Convert to driver structure and execute command */ + pCmdHndlr->pCurrCmd->eCmdStatus = cmdInterpret_convertAndExecute (pCmdHndlr->hCmdInterpret, pCmdHndlr->pCurrCmd); + + /* + * If command not completed in this context (Async), return. + * (we'll be called back upon command completion) + */ + if(COMMAND_PENDING == pCmdHndlr->pCurrCmd->eCmdStatus) + { + return; + } + + /* Command was completed so free the wait signal and continue to next command */ + wlanDrvIf_CommandDone(pCmdHndlr->hOs, pCmdHndlr->pCurrCmd->pSignalObject, pCmdHndlr->pCurrCmd->CmdRespBuffer); + + pCmdHndlr->pCurrCmd = NULL; + + } + + /* Else, we don't have commands to handle */ + else + { + /* Indicate that we are not handling commands (before leaving critical section!) */ + pCmdHndlr->bProcessingCmds = TI_FALSE; + + /* Leave critical section */ + context_LeaveCriticalSection (pCmdHndlr->hContext); + + /* Exit (no more work) */ + return; + } + } +} + + +/** + * \fn cmdHndlr_Complete + * \brief called whenever a command has finished executing + * + * This routine is called whenever a command has finished executing. + * Either called by the cmdHndlr_HandleCommands if completed in the same context, + * or by the CmdInterpreter module when tcompleted in a later context (Async). + * + * \note + * \param hCmdHndlr - The module object + * \return void + * \sa cmdHndlr_InsertCommand, cmdHndlr_HandleCommands + */ +void cmdHndlr_Complete (TI_HANDLE hCmdHndlr) +{ + TCmdHndlrObj *pCmdHndlr = (TCmdHndlrObj *)hCmdHndlr; + TI_BOOL bLocalWaitFlag; + + if (pCmdHndlr->pCurrCmd) + { + /* set Status to COMPLETE */ + pCmdHndlr->pCurrCmd->eCmdStatus = TI_OK; + + /* save the wait flag before free semaphore */ + bLocalWaitFlag = pCmdHndlr->pCurrCmd->bWaitFlag; + + wlanDrvIf_CommandDone(pCmdHndlr->hOs, pCmdHndlr->pCurrCmd->pSignalObject, pCmdHndlr->pCurrCmd->CmdRespBuffer); + + /* if cmdHndlr_InsertCommand() not wait to cmd complete? */ + if (TI_FALSE == bLocalWaitFlag) + { + /* no wait, free the command memory */ + os_memoryFree (pCmdHndlr->hOs, pCmdHndlr->pCurrCmd, sizeof (TConfigCommand)); + } + + pCmdHndlr->pCurrCmd = NULL; + + return; + } + + TRACE0(pCmdHndlr->hReport, REPORT_SEVERITY_ERROR, "cmdHndlr_Complete(): pCurrCmd is NULL!\n"); +} + + +/** + * \fn cmdHndlr_GetStat + * \brief Get driver statistics + * + * Get the driver statistics (Tx, Rx, signal quality). + * + * \note + * \param hCmdHndlr - The object + * \return The driver statistics pointer + * \sa + */ +void * cmdHndlr_GetStat (TI_HANDLE hCmdHndlr) +{ + TCmdHndlrObj *pCmdHndlr = (TCmdHndlrObj *)hCmdHndlr; + + return cmdInterpret_GetStat (pCmdHndlr->hCmdInterpret); +} + + +/** + * \fn cmdHndlr_Enable & cmdHndlr_Disable + * \brief Enable/Disable invoking CmdHndlr module from driver-task + * + * Called by the Driver-Main Init SM to enable/disable external inputs processing. + * Calls the context-engine enable/disable function accordingly. + * + * \note + * \param hCmdHndlr - The object + * \return void + * \sa + */ +void cmdHndlr_Enable (TI_HANDLE hCmdHndlr) +{ + TCmdHndlrObj *pCmdHndlr = (TCmdHndlrObj *)hCmdHndlr; + + context_EnableClient (pCmdHndlr->hContext, pCmdHndlr->uContextId); +} + +void cmdHndlr_Disable (TI_HANDLE hCmdHndlr) +{ + TCmdHndlrObj *pCmdHndlr = (TCmdHndlrObj *)hCmdHndlr; + + context_DisableClient (pCmdHndlr->hContext, pCmdHndlr->uContextId); +} + |