You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/08/01 17:29:08 UTC

[incubator-nuttx] 04/22: sensor: add SNIOC_READLAST

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

commit 6f3873dfa2f47b241c79e0500bc55c1a31a96fa4
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Tue Apr 26 14:01:11 2022 +0800

    sensor: add SNIOC_READLAST
    
    If enable SNIOC_READLAST, sensor_read will return 0
    when there is no new data until last read.
    
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 drivers/sensors/sensor.c      | 73 ++++++++++++++++++++++++++-----------------
 include/nuttx/sensors/ioctl.h |  9 ++++++
 2 files changed, 54 insertions(+), 28 deletions(-)

diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index 29add29309..a1ce148cf3 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -95,6 +95,7 @@ struct sensor_upperhalf_s
   struct circbuf_s   buffer;             /* The circular buffer of sensor device */
   sem_t              exclsem;            /* Manages exclusive access to file operations */
   struct list_node   userlist;           /* List of users */
+  bool               readlast;           /* The flag of readlast */
 };
 
 /****************************************************************************
@@ -525,52 +526,61 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
     }
   else
     {
-      /* We must make sure that when the semaphore is equal to 1, there must
-       * be events available in the buffer, so we use a while statement to
-       * synchronize this case that other read operations consume events
-       * that have just entered the buffer.
+      /* If readlast is true, you can always read the last data
+       * in the circbuffer as initial value for new users when the
+       * sensor device has not yet generated new data, otherwise,
+       * it will return 0 when there isn't new data.
        */
 
-      while (circbuf_is_empty(&upper->buffer))
+      if (upper->readlast)
         {
-          if (filep->f_oflags & O_NONBLOCK)
+          if (circbuf_is_empty(&upper->buffer))
             {
-              ret = -EAGAIN;
+              ret = -ENODATA;
               goto out;
             }
-          else
+
+          if (user->generation == upper->state.generation)
             {
-              nxsem_post(&upper->exclsem);
-              ret = nxsem_wait_uninterruptible(&user->buffersem);
-              if (ret < 0)
+              user->generation--;
+            }
+        }
+      else
+        {
+          /* We must make sure that when the semaphore is equal to 1,
+           * there must be events available in the buffer, so we use a
+           * while statement to synchronize this case that other read
+           * operations consume events that have just entered the buffer.
+           */
+
+          while (circbuf_is_empty(&upper->buffer) ||
+                 user->generation == upper->state.generation)
+            {
+              if (filep->f_oflags & O_NONBLOCK)
                 {
-                  return ret;
+                  ret = -EAGAIN;
+                  goto out;
                 }
-
-              ret = nxsem_wait(&upper->exclsem);
-              if (ret < 0)
+              else
                 {
-                  return ret;
+                  nxmutex_unlock(&upper->lock);
+                  ret = nxsem_wait_uninterruptible(&user->buffersem);
+                  if (ret < 0)
+                    {
+                      return ret;
+                    }
+
+                  nxmutex_lock(&upper->lock);
                 }
             }
         }
 
-      /* Always read the last data in the circbuffer as initial value
-       * for new users when the sensor device has not yet generated
-       * new data.
-       */
-
-      if (user->generation == upper->state.generation)
-        {
-          user->generation--;
-        }
-
       /* If user's generation isn't within circbuffer range, the
        * oldest data in circbuffer are returned to the users.
        */
 
-      else if (!sensor_in_range(upper->state.generation - lower->nbuffer,
-                                user->generation, upper->state.generation))
+      if (!sensor_in_range(upper->state.generation - lower->nbuffer,
+                           user->generation, upper->state.generation))
 
         {
           user->generation = upper->state.generation - lower->nbuffer;
@@ -704,6 +714,12 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
         }
         break;
 
+      case SNIOC_READLAST:
+        {
+          upper->readlast = !!arg;
+        }
+        break;
+
       default:
 
         /* Lowerhalf driver process other cmd. */
@@ -969,6 +985,7 @@ int sensor_custom_register(FAR struct sensor_lowerhalf_s *lower,
   /* Initialize the upper-half data structure */
 
   list_initialize(&upper->userlist);
+  upper->readlast = true;
   upper->state.esize = esize;
   upper->state.min_interval = ULONG_MAX;
   upper->state.min_latency = ULONG_MAX;
diff --git a/include/nuttx/sensors/ioctl.h b/include/nuttx/sensors/ioctl.h
index 7cee985204..1e415a98cc 100644
--- a/include/nuttx/sensors/ioctl.h
+++ b/include/nuttx/sensors/ioctl.h
@@ -326,4 +326,13 @@
 #define SNIOC_UNREGISTER           _SNIOC(0x0090)
 #endif
 
+/* Command:      SNIOC_READLAST
+ * Description:  If enable readlast, there is no data update in time,
+ *               the latest data can always be returned.
+ *               Disable readlast, if there is no data update, return 0.
+ * Argument:     True or false
+ */
+
+#define SNIOC_READLAST             _SNIOC(0x0091)
+
 #endif /* __INCLUDE_NUTTX_SENSORS_IOCTL_H */