41 #include "../CDev.hpp" 43 #include <px4_platform_common/log.h> 44 #include <px4_platform_common/posix.h> 45 #include <px4_platform_common/time.h> 54 pthread_mutex_t
devmutex = PTHREAD_MUTEX_INITIALIZER;
55 pthread_mutex_t
filemutex = PTHREAD_MUTEX_INITIALIZER;
57 #define PX4_MAX_FD 350 67 PX4_DEBUG(
"CDev::getDev");
71 auto item = devmap.find(path);
73 if (item != devmap.end()) {
86 bool valid = (fd < PX4_MAX_FD && fd >= 0 && filemap[
fd].
vdev);
102 PX4_DEBUG(
"CDev::register_driver %s", name);
105 if (name ==
nullptr || data ==
nullptr) {
112 auto item = devmap.find(name);
114 if (item != devmap.end()) {
119 devmap[
name] = (
void *)data;
120 PX4_DEBUG(
"Registered DEV %s", name);
129 PX4_DEBUG(
"CDev::unregister_driver %s", name);
132 if (name ==
nullptr) {
138 if (devmap.erase(name) > 0) {
139 PX4_DEBUG(
"Unregistered DEV %s", name);
150 PX4_DEBUG(
"px4_open");
156 if (!dev && (flags & PX4_F_WRONLY) != 0 &&
157 strncmp(path,
"/obj/", 5) != 0 &&
158 strncmp(path,
"/dev/", 5) != 0) {
161 mode = va_arg(p,
int);
165 PX4_DEBUG(
"Creating virtual file %s", path);
174 if (filemap[i].vdev ==
nullptr) {
182 if (i < PX4_MAX_FD) {
183 ret = dev->
open(&filemap[i]);
187 const unsigned NAMELEN = 32;
188 char thread_name[NAMELEN] = {};
190 PX4_WARN(
"%s: exceeded maximum number of file descriptors, accessing %s",
193 int nret = pthread_getname_np(pthread_self(), thread_name, NAMELEN);
195 if (nret || thread_name[0] == 0) {
196 PX4_WARN(
"failed getting thread name");
212 PX4_DEBUG(
"px4_open fd = %d", i);
224 ret = dev->
close(&filemap[fd]);
226 filemap[
fd].
vdev =
nullptr;
229 PX4_DEBUG(
"px4_close fd = %d", fd);
250 PX4_DEBUG(
"px4_read fd = %d", fd);
251 ret = dev->
read(&filemap[fd], (
char *)buffer, buflen);
272 PX4_DEBUG(
"px4_write fd = %d", fd);
273 ret = dev->
write(&filemap[fd], (
const char *)buffer, buflen);
289 PX4_DEBUG(
"px4_ioctl fd = %d", fd);
295 ret = dev->
ioctl(&filemap[fd], cmd, arg);
308 int px4_poll(px4_pollfd_struct_t *fds, nfds_t nfds,
int timeout)
311 PX4_WARN(
"px4_poll with no fds");
320 const unsigned NAMELEN = 32;
321 char thread_name[NAMELEN] = {};
324 int nret = pthread_getname_np(pthread_self(), thread_name, NAMELEN);
326 if (nret || thread_name[0] == 0) {
327 PX4_WARN(
"failed getting thread name");
332 PX4_DEBUG(
"Called px4_poll timeout = %d", timeout);
334 px4_sem_init(&sem, 0, 0);
337 px4_sem_setprotocol(&sem, SEM_PRIO_NONE);
340 bool fd_pollable =
false;
342 for (i = 0; i < nfds; ++i) {
345 fds[i].priv =
nullptr;
351 PX4_DEBUG(
"%s: px4_poll: CDev->poll(setup) %d", thread_name, fds[i].fd);
352 ret = dev->
poll(&filemap[fds[i].fd], &fds[i],
true);
355 PX4_WARN(
"%s: px4_poll() error: %s",
356 thread_name, strerror(errno));
375 px4_clock_gettime(CLOCK_MONOTONIC, &ts);
378 const unsigned billion = (1000 * 1000 * 1000);
379 uint64_t nsecs = ts.tv_nsec + ((uint64_t)timeout * 1000 * 1000);
380 ts.tv_sec += nsecs / billion;
381 nsecs -= (nsecs / billion) * billion;
384 ret = px4_sem_timedwait(&sem, &ts);
386 if (ret && errno != ETIMEDOUT) {
387 PX4_WARN(
"%s: px4_poll() sem error: %s", thread_name, strerror(errno));
390 }
else if (timeout < 0) {
396 for (i = 0; i < nfds; ++i) {
402 PX4_DEBUG(
"%s: px4_poll: CDev->poll(teardown) %d", thread_name, fds[i].fd);
403 ret = dev->
poll(&filemap[fds[i].fd], &fds[i],
false);
406 PX4_WARN(
"%s: px4_poll() 2nd poll fail", thread_name);
410 if (fds[i].revents) {
417 px4_sem_destroy(&sem);
421 return (count) ? count : ret;
437 return (dev !=
nullptr) ? 0 : -1;
443 PX4_INFO(
"PX4 Devices:");
447 for (
const auto &dev : devmap) {
448 if (strncmp(dev.first.c_str(),
"/dev/", 5) == 0) {
449 PX4_INFO(
" %s", dev.first.c_str());
455 PX4_INFO(
"DF Devices:");
456 const char *dev_path;
457 unsigned int index = 0;
462 i = DevMgr::getNextDeviceName(index, &dev_path);
465 PX4_INFO(
" %s", dev_path);
472 PX4_INFO(
"Devices:");
476 for (
const auto &dev : devmap) {
477 if (strncmp(dev.first.c_str(),
"/obj/", 5) == 0) {
478 PX4_INFO(
" %s", dev.first.c_str());
491 for (
const auto &dev : devmap) {
492 if (strncmp(dev.first.c_str(),
"/obj/", 5) != 0 &&
493 strncmp(dev.first.c_str(),
"/dev/", 5) != 0) {
494 PX4_INFO(
" %s", dev.first.c_str());
virtual int open(file_t *filep)
Handle an open of the device.
static const px4_file_operations_t fops
Pointer to the default cdev file operations table; useful for registering clone devices etc...
virtual ssize_t read(file_t *filep, char *buffer, size_t buflen)
Perform a read from the device.
virtual int close(file_t *filep)
Handle a close of the device.
Abstract class for any character device.
static VFile * createFile(const char *fname, mode_t mode)
virtual ssize_t write(file_t *filep, const char *buffer, size_t buflen)
Perform a write to the device.
virtual int ioctl(file_t *filep, int cmd, unsigned long arg)
Perform an ioctl operation on the device.
virtual int poll(file_t *filep, px4_pollfd_struct_t *fds, bool setup)
Perform a poll setup/teardown operation.