Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/media/dvb/dvb-core/dvb_demux.c
15112 views
1
/*
2
* dvb_demux.c - DVB kernel demux API
3
*
4
* Copyright (C) 2000-2001 Ralph Metzler <[email protected]>
5
* & Marcus Metzler <[email protected]>
6
* for convergence integrated media GmbH
7
*
8
* This program is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU Lesser General Public License
10
* as published by the Free Software Foundation; either version 2.1
11
* of the License, or (at your option) any later version.
12
*
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
17
*
18
* You should have received a copy of the GNU Lesser General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
*
22
*/
23
24
#include <linux/sched.h>
25
#include <linux/spinlock.h>
26
#include <linux/slab.h>
27
#include <linux/vmalloc.h>
28
#include <linux/module.h>
29
#include <linux/poll.h>
30
#include <linux/string.h>
31
#include <linux/crc32.h>
32
#include <asm/uaccess.h>
33
#include <asm/div64.h>
34
35
#include "dvb_demux.h"
36
37
#define NOBUFS
38
/*
39
** #define DVB_DEMUX_SECTION_LOSS_LOG to monitor payload loss in the syslog
40
*/
41
// #define DVB_DEMUX_SECTION_LOSS_LOG
42
43
static int dvb_demux_tscheck;
44
module_param(dvb_demux_tscheck, int, 0644);
45
MODULE_PARM_DESC(dvb_demux_tscheck,
46
"enable transport stream continuity and TEI check");
47
48
static int dvb_demux_speedcheck;
49
module_param(dvb_demux_speedcheck, int, 0644);
50
MODULE_PARM_DESC(dvb_demux_speedcheck,
51
"enable transport stream speed check");
52
53
#define dprintk_tscheck(x...) do { \
54
if (dvb_demux_tscheck && printk_ratelimit()) \
55
printk(x); \
56
} while (0)
57
58
/******************************************************************************
59
* static inlined helper functions
60
******************************************************************************/
61
62
static inline u16 section_length(const u8 *buf)
63
{
64
return 3 + ((buf[1] & 0x0f) << 8) + buf[2];
65
}
66
67
static inline u16 ts_pid(const u8 *buf)
68
{
69
return ((buf[1] & 0x1f) << 8) + buf[2];
70
}
71
72
static inline u8 payload(const u8 *tsp)
73
{
74
if (!(tsp[3] & 0x10)) // no payload?
75
return 0;
76
77
if (tsp[3] & 0x20) { // adaptation field?
78
if (tsp[4] > 183) // corrupted data?
79
return 0;
80
else
81
return 184 - 1 - tsp[4];
82
}
83
84
return 184;
85
}
86
87
static u32 dvb_dmx_crc32(struct dvb_demux_feed *f, const u8 *src, size_t len)
88
{
89
return (f->feed.sec.crc_val = crc32_be(f->feed.sec.crc_val, src, len));
90
}
91
92
static void dvb_dmx_memcopy(struct dvb_demux_feed *f, u8 *d, const u8 *s,
93
size_t len)
94
{
95
memcpy(d, s, len);
96
}
97
98
/******************************************************************************
99
* Software filter functions
100
******************************************************************************/
101
102
static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed,
103
const u8 *buf)
104
{
105
int count = payload(buf);
106
int p;
107
//int ccok;
108
//u8 cc;
109
110
if (count == 0)
111
return -1;
112
113
p = 188 - count;
114
115
/*
116
cc = buf[3] & 0x0f;
117
ccok = ((feed->cc + 1) & 0x0f) == cc;
118
feed->cc = cc;
119
if (!ccok)
120
printk("missed packet!\n");
121
*/
122
123
if (buf[1] & 0x40) // PUSI ?
124
feed->peslen = 0xfffa;
125
126
feed->peslen += count;
127
128
return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts, DMX_OK);
129
}
130
131
static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed,
132
struct dvb_demux_filter *f)
133
{
134
u8 neq = 0;
135
int i;
136
137
for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
138
u8 xor = f->filter.filter_value[i] ^ feed->feed.sec.secbuf[i];
139
140
if (f->maskandmode[i] & xor)
141
return 0;
142
143
neq |= f->maskandnotmode[i] & xor;
144
}
145
146
if (f->doneq && !neq)
147
return 0;
148
149
return feed->cb.sec(feed->feed.sec.secbuf, feed->feed.sec.seclen,
150
NULL, 0, &f->filter, DMX_OK);
151
}
152
153
static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed)
154
{
155
struct dvb_demux *demux = feed->demux;
156
struct dvb_demux_filter *f = feed->filter;
157
struct dmx_section_feed *sec = &feed->feed.sec;
158
int section_syntax_indicator;
159
160
if (!sec->is_filtering)
161
return 0;
162
163
if (!f)
164
return 0;
165
166
if (sec->check_crc) {
167
section_syntax_indicator = ((sec->secbuf[1] & 0x80) != 0);
168
if (section_syntax_indicator &&
169
demux->check_crc32(feed, sec->secbuf, sec->seclen))
170
return -1;
171
}
172
173
do {
174
if (dvb_dmx_swfilter_sectionfilter(feed, f) < 0)
175
return -1;
176
} while ((f = f->next) && sec->is_filtering);
177
178
sec->seclen = 0;
179
180
return 0;
181
}
182
183
static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed)
184
{
185
struct dmx_section_feed *sec = &feed->feed.sec;
186
187
#ifdef DVB_DEMUX_SECTION_LOSS_LOG
188
if (sec->secbufp < sec->tsfeedp) {
189
int i, n = sec->tsfeedp - sec->secbufp;
190
191
/*
192
* Section padding is done with 0xff bytes entirely.
193
* Due to speed reasons, we won't check all of them
194
* but just first and last.
195
*/
196
if (sec->secbuf[0] != 0xff || sec->secbuf[n - 1] != 0xff) {
197
printk("dvb_demux.c section ts padding loss: %d/%d\n",
198
n, sec->tsfeedp);
199
printk("dvb_demux.c pad data:");
200
for (i = 0; i < n; i++)
201
printk(" %02x", sec->secbuf[i]);
202
printk("\n");
203
}
204
}
205
#endif
206
207
sec->tsfeedp = sec->secbufp = sec->seclen = 0;
208
sec->secbuf = sec->secbuf_base;
209
}
210
211
/*
212
* Losless Section Demux 1.4.1 by Emard
213
* Valsecchi Patrick:
214
* - middle of section A (no PUSI)
215
* - end of section A and start of section B
216
* (with PUSI pointing to the start of the second section)
217
*
218
* In this case, without feed->pusi_seen you'll receive a garbage section
219
* consisting of the end of section A. Basically because tsfeedp
220
* is incemented and the use=0 condition is not raised
221
* when the second packet arrives.
222
*
223
* Fix:
224
* when demux is started, let feed->pusi_seen = 0 to
225
* prevent initial feeding of garbage from the end of
226
* previous section. When you for the first time see PUSI=1
227
* then set feed->pusi_seen = 1
228
*/
229
static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
230
const u8 *buf, u8 len)
231
{
232
struct dvb_demux *demux = feed->demux;
233
struct dmx_section_feed *sec = &feed->feed.sec;
234
u16 limit, seclen, n;
235
236
if (sec->tsfeedp >= DMX_MAX_SECFEED_SIZE)
237
return 0;
238
239
if (sec->tsfeedp + len > DMX_MAX_SECFEED_SIZE) {
240
#ifdef DVB_DEMUX_SECTION_LOSS_LOG
241
printk("dvb_demux.c section buffer full loss: %d/%d\n",
242
sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE,
243
DMX_MAX_SECFEED_SIZE);
244
#endif
245
len = DMX_MAX_SECFEED_SIZE - sec->tsfeedp;
246
}
247
248
if (len <= 0)
249
return 0;
250
251
demux->memcopy(feed, sec->secbuf_base + sec->tsfeedp, buf, len);
252
sec->tsfeedp += len;
253
254
/*
255
* Dump all the sections we can find in the data (Emard)
256
*/
257
limit = sec->tsfeedp;
258
if (limit > DMX_MAX_SECFEED_SIZE)
259
return -1; /* internal error should never happen */
260
261
/* to be sure always set secbuf */
262
sec->secbuf = sec->secbuf_base + sec->secbufp;
263
264
for (n = 0; sec->secbufp + 2 < limit; n++) {
265
seclen = section_length(sec->secbuf);
266
if (seclen <= 0 || seclen > DMX_MAX_SECTION_SIZE
267
|| seclen + sec->secbufp > limit)
268
return 0;
269
sec->seclen = seclen;
270
sec->crc_val = ~0;
271
/* dump [secbuf .. secbuf+seclen) */
272
if (feed->pusi_seen)
273
dvb_dmx_swfilter_section_feed(feed);
274
#ifdef DVB_DEMUX_SECTION_LOSS_LOG
275
else
276
printk("dvb_demux.c pusi not seen, discarding section data\n");
277
#endif
278
sec->secbufp += seclen; /* secbufp and secbuf moving together is */
279
sec->secbuf += seclen; /* redundant but saves pointer arithmetic */
280
}
281
282
return 0;
283
}
284
285
static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
286
const u8 *buf)
287
{
288
u8 p, count;
289
int ccok, dc_i = 0;
290
u8 cc;
291
292
count = payload(buf);
293
294
if (count == 0) /* count == 0 if no payload or out of range */
295
return -1;
296
297
p = 188 - count; /* payload start */
298
299
cc = buf[3] & 0x0f;
300
ccok = ((feed->cc + 1) & 0x0f) == cc;
301
feed->cc = cc;
302
303
if (buf[3] & 0x20) {
304
/* adaption field present, check for discontinuity_indicator */
305
if ((buf[4] > 0) && (buf[5] & 0x80))
306
dc_i = 1;
307
}
308
309
if (!ccok || dc_i) {
310
#ifdef DVB_DEMUX_SECTION_LOSS_LOG
311
printk("dvb_demux.c discontinuity detected %d bytes lost\n",
312
count);
313
/*
314
* those bytes under sume circumstances will again be reported
315
* in the following dvb_dmx_swfilter_section_new
316
*/
317
#endif
318
/*
319
* Discontinuity detected. Reset pusi_seen = 0 to
320
* stop feeding of suspicious data until next PUSI=1 arrives
321
*/
322
feed->pusi_seen = 0;
323
dvb_dmx_swfilter_section_new(feed);
324
}
325
326
if (buf[1] & 0x40) {
327
/* PUSI=1 (is set), section boundary is here */
328
if (count > 1 && buf[p] < count) {
329
const u8 *before = &buf[p + 1];
330
u8 before_len = buf[p];
331
const u8 *after = &before[before_len];
332
u8 after_len = count - 1 - before_len;
333
334
dvb_dmx_swfilter_section_copy_dump(feed, before,
335
before_len);
336
/* before start of new section, set pusi_seen = 1 */
337
feed->pusi_seen = 1;
338
dvb_dmx_swfilter_section_new(feed);
339
dvb_dmx_swfilter_section_copy_dump(feed, after,
340
after_len);
341
}
342
#ifdef DVB_DEMUX_SECTION_LOSS_LOG
343
else if (count > 0)
344
printk("dvb_demux.c PUSI=1 but %d bytes lost\n", count);
345
#endif
346
} else {
347
/* PUSI=0 (is not set), no section boundary */
348
dvb_dmx_swfilter_section_copy_dump(feed, &buf[p], count);
349
}
350
351
return 0;
352
}
353
354
static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed,
355
const u8 *buf)
356
{
357
switch (feed->type) {
358
case DMX_TYPE_TS:
359
if (!feed->feed.ts.is_filtering)
360
break;
361
if (feed->ts_type & TS_PACKET) {
362
if (feed->ts_type & TS_PAYLOAD_ONLY)
363
dvb_dmx_swfilter_payload(feed, buf);
364
else
365
feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts,
366
DMX_OK);
367
}
368
if (feed->ts_type & TS_DECODER)
369
if (feed->demux->write_to_decoder)
370
feed->demux->write_to_decoder(feed, buf, 188);
371
break;
372
373
case DMX_TYPE_SEC:
374
if (!feed->feed.sec.is_filtering)
375
break;
376
if (dvb_dmx_swfilter_section_packet(feed, buf) < 0)
377
feed->feed.sec.seclen = feed->feed.sec.secbufp = 0;
378
break;
379
380
default:
381
break;
382
}
383
}
384
385
#define DVR_FEED(f) \
386
(((f)->type == DMX_TYPE_TS) && \
387
((f)->feed.ts.is_filtering) && \
388
(((f)->ts_type & (TS_PACKET | TS_DEMUX)) == TS_PACKET))
389
390
static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
391
{
392
struct dvb_demux_feed *feed;
393
u16 pid = ts_pid(buf);
394
int dvr_done = 0;
395
396
if (dvb_demux_speedcheck) {
397
struct timespec cur_time, delta_time;
398
u64 speed_bytes, speed_timedelta;
399
400
demux->speed_pkts_cnt++;
401
402
/* show speed every SPEED_PKTS_INTERVAL packets */
403
if (!(demux->speed_pkts_cnt % SPEED_PKTS_INTERVAL)) {
404
cur_time = current_kernel_time();
405
406
if (demux->speed_last_time.tv_sec != 0 &&
407
demux->speed_last_time.tv_nsec != 0) {
408
delta_time = timespec_sub(cur_time,
409
demux->speed_last_time);
410
speed_bytes = (u64)demux->speed_pkts_cnt
411
* 188 * 8;
412
/* convert to 1024 basis */
413
speed_bytes = 1000 * div64_u64(speed_bytes,
414
1024);
415
speed_timedelta =
416
(u64)timespec_to_ns(&delta_time);
417
speed_timedelta = div64_u64(speed_timedelta,
418
1000000); /* nsec -> usec */
419
printk(KERN_INFO "TS speed %llu Kbits/sec \n",
420
div64_u64(speed_bytes,
421
speed_timedelta));
422
};
423
424
demux->speed_last_time = cur_time;
425
demux->speed_pkts_cnt = 0;
426
};
427
};
428
429
if (demux->cnt_storage && dvb_demux_tscheck) {
430
/* check pkt counter */
431
if (pid < MAX_PID) {
432
if (buf[1] & 0x80)
433
dprintk_tscheck("TEI detected. "
434
"PID=0x%x data1=0x%x\n",
435
pid, buf[1]);
436
437
if ((buf[3] & 0xf) != demux->cnt_storage[pid])
438
dprintk_tscheck("TS packet counter mismatch. "
439
"PID=0x%x expected 0x%x "
440
"got 0x%x\n",
441
pid, demux->cnt_storage[pid],
442
buf[3] & 0xf);
443
444
demux->cnt_storage[pid] = ((buf[3] & 0xf) + 1)&0xf;
445
};
446
/* end check */
447
};
448
449
list_for_each_entry(feed, &demux->feed_list, list_head) {
450
if ((feed->pid != pid) && (feed->pid != 0x2000))
451
continue;
452
453
/* copy each packet only once to the dvr device, even
454
* if a PID is in multiple filters (e.g. video + PCR) */
455
if ((DVR_FEED(feed)) && (dvr_done++))
456
continue;
457
458
if (feed->pid == pid)
459
dvb_dmx_swfilter_packet_type(feed, buf);
460
else if (feed->pid == 0x2000)
461
feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, DMX_OK);
462
}
463
}
464
465
void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
466
size_t count)
467
{
468
spin_lock(&demux->lock);
469
470
while (count--) {
471
if (buf[0] == 0x47)
472
dvb_dmx_swfilter_packet(demux, buf);
473
buf += 188;
474
}
475
476
spin_unlock(&demux->lock);
477
}
478
479
EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
480
481
static inline int find_next_packet(const u8 *buf, int pos, size_t count,
482
const int pktsize)
483
{
484
int start = pos, lost;
485
486
while (pos < count) {
487
if (buf[pos] == 0x47 ||
488
(pktsize == 204 && buf[pos] == 0xB8))
489
break;
490
pos++;
491
}
492
493
lost = pos - start;
494
if (lost) {
495
/* This garbage is part of a valid packet? */
496
int backtrack = pos - pktsize;
497
if (backtrack >= 0 && (buf[backtrack] == 0x47 ||
498
(pktsize == 204 && buf[backtrack] == 0xB8)))
499
return backtrack;
500
}
501
502
return pos;
503
}
504
505
/* Filter all pktsize= 188 or 204 sized packets and skip garbage. */
506
static inline void _dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf,
507
size_t count, const int pktsize)
508
{
509
int p = 0, i, j;
510
const u8 *q;
511
512
spin_lock(&demux->lock);
513
514
if (demux->tsbufp) { /* tsbuf[0] is now 0x47. */
515
i = demux->tsbufp;
516
j = pktsize - i;
517
if (count < j) {
518
memcpy(&demux->tsbuf[i], buf, count);
519
demux->tsbufp += count;
520
goto bailout;
521
}
522
memcpy(&demux->tsbuf[i], buf, j);
523
if (demux->tsbuf[0] == 0x47) /* double check */
524
dvb_dmx_swfilter_packet(demux, demux->tsbuf);
525
demux->tsbufp = 0;
526
p += j;
527
}
528
529
while (1) {
530
p = find_next_packet(buf, p, count, pktsize);
531
if (p >= count)
532
break;
533
if (count - p < pktsize)
534
break;
535
536
q = &buf[p];
537
538
if (pktsize == 204 && (*q == 0xB8)) {
539
memcpy(demux->tsbuf, q, 188);
540
demux->tsbuf[0] = 0x47;
541
q = demux->tsbuf;
542
}
543
dvb_dmx_swfilter_packet(demux, q);
544
p += pktsize;
545
}
546
547
i = count - p;
548
if (i) {
549
memcpy(demux->tsbuf, &buf[p], i);
550
demux->tsbufp = i;
551
if (pktsize == 204 && demux->tsbuf[0] == 0xB8)
552
demux->tsbuf[0] = 0x47;
553
}
554
555
bailout:
556
spin_unlock(&demux->lock);
557
}
558
559
void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
560
{
561
_dvb_dmx_swfilter(demux, buf, count, 188);
562
}
563
EXPORT_SYMBOL(dvb_dmx_swfilter);
564
565
void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
566
{
567
_dvb_dmx_swfilter(demux, buf, count, 204);
568
}
569
EXPORT_SYMBOL(dvb_dmx_swfilter_204);
570
571
static struct dvb_demux_filter *dvb_dmx_filter_alloc(struct dvb_demux *demux)
572
{
573
int i;
574
575
for (i = 0; i < demux->filternum; i++)
576
if (demux->filter[i].state == DMX_STATE_FREE)
577
break;
578
579
if (i == demux->filternum)
580
return NULL;
581
582
demux->filter[i].state = DMX_STATE_ALLOCATED;
583
584
return &demux->filter[i];
585
}
586
587
static struct dvb_demux_feed *dvb_dmx_feed_alloc(struct dvb_demux *demux)
588
{
589
int i;
590
591
for (i = 0; i < demux->feednum; i++)
592
if (demux->feed[i].state == DMX_STATE_FREE)
593
break;
594
595
if (i == demux->feednum)
596
return NULL;
597
598
demux->feed[i].state = DMX_STATE_ALLOCATED;
599
600
return &demux->feed[i];
601
}
602
603
static int dvb_demux_feed_find(struct dvb_demux_feed *feed)
604
{
605
struct dvb_demux_feed *entry;
606
607
list_for_each_entry(entry, &feed->demux->feed_list, list_head)
608
if (entry == feed)
609
return 1;
610
611
return 0;
612
}
613
614
static void dvb_demux_feed_add(struct dvb_demux_feed *feed)
615
{
616
spin_lock_irq(&feed->demux->lock);
617
if (dvb_demux_feed_find(feed)) {
618
printk(KERN_ERR "%s: feed already in list (type=%x state=%x pid=%x)\n",
619
__func__, feed->type, feed->state, feed->pid);
620
goto out;
621
}
622
623
list_add(&feed->list_head, &feed->demux->feed_list);
624
out:
625
spin_unlock_irq(&feed->demux->lock);
626
}
627
628
static void dvb_demux_feed_del(struct dvb_demux_feed *feed)
629
{
630
spin_lock_irq(&feed->demux->lock);
631
if (!(dvb_demux_feed_find(feed))) {
632
printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n",
633
__func__, feed->type, feed->state, feed->pid);
634
goto out;
635
}
636
637
list_del(&feed->list_head);
638
out:
639
spin_unlock_irq(&feed->demux->lock);
640
}
641
642
static int dmx_ts_feed_set(struct dmx_ts_feed *ts_feed, u16 pid, int ts_type,
643
enum dmx_ts_pes pes_type,
644
size_t circular_buffer_size, struct timespec timeout)
645
{
646
struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
647
struct dvb_demux *demux = feed->demux;
648
649
if (pid > DMX_MAX_PID)
650
return -EINVAL;
651
652
if (mutex_lock_interruptible(&demux->mutex))
653
return -ERESTARTSYS;
654
655
if (ts_type & TS_DECODER) {
656
if (pes_type >= DMX_TS_PES_OTHER) {
657
mutex_unlock(&demux->mutex);
658
return -EINVAL;
659
}
660
661
if (demux->pesfilter[pes_type] &&
662
demux->pesfilter[pes_type] != feed) {
663
mutex_unlock(&demux->mutex);
664
return -EINVAL;
665
}
666
667
demux->pesfilter[pes_type] = feed;
668
demux->pids[pes_type] = pid;
669
}
670
671
dvb_demux_feed_add(feed);
672
673
feed->pid = pid;
674
feed->buffer_size = circular_buffer_size;
675
feed->timeout = timeout;
676
feed->ts_type = ts_type;
677
feed->pes_type = pes_type;
678
679
if (feed->buffer_size) {
680
#ifdef NOBUFS
681
feed->buffer = NULL;
682
#else
683
feed->buffer = vmalloc(feed->buffer_size);
684
if (!feed->buffer) {
685
mutex_unlock(&demux->mutex);
686
return -ENOMEM;
687
}
688
#endif
689
}
690
691
feed->state = DMX_STATE_READY;
692
mutex_unlock(&demux->mutex);
693
694
return 0;
695
}
696
697
static int dmx_ts_feed_start_filtering(struct dmx_ts_feed *ts_feed)
698
{
699
struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
700
struct dvb_demux *demux = feed->demux;
701
int ret;
702
703
if (mutex_lock_interruptible(&demux->mutex))
704
return -ERESTARTSYS;
705
706
if (feed->state != DMX_STATE_READY || feed->type != DMX_TYPE_TS) {
707
mutex_unlock(&demux->mutex);
708
return -EINVAL;
709
}
710
711
if (!demux->start_feed) {
712
mutex_unlock(&demux->mutex);
713
return -ENODEV;
714
}
715
716
if ((ret = demux->start_feed(feed)) < 0) {
717
mutex_unlock(&demux->mutex);
718
return ret;
719
}
720
721
spin_lock_irq(&demux->lock);
722
ts_feed->is_filtering = 1;
723
feed->state = DMX_STATE_GO;
724
spin_unlock_irq(&demux->lock);
725
mutex_unlock(&demux->mutex);
726
727
return 0;
728
}
729
730
static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed *ts_feed)
731
{
732
struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
733
struct dvb_demux *demux = feed->demux;
734
int ret;
735
736
mutex_lock(&demux->mutex);
737
738
if (feed->state < DMX_STATE_GO) {
739
mutex_unlock(&demux->mutex);
740
return -EINVAL;
741
}
742
743
if (!demux->stop_feed) {
744
mutex_unlock(&demux->mutex);
745
return -ENODEV;
746
}
747
748
ret = demux->stop_feed(feed);
749
750
spin_lock_irq(&demux->lock);
751
ts_feed->is_filtering = 0;
752
feed->state = DMX_STATE_ALLOCATED;
753
spin_unlock_irq(&demux->lock);
754
mutex_unlock(&demux->mutex);
755
756
return ret;
757
}
758
759
static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx,
760
struct dmx_ts_feed **ts_feed,
761
dmx_ts_cb callback)
762
{
763
struct dvb_demux *demux = (struct dvb_demux *)dmx;
764
struct dvb_demux_feed *feed;
765
766
if (mutex_lock_interruptible(&demux->mutex))
767
return -ERESTARTSYS;
768
769
if (!(feed = dvb_dmx_feed_alloc(demux))) {
770
mutex_unlock(&demux->mutex);
771
return -EBUSY;
772
}
773
774
feed->type = DMX_TYPE_TS;
775
feed->cb.ts = callback;
776
feed->demux = demux;
777
feed->pid = 0xffff;
778
feed->peslen = 0xfffa;
779
feed->buffer = NULL;
780
781
(*ts_feed) = &feed->feed.ts;
782
(*ts_feed)->parent = dmx;
783
(*ts_feed)->priv = NULL;
784
(*ts_feed)->is_filtering = 0;
785
(*ts_feed)->start_filtering = dmx_ts_feed_start_filtering;
786
(*ts_feed)->stop_filtering = dmx_ts_feed_stop_filtering;
787
(*ts_feed)->set = dmx_ts_feed_set;
788
789
if (!(feed->filter = dvb_dmx_filter_alloc(demux))) {
790
feed->state = DMX_STATE_FREE;
791
mutex_unlock(&demux->mutex);
792
return -EBUSY;
793
}
794
795
feed->filter->type = DMX_TYPE_TS;
796
feed->filter->feed = feed;
797
feed->filter->state = DMX_STATE_READY;
798
799
mutex_unlock(&demux->mutex);
800
801
return 0;
802
}
803
804
static int dvbdmx_release_ts_feed(struct dmx_demux *dmx,
805
struct dmx_ts_feed *ts_feed)
806
{
807
struct dvb_demux *demux = (struct dvb_demux *)dmx;
808
struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
809
810
mutex_lock(&demux->mutex);
811
812
if (feed->state == DMX_STATE_FREE) {
813
mutex_unlock(&demux->mutex);
814
return -EINVAL;
815
}
816
#ifndef NOBUFS
817
vfree(feed->buffer);
818
feed->buffer = NULL;
819
#endif
820
821
feed->state = DMX_STATE_FREE;
822
feed->filter->state = DMX_STATE_FREE;
823
824
dvb_demux_feed_del(feed);
825
826
feed->pid = 0xffff;
827
828
if (feed->ts_type & TS_DECODER && feed->pes_type < DMX_TS_PES_OTHER)
829
demux->pesfilter[feed->pes_type] = NULL;
830
831
mutex_unlock(&demux->mutex);
832
return 0;
833
}
834
835
/******************************************************************************
836
* dmx_section_feed API calls
837
******************************************************************************/
838
839
static int dmx_section_feed_allocate_filter(struct dmx_section_feed *feed,
840
struct dmx_section_filter **filter)
841
{
842
struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
843
struct dvb_demux *dvbdemux = dvbdmxfeed->demux;
844
struct dvb_demux_filter *dvbdmxfilter;
845
846
if (mutex_lock_interruptible(&dvbdemux->mutex))
847
return -ERESTARTSYS;
848
849
dvbdmxfilter = dvb_dmx_filter_alloc(dvbdemux);
850
if (!dvbdmxfilter) {
851
mutex_unlock(&dvbdemux->mutex);
852
return -EBUSY;
853
}
854
855
spin_lock_irq(&dvbdemux->lock);
856
*filter = &dvbdmxfilter->filter;
857
(*filter)->parent = feed;
858
(*filter)->priv = NULL;
859
dvbdmxfilter->feed = dvbdmxfeed;
860
dvbdmxfilter->type = DMX_TYPE_SEC;
861
dvbdmxfilter->state = DMX_STATE_READY;
862
dvbdmxfilter->next = dvbdmxfeed->filter;
863
dvbdmxfeed->filter = dvbdmxfilter;
864
spin_unlock_irq(&dvbdemux->lock);
865
866
mutex_unlock(&dvbdemux->mutex);
867
return 0;
868
}
869
870
static int dmx_section_feed_set(struct dmx_section_feed *feed,
871
u16 pid, size_t circular_buffer_size,
872
int check_crc)
873
{
874
struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
875
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
876
877
if (pid > 0x1fff)
878
return -EINVAL;
879
880
if (mutex_lock_interruptible(&dvbdmx->mutex))
881
return -ERESTARTSYS;
882
883
dvb_demux_feed_add(dvbdmxfeed);
884
885
dvbdmxfeed->pid = pid;
886
dvbdmxfeed->buffer_size = circular_buffer_size;
887
dvbdmxfeed->feed.sec.check_crc = check_crc;
888
889
#ifdef NOBUFS
890
dvbdmxfeed->buffer = NULL;
891
#else
892
dvbdmxfeed->buffer = vmalloc(dvbdmxfeed->buffer_size);
893
if (!dvbdmxfeed->buffer) {
894
mutex_unlock(&dvbdmx->mutex);
895
return -ENOMEM;
896
}
897
#endif
898
899
dvbdmxfeed->state = DMX_STATE_READY;
900
mutex_unlock(&dvbdmx->mutex);
901
return 0;
902
}
903
904
static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed)
905
{
906
int i;
907
struct dvb_demux_filter *f;
908
struct dmx_section_filter *sf;
909
u8 mask, mode, doneq;
910
911
if (!(f = dvbdmxfeed->filter))
912
return;
913
do {
914
sf = &f->filter;
915
doneq = 0;
916
for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
917
mode = sf->filter_mode[i];
918
mask = sf->filter_mask[i];
919
f->maskandmode[i] = mask & mode;
920
doneq |= f->maskandnotmode[i] = mask & ~mode;
921
}
922
f->doneq = doneq ? 1 : 0;
923
} while ((f = f->next));
924
}
925
926
static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed)
927
{
928
struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
929
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
930
int ret;
931
932
if (mutex_lock_interruptible(&dvbdmx->mutex))
933
return -ERESTARTSYS;
934
935
if (feed->is_filtering) {
936
mutex_unlock(&dvbdmx->mutex);
937
return -EBUSY;
938
}
939
940
if (!dvbdmxfeed->filter) {
941
mutex_unlock(&dvbdmx->mutex);
942
return -EINVAL;
943
}
944
945
dvbdmxfeed->feed.sec.tsfeedp = 0;
946
dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base;
947
dvbdmxfeed->feed.sec.secbufp = 0;
948
dvbdmxfeed->feed.sec.seclen = 0;
949
950
if (!dvbdmx->start_feed) {
951
mutex_unlock(&dvbdmx->mutex);
952
return -ENODEV;
953
}
954
955
prepare_secfilters(dvbdmxfeed);
956
957
if ((ret = dvbdmx->start_feed(dvbdmxfeed)) < 0) {
958
mutex_unlock(&dvbdmx->mutex);
959
return ret;
960
}
961
962
spin_lock_irq(&dvbdmx->lock);
963
feed->is_filtering = 1;
964
dvbdmxfeed->state = DMX_STATE_GO;
965
spin_unlock_irq(&dvbdmx->lock);
966
967
mutex_unlock(&dvbdmx->mutex);
968
return 0;
969
}
970
971
static int dmx_section_feed_stop_filtering(struct dmx_section_feed *feed)
972
{
973
struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
974
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
975
int ret;
976
977
mutex_lock(&dvbdmx->mutex);
978
979
if (!dvbdmx->stop_feed) {
980
mutex_unlock(&dvbdmx->mutex);
981
return -ENODEV;
982
}
983
984
ret = dvbdmx->stop_feed(dvbdmxfeed);
985
986
spin_lock_irq(&dvbdmx->lock);
987
dvbdmxfeed->state = DMX_STATE_READY;
988
feed->is_filtering = 0;
989
spin_unlock_irq(&dvbdmx->lock);
990
991
mutex_unlock(&dvbdmx->mutex);
992
return ret;
993
}
994
995
static int dmx_section_feed_release_filter(struct dmx_section_feed *feed,
996
struct dmx_section_filter *filter)
997
{
998
struct dvb_demux_filter *dvbdmxfilter = (struct dvb_demux_filter *)filter, *f;
999
struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
1000
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
1001
1002
mutex_lock(&dvbdmx->mutex);
1003
1004
if (dvbdmxfilter->feed != dvbdmxfeed) {
1005
mutex_unlock(&dvbdmx->mutex);
1006
return -EINVAL;
1007
}
1008
1009
if (feed->is_filtering)
1010
feed->stop_filtering(feed);
1011
1012
spin_lock_irq(&dvbdmx->lock);
1013
f = dvbdmxfeed->filter;
1014
1015
if (f == dvbdmxfilter) {
1016
dvbdmxfeed->filter = dvbdmxfilter->next;
1017
} else {
1018
while (f->next != dvbdmxfilter)
1019
f = f->next;
1020
f->next = f->next->next;
1021
}
1022
1023
dvbdmxfilter->state = DMX_STATE_FREE;
1024
spin_unlock_irq(&dvbdmx->lock);
1025
mutex_unlock(&dvbdmx->mutex);
1026
return 0;
1027
}
1028
1029
static int dvbdmx_allocate_section_feed(struct dmx_demux *demux,
1030
struct dmx_section_feed **feed,
1031
dmx_section_cb callback)
1032
{
1033
struct dvb_demux *dvbdmx = (struct dvb_demux *)demux;
1034
struct dvb_demux_feed *dvbdmxfeed;
1035
1036
if (mutex_lock_interruptible(&dvbdmx->mutex))
1037
return -ERESTARTSYS;
1038
1039
if (!(dvbdmxfeed = dvb_dmx_feed_alloc(dvbdmx))) {
1040
mutex_unlock(&dvbdmx->mutex);
1041
return -EBUSY;
1042
}
1043
1044
dvbdmxfeed->type = DMX_TYPE_SEC;
1045
dvbdmxfeed->cb.sec = callback;
1046
dvbdmxfeed->demux = dvbdmx;
1047
dvbdmxfeed->pid = 0xffff;
1048
dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base;
1049
dvbdmxfeed->feed.sec.secbufp = dvbdmxfeed->feed.sec.seclen = 0;
1050
dvbdmxfeed->feed.sec.tsfeedp = 0;
1051
dvbdmxfeed->filter = NULL;
1052
dvbdmxfeed->buffer = NULL;
1053
1054
(*feed) = &dvbdmxfeed->feed.sec;
1055
(*feed)->is_filtering = 0;
1056
(*feed)->parent = demux;
1057
(*feed)->priv = NULL;
1058
1059
(*feed)->set = dmx_section_feed_set;
1060
(*feed)->allocate_filter = dmx_section_feed_allocate_filter;
1061
(*feed)->start_filtering = dmx_section_feed_start_filtering;
1062
(*feed)->stop_filtering = dmx_section_feed_stop_filtering;
1063
(*feed)->release_filter = dmx_section_feed_release_filter;
1064
1065
mutex_unlock(&dvbdmx->mutex);
1066
return 0;
1067
}
1068
1069
static int dvbdmx_release_section_feed(struct dmx_demux *demux,
1070
struct dmx_section_feed *feed)
1071
{
1072
struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
1073
struct dvb_demux *dvbdmx = (struct dvb_demux *)demux;
1074
1075
mutex_lock(&dvbdmx->mutex);
1076
1077
if (dvbdmxfeed->state == DMX_STATE_FREE) {
1078
mutex_unlock(&dvbdmx->mutex);
1079
return -EINVAL;
1080
}
1081
#ifndef NOBUFS
1082
vfree(dvbdmxfeed->buffer);
1083
dvbdmxfeed->buffer = NULL;
1084
#endif
1085
dvbdmxfeed->state = DMX_STATE_FREE;
1086
1087
dvb_demux_feed_del(dvbdmxfeed);
1088
1089
dvbdmxfeed->pid = 0xffff;
1090
1091
mutex_unlock(&dvbdmx->mutex);
1092
return 0;
1093
}
1094
1095
/******************************************************************************
1096
* dvb_demux kernel data API calls
1097
******************************************************************************/
1098
1099
static int dvbdmx_open(struct dmx_demux *demux)
1100
{
1101
struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
1102
1103
if (dvbdemux->users >= MAX_DVB_DEMUX_USERS)
1104
return -EUSERS;
1105
1106
dvbdemux->users++;
1107
return 0;
1108
}
1109
1110
static int dvbdmx_close(struct dmx_demux *demux)
1111
{
1112
struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
1113
1114
if (dvbdemux->users == 0)
1115
return -ENODEV;
1116
1117
dvbdemux->users--;
1118
//FIXME: release any unneeded resources if users==0
1119
return 0;
1120
}
1121
1122
static int dvbdmx_write(struct dmx_demux *demux, const char __user *buf, size_t count)
1123
{
1124
struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
1125
void *p;
1126
1127
if ((!demux->frontend) || (demux->frontend->source != DMX_MEMORY_FE))
1128
return -EINVAL;
1129
1130
p = memdup_user(buf, count);
1131
if (IS_ERR(p))
1132
return PTR_ERR(p);
1133
if (mutex_lock_interruptible(&dvbdemux->mutex)) {
1134
kfree(p);
1135
return -ERESTARTSYS;
1136
}
1137
dvb_dmx_swfilter(dvbdemux, p, count);
1138
kfree(p);
1139
mutex_unlock(&dvbdemux->mutex);
1140
1141
if (signal_pending(current))
1142
return -EINTR;
1143
return count;
1144
}
1145
1146
static int dvbdmx_add_frontend(struct dmx_demux *demux,
1147
struct dmx_frontend *frontend)
1148
{
1149
struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
1150
struct list_head *head = &dvbdemux->frontend_list;
1151
1152
list_add(&(frontend->connectivity_list), head);
1153
1154
return 0;
1155
}
1156
1157
static int dvbdmx_remove_frontend(struct dmx_demux *demux,
1158
struct dmx_frontend *frontend)
1159
{
1160
struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
1161
struct list_head *pos, *n, *head = &dvbdemux->frontend_list;
1162
1163
list_for_each_safe(pos, n, head) {
1164
if (DMX_FE_ENTRY(pos) == frontend) {
1165
list_del(pos);
1166
return 0;
1167
}
1168
}
1169
1170
return -ENODEV;
1171
}
1172
1173
static struct list_head *dvbdmx_get_frontends(struct dmx_demux *demux)
1174
{
1175
struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
1176
1177
if (list_empty(&dvbdemux->frontend_list))
1178
return NULL;
1179
1180
return &dvbdemux->frontend_list;
1181
}
1182
1183
static int dvbdmx_connect_frontend(struct dmx_demux *demux,
1184
struct dmx_frontend *frontend)
1185
{
1186
struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
1187
1188
if (demux->frontend)
1189
return -EINVAL;
1190
1191
mutex_lock(&dvbdemux->mutex);
1192
1193
demux->frontend = frontend;
1194
mutex_unlock(&dvbdemux->mutex);
1195
return 0;
1196
}
1197
1198
static int dvbdmx_disconnect_frontend(struct dmx_demux *demux)
1199
{
1200
struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
1201
1202
mutex_lock(&dvbdemux->mutex);
1203
1204
demux->frontend = NULL;
1205
mutex_unlock(&dvbdemux->mutex);
1206
return 0;
1207
}
1208
1209
static int dvbdmx_get_pes_pids(struct dmx_demux *demux, u16 * pids)
1210
{
1211
struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
1212
1213
memcpy(pids, dvbdemux->pids, 5 * sizeof(u16));
1214
return 0;
1215
}
1216
1217
int dvb_dmx_init(struct dvb_demux *dvbdemux)
1218
{
1219
int i;
1220
struct dmx_demux *dmx = &dvbdemux->dmx;
1221
1222
dvbdemux->cnt_storage = NULL;
1223
dvbdemux->users = 0;
1224
dvbdemux->filter = vmalloc(dvbdemux->filternum * sizeof(struct dvb_demux_filter));
1225
1226
if (!dvbdemux->filter)
1227
return -ENOMEM;
1228
1229
dvbdemux->feed = vmalloc(dvbdemux->feednum * sizeof(struct dvb_demux_feed));
1230
if (!dvbdemux->feed) {
1231
vfree(dvbdemux->filter);
1232
dvbdemux->filter = NULL;
1233
return -ENOMEM;
1234
}
1235
for (i = 0; i < dvbdemux->filternum; i++) {
1236
dvbdemux->filter[i].state = DMX_STATE_FREE;
1237
dvbdemux->filter[i].index = i;
1238
}
1239
for (i = 0; i < dvbdemux->feednum; i++) {
1240
dvbdemux->feed[i].state = DMX_STATE_FREE;
1241
dvbdemux->feed[i].index = i;
1242
}
1243
1244
dvbdemux->cnt_storage = vmalloc(MAX_PID + 1);
1245
if (!dvbdemux->cnt_storage)
1246
printk(KERN_WARNING "Couldn't allocate memory for TS/TEI check. Disabling it\n");
1247
1248
INIT_LIST_HEAD(&dvbdemux->frontend_list);
1249
1250
for (i = 0; i < DMX_TS_PES_OTHER; i++) {
1251
dvbdemux->pesfilter[i] = NULL;
1252
dvbdemux->pids[i] = 0xffff;
1253
}
1254
1255
INIT_LIST_HEAD(&dvbdemux->feed_list);
1256
1257
dvbdemux->playing = 0;
1258
dvbdemux->recording = 0;
1259
dvbdemux->tsbufp = 0;
1260
1261
if (!dvbdemux->check_crc32)
1262
dvbdemux->check_crc32 = dvb_dmx_crc32;
1263
1264
if (!dvbdemux->memcopy)
1265
dvbdemux->memcopy = dvb_dmx_memcopy;
1266
1267
dmx->frontend = NULL;
1268
dmx->priv = dvbdemux;
1269
dmx->open = dvbdmx_open;
1270
dmx->close = dvbdmx_close;
1271
dmx->write = dvbdmx_write;
1272
dmx->allocate_ts_feed = dvbdmx_allocate_ts_feed;
1273
dmx->release_ts_feed = dvbdmx_release_ts_feed;
1274
dmx->allocate_section_feed = dvbdmx_allocate_section_feed;
1275
dmx->release_section_feed = dvbdmx_release_section_feed;
1276
1277
dmx->add_frontend = dvbdmx_add_frontend;
1278
dmx->remove_frontend = dvbdmx_remove_frontend;
1279
dmx->get_frontends = dvbdmx_get_frontends;
1280
dmx->connect_frontend = dvbdmx_connect_frontend;
1281
dmx->disconnect_frontend = dvbdmx_disconnect_frontend;
1282
dmx->get_pes_pids = dvbdmx_get_pes_pids;
1283
1284
mutex_init(&dvbdemux->mutex);
1285
spin_lock_init(&dvbdemux->lock);
1286
1287
return 0;
1288
}
1289
1290
EXPORT_SYMBOL(dvb_dmx_init);
1291
1292
void dvb_dmx_release(struct dvb_demux *dvbdemux)
1293
{
1294
vfree(dvbdemux->cnt_storage);
1295
vfree(dvbdemux->filter);
1296
vfree(dvbdemux->feed);
1297
}
1298
1299
EXPORT_SYMBOL(dvb_dmx_release);
1300
1301