#include "PlocHandler.h" #include #include #include #include PlocHandler::PlocHandler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie) : DeviceHandlerBase(objectId, comIF, comCookie) { if (comCookie == NULL) { sif::error << "PlocHandler: Invalid com cookie" << std::endl; } } PlocHandler::~PlocHandler() { } void PlocHandler::doStartUp(){ if(mode == _MODE_START_UP){ setMode(MODE_ON); } } void PlocHandler::doShutDown(){ } ReturnValue_t PlocHandler::buildNormalDeviceCommand( DeviceCommandId_t * id) { return RETURN_OK; } ReturnValue_t PlocHandler::buildTransitionDeviceCommand( DeviceCommandId_t * id){ return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t PlocHandler::buildCommandFromCommand( DeviceCommandId_t deviceCommand, const uint8_t * commandData, size_t commandDataLen) { switch(deviceCommand) { case(PLOC::TC_MEM_WRITE): { return prepareTcMemWriteCommand(commandData, commandDataLen); } case(PLOC::TC_MEM_READ): { return prepareTcMemReadCommand(commandData, commandDataLen); } default: sif::debug << "PlocHandler::buildCommandFromCommand: Command not implemented" << std::endl; return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; } return HasReturnvaluesIF::RETURN_FAILED; } ReturnValue_t PlocHandler::prepareTcMemWriteCommand(const uint8_t * commandData, size_t commandDataLen) { const uint32_t memoryAddress = *(commandData) << 24 | *(commandData + 1) << 16 | *(commandData + 2) << 8 | *(commandData + 3); const uint32_t memoryData = *(commandData + 4) << 24 | *(commandData + 5) << 16 | *(commandData + 6) << 8 | *(commandData + 7); PLOC::TcMemWrite tcMemWrite(memoryAddress, memoryData); if (tcMemWrite.getFullSize() > PLOC::MAX_COMMAND_SIZE) { sif::debug << "PlocHandler::prepareTcMemWriteCommand: Command too big" << std::endl; return RETURN_FAILED; } memcpy(commandBuffer, tcMemWrite.getWholeData(), tcMemWrite.getFullSize()); rawPacket = commandBuffer; rawPacketLen = tcMemWrite.getFullSize(); rememberCommandId = PLOC::TC_MEM_WRITE; return RETURN_OK; } ReturnValue_t PlocHandler::prepareTcMemReadCommand(const uint8_t * commandData, size_t commandDataLen) { const uint32_t memoryAddress = *(commandData) << 24 | *(commandData + 1) << 16 | *(commandData + 2) << 8 | *(commandData + 3); PLOC::TcMemRead tcMemRead(memoryAddress); if (tcMemRead.getFullSize() > PLOC::MAX_COMMAND_SIZE) { sif::debug << "PlocHandler::prepareTcMemReadCommand: Command too big" << std::endl; return RETURN_FAILED; } memcpy(commandBuffer, tcMemRead.getWholeData(), tcMemRead.getFullSize()); rawPacket = commandBuffer; rawPacketLen = tcMemRead.getFullSize(); rememberCommandId = PLOC::TC_MEM_READ; return RETURN_OK; } void PlocHandler::fillCommandAndReplyMap() { this->insertInCommandAndReplyMap(PLOC::TC_MEM_WRITE, 1, nullptr, PLOC::SIZE_ACK_REPORT); this->insertInCommandAndReplyMap(PLOC::TC_MEM_READ, 1, nullptr, PLOC::SIZE_ACK_REPORT); } ReturnValue_t PlocHandler::scanForReply(const uint8_t *start, size_t remainingSize, DeviceCommandId_t *foundId, size_t *foundLen) { ReturnValue_t result = RETURN_OK; uint16_t apid = (*(start) << 8 | *(start + 1)) & APID_MASK; switch(apid) { case(PLOC::APID_ACK_SUCCESS): *foundLen = PLOC::SIZE_ACK_REPORT; *foundId = rememberCommandId; break; case(PLOC::APID_ACK_FAILURE): *foundLen = PLOC::SIZE_ACK_REPORT; *foundId = rememberCommandId; break; default: sif::debug << "PlocHandler::scanForReply: Reply has invalid apid" << std::endl; return IGNORE_REPLY_DATA; break; } return result; } ReturnValue_t PlocHandler::verifyPacket(const uint8_t* start, size_t foundLen) { uint16_t receivedCrc = *(start + foundLen - 2) << 8 | *(start + foundLen - 1); uint16_t recalculatedCrc = CRC::crc16ccitt(start, foundLen - 2, 0); if (receivedCrc != recalculatedCrc) { sif::debug << "PlocHandler::verifyPacket: CRC failure of ACK reply" << std::endl; return CRC_FAILURE; } return RETURN_OK; } ReturnValue_t PlocHandler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) { uint16_t apid = (*(packet) << 8 | *(packet + 1)) & APID_MASK; if (apid == PLOC::APID_ACK_FAILURE) { sif::error << "PlocHandler::interpretDeviceReply: Received ACK failure reply" << std::endl; triggerEvent(ACK_FAILURE, id); replyRawData(packet, PLOC::SIZE_ACK_REPORT, defaultRawReceiver); return RETURN_OK; } if (verifyPacket(packet, PLOC::SIZE_ACK_REPORT) == CRC_FAILURE) { sif::error << "PlocHandler::interpretDeviceReply: CRC failure in Ack reply" << std::endl; replyRawData(packet, PLOC::SIZE_ACK_REPORT, defaultRawReceiver); triggerEvent(CRC_FAILURE_IN_ACK_REPLY, id); return RETURN_OK; } switch (id) { case (PLOC::TC_MEM_WRITE): receiveExecutionReport(); break; case (PLOC::TC_MEM_READ): receiveTmMemoryReadReport(); receiveExecutionReport(); break; default: sif::debug << "PlocHandler::interpretDeviceReply: Unknown device reply id" << std::endl; return DeviceHandlerIF::UNKNOWN_DEVICE_REPLY; } rememberCommandId = PLOC::NONE; return RETURN_OK; } ReturnValue_t PlocHandler::receiveExecutionReport() { size_t receivedDataLen = 0; uint8_t *receivedData = nullptr; ReturnValue_t result = RETURN_OK; result = communicationInterface->requestReceiveMessage(comCookie, PLOC::SIZE_EXE_REPORT); if (result != RETURN_OK) { sif::error << "PlocHandler::receiveExecutionReport: Failed to request execution report" << std::endl; return result; } result = communicationInterface->readReceivedMessage(comCookie, &receivedData, &receivedDataLen); if (result != RETURN_OK) { sif::error << "PlocHandler::receiveExecutionReport: Failed to read execution report" << std::endl; return result; } if(verifyPacket(receivedData, receivedDataLen) == CRC_FAILURE) { replyRawData(receivedData, receivedDataLen, defaultRawReceiver); triggerEvent(EXE_RPT_INVALID_CRC); sif::error << "PlocHandler::receiveExecutionReport: Execution report has invalid crc" << std::endl; return result; } result = handleExecutionReport(receivedData, receivedDataLen); } void PlocHandler::handleExecutionReport(const uint8_t* receivedData, size_t receivedDataLen) { uint16_t apid = (*(receivedData) << 8 | *(receivedData + 1)) & APID_MASK; switch (apid) { case (PLOC::APID_EXE_SUCCESS): { return; } case (PLOC::APID_EXE_FAILURE): { //TODO: Interpretation of status field in execution report sif::error << "PlocHandler::handleExecutionReport: Received execution failure report" << std::endl; triggerEvent(EXE_FAILURE, rememberCommandId); return EXE_REPLY_CRC_FAILURE; } } return RETURN_OK; } void PlocHandler::receiveTmMemoryReadReport() { size_t receivedDataLen = 0; uint8_t *receivedData = nullptr; /* Receiving the telemetry packet */ ReturnValue_t result = communicationInterface->requestReceiveMessage(comCookie, PLOC::SIZE_TM_MEM_READ_REPORT); if (result != RETURN_OK) { sif::error << "PlocHandler::receiveExecutionReport: Failed to request memory read telemetry " << std::endl; triggerEvent(REQUESTING_TM_READ_REPORT_FAILED, result); return; } result = communicationInterface->readReceivedMessage(comCookie, &receivedData, &receivedDataLen); if (result != RETURN_OK) { sif::error << "PlocHandler::receiveExecutionReport: Failed to request memory read telemetry " << std::endl; return; } uint16_t apid = (*(receivedData) << 8 | *(receivedData + 1)) & APID_MASK; if (apid != PLOC::APID_TM_READ_REPORT) { sif::error << "PlocHandler::receiveTmReadReport: Tm read report has invalid apid" << std::endl; return; } if(verifyPacket(receivedData, receivedDataLen) == CRC_FAILURE) { replyRawData(receivedData, receivedDataLen, defaultRawReceiver); triggerEvent(TM_READ_RPT_INVALID_CRC); sif::error << "PlocHandler::receiveTmReadReport: TM read report has invalid crc" << std::endl; return; } handleDeviceTM(receivedData, receivedDataLen, PLOC::TC_MEM_READ); } void PlocHandler::handleDeviceTM(const uint8_t* data, size_t dataSize, DeviceCommandId_t replyId) { ReturnValue_t result = RETURN_OK; DeviceReplyMap::iterator iter = deviceReplyMap.find(replyId); if (iter == deviceReplyMap.end()) { sif::debug << "PlocHandler::handleDeviceTM: Unknown reply id" << std::endl; return; } MessageQueueId_t queueId = iter->second.command->second.sendReplyTo; if (queueId == NO_COMMANDER) { return; } result = actionHelper.reportData(queueId, replyId, data, dataSize); if (result != RETURN_OK) { sif::debug << "PlocHandler::handleDeviceTM: Failed to report data" << std::endl; } } void PlocHandler::setNormalDatapoolEntriesInvalid(){ } uint32_t PlocHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo){ return 500; } ReturnValue_t PlocHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, LocalDataPoolManager& poolManager) { return HasReturnvaluesIF::RETURN_OK; } void PlocHandler::setModeNormal() { mode = MODE_NORMAL; }