linux/drivers/media/dvb/dvb-core/dmxdev.c
<<
>>
Prefs
   1/*
   2 * dmxdev.c - DVB demultiplexer device
   3 *
   4 * Copyright (C) 2000 Ralph Metzler & Marcus Metzler
   5 *                    for convergence integrated media GmbH
   6 *
   7 * This program is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU Lesser General Public License
   9 * as published by the Free Software Foundation; either version 2.1
  10 * of the License, or (at your option) any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU Lesser General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  20 *
  21 */
  22
  23#include <linux/spinlock.h>
  24#include <linux/slab.h>
  25#include <linux/vmalloc.h>
  26#include <linux/module.h>
  27#include <linux/poll.h>
  28#include <linux/ioctl.h>
  29#include <linux/wait.h>
  30#include <asm/uaccess.h>
  31#include <asm/system.h>
  32#include "dmxdev.h"
  33
  34static int debug;
  35
  36module_param(debug, int, 0644);
  37MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
  38
  39#define dprintk if (debug) printk
  40
  41static int dvb_dmxdev_buffer_write(struct dvb_ringbuffer *buf,
  42                                   const u8 *src, size_t len)
  43{
  44        ssize_t free;
  45
  46        if (!len)
  47                return 0;
  48        if (!buf->data)
  49                return 0;
  50
  51        free = dvb_ringbuffer_free(buf);
  52        if (len > free) {
  53                dprintk("dmxdev: buffer overflow\n");
  54                return -EOVERFLOW;
  55        }
  56
  57        return dvb_ringbuffer_write(buf, src, len);
  58}
  59
  60static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src,
  61                                      int non_blocking, char __user *buf,
  62                                      size_t count, loff_t *ppos)
  63{
  64        size_t todo;
  65        ssize_t avail;
  66        ssize_t ret = 0;
  67
  68        if (!src->data)
  69                return 0;
  70
  71        if (src->error) {
  72                ret = src->error;
  73                dvb_ringbuffer_flush(src);
  74                return ret;
  75        }
  76
  77        for (todo = count; todo > 0; todo -= ret) {
  78                if (non_blocking && dvb_ringbuffer_empty(src)) {
  79                        ret = -EWOULDBLOCK;
  80                        break;
  81                }
  82
  83                ret = wait_event_interruptible(src->queue,
  84                                               !dvb_ringbuffer_empty(src) ||
  85                                               (src->error != 0));
  86                if (ret < 0)
  87                        break;
  88
  89                if (src->error) {
  90                        ret = src->error;
  91                        dvb_ringbuffer_flush(src);
  92                        break;
  93                }
  94
  95                avail = dvb_ringbuffer_avail(src);
  96                if (avail > todo)
  97                        avail = todo;
  98
  99                ret = dvb_ringbuffer_read(src, (u8 *)buf, avail, 1);
 100                if (ret < 0)
 101                        break;
 102
 103                buf += ret;
 104        }
 105
 106        return (count - todo) ? (count - todo) : ret;
 107}
 108
 109static struct dmx_frontend *get_fe(struct dmx_demux *demux, int type)
 110{
 111        struct list_head *head, *pos;
 112
 113        head = demux->get_frontends(demux);
 114        if (!head)
 115                return NULL;
 116        list_for_each(pos, head)
 117                if (DMX_FE_ENTRY(pos)->source == type)
 118                        return DMX_FE_ENTRY(pos);
 119
 120        return NULL;
 121}
 122
 123static int dvb_dvr_open(struct inode *inode, struct file *file)
 124{
 125        struct dvb_device *dvbdev = file->private_data;
 126        struct dmxdev *dmxdev = dvbdev->priv;
 127        struct dmx_frontend *front;
 128
 129        dprintk("function : %s\n", __FUNCTION__);
 130
 131        if (mutex_lock_interruptible(&dmxdev->mutex))
 132                return -ERESTARTSYS;
 133
 134        if (dmxdev->exit) {
 135                mutex_unlock(&dmxdev->mutex);
 136                return -ENODEV;
 137        }
 138
 139        if ((file->f_flags & O_ACCMODE) == O_RDWR) {
 140                if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) {
 141                        mutex_unlock(&dmxdev->mutex);
 142                        return -EOPNOTSUPP;
 143                }
 144        }
 145
 146        if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
 147                void *mem;
 148                if (!dvbdev->readers) {
 149                        mutex_unlock(&dmxdev->mutex);
 150                        return -EBUSY;
 151                }
 152                mem = vmalloc(DVR_BUFFER_SIZE);
 153                if (!mem) {
 154                        mutex_unlock(&dmxdev->mutex);
 155                        return -ENOMEM;
 156                }
 157                dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE);
 158                dvbdev->readers--;
 159        }
 160
 161        if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
 162                dmxdev->dvr_orig_fe = dmxdev->demux->frontend;
 163
 164                if (!dmxdev->demux->write) {
 165                        mutex_unlock(&dmxdev->mutex);
 166                        return -EOPNOTSUPP;
 167                }
 168
 169                front = get_fe(dmxdev->demux, DMX_MEMORY_FE);
 170
 171                if (!front) {
 172                        mutex_unlock(&dmxdev->mutex);
 173                        return -EINVAL;
 174                }
 175                dmxdev->demux->disconnect_frontend(dmxdev->demux);
 176                dmxdev->demux->connect_frontend(dmxdev->demux, front);
 177        }
 178        dvbdev->users++;
 179        mutex_unlock(&dmxdev->mutex);
 180        return 0;
 181}
 182
 183static int dvb_dvr_release(struct inode *inode, struct file *file)
 184{
 185        struct dvb_device *dvbdev = file->private_data;
 186        struct dmxdev *dmxdev = dvbdev->priv;
 187
 188        mutex_lock(&dmxdev->mutex);
 189
 190        if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
 191                dmxdev->demux->disconnect_frontend(dmxdev->demux);
 192                dmxdev->demux->connect_frontend(dmxdev->demux,
 193                                                dmxdev->dvr_orig_fe);
 194        }
 195        if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
 196                dvbdev->readers++;
 197                if (dmxdev->dvr_buffer.data) {
 198                        void *mem = dmxdev->dvr_buffer.data;
 199                        mb();
 200                        spin_lock_irq(&dmxdev->lock);
 201                        dmxdev->dvr_buffer.data = NULL;
 202                        spin_unlock_irq(&dmxdev->lock);
 203                        vfree(mem);
 204                }
 205        }
 206        /* TODO */
 207        dvbdev->users--;
 208        if(dvbdev->users==-1 && dmxdev->exit==1) {
 209                fops_put(file->f_op);
 210                file->f_op = NULL;
 211                mutex_unlock(&dmxdev->mutex);
 212                wake_up(&dvbdev->wait_queue);
 213        } else
 214                mutex_unlock(&dmxdev->mutex);
 215
 216        return 0;
 217}
 218
 219static ssize_t dvb_dvr_write(struct file *file, const char __user *buf,
 220                             size_t count, loff_t *ppos)
 221{
 222        struct dvb_device *dvbdev = file->private_data;
 223        struct dmxdev *dmxdev = dvbdev->priv;
 224        int ret;
 225
 226        if (!dmxdev->demux->write)
 227                return -EOPNOTSUPP;
 228        if ((file->f_flags & O_ACCMODE) != O_WRONLY)
 229                return -EINVAL;
 230        if (mutex_lock_interruptible(&dmxdev->mutex))
 231                return -ERESTARTSYS;
 232
 233        if (dmxdev->exit) {
 234                mutex_unlock(&dmxdev->mutex);
 235                return -ENODEV;
 236        }
 237        ret = dmxdev->demux->write(dmxdev->demux, buf, count);
 238        mutex_unlock(&dmxdev->mutex);
 239        return ret;
 240}
 241
 242static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count,
 243                            loff_t *ppos)
 244{
 245        struct dvb_device *dvbdev = file->private_data;
 246        struct dmxdev *dmxdev = dvbdev->priv;
 247        int ret;
 248
 249        if (dmxdev->exit) {
 250                mutex_unlock(&dmxdev->mutex);
 251                return -ENODEV;
 252        }
 253
 254        //mutex_lock(&dmxdev->mutex);
 255        ret = dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer,
 256                                     file->f_flags & O_NONBLOCK,
 257                                     buf, count, ppos);
 258        //mutex_unlock(&dmxdev->mutex);
 259        return ret;
 260}
 261
 262static inline void dvb_dmxdev_filter_state_set(struct dmxdev_filter
 263                                               *dmxdevfilter, int state)
 264{
 265        spin_lock_irq(&dmxdevfilter->dev->lock);
 266        dmxdevfilter->state = state;
 267        spin_unlock_irq(&dmxdevfilter->dev->lock);
 268}
 269
 270static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter,
 271                                      unsigned long size)
 272{
 273        struct dvb_ringbuffer *buf = &dmxdevfilter->buffer;
 274        void *mem;
 275
 276        if (buf->size == size)
 277                return 0;
 278        if (dmxdevfilter->state >= DMXDEV_STATE_GO)
 279                return -EBUSY;
 280        spin_lock_irq(&dmxdevfilter->dev->lock);
 281        mem = buf->data;
 282        buf->data = NULL;
 283        buf->size = size;
 284        dvb_ringbuffer_flush(buf);
 285        spin_unlock_irq(&dmxdevfilter->dev->lock);
 286        vfree(mem);
 287
 288        if (buf->size) {
 289                mem = vmalloc(dmxdevfilter->buffer.size);
 290                if (!mem)
 291                        return -ENOMEM;
 292                spin_lock_irq(&dmxdevfilter->dev->lock);
 293                buf->data = mem;
 294                spin_unlock_irq(&dmxdevfilter->dev->lock);
 295        }
 296        return 0;
 297}
 298
 299static void dvb_dmxdev_filter_timeout(unsigned long data)
 300{
 301        struct dmxdev_filter *dmxdevfilter = (struct dmxdev_filter *)data;
 302
 303        dmxdevfilter->buffer.error = -ETIMEDOUT;
 304        spin_lock_irq(&dmxdevfilter->dev->lock);
 305        dmxdevfilter->state = DMXDEV_STATE_TIMEDOUT;
 306        spin_unlock_irq(&dmxdevfilter->dev->lock);
 307        wake_up(&dmxdevfilter->buffer.queue);
 308}
 309
 310static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)
 311{
 312        struct dmx_sct_filter_params *para = &dmxdevfilter->params.sec;
 313
 314        del_timer(&dmxdevfilter->timer);
 315        if (para->timeout) {
 316                dmxdevfilter->timer.function = dvb_dmxdev_filter_timeout;
 317                dmxdevfilter->timer.data = (unsigned long)dmxdevfilter;
 318                dmxdevfilter->timer.expires =
 319                    jiffies + 1 + (HZ / 2 + HZ * para->timeout) / 1000;
 320                add_timer(&dmxdevfilter->timer);
 321        }
 322}
 323
 324static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
 325                                       const u8 *buffer2, size_t buffer2_len,
 326                                       struct dmx_section_filter *filter,
 327                                       enum dmx_success success)
 328{
 329        struct dmxdev_filter *dmxdevfilter = filter->priv;
 330        int ret;
 331
 332        if (dmxdevfilter->buffer.error) {
 333                wake_up(&dmxdevfilter->buffer.queue);
 334                return 0;
 335        }
 336        spin_lock(&dmxdevfilter->dev->lock);
 337        if (dmxdevfilter->state != DMXDEV_STATE_GO) {
 338                spin_unlock(&dmxdevfilter->dev->lock);
 339                return 0;
 340        }
 341        del_timer(&dmxdevfilter->timer);
 342        dprintk("dmxdev: section callback %02x %02x %02x %02x %02x %02x\n",
 343                buffer1[0], buffer1[1],
 344                buffer1[2], buffer1[3], buffer1[4], buffer1[5]);
 345        ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer1,
 346                                      buffer1_len);
 347        if (ret == buffer1_len) {
 348                ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer2,
 349                                              buffer2_len);
 350        }
 351        if (ret < 0) {
 352                dvb_ringbuffer_flush(&dmxdevfilter->buffer);
 353                dmxdevfilter->buffer.error = ret;
 354        }
 355        if (dmxdevfilter->params.sec.flags & DMX_ONESHOT)
 356                dmxdevfilter->state = DMXDEV_STATE_DONE;
 357        spin_unlock(&dmxdevfilter->dev->lock);
 358        wake_up(&dmxdevfilter->buffer.queue);
 359        return 0;
 360}
 361
 362static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
 363                                  const u8 *buffer2, size_t buffer2_len,
 364                                  struct dmx_ts_feed *feed,
 365                                  enum dmx_success success)
 366{
 367        struct dmxdev_filter *dmxdevfilter = feed->priv;
 368        struct dvb_ringbuffer *buffer;
 369        int ret;
 370
 371        spin_lock(&dmxdevfilter->dev->lock);
 372        if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) {
 373                spin_unlock(&dmxdevfilter->dev->lock);
 374                return 0;
 375        }
 376
 377        if (dmxdevfilter->params.pes.output == DMX_OUT_TAP)
 378                buffer = &dmxdevfilter->buffer;
 379        else
 380                buffer = &dmxdevfilter->dev->dvr_buffer;
 381        if (buffer->error) {
 382                spin_unlock(&dmxdevfilter->dev->lock);
 383                wake_up(&buffer->queue);
 384                return 0;
 385        }
 386        ret = dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len);
 387        if (ret == buffer1_len)
 388                ret = dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len);
 389        if (ret < 0) {
 390                dvb_ringbuffer_flush(buffer);
 391                buffer->error = ret;
 392        }
 393        spin_unlock(&dmxdevfilter->dev->lock);
 394        wake_up(&buffer->queue);
 395        return 0;
 396}
 397
 398/* stop feed but only mark the specified filter as stopped (state set) */
 399static int dvb_dmxdev_feed_stop(struct dmxdev_filter *dmxdevfilter)
 400{
 401        dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET);
 402
 403        switch (dmxdevfilter->type) {
 404        case DMXDEV_TYPE_SEC:
 405                del_timer(&dmxdevfilter->timer);
 406                dmxdevfilter->feed.sec->stop_filtering(dmxdevfilter->feed.sec);
 407                break;
 408        case DMXDEV_TYPE_PES:
 409                dmxdevfilter->feed.ts->stop_filtering(dmxdevfilter->feed.ts);
 410                break;
 411        default:
 412                return -EINVAL;
 413        }
 414        return 0;
 415}
 416
 417/* start feed associated with the specified filter */
 418static int dvb_dmxdev_feed_start(struct dmxdev_filter *filter)
 419{
 420        dvb_dmxdev_filter_state_set(filter, DMXDEV_STATE_GO);
 421
 422        switch (filter->type) {
 423        case DMXDEV_TYPE_SEC:
 424                return filter->feed.sec->start_filtering(filter->feed.sec);
 425        case DMXDEV_TYPE_PES:
 426                return filter->feed.ts->start_filtering(filter->feed.ts);
 427        default:
 428                return -EINVAL;
 429        }
 430
 431        return 0;
 432}
 433
 434/* restart section feed if it has filters left associated with it,
 435   otherwise release the feed */
 436static int dvb_dmxdev_feed_restart(struct dmxdev_filter *filter)
 437{
 438        int i;
 439        struct dmxdev *dmxdev = filter->dev;
 440        u16 pid = filter->params.sec.pid;
 441
 442        for (i = 0; i < dmxdev->filternum; i++)
 443                if (dmxdev->filter[i].state >= DMXDEV_STATE_GO &&
 444                    dmxdev->filter[i].type == DMXDEV_TYPE_SEC &&
 445                    dmxdev->filter[i].params.sec.pid == pid) {
 446                        dvb_dmxdev_feed_start(&dmxdev->filter[i]);
 447                        return 0;
 448                }
 449
 450        filter->dev->demux->release_section_feed(dmxdev->demux,
 451                                                 filter->feed.sec);
 452
 453        return 0;
 454}
 455
 456static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter)
 457{
 458        if (dmxdevfilter->state < DMXDEV_STATE_GO)
 459                return 0;
 460
 461        switch (dmxdevfilter->type) {
 462        case DMXDEV_TYPE_SEC:
 463                if (!dmxdevfilter->feed.sec)
 464                        break;
 465                dvb_dmxdev_feed_stop(dmxdevfilter);
 466                if (dmxdevfilter->filter.sec)
 467                        dmxdevfilter->feed.sec->
 468                            release_filter(dmxdevfilter->feed.sec,
 469                                           dmxdevfilter->filter.sec);
 470                dvb_dmxdev_feed_restart(dmxdevfilter);
 471                dmxdevfilter->feed.sec = NULL;
 472                break;
 473        case DMXDEV_TYPE_PES:
 474                if (!dmxdevfilter->feed.ts)
 475                        break;
 476                dvb_dmxdev_feed_stop(dmxdevfilter);
 477                dmxdevfilter->dev->demux->
 478                    release_ts_feed(dmxdevfilter->dev->demux,
 479                                    dmxdevfilter->feed.ts);
 480                dmxdevfilter->feed.ts = NULL;
 481                break;
 482        default:
 483                if (dmxdevfilter->state == DMXDEV_STATE_ALLOCATED)
 484                        return 0;
 485                return -EINVAL;
 486        }
 487
 488        dvb_ringbuffer_flush(&dmxdevfilter->buffer);
 489        return 0;
 490}
 491
 492static inline int dvb_dmxdev_filter_reset(struct dmxdev_filter *dmxdevfilter)
 493{
 494        if (dmxdevfilter->state < DMXDEV_STATE_SET)
 495                return 0;
 496
 497        dmxdevfilter->type = DMXDEV_TYPE_NONE;
 498        dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
 499        return 0;
 500}
 501
 502static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
 503{
 504        struct dmxdev *dmxdev = filter->dev;
 505        void *mem;
 506        int ret, i;
 507
 508        if (filter->state < DMXDEV_STATE_SET)
 509                return -EINVAL;
 510
 511        if (filter->state >= DMXDEV_STATE_GO)
 512                dvb_dmxdev_filter_stop(filter);
 513
 514        if (!filter->buffer.data) {
 515                mem = vmalloc(filter->buffer.size);
 516                if (!mem)
 517                        return -ENOMEM;
 518                spin_lock_irq(&filter->dev->lock);
 519                filter->buffer.data = mem;
 520                spin_unlock_irq(&filter->dev->lock);
 521        }
 522
 523        dvb_ringbuffer_flush(&filter->buffer);
 524
 525        switch (filter->type) {
 526        case DMXDEV_TYPE_SEC:
 527        {
 528                struct dmx_sct_filter_params *para = &filter->params.sec;
 529                struct dmx_section_filter **secfilter = &filter->filter.sec;
 530                struct dmx_section_feed **secfeed = &filter->feed.sec;
 531
 532                *secfilter = NULL;
 533                *secfeed = NULL;
 534
 535
 536                /* find active filter/feed with same PID */
 537                for (i = 0; i < dmxdev->filternum; i++) {
 538                        if (dmxdev->filter[i].state >= DMXDEV_STATE_GO &&
 539                            dmxdev->filter[i].type == DMXDEV_TYPE_SEC &&
 540                            dmxdev->filter[i].params.sec.pid == para->pid) {
 541                                *secfeed = dmxdev->filter[i].feed.sec;
 542                                break;
 543                        }
 544                }
 545
 546                /* if no feed found, try to allocate new one */
 547                if (!*secfeed) {
 548                        ret = dmxdev->demux->allocate_section_feed(dmxdev->demux,
 549                                                                   secfeed,
 550                                                                   dvb_dmxdev_section_callback);
 551                        if (ret < 0) {
 552                                printk("DVB (%s): could not alloc feed\n",
 553                                       __FUNCTION__);
 554                                return ret;
 555                        }
 556
 557                        ret = (*secfeed)->set(*secfeed, para->pid, 32768,
 558                                              (para->flags & DMX_CHECK_CRC) ? 1 : 0);
 559                        if (ret < 0) {
 560                                printk("DVB (%s): could not set feed\n",
 561                                       __FUNCTION__);
 562                                dvb_dmxdev_feed_restart(filter);
 563                                return ret;
 564                        }
 565                } else {
 566                        dvb_dmxdev_feed_stop(filter);
 567                }
 568
 569                ret = (*secfeed)->allocate_filter(*secfeed, secfilter);
 570                if (ret < 0) {
 571                        dvb_dmxdev_feed_restart(filter);
 572                        filter->feed.sec->start_filtering(*secfeed);
 573                        dprintk("could not get filter\n");
 574                        return ret;
 575                }
 576
 577                (*secfilter)->priv = filter;
 578
 579                memcpy(&((*secfilter)->filter_value[3]),
 580                       &(para->filter.filter[1]), DMX_FILTER_SIZE - 1);
 581                memcpy(&(*secfilter)->filter_mask[3],
 582                       &para->filter.mask[1], DMX_FILTER_SIZE - 1);
 583                memcpy(&(*secfilter)->filter_mode[3],
 584                       &para->filter.mode[1], DMX_FILTER_SIZE - 1);
 585
 586                (*secfilter)->filter_value[0] = para->filter.filter[0];
 587                (*secfilter)->filter_mask[0] = para->filter.mask[0];
 588                (*secfilter)->filter_mode[0] = para->filter.mode[0];
 589                (*secfilter)->filter_mask[1] = 0;
 590                (*secfilter)->filter_mask[2] = 0;
 591
 592                filter->todo = 0;
 593
 594                ret = filter->feed.sec->start_filtering(filter->feed.sec);
 595                if (ret < 0)
 596                        return ret;
 597
 598                dvb_dmxdev_filter_timer(filter);
 599                break;
 600        }
 601        case DMXDEV_TYPE_PES:
 602        {
 603                struct timespec timeout = { 0 };
 604                struct dmx_pes_filter_params *para = &filter->params.pes;
 605                dmx_output_t otype;
 606                int ret;
 607                int ts_type;
 608                enum dmx_ts_pes ts_pes;
 609                struct dmx_ts_feed **tsfeed = &filter->feed.ts;
 610
 611                filter->feed.ts = NULL;
 612                otype = para->output;
 613
 614                ts_pes = (enum dmx_ts_pes)para->pes_type;
 615
 616                if (ts_pes < DMX_PES_OTHER)
 617                        ts_type = TS_DECODER;
 618                else
 619                        ts_type = 0;
 620
 621                if (otype == DMX_OUT_TS_TAP)
 622                        ts_type |= TS_PACKET;
 623
 624                if (otype == DMX_OUT_TAP)
 625                        ts_type |= TS_PAYLOAD_ONLY | TS_PACKET;
 626
 627                ret = dmxdev->demux->allocate_ts_feed(dmxdev->demux,
 628                                                      tsfeed,
 629                                                      dvb_dmxdev_ts_callback);
 630                if (ret < 0)
 631                        return ret;
 632
 633                (*tsfeed)->priv = filter;
 634
 635                ret = (*tsfeed)->set(*tsfeed, para->pid, ts_type, ts_pes,
 636                                     32768, timeout);
 637                if (ret < 0) {
 638                        dmxdev->demux->release_ts_feed(dmxdev->demux,
 639                                                       *tsfeed);
 640                        return ret;
 641                }
 642
 643                ret = filter->feed.ts->start_filtering(filter->feed.ts);
 644                if (ret < 0) {
 645                        dmxdev->demux->release_ts_feed(dmxdev->demux,
 646                                                       *tsfeed);
 647                        return ret;
 648                }
 649
 650                break;
 651        }
 652        default:
 653                return -EINVAL;
 654        }
 655
 656        dvb_dmxdev_filter_state_set(filter, DMXDEV_STATE_GO);
 657        return 0;
 658}
 659
 660static int dvb_demux_open(struct inode *inode, struct file *file)
 661{
 662        struct dvb_device *dvbdev = file->private_data;
 663        struct dmxdev *dmxdev = dvbdev->priv;
 664        int i;
 665        struct dmxdev_filter *dmxdevfilter;
 666
 667        if (!dmxdev->filter)
 668                return -EINVAL;
 669
 670        if (mutex_lock_interruptible(&dmxdev->mutex))
 671                return -ERESTARTSYS;
 672
 673        for (i = 0; i < dmxdev->filternum; i++)
 674                if (dmxdev->filter[i].state == DMXDEV_STATE_FREE)
 675                        break;
 676
 677        if (i == dmxdev->filternum) {
 678                mutex_unlock(&dmxdev->mutex);
 679                return -EMFILE;
 680        }
 681
 682        dmxdevfilter = &dmxdev->filter[i];
 683        mutex_init(&dmxdevfilter->mutex);
 684        file->private_data = dmxdevfilter;
 685
 686        dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192);
 687        dmxdevfilter->type = DMXDEV_TYPE_NONE;
 688        dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
 689        dmxdevfilter->feed.ts = NULL;
 690        init_timer(&dmxdevfilter->timer);
 691
 692        dvbdev->users++;
 693
 694        mutex_unlock(&dmxdev->mutex);
 695        return 0;
 696}
 697
 698static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev,
 699                                  struct dmxdev_filter *dmxdevfilter)
 700{
 701        mutex_lock(&dmxdev->mutex);
 702        mutex_lock(&dmxdevfilter->mutex);
 703
 704        dvb_dmxdev_filter_stop(dmxdevfilter);
 705        dvb_dmxdev_filter_reset(dmxdevfilter);
 706
 707        if (dmxdevfilter->buffer.data) {
 708                void *mem = dmxdevfilter->buffer.data;
 709
 710                spin_lock_irq(&dmxdev->lock);
 711                dmxdevfilter->buffer.data = NULL;
 712                spin_unlock_irq(&dmxdev->lock);
 713                vfree(mem);
 714        }
 715
 716        dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_FREE);
 717        wake_up(&dmxdevfilter->buffer.queue);
 718        mutex_unlock(&dmxdevfilter->mutex);
 719        mutex_unlock(&dmxdev->mutex);
 720        return 0;
 721}
 722
 723static inline void invert_mode(dmx_filter_t *filter)
 724{
 725        int i;
 726
 727        for (i = 0; i < DMX_FILTER_SIZE; i++)
 728                filter->mode[i] ^= 0xff;
 729}
 730
 731static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev,
 732                                 struct dmxdev_filter *dmxdevfilter,
 733                                 struct dmx_sct_filter_params *params)
 734{
 735        dprintk("function : %s\n", __FUNCTION__);
 736
 737        dvb_dmxdev_filter_stop(dmxdevfilter);
 738
 739        dmxdevfilter->type = DMXDEV_TYPE_SEC;
 740        memcpy(&dmxdevfilter->params.sec,
 741               params, sizeof(struct dmx_sct_filter_params));
 742        invert_mode(&dmxdevfilter->params.sec.filter);
 743        dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET);
 744
 745        if (params->flags & DMX_IMMEDIATE_START)
 746                return dvb_dmxdev_filter_start(dmxdevfilter);
 747
 748        return 0;
 749}
 750
 751static int dvb_dmxdev_pes_filter_set(struct dmxdev *dmxdev,
 752                                     struct dmxdev_filter *dmxdevfilter,
 753                                     struct dmx_pes_filter_params *params)
 754{
 755        dvb_dmxdev_filter_stop(dmxdevfilter);
 756
 757        if (params->pes_type > DMX_PES_OTHER || params->pes_type < 0)
 758                return -EINVAL;
 759
 760        dmxdevfilter->type = DMXDEV_TYPE_PES;
 761        memcpy(&dmxdevfilter->params, params,
 762               sizeof(struct dmx_pes_filter_params));
 763
 764        dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET);
 765
 766        if (params->flags & DMX_IMMEDIATE_START)
 767                return dvb_dmxdev_filter_start(dmxdevfilter);
 768
 769        return 0;
 770}
 771
 772static ssize_t dvb_dmxdev_read_sec(struct dmxdev_filter *dfil,
 773                                   struct file *file, char __user *buf,
 774                                   size_t count, loff_t *ppos)
 775{
 776        int result, hcount;
 777        int done = 0;
 778
 779        if (dfil->todo <= 0) {
 780                hcount = 3 + dfil->todo;
 781                if (hcount > count)
 782                        hcount = count;
 783                result = dvb_dmxdev_buffer_read(&dfil->buffer,
 784                                                file->f_flags & O_NONBLOCK,
 785                                                buf, hcount, ppos);
 786                if (result < 0) {
 787                        dfil->todo = 0;
 788                        return result;
 789                }
 790                if (copy_from_user(dfil->secheader - dfil->todo, buf, result))
 791                        return -EFAULT;
 792                buf += result;
 793                done = result;
 794                count -= result;
 795                dfil->todo -= result;
 796                if (dfil->todo > -3)
 797                        return done;
 798                dfil->todo = ((dfil->secheader[1] << 8) | dfil->secheader[2]) & 0xfff;
 799                if (!count)
 800                        return done;
 801        }
 802        if (count > dfil->todo)
 803                count = dfil->todo;
 804        result = dvb_dmxdev_buffer_read(&dfil->buffer,
 805                                        file->f_flags & O_NONBLOCK,
 806                                        buf, count, ppos);
 807        if (result < 0)
 808                return result;
 809        dfil->todo -= result;
 810        return (result + done);
 811}
 812
 813static ssize_t
 814dvb_demux_read(struct file *file, char __user *buf, size_t count,
 815               loff_t *ppos)
 816{
 817        struct dmxdev_filter *dmxdevfilter = file->private_data;
 818        int ret;
 819
 820        if (mutex_lock_interruptible(&dmxdevfilter->mutex))
 821                return -ERESTARTSYS;
 822
 823        if (dmxdevfilter->type == DMXDEV_TYPE_SEC)
 824                ret = dvb_dmxdev_read_sec(dmxdevfilter, file, buf, count, ppos);
 825        else
 826                ret = dvb_dmxdev_buffer_read(&dmxdevfilter->buffer,
 827                                             file->f_flags & O_NONBLOCK,
 828                                             buf, count, ppos);
 829
 830        mutex_unlock(&dmxdevfilter->mutex);
 831        return ret;
 832}
 833
 834static int dvb_demux_do_ioctl(struct inode *inode, struct file *file,
 835                              unsigned int cmd, void *parg)
 836{
 837        struct dmxdev_filter *dmxdevfilter = file->private_data;
 838        struct dmxdev *dmxdev = dmxdevfilter->dev;
 839        unsigned long arg = (unsigned long)parg;
 840        int ret = 0;
 841
 842        if (mutex_lock_interruptible(&dmxdev->mutex))
 843                return -ERESTARTSYS;
 844
 845        switch (cmd) {
 846        case DMX_START:
 847                if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
 848                        mutex_unlock(&dmxdev->mutex);
 849                        return -ERESTARTSYS;
 850                }
 851                if (dmxdevfilter->state < DMXDEV_STATE_SET)
 852                        ret = -EINVAL;
 853                else
 854                        ret = dvb_dmxdev_filter_start(dmxdevfilter);
 855                mutex_unlock(&dmxdevfilter->mutex);
 856                break;
 857
 858        case DMX_STOP:
 859                if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
 860                        mutex_unlock(&dmxdev->mutex);
 861                        return -ERESTARTSYS;
 862                }
 863                ret = dvb_dmxdev_filter_stop(dmxdevfilter);
 864                mutex_unlock(&dmxdevfilter->mutex);
 865                break;
 866
 867        case DMX_SET_FILTER:
 868                if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
 869                        mutex_unlock(&dmxdev->mutex);
 870                        return -ERESTARTSYS;
 871                }
 872                ret = dvb_dmxdev_filter_set(dmxdev, dmxdevfilter, parg);
 873                mutex_unlock(&dmxdevfilter->mutex);
 874                break;
 875
 876        case DMX_SET_PES_FILTER:
 877                if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
 878                        mutex_unlock(&dmxdev->mutex);
 879                        return -ERESTARTSYS;
 880                }
 881                ret = dvb_dmxdev_pes_filter_set(dmxdev, dmxdevfilter, parg);
 882                mutex_unlock(&dmxdevfilter->mutex);
 883                break;
 884
 885        case DMX_SET_BUFFER_SIZE:
 886                if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
 887                        mutex_unlock(&dmxdev->mutex);
 888                        return -ERESTARTSYS;
 889                }
 890                ret = dvb_dmxdev_set_buffer_size(dmxdevfilter, arg);
 891                mutex_unlock(&dmxdevfilter->mutex);
 892                break;
 893
 894        case DMX_GET_PES_PIDS:
 895                if (!dmxdev->demux->get_pes_pids) {
 896                        ret = -EINVAL;
 897                        break;
 898                }
 899                dmxdev->demux->get_pes_pids(dmxdev->demux, parg);
 900                break;
 901
 902        case DMX_GET_CAPS:
 903                if (!dmxdev->demux->get_caps) {
 904                        ret = -EINVAL;
 905                        break;
 906                }
 907                ret = dmxdev->demux->get_caps(dmxdev->demux, parg);
 908                break;
 909
 910        case DMX_SET_SOURCE:
 911                if (!dmxdev->demux->set_source) {
 912                        ret = -EINVAL;
 913                        break;
 914                }
 915                ret = dmxdev->demux->set_source(dmxdev->demux, parg);
 916                break;
 917
 918        case DMX_GET_STC:
 919                if (!dmxdev->demux->get_stc) {
 920                        ret = -EINVAL;
 921                        break;
 922                }
 923                ret = dmxdev->demux->get_stc(dmxdev->demux,
 924                                             ((struct dmx_stc *)parg)->num,
 925                                             &((struct dmx_stc *)parg)->stc,
 926                                             &((struct dmx_stc *)parg)->base);
 927                break;
 928
 929        default:
 930                ret = -EINVAL;
 931                break;
 932        }
 933        mutex_unlock(&dmxdev->mutex);
 934        return ret;
 935}
 936
 937static int dvb_demux_ioctl(struct inode *inode, struct file *file,
 938                           unsigned int cmd, unsigned long arg)
 939{
 940        return dvb_usercopy(inode, file, cmd, arg, dvb_demux_do_ioctl);
 941}
 942
 943static unsigned int dvb_demux_poll(struct file *file, poll_table *wait)
 944{
 945        struct dmxdev_filter *dmxdevfilter = file->private_data;
 946        unsigned int mask = 0;
 947
 948        if (!dmxdevfilter)
 949                return -EINVAL;
 950
 951        poll_wait(file, &dmxdevfilter->buffer.queue, wait);
 952
 953        if (dmxdevfilter->state != DMXDEV_STATE_GO &&
 954            dmxdevfilter->state != DMXDEV_STATE_DONE &&
 955            dmxdevfilter->state != DMXDEV_STATE_TIMEDOUT)
 956                return 0;
 957
 958        if (dmxdevfilter->buffer.error)
 959                mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR);
 960
 961        if (!dvb_ringbuffer_empty(&dmxdevfilter->buffer))
 962                mask |= (POLLIN | POLLRDNORM | POLLPRI);
 963
 964        return mask;
 965}
 966
 967static int dvb_demux_release(struct inode *inode, struct file *file)
 968{
 969        struct dmxdev_filter *dmxdevfilter = file->private_data;
 970        struct dmxdev *dmxdev = dmxdevfilter->dev;
 971
 972        int ret;
 973
 974        ret = dvb_dmxdev_filter_free(dmxdev, dmxdevfilter);
 975
 976        mutex_lock(&dmxdev->mutex);
 977        dmxdev->dvbdev->users--;
 978        if(dmxdev->dvbdev->users==1 && dmxdev->exit==1) {
 979                fops_put(file->f_op);
 980                file->f_op = NULL;
 981                mutex_unlock(&dmxdev->mutex);
 982                wake_up(&dmxdev->dvbdev->wait_queue);
 983        } else
 984                mutex_unlock(&dmxdev->mutex);
 985
 986        return ret;
 987}
 988
 989static struct file_operations dvb_demux_fops = {
 990        .owner = THIS_MODULE,
 991        .read = dvb_demux_read,
 992        .ioctl = dvb_demux_ioctl,
 993        .open = dvb_demux_open,
 994        .release = dvb_demux_release,
 995        .poll = dvb_demux_poll,
 996};
 997
 998static struct dvb_device dvbdev_demux = {
 999        .priv = NULL,
1000        .users = 1,
1001        .writers = 1,
1002        .fops = &dvb_demux_fops
1003};
1004
1005static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file,
1006                            unsigned int cmd, void *parg)
1007{
1008        struct dvb_device *dvbdev = file->private_data;
1009        struct dmxdev *dmxdev = dvbdev->priv;
1010        int ret;
1011
1012        if (mutex_lock_interruptible(&dmxdev->mutex))
1013                return -ERESTARTSYS;
1014
1015        switch (cmd) {
1016        case DMX_SET_BUFFER_SIZE:
1017                // FIXME: implement
1018                ret = 0;
1019                break;
1020
1021        default:
1022                ret = -EINVAL;
1023                break;
1024        }
1025        mutex_unlock(&dmxdev->mutex);
1026        return ret;
1027}
1028
1029static int dvb_dvr_ioctl(struct inode *inode, struct file *file,
1030                         unsigned int cmd, unsigned long arg)
1031{
1032        return dvb_usercopy(inode, file, cmd, arg, dvb_dvr_do_ioctl);
1033}
1034
1035static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait)
1036{
1037        struct dvb_device *dvbdev = file->private_data;
1038        struct dmxdev *dmxdev = dvbdev->priv;
1039        unsigned int mask = 0;
1040
1041        dprintk("function : %s\n", __FUNCTION__);
1042
1043        poll_wait(file, &dmxdev->dvr_buffer.queue, wait);
1044
1045        if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
1046                if (dmxdev->dvr_buffer.error)
1047                        mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR);
1048
1049                if (!dvb_ringbuffer_empty(&dmxdev->dvr_buffer))
1050                        mask |= (POLLIN | POLLRDNORM | POLLPRI);
1051        } else
1052                mask |= (POLLOUT | POLLWRNORM | POLLPRI);
1053
1054        return mask;
1055}
1056
1057static struct file_operations dvb_dvr_fops = {
1058        .owner = THIS_MODULE,
1059        .read = dvb_dvr_read,
1060        .write = dvb_dvr_write,
1061        .ioctl = dvb_dvr_ioctl,
1062        .open = dvb_dvr_open,
1063        .release = dvb_dvr_release,
1064        .poll = dvb_dvr_poll,
1065};
1066
1067static struct dvb_device dvbdev_dvr = {
1068        .priv = NULL,
1069        .readers = 1,
1070        .users = 1,
1071        .fops = &dvb_dvr_fops
1072};
1073
1074int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
1075{
1076        int i;
1077
1078        if (dmxdev->demux->open(dmxdev->demux) < 0)
1079                return -EUSERS;
1080
1081        dmxdev->filter = vmalloc(dmxdev->filternum * sizeof(struct dmxdev_filter));
1082        if (!dmxdev->filter)
1083                return -ENOMEM;
1084
1085        mutex_init(&dmxdev->mutex);
1086        spin_lock_init(&dmxdev->lock);
1087        for (i = 0; i < dmxdev->filternum; i++) {
1088                dmxdev->filter[i].dev = dmxdev;
1089                dmxdev->filter[i].buffer.data = NULL;
1090                dvb_dmxdev_filter_state_set(&dmxdev->filter[i],
1091                                            DMXDEV_STATE_FREE);
1092        }
1093
1094        dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev,
1095                            DVB_DEVICE_DEMUX);
1096        dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr,
1097                            dmxdev, DVB_DEVICE_DVR);
1098
1099        dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192);
1100
1101        return 0;
1102}
1103
1104EXPORT_SYMBOL(dvb_dmxdev_init);
1105
1106void dvb_dmxdev_release(struct dmxdev *dmxdev)
1107{
1108        dmxdev->exit=1;
1109        if (dmxdev->dvbdev->users > 1) {
1110                wait_event(dmxdev->dvbdev->wait_queue,
1111                                dmxdev->dvbdev->users==1);
1112        }
1113        if (dmxdev->dvr_dvbdev->users > 1) {
1114                wait_event(dmxdev->dvr_dvbdev->wait_queue,
1115                                dmxdev->dvr_dvbdev->users==1);
1116        }
1117
1118        dvb_unregister_device(dmxdev->dvbdev);
1119        dvb_unregister_device(dmxdev->dvr_dvbdev);
1120
1121        vfree(dmxdev->filter);
1122        dmxdev->filter = NULL;
1123        dmxdev->demux->close(dmxdev->demux);
1124}
1125
1126EXPORT_SYMBOL(dvb_dmxdev_release);
1127
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.