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

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

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