Module Name: src Committed By: nat Date: Sun Oct 1 21:49:20 UTC 2017
Modified Files: src/sys/dev: audio.c Log Message: Ensure proper use of sc_opens (play back) and sc_recopens (recording). Fix logic for /dev/sound so audiosetinfo is only called once. These changes are to ensure that init_output/input is only called once for the respective function play back or recording. For multiple recording or plack back streams init_input/output is only called once fot the first play/rec stream. This addresses PR kern/52580, PR kern/52581 and PR kern/52582 analyzed and reported by isaki@. To generate a diff of this commit: cvs rdiff -u -r1.409 -r1.410 src/sys/dev/audio.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/audio.c diff -u src/sys/dev/audio.c:1.409 src/sys/dev/audio.c:1.410 --- src/sys/dev/audio.c:1.409 Sat Sep 30 05:37:55 2017 +++ src/sys/dev/audio.c Sun Oct 1 21:49:20 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: audio.c,v 1.409 2017/09/30 05:37:55 isaki Exp $ */ +/* $NetBSD: audio.c,v 1.410 2017/10/01 21:49:20 nat Exp $ */ /*- * Copyright (c) 2016 Nathanial Sloss <nathanialsl...@yahoo.com.au> @@ -148,7 +148,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.409 2017/09/30 05:37:55 isaki Exp $"); +__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.410 2017/10/01 21:49:20 nat Exp $"); #ifdef _KERNEL_OPT #include "audio.h" @@ -2027,7 +2027,7 @@ audio_initbufs(struct audio_softc *sc, s ((vc->sc_open & AUOPEN_READ) || vc == sc->sc_hwvc)) { audio_init_ringbuffer(sc, &vc->sc_mrr, AUMODE_RECORD); - if (sc->sc_opens == 0 && (vc->sc_mode & AUMODE_RECORD)) { + if (sc->sc_recopens == 0 && (vc->sc_open & AUOPEN_READ)) { if (hw->init_input) { error = hw->init_input(sc->hw_hdl, vc->sc_mrr.s.start, @@ -2043,7 +2043,7 @@ audio_initbufs(struct audio_softc *sc, s audio_init_ringbuffer(sc, &vc->sc_mpr, AUMODE_PLAY); vc->sc_sil_count = 0; - if (sc->sc_opens == 0 && (vc->sc_mode & AUMODE_PLAY)) { + if (sc->sc_opens == 0 && (vc->sc_open & AUOPEN_WRITE)) { if (hw->init_output) { error = hw->init_output(sc->hw_hdl, vc->sc_mpr.s.start, @@ -2157,7 +2157,7 @@ audio_open(dev_t dev, struct audio_softc if (error) goto bad; - if (sc->sc_opens == 0) { + if (sc->sc_opens + sc->sc_recopens == 0) { sc->sc_credentials = kauth_cred_get(); kauth_cred_hold(sc->sc_credentials); if (hw->open != NULL) { @@ -2216,13 +2216,13 @@ audio_open(dev_t dev, struct audio_softc * The /dev/audio is always (re)set to 8-bit MU-Law mono * For the other devices, you get what they were last set to. */ - error = audio_set_defaults(sc, mode, vc); - if (!error && ISDEVSOUND(dev) && sc->sc_aivalid == true) { + if (ISDEVSOUND(dev) && sc->sc_aivalid == true) { sc->sc_ai.mode = mode; sc->sc_ai.play.port = ~0; sc->sc_ai.record.port = ~0; error = audiosetinfo(sc, &sc->sc_ai, true, vc); - } + } else + error = audio_set_defaults(sc, mode, vc); if (error) goto bad; @@ -2250,7 +2250,8 @@ audio_open(dev_t dev, struct audio_softc grow_mixer_states(sc, 2); if (flags & FREAD) sc->sc_recopens++; - sc->sc_opens++; + if (flags & FWRITE) + sc->sc_opens++; chan->dev = dev; chan->chan = n; chan->deschan = n; @@ -2265,7 +2266,7 @@ audio_open(dev_t dev, struct audio_softc bad: audio_destroy_pfilters(vc); audio_destroy_rfilters(vc); - if (hw->close != NULL && sc->sc_opens == 0) + if (hw->close != NULL && sc->sc_opens == 0 && sc->sc_recopens == 0) hw->close(sc->hw_hdl); mutex_exit(sc->sc_lock); audio_free_ring(sc, &vc->sc_mpr); @@ -2285,7 +2286,7 @@ audio_init_record(struct audio_softc *sc KASSERT(mutex_owned(sc->sc_lock)); - if (sc->sc_opens != 0) + if (sc->sc_recopens != 0) return; mutex_enter(sc->sc_intr_lock); @@ -2416,7 +2417,7 @@ audio_close(struct audio_softc *sc, int KASSERT(mutex_owned(sc->sc_lock)); - if (sc->sc_opens == 0) + if (sc->sc_opens == 0 && sc->sc_recopens == 0) return ENXIO; vc = chan->vc; @@ -2450,7 +2451,7 @@ audio_close(struct audio_softc *sc, int audio_drain(sc, chan->vc); vc->sc_pbus = false; } - if (sc->sc_opens == 1) { + if ((flags & FWRITE) && (sc->sc_opens == 1)) { if (vc->sc_mpr.mmapped == false) audio_drain(sc, sc->sc_hwvc); if (hw->drain) @@ -2461,11 +2462,11 @@ audio_close(struct audio_softc *sc, int if ((flags & FREAD) && (sc->sc_recopens == 1)) sc->sc_rec_started = false; - if (sc->sc_opens == 1 && hw->close != NULL) + if (sc->sc_opens + sc->sc_recopens == 1 && hw->close != NULL) hw->close(sc->hw_hdl); mutex_exit(sc->sc_intr_lock); - if (sc->sc_opens == 1) { + if (sc->sc_opens + sc->sc_recopens == 1) { sc->sc_async_audio = 0; kauth_cred_free(sc->sc_credentials); } @@ -2479,7 +2480,8 @@ audio_close(struct audio_softc *sc, int if (flags & FREAD) sc->sc_recopens--; - sc->sc_opens--; + if (flags & FWRITE) + sc->sc_opens--; shrink_mixer_states(sc, 2); SIMPLEQ_REMOVE(&sc->sc_audiochan, chan, audio_chan, entries); mutex_exit(sc->sc_lock); @@ -4710,7 +4712,7 @@ audiosetinfo(struct audio_softc *sc, str } } - if (hw->commit_settings && sc->sc_opens == 0) { + if (hw->commit_settings && sc->sc_opens + sc->sc_recopens == 0) { error = hw->commit_settings(sc->hw_hdl); if (error) goto cleanup; @@ -5830,7 +5832,7 @@ audio_sysctl_frequency(SYSCTLFN_ARGS) mutex_enter(sc->sc_lock); /* This may not change when a virtual channel is open */ - if (sc->sc_opens) { + if (sc->sc_opens || sc->sc_recopens) { mutex_exit(sc->sc_lock); return EBUSY; } @@ -5871,7 +5873,7 @@ audio_sysctl_precision(SYSCTLFN_ARGS) mutex_enter(sc->sc_lock); /* This may not change when a virtual channel is open */ - if (sc->sc_opens) { + if (sc->sc_opens || sc->sc_recopens) { mutex_exit(sc->sc_lock); return EBUSY; } @@ -5923,7 +5925,7 @@ audio_sysctl_channels(SYSCTLFN_ARGS) mutex_enter(sc->sc_lock); /* This may not change when a virtual channel is open */ - if (sc->sc_opens) { + if (sc->sc_opens || sc->sc_recopens) { mutex_exit(sc->sc_lock); return EBUSY; }