Change snd_usb_capture_ops trigger to hold audio token prior starting endpoints for SNDRV_PCM_TRIGGER_START request and release after stopping endpoints for SNDRV_PCM_TRIGGER_STOP request. Audio token is released from snd_usb_capture_ops close interface to cover the case where an application exits without stopping capture. Audio token get request will succeed if it is free or when a media application with the same task pid or task gid makes the request. This covers the cases when a media application first hold the tuner nd audio token and then requests SNDRV_PCM_TRIGGER_START either from the same thread or a another thread in the same process group.
Signed-off-by: Shuah Khan shuahkh@osg.samsung.com --- sound/usb/pcm.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index c62a165..d23abeb 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -21,6 +21,7 @@ #include <linux/usb.h> #include <linux/usb/audio.h> #include <linux/usb/audio-v2.h> +#include <linux/media_tknres.h>
#include <sound/core.h> #include <sound/pcm.h> @@ -1220,6 +1221,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
subs->pcm_substream = NULL; snd_usb_autosuspend(subs->stream->chip); + media_put_audio_tkn(&subs->dev->dev);
return 0; } @@ -1573,6 +1575,12 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream
switch (cmd) { case SNDRV_PCM_TRIGGER_START: + err = media_get_audio_tkn(&subs->dev->dev); + if (err == -EBUSY) { + dev_info(&subs->dev->dev, "%s device is busy\n", + __func__); + return err; + } err = start_endpoints(subs, false); if (err < 0) return err; @@ -1583,6 +1591,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream case SNDRV_PCM_TRIGGER_STOP: stop_endpoints(subs, false); subs->running = 0; + media_put_audio_tkn(&subs->dev->dev); return 0; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: subs->data_endpoint->retire_data_urb = NULL;