starting restructure with stream abstraction
This commit is contained in:
parent
c725e2bb94
commit
74361b9d89
124
aes67.c
124
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 <preston@preston-baxter.xom>");
|
||||
MODULE_AUTHOR("Preston Baxter <preston@preston-baxter.com>");
|
||||
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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue