Changed device::px4_device_handle_t to device::file_t

This change allowed the _posix.cpp file changes to be merged
back into the original files.

Signed-off-by: Mark Charlebois <charlebm@gmail.com>
This commit is contained in:
Mark Charlebois
2015-04-24 17:49:35 -07:00
parent 20d35e33da
commit d913ec8dc9
28 changed files with 600 additions and 1327 deletions
+2 -2
View File
@@ -140,7 +140,7 @@ public:
virtual int init();
virtual int probe();
virtual int setMode(int mode);
virtual int ioctl(device::px4_dev_handle_t *handlep, int cmd, unsigned long arg);
virtual int ioctl(device::file_t *filp, int cmd, unsigned long arg);
static const char *const script_names[];
@@ -358,7 +358,7 @@ BlinkM::probe()
}
int
BlinkM::ioctl(device::px4_dev_handle_t *handlep, int cmd, unsigned long arg)
BlinkM::ioctl(device::file_t *filp, int cmd, unsigned long arg)
{
int ret = ENOTTY;
@@ -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);
+15 -12
View File
@@ -44,6 +44,7 @@
* 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>
@@ -59,6 +60,8 @@
namespace device __EXPORT
{
typedef struct file file_t;
/**
* Fundamental base class for all device drivers.
*
@@ -275,7 +278,7 @@ public:
* @param filp Pointer to the NuttX file structure.
* @return OK if the open is allowed, -errno otherwise.
*/
virtual int open(struct file *filp);
virtual int open(file_t *filp);
/**
* Handle a close of the device.
@@ -286,7 +289,7 @@ public:
* @param filp Pointer to the NuttX file structure.
* @return OK if the close was successful, -errno otherwise.
*/
virtual int close(struct file *filp);
virtual int close(file_t *filp);
/**
* Perform a read from the device.
@@ -298,7 +301,7 @@ public:
* @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);
virtual ssize_t read(file_t *filp, char *buffer, size_t buflen);
/**
* Perform a write to the device.
@@ -310,7 +313,7 @@ public:
* @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);
virtual ssize_t write(file_t *filp, const char *buffer, size_t buflen);
/**
* Perform a logical seek operation on the device.
@@ -322,7 +325,7 @@ public:
* @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);
virtual off_t seek(file_t *filp, off_t offset, int whence);
/**
* Perform an ioctl operation on the device.
@@ -336,7 +339,7 @@ public:
* @param arg The ioctl argument value.
* @return OK on success, or -errno otherwise.
*/
virtual int ioctl(struct file *filp, int cmd, unsigned long arg);
virtual int ioctl(file_t *filp, int cmd, unsigned long arg);
/**
* Perform a poll setup/teardown operation.
@@ -349,7 +352,7 @@ public:
* it is being torn down.
* @return OK on success, or -errno otherwise.
*/
virtual int poll(struct file *filp, struct pollfd *fds, bool setup);
virtual int poll(file_t *filp, struct pollfd *fds, bool setup);
/**
* Test whether the device is currently open.
@@ -380,7 +383,7 @@ protected:
* @param filp The file that's interested.
* @return The current set of poll events.
*/
virtual pollevent_t poll_state(struct file *filp);
virtual pollevent_t poll_state(file_t *filp);
/**
* Report new poll events.
@@ -398,7 +401,7 @@ protected:
* @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);
virtual void poll_notify_one(px4_pollfd_struct_t *fds, pollevent_t events);
/**
* Notification of the first open.
@@ -411,7 +414,7 @@ protected:
* @param filp Pointer to the NuttX file structure.
* @return OK if the open should proceed, -errno otherwise.
*/
virtual int open_first(struct file *filp);
virtual int open_first(file_t *filp);
/**
* Notification of the last close.
@@ -424,7 +427,7 @@ protected:
* @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);
virtual int close_last(file_t *filp);
/**
* Register a class device name, automatically adding device
@@ -470,7 +473,7 @@ private:
*
* @return OK, or -errno on error.
*/
int store_poll_waiter(struct pollfd *fds);
int store_poll_waiter(px4_pollfd_struct_t *fds);
/**
* Remove a poll waiter.
+4 -4
View File
@@ -221,7 +221,7 @@ I2C::transfer(struct i2c_msg *msgv, unsigned msgs)
return ret;
}
int I2C::ioctl(device::px4_dev_handle_t *handlep, int cmd, unsigned long arg)
int I2C::ioctl(device::file_t *filp, int cmd, unsigned long arg)
{
//struct i2c_rdwr_ioctl_data *packets = (i2c_rdwr_ioctl_data *)(void *)arg;
@@ -231,11 +231,11 @@ int I2C::ioctl(device::px4_dev_handle_t *handlep, int cmd, unsigned long arg)
return 0;
default:
/* give it to the superclass */
return VDev::ioctl(handlep, cmd, arg);
return VDev::ioctl(filp, cmd, arg);
}
}
ssize_t I2C::read(px4_dev_handle_t *handlep, char *buffer, size_t buflen)
ssize_t I2C::read(file_t *filp, char *buffer, size_t buflen)
{
if (simulate) {
// FIXME no idea what this should be
@@ -246,7 +246,7 @@ ssize_t I2C::read(px4_dev_handle_t *handlep, char *buffer, size_t buflen)
return ::read(_fd, buffer, buflen);
}
ssize_t I2C::write(px4_dev_handle_t *handlep, const char *buffer, size_t buflen)
ssize_t I2C::write(file_t *filp, const char *buffer, size_t buflen)
{
if (simulate) {
warnx ("2C SIM I2C::write");
+3 -3
View File
@@ -93,9 +93,9 @@ protected:
virtual int init();
virtual ssize_t read(px4_dev_handle_t *handlep, char *buffer, size_t buflen);
virtual ssize_t write(px4_dev_handle_t *handlep, const char *buffer, size_t buflen);
virtual int ioctl(device::px4_dev_handle_t *handlep, int cmd, unsigned long arg);
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.
+4 -3
View File
@@ -38,14 +38,15 @@
ifeq ($(PX4_TARGET_OS),nuttx)
SRCS = \
device_nuttx.cpp \
cdev_nuttx.cpp \
cdev.cpp \
i2c_nuttx.cpp \
pio.cpp \
spi.cpp \
ringbuffer.cpp
else
SRCS = vdev.cpp \
device.cpp \
SRCS = \
device_posix.cpp \
vdev.cpp \
vdev_posix.cpp \
i2c_posix.cpp \
sim.cpp \
+15 -15
View File
@@ -207,7 +207,7 @@ out:
* Default implementations of the character device interface
*/
int
VDev::open(px4_dev_handle_t *handlep)
VDev::open(file_t *filep)
{
int ret = PX4_OK;
@@ -219,7 +219,7 @@ VDev::open(px4_dev_handle_t *handlep)
if (_open_count == 1) {
/* first-open callback may decline the open */
ret = open_first(handlep);
ret = open_first(filep);
if (ret != PX4_OK)
_open_count--;
@@ -231,14 +231,14 @@ VDev::open(px4_dev_handle_t *handlep)
}
int
VDev::open_first(px4_dev_handle_t *handlep)
VDev::open_first(file_t *filep)
{
debug("VDev::open_first");
return PX4_OK;
}
int
VDev::close(px4_dev_handle_t *handlep)
VDev::close(file_t *filep)
{
debug("VDev::close");
int ret = PX4_OK;
@@ -251,7 +251,7 @@ VDev::close(px4_dev_handle_t *handlep)
/* callback cannot decline the close */
if (_open_count == 0)
ret = close_last(handlep);
ret = close_last(filep);
} else {
ret = -EBADF;
@@ -263,34 +263,34 @@ VDev::close(px4_dev_handle_t *handlep)
}
int
VDev::close_last(px4_dev_handle_t *handlep)
VDev::close_last(file_t *filep)
{
debug("VDev::close_last");
return PX4_OK;
}
ssize_t
VDev::read(px4_dev_handle_t *handlep, char *buffer, size_t buflen)
VDev::read(file_t *filep, char *buffer, size_t buflen)
{
debug("VDev::read");
return -ENOSYS;
}
ssize_t
VDev::write(px4_dev_handle_t *handlep, const char *buffer, size_t buflen)
VDev::write(file_t *filep, const char *buffer, size_t buflen)
{
debug("VDev::write");
return -ENOSYS;
}
off_t
VDev::seek(px4_dev_handle_t *handlep, off_t offset, int whence)
VDev::seek(file_t *filep, off_t offset, int whence)
{
return -ENOSYS;
}
int
VDev::ioctl(px4_dev_handle_t *handlep, int cmd, unsigned long arg)
VDev::ioctl(file_t *filep, int cmd, unsigned long arg)
{
int ret = -ENOTTY;
@@ -320,7 +320,7 @@ VDev::ioctl(px4_dev_handle_t *handlep, int cmd, unsigned long arg)
}
int
VDev::poll(px4_dev_handle_t *handlep, px4_pollfd_struct_t *fds, bool setup)
VDev::poll(file_t *filep, px4_pollfd_struct_t *fds, bool setup)
{
int ret = PX4_OK;
debug("VDev::Poll %s", setup ? "setup" : "teardown");
@@ -335,8 +335,8 @@ VDev::poll(px4_dev_handle_t *handlep, px4_pollfd_struct_t *fds, bool setup)
* Save the file pointer in the pollfd for the subclass'
* benefit.
*/
fds->priv = (void *)handlep;
debug("VDev::poll: fds->priv = %p", handlep);
fds->priv = (void *)filep;
debug("VDev::poll: fds->priv = %p", filep);
/*
* Handle setup requests.
@@ -349,7 +349,7 @@ VDev::poll(px4_dev_handle_t *handlep, px4_pollfd_struct_t *fds, bool setup)
* Check to see whether we should send a poll notification
* immediately.
*/
fds->revents |= fds->events & poll_state(handlep);
fds->revents |= fds->events & poll_state(filep);
/* yes? post the notification */
if (fds->revents != 0)
@@ -402,7 +402,7 @@ VDev::poll_notify_one(px4_pollfd_struct_t *fds, pollevent_t events)
}
pollevent_t
VDev::poll_state(px4_dev_handle_t *handlep)
VDev::poll_state(file_t *filep)
{
debug("VDev::poll_notify");
/* by default, no poll events to report */
+23 -26
View File
@@ -57,17 +57,14 @@
namespace device __EXPORT
{
#define PX4_F_RDONLY 1
#define PX4_F_WRONLY 2
struct px4_dev_handle_t {
struct file_t {
int fd;
int flags;
void *priv;
void *vdev;
px4_dev_handle_t() : fd(-1), flags(0), priv(NULL), vdev(NULL) {}
px4_dev_handle_t(int f, void *c, int d) : fd(d), flags(f), priv(NULL), vdev(c) {}
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) {}
};
/**
@@ -242,13 +239,13 @@ public:
*
* This is handled internally and should not normally be overridden.
*
* @param handlep Pointer to the internal file structure.
* @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(px4_dev_handle_t *handlep, px4_pollfd_struct_t *fds, bool setup);
virtual int poll(file_t *filep, px4_pollfd_struct_t *fds, bool setup);
/**
* Test whether the device is currently open.
@@ -266,10 +263,10 @@ public:
* This function is called for every open of the device. The default
* implementation maintains _open_count and always returns OK.
*
* @param handlep Pointer to the NuttX file structure.
* @param filep Pointer to the NuttX file structure.
* @return OK if the open is allowed, -errno otherwise.
*/
virtual int open(px4_dev_handle_t *handlep);
virtual int open(file_t *filep);
/**
* Handle a close of the device.
@@ -277,46 +274,46 @@ public:
* 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 handlep Pointer to the NuttX file structure.
* @param filep Pointer to the NuttX file structure.
* @return OK if the close was successful, -errno otherwise.
*/
virtual int close(px4_dev_handle_t *handlep);
virtual int close(file_t *filep);
/**
* Perform a read from the device.
*
* The default implementation returns -ENOSYS.
*
* @param handlep Pointer to the NuttX file structure.
* @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(px4_dev_handle_t *handlep, char *buffer, size_t buflen);
virtual ssize_t read(file_t *filep, char *buffer, size_t buflen);
/**
* Perform a write to the device.
*
* The default implementation returns -ENOSYS.
*
* @param handlep Pointer to the NuttX file structure.
* @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(px4_dev_handle_t *handlep, const char *buffer, size_t buflen);
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 handlep Pointer to the NuttX file structure.
* @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(px4_dev_handle_t *handlep, off_t offset, int whence);
virtual off_t seek(file_t *filep, off_t offset, int whence);
/**
* Perform an ioctl operation on the device.
@@ -325,12 +322,12 @@ public:
* returns -ENOTTY. Subclasses should call the default implementation
* for any command they do not handle themselves.
*
* @param handlep Pointer to the NuttX file structure.
* @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(px4_dev_handle_t *handlep, int cmd, unsigned long arg);
virtual int ioctl(file_t *filep, int cmd, unsigned long arg);
static VDev *getDev(const char *path);
static void showDevices(void);
@@ -352,10 +349,10 @@ protected:
*
* The default implementation returns no events.
*
* @param handlep The file that's interested.
* @param filep The file that's interested.
* @return The current set of poll events.
*/
virtual pollevent_t poll_state(px4_dev_handle_t *handlep);
virtual pollevent_t poll_state(file_t *filep);
/**
* Report new poll events.
@@ -383,10 +380,10 @@ protected:
*
* The default implementation returns OK.
*
* @param handlep Pointer to the NuttX file structure.
* @param filep Pointer to the NuttX file structure.
* @return OK if the open should proceed, -errno otherwise.
*/
virtual int open_first(px4_dev_handle_t *handlep);
virtual int open_first(file_t *filep);
/**
* Notification of the last close.
@@ -396,10 +393,10 @@ protected:
*
* The default implementation returns OK.
*
* @param handlep Pointer to the NuttX file structure.
* @param filep Pointer to the NuttX file structure.
* @return OK if the open should return OK, -errno otherwise.
*/
virtual int close_last(px4_dev_handle_t *handlep);
virtual int close_last(file_t *filep);
/**
* Register a class device name, automatically adding device
+5 -3
View File
@@ -32,7 +32,7 @@
****************************************************************************/
/**
* @file vcdev_posix.cpp
* @file vdev_posix.cpp
*
* POSIX-like API for virtual character device
*/
@@ -47,6 +47,8 @@
#include <pthread.h>
#include <unistd.h>
#define PX4_DEBUG(...)
using namespace device;
extern "C" {
@@ -74,7 +76,7 @@ static void *timer_handler(void *data)
}
#define PX4_MAX_FD 100
static px4_dev_handle_t *filemap[PX4_MAX_FD] = {};
static device::file_t *filemap[PX4_MAX_FD] = {};
int px4_errno;
@@ -95,7 +97,7 @@ int px4_open(const char *path, int flags)
else {
for (i=0; i<PX4_MAX_FD; ++i) {
if (filemap[i] == 0) {
filemap[i] = new px4_dev_handle_t(flags,dev,i);
filemap[i] = new device::file_t(flags,dev,i);
break;
}
}
+112 -75
View File
@@ -49,6 +49,9 @@
*/
#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;
}
-873
View File
@@ -1,873 +0,0 @@
/****************************************************************************
*
* 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 hil_linux.cpp
*
* Driver/configurator for the virtual HIL port.
*
* This virtual driver emulates PWM / servo outputs for setups where
* the connected hardware does not provide enough or no PWM outputs.
*
* Its only function is to take actuator_control uORB messages,
* mix them with any loaded mixer and output the result to the
* actuator_output uORB topic. HIL can also be performed with normal
* PWM outputs, a special flag prevents the outputs to be operated
* during HIL mode. If HIL is not performed with a standalone FMU,
* but in a real system, it is NOT recommended to use this virtual
* driver. Use instead the normal FMU or IO driver.
*/
#include <px4_config.h>
#include <px4_tasks.h>
#include <px4_time.h>
#include <px4_common.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <semaphore.h>
#include <string.h>
#include <fcntl.h>
#include <poll.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <cmath>
#include <unistd.h>
#include <drivers/device/device.h>
#include <drivers/drv_pwm_output.h>
#include <drivers/drv_gpio.h>
#include <drivers/drv_hrt.h>
#include <drivers/drv_mixer.h>
#include <systemlib/systemlib.h>
#include <systemlib/mixer/mixer.h>
#include <uORB/topics/actuator_controls.h>
#include <uORB/topics/actuator_controls_0.h>
#include <uORB/topics/actuator_controls_1.h>
#include <uORB/topics/actuator_armed.h>
#include <uORB/topics/actuator_outputs.h>
#include <systemlib/err.h>
class HIL : public device::VDev
{
public:
enum Mode {
MODE_2PWM,
MODE_4PWM,
MODE_8PWM,
MODE_12PWM,
MODE_16PWM,
MODE_NONE
};
HIL();
virtual ~HIL();
virtual int ioctl(device::px4_dev_handle_t *handlep, int cmd, unsigned long arg);
virtual int init();
int set_mode(Mode mode);
int set_pwm_rate(unsigned rate);
private:
static const unsigned _max_actuators = 4;
Mode _mode;
int _update_rate;
int _current_update_rate;
int _task;
int _t_actuators;
int _t_armed;
orb_advert_t _t_outputs;
unsigned _num_outputs;
bool _primary_pwm_device;
volatile bool _task_should_exit;
bool _armed;
MixerGroup *_mixers;
actuator_controls_s _controls;
static void task_main_trampoline(int argc, char *argv[]);
void task_main();
static int control_callback(uintptr_t handle,
uint8_t control_group,
uint8_t control_index,
float &input);
int pwm_ioctl(device::px4_dev_handle_t *handlep, int cmd, unsigned long arg);
struct GPIOConfig {
uint32_t input;
uint32_t output;
uint32_t alt;
};
static const GPIOConfig _gpio_tab[];
static const unsigned _ngpio;
void gpio_reset(void);
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(device::px4_dev_handle_t *handlep, int cmd, unsigned long arg);
};
namespace
{
HIL *g_hil;
} // namespace
HIL::HIL() :
VDev("hilservo", PWM_OUTPUT0_DEVICE_PATH/*"/dev/hil" XXXL*/),
_mode(MODE_NONE),
_update_rate(50),
_current_update_rate(0),
_task(-1),
_t_actuators(-1),
_t_armed(-1),
_t_outputs(0),
_num_outputs(0),
_primary_pwm_device(false),
_task_should_exit(false),
_armed(false),
_mixers(nullptr)
{
_debug_enabled = true;
}
HIL::~HIL()
{
if (_task != -1) {
/* tell the task we want it to go away */
_task_should_exit = true;
unsigned i = 10;
do {
/* wait 50ms - it should wake every 100ms or so worst-case */
usleep(50000);
/* if we have given up, kill it */
if (--i == 0) {
px4_task_delete(_task);
break;
}
} while (_task != -1);
}
// XXX already claimed with CDEV
// /* clean up the alternate device node */
// if (_primary_pwm_device)
// unregister_driver(PWM_OUTPUT_DEVICE_PATH);
g_hil = nullptr;
}
int
HIL::init()
{
int ret;
ASSERT(_task == -1);
/* do regular cdev init */
ret = VDev::init();
if (ret != PX4_OK)
return ret;
// XXX already claimed with CDEV
///* try to claim the generic PWM output device node as well - it's OK if we fail at this */
//ret = register_driver(PWM_OUTPUT_DEVICE_PATH, &fops, 0666, (void *)this);
if (ret == PX4_OK) {
log("default PWM output device");
_primary_pwm_device = true;
}
/* reset GPIOs */
// gpio_reset();
/* start the HIL interface task */
_task = px4_task_spawn_cmd("fmuhil",
SCHED_DEFAULT,
SCHED_PRIORITY_DEFAULT,
1200,
(px4_main_t)&HIL::task_main_trampoline,
nullptr);
if (_task < 0) {
debug("task start failed: %d", errno);
return -errno;
}
return PX4_OK;
}
void
HIL::task_main_trampoline(int argc, char *argv[])
{
g_hil->task_main();
}
int
HIL::set_mode(Mode mode)
{
/*
* Configure for PWM output.
*
* Note that regardless of the configured mode, the task is always
* listening and mixing; the mode just selects which of the channels
* are presented on the output pins.
*/
switch (mode) {
case MODE_2PWM:
debug("MODE_2PWM");
/* multi-port with flow control lines as PWM */
_update_rate = 50; /* default output rate */
break;
case MODE_4PWM:
debug("MODE_4PWM");
/* multi-port as 4 PWM outs */
_update_rate = 50; /* default output rate */
break;
case MODE_8PWM:
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_16PWM:
debug("MODE_16PWM");
/* multi-port as 16 PWM outs */
_update_rate = 50; /* default output rate */
break;
case MODE_NONE:
debug("MODE_NONE");
/* disable servo outputs and set a very low update rate */
_update_rate = 10;
break;
default:
return -EINVAL;
}
_mode = mode;
return PX4_OK;
}
int
HIL::set_pwm_rate(unsigned rate)
{
if ((rate > 500) || (rate < 10))
return -EINVAL;
_update_rate = rate;
return PX4_OK;
}
void
HIL::task_main()
{
/*
* Subscribe to the appropriate PWM output topic based on whether we are the
* primary PWM output or not.
*/
_t_actuators = orb_subscribe(_primary_pwm_device ? ORB_ID_VEHICLE_ATTITUDE_CONTROLS :
ORB_ID(actuator_controls_1));
/* force a reset of the update rate */
_current_update_rate = 0;
_t_armed = orb_subscribe(ORB_ID(actuator_armed));
orb_set_interval(_t_armed, 200); /* 5Hz update rate */
/* advertise the mixed control outputs */
actuator_outputs_s outputs;
memset(&outputs, 0, sizeof(outputs));
/* advertise the mixed control outputs */
int dummy;
_t_outputs = orb_advertise_multi(ORB_ID(actuator_outputs),
&outputs, &dummy, ORB_PRIO_LOW);
px4_pollfd_struct_t fds[2];
fds[0].fd = _t_actuators;
fds[0].events = POLLIN;
fds[1].fd = _t_armed;
fds[1].events = POLLIN;
unsigned num_outputs;
/* select the number of virtual outputs */
switch (_mode) {
case MODE_2PWM:
num_outputs = 2;
break;
case MODE_4PWM:
num_outputs = 4;
break;
case MODE_8PWM:
case MODE_12PWM:
case MODE_16PWM:
// XXX only support the lower 8 - trivial to extend
num_outputs = 8;
break;
case MODE_NONE:
default:
num_outputs = 0;
break;
}
log("starting");
/* loop until killed */
while (!_task_should_exit) {
/* handle update rate changes */
if (_current_update_rate != _update_rate) {
int update_rate_in_ms = int(1000 / _update_rate);
if (update_rate_in_ms < 2)
update_rate_in_ms = 2;
orb_set_interval(_t_actuators, update_rate_in_ms);
// up_pwm_servo_set_rate(_update_rate);
_current_update_rate = _update_rate;
}
/* sleep waiting for data, but no more than a second */
int ret = px4_poll(&fds[0], 2, 1000);
/* this would be bad... */
if (ret < 0) {
log("poll error %d", errno);
continue;
}
/* do we have a control update? */
if (fds[0].revents & POLLIN) {
/* get controls - must always do this to avoid spinning */
orb_copy(_primary_pwm_device ? ORB_ID_VEHICLE_ATTITUDE_CONTROLS :
ORB_ID(actuator_controls_1), _t_actuators, &_controls);
/* can we mix? */
if (_mixers != nullptr) {
/* do mixing */
outputs.noutputs = _mixers->mix(&outputs.output[0], num_outputs, NULL);
outputs.timestamp = hrt_absolute_time();
/* iterate actuators */
for (unsigned i = 0; i < num_outputs; i++) {
/* last resort: catch NaN, INF and out-of-band errors */
if (i < outputs.noutputs &&
PX4_ISFINITE(outputs.output[i]) &&
outputs.output[i] >= -1.0f &&
outputs.output[i] <= 1.0f) {
/* scale for PWM output 900 - 2100us */
outputs.output[i] = 1500 + (600 * outputs.output[i]);
} else {
/*
* Value is NaN, INF or out of band - set to the minimum value.
* This will be clearly visible on the servo status and will limit the risk of accidentally
* spinning motors. It would be deadly in flight.
*/
outputs.output[i] = 900;
}
}
/* and publish for anyone that cares to see */
orb_publish(ORB_ID(actuator_outputs), _t_outputs, &outputs);
}
}
/* how about an arming update? */
if (fds[1].revents & POLLIN) {
actuator_armed_s aa;
/* get new value */
orb_copy(ORB_ID(actuator_armed), _t_armed, &aa);
}
}
px4_close(_t_actuators);
px4_close(_t_armed);
/* make sure servos are off */
// up_pwm_servo_deinit();
/* note - someone else is responsible for restoring the GPIO config */
/* tell the dtor that we are exiting */
_task = -1;
}
int
HIL::control_callback(uintptr_t handle,
uint8_t control_group,
uint8_t control_index,
float &input)
{
const actuator_controls_s *controls = (actuator_controls_s *)handle;
input = controls->control[control_index];
return 0;
}
int
HIL::ioctl(device::px4_dev_handle_t *handlep, int cmd, unsigned long arg)
{
int ret;
debug("ioctl 0x%04x 0x%08x", cmd, arg);
// /* try it as a GPIO ioctl first */
// ret = HIL::gpio_ioctl(handlep, cmd, arg);
// if (ret != -ENOTTY)
// return ret;
/* if we are in valid PWM mode, try it as a PWM ioctl as well */
switch(_mode) {
case MODE_2PWM:
case MODE_4PWM:
case MODE_8PWM:
case MODE_12PWM:
case MODE_16PWM:
ret = HIL::pwm_ioctl(handlep, cmd, arg);
break;
default:
ret = -ENOTTY;
debug("not in a PWM mode");
break;
}
/* if nobody wants it, let VDev have it */
if (ret == -ENOTTY)
ret = VDev::ioctl(handlep, cmd, arg);
return ret;
}
int
HIL::pwm_ioctl(device::px4_dev_handle_t *handlep, int cmd, unsigned long arg)
{
int ret = PX4_OK;
// int channel;
lock();
switch (cmd) {
case PWM_SERVO_ARM:
// up_pwm_servo_arm(true);
break;
case PWM_SERVO_DISARM:
// up_pwm_servo_arm(false);
break;
case PWM_SERVO_SET_UPDATE_RATE:
// HIL always outputs at the alternate (usually faster) rate
g_hil->set_pwm_rate(arg);
break;
case PWM_SERVO_SET_SELECT_UPDATE_RATE:
// HIL always outputs at the alternate (usually faster) rate
break;
case PWM_SERVO_SET(2):
case PWM_SERVO_SET(3):
if (_mode != MODE_4PWM) {
ret = -EINVAL;
break;
}
/* FALLTHROUGH */
case PWM_SERVO_SET(0):
case PWM_SERVO_SET(1):
if (arg < 2100) {
// channel = cmd - PWM_SERVO_SET(0);
// up_pwm_servo_set(channel, arg); XXX
} else {
ret = -EINVAL;
}
break;
case PWM_SERVO_GET(2):
case PWM_SERVO_GET(3):
if (_mode != MODE_4PWM) {
ret = -EINVAL;
break;
}
/* FALLTHROUGH */
case PWM_SERVO_GET(0):
case PWM_SERVO_GET(1): {
// channel = cmd - PWM_SERVO_SET(0);
// *(servo_position_t *)arg = up_pwm_servo_get(channel);
break;
}
case PWM_SERVO_GET_RATEGROUP(0) ... PWM_SERVO_GET_RATEGROUP(PWM_OUTPUT_MAX_CHANNELS - 1): {
// no restrictions on output grouping
unsigned channel = cmd - PWM_SERVO_GET_RATEGROUP(0);
*(uint32_t *)arg = (1 << channel);
break;
}
case MIXERIOCGETOUTPUTCOUNT:
if (_mode == MODE_4PWM) {
*(unsigned *)arg = 4;
} else {
*(unsigned *)arg = 2;
}
break;
case MIXERIOCRESET:
if (_mixers != nullptr) {
delete _mixers;
_mixers = nullptr;
}
break;
case MIXERIOCADDSIMPLE: {
mixer_simple_s *mixinfo = (mixer_simple_s *)arg;
SimpleMixer *mixer = new SimpleMixer(control_callback,
(uintptr_t)&_controls, mixinfo);
if (mixer->check()) {
delete mixer;
ret = -EINVAL;
} else {
if (_mixers == nullptr)
_mixers = new MixerGroup(control_callback,
(uintptr_t)&_controls);
_mixers->add_mixer(mixer);
}
break;
}
case MIXERIOCLOADBUF: {
const char *buf = (const char *)arg;
unsigned buflen = strnlen(buf, 1024);
if (_mixers == nullptr)
_mixers = new MixerGroup(control_callback, (uintptr_t)&_controls);
if (_mixers == nullptr) {
ret = -ENOMEM;
} else {
ret = _mixers->load_from_buf(buf, buflen);
if (ret != 0) {
debug("mixer load failed with %d", ret);
delete _mixers;
_mixers = nullptr;
ret = -EINVAL;
}
}
break;
}
default:
ret = -ENOTTY;
break;
}
unlock();
return ret;
}
namespace
{
enum PortMode {
PORT_MODE_UNDEFINED = 0,
PORT1_MODE_UNSET,
PORT1_FULL_PWM,
PORT1_PWM_AND_SERIAL,
PORT1_PWM_AND_GPIO,
PORT2_MODE_UNSET,
PORT2_8PWM,
PORT2_12PWM,
PORT2_16PWM,
};
PortMode g_port_mode;
int
hil_new_mode(PortMode new_mode)
{
// uint32_t gpio_bits;
// /* reset to all-inputs */
// g_hil->ioctl(0, GPIO_RESET, 0);
// gpio_bits = 0;
HIL::Mode servo_mode = HIL::MODE_NONE;
switch (new_mode) {
case PORT_MODE_UNDEFINED:
case PORT1_MODE_UNSET:
case PORT2_MODE_UNSET:
/* nothing more to do here */
break;
case PORT1_FULL_PWM:
/* select 4-pin PWM mode */
servo_mode = HIL::MODE_4PWM;
break;
case PORT1_PWM_AND_SERIAL:
/* select 2-pin PWM mode */
servo_mode = HIL::MODE_2PWM;
// /* set RX/TX multi-GPIOs to serial mode */
// gpio_bits = GPIO_MULTI_3 | GPIO_MULTI_4;
break;
case PORT1_PWM_AND_GPIO:
/* select 2-pin PWM mode */
servo_mode = HIL::MODE_2PWM;
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_16PWM:
/* select 16-pin PWM mode */
servo_mode = HIL::MODE_16PWM;
break;
}
// /* adjust GPIO config for serial mode(s) */
// if (gpio_bits != 0)
// g_hil->ioctl(0, GPIO_SET_ALT_1, gpio_bits);
/* (re)set the PWM output mode */
g_hil->set_mode(servo_mode);
return PX4_OK;
}
int
hil_start(void)
{
int ret = PX4_OK;
if (g_hil == nullptr) {
g_hil = new HIL;
if (g_hil == nullptr) {
ret = -ENOMEM;
} else {
ret = g_hil->init();
if (ret != PX4_OK) {
delete g_hil;
g_hil = nullptr;
}
}
}
return ret;
}
int
test(void)
{
int fd;
fd = px4_open(PWM_OUTPUT0_DEVICE_PATH, 0);
if (fd < 0) {
puts("open fail");
return -ENODEV;
}
px4_ioctl(fd, PWM_SERVO_ARM, 0);
px4_ioctl(fd, PWM_SERVO_SET(0), 1000);
px4_close(fd);
return PX4_OK;
}
int
fake(int argc, char *argv[])
{
if (argc < 5) {
puts("hil fake <roll> <pitch> <yaw> <thrust> (values -100 .. 100)");
return -EINVAL;
}
actuator_controls_s ac;
ac.control[0] = strtol(argv[1], 0, 0) / 100.0f;
ac.control[1] = strtol(argv[2], 0, 0) / 100.0f;
ac.control[2] = strtol(argv[3], 0, 0) / 100.0f;
ac.control[3] = strtol(argv[4], 0, 0) / 100.0f;
orb_advert_t handle = orb_advertise(ORB_ID_VEHICLE_ATTITUDE_CONTROLS, &ac);
if (handle < 0) {
puts("advertise failed");
return 1;
}
return 0;
}
} // namespace
extern "C" __EXPORT int hil_main(int argc, char *argv[]);
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;
int ret = PX4_OK;
if (hil_start() != PX4_OK) {
warnx("failed to start the HIL driver");
return 1;
}
if (argc < 2) {
usage();
return -EINVAL;
}
verb = argv[1];
/*
* Mode switches.
*/
// this was all cut-and-pasted from the FMU driver; it's junk
if (!strcmp(verb, "mode_pwm")) {
new_mode = PORT1_FULL_PWM;
} else if (!strcmp(verb, "mode_pwm_serial")) {
new_mode = PORT1_PWM_AND_SERIAL;
} else if (!strcmp(verb, "mode_pwm_gpio")) {
new_mode = PORT1_PWM_AND_GPIO;
} else if (!strcmp(verb, "mode_port2_pwm8")) {
new_mode = PORT2_8PWM;
} else if (!strcmp(verb, "mode_port2_pwm12")) {
new_mode = PORT2_8PWM;
} else if (!strcmp(verb, "mode_port2_pwm16")) {
new_mode = PORT2_8PWM;
}
/* was a new mode set? */
if (new_mode != PORT_MODE_UNDEFINED) {
/* yes but it's the same mode */
if (new_mode == g_port_mode)
return PX4_OK;
/* switch modes */
return hil_new_mode(new_mode);
}
if (!strcmp(verb, "test")) {
ret = test();
}
else if (!strcmp(verb, "fake")) {
ret = fake(argc - 1, argv + 1);
}
else {
usage();
ret = -EINVAL;
}
return ret;
}
-4
View File
@@ -37,10 +37,6 @@
MODULE_COMMAND = hil
ifeq ($(PX4_TARGET_OS),nuttx)
SRCS = hil.cpp
MAXOPTIMIZATION = -Os
else
SRCS = hil_posix.cpp
endif
-4
View File
@@ -4,10 +4,6 @@
MODULE_COMMAND = rgbled
ifeq ($(PX4_TARGET_OS),nuttx)
SRCS = rgbled.cpp
else
SRCS = rgbled_posix.cpp
endif
MAXOPTIMIZATION = -Os
+61 -40
View File
@@ -41,6 +41,7 @@
*/
#include <px4_config.h>
#include <px4_getopt.h>
#include <drivers/device/i2c.h>
@@ -54,7 +55,7 @@
#include <stdio.h>
#include <ctype.h>
#include <nuttx/wqueue.h>
#include <px4_workqueue.h>
#include <systemlib/perf_counter.h>
#include <systemlib/err.h>
@@ -88,7 +89,7 @@ public:
virtual int init();
virtual int probe();
virtual int info();
virtual int ioctl(struct file *filp, int cmd, unsigned long arg);
virtual int ioctl(device::file_t *filp, int cmd, unsigned long arg);
private:
work_s _work;
@@ -129,7 +130,11 @@ void rgbled_usage();
extern "C" __EXPORT int rgbled_main(int argc, char *argv[]);
RGBLED::RGBLED(int bus, int rgbled) :
I2C("rgbled", RGBLED0_DEVICE_PATH, bus, rgbled, 100000 /* maximum speed supported */),
I2C("rgbled", RGBLED0_DEVICE_PATH, bus, rgbled
#ifdef __PX4_NUTTX
,100000 /* maximum speed supported */
#endif
),
_mode(RGBLED_MODE_OFF),
_r(0),
_g(0),
@@ -218,7 +223,7 @@ RGBLED::info()
}
int
RGBLED::ioctl(struct file *filp, int cmd, unsigned long arg)
RGBLED::ioctl(device::file_t *filp, int cmd, unsigned long arg)
{
int ret = ENOTTY;
@@ -249,7 +254,11 @@ RGBLED::ioctl(struct file *filp, int cmd, unsigned long arg)
default:
/* see if the parent class can make any use of it */
#ifdef __PX4_NUTTX
ret = CDev::ioctl(filp, cmd, arg);
#else
ret = VDev::ioctl(filp, cmd, arg);
#endif
break;
}
@@ -582,35 +591,39 @@ rgbled_main(int argc, char *argv[])
int ch;
/* jump over start/off/etc and look at options first */
while ((ch = getopt(argc, argv, "a:b:")) != EOF) {
int myoptind = 1;
const char *myoptarg = NULL;
while ((ch = px4_getopt(argc, argv, "a:b:", &myoptind, &myoptarg)) != EOF) {
switch (ch) {
case 'a':
rgbledadr = strtol(optarg, NULL, 0);
rgbledadr = strtol(myoptarg, NULL, 0);
break;
case 'b':
i2cdevice = strtol(optarg, NULL, 0);
i2cdevice = strtol(myoptarg, NULL, 0);
break;
default:
rgbled_usage();
exit(0);
return 1;
}
}
if (optind >= argc) {
if (myoptind >= argc) {
rgbled_usage();
exit(1);
return 1;
}
const char *verb = argv[optind];
const char *verb = argv[myoptind];
int fd;
int ret;
if (!strcmp(verb, "start")) {
if (g_rgbled != nullptr)
errx(1, "already started");
if (g_rgbled != nullptr) {
warnx("already started");
return 1;
}
if (i2cdevice == -1) {
// try the external bus first
@@ -625,7 +638,8 @@ rgbled_main(int argc, char *argv[])
if (g_rgbled == nullptr) {
// fall back to default bus
if (PX4_I2C_BUS_LED == PX4_I2C_BUS_EXPANSION) {
errx(1, "init failed");
warnx("init failed");
return 1;
}
i2cdevice = PX4_I2C_BUS_LED;
}
@@ -634,88 +648,95 @@ rgbled_main(int argc, char *argv[])
if (g_rgbled == nullptr) {
g_rgbled = new RGBLED(i2cdevice, rgbledadr);
if (g_rgbled == nullptr)
errx(1, "new failed");
if (g_rgbled == nullptr) {
warnx("new failed");
return 1;
}
if (OK != g_rgbled->init()) {
delete g_rgbled;
g_rgbled = nullptr;
errx(1, "init failed");
warnx("init failed");
return 1;
}
}
exit(0);
return 0;
}
/* need the driver past this point */
if (g_rgbled == nullptr) {
warnx("not started");
rgbled_usage();
exit(1);
return 1;
}
if (!strcmp(verb, "test")) {
fd = open(RGBLED0_DEVICE_PATH, 0);
fd = px4_open(RGBLED0_DEVICE_PATH, 0);
if (fd == -1) {
errx(1, "Unable to open " RGBLED0_DEVICE_PATH);
warnx("Unable to open " RGBLED0_DEVICE_PATH);
return 1;
}
rgbled_pattern_t pattern = { {RGBLED_COLOR_RED, RGBLED_COLOR_GREEN, RGBLED_COLOR_BLUE, RGBLED_COLOR_WHITE, RGBLED_COLOR_OFF, RGBLED_COLOR_OFF},
{500, 500, 500, 500, 1000, 0 } // "0" indicates end of pattern
};
ret = ioctl(fd, RGBLED_SET_PATTERN, (unsigned long)&pattern);
ret = ioctl(fd, RGBLED_SET_MODE, (unsigned long)RGBLED_MODE_PATTERN);
ret = px4_ioctl(fd, RGBLED_SET_PATTERN, (unsigned long)&pattern);
ret = px4_ioctl(fd, RGBLED_SET_MODE, (unsigned long)RGBLED_MODE_PATTERN);
close(fd);
exit(ret);
px4_close(fd);
return ret;
}
if (!strcmp(verb, "info")) {
g_rgbled->info();
exit(0);
return 0;
}
if (!strcmp(verb, "off") || !strcmp(verb, "stop")) {
fd = open(RGBLED0_DEVICE_PATH, 0);
fd = px4_open(RGBLED0_DEVICE_PATH, 0);
if (fd == -1) {
errx(1, "Unable to open " RGBLED0_DEVICE_PATH);
warnx("Unable to open " RGBLED0_DEVICE_PATH);
return 1;
}
ret = ioctl(fd, RGBLED_SET_MODE, (unsigned long)RGBLED_MODE_OFF);
close(fd);
ret = px4_ioctl(fd, RGBLED_SET_MODE, (unsigned long)RGBLED_MODE_OFF);
px4_close(fd);
/* delete the rgbled object if stop was requested, in addition to turning off the LED. */
if (!strcmp(verb, "stop")) {
delete g_rgbled;
g_rgbled = nullptr;
exit(0);
return 0;
}
exit(ret);
return ret;
}
if (!strcmp(verb, "rgb")) {
if (argc < 5) {
errx(1, "Usage: rgbled rgb <red> <green> <blue>");
warnx("Usage: rgbled rgb <red> <green> <blue>");
return 1;
}
fd = open(RGBLED0_DEVICE_PATH, 0);
fd = px4_open(RGBLED0_DEVICE_PATH, 0);
if (fd == -1) {
errx(1, "Unable to open " RGBLED0_DEVICE_PATH);
warnx("Unable to open " RGBLED0_DEVICE_PATH);
return 1;
}
rgbled_rgbset_t v;
v.red = strtol(argv[2], NULL, 0);
v.green = strtol(argv[3], NULL, 0);
v.blue = strtol(argv[4], NULL, 0);
ret = ioctl(fd, RGBLED_SET_RGB, (unsigned long)&v);
ret = ioctl(fd, RGBLED_SET_MODE, (unsigned long)RGBLED_MODE_ON);
close(fd);
exit(ret);
ret = px4_ioctl(fd, RGBLED_SET_RGB, (unsigned long)&v);
ret = px4_ioctl(fd, RGBLED_SET_MODE, (unsigned long)RGBLED_MODE_ON);
px4_close(fd);
return ret;
}
rgbled_usage();
exit(0);
return 1;
}