From 2c8437151f5749a3eafd5aa3a100c246a2a75f32 Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Sun, 27 Feb 2022 02:52:47 +0800 Subject: [PATCH] input/djoystick: Fix the event lose between the invocation of poll Signed-off-by: Xiang Xiao --- drivers/input/djoystick.c | 43 +++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/drivers/input/djoystick.c b/drivers/input/djoystick.c index d1643c80fa..5e614d6cc1 100644 --- a/drivers/input/djoystick.c +++ b/drivers/input/djoystick.c @@ -99,6 +99,7 @@ struct djoy_open_s * driver events. */ + bool do_pollpending; FAR struct pollfd *do_fds[CONFIG_INPUT_DJOYSTICK_NPOLLWAITERS]; }; @@ -174,7 +175,6 @@ static void djoy_enable(FAR struct djoy_upperhalf_s *priv) djoy_buttonset_t press; djoy_buttonset_t release; irqstate_t flags; - int i; DEBUGASSERT(priv); lower = priv->du_lower; @@ -193,19 +193,8 @@ static void djoy_enable(FAR struct djoy_upperhalf_s *priv) for (opriv = priv->du_open; opriv; opriv = opriv->do_flink) { - /* Are there any poll waiters? */ - - for (i = 0; i < CONFIG_INPUT_DJOYSTICK_NPOLLWAITERS; i++) - { - if (opriv->do_fds[i]) - { - /* Yes.. OR in the poll event buttons */ - - press |= opriv->do_pollevents.dp_press; - release |= opriv->do_pollevents.dp_release; - break; - } - } + press |= opriv->do_pollevents.dp_press; + release |= opriv->do_pollevents.dp_release; /* OR in the signal events */ @@ -285,8 +274,8 @@ static void djoy_sample(FAR struct djoy_upperhalf_s *priv) * newly released. */ - change = sample ^ priv->du_sample; - press = change & sample; + change = sample ^ priv->du_sample; + press = change & sample; DEBUGASSERT(lower->dl_supported); release = change & (lower->dl_supported(lower) & ~sample); @@ -300,6 +289,8 @@ static void djoy_sample(FAR struct djoy_upperhalf_s *priv) if ((press & opriv->do_pollevents.dp_press) != 0 || (release & opriv->do_pollevents.dp_release) != 0) { + opriv->do_pollpending = true; + /* Yes.. Notify all waiters */ for (i = 0; i < CONFIG_INPUT_DJOYSTICK_NPOLLWAITERS; i++) @@ -385,6 +376,10 @@ static int djoy_open(FAR struct file *filep) opriv->do_flink = priv->du_open; priv->du_open = opriv; + /* Enable/disable interrupt handling */ + + djoy_enable(priv); + /* Attach the open structure to the file structure */ filep->f_priv = (FAR void *)opriv; @@ -498,11 +493,13 @@ static ssize_t djoy_read(FAR struct file *filep, FAR char *buffer, size_t len) { FAR struct inode *inode; + FAR struct djoy_open_s *opriv; FAR struct djoy_upperhalf_s *priv; FAR const struct djoy_lowerhalf_s *lower; int ret; DEBUGASSERT(filep && filep->f_inode); + opriv = filep->f_priv; inode = filep->f_inode; DEBUGASSERT(inode->i_private); priv = (FAR struct djoy_upperhalf_s *)inode->i_private; @@ -532,6 +529,7 @@ static ssize_t djoy_read(FAR struct file *filep, FAR char *buffer, DEBUGASSERT(lower && lower->dl_sample); priv->du_sample = lower->dl_sample(lower); *(FAR djoy_buttonset_t *)buffer = priv->du_sample; + opriv->do_pollpending = false; ret = sizeof(djoy_buttonset_t); djoy_givesem(&priv->du_exclsem); @@ -713,6 +711,17 @@ static int djoy_poll(FAR struct file *filep, FAR struct pollfd *fds, opriv->do_fds[i] = fds; fds->priv = &opriv->do_fds[i]; + + if (opriv->do_pollpending) + { + fds->revents |= (fds->events & POLLIN); + if (fds->revents != 0) + { + iinfo("Report events: %02x\n", fds->revents); + nxsem_post(fds->sem); + } + } + break; } } @@ -765,7 +774,7 @@ errout_with_dusem: * * Input Parameters: * devname - The name of the discrete joystick device to be registers. - * This should be a string of the form "/priv/djoyN" where N is the + * This should be a string of the form "/dev/djoyN" where N is the * minor device number. * lower - An instance of the platform-specific discrete joystick lower * half driver.