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

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

commit 770d4a6c868e22989c1f5365d8f646e661136204
Author: wangjianyu3 <wangjian...@xiaomi.com>
AuthorDate: Sat Jul 5 00:36:05 2025 +0800

    drivers/input/ft5x06: Adapt to touchscreen frame
    
    Calling touch_register() to register touchscreen driver instead of
    registering generic driver.
    
    Signed-off-by: wangjianyu3 <wangjian...@xiaomi.com>
---
 drivers/input/Kconfig        |  16 +-
 drivers/input/ft5x06.c       | 453 ++++---------------------------------------
 include/nuttx/input/ft5x06.h |   2 +
 3 files changed, 40 insertions(+), 431 deletions(-)

diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index 959b9e0cda..47b861b739 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -218,12 +218,6 @@ config FT5X06_POLLMODE
                in detecting touch related events and (2) it will consume a
                significant amount of CPU time to perform the polling.
 
-config FT5X06_SWAPXY
-       bool "Swap X/Y"
-       default n
-       ---help---
-               Reverse the meaning of X and Y to handle different LCD 
orientations.
-
 config FT5X06_SINGLEPOINT
        bool "Single point"
        default n
@@ -252,11 +246,11 @@ config FT5X06_THRESHY
 
 endif # FT5X06_SINGLEPOINT
 
-config FT5X06_NPOLLWAITERS
-       int "Number FT5336/FT5x06 poll waiters"
-       default 4
-       ---help---
-               Maximum number of threads that can be waiting on poll()
+config FT5X06_SAMPLE_NBUFFER
+       int "Number FT5336/FT5x06 sample buffers"
+       default 4
+       ---help---
+               Maximum number of samples buffered.
 
 endif # INPUT_FT5X06
 
diff --git a/drivers/input/ft5x06.c b/drivers/input/ft5x06.c
index 0af7e41c51..f5d7e31b8d 100644
--- a/drivers/input/ft5x06.c
+++ b/drivers/input/ft5x06.c
@@ -97,10 +97,7 @@
 
 struct ft5x06_dev_s
 {
-  uint8_t crefs;                            /* Number of times the device
-                                             * has been opened */
-  uint8_t nwaiters;                         /* Number of threads waiting for
-                                             * FT5x06 data */
+  struct ft5x06_config_s config;            /* Board configuration data */
   volatile bool valid;                      /* True:  New, valid touch data
                                              * in touchbuf[] */
 #ifdef CONFIG_FT5X06_SINGLEPOINT
@@ -111,14 +108,11 @@ struct ft5x06_dev_s
 #endif
   mutex_t devlock;                          /* Manages exclusive access to
                                              * this structure */
-  sem_t waitsem;                            /* Used to wait for the
-                                             * availability of data */
   uint32_t frequency;                       /* Current I2C frequency */
 #ifdef CONFIG_FT5X06_POLLMODE
   uint32_t delay;                           /* Current poll delay */
 #endif
 
-  FAR const struct ft5x06_config_s *config; /* Board configuration data */
   FAR struct i2c_master_s *i2c;             /* Saved I2C driver instance */
   struct work_s work;                       /* Supports the interrupt
                                              * handling "bottom half" */
@@ -126,13 +120,6 @@ struct ft5x06_dev_s
   struct wdog_s polltimer;                  /* Poll timer */
 #endif
   uint8_t touchbuf[FT5X06_TOUCH_DATA_LEN];  /* Raw touch data */
-
-  /* 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_FT5X06_NPOLLWAITERS];
 };
 
 /****************************************************************************
@@ -148,41 +135,15 @@ static int  ft5x06_data_interrupt(int irq, FAR void 
*context, FAR void *arg);
 #endif
 static ssize_t ft5x06_sample(FAR struct ft5x06_dev_s *priv, FAR char *buffer,
                              size_t len);
-static ssize_t ft5x06_waitsample(FAR struct ft5x06_dev_s *priv,
-                                 FAR char *buffer, size_t len);
-static int  ft5x06_bringup(FAR struct ft5x06_dev_s *priv);
-static void ft5x06_shutdown(FAR struct ft5x06_dev_s *priv);
-
-/* Character driver methods */
-
-static int  ft5x06_open(FAR struct file *filep);
-static int  ft5x06_close(FAR struct file *filep);
-static ssize_t ft5x06_read(FAR struct file *filep, FAR char *buffer,
-                           size_t len);
-static int  ft5x06_ioctl(FAR struct file *filep, int cmd,
+static int  ft5x06_bringup(FAR struct touch_lowerhalf_s *lower);
+static int  ft5x06_shutdown(FAR struct touch_lowerhalf_s *lower);
+static int  ft5x06_ioctl(FAR struct touch_lowerhalf_s *lower, int cmd,
                          unsigned long arg);
-static int  ft5x06_poll(FAR struct file *filep, FAR struct pollfd *fds,
-                        bool setup);
 
 /****************************************************************************
  * Private Data
  ****************************************************************************/
 
-/* This the vtable that supports the character driver interface */
-
-static const struct file_operations g_ft5x06_fops =
-{
-  ft5x06_open,    /* open */
-  ft5x06_close,   /* close */
-  ft5x06_read,    /* read */
-  NULL,           /* write */
-  NULL,           /* seek */
-  ft5x06_ioctl,   /* ioctl */
-  NULL,           /* mmap */
-  NULL,           /* truncate */
-  ft5x06_poll     /* poll */
-};
-
 /* Maps FT5x06 touch events into bit encoded representation used by NuttX */
 
 static const uint8_t g_event_map[4] =
@@ -203,25 +164,12 @@ static const uint8_t g_event_map[4] =
 
 static void ft5x06_notify(FAR struct ft5x06_dev_s *priv)
 {
-  /* If there are threads waiting on poll() for FT5x06 data to become
-   * available, then wake them up now.  NOTE: we wake up all waiting threads
-   * because we do not know that they are going to do.  If they all try to
-   * read the data, then some make end up blocking after all.
-   */
-
-  poll_notify(priv->fds, CONFIG_FT5X06_NPOLLWAITERS, POLLIN);
-
-  /* If there are threads waiting for read data, then signal one of them
-   * that the read data is available.
-   */
+  struct touch_sample_s sample;
 
-  if (priv->nwaiters > 0)
+  memset(&sample, 0, sizeof(sample));
+  if (ft5x06_sample(priv, (FAR char *)&sample, sizeof(sample)) > 0)
     {
-      /* After posting this semaphore, we need to exit because the FT5x06
-       * is no longer available.
-       */
-
-      nxsem_post(&priv->waitsem);
+      touch_event(priv->config.lower.priv, &sample);
     }
 }
 
@@ -240,8 +188,8 @@ static void ft5x06_data_worker(FAR void *arg)
 
   /* Get a pointer the callbacks for convenience */
 
-  DEBUGASSERT(priv != NULL && priv->config != NULL);
-  config = priv->config;
+  DEBUGASSERT(priv != NULL);
+  config = &priv->config;
 
   /* We need to have exclusive access to the touchbuf so that we do not
    * corrupt any read operation that is in place.
@@ -374,7 +322,7 @@ static int ft5x06_data_interrupt(int irq, FAR void 
*context, FAR void *arg)
    * ugly).
    */
 
-  config = priv->config;
+  config = &priv->config;
   DEBUGASSERT(config != NULL);
 
   /* Disable further interrupts */
@@ -429,13 +377,8 @@ static ssize_t ft5x06_sample(FAR struct ft5x06_dev_s 
*priv, FAR char *buffer,
 
   /* Get the reported X and Y positions */
 
-  #ifdef CONFIG_FT5X06_SWAPXY
-  y = TOUCH_POINT_GET_X(touch[0]);
-  x = TOUCH_POINT_GET_Y(touch[0]);
-#else
   x = TOUCH_POINT_GET_X(touch[0]);
   y = TOUCH_POINT_GET_Y(touch[0]);
-#endif
 
   /* Get the touch point ID and event */
 
@@ -582,13 +525,8 @@ static ssize_t ft5x06_sample(FAR struct ft5x06_dev_s 
*priv, FAR char *buffer,
 
       point[i].id       = TOUCH_POINT_GET_ID(touch[i]);
       point[i].flags    = g_event_map[event];
-#ifdef CONFIG_FT5X06_SWAPXY
-      point[i].y        = TOUCH_POINT_GET_X(touch[i]);
-      point[i].x        = TOUCH_POINT_GET_Y(touch[i]);
-#else
       point[i].x        = TOUCH_POINT_GET_X(touch[i]);
       point[i].y        = TOUCH_POINT_GET_Y(touch[i]);
-#endif
       point[i].h        = 0;
       point[i].w        = 0;
       point[i].pressure = 0;
@@ -599,71 +537,13 @@ static ssize_t ft5x06_sample(FAR struct ft5x06_dev_s 
*priv, FAR char *buffer,
 }
 #endif /* CONFIG_FT5X06_SINGLEPOINT */
 
-/****************************************************************************
- * Name: ft5x06_waitsample
- ****************************************************************************/
-
-static ssize_t ft5x06_waitsample(FAR struct ft5x06_dev_s *priv,
-                                 FAR char *buffer, size_t len)
-{
-  int ret;
-
-  /* Now release the semaphore that manages mutually exclusive access to
-   * the device structure.  This may cause other tasks to become ready to
-   * run, but they cannot run yet because pre-emption is disabled.
-   */
-
-  nxmutex_unlock(&priv->devlock);
-
-  /* Try to get the a sample... if we cannot, then wait on the semaphore
-   * that is posted when new sample data is available.
-   */
-
-  while (!priv->valid)
-    {
-      /* Increment the count of waiters */
-
-      priv->nwaiters++;
-
-      /* Wait for a change in the FT5x06 state */
-
-      ret = nxsem_wait(&priv->waitsem);
-      priv->nwaiters--;
-
-      if (ret < 0)
-        {
-          ierr("ERROR: nxsem_wait failed: %d\n", ret);
-          goto errout;
-        }
-    }
-
-  /* Re-acquire the semaphore that manages mutually exclusive access to
-   * the device structure.  We may have to wait here.  But we have our
-   * sample.  Interrupts and pre-emption will be re-enabled while we wait.
-   */
-
-  ret = nxmutex_lock(&priv->devlock);
-  if (ret >= 0)
-    {
-      /* Now sample the data.
-       *
-       * REVISIT:  Is it safe to assume that priv->valid will always be
-       * true?  I think that sched_lock() would protect the setting.
-       */
-
-      ret = ft5x06_sample(priv, buffer, len);
-    }
-
-errout:
-  return ret;
-}
-
 /****************************************************************************
  * Name: ft5x06_bringup
  ****************************************************************************/
 
-static int ft5x06_bringup(FAR struct ft5x06_dev_s *priv)
+static int ft5x06_bringup(FAR struct touch_lowerhalf_s *lower)
 {
+  FAR struct ft5x06_dev_s *priv = (FAR struct ft5x06_dev_s *)lower;
   FAR const struct ft5x06_config_s *config;
   struct i2c_msg_s msg;
   uint8_t data[2];
@@ -673,7 +553,7 @@ static int ft5x06_bringup(FAR struct ft5x06_dev_s *priv)
    * ugly).
    */
 
-  config = priv->config;
+  config = &priv->config;
   DEBUGASSERT(config != NULL);
 
   /* Set device mode to normal operation */
@@ -706,215 +586,38 @@ static int ft5x06_bringup(FAR struct ft5x06_dev_s *priv)
  * Name: ft5x06_shutdown
  ****************************************************************************/
 
-static void ft5x06_shutdown(FAR struct ft5x06_dev_s *priv)
+static int ft5x06_shutdown(FAR struct touch_lowerhalf_s *lower)
 {
+  FAR struct ft5x06_dev_s *priv = (FAR struct ft5x06_dev_s *)lower;
+
 #ifdef CONFIG_FT5X06_POLLMODE
   /* Stop the poll timer */
 
   wd_cancel(&priv->polltimer);
 
 #else
-  FAR const struct ft5x06_config_s *config = priv->config;
+  FAR const struct ft5x06_config_s *config = &priv->config;
 
   /* Make sure that the FT5x06 interrupt is disabled */
 
   config->clear(config);
   config->enable(config, false);
 #endif
-}
-
-/****************************************************************************
- * Name: ft5x06_open
- ****************************************************************************/
-
-static int ft5x06_open(FAR struct file *filep)
-{
-  FAR struct inode *inode;
-  FAR struct ft5x06_dev_s *priv;
-  uint8_t tmp;
-  int ret;
-
-  inode = filep->f_inode;
-
-  DEBUGASSERT(inode->i_private);
-  priv  = inode->i_private;
-
-  /* Get exclusive access to the driver data structure */
-
-  ret = nxmutex_lock(&priv->devlock);
-  if (ret < 0)
-    {
-      ierr("ERROR: nxmutex_lock failed: %d\n", ret);
-      return ret;
-    }
-
-  /* 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_lock;
-    }
-
-  /* When the reference increments to 1, this is the first open event
-   * on the driver.. and the time when we must initialize the driver.
-   */
-
-  if (tmp == 1)
-    {
-      ret = ft5x06_bringup(priv);
-      if (ret < 0)
-        {
-          ierr("ERROR: ft5x06_bringup failed: %d\n", ret);
-          goto errout_with_lock;
-        }
-    }
-
-  /* Save the new open count on success */
-
-  priv->crefs = tmp;
-
-errout_with_lock:
-  nxmutex_unlock(&priv->devlock);
-  return ret;
-}
-
-/****************************************************************************
- * Name: ft5x06_close
- ****************************************************************************/
-
-static int ft5x06_close(FAR struct file *filep)
-{
-  FAR struct inode *inode;
-  FAR struct ft5x06_dev_s *priv;
-  int ret;
-
-  inode = filep->f_inode;
-
-  DEBUGASSERT(inode->i_private);
-  priv  = inode->i_private;
-
-  /* Get exclusive access to the driver data structure */
-
-  ret = nxmutex_lock(&priv->devlock);
-  if (ret < 0)
-    {
-      ierr("ERROR: nxmutex_lock failed: %d\n", ret);
-      return ret;
-    }
-
-  /* Decrement the reference count unless it would decrement a negative
-   * value.
-   */
 
-  if (priv->crefs >= 1)
-    {
-      priv->crefs--;
-    }
-
-  /* When the count decrements to zero, there are no further open references
-   * to the driver and it can be uninitialized.
-   */
-
-  if (priv->crefs == 0)
-    {
-      ft5x06_shutdown(priv);
-    }
-
-  nxmutex_unlock(&priv->devlock);
-  return OK;
-}
-
-/****************************************************************************
- * Name: ft5x06_read
- ****************************************************************************/
-
-static ssize_t ft5x06_read(FAR struct file *filep, FAR char *buffer,
-                           size_t len)
-{
-  FAR struct inode *inode;
-  FAR struct ft5x06_dev_s *priv;
-  int ret;
-
-  inode = filep->f_inode;
-
-  DEBUGASSERT(inode->i_private);
-  priv  = inode->i_private;
-
-  /* Verify that the caller has provided a buffer large enough to receive
-   * the touch data.
-   */
-
-  if (len < SIZEOF_TOUCH_SAMPLE_S(1))
-    {
-      /* We could provide logic to break up a touch report into segments and
-       * handle smaller reads... but why?
-       */
-
-      return -ENOSYS;
-    }
-
-  /* Get exclusive access to the driver data structure */
-
-  ret = nxmutex_lock(&priv->devlock);
-  if (ret < 0)
-    {
-      ierr("ERROR: nxmutex_lock failed: %d\n", ret);
-      return ret;
-    }
-
-  /* Try to read sample data. */
-
-  ret = ft5x06_sample(priv, buffer, len);
-  while (ret == 0)
-    {
-      /* Sample data is not available now.  We would have to wait to receive
-       * sample data.  If the user has specified the O_NONBLOCK option, then
-       * just return an error.
-       */
-
-      if (filep->f_oflags & O_NONBLOCK)
-        {
-          ret = -EAGAIN;
-          goto errout;
-        }
-
-      /* Wait for sample data */
-
-      ret = ft5x06_waitsample(priv, buffer, len);
-      if (ret < 0)
-        {
-          /* We might have been awakened by a signal */
-
-          goto errout;
-        }
-    }
-
-  ret = SIZEOF_TOUCH_SAMPLE_S(1);
-
-errout:
-  nxmutex_unlock(&priv->devlock);
-  return ret;
+  return 0;
 }
 
 /****************************************************************************
  * Name: ft5x06_ioctl
  ****************************************************************************/
 
-static int ft5x06_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
+static int ft5x06_ioctl(FAR struct touch_lowerhalf_s *lower, int cmd,
+                        unsigned long arg)
 {
-  FAR struct inode        *inode;
-  FAR struct ft5x06_dev_s *priv;
+  FAR struct ft5x06_dev_s *priv = (FAR struct ft5x06_dev_s *)lower;
   int                      ret;
 
   iinfo("cmd: %d arg: %ld\n", cmd, arg);
-  inode = filep->f_inode;
-
-  DEBUGASSERT(inode->i_private);
-  priv  = inode->i_private;
 
   /* Get exclusive access to the driver data structure */
 
@@ -932,7 +635,7 @@ static int ft5x06_ioctl(FAR struct file *filep, int cmd, 
unsigned long arg)
       case TSIOC_SETFREQUENCY:  /* arg: Pointer to uint32_t frequency value */
         {
           FAR uint32_t *ptr = (FAR uint32_t *)((uintptr_t)arg);
-          DEBUGASSERT(priv->config != NULL && ptr != NULL);
+          DEBUGASSERT(ptr != NULL);
           priv->frequency = *ptr;
         }
         break;
@@ -940,7 +643,7 @@ static int ft5x06_ioctl(FAR struct file *filep, int cmd, 
unsigned long arg)
       case TSIOC_GETFREQUENCY:  /* arg: Pointer to uint32_t frequency value */
         {
           FAR uint32_t *ptr = (FAR uint32_t *)((uintptr_t)arg);
-          DEBUGASSERT(priv->config != NULL && ptr != NULL);
+          DEBUGASSERT(ptr != NULL);
           *ptr = priv->frequency;
         }
         break;
@@ -954,101 +657,6 @@ static int ft5x06_ioctl(FAR struct file *filep, int cmd, 
unsigned long arg)
   return ret;
 }
 
-/****************************************************************************
- * Name: ft5x06_poll
- ****************************************************************************/
-
-static int ft5x06_poll(FAR struct file *filep, FAR struct pollfd *fds,
-                       bool setup)
-{
-  FAR struct inode        *inode;
-  FAR struct ft5x06_dev_s *priv;
-  int                      ret;
-  int                      i;
-
-  iinfo("setup: %d\n", (int)setup);
-  DEBUGASSERT(fds);
-  inode = filep->f_inode;
-
-  DEBUGASSERT(inode->i_private);
-  priv  = inode->i_private;
-
-  /* Are we setting up the poll?  Or tearing it down? */
-
-  ret = nxmutex_lock(&priv->devlock);
-  if (ret < 0)
-    {
-      ierr("ERROR: nxmutex_lock failed: %d\n", ret);
-      return ret;
-    }
-
-  if (setup)
-    {
-      /* Ignore waits that do not include POLLIN */
-
-      if ((fds->events & POLLIN) == 0)
-        {
-          ierr("ERROR: Missing POLLIN: revents: %08" PRIx32 "\n",
-               fds->revents);
-          ret = -EDEADLK;
-          goto errout;
-        }
-
-      /* This is a request to set up the poll.  Find an available
-       * slot for the poll structure reference
-       */
-
-      for (i = 0; i < CONFIG_FT5X06_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_FT5X06_NPOLLWAITERS)
-        {
-          ierr("ERROR: No available slot found: %d\n", i);
-          fds->priv = NULL;
-          ret       = -EBUSY;
-          goto errout;
-        }
-
-      /* Should we immediately notify on any of the requested events? */
-
-      if (priv->valid)
-        {
-          poll_notify(&fds, 1, POLLIN);
-        }
-    }
-  else if (fds->priv)
-    {
-      /* This is a request to tear down the poll. */
-
-      FAR struct pollfd **slot = (FAR struct pollfd **)fds->priv;
-      DEBUGASSERT(slot != NULL);
-
-      /* Remove all memory of the poll setup */
-
-      *slot     = NULL;
-      fds->priv = NULL;
-    }
-
-errout:
-  nxmutex_unlock(&priv->devlock);
-  return ret;
-}
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -1101,11 +709,13 @@ int ft5x06_register(FAR struct i2c_master_s *i2c,
   /* Initialize the FT5x06 device driver instance */
 
   priv->i2c       = i2c;               /* Save the I2C device handle */
-  priv->config    = config;            /* Save the board configuration */
   priv->frequency = config->frequency; /* Set the current I2C frequency */
 
+  /* Save the board configuration */
+
+  memcpy(&priv->config, config, sizeof(priv->config));
+
   nxmutex_init(&priv->devlock);        /* Initialize device structure mutex */
-  nxsem_init(&priv->waitsem, 0, 0);    /* Initialize pen event wait semaphore 
*/
 
 #ifdef CONFIG_FT5X06_POLLMODE
   /* Allocate a timer for polling the FT5x06 */
@@ -1130,10 +740,14 @@ int ft5x06_register(FAR struct i2c_master_s *i2c,
 
   /* Register the device as an input device */
 
+  priv->config.lower.open = ft5x06_bringup;
+  priv->config.lower.close = ft5x06_shutdown;
+  priv->config.lower.control = ft5x06_ioctl;
   snprintf(devname, sizeof(devname), DEV_FORMAT, minor);
   iinfo("Registering %s\n", devname);
 
-  ret = register_driver(devname, &g_ft5x06_fops, 0666, priv);
+  ret = touch_register(&priv->config.lower, devname,
+                       CONFIG_FT5X06_SAMPLE_NBUFFER);
   if (ret < 0)
     {
       ierr("ERROR: register_driver() failed: %d\n", ret);
@@ -1157,7 +771,6 @@ int ft5x06_register(FAR struct i2c_master_s *i2c,
 
 errout_with_priv:
   nxmutex_destroy(&priv->devlock);
-  nxsem_destroy(&priv->waitsem);
   kmm_free(priv);
   return ret;
 }
diff --git a/include/nuttx/input/ft5x06.h b/include/nuttx/input/ft5x06.h
index ef81fa0cf4..72e74d6a6f 100644
--- a/include/nuttx/input/ft5x06.h
+++ b/include/nuttx/input/ft5x06.h
@@ -40,6 +40,7 @@
 
 #include <nuttx/irq.h>
 #include <nuttx/i2c/i2c_master.h>
+#include <nuttx/input/touchscreen.h>
 
 #ifdef CONFIG_INPUT_FT5X06
 
@@ -81,6 +82,7 @@ struct ft5x06_config_s
 {
   /* Device characterization */
 
+  struct touch_lowerhalf_s lower;
   uint8_t  address;    /* 7-bit I2C address (only bits 0-6 used) */
   uint32_t frequency;  /* Default I2C frequency */
 

Reply via email to