git: be04a9d9387f - main - sound: Improve simplex handling in dsp_open()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 06 Jul 2024 18:24:12 UTC
The branch main has been updated by christos:
URL: https://cgit.FreeBSD.org/src/commit/?id=be04a9d9387f6b5d4e83fc4976d8d83bb03fe5af
commit be04a9d9387f6b5d4e83fc4976d8d83bb03fe5af
Author: Christos Margiolis <christos@FreeBSD.org>
AuthorDate: 2024-07-06 18:22:45 +0000
Commit: Christos Margiolis <christos@FreeBSD.org>
CommitDate: 2024-07-06 18:22:45 +0000
sound: Improve simplex handling in dsp_open()
If we are in simplex mode, make sure we do not open in both directions
(read/write) and also that we do not open in a direction opposite of
what is already opened. For example, if the device is already doing
playback, we cannot open the device for recording at the same time, and
vice-versa.
While here, remove dsp_cdevpriv->simplex as it's no longer needed.
Sponsored by: The FreeBSD Foundation
MFC after: 2 days
Reviewed by: dev_submerge.ch
Differential Revision: https://reviews.freebsd.org/D45835
---
sys/dev/sound/pcm/dsp.c | 36 ++++++++++++++++++++++++++++++++----
1 file changed, 32 insertions(+), 4 deletions(-)
diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c
index f2cead08783c..26a2919ed1da 100644
--- a/sys/dev/sound/pcm/dsp.c
+++ b/sys/dev/sound/pcm/dsp.c
@@ -52,7 +52,6 @@ struct dsp_cdevpriv {
struct pcm_channel *rdch;
struct pcm_channel *wrch;
struct pcm_channel *volch;
- int simplex;
};
static int dsp_mmap_allow_prot_exec = 0;
@@ -301,10 +300,10 @@ static int
dsp_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
{
struct dsp_cdevpriv *priv;
- struct pcm_channel *rdch, *wrch;
+ struct pcm_channel *rdch, *wrch, *ch;
struct snddev_info *d;
uint32_t fmt, spd;
- int error, rderror, wrerror;
+ int error, rderror, wrerror, dir;
/* Kind of impossible.. */
if (i_dev == NULL || td == NULL)
@@ -319,7 +318,6 @@ dsp_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
priv->rdch = NULL;
priv->wrch = NULL;
priv->volch = NULL;
- priv->simplex = (pcm_getflags(d->dev) & SD_F_SIMPLEX) ? 1 : 0;
error = devfs_set_cdevpriv(priv, dsp_close);
if (error != 0)
@@ -333,6 +331,36 @@ dsp_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
error = 0;
DSP_FIXUP_ERROR();
+ if (pcm_getflags(d->dev) & SD_F_SIMPLEX) {
+ if (DSP_F_DUPLEX(flags)) {
+ /*
+ * If no channels are opened yet, and we request
+ * DUPLEX, limit to playback only, otherwise open one
+ * channel in a direction that already exists.
+ */
+ if (CHN_EMPTY(d, channels.pcm.opened)) {
+ if (d->playcount > 0)
+ flags &= ~FREAD;
+ else if (d->reccount > 0)
+ flags &= ~FWRITE;
+ } else {
+ ch = CHN_FIRST(d, channels.pcm.opened);
+ if (ch->direction == PCMDIR_PLAY)
+ flags &= ~FREAD;
+ else if (ch->direction == PCMDIR_REC)
+ flags &= ~FWRITE;
+ }
+ } else if (!CHN_EMPTY(d, channels.pcm.opened)) {
+ /*
+ * If we requested SIMPLEX, make sure we do not open a
+ * channel in the opposite direction.
+ */
+ ch = CHN_FIRST(d, channels.pcm.opened);
+ dir = DSP_F_READ(flags) ? PCMDIR_REC : PCMDIR_PLAY;
+ if (ch->direction != dir)
+ error = ENOTSUP;
+ }
+ }
if (error != 0) {
PCM_UNLOCK(d);
PCM_GIANT_EXIT(d);