This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 7381245  input/touchscreen: separate the interface for user interaction
7381245 is described below

commit 73812451599a24fce017142a10ff34037c7d54dc
Author: futerigele <futerig...@xiaomi.com>
AuthorDate: Thu Oct 28 14:49:31 2021 +0800

    input/touchscreen: separate the interface for user interaction
    
    Separate the interface for user interaction, touch upper half
    provides the interface uniformly.
    
    Signed-off-by: futerigele <futerig...@xiaomi.com>
---
 drivers/input/Kconfig             |  11 +
 drivers/input/Make.defs           |   4 +
 drivers/input/touchscreen_upper.c | 426 ++++++++++++++++++++++++++++++++++++++
 include/nuttx/input/touchscreen.h | 140 ++++++++++---
 4 files changed, 551 insertions(+), 30 deletions(-)

diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index aca3379..2d2bab0 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -32,8 +32,19 @@ endif # INPUT_MOUSE
 
 config INPUT_TOUCHSCREEN
        bool
+       select MM_CIRCBUF
        default n
 
+if INPUT_TOUCHSCREEN
+
+config INPUT_TOUCHSCREEN_NPOLLWAITERS
+       int "Number touchscreen poll waiters"
+       default 4
+       ---help---
+               Maximum number of threads that can be waiting on poll()
+
+endif # INPUT_TOUCHSCREEN
+
 config INPUT_MAX11802
        bool "MAX11802 touchscreen controller"
        default n
diff --git a/drivers/input/Make.defs b/drivers/input/Make.defs
index 218963d..44dbb5e 100644
--- a/drivers/input/Make.defs
+++ b/drivers/input/Make.defs
@@ -24,6 +24,10 @@ ifeq ($(CONFIG_INPUT),y)
 
 # Include the selected touchscreen drivers
 
+ifeq ($(CONFIG_INPUT_TOUCHSCREEN),y)
+CSRCS += touchscreen_upper.c
+endif
+
 ifeq ($(CONFIG_INPUT_TSC2007),y)
   CSRCS += tsc2007.c
 endif
diff --git a/drivers/input/touchscreen_upper.c 
b/drivers/input/touchscreen_upper.c
new file mode 100644
index 0000000..1298f03
--- /dev/null
+++ b/drivers/input/touchscreen_upper.c
@@ -0,0 +1,426 @@
+/****************************************************************************
+ * drivers/input/touchscreen_upper.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <poll.h>
+#include <fcntl.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/mm/circbuf.h>
+#include <nuttx/input/touchscreen.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This structure is for touchscreen upper half driver */
+
+struct touch_upperhalf_s
+{
+  uint8_t                      open_count;   /* Number of times the device has 
been opened */
+  uint32_t                     buff_nums;    /* Number of touch point 
structure */
+  uint8_t                      nwaiters;     /* Number of threads waiting for 
touch point data */
+  sem_t                        exclsem;      /* Manages exclusive access to 
this structure */
+  sem_t                        buffersem;    /* Used to wait for the 
availability of data */
+  struct circbuf_s             buffer;       /* Store touch point data in 
circle buffer */
+
+  /* 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'.
+   */
+
+  FAR struct pollfd            *fds[CONFIG_INPUT_TOUCHSCREEN_NPOLLWAITERS];
+  FAR struct touch_lowerhalf_s *lower;       /* A pointer of lower half 
instance */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static void    touch_notify(FAR struct touch_upperhalf_s *upper,
+                            pollevent_t eventset);
+static int     touch_open(FAR struct file *filep);
+static int     touch_close(FAR struct file *filep);
+static ssize_t touch_read(FAR struct file *filep, FAR char *buffer,
+                          size_t buflen);
+static int     touch_ioctl(FAR struct file *filep, int cmd,
+                           unsigned long arg);
+static int     touch_poll(FAR struct file *filep, FAR struct pollfd *fds,
+                          bool setup);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_touch_fops =
+{
+  touch_open,
+  touch_close,
+  touch_read,
+  NULL,
+  NULL,
+  touch_ioctl,
+  touch_poll
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static void touch_notify(FAR struct touch_upperhalf_s *upper,
+                         pollevent_t eventset)
+{
+  FAR struct pollfd *fd;
+  int i;
+
+  for (i = 0; i < CONFIG_INPUT_TOUCHSCREEN_NPOLLWAITERS; i++)
+    {
+      fd = upper->fds[i];
+      if (fd)
+        {
+          fd->revents |= (fd->events & eventset);
+          if (fd->revents != 0)
+            {
+              /* report event log */
+
+              int semcount;
+              nxsem_get_value(fd->sem, &semcount);
+              if (semcount < 1)
+                {
+                   nxsem_post(fd->sem);
+                }
+            }
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: touch_open
+ ****************************************************************************/
+
+static int touch_open(FAR struct file *filep)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct touch_upperhalf_s *upper = inode->i_private;
+  FAR struct touch_lowerhalf_s *lower = upper->lower;
+  int ret;
+  int tmp;
+
+  ret = nxsem_wait(&upper->exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  tmp = upper->open_count + 1;
+  if (tmp == 0)
+    {
+      ret = -EMFILE;
+      goto err_out;
+    }
+  else if (tmp == 1)
+    {
+      ret = circbuf_init(&upper->buffer, NULL, upper->buff_nums *
+                         SIZEOF_TOUCH_SAMPLE_S(lower->maxpoint));
+      if (ret < 0)
+        {
+          goto err_out;
+        }
+    }
+
+  upper->open_count = tmp;
+
+err_out:
+  nxsem_post(&upper->exclsem);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: touch_close
+ ****************************************************************************/
+
+static int touch_close(FAR struct file *filep)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct touch_upperhalf_s *upper = inode->i_private;
+  int ret;
+
+  ret = nxsem_wait(&upper->exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  if (upper->open_count == 1)
+    {
+      upper->open_count--;
+      circbuf_uninit(&upper->buffer);
+    }
+
+  nxsem_post(&upper->exclsem);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: touch_read
+ ****************************************************************************/
+
+static ssize_t touch_read(FAR struct file *filep, FAR char *buffer,
+                          size_t len)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct touch_upperhalf_s *upper = inode->i_private;
+  int ret;
+
+  if (!buffer || !len)
+    {
+      return -EINVAL;
+    }
+
+  ret = nxsem_wait(&upper->exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  while (circbuf_is_empty(&upper->buffer))
+    {
+      if (filep->f_oflags & O_NONBLOCK)
+        {
+          ret = -EAGAIN;
+          goto out;
+        }
+      else
+        {
+          nxsem_post(&upper->exclsem);
+          ret = nxsem_wait_uninterruptible(&upper->buffersem);
+          if (ret < 0)
+            {
+              return ret;
+            }
+
+          ret = nxsem_wait(&upper->exclsem);
+          if (ret < 0)
+            {
+              return ret;
+            }
+        }
+    }
+
+  ret = circbuf_read(&upper->buffer, buffer, len);
+
+out:
+  nxsem_post(&upper->exclsem);
+  return ret;
+}
+
+static int touch_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct touch_upperhalf_s *upper = inode->i_private;
+  FAR struct touch_lowerhalf_s *lower = upper->lower;
+  int ret;
+
+  ret = nxsem_wait(&upper->exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  if (lower->control)
+    {
+      ret = lower->control(lower, cmd, arg);
+    }
+  else
+    {
+      ret = -ENOTTY;
+    }
+
+  nxsem_post(&upper->exclsem);
+  return ret;
+}
+
+static int touch_poll(FAR struct file *filep,
+                      struct pollfd *fds, bool setup)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct touch_upperhalf_s *upper = inode->i_private;
+  pollevent_t eventset = 0;
+  int ret;
+  int i;
+
+  ret = nxsem_wait(&upper->exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  if (setup)
+    {
+      for (i = 0; i < CONFIG_INPUT_TOUCHSCREEN_NPOLLWAITERS; i++)
+        {
+          if (NULL == upper->fds[i])
+            {
+              upper->fds[i] = fds;
+              fds->priv = &upper->fds[i];
+              break;
+            }
+        }
+
+      if (i >= CONFIG_INPUT_TOUCHSCREEN_NPOLLWAITERS)
+        {
+          fds->priv = NULL;
+          ret       = -EBUSY;
+          goto errout;
+        }
+
+      if (!circbuf_is_empty(&upper->buffer))
+        {
+          eventset |= (fds->events & POLLIN);
+        }
+
+      if (eventset)
+        {
+          touch_notify(upper, eventset);
+        }
+    }
+  else if (fds->priv)
+    {
+      for (i = 0; i < CONFIG_INPUT_TOUCHSCREEN_NPOLLWAITERS; i++)
+        {
+          if (fds == upper->fds[i])
+            {
+              upper->fds[i] = NULL;
+              fds->priv = NULL;
+              break;
+            }
+        }
+    }
+
+errout:
+  nxsem_post(&upper->exclsem);
+  return ret;
+}
+
+/****************************************************************************
+ * Public Function
+ ****************************************************************************/
+
+void touch_event(FAR void *priv, FAR const struct touch_sample_s *sample)
+{
+  FAR struct touch_upperhalf_s *upper = priv;
+  int semcount;
+
+  if (nxsem_wait(&upper->exclsem) < 0)
+    {
+      return;
+    }
+
+  circbuf_overwrite(&upper->buffer, sample,
+                    SIZEOF_TOUCH_SAMPLE_S(sample->npoints));
+  touch_notify(upper, POLLIN);
+  nxsem_get_value(&upper->buffersem, &semcount);
+  if (semcount < 1)
+    {
+      nxsem_post(&upper->buffersem);
+    }
+
+  nxsem_post(&upper->exclsem);
+}
+
+int touch_register(FAR struct touch_lowerhalf_s *lower,
+                   FAR const char *path, uint8_t buff_nums)
+{
+  FAR struct touch_upperhalf_s *upper;
+  int ret;
+
+  iinfo("Registering %s\n", path);
+
+  if (lower == NULL || !buff_nums)
+    {
+      ierr("ERROR: invalid touchscreen device\n");
+      return -EINVAL;
+    }
+
+  upper = kmm_zalloc(sizeof(struct touch_upperhalf_s));
+  if (!upper)
+    {
+      ierr("ERROR: Failed to mem alloc!\n");
+      return -ENOMEM;
+    }
+
+  upper->lower     = lower;
+  upper->buff_nums = buff_nums;
+
+  nxsem_init(&upper->exclsem, 0, 1);
+  nxsem_init(&upper->buffersem, 0, 0);
+
+  nxsem_set_protocol(&upper->buffersem, SEM_PRIO_NONE);
+
+  lower->priv = upper;
+
+  ret = register_driver(path, &g_touch_fops, 0666, upper);
+  if (ret < 0)
+    {
+      goto err_out;
+    }
+
+  return ret;
+err_out:
+  nxsem_destroy(&upper->exclsem);
+  nxsem_destroy(&upper->buffersem);
+  kmm_free(upper);
+  return ret;
+}
+
+void touch_unregister(FAR struct touch_lowerhalf_s *lower,
+                      FAR const char *path)
+{
+  FAR struct touch_upperhalf_s *upper;
+
+  DEBUGASSERT(lower != NULL);
+  DEBUGASSERT(lower->priv != NULL);
+
+  upper = lower->priv;
+
+  iinfo("UnRegistering %s\n", path);
+  unregister_driver(path);
+
+  nxsem_destroy(&upper->exclsem);
+  nxsem_destroy(&upper->buffersem);
+
+  kmm_free(upper);
+}
diff --git a/include/nuttx/input/touchscreen.h 
b/include/nuttx/input/touchscreen.h
index 0647a88..0af133a 100644
--- a/include/nuttx/input/touchscreen.h
+++ b/include/nuttx/input/touchscreen.h
@@ -1,4 +1,4 @@
-/************************************************************************************
+/****************************************************************************
  * include/nuttx/input/touchscreen.h
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -16,7 +16,7 @@
  * License for the specific language governing permissions and limitations
  * under the License.
  *
- 
************************************************************************************/
+ ****************************************************************************/
 
 /* The TOUCHSCREEN driver exports a standard character driver interface. By
  * convention, the touchscreen driver is registers as an input device at
@@ -30,20 +30,22 @@
 #ifndef __INCLUDE_NUTTX_INPUT_TOUCHSCREEN_H
 #define __INCLUDE_NUTTX_INPUT_TOUCHSCREEN_H
 
-/************************************************************************************
+/****************************************************************************
  * Included Files
- 
************************************************************************************/
+ ****************************************************************************/
 
 #include <nuttx/config.h>
 #include <nuttx/fs/ioctl.h>
+#include <nuttx/mm/circbuf.h>
+#include <nuttx/semaphore.h>
 
 #ifdef CONFIG_INPUT
 
-/************************************************************************************
+/****************************************************************************
  * Pre-processor Definitions
- 
************************************************************************************/
+ ****************************************************************************/
 
-/* IOCTL Commands 
*******************************************************************/
+/* IOCTL Commands ***********************************************************/
 
 /* Common TSC IOCTL commands */
 
@@ -56,28 +58,29 @@
 #define TSC_FIRST            0x0001          /* First common command */
 #define TSC_NCMDS            5               /* Five common commands */
 
-/* User defined ioctl commands are also supported.  However, the TSC driver 
must
- * reserve a block of commands as follows in order prevent IOCTL command 
numbers
- * from overlapping.
+/* User defined ioctl commands are also supported.  However, the
+ * TSC driver must reserve a block of commands as follows in order
+ * prevent IOCTL command numbers from overlapping.
  *
- * This is generally done as follows.  The first reservation for TSC driver A 
would
- * look like:
+ * This is generally done as follows.  The first reservation for
+ * TSC driver A would look like:
  *
- *   TSC_A_FIRST                 (TSC_FIRST + TSC_NCMDS)     <- First command
- *   TSC_A_NCMDS                 42                          <- Number of 
commands
+ *   TSC_A_FIRST         (TSC_FIRST + TSC_NCMDS)     <- First command
+ *   TSC_A_NCMDS         42                          <- Number of commands
  *
- * IOCTL commands for TSC driver A would then be defined in a TSC A header 
file like:
+ * IOCTL commands for TSC driver A would then be defined in a
+ * TSC A header file like:
  *
- *   TSCIOC_A_CMD1               _TSIOC(TSC_A_FIRST + 0)
- *   TSCIOC_A_CMD2               _TSIOC(TSC_A_FIRST + 1)
- *   TSCIOC_A_CMD3               _TSIOC(TSC_A_FIRST + 2)
+ *   TSCIOC_A_CMD1       _TSIOC(TSC_A_FIRST + 0)
+ *   TSCIOC_A_CMD2       _TSIOC(TSC_A_FIRST + 1)
+ *   TSCIOC_A_CMD3       _TSIOC(TSC_A_FIRST + 2)
  *   ...
- *   TSCIOC_A_CMD42              _TSIOC(TSC_A_FIRST + 41)
+ *   TSCIOC_A_CMD42      _TSIOC(TSC_A_FIRST + 41)
  *
  * The next reservation would look like:
  *
- *   TSC_B_FIRST                 (TSC_A_FIRST + TSC_A_NCMDS) <- Next command
- *   TSC_B_NCMDS                 77                          <- Number of 
commands
+ *   TSC_B_FIRST         (TSC_A_FIRST + TSC_A_NCMDS) <- Next command
+ *   TSC_B_NCMDS         77                          <- Number of commands
  */
 
 /* These definitions provide the meaning of all of the bits that may be
@@ -92,9 +95,9 @@
 #define TOUCH_PRESSURE_VALID (1 << 5) /* Hardware provided a valid pressure */
 #define TOUCH_SIZE_VALID     (1 << 6) /* Hardware provided a valid H/W contact 
size */
 
-/************************************************************************************
+/****************************************************************************
  * Public Types
- 
************************************************************************************/
+ ****************************************************************************/
 
 /* This structure contains information about a single touch point.
  * Positional units are device specific.
@@ -111,9 +114,9 @@ struct touch_point_s
   uint16_t pressure; /* Touch pressure */
 };
 
-/* The typical touchscreen driver is a read-only, input character device 
driver.
- * the driver write() method is not supported and any attempt to open the
- * driver in any mode other than read-only will fail.
+/* The typical touchscreen driver is a read-only, input character device
+ * driver.the driver write() method is not supported and any attempt to
+ * open the driver in any mode other than read-only will fail.
  *
  * Data read from the touchscreen device consists only of touch events and
  * touch sample data.  This is reflected by struct touch_sample_s.  This
@@ -121,8 +124,8 @@ struct touch_point_s
  *
  * On some devices, multiple touchpoints may be supported. So this top level
  * data structure is a struct touch_sample_s that "contains" a set of touch
- * points.  Each touch point is managed individually using an ID that 
identifies
- * a touch from first contact until the end of the contact.
+ * points.  Each touch point is managed individually using an ID that
+ * identifies a touch from first contact until the end of the contact.
  */
 
 struct touch_sample_s
@@ -134,9 +137,86 @@ struct touch_sample_s
 #define SIZEOF_TOUCH_SAMPLE_S(n) \
   (sizeof(struct touch_sample_s) + ((n) - 1) * sizeof(struct touch_point_s))
 
-/************************************************************************************
+/* This structure is for touchscreen lower half driver */
+
+struct touch_lowerhalf_s
+{
+  uint8_t       maxpoint;       /* Maximal point supported by the touchscreen 
*/
+  FAR void      *priv;          /* Save the upper half pointer */
+
+  /**************************************************************************
+   * Name: control
+   *
+   * Description:
+   *   Users can use this interface to implement custom IOCTL.
+   *
+   * Arguments:
+   *   lower   - The instance of lower half of touchscreen device.
+   *   cmd     - User defined specific command.
+   *   arg     - Argument of the specific command.
+   *
+   * Return Value:
+   *   Zero(OK) on success; a negated errno value on failure.
+   *   -ENOTTY - The command is not supported.
+   **************************************************************************/
+
+  CODE int (*control)(FAR struct touch_lowerhalf_s *lower,
+                      int cmd, unsigned long arg);
+};
+
+/****************************************************************************
  * Public Function Prototypes
- 
************************************************************************************/
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: touch_event
+ *
+ * Description:
+ *   The lower half driver pushes touchscreen events through this interface,
+ *   provided by touchscreen upper half.
+ *
+ * Arguments:
+ *   priv    - Upper half driver handle.
+ *   sample  - pointer to data of touch point event.
+ ****************************************************************************/
+
+void touch_event(FAR void *priv, FAR const struct touch_sample_s *sample);
+
+/****************************************************************************
+ * Name: touch_register
+ *
+ * Description:
+ *   This function registers a touchscreen device, the upper half binds
+ *   with hardware device through the lower half instance.
+ *
+ * Arguments:
+ *   lower     - A pointer of lower half instance.
+ *   path      - The path of touchscreen device. such as "/dev/input0"
+ *   buff_nums - Number of the touch points structure.
+ *
+ * Return:
+ *   OK if the driver was successfully registered; A negated errno value is
+ *   returned on any failure.
+ *
+ ****************************************************************************/
+
+int touch_register(FAR struct touch_lowerhalf_s *lower,
+                   FAR const char *path, uint8_t buff_nums);
+
+/****************************************************************************
+ * Name: touch_unregister
+ *
+ * Description:
+ *   This function is used to touchscreen driver to unregister and
+ *   release the occupied resources.
+ *
+ * Arguments:
+ *   lower     - A pointer to an insatnce of touchscreen lower half driver.
+ *   path      - The path of touchscreen device. such as "/dev/input0"
+ ****************************************************************************/
+
+void touch_unregister(FAR struct touch_lowerhalf_s *lower,
+                      FAR const char *path);
 
 #ifdef __cplusplus
 #define EXTERN extern "C"

Reply via email to