drivers/adc: update upper-half layer
authorHeesub Shin <heesub.shin@samsung.com>
Thu, 6 Apr 2017 03:53:32 +0000 (12:53 +0900)
committerHeesub Shin <heesub.shin@samsung.com>
Tue, 18 Apr 2017 03:02:12 +0000 (12:02 +0900)
This commit updates the upper-half driver of ADC subsystem,
synchronizing with the latest version of NuttX. ADC drivers that
implements the lower-half can be broken with this commit, but in TizenRT
there is no lower-half driver of ADC. Thus, this commit does not cause
any harm. All credits should go to many other contributors who wrote the
original patches for NuttX. Sorry for not listing their names here.

Change-Id: I42dc6b1fa597ae74494ef635897b4bc695e1c343
[Shin: backported from the latest NuttX]
Signed-off-by: Heesub Shin <heesub.shin@samsung.com>
os/drivers/analog/adc.c
os/include/tinyara/analog/adc.h
os/include/tinyara/analog/ioctl.h [new file with mode: 0644]

index 2f3d986..98120d1 100644 (file)
 /****************************************************************************
  * drivers/analog/adc.c
  *
+ *   Copyright (C) 2008-2009, 2016 Gregory Nutt. All rights reserved.
  *   Copyright (C) 2011 Li Zhuoyi. All rights reserved.
  *   Author: Li Zhuoyi <lzyy.cn@gmail.com>
- *   History: 0.1 2011-08-04 initial version
+ *           Gregory Nutt <gnutt@nuttx.org>
  *
  * Derived from drivers/can.c
  *
 
 #include <tinyara/fs/fs.h>
 #include <tinyara/arch.h>
+#include <tinyara/semaphore.h>
 #include <tinyara/analog/adc.h>
 
-#include <arch/irq.h>
+#include <tinyara/irq.h>
 
 /****************************************************************************
  * Private Function Prototypes
  ****************************************************************************/
-
-static int adc_open(FAR struct file *filep);
-static int adc_close(FAR struct file *filep);
-static ssize_t adc_read(FAR struct file *, FAR char *, size_t);
-static int adc_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
-static ssize_t adc_write(FAR struct file *filep, FAR const char *buffer, size_t buflen);
+static int     adc_open(FAR struct file *filep);
+static int     adc_close(FAR struct file *filep);
+static ssize_t adc_read(FAR struct file *fielp, FAR char *buffer,
+                       size_t buflen);
+static int     adc_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
+static int     adc_receive(FAR struct adc_dev_s *dev, uint8_t ch,
+                          int32_t data);
 
 /****************************************************************************
  * Private Data
  ****************************************************************************/
-
-static const struct file_operations adc_fops = {
-       adc_open,                                       /* open */
-       adc_close,                                      /* close */
-       adc_read,                                       /* read */
-       adc_write,                                      /* write */
-       0,                                                      /* seek */
-       adc_ioctl                                       /* ioctl */
+static const struct file_operations g_adc_fops = {
+       adc_open,       /* open */
+       adc_close,      /* close */
+       adc_read,       /* read */
+       0,              /* write */
+       0,              /* seek */
+       adc_ioctl,      /* ioctl */
 #ifndef CONFIG_DISABLE_POLL
-       , 0                                             /* poll */
+       0,              /* poll */
 #endif
 };
 
+static const struct adc_callback_s g_adc_callback = {
+       adc_receive     /* au_receive */
+};
+
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
-/************************************************************************************
+/****************************************************************************
  * Name: adc_open
  *
  * Description:
  *   This function is called whenever the ADC device is opened.
  *
- ************************************************************************************/
-
+ ****************************************************************************/
 static int adc_open(FAR struct file *filep)
 {
-       FAR struct inode *inode = filep->f_inode;
-       FAR struct adc_dev_s *dev = inode->i_private;
-       uint8_t tmp;
-       int ret = OK;
-
-       /* If the port is the middle of closing, wait until the close is finished */
-
+       FAR struct inode     *inode = filep->f_inode;
+       FAR struct adc_dev_s *dev   = inode->i_private;
+       uint8_t               tmp;
+       int                   ret   = OK;
+
+       /*
+        * If the port is the middle of closing, wait until the close is
+        * finished
+        */
        if (sem_wait(&dev->ad_closesem) != OK) {
                ret = -errno;
        } else {
-               /* Increment the count of references to the device.  If this the first
-                * time that the driver has been opened for this device, then initialize
-                * the device.
+               /*
+                * Increment the count of references to the device.  If this
+                * the first time that the driver has been opened for this
+                * device, then initialize the device.
                 */
-
                tmp = dev->ad_ocount + 1;
                if (tmp == 0) {
                        /* More than 255 opens; uint8_t overflows to zero */
-
                        ret = -EMFILE;
                } else {
-                       /* Check if this is the first time that the driver has been opened. */
-
+                       /*
+                        * Check if this is the first time that the driver
+                        * has been opened.
+                        */
                        if (tmp == 1) {
-                               /* Yes.. perform one time hardware initialization. */
-
+                               /*
+                                * Yes.. perform one time hardware
+                                * initialization.
+                                */
                                irqstate_t flags = irqsave();
                                ret = dev->ad_ops->ao_setup(dev);
                                if (ret == OK) {
                                        /* Mark the FIFOs empty */
-
                                        dev->ad_recv.af_head = 0;
                                        dev->ad_recv.af_tail = 0;
 
-                                       /* Finally, Enable the ADC RX interrupt */
-
+                                       /*
+                                        * Finally, Enable the ADC RX
+                                        * interrupt
+                                        */
                                        dev->ad_ops->ao_rxint(dev, true);
 
                                        /* Save the new open count on success */
-
                                        dev->ad_ocount = tmp;
                                }
 
@@ -170,41 +180,38 @@ static int adc_open(FAR struct file *filep)
        return ret;
 }
 
-/************************************************************************************
+/****************************************************************************
  * Name: adc_close
  *
  * Description:
  *   This routine is called when the ADC device is closed.
  *   It waits for the last remaining data to be sent.
  *
- ************************************************************************************/
-
+ ****************************************************************************/
 static int adc_close(FAR struct file *filep)
 {
-       FAR struct inode *inode = filep->f_inode;
-       FAR struct adc_dev_s *dev = inode->i_private;
-       irqstate_t flags;
-       int ret = OK;
+       FAR struct inode     *inode = filep->f_inode;
+       FAR struct adc_dev_s *dev   = inode->i_private;
+       irqstate_t            flags;
+       int                   ret = OK;
 
        if (sem_wait(&dev->ad_closesem) != OK) {
                ret = -errno;
        } else {
-               /* Decrement the references to the driver.  If the reference count will
-                * decrement to 0, then uninitialize the driver.
+               /*
+                * Decrement the references to the driver.  If the reference
+                * count will decrement to 0, then uninitialize the driver.
                 */
-
                if (dev->ad_ocount > 1) {
                        dev->ad_ocount--;
                        sem_post(&dev->ad_closesem);
                } else {
                        /* There are no more references to the port */
-
                        dev->ad_ocount = 0;
 
                        /* Free the IRQ and disable the ADC device */
-
-                       flags = irqsave();      /* Disable interrupts */
-                       dev->ad_ops->ao_shutdown(dev);  /* Disable the ADC */
+                       flags = irqsave(); /* Disable interrupts */
+                       dev->ad_ops->ao_shutdown(dev); /* Disable the ADC */
                        irqrestore(flags);
 
                        sem_post(&dev->ad_closesem);
@@ -217,46 +224,48 @@ static int adc_close(FAR struct file *filep)
 /****************************************************************************
  * Name: adc_read
  ****************************************************************************/
-
-static ssize_t adc_read(FAR struct file *filep, FAR char *buffer, size_t buflen)
+static ssize_t adc_read(FAR struct file *filep, FAR char *buffer,
+                       size_t buflen)
 {
-       FAR struct inode *inode = filep->f_inode;
-       FAR struct adc_dev_s *dev = inode->i_private;
-       size_t nread;
-       irqstate_t flags;
-       int ret = 0;
-       int msglen;
+       FAR struct inode     *inode = filep->f_inode;
+       FAR struct adc_dev_s *dev   = inode->i_private;
+       size_t                nread;
+       irqstate_t            flags;
+       int                   ret   = 0;
+       int                   msglen;
 
        avdbg("buflen: %d\n", (int)buflen);
 
-       if (buflen % 5 == 0) {
+       if (buflen % 5 == 0)
                msglen = 5;
-       } else if (buflen % 4 == 0) {
+       else if (buflen % 4 == 0)
                msglen = 4;
-       } else if (buflen % 3 == 0) {
+       else if (buflen % 3 == 0)
                msglen = 3;
-       } else if (buflen % 2 == 0) {
+       else if (buflen % 2 == 0)
                msglen = 2;
-       } else if (buflen == 1) {
+       else if (buflen == 1)
                msglen = 1;
-       } else {
+       else
                msglen = 5;
-       }
 
        if (buflen >= msglen) {
-               /* Interrupts must be disabled while accessing the ad_recv FIFO */
-
+               /*
+                * Interrupts must be disabled while accessing the ad_recv
+                * FIFO
+                */
                flags = irqsave();
                while (dev->ad_recv.af_head == dev->ad_recv.af_tail) {
-                       /* The receive FIFO is empty -- was non-blocking mode selected? */
-
+                       /*
+                        * The receive FIFO is empty
+                        * -- was non-blocking mode selected?
+                        */
                        if (filep->f_oflags & O_NONBLOCK) {
                                ret = -EAGAIN;
                                goto return_with_irqdisabled;
                        }
 
                        /* Wait for a message to be received */
-
                        dev->ad_nrxwaiters++;
                        ret = sem_wait(&dev->ad_recv.af_sem);
                        dev->ad_nrxwaiters--;
@@ -266,63 +275,62 @@ static ssize_t adc_read(FAR struct file *filep, FAR char *buffer, size_t buflen)
                        }
                }
 
-               /* The ad_recv FIFO is not empty.  Copy all buffered data that will fit
-                * in the user buffer.
+               /*
+                * The ad_recv FIFO is not empty.
+                * Copy all buffered data that will fit in the user buffer.
                 */
-
                nread = 0;
                do {
-                       FAR struct adc_msg_s *msg = &dev->ad_recv.af_buffer[dev->ad_recv.af_head];
-
-                       /* Will the next message in the FIFO fit into the user buffer? */
+                       FAR struct adc_msg_s *msg =
+                               &dev->ad_recv.af_buffer[dev->ad_recv.af_head];
 
+                       /*
+                        * Will the next message in the FIFO fit into the
+                        * user buffer?
+                        */
                        if (nread + msglen > buflen) {
-                               /* No.. break out of the loop now with nread equal to the actual
-                                * number of bytes transferred.
+                               /*
+                                * No.. break out of the loop now with nread
+                                * equal to the actual number of bytes
+                                * transferred.
                                 */
-
                                break;
                        }
 
                        /* Copy the message to the user buffer */
-
                        if (msglen == 1) {
                                /* Only one channel,read highest 8-bits */
-
                                buffer[nread] = msg->am_data >> 24;
                        } else if (msglen == 2) {
                                /* Only one channel, read highest 16-bits */
-
-                               *(int16_t *)&buffer[nread] = msg->am_data >> 16;
+                               *(int16_t *)&buffer[nread] =
+                                                       msg->am_data >> 16;
                        } else if (msglen == 3) {
                                /* Read channel highest 16-bits */
-
                                buffer[nread] = msg->am_channel;
-                               *(int16_t *)&buffer[nread + 1] = msg->am_data >> 16;
+                               *(int16_t *)&buffer[nread + 1] =
+                                                       msg->am_data >> 16;
                        } else if (msglen == 4) {
                                /* read channel highest 24-bits */
-
                                *(int32_t *)&buffer[nread] = msg->am_data;
                                buffer[nread] = msg->am_channel;
                        } else {
                                /* Read all */
-
-                               memcpy((int32_t *)&buffer[nread + 1], &msg->am_data, sizeof(int32_t));
+                               *(int32_t *)&buffer[nread + 1] = msg->am_data;
                                buffer[nread] = msg->am_channel;
                        }
                        nread += msglen;
 
                        /* Increment the head of the circular message buffer */
-
                        if (++dev->ad_recv.af_head >= CONFIG_ADC_FIFOSIZE) {
                                dev->ad_recv.af_head = 0;
                        }
                } while (dev->ad_recv.af_head != dev->ad_recv.af_tail);
 
-               /* All on the messages have bee transferred.  Return the number of bytes
-                * that were read.
+               /*
+                * All on the messages have bee transferred.
+                * Return the number of bytes that were read.
                 */
-
                ret = nread;
 
 return_with_irqdisabled:
@@ -333,16 +341,9 @@ return_with_irqdisabled:
        return ret;
 }
 
-ssize_t adc_write(FAR struct file *filep, FAR const char *buffer, size_t len)
-{
-       dbg("%s not implemented\n", __func__);
-       return 0;
-}
-
-/************************************************************************************
+/****************************************************************************
  * Name: adc_ioctl
- ************************************************************************************/
-
+ ****************************************************************************/
 static int adc_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
 {
        FAR struct inode *inode = filep->f_inode;
@@ -354,63 +355,86 @@ static int adc_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
 }
 
 /****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-/****************************************************************************
  * Name: adc_receive
  ****************************************************************************/
-
-int adc_receive(FAR struct adc_dev_s *dev, uint8_t ch, int32_t data)
+static int adc_receive(FAR struct adc_dev_s *dev, uint8_t ch, int32_t data)
 {
        FAR struct adc_fifo_s *fifo = &dev->ad_recv;
-       int nexttail;
-       int err = -ENOMEM;
+       int                    nexttail;
+       int                    errcode = -ENOMEM;
 
-       /* Check if adding this new message would over-run the drivers ability to enqueue
-        * read data.
+       /*
+        * Check if adding this new message would over-run the drivers
+        * ability to enqueue read data.
         */
-
        nexttail = fifo->af_tail + 1;
        if (nexttail >= CONFIG_ADC_FIFOSIZE) {
                nexttail = 0;
        }
 
        /* Refuse the new data if the FIFO is full */
-
        if (nexttail != fifo->af_head) {
                /* Add the new, decoded ADC sample at the tail of the FIFO */
-
                fifo->af_buffer[fifo->af_tail].am_channel = ch;
-               memcpy(&(fifo->af_buffer[fifo->af_tail].am_data), &data, sizeof(int32_t));
+               fifo->af_buffer[fifo->af_tail].am_data    = data;
 
                /* Increment the tail of the circular buffer */
-
                fifo->af_tail = nexttail;
 
                if (dev->ad_nrxwaiters > 0) {
                        sem_post(&fifo->af_sem);
                }
 
-               err = OK;
+               errcode = OK;
        }
-       return err;
+
+       return errcode;
 }
 
 /****************************************************************************
- * Name: adc_register
+ * Public Functions
  ****************************************************************************/
 
+/****************************************************************************
+ * Name: adc_register
+ ****************************************************************************/
 int adc_register(FAR const char *path, FAR struct adc_dev_s *dev)
 {
-       /* Initialize the ADC device structure */
+       int ret;
+
+       DEBUGASSERT(path != NULL && dev != NULL);
 
+       /* Bind the upper-half callbacks to the lower half ADC driver */
+       DEBUGASSERT(dev->ad_ops != NULL && dev->ad_ops->ao_bind != NULL);
+       ret = dev->ad_ops->ao_bind(dev, &g_adc_callback);
+       if (ret < 0) {
+               avdbg("ERROR: Failed to bind callbacks: %d\n", ret);
+               return ret;
+       }
+
+       /* Initialize the ADC device structure */
        dev->ad_ocount = 0;
 
+       /* Initialize semaphores */
        sem_init(&dev->ad_recv.af_sem, 0, 0);
        sem_init(&dev->ad_closesem, 0, 1);
 
+       /*
+        * The receive semaphore is used for signaling and, hence,
+        * should not have priority inheritance enabled.
+        */
+       sem_setprotocol(&dev->ad_recv.af_sem, SEM_PRIO_NONE);
+
+       /* Reset the ADC hardware */
+       DEBUGASSERT(dev->ad_ops->ao_reset != NULL);
        dev->ad_ops->ao_reset(dev);
 
-       return register_driver(path, &adc_fops, 0444, dev);
+       /* Register the ADC character driver */
+       ret = register_driver(path, &g_adc_fops, 0444, dev);
+       if (ret < 0) {
+               sem_destroy(&dev->ad_recv.af_sem);
+               sem_destroy(&dev->ad_closesem);
+       }
+
+       return ret;
 }
index 9fc2033..8c5b5e3 100644 (file)
  * language governing permissions and limitations under the License.
  *
  ****************************************************************************/
-/************************************************************************************
+/****************************************************************************
+ * include/tinyara/analog/adc.h
  *
+ *   Copyright (C) 2016-2017 Gregory Nutt. All rights reserved.
  *   Copyright (C) 2011 Li Zhuoyi. All rights reserved.
  *   Author: Li Zhuoyi <lzyy.cn@gmail.com>
- *   History: 0.1 2011-08-04 initial version
- *            0.2 remove ao_read
+ *           Gregory Nutt <gnutt@nuttx.org>
  *
- * Derived from include/tinyara/can.h
+ * Derived from include/nuttx/drivers/can.h
  *
  *   Copyright (C) 2008, 2009 Gregory Nutt. All rights reserved.
  *   Author: Gregory Nutt <gnutt@nuttx.org>
  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  *
- ************************************************************************************/
+ ****************************************************************************/
 
 #ifndef __INCLUDE_TINYARA_ANALOG_ADC_H
 #define __INCLUDE_TINYARA_ANALOG_ADC_H
 
-/************************************************************************************
+/****************************************************************************
  * Included Files
- ************************************************************************************/
+ ****************************************************************************/
 
 #include <tinyara/config.h>
 #include <tinyara/compiler.h>
 #include <tinyara/fs/fs.h>
 #include <tinyara/spi/spi.h>
 
-/************************************************************************************
+/****************************************************************************
  * Pre-processor Definitions
- ************************************************************************************/
+ ****************************************************************************/
 
-/* Default configuration settings that may be overridden in the TinyAra configuration
- * file.  The configured size is limited to 255 to fit into a uint8_t.
+/*
+ * Default configuration settings that may be overridden in the TinyARA
+ * configuration file. The configured size is limited to 255 to fit into
+ * a uint8_t.
  */
 
 #if !defined(CONFIG_ADC_FIFOSIZE)
 #define CONFIG_ADC_FIFOSIZE 255
 #endif
 
-/************************************************************************************
+#define ADC_RESET(dev)         ((dev)->ad_ops->ao_reset((dev)))
+#define ADC_SETUP(dev)         ((dev)->ad_ops->ao_setup((dev)))
+#define ADC_SHUTDOWN(dev)      ((dev)->ad_ops->ao_shutdown((dev)))
+#define ADC_RXINT(dev)         ((dev)->ad_ops->ao_rxint((dev)))
+#define ADC_IOCTL(dev,cmd,arg) ((dev)->ad_ops->ao_ioctl((dev),(cmd),(arg)))
+
+/****************************************************************************
  * Public Types
- ************************************************************************************/
+ ****************************************************************************/
+/* These are callbacks to notify the upper-half driver of ADC events */
+
+struct adc_dev_s;
+struct adc_callback_s {
+       /*
+        * This method is called from the lower half, platform-specific ADC
+        * logic when new ADC sample data is available.
+        *
+        * Input Parameters:
+        *   dev  - The ADC device structure that was previously registered
+        *          by adc_register()
+        *   ch   - And ID for the ADC channel number that generated the data
+        *   data - The actual converted data from the channel.
+        *
+        * Returned Value:
+        *   Zero on success; a negated errno value on failure.
+        */
+
+       CODE int (*au_receive)(FAR struct adc_dev_s *dev, uint8_t ch,
+                              int32_t data);
+};
+
+/* This describes on ADC message */
 
 struct adc_msg_s {
-       uint8_t am_channel;                     /* The 8-bit ADC Channel */
-       int32_t am_data;                        /* ADC convert result (4 bytes) */
+       uint8_t am_channel;     /* The 8-bit ADC Channel */
+       int32_t am_data;        /* ADC convert result (4 bytes) */
 } packed_struct;
 
+/* This describes a FIFO of ADC messages */
+
 struct adc_fifo_s {
-       sem_t af_sem;                           /* Counting semaphore */
-       uint8_t af_head;                        /* Index to the head [IN] index in the circular buffer */
-       uint8_t af_tail;                        /* Index to the tail [OUT] index in the circular buffer */
+       sem_t   af_sem;         /* Counting semaphore */
+       uint8_t af_head;        /* Index to the head [IN] index in the circular buffer */
+       uint8_t af_tail;        /* Index to the tail [OUT] index in the circular buffer */
        /* Circular buffer of CAN messages */
-       struct adc_msg_s af_buffer[CONFIG_ADC_FIFOSIZE];
+       struct  adc_msg_s af_buffer[CONFIG_ADC_FIFOSIZE];
 };
 
-/* This structure defines all of the operations providd by the architecture specific
- * logic.  All fields must be provided with non-NULL function pointers by the
- * caller of can_register().
+/*
+ * This structure defines all of the operations providd by the architecture
+ * specific logic. All fields must be provided with non-NULL function pointers
+ * by the caller of can_register().
  */
 
 struct adc_dev_s;
 struct adc_ops_s {
-       /* Reset the ADC device.  Called early to initialize the hardware. This
-        * is called, before ao_setup() and on error conditions.
+       /*
+        * Bind the upper-half driver callbacks to the lower-half
+        * implementation. This must be called early in order to receive ADC
+        * event notifications.
+        */
+
+       CODE int (*ao_bind)(FAR struct adc_dev_s *dev,
+                       FAR const struct adc_callback_s *callback);
+
+       /*
+        * Reset the ADC device.  Called early to initialize the hardware.
+        * This is called, before ao_setup() and on error conditions.
         */
 
        CODE void (*ao_reset)(FAR struct adc_dev_s *dev);
 
-       /* Configure the ADC. This method is called the first time that the ADC
-        * device is opened.  This will occur when the port is first opened.
-        * This setup includes configuring and attaching ADC interrupts.  Interrupts
-        * are all disabled upon return.
+       /*
+        * Configure the ADC. This method is called the first time that the
+        * ADC device is opened.  This will occur when the port is first
+        * opened. This setup includes configuring and attaching ADC
+        * interrupts. Interrupts are all disabled upon return.
         */
 
        CODE int (*ao_setup)(FAR struct adc_dev_s *dev);
 
-       /* Disable the ADC.  This method is called when the ADC device is closed.
-        * This method reverses the operation the setup method.
+       /*
+        * Disable the ADC. This method is called when the ADC device is
+        * closed. This method reverses the operation the setup method.
         */
 
        CODE void (*ao_shutdown)(FAR struct adc_dev_s *dev);
@@ -141,9 +188,10 @@ struct adc_ops_s {
        CODE int (*ao_ioctl)(FAR struct adc_dev_s *dev, int cmd, unsigned long arg);
 };
 
-/* This is the device structure used by the driver.  The caller of
- * adc_register() must allocate and initialize this structure.  The
- * calling logic need only set all fields to zero except:
+/*
+ * This is the device structure used by the driver.  The caller of
+ * adc_register() must allocate and initialize this structure.  The calling
+ * logic need only set all fields to zero except:
  *
  *   The elements of 'ad_ops', and 'ad_priv'
  *
@@ -151,43 +199,48 @@ struct adc_ops_s {
  */
 
 struct adc_dev_s {
-       uint8_t ad_ocount;                      /* The number of times the device has been opened */
-       uint8_t ad_nrxwaiters;          /* Number of threads waiting to enqueue a message */
-       sem_t ad_closesem;                      /* Locks out new opens while close is in progress */
-       sem_t ad_recvsem;                       /* Used to wakeup user waiting for space in ad_recv.buffer */
-       struct adc_fifo_s ad_recv;      /* Describes receive FIFO */
-       const struct adc_ops_s *ad_ops; /* Arch-specific operations */
-       void *ad_priv;                          /* Used by the arch-specific logic */
-};
+#ifdef CONFIG_ADC
+       /* Fields managed by common upper half ADC logic */
+
+       uint8_t           ad_ocount;     /* The number of times the device has been opened */
+       uint8_t           ad_nrxwaiters; /* Number of threads waiting to enqueue a message */
+       sem_t             ad_closesem;   /* Locks out new opens while close is in progress */
+       sem_t             ad_recvsem;    /* Used to wakeup user waiting for space in ad_recv.buffer */
+       struct adc_fifo_s ad_recv;       /* Describes receive FIFO */
+#endif
 
-/************************************************************************************
- * Public Data
- ************************************************************************************/
+       /* Fields provided by lower half ADC logic */
 
-/************************************************************************************
- * Public Functions
- ************************************************************************************/
+       FAR const struct adc_ops_s *ad_ops;  /* Arch-specific operations */
+       FAR void                   *ad_priv; /* Used by the arch-specific logic */
+};
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
 
 #if defined(__cplusplus)
-extern "C" {
+extern "C"
+{
 #endif
 
-/************************************************************************************
+/****************************************************************************
  * "Upper-Half" ADC Driver Interfaces
- ************************************************************************************/
-/************************************************************************************
+ ****************************************************************************/
+
+/****************************************************************************
  * Name: adc_register
  *
  * Description:
- *   Register a ADC driver. This function binds an instance of a "lower half" ADC
- *   driver with the "upper half" ADC device and registers that device so that can
- *   be used by application code.
+ *   Register a ADC driver. This function binds an instance of a "lower half"
+ *   ADC driver with the "upper half" ADC device and registers that device so
+ *   that can be used by application code.
  *
  * Input parameters:
- *   path - The full path to the driver to be registers in the TinyAra pseudo-
- *     filesystem.  The recommended convention is to name all PWM drivers
- *     as "/dev/adc", "/dev/adc1", etc.  where the driver path differs only
- *     in the "minor" number at the end of the device name.
+ *   path - The full path to the driver to be registers in the TinyARA
+ *     pseudo-filesystem. The recommended convention is to name all PWM
+ *     drivers as "/dev/adc", "/dev/adc1", etc.  where the driver path differs
+ *     only in the "minor" number at the end of the device name.
  *   dev - A pointer to an instance of lower half ADC driver.  This instance
  *     is bound to the upper half ADC driver and must persists as long as the
  *     upper half driver driver persists.
@@ -195,43 +248,27 @@ extern "C" {
  * Returned Value:
  *   Zero on success; a negated errno value on failure.
  *
- ************************************************************************************/
+ ****************************************************************************/
 
 int adc_register(FAR const char *path, FAR struct adc_dev_s *dev);
 
-/************************************************************************************
- * Name: adc_receive
- *
- * Description:
- *   This function is called from the lower half, platform-specific ADC logic when
- *   new ADC sample data is available.
- *
- * Input Parameters:
- *   dev - The ADC device structure that was previously registered by adc_register()
- *   ch  - And ID for the ADC channel number that generated the data
- *   data - The actualy converted data from the channel.
- *
- * Returned Value:
- *   Zero on success; a negated errno value on failure.
- *
- ************************************************************************************/
-
-int adc_receive(FAR struct adc_dev_s *dev, uint8_t ch, int32_t data);
-
-/************************************************************************************
+/****************************************************************************
  * Platform-Independent "Lower Half" ADC Driver Interfaces
- ************************************************************************************/
-/************************************************************************************
+ ****************************************************************************/
+
+/****************************************************************************
  * Name: up_ads1255initialize
  *
  * Description:
  *   Initialize the TI ADS 125X lower half driver
  *
- ************************************************************************************/
+ ****************************************************************************/
 
-FAR struct adc_dev_s *up_ads1255initialize(FAR struct spi_dev_s *spi, unsigned int devno);
+FAR struct adc_dev_s *up_ads1255initialize(FAR struct spi_dev_s *spi,
+               unsigned int devno);
 
 #if defined(__cplusplus)
 }
 #endif
-#endif                                                 /* __INCLUDE_TINYARA_ANALOG_ADC_H */
+
+#endif /* __INCLUDE_TINYARA_ANALOG_ADC_H */
diff --git a/os/include/tinyara/analog/ioctl.h b/os/include/tinyara/analog/ioctl.h
new file mode 100644 (file)
index 0000000..c8a0c1a
--- /dev/null
@@ -0,0 +1,113 @@
+/****************************************************************************
+ *
+ * Copyright 2017 Samsung Electronics All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * include/tinyara/analog/ioctl.h
+ *
+ *   Copyright (C) 2017 Gregory Nutt. All rights reserved.
+ *   Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_TINYARA_ANALOG_IOCTL_H
+#define __INCLUDE_TINYARA_ANALOG_IOCTL_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <tinyara/config.h>
+#include <tinyara/fs/ioctl.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/*
+ * The analog driver sub-system uses the standard character driver framework.
+ * However, since the driver is a devices control interface rather than a
+ * data transfer interface, the majority of the functionality is implemented
+ * in driver ioctl calls.  Standard ioctl commands are listed below:
+ */
+
+/* ADC */
+
+#define ANIOC_TRIGGER          _ANIOC(0x0001)  /* Trigger one conversion
+                                                * IN: None
+                                                * OUT: None */
+
+#define AN_FIRST               0x0001          /* First commands */
+#define AN_NCMDS               1               /* Two common commands */
+
+/*
+ * User defined ioctl commands are also supported. These will be forwarded
+ * by the upper-half QE driver to the lower-half QE driver via the ioctl()
+ * method of the QE lower-half interface. However, the lower-half driver
+ * must reserve a block of commands as follows in order prevent IOCTL
+ * command numbers from overlapping.
+ */
+
+/* See include/tinyara/sensors/ads2142.h */
+
+#define AN_ADS2142_FIRST       (AN_FIRST + AN_NCMDS)
+#define AN_ADS2142_NCMDS       6
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_TINYARA_ANALOG_IOCTL_H */