diff options
author | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2018-05-26 10:13:19 +0000 |
---|---|---|
committer | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2018-05-26 10:13:19 +0000 |
commit | 56c7c476f8191c9750adf4c9a5847cad92e74c02 (patch) | |
tree | 5d6f2a8e9e5ed75cc9332ae7cf2659e296e992b7 | |
parent | 5ce0e4a4c6df4c9ceae0b1e9a67b0c42d8b10ee2 (diff) |
Add a "record.enable" mixer knob to control recording. When recording
is disabled, the device records silence. The control may be modified
only by root and defaults to "off", ie. recording is disabled by
default.
ok florian, deraadt
-rw-r--r-- | sys/dev/audio.c | 118 |
1 files changed, 106 insertions, 12 deletions
diff --git a/sys/dev/audio.c b/sys/dev/audio.c index ce73f818233..30260cc69a4 100644 --- a/sys/dev/audio.c +++ b/sys/dev/audio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: audio.c,v 1.169 2018/04/11 04:48:31 ratchov Exp $ */ +/* $OpenBSD: audio.c,v 1.170 2018/05/26 10:13:18 ratchov Exp $ */ /* * Copyright (c) 2015 Alexandre Ratchov <alex@caoua.org> * @@ -56,6 +56,14 @@ #define AUDIO_BUFSZ 65536 /* buffer size in bytes */ /* + * mixer entries added by the audio(4) layer + */ +#define MIXER_RECORD 0 /* record class */ +#define MIXER_RECORD_ENABLE 1 /* record.enable control */ +#define MIXER_RECORD_ENABLE_OFF 0 /* record.enable=off value */ +#define MIXER_RECORD_ENABLE_ON 1 /* record.enable=on value */ + +/* * dma buffer */ struct audio_buf { @@ -118,6 +126,7 @@ struct audio_softc { struct task wskbd_task; int wskbd_taskset; #endif + int record_enable; /* mixer record.enable value */ }; int audio_match(struct device *, void *, void *); @@ -463,6 +472,10 @@ audio_rintr(void *addr) } sc->rec.pos += sc->rec.blksz; + if (sc->record_enable == MIXER_RECORD_ENABLE_OFF) { + ptr = audio_buf_wgetblk(&sc->rec, &count); + audio_fill_sil(sc, ptr, sc->rec.blksz); + } audio_buf_wcommit(&sc->rec, sc->rec.blksz); if (sc->rec.used > sc->rec.len - sc->rec.blksz) { DPRINTFN(1, "%s: rec overrun\n", DEVNAME(sc)); @@ -1057,6 +1070,7 @@ audio_attach(struct device *parent, struct device *self, void *aux) sc->round = 960; sc->nblks = 2; sc->play.pos = sc->play.xrun = sc->rec.pos = sc->rec.xrun = 0; + sc->record_enable = MIXER_RECORD_ENABLE_OFF; /* * allocate an array of mixer_ctrl structures to save the @@ -1603,10 +1617,96 @@ audio_ioctl(struct audio_softc *sc, unsigned long cmd, void *addr) } int -audio_ioctl_mixer(struct audio_softc *sc, unsigned long cmd, void *addr) +audio_mixer_devinfo(struct audio_softc *sc, struct mixer_devinfo *devinfo) +{ + if (devinfo->index < sc->mix_nent) + return sc->ops->query_devinfo(sc->arg, devinfo); + + devinfo->next = -1; + devinfo->prev = -1; + switch (devinfo->index - sc->mix_nent) { + case MIXER_RECORD: + strlcpy(devinfo->label.name, AudioCrecord, MAX_AUDIO_DEV_LEN); + devinfo->type = AUDIO_MIXER_CLASS; + devinfo->mixer_class = -1; + break; + case MIXER_RECORD_ENABLE: + strlcpy(devinfo->label.name, "enable", MAX_AUDIO_DEV_LEN); + devinfo->type = AUDIO_MIXER_ENUM; + devinfo->mixer_class = MIXER_RECORD + sc->mix_nent; + devinfo->un.e.num_mem = 2; + devinfo->un.e.member[0].ord = MIXER_RECORD_ENABLE_OFF; + strlcpy(devinfo->un.e.member[0].label.name, "off", + MAX_AUDIO_DEV_LEN); + devinfo->un.e.member[1].ord = MIXER_RECORD_ENABLE_ON; + strlcpy(devinfo->un.e.member[1].label.name, "on", + MAX_AUDIO_DEV_LEN); + break; + default: + return EINVAL; + } + + return 0; +} + +int +audio_mixer_read(struct audio_softc *sc, struct mixer_ctrl *c) +{ + if (c->dev < sc->mix_nent) + return sc->ops->get_port(sc->arg, c); + + switch (c->dev - sc->mix_nent) { + case MIXER_RECORD: + return EBADF; + case MIXER_RECORD_ENABLE: + c->un.ord = sc->record_enable; + break; + default: + return EINVAL; + } + + return 0; +} + +int +audio_mixer_write(struct audio_softc *sc, struct mixer_ctrl *c, struct proc *p) { int error; + if (c->dev < sc->mix_nent) { + error = sc->ops->set_port(sc->arg, c); + if (error) + return error; + if (sc->ops->commit_settings) + return sc->ops->commit_settings(sc->arg); + return 0; + } + + switch (c->dev - sc->mix_nent) { + case MIXER_RECORD: + return EBADF; + case MIXER_RECORD_ENABLE: + switch (c->un.ord) { + case MIXER_RECORD_ENABLE_OFF: + case MIXER_RECORD_ENABLE_ON: + break; + default: + return EINVAL; + } + if (suser(p) == 0) + sc->record_enable = c->un.ord; + break; + default: + return EINVAL; + } + + return 0; +} + +int +audio_ioctl_mixer(struct audio_softc *sc, unsigned long cmd, void *addr, + struct proc *p) +{ /* block if quiesced */ while (sc->quiesce) tsleep(&sc->quiesce, 0, "mix_qio", 0); @@ -1616,17 +1716,11 @@ audio_ioctl_mixer(struct audio_softc *sc, unsigned long cmd, void *addr) /* All handled in the upper FS layer. */ break; case AUDIO_MIXER_DEVINFO: - ((mixer_devinfo_t *)addr)->un.v.delta = 0; - return sc->ops->query_devinfo(sc->arg, (mixer_devinfo_t *)addr); + return audio_mixer_devinfo(sc, addr); case AUDIO_MIXER_READ: - return sc->ops->get_port(sc->arg, (mixer_ctrl_t *)addr); + return audio_mixer_read(sc, addr); case AUDIO_MIXER_WRITE: - error = sc->ops->set_port(sc->arg, (mixer_ctrl_t *)addr); - if (error) - return error; - if (sc->ops->commit_settings) - return sc->ops->commit_settings(sc->arg); - break; + return audio_mixer_write(sc, addr, p); default: return ENOTTY; } @@ -1778,7 +1872,7 @@ audioioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) error = audio_ioctl(sc, cmd, addr); break; case AUDIO_DEV_MIXER: - error = audio_ioctl_mixer(sc, cmd, addr); + error = audio_ioctl_mixer(sc, cmd, addr, p); break; default: error = ENXIO; |