diff options
| author | jmcneill <jmcneill@NetBSD.org> | 2011-12-26 21:06:42 +0000 |
|---|---|---|
| committer | jmcneill <jmcneill@NetBSD.org> | 2011-12-26 21:06:42 +0000 |
| commit | 012e670af2df5590aa02ff385dbe8e763c8a2129 (patch) | |
| tree | 3fa881f0e1f0f221eb38d773c9f364e740718b51 | |
| parent | 491d368d482074fd871ec977e3789e028a9c2b42 (diff) | |
add vaudio(4) audio device driver
| -rw-r--r-- | sys/arch/usermode/conf/GENERIC.common | 6 | ||||
| -rw-r--r-- | sys/arch/usermode/conf/files.usermode | 6 | ||||
| -rw-r--r-- | sys/arch/usermode/dev/mainbus.c | 11 | ||||
| -rw-r--r-- | sys/arch/usermode/dev/vaudio.c | 423 | ||||
| -rw-r--r-- | sys/arch/usermode/include/mainbus.h | 6 | ||||
| -rw-r--r-- | sys/arch/usermode/include/thunk.h | 19 | ||||
| -rw-r--r-- | sys/arch/usermode/usermode/machdep.c | 19 | ||||
| -rw-r--r-- | sys/arch/usermode/usermode/thunk.c | 88 |
8 files changed, 567 insertions, 11 deletions
diff --git a/sys/arch/usermode/conf/GENERIC.common b/sys/arch/usermode/conf/GENERIC.common index 18920c03bc3..3c31a0b20e3 100644 --- a/sys/arch/usermode/conf/GENERIC.common +++ b/sys/arch/usermode/conf/GENERIC.common @@ -1,9 +1,9 @@ -# $NetBSD: GENERIC.common,v 1.2 2011/12/26 12:39:19 jmcneill Exp $ +# $NetBSD: GENERIC.common,v 1.3 2011/12/26 21:06:42 jmcneill Exp $ include "arch/usermode/conf/std.usermode" options INCLUDE_CONFIG_FILE -#ident "GENERIC-$Revision: 1.2 $" +#ident "GENERIC-$Revision: 1.3 $" maxusers 32 makeoptions DEBUG="-O1 -g3" @@ -50,6 +50,8 @@ clock0 at mainbus? ttycons0 at mainbus? ld0 at mainbus? veth0 at mainbus? +vaudio0 at mainbus? +audio0 at vaudio0 #options SDL #genfb0 at thunkbus? diff --git a/sys/arch/usermode/conf/files.usermode b/sys/arch/usermode/conf/files.usermode index 4e5b37b6d3c..5f10e1a576e 100644 --- a/sys/arch/usermode/conf/files.usermode +++ b/sys/arch/usermode/conf/files.usermode @@ -1,4 +1,4 @@ -# $NetBSD: files.usermode,v 1.13 2011/12/26 12:39:19 jmcneill Exp $ +# $NetBSD: files.usermode,v 1.14 2011/12/26 21:06:42 jmcneill Exp $ maxpartitions 8 maxusers 8 16 64 @@ -31,6 +31,10 @@ device veth { } : arp, ether, ifnet attach veth at thunkbus file arch/usermode/dev/if_veth.c veth +device vaudio { } : audiobus, auconv, aurateconv, mulaw +attach vaudio at thunkbus +file arch/usermode/dev/vaudio.c vaudio + attach ld at thunkbus with ld_thunkbus file arch/usermode/dev/ld_thunkbus.c ld_thunkbus diff --git a/sys/arch/usermode/dev/mainbus.c b/sys/arch/usermode/dev/mainbus.c index fbfdc3bb6ee..50d19d2be6a 100644 --- a/sys/arch/usermode/dev/mainbus.c +++ b/sys/arch/usermode/dev/mainbus.c @@ -1,4 +1,4 @@ -/* $NetBSD: mainbus.c,v 1.6 2011/12/26 12:39:19 jmcneill Exp $ */ +/* $NetBSD: mainbus.c,v 1.7 2011/12/26 21:06:42 jmcneill Exp $ */ /*- * Copyright (c) 2007 Jared D. McNeill <jmcneill@invisible.ca> @@ -31,7 +31,7 @@ #endif #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.6 2011/12/26 12:39:19 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.7 2011/12/26 21:06:42 jmcneill Exp $"); #include <sys/param.h> #include <sys/proc.h> @@ -57,6 +57,7 @@ CFATTACH_DECL_NEW(mainbus, sizeof(mainbus_softc_t), extern char *usermode_root_image_path; extern char *usermode_tap_device; extern char *usermode_tap_eaddr; +extern char *usermode_audio_device; static int mainbus_match(device_t parent, cfdata_t match, void *opaque) @@ -97,6 +98,12 @@ mainbus_attach(device_t parent, device_t self, void *opaque) config_found_ia(self, "thunkbus", &taa, mainbus_print); } + if (usermode_audio_device) { + taa.taa_type = THUNKBUS_TYPE_VAUDIO; + taa.u.vaudio.device = usermode_audio_device; + config_found_ia(self, "thunkbus", &taa, mainbus_print); + } + if (usermode_root_image_path) { taa.taa_type = THUNKBUS_TYPE_DISKIMAGE; taa.u.diskimage.path = usermode_root_image_path; diff --git a/sys/arch/usermode/dev/vaudio.c b/sys/arch/usermode/dev/vaudio.c new file mode 100644 index 00000000000..45287313fa4 --- /dev/null +++ b/sys/arch/usermode/dev/vaudio.c @@ -0,0 +1,423 @@ +/* $NetBSD: vaudio.c,v 1.1 2011/12/26 21:09:22 jmcneill Exp $ */ + +/*- + * Copyright (c) 2011 Jared D. McNeill <jmcneill@invisible.ca> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: vaudio.c,v 1.1 2011/12/26 21:09:22 jmcneill Exp $"); + +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/audioio.h> + +#include <machine/mainbus.h> +#include <machine/thunk.h> + +#include <dev/audio_if.h> +#include <dev/auconv.h> + +static const struct audio_format vaudio_audio_formats[1] = { + { NULL, AUMODE_PLAY|AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16, + 2, AUFMT_STEREO, 0, { 8000, 48000 } }, +}; + +struct vaudio_stream { + struct vaudio_softc *st_softc; + void * st_sih; + callout_t st_callout; + void (*st_intr)(void *); + void * st_intrarg; + uint8_t * st_start; + uint8_t * st_end; + uint8_t * st_cur; + int st_blksize; + bool st_running; +}; + +struct vaudio_softc { + device_t sc_dev; + void * sc_audiodev; + const char * sc_audiopath; + int sc_audiofd; + struct audio_encoding_set * sc_encodings; + audio_params_t sc_pparam; + audio_params_t sc_rparam; + kmutex_t sc_lock; + kmutex_t sc_intr_lock; + + struct vaudio_stream sc_play; + struct vaudio_stream sc_record; +}; + +static int vaudio_match(device_t, cfdata_t, void *); +static void vaudio_attach(device_t, device_t, void *); + +static void vaudio_intr(void *); +static void vaudio_softintr_play(void *); +static void vaudio_softintr_record(void *); + +static int vaudio_open(void *, int); +static void vaudio_close(void *); +static int vaudio_drain(void *); +static int vaudio_query_encoding(void *, audio_encoding_t *); +static int vaudio_set_params(void *, int, int, audio_params_t *, + audio_params_t *, stream_filter_list_t *, + stream_filter_list_t *); +static int vaudio_commit_settings(void *); +static int vaudio_trigger_output(void *, void *, void *, int, + void (*)(void *), void *, + const audio_params_t *); +static int vaudio_trigger_input(void *, void *, void *, int, + void (*)(void *), void *, + const audio_params_t *); +static int vaudio_halt_output(void *); +static int vaudio_halt_input(void *); +static int vaudio_getdev(void *, struct audio_device *); +static int vaudio_set_port(void *, mixer_ctrl_t *); +static int vaudio_get_port(void *, mixer_ctrl_t *); +static int vaudio_query_devinfo(void *, mixer_devinfo_t *); +static int vaudio_get_props(void *); +static void vaudio_get_locks(void *, kmutex_t **, kmutex_t **); + +CFATTACH_DECL_NEW(vaudio, sizeof(struct vaudio_softc), + vaudio_match, vaudio_attach, NULL, NULL); + +static const struct audio_hw_if vaudio_hw_if = { + .open = vaudio_open, + .close = vaudio_close, + .drain = vaudio_drain, + .query_encoding = vaudio_query_encoding, + .set_params = vaudio_set_params, + .commit_settings = vaudio_commit_settings, + .halt_output = vaudio_halt_output, + .halt_input = vaudio_halt_input, + .getdev = vaudio_getdev, + .set_port = vaudio_set_port, + .get_port = vaudio_get_port, + .query_devinfo = vaudio_query_devinfo, + .get_props = vaudio_get_props, + .trigger_output = vaudio_trigger_output, + .trigger_input = vaudio_trigger_input, + .get_locks = vaudio_get_locks, +}; + +static int +vaudio_match(device_t parent, cfdata_t match, void *opaque) +{ + struct thunkbus_attach_args *taa = opaque; + + if (taa->taa_type != THUNKBUS_TYPE_VAUDIO) + return 0; + + return 1; +} + +static void +vaudio_attach(device_t parent, device_t self, void *opaque) +{ + struct vaudio_softc *sc = device_private(self); + struct thunkbus_attach_args *taa = opaque; + int error; + + aprint_naive("\n"); + aprint_normal(": Virtual Audio (device = %s)\n", taa->u.vaudio.device); + + sc->sc_dev = self; + sc->sc_audiopath = taa->u.vaudio.device; + sc->sc_audiofd = thunk_audio_open(sc->sc_audiopath); + if (sc->sc_audiofd == -1) { + aprint_error_dev(self, "couldn't open audio device: %d\n", + thunk_geterrno()); + return; + } + + mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); + mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO); + + error = auconv_create_encodings(vaudio_audio_formats, + __arraycount(vaudio_audio_formats), &sc->sc_encodings); + if (error) { + aprint_error_dev(self, "couldn't create encodings\n"); + return; + } + + sc->sc_play.st_softc = sc; + sc->sc_play.st_sih = softint_establish(SOFTINT_SERIAL, + vaudio_softintr_play, &sc->sc_play); + callout_init(&sc->sc_play.st_callout, 0); + callout_setfunc(&sc->sc_play.st_callout, vaudio_intr, &sc->sc_play); + + sc->sc_record.st_softc = sc; + sc->sc_record.st_sih = softint_establish(SOFTINT_SERIAL, + vaudio_softintr_record, &sc->sc_record); + callout_init(&sc->sc_record.st_callout, 0); + callout_setfunc(&sc->sc_record.st_callout, vaudio_intr, &sc->sc_record); + + sc->sc_audiodev = audio_attach_mi(&vaudio_hw_if, sc, self); +} + +static void +vaudio_intr(void *opaque) +{ + struct vaudio_stream *st = opaque; + + softint_schedule(st->st_sih); +} + +static void +vaudio_softintr_play(void *opaque) +{ + struct vaudio_stream *st = opaque; + struct vaudio_softc *sc = st->st_softc; + + while (st->st_running) { + if (thunk_audio_pollout(sc->sc_audiofd) < st->st_blksize) + break; + thunk_audio_write(sc->sc_audiofd, st->st_cur, st->st_blksize); + mutex_spin_enter(&sc->sc_intr_lock); + st->st_intr(st->st_intrarg); + mutex_spin_exit(&sc->sc_intr_lock); + st->st_cur += st->st_blksize; + if (st->st_cur >= st->st_end) + st->st_cur = st->st_start; + } + + if (st->st_running) { + callout_schedule(&st->st_callout, 1); + } +} + +static void +vaudio_softintr_record(void *opaque) +{ + struct vaudio_stream *st = opaque; + struct vaudio_softc *sc = st->st_softc; + + while (st->st_running) { + if (thunk_audio_pollin(sc->sc_audiofd) < st->st_blksize) + break; + thunk_audio_read(sc->sc_audiofd, st->st_cur, st->st_blksize); + mutex_spin_enter(&sc->sc_intr_lock); + st->st_intr(st->st_intrarg); + mutex_spin_exit(&sc->sc_intr_lock); + st->st_cur += st->st_blksize; + if (st->st_cur >= st->st_end) + st->st_cur = st->st_start; + } + + if (st->st_running) { + callout_schedule(&st->st_callout, 1); + } +} + +static int +vaudio_open(void *opaque, int flags) +{ + return 0; +} + +static void +vaudio_close(void *opaque) +{ +} + +static int +vaudio_drain(void *opaque) +{ + struct vaudio_softc *sc = opaque; + + return thunk_audio_drain(sc->sc_audiofd); +} + +static int +vaudio_query_encoding(void *opaque, audio_encoding_t *enc) +{ + struct vaudio_softc *sc = opaque; + + return auconv_query_encoding(sc->sc_encodings, enc); +} + +static int +vaudio_set_params(void *opaque, int setmode, int usemode, + audio_params_t *play, audio_params_t *rec, + stream_filter_list_t *pfil, stream_filter_list_t *rfil) +{ + struct vaudio_softc *sc = opaque; + audio_params_t *p; + stream_filter_list_t *fil; + int mode, index; + + for (mode = AUMODE_RECORD; mode != -1; + mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) { + if ((setmode & mode) == 0) + continue; + p = mode == AUMODE_PLAY ? play : rec; + fil = mode == AUMODE_PLAY ? pfil : rfil; + if (p == NULL) + continue; + + index = auconv_set_converter(vaudio_audio_formats, + __arraycount(vaudio_audio_formats), mode, p, TRUE, fil); + if (index < 0) + return EINVAL; + if (fil->req_size > 0) + p = &fil->filters[0].param; + + if (mode == AUMODE_PLAY) + sc->sc_pparam = *p; + else + sc->sc_rparam = *p; + } + + return 0; +} + +static int +vaudio_commit_settings(void *opaque) +{ + struct vaudio_softc *sc = opaque; + thunk_audio_config_t pconf, rconf; + + memset(&pconf, 0, sizeof(pconf)); + pconf.sample_rate = sc->sc_pparam.sample_rate; + pconf.precision = sc->sc_pparam.precision; + pconf.validbits = sc->sc_pparam.validbits; + pconf.channels = sc->sc_pparam.channels; + + memset(&rconf, 0, sizeof(rconf)); + rconf.sample_rate = sc->sc_rparam.sample_rate; + rconf.precision = sc->sc_rparam.precision; + rconf.validbits = sc->sc_rparam.validbits; + rconf.channels = sc->sc_rparam.channels; + + return thunk_audio_config(sc->sc_audiofd, &pconf, &rconf); +} + +static int +vaudio_trigger_output(void *opaque, void *start, void *end, int blksize, + void (*intr)(void *), void *intrarg, const audio_params_t *param) +{ + struct vaudio_softc *sc = opaque; + struct vaudio_stream *st = &sc->sc_play; + + st->st_intr = intr; + st->st_intrarg = intrarg; + st->st_start = st->st_cur = start; + st->st_end = end; + st->st_blksize = blksize; + st->st_running = true; + callout_schedule(&st->st_callout, 1); + + return 0; +} + +static int +vaudio_trigger_input(void *opaque, void *start, void *end, int blksize, + void (*intr)(void *), void *intrarg, const audio_params_t *param) +{ + struct vaudio_softc *sc = opaque; + struct vaudio_stream *st = &sc->sc_record; + + st->st_intr = intr; + st->st_intrarg = intrarg; + st->st_start = st->st_cur = start; + st->st_end = end; + st->st_blksize = blksize; + st->st_running = true; + callout_schedule(&st->st_callout, 1); + + return 0; +} + +static int +vaudio_halt_output(void *opaque) +{ + struct vaudio_softc *sc = opaque; + + sc->sc_play.st_running = false; + callout_halt(&sc->sc_play.st_callout, NULL); + + return 0; +} + +static int +vaudio_halt_input(void *opaque) +{ + struct vaudio_softc *sc = opaque; + + sc->sc_record.st_running = false; + callout_halt(&sc->sc_record.st_callout, NULL); + + return 0; +} + +static int +vaudio_getdev(void *opaque, struct audio_device *adev) +{ + struct vaudio_softc *sc = opaque; + + sprintf(adev->name, "Virtual Audio"); + sprintf(adev->version, ""); + snprintf(adev->config, sizeof(adev->config), "%s", sc->sc_audiopath); + + return 0; +} + +static int +vaudio_set_port(void *opaque, mixer_ctrl_t *mc) +{ + return EINVAL; +} + +static int +vaudio_get_port(void *opaque, mixer_ctrl_t *mc) +{ + return EINVAL; +} + +static int +vaudio_query_devinfo(void *opaque, mixer_devinfo_t *di) +{ + return EINVAL; +} + +static int +vaudio_get_props(void *opaque) +{ + /* NB: should query host audio driver for capabilities */ + return AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE; +} + +static void +vaudio_get_locks(void *opaque, kmutex_t **intr, kmutex_t **thread) +{ + struct vaudio_softc *sc = opaque; + + *intr = &sc->sc_intr_lock; + *thread = &sc->sc_lock; +} diff --git a/sys/arch/usermode/include/mainbus.h b/sys/arch/usermode/include/mainbus.h index 9fa1d41615d..d4aacab69e6 100644 --- a/sys/arch/usermode/include/mainbus.h +++ b/sys/arch/usermode/include/mainbus.h @@ -1,4 +1,4 @@ -/* $NetBSD: mainbus.h,v 1.5 2011/12/26 12:39:19 jmcneill Exp $ */ +/* $NetBSD: mainbus.h,v 1.6 2011/12/26 21:06:42 jmcneill Exp $ */ /*- * Copyright (c) 2007 Jared D. McNeill <jmcneill@invisible.ca> @@ -37,6 +37,7 @@ struct thunkbus_attach_args { #define THUNKBUS_TYPE_DISKIMAGE 3 #define THUNKBUS_TYPE_GENFB 4 #define THUNKBUS_TYPE_VETH 5 +#define THUNKBUS_TYPE_VAUDIO 6 union { struct { @@ -46,6 +47,9 @@ struct thunkbus_attach_args { const char *device; const char *eaddr; } veth; + struct { + const char *device; + } vaudio; } u; }; diff --git a/sys/arch/usermode/include/thunk.h b/sys/arch/usermode/include/thunk.h index 76031423f51..80ce0aea0ee 100644 --- a/sys/arch/usermode/include/thunk.h +++ b/sys/arch/usermode/include/thunk.h @@ -1,4 +1,4 @@ -/* $NetBSD: thunk.h,v 1.45 2011/12/26 12:39:19 jmcneill Exp $ */ +/* $NetBSD: thunk.h,v 1.46 2011/12/26 21:06:42 jmcneill Exp $ */ /*- * Copyright (c) 2011 Jared D. McNeill <jmcneill@invisible.ca> @@ -152,6 +152,23 @@ int thunk_open_tap(const char *); int thunk_pollin_tap(int, int); int thunk_pollout_tap(int, int); +typedef struct { + unsigned int sample_rate; + unsigned int precision; + unsigned int validbits; + unsigned int channels; +} thunk_audio_config_t; + +int thunk_audio_open(const char *); +int thunk_audio_close(int); +int thunk_audio_drain(int); +int thunk_audio_config(int, const thunk_audio_config_t *, + const thunk_audio_config_t *); +int thunk_audio_pollout(int); +int thunk_audio_pollin(int); +int thunk_audio_write(int, const void *, size_t); +int thunk_audio_read(int, void *, size_t); + int thunk_sdl_init(unsigned int, unsigned int, unsigned short); void * thunk_sdl_getfb(size_t); int thunk_sdl_getchar(void); diff --git a/sys/arch/usermode/usermode/machdep.c b/sys/arch/usermode/usermode/machdep.c index bffaa9f1091..5b4809ffca1 100644 --- a/sys/arch/usermode/usermode/machdep.c +++ b/sys/arch/usermode/usermode/machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.c,v 1.43 2011/12/26 12:39:20 jmcneill Exp $ */ +/* $NetBSD: machdep.c,v 1.44 2011/12/26 21:06:42 jmcneill Exp $ */ /*- * Copyright (c) 2011 Reinoud Zandijk <reinoud@netbsd.org> @@ -38,7 +38,7 @@ #include "opt_sdl.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.43 2011/12/26 12:39:20 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.44 2011/12/26 21:06:42 jmcneill Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -67,6 +67,8 @@ char *usermode_root_image_path = NULL; static char usermode_tap_devicebuf[PATH_MAX] = ""; char *usermode_tap_device = NULL; char *usermode_tap_eaddr = NULL; +static char usermode_audio_devicebuf[PATH_MAX] = ""; +char *usermode_audio_device = NULL; void main(int argc, char *argv[]); void usermode_reboot(void); @@ -116,6 +118,19 @@ main(int argc, char *argv[]) "%s", tap); usermode_tap_device = usermode_tap_devicebuf; usermode_tap_eaddr = mac; + } else if (strncmp(argv[i], "audio=", + strlen("audio=")) == 0) { + char *audio = argv[i] + strlen("audio="); + if (*audio != '/') + snprintf(usermode_audio_devicebuf, + sizeof(usermode_audio_devicebuf), + "/dev/%s", audio); + else + snprintf(usermode_audio_devicebuf, + sizeof(usermode_audio_devicebuf), + "%s", audio); + usermode_audio_device = + usermode_audio_devicebuf; } else { usermode_root_image_path = argv[i]; } diff --git a/sys/arch/usermode/usermode/thunk.c b/sys/arch/usermode/usermode/thunk.c index 8dea2ba1bb4..f5e9ebb4948 100644 --- a/sys/arch/usermode/usermode/thunk.c +++ b/sys/arch/usermode/usermode/thunk.c @@ -1,4 +1,4 @@ -/* $NetBSD: thunk.c,v 1.53 2011/12/26 14:50:27 jmcneill Exp $ */ +/* $NetBSD: thunk.c,v 1.54 2011/12/26 21:06:42 jmcneill Exp $ */ /*- * Copyright (c) 2011 Jared D. McNeill <jmcneill@invisible.ca> @@ -28,7 +28,7 @@ #include <sys/cdefs.h> #ifdef __NetBSD__ -__RCSID("$NetBSD: thunk.c,v 1.53 2011/12/26 14:50:27 jmcneill Exp $"); +__RCSID("$NetBSD: thunk.c,v 1.54 2011/12/26 21:06:42 jmcneill Exp $"); #endif #include <sys/types.h> @@ -37,6 +37,7 @@ __RCSID("$NetBSD: thunk.c,v 1.53 2011/12/26 14:50:27 jmcneill Exp $"); #include <sys/poll.h> #include <sys/sysctl.h> #include <sys/socket.h> +#include <sys/audioio.h> #include <machine/vmparam.h> #include <net/if.h> @@ -760,3 +761,86 @@ thunk_pollout_tap(int fd, int timeout) return poll(fds, __arraycount(fds), timeout); } + +int +thunk_audio_open(const char *path) +{ + return open(path, O_RDWR); +} + +int +thunk_audio_close(int fd) +{ + return close(fd); +} + +int +thunk_audio_drain(int fd) +{ + return ioctl(fd, AUDIO_DRAIN, 0); +} + +int +thunk_audio_config(int fd, const thunk_audio_config_t *pconf, + const thunk_audio_config_t *rconf) +{ + struct audio_info info; + int error; + + AUDIO_INITINFO(&info); + info.play.sample_rate = pconf->sample_rate; + info.play.channels = pconf->channels; + info.play.precision = pconf->precision; + info.play.encoding = AUDIO_ENCODING_SLINEAR_LE; + info.record.sample_rate = rconf->sample_rate; + info.record.channels = rconf->channels; + info.record.precision = rconf->precision; + info.record.encoding = AUDIO_ENCODING_SLINEAR_LE; + info.mode = AUMODE_PLAY_ALL|AUMODE_RECORD; + + error = ioctl(fd, AUDIO_SETINFO, &info); + if (error) + printf("AUDIO_SETINFO failed: %s\n", strerror(errno)); + + return error; +} + +int +thunk_audio_pollout(int fd) +{ + struct audio_info info; + int error; + + AUDIO_INITINFO(&info); + error = ioctl(fd, AUDIO_GETBUFINFO, &info); + if (error) + return -1; + + return info.play.buffer_size - info.play.seek; +} + +int +thunk_audio_pollin(int fd) +{ + struct audio_info info; + int error; + + AUDIO_INITINFO(&info); + error = ioctl(fd, AUDIO_GETBUFINFO, &info); + if (error) + return -1; + + return info.record.seek; +} + +int +thunk_audio_write(int fd, const void *buf, size_t buflen) +{ + return write(fd, buf, buflen); +} + +int +thunk_audio_read(int fd, void *buf, size_t buflen) +{ + return read(fd, buf, buflen); +} |
