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 <[email protected]>
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 <[email protected]>
---
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"