Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.22-rc7 1225 lines 29 kB view raw
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 struct list_head *pos, *head = &demux->feed_list; 377 u16 pid = ts_pid(buf); 378 int dvr_done = 0; 379 380 list_for_each(pos, head) { 381 feed = list_entry(pos, struct dvb_demux_feed, list_head); 382 383 if ((feed->pid != pid) && (feed->pid != 0x2000)) 384 continue; 385 386 /* copy each packet only once to the dvr device, even 387 * if a PID is in multiple filters (e.g. video + PCR) */ 388 if ((DVR_FEED(feed)) && (dvr_done++)) 389 continue; 390 391 if (feed->pid == pid) { 392 dvb_dmx_swfilter_packet_type(feed, buf); 393 if (DVR_FEED(feed)) 394 continue; 395 } 396 397 if (feed->pid == 0x2000) 398 feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, DMX_OK); 399 } 400} 401 402void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, 403 size_t count) 404{ 405 spin_lock(&demux->lock); 406 407 while (count--) { 408 if (buf[0] == 0x47) 409 dvb_dmx_swfilter_packet(demux, buf); 410 buf += 188; 411 } 412 413 spin_unlock(&demux->lock); 414} 415 416EXPORT_SYMBOL(dvb_dmx_swfilter_packets); 417 418void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count) 419{ 420 int p = 0, i, j; 421 422 spin_lock(&demux->lock); 423 424 if (demux->tsbufp) { 425 i = demux->tsbufp; 426 j = 188 - i; 427 if (count < j) { 428 memcpy(&demux->tsbuf[i], buf, count); 429 demux->tsbufp += count; 430 goto bailout; 431 } 432 memcpy(&demux->tsbuf[i], buf, j); 433 if (demux->tsbuf[0] == 0x47) 434 dvb_dmx_swfilter_packet(demux, demux->tsbuf); 435 demux->tsbufp = 0; 436 p += j; 437 } 438 439 while (p < count) { 440 if (buf[p] == 0x47) { 441 if (count - p >= 188) { 442 dvb_dmx_swfilter_packet(demux, &buf[p]); 443 p += 188; 444 } else { 445 i = count - p; 446 memcpy(demux->tsbuf, &buf[p], i); 447 demux->tsbufp = i; 448 goto bailout; 449 } 450 } else 451 p++; 452 } 453 454bailout: 455 spin_unlock(&demux->lock); 456} 457 458EXPORT_SYMBOL(dvb_dmx_swfilter); 459 460void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count) 461{ 462 int p = 0, i, j; 463 u8 tmppack[188]; 464 465 spin_lock(&demux->lock); 466 467 if (demux->tsbufp) { 468 i = demux->tsbufp; 469 j = 204 - i; 470 if (count < j) { 471 memcpy(&demux->tsbuf[i], buf, count); 472 demux->tsbufp += count; 473 goto bailout; 474 } 475 memcpy(&demux->tsbuf[i], buf, j); 476 if ((demux->tsbuf[0] == 0x47) || (demux->tsbuf[0] == 0xB8)) { 477 memcpy(tmppack, demux->tsbuf, 188); 478 if (tmppack[0] == 0xB8) 479 tmppack[0] = 0x47; 480 dvb_dmx_swfilter_packet(demux, tmppack); 481 } 482 demux->tsbufp = 0; 483 p += j; 484 } 485 486 while (p < count) { 487 if ((buf[p] == 0x47) || (buf[p] == 0xB8)) { 488 if (count - p >= 204) { 489 memcpy(tmppack, &buf[p], 188); 490 if (tmppack[0] == 0xB8) 491 tmppack[0] = 0x47; 492 dvb_dmx_swfilter_packet(demux, tmppack); 493 p += 204; 494 } else { 495 i = count - p; 496 memcpy(demux->tsbuf, &buf[p], i); 497 demux->tsbufp = i; 498 goto bailout; 499 } 500 } else { 501 p++; 502 } 503 } 504 505bailout: 506 spin_unlock(&demux->lock); 507} 508 509EXPORT_SYMBOL(dvb_dmx_swfilter_204); 510 511static struct dvb_demux_filter *dvb_dmx_filter_alloc(struct dvb_demux *demux) 512{ 513 int i; 514 515 for (i = 0; i < demux->filternum; i++) 516 if (demux->filter[i].state == DMX_STATE_FREE) 517 break; 518 519 if (i == demux->filternum) 520 return NULL; 521 522 demux->filter[i].state = DMX_STATE_ALLOCATED; 523 524 return &demux->filter[i]; 525} 526 527static struct dvb_demux_feed *dvb_dmx_feed_alloc(struct dvb_demux *demux) 528{ 529 int i; 530 531 for (i = 0; i < demux->feednum; i++) 532 if (demux->feed[i].state == DMX_STATE_FREE) 533 break; 534 535 if (i == demux->feednum) 536 return NULL; 537 538 demux->feed[i].state = DMX_STATE_ALLOCATED; 539 540 return &demux->feed[i]; 541} 542 543static int dvb_demux_feed_find(struct dvb_demux_feed *feed) 544{ 545 struct dvb_demux_feed *entry; 546 547 list_for_each_entry(entry, &feed->demux->feed_list, list_head) 548 if (entry == feed) 549 return 1; 550 551 return 0; 552} 553 554static void dvb_demux_feed_add(struct dvb_demux_feed *feed) 555{ 556 spin_lock_irq(&feed->demux->lock); 557 if (dvb_demux_feed_find(feed)) { 558 printk(KERN_ERR "%s: feed already in list (type=%x state=%x pid=%x)\n", 559 __FUNCTION__, feed->type, feed->state, feed->pid); 560 goto out; 561 } 562 563 list_add(&feed->list_head, &feed->demux->feed_list); 564out: 565 spin_unlock_irq(&feed->demux->lock); 566} 567 568static void dvb_demux_feed_del(struct dvb_demux_feed *feed) 569{ 570 spin_lock_irq(&feed->demux->lock); 571 if (!(dvb_demux_feed_find(feed))) { 572 printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n", 573 __FUNCTION__, feed->type, feed->state, feed->pid); 574 goto out; 575 } 576 577 list_del(&feed->list_head); 578out: 579 spin_unlock_irq(&feed->demux->lock); 580} 581 582static int dmx_ts_feed_set(struct dmx_ts_feed *ts_feed, u16 pid, int ts_type, 583 enum dmx_ts_pes pes_type, 584 size_t circular_buffer_size, struct timespec timeout) 585{ 586 struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed; 587 struct dvb_demux *demux = feed->demux; 588 589 if (pid > DMX_MAX_PID) 590 return -EINVAL; 591 592 if (mutex_lock_interruptible(&demux->mutex)) 593 return -ERESTARTSYS; 594 595 if (ts_type & TS_DECODER) { 596 if (pes_type >= DMX_TS_PES_OTHER) { 597 mutex_unlock(&demux->mutex); 598 return -EINVAL; 599 } 600 601 if (demux->pesfilter[pes_type] && 602 demux->pesfilter[pes_type] != feed) { 603 mutex_unlock(&demux->mutex); 604 return -EINVAL; 605 } 606 607 demux->pesfilter[pes_type] = feed; 608 demux->pids[pes_type] = pid; 609 } 610 611 dvb_demux_feed_add(feed); 612 613 feed->pid = pid; 614 feed->buffer_size = circular_buffer_size; 615 feed->timeout = timeout; 616 feed->ts_type = ts_type; 617 feed->pes_type = pes_type; 618 619 if (feed->buffer_size) { 620#ifdef NOBUFS 621 feed->buffer = NULL; 622#else 623 feed->buffer = vmalloc(feed->buffer_size); 624 if (!feed->buffer) { 625 mutex_unlock(&demux->mutex); 626 return -ENOMEM; 627 } 628#endif 629 } 630 631 feed->state = DMX_STATE_READY; 632 mutex_unlock(&demux->mutex); 633 634 return 0; 635} 636 637static int dmx_ts_feed_start_filtering(struct dmx_ts_feed *ts_feed) 638{ 639 struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed; 640 struct dvb_demux *demux = feed->demux; 641 int ret; 642 643 if (mutex_lock_interruptible(&demux->mutex)) 644 return -ERESTARTSYS; 645 646 if (feed->state != DMX_STATE_READY || feed->type != DMX_TYPE_TS) { 647 mutex_unlock(&demux->mutex); 648 return -EINVAL; 649 } 650 651 if (!demux->start_feed) { 652 mutex_unlock(&demux->mutex); 653 return -ENODEV; 654 } 655 656 if ((ret = demux->start_feed(feed)) < 0) { 657 mutex_unlock(&demux->mutex); 658 return ret; 659 } 660 661 spin_lock_irq(&demux->lock); 662 ts_feed->is_filtering = 1; 663 feed->state = DMX_STATE_GO; 664 spin_unlock_irq(&demux->lock); 665 mutex_unlock(&demux->mutex); 666 667 return 0; 668} 669 670static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed *ts_feed) 671{ 672 struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed; 673 struct dvb_demux *demux = feed->demux; 674 int ret; 675 676 mutex_lock(&demux->mutex); 677 678 if (feed->state < DMX_STATE_GO) { 679 mutex_unlock(&demux->mutex); 680 return -EINVAL; 681 } 682 683 if (!demux->stop_feed) { 684 mutex_unlock(&demux->mutex); 685 return -ENODEV; 686 } 687 688 ret = demux->stop_feed(feed); 689 690 spin_lock_irq(&demux->lock); 691 ts_feed->is_filtering = 0; 692 feed->state = DMX_STATE_ALLOCATED; 693 spin_unlock_irq(&demux->lock); 694 mutex_unlock(&demux->mutex); 695 696 return ret; 697} 698 699static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx, 700 struct dmx_ts_feed **ts_feed, 701 dmx_ts_cb callback) 702{ 703 struct dvb_demux *demux = (struct dvb_demux *)dmx; 704 struct dvb_demux_feed *feed; 705 706 if (mutex_lock_interruptible(&demux->mutex)) 707 return -ERESTARTSYS; 708 709 if (!(feed = dvb_dmx_feed_alloc(demux))) { 710 mutex_unlock(&demux->mutex); 711 return -EBUSY; 712 } 713 714 feed->type = DMX_TYPE_TS; 715 feed->cb.ts = callback; 716 feed->demux = demux; 717 feed->pid = 0xffff; 718 feed->peslen = 0xfffa; 719 feed->buffer = NULL; 720 721 (*ts_feed) = &feed->feed.ts; 722 (*ts_feed)->parent = dmx; 723 (*ts_feed)->priv = NULL; 724 (*ts_feed)->is_filtering = 0; 725 (*ts_feed)->start_filtering = dmx_ts_feed_start_filtering; 726 (*ts_feed)->stop_filtering = dmx_ts_feed_stop_filtering; 727 (*ts_feed)->set = dmx_ts_feed_set; 728 729 if (!(feed->filter = dvb_dmx_filter_alloc(demux))) { 730 feed->state = DMX_STATE_FREE; 731 mutex_unlock(&demux->mutex); 732 return -EBUSY; 733 } 734 735 feed->filter->type = DMX_TYPE_TS; 736 feed->filter->feed = feed; 737 feed->filter->state = DMX_STATE_READY; 738 739 mutex_unlock(&demux->mutex); 740 741 return 0; 742} 743 744static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, 745 struct dmx_ts_feed *ts_feed) 746{ 747 struct dvb_demux *demux = (struct dvb_demux *)dmx; 748 struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed; 749 750 mutex_lock(&demux->mutex); 751 752 if (feed->state == DMX_STATE_FREE) { 753 mutex_unlock(&demux->mutex); 754 return -EINVAL; 755 } 756#ifndef NOBUFS 757 vfree(feed->buffer); 758 feed->buffer = NULL; 759#endif 760 761 feed->state = DMX_STATE_FREE; 762 feed->filter->state = DMX_STATE_FREE; 763 764 dvb_demux_feed_del(feed); 765 766 feed->pid = 0xffff; 767 768 if (feed->ts_type & TS_DECODER && feed->pes_type < DMX_TS_PES_OTHER) 769 demux->pesfilter[feed->pes_type] = NULL; 770 771 mutex_unlock(&demux->mutex); 772 return 0; 773} 774 775/****************************************************************************** 776 * dmx_section_feed API calls 777 ******************************************************************************/ 778 779static int dmx_section_feed_allocate_filter(struct dmx_section_feed *feed, 780 struct dmx_section_filter **filter) 781{ 782 struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; 783 struct dvb_demux *dvbdemux = dvbdmxfeed->demux; 784 struct dvb_demux_filter *dvbdmxfilter; 785 786 if (mutex_lock_interruptible(&dvbdemux->mutex)) 787 return -ERESTARTSYS; 788 789 dvbdmxfilter = dvb_dmx_filter_alloc(dvbdemux); 790 if (!dvbdmxfilter) { 791 mutex_unlock(&dvbdemux->mutex); 792 return -EBUSY; 793 } 794 795 spin_lock_irq(&dvbdemux->lock); 796 *filter = &dvbdmxfilter->filter; 797 (*filter)->parent = feed; 798 (*filter)->priv = NULL; 799 dvbdmxfilter->feed = dvbdmxfeed; 800 dvbdmxfilter->type = DMX_TYPE_SEC; 801 dvbdmxfilter->state = DMX_STATE_READY; 802 dvbdmxfilter->next = dvbdmxfeed->filter; 803 dvbdmxfeed->filter = dvbdmxfilter; 804 spin_unlock_irq(&dvbdemux->lock); 805 806 mutex_unlock(&dvbdemux->mutex); 807 return 0; 808} 809 810static int dmx_section_feed_set(struct dmx_section_feed *feed, 811 u16 pid, size_t circular_buffer_size, 812 int check_crc) 813{ 814 struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; 815 struct dvb_demux *dvbdmx = dvbdmxfeed->demux; 816 817 if (pid > 0x1fff) 818 return -EINVAL; 819 820 if (mutex_lock_interruptible(&dvbdmx->mutex)) 821 return -ERESTARTSYS; 822 823 dvb_demux_feed_add(dvbdmxfeed); 824 825 dvbdmxfeed->pid = pid; 826 dvbdmxfeed->buffer_size = circular_buffer_size; 827 dvbdmxfeed->feed.sec.check_crc = check_crc; 828 829#ifdef NOBUFS 830 dvbdmxfeed->buffer = NULL; 831#else 832 dvbdmxfeed->buffer = vmalloc(dvbdmxfeed->buffer_size); 833 if (!dvbdmxfeed->buffer) { 834 mutex_unlock(&dvbdmx->mutex); 835 return -ENOMEM; 836 } 837#endif 838 839 dvbdmxfeed->state = DMX_STATE_READY; 840 mutex_unlock(&dvbdmx->mutex); 841 return 0; 842} 843 844static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed) 845{ 846 int i; 847 struct dvb_demux_filter *f; 848 struct dmx_section_filter *sf; 849 u8 mask, mode, doneq; 850 851 if (!(f = dvbdmxfeed->filter)) 852 return; 853 do { 854 sf = &f->filter; 855 doneq = 0; 856 for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) { 857 mode = sf->filter_mode[i]; 858 mask = sf->filter_mask[i]; 859 f->maskandmode[i] = mask & mode; 860 doneq |= f->maskandnotmode[i] = mask & ~mode; 861 } 862 f->doneq = doneq ? 1 : 0; 863 } while ((f = f->next)); 864} 865 866static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed) 867{ 868 struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; 869 struct dvb_demux *dvbdmx = dvbdmxfeed->demux; 870 int ret; 871 872 if (mutex_lock_interruptible(&dvbdmx->mutex)) 873 return -ERESTARTSYS; 874 875 if (feed->is_filtering) { 876 mutex_unlock(&dvbdmx->mutex); 877 return -EBUSY; 878 } 879 880 if (!dvbdmxfeed->filter) { 881 mutex_unlock(&dvbdmx->mutex); 882 return -EINVAL; 883 } 884 885 dvbdmxfeed->feed.sec.tsfeedp = 0; 886 dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base; 887 dvbdmxfeed->feed.sec.secbufp = 0; 888 dvbdmxfeed->feed.sec.seclen = 0; 889 890 if (!dvbdmx->start_feed) { 891 mutex_unlock(&dvbdmx->mutex); 892 return -ENODEV; 893 } 894 895 prepare_secfilters(dvbdmxfeed); 896 897 if ((ret = dvbdmx->start_feed(dvbdmxfeed)) < 0) { 898 mutex_unlock(&dvbdmx->mutex); 899 return ret; 900 } 901 902 spin_lock_irq(&dvbdmx->lock); 903 feed->is_filtering = 1; 904 dvbdmxfeed->state = DMX_STATE_GO; 905 spin_unlock_irq(&dvbdmx->lock); 906 907 mutex_unlock(&dvbdmx->mutex); 908 return 0; 909} 910 911static int dmx_section_feed_stop_filtering(struct dmx_section_feed *feed) 912{ 913 struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; 914 struct dvb_demux *dvbdmx = dvbdmxfeed->demux; 915 int ret; 916 917 mutex_lock(&dvbdmx->mutex); 918 919 if (!dvbdmx->stop_feed) { 920 mutex_unlock(&dvbdmx->mutex); 921 return -ENODEV; 922 } 923 924 ret = dvbdmx->stop_feed(dvbdmxfeed); 925 926 spin_lock_irq(&dvbdmx->lock); 927 dvbdmxfeed->state = DMX_STATE_READY; 928 feed->is_filtering = 0; 929 spin_unlock_irq(&dvbdmx->lock); 930 931 mutex_unlock(&dvbdmx->mutex); 932 return ret; 933} 934 935static int dmx_section_feed_release_filter(struct dmx_section_feed *feed, 936 struct dmx_section_filter *filter) 937{ 938 struct dvb_demux_filter *dvbdmxfilter = (struct dvb_demux_filter *)filter, *f; 939 struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; 940 struct dvb_demux *dvbdmx = dvbdmxfeed->demux; 941 942 mutex_lock(&dvbdmx->mutex); 943 944 if (dvbdmxfilter->feed != dvbdmxfeed) { 945 mutex_unlock(&dvbdmx->mutex); 946 return -EINVAL; 947 } 948 949 if (feed->is_filtering) 950 feed->stop_filtering(feed); 951 952 spin_lock_irq(&dvbdmx->lock); 953 f = dvbdmxfeed->filter; 954 955 if (f == dvbdmxfilter) { 956 dvbdmxfeed->filter = dvbdmxfilter->next; 957 } else { 958 while (f->next != dvbdmxfilter) 959 f = f->next; 960 f->next = f->next->next; 961 } 962 963 dvbdmxfilter->state = DMX_STATE_FREE; 964 spin_unlock_irq(&dvbdmx->lock); 965 mutex_unlock(&dvbdmx->mutex); 966 return 0; 967} 968 969static int dvbdmx_allocate_section_feed(struct dmx_demux *demux, 970 struct dmx_section_feed **feed, 971 dmx_section_cb callback) 972{ 973 struct dvb_demux *dvbdmx = (struct dvb_demux *)demux; 974 struct dvb_demux_feed *dvbdmxfeed; 975 976 if (mutex_lock_interruptible(&dvbdmx->mutex)) 977 return -ERESTARTSYS; 978 979 if (!(dvbdmxfeed = dvb_dmx_feed_alloc(dvbdmx))) { 980 mutex_unlock(&dvbdmx->mutex); 981 return -EBUSY; 982 } 983 984 dvbdmxfeed->type = DMX_TYPE_SEC; 985 dvbdmxfeed->cb.sec = callback; 986 dvbdmxfeed->demux = dvbdmx; 987 dvbdmxfeed->pid = 0xffff; 988 dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base; 989 dvbdmxfeed->feed.sec.secbufp = dvbdmxfeed->feed.sec.seclen = 0; 990 dvbdmxfeed->feed.sec.tsfeedp = 0; 991 dvbdmxfeed->filter = NULL; 992 dvbdmxfeed->buffer = NULL; 993 994 (*feed) = &dvbdmxfeed->feed.sec; 995 (*feed)->is_filtering = 0; 996 (*feed)->parent = demux; 997 (*feed)->priv = NULL; 998 999 (*feed)->set = dmx_section_feed_set; 1000 (*feed)->allocate_filter = dmx_section_feed_allocate_filter; 1001 (*feed)->start_filtering = dmx_section_feed_start_filtering; 1002 (*feed)->stop_filtering = dmx_section_feed_stop_filtering; 1003 (*feed)->release_filter = dmx_section_feed_release_filter; 1004 1005 mutex_unlock(&dvbdmx->mutex); 1006 return 0; 1007} 1008 1009static int dvbdmx_release_section_feed(struct dmx_demux *demux, 1010 struct dmx_section_feed *feed) 1011{ 1012 struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; 1013 struct dvb_demux *dvbdmx = (struct dvb_demux *)demux; 1014 1015 mutex_lock(&dvbdmx->mutex); 1016 1017 if (dvbdmxfeed->state == DMX_STATE_FREE) { 1018 mutex_unlock(&dvbdmx->mutex); 1019 return -EINVAL; 1020 } 1021#ifndef NOBUFS 1022 vfree(dvbdmxfeed->buffer); 1023 dvbdmxfeed->buffer = NULL; 1024#endif 1025 dvbdmxfeed->state = DMX_STATE_FREE; 1026 1027 dvb_demux_feed_del(dvbdmxfeed); 1028 1029 dvbdmxfeed->pid = 0xffff; 1030 1031 mutex_unlock(&dvbdmx->mutex); 1032 return 0; 1033} 1034 1035/****************************************************************************** 1036 * dvb_demux kernel data API calls 1037 ******************************************************************************/ 1038 1039static int dvbdmx_open(struct dmx_demux *demux) 1040{ 1041 struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; 1042 1043 if (dvbdemux->users >= MAX_DVB_DEMUX_USERS) 1044 return -EUSERS; 1045 1046 dvbdemux->users++; 1047 return 0; 1048} 1049 1050static int dvbdmx_close(struct dmx_demux *demux) 1051{ 1052 struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; 1053 1054 if (dvbdemux->users == 0) 1055 return -ENODEV; 1056 1057 dvbdemux->users--; 1058 //FIXME: release any unneeded resources if users==0 1059 return 0; 1060} 1061 1062static int dvbdmx_write(struct dmx_demux *demux, const char *buf, size_t count) 1063{ 1064 struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; 1065 1066 if ((!demux->frontend) || (demux->frontend->source != DMX_MEMORY_FE)) 1067 return -EINVAL; 1068 1069 if (mutex_lock_interruptible(&dvbdemux->mutex)) 1070 return -ERESTARTSYS; 1071 dvb_dmx_swfilter(dvbdemux, buf, count); 1072 mutex_unlock(&dvbdemux->mutex); 1073 1074 if (signal_pending(current)) 1075 return -EINTR; 1076 return count; 1077} 1078 1079static int dvbdmx_add_frontend(struct dmx_demux *demux, 1080 struct dmx_frontend *frontend) 1081{ 1082 struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; 1083 struct list_head *head = &dvbdemux->frontend_list; 1084 1085 list_add(&(frontend->connectivity_list), head); 1086 1087 return 0; 1088} 1089 1090static int dvbdmx_remove_frontend(struct dmx_demux *demux, 1091 struct dmx_frontend *frontend) 1092{ 1093 struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; 1094 struct list_head *pos, *n, *head = &dvbdemux->frontend_list; 1095 1096 list_for_each_safe(pos, n, head) { 1097 if (DMX_FE_ENTRY(pos) == frontend) { 1098 list_del(pos); 1099 return 0; 1100 } 1101 } 1102 1103 return -ENODEV; 1104} 1105 1106static struct list_head *dvbdmx_get_frontends(struct dmx_demux *demux) 1107{ 1108 struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; 1109 1110 if (list_empty(&dvbdemux->frontend_list)) 1111 return NULL; 1112 1113 return &dvbdemux->frontend_list; 1114} 1115 1116static int dvbdmx_connect_frontend(struct dmx_demux *demux, 1117 struct dmx_frontend *frontend) 1118{ 1119 struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; 1120 1121 if (demux->frontend) 1122 return -EINVAL; 1123 1124 mutex_lock(&dvbdemux->mutex); 1125 1126 demux->frontend = frontend; 1127 mutex_unlock(&dvbdemux->mutex); 1128 return 0; 1129} 1130 1131static int dvbdmx_disconnect_frontend(struct dmx_demux *demux) 1132{ 1133 struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; 1134 1135 mutex_lock(&dvbdemux->mutex); 1136 1137 demux->frontend = NULL; 1138 mutex_unlock(&dvbdemux->mutex); 1139 return 0; 1140} 1141 1142static int dvbdmx_get_pes_pids(struct dmx_demux *demux, u16 * pids) 1143{ 1144 struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; 1145 1146 memcpy(pids, dvbdemux->pids, 5 * sizeof(u16)); 1147 return 0; 1148} 1149 1150int dvb_dmx_init(struct dvb_demux *dvbdemux) 1151{ 1152 int i; 1153 struct dmx_demux *dmx = &dvbdemux->dmx; 1154 1155 dvbdemux->users = 0; 1156 dvbdemux->filter = vmalloc(dvbdemux->filternum * sizeof(struct dvb_demux_filter)); 1157 1158 if (!dvbdemux->filter) 1159 return -ENOMEM; 1160 1161 dvbdemux->feed = vmalloc(dvbdemux->feednum * sizeof(struct dvb_demux_feed)); 1162 if (!dvbdemux->feed) { 1163 vfree(dvbdemux->filter); 1164 return -ENOMEM; 1165 } 1166 for (i = 0; i < dvbdemux->filternum; i++) { 1167 dvbdemux->filter[i].state = DMX_STATE_FREE; 1168 dvbdemux->filter[i].index = i; 1169 } 1170 for (i = 0; i < dvbdemux->feednum; i++) { 1171 dvbdemux->feed[i].state = DMX_STATE_FREE; 1172 dvbdemux->feed[i].index = i; 1173 } 1174 1175 INIT_LIST_HEAD(&dvbdemux->frontend_list); 1176 1177 for (i = 0; i < DMX_TS_PES_OTHER; i++) { 1178 dvbdemux->pesfilter[i] = NULL; 1179 dvbdemux->pids[i] = 0xffff; 1180 } 1181 1182 INIT_LIST_HEAD(&dvbdemux->feed_list); 1183 1184 dvbdemux->playing = 0; 1185 dvbdemux->recording = 0; 1186 dvbdemux->tsbufp = 0; 1187 1188 if (!dvbdemux->check_crc32) 1189 dvbdemux->check_crc32 = dvb_dmx_crc32; 1190 1191 if (!dvbdemux->memcopy) 1192 dvbdemux->memcopy = dvb_dmx_memcopy; 1193 1194 dmx->frontend = NULL; 1195 dmx->priv = dvbdemux; 1196 dmx->open = dvbdmx_open; 1197 dmx->close = dvbdmx_close; 1198 dmx->write = dvbdmx_write; 1199 dmx->allocate_ts_feed = dvbdmx_allocate_ts_feed; 1200 dmx->release_ts_feed = dvbdmx_release_ts_feed; 1201 dmx->allocate_section_feed = dvbdmx_allocate_section_feed; 1202 dmx->release_section_feed = dvbdmx_release_section_feed; 1203 1204 dmx->add_frontend = dvbdmx_add_frontend; 1205 dmx->remove_frontend = dvbdmx_remove_frontend; 1206 dmx->get_frontends = dvbdmx_get_frontends; 1207 dmx->connect_frontend = dvbdmx_connect_frontend; 1208 dmx->disconnect_frontend = dvbdmx_disconnect_frontend; 1209 dmx->get_pes_pids = dvbdmx_get_pes_pids; 1210 1211 mutex_init(&dvbdemux->mutex); 1212 spin_lock_init(&dvbdemux->lock); 1213 1214 return 0; 1215} 1216 1217EXPORT_SYMBOL(dvb_dmx_init); 1218 1219void dvb_dmx_release(struct dvb_demux *dvbdemux) 1220{ 1221 vfree(dvbdemux->filter); 1222 vfree(dvbdemux->feed); 1223} 1224 1225EXPORT_SYMBOL(dvb_dmx_release);