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