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 d85c4db9321255555089f2a14354617d4a32aa44 Author: yangyalei <[email protected]> AuthorDate: Wed Jun 11 16:42:50 2025 +0800 nuttx/audio: Add Hardware pointer Add Hw pointer recored apb buffer read/write position Signed-off-by: yangyalei <[email protected]> --- audio/audio.c | 100 +++++++++++++++++++++++++++++++++----------- include/nuttx/audio/audio.h | 11 ++++- 2 files changed, 85 insertions(+), 26 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 232ea5311b3..a321c0d57e5 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -44,6 +44,7 @@ #include <nuttx/fs/fs.h> #include <nuttx/audio/audio.h> #include <nuttx/mutex.h> +#include <nuttx/spinlock.h> #include <arch/irq.h> @@ -73,12 +74,13 @@ struct audio_upperhalf_s { - uint8_t crefs; /* The number of times the device has been opened */ - volatile enum audio_state_e state; /* lowerhalf state */ - struct audio_info_s info; /* Record the last playing audio format */ - mutex_t lock; /* Supports mutual exclusion */ - FAR struct audio_lowerhalf_s *dev; /* lower-half state */ - struct file *usermq; /* User mode app's message queue */ + uint8_t crefs; /* The number of times the device has been opened */ + struct audio_info_s info; /* Record the last playing audio format */ + mutex_t lock; /* Supports mutual exclusion */ + spinlock_t spinlock; /* Supports spin lock */ + 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 */ }; /**************************************************************************** @@ -152,7 +154,20 @@ static int audio_open(FAR struct file *filep) ret = nxmutex_lock(&upper->lock); if (ret < 0) { - goto errout; + return ret; + } + + /* First open, alloc status memory */ + + if (upper->crefs == 0) + { + upper->status = kumm_zalloc(sizeof(struct audio_status_s)); + if (!upper->status) + { + auderr("ERROR: Allocation status failed\n"); + ret = -ENOMEM; + goto errout; + } } /* Increment the count of references to the device. If this the first @@ -166,7 +181,7 @@ static int audio_open(FAR struct file *filep) /* More than 255 opens; uint8_t overflows to zero */ ret = -EMFILE; - goto errout_with_lock; + goto errout; } /* Save the new open count on success */ @@ -174,10 +189,8 @@ static int audio_open(FAR struct file *filep) upper->crefs = tmp; ret = OK; -errout_with_lock: - nxmutex_unlock(&upper->lock); - errout: + nxmutex_unlock(&upper->lock); return ret; } @@ -228,7 +241,8 @@ static int audio_close(FAR struct file *filep) lower->ops->shutdown(lower); upper->usermq = NULL; - upper->state = AUDIO_STATE_OPEN; + kumm_free(upper->status); + upper->status = NULL; } ret = OK; @@ -294,6 +308,24 @@ static ssize_t audio_write(FAR struct file *filep, return 0; } +/**************************************************************************** + * Name: audio_setstate + * + * Description: + * Update lower driver state + * + ****************************************************************************/ + +static inline void audio_setstate(FAR struct audio_upperhalf_s *upper, + int state) +{ + irqstate_t flags; + + flags = spin_lock_irqsave(&upper->spinlock); + upper->status->state = state; + spin_unlock_irqrestore(&upper->spinlock, flags); +} + /**************************************************************************** * Name: audio_configure * @@ -320,7 +352,7 @@ static int audio_configure(FAR struct audio_upperhalf_s *upper, if (ret == OK && (caps->ac_type == AUDIO_TYPE_INPUT || caps->ac_type == AUDIO_TYPE_OUTPUT)) { - upper->state = AUDIO_STATE_PREPARED; + audio_setstate(upper, AUDIO_STATE_PREPARED); upper->info.format = caps->ac_subtype; upper->info.channels = caps->ac_channels; upper->info.subformat = caps->ac_controls.b[2]; @@ -353,7 +385,7 @@ static int audio_start(FAR struct audio_upperhalf_s *upper) /* Verify that the Audio is not already running */ - if (upper->state == AUDIO_STATE_PREPARED) + if (upper->status->state == AUDIO_STATE_PREPARED) { /* Invoke the bottom half method to start the audio stream */ @@ -371,7 +403,7 @@ static int audio_start(FAR struct audio_upperhalf_s *upper) { /* Indicate that the audio stream has started */ - upper->state = AUDIO_STATE_RUNNING; + audio_setstate(upper, AUDIO_STATE_RUNNING); } } @@ -395,6 +427,7 @@ static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg) #ifdef CONFIG_AUDIO_MULTI_SESSION FAR void *session; #endif + irqstate_t flags; int ret; audinfo("cmd: %d arg: %ld\n", cmd, arg); @@ -489,8 +522,8 @@ static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg) audinfo("AUDIOIOC_STOP\n"); DEBUGASSERT(lower->ops->stop != NULL); - if (upper->state == AUDIO_STATE_RUNNING || - upper->state == AUDIO_STATE_PAUSED) + if (upper->status->state == AUDIO_STATE_RUNNING || + upper->status->state == AUDIO_STATE_PAUSED) { #ifdef CONFIG_AUDIO_MULTI_SESSION session = (FAR void *) arg; @@ -500,7 +533,7 @@ static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg) #endif if (ret == OK) { - upper->state = AUDIO_STATE_DRAINING; + audio_setstate(upper, AUDIO_STATE_DRAINING); } } } @@ -519,7 +552,7 @@ static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg) audinfo("AUDIOIOC_PAUSE\n"); DEBUGASSERT(lower->ops->pause != NULL); - if (upper->state == AUDIO_STATE_RUNNING) + if (upper->status->state == AUDIO_STATE_RUNNING) { #ifdef CONFIG_AUDIO_MULTI_SESSION session = (FAR void *) arg; @@ -529,7 +562,7 @@ static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg) #endif if (ret == OK) { - upper->state = AUDIO_STATE_PAUSED; + audio_setstate(upper, AUDIO_STATE_PAUSED); } } } @@ -545,7 +578,7 @@ static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg) audinfo("AUDIOIOC_RESUME\n"); DEBUGASSERT(lower->ops->resume != NULL); - if (upper->state == AUDIO_STATE_PAUSED) + if (upper->status->state == AUDIO_STATE_PAUSED) { #ifdef CONFIG_AUDIO_MULTI_SESSION session = (FAR void *) arg; @@ -555,7 +588,7 @@ static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg) #endif if (ret == OK) { - upper->state = AUDIO_STATE_RUNNING; + audio_setstate(upper, AUDIO_STATE_RUNNING); } } } @@ -624,6 +657,12 @@ static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg) bufdesc = (FAR struct audio_buf_desc_s *) arg; ret = lower->ops->enqueuebuffer(lower, bufdesc->u.buffer); + if (ret == OK) + { + flags = spin_lock_irqsave_nopreempt(&upper->spinlock); + upper->status->head++; + spin_unlock_irqrestore_nopreempt(&upper->spinlock, flags); + } } break; @@ -707,14 +746,14 @@ static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg) } break; - /* AUDIOIOC_GETSTATE - Get lower driver state + /* AUDIOIOC_GETSTATUS - Get lower driver state * * ioctl argument - pointer to receive the state */ - case AUDIOIOC_GETSTATE: + case AUDIOIOC_GETSTATUS: { - *(FAR enum audio_state_e *)arg = upper->state; + memcpy((void *)arg, upper->status, sizeof(struct audio_status_s)); ret = OK; } break; @@ -778,9 +817,14 @@ static inline void audio_dequeuebuffer(FAR struct audio_upperhalf_s *upper, #endif { struct audio_msg_s msg; + irqstate_t flags; audinfo("Entry\n"); + flags = spin_lock_irqsave_nopreempt(&upper->spinlock); + upper->status->tail++; + spin_unlock_irqrestore_nopreempt(&upper->spinlock, flags); + /* Send a dequeue message to the user if a message queue is registered */ if (upper->usermq != NULL) @@ -819,6 +863,11 @@ static inline void audio_complete(FAR struct audio_upperhalf_s *upper, audinfo("Entry\n"); + if (upper->status != NULL) + { + audio_setstate(upper, AUDIO_STATE_OPEN); + } + /* Send a dequeue message to the user if a message queue is registered */ if (upper->usermq != NULL) @@ -1104,6 +1153,7 @@ int audio_register(FAR const char *name, FAR struct audio_lowerhalf_s *dev) */ nxmutex_init(&upper->lock); + spin_lock_init(&upper->spinlock); upper->dev = dev; #ifdef CONFIG_AUDIO_CUSTOM_DEV_PATH diff --git a/include/nuttx/audio/audio.h b/include/nuttx/audio/audio.h index 29e4d789a61..a206ec25362 100644 --- a/include/nuttx/audio/audio.h +++ b/include/nuttx/audio/audio.h @@ -118,7 +118,7 @@ #define AUDIOIOC_FLUSH _AUDIOIOC(20) #define AUDIOIOC_GETPOSITION _AUDIOIOC(21) #define AUDIOIOC_GETAUDIOINFO _AUDIOIOC(22) -#define AUDIOIOC_GETSTATE _AUDIOIOC(23) +#define AUDIOIOC_GETSTATUS _AUDIOIOC(23) /* Audio Device Types *******************************************************/ @@ -398,6 +398,15 @@ typedef uint32_t apb_samp_t; typedef uint16_t apb_samp_t; #endif +/* This structure describes the lower driver status */ + +struct audio_status_s +{ + volatile int state; + volatile unsigned long head; + volatile unsigned long tail; +}; + /* This structure is used to describe the audio device capabilities */ struct audio_caps_s
