| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // ====================================================================== | ||
| 2 | // \title FprimeRouter.cpp | ||
| 3 | // \author thomas-bc | ||
| 4 | // \brief cpp file for FprimeRouter component implementation class | ||
| 5 | // ====================================================================== | ||
| 6 | |||
| 7 | #include "Svc/FprimeRouter/FprimeRouter.hpp" | ||
| 8 | #include "Fw/Com/ComPacket.hpp" | ||
| 9 | #include "Fw/FPrimeBasicTypes.hpp" | ||
| 10 | #include "Fw/Logger/Logger.hpp" | ||
| 11 | #include "config/ApidEnumAc.hpp" | ||
| 12 | |||
| 13 | namespace Svc { | ||
| 14 | |||
| 15 | // ---------------------------------------------------------------------- | ||
| 16 | // Component construction and destruction | ||
| 17 | // ---------------------------------------------------------------------- | ||
| 18 | |||
| 19 |
3/9✓ Branch 2 taken 50 times.
✓ Branch 4 taken 50 times.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
|
51 | FprimeRouter ::FprimeRouter(const char* const compName) : FprimeRouterComponentBase(compName) { |
| 20 | // Mark every table entry unused | ||
| 21 |
2/2✓ Branch 1 taken 50 times.
✓ Branch 2 taken 1 times.
|
51 | for (FwSizeType i = 0; i < FW_NUM_ARRAY_ELEMENTS(this->m_bufferContextTable); i++) { |
| 22 |
1/1✓ Branch 1 taken 50 times.
|
50 | this->m_bufferContextTable[i].state = Fw::Active::INACTIVE; |
| 23 | } | ||
| 24 | 1 | } | |
| 25 | |||
| 26 |
3/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
✓ Branch 3 taken 1 times.
|
102 | FprimeRouter ::~FprimeRouter() {} |
| 27 | |||
| 28 | // ---------------------------------------------------------------------- | ||
| 29 | // Handler implementations for user-defined typed input ports | ||
| 30 | // ---------------------------------------------------------------------- | ||
| 31 | |||
| 32 | 146 | void FprimeRouter ::dataIn_handler(FwIndexType portNum, Fw::Buffer& packetBuffer, const ComCfg::FrameContext& context) { | |
| 33 | Fw::SerializeStatus status; | ||
| 34 | 146 | Fw::ComPacketType packetType = context.get_apid(); | |
| 35 | // Route based on received APID (packet type) | ||
| 36 |
2/3✓ Branch 0 taken 140 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
146 | switch (packetType) { |
| 37 | // Handle a command packet | ||
| 38 | 140 | case Fw::ComPacketType::FW_PACKET_COMMAND: { | |
| 39 | // Allocate a com buffer on the stack | ||
| 40 |
1/1✓ Branch 1 taken 140 times.
|
140 | Fw::ComBuffer com; |
| 41 | // Copy the contents of the packet buffer into the com buffer | ||
| 42 |
3/3✓ Branch 1 taken 140 times.
✓ Branch 4 taken 140 times.
✓ Branch 7 taken 140 times.
|
140 | status = com.setBuff(packetBuffer.getData(), packetBuffer.getSize()); |
| 43 |
1/2✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
|
140 | if (status == Fw::FW_SERIALIZE_OK) { |
| 44 | // Send the com buffer - critical functionality so it is considered an error not to | ||
| 45 | // have the port connected. This is why we don't check isConnected() before sending. | ||
| 46 |
1/1✓ Branch 1 taken 140 times.
|
140 | this->commandOut_out(0, com, 0); |
| 47 | } else { | ||
| 48 | ✗ | this->log_WARNING_HI_SerializationError(status); | |
| 49 | } | ||
| 50 | // The command buffer was copied into the com buffer above, so ownership of the | ||
| 51 | // incoming packetBuffer is returned immediately with the context it was received with. | ||
| 52 |
1/1✓ Branch 1 taken 140 times.
|
140 | this->dataReturnOut_out(0, packetBuffer, context); |
| 53 | 140 | break; | |
| 54 | 140 | } | |
| 55 | // Handle a file packet | ||
| 56 | 6 | case Fw::ComPacketType::FW_PACKET_FILE: { | |
| 57 | // If the file uplink output port is connected, send the file packet directly. | ||
| 58 | // Ownership is passed to the receiver and will come back on fileBufferReturnIn, | ||
| 59 | // at which point we return it to the deframer via dataReturnOut. fileOut carries | ||
| 60 | // only Fw::Buffer, so remember the context here to restore it on return. | ||
| 61 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if (this->isConnected_fileOut_OutputPort(0)) { |
| 62 |
2/3✓ Branch 1 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
|
6 | if (this->insertContext(packetBuffer, context) == Fw::Success::FAILURE) { |
| 63 | ✗ | this->log_WARNING_HI_FileOutContextTableFull(); | |
| 64 | } | ||
| 65 | 6 | this->fileOut_out(0, packetBuffer); | |
| 66 | } else { | ||
| 67 | // Port not connected, return the buffer immediately with its context | ||
| 68 | ✗ | this->dataReturnOut_out(0, packetBuffer, context); | |
| 69 | } | ||
| 70 | 6 | break; | |
| 71 | } | ||
| 72 | ✗ | default: { | |
| 73 | // Packet type is not known to the F Prime protocol. If the unknownDataOut port is | ||
| 74 | // connected, forward packet and context for further processing. | ||
| 75 | // Ownership is passed to the receiver and will come back on fileBufferReturnIn, | ||
| 76 | // at which point we return it to the deframer via dataReturnOut. The return path | ||
| 77 | // (fileBufferReturnIn) carries no context, so remember it here to restore on return. | ||
| 78 | ✗ | if (this->isConnected_unknownDataOut_OutputPort(0)) { | |
| 79 | ✗ | if (this->insertContext(packetBuffer, context) == Fw::Success::FAILURE) { | |
| 80 | ✗ | this->log_WARNING_HI_UnknownDataOutContextTableFull(); | |
| 81 | } | ||
| 82 | ✗ | this->unknownDataOut_out(0, packetBuffer, context); | |
| 83 | } else { | ||
| 84 | // Port not connected, return the buffer immediately with its context | ||
| 85 | ✗ | this->dataReturnOut_out(0, packetBuffer, context); | |
| 86 | } | ||
| 87 | ✗ | break; | |
| 88 | } | ||
| 89 | } | ||
| 90 | 146 | } | |
| 91 | |||
| 92 | 140 | void FprimeRouter ::cmdResponseIn_handler(FwIndexType portNum, | |
| 93 | FwOpcodeType opcode, | ||
| 94 | U32 cmdSeq, | ||
| 95 | const Fw::CmdResponse& response) { | ||
| 96 | // Nothing to do | ||
| 97 | 140 | } | |
| 98 | |||
| 99 | 6 | void FprimeRouter ::fileBufferReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) { | |
| 100 | // Restore the context that was saved when this buffer was handed off on | ||
| 101 | // fileOut/unknownDataOut | ||
| 102 |
1/1✓ Branch 1 taken 6 times.
|
6 | ComCfg::FrameContext context; |
| 103 |
2/3✓ Branch 1 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
|
6 | if (this->takeContext(fwBuffer, context) == Fw::Success::FAILURE) { |
| 104 | // Buffer not found in the table: return with an empty context (already default) | ||
| 105 | ✗ | this->log_WARNING_HI_BufferContextNotFound(); | |
| 106 | } | ||
| 107 |
1/1✓ Branch 1 taken 6 times.
|
6 | this->dataReturnOut_out(0, fwBuffer, context); |
| 108 | 6 | } | |
| 109 | |||
| 110 | // ---------------------------------------------------------------------- | ||
| 111 | // Buffer-to-context association table helpers | ||
| 112 | // ---------------------------------------------------------------------- | ||
| 113 | |||
| 114 | 6 | Fw::Success FprimeRouter ::insertContext(const Fw::Buffer& buffer, const ComCfg::FrameContext& context) { | |
| 115 | 6 | const U8* key = buffer.getData(); | |
| 116 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | for (FwSizeType i = 0; i < FW_NUM_ARRAY_ELEMENTS(this->m_bufferContextTable); i++) { |
| 117 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if (this->m_bufferContextTable[i].state == Fw::Active::INACTIVE) { |
| 118 | 6 | this->m_bufferContextTable[i].state = Fw::Active::ACTIVE; | |
| 119 | 6 | this->m_bufferContextTable[i].key = key; | |
| 120 | 6 | this->m_bufferContextTable[i].context = context; | |
| 121 | 6 | return Fw::Success::SUCCESS; | |
| 122 | } | ||
| 123 | } | ||
| 124 | // Table full | ||
| 125 | ✗ | return Fw::Success::FAILURE; | |
| 126 | } | ||
| 127 | |||
| 128 | 6 | Fw::Success FprimeRouter ::takeContext(const Fw::Buffer& buffer, ComCfg::FrameContext& context) { | |
| 129 | 6 | const U8* key = buffer.getData(); | |
| 130 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | for (FwSizeType i = 0; i < FW_NUM_ARRAY_ELEMENTS(this->m_bufferContextTable); i++) { |
| 131 |
3/6✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
|
6 | if (this->m_bufferContextTable[i].state == Fw::Active::ACTIVE && this->m_bufferContextTable[i].key == key) { |
| 132 | 6 | context = this->m_bufferContextTable[i].context; | |
| 133 | 6 | this->m_bufferContextTable[i].state = Fw::Active::INACTIVE; | |
| 134 | 6 | return Fw::Success::SUCCESS; | |
| 135 | } | ||
| 136 | } | ||
| 137 | // Not found | ||
| 138 | ✗ | return Fw::Success::FAILURE; | |
| 139 | } | ||
| 140 | |||
| 141 | } // namespace Svc | ||
| 142 |