diff --git a/aes67.c b/aes67.c index 40f2f85..0eeeabb 100644 --- a/aes67.c +++ b/aes67.c @@ -32,6 +32,9 @@ static struct platform_device *devices[SNDRV_CARDS]; #define AES67_NET_SUCCESS 0 +#define AES67_STREAM_RX 0 +#define AES67_STREAM_TX 1 + module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); module_param_array(id, charp, NULL, 0444); @@ -43,10 +46,18 @@ MODULE_PARM_DESC(pcm_devs, "PCM devices # (0-4) for dummy driver."); module_param_array(pcm_substreams, int, NULL, 0444); MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-128) for dummy driver."); -MODULE_AUTHOR("Preston Baxter "); +MODULE_AUTHOR("Preston Baxter "); MODULE_DESCRIPTION("AES67 Virtual Soundcard"); MODULE_LICENSE("GPL"); +/* Definition of stream abstraction*/ +struct aes67_stream { + bool running; + struct socket *socket; + spinlock_t rlock; + struct work_struct work; +}; + /* Definistion of AES67 Virtual SoundCard */ struct aes67 { /* ALSA Soundcard*/ @@ -56,15 +67,13 @@ struct aes67 { /* Linux Device */ struct device *dev; /* Socket */ - struct socket *socket; - /* Receiving Work Queue */ - spinlock_t rlock; - struct work_struct receive_work; - bool rx_on; + /* Streams */ + struct aes67_stream *rx; + struct aes67_stream *tx; }; -//Forward declarations +/* Forward declarations */ static int snd_aes67_new_pcm(struct aes67 *virtcard); static int work_start(void); @@ -72,6 +81,9 @@ static void work_stop(void); static void aes67_rx_net(struct work_struct *rwork); +static void aes67_stream_free(struct aes67_stream *stream); +static int aes67_stream_create(struct aes67_stream **stream, int direction); + /* Destructor */ static int snd_aes67_free(struct aes67 *virtcard) { @@ -79,10 +91,15 @@ static int snd_aes67_free(struct aes67 *virtcard) 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); + /* free streams */ + if (virtcard->rx) { + snd_printk(KERN_INFO "Freeing RX stream\n"); + aes67_stream_free(virtcard->rx); + } + + if (virtcard->tx) { + snd_printk(KERN_INFO "Freeing TX stream\n"); + aes67_stream_free(virtcard->tx); } kfree(virtcard); @@ -106,9 +123,6 @@ static int snd_aes67_create(struct snd_card *card, struct aes67 **rvirtcard) }; *rvirtcard = NULL; - - /* Setup Connection Handlers */ - /* allocate memory for virt card */ virtcard = kzalloc(sizeof(*virtcard), GFP_KERNEL); if (virtcard == NULL) @@ -116,8 +130,6 @@ static int snd_aes67_create(struct snd_card *card, struct aes67 **rvirtcard) virtcard->card = card; - /* COnnect to things */ - /* Build Sound Device */ err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, virtcard, &ops); if (err < 0) { @@ -126,32 +138,6 @@ 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; - } - - /* Spin lock for receiving */ - spin_lock_init(&virtcard->rlock); - /* Init work for card */ - INIT_WORK(&virtcard->receive_work, aes67_rx_net); - /* Add PCM */ err = snd_aes67_new_pcm(virtcard); if (err < 0) { @@ -221,8 +207,8 @@ static void work_stop(void) static int work_start(void) { - io_workqueue = alloc_workqueue("aes67_io", WQ_HIGHPRI | WQ_MEM_RECLAIM | - WQ_UNBOUND, 0); + io_workqueue = alloc_workqueue( + "aes67_io", WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 0); if (!io_workqueue) { snd_printk(KERN_ERR "Failed to start io workqueue struct\n"); @@ -236,7 +222,6 @@ static int work_start(void) 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; ssize_t msglen; @@ -250,10 +235,11 @@ static void aes67_rx_net(struct work_struct *work) return; } - msg.msg_flags = MSG_PEEK | MSG_DONTWAIT; + msg.msg_flags = MSG_WAITFORONE; snd_printk(KERN_INFO "Starting network receive loop\n"); for (;;) { + struct kvec iv; iv.iov_base = recv_buf; iv.iov_len = recv_buf_size; @@ -275,12 +261,13 @@ static void aes67_rx_net(struct work_struct *work) } if (msglen > 0) { - snd_printk(KERN_INFO "Received Buffer: %ph", recv_buf); - break; + snd_printk(KERN_INFO "Received Buffer: %s\n", recv_buf); + continue; } } /* Handle stream end */ snd_printk(KERN_INFO "Finished Receiving work queue\n"); + kfree(recv_buf); return; } @@ -460,6 +447,47 @@ static int snd_aes67_new_pcm(struct aes67 *virtcard) return 0; } +static int aes67_stream_create(struct aes67_stream **stream, int direction) +{ + struct aes67_stream *strm; + int err; + + strm = kzalloc(sizeof(*strm), GFP_KERNEL); + if (!strm) + return -ENOMEM; + + /* create socket */ + err = sock_create_kern(&init_net, PF_INET, SOCK_DGRAM, IPPROTO_UDP, + &strm->socket); + if (err < 0) { + snd_printk(KERN_ERR "Failed to create socket for stream\n"); + return err; + } + + struct sockaddr_in addr = { .sin_family = AF_INET, + .sin_port = htons(9375), + .sin_addr = { htonl(INADDR_LOOPBACK) } }; + + strm->socket->ops->bind(strm->socket, (struct sockaddr *)&addr, + sizeof(addr)); + if (err < 0) { + snd_printk(KERN_ERR + "Failed to bind socket for virtual soundcard\n"); + return err; + } + + /* Spin lock for receiving */ + spin_lock_init(&strm->rlock); + /* Init work for card */ + switch (direction) { + case AES67_STREAM_RX: + INIT_WORK(&strm->work, aes67_rx_net); + break; + default: + snd_printk(KERN_WARNING "Unimplemented Direction\n"); + } +} + /* Power Methods */ static int snd_aes67_suspend(struct device *pdev) {