2016-06-15 23:48:41 +02:00
# include <framework/datapool/DataSet.h>
# include <framework/datapool/PoolVariable.h>
# include <framework/datapool/PoolVector.h>
2018-07-12 16:29:32 +02:00
# include <framework/devicehandlers/AcceptsDeviceResponsesIF.h>
2016-06-15 23:48:41 +02:00
# include <framework/devicehandlers/DeviceHandlerBase.h>
# include <framework/devicehandlers/DeviceTmReportingWrapper.h>
2020-04-06 13:22:42 +02:00
# include <framework/globalfunctions/CRC.h>
2016-06-15 23:48:41 +02:00
# include <framework/objectmanager/ObjectManager.h>
# include <framework/storagemanager/StorageManagerIF.h>
# include <framework/subsystem/SubsystemBase.h>
2018-07-12 16:29:32 +02:00
# include <framework/thermal/ThermalComponentIF.h>
# include <framework/ipc/QueueFactory.h>
2019-08-28 14:50:24 +02:00
# include <framework/serviceinterface/ServiceInterfaceStream.h>
2018-07-12 16:29:32 +02:00
object_id_t DeviceHandlerBase : : powerSwitcherId = 0 ;
object_id_t DeviceHandlerBase : : rawDataReceiverId = 0 ;
object_id_t DeviceHandlerBase : : defaultFDIRParentId = 0 ;
2016-06-15 23:48:41 +02:00
DeviceHandlerBase : : DeviceHandlerBase ( uint32_t ioBoardAddress ,
object_id_t setObjectId , uint32_t maxDeviceReplyLen ,
uint8_t setDeviceSwitch , object_id_t deviceCommunication ,
uint32_t thermalStatePoolId , uint32_t thermalRequestPoolId ,
2018-07-12 16:29:32 +02:00
FailureIsolationBase * fdirInstance , uint32_t cmdQueueSize ) :
2016-06-15 23:48:41 +02:00
SystemObject ( setObjectId ) , rawPacket ( 0 ) , rawPacketLen ( 0 ) , mode (
MODE_OFF ) , submode ( SUBMODE_NONE ) , pstStep ( 0 ) , maxDeviceReplyLen (
2018-07-12 16:29:32 +02:00
maxDeviceReplyLen ) , wiretappingMode ( OFF ) , defaultRawReceiver ( 0 ) , storedRawData (
StorageManagerIF : : INVALID_ADDRESS ) , requestedRawTraffic ( 0 ) , powerSwitcher (
NULL ) , IPCStore ( NULL ) , deviceCommunicationId ( deviceCommunication ) , communicationInterface (
NULL ) , cookie (
NULL ) , commandQueue ( NULL ) , deviceThermalStatePoolId ( thermalStatePoolId ) , deviceThermalRequestPoolId (
2016-06-15 23:48:41 +02:00
thermalRequestPoolId ) , healthHelper ( this , setObjectId ) , modeHelper (
this ) , parameterHelper ( this ) , childTransitionFailure ( RETURN_OK ) , ignoreMissedRepliesCount (
2018-07-12 16:29:32 +02:00
0 ) , fdirInstance ( fdirInstance ) , hkSwitcher ( this ) , defaultFDIRUsed (
2018-07-13 18:28:26 +02:00
fdirInstance = = NULL ) , switchOffWasReported ( false ) , executingTask ( NULL ) , actionHelper ( this , NULL ) , cookieInfo ( ) , ioBoardAddress (
2018-07-12 16:29:32 +02:00
ioBoardAddress ) , timeoutStart ( 0 ) , childTransitionDelay ( 5000 ) , transitionSourceMode (
_MODE_POWER_DOWN ) , transitionSourceSubMode ( SUBMODE_NONE ) , deviceSwitch (
setDeviceSwitch ) {
commandQueue = QueueFactory : : instance ( ) - > createMessageQueue ( cmdQueueSize ,
CommandMessage : : MAX_MESSAGE_SIZE ) ;
2016-06-15 23:48:41 +02:00
cookieInfo . state = COOKIE_UNUSED ;
insertInCommandMap ( RAW_COMMAND_ID ) ;
if ( this - > fdirInstance = = NULL ) {
2018-07-12 16:29:32 +02:00
this - > fdirInstance = new DeviceHandlerFailureIsolation ( setObjectId ,
defaultFDIRParentId ) ;
2016-06-15 23:48:41 +02:00
}
}
DeviceHandlerBase : : ~ DeviceHandlerBase ( ) {
communicationInterface - > close ( cookie ) ;
if ( defaultFDIRUsed ) {
delete fdirInstance ;
}
2018-07-12 16:29:32 +02:00
QueueFactory : : instance ( ) - > deleteMessageQueue ( commandQueue ) ;
2016-06-15 23:48:41 +02:00
}
2018-07-12 16:29:32 +02:00
ReturnValue_t DeviceHandlerBase : : performOperation ( uint8_t counter ) {
2016-06-15 23:48:41 +02:00
this - > pstStep = counter ;
if ( counter = = 0 ) {
cookieInfo . state = COOKIE_UNUSED ;
readCommandQueue ( ) ;
doStateMachine ( ) ;
checkSwitchState ( ) ;
decrementDeviceReplyMap ( ) ;
fdirInstance - > checkForFailures ( ) ;
2018-07-12 16:29:32 +02:00
hkSwitcher . performOperation ( ) ;
2016-06-15 23:48:41 +02:00
}
if ( mode = = MODE_OFF ) {
2018-07-12 16:29:32 +02:00
return RETURN_OK ;
2016-06-15 23:48:41 +02:00
}
switch ( getRmapAction ( ) ) {
case SEND_WRITE :
if ( ( cookieInfo . state = = COOKIE_UNUSED ) ) {
buildInternalCommand ( ) ;
}
doSendWrite ( ) ;
break ;
case GET_WRITE :
doGetWrite ( ) ;
break ;
case SEND_READ :
doSendRead ( ) ;
break ;
case GET_READ :
doGetRead ( ) ;
cookieInfo . state = COOKIE_UNUSED ;
break ;
default :
break ;
}
2018-07-12 16:29:32 +02:00
return RETURN_OK ;
2016-06-15 23:48:41 +02:00
}
void DeviceHandlerBase : : decrementDeviceReplyMap ( ) {
for ( std : : map < DeviceCommandId_t , DeviceReplyInfo > : : iterator iter =
deviceReplyMap . begin ( ) ; iter ! = deviceReplyMap . end ( ) ; iter + + ) {
if ( iter - > second . delayCycles ! = 0 ) {
iter - > second . delayCycles - - ;
if ( iter - > second . delayCycles = = 0 ) {
if ( iter - > second . periodic ! = 0 ) {
iter - > second . delayCycles = iter - > second . maxDelayCycles ;
}
replyToReply ( iter , TIMEOUT ) ;
missedReply ( iter - > first ) ;
}
}
}
}
void DeviceHandlerBase : : readCommandQueue ( ) {
if ( dontCheckQueue ( ) ) {
return ;
}
CommandMessage message ;
2018-07-12 16:29:32 +02:00
ReturnValue_t result = commandQueue - > receiveMessage ( & message ) ;
2016-06-15 23:48:41 +02:00
if ( result ! = RETURN_OK ) {
return ;
}
result = healthHelper . handleHealthCommand ( & message ) ;
if ( result = = RETURN_OK ) {
return ;
}
result = modeHelper . handleModeCommand ( & message ) ;
if ( result = = RETURN_OK ) {
return ;
}
result = actionHelper . handleActionMessage ( & message ) ;
if ( result = = RETURN_OK ) {
return ;
}
result = parameterHelper . handleParameterMessage ( & message ) ;
if ( result = = RETURN_OK ) {
return ;
}
result = handleDeviceHandlerMessage ( & message ) ;
if ( result = = RETURN_OK ) {
return ;
}
result = letChildHandleMessage ( & message ) ;
if ( result = = RETURN_OK ) {
return ;
}
replyReturnvalueToCommand ( CommandMessage : : UNKNOW_COMMAND ) ;
}
void DeviceHandlerBase : : doStateMachine ( ) {
switch ( mode ) {
case _MODE_START_UP :
case _MODE_SHUT_DOWN :
case _MODE_TO_NORMAL :
case _MODE_TO_ON :
case _MODE_TO_RAW : {
Mode_t currentMode = mode ;
callChildStatemachine ( ) ;
//Only do timeout if child did not change anything
if ( mode ! = currentMode ) {
break ;
}
uint32_t currentUptime ;
2018-07-12 16:29:32 +02:00
Clock : : getUptime ( & currentUptime ) ;
2016-06-15 23:48:41 +02:00
if ( currentUptime - timeoutStart > = childTransitionDelay ) {
triggerEvent ( MODE_TRANSITION_FAILED , childTransitionFailure , 0 ) ;
setMode ( transitionSourceMode , transitionSourceSubMode ) ;
break ;
}
}
break ;
case _MODE_POWER_DOWN :
commandSwitch ( PowerSwitchIF : : SWITCH_OFF ) ;
setMode ( _MODE_WAIT_OFF ) ;
break ;
case _MODE_POWER_ON :
commandSwitch ( PowerSwitchIF : : SWITCH_ON ) ;
setMode ( _MODE_WAIT_ON ) ;
break ;
case _MODE_WAIT_ON : {
uint32_t currentUptime ;
2018-07-12 16:29:32 +02:00
Clock : : getUptime ( & currentUptime ) ;
2016-06-15 23:48:41 +02:00
if ( currentUptime - timeoutStart > = powerSwitcher - > getSwitchDelayMs ( ) ) {
triggerEvent ( MODE_TRANSITION_FAILED , PowerSwitchIF : : SWITCH_TIMEOUT ,
0 ) ;
setMode ( _MODE_POWER_DOWN ) ;
callChildStatemachine ( ) ;
break ;
}
ReturnValue_t switchState = getStateOfSwitches ( ) ;
if ( ( switchState = = PowerSwitchIF : : SWITCH_ON )
| | ( switchState = = NO_SWITCH ) ) {
//NOTE: TransitionSourceMode and -SubMode are set by handleCommandedModeTransition
childTransitionFailure = CHILD_TIMEOUT ;
setMode ( _MODE_START_UP ) ;
callChildStatemachine ( ) ;
}
}
break ;
case _MODE_WAIT_OFF : {
uint32_t currentUptime ;
2018-07-12 16:29:32 +02:00
Clock : : getUptime ( & currentUptime ) ;
2016-06-15 23:48:41 +02:00
if ( currentUptime - timeoutStart > = powerSwitcher - > getSwitchDelayMs ( ) ) {
triggerEvent ( MODE_TRANSITION_FAILED , PowerSwitchIF : : SWITCH_TIMEOUT ,
0 ) ;
setMode ( MODE_ERROR_ON ) ;
break ;
}
ReturnValue_t switchState = getStateOfSwitches ( ) ;
if ( ( switchState = = PowerSwitchIF : : SWITCH_OFF )
| | ( switchState = = NO_SWITCH ) ) {
setMode ( _MODE_SWITCH_IS_OFF ) ;
}
}
break ;
case MODE_OFF :
doOffActivity ( ) ;
break ;
case MODE_ON :
doOnActivity ( ) ;
break ;
case MODE_RAW :
case MODE_NORMAL :
case MODE_ERROR_ON :
break ;
case _MODE_SWITCH_IS_OFF :
setMode ( MODE_OFF , SUBMODE_NONE ) ;
break ;
default :
triggerEvent ( OBJECT_IN_INVALID_MODE , mode , submode ) ;
setMode ( _MODE_POWER_DOWN , 0 ) ;
break ;
}
}
ReturnValue_t DeviceHandlerBase : : isModeCombinationValid ( Mode_t mode ,
Submode_t submode ) {
switch ( mode ) {
case MODE_OFF :
case MODE_ON :
case MODE_NORMAL :
case MODE_RAW :
if ( submode = = SUBMODE_NONE ) {
return RETURN_OK ;
} else {
return INVALID_SUBMODE ;
}
default :
return HasModesIF : : INVALID_MODE ;
}
}
ReturnValue_t DeviceHandlerBase : : insertInCommandAndReplyMap (
DeviceCommandId_t deviceCommand , uint16_t maxDelayCycles ,
uint8_t periodic , bool hasDifferentReplyId , DeviceCommandId_t replyId ) {
//No need to check, as we may try to insert multiple times.
insertInCommandMap ( deviceCommand ) ;
if ( hasDifferentReplyId ) {
return insertInReplyMap ( replyId , maxDelayCycles , periodic ) ;
} else {
return insertInReplyMap ( deviceCommand , maxDelayCycles , periodic ) ;
}
}
ReturnValue_t DeviceHandlerBase : : insertInReplyMap ( DeviceCommandId_t replyId ,
uint16_t maxDelayCycles , uint8_t periodic ) {
DeviceReplyInfo info ;
info . maxDelayCycles = maxDelayCycles ;
info . periodic = periodic ;
info . delayCycles = 0 ;
info . command = deviceCommandMap . end ( ) ;
std : : pair < std : : map < DeviceCommandId_t , DeviceReplyInfo > : : iterator , bool > returnValue ;
returnValue = deviceReplyMap . insert (
std : : pair < DeviceCommandId_t , DeviceReplyInfo > ( replyId , info ) ) ;
if ( returnValue . second ) {
return RETURN_OK ;
} else {
return RETURN_FAILED ;
}
}
ReturnValue_t DeviceHandlerBase : : insertInCommandMap (
DeviceCommandId_t deviceCommand ) {
DeviceCommandInfo info ;
info . expectedReplies = 0 ;
info . isExecuting = false ;
info . sendReplyTo = NO_COMMANDER ;
std : : pair < std : : map < DeviceCommandId_t , DeviceCommandInfo > : : iterator , bool > returnValue ;
returnValue = deviceCommandMap . insert (
std : : pair < DeviceCommandId_t , DeviceCommandInfo > ( deviceCommand ,
info ) ) ;
if ( returnValue . second ) {
return RETURN_OK ;
} else {
return RETURN_FAILED ;
}
}
ReturnValue_t DeviceHandlerBase : : updateReplyMapEntry (
DeviceCommandId_t deviceReply , uint16_t delayCycles ,
uint16_t maxDelayCycles , uint8_t periodic ) {
std : : map < DeviceCommandId_t , DeviceReplyInfo > : : iterator iter =
deviceReplyMap . find ( deviceReply ) ;
if ( iter = = deviceReplyMap . end ( ) ) {
triggerEvent ( INVALID_DEVICE_COMMAND , deviceReply ) ;
return RETURN_FAILED ;
} else {
DeviceReplyInfo * info = & ( iter - > second ) ;
if ( maxDelayCycles ! = 0 ) {
info - > maxDelayCycles = maxDelayCycles ;
}
info - > delayCycles = delayCycles ;
info - > periodic = periodic ;
return RETURN_OK ;
}
}
void DeviceHandlerBase : : callChildStatemachine ( ) {
if ( mode = = _MODE_START_UP ) {
doStartUp ( ) ;
} else if ( mode = = _MODE_SHUT_DOWN ) {
doShutDown ( ) ;
} else if ( mode & TRANSITION_MODE_CHILD_ACTION_MASK ) {
doTransition ( transitionSourceMode , transitionSourceSubMode ) ;
}
}
void DeviceHandlerBase : : setTransition ( Mode_t modeTo , Submode_t submodeTo ) {
2020-07-08 15:19:49 +02:00
sif : : debug < < " DeviceHandlerBase::setTransition " < < std : : endl ;
2016-06-15 23:48:41 +02:00
triggerEvent ( CHANGING_MODE , modeTo , submodeTo ) ;
childTransitionDelay = getTransitionDelayMs ( mode , modeTo ) ;
transitionSourceMode = mode ;
transitionSourceSubMode = submode ;
childTransitionFailure = CHILD_TIMEOUT ;
//transitionTargetMode is set by setMode
setMode ( ( modeTo | TRANSITION_MODE_CHILD_ACTION_MASK ) , submodeTo ) ;
}
void DeviceHandlerBase : : setMode ( Mode_t newMode , uint8_t newSubmode ) {
2018-07-12 16:29:32 +02:00
changeHK ( mode , submode , false ) ;
2016-06-15 23:48:41 +02:00
submode = newSubmode ;
mode = newMode ;
modeChanged ( ) ;
setNormalDatapoolEntriesInvalid ( ) ;
if ( ! isTransitionalMode ( ) ) {
modeHelper . modeChanged ( newMode , newSubmode ) ;
announceMode ( false ) ;
}
2018-07-12 16:29:32 +02:00
Clock : : getUptime ( & timeoutStart ) ;
2016-06-15 23:48:41 +02:00
if ( mode = = MODE_OFF ) {
DataSet mySet ;
PoolVariable < int8_t > thermalRequest ( deviceThermalRequestPoolId , & mySet ,
PoolVariableIF : : VAR_READ_WRITE ) ;
mySet . read ( ) ;
if ( thermalRequest ! = ThermalComponentIF : : STATE_REQUEST_IGNORE ) {
thermalRequest = ThermalComponentIF : : STATE_REQUEST_NON_OPERATIONAL ;
}
mySet . commit ( PoolVariableIF : : VALID ) ;
}
2018-07-12 16:29:32 +02:00
changeHK ( mode , submode , true ) ;
2016-06-15 23:48:41 +02:00
}
void DeviceHandlerBase : : setMode ( Mode_t newMode ) {
setMode ( newMode , submode ) ;
}
void DeviceHandlerBase : : replyReturnvalueToCommand ( ReturnValue_t status ,
uint32_t parameter ) {
2019-08-28 14:50:24 +02:00
//This is actually the reply protocol for raw and misc DH commands.
2016-06-15 23:48:41 +02:00
if ( status = = RETURN_OK ) {
CommandMessage reply ( CommandMessage : : REPLY_COMMAND_OK , 0 , parameter ) ;
2018-07-12 16:29:32 +02:00
commandQueue - > reply ( & reply ) ;
2016-06-15 23:48:41 +02:00
} else {
CommandMessage reply ( CommandMessage : : REPLY_REJECTED , status , parameter ) ;
2018-07-12 16:29:32 +02:00
commandQueue - > reply ( & reply ) ;
2016-06-15 23:48:41 +02:00
}
}
void DeviceHandlerBase : : replyToCommand ( ReturnValue_t status ,
uint32_t parameter ) {
//Check if we reply to a raw command.
if ( cookieInfo . pendingCommand - > first = = RAW_COMMAND_ID ) {
if ( status = = NO_REPLY_EXPECTED ) {
status = RETURN_OK ;
}
replyReturnvalueToCommand ( status , parameter ) ;
//Always delete data from a raw command.
IPCStore - > deleteData ( storedRawData ) ;
return ;
}
//Check if we were externally commanded.
if ( cookieInfo . pendingCommand - > second . sendReplyTo ! = NO_COMMANDER ) {
MessageQueueId_t queueId = cookieInfo . pendingCommand - > second . sendReplyTo ;
if ( status = = NO_REPLY_EXPECTED ) {
actionHelper . finish ( queueId , cookieInfo . pendingCommand - > first ,
RETURN_OK ) ;
} else {
actionHelper . step ( 1 , queueId , cookieInfo . pendingCommand - > first ,
status ) ;
}
}
}
void DeviceHandlerBase : : replyToReply ( DeviceReplyMap : : iterator iter ,
ReturnValue_t status ) {
//No need to check if iter exists, as this is checked by callers. If someone else uses the method, add check.
if ( iter - > second . command = = deviceCommandMap . end ( ) ) {
//Is most likely periodic reply. Silent return.
return ;
}
//Check if more replies are expected. If so, do nothing.
DeviceCommandInfo * info = & ( iter - > second . command - > second ) ;
if ( - - info - > expectedReplies = = 0 ) {
//Check if it was transition or internal command. Don't send any replies in that case.
if ( info - > sendReplyTo ! = NO_COMMANDER ) {
actionHelper . finish ( info - > sendReplyTo , iter - > first , status ) ;
}
info - > isExecuting = false ;
}
}
void DeviceHandlerBase : : doSendWrite ( ) {
if ( cookieInfo . state = = COOKIE_WRITE_READY ) {
2020-06-17 08:35:58 +02:00
sif : : debug < < " DeviceHandlerBase::doSendWrite: Calling sendMessage " < < std : : endl ;
2016-06-15 23:48:41 +02:00
ReturnValue_t result = communicationInterface - > sendMessage ( cookie ,
rawPacket , rawPacketLen ) ;
if ( result = = RETURN_OK ) {
cookieInfo . state = COOKIE_WRITE_SENT ;
2020-06-17 09:50:52 +02:00
sif : : debug < < " DeviceHandlerBase::doSendWrite: Calling sendMessage succeeded " < < std : : endl ;
2016-06-15 23:48:41 +02:00
} else {
2020-06-17 09:50:52 +02:00
sif : : debug < < " DeviceHandlerBase::doSendWrite: Calling sendMessage failed " < < std : : endl ;
2016-06-15 23:48:41 +02:00
//always generate a failure event, so that FDIR knows what's up
triggerEvent ( DEVICE_SENDING_COMMAND_FAILED , result ,
cookieInfo . pendingCommand - > first ) ;
replyToCommand ( result ) ;
cookieInfo . state = COOKIE_UNUSED ;
cookieInfo . pendingCommand - > second . isExecuting = false ;
}
}
}
void DeviceHandlerBase : : doGetWrite ( ) {
if ( cookieInfo . state ! = COOKIE_WRITE_SENT ) {
2020-06-22 11:06:07 +02:00
// sif::debug<<" DeviceHandlerBase::doGetWrite: COOKIE_WRITE_SENT not set"<<std::endl;
2016-06-15 23:48:41 +02:00
return ;
}
cookieInfo . state = COOKIE_UNUSED ;
2020-06-17 08:35:58 +02:00
sif : : debug < < " DeviceHandlerBase::doGetWrite: Calling getSendSuccess " < < std : : endl ;
2016-06-15 23:48:41 +02:00
ReturnValue_t result = communicationInterface - > getSendSuccess ( cookie ) ;
if ( result = = RETURN_OK ) {
if ( wiretappingMode = = RAW ) {
2018-07-12 16:29:32 +02:00
replyRawData ( rawPacket , rawPacketLen , requestedRawTraffic , true ) ;
2016-06-15 23:48:41 +02:00
}
//We need to distinguish here, because a raw command never expects a reply. (Could be done in eRIRM, but then child implementations need to be careful.
result = enableReplyInReplyMap ( cookieInfo . pendingCommand ) ;
} else {
//always generate a failure event, so that FDIR knows what's up
triggerEvent ( DEVICE_SENDING_COMMAND_FAILED , result ,
cookieInfo . pendingCommand - > first ) ;
}
if ( result ! = RETURN_OK ) {
cookieInfo . pendingCommand - > second . isExecuting = false ;
}
replyToCommand ( result ) ;
}
void DeviceHandlerBase : : doSendRead ( ) {
ReturnValue_t result ;
2020-06-17 08:35:58 +02:00
// sif::debug<<" DeviceHandlerBase::doSendRead: Calling requestReceiveMessage"<<std::endl;
2016-06-15 23:48:41 +02:00
result = communicationInterface - > requestReceiveMessage ( cookie ) ;
if ( result = = RETURN_OK ) {
cookieInfo . state = COOKIE_READ_SENT ;
} else {
triggerEvent ( DEVICE_REQUESTING_REPLY_FAILED , result ) ;
//We can't inform anyone, because we don't know which command was sent last.
//So, we need to wait for a timeout.
//but I think we can allow to ignore one missedReply.
ignoreMissedRepliesCount + + ;
cookieInfo . state = COOKIE_UNUSED ;
}
}
void DeviceHandlerBase : : doGetRead ( ) {
uint32_t receivedDataLen ;
uint8_t * receivedData ;
DeviceCommandId_t foundId = 0xFFFFFFFF ;
uint32_t foundLen = 0 ;
ReturnValue_t result ;
if ( cookieInfo . state ! = COOKIE_READ_SENT ) {
cookieInfo . state = COOKIE_UNUSED ;
return ;
}
cookieInfo . state = COOKIE_UNUSED ;
2020-06-17 08:35:58 +02:00
// sif::debug<<" DeviceHandlerBase::doGetRead: Calling readReceivedMessage"<<std::endl;
2016-06-15 23:48:41 +02:00
result = communicationInterface - > readReceivedMessage ( cookie , & receivedData ,
& receivedDataLen ) ;
if ( result ! = RETURN_OK ) {
triggerEvent ( DEVICE_REQUESTING_REPLY_FAILED , result ) ;
//I think we can allow to ignore one missedReply.
ignoreMissedRepliesCount + + ;
return ;
}
if ( receivedDataLen = = 0 )
return ;
if ( wiretappingMode = = RAW ) {
2018-07-12 16:29:32 +02:00
replyRawData ( receivedData , receivedDataLen , requestedRawTraffic ) ;
2016-06-15 23:48:41 +02:00
}
if ( mode = = MODE_RAW ) {
2018-07-12 16:29:32 +02:00
replyRawReplyIfnotWiretapped ( receivedData , receivedDataLen ) ;
2016-06-15 23:48:41 +02:00
} else {
//The loop may not execute more often than the number of received bytes (worst case).
//This approach avoids infinite loops due to buggy scanForReply routines (seen in bug 1077).
uint32_t remainingLength = receivedDataLen ;
for ( uint32_t count = 0 ; count < receivedDataLen ; count + + ) {
2020-06-17 08:35:58 +02:00
sif : : debug < < " DeviceHandlerBase::doGetRead: Calling scanForReply " < < std : : endl ;
2016-06-15 23:48:41 +02:00
result = scanForReply ( receivedData , remainingLength , & foundId ,
& foundLen ) ;
switch ( result ) {
case RETURN_OK :
2020-06-17 08:35:58 +02:00
sif : : debug < < " DeviceHandlerBase::doGetRead: Calling handle reply " < < std : : endl ;
2018-07-12 16:29:32 +02:00
handleReply ( receivedData , foundId , foundLen ) ;
2016-06-15 23:48:41 +02:00
break ;
case APERIODIC_REPLY : {
result = interpretDeviceReply ( foundId , receivedData ) ;
if ( result ! = RETURN_OK ) {
2018-07-12 16:29:32 +02:00
replyRawReplyIfnotWiretapped ( receivedData , foundLen ) ;
2016-06-15 23:48:41 +02:00
triggerEvent ( DEVICE_INTERPRETING_REPLY_FAILED , result ,
foundId ) ;
}
}
break ;
case IGNORE_REPLY_DATA :
break ;
default :
//We need to wait for timeout.. don't know what command failed and who sent it.
2018-07-12 16:29:32 +02:00
replyRawReplyIfnotWiretapped ( receivedData , foundLen ) ;
2016-06-15 23:48:41 +02:00
triggerEvent ( DEVICE_READING_REPLY_FAILED , result , foundLen ) ;
break ;
}
receivedData + = foundLen ;
if ( remainingLength > foundLen ) {
remainingLength - = foundLen ;
} else {
return ;
}
}
}
}
ReturnValue_t DeviceHandlerBase : : getStorageData ( store_address_t storageAddress ,
uint8_t * * data , uint32_t * len ) {
2020-05-04 16:53:04 +02:00
size_t lenTmp ;
2016-06-15 23:48:41 +02:00
if ( IPCStore = = NULL ) {
* data = NULL ;
* len = 0 ;
return RETURN_FAILED ;
}
ReturnValue_t result = IPCStore - > modifyData ( storageAddress , data , & lenTmp ) ;
if ( result = = RETURN_OK ) {
* len = lenTmp ;
return RETURN_OK ;
} else {
triggerEvent ( StorageManagerIF : : GET_DATA_FAILED , result ,
storageAddress . raw ) ;
* data = NULL ;
* len = 0 ;
return result ;
}
}
ReturnValue_t DeviceHandlerBase : : initialize ( ) {
ReturnValue_t result = SystemObject : : initialize ( ) ;
if ( result ! = RETURN_OK ) {
return result ;
}
communicationInterface = objectManager - > get < DeviceCommunicationIF > (
deviceCommunicationId ) ;
if ( communicationInterface = = NULL ) {
return RETURN_FAILED ;
}
result = communicationInterface - > open ( & cookie , ioBoardAddress ,
maxDeviceReplyLen ) ;
if ( result ! = RETURN_OK ) {
return result ;
}
IPCStore = objectManager - > get < StorageManagerIF > ( objects : : IPC_STORE ) ;
if ( IPCStore = = NULL ) {
return RETURN_FAILED ;
}
AcceptsDeviceResponsesIF * rawReceiver = objectManager - > get <
2018-07-12 16:29:32 +02:00
AcceptsDeviceResponsesIF > ( rawDataReceiverId ) ;
2016-06-15 23:48:41 +02:00
if ( rawReceiver = = NULL ) {
return RETURN_FAILED ;
}
2018-07-12 16:29:32 +02:00
defaultRawReceiver = rawReceiver - > getDeviceQueue ( ) ;
2016-06-15 23:48:41 +02:00
2018-07-12 16:29:32 +02:00
powerSwitcher = objectManager - > get < PowerSwitchIF > ( powerSwitcherId ) ;
2016-06-15 23:48:41 +02:00
if ( powerSwitcher = = NULL ) {
return RETURN_FAILED ;
}
result = healthHelper . initialize ( ) ;
if ( result ! = RETURN_OK ) {
return result ;
}
result = modeHelper . initialize ( ) ;
if ( result ! = RETURN_OK ) {
return result ;
}
2018-07-13 18:28:26 +02:00
result = actionHelper . initialize ( commandQueue ) ;
2016-06-15 23:48:41 +02:00
if ( result ! = RETURN_OK ) {
return result ;
}
result = fdirInstance - > initialize ( ) ;
if ( result ! = HasReturnvaluesIF : : RETURN_OK ) {
return result ;
}
result = parameterHelper . initialize ( ) ;
if ( result ! = HasReturnvaluesIF : : RETURN_OK ) {
return result ;
}
2018-07-12 16:29:32 +02:00
result = hkSwitcher . initialize ( ) ;
if ( result ! = HasReturnvaluesIF : : RETURN_OK ) {
return result ;
}
2016-06-15 23:48:41 +02:00
fillCommandAndReplyMap ( ) ;
//Set temperature target state to NON_OP.
DataSet mySet ;
PoolVariable < int8_t > thermalRequest ( deviceThermalRequestPoolId , & mySet ,
PoolVariableIF : : VAR_WRITE ) ;
mySet . read ( ) ;
thermalRequest = ThermalComponentIF : : STATE_REQUEST_NON_OPERATIONAL ;
mySet . commit ( PoolVariableIF : : VALID ) ;
return RETURN_OK ;
}
void DeviceHandlerBase : : replyRawData ( const uint8_t * data , size_t len ,
MessageQueueId_t sendTo , bool isCommand ) {
if ( IPCStore = = NULL | | len = = 0 ) {
return ;
}
store_address_t address ;
ReturnValue_t result = IPCStore - > addData ( & address , data , len ) ;
if ( result ! = RETURN_OK ) {
triggerEvent ( StorageManagerIF : : STORE_DATA_FAILED , result ) ;
return ;
}
CommandMessage message ;
2019-08-28 14:50:24 +02:00
DeviceHandlerMessage : : setDeviceHandlerRawReplyMessage ( & message ,
2016-06-15 23:48:41 +02:00
getObjectId ( ) , address , isCommand ) ;
// this->DeviceHandlerCommand = CommandMessage::CMD_NONE;
2018-07-12 16:29:32 +02:00
result = commandQueue - > sendMessage ( sendTo , & message ) ;
2016-06-15 23:48:41 +02:00
if ( result ! = RETURN_OK ) {
IPCStore - > deleteData ( address ) ;
2018-07-12 16:29:32 +02:00
//Silently discard data, this indicates heavy TM traffic which should not be increased by additional events.
2016-06-15 23:48:41 +02:00
}
}
//Default child implementations
DeviceHandlerBase : : RmapAction_t DeviceHandlerBase : : getRmapAction ( ) {
switch ( pstStep ) {
case 0 :
return SEND_WRITE ;
break ;
case 1 :
return GET_WRITE ;
break ;
case 2 :
return SEND_READ ;
break ;
case 3 :
return GET_READ ;
break ;
default :
break ;
}
return NOTHING ;
}
MessageQueueId_t DeviceHandlerBase : : getCommandQueue ( ) const {
2018-07-12 16:29:32 +02:00
return commandQueue - > getId ( ) ;
2016-06-15 23:48:41 +02:00
}
void DeviceHandlerBase : : handleReply ( const uint8_t * receivedData ,
2018-07-12 16:29:32 +02:00
DeviceCommandId_t foundId , uint32_t foundLen ) {
2016-06-15 23:48:41 +02:00
ReturnValue_t result ;
DeviceReplyMap : : iterator iter = deviceReplyMap . find ( foundId ) ;
if ( iter = = deviceReplyMap . end ( ) ) {
2018-07-12 16:29:32 +02:00
replyRawReplyIfnotWiretapped ( receivedData , foundLen ) ;
2016-06-15 23:48:41 +02:00
triggerEvent ( DEVICE_UNKNOWN_REPLY , foundId ) ;
return ;
}
DeviceReplyInfo * info = & ( iter - > second ) ;
if ( info - > delayCycles ! = 0 ) {
if ( info - > periodic ! = 0 ) {
info - > delayCycles = info - > maxDelayCycles ;
} else {
info - > delayCycles = 0 ;
}
result = interpretDeviceReply ( foundId , receivedData ) ;
if ( result ! = RETURN_OK ) {
//Report failed interpretation to FDIR.
2018-07-12 16:29:32 +02:00
replyRawReplyIfnotWiretapped ( receivedData , foundLen ) ;
2016-06-15 23:48:41 +02:00
triggerEvent ( DEVICE_INTERPRETING_REPLY_FAILED , result , foundId ) ;
}
replyToReply ( iter , result ) ;
} else {
//Other completion failure messages are created by timeout.
2018-07-12 16:29:32 +02:00
//Powering down the device might take some time during which periodic replies may still come in.
2016-06-15 23:48:41 +02:00
if ( mode ! = _MODE_WAIT_OFF ) {
triggerEvent ( DEVICE_UNREQUESTED_REPLY , foundId ) ;
}
}
}
ReturnValue_t DeviceHandlerBase : : switchCookieChannel ( object_id_t newChannelId ) {
DeviceCommunicationIF * newCommunication = objectManager - > get <
DeviceCommunicationIF > ( newChannelId ) ;
if ( newCommunication ! = NULL ) {
ReturnValue_t result = newCommunication - > reOpen ( cookie , ioBoardAddress ,
maxDeviceReplyLen ) ;
if ( result ! = RETURN_OK ) {
return result ;
}
return RETURN_OK ;
}
return RETURN_FAILED ;
}
void DeviceHandlerBase : : buildRawDeviceCommand ( CommandMessage * commandMessage ) {
storedRawData = DeviceHandlerMessage : : getStoreAddress ( commandMessage ) ;
ReturnValue_t result = getStorageData ( storedRawData , & rawPacket ,
& rawPacketLen ) ;
if ( result ! = RETURN_OK ) {
replyReturnvalueToCommand ( result , RAW_COMMAND_ID ) ;
storedRawData . raw = StorageManagerIF : : INVALID_ADDRESS ;
} else {
cookieInfo . pendingCommand = deviceCommandMap . find (
( DeviceCommandId_t ) RAW_COMMAND_ID ) ;
cookieInfo . pendingCommand - > second . isExecuting = true ;
cookieInfo . state = COOKIE_WRITE_READY ;
}
}
void DeviceHandlerBase : : commandSwitch ( ReturnValue_t onOff ) {
const uint8_t * switches ;
uint8_t numberOfSwitches = 0 ;
ReturnValue_t result = getSwitches ( & switches , & numberOfSwitches ) ;
if ( result = = RETURN_OK ) {
while ( numberOfSwitches > 0 ) {
powerSwitcher - > sendSwitchCommand ( switches [ numberOfSwitches - 1 ] ,
onOff ) ;
numberOfSwitches - - ;
}
}
}
ReturnValue_t DeviceHandlerBase : : getSwitches ( const uint8_t * * switches ,
uint8_t * numberOfSwitches ) {
* switches = & deviceSwitch ;
* numberOfSwitches = 1 ;
return RETURN_OK ;
}
void DeviceHandlerBase : : modeChanged ( void ) {
}
ReturnValue_t DeviceHandlerBase : : enableReplyInReplyMap (
DeviceCommandMap : : iterator command , uint8_t expectedReplies ,
bool useAlternativeId , DeviceCommandId_t alternativeReply ) {
DeviceReplyMap : : iterator iter ;
if ( useAlternativeId ) {
iter = deviceReplyMap . find ( alternativeReply ) ;
} else {
iter = deviceReplyMap . find ( command - > first ) ;
}
if ( iter ! = deviceReplyMap . end ( ) ) {
DeviceReplyInfo * info = & ( iter - > second ) ;
info - > delayCycles = info - > maxDelayCycles ;
info - > command = command ;
command - > second . expectedReplies = expectedReplies ;
return RETURN_OK ;
} else {
return NO_REPLY_EXPECTED ;
}
}
void DeviceHandlerBase : : doTransition ( Mode_t modeFrom , Submode_t subModeFrom ) {
setMode ( getBaseMode ( mode ) ) ;
2020-07-08 15:19:49 +02:00
sif : : debug < < " DeviceHandlerBase::doTransition Mode: " < < mode < < " reached " < < std : : endl ;
2016-06-15 23:48:41 +02:00
}
uint32_t DeviceHandlerBase : : getTransitionDelayMs ( Mode_t modeFrom ,
Mode_t modeTo ) {
return 0 ;
}
ReturnValue_t DeviceHandlerBase : : getStateOfSwitches ( void ) {
uint8_t numberOfSwitches = 0 ;
const uint8_t * switches ;
ReturnValue_t result = getSwitches ( & switches , & numberOfSwitches ) ;
if ( ( result = = RETURN_OK ) & & ( numberOfSwitches ! = 0 ) ) {
while ( numberOfSwitches > 0 ) {
if ( powerSwitcher - > getSwitchState ( switches [ numberOfSwitches - 1 ] )
= = PowerSwitchIF : : SWITCH_OFF ) {
return PowerSwitchIF : : SWITCH_OFF ;
}
numberOfSwitches - - ;
}
return PowerSwitchIF : : SWITCH_ON ;
}
return NO_SWITCH ;
}
Mode_t DeviceHandlerBase : : getBaseMode ( Mode_t transitionMode ) {
//only child action special modes are handled, as a child should never see any base action modes
if ( transitionMode = = _MODE_START_UP ) {
return _MODE_TO_ON ;
}
if ( transitionMode = = _MODE_SHUT_DOWN ) {
return _MODE_POWER_DOWN ;
}
return transitionMode
& ~ ( TRANSITION_MODE_BASE_ACTION_MASK
| TRANSITION_MODE_CHILD_ACTION_MASK ) ;
}
//SHOULDDO: Allow transition from OFF to NORMAL to reduce complexity in assemblies. And, by the way, throw away DHB and write a new one:
// - Include power and thermal completely, but more modular :-)
// - Don't use modes for state transitions, reduce FSM (Finte State Machine) complexity.
// - Modularization?
ReturnValue_t DeviceHandlerBase : : checkModeCommand ( Mode_t commandedMode ,
Submode_t commandedSubmode , uint32_t * msToReachTheMode ) {
if ( isTransitionalMode ( ) ) {
return IN_TRANSITION ;
}
if ( ( mode = = MODE_ERROR_ON ) & & ( commandedMode ! = MODE_OFF ) ) {
return TRANS_NOT_ALLOWED ;
}
if ( ( commandedMode = = MODE_NORMAL ) & & ( mode = = MODE_OFF ) ) {
return TRANS_NOT_ALLOWED ;
}
if ( ( commandedMode = = MODE_ON ) & & ( mode = = MODE_OFF )
& & ( deviceThermalStatePoolId ! = PoolVariableIF : : NO_PARAMETER ) ) {
DataSet mySet ;
PoolVariable < int8_t > thermalState ( deviceThermalStatePoolId , & mySet ,
PoolVariableIF : : VAR_READ ) ;
PoolVariable < int8_t > thermalRequest ( deviceThermalRequestPoolId , & mySet ,
PoolVariableIF : : VAR_READ ) ;
mySet . read ( ) ;
if ( thermalRequest ! = ThermalComponentIF : : STATE_REQUEST_IGNORE ) {
if ( ! ThermalComponentIF : : isOperational ( thermalState ) ) {
2018-07-12 16:29:32 +02:00
triggerEvent ( ThermalComponentIF : : TEMP_NOT_IN_OP_RANGE ,
thermalState ) ;
2016-06-15 23:48:41 +02:00
return NON_OP_TEMPERATURE ;
}
}
}
return isModeCombinationValid ( commandedMode , commandedSubmode ) ;
}
void DeviceHandlerBase : : startTransition ( Mode_t commandedMode ,
Submode_t commandedSubmode ) {
2020-07-08 15:19:49 +02:00
sif : : debug < < " DeviceHandlerBase::startTransition " < < std : : endl ;
2016-06-15 23:48:41 +02:00
switch ( commandedMode ) {
case MODE_ON :
if ( mode = = MODE_OFF ) {
transitionSourceMode = _MODE_POWER_DOWN ;
transitionSourceSubMode = SUBMODE_NONE ;
setMode ( _MODE_POWER_ON , commandedSubmode ) ;
//already set the delay for the child transition so we don't need to call it twice
childTransitionDelay = getTransitionDelayMs ( _MODE_START_UP ,
MODE_ON ) ;
triggerEvent ( CHANGING_MODE , commandedMode , commandedSubmode ) ;
DataSet mySet ;
PoolVariable < int8_t > thermalRequest ( deviceThermalRequestPoolId ,
& mySet , PoolVariableIF : : VAR_READ_WRITE ) ;
mySet . read ( ) ;
if ( thermalRequest ! = ThermalComponentIF : : STATE_REQUEST_IGNORE ) {
thermalRequest = ThermalComponentIF : : STATE_REQUEST_OPERATIONAL ;
mySet . commit ( PoolVariableIF : : VALID ) ;
}
} else {
setTransition ( MODE_ON , commandedSubmode ) ;
}
break ;
case MODE_OFF :
if ( mode = = MODE_OFF ) {
triggerEvent ( CHANGING_MODE , commandedMode , commandedSubmode ) ;
setMode ( _MODE_POWER_DOWN , commandedSubmode ) ;
} else {
//already set the delay for the child transition so we don't need to call it twice
childTransitionDelay = getTransitionDelayMs ( mode , _MODE_POWER_DOWN ) ;
transitionSourceMode = _MODE_POWER_DOWN ;
transitionSourceSubMode = commandedSubmode ;
childTransitionFailure = CHILD_TIMEOUT ;
setMode ( _MODE_SHUT_DOWN , commandedSubmode ) ;
triggerEvent ( CHANGING_MODE , commandedMode , commandedSubmode ) ;
}
break ;
case MODE_RAW :
if ( mode ! = MODE_OFF ) {
setTransition ( MODE_RAW , commandedSubmode ) ;
} else {
setMode ( MODE_RAW , commandedSubmode ) ;
}
break ;
case MODE_NORMAL :
if ( mode ! = MODE_OFF ) {
setTransition ( MODE_NORMAL , commandedSubmode ) ;
} else {
replyReturnvalueToCommand ( HasModesIF : : TRANS_NOT_ALLOWED ) ;
}
break ;
}
}
void DeviceHandlerBase : : getMode ( Mode_t * mode , Submode_t * submode ) {
* mode = this - > mode ;
* submode = this - > submode ;
}
void DeviceHandlerBase : : setToExternalControl ( ) {
healthHelper . setHealth ( EXTERNAL_CONTROL ) ;
}
void DeviceHandlerBase : : announceMode ( bool recursive ) {
triggerEvent ( MODE_INFO , mode , submode ) ;
}
bool DeviceHandlerBase : : dontCheckQueue ( ) {
return false ;
}
void DeviceHandlerBase : : missedReply ( DeviceCommandId_t id ) {
if ( ignoreMissedRepliesCount > 0 ) {
ignoreMissedRepliesCount - - ;
} else {
triggerEvent ( DEVICE_MISSED_REPLY , id ) ;
}
}
HasHealthIF : : HealthState DeviceHandlerBase : : getHealth ( ) {
return healthHelper . getHealth ( ) ;
}
ReturnValue_t DeviceHandlerBase : : setHealth ( HealthState health ) {
healthHelper . setHealth ( health ) ;
return HasReturnvaluesIF : : RETURN_OK ;
}
void DeviceHandlerBase : : checkSwitchState ( ) {
if ( ( mode = = MODE_ON | | mode = = MODE_NORMAL ) ) {
//We only check in ON and NORMAL, ignore RAW and ERROR_ON.
ReturnValue_t result = getStateOfSwitches ( ) ;
if ( result = = PowerSwitchIF : : SWITCH_OFF & & ! switchOffWasReported ) {
triggerEvent ( PowerSwitchIF : : SWITCH_WENT_OFF ) ;
switchOffWasReported = true ;
}
} else {
switchOffWasReported = false ;
}
}
void DeviceHandlerBase : : doOnActivity ( ) {
}
ReturnValue_t DeviceHandlerBase : : acceptExternalDeviceCommands ( ) {
if ( ( mode ! = MODE_ON ) & & ( mode ! = MODE_NORMAL ) ) {
return WRONG_MODE_FOR_COMMAND ;
}
return RETURN_OK ;
}
2018-07-12 16:29:32 +02:00
void DeviceHandlerBase : : replyRawReplyIfnotWiretapped ( const uint8_t * data ,
size_t len ) {
if ( ( wiretappingMode = = RAW )
& & ( defaultRawReceiver = = requestedRawTraffic ) ) {
//The raw packet was already sent by the wiretapping service
} else {
replyRawData ( data , len , defaultRawReceiver ) ;
}
}
2016-06-15 23:48:41 +02:00
ReturnValue_t DeviceHandlerBase : : handleDeviceHandlerMessage (
CommandMessage * message ) {
ReturnValue_t result ;
switch ( message - > getCommand ( ) ) {
case DeviceHandlerMessage : : CMD_WIRETAPPING :
switch ( DeviceHandlerMessage : : getWiretappingMode ( message ) ) {
case RAW :
wiretappingMode = RAW ;
2018-07-12 16:29:32 +02:00
requestedRawTraffic = commandQueue - > getLastPartner ( ) ;
2016-06-15 23:48:41 +02:00
break ;
case TM :
wiretappingMode = TM ;
2018-07-12 16:29:32 +02:00
requestedRawTraffic = commandQueue - > getLastPartner ( ) ;
2016-06-15 23:48:41 +02:00
break ;
case OFF :
wiretappingMode = OFF ;
break ;
default :
replyReturnvalueToCommand ( INVALID_COMMAND_PARAMETER ) ;
wiretappingMode = OFF ;
return RETURN_OK ;
}
replyReturnvalueToCommand ( RETURN_OK ) ;
return RETURN_OK ;
case DeviceHandlerMessage : : CMD_SWITCH_IOBOARD :
if ( mode ! = MODE_OFF ) {
replyReturnvalueToCommand ( WRONG_MODE_FOR_COMMAND ) ;
} else {
result = switchCookieChannel (
DeviceHandlerMessage : : getIoBoardObjectId ( message ) ) ;
if ( result = = RETURN_OK ) {
replyReturnvalueToCommand ( RETURN_OK ) ;
} else {
replyReturnvalueToCommand ( CANT_SWITCH_IOBOARD ) ;
}
}
return RETURN_OK ;
case DeviceHandlerMessage : : CMD_RAW :
if ( ( mode ! = MODE_RAW ) ) {
DeviceHandlerMessage : : clear ( message ) ;
replyReturnvalueToCommand ( WRONG_MODE_FOR_COMMAND ) ;
} else {
buildRawDeviceCommand ( message ) ;
}
return RETURN_OK ;
default :
return RETURN_FAILED ;
}
}
void DeviceHandlerBase : : setParentQueue ( MessageQueueId_t parentQueueId ) {
modeHelper . setParentQueue ( parentQueueId ) ;
healthHelper . setParentQeueue ( parentQueueId ) ;
}
bool DeviceHandlerBase : : isAwaitingReply ( ) {
std : : map < DeviceCommandId_t , DeviceReplyInfo > : : iterator iter ;
for ( iter = deviceReplyMap . begin ( ) ; iter ! = deviceReplyMap . end ( ) ; + + iter ) {
if ( iter - > second . delayCycles ! = 0 ) {
return true ;
}
}
return false ;
}
ReturnValue_t DeviceHandlerBase : : letChildHandleMessage (
CommandMessage * message ) {
return RETURN_FAILED ;
}
void DeviceHandlerBase : : handleDeviceTM ( SerializeIF * data ,
2018-07-12 16:29:32 +02:00
DeviceCommandId_t replyId , bool neverInDataPool , bool forceDirectTm ) {
2016-06-15 23:48:41 +02:00
DeviceReplyMap : : iterator iter = deviceReplyMap . find ( replyId ) ;
if ( iter = = deviceReplyMap . end ( ) ) {
triggerEvent ( DEVICE_UNKNOWN_REPLY , replyId ) ;
return ;
}
2018-07-12 16:29:32 +02:00
DeviceTmReportingWrapper wrapper ( getObjectId ( ) , replyId , data ) ;
if ( iter - > second . command ! = deviceCommandMap . end ( ) ) { //replies to a command
2016-06-15 23:48:41 +02:00
MessageQueueId_t queueId = iter - > second . command - > second . sendReplyTo ;
2018-07-12 16:29:32 +02:00
2016-06-15 23:48:41 +02:00
if ( queueId ! = NO_COMMANDER ) {
2018-07-12 16:29:32 +02:00
//This may fail, but we'll ignore the fault.
2016-06-15 23:48:41 +02:00
actionHelper . reportData ( queueId , replyId , data ) ;
}
//This check should make sure we get any TM but don't get anything doubled.
2018-07-12 16:29:32 +02:00
if ( wiretappingMode = = TM & & ( requestedRawTraffic ! = queueId ) ) {
actionHelper . reportData ( requestedRawTraffic , replyId , & wrapper ) ;
} else if ( forceDirectTm & & ( defaultRawReceiver ! = queueId ) ) {
// hiding of sender needed so the service will handle it as unexpected Data, no matter what state
//(progress or completed) it is in
actionHelper . reportData ( defaultRawReceiver , replyId , & wrapper ,
true ) ;
}
} else { //unrequested/aperiodic replies
if ( wiretappingMode = = TM ) {
actionHelper . reportData ( requestedRawTraffic , replyId , & wrapper ) ;
} else if ( forceDirectTm ) {
// hiding of sender needed so the service will handle it as unexpected Data, no matter what state
//(progress or completed) it is in
actionHelper . reportData ( defaultRawReceiver , replyId , & wrapper ,
true ) ;
2016-06-15 23:48:41 +02:00
}
}
//Try to cast to DataSet and commit data.
if ( ! neverInDataPool ) {
DataSet * dataSet = dynamic_cast < DataSet * > ( data ) ;
if ( dataSet ! = NULL ) {
dataSet - > commit ( PoolVariableIF : : VALID ) ;
}
}
}
ReturnValue_t DeviceHandlerBase : : executeAction ( ActionId_t actionId ,
MessageQueueId_t commandedBy , const uint8_t * data , uint32_t size ) {
ReturnValue_t result = acceptExternalDeviceCommands ( ) ;
if ( result ! = HasReturnvaluesIF : : RETURN_OK ) {
return result ;
}
DeviceCommandMap : : iterator iter = deviceCommandMap . find ( actionId ) ;
if ( iter = = deviceCommandMap . end ( ) ) {
result = COMMAND_NOT_SUPPORTED ;
} else if ( iter - > second . isExecuting ) {
result = COMMAND_ALREADY_SENT ;
} else {
result = buildCommandFromCommand ( actionId , data , size ) ;
}
if ( result = = RETURN_OK ) {
iter - > second . sendReplyTo = commandedBy ;
iter - > second . isExecuting = true ;
cookieInfo . pendingCommand = iter ;
cookieInfo . state = COOKIE_WRITE_READY ;
}
return result ;
}
void DeviceHandlerBase : : buildInternalCommand ( void ) {
//Neither Raw nor Direct could build a command
ReturnValue_t result = NOTHING_TO_SEND ;
DeviceCommandId_t deviceCommandId = NO_COMMAND_ID ;
if ( mode = = MODE_NORMAL ) {
result = buildNormalDeviceCommand ( & deviceCommandId ) ;
if ( result = = BUSY ) {
2020-06-23 16:58:26 +02:00
// sif::debug << std::hex << getObjectId()
// << ": DeviceHandlerBase::buildInternalCommand busy" << std::endl; //so we can track misconfigurations
2016-06-15 23:48:41 +02:00
result = NOTHING_TO_SEND ; //no need to report this
}
} else if ( mode = = MODE_RAW ) {
result = buildChildRawCommand ( ) ;
deviceCommandId = RAW_COMMAND_ID ;
} else if ( mode & TRANSITION_MODE_CHILD_ACTION_MASK ) {
result = buildTransitionDeviceCommand ( & deviceCommandId ) ;
} else {
return ;
}
if ( result = = NOTHING_TO_SEND ) {
return ;
}
if ( result = = RETURN_OK ) {
DeviceCommandMap : : iterator iter = deviceCommandMap . find (
deviceCommandId ) ;
if ( iter = = deviceCommandMap . end ( ) ) {
result = COMMAND_NOT_SUPPORTED ;
} else if ( iter - > second . isExecuting ) {
2020-06-23 16:58:26 +02:00
// sif::debug << std::hex << getObjectId()
// << ": DHB::buildInternalCommand: Command "
// << deviceCommandId << " isExecuting" << std::endl; //so we can track misconfigurations
2016-06-15 23:48:41 +02:00
return ; //this is an internal command, no need to report a failure here, missed reply will track if a reply is too late, otherwise, it's ok
} else {
iter - > second . sendReplyTo = NO_COMMANDER ;
iter - > second . isExecuting = true ;
cookieInfo . pendingCommand = iter ;
cookieInfo . state = COOKIE_WRITE_READY ;
}
}
if ( result ! = RETURN_OK ) {
triggerEvent ( DEVICE_BUILDING_COMMAND_FAILED , result , deviceCommandId ) ;
}
}
ReturnValue_t DeviceHandlerBase : : buildChildRawCommand ( ) {
return NOTHING_TO_SEND ;
}
uint8_t DeviceHandlerBase : : getReplyDelayCycles (
DeviceCommandId_t deviceCommand ) {
DeviceReplyMap : : iterator iter = deviceReplyMap . find ( deviceCommand ) ;
if ( iter = = deviceReplyMap . end ( ) ) {
return 0 ;
}
return iter - > second . delayCycles ;
}
Mode_t DeviceHandlerBase : : getTransitionSourceMode ( ) const {
return transitionSourceMode ;
}
Submode_t DeviceHandlerBase : : getTransitionSourceSubMode ( ) const {
return transitionSourceSubMode ;
}
void DeviceHandlerBase : : triggerEvent ( Event event , uint32_t parameter1 ,
uint32_t parameter2 ) {
fdirInstance - > triggerEvent ( event , parameter1 , parameter2 ) ;
}
void DeviceHandlerBase : : forwardEvent ( Event event , uint32_t parameter1 ,
uint32_t parameter2 ) const {
fdirInstance - > triggerEvent ( event , parameter1 , parameter2 ) ;
}
void DeviceHandlerBase : : doOffActivity ( ) {
}
ReturnValue_t DeviceHandlerBase : : getParameter ( uint8_t domainId ,
uint16_t parameterId , ParameterWrapper * parameterWrapper ,
const ParameterWrapper * newValues , uint16_t startAtIndex ) {
ReturnValue_t result = fdirInstance - > getParameter ( domainId , parameterId ,
parameterWrapper , newValues , startAtIndex ) ;
if ( result ! = INVALID_DOMAIN_ID ) {
return result ;
}
return INVALID_DOMAIN_ID ;
}
bool DeviceHandlerBase : : isTransitionalMode ( ) {
2018-07-12 16:29:32 +02:00
return ( ( mode
& ( TRANSITION_MODE_BASE_ACTION_MASK
| TRANSITION_MODE_CHILD_ACTION_MASK ) ) ! = 0 ) ;
2016-06-15 23:48:41 +02:00
}
bool DeviceHandlerBase : : commandIsExecuting ( DeviceCommandId_t commandId ) {
auto iter = deviceCommandMap . find ( commandId ) ;
if ( iter ! = deviceCommandMap . end ( ) ) {
return iter - > second . isExecuting ;
} else {
return false ;
}
}
2018-07-12 16:29:32 +02:00
void DeviceHandlerBase : : changeHK ( Mode_t mode , Submode_t submode , bool enable ) {
}
2018-07-13 18:28:26 +02:00
void DeviceHandlerBase : : setTaskIF ( PeriodicTaskIF * task_ ) {
executingTask = task_ ;
}