socsvn commit: r306995 - soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve

iateaca at FreeBSD.org iateaca at FreeBSD.org
Sat Jul 30 20:37:04 UTC 2016


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, &params);
+	if (err)
+		return -1;
+
+	DPRINTF("rate: %d, channels: %d, format: 0x%x\n", params.rate, params.channels, params.format);
+
+	return audio_set_params(aud, &params);
+}
+
+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, &params);
+	if (err)
+		return -1;
+
+	DPRINTF("rate: %d, channels: %d, format: 0x%x\n", params.rate, params.channels, params.format);
+
+	return audio_set_params(aud, &params);
+}
+
+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, &params);
-	if (err)
-		return -1;
-
-	DPRINTF("rate: %d, channels: %d, format: 0x%x\n", params.rate, params.channels, params.format);
-
-	return audio_set_params(aud, &params);
-}
-
 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);


More information about the svn-soc-all mailing list