fsfw/src/fsfw/pus/Service2DeviceAccess.cpp

159 lines
6.6 KiB
C++
Raw Normal View History

2021-07-13 20:58:45 +02:00
#include "fsfw/pus/Service2DeviceAccess.h"
2020-08-13 20:53:35 +02:00
2022-02-02 10:29:30 +01:00
#include "fsfw/action/ActionMessage.h"
2021-07-13 20:58:45 +02:00
#include "fsfw/devicehandlers/DeviceHandlerIF.h"
#include "fsfw/devicehandlers/DeviceHandlerMessage.h"
2022-02-02 10:29:30 +01:00
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/pus/servicepackets/Service2Packets.h"
2021-07-13 20:58:45 +02:00
#include "fsfw/serialize/EndianConverter.h"
#include "fsfw/serialize/SerialLinkedListAdapter.h"
2022-02-02 10:29:30 +01:00
#include "fsfw/serialize/SerializeAdapter.h"
2021-07-13 20:58:45 +02:00
#include "fsfw/serviceinterface/ServiceInterface.h"
2022-02-02 10:29:30 +01:00
#include "fsfw/storagemanager/StorageManagerIF.h"
2020-08-13 20:53:35 +02:00
2022-02-02 10:29:30 +01:00
Service2DeviceAccess::Service2DeviceAccess(object_id_t objectId, uint16_t apid, uint8_t serviceId,
uint8_t numberOfParallelCommands,
uint16_t commandTimeoutSeconds)
2022-09-14 20:10:41 +02:00
: CommandingServiceBase(objectId, apid, "PUS 2 Raw Commanding", serviceId,
numberOfParallelCommands, commandTimeoutSeconds) {}
2020-08-13 20:53:35 +02:00
Service2DeviceAccess::~Service2DeviceAccess() {}
ReturnValue_t Service2DeviceAccess::isValidSubservice(uint8_t subservice) {
2022-02-02 10:29:30 +01:00
switch (static_cast<Subservice>(subservice)) {
case Subservice::COMMAND_RAW_COMMANDING:
case Subservice::COMMAND_TOGGLE_WIRETAPPING:
2022-08-16 01:08:26 +02:00
return returnvalue::OK;
2022-02-02 10:29:30 +01:00
default:
2021-01-03 14:16:52 +01:00
#if FSFW_CPP_OSTREAM_ENABLED == 1
2022-02-02 10:29:30 +01:00
sif::error << "Invalid Subservice" << std::endl;
#endif
2022-02-02 10:29:30 +01:00
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
}
2020-08-13 20:53:35 +02:00
}
2022-02-02 10:29:30 +01:00
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-08-13 20:53:35 +02:00
2022-02-02 10:29:30 +01:00
return checkInterfaceAndAcquireMessageQueue(id, objectId);
2020-08-13 20:53:35 +02:00
}
ReturnValue_t Service2DeviceAccess::checkInterfaceAndAcquireMessageQueue(
2022-02-02 10:29:30 +01:00
MessageQueueId_t* messageQueueToSet, object_id_t* objectId) {
DeviceHandlerIF* possibleTarget = ObjectManager::instance()->get<DeviceHandlerIF>(*objectId);
if (possibleTarget == nullptr) {
return CommandingServiceBase::INVALID_OBJECT;
}
*messageQueueToSet = possibleTarget->getCommandQueue();
2022-08-16 01:08:26 +02:00
return returnvalue::OK;
2020-08-13 20:53:35 +02:00
}
2022-02-02 10:29:30 +01:00
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)) {
case Subservice::COMMAND_RAW_COMMANDING: {
return prepareRawCommand(message, tcData, tcDataLen);
} break;
case Subservice::COMMAND_TOGGLE_WIRETAPPING: {
return prepareWiretappingCommand(message, tcData, tcDataLen);
} break;
default:
2022-08-16 01:08:26 +02:00
return returnvalue::FAILED;
2022-02-02 10:29:30 +01:00
}
2020-08-13 20:53:35 +02:00
}
2022-02-02 10:29:30 +01:00
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 =
2022-07-20 22:21:15 +02:00
ipcStore->addData(&storeAddress, RawCommand.getCommand(), RawCommand.getCommandSize());
2022-02-02 10:29:30 +01:00
DeviceHandlerMessage::setDeviceHandlerRawCommandMessage(messageToSet, storeAddress);
return result;
2020-08-13 20:53:35 +02:00
}
2022-02-02 10:29:30 +01:00
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;
2020-08-13 20:53:35 +02:00
}
ReturnValue_t Service2DeviceAccess::handleReply(const CommandMessage* reply,
2022-02-02 10:29:30 +01:00
Command_t previousCommand, uint32_t* state,
CommandMessage* optionalNextCommand,
object_id_t objectId, bool* isStep) {
switch (reply->getCommand()) {
case CommandMessage::REPLY_COMMAND_OK:
2022-08-16 01:08:26 +02:00
return returnvalue::OK;
2022-02-02 10:29:30 +01:00
case CommandMessage::REPLY_REJECTED:
return reply->getReplyRejectedReason();
default:
return CommandingServiceBase::INVALID_REPLY;
}
2020-08-13 20:53:35 +02:00
}
// 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) {
2022-02-02 10:29:30 +01:00
switch (reply->getCommand()) {
case DeviceHandlerMessage::REPLY_RAW_COMMAND:
sendWiretappingTm(reply, static_cast<uint8_t>(Subservice::REPLY_WIRETAPPING_RAW_TC));
break;
case DeviceHandlerMessage::REPLY_RAW_REPLY:
sendWiretappingTm(reply, static_cast<uint8_t>(Subservice::REPLY_RAW));
break;
default:
2021-01-03 14:16:52 +01:00
#if FSFW_CPP_OSTREAM_ENABLED == 1
2022-02-02 10:29:30 +01:00
sif::error << "Unknown message in Service2DeviceAccess::"
"handleUnrequestedReply with command ID "
<< reply->getCommand() << std::endl;
#endif
2022-02-02 10:29:30 +01:00
break;
}
// Must be reached by all cases to clear message
reply->clear();
2020-08-13 20:53:35 +02:00
}
2022-02-02 10:29:30 +01:00
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;
2022-07-20 22:21:15 +02:00
ReturnValue_t result = ipcStore->getData(storeAddress, &data, &size);
2022-08-16 01:08:26 +02:00
if (result != returnvalue::OK) {
2021-01-03 14:16:52 +01:00
#if FSFW_CPP_OSTREAM_ENABLED == 1
2022-02-02 10:29:30 +01:00
sif::error << "Service2DeviceAccess::sendWiretappingTm: Data Lost in "
"handleUnrequestedReply with failure ID "
<< result << std::endl;
#endif
2022-02-02 10:29:30 +01:00
return;
}
// Init our dummy packet and correct endianness of object ID before
// sending it back.
2022-07-20 22:21:15 +02:00
WiretappingPacket tmPacket(DeviceHandlerMessage::getDeviceObjectId(reply), data);
2022-07-26 13:59:09 +02:00
result = sendTmPacket(subservice, tmPacket.objectId, tmPacket.data, size);
2022-08-16 01:08:26 +02:00
if (result != returnvalue::OK) {
2022-07-26 13:59:09 +02:00
// TODO: Warning
return;
}
2020-08-13 20:53:35 +02:00
}
2022-02-02 10:29:30 +01:00
MessageQueueId_t Service2DeviceAccess::getDeviceQueue() { return commandQueue->getId(); }