You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by GitBox <gi...@apache.org> on 2020/09/09 01:27:48 UTC

[GitHub] [incubator-nuttx] YuuichiNakamura commented on a change in pull request #1731: note: Rename note driver to noteram driver

YuuichiNakamura commented on a change in pull request #1731:
URL: https://github.com/apache/incubator-nuttx/pull/1731#discussion_r485282212



##########
File path: drivers/note/noteram_driver.c
##########
@@ -0,0 +1,477 @@
+/****************************************************************************
+ * drivers/note/noteram_driver.c
+ *
+ *   Copyright (C) 2016 Gregory Nutt. All rights reserved.
+ *   Author: Gregory Nutt <gn...@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <sched.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <nuttx/spinlock.h>
+#include <nuttx/sched_note.h>
+#include <nuttx/note/noteram_driver.h>
+#include <nuttx/fs/fs.h>
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct noteram_info_s
+{
+  volatile unsigned int ni_head;
+  volatile unsigned int ni_tail;
+  uint8_t ni_buffer[CONFIG_DRIVER_NOTERAM_BUFSIZE];
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static ssize_t noteram_read(FAR struct file *filep,
+                            FAR char *buffer, size_t buflen);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_noteram_fops =
+{
+  NULL,          /* open */
+  NULL,          /* close */
+  noteram_read,  /* read */
+  NULL,          /* write */
+  NULL,          /* seek */
+  NULL,          /* ioctl */
+  NULL           /* poll */
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+  , 0            /* unlink */
+#endif
+};
+
+static struct noteram_info_s g_noteram_info;
+
+#ifdef CONFIG_SMP
+static volatile spinlock_t g_noteram_lock;
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: noteram_next
+ *
+ * Description:
+ *   Return the circular buffer index at offset from the specified index
+ *   value, handling wraparound
+ *
+ * Input Parameters:
+ *   ndx - Old circular buffer index
+ *
+ * Returned Value:
+ *   New circular buffer index
+ *
+ ****************************************************************************/
+
+static inline unsigned int noteram_next(unsigned int ndx,
+                                        unsigned int offset)
+{
+  ndx += offset;
+  if (ndx >= CONFIG_DRIVER_NOTERAM_BUFSIZE)
+    {
+      ndx -= CONFIG_DRIVER_NOTERAM_BUFSIZE;
+    }
+
+  return ndx;
+}
+
+/****************************************************************************
+ * Name: noteram_length
+ *
+ * Description:
+ *   Length of data currently in circular buffer.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Length of data currently in circular buffer.
+ *
+ ****************************************************************************/
+
+static unsigned int noteram_length(void)
+{
+  unsigned int head = g_noteram_info.ni_head;
+  unsigned int tail = g_noteram_info.ni_tail;
+
+  if (tail > head)
+    {
+      head += CONFIG_DRIVER_NOTERAM_BUFSIZE;
+    }
+
+  return head - tail;
+}
+
+/****************************************************************************
+ * Name: noteram_remove
+ *
+ * Description:
+ *   Remove the variable length note from the tail of the circular buffer
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   We are within a critical section.
+ *
+ ****************************************************************************/
+
+static void noteram_remove(void)
+{
+  FAR struct note_common_s *note;
+  unsigned int tail;
+  unsigned int length;
+
+  /* Get the tail index of the circular buffer */
+
+  tail = g_noteram_info.ni_tail;
+  DEBUGASSERT(tail < CONFIG_DRIVER_NOTERAM_BUFSIZE);
+
+  /* Get the length of the note at the tail index */
+
+  note   = (FAR struct note_common_s *)&g_noteram_info.ni_buffer[tail];
+  length = note->nc_length;
+  DEBUGASSERT(length <= noteram_length());
+
+  /* Increment the tail index to remove the entire note from the circular
+   * buffer.
+   */
+
+  g_noteram_info.ni_tail = noteram_next(tail, length);
+}
+
+/****************************************************************************
+ * Name: noteram_get
+ *
+ * Description:
+ *   Remove the next note from the tail of the circular buffer.  The note
+ *   is also removed from the circular buffer to make room for further notes.
+ *
+ * Input Parameters:
+ *   buffer - Location to return the next note
+ *   buflen - The length of the user provided buffer.
+ *
+ * Returned Value:
+ *   On success, the positive, non-zero length of the return note is
+ *   provided.  Zero is returned only if the circular buffer is empty.  A
+ *   negated errno value is returned in the event of any failure.
+ *
+ ****************************************************************************/
+
+static ssize_t noteram_get(FAR uint8_t *buffer, size_t buflen)
+{
+  FAR struct note_common_s *note;
+  irqstate_t flags;
+  unsigned int remaining;
+  unsigned int tail;
+  ssize_t notelen;
+  size_t circlen;
+
+  DEBUGASSERT(buffer != NULL);
+  flags = enter_critical_section();
+
+  /* Verify that the circular buffer is not empty */
+
+  circlen = noteram_length();
+  if (circlen <= 0)
+    {
+      notelen = 0;
+      goto errout_with_csection;
+    }
+
+  /* Get the index to the tail of the circular buffer */
+
+  tail    = g_noteram_info.ni_tail;
+  DEBUGASSERT(tail < CONFIG_DRIVER_NOTERAM_BUFSIZE);
+
+  /* Get the length of the note at the tail index */
+
+  note    = (FAR struct note_common_s *)&g_noteram_info.ni_buffer[tail];
+  notelen = note->nc_length;
+  DEBUGASSERT(notelen <= circlen);
+
+  /* Is the user buffer large enough to hold the note? */
+
+  if (buflen < notelen)
+    {
+      /* Remove the large note so that we do not get constipated. */
+
+      noteram_remove();
+
+      /* and return an error */
+
+      notelen = -EFBIG;
+      goto errout_with_csection;
+    }
+
+  /* Loop until the note has been transferred to the user buffer */
+
+  remaining = (unsigned int)notelen;
+  while (remaining > 0)
+    {
+      /* Copy the next byte at the tail index */
+
+      *buffer++ = g_noteram_info.ni_buffer[tail];
+
+      /* Adjust indices and counts */
+
+      tail = noteram_next(tail, 1);
+      remaining--;
+    }
+
+  g_noteram_info.ni_tail = tail;
+
+errout_with_csection:
+  leave_critical_section(flags);
+  return notelen;
+}
+
+/****************************************************************************
+ * Name: noteram_size
+ *
+ * Description:
+ *   Return the size of the next note at the tail of the circular buffer.
+ *
+ * Input Parameters:
+ *   None.
+ *
+ * Returned Value:
+ *   Zero is returned if the circular buffer is empty.  Otherwise, the size
+ *   of the next note is returned.
+ *
+ ****************************************************************************/
+
+static ssize_t noteram_size(void)
+{
+  FAR struct note_common_s *note;
+  irqstate_t flags;
+  unsigned int tail;
+  ssize_t notelen;
+  size_t circlen;
+
+  flags = enter_critical_section();
+
+  /* Verify that the circular buffer is not empty */
+
+  circlen = noteram_length();
+  if (circlen <= 0)
+    {
+      notelen = 0;
+      goto errout_with_csection;
+    }
+
+  /* Get the index to the tail of the circular buffer */
+
+  tail = g_noteram_info.ni_tail;
+  DEBUGASSERT(tail < CONFIG_DRIVER_NOTERAM_BUFSIZE);
+
+  /* Get the length of the note at the tail index */
+
+  note    = (FAR struct note_common_s *)&g_noteram_info.ni_buffer[tail];
+  notelen = note->nc_length;
+  DEBUGASSERT(notelen <= circlen);
+
+errout_with_csection:
+  leave_critical_section(flags);
+  return notelen;
+}
+
+/****************************************************************************
+ * Name: noteram_read
+ ****************************************************************************/
+
+static ssize_t noteram_read(FAR struct file *filep,
+                            FAR char *buffer, size_t buflen)
+{
+  ssize_t notelen;
+  ssize_t retlen ;
+
+  DEBUGASSERT(filep != 0 && buffer != NULL && buflen > 0);
+
+  /* Then loop, adding as many notes as possible to the user buffer. */
+
+  retlen = 0;
+  sched_lock();
+  do
+    {
+      /* Get the next note (removing it from the buffer) */
+
+      notelen = noteram_get((FAR uint8_t *)buffer, buflen);
+      if (notelen < 0)
+        {
+          /* We were unable to read the next note, probably because it will
+           * not fit into the user buffer.
+           */
+
+          if (retlen == 0)
+            {
+              /* If nothing was read then report the error.  Otherwise,
+               * just silently drop the note.
+               */
+
+              retlen = notelen;
+            }
+
+          break;
+        }
+
+      /* Update pointers from the note that was transferred */
+
+      retlen += notelen;
+      buffer += notelen;
+      buflen -= notelen;
+
+      /* Will the next note fit?  There is a race here and even if the next
+       * note will fit, it may fail still when noteram_get() is called.
+       *
+       * It won't fit (or an error occurred).  Return what we have without
+       * trying to get the next note (which would cause it to be deleted).
+       */
+
+      notelen = noteram_size();
+    }
+  while (notelen > 0 && notelen <= buflen);
+
+  sched_unlock();
+  return retlen;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: note_add
+ *
+ * Description:
+ *   Add the variable length note to the transport layer
+ *
+ * Input Parameters:
+ *   note    - The note buffer
+ *   notelen - The buffer length
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   We are within a critical section.
+ *
+ ****************************************************************************/
+
+void note_add(FAR const uint8_t *note, uint8_t notelen)
+{
+  unsigned int head;
+  unsigned int next;
+
+#ifdef CONFIG_SMP
+  irqstate_t flags = up_irq_save();
+  spin_lock_wo_note(&g_noteram_lock);
+#endif
+
+  /* Get the index to the head of the circular buffer */
+
+  DEBUGASSERT(note != NULL && notelen < CONFIG_DRIVER_NOTERAM_BUFSIZE);
+  head = g_noteram_info.ni_head;
+
+  /* Loop until all bytes have been transferred to the circular buffer */
+
+  while (notelen > 0)
+    {
+      /* Get the next head index.  Would it collide with the current tail
+       * index?
+       */
+
+      next = noteram_next(head, 1);
+      if (next == g_noteram_info.ni_tail)
+        {
+          /* Yes, then remove the note at the tail index */
+
+          noteram_remove();
+        }
+
+      /* Save the next byte at the head index */
+
+      g_noteram_info.ni_buffer[head] = *note++;
+
+      head = next;
+      notelen--;
+    }
+
+  g_noteram_info.ni_head = head;
+
+#ifdef CONFIG_SMP
+  spin_unlock_wo_note(&g_noteram_lock);
+  up_irq_restore(flags);
+#endif
+}
+
+/****************************************************************************
+ * Name: noteram_register
+ *
+ * Description:
+ *   Register a serial driver at /dev/note that can be used by an
+ *   application to read data from the circular note buffer.
+ *
+ * Input Parameters:
+ *   None.
+ *
+ * Returned Value:
+ *   Zero is returned if the circular buffer is empty.  Otherwise, a negated
+ *   errno value is returned.
+ *
+ ****************************************************************************/
+
+int noteram_register(void)
+{
+  return register_driver("dev/note", &g_noteram_fops, 0666, NULL);

Review comment:
       The first "/" is missing.

##########
File path: drivers/note/noteram_driver.c
##########
@@ -0,0 +1,477 @@
+/****************************************************************************
+ * drivers/note/noteram_driver.c
+ *
+ *   Copyright (C) 2016 Gregory Nutt. All rights reserved.
+ *   Author: Gregory Nutt <gn...@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <sched.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <nuttx/spinlock.h>
+#include <nuttx/sched_note.h>
+#include <nuttx/note/noteram_driver.h>
+#include <nuttx/fs/fs.h>
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct noteram_info_s
+{
+  volatile unsigned int ni_head;
+  volatile unsigned int ni_tail;
+  uint8_t ni_buffer[CONFIG_DRIVER_NOTERAM_BUFSIZE];
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static ssize_t noteram_read(FAR struct file *filep,
+                            FAR char *buffer, size_t buflen);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_noteram_fops =
+{
+  NULL,          /* open */
+  NULL,          /* close */
+  noteram_read,  /* read */
+  NULL,          /* write */
+  NULL,          /* seek */
+  NULL,          /* ioctl */
+  NULL           /* poll */
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+  , 0            /* unlink */
+#endif
+};
+
+static struct noteram_info_s g_noteram_info;
+
+#ifdef CONFIG_SMP
+static volatile spinlock_t g_noteram_lock;
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: noteram_next
+ *
+ * Description:
+ *   Return the circular buffer index at offset from the specified index
+ *   value, handling wraparound
+ *
+ * Input Parameters:
+ *   ndx - Old circular buffer index
+ *
+ * Returned Value:
+ *   New circular buffer index
+ *
+ ****************************************************************************/
+
+static inline unsigned int noteram_next(unsigned int ndx,
+                                        unsigned int offset)
+{
+  ndx += offset;
+  if (ndx >= CONFIG_DRIVER_NOTERAM_BUFSIZE)
+    {
+      ndx -= CONFIG_DRIVER_NOTERAM_BUFSIZE;
+    }
+
+  return ndx;
+}
+
+/****************************************************************************
+ * Name: noteram_length
+ *
+ * Description:
+ *   Length of data currently in circular buffer.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Length of data currently in circular buffer.
+ *
+ ****************************************************************************/
+
+static unsigned int noteram_length(void)
+{
+  unsigned int head = g_noteram_info.ni_head;
+  unsigned int tail = g_noteram_info.ni_tail;
+
+  if (tail > head)
+    {
+      head += CONFIG_DRIVER_NOTERAM_BUFSIZE;
+    }
+
+  return head - tail;
+}
+
+/****************************************************************************
+ * Name: noteram_remove
+ *
+ * Description:
+ *   Remove the variable length note from the tail of the circular buffer
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   We are within a critical section.
+ *
+ ****************************************************************************/
+
+static void noteram_remove(void)
+{
+  FAR struct note_common_s *note;
+  unsigned int tail;
+  unsigned int length;
+
+  /* Get the tail index of the circular buffer */
+
+  tail = g_noteram_info.ni_tail;
+  DEBUGASSERT(tail < CONFIG_DRIVER_NOTERAM_BUFSIZE);
+
+  /* Get the length of the note at the tail index */
+
+  note   = (FAR struct note_common_s *)&g_noteram_info.ni_buffer[tail];
+  length = note->nc_length;
+  DEBUGASSERT(length <= noteram_length());
+
+  /* Increment the tail index to remove the entire note from the circular
+   * buffer.
+   */
+
+  g_noteram_info.ni_tail = noteram_next(tail, length);
+}
+
+/****************************************************************************
+ * Name: noteram_get
+ *
+ * Description:
+ *   Remove the next note from the tail of the circular buffer.  The note
+ *   is also removed from the circular buffer to make room for further notes.
+ *
+ * Input Parameters:
+ *   buffer - Location to return the next note
+ *   buflen - The length of the user provided buffer.
+ *
+ * Returned Value:
+ *   On success, the positive, non-zero length of the return note is
+ *   provided.  Zero is returned only if the circular buffer is empty.  A
+ *   negated errno value is returned in the event of any failure.
+ *
+ ****************************************************************************/
+
+static ssize_t noteram_get(FAR uint8_t *buffer, size_t buflen)
+{
+  FAR struct note_common_s *note;
+  irqstate_t flags;
+  unsigned int remaining;
+  unsigned int tail;
+  ssize_t notelen;
+  size_t circlen;
+
+  DEBUGASSERT(buffer != NULL);
+  flags = enter_critical_section();
+
+  /* Verify that the circular buffer is not empty */
+
+  circlen = noteram_length();
+  if (circlen <= 0)
+    {
+      notelen = 0;
+      goto errout_with_csection;
+    }
+
+  /* Get the index to the tail of the circular buffer */
+
+  tail    = g_noteram_info.ni_tail;
+  DEBUGASSERT(tail < CONFIG_DRIVER_NOTERAM_BUFSIZE);
+
+  /* Get the length of the note at the tail index */
+
+  note    = (FAR struct note_common_s *)&g_noteram_info.ni_buffer[tail];
+  notelen = note->nc_length;
+  DEBUGASSERT(notelen <= circlen);
+
+  /* Is the user buffer large enough to hold the note? */
+
+  if (buflen < notelen)
+    {
+      /* Remove the large note so that we do not get constipated. */
+
+      noteram_remove();
+
+      /* and return an error */
+
+      notelen = -EFBIG;
+      goto errout_with_csection;
+    }
+
+  /* Loop until the note has been transferred to the user buffer */
+
+  remaining = (unsigned int)notelen;
+  while (remaining > 0)
+    {
+      /* Copy the next byte at the tail index */
+
+      *buffer++ = g_noteram_info.ni_buffer[tail];
+
+      /* Adjust indices and counts */
+
+      tail = noteram_next(tail, 1);
+      remaining--;
+    }
+
+  g_noteram_info.ni_tail = tail;
+
+errout_with_csection:
+  leave_critical_section(flags);
+  return notelen;
+}
+
+/****************************************************************************
+ * Name: noteram_size
+ *
+ * Description:
+ *   Return the size of the next note at the tail of the circular buffer.
+ *
+ * Input Parameters:
+ *   None.
+ *
+ * Returned Value:
+ *   Zero is returned if the circular buffer is empty.  Otherwise, the size
+ *   of the next note is returned.
+ *
+ ****************************************************************************/
+
+static ssize_t noteram_size(void)
+{
+  FAR struct note_common_s *note;
+  irqstate_t flags;
+  unsigned int tail;
+  ssize_t notelen;
+  size_t circlen;
+
+  flags = enter_critical_section();
+
+  /* Verify that the circular buffer is not empty */
+
+  circlen = noteram_length();
+  if (circlen <= 0)
+    {
+      notelen = 0;
+      goto errout_with_csection;
+    }
+
+  /* Get the index to the tail of the circular buffer */
+
+  tail = g_noteram_info.ni_tail;
+  DEBUGASSERT(tail < CONFIG_DRIVER_NOTERAM_BUFSIZE);
+
+  /* Get the length of the note at the tail index */
+
+  note    = (FAR struct note_common_s *)&g_noteram_info.ni_buffer[tail];
+  notelen = note->nc_length;
+  DEBUGASSERT(notelen <= circlen);
+
+errout_with_csection:
+  leave_critical_section(flags);
+  return notelen;
+}
+
+/****************************************************************************
+ * Name: noteram_read
+ ****************************************************************************/
+
+static ssize_t noteram_read(FAR struct file *filep,
+                            FAR char *buffer, size_t buflen)
+{
+  ssize_t notelen;
+  ssize_t retlen ;
+
+  DEBUGASSERT(filep != 0 && buffer != NULL && buflen > 0);
+
+  /* Then loop, adding as many notes as possible to the user buffer. */
+
+  retlen = 0;
+  sched_lock();
+  do
+    {
+      /* Get the next note (removing it from the buffer) */
+
+      notelen = noteram_get((FAR uint8_t *)buffer, buflen);
+      if (notelen < 0)
+        {
+          /* We were unable to read the next note, probably because it will
+           * not fit into the user buffer.
+           */
+
+          if (retlen == 0)
+            {
+              /* If nothing was read then report the error.  Otherwise,
+               * just silently drop the note.
+               */
+
+              retlen = notelen;
+            }
+
+          break;
+        }
+
+      /* Update pointers from the note that was transferred */
+
+      retlen += notelen;
+      buffer += notelen;
+      buflen -= notelen;
+
+      /* Will the next note fit?  There is a race here and even if the next
+       * note will fit, it may fail still when noteram_get() is called.
+       *
+       * It won't fit (or an error occurred).  Return what we have without
+       * trying to get the next note (which would cause it to be deleted).
+       */
+
+      notelen = noteram_size();
+    }
+  while (notelen > 0 && notelen <= buflen);
+
+  sched_unlock();
+  return retlen;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: note_add
+ *
+ * Description:
+ *   Add the variable length note to the transport layer
+ *
+ * Input Parameters:
+ *   note    - The note buffer
+ *   notelen - The buffer length
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   We are within a critical section.
+ *
+ ****************************************************************************/
+
+void note_add(FAR const uint8_t *note, uint8_t notelen)
+{
+  unsigned int head;
+  unsigned int next;
+
+#ifdef CONFIG_SMP
+  irqstate_t flags = up_irq_save();
+  spin_lock_wo_note(&g_noteram_lock);
+#endif
+
+  /* Get the index to the head of the circular buffer */
+
+  DEBUGASSERT(note != NULL && notelen < CONFIG_DRIVER_NOTERAM_BUFSIZE);
+  head = g_noteram_info.ni_head;
+
+  /* Loop until all bytes have been transferred to the circular buffer */
+
+  while (notelen > 0)
+    {
+      /* Get the next head index.  Would it collide with the current tail
+       * index?
+       */
+
+      next = noteram_next(head, 1);
+      if (next == g_noteram_info.ni_tail)
+        {
+          /* Yes, then remove the note at the tail index */
+
+          noteram_remove();
+        }
+
+      /* Save the next byte at the head index */
+
+      g_noteram_info.ni_buffer[head] = *note++;
+
+      head = next;
+      notelen--;
+    }
+
+  g_noteram_info.ni_head = head;
+
+#ifdef CONFIG_SMP
+  spin_unlock_wo_note(&g_noteram_lock);
+  up_irq_restore(flags);
+#endif
+}
+
+/****************************************************************************
+ * Name: noteram_register
+ *
+ * Description:
+ *   Register a serial driver at /dev/note that can be used by an
+ *   application to read data from the circular note buffer.
+ *
+ * Input Parameters:
+ *   None.
+ *
+ * Returned Value:
+ *   Zero is returned if the circular buffer is empty.  Otherwise, a negated
+ *   errno value is returned.

Review comment:
       This comment is wrong. Zero is returned if the device is registered successfully.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org