Date: Sat, 30 Jul 2016 20:37:02 GMT From: iateaca@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r306995 - soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve Message-ID: <201607302037.u6UKb2MT041822@socsvn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: iateaca Date: Sat Jul 30 20:37:01 2016 New Revision: 306995 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=306995 Log: implement audio_record - records samples from the sound device using blocking operations add suport for input stream in hda_codec (implement hda_codec_audio_input_nid, hda_codec_audio_input_do_transfer, hda_codec_audio_input_do_setup) if hda_transfer is called with stream=0 return error(it means the stream has been stopped) M bhyve/audio.c M bhyve/audio.h M bhyve/hda_codec.c M bhyve/pci_hda.c Modified: soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.c soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.h soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/hda_codec.c soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c Modified: soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.c ============================================================================== --- soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.c Sat Jul 30 19:03:32 2016 (r306994) +++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.c Sat Jul 30 20:37:01 2016 (r306995) @@ -161,3 +161,36 @@ return 0; } +/* + * audio_record - records samples from the sound device using blocking operations + * @aud - the audio player used to capture the samples + * @buf - the buffer to receive the samples + * @count - the number of bytes to capture in buffer + * Returns -1 on error and 0 on success + */ +int audio_record(struct audio *aud, void *buf, size_t count) +{ + int audio_fd = -1; + ssize_t len = 0, total = 0; + + assert(aud); + assert(!aud->dir); + assert(buf); + + audio_fd = aud->fd; + assert(audio_fd != -1); + + total = 0; + while (total < count) { + len = read(audio_fd, buf + total, count - total); + if (len == -1) { + DPRINTF("Fail to write to fd: %d, errno: %d\n", audio_fd, errno); + return -1; + } + + total += len; + } + + return 0; +} + Modified: soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.h ============================================================================== --- soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.h Sat Jul 30 19:03:32 2016 (r306994) +++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.h Sat Jul 30 20:37:01 2016 (r306995) @@ -46,4 +46,13 @@ */ int audio_playback(struct audio *aud, const void *buf, size_t count); +/* + * audio_record - records samples from the sound device using blocking operations + * @aud - the audio player used to capture the samples + * @buf - the buffer to receive the samples + * @count - the number of bytes to capture in buffer + * Returns -1 on error and 0 on success + */ +int audio_record(struct audio *aud, void *buf, size_t count); + #endif /* _AUDIO_EMUL_H_ */ Modified: soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/hda_codec.c ============================================================================== --- soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/hda_codec.c Sat Jul 30 19:03:32 2016 (r306994) +++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/hda_codec.c Sat Jul 30 20:37:01 2016 (r306995) @@ -171,6 +171,15 @@ hda_codec_audio_output_do_transfer(void *arg); static int hda_codec_audio_output_do_setup(void *arg); +static uint32_t +hda_codec_audio_input_nid(struct hda_codec_softc *sc, uint16_t verb, uint16_t payload); +static void +hda_codec_audio_input_do_transfer(void *arg); +static int +hda_codec_audio_input_do_setup(void *arg); + +static uint32_t +hda_codec_audio_inout_nid(struct hda_codec_stream *st, uint16_t verb, uint16_t payload); /* * HDA Codec global data @@ -267,6 +276,7 @@ static const verb_func_t hda_codec_verb_handlers[HDA_CODEC_NODES_COUNT] = { [HDA_CODEC_AUDIO_OUTPUT_NID] = hda_codec_audio_output_nid, + [HDA_CODEC_AUDIO_INPUT_NID] = hda_codec_audio_input_nid, }; /* @@ -295,6 +305,9 @@ sc->verb_handlers = hda_codec_verb_handlers; DPRINTF("HDA Codec nodes: %d\n", sc->no_nodes); + /* + * Initialize the Audio Output stream + */ st = &sc->streams[HDA_CODEC_STREAM_OUTPUT]; err = hda_audio_ctxt_init(&st->actx, "hda-audio-output", hda_codec_audio_output_do_transfer, hda_codec_audio_output_do_setup, sc); @@ -307,6 +320,21 @@ return -1; } + /* + * Initialize the Audio Input stream + */ + st = &sc->streams[HDA_CODEC_STREAM_INPUT]; + + err = hda_audio_ctxt_init(&st->actx, "hda-audio-input", hda_codec_audio_input_do_transfer, hda_codec_audio_input_do_setup, sc); + assert(!err); + + /* TODO Get the name of the sound device from the config string */ + st->aud = audio_init("/dev/dsp", 0); + if (!st->aud) { + DPRINTF("Fail to init the input audio player\n"); + return -1; + } + sc->hci = hci; hci->priv = sc; @@ -319,6 +347,7 @@ struct hda_ops *hops = NULL; struct hda_codec_softc *sc = NULL; struct hda_codec_stream *st = NULL; + int i; assert(hci); @@ -328,11 +357,13 @@ sc = (struct hda_codec_softc *)hci->priv; assert(sc); - st = &sc->streams[HDA_CODEC_STREAM_OUTPUT]; - st->left_gain = HDA_CODEC_AMP_NUMSTEPS; - st->right_gain = HDA_CODEC_AMP_NUMSTEPS; - st->left_mute = HDA_CODEC_SET_AMP_GAIN_MUTE_MUTE; - st->right_mute = HDA_CODEC_SET_AMP_GAIN_MUTE_MUTE; + for (i = 0; i < HDA_CODEC_STREAMS_COUNT; i++) { + st = &sc->streams[i]; + st->left_gain = HDA_CODEC_AMP_NUMSTEPS; + st->right_gain = HDA_CODEC_AMP_NUMSTEPS; + st->left_mute = HDA_CODEC_SET_AMP_GAIN_MUTE_MUTE; + st->right_mute = HDA_CODEC_SET_AMP_GAIN_MUTE_MUTE; + } DPRINTF("cad: 0x%x\n", hci->cad); @@ -420,28 +451,28 @@ struct hda_codec_softc *sc = NULL; struct hda_codec_stream *st = NULL; struct hda_audio_ctxt *actx = NULL; + int i; int err; assert(hci); + assert(stream); sc = (struct hda_codec_softc *)hci->priv; assert(sc); - /* TODO search the right stream - * For now, there is only one stream - */ - st = &sc->streams[HDA_CODEC_STREAM_OUTPUT]; + for (i = 0; i < HDA_CODEC_STREAMS_COUNT; i++) { + st = &sc->streams[i]; + if (st->stream == stream) + break; + } DPRINTF("run: %d, stream: 0x%x, st->stream: 0x%x dir: %d\n", run, stream, st->stream, dir); - if (!st->stream) { - DPRINTF("Stream not set\n"); + if (stream != st->stream) { + DPRINTF("Stream not found\n"); return 0; } - if (stream != st->stream) - return -1; - actx = &st->actx; if (run) @@ -504,15 +535,132 @@ static uint32_t hda_codec_audio_output_nid(struct hda_codec_softc *sc, uint16_t verb, uint16_t payload) { + struct hda_codec_stream *st = &sc->streams[HDA_CODEC_STREAM_OUTPUT]; + int res; + + res = hda_codec_audio_inout_nid(st, verb, payload); + + return res; +} + +static void +hda_codec_audio_output_do_transfer(void *arg) +{ + struct hda_codec_softc *sc = (struct hda_codec_softc *)arg; + struct hda_codec_inst *hci = NULL; + struct hda_ops *hops = NULL; + struct hda_codec_stream *st = NULL; + struct audio *aud = NULL; + int err; + + hci = sc->hci; + assert(hci); + + hops = hci->hops; + assert(hops); + + st = &sc->streams[HDA_CODEC_STREAM_OUTPUT]; + aud = st->aud; + + err = hops->transfer(hci, st->stream, 1, st->buf, sizeof(st->buf)); + if (err) + return; + + err = audio_playback(aud, st->buf, sizeof(st->buf)); + assert(!err); + + return; +} + +static int +hda_codec_audio_output_do_setup(void *arg) +{ + struct hda_codec_softc *sc = (struct hda_codec_softc *)arg; + struct hda_codec_stream *st = NULL; + struct audio *aud = NULL; + struct audio_params params; + int err; + + st = &sc->streams[HDA_CODEC_STREAM_OUTPUT]; + aud = st->aud; + + err = hda_codec_parse_format(st->fmt, ¶ms); + if (err) + return -1; + + DPRINTF("rate: %d, channels: %d, format: 0x%x\n", params.rate, params.channels, params.format); + + return audio_set_params(aud, ¶ms); +} + +static uint32_t +hda_codec_audio_input_nid(struct hda_codec_softc *sc, uint16_t verb, uint16_t payload) +{ + struct hda_codec_stream *st = &sc->streams[HDA_CODEC_STREAM_INPUT]; + int res; + + res = hda_codec_audio_inout_nid(st, verb, payload); + + return res; +} + +static void +hda_codec_audio_input_do_transfer(void *arg) +{ + struct hda_codec_softc *sc = (struct hda_codec_softc *)arg; + struct hda_codec_inst *hci = NULL; + struct hda_ops *hops = NULL; + struct hda_codec_stream *st = NULL; + struct audio *aud = NULL; + int err; + + hci = sc->hci; + assert(hci); + + hops = hci->hops; + assert(hops); + + st = &sc->streams[HDA_CODEC_STREAM_INPUT]; + aud = st->aud; + + err = audio_record(aud, st->buf, sizeof(st->buf)); + assert(!err); + + hops->transfer(hci, st->stream, 0, st->buf, sizeof(st->buf)); + + return; +} + +static int +hda_codec_audio_input_do_setup(void *arg) +{ + struct hda_codec_softc *sc = (struct hda_codec_softc *)arg; struct hda_codec_stream *st = NULL; + struct audio *aud = NULL; + struct audio_params params; + int err; + + st = &sc->streams[HDA_CODEC_STREAM_INPUT]; + aud = st->aud; + + err = hda_codec_parse_format(st->fmt, ¶ms); + if (err) + return -1; + + DPRINTF("rate: %d, channels: %d, format: 0x%x\n", params.rate, params.channels, params.format); + + return audio_set_params(aud, ¶ms); +} + +static uint32_t +hda_codec_audio_inout_nid(struct hda_codec_stream *st, uint16_t verb, uint16_t payload) +{ uint32_t res = 0; uint8_t mute = 0; uint8_t gain = 0; DPRINTF("verb: 0x%x, payload, 0x%x\n", verb, payload); - st = &sc->streams[HDA_CODEC_STREAM_OUTPUT]; - switch (verb) { case HDA_CMD_VERB_GET_CONV_FMT: res = st->fmt; @@ -521,7 +669,6 @@ st->fmt = payload; break; case HDA_CMD_VERB_GET_AMP_GAIN_MUTE: - assert(payload & HDA_CMD_GET_AMP_GAIN_MUTE_OUTPUT); if (payload & HDA_CMD_GET_AMP_GAIN_MUTE_LEFT) { res = st->left_gain | st->left_mute; DPRINTF("GET_AMP_GAIN_MUTE_LEFT: 0x%x\n", res); @@ -531,8 +678,6 @@ } break; case HDA_CMD_VERB_SET_AMP_GAIN_MUTE: - assert(payload & HDA_CMD_SET_AMP_GAIN_MUTE_OUTPUT); - mute = payload & HDA_CODEC_SET_AMP_GAIN_MUTE_MUTE; gain = payload & HDA_CODEC_SET_AMP_GAIN_MUTE_GAIN_MASK; @@ -566,56 +711,6 @@ return res; } -static void -hda_codec_audio_output_do_transfer(void *arg) -{ - struct hda_codec_softc *sc = (struct hda_codec_softc *)arg; - struct hda_codec_inst *hci = NULL; - struct hda_ops *hops = NULL; - struct hda_codec_stream *st = NULL; - struct audio *aud = NULL; - int err; - - hci = sc->hci; - assert(hci); - - hops = hci->hops; - assert(hops); - - st = &sc->streams[HDA_CODEC_STREAM_OUTPUT]; - aud = st->aud; - - err = hops->transfer(hci, st->stream, 1, st->buf, sizeof(st->buf)); - if (err) - return; - - err = audio_playback(aud, st->buf, sizeof(st->buf)); - assert(!err); - - return; -} - -static int -hda_codec_audio_output_do_setup(void *arg) -{ - struct hda_codec_softc *sc = (struct hda_codec_softc *)arg; - struct hda_codec_stream *st = NULL; - struct audio *aud = NULL; - struct audio_params params; - int err; - - st = &sc->streams[HDA_CODEC_STREAM_OUTPUT]; - aud = st->aud; - - err = hda_codec_parse_format(st->fmt, ¶ms); - if (err) - return -1; - - DPRINTF("rate: %d, channels: %d, format: 0x%x\n", params.rate, params.channels, params.format); - - return audio_set_params(aud, ¶ms); -} - struct hda_codec_class hda_codec = { .name = "hda_codec", .init = hda_codec_init, Modified: soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c ============================================================================== --- soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c Sat Jul 30 19:03:32 2016 (r306994) +++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c Sat Jul 30 20:37:01 2016 (r306995) @@ -1112,6 +1112,11 @@ assert(buf); assert(!(count % HDA_DMA_ACCESS_LEN)); + if (!stream) { + DPRINTF("Invalid stream\n"); + return -1; + } + sc = hci->hda; assert(stream < HDA_STREAM_TAGS_CNT);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201607302037.u6UKb2MT041822>