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