uc_dispatcher.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
3  */
4 
6 #include <uavcan/debug.hpp>
7 #include <cassert>
8 
9 namespace uavcan
10 {
11 #if !UAVCAN_TINY
12 /*
13  * LoopbackFrameListenerBase
14  */
16 {
18 }
19 
21 {
23 }
24 
26 {
28 }
29 
30 /*
31  * LoopbackFrameListenerRegistry
32  */
34 {
35  UAVCAN_ASSERT(listener);
36  listeners_.insert(listener);
37 }
38 
40 {
41  UAVCAN_ASSERT(listener);
42  listeners_.remove(listener);
43 }
44 
46 {
47  UAVCAN_ASSERT(listener);
48  const LoopbackFrameListenerBase* p = listeners_.get();
49  while (p)
50  {
51  if (p == listener)
52  {
53  return true;
54  }
55  p = p->getNextListNode();
56  }
57  return false;
58 }
59 
61 {
63  while (p)
64  {
65  LoopbackFrameListenerBase* const next = p->getNextListNode();
66  p->handleLoopbackFrame(frame); // p may be modified
67  p = next;
68  }
69 }
70 #endif
71 
72 /*
73  * Dispatcher::ListenerRegister
74  */
76 {
77  if (mode == UniqueListener)
78  {
79  TransferListener* p = list_.get();
80  while (p)
81  {
82  if (p->getDataTypeDescriptor().getID() == listener->getDataTypeDescriptor().getID())
83  {
84  return false;
85  }
86  p = p->getNextListNode();
87  }
88  }
89  // Objective is to arrange entries by Data Type ID in ascending order from root.
90  list_.insertBefore(listener, DataTypeIDInsertionComparator(listener->getDataTypeDescriptor().getID()));
91  return true;
92 }
93 
95 {
96  list_.remove(listener);
97 }
98 
100 {
101  TransferListener* p = list_.get();
102  while (p)
103  {
104  if (p->getDataTypeDescriptor().getID() == dtid)
105  {
106  return true;
107  }
108  p = p->getNextListNode();
109  }
110  return false;
111 }
112 
114 {
115  TransferListener* p = list_.get();
116  while (p)
117  {
118  TransferListener* const next = p->getNextListNode();
119  p->cleanup(ts); // p may be modified
120  p = next;
121  }
122 }
123 
125 {
126  TransferListener* p = list_.get();
127  while (p)
128  {
129  TransferListener* const next = p->getNextListNode();
130  if (p->getDataTypeDescriptor().getID() == frame.getDataTypeID())
131  {
132  p->handleFrame(frame); // p may be modified
133  }
134  else if (p->getDataTypeDescriptor().getID() < frame.getDataTypeID()) // Listeners are ordered by data type id!
135  {
136  break;
137  }
138  else
139  {
140  ; // Nothing to do with this one
141  }
142  p = next;
143  }
144 }
145 
146 /*
147  * Dispatcher
148  */
149 void Dispatcher::handleFrame(const CanRxFrame& can_frame)
150 {
151  RxFrame frame;
152  if (!frame.parse(can_frame))
153  {
154  // This is not counted as a transport error
155  UAVCAN_TRACE("Dispatcher", "Invalid CAN frame received: %s", can_frame.toString().c_str());
156  return;
157  }
158 
159  if ((frame.getDstNodeID() != NodeID::Broadcast) &&
160  (frame.getDstNodeID() != getNodeID()))
161  {
162  return;
163  }
164 
165  switch (frame.getTransferType())
166  {
168  {
170  break;
171  }
173  {
175  break;
176  }
178  {
180  break;
181  }
182  default:
183  {
184  UAVCAN_ASSERT(0);
185  break;
186  }
187  }
188 }
189 
190 #if UAVCAN_TINY
192 {
193 }
194 
195 void Dispatcher::notifyRxFrameListener(const CanRxFrame&, CanIOFlags)
196 {
197 }
198 #else
200 {
201  RxFrame frame;
202  if (!frame.parse(can_frame))
203  {
204  UAVCAN_TRACE("Dispatcher", "Invalid loopback CAN frame: %s", can_frame.toString().c_str());
205  UAVCAN_ASSERT(0); // No way!
206  return;
207  }
208  UAVCAN_ASSERT(frame.getSrcNodeID() == getNodeID());
210 }
211 
213 {
215  {
216  rx_listener_->handleRxFrame(can_frame, flags);
217  }
218 }
219 #endif
220 
222 {
223  int num_frames_processed = 0;
224  do
225  {
226  CanIOFlags flags = 0;
228  const int res = canio_.receive(frame, deadline, flags);
229  if (res < 0)
230  {
231  return res;
232  }
233  if (res > 0)
234  {
235  if (flags & CanIOFlagLoopback)
236  {
238  }
239  else
240  {
241  num_frames_processed++;
243  }
245  }
246  }
247  while (sysclock_.getMonotonic() < deadline);
248 
249  return num_frames_processed;
250 }
251 
253 {
254  int num_frames_processed = 0;
255 
256  while (true)
257  {
258  CanIOFlags flags = 0;
260  const int res = canio_.receive(frame, MonotonicTime(), flags);
261  if (res < 0)
262  {
263  return res;
264  }
265  else if (res > 0)
266  {
267  if (flags & CanIOFlagLoopback)
268  {
270  }
271  else
272  {
273  num_frames_processed++;
275  }
277  }
278  else
279  {
280  break; // No frames left
281  }
282  }
283 
284  return num_frames_processed;
285 }
286 
287 int Dispatcher::send(const Frame& frame, MonotonicTime tx_deadline, MonotonicTime blocking_deadline,
288  CanIOFlags flags, uint8_t iface_mask)
289 {
290  if (frame.getSrcNodeID() != getNodeID())
291  {
292  UAVCAN_ASSERT(0);
293  return -ErrLogic;
294  }
295 
296  CanFrame can_frame;
297  if (!frame.compile(can_frame))
298  {
299  UAVCAN_TRACE("Dispatcher", "Unable to send: frame is malformed: %s", frame.toString().c_str());
300  UAVCAN_ASSERT(0);
301  return -ErrLogic;
302  }
303  return canio_.send(can_frame, tx_deadline, blocking_deadline, iface_mask, flags);
304 }
305 
307 {
309  lmsg_.cleanup(ts);
310  lsrv_req_.cleanup(ts);
311  lsrv_resp_.cleanup(ts);
312 }
313 
315 {
317  {
318  UAVCAN_ASSERT(0);
319  return false;
320  }
321  return lmsg_.add(listener, ListenerRegistry::ManyListeners); // Multiple subscribers are OK
322 }
323 
325 {
327  {
328  UAVCAN_ASSERT(0);
329  return false;
330  }
331  return lsrv_req_.add(listener, ListenerRegistry::UniqueListener); // Only one server per data type
332 }
333 
335 {
337  {
338  UAVCAN_ASSERT(0);
339  return false;
340  }
341  return lsrv_resp_.add(listener, ListenerRegistry::ManyListeners); // Multiple callers may call same srv
342 }
343 
345 {
346  lmsg_.remove(listener);
347 }
348 
350 {
351  lsrv_req_.remove(listener);
352 }
353 
355 {
356  lsrv_resp_.remove(listener);
357 }
358 
360 {
361  return lmsg_.exists(dtid);
362 }
363 
365 {
367 }
368 
370 {
371  return lsrv_req_.exists(dtid);
372 }
373 
375 {
377  {
378  self_node_id_ = nid;
379  self_node_id_is_set_ = true;
380  return true;
381  }
382  return false;
383 }
384 
385 }
uavcan::Dispatcher::registerServiceResponseListener
bool registerServiceResponseListener(TransferListener *listener)
Definition: uc_dispatcher.cpp:334
uavcan::LoopbackFrameListenerBase::startListening
void startListening()
Definition: uc_dispatcher.cpp:15
uavcan::Dispatcher::sysclock_
ISystemClock & sysclock_
Definition: dispatcher.hpp:83
uavcan::LoopbackFrameListenerRegistry::listeners_
LinkedListRoot< LoopbackFrameListenerBase > listeners_
Definition: dispatcher.hpp:51
uavcan::TransferListener::getDataTypeDescriptor
const DataTypeDescriptor & getDataTypeDescriptor() const
Definition: transfer_listener.hpp:143
uavcan::Dispatcher::lsrv_resp_
ListenerRegistry lsrv_resp_
Definition: dispatcher.hpp:119
UAVCAN_NULLPTR
#define UAVCAN_NULLPTR
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:51
uavcan::Dispatcher::ListenerRegistry::cleanup
void cleanup(MonotonicTime ts)
Definition: uc_dispatcher.cpp:113
uavcan::Dispatcher::canio_
CanIOManager canio_
Definition: dispatcher.hpp:82
uavcan::LoopbackFrameListenerRegistry::add
void add(LoopbackFrameListenerBase *listener)
Definition: uc_dispatcher.cpp:33
uavcan::LoopbackFrameListenerBase::dispatcher_
Dispatcher & dispatcher_
Definition: dispatcher.hpp:29
uavcan::LoopbackFrameListenerBase::stopListening
void stopListening()
Definition: uc_dispatcher.cpp:20
debug.hpp
uavcan::DataTypeKindService
@ DataTypeKindService
Definition: data_type.hpp:21
uavcan::Dispatcher::registerMessageListener
bool registerMessageListener(TransferListener *listener)
Definition: uc_dispatcher.cpp:314
uavcan::Dispatcher::lmsg_
ListenerRegistry lmsg_
Definition: dispatcher.hpp:117
uavcan::LoopbackFrameListenerBase::isListening
bool isListening() const
Definition: uc_dispatcher.cpp:25
uavcan::Dispatcher::ListenerRegistry::Mode
Mode
Definition: dispatcher.hpp:104
uavcan::TransferTypeServiceResponse
@ TransferTypeServiceResponse
Definition: transfer.hpp:20
uavcan::NodeID
Definition: transfer.hpp:112
uavcan::Dispatcher::setNodeID
bool setNodeID(NodeID nid)
Definition: uc_dispatcher.cpp:374
uavcan::Dispatcher::handleFrame
void handleFrame(const CanRxFrame &can_frame)
Definition: uc_dispatcher.cpp:149
uavcan::Dispatcher::ListenerRegistry::list_
LinkedListRoot< TransferListener > list_
Definition: dispatcher.hpp:89
uavcan::CanFrame
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:24
uavcan::CanIOFlagLoopback
static const CanIOFlags CanIOFlagLoopback
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:141
UAVCAN_TRACE
#define UAVCAN_TRACE(...)
Definition: libuavcan/libuavcan/include/uavcan/debug.hpp:31
uavcan::CanRxFrame
Definition: can_io.hpp:25
uavcan::TransferTypeServiceRequest
@ TransferTypeServiceRequest
Definition: transfer.hpp:21
uavcan::Dispatcher::ListenerRegistry::handleFrame
void handleFrame(const RxFrame &frame)
Definition: uc_dispatcher.cpp:124
uavcan::Dispatcher::spinOnce
int spinOnce()
Definition: uc_dispatcher.cpp:252
uavcan::Dispatcher::ListenerRegistry::DataTypeIDInsertionComparator
Definition: dispatcher.hpp:91
uavcan::Dispatcher::ListenerRegistry::UniqueListener
@ UniqueListener
Definition: dispatcher.hpp:104
uavcan::Dispatcher::self_node_id_
NodeID self_node_id_
Definition: dispatcher.hpp:126
uavcan::TransferListener::cleanup
void cleanup(MonotonicTime ts)
Definition: uc_transfer_listener.cpp:196
uavcan::Dispatcher::loopback_listeners_
LoopbackFrameListenerRegistry loopback_listeners_
Definition: dispatcher.hpp:122
uavcan::Dispatcher::rx_listener_
IRxFrameListener * rx_listener_
Definition: dispatcher.hpp:123
dispatcher.hpp
uavcan::Dispatcher::handleLoopbackFrame
void handleLoopbackFrame(const CanRxFrame &can_frame)
Definition: uc_dispatcher.cpp:199
uavcan::LoopbackFrameListenerBase
Definition: dispatcher.hpp:27
uavcan::Dispatcher::spin
int spin(MonotonicTime deadline)
Definition: uc_dispatcher.cpp:221
uavcan_kinetis::ErrLogic
static const uavcan::int16_t ErrLogic
Internal logic error.
Definition: platform_specific_components/kinetis/libuavcan/driver/include/uavcan_kinetis/can.hpp:22
uavcan::Dispatcher::hasPublisher
bool hasPublisher(DataTypeID dtid) const
Definition: uc_dispatcher.cpp:364
uavcan::uint8_t
std::uint8_t uint8_t
Definition: std.hpp:24
uavcan::DataTypeID
Definition: data_type.hpp:47
uavcan::TransferTypeMessageBroadcast
@ TransferTypeMessageBroadcast
Definition: transfer.hpp:22
uavcan::RxFrame
Definition: frame.hpp:104
uavcan::CanIOManager::send
int send(const CanFrame &frame, MonotonicTime tx_deadline, MonotonicTime blocking_deadline, uint8_t iface_mask, CanIOFlags flags)
Definition: uc_can_io.cpp:297
uavcan::Dispatcher::cleanup
void cleanup(MonotonicTime ts)
Definition: uc_dispatcher.cpp:306
uavcan::Dispatcher::ListenerRegistry::remove
void remove(TransferListener *listener)
Definition: uc_dispatcher.cpp:94
uavcan::Dispatcher::self_node_id_is_set_
bool self_node_id_is_set_
Definition: dispatcher.hpp:127
uavcan::LoopbackFrameListenerBase::handleLoopbackFrame
virtual void handleLoopbackFrame(const RxFrame &frame)=0
uavcan::LoopbackFrameListenerRegistry::doesExist
bool doesExist(const LoopbackFrameListenerBase *listener) const
Definition: uc_dispatcher.cpp:45
uavcan::Dispatcher::hasSubscriber
bool hasSubscriber(DataTypeID dtid) const
Definition: uc_dispatcher.cpp:359
uavcan::OutgoingTransferRegistry::exists
bool exists(DataTypeID dtid, TransferType tt) const
Definition: uc_outgoing_transfer_registry.cpp:45
uavcan::Dispatcher::unregisterServiceRequestListener
void unregisterServiceRequestListener(TransferListener *listener)
Definition: uc_dispatcher.cpp:349
uavcan::NodeID::Broadcast
static const NodeID Broadcast
Definition: transfer.hpp:122
uavcan::Dispatcher::lsrv_req_
ListenerRegistry lsrv_req_
Definition: dispatcher.hpp:118
uavcan::CanIOManager::receive
int receive(CanRxFrame &out_frame, MonotonicTime blocking_deadline, CanIOFlags &out_flags)
Definition: uc_can_io.cpp:412
uavcan::TransferListener
Definition: transfer_listener.hpp:99
uavcan::Dispatcher::ListenerRegistry::add
bool add(TransferListener *listener, Mode mode)
Definition: uc_dispatcher.cpp:75
frame
uavcan::CanFrame frame
Definition: can.cpp:78
uavcan::IRxFrameListener::handleRxFrame
virtual void handleRxFrame(const CanRxFrame &frame, CanIOFlags flags)=0
uavcan::Dispatcher::notifyRxFrameListener
void notifyRxFrameListener(const CanRxFrame &can_frame, CanIOFlags flags)
Definition: uc_dispatcher.cpp:212
uavcan::Dispatcher::outgoing_transfer_reg_
OutgoingTransferRegistry outgoing_transfer_reg_
Definition: dispatcher.hpp:84
uavcan::Dispatcher::send
int send(const Frame &frame, MonotonicTime tx_deadline, MonotonicTime blocking_deadline, CanIOFlags flags, uint8_t iface_mask)
Definition: uc_dispatcher.cpp:287
uavcan::LoopbackFrameListenerRegistry::invokeListeners
void invokeListeners(RxFrame &frame)
Definition: uc_dispatcher.cpp:60
uavcan::TransferListener::handleFrame
virtual void handleFrame(const RxFrame &frame)
Definition: uc_transfer_listener.cpp:202
uavcan::Frame
Definition: frame.hpp:17
uavcan::Dispatcher::registerServiceRequestListener
bool registerServiceRequestListener(TransferListener *listener)
Definition: uc_dispatcher.cpp:324
uavcan::Dispatcher::getLoopbackFrameListenerRegistry
LoopbackFrameListenerRegistry & getLoopbackFrameListenerRegistry()
Definition: dispatcher.hpp:207
uavcan::Dispatcher::getNodeID
NodeID getNodeID() const
Definition: dispatcher.hpp:222
uavcan::Dispatcher::ListenerRegistry::exists
bool exists(DataTypeID dtid) const
Definition: uc_dispatcher.cpp:99
uavcan::Dispatcher::ListenerRegistry::ManyListeners
@ ManyListeners
Definition: dispatcher.hpp:104
uavcan::DataTypeDescriptor::getID
DataTypeID getID() const
Definition: data_type.hpp:159
uavcan::CanIOFlags
uint16_t CanIOFlags
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:140
uavcan::MonotonicTime
Definition: time.hpp:184
uavcan::LinkedListNode::getNextListNode
T * getNextListNode() const
Definition: linked_list.hpp:32
uavcan::LoopbackFrameListenerRegistry::remove
void remove(LoopbackFrameListenerBase *listener)
Definition: uc_dispatcher.cpp:39
uavcan
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:204
uavcan::DataTypeKindMessage
@ DataTypeKindMessage
Definition: data_type.hpp:22
uavcan::Dispatcher::hasServer
bool hasServer(DataTypeID dtid) const
Definition: uc_dispatcher.cpp:369
uavcan::OutgoingTransferRegistry::cleanup
void cleanup(MonotonicTime ts)
Definition: uc_outgoing_transfer_registry.cpp:50
uavcan::ISystemClock::getMonotonic
virtual MonotonicTime getMonotonic() const =0
uavcan::Dispatcher::unregisterServiceResponseListener
void unregisterServiceResponseListener(TransferListener *listener)
Definition: uc_dispatcher.cpp:354
uavcan::Dispatcher::unregisterMessageListener
void unregisterMessageListener(TransferListener *listener)
Definition: uc_dispatcher.cpp:344
UAVCAN_ASSERT
#define UAVCAN_ASSERT(x)
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:184
uavcan::DataTypeDescriptor::getKind
DataTypeKind getKind() const
Definition: data_type.hpp:158


uavcan_communicator
Author(s):
autogenerated on Fri Dec 13 2024 03:10:03