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:04 UTC

[incubator-nuttx] branch master updated (1cc7f6e63a -> 78381f9fc4)

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

xiaoxiang pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


    from 1cc7f6e63a Add MIT license kconfig symbol
     new c5f87bb5c6 driver/sensor: support access remote sensor by rpmsg
     new 8de6c29aa4 driver/sensor: enable usensor and rpmsg_sensor
     new 2f5727b102 driver/sensor: add _SNIOCVALID check to command
     new 6f3873dfa2 sensor: add SNIOC_READLAST
     new 74b2be20d0 driver/sensor: move readlast for each user
     new 2a910b7ca9 driver/sensor: using re-entrant mutex for sensor access to avoid deadlock
     new fa4cebce32 driver/sensor: support sensor data persist
     new 67f156c2f7 driver/sensor: add cpuname info about failed case
     new bf6063cc04 driver/sensor/rpmsg: fix deadlock case: push event in ioctl_ack handler
     new 38393cfc94 driver/sensor: move register_driver to end to avoid race condition
     new 78eb832e23 driver/sensor: using standard recursive mutex api
     new 8e03f213e3 driver/sensor: convert interval 0 to ULONG_MAX
     new ddd4a0d635 driver/sensor: sync batch and interval when update interval
     new 01254de1bf driver/sensor: update batch initial value
     new 48b4667318 driver/sensor: slove deadlock issue because ept/devlist using same lock
     new 107e3e5d52 driver/sensor: export upper half lock
     new fe1d83c41b driver/sensor: solve the deadlock problem caused by sensor_close
     new 12e5371a05 uorb: fix, should check min_interval modified by lowerhalf.
     new 5b91641a09 driver/sensor: add cmd SNIOC_UPDATED and remove readlast
     new 9485174ff0 nuttx/dirvers/sensor: down-sampling 2.0
     new ad20bd4bb3 driver/sensor: fix rpmsg send failed when buffer is NULL
     new 78381f9fc4 driver/sensor: fix deadlock about sensor_rpmsg

The 22 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 drivers/drivers_initialize.c   |   11 +-
 drivers/sensors/Kconfig        |    7 +
 drivers/sensors/Make.defs      |    4 +
 drivers/sensors/sensor.c       |  533 ++++++++++------
 drivers/sensors/sensor_rpmsg.c | 1377 ++++++++++++++++++++++++++++++++++++++++
 drivers/sensors/usensor.c      |    1 +
 include/nuttx/sensors/ioctl.h  |   15 +
 include/nuttx/sensors/sensor.h |  102 ++-
 8 files changed, 1857 insertions(+), 193 deletions(-)
 create mode 100644 drivers/sensors/sensor_rpmsg.c


[incubator-nuttx] 18/22: uorb: fix, should check min_interval modified by lowerhalf.

Posted by xi...@apache.org.
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 12e5371a05a279ffde9618af205d3c9e0dd5477f
Author: jihandong <ji...@xiaomi.com>
AuthorDate: Sat Jun 25 17:12:39 2022 +0800

    uorb: fix, should check min_interval modified by lowerhalf.
    
    Signed-off-by: jihandong <ji...@xiaomi.com>
---
 drivers/sensors/sensor.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index 4d61eb2c9b..99544231bf 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -250,11 +250,16 @@ static int sensor_update_interval(FAR struct file *filep,
       if (min_interval != ULONG_MAX &&
           min_interval != upper->state.min_interval)
         {
+          unsigned long expected_interval = min_interval;
           ret = lower->ops->set_interval(lower, filep, &min_interval);
           if (ret < 0)
             {
               return ret;
             }
+          else if (min_interval > expected_interval)
+            {
+              return -EINVAL;
+            }
         }
 
       if (min_latency == ULONG_MAX)


[incubator-nuttx] 13/22: driver/sensor: sync batch and interval when update interval

Posted by xi...@apache.org.
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 ddd4a0d63583c4b9027a1140f443e685814e33dc
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Thu Jun 16 14:26:42 2022 +0800

    driver/sensor: sync batch and interval when update interval
    
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 drivers/sensors/sensor.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index e054116a8d..fb22d1c855 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -245,6 +245,11 @@ update:
         {
           return ret;
         }
+
+      if (upper->state.min_latency != ULONG_MAX)
+        {
+          lower->ops->batch(filep, lower, &upper->state.min_latency);
+        }
     }
 
   upper->state.min_interval = min_interval;


[incubator-nuttx] 11/22: driver/sensor: using standard recursive mutex api

Posted by xi...@apache.org.
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 78eb832e23109387e3eb5c45e17f414cf0ec6987
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Tue Jun 14 11:33:13 2022 +0800

    driver/sensor: using standard recursive mutex api
    
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 drivers/sensors/sensor.c | 104 ++++++++++++++++-------------------------------
 1 file changed, 35 insertions(+), 69 deletions(-)

diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index ac487bb39f..41717cb9bb 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -37,6 +37,7 @@
 #include <nuttx/list.h>
 #include <nuttx/kmalloc.h>
 #include <nuttx/mm/circbuf.h>
+#include <nuttx/mutex.h>
 #include <nuttx/sensors/sensor.h>
 
 /****************************************************************************
@@ -94,9 +95,7 @@ struct sensor_upperhalf_s
   FAR struct sensor_lowerhalf_s *lower;  /* The handle of lower half driver */
   struct sensor_state_s          state;  /* The state of sensor device */
   struct circbuf_s   buffer;             /* The circular buffer of sensor device */
-  sem_t              exclsem;            /* Manages exclusive access to file operations */
-  pid_t              semholder;          /* The current holder of the semaphore */
-  int16_t            semcount;           /* Number of counts held */
+  rmutex_t           lock;               /* Manages exclusive access to file operations */
   struct list_node   userlist;           /* List of users */
 };
 
@@ -178,38 +177,6 @@ static const struct file_operations g_sensor_fops =
  * Private Functions
  ****************************************************************************/
 
-static void sensor_semtake(FAR struct sensor_upperhalf_s *upper)
-{
-  pid_t pid = gettid();
-
-  if (pid == upper->semholder)
-    {
-      upper->semcount++;
-    }
-  else
-    {
-      nxsem_wait_uninterruptible(&upper->exclsem);
-      upper->semholder = pid;
-      upper->semcount = 1;
-    }
-}
-
-static void sensor_semgive(FAR struct sensor_upperhalf_s *upper)
-{
-  DEBUGASSERT(upper->semholder == gettid());
-
-  if (upper->semcount > 1)
-    {
-      upper->semcount--;
-    }
-  else
-    {
-      upper->semholder = INVALID_PROCESS_ID;
-      upper->semcount  = 0;
-      nxsem_post(&upper->exclsem);
-    }
-}
-
 static bool sensor_in_range(unsigned long left, unsigned long value,
                             unsigned long right)
 {
@@ -392,7 +359,7 @@ static int sensor_open(FAR struct file *filep)
   FAR struct sensor_user_s *user;
   int ret = 0;
 
-  sensor_semtake(upper);
+  nxrmutex_lock(&upper->lock);
   user = kmm_zalloc(sizeof(struct sensor_user_s));
   if (user == NULL)
     {
@@ -464,7 +431,7 @@ errout_with_open:
 errout_with_user:
   kmm_free(user);
 errout_with_sem:
-  sensor_semgive(upper);
+  nxrmutex_unlock(&upper->lock);
   return ret;
 }
 
@@ -476,13 +443,13 @@ static int sensor_close(FAR struct file *filep)
   FAR struct sensor_user_s *user = filep->f_priv;
   int ret = 0;
 
-  sensor_semtake(upper);
+  nxrmutex_lock(&upper->lock);
   if (lower->ops->close)
     {
       ret = lower->ops->close(lower, filep);
       if (ret < 0)
         {
-          sensor_semgive(upper);
+          nxrmutex_unlock(&upper->lock);
           return ret;
         }
     }
@@ -509,7 +476,7 @@ static int sensor_close(FAR struct file *filep)
   /* The user is closed, notify to other users */
 
   sensor_pollnotify(upper, POLLPRI);
-  sensor_semgive(upper);
+  nxrmutex_unlock(&upper->lock);
 
   kmm_free(user);
   return ret;
@@ -530,19 +497,19 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
       return -EINVAL;
     }
 
-  sensor_semtake(upper);
+  nxrmutex_lock(&upper->lock);
   if (lower->ops->fetch)
     {
       if (!(filep->f_oflags & O_NONBLOCK))
         {
-          sensor_semgive(upper);
+          nxrmutex_unlock(&upper->lock);
           ret = nxsem_wait_uninterruptible(&user->buffersem);
           if (ret < 0)
             {
               return ret;
             }
 
-          sensor_semtake(upper);
+          nxrmutex_lock(&upper->lock);
         }
       else if (!upper->state.nsubscribers)
         {
@@ -604,14 +571,14 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
                 }
               else
                 {
-                  sensor_semgive(upper);
+                  nxrmutex_unlock(&upper->lock);
                   ret = nxsem_wait_uninterruptible(&user->buffersem);
                   if (ret < 0)
                     {
                       return ret;
                     }
 
-                  sensor_semtake(upper);
+                  nxrmutex_lock(&upper->lock);
                 }
             }
         }
@@ -641,7 +608,7 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
     }
 
 out:
-  sensor_semgive(upper);
+  nxrmutex_unlock(&upper->lock);
   return ret;
 }
 
@@ -669,27 +636,27 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
     {
       case SNIOC_GET_STATE:
         {
-          sensor_semtake(upper);
+          nxrmutex_lock(&upper->lock);
           memcpy((FAR void *)(uintptr_t)arg,
                  &upper->state, sizeof(upper->state));
           user->changed = false;
-          sensor_semgive(upper);
+          nxrmutex_unlock(&upper->lock);
         }
         break;
 
       case SNIOC_SET_INTERVAL:
         {
-          sensor_semtake(upper);
+          nxrmutex_lock(&upper->lock);
           ret = sensor_update_interval(filep, upper, user, arg);
-          sensor_semgive(upper);
+          nxrmutex_unlock(&upper->lock);
         }
         break;
 
       case SNIOC_BATCH:
         {
-          sensor_semtake(upper);
+          nxrmutex_lock(&upper->lock);
           ret = sensor_update_latency(filep, upper, user, arg);
-          sensor_semgive(upper);
+          nxrmutex_unlock(&upper->lock);
         }
         break;
 
@@ -731,15 +698,15 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
 
       case SNIOC_SET_USERPRIV:
         {
-          sensor_semtake(upper);
+          nxrmutex_lock(&upper->lock);
           upper->state.priv = (FAR void *)(uintptr_t)arg;
-          sensor_semgive(upper);
+          nxrmutex_unlock(&upper->lock);
         }
         break;
 
       case SNIOC_SET_BUFFER_NUMBER:
         {
-          sensor_semtake(upper);
+          nxrmutex_lock(&upper->lock);
           if (!circbuf_is_init(&upper->buffer))
             {
               if (arg >= lower->nbuffer)
@@ -756,15 +723,15 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
               ret = -EBUSY;
             }
 
-          sensor_semgive(upper);
+          nxrmutex_unlock(&upper->lock);
         }
         break;
 
       case SNIOC_READLAST:
         {
-          sensor_semtake(upper);
+          nxrmutex_lock(&upper->lock);
           user->readlast = !!arg;
-          sensor_semgive(upper);
+          nxrmutex_unlock(&upper->lock);
         }
         break;
 
@@ -798,7 +765,7 @@ static int sensor_poll(FAR struct file *filep,
   int semcount;
   int ret = 0;
 
-  sensor_semtake(upper);
+  nxrmutex_lock(&upper->lock);
   if (setup)
     {
       /* Don't have enough space to store fds */
@@ -850,7 +817,7 @@ static int sensor_poll(FAR struct file *filep,
     }
 
 errout:
-  sensor_semgive(upper);
+  nxrmutex_unlock(&upper->lock);
   return ret;
 }
 
@@ -870,7 +837,7 @@ static ssize_t sensor_push_event(FAR void *priv, FAR const void *data,
       return -EINVAL;
     }
 
-  sensor_semtake(upper);
+  nxrmutex_lock(&upper->lock);
   if (!circbuf_is_init(&upper->buffer))
     {
       /* Initialize sensor buffer when data is first generated */
@@ -879,7 +846,7 @@ static ssize_t sensor_push_event(FAR void *priv, FAR const void *data,
                          upper->state.esize);
       if (ret < 0)
         {
-          sensor_semgive(upper);
+          nxrmutex_unlock(&upper->lock);
           return ret;
         }
     }
@@ -900,7 +867,7 @@ static ssize_t sensor_push_event(FAR void *priv, FAR const void *data,
         }
     }
 
-  sensor_semgive(upper);
+  nxrmutex_unlock(&upper->lock);
   return bytes;
 }
 
@@ -910,7 +877,7 @@ static void sensor_notify_event(FAR void *priv)
   FAR struct sensor_user_s *user;
   int semcount;
 
-  sensor_semtake(upper);
+  nxrmutex_lock(&upper->lock);
   list_for_every_entry(&upper->userlist, user, struct sensor_user_s, node)
     {
       nxsem_get_value(&user->buffersem, &semcount);
@@ -922,7 +889,7 @@ static void sensor_notify_event(FAR void *priv)
       sensor_pollnotify_one(user, POLLIN);
     }
 
-  sensor_semgive(upper);
+  nxrmutex_unlock(&upper->lock);
 }
 
 /****************************************************************************
@@ -1026,8 +993,7 @@ int sensor_custom_register(FAR struct sensor_lowerhalf_s *lower,
       upper->state.nadvertisers = 1;
     }
 
-  upper->semholder = INVALID_PROCESS_ID;
-  nxsem_init(&upper->exclsem, 0, 1);
+  nxrmutex_init(&upper->lock);
 
   /* Bind the lower half data structure member */
 
@@ -1069,7 +1035,7 @@ int sensor_custom_register(FAR struct sensor_lowerhalf_s *lower,
   return ret;
 
 drv_err:
-  nxsem_destroy(&upper->exclsem);
+  nxrmutex_destroy(&upper->lock);
 
   kmm_free(upper);
 
@@ -1132,7 +1098,7 @@ void sensor_custom_unregister(FAR struct sensor_lowerhalf_s *lower,
   sensor_rpmsg_unregister(lower);
 #endif
 
-  nxsem_destroy(&upper->exclsem);
+  nxrmutex_destroy(&upper->lock);
   if (circbuf_is_init(&upper->buffer))
     {
       circbuf_uninit(&upper->buffer);


[incubator-nuttx] 08/22: driver/sensor: add cpuname info about failed case

Posted by xi...@apache.org.
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 67f156c2f73b42ca2e1d657f7519409e8968c816
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Wed May 25 19:46:29 2022 +0800

    driver/sensor: add cpuname info about failed case
    
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 drivers/sensors/sensor_rpmsg.c | 34 ++++++++++++++++++++--------------
 1 file changed, 20 insertions(+), 14 deletions(-)

diff --git a/drivers/sensors/sensor_rpmsg.c b/drivers/sensors/sensor_rpmsg.c
index 58ba632c7d..0111ca38bc 100644
--- a/drivers/sensors/sensor_rpmsg.c
+++ b/drivers/sensors/sensor_rpmsg.c
@@ -297,8 +297,8 @@ static void sensor_rpmsg_advsub_one(FAR struct sensor_rpmsg_dev_s *dev,
   msg = rpmsg_get_tx_payload_buffer(ept, &space, true);
   if (!msg)
     {
-      snerr("ERROR: advsub:%d get buffer failed:%s\n",
-            command, dev->path);
+      snerr("ERROR: advsub:%d get buffer failed:%s, %s\n",
+            command, dev->path, rpmsg_get_cpuname(ept->rdev));
       return;
     }
 
@@ -310,8 +310,8 @@ static void sensor_rpmsg_advsub_one(FAR struct sensor_rpmsg_dev_s *dev,
   ret = rpmsg_send_nocopy(ept, msg, sizeof(*msg) + len);
   if (ret < 0)
     {
-      snerr("ERROR: advsub:%d rpmsg send failed:%s %d\n",
-            command, dev->path, ret);
+      snerr("ERROR: advsub:%d rpmsg send failed:%s, %d, %s\n",
+            command, dev->path, ret, rpmsg_get_cpuname(ept->rdev));
     }
 }
 
@@ -362,7 +362,8 @@ static int sensor_rpmsg_ioctl(FAR struct sensor_rpmsg_dev_s *dev,
       if (!msg)
         {
           ret = -ENOMEM;
-          snerr("ERROR: ioctl get buffer failed:%s\n", dev->path);
+          snerr("ERROR: ioctl get buffer failed:%s, %s\n",
+                dev->path, rpmsg_get_cpuname(proxy->ept->rdev));
           break;
         }
 
@@ -383,7 +384,8 @@ static int sensor_rpmsg_ioctl(FAR struct sensor_rpmsg_dev_s *dev,
       ret = rpmsg_send_nocopy(proxy->ept, msg, sizeof(*msg) + len);
       if (ret < 0)
         {
-          snerr("ERROR: ioctl rpmsg send failed:%s %d\n", dev->path, ret);
+          snerr("ERROR: ioctl rpmsg send failed:%s, %d, %s\n",
+                dev->path, ret, rpmsg_get_cpuname(proxy->ept->rdev));
           break;
         }
 
@@ -397,7 +399,8 @@ static int sensor_rpmsg_ioctl(FAR struct sensor_rpmsg_dev_s *dev,
       nxmutex_lock(&dev->lock);
       if (ret < 0)
         {
-          snerr("ERROR: ioctl rpmsg wait failed:%s %d\n", dev->path, ret);
+          snerr("ERROR: ioctl rpmsg wait failed:%s, %d, %s\n",
+                dev->path, ret, rpmsg_get_cpuname(proxy->ept->rdev));
           break;
         }
 
@@ -786,8 +789,8 @@ static void sensor_rpmsg_push_event_one(FAR struct sensor_rpmsg_dev_s *dev,
       sre->buffer = NULL;
       if (ret < 0)
         {
-          snerr("ERROR: push event rpmsg send failed:%s %d\n",
-                rpmsg_get_cpuname(sre->ept.rdev), ret);
+          snerr("ERROR: push event rpmsg send failed:%d, %s\n",
+                ret, rpmsg_get_cpuname(sre->ept.rdev));
         }
     }
   else
@@ -882,7 +885,8 @@ static int sensor_rpmsg_adv_handler(FAR struct rpmsg_endpoint *ept,
       if (ret < 0)
         {
           sensor_rpmsg_free_proxy(proxy);
-          snerr("ERROR: adv rpmsg send failed:%s %d\n", dev->path, ret);
+          snerr("ERROR: adv rpmsg send failed:%s, %d, %s\n",
+                dev->path, ret, rpmsg_get_cpuname(ept->rdev));
         }
     }
 
@@ -900,7 +904,8 @@ static int sensor_rpmsg_advack_handler(FAR struct rpmsg_endpoint *ept,
   if (dev && !sensor_rpmsg_alloc_stub(dev, ept, msg->cookie))
     {
       sensor_rpmsg_advsub_one(dev, ept, SENSOR_RPMSG_UNADVERTISE);
-      snerr("ERROR: advack failed:%s\n", dev->path);
+      snerr("ERROR: advack failed:%s, %s\n", dev->path,
+            rpmsg_get_cpuname(ept->rdev));
     }
 
   return 0;
@@ -965,7 +970,8 @@ static int sensor_rpmsg_sub_handler(FAR struct rpmsg_endpoint *ept,
       if (ret < 0)
         {
           sensor_rpmsg_free_stub(stub);
-          snerr("ERROR: sub rpmsg send failed:%s %d\n", dev->path, ret);
+          snerr("ERROR: sub rpmsg send failed:%s, %d, %s\n",
+                dev->path, ret, rpmsg_get_cpuname(ept->rdev));
         }
     }
 
@@ -1067,8 +1073,8 @@ static int sensor_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept,
               ret = rpmsg_send(ept, msg, len);
               if (ret < 0)
                 {
-                  snerr("ERROR: ioctl rpmsg send failed:%s %d\n",
-                        dev->path, ret);
+                  snerr("ERROR: ioctl rpmsg send failed:%s, %d, %s\n",
+                        dev->path, ret, rpmsg_get_cpuname(ept->rdev));
                 }
             }
         }


[incubator-nuttx] 17/22: driver/sensor: solve the deadlock problem caused by sensor_close

Posted by xi...@apache.org.
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 fe1d83c41b4ff752ad17c596998cbaa522ba0c96
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Thu Jun 23 12:15:12 2022 +0800

    driver/sensor: solve the deadlock problem caused by sensor_close
    
    note: replace dev lock by upper driver lock
    
    rptun:
    sem_wait
    sched/semaphore/sem_wait.c:273
    nxmutex_lock
    /home/neo/projects/monkey/nuttx/include/nuttx/mutex.h:161
    sensor_close (wait upper driver lock)
    drivers/sensors/sensor.c:509
    sensor_rpmsg_free_stub (get dev lock)
    drivers/sensors/sensor_rpmsg.c:546
    sensor_rpmsg_unsub_handler
    drivers/sensors/sensor_rpmsg.c:1025
    rptun_thread
    
    apps:
    sem_wait
    sched/semaphore/sem_wait.c:273
    sensor_rpmsg_close (wait dev lock)
    drivers/sensors/sensor_rpmsg.c:613
    sensor_close (get upper driver lock)
    drivers/sensors/sensor.c:512
    
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 drivers/sensors/sensor_rpmsg.c | 77 +++++++++++++++++++++++++-----------------
 1 file changed, 46 insertions(+), 31 deletions(-)

diff --git a/drivers/sensors/sensor_rpmsg.c b/drivers/sensors/sensor_rpmsg.c
index 074da1737f..8aa9f263d2 100644
--- a/drivers/sensors/sensor_rpmsg.c
+++ b/drivers/sensors/sensor_rpmsg.c
@@ -82,7 +82,6 @@ struct sensor_rpmsg_dev_s
 {
   struct sensor_lowerhalf_s      lower;
   FAR struct sensor_lowerhalf_s *drv;
-  rmutex_t                       lock;
   struct list_node               node;
   struct list_node               stublist;
   struct list_node               proxylist;
@@ -286,6 +285,16 @@ static mutex_t g_dev_lock = NXMUTEX_INITIALIZER;
  * Private Functions
  ****************************************************************************/
 
+static void sensor_rpmsg_lock(FAR struct sensor_rpmsg_dev_s *dev)
+{
+  dev->lower.sensor_lock(dev->upper);
+}
+
+static void sensor_rpmsg_unlock(FAR struct sensor_rpmsg_dev_s *dev)
+{
+  dev->lower.sensor_unlock(dev->upper);
+}
+
 static void sensor_rpmsg_advsub_one(FAR struct sensor_rpmsg_dev_s *dev,
                                     FAR struct rpmsg_endpoint *ept,
                                     int command)
@@ -355,7 +364,7 @@ static int sensor_rpmsg_ioctl(FAR struct sensor_rpmsg_dev_s *dev,
    * if device doesn't have proxy, it must return -ENOTTY.
    */
 
-  nxrmutex_lock(&dev->lock);
+  sensor_rpmsg_lock(dev);
   list_for_every_entry(&dev->proxylist, proxy,
                        struct sensor_rpmsg_proxy_s, node)
     {
@@ -395,9 +404,9 @@ static int sensor_rpmsg_ioctl(FAR struct sensor_rpmsg_dev_s *dev,
           continue;
         }
 
-      nxrmutex_unlock(&dev->lock);
+      sensor_rpmsg_unlock(dev);
       ret = rpmsg_wait(proxy->ept, &cookie.sem);
-      nxrmutex_lock(&dev->lock);
+      sensor_rpmsg_lock(dev);
       if (ret < 0)
         {
           snerr("ERROR: ioctl rpmsg wait failed:%s, %d, %s\n",
@@ -412,7 +421,7 @@ static int sensor_rpmsg_ioctl(FAR struct sensor_rpmsg_dev_s *dev,
         }
     }
 
-  nxrmutex_unlock(&dev->lock);
+  sensor_rpmsg_unlock(dev);
   if (wait)
     {
       nxsem_destroy(&cookie.sem);
@@ -431,15 +440,19 @@ sensor_rpmsg_alloc_proxy(FAR struct sensor_rpmsg_dev_s *dev,
   struct file file;
   int ret;
 
+  sensor_rpmsg_lock(dev);
   list_for_every_entry(&dev->proxylist, proxy,
                        struct sensor_rpmsg_proxy_s, node)
     {
       if (proxy->ept == ept && proxy->cookie == msg->cookie)
         {
+          sensor_rpmsg_unlock(dev);
           return proxy;
         }
     }
 
+  sensor_rpmsg_unlock(dev);
+
   /* Create new proxy to represent a remote advertiser */
 
   proxy = kmm_malloc(sizeof(*proxy));
@@ -461,7 +474,7 @@ sensor_rpmsg_alloc_proxy(FAR struct sensor_rpmsg_dev_s *dev,
   file_ioctl(&file, SNIOC_GET_STATE, &state);
   file_close(&file);
 
-  nxrmutex_lock(&dev->lock);
+  sensor_rpmsg_lock(dev);
   if (msg->persist)
     {
       dev->drv->persist = true;
@@ -469,7 +482,7 @@ sensor_rpmsg_alloc_proxy(FAR struct sensor_rpmsg_dev_s *dev,
     }
 
   list_add_tail(&dev->proxylist, &proxy->node);
-  nxrmutex_unlock(&dev->lock);
+  sensor_rpmsg_unlock(dev);
 
   /* sync interval and latency */
 
@@ -495,15 +508,19 @@ sensor_rpmsg_alloc_stub(FAR struct sensor_rpmsg_dev_s *dev,
   FAR struct sensor_rpmsg_stub_s *stub;
   int ret;
 
+  sensor_rpmsg_lock(dev);
   list_for_every_entry(&dev->stublist, stub,
                        struct sensor_rpmsg_stub_s, node)
     {
       if (stub->ept == ept && stub->cookie == cookie)
         {
+          sensor_rpmsg_unlock(dev);
           return stub;
         }
     }
 
+  sensor_rpmsg_unlock(dev);
+
   /* Create new stub to represent a remote subscribers */
 
   stub = kmm_malloc(sizeof(*stub));
@@ -523,9 +540,9 @@ sensor_rpmsg_alloc_stub(FAR struct sensor_rpmsg_dev_s *dev,
     }
 
   file_ioctl(&stub->file, SNIOC_READLAST, false);
-  nxrmutex_lock(&dev->lock);
+  sensor_rpmsg_lock(dev);
   list_add_tail(&dev->stublist, &stub->node);
-  nxrmutex_unlock(&dev->lock);
+  sensor_rpmsg_unlock(dev);
 
   if (dev->lower.persist)
     {
@@ -569,7 +586,7 @@ static int sensor_rpmsg_open(FAR struct file *filep,
       return 0;
     }
 
-  nxrmutex_lock(&dev->lock);
+  sensor_rpmsg_lock(dev);
   if (filep->f_oflags & O_WROK)
     {
       if (dev->nadvertisers++ == 0)
@@ -586,7 +603,7 @@ static int sensor_rpmsg_open(FAR struct file *filep,
         }
     }
 
-  nxrmutex_unlock(&dev->lock);
+  sensor_rpmsg_unlock(dev);
   return 0;
 }
 
@@ -611,7 +628,7 @@ static int sensor_rpmsg_close(FAR struct file *filep,
       return ret;
     }
 
-  nxrmutex_lock(&dev->lock);
+  sensor_rpmsg_lock(dev);
   if (filep->f_oflags & O_WROK)
     {
       if (dev->nadvertisers == 1)
@@ -642,7 +659,7 @@ static int sensor_rpmsg_close(FAR struct file *filep,
       dev->nsubscribers--;
     }
 
-  nxrmutex_unlock(&dev->lock);
+  sensor_rpmsg_unlock(dev);
   return ret;
 }
 
@@ -828,14 +845,14 @@ static ssize_t sensor_rpmsg_push_event(FAR void *priv, FAR const void *data,
    * is successful, and must return length of written.
    */
 
-  nxrmutex_lock(&dev->lock);
+  sensor_rpmsg_lock(dev);
   list_for_every_entry(&dev->stublist, stub,
                        struct sensor_rpmsg_stub_s, node)
     {
       sensor_rpmsg_push_event_one(dev, stub);
     }
 
-  nxrmutex_unlock(&dev->lock);
+  sensor_rpmsg_unlock(dev);
   return ret;
 }
 
@@ -885,9 +902,9 @@ static int sensor_rpmsg_adv_handler(FAR struct rpmsg_endpoint *ept,
       ret = rpmsg_send(ept, msg, len);
       if (ret < 0)
         {
-          nxrmutex_lock(&dev->lock);
+          sensor_rpmsg_lock(dev);
           sensor_rpmsg_free_proxy(proxy);
-          nxrmutex_unlock(&dev->lock);
+          sensor_rpmsg_unlock(dev);
           snerr("ERROR: adv rpmsg send failed:%s, %d, %s\n",
                 dev->path, ret, rpmsg_get_cpuname(ept->rdev));
         }
@@ -928,7 +945,7 @@ static int sensor_rpmsg_unadv_handler(FAR struct rpmsg_endpoint *ept,
       return 0;
     }
 
-  nxrmutex_lock(&dev->lock);
+  sensor_rpmsg_lock(dev);
   list_for_every_entry(&dev->proxylist, proxy,
                        struct sensor_rpmsg_proxy_s, node)
     {
@@ -939,7 +956,7 @@ static int sensor_rpmsg_unadv_handler(FAR struct rpmsg_endpoint *ept,
         }
     }
 
-  nxrmutex_unlock(&dev->lock);
+  sensor_rpmsg_unlock(dev);
   return 0;
 }
 
@@ -972,9 +989,9 @@ static int sensor_rpmsg_sub_handler(FAR struct rpmsg_endpoint *ept,
       ret = rpmsg_send(ept, msg, len);
       if (ret < 0)
         {
-          nxrmutex_lock(&dev->lock);
+          sensor_rpmsg_lock(dev);
           sensor_rpmsg_free_stub(stub);
-          nxrmutex_unlock(&dev->lock);
+          sensor_rpmsg_unlock(dev);
           snerr("ERROR: sub rpmsg send failed:%s, %d, %s\n",
                 dev->path, ret, rpmsg_get_cpuname(ept->rdev));
         }
@@ -1015,7 +1032,7 @@ static int sensor_rpmsg_unsub_handler(FAR struct rpmsg_endpoint *ept,
       return 0;
     }
 
-  nxrmutex_lock(&dev->lock);
+  sensor_rpmsg_lock(dev);
   list_for_every_entry(&dev->stublist, stub,
                        struct sensor_rpmsg_stub_s, node)
     {
@@ -1026,7 +1043,7 @@ static int sensor_rpmsg_unsub_handler(FAR struct rpmsg_endpoint *ept,
         }
     }
 
-  nxrmutex_unlock(&dev->lock);
+  sensor_rpmsg_unlock(dev);
   return 0;
 }
 
@@ -1065,7 +1082,7 @@ static int sensor_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept,
   arg = msg->arglen > 0 ? (unsigned long)(uintptr_t)msg->argbuf :
                           msg->arg;
   dev = (FAR struct sensor_rpmsg_dev_s *)(uintptr_t)msg->proxy;
-  nxrmutex_lock(&dev->lock);
+  sensor_rpmsg_lock(dev);
   list_for_every_entry(&dev->stublist, stub,
                        struct sensor_rpmsg_stub_s, node)
     {
@@ -1087,7 +1104,7 @@ static int sensor_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept,
         }
     }
 
-  nxrmutex_unlock(&dev->lock);
+  sensor_rpmsg_unlock(dev);
   return 0;
 }
 
@@ -1142,7 +1159,7 @@ static void sensor_rpmsg_ns_unbind_cb(FAR struct rpmsg_endpoint *ept)
   list_for_every_entry(&g_devlist, dev,
                        struct sensor_rpmsg_dev_s, node)
     {
-      nxrmutex_lock(&dev->lock);
+      sensor_rpmsg_lock(dev);
       list_for_every_entry(&dev->proxylist, proxy,
                            struct sensor_rpmsg_proxy_s, node)
         {
@@ -1163,7 +1180,7 @@ static void sensor_rpmsg_ns_unbind_cb(FAR struct rpmsg_endpoint *ept)
             }
         }
 
-      nxrmutex_unlock(&dev->lock);
+      sensor_rpmsg_unlock(dev);
     }
 
   nxmutex_unlock(&g_dev_lock);
@@ -1194,7 +1211,7 @@ static void sensor_rpmsg_device_ns_bound(FAR struct rpmsg_endpoint *ept)
   list_for_every_entry(&g_devlist, dev,
                        struct sensor_rpmsg_dev_s, node)
     {
-      nxrmutex_lock(&dev->lock);
+      sensor_rpmsg_lock(dev);
       if (dev->nadvertisers > 0)
         {
           sensor_rpmsg_advsub_one(dev, ept, SENSOR_RPMSG_ADVERTISE);
@@ -1205,7 +1222,7 @@ static void sensor_rpmsg_device_ns_bound(FAR struct rpmsg_endpoint *ept)
           sensor_rpmsg_advsub_one(dev, ept, SENSOR_RPMSG_SUBSCRIBE);
         }
 
-      nxrmutex_unlock(&dev->lock);
+      sensor_rpmsg_unlock(dev);
     }
 
   nxmutex_unlock(&g_dev_lock);
@@ -1277,7 +1294,6 @@ sensor_rpmsg_register(FAR struct sensor_lowerhalf_s *lower,
 
   list_initialize(&dev->stublist);
   list_initialize(&dev->proxylist);
-  nxrmutex_init(&dev->lock);
   strcpy(dev->path, path);
 
   dev->nadvertisers   = !!lower->ops->activate;
@@ -1333,7 +1349,6 @@ void sensor_rpmsg_unregister(FAR struct sensor_lowerhalf_s *lower)
   list_delete(&dev->node);
   nxmutex_unlock(&g_dev_lock);
 
-  nxrmutex_destroy(&dev->lock);
   kmm_free(dev);
 }
 


[incubator-nuttx] 15/22: driver/sensor: slove deadlock issue because ept/devlist using same lock

Posted by xi...@apache.org.
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 48b46673186b2c1261182dbe52786d617be68e43
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Wed Jun 22 21:37:14 2022 +0800

    driver/sensor: slove deadlock issue because ept/devlist using same lock
    
    CHAMPION-6418
    rptun sensor:
    [ap] [ 5] [<0x2c352c68>] arm_switchcontext+0xc/0x10
    [ap] [ 5] [<0x2c322eae>] sem_wait+0x5a/0xbc
    [ap] [ 5] [<0x2c3376cc>] sensor_rpmsg_find_dev+0x8/0x78 (wait g_lock)
    [ap] [ 5] [<0x2c338d96>] sensor_rpmsg_suback_handler+0xa/0x4c
    [ap] [ 5] [<0x2c7630f6>] rpmsg_virtio_rx_callback+0xba/0x1b4
    [ap] [ 5] [<0x2c762788>] rproc_virtio_notified+0x44/0x5c
    [ap] [ 5] [<0x2c762154>] remoteproc_get_notification+0x1c/0x2c
    [ap] [ 5] [<0x2c335576>] rptun_thread+0x6e/0x164
    [ap] [ 5] [<0x2c324aba>] nxtask_start+0x3a/0x60
    
    apps:(note: ipc buffer is busy, it's not enough for dual core.)
    [ap] [26] [<0x2c323a5e>] nxsig_timedwait+0x8a/0x184
    [ap] [26] [<0x2c324344>] nxsig_nanosleep+0x34/0xa4
    [ap] [26] [<0x2c324446>] nxsig_usleep+0x26/0x38
    [ap] [26] [<0x2c76338e>] rpmsg_virtio_get_tx_payload_buffer+0x5e/0x100 (wait ipc buffer)
    [ap] [26] [<0x2c33775a>] sensor_rpmsg_advsub_one+0x1e/0xdc (get g_lock)
    [ap] [26] [<0x2c338312>] sensor_rpmsg_open+0xee/0x178
    [ap] [26] [<0x2c3365bc>] sensor_open+0x50/0x234
    [ap] [26] [<0x2c749cb8>] open+0xc8/0x194
    [ap] [26] [<0x2c375324>] orb_subscribe_multi+0x1c/0x94
    
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 drivers/sensors/sensor_rpmsg.c | 61 ++++++++++++++++++++++++++----------------
 1 file changed, 38 insertions(+), 23 deletions(-)

diff --git a/drivers/sensors/sensor_rpmsg.c b/drivers/sensors/sensor_rpmsg.c
index 8338a592a9..074da1737f 100644
--- a/drivers/sensors/sensor_rpmsg.c
+++ b/drivers/sensors/sensor_rpmsg.c
@@ -279,7 +279,8 @@ static const rpmsg_ept_cb g_sensor_rpmsg_handler[] =
 
 static struct list_node g_devlist = LIST_INITIAL_VALUE(g_devlist);
 static struct list_node g_eptlist = LIST_INITIAL_VALUE(g_eptlist);
-static mutex_t g_lock = MUTEX_INITIALIZER;
+static mutex_t g_ept_lock = NXMUTEX_INITIALIZER;
+static mutex_t g_dev_lock = NXMUTEX_INITIALIZER;
 
 /****************************************************************************
  * Private Functions
@@ -322,14 +323,14 @@ static void sensor_rpmsg_advsub(FAR struct sensor_rpmsg_dev_s *dev,
 
   /* Broadcast advertise/subscribe message to all ready ept */
 
-  nxmutex_lock(&g_lock);
+  nxmutex_lock(&g_ept_lock);
   list_for_every_entry(&g_eptlist, sre, struct sensor_rpmsg_ept_s,
                        node)
     {
       sensor_rpmsg_advsub_one(dev, &sre->ept, command);
     }
 
-  nxmutex_unlock(&g_lock);
+  nxmutex_unlock(&g_ept_lock);
 }
 
 static int sensor_rpmsg_ioctl(FAR struct sensor_rpmsg_dev_s *dev,
@@ -843,17 +844,17 @@ sensor_rpmsg_find_dev(FAR const char *path)
 {
   FAR struct sensor_rpmsg_dev_s *dev;
 
-  nxmutex_lock(&g_lock);
+  nxmutex_lock(&g_dev_lock);
   list_for_every_entry(&g_devlist, dev, struct sensor_rpmsg_dev_s, node)
     {
       if (strcmp(dev->path, path) == 0)
         {
-          nxmutex_unlock(&g_lock);
+          nxmutex_unlock(&g_dev_lock);
           return dev;
         }
     }
 
-  nxmutex_unlock(&g_lock);
+  nxmutex_unlock(&g_dev_lock);
   return NULL;
 }
 
@@ -884,7 +885,9 @@ static int sensor_rpmsg_adv_handler(FAR struct rpmsg_endpoint *ept,
       ret = rpmsg_send(ept, msg, len);
       if (ret < 0)
         {
+          nxrmutex_lock(&dev->lock);
           sensor_rpmsg_free_proxy(proxy);
+          nxrmutex_unlock(&dev->lock);
           snerr("ERROR: adv rpmsg send failed:%s, %d, %s\n",
                 dev->path, ret, rpmsg_get_cpuname(ept->rdev));
         }
@@ -969,7 +972,9 @@ static int sensor_rpmsg_sub_handler(FAR struct rpmsg_endpoint *ept,
       ret = rpmsg_send(ept, msg, len);
       if (ret < 0)
         {
+          nxrmutex_lock(&dev->lock);
           sensor_rpmsg_free_stub(stub);
+          nxrmutex_unlock(&dev->lock);
           snerr("ERROR: sub rpmsg send failed:%s, %d, %s\n",
                 dev->path, ret, rpmsg_get_cpuname(ept->rdev));
         }
@@ -1077,6 +1082,8 @@ static int sensor_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept,
                         dev->path, ret, rpmsg_get_cpuname(ept->rdev));
                 }
             }
+
+          break;
         }
     }
 
@@ -1123,9 +1130,7 @@ static void sensor_rpmsg_ns_unbind_cb(FAR struct rpmsg_endpoint *ept)
   FAR struct sensor_rpmsg_ept_s *sre;
   FAR struct sensor_rpmsg_dev_s *dev;
   FAR struct sensor_rpmsg_stub_s *stub;
-  FAR struct sensor_rpmsg_stub_s *stmp;
   FAR struct sensor_rpmsg_proxy_s *proxy;
-  FAR struct sensor_rpmsg_proxy_s *ptmp;
 
   sre = container_of(ept, struct sensor_rpmsg_ept_s, ept);
 
@@ -1133,37 +1138,43 @@ static void sensor_rpmsg_ns_unbind_cb(FAR struct rpmsg_endpoint *ept)
    * destoryed.
    */
 
-  nxmutex_lock(&g_lock);
+  nxmutex_lock(&g_dev_lock);
   list_for_every_entry(&g_devlist, dev,
                        struct sensor_rpmsg_dev_s, node)
     {
       nxrmutex_lock(&dev->lock);
-      list_for_every_entry_safe(&dev->proxylist, proxy, ptmp,
-                                struct sensor_rpmsg_proxy_s, node)
+      list_for_every_entry(&dev->proxylist, proxy,
+                           struct sensor_rpmsg_proxy_s, node)
         {
           if (proxy->ept == ept)
             {
               sensor_rpmsg_free_proxy(proxy);
+              break;
             }
         }
 
-      list_for_every_entry_safe(&dev->stublist, stub, stmp,
-                                struct sensor_rpmsg_stub_s, node)
+      list_for_every_entry(&dev->stublist, stub,
+                           struct sensor_rpmsg_stub_s, node)
         {
           if (stub->ept == ept)
             {
               sensor_rpmsg_free_stub(stub);
+              break;
             }
         }
 
       nxrmutex_unlock(&dev->lock);
     }
 
+  nxmutex_unlock(&g_dev_lock);
+
+  nxmutex_lock(&g_ept_lock);
   list_delete(&sre->node);
-  nxmutex_unlock(&g_lock);
-  rpmsg_destroy_ept(ept);
+  nxmutex_unlock(&g_ept_lock);
+
   nxmutex_destroy(&sre->lock);
   kmm_free(sre);
+  rpmsg_destroy_ept(ept);
 }
 
 static void sensor_rpmsg_device_ns_bound(FAR struct rpmsg_endpoint *ept)
@@ -1173,11 +1184,13 @@ static void sensor_rpmsg_device_ns_bound(FAR struct rpmsg_endpoint *ept)
 
   sre = container_of(ept, struct sensor_rpmsg_ept_s, ept);
 
-  nxmutex_lock(&g_lock);
+  nxmutex_lock(&g_ept_lock);
   list_add_tail(&g_eptlist, &sre->node);
+  nxmutex_unlock(&g_ept_lock);
 
   /* Broadcast all device to ready ept */
 
+  nxmutex_lock(&g_dev_lock);
   list_for_every_entry(&g_devlist, dev,
                        struct sensor_rpmsg_dev_s, node)
     {
@@ -1195,7 +1208,7 @@ static void sensor_rpmsg_device_ns_bound(FAR struct rpmsg_endpoint *ept)
       nxrmutex_unlock(&dev->lock);
     }
 
-  nxmutex_unlock(&g_lock);
+  nxmutex_unlock(&g_dev_lock);
 }
 
 static void sensor_rpmsg_device_created(FAR struct rpmsg_device *rdev,
@@ -1267,6 +1280,7 @@ sensor_rpmsg_register(FAR struct sensor_lowerhalf_s *lower,
   nxrmutex_init(&dev->lock);
   strcpy(dev->path, path);
 
+  dev->nadvertisers   = !!lower->ops->activate;
   dev->push_event     = lower->push_event;
   dev->upper          = lower->priv;
   lower->push_event   = sensor_rpmsg_push_event;
@@ -1277,19 +1291,20 @@ sensor_rpmsg_register(FAR struct sensor_lowerhalf_s *lower,
 
   /* If openamp is ready, send advertisement to remote proc */
 
-  nxmutex_lock(&g_lock);
+  nxmutex_lock(&g_dev_lock);
   list_add_tail(&g_devlist, &dev->node);
+  nxmutex_unlock(&g_dev_lock);
   if (lower->ops->activate)
     {
-      dev->nadvertisers = 1;
+      nxmutex_lock(&g_ept_lock);
       list_for_every_entry(&g_eptlist, sre, struct sensor_rpmsg_ept_s,
                            node)
         {
           sensor_rpmsg_advsub_one(dev, &sre->ept, SENSOR_RPMSG_ADVERTISE);
         }
-    }
 
-  nxmutex_unlock(&g_lock);
+      nxmutex_unlock(&g_ept_lock);
+    }
 
   return &dev->lower;
 }
@@ -1314,9 +1329,9 @@ void sensor_rpmsg_unregister(FAR struct sensor_lowerhalf_s *lower)
       return;
     }
 
-  nxmutex_lock(&g_lock);
+  nxmutex_lock(&g_dev_lock);
   list_delete(&dev->node);
-  nxmutex_unlock(&g_lock);
+  nxmutex_unlock(&g_dev_lock);
 
   nxrmutex_destroy(&dev->lock);
   kmm_free(dev);


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

Posted by xi...@apache.org.
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 */


[incubator-nuttx] 05/22: driver/sensor: move readlast for each user

Posted by xi...@apache.org.
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 74b2be20d061d520ff2073d3002b2ad7936a060a
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Tue May 10 22:15:54 2022 +0800

    driver/sensor: move readlast for each user
    
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 drivers/sensors/sensor.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index a1ce148cf3..1bcb977393 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -84,6 +84,7 @@ struct sensor_user_s
   unsigned long    generation; /* Last generation subscriber has seen */
   unsigned long    interval;   /* The interval for subscriber */
   unsigned long    latency;    /* The bactch latency for subscriber */
+  bool             readlast;   /* The flag of readlast */
 };
 
 /* This structure describes the state of the upper half driver */
@@ -95,7 +96,6 @@ 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 */
 };
 
 /****************************************************************************
@@ -402,6 +402,7 @@ static int sensor_open(FAR struct file *filep)
   user->interval   = ULONG_MAX;
   user->latency    = ULONG_MAX;
   user->generation = upper->state.generation;
+  user->readlast   = true;
   nxsem_init(&user->buffersem, 0, 0);
   nxsem_set_protocol(&user->buffersem, SEM_PRIO_NONE);
   list_add_tail(&upper->userlist, &user->node);
@@ -532,7 +533,7 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
        * it will return 0 when there isn't new data.
        */
 
-      if (upper->readlast)
+      if (user->readlast)
         {
           if (circbuf_is_empty(&upper->buffer))
             {
@@ -716,7 +717,9 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
 
       case SNIOC_READLAST:
         {
-          upper->readlast = !!arg;
+          sensor_semtake(upper);
+          user->readlast = !!arg;
+          sensor_semgive(upper);
         }
         break;
 
@@ -985,7 +988,6 @@ 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;


[incubator-nuttx] 20/22: nuttx/dirvers/sensor: down-sampling 2.0

Posted by xi...@apache.org.
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 9485174ff08edd2d57bed2209e8306ac57d71a5a
Author: jihandong <ji...@xiaomi.com>
AuthorDate: Wed May 11 13:49:39 2022 +0800

    nuttx/dirvers/sensor: down-sampling 2.0
    
    1. about interval:
      If interval is not set, generation is increased by 1 along with
      publish and copy, multi-copy is continuous.
    
      If interval is set, pick proper samples from buffer based on
      mainline/user generation, multi-copy is one-by-one.
    
    2. about bufferpos:
      user->bufferpos always point to next position to check.
    
           data user last read
      ----------v--------------------------
      |        |        |        |
      -------------------^-----------------
                     bufferpos
    
      If buffer is full, bufferpos point to buffer.head
    
    Examples:
      If a buffer contains 4 samples, newest generatoin is 40.
    
      -------------------------------------
      |10      |20      |30      |40
      ------------------------------^------
                                    |
       if user's next generation is 42, notify user to copy No.40 sample,
                    because 42 is closer to 40 than 50.
    
      -------------------------------------
      |10      |20      |30      |40
      ----------------------------------^--
                                        |
       if user's next generation is 48, do not notify user,
             because 48 is closer to 50, which is next mainline sample.
    
    Signed-off-by: jihandong <ji...@xiaomi.com>
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 drivers/sensors/sensor.c | 268 +++++++++++++++++++++++++++++++++--------------
 1 file changed, 192 insertions(+), 76 deletions(-)

diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index 50e9d33cc8..cd8b06eccc 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -46,9 +46,10 @@
 
 /* Device naming ************************************************************/
 
-#define ROUNDUP(x, esize)  ((x + (esize - 1)) / (esize)) * (esize)
-#define DEVNAME_FMT        "/dev/sensor/sensor_%s%s%d"
-#define DEVNAME_UNCAL      "_uncal"
+#define ROUND_DOWN(x, y)    (((x) / (y)) * (y))
+#define DEVNAME_FMT         "/dev/sensor/sensor_%s%s%d"
+#define DEVNAME_UNCAL       "_uncal"
+#define TIMING_BUF_ESIZE    (sizeof(unsigned long))
 
 /****************************************************************************
  * Private Types
@@ -76,6 +77,7 @@ struct sensor_user_s
                                 * asynchronous notify other users
                                 */
   sem_t            buffersem;  /* Wakeup user waiting for data in circular buffer */
+  size_t           bufferpos;  /* The index of user generation in buffer */
 
   /* The subscriber info
    * Support multi advertisers to subscribe their own data when they
@@ -93,7 +95,8 @@ struct sensor_upperhalf_s
 {
   FAR struct sensor_lowerhalf_s *lower;  /* The handle of lower half driver */
   struct sensor_state_s          state;  /* The state of sensor device */
-  struct circbuf_s   buffer;             /* The circular buffer of sensor device */
+  struct circbuf_s   timing;             /* The circular buffer of generation */
+  struct circbuf_s   buffer;             /* The circular buffer of data */
   rmutex_t           lock;               /* Manages exclusive access to file operations */
   struct list_node   userlist;           /* List of users */
 };
@@ -188,27 +191,6 @@ static void sensor_unlock(FAR void *priv)
   nxrmutex_unlock(&upper->lock);
 }
 
-static bool sensor_in_range(unsigned long left, unsigned long value,
-                            unsigned long right)
-{
-  if (left < right)
-    {
-      return left <= value && value < right;
-    }
-  else
-    {
-      /* Maybe the data overflowed and a wraparound occurred */
-
-      return left <= value || value < right;
-    }
-}
-
-static bool sensor_is_updated(unsigned long generation,
-                              unsigned long ugeneration)
-{
-  return generation > ugeneration;
-}
-
 static int sensor_update_interval(FAR struct file *filep,
                                   FAR struct sensor_upperhalf_s *upper,
                                   FAR struct sensor_user_s *user,
@@ -350,6 +332,159 @@ update:
   return ret;
 }
 
+static void sensor_generate_timing(FAR struct sensor_upperhalf_s *upper,
+                                   unsigned long nums)
+{
+  unsigned long interval = upper->state.min_interval != ULONG_MAX ?
+                           upper->state.min_interval : 1;
+  while (nums-- > 0)
+    {
+      upper->state.generation += interval;
+      circbuf_overwrite(&upper->timing, &upper->state.generation,
+                        TIMING_BUF_ESIZE);
+    }
+}
+
+static bool sensor_is_updated(FAR struct sensor_upperhalf_s *upper,
+                              FAR struct sensor_user_s *user)
+{
+  long delta = upper->state.generation - user->generation;
+
+  if (delta <= 0)
+    {
+      return false;
+    }
+  else if (user->interval == ULONG_MAX)
+    {
+      return true;
+    }
+  else
+    {
+      /* Check whether next generation user want in buffer.
+       * generation     next generation(not published yet)
+       * ____v_____________v
+       * ////|//////^      |
+       *         ^ middle point
+       *   next generation user want
+       */
+
+      return delta >= user->interval - (upper->state.min_interval >> 1);
+    }
+}
+
+static void sensor_catch_up(FAR struct sensor_upperhalf_s *upper,
+                            FAR struct sensor_user_s *user)
+{
+  unsigned long generation;
+  long delta;
+
+  circbuf_peek(&upper->timing, &generation, TIMING_BUF_ESIZE);
+  delta = generation - user->generation;
+  if (delta > 0)
+    {
+      user->bufferpos = upper->timing.tail / TIMING_BUF_ESIZE;
+      if (user->interval == ULONG_MAX)
+        {
+          user->generation = generation - 1;
+        }
+      else
+        {
+          delta -= upper->state.min_interval >> 1;
+          user->generation += ROUND_DOWN(delta, user->interval);
+        }
+    }
+}
+
+static ssize_t sensor_do_samples(FAR struct sensor_upperhalf_s *upper,
+                                 FAR struct sensor_user_s *user,
+                                 FAR char *buffer, size_t len)
+{
+  unsigned long generation;
+  ssize_t ret = 0;
+  size_t nums;
+  size_t pos;
+  size_t end;
+
+  sensor_catch_up(upper, user);
+  nums = upper->timing.head / TIMING_BUF_ESIZE - user->bufferpos;
+  if (len < nums * upper->state.esize)
+    {
+      nums = len / upper->state.esize;
+    }
+
+  len = nums * upper->state.esize;
+
+  /* Take samples continuously */
+
+  if (user->interval == ULONG_MAX)
+    {
+      ret = circbuf_peekat(&upper->buffer,
+                           user->bufferpos * upper->state.esize,
+                           buffer, len);
+      user->bufferpos += nums;
+      circbuf_peekat(&upper->timing,
+                     (user->bufferpos - 1) * TIMING_BUF_ESIZE,
+                     &user->generation, TIMING_BUF_ESIZE);
+      return ret;
+    }
+
+  /* Take samples one-bye-one, to determine whether a sample needed:
+   *
+   * If user's next generation is on the left side of middle point,
+   * we should copy this sample for user.
+   *                      next_generation(or end)
+   *                ________________v____
+   * timing buffer: //|//////.      |
+   *                  ^   middle
+   *              generation
+   *                        next sample(or end)
+   *                ________________v____
+   *  data  buffer:   |             |
+   *                  ^
+   *                sample
+   */
+
+  pos = user->bufferpos;
+  end = upper->timing.head / TIMING_BUF_ESIZE;
+  circbuf_peekat(&upper->timing, pos * TIMING_BUF_ESIZE,
+                 &generation, TIMING_BUF_ESIZE);
+  while (pos++ != end)
+    {
+      unsigned long next_generation;
+      long delta;
+
+      if (pos * TIMING_BUF_ESIZE == upper->timing.head)
+        {
+          next_generation = upper->state.generation +
+                            upper->state.min_interval;
+        }
+      else
+        {
+          circbuf_peekat(&upper->timing, pos * TIMING_BUF_ESIZE,
+                         &next_generation, TIMING_BUF_ESIZE);
+        }
+
+      delta = next_generation + generation -
+              ((user->generation + user->interval) << 1);
+      if (delta >= 0)
+        {
+          ret += circbuf_peekat(&upper->buffer,
+                                (pos - 1) * upper->state.esize,
+                                buffer + ret, upper->state.esize);
+          user->bufferpos = pos;
+          user->generation += user->interval;
+          if (ret >= len)
+            {
+              break;
+            }
+        }
+
+      generation = next_generation;
+    }
+
+  return ret;
+}
+
 static void sensor_pollnotify_one(FAR struct sensor_user_s *user,
                                   pollevent_t eventset)
 {
@@ -439,10 +574,12 @@ static int sensor_open(FAR struct file *filep)
   if (upper->state.generation && lower->persist)
     {
       user->generation = upper->state.generation - 1;
+      user->bufferpos  = upper->timing.head / TIMING_BUF_ESIZE - 1;
     }
   else
     {
       user->generation = upper->state.generation;
+      user->bufferpos  = upper->timing.head / TIMING_BUF_ESIZE;
     }
 
   user->interval = ULONG_MAX;
@@ -524,7 +661,6 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
   FAR struct sensor_upperhalf_s *upper = inode->i_private;
   FAR struct sensor_lowerhalf_s *lower = upper->lower;
   FAR struct sensor_user_s *user = filep->f_priv;
-  unsigned long nums;
   ssize_t ret;
 
   if (!buffer || !len)
@@ -554,54 +690,25 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
 
         ret = lower->ops->fetch(lower, filep, buffer, len);
     }
-  else
+  else if (circbuf_is_empty(&upper->buffer))
     {
-      if (circbuf_is_empty(&upper->buffer))
-        {
-          ret = -ENODATA;
-          goto out;
-        }
-
-      /* If the device data is persistent, and when the device has
-       * no new data, the user can copy the old data, otherwise
-       * return -ENODATA.
-       */
-
-      if (user->generation == upper->state.generation)
-        {
-          if (lower->persist)
-            {
-              user->generation--;
-            }
-          else
-            {
-              ret = -ENODATA;
-              goto out;
-            }
-        }
-
-      /* If user's generation isn't within circbuffer range, the
-       * oldest data in circbuffer are returned to the users.
-       */
-
-      if (!sensor_in_range(upper->state.generation - lower->nbuffer,
-                           user->generation, upper->state.generation))
-
-        {
-          user->generation = upper->state.generation - lower->nbuffer;
-        }
-
-      nums = upper->state.generation - user->generation;
-      if (len < nums * upper->state.esize)
-        {
-          nums = len / upper->state.esize;
-        }
+      ret = -ENODATA;
+    }
+  else if (sensor_is_updated(upper, user))
+    {
+      ret = sensor_do_samples(upper, user, buffer, len);
+    }
+  else if (lower->persist)
+    {
+      /* Persistent device can get latest old data if not updated. */
 
-      len = nums * upper->state.esize;
       ret = circbuf_peekat(&upper->buffer,
-                           user->generation * upper->state.esize,
-                           buffer, len);
-      user->generation += nums;
+                           (user->bufferpos - 1) * upper->state.esize,
+                           buffer, upper->state.esize);
+    }
+  else
+    {
+      ret = -ENODATA;
     }
 
 out:
@@ -728,8 +835,7 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
       case SNIOC_UPDATED:
         {
           nxrmutex_lock(&upper->lock);
-          *(FAR bool *)(uintptr_t)arg =
-          sensor_is_updated(upper->state.generation, user->generation);
+          *(FAR bool *)(uintptr_t)arg = sensor_is_updated(upper, user);
           nxrmutex_unlock(&upper->lock);
         }
         break;
@@ -794,7 +900,7 @@ static int sensor_poll(FAR struct file *filep,
                 }
             }
         }
-      else if (sensor_is_updated(upper->state.generation, user->generation))
+      else if (sensor_is_updated(upper, user))
         {
           eventset |= (fds->events & POLLIN);
         }
@@ -848,13 +954,22 @@ static ssize_t sensor_push_event(FAR void *priv, FAR const void *data,
           nxrmutex_unlock(&upper->lock);
           return ret;
         }
+
+      ret = circbuf_init(&upper->timing, NULL, lower->nbuffer *
+                         TIMING_BUF_ESIZE);
+      if (ret < 0)
+        {
+          circbuf_uninit(&upper->buffer);
+          nxrmutex_unlock(&upper->lock);
+          return ret;
+        }
     }
 
   circbuf_overwrite(&upper->buffer, data, bytes);
-  upper->state.generation += envcount;
+  sensor_generate_timing(upper, envcount);
   list_for_every_entry(&upper->userlist, user, struct sensor_user_s, node)
     {
-      if (sensor_is_updated(upper->state.generation, user->generation))
+      if (sensor_is_updated(upper, user))
         {
           nxsem_get_value(&user->buffersem, &semcount);
           if (semcount < 1)
@@ -1102,6 +1217,7 @@ void sensor_custom_unregister(FAR struct sensor_lowerhalf_s *lower,
   if (circbuf_is_init(&upper->buffer))
     {
       circbuf_uninit(&upper->buffer);
+      circbuf_uninit(&upper->timing);
     }
 
   kmm_free(upper);


[incubator-nuttx] 22/22: driver/sensor: fix deadlock about sensor_rpmsg

Posted by xi...@apache.org.
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 78381f9fc439f2d9d84ed738a3405ed269fda0be
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Mon Jul 4 11:08:30 2022 +0800

    driver/sensor: fix deadlock about sensor_rpmsg
    
    task1:
    nuttx/arch/arm/src/common/arm_blocktask.c:151
    nxsem_wait
    nuttx/arch/arm/src/../../../sched/semaphore/sem_wait.c:155 (discriminator 2)
    sem_wait
    nuttx/arch/arm/src/../../../sched/semaphore/sem_wait.c:273
    nxmutex_lock.lto_priv.2
    nuttx/include/nuttx/mutex.h:161
    sensor_rpmsg_push_event_one
    nuttx/arch/arm/src/../../../drivers/sensors/sensor_rpmsg.c:748
    up_unblock_task
    nuttx/arch/arm/src/common/arm_unblocktask.c:75 (discriminator 2)
    sensor_rpmsg_push_event
    nuttx/arch/arm/src/../../../drivers/sensors/sensor_rpmsg.c:858
    write
    orb_publish_multi
    nuttx/arch/arm/src/../../../../apps/system/uorb/uORB/uORB.c:188
    
    task2:
    nxrmutex_lock.isra.0
    sensor_read
    nuttx/arch/arm/src/../../../drivers/sensors/sensor.c:753
    sem_post
    nuttx/arch/arm/src/../../../sched/semaphore/sem_post.c:224
    nxmutex_unlock.lto_priv.1
    nuttx/include/nuttx/mutex.h:259
    sensor_rpmsg_push_event_one
    nuttx/arch/arm/src/../../../drivers/sensors/sensor_rpmsg.c:787
    nxmutex_unlock.lto_priv.1
    nuttx/include/nuttx/mutex.h:259
    nuttx/arch/arm/src/../../../drivers/sensors/sensor.c:969
    sensor_rpmsg_alloc_stub
    nuttx/arch/arm/src/../../../drivers/sensors/sensor_rpmsg.c:549
    sensor_rpmsg_advack_handler
    
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 drivers/sensors/sensor_rpmsg.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/sensors/sensor_rpmsg.c b/drivers/sensors/sensor_rpmsg.c
index 0243119f3a..37351fd23d 100644
--- a/drivers/sensors/sensor_rpmsg.c
+++ b/drivers/sensors/sensor_rpmsg.c
@@ -541,13 +541,14 @@ sensor_rpmsg_alloc_stub(FAR struct sensor_rpmsg_dev_s *dev,
 
   sensor_rpmsg_lock(dev);
   list_add_tail(&dev->stublist, &stub->node);
-  sensor_rpmsg_unlock(dev);
 
   if (dev->lower.persist)
     {
       sensor_rpmsg_push_event_one(dev, stub);
     }
 
+  sensor_rpmsg_unlock(dev);
+
   return stub;
 }
 


[incubator-nuttx] 19/22: driver/sensor: add cmd SNIOC_UPDATED and remove readlast

Posted by xi...@apache.org.
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 5b91641a09374e7bf798b11c8903067bf0fb0f37
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Tue Jun 28 15:50:37 2022 +0800

    driver/sensor: add cmd SNIOC_UPDATED and remove readlast
    
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 drivers/sensors/sensor.c       | 75 ++++++++++--------------------------------
 drivers/sensors/sensor_rpmsg.c |  8 ++++-
 include/nuttx/sensors/ioctl.h  | 11 +++----
 3 files changed, 30 insertions(+), 64 deletions(-)

diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index 99544231bf..50e9d33cc8 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -85,7 +85,6 @@ struct sensor_user_s
   unsigned long    generation; /* Last generation subscriber has seen */
   unsigned long    interval;   /* The interval for subscriber */
   unsigned long    latency;    /* The bactch latency for subscriber */
-  bool             readlast;   /* The flag of readlast */
 };
 
 /* This structure describes the state of the upper half driver */
@@ -447,7 +446,6 @@ static int sensor_open(FAR struct file *filep)
     }
 
   user->interval = ULONG_MAX;
-  user->readlast = true;
   nxsem_init(&user->buffersem, 0, 0);
   nxsem_set_protocol(&user->buffersem, SEM_PRIO_NONE);
   list_add_tail(&upper->userlist, &user->node);
@@ -558,65 +556,27 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
     }
   else
     {
-      /* 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.
+      if (circbuf_is_empty(&upper->buffer))
+        {
+          ret = -ENODATA;
+          goto out;
+        }
+
+      /* If the device data is persistent, and when the device has
+       * no new data, the user can copy the old data, otherwise
+       * return -ENODATA.
        */
 
-      if (user->readlast)
+      if (user->generation == upper->state.generation)
         {
-          if (circbuf_is_empty(&upper->buffer))
+          if (lower->persist)
             {
-              ret = -ENODATA;
-              goto out;
+              user->generation--;
             }
-
-          /* If the device data is persistent, and when the device has no
-           * new data, the user can copy the old data, otherwise return
-           * -ENODATA.
-           */
-
-          if (user->generation == upper->state.generation)
-            {
-              if (lower->persist)
-                {
-                  user->generation--;
-                }
-              else
-                {
-                  ret = -ENODATA;
-                  goto out;
-                }
-            }
-        }
-      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)
+          else
             {
-              if (filep->f_oflags & O_NONBLOCK)
-                {
-                  ret = -EAGAIN;
-                  goto out;
-                }
-              else
-                {
-                  nxrmutex_unlock(&upper->lock);
-                  ret = nxsem_wait_uninterruptible(&user->buffersem);
-                  if (ret < 0)
-                    {
-                      return ret;
-                    }
-
-                  nxrmutex_lock(&upper->lock);
-                }
+              ret = -ENODATA;
+              goto out;
             }
         }
 
@@ -765,10 +725,11 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
         }
         break;
 
-      case SNIOC_READLAST:
+      case SNIOC_UPDATED:
         {
           nxrmutex_lock(&upper->lock);
-          user->readlast = !!arg;
+          *(FAR bool *)(uintptr_t)arg =
+          sensor_is_updated(upper->state.generation, user->generation);
           nxrmutex_unlock(&upper->lock);
         }
         break;
diff --git a/drivers/sensors/sensor_rpmsg.c b/drivers/sensors/sensor_rpmsg.c
index 8aa9f263d2..2b608d3f3e 100644
--- a/drivers/sensors/sensor_rpmsg.c
+++ b/drivers/sensors/sensor_rpmsg.c
@@ -539,7 +539,6 @@ sensor_rpmsg_alloc_stub(FAR struct sensor_rpmsg_dev_s *dev,
       return NULL;
     }
 
-  file_ioctl(&stub->file, SNIOC_READLAST, false);
   sensor_rpmsg_lock(dev);
   list_add_tail(&dev->stublist, &stub->node);
   sensor_rpmsg_unlock(dev);
@@ -729,6 +728,7 @@ static void sensor_rpmsg_push_event_one(FAR struct sensor_rpmsg_dev_s *dev,
   FAR struct sensor_rpmsg_data_s *msg;
   struct sensor_state_s state;
   uint64_t now;
+  bool updated;
   int ret;
 
   /* Get state of device to do send data with timeout */
@@ -756,6 +756,12 @@ static void sensor_rpmsg_push_event_one(FAR struct sensor_rpmsg_dev_s *dev,
 
   for (; ; )
     {
+      ret = file_ioctl(&stub->file, SNIOC_UPDATED, &updated);
+      if (ret < 0 || !updated)
+        {
+          break;
+        }
+
       /* If buffer isn't created or it doesn't have enough space to fill
        * new data, you should create or send this buffer at once.
        */
diff --git a/include/nuttx/sensors/ioctl.h b/include/nuttx/sensors/ioctl.h
index 1e415a98cc..992367cc14 100644
--- a/include/nuttx/sensors/ioctl.h
+++ b/include/nuttx/sensors/ioctl.h
@@ -326,13 +326,12 @@
 #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
+/* Command:      SNIOC_UPDATED
+ * Description:  Check whether the topic has been updated since
+ *               it was last read.
+ * Argument:     Sets *(bool *)arg
  */
 
-#define SNIOC_READLAST             _SNIOC(0x0091)
+#define SNIOC_UPDATED              _SNIOC(0x0091)
 
 #endif /* __INCLUDE_NUTTX_SENSORS_IOCTL_H */


[incubator-nuttx] 10/22: driver/sensor: move register_driver to end to avoid race condition

Posted by xi...@apache.org.
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 38393cfc940d3032325c6dc6de60b870fc0ea0ac
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Tue Jun 14 11:44:24 2022 +0800

    driver/sensor: move register_driver to end to avoid race condition
    
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 drivers/sensors/sensor.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index 89b47813ba..ac487bb39f 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -1048,14 +1048,6 @@ int sensor_custom_register(FAR struct sensor_lowerhalf_s *lower,
       lower->nbuffer = 0;
     }
 
-  upper->state.nbuffer = lower->nbuffer;
-  sninfo("Registering %s\n", path);
-  ret = register_driver(path, &g_sensor_fops, 0666, upper);
-  if (ret)
-    {
-      goto drv_err;
-    }
-
 #ifdef CONFIG_SENSORS_RPMSG
   lower = sensor_rpmsg_register(lower, path);
   if (lower == NULL)
@@ -1065,7 +1057,15 @@ int sensor_custom_register(FAR struct sensor_lowerhalf_s *lower,
     }
 #endif
 
+  upper->state.nbuffer = lower->nbuffer;
   upper->lower = lower;
+  sninfo("Registering %s\n", path);
+  ret = register_driver(path, &g_sensor_fops, 0666, upper);
+  if (ret)
+    {
+      goto drv_err;
+    }
+
   return ret;
 
 drv_err:


[incubator-nuttx] 02/22: driver/sensor: enable usensor and rpmsg_sensor

Posted by xi...@apache.org.
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 8de6c29aa4be51f4902c0c2eea64b9534f0f2c4e
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Thu Apr 14 12:21:45 2022 +0800

    driver/sensor: enable usensor and rpmsg_sensor
    
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 drivers/drivers_initialize.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/drivers_initialize.c b/drivers/drivers_initialize.c
index bb62e23f88..7ba9363479 100644
--- a/drivers/drivers_initialize.c
+++ b/drivers/drivers_initialize.c
@@ -31,9 +31,10 @@
 #include <nuttx/net/telnet.h>
 #include <nuttx/note/note_driver.h>
 #include <nuttx/power/pm.h>
+#include <nuttx/sensors/sensor.h>
+#include <nuttx/serial/pty.h>
 #include <nuttx/syslog/syslog.h>
 #include <nuttx/syslog/syslog_console.h>
-#include <nuttx/serial/pty.h>
 
 /****************************************************************************
  * Public Functions
@@ -143,4 +144,12 @@ void drivers_initialize(void)
 
   telnet_initialize();
 #endif
+
+#ifdef CONFIG_USENSOR
+  usensor_initialize();
+#endif
+
+#ifdef CONFIG_SENSORS_RPMSG
+  sensor_rpmsg_initialize();
+#endif
 }


[incubator-nuttx] 16/22: driver/sensor: export upper half lock

Posted by xi...@apache.org.
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 107e3e5d5276bce6f0f24e2af19dd266fd177616
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Thu Jun 23 12:13:56 2022 +0800

    driver/sensor: export upper half lock
    
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 drivers/sensors/sensor.c       | 16 +++++++++++++++-
 include/nuttx/sensors/sensor.h | 13 +++++++++++++
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index 45b67b011a..4d61eb2c9b 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -177,6 +177,18 @@ static const struct file_operations g_sensor_fops =
  * Private Functions
  ****************************************************************************/
 
+static void sensor_lock(FAR void *priv)
+{
+  FAR struct sensor_upperhalf_s *upper = priv;
+  nxrmutex_lock(&upper->lock);
+}
+
+static void sensor_unlock(FAR void *priv)
+{
+  FAR struct sensor_upperhalf_s *upper = priv;
+  nxrmutex_unlock(&upper->lock);
+}
+
 static bool sensor_in_range(unsigned long left, unsigned long value,
                             unsigned long right)
 {
@@ -1017,7 +1029,9 @@ int sensor_custom_register(FAR struct sensor_lowerhalf_s *lower,
 
   /* Bind the lower half data structure member */
 
-  lower->priv = upper;
+  lower->priv          = upper;
+  lower->sensor_lock   = sensor_lock;
+  lower->sensor_unlock = sensor_unlock;
 
   if (!lower->ops->fetch)
     {
diff --git a/include/nuttx/sensors/sensor.h b/include/nuttx/sensors/sensor.h
index 35172a6080..8af4eca43f 100644
--- a/include/nuttx/sensors/sensor.h
+++ b/include/nuttx/sensors/sensor.h
@@ -937,6 +937,19 @@ struct sensor_lowerhalf_s
       sensor_notify_event_t notify_event;
     };
 
+/****************************************************************************
+ * Name: sensor_lock/sensor_unlock
+ *
+ * Description:
+ *   Lower half driver can lock/unlock upper half driver by this interface.
+ *
+ * Input Parameters:
+ *   priv   - Upper half driver handle
+ ****************************************************************************/
+
+  void (*sensor_lock)(void * priv);
+  void (*sensor_unlock)(void * priv);
+
   /* The private opaque pointer to be passed to upper-layer during callback */
 
   FAR void *priv;


[incubator-nuttx] 09/22: driver/sensor/rpmsg: fix deadlock case: push event in ioctl_ack handler

Posted by xi...@apache.org.
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 bf6063cc046be6287ed7803000c889abef60cd11
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Fri Jun 10 22:46:04 2022 +0800

    driver/sensor/rpmsg: fix deadlock case: push event in ioctl_ack handler
    
    using recursive mutex to fix this issue.
    
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 drivers/sensors/sensor_rpmsg.c | 54 +++++++++++++++++++++---------------------
 1 file changed, 27 insertions(+), 27 deletions(-)

diff --git a/drivers/sensors/sensor_rpmsg.c b/drivers/sensors/sensor_rpmsg.c
index 0111ca38bc..8338a592a9 100644
--- a/drivers/sensors/sensor_rpmsg.c
+++ b/drivers/sensors/sensor_rpmsg.c
@@ -82,7 +82,7 @@ struct sensor_rpmsg_dev_s
 {
   struct sensor_lowerhalf_s      lower;
   FAR struct sensor_lowerhalf_s *drv;
-  mutex_t                        lock;
+  rmutex_t                       lock;
   struct list_node               node;
   struct list_node               stublist;
   struct list_node               proxylist;
@@ -354,7 +354,7 @@ static int sensor_rpmsg_ioctl(FAR struct sensor_rpmsg_dev_s *dev,
    * if device doesn't have proxy, it must return -ENOTTY.
    */
 
-  nxmutex_lock(&dev->lock);
+  nxrmutex_lock(&dev->lock);
   list_for_every_entry(&dev->proxylist, proxy,
                        struct sensor_rpmsg_proxy_s, node)
     {
@@ -394,9 +394,9 @@ static int sensor_rpmsg_ioctl(FAR struct sensor_rpmsg_dev_s *dev,
           continue;
         }
 
-      nxmutex_unlock(&dev->lock);
+      nxrmutex_unlock(&dev->lock);
       ret = rpmsg_wait(proxy->ept, &cookie.sem);
-      nxmutex_lock(&dev->lock);
+      nxrmutex_lock(&dev->lock);
       if (ret < 0)
         {
           snerr("ERROR: ioctl rpmsg wait failed:%s, %d, %s\n",
@@ -411,7 +411,7 @@ static int sensor_rpmsg_ioctl(FAR struct sensor_rpmsg_dev_s *dev,
         }
     }
 
-  nxmutex_unlock(&dev->lock);
+  nxrmutex_unlock(&dev->lock);
   if (wait)
     {
       nxsem_destroy(&cookie.sem);
@@ -460,7 +460,7 @@ sensor_rpmsg_alloc_proxy(FAR struct sensor_rpmsg_dev_s *dev,
   file_ioctl(&file, SNIOC_GET_STATE, &state);
   file_close(&file);
 
-  nxmutex_lock(&dev->lock);
+  nxrmutex_lock(&dev->lock);
   if (msg->persist)
     {
       dev->drv->persist = true;
@@ -468,7 +468,7 @@ sensor_rpmsg_alloc_proxy(FAR struct sensor_rpmsg_dev_s *dev,
     }
 
   list_add_tail(&dev->proxylist, &proxy->node);
-  nxmutex_unlock(&dev->lock);
+  nxrmutex_unlock(&dev->lock);
 
   /* sync interval and latency */
 
@@ -522,9 +522,9 @@ sensor_rpmsg_alloc_stub(FAR struct sensor_rpmsg_dev_s *dev,
     }
 
   file_ioctl(&stub->file, SNIOC_READLAST, false);
-  nxmutex_lock(&dev->lock);
+  nxrmutex_lock(&dev->lock);
   list_add_tail(&dev->stublist, &stub->node);
-  nxmutex_unlock(&dev->lock);
+  nxrmutex_unlock(&dev->lock);
 
   if (dev->lower.persist)
     {
@@ -568,7 +568,7 @@ static int sensor_rpmsg_open(FAR struct file *filep,
       return 0;
     }
 
-  nxmutex_lock(&dev->lock);
+  nxrmutex_lock(&dev->lock);
   if (filep->f_oflags & O_WROK)
     {
       if (dev->nadvertisers++ == 0)
@@ -585,7 +585,7 @@ static int sensor_rpmsg_open(FAR struct file *filep,
         }
     }
 
-  nxmutex_unlock(&dev->lock);
+  nxrmutex_unlock(&dev->lock);
   return 0;
 }
 
@@ -610,7 +610,7 @@ static int sensor_rpmsg_close(FAR struct file *filep,
       return ret;
     }
 
-  nxmutex_lock(&dev->lock);
+  nxrmutex_lock(&dev->lock);
   if (filep->f_oflags & O_WROK)
     {
       if (dev->nadvertisers == 1)
@@ -641,7 +641,7 @@ static int sensor_rpmsg_close(FAR struct file *filep,
       dev->nsubscribers--;
     }
 
-  nxmutex_unlock(&dev->lock);
+  nxrmutex_unlock(&dev->lock);
   return ret;
 }
 
@@ -827,14 +827,14 @@ static ssize_t sensor_rpmsg_push_event(FAR void *priv, FAR const void *data,
    * is successful, and must return length of written.
    */
 
-  nxmutex_lock(&dev->lock);
+  nxrmutex_lock(&dev->lock);
   list_for_every_entry(&dev->stublist, stub,
                        struct sensor_rpmsg_stub_s, node)
     {
       sensor_rpmsg_push_event_one(dev, stub);
     }
 
-  nxmutex_unlock(&dev->lock);
+  nxrmutex_unlock(&dev->lock);
   return ret;
 }
 
@@ -925,7 +925,7 @@ static int sensor_rpmsg_unadv_handler(FAR struct rpmsg_endpoint *ept,
       return 0;
     }
 
-  nxmutex_lock(&dev->lock);
+  nxrmutex_lock(&dev->lock);
   list_for_every_entry(&dev->proxylist, proxy,
                        struct sensor_rpmsg_proxy_s, node)
     {
@@ -936,7 +936,7 @@ static int sensor_rpmsg_unadv_handler(FAR struct rpmsg_endpoint *ept,
         }
     }
 
-  nxmutex_unlock(&dev->lock);
+  nxrmutex_unlock(&dev->lock);
   return 0;
 }
 
@@ -1010,7 +1010,7 @@ static int sensor_rpmsg_unsub_handler(FAR struct rpmsg_endpoint *ept,
       return 0;
     }
 
-  nxmutex_lock(&dev->lock);
+  nxrmutex_lock(&dev->lock);
   list_for_every_entry(&dev->stublist, stub,
                        struct sensor_rpmsg_stub_s, node)
     {
@@ -1021,7 +1021,7 @@ static int sensor_rpmsg_unsub_handler(FAR struct rpmsg_endpoint *ept,
         }
     }
 
-  nxmutex_unlock(&dev->lock);
+  nxrmutex_unlock(&dev->lock);
   return 0;
 }
 
@@ -1060,7 +1060,7 @@ static int sensor_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept,
   arg = msg->arglen > 0 ? (unsigned long)(uintptr_t)msg->argbuf :
                           msg->arg;
   dev = (FAR struct sensor_rpmsg_dev_s *)(uintptr_t)msg->proxy;
-  nxmutex_lock(&dev->lock);
+  nxrmutex_lock(&dev->lock);
   list_for_every_entry(&dev->stublist, stub,
                        struct sensor_rpmsg_stub_s, node)
     {
@@ -1080,7 +1080,7 @@ static int sensor_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept,
         }
     }
 
-  nxmutex_unlock(&dev->lock);
+  nxrmutex_unlock(&dev->lock);
   return 0;
 }
 
@@ -1137,7 +1137,7 @@ static void sensor_rpmsg_ns_unbind_cb(FAR struct rpmsg_endpoint *ept)
   list_for_every_entry(&g_devlist, dev,
                        struct sensor_rpmsg_dev_s, node)
     {
-      nxmutex_lock(&dev->lock);
+      nxrmutex_lock(&dev->lock);
       list_for_every_entry_safe(&dev->proxylist, proxy, ptmp,
                                 struct sensor_rpmsg_proxy_s, node)
         {
@@ -1156,7 +1156,7 @@ static void sensor_rpmsg_ns_unbind_cb(FAR struct rpmsg_endpoint *ept)
             }
         }
 
-      nxmutex_unlock(&dev->lock);
+      nxrmutex_unlock(&dev->lock);
     }
 
   list_delete(&sre->node);
@@ -1181,7 +1181,7 @@ static void sensor_rpmsg_device_ns_bound(FAR struct rpmsg_endpoint *ept)
   list_for_every_entry(&g_devlist, dev,
                        struct sensor_rpmsg_dev_s, node)
     {
-      nxmutex_lock(&dev->lock);
+      nxrmutex_lock(&dev->lock);
       if (dev->nadvertisers > 0)
         {
           sensor_rpmsg_advsub_one(dev, ept, SENSOR_RPMSG_ADVERTISE);
@@ -1192,7 +1192,7 @@ static void sensor_rpmsg_device_ns_bound(FAR struct rpmsg_endpoint *ept)
           sensor_rpmsg_advsub_one(dev, ept, SENSOR_RPMSG_SUBSCRIBE);
         }
 
-      nxmutex_unlock(&dev->lock);
+      nxrmutex_unlock(&dev->lock);
     }
 
   nxmutex_unlock(&g_lock);
@@ -1264,7 +1264,7 @@ sensor_rpmsg_register(FAR struct sensor_lowerhalf_s *lower,
 
   list_initialize(&dev->stublist);
   list_initialize(&dev->proxylist);
-  nxmutex_init(&dev->lock);
+  nxrmutex_init(&dev->lock);
   strcpy(dev->path, path);
 
   dev->push_event     = lower->push_event;
@@ -1318,7 +1318,7 @@ void sensor_rpmsg_unregister(FAR struct sensor_lowerhalf_s *lower)
   list_delete(&dev->node);
   nxmutex_unlock(&g_lock);
 
-  nxmutex_destroy(&dev->lock);
+  nxrmutex_destroy(&dev->lock);
   kmm_free(dev);
 }
 


[incubator-nuttx] 12/22: driver/sensor: convert interval 0 to ULONG_MAX

Posted by xi...@apache.org.
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 8e03f213e330d50f14309f706f0932eb96fe5d7f
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Wed Jun 15 21:26:09 2022 +0800

    driver/sensor: convert interval 0 to ULONG_MAX
    
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 drivers/sensors/sensor.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index 41717cb9bb..e054116a8d 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -647,7 +647,8 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
       case SNIOC_SET_INTERVAL:
         {
           nxrmutex_lock(&upper->lock);
-          ret = sensor_update_interval(filep, upper, user, arg);
+          ret = sensor_update_interval(filep, upper, user,
+                                       arg ? arg : ULONG_MAX);
           nxrmutex_unlock(&upper->lock);
         }
         break;


[incubator-nuttx] 03/22: driver/sensor: add _SNIOCVALID check to command

Posted by xi...@apache.org.
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 2f5727b1021dfe969feb689ee58f6e9b1c232f4e
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Mon May 23 14:50:14 2022 +0800

    driver/sensor: add _SNIOCVALID check to command
    
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 drivers/sensors/sensor_rpmsg.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/sensors/sensor_rpmsg.c b/drivers/sensors/sensor_rpmsg.c
index e69e2fe6f6..1b2a1176cd 100644
--- a/drivers/sensors/sensor_rpmsg.c
+++ b/drivers/sensors/sensor_rpmsg.c
@@ -646,7 +646,7 @@ static int sensor_rpmsg_control(FAR struct file *filep,
     {
       return drv->ops->control(filep, drv, cmd, arg);
     }
-  else if (!(filep->f_oflags & O_REMOTE))
+  else if (!(filep->f_oflags & O_REMOTE) && _SNIOCVALID(cmd))
     {
       return sensor_rpmsg_ioctl(dev, cmd, arg,
                                 sizeof(*ioctl) + ioctl->len, true);


[incubator-nuttx] 01/22: driver/sensor: support access remote sensor by rpmsg

Posted by xi...@apache.org.
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 c5f87bb5c60e162ef23d604249373bdfa4ba06ca
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Fri Apr 8 22:46:29 2022 +0800

    driver/sensor: support access remote sensor by rpmsg
    
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 drivers/sensors/Kconfig        |    7 +
 drivers/sensors/Make.defs      |    4 +
 drivers/sensors/sensor.c       |   19 +-
 drivers/sensors/sensor_rpmsg.c | 1303 ++++++++++++++++++++++++++++++++++++++++
 include/nuttx/sensors/sensor.h |   62 +-
 5 files changed, 1389 insertions(+), 6 deletions(-)

diff --git a/drivers/sensors/Kconfig b/drivers/sensors/Kconfig
index 1f2fc138ac..c3033070ac 100644
--- a/drivers/sensors/Kconfig
+++ b/drivers/sensors/Kconfig
@@ -18,6 +18,13 @@ config USENSOR
 	---help---
 		Allow application to register user sensor by /dev/usensor.
 
+config SENSORS_RPMSG
+	bool "Sensor rpmsg Support"
+	default n
+	depends on RPTUN
+	---help---
+		Allow application to read or control remote sensor device by rpmsg.
+
 config SENSORS_WTGAHRS2
 	bool "Wtgahrs2 Sensor Support"
 	default n
diff --git a/drivers/sensors/Make.defs b/drivers/sensors/Make.defs
index f372b78ec2..4543a3e9a3 100644
--- a/drivers/sensors/Make.defs
+++ b/drivers/sensors/Make.defs
@@ -28,6 +28,10 @@ ifeq ($(CONFIG_USENSOR),y)
 CSRCS += usensor.c
 endif
 
+ifeq ($(CONFIG_SENSORS_RPMSG),y)
+CSRCS += sensor_rpmsg.c
+endif
+
 ifeq ($(CONFIG_SENSORS_WTGAHRS2),y)
   CSRCS += wtgahrs2.c
 endif
diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index 25431ae489..29add29309 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -599,8 +599,9 @@ static ssize_t sensor_write(FAR struct file *filep, FAR const char *buffer,
 {
   FAR struct inode *inode = filep->f_inode;
   FAR struct sensor_upperhalf_s *upper = inode->i_private;
+  FAR struct sensor_lowerhalf_s *lower = upper->lower;
 
-  return sensor_push_event(upper, buffer, buflen);
+  return lower->push_event(lower->priv, buffer, buflen);
 }
 
 static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
@@ -967,8 +968,6 @@ int sensor_custom_register(FAR struct sensor_lowerhalf_s *lower,
 
   /* Initialize the upper-half data structure */
 
-  upper->lower = lower;
-
   list_initialize(&upper->userlist);
   upper->state.esize = esize;
   upper->state.min_interval = ULONG_MAX;
@@ -1007,6 +1006,16 @@ int sensor_custom_register(FAR struct sensor_lowerhalf_s *lower,
       goto drv_err;
     }
 
+#ifdef CONFIG_SENSORS_RPMSG
+  lower = sensor_rpmsg_register(lower, path);
+  if (lower == NULL)
+    {
+      ret = -EIO;
+      goto drv_err;
+    }
+#endif
+
+  upper->lower = lower;
   return ret;
 
 drv_err:
@@ -1069,6 +1078,10 @@ void sensor_custom_unregister(FAR struct sensor_lowerhalf_s *lower,
   sninfo("UnRegistering %s\n", path);
   unregister_driver(path);
 
+#ifdef CONFIG_SENSORS_RPMSG
+  sensor_rpmsg_unregister(lower);
+#endif
+
   nxsem_destroy(&upper->exclsem);
   if (circbuf_is_init(&upper->buffer))
     {
diff --git a/drivers/sensors/sensor_rpmsg.c b/drivers/sensors/sensor_rpmsg.c
new file mode 100644
index 0000000000..e69e2fe6f6
--- /dev/null
+++ b/drivers/sensors/sensor_rpmsg.c
@@ -0,0 +1,1303 @@
+/****************************************************************************
+ * drivers/sensors/sensor_rpmsg.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <fcntl.h>
+#include <debug.h>
+
+#include <nuttx/list.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/mutex.h>
+#include <nuttx/sensors/sensor.h>
+#include <nuttx/rptun/openamp.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define O_REMOTE                   (1 << 31)
+
+#define SENSOR_RPMSG_EPT_NAME      "rpmsg-sensor"
+#define SENSOR_RPMSG_ADVERTISE     0
+#define SENSOR_RPMSG_ADVERTISE_ACK 1
+#define SENSOR_RPMSG_UNADVERTISE   2
+#define SENSOR_RPMSG_SUBSCRIBE     3
+#define SENSOR_RPMSG_SUBSCRIBE_ACK 4
+#define SENSOR_RPMSG_UNSUBSCRIBE   5
+#define SENSOR_RPMSG_PUBLISH       6
+#define SENSOR_RPMSG_IOCTL         7
+#define SENSOR_RPMSG_IOCTL_ACK     8
+
+#define SENSOR_RPMSG_FUNCTION(name, cmd, arg1, arg2, size, wait) \
+static int sensor_rpmsg_##name(FAR struct file *filep, \
+                               FAR struct sensor_lowerhalf_s *lower, \
+                               unsigned long arg1) \
+{ \
+  FAR struct sensor_rpmsg_dev_s *dev = lower->priv; \
+  FAR struct sensor_lowerhalf_s *drv = dev->drv; \
+  int ret; \
+\
+  if (drv->ops->name) \
+    { \
+      return drv->ops->name(filep, drv, arg2); \
+    } \
+  else if (!(filep->f_oflags & O_REMOTE)) \
+    { \
+      ret = sensor_rpmsg_ioctl(dev, cmd, arg1, size, wait); \
+      return wait ? ret : 0; \
+    } \
+  else \
+    { \
+      return wait ? -ENOTSUP : 0; \
+    } \
+} \
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This structure describes the context of sensor rpmsg device driver. */
+
+struct sensor_rpmsg_dev_s
+{
+  struct sensor_lowerhalf_s      lower;
+  FAR struct sensor_lowerhalf_s *drv;
+  mutex_t                        lock;
+  struct list_node               node;
+  struct list_node               stublist;
+  struct list_node               proxylist;
+  uint8_t                        nadvertisers;
+  uint8_t                        nsubscribers;
+  FAR void                      *upper;
+  sensor_push_event_t            push_event;
+  char                           path[1];
+};
+
+/* This structure describes the context of sensor rpmsg endpoint. */
+
+struct sensor_rpmsg_ept_s
+{
+  struct list_node               node;
+  struct rpmsg_endpoint          ept;
+  FAR struct rpmsg_device       *rdev;
+  struct work_s                  work;
+  mutex_t                        lock;
+  FAR void                      *buffer;
+  uint64_t                       expire;
+  uint32_t                       space;
+  size_t                         written;
+};
+
+/* This structure describes the stub info about remote subscribers. */
+
+struct sensor_rpmsg_stub_s
+{
+  struct list_node               node;
+  FAR struct rpmsg_endpoint     *ept;
+  uint64_t                       cookie;
+  struct file                    file;
+};
+
+/* This structure describes the proxy info about remote advertisers. */
+
+struct sensor_rpmsg_proxy_s
+{
+  struct list_node               node;
+  FAR struct rpmsg_endpoint     *ept;
+  uint64_t                       cookie;
+};
+
+/* Remote message structure */
+
+/* This structure describes the message about initiating a remote
+ * subscription and remote advertisement.
+ */
+
+struct sensor_rpmsg_advsub_s
+{
+  uint32_t                       command;
+  uint32_t                       nbuffer;
+  uint64_t                       cookie;
+  char                           path[1];
+};
+
+/* The structure sensor_rpmsg_cell_s describes a data message,
+ * include remote receiver, the length of data and the data payload.
+ * The structure sensor_rpmsg_data_s describes a set of data message.
+ */
+
+struct sensor_rpmsg_cell_s
+{
+  uint64_t                       cookie;
+  uint32_t                       len;
+  char                           data[0];
+};
+
+struct sensor_rpmsg_data_s
+{
+  uint32_t                       command;
+  uint32_t                       reserved;
+  struct sensor_rpmsg_cell_s     cell[0];
+};
+
+/* This structure uses to send ioctl from remote device to physical device,
+ * it supports pass pointer to remove device by cookie_xx member.
+ */
+
+struct sensor_rpmsg_ioctl_cookie_s
+{
+  sem_t                          sem;
+  FAR void                      *data;
+  int                            result;
+};
+
+struct sensor_rpmsg_ioctl_s
+{
+  uint32_t                       command;
+  int32_t                        result;
+  uint64_t                       cookie;
+  uint64_t                       proxy;
+
+  int32_t                        request;
+  uint32_t                       arglen;
+  union
+    {
+      uint64_t                   arg;
+      char                       argbuf[0];
+    };
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int sensor_rpmsg_open(FAR struct file *filep,
+                             FAR struct sensor_lowerhalf_s *lower);
+static int sensor_rpmsg_close(FAR struct file *filep,
+                              FAR struct sensor_lowerhalf_s *lower);
+static int sensor_rpmsg_activate(FAR struct file *filep,
+                                 FAR struct sensor_lowerhalf_s *lower,
+                                 bool enable);
+static int sensor_rpmsg_set_interval(FAR struct file *filep,
+                                     FAR struct sensor_lowerhalf_s *lower,
+                                     FAR unsigned long *period_us);
+static int sensor_rpmsg_batch(FAR struct file *filep,
+                              FAR struct sensor_lowerhalf_s *lower,
+                              FAR unsigned long *latency_us);
+static int sensor_rpmsg_selftest(FAR struct file *filep,
+                                 FAR struct sensor_lowerhalf_s *lower,
+                                 unsigned long arg);
+static int sensor_rpmsg_set_calibvalue(FAR struct file *filep,
+                                  FAR struct sensor_lowerhalf_s *lower,
+                                  unsigned long arg);
+static int sensor_rpmsg_calibrate(FAR struct file *filep,
+                                  FAR struct sensor_lowerhalf_s *lower,
+                                  unsigned long arg);
+static int sensor_rpmsg_control(FAR struct file *filep,
+                                FAR struct sensor_lowerhalf_s *lower,
+                                int cmd, unsigned long arg);
+static int sensor_rpmsg_adv_handler(FAR struct rpmsg_endpoint *ept,
+                                    FAR void *data, size_t len,
+                                    uint32_t src, FAR void *priv);
+static int sensor_rpmsg_advack_handler(FAR struct rpmsg_endpoint *ept,
+                                       FAR void *data, size_t len,
+                                       uint32_t src, FAR void *priv);
+static int sensor_rpmsg_unadv_handler(FAR struct rpmsg_endpoint *ept,
+                                      FAR void *data, size_t len,
+                                      uint32_t src, FAR void *priv);
+static int sensor_rpmsg_sub_handler(FAR struct rpmsg_endpoint *ept,
+                                    FAR void *data, size_t len,
+                                    uint32_t src, FAR void *priv);
+static int sensor_rpmsg_suback_handler(FAR struct rpmsg_endpoint *ept,
+                                       FAR void *data, size_t len,
+                                       uint32_t src, FAR void *priv);
+static int sensor_rpmsg_unsub_handler(FAR struct rpmsg_endpoint *ept,
+                                      FAR void *data, size_t len,
+                                      uint32_t src, FAR void *priv);
+static int sensor_rpmsg_publish_handler(FAR struct rpmsg_endpoint *ept,
+                                        FAR void *data, size_t len,
+                                        uint32_t src, FAR void *priv);
+static int sensor_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept,
+                                      FAR void *data, size_t len,
+                                      uint32_t src, FAR void *priv);
+static int sensor_rpmsg_ioctlack_handler(FAR struct rpmsg_endpoint *ept,
+                                         FAR void *data, size_t len,
+                                         uint32_t src, FAR void *priv);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct sensor_ops_s g_sensor_rpmsg_ops =
+{
+  .open           = sensor_rpmsg_open,
+  .close          = sensor_rpmsg_close,
+  .activate       = sensor_rpmsg_activate,
+  .set_interval   = sensor_rpmsg_set_interval,
+  .batch          = sensor_rpmsg_batch,
+  .selftest       = sensor_rpmsg_selftest,
+  .set_calibvalue = sensor_rpmsg_set_calibvalue,
+  .calibrate      = sensor_rpmsg_calibrate,
+  .control        = sensor_rpmsg_control
+};
+
+static const rpmsg_ept_cb g_sensor_rpmsg_handler[] =
+{
+  [SENSOR_RPMSG_ADVERTISE]     = sensor_rpmsg_adv_handler,
+  [SENSOR_RPMSG_ADVERTISE_ACK] = sensor_rpmsg_advack_handler,
+  [SENSOR_RPMSG_UNADVERTISE]   = sensor_rpmsg_unadv_handler,
+  [SENSOR_RPMSG_SUBSCRIBE]     = sensor_rpmsg_sub_handler,
+  [SENSOR_RPMSG_SUBSCRIBE_ACK] = sensor_rpmsg_suback_handler,
+  [SENSOR_RPMSG_UNSUBSCRIBE]   = sensor_rpmsg_unsub_handler,
+  [SENSOR_RPMSG_PUBLISH]       = sensor_rpmsg_publish_handler,
+  [SENSOR_RPMSG_IOCTL]         = sensor_rpmsg_ioctl_handler,
+  [SENSOR_RPMSG_IOCTL_ACK]     = sensor_rpmsg_ioctlack_handler,
+};
+
+static struct list_node g_devlist = LIST_INITIAL_VALUE(g_devlist);
+static struct list_node g_eptlist = LIST_INITIAL_VALUE(g_eptlist);
+static mutex_t g_lock = MUTEX_INITIALIZER;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static void sensor_rpmsg_advsub_one(FAR struct sensor_rpmsg_dev_s *dev,
+                                    FAR struct rpmsg_endpoint *ept,
+                                    int command)
+{
+  FAR struct sensor_rpmsg_advsub_s *msg;
+  uint32_t space;
+  int len = strlen(dev->path) + 1;
+  int ret;
+
+  msg = rpmsg_get_tx_payload_buffer(ept, &space, true);
+  if (!msg)
+    {
+      snerr("ERROR: advsub:%d get buffer failed:%s\n",
+            command, dev->path);
+      return;
+    }
+
+  msg->command = command;
+  msg->cookie  = (uint64_t)(uintptr_t)dev;
+  msg->nbuffer = dev->lower.nbuffer;
+  memcpy(msg->path, dev->path, len);
+  ret = rpmsg_send_nocopy(ept, msg, sizeof(*msg) + len);
+  if (ret < 0)
+    {
+      snerr("ERROR: advsub:%d rpmsg send failed:%s %d\n",
+            command, dev->path, ret);
+    }
+}
+
+static void sensor_rpmsg_advsub(FAR struct sensor_rpmsg_dev_s *dev,
+                                int command)
+{
+  FAR struct sensor_rpmsg_ept_s *sre;
+
+  /* Broadcast advertise/subscribe message to all ready ept */
+
+  nxmutex_lock(&g_lock);
+  list_for_every_entry(&g_eptlist, sre, struct sensor_rpmsg_ept_s,
+                       node)
+    {
+      sensor_rpmsg_advsub_one(dev, &sre->ept, command);
+    }
+
+  nxmutex_unlock(&g_lock);
+}
+
+static int sensor_rpmsg_ioctl(FAR struct sensor_rpmsg_dev_s *dev,
+                              int cmd, unsigned long arg, size_t len,
+                              bool wait)
+{
+  struct sensor_rpmsg_ioctl_cookie_s cookie;
+  FAR struct sensor_rpmsg_proxy_s *proxy;
+  FAR struct sensor_rpmsg_ioctl_s *msg;
+  uint32_t space;
+  int ret = -ENOTTY;
+
+  if (wait)
+    {
+      cookie.data   = (FAR void *)(uintptr_t)arg;
+      cookie.result = -ENXIO;
+      nxsem_init(&cookie.sem, 0, 0);
+      nxsem_set_protocol(&cookie.sem, SEM_PRIO_NONE);
+    }
+
+  /* All control is always send to own proxy(remote advertisers),
+   * if device doesn't have proxy, it must return -ENOTTY.
+   */
+
+  nxmutex_lock(&dev->lock);
+  list_for_every_entry(&dev->proxylist, proxy,
+                       struct sensor_rpmsg_proxy_s, node)
+    {
+      msg = rpmsg_get_tx_payload_buffer(proxy->ept, &space, true);
+      if (!msg)
+        {
+          ret = -ENOMEM;
+          snerr("ERROR: ioctl get buffer failed:%s\n", dev->path);
+          break;
+        }
+
+      msg->command = SENSOR_RPMSG_IOCTL;
+      msg->cookie  = wait ? (uint64_t)(uintptr_t)&cookie : 0;
+      msg->proxy   = proxy->cookie;
+      msg->request = cmd;
+      msg->arglen  = len;
+      if (len > 0)
+        {
+          memcpy(msg->argbuf, (FAR void *)(uintptr_t)arg, len);
+        }
+      else
+        {
+          msg->arg = arg;
+        }
+
+      ret = rpmsg_send_nocopy(proxy->ept, msg, sizeof(*msg) + len);
+      if (ret < 0)
+        {
+          snerr("ERROR: ioctl rpmsg send failed:%s %d\n", dev->path, ret);
+          break;
+        }
+
+      if (!wait)
+        {
+          continue;
+        }
+
+      nxmutex_unlock(&dev->lock);
+      ret = rpmsg_wait(proxy->ept, &cookie.sem);
+      nxmutex_lock(&dev->lock);
+      if (ret < 0)
+        {
+          snerr("ERROR: ioctl rpmsg wait failed:%s %d\n", dev->path, ret);
+          break;
+        }
+
+      ret = cookie.result;
+      if (ret < 0 && ret != -ENOTTY)
+        {
+          break;
+        }
+    }
+
+  nxmutex_unlock(&dev->lock);
+  if (wait)
+    {
+      nxsem_destroy(&cookie.sem);
+    }
+
+  return ret;
+}
+
+static FAR struct sensor_rpmsg_proxy_s *
+sensor_rpmsg_alloc_proxy(FAR struct sensor_rpmsg_dev_s *dev,
+                         FAR struct rpmsg_endpoint *ept,
+                         uint64_t cookie, uint32_t nbuffer)
+{
+  FAR struct sensor_rpmsg_proxy_s *proxy;
+  struct sensor_state_s state;
+  struct file file;
+  int ret;
+
+  /* Create new proxy to represent a remote advertiser */
+
+  proxy = kmm_malloc(sizeof(*proxy));
+  if (!proxy)
+    {
+      return NULL;
+    }
+
+  proxy->ept = ept;
+  proxy->cookie = cookie;
+  ret = file_open(&file, dev->path, O_REMOTE);
+  if (ret < 0)
+    {
+      kmm_free(proxy);
+      return NULL;
+    }
+
+  file_ioctl(&file, SNIOC_SET_BUFFER_NUMBER, nbuffer);
+  file_ioctl(&file, SNIOC_GET_STATE, &state);
+  file_close(&file);
+
+  nxmutex_lock(&dev->lock);
+  list_add_tail(&dev->proxylist, &proxy->node);
+  nxmutex_unlock(&dev->lock);
+
+  /* sync interval and latency */
+
+  if (state.min_interval != ULONG_MAX)
+    {
+      sensor_rpmsg_ioctl(dev, SNIOC_SET_INTERVAL, state.min_interval,
+                         0, false);
+    }
+
+  if (state.min_latency != ULONG_MAX)
+    {
+      sensor_rpmsg_ioctl(dev, SNIOC_BATCH, state.min_latency, 0, false);
+    }
+
+  return proxy;
+}
+
+static FAR struct sensor_rpmsg_stub_s *
+sensor_rpmsg_alloc_stub(FAR struct sensor_rpmsg_dev_s *dev,
+                        FAR struct rpmsg_endpoint *ept,
+                        uint64_t cookie)
+{
+  FAR struct sensor_rpmsg_stub_s *stub;
+  int ret;
+
+  /* Create new stub to represent a remote subscribers */
+
+  stub = kmm_malloc(sizeof(*stub));
+  if (!stub)
+    {
+      return NULL;
+    }
+
+  stub->ept = ept;
+  stub->cookie = cookie;
+  ret = file_open(&stub->file, dev->path,
+                  O_RDOK | O_NONBLOCK | O_REMOTE);
+  if (ret < 0)
+    {
+      kmm_free(stub);
+      return NULL;
+    }
+
+  file_ioctl(&stub->file, SNIOC_READLAST, false);
+  nxmutex_lock(&dev->lock);
+  list_add_tail(&dev->stublist, &stub->node);
+  nxmutex_unlock(&dev->lock);
+
+  return stub;
+}
+
+static void sensor_rpmsg_free_proxy(FAR struct sensor_rpmsg_proxy_s *proxy)
+{
+  list_delete(&proxy->node);
+  kmm_free(proxy);
+}
+
+static void sensor_rpmsg_free_stub(FAR struct sensor_rpmsg_stub_s *stub)
+{
+  list_delete(&stub->node);
+  file_close(&stub->file);
+  kmm_free(stub);
+}
+
+static int sensor_rpmsg_open(FAR struct file *filep,
+                             FAR struct sensor_lowerhalf_s *lower)
+{
+  FAR struct sensor_rpmsg_dev_s *dev = lower->priv;
+  FAR struct sensor_lowerhalf_s *drv = dev->drv;
+  int ret;
+
+  if (drv->ops->open)
+    {
+      ret = drv->ops->open(filep, drv);
+      if (ret < 0)
+        {
+          return ret;
+        }
+    }
+
+  if (filep->f_oflags & O_REMOTE)
+    {
+      return 0;
+    }
+
+  nxmutex_lock(&dev->lock);
+  if (filep->f_oflags & O_WROK)
+    {
+      if (dev->nadvertisers++ == 0)
+        {
+          sensor_rpmsg_advsub(dev, SENSOR_RPMSG_ADVERTISE);
+        }
+    }
+
+  if (filep->f_oflags & O_RDOK)
+    {
+      if (dev->nsubscribers++ == 0)
+        {
+          sensor_rpmsg_advsub(dev, SENSOR_RPMSG_SUBSCRIBE);
+        }
+    }
+
+  nxmutex_unlock(&dev->lock);
+  return 0;
+}
+
+static int sensor_rpmsg_close(FAR struct file *filep,
+                              FAR struct sensor_lowerhalf_s *lower)
+{
+  FAR struct sensor_rpmsg_dev_s *dev = lower->priv;
+  FAR struct sensor_lowerhalf_s *drv = dev->drv;
+  FAR struct sensor_rpmsg_proxy_s *proxy;
+  FAR struct sensor_rpmsg_proxy_s *ptmp;
+  FAR struct sensor_rpmsg_stub_s *stub;
+  FAR struct sensor_rpmsg_stub_s *stmp;
+  int ret = 0;
+
+  if (drv->ops->close)
+    {
+      ret = drv->ops->close(filep, drv);
+    }
+
+  if (filep->f_oflags & O_REMOTE)
+    {
+      return ret;
+    }
+
+  nxmutex_lock(&dev->lock);
+  if (filep->f_oflags & O_WROK)
+    {
+      if (dev->nadvertisers == 1)
+        {
+          sensor_rpmsg_advsub(dev, SENSOR_RPMSG_UNADVERTISE);
+          list_for_every_entry_safe(&dev->stublist, stub, stmp,
+                                    struct sensor_rpmsg_stub_s, node)
+            {
+              sensor_rpmsg_free_stub(stub);
+            }
+        }
+
+      dev->nadvertisers--;
+    }
+
+  if (filep->f_oflags & O_RDOK)
+    {
+      if (dev->nsubscribers == 1)
+        {
+          sensor_rpmsg_advsub(dev, SENSOR_RPMSG_UNSUBSCRIBE);
+          list_for_every_entry_safe(&dev->proxylist, proxy, ptmp,
+                                    struct sensor_rpmsg_proxy_s, node)
+            {
+              sensor_rpmsg_free_proxy(proxy);
+            }
+        }
+
+      dev->nsubscribers--;
+    }
+
+  nxmutex_unlock(&dev->lock);
+  return ret;
+}
+
+static int sensor_rpmsg_activate(FAR struct file *filep,
+                                  FAR struct sensor_lowerhalf_s *lower,
+                                  bool enable)
+{
+  FAR struct sensor_rpmsg_dev_s *dev = lower->priv;
+  FAR struct sensor_lowerhalf_s *drv = dev->drv;
+
+  if (drv->ops->activate)
+    {
+      return drv->ops->activate(filep, drv, enable);
+    }
+
+  return 0;
+}
+
+SENSOR_RPMSG_FUNCTION(set_interval, SNIOC_SET_INTERVAL,
+                      *interval, interval, 0, false)
+SENSOR_RPMSG_FUNCTION(batch, SNIOC_BATCH, *latency, latency, 0, false)
+SENSOR_RPMSG_FUNCTION(selftest, SNIOC_SELFTEST, arg, arg, 0, true)
+SENSOR_RPMSG_FUNCTION(set_calibvalue, SNIOC_SET_CALIBVALUE,
+                      arg, arg, 256, true)
+SENSOR_RPMSG_FUNCTION(calibrate, SNIOC_CALIBRATE, arg, arg, 256, true)
+
+static int sensor_rpmsg_control(FAR struct file *filep,
+                                FAR struct sensor_lowerhalf_s *lower,
+                                int cmd, unsigned long arg)
+{
+  FAR struct sensor_rpmsg_dev_s *dev = lower->priv;
+  FAR struct sensor_lowerhalf_s *drv = dev->drv;
+  FAR struct sensor_ioctl_s *ioctl = (FAR void *)(uintptr_t)arg;
+
+  if (drv->ops->control)
+    {
+      return drv->ops->control(filep, drv, cmd, arg);
+    }
+  else if (!(filep->f_oflags & O_REMOTE))
+    {
+      return sensor_rpmsg_ioctl(dev, cmd, arg,
+                                sizeof(*ioctl) + ioctl->len, true);
+    }
+
+  return -ENOTTY;
+}
+
+static void sensor_rpmsg_data_worker(FAR void *arg)
+{
+  FAR struct sensor_rpmsg_ept_s *sre = arg;
+
+  nxmutex_lock(&sre->lock);
+  if (sre->buffer)
+    {
+      rpmsg_send_nocopy(&sre->ept, sre->buffer, sre->written);
+      sre->buffer = NULL;
+    }
+
+  nxmutex_unlock(&sre->lock);
+}
+
+static void sensor_rpmsg_push_event_one(FAR struct sensor_rpmsg_dev_s *dev,
+                                        FAR struct sensor_rpmsg_stub_s *stub)
+{
+  FAR struct sensor_rpmsg_cell_s *cell;
+  FAR struct sensor_rpmsg_ept_s *sre;
+  FAR struct sensor_rpmsg_data_s *msg;
+  struct sensor_state_s state;
+  uint64_t now;
+  int ret;
+
+  /* Get state of device to do send data with timeout */
+
+  ret = file_ioctl(&stub->file, SNIOC_GET_STATE, &state);
+  if (ret < 0)
+    {
+      return;
+    }
+
+  if (state.min_interval == ULONG_MAX)
+    {
+      state.min_interval = 0;
+    }
+
+  sre = container_of(stub->ept, struct sensor_rpmsg_ept_s, ept);
+  nxmutex_lock(&sre->lock);
+
+  /* Cancel work to fill new data to buffer */
+
+  if (sre->buffer)
+    {
+      work_cancel(HPWORK, &sre->work);
+    }
+
+  for (; ; )
+    {
+      /* If buffer isn't created or it doesn't have enough space to fill
+       * new data, you should create or send this buffer at once.
+       */
+
+      if (!sre->buffer ||
+          sre->written + sizeof(*cell) + state.esize > sre->space)
+        {
+          if (sre->buffer)
+            {
+              rpmsg_send_nocopy(&sre->ept, sre->buffer, sre->written);
+            }
+
+          msg = rpmsg_get_tx_payload_buffer(&sre->ept, &sre->space, true);
+          sre->buffer = msg;
+          if (!msg)
+            {
+              snerr("ERROR: push event get buffer failed:%s\n",
+                    rpmsg_get_cpuname(sre->ept.rdev));
+              nxmutex_unlock(&sre->lock);
+              return;
+            }
+
+          msg->command = SENSOR_RPMSG_PUBLISH;
+          sre->written = sizeof(*msg);
+          sre->expire  = UINT64_MAX;
+        }
+
+      cell = sre->buffer + sre->written;
+      ret  = file_read(&stub->file, cell->data,
+                       sre->space - sre->written - sizeof(*cell));
+      if (ret <= 0)
+        {
+          break;
+        }
+
+      cell->len     = ret;
+      cell->cookie  = stub->cookie;
+      sre->written += (sizeof(*cell) + ret + 0x7) & ~0x7;
+    }
+
+  /* If buffer timeout is expired, do rpmsg_send_nocopy, otherwise using
+   * delay work to send data.
+   */
+
+  now = sensor_get_timestamp();
+  if (sre->expire <= now)
+    {
+      ret = rpmsg_send_nocopy(&sre->ept, sre->buffer, sre->written);
+      sre->buffer = NULL;
+      if (ret < 0)
+        {
+          snerr("ERROR: push event rpmsg send failed:%s %d\n",
+                rpmsg_get_cpuname(sre->ept.rdev), ret);
+        }
+    }
+  else
+    {
+      if (sre->expire == UINT64_MAX ||
+          sre->expire - now > state.min_interval / 2)
+        {
+          sre->expire = now + state.min_interval / 2;
+        }
+
+      work_queue(HPWORK, &sre->work, sensor_rpmsg_data_worker, sre,
+                 (sre->expire - now) / USEC_PER_TICK);
+    }
+
+  nxmutex_unlock(&sre->lock);
+}
+
+static ssize_t sensor_rpmsg_push_event(FAR void *priv, FAR const void *data,
+                                       size_t bytes)
+{
+  FAR struct sensor_rpmsg_dev_s *dev = priv;
+  FAR struct sensor_rpmsg_stub_s *stub;
+  ssize_t ret;
+
+  /* Push new data to upperhalf driver's circular buffer */
+
+  ret = dev->push_event(dev->upper, data, bytes);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  /* Send new data to own proxy(remote subscribers), don't care whether
+   * is successful, and must return length of written.
+   */
+
+  nxmutex_lock(&dev->lock);
+  list_for_every_entry(&dev->stublist, stub,
+                       struct sensor_rpmsg_stub_s, node)
+    {
+      sensor_rpmsg_push_event_one(dev, stub);
+    }
+
+  nxmutex_unlock(&dev->lock);
+  return ret;
+}
+
+static FAR struct sensor_rpmsg_dev_s *
+sensor_rpmsg_find_dev(FAR const char *path)
+{
+  FAR struct sensor_rpmsg_dev_s *dev;
+
+  nxmutex_lock(&g_lock);
+  list_for_every_entry(&g_devlist, dev, struct sensor_rpmsg_dev_s, node)
+    {
+      if (strcmp(dev->path, path) == 0)
+        {
+          nxmutex_unlock(&g_lock);
+          return dev;
+        }
+    }
+
+  nxmutex_unlock(&g_lock);
+  return NULL;
+}
+
+static int sensor_rpmsg_adv_handler(FAR struct rpmsg_endpoint *ept,
+                                    FAR void *data, size_t len,
+                                    uint32_t src, FAR void *priv)
+{
+  FAR struct sensor_rpmsg_advsub_s *msg = data;
+  FAR struct sensor_rpmsg_proxy_s *proxy;
+  FAR struct sensor_rpmsg_dev_s *dev;
+  int ret;
+
+  dev = sensor_rpmsg_find_dev(msg->path);
+  if (!dev || !dev->nsubscribers)
+    {
+      return 0;
+    }
+
+  proxy = sensor_rpmsg_alloc_proxy(dev, ept, msg->cookie, msg->nbuffer);
+  if (!proxy)
+    {
+      snerr("ERROR: adv alloc proxy failed:%s\n", dev->path);
+    }
+  else
+    {
+      msg->cookie = (uint64_t)(uintptr_t)dev;
+      msg->command = SENSOR_RPMSG_ADVERTISE_ACK;
+      ret = rpmsg_send(ept, msg, len);
+      if (ret < 0)
+        {
+          sensor_rpmsg_free_proxy(proxy);
+          snerr("ERROR: adv rpmsg send failed:%s %d\n", dev->path, ret);
+        }
+    }
+
+  return 0;
+}
+
+static int sensor_rpmsg_advack_handler(FAR struct rpmsg_endpoint *ept,
+                                       FAR void *data, size_t len,
+                                       uint32_t src, FAR void *priv)
+{
+  FAR struct sensor_rpmsg_advsub_s *msg = data;
+  FAR struct sensor_rpmsg_dev_s *dev;
+
+  dev = sensor_rpmsg_find_dev(msg->path);
+  if (dev && (!dev->nadvertisers ||
+      !sensor_rpmsg_alloc_stub(dev, ept, msg->cookie)))
+    {
+      sensor_rpmsg_advsub_one(dev, ept, SENSOR_RPMSG_UNADVERTISE);
+      snerr("ERROR: advack failed:%s\n", dev->path);
+    }
+
+  return 0;
+}
+
+static int sensor_rpmsg_unadv_handler(FAR struct rpmsg_endpoint *ept,
+                                      FAR void *data, size_t len,
+                                      uint32_t src, FAR void *priv)
+{
+  FAR struct sensor_rpmsg_advsub_s *msg = data;
+  FAR struct sensor_rpmsg_proxy_s *proxy;
+  FAR struct sensor_rpmsg_dev_s *dev;
+
+  dev = sensor_rpmsg_find_dev(msg->path);
+  if (!dev)
+    {
+      return 0;
+    }
+
+  nxmutex_lock(&dev->lock);
+  list_for_every_entry(&dev->proxylist, proxy,
+                       struct sensor_rpmsg_proxy_s, node)
+    {
+      if (proxy->ept == ept && proxy->cookie == msg->cookie)
+        {
+          sensor_rpmsg_free_proxy(proxy);
+          break;
+        }
+    }
+
+  nxmutex_unlock(&dev->lock);
+  return 0;
+}
+
+static int sensor_rpmsg_sub_handler(FAR struct rpmsg_endpoint *ept,
+                                    FAR void *data, size_t len,
+                                    uint32_t src, FAR void *priv)
+{
+  FAR struct sensor_rpmsg_advsub_s *msg = data;
+  FAR struct sensor_rpmsg_dev_s *dev;
+  FAR struct sensor_rpmsg_stub_s *stub;
+  int ret;
+
+  dev = sensor_rpmsg_find_dev(msg->path);
+  if (!dev || !dev->nadvertisers)
+    {
+      return 0;
+    }
+
+  stub = sensor_rpmsg_alloc_stub(dev, ept, msg->cookie);
+  if (!stub)
+    {
+      snerr("ERROR: sub alloc stub failed:%s\n", dev->path);
+    }
+  else
+    {
+      msg->cookie  = (uint64_t)(uintptr_t)dev;
+      msg->command = SENSOR_RPMSG_SUBSCRIBE_ACK;
+      msg->nbuffer = dev->lower.nbuffer;
+      ret = rpmsg_send(ept, msg, len);
+      if (ret < 0)
+        {
+          sensor_rpmsg_free_stub(stub);
+          snerr("ERROR: sub rpmsg send failed:%s %d\n", dev->path, ret);
+        }
+    }
+
+  return 0;
+}
+
+static int sensor_rpmsg_suback_handler(FAR struct rpmsg_endpoint *ept,
+                                       FAR void *data, size_t len,
+                                       uint32_t src, FAR void *priv)
+{
+  FAR struct sensor_rpmsg_advsub_s *msg = data;
+  FAR struct sensor_rpmsg_dev_s *dev;
+
+  dev = sensor_rpmsg_find_dev(msg->path);
+  if (dev && (!dev->nsubscribers ||
+      !sensor_rpmsg_alloc_proxy(dev, ept, msg->cookie, msg->nbuffer)))
+    {
+      sensor_rpmsg_advsub_one(dev, ept, SENSOR_RPMSG_UNSUBSCRIBE);
+      snerr("ERROR: suback failed:%s\n", dev->path);
+    }
+
+  return 0;
+}
+
+static int sensor_rpmsg_unsub_handler(FAR struct rpmsg_endpoint *ept,
+                                      FAR void *data, size_t len,
+                                      uint32_t src, FAR void *priv)
+{
+  FAR struct sensor_rpmsg_advsub_s *msg = data;
+  FAR struct sensor_rpmsg_dev_s *dev;
+  FAR struct sensor_rpmsg_stub_s *stub;
+
+  dev = sensor_rpmsg_find_dev(msg->path);
+  if (!dev)
+    {
+      return 0;
+    }
+
+  nxmutex_lock(&dev->lock);
+  list_for_every_entry(&dev->stublist, stub,
+                       struct sensor_rpmsg_stub_s, node)
+    {
+      if (stub->ept == ept && stub->cookie == msg->cookie)
+        {
+          sensor_rpmsg_free_stub(stub);
+          break;
+        }
+    }
+
+  nxmutex_unlock(&dev->lock);
+  return 0;
+}
+
+static int sensor_rpmsg_publish_handler(FAR struct rpmsg_endpoint *ept,
+                                        FAR void *data, size_t len,
+                                        uint32_t src, FAR void *priv)
+{
+  FAR struct sensor_rpmsg_data_s *msg = data;
+  FAR struct sensor_rpmsg_cell_s *cell;
+  FAR struct sensor_rpmsg_dev_s *dev;
+  size_t written = sizeof(*msg);
+
+  while (written < len)
+    {
+      cell = (FAR struct sensor_rpmsg_cell_s *)
+             ((FAR char *)data + written);
+      dev = (FAR struct sensor_rpmsg_dev_s *)(uintptr_t)cell->cookie;
+      dev->push_event(dev->upper, cell->data, cell->len);
+      written += sizeof(*cell) + cell->len + 0x7;
+      written &= ~0x7;
+    }
+
+  return 0;
+}
+
+static int sensor_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept,
+                                      FAR void *data, size_t len,
+                                      uint32_t src, FAR void *priv)
+{
+  FAR struct sensor_rpmsg_ioctl_s *msg = data;
+  FAR struct sensor_rpmsg_stub_s *stub;
+  FAR struct sensor_rpmsg_dev_s *dev;
+  unsigned long arg;
+  int ret;
+
+  arg = msg->arglen > 0 ? (unsigned long)(uintptr_t)msg->argbuf :
+                          msg->arg;
+  dev = (FAR struct sensor_rpmsg_dev_s *)(uintptr_t)msg->proxy;
+  nxmutex_lock(&dev->lock);
+  list_for_every_entry(&dev->stublist, stub,
+                       struct sensor_rpmsg_stub_s, node)
+    {
+      if (stub->ept == ept)
+        {
+          msg->result = file_ioctl(&stub->file, msg->request, arg);
+          if (msg->cookie)
+            {
+              msg->command = SENSOR_RPMSG_IOCTL_ACK;
+              ret = rpmsg_send(ept, msg, len);
+              if (ret < 0)
+                {
+                  snerr("ERROR: ioctl rpmsg send failed:%s %d\n",
+                        dev->path, ret);
+                }
+            }
+        }
+    }
+
+  nxmutex_unlock(&dev->lock);
+  return 0;
+}
+
+static int sensor_rpmsg_ioctlack_handler(FAR struct rpmsg_endpoint *ept,
+                                         FAR void *data, size_t len,
+                                         uint32_t src, FAR void *priv)
+{
+  FAR struct sensor_rpmsg_ioctl_cookie_s *cookie;
+  FAR struct sensor_rpmsg_ioctl_s *msg = data;
+
+  cookie = (FAR struct sensor_rpmsg_ioctl_cookie_s *)
+           (uintptr_t)msg->cookie;
+  cookie->result = msg->result;
+  if (msg->result >= 0 && msg->arglen > 0)
+    {
+      memcpy(cookie->data, msg->argbuf, msg->arglen);
+    }
+
+  rpmsg_post(ept, &cookie->sem);
+  return 0;
+}
+
+static int sensor_rpmsg_ept_cb(FAR struct rpmsg_endpoint *ept,
+                               FAR void *data, size_t len, uint32_t src,
+                               FAR void *priv)
+{
+  FAR struct sensor_rpmsg_advsub_s *msg = data;
+
+  if (msg->command < sizeof(g_sensor_rpmsg_handler) /
+                     sizeof(g_sensor_rpmsg_handler[0]))
+    {
+      return g_sensor_rpmsg_handler[msg->command](ept, data, len, src, priv);
+    }
+
+  return -EINVAL;
+}
+
+static void sensor_rpmsg_ns_unbind_cb(FAR struct rpmsg_endpoint *ept)
+{
+  FAR struct sensor_rpmsg_ept_s *sre;
+  FAR struct sensor_rpmsg_dev_s *dev;
+  FAR struct sensor_rpmsg_stub_s *stub;
+  FAR struct sensor_rpmsg_stub_s *stmp;
+  FAR struct sensor_rpmsg_proxy_s *proxy;
+  FAR struct sensor_rpmsg_proxy_s *ptmp;
+
+  sre = container_of(ept, struct sensor_rpmsg_ept_s, ept);
+
+  /* Remove all proxy and stub info in sensor device with the ept
+   * destoryed.
+   */
+
+  nxmutex_lock(&g_lock);
+  list_for_every_entry(&g_devlist, dev,
+                       struct sensor_rpmsg_dev_s, node)
+    {
+      nxmutex_lock(&dev->lock);
+      list_for_every_entry_safe(&dev->proxylist, proxy, ptmp,
+                                struct sensor_rpmsg_proxy_s, node)
+        {
+          if (proxy->ept == ept)
+            {
+              sensor_rpmsg_free_proxy(proxy);
+            }
+        }
+
+      list_for_every_entry_safe(&dev->stublist, stub, stmp,
+                                struct sensor_rpmsg_stub_s, node)
+        {
+          if (stub->ept == ept)
+            {
+              sensor_rpmsg_free_stub(stub);
+            }
+        }
+
+      nxmutex_unlock(&dev->lock);
+    }
+
+  list_delete(&sre->node);
+  nxmutex_unlock(&g_lock);
+  rpmsg_destroy_ept(ept);
+  nxmutex_destroy(&sre->lock);
+  kmm_free(sre);
+}
+
+static void sensor_rpmsg_device_ns_bound(FAR struct rpmsg_endpoint *ept)
+{
+  FAR struct sensor_rpmsg_ept_s *sre;
+  FAR struct sensor_rpmsg_dev_s *dev;
+
+  sre = container_of(ept, struct sensor_rpmsg_ept_s, ept);
+
+  nxmutex_lock(&g_lock);
+  list_add_tail(&g_eptlist, &sre->node);
+
+  /* Broadcast all device to ready ept */
+
+  list_for_every_entry(&g_devlist, dev,
+                       struct sensor_rpmsg_dev_s, node)
+    {
+      nxmutex_lock(&dev->lock);
+      if (dev->nadvertisers > 0)
+        {
+          sensor_rpmsg_advsub_one(dev, ept, SENSOR_RPMSG_ADVERTISE);
+        }
+
+      if (dev->nsubscribers > 0)
+        {
+          sensor_rpmsg_advsub_one(dev, ept, SENSOR_RPMSG_SUBSCRIBE);
+        }
+
+      nxmutex_unlock(&dev->lock);
+    }
+
+  nxmutex_unlock(&g_lock);
+}
+
+static void sensor_rpmsg_device_created(FAR struct rpmsg_device *rdev,
+                                        FAR void *priv)
+{
+  FAR struct sensor_rpmsg_ept_s *sre;
+
+  sre = kmm_zalloc(sizeof(*sre));
+  if (!sre)
+    {
+      return;
+    }
+
+  sre->rdev = rdev;
+  sre->ept.priv = sre;
+  nxmutex_init(&sre->lock);
+  sre->ept.ns_bound_cb = sensor_rpmsg_device_ns_bound;
+  if (rpmsg_create_ept(&sre->ept, rdev, SENSOR_RPMSG_EPT_NAME,
+                       RPMSG_ADDR_ANY, RPMSG_ADDR_ANY,
+                       sensor_rpmsg_ept_cb,
+                       sensor_rpmsg_ns_unbind_cb) < 0)
+    {
+      nxmutex_destroy(&sre->lock);
+      kmm_free(sre);
+    }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: sensor_rpmsg_register
+ *
+ * Description:
+ *   This function registers rpmsg takeover for the real lower half, and
+ *   initialize rpmsg resource.
+ *
+ * Input Parameters:
+ *   lower - The instance of lower half sensor driver.
+ *   path  - The path of character node, ex: /dev/sensor/xxx.
+ *
+ * Returned Value:
+ *   The takeover rpmsg lowerhalf returned on success, NULL on failure.
+ ****************************************************************************/
+
+FAR struct sensor_lowerhalf_s *
+sensor_rpmsg_register(FAR struct sensor_lowerhalf_s *lower,
+                      FAR const char *path)
+{
+  FAR struct sensor_rpmsg_ept_s *sre;
+  FAR struct sensor_rpmsg_dev_s *dev;
+
+  if (lower->ops->fetch)
+    {
+      return lower;
+    }
+
+  dev = kmm_zalloc(sizeof(*dev) + strlen(path));
+  if (!dev)
+    {
+      return NULL;
+    }
+
+  /* Initialize the sensor rpmsg device structure */
+
+  list_initialize(&dev->stublist);
+  list_initialize(&dev->proxylist);
+  nxmutex_init(&dev->lock);
+  strcpy(dev->path, path);
+
+  dev->push_event     = lower->push_event;
+  dev->upper          = lower->priv;
+  lower->push_event   = sensor_rpmsg_push_event;
+  lower->priv         = dev;
+  memcpy(&dev->lower, lower, sizeof(*lower));
+  dev->lower.ops      = &g_sensor_rpmsg_ops;
+  dev->drv            = lower;
+
+  /* If openamp is ready, send advertisement to remote proc */
+
+  nxmutex_lock(&g_lock);
+  list_add_tail(&g_devlist, &dev->node);
+  if (lower->ops->activate)
+    {
+      dev->nadvertisers = 1;
+      list_for_every_entry(&g_eptlist, sre, struct sensor_rpmsg_ept_s,
+                           node)
+        {
+          sensor_rpmsg_advsub_one(dev, &sre->ept, SENSOR_RPMSG_ADVERTISE);
+        }
+    }
+
+  nxmutex_unlock(&g_lock);
+
+  return &dev->lower;
+}
+
+/****************************************************************************
+ * Name: sensor_rpmsg_unregister
+ *
+ * Description:
+ *   This function unregisters rpmsg takeover for the real lower half, and
+ *   release rpmsg resource. This API corresponds to sensor_rpmsg_register.
+ *
+ * Input Parameters:
+ *   lower - The instance of lower half sensor driver.
+ ****************************************************************************/
+
+void sensor_rpmsg_unregister(FAR struct sensor_lowerhalf_s *lower)
+{
+  FAR struct sensor_rpmsg_dev_s *dev = lower->priv;
+
+  if (lower->ops != &g_sensor_rpmsg_ops)
+    {
+      return;
+    }
+
+  nxmutex_lock(&g_lock);
+  list_delete(&dev->node);
+  nxmutex_unlock(&g_lock);
+
+  nxmutex_destroy(&dev->lock);
+  kmm_free(dev);
+}
+
+/****************************************************************************
+ * Name: sensor_rpmsg_initialize
+ *
+ * Description:
+ *   This function initializes the context of sensor rpmsg, registers
+ *   rpmsg callback and prepares enviroment to intercat with remote sensor.
+ *
+ * Returned Value:
+ *   OK on success; A negated errno value is returned on any failure.
+ ****************************************************************************/
+
+int sensor_rpmsg_initialize(void)
+{
+  return rpmsg_register_callback(NULL, sensor_rpmsg_device_created,
+                                 NULL, NULL);
+}
diff --git a/include/nuttx/sensors/sensor.h b/include/nuttx/sensors/sensor.h
index 0658d5c788..ef0f2442a3 100644
--- a/include/nuttx/sensors/sensor.h
+++ b/include/nuttx/sensors/sensor.h
@@ -857,6 +857,11 @@ struct sensor_ops_s
  * Sensor driver.
  */
 
+typedef CODE ssize_t (*sensor_push_event_t)(FAR void *priv,
+                                            FAR const void *data,
+                                            size_t bytes);
+typedef CODE void (*sensor_notify_event_t)(FAR void *priv);
+
 struct sensor_lowerhalf_s
 {
   /* The type of sensor device */
@@ -908,8 +913,7 @@ struct sensor_lowerhalf_s
        *   A negated errno value is returned on any failure.
        **********************************************************************/
 
-      CODE ssize_t (*push_event)(FAR void *priv, FAR const void *data,
-                                 size_t bytes);
+      sensor_push_event_t push_event;
 
       /**********************************************************************
        * Name: notify_event
@@ -925,7 +929,7 @@ struct sensor_lowerhalf_s
        *   priv   - Upper half driver handle
        **********************************************************************/
 
-      CODE void (*notify_event)(FAR void *priv);
+      sensor_notify_event_t notify_event;
     };
 
   /* The private opaque pointer to be passed to upper-layer during callback */
@@ -1084,6 +1088,58 @@ void sensor_custom_unregister(FAR struct sensor_lowerhalf_s *dev,
 int usensor_initialize(void);
 #endif
 
+/****************************************************************************
+ * Name: sensor_rpmsg_register
+ *
+ * Description:
+ *   This function registers rpmsg takeover for the real lower half, and
+ *   initialize rpmsg resource.
+ *
+ * Input Parameters:
+ *   lower - The instance of lower half sensor driver.
+ *   path  - The path of character node, ex: /dev/sensor/xxx.
+ *
+ * Returned Value:
+ *   The takeover rpmsg lowerhalf returned on success, NULL on failure.
+ ****************************************************************************/
+
+#ifdef CONFIG_SENSORS_RPMSG
+FAR struct sensor_lowerhalf_s *sensor_rpmsg_register(
+                                       FAR struct sensor_lowerhalf_s *lower,
+                                       FAR const char *path);
+#endif
+
+/****************************************************************************
+ * Name: sensor_rpmsg_unregister
+ *
+ * Description:
+ *   This function unregisters rpmsg takeover for the real lower half, and
+ *   release rpmsg resource. This API corresponds to the
+ *   sensor_rpmsg_register.
+ *
+ * Input Parameters:
+ *   lower - The instance of lower half sensor driver.
+ ****************************************************************************/
+
+#ifdef CONFIG_SENSORS_RPMSG
+void sensor_rpmsg_unregister(FAR struct sensor_lowerhalf_s *lower);
+#endif
+
+/****************************************************************************
+ * Name: sensor_rpmsg_initialize
+ *
+ * Description:
+ *   This function initializes the context of sensor rpmsg, registers
+ *   rpmsg callback and prepares enviroment to intercat with remote sensor.
+ *
+ * Returned Value:
+ *   OK on success; A negated errno value is returned on any failure.
+ ****************************************************************************/
+
+#ifdef CONFIG_SENSORS_RPMSG
+int sensor_rpmsg_initialize(void);
+#endif
+
 #undef EXTERN
 #if defined(__cplusplus)
 }


[incubator-nuttx] 07/22: driver/sensor: support sensor data persist

Posted by xi...@apache.org.
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 fa4cebce32e477590bd6c643807e71487436d5f5
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Sat May 21 17:50:29 2022 +0800

    driver/sensor: support sensor data persist
    
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 drivers/sensors/sensor.c       | 29 +++++++++++++++++--
 drivers/sensors/sensor_rpmsg.c | 63 +++++++++++++++++++++++++++++++-----------
 drivers/sensors/usensor.c      |  1 +
 include/nuttx/sensors/sensor.h | 17 ++++++++++++
 4 files changed, 92 insertions(+), 18 deletions(-)

diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index 93fba9e504..89b47813ba 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -426,11 +426,23 @@ static int sensor_open(FAR struct file *filep)
   if (filep->f_oflags & O_WROK)
     {
       upper->state.nadvertisers++;
+      if (filep->f_oflags & SENSOR_PERSIST)
+        {
+          lower->persist = true;
+        }
+    }
+
+  if (upper->state.generation && lower->persist)
+    {
+      user->generation = upper->state.generation - 1;
+    }
+  else
+    {
+      user->generation = upper->state.generation;
     }
 
   user->interval   = ULONG_MAX;
   user->latency    = ULONG_MAX;
-  user->generation = upper->state.generation;
   user->readlast   = true;
   nxsem_init(&user->buffersem, 0, 0);
   nxsem_set_protocol(&user->buffersem, SEM_PRIO_NONE);
@@ -556,9 +568,22 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
               goto out;
             }
 
+          /* If the device data is persistent, and when the device has no
+           * new data, the user can copy the old data, otherwise return
+           * -ENODATA.
+           */
+
           if (user->generation == upper->state.generation)
             {
-              user->generation--;
+              if (lower->persist)
+                {
+                  user->generation--;
+                }
+              else
+                {
+                  ret = -ENODATA;
+                  goto out;
+                }
             }
         }
       else
diff --git a/drivers/sensors/sensor_rpmsg.c b/drivers/sensors/sensor_rpmsg.c
index 1b2a1176cd..58ba632c7d 100644
--- a/drivers/sensors/sensor_rpmsg.c
+++ b/drivers/sensors/sensor_rpmsg.c
@@ -37,8 +37,6 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
-#define O_REMOTE                   (1 << 31)
-
 #define SENSOR_RPMSG_EPT_NAME      "rpmsg-sensor"
 #define SENSOR_RPMSG_ADVERTISE     0
 #define SENSOR_RPMSG_ADVERTISE_ACK 1
@@ -63,7 +61,7 @@ static int sensor_rpmsg_##name(FAR struct file *filep, \
     { \
       return drv->ops->name(filep, drv, arg2); \
     } \
-  else if (!(filep->f_oflags & O_REMOTE)) \
+  else if (!(filep->f_oflags & SENSOR_REMOTE)) \
     { \
       ret = sensor_rpmsg_ioctl(dev, cmd, arg1, size, wait); \
       return wait ? ret : 0; \
@@ -140,6 +138,7 @@ struct sensor_rpmsg_advsub_s
   uint32_t                       command;
   uint32_t                       nbuffer;
   uint64_t                       cookie;
+  uint32_t                       persist;
   char                           path[1];
 };
 
@@ -245,6 +244,8 @@ static int sensor_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept,
 static int sensor_rpmsg_ioctlack_handler(FAR struct rpmsg_endpoint *ept,
                                          FAR void *data, size_t len,
                                          uint32_t src, FAR void *priv);
+static void sensor_rpmsg_push_event_one(FAR struct sensor_rpmsg_dev_s *dev,
+                                       FAR struct sensor_rpmsg_stub_s *stub);
 
 /****************************************************************************
  * Private Data
@@ -304,6 +305,7 @@ static void sensor_rpmsg_advsub_one(FAR struct sensor_rpmsg_dev_s *dev,
   msg->command = command;
   msg->cookie  = (uint64_t)(uintptr_t)dev;
   msg->nbuffer = dev->lower.nbuffer;
+  msg->persist = dev->lower.persist;
   memcpy(msg->path, dev->path, len);
   ret = rpmsg_send_nocopy(ept, msg, sizeof(*msg) + len);
   if (ret < 0)
@@ -418,13 +420,22 @@ static int sensor_rpmsg_ioctl(FAR struct sensor_rpmsg_dev_s *dev,
 static FAR struct sensor_rpmsg_proxy_s *
 sensor_rpmsg_alloc_proxy(FAR struct sensor_rpmsg_dev_s *dev,
                          FAR struct rpmsg_endpoint *ept,
-                         uint64_t cookie, uint32_t nbuffer)
+                         FAR struct sensor_rpmsg_advsub_s *msg)
 {
   FAR struct sensor_rpmsg_proxy_s *proxy;
   struct sensor_state_s state;
   struct file file;
   int ret;
 
+  list_for_every_entry(&dev->proxylist, proxy,
+                       struct sensor_rpmsg_proxy_s, node)
+    {
+      if (proxy->ept == ept && proxy->cookie == msg->cookie)
+        {
+          return proxy;
+        }
+    }
+
   /* Create new proxy to represent a remote advertiser */
 
   proxy = kmm_malloc(sizeof(*proxy));
@@ -434,19 +445,25 @@ sensor_rpmsg_alloc_proxy(FAR struct sensor_rpmsg_dev_s *dev,
     }
 
   proxy->ept = ept;
-  proxy->cookie = cookie;
-  ret = file_open(&file, dev->path, O_REMOTE);
+  proxy->cookie = msg->cookie;
+  ret = file_open(&file, dev->path, SENSOR_REMOTE);
   if (ret < 0)
     {
       kmm_free(proxy);
       return NULL;
     }
 
-  file_ioctl(&file, SNIOC_SET_BUFFER_NUMBER, nbuffer);
+  file_ioctl(&file, SNIOC_SET_BUFFER_NUMBER, msg->nbuffer);
   file_ioctl(&file, SNIOC_GET_STATE, &state);
   file_close(&file);
 
   nxmutex_lock(&dev->lock);
+  if (msg->persist)
+    {
+      dev->drv->persist = true;
+      dev->lower.persist = true;
+    }
+
   list_add_tail(&dev->proxylist, &proxy->node);
   nxmutex_unlock(&dev->lock);
 
@@ -474,6 +491,15 @@ sensor_rpmsg_alloc_stub(FAR struct sensor_rpmsg_dev_s *dev,
   FAR struct sensor_rpmsg_stub_s *stub;
   int ret;
 
+  list_for_every_entry(&dev->stublist, stub,
+                       struct sensor_rpmsg_stub_s, node)
+    {
+      if (stub->ept == ept && stub->cookie == cookie)
+        {
+          return stub;
+        }
+    }
+
   /* Create new stub to represent a remote subscribers */
 
   stub = kmm_malloc(sizeof(*stub));
@@ -485,7 +511,7 @@ sensor_rpmsg_alloc_stub(FAR struct sensor_rpmsg_dev_s *dev,
   stub->ept = ept;
   stub->cookie = cookie;
   ret = file_open(&stub->file, dev->path,
-                  O_RDOK | O_NONBLOCK | O_REMOTE);
+                  O_RDOK | O_NONBLOCK | SENSOR_REMOTE);
   if (ret < 0)
     {
       kmm_free(stub);
@@ -497,6 +523,11 @@ sensor_rpmsg_alloc_stub(FAR struct sensor_rpmsg_dev_s *dev,
   list_add_tail(&dev->stublist, &stub->node);
   nxmutex_unlock(&dev->lock);
 
+  if (dev->lower.persist)
+    {
+      sensor_rpmsg_push_event_one(dev, stub);
+    }
+
   return stub;
 }
 
@@ -529,7 +560,7 @@ static int sensor_rpmsg_open(FAR struct file *filep,
         }
     }
 
-  if (filep->f_oflags & O_REMOTE)
+  if (filep->f_oflags & SENSOR_REMOTE)
     {
       return 0;
     }
@@ -571,7 +602,7 @@ static int sensor_rpmsg_close(FAR struct file *filep,
       ret = drv->ops->close(filep, drv);
     }
 
-  if (filep->f_oflags & O_REMOTE)
+  if (filep->f_oflags & SENSOR_REMOTE)
     {
       return ret;
     }
@@ -646,7 +677,7 @@ static int sensor_rpmsg_control(FAR struct file *filep,
     {
       return drv->ops->control(filep, drv, cmd, arg);
     }
-  else if (!(filep->f_oflags & O_REMOTE) && _SNIOCVALID(cmd))
+  else if (!(filep->f_oflags & SENSOR_REMOTE) && _SNIOCVALID(cmd))
     {
       return sensor_rpmsg_ioctl(dev, cmd, arg,
                                 sizeof(*ioctl) + ioctl->len, true);
@@ -838,7 +869,7 @@ static int sensor_rpmsg_adv_handler(FAR struct rpmsg_endpoint *ept,
       return 0;
     }
 
-  proxy = sensor_rpmsg_alloc_proxy(dev, ept, msg->cookie, msg->nbuffer);
+  proxy = sensor_rpmsg_alloc_proxy(dev, ept, msg);
   if (!proxy)
     {
       snerr("ERROR: adv alloc proxy failed:%s\n", dev->path);
@@ -866,8 +897,7 @@ static int sensor_rpmsg_advack_handler(FAR struct rpmsg_endpoint *ept,
   FAR struct sensor_rpmsg_dev_s *dev;
 
   dev = sensor_rpmsg_find_dev(msg->path);
-  if (dev && (!dev->nadvertisers ||
-      !sensor_rpmsg_alloc_stub(dev, ept, msg->cookie)))
+  if (dev && !sensor_rpmsg_alloc_stub(dev, ept, msg->cookie))
     {
       sensor_rpmsg_advsub_one(dev, ept, SENSOR_RPMSG_UNADVERTISE);
       snerr("ERROR: advack failed:%s\n", dev->path);
@@ -915,7 +945,7 @@ static int sensor_rpmsg_sub_handler(FAR struct rpmsg_endpoint *ept,
   int ret;
 
   dev = sensor_rpmsg_find_dev(msg->path);
-  if (!dev || !dev->nadvertisers)
+  if (!dev)
     {
       return 0;
     }
@@ -930,6 +960,7 @@ static int sensor_rpmsg_sub_handler(FAR struct rpmsg_endpoint *ept,
       msg->cookie  = (uint64_t)(uintptr_t)dev;
       msg->command = SENSOR_RPMSG_SUBSCRIBE_ACK;
       msg->nbuffer = dev->lower.nbuffer;
+      msg->persist = dev->lower.persist;
       ret = rpmsg_send(ept, msg, len);
       if (ret < 0)
         {
@@ -950,7 +981,7 @@ static int sensor_rpmsg_suback_handler(FAR struct rpmsg_endpoint *ept,
 
   dev = sensor_rpmsg_find_dev(msg->path);
   if (dev && (!dev->nsubscribers ||
-      !sensor_rpmsg_alloc_proxy(dev, ept, msg->cookie, msg->nbuffer)))
+      !sensor_rpmsg_alloc_proxy(dev, ept, msg)))
     {
       sensor_rpmsg_advsub_one(dev, ept, SENSOR_RPMSG_UNSUBSCRIBE);
       snerr("ERROR: suback failed:%s\n", dev->path);
diff --git a/drivers/sensors/usensor.c b/drivers/sensors/usensor.c
index ef203b51f4..a011b9a7f2 100644
--- a/drivers/sensors/usensor.c
+++ b/drivers/sensors/usensor.c
@@ -105,6 +105,7 @@ static int usensor_register(FAR struct usensor_context_s *usensor,
     }
 
   lower->driver.nbuffer = info->nbuffer;
+  lower->driver.persist = info->persist;
   lower->driver.ops = &g_usensor_ops;
   strcpy(lower->path, info->path);
   ret = sensor_custom_register(&lower->driver, lower->path, info->esize);
diff --git a/include/nuttx/sensors/sensor.h b/include/nuttx/sensors/sensor.h
index ef0f2442a3..35172a6080 100644
--- a/include/nuttx/sensors/sensor.h
+++ b/include/nuttx/sensors/sensor.h
@@ -293,6 +293,11 @@
 
 #define SENSOR_TYPE_COUNT                           33
 
+/* The additional sensor open flags */
+
+#define SENSOR_REMOTE                               (1 << 31)
+#define SENSOR_PERSIST                              (1 << 30)
+
 /****************************************************************************
  * Inline Functions
  ****************************************************************************/
@@ -935,6 +940,12 @@ struct sensor_lowerhalf_s
   /* The private opaque pointer to be passed to upper-layer during callback */
 
   FAR void *priv;
+
+  /* The flag is used to indicate that the validity of sensor data is
+   * persistent, such as battery status information, switch information, etc.
+   */
+
+  bool persist;
 };
 
 /* This structure describes the state for the sensor device */
@@ -959,6 +970,12 @@ struct sensor_reginfo_s
   FAR const char *path;        /* The path of user sensor */
   unsigned long   esize;       /* The element size of user sensor */
   unsigned long   nbuffer;     /* The number of queue buffered elements */
+
+  /* The flag is used to indicate that the validity of sensor data
+   * is persistent.
+   */
+
+  bool            persist;
 };
 #endif
 


[incubator-nuttx] 14/22: driver/sensor: update batch initial value

Posted by xi...@apache.org.
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 01254de1bf105f86a568ce302e5a53b54b065324
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Wed Jun 15 12:17:51 2022 +0800

    driver/sensor: update batch initial value
    
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 drivers/sensors/sensor.c | 68 +++++++++++++++++++++++++++++-------------------
 1 file changed, 41 insertions(+), 27 deletions(-)

diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index fb22d1c855..45b67b011a 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -206,6 +206,8 @@ static int sensor_update_interval(FAR struct file *filep,
   FAR struct sensor_lowerhalf_s *lower = upper->lower;
   FAR struct sensor_user_s *tmp;
   unsigned long min_interval = interval;
+  unsigned long min_latency = interval != ULONG_MAX ?
+                              user->latency : ULONG_MAX;
   int ret = 0;
 
   if (interval == user->interval)
@@ -213,14 +215,9 @@ static int sensor_update_interval(FAR struct file *filep,
       return 0;
     }
 
-  if (interval <= upper->state.min_interval)
-    {
-      goto update;
-    }
-
   list_for_every_entry(&upper->userlist, tmp, struct sensor_user_s, node)
     {
-      if (tmp == user)
+      if (tmp == user || tmp->interval == ULONG_MAX)
         {
           continue;
         }
@@ -229,26 +226,39 @@ static int sensor_update_interval(FAR struct file *filep,
         {
           min_interval = tmp->interval;
         }
-    }
 
-update:
-  if (min_interval == upper->state.min_interval)
-    {
-      user->interval = interval;
-      return ret;
+      if (min_latency > tmp->latency)
+        {
+          min_latency = tmp->latency;
+        }
     }
 
-  if (min_interval != ULONG_MAX && lower->ops->set_interval)
+  if (lower->ops->set_interval)
     {
-      ret = lower->ops->set_interval(lower, filep, &min_interval);
-      if (ret < 0)
+      if (min_interval != ULONG_MAX &&
+          min_interval != upper->state.min_interval)
         {
-          return ret;
+          ret = lower->ops->set_interval(lower, filep, &min_interval);
+          if (ret < 0)
+            {
+              return ret;
+            }
+        }
+
+      if (min_latency == ULONG_MAX)
+        {
+          min_latency = 0;
         }
 
-      if (upper->state.min_latency != ULONG_MAX)
+      if (lower->ops->batch &&
+          (min_latency != upper->state.min_latency ||
+          (min_interval != upper->state.min_interval && min_latency)))
         {
-          lower->ops->batch(filep, lower, &upper->state.min_latency);
+          ret = lower->ops->batch(lower, filep, &min_latency);
+          if (ret >= 0)
+            {
+              upper->state.min_latency = min_latency;
+            }
         }
     }
 
@@ -268,13 +278,14 @@ static int sensor_update_latency(FAR struct file *filep,
   unsigned long min_latency = latency;
   int ret = 0;
 
-  if (upper->state.min_interval == 0)
+  if (latency == user->latency)
     {
-      return -EINVAL;
+      return 0;
     }
 
-  if (latency == user->latency)
+  if (user->interval == ULONG_MAX)
     {
+      user->latency = latency;
       return 0;
     }
 
@@ -285,7 +296,7 @@ static int sensor_update_latency(FAR struct file *filep,
 
   list_for_every_entry(&upper->userlist, tmp, struct sensor_user_s, node)
     {
-      if (tmp == user)
+      if (tmp == user || tmp->interval == ULONG_MAX)
         {
           continue;
         }
@@ -297,13 +308,18 @@ static int sensor_update_latency(FAR struct file *filep,
     }
 
 update:
+  if (min_latency == ULONG_MAX)
+    {
+      min_latency = 0;
+    }
+
   if (min_latency == upper->state.min_latency)
     {
       user->latency = latency;
       return ret;
     }
 
-  if (min_latency != ULONG_MAX && lower->ops->batch)
+  if (lower->ops->batch)
     {
       ret = lower->ops->batch(lower, filep, &min_latency);
       if (ret < 0)
@@ -413,9 +429,8 @@ static int sensor_open(FAR struct file *filep)
       user->generation = upper->state.generation;
     }
 
-  user->interval   = ULONG_MAX;
-  user->latency    = ULONG_MAX;
-  user->readlast   = true;
+  user->interval = ULONG_MAX;
+  user->readlast = true;
   nxsem_init(&user->buffersem, 0, 0);
   nxsem_set_protocol(&user->buffersem, SEM_PRIO_NONE);
   list_add_tail(&upper->userlist, &user->node);
@@ -993,7 +1008,6 @@ int sensor_custom_register(FAR struct sensor_lowerhalf_s *lower,
   list_initialize(&upper->userlist);
   upper->state.esize = esize;
   upper->state.min_interval = ULONG_MAX;
-  upper->state.min_latency = ULONG_MAX;
   if (lower->ops->activate)
     {
       upper->state.nadvertisers = 1;


[incubator-nuttx] 21/22: driver/sensor: fix rpmsg send failed when buffer is NULL

Posted by xi...@apache.org.
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 ad20bd4bb35361a633169dec4557811b38197742
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Wed Jun 29 17:34:55 2022 +0800

    driver/sensor: fix rpmsg send failed when buffer is NULL
    
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 drivers/sensors/sensor.c       | 76 ++++++++++++++++++++++++------------------
 drivers/sensors/sensor_rpmsg.c | 14 ++++----
 include/nuttx/sensors/ioctl.h  |  7 ++++
 include/nuttx/sensors/sensor.h | 10 ++++++
 4 files changed, 67 insertions(+), 40 deletions(-)

diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index cd8b06eccc..6e793801af 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -84,9 +84,7 @@ struct sensor_user_s
    * appear in dual role
    */
 
-  unsigned long    generation; /* Last generation subscriber has seen */
-  unsigned long    interval;   /* The interval for subscriber */
-  unsigned long    latency;    /* The bactch latency for subscriber */
+  struct sensor_ustate_s state;
 };
 
 /* This structure describes the state of the upper half driver */
@@ -200,29 +198,29 @@ static int sensor_update_interval(FAR struct file *filep,
   FAR struct sensor_user_s *tmp;
   unsigned long min_interval = interval;
   unsigned long min_latency = interval != ULONG_MAX ?
-                              user->latency : ULONG_MAX;
+                              user->state.latency : ULONG_MAX;
   int ret = 0;
 
-  if (interval == user->interval)
+  if (interval == user->state.interval)
     {
       return 0;
     }
 
   list_for_every_entry(&upper->userlist, tmp, struct sensor_user_s, node)
     {
-      if (tmp == user || tmp->interval == ULONG_MAX)
+      if (tmp == user || tmp->state.interval == ULONG_MAX)
         {
           continue;
         }
 
-      if (min_interval > tmp->interval)
+      if (min_interval > tmp->state.interval)
         {
-          min_interval = tmp->interval;
+          min_interval = tmp->state.interval;
         }
 
-      if (min_latency > tmp->latency)
+      if (min_latency > tmp->state.latency)
         {
-          min_latency = tmp->latency;
+          min_latency = tmp->state.latency;
         }
     }
 
@@ -261,7 +259,7 @@ static int sensor_update_interval(FAR struct file *filep,
     }
 
   upper->state.min_interval = min_interval;
-  user->interval = interval;
+  user->state.interval = interval;
   sensor_pollnotify(upper, POLLPRI);
   return ret;
 }
@@ -276,14 +274,14 @@ static int sensor_update_latency(FAR struct file *filep,
   unsigned long min_latency = latency;
   int ret = 0;
 
-  if (latency == user->latency)
+  if (latency == user->state.latency)
     {
       return 0;
     }
 
-  if (user->interval == ULONG_MAX)
+  if (user->state.interval == ULONG_MAX)
     {
-      user->latency = latency;
+      user->state.latency = latency;
       return 0;
     }
 
@@ -294,14 +292,14 @@ static int sensor_update_latency(FAR struct file *filep,
 
   list_for_every_entry(&upper->userlist, tmp, struct sensor_user_s, node)
     {
-      if (tmp == user || tmp->interval == ULONG_MAX)
+      if (tmp == user || tmp->state.interval == ULONG_MAX)
         {
           continue;
         }
 
-      if (min_latency > tmp->latency)
+      if (min_latency > tmp->state.latency)
         {
-          min_latency = tmp->latency;
+          min_latency = tmp->state.latency;
         }
     }
 
@@ -313,7 +311,7 @@ update:
 
   if (min_latency == upper->state.min_latency)
     {
-      user->latency = latency;
+      user->state.latency = latency;
       return ret;
     }
 
@@ -327,7 +325,7 @@ update:
     }
 
   upper->state.min_latency = min_latency;
-  user->latency = latency;
+  user->state.latency = latency;
   sensor_pollnotify(upper, POLLPRI);
   return ret;
 }
@@ -348,13 +346,13 @@ static void sensor_generate_timing(FAR struct sensor_upperhalf_s *upper,
 static bool sensor_is_updated(FAR struct sensor_upperhalf_s *upper,
                               FAR struct sensor_user_s *user)
 {
-  long delta = upper->state.generation - user->generation;
+  long delta = upper->state.generation - user->state.generation;
 
   if (delta <= 0)
     {
       return false;
     }
-  else if (user->interval == ULONG_MAX)
+  else if (user->state.interval == ULONG_MAX)
     {
       return true;
     }
@@ -368,7 +366,8 @@ static bool sensor_is_updated(FAR struct sensor_upperhalf_s *upper,
        *   next generation user want
        */
 
-      return delta >= user->interval - (upper->state.min_interval >> 1);
+      return delta >= user->state.interval -
+                      (upper->state.min_interval >> 1);
     }
 }
 
@@ -379,18 +378,19 @@ static void sensor_catch_up(FAR struct sensor_upperhalf_s *upper,
   long delta;
 
   circbuf_peek(&upper->timing, &generation, TIMING_BUF_ESIZE);
-  delta = generation - user->generation;
+  delta = generation - user->state.generation;
   if (delta > 0)
     {
       user->bufferpos = upper->timing.tail / TIMING_BUF_ESIZE;
-      if (user->interval == ULONG_MAX)
+      if (user->state.interval == ULONG_MAX)
         {
-          user->generation = generation - 1;
+          user->state.generation = generation - 1;
         }
       else
         {
           delta -= upper->state.min_interval >> 1;
-          user->generation += ROUND_DOWN(delta, user->interval);
+          user->state.generation += ROUND_DOWN(delta,
+                                               user->state.interval);
         }
     }
 }
@@ -416,7 +416,7 @@ static ssize_t sensor_do_samples(FAR struct sensor_upperhalf_s *upper,
 
   /* Take samples continuously */
 
-  if (user->interval == ULONG_MAX)
+  if (user->state.interval == ULONG_MAX)
     {
       ret = circbuf_peekat(&upper->buffer,
                            user->bufferpos * upper->state.esize,
@@ -424,7 +424,7 @@ static ssize_t sensor_do_samples(FAR struct sensor_upperhalf_s *upper,
       user->bufferpos += nums;
       circbuf_peekat(&upper->timing,
                      (user->bufferpos - 1) * TIMING_BUF_ESIZE,
-                     &user->generation, TIMING_BUF_ESIZE);
+                     &user->state.generation, TIMING_BUF_ESIZE);
       return ret;
     }
 
@@ -465,14 +465,14 @@ static ssize_t sensor_do_samples(FAR struct sensor_upperhalf_s *upper,
         }
 
       delta = next_generation + generation -
-              ((user->generation + user->interval) << 1);
+              ((user->state.generation + user->state.interval) << 1);
       if (delta >= 0)
         {
           ret += circbuf_peekat(&upper->buffer,
                                 (pos - 1) * upper->state.esize,
                                 buffer + ret, upper->state.esize);
           user->bufferpos = pos;
-          user->generation += user->interval;
+          user->state.generation += user->state.interval;
           if (ret >= len)
             {
               break;
@@ -573,16 +573,17 @@ static int sensor_open(FAR struct file *filep)
 
   if (upper->state.generation && lower->persist)
     {
-      user->generation = upper->state.generation - 1;
+      user->state.generation = upper->state.generation - 1;
       user->bufferpos  = upper->timing.head / TIMING_BUF_ESIZE - 1;
     }
   else
     {
-      user->generation = upper->state.generation;
+      user->state.generation = upper->state.generation;
       user->bufferpos  = upper->timing.head / TIMING_BUF_ESIZE;
     }
 
-  user->interval = ULONG_MAX;
+  user->state.interval = ULONG_MAX;
+  user->state.esize = upper->state.esize;
   nxsem_init(&user->buffersem, 0, 0);
   nxsem_set_protocol(&user->buffersem, SEM_PRIO_NONE);
   list_add_tail(&upper->userlist, &user->node);
@@ -748,6 +749,15 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
         }
         break;
 
+      case SNIOC_GET_USTATE:
+        {
+          nxrmutex_lock(&upper->lock);
+          memcpy((FAR void *)(uintptr_t)arg,
+                 &user->state, sizeof(user->state));
+          nxrmutex_unlock(&upper->lock);
+        }
+        break;
+
       case SNIOC_SET_INTERVAL:
         {
           nxrmutex_lock(&upper->lock);
diff --git a/drivers/sensors/sensor_rpmsg.c b/drivers/sensors/sensor_rpmsg.c
index 2b608d3f3e..0243119f3a 100644
--- a/drivers/sensors/sensor_rpmsg.c
+++ b/drivers/sensors/sensor_rpmsg.c
@@ -726,22 +726,22 @@ static void sensor_rpmsg_push_event_one(FAR struct sensor_rpmsg_dev_s *dev,
   FAR struct sensor_rpmsg_cell_s *cell;
   FAR struct sensor_rpmsg_ept_s *sre;
   FAR struct sensor_rpmsg_data_s *msg;
-  struct sensor_state_s state;
+  struct sensor_ustate_s state;
   uint64_t now;
   bool updated;
   int ret;
 
   /* Get state of device to do send data with timeout */
 
-  ret = file_ioctl(&stub->file, SNIOC_GET_STATE, &state);
+  ret = file_ioctl(&stub->file, SNIOC_GET_USTATE, &state);
   if (ret < 0)
     {
       return;
     }
 
-  if (state.min_interval == ULONG_MAX)
+  if (state.interval == ULONG_MAX)
     {
-      state.min_interval = 0;
+      state.interval = 0;
     }
 
   sre = container_of(stub->ept, struct sensor_rpmsg_ept_s, ept);
@@ -807,7 +807,7 @@ static void sensor_rpmsg_push_event_one(FAR struct sensor_rpmsg_dev_s *dev,
    */
 
   now = sensor_get_timestamp();
-  if (sre->expire <= now)
+  if (sre->expire <= now && sre->buffer)
     {
       ret = rpmsg_send_nocopy(&sre->ept, sre->buffer, sre->written);
       sre->buffer = NULL;
@@ -820,9 +820,9 @@ static void sensor_rpmsg_push_event_one(FAR struct sensor_rpmsg_dev_s *dev,
   else
     {
       if (sre->expire == UINT64_MAX ||
-          sre->expire - now > state.min_interval / 2)
+          sre->expire - now > state.interval / 2)
         {
-          sre->expire = now + state.min_interval / 2;
+          sre->expire = now + state.interval / 2;
         }
 
       work_queue(HPWORK, &sre->work, sensor_rpmsg_data_worker, sre,
diff --git a/include/nuttx/sensors/ioctl.h b/include/nuttx/sensors/ioctl.h
index 992367cc14..403bac1a28 100644
--- a/include/nuttx/sensors/ioctl.h
+++ b/include/nuttx/sensors/ioctl.h
@@ -334,4 +334,11 @@
 
 #define SNIOC_UPDATED              _SNIOC(0x0091)
 
+/* Command:      SNIOC_GET_USTATE
+ * Description:  Get state for user.
+ * Argument:     This is the state pointer(struct sensor_state_s)
+ */
+
+#define SNIOC_GET_USTATE           _SNIOC(0x0092)
+
 #endif /* __INCLUDE_NUTTX_SENSORS_IOCTL_H */
diff --git a/include/nuttx/sensors/sensor.h b/include/nuttx/sensors/sensor.h
index 8af4eca43f..e58f41d3af 100644
--- a/include/nuttx/sensors/sensor.h
+++ b/include/nuttx/sensors/sensor.h
@@ -975,6 +975,16 @@ struct sensor_state_s
   FAR void     *priv;          /* The pointer to private data of userspace user */
 };
 
+/* This structure describes the state for the sensor user */
+
+struct sensor_ustate_s
+{
+  unsigned long esize;         /* The element size of circular buffer */
+  unsigned long latency;       /* The batch latency for user, in us */
+  unsigned long interval;      /* The subscription interval for user, in us */
+  unsigned long generation;    /* The recent generation of circular buffer */
+};
+
 /* This structure describes the register info for the user sensor */
 
 #ifdef CONFIG_USENSOR


[incubator-nuttx] 06/22: driver/sensor: using re-entrant mutex for sensor access to avoid deadlock

Posted by xi...@apache.org.
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 2a910b7ca9661cdcd2a691d809b2bedde4a7d2f0
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Fri Apr 29 23:08:59 2022 +0800

    driver/sensor: using re-entrant mutex for sensor access to avoid deadlock
    
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 drivers/sensors/sensor.c | 130 +++++++++++++++++++++++++----------------------
 1 file changed, 68 insertions(+), 62 deletions(-)

diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index 1bcb977393..93fba9e504 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -95,6 +95,8 @@ struct sensor_upperhalf_s
   struct sensor_state_s          state;  /* The state of sensor device */
   struct circbuf_s   buffer;             /* The circular buffer of sensor device */
   sem_t              exclsem;            /* Manages exclusive access to file operations */
+  pid_t              semholder;          /* The current holder of the semaphore */
+  int16_t            semcount;           /* Number of counts held */
   struct list_node   userlist;           /* List of users */
 };
 
@@ -176,6 +178,38 @@ static const struct file_operations g_sensor_fops =
  * Private Functions
  ****************************************************************************/
 
+static void sensor_semtake(FAR struct sensor_upperhalf_s *upper)
+{
+  pid_t pid = gettid();
+
+  if (pid == upper->semholder)
+    {
+      upper->semcount++;
+    }
+  else
+    {
+      nxsem_wait_uninterruptible(&upper->exclsem);
+      upper->semholder = pid;
+      upper->semcount = 1;
+    }
+}
+
+static void sensor_semgive(FAR struct sensor_upperhalf_s *upper)
+{
+  DEBUGASSERT(upper->semholder == gettid());
+
+  if (upper->semcount > 1)
+    {
+      upper->semcount--;
+    }
+  else
+    {
+      upper->semholder = INVALID_PROCESS_ID;
+      upper->semcount  = 0;
+      nxsem_post(&upper->exclsem);
+    }
+}
+
 static bool sensor_in_range(unsigned long left, unsigned long value,
                             unsigned long right)
 {
@@ -356,14 +390,9 @@ static int sensor_open(FAR struct file *filep)
   FAR struct sensor_upperhalf_s *upper = inode->i_private;
   FAR struct sensor_lowerhalf_s *lower = upper->lower;
   FAR struct sensor_user_s *user;
-  int ret;
-
-  ret = nxsem_wait(&upper->exclsem);
-  if (ret < 0)
-    {
-      return ret;
-    }
+  int ret = 0;
 
+  sensor_semtake(upper);
   user = kmm_zalloc(sizeof(struct sensor_user_s));
   if (user == NULL)
     {
@@ -423,7 +452,7 @@ errout_with_open:
 errout_with_user:
   kmm_free(user);
 errout_with_sem:
-  nxsem_post(&upper->exclsem);
+  sensor_semgive(upper);
   return ret;
 }
 
@@ -433,20 +462,15 @@ static int sensor_close(FAR struct file *filep)
   FAR struct sensor_upperhalf_s *upper = inode->i_private;
   FAR struct sensor_lowerhalf_s *lower = upper->lower;
   FAR struct sensor_user_s *user = filep->f_priv;
-  int ret;
-
-  ret = nxsem_wait(&upper->exclsem);
-  if (ret < 0)
-    {
-      return ret;
-    }
+  int ret = 0;
 
+  sensor_semtake(upper);
   if (lower->ops->close)
     {
       ret = lower->ops->close(lower, filep);
       if (ret < 0)
         {
-          nxsem_post(&upper->exclsem);
+          sensor_semgive(upper);
           return ret;
         }
     }
@@ -473,7 +497,7 @@ static int sensor_close(FAR struct file *filep)
   /* The user is closed, notify to other users */
 
   sensor_pollnotify(upper, POLLPRI);
-  nxsem_post(&upper->exclsem);
+  sensor_semgive(upper);
 
   kmm_free(user);
   return ret;
@@ -494,28 +518,19 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
       return -EINVAL;
     }
 
-  ret = nxsem_wait(&upper->exclsem);
-  if (ret < 0)
-    {
-      return ret;
-    }
-
+  sensor_semtake(upper);
   if (lower->ops->fetch)
     {
       if (!(filep->f_oflags & O_NONBLOCK))
         {
-          nxsem_post(&upper->exclsem);
+          sensor_semgive(upper);
           ret = nxsem_wait_uninterruptible(&user->buffersem);
           if (ret < 0)
             {
               return ret;
             }
 
-          ret = nxsem_wait(&upper->exclsem);
-          if (ret < 0)
-            {
-              return ret;
-            }
+          sensor_semtake(upper);
         }
       else if (!upper->state.nsubscribers)
         {
@@ -564,14 +579,14 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
                 }
               else
                 {
-                  nxmutex_unlock(&upper->lock);
+                  sensor_semgive(upper);
                   ret = nxsem_wait_uninterruptible(&user->buffersem);
                   if (ret < 0)
                     {
                       return ret;
                     }
 
-                  nxmutex_lock(&upper->lock);
+                  sensor_semtake(upper);
                 }
             }
         }
@@ -601,7 +616,7 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
     }
 
 out:
-  nxsem_post(&upper->exclsem);
+  sensor_semgive(upper);
   return ret;
 }
 
@@ -621,35 +636,35 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
   FAR struct sensor_upperhalf_s *upper = inode->i_private;
   FAR struct sensor_lowerhalf_s *lower = upper->lower;
   FAR struct sensor_user_s *user = filep->f_priv;
-  int ret;
+  int ret = 0;
 
   sninfo("cmd=%x arg=%08lx\n", cmd, arg);
 
-  ret = nxsem_wait(&upper->exclsem);
-  if (ret < 0)
-    {
-      return ret;
-    }
-
   switch (cmd)
     {
       case SNIOC_GET_STATE:
         {
+          sensor_semtake(upper);
           memcpy((FAR void *)(uintptr_t)arg,
                  &upper->state, sizeof(upper->state));
           user->changed = false;
+          sensor_semgive(upper);
         }
         break;
 
       case SNIOC_SET_INTERVAL:
         {
+          sensor_semtake(upper);
           ret = sensor_update_interval(filep, upper, user, arg);
+          sensor_semgive(upper);
         }
         break;
 
       case SNIOC_BATCH:
         {
+          sensor_semtake(upper);
           ret = sensor_update_latency(filep, upper, user, arg);
+          sensor_semgive(upper);
         }
         break;
 
@@ -691,12 +706,15 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
 
       case SNIOC_SET_USERPRIV:
         {
+          sensor_semtake(upper);
           upper->state.priv = (FAR void *)(uintptr_t)arg;
+          sensor_semgive(upper);
         }
         break;
 
       case SNIOC_SET_BUFFER_NUMBER:
         {
+          sensor_semtake(upper);
           if (!circbuf_is_init(&upper->buffer))
             {
               if (arg >= lower->nbuffer)
@@ -712,6 +730,8 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
             {
               ret = -EBUSY;
             }
+
+          sensor_semgive(upper);
         }
         break;
 
@@ -739,7 +759,6 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
         break;
     }
 
-  nxsem_post(&upper->exclsem);
   return ret;
 }
 
@@ -752,14 +771,9 @@ static int sensor_poll(FAR struct file *filep,
   FAR struct sensor_user_s *user = filep->f_priv;
   pollevent_t eventset = 0;
   int semcount;
-  int ret;
-
-  ret = nxsem_wait(&upper->exclsem);
-  if (ret < 0)
-    {
-      return ret;
-    }
+  int ret = 0;
 
+  sensor_semtake(upper);
   if (setup)
     {
       /* Don't have enough space to store fds */
@@ -811,7 +825,7 @@ static int sensor_poll(FAR struct file *filep,
     }
 
 errout:
-  nxsem_post(&upper->exclsem);
+  sensor_semgive(upper);
   return ret;
 }
 
@@ -831,12 +845,7 @@ static ssize_t sensor_push_event(FAR void *priv, FAR const void *data,
       return -EINVAL;
     }
 
-  ret = nxsem_wait(&upper->exclsem);
-  if (ret < 0)
-    {
-      return ret;
-    }
-
+  sensor_semtake(upper);
   if (!circbuf_is_init(&upper->buffer))
     {
       /* Initialize sensor buffer when data is first generated */
@@ -845,7 +854,7 @@ static ssize_t sensor_push_event(FAR void *priv, FAR const void *data,
                          upper->state.esize);
       if (ret < 0)
         {
-          nxsem_post(&upper->exclsem);
+          sensor_semgive(upper);
           return ret;
         }
     }
@@ -866,7 +875,7 @@ static ssize_t sensor_push_event(FAR void *priv, FAR const void *data,
         }
     }
 
-  nxsem_post(&upper->exclsem);
+  sensor_semgive(upper);
   return bytes;
 }
 
@@ -876,11 +885,7 @@ static void sensor_notify_event(FAR void *priv)
   FAR struct sensor_user_s *user;
   int semcount;
 
-  if (nxsem_wait(&upper->exclsem) < 0)
-    {
-      return;
-    }
-
+  sensor_semtake(upper);
   list_for_every_entry(&upper->userlist, user, struct sensor_user_s, node)
     {
       nxsem_get_value(&user->buffersem, &semcount);
@@ -892,7 +897,7 @@ static void sensor_notify_event(FAR void *priv)
       sensor_pollnotify_one(user, POLLIN);
     }
 
-  nxsem_post(&upper->exclsem);
+  sensor_semgive(upper);
 }
 
 /****************************************************************************
@@ -996,6 +1001,7 @@ int sensor_custom_register(FAR struct sensor_lowerhalf_s *lower,
       upper->state.nadvertisers = 1;
     }
 
+  upper->semholder = INVALID_PROCESS_ID;
   nxsem_init(&upper->exclsem, 0, 1);
 
   /* Bind the lower half data structure member */