summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/audio.c149
-rw-r--r--sys/kern/kern_pledge.c6
-rw-r--r--sys/sys/audioio.h26
3 files changed, 178 insertions, 3 deletions
diff --git a/sys/dev/audio.c b/sys/dev/audio.c
index 1271bc77517..0db6c5d679b 100644
--- a/sys/dev/audio.c
+++ b/sys/dev/audio.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: audio.c,v 1.144 2016/01/29 15:14:23 ratchov Exp $ */
+/* $OpenBSD: audio.c,v 1.145 2016/03/16 06:46:39 ratchov Exp $ */
/*
* Copyright (c) 2015 Alexandre Ratchov <alex@caoua.org>
*
@@ -1023,6 +1023,135 @@ audio_getinfo(struct audio_softc *sc, struct audio_info *ai)
}
int
+audio_ioc_start(struct audio_softc *sc)
+{
+ if (!sc->pause) {
+ DPRINTF("%s: can't start: already started\n", DEVNAME(sc));
+ return EBUSY;
+ }
+ if ((sc->mode & AUMODE_PLAY) && sc->play.used != sc->play.len) {
+ DPRINTF("%s: play buffer not ready\n", DEVNAME(sc));
+ return EBUSY;
+ }
+ if ((sc->mode & AUMODE_RECORD) && sc->rec.used != 0) {
+ DPRINTF("%s: record buffer not ready\n", DEVNAME(sc));
+ return EBUSY;
+ }
+ sc->pause = 0;
+ return audio_start(sc);
+}
+
+int
+audio_ioc_stop(struct audio_softc *sc)
+{
+ if (sc->pause) {
+ DPRINTF("%s: can't stop: not started\n", DEVNAME(sc));
+ return EBUSY;
+ }
+ sc->pause = 1;
+ if (sc->active)
+ return audio_stop(sc);
+ return 0;
+}
+
+int
+audio_ioc_getpar(struct audio_softc *sc, struct audio_swpar *p)
+{
+ p->rate = sc->rate;
+ p->sig = sc->sw_enc == AUDIO_ENCODING_SLINEAR_LE ||
+ sc->sw_enc == AUDIO_ENCODING_SLINEAR_BE;
+ p->le = sc->sw_enc == AUDIO_ENCODING_SLINEAR_LE ||
+ sc->sw_enc == AUDIO_ENCODING_ULINEAR_LE;
+ p->bits = sc->bits;
+ p->bps = sc->bps;
+ p->msb = sc->msb;
+ p->pchan = sc->pchan;
+ p->rchan = sc->rchan;
+ p->nblks = sc->nblks;
+ p->round = sc->round;
+ return 0;
+}
+
+int
+audio_ioc_setpar(struct audio_softc *sc, struct audio_swpar *p)
+{
+ int error, le, sig;
+
+ if (sc->active) {
+ DPRINTF("%s: can't change params during dma\n",
+ DEVNAME(sc));
+ return EBUSY;
+ }
+
+ /*
+ * copy desired parameters into the softc structure
+ */
+ if (p->sig != ~0U || p->le != ~0U || p->bits != ~0U) {
+ sig = 1;
+ le = (BYTE_ORDER == LITTLE_ENDIAN);
+ sc->bits = 16;
+ sc->bps = 2;
+ sc->msb = 1;
+ if (p->sig != ~0U)
+ sig = p->sig;
+ if (p->le != ~0U)
+ le = p->le;
+ if (p->bits != ~0U) {
+ sc->bits = p->bits;
+ sc->bps = sc->bits <= 8 ?
+ 1 : (sc->bits <= 16 ? 2 : 4);
+ if (p->bps != ~0U)
+ sc->bps = p->bps;
+ if (p->msb != ~0U)
+ sc->msb = p->msb ? 1 : 0;
+ }
+ sc->sw_enc = (sig) ?
+ (le ? AUDIO_ENCODING_SLINEAR_LE :
+ AUDIO_ENCODING_SLINEAR_BE) :
+ (le ? AUDIO_ENCODING_ULINEAR_LE :
+ AUDIO_ENCODING_ULINEAR_BE);
+ }
+ if (p->rate != ~0)
+ sc->rate = p->rate;
+ if (p->pchan != ~0)
+ sc->pchan = p->pchan;
+ if (p->rchan != ~0)
+ sc->rchan = p->rchan;
+ if (p->round != ~0)
+ sc->round = p->round;
+ if (p->nblks != ~0)
+ sc->nblks = p->nblks;
+
+ /*
+ * if the device is not opened for playback or recording don't
+ * touch the hardware yet (ex. if this is /dev/audioctlN)
+ */
+ if (sc->mode == 0)
+ return 0;
+
+ /*
+ * negociate parameters with the hardware
+ */
+ error = audio_setpar(sc);
+ if (error)
+ return error;
+ audio_clear(sc);
+ if ((sc->mode & AUMODE_PLAY) && sc->ops->init_output) {
+ error = sc->ops->init_output(sc->arg,
+ sc->play.data, sc->play.len);
+ if (error)
+ return error;
+ }
+ if ((sc->mode & AUMODE_RECORD) && sc->ops->init_input) {
+ error = sc->ops->init_input(sc->arg,
+ sc->rec.data, sc->rec.len);
+ if (error)
+ return error;
+ }
+ return 0;
+}
+
+int
audio_match(struct device *parent, void *match, void *aux)
{
struct audio_attach_args *sa = aux;
@@ -1587,6 +1716,16 @@ audio_ioctl(struct audio_softc *sc, unsigned long cmd, void *addr)
ap->rec_xrun = sc->rec.xrun;
mtx_leave(&audio_lock);
break;
+ case AUDIO_START:
+ return audio_ioc_start(sc);
+ case AUDIO_STOP:
+ return audio_ioc_stop(sc);
+ case AUDIO_SETPAR:
+ error = audio_ioc_setpar(sc, (struct audio_swpar *)addr);
+ break;
+ case AUDIO_GETPAR:
+ error = audio_ioc_getpar(sc, (struct audio_swpar *)addr);
+ break;
case AUDIO_SETINFO:
error = audio_setinfo(sc, (struct audio_info *)addr);
break;
@@ -1795,6 +1934,14 @@ audioioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
error = EBUSY;
break;
}
+ if (cmd == AUDIO_SETPAR && sc->mode != 0) {
+ error = EBUSY;
+ break;
+ }
+ if (cmd == AUDIO_START || cmd == AUDIO_STOP) {
+ error = ENXIO;
+ break;
+ }
error = audio_ioctl(sc, cmd, addr);
break;
case AUDIO_DEV_MIXER:
diff --git a/sys/kern/kern_pledge.c b/sys/kern/kern_pledge.c
index 9d20c7f1784..1c711883fdf 100644
--- a/sys/kern/kern_pledge.c
+++ b/sys/kern/kern_pledge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_pledge.c,v 1.157 2016/03/15 15:10:09 semarie Exp $ */
+/* $OpenBSD: kern_pledge.c,v 1.158 2016/03/16 06:46:39 ratchov Exp $ */
/*
* Copyright (c) 2015 Nicholas Marriott <nicm@openbsd.org>
@@ -1170,6 +1170,10 @@ pledge_ioctl(struct proc *p, long com, struct file *fp)
#if NAUDIO > 0
switch (com) {
case AUDIO_GETPOS:
+ case AUDIO_GETPAR:
+ case AUDIO_SETPAR:
+ case AUDIO_START:
+ case AUDIO_STOP:
case AUDIO_SETINFO:
case AUDIO_GETINFO:
case AUDIO_GETENC:
diff --git a/sys/sys/audioio.h b/sys/sys/audioio.h
index f93c1c45e56..0c5e850f073 100644
--- a/sys/sys/audioio.h
+++ b/sys/sys/audioio.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: audioio.h,v 1.23 2015/07/28 20:45:02 ratchov Exp $ */
+/* $OpenBSD: audioio.h,v 1.24 2016/03/16 06:46:39 ratchov Exp $ */
/* $NetBSD: audioio.h,v 1.24 1998/08/13 06:28:41 mrg Exp $ */
/*
@@ -38,6 +38,26 @@
#ifndef _SYS_AUDIOIO_H_
#define _SYS_AUDIOIO_H_
+#define AUDIO_INITPAR(p) \
+ (void)memset((void *)(p), 0xff, sizeof(struct audio_swpar))
+
+/*
+ * argument to AUDIO_SETPAR and AUDIO_GETPAR ioctls
+ */
+struct audio_swpar {
+ unsigned int sig; /* if 1, encoding is signed */
+ unsigned int le; /* if 1, encoding is little-endian */
+ unsigned int bits; /* bits per sample */
+ unsigned int bps; /* bytes per sample */
+ unsigned int msb; /* if 1, bits are msb-aligned */
+ unsigned int rate; /* common play & rec sample rate */
+ unsigned int pchan; /* play channels */
+ unsigned int rchan; /* rec channels */
+ unsigned int nblks; /* number of blocks in play buffer */
+ unsigned int round; /* common frames per block */
+ unsigned int _spare[6];
+};
+
/*
* Audio device
*/
@@ -149,6 +169,10 @@ typedef struct audio_encoding {
#define AUDIO_GETOOFFS _IOR('A', 33, struct audio_offset)
#define AUDIO_GETPROPS _IOR('A', 34, int)
#define AUDIO_GETPOS _IOR('A', 35, struct audio_pos)
+#define AUDIO_GETPAR _IOR('A', 36, struct audio_swpar)
+#define AUDIO_SETPAR _IOWR('A', 37, struct audio_swpar)
+#define AUDIO_START _IO('A', 38)
+#define AUDIO_STOP _IO('A', 39)
#define AUDIO_PROP_FULLDUPLEX 0x01
#define AUDIO_PROP_MMAP 0x02
#define AUDIO_PROP_INDEPENDENT 0x04