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