mirror of
https://git.FreeBSD.org/src.git
synced 2024-11-28 08:02:54 +00:00
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
This commit is contained in:
parent
46e92a41cb
commit
be04a9d938
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user