aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--loopback/Kconfig12
-rw-r--r--loopback/Makefile6
-rw-r--r--loopback/loopback.c112
3 files changed, 130 insertions, 0 deletions
diff --git a/loopback/Kconfig b/loopback/Kconfig
new file mode 100644
index 0000000..6293c5c
--- /dev/null
+++ b/loopback/Kconfig
@@ -0,0 +1,12 @@
+#
+# AVIRT Loopback Audio Path
+#
+
+config AVIRT_LOOPBACKAP
+ tristate "LoopbackAP"
+ select SND_PCM
+ ---help---
+ Say Y here if you want to add loopback audio path.
+
+ To compile this driver as a module, choose M here: the
+ module will be called avirt_loopbackap.
diff --git a/loopback/Makefile b/loopback/Makefile
new file mode 100644
index 0000000..55da206
--- /dev/null
+++ b/loopback/Makefile
@@ -0,0 +1,6 @@
+obj-$(CONFIG_AVIRT_LOOPBACKAP) += avirt_loopbackap.o
+
+$(info $(src))
+avirt_loopbackap-objs := loopback.o
+ccflags-y += -Idrivers/staging/
+ccflags-y += -I$(src)/../../
diff --git a/loopback/loopback.c b/loopback/loopback.c
new file mode 100644
index 0000000..57f3c34
--- /dev/null
+++ b/loopback/loopback.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ALSA Virtual Soundcard
+ *
+ * loopback_audiopath.c - AVIRT sample Audio Path definition
+ *
+ * Copyright (C) 2010-2018 Fiberdyne Systems Pty Ltd
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <avirt/core.h>
+
+MODULE_AUTHOR("JOSHANNE <james.oshannessy@fiberdyne.com.au>");
+MODULE_AUTHOR("MFARRUGI <mark.farrugia@fiberdyne.com.au>");
+MODULE_DESCRIPTION("Sample Audio Path Module Interface");
+MODULE_LICENSE("GPL v2");
+
+static struct avirt_coreinfo *coreinfo;
+
+/*******************************************************************************
+ * Audio Path ALSA PCM Callbacks
+ ******************************************************************************/
+static int loopback_pcm_open(struct snd_pcm_substream *substream)
+{
+ return 0;
+}
+
+static int loopback_pcm_close(struct snd_pcm_substream *substream)
+{
+ return 0;
+}
+
+static snd_pcm_uframes_t
+ loopback_pcm_pointer(struct snd_pcm_substream *substream)
+{
+ return 0;
+}
+
+static int loopback_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int loopback_pcm_prepare(struct snd_pcm_substream *substream)
+{
+ return 0;
+}
+
+static struct snd_pcm_ops loopbackap_pcm_ops = {
+ .open = loopback_pcm_open,
+ .close = loopback_pcm_close,
+ .prepare = loopback_pcm_prepare,
+ .pointer = loopback_pcm_pointer,
+ .trigger = loopback_pcm_trigger,
+};
+
+/*******************************************************************************
+ * Loopback Audio Path AVIRT registration
+ ******************************************************************************/
+static struct snd_pcm_hardware loopbackap_hw = {
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .info = (SNDRV_PCM_INFO_INTERLEAVED // Channel interleaved audio
+ | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID),
+ .rates = SNDRV_PCM_RATE_48000,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .periods_min = 1,
+ .periods_max = 8,
+};
+
+static struct avirt_audiopath loopbackap_module = {
+ .name = "Loopback Audio Path",
+ .version = { 0, 0, 1 },
+ .value = 10,
+ .hw = &loopbackap_hw,
+ .pcm_ops = &loopbackap_pcm_ops,
+ .blocksize = 512,
+};
+
+static int __init loopback_init(void)
+{
+ int err = 0;
+
+ pr_info("init()\n");
+
+ err = avirt_register_audiopath(&loopbackap_module, &coreinfo);
+ if ((err < 0) || (!coreinfo)) {
+ pr_err("%s: coreinfo is NULL!\n", __func__);
+ return err;
+ }
+
+ return err;
+}
+
+static void __exit loopback_exit(void)
+{
+ pr_info("exit()\n");
+
+ avirt_deregister_audiopath(&loopbackap_module);
+}
+
+module_init(loopback_init);
+module_exit(loopback_exit);