mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-19 00:33:33 +08:00
Merge branch 'master' of https://github.com/PX4/Firmware into distance_sensor
This commit is contained in:
@@ -38,7 +38,7 @@
|
||||
* Driver for the Eagle Tree Airspeed V3 connected via I2C.
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <drivers/device/i2c.h>
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
* Generic driver for airspeed sensors connected via I2C.
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <drivers/device/i2c.h>
|
||||
|
||||
@@ -55,9 +55,14 @@
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef __PX4_NUTTX
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/wqueue.h>
|
||||
#include <nuttx/clock.h>
|
||||
#
|
||||
#else
|
||||
#include <px4_workqueue.h>
|
||||
#endif
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
@@ -95,8 +100,8 @@ public:
|
||||
|
||||
virtual int init();
|
||||
|
||||
virtual ssize_t read(struct file *filp, char *buffer, size_t buflen);
|
||||
virtual int ioctl(struct file *filp, int cmd, unsigned long arg);
|
||||
virtual ssize_t read(device::file_t *filp, char *buffer, size_t buflen);
|
||||
virtual int ioctl(device::file_t *filp, int cmd, unsigned long arg);
|
||||
|
||||
/**
|
||||
* Diagnostics - print some basic information about the driver.
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
* Implementation of AR.Drone 1.0 / 2.0 motor control interface.
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -121,7 +121,7 @@ int ardrone_interface_main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
thread_should_exit = false;
|
||||
ardrone_interface_task = task_spawn_cmd("ardrone_interface",
|
||||
ardrone_interface_task = px4_task_spawn_cmd("ardrone_interface",
|
||||
SCHED_DEFAULT,
|
||||
SCHED_PRIORITY_MAX - 15,
|
||||
1100,
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
* Implementation of AR.Drone 1.0 / 2.0 motor control interface
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
* @author Randy Mackay <rmackay9@yahoo.com>
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
@@ -106,7 +106,7 @@
|
||||
#include <ctype.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include <nuttx/wqueue.h>
|
||||
#include <px4_workqueue.h>
|
||||
|
||||
#include <systemlib/perf_counter.h>
|
||||
#include <systemlib/err.h>
|
||||
@@ -140,7 +140,7 @@ public:
|
||||
virtual int init();
|
||||
virtual int probe();
|
||||
virtual int setMode(int mode);
|
||||
virtual int ioctl(struct file *filp, int cmd, unsigned long arg);
|
||||
virtual int ioctl(device::file_t *filp, int cmd, unsigned long arg);
|
||||
|
||||
static const char *const script_names[];
|
||||
|
||||
@@ -275,7 +275,11 @@ const char *const BlinkM::script_names[] = {
|
||||
extern "C" __EXPORT int blinkm_main(int argc, char *argv[]);
|
||||
|
||||
BlinkM::BlinkM(int bus, int blinkm) :
|
||||
I2C("blinkm", BLINKM0_DEVICE_PATH, bus, blinkm, 100000),
|
||||
I2C("blinkm", BLINKM0_DEVICE_PATH, bus, blinkm
|
||||
#ifdef __PX4_NUTTX
|
||||
, 100000
|
||||
#endif
|
||||
),
|
||||
led_color_1(LED_OFF),
|
||||
led_color_2(LED_OFF),
|
||||
led_color_3(LED_OFF),
|
||||
@@ -316,6 +320,7 @@ BlinkM::init()
|
||||
ret = I2C::init();
|
||||
|
||||
if (ret != OK) {
|
||||
warnx("I2C init failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -357,7 +362,7 @@ BlinkM::probe()
|
||||
}
|
||||
|
||||
int
|
||||
BlinkM::ioctl(struct file *filp, int cmd, unsigned long arg)
|
||||
BlinkM::ioctl(device::file_t *filp, int cmd, unsigned long arg)
|
||||
{
|
||||
int ret = ENOTTY;
|
||||
|
||||
@@ -942,6 +947,10 @@ blinkm_main(int argc, char *argv[])
|
||||
|
||||
int x;
|
||||
|
||||
if (argc < 2) {
|
||||
blinkm_usage();
|
||||
return 1;
|
||||
}
|
||||
for (x = 1; x < argc; x++) {
|
||||
if (strcmp(argv[x], "-b") == 0 || strcmp(argv[x], "--bus") == 0) {
|
||||
if (argc > x + 1) {
|
||||
@@ -958,38 +967,43 @@ blinkm_main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "start")) {
|
||||
if (g_blinkm != nullptr)
|
||||
errx(1, "already started");
|
||||
if (g_blinkm != nullptr) {
|
||||
warnx("already started");
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_blinkm = new BlinkM(i2cdevice, blinkmadr);
|
||||
|
||||
if (g_blinkm == nullptr)
|
||||
errx(1, "new failed");
|
||||
if (g_blinkm == nullptr) {
|
||||
warnx("new failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (OK != g_blinkm->init()) {
|
||||
delete g_blinkm;
|
||||
g_blinkm = nullptr;
|
||||
errx(1, "no BlinkM found");
|
||||
warnx("init failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
exit(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (g_blinkm == nullptr) {
|
||||
fprintf(stderr, "not started\n");
|
||||
blinkm_usage();
|
||||
exit(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "systemstate")) {
|
||||
g_blinkm->setMode(1);
|
||||
exit(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "ledoff")) {
|
||||
g_blinkm->setMode(0);
|
||||
exit(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -997,18 +1011,22 @@ blinkm_main(int argc, char *argv[])
|
||||
for (unsigned i = 0; BlinkM::script_names[i] != nullptr; i++)
|
||||
fprintf(stderr, " %s\n", BlinkM::script_names[i]);
|
||||
fprintf(stderr, " <html color number>\n");
|
||||
exit(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* things that require access to the device */
|
||||
int fd = open(BLINKM0_DEVICE_PATH, 0);
|
||||
if (fd < 0)
|
||||
err(1, "can't open BlinkM device");
|
||||
int fd = px4_open(BLINKM0_DEVICE_PATH, 0);
|
||||
if (fd < 0) {
|
||||
warn("can't open BlinkM device");
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_blinkm->setMode(0);
|
||||
if (ioctl(fd, BLINKM_PLAY_SCRIPT_NAMED, (unsigned long)argv[1]) == OK)
|
||||
exit(0);
|
||||
if (px4_ioctl(fd, BLINKM_PLAY_SCRIPT_NAMED, (unsigned long)argv[1]) == OK)
|
||||
return 0;
|
||||
|
||||
px4_close(fd);
|
||||
|
||||
blinkm_usage();
|
||||
exit(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
* Driver for the Bosch BMA 180 MEMS accelerometer connected via SPI.
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
* AeroCore LED backend.
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
* Included Files
|
||||
************************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
* Included Files
|
||||
****************************************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
#include <nuttx/compiler.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
* Included Files
|
||||
****************************************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
#include <nuttx/compiler.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
* Included Files
|
||||
************************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
* PX4FMU LED backend.
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
* Included Files
|
||||
************************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
* Included Files
|
||||
************************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
* Included Files
|
||||
****************************************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
#include <nuttx/compiler.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
* PX4FMU LED backend.
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
* Included Files
|
||||
************************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
* Included Files
|
||||
************************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
* Included Files
|
||||
************************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
* Included Files
|
||||
************************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
#include <nuttx/compiler.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
* Included Files
|
||||
******************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
#include <nuttx/compiler.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
+24
-24
@@ -60,13 +60,13 @@ static const unsigned pollset_increment = 0;
|
||||
* The standard NuttX operation dispatch table can't call C++ member functions
|
||||
* directly, so we have to bounce them through this dispatch table.
|
||||
*/
|
||||
static int cdev_open(struct file *filp);
|
||||
static int cdev_close(struct file *filp);
|
||||
static ssize_t cdev_read(struct file *filp, char *buffer, size_t buflen);
|
||||
static ssize_t cdev_write(struct file *filp, const char *buffer, size_t buflen);
|
||||
static off_t cdev_seek(struct file *filp, off_t offset, int whence);
|
||||
static int cdev_ioctl(struct file *filp, int cmd, unsigned long arg);
|
||||
static int cdev_poll(struct file *filp, struct pollfd *fds, bool setup);
|
||||
static int cdev_open(file_t *filp);
|
||||
static int cdev_close(file_t *filp);
|
||||
static ssize_t cdev_read(file_t *filp, char *buffer, size_t buflen);
|
||||
static ssize_t cdev_write(file_t *filp, const char *buffer, size_t buflen);
|
||||
static off_t cdev_seek(file_t *filp, off_t offset, int whence);
|
||||
static int cdev_ioctl(file_t *filp, int cmd, unsigned long arg);
|
||||
static int cdev_poll(file_t *filp, px4_pollfd_struct_t *fds, bool setup);
|
||||
|
||||
/**
|
||||
* Character device indirection table.
|
||||
@@ -169,7 +169,7 @@ out:
|
||||
* Default implementations of the character device interface
|
||||
*/
|
||||
int
|
||||
CDev::open(struct file *filp)
|
||||
CDev::open(file_t *filp)
|
||||
{
|
||||
int ret = OK;
|
||||
|
||||
@@ -192,13 +192,13 @@ CDev::open(struct file *filp)
|
||||
}
|
||||
|
||||
int
|
||||
CDev::open_first(struct file *filp)
|
||||
CDev::open_first(file_t *filp)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
int
|
||||
CDev::close(struct file *filp)
|
||||
CDev::close(file_t *filp)
|
||||
{
|
||||
int ret = OK;
|
||||
|
||||
@@ -222,31 +222,31 @@ CDev::close(struct file *filp)
|
||||
}
|
||||
|
||||
int
|
||||
CDev::close_last(struct file *filp)
|
||||
CDev::close_last(file_t *filp)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
CDev::read(struct file *filp, char *buffer, size_t buflen)
|
||||
CDev::read(file_t *filp, char *buffer, size_t buflen)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
CDev::write(struct file *filp, const char *buffer, size_t buflen)
|
||||
CDev::write(file_t *filp, const char *buffer, size_t buflen)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
off_t
|
||||
CDev::seek(struct file *filp, off_t offset, int whence)
|
||||
CDev::seek(file_t *filp, off_t offset, int whence)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int
|
||||
CDev::ioctl(struct file *filp, int cmd, unsigned long arg)
|
||||
CDev::ioctl(file_t *filp, int cmd, unsigned long arg)
|
||||
{
|
||||
switch (cmd) {
|
||||
|
||||
@@ -275,7 +275,7 @@ CDev::ioctl(struct file *filp, int cmd, unsigned long arg)
|
||||
}
|
||||
|
||||
int
|
||||
CDev::poll(struct file *filp, struct pollfd *fds, bool setup)
|
||||
CDev::poll(file_t *filp, struct pollfd *fds, bool setup)
|
||||
{
|
||||
int ret = OK;
|
||||
|
||||
@@ -347,7 +347,7 @@ CDev::poll_notify_one(struct pollfd *fds, pollevent_t events)
|
||||
}
|
||||
|
||||
pollevent_t
|
||||
CDev::poll_state(struct file *filp)
|
||||
CDev::poll_state(file_t *filp)
|
||||
{
|
||||
/* by default, no poll events to report */
|
||||
return 0;
|
||||
@@ -389,7 +389,7 @@ CDev::remove_poll_waiter(struct pollfd *fds)
|
||||
}
|
||||
|
||||
static int
|
||||
cdev_open(struct file *filp)
|
||||
cdev_open(file_t *filp)
|
||||
{
|
||||
CDev *cdev = (CDev *)(filp->f_inode->i_private);
|
||||
|
||||
@@ -397,7 +397,7 @@ cdev_open(struct file *filp)
|
||||
}
|
||||
|
||||
static int
|
||||
cdev_close(struct file *filp)
|
||||
cdev_close(file_t *filp)
|
||||
{
|
||||
CDev *cdev = (CDev *)(filp->f_inode->i_private);
|
||||
|
||||
@@ -405,7 +405,7 @@ cdev_close(struct file *filp)
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
cdev_read(struct file *filp, char *buffer, size_t buflen)
|
||||
cdev_read(file_t *filp, char *buffer, size_t buflen)
|
||||
{
|
||||
CDev *cdev = (CDev *)(filp->f_inode->i_private);
|
||||
|
||||
@@ -413,7 +413,7 @@ cdev_read(struct file *filp, char *buffer, size_t buflen)
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
cdev_write(struct file *filp, const char *buffer, size_t buflen)
|
||||
cdev_write(file_t *filp, const char *buffer, size_t buflen)
|
||||
{
|
||||
CDev *cdev = (CDev *)(filp->f_inode->i_private);
|
||||
|
||||
@@ -421,7 +421,7 @@ cdev_write(struct file *filp, const char *buffer, size_t buflen)
|
||||
}
|
||||
|
||||
static off_t
|
||||
cdev_seek(struct file *filp, off_t offset, int whence)
|
||||
cdev_seek(file_t *filp, off_t offset, int whence)
|
||||
{
|
||||
CDev *cdev = (CDev *)(filp->f_inode->i_private);
|
||||
|
||||
@@ -429,7 +429,7 @@ cdev_seek(struct file *filp, off_t offset, int whence)
|
||||
}
|
||||
|
||||
static int
|
||||
cdev_ioctl(struct file *filp, int cmd, unsigned long arg)
|
||||
cdev_ioctl(file_t *filp, int cmd, unsigned long arg)
|
||||
{
|
||||
CDev *cdev = (CDev *)(filp->f_inode->i_private);
|
||||
|
||||
@@ -437,7 +437,7 @@ cdev_ioctl(struct file *filp, int cmd, unsigned long arg)
|
||||
}
|
||||
|
||||
static int
|
||||
cdev_poll(struct file *filp, struct pollfd *fds, bool setup)
|
||||
cdev_poll(file_t *filp, px4_pollfd_struct_t *fds, bool setup)
|
||||
{
|
||||
CDev *cdev = (CDev *)(filp->f_inode->i_private);
|
||||
|
||||
|
||||
+6
-525
@@ -31,530 +31,11 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file device.h
|
||||
*
|
||||
* Definitions for the generic base classes in the device framework.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifndef _DEVICE_DEVICE_H
|
||||
#define _DEVICE_DEVICE_H
|
||||
#ifdef __PX4_NUTTX
|
||||
#include "device_nuttx.h"
|
||||
#elif defined (__PX4_POSIX)
|
||||
#include "vdev.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Includes here should only cover the needs of the framework definitions.
|
||||
*/
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include <nuttx/fs/fs.h>
|
||||
|
||||
/**
|
||||
* Namespace encapsulating all device framework classes, functions and data.
|
||||
*/
|
||||
namespace device __EXPORT
|
||||
{
|
||||
|
||||
/**
|
||||
* Fundamental base class for all device drivers.
|
||||
*
|
||||
* This class handles the basic "being a driver" things, including
|
||||
* interrupt registration and dispatch.
|
||||
*/
|
||||
class __EXPORT Device
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Destructor.
|
||||
*
|
||||
* Public so that anonymous devices can be destroyed.
|
||||
*/
|
||||
virtual ~Device();
|
||||
|
||||
/**
|
||||
* Interrupt handler.
|
||||
*/
|
||||
virtual void interrupt(void *ctx); /**< interrupt handler */
|
||||
|
||||
/*
|
||||
* Direct access methods.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialise the driver and make it ready for use.
|
||||
*
|
||||
* @return OK if the driver initialized OK, negative errno otherwise;
|
||||
*/
|
||||
virtual int init();
|
||||
|
||||
/**
|
||||
* Read directly from the device.
|
||||
*
|
||||
* The actual size of each unit quantity is device-specific.
|
||||
*
|
||||
* @param offset The device address at which to start reading
|
||||
* @param data The buffer into which the read values should be placed.
|
||||
* @param count The number of items to read.
|
||||
* @return The number of items read on success, negative errno otherwise.
|
||||
*/
|
||||
virtual int read(unsigned address, void *data, unsigned count);
|
||||
|
||||
/**
|
||||
* Write directly to the device.
|
||||
*
|
||||
* The actual size of each unit quantity is device-specific.
|
||||
*
|
||||
* @param address The device address at which to start writing.
|
||||
* @param data The buffer from which values should be read.
|
||||
* @param count The number of items to write.
|
||||
* @return The number of items written on success, negative errno otherwise.
|
||||
*/
|
||||
virtual int write(unsigned address, void *data, unsigned count);
|
||||
|
||||
/**
|
||||
* Perform a device-specific operation.
|
||||
*
|
||||
* @param operation The operation to perform.
|
||||
* @param arg An argument to the operation.
|
||||
* @return Negative errno on error, OK or positive value on success.
|
||||
*/
|
||||
virtual int ioctl(unsigned operation, unsigned &arg);
|
||||
|
||||
/*
|
||||
device bus types for DEVID
|
||||
*/
|
||||
enum DeviceBusType {
|
||||
DeviceBusType_UNKNOWN = 0,
|
||||
DeviceBusType_I2C = 1,
|
||||
DeviceBusType_SPI = 2,
|
||||
DeviceBusType_UAVCAN = 3,
|
||||
};
|
||||
|
||||
/*
|
||||
broken out device elements. The bitfields are used to keep
|
||||
the overall value small enough to fit in a float accurately,
|
||||
which makes it possible to transport over the MAVLink
|
||||
parameter protocol without loss of information.
|
||||
*/
|
||||
struct DeviceStructure {
|
||||
enum DeviceBusType bus_type:3;
|
||||
uint8_t bus:5; // which instance of the bus type
|
||||
uint8_t address; // address on the bus (eg. I2C address)
|
||||
uint8_t devtype; // device class specific device type
|
||||
};
|
||||
|
||||
union DeviceId {
|
||||
struct DeviceStructure devid_s;
|
||||
uint32_t devid;
|
||||
};
|
||||
|
||||
protected:
|
||||
const char *_name; /**< driver name */
|
||||
bool _debug_enabled; /**< if true, debug messages are printed */
|
||||
union DeviceId _device_id; /**< device identifier information */
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param name Driver name
|
||||
* @param irq Interrupt assigned to the device.
|
||||
*/
|
||||
Device(const char *name,
|
||||
int irq = 0);
|
||||
|
||||
/**
|
||||
* Enable the device interrupt
|
||||
*/
|
||||
void interrupt_enable();
|
||||
|
||||
/**
|
||||
* Disable the device interrupt
|
||||
*/
|
||||
void interrupt_disable();
|
||||
|
||||
/**
|
||||
* Take the driver lock.
|
||||
*
|
||||
* Each driver instance has its own lock/semaphore.
|
||||
*
|
||||
* Note that we must loop as the wait may be interrupted by a signal.
|
||||
*/
|
||||
void lock() {
|
||||
do {} while (sem_wait(&_lock) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Release the driver lock.
|
||||
*/
|
||||
void unlock() {
|
||||
sem_post(&_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a message.
|
||||
*
|
||||
* The message is prefixed with the driver name, and followed
|
||||
* by a newline.
|
||||
*/
|
||||
void log(const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* Print a debug message.
|
||||
*
|
||||
* The message is prefixed with the driver name, and followed
|
||||
* by a newline.
|
||||
*/
|
||||
void debug(const char *fmt, ...);
|
||||
|
||||
private:
|
||||
int _irq;
|
||||
bool _irq_attached;
|
||||
sem_t _lock;
|
||||
|
||||
/** disable copy construction for this and all subclasses */
|
||||
Device(const Device &);
|
||||
|
||||
/** disable assignment for this and all subclasses */
|
||||
Device &operator = (const Device &);
|
||||
|
||||
/**
|
||||
* Register ourselves as a handler for an interrupt
|
||||
*
|
||||
* @param irq The interrupt to claim
|
||||
* @return OK if the interrupt was registered
|
||||
*/
|
||||
int dev_register_interrupt(int irq);
|
||||
|
||||
/**
|
||||
* Unregister ourselves as a handler for any interrupt
|
||||
*/
|
||||
void dev_unregister_interrupt();
|
||||
|
||||
/**
|
||||
* Interrupt dispatcher
|
||||
*
|
||||
* @param irq The interrupt that has been triggered.
|
||||
* @param context Pointer to the interrupted context.
|
||||
*/
|
||||
static void dev_interrupt(int irq, void *context);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Abstract class for any character device
|
||||
*/
|
||||
class __EXPORT CDev : public Device
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param name Driver name
|
||||
* @param devname Device node name
|
||||
* @param irq Interrupt assigned to the device
|
||||
*/
|
||||
CDev(const char *name, const char *devname, int irq = 0);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~CDev();
|
||||
|
||||
virtual int init();
|
||||
|
||||
/**
|
||||
* Handle an open of the device.
|
||||
*
|
||||
* This function is called for every open of the device. The default
|
||||
* implementation maintains _open_count and always returns OK.
|
||||
*
|
||||
* @param filp Pointer to the NuttX file structure.
|
||||
* @return OK if the open is allowed, -errno otherwise.
|
||||
*/
|
||||
virtual int open(struct file *filp);
|
||||
|
||||
/**
|
||||
* Handle a close of the device.
|
||||
*
|
||||
* This function is called for every close of the device. The default
|
||||
* implementation maintains _open_count and returns OK as long as it is not zero.
|
||||
*
|
||||
* @param filp Pointer to the NuttX file structure.
|
||||
* @return OK if the close was successful, -errno otherwise.
|
||||
*/
|
||||
virtual int close(struct file *filp);
|
||||
|
||||
/**
|
||||
* Perform a read from the device.
|
||||
*
|
||||
* The default implementation returns -ENOSYS.
|
||||
*
|
||||
* @param filp Pointer to the NuttX file structure.
|
||||
* @param buffer Pointer to the buffer into which data should be placed.
|
||||
* @param buflen The number of bytes to be read.
|
||||
* @return The number of bytes read or -errno otherwise.
|
||||
*/
|
||||
virtual ssize_t read(struct file *filp, char *buffer, size_t buflen);
|
||||
|
||||
/**
|
||||
* Perform a write to the device.
|
||||
*
|
||||
* The default implementation returns -ENOSYS.
|
||||
*
|
||||
* @param filp Pointer to the NuttX file structure.
|
||||
* @param buffer Pointer to the buffer from which data should be read.
|
||||
* @param buflen The number of bytes to be written.
|
||||
* @return The number of bytes written or -errno otherwise.
|
||||
*/
|
||||
virtual ssize_t write(struct file *filp, const char *buffer, size_t buflen);
|
||||
|
||||
/**
|
||||
* Perform a logical seek operation on the device.
|
||||
*
|
||||
* The default implementation returns -ENOSYS.
|
||||
*
|
||||
* @param filp Pointer to the NuttX file structure.
|
||||
* @param offset The new file position relative to whence.
|
||||
* @param whence SEEK_OFS, SEEK_CUR or SEEK_END.
|
||||
* @return The previous offset, or -errno otherwise.
|
||||
*/
|
||||
virtual off_t seek(struct file *filp, off_t offset, int whence);
|
||||
|
||||
/**
|
||||
* Perform an ioctl operation on the device.
|
||||
*
|
||||
* The default implementation handles DIOC_GETPRIV, and otherwise
|
||||
* returns -ENOTTY. Subclasses should call the default implementation
|
||||
* for any command they do not handle themselves.
|
||||
*
|
||||
* @param filp Pointer to the NuttX file structure.
|
||||
* @param cmd The ioctl command value.
|
||||
* @param arg The ioctl argument value.
|
||||
* @return OK on success, or -errno otherwise.
|
||||
*/
|
||||
virtual int ioctl(struct file *filp, int cmd, unsigned long arg);
|
||||
|
||||
/**
|
||||
* Perform a poll setup/teardown operation.
|
||||
*
|
||||
* This is handled internally and should not normally be overridden.
|
||||
*
|
||||
* @param filp Pointer to the NuttX file structure.
|
||||
* @param fds Poll descriptor being waited on.
|
||||
* @param arg True if this is establishing a request, false if
|
||||
* it is being torn down.
|
||||
* @return OK on success, or -errno otherwise.
|
||||
*/
|
||||
virtual int poll(struct file *filp, struct pollfd *fds, bool setup);
|
||||
|
||||
/**
|
||||
* Test whether the device is currently open.
|
||||
*
|
||||
* This can be used to avoid tearing down a device that is still active.
|
||||
* Note - not virtual, cannot be overridden by a subclass.
|
||||
*
|
||||
* @return True if the device is currently open.
|
||||
*/
|
||||
bool is_open() { return _open_count > 0; }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Pointer to the default cdev file operations table; useful for
|
||||
* registering clone devices etc.
|
||||
*/
|
||||
static const struct file_operations fops;
|
||||
|
||||
/**
|
||||
* Check the current state of the device for poll events from the
|
||||
* perspective of the file.
|
||||
*
|
||||
* This function is called by the default poll() implementation when
|
||||
* a poll is set up to determine whether the poll should return immediately.
|
||||
*
|
||||
* The default implementation returns no events.
|
||||
*
|
||||
* @param filp The file that's interested.
|
||||
* @return The current set of poll events.
|
||||
*/
|
||||
virtual pollevent_t poll_state(struct file *filp);
|
||||
|
||||
/**
|
||||
* Report new poll events.
|
||||
*
|
||||
* This function should be called anytime the state of the device changes
|
||||
* in a fashion that might be interesting to a poll waiter.
|
||||
*
|
||||
* @param events The new event(s) being announced.
|
||||
*/
|
||||
virtual void poll_notify(pollevent_t events);
|
||||
|
||||
/**
|
||||
* Internal implementation of poll_notify.
|
||||
*
|
||||
* @param fds A poll waiter to notify.
|
||||
* @param events The event(s) to send to the waiter.
|
||||
*/
|
||||
virtual void poll_notify_one(struct pollfd *fds, pollevent_t events);
|
||||
|
||||
/**
|
||||
* Notification of the first open.
|
||||
*
|
||||
* This function is called when the device open count transitions from zero
|
||||
* to one. The driver lock is held for the duration of the call.
|
||||
*
|
||||
* The default implementation returns OK.
|
||||
*
|
||||
* @param filp Pointer to the NuttX file structure.
|
||||
* @return OK if the open should proceed, -errno otherwise.
|
||||
*/
|
||||
virtual int open_first(struct file *filp);
|
||||
|
||||
/**
|
||||
* Notification of the last close.
|
||||
*
|
||||
* This function is called when the device open count transitions from
|
||||
* one to zero. The driver lock is held for the duration of the call.
|
||||
*
|
||||
* The default implementation returns OK.
|
||||
*
|
||||
* @param filp Pointer to the NuttX file structure.
|
||||
* @return OK if the open should return OK, -errno otherwise.
|
||||
*/
|
||||
virtual int close_last(struct file *filp);
|
||||
|
||||
/**
|
||||
* Register a class device name, automatically adding device
|
||||
* class instance suffix if need be.
|
||||
*
|
||||
* @param class_devname Device class name
|
||||
* @return class_instamce Class instance created, or -errno on failure
|
||||
*/
|
||||
virtual int register_class_devname(const char *class_devname);
|
||||
|
||||
/**
|
||||
* Register a class device name, automatically adding device
|
||||
* class instance suffix if need be.
|
||||
*
|
||||
* @param class_devname Device class name
|
||||
* @param class_instance Device class instance from register_class_devname()
|
||||
* @return OK on success, -errno otherwise
|
||||
*/
|
||||
virtual int unregister_class_devname(const char *class_devname, unsigned class_instance);
|
||||
|
||||
/**
|
||||
* Get the device name.
|
||||
*
|
||||
* @return the file system string of the device handle
|
||||
*/
|
||||
const char* get_devname() { return _devname; }
|
||||
|
||||
bool _pub_blocked; /**< true if publishing should be blocked */
|
||||
|
||||
private:
|
||||
static const unsigned _max_pollwaiters = 8;
|
||||
|
||||
const char *_devname; /**< device node name */
|
||||
bool _registered; /**< true if device name was registered */
|
||||
unsigned _open_count; /**< number of successful opens */
|
||||
|
||||
struct pollfd *_pollset[_max_pollwaiters];
|
||||
|
||||
/**
|
||||
* Store a pollwaiter in a slot where we can find it later.
|
||||
*
|
||||
* Expands the pollset as required. Must be called with the driver locked.
|
||||
*
|
||||
* @return OK, or -errno on error.
|
||||
*/
|
||||
int store_poll_waiter(struct pollfd *fds);
|
||||
|
||||
/**
|
||||
* Remove a poll waiter.
|
||||
*
|
||||
* @return OK, or -errno on error.
|
||||
*/
|
||||
int remove_poll_waiter(struct pollfd *fds);
|
||||
|
||||
/* do not allow copying this class */
|
||||
CDev(const CDev&);
|
||||
CDev operator=(const CDev&);
|
||||
};
|
||||
|
||||
/**
|
||||
* Abstract class for character device accessed via PIO
|
||||
*/
|
||||
class __EXPORT PIO : public CDev
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param name Driver name
|
||||
* @param devname Device node name
|
||||
* @param base Base address of the device PIO area
|
||||
* @param irq Interrupt assigned to the device (or zero if none)
|
||||
*/
|
||||
PIO(const char *name,
|
||||
const char *devname,
|
||||
uint32_t base,
|
||||
int irq = 0);
|
||||
virtual ~PIO();
|
||||
|
||||
virtual int init();
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Read a register
|
||||
*
|
||||
* @param offset Register offset in bytes from the base address.
|
||||
*/
|
||||
uint32_t reg(uint32_t offset) {
|
||||
return *(volatile uint32_t *)(_base + offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a register
|
||||
*
|
||||
* @param offset Register offset in bytes from the base address.
|
||||
* @param value Value to write.
|
||||
*/
|
||||
void reg(uint32_t offset, uint32_t value) {
|
||||
*(volatile uint32_t *)(_base + offset) = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify a register
|
||||
*
|
||||
* Note that there is a risk of a race during the read/modify/write cycle
|
||||
* that must be taken care of by the caller.
|
||||
*
|
||||
* @param offset Register offset in bytes from the base address.
|
||||
* @param clearbits Bits to clear in the register
|
||||
* @param setbits Bits to set in the register
|
||||
*/
|
||||
void modify(uint32_t offset, uint32_t clearbits, uint32_t setbits) {
|
||||
uint32_t val = reg(offset);
|
||||
val &= ~clearbits;
|
||||
val |= setbits;
|
||||
reg(offset, val);
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t _base;
|
||||
};
|
||||
|
||||
} // namespace device
|
||||
|
||||
// class instance for primary driver of each class
|
||||
enum CLASS_DEVICE {
|
||||
CLASS_DEVICE_PRIMARY=0,
|
||||
CLASS_DEVICE_SECONDARY=1,
|
||||
CLASS_DEVICE_TERTIARY=2
|
||||
};
|
||||
|
||||
#endif /* _DEVICE_DEVICE_H */
|
||||
|
||||
@@ -0,0 +1,563 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2012-2014 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file device_nuttx.h
|
||||
*
|
||||
* Definitions for the generic base classes in the device framework.
|
||||
*/
|
||||
|
||||
#ifndef _DEVICE_DEVICE_H
|
||||
#define _DEVICE_DEVICE_H
|
||||
|
||||
/*
|
||||
* Includes here should only cover the needs of the framework definitions.
|
||||
*/
|
||||
#include <px4_config.h>
|
||||
#include <px4_posix.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include <nuttx/fs/fs.h>
|
||||
|
||||
/**
|
||||
* Namespace encapsulating all device framework classes, functions and data.
|
||||
*/
|
||||
namespace device __EXPORT
|
||||
{
|
||||
|
||||
typedef struct file file_t;
|
||||
|
||||
/**
|
||||
* Fundamental base class for all device drivers.
|
||||
*
|
||||
* This class handles the basic "being a driver" things, including
|
||||
* interrupt registration and dispatch.
|
||||
*/
|
||||
class __EXPORT Device
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Destructor.
|
||||
*
|
||||
* Public so that anonymous devices can be destroyed.
|
||||
*/
|
||||
virtual ~Device();
|
||||
|
||||
/**
|
||||
* Interrupt handler.
|
||||
*/
|
||||
virtual void interrupt(void *ctx); /**< interrupt handler */
|
||||
|
||||
/*
|
||||
* Direct access methods.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialise the driver and make it ready for use.
|
||||
*
|
||||
* @return OK if the driver initialized OK, negative errno otherwise;
|
||||
*/
|
||||
virtual int init();
|
||||
|
||||
/**
|
||||
* Read directly from the device.
|
||||
*
|
||||
* The actual size of each unit quantity is device-specific.
|
||||
*
|
||||
* @param offset The device address at which to start reading
|
||||
* @param data The buffer into which the read values should be placed.
|
||||
* @param count The number of items to read.
|
||||
* @return The number of items read on success, negative errno otherwise.
|
||||
*/
|
||||
virtual int read(unsigned address, void *data, unsigned count);
|
||||
|
||||
/**
|
||||
* Write directly to the device.
|
||||
*
|
||||
* The actual size of each unit quantity is device-specific.
|
||||
*
|
||||
* @param address The device address at which to start writing.
|
||||
* @param data The buffer from which values should be read.
|
||||
* @param count The number of items to write.
|
||||
* @return The number of items written on success, negative errno otherwise.
|
||||
*/
|
||||
virtual int write(unsigned address, void *data, unsigned count);
|
||||
|
||||
/**
|
||||
* Perform a device-specific operation.
|
||||
*
|
||||
* @param operation The operation to perform.
|
||||
* @param arg An argument to the operation.
|
||||
* @return Negative errno on error, OK or positive value on success.
|
||||
*/
|
||||
virtual int ioctl(unsigned operation, unsigned &arg);
|
||||
|
||||
/*
|
||||
device bus types for DEVID
|
||||
*/
|
||||
enum DeviceBusType {
|
||||
DeviceBusType_UNKNOWN = 0,
|
||||
DeviceBusType_I2C = 1,
|
||||
DeviceBusType_SPI = 2,
|
||||
DeviceBusType_UAVCAN = 3,
|
||||
};
|
||||
|
||||
/*
|
||||
broken out device elements. The bitfields are used to keep
|
||||
the overall value small enough to fit in a float accurately,
|
||||
which makes it possible to transport over the MAVLink
|
||||
parameter protocol without loss of information.
|
||||
*/
|
||||
struct DeviceStructure {
|
||||
enum DeviceBusType bus_type:3;
|
||||
uint8_t bus:5; // which instance of the bus type
|
||||
uint8_t address; // address on the bus (eg. I2C address)
|
||||
uint8_t devtype; // device class specific device type
|
||||
};
|
||||
|
||||
union DeviceId {
|
||||
struct DeviceStructure devid_s;
|
||||
uint32_t devid;
|
||||
};
|
||||
|
||||
protected:
|
||||
const char *_name; /**< driver name */
|
||||
bool _debug_enabled; /**< if true, debug messages are printed */
|
||||
union DeviceId _device_id; /**< device identifier information */
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param name Driver name
|
||||
* @param irq Interrupt assigned to the device.
|
||||
*/
|
||||
Device(const char *name,
|
||||
int irq = 0);
|
||||
|
||||
/**
|
||||
* Enable the device interrupt
|
||||
*/
|
||||
void interrupt_enable();
|
||||
|
||||
/**
|
||||
* Disable the device interrupt
|
||||
*/
|
||||
void interrupt_disable();
|
||||
|
||||
/**
|
||||
* Take the driver lock.
|
||||
*
|
||||
* Each driver instance has its own lock/semaphore.
|
||||
*
|
||||
* Note that we must loop as the wait may be interrupted by a signal.
|
||||
*/
|
||||
void lock() {
|
||||
do {} while (sem_wait(&_lock) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Release the driver lock.
|
||||
*/
|
||||
void unlock() {
|
||||
sem_post(&_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a message.
|
||||
*
|
||||
* The message is prefixed with the driver name, and followed
|
||||
* by a newline.
|
||||
*/
|
||||
void log(const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* Print a debug message.
|
||||
*
|
||||
* The message is prefixed with the driver name, and followed
|
||||
* by a newline.
|
||||
*/
|
||||
void debug(const char *fmt, ...);
|
||||
|
||||
private:
|
||||
int _irq;
|
||||
bool _irq_attached;
|
||||
sem_t _lock;
|
||||
|
||||
/** disable copy construction for this and all subclasses */
|
||||
Device(const Device &);
|
||||
|
||||
/** disable assignment for this and all subclasses */
|
||||
Device &operator = (const Device &);
|
||||
|
||||
/**
|
||||
* Register ourselves as a handler for an interrupt
|
||||
*
|
||||
* @param irq The interrupt to claim
|
||||
* @return OK if the interrupt was registered
|
||||
*/
|
||||
int dev_register_interrupt(int irq);
|
||||
|
||||
/**
|
||||
* Unregister ourselves as a handler for any interrupt
|
||||
*/
|
||||
void dev_unregister_interrupt();
|
||||
|
||||
/**
|
||||
* Interrupt dispatcher
|
||||
*
|
||||
* @param irq The interrupt that has been triggered.
|
||||
* @param context Pointer to the interrupted context.
|
||||
*/
|
||||
static void dev_interrupt(int irq, void *context);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Abstract class for any character device
|
||||
*/
|
||||
class __EXPORT CDev : public Device
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param name Driver name
|
||||
* @param devname Device node name
|
||||
* @param irq Interrupt assigned to the device
|
||||
*/
|
||||
CDev(const char *name, const char *devname, int irq = 0);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~CDev();
|
||||
|
||||
virtual int init();
|
||||
|
||||
/**
|
||||
* Handle an open of the device.
|
||||
*
|
||||
* This function is called for every open of the device. The default
|
||||
* implementation maintains _open_count and always returns OK.
|
||||
*
|
||||
* @param filp Pointer to the NuttX file structure.
|
||||
* @return OK if the open is allowed, -errno otherwise.
|
||||
*/
|
||||
virtual int open(file_t *filp);
|
||||
|
||||
/**
|
||||
* Handle a close of the device.
|
||||
*
|
||||
* This function is called for every close of the device. The default
|
||||
* implementation maintains _open_count and returns OK as long as it is not zero.
|
||||
*
|
||||
* @param filp Pointer to the NuttX file structure.
|
||||
* @return OK if the close was successful, -errno otherwise.
|
||||
*/
|
||||
virtual int close(file_t *filp);
|
||||
|
||||
/**
|
||||
* Perform a read from the device.
|
||||
*
|
||||
* The default implementation returns -ENOSYS.
|
||||
*
|
||||
* @param filp Pointer to the NuttX file structure.
|
||||
* @param buffer Pointer to the buffer into which data should be placed.
|
||||
* @param buflen The number of bytes to be read.
|
||||
* @return The number of bytes read or -errno otherwise.
|
||||
*/
|
||||
virtual ssize_t read(file_t *filp, char *buffer, size_t buflen);
|
||||
|
||||
/**
|
||||
* Perform a write to the device.
|
||||
*
|
||||
* The default implementation returns -ENOSYS.
|
||||
*
|
||||
* @param filp Pointer to the NuttX file structure.
|
||||
* @param buffer Pointer to the buffer from which data should be read.
|
||||
* @param buflen The number of bytes to be written.
|
||||
* @return The number of bytes written or -errno otherwise.
|
||||
*/
|
||||
virtual ssize_t write(file_t *filp, const char *buffer, size_t buflen);
|
||||
|
||||
/**
|
||||
* Perform a logical seek operation on the device.
|
||||
*
|
||||
* The default implementation returns -ENOSYS.
|
||||
*
|
||||
* @param filp Pointer to the NuttX file structure.
|
||||
* @param offset The new file position relative to whence.
|
||||
* @param whence SEEK_OFS, SEEK_CUR or SEEK_END.
|
||||
* @return The previous offset, or -errno otherwise.
|
||||
*/
|
||||
virtual off_t seek(file_t *filp, off_t offset, int whence);
|
||||
|
||||
/**
|
||||
* Perform an ioctl operation on the device.
|
||||
*
|
||||
* The default implementation handles DIOC_GETPRIV, and otherwise
|
||||
* returns -ENOTTY. Subclasses should call the default implementation
|
||||
* for any command they do not handle themselves.
|
||||
*
|
||||
* @param filp Pointer to the NuttX file structure.
|
||||
* @param cmd The ioctl command value.
|
||||
* @param arg The ioctl argument value.
|
||||
* @return OK on success, or -errno otherwise.
|
||||
*/
|
||||
virtual int ioctl(file_t *filp, int cmd, unsigned long arg);
|
||||
|
||||
/**
|
||||
* Perform a poll setup/teardown operation.
|
||||
*
|
||||
* This is handled internally and should not normally be overridden.
|
||||
*
|
||||
* @param filp Pointer to the NuttX file structure.
|
||||
* @param fds Poll descriptor being waited on.
|
||||
* @param arg True if this is establishing a request, false if
|
||||
* it is being torn down.
|
||||
* @return OK on success, or -errno otherwise.
|
||||
*/
|
||||
virtual int poll(file_t *filp, struct pollfd *fds, bool setup);
|
||||
|
||||
/**
|
||||
* Test whether the device is currently open.
|
||||
*
|
||||
* This can be used to avoid tearing down a device that is still active.
|
||||
* Note - not virtual, cannot be overridden by a subclass.
|
||||
*
|
||||
* @return True if the device is currently open.
|
||||
*/
|
||||
bool is_open() { return _open_count > 0; }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Pointer to the default cdev file operations table; useful for
|
||||
* registering clone devices etc.
|
||||
*/
|
||||
static const struct file_operations fops;
|
||||
|
||||
/**
|
||||
* Check the current state of the device for poll events from the
|
||||
* perspective of the file.
|
||||
*
|
||||
* This function is called by the default poll() implementation when
|
||||
* a poll is set up to determine whether the poll should return immediately.
|
||||
*
|
||||
* The default implementation returns no events.
|
||||
*
|
||||
* @param filp The file that's interested.
|
||||
* @return The current set of poll events.
|
||||
*/
|
||||
virtual pollevent_t poll_state(file_t *filp);
|
||||
|
||||
/**
|
||||
* Report new poll events.
|
||||
*
|
||||
* This function should be called anytime the state of the device changes
|
||||
* in a fashion that might be interesting to a poll waiter.
|
||||
*
|
||||
* @param events The new event(s) being announced.
|
||||
*/
|
||||
virtual void poll_notify(pollevent_t events);
|
||||
|
||||
/**
|
||||
* Internal implementation of poll_notify.
|
||||
*
|
||||
* @param fds A poll waiter to notify.
|
||||
* @param events The event(s) to send to the waiter.
|
||||
*/
|
||||
virtual void poll_notify_one(px4_pollfd_struct_t *fds, pollevent_t events);
|
||||
|
||||
/**
|
||||
* Notification of the first open.
|
||||
*
|
||||
* This function is called when the device open count transitions from zero
|
||||
* to one. The driver lock is held for the duration of the call.
|
||||
*
|
||||
* The default implementation returns OK.
|
||||
*
|
||||
* @param filp Pointer to the NuttX file structure.
|
||||
* @return OK if the open should proceed, -errno otherwise.
|
||||
*/
|
||||
virtual int open_first(file_t *filp);
|
||||
|
||||
/**
|
||||
* Notification of the last close.
|
||||
*
|
||||
* This function is called when the device open count transitions from
|
||||
* one to zero. The driver lock is held for the duration of the call.
|
||||
*
|
||||
* The default implementation returns OK.
|
||||
*
|
||||
* @param filp Pointer to the NuttX file structure.
|
||||
* @return OK if the open should return OK, -errno otherwise.
|
||||
*/
|
||||
virtual int close_last(file_t *filp);
|
||||
|
||||
/**
|
||||
* Register a class device name, automatically adding device
|
||||
* class instance suffix if need be.
|
||||
*
|
||||
* @param class_devname Device class name
|
||||
* @return class_instamce Class instance created, or -errno on failure
|
||||
*/
|
||||
virtual int register_class_devname(const char *class_devname);
|
||||
|
||||
/**
|
||||
* Register a class device name, automatically adding device
|
||||
* class instance suffix if need be.
|
||||
*
|
||||
* @param class_devname Device class name
|
||||
* @param class_instance Device class instance from register_class_devname()
|
||||
* @return OK on success, -errno otherwise
|
||||
*/
|
||||
virtual int unregister_class_devname(const char *class_devname, unsigned class_instance);
|
||||
|
||||
/**
|
||||
* Get the device name.
|
||||
*
|
||||
* @return the file system string of the device handle
|
||||
*/
|
||||
const char* get_devname() { return _devname; }
|
||||
|
||||
bool _pub_blocked; /**< true if publishing should be blocked */
|
||||
|
||||
private:
|
||||
static const unsigned _max_pollwaiters = 8;
|
||||
|
||||
const char *_devname; /**< device node name */
|
||||
bool _registered; /**< true if device name was registered */
|
||||
unsigned _open_count; /**< number of successful opens */
|
||||
|
||||
struct pollfd *_pollset[_max_pollwaiters];
|
||||
|
||||
/**
|
||||
* Store a pollwaiter in a slot where we can find it later.
|
||||
*
|
||||
* Expands the pollset as required. Must be called with the driver locked.
|
||||
*
|
||||
* @return OK, or -errno on error.
|
||||
*/
|
||||
int store_poll_waiter(px4_pollfd_struct_t *fds);
|
||||
|
||||
/**
|
||||
* Remove a poll waiter.
|
||||
*
|
||||
* @return OK, or -errno on error.
|
||||
*/
|
||||
int remove_poll_waiter(struct pollfd *fds);
|
||||
|
||||
/* do not allow copying this class */
|
||||
CDev(const CDev&);
|
||||
CDev operator=(const CDev&);
|
||||
};
|
||||
|
||||
/**
|
||||
* Abstract class for character device accessed via PIO
|
||||
*/
|
||||
class __EXPORT PIO : public CDev
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param name Driver name
|
||||
* @param devname Device node name
|
||||
* @param base Base address of the device PIO area
|
||||
* @param irq Interrupt assigned to the device (or zero if none)
|
||||
*/
|
||||
PIO(const char *name,
|
||||
const char *devname,
|
||||
uint32_t base,
|
||||
int irq = 0);
|
||||
virtual ~PIO();
|
||||
|
||||
virtual int init();
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Read a register
|
||||
*
|
||||
* @param offset Register offset in bytes from the base address.
|
||||
*/
|
||||
uint32_t reg(uint32_t offset) {
|
||||
return *(volatile uint32_t *)(_base + offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a register
|
||||
*
|
||||
* @param offset Register offset in bytes from the base address.
|
||||
* @param value Value to write.
|
||||
*/
|
||||
void reg(uint32_t offset, uint32_t value) {
|
||||
*(volatile uint32_t *)(_base + offset) = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify a register
|
||||
*
|
||||
* Note that there is a risk of a race during the read/modify/write cycle
|
||||
* that must be taken care of by the caller.
|
||||
*
|
||||
* @param offset Register offset in bytes from the base address.
|
||||
* @param clearbits Bits to clear in the register
|
||||
* @param setbits Bits to set in the register
|
||||
*/
|
||||
void modify(uint32_t offset, uint32_t clearbits, uint32_t setbits) {
|
||||
uint32_t val = reg(offset);
|
||||
val &= ~clearbits;
|
||||
val |= setbits;
|
||||
reg(offset, val);
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t _base;
|
||||
};
|
||||
|
||||
} // namespace device
|
||||
|
||||
// class instance for primary driver of each class
|
||||
enum CLASS_DEVICE {
|
||||
CLASS_DEVICE_PRIMARY=0,
|
||||
CLASS_DEVICE_SECONDARY=1,
|
||||
CLASS_DEVICE_TERTIARY=2
|
||||
};
|
||||
|
||||
#endif /* _DEVICE_DEVICE_H */
|
||||
@@ -0,0 +1,131 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2012-2014 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file device.cpp
|
||||
*
|
||||
* Fundamental driver base class for the virtual device framework.
|
||||
*/
|
||||
|
||||
#include "device.h"
|
||||
|
||||
#include <px4_defines.h>
|
||||
#include <px4_posix.h>
|
||||
#include <drivers/drv_device.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace device
|
||||
{
|
||||
|
||||
Device::Device(const char *name) :
|
||||
// public
|
||||
// protected
|
||||
_name(name),
|
||||
_debug_enabled(false)
|
||||
{
|
||||
sem_init(&_lock, 0, 1);
|
||||
|
||||
/* setup a default device ID. When bus_type is UNKNOWN the
|
||||
other fields are invalid */
|
||||
_device_id.devid = 0;
|
||||
_device_id.devid_s.bus_type = DeviceBusType_UNKNOWN;
|
||||
_device_id.devid_s.bus = 0;
|
||||
_device_id.devid_s.address = 0;
|
||||
_device_id.devid_s.devtype = 0;
|
||||
}
|
||||
|
||||
Device::~Device()
|
||||
{
|
||||
sem_destroy(&_lock);
|
||||
}
|
||||
|
||||
int
|
||||
Device::init()
|
||||
{
|
||||
int ret = OK;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
Device::log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
PX4_INFO("[%s] ", _name);
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void
|
||||
Device::debug(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (_debug_enabled) {
|
||||
printf("<%s> ", _name);
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
Device::dev_read(unsigned offset, void *data, unsigned count)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int
|
||||
Device::dev_write(unsigned offset, void *data, unsigned count)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int
|
||||
Device::dev_ioctl(unsigned operation, unsigned &arg)
|
||||
{
|
||||
switch (operation) {
|
||||
case DEVIOCGDEVICEID:
|
||||
return (int)_device_id.devid;
|
||||
}
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
} // namespace device
|
||||
+7
-121
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
* Copyright (C) 2015 Mark Charlebois. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -30,124 +30,10 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* @file i2c.h
|
||||
*
|
||||
* Base class for devices connected via I2C.
|
||||
*/
|
||||
|
||||
#ifndef _DEVICE_I2C_H
|
||||
#define _DEVICE_I2C_H
|
||||
|
||||
#include "device.h"
|
||||
|
||||
#include <nuttx/i2c.h>
|
||||
|
||||
namespace device __EXPORT
|
||||
{
|
||||
|
||||
/**
|
||||
* Abstract class for character device on I2C
|
||||
*/
|
||||
class __EXPORT I2C : public CDev
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Get the address
|
||||
*/
|
||||
int16_t get_address() const { return _address; }
|
||||
|
||||
static int set_bus_clock(unsigned bus, unsigned clock_hz);
|
||||
|
||||
static unsigned int _bus_clocks[3];
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The number of times a read or write operation will be retried on
|
||||
* error.
|
||||
*/
|
||||
unsigned _retries;
|
||||
|
||||
/**
|
||||
* The I2C bus number the device is attached to.
|
||||
*/
|
||||
int _bus;
|
||||
|
||||
/**
|
||||
* @ Constructor
|
||||
*
|
||||
* @param name Driver name
|
||||
* @param devname Device node name
|
||||
* @param bus I2C bus on which the device lives
|
||||
* @param address I2C bus address, or zero if set_address will be used
|
||||
* @param frequency I2C bus frequency for the device (currently not used)
|
||||
* @param irq Interrupt assigned to the device (or zero if none)
|
||||
*/
|
||||
I2C(const char *name,
|
||||
const char *devname,
|
||||
int bus,
|
||||
uint16_t address,
|
||||
uint32_t frequency,
|
||||
int irq = 0);
|
||||
virtual ~I2C();
|
||||
|
||||
virtual int init();
|
||||
|
||||
/**
|
||||
* Check for the presence of the device on the bus.
|
||||
*/
|
||||
virtual int probe();
|
||||
|
||||
/**
|
||||
* Perform an I2C transaction to the device.
|
||||
*
|
||||
* At least one of send_len and recv_len must be non-zero.
|
||||
*
|
||||
* @param send Pointer to bytes to send.
|
||||
* @param send_len Number of bytes to send.
|
||||
* @param recv Pointer to buffer for bytes received.
|
||||
* @param recv_len Number of bytes to receive.
|
||||
* @return OK if the transfer was successful, -errno
|
||||
* otherwise.
|
||||
*/
|
||||
int transfer(const uint8_t *send, unsigned send_len,
|
||||
uint8_t *recv, unsigned recv_len);
|
||||
|
||||
/**
|
||||
* Perform a multi-part I2C transaction to the device.
|
||||
*
|
||||
* @param msgv An I2C message vector.
|
||||
* @param msgs The number of entries in the message vector.
|
||||
* @return OK if the transfer was successful, -errno
|
||||
* otherwise.
|
||||
*/
|
||||
int transfer(i2c_msg_s *msgv, unsigned msgs);
|
||||
|
||||
/**
|
||||
* Change the bus address.
|
||||
*
|
||||
* Most often useful during probe() when the driver is testing
|
||||
* several possible bus addresses.
|
||||
*
|
||||
* @param address The new bus address to set.
|
||||
*/
|
||||
void set_address(uint16_t address) {
|
||||
_address = address;
|
||||
_device_id.devid_s.address = _address;
|
||||
}
|
||||
|
||||
private:
|
||||
uint16_t _address;
|
||||
uint32_t _frequency;
|
||||
struct i2c_dev_s *_dev;
|
||||
|
||||
I2C(const device::I2C &);
|
||||
I2C operator=(const device::I2C &);
|
||||
};
|
||||
|
||||
} // namespace device
|
||||
|
||||
#endif /* _DEVICE_I2C_H */
|
||||
#ifdef __PX4_NUTTX
|
||||
#include "i2c_nuttx.h"
|
||||
#else
|
||||
#include "i2c_posix.h"
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file i2c.h
|
||||
*
|
||||
* Base class for devices connected via I2C.
|
||||
*/
|
||||
|
||||
#ifndef _DEVICE_I2C_H
|
||||
#define _DEVICE_I2C_H
|
||||
|
||||
#include "device.h"
|
||||
|
||||
#include <px4_i2c.h>
|
||||
|
||||
namespace device __EXPORT
|
||||
{
|
||||
|
||||
/**
|
||||
* Abstract class for character device on I2C
|
||||
*/
|
||||
class __EXPORT I2C : public CDev
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Get the address
|
||||
*/
|
||||
int16_t get_address() const { return _address; }
|
||||
|
||||
static int set_bus_clock(unsigned bus, unsigned clock_hz);
|
||||
|
||||
static unsigned int _bus_clocks[3];
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The number of times a read or write operation will be retried on
|
||||
* error.
|
||||
*/
|
||||
unsigned _retries;
|
||||
|
||||
/**
|
||||
* The I2C bus number the device is attached to.
|
||||
*/
|
||||
int _bus;
|
||||
|
||||
/**
|
||||
* @ Constructor
|
||||
*
|
||||
* @param name Driver name
|
||||
* @param devname Device node name
|
||||
* @param bus I2C bus on which the device lives
|
||||
* @param address I2C bus address, or zero if set_address will be used
|
||||
* @param frequency I2C bus frequency for the device (currently not used)
|
||||
* @param irq Interrupt assigned to the device (or zero if none)
|
||||
*/
|
||||
I2C(const char *name,
|
||||
const char *devname,
|
||||
int bus,
|
||||
uint16_t address,
|
||||
uint32_t frequency,
|
||||
int irq = 0);
|
||||
virtual ~I2C();
|
||||
|
||||
virtual int init();
|
||||
|
||||
/**
|
||||
* Check for the presence of the device on the bus.
|
||||
*/
|
||||
virtual int probe();
|
||||
|
||||
/**
|
||||
* Perform an I2C transaction to the device.
|
||||
*
|
||||
* At least one of send_len and recv_len must be non-zero.
|
||||
*
|
||||
* @param send Pointer to bytes to send.
|
||||
* @param send_len Number of bytes to send.
|
||||
* @param recv Pointer to buffer for bytes received.
|
||||
* @param recv_len Number of bytes to receive.
|
||||
* @return OK if the transfer was successful, -errno
|
||||
* otherwise.
|
||||
*/
|
||||
int transfer(const uint8_t *send, unsigned send_len,
|
||||
uint8_t *recv, unsigned recv_len);
|
||||
|
||||
/**
|
||||
* Perform a multi-part I2C transaction to the device.
|
||||
*
|
||||
* @param msgv An I2C message vector.
|
||||
* @param msgs The number of entries in the message vector.
|
||||
* @return OK if the transfer was successful, -errno
|
||||
* otherwise.
|
||||
*/
|
||||
int transfer(px4_i2c_msg_t *msgv, unsigned msgs);
|
||||
|
||||
/**
|
||||
* Change the bus address.
|
||||
*
|
||||
* Most often useful during probe() when the driver is testing
|
||||
* several possible bus addresses.
|
||||
*
|
||||
* @param address The new bus address to set.
|
||||
*/
|
||||
void set_address(uint16_t address) {
|
||||
_address = address;
|
||||
_device_id.devid_s.address = _address;
|
||||
}
|
||||
|
||||
private:
|
||||
uint16_t _address;
|
||||
uint32_t _frequency;
|
||||
px4_i2c_dev_t *_dev;
|
||||
|
||||
I2C(const device::I2C &);
|
||||
I2C operator=(const device::I2C &);
|
||||
};
|
||||
|
||||
} // namespace device
|
||||
|
||||
#endif /* _DEVICE_I2C_H */
|
||||
@@ -0,0 +1,263 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2012-2015 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file i2c.cpp
|
||||
*
|
||||
* Base class for devices attached via the I2C bus.
|
||||
*
|
||||
* @todo Bus frequency changes; currently we do nothing with the value
|
||||
* that is supplied. Should we just depend on the bus knowing?
|
||||
*/
|
||||
|
||||
#include "i2c.h"
|
||||
#ifdef __PX4_LINUX
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#define PX4_SIMULATE_I2C 1
|
||||
static int simulate = PX4_SIMULATE_I2C;
|
||||
|
||||
namespace device
|
||||
{
|
||||
|
||||
I2C::I2C(const char *name,
|
||||
const char *devname,
|
||||
int bus,
|
||||
uint16_t address) :
|
||||
// base class
|
||||
VDev(name, devname),
|
||||
// public
|
||||
// protected
|
||||
_retries(0),
|
||||
// private
|
||||
_bus(bus),
|
||||
_address(address),
|
||||
_fd(-1)
|
||||
{
|
||||
warnx("I2C::I2C name = %s devname = %s", name, devname);
|
||||
// fill in _device_id fields for a I2C device
|
||||
_device_id.devid_s.bus_type = DeviceBusType_I2C;
|
||||
_device_id.devid_s.bus = bus;
|
||||
_device_id.devid_s.address = address;
|
||||
// devtype needs to be filled in by the driver
|
||||
_device_id.devid_s.devtype = 0;
|
||||
}
|
||||
|
||||
I2C::~I2C()
|
||||
{
|
||||
if (_fd >= 0) {
|
||||
::close(_fd);
|
||||
_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
I2C::init()
|
||||
{
|
||||
int ret = PX4_OK;
|
||||
|
||||
// Assume the driver set the desired bus frequency. There is no standard
|
||||
// way to set it from user space.
|
||||
|
||||
// do base class init, which will create device node, etc
|
||||
ret = VDev::init();
|
||||
|
||||
if (ret != PX4_OK) {
|
||||
debug("VDev::init failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
_fd = px4_open(get_devname(), PX4_F_RDONLY | PX4_F_WRONLY);
|
||||
if (_fd < 0) {
|
||||
debug("px4_open failed of device %s", get_devname());
|
||||
return PX4_ERROR;
|
||||
}
|
||||
|
||||
#ifdef __PX4_QURT
|
||||
simulate = true;
|
||||
#endif
|
||||
|
||||
if (simulate) {
|
||||
_fd = 10000;
|
||||
}
|
||||
else {
|
||||
// Open the actual I2C device and map to the virtual dev name
|
||||
_fd = ::open(get_devname(), O_RDWR);
|
||||
if (_fd < 0) {
|
||||
warnx("could not open %s", get_devname());
|
||||
px4_errno = errno;
|
||||
return PX4_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
I2C::transfer(const uint8_t *send, unsigned send_len, uint8_t *recv, unsigned recv_len)
|
||||
{
|
||||
struct i2c_msg msgv[2];
|
||||
unsigned msgs;
|
||||
struct i2c_rdwr_ioctl_data packets;
|
||||
int ret;
|
||||
unsigned retry_count = 0;
|
||||
|
||||
if (_fd < 0) {
|
||||
warnx("I2C device not opened");
|
||||
return 1;
|
||||
}
|
||||
|
||||
do {
|
||||
// debug("transfer out %p/%u in %p/%u", send, send_len, recv, recv_len);
|
||||
msgs = 0;
|
||||
|
||||
if (send_len > 0) {
|
||||
msgv[msgs].addr = _address;
|
||||
msgv[msgs].flags = 0;
|
||||
msgv[msgs].buf = const_cast<uint8_t *>(send);
|
||||
msgv[msgs].len = send_len;
|
||||
msgs++;
|
||||
}
|
||||
|
||||
if (recv_len > 0) {
|
||||
msgv[msgs].addr = _address;
|
||||
msgv[msgs].flags = I2C_M_READ;
|
||||
msgv[msgs].buf = recv;
|
||||
msgv[msgs].len = recv_len;
|
||||
msgs++;
|
||||
}
|
||||
|
||||
if (msgs == 0)
|
||||
return -EINVAL;
|
||||
|
||||
packets.msgs = msgv;
|
||||
packets.nmsgs = msgs;
|
||||
|
||||
if (simulate) {
|
||||
//warnx("I2C SIM: transfer_4 on %s", get_devname());
|
||||
ret = PX4_OK;
|
||||
}
|
||||
else {
|
||||
ret = ::ioctl(_fd, I2C_RDWR, (unsigned long)&packets);
|
||||
if (ret < 0) {
|
||||
warnx("I2C transfer failed");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* success */
|
||||
if (ret == PX4_OK)
|
||||
break;
|
||||
|
||||
} while (retry_count++ < _retries);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
I2C::transfer(struct i2c_msg *msgv, unsigned msgs)
|
||||
{
|
||||
struct i2c_rdwr_ioctl_data packets;
|
||||
int ret;
|
||||
unsigned retry_count = 0;
|
||||
|
||||
/* force the device address into the message vector */
|
||||
for (unsigned i = 0; i < msgs; i++)
|
||||
msgv[i].addr = _address;
|
||||
|
||||
do {
|
||||
packets.msgs = msgv;
|
||||
packets.nmsgs = msgs;
|
||||
|
||||
if (simulate) {
|
||||
warnx("I2C SIM: transfer_2 on %s", get_devname());
|
||||
ret = PX4_OK;
|
||||
}
|
||||
else {
|
||||
ret = ::ioctl(_fd, I2C_RDWR, (unsigned long)&packets);
|
||||
}
|
||||
if (ret < 0) {
|
||||
warnx("I2C transfer failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* success */
|
||||
if (ret == PX4_OK)
|
||||
break;
|
||||
|
||||
} while (retry_count++ < _retries);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int I2C::ioctl(device::file_t *filp, int cmd, unsigned long arg)
|
||||
{
|
||||
//struct i2c_rdwr_ioctl_data *packets = (i2c_rdwr_ioctl_data *)(void *)arg;
|
||||
|
||||
switch (cmd) {
|
||||
case I2C_RDWR:
|
||||
warnx("Use I2C::transfer, not ioctl");
|
||||
return 0;
|
||||
default:
|
||||
/* give it to the superclass */
|
||||
return VDev::ioctl(filp, cmd, arg);
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t I2C::read(file_t *filp, char *buffer, size_t buflen)
|
||||
{
|
||||
if (simulate) {
|
||||
// FIXME no idea what this should be
|
||||
warnx ("2C SIM I2C::read");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ::read(_fd, buffer, buflen);
|
||||
}
|
||||
|
||||
ssize_t I2C::write(file_t *filp, const char *buffer, size_t buflen)
|
||||
{
|
||||
if (simulate) {
|
||||
warnx ("2C SIM I2C::write");
|
||||
return buflen;
|
||||
}
|
||||
|
||||
return ::write(_fd, buffer, buflen);
|
||||
}
|
||||
|
||||
} // namespace device
|
||||
@@ -0,0 +1,136 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file i2c.h
|
||||
*
|
||||
* Base class for devices connected via I2C.
|
||||
*/
|
||||
|
||||
#ifndef _DEVICE_I2C_H
|
||||
#define _DEVICE_I2C_H
|
||||
|
||||
#include "vdev.h"
|
||||
|
||||
#include <px4_i2c.h>
|
||||
#ifdef __PX4_LINUX
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
#endif
|
||||
#include <string>
|
||||
|
||||
namespace device __EXPORT
|
||||
{
|
||||
|
||||
/**
|
||||
* Abstract class for character device on I2C
|
||||
*/
|
||||
class __EXPORT I2C : public VDev
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Get the address
|
||||
*/
|
||||
int16_t get_address() const { return _address; }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The number of times a read or write operation will be retried on
|
||||
* error.
|
||||
*/
|
||||
unsigned _retries;
|
||||
|
||||
/**
|
||||
* The I2C bus number the device is attached to.
|
||||
*/
|
||||
int _bus;
|
||||
|
||||
/**
|
||||
* @ Constructor
|
||||
*
|
||||
* @param name Driver name
|
||||
* @param devname Device node name
|
||||
* @param bus I2C bus on which the device lives
|
||||
* @param address I2C bus address, or zero if set_address will be used
|
||||
*/
|
||||
I2C(const char *name,
|
||||
const char *devname,
|
||||
int bus,
|
||||
uint16_t address);
|
||||
virtual ~I2C();
|
||||
|
||||
virtual int init();
|
||||
|
||||
virtual ssize_t read(file_t *handlep, char *buffer, size_t buflen);
|
||||
virtual ssize_t write(file_t *handlep, const char *buffer, size_t buflen);
|
||||
virtual int ioctl(file_t *handlep, int cmd, unsigned long arg);
|
||||
|
||||
/**
|
||||
* Perform an I2C transaction to the device.
|
||||
*
|
||||
* At least one of send_len and recv_len must be non-zero.
|
||||
*
|
||||
* @param send Pointer to bytes to send.
|
||||
* @param send_len Number of bytes to send.
|
||||
* @param recv Pointer to buffer for bytes received.
|
||||
* @param recv_len Number of bytes to receive.
|
||||
* @return OK if the transfer was successful, -errno
|
||||
* otherwise.
|
||||
*/
|
||||
int transfer(const uint8_t *send, unsigned send_len,
|
||||
uint8_t *recv, unsigned recv_len);
|
||||
|
||||
/**
|
||||
* Perform a multi-part I2C transaction to the device.
|
||||
*
|
||||
* @param msgv An I2C message vector.
|
||||
* @param msgs The number of entries in the message vector.
|
||||
* @return OK if the transfer was successful, -errno
|
||||
* otherwise.
|
||||
*/
|
||||
int transfer(struct i2c_msg *msgv, unsigned msgs);
|
||||
|
||||
private:
|
||||
uint16_t _address;
|
||||
int _fd;
|
||||
std::string _dname;
|
||||
|
||||
I2C(const device::I2C&);
|
||||
I2C operator=(const device::I2C&);
|
||||
};
|
||||
|
||||
} // namespace device
|
||||
|
||||
#endif /* _DEVICE_I2C_H */
|
||||
@@ -35,8 +35,20 @@
|
||||
# Build the device driver framework.
|
||||
#
|
||||
|
||||
SRCS = cdev.cpp \
|
||||
device.cpp \
|
||||
i2c.cpp \
|
||||
ifeq ($(PX4_TARGET_OS),nuttx)
|
||||
SRCS = \
|
||||
device_nuttx.cpp \
|
||||
cdev.cpp \
|
||||
i2c_nuttx.cpp \
|
||||
pio.cpp \
|
||||
spi.cpp
|
||||
spi.cpp
|
||||
else
|
||||
SRCS = \
|
||||
device_posix.cpp \
|
||||
vdev.cpp \
|
||||
vfile.cpp \
|
||||
vdev_posix.cpp \
|
||||
i2c_posix.cpp \
|
||||
sim.cpp \
|
||||
ringbuffer.cpp
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,400 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2013 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file ringbuffer.cpp
|
||||
*
|
||||
* A flexible ringbuffer class.
|
||||
*/
|
||||
|
||||
#include "ringbuffer.h"
|
||||
#include <string.h>
|
||||
|
||||
RingBuffer::RingBuffer(unsigned num_items, size_t item_size) :
|
||||
_num_items(num_items),
|
||||
_item_size(item_size),
|
||||
_buf(new char[(_num_items+1) * item_size]),
|
||||
_head(_num_items),
|
||||
_tail(_num_items)
|
||||
{}
|
||||
|
||||
RingBuffer::~RingBuffer()
|
||||
{
|
||||
if (_buf != nullptr)
|
||||
delete[] _buf;
|
||||
}
|
||||
|
||||
unsigned
|
||||
RingBuffer::_next(unsigned index)
|
||||
{
|
||||
return (0 == index) ? _num_items : (index - 1);
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::empty()
|
||||
{
|
||||
return _tail == _head;
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::full()
|
||||
{
|
||||
return _next(_head) == _tail;
|
||||
}
|
||||
|
||||
unsigned
|
||||
RingBuffer::size()
|
||||
{
|
||||
return (_buf != nullptr) ? _num_items : 0;
|
||||
}
|
||||
|
||||
void
|
||||
RingBuffer::flush()
|
||||
{
|
||||
while (!empty())
|
||||
get(NULL);
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::put(const void *val, size_t val_size)
|
||||
{
|
||||
unsigned next = _next(_head);
|
||||
if (next != _tail) {
|
||||
if ((val_size == 0) || (val_size > _item_size))
|
||||
val_size = _item_size;
|
||||
memcpy(&_buf[_head * _item_size], val, val_size);
|
||||
_head = next;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::put(int8_t val)
|
||||
{
|
||||
return put(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::put(uint8_t val)
|
||||
{
|
||||
return put(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::put(int16_t val)
|
||||
{
|
||||
return put(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::put(uint16_t val)
|
||||
{
|
||||
return put(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::put(int32_t val)
|
||||
{
|
||||
return put(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::put(uint32_t val)
|
||||
{
|
||||
return put(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::put(int64_t val)
|
||||
{
|
||||
return put(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::put(uint64_t val)
|
||||
{
|
||||
return put(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::put(float val)
|
||||
{
|
||||
return put(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::put(double val)
|
||||
{
|
||||
return put(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::force(const void *val, size_t val_size)
|
||||
{
|
||||
bool overwrote = false;
|
||||
|
||||
for (;;) {
|
||||
if (put(val, val_size))
|
||||
break;
|
||||
get(NULL);
|
||||
overwrote = true;
|
||||
}
|
||||
return overwrote;
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::force(int8_t val)
|
||||
{
|
||||
return force(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::force(uint8_t val)
|
||||
{
|
||||
return force(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::force(int16_t val)
|
||||
{
|
||||
return force(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::force(uint16_t val)
|
||||
{
|
||||
return force(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::force(int32_t val)
|
||||
{
|
||||
return force(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::force(uint32_t val)
|
||||
{
|
||||
return force(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::force(int64_t val)
|
||||
{
|
||||
return force(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::force(uint64_t val)
|
||||
{
|
||||
return force(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::force(float val)
|
||||
{
|
||||
return force(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::force(double val)
|
||||
{
|
||||
return force(&val, sizeof(val));
|
||||
}
|
||||
|
||||
// FIXME - clang crashes on this get() call
|
||||
#ifdef __PX4_QURT
|
||||
#define __PX4_SBCAP my_sync_bool_compare_and_swap
|
||||
static inline bool my_sync_bool_compare_and_swap(volatile unsigned *a, unsigned b, unsigned c)
|
||||
{
|
||||
if (*a == b) {
|
||||
*a = c;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
#define __PX4_SBCAP __sync_bool_compare_and_swap
|
||||
#endif
|
||||
bool
|
||||
RingBuffer::get(void *val, size_t val_size)
|
||||
{
|
||||
if (_tail != _head) {
|
||||
unsigned candidate;
|
||||
unsigned next;
|
||||
|
||||
if ((val_size == 0) || (val_size > _item_size))
|
||||
val_size = _item_size;
|
||||
|
||||
do {
|
||||
/* decide which element we think we're going to read */
|
||||
candidate = _tail;
|
||||
|
||||
/* and what the corresponding next index will be */
|
||||
next = _next(candidate);
|
||||
|
||||
/* go ahead and read from this index */
|
||||
if (val != NULL)
|
||||
memcpy(val, &_buf[candidate * _item_size], val_size);
|
||||
|
||||
/* if the tail pointer didn't change, we got our item */
|
||||
} while (!__PX4_SBCAP(&_tail, candidate, next));
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::get(int8_t &val)
|
||||
{
|
||||
return get(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::get(uint8_t &val)
|
||||
{
|
||||
return get(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::get(int16_t &val)
|
||||
{
|
||||
return get(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::get(uint16_t &val)
|
||||
{
|
||||
return get(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::get(int32_t &val)
|
||||
{
|
||||
return get(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::get(uint32_t &val)
|
||||
{
|
||||
return get(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::get(int64_t &val)
|
||||
{
|
||||
return get(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::get(uint64_t &val)
|
||||
{
|
||||
return get(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::get(float &val)
|
||||
{
|
||||
return get(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::get(double &val)
|
||||
{
|
||||
return get(&val, sizeof(val));
|
||||
}
|
||||
|
||||
unsigned
|
||||
RingBuffer::space(void)
|
||||
{
|
||||
unsigned tail, head;
|
||||
|
||||
/*
|
||||
* Make a copy of the head/tail pointers in a fashion that
|
||||
* may err on the side of under-estimating the free space
|
||||
* in the buffer in the case that the buffer is being updated
|
||||
* asynchronously with our check.
|
||||
* If the head pointer changes (reducing space) while copying,
|
||||
* re-try the copy.
|
||||
*/
|
||||
do {
|
||||
head = _head;
|
||||
tail = _tail;
|
||||
} while (head != _head);
|
||||
|
||||
return (tail >= head) ? (_num_items - (tail - head)) : (head - tail - 1);
|
||||
}
|
||||
|
||||
unsigned
|
||||
RingBuffer::count(void)
|
||||
{
|
||||
/*
|
||||
* Note that due to the conservative nature of space(), this may
|
||||
* over-estimate the number of items in the buffer.
|
||||
*/
|
||||
return _num_items - space();
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::resize(unsigned new_size)
|
||||
{
|
||||
char *old_buffer;
|
||||
char *new_buffer = new char [(new_size+1) * _item_size];
|
||||
if (new_buffer == nullptr) {
|
||||
return false;
|
||||
}
|
||||
old_buffer = _buf;
|
||||
_buf = new_buffer;
|
||||
_num_items = new_size;
|
||||
_head = new_size;
|
||||
_tail = new_size;
|
||||
delete[] old_buffer;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
RingBuffer::print_info(const char *name)
|
||||
{
|
||||
printf("%s %u/%lu (%u/%u @ %p)\n",
|
||||
name,
|
||||
_num_items,
|
||||
(unsigned long)_num_items * _item_size,
|
||||
_head,
|
||||
_tail,
|
||||
_buf);
|
||||
}
|
||||
+10
-343
@@ -39,6 +39,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
class RingBuffer {
|
||||
public:
|
||||
RingBuffer(unsigned ring_size, size_t entry_size);
|
||||
@@ -168,346 +172,9 @@ private:
|
||||
RingBuffer operator=(const RingBuffer&);
|
||||
};
|
||||
|
||||
RingBuffer::RingBuffer(unsigned num_items, size_t item_size) :
|
||||
_num_items(num_items),
|
||||
_item_size(item_size),
|
||||
_buf(new char[(_num_items+1) * item_size]),
|
||||
_head(_num_items),
|
||||
_tail(_num_items)
|
||||
{}
|
||||
|
||||
RingBuffer::~RingBuffer()
|
||||
{
|
||||
if (_buf != nullptr)
|
||||
delete[] _buf;
|
||||
}
|
||||
|
||||
unsigned
|
||||
RingBuffer::_next(unsigned index)
|
||||
{
|
||||
return (0 == index) ? _num_items : (index - 1);
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::empty()
|
||||
{
|
||||
return _tail == _head;
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::full()
|
||||
{
|
||||
return _next(_head) == _tail;
|
||||
}
|
||||
|
||||
unsigned
|
||||
RingBuffer::size()
|
||||
{
|
||||
return (_buf != nullptr) ? _num_items : 0;
|
||||
}
|
||||
|
||||
void
|
||||
RingBuffer::flush()
|
||||
{
|
||||
while (!empty())
|
||||
get(NULL);
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::put(const void *val, size_t val_size)
|
||||
{
|
||||
unsigned next = _next(_head);
|
||||
if (next != _tail) {
|
||||
if ((val_size == 0) || (val_size > _item_size))
|
||||
val_size = _item_size;
|
||||
memcpy(&_buf[_head * _item_size], val, val_size);
|
||||
_head = next;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::put(int8_t val)
|
||||
{
|
||||
return put(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::put(uint8_t val)
|
||||
{
|
||||
return put(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::put(int16_t val)
|
||||
{
|
||||
return put(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::put(uint16_t val)
|
||||
{
|
||||
return put(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::put(int32_t val)
|
||||
{
|
||||
return put(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::put(uint32_t val)
|
||||
{
|
||||
return put(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::put(int64_t val)
|
||||
{
|
||||
return put(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::put(uint64_t val)
|
||||
{
|
||||
return put(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::put(float val)
|
||||
{
|
||||
return put(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::put(double val)
|
||||
{
|
||||
return put(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::force(const void *val, size_t val_size)
|
||||
{
|
||||
bool overwrote = false;
|
||||
|
||||
for (;;) {
|
||||
if (put(val, val_size))
|
||||
break;
|
||||
get(NULL);
|
||||
overwrote = true;
|
||||
}
|
||||
return overwrote;
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::force(int8_t val)
|
||||
{
|
||||
return force(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::force(uint8_t val)
|
||||
{
|
||||
return force(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::force(int16_t val)
|
||||
{
|
||||
return force(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::force(uint16_t val)
|
||||
{
|
||||
return force(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::force(int32_t val)
|
||||
{
|
||||
return force(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::force(uint32_t val)
|
||||
{
|
||||
return force(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::force(int64_t val)
|
||||
{
|
||||
return force(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::force(uint64_t val)
|
||||
{
|
||||
return force(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::force(float val)
|
||||
{
|
||||
return force(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::force(double val)
|
||||
{
|
||||
return force(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::get(void *val, size_t val_size)
|
||||
{
|
||||
if (_tail != _head) {
|
||||
unsigned candidate;
|
||||
unsigned next;
|
||||
|
||||
if ((val_size == 0) || (val_size > _item_size))
|
||||
val_size = _item_size;
|
||||
|
||||
do {
|
||||
/* decide which element we think we're going to read */
|
||||
candidate = _tail;
|
||||
|
||||
/* and what the corresponding next index will be */
|
||||
next = _next(candidate);
|
||||
|
||||
/* go ahead and read from this index */
|
||||
if (val != NULL)
|
||||
memcpy(val, &_buf[candidate * _item_size], val_size);
|
||||
|
||||
/* if the tail pointer didn't change, we got our item */
|
||||
} while (!__sync_bool_compare_and_swap(&_tail, candidate, next));
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::get(int8_t &val)
|
||||
{
|
||||
return get(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::get(uint8_t &val)
|
||||
{
|
||||
return get(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::get(int16_t &val)
|
||||
{
|
||||
return get(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::get(uint16_t &val)
|
||||
{
|
||||
return get(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::get(int32_t &val)
|
||||
{
|
||||
return get(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::get(uint32_t &val)
|
||||
{
|
||||
return get(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::get(int64_t &val)
|
||||
{
|
||||
return get(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::get(uint64_t &val)
|
||||
{
|
||||
return get(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::get(float &val)
|
||||
{
|
||||
return get(&val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::get(double &val)
|
||||
{
|
||||
return get(&val, sizeof(val));
|
||||
}
|
||||
|
||||
unsigned
|
||||
RingBuffer::space(void)
|
||||
{
|
||||
unsigned tail, head;
|
||||
|
||||
/*
|
||||
* Make a copy of the head/tail pointers in a fashion that
|
||||
* may err on the side of under-estimating the free space
|
||||
* in the buffer in the case that the buffer is being updated
|
||||
* asynchronously with our check.
|
||||
* If the head pointer changes (reducing space) while copying,
|
||||
* re-try the copy.
|
||||
*/
|
||||
do {
|
||||
head = _head;
|
||||
tail = _tail;
|
||||
} while (head != _head);
|
||||
|
||||
return (tail >= head) ? (_num_items - (tail - head)) : (head - tail - 1);
|
||||
}
|
||||
|
||||
unsigned
|
||||
RingBuffer::count(void)
|
||||
{
|
||||
/*
|
||||
* Note that due to the conservative nature of space(), this may
|
||||
* over-estimate the number of items in the buffer.
|
||||
*/
|
||||
return _num_items - space();
|
||||
}
|
||||
|
||||
bool
|
||||
RingBuffer::resize(unsigned new_size)
|
||||
{
|
||||
char *old_buffer;
|
||||
char *new_buffer = new char [(new_size+1) * _item_size];
|
||||
if (new_buffer == nullptr) {
|
||||
return false;
|
||||
}
|
||||
old_buffer = _buf;
|
||||
_buf = new_buffer;
|
||||
_num_items = new_size;
|
||||
_head = new_size;
|
||||
_tail = new_size;
|
||||
delete[] old_buffer;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
RingBuffer::print_info(const char *name)
|
||||
{
|
||||
printf("%s %u/%u (%u/%u @ %p)\n",
|
||||
name,
|
||||
_num_items,
|
||||
_num_items * _item_size,
|
||||
_head,
|
||||
_tail,
|
||||
_buf);
|
||||
}
|
||||
#ifdef __PX4_NUTTX
|
||||
// Not sure why NuttX requires these to be defined in the header file
|
||||
// but on other targets it causes a problem with multiple definitions
|
||||
// at link time
|
||||
#include "ringbuffer.cpp"
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2012-2015 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file sim.cpp
|
||||
*
|
||||
* Base class for simulated devices.
|
||||
*
|
||||
* @todo Bus frequency changes; currently we do nothing with the value
|
||||
* that is supplied. Should we just depend on the bus knowing?
|
||||
*/
|
||||
|
||||
#include <px4_log.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include "sim.h"
|
||||
|
||||
namespace device
|
||||
{
|
||||
|
||||
SIM::SIM(const char *name,
|
||||
const char *devname,
|
||||
int bus,
|
||||
uint16_t address) :
|
||||
// base class
|
||||
Device(name),
|
||||
// public
|
||||
// protected
|
||||
// private
|
||||
_bus(bus),
|
||||
_address(address),
|
||||
_devname(devname)
|
||||
{
|
||||
|
||||
PX4_DEBUG("SIM::SIM name = %s devname = %s", name, devname);
|
||||
// fill in _device_id fields for a SIM device
|
||||
_device_id.devid_s.bus_type = DeviceBusType_SIM;
|
||||
_device_id.devid_s.bus = bus;
|
||||
_device_id.devid_s.address = address;
|
||||
// devtype needs to be filled in by the driver
|
||||
_device_id.devid_s.devtype = 0;
|
||||
}
|
||||
|
||||
SIM::~SIM()
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
SIM::init()
|
||||
{
|
||||
int ret = PX4_OK;
|
||||
|
||||
// Assume the driver set the desired bus frequency. There is no standard
|
||||
// way to set it from user space.
|
||||
|
||||
// do base class init, which registers the virtual driver
|
||||
ret = Device::init();
|
||||
|
||||
if (ret != PX4_OK) {
|
||||
PX4_ERR("VDev::init failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
SIM::transfer(const uint8_t *send, unsigned send_len, uint8_t *recv, unsigned recv_len)
|
||||
{
|
||||
if (send_len > 0) {
|
||||
PX4_DEBUG("SIM: sending %d bytes", send_len);
|
||||
}
|
||||
|
||||
if (recv_len > 0) {
|
||||
PX4_DEBUG("SIM: receiving %d bytes", recv_len);
|
||||
|
||||
// TODO - write data to recv;
|
||||
}
|
||||
|
||||
PX4_DEBUG("I2C SIM: transfer_4 on %s", _devname);
|
||||
|
||||
return PX4_OK;
|
||||
}
|
||||
|
||||
} // namespace device
|
||||
@@ -0,0 +1,112 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file sim.h
|
||||
*
|
||||
* Base class for devices on simulation bus.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "vdev.h"
|
||||
|
||||
namespace device __EXPORT
|
||||
{
|
||||
|
||||
/**
|
||||
* Abstract class for character device on SIM
|
||||
*/
|
||||
class __EXPORT SIM : public Device
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Get the address
|
||||
*/
|
||||
int16_t get_address() const { return _address; }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The number of times a read or write operation will be retried on
|
||||
* error.
|
||||
*/
|
||||
unsigned _retries;
|
||||
|
||||
/**
|
||||
* The SIM bus number the device is attached to.
|
||||
*/
|
||||
int _bus;
|
||||
|
||||
/**
|
||||
* @ Constructor
|
||||
*
|
||||
* @param name Driver name
|
||||
* @param devname Device node name
|
||||
* @param bus SIM bus on which the device lives
|
||||
* @param address SIM bus address, or zero if set_address will be used
|
||||
*/
|
||||
SIM(const char *name,
|
||||
const char *devname,
|
||||
int bus,
|
||||
uint16_t address);
|
||||
virtual ~SIM();
|
||||
|
||||
virtual int init();
|
||||
|
||||
/**
|
||||
* Perform an SIM transaction to the device.
|
||||
*
|
||||
* At least one of send_len and recv_len must be non-zero.
|
||||
*
|
||||
* @param send Pointer to bytes to send.
|
||||
* @param send_len Number of bytes to send.
|
||||
* @param recv Pointer to buffer for bytes received.
|
||||
* @param recv_len Number of bytes to receive.
|
||||
* @return OK if the transfer was successful, -errno
|
||||
* otherwise.
|
||||
*/
|
||||
virtual int transfer(const uint8_t *send, unsigned send_len,
|
||||
uint8_t *recv, unsigned recv_len);
|
||||
|
||||
private:
|
||||
uint16_t _address;
|
||||
const char * _devname;
|
||||
|
||||
SIM(const device::SIM&);
|
||||
SIM operator=(const device::SIM&);
|
||||
};
|
||||
|
||||
} // namespace device
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
#include "device.h"
|
||||
|
||||
#include <nuttx/spi.h>
|
||||
#include <px4_spi.h>
|
||||
|
||||
namespace device __EXPORT
|
||||
{
|
||||
@@ -50,7 +50,11 @@ namespace device __EXPORT
|
||||
/**
|
||||
* Abstract class for character device on SPI
|
||||
*/
|
||||
#ifdef __PX4_NUTTX
|
||||
class __EXPORT SPI : public CDev
|
||||
#else
|
||||
class __EXPORT SPI : public VDev
|
||||
#endif
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,524 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2012-2014 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file vcdev.cpp
|
||||
*
|
||||
* Virtual character device base class.
|
||||
*/
|
||||
|
||||
#include "px4_posix.h"
|
||||
#include "vdev.h"
|
||||
#include "drivers/drv_device.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace device
|
||||
{
|
||||
|
||||
int px4_errno;
|
||||
|
||||
struct px4_dev_t {
|
||||
char *name;
|
||||
void *cdev;
|
||||
|
||||
px4_dev_t(const char *n, void *c) : cdev(c) {
|
||||
name = strdup(n);
|
||||
}
|
||||
|
||||
~px4_dev_t() { free(name); }
|
||||
|
||||
private:
|
||||
px4_dev_t() {}
|
||||
};
|
||||
|
||||
#define PX4_MAX_DEV 30
|
||||
static px4_dev_t *devmap[PX4_MAX_DEV];
|
||||
|
||||
/*
|
||||
* The standard NuttX operation dispatch table can't call C++ member functions
|
||||
* directly, so we have to bounce them through this dispatch table.
|
||||
*/
|
||||
|
||||
VDev::VDev(const char *name,
|
||||
const char *devname) :
|
||||
// base class
|
||||
Device(name),
|
||||
// public
|
||||
// protected
|
||||
_pub_blocked(false),
|
||||
// private
|
||||
_devname(devname),
|
||||
_registered(false),
|
||||
_open_count(0)
|
||||
{
|
||||
PX4_DEBUG("VDev::VDev");
|
||||
for (unsigned i = 0; i < _max_pollwaiters; i++)
|
||||
_pollset[i] = nullptr;
|
||||
}
|
||||
|
||||
VDev::~VDev()
|
||||
{
|
||||
PX4_DEBUG("VDev::~VDev");
|
||||
if (_registered)
|
||||
unregister_driver(_devname);
|
||||
}
|
||||
|
||||
int
|
||||
VDev::register_class_devname(const char *class_devname)
|
||||
{
|
||||
PX4_DEBUG("VDev::register_class_devname");
|
||||
if (class_devname == nullptr) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int class_instance = 0;
|
||||
int ret = -ENOSPC;
|
||||
|
||||
while (class_instance < 4) {
|
||||
char name[32];
|
||||
snprintf(name, sizeof(name), "%s%d", class_devname, class_instance);
|
||||
ret = register_driver(name, (void *)this);
|
||||
if (ret == OK) break;
|
||||
class_instance++;
|
||||
}
|
||||
|
||||
if (class_instance == 4) {
|
||||
return ret;
|
||||
}
|
||||
return class_instance;
|
||||
}
|
||||
|
||||
int
|
||||
VDev::register_driver(const char *name, void *data)
|
||||
{
|
||||
PX4_DEBUG("VDev::register_driver");
|
||||
int ret = -ENOSPC;
|
||||
|
||||
if (name == NULL || data == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
// Make sure the device does not already exist
|
||||
// FIXME - convert this to a map for efficiency
|
||||
for (int i=0;i<PX4_MAX_DEV; ++i) {
|
||||
if (devmap[i] && (strcmp(devmap[i]->name,name) == 0)) {
|
||||
return -EEXIST;
|
||||
}
|
||||
}
|
||||
for (int i=0;i<PX4_MAX_DEV; ++i) {
|
||||
if (devmap[i] == NULL) {
|
||||
devmap[i] = new px4_dev_t(name, (void *)data);
|
||||
PX4_DEBUG("Registered DEV %s", name);
|
||||
ret = PX4_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
VDev::unregister_driver(const char *name)
|
||||
{
|
||||
PX4_DEBUG("VDev::unregister_driver");
|
||||
int ret = -ENOSPC;
|
||||
|
||||
if (name == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
for (int i=0;i<PX4_MAX_DEV; ++i) {
|
||||
if (devmap[i] && (strcmp(name, devmap[i]->name) == 0)) {
|
||||
delete devmap[i];
|
||||
devmap[i] = NULL;
|
||||
PX4_DEBUG("Unregistered DEV %s", name);
|
||||
ret = PX4_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
VDev::unregister_class_devname(const char *class_devname, unsigned class_instance)
|
||||
{
|
||||
PX4_DEBUG("VDev::unregister_class_devname");
|
||||
char name[32];
|
||||
snprintf(name, sizeof(name), "%s%u", class_devname, class_instance);
|
||||
for (int i=0;i<PX4_MAX_DEV; ++i) {
|
||||
if (devmap[i] && strcmp(devmap[i]->name,name) == 0) {
|
||||
delete devmap[i];
|
||||
PX4_DEBUG("Unregistered class DEV %s", name);
|
||||
devmap[i] = NULL;
|
||||
return PX4_OK;
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int
|
||||
VDev::init()
|
||||
{
|
||||
PX4_DEBUG("VDev::init");
|
||||
|
||||
// base class init first
|
||||
int ret = Device::init();
|
||||
|
||||
if (ret != PX4_OK)
|
||||
goto out;
|
||||
|
||||
// now register the driver
|
||||
if (_devname != nullptr) {
|
||||
ret = register_driver(_devname, (void *)this);
|
||||
|
||||
if (ret != PX4_OK)
|
||||
goto out;
|
||||
|
||||
_registered = true;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Default implementations of the character device interface
|
||||
*/
|
||||
int
|
||||
VDev::open(file_t *filep)
|
||||
{
|
||||
PX4_DEBUG("VDev::open");
|
||||
int ret = PX4_OK;
|
||||
|
||||
lock();
|
||||
/* increment the open count */
|
||||
_open_count++;
|
||||
|
||||
if (_open_count == 1) {
|
||||
|
||||
/* first-open callback may decline the open */
|
||||
ret = open_first(filep);
|
||||
|
||||
if (ret != PX4_OK)
|
||||
_open_count--;
|
||||
}
|
||||
|
||||
unlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
VDev::open_first(file_t *filep)
|
||||
{
|
||||
PX4_DEBUG("VDev::open_first");
|
||||
return PX4_OK;
|
||||
}
|
||||
|
||||
int
|
||||
VDev::close(file_t *filep)
|
||||
{
|
||||
PX4_DEBUG("VDev::close");
|
||||
int ret = PX4_OK;
|
||||
|
||||
lock();
|
||||
|
||||
if (_open_count > 0) {
|
||||
/* decrement the open count */
|
||||
_open_count--;
|
||||
|
||||
/* callback cannot decline the close */
|
||||
if (_open_count == 0)
|
||||
ret = close_last(filep);
|
||||
|
||||
} else {
|
||||
ret = -EBADF;
|
||||
}
|
||||
|
||||
unlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
VDev::close_last(file_t *filep)
|
||||
{
|
||||
PX4_DEBUG("VDev::close_last");
|
||||
return PX4_OK;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
VDev::read(file_t *filep, char *buffer, size_t buflen)
|
||||
{
|
||||
PX4_DEBUG("VDev::read");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
VDev::write(file_t *filep, const char *buffer, size_t buflen)
|
||||
{
|
||||
PX4_DEBUG("VDev::write");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
off_t
|
||||
VDev::seek(file_t *filep, off_t offset, int whence)
|
||||
{
|
||||
PX4_DEBUG("VDev::seek");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int
|
||||
VDev::ioctl(file_t *filep, int cmd, unsigned long arg)
|
||||
{
|
||||
PX4_DEBUG("VDev::ioctl");
|
||||
int ret = -ENOTTY;
|
||||
|
||||
switch (cmd) {
|
||||
|
||||
/* fetch a pointer to the driver's private data */
|
||||
case DIOC_GETPRIV:
|
||||
*(void **)(uintptr_t)arg = (void *)this;
|
||||
ret = PX4_OK;
|
||||
break;
|
||||
case DEVIOCSPUBBLOCK:
|
||||
_pub_blocked = (arg != 0);
|
||||
ret = PX4_OK;
|
||||
break;
|
||||
case DEVIOCGPUBBLOCK:
|
||||
ret = _pub_blocked;
|
||||
break;
|
||||
case DEVIOCGDEVICEID:
|
||||
ret = (int)_device_id.devid;
|
||||
PX4_INFO("IOCTL DEVIOCGDEVICEID %d", ret);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
VDev::poll(file_t *filep, px4_pollfd_struct_t *fds, bool setup)
|
||||
{
|
||||
PX4_DEBUG("VDev::Poll %s", setup ? "setup" : "teardown");
|
||||
int ret = PX4_OK;
|
||||
|
||||
/*
|
||||
* Lock against pollnotify() (and possibly other callers)
|
||||
*/
|
||||
lock();
|
||||
|
||||
if (setup) {
|
||||
/*
|
||||
* Save the file pointer in the pollfd for the subclass'
|
||||
* benefit.
|
||||
*/
|
||||
fds->priv = (void *)filep;
|
||||
PX4_DEBUG("VDev::poll: fds->priv = %p", filep);
|
||||
|
||||
/*
|
||||
* Handle setup requests.
|
||||
*/
|
||||
ret = store_poll_waiter(fds);
|
||||
|
||||
if (ret == PX4_OK) {
|
||||
|
||||
/*
|
||||
* Check to see whether we should send a poll notification
|
||||
* immediately.
|
||||
*/
|
||||
fds->revents |= fds->events & poll_state(filep);
|
||||
|
||||
/* yes? post the notification */
|
||||
if (fds->revents != 0)
|
||||
sem_post(fds->sem);
|
||||
}
|
||||
|
||||
} else {
|
||||
/*
|
||||
* Handle a teardown request.
|
||||
*/
|
||||
ret = remove_poll_waiter(fds);
|
||||
}
|
||||
|
||||
unlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
VDev::poll_notify(pollevent_t events)
|
||||
{
|
||||
PX4_DEBUG("VDev::poll_notify events = %0x", events);
|
||||
|
||||
/* lock against poll() as well as other wakeups */
|
||||
lock();
|
||||
|
||||
for (unsigned i = 0; i < _max_pollwaiters; i++)
|
||||
if (nullptr != _pollset[i])
|
||||
poll_notify_one(_pollset[i], events);
|
||||
|
||||
unlock();
|
||||
}
|
||||
|
||||
void
|
||||
VDev::poll_notify_one(px4_pollfd_struct_t *fds, pollevent_t events)
|
||||
{
|
||||
PX4_DEBUG("VDev::poll_notify_one");
|
||||
int value;
|
||||
sem_getvalue(fds->sem, &value);
|
||||
|
||||
/* update the reported event set */
|
||||
fds->revents |= fds->events & events;
|
||||
|
||||
PX4_DEBUG(" Events fds=%p %0x %0x %0x %d",fds, fds->revents, fds->events, events, value);
|
||||
|
||||
/* if the state is now interesting, wake the waiter if it's still asleep */
|
||||
/* XXX semcount check here is a vile hack; counting semphores should not be abused as cvars */
|
||||
if ((fds->revents != 0) && (value <= 0))
|
||||
sem_post(fds->sem);
|
||||
}
|
||||
|
||||
pollevent_t
|
||||
VDev::poll_state(file_t *filep)
|
||||
{
|
||||
PX4_DEBUG("VDev::poll_notify");
|
||||
/* by default, no poll events to report */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
VDev::store_poll_waiter(px4_pollfd_struct_t *fds)
|
||||
{
|
||||
/*
|
||||
* Look for a free slot.
|
||||
*/
|
||||
PX4_DEBUG("VDev::store_poll_waiter");
|
||||
for (unsigned i = 0; i < _max_pollwaiters; i++) {
|
||||
if (nullptr == _pollset[i]) {
|
||||
|
||||
/* save the pollfd */
|
||||
_pollset[i] = fds;
|
||||
|
||||
return PX4_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
int
|
||||
VDev::remove_poll_waiter(px4_pollfd_struct_t *fds)
|
||||
{
|
||||
PX4_DEBUG("VDev::remove_poll_waiter");
|
||||
for (unsigned i = 0; i < _max_pollwaiters; i++) {
|
||||
if (fds == _pollset[i]) {
|
||||
|
||||
_pollset[i] = nullptr;
|
||||
return PX4_OK;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
PX4_WARN("poll: bad fd state");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
VDev *VDev::getDev(const char *path)
|
||||
{
|
||||
PX4_DEBUG("VDev::getDev");
|
||||
int i=0;
|
||||
for (; i<PX4_MAX_DEV; ++i) {
|
||||
//if (devmap[i]) {
|
||||
// printf("%s %s\n", devmap[i]->name, path);
|
||||
//}
|
||||
if (devmap[i] && (strcmp(devmap[i]->name, path) == 0)) {
|
||||
return (VDev *)(devmap[i]->cdev);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void VDev::showDevices()
|
||||
{
|
||||
int i=0;
|
||||
PX4_INFO("Devices:\n");
|
||||
for (; i<PX4_MAX_DEV; ++i) {
|
||||
if (devmap[i] && strncmp(devmap[i]->name, "/dev/", 5) == 0) {
|
||||
PX4_INFO(" %s\n", devmap[i]->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VDev::showTopics()
|
||||
{
|
||||
int i=0;
|
||||
PX4_INFO("Devices:\n");
|
||||
for (; i<PX4_MAX_DEV; ++i) {
|
||||
if (devmap[i] && strncmp(devmap[i]->name, "/obj/", 5) == 0) {
|
||||
PX4_INFO(" %s\n", devmap[i]->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VDev::showFiles()
|
||||
{
|
||||
int i=0;
|
||||
PX4_INFO("Files:\n");
|
||||
for (; i<PX4_MAX_DEV; ++i) {
|
||||
if (devmap[i] && strncmp(devmap[i]->name, "/obj/", 5) != 0 &&
|
||||
strncmp(devmap[i]->name, "/dev/", 5) != 0) {
|
||||
PX4_INFO(" %s\n", devmap[i]->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *VDev::topicList(unsigned int *next)
|
||||
{
|
||||
for (;*next<PX4_MAX_DEV; (*next)++)
|
||||
if (devmap[*next] && strncmp(devmap[(*next)]->name, "/obj/", 5) == 0)
|
||||
return devmap[(*next)++]->name;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *VDev::devList(unsigned int *next)
|
||||
{
|
||||
for (;*next<PX4_MAX_DEV; (*next)++)
|
||||
if (devmap[*next] && strncmp(devmap[(*next)]->name, "/dev/", 5) == 0)
|
||||
return devmap[(*next)++]->name;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} // namespace device
|
||||
|
||||
@@ -0,0 +1,535 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2012-2014 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file vdevice.h
|
||||
*
|
||||
* Definitions for the generic base classes in the virtual device framework.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* Includes here should only cover the needs of the framework definitions.
|
||||
*/
|
||||
#include <px4_posix.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
/**
|
||||
* Namespace encapsulating all device framework classes, functions and data.
|
||||
*/
|
||||
namespace device __EXPORT
|
||||
{
|
||||
|
||||
struct file_t {
|
||||
int fd;
|
||||
int flags;
|
||||
mode_t mode;
|
||||
void *priv;
|
||||
void *vdev;
|
||||
|
||||
file_t() : fd(-1), flags(0), priv(NULL), vdev(NULL) {}
|
||||
file_t(int f, void *c, int d) : fd(d), flags(f), priv(NULL), vdev(c) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Fundamental base class for all physical drivers (I2C, SPI).
|
||||
*
|
||||
* This class provides the basic driver template for I2C and SPI devices
|
||||
*/
|
||||
class __EXPORT Device
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Destructor.
|
||||
*
|
||||
* Public so that anonymous devices can be destroyed.
|
||||
*/
|
||||
virtual ~Device();
|
||||
|
||||
/*
|
||||
* Direct access methods.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialise the driver and make it ready for use.
|
||||
*
|
||||
* @return OK if the driver initialized OK, negative errno otherwise;
|
||||
*/
|
||||
virtual int init();
|
||||
|
||||
/**
|
||||
* Read directly from the device.
|
||||
*
|
||||
* The actual size of each unit quantity is device-specific.
|
||||
*
|
||||
* @param offset The device address at which to start reading
|
||||
* @param data The buffer into which the read values should be placed.
|
||||
* @param count The number of items to read.
|
||||
* @return The number of items read on success, negative errno otherwise.
|
||||
*/
|
||||
virtual int dev_read(unsigned address, void *data, unsigned count);
|
||||
|
||||
/**
|
||||
* Write directly to the device.
|
||||
*
|
||||
* The actual size of each unit quantity is device-specific.
|
||||
*
|
||||
* @param address The device address at which to start writing.
|
||||
* @param data The buffer from which values should be read.
|
||||
* @param count The number of items to write.
|
||||
* @return The number of items written on success, negative errno otherwise.
|
||||
*/
|
||||
virtual int dev_write(unsigned address, void *data, unsigned count);
|
||||
|
||||
/**
|
||||
* Perform a device-specific operation.
|
||||
*
|
||||
* @param operation The operation to perform.
|
||||
* @param arg An argument to the operation.
|
||||
* @return Negative errno on error, OK or positive value on success.
|
||||
*/
|
||||
virtual int dev_ioctl(unsigned operation, unsigned &arg);
|
||||
|
||||
/*
|
||||
device bus types for DEVID
|
||||
*/
|
||||
enum DeviceBusType {
|
||||
DeviceBusType_UNKNOWN = 0,
|
||||
DeviceBusType_I2C = 1,
|
||||
DeviceBusType_SPI = 2,
|
||||
DeviceBusType_UAVCAN = 3,
|
||||
DeviceBusType_SIM = 4,
|
||||
};
|
||||
|
||||
/*
|
||||
broken out device elements. The bitfields are used to keep
|
||||
the overall value small enough to fit in a float accurately,
|
||||
which makes it possible to transport over the MAVLink
|
||||
parameter protocol without loss of information.
|
||||
*/
|
||||
struct DeviceStructure {
|
||||
enum DeviceBusType bus_type:3;
|
||||
uint8_t bus:5; // which instance of the bus type
|
||||
uint8_t address; // address on the bus (eg. I2C address)
|
||||
uint8_t devtype; // device class specific device type
|
||||
};
|
||||
|
||||
union DeviceId {
|
||||
struct DeviceStructure devid_s;
|
||||
uint32_t devid;
|
||||
};
|
||||
|
||||
protected:
|
||||
const char *_name; /**< driver name */
|
||||
bool _debug_enabled; /**< if true, debug messages are printed */
|
||||
union DeviceId _device_id; /**< device identifier information */
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param name Driver name
|
||||
*/
|
||||
Device(const char *name);
|
||||
|
||||
/**
|
||||
* Take the driver lock.
|
||||
*
|
||||
* Each driver instance has its own lock/semaphore.
|
||||
*
|
||||
* Note that we must loop as the wait may be interrupted by a signal.
|
||||
*/
|
||||
void lock() {
|
||||
debug("lock");
|
||||
do {} while (sem_wait(&_lock) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Release the driver lock.
|
||||
*/
|
||||
void unlock() {
|
||||
debug("unlock");
|
||||
sem_post(&_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a message.
|
||||
*
|
||||
* The message is prefixed with the driver name, and followed
|
||||
* by a newline.
|
||||
*/
|
||||
void log(const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* Print a debug message.
|
||||
*
|
||||
* The message is prefixed with the driver name, and followed
|
||||
* by a newline.
|
||||
*/
|
||||
void debug(const char *fmt, ...);
|
||||
|
||||
private:
|
||||
sem_t _lock;
|
||||
|
||||
/** disable copy construction for this and all subclasses */
|
||||
Device(const Device &);
|
||||
|
||||
/** disable assignment for this and all subclasses */
|
||||
Device &operator = (const Device &);
|
||||
};
|
||||
|
||||
/**
|
||||
* Abstract class for any virtual character device
|
||||
*/
|
||||
class __EXPORT VDev : public Device
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param name Driver name
|
||||
* @param devname Device node name
|
||||
*/
|
||||
VDev(const char *name, const char *devname);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~VDev();
|
||||
|
||||
virtual int init();
|
||||
|
||||
/**
|
||||
* Perform a poll setup/teardown operation. Based on NuttX implementation.
|
||||
*
|
||||
* This is handled internally and should not normally be overridden.
|
||||
*
|
||||
* @param filep Pointer to the internal file structure.
|
||||
* @param fds Poll descriptor being waited on.
|
||||
* @param setup True if this is establishing a request, false if
|
||||
* it is being torn down.
|
||||
* @return OK on success, or -errno otherwise.
|
||||
*/
|
||||
virtual int poll(file_t *filep, px4_pollfd_struct_t *fds, bool setup);
|
||||
|
||||
/**
|
||||
* Test whether the device is currently open.
|
||||
*
|
||||
* This can be used to avoid tearing down a device that is still active.
|
||||
* Note - not virtual, cannot be overridden by a subclass.
|
||||
*
|
||||
* @return True if the device is currently open.
|
||||
*/
|
||||
bool is_open() { return _open_count > 0; }
|
||||
|
||||
/**
|
||||
* Handle an open of the device.
|
||||
*
|
||||
* This function is called for every open of the device. The default
|
||||
* implementation maintains _open_count and always returns OK.
|
||||
*
|
||||
* @param filep Pointer to the NuttX file structure.
|
||||
* @return OK if the open is allowed, -errno otherwise.
|
||||
*/
|
||||
virtual int open(file_t *filep);
|
||||
|
||||
/**
|
||||
* Handle a close of the device.
|
||||
*
|
||||
* This function is called for every close of the device. The default
|
||||
* implementation maintains _open_count and returns OK as long as it is not zero.
|
||||
*
|
||||
* @param filep Pointer to the NuttX file structure.
|
||||
* @return OK if the close was successful, -errno otherwise.
|
||||
*/
|
||||
virtual int close(file_t *filep);
|
||||
|
||||
/**
|
||||
* Perform a read from the device.
|
||||
*
|
||||
* The default implementation returns -ENOSYS.
|
||||
*
|
||||
* @param filep Pointer to the NuttX file structure.
|
||||
* @param buffer Pointer to the buffer into which data should be placed.
|
||||
* @param buflen The number of bytes to be read.
|
||||
* @return The number of bytes read or -errno otherwise.
|
||||
*/
|
||||
virtual ssize_t read(file_t *filep, char *buffer, size_t buflen);
|
||||
|
||||
/**
|
||||
* Perform a write to the device.
|
||||
*
|
||||
* The default implementation returns -ENOSYS.
|
||||
*
|
||||
* @param filep Pointer to the NuttX file structure.
|
||||
* @param buffer Pointer to the buffer from which data should be read.
|
||||
* @param buflen The number of bytes to be written.
|
||||
* @return The number of bytes written or -errno otherwise.
|
||||
*/
|
||||
virtual ssize_t write(file_t *filep, const char *buffer, size_t buflen);
|
||||
|
||||
/**
|
||||
* Perform a logical seek operation on the device.
|
||||
*
|
||||
* The default implementation returns -ENOSYS.
|
||||
*
|
||||
* @param filep Pointer to the NuttX file structure.
|
||||
* @param offset The new file position relative to whence.
|
||||
* @param whence SEEK_OFS, SEEK_CUR or SEEK_END.
|
||||
* @return The previous offset, or -errno otherwise.
|
||||
*/
|
||||
virtual off_t seek(file_t *filep, off_t offset, int whence);
|
||||
|
||||
/**
|
||||
* Perform an ioctl operation on the device.
|
||||
*
|
||||
* The default implementation handles DIOC_GETPRIV, and otherwise
|
||||
* returns -ENOTTY. Subclasses should call the default implementation
|
||||
* for any command they do not handle themselves.
|
||||
*
|
||||
* @param filep Pointer to the NuttX file structure.
|
||||
* @param cmd The ioctl command value.
|
||||
* @param arg The ioctl argument value.
|
||||
* @return OK on success, or -errno otherwise.
|
||||
*/
|
||||
virtual int ioctl(file_t *filep, int cmd, unsigned long arg);
|
||||
|
||||
static VDev *getDev(const char *path);
|
||||
static void showFiles(void);
|
||||
static void showDevices(void);
|
||||
static void showTopics(void);
|
||||
static const char *devList(unsigned int *next);
|
||||
static const char *topicList(unsigned int *next);
|
||||
|
||||
protected:
|
||||
|
||||
int register_driver(const char *name, void *data);
|
||||
int unregister_driver(const char *name);
|
||||
|
||||
/**
|
||||
* Check the current state of the device for poll events from the
|
||||
* perspective of the file.
|
||||
*
|
||||
* This function is called by the default poll() implementation when
|
||||
* a poll is set up to determine whether the poll should return immediately.
|
||||
*
|
||||
* The default implementation returns no events.
|
||||
*
|
||||
* @param filep The file that's interested.
|
||||
* @return The current set of poll events.
|
||||
*/
|
||||
virtual pollevent_t poll_state(file_t *filep);
|
||||
|
||||
/**
|
||||
* Report new poll events.
|
||||
*
|
||||
* This function should be called anytime the state of the device changes
|
||||
* in a fashion that might be interesting to a poll waiter.
|
||||
*
|
||||
* @param events The new event(s) being announced.
|
||||
*/
|
||||
virtual void poll_notify(pollevent_t events);
|
||||
|
||||
/**
|
||||
* Internal implementation of poll_notify.
|
||||
*
|
||||
* @param fds A poll waiter to notify.
|
||||
* @param events The event(s) to send to the waiter.
|
||||
*/
|
||||
virtual void poll_notify_one(px4_pollfd_struct_t *fds, pollevent_t events);
|
||||
|
||||
/**
|
||||
* Notification of the first open.
|
||||
*
|
||||
* This function is called when the device open count transitions from zero
|
||||
* to one. The driver lock is held for the duration of the call.
|
||||
*
|
||||
* The default implementation returns OK.
|
||||
*
|
||||
* @param filep Pointer to the NuttX file structure.
|
||||
* @return OK if the open should proceed, -errno otherwise.
|
||||
*/
|
||||
virtual int open_first(file_t *filep);
|
||||
|
||||
/**
|
||||
* Notification of the last close.
|
||||
*
|
||||
* This function is called when the device open count transitions from
|
||||
* one to zero. The driver lock is held for the duration of the call.
|
||||
*
|
||||
* The default implementation returns OK.
|
||||
*
|
||||
* @param filep Pointer to the NuttX file structure.
|
||||
* @return OK if the open should return OK, -errno otherwise.
|
||||
*/
|
||||
virtual int close_last(file_t *filep);
|
||||
|
||||
/**
|
||||
* Register a class device name, automatically adding device
|
||||
* class instance suffix if need be.
|
||||
*
|
||||
* @param class_devname Device class name
|
||||
* @return class_instamce Class instance created, or -errno on failure
|
||||
*/
|
||||
virtual int register_class_devname(const char *class_devname);
|
||||
|
||||
/**
|
||||
* Register a class device name, automatically adding device
|
||||
* class instance suffix if need be.
|
||||
*
|
||||
* @param class_devname Device class name
|
||||
* @param class_instance Device class instance from register_class_devname()
|
||||
* @return OK on success, -errno otherwise
|
||||
*/
|
||||
virtual int unregister_class_devname(const char *class_devname, unsigned class_instance);
|
||||
|
||||
/**
|
||||
* Get the device name.
|
||||
*
|
||||
* @return the file system string of the device handle
|
||||
*/
|
||||
const char* get_devname() { return _devname; }
|
||||
|
||||
bool _pub_blocked; /**< true if publishing should be blocked */
|
||||
|
||||
private:
|
||||
static const unsigned _max_pollwaiters = 8;
|
||||
|
||||
const char *_devname; /**< device node name */
|
||||
bool _registered; /**< true if device name was registered */
|
||||
unsigned _open_count; /**< number of successful opens */
|
||||
|
||||
px4_pollfd_struct_t *_pollset[_max_pollwaiters];
|
||||
|
||||
/**
|
||||
* Store a pollwaiter in a slot where we can find it later.
|
||||
*
|
||||
* Expands the pollset as required. Must be called with the driver locked.
|
||||
*
|
||||
* @return OK, or -errno on error.
|
||||
*/
|
||||
int store_poll_waiter(px4_pollfd_struct_t *fds);
|
||||
|
||||
/**
|
||||
* Remove a poll waiter.
|
||||
*
|
||||
* @return OK, or -errno on error.
|
||||
*/
|
||||
int remove_poll_waiter(px4_pollfd_struct_t *fds);
|
||||
|
||||
/* do not allow copying this class */
|
||||
VDev(const VDev&);
|
||||
//VDev operator=(const VDev&);
|
||||
};
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* Abstract class for character device accessed via PIO
|
||||
*/
|
||||
class __EXPORT VPIO : public CDev
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param name Driver name
|
||||
* @param devname Device node name
|
||||
* @param base Base address of the device PIO area
|
||||
* @param irq Interrupt assigned to the device (or zero if none)
|
||||
*/
|
||||
PIO(const char *name,
|
||||
const char *devname,
|
||||
unsigned long base
|
||||
);
|
||||
virtual ~PIO();
|
||||
|
||||
virtual int init();
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Read a register
|
||||
*
|
||||
* @param offset Register offset in bytes from the base address.
|
||||
*/
|
||||
uint32_t reg(uint32_t offset) {
|
||||
return *(volatile uint32_t *)(_base + offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a register
|
||||
*
|
||||
* @param offset Register offset in bytes from the base address.
|
||||
* @param value Value to write.
|
||||
*/
|
||||
void reg(uint32_t offset, uint32_t value) {
|
||||
*(volatile uint32_t *)(_base + offset) = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify a register
|
||||
*
|
||||
* Note that there is a risk of a race during the read/modify/write cycle
|
||||
* that must be taken care of by the caller.
|
||||
*
|
||||
* @param offset Register offset in bytes from the base address.
|
||||
* @param clearbits Bits to clear in the register
|
||||
* @param setbits Bits to set in the register
|
||||
*/
|
||||
void modify(uint32_t offset, uint32_t clearbits, uint32_t setbits) {
|
||||
uint32_t val = reg(offset);
|
||||
val &= ~clearbits;
|
||||
val |= setbits;
|
||||
reg(offset, val);
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned long _base;
|
||||
};
|
||||
#endif
|
||||
|
||||
} // namespace device
|
||||
|
||||
// class instance for primary driver of each class
|
||||
enum CLASS_DEVICE {
|
||||
CLASS_DEVICE_PRIMARY=0,
|
||||
CLASS_DEVICE_SECONDARY=1,
|
||||
CLASS_DEVICE_TERTIARY=2
|
||||
};
|
||||
|
||||
@@ -0,0 +1,322 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2015 Mark Charlebois. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file vdev_posix.cpp
|
||||
*
|
||||
* POSIX-like API for virtual character device
|
||||
*/
|
||||
|
||||
#include <px4_log.h>
|
||||
#include <px4_posix.h>
|
||||
#include <px4_time.h>
|
||||
#include "device.h"
|
||||
#include "vfile.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
using namespace device;
|
||||
|
||||
extern "C" {
|
||||
|
||||
struct timerData {
|
||||
sem_t &sem;
|
||||
struct timespec &ts;
|
||||
|
||||
timerData(sem_t &s, struct timespec &t) : sem(s), ts(t) {}
|
||||
~timerData() {}
|
||||
};
|
||||
|
||||
static void *timer_handler(void *data)
|
||||
{
|
||||
struct timerData *td = (struct timerData *)data;
|
||||
|
||||
if (td->ts.tv_sec) {
|
||||
sleep(td->ts.tv_sec);
|
||||
}
|
||||
usleep(td->ts.tv_nsec/1000);
|
||||
sem_post(&(td->sem));
|
||||
|
||||
PX4_DEBUG("timer_handler: Timer expired");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define PX4_MAX_FD 100
|
||||
static device::file_t *filemap[PX4_MAX_FD] = {};
|
||||
|
||||
int px4_errno;
|
||||
|
||||
inline bool valid_fd(int fd)
|
||||
{
|
||||
return (fd < PX4_MAX_FD && fd >= 0 && filemap[fd] != NULL);
|
||||
}
|
||||
|
||||
int px4_open(const char *path, int flags, ...)
|
||||
{
|
||||
PX4_DEBUG("px4_open");
|
||||
VDev *dev = VDev::getDev(path);
|
||||
int ret = 0;
|
||||
int i;
|
||||
mode_t mode;
|
||||
|
||||
if (!dev && (flags & (PX4_F_WRONLY|PX4_F_CREAT)) != 0 &&
|
||||
strncmp(path, "/obj/", 5) != 0 &&
|
||||
strncmp(path, "/dev/", 5) != 0)
|
||||
{
|
||||
va_list p;
|
||||
va_start(p, flags);
|
||||
mode = va_arg(p, mode_t);
|
||||
va_end(p);
|
||||
|
||||
// Create the file
|
||||
PX4_DEBUG("Creating virtual file %s", path);
|
||||
dev = VFile::createFile(path, mode);
|
||||
}
|
||||
if (dev) {
|
||||
for (i=0; i<PX4_MAX_FD; ++i) {
|
||||
if (filemap[i] == 0) {
|
||||
filemap[i] = new device::file_t(flags,dev,i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < PX4_MAX_FD) {
|
||||
ret = dev->open(filemap[i]);
|
||||
}
|
||||
else {
|
||||
ret = -ENOENT;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (ret < 0) {
|
||||
px4_errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
PX4_DEBUG("px4_open fd = %d", filemap[i]->fd);
|
||||
return filemap[i]->fd;
|
||||
}
|
||||
|
||||
int px4_close(int fd)
|
||||
{
|
||||
int ret;
|
||||
if (valid_fd(fd)) {
|
||||
VDev *dev = (VDev *)(filemap[fd]->vdev);
|
||||
PX4_DEBUG("px4_close fd = %d", fd);
|
||||
ret = dev->close(filemap[fd]);
|
||||
filemap[fd] = NULL;
|
||||
}
|
||||
else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (ret < 0) {
|
||||
px4_errno = -ret;
|
||||
ret = PX4_ERROR;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t px4_read(int fd, void *buffer, size_t buflen)
|
||||
{
|
||||
int ret;
|
||||
if (valid_fd(fd)) {
|
||||
VDev *dev = (VDev *)(filemap[fd]->vdev);
|
||||
PX4_DEBUG("px4_read fd = %d", fd);
|
||||
ret = dev->read(filemap[fd], (char *)buffer, buflen);
|
||||
}
|
||||
else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (ret < 0) {
|
||||
px4_errno = -ret;
|
||||
ret = PX4_ERROR;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t px4_write(int fd, const void *buffer, size_t buflen)
|
||||
{
|
||||
int ret;
|
||||
if (valid_fd(fd)) {
|
||||
VDev *dev = (VDev *)(filemap[fd]->vdev);
|
||||
PX4_DEBUG("px4_write fd = %d", fd);
|
||||
ret = dev->write(filemap[fd], (const char *)buffer, buflen);
|
||||
}
|
||||
else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (ret < 0) {
|
||||
px4_errno = -ret;
|
||||
ret = PX4_ERROR;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int px4_ioctl(int fd, int cmd, unsigned long arg)
|
||||
{
|
||||
PX4_DEBUG("px4_ioctl fd = %d", fd);
|
||||
int ret = 0;
|
||||
if (valid_fd(fd)) {
|
||||
VDev *dev = (VDev *)(filemap[fd]->vdev);
|
||||
ret = dev->ioctl(filemap[fd], cmd, arg);
|
||||
}
|
||||
else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (ret < 0) {
|
||||
px4_errno = -ret;
|
||||
}
|
||||
|
||||
return (ret == 0) ? PX4_OK : PX4_ERROR;
|
||||
}
|
||||
|
||||
int px4_poll(px4_pollfd_struct_t *fds, nfds_t nfds, int timeout)
|
||||
{
|
||||
sem_t sem;
|
||||
int count = 0;
|
||||
int ret;
|
||||
unsigned int i;
|
||||
struct timespec ts;
|
||||
|
||||
PX4_DEBUG("Called px4_poll timeout = %d", timeout);
|
||||
sem_init(&sem, 0, 0);
|
||||
|
||||
// For each fd
|
||||
for (i=0; i<nfds; ++i)
|
||||
{
|
||||
fds[i].sem = &sem;
|
||||
fds[i].revents = 0;
|
||||
fds[i].priv = NULL;
|
||||
|
||||
// If fd is valid
|
||||
if (valid_fd(fds[i].fd))
|
||||
{
|
||||
VDev *dev = (VDev *)(filemap[fds[i].fd]->vdev);;
|
||||
PX4_DEBUG("px4_poll: VDev->poll(setup) %d", fds[i].fd);
|
||||
ret = dev->poll(filemap[fds[i].fd], &fds[i], true);
|
||||
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret >= 0)
|
||||
{
|
||||
if (timeout >= 0)
|
||||
{
|
||||
pthread_t pt;
|
||||
void *res;
|
||||
|
||||
ts.tv_sec = timeout/1000;
|
||||
ts.tv_nsec = (timeout % 1000)*1000;
|
||||
|
||||
// Create a timer to unblock
|
||||
struct timerData td(sem, ts);
|
||||
int rv = pthread_create(&pt, NULL, timer_handler, (void *)&td);
|
||||
if (rv != 0) {
|
||||
count = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
sem_wait(&sem);
|
||||
|
||||
// Make sure timer thread is killed before sem goes
|
||||
// out of scope
|
||||
(void)pthread_cancel(pt);
|
||||
(void)pthread_join(pt, &res);
|
||||
}
|
||||
else
|
||||
{
|
||||
sem_wait(&sem);
|
||||
}
|
||||
|
||||
// For each fd
|
||||
for (i=0; i<nfds; ++i)
|
||||
{
|
||||
// If fd is valid
|
||||
if (valid_fd(fds[i].fd))
|
||||
{
|
||||
VDev *dev = (VDev *)(filemap[fds[i].fd]->vdev);;
|
||||
PX4_DEBUG("px4_poll: VDev->poll(teardown) %d", fds[i].fd);
|
||||
ret = dev->poll(filemap[fds[i].fd], &fds[i], false);
|
||||
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
if (fds[i].revents)
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
sem_destroy(&sem);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int px4_fsync(int fd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void px4_show_devices()
|
||||
{
|
||||
VDev::showDevices();
|
||||
}
|
||||
|
||||
void px4_show_topics()
|
||||
{
|
||||
VDev::showTopics();
|
||||
}
|
||||
|
||||
void px4_show_files()
|
||||
{
|
||||
VDev::showFiles();
|
||||
}
|
||||
|
||||
const char * px4_get_device_names(unsigned int *handle)
|
||||
{
|
||||
return VDev::devList(handle);
|
||||
}
|
||||
|
||||
const char * px4_get_topic_names(unsigned int *handle)
|
||||
{
|
||||
return VDev::topicList(handle);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2015 Mark Charlebois. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file vdev_file.cpp
|
||||
* Virtual file
|
||||
*
|
||||
* @author Mark Charlebois <charlebm@gmail.com>
|
||||
*/
|
||||
|
||||
#include "vfile.h"
|
||||
#include <stdio.h>
|
||||
|
||||
using namespace device;
|
||||
|
||||
VFile::VFile(const char *fname, mode_t mode) :
|
||||
VDev("vfile", fname)
|
||||
{
|
||||
}
|
||||
|
||||
VFile * VFile::createFile(const char *fname, mode_t mode)
|
||||
{
|
||||
VFile *me = new VFile(fname, mode);
|
||||
me->register_driver(fname, me);
|
||||
return me;
|
||||
}
|
||||
|
||||
ssize_t VFile::write(device::file_t *handlep, const char *buffer, size_t buflen)
|
||||
{
|
||||
// ignore what was written, but let pollers know something was written
|
||||
poll_notify(POLLIN);
|
||||
|
||||
return buflen;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2015 Mark Charlebois. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file vfile.cpp
|
||||
* Virtual file
|
||||
*
|
||||
* @author Mark Charlebois <charlebm@gmail.com>
|
||||
*/
|
||||
|
||||
#include <px4_tasks.h>
|
||||
#include <drivers/drv_device.h>
|
||||
#include "device.h"
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
class VFile : public device::VDev {
|
||||
public:
|
||||
|
||||
static VFile *createFile(const char *fname, mode_t mode);
|
||||
~VFile() {}
|
||||
|
||||
virtual ssize_t write(device::file_t *handlep, const char *buffer, size_t buflen);
|
||||
|
||||
private:
|
||||
VFile(const char *fname, mode_t mode);
|
||||
VFile(const VFile &);
|
||||
};
|
||||
@@ -94,7 +94,7 @@ ORB_DECLARE(sensor_accel);
|
||||
*/
|
||||
|
||||
#define _ACCELIOCBASE (0x2100)
|
||||
#define _ACCELIOC(_n) (_IOC(_ACCELIOCBASE, _n))
|
||||
#define _ACCELIOC(_n) (_PX4_IOC(_ACCELIOCBASE, _n))
|
||||
|
||||
|
||||
/** set the accel internal sample rate to at least (arg) Hz */
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
*/
|
||||
|
||||
#define _AIRSPEEDIOCBASE (0x7700)
|
||||
#define __AIRSPEEDIOC(_n) (_IOC(_AIRSPEEDIOCBASE, _n))
|
||||
#define __AIRSPEEDIOC(_n) (_PX4_IOC(_AIRSPEEDIOCBASE, _n))
|
||||
|
||||
#define AIRSPEEDIOCSSCALE __AIRSPEEDIOC(0)
|
||||
#define AIRSPEEDIOCGSCALE __AIRSPEEDIOC(1)
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#ifndef _DRV_BARO_H
|
||||
#define _DRV_BARO_H
|
||||
|
||||
#include <px4_defines.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
@@ -71,7 +72,7 @@ ORB_DECLARE(sensor_baro);
|
||||
*/
|
||||
|
||||
#define _BAROIOCBASE (0x2200)
|
||||
#define _BAROIOC(_n) (_IOC(_BAROIOCBASE, _n))
|
||||
#define _BAROIOC(_n) (_PX4_IOC(_BAROIOCBASE, _n))
|
||||
|
||||
/** set corrected MSL pressure in pascals */
|
||||
#define BAROIOCSMSLPRESSURE _BAROIOC(0)
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <px4_defines.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
@@ -52,7 +53,7 @@
|
||||
*/
|
||||
|
||||
#define _BLINKMIOCBASE (0x2900)
|
||||
#define _BLINKMIOC(_n) (_IOC(_BLINKMIOCBASE, _n))
|
||||
#define _BLINKMIOC(_n) (_PX4_IOC(_BLINKMIOCBASE, _n))
|
||||
|
||||
/** play the named script in *(char *)arg, repeating forever */
|
||||
#define BLINKM_PLAY_SCRIPT_NAMED _BLINKMIOC(1)
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
*/
|
||||
|
||||
#define _DEVICEIOCBASE (0x100)
|
||||
#define _DEVICEIOC(_n) (_IOC(_DEVICEIOCBASE, _n))
|
||||
#define _DEVICEIOC(_n) (_PX4_IOC(_DEVICEIOCBASE, _n))
|
||||
|
||||
/** ask device to stop publishing */
|
||||
#define DEVIOCSPUBBLOCK _DEVICEIOC(0)
|
||||
@@ -65,5 +65,8 @@
|
||||
*/
|
||||
#define DEVIOCGDEVICEID _DEVICEIOC(2)
|
||||
|
||||
#ifdef __PX4_POSIX
|
||||
#define DIOC_GETPRIV SIOCDEVPRIVATE
|
||||
#endif
|
||||
|
||||
#endif /* _DRV_DEVICE_H */
|
||||
|
||||
@@ -114,9 +114,14 @@
|
||||
/* no GPIO driver on the PX4_STM32F4DISCOVERY board */
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_BOARD_POSIXTEST
|
||||
/* no GPIO driver on the POSIXTEST board */
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_ARCH_BOARD_PX4IO_V1) && !defined(CONFIG_ARCH_BOARD_PX4IO_V2) && \
|
||||
!defined(CONFIG_ARCH_BOARD_PX4FMU_V1) && !defined(CONFIG_ARCH_BOARD_PX4FMU_V2) && \
|
||||
!defined(CONFIG_ARCH_BOARD_AEROCORE) && !defined(CONFIG_ARCH_BOARD_PX4_STM32F4DISCOVERY)
|
||||
!defined(CONFIG_ARCH_BOARD_AEROCORE) && !defined(CONFIG_ARCH_BOARD_PX4_STM32F4DISCOVERY) && \
|
||||
!defined(CONFIG_ARCH_BOARD_POSIXTEST)
|
||||
# error No CONFIG_ARCH_BOARD_xxxx set
|
||||
#endif
|
||||
/*
|
||||
|
||||
@@ -91,7 +91,7 @@ ORB_DECLARE(sensor_gyro);
|
||||
*/
|
||||
|
||||
#define _GYROIOCBASE (0x2300)
|
||||
#define _GYROIOC(_n) (_IOC(_GYROIOCBASE, _n))
|
||||
#define _GYROIOC(_n) (_PX4_IOC(_GYROIOCBASE, _n))
|
||||
|
||||
/** set the gyro internal sample rate to at least (arg) Hz */
|
||||
#define GYROIOCSSAMPLERATE _GYROIOC(0)
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <px4_posix.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdbool.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <px4_defines.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
@@ -52,9 +53,9 @@
|
||||
#define LED_BLUE 0
|
||||
#define LED_SAFETY 2
|
||||
|
||||
#define LED_ON _IOC(_LED_BASE, 0)
|
||||
#define LED_OFF _IOC(_LED_BASE, 1)
|
||||
#define LED_TOGGLE _IOC(_LED_BASE, 2)
|
||||
#define LED_ON _PX4_IOC(_LED_BASE, 0)
|
||||
#define LED_OFF _PX4_IOC(_LED_BASE, 1)
|
||||
#define LED_TOGGLE _PX4_IOC(_LED_BASE, 2)
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ ORB_DECLARE(sensor_mag);
|
||||
*/
|
||||
|
||||
#define _MAGIOCBASE (0x2400)
|
||||
#define _MAGIOC(_n) (_IOC(_MAGIOCBASE, _n))
|
||||
#define _MAGIOC(_n) (_PX4_IOC(_MAGIOCBASE, _n))
|
||||
|
||||
/** set the mag internal sample rate to at least (arg) Hz */
|
||||
#define MAGIOCSSAMPLERATE _MAGIOC(0)
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
#ifndef _DRV_MIXER_H
|
||||
#define _DRV_MIXER_H
|
||||
|
||||
#include <px4_defines.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
@@ -62,7 +63,7 @@
|
||||
* ioctl() definitions
|
||||
*/
|
||||
#define _MIXERIOCBASE (0x2500)
|
||||
#define _MIXERIOC(_n) (_IOC(_MIXERIOCBASE, _n))
|
||||
#define _MIXERIOC(_n) (_PX4_IOC(_MIXERIOCBASE, _n))
|
||||
|
||||
/** get the number of mixable outputs */
|
||||
#define MIXERIOCGETOUTPUTCOUNT _MIXERIOC(0)
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
* uORB published object driver.
|
||||
*/
|
||||
|
||||
#include <px4_defines.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <stdint.h>
|
||||
@@ -61,7 +62,7 @@
|
||||
#define ORB_MAXNAME 32
|
||||
|
||||
#define _ORBIOCBASE (0x2600)
|
||||
#define _ORBIOC(_n) (_IOC(_ORBIOCBASE, _n))
|
||||
#define _ORBIOC(_n) (_PX4_IOC(_ORBIOCBASE, _n))
|
||||
|
||||
/*
|
||||
* IOCTLs for the uORB control device
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <px4_defines.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
@@ -149,102 +150,102 @@ ORB_DECLARE(output_pwm);
|
||||
#define _PWM_SERVO_BASE 0x2a00
|
||||
|
||||
/** arm all servo outputs handle by this driver */
|
||||
#define PWM_SERVO_ARM _IOC(_PWM_SERVO_BASE, 0)
|
||||
#define PWM_SERVO_ARM _PX4_IOC(_PWM_SERVO_BASE, 0)
|
||||
|
||||
/** disarm all servo outputs (stop generating pulses) */
|
||||
#define PWM_SERVO_DISARM _IOC(_PWM_SERVO_BASE, 1)
|
||||
#define PWM_SERVO_DISARM _PX4_IOC(_PWM_SERVO_BASE, 1)
|
||||
|
||||
/** get default servo update rate */
|
||||
#define PWM_SERVO_GET_DEFAULT_UPDATE_RATE _IOC(_PWM_SERVO_BASE, 2)
|
||||
|
||||
/** set alternate servo update rate */
|
||||
#define PWM_SERVO_SET_UPDATE_RATE _IOC(_PWM_SERVO_BASE, 3)
|
||||
#define PWM_SERVO_SET_UPDATE_RATE _PX4_IOC(_PWM_SERVO_BASE, 3)
|
||||
|
||||
/** get alternate servo update rate */
|
||||
#define PWM_SERVO_GET_UPDATE_RATE _IOC(_PWM_SERVO_BASE, 4)
|
||||
#define PWM_SERVO_GET_UPDATE_RATE _PX4_IOC(_PWM_SERVO_BASE, 4)
|
||||
|
||||
/** get the number of servos in *(unsigned *)arg */
|
||||
#define PWM_SERVO_GET_COUNT _IOC(_PWM_SERVO_BASE, 5)
|
||||
#define PWM_SERVO_GET_COUNT _PX4_IOC(_PWM_SERVO_BASE, 5)
|
||||
|
||||
/** selects servo update rates, one bit per servo. 0 = default (50Hz), 1 = alternate */
|
||||
#define PWM_SERVO_SET_SELECT_UPDATE_RATE _IOC(_PWM_SERVO_BASE, 6)
|
||||
#define PWM_SERVO_SET_SELECT_UPDATE_RATE _PX4_IOC(_PWM_SERVO_BASE, 6)
|
||||
|
||||
/** check the selected update rates */
|
||||
#define PWM_SERVO_GET_SELECT_UPDATE_RATE _IOC(_PWM_SERVO_BASE, 7)
|
||||
#define PWM_SERVO_GET_SELECT_UPDATE_RATE _PX4_IOC(_PWM_SERVO_BASE, 7)
|
||||
|
||||
/** set the 'ARM ok' bit, which activates the safety switch */
|
||||
#define PWM_SERVO_SET_ARM_OK _IOC(_PWM_SERVO_BASE, 8)
|
||||
#define PWM_SERVO_SET_ARM_OK _PX4_IOC(_PWM_SERVO_BASE, 8)
|
||||
|
||||
/** clear the 'ARM ok' bit, which deactivates the safety switch */
|
||||
#define PWM_SERVO_CLEAR_ARM_OK _IOC(_PWM_SERVO_BASE, 9)
|
||||
#define PWM_SERVO_CLEAR_ARM_OK _PX4_IOC(_PWM_SERVO_BASE, 9)
|
||||
|
||||
/** start DSM bind */
|
||||
#define DSM_BIND_START _IOC(_PWM_SERVO_BASE, 10)
|
||||
#define DSM_BIND_START _PX4_IOC(_PWM_SERVO_BASE, 10)
|
||||
|
||||
#define DSM2_BIND_PULSES 3 /* DSM_BIND_START ioctl parameter, pulses required to start dsm2 pairing */
|
||||
#define DSMX_BIND_PULSES 7 /* DSM_BIND_START ioctl parameter, pulses required to start dsmx pairing */
|
||||
#define DSMX8_BIND_PULSES 9 /* DSM_BIND_START ioctl parameter, pulses required to start 8 or more channel dsmx pairing */
|
||||
|
||||
/** power up DSM receiver */
|
||||
#define DSM_BIND_POWER_UP _IOC(_PWM_SERVO_BASE, 11)
|
||||
#define DSM_BIND_POWER_UP _PX4_IOC(_PWM_SERVO_BASE, 11)
|
||||
|
||||
/** set the PWM value for failsafe */
|
||||
#define PWM_SERVO_SET_FAILSAFE_PWM _IOC(_PWM_SERVO_BASE, 12)
|
||||
#define PWM_SERVO_SET_FAILSAFE_PWM _PX4_IOC(_PWM_SERVO_BASE, 12)
|
||||
|
||||
/** get the PWM value for failsafe */
|
||||
#define PWM_SERVO_GET_FAILSAFE_PWM _IOC(_PWM_SERVO_BASE, 13)
|
||||
#define PWM_SERVO_GET_FAILSAFE_PWM _PX4_IOC(_PWM_SERVO_BASE, 13)
|
||||
|
||||
/** set the PWM value when disarmed - should be no PWM (zero) by default */
|
||||
#define PWM_SERVO_SET_DISARMED_PWM _IOC(_PWM_SERVO_BASE, 14)
|
||||
#define PWM_SERVO_SET_DISARMED_PWM _PX4_IOC(_PWM_SERVO_BASE, 14)
|
||||
|
||||
/** get the PWM value when disarmed */
|
||||
#define PWM_SERVO_GET_DISARMED_PWM _IOC(_PWM_SERVO_BASE, 15)
|
||||
#define PWM_SERVO_GET_DISARMED_PWM _PX4_IOC(_PWM_SERVO_BASE, 15)
|
||||
|
||||
/** set the minimum PWM value the output will send */
|
||||
#define PWM_SERVO_SET_MIN_PWM _IOC(_PWM_SERVO_BASE, 16)
|
||||
#define PWM_SERVO_SET_MIN_PWM _PX4_IOC(_PWM_SERVO_BASE, 16)
|
||||
|
||||
/** get the minimum PWM value the output will send */
|
||||
#define PWM_SERVO_GET_MIN_PWM _IOC(_PWM_SERVO_BASE, 17)
|
||||
#define PWM_SERVO_GET_MIN_PWM _PX4_IOC(_PWM_SERVO_BASE, 17)
|
||||
|
||||
/** set the maximum PWM value the output will send */
|
||||
#define PWM_SERVO_SET_MAX_PWM _IOC(_PWM_SERVO_BASE, 18)
|
||||
#define PWM_SERVO_SET_MAX_PWM _PX4_IOC(_PWM_SERVO_BASE, 18)
|
||||
|
||||
/** get the maximum PWM value the output will send */
|
||||
#define PWM_SERVO_GET_MAX_PWM _IOC(_PWM_SERVO_BASE, 19)
|
||||
#define PWM_SERVO_GET_MAX_PWM _PX4_IOC(_PWM_SERVO_BASE, 19)
|
||||
|
||||
/** set the number of servos in (unsigned)arg - allows change of
|
||||
* split between servos and GPIO */
|
||||
#define PWM_SERVO_SET_COUNT _IOC(_PWM_SERVO_BASE, 20)
|
||||
#define PWM_SERVO_SET_COUNT _PX4_IOC(_PWM_SERVO_BASE, 20)
|
||||
|
||||
/** set the lockdown override flag to enable outputs in HIL */
|
||||
#define PWM_SERVO_SET_DISABLE_LOCKDOWN _IOC(_PWM_SERVO_BASE, 21)
|
||||
#define PWM_SERVO_SET_DISABLE_LOCKDOWN _PX4_IOC(_PWM_SERVO_BASE, 21)
|
||||
|
||||
/** get the lockdown override flag to enable outputs in HIL */
|
||||
#define PWM_SERVO_GET_DISABLE_LOCKDOWN _IOC(_PWM_SERVO_BASE, 22)
|
||||
#define PWM_SERVO_GET_DISABLE_LOCKDOWN _PX4_IOC(_PWM_SERVO_BASE, 22)
|
||||
|
||||
/** force safety switch off (to disable use of safety switch) */
|
||||
#define PWM_SERVO_SET_FORCE_SAFETY_OFF _IOC(_PWM_SERVO_BASE, 23)
|
||||
#define PWM_SERVO_SET_FORCE_SAFETY_OFF _PX4_IOC(_PWM_SERVO_BASE, 23)
|
||||
|
||||
/** force failsafe mode (failsafe values are set immediately even if failsafe condition not met) */
|
||||
#define PWM_SERVO_SET_FORCE_FAILSAFE _IOC(_PWM_SERVO_BASE, 24)
|
||||
#define PWM_SERVO_SET_FORCE_FAILSAFE _PX4_IOC(_PWM_SERVO_BASE, 24)
|
||||
|
||||
/** make failsafe non-recoverable (termination) if it occurs */
|
||||
#define PWM_SERVO_SET_TERMINATION_FAILSAFE _IOC(_PWM_SERVO_BASE, 25)
|
||||
#define PWM_SERVO_SET_TERMINATION_FAILSAFE _PX4_IOC(_PWM_SERVO_BASE, 25)
|
||||
|
||||
/** force safety switch on (to enable use of safety switch) */
|
||||
#define PWM_SERVO_SET_FORCE_SAFETY_ON _IOC(_PWM_SERVO_BASE, 26)
|
||||
#define PWM_SERVO_SET_FORCE_SAFETY_ON _PX4_IOC(_PWM_SERVO_BASE, 26)
|
||||
|
||||
/** set RC config for a channel. This takes a pointer to pwm_output_rc_config */
|
||||
#define PWM_SERVO_SET_RC_CONFIG _IOC(_PWM_SERVO_BASE, 27)
|
||||
#define PWM_SERVO_SET_RC_CONFIG _PX4_IOC(_PWM_SERVO_BASE, 27)
|
||||
|
||||
/** set the 'OVERRIDE OK' bit, which allows for RC control on FMU loss */
|
||||
#define PWM_SERVO_SET_OVERRIDE_OK _IOC(_PWM_SERVO_BASE, 28)
|
||||
#define PWM_SERVO_SET_OVERRIDE_OK _PX4_IOC(_PWM_SERVO_BASE, 28)
|
||||
|
||||
/** clear the 'OVERRIDE OK' bit, which allows for RC control on FMU loss */
|
||||
#define PWM_SERVO_CLEAR_OVERRIDE_OK _IOC(_PWM_SERVO_BASE, 29)
|
||||
#define PWM_SERVO_CLEAR_OVERRIDE_OK _PX4_IOC(_PWM_SERVO_BASE, 29)
|
||||
|
||||
/** setup OVERRIDE_IMMEDIATE behaviour on FMU fail */
|
||||
#define PWM_SERVO_SET_OVERRIDE_IMMEDIATE _IOC(_PWM_SERVO_BASE, 30)
|
||||
#define PWM_SERVO_SET_OVERRIDE_IMMEDIATE _PX4_IOC(_PWM_SERVO_BASE, 30)
|
||||
|
||||
/*
|
||||
*
|
||||
@@ -255,15 +256,15 @@ ORB_DECLARE(output_pwm);
|
||||
*/
|
||||
|
||||
/** set a single servo to a specific value */
|
||||
#define PWM_SERVO_SET(_servo) _IOC(_PWM_SERVO_BASE, 0x20 + _servo)
|
||||
#define PWM_SERVO_SET(_servo) _PX4_IOC(_PWM_SERVO_BASE, 0x20 + _servo)
|
||||
|
||||
/** get a single specific servo value */
|
||||
#define PWM_SERVO_GET(_servo) _IOC(_PWM_SERVO_BASE, 0x40 + _servo)
|
||||
#define PWM_SERVO_GET(_servo) _PX4_IOC(_PWM_SERVO_BASE, 0x40 + _servo)
|
||||
|
||||
/** get the _n'th rate group's channels; *(uint32_t *)arg returns a bitmap of channels
|
||||
* whose update rates must be the same.
|
||||
*/
|
||||
#define PWM_SERVO_GET_RATEGROUP(_n) _IOC(_PWM_SERVO_BASE, 0x60 + _n)
|
||||
#define PWM_SERVO_GET_RATEGROUP(_n) _PX4_IOC(_PWM_SERVO_BASE, 0x60 + _n)
|
||||
|
||||
/*
|
||||
* Low-level PWM output interface.
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
*/
|
||||
|
||||
#define _RGBLEDIOCBASE (0x2900)
|
||||
#define _RGBLEDIOC(_n) (_IOC(_RGBLEDIOCBASE, _n))
|
||||
#define _RGBLEDIOC(_n) (_PX4_IOC(_RGBLEDIOCBASE, _n))
|
||||
|
||||
/** play the named script in *(char *)arg, repeating forever */
|
||||
#define RGBLED_PLAY_SCRIPT_NAMED _RGBLEDIOC(1)
|
||||
|
||||
+15
-10
@@ -40,6 +40,7 @@
|
||||
#ifndef _DRV_SENSOR_H
|
||||
#define _DRV_SENSOR_H
|
||||
|
||||
#include <px4_defines.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
@@ -51,15 +52,19 @@
|
||||
* Used to create a unique device id for redundant and combo sensors
|
||||
*/
|
||||
|
||||
#define DRV_MAG_DEVTYPE_HMC5883 0x01
|
||||
#define DRV_MAG_DEVTYPE_LSM303D 0x02
|
||||
#define DRV_ACC_DEVTYPE_LSM303D 0x11
|
||||
#define DRV_ACC_DEVTYPE_BMA180 0x12
|
||||
#define DRV_ACC_DEVTYPE_MPU6000 0x13
|
||||
#define DRV_GYR_DEVTYPE_MPU6000 0x21
|
||||
#define DRV_GYR_DEVTYPE_L3GD20 0x22
|
||||
#define DRV_RNG_DEVTYPE_MB12XX 0x31
|
||||
#define DRV_RNG_DEVTYPE_LL40LS 0x32
|
||||
#define DRV_MAG_DEVTYPE_HMC5883 0x01
|
||||
#define DRV_MAG_DEVTYPE_LSM303D 0x02
|
||||
#define DRV_MAG_DEVTYPE_ACCELSIM 0x03
|
||||
#define DRV_ACC_DEVTYPE_LSM303D 0x11
|
||||
#define DRV_ACC_DEVTYPE_BMA180 0x12
|
||||
#define DRV_ACC_DEVTYPE_MPU6000 0x13
|
||||
#define DRV_ACC_DEVTYPE_ACCELSIM 0x14
|
||||
#define DRV_ACC_DEVTYPE_GYROSIM 0x15
|
||||
#define DRV_GYR_DEVTYPE_MPU6000 0x21
|
||||
#define DRV_GYR_DEVTYPE_L3GD20 0x22
|
||||
#define DRV_GYR_DEVTYPE_GYROSIM 0x23
|
||||
#define DRV_RNG_DEVTYPE_MB12XX 0x31
|
||||
#define DRV_RNG_DEVTYPE_LL40LS 0x32
|
||||
|
||||
/*
|
||||
* ioctl() definitions
|
||||
@@ -69,7 +74,7 @@
|
||||
*/
|
||||
|
||||
#define _SENSORIOCBASE (0x2000)
|
||||
#define _SENSORIOC(_n) (_IOC(_SENSORIOCBASE, _n))
|
||||
#define _SENSORIOC(_n) (_PX4_IOC(_SENSORIOCBASE, _n))
|
||||
|
||||
/**
|
||||
* Set the driver polling rate to (arg) Hz, or one of the SENSOR_POLLRATE
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
#define TONEALARM0_DEVICE_PATH "/dev/tone_alarm0"
|
||||
|
||||
#define _TONE_ALARM_BASE 0x7400
|
||||
#define TONE_SET_ALARM _IOC(_TONE_ALARM_BASE, 1)
|
||||
#define TONE_SET_ALARM _PX4_IOC(_TONE_ALARM_BASE, 1)
|
||||
|
||||
/* structure describing one note in a tone pattern */
|
||||
struct tone_note {
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
* Driver for the Eagle Tree Airspeed V3 connected via I2C.
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <drivers/device/i2c.h>
|
||||
|
||||
|
||||
@@ -216,7 +216,7 @@ int frsky_telemetry_main(int argc, char *argv[])
|
||||
errx(0, "frsky_telemetry already running");
|
||||
|
||||
thread_should_exit = false;
|
||||
frsky_task = task_spawn_cmd("frsky_telemetry",
|
||||
frsky_task = px4_task_spawn_cmd("frsky_telemetry",
|
||||
SCHED_DEFAULT,
|
||||
SCHED_PRIORITY_DEFAULT,
|
||||
2000,
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
* and output via the standardized control group #2 and a mixer.
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
+17
-9
@@ -51,7 +51,7 @@
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <arch/board/board.h>
|
||||
#include <drivers/drv_hrt.h>
|
||||
@@ -229,7 +229,7 @@ GPS::init()
|
||||
goto out;
|
||||
|
||||
/* start the GPS driver worker task */
|
||||
_task = task_spawn_cmd("gps", SCHED_DEFAULT,
|
||||
_task = px4_task_spawn_cmd("gps", SCHED_DEFAULT,
|
||||
SCHED_PRIORITY_SLOW_DRIVER, 1500, (main_t)&GPS::task_main_trampoline, nullptr);
|
||||
|
||||
if (_task < 0) {
|
||||
@@ -354,6 +354,20 @@ GPS::task_main()
|
||||
if (_Helper->configure(_baudrate) == 0) {
|
||||
unlock();
|
||||
|
||||
//Publish initial report that we have access to a GPS
|
||||
//Make sure to clear any stale data in case driver is reset
|
||||
memset(&_report_gps_pos, 0, sizeof(_report_gps_pos));
|
||||
_report_gps_pos.timestamp_position = hrt_absolute_time();
|
||||
_report_gps_pos.timestamp_variance = hrt_absolute_time();
|
||||
_report_gps_pos.timestamp_velocity = hrt_absolute_time();
|
||||
_report_gps_pos.timestamp_time = hrt_absolute_time();
|
||||
if (_report_gps_pos_pub > 0) {
|
||||
orb_publish(ORB_ID(vehicle_gps_position), _report_gps_pos_pub, &_report_gps_pos);
|
||||
|
||||
} else {
|
||||
_report_gps_pos_pub = orb_advertise(ORB_ID(vehicle_gps_position), &_report_gps_pos);
|
||||
}
|
||||
|
||||
// GPS is obviously detected successfully, reset statistics
|
||||
_Helper->reset_update_rates();
|
||||
|
||||
@@ -364,13 +378,7 @@ GPS::task_main()
|
||||
|
||||
if (!(_pub_blocked)) {
|
||||
if (helper_ret & 1) {
|
||||
|
||||
if (_report_gps_pos_pub > 0) {
|
||||
orb_publish(ORB_ID(vehicle_gps_position), _report_gps_pos_pub, &_report_gps_pos);
|
||||
|
||||
} else {
|
||||
_report_gps_pos_pub = orb_advertise(ORB_ID(vehicle_gps_position), &_report_gps_pos);
|
||||
}
|
||||
orb_publish(ORB_ID(vehicle_gps_position), _report_gps_pos_pub, &_report_gps_pos);
|
||||
}
|
||||
if (_p_report_sat_info && (helper_ret & 2)) {
|
||||
if (_report_sat_info_pub > 0) {
|
||||
|
||||
+113
-76
@@ -48,7 +48,10 @@
|
||||
* driver. Use instead the normal FMU or IO driver.
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
#include <px4_tasks.h>
|
||||
#include <px4_time.h>
|
||||
#include <px4_common.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
@@ -60,11 +63,10 @@
|
||||
#include <poll.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <cmath>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
|
||||
#include <drivers/device/device.h>
|
||||
#include <drivers/drv_pwm_output.h>
|
||||
#include <drivers/drv_gpio.h>
|
||||
@@ -82,21 +84,25 @@
|
||||
|
||||
#include <systemlib/err.h>
|
||||
|
||||
#ifdef __PX4_NUTTX
|
||||
class HIL : public device::CDev
|
||||
#else
|
||||
class HIL : public device::VDev
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
enum Mode {
|
||||
MODE_2PWM,
|
||||
MODE_4PWM,
|
||||
MODE_8PWM,
|
||||
MODE_12PWM,
|
||||
MODE_16PWM,
|
||||
MODE_8PWM,
|
||||
MODE_12PWM,
|
||||
MODE_16PWM,
|
||||
MODE_NONE
|
||||
};
|
||||
HIL();
|
||||
virtual ~HIL();
|
||||
|
||||
virtual int ioctl(file *filp, int cmd, unsigned long arg);
|
||||
virtual int ioctl(device::file_t *filp, int cmd, unsigned long arg);
|
||||
|
||||
virtual int init();
|
||||
|
||||
@@ -131,7 +137,7 @@ private:
|
||||
uint8_t control_index,
|
||||
float &input);
|
||||
|
||||
int pwm_ioctl(file *filp, int cmd, unsigned long arg);
|
||||
int pwm_ioctl(device::file_t *filp, int cmd, unsigned long arg);
|
||||
|
||||
struct GPIOConfig {
|
||||
uint32_t input;
|
||||
@@ -146,7 +152,7 @@ private:
|
||||
void gpio_set_function(uint32_t gpios, int function);
|
||||
void gpio_write(uint32_t gpios, int function);
|
||||
uint32_t gpio_read(void);
|
||||
int gpio_ioctl(file *filp, int cmd, unsigned long arg);
|
||||
int gpio_ioctl(device::file_t *filp, int cmd, unsigned long arg);
|
||||
|
||||
};
|
||||
|
||||
@@ -158,7 +164,12 @@ HIL *g_hil;
|
||||
} // namespace
|
||||
|
||||
HIL::HIL() :
|
||||
CDev("hilservo", PWM_OUTPUT0_DEVICE_PATH/*"/dev/hil" XXXL*/),
|
||||
#ifdef __PX4_NUTTX
|
||||
CDev(
|
||||
#else
|
||||
VDev(
|
||||
#endif
|
||||
"hilservo", PWM_OUTPUT0_DEVICE_PATH/*"/dev/hil" XXXL*/),
|
||||
_mode(MODE_NONE),
|
||||
_update_rate(50),
|
||||
_current_update_rate(0),
|
||||
@@ -188,7 +199,7 @@ HIL::~HIL()
|
||||
|
||||
/* if we have given up, kill it */
|
||||
if (--i == 0) {
|
||||
task_delete(_task);
|
||||
px4_task_delete(_task);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -211,7 +222,11 @@ HIL::init()
|
||||
ASSERT(_task == -1);
|
||||
|
||||
/* do regular cdev init */
|
||||
#ifdef __PX4_NUTTX
|
||||
ret = CDev::init();
|
||||
#else
|
||||
ret = VDev::init();
|
||||
#endif
|
||||
|
||||
if (ret != OK)
|
||||
return ret;
|
||||
@@ -228,11 +243,11 @@ HIL::init()
|
||||
// gpio_reset();
|
||||
|
||||
/* start the HIL interface task */
|
||||
_task = task_spawn_cmd("fmuhil",
|
||||
_task = px4_task_spawn_cmd("fmuhil",
|
||||
SCHED_DEFAULT,
|
||||
SCHED_PRIORITY_DEFAULT,
|
||||
1200,
|
||||
(main_t)&HIL::task_main_trampoline,
|
||||
(px4_main_t)&HIL::task_main_trampoline,
|
||||
nullptr);
|
||||
|
||||
if (_task < 0) {
|
||||
@@ -273,22 +288,22 @@ HIL::set_mode(Mode mode)
|
||||
break;
|
||||
|
||||
case MODE_8PWM:
|
||||
debug("MODE_8PWM");
|
||||
/* multi-port as 8 PWM outs */
|
||||
_update_rate = 50; /* default output rate */
|
||||
break;
|
||||
debug("MODE_8PWM");
|
||||
/* multi-port as 8 PWM outs */
|
||||
_update_rate = 50; /* default output rate */
|
||||
break;
|
||||
|
||||
case MODE_12PWM:
|
||||
debug("MODE_12PWM");
|
||||
/* multi-port as 12 PWM outs */
|
||||
_update_rate = 50; /* default output rate */
|
||||
break;
|
||||
case MODE_12PWM:
|
||||
debug("MODE_12PWM");
|
||||
/* multi-port as 12 PWM outs */
|
||||
_update_rate = 50; /* default output rate */
|
||||
break;
|
||||
|
||||
case MODE_16PWM:
|
||||
debug("MODE_16PWM");
|
||||
/* multi-port as 16 PWM outs */
|
||||
_update_rate = 50; /* default output rate */
|
||||
break;
|
||||
case MODE_16PWM:
|
||||
debug("MODE_16PWM");
|
||||
/* multi-port as 16 PWM outs */
|
||||
_update_rate = 50; /* default output rate */
|
||||
break;
|
||||
|
||||
case MODE_NONE:
|
||||
debug("MODE_NONE");
|
||||
@@ -336,7 +351,7 @@ HIL::task_main()
|
||||
_t_outputs = orb_advertise_multi(ORB_ID(actuator_outputs),
|
||||
&outputs, &dummy, ORB_PRIO_LOW);
|
||||
|
||||
pollfd fds[2];
|
||||
px4_pollfd_struct_t fds[2];
|
||||
fds[0].fd = _t_actuators;
|
||||
fds[0].events = POLLIN;
|
||||
fds[1].fd = _t_armed;
|
||||
@@ -383,7 +398,7 @@ HIL::task_main()
|
||||
}
|
||||
|
||||
/* sleep waiting for data, but no more than a second */
|
||||
int ret = ::poll(&fds[0], 2, 1000);
|
||||
int ret = px4_poll(&fds[0], 2, 1000);
|
||||
|
||||
/* this would be bad... */
|
||||
if (ret < 0) {
|
||||
@@ -410,7 +425,7 @@ HIL::task_main()
|
||||
|
||||
/* last resort: catch NaN, INF and out-of-band errors */
|
||||
if (i < outputs.noutputs &&
|
||||
isfinite(outputs.output[i]) &&
|
||||
PX4_ISFINITE(outputs.output[i]) &&
|
||||
outputs.output[i] >= -1.0f &&
|
||||
outputs.output[i] <= 1.0f) {
|
||||
/* scale for PWM output 900 - 2100us */
|
||||
@@ -439,8 +454,8 @@ HIL::task_main()
|
||||
}
|
||||
}
|
||||
|
||||
::close(_t_actuators);
|
||||
::close(_t_armed);
|
||||
px4_close(_t_actuators);
|
||||
px4_close(_t_armed);
|
||||
|
||||
/* make sure servos are off */
|
||||
// up_pwm_servo_deinit();
|
||||
@@ -449,7 +464,6 @@ HIL::task_main()
|
||||
|
||||
/* tell the dtor that we are exiting */
|
||||
_task = -1;
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -465,7 +479,7 @@ HIL::control_callback(uintptr_t handle,
|
||||
}
|
||||
|
||||
int
|
||||
HIL::ioctl(file *filp, int cmd, unsigned long arg)
|
||||
HIL::ioctl(device::file_t *filp, int cmd, unsigned long arg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -480,9 +494,9 @@ HIL::ioctl(file *filp, int cmd, unsigned long arg)
|
||||
switch(_mode) {
|
||||
case MODE_2PWM:
|
||||
case MODE_4PWM:
|
||||
case MODE_8PWM:
|
||||
case MODE_12PWM:
|
||||
case MODE_16PWM:
|
||||
case MODE_8PWM:
|
||||
case MODE_12PWM:
|
||||
case MODE_16PWM:
|
||||
ret = HIL::pwm_ioctl(filp, cmd, arg);
|
||||
break;
|
||||
default:
|
||||
@@ -492,14 +506,19 @@ HIL::ioctl(file *filp, int cmd, unsigned long arg)
|
||||
}
|
||||
|
||||
/* if nobody wants it, let CDev have it */
|
||||
if (ret == -ENOTTY)
|
||||
if (ret == -ENOTTY) {
|
||||
#ifdef __PX4_NUTTX
|
||||
ret = CDev::ioctl(filp, cmd, arg);
|
||||
#else
|
||||
ret = VDev::ioctl(filp, cmd, arg);
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
HIL::pwm_ioctl(file *filp, int cmd, unsigned long arg)
|
||||
HIL::pwm_ioctl(device::file_t *filp, int cmd, unsigned long arg)
|
||||
{
|
||||
int ret = OK;
|
||||
// int channel;
|
||||
@@ -675,8 +694,8 @@ hil_new_mode(PortMode new_mode)
|
||||
case PORT_MODE_UNDEFINED:
|
||||
case PORT1_MODE_UNSET:
|
||||
case PORT2_MODE_UNSET:
|
||||
/* nothing more to do here */
|
||||
break;
|
||||
/* nothing more to do here */
|
||||
break;
|
||||
|
||||
case PORT1_FULL_PWM:
|
||||
/* select 4-pin PWM mode */
|
||||
@@ -695,20 +714,20 @@ hil_new_mode(PortMode new_mode)
|
||||
servo_mode = HIL::MODE_2PWM;
|
||||
break;
|
||||
|
||||
case PORT2_8PWM:
|
||||
/* select 8-pin PWM mode */
|
||||
servo_mode = HIL::MODE_8PWM;
|
||||
break;
|
||||
case PORT2_8PWM:
|
||||
/* select 8-pin PWM mode */
|
||||
servo_mode = HIL::MODE_8PWM;
|
||||
break;
|
||||
|
||||
case PORT2_12PWM:
|
||||
/* select 12-pin PWM mode */
|
||||
servo_mode = HIL::MODE_12PWM;
|
||||
break;
|
||||
case PORT2_12PWM:
|
||||
/* select 12-pin PWM mode */
|
||||
servo_mode = HIL::MODE_12PWM;
|
||||
break;
|
||||
|
||||
case PORT2_16PWM:
|
||||
/* select 16-pin PWM mode */
|
||||
servo_mode = HIL::MODE_16PWM;
|
||||
break;
|
||||
case PORT2_16PWM:
|
||||
/* select 16-pin PWM mode */
|
||||
servo_mode = HIL::MODE_16PWM;
|
||||
break;
|
||||
}
|
||||
|
||||
// /* adjust GPIO config for serial mode(s) */
|
||||
@@ -746,32 +765,32 @@ hil_start(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
test(void)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = open(PWM_OUTPUT0_DEVICE_PATH, 0);
|
||||
fd = px4_open(PWM_OUTPUT0_DEVICE_PATH, 0);
|
||||
|
||||
if (fd < 0) {
|
||||
puts("open fail");
|
||||
exit(1);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ioctl(fd, PWM_SERVO_ARM, 0);
|
||||
ioctl(fd, PWM_SERVO_SET(0), 1000);
|
||||
px4_ioctl(fd, PWM_SERVO_ARM, 0);
|
||||
px4_ioctl(fd, PWM_SERVO_SET(0), 1000);
|
||||
|
||||
close(fd);
|
||||
px4_close(fd);
|
||||
|
||||
exit(0);
|
||||
return OK;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
fake(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 5) {
|
||||
puts("hil fake <roll> <pitch> <yaw> <thrust> (values -100 .. 100)");
|
||||
exit(1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
actuator_controls_s ac;
|
||||
@@ -788,24 +807,39 @@ fake(int argc, char *argv[])
|
||||
|
||||
if (handle < 0) {
|
||||
puts("advertise failed");
|
||||
exit(1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
exit(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" __EXPORT int hil_main(int argc, char *argv[]);
|
||||
|
||||
static void
|
||||
usage() {
|
||||
fprintf(stderr, "HIL: unrecognized command, try:\n");
|
||||
fprintf(stderr, " mode_pwm, mode_gpio_serial, mode_pwm_serial, mode_pwm_gpio, mode_port2_pwm8, mode_port2_pwm12, mode_port2_pwm16\n");
|
||||
}
|
||||
|
||||
int
|
||||
hil_main(int argc, char *argv[])
|
||||
{
|
||||
PortMode new_mode = PORT_MODE_UNDEFINED;
|
||||
const char *verb = argv[1];
|
||||
const char *verb;
|
||||
int ret = OK;
|
||||
|
||||
if (hil_start() != OK)
|
||||
errx(1, "failed to start the HIL driver");
|
||||
if (hil_start() != OK) {
|
||||
warnx("failed to start the HIL driver");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (argc < 2) {
|
||||
usage();
|
||||
return -EINVAL;
|
||||
}
|
||||
verb = argv[1];
|
||||
|
||||
/*
|
||||
* Mode switches.
|
||||
@@ -842,14 +876,17 @@ hil_main(int argc, char *argv[])
|
||||
return hil_new_mode(new_mode);
|
||||
}
|
||||
|
||||
if (!strcmp(verb, "test"))
|
||||
test();
|
||||
if (!strcmp(verb, "test")) {
|
||||
ret = test();
|
||||
}
|
||||
|
||||
if (!strcmp(verb, "fake"))
|
||||
fake(argc - 1, argv + 1);
|
||||
else if (!strcmp(verb, "fake")) {
|
||||
ret = fake(argc - 1, argv + 1);
|
||||
}
|
||||
|
||||
|
||||
fprintf(stderr, "HIL: unrecognized command, try:\n");
|
||||
fprintf(stderr, " mode_pwm, mode_gpio_serial, mode_pwm_serial, mode_pwm_gpio, mode_port2_pwm8, mode_port2_pwm12, mode_port2_pwm16\n");
|
||||
return -EINVAL;
|
||||
else {
|
||||
usage();
|
||||
ret = -EINVAL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -38,5 +38,5 @@
|
||||
MODULE_COMMAND = hil
|
||||
|
||||
SRCS = hil.cpp
|
||||
|
||||
MAXOPTIMIZATION = -Os
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
* Driver for the HMC5883 / HMC5983 magnetometer connected via I2C or SPI.
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <drivers/device/i2c.h>
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
*/
|
||||
|
||||
/* XXX trim includes */
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
*/
|
||||
|
||||
/* XXX trim includes */
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
#include <poll.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@@ -209,7 +209,7 @@ hott_sensors_main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
thread_should_exit = false;
|
||||
deamon_task = task_spawn_cmd(daemon_name,
|
||||
deamon_task = px4_task_spawn_cmd(daemon_name,
|
||||
SCHED_DEFAULT,
|
||||
SCHED_PRIORITY_DEFAULT,
|
||||
1024,
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
#include <poll.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@@ -235,7 +235,7 @@ hott_telemetry_main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
thread_should_exit = false;
|
||||
deamon_task = task_spawn_cmd(daemon_name,
|
||||
deamon_task = px4_task_spawn_cmd(daemon_name,
|
||||
SCHED_DEFAULT,
|
||||
SCHED_PRIORITY_DEFAULT,
|
||||
2048,
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
* also supported by this driver.
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
@@ -195,7 +195,7 @@ static const int ERROR = -1;
|
||||
This time reduction is enough to cope with worst case timing jitter
|
||||
due to other timers
|
||||
*/
|
||||
#define L3GD20_TIMER_REDUCTION 200
|
||||
#define L3GD20_TIMER_REDUCTION 600
|
||||
|
||||
extern "C" { __EXPORT int l3gd20_main(int argc, char *argv[]); }
|
||||
|
||||
|
||||
+22
-3
@@ -37,9 +37,11 @@
|
||||
* LED driver.
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
#include <px4_posix.h>
|
||||
#include <drivers/device/device.h>
|
||||
#include <drivers/drv_led.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* Ideally we'd be able to get these from up_internal.h,
|
||||
@@ -55,18 +57,26 @@ extern void led_off(int led);
|
||||
extern void led_toggle(int led);
|
||||
__END_DECLS
|
||||
|
||||
#ifdef __PX4_NUTTX
|
||||
class LED : device::CDev
|
||||
#else
|
||||
class LED : device::VDev
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
LED();
|
||||
virtual ~LED();
|
||||
|
||||
virtual int init();
|
||||
virtual int ioctl(struct file *filp, int cmd, unsigned long arg);
|
||||
virtual int ioctl(device::file_t *filp, int cmd, unsigned long arg);
|
||||
};
|
||||
|
||||
LED::LED() :
|
||||
#ifdef __PX4_NUTTX
|
||||
CDev("led", LED0_DEVICE_PATH)
|
||||
#else
|
||||
VDev("led", LED0_DEVICE_PATH)
|
||||
#endif
|
||||
{
|
||||
// force immediate init/device registration
|
||||
init();
|
||||
@@ -79,14 +89,19 @@ LED::~LED()
|
||||
int
|
||||
LED::init()
|
||||
{
|
||||
debug("LED::init");
|
||||
#ifdef __PX4_NUTTX
|
||||
CDev::init();
|
||||
#else
|
||||
VDev::init();
|
||||
#endif
|
||||
led_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
LED::ioctl(struct file *filp, int cmd, unsigned long arg)
|
||||
LED::ioctl(device::file_t *filp, int cmd, unsigned long arg)
|
||||
{
|
||||
int result = OK;
|
||||
|
||||
@@ -105,7 +120,11 @@ LED::ioctl(struct file *filp, int cmd, unsigned long arg)
|
||||
|
||||
|
||||
default:
|
||||
#ifdef __PX4_NUTTX
|
||||
result = CDev::ioctl(filp, cmd, arg);
|
||||
#else
|
||||
result = VDev::ioctl(filp, cmd, arg);
|
||||
#endif
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
* Driver for the PulsedLight Lidar-Lite range finders connected via I2C.
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <drivers/device/i2c.h>
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
* Driver for the ST LSM303D MEMS accelerometer / magnetometer connected via SPI.
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
* Driver for the Maxbotix sonar range finders connected via I2C.
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <drivers/device/i2c.h>
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -110,7 +110,7 @@ int md25_main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
thread_should_exit = false;
|
||||
deamon_task = task_spawn_cmd("md25",
|
||||
deamon_task = px4_task_spawn_cmd("md25",
|
||||
SCHED_DEFAULT,
|
||||
SCHED_PRIORITY_MAX - 10,
|
||||
2048,
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <drivers/device/i2c.h>
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
#include <drivers/device/i2c.h>
|
||||
#include <systemlib/param/param.h>
|
||||
|
||||
@@ -302,7 +302,7 @@ MK::init(unsigned motors)
|
||||
}
|
||||
|
||||
/* start the IO interface task */
|
||||
_task = task_spawn_cmd("mkblctrl",
|
||||
_task = px4_task_spawn_cmd("mkblctrl",
|
||||
SCHED_DEFAULT,
|
||||
SCHED_PRIORITY_MAX - 20,
|
||||
1500,
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
* @author Marco Bauer <marco@wtns.de>
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
#include <systemlib/param/param.h>
|
||||
|
||||
/**
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
* @author Pat Hickey
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -37,6 +37,10 @@
|
||||
|
||||
MODULE_COMMAND = ms5611
|
||||
|
||||
SRCS = ms5611.cpp ms5611_spi.cpp ms5611_i2c.cpp
|
||||
ifeq ($(PX4_TARGET_OS),nuttx)
|
||||
SRCS = ms5611_nuttx.cpp ms5611_spi.cpp ms5611_i2c.cpp
|
||||
else
|
||||
SRCS = ms5611_posix.cpp ms5611_spi.cpp ms5611_i2c.cpp ms5611_sim.cpp
|
||||
endif
|
||||
|
||||
MAXOPTIMIZATION = -Os
|
||||
|
||||
@@ -80,6 +80,7 @@ extern bool crc4(uint16_t *n_prom);
|
||||
} /* namespace */
|
||||
|
||||
/* interface factories */
|
||||
extern device::Device *MS5611_spi_interface(ms5611::prom_u &prom_buf, uint8_t busnum) weak_function;
|
||||
extern device::Device *MS5611_i2c_interface(ms5611::prom_u &prom_buf, uint8_t busnum) weak_function;
|
||||
typedef device::Device *(*MS5611_constructor)(ms5611::prom_u &prom_buf, uint8_t busnum);
|
||||
extern device::Device *MS5611_spi_interface(ms5611::prom_u &prom_buf, uint8_t busnum) __attribute__((weak));
|
||||
extern device::Device *MS5611_i2c_interface(ms5611::prom_u &prom_buf, uint8_t busnum) __attribute__((weak));
|
||||
extern device::Device *MS5611_sim_interface(ms5611::prom_u &prom_buf, uint8_t busnum) __attribute__((weak));
|
||||
typedef device::Device* (*MS5611_constructor)(ms5611::prom_u &prom_buf, uint8_t busnum);
|
||||
|
||||
@@ -38,13 +38,14 @@
|
||||
*/
|
||||
|
||||
/* XXX trim includes */
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
#include <px4_defines.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
//#include <debug.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -70,16 +71,20 @@ public:
|
||||
virtual ~MS5611_I2C();
|
||||
|
||||
virtual int init();
|
||||
virtual int read(unsigned offset, void *data, unsigned count);
|
||||
virtual int ioctl(unsigned operation, unsigned &arg);
|
||||
virtual int dev_read(unsigned offset, void *data, unsigned count);
|
||||
virtual int dev_ioctl(unsigned operation, unsigned &arg);
|
||||
|
||||
#ifdef __PX4_NUTTX
|
||||
protected:
|
||||
virtual int probe();
|
||||
#endif
|
||||
|
||||
private:
|
||||
ms5611::prom_u &_prom;
|
||||
|
||||
#ifdef __PX4_NUTTX
|
||||
int _probe_address(uint8_t address);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Send a reset command to the MS5611.
|
||||
@@ -98,7 +103,7 @@ private:
|
||||
/**
|
||||
* Read the MS5611 PROM
|
||||
*
|
||||
* @return OK if the PROM reads successfully.
|
||||
* @return PX4_OK if the PROM reads successfully.
|
||||
*/
|
||||
int _read_prom();
|
||||
|
||||
@@ -111,7 +116,13 @@ MS5611_i2c_interface(ms5611::prom_u &prom_buf, uint8_t busnum)
|
||||
}
|
||||
|
||||
MS5611_I2C::MS5611_I2C(uint8_t bus, ms5611::prom_u &prom) :
|
||||
I2C("MS5611_I2C", nullptr, bus, 0, 400000),
|
||||
I2C("MS5611_I2C",
|
||||
#ifdef __PX4_NUTTX
|
||||
nullptr, bus, 0, 400000
|
||||
#else
|
||||
"/dev/MS5611_I2C", bus, 0
|
||||
#endif
|
||||
),
|
||||
_prom(prom)
|
||||
{
|
||||
}
|
||||
@@ -128,7 +139,7 @@ MS5611_I2C::init()
|
||||
}
|
||||
|
||||
int
|
||||
MS5611_I2C::read(unsigned offset, void *data, unsigned count)
|
||||
MS5611_I2C::dev_read(unsigned offset, void *data, unsigned count)
|
||||
{
|
||||
union _cvt {
|
||||
uint8_t b[4];
|
||||
@@ -139,7 +150,7 @@ MS5611_I2C::read(unsigned offset, void *data, unsigned count)
|
||||
/* read the most recent measurement */
|
||||
uint8_t cmd = 0;
|
||||
int ret = transfer(&cmd, 1, &buf[0], 3);
|
||||
if (ret == OK) {
|
||||
if (ret == PX4_OK) {
|
||||
/* fetch the raw value */
|
||||
cvt->b[0] = buf[2];
|
||||
cvt->b[1] = buf[1];
|
||||
@@ -151,7 +162,7 @@ MS5611_I2C::read(unsigned offset, void *data, unsigned count)
|
||||
}
|
||||
|
||||
int
|
||||
MS5611_I2C::ioctl(unsigned operation, unsigned &arg)
|
||||
MS5611_I2C::dev_ioctl(unsigned operation, unsigned &arg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -171,19 +182,20 @@ MS5611_I2C::ioctl(unsigned operation, unsigned &arg)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef __PX4_NUTTX
|
||||
int
|
||||
MS5611_I2C::probe()
|
||||
{
|
||||
_retries = 10;
|
||||
|
||||
if ((OK == _probe_address(MS5611_ADDRESS_1)) ||
|
||||
(OK == _probe_address(MS5611_ADDRESS_2))) {
|
||||
if ((PX4_OK == _probe_address(MS5611_ADDRESS_1)) ||
|
||||
(PX4_OK == _probe_address(MS5611_ADDRESS_2))) {
|
||||
/*
|
||||
* Disable retries; we may enable them selectively in some cases,
|
||||
* but the device gets confused if we retry some of the commands.
|
||||
*/
|
||||
_retries = 0;
|
||||
return OK;
|
||||
return PX4_OK;
|
||||
}
|
||||
|
||||
return -EIO;
|
||||
@@ -196,15 +208,16 @@ MS5611_I2C::_probe_address(uint8_t address)
|
||||
set_address(address);
|
||||
|
||||
/* send reset command */
|
||||
if (OK != _reset())
|
||||
if (PX4_OK != _reset())
|
||||
return -EIO;
|
||||
|
||||
/* read PROM */
|
||||
if (OK != _read_prom())
|
||||
if (PX4_OK != _read_prom())
|
||||
return -EIO;
|
||||
|
||||
return OK;
|
||||
return PX4_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
@@ -254,7 +267,7 @@ MS5611_I2C::_read_prom()
|
||||
for (int i = 0; i < 8; i++) {
|
||||
uint8_t cmd = ADDR_PROM_SETUP + (i * 2);
|
||||
|
||||
if (OK != transfer(&cmd, 1, &prom_buf[0], 2))
|
||||
if (PX4_OK != transfer(&cmd, 1, &prom_buf[0], 2))
|
||||
break;
|
||||
|
||||
/* assemble 16 bit value and convert from big endian (sensor) to little endian (MCU) */
|
||||
@@ -264,5 +277,5 @@ MS5611_I2C::_read_prom()
|
||||
}
|
||||
|
||||
/* calculate CRC and return success/failure accordingly */
|
||||
return ms5611::crc4(&_prom.c[0]) ? OK : -EIO;
|
||||
return ms5611::crc4(&_prom.c[0]) ? PX4_OK : -EIO;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
* Driver for the MS5611 barometric pressure sensor connected via I2C or SPI.
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,205 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2013 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file ms5611_i2c.cpp
|
||||
*
|
||||
* SIM interface for MS5611
|
||||
*/
|
||||
|
||||
/* XXX trim includes */
|
||||
#include <px4_config.h>
|
||||
#include <px4_defines.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
//#include <debug.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <drivers/device/sim.h>
|
||||
#include "ms5611.h"
|
||||
#include "board_config.h"
|
||||
|
||||
device::Device *MS5611_sim_interface(ms5611::prom_u &prom_buf);
|
||||
|
||||
class MS5611_SIM : public device::SIM
|
||||
{
|
||||
public:
|
||||
MS5611_SIM(uint8_t bus, ms5611::prom_u &prom_buf);
|
||||
virtual ~MS5611_SIM();
|
||||
|
||||
virtual int init();
|
||||
virtual int dev_read(unsigned offset, void *data, unsigned count);
|
||||
virtual int dev_ioctl(unsigned operation, unsigned &arg);
|
||||
|
||||
virtual int transfer(const uint8_t *send, unsigned send_len,
|
||||
uint8_t *recv, unsigned recv_len);
|
||||
private:
|
||||
ms5611::prom_u &_prom;
|
||||
|
||||
/**
|
||||
* Send a reset command to the MS5611.
|
||||
*
|
||||
* This is required after any bus reset.
|
||||
*/
|
||||
int _reset();
|
||||
|
||||
/**
|
||||
* Send a measure command to the MS5611.
|
||||
*
|
||||
* @param addr Which address to use for the measure operation.
|
||||
*/
|
||||
int _measure(unsigned addr);
|
||||
|
||||
/**
|
||||
* Read the MS5611 PROM
|
||||
*
|
||||
* @return PX4_OK if the PROM reads successfully.
|
||||
*/
|
||||
int _read_prom();
|
||||
|
||||
};
|
||||
|
||||
device::Device *
|
||||
MS5611_sim_interface(ms5611::prom_u &prom_buf, uint8_t busnum)
|
||||
{
|
||||
return new MS5611_SIM(busnum, prom_buf);
|
||||
}
|
||||
|
||||
MS5611_SIM::MS5611_SIM(uint8_t bus, ms5611::prom_u &prom) :
|
||||
SIM("MS5611_SIM", "/dev/MS5611_SIM", bus, 0),
|
||||
_prom(prom)
|
||||
{
|
||||
}
|
||||
|
||||
MS5611_SIM::~MS5611_SIM()
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
MS5611_SIM::init()
|
||||
{
|
||||
return SIM::init();
|
||||
}
|
||||
|
||||
int
|
||||
MS5611_SIM::dev_read(unsigned offset, void *data, unsigned count)
|
||||
{
|
||||
union _cvt {
|
||||
uint8_t b[4];
|
||||
uint32_t w;
|
||||
} *cvt = (_cvt *)data;
|
||||
uint8_t buf[3];
|
||||
|
||||
/* read the most recent measurement */
|
||||
uint8_t cmd = 0;
|
||||
int ret = transfer(&cmd, 1, &buf[0], 3);
|
||||
if (ret == PX4_OK) {
|
||||
/* fetch the raw value */
|
||||
cvt->b[0] = buf[2];
|
||||
cvt->b[1] = buf[1];
|
||||
cvt->b[2] = buf[0];
|
||||
cvt->b[3] = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
MS5611_SIM::dev_ioctl(unsigned operation, unsigned &arg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (operation) {
|
||||
case IOCTL_RESET:
|
||||
ret = _reset();
|
||||
break;
|
||||
|
||||
case IOCTL_MEASURE:
|
||||
ret = _measure(arg);
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
MS5611_SIM::_reset()
|
||||
{
|
||||
unsigned old_retrycount = _retries;
|
||||
uint8_t cmd = ADDR_RESET_CMD;
|
||||
int result;
|
||||
|
||||
/* bump the retry count */
|
||||
_retries = 10;
|
||||
result = transfer(&cmd, 1, nullptr, 0);
|
||||
_retries = old_retrycount;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
MS5611_SIM::_measure(unsigned addr)
|
||||
{
|
||||
/*
|
||||
* Disable retries on this command; we can't know whether failure
|
||||
* means the device did or did not see the command.
|
||||
*/
|
||||
_retries = 0;
|
||||
|
||||
uint8_t cmd = addr;
|
||||
return transfer(&cmd, 1, nullptr, 0);
|
||||
}
|
||||
|
||||
int
|
||||
MS5611_SIM::_read_prom()
|
||||
{
|
||||
int ret = 1;
|
||||
// TODO input simlation data
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
MS5611_SIM::transfer(const uint8_t *send, unsigned send_len,
|
||||
uint8_t *recv, unsigned recv_len)
|
||||
{
|
||||
// TODO add Simulation data connection so calls retrieve
|
||||
// data from the simulator
|
||||
return 0;
|
||||
}
|
||||
@@ -38,13 +38,13 @@
|
||||
*/
|
||||
|
||||
/* XXX trim includes */
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
//#include <debug.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <drivers/device/i2c.h>
|
||||
#include <drivers/drv_hrt.h>
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
* @author Anton Babushkin <anton.babushkin@me.com>
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <drivers/device/i2c.h>
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
* @author Thomas Gubler <thomasgubler@gmail.com>
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <drivers/device/i2c.h>
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
* which in turn was based on drv_hrt.c
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
* Driver for the PX4FLOW module connected via I2C.
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <drivers/device/i2c.h>
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
* Driver/configurator for the PX4 FMU multi-purpose port on v1 and v2 boards.
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
@@ -341,7 +341,7 @@ PX4FMU::init()
|
||||
gpio_reset();
|
||||
|
||||
/* start the IO interface task */
|
||||
_task = task_spawn_cmd("fmuservo",
|
||||
_task = px4_task_spawn_cmd("fmuservo",
|
||||
SCHED_DEFAULT,
|
||||
SCHED_PRIORITY_DEFAULT,
|
||||
1600,
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
* PX4IO is connected via I2C or DMA enabled high-speed UART.
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
@@ -854,7 +854,7 @@ PX4IO::init()
|
||||
}
|
||||
|
||||
/* start the IO interface task */
|
||||
_task = task_spawn_cmd("px4io",
|
||||
_task = px4_task_spawn_cmd("px4io",
|
||||
SCHED_DEFAULT,
|
||||
SCHED_PRIORITY_ACTUATOR_OUTPUTS,
|
||||
1800,
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
*/
|
||||
|
||||
/* XXX trim includes */
|
||||
#include <nuttx/config.h>
|
||||
#include <px4_config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user