libuav original
Dependents: UAVCAN UAVCAN_Subscriber
dispatcher.hpp
00001 /* 00002 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com> 00003 */ 00004 00005 #ifndef UAVCAN_TRANSPORT_DISPATCHER_HPP_INCLUDED 00006 #define UAVCAN_TRANSPORT_DISPATCHER_HPP_INCLUDED 00007 00008 #include <cassert> 00009 #include <uavcan/error.hpp> 00010 #include <uavcan/std.hpp> 00011 #include <uavcan/build_config.hpp> 00012 #include <uavcan/transport/perf_counter.hpp> 00013 #include <uavcan/transport/transfer_listener.hpp> 00014 #include <uavcan/transport/outgoing_transfer_registry.hpp> 00015 #include <uavcan/transport/can_io.hpp> 00016 #include <uavcan/util/linked_list.hpp> 00017 00018 namespace uavcan 00019 { 00020 00021 class UAVCAN_EXPORT Dispatcher; 00022 00023 #if !UAVCAN_TINY 00024 /** 00025 * Inherit this class to receive notifications about all TX CAN frames that were transmitted with the loopback flag. 00026 */ 00027 class UAVCAN_EXPORT LoopbackFrameListenerBase : public LinkedListNode<LoopbackFrameListenerBase> 00028 { 00029 Dispatcher& dispatcher_; 00030 00031 protected: 00032 explicit LoopbackFrameListenerBase(Dispatcher& dispatcher) 00033 : dispatcher_(dispatcher) 00034 { } 00035 00036 virtual ~LoopbackFrameListenerBase() { stopListening(); } 00037 00038 void startListening(); 00039 void stopListening(); 00040 bool isListening() const; 00041 00042 Dispatcher& getDispatcher() { return dispatcher_; } 00043 00044 public: 00045 virtual void handleLoopbackFrame(const RxFrame& frame) = 0; 00046 }; 00047 00048 00049 class UAVCAN_EXPORT LoopbackFrameListenerRegistry : Noncopyable 00050 { 00051 LinkedListRoot<LoopbackFrameListenerBase> listeners_; 00052 00053 public: 00054 void add(LoopbackFrameListenerBase* listener); 00055 void remove(LoopbackFrameListenerBase* listener); 00056 bool doesExist(const LoopbackFrameListenerBase* listener) const; 00057 unsigned getNumListeners() const { return listeners_.getLength(); } 00058 00059 void invokeListeners(RxFrame& frame); 00060 }; 00061 00062 /** 00063 * Implement this interface to receive notifications about all incoming CAN frames, including loopback. 00064 */ 00065 class UAVCAN_EXPORT IRxFrameListener 00066 { 00067 public: 00068 virtual ~IRxFrameListener() { } 00069 00070 /** 00071 * Make sure to filter out loopback frames if they are not wanted. 00072 */ 00073 virtual void handleRxFrame(const CanRxFrame& frame, CanIOFlags flags) = 0; 00074 }; 00075 #endif 00076 00077 /** 00078 * This class performs low-level CAN frame routing. 00079 */ 00080 class UAVCAN_EXPORT Dispatcher : Noncopyable 00081 { 00082 CanIOManager canio_; 00083 ISystemClock& sysclock_; 00084 OutgoingTransferRegistry outgoing_transfer_reg_; 00085 TransferPerfCounter perf_; 00086 00087 class ListenerRegistry 00088 { 00089 LinkedListRoot<TransferListener> list_; 00090 00091 class DataTypeIDInsertionComparator 00092 { 00093 const DataTypeID id_; 00094 public: 00095 explicit DataTypeIDInsertionComparator(DataTypeID id) : id_(id) { } 00096 bool operator()(const TransferListener* listener) const 00097 { 00098 UAVCAN_ASSERT(listener); 00099 return id_ > listener->getDataTypeDescriptor().getID(); 00100 } 00101 }; 00102 00103 public: 00104 enum Mode { UniqueListener, ManyListeners }; 00105 00106 bool add(TransferListener* listener, Mode mode); 00107 void remove(TransferListener* listener); 00108 bool exists(DataTypeID dtid) const; 00109 void cleanup(MonotonicTime ts); 00110 void handleFrame(const RxFrame& frame); 00111 00112 unsigned getNumEntries() const { return list_.getLength(); } 00113 00114 const LinkedListRoot<TransferListener> & getList() const { return list_; } 00115 }; 00116 00117 ListenerRegistry lmsg_; 00118 ListenerRegistry lsrv_req_; 00119 ListenerRegistry lsrv_resp_; 00120 00121 #if !UAVCAN_TINY 00122 LoopbackFrameListenerRegistry loopback_listeners_; 00123 IRxFrameListener* rx_listener_; 00124 #endif 00125 00126 NodeID self_node_id_; 00127 bool self_node_id_is_set_; 00128 00129 void handleFrame(const CanRxFrame& can_frame); 00130 00131 void handleLoopbackFrame(const CanRxFrame& can_frame); 00132 00133 void notifyRxFrameListener(const CanRxFrame& can_frame, CanIOFlags flags); 00134 00135 public: 00136 Dispatcher(ICanDriver& driver, IPoolAllocator& allocator, ISystemClock& sysclock) 00137 : canio_(driver, allocator, sysclock) 00138 , sysclock_(sysclock) 00139 , outgoing_transfer_reg_(allocator) 00140 #if !UAVCAN_TINY 00141 , rx_listener_(UAVCAN_NULLPTR) 00142 #endif 00143 , self_node_id_(NodeID::Broadcast) // Default 00144 , self_node_id_is_set_(false) 00145 { } 00146 00147 /** 00148 * This version returns strictly when the deadline is reached. 00149 */ 00150 int spin(MonotonicTime deadline); 00151 00152 /** 00153 * This version does not return until all available frames are processed. 00154 */ 00155 int spinOnce(); 00156 00157 /** 00158 * Refer to CanIOManager::send() for the parameter description 00159 */ 00160 int send(const Frame& frame, MonotonicTime tx_deadline, MonotonicTime blocking_deadline, CanTxQueue::Qos qos, 00161 CanIOFlags flags, uint8_t iface_mask); 00162 00163 void cleanup(MonotonicTime ts); 00164 00165 bool registerMessageListener(TransferListener* listener); 00166 bool registerServiceRequestListener(TransferListener* listener); 00167 bool registerServiceResponseListener(TransferListener* listener); 00168 00169 void unregisterMessageListener(TransferListener* listener); 00170 void unregisterServiceRequestListener(TransferListener* listener); 00171 void unregisterServiceResponseListener(TransferListener* listener); 00172 00173 bool hasSubscriber(DataTypeID dtid) const; 00174 bool hasPublisher(DataTypeID dtid) const; 00175 bool hasServer(DataTypeID dtid) const; 00176 00177 unsigned getNumMessageListeners() const { return lmsg_.getNumEntries(); } 00178 unsigned getNumServiceRequestListeners() const { return lsrv_req_.getNumEntries(); } 00179 unsigned getNumServiceResponseListeners() const { return lsrv_resp_.getNumEntries(); } 00180 00181 /** 00182 * These methods can be used to retreive lists of messages, service requests and service responses the 00183 * dispatcher is currently listening to. 00184 * Note that the list of service response listeners is very volatile, because a response listener will be 00185 * removed from this list as soon as the corresponding service call is complete. 00186 * @{ 00187 */ 00188 const LinkedListRoot<TransferListener> & getListOfMessageListeners() const 00189 { 00190 return lmsg_.getList(); 00191 } 00192 const LinkedListRoot<TransferListener> & getListOfServiceRequestListeners() const 00193 { 00194 return lsrv_req_.getList(); 00195 } 00196 const LinkedListRoot<TransferListener>& getListOfServiceResponseListeners() const 00197 { 00198 return lsrv_resp_.getList(); 00199 } 00200 /** 00201 * @} 00202 */ 00203 00204 OutgoingTransferRegistry& getOutgoingTransferRegistry() { return outgoing_transfer_reg_; } 00205 00206 #if !UAVCAN_TINY 00207 LoopbackFrameListenerRegistry& getLoopbackFrameListenerRegistry() { return loopback_listeners_; } 00208 00209 IRxFrameListener* getRxFrameListener() const { return rx_listener_; } 00210 void removeRxFrameListener() { rx_listener_ = UAVCAN_NULLPTR; } 00211 void installRxFrameListener(IRxFrameListener* listener) 00212 { 00213 UAVCAN_ASSERT(listener != UAVCAN_NULLPTR); 00214 rx_listener_ = listener; 00215 } 00216 #endif 00217 00218 /** 00219 * Node ID can be set only once. 00220 * Non-unicast Node ID puts the node into passive mode. 00221 */ 00222 NodeID getNodeID() const { return self_node_id_; } 00223 bool setNodeID(NodeID nid); 00224 00225 /** 00226 * Refer to the specs to learn more about passive mode. 00227 */ 00228 bool isPassiveMode() const { return !getNodeID().isUnicast(); } 00229 00230 const ISystemClock& getSystemClock() const { return sysclock_; } 00231 ISystemClock& getSystemClock() { return sysclock_; } 00232 00233 const CanIOManager& getCanIOManager() const { return canio_; } 00234 CanIOManager& getCanIOManager() { return canio_; } 00235 00236 const TransferPerfCounter& getTransferPerfCounter() const { return perf_; } 00237 TransferPerfCounter& getTransferPerfCounter() { return perf_; } 00238 }; 00239 00240 } 00241 00242 #endif // UAVCAN_TRANSPORT_DISPATCHER_HPP_INCLUDED
Generated on Tue Jul 12 2022 17:17:31 by 1.7.2