NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: kern/46545: pad(4):Support for fullduplex playback/recording polling and nonblocking mode
The following reply was made to PR kern/46545; it has been noted by GNATS.
From: Nat Sloss <nathanialsloss%yahoo.com.au@localhost>
To: gnats-bugs%netbsd.org@localhost
Cc:
Subject: Re: kern/46545: pad(4):Support for fullduplex playback/recording
polling and nonblocking mode
Date: Tue, 5 Jun 2012 23:05:48 +1000
Hi
Here are my patches:
Index: sys/dev/pad/pad.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pad/pad.c,v
retrieving revision 1.19
diff -u -r1.19 pad.c
--- sys/dev/pad/pad.c 24 Nov 2011 01:54:08 -0000 1.19
+++ sys/dev/pad/pad.c 5 Jun 2012 12:27:28 -0000
@@ -33,10 +33,14 @@
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/buf.h>
+#include <sys/errno.h>
+#include <sys/fcntl.h>
+#include <sys/ioctl.h>
#include <sys/kmem.h>
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/proc.h>
+#include <sys/poll.h>
#include <sys/condvar.h>
#include <sys/select.h>
#include <sys/audioio.h>
@@ -54,7 +58,6 @@
#define PADUNIT(x) minor(x)
extern struct cfdriver pad_cd;
-
typedef struct pad_block {
uint8_t *pb_ptr;
int pb_len;
@@ -63,8 +66,10 @@
enum {
PAD_OUTPUT_CLASS,
PAD_INPUT_CLASS,
+ PAD_RECORD_CLASS,
PAD_OUTPUT_MASTER_VOLUME,
PAD_INPUT_DAC_VOLUME,
+ PAD_INPUT_MIC_VOLUME,
PAD_ENUM_LAST,
};
@@ -84,14 +89,19 @@
static int pad_halt_output(void *);
static int pad_halt_input(void *);
static int pad_getdev(void *, struct audio_device *);
+static int pad_setfd(void *, int);
static int pad_set_port(void *, mixer_ctrl_t *);
static int pad_get_port(void *, mixer_ctrl_t *);
static int pad_query_devinfo(void *, mixer_devinfo_t *);
static int pad_get_props(void *);
static int pad_round_blocksize(void *, int, int, const audio_params_t *);
static void pad_get_locks(void *, kmutex_t **, kmutex_t **);
+static int pad_audio_open(void *,int);
+static void pad_audio_close(void *);
static const struct audio_hw_if pad_hw_if = {
+ .open = pad_audio_open,
+ .close = pad_audio_close,
.query_encoding = pad_query_encoding,
.set_params = pad_set_params,
.start_output = pad_start_output,
@@ -99,6 +109,7 @@
.halt_output = pad_halt_output,
.halt_input = pad_halt_input,
.getdev = pad_getdev,
+ .setfd = pad_setfd,
.set_port = pad_set_port,
.get_port = pad_get_port,
.query_devinfo = pad_query_devinfo,
@@ -115,22 +126,28 @@
extern void padattach(int);
-static int pad_add_block(pad_softc_t *, uint8_t *, int);
-static int pad_get_block(pad_softc_t *, pad_block_t *, int);
+static int pad_add_block_out(pad_softc_t *, uint8_t *, int);
+static int pad_get_block_out(pad_softc_t *, pad_block_t *, int);
+
+static int pad_add_block_in(pad_softc_t *, uint8_t *, int);
+static int pad_get_block_in(pad_softc_t *, pad_block_t *, int);
dev_type_open(pad_open);
dev_type_close(pad_close);
dev_type_read(pad_read);
+dev_type_read(pad_write);
+dev_type_poll(pad_poll);
+dev_type_ioctl(pad_ioctl);
const struct cdevsw pad_cdevsw = {
.d_open = pad_open,
.d_close = pad_close,
.d_read = pad_read,
- .d_write = nowrite,
- .d_ioctl = noioctl,
+ .d_write = pad_write,
+ .d_ioctl = pad_ioctl,
.d_stop = nostop,
.d_tty = notty,
- .d_poll = nopoll,
+ .d_poll = pad_poll,
.d_mmap = nommap,
.d_kqfilter = nokqfilter,
.d_flag = D_OTHER | D_MPSAFE,
@@ -174,47 +191,77 @@
}
static int
-pad_add_block(pad_softc_t *sc, uint8_t *blk, int blksize)
+pad_add_block_out(pad_softc_t *sc, uint8_t *blk, int blksize)
{
int l;
- if (sc->sc_open == 0)
+ if ((sc->sc_open & AUOPEN_READ) == 0)
return EIO;
KASSERT(mutex_owned(&sc->sc_lock));
- if (sc->sc_buflen + blksize > PAD_BUFSIZE)
- return ENOBUFS;
+ if (sc->sc_out_buflen + blksize > PAD_BUFSIZE)
+ return 0;
- if (sc->sc_wpos + blksize <= PAD_BUFSIZE)
- memcpy(sc->sc_audiobuf + sc->sc_wpos, blk, blksize);
+ if (sc->sc_opos + blksize <= PAD_BUFSIZE)
+ memcpy(sc->sc_out_audiobuf + sc->sc_opos, blk, blksize);
else {
- l = PAD_BUFSIZE - sc->sc_wpos;
- memcpy(sc->sc_audiobuf + sc->sc_wpos, blk, l);
- memcpy(sc->sc_audiobuf, blk + l, blksize - l);
+ l = PAD_BUFSIZE - sc->sc_opos;
+ memcpy(sc->sc_out_audiobuf + sc->sc_opos, blk, l);
+ memcpy(sc->sc_out_audiobuf, blk + l, blksize - l);
+ }
+
+ sc->sc_opos += blksize;
+ if (sc->sc_opos > PAD_BUFSIZE)
+ sc->sc_opos -= PAD_BUFSIZE;
+
+ sc->sc_out_buflen += blksize;
+
+ return 0;
+}
+
+static int
+pad_add_block_in(pad_softc_t *sc, uint8_t *blk, int blksize)
+{
+ int l;
+
+ if ((sc->sc_open & AUOPEN_WRITE) == 0)
+ return EIO;
+
+ KASSERT(mutex_owned(&sc->sc_lock));
+
+ if (sc->sc_in_buflen < PAD_BLKSIZE)
+ return 0;
+
+ if (sc->sc_ipos + blksize <= PAD_BUFSIZE)
+ memcpy(blk, sc->sc_in_audiobuf + sc->sc_ipos, blksize);
+ else {
+ l = PAD_BUFSIZE - sc->sc_ipos;
+ memcpy(blk, sc->sc_in_audiobuf + sc->sc_ipos, l);
+ memcpy(blk + l, sc->sc_in_audiobuf, blksize - l);
}
- sc->sc_wpos += blksize;
- if (sc->sc_wpos > PAD_BUFSIZE)
- sc->sc_wpos -= PAD_BUFSIZE;
+ sc->sc_ipos += blksize;
+ if (sc->sc_ipos > PAD_BUFSIZE)
+ sc->sc_ipos -= PAD_BUFSIZE;
- sc->sc_buflen += blksize;
+ sc->sc_in_buflen -= blksize;
return 0;
}
static int
-pad_get_block(pad_softc_t *sc, pad_block_t *pb, int blksize)
+pad_get_block_out(pad_softc_t *sc, pad_block_t *pb, int blksize)
{
int l;
KASSERT(mutex_owned(&sc->sc_lock));
KASSERT(pb != NULL);
- if (sc->sc_buflen < blksize)
+ if (sc->sc_out_buflen < blksize)
return ERESTART;
- pb->pb_ptr = (sc->sc_audiobuf + sc->sc_rpos);
+ pb->pb_ptr = (sc->sc_out_audiobuf + sc->sc_rpos);
if (sc->sc_rpos + blksize < PAD_BUFSIZE) {
pb->pb_len = blksize;
sc->sc_rpos += blksize;
@@ -223,7 +270,32 @@
pb->pb_len = l;
sc->sc_rpos = 0;
}
- sc->sc_buflen -= pb->pb_len;
+ sc->sc_out_buflen -= pb->pb_len;
+
+ return 0;
+}
+
+static int
+pad_get_block_in(pad_softc_t *sc, pad_block_t *pb, int blksize)
+{
+ int l;
+
+ KASSERT(mutex_owned(&sc->sc_lock));
+ KASSERT(pb != NULL);
+
+ if (sc->sc_in_buflen + blksize > PAD_BUFSIZE)
+ return ENOBUFS;
+
+ pb->pb_ptr = (sc->sc_in_audiobuf + sc->sc_wpos);
+ if (sc->sc_wpos + blksize < PAD_BUFSIZE) {
+ pb->pb_len = blksize;
+ sc->sc_wpos += blksize;
+ } else {
+ l = PAD_BUFSIZE - sc->sc_wpos;
+ pb->pb_len = l;
+ sc->sc_wpos = 0;
+ }
+ sc->sc_in_buflen += pb->pb_len;
return 0;
}
@@ -252,19 +324,27 @@
sc->sc_dev = self;
sc->sc_open = 0;
+ sc->sc_flags = 0;
+ sc->sc_mode = 0;
if (auconv_create_encodings(pad_formats, PAD_NFORMATS,
&sc->sc_encodings) != 0) {
aprint_error_dev(self, "couldn't create encodings\n");
return;
}
- cv_init(&sc->sc_condvar, device_xname(self));
+ cv_init(&sc->sc_condvar_in, device_xname(self));
+ cv_init(&sc->sc_condvar_out, device_xname(self));
mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_NONE);
sc->sc_swvol = 255;
- sc->sc_buflen = 0;
- sc->sc_rpos = sc->sc_wpos = 0;
+ sc->sc_out_buflen = 0;
+ sc->sc_rpos = sc->sc_opos = 0;
+
+ sc->sc_recvol = 255;
+ sc->sc_in_buflen = 0;
+ sc->sc_wpos = sc->sc_ipos = 0;
+
sc->sc_audiodev = (void *)audio_attach_mi(&pad_hw_if, sc, sc->sc_dev);
if (!pmf_device_register(self, NULL, NULL))
@@ -290,7 +370,8 @@
mutex_destroy(&sc->sc_lock);
mutex_destroy(&sc->sc_intr_lock);
- cv_destroy(&sc->sc_condvar);
+ cv_destroy(&sc->sc_condvar_in);
+ cv_destroy(&sc->sc_condvar_out);
auconv_delete_encodings(sc->sc_encodings);
@@ -306,8 +387,20 @@
if (sc == NULL)
return ENXIO;
- if (atomic_swap_uint(&sc->sc_open, 1) != 0) {
+ if (((flags & FREAD) && (sc->sc_open & AUOPEN_READ)) ||
+ ((flags & FWRITE) && (sc->sc_open & AUOPEN_WRITE)))
return EBUSY;
+
+ if (flags & FREAD) {
+ sc->sc_open |= AUOPEN_READ;
+ sc->sc_out_buflen = 0;
+ sc->sc_rpos = sc->sc_opos = 0;
+ }
+
+ if (flags & FWRITE) {
+ sc->sc_open |= AUOPEN_WRITE;
+ sc->sc_in_buflen = 0;
+ sc->sc_wpos = sc->sc_ipos = 0;
}
return 0;
@@ -323,7 +416,9 @@
return ENXIO;
KASSERT(sc->sc_open > 0);
+
sc->sc_open = 0;
+ sc->sc_flags = 0;
return 0;
}
@@ -335,20 +430,26 @@
pad_block_t pb;
void (*intr)(void *);
void *intrarg;
- int err;
+ int err, timeout;
sc = device_lookup_private(&pad_cd, PADUNIT(dev));
if (sc == NULL)
return ENXIO;
+ if ((sc->sc_open & AUOPEN_READ) == 0)
+ return EIO;
+
err = 0;
+ timeout = mstohz(1000);
+ if (timeout == 0)
+ timeout = 1;
mutex_enter(&sc->sc_lock);
- intr = sc->sc_intr;
- intrarg = sc->sc_intrarg;
+ intr = sc->sc_out_intr;
+ intrarg = sc->sc_out_intrarg;
while (uio->uio_resid > 0 && !err) {
- err = pad_get_block(sc, &pb, min(uio->uio_resid, PAD_BLKSIZE));
+ err = pad_get_block_out(sc, &pb, min(uio->uio_resid,
PAD_BLKSIZE));
if (!err) {
mutex_exit(&sc->sc_lock);
err = uiomove(pb.pb_ptr, pb.pb_len, uio);
@@ -360,27 +461,84 @@
mutex_enter(&sc->sc_intr_lock);
(*intr)(intrarg);
mutex_exit(&sc->sc_intr_lock);
- intr = sc->sc_intr;
- intrarg = sc->sc_intrarg;
+ intr = sc->sc_out_intr;
+ intrarg = sc->sc_out_intrarg;
err = 0;
continue;
}
- err = cv_wait_sig(&sc->sc_condvar, &sc->sc_lock);
+
+ if ((sc->sc_flags & O_NONBLOCK) == 0)
+ err = cv_wait_sig(&sc->sc_condvar_out, &sc->sc_lock);
+ else
+ err = cv_timedwait_sig(&sc->sc_condvar_out,
&sc->sc_lock, timeout);
+
if (err != 0) {
mutex_exit(&sc->sc_lock);
return err;
}
- intr = sc->sc_intr;
- intrarg = sc->sc_intrarg;
- }
+ intr = sc->sc_out_intr;
+ intrarg = sc->sc_out_intrarg;
- if (intr) {
- mutex_enter(&sc->sc_intr_lock);
- (*intr)(intrarg);
- mutex_exit(&sc->sc_intr_lock);
}
+
mutex_exit(&sc->sc_lock);
+ return err;
+}
+
+int
+pad_write(dev_t dev, struct uio *uio, int flags)
+{
+ pad_softc_t *sc;
+ pad_block_t pb;
+ void (*intr)(void *);
+ void *intrarg;
+ int err;
+
+ sc = device_lookup_private(&pad_cd, PADUNIT(dev));
+ if (sc == NULL)
+ return ENXIO;
+
+ if ((sc->sc_open & AUOPEN_WRITE) == 0)
+ return EIO;
+
+ err = 0;
+
+ mutex_enter(&sc->sc_lock);
+ intr = sc->sc_in_intr;
+ intrarg = sc->sc_in_intrarg;
+
+ while (uio->uio_resid > 0 && !err) {
+ err = pad_get_block_in(sc, &pb, min(uio->uio_resid,
PAD_BLKSIZE));
+ if (!err) {
+ mutex_exit(&sc->sc_lock);
+ err = uiomove(pb.pb_ptr, pb.pb_len, uio);
+ if (err != 0)
+ return err;
+ mutex_enter(&sc->sc_lock);
+ continue;
+ }
+
+ if (intr) {
+ mutex_enter(&sc->sc_intr_lock);
+ (*intr)(intrarg);
+ mutex_exit(&sc->sc_intr_lock);
+ intr = sc->sc_in_intr;
+ intrarg = sc->sc_in_intrarg;
+ err = 0;
+ continue;
+ }
+ err = cv_wait_sig(&sc->sc_condvar_in, &sc->sc_lock);
+ if (err != 0) {
+ mutex_exit(&sc->sc_lock);
+ return err;
+ }
+ intr = sc->sc_in_intr;
+ intrarg = sc->sc_in_intrarg;
+
+ }
+
+ mutex_exit(&sc->sc_lock);
return err;
}
@@ -419,11 +577,26 @@
switch (play->encoding) {
case AUDIO_ENCODING_SLINEAR_LE:
if (play->precision == 16 && play->validbits == 16)
- pfil->prepend(pfil, pad_vol_slinear16_le, play);
+ pfil->prepend(pfil, pad_vol_slinear16_le_play, play);
break;
case AUDIO_ENCODING_SLINEAR_BE:
if (play->precision == 16 && play->validbits == 16)
- pfil->prepend(pfil, pad_vol_slinear16_be, play);
+ pfil->prepend(pfil, pad_vol_slinear16_be_play, play);
+ break;
+ default:
+ break;
+ }
+
+ if (rfil->req_size > 0)
+ rec = &rfil->filters[0].param;
+ switch (rec->encoding) {
+ case AUDIO_ENCODING_SLINEAR_LE:
+ if (rec->precision == 16 && rec->validbits == 16)
+ rfil->prepend(rfil, pad_vol_slinear16_le_rec, rec);
+ break;
+ case AUDIO_ENCODING_SLINEAR_BE:
+ if (rec->precision == 16 && rec->validbits == 16)
+ rfil->prepend(rfil, pad_vol_slinear16_be_rec, rec);
break;
default:
break;
@@ -443,13 +616,13 @@
KASSERT(mutex_owned(&sc->sc_lock));
- sc->sc_intr = intr;
- sc->sc_intrarg = intrarg;
+ sc->sc_out_intr = intr;
+ sc->sc_out_intrarg = intrarg;
sc->sc_blksize = blksize;
- err = pad_add_block(sc, block, blksize);
+ err = pad_add_block_out(sc, block, blksize);
- cv_broadcast(&sc->sc_condvar);
+ cv_broadcast(&sc->sc_condvar_out);
return err;
}
@@ -459,12 +632,21 @@
void (*intr)(void *), void *intrarg)
{
pad_softc_t *sc;
+ int err;
sc = (pad_softc_t *)opaque;
KASSERT(mutex_owned(&sc->sc_lock));
- return EOPNOTSUPP;
+ sc->sc_in_intr = intr;
+ sc->sc_in_intrarg = intrarg;
+ sc->sc_blksize = blksize;
+
+ err = pad_add_block_in(sc, block, blksize);
+
+ cv_broadcast(&sc->sc_condvar_in);
+
+ return err;
}
static int
@@ -476,10 +658,10 @@
KASSERT(mutex_owned(&sc->sc_lock));
- sc->sc_intr = NULL;
- sc->sc_intrarg = NULL;
- sc->sc_buflen = 0;
- sc->sc_rpos = sc->sc_wpos = 0;
+ sc->sc_out_intr = NULL;
+ sc->sc_out_intrarg = NULL;
+ sc->sc_out_buflen = 0;
+ sc->sc_rpos = sc->sc_opos = 0;
return 0;
}
@@ -493,6 +675,11 @@
KASSERT(mutex_owned(&sc->sc_lock));
+ sc->sc_in_intr = NULL;
+ sc->sc_in_intrarg = NULL;
+ sc->sc_in_buflen = 0;
+ sc->sc_wpos = sc->sc_ipos = 0;
+
return 0;
}
@@ -507,6 +694,11 @@
}
static int
+pad_setfd(void *hdl, int fd) {
+ return 0;
+}
+
+static int
pad_set_port(void *opaque, mixer_ctrl_t *mc)
{
pad_softc_t *sc;
@@ -520,6 +712,9 @@
case PAD_INPUT_DAC_VOLUME:
sc->sc_swvol = mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
return 0;
+ case PAD_INPUT_MIC_VOLUME:
+ sc->sc_recvol = mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
+ return 0;
}
return ENXIO;
@@ -539,6 +734,9 @@
case PAD_INPUT_DAC_VOLUME:
mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_swvol;
return 0;
+ case PAD_INPUT_MIC_VOLUME:
+ mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_recvol;
+ return 0;
}
return ENXIO;
@@ -566,6 +764,12 @@
di->type = AUDIO_MIXER_CLASS;
di->next = di->prev = AUDIO_MIXER_LAST;
return 0;
+ case PAD_RECORD_CLASS:
+ di->mixer_class = PAD_RECORD_CLASS;
+ strcpy(di->label.name, AudioCrecord);
+ di->type = AUDIO_MIXER_CLASS;
+ di->next = di->prev = AUDIO_MIXER_LAST;
+ return 0;
case PAD_OUTPUT_MASTER_VOLUME:
di->mixer_class = PAD_OUTPUT_CLASS;
strcpy(di->label.name, AudioNmaster);
@@ -582,6 +786,14 @@
di->un.v.num_channels = 1;
strcpy(di->un.v.units.name, AudioNvolume);
return 0;
+ case PAD_INPUT_MIC_VOLUME:
+ di->mixer_class = PAD_RECORD_CLASS;
+ strcpy(di->label.name, AudioNmicrophone);
+ di->type = AUDIO_MIXER_VALUE;
+ di->next = di->prev = AUDIO_MIXER_LAST;
+ di->un.v.num_channels = 1;
+ strcpy(di->un.v.units.name, AudioNvolume);
+ return 0;
}
return ENXIO;
@@ -596,7 +808,7 @@
KASSERT(mutex_owned(&sc->sc_lock));
- return 0;
+ return AUDIO_PROP_FULLDUPLEX;
}
static int
@@ -622,6 +834,89 @@
*thread = &sc->sc_lock;
}
+int
+pad_poll(dev_t dev, int events, lwp_t *l)
+{
+ pad_softc_t *sc;
+ int revents = 0;
+
+ sc = device_lookup_private(&pad_cd, PADUNIT(dev));
+ if (sc == NULL)
+ return ENXIO;
+
+ mutex_enter(&sc->sc_lock);
+
+ if (events & (POLLIN | POLLRDNORM)) {
+ if ((sc->sc_open & AUOPEN_READ) && (sc->sc_opos > 0)
+ && (sc->sc_mode & AUMODE_PLAY))
+ revents |= events & (POLLIN | POLLRDNORM);
+ }
+
+ if (events & (POLLOUT | POLLWRNORM)) {
+ if ((sc->sc_open & AUOPEN_WRITE) && (sc->sc_mode &
AUMODE_RECORD))
+ revents |= events & (POLLOUT | POLLWRNORM);
+ }
+
+ mutex_exit(&sc->sc_lock);
+
+ return revents;
+}
+
+static int
+pad_audio_open(void *hdl, int flags) {
+ struct pad_softc *sc = hdl;
+
+ if (!sc->sc_open)
+ return EIO;
+
+ if (flags & FREAD)
+ sc->sc_mode |= AUMODE_RECORD;
+
+ if (flags & FWRITE)
+ sc->sc_mode |= AUMODE_PLAY;
+
+ sc->sc_out_buflen = 0;
+ sc->sc_rpos = sc->sc_opos = 0;
+
+ sc->sc_in_buflen = 0;
+ sc->sc_wpos = sc->sc_ipos = 0;
+
+ return 0;
+}
+
+static void
+pad_audio_close(void *hdl) {
+ struct pad_softc *sc = hdl;
+
+ sc->sc_mode = 0;
+
+ sc->sc_out_buflen = 0;
+ sc->sc_rpos = sc->sc_opos = 0;
+
+ sc->sc_in_buflen = 0;
+ sc->sc_wpos = sc->sc_ipos = 0;
+
+ return;
+}
+
+int
+pad_ioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
+{
+ pad_softc_t *sc;
+ sc = device_lookup_private(&pad_cd, PADUNIT(dev));
+
+ /* Figure out which lock type we need. */
+ switch (cmd) {
+ case FIONBIO:
+ if (flag == 0)
+ sc->sc_flags &= ~O_NONBLOCK;
+ else
+ sc->sc_flags |= O_NONBLOCK;
+ }
+
+ return 0;
+}
+
#ifdef _MODULE
MODULE(MODULE_CLASS_DRIVER, pad, NULL);
Index: sys/dev/pad/padvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pad/padvar.h,v
retrieving revision 1.4
diff -u -r1.4 padvar.h
--- sys/dev/pad/padvar.h 23 Nov 2011 23:07:33 -0000 1.4
+++ sys/dev/pad/padvar.h 5 Jun 2012 12:27:28 -0000
@@ -33,11 +33,16 @@
device_t sc_dev;
u_int sc_open;
+ u_int sc_flags;
+ u_char sc_mode;
struct audio_encoding_set *sc_encodings;
- void (*sc_intr)(void *);
- void *sc_intrarg;
+ void (*sc_out_intr)(void *);
+ void *sc_out_intrarg;
+ void (*sc_in_intr)(void *);
+ void *sc_in_intrarg;
- kcondvar_t sc_condvar;
+ kcondvar_t sc_condvar_in;
+ kcondvar_t sc_condvar_out;
kmutex_t sc_lock;
kmutex_t sc_intr_lock;
@@ -46,11 +51,15 @@
#define PAD_BLKSIZE 1024
#define PAD_BUFSIZE 65536
- uint8_t sc_audiobuf[PAD_BUFSIZE];
- uint32_t sc_buflen;
- uint32_t sc_rpos, sc_wpos;
+ uint8_t sc_out_audiobuf[PAD_BUFSIZE];
+ uint8_t sc_in_audiobuf[PAD_BUFSIZE];
+ uint32_t sc_out_buflen;
+ uint32_t sc_in_buflen;
+ uint32_t sc_rpos, sc_opos;
+ uint32_t sc_wpos, sc_ipos;
u_int sc_swvol;
+ u_int sc_recvol;
} pad_softc_t;
#endif /* !_SYS_DEV_PAD_PADVAR_H */
Index: sys/dev/pad/padvol.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pad/padvol.c,v
retrieving revision 1.6
diff -u -r1.6 padvol.c
--- sys/dev/pad/padvol.c 23 Nov 2011 23:07:33 -0000 1.6
+++ sys/dev/pad/padvol.c 5 Jun 2012 12:27:28 -0000
@@ -72,7 +72,7 @@
return (stream_filter_t *)this;
}
-PAD_DEFINE_FILTER(pad_vol_slinear16_le)
+PAD_DEFINE_FILTER(pad_vol_slinear16_le_play)
{
pad_filter_t *pf;
pad_softc_t *sc;
@@ -98,7 +98,7 @@
return 0;
}
-PAD_DEFINE_FILTER(pad_vol_slinear16_be)
+PAD_DEFINE_FILTER(pad_vol_slinear16_be_play)
{
pad_filter_t *pf;
pad_softc_t *sc;
@@ -123,3 +123,55 @@
return 0;
}
+
+PAD_DEFINE_FILTER(pad_vol_slinear16_le_rec)
+{
+ pad_filter_t *pf;
+ pad_softc_t *sc;
+ stream_filter_t *this;
+ int16_t j, *wp;
+ int m, err;
+
+ pf = (pad_filter_t *)self;
+ sc = device_private(pf->audiosc->sc_dev);
+ this = &pf->base;
+ max_used = (max_used + 1) & ~1;
+
+ if ((err = this->prev->fetch_to(asc, this->prev, this->src, max_used)))
+ return err;
+ m = (dst->end - dst->start) & ~1;
+ m = min(m, max_used);
+ FILTER_LOOP_PROLOGUE(this->src, 2, dst, 2, m) {
+ j = le16dec(s);
+ wp = (int16_t *)d;
+ le16enc(wp, (j * sc->sc_recvol) / 255);
+ } FILTER_LOOP_EPILOGUE(this->src, dst);
+
+ return 0;
+}
+
+PAD_DEFINE_FILTER(pad_vol_slinear16_be_rec)
+{
+ pad_filter_t *pf;
+ pad_softc_t *sc;
+ stream_filter_t *this;
+ int16_t j, *wp;
+ int m, err;
+
+ pf = (pad_filter_t *)self;
+ sc = device_private(pf->audiosc->sc_dev);
+ this = &pf->base;
+ max_used = (max_used + 1) & ~1;
+
+ if ((err = this->prev->fetch_to(asc, this->prev, this->src, max_used)))
+ return err;
+ m = (dst->end - dst->start) & ~1;
+ m = min(m, max_used);
+ FILTER_LOOP_PROLOGUE(this->src, 2, dst, 2, m) {
+ j = be16dec(s);
+ wp = (int16_t *)d;
+ be16enc(wp, (j * sc->sc_recvol) / 255);
+ } FILTER_LOOP_EPILOGUE(this->src, dst);
+
+ return 0;
+}
Index: sys/dev/pad/padvol.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pad/padvol.h,v
retrieving revision 1.3
diff -u -r1.3 padvol.h
--- sys/dev/pad/padvol.h 23 Nov 2011 23:07:33 -0000 1.3
+++ sys/dev/pad/padvol.h 5 Jun 2012 12:27:28 -0000
@@ -29,9 +29,13 @@
#ifndef _SYS_DEV_PAD_PADVOL_H
#define _SYS_DEV_PAD_PADVOL_H
-stream_filter_t * pad_vol_slinear16_le(struct audio_softc *,
+stream_filter_t * pad_vol_slinear16_le_play(struct audio_softc *,
const audio_params_t *, const audio_params_t *);
-stream_filter_t * pad_vol_slinear16_be(struct audio_softc *,
+stream_filter_t * pad_vol_slinear16_be_play(struct audio_softc *,
+ const audio_params_t *, const audio_params_t *);
+stream_filter_t * pad_vol_slinear16_le_rec(struct audio_softc *,
+ const audio_params_t *, const audio_params_t *);
+stream_filter_t * pad_vol_slinear16_be_rec(struct audio_softc *,
const audio_params_t *, const audio_params_t *);
#define PAD_DEFINE_FILTER(name)
\
Note: These patches are derived from pad/padvol.c and are my own work which I
submit under the NetBSD license.
Regards,
Nat.
Home |
Main Index |
Thread Index |
Old Index