summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorcg <cg@FreeBSD.org>2000-04-05 01:13:42 +0000
committercg <cg@FreeBSD.org>2000-04-05 01:13:42 +0000
commita00d5b661c9af018104cb3aab9f227dce8bbccee (patch)
treef85efc687b801346e4cd37b5434c393570617e04 /sys
parent02dcd03a452a2d51ebf2a0ac2fa380ecb81b58ee (diff)
downloadFreeBSD-src-a00d5b661c9af018104cb3aab9f227dce8bbccee.zip
FreeBSD-src-a00d5b661c9af018104cb3aab9f227dce8bbccee.tar.gz
allow /dev/dsp to be opened seperately for reading and writing.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/sound/pcm/datatypes.h1
-rw-r--r--sys/dev/sound/pcm/dsp.c32
-rw-r--r--sys/dev/sound/pcm/sound.c5
3 files changed, 27 insertions, 11 deletions
diff --git a/sys/dev/sound/pcm/datatypes.h b/sys/dev/sound/pcm/datatypes.h
index 7ea9390..6aba9c2 100644
--- a/sys/dev/sound/pcm/datatypes.h
+++ b/sys/dev/sound/pcm/datatypes.h
@@ -137,6 +137,7 @@ typedef void (pcm_swap_t)(void *data, int dir);
/* descriptor of audio device */
struct _snddev_info {
pcm_channel *play, *rec, **aplay, **arec, fakechan;
+ int *ref;
unsigned playcount, reccount, chancount;
snd_mixer mixer;
u_long magic;
diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c
index cc343d6..5ad60bd 100644
--- a/sys/dev/sound/pcm/dsp.c
+++ b/sys/dev/sound/pcm/dsp.c
@@ -57,6 +57,7 @@ getchns(snddev_info *d, int chan, pcm_channel **rdch, pcm_channel **wrch)
if ((d->flags & SD_F_SIMPLEX) && (d->flags & SD_F_PRIO_SET)) {
*rdch = (d->flags & SD_F_PRIO_RD)? d->arec[chan] : &d->fakechan;
*wrch = (d->flags & SD_F_PRIO_WR)? d->aplay[chan] : &d->fakechan;
+ d->fakechan.flags |= CHN_F_BUSY;
} else {
*rdch = d->arec[chan];
*wrch = d->aplay[chan];
@@ -76,24 +77,31 @@ setchns(snddev_info *d, int chan)
int
dsp_open(snddev_info *d, int chan, int oflags, int devtype)
{
- pcm_channel *rdch = NULL, *wrch = NULL;
+ pcm_channel *rdch, *wrch;
u_int32_t fmt;
if (chan >= d->chancount) return ENODEV;
- if (d->aplay[chan] || d->arec[chan]) return EBUSY;
+ if ((d->flags & SD_F_SIMPLEX) && (d->ref[chan] > 0)) return EBUSY;
+ rdch = d->arec[chan];
+ wrch = d->aplay[chan];
if (oflags & FREAD) {
- rdch = allocchn(d, PCMDIR_REC);
- if (!rdch) return EBUSY;
+ if (rdch == NULL) {
+ rdch = allocchn(d, PCMDIR_REC);
+ if (!rdch) return EBUSY;
+ } else return EBUSY;
}
if (oflags & FWRITE) {
- wrch = allocchn(d, PCMDIR_PLAY);
- if (!wrch) {
- if (rdch) rdch->flags &= ~CHN_F_BUSY;
- return EBUSY;
- }
+ if (wrch == NULL) {
+ wrch = allocchn(d, PCMDIR_PLAY);
+ if (!wrch && (oflags & FREAD)) {
+ rdch->flags &= ~CHN_F_BUSY;
+ return EBUSY;
+ }
+ } else return EBUSY;
}
d->aplay[chan] = wrch;
d->arec[chan] = rdch;
+ d->ref[chan]++;
switch (devtype) {
case SND_DEV_DSP16:
fmt = AFMT_S16_LE;
@@ -115,7 +123,7 @@ dsp_open(snddev_info *d, int chan, int oflags, int devtype)
return ENXIO;
}
- if (rdch) {
+ if (rdch && (oflags & FREAD)) {
chn_reset(rdch);
if (oflags & O_NONBLOCK) rdch->flags |= CHN_F_NBIO;
if (fmt) {
@@ -125,7 +133,7 @@ dsp_open(snddev_info *d, int chan, int oflags, int devtype)
rdch->blocksize = 2048;
}
}
- if (wrch) {
+ if (wrch && (oflags & FWRITE)) {
chn_reset(wrch);
if (oflags & O_NONBLOCK) wrch->flags |= CHN_F_NBIO;
if (fmt) {
@@ -143,6 +151,8 @@ dsp_close(snddev_info *d, int chan, int devtype)
{
pcm_channel *rdch, *wrch;
+ d->ref[chan]--;
+ if (d->ref[chan]) return 0;
d->flags &= ~SD_F_TRANSIENT;
rdch = d->arec[chan];
wrch = d->aplay[chan];
diff --git a/sys/dev/sound/pcm/sound.c b/sys/dev/sound/pcm/sound.c
index a9c0c10..f0037fe 100644
--- a/sys/dev/sound/pcm/sound.c
+++ b/sys/dev/sound/pcm/sound.c
@@ -183,6 +183,11 @@ pcm_register(device_t dev, void *devinfo, int numplay, int numrec)
d->arec = (pcm_channel **)malloc(sz, M_DEVBUF, M_NOWAIT);
if (!d->arec) goto no;
bzero(d->arec, sz);
+
+ sz = (numplay + numrec) * sizeof(int);
+ d->ref = (int *)malloc(sz, M_DEVBUF, M_NOWAIT);
+ if (!d->ref) goto no;
+ bzero(d->ref, sz);
}
if (numplay > 0) {
OpenPOWER on IntegriCloud