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 face051 touchscreen: update sim_touchscreen, using touch_upperhalf face051 is described below commit face0514b696221b5d7fc4fd1c7179c9fa62f183 Author: yinshengkai <yinsheng...@xiaomi.com> AuthorDate: Wed Nov 10 22:27:50 2021 +0800 touchscreen: update sim_touchscreen, using touch_upperhalf Signed-off-by: yinshengkai <yinsheng...@xiaomi.com> --- arch/sim/Kconfig | 1 + arch/sim/src/sim/up_touchscreen.c | 602 +++----------------------------------- 2 files changed, 40 insertions(+), 563 deletions(-) diff --git a/arch/sim/Kconfig b/arch/sim/Kconfig index 4ef4fc8..115f346 100644 --- a/arch/sim/Kconfig +++ b/arch/sim/Kconfig @@ -323,6 +323,7 @@ choice config SIM_TOUCHSCREEN bool "X11 mouse-based touchscreen emulation" + select INPUT_TOUCHSCREEN depends on SIM_X11FB ---help--- Support an X11 mouse-based touchscreen emulation. Also needs INPUT=y diff --git a/arch/sim/src/sim/up_touchscreen.c b/arch/sim/src/sim/up_touchscreen.c index 062906b..962a8be 100644 --- a/arch/sim/src/sim/up_touchscreen.c +++ b/arch/sim/src/sim/up_touchscreen.c @@ -28,22 +28,10 @@ #include <stdbool.h> #include <stdio.h> -#include <unistd.h> #include <string.h> -#include <fcntl.h> -#include <poll.h> -#include <errno.h> #include <assert.h> #include <debug.h> -#include <nuttx/irq.h> -#include <nuttx/board.h> -#include <nuttx/kmalloc.h> -#include <nuttx/arch.h> -#include <nuttx/semaphore.h> -#include <nuttx/fs/fs.h> -#include <nuttx/nx/nx.h> - #include <nuttx/input/touchscreen.h> #include "up_internal.h" @@ -52,12 +40,6 @@ * Pre-processor Definitions ****************************************************************************/ -/* Configuration ************************************************************/ - -#ifndef CONFIG_SIM_TCNWAITERS -# define CONFIG_SIM_TCNWAITERS 4 -#endif - /* Driver support ***********************************************************/ /* This format is used to construct the /dev/input[n] device driver path. It @@ -71,83 +53,21 @@ * Private Types ****************************************************************************/ -/* This describes the state of one contact */ - -enum up_contact_3 -{ - CONTACT_NONE = 0, /* No contact */ - CONTACT_DOWN, /* First contact */ - CONTACT_MOVE, /* Same contact, possibly different position */ - CONTACT_UP, /* Contact lost */ -}; - -/* This structure describes the results of one touchscreen sample */ - -struct up_sample_s -{ - uint8_t id; /* Sampled touch point ID */ - uint8_t contact; /* Contact state (see enum up_contact_e) */ - uint16_t x; /* Measured X position */ - uint16_t y; /* Measured Y position */ -}; - /* This structure describes the state of one touchscreen driver instance */ struct up_dev_s { int eventloop; - volatile uint8_t nwaiters; /* Number of threads waiting for touchscreen data */ uint8_t id; /* Current touch point ID */ + uint8_t contact; /* Last contact state */ uint8_t minor; /* Minor device number */ - volatile bool penchange; /* An unreported event is buffered */ - sem_t devsem; /* Manages exclusive access to this structure */ - sem_t waitsem; /* Used to wait for the availability of data */ - - struct up_sample_s sample; /* Last sampled touch point 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'. - */ - - struct pollfd *fds[CONFIG_SIM_TCNWAITERS]; + struct touch_lowerhalf_s lower; /* Touchsrceen lowerhalf */ }; /**************************************************************************** - * Private Function Prototypes - ****************************************************************************/ - -static void up_notify(FAR struct up_dev_s *priv); -static int up_sample(FAR struct up_dev_s *priv, - FAR struct up_sample_s *sample); -static int up_waitsample(FAR struct up_dev_s *priv, - FAR struct up_sample_s *sample); - -/* Character driver methods */ - -static int up_open(FAR struct file *filep); -static int up_close(FAR struct file *filep); -static ssize_t up_read(FAR struct file *filep, FAR char *buffer, size_t len); -static int up_ioctl(FAR struct file *filep, int cmd, unsigned long arg); -static int up_poll(FAR struct file *filep, struct pollfd *fds, bool setup); - -/**************************************************************************** * Private Data ****************************************************************************/ -/* This the vtable that supports the character driver interface */ - -static const struct file_operations up_fops = -{ - up_open, /* open */ - up_close, /* close */ - up_read, /* read */ - NULL, /* write */ - NULL, /* seek */ - up_ioctl, /* ioctl */ - up_poll /* poll */ -}; - /* Only one simulated touchscreen is supported so the driver state * structure may as well be pre-allocated. */ @@ -155,431 +75,6 @@ static const struct file_operations up_fops = static struct up_dev_s g_simtouchscreen; /**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: up_notify - ****************************************************************************/ - -static void up_notify(FAR struct up_dev_s *priv) -{ - int i; - - /* If there are threads waiting on poll() for touchscreen data to become - * available, then wake them up now. NOTE: we wake up all waiting threads - * because we do not know what they are going to do. If they all try to - * read the data then some make end up blocking after all. - */ - - for (i = 0; i < CONFIG_SIM_TCNWAITERS; i++) - { - struct pollfd *fds = priv->fds[i]; - if (fds) - { - fds->revents |= POLLIN; - iinfo("Report events: %02x\n", fds->revents); - nxsem_post(fds->sem); - } - } - - /* If there are threads waiting for read data, then signal one of them - * that the read data is available. - */ - - iinfo("contact=%d nwaiters=%d\n", priv->sample.contact, priv->nwaiters); - if (priv->nwaiters > 0) - { - /* After posting this semaphore, we need to exit because - * the touchscreen is no longer available. - */ - - nxsem_post(&priv->waitsem); - } -} - -/**************************************************************************** - * Name: up_sample - ****************************************************************************/ - -static int up_sample(FAR struct up_dev_s *priv, - FAR struct up_sample_s *sample) -{ - int ret = -EAGAIN; - - /* Is there new touchscreen sample data available? */ - - iinfo("penchange=%d contact=%d id=%d\n", - priv->penchange, sample->contact, priv->id); - - if (priv->penchange) - { - /* Yes.. the state has changed in some way. Return a copy of the - * sampled data. - */ - - memcpy(sample, &priv->sample, sizeof(struct up_sample_s)); - - /* Now manage state transitions */ - - if (sample->contact == CONTACT_UP) - { - /* Next.. no contract. Increment the ID so that next contact ID - * will be unique - */ - - priv->sample.contact = CONTACT_NONE; - priv->id++; - } - else if (sample->contact == CONTACT_DOWN) - { - /* First report -- next report will be a movement */ - - priv->sample.contact = CONTACT_MOVE; - } - - priv->penchange = false; - iinfo("penchange=%d contact=%d id=%d\n", - priv->penchange, priv->sample.contact, priv->id); - - ret = OK; - } - - return ret; -} - -/**************************************************************************** - * Name: up_waitsample - ****************************************************************************/ - -static int up_waitsample(FAR struct up_dev_s *priv, - FAR struct up_sample_s *sample) -{ - irqstate_t flags; - int ret; - - /* Interrupts me be disabled when this is called to (1) prevent posting - * of semphores from interrupt handlers, and (2) to prevent sampled data - * from changing until it has been reported. - * - * In addition, we will also disable pre-emption to prevent other threads - * from getting control while we muck with the semaphores. - */ - - sched_lock(); - flags = enter_critical_section(); - - /* 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. - */ - - nxsem_post(&priv->devsem); - - /* Try to get the a sample... if we cannot, then wait on the semaphore - * that is posted when new sample data is available. - */ - - while (up_sample(priv, sample) < 0) - { - /* Wait for a change in the touchscreen state */ - - iinfo("Waiting...\n"); - priv->nwaiters++; - ret = nxsem_wait(&priv->waitsem); - priv->nwaiters--; - iinfo("Awakened...\n"); - - if (ret < 0) - { - 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 = nxsem_wait(&priv->devsem); - -errout: - /* Then re-enable interrupts. We might get interrupt here and there - * could be a new sample. But no new threads will run because we still - * have pre-emption disabled. - */ - - leave_critical_section(flags); - - /* Restore pre-emption. We might get suspended here but that is okay - * because we already have our sample. Note: this means that if there - * were two threads reading from the touchscreen for some reason, the data - * might be read out of order. - */ - - sched_unlock(); - return ret; -} - -/**************************************************************************** - * Name: up_open - ****************************************************************************/ - -static int up_open(FAR struct file *filep) -{ - iinfo("Opening...\n"); - return OK; -} - -/**************************************************************************** - * Name: up_close - ****************************************************************************/ - -static int up_close(FAR struct file *filep) -{ - iinfo("Closing...\n"); - return OK; -} - -/**************************************************************************** - * Name: up_read - ****************************************************************************/ - -static ssize_t up_read(FAR struct file *filep, FAR char *buffer, size_t len) -{ - FAR struct inode *inode; - FAR struct up_dev_s *priv; - FAR struct touch_sample_s *report; - struct up_sample_s sample; - int ret; - - iinfo("len=%zd\n", len); - - DEBUGASSERT(filep); - inode = filep->f_inode; - - DEBUGASSERT(inode && inode->i_private); - priv = (FAR struct up_dev_s *)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 = nxsem_wait(&priv->devsem); - if (ret < 0) - { - return ret; - } - - /* Try to read sample data. */ - - ret = up_sample(priv, &sample); - if (ret < 0) - { - /* Sample data is not available now. We would ave to wait to get - * 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 = up_waitsample(priv, &sample); - if (ret < 0) - { - /* We might have been awakened by a signal */ - - goto errout; - } - } - - /* In any event, we now have sampled touchscreen data that we can report - * to the caller. - */ - - report = (FAR struct touch_sample_s *)buffer; - memset(report, 0, SIZEOF_TOUCH_SAMPLE_S(1)); - report->npoints = 1; - report->point[0].id = priv->id; - report->point[0].x = sample.x; - report->point[0].y = sample.y; - report->point[0].h = 1; - report->point[0].w = 1; - report->point[0].pressure = 42; - - /* Report the appropriate flags */ - - if (sample.contact == CONTACT_UP) - { - /* Pen is now up */ - - report->point[0].flags = TOUCH_UP | TOUCH_ID_VALID; - } - else if (sample.contact == CONTACT_DOWN) - { - /* First contact */ - - report->point[0].flags = TOUCH_DOWN | TOUCH_ID_VALID | - TOUCH_POS_VALID | TOUCH_PRESSURE_VALID; - } - else /* if (sample->contact == CONTACT_MOVE) */ - { - /* Movement of the same contact */ - - report->point[0].flags = TOUCH_MOVE | TOUCH_ID_VALID | - TOUCH_POS_VALID | TOUCH_PRESSURE_VALID; - } - - ret = SIZEOF_TOUCH_SAMPLE_S(1); - -errout: - iinfo("Returning %d\n", ret); - nxsem_post(&priv->devsem); - return ret; -} - -/**************************************************************************** - * Name: up_ioctl - ****************************************************************************/ - -static int up_ioctl(FAR struct file *filep, int cmd, unsigned long arg) -{ - FAR struct inode *inode; - FAR struct up_dev_s *priv; - int ret; - - iinfo("cmd: %d arg: %ld\n", cmd, arg); - DEBUGASSERT(filep); - inode = filep->f_inode; - - DEBUGASSERT(inode && inode->i_private); - priv = (FAR struct up_dev_s *)inode->i_private; - - /* Get exclusive access to the driver data structure */ - - ret = nxsem_wait(&priv->devsem); - if (ret < 0) - { - return ret; - } - - /* Process the IOCTL by command */ - - switch (cmd) - { - default: - ret = -ENOTTY; - break; - } - - nxsem_post(&priv->devsem); - return ret; -} - -/**************************************************************************** - * Name: up_poll - ****************************************************************************/ - -static int up_poll(FAR struct file *filep, FAR struct pollfd *fds, - bool setup) -{ - FAR struct inode *inode; - FAR struct up_dev_s *priv; - int ret; - int i; - - iinfo("setup: %d\n", (int)setup); - DEBUGASSERT(filep && fds); - inode = filep->f_inode; - - DEBUGASSERT(inode && inode->i_private); - priv = (FAR struct up_dev_s *)inode->i_private; - - /* Are we setting up the poll? Or tearing it down? */ - - ret = nxsem_wait(&priv->devsem); - if (ret < 0) - { - return ret; - } - - if (setup) - { - /* Ignore waits that do not include POLLIN */ - - if ((fds->revents & POLLIN) == 0) - { - 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_SIM_TCNWAITERS; 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_SIM_TCNWAITERS) - { - fds->priv = NULL; - ret = -EBUSY; - goto errout; - } - - /* Should we immediately notify on any of the requested events? */ - - if (priv->penchange) - { - up_notify(priv); - } - } - else if (fds->priv) - { - /* This is a request to tear down the poll. */ - - struct pollfd **slot = (struct pollfd **)fds->priv; - DEBUGASSERT(slot != NULL); - - /* Remove all memory of the poll setup */ - - *slot = NULL; - fds->priv = NULL; - } - -errout: - nxsem_post(&priv->devsem); - return ret; -} - -/**************************************************************************** * Public Functions ****************************************************************************/ @@ -615,29 +110,19 @@ int sim_tsc_initialize(int minor) memset(priv, 0, sizeof(struct up_dev_s)); - /* Initialize semaphores */ - - nxsem_init(&priv->devsem, 0, 1); /* Initialize device structure semaphore */ - nxsem_init(&priv->waitsem, 0, 0); /* Initialize pen event wait semaphore */ - - /* The waitsem semaphore is used for signaling and, hence, should not have - * priority inheritance enabled. - */ - - nxsem_set_protocol(&priv->waitsem, SEM_PRIO_NONE); - priv->minor = minor; + priv->lower.maxpoint = 1; /* Register the device as an input device */ snprintf(devname, DEV_NAMELEN, DEV_FORMAT, minor); iinfo("Registering %s\n", devname); - ret = register_driver(devname, &up_fops, 0666, priv); + ret = touch_register(&priv->lower, devname, 1); if (ret < 0) { - ierr("ERROR: register_driver() failed: %d\n", ret); - goto errout_with_priv; + ierr("ERROR: touch_register() failed: %d\n", ret); + return ret; } /* Enable X11 event processing from the IDLE loop */ @@ -647,11 +132,6 @@ int sim_tsc_initialize(int minor) /* And return success */ return OK; - -errout_with_priv: - nxsem_destroy(&priv->waitsem); - nxsem_destroy(&priv->devsem); - return ret; } /**************************************************************************** @@ -672,15 +152,6 @@ int sim_tsc_uninitialize(void) { FAR struct up_dev_s *priv = (FAR struct up_dev_s *)&g_simtouchscreen; char devname[DEV_NAMELEN]; - int ret = OK; - - /* Get exclusive access */ - - ret = nxsem_wait_uninterruptible(&priv->devsem); - if (ret < 0) - { - return ret; - } /* Stop the event loop (Hmm.. the caller must be sure that there are no * open references to the touchscreen driver. This might better be @@ -694,18 +165,9 @@ int sim_tsc_uninitialize(void) snprintf(devname, DEV_NAMELEN, DEV_FORMAT, priv->minor); iinfo("Un-registering %s\n", devname); - ret = unregister_driver(devname); - if (ret < 0) - { - ierr("ERROR: uregister_driver() failed: %d\n", ret); - } - - /* Clean up any resources. Ouch! While we are holding the semaphore? */ + touch_unregister(&priv->lower, devname); - nxsem_destroy(&priv->waitsem); - nxsem_destroy(&priv->devsem); - - return ret; + return OK; } /**************************************************************************** @@ -714,8 +176,9 @@ int sim_tsc_uninitialize(void) void up_buttonevent(int x, int y, int buttons) { - FAR struct up_dev_s *priv = (FAR struct up_dev_s *)&g_simtouchscreen; - bool pendown; /* true: pen is down */ + FAR struct up_dev_s *priv = (FAR struct up_dev_s *)&g_simtouchscreen; + struct touch_sample_s sample; /* Sampled touch point data */ + bool pendown; /* true: pen is down */ if (priv->eventloop == 0) { @@ -723,7 +186,6 @@ void up_buttonevent(int x, int y, int buttons) } iinfo("x=%d y=%d buttons=%02x\n", x, y, buttons); - iinfo("contact=%d nwaiters=%d\n", priv->sample.contact, priv->nwaiters); /* Any button press will count as pendown. */ @@ -738,42 +200,56 @@ void up_buttonevent(int x, int y, int buttons) * CONTACT_UP == pen up, but not reported) */ - if (priv->sample.contact == CONTACT_NONE) + if (priv->contact == TOUCH_UP) { return; } /* Not yet reported */ - priv->sample.contact = CONTACT_UP; + priv->contact = TOUCH_UP; + sample.point[0].flags = TOUCH_UP | TOUCH_ID_VALID; } else { /* Save the measurements */ - priv->sample.x = x; - priv->sample.y = y; + sample.point[0].x = x; + sample.point[0].y = y; /* Note the availability of new measurements: * If this is the first (acknowledged) pen down report, then report - * this as the first contact. If contact == CONTACT_DOWN, it will be - * set to set to CONTACT_MOVE after the contact is first sampled. + * this as the first contact. If flags == TOUCH_DOWN, it will be + * set to set to TOUCH_MOVE after the contact is first sampled. */ - if (priv->sample.contact != CONTACT_MOVE) + if (priv->contact == TOUCH_UP) { /* First contact */ - priv->sample.contact = CONTACT_DOWN; + priv->contact = TOUCH_DOWN; + sample.point[0].flags = TOUCH_DOWN | TOUCH_ID_VALID | + TOUCH_POS_VALID | TOUCH_PRESSURE_VALID; + + /* Indicate the availability of new sample data for this ID */ + + priv->id++; + } + else + { + priv->contact = TOUCH_MOVE; + sample.point[0].flags = TOUCH_MOVE | TOUCH_ID_VALID | + TOUCH_POS_VALID | TOUCH_PRESSURE_VALID; } } - /* Indicate the availability of new sample data for this ID */ - - priv->sample.id = priv->id; - priv->penchange = true; + sample.npoints = 1; + sample.point[0].h = 1; + sample.point[0].w = 1; + sample.point[0].pressure = 42; + sample.point[0].id = priv->id; - /* Notify any waiters that new touchscreen data is available */ + /* Report data changes */ - up_notify(priv); + touch_event(priv->lower.priv, &sample); }