fsfw/pus/Service2DeviceAccess.cpp

172 lines
5.9 KiB
C++
Raw Permalink Normal View History

2020-08-13 20:53:35 +02:00
#include "Service2DeviceAccess.h"
#include "servicepackets/Service2Packets.h"
2021-06-05 19:52:38 +02:00
#include "../objectmanager/ObjectManager.h"
2020-08-13 20:53:35 +02:00
#include "../devicehandlers/DeviceHandlerIF.h"
#include "../storagemanager/StorageManagerIF.h"
#include "../devicehandlers/DeviceHandlerMessage.h"
#include "../serialize/EndianConverter.h"
#include "../action/ActionMessage.h"
#include "../serialize/SerializeAdapter.h"
#include "../serialize/SerialLinkedListAdapter.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
Service2DeviceAccess::Service2DeviceAccess(object_id_t objectId,
uint16_t apid, uint8_t serviceId, uint8_t numberOfParallelCommands,
uint16_t commandTimeoutSeconds):
CommandingServiceBase(objectId, apid, serviceId,
numberOfParallelCommands, commandTimeoutSeconds) {}
Service2DeviceAccess::~Service2DeviceAccess() {}
ReturnValue_t Service2DeviceAccess::isValidSubservice(uint8_t subservice) {
switch(static_cast<Subservice>(subservice)){
2020-11-09 21:33:09 +01:00
case Subservice::COMMAND_RAW_COMMANDING:
case Subservice::COMMAND_TOGGLE_WIRETAPPING:
2020-08-13 20:53:35 +02:00
return HasReturnvaluesIF::RETURN_OK;
default:
2021-01-03 14:16:52 +01:00
#if FSFW_CPP_OSTREAM_ENABLED == 1
2020-08-13 20:53:35 +02:00
sif::error << "Invalid Subservice" << std::endl;
#endif
2020-08-13 20:53:35 +02:00
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
}
}
ReturnValue_t Service2DeviceAccess::getMessageQueueAndObject(
uint8_t subservice, const uint8_t* tcData, size_t tcDataLen,
MessageQueueId_t* id, object_id_t* objectId) {
if(tcDataLen < sizeof(object_id_t)) {
return CommandingServiceBase::INVALID_TC;
}
SerializeAdapter::deSerialize(objectId, &tcData,
&tcDataLen, SerializeIF::Endianness::BIG);
2020-11-09 21:33:09 +01:00
return checkInterfaceAndAcquireMessageQueue(id,objectId);
2020-08-13 20:53:35 +02:00
}
ReturnValue_t Service2DeviceAccess::checkInterfaceAndAcquireMessageQueue(
MessageQueueId_t * messageQueueToSet, object_id_t *objectId) {
DeviceHandlerIF* possibleTarget =
2021-06-05 19:52:38 +02:00
ObjectManager::instance()->get<DeviceHandlerIF>(*objectId);
2020-08-13 20:53:35 +02:00
if(possibleTarget == nullptr) {
return CommandingServiceBase::INVALID_OBJECT;
}
*messageQueueToSet = possibleTarget->getCommandQueue();
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Service2DeviceAccess::prepareCommand(CommandMessage* message,
uint8_t subservice, const uint8_t* tcData, size_t tcDataLen,
uint32_t* state, object_id_t objectId) {
switch(static_cast<Subservice>(subservice)){
2020-11-09 21:33:09 +01:00
case Subservice::COMMAND_RAW_COMMANDING: {
return prepareRawCommand(message, tcData, tcDataLen);
2020-08-13 20:53:35 +02:00
}
break;
2020-11-09 21:33:09 +01:00
case Subservice::COMMAND_TOGGLE_WIRETAPPING: {
return prepareWiretappingCommand(message, tcData, tcDataLen);
2020-08-13 20:53:35 +02:00
}
break;
default:
return HasReturnvaluesIF::RETURN_FAILED;
}
}
ReturnValue_t Service2DeviceAccess::prepareRawCommand(
CommandMessage* messageToSet, const uint8_t *tcData,size_t tcDataLen) {
RawCommand RawCommand(tcData,tcDataLen);
// store command into the Inter Process Communication Store
store_address_t storeAddress;
ReturnValue_t result = IPCStore->addData(&storeAddress,
RawCommand.getCommand(), RawCommand.getCommandSize());
DeviceHandlerMessage::setDeviceHandlerRawCommandMessage(messageToSet,
storeAddress);
return result;
}
ReturnValue_t Service2DeviceAccess::prepareWiretappingCommand(
CommandMessage *messageToSet, const uint8_t *tcData,
size_t tcDataLen) {
if(tcDataLen != WiretappingToggle::WIRETAPPING_COMMAND_SIZE) {
return CommandingServiceBase::INVALID_TC;
}
WiretappingToggle command;
ReturnValue_t result = command.deSerialize(&tcData, &tcDataLen,
SerializeIF::Endianness::BIG);
DeviceHandlerMessage::setDeviceHandlerWiretappingMessage(messageToSet,
command.getWiretappingMode());
return result;
}
ReturnValue_t Service2DeviceAccess::handleReply(const CommandMessage* reply,
Command_t previousCommand, uint32_t* state,
CommandMessage* optionalNextCommand, object_id_t objectId,
bool* isStep) {
switch(reply->getCommand()) {
case CommandMessage::REPLY_COMMAND_OK:
return HasReturnvaluesIF::RETURN_OK;
case CommandMessage::REPLY_REJECTED:
return reply->getReplyRejectedReason();
default:
return CommandingServiceBase::INVALID_REPLY;
}
}
// All device handlers set service 2 as default raw receiver for wiretapping
// so we have to handle those unrequested messages.
void Service2DeviceAccess::handleUnrequestedReply(CommandMessage* reply) {
switch(reply->getCommand()) {
case DeviceHandlerMessage::REPLY_RAW_COMMAND:
sendWiretappingTm(reply,
2020-11-09 21:33:09 +01:00
static_cast<uint8_t>(Subservice::REPLY_WIRETAPPING_RAW_TC));
2020-08-13 20:53:35 +02:00
break;
case DeviceHandlerMessage::REPLY_RAW_REPLY:
sendWiretappingTm(reply,
2020-11-09 21:33:09 +01:00
static_cast<uint8_t>(Subservice::REPLY_RAW));
2020-08-13 20:53:35 +02:00
break;
default:
2021-01-03 14:16:52 +01:00
#if FSFW_CPP_OSTREAM_ENABLED == 1
2020-08-13 20:53:35 +02:00
sif::error << "Unknown message in Service2DeviceAccess::"
"handleUnrequestedReply with command ID " <<
reply->getCommand() << std::endl;
#endif
2020-08-13 20:53:35 +02:00
break;
}
//Must be reached by all cases to clear message
reply->clear();
}
void Service2DeviceAccess::sendWiretappingTm(CommandMessage *reply,
uint8_t subservice) {
// Raw Wiretapping
// Get Address of Data from Message
store_address_t storeAddress = DeviceHandlerMessage::getStoreAddress(reply);
const uint8_t* data = nullptr;
size_t size = 0;
ReturnValue_t result = IPCStore->getData(storeAddress, &data, &size);
if(result != HasReturnvaluesIF::RETURN_OK){
2021-01-03 14:16:52 +01:00
#if FSFW_CPP_OSTREAM_ENABLED == 1
2020-08-13 20:53:35 +02:00
sif::error << "Service2DeviceAccess::sendWiretappingTm: Data Lost in "
"handleUnrequestedReply with failure ID "<< result
<< std::endl;
#endif
2020-08-13 20:53:35 +02:00
return;
}
// Init our dummy packet and correct endianness of object ID before
// sending it back.
WiretappingPacket TmPacket(DeviceHandlerMessage::getDeviceObjectId(reply),
data);
TmPacket.objectId = EndianConverter::convertBigEndian(TmPacket.objectId);
sendTmPacket(subservice, TmPacket.data,size, reinterpret_cast<uint8_t*>(
&TmPacket.objectId), sizeof(TmPacket.objectId));
}
MessageQueueId_t Service2DeviceAccess::getDeviceQueue() {
return commandQueue->getId();
}