/* * measurementMgrSM.c * * Copyright(c) 1998 - 2010 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. */ /**************************************************************************/ /* */ /* MODULE: measurementMgrSM.c */ /* PURPOSE: Measurement Manager State Machine module interface. */ /* */ /**************************************************************************/ #define __FILE_ID__ FILE_ID_2 #include "measurementMgrSM.h" #include "measurementMgr.h" #include "802_11Defs.h" #ifdef XCC_MODULE_INCLUDED #include "XCCMngr.h" #include "XCCRMMngr.h" #endif #include "spectrumMngmntMgr.h" #include "siteMgrApi.h" #include "MacServices_api.h" #include "regulatoryDomainApi.h" #include "TWDriver.h" #include "timer.h" #include "sme.h" char * measurementMgr_stateDesc[MEASUREMENTMGR_NUM_STATES] = { "STATE_IDLE", "STATE_PROCESSING_REQUEST", "STATE_WAITING_FOR_SCR", "STATE_MEASURING" }; char * measurementMgr_eventDesc[MEASUREMENTMGR_NUM_EVENTS] = { "EVENT_CONNECTED", "EVENT_DISCONNECTED", "EVENT_ENABLE", "EVENT_DISABLE", "EVENT_FRAME_RECV", "EVENT_SEND_REPORT", "EVENT_REQUEST_SCR", "EVENT_SCR_WAIT", "EVENT_SCR_RUN", "EVENT_ABORT", "EVENT_COMPLETE", "EVENT_FW_RESET" }; /********************************************************************************/ /* MeasurementMgr SM Action Prototypes */ /********************************************************************************/ static TI_STATUS measurementMgrSM_acUnexpected(void * pData); static TI_STATUS measurementMgrSM_acNop(void * pData); static TI_STATUS measurementMgrSM_acConnected(void * pData); static TI_STATUS measurementMgrSM_acDisconnected_fromIdle(void * pData); static TI_STATUS measurementMgrSM_acEnable(void * pData); static TI_STATUS measurementMgrSM_acDisable_fromIdle(void * pData); static TI_STATUS measurementMgrSM_acFrameReceived_fromIdle(void * pData); static TI_STATUS measurementMgrSM_acSendReportAndCleanObj(void * pData); static TI_STATUS measurementMgrSM_acDisconnected_fromProcessingRequest(void * pData); static TI_STATUS measurementMgrSM_acDisable_fromProcessingRequest(void * pData); static TI_STATUS measurementMgrSM_acFrameReceived_fromProcessingRequest(void * pData); static TI_STATUS measurementMgrSM_acAbort_fromProcessingRequest(void * pData); static TI_STATUS measurementMgrSM_acRequestSCR(void * pData); static TI_STATUS measurementMgrSM_acDisconnected_fromWaitForSCR(void * pData); static TI_STATUS measurementMgrSM_acDisable_fromWaitForSCR(void * pData); static TI_STATUS measurementMgrSM_acFrameReceived_fromWaitForSCR(void * pData); static TI_STATUS measurementMgrSM_acAbort_fromWaitForSCR(void * pData); static TI_STATUS measurementMgrSM_acStartMeasurement(void * pData); static TI_STATUS measurementMgrSM_acDisconnected_fromMeasuring(void * pData); static TI_STATUS measurementMgrSM_acDisable_fromMeasuring(void * pData); static TI_STATUS measurementMgrSM_acFrameReceived_fromMeasuring(void * pData); static TI_STATUS measurementMgrSM_acAbort_fromMeasuring(void * pData); static TI_STATUS measurementMgrSM_acMeasurementComplete(void * pData); static TI_STATUS measurementMgrSM_acFirmwareReset(void * pData); /********************************************************************************/ /* Internal Functions Prototypes */ /********************************************************************************/ static void measurementMgrSM_resetParams(measurementMgr_t * pMeasurementMgr); static void measurementMgrSM_uponActivationDelayTimeout (TI_HANDLE hMeasurementMgr, TI_BOOL bTwdInitOccured); /********************************************************************************/ /* MeasurementMgr SM General Use Functions */ /********************************************************************************/ /** * Configures the Measurement Manager State Machine. * * @param hMeasurementMgr A handle to the Measurement Manager module. * * @date 01-Jan-2006 */ TI_STATUS measurementMgrSM_config(TI_HANDLE hMeasurementMgr) { measurementMgr_t * pMeasurementMgr = (measurementMgr_t *) hMeasurementMgr; TI_STATUS status; /* MeasurementMgr State Machine matrix */ fsm_actionCell_t measurementMgr_matrix[MEASUREMENTMGR_NUM_STATES][MEASUREMENTMGR_NUM_EVENTS] = { /* next state and actions for STATE_IDLE state */ { {MEASUREMENTMGR_STATE_IDLE, measurementMgrSM_acConnected}, /* CONNECTED */ {MEASUREMENTMGR_STATE_IDLE, measurementMgrSM_acDisconnected_fromIdle}, /* DISCONNECTED */ {MEASUREMENTMGR_STATE_IDLE, measurementMgrSM_acEnable}, /* ENABLE */ {MEASUREMENTMGR_STATE_IDLE, measurementMgrSM_acDisable_fromIdle}, /* DISABLE */ {MEASUREMENTMGR_STATE_PROCESSING_REQUEST, measurementMgrSM_acFrameReceived_fromIdle}, /* FRAME_RECV */ {MEASUREMENTMGR_STATE_IDLE, measurementMgrSM_acSendReportAndCleanObj}, /* SEND_REPORT */ {MEASUREMENTMGR_STATE_IDLE, measurementMgrSM_acUnexpected}, /* REQUEST_SCR */ {MEASUREMENTMGR_STATE_IDLE, measurementMgrSM_acUnexpected}, /* SCR_WAIT */ {MEASUREMENTMGR_STATE_IDLE, measurementMgrSM_acUnexpected}, /* SCR_RUN */ {MEASUREMENTMGR_STATE_IDLE, measurementMgrSM_acUnexpected}, /* ABORT */ {MEASUREMENTMGR_STATE_IDLE, measurementMgrSM_acUnexpected}, /* COMPLETE */ {MEASUREMENTMGR_STATE_IDLE, measurementMgrSM_acUnexpected} /* FW_RESET */ }, /* next state and actions for STATE_PROCESSING_REQUEST state */ { {MEASUREMENTMGR_STATE_PROCESSING_REQUEST, measurementMgrSM_acUnexpected}, /* CONNECTED */ {MEASUREMENTMGR_STATE_IDLE, measurementMgrSM_acDisconnected_fromProcessingRequest}, /* DISCONNECTED */ {MEASUREMENTMGR_STATE_PROCESSING_REQUEST, measurementMgrSM_acNop}, /* ENABLE */ {MEASUREMENTMGR_STATE_IDLE, measurementMgrSM_acDisable_fromProcessingRequest}, /* DISABLE */ {MEASUREMENTMGR_STATE_PROCESSING_REQUEST, measurementMgrSM_acFrameReceived_fromProcessingRequest}, /* FRAME_RECV */ {MEASUREMENTMGR_STATE_IDLE, measurementMgrSM_acSendReportAndCleanObj}, /* SEND_REPORT */ {MEASUREMENTMGR_STATE_WAITING_FOR_SCR, measurementMgrSM_acRequestSCR}, /* REQUEST_SCR */ {MEASUREMENTMGR_STATE_PROCESSING_REQUEST, measurementMgrSM_acUnexpected}, /* SCR_WAIT */ {MEASUREMENTMGR_STATE_PROCESSING_REQUEST, measurementMgrSM_acUnexpected}, /* SCR_RUN */ {MEASUREMENTMGR_STATE_IDLE, measurementMgrSM_acAbort_fromProcessingRequest}, /* ABORT */ {MEASUREMENTMGR_STATE_PROCESSING_REQUEST, measurementMgrSM_acUnexpected}, /* COMPLETE */ {MEASUREMENTMGR_STATE_PROCESSING_REQUEST, measurementMgrSM_acUnexpected} /* FW_RESET */ }, /* next state and actions for STATE_WAITING_FOR_SCR state */ { {MEASUREMENTMGR_STATE_WAITING_FOR_SCR, measurementMgrSM_acUnexpected}, /* CONNECTED */ {MEASUREMENTMGR_STATE_IDLE, measurementMgrSM_acDisconnected_fromWaitForSCR}, /* DISCONNECTED */ {MEASUREMENTMGR_STATE_WAITING_FOR_SCR, measurementMgrSM_acNop}, /* ENABLE */ {MEASUREMENTMGR_STATE_IDLE, measurementMgrSM_acDisable_fromWaitForSCR}, /* DISABLE */ {MEASUREMENTMGR_STATE_PROCESSING_REQUEST, measurementMgrSM_acFrameReceived_fromWaitForSCR}, /* FRAME_RECV */ {MEASUREMENTMGR_STATE_WAITING_FOR_SCR, measurementMgrSM_acUnexpected}, /* SEND_REPORT */ {MEASUREMENTMGR_STATE_WAITING_FOR_SCR, measurementMgrSM_acUnexpected}, /* REQUEST_SCR */ {MEASUREMENTMGR_STATE_WAITING_FOR_SCR, measurementMgrSM_acNop}, /* SCR_WAIT */ {MEASUREMENTMGR_STATE_MEASURING, measurementMgrSM_acStartMeasurement}, /* SCR_RUN */ {MEASUREMENTMGR_STATE_IDLE, measurementMgrSM_acAbort_fromWaitForSCR}, /* ABORT */ {MEASUREMENTMGR_STATE_WAITING_FOR_SCR, measurementMgrSM_acUnexpected}, /* COMPLETE */ {MEASUREMENTMGR_STATE_WAITING_FOR_SCR, measurementMgrSM_acUnexpected} /* FW_RESET */ }, /* next state and actions for STATE_MEASURING state */ { {MEASUREMENTMGR_STATE_MEASURING, measurementMgrSM_acUnexpected}, /* CONNECTED */ {MEASUREMENTMGR_STATE_IDLE, measurementMgrSM_acDisconnected_fromMeasuring}, /* DISCONNECTED */ {MEASUREMENTMGR_STATE_MEASURING, measurementMgrSM_acNop}, /* ENABLE */ {MEASUREMENTMGR_STATE_IDLE, measurementMgrSM_acDisable_fromMeasuring}, /* DISABLE */ {MEASUREMENTMGR_STATE_PROCESSING_REQUEST, measurementMgrSM_acFrameReceived_fromMeasuring}, /* FRAME_RECV */ {MEASUREMENTMGR_STATE_MEASURING, measurementMgrSM_acUnexpected}, /* SEND_REPORT */ {MEASUREMENTMGR_STATE_MEASURING, measurementMgrSM_acUnexpected}, /* REQUEST_SCR */ {MEASUREMENTMGR_STATE_MEASURING, measurementMgrSM_acUnexpected}, /* SCR_WAIT */ {MEASUREMENTMGR_STATE_MEASURING, measurementMgrSM_acUnexpected}, /* SCR_RUN */ {MEASUREMENTMGR_STATE_IDLE, measurementMgrSM_acAbort_fromMeasuring}, /* ABORT */ {MEASUREMENTMGR_STATE_PROCESSING_REQUEST, measurementMgrSM_acMeasurementComplete}, /* COMPLETE */ {MEASUREMENTMGR_STATE_IDLE, measurementMgrSM_acFirmwareReset} /* FW_RESET */ } }; TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Configured MeasurementMgr state machine\n"); status = fsm_Config(pMeasurementMgr->pMeasurementMgrSm, &measurementMgr_matrix[0][0], MEASUREMENTMGR_NUM_STATES, MEASUREMENTMGR_NUM_EVENTS, measurementMgrSM_event, pMeasurementMgr->hOs); return status; } /** * Raises a State Machine event in the Measurement Manager SM. * * @param currentState A point to the member holding the SM's current state. * @param event The event we want to raise. * @param hMeasurementMgr A handle to the Measurement Manager module. * * @date 05-Jan-2006 */ TI_STATUS measurementMgrSM_event(TI_UINT8 * currentState, TI_UINT8 event, TI_HANDLE hMeasurementMgr) { measurementMgr_t * pMeasurementMgr = (measurementMgr_t *) hMeasurementMgr; TI_STATUS status; TI_UINT8 nextState; status = fsm_GetNextState(pMeasurementMgr->pMeasurementMgrSm, *currentState, event, &nextState); if (status != TI_OK) { TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": State machine error, failed getting next state\n"); return(TI_NOK); } TRACE3(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, "measurementMgrSM_event: <currentState = %d, event = %d> --> nextState = %d\n", currentState, event, nextState); status = fsm_Event(pMeasurementMgr->pMeasurementMgrSm, currentState, event, (void *) pMeasurementMgr); return status; } /********************************************************************************/ /* MeasurementMgr SM Action Functions */ /********************************************************************************/ /********************************************************************************/ /* IDLE State Actions */ /********************************************************************************/ /** * Performs the required action when the Measurement Manager module has * been advised that the station has connected to an AP. * * @date 05-Jan-2006 */ static TI_STATUS measurementMgrSM_acConnected(void * pData) { measurementMgr_t * pMeasurementMgr = (measurementMgr_t *) pData; paramInfo_t param; #ifdef XCC_MODULE_INCLUDED iappParsingRegistrationTable_t iappParsingRegistration; #endif /* do nothing if we're already in connected mode */ if (pMeasurementMgr->Connected) { TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Connected flag already set\n"); return TI_OK; } pMeasurementMgr->Connected = TI_TRUE; TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Connected flag has been set\n"); /* upon connection to a new AP set the measurment scan flag to FALSE */ pMeasurementMgr->bMeasurementScanExecuted = TI_FALSE; /* get the current serving channel */ param.paramType = SITE_MGR_CURRENT_CHANNEL_PARAM; siteMgr_getParam(pMeasurementMgr->hSiteMgr, ¶m); pMeasurementMgr->servingChannelID = param.content.siteMgrCurrentChannel; #ifdef XCC_MODULE_INCLUDED if(pMeasurementMgr->Mode == MSR_MODE_XCC) { TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": MeasurementMgr set to XCC mode\n"); if(pMeasurementMgr->isModuleRegistered == TI_FALSE) { /* Registering to the XCCMngr */ iappParsingRegistration.handler = pMeasurementMgr; iappParsingRegistration.iappParsingRegistrationProcedure = measurementMgr_XCCParse; if (XCCMngr_registerForRecvIappPacket(pMeasurementMgr->hXCCMngr, iappParsingRegistration, IAPP_RADIO_MEASUREMENT) != TI_OK) { TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_WARNING, ": Could not register to receive IAPP packets\n"); return TI_NOK; } pMeasurementMgr->isModuleRegistered = TI_TRUE; } pMeasurementMgr->parserFrameReq = measurementMgr_XCCParseFrameReq; pMeasurementMgr->isTypeValid = measurementMgr_XCCIsTypeValid; pMeasurementMgr->buildReport = measurementMgr_XCCBuildReport; pMeasurementMgr->buildRejectReport = measurementMgr_XCCBuildRejectReport; pMeasurementMgr->sendReportAndCleanObj = measurementMgr_XCCSendReportAndCleanObject; requestHandler_setRequestParserFunction(pMeasurementMgr->hRequestH, measurementMgr_XCCParseRequestIEHdr); } else #endif { if(pMeasurementMgr->Mode == MSR_MODE_SPECTRUM_MANAGEMENT) { TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": MeasurementMgr set to Spectrum Management mode\n"); /* NOTE: These 5 functions need to be corrected to fit the 802.11h standered */ pMeasurementMgr->parserFrameReq = measurementMgr_dot11hParseFrameReq; pMeasurementMgr->isTypeValid = measurementMgr_dot11hIsTypeValid; pMeasurementMgr->buildReport = measurementMgr_dot11hBuildReport; pMeasurementMgr->buildRejectReport = measurementMgr_dot11hBuildRejectReport; pMeasurementMgr->sendReportAndCleanObj = measurementMgr_dot11hSendReportAndCleanObject; requestHandler_setRequestParserFunction(pMeasurementMgr->hRequestH, measurementMgr_dot11hParseRequestIEHdr); } } return TI_OK; } /** * Called when the Measurement Manager has been advised that the station * has disconnected from the AP. * * @date 05-Jan-2006 */ static TI_STATUS measurementMgrSM_acDisconnected_fromIdle(void * pData) { measurementMgr_t * pMeasurementMgr = (measurementMgr_t *) pData; TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Connected flag unset\n"); pMeasurementMgr->Connected = TI_FALSE; return TI_OK; } /** * Called when the Measurement Manager is enabled. * * @date 05-Jan-2006 */ static TI_STATUS measurementMgrSM_acEnable(void * pData) { measurementMgr_t * pMeasurementMgr = (measurementMgr_t *) pData; TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Measurement Manager has been enabled\n"); pMeasurementMgr->Enabled = TI_TRUE; return TI_OK; } /** * Called when the Measurement Manager is disabled. * * @date 05-Jan-2006 */ static TI_STATUS measurementMgrSM_acDisable_fromIdle(void * pData) { measurementMgr_t * pMeasurementMgr = (measurementMgr_t *) pData; TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Measurement Manager has been disabled\n"); pMeasurementMgr->Enabled = TI_FALSE; return TI_OK; } /** * Called when the SM is in an idle state and we receive a new measurement frame. * * @date 05-Jan-2006 */ static TI_STATUS measurementMgrSM_acFrameReceived_fromIdle(void * pData) { measurementMgr_t * pMeasurementMgr = (measurementMgr_t *) pData; TI_UINT16 activationDelay; TI_STATUS status; paramInfo_t param; TI_UINT16 tbtt; /* handle frame request only if we're connected and measurement is enabled */ if (pMeasurementMgr->Connected == TI_FALSE || pMeasurementMgr->Enabled == TI_FALSE) { TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_ERROR, ": Frame received while SM is in disconnected/disabled state\n"); return measurementMgrSM_event((TI_UINT8 *) &(pMeasurementMgr->currentState), MEASUREMENTMGR_EVENT_ABORT, pMeasurementMgr); } /* Setting the frame Type */ pMeasurementMgr->currentFrameType = pMeasurementMgr->newFrameRequest.frameType; TRACE1(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Frame Type = %d\n", pMeasurementMgr->currentFrameType); /* Getting the Beacon Interval from the Site Mgr */ param.paramType = SITE_MGR_BEACON_INTERVAL_PARAM; status = siteMgr_getParam(pMeasurementMgr->hSiteMgr, ¶m); if (status != TI_OK) { TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_ERROR, ": Failed to retrieve beacon interval - not connected?\n"); return measurementMgrSM_event((TI_UINT8 *) &(pMeasurementMgr->currentState), MEASUREMENTMGR_EVENT_ABORT, pMeasurementMgr); } /* converting beacon interval to msec */ tbtt = (param.content.beaconInterval * 1024) / 1000; /* from TU to msec */ /* Initializing Activation Delay Time */ activationDelay = pMeasurementMgr->newFrameRequest.hdr->activatioDelay; activationDelay *= tbtt; /* Adding the Measurement Offset to the activation delay */ activationDelay += pMeasurementMgr->newFrameRequest.hdr->measurementOffset; /* Inserting all received measurement requests into the queue */ status = requestHandler_insertRequests(pMeasurementMgr->hRequestH, pMeasurementMgr->Mode, pMeasurementMgr->newFrameRequest); /* Clean New Frame Params */ os_memoryZero(pMeasurementMgr->hOs, &pMeasurementMgr->newFrameRequest, sizeof(TMeasurementFrameRequest)); if (status != TI_OK) { pMeasurementMgr->currentFrameType = MSR_FRAME_TYPE_NO_ACTIVE; TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_ERROR, ": Could not insert request into the queue\n"); return measurementMgrSM_event((TI_UINT8 *) &(pMeasurementMgr->currentState), MEASUREMENTMGR_EVENT_ABORT, pMeasurementMgr); } TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": New frame has been inserted into the queue\n"); /* If frame type isn't Unicast add to Activation Delay a random delay */ if ((pMeasurementMgr->currentFrameType != MSR_FRAME_TYPE_UNICAST) && (activationDelay > 0)) { activationDelay += ((os_timeStampMs(pMeasurementMgr->hOs) % MSR_ACTIVATION_DELAY_RANDOM) + MSR_ACTIVATION_DELAY_OFFSET); } TRACE1(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Activation Delay in ms = %d\n", activationDelay); if (activationDelay > 0) { TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Going to wait for activation delay timer callback\n"); /* Starting the Activation Delay Timer */ tmr_StartTimer (pMeasurementMgr->hActivationDelayTimer, measurementMgrSM_uponActivationDelayTimeout, (TI_HANDLE)pMeasurementMgr, activationDelay, TI_FALSE); return TI_OK; } else { TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Activating the next request immediately without waiting for callback\n"); /* Calling to schedule the first waiting request */ return measurementMgr_activateNextRequest(pData); } } /********************************************************************************/ /* PROCESSING_REQUEST State Actions */ /********************************************************************************/ /** * Called when the station disconnects from the AP while processing * a measurement request. * * @date 05-Jan-2006 */ static TI_STATUS measurementMgrSM_acDisconnected_fromProcessingRequest(void * pData) { measurementMgr_t * pMeasurementMgr = (measurementMgr_t *) pData; /* Stopping the activationDelay Timer */ tmr_StopTimer (pMeasurementMgr->hActivationDelayTimer); /* Clear Measurement fields */ measurementMgrSM_resetParams(pMeasurementMgr); pMeasurementMgr->Connected = TI_FALSE; return TI_OK; } /** * Called when the Measurement Manager module has been disable while * processing a measurement request. * * @date 05-Jan-2006 */ static TI_STATUS measurementMgrSM_acDisable_fromProcessingRequest(void * pData) { measurementMgr_t * pMeasurementMgr = (measurementMgr_t *) pData; /* Stopping the activationDelay Timer */ tmr_StopTimer (pMeasurementMgr->hActivationDelayTimer); /* Clear Measurement fields */ measurementMgrSM_resetParams(pMeasurementMgr); pMeasurementMgr->Enabled = TI_FALSE; return TI_OK; } /** * Called when a frame has been received while we are processing another frame. * In this case the older frame is discarded and the new frame is processed. * * @date 05-Jan-2006 */ static TI_STATUS measurementMgrSM_acFrameReceived_fromProcessingRequest(void * pData) { measurementMgr_t * pMeasurementMgr = (measurementMgr_t *) pData; /* Stopping the activationDelay Timer */ tmr_StopTimer (pMeasurementMgr->hActivationDelayTimer); /* Clear Measurement fields */ measurementMgrSM_resetParams(pMeasurementMgr); /* Process New Frame */ return measurementMgrSM_acFrameReceived_fromIdle(pData); } /** * Sends measurement reports to the AP and cleans up the module. * * @date 05-Jan-2006 */ static TI_STATUS measurementMgrSM_acSendReportAndCleanObj(void * pData) { measurementMgr_t * pMeasurementMgr = (measurementMgr_t *) pData; TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Sending pending reports and cleaning up...\n"); return pMeasurementMgr->sendReportAndCleanObj(pData); } /** * Called when for some reason we abort while processing a request. * * @date 05-Jan-2006 */ static TI_STATUS measurementMgrSM_acAbort_fromProcessingRequest(void * pData) { measurementMgr_t * pMeasurementMgr = (measurementMgr_t *) pData; TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Entered\n"); /* Stopping the activationDelay Timer */ tmr_StopTimer (pMeasurementMgr->hActivationDelayTimer); /* Clear Measurement fields */ measurementMgrSM_resetParams(pMeasurementMgr); return TI_OK; } /** * Called when we finished processing a request and want to request the SCR. * * @date 05-Jan-2006 */ static TI_STATUS measurementMgrSM_acRequestSCR(void * pData) { measurementMgr_t * pMeasurementMgr = (measurementMgr_t *) pData; EScrClientRequestStatus scrStatus; EScePendReason scrPendReason; /* Request the channel */ scrStatus = scr_clientRequest(pMeasurementMgr->hScr, SCR_CID_XCC_MEASURE, SCR_RESOURCE_SERVING_CHANNEL, &scrPendReason); if (scrStatus == SCR_CRS_RUN) { TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Received RUN response from SCR\n"); /* The channel is allocated for the measurement */ return measurementMgrSM_event((TI_UINT8 *) &(pMeasurementMgr->currentState), MEASUREMENTMGR_EVENT_SCR_RUN, pMeasurementMgr); } else if ((scrStatus == SCR_CRS_PEND) && (scrPendReason == SCR_PR_DIFFERENT_GROUP_RUNNING)) { TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Received PEND/DIFFGROUP response from SCR\n"); /* No need to wait for the channel allocation */ return measurementMgrSM_event((TI_UINT8 *) &(pMeasurementMgr->currentState), MEASUREMENTMGR_EVENT_ABORT, pMeasurementMgr); } TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Going to wait for SCR callback...\n"); /* In all other cases wait for the callback function to be called */ return TI_OK; } /********************************************************************************/ /* WAIT_FOR_SCR State Actions */ /********************************************************************************/ /** * Called if the station disconnects from the AP while waiting for a * response from the SCR. * * @date 05-Jan-2006 */ static TI_STATUS measurementMgrSM_acDisconnected_fromWaitForSCR(void * pData) { measurementMgr_t * pMeasurementMgr = (measurementMgr_t *) pData; setDefaultProbeReqTemplate (pMeasurementMgr->hSiteMgr); /* Release the SCR */ scr_clientComplete(pMeasurementMgr->hScr, SCR_CID_XCC_MEASURE, SCR_RESOURCE_SERVING_CHANNEL); /* Clear Measurement fields */ measurementMgrSM_resetParams(pMeasurementMgr); pMeasurementMgr->Connected = TI_FALSE; return TI_OK; } /** * Called if the Measurement Manager module is disabled while we are * waiting for a response from the SCR. * * @date 05-Jan-2006 */ static TI_STATUS measurementMgrSM_acDisable_fromWaitForSCR(void * pData) { measurementMgr_t * pMeasurementMgr = (measurementMgr_t *) pData; setDefaultProbeReqTemplate (pMeasurementMgr->hSiteMgr); /* Release the SCR */ scr_clientComplete(pMeasurementMgr->hScr, SCR_CID_XCC_MEASURE, SCR_RESOURCE_SERVING_CHANNEL); /* Clear Measurement fields */ measurementMgrSM_resetParams(pMeasurementMgr); pMeasurementMgr->Enabled = TI_FALSE; return TI_OK; } /** * Called if a frame is received after we requested the SCR for another frame. * In this case the older frame is discarded and the new frame is processed. * * @date 05-Jan-2006 */ static TI_STATUS measurementMgrSM_acFrameReceived_fromWaitForSCR(void * pData) { measurementMgr_t * pMeasurementMgr = (measurementMgr_t *) pData; setDefaultProbeReqTemplate (pMeasurementMgr->hSiteMgr); /* Release the SCR */ scr_clientComplete(pMeasurementMgr->hScr, SCR_CID_XCC_MEASURE, SCR_RESOURCE_SERVING_CHANNEL); /* Clear Measurement fields */ measurementMgrSM_resetParams(pMeasurementMgr); /* Process New Frame */ return measurementMgrSM_acFrameReceived_fromIdle(pData); } /** * Called if the SCR callbacked with a response other than RUN. * * @date 05-Jan-2006 */ static TI_STATUS measurementMgrSM_acAbort_fromWaitForSCR(void * pData) { measurementMgr_t * pMeasurementMgr = (measurementMgr_t *) pData; setDefaultProbeReqTemplate (pMeasurementMgr->hSiteMgr); /* Release the SCR */ scr_clientComplete(pMeasurementMgr->hScr, SCR_CID_XCC_MEASURE, SCR_RESOURCE_SERVING_CHANNEL); /* Build a reject report */ measurementMgr_rejectPendingRequests(pMeasurementMgr, MSR_REJECT_SCR_UNAVAILABLE); /* Clear Measurement fields */ pMeasurementMgr->sendReportAndCleanObj(pMeasurementMgr); return TI_OK; } /** * Called when the SCR callbacks with a RUN response or if the SCR * returned a RUN response when we requested it. * * @date 05-Jan-2006 */ static TI_STATUS measurementMgrSM_acStartMeasurement(void * pData) { measurementMgr_t * pMeasurementMgr = (measurementMgr_t *) pData; /* Cryptic: the first struct is the requestHandler request while */ /* the second one is the measurementSRV request */ MeasurementRequest_t * pRequestArr[MAX_NUM_REQ]; TMeasurementRequest request; paramInfo_t *pParam; TI_UINT8 numOfRequestsInParallel; TI_UINT8 requestIndex; TI_UINT32 timePassed; TI_BOOL requestedBeaconMeasurement= TI_FALSE; TI_STATUS status; TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Starting Measurement operation\n"); pParam = (paramInfo_t *)os_memoryAlloc(pMeasurementMgr->hOs, sizeof(paramInfo_t)); if (!pParam) { return TI_NOK; } request.channel = pMeasurementMgr->measuredChannelID; request.startTime = 0; /* ignored by MeasurementSRV for now - for .11k */ request.numberOfTypes = 0; TRACE1(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Measured Channel = %d\n", pMeasurementMgr->measuredChannelID); pParam->paramType = REGULATORY_DOMAIN_GET_SCAN_CAPABILITIES; pParam->content.channelCapabilityReq.channelNum = pMeasurementMgr->measuredChannelID; pParam->content.channelCapabilityReq.scanOption = ACTIVE_SCANNING; if (pMeasurementMgr->measuredChannelID <= MAX_CHANNEL_IN_BAND_2_4) { request.band = RADIO_BAND_2_4_GHZ; pParam->content.channelCapabilityReq.band = RADIO_BAND_2_4_GHZ; } else { request.band = RADIO_BAND_5_0_GHZ; pParam->content.channelCapabilityReq.band = RADIO_BAND_5_0_GHZ; } regulatoryDomain_getParam(pMeasurementMgr->hRegulatoryDomain, pParam); request.txPowerDbm = pParam->content.channelCapabilityRet.maxTxPowerDbm; request.eTag = SCAN_RESULT_TAG_MEASUREMENT; os_memoryFree(pMeasurementMgr->hOs, pParam, sizeof(paramInfo_t)); TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Querying Request Handler for the next request in the queue\n"); /* Getting the next request/requests from the request handler */ status = requestHandler_getNextReq(pMeasurementMgr->hRequestH, TI_TRUE, pRequestArr, &numOfRequestsInParallel); if (status != TI_OK) { TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_ERROR, ": Failed getting next request from Request Handler\n"); return measurementMgrSM_event((TI_UINT8 *) &(pMeasurementMgr->currentState), MEASUREMENTMGR_EVENT_COMPLETE, pMeasurementMgr); } /* Save the number of requests in parallel so that once the */ /* measurement operation ends we can get rid of this amount of requests */ /* from the requestHandler */ pMeasurementMgr->currentNumOfRequestsInParallel = numOfRequestsInParallel; for (requestIndex = 0; requestIndex < numOfRequestsInParallel; requestIndex++) { if (pRequestArr[requestIndex]->Type == MSR_TYPE_BEACON_MEASUREMENT) { requestedBeaconMeasurement = TI_TRUE; if (pRequestArr[requestIndex]->ScanMode == MSR_SCAN_MODE_BEACON_TABLE) { TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Beacon Table request encountered, building report now\n"); /* building Report for beacon table request */ pMeasurementMgr->buildReport(pMeasurementMgr, *pRequestArr[requestIndex], NULL); continue; } } /* save the request so we can reference it when results arrive */ pMeasurementMgr->currentRequest[request.numberOfTypes] = pRequestArr[requestIndex]; /* add the measurement type to the request's list */ request.msrTypes[request.numberOfTypes].duration = pRequestArr[requestIndex]->DurationTime; request.msrTypes[request.numberOfTypes].scanMode = pRequestArr[requestIndex]->ScanMode; request.msrTypes[request.numberOfTypes].msrType = pRequestArr[requestIndex]->Type; TRACE3(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ":\n\nMeasurement Request #%d Details: Type = %d, Duration = %d\n\n", request.numberOfTypes+1, request.msrTypes[request.numberOfTypes].msrType, request.msrTypes[request.numberOfTypes].duration); request.numberOfTypes++; } if (requestedBeaconMeasurement == TI_TRUE) { /* build a probe request template and send it to the HAL */ TSetTemplate templateStruct; probeReqTemplate_t probeReqTemplate; TSsid broadcastSSID; templateStruct.ptr = (TI_UINT8 *) &probeReqTemplate; templateStruct.type = PROBE_REQUEST_TEMPLATE; templateStruct.eBand = request.band; templateStruct.uRateMask = RATE_MASK_UNSPECIFIED; broadcastSSID.len = 0; TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Sending probe request template...\n"); buildProbeReqTemplate( pMeasurementMgr->hSiteMgr, &templateStruct, &broadcastSSID, request.band ); #ifdef XCC_MODULE_INCLUDED { /* Insert Radio Mngt Capability IE according XCC4*/ TI_UINT32 len = 0; measurementMgr_radioMngtCapabilityBuild (pMeasurementMgr, templateStruct.ptr + templateStruct.len, (TI_UINT8*)&len); templateStruct.len += len; } #endif TWD_CmdTemplate (pMeasurementMgr->hTWD, &templateStruct, NULL, NULL); } /* Check if the maximum time to wait for the measurement request to */ /* finish has already passed */ timePassed = os_timeStampMs(pMeasurementMgr->hOs) - pMeasurementMgr->currentRequestStartTime; if (timePassed > MSR_START_MAX_DELAY) { TRACE2(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Maximum delay to perform measurement operation has passed (%d / %d)\n", MSR_START_MAX_DELAY, (os_timeStampMs(pMeasurementMgr->hOs) - pMeasurementMgr->currentRequestStartTime)); pMeasurementMgr->buildRejectReport(pMeasurementMgr, pRequestArr, numOfRequestsInParallel, MSR_REJECT_MAX_DELAY_PASSED); return measurementMgrSM_event((TI_UINT8 *) &(pMeasurementMgr->currentState), MEASUREMENTMGR_EVENT_COMPLETE, pMeasurementMgr); } /* set the measurement scan executed flag to TRUE */ pMeasurementMgr->bMeasurementScanExecuted = TI_TRUE; /* Yalla, start measuring */ TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Finished preparing request. Handing over to MeasurementSRV...\n"); TWD_StartMeasurement (pMeasurementMgr->hTWD, &request, MSR_START_MAX_DELAY - timePassed, NULL, NULL, measurementMgr_MeasurementCompleteCB, pMeasurementMgr); return TI_OK; } /********************************************************************************/ /* MEASURING State Actions */ /********************************************************************************/ static TI_STATUS measurementMgrSM_acDisconnected_fromMeasuring(void * pData) { measurementMgr_t * pMeasurementMgr = (measurementMgr_t *) pData; setDefaultProbeReqTemplate (pMeasurementMgr->hSiteMgr); /* release the SCR */ scr_clientComplete(pMeasurementMgr->hScr, SCR_CID_XCC_MEASURE, SCR_RESOURCE_SERVING_CHANNEL); /* Clear Measurement fields */ measurementMgrSM_resetParams(pMeasurementMgr); pMeasurementMgr->Connected = TI_FALSE; return TI_OK; } static TI_STATUS measurementMgrSM_acDisable_fromMeasuring(void * pData) { measurementMgr_t * pMeasurementMgr = (measurementMgr_t *) pData; setDefaultProbeReqTemplate (pMeasurementMgr->hSiteMgr); /* release the SCR */ scr_clientComplete(pMeasurementMgr->hScr, SCR_CID_XCC_MEASURE, SCR_RESOURCE_SERVING_CHANNEL); /* Clear Measurement fields */ measurementMgrSM_resetParams(pMeasurementMgr); pMeasurementMgr->Enabled = TI_FALSE; return TI_OK; } static TI_STATUS measurementMgrSM_acFrameReceived_fromMeasuring(void * pData) { measurementMgr_t * pMeasurementMgr = (measurementMgr_t *) pData; setDefaultProbeReqTemplate (pMeasurementMgr->hSiteMgr); /* release the SCR */ scr_clientComplete(pMeasurementMgr->hScr, SCR_CID_XCC_MEASURE, SCR_RESOURCE_SERVING_CHANNEL); /* Clear Measurement fields */ measurementMgrSM_resetParams(pMeasurementMgr); /* Process New Frame */ return measurementMgrSM_acFrameReceived_fromIdle(pData); } static TI_STATUS measurementMgrSM_acAbort_fromMeasuring(void * pData) { measurementMgr_t * pMeasurementMgr = (measurementMgr_t *) pData; setDefaultProbeReqTemplate (pMeasurementMgr->hSiteMgr); /* release the SCR */ scr_clientComplete(pMeasurementMgr->hScr, SCR_CID_XCC_MEASURE, SCR_RESOURCE_SERVING_CHANNEL); /* Clear Measurement fields */ measurementMgrSM_resetParams(pMeasurementMgr); TWD_StopMeasurement (pMeasurementMgr->hTWD, TI_TRUE ,NULL, NULL); return TI_OK; } /** * Called when we finished a measurement request. * * @date 05-Jan-2006 */ static TI_STATUS measurementMgrSM_acMeasurementComplete(void * pData) { measurementMgr_t * pMeasurementMgr = (measurementMgr_t *) pData; requestHandler_t * pRequestH = (requestHandler_t *) pMeasurementMgr->hRequestH; TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Completing measurement operation and resuming normal behavior\n"); /* advance the activeRequestID variable to get rid of the */ /* measurement requests we've already executed */ TRACE2(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Increasing activeRequestID from %d to %d.\n", pRequestH->activeRequestID, pRequestH->activeRequestID + pMeasurementMgr->currentNumOfRequestsInParallel); pRequestH->activeRequestID += pMeasurementMgr->currentNumOfRequestsInParallel; setDefaultProbeReqTemplate (pMeasurementMgr->hSiteMgr); /* move the driver result table to stable state and clear it */ sme_MeansurementScanResult (pMeasurementMgr->hSme, SCAN_CRS_SCAN_COMPLETE_OK, NULL); /* release the SCR */ scr_clientComplete(pMeasurementMgr->hScr, SCR_CID_XCC_MEASURE, SCR_RESOURCE_SERVING_CHANNEL); /* Process New Frame */ return measurementMgr_activateNextRequest(pData); } /** * Called when a firmware reset has been detected. * * @date 05-Jan-2006 */ static TI_STATUS measurementMgrSM_acFirmwareReset(void * pData) { measurementMgr_t * pMeasurementMgr = (measurementMgr_t *) pData; TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Firmware Reset!!\n"); setDefaultProbeReqTemplate (pMeasurementMgr->hSiteMgr); /* release the SCR */ scr_clientComplete(pMeasurementMgr->hScr, SCR_CID_XCC_MEASURE, SCR_RESOURCE_SERVING_CHANNEL); /* Clear Measurement fields */ measurementMgrSM_resetParams(pMeasurementMgr); return TI_OK; } /********************************************************************************/ /* Miscellaneous State Actions */ /********************************************************************************/ /** * Called when an unexpected event has been triggered. * * @date 05-Jan-2006 */ static TI_STATUS measurementMgrSM_acUnexpected(void * pData) { measurementMgr_t * pMeasurementMgr = (measurementMgr_t *) pData; TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Entered when state is \n"); return TI_OK; } /** * A do nothing action. * * @date 05-Jan-2006 */ static TI_STATUS measurementMgrSM_acNop(void * pData) { measurementMgr_t * pMeasurementMgr = (measurementMgr_t *) pData; TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Entered when state is \n"); return TI_OK; } /********************************************************************************/ /* Internal Functions Prototypes */ /********************************************************************************/ static void measurementMgrSM_resetParams(measurementMgr_t *pMeasurementMgr) { /* clear the waiting requests */ requestHandler_clearRequests(pMeasurementMgr->hRequestH); /* clearing reports data base */ #ifdef XCC_MODULE_INCLUDED os_memoryZero(pMeasurementMgr->hOs,&(pMeasurementMgr->XCCFrameReport), sizeof(RM_report_frame_t)); #endif os_memoryZero(pMeasurementMgr->hOs,&(pMeasurementMgr->dot11hFrameReport), sizeof(MeasurementReportFrame_t)); pMeasurementMgr->frameLength = 0; pMeasurementMgr->nextEmptySpaceInReport = 0; pMeasurementMgr->measuredChannelID = 0; pMeasurementMgr->currentFrameType = MSR_FRAME_TYPE_NO_ACTIVE; } /** * The callback called when the activation delay timer has ended. * * @param hMeasurementMgr - A handle to the Measurement Manager module. * @param bTwdInitOccured - Indicates if TWDriver recovery occured since timer started * * @date 01-Jan-2006 */ static void measurementMgrSM_uponActivationDelayTimeout (TI_HANDLE hMeasurementMgr, TI_BOOL bTwdInitOccured) { measurementMgr_t * pMeasurementMgr = (measurementMgr_t *)hMeasurementMgr; TRACE0(pMeasurementMgr->hReport, REPORT_SEVERITY_INFORMATION, ": Activation delay timeout callback entered\n"); measurementMgr_activateNextRequest (pMeasurementMgr); }