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

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 06e233079f46f42f37def1c81a11f460cd923d4e
Author: yangyalei <[email protected]>
AuthorDate: Fri May 30 19:16:09 2025 +0800

    nuttx/audio: support record/release apb buffer in upper driver
    
    support maintain apb buffer in upper half driver
    
    Signed-off-by: yangyalei <[email protected]>
---
 audio/audio.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 110 insertions(+), 22 deletions(-)

diff --git a/audio/audio.c b/audio/audio.c
index a321c0d57e5..e9be095dab7 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -78,6 +78,8 @@ struct audio_upperhalf_s
   struct audio_info_s          info;     /* Record the last playing audio 
format */
   mutex_t                      lock;     /* Supports mutual exclusion */
   spinlock_t                   spinlock; /* Supports spin lock */
+  uint8_t                      periods;  /* Ap buffers number */
+  FAR struct ap_buffer_s       **apbs;   /* Ap buffers list */
   FAR struct audio_lowerhalf_s *dev;     /* lower-half state */
   struct audio_status_s        *status;  /* lowerhalf driver status */
   struct file                  *usermq;  /* User mode app's message queue */
@@ -98,6 +100,10 @@ static ssize_t  audio_write(FAR struct file *filep,
 static int      audio_ioctl(FAR struct file *filep,
                             int cmd,
                             unsigned long arg);
+static int      audio_allocbuffer(FAR struct audio_upperhalf_s *upper,
+                                  FAR struct audio_buf_desc_s * bufdesc);
+static int      audio_freebuffer(FAR struct audio_upperhalf_s *upper,
+                                 FAR struct audio_buf_desc_s * bufdesc);
 #ifdef CONFIG_AUDIO_MULTI_SESSION
 static int      audio_start(FAR struct audio_upperhalf_s *upper,
                             FAR void *session);
@@ -606,16 +612,7 @@ static int audio_ioctl(FAR struct file *filep, int cmd, 
unsigned long arg)
           audinfo("AUDIOIOC_ALLOCBUFFER\n");
 
           bufdesc = (FAR struct audio_buf_desc_s *) arg;
-          if (lower->ops->allocbuffer)
-            {
-              ret = lower->ops->allocbuffer(lower, bufdesc);
-            }
-          else
-            {
-              /* Perform a simple kumm_malloc operation assuming 1 session */
-
-              ret = apb_alloc(bufdesc);
-            }
+          ret = audio_allocbuffer(upper, bufdesc);
         }
         break;
 
@@ -629,18 +626,7 @@ static int audio_ioctl(FAR struct file *filep, int cmd, 
unsigned long arg)
           audinfo("AUDIOIOC_FREEBUFFER\n");
 
           bufdesc = (FAR struct audio_buf_desc_s *) arg;
-          if (lower->ops->freebuffer)
-            {
-              ret = lower->ops->freebuffer(lower, bufdesc);
-            }
-          else
-            {
-              /* Perform a simple apb_free operation */
-
-              DEBUGASSERT(bufdesc->u.buffer != NULL);
-              apb_free(bufdesc->u.buffer);
-              ret = sizeof(struct audio_buf_desc_s);
-            }
+          ret = audio_freebuffer(upper, bufdesc);
         }
         break;
 
@@ -775,6 +761,108 @@ static int audio_ioctl(FAR struct file *filep, int cmd, 
unsigned long arg)
   return ret;
 }
 
+/****************************************************************************
+ * Name: audio_allocbuffer
+ *
+ * Description:
+ *   Handle the AUDIOIOC_ALLOCBUFFER ioctl command
+ *
+ ****************************************************************************/
+
+static int audio_allocbuffer(FAR struct audio_upperhalf_s *upper,
+                             FAR struct audio_buf_desc_s *bufdesc)
+{
+  FAR struct audio_lowerhalf_s *lower = upper->dev;
+  FAR struct ap_buffer_s *apb;
+  bool share = false;
+  FAR void *newaddr;
+  int ret;
+
+  if (bufdesc->u.pbuffer == NULL)
+    {
+      bufdesc->u.pbuffer = &apb;
+      share = true;
+    }
+
+  if (lower->ops->allocbuffer)
+    {
+      ret = lower->ops->allocbuffer(lower, bufdesc);
+    }
+  else
+    {
+      /* Perform a simple kumm_malloc operation assuming 1 session */
+
+      ret = apb_alloc(bufdesc);
+    }
+
+  if (ret > 0 && share)
+    {
+      newaddr = kmm_realloc(upper->apbs,
+                            (upper->periods + 1) * sizeof(*upper->apbs));
+      if (newaddr == NULL)
+        {
+          audio_freebuffer(upper, bufdesc);
+          return -ENOMEM;
+        }
+
+      upper->apbs = (FAR struct ap_buffer_s **)newaddr;
+      upper->apbs[upper->periods] = apb;
+      upper->periods++;
+      bufdesc->u.pbuffer = NULL;
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: audio_freebuffer
+ *
+ * Description:
+ *   Handle the AUDIOIOC_FREEBUFFER ioctl command
+ *
+ ****************************************************************************/
+
+static int audio_freebuffer(FAR struct audio_upperhalf_s *upper,
+                            FAR struct audio_buf_desc_s *bufdesc)
+{
+  FAR struct audio_lowerhalf_s *lower = upper->dev;
+  bool share = false;
+  int ret;
+
+  if (bufdesc->u.buffer == NULL)
+    {
+      bufdesc->u.buffer = upper->apbs[upper->periods - 1];
+      share = true;
+    }
+
+  if (lower->ops->freebuffer)
+    {
+      ret = lower->ops->freebuffer(lower, bufdesc);
+    }
+  else
+    {
+      /* Perform a simple apb_free operation */
+
+      DEBUGASSERT(bufdesc->u.buffer != NULL);
+      apb_free(bufdesc->u.buffer);
+      ret = sizeof(struct audio_buf_desc_s);
+    }
+
+  if (ret > 0 && share)
+    {
+      bufdesc->u.buffer = NULL;
+      upper->apbs[upper->periods] = NULL;
+      upper->periods--;
+      if (upper->periods == 0)
+        {
+          kmm_free(upper->apbs);
+          upper->apbs = NULL;
+        }
+    }
+
+  return ret;
+}
+
 /****************************************************************************
  * Name: audio_dequeuebuffer
  *

Reply via email to