/** * \fn ifSlpMng_handleRxReady * \brief Interface Sleep Manager state machine for Rx ready event * * Processes receive ready event of Interface Sleep Manager state machine. * Any bytes received in sleep state are treated as awake indication and Rx buffer is cleared. * */ EMcpfRes ifSlpMng_handleRxReady(handle_t hIfSlpMng) { TifSlpMngObj * pIfSlpMng = (TifSlpMngObj *) hIfSlpMng; McpBool stateChanged = MCP_FALSE; MCPF_ENTER_CRIT_SEC (pIfSlpMng->hMcpf); if (pIfSlpMng->eState == IFSLPMNG_STATE_ASLEEP) { pIfSlpMng->eState = IFSLPMNG_STATE_AWAKE; stateChanged = MCP_TRUE; pIfSlpMng->stat.AwakeInd_Rx++; } MCPF_EXIT_CRIT_SEC (pIfSlpMng->hMcpf); if (stateChanged) { MCPF_REPORT_DEBUG_TX(pIfSlpMng->hMcpf,IFSLPMNG_MODULE_LOG, ("ifSlpMng_handleRxReady: Awaking, state=%d\n", pIfSlpMng->eState)); MCP_HAL_PM_TransportWakeup (pIfSlpMng->tChipId, pIfSlpMng->tTransId); busDrv_RxReset (pIfSlpMng->hBusDrv); /* Prepare and send SleepAck request */ TXN_PARAM_SET_IFSLPMNG_OP (pIfSlpMng->pMngTxn, TXN_PARAM_IFSLPMNG_OP_AWAKE_ACK); txnQ_Transact (pIfSlpMng->hTxnQ, pIfSlpMng->pMngTxn); txnQ_Run (pIfSlpMng->hTxnQ, pIfSlpMng->uFuncId); pIfSlpMng->stat.AwakeAck_Tx++; return RES_PENDING; /* indicate the state was sleeping */ } return RES_COMPLETE; }
/** * \fn twIf_HandleSmEvent * \brief The TwIf SM implementation * * Handle SM event. * Control the device awake/sleep states and the TxnQ run/stop states according to the event. * * \note * \param hTwIf - The module's object * \return void * \sa */ static void twIf_HandleSmEvent (TTwIfObj *pTwIf, ESmEvent eEvent) { ESmState eState = pTwIf->eState; /* The state before handling the event */ /* Switch by current state and handle event */ switch (eState) { case SM_STATE_AWAKE: /* SLEEP event: AWAKE ==> SLEEP, stop TxnQ and set ELP reg to sleep */ if (eEvent == SM_EVENT_SLEEP) { pTwIf->eState = SM_STATE_SLEEP; txnQ_Stop (pTwIf->hTxnQ, TXN_FUNC_ID_WLAN); twIf_WriteElpReg (pTwIf, ELP_CTRL_REG_SLEEP); } break; case SM_STATE_SLEEP: /* START event: SLEEP ==> WAIT_HW, set ELP reg to wake-up */ if (eEvent == SM_EVENT_START) { pTwIf->eState = SM_STATE_WAIT_HW; twIf_WriteElpReg (pTwIf, ELP_CTRL_REG_AWAKE); } /* HW_AVAILABLE event: SLEEP ==> AWAKE, set ELP reg to wake-up and run TxnQ */ else if (eEvent == SM_EVENT_HW_AVAILABLE) { pTwIf->eState = SM_STATE_AWAKE; twIf_WriteElpReg (pTwIf, ELP_CTRL_REG_AWAKE); txnQ_Run (pTwIf->hTxnQ, TXN_FUNC_ID_WLAN); } break; case SM_STATE_WAIT_HW: /* HW_AVAILABLE event: WAIT_HW ==> AWAKE, run TxnQ */ if (eEvent == SM_EVENT_HW_AVAILABLE) { pTwIf->eState = SM_STATE_AWAKE; txnQ_Run (pTwIf->hTxnQ, TXN_FUNC_ID_WLAN); } break; } }
EMcpfRes ifSlpMng_Reinit (handle_t hIfSlpMng) { TifSlpMngObj * pIfSlpMng = (TifSlpMngObj *) hIfSlpMng; McpHalPmHandler pmHandler = {pmEventHandler}; MCPF_ENTER_CRIT_SEC (pIfSlpMng->hMcpf); pIfSlpMng->eState = IFSLPMNG_STATE_AWAKE; MCPF_EXIT_CRIT_SEC (pIfSlpMng->hMcpf); txnQ_Stop (pIfSlpMng->hTxnQ, pIfSlpMng->uFuncId); txnQ_Run (pIfSlpMng->hTxnQ, pIfSlpMng->uFuncId); MCP_HAL_PM_RegisterTransport (pIfSlpMng->tChipId, pIfSlpMng->tTransId, &pmHandler); return RES_OK; }
/** * \fn ifSlpMng_HandleRxEvent * \brief Interface Sleep Manager state machine for Rx event * * Process Rx event of Interface Sleep Manager state machine * */ EIfSlpMngStatus ifSlpMng_HandleRxEvent (handle_t hIfSlpMng, TTxnStruct *pTxn) { TifSlpMngObj * pIfSlpMng = (TifSlpMngObj *) hIfSlpMng; EIfSlpMngStatus eRes = IfSlpMng_ERR; McpBool stateChanged = MCP_FALSE; if (TXN_PARAM_GET_SINGLE_STEP (pTxn)) { /* IfSlpMng transaction is always single step, * get IfSlpMng opcode from transaction structure */ eRes = IfSlpMng_SLP_PKT_TYPE; switch (TXN_PARAM_GET_IFSLPMNG_OP (pTxn)) { case TXN_PARAM_IFSLPMNG_OP_SLEEP: MCPF_REPORT_DEBUG_RX(pIfSlpMng->hMcpf, IFSLPMNG_MODULE_LOG, ("ifSlpMng_HandleRxEvent: SLEEP_IND, state=%d\n",pIfSlpMng->eState)); MCPF_ENTER_CRIT_SEC (pIfSlpMng->hMcpf); if (pIfSlpMng->eState == IFSLPMNG_STATE_AWAKE) { pIfSlpMng->eState = IFSLPMNG_STATE_WAIT_FOR_SLEEPACK_TX_COMPL; stateChanged = MCP_TRUE; } pIfSlpMng->stat.SleepInd_Rx++; MCPF_EXIT_CRIT_SEC (pIfSlpMng->hMcpf); if (stateChanged) { txnQ_Stop (pIfSlpMng->hTxnQ, pIfSlpMng->uFuncId); /* Prepare and send SleepAck request */ TXN_PARAM_SET_IFSLPMNG_OP (pIfSlpMng->pMngTxn, TXN_PARAM_IFSLPMNG_OP_SLEEP_ACK); txnQ_Transact (pIfSlpMng->hTxnQ, pIfSlpMng->pMngTxn); pIfSlpMng->stat.SleepAck_Tx++; } break; case TXN_PARAM_IFSLPMNG_OP_SLEEP_ACK: MCPF_REPORT_ERROR (pIfSlpMng->hMcpf, IFSLPMNG_MODULE_LOG, ("%s: Not expected SleepAck received\n", __FUNCTION__)); pIfSlpMng->stat.SleepAck_Rx++; break; case TXN_PARAM_IFSLPMNG_OP_AWAKE: { EIfSlpMngState oldState; MCPF_REPORT_DEBUG_RX(pIfSlpMng->hMcpf, IFSLPMNG_MODULE_LOG, ("ifSlpMng_HandleRxEvent: AWAKE_IND, state=%d\n",pIfSlpMng->eState)); MCPF_ENTER_CRIT_SEC (pIfSlpMng->hMcpf); oldState = pIfSlpMng->eState; if ((pIfSlpMng->eState == IFSLPMNG_STATE_ASLEEP) || (pIfSlpMng->eState == IFSLPMNG_STATE_WAIT_FOR_AWAKE_ACK)) { pIfSlpMng->eState = IFSLPMNG_STATE_AWAKE; stateChanged = MCP_TRUE; } pIfSlpMng->stat.AwakeInd_Rx++; MCPF_EXIT_CRIT_SEC (pIfSlpMng->hMcpf); if (stateChanged) { switch (oldState) { case IFSLPMNG_STATE_ASLEEP: /* Prepare and send SleepAck request */ TXN_PARAM_SET_IFSLPMNG_OP (pIfSlpMng->pMngTxn, TXN_PARAM_IFSLPMNG_OP_AWAKE_ACK); txnQ_Transact (pIfSlpMng->hTxnQ, pIfSlpMng->pMngTxn); txnQ_Run (pIfSlpMng->hTxnQ, pIfSlpMng->uFuncId); pIfSlpMng->stat.AwakeAck_Tx++; break; case IFSLPMNG_STATE_WAIT_FOR_AWAKE_ACK: txnQ_Run (pIfSlpMng->hTxnQ, pIfSlpMng->uFuncId); break; default: break; } } } break; case TXN_PARAM_IFSLPMNG_OP_AWAKE_ACK: MCPF_REPORT_DEBUG_RX(pIfSlpMng->hMcpf, IFSLPMNG_MODULE_LOG, ("ifSlpMng_HandleRxEvent: AWAKE_ACK, state=%d\n",pIfSlpMng->eState)); MCPF_ENTER_CRIT_SEC (pIfSlpMng->hMcpf); if (pIfSlpMng->eState == IFSLPMNG_STATE_WAIT_FOR_AWAKE_ACK) { pIfSlpMng->eState = IFSLPMNG_STATE_AWAKE; stateChanged = MCP_TRUE; } pIfSlpMng->stat.AwakeAck_Rx++; MCPF_EXIT_CRIT_SEC (pIfSlpMng->hMcpf); if (stateChanged) { txnQ_Run (pIfSlpMng->hTxnQ, pIfSlpMng->uFuncId); } break; default: MCPF_REPORT_ERROR (pIfSlpMng->hMcpf, IFSLPMNG_MODULE_LOG, ("%s: Invalid IfSlpMng opcode=%u\n", __FUNCTION__, TXN_PARAM_GET_IFSLPMNG_OP (pTxn))); eRes = IfSlpMng_ERR; break; } /* Rx IFSLPMNG_OP */ } else { /* Normal packet received */ MCPF_ENTER_CRIT_SEC (pIfSlpMng->hMcpf); if (pIfSlpMng->eState == IFSLPMNG_STATE_ASLEEP) { pIfSlpMng->eState = IFSLPMNG_STATE_AWAKE; stateChanged = MCP_TRUE; pIfSlpMng->stat.AwakeAck_Tx++; } MCPF_EXIT_CRIT_SEC (pIfSlpMng->hMcpf); if (stateChanged) { /* Prepare and send SleepAck request */ TXN_PARAM_SET_IFSLPMNG_OP (pIfSlpMng->pMngTxn, TXN_PARAM_IFSLPMNG_OP_AWAKE_ACK); txnQ_Transact (pIfSlpMng->hTxnQ, pIfSlpMng->pMngTxn); txnQ_Run (pIfSlpMng->hTxnQ, pIfSlpMng->uFuncId); MCPF_REPORT_DEBUG_RX(pIfSlpMng->hMcpf, IFSLPMNG_MODULE_LOG, ("ifSlpMng_HandleRxEvent: Normal RX, state=%d\n",pIfSlpMng->eState)); } eRes = IfSlpMng_OK; } return eRes; }