1 #include <linux/cdev.h>
2 #include <linux/device.h>
4 #include <linux/list.h>
5 #include <linux/kernel.h>
6 #include <linux/module.h>
7 #include <linux/slab.h>
8 #include <linux/signal.h>
9 #include <linux/sched.h>
10 #include <linux/poll.h>
12 #include <linux/tapi/tapi.h>
13 #include <linux/tapi/tapi-ioctl.h>
16 struct tapi_stream_file
{
17 struct tapi_device
*tdev
;
18 struct tapi_stream
*stream
;
21 static inline struct tapi_device
*inode_to_tdev(struct inode
*inode
)
23 return container_of(inode
->i_cdev
, struct tapi_char_device
, cdev
)->tdev
;
26 static int tapi_stream_open(struct inode
*inode
, struct file
*file
)
29 struct tapi_device
*tdev
= inode_to_tdev(inode
);
30 struct tapi_stream_file
*stream
;
32 get_device(&tdev
->dev
);
34 stream
= kzalloc(sizeof(*stream
), GFP_KERNEL
);
40 stream
->stream
= tapi_stream_alloc(tdev
);
41 if (IS_ERR(stream
->stream
)) {
42 ret
= PTR_ERR(stream
->stream
);
47 init_waitqueue_head(&stream
->stream
->recv_wait
);
48 skb_queue_head_init(&stream
->stream
->recv_queue
);
50 file
->private_data
= stream
;
57 put_device(&tdev
->dev
);
61 static int tapi_stream_release(struct inode
*inode
, struct file
*file
)
63 struct tapi_stream_file
*stream
= file
->private_data
;
66 tapi_stream_free(stream
->tdev
, stream
->stream
);
67 put_device(&stream
->tdev
->dev
);
74 static long tapi_stream_ioctl(struct file
*file
, unsigned int cmd
,
78 struct tapi_stream_file
*stream
= file
->private_data
;
79 struct tapi_device
*tdev
= stream
->tdev
;
82 case TAPI_STREAM_IOCTL_GET_ENDPOINT
:
83 ret
= stream
->stream
->ep
.id
;
85 case TAPI_STREAM_IOCTL_CONFIGURE
:
87 case TAPI_STREAM_IOCTL_START
:
88 ret
= tapi_stream_start(tdev
, stream
->stream
);
90 case TAPI_STREAM_IOCTL_STOP
:
91 ret
= tapi_stream_stop(tdev
, stream
->stream
);
101 static unsigned int tapi_stream_poll(struct file
*file
, struct poll_table_struct
*wait
)
103 struct tapi_stream_file
*stream
= file
->private_data
;
106 poll_wait(file
, &stream
->stream
->recv_wait
, wait
);
110 if (!skb_queue_empty(&stream
->stream
->recv_queue
))
116 static ssize_t
tapi_stream_read(struct file
*file
, char __user
*buffer
,
117 size_t count
, loff_t
*offset
)
119 struct tapi_stream_file
*stream
= file
->private_data
;
122 skb
= skb_dequeue(&stream
->stream
->recv_queue
);
124 if (file
->f_flags
& O_NONBLOCK
)
128 interruptible_sleep_on(&stream
->stream
->recv_wait
);
129 skb
= skb_dequeue(&stream
->stream
->recv_queue
);
130 } while (skb
== NULL
&& !signal_pending(current
));
133 return -ERESTARTNOHAND
;
136 if (skb
->len
> count
) {
137 skb_queue_head(&stream
->stream
->recv_queue
, skb
);
141 if (copy_to_user(buffer
, skb
->data
, skb
->len
)) {
142 skb_queue_head(&stream
->stream
->recv_queue
, skb
);
153 static ssize_t
tapi_stream_write(struct file
*file
, const char __user
*buffer
,
154 size_t count
, loff_t
*ppos
)
156 struct tapi_stream_file
*stream
= file
->private_data
;
157 struct tapi_device
*tdev
= stream
->tdev
;
163 skb
= alloc_skb(count
, GFP_USER
);
167 if (copy_from_user(skb_put(skb
, count
), buffer
, count
)) {
172 tdev
->ops
->stream_send(tdev
, stream
->stream
, skb
);
177 static const struct file_operations tapi_stream_file_ops
= {
178 .owner
= THIS_MODULE
,
179 .read
= tapi_stream_read
,
180 .write
= tapi_stream_write
,
181 .open
= tapi_stream_open
,
182 .release
= tapi_stream_release
,
183 .poll
= tapi_stream_poll
,
184 .unlocked_ioctl
= tapi_stream_ioctl
,
187 int tapi_register_stream_device(struct tapi_device
* tdev
)
189 dev_set_name(&tdev
->stream_dev
.dev
, "tapi%uS", tdev
->id
);
190 return tapi_char_device_register(tdev
, &tdev
->stream_dev
, &tapi_stream_file_ops
);
193 int tapi_stream_recv(struct tapi_device
*tdev
, struct tapi_stream
* stream
,
196 skb_queue_tail(&stream
->recv_queue
, skb
);
197 wake_up(&stream
->recv_wait
);
201 EXPORT_SYMBOL_GPL(tapi_stream_recv
);