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.
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 serializeFrom(U8 val, Endianness mode=Endianness::BIG) override
Serialize an 8-bit unsigned integer value.
SerializeStatus
forward declaration for string
The size of the serial representation.
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.
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.
Enum representing event severity.
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:54
FwSizeType getSize() const
Definition: Buffer.cpp:90
The size of the serial representation.
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