diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-07-29 18:51:56 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-07-29 18:51:56 +0000 |
commit | ee8740ba0d2a6af731d9bcb1e485c95ec3886718 (patch) | |
tree | ef7387163cc3da8c53657dfb30dda18bd3c0b3a7 /nuttx/drivers/input | |
parent | 4e8206d3981a8e5ca0431a16b8fa3817db6692ba (diff) | |
download | px4-nuttx-ee8740ba0d2a6af731d9bcb1e485c95ec3886718.tar.gz px4-nuttx-ee8740ba0d2a6af731d9bcb1e485c95ec3886718.tar.bz2 px4-nuttx-ee8740ba0d2a6af731d9bcb1e485c95ec3886718.zip |
Add framework for input devices and TSC2007 touchscreen driver
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3827 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/drivers/input')
-rwxr-xr-x | nuttx/drivers/input/Make.defs | 52 | ||||
-rw-r--r-- | nuttx/drivers/input/tsc2007.c | 515 |
2 files changed, 567 insertions, 0 deletions
diff --git a/nuttx/drivers/input/Make.defs b/nuttx/drivers/input/Make.defs new file mode 100755 index 000000000..e4758ed84 --- /dev/null +++ b/nuttx/drivers/input/Make.defs @@ -0,0 +1,52 @@ +############################################################################ +# drivers/input/Make.defs +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt <spudmonkey@racsa.co.cr> +# +# 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 NuttX 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. +# +############################################################################ + +# Don't build anything if there is no NX support for input devices + +ifeq ($(CONFIG_INPUT),y) + +# Include the TI TSC2007 drivers + +ifeq ($(CONFIG_INPUT_TSC2007),y) + CSRCS += tsc2007.c +endif + +# Include input device driver build support + +DEPPATH += --dep-path input +VPATH += :input +CFLAGS += ${shell $(TOPDIR)/tools/incdir.sh $(INCDIROPT) "$(CC)" $(TOPDIR)/drivers/input} +endif + diff --git a/nuttx/drivers/input/tsc2007.c b/nuttx/drivers/input/tsc2007.c new file mode 100644 index 000000000..bb8c7f01f --- /dev/null +++ b/nuttx/drivers/input/tsc2007.c @@ -0,0 +1,515 @@ +/**************************************************************************** + * drivers/input/tsc2007.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 NuttX 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <sys/types.h> + +#include <stdbool.h> +#include <stdio.h> +#include <string.h> +#include <semaphore.h> +#include <poll.h> +#include <errno.h> +#include <assert.h> +#include <debug.h> + +#include <nuttx/kmalloc.h> +#include <nuttx/arch.h> +#include <nuttx/fs.h> +#include <nuttx/i2c.h> +#include <nuttx/input/tsc2007.h> + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Driver support ***********************************************************/ +/* This format is used to construct the /dev/skel[n] device driver path. It + * defined here so that it will be used consistently in all places. + */ + +#define DEV_FORMAT "/dev/input%d" +#define DEV_NAMELEN 16 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct tsc2007_dev_s +{ + uint8_t crefs; /* Number of times the device has been opened */ + sem_t devsem; /* Manages exclusive access to this structure */ + FAR struct i2c_dev_s *i2c; /* Saved I2C driver instance */ + + /* The following is a list if poll structures of threads waiting for + * driver events. The 'struct pollfd' reference for each open is also + * retained in the f_priv field of the 'struct file'. + */ + +#ifndef CONFIG_DISABLE_POLL + struct pollfd *fds[CONFIG_TSC2007_NPOLLWAITERS]; +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int tsc2007_open(FAR struct file *filep); +static int tsc2007_close(FAR struct file *filep); +static ssize_t tsc2007_read(FAR struct file *filep, FAR char *buffer, size_t len); +static ssize_t tsc2007_write(FAR struct file *filep, FAR const char *buffer, size_t len); +static int tsc2007_ioctl(FAR struct file *filep, int cmd, unsigned long arg); +#ifndef CONFIG_DISABLE_POLL +static int tsc2007_poll(FAR struct file *filep, struct pollfd *fds, bool setup); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations tsc2007_fops = +{ + tsc2007_open, /* open */ + tsc2007_close, /* close */ + tsc2007_read, /* read */ + tsc2007_write, /* write */ + 0, /* seek */ + tsc2007_ioctl /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , tsc2007_poll /* poll */ +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tsc2007_pollnotify + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +static void tsc2007_pollnotify(FAR struct tsc2007_dev_s *priv, pollevent_t eventset) +{ + int i; + + for (i = 0; i < CONFIG_TSC2007_NPOLLWAITERS; i++) + { + struct pollfd *fds = priv->fds[i]; + if (fds) + { + fds->revents |= (fds->events & eventset); + if (fds->revents != 0) + { + ivdbg("Report events: %02x\n", fds->revents); + sem_post(fds->sem); + } + } + } +} +#else +# define tsc2007_pollnotify(priv,event) +#endif + +/**************************************************************************** + * Name: tsc2007_open + ****************************************************************************/ + +static int tsc2007_open(FAR struct file *filep) +{ + FAR struct inode *inode; + FAR struct tsc2007_dev_s *priv; + uint8_t tmp; + int ret; + + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct tsc2007_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + + ret = sem_wait(&priv->devsem); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(errno == EINTR); + return -EINTR; + } + + /* Increment the reference count */ + + tmp = priv->crefs + 1; + if (tmp == 0) + { + /* More than 255 opens; uint8_t overflows to zero */ + + ret = -EMFILE; + goto errout_with_sem; + } + + /* Check if this is the first time that the driver has been opened. */ + + if (tmp == 1) + { + irqstate_t flags = irqsave(); + + /* Perform one time hardware initialization */ + +#warning "Missing logic" + irqrestore(flags); + } + + /* Save the new open count on success */ + + priv->crefs = tmp; + +errout_with_sem: + sem_post(&priv->devsem); + return ret; +} + +/**************************************************************************** + * Name: tsc2007_close + ****************************************************************************/ + +static int tsc2007_close(FAR struct file *filep) +{ + FAR struct inode *inode; + FAR struct tsc2007_dev_s *priv; + int ret; + + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct tsc2007_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + + ret = sem_wait(&priv->devsem); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(errno == EINTR); + return -EINTR; + } + + /* Decrement the reference count unless it would decrement to zero */ + if (priv->crefs > 1) + { + priv->crefs--; + sem_post(&priv->devsem); + return OK; + } + + /* There are no more references to the port */ + + priv->crefs = 0; + + /* Perform driver teardown */ +#warning "Missing logic" + + sem_post(&priv->devsem); + return OK; +} + +/**************************************************************************** + * Name: tsc2007_read + ****************************************************************************/ + +static ssize_t tsc2007_read(FAR struct file *filep, FAR char *buffer, size_t len) +{ + FAR struct inode *inode; + FAR struct tsc2007_dev_s *priv; + int ret; + + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct tsc2007_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + + ret = sem_wait(&priv->devsem); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(errno == EINTR); + return -EINTR; + } + +#warning "Not implemented" + + sem_post(&priv->devsem); + return -ENOSYS; +} + +/**************************************************************************** + * Name: tsc2007_write + ****************************************************************************/ + +static ssize_t tsc2007_write(FAR struct file *filep, FAR const char *buffer, size_t len) +{ + FAR struct inode *inode; + FAR struct tsc2007_dev_s *priv; + int ret; + + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct tsc2007_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + + ret = sem_wait(&priv->devsem); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(errno == EINTR); + return -EINTR; + } + +#warning "Not implemented" + sem_post(&priv->devsem); + return -ENOSYS; +} + +/**************************************************************************** + * Name:tsc2007_ioctl + ****************************************************************************/ + +static int tsc2007_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode; + FAR struct tsc2007_dev_s *priv; + int ret; + + ivdbg("cmd: %d arg: %ld\n", cmd, arg); + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct tsc2007_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + + ret = sem_wait(&priv->devsem); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(errno == EINTR); + return -EINTR; + } + + /* Process the IOCTL by command */ + + switch (cmd) + { + /* Add support for ioctl commands here */ + + default: + ret = -ENOTTY; + break; + } + + sem_post(&priv->devsem); + return ret; +} + +/**************************************************************************** + * Name: tsc2007_poll + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +static int tsc2007_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup) +{ + FAR struct inode *inode; + FAR struct tsc2007_dev_s *priv; + pollevent_t eventset; + int ndx; + int ret = OK; + int i; + + ivdbg("setup: %d\n", (int)setup); + DEBUGASSERT(filep && fds); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct tsc2007_dev_s *)inode->i_private; + + /* Are we setting up the poll? Or tearing it down? */ + + ret = sem_wait(&priv->devsem); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(errno == EINTR); + return -EINTR; + } + + if (setup) + { + /* This is a request to set up the poll. Find an available + * slot for the poll structure reference + */ + + for (i = 0; i < CONFIG_TSC2007_NPOLLWAITERS; i++) + { + /* Find an available slot */ + + if (!priv->fds[i]) + { + /* Bind the poll structure and this slot */ + + priv->fds[i] = fds; + fds->priv = &priv->fds[i]; + break; + } + } + + if (i >= CONFIG_TSC2007_NPOLLWAITERS) + { + fds->priv = NULL; + ret = -EBUSY; + goto errout; + } + + /* Should immediately notify on any of the requested events? */ +#warning "Missing logic" + + + } + else if (fds->priv) + { + /* This is a request to tear down the poll. */ + + struct pollfd **slot = (struct pollfd **)fds->priv; + +#ifdef CONFIG_DEBUG + if (!slot) + { + ret = -EIO; + goto errout; + } +#endif + + /* Remove all memory of the poll setup */ + + *slot = NULL; + fds->priv = NULL; + } + +errout: + sem_post(&priv->devsem); + return ret; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tsc2007_register + * + * Description: + * Configure the TSC2007 to use the provided I2C device instance. This + * will register the driver as /dev/inputN where N is the minor device + * number + * + * Input Parameters: + * dev - An I2C driver instance + * minor - The input device minor number + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int tsc2007_register(FAR struct i2c_dev_s *dev, int minor) +{ + FAR struct tsc2007_dev_s *priv; + char devname[DEV_NAMELEN]; + int ret; + + ivdbg("dev: %p minor: %d\n", dev, minor); + DEBUGASSERT(dev != NULL && minor > 0 && minor < 100); + + /* Create and initialize a TSC2007 device driver instance */ + + priv = (FAR struct tsc2007_dev_s *)kmalloc(sizeof(struct tsc2007_dev_s)); + if (!priv) + { + idbg("kmalloc(%d) failed\n", sizeof(struct tsc2007_dev_s)); + return -ENOMEM; + } + + /* Initialize a TSC2007 device driver instance */ + + priv->i2c = dev; + sem_init(&priv->devsem, 0, 1); + + /* Register the input device */ + + (void)snprintf(devname, DEV_NAMELEN, DEV_FORMAT, minor); + ivdbg("Registering %s\n", devname); + ret = register_driver(devname, &tsc2007_fops, 0666, priv); + if (ret < 0) + { + idbg("register_driver() failed: %d\n", ret); + } + return ret; +} |