Compare commits
2 Commits
941cae8042
...
7d45dde84e
Author | SHA1 | Date |
---|---|---|
Preston Baxter | 7d45dde84e | |
Preston Baxter | 69e26d6a55 |
|
@ -6,3 +6,4 @@
|
|||
*.mod.c
|
||||
*.symvers
|
||||
*.cache
|
||||
*.o.d
|
||||
|
|
2
Makefile
2
Makefile
|
@ -3,7 +3,7 @@ obj-m += aes67.o
|
|||
CC=gcc
|
||||
KERN_DIR=/lib/modules/$(shell uname -r)/build/
|
||||
|
||||
host:
|
||||
default:
|
||||
$(MAKE) -C $(KERN_DIR) M=$$PWD modules
|
||||
clean:
|
||||
make -C $(KERN_DIR) M=$(PWD) clean
|
||||
|
|
95
aes67.c
95
aes67.c
|
@ -4,9 +4,14 @@
|
|||
*
|
||||
* */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/socket.h>
|
||||
#include <linux/net.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <net/net_namespace.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/initval.h>
|
||||
|
@ -21,6 +26,8 @@ static struct platform_device *devices[SNDRV_CARDS];
|
|||
|
||||
#define CARD_NAME "AES67 Virtual Soundcard"
|
||||
|
||||
#define AES67_NET_SUCCESS 0
|
||||
|
||||
module_param_array(index, int, NULL, 0444);
|
||||
MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
|
||||
module_param_array(id, charp, NULL, 0444);
|
||||
|
@ -38,9 +45,17 @@ MODULE_LICENSE("GPL");
|
|||
|
||||
/* Definistion of AES67 Virtual SoundCard */
|
||||
struct aes67 {
|
||||
/* ALSA Soundcard*/
|
||||
struct snd_card *card;
|
||||
/* PCM Device Soundcard*/
|
||||
struct snd_pcm *pcm;
|
||||
/* Linux Device */
|
||||
struct device *dev;
|
||||
/* Socket */
|
||||
struct socket *socket;
|
||||
|
||||
/* Receiving Work Queue */
|
||||
struct work_struct receive_work;
|
||||
};
|
||||
|
||||
//Forward declarations
|
||||
|
@ -49,7 +64,16 @@ static int snd_aes67_new_pcm(struct aes67 *virtcard);
|
|||
/* Destructor */
|
||||
static int snd_aes67_free(struct aes67 *virtcard)
|
||||
{
|
||||
/* free card */
|
||||
snd_printk(KERN_INFO "Freeing Soundcard\n");
|
||||
snd_card_free(virtcard->card);
|
||||
|
||||
/* free socket */
|
||||
if (virtcard->socket) {
|
||||
snd_printk(KERN_INFO "Freeing Socket\n");
|
||||
sock_release(virtcard->socket);
|
||||
}
|
||||
|
||||
kfree(virtcard);
|
||||
return 0;
|
||||
}
|
||||
|
@ -91,6 +115,27 @@ static int snd_aes67_create(struct snd_card *card, struct aes67 **rvirtcard)
|
|||
return err;
|
||||
}
|
||||
|
||||
/* create socket */
|
||||
err = sock_create_kern(&init_net, PF_INET, SOCK_DGRAM, IPPROTO_UDP,
|
||||
&virtcard->socket);
|
||||
if (err < 0) {
|
||||
snd_printk(KERN_ERR
|
||||
"Failed to create socket for virtual soundcard\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
struct sockaddr_in addr = { .sin_family = AF_INET,
|
||||
.sin_port = htons(9375),
|
||||
.sin_addr = { htonl(INADDR_LOOPBACK) } };
|
||||
|
||||
virtcard->socket->ops->bind(virtcard->socket, (struct sockaddr *)&addr,
|
||||
sizeof(addr));
|
||||
if (err < 0) {
|
||||
snd_printk(KERN_ERR
|
||||
"Failed to bind socket for virtual soundcard\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Add PCM */
|
||||
err = snd_aes67_new_pcm(virtcard);
|
||||
if (err < 0) {
|
||||
|
@ -99,7 +144,6 @@ static int snd_aes67_create(struct snd_card *card, struct aes67 **rvirtcard)
|
|||
return err;
|
||||
}
|
||||
|
||||
|
||||
snd_printk(KERN_INFO "Successfully created AES67\n");
|
||||
*rvirtcard = virtcard;
|
||||
return 0;
|
||||
|
@ -150,6 +194,39 @@ error:
|
|||
snd_card_free(card);
|
||||
return err;
|
||||
}
|
||||
/* Network functions */
|
||||
|
||||
static void aes67_rx_net(struct work_struct *work)
|
||||
{
|
||||
struct aes67 *virtcard = container_of(work, struct aes67, receive_work);
|
||||
struct kvec iv;
|
||||
struct msghdr msg = {};
|
||||
size_t recv_buf_size = 4096;
|
||||
int ret, buflen;
|
||||
void *recv_buf;
|
||||
/* Read lock socket */
|
||||
|
||||
/* Loop Receive */
|
||||
recv_buf = kzalloc(recv_buf_size, GFP_KERNEL);
|
||||
if (!recv_buf) {
|
||||
snd_printk(KERN_ERR
|
||||
"Failed to allocate network receive buffer\n");
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
iv.iov_base = recv_buf;
|
||||
iv.iov_len = recv_buf_size;
|
||||
|
||||
msglen = kernel_recvmsg(virtcard->socket, &msg, &iv, 1, iv.iov_len, MSG_DONTWAIT);
|
||||
|
||||
} while (ret == AES67_NET_SUCCESS);
|
||||
|
||||
/* Handle stream end */
|
||||
snd_printk(KERN_INFO "Finished Receiving work queue\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* PCM Shenaniagians */
|
||||
/* Playback definition */
|
||||
|
@ -243,9 +320,13 @@ static int snd_aes67_pcm_prepare(struct snd_pcm_substream *substream)
|
|||
|
||||
static int snd_aes67_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||
{
|
||||
struct aes67 *chip = snd_pcm_substream_chip(substream);
|
||||
|
||||
int err;
|
||||
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
/* do something to start the PCM engine */
|
||||
INIT_WORK(&chip->receive_work, aes67_rx_net);
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
/* do something to stop the PCM engine */
|
||||
|
@ -303,7 +384,8 @@ static int snd_aes67_new_pcm(struct aes67 *virtcard)
|
|||
snd_printk(KERN_INFO "Initializing PCM for Virtual Soundcard");
|
||||
err = snd_pcm_new(virtcard->card, CARD_NAME, 0, 1, 1, &pcm);
|
||||
if (err < 0) {
|
||||
snd_printk(KERN_INFO "Failed initializing PCM for Virtual Soundcard");
|
||||
snd_printk(KERN_INFO
|
||||
"Failed initializing PCM for Virtual Soundcard");
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -319,8 +401,8 @@ static int snd_aes67_new_pcm(struct aes67 *virtcard)
|
|||
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_aes67_capture_ops);
|
||||
/*Da buffers*/
|
||||
snd_printk(KERN_INFO "Settig PCM managed buffer");
|
||||
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DEV_LOWLEVEL, virtcard->dev, 64 * 1024,
|
||||
64 * 1024);
|
||||
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DEV_LOWLEVEL, virtcard->dev,
|
||||
64 * 1024, 64 * 1024);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -392,5 +474,4 @@ static void __exit alsa_card_aes67_exit(void)
|
|||
platform_driver_unregister(&snd_aes67_driver);
|
||||
}
|
||||
|
||||
module_init(alsa_card_aes67_init)
|
||||
module_exit(alsa_card_aes67_exit)
|
||||
module_init(alsa_card_aes67_init) module_exit(alsa_card_aes67_exit)
|
||||
|
|
Loading…
Reference in New Issue