F´ Flight Software - C/C++ Documentation
A framework for building embedded system applications to NASA flight quality standards.
GenericHub.cpp
Go to the documentation of this file.
1 // ======================================================================
2 // \title GenericHub.cpp
3 // \author mstarch
4 // \brief cpp file for GenericHub component implementation class
5 //
6 // \copyright
7 // Copyright 2009-2015, by the California Institute of Technology.
8 // ALL RIGHTS RESERVED. United States Government Sponsorship
9 // acknowledged.
10 //
11 // ======================================================================
12 
13 #include <Fw/FPrimeBasicTypes.hpp>
15 #include "Fw/Logger/Logger.hpp"
16 #include "Fw/Types/Assert.hpp"
17 
18 // Required port serialization or the hub cannot work
19 static_assert(FW_PORT_SERIALIZATION, "FW_PORT_SERIALIZATION must be enabled to use GenericHub");
20 
21 namespace Svc {
22 
23 // ----------------------------------------------------------------------
24 // Construction, initialization, and destruction
25 // ----------------------------------------------------------------------
26 
27 GenericHub::GenericHub(const char* const compName) : GenericHubComponentBase(compName) {}
28 
30 
31 void GenericHub::send_data(const HubType type, const FwIndexType port, const U8* data, const FwSizeType size) {
32  FW_ASSERT(data != nullptr);
33  Fw::SerializeStatus status;
34  // Buffer to send and a buffer used to write to it
35  Fw::Buffer outgoing = allocate_out(0, static_cast<U32>(size + sizeof(U32) + sizeof(U32) + sizeof(FwBuffSizeType)));
36  auto serialize = outgoing.getSerializer();
37  // Write data to our buffer
38  status = serialize.serializeFrom(static_cast<U32>(type));
39  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, static_cast<FwAssertArgType>(status));
40  status = serialize.serializeFrom(static_cast<U32>(port));
41  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, static_cast<FwAssertArgType>(status));
42  status = serialize.serializeFrom(data, static_cast<FwBuffSizeType>(size));
43  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, static_cast<FwAssertArgType>(status));
44  outgoing.setSize(serialize.getSize());
45  toBufferDriver_out(0, outgoing);
46 }
47 
48 // ----------------------------------------------------------------------
49 // Handler implementations for user-defined typed input ports
50 // ----------------------------------------------------------------------
51 
52 void GenericHub::bufferIn_handler(const FwIndexType portNum, Fw::Buffer& fwBuffer) {
53  this->send_data(HUB_TYPE_BUFFER, portNum, fwBuffer.getData(), fwBuffer.getSize());
54  bufferInReturn_out(portNum, fwBuffer);
55 }
56 
57 void GenericHub::bufferOutReturn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) {
58  // Return the buffer
59  fromBufferDriverReturn_out(0, fwBuffer);
60 }
61 
62 void GenericHub ::cmdDispIn_handler(FwIndexType portNum, Fw::ComBuffer& data, U32 context) {
63  Fw::SerializeStatus status;
64  // Buffer to send and a buffer used to write to it. Must hold a maximum-size
65  // command buffer (serialized without its length token) plus the context word.
66  U8 buffer[FW_COM_BUFFER_MAX_SIZE + sizeof(U32)];
67 
68  Fw::ExternalSerializeBuffer serializer(buffer, sizeof(buffer));
69  serializer.resetSer();
70 
71  status = serializer.serializeFrom(data.getBuffAddr(), data.getSize(), Fw::Serialization::OMIT_LENGTH);
72  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, static_cast<FwAssertArgType>(status));
73  status = serializer.serializeFrom(context);
74  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, static_cast<FwAssertArgType>(status));
75  FwSizeType size = serializer.getSize();
76 
77  this->send_data(HUB_TYPE_CMD_DISP, portNum, buffer, size);
78 }
79 
80 void GenericHub ::cmdRespIn_handler(FwIndexType portNum,
81  FwOpcodeType opCode,
82  U32 cmdSeq,
83  const Fw::CmdResponse& response) {
85  U8 buffer[sizeof(opCode) + sizeof(cmdSeq) + Fw::CmdResponse::SERIALIZED_SIZE];
86  Fw::ExternalSerializeBuffer serializer(buffer, sizeof(buffer));
87  serializer.resetSer();
88 
89  status = serializer.serializeFrom(opCode);
91  status = serializer.serializeFrom(cmdSeq);
93  status = serializer.serializeFrom(response);
95  FwSizeType size = serializer.getSize();
96 
97  this->send_data(HUB_TYPE_CMD_RESP, portNum, buffer, size);
98 }
99 
100 void GenericHub::fromBufferDriver_handler(const FwIndexType portNum, Fw::Buffer& fwBuffer) {
101  HubType type = HUB_TYPE_MAX;
102  U32 type_in = 0;
103  U32 port = 0;
104  FwBuffSizeType size = 0;
106 
107  // Representation of incoming data prepped for serialization
108  auto incoming = fwBuffer.getDeserializer();
109  // Check the size of the data first
110  if (fwBuffer.getSize() < (sizeof(U32) + sizeof(U32) + sizeof(FwBuffSizeType))) {
112  } else {
113  status = incoming.deserializeTo(type_in);
114  }
115  // If the deserialization was good, but the type is invalid, set invalid data
116  if ((status == Fw::FW_SERIALIZE_OK) && (type_in >= HUB_TYPE_MAX)) {
118  }
119  // If the deserialization was good and the type was valid, set the type and move onto port deserialization
120  else if (status == Fw::FW_SERIALIZE_OK) {
121  type = static_cast<HubType>(type_in);
122  status = incoming.deserializeTo(port);
123  }
124  // If the deserialization was good, move onto size deserialization
125  if (status == Fw::FW_SERIALIZE_OK) {
126  status = incoming.deserializeTo(size);
127  }
128  // All deserialization looks good, check that the size matches the buffer size before calling the appropriate ports
129  if (status == Fw::FW_SERIALIZE_OK &&
130  (size == (fwBuffer.getSize() - sizeof(U32) - sizeof(U32) - sizeof(FwBuffSizeType)))) {
131  // invokeSerial deserializes arguments before calling a normal invoke, this will return ownership immediately
132  U8* rawData = fwBuffer.getData() + sizeof(U32) + sizeof(U32) + sizeof(FwBuffSizeType);
133  FwSizeType rawSize = fwBuffer.getSize() - sizeof(U32) - sizeof(U32) - sizeof(FwBuffSizeType);
134  if (type == HUB_TYPE_PORT) {
135  // Com buffer representations should be copied before the call returns, so we need not "allocate" new data
136  Fw::ExternalSerializeBuffer wrapper(rawData, rawSize);
137  status = wrapper.setBuffLen(rawSize);
138  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, static_cast<FwAssertArgType>(status));
139  // Confirm that the port is valid and connected before calling out
140  if (port < this->getNum_serialOut_OutputPorts() &&
141  this->isConnected_serialOut_OutputPort(static_cast<FwIndexType>(port))) {
142  serialOut_out(static_cast<FwIndexType>(port), wrapper);
143  }
144  // Deallocate the existing buffer
145  fromBufferDriverReturn_out(0, fwBuffer);
146  } else if (type == HUB_TYPE_BUFFER) {
147  // Fw::Buffers can reuse the existing data buffer as the storage type! No deallocation done.
148  fwBuffer.set(rawData, rawSize, fwBuffer.getContext());
149  // Confirm that the port is valid and connected before calling out
150  if (port < this->getNum_bufferOut_OutputPorts() &&
151  this->isConnected_bufferOut_OutputPort(static_cast<FwIndexType>(port))) {
152  bufferOut_out(static_cast<FwIndexType>(port), fwBuffer);
153  } else {
154  // Return the buffer if the port is invalid or not connected to avoid leaks
155  fromBufferDriverReturn_out(0, fwBuffer);
156  }
157  } else if (type == HUB_TYPE_EVENT) {
158  FwEventIdType id;
159  Fw::Time timeTag;
160  Fw::LogSeverity severity;
161  Fw::LogBuffer args;
162 
163  // Deserialize tokens for events
164  status = incoming.deserializeTo(id);
165  if (status == Fw::FW_SERIALIZE_OK) {
166  status = incoming.deserializeTo(timeTag);
167  }
168  if (status == Fw::FW_SERIALIZE_OK) {
169  status = incoming.deserializeTo(severity);
170  }
171  if (status == Fw::FW_SERIALIZE_OK) {
172  status = incoming.deserializeTo(args);
173  }
174 
175  // Send it!
176  if ((status == Fw::FW_SERIALIZE_OK) && (port < this->getNum_eventOut_OutputPorts()) &&
177  this->isConnected_eventOut_OutputPort(static_cast<FwIndexType>(port))) {
178  this->eventOut_out(static_cast<FwIndexType>(port), id, timeTag, severity, args);
179  }
180  // Deallocate the existing buffer
181  fromBufferDriverReturn_out(0, fwBuffer);
182  } else if (type == HUB_TYPE_CHANNEL) {
183  FwChanIdType id;
184  Fw::Time timeTag;
185  Fw::TlmBuffer val;
186 
187  // Deserialize tokens for channels
188  status = incoming.deserializeTo(id);
189  if (status == Fw::FW_SERIALIZE_OK) {
190  status = incoming.deserializeTo(timeTag);
191  }
192  if (status == Fw::FW_SERIALIZE_OK) {
193  status = incoming.deserializeTo(val);
194  }
195  if ((status == Fw::FW_SERIALIZE_OK) && (port < this->getNum_tlmOut_OutputPorts()) &&
196  this->isConnected_tlmOut_OutputPort(static_cast<FwIndexType>(port))) {
197  // Send it!
198  this->tlmOut_out(static_cast<FwIndexType>(port), id, timeTag, val);
199  }
200 
201  // Return the received buffer
202  fromBufferDriverReturn_out(0, fwBuffer);
203  } else if (type == HUB_TYPE_CMD_DISP) {
204  U32 context;
205  // Check that the size is sufficient for the context
206  // The wrapped command must fit the ComBuffer capacity; SERIALIZED_SIZE is the capacity
207  // plus the stored length and would admit sizes the ComBuffer cannot hold
208  if (rawSize < sizeof(U32) || (rawSize - sizeof(U32)) > FW_COM_BUFFER_MAX_SIZE) {
210  }
211  // Shift the command buffer out and deserialize the context
212  if (status == Fw::FW_SERIALIZE_OK) {
213  Fw::ComBuffer wrapper(rawData, (rawSize - sizeof(U32)));
214  status = wrapper.setBuffLen(rawSize - sizeof(U32));
215  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, static_cast<FwAssertArgType>(status));
216  // Skip the command buffer that has already been wrapped
217  status = incoming.deserializeSkip(rawSize - sizeof(U32));
218  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, static_cast<FwAssertArgType>(status));
219  status = incoming.deserializeTo(context);
220  // Send it!
221  if ((status == Fw::FW_SERIALIZE_OK) && (port < this->getNum_cmdDispOut_OutputPorts()) &&
222  this->isConnected_cmdDispOut_OutputPort(static_cast<FwIndexType>(port))) {
223  this->cmdDispOut_out(static_cast<FwIndexType>(port), wrapper, context);
224  }
225  }
226  // Deallocate the existing buffer
227  fromBufferDriverReturn_out(0, fwBuffer);
228  } else if (type == HUB_TYPE_CMD_RESP) {
229  FwOpcodeType opCode;
230  U32 cmdSeq;
231  Fw::CmdResponse response;
232 
233  // Deserialize tokens for channels
234  status = incoming.deserializeTo(opCode);
235  if (status == Fw::FW_SERIALIZE_OK) {
236  status = incoming.deserializeTo(cmdSeq);
237  }
238  if (status == Fw::FW_SERIALIZE_OK) {
239  status = incoming.deserializeTo(response);
240  }
241  // Send it!
242  if ((status == Fw::FW_SERIALIZE_OK) && (port < this->getNum_cmdRespOut_OutputPorts()) &&
243  this->isConnected_cmdRespOut_OutputPort(static_cast<FwIndexType>(port))) {
244  this->cmdRespOut_out(static_cast<FwIndexType>(port), opCode, cmdSeq, response);
245  }
246  // Return the received buffer
247  fromBufferDriverReturn_out(0, fwBuffer);
248  }
249  } else {
250  // On deserialization failure, return the buffer to avoid leaks
251  fromBufferDriverReturn_out(0, fwBuffer);
252  }
253 }
254 
255 void GenericHub::toBufferDriverReturn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) {
256  // Deallocate the existing buffer
257  deallocate_out(portNum, fwBuffer);
258 }
259 
260 void GenericHub::eventIn_handler(const FwIndexType portNum,
261  FwEventIdType id,
262  Fw::Time& timeTag,
263  const Fw::LogSeverity& severity,
264  Fw::LogBuffer& args) {
268  Fw::ExternalSerializeBuffer serializer(buffer, sizeof(buffer));
269  serializer.resetSer();
270  status = serializer.serializeFrom(id);
272  status = serializer.serializeFrom(timeTag);
274  status = serializer.serializeFrom(severity);
276  status = serializer.serializeFrom(args);
278  FwSizeType size = serializer.getSize();
279  this->send_data(HubType::HUB_TYPE_EVENT, portNum, buffer, size);
280 }
281 
282 void GenericHub::tlmIn_handler(const FwIndexType portNum, FwChanIdType id, Fw::Time& timeTag, Fw::TlmBuffer& val) {
285  Fw::ExternalSerializeBuffer serializer(buffer, sizeof(buffer));
286  serializer.resetSer();
287  status = serializer.serializeFrom(id);
289  status = serializer.serializeFrom(timeTag);
291  status = serializer.serializeFrom(val);
293  FwSizeType size = serializer.getSize();
294  this->send_data(HubType::HUB_TYPE_CHANNEL, portNum, buffer, size);
295 }
296 
297 // ----------------------------------------------------------------------
298 // Handler implementations for user-defined serial input ports
299 // ----------------------------------------------------------------------
300 
301 void GenericHub::serialIn_handler(FwIndexType portNum,
302  Fw::LinearBufferBase& Buffer
303 ) {
304  send_data(HUB_TYPE_PORT, portNum, Buffer.getBuffAddr(), Buffer.getSize());
305 }
306 
307 } // end namespace Svc
Serialization/Deserialization operation was successful.
FwIdType FwOpcodeType
The type of a command opcode.
void set(U8 *data, FwSizeType size, U32 context=NO_CONTEXT)
Definition: Buffer.cpp:144
PlatformSizeType FwSizeType
void setSize(FwSizeType size)
Definition: Buffer.cpp:131
Serializable::SizeType getSize() const override
Get current buffer size.
SerializeStatus deserializeTo(U8 &val, Endianness mode=Endianness::BIG) override
Deserialize an 8-bit unsigned integer value.
Fw::SerializeStatus serialize(Fw::SerialBufferBase &serializer, FwSizeType size)
Serialize an idle packet of exactly size bytes (header and idle data) into serializer ...
Definition: IdlePacket.cpp:16
Command response type.
Definition: GenericHub.hpp:33
U32 getContext() const
Definition: Buffer.cpp:102
U8 * getData() const
Definition: Buffer.cpp:82
FwSizeStoreType FwBuffSizeType
Enum representing a command response.
SerializeStatus
forward declaration for string
ExternalSerializeBufferWithMemberCopy getDeserializer()
Definition: Buffer.cpp:165
FwIdType FwEventIdType
The type of an event identifier.
Data failed validation.
Buffer type transmission.
Definition: GenericHub.hpp:29
U8 * getBuffAddr()
Get buffer address for data filling (non-const version)
Omit length from serialization.
The size of the serial representation.
Data was left in the buffer, but not enough to deserialize.
External serialize buffer with no copy semantics.
FwIdType FwChanIdType
The type of a telemetry channel identifier.
FwSizeType FwSizeStoreType
Enum representing event severity.
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:54
FwSizeType getSize() const
Definition: Buffer.cpp:90
PlatformIndexType FwIndexType
Telemetry channel type.
Definition: GenericHub.hpp:31
Port type transmission.
Definition: GenericHub.hpp:28
RateGroupDivider component implementation.
Command dispatch type.
Definition: GenericHub.hpp:32
GenericHub(const char *const compName)
Definition: GenericHub.cpp:27
Event transmission.
Definition: GenericHub.hpp:30
ExternalSerializeBufferWithMemberCopy getSerializer()
Definition: Buffer.cpp:155
#define FW_ASSERT(...)
Definition: Assert.hpp:14
#define FW_PORT_SERIALIZATION
calls for multi-note systems)
Definition: FpConfig.h:83
The size of the serial representation.