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 2020/11/20 13:33:16 UTC

[incubator-nuttx] 02/02: driver/sensor rc: use mm/circbuf manage intermediate buffer

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 8f9ca79ffc7d031e273449b2fbff4a6dc56f3730
Author: dongjiuzhu <do...@xiaomi.com>
AuthorDate: Thu Nov 12 18:40:37 2020 +0800

    driver/sensor rc: use mm/circbuf manage intermediate buffer
    
    N/A
    
    Change-Id: Ifdd8117da9d20ac2f48f04b7b383449e6dd03f06
    Signed-off-by: dongjiuzhu <do...@xiaomi.com>
---
 drivers/rc/Kconfig       |   1 +
 drivers/rc/lirc_dev.c    | 133 ++++------------------------
 drivers/sensors/Kconfig  |   1 +
 drivers/sensors/sensor.c | 226 ++++++++---------------------------------------
 4 files changed, 57 insertions(+), 304 deletions(-)

diff --git a/drivers/rc/Kconfig b/drivers/rc/Kconfig
index 65cf457..9e4a5d4 100644
--- a/drivers/rc/Kconfig
+++ b/drivers/rc/Kconfig
@@ -5,6 +5,7 @@
 
 menuconfig DRIVERS_RC
 	bool "Remote Control Device Support"
+	select MM_CIRCBUF
 	default n
 	---help---
 		Drivers for various remote control
diff --git a/drivers/rc/lirc_dev.c b/drivers/rc/lirc_dev.c
index 057a6b3..d68a1d8 100644
--- a/drivers/rc/lirc_dev.c
+++ b/drivers/rc/lirc_dev.c
@@ -30,6 +30,7 @@
 #include <fcntl.h>
 
 #include <nuttx/kmalloc.h>
+#include <nuttx/mm/circbuf.h>
 #include <nuttx/rc/lirc_dev.h>
 
 /****************************************************************************
@@ -56,23 +57,13 @@ struct lirc_upperhalf_s
   uint64_t                     gap_duration; /* duration of initial gap */
 };
 
-/* This structure describes lirc circular buffer */
-
-struct lirc_buffer_s
-{
-  uint32_t  head;
-  uint32_t  tail;
-  uint32_t  size;
-  FAR void *data;
-};
-
 /* The structure describes an open lirc file */
 
 struct lirc_fh_s
 {
   struct list_node             node;         /* list of open file handles */
   FAR struct lirc_lowerhalf_s *lower;        /* the pointer to lirc_lowerhalf_s */
-  FAR struct lirc_buffer_s    *buffer;       /* buffer for incoming IR */
+  struct circbuf_s             buffer;       /* buffer for incoming IR */
   FAR struct pollfd           *fd;           /* poll structures of threads waiting for driver events */
   sem_t                        waitsem;      /* sem of wait buffer for ready */
   int                          carrier_low;  /* when setting the carrier range, first the low end must be
@@ -117,96 +108,6 @@ static const struct file_operations g_lirc_fops =
  * Private Functions
  ****************************************************************************/
 
-static void lirc_buffer_free(FAR struct lirc_buffer_s *buffer)
-{
-  kmm_free(buffer);
-}
-
-static uint32_t lirc_buffer_len(FAR struct lirc_buffer_s *buffer)
-{
-  return buffer->head - buffer->tail;
-}
-
-static uint32_t lirc_buffer_empty(FAR struct lirc_buffer_s *buffer)
-{
-  return !lirc_buffer_len(buffer);
-}
-
-static uint32_t lirc_buffer_unused(FAR struct lirc_buffer_s *buffer)
-{
-  return buffer->size - lirc_buffer_len(buffer);
-}
-
-static uint32_t lirc_buffer_read(FAR struct lirc_buffer_s *buffer,
-                            FAR void *dest, uint32_t bytes)
-{
-  uint32_t len = lirc_buffer_len(buffer);
-  uint32_t off = buffer->tail % buffer->size;
-
-  if (bytes > len)
-    {
-      bytes = len;
-    }
-
-  len = buffer->size - off;
-  if (bytes < len)
-    {
-      len = bytes;
-    }
-
-  memcpy(dest, buffer->data + off, len);
-  memcpy(dest + len, buffer->data, bytes - len);
-  buffer->tail += bytes;
-
-  return bytes;
-}
-
-static uint32_t lirc_buffer_write(FAR struct lirc_buffer_s *buffer,
-                             FAR const void *src, uint32_t bytes)
-{
-  uint32_t space = lirc_buffer_unused(buffer);
-  uint32_t off = buffer->head % buffer->size;
-
-  if (bytes > space)
-    {
-      bytes = space;
-    }
-
-  space = buffer->size - off;
-  if (bytes < space)
-    {
-      space = bytes;
-    }
-
-  memcpy(buffer->data + off, src, space);
-  memcpy(buffer->data, src + space, bytes - space);
-  buffer->head += bytes;
-
-  return bytes;
-}
-
-static int lirc_buffer_create(FAR struct lirc_buffer_s **buffer,
-                              uint32_t bytes)
-{
-  FAR struct lirc_buffer_s *tmp;
-
-  tmp = kmm_malloc(sizeof((*tmp)) + bytes);
-  if (!tmp)
-    {
-      rcerr("Faild to malloc memory for circular buffer\n");
-      return -ENOMEM;
-    }
-
-  tmp->size = bytes;
-  tmp->data = tmp + 1;
-  tmp->head = 0;
-  tmp->tail = 0;
-
-  *buffer = tmp;
-
-  return 0;
-}
-
 static void lirc_pollnotify(FAR struct lirc_fh_s *fh,
                             pollevent_t eventset)
 {
@@ -263,9 +164,9 @@ static int lirc_open(FAR struct file *filep)
       fh->send_mode = LIRC_MODE_PULSE;
     }
 
-  if (lirc_buffer_create(&fh->buffer, lower->buffer_bytes))
+  ret = circbuf_init(&fh->buffer, NULL, lower->buffer_bytes);
+  if (ret < 0)
     {
-      ret = -ENOMEM;
       goto buffer_err;
     }
 
@@ -293,7 +194,7 @@ static int lirc_open(FAR struct file *filep)
 
 open_err:
   nxsem_destroy(&fh->waitsem);
-  lirc_buffer_free(fh->buffer);
+  circbuf_uninit(&fh->buffer);
 buffer_err:
   kmm_free(fh);
   return ret;
@@ -312,7 +213,7 @@ static int lirc_close(FAR struct file *filep)
   leave_critical_section(flags);
 
   nxsem_destroy(&fh->waitsem);
-  lirc_buffer_free(fh->buffer);
+  circbuf_uninit(&fh->buffer);
 
   kmm_free(fh);
   if (list_is_empty(&upper->fh))
@@ -343,7 +244,7 @@ static int lirc_poll(FAR struct file *filep,
       fh->fd = fds;
       fds->priv = &fh->fd;
 
-      if (!lirc_buffer_empty(fh->buffer))
+      if (!circbuf_is_empty(&fh->buffer))
         {
           eventset = (fds->events & (POLLIN | POLLRDNORM));
         }
@@ -787,7 +688,7 @@ static ssize_t lirc_read_scancode(FAR struct file *filep, FAR char *buffer,
   flags = enter_critical_section();
   do
     {
-      if (lirc_buffer_empty(fh->buffer))
+      if (circbuf_is_empty(&fh->buffer))
         {
           if (filep->f_oflags & O_NONBLOCK)
             {
@@ -802,9 +703,9 @@ static ssize_t lirc_read_scancode(FAR struct file *filep, FAR char *buffer,
             }
         }
 
-      len = lirc_buffer_read(fh->buffer, buffer, length);
+      len = circbuf_read(&fh->buffer, buffer, length);
     }
-  while (len == 0);
+  while (len <= 0);
 
 err:
   leave_critical_section(flags);
@@ -827,7 +728,7 @@ static ssize_t lirc_read_mode2(FAR struct file *filep, FAR char *buffer,
   flags = enter_critical_section();
   do
     {
-      if (lirc_buffer_empty(fh->buffer))
+      if (circbuf_is_empty(&fh->buffer))
         {
           if (filep->f_oflags & O_NONBLOCK)
             {
@@ -842,9 +743,9 @@ static ssize_t lirc_read_mode2(FAR struct file *filep, FAR char *buffer,
             }
         }
 
-      len = lirc_buffer_read(fh->buffer, buffer, length);
+      len = circbuf_read(&fh->buffer, buffer, length);
     }
-  while (len == 0);
+  while (len <= 0);
 
 err:
   leave_critical_section(flags);
@@ -1035,7 +936,7 @@ void lirc_raw_event(FAR struct lirc_lowerhalf_s *lower,
           list_for_every_safe(&upper->fh, node, tmp)
             {
               fh = (FAR struct lirc_fh_s *)node;
-              if (lirc_buffer_write(fh->buffer, &gap, sizeof(int)))
+              if (circbuf_write(&fh->buffer, &gap, sizeof(int)) > 0)
                 {
                   lirc_pollnotify(fh, POLLIN | POLLRDNORM);
                   nxsem_get_value(&fh->waitsem, &semcount);
@@ -1063,7 +964,7 @@ void lirc_raw_event(FAR struct lirc_lowerhalf_s *lower,
           continue;
         }
 
-      if (lirc_buffer_write(fh->buffer, &sample, sizeof(unsigned int)))
+      if (circbuf_write(&fh->buffer, &sample, sizeof(unsigned int)) > 0)
         {
           lirc_pollnotify(fh, POLLIN | POLLRDNORM);
           nxsem_get_value(&fh->waitsem, &semcount);
@@ -1107,7 +1008,7 @@ void lirc_scancode_event(FAR struct lirc_lowerhalf_s *lower,
   list_for_every_safe(&upper->fh, node, tmp)
     {
       fh = (FAR struct lirc_fh_s *)node;
-      if (lirc_buffer_write(fh->buffer, lsc, sizeof(*lsc)))
+      if (circbuf_write(&fh->buffer, lsc, sizeof(*lsc)) > 0)
         {
           lirc_pollnotify(fh, POLLIN | POLLRDNORM);
           nxsem_get_value(&fh->waitsem, &semcount);
@@ -1153,7 +1054,7 @@ void lirc_sample_event(FAR struct lirc_lowerhalf_s *lower,
   list_for_every_safe(&upper->fh, node, tmp)
     {
       fh = (FAR struct lirc_fh_s *)node;
-      if (lirc_buffer_write(fh->buffer, &sample, sizeof(unsigned int)))
+      if (circbuf_write(&fh->buffer, &sample, sizeof(unsigned int)) > 0)
         {
           lirc_pollnotify(fh, POLLIN | POLLRDNORM);
           nxsem_get_value(&fh->waitsem, &semcount);
diff --git a/drivers/sensors/Kconfig b/drivers/sensors/Kconfig
index f800092..0ac30e2 100644
--- a/drivers/sensors/Kconfig
+++ b/drivers/sensors/Kconfig
@@ -5,6 +5,7 @@
 
 menuconfig SENSORS
 	bool "Sensor Device Support"
+	select MM_CIRCBUF
 	default n
 	---help---
 		Drivers for various sensors
diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index 1f6ae10..64d26a3 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -34,6 +34,7 @@
 #include <poll.h>
 #include <fcntl.h>
 #include <nuttx/kmalloc.h>
+#include <nuttx/mm/circbuf.h>
 #include <nuttx/sensors/sensor.h>
 
 /****************************************************************************
@@ -59,16 +60,6 @@ struct sensor_info
   FAR char *name;
 };
 
-/* This structure describes sensor circular buffer */
-
-struct sensor_buffer_s
-{
-  uint32_t  head;
-  uint32_t  tail;
-  uint32_t  size;
-  FAR void *data;
-};
-
 /* This structure describes the state of the upper half driver */
 
 struct sensor_upperhalf_s
@@ -77,7 +68,7 @@ struct sensor_upperhalf_s
 
   FAR struct pollfd             *fds[CONFIG_SENSORS_NPOLLWAITERS];
   FAR struct sensor_lowerhalf_s *lower;  /* the handle of lower half driver */
-  FAR struct sensor_buffer_s    *buffer; /* The circualr buffer of sensor device */
+  struct circbuf_s   buffer;             /* The circular buffer of sensor device */
   uint8_t            crefs;              /* Number of times the device has been opened */
   sem_t              exclsem;            /* Manages exclusive access to file operations */
   sem_t              buffersem;          /* Wakeup user waiting for data in circular buffer */
@@ -148,154 +139,6 @@ static const struct file_operations g_sensor_fops =
  * Private Functions
  ****************************************************************************/
 
-static bool sensor_buffer_is_empty(FAR struct sensor_buffer_s *buffer)
-{
-  return buffer->head == buffer->tail;
-}
-
-static uint32_t sensor_buffer_len(FAR struct sensor_buffer_s *buffer)
-{
-  return buffer->head - buffer->tail;
-}
-
-static uint32_t sensor_buffer_unused(FAR struct sensor_buffer_s *buffer)
-{
-  return buffer->size - sensor_buffer_len(buffer);
-}
-
-static void sensor_buffer_reset(FAR struct sensor_buffer_s *buffer)
-{
-  buffer->head = buffer->tail = 0;
-}
-
-static void sensor_buffer_push(FAR struct sensor_buffer_s *buffer,
-                               FAR const void *data, uint32_t bytes)
-{
-  uint32_t space = sensor_buffer_unused(buffer);
-  uint32_t off = buffer->head % buffer->size;
-  uint32_t overwrite = 0;
-
-  /* If buffer is full or there is not enough space, overwriting of old
-   * data will occur, we should move tail point after pushing data
-   * completely.
-   */
-
-  if (bytes > buffer->size)
-    {
-      data += bytes - buffer->size;
-      bytes = buffer->size;
-    }
-
-  if (bytes > space)
-    {
-      overwrite = bytes - space;
-    }
-
-  space = buffer->size - off;
-  if (bytes < space)
-    {
-      space = bytes;
-    }
-
-  memcpy(buffer->data + off, data, space);
-  memcpy(buffer->data, data + space, bytes - space);
-  buffer->head += bytes;
-  buffer->tail += overwrite;
-}
-
-static uint32_t sensor_buffer_pop(FAR struct sensor_buffer_s *buffer,
-                                  FAR void *data, uint32_t bytes)
-{
-  uint32_t len = sensor_buffer_len(buffer);
-  uint32_t off;
-
-  if (bytes > len)
-    {
-      bytes = len;
-    }
-
-  if (!data)
-    {
-      goto skip;
-    }
-
-  off = buffer->tail % buffer->size;
-  len = buffer->size - off;
-  if (bytes < len)
-    {
-      len = bytes;
-    }
-
-  memcpy(data, buffer->data + off, len);
-  memcpy(data + len, buffer->data, bytes - len);
-
-skip:
-  buffer->tail += bytes;
-
-  return bytes;
-}
-
-static int sensor_buffer_resize(FAR struct sensor_buffer_s **buffer,
-                                int type, uint32_t bytes)
-{
-  FAR struct sensor_buffer_s *tmp;
-  int len = sensor_buffer_len(*buffer);
-  int skipped;
-
-  bytes = ROUNDUP(bytes, g_sensor_info[type].esize);
-  tmp = kmm_malloc(sizeof(*tmp) + bytes);
-  if (!tmp)
-    {
-      snerr("Faild to alloc memory for circular buffer\n");
-      return -ENOMEM;
-    }
-
-  tmp->data = tmp + 1;
-
-  skipped = (bytes > len) ? 0 : len - bytes;
-  len -= skipped;
-  sensor_buffer_pop(*buffer, NULL, skipped);
-  sensor_buffer_pop(*buffer, tmp->data, len);
-
-  tmp->size = bytes;
-  tmp->head = len;
-  tmp->tail = 0;
-
-  kmm_free(*buffer);
-  *buffer = tmp;
-
-  return 0;
-}
-
-static int sensor_buffer_create(FAR struct sensor_buffer_s **buffer,
-                                int type, uint32_t bytes)
-{
-  FAR struct sensor_buffer_s *tmp;
-
-  bytes = ROUNDUP(bytes, g_sensor_info[type].esize);
-
-  tmp = kmm_malloc(sizeof(*tmp) + bytes);
-  if (!tmp)
-    {
-      snerr("Faild to malloc memory for circular buffer\n");
-      return -ENOMEM;
-    }
-
-  tmp->size = bytes;
-  tmp->data = tmp + 1;
-  tmp->head = 0;
-  tmp->tail = 0;
-
-  *buffer = tmp;
-
-  return 0;
-}
-
-static void sensor_buffer_release(FAR struct sensor_buffer_s *buffer)
-{
-  kmm_free(buffer);
-}
-
 static void sensor_pollnotify(FAR struct sensor_upperhalf_s *upper,
                               pollevent_t eventset)
 {
@@ -328,6 +171,8 @@ static int sensor_open(FAR struct file *filep)
 {
   FAR struct inode *inode = filep->f_inode;
   FAR struct sensor_upperhalf_s *upper = inode->i_private;
+  FAR struct sensor_lowerhalf_s *lower = upper->lower;
+  size_t bytes;
   uint8_t tmp;
   int ret;
 
@@ -347,7 +192,14 @@ static int sensor_open(FAR struct file *filep)
     }
   else if (tmp == 1)
     {
-      sensor_buffer_reset(upper->buffer);
+      /* Initialize sensor buffer */
+
+      bytes = ROUNDUP(lower->buffer_size, g_sensor_info[lower->type].esize);
+      ret = circbuf_init(&upper->buffer, NULL, bytes);
+      if (ret < 0)
+        {
+          goto err;
+        }
     }
 
   upper->crefs = tmp;
@@ -376,6 +228,7 @@ static int sensor_close(FAR struct file *filep)
       if (ret >= 0)
         {
           upper->enabled = false;
+          circbuf_uninit(&upper->buffer);
         }
     }
 
@@ -390,6 +243,7 @@ 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;
   ssize_t ret;
+  size_t bytes;
 
   if (!buffer || !len)
     {
@@ -430,7 +284,7 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
        * that have just entered the buffer.
        */
 
-      while (sensor_buffer_is_empty(upper->buffer))
+      while (circbuf_is_empty(&upper->buffer))
         {
           if (filep->f_oflags & O_NONBLOCK)
             {
@@ -454,7 +308,7 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
             }
         }
 
-      ret = sensor_buffer_pop(upper->buffer, buffer, len);
+      ret = circbuf_read(&upper->buffer, buffer, len);
 
       /* Release some buffer space when current mode isn't batch mode
        * and last mode is batch mode, and the number of bytes avaliable
@@ -462,11 +316,12 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
        */
 
       if (upper->latency == 0 &&
-          upper->buffer->size > lower->buffer_size &&
-          sensor_buffer_len(upper->buffer) <= lower->buffer_size)
+          circbuf_size(&upper->buffer) > lower->buffer_size &&
+          circbuf_used(&upper->buffer) <= lower->buffer_size)
         {
-          sensor_buffer_resize(&upper->buffer, lower->type,
-                               lower->buffer_size);
+          bytes = ROUNDUP(lower->buffer_size,
+                          g_sensor_info[lower->type].esize);
+          ret = circbuf_resize(&upper->buffer, bytes);
         }
     }
 
@@ -481,6 +336,7 @@ 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 unsigned int *val = (unsigned int *)(uintptr_t)arg;
+  size_t bytes;
   int ret;
 
   sninfo("cmd=%x arg=%08x\n", cmd, arg);
@@ -547,11 +403,13 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
                 {
                   /* Adjust length of buffer in batch mode */
 
-                  sensor_buffer_resize(&upper->buffer, lower->type,
-                                       lower->buffer_size +
-                                       ROUNDUP(*val, upper->interval) /
-                                       upper->interval *
-                                       g_sensor_info[lower->type].esize);
+                  bytes = ROUNDUP(ROUNDUP(*val, upper->interval) /
+                                  upper->interval *
+                                  g_sensor_info[lower->type].esize +
+                                  lower->buffer_size,
+                                  g_sensor_info[lower->type].esize);
+
+                  ret = circbuf_resize(&upper->buffer, bytes);
                 }
             }
         }
@@ -569,9 +427,13 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
             {
               lower->buffer_size = ROUNDUP(*val,
                                    g_sensor_info[lower->type].esize);
-              sensor_buffer_resize(&upper->buffer, lower->type,
-                                   lower->buffer_size);
-              *val = lower->buffer_size;
+              bytes = ROUNDUP(lower->buffer_size,
+                              g_sensor_info[lower->type].esize);
+              ret = circbuf_resize(&upper->buffer, bytes);
+              if (ret >= 0)
+                {
+                  *val = lower->buffer_size;
+                }
             }
         }
         break;
@@ -650,7 +512,7 @@ static int sensor_poll(FAR struct file *filep,
                 }
             }
         }
-      else if (!sensor_buffer_is_empty(upper->buffer))
+      else if (!circbuf_is_empty(&upper->buffer))
         {
           eventset |= (fds->events & POLLIN);
         }
@@ -689,7 +551,7 @@ static void sensor_push_event(FAR void *priv, FAR const void *data,
       return;
     }
 
-  sensor_buffer_push(upper->buffer, data, bytes);
+  circbuf_overwrite(&upper->buffer, data, bytes);
   sensor_pollnotify(upper, POLLIN);
   nxsem_get_value(&upper->buffersem, &semcount);
   if (semcount < 1)
@@ -799,15 +661,6 @@ int sensor_register(FAR struct sensor_lowerhalf_s *lower, int devno)
       lower->notify_event = sensor_notify_event;
     }
 
-  /* Initialize sensor buffer */
-
-  ret = sensor_buffer_create(&upper->buffer,
-                             lower->type, lower->buffer_size);
-  if (ret)
-    {
-      goto buf_err;
-    }
-
   snprintf(path, DEVNAME_MAX, DEVNAME_FMT,
            g_sensor_info[lower->type].name,
            lower->uncalibrated ? DEVNAME_UNCAL : "",
@@ -823,8 +676,6 @@ int sensor_register(FAR struct sensor_lowerhalf_s *lower, int devno)
   return ret;
 
 drv_err:
-  sensor_buffer_release(upper->buffer);
-buf_err:
   nxsem_destroy(&upper->exclsem);
   nxsem_destroy(&upper->buffersem);
 
@@ -867,6 +718,5 @@ void sensor_unregister(FAR struct sensor_lowerhalf_s *lower, int devno)
   nxsem_destroy(&upper->exclsem);
   nxsem_destroy(&upper->buffersem);
 
-  sensor_buffer_release(upper->buffer);
   kmm_free(upper);
 }