2 * dvb_demux.c - DVB kernel demux API
4 * Copyright (C) 2000-2001 Ralph Metzler <ralph@convergence.de>
5 * & Marcus Metzler <marcus@convergence.de>
6 * for convergence integrated media GmbH
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.
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.
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.
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>
33 #include "dvb_demux.h"
34 #include "dvb_functions.h"
38 ** #define DVB_DEMUX_SECTION_LOSS_LOG to monitor payload loss in the syslog
40 // #define DVB_DEMUX_SECTION_LOSS_LOG
46 int dmx_register_demux(struct dmx_demux
*demux
)
49 list_add(&demux
->reg_list
, &dmx_muxs
);
53 int dmx_unregister_demux(struct dmx_demux
* demux
)
55 struct list_head
*pos
, *n
, *head
=&dmx_muxs
;
57 list_for_each_safe (pos
, n
, head
) {
58 if (DMX_DIR_ENTRY(pos
) == demux
) {
70 struct list_head
*dmx_get_demuxes(void)
72 if (list_empty(&dmx_muxs
))
78 /******************************************************************************
79 * static inlined helper functions
80 ******************************************************************************/
83 static inline u16
section_length(const u8
*buf
)
85 return 3+((buf
[1]&0x0f)<<8)+buf
[2];
89 static inline u16
ts_pid(const u8
*buf
)
91 return ((buf
[1]&0x1f)<<8)+buf
[2];
95 static inline u8
payload(const u8
*tsp
)
97 if (!(tsp
[3]&0x10)) // no payload?
99 if (tsp
[3]&0x20) { // adaptation field?
100 if (tsp
[4]>183) // corrupted data?
109 void dvb_set_crc32(u8
*data
, int length
)
113 crc
= crc32_be(~0, data
, length
);
115 data
[length
] = (crc
>> 24) & 0xff;
116 data
[length
+1] = (crc
>> 16) & 0xff;
117 data
[length
+2] = (crc
>> 8) & 0xff;
118 data
[length
+3] = (crc
) & 0xff;
122 static u32
dvb_dmx_crc32 (struct dvb_demux_feed
*f
, const u8
*src
, size_t len
)
124 return (f
->feed
.sec
.crc_val
= crc32_be (f
->feed
.sec
.crc_val
, src
, len
));
128 static void dvb_dmx_memcopy (struct dvb_demux_feed
*f
, u8
*d
, const u8
*s
, size_t len
)
134 /******************************************************************************
135 * Software filter functions
136 ******************************************************************************/
138 static inline int dvb_dmx_swfilter_payload (struct dvb_demux_feed
*feed
, const u8
*buf
)
140 int count
= payload(buf
);
152 ccok=((dvbdmxfeed->cc+1)&0x0f)==cc ? 1 : 0;
155 printk("missed packet!\n");
158 if (buf
[1] & 0x40) // PUSI ?
159 feed
->peslen
= 0xfffa;
161 feed
->peslen
+= count
;
163 return feed
->cb
.ts (&buf
[p
], count
, NULL
, 0, &feed
->feed
.ts
, DMX_OK
);
167 static int dvb_dmx_swfilter_sectionfilter (struct dvb_demux_feed
*feed
,
168 struct dvb_demux_filter
*f
)
173 for (i
=0; i
<DVB_DEMUX_MASK_MAX
; i
++) {
174 u8
xor = f
->filter
.filter_value
[i
] ^ feed
->feed
.sec
.secbuf
[i
];
176 if (f
->maskandmode
[i
] & xor)
179 neq
|= f
->maskandnotmode
[i
] & xor;
182 if (f
->doneq
&& !neq
)
185 return feed
->cb
.sec (feed
->feed
.sec
.secbuf
, feed
->feed
.sec
.seclen
,
186 NULL
, 0, &f
->filter
, DMX_OK
);
190 static inline int dvb_dmx_swfilter_section_feed (struct dvb_demux_feed
*feed
)
192 struct dvb_demux
*demux
= feed
->demux
;
193 struct dvb_demux_filter
*f
= feed
->filter
;
194 struct dmx_section_feed
*sec
= &feed
->feed
.sec
;
195 int section_syntax_indicator
;
197 if (!sec
->is_filtering
)
203 if (sec
->check_crc
) {
204 section_syntax_indicator
= ((sec
->secbuf
[1] & 0x80) != 0);
205 if (section_syntax_indicator
&&
206 demux
->check_crc32(feed
, sec
->secbuf
, sec
->seclen
))
211 if (dvb_dmx_swfilter_sectionfilter(feed
, f
) < 0)
213 } while ((f
= f
->next
) && sec
->is_filtering
);
221 static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed
*feed
)
223 struct dmx_section_feed
*sec
= &feed
->feed
.sec
;
225 #ifdef DVB_DEMUX_SECTION_LOSS_LOG
226 if(sec
->secbufp
< sec
->tsfeedp
)
228 int i
, n
= sec
->tsfeedp
- sec
->secbufp
;
230 /* section padding is done with 0xff bytes entirely.
231 ** due to speed reasons, we won't check all of them
232 ** but just first and last
234 if(sec
->secbuf
[0] != 0xff || sec
->secbuf
[n
-1] != 0xff)
236 printk("dvb_demux.c section ts padding loss: %d/%d\n",
238 printk("dvb_demux.c pad data:");
239 for(i
= 0; i
< n
; i
++)
240 printk(" %02x", sec
->secbuf
[i
]);
246 sec
->tsfeedp
= sec
->secbufp
= sec
->seclen
= 0;
247 sec
->secbuf
= sec
->secbuf_base
;
251 ** Losless Section Demux 1.4 by Emard
253 static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed
*feed
, const u8
*buf
, u8 len
)
255 struct dvb_demux
*demux
= feed
->demux
;
256 struct dmx_section_feed
*sec
= &feed
->feed
.sec
;
257 u16 limit
, seclen
, n
;
259 if(sec
->tsfeedp
>= DMX_MAX_SECFEED_SIZE
)
262 if(sec
->tsfeedp
+ len
> DMX_MAX_SECFEED_SIZE
)
264 #ifdef DVB_DEMUX_SECTION_LOSS_LOG
265 printk("dvb_demux.c section buffer full loss: %d/%d\n",
266 sec
->tsfeedp
+ len
- DMX_MAX_SECFEED_SIZE
, DMX_MAX_SECFEED_SIZE
);
268 len
= DMX_MAX_SECFEED_SIZE
- sec
->tsfeedp
;
274 demux
->memcopy(feed
, sec
->secbuf_base
+ sec
->tsfeedp
, buf
, len
);
277 /* -----------------------------------------------------
278 ** Dump all the sections we can find in the data (Emard)
281 limit
= sec
->tsfeedp
;
282 if(limit
> DMX_MAX_SECFEED_SIZE
)
283 return -1; /* internal error should never happen */
285 /* to be sure always set secbuf */
286 sec
->secbuf
= sec
->secbuf_base
+ sec
->secbufp
;
288 for(n
= 0; sec
->secbufp
+ 2 < limit
; n
++)
290 seclen
= section_length(sec
->secbuf
);
291 if(seclen
<= 0 || seclen
> DMX_MAX_SECFEED_SIZE
292 || seclen
+ sec
->secbufp
> limit
)
294 sec
->seclen
= seclen
;
296 /* dump [secbuf .. secbuf+seclen) */
297 dvb_dmx_swfilter_section_feed(feed
);
298 sec
->secbufp
+= seclen
; /* secbufp and secbuf moving together is */
299 sec
->secbuf
+= seclen
; /* redundand but saves pointer arithmetic */
306 static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed
*feed
, const u8
*buf
)
312 count
= payload(buf
);
314 if (count
== 0) /* count == 0 if no payload or out of range */
317 p
= 188-count
; /* payload start */
320 ccok
= ((feed
->cc
+1) & 0x0f) == cc
? 1 : 0;
324 #ifdef DVB_DEMUX_SECTION_LOSS_LOG
325 printk("dvb_demux.c discontinuity detected %d bytes lost\n", count
);
326 /* those bytes under sume circumstances will again be reported
327 ** in the following dvb_dmx_swfilter_section_new
330 dvb_dmx_swfilter_section_new(feed
);
336 // PUSI=1 (is set), section boundary is here
337 if(count
> 1 && buf
[p
] < count
)
339 const u8
*before
= buf
+p
+1;
340 u8 before_len
= buf
[p
];
341 const u8
*after
= before
+before_len
;
342 u8 after_len
= count
-1-before_len
;
344 dvb_dmx_swfilter_section_copy_dump(feed
, before
, before_len
);
345 dvb_dmx_swfilter_section_new(feed
);
346 dvb_dmx_swfilter_section_copy_dump(feed
, after
, after_len
);
348 #ifdef DVB_DEMUX_SECTION_LOSS_LOG
351 printk("dvb_demux.c PUSI=1 but %d bytes lost\n", count
);
356 // PUSI=0 (is not set), no section boundary
357 const u8
*entire
= buf
+p
;
358 u8 entire_len
= count
;
360 dvb_dmx_swfilter_section_copy_dump(feed
, entire
, entire_len
);
366 static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed
*feed
, const u8
*buf
)
370 if (!feed
->feed
.ts
.is_filtering
)
372 if (feed
->ts_type
& TS_PACKET
) {
373 if (feed
->ts_type
& TS_PAYLOAD_ONLY
)
374 dvb_dmx_swfilter_payload(feed
, buf
);
376 feed
->cb
.ts(buf
, 188, NULL
, 0, &feed
->feed
.ts
, DMX_OK
);
378 if (feed
->ts_type
& TS_DECODER
)
379 if (feed
->demux
->write_to_decoder
)
380 feed
->demux
->write_to_decoder(feed
, buf
, 188);
384 if (!feed
->feed
.sec
.is_filtering
)
386 if (dvb_dmx_swfilter_section_packet(feed
, buf
) < 0)
387 feed
->feed
.sec
.seclen
= feed
->feed
.sec
.secbufp
=0;
395 #define DVR_FEED(f) \
396 (((f)->type == DMX_TYPE_TS) && \
397 ((f)->feed.ts.is_filtering) && \
398 (((f)->ts_type & (TS_PACKET|TS_PAYLOAD_ONLY)) == TS_PACKET))
400 void dvb_dmx_swfilter_packet(struct dvb_demux
*demux
, const u8
*buf
)
402 struct dvb_demux_feed
*feed
;
403 struct list_head
*pos
, *head
=&demux
->feed_list
;
404 u16 pid
= ts_pid(buf
);
407 list_for_each(pos
, head
) {
408 feed
= list_entry(pos
, struct dvb_demux_feed
, list_head
);
410 if ((feed
->pid
!= pid
) && (feed
->pid
!= 0x2000))
413 /* copy each packet only once to the dvr device, even
414 * if a PID is in multiple filters (e.g. video + PCR) */
415 if ((DVR_FEED(feed
)) && (dvr_done
++))
418 if (feed
->pid
== pid
) {
419 dvb_dmx_swfilter_packet_type (feed
, buf
);
424 if (feed
->pid
== 0x2000)
425 feed
->cb
.ts(buf
, 188, NULL
, 0, &feed
->feed
.ts
, DMX_OK
);
430 void dvb_dmx_swfilter_packets(struct dvb_demux
*demux
, const u8
*buf
, size_t count
)
432 spin_lock(&demux
->lock
);
436 dvb_dmx_swfilter_packet(demux
, buf
);
441 spin_unlock(&demux
->lock
);
445 void dvb_dmx_swfilter(struct dvb_demux
*demux
, const u8
*buf
, size_t count
)
449 spin_lock(&demux
->lock
);
451 if ((i
= demux
->tsbufp
)) {
452 if (count
< (j
=188-i
)) {
453 memcpy(&demux
->tsbuf
[i
], buf
, count
);
454 demux
->tsbufp
+= count
;
457 memcpy(&demux
->tsbuf
[i
], buf
, j
);
458 if (demux
->tsbuf
[0] == 0x47)
459 dvb_dmx_swfilter_packet(demux
, demux
->tsbuf
);
465 if (buf
[p
] == 0x47) {
466 if (count
-p
>= 188) {
467 dvb_dmx_swfilter_packet(demux
, buf
+p
);
471 memcpy(demux
->tsbuf
, buf
+p
, i
);
480 spin_unlock(&demux
->lock
);
483 void dvb_dmx_swfilter_204(struct dvb_demux
*demux
, const u8
*buf
, size_t count
)
487 spin_lock(&demux
->lock
);
489 if ((i
= demux
->tsbufp
)) {
490 if (count
< (j
=204-i
)) {
491 memcpy(&demux
->tsbuf
[i
], buf
, count
);
492 demux
->tsbufp
+= count
;
495 memcpy(&demux
->tsbuf
[i
], buf
, j
);
496 if ((demux
->tsbuf
[0] == 0x47)|(demux
->tsbuf
[0]==0xB8)) {
497 memcpy(tmppack
, demux
->tsbuf
, 188);
498 if (tmppack
[0] == 0xB8) tmppack
[0] = 0x47;
499 dvb_dmx_swfilter_packet(demux
, tmppack
);
506 if ((buf
[p
] == 0x47)|(buf
[p
] == 0xB8)) {
507 if (count
-p
>= 204) {
508 memcpy(tmppack
, buf
+p
, 188);
509 if (tmppack
[0] == 0xB8) tmppack
[0] = 0x47;
510 dvb_dmx_swfilter_packet(demux
, tmppack
);
514 memcpy(demux
->tsbuf
, buf
+p
, i
);
524 spin_unlock(&demux
->lock
);
528 static struct dvb_demux_filter
* dvb_dmx_filter_alloc(struct dvb_demux
*demux
)
532 for (i
=0; i
<demux
->filternum
; i
++)
533 if (demux
->filter
[i
].state
== DMX_STATE_FREE
)
536 if (i
== demux
->filternum
)
539 demux
->filter
[i
].state
= DMX_STATE_ALLOCATED
;
541 return &demux
->filter
[i
];
544 static struct dvb_demux_feed
* dvb_dmx_feed_alloc(struct dvb_demux
*demux
)
548 for (i
=0; i
<demux
->feednum
; i
++)
549 if (demux
->feed
[i
].state
== DMX_STATE_FREE
)
552 if (i
== demux
->feednum
)
555 demux
->feed
[i
].state
= DMX_STATE_ALLOCATED
;
557 return &demux
->feed
[i
];
560 static int dvb_demux_feed_find(struct dvb_demux_feed
*feed
)
562 struct dvb_demux_feed
*entry
;
564 list_for_each_entry(entry
, &feed
->demux
->feed_list
, list_head
)
571 static void dvb_demux_feed_add(struct dvb_demux_feed
*feed
)
573 if (dvb_demux_feed_find(feed
)) {
574 printk(KERN_ERR
"%s: feed already in list (type=%x state=%x pid=%x)\n",
575 __FUNCTION__
, feed
->type
, feed
->state
, feed
->pid
);
579 list_add(&feed
->list_head
, &feed
->demux
->feed_list
);
582 static void dvb_demux_feed_del(struct dvb_demux_feed
*feed
)
584 if (!(dvb_demux_feed_find(feed
))) {
585 printk(KERN_ERR
"%s: feed not in list (type=%x state=%x pid=%x)\n",
586 __FUNCTION__
, feed
->type
, feed
->state
, feed
->pid
);
590 list_del(&feed
->list_head
);
593 static int dmx_ts_feed_set (struct dmx_ts_feed
* ts_feed
, u16 pid
, int ts_type
,
594 enum dmx_ts_pes pes_type
, size_t callback_length
,
595 size_t circular_buffer_size
, int descramble
,
596 struct timespec timeout
)
598 struct dvb_demux_feed
*feed
= (struct dvb_demux_feed
*) ts_feed
;
599 struct dvb_demux
*demux
= feed
->demux
;
601 if (pid
> DMX_MAX_PID
)
604 if (down_interruptible (&demux
->mutex
))
607 if (ts_type
& TS_DECODER
) {
608 if (pes_type
>= DMX_TS_PES_OTHER
) {
613 if (demux
->pesfilter
[pes_type
] &&
614 demux
->pesfilter
[pes_type
] != feed
) {
619 demux
->pesfilter
[pes_type
] = feed
;
620 demux
->pids
[pes_type
] = pid
;
623 dvb_demux_feed_add(feed
);
626 feed
->buffer_size
= circular_buffer_size
;
627 feed
->descramble
= descramble
;
628 feed
->timeout
= timeout
;
629 feed
->cb_length
= callback_length
;
630 feed
->ts_type
= ts_type
;
631 feed
->pes_type
= pes_type
;
633 if (feed
->descramble
) {
638 if (feed
->buffer_size
) {
642 feed
->buffer
= vmalloc(feed
->buffer_size
);
650 feed
->state
= DMX_STATE_READY
;
657 static int dmx_ts_feed_start_filtering(struct dmx_ts_feed
* ts_feed
)
659 struct dvb_demux_feed
*feed
= (struct dvb_demux_feed
*) ts_feed
;
660 struct dvb_demux
*demux
= feed
->demux
;
663 if (down_interruptible (&demux
->mutex
))
666 if (feed
->state
!= DMX_STATE_READY
|| feed
->type
!= DMX_TYPE_TS
) {
671 if (!demux
->start_feed
) {
676 if ((ret
= demux
->start_feed(feed
)) < 0) {
681 spin_lock_irq(&demux
->lock
);
682 ts_feed
->is_filtering
= 1;
683 feed
->state
= DMX_STATE_GO
;
684 spin_unlock_irq(&demux
->lock
);
690 static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed
* ts_feed
)
692 struct dvb_demux_feed
*feed
= (struct dvb_demux_feed
*) ts_feed
;
693 struct dvb_demux
*demux
= feed
->demux
;
696 if (down_interruptible (&demux
->mutex
))
699 if (feed
->state
<DMX_STATE_GO
) {
704 if (!demux
->stop_feed
) {
709 ret
= demux
->stop_feed(feed
);
711 spin_lock_irq(&demux
->lock
);
712 ts_feed
->is_filtering
= 0;
713 feed
->state
= DMX_STATE_ALLOCATED
;
714 spin_unlock_irq(&demux
->lock
);
720 static int dvbdmx_allocate_ts_feed (struct dmx_demux
*dmx
, struct dmx_ts_feed
**ts_feed
,
723 struct dvb_demux
*demux
= (struct dvb_demux
*) dmx
;
724 struct dvb_demux_feed
*feed
;
726 if (down_interruptible (&demux
->mutex
))
729 if (!(feed
= dvb_dmx_feed_alloc(demux
))) {
734 feed
->type
= DMX_TYPE_TS
;
735 feed
->cb
.ts
= callback
;
738 feed
->peslen
= 0xfffa;
741 (*ts_feed
) = &feed
->feed
.ts
;
742 (*ts_feed
)->parent
= dmx
;
743 (*ts_feed
)->priv
= NULL
;
744 (*ts_feed
)->is_filtering
= 0;
745 (*ts_feed
)->start_filtering
= dmx_ts_feed_start_filtering
;
746 (*ts_feed
)->stop_filtering
= dmx_ts_feed_stop_filtering
;
747 (*ts_feed
)->set
= dmx_ts_feed_set
;
750 if (!(feed
->filter
= dvb_dmx_filter_alloc(demux
))) {
751 feed
->state
= DMX_STATE_FREE
;
756 feed
->filter
->type
= DMX_TYPE_TS
;
757 feed
->filter
->feed
= feed
;
758 feed
->filter
->state
= DMX_STATE_READY
;
765 static int dvbdmx_release_ts_feed(struct dmx_demux
*dmx
, struct dmx_ts_feed
*ts_feed
)
767 struct dvb_demux
*demux
= (struct dvb_demux
*) dmx
;
768 struct dvb_demux_feed
*feed
= (struct dvb_demux_feed
*) ts_feed
;
770 if (down_interruptible (&demux
->mutex
))
773 if (feed
->state
== DMX_STATE_FREE
) {
785 feed
->state
= DMX_STATE_FREE
;
786 feed
->filter
->state
= DMX_STATE_FREE
;
788 dvb_demux_feed_del(feed
);
792 if (feed
->ts_type
& TS_DECODER
)
793 demux
->pesfilter
[feed
->pes_type
] = NULL
;
800 /******************************************************************************
801 * dmx_section_feed API calls
802 ******************************************************************************/
804 static int dmx_section_feed_allocate_filter(struct dmx_section_feed
* feed
,
805 struct dmx_section_filter
** filter
)
807 struct dvb_demux_feed
*dvbdmxfeed
=(struct dvb_demux_feed
*) feed
;
808 struct dvb_demux
*dvbdemux
=dvbdmxfeed
->demux
;
809 struct dvb_demux_filter
*dvbdmxfilter
;
811 if (down_interruptible (&dvbdemux
->mutex
))
814 dvbdmxfilter
=dvb_dmx_filter_alloc(dvbdemux
);
816 up(&dvbdemux
->mutex
);
820 spin_lock_irq(&dvbdemux
->lock
);
821 *filter
=&dvbdmxfilter
->filter
;
822 (*filter
)->parent
=feed
;
823 (*filter
)->priv
=NULL
;
824 dvbdmxfilter
->feed
=dvbdmxfeed
;
825 dvbdmxfilter
->type
=DMX_TYPE_SEC
;
826 dvbdmxfilter
->state
=DMX_STATE_READY
;
828 dvbdmxfilter
->next
=dvbdmxfeed
->filter
;
829 dvbdmxfeed
->filter
=dvbdmxfilter
;
830 spin_unlock_irq(&dvbdemux
->lock
);
831 up(&dvbdemux
->mutex
);
836 static int dmx_section_feed_set(struct dmx_section_feed
* feed
,
837 u16 pid
, size_t circular_buffer_size
,
838 int descramble
, int check_crc
)
840 struct dvb_demux_feed
*dvbdmxfeed
=(struct dvb_demux_feed
*) feed
;
841 struct dvb_demux
*dvbdmx
=dvbdmxfeed
->demux
;
846 if (down_interruptible (&dvbdmx
->mutex
))
849 dvb_demux_feed_add(dvbdmxfeed
);
851 dvbdmxfeed
->pid
= pid
;
852 dvbdmxfeed
->buffer_size
=circular_buffer_size
;
853 dvbdmxfeed
->descramble
=descramble
;
854 if (dvbdmxfeed
->descramble
) {
859 dvbdmxfeed
->feed
.sec
.check_crc
=check_crc
;
861 dvbdmxfeed
->buffer
=NULL
;
863 dvbdmxfeed
->buffer
=vmalloc(dvbdmxfeed
->buffer_size
);
864 if (!dvbdmxfeed
->buffer
) {
869 dvbdmxfeed
->state
=DMX_STATE_READY
;
874 static void prepare_secfilters(struct dvb_demux_feed
*dvbdmxfeed
)
877 struct dvb_demux_filter
*f
;
878 struct dmx_section_filter
*sf
;
879 u8 mask
, mode
, doneq
;
881 if (!(f
=dvbdmxfeed
->filter
))
886 for (i
=0; i
<DVB_DEMUX_MASK_MAX
; i
++) {
887 mode
=sf
->filter_mode
[i
];
888 mask
=sf
->filter_mask
[i
];
889 f
->maskandmode
[i
]=mask
&mode
;
890 doneq
|=f
->maskandnotmode
[i
]=mask
&~mode
;
892 f
->doneq
=doneq
? 1 : 0;
893 } while ((f
=f
->next
));
897 static int dmx_section_feed_start_filtering(struct dmx_section_feed
*feed
)
899 struct dvb_demux_feed
*dvbdmxfeed
=(struct dvb_demux_feed
*) feed
;
900 struct dvb_demux
*dvbdmx
=dvbdmxfeed
->demux
;
903 if (down_interruptible (&dvbdmx
->mutex
))
906 if (feed
->is_filtering
) {
910 if (!dvbdmxfeed
->filter
) {
915 dvbdmxfeed
->feed
.sec
.tsfeedp
= 0;
916 dvbdmxfeed
->feed
.sec
.secbuf
= dvbdmxfeed
->feed
.sec
.secbuf_base
;
917 dvbdmxfeed
->feed
.sec
.secbufp
=0;
918 dvbdmxfeed
->feed
.sec
.seclen
=0;
920 if (!dvbdmx
->start_feed
) {
925 prepare_secfilters(dvbdmxfeed
);
927 if ((ret
= dvbdmx
->start_feed(dvbdmxfeed
)) < 0) {
932 spin_lock_irq(&dvbdmx
->lock
);
933 feed
->is_filtering
=1;
934 dvbdmxfeed
->state
=DMX_STATE_GO
;
935 spin_unlock_irq(&dvbdmx
->lock
);
941 static int dmx_section_feed_stop_filtering(struct dmx_section_feed
* feed
)
943 struct dvb_demux_feed
*dvbdmxfeed
=(struct dvb_demux_feed
*) feed
;
944 struct dvb_demux
*dvbdmx
=dvbdmxfeed
->demux
;
947 if (down_interruptible (&dvbdmx
->mutex
))
950 if (!dvbdmx
->stop_feed
) {
954 ret
=dvbdmx
->stop_feed(dvbdmxfeed
);
955 spin_lock_irq(&dvbdmx
->lock
);
956 dvbdmxfeed
->state
=DMX_STATE_READY
;
957 feed
->is_filtering
=0;
958 spin_unlock_irq(&dvbdmx
->lock
);
964 static int dmx_section_feed_release_filter(struct dmx_section_feed
*feed
,
965 struct dmx_section_filter
* filter
)
967 struct dvb_demux_filter
*dvbdmxfilter
=(struct dvb_demux_filter
*) filter
, *f
;
968 struct dvb_demux_feed
*dvbdmxfeed
=(struct dvb_demux_feed
*) feed
;
969 struct dvb_demux
*dvbdmx
=dvbdmxfeed
->demux
;
971 if (down_interruptible (&dvbdmx
->mutex
))
974 if (dvbdmxfilter
->feed
!=dvbdmxfeed
) {
978 if (feed
->is_filtering
)
979 feed
->stop_filtering(feed
);
981 spin_lock_irq(&dvbdmx
->lock
);
982 f
=dvbdmxfeed
->filter
;
984 if (f
== dvbdmxfilter
) {
985 dvbdmxfeed
->filter
=dvbdmxfilter
->next
;
987 while(f
->next
!=dvbdmxfilter
)
989 f
->next
=f
->next
->next
;
991 dvbdmxfilter
->state
=DMX_STATE_FREE
;
992 spin_unlock_irq(&dvbdmx
->lock
);
997 static int dvbdmx_allocate_section_feed(struct dmx_demux
*demux
,
998 struct dmx_section_feed
**feed
,
999 dmx_section_cb callback
)
1001 struct dvb_demux
*dvbdmx
=(struct dvb_demux
*) demux
;
1002 struct dvb_demux_feed
*dvbdmxfeed
;
1004 if (down_interruptible (&dvbdmx
->mutex
))
1005 return -ERESTARTSYS
;
1007 if (!(dvbdmxfeed
=dvb_dmx_feed_alloc(dvbdmx
))) {
1011 dvbdmxfeed
->type
=DMX_TYPE_SEC
;
1012 dvbdmxfeed
->cb
.sec
=callback
;
1013 dvbdmxfeed
->demux
=dvbdmx
;
1014 dvbdmxfeed
->pid
=0xffff;
1015 dvbdmxfeed
->feed
.sec
.secbuf
= dvbdmxfeed
->feed
.sec
.secbuf_base
;
1016 dvbdmxfeed
->feed
.sec
.secbufp
= dvbdmxfeed
->feed
.sec
.seclen
= 0;
1017 dvbdmxfeed
->feed
.sec
.tsfeedp
= 0;
1018 dvbdmxfeed
->filter
=NULL
;
1019 dvbdmxfeed
->buffer
=NULL
;
1021 (*feed
)=&dvbdmxfeed
->feed
.sec
;
1022 (*feed
)->is_filtering
=0;
1023 (*feed
)->parent
=demux
;
1026 (*feed
)->set
=dmx_section_feed_set
;
1027 (*feed
)->allocate_filter
=dmx_section_feed_allocate_filter
;
1028 (*feed
)->start_filtering
=dmx_section_feed_start_filtering
;
1029 (*feed
)->stop_filtering
=dmx_section_feed_stop_filtering
;
1030 (*feed
)->release_filter
= dmx_section_feed_release_filter
;
1036 static int dvbdmx_release_section_feed(struct dmx_demux
*demux
,
1037 struct dmx_section_feed
*feed
)
1039 struct dvb_demux_feed
*dvbdmxfeed
=(struct dvb_demux_feed
*) feed
;
1040 struct dvb_demux
*dvbdmx
=(struct dvb_demux
*) demux
;
1042 if (down_interruptible (&dvbdmx
->mutex
))
1043 return -ERESTARTSYS
;
1045 if (dvbdmxfeed
->state
==DMX_STATE_FREE
) {
1050 if (dvbdmxfeed
->buffer
) {
1051 vfree(dvbdmxfeed
->buffer
);
1052 dvbdmxfeed
->buffer
=0;
1055 dvbdmxfeed
->state
=DMX_STATE_FREE
;
1057 dvb_demux_feed_del(dvbdmxfeed
);
1059 dvbdmxfeed
->pid
= 0xffff;
1066 /******************************************************************************
1067 * dvb_demux kernel data API calls
1068 ******************************************************************************/
1070 static int dvbdmx_open(struct dmx_demux
*demux
)
1072 struct dvb_demux
*dvbdemux
=(struct dvb_demux
*) demux
;
1074 if (dvbdemux
->users
>=MAX_DVB_DEMUX_USERS
)
1081 static int dvbdmx_close(struct dmx_demux
*demux
)
1083 struct dvb_demux
*dvbdemux
=(struct dvb_demux
*) demux
;
1085 if (dvbdemux
->users
==0)
1088 //FIXME: release any unneeded resources if users==0
1093 static int dvbdmx_write(struct dmx_demux
*demux
, const char *buf
, size_t count
)
1095 struct dvb_demux
*dvbdemux
=(struct dvb_demux
*) demux
;
1097 if ((!demux
->frontend
) || (demux
->frontend
->source
!= DMX_MEMORY_FE
))
1100 if (down_interruptible (&dvbdemux
->mutex
))
1101 return -ERESTARTSYS
;
1102 dvb_dmx_swfilter(dvbdemux
, buf
, count
);
1103 up(&dvbdemux
->mutex
);
1105 if (signal_pending(current
))
1111 static int dvbdmx_add_frontend(struct dmx_demux
*demux
, struct dmx_frontend
*frontend
)
1113 struct dvb_demux
*dvbdemux
=(struct dvb_demux
*) demux
;
1114 struct list_head
*head
= &dvbdemux
->frontend_list
;
1116 list_add(&(frontend
->connectivity_list
), head
);
1122 static int dvbdmx_remove_frontend(struct dmx_demux
*demux
, struct dmx_frontend
*frontend
)
1124 struct dvb_demux
*dvbdemux
=(struct dvb_demux
*) demux
;
1125 struct list_head
*pos
, *n
, *head
=&dvbdemux
->frontend_list
;
1127 list_for_each_safe (pos
, n
, head
) {
1128 if (DMX_FE_ENTRY(pos
) == frontend
) {
1137 static struct list_head
* dvbdmx_get_frontends(struct dmx_demux
*demux
)
1139 struct dvb_demux
*dvbdemux
=(struct dvb_demux
*) demux
;
1141 if (list_empty(&dvbdemux
->frontend_list
))
1143 return &dvbdemux
->frontend_list
;
1147 int dvbdmx_connect_frontend(struct dmx_demux
*demux
, struct dmx_frontend
*frontend
)
1149 struct dvb_demux
*dvbdemux
=(struct dvb_demux
*) demux
;
1151 if (demux
->frontend
)
1154 if (down_interruptible (&dvbdemux
->mutex
))
1155 return -ERESTARTSYS
;
1157 demux
->frontend
=frontend
;
1158 up(&dvbdemux
->mutex
);
1163 int dvbdmx_disconnect_frontend(struct dmx_demux
*demux
)
1165 struct dvb_demux
*dvbdemux
=(struct dvb_demux
*) demux
;
1167 if (down_interruptible (&dvbdemux
->mutex
))
1168 return -ERESTARTSYS
;
1170 demux
->frontend
=NULL
;
1171 up(&dvbdemux
->mutex
);
1176 static int dvbdmx_get_pes_pids(struct dmx_demux
*demux
, u16
*pids
)
1178 struct dvb_demux
*dvbdemux
=(struct dvb_demux
*) demux
;
1180 memcpy(pids
, dvbdemux
->pids
, 5*sizeof(u16
));
1185 int dvb_dmx_init(struct dvb_demux
*dvbdemux
)
1188 struct dmx_demux
*dmx
= &dvbdemux
->dmx
;
1191 dvbdemux
->filter
=vmalloc(dvbdemux
->filternum
*sizeof(struct dvb_demux_filter
));
1192 if (!dvbdemux
->filter
)
1195 dvbdemux
->feed
=vmalloc(dvbdemux
->feednum
*sizeof(struct dvb_demux_feed
));
1196 if (!dvbdemux
->feed
) {
1197 vfree(dvbdemux
->filter
);
1200 for (i
=0; i
<dvbdemux
->filternum
; i
++) {
1201 dvbdemux
->filter
[i
].state
=DMX_STATE_FREE
;
1202 dvbdemux
->filter
[i
].index
=i
;
1204 for (i
=0; i
<dvbdemux
->feednum
; i
++)
1205 dvbdemux
->feed
[i
].state
=DMX_STATE_FREE
;
1206 dvbdemux
->frontend_list
.next
=
1207 dvbdemux
->frontend_list
.prev
=
1208 &dvbdemux
->frontend_list
;
1209 for (i
=0; i
<DMX_TS_PES_OTHER
; i
++) {
1210 dvbdemux
->pesfilter
[i
]=NULL
;
1211 dvbdemux
->pids
[i
]=0xffff;
1214 INIT_LIST_HEAD(&dvbdemux
->feed_list
);
1216 dvbdemux
->playing
= 0;
1217 dvbdemux
->recording
= 0;
1220 if (!dvbdemux
->check_crc32
)
1221 dvbdemux
->check_crc32
= dvb_dmx_crc32
;
1223 if (!dvbdemux
->memcopy
)
1224 dvbdemux
->memcopy
= dvb_dmx_memcopy
;
1227 dmx
->reg_list
.prev
= dmx
->reg_list
.next
= &dmx
->reg_list
;
1228 dmx
->priv
=(void *) dvbdemux
;
1229 dmx
->open
=dvbdmx_open
;
1230 dmx
->close
=dvbdmx_close
;
1231 dmx
->write
=dvbdmx_write
;
1232 dmx
->allocate_ts_feed
=dvbdmx_allocate_ts_feed
;
1233 dmx
->release_ts_feed
=dvbdmx_release_ts_feed
;
1234 dmx
->allocate_section_feed
=dvbdmx_allocate_section_feed
;
1235 dmx
->release_section_feed
=dvbdmx_release_section_feed
;
1237 dmx
->descramble_mac_address
=NULL
;
1238 dmx
->descramble_section_payload
=NULL
;
1240 dmx
->add_frontend
=dvbdmx_add_frontend
;
1241 dmx
->remove_frontend
=dvbdmx_remove_frontend
;
1242 dmx
->get_frontends
=dvbdmx_get_frontends
;
1243 dmx
->connect_frontend
=dvbdmx_connect_frontend
;
1244 dmx
->disconnect_frontend
=dvbdmx_disconnect_frontend
;
1245 dmx
->get_pes_pids
=dvbdmx_get_pes_pids
;
1246 sema_init(&dvbdemux
->mutex
, 1);
1247 spin_lock_init(&dvbdemux
->lock
);
1249 if ((err
= dmx_register_demux(dmx
)) < 0)
1256 int dvb_dmx_release(struct dvb_demux
*dvbdemux
)
1258 struct dmx_demux
*dmx
= &dvbdemux
->dmx
;
1260 dmx_unregister_demux(dmx
);
1261 if (dvbdemux
->filter
)
1262 vfree(dvbdemux
->filter
);
1264 vfree(dvbdemux
->feed
);