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