The branch main has been updated by christos:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=be04a9d9387f6b5d4e83fc4976d8d83bb03fe5af

commit be04a9d9387f6b5d4e83fc4976d8d83bb03fe5af
Author:     Christos Margiolis <[email protected]>
AuthorDate: 2024-07-06 18:22:45 +0000
Commit:     Christos Margiolis <[email protected]>
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);

Reply via email to