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