PX4 Firmware
PX4 Autopilot Software http://px4.io
uORBDeviceNode.hpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2012-2016 PX4 Development Team. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name PX4 nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
34 #pragma once
35 
36 #include "uORBCommon.hpp"
37 #include "uORBDeviceMaster.hpp"
38 
39 #include <lib/cdev/CDev.hpp>
40 
41 #include <containers/List.hpp>
42 #include <px4_platform_common/atomic.h>
43 
44 namespace uORB
45 {
46 class DeviceNode;
47 class DeviceMaster;
48 class Manager;
49 class SubscriptionCallback;
50 }
51 
52 /**
53  * Per-object device instance.
54  */
55 class uORB::DeviceNode : public cdev::CDev, public ListNode<uORB::DeviceNode *>
56 {
57 public:
58  DeviceNode(const struct orb_metadata *meta, const uint8_t instance, const char *path, uint8_t priority,
59  uint8_t queue_size = 1);
60  virtual ~DeviceNode();
61 
62  // no copy, assignment, move, move assignment
63  DeviceNode(const DeviceNode &) = delete;
64  DeviceNode &operator=(const DeviceNode &) = delete;
65  DeviceNode(DeviceNode &&) = delete;
66  DeviceNode &operator=(DeviceNode &&) = delete;
67 
68  /**
69  * Method to create a subscriber instance and return the struct
70  * pointing to the subscriber as a file pointer.
71  */
72  int open(cdev::file_t *filp) override;
73 
74  /**
75  * Method to close a subscriber for this topic.
76  */
77  int close(cdev::file_t *filp) override;
78 
79  /**
80  * reads data from a subscriber node to the buffer provided.
81  * @param filp
82  * The subscriber from which the data needs to be read from.
83  * @param buffer
84  * The buffer into which the data is read into.
85  * @param buflen
86  * the length of the buffer
87  * @return
88  * ssize_t the number of bytes read.
89  */
90  ssize_t read(cdev::file_t *filp, char *buffer, size_t buflen) override;
91 
92  /**
93  * writes the published data to the internal buffer to be read by
94  * subscribers later.
95  * @param filp
96  * the subscriber; this is not used.
97  * @param buffer
98  * The buffer for the input data
99  * @param buflen
100  * the length of the buffer.
101  * @return ssize_t
102  * The number of bytes that are written
103  */
104  ssize_t write(cdev::file_t *filp, const char *buffer, size_t buflen) override;
105 
106  /**
107  * IOCTL control for the subscriber.
108  */
109  int ioctl(cdev::file_t *filp, int cmd, unsigned long arg) override;
110 
111  /**
112  * Method to publish a data to this node.
113  */
114  static ssize_t publish(const orb_metadata *meta, orb_advert_t handle, const void *data);
115 
116  static int unadvertise(orb_advert_t handle);
117 
118 #ifdef ORB_COMMUNICATOR
119  static int16_t topic_advertised(const orb_metadata *meta, int priority);
120  //static int16_t topic_unadvertised(const orb_metadata *meta, int priority);
121 
122  /**
123  * processes a request for add subscription from remote
124  * @param rateInHz
125  * Specifies the desired rate for the message.
126  * @return
127  * 0 = success
128  * otherwise failure.
129  */
130  int16_t process_add_subscription(int32_t rateInHz);
131 
132  /**
133  * processes a request to remove a subscription from remote.
134  */
135  int16_t process_remove_subscription();
136 
137  /**
138  * processed the received data message from remote.
139  */
140  int16_t process_received_message(int32_t length, uint8_t *data);
141 #endif /* ORB_COMMUNICATOR */
142 
143  /**
144  * Add the subscriber to the node's list of subscriber. If there is
145  * remote proxy to which this subscription needs to be sent, it will
146  * done via uORBCommunicator::IChannel interface.
147  * @param sd
148  * the subscriber to be added.
149  */
151 
152  /**
153  * Removes the subscriber from the list. Also notifies the remote
154  * if there a uORBCommunicator::IChannel instance.
155  * @param sd
156  * the Subscriber to be removed.
157  */
159 
160  /**
161  * Return true if this topic has been advertised.
162  *
163  * This is used in the case of multi_pub/sub to check if it's valid to advertise
164  * and publish to this node or if another node should be tried. */
165  bool is_advertised() const { return _advertised; }
166 
167  void mark_as_advertised() { _advertised = true; }
168 
169  /**
170  * Try to change the size of the queue. This can only be done as long as nobody published yet.
171  * This is the case, for example when orb_subscribe was called before an orb_advertise.
172  * The queue size can only be increased.
173  * @param queue_size new size of the queue
174  * @return PX4_OK if queue size successfully set
175  */
176  int update_queue_size(unsigned int queue_size);
177 
178  /**
179  * Print statistics (nr of lost messages)
180  * @param reset if true, reset statistics afterwards
181  * @return true if printed something, false otherwise (if no lost messages)
182  */
183  bool print_statistics(bool reset);
184 
185  uint8_t get_queue_size() const { return _queue_size; }
186 
187  int8_t subscriber_count() const { return _subscriber_count; }
188 
189  uint32_t lost_message_count() const { return _lost_messages; }
190 
191  unsigned published_message_count() const { return _generation.load(); }
192 
193  const orb_metadata *get_meta() const { return _meta; }
194 
195  const char *get_name() const { return _meta->o_name; }
196 
197  uint8_t get_instance() const { return _instance; }
198 
199  int get_priority() const { return _priority; }
200  void set_priority(uint8_t priority) { _priority = priority; }
201 
202  /**
203  * Copies data and the corresponding generation
204  * from a node to the buffer provided.
205  *
206  * @param dst
207  * The buffer into which the data is copied.
208  * @param generation
209  * The generation that was copied.
210  * @return bool
211  * Returns true if the data was copied.
212  */
213  bool copy(void *dst, unsigned &generation);
214 
215  /**
216  * Copies data and the corresponding generation
217  * from a node to the buffer provided.
218  *
219  * @param dst
220  * The buffer into which the data is copied.
221  * If topic was not updated since last check it will return false but
222  * still copy the data.
223  * @param generation
224  * The generation that was copied.
225  * @return uint64_t
226  * Returns the timestamp of the copied data.
227  */
228  uint64_t copy_and_get_timestamp(void *dst, unsigned &generation);
229 
230  // add item to list of work items to schedule on node update
231  bool register_callback(SubscriptionCallback *callback_sub);
232 
233  // remove item from list of work items
234  void unregister_callback(SubscriptionCallback *callback_sub);
235 
236 protected:
237 
238  pollevent_t poll_state(cdev::file_t *filp) override;
239 
240  void poll_notify_one(px4_pollfd_struct_t *fds, pollevent_t events) override;
241 
242 private:
243 
244  /**
245  * Copies data and the corresponding generation
246  * from a node to the buffer provided. Caller handles locking.
247  *
248  * @param dst
249  * The buffer into which the data is copied.
250  * @param generation
251  * The generation that was copied.
252  * @return bool
253  * Returns true if the data was copied.
254  */
255  bool copy_locked(void *dst, unsigned &generation);
256 
258  uint64_t last_update{0}; /**< time at which the last update was provided, used when update_interval is nonzero */
259  unsigned interval{0}; /**< if nonzero minimum interval between updates */
260  };
261 
262  struct SubscriberData {
264 
265  unsigned generation{0}; /**< last generation the subscriber has seen */
266  UpdateIntervalData *update_interval{nullptr}; /**< if null, no update interval */
267  };
268 
269  const orb_metadata *_meta; /**< object metadata information */
270  const uint8_t _instance; /**< orb multi instance identifier */
271  uint8_t *_data{nullptr}; /**< allocated object buffer */
272  hrt_abstime _last_update{0}; /**< time the object was last updated */
273  px4::atomic<unsigned> _generation{0}; /**< object generation count */
275  uint8_t _priority; /**< priority of the topic */
276  bool _advertised{false}; /**< has ever been advertised (not necessarily published data yet) */
277  uint8_t _queue_size; /**< maximum number of elements in the queue */
278  int8_t _subscriber_count{0};
279 
280  // statistics
281  uint32_t _lost_messages = 0; /**< nr of lost messages for all subscribers. If two subscribers lose the same
282  message, it is counted as two. */
283 
284  inline static SubscriberData *filp_to_sd(cdev::file_t *filp);
285 
286  /**
287  * Check whether a topic appears updated to a subscriber.
288  *
289  * Lock must already be held when calling this.
290  *
291  * @param sd The subscriber for whom to check.
292  * @return True if the topic should appear updated to the subscriber
293  */
295 
296 };
static ssize_t publish(const orb_metadata *meta, orb_advert_t handle, const void *data)
Method to publish a data to this node.
bool copy_locked(void *dst, unsigned &generation)
Copies data and the corresponding generation from a node to the buffer provided.
px4::atomic< unsigned > _generation
object generation count
void unregister_callback(SubscriptionCallback *callback_sub)
pollevent_t poll_state(cdev::file_t *filp) override
Check the current state of the device for poll events from the perspective of the file...
uint8_t get_queue_size() const
uint64_t last_update
time at which the last update was provided, used when update_interval is nonzero
const orb_metadata * _meta
object metadata information
int update_queue_size(unsigned int queue_size)
Try to change the size of the queue.
void poll_notify_one(px4_pollfd_struct_t *fds, pollevent_t events) override
Internal implementation of poll_notify.
void set_priority(uint8_t priority)
uint32_t lost_message_count() const
An intrusive linked list.
int8_t subscriber_count() const
int reset(enum LPS22HB_BUS busid)
Reset the driver.
static int update_interval
Definition: hrt_test.cpp:55
LidarLite * instance
Definition: ll40ls.cpp:65
int open(cdev::file_t *filp) override
Method to create a subscriber instance and return the struct pointing to the subscriber as a file poi...
const char * o_name
unique object name
Definition: uORB.h:51
uint8_t * _data
allocated object buffer
DeviceNode & operator=(const DeviceNode &)=delete
ssize_t write(cdev::file_t *filp, const char *buffer, size_t buflen) override
writes the published data to the internal buffer to be read by subscribers later. ...
uint8_t _priority
priority of the topic
Definition: List.hpp:59
Abstract class for any character device.
Definition: CDev.hpp:58
unsigned published_message_count() const
uint32_t _lost_messages
nr of lost messages for all subscribers.
Per-object device instance.
uint8_t * data
Definition: dataman.cpp:149
uint64_t copy_and_get_timestamp(void *dst, unsigned &generation)
Copies data and the corresponding generation from a node to the buffer provided.
int get_priority() const
void remove_internal_subscriber()
Removes the subscriber from the list.
hrt_abstime _last_update
time the object was last updated
bool appears_updated(SubscriberData *sd)
Check whether a topic appears updated to a subscriber.
__BEGIN_DECLS typedef uint64_t hrt_abstime
Absolute time, in microsecond units.
Definition: drv_hrt.h:58
__BEGIN_DECLS typedef void * orb_advert_t
ORB topic advertiser handle.
Definition: uORB.h:134
bool is_advertised() const
Return true if this topic has been advertised.
const uint8_t _instance
orb multi instance identifier
uint8_t get_instance() const
int close(cdev::file_t *filp) override
Method to close a subscriber for this topic.
static SubscriberData * filp_to_sd(cdev::file_t *filp)
const orb_metadata * get_meta() const
Object metadata.
Definition: uORB.h:50
ssize_t read(cdev::file_t *filp, char *buffer, size_t buflen) override
reads data from a subscriber node to the buffer provided.
void add_internal_subscriber()
Add the subscriber to the node&#39;s list of subscriber.
unsigned interval
if nonzero minimum interval between updates
bool copy(void *dst, unsigned &generation)
Copies data and the corresponding generation from a node to the buffer provided.
bool register_callback(SubscriptionCallback *callback_sub)
DeviceNode(const struct orb_metadata *meta, const uint8_t instance, const char *path, uint8_t priority, uint8_t queue_size=1)
List< uORB::SubscriptionCallback * > _callbacks
static int unadvertise(orb_advert_t handle)
int ioctl(cdev::file_t *filp, int cmd, unsigned long arg) override
IOCTL control for the subscriber.
bool print_statistics(bool reset)
Print statistics (nr of lost messages)
uint8_t _queue_size
maximum number of elements in the queue
const char * get_name() const
bool _advertised
has ever been advertised (not necessarily published data yet)