PX4 Firmware
PX4 Autopilot Software http://px4.io
CDev.hpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2012-2018 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 /**
35  * @file CDev.hpp
36  *
37  * Definitions for the generic base classes in the device framework.
38  */
39 
40 #ifndef _CDEV_HPP
41 #define _CDEV_HPP
42 
43 #include <px4_platform_common/px4_config.h>
44 #include <px4_platform_common/posix.h>
45 
46 #ifdef __PX4_NUTTX
47 #include "nuttx/cdev_platform.hpp"
48 #else
49 #include "posix/cdev_platform.hpp"
50 #endif
51 
52 namespace cdev
53 {
54 
55 /**
56  * Abstract class for any character device
57  */
59 {
60 public:
61  /**
62  * Constructor
63  *
64  * @param name Driver name
65  * @param devname Device node name
66  */
67  explicit CDev(const char *devname);
68 
69  // no copy, assignment, move, move assignment
70  CDev(const CDev &) = delete;
71  CDev &operator=(const CDev &) = delete;
72  CDev(CDev &&) = delete;
73  CDev &operator=(CDev &&) = delete;
74 
75  virtual ~CDev();
76 
77  virtual int init();
78 
79  /**
80  * Handle an open of the device.
81  *
82  * This function is called for every open of the device. The default
83  * implementation maintains _open_count and always returns OK.
84  *
85  * @param filep Pointer to the NuttX file structure.
86  * @return OK if the open is allowed, -errno otherwise.
87  */
88  virtual int open(file_t *filep);
89 
90  /**
91  * Handle a close of the device.
92  *
93  * This function is called for every close of the device. The default
94  * implementation maintains _open_count and returns OK as long as it is not zero.
95  *
96  * @param filep Pointer to the NuttX file structure.
97  * @return OK if the close was successful, -errno otherwise.
98  */
99  virtual int close(file_t *filep);
100 
101  /**
102  * Perform a read from the device.
103  *
104  * The default implementation returns -ENOSYS.
105  *
106  * @param filep Pointer to the NuttX file structure.
107  * @param buffer Pointer to the buffer into which data should be placed.
108  * @param buflen The number of bytes to be read.
109  * @return The number of bytes read or -errno otherwise.
110  */
111  virtual ssize_t read(file_t *filep, char *buffer, size_t buflen) { return -ENOSYS; }
112 
113  /**
114  * Perform a write to the device.
115  *
116  * The default implementation returns -ENOSYS.
117  *
118  * @param filep Pointer to the NuttX file structure.
119  * @param buffer Pointer to the buffer from which data should be read.
120  * @param buflen The number of bytes to be written.
121  * @return The number of bytes written or -errno otherwise.
122  */
123  virtual ssize_t write(file_t *filep, const char *buffer, size_t buflen) { return -ENOSYS; }
124 
125  /**
126  * Perform a logical seek operation on the device.
127  *
128  * The default implementation returns -ENOSYS.
129  *
130  * @param filep Pointer to the NuttX file structure.
131  * @param offset The new file position relative to whence.
132  * @param whence SEEK_OFS, SEEK_CUR or SEEK_END.
133  * @return The previous offset, or -errno otherwise.
134  */
135  virtual off_t seek(file_t *filep, off_t offset, int whence) { return -ENOSYS; }
136 
137  /**
138  * Perform an ioctl operation on the device.
139  *
140  * The default implementation handles DIOC_GETPRIV, and otherwise
141  * returns -ENOTTY. Subclasses should call the default implementation
142  * for any command they do not handle themselves.
143  *
144  * @param filep Pointer to the NuttX file structure.
145  * @param cmd The ioctl command value.
146  * @param arg The ioctl argument value.
147  * @return OK on success, or -errno otherwise.
148  */
149  virtual int ioctl(file_t *filep, int cmd, unsigned long arg);
150 
151  /**
152  * Perform a poll setup/teardown operation.
153  *
154  * This is handled internally and should not normally be overridden.
155  *
156  * @param filep Pointer to the internal file structure.
157  * @param fds Poll descriptor being waited on.
158  * @param setup True if this is establishing a request, false if
159  * it is being torn down.
160  * @return OK on success, or -errno otherwise.
161  */
162  virtual int poll(file_t *filep, px4_pollfd_struct_t *fds, bool setup);
163 
164  /**
165  * Get the device name.
166  *
167  * @return the file system string of the device handle
168  */
169  const char *get_devname() const { return _devname; }
170 
171 protected:
172  /**
173  * Pointer to the default cdev file operations table; useful for
174  * registering clone devices etc.
175  */
177 
178  /**
179  * Check the current state of the device for poll events from the
180  * perspective of the file.
181  *
182  * This function is called by the default poll() implementation when
183  * a poll is set up to determine whether the poll should return immediately.
184  *
185  * The default implementation returns no events.
186  *
187  * @param filep The file that's interested.
188  * @return The current set of poll events.
189  */
190  virtual pollevent_t poll_state(file_t *filep) { return 0; }
191 
192  /**
193  * Report new poll events.
194  *
195  * This function should be called anytime the state of the device changes
196  * in a fashion that might be interesting to a poll waiter.
197  *
198  * @param events The new event(s) being announced.
199  */
200  virtual void poll_notify(pollevent_t events);
201 
202  /**
203  * Internal implementation of poll_notify.
204  *
205  * @param fds A poll waiter to notify.
206  * @param events The event(s) to send to the waiter.
207  */
208  virtual void poll_notify_one(px4_pollfd_struct_t *fds, pollevent_t events);
209 
210  /**
211  * Notification of the first open.
212  *
213  * This function is called when the device open count transitions from zero
214  * to one. The driver lock is held for the duration of the call.
215  *
216  * The default implementation returns OK.
217  *
218  * @param filep Pointer to the NuttX file structure.
219  * @return OK if the open should proceed, -errno otherwise.
220  */
221  virtual int open_first(file_t *filep) { return PX4_OK; }
222 
223  /**
224  * Notification of the last close.
225  *
226  * This function is called when the device open count transitions from
227  * one to zero. The driver lock is held for the duration of the call.
228  *
229  * The default implementation returns OK.
230  *
231  * @param filep Pointer to the NuttX file structure.
232  * @return OK if the open should return OK, -errno otherwise.
233  */
234  virtual int close_last(file_t *filep) { return PX4_OK; }
235 
236  /**
237  * Register a class device name, automatically adding device
238  * class instance suffix if need be.
239  *
240  * @param class_devname Device class name
241  * @return class_instamce Class instance created, or -errno on failure
242  */
243  virtual int register_class_devname(const char *class_devname);
244 
245  /**
246  * Register a class device name, automatically adding device
247  * class instance suffix if need be.
248  *
249  * @param class_devname Device class name
250  * @param class_instance Device class instance from register_class_devname()
251  * @return OK on success, -errno otherwise
252  */
253  virtual int unregister_class_devname(const char *class_devname, unsigned class_instance);
254 
255  /**
256  * Take the driver lock.
257  *
258  * Each driver instance has its own lock/semaphore.
259  *
260  * Note that we must loop as the wait may be interrupted by a signal.
261  *
262  * Careful: lock() calls cannot be nested!
263  */
264  void lock() { do {} while (px4_sem_wait(&_lock) != 0); }
265 
266  /**
267  * Release the driver lock.
268  */
269  void unlock() { px4_sem_post(&_lock); }
270 
271  px4_sem_t _lock; /**< lock to protect access to all class members (also for derived classes) */
272 
273 
274  /**
275  * First, unregisters the driver. Next, free the memory for the devname,
276  * in case it was expected to have ownership. Sets devname to nullptr.
277  *
278  * This is only needed if the ownership of the devname was passed to the CDev, otherwise ~CDev handles it.
279  *
280  * @return PX4_OK on success, -ENODEV if the devname is already nullptr
281  */
282  int unregister_driver_and_memory();
283 
284 private:
285  const char *_devname{nullptr}; /**< device node name */
286 
287  px4_pollfd_struct_t **_pollset{nullptr};
288 
289  bool _registered{false}; /**< true if device name was registered */
290 
291  uint8_t _max_pollwaiters{0}; /**< size of the _pollset array */
292  uint16_t _open_count{0}; /**< number of successful opens */
293 
294  /**
295  * Store a pollwaiter in a slot where we can find it later.
296  *
297  * Expands the pollset as required. Must be called with the driver locked.
298  *
299  * @return OK, or -errno on error.
300  */
301  inline int store_poll_waiter(px4_pollfd_struct_t *fds);
302 
303  /**
304  * Remove a poll waiter.
305  *
306  * @return OK, or -errno on error.
307  */
308  inline int remove_poll_waiter(px4_pollfd_struct_t *fds);
309 
310 };
311 
312 } // namespace cdev
313 
314 #endif /* _CDEV_HPP */
virtual int close_last(file_t *filep)
Notification of the last close.
Definition: CDev.hpp:234
px4_sem_t _lock
lock to protect access to all class members (also for derived classes)
Definition: CDev.hpp:271
void lock()
Take the driver lock.
Definition: CDev.hpp:264
Definition: I2C.hpp:51
virtual pollevent_t poll_state(file_t *filep)
Check the current state of the device for poll events from the perspective of the file...
Definition: CDev.hpp:190
static const px4_file_operations_t fops
Pointer to the default cdev file operations table; useful for registering clone devices etc...
Definition: CDev.hpp:176
virtual ssize_t read(file_t *filep, char *buffer, size_t buflen)
Perform a read from the device.
Definition: CDev.hpp:111
virtual int open_first(file_t *filep)
Notification of the first open.
Definition: CDev.hpp:221
virtual off_t seek(file_t *filep, off_t offset, int whence)
Perform a logical seek operation on the device.
Definition: CDev.hpp:135
Abstract class for any character device.
Definition: CDev.hpp:58
void init()
Activates/configures the hardware registers.
virtual ssize_t write(file_t *filep, const char *buffer, size_t buflen)
Perform a write to the device.
Definition: CDev.hpp:123
Definition: CDev.cpp:47
const char * get_devname() const
Get the device name.
Definition: CDev.hpp:169
void unlock()
Release the driver lock.
Definition: CDev.hpp:269