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

iateaca at FreeBSD.org iateaca at FreeBSD.org
Sat Jun 25 18:28:24 UTC 2016


Author: iateaca
Date: Sat Jun 25 18:28:22 2016
New Revision: 305547
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=305547

Log:
  implement the Audio Player used to play samples to the sound device (/dev/dsp)
  the public interface provides 3 functions: audio_init, audio_set_params and audio_playback
  
  A    audio.c
  A    audio.h

Added:
  soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.c
  soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.h

Added: soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.c	Sat Jun 25 18:28:22 2016	(r305547)
@@ -0,0 +1,163 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "audio.h"
+#include "pci_hda.h"
+
+/*
+ * Audio Player internal data structures
+ */
+
+struct audio {
+	int fd;
+	uint8_t dir;
+	char dev_name[64];
+};
+
+/*
+ * Audio Player module function definitions
+ */
+
+/*
+ * audio_init - initialize an instance of audio player
+ * @dev_name - the backend sound device used to play / capture
+ * @dir - dir = 1 for write mode, dir = 0 for read mode
+ */
+struct audio *audio_init(const char *dev_name, uint8_t dir)
+{
+	struct audio *aud = NULL;
+
+	assert(dev_name);
+
+	aud = calloc(1, sizeof(*aud));
+	if (!aud)
+		return NULL;
+
+	if (strlen(dev_name) < sizeof(aud->dev_name))
+		memcpy(aud->dev_name, dev_name, strlen(dev_name) + 1);
+	else {
+		DPRINTF("dev_name too big\n");
+		free(aud);
+		return NULL;
+	}
+
+	aud->fd = -1;
+	aud->dir = dir;
+
+	return aud;
+}
+
+/*
+ * audio_set_params - reset the sound device and set the audio params
+ * @aud - the audio player to be configured
+ * @params - the audio parameters to be set
+ */
+int audio_set_params(struct audio *aud, struct audio_params *params)
+{
+	int audio_fd = -1;
+	int format, channels, rate;
+	int err;
+
+	assert(aud);
+	assert(params);
+
+	/* Close the device if was opened before */
+	if (aud->fd != -1) {
+		err = close(aud->fd);
+		if (err == -1) {
+			DPRINTF("Fail to close fd: %d, errno: %d\n", aud->fd, errno);
+			return -1;
+		}
+	}
+
+	audio_fd = open(aud->dev_name, aud->dir ? O_WRONLY : O_RDONLY, 0);
+	if (audio_fd == -1) {
+		DPRINTF("Fail to open dev: %s, errno: %d\n", aud->dev_name, errno);
+		return -1;
+	}
+
+	aud->fd = audio_fd;
+
+	/* Set the Format (Bits per Sample) */
+	format = params->format;
+	err = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format);
+	if (err == -1) {
+		DPRINTF("Fail to set fmt: 0x%x errno: %d\n", params->format, errno);
+		return -1;
+	}
+
+	/* The device does not support the requested audio format */
+	if (format != params->format) {
+		DPRINTF("Mismatch format: 0x%x params->format: 0x%x\n", format, params->format);
+		return -1;
+	}
+
+	/* Set the Number of Channels */
+	channels = params->channels;
+	err = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &channels);
+	if (err == -1) {
+		DPRINTF("Fail to set channels: %d errno: %d\n", params->channels, errno);
+		return -1;
+	}
+
+	/* The device does not support the requested no. of channels */
+	if (channels != params->channels) {
+		DPRINTF("Mismatch channels: %d params->channels: %d\n", channels, params->channels);
+		return -1;
+	}
+
+	/* Set the Sample Rate / Speed */
+	rate = params->rate;
+	err = ioctl(audio_fd, SNDCTL_DSP_SPEED, &rate);
+	if (err == -1) {
+		DPRINTF("Fail to set speed: %d errno: %d\n", params->rate, errno);
+		return -1;
+	}
+
+	/* The device does not support the requested rate / speed */
+	if (rate != params->rate) {
+		DPRINTF("Mismatch rate: %d params->rate: %d\n", rate, params->rate);
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * audio_playback - plays samples to the sound device using blocking operations
+ * @aud - the audio player used to play the samples
+ * @buf - the buffer containing the samples
+ * @count - the number of bytes in buffer
+ */
+ssize_t audio_playback(struct audio *aud, const 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 = write(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;
+}
+

Added: soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.h	Sat Jun 25 18:28:22 2016	(r305547)
@@ -0,0 +1,46 @@
+
+#ifndef _AUDIO_EMUL_H_ 
+#define _AUDIO_EMUL_H_
+
+#include <sys/types.h>
+#include <sys/soundcard.h>
+
+/*
+ * Audio Player data structures
+ */
+
+struct audio;
+
+struct audio_params {
+	int format;
+	int channels;
+	int rate;
+};
+
+/*
+ * Audio Player API
+ */
+
+/*
+ * audio_init - initialize an instance of audio player
+ * @dev_name - the backend sound device used to play / capture
+ * @dir - dir = 1 for write mode, dir = 0 for read mode
+ */
+struct audio *audio_init(const char *dev_name, uint8_t dir);
+
+/*
+ * audio_set_params - reset the sound device and set the audio params
+ * @aud - the audio player to be configured
+ * @params - the audio parameters to be set
+ */
+int audio_set_params(struct audio *aud, struct audio_params *params);
+
+/*
+ * audio_playback - plays samples to the sound device using blocking operations
+ * @aud - the audio player used to play the samples
+ * @buf - the buffer containing the samples
+ * @count - the number of bytes in buffer
+ */
+ssize_t audio_playback(struct audio *aud, const void *buf, size_t count);
+
+#endif  /* _AUDIO_EMUL_H_ */


More information about the svn-soc-all mailing list