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

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

commit e884b6c3c8b213ac1dc5d772dc37c4d16d773c04
Author: Jorge Guzman <[email protected]>
AuthorDate: Mon Aug 31 01:23:30 2026 -0300

    input/gt9xx: fix register write and no-contact read
    
    Two defects keep the driver from reporting touches on a board that
    cannot use the interrupt line.
    
    The register write built two messages joined by I2C_M_NOSTART.  That
    puts the same bytes on the wire as a single three byte message, but
    resuming a transfer without a start condition is optional, and a
    controller that does not implement it fails the transfer.  On the
    ESP32-P4 every write returned -ETIMEDOUT, so the buffer status clear
    at 0x814E never reached the controller and gt9xx_read_touch_data()
    returned an error for every read.  Send the register address and the
    value as a single message.
    
    read() returned a full struct touch_sample_s even when the controller
    reported no contact, with npoints set to zero.  A caller that judges
    the read by its return value takes that for valid data: the LVGL
    touchscreen driver reads a second sample to decide whether to keep
    reading, always gets one, so it sets continue_reading on every pass
    and lv_indev_read() never returns.  The display then stops refreshing
    after the first frame while the touch reads spin.  Return -EAGAIN when
    there is no contact and the file was opened with O_NONBLOCK, which is
    what the touchscreen upper half does in the same situation.  A
    blocking reader keeps the previous behaviour.
    
    While here, add the blank line after the declaration in gt9xx_poll() that
    nxstyle asks for.  It predates this change, but the CI runs checkpatch over
    every file a commit touches, so it has to go.
    
    Signed-off-by: Jorge Guzman <[email protected]>
---
 drivers/input/gt9xx.c | 53 ++++++++++++++++++++++++++-------------------------
 1 file changed, 27 insertions(+), 26 deletions(-)

diff --git a/drivers/input/gt9xx.c b/drivers/input/gt9xx.c
index 30ebf183ad6..6875e7aa1ce 100644
--- a/drivers/input/gt9xx.c
+++ b/drivers/input/gt9xx.c
@@ -30,6 +30,7 @@
  ****************************************************************************/
 
 #include <nuttx/config.h>
+
 #include <sys/types.h>
 #include <stdbool.h>
 #include <stdint.h>
@@ -37,6 +38,7 @@
 #include <poll.h>
 #include <assert.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <nuttx/debug.h>
 
 #include <nuttx/arch.h>
@@ -237,40 +239,27 @@ static int gt9xx_i2c_write(FAR struct gt9xx_dev_s *dev,
 {
   int ret;
 
-  /* Send the Register Address, MSB first */
-
-  uint8_t regbuf[2] =
-  {
-    reg >> 8,   /* First Byte: MSB */
-    reg & 0xff  /* Second Byte: LSB */
-  };
-
-  /* Send the Register Value */
+  /* Send the Register Address MSB first, followed by the value, as a
+   * single message.  Splitting it into two messages joined by
+   * I2C_M_NOSTART puts the same bytes on the wire, but not every I2C
+   * controller can resume a transfer that way.
+   */
 
-  uint8_t buf[1] =
+  uint8_t buf[3] =
   {
-    val  /* Value to be written */
+    reg >> 8,   /* First Byte: Register Address MSB */
+    reg & 0xff, /* Second Byte: Register Address LSB */
+    val         /* Third Byte: Value to be written */
   };
 
-  /* Compose the I2C Messages */
+  /* Compose the I2C Message */
 
-  struct i2c_msg_s msgv[2] =
+  struct i2c_msg_s msgv[1] =
   {
     {
-      /* Send the I2C Register Address */
-
       .frequency = CONFIG_INPUT_GT9XX_I2C_FREQUENCY,
       .addr      = dev->addr,
       .flags     = 0,
-      .buffer    = regbuf,
-      .length    = sizeof(regbuf)
-    },
-    {
-      /* Send the I2C Register Value */
-
-      .frequency = CONFIG_INPUT_GT9XX_I2C_FREQUENCY,
-      .addr      = dev->addr,
-      .flags     = I2C_M_NOSTART,
       .buffer    = buf,
       .length    = sizeof(buf)
     }
@@ -551,9 +540,20 @@ static ssize_t gt9xx_read(FAR struct file *filep, FAR char 
*buffer,
           iinfo("skip duplicate x=%d, y=%d\n", priv->x, priv->y);
         }
 
-      /* Return the Touch Point */
+      /* Return the Touch Point, if there is one.  With no contact and a
+       * non-blocking read there is nothing to hand over: a sample carrying
+       * zero points would look like valid data to callers that judge the
+       * read by its return value.
+       */
 
-      memcpy(buffer, &sample, sizeof(sample));
+      if (sample.npoints == 0 && (filep->f_oflags & O_NONBLOCK) != 0)
+        {
+          ret = -EAGAIN;
+        }
+      else
+        {
+          memcpy(buffer, &sample, sizeof(sample));
+        }
 
       /* Begin Critical Section */
 
@@ -826,6 +826,7 @@ static int gt9xx_poll(FAR struct file *filep, FAR struct 
pollfd *fds,
       /* If Poll Teardown: Remove the poll setup */
 
       FAR struct pollfd **slot = (FAR struct pollfd **)fds->priv;
+
       DEBUGASSERT(slot != NULL);
 
       *slot = NULL;

Reply via email to