From 0f7edd8f0b5171f625c8695fee6db92e10a3e718 Mon Sep 17 00:00:00 2001 From: SPRESENSE <41312067+SPRESENSE@users.noreply.github.com> Date: Tue, 27 Feb 2024 13:54:32 +0900 Subject: [PATCH] audio: Add setup method and add reference counter on shutdown Add an 'setup' method on the 'struct audio_ops_s' to notify to the driver that the related device file has been opened and is ready for use. And also add refcount argument on shutdown method to know how many device file is still opened. --- arch/arm/src/cxd56xx/cxd56_nxaudio.c | 5 ++- arch/arm/src/sama5/sam_classd.c | 3 +- arch/sim/src/sim/posix/sim_alsa.c | 5 ++- audio/audio.c | 63 +++++++++++++++++++++++++++- audio/audio_comp.c | 52 +++++++++++++++++++++-- audio/pcm_decode.c | 37 ++++++++++++++-- drivers/audio/audio_dma.c | 5 ++- drivers/audio/audio_i2s.c | 7 ++-- drivers/audio/audio_null.c | 3 +- drivers/audio/cs4344.c | 5 ++- drivers/audio/cs43l22.c | 5 ++- drivers/audio/es8311.c | 5 ++- drivers/audio/es8388.c | 5 ++- drivers/audio/vs1053.c | 3 +- drivers/audio/wm8776.c | 5 ++- drivers/audio/wm8904.c | 5 ++- drivers/audio/wm8994.c | 5 ++- drivers/virtio/virtio-snd.c | 5 ++- include/nuttx/audio/audio.h | 8 +++- 19 files changed, 193 insertions(+), 38 deletions(-) diff --git a/arch/arm/src/cxd56xx/cxd56_nxaudio.c b/arch/arm/src/cxd56xx/cxd56_nxaudio.c index 6551111157b98..99c8d04cdc98d 100644 --- a/arch/arm/src/cxd56xx/cxd56_nxaudio.c +++ b/arch/arm/src/cxd56xx/cxd56_nxaudio.c @@ -381,7 +381,7 @@ static int cxd56_release(struct audio_lowerhalf_s *lower); static int cxd56_getcaps(struct audio_lowerhalf_s *lower, int type, struct audio_caps_s *caps); -static int cxd56_shutdown(struct audio_lowerhalf_s *lower); +static int cxd56_shutdown(struct audio_lowerhalf_s *lower, int opencnt); static int cxd56_enqueuebuffer(struct audio_lowerhalf_s *lower, struct ap_buffer_s *apb); static int cxd56_cancelbuffer(struct audio_lowerhalf_s *lower, @@ -438,6 +438,7 @@ static uint16_t g_codec_start_count = 0; static const struct audio_ops_s g_audioops = { + NULL, /* setup */ cxd56_getcaps, /* getcaps */ cxd56_configure, /* configure */ cxd56_shutdown, /* shutdown */ @@ -2698,7 +2699,7 @@ static int cxd56_getcaps(struct audio_lowerhalf_s *lower, int type, * ****************************************************************************/ -static int cxd56_shutdown(struct audio_lowerhalf_s *lower) +static int cxd56_shutdown(struct audio_lowerhalf_s *lower, int opencnt) { int ret; struct cxd56_dev_s *priv = (struct cxd56_dev_s *)lower; diff --git a/arch/arm/src/sama5/sam_classd.c b/arch/arm/src/sama5/sam_classd.c index 74adb4fa313a2..450df55e9c18a 100644 --- a/arch/arm/src/sama5/sam_classd.c +++ b/arch/arm/src/sama5/sam_classd.c @@ -554,6 +554,7 @@ static struct sam_classd_config_s sam_classd_const = static const struct audio_ops_s g_audioops = { + NULL, /* setup */ classd_getcaps, /* getcaps */ classd_configure, /* configure */ classd_shutdown, /* shutdown */ @@ -1747,7 +1748,7 @@ static int classd_configure(struct audio_lowerhalf_s *dev, * ****************************************************************************/ -static int classd_shutdown(struct audio_lowerhalf_s *dev) +static int classd_shutdown(struct audio_lowerhalf_s *dev, int cnt) { struct classd_dev_s *priv = (struct classd_dev_s *)dev; diff --git a/arch/sim/src/sim/posix/sim_alsa.c b/arch/sim/src/sim/posix/sim_alsa.c index bf6fc06e7529c..0eb5c44535e80 100644 --- a/arch/sim/src/sim/posix/sim_alsa.c +++ b/arch/sim/src/sim/posix/sim_alsa.c @@ -104,7 +104,7 @@ static int sim_audio_resume(struct audio_lowerhalf_s *dev); static int sim_audio_reserve(struct audio_lowerhalf_s *dev); static int sim_audio_release(struct audio_lowerhalf_s *dev); #endif -static int sim_audio_shutdown(struct audio_lowerhalf_s *dev); +static int sim_audio_shutdown(struct audio_lowerhalf_s *dev, int cnt); static int sim_audio_enqueuebuffer(struct audio_lowerhalf_s *dev, struct ap_buffer_s *apb); static int sim_audio_ioctl(struct audio_lowerhalf_s *dev, int cmd, @@ -115,6 +115,7 @@ static int sim_audio_ioctl(struct audio_lowerhalf_s *dev, int cmd, static const struct audio_ops_s g_sim_audio_ops = { + .setup = NULL, .getcaps = sim_audio_getcaps, .configure = sim_audio_configure, .shutdown = sim_audio_shutdown, @@ -484,7 +485,7 @@ static int sim_audio_configure(struct audio_lowerhalf_s *dev, return ret; } -static int sim_audio_shutdown(struct audio_lowerhalf_s *dev) +static int sim_audio_shutdown(struct audio_lowerhalf_s *dev, int cnt) { return 0; } diff --git a/audio/audio.c b/audio/audio.c index 3bc906e9836cc..aeec0dbe00acd 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -139,6 +139,7 @@ static int audio_open(FAR struct file *filep) { FAR struct inode *inode = filep->f_inode; FAR struct audio_upperhalf_s *upper = inode->i_private; + FAR struct audio_lowerhalf_s *lower = upper->dev; uint8_t tmp; int ret; @@ -166,6 +167,17 @@ static int audio_open(FAR struct file *filep) goto errout_with_lock; } + /* Call open method of lowerhalf if exist */ + + if (lower && lower->ops && lower->ops->setup) + { + ret = lower->ops->setup(lower, tmp); + if (ret < 0) + { + goto errout_with_lock; + } + } + /* Save the new open count on success */ upper->crefs = tmp; @@ -223,7 +235,7 @@ static int audio_close(FAR struct file *filep) DEBUGASSERT(lower->ops->shutdown != NULL); audinfo("calling shutdown\n"); - lower->ops->shutdown(lower); + lower->ops->shutdown(lower, upper->crefs); upper->usermq = NULL; } @@ -415,7 +427,8 @@ static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg) /* Call the lower-half driver initialize handler */ - ret = lower->ops->shutdown(lower); + ret = lower->ops->shutdown(lower, upper->crefs); + upper->started = false; } break; @@ -479,6 +492,7 @@ static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg) audinfo("AUDIOIOC_PAUSE\n"); DEBUGASSERT(lower->ops->pause != NULL); + ret = -EAGAIN; if (upper->started) { #ifdef CONFIG_AUDIO_MULTI_SESSION @@ -501,6 +515,7 @@ static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg) audinfo("AUDIOIOC_RESUME\n"); DEBUGASSERT(lower->ops->resume != NULL); + ret = -EAGAIN; if (upper->started) { #ifdef CONFIG_AUDIO_MULTI_SESSION @@ -723,6 +738,45 @@ static inline void audio_dequeuebuffer(FAR struct audio_upperhalf_s *upper, } } +/**************************************************************************** + * Name: audio_ioerror + * + * Description: + * Send an AUDIO_MSG_IOERROR message to the client to indicate that a + * something error was happend in lower-half driver. The lower-half + * driver initiates this call via its callback pointer to our upper-half + * driver. + * + ****************************************************************************/ + +#ifdef CONFIG_AUDIO_MULTI_SESSION +static inline void audio_ioerror(FAR struct audio_upperhalf_s *upper, + FAR struct ap_buffer_s *apb, uint16_t status, + FAR void *session) +#else +static inline void audio_ioerror(FAR struct audio_upperhalf_s *upper, + FAR struct ap_buffer_s *apb, uint16_t status) +#endif +{ + struct audio_msg_s msg; + + audinfo("Entry\n"); + + /* Send a dequeue message to the user if a message queue is registered */ + + upper->started = false; + if (upper->usermq != NULL) + { + msg.msg_id = AUDIO_MSG_IOERROR; + msg.u.data = (uint32_t)status; +#ifdef CONFIG_AUDIO_MULTI_SESSION + msg.session = session; +#endif + file_mq_send(upper->usermq, (FAR const char *)&msg, sizeof(msg), + CONFIG_AUDIO_BUFFER_DEQUEUE_PRIO); + } +} + /**************************************************************************** * Name: audio_complete * @@ -849,6 +903,11 @@ static void audio_callback(FAR void *handle, uint16_t reason, case AUDIO_CALLBACK_IOERR: { +#ifdef CONFIG_AUDIO_MULTI_SESSION + audio_ioerror(upper, apb, status, session); +#else + audio_ioerror(upper, apb, status); +#endif } break; diff --git a/audio/audio_comp.c b/audio/audio_comp.c index d9957da3131c4..87e91502465e2 100644 --- a/audio/audio_comp.c +++ b/audio/audio_comp.c @@ -57,6 +57,7 @@ struct audio_comp_priv_s * Private Function Prototypes ****************************************************************************/ +static int audio_comp_setup(FAR struct audio_lowerhalf_s *dev, int opencnt); static int audio_comp_getcaps(FAR struct audio_lowerhalf_s *dev, int type, FAR struct audio_caps_s *caps); #ifdef CONFIG_AUDIO_MULTI_SESSION @@ -67,7 +68,7 @@ static int audio_comp_configure(FAR struct audio_lowerhalf_s *dev, static int audio_comp_configure(FAR struct audio_lowerhalf_s *dev, FAR const struct audio_caps_s *caps); #endif -static int audio_comp_shutdown(FAR struct audio_lowerhalf_s *dev); +static int audio_comp_shutdown(FAR struct audio_lowerhalf_s *dev, int cnt); #ifdef CONFIG_AUDIO_MULTI_SESSION static int audio_comp_start(FAR struct audio_lowerhalf_s *dev, FAR void *session); @@ -137,6 +138,7 @@ static void audio_comp_callback(FAR void *arg, uint16_t reason, static const struct audio_ops_s g_audio_comp_ops = { + audio_comp_setup, /* setup */ audio_comp_getcaps, /* getcaps */ audio_comp_configure, /* configure */ audio_comp_shutdown, /* shutdown */ @@ -163,6 +165,50 @@ static const struct audio_ops_s g_audio_comp_ops = * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: audio_comp_setup + * + * Description: Call lower device driver's setup + * + ****************************************************************************/ + +static int audio_comp_setup(FAR struct audio_lowerhalf_s *dev, int cnt) +{ + FAR struct audio_comp_priv_s *priv = (FAR struct audio_comp_priv_s *)dev; + FAR struct audio_lowerhalf_s **lower = priv->lower; + int i; + int ret; + + for (i = 0; i < priv->count; i++) + { + if (lower[i]->ops->setup) + { + ret = lower[i]->ops->setup(lower[i], cnt); + if (ret < 0) + { + break; + } + } + } + + /* If an error is occured on a lower device, + * shutdown of lower device which is already opened is called. + */ + + if (i != priv->count) + { + for (; i >= 0; i--) + { + if (lower[i]->ops->open && lower[i]->ops->shutdown) + { + lower[i]->ops->shutdown(lower[i], cnt - 1); + } + } + } + + return ret; +} + /**************************************************************************** * Name: audio_comp_getcaps * @@ -280,7 +326,7 @@ static int audio_comp_configure(FAR struct audio_lowerhalf_s *dev, * ****************************************************************************/ -static int audio_comp_shutdown(FAR struct audio_lowerhalf_s *dev) +static int audio_comp_shutdown(FAR struct audio_lowerhalf_s *dev, int cnt) { FAR struct audio_comp_priv_s *priv = (FAR struct audio_comp_priv_s *)dev; FAR struct audio_lowerhalf_s **lower = priv->lower; @@ -291,7 +337,7 @@ static int audio_comp_shutdown(FAR struct audio_lowerhalf_s *dev) { if (lower[i]->ops->shutdown) { - int tmp = lower[i]->ops->shutdown(lower[i]); + int tmp = lower[i]->ops->shutdown(lower[i], cnt); if (tmp == -ENOTTY) { continue; diff --git a/audio/pcm_decode.c b/audio/pcm_decode.c index 60c8b9af4d9fe..3cab75113652e 100644 --- a/audio/pcm_decode.c +++ b/audio/pcm_decode.c @@ -122,6 +122,8 @@ static void pcm_subsample(FAR struct pcm_decode_s *priv, /* struct audio_lowerhalf_s methods *****************************************/ +static int pcm_setup(FAR struct audio_lowerhalf_s *dev, int opencnt); + static int pcm_getcaps(FAR struct audio_lowerhalf_s *dev, int type, FAR struct audio_caps_s *caps); @@ -133,7 +135,7 @@ static int pcm_configure(FAR struct audio_lowerhalf_s *dev, FAR const struct audio_caps_s *caps); #endif -static int pcm_shutdown(FAR struct audio_lowerhalf_s *dev); +static int pcm_shutdown(FAR struct audio_lowerhalf_s *dev, int cnt); #ifdef CONFIG_AUDIO_MULTI_SESSION static int pcm_start(FAR struct audio_lowerhalf_s *dev, FAR void *session); @@ -665,6 +667,34 @@ static void pcm_subsample(FAR struct pcm_decode_s *priv, } #endif +/**************************************************************************** + * Name: pcm_setup + * + * Description: + * This method is called when the related device file is opened. + * And then next lower's setup is called in this method. + * + ****************************************************************************/ + +static int pcm_setup(FAR struct audio_lowerhalf_s *dev, int opencnt) +{ + FAR struct pcm_decode_s *priv = (FAR struct pcm_decode_s *)dev; + FAR struct audio_lowerhalf_s *lower; + + DEBUGASSERT(priv); + + lower = priv->lower; + + DEBUGASSERT(lower); + + if (lower->ops && lower->ops->setup) + { + return lower->ops->setup(lower, opencnt); + } + + return OK; +} + /**************************************************************************** * Name: pcm_getcaps * @@ -788,7 +818,7 @@ static int pcm_configure(FAR struct audio_lowerhalf_s *dev, * ****************************************************************************/ -static int pcm_shutdown(FAR struct audio_lowerhalf_s *dev) +static int pcm_shutdown(FAR struct audio_lowerhalf_s *dev, int cnt) { FAR struct pcm_decode_s *priv = (FAR struct pcm_decode_s *)dev; FAR struct audio_lowerhalf_s *lower; @@ -805,7 +835,7 @@ static int pcm_shutdown(FAR struct audio_lowerhalf_s *dev) DEBUGASSERT(lower && lower->ops->start); audinfo("Defer to lower shutdown\n"); - return lower->ops->shutdown(lower); + return lower->ops->shutdown(lower, cnt); } /**************************************************************************** @@ -1403,6 +1433,7 @@ FAR struct audio_lowerhalf_s * /* Setup our operations */ ops = &priv->ops; + ops->setup = pcm_setup; ops->getcaps = pcm_getcaps; ops->configure = pcm_configure; ops->shutdown = pcm_shutdown; diff --git a/drivers/audio/audio_dma.c b/drivers/audio/audio_dma.c index 10b5c753ec7e5..1e7f228389789 100644 --- a/drivers/audio/audio_dma.c +++ b/drivers/audio/audio_dma.c @@ -55,7 +55,7 @@ struct audio_dma_s static int audio_dma_getcaps(struct audio_lowerhalf_s *dev, int type, struct audio_caps_s *caps); -static int audio_dma_shutdown(struct audio_lowerhalf_s *dev); +static int audio_dma_shutdown(struct audio_lowerhalf_s *dev, int cnt); #ifdef CONFIG_AUDIO_MULTI_SESSION static int audio_dma_configure(struct audio_lowerhalf_s *dev, void *session, @@ -106,6 +106,7 @@ static void audio_dma_callback(struct dma_chan_s *chan, void *arg, static const struct audio_ops_s g_audio_dma_ops = { + .setup = NULL, .getcaps = audio_dma_getcaps, .configure = audio_dma_configure, .shutdown = audio_dma_shutdown, @@ -255,7 +256,7 @@ static int audio_dma_configure(struct audio_lowerhalf_s *dev, return ret; } -static int audio_dma_shutdown(struct audio_lowerhalf_s *dev) +static int audio_dma_shutdown(struct audio_lowerhalf_s *dev, int cnt) { /* apps enqueued buffers, but doesn't start. stop here to * clear audio_dma->pendq. diff --git a/drivers/audio/audio_i2s.c b/drivers/audio/audio_i2s.c index c427b6e5ed1fe..65628c414b819 100644 --- a/drivers/audio/audio_i2s.c +++ b/drivers/audio/audio_i2s.c @@ -48,7 +48,7 @@ struct audio_i2s_s static int audio_i2s_getcaps(FAR struct audio_lowerhalf_s *dev, int type, FAR struct audio_caps_s *caps); -static int audio_i2s_shutdown(FAR struct audio_lowerhalf_s *dev); +static int audio_i2s_shutdown(FAR struct audio_lowerhalf_s *dev, int cnt); #ifdef CONFIG_AUDIO_MULTI_SESSION static int audio_i2s_configure(FAR struct audio_lowerhalf_s *dev, FAR void *session, @@ -101,6 +101,7 @@ static void audio_i2s_callback(struct i2s_dev_s *dev, static const struct audio_ops_s g_audio_i2s_ops = { + NULL, /* setup */ audio_i2s_getcaps, /* getcaps */ audio_i2s_configure, /* configure */ audio_i2s_shutdown, /* shutdown */ @@ -185,9 +186,7 @@ static int audio_i2s_getcaps(FAR struct audio_lowerhalf_s *dev, int type, /* Report the Sample rates we support */ caps->ac_controls.hw[0] = AUDIO_SAMP_RATE_DEF_ALL; - caps->ac_channels = 2; - break; } @@ -255,7 +254,7 @@ static int audio_i2s_configure(FAR struct audio_lowerhalf_s *dev, return ret; } -static int audio_i2s_shutdown(FAR struct audio_lowerhalf_s *dev) +static int audio_i2s_shutdown(FAR struct audio_lowerhalf_s *dev, int cnt) { FAR struct audio_i2s_s *audio_i2s = (struct audio_i2s_s *)dev; FAR struct i2s_dev_s *i2s = audio_i2s->i2s; diff --git a/drivers/audio/audio_null.c b/drivers/audio/audio_null.c index 427f32bf23108..b015bde8b4b63 100644 --- a/drivers/audio/audio_null.c +++ b/drivers/audio/audio_null.c @@ -132,6 +132,7 @@ static int null_sleep(FAR struct audio_lowerhalf_s *dev, static const struct audio_ops_s g_audioops = { + NULL, /* setup */ null_getcaps, /* getcaps */ null_configure, /* configure */ null_shutdown, /* shutdown */ @@ -451,7 +452,7 @@ static int null_configure(FAR struct audio_lowerhalf_s *dev, * ****************************************************************************/ -static int null_shutdown(FAR struct audio_lowerhalf_s *dev) +static int null_shutdown(FAR struct audio_lowerhalf_s *dev, int cnt) { audinfo("Return OK\n"); return OK; diff --git a/drivers/audio/cs4344.c b/drivers/audio/cs4344.c index cfdc37c3700c8..b54b6e087e036 100644 --- a/drivers/audio/cs4344.c +++ b/drivers/audio/cs4344.c @@ -71,7 +71,7 @@ static int cs4344_configure(FAR struct audio_lowerhalf_s *dev, static int cs4344_configure(FAR struct audio_lowerhalf_s *dev, FAR const struct audio_caps_s *caps); #endif -static int cs4344_shutdown(FAR struct audio_lowerhalf_s *dev); +static int cs4344_shutdown(FAR struct audio_lowerhalf_s *dev, int cnt); static void cs4344_senddone(FAR struct i2s_dev_s *i2s, FAR struct ap_buffer_s *apb, FAR void *arg, int result); @@ -134,6 +134,7 @@ static int cs4344_reset(FAR struct cs4344_dev_s *priv); static const struct audio_ops_s g_audioops = { + NULL, /* setup */ cs4344_getcaps, /* getcaps */ cs4344_configure, /* configure */ cs4344_shutdown, /* shutdown */ @@ -627,7 +628,7 @@ cs4344_configure(FAR struct audio_lowerhalf_s *dev, * ****************************************************************************/ -static int cs4344_shutdown(FAR struct audio_lowerhalf_s *dev) +static int cs4344_shutdown(FAR struct audio_lowerhalf_s *dev, int cnt) { FAR struct cs4344_dev_s *priv = (FAR struct cs4344_dev_s *)dev; diff --git a/drivers/audio/cs43l22.c b/drivers/audio/cs43l22.c index 299518f028317..8523b5335767b 100644 --- a/drivers/audio/cs43l22.c +++ b/drivers/audio/cs43l22.c @@ -88,7 +88,7 @@ static int cs43l22_configure(FAR struct audio_lowerhalf_s *dev, static int cs43l22_configure(FAR struct audio_lowerhalf_s *dev, FAR const struct audio_caps_s *caps); #endif -static int cs43l22_shutdown(FAR struct audio_lowerhalf_s *dev); +static int cs43l22_shutdown(FAR struct audio_lowerhalf_s *dev, int cnt); static void cs43l22_senddone(FAR struct i2s_dev_s *i2s, FAR struct ap_buffer_s *apb, FAR void *arg, int result); @@ -168,6 +168,7 @@ static void cs43l22_reset(FAR struct cs43l22_dev_s *priv); static const struct audio_ops_s g_audioops = { + NULL, /* setup */ cs43l22_getcaps, /* getcaps */ cs43l22_configure, /* configure */ cs43l22_shutdown, /* shutdown */ @@ -858,7 +859,7 @@ cs43l22_configure(FAR struct audio_lowerhalf_s *dev, * ****************************************************************************/ -static int cs43l22_shutdown(FAR struct audio_lowerhalf_s *dev) +static int cs43l22_shutdown(FAR struct audio_lowerhalf_s *dev, int cnt) { FAR struct cs43l22_dev_s *priv = (FAR struct cs43l22_dev_s *)dev; diff --git a/drivers/audio/es8311.c b/drivers/audio/es8311.c index 296c75cb58e0c..9eb90049d7a11 100644 --- a/drivers/audio/es8311.c +++ b/drivers/audio/es8311.c @@ -91,7 +91,7 @@ static int es8311_configure(FAR struct audio_lowerhalf_s *dev, static int es8311_configure(FAR struct audio_lowerhalf_s *dev, FAR const struct audio_caps_s *caps); #endif /* !CONFIG_AUDIO_MULTI_SESSION */ -static int es8311_shutdown(FAR struct audio_lowerhalf_s *dev); +static int es8311_shutdown(FAR struct audio_lowerhalf_s *dev, int cnt); static void es8311_processdone(FAR struct i2s_dev_s *i2s, FAR struct ap_buffer_s *apb, FAR void *arg, @@ -154,6 +154,7 @@ static int es8311_get_mclk_src(void); static const struct audio_ops_s g_audioops = { + NULL, /* setup */ es8311_getcaps, /* getcaps */ es8311_configure, /* configure */ es8311_shutdown, /* shutdown */ @@ -1107,7 +1108,7 @@ static int es8311_configure(FAR struct audio_lowerhalf_s *dev, * ****************************************************************************/ -static int es8311_shutdown(FAR struct audio_lowerhalf_s *dev) +static int es8311_shutdown(FAR struct audio_lowerhalf_s *dev, int cnt) { FAR struct es8311_dev_s *priv = (FAR struct es8311_dev_s *)dev; diff --git a/drivers/audio/es8388.c b/drivers/audio/es8388.c index 4708fb0d9ef52..57aa0bdf5e733 100644 --- a/drivers/audio/es8388.c +++ b/drivers/audio/es8388.c @@ -91,7 +91,7 @@ static int es8388_configure(FAR struct audio_lowerhalf_s *dev, static int es8388_configure(FAR struct audio_lowerhalf_s *dev, FAR const struct audio_caps_s *caps); #endif -static int es8388_shutdown(FAR struct audio_lowerhalf_s *dev); +static int es8388_shutdown(FAR struct audio_lowerhalf_s *dev, int cnt); static void es8388_processdone(FAR struct i2s_dev_s *i2s, FAR struct ap_buffer_s *apb, FAR void *arg, @@ -153,6 +153,7 @@ static void es8388_reset(FAR struct es8388_dev_s *priv); static const struct audio_ops_s g_audioops = { + NULL, /* setup */ es8388_getcaps, /* getcaps */ es8388_configure, /* configure */ es8388_shutdown, /* shutdown */ @@ -1123,7 +1124,7 @@ static int es8388_configure(FAR struct audio_lowerhalf_s *dev, * ****************************************************************************/ -static int es8388_shutdown(FAR struct audio_lowerhalf_s *dev) +static int es8388_shutdown(FAR struct audio_lowerhalf_s *dev, int cnt) { FAR struct es8388_dev_s *priv = (FAR struct es8388_dev_s *)dev; diff --git a/drivers/audio/vs1053.c b/drivers/audio/vs1053.c index 1b8d0aa1b062c..8901729d1c865 100644 --- a/drivers/audio/vs1053.c +++ b/drivers/audio/vs1053.c @@ -181,6 +181,7 @@ static int vs1053_ioctl(FAR struct audio_lowerhalf_s *lower, int cmd, static const struct audio_ops_s g_audioops = { + NULL, /* setup */ vs1053_getcaps, /* getcaps */ vs1053_configure, /* configure */ vs1053_shutdown, /* shutdown */ @@ -932,7 +933,7 @@ static int vs1053_hardreset(FAR struct vs1053_struct_s *dev) * ****************************************************************************/ -static int vs1053_shutdown(FAR struct audio_lowerhalf_s *lower) +static int vs1053_shutdown(FAR struct audio_lowerhalf_s *lower, int cnt) { FAR struct vs1053_struct_s *dev = (struct vs1053_struct_s *) lower; FAR struct spi_dev_s *spi = dev->spi; diff --git a/drivers/audio/wm8776.c b/drivers/audio/wm8776.c index b2088a2180fb1..79632c413dcd9 100644 --- a/drivers/audio/wm8776.c +++ b/drivers/audio/wm8776.c @@ -67,7 +67,7 @@ static int wm8776_configure(FAR struct audio_lowerhalf_s *dev, static int wm8776_configure(FAR struct audio_lowerhalf_s *dev, FAR const struct audio_caps_s *caps); #endif -static int wm8776_shutdown(FAR struct audio_lowerhalf_s *dev); +static int wm8776_shutdown(FAR struct audio_lowerhalf_s *dev, int cnt); static void wm8776_senddone(FAR struct i2s_dev_s *i2s, FAR struct ap_buffer_s *apb, FAR void *arg, int result); static void wm8776_returnbuffers(FAR struct wm8776_dev_s *priv); @@ -133,6 +133,7 @@ static void wm8776_hw_reset(FAR struct wm8776_dev_s *priv); static const struct audio_ops_s g_audioops = { + NULL, /* setup */ wm8776_getcaps, /* getcaps */ wm8776_configure, /* configure */ wm8776_shutdown, /* shutdown */ @@ -450,7 +451,7 @@ static int wm8776_configure(FAR struct audio_lowerhalf_s *dev, * ****************************************************************************/ -static int wm8776_shutdown(FAR struct audio_lowerhalf_s *dev) +static int wm8776_shutdown(FAR struct audio_lowerhalf_s *dev, int cnt) { FAR struct wm8776_dev_s *priv = (FAR struct wm8776_dev_s *)dev; diff --git a/drivers/audio/wm8904.c b/drivers/audio/wm8904.c index 1f25a7aae0b71..f45ab04f7eb8c 100644 --- a/drivers/audio/wm8904.c +++ b/drivers/audio/wm8904.c @@ -103,7 +103,7 @@ static int wm8904_configure(FAR struct audio_lowerhalf_s *dev, static int wm8904_configure(FAR struct audio_lowerhalf_s *dev, FAR const struct audio_caps_s *caps); #endif -static int wm8904_shutdown(FAR struct audio_lowerhalf_s *dev); +static int wm8904_shutdown(FAR struct audio_lowerhalf_s *dev, int cnt); static void wm8904_senddone(FAR struct i2s_dev_s *i2s, FAR struct ap_buffer_s *apb, FAR void *arg, int result); static void wm8904_returnbuffers(FAR struct wm8904_dev_s *priv); @@ -182,6 +182,7 @@ static void wm8904_hw_reset(FAR struct wm8904_dev_s *priv); static const struct audio_ops_s g_audioops = { + NULL, /* setup */ wm8904_getcaps, /* getcaps */ wm8904_configure, /* configure */ wm8904_shutdown, /* shutdown */ @@ -1298,7 +1299,7 @@ static int wm8904_configure(FAR struct audio_lowerhalf_s *dev, * ****************************************************************************/ -static int wm8904_shutdown(FAR struct audio_lowerhalf_s *dev) +static int wm8904_shutdown(FAR struct audio_lowerhalf_s *dev, int cnt) { FAR struct wm8904_dev_s *priv = (FAR struct wm8904_dev_s *)dev; diff --git a/drivers/audio/wm8994.c b/drivers/audio/wm8994.c index 418fc1011fe9a..07ba935893897 100644 --- a/drivers/audio/wm8994.c +++ b/drivers/audio/wm8994.c @@ -113,7 +113,7 @@ static int wm8994_configure(FAR struct audio_lowerhalf_s *dev, static int wm8994_configure(FAR struct audio_lowerhalf_s *dev, FAR const struct audio_caps_s *caps); #endif -static int wm8994_shutdown(FAR struct audio_lowerhalf_s *dev); +static int wm8994_shutdown(FAR struct audio_lowerhalf_s *dev, int cnt); static void wm8994_senddone(FAR struct i2s_dev_s *i2s, FAR struct ap_buffer_s *apb, FAR void *arg, int result); static void wm8994_returnbuffers(FAR struct wm8994_dev_s *priv); @@ -190,6 +190,7 @@ static void wm8994_hw_reset(FAR struct wm8994_dev_s *priv); static const struct audio_ops_s g_audioops = { + NULL, /* setup */ wm8994_getcaps, /* getcaps */ wm8994_configure, /* configure */ wm8994_shutdown, /* shutdown */ @@ -993,7 +994,7 @@ static int wm8994_configure(FAR struct audio_lowerhalf_s *dev, * */ -static int wm8994_shutdown(FAR struct audio_lowerhalf_s *dev) +static int wm8994_shutdown(FAR struct audio_lowerhalf_s *dev, int cnt) { FAR struct wm8994_dev_s *priv = (FAR struct wm8994_dev_s *)dev; diff --git a/drivers/virtio/virtio-snd.c b/drivers/virtio/virtio-snd.c index 210c9a49794b2..691919aa1a2bc 100644 --- a/drivers/virtio/virtio-snd.c +++ b/drivers/virtio/virtio-snd.c @@ -168,7 +168,7 @@ static int virtio_snd_enqueuebuffer(FAR struct audio_lowerhalf_s *dev, static int virtio_snd_ioctl(FAR struct audio_lowerhalf_s *dev, int cmd, unsigned long arg); -static int virtio_snd_shutdown(FAR struct audio_lowerhalf_s *dev); +static int virtio_snd_shutdown(FAR struct audio_lowerhalf_s *dev, int cnt); static int virtio_snd_probe(FAR struct virtio_device *vdev); static void virtio_snd_remove(FAR struct virtio_device *vdev); @@ -243,6 +243,7 @@ static struct virtio_driver g_virtio_snd_driver = static const struct audio_ops_s g_virtio_snd_ops = { + NULL, /* setup */ virtio_snd_getcaps, /* getcaps */ virtio_snd_configure, /* configure */ virtio_snd_shutdown, /* shutdown */ @@ -1004,7 +1005,7 @@ static int virtio_snd_ioctl(FAR struct audio_lowerhalf_s *dev, * ****************************************************************************/ -static int virtio_snd_shutdown(FAR struct audio_lowerhalf_s *dev) +static int virtio_snd_shutdown(FAR struct audio_lowerhalf_s *dev, int cnt) { vrtinfo("Return OK\n"); return OK; diff --git a/include/nuttx/audio/audio.h b/include/nuttx/audio/audio.h index 1053d8b9ffa00..d26e780e5a9d4 100644 --- a/include/nuttx/audio/audio.h +++ b/include/nuttx/audio/audio.h @@ -114,6 +114,7 @@ #define AUDIOIOC_SETPARAMTER _AUDIOIOC(18) #define AUDIOIOC_GETLATENCY _AUDIOIOC(19) #define AUDIOIOC_FLUSH _AUDIOIOC(20) +#define AUDIOIOC_VENDORSPECIFIC _AUDIOIOC(255) /* Audio Device Types *******************************************************/ @@ -353,6 +354,7 @@ #define AUDIO_MSG_COMMAND 10 #define AUDIO_MSG_SLIENCE 11 #define AUDIO_MSG_UNDERRUN 12 +#define AUDIO_MSG_IOERROR 13 #define AUDIO_MSG_USER 64 /* Audio Pipeline Buffer flags */ @@ -534,6 +536,10 @@ typedef CODE void (*audio_callback_t)(FAR void *priv, uint16_t reason, struct audio_lowerhalf_s; struct audio_ops_s { + /* This method is called when the related device file is opened. */ + + CODE int (*setup)(FAR struct audio_lowerhalf_s *dev, int opencnt); + /* This method is called to retrieve the lower-half device capabilities. * It will be called with device type AUDIO_TYPE_QUERY to request the * overall capabilities, such as to determine the types of devices @@ -571,7 +577,7 @@ struct audio_ops_s * processed / dequeued should be dequeued by this function. */ - CODE int (*shutdown)(FAR struct audio_lowerhalf_s *dev); + CODE int (*shutdown)(FAR struct audio_lowerhalf_s *dev, int opencnt); /* Start audio streaming in the configured mode. For input and synthesis * devices, this means it should begin sending streaming audio data.