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 */