1 | // SPDX-License-Identifier: LGPL-2.1-or-later |
2 | /* |
3 | * dmxdev.c - DVB demultiplexer device |
4 | * |
5 | * Copyright (C) 2000 Ralph Metzler & Marcus Metzler |
6 | * for convergence integrated media GmbH |
7 | */ |
8 | |
9 | #define pr_fmt(fmt) "dmxdev: " fmt |
10 | |
11 | #include <linux/sched.h> |
12 | #include <linux/spinlock.h> |
13 | #include <linux/slab.h> |
14 | #include <linux/vmalloc.h> |
15 | #include <linux/module.h> |
16 | #include <linux/poll.h> |
17 | #include <linux/ioctl.h> |
18 | #include <linux/wait.h> |
19 | #include <linux/uaccess.h> |
20 | #include <media/dmxdev.h> |
21 | #include <media/dvb_vb2.h> |
22 | |
23 | static int debug; |
24 | |
25 | module_param(debug, int, 0644); |
26 | MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)." ); |
27 | |
28 | #define dprintk(fmt, arg...) do { \ |
29 | if (debug) \ |
30 | printk(KERN_DEBUG pr_fmt("%s: " fmt), \ |
31 | __func__, ##arg); \ |
32 | } while (0) |
33 | |
34 | static int dvb_dmxdev_buffer_write(struct dvb_ringbuffer *buf, |
35 | const u8 *src, size_t len) |
36 | { |
37 | ssize_t free; |
38 | |
39 | if (!len) |
40 | return 0; |
41 | if (!buf->data) |
42 | return 0; |
43 | |
44 | free = dvb_ringbuffer_free(rbuf: buf); |
45 | if (len > free) { |
46 | dprintk("buffer overflow\n" ); |
47 | return -EOVERFLOW; |
48 | } |
49 | |
50 | return dvb_ringbuffer_write(rbuf: buf, buf: src, len); |
51 | } |
52 | |
53 | static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src, |
54 | int non_blocking, char __user *buf, |
55 | size_t count, loff_t *ppos) |
56 | { |
57 | size_t todo; |
58 | ssize_t avail; |
59 | ssize_t ret = 0; |
60 | |
61 | if (!src->data) |
62 | return 0; |
63 | |
64 | if (src->error) { |
65 | ret = src->error; |
66 | dvb_ringbuffer_flush(rbuf: src); |
67 | return ret; |
68 | } |
69 | |
70 | for (todo = count; todo > 0; todo -= ret) { |
71 | if (non_blocking && dvb_ringbuffer_empty(rbuf: src)) { |
72 | ret = -EWOULDBLOCK; |
73 | break; |
74 | } |
75 | |
76 | ret = wait_event_interruptible(src->queue, |
77 | !dvb_ringbuffer_empty(src) || |
78 | (src->error != 0)); |
79 | if (ret < 0) |
80 | break; |
81 | |
82 | if (src->error) { |
83 | ret = src->error; |
84 | dvb_ringbuffer_flush(rbuf: src); |
85 | break; |
86 | } |
87 | |
88 | avail = dvb_ringbuffer_avail(rbuf: src); |
89 | if (avail > todo) |
90 | avail = todo; |
91 | |
92 | ret = dvb_ringbuffer_read_user(rbuf: src, buf, len: avail); |
93 | if (ret < 0) |
94 | break; |
95 | |
96 | buf += ret; |
97 | } |
98 | |
99 | return (count - todo) ? (count - todo) : ret; |
100 | } |
101 | |
102 | static struct dmx_frontend *get_fe(struct dmx_demux *demux, int type) |
103 | { |
104 | struct list_head *head, *pos; |
105 | |
106 | head = demux->get_frontends(demux); |
107 | if (!head) |
108 | return NULL; |
109 | list_for_each(pos, head) |
110 | if (DMX_FE_ENTRY(pos)->source == type) |
111 | return DMX_FE_ENTRY(pos); |
112 | |
113 | return NULL; |
114 | } |
115 | |
116 | static int dvb_dvr_open(struct inode *inode, struct file *file) |
117 | { |
118 | struct dvb_device *dvbdev = file->private_data; |
119 | struct dmxdev *dmxdev = dvbdev->priv; |
120 | struct dmx_frontend *front; |
121 | bool need_ringbuffer = false; |
122 | |
123 | dprintk("%s\n" , __func__); |
124 | |
125 | if (mutex_lock_interruptible(&dmxdev->mutex)) |
126 | return -ERESTARTSYS; |
127 | |
128 | if (dmxdev->exit) { |
129 | mutex_unlock(lock: &dmxdev->mutex); |
130 | return -ENODEV; |
131 | } |
132 | |
133 | dmxdev->may_do_mmap = 0; |
134 | |
135 | /* |
136 | * The logic here is a little tricky due to the ifdef. |
137 | * |
138 | * The ringbuffer is used for both read and mmap. |
139 | * |
140 | * It is not needed, however, on two situations: |
141 | * - Write devices (access with O_WRONLY); |
142 | * - For duplex device nodes, opened with O_RDWR. |
143 | */ |
144 | |
145 | if ((file->f_flags & O_ACCMODE) == O_RDONLY) |
146 | need_ringbuffer = true; |
147 | else if ((file->f_flags & O_ACCMODE) == O_RDWR) { |
148 | if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) { |
149 | #ifdef CONFIG_DVB_MMAP |
150 | dmxdev->may_do_mmap = 1; |
151 | need_ringbuffer = true; |
152 | #else |
153 | mutex_unlock(&dmxdev->mutex); |
154 | return -EOPNOTSUPP; |
155 | #endif |
156 | } |
157 | } |
158 | |
159 | if (need_ringbuffer) { |
160 | void *mem; |
161 | |
162 | if (!dvbdev->readers) { |
163 | mutex_unlock(lock: &dmxdev->mutex); |
164 | return -EBUSY; |
165 | } |
166 | mem = vmalloc(DVR_BUFFER_SIZE); |
167 | if (!mem) { |
168 | mutex_unlock(lock: &dmxdev->mutex); |
169 | return -ENOMEM; |
170 | } |
171 | dvb_ringbuffer_init(rbuf: &dmxdev->dvr_buffer, data: mem, DVR_BUFFER_SIZE); |
172 | if (dmxdev->may_do_mmap) |
173 | dvb_vb2_init(ctx: &dmxdev->dvr_vb2_ctx, name: "dvr" , |
174 | non_blocking: file->f_flags & O_NONBLOCK); |
175 | dvbdev->readers--; |
176 | } |
177 | |
178 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) { |
179 | dmxdev->dvr_orig_fe = dmxdev->demux->frontend; |
180 | |
181 | if (!dmxdev->demux->write) { |
182 | mutex_unlock(lock: &dmxdev->mutex); |
183 | return -EOPNOTSUPP; |
184 | } |
185 | |
186 | front = get_fe(demux: dmxdev->demux, type: DMX_MEMORY_FE); |
187 | |
188 | if (!front) { |
189 | mutex_unlock(lock: &dmxdev->mutex); |
190 | return -EINVAL; |
191 | } |
192 | dmxdev->demux->disconnect_frontend(dmxdev->demux); |
193 | dmxdev->demux->connect_frontend(dmxdev->demux, front); |
194 | } |
195 | dvbdev->users++; |
196 | mutex_unlock(lock: &dmxdev->mutex); |
197 | return 0; |
198 | } |
199 | |
200 | static int dvb_dvr_release(struct inode *inode, struct file *file) |
201 | { |
202 | struct dvb_device *dvbdev = file->private_data; |
203 | struct dmxdev *dmxdev = dvbdev->priv; |
204 | |
205 | mutex_lock(&dmxdev->mutex); |
206 | |
207 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) { |
208 | dmxdev->demux->disconnect_frontend(dmxdev->demux); |
209 | dmxdev->demux->connect_frontend(dmxdev->demux, |
210 | dmxdev->dvr_orig_fe); |
211 | } |
212 | |
213 | if (((file->f_flags & O_ACCMODE) == O_RDONLY) || |
214 | dmxdev->may_do_mmap) { |
215 | if (dmxdev->may_do_mmap) { |
216 | if (dvb_vb2_is_streaming(ctx: &dmxdev->dvr_vb2_ctx)) |
217 | dvb_vb2_stream_off(ctx: &dmxdev->dvr_vb2_ctx); |
218 | dvb_vb2_release(ctx: &dmxdev->dvr_vb2_ctx); |
219 | } |
220 | dvbdev->readers++; |
221 | if (dmxdev->dvr_buffer.data) { |
222 | void *mem = dmxdev->dvr_buffer.data; |
223 | /*memory barrier*/ |
224 | mb(); |
225 | spin_lock_irq(lock: &dmxdev->lock); |
226 | dmxdev->dvr_buffer.data = NULL; |
227 | spin_unlock_irq(lock: &dmxdev->lock); |
228 | vfree(addr: mem); |
229 | } |
230 | } |
231 | /* TODO */ |
232 | dvbdev->users--; |
233 | if (dvbdev->users == 1 && dmxdev->exit == 1) { |
234 | mutex_unlock(lock: &dmxdev->mutex); |
235 | wake_up(&dvbdev->wait_queue); |
236 | } else |
237 | mutex_unlock(lock: &dmxdev->mutex); |
238 | |
239 | return 0; |
240 | } |
241 | |
242 | static ssize_t dvb_dvr_write(struct file *file, const char __user *buf, |
243 | size_t count, loff_t *ppos) |
244 | { |
245 | struct dvb_device *dvbdev = file->private_data; |
246 | struct dmxdev *dmxdev = dvbdev->priv; |
247 | int ret; |
248 | |
249 | if (!dmxdev->demux->write) |
250 | return -EOPNOTSUPP; |
251 | if ((file->f_flags & O_ACCMODE) != O_WRONLY) |
252 | return -EINVAL; |
253 | if (mutex_lock_interruptible(&dmxdev->mutex)) |
254 | return -ERESTARTSYS; |
255 | |
256 | if (dmxdev->exit) { |
257 | mutex_unlock(lock: &dmxdev->mutex); |
258 | return -ENODEV; |
259 | } |
260 | ret = dmxdev->demux->write(dmxdev->demux, buf, count); |
261 | mutex_unlock(lock: &dmxdev->mutex); |
262 | return ret; |
263 | } |
264 | |
265 | static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count, |
266 | loff_t *ppos) |
267 | { |
268 | struct dvb_device *dvbdev = file->private_data; |
269 | struct dmxdev *dmxdev = dvbdev->priv; |
270 | |
271 | if (dmxdev->exit) |
272 | return -ENODEV; |
273 | |
274 | return dvb_dmxdev_buffer_read(src: &dmxdev->dvr_buffer, |
275 | non_blocking: file->f_flags & O_NONBLOCK, |
276 | buf, count, ppos); |
277 | } |
278 | |
279 | static int dvb_dvr_set_buffer_size(struct dmxdev *dmxdev, |
280 | unsigned long size) |
281 | { |
282 | struct dvb_ringbuffer *buf = &dmxdev->dvr_buffer; |
283 | void *newmem; |
284 | void *oldmem; |
285 | |
286 | dprintk("%s\n" , __func__); |
287 | |
288 | if (buf->size == size) |
289 | return 0; |
290 | if (!size) |
291 | return -EINVAL; |
292 | |
293 | newmem = vmalloc(size); |
294 | if (!newmem) |
295 | return -ENOMEM; |
296 | |
297 | oldmem = buf->data; |
298 | |
299 | spin_lock_irq(lock: &dmxdev->lock); |
300 | buf->data = newmem; |
301 | buf->size = size; |
302 | |
303 | /* reset and not flush in case the buffer shrinks */ |
304 | dvb_ringbuffer_reset(rbuf: buf); |
305 | spin_unlock_irq(lock: &dmxdev->lock); |
306 | |
307 | vfree(addr: oldmem); |
308 | |
309 | return 0; |
310 | } |
311 | |
312 | static inline void dvb_dmxdev_filter_state_set(struct dmxdev_filter |
313 | *dmxdevfilter, int state) |
314 | { |
315 | spin_lock_irq(lock: &dmxdevfilter->dev->lock); |
316 | dmxdevfilter->state = state; |
317 | spin_unlock_irq(lock: &dmxdevfilter->dev->lock); |
318 | } |
319 | |
320 | static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter, |
321 | unsigned long size) |
322 | { |
323 | struct dvb_ringbuffer *buf = &dmxdevfilter->buffer; |
324 | void *newmem; |
325 | void *oldmem; |
326 | |
327 | if (buf->size == size) |
328 | return 0; |
329 | if (!size) |
330 | return -EINVAL; |
331 | if (dmxdevfilter->state >= DMXDEV_STATE_GO) |
332 | return -EBUSY; |
333 | |
334 | newmem = vmalloc(size); |
335 | if (!newmem) |
336 | return -ENOMEM; |
337 | |
338 | oldmem = buf->data; |
339 | |
340 | spin_lock_irq(lock: &dmxdevfilter->dev->lock); |
341 | buf->data = newmem; |
342 | buf->size = size; |
343 | |
344 | /* reset and not flush in case the buffer shrinks */ |
345 | dvb_ringbuffer_reset(rbuf: buf); |
346 | spin_unlock_irq(lock: &dmxdevfilter->dev->lock); |
347 | |
348 | vfree(addr: oldmem); |
349 | |
350 | return 0; |
351 | } |
352 | |
353 | static void dvb_dmxdev_filter_timeout(struct timer_list *t) |
354 | { |
355 | struct dmxdev_filter *dmxdevfilter = from_timer(dmxdevfilter, t, timer); |
356 | |
357 | dmxdevfilter->buffer.error = -ETIMEDOUT; |
358 | spin_lock_irq(lock: &dmxdevfilter->dev->lock); |
359 | dmxdevfilter->state = DMXDEV_STATE_TIMEDOUT; |
360 | spin_unlock_irq(lock: &dmxdevfilter->dev->lock); |
361 | wake_up(&dmxdevfilter->buffer.queue); |
362 | } |
363 | |
364 | static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter) |
365 | { |
366 | struct dmx_sct_filter_params *para = &dmxdevfilter->params.sec; |
367 | |
368 | del_timer(timer: &dmxdevfilter->timer); |
369 | if (para->timeout) { |
370 | dmxdevfilter->timer.expires = |
371 | jiffies + 1 + (HZ / 2 + HZ * para->timeout) / 1000; |
372 | add_timer(timer: &dmxdevfilter->timer); |
373 | } |
374 | } |
375 | |
376 | static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, |
377 | const u8 *buffer2, size_t buffer2_len, |
378 | struct dmx_section_filter *filter, |
379 | u32 *buffer_flags) |
380 | { |
381 | struct dmxdev_filter *dmxdevfilter = filter->priv; |
382 | int ret; |
383 | |
384 | if (!dvb_vb2_is_streaming(ctx: &dmxdevfilter->vb2_ctx) && |
385 | dmxdevfilter->buffer.error) { |
386 | wake_up(&dmxdevfilter->buffer.queue); |
387 | return 0; |
388 | } |
389 | spin_lock(lock: &dmxdevfilter->dev->lock); |
390 | if (dmxdevfilter->state != DMXDEV_STATE_GO) { |
391 | spin_unlock(lock: &dmxdevfilter->dev->lock); |
392 | return 0; |
393 | } |
394 | del_timer(timer: &dmxdevfilter->timer); |
395 | dprintk("section callback %*ph\n" , 6, buffer1); |
396 | if (dvb_vb2_is_streaming(ctx: &dmxdevfilter->vb2_ctx)) { |
397 | ret = dvb_vb2_fill_buffer(ctx: &dmxdevfilter->vb2_ctx, |
398 | src: buffer1, len: buffer1_len, |
399 | buffer_flags); |
400 | if (ret == buffer1_len) |
401 | ret = dvb_vb2_fill_buffer(ctx: &dmxdevfilter->vb2_ctx, |
402 | src: buffer2, len: buffer2_len, |
403 | buffer_flags); |
404 | } else { |
405 | ret = dvb_dmxdev_buffer_write(buf: &dmxdevfilter->buffer, |
406 | src: buffer1, len: buffer1_len); |
407 | if (ret == buffer1_len) { |
408 | ret = dvb_dmxdev_buffer_write(buf: &dmxdevfilter->buffer, |
409 | src: buffer2, len: buffer2_len); |
410 | } |
411 | } |
412 | if (ret < 0) |
413 | dmxdevfilter->buffer.error = ret; |
414 | if (dmxdevfilter->params.sec.flags & DMX_ONESHOT) |
415 | dmxdevfilter->state = DMXDEV_STATE_DONE; |
416 | spin_unlock(lock: &dmxdevfilter->dev->lock); |
417 | wake_up(&dmxdevfilter->buffer.queue); |
418 | return 0; |
419 | } |
420 | |
421 | static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, |
422 | const u8 *buffer2, size_t buffer2_len, |
423 | struct dmx_ts_feed *feed, |
424 | u32 *buffer_flags) |
425 | { |
426 | struct dmxdev_filter *dmxdevfilter = feed->priv; |
427 | struct dvb_ringbuffer *buffer; |
428 | #ifdef CONFIG_DVB_MMAP |
429 | struct dvb_vb2_ctx *ctx; |
430 | #endif |
431 | int ret; |
432 | |
433 | spin_lock(lock: &dmxdevfilter->dev->lock); |
434 | if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) { |
435 | spin_unlock(lock: &dmxdevfilter->dev->lock); |
436 | return 0; |
437 | } |
438 | |
439 | if (dmxdevfilter->params.pes.output == DMX_OUT_TAP || |
440 | dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP) { |
441 | buffer = &dmxdevfilter->buffer; |
442 | #ifdef CONFIG_DVB_MMAP |
443 | ctx = &dmxdevfilter->vb2_ctx; |
444 | #endif |
445 | } else { |
446 | buffer = &dmxdevfilter->dev->dvr_buffer; |
447 | #ifdef CONFIG_DVB_MMAP |
448 | ctx = &dmxdevfilter->dev->dvr_vb2_ctx; |
449 | #endif |
450 | } |
451 | |
452 | if (dvb_vb2_is_streaming(ctx)) { |
453 | ret = dvb_vb2_fill_buffer(ctx, src: buffer1, len: buffer1_len, |
454 | buffer_flags); |
455 | if (ret == buffer1_len) |
456 | ret = dvb_vb2_fill_buffer(ctx, src: buffer2, len: buffer2_len, |
457 | buffer_flags); |
458 | } else { |
459 | if (buffer->error) { |
460 | spin_unlock(lock: &dmxdevfilter->dev->lock); |
461 | wake_up(&buffer->queue); |
462 | return 0; |
463 | } |
464 | ret = dvb_dmxdev_buffer_write(buf: buffer, src: buffer1, len: buffer1_len); |
465 | if (ret == buffer1_len) |
466 | ret = dvb_dmxdev_buffer_write(buf: buffer, |
467 | src: buffer2, len: buffer2_len); |
468 | } |
469 | if (ret < 0) |
470 | buffer->error = ret; |
471 | spin_unlock(lock: &dmxdevfilter->dev->lock); |
472 | wake_up(&buffer->queue); |
473 | return 0; |
474 | } |
475 | |
476 | /* stop feed but only mark the specified filter as stopped (state set) */ |
477 | static int dvb_dmxdev_feed_stop(struct dmxdev_filter *dmxdevfilter) |
478 | { |
479 | struct dmxdev_feed *feed; |
480 | |
481 | dvb_dmxdev_filter_state_set(dmxdevfilter, state: DMXDEV_STATE_SET); |
482 | |
483 | switch (dmxdevfilter->type) { |
484 | case DMXDEV_TYPE_SEC: |
485 | del_timer(timer: &dmxdevfilter->timer); |
486 | dmxdevfilter->feed.sec->stop_filtering(dmxdevfilter->feed.sec); |
487 | break; |
488 | case DMXDEV_TYPE_PES: |
489 | list_for_each_entry(feed, &dmxdevfilter->feed.ts, next) |
490 | feed->ts->stop_filtering(feed->ts); |
491 | break; |
492 | default: |
493 | return -EINVAL; |
494 | } |
495 | return 0; |
496 | } |
497 | |
498 | /* start feed associated with the specified filter */ |
499 | static int dvb_dmxdev_feed_start(struct dmxdev_filter *filter) |
500 | { |
501 | struct dmxdev_feed *feed; |
502 | int ret; |
503 | |
504 | dvb_dmxdev_filter_state_set(dmxdevfilter: filter, state: DMXDEV_STATE_GO); |
505 | |
506 | switch (filter->type) { |
507 | case DMXDEV_TYPE_SEC: |
508 | return filter->feed.sec->start_filtering(filter->feed.sec); |
509 | case DMXDEV_TYPE_PES: |
510 | list_for_each_entry(feed, &filter->feed.ts, next) { |
511 | ret = feed->ts->start_filtering(feed->ts); |
512 | if (ret < 0) { |
513 | dvb_dmxdev_feed_stop(dmxdevfilter: filter); |
514 | return ret; |
515 | } |
516 | } |
517 | break; |
518 | default: |
519 | return -EINVAL; |
520 | } |
521 | |
522 | return 0; |
523 | } |
524 | |
525 | /* restart section feed if it has filters left associated with it, |
526 | otherwise release the feed */ |
527 | static int dvb_dmxdev_feed_restart(struct dmxdev_filter *filter) |
528 | { |
529 | int i; |
530 | struct dmxdev *dmxdev = filter->dev; |
531 | u16 pid = filter->params.sec.pid; |
532 | |
533 | for (i = 0; i < dmxdev->filternum; i++) |
534 | if (dmxdev->filter[i].state >= DMXDEV_STATE_GO && |
535 | dmxdev->filter[i].type == DMXDEV_TYPE_SEC && |
536 | dmxdev->filter[i].params.sec.pid == pid) { |
537 | dvb_dmxdev_feed_start(filter: &dmxdev->filter[i]); |
538 | return 0; |
539 | } |
540 | |
541 | filter->dev->demux->release_section_feed(dmxdev->demux, |
542 | filter->feed.sec); |
543 | |
544 | return 0; |
545 | } |
546 | |
547 | static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter) |
548 | { |
549 | struct dmxdev_feed *feed; |
550 | struct dmx_demux *demux; |
551 | |
552 | if (dmxdevfilter->state < DMXDEV_STATE_GO) |
553 | return 0; |
554 | |
555 | switch (dmxdevfilter->type) { |
556 | case DMXDEV_TYPE_SEC: |
557 | if (!dmxdevfilter->feed.sec) |
558 | break; |
559 | dvb_dmxdev_feed_stop(dmxdevfilter); |
560 | if (dmxdevfilter->filter.sec) |
561 | dmxdevfilter->feed.sec-> |
562 | release_filter(dmxdevfilter->feed.sec, |
563 | dmxdevfilter->filter.sec); |
564 | dvb_dmxdev_feed_restart(filter: dmxdevfilter); |
565 | dmxdevfilter->feed.sec = NULL; |
566 | break; |
567 | case DMXDEV_TYPE_PES: |
568 | dvb_dmxdev_feed_stop(dmxdevfilter); |
569 | demux = dmxdevfilter->dev->demux; |
570 | list_for_each_entry(feed, &dmxdevfilter->feed.ts, next) { |
571 | demux->release_ts_feed(demux, feed->ts); |
572 | feed->ts = NULL; |
573 | } |
574 | break; |
575 | default: |
576 | if (dmxdevfilter->state == DMXDEV_STATE_ALLOCATED) |
577 | return 0; |
578 | return -EINVAL; |
579 | } |
580 | |
581 | dvb_ringbuffer_flush(rbuf: &dmxdevfilter->buffer); |
582 | return 0; |
583 | } |
584 | |
585 | static void dvb_dmxdev_delete_pids(struct dmxdev_filter *dmxdevfilter) |
586 | { |
587 | struct dmxdev_feed *feed, *tmp; |
588 | |
589 | /* delete all PIDs */ |
590 | list_for_each_entry_safe(feed, tmp, &dmxdevfilter->feed.ts, next) { |
591 | list_del(entry: &feed->next); |
592 | kfree(objp: feed); |
593 | } |
594 | |
595 | BUG_ON(!list_empty(&dmxdevfilter->feed.ts)); |
596 | } |
597 | |
598 | static inline int dvb_dmxdev_filter_reset(struct dmxdev_filter *dmxdevfilter) |
599 | { |
600 | if (dmxdevfilter->state < DMXDEV_STATE_SET) |
601 | return 0; |
602 | |
603 | if (dmxdevfilter->type == DMXDEV_TYPE_PES) |
604 | dvb_dmxdev_delete_pids(dmxdevfilter); |
605 | |
606 | dmxdevfilter->type = DMXDEV_TYPE_NONE; |
607 | dvb_dmxdev_filter_state_set(dmxdevfilter, state: DMXDEV_STATE_ALLOCATED); |
608 | return 0; |
609 | } |
610 | |
611 | static int dvb_dmxdev_start_feed(struct dmxdev *dmxdev, |
612 | struct dmxdev_filter *filter, |
613 | struct dmxdev_feed *feed) |
614 | { |
615 | ktime_t timeout = ktime_set(secs: 0, nsecs: 0); |
616 | struct dmx_pes_filter_params *para = &filter->params.pes; |
617 | enum dmx_output otype; |
618 | int ret; |
619 | int ts_type; |
620 | enum dmx_ts_pes ts_pes; |
621 | struct dmx_ts_feed *tsfeed; |
622 | |
623 | feed->ts = NULL; |
624 | otype = para->output; |
625 | |
626 | ts_pes = para->pes_type; |
627 | |
628 | if (ts_pes < DMX_PES_OTHER) |
629 | ts_type = TS_DECODER; |
630 | else |
631 | ts_type = 0; |
632 | |
633 | if (otype == DMX_OUT_TS_TAP) |
634 | ts_type |= TS_PACKET; |
635 | else if (otype == DMX_OUT_TSDEMUX_TAP) |
636 | ts_type |= TS_PACKET | TS_DEMUX; |
637 | else if (otype == DMX_OUT_TAP) |
638 | ts_type |= TS_PACKET | TS_DEMUX | TS_PAYLOAD_ONLY; |
639 | |
640 | ret = dmxdev->demux->allocate_ts_feed(dmxdev->demux, &feed->ts, |
641 | dvb_dmxdev_ts_callback); |
642 | if (ret < 0) |
643 | return ret; |
644 | |
645 | tsfeed = feed->ts; |
646 | tsfeed->priv = filter; |
647 | |
648 | ret = tsfeed->set(tsfeed, feed->pid, ts_type, ts_pes, timeout); |
649 | if (ret < 0) { |
650 | dmxdev->demux->release_ts_feed(dmxdev->demux, tsfeed); |
651 | return ret; |
652 | } |
653 | |
654 | ret = tsfeed->start_filtering(tsfeed); |
655 | if (ret < 0) { |
656 | dmxdev->demux->release_ts_feed(dmxdev->demux, tsfeed); |
657 | return ret; |
658 | } |
659 | |
660 | return 0; |
661 | } |
662 | |
663 | static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter) |
664 | { |
665 | struct dmxdev *dmxdev = filter->dev; |
666 | struct dmxdev_feed *feed; |
667 | void *mem; |
668 | int ret, i; |
669 | |
670 | if (filter->state < DMXDEV_STATE_SET) |
671 | return -EINVAL; |
672 | |
673 | if (filter->state >= DMXDEV_STATE_GO) |
674 | dvb_dmxdev_filter_stop(dmxdevfilter: filter); |
675 | |
676 | if (!filter->buffer.data) { |
677 | mem = vmalloc(size: filter->buffer.size); |
678 | if (!mem) |
679 | return -ENOMEM; |
680 | spin_lock_irq(lock: &filter->dev->lock); |
681 | filter->buffer.data = mem; |
682 | spin_unlock_irq(lock: &filter->dev->lock); |
683 | } |
684 | |
685 | dvb_ringbuffer_flush(rbuf: &filter->buffer); |
686 | |
687 | switch (filter->type) { |
688 | case DMXDEV_TYPE_SEC: |
689 | { |
690 | struct dmx_sct_filter_params *para = &filter->params.sec; |
691 | struct dmx_section_filter **secfilter = &filter->filter.sec; |
692 | struct dmx_section_feed **secfeed = &filter->feed.sec; |
693 | |
694 | *secfilter = NULL; |
695 | *secfeed = NULL; |
696 | |
697 | |
698 | /* find active filter/feed with same PID */ |
699 | for (i = 0; i < dmxdev->filternum; i++) { |
700 | if (dmxdev->filter[i].state >= DMXDEV_STATE_GO && |
701 | dmxdev->filter[i].type == DMXDEV_TYPE_SEC && |
702 | dmxdev->filter[i].params.sec.pid == para->pid) { |
703 | *secfeed = dmxdev->filter[i].feed.sec; |
704 | break; |
705 | } |
706 | } |
707 | |
708 | /* if no feed found, try to allocate new one */ |
709 | if (!*secfeed) { |
710 | ret = dmxdev->demux->allocate_section_feed(dmxdev->demux, |
711 | secfeed, |
712 | dvb_dmxdev_section_callback); |
713 | if (!*secfeed) { |
714 | pr_err("DVB (%s): could not alloc feed\n" , |
715 | __func__); |
716 | return ret; |
717 | } |
718 | |
719 | ret = (*secfeed)->set(*secfeed, para->pid, |
720 | (para->flags & DMX_CHECK_CRC) ? 1 : 0); |
721 | if (ret < 0) { |
722 | pr_err("DVB (%s): could not set feed\n" , |
723 | __func__); |
724 | dvb_dmxdev_feed_restart(filter); |
725 | return ret; |
726 | } |
727 | } else { |
728 | dvb_dmxdev_feed_stop(dmxdevfilter: filter); |
729 | } |
730 | |
731 | ret = (*secfeed)->allocate_filter(*secfeed, secfilter); |
732 | if (ret < 0) { |
733 | dvb_dmxdev_feed_restart(filter); |
734 | filter->feed.sec->start_filtering(*secfeed); |
735 | dprintk("could not get filter\n" ); |
736 | return ret; |
737 | } |
738 | |
739 | (*secfilter)->priv = filter; |
740 | |
741 | memcpy(&((*secfilter)->filter_value[3]), |
742 | &(para->filter.filter[1]), DMX_FILTER_SIZE - 1); |
743 | memcpy(&(*secfilter)->filter_mask[3], |
744 | ¶->filter.mask[1], DMX_FILTER_SIZE - 1); |
745 | memcpy(&(*secfilter)->filter_mode[3], |
746 | ¶->filter.mode[1], DMX_FILTER_SIZE - 1); |
747 | |
748 | (*secfilter)->filter_value[0] = para->filter.filter[0]; |
749 | (*secfilter)->filter_mask[0] = para->filter.mask[0]; |
750 | (*secfilter)->filter_mode[0] = para->filter.mode[0]; |
751 | (*secfilter)->filter_mask[1] = 0; |
752 | (*secfilter)->filter_mask[2] = 0; |
753 | |
754 | filter->todo = 0; |
755 | |
756 | ret = filter->feed.sec->start_filtering(filter->feed.sec); |
757 | if (ret < 0) |
758 | return ret; |
759 | |
760 | dvb_dmxdev_filter_timer(dmxdevfilter: filter); |
761 | break; |
762 | } |
763 | case DMXDEV_TYPE_PES: |
764 | list_for_each_entry(feed, &filter->feed.ts, next) { |
765 | ret = dvb_dmxdev_start_feed(dmxdev, filter, feed); |
766 | if (ret < 0) { |
767 | dvb_dmxdev_filter_stop(dmxdevfilter: filter); |
768 | return ret; |
769 | } |
770 | } |
771 | break; |
772 | default: |
773 | return -EINVAL; |
774 | } |
775 | |
776 | dvb_dmxdev_filter_state_set(dmxdevfilter: filter, state: DMXDEV_STATE_GO); |
777 | return 0; |
778 | } |
779 | |
780 | static int dvb_demux_open(struct inode *inode, struct file *file) |
781 | { |
782 | struct dvb_device *dvbdev = file->private_data; |
783 | struct dmxdev *dmxdev = dvbdev->priv; |
784 | int i; |
785 | struct dmxdev_filter *dmxdevfilter; |
786 | |
787 | if (!dmxdev->filter) |
788 | return -EINVAL; |
789 | |
790 | if (mutex_lock_interruptible(&dmxdev->mutex)) |
791 | return -ERESTARTSYS; |
792 | |
793 | if (dmxdev->exit) { |
794 | mutex_unlock(lock: &dmxdev->mutex); |
795 | return -ENODEV; |
796 | } |
797 | |
798 | for (i = 0; i < dmxdev->filternum; i++) |
799 | if (dmxdev->filter[i].state == DMXDEV_STATE_FREE) |
800 | break; |
801 | |
802 | if (i == dmxdev->filternum) { |
803 | mutex_unlock(lock: &dmxdev->mutex); |
804 | return -EMFILE; |
805 | } |
806 | |
807 | dmxdevfilter = &dmxdev->filter[i]; |
808 | mutex_init(&dmxdevfilter->mutex); |
809 | file->private_data = dmxdevfilter; |
810 | |
811 | #ifdef CONFIG_DVB_MMAP |
812 | dmxdev->may_do_mmap = 1; |
813 | #else |
814 | dmxdev->may_do_mmap = 0; |
815 | #endif |
816 | |
817 | dvb_ringbuffer_init(rbuf: &dmxdevfilter->buffer, NULL, len: 8192); |
818 | dvb_vb2_init(ctx: &dmxdevfilter->vb2_ctx, name: "demux_filter" , |
819 | non_blocking: file->f_flags & O_NONBLOCK); |
820 | dmxdevfilter->type = DMXDEV_TYPE_NONE; |
821 | dvb_dmxdev_filter_state_set(dmxdevfilter, state: DMXDEV_STATE_ALLOCATED); |
822 | timer_setup(&dmxdevfilter->timer, dvb_dmxdev_filter_timeout, 0); |
823 | |
824 | dvbdev->users++; |
825 | |
826 | mutex_unlock(lock: &dmxdev->mutex); |
827 | return 0; |
828 | } |
829 | |
830 | static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev, |
831 | struct dmxdev_filter *dmxdevfilter) |
832 | { |
833 | mutex_lock(&dmxdev->mutex); |
834 | mutex_lock(&dmxdevfilter->mutex); |
835 | if (dvb_vb2_is_streaming(ctx: &dmxdevfilter->vb2_ctx)) |
836 | dvb_vb2_stream_off(ctx: &dmxdevfilter->vb2_ctx); |
837 | dvb_vb2_release(ctx: &dmxdevfilter->vb2_ctx); |
838 | |
839 | |
840 | dvb_dmxdev_filter_stop(dmxdevfilter); |
841 | dvb_dmxdev_filter_reset(dmxdevfilter); |
842 | |
843 | if (dmxdevfilter->buffer.data) { |
844 | void *mem = dmxdevfilter->buffer.data; |
845 | |
846 | spin_lock_irq(lock: &dmxdev->lock); |
847 | dmxdevfilter->buffer.data = NULL; |
848 | spin_unlock_irq(lock: &dmxdev->lock); |
849 | vfree(addr: mem); |
850 | } |
851 | |
852 | dvb_dmxdev_filter_state_set(dmxdevfilter, state: DMXDEV_STATE_FREE); |
853 | wake_up(&dmxdevfilter->buffer.queue); |
854 | mutex_unlock(lock: &dmxdevfilter->mutex); |
855 | mutex_unlock(lock: &dmxdev->mutex); |
856 | return 0; |
857 | } |
858 | |
859 | static inline void invert_mode(struct dmx_filter *filter) |
860 | { |
861 | int i; |
862 | |
863 | for (i = 0; i < DMX_FILTER_SIZE; i++) |
864 | filter->mode[i] ^= 0xff; |
865 | } |
866 | |
867 | static int dvb_dmxdev_add_pid(struct dmxdev *dmxdev, |
868 | struct dmxdev_filter *filter, u16 pid) |
869 | { |
870 | struct dmxdev_feed *feed; |
871 | |
872 | if ((filter->type != DMXDEV_TYPE_PES) || |
873 | (filter->state < DMXDEV_STATE_SET)) |
874 | return -EINVAL; |
875 | |
876 | /* only TS packet filters may have multiple PIDs */ |
877 | if ((filter->params.pes.output != DMX_OUT_TSDEMUX_TAP) && |
878 | (!list_empty(head: &filter->feed.ts))) |
879 | return -EINVAL; |
880 | |
881 | feed = kzalloc(size: sizeof(struct dmxdev_feed), GFP_KERNEL); |
882 | if (feed == NULL) |
883 | return -ENOMEM; |
884 | |
885 | feed->pid = pid; |
886 | list_add(new: &feed->next, head: &filter->feed.ts); |
887 | |
888 | if (filter->state >= DMXDEV_STATE_GO) |
889 | return dvb_dmxdev_start_feed(dmxdev, filter, feed); |
890 | |
891 | return 0; |
892 | } |
893 | |
894 | static int dvb_dmxdev_remove_pid(struct dmxdev *dmxdev, |
895 | struct dmxdev_filter *filter, u16 pid) |
896 | { |
897 | struct dmxdev_feed *feed, *tmp; |
898 | |
899 | if ((filter->type != DMXDEV_TYPE_PES) || |
900 | (filter->state < DMXDEV_STATE_SET)) |
901 | return -EINVAL; |
902 | |
903 | list_for_each_entry_safe(feed, tmp, &filter->feed.ts, next) { |
904 | if ((feed->pid == pid) && (feed->ts != NULL)) { |
905 | feed->ts->stop_filtering(feed->ts); |
906 | filter->dev->demux->release_ts_feed(filter->dev->demux, |
907 | feed->ts); |
908 | list_del(entry: &feed->next); |
909 | kfree(objp: feed); |
910 | } |
911 | } |
912 | |
913 | return 0; |
914 | } |
915 | |
916 | static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev, |
917 | struct dmxdev_filter *dmxdevfilter, |
918 | struct dmx_sct_filter_params *params) |
919 | { |
920 | dprintk("%s: PID=0x%04x, flags=%02x, timeout=%d\n" , |
921 | __func__, params->pid, params->flags, params->timeout); |
922 | |
923 | dvb_dmxdev_filter_stop(dmxdevfilter); |
924 | |
925 | dmxdevfilter->type = DMXDEV_TYPE_SEC; |
926 | memcpy(&dmxdevfilter->params.sec, |
927 | params, sizeof(struct dmx_sct_filter_params)); |
928 | invert_mode(filter: &dmxdevfilter->params.sec.filter); |
929 | dvb_dmxdev_filter_state_set(dmxdevfilter, state: DMXDEV_STATE_SET); |
930 | |
931 | if (params->flags & DMX_IMMEDIATE_START) |
932 | return dvb_dmxdev_filter_start(filter: dmxdevfilter); |
933 | |
934 | return 0; |
935 | } |
936 | |
937 | static int dvb_dmxdev_pes_filter_set(struct dmxdev *dmxdev, |
938 | struct dmxdev_filter *dmxdevfilter, |
939 | struct dmx_pes_filter_params *params) |
940 | { |
941 | int ret; |
942 | |
943 | dvb_dmxdev_filter_stop(dmxdevfilter); |
944 | dvb_dmxdev_filter_reset(dmxdevfilter); |
945 | |
946 | if ((unsigned int)params->pes_type > DMX_PES_OTHER) |
947 | return -EINVAL; |
948 | |
949 | dmxdevfilter->type = DMXDEV_TYPE_PES; |
950 | memcpy(&dmxdevfilter->params, params, |
951 | sizeof(struct dmx_pes_filter_params)); |
952 | INIT_LIST_HEAD(list: &dmxdevfilter->feed.ts); |
953 | |
954 | dvb_dmxdev_filter_state_set(dmxdevfilter, state: DMXDEV_STATE_SET); |
955 | |
956 | ret = dvb_dmxdev_add_pid(dmxdev, filter: dmxdevfilter, |
957 | pid: dmxdevfilter->params.pes.pid); |
958 | if (ret < 0) |
959 | return ret; |
960 | |
961 | if (params->flags & DMX_IMMEDIATE_START) |
962 | return dvb_dmxdev_filter_start(filter: dmxdevfilter); |
963 | |
964 | return 0; |
965 | } |
966 | |
967 | static ssize_t dvb_dmxdev_read_sec(struct dmxdev_filter *dfil, |
968 | struct file *file, char __user *buf, |
969 | size_t count, loff_t *ppos) |
970 | { |
971 | int result, hcount; |
972 | int done = 0; |
973 | |
974 | if (dfil->todo <= 0) { |
975 | hcount = 3 + dfil->todo; |
976 | if (hcount > count) |
977 | hcount = count; |
978 | result = dvb_dmxdev_buffer_read(src: &dfil->buffer, |
979 | non_blocking: file->f_flags & O_NONBLOCK, |
980 | buf, count: hcount, ppos); |
981 | if (result < 0) { |
982 | dfil->todo = 0; |
983 | return result; |
984 | } |
985 | if (copy_from_user(to: dfil->secheader - dfil->todo, from: buf, n: result)) |
986 | return -EFAULT; |
987 | buf += result; |
988 | done = result; |
989 | count -= result; |
990 | dfil->todo -= result; |
991 | if (dfil->todo > -3) |
992 | return done; |
993 | dfil->todo = ((dfil->secheader[1] << 8) | dfil->secheader[2]) & 0xfff; |
994 | if (!count) |
995 | return done; |
996 | } |
997 | if (count > dfil->todo) |
998 | count = dfil->todo; |
999 | result = dvb_dmxdev_buffer_read(src: &dfil->buffer, |
1000 | non_blocking: file->f_flags & O_NONBLOCK, |
1001 | buf, count, ppos); |
1002 | if (result < 0) |
1003 | return result; |
1004 | dfil->todo -= result; |
1005 | return (result + done); |
1006 | } |
1007 | |
1008 | static ssize_t |
1009 | dvb_demux_read(struct file *file, char __user *buf, size_t count, |
1010 | loff_t *ppos) |
1011 | { |
1012 | struct dmxdev_filter *dmxdevfilter = file->private_data; |
1013 | int ret; |
1014 | |
1015 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) |
1016 | return -ERESTARTSYS; |
1017 | |
1018 | if (dmxdevfilter->type == DMXDEV_TYPE_SEC) |
1019 | ret = dvb_dmxdev_read_sec(dfil: dmxdevfilter, file, buf, count, ppos); |
1020 | else |
1021 | ret = dvb_dmxdev_buffer_read(src: &dmxdevfilter->buffer, |
1022 | non_blocking: file->f_flags & O_NONBLOCK, |
1023 | buf, count, ppos); |
1024 | |
1025 | mutex_unlock(lock: &dmxdevfilter->mutex); |
1026 | return ret; |
1027 | } |
1028 | |
1029 | static int dvb_demux_do_ioctl(struct file *file, |
1030 | unsigned int cmd, void *parg) |
1031 | { |
1032 | struct dmxdev_filter *dmxdevfilter = file->private_data; |
1033 | struct dmxdev *dmxdev = dmxdevfilter->dev; |
1034 | unsigned long arg = (unsigned long)parg; |
1035 | int ret = 0; |
1036 | |
1037 | if (mutex_lock_interruptible(&dmxdev->mutex)) |
1038 | return -ERESTARTSYS; |
1039 | |
1040 | switch (cmd) { |
1041 | case DMX_START: |
1042 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { |
1043 | mutex_unlock(lock: &dmxdev->mutex); |
1044 | return -ERESTARTSYS; |
1045 | } |
1046 | if (dmxdevfilter->state < DMXDEV_STATE_SET) |
1047 | ret = -EINVAL; |
1048 | else |
1049 | ret = dvb_dmxdev_filter_start(filter: dmxdevfilter); |
1050 | mutex_unlock(lock: &dmxdevfilter->mutex); |
1051 | break; |
1052 | |
1053 | case DMX_STOP: |
1054 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { |
1055 | mutex_unlock(lock: &dmxdev->mutex); |
1056 | return -ERESTARTSYS; |
1057 | } |
1058 | ret = dvb_dmxdev_filter_stop(dmxdevfilter); |
1059 | mutex_unlock(lock: &dmxdevfilter->mutex); |
1060 | break; |
1061 | |
1062 | case DMX_SET_FILTER: |
1063 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { |
1064 | mutex_unlock(lock: &dmxdev->mutex); |
1065 | return -ERESTARTSYS; |
1066 | } |
1067 | ret = dvb_dmxdev_filter_set(dmxdev, dmxdevfilter, params: parg); |
1068 | mutex_unlock(lock: &dmxdevfilter->mutex); |
1069 | break; |
1070 | |
1071 | case DMX_SET_PES_FILTER: |
1072 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { |
1073 | mutex_unlock(lock: &dmxdev->mutex); |
1074 | return -ERESTARTSYS; |
1075 | } |
1076 | ret = dvb_dmxdev_pes_filter_set(dmxdev, dmxdevfilter, params: parg); |
1077 | mutex_unlock(lock: &dmxdevfilter->mutex); |
1078 | break; |
1079 | |
1080 | case DMX_SET_BUFFER_SIZE: |
1081 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { |
1082 | mutex_unlock(lock: &dmxdev->mutex); |
1083 | return -ERESTARTSYS; |
1084 | } |
1085 | ret = dvb_dmxdev_set_buffer_size(dmxdevfilter, size: arg); |
1086 | mutex_unlock(lock: &dmxdevfilter->mutex); |
1087 | break; |
1088 | |
1089 | case DMX_GET_PES_PIDS: |
1090 | if (!dmxdev->demux->get_pes_pids) { |
1091 | ret = -EINVAL; |
1092 | break; |
1093 | } |
1094 | dmxdev->demux->get_pes_pids(dmxdev->demux, parg); |
1095 | break; |
1096 | |
1097 | case DMX_GET_STC: |
1098 | if (!dmxdev->demux->get_stc) { |
1099 | ret = -EINVAL; |
1100 | break; |
1101 | } |
1102 | ret = dmxdev->demux->get_stc(dmxdev->demux, |
1103 | ((struct dmx_stc *)parg)->num, |
1104 | &((struct dmx_stc *)parg)->stc, |
1105 | &((struct dmx_stc *)parg)->base); |
1106 | break; |
1107 | |
1108 | case DMX_ADD_PID: |
1109 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { |
1110 | ret = -ERESTARTSYS; |
1111 | break; |
1112 | } |
1113 | ret = dvb_dmxdev_add_pid(dmxdev, filter: dmxdevfilter, pid: *(u16 *)parg); |
1114 | mutex_unlock(lock: &dmxdevfilter->mutex); |
1115 | break; |
1116 | |
1117 | case DMX_REMOVE_PID: |
1118 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { |
1119 | ret = -ERESTARTSYS; |
1120 | break; |
1121 | } |
1122 | ret = dvb_dmxdev_remove_pid(dmxdev, filter: dmxdevfilter, pid: *(u16 *)parg); |
1123 | mutex_unlock(lock: &dmxdevfilter->mutex); |
1124 | break; |
1125 | |
1126 | #ifdef CONFIG_DVB_MMAP |
1127 | case DMX_REQBUFS: |
1128 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { |
1129 | mutex_unlock(lock: &dmxdev->mutex); |
1130 | return -ERESTARTSYS; |
1131 | } |
1132 | ret = dvb_vb2_reqbufs(ctx: &dmxdevfilter->vb2_ctx, req: parg); |
1133 | mutex_unlock(lock: &dmxdevfilter->mutex); |
1134 | break; |
1135 | |
1136 | case DMX_QUERYBUF: |
1137 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { |
1138 | mutex_unlock(lock: &dmxdev->mutex); |
1139 | return -ERESTARTSYS; |
1140 | } |
1141 | ret = dvb_vb2_querybuf(ctx: &dmxdevfilter->vb2_ctx, b: parg); |
1142 | mutex_unlock(lock: &dmxdevfilter->mutex); |
1143 | break; |
1144 | |
1145 | case DMX_EXPBUF: |
1146 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { |
1147 | mutex_unlock(lock: &dmxdev->mutex); |
1148 | return -ERESTARTSYS; |
1149 | } |
1150 | ret = dvb_vb2_expbuf(ctx: &dmxdevfilter->vb2_ctx, exp: parg); |
1151 | mutex_unlock(lock: &dmxdevfilter->mutex); |
1152 | break; |
1153 | |
1154 | case DMX_QBUF: |
1155 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { |
1156 | mutex_unlock(lock: &dmxdev->mutex); |
1157 | return -ERESTARTSYS; |
1158 | } |
1159 | ret = dvb_vb2_qbuf(ctx: &dmxdevfilter->vb2_ctx, b: parg); |
1160 | if (ret == 0 && !dvb_vb2_is_streaming(ctx: &dmxdevfilter->vb2_ctx)) |
1161 | ret = dvb_vb2_stream_on(ctx: &dmxdevfilter->vb2_ctx); |
1162 | mutex_unlock(lock: &dmxdevfilter->mutex); |
1163 | break; |
1164 | |
1165 | case DMX_DQBUF: |
1166 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { |
1167 | mutex_unlock(lock: &dmxdev->mutex); |
1168 | return -ERESTARTSYS; |
1169 | } |
1170 | ret = dvb_vb2_dqbuf(ctx: &dmxdevfilter->vb2_ctx, b: parg); |
1171 | mutex_unlock(lock: &dmxdevfilter->mutex); |
1172 | break; |
1173 | #endif |
1174 | default: |
1175 | ret = -ENOTTY; |
1176 | break; |
1177 | } |
1178 | mutex_unlock(lock: &dmxdev->mutex); |
1179 | return ret; |
1180 | } |
1181 | |
1182 | static long dvb_demux_ioctl(struct file *file, unsigned int cmd, |
1183 | unsigned long arg) |
1184 | { |
1185 | return dvb_usercopy(file, cmd, arg, func: dvb_demux_do_ioctl); |
1186 | } |
1187 | |
1188 | static __poll_t dvb_demux_poll(struct file *file, poll_table *wait) |
1189 | { |
1190 | struct dmxdev_filter *dmxdevfilter = file->private_data; |
1191 | __poll_t mask = 0; |
1192 | |
1193 | poll_wait(filp: file, wait_address: &dmxdevfilter->buffer.queue, p: wait); |
1194 | |
1195 | if ((!dmxdevfilter) || dmxdevfilter->dev->exit) |
1196 | return EPOLLERR; |
1197 | if (dvb_vb2_is_streaming(ctx: &dmxdevfilter->vb2_ctx)) |
1198 | return dvb_vb2_poll(ctx: &dmxdevfilter->vb2_ctx, file, wait); |
1199 | |
1200 | if (dmxdevfilter->state != DMXDEV_STATE_GO && |
1201 | dmxdevfilter->state != DMXDEV_STATE_DONE && |
1202 | dmxdevfilter->state != DMXDEV_STATE_TIMEDOUT) |
1203 | return 0; |
1204 | |
1205 | if (dmxdevfilter->buffer.error) |
1206 | mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI | EPOLLERR); |
1207 | |
1208 | if (!dvb_ringbuffer_empty(rbuf: &dmxdevfilter->buffer)) |
1209 | mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI); |
1210 | |
1211 | return mask; |
1212 | } |
1213 | |
1214 | #ifdef CONFIG_DVB_MMAP |
1215 | static int dvb_demux_mmap(struct file *file, struct vm_area_struct *vma) |
1216 | { |
1217 | struct dmxdev_filter *dmxdevfilter = file->private_data; |
1218 | struct dmxdev *dmxdev = dmxdevfilter->dev; |
1219 | int ret; |
1220 | |
1221 | if (!dmxdev->may_do_mmap) |
1222 | return -ENOTTY; |
1223 | |
1224 | if (mutex_lock_interruptible(&dmxdev->mutex)) |
1225 | return -ERESTARTSYS; |
1226 | |
1227 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { |
1228 | mutex_unlock(lock: &dmxdev->mutex); |
1229 | return -ERESTARTSYS; |
1230 | } |
1231 | ret = dvb_vb2_mmap(ctx: &dmxdevfilter->vb2_ctx, vma); |
1232 | |
1233 | mutex_unlock(lock: &dmxdevfilter->mutex); |
1234 | mutex_unlock(lock: &dmxdev->mutex); |
1235 | |
1236 | return ret; |
1237 | } |
1238 | #endif |
1239 | |
1240 | static int dvb_demux_release(struct inode *inode, struct file *file) |
1241 | { |
1242 | struct dmxdev_filter *dmxdevfilter = file->private_data; |
1243 | struct dmxdev *dmxdev = dmxdevfilter->dev; |
1244 | int ret; |
1245 | |
1246 | ret = dvb_dmxdev_filter_free(dmxdev, dmxdevfilter); |
1247 | |
1248 | mutex_lock(&dmxdev->mutex); |
1249 | dmxdev->dvbdev->users--; |
1250 | if (dmxdev->dvbdev->users == 1 && dmxdev->exit == 1) { |
1251 | mutex_unlock(lock: &dmxdev->mutex); |
1252 | wake_up(&dmxdev->dvbdev->wait_queue); |
1253 | } else |
1254 | mutex_unlock(lock: &dmxdev->mutex); |
1255 | |
1256 | return ret; |
1257 | } |
1258 | |
1259 | static const struct file_operations dvb_demux_fops = { |
1260 | .owner = THIS_MODULE, |
1261 | .read = dvb_demux_read, |
1262 | .unlocked_ioctl = dvb_demux_ioctl, |
1263 | .compat_ioctl = dvb_demux_ioctl, |
1264 | .open = dvb_demux_open, |
1265 | .release = dvb_demux_release, |
1266 | .poll = dvb_demux_poll, |
1267 | .llseek = default_llseek, |
1268 | #ifdef CONFIG_DVB_MMAP |
1269 | .mmap = dvb_demux_mmap, |
1270 | #endif |
1271 | }; |
1272 | |
1273 | static const struct dvb_device dvbdev_demux = { |
1274 | .priv = NULL, |
1275 | .users = 1, |
1276 | .writers = 1, |
1277 | #if defined(CONFIG_MEDIA_CONTROLLER_DVB) |
1278 | .name = "dvb-demux" , |
1279 | #endif |
1280 | .fops = &dvb_demux_fops |
1281 | }; |
1282 | |
1283 | static int dvb_dvr_do_ioctl(struct file *file, |
1284 | unsigned int cmd, void *parg) |
1285 | { |
1286 | struct dvb_device *dvbdev = file->private_data; |
1287 | struct dmxdev *dmxdev = dvbdev->priv; |
1288 | unsigned long arg = (unsigned long)parg; |
1289 | int ret; |
1290 | |
1291 | if (mutex_lock_interruptible(&dmxdev->mutex)) |
1292 | return -ERESTARTSYS; |
1293 | |
1294 | switch (cmd) { |
1295 | case DMX_SET_BUFFER_SIZE: |
1296 | ret = dvb_dvr_set_buffer_size(dmxdev, size: arg); |
1297 | break; |
1298 | |
1299 | #ifdef CONFIG_DVB_MMAP |
1300 | case DMX_REQBUFS: |
1301 | ret = dvb_vb2_reqbufs(ctx: &dmxdev->dvr_vb2_ctx, req: parg); |
1302 | break; |
1303 | |
1304 | case DMX_QUERYBUF: |
1305 | ret = dvb_vb2_querybuf(ctx: &dmxdev->dvr_vb2_ctx, b: parg); |
1306 | break; |
1307 | |
1308 | case DMX_EXPBUF: |
1309 | ret = dvb_vb2_expbuf(ctx: &dmxdev->dvr_vb2_ctx, exp: parg); |
1310 | break; |
1311 | |
1312 | case DMX_QBUF: |
1313 | ret = dvb_vb2_qbuf(ctx: &dmxdev->dvr_vb2_ctx, b: parg); |
1314 | if (ret == 0 && !dvb_vb2_is_streaming(ctx: &dmxdev->dvr_vb2_ctx)) |
1315 | ret = dvb_vb2_stream_on(ctx: &dmxdev->dvr_vb2_ctx); |
1316 | break; |
1317 | |
1318 | case DMX_DQBUF: |
1319 | ret = dvb_vb2_dqbuf(ctx: &dmxdev->dvr_vb2_ctx, b: parg); |
1320 | break; |
1321 | #endif |
1322 | default: |
1323 | ret = -ENOTTY; |
1324 | break; |
1325 | } |
1326 | mutex_unlock(lock: &dmxdev->mutex); |
1327 | return ret; |
1328 | } |
1329 | |
1330 | static long dvb_dvr_ioctl(struct file *file, |
1331 | unsigned int cmd, unsigned long arg) |
1332 | { |
1333 | return dvb_usercopy(file, cmd, arg, func: dvb_dvr_do_ioctl); |
1334 | } |
1335 | |
1336 | static __poll_t dvb_dvr_poll(struct file *file, poll_table *wait) |
1337 | { |
1338 | struct dvb_device *dvbdev = file->private_data; |
1339 | struct dmxdev *dmxdev = dvbdev->priv; |
1340 | __poll_t mask = 0; |
1341 | |
1342 | dprintk("%s\n" , __func__); |
1343 | |
1344 | poll_wait(filp: file, wait_address: &dmxdev->dvr_buffer.queue, p: wait); |
1345 | |
1346 | if (dmxdev->exit) |
1347 | return EPOLLERR; |
1348 | if (dvb_vb2_is_streaming(ctx: &dmxdev->dvr_vb2_ctx)) |
1349 | return dvb_vb2_poll(ctx: &dmxdev->dvr_vb2_ctx, file, wait); |
1350 | |
1351 | if (((file->f_flags & O_ACCMODE) == O_RDONLY) || |
1352 | dmxdev->may_do_mmap) { |
1353 | if (dmxdev->dvr_buffer.error) |
1354 | mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI | EPOLLERR); |
1355 | |
1356 | if (!dvb_ringbuffer_empty(rbuf: &dmxdev->dvr_buffer)) |
1357 | mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI); |
1358 | } else |
1359 | mask |= (EPOLLOUT | EPOLLWRNORM | EPOLLPRI); |
1360 | |
1361 | return mask; |
1362 | } |
1363 | |
1364 | #ifdef CONFIG_DVB_MMAP |
1365 | static int dvb_dvr_mmap(struct file *file, struct vm_area_struct *vma) |
1366 | { |
1367 | struct dvb_device *dvbdev = file->private_data; |
1368 | struct dmxdev *dmxdev = dvbdev->priv; |
1369 | int ret; |
1370 | |
1371 | if (!dmxdev->may_do_mmap) |
1372 | return -ENOTTY; |
1373 | |
1374 | if (dmxdev->exit) |
1375 | return -ENODEV; |
1376 | |
1377 | if (mutex_lock_interruptible(&dmxdev->mutex)) |
1378 | return -ERESTARTSYS; |
1379 | |
1380 | ret = dvb_vb2_mmap(ctx: &dmxdev->dvr_vb2_ctx, vma); |
1381 | mutex_unlock(lock: &dmxdev->mutex); |
1382 | return ret; |
1383 | } |
1384 | #endif |
1385 | |
1386 | static const struct file_operations dvb_dvr_fops = { |
1387 | .owner = THIS_MODULE, |
1388 | .read = dvb_dvr_read, |
1389 | .write = dvb_dvr_write, |
1390 | .unlocked_ioctl = dvb_dvr_ioctl, |
1391 | .open = dvb_dvr_open, |
1392 | .release = dvb_dvr_release, |
1393 | .poll = dvb_dvr_poll, |
1394 | .llseek = default_llseek, |
1395 | #ifdef CONFIG_DVB_MMAP |
1396 | .mmap = dvb_dvr_mmap, |
1397 | #endif |
1398 | }; |
1399 | |
1400 | static const struct dvb_device dvbdev_dvr = { |
1401 | .priv = NULL, |
1402 | .readers = 1, |
1403 | .users = 1, |
1404 | #if defined(CONFIG_MEDIA_CONTROLLER_DVB) |
1405 | .name = "dvb-dvr" , |
1406 | #endif |
1407 | .fops = &dvb_dvr_fops |
1408 | }; |
1409 | int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter) |
1410 | { |
1411 | int i, ret; |
1412 | |
1413 | if (dmxdev->demux->open(dmxdev->demux) < 0) |
1414 | return -EUSERS; |
1415 | |
1416 | dmxdev->filter = vmalloc(array_size(sizeof(struct dmxdev_filter), |
1417 | dmxdev->filternum)); |
1418 | if (!dmxdev->filter) |
1419 | return -ENOMEM; |
1420 | |
1421 | mutex_init(&dmxdev->mutex); |
1422 | spin_lock_init(&dmxdev->lock); |
1423 | for (i = 0; i < dmxdev->filternum; i++) { |
1424 | dmxdev->filter[i].dev = dmxdev; |
1425 | dmxdev->filter[i].buffer.data = NULL; |
1426 | dvb_dmxdev_filter_state_set(dmxdevfilter: &dmxdev->filter[i], |
1427 | state: DMXDEV_STATE_FREE); |
1428 | } |
1429 | |
1430 | ret = dvb_register_device(adap: dvb_adapter, pdvbdev: &dmxdev->dvbdev, template: &dvbdev_demux, priv: dmxdev, |
1431 | type: DVB_DEVICE_DEMUX, demux_sink_pads: dmxdev->filternum); |
1432 | if (ret < 0) |
1433 | goto err_register_dvbdev; |
1434 | |
1435 | ret = dvb_register_device(adap: dvb_adapter, pdvbdev: &dmxdev->dvr_dvbdev, template: &dvbdev_dvr, |
1436 | priv: dmxdev, type: DVB_DEVICE_DVR, demux_sink_pads: dmxdev->filternum); |
1437 | if (ret < 0) |
1438 | goto err_register_dvr_dvbdev; |
1439 | |
1440 | dvb_ringbuffer_init(rbuf: &dmxdev->dvr_buffer, NULL, len: 8192); |
1441 | |
1442 | return 0; |
1443 | |
1444 | err_register_dvr_dvbdev: |
1445 | dvb_unregister_device(dvbdev: dmxdev->dvbdev); |
1446 | err_register_dvbdev: |
1447 | vfree(addr: dmxdev->filter); |
1448 | dmxdev->filter = NULL; |
1449 | return ret; |
1450 | } |
1451 | |
1452 | EXPORT_SYMBOL(dvb_dmxdev_init); |
1453 | |
1454 | void dvb_dmxdev_release(struct dmxdev *dmxdev) |
1455 | { |
1456 | mutex_lock(&dmxdev->mutex); |
1457 | dmxdev->exit = 1; |
1458 | mutex_unlock(lock: &dmxdev->mutex); |
1459 | |
1460 | if (dmxdev->dvbdev->users > 1) { |
1461 | wait_event(dmxdev->dvbdev->wait_queue, |
1462 | dmxdev->dvbdev->users == 1); |
1463 | } |
1464 | if (dmxdev->dvr_dvbdev->users > 1) { |
1465 | wait_event(dmxdev->dvr_dvbdev->wait_queue, |
1466 | dmxdev->dvr_dvbdev->users == 1); |
1467 | } |
1468 | |
1469 | dvb_unregister_device(dvbdev: dmxdev->dvbdev); |
1470 | dvb_unregister_device(dvbdev: dmxdev->dvr_dvbdev); |
1471 | |
1472 | vfree(addr: dmxdev->filter); |
1473 | dmxdev->filter = NULL; |
1474 | dmxdev->demux->close(dmxdev->demux); |
1475 | } |
1476 | |
1477 | EXPORT_SYMBOL(dvb_dmxdev_release); |
1478 | |