pax_global_header00006660000000000000000000000064130571413250014513gustar00rootroot0000000000000052 comment=5914a72a22407e5e96b7abf0ce55ab15832897a0 MuMuDVB-2.1.0/000077500000000000000000000000001305714132500127325ustar00rootroot00000000000000MuMuDVB-2.1.0/.gitignore000066400000000000000000000002401305714132500147160ustar00rootroot00000000000000Makefile Makefile.in config.* /aclocal.m4 /compile /configure /depcomp /missing /autom4te.cache /install-sh /src/.deps/ /src/mumudvb /src/stamp-h1 *.o *.sw[po] MuMuDVB-2.1.0/.travis.yml000066400000000000000000000000141305714132500150360ustar00rootroot00000000000000language: c MuMuDVB-2.1.0/COPYING000066400000000000000000000430761305714132500137770ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. MuMuDVB-2.1.0/ChangeLog000066400000000000000000000142101305714132500145020ustar00rootroot00000000000000-- MuMuDVB 2.0 -- New features / improvements : * Autoconfiguration: complete rewrite, more flexible, can follow channel changes, partial autoconf dropped. * EPG: Electronic Programs guide (EIT table) available from the webservices * Video: support for HEVC * Scam: various improvements and fixes * Tuning: Diseqc improvments -- MuMuDVB 1.7 -- New features / improvements : * Implements dual stack for IPv6 Mulicast * Tuning: Support for multiple tuners and DVB-T2 DVB-S2 * Error : Add option filter_transport_error to send packets with error bit set by decoder * Dump : Possibility to dump the raw stream for debugging purposes + update of the man page * Logging: Possibility to choose the destination of the logs : console, file or syslog. The formatting of the logs can be adjusted. * CAM Menu : CAM menu access while streaming (using a web/AJAX interface - see WEBSERVICES.txt * Templates support for more flexibility in autoconfiguration * Webservices : XML webservice exposing detailed streaming status (see WEBSERVICES.txt) * PID : Add option filename_pid Possibility to define the path for the pid file : * DiSEqC : improvments : support of uncommited switches. Set of the tone burst * Autoconfiguration: Several improvements in the options and in the parsing of the DVB tables * Possibility to tune the up/down detection thresholds * Testing suite : test program for various MuMuDVB functions to compile this program, run "make check" * Table parsing : the NIT is parsed for debugging purposes, possibility to use the LCN in autoconfiguration, better detection of PIDs * Signal display : more information (uncorrected blocks) * Cards listing with their capabilities. Bugs corrected : * SDT rewrite improve : we copy only the interesting services to the rewritten SDT * Filter : New option psi_tables_filtering to keep only mandatory PSI PID. Useful for some STB. * Memory leaks Next : * autoconfiguration : merge of the two autoconfiguration modes * IPv6 : HTTP unicast IPv6 * RTSP -- MuMuDVB 1.6 -- New features / improvements : * Support for HTTP Unicast * Implementation of the RTP headers. * The limit in the size of the PAT PID for PAT rewriting has been removed * PAT rewrite is less CPU consuming * ATSC autoconfiguration fully fonctionnal * Autoconfiguration: MuMuDVB can update the PIDs while running if they change * Tuning: Support for circular polarization, more LNBs and possibility to fix LNB voltage to 0V * Tuning: We can set the coderate (FEC) for satellite and cable with the option coderate * Documentation rewrite. The doc is now in asciidoc format + new configuration examples * Autoconfiguration: We wait for all the channels in the PAT to be configured before continuing * Autoconfiguration: New option autoconf_scrambled which permit to autoconfigure scrambbled channels even without cam_support * CAM support: We look on the packets to check if the descrambling was successful * Option dont_send_scrambled to avoid sending scrambled packets (thus not making SAP announces for scrambled channels) * Option to show the traffic for each channel * Reduce CPU usage : experimental feature : DVB buffering * CAM : MuMuDVB can reset the CAM module if it initialize badly * SAP : new option sap_uri. * VLC bug : add an option to avoid sending the SDT, this is a workaround for VLC Bugs corrected : * Cam support : wait a bit more between polling events (solve problems with T-Rex Supermodule v4.6) * Cam : Change the list managment. This solves the problem of only one channel descrambled with aston pro * We check if the PMT_QUERY sending (asking a channel to be descrambled) to the CAM was sucessful. * Autoconfiguration, pat rewrite, CAM : we check the transport_stream id. This solve problems with shared PMT betwwen channels. -- Mumudvb 1.5.4 -- New features / improvements : * New stack for cam support, based on libdvben50221 from dvb_apps * Option dont_tune to avoid mumudvb to try to tune the card (can be used to test dvb-s2) * Non ascii channels names are now well handled by autoconf * Autoconfiguration : Better pid selection (new descriptor types added), can correct issues with some nondetected audio/video pids * Autoconfiguration ; Detection of the PCR PID, this solves problem with vlc and the absence of sound on certain channels * A configuration file is generated after autoconfiguration * Preliminary support for ATSC cards, new option atsc_modulation Bugs corrected : * We don't set the filters multiple times * Better reading of the config file * Segmentation faults with some particular configuration files * Bug in intialisation scripts * Better handling of partial packets. Mumudvb doesn't exit anymore. -- Mumudvb 1.5.3 -- New features : * Option multicast_ttl to override default ttl * Option autoconf_ip_header, to change the first part of ip addresses used by autoconfiguration * Option sap_default_group * Init scripts, cf scripts/ directory * Smaller memory footprint Bugs corrected : * Better conformances to RFC for sap announces (this correct issues with VLC < 0.8.6f) * Better memory freeing * CRC32 calculation was wrong on 64bits platforms -- Mumudvb 1.5.2 -- New features : * Generation of sap announces (beta) Bugs corrected : * Segfault when the directory /var/run/mumudvb doesn't exist * Gcc 4.2 issues when using pat rewriting or autoconfiguration * Small corrections -- Mumudvb 1.5 -- This is a test version for autoconf and cam support New features : * Support for conditionnal acces modules (support of scrambled channels) (beta) * Support for autoconfiguration. Mumudvb is now able to partially decode the stream to find the channels. (beta) * Verbosity levels for log messages * Better default values for DVB-T * common_port directive Bugs corrected : * Logging priority issue (LOG_INFO and co) * General code cleaning * Small bugs Documentation update -- Mumudvb 1.2 -- New Features : * PAT revriting : For some set top boxes, the pid PAT (wich announces the channels) should only contain the streamed channel When you enable pat_revriting, mumudvb modify the pat packets for that Bugs Corrected * Small bugs -- Mumudvb 1.0 -- First major release of mumudvb Main features : MuMuDVB-2.1.0/ChangeLog-detailled000066400000000000000000000512201305714132500164310ustar00rootroot00000000000000See github 2011-08-26 Brice DUBOST * Display the configuration file in the very verbose logs 2011-08-24 Brice DUBOST * Autoconf_lcn option is removed. We parse the NIT by default * MuMuDVB not exciting... Timeout when we cannot join the threads 2011-06-10 Brice DUBOST * Replace autoconfiguration=1 by autoconfiguration=partial 2011-06-05 Ludovic BOUÉ * Replace autoconfiguration=1 by autoconfiguration=partial and autoconfiguration=2 by autoconfiguration=full 2011-06-05 Brice DUBOST * Autoconf: NIT parsing: new descriptor read * Unicast: typo in the XML * CAM: less static strings, less snprintf, some cleaning 2011-05-27 Brice DUBOST * DVB-T2 Expermimental support It could be tested with PCTV nanoStick T2 290e Uses delivery_system=DVBT2 option * tune.c: small modifications to the file header * Small changes in the test suite 2011-05-23 Brice DUBOST * CAM support: Bad initialisation in case autoconfiguration!=full 2011-05-22 Brice DUBOST * Logs : more clear message for SDT rewriting * Decoding of channel names, control caraters badly implemented This close issue 13 on redmine * More detailled message 2011-05-21 Brice DUBOST * Details * New parser : explanation and better values for static limits * EIT sorting The continuity counter is on 4 bits not 5 This mistake had no effect thanks to the ts_header structure * Segfault occurs when I try to flush the log using kill -SIGHUP. This close the issue http://mumuredmine.braice.net/issues/19 * Debugging information: PAT contents displayed more often 2011-05-20 Brice DUBOST * Small mistake * New template: %lang. It's the primary channel language ie the language of the first PID with the language information (in the PMT) 2011-05-19 Brice DUBOST * Reading of the country avaibility descriptor (available in verbose mode) 2011-05-18 Brice DUBOST * Typo in doc + error checking when writing the dump * More stream types descriptions 2011-05-17 Brice DUBOST * New DVB parser, fully dealing with pointer field etc ... * New diagrams * Useless conditions, libpthread is always needed for building MuMuDVB * Preparation for the future TS parser, details below 1. To simplify the work, we unmerge the PMT packet from the CAM versus the PMT packet for the autoconfiguration. * Comments 2011-05-14 Brice DUBOST * Avoid flooding the logs when the card driver doesn't implement some IOCTLs * Issue with join group * Cleanup * Diagram documenting get_ts_packet 2011-05-13 Brice DUBOST * Cleanup * Better directory * Diagrams for TS packet repartition * New DVB parser This parser is able to parse packets with pointer field There is still a few case he cannot deal with, this will be detailed in a drawing soon * Test dump * Replacement of 188 by TS_PACKET_SIZE * Detail to make the code of get_ts_begin more clear * Detail : use a define for the TS packet size * Small improvments test program * Updated tests to implement the new demultiplexer 2011-05-10 Brice DUBOST * Compilation without cam support fixed 2011-05-05 Brice DUBOST * Continuity counter checking Thanks to Sebastien Raillard for the initial patch * Documentation update 2011-05-04 Brice DUBOST * Display of the uncorrected blocks with the signal (logs, XML and JSON) 2011-05-03 Brice DUBOST * Do not use ioctls for signal getting outside monitor thread 2011-05-01 Brice DUBOST * Possibility to follow PMT version for CAM and non autoconfigurated channels Option : cam_pmt_follow, default 0 * Timing information about the ioctl to get signal strength 2011-04-26 Brice DUBOST * Documentation update * Documentation update about sasc-ng 2011-04-25 Brice Dubost * Documentation update for not-so-used options 2011-03-30 Sebastien RAILLARD * Add scrambled status by PID in webservice monitoring 2011-03-03 Sebastien RAILLARD * Correct some CAM issues (polling interval, closing sessions) 2011-04-05 Sebastien RAILLARD * Preventing division by zero in stats calculations 2011-04-10 Brice DUBOST * Branch name in the version 2011-03-08 Brice DUBOST * ersion bump# README-fr~ * Issue with transcoding compile Thanks to Przemysław (HaCeK) Bryniak for reporting 2011-02-13 Brice DUBOST * Simpler example 2011-02-13 Sebastien Raillard * CA PMT reask if partially unscrambled or down chanel. Detect CAM crash (TL disconnect) and exit. correct the issues described in bug #10 in redmine. 2011-02-13 Brice DUBOST * Doc update * Fix compilation issues 2011-02-13 Ludovic BOUE * Documentation update 2011-02-13 Dave Chapman * Using bysid URLs in playlist*.m3u etc 2011-02-13 Brice DUBOST * We are not using permanent multicast addresses so we have to set the T flag * The default scope is now site local link local seems to be attached to an interface, and VLC have difficulties to get the stream if the interface is not specified in the address 2011-02-09 Brice DUBOST * Possibility to choose the multicast interface 2011-02-05 Brice DUBOST * New update of ipv6 documentation * IPv6 documentation update 2011-01-19 Brice DUBOST * IPv6 Autoconfiguration Header improved 2011-01-19 Brice Dubost * SAP and IPv6: Sap was not sent when IPv6 only. Possible crash corrected 2011-01-18 Brice Dubost * IPv6 autoconfiguration 2010-12-30 Brice DUBOST * SAP IPv6 * First ipv6 version Still to do SAP Autoconf Log the IPv6 addr Unicast Transcoding 2010-12-28 Brice DUBOST * Cast * memory leak corrected see http://mumuredmine.braice.net/issues/8 * Small memory leak corrected see http://mumuredmine.braice.net/issues/8 2010-11-28 Brice DUBOST * Compilation warnings about strictg aliasing * Compilation issues when CAM_SUPPORT was not set 2010-11-27 Brice DUBOST * SDT rewrite : we copy only the interesting services to the rewritten SDT. This avoid problems with some SDT which are too big with private descriptors (BBC for example) * Autoconf, detail: possibility to call parse_sdt_descriptor without a service * Testing of the SDT rewrite * SDT rewrite could fail when the SDT was spread over several sections * Debug messages 2010-11-15 Brice DUBOST * Testing : precaution * TS parse : small code factorisation 2010-11-14 Brice DUBOST * Possibility to dump the raw stream for debugging purposes + update of the man page * MuMuDVB test suite : more tests * Atoconf : logs * TS parsing : more logs * Autoconf : SDT reading : we look only for the actual transport stream table 2010-11-13 Brice DUBOST * Typos and spaces * More tests * doc : Columns size * Detail * Logging 2010-11-11 Brice DUBOST * Documentation update * Possible segmentation faults with faulty TS packets corrected 2010-11-08 Brice DUBOST * MuMuDVB test suite now test the get_ts_packets with any data + SDT parser testing, string comput testing Here it's random data (from /dev/urandom) to trace segmentation faults due to corrupted data * TS More debugging 2010-11-06 Brice DUBOST * Autoconf : we avoiid to have alway an empty service * More testing * Autoconf sdt : more debugging * This declaration shouldn't be here 2010-11-04 Brice DUBOST * Testing program for MuMuDVB This is the beginning of a test program for various MuMuDVB functions to compile this program, run "make check" 2010-11-03 Brice DUBOST * Change of the default dvr_buffer_size value * doc : WebServices doc in html 2010-11-02 Sebastien RAILLARD * Add documentation about webservices and new options * Add constant to set the maximum answer length to ENQUIRY question * Add some constants to describe MENU and LIST mmi display objects * Small correction (not a fix) to prevent warning when compiling with gcc 4.4.1 * Correction of bug preventing the CAM PMT UPDATE to be send when reask is enabled 2010-11-02 Brice DUBOST * Unicast : debugging option : flush_on_eagain 2010-11-01 Ludovic BOUE * Tune : Tuner number information 2010-10-19 Sebastien RAILLARD * Add HTTP webservice for AJAX access to the CAM menu during streaming 2010-10-18 Sebastien RAILLARD * Adding HTTP webservice for querying detailled status 2010-10-18 Sebastien RAILLARD * Decrease some HTTP log messages to MSG_FLOOD level * Correcting a cast error * Logging start and stop to make log easier to read (exitcode error description is missing) * Add psi_tables_filtering option * Correct warning message when disabling autoconfiguration in config file with value none * Add option filter_transport_error 2010-10-24 Sebastien Raillard * [PATCH 04/12] Variable renaming to english 2010-10-18 Sebastien RAILLARD * Add log details for source error identification * Change some log messages levels 2010-10-24 Brice DUBOST * Main : no periodic alarm anymore 2010-10-23 Brice DUBOST * We don't discard packets with adaptation field * TS parsing : we check the size of the adaptation field * TS parsing, potential issue with the adaptation field 2010-10-20 Brice DUBOST * Sap: correction of a possible segfault 2010-10-19 Brice DUBOST * Variable uninitialised 2010-10-17 Brice DUBOST * Segfault when closing too early * Possibility to define the path for the pid file : filename_pid This option accepts the templates %tuner, %card and %server * Details * Even less global variables * One call to mumudvb_close * Compilation warning * Cam parameters not global anymore * Comments * Segfault when the card is not able to tune * Tuneparams not global anymore * Uncast_vars not global anymore * Main : server_id not global anymore, autoconf_poll in the monitor thread * Autoconf: we remove the direct access to server_id 2010-10-16 Brice DUBOST * PAT rewrite : stupid pointer ofset, was making the check for current_next_indicator bad * Logging, 's' is not always needed in this log message 2010-10-13 Sebastien Raillard * Bandwidth for IP volume in base 1000 (kBps) * Small format change in CAM log 2010-10-16 Brice DUBOST * Real_start_time was computed too late Thanks to Sébastien Raillard 2010-10-13 root * Correct warning message when disabling autoconfiguration in config file 2010-10-16 Brice DUBOST * "Now" updated more often * Logging * Typo, could influence the no diff timeout * Main: real_start_time is useless here 2010-10-14 Brice DUBOST * TS parsing, we get the good beginning of a ts packet (get_ts_begin) * TS parsing : new function to get the beginning of the payload * TS parsing, we check if the pointer field is not too big 2010-10-13 Brice DUBOST * Autoconf : we take the current_next_indicator in account for the PSIP * Autoconf : we take the current_next_indicator in account for the NIT Thanks to Sébastien Raillard for noticing * Doxygen * SDT rewrite, Autoconf : we take the current_next_indicator in account for the SDT Thanks to Sébastien Raillard for noticing * CAM, Autoconf : we take the current_next_indicator in account for the PMT Thanks to Sébastien Raillard for noticing * PAT rewrite, Autoconf : we take the current_next_indicator in account for the PAT Thanks to Sébastien Raillard for noticing * TS parsing : we take in account the pointer_field 2010-10-12 Brice DUBOST * Log: The logging filename template take the card in account even if it's specified after 2010-10-10 Brice DUBOST * Logging : File flushing interval : log_flush_interval * Freeing on close * Logging: Log file flush and reopen on SIGHUP 2010-10-07 Brice DUBOST * Freeing on close * Logging: The presence of the \n at the end of the log is checked and added if absent * Logging : new option log_header which allow to specify the logging header with templates The implemented templates are %priority %module %timeepoch %date %pid * Typos * Logging : possibility to log on several "channels" 2010-10-06 Sebastien Raillard * Correct buffer size problem when writing HTTP response (in unicast_reply_write) 2010-10-06 Brice DUBOST * Typos 2010-10-05 Brice DUBOST * Template for the logging filename, file oppened in append mode * Logging: possibility to log to a file * Logging: possibility to choose the logging type * Typo * Move the logging config file reading in log.c * New minimum time interval for traffic calculations * Possibility to tune the up/down detection thresholds 2010-10-04 Brice DUBOST * Logging : missing EOL * Main: move of the work made periodically in sighandler to a thread This is to avoid global variables 2010-10-03 Brice DUBOST * Main : move to a thread things triggerd by sigalarm. First step : creation/close of the thread Move of the sap announce sending to this thread * Typos * The libpthread is now a mandatory dependancy of MuMuDVB 2010-09-30 Brice DUBOST * Unicast : Debug option : drop on eagain. This allow packets to be dropped when the socket sending queue is full, should help to solve traffic issues * Unicast : option socket_sendbuf_size to tune the sending socket slicing window (SOL_SOCKET, SO_SNDBUF) * Typo * Tune : possibility for non integer frequencies. DiseqC : more debugging 2010-09-26 Brice DUBOST * Logging, CAM, newlines 2010-09-19 Brice DUBOST * Unicast : we Disable the Nagle (TCP No Delay) algorithm for client sockets The hope is to improve unicast streaming performance 2010-09-09 Brice DUBOST * The warning on the PAT version changed could be printed because of a bad packet The warning is now printed after the full packet is got. This means that the CRC32 is checked before displaying the warning * Compilation warning * Unicast : Better dealing when the data is partially sent from the queue 2010-08-25 Brice DUBOST * CAM : we avoid flooding the logs 2010-08-17 Brice DUBOST * Documentation update 2010-08-10 Brice DUBOST * The --card option, also overrides card_dev_path * The card number specified on the command line overrides the config file 2010-08-01 Brice DUBOST * Documentation. Gettext is needed when compiling from sources * Correction of a possible segfault, while using patterns This bug was hapenning when the pattern is at the end of a string, replaced by an empty pattern (typically %type for sap announces) The final '\0' was not copied by the memmove, so the same pattern was discovered again by strstr etc ... 2010-07-29 Brice DUBOST * Possible segfault corrected. It was due to a misuse of va_start/va_end function 2010-06-23 Brice DUBOST * Transcode, doumentation and removal of useless spaces 2010-06-22 Brice DUBOST * Transcoding: typo and debug messages 2010-06-20 Brice DUBOST * Doumentation update * CAM: update of ca_sys_id * Typos * free forgotten * Transcode : new option transcode_send_transcoded_only This option is made to avoid the untranscoded stream to be sent * Unicast : typo * Typo * New template : %tuner * Compilation warning * Transcode : template and full autoconfiguration support * Transcoding : we copy global options, improvment of the copying function * Transcoding : function to cpy the options + removal of the useless option port 2010-06-19 Brice DUBOST * Function for appenning a string to another -> simpler log code 2010-06-16 Brice DUBOST * Segfault corrected. It was happenning when using partial autoconfiguration and autoconf_lcn * Transcoding : display of the available codecs in verbose mode 2010-06-15 Brice DUBOST * Log level * Code moving * Autoconf: improved logging * Some updqtes on transcoding. This is the first step towards transcoding working with full autoconfiguration For working with full autoconf, we need to be able to set treanscoding options outside a channel and these options to be copied back onto the created channels. Moreover we also need to support templates for the url 2010-06-14 Brice DUBOST * New command line option : --server_id. Documentation update This new option if for the template %server 2010-06-13 Brice DUBOST * More explicit message * Small corrections * Checking of the card status to detect a lost signal * Details * Logging improvments 2010-06-12 Brice DUBOST * Correction of a possible SEGFAULT while parsing the NIT (for getting the LCN) The decriptor len could become negative but it was an unsigned char :( * Small doc update * Possible problem when tuning_timeout is set to 0 2010-06-07 Brice DUBOST * autoconf_ip_header was broken 2010-06-06 Brice DUBOST * ypo in traffic calculation * Channel language detection + better PID identification Thanks to Sebastien Raillard for the original patch 2010-05-30 Brice DUBOST * CAM : various improvments, new options New options : cam_delay_pmt_send, cam_interval_pmt_send More logs concerning the CAM Catching of a part of the errors from the libdvben50221 2010-05-23 Brice DUBOST * Author 2010-05-13 Brice DUBOST * The init scripts set the adapter * Support for multiple tuners Thanks to Romolo Manfredini romoloman hotmail com for the patch 2010-05-13 Brice DUBOST * Documentation update * Memory freeing 2010-03-07 Brice DUBOST * Typo 2010-03-01 Brice DUBOST * Autotools, small bug 2010-02-27 Brice DUBOST * Traffic in kb/s * Debian init script: test corrected Thanks to Florent R. for reporting * Unicast: channel numbers starting at 1 * Autoconf: New option autoconf_multicast_port, allows to define the multicast port with templates 2010-02-21 Brice DUBOST * CAM support: option cam_reask to ask again the cam for a channel if it stay scrambled * Debug and typos 2010-02-07 Brice DUBOST * OpenWRT: flags for c99 are not well detected by the ./configure 2010-01-26 Brice DUBOST * Indent 2010-01-24 Brice DUBOST * Typos 2010-01-15 Brice DUBOST * New template: %server and option server_id 2010-01-10 Brice DUBOST * Autoconf : possibility to use template for autoconf ip 2010-01-06 Brice DUBOST * Flexibility for the unicast port set by autoconfiguration * Conf generation: simpler way to detect autoconf parameters 2010-01-05 Brice DUBOST * TS_id => service id * Math evaluation: a bit less efficient but simpler functions * Unicast: possibility to use mathematical expression for the port_http * Function to compute a mathematical expression containing + and * (works on integers only) 2010-01-03 Brice DUBOST * Tuning : More waiting. Should improve the tuning on some cards * Tune : ident MuMuDVB-2.1.0/Makefile.am000066400000000000000000000001601305714132500147630ustar00rootroot00000000000000AUTOMAKE_OPTIONS = foreign SUBDIRS = src doc doc: cd doc && $(MAKE) $(AM_MAKEFLAGS) doc .PHONY: $(SUBDIRS) MuMuDVB-2.1.0/README000077700000000000000000000000001305714132500160502doc/README.txtustar00rootroot00000000000000MuMuDVB-2.1.0/README-fr000077700000000000000000000000001305714132500170622doc/README-fr.txtustar00rootroot00000000000000MuMuDVB-2.1.0/config.rpath000066400000000000000000000000001305714132500152250ustar00rootroot00000000000000MuMuDVB-2.1.0/configure.ac000066400000000000000000000123611305714132500152230ustar00rootroot00000000000000# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. AC_PREREQ([2.61]) AC_INIT([MuMuDVB], [2.1.0_20170305_mumudvb2], [mumudvb@braice.net]) AC_CONFIG_SRCDIR([src/mumudvb.c]) AM_INIT_AUTOMAKE AC_CONFIG_HEADERS([src/config.h]) dnl dnl Check for linux dvb api headers dnl AC_CHECK_HEADER([linux/dvb/dmx.h]) if test "$ac_cv_header_linux_dvb_dmx_h" = no; then AC_MSG_ERROR([linux dvb api headers are required to build]) fi # Checks for programs. AC_PROG_CC AC_PROG_INSTALL AC_PROG_MAKE_SET AC_PROG_CC_C99 dnl dnl Iconv stuff dnl AM_ICONV AC_CHECK_LIB([dvbapi], [dvbdemux_set_section_filter]) AC_CHECK_LIB([ucsi], [atsc_text_segment_decode],[atsc_long_names="yes"], [atsc_long_names="no"]) AC_CHECK_LIB([pthread], [pthread_create]) AC_CHECK_LIB([rt], [clock_gettime]) AC_CHECK_LIB([m], [log2l]) dnl dnl cam support dnl AC_ARG_ENABLE(cam_support, [ --enable-cam-support CAM support (default enabled)],,[enable_cam_support="yes"]) if test "${enable_cam_support}" = "yes" then AC_CHECK_LIB([ucsi], [atsc_text_segment_decode],[], [enable_cam_support="no"]) AC_CHECK_LIB([dvben50221], [en50221_tl_create],[], [enable_cam_support="no"]) if test "${enable_cam_support}" != "no" then AC_DEFINE(ENABLE_CAM_SUPPORT, 1, Define if you want the CAM support) else AC_MSG_WARN([libucsi and libdvben50221 are needed for CAM support]) fi else enable_cam_support="no" fi AM_CONDITIONAL(BUILD_CAMSUPPORT, [test "${enable_cam_support}" != "no"]) dnl dnl scam support dnl AC_ARG_ENABLE(scam_support, [ --enable-scam-support SCAM support (default enabled)],,[enable_scam_support="yes"]) if test "${enable_scam_support}" = "yes" then AC_CHECK_LIB([dvbcsa], [dvbcsa_bs_decrypt],[], [enable_scam_support="no"]) if test "${enable_scam_support}" != "no" then AC_DEFINE(ENABLE_SCAM_SUPPORT, 1, Define if you want the SCAM support) else AC_MSG_WARN([libdvbcsa are needed for SCAM support]) fi else enable_scam_support="no" fi AM_CONDITIONAL(BUILD_SCAMSUPPORT, [test "${enable_scam_support}" != "no"]) dnl dnl Test coverage dnl AC_ARG_ENABLE(coverage, [ --enable-coverage build for test coverage (default disabled)],, [enable_coverage="no"]) AS_IF([test "${enable_coverage}" != "no"], [ CFLAGS="-fprofile-arcs -ftest-coverage ${CFLAGS}" CXXFLAGS="-fprofile-arcs -ftest-coverage ${CXXFLAGS}" LDFLAGS="-lgcov ${LDFLAGS}" ]) dnl dnl duma support dnl AC_ARG_ENABLE(duma, [ --enable-duma Debbuging DUMA library (default disabled)],, [enable_duma="no"]) if test "${enable_duma}" = "yes" then AC_CHECK_LIB([duma], [_duma_malloc],[], [enable_duma="no"]) if test "${enable_duma}" != "no" then LDFLAGS="-lduma ${LDFLAGS}" else AC_MSG_WARN([The DUMA library needs to be installed before]) fi fi AC_ARG_ENABLE(android, [ --enable-android Build for android (default disabled)],,[enable_android="no"]) if test "${enable_android}" = "yes" then AC_DEFINE(ANDROID, 1, Define if you want build for android) fi AC_ARG_ENABLE(tune_old, [ --enable-tune_old Use old code for tuning (default disabled)],,[enable_tune_old="no"]) if test "${enable_tune_old}" = "yes" then AC_DEFINE(TUNE_OLD, 1, Define if you want the old code for tuning) fi # Checks for header files. AC_HEADER_RESOLV AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdint.h stdlib.h string.h sys/ioctl.h sys/socket.h sys/time.h syslog.h unistd.h values.h]) # Checks for typedefs, structures, and compiler characteristics. AC_TYPE_INT32_T AC_TYPE_SIZE_T AC_TYPE_UINT16_T AC_TYPE_UINT32_T AC_TYPE_UINT8_T # Checks for library functions. AC_CHECK_FUNCS([alarm gettimeofday inet_ntoa memset socket strerror strstr]) AC_CONFIG_FILES([Makefile doc/Makefile src/Makefile]) AC_OUTPUT #put resume at the end echo "" echo "-------------------------------------------------------" echo "MuMuDVB configure results:" echo "" echo "Features" echo "" if test "${enable_cam_support}" != "no" ; then echo "Build with CAM support: yes" else echo "Build with CAM support: no" fi if test "${enable_scam_support}" != "no" ; then echo "Build with SCAM support: yes" else echo "Build with SCAM support: no" fi if test "${atsc_long_names}" = "yes" ; then echo "Build with ATSC long names support: yes" else echo "Build with ATSC long names support: no" fi if test "${enable_android}" = "yes" ; then echo "Build with compatibility for android: yes" else echo "Build with compatibility for android: no" fi if test "${enable_tune_old}" = "yes" ; then echo "Build with old tuning code: yes" fi echo "" echo "Debugging" echo "" if test "${enable_coverage}" = "yes" ; then echo "Build with code coverage debug symbols yes" else echo "Build with code coverage debug symbols no" fi if test "${enable_duma}" = "yes" ; then echo "Build with debugging DUMA library yes" else echo "Build with debugging DUMA library no" fi MuMuDVB-2.1.0/devtools/000077500000000000000000000000001305714132500145715ustar00rootroot00000000000000MuMuDVB-2.1.0/devtools/update_version.sh000077500000000000000000000002331305714132500201550ustar00rootroot00000000000000#/bin/bash # $date=date +%Y%m%d sed -e s/VERSION/`date +%Y%m%d`_`git branch --contains HEAD | grep \* | tr -d "* "`/g configure.ac.template > configure.ac MuMuDVB-2.1.0/doc/000077500000000000000000000000001305714132500134775ustar00rootroot00000000000000MuMuDVB-2.1.0/doc/CAM_menu_interface.png000066400000000000000000000414321305714132500176550ustar00rootroot00000000000000PNG  IHDRK;EtEXtSoftwareAdobe ImageReadyqe<BIDATx;o$GS #{ 9md, h`/#-ІAwELh:?cog3p29$baKvXZ{bX<.U!Yd2 _)u ` 7:ܼ2խT>74%ёы{zGUi;I'='vS }ʠΡэ}rҩu>ZZ9f3:)HZë*㜻4f{w)l2;& :7::5IwMt:;Q<'j4ߑlNεaU|4nFpyhGHbѮWمwN Ch (FI3ZuQ8p@p@ ( (P8p@(P8p@ B!+߬ydq)efWnHJ^z=;E ک MY_mK]]-bYX2\5T`>UkU:V YYՅ?nMGl*fVv*|2tiE^kOfhv6[ϵMˋMy\j>ܑx^:uu'՟e\gFNZU8܎֪&y鄋E QDAĠGE8ZPivRG٩=4{C9ަ@}/+UnȦ .!J$.>$62]^<~rVŹQf^;_aswMr~Cc -XL^'Ȍ@mCuaⴺ6<6D]cMˋ+-Ջ}q\ )TF\m|g+2wFG5yiMM8UMV)\Z <'y?'m EUh*ZZ <]^梲^,vky)̻o>.,h2B*tm2.YXf;AD(RtkYRK_lƈuY=tl񾉼I>WOgFhU}jhfH_DZ !g^e zJFhӊ Pv@my 9k=㇬C&={]yHGĤOI{̷F Yv7:^۞zE]MO*2۶5ȳMe& (8k[*v%qZlj(o&bǰș0c1fD6haDgy 闞*N5s ?],H^G>]Osԥ"'T$"ƕ5=o^ ךz>2w G"9{xpY"bFAޓNFhexfWf~I퐸Um>NL2hS뱹:y";97g]tx M٫vZz i]j%L.Ӫxu_W \-,quVsm&Ulk*f$텬чJⳆёLhԻr[kiqz=/6ہN7:TMfEzweUo-zpՋ[=ݞ}S-Mr! 关{.\`TD0$^ӭ\>XdtJ_+* k<'DW1u[5wHԡJH][}`wxyLվ6葦#<<׃ɼo~2Ws*b>o]HLw4y0Oqi7֥pֶyx6 ƮR>I:æY:a+Ux3SٴpIA$%^`UZ])U%H^g儓zL,^x6гVi7rKJV <^P8p@ @ (P8 (P8p@P8p@ W&4׎1"VwMřԋ+duqXe%ʣ%IS]7bӚW緆(R۰P㋣y(?]l*|XX^u[ٱ-OlvM^dySQ,\,ʣPFoCdhf[M%i.]̃8sy?&-Ipϥ'9Y1v˭>q::$rW.:[m (u{i֦pG AH0=Zh<]i$}Ǜxi~{{]ƻ{փ)e. 1ĴϞK]Hvvxg'៖yR&PYo LY'F_j\h;r> a<I{='rͫvΥC@ ![o=^L߰}8 (P8p@(P8p@ @ )|6Q4qF!v#>}(jO3c*}8.P8p¯.4yg-|*Γx\0y(.NGU96xk"%g+gTL =U| h'ƣT*8 ;:Y߉2y-1bQJ#O/^\nݝQteU W'^!Uq]=u |5 Pݕ˳FyRpppp}9|]_wG4KE]__B&r0wd*uY%>^)_TA2e 'Wd!UBvX/ #*E[܈=(Hw;oH[3x:ͺfڣ*?^6zC($䶘b)9|-;B''F R5DONN鍇wHȐ@mu9JgY*TswVԕQ^U#!r NtP]7GJݴMzPDnwԪߗWa\,Y9jnDQ yemuTbWgdPm,2 Gih-WhD _XEueE*6% pvkLj] ]58!މje{PCr`h35 L=iKdeӬb 7RRMMÛ1PCdU 7<4L-1-BUT$ ,X)Y)ݎ'˲Ɩe~uPJ㒮3 ~ɟViV]k*'=͌-[b P՞b͙!)#~aw^ &Ҋ{D{r֥职̙ Q) \F.T?=-)wb?<3.vW~H>ԈaҼ}vRជaLKyz&uF1\ug7DL{c2n=UߞMˮPSD-!tyn>UibłLsf-륬Ew*s$.+GWih\XԢzy=WyP]og,𬟯:F1C`3cqq>ygH,*}b%:ԙl$~oogz+{([FчV9ڇ Q:~p%0(UAwyzvVWnG R[^R0Gq(|$t4BOM=/} R$ȠoiziruyquBY4Z"'ӓlwngb{@tmDvzbE< <ϩ%n~.R=Ơ El@[49w=fr81<ƂQf5H΅LarSH\ḧV"E|򝮬 1:CEubk1y&ko_ ^ BcliVfJ ]kDε1P̆9DEzvb@%zW-B*n-خܽ^#48 EsV q_;6ݜʡͺu،o49v\mm#t ;^,TTMNrJF)G儘w uvgegkV$oEgPGK DjcY)"~Hp:1re;񢉹z Ʊ̼sk/"oj.rW$RL=֌^[엾.pu&_:ߖ (R@ K J`(P8NyvFLW^Đr};dc-bmΖ B6nPr wnJP焓6 R^(+VvɦT~@nTߢE80<^ٲv/'X'i͓+yq"v͝R|~_- C|Rۼ6Y(k~/o{iK4E__鮁JO// 4=KBye"Y48Τ|CxL)Mzw~]h6:>gV3os VD)âV6gfjKw-H`vU/bFwy,T5LBoU/ *oޢ3)oR8]Wx;Y~uW>E6t\=^Wx%:쿵۟}5Shu?PW}u~)fe|UuYz[rseY] dq^syBwp|siO 7Pa'=PnKV/|ӓ}l3\7\lu7^ʭR|CXjVB@oowf".dpG'j(#pnδew-+X_~z@OVM[on' yf^Y LךP+tKFQI<އ-@=5zj/uXXd k/YvC|'^NA[ՌU< j1ir.CkN9Q^pDt~WYh9ȦPW6 ,h7J/uWՈ*Ri6MW.'u^DiJhz`Gb^icqCE Vs%5'}hv7Dc1ɕ8_bKAn8^*N=r>Ch-n' oʫ{e2ԾTh9l_Wo@kCZzeP|_|N˽]~:3ױcYcictXh(^*˗ʢƒ*dWy`l}x`ٟt~2{dmEIU` wJ_OBbUحT_կ ~^Eja{,;:@+^ۀ~=nU [:.)6x'ÕIlHCwLZ(%:UoF=+'N{Q\ZS`p;xu<׭KE{qY>83`N(8k~ԩC*}YO`eo?W{pIJp6jXuwS(X_z{"?# H]ՉL=^w6jxL.9a/!޿3ܜ_zJhn嬎9-&մTqԼYў_#B&s#8\CVvIY ΍`} ߈_zU[SL#&s#X7痮fȮEԸ5L#&\t@tYVЗӸɇ Mb)_.'^ f1j~vf~9@Ͼ z3~; qz< )S ŒDj;Ed]#7w8Q: Ke `]Q:p@` &aSz ,[ tatԃ64ڋvVoxS`.}Ps>Ȇ=WFm;冡D$^?6ЪD(N;?{]ŞZqXϵ:8҉҃yp.PFkK7,-ֺYx6(s_.RQ>2..ϭ&nLj{+v^wl˃s =AحK/پK s EZi-d![)+gqasH3C% pJl~踲:70?V\\=Xy`\Ck՘떭* 3 >"j\K6W`k (/z(^ Fsks'-[K&չ.nh'_Έ[&ҭ,`yȦĵ/p<+juo1ro`/Rg2 (`/}Pec #SnhU `y;sQ.x[:OV対uSܱZ;:@?m)b7~^^2&gWg8zWRqO4ҝG (ԃz,`Y0wOZ^`׼W /M6l6x8K SKs/]aYSbvUIcz6E\=Y$}8pXs_:}8l/ (P8 (P8p@P8p@ @ Փ"-mّ"i7ɛNy [^<7],F2Eb[|*[/T1>]tx F^;S ;ũūC R'IEMضU%wT$V~ U`DS#ŸN4aOQO]ݓP)6'ֽ}&pKȨvdH f>~:)aְdrش{r:Gzn8rr^UN+EU:!1 O;NFdάEŢ;zd>/]'lgQE5IحϗdVU뺝v/u2+;ԅַ#[K:nxr oW c ]o(Pjh6jOny>8Njo^T53ޮ7 ܐ|F80 (P8p(P8p@p@ ( (P8p@O|eBmjgj&wX<9#gV!)\4Z?բٰ_ZܷMͳuv\`X,"ˋ-og+Mb]ݶ&[}?r::zxhZԀqWF {ǹ(ogG_,[eA{5B\^<co9} o|◊znuAuӣu@8 qmg-|§vSL;3K}-H-g\x"gI˧M`Z<0K[\5^b0~r.|Z\\,u[`~0OB_-܆bt)kC+}&|m(`]p@  (P8p(P8p@gE0:\ޣPv#>s _}EGѭ輿Ӈk^_bJ>WlѵVxw25EGmIѵVxPݠ( 8 > 7>`z l]h%]+t%woMPjy_-8WS*M(,Qv+Wبq^Qs%ӌvN> s^٣Gb $Q }yLM}ďc̥a=ÜK.e61 QEr-*77ߣpf'#@?zuA܌k mTӯou=ә'elh˼~ Aˠp(P87(Q*>AQt#Px܍(:q8l\2E#J;Xp0X^ۆk5`y=n{3ֈEGm(P8(VcVºePkFKMl7 .}u&J8c:"ӉXZVSjeJѳ͒q }s̪ݺ*Rg|:g8Bxrbt q[#,ڊH={6qd 3lDVXʨhgmUvGua-''=u[oB+g3FxV&ܣq8ۂEM(cǑ-˜(u6\v ʄ]Y#3E8V+LX^HL8,GmCѵVxq E=EZk6p(8 '[[ io(^E7214u먰Eǚ'm-Yt2(|5Ux|I?^d[Ś1c߆&;bFp#V/kZ\«(q*gCo.B6O踋uF${|hROxH2InYEZh.[FD=[LhY*ƼX|L>w2ޗ^H=#]^oQcF#+S)Vz_0-uۚoǹDEG (HaeBQtۮpֈ EGэ@c+ vV&\,GmV& ף趡Z+/AYܼKY$Bx_Lݕ{BڏrOO)/Ÿ~Ȟҵ7ٓ?/{FjeQ->=~?y /{4"n>uOˎo?7eHtY6O>ůr2?+\?츑;|2x~_)~1ݟeP]عn?Lq?~㏽^g>){'wӴ~On~2L""k.˼WGoV{.B߳Yk巟T7,ysDW ߖ׏/R0/"坫?>?~qlǺ|<ɧ|cF;Kh?r<Εi {:}t߼ӟ_Oӏs_?0w4?|_כ`.ǟۄŏo:s)v~kDW?}2c>N7DGt=DӇ?y^~^e+pÖEcF^ۍ[ip?'giwȅ$t9cj:B保◝>hcQ_~T可{Z% >r==bV}_g~O~_za/#^鹑`4EĞɈ=wC?r8~;}-djdw/??~'ŊO> Version 2.0.0 [NOTE] An HTML version of this file is available on http://www.mumudvb.net[MuMuDVB's website]. What limits the number of transponders I can stream ? ----------------------------------------------------- MuMuDVB has a low CPU footprint, so except on embedded systems, the CPU will not be the limiting factor. You will usually be limited by your network or the capacity of the PCI/PCI-E bus. How can I stream to a large number of unicast clients ? ------------------------------------------------------- If you need high unicast load, it is best to split the unicast distribution from the DVB demuxing. To do this you can use together with MuMuDVB, other software like http://git.sesse.net/?p=cubemap[cubemap]. Such software can scale very well and use MuMuDVB stream as input with configuration like --------------------------------------------------------------------- stream /udp.ts src=udp://@239.100.100.100:1234 backlog_size=10048576 --------------------------------------------------------------------- Cards not available ------------------- MuMuDVB is able to support as many cards as the operating system does. To know which cards MuMuDVB sees, use `mumudvb -lv`. Special satellite Bands ----------------------- MuMuDVB supports satellites in the Ku band, with universal or standard LNBs. Support for satellites in the S or C band is implemented via the use of the lo_frequency option. See `doc/README_CONF.txt` (link:README_CONF.html[HTML version]). System wide freezes ------------------- Try to avoid ultra low cost motherboards. They can crash when dealing with large data streams. VLC can't read the stream, but it is fine with xine or mplayer -------------------------------------------------------------- * For VLC, you must specify the PMT PID in addition to the audio and video PIDs. The best solution is to use autoconfiguration so MuMuDVB will discover the PIDs for you. If you want to stick to manual mode, you can use the verbose mode of VLC (`vlc -v`) and you'll see a line like: `[00000269] ts demuxer debug: * number=1025 pid=110` You'll have the PMT PID associated with your program number. You can also use dvbsnoop, or see how to find PIDs in `doc/README_CONF.txt` (link:README_CONF.html[HTML version]). VLC shows the video but no audio -------------------------------- * This problem can happen if the PCR (i.e. clock) information is not carried with the video. In this case, you have to check if the PCR PID is in the list of PIDs. See above answer on how to get PIDs MuMuDVB can't daemonize ----------------------- * So that it can daemonize, MuMuDVB needs the directory `/var/run/mumudvb/` to be writable, in order to write its process identifier and the channel list. Tuning issues with DVB-T ------------------------ * You must check tuning settings. Keep in mind that auto bandwidth usually does not work. What is the meaning of BER, SNR and Strength? --------------------------------------------- * BER: Bit Error Rate * SNR: Signal to noise ratio * Strength: Strength of the signal received by the card. These values are reported to MuMuDVB by the card driver. The units will depend on the card, the driver and the options of the driver module. TBS cards ~~~~~~~~~ For TBS cards, you can have the signal to noise reported in Es/N0: ETSI (European Telecommunications Standards Institute) specification for DVB-S/S2 states dB of the signal (measured in Es/N0 dB) that is the minimum needed for error-free reception, that's called "Es/N0 Threshold" To activate SNR in Es/N0, you have to specify in `/etc/modprobe.d/tbs.conf` ------------------------------- options tbsfe esno=1 options isl6423 esno=1 ------------------------------- The SNR will be in 0.1dB EsN0 (a value of 100 is 10dB Es/N0) You can also activate the signal strength in dBm by specifying ------------------------------- options tbsfe dbm=1 options isl6423 dbm=1 ------------------------------- The signal strength will be in '-1dB' (a value of 42 is -42dBm) The set-top box display a blank screen -------------------------------------- * If the stream is working well when reading it with a computer and not with your set-top box, this is probably because your set-top box needs the PAT PID to be rewritten. To do this add `rewrite_pat=1` to your config file. The CAM is complaining about locked channels -------------------------------------------- * Some viaccess CAMs can have a lock for "mature" channels. To deactivate this lock go on the CAM menu using "gnutv -cammenu" for example (from linuxtv dvb-apps). You have to set the maturity rating to maximum and unlock Maturity rating in Bolts submenu. VLC doesn't select the good program even with PAT rewriting ----------------------------------------------------------- You also have to rewrite the SDT PID using the `rewrite_sdt` option [[problems_hp]] My multicast traffic is flooded (I have a "very old" HP procurve switch) ------------------------------------------------------------------------ The best explanation is found in the HP multicast routing guide. On switches that do not support Data-Driven IGMP, unregistered multicast groups are flooded to the VLAN rather than pruned. In this scenario, Fast-Leave IGMP can actually increase the problem of multicast flooding by removing the IGMP group filter before the Querier has recognized the IGMP leave. The Querier will continue to transmit the multicast group during this short time, and because the group is no longer registered the switch will then flood the multicast group to all ports. On ProCurve switches that do support Data-Driven IGMP (“Smart” IGMP), when unregistered multicasts are received the switch automatically filters (drops) them. Thus, the sooner the IGMP Leave is processed, the sooner this multicast traffic stops flowing. Switches without problems (supporting data driven igmp): * Switch 6400cl * Switch 6200yl * Switch 5400zl * Switch 5300xl * Switch 4200vl * Switch 3500yl * Switch 3400cl * Switch 2900 * Switch 2800 * Switch 2500 Switches WITH problems (NOT supporting data driven igmp): * Switch 2600 * Switch 2600-PWR * Switch 4100gl * Switch 6108 So if you have one of the above switches this is "normal". The workaround is to make MuMuDVB join the multicast group. For this put `multicast_auto_join=1` in your configuration file. MuMuDVB is eating a lot of CPU with sasc-ng ! --------------------------------------------- If you use sasc-ng + dvbloopback, MuMuDVB will eat more CPU than needed. A part of this CPU time is used to descramble the channels, another part is due to the way dvbloopback is implemented and the way MuMuDVB ask the card. To reduce the cpu usage, see <> section. In the case of using MuMuDVB with sasc-ng this improvement can be quite large. Or you can use oscam. The reception is working but all the channels are down ------------------------------------------------------ If the signal is good but MuMuDVB tells you that all the channels are down and you are sure about your PIDs it can be due to your CAM module if you have one. Try after unplugging your CAM module. To check deeper you can look to the traffic sent to each channel with the WEBSERVICES or the command line flag. I want to stream from several cards ----------------------------------- You need to launch a MuMuDVB process for each card. I want to stream the whole transponder on one "channel" ------------------------------------------------------- MuMuDVB can stream all the data received by the card to one "channel" (multicast or unicast). In order to do this you have to use the put the PID 8192 in the channel PID list. I have several network interfaces and I want to choose on which interface the multicast traffic will go ------------------------------------------------------------------------------------------------------- In order to specify the interface, you can specify a route for the multicast traffic like : --------------------------------------------------- route add -net 224.0.0.0 netmask 240.0.0.0 dev eth2 --------------------------------------------------- or use multicast_iface4 and multicast_iface6 options What does the MuMuDVB error code means ? ---------------------------------------- Here's a short description of the error codes ------------------------------ ERROR_ARGS=1, ERROR_CONF_FILE, ERROR_CONF, ERROR_TOO_CHANNELS, ERROR_CREATE_FILE, ERROR_DEL_FILE, ERROR_TUNE, ERROR_NO_DIFF, ERROR_MEMORY, ERROR_NETWORK, ERROR_CAM, ERROR_GENERIC, ERROR_NO_CAM_INIT, ------------------------------ I get the message "DVR Read Error: Value too large for defined data type" what does it mean ? --------------------------------------------------------------------------------------------- This message means that an overflow append in the card drivers buffer. I.e MuMuDVB was not able to get the packets sufficiently fast. This issue can have various causes, anything which an slow down (a lot) MuMuDVB an create this message. To avoid it you can try threaded_read see <> section. Faulty network switch ~~~~~~~~~~~~~~~~~~~~~ I experienced the "DVR Read Error..." message very often on my Streaming Server (ia64 Madison 1.3Ghz) (with errors in the video). I could solve the problem by exchanging the network switch. The old switch was limiting multicast traffic to 10Mb/s per port. This limit is not documented. I have tested the limit the programm dd and mnc (Multicast netcat, http://code.google.com/p/mnc/) dd if=/dev/zero bs=188 count=1000000 | ./mnc-bin 239.10.0.3 I looked with "iftop" at the current network statistics and with my old switch i saw the limit at 10Mb/s with another switch I was able to transmit 92Mb/s ~ 100% of the avaiable bandwith. Thanks to Jan-Philipp Hülshoff for the report Flow control issues ~~~~~~~~~~~~~~~~~~~ Switch: Alcatel Omniswitch 6850E The problem turned out to be the network: Even though the interface was at 1GB/s, the switch it is connected to uses 'flow control'. This, is, for multicasts, generally a bad idea. In this case, one of the machines that received the multicast negotiated their port to 100MBit. Since the switch couldn't deliver the multicast packets fast enough, it applied "back pressure" via ethernet flow control in order to throttle the data rate. This causes the 'sendto' call in MuMuDVB to block, delaying reads from the DVB interface, causing buffer overflows inside the DVB driver. The giveaway was, even though I configured all 8 input to multicast everything they have, data rate did not increase beyond 97MBit. It should have been around 400MBit. Another giveaway, if you know where to look: ethtool -S p1p1 ... rx_flow_control_xon: 4028153 rx_flow_control_xoff: 4028155 ... tells you that there is 'backpressure' from ethernet, at least the Intel e1000 driver does. Lesson: - Don't trust the network - Don't use ethernet flow control with multicast (Report from Mathias) This is interesting, we found flow control INCREASE the perceived quality of IPTV on access ports as this allows consumer grade STBs to cope with high bandwidth channels. This might be highly vendor dependent support of IEEE 802.3x, as most equipment only supplies a "flow control on/off"-switch, but it should provide "honor received pause-frames", "send pause-frames" switches in configuration (or at least clarify what kind of support is implemented). Thanks to Johannes Deisenhofer I have an issue which is not reported above ------------------------------------------- Please report it to the .Mailing list: - mailto:mumudvb-dev@REMOVEMElists.crans.org[MuMuDVB mailing list] - https://lists.crans.org/listinfo/mumudvb-dev[MuMuDVB mailing list information and subscription] With as much information as possible, like full verbose logs, hardware, description. If it is a crash please report also a gdb backtrace, for this do ---------------------------------------------- (in your shell) gdb mumudvb (in GDB) run [your usual command line options] (MuMuDVB Runs as usual an crash) (in GDB) bt ---------------------------------------------- MuMuDVB-2.1.0/doc/Makefile.am000066400000000000000000000007541305714132500155410ustar00rootroot00000000000000#We just have a doc target to compile the documentation, no installation is made ASCIIDOCFLAGS = -a toc -a numbered htmldocdir = html html_DOC = $(htmldocdir)/README.html $(htmldocdir)/README_CONF.html $(htmldocdir)/QUICKSTART.html $(htmldocdir)/WEBSERVICES.html $(htmldocdir)/TRANSCODE_EXTERNAL.html $(htmldocdir)/FAQ.html $(htmldocdir)/index.html #DISTCLEANFILES = $(html_DOC) doc: $(html_DOC) $(htmldocdir)/%.html: %.txt install -d $(htmldocdir) -asciidoc $(ASCIIDOCFLAGS) -o $@ $^ MuMuDVB-2.1.0/doc/QUICKSTART.txt000066400000000000000000000061741305714132500157420ustar00rootroot00000000000000Quickstart guide for MuMuDVB ============================ Brice Dubost What is this quickstart guide ? ------------------------------- In this guide I'll explain how to stream a full transponder (all the channels multiplexed on the same carrier frequency) over a network, by assigning each channel to a different multicast IP. The SAP announces will automatically be generated. For HTTP unicast or more advanced features, please refer to the full documentation. I'll take an example for DVB-S (satellite) and DVB-T (terrestrial). DVB-C and ATSC are similar. I suppose you have one DVB card which is already working, if you have more than one card refer to the full documentation. If you don't know your transponder frequencies, have a look to the README_CONF DVB-S ----- - First install mumudvb * Use the debian package, or * type `./configure` then `make` in the mumudvb directory and, as root, `make install` - You have to find which transponder you want to stream. * For European users you can use http://www.kingofsat.net/[King Of Sat] * You need: the frequency, the polarisation and the symbol rate (srate) - Now create a config file, which contains : ------------------------------------ autoconfiguration=full freq=__tranponder frequency in MHz__ pol=__polarisation H, V, L or R__ srate=__symbol rate__ ------------------------------------ .Example : ------------------------------------ autoconfiguration=full freq=11785 pol=h srate=27500 ------------------------------------ - Now launch MuMuDVB with : ------------------------------------ mumudvb -d -c __path to config file__ ------------------------------------ - That's all, you should get a list of the streamed channels with their IP addresses [NOTE] The SAP (session announcement protocol) announces will be sent automatically. [NOTE] If you want to stream a subset of the transponder you can use autoconf_sid_list DVB-T ----- - It's the same way as DVB-S except that you need other information on tuning your card. You can find these informations in : `/usr/share/doc/dvb-utils/examples/scan/dvb-t/` if you installed the dvb-utils package Your config file will be : ------------------------------------- autoconfiguration=full freq=__frequency in kHz__ ------------------------------------- [NOTE] If your bandwith is different from 8Mhz or if you experience tuning issues, look for the following parameters in README_CONF : bandwidth, qam, trans_mode, guardinterval, coderate [NOTE] The SAP (session announcement protocol) announces will be sent automatically. Troubleshooting --------------- - Try adding one ore several `-v` to the mumudvb command line to have more detailed messages - If you experience tuning issues, try with other dvb software like scan or szap and check your parameters - If it still don't work, look at common issues in the README and you can contact (see the README for getting the e-mail addresses) [NOTE] When contacting about an issue, please join the config file used and the output of MuMuDVB in verbose mode ( -vvv on the command line) and any other information that could be useful. [NOTE] You can easily select a part of a transponder using autoconf_sid_list MuMuDVB-2.1.0/doc/README.txt000066400000000000000000001314161305714132500152030ustar00rootroot00000000000000MuMuDVB - README ================ Brice Dubost Version 2.0.0 [NOTE] An HTML version of this file is availaible on http://www.mumudvb.net[MuMuDVB's website]. image::http://www.mumudvb.net/sites/default/files/logo.png[caption="logo MuMuDVB"] Presentation ------------ Description ~~~~~~~~~~~ MuMuDVB (Multi Multicast DVB) is a program that redistributes streams from DVB or ATSC (Digital Television) on a network (also called IPTV) using multicasting or HTTP unicast.It supports satellite, terrestrial and cable TV, in clear or scrambled channels and run on PC as well as several embedded platforms. It is intended to multicast (the stream is sent once and the network equipments split the data for the different clients) a whole DVB transponder (set of channels sent on the same carrier frequency) by assigning each channel a different multicast group. It detects the different services present as well as their important parameters for streaming, rewrite the main DVB tables to show clients only the right stream in each group. History : MuMuDVB is originally a modification of dvbstream that http://www.crans.org[cr@ns] made to stream TV in a few hundred rooms. Website ~~~~~~~ http://mumudvb.braice.net[MuMuDVB main site] Authors and contacts -------------------- .Upstream author - mailto:mumudvb@braice.net[Brice Dubost] .Contributions - mailto:manu@REMOVEMEcrans.ens-cachan.fr[Manuel Sabban] (getopt) - mailto:glondu@REMOVEMEcrans.ens-cachan.fr[Stéphane Glondu] (man page, debian package) - Special thanks to Dave Chapman (dvbstream author and contributor) - Pierre Gronlier, Sébastien Raillard, Ludovic Boué, Romolo Manfredini, Matthias Šubik, Krzysztof Ostrowski - Others, please see git logs .Mailing list: - mailto:mumudvb-dev@REMOVEMElists.crans.org[MuMuDVB mailing list] - https://lists.crans.org/listinfo/mumudvb-dev[MuMuDVB mailing list information and subscription] [NOTE] When contacting about an issue, please join the output of MuMuDVB in verbose mode ("-vvv" on the command line) and any other information that could be useful. Contents and features --------------------- Features overview ~~~~~~~~~~~~~~~~~ - Stream channels from a transponder on different multicast IPs - Support for scrambled channels (if you don't have a CAM you can use sasc-ng, but check if it's allowed in you country/by your broadcaster) - Support for automatic configuration i.e channels discovery and follow changes, see <> section - Generation of SAP announces, see <> section - Support of DVB-S2, DVB-S, DVB-C, DVB-T and ATSC - Possibility to partially rewrite the stream for better compatibility with set-top boxes and some clients. See <>, <> and <> sections. - Support for HTTP unicast see <> section - Support for RTP headers (only for multicast) - CAM menu access while streaming (using a web/AJAX interface - see WEBSERVICES.txt and CAM_menu_interface.png for screenshot) - Software descrambling through oscam dvbapi and libdvbcsa - Flexible configuration mechanism using templates - Support for embedded platforms based on UCLIBC and ANDROID Installation ------------ From sources ~~~~~~~~~~~~ From a snapshot ^^^^^^^^^^^^^^^ If you downloaded a snapshot, you will have to generate the auto(conf make etc ...) files. In order to do this you will need the autotools, automake, gettext and libtool and, type in the folder of MuMuDVB ---------------- autoreconf -i -f ---------------- Then you have a source which can be installed as a release package. From a release package ^^^^^^^^^^^^^^^^^^^^^^ [NOTE] If you want to compile for OpenWRT, please follow http://ocsovszki-dorian.blogspot.co.uk/2014/01/tl-wdr4900-openwrt-dvb-t-with-ite9135.html[OpenWRT tutorial] In order to install MuMuDVB type: --------------------------------- $ ./configure [configure options] $ make # make install --------------------------------- The `[configure options]` specific to MuMuDVB are: --------------------------------------------------------------------- --enable-cam-support CAM support (default enabled) --enable-scam-support SCAM support (default enabled) (see note below) --enable-coverage build for test coverage (default disabled) --enable-duma Debbuging DUMA library (default disabled) --enable-android Support for Android (default disabled) --------------------------------------------------------------------- [NOTE] If you want to compile MuMuDVB with clang/llvm, you have to install llvm-gcc and add `CC=llvm-gcc LD=llvm-ld` or `CC=clang LD=llvm-ld` to your `[configure options]`. You can have a list of all the configure options by typing -------------------- $ ./configure --help -------------------- [NOTE] The CAM support depends on libdvben50221, libucsi (from linuxtv's dvb-apps). The configure script will detect automatically the presence of these libraries and deactivate the CAM support if one of them is not present. In the case of fedora, the dvb-apps package does not contains the headers, you have to install it manually following the instructions here : http://www.linuxtv.org/wiki/index.php/LinuxTV_dvb-apps[LinuxTv DVB-apps page] [NOTE] The SCAM support depends on libdvbcsa from videolan. The configure script will detect automatically the presence of these libraries and deactivate the SCAM support if one of them is not present. It needs also trunk version of oscam to get control words. Oscam configuration is described below in section concerning software descrambling v2 inside mumudvb. [NOTE] The decoding of long channel names for autoconfiguration in ATSC depends on libucsi (from linuxtv's dvb-apps). The configure script will detect automatically the presence of this library and deactivate the long channel name support if it is not present. The full autoconfiguration will still work with ATSC but the channel names will be the short channels names (7 characters maximum) [NOTE] If you want to compile the doc i.e. generate HTML files using asciidoc, type `make doc`. The rendering for the tables will work with asciidoc 8.4.4 (can work with lower version but not tested). In order to install starting scripts (debian flavor) type: ------------------------------------------------------------ # cp scripts/debian/etc/default/mumudvb /etc/default/mumudvb # cp scripts/debian/etc/init.d/mumudvb /etc/init.d/mumudvb ------------------------------------------------------------ [NOTE] It is advised to create a system user for MuMuDVB, e.g. : `_mumudvb`, you have to add this user to the video group and make the directory `/var/run/mumudvb` RW by this user. By doing this, you'll be able to get all the features of MuMuDVB. From Debian package ~~~~~~~~~~~~~~~~~~~ If you want to install a version which is not in your repositories, you can install it by hand by typing: ---------------------- # dpkg -i mumudvb*.deb ---------------------- Otherwise you can use aptitude/synaptic as usual Usage ----- The documentation for configuration file syntax is in `doc/README_CONF.txt` (link:README_CONF.html[HTML version]). Usage: -------------------------------------- mumudvb [options] -c config_file mumudvb [options] --config config_file -------------------------------------- Possible options are: ------------------------------------------------------------------ -d, --debug Don't deamonize and print messages on the standard output. -s, --signal Print signal strenght every 5 seconds -t, --traffic Print the traffic of the channels every 10 seconds -l, --list-cards List the DVB cards and exit --card The DVB card to use (overrided by the configuration file) --server_id The server id (for autoconfiguration, overrided by the configuration file) -h, --help Show help -v More verbose (add for more) -q More quiet (add for less) --dumpfile Debug option : Dump the stream into the specified file ------------------------------------------------------------------ Signal: (see kill(1)) ------------------------------------------------------------------ SIGUSR1: switch the signal strenght printing SIGUSR2: switch the traffic printing SIGHUP: flush the log files ------------------------------------------------------------------ [[autoconfiguration]] Autoconfiguration ----------------- MuMuDVB is able to find the channels in the transponder, their PIDs (Program IDentifiers), names, and Logical channel numbers. Without autoconfiguration, you have to set the transponder parameters, and for each channel, the multicast ip, the name and the PIDs (PMT, audio, video, teletext etc...) If the channel list or the PIDs are changed, MuMuDVB will automatically update the channels. In autoconfiguration MuMuDVB will try to detect everything and keep the user set parameters fixed. So you can tune manually only things which are relevant for your usage like the multicast IP. You can also use templates to generate multicast IP or other parameters. We will review autoconfiguration starting without personalization then the cases when you want to change specific parameters for a (several) channel(s). Pure autoconfiguration ~~~~~~~~~~~~~~~~~~~~~~ This is the easiest way to use MuMuDVB. Use this when you want to stream a full transponder or a subset of a transponder (using autoconf_sid_list). [NOTE] You don't have to specify any channel in autoconfiguration except if you need to specify special parameters. In this mode, MuMuDVB will find for you the different channels, their name and their PIDs (PMT, PCR, Audio, Video, Subtitle, Teletext and AC3). In order to use autoconfiguration you have to: - Set the tuning parameters to your config file - Add `autoconfiguration=full` to your config file - You don't have to set any channels - For a first use don't forget to put the `-d` parameter when you launch MuMuDVB: e.g. `mumudvb -d -c your_config_file` .Example config file for satellite at frequency 11.296GHz with horizontal polarization ---------------------- freq=11296 pol=h srate=27500 autoconfiguration=full ---------------------- The channels will be streamed over the multicasts ip addresses 239.100.c.n where c is the card number (0 by default) and n is the channel number. If you don't use the common_port directive, MuMuDVB will use the port 1234. [NOTE] By default, SAP announces are activated if you use autoconfiguration. To disable them put `sap=0` in your config file. By default, SDT rewriting is activated if you use autoconfiguration. To disable it put `rewrite_sdt=0` in your config file. By default, PAT rewriting is activated if you use autoconfiguration. To disable it put `rewrite_pat=0` in your config file. [NOTE] If you want to select the services to stream, you can use the `autoconf_sid_list` option which allows to specify the service identifier of the channels you want to be configured. [NOTE] A detailled, documented example configuration file can be found in `doc/configuration_examples/autoconf_full.conf` Templates and autoconfiguration ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Name ++++ By default the name of the channel will be the name of the service defined by the provider. If you want more flexibility you can use a template. For example, if you use `autoconf_name_template=%number-%name` The channels name will be in the form : - `1-CNN` - `2-Euronews` There is different keywords available: [width="80%",cols="2,8",options="header"] |================================================================================================================== |Keyword |Description |%name | The name given by the provider |%number | The MuMuDVB channel number |%lang | The channel primary language |%card | The DVB card number |%tuner | The tuner number |%server| The server number specified by server_id or the command line |%lcn | The logical channel number (channel number given by the provider). Your provider have to stream the LCN. The LCN will be displayed with three digits including 0. Ex "002". If the LCN is not detected, %lcn will be replaced by an empty string. |%2lcn | Same as above but with a two digits format |%sid| The channel service id (decimal for the port, hexadecimal for ipv6) |%sid_hi| The channel service id. The two higher bits (between 0 and 255) |%sid_lo| The channel service id. The two lower bits (between 0 and 255) |================================================================================================================== Other options: Ip, port +++++++++++++++++++++++ You can also use templates for specifying the ip addresses or the port, for example if you want to use the service identifier (unique channel number in the transponder) in your ip address, you can use `autoconf_ip4=239.42.%sid_hi.%sid_lo`. Maybe you will notice different transponders having different channels with the same service identifier, you can then use other template to make your IP unique `autoconf_ip4=239.10*%server+%card.%sid_hi.%sid_lo`. Please refer to `doc/README_CONF.txt` (link:README_CONF.html[HTML version]) in the section "Autoconfiguration parameters" to see which options accept which templates Other keywords can be easily added if necessary, please contact if you have particular needs. Advanced autoconfiguration ~~~~~~~~~~~~~~~~~~~~~~~~~~ If the autodection mechanisms of Autoconfiguration are not suiting your needs, for example you need special IP for your channels or special names, you can force manually all channel parameters. The channel parameters specified by the user will not be overriden by autoconfiguration. The channels are identified in DVB by their service identifier (SID), so you will need to specify this number to allow MuMuDVB know which channel you are refering too. Some examples to show you the possibilities: Specific IP ^^^^^^^^^^^ For example you need to specify a particular IP address for the channel with the service identifier 517, you can use the following configuration file ------------------------------------- freq=506000 autoconfiguration=full new_channel service_id=517 ip=239.42.42.42 ------------------------------------- The IP address of all the other channels will be attributed using the default scheme, or the template you can define using autoconf_ip4,autoconf_ip6 Extra channels ^^^^^^^^^^^^^^ You can also use this personalization to add specific channels, with the following example you will obtain all detected channels plus one extra which is the one you specified. ------------------------------------- freq=506000 autoconfiguration=full new_channel name=my dump channel ip=239.42.42.42 pids=8192 ------------------------------------- Specific channels with specific IP ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This mode can be combined with autoconf_sid_list if you want to restrict the channels autodetected, in the following example we want to stream two channels and specify their IPs ------------------------------------- freq=506000 autoconfiguration=full autoconf_sid_list=516 517 new_channel service_id=516 ip=239.42.42.1 new_channel service_id=517 ip=239.42.42.2 ------------------------------------- [[sap]] SAP announces ------------- SAP (Session Announcement Protocol) announces are made for the client to know which channels are streamed and what is their name and address. It avoids to give to the client the list of the multicast ip addresses. VLC and most of set-top boxes are known to support them. MuMuDVB will automatically generate and send SAP announces if asked to in the config file or if you are in full autoconfiguration mode. The SAP announces will be only sent for alive channels. When a channel goes down, MuMuDVB will stop sending announces for this channel, until it goes back. Asking MuMuDVB to generate SAP announces ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ For sending SAP announces you have to add `sap=1` to your config file. The other parameters concerning the sap announces are documented in the `doc/README_CONF.txt` file (link:README_CONF.html[HTML version]). SAP announces and full autoconfiguration ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If you use full autoconfiguration, you can use the keyword '%type' in the sap_default_group option. This keyword will be replaced by the type of the channel: Television or Radio. .Example If you put `sap_default_group=%type`, you will get two sap groups: Television and Radio, each containing the corresponding services. Configuring the client to get the SAP announces ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VLC > 2.0.0 ^^^^^^^^^^^ SAP announces are enabled by default, you will find them in the local network left submenu of the playlist VLC < 2.0.0 ^^^^^^^^^^^ Click on the "Settings" menu, then on "add interface" and choose SAP playlist. Then open you playlist, the SAP announces should appear automatically. VLC > 0.8.2 && VLC < 2.0.0 ^^^^^^^^^^^^^^^^^^^^^^^^^^ You have to enter the settings, choose advanced settings. The SAP announces are in playlist->service discovery. Don't forget to save the settings. You should have now a SAP section in your playlist. [[unicast]] HTTP Unicast ------------ In addition to multicast, MuMuDVB also supports HTTP unicast. This make you able to use MuMuDVB on networks wich doesn't support multicast. There is one listening connection, the channel is selected via the HTTP path, see further. And you can have listening sockets per channel, in this case the client will always get the same channel independantly of the path. [NOTE] Be careful with unicast, it can eat a lot of bandwith. Think about limitting the number of clients. [NOTE] If you don't want the (always here) multicast traffic to go on your network set `multicast=0` Activate HTTP unicast ~~~~~~~~~~~~~~~~~~~~~ To enable HTTP unicast you have to set the option `unicast`. By default MuMuDVB will listen on all your interfaces for incoming connections. You can also define the listening port using `port_http`. If the port is not defined, the default port will be 4242. Activate "per channel" listening socket ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ You can create listening connections only for a channel. In this case, when a client connect to this socket he will alway get the same channel independantly of the HTTP path. If you use full autoconfiguration ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ You need to set the option `autoconf_unicast_start_port` which define what is the output port for the first discovered channel (for the following channels the port will be incremented). If you don't use full autoconfiguration ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ For the channels for which you want to have a listening unicast socket you have to set the option `unicast_port` which define the listening port of the socket Client side, the different methods to get channels ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [[playlist]] Using a playlist ^^^^^^^^^^^^^^^^ MuMuDVB generates m3u playlists. If you server is listening on the ip 10.0.0.1 and the port 4242, ------------------------------------- vlc http://10.0.0.1:4242/playlist.m3u ------------------------------------- [NOTE] In this playlist the channels will be announced with URLs type `/bysid/` (see below), if you want a playlist for single channel sockets, use the URL `/playlist_port.m3u`. [NOTE] Playlists for multicast are also generated, they are accessible using the following names: "playlist_multicast.m3u" and "playlist_multicast_vlc.m3u" Single channel socket ^^^^^^^^^^^^^^^^^^^^^ If the client connect to a single client socket he will get the associated channel independantly of the path. If you server is listening on the ip 10.0.0.1 and the port for the channel is 5000, ------------------------- vlc http://10.0.0.1:5000/ ------------------------- Get the channel by number ^^^^^^^^^^^^^^^^^^^^^^^^^ You can ask the channel by the channel number (starting at 1). If you server is listening on the ip 10.0.0.1 and the port 4242, ------------------------------------ vlc http://10.0.0.1:4242/bynumber/3 ------------------------------------ will give you the channel number 3. This works also with xine and mplayer. Get the channel by service id ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ You can ask the channel by the service id. If you server is listening on the ip 10.0.0.1 and the port 4242, ---------------------------------- vlc http://10.0.0.1:4242/bysid/100 ---------------------------------- will give you the channel with the service id 100, or a 404 error if there is no channel with this service id. This works also with xine and mplayer. Get the channel by name ^^^^^^^^^^^^^^^^^^^^^^^ You can ask the channel by the channel name. The search is case insensitive. If your channel name contains spaces, replace them by '-' character. If you server is listening on the ip 10.0.0.1 and the port 4242, ---------------------------------------------------- vlc http://10.0.0.1:4242/byname/your-tv-station-name ---------------------------------------------------- will give you the channel with name "Your TV station name". This works also with xine and mplayer. Get the channels list ^^^^^^^^^^^^^^^^^^^^^ If you server is listening on the ip 10.0.1 and the port 4242, To get the channel list (in basic html) just enter the address `http://10.0.0.1:4242/channels_list.html` in your web browser. To get the channel list (in JSON) just enter the address `http://10.0.0.1:4242/channels_list.json` in your web browser. HTTP unicast and monitoring ~~~~~~~~~~~~~~~~~~~~~~~~~~~ This HTTP connection can be used to monitor MuMuDVB. Monitoring information is avalaible in JSON format (http://en.wikipedia.org/wiki/JSON) vis the following urls `/monitor/signal_power.json` and `/monitor/channels_traffic.json` It's quite easy to add new informations to these files if needed. Monitoring ---------- You can use http://mmonit.com/monit/[Monit] to monitor MuMuDVB an restart it when it experiences problems (MuMuDVB kill himself when big issues appear). You have to install the init scripts (automatic if you used the Debian package) and add the following lines to your `/etc/monit/services` file: ---------------------------------------------------------------------- check process mumudvb with pidfile /var/run/mumudvb/mumudvb_adapter0_tuner0.pid start program = "/etc/init.d/mumudvb start" stop program = "/etc/init.d/mumudvb stop" ---------------------------------------------------------------------- [NOTE] The 0 have to be replaced by the DVB card number if you have multiples cards. For more detailled information, refer to the http://mmonit.com/monit/[Monit Website]. MuMuDVB usually run for many days without problems, but with monit you are safe. Monit is also able to send e-mails in case of problems. Scrambled channels support -------------------------- Important note : check the contract with your broadcaster to see if you are allowed to stream the scrambled channels you're subscribed to. Hardware descrambling ~~~~~~~~~~~~~~~~~~~~~ MuMuDVB supports scrambled channels via hardware descrambling i.e. a CAM (Conditionnal Access Module). It can ask the CAM to descramble multiple channels if the CAM supports it (Aston Pro, or PowerCam Pro are known to work with multiple channels). If you are limited by the number of PIDs the can can decrypt simultaneously, it is possible to ask the CAM to decrypt only the audio and video. This feature is not implemented, please ask if you need it. [NOTE] The hardware descramblig uses almost no CPU, all the descrambling is made by the CAM. [NOTE] MuMuDVB doesn't query the CAM before asking for descrambling. The query is not reliable. Most of CAMs answer a menu when the descrambling is not possible and MuMuDVB will display it on the standard error. The information concerning the CAM is stored in '''/var/run/mumudvb/caminfo_adapter%d_tuner%d''' where %d is the DVB card number. .Example contents of '''/var/run/mumudvb/caminfo_carte%d''' ---------------------------------------------------- CAM_Application_Type=01 CAM_Application_Manufacturer=02ca CAM_Manufacturer_Code=3000 CAM_Menu_String=PowerCam_HD V2.0 ID_CA_Supported=0100 ID_CA_Supported=0500 ---------------------------------------------------- [NOTE] In case of issues with some king of CAMs the libdvben50221 could have to be patched: http://article.gmane.org/gmane.linux.drivers.video-input-infrastructure/29866[Link to the patch] How to ask MuMuDVB for descrambling? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .You are using autoconfiguration : Just add `cam_support=1` to your config file .You are not using autoconfiguration * Add `cam_support=1` to your config file (before the channels) * For each scrambled channel add the `pmt_pid` option. This option is made for MuMuDVB to know wich PID is the PMT PID wich will be used to ask for descrambling Hardware CAM issues ~~~~~~~~~~~~~~~~~~~ Some hardware CAM are not directly connected to the tuner, one can choose the stream sent to the CAM. This can make the work slightly more complicated to run the CAM since you have to ensure the right stream is sent to the CAM. Digital Devices Cine CT V6 ^^^^^^^^^^^^^^^^^^^^^^^^^^ We always use cards and hardware from Digital Devices(http://www.digitaldevices.de/). - Octopus CI - Cine S2 V6.5 After a lot of problem with MuMuDVB and the CI card we found out, that the hardware wasn't detected by MuMuDVB. The folder /dev/dvb looked like : ---------------------------------------- - Adapter0 - Adapter1 - Adapter2 - Adapter3 ---------------------------------------- `/dev/dvb/Adapter0` and Adapter1 had the following content: ---------------------------------------- demux0 dvr0 frontend0 net0 ---------------------------------------- `/dev/dvb/Adapter2` and Adapter3 had the following content: ---------------------------------------- sec0 ca0 ---------------------------------------- So there was no connection between the tuner and the CI. So we tried to load the driver of the card with a different parameter to get everything into one single folder. ----------------------------------------- sudo modprobe ddbridge adapter_alloc = 3 ----------------------------------------- Result: /dev/dvb/ includes only adapter0 Content of adapter0: ----------------------------------------- ca0 demux0 dvr0 frontend0 net0 sec0 ca1 demux1 dvr1 frontend1 net1 sec1 ----------------------------------------- After that we had to pipe the stream from the frontend truth the CI modul. This part is still very buggy and we don't know exactly how that works. ------------------------------------------------------------ sudo echo "02 02" > /sys/class/ddbridge/ddbridge0/redirect sudo echo "03 03" > /sys/class/ddbridge/ddbridge0/redirect ------------------------------------------------------------ At the moment we have the problem that we can use only one tuner. :( Here you can see some more information about this problem http://www.spinics.net/lists/linux-media/msg39494.html Software descrambling v1 ~~~~~~~~~~~~~~~~~~~~~~~~ Important note : this solution is not allowed by some provider contracts. MuMuDVB has been reported to work with software descrambling solutions like sascng + newcs + dvbloopback. In this case you don't need to set the `cam_support` option. Just ajust the `card` option to fit with your virtual dvbloopback card. If you use these solutions, see <> section. Some information on how to configure SASC-NG ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The following informations have been given by MuMuDVB users on the MuMuDVB-dev mailing list When the channels are not sucessfully descrambled (channel down in MuMuDVB) the following options are reported to improve the situation -------------------------------------------------- --sid-nocache --buffer 8M --sid-filt=200 -D -------------------------------------------------- You can try also the option --sid-allpid It seems to happend with transponders with a lot of channels (TV or RADIO channels). Scrambling status ~~~~~~~~~~~~~~~~~ The scrambling status is stored together with the streamed channel list. .Example ---------------------------------------------- 239.100.0.7:1234:ESCALES:PartiallyUnscrambled 239.100.0.8:1234:Fit/Toute l'Histoire:PartiallyUnscrambled 239.100.0.9:1234:NT1:PartiallyUnscrambled 239.100.0.10:1234:ACTION:PartiallyUnscrambled 239.100.0.11:1234:MANGAS:PartiallyUnscrambled 239.100.0.12:1234:ENCYCLOPEDIA:PartiallyUnscrambled 239.100.0.13:1234:XXL PL:PartiallyUnscrambled 239.100.0.14:1234:France 5:HighlyScrambled 239.100.0.16:1234:LCP:FullyUnscrambled 239.100.0.17:1234:VIDEOCLICK:FullyUnscrambled ---------------------------------------------- * FullyUnscrambled : less than 5% of scrambled packets * PartiallyUnscrambled : between 5% and 95% of scrambled packets * HighlyScrambled : more than 95% of scrambled packets Software descrambling v2 ~~~~~~~~~~~~~~~~~~~~~~~~ Important note : this solution is not allowed by some provider contracts. MuMuDVB now has support for software descrambling on its own, to do that you'll need to have trunk version of oscam and libdvbcsa installed. To enable you have to add to global options scam_support=1 on program options add oscam=1 Other setting are documented at `doc/README_CONF.txt` (link:README_CONF.html[HTML version]), there is also a configuration example available at `configuration_examples/oscam.conf` If channel has a lot of bandwidth it may be needed to extend ring buffer size. If cw's don't get in time defined as decsa delay(default 500000us=0.5s), you may try to extend it (decsa_delay max is 10000000, and send_delay should be lower than decsa_delay, because we can't send descrambled packets befor they're being descrambled) for example: ------------------------------ decsa_delay=3500000 send_delay=4500000 ------------------------------ note that bigger delays in ring buffer may need also extending ring buffer size In debug mode number of packets in the buffer is reported and buffer overflow is detected, you should use that to tweak your delays and ring buffer size. In http state.xml number of packets in the buffer is also reported. [NOTE] Use the latest version of oscam from trunk, older versions did not have support for pc dvbapi. Instructions how to compile are on http://streamboard.de.vu:8001/wiki/crosscompiling [NOTE] When using oscam with more than 16 channels adjust macro definition `MAX_DEMUX` (line below) on oscam header `module-dvbapi.h` to number of your channels ------------------------------ #define MAX_DEMUX 16 ------------------------------ [NOTE] When using multiple channels per card (more than (ecm_change_time)/(2*card_response_time)), you may get timeouts on oscam on mumudvb startup, it's because on startup oscam asks card for two cw's at the same time. It should get right after a while. Currently there is no solution for that bug. Some information on how to configure oscam ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In the `oscam.conf` file add the following options ------------------------------ [dvbapi] enabled = 1 au = 1 boxtype = pc user = mumudvb pmt_mode = 4 request_mode = 1 ------------------------------ [[pat_rewrite]] PAT (Program Allocation Table) Rewriting ----------------------------------------- This feature is mainly intended for set-top boxes. This option will announce only the streamed channel in the Program Allocation Table instead of all transponder channels. Computer clients parse this table and decode the first working program. Set-top boxes usually try only the first one which give usually a blank screen in most of the channels. To enable PAT rewriting, add `rewrite_pat=1` to your config file. This feature consumes few CPU, since the rewritten PAT is stored in memory and computed only once per channel. [NOTE] PAT rewrite can fail (i.e. doesn't solve the previous symptoms) for some channels if their PMT pid is shared. In this case you have to add the `service_id` option to the channel to specify the service id. [[sdt_rewrite]] SDT (Service Description Table) Rewriting ----------------------------------------- This option will announce only the streamed channel in the Service Description Table instead of all transponder channels. Some clients parse this table and can show/select ghost programs if it is not rewritten (even if the PAT is). This can rise to a random black screen. To enable SDT rewriting, add `rewrite_sdt=1` to your config file. This feature consumes few CPU, since the rewritten SDT is stored in memory and computed only once per channel. [NOTE] If you don't use full autoconfiguration, SDT rewrite needs the `service_id` option for each channel to specify the service id. [[pmt_rewrite]] PMT (Program Map Table) Rewriting ----------------------------------------- This option must be used if you don't stream all PIDs for a channel. It's useful for separating one channel with multiple audio streams (multiple languages) into separate channels. Without PMT rewrite, players can get confused due to missing streams, especially if the first PID in the table is not streamed, and the playback may fail. However, teletext PID can usually be dropped safely without rewriting PMT, as it's the last PID in the table. To enable PMT rewriting, add `rewrite_pmt=1` to your config file. [NOTE] PMT rewrite will work only if PIDs are set manually. If they are autodetected, everything will be streamed so there's no need to rewrite the PMT. EIT PID (Event Information Table) Sorting ----------------------------------------- This option will make MuMuDVB stream only the EIT packets corresponding to the streamed channel instead of all transponder channels. Some clients parse this table and can show/select ghost programs (even if the PAT and the SDT are rewritten). The EIT PID contains the description of the current program and the future programs. It is used to build the Electronic Program Guide. To enable EIT sorting, add `sort_eit=1` to your config file. [NOTE] If you don't use full autoconfiguration, EIT sorting needs the `service_id` option for each channel to specify the service id. [[reduce_cpu]] Reduce MuMuDVB CPU usage ------------------------ Normally MuMuDVB reads the packets from the card one by one and ask the card if there is data avalaible between each packets (poll). But often the cards have an internal buffer. Because of this buffer, some pollings are useless. These pollings eat some CPU time. To reduce CPU usage, one solution is to try to read several packets at the same time. To do this use the option `dvr_buffer_size`. .Example ------------------ dvr_buffer_size=40 ------------------ To see if the value you put is too big or to low, run MuMuDVB in verbose mode, the average number of packets received at the same time will be shown every 2 minutes. If this number if below your buffer size, it is useless to increase it. The CPU usage reduction can be between 20% and 50%. [[threaded_read]] Data reading using a thread --------------------------- In order to make MuMuDVB more robust (at the cost of a slight CPU consumption increase), MuMuDVB can read the data from the card using a thread. This make the data reading "independant" of the rest of the program. In order to enable this feature, use the option `dvr_thread`. This reading uses two buffers: one for the data just received from the card, one for the data treated by the main program. You can adjust the size of this buffers using the option `dvr_thread_buffer_size`. The default value (5000 packets of 188 bytes) should be sufficient for most of the cases. The message "Thread trowing dvb packets" informs you that the thread buffer is full and some packets are dropped. Increase the buffer size will probably solve the problem. [[ipv6]] IPv6 ---- MuMuDVB supports IPv6 multicasting. It is not enabled by default you have to activate it using the multicast_ipv6 option To "enjoy" multicasting you need a switch which supports the http://en.wikipedia.org/wiki/Multicast_Listener_Discovery[Multicast Listener Discovery] protocol. IPv6 use extensively the concept of http://en.wikipedia.org/wiki/Multicast_address[scoping]. By default MuMuDVB uses the scope "site-local" (ie multicast addresses starting with FF05) the SAP announcements are also sent with this scope. If you need to have more flexibility on this side, please contact. Here some documentation about IPv6 and multicasting http://www.cisco.com/en/US/technologies/tk648/tk872/technologies_white_paper0900aecd80260049.pdf[IPv6 Multicast at a Glance - Cisco] http://www.cisco.com/en/US/technologies/tk648/tk872/technologies_white_paper0900aecd8026003d.pdf[IPv6 Addressing at a Glance - Cisco] RFCs concerning IPv6 scopes and addressing http://tools.ietf.org/html/rfc4007[RFC4007] http://tools.ietf.org/html/rfc4291[RFC4291] What is MLD snooping (equivalent of IGMP in IPv6) and how to configure it on HP switches http://cdn.procurve.com/training/Manuals/2900-3500-5400-6200-8200-IPv6-Jan08-7-MLD.pdf[MLD snooping on Procurve] Support of IPv6 on Cisco switches http://www.cisco.com/en/US/technologies/collateral/tk648/tk872/tk373/technologies_white_paper_09186a00802219bc_ps6553_Products_White_Paper.html[IPV6 on cisco] Extract of the previous page ---------------------------------------------------------------------------------- Layer 2 Switches IPv6 traffic forwarding does not impact Layer 2 LAN switches, since these devices do not need to look at the Layer 3 header to forward an IPv6 frame; thus IPv6 hosts can be transparently attached to the following Cisco products. In addition, Layer 2 switches may integrate dedicated IPv6 features such as native IPv6 network management or MLD snooping (Cisco products marked with "*" in the list). • Cisco Catalyst Express 500 Series Switch • Cisco Catalyst 2900XL Series Switch • Cisco Catalyst 2960 Series (*) • Cisco Catalyst 3500XL Series Switch • Cisco Catalyst 3560, 3560-E, 3750 and 3750-E Series Switch (*) • Cisco Catalyst 4500 Series Switch • Cisco Catalyst 4500-E Series Switch (*) • Cisco Catalyst 5000 Series Switch • Cisco Catalyst 6500 Series Switch (*) ---------------------------------------------------------------------------------- Also Cisco introduced IPv6 Multicast in Cisco IOS Software Releases 12.0(26)S, 12 .2(18)S, and12.3(2)T. It has been deployed in numerous business-critical IPv6 Multicast networks. http://www.cisco.com/cisco/web/solutions/small_business/products/routers_switches/300_series_switches/index.html[IPV6 small business switch] Some useful commands for ipv6 multicast debugging under linux ------------------------------------------ Show the open sockets netstat -6tulp See the traffic (on iface eth0) tcpdump -ni eth0 ip6 See the traffic to a particular address (here the SAP IPv6 announces) tcpdump -ni eth0 ip6 host FF05::2:7FFE Read an IPv6 stream with VLC (under linux) vlc -vvv --ipv6 udp://@\[ff15::1\]:1234 ------------------------------------------ MuMuDVB Logs ------------ MuMuDVB can send it's logs to the console, to a file or via syslog. It can also be several of these channels. The formatting of the logs can also be adjusted. By default, the logs are sent to the console if not daemonized and via syslog otherwise. If the logs are sent to a file, you can ask MuMuDVB to flush the file using the SIGHUP signal. For more detail about these features see `doc/README_CONF.txt` (link:README_CONF.html[HTML version]). Using MuMuDVB with "particular" clients --------------------------------------- People were able to use MuMuDVB with various clients, I will report here the tutorials I received for some of them XBMC (for XBOX originally) ~~~~~~~~~~~~~~~~~~~~~~~~~~ *Description:* XBMC (XBMP really) started as a program for modified XBOX consoles. In the following years, XBMC has grown into a multi-platform, multi-architecture media center that runs on most standard hardware. The hardware and legal limitations of the XBOX were always a concern and the Team has instead focused on running on the hardware that most people already have. *Website:* http://xbmc.org/ *Tutorial:* Here`s what You have to do, open Your favorite text editor and write an ip address with the protocol You are using of the particular program and port save it as something.strm. You have to create .strm files for every program You are streaming. Once you have done that fire up WinSCP and connect to the ip address of Your XBMC box if You are using the live version username and password is xbmc xbmc if You have installed the live version then You have provided the username and password during install process. Now copy theoes .strm files to the XBMC box in lets say home folder. Now in XBMC go to the video menu then click add source then click browse and navigate to the home folder and click ok then u have to give the name of that source use what ever You like and click ok and thats it. Go to the video menu You will see that You have a folder named as You named the source open it and You will see all of Yours .strm files click on it and it will start to play the stream from mumudvb. Works weather You are using multicast or unicast. Thanks to Ivan Cabraja for the tutorial MythTV ~~~~~~ *Description:* MythTV is a Free Open Source software digital video recorder (DVR) project distributed under the terms of the GNU GPL. *Website:* http://www.mythtv.org/ *Tutorial:* Configuring Mythtv and mumudvb Mumudvb Configuration: ^^^^^^^^^^^^^^^^^^^^^^ You need to turn pat rewriting on (i.e. rewrite_pat=1). You can use either multicast or udp streaming to mythtv (udp streaming is achieved by using a non-multicast ip address in the configuration file i.e. ip=192.168.1.100). Http unicast streaming is not supported in mythtv, but RTSP should be when this is implemented in mumudvb. The channel name needs to be in the following format "channel number" - "channel name" (e.g. name=1 - TV One ) Mythtv configuration: ^^^^^^^^^^^^^^^^^^^^^ *Single-transponder* In mythtv-setup you need to add a new "network recorder" capture card. Enter the address of the playlist mumudvb provides in the "M3U URL" field. This will be something like http://192.168.2.2:4242/playlist_multicast.m3u You then create a video source as normal, and associate this with the "Network recorder" capture card via the "input connections" option. You then need to carry out a channel scan (while you are associating the video source or via the channel editor). The channel scan appears to hang on 0%, but just select finish after a couple of seconds. This should have loaded the channels defined in the M3U file into mythtv. Relying on the EIT information embedded in the stream does not appear to work, so you need to load this information from an external xmltv source. You do this by going into the channel editor and adding the correct xmltv ID for each channel. Once you have done this you exit out of mythtv-setup and run something like: mythfilldatabase --file 1 freeview.xml (where in this case the the xmltv file is called freeview.xml). To allow recording and viewing of multiple channels from the one transponder, you need to add additional (identically configured) "network recorder" capture cards. For example if you want to be able to record two channels and watch a third at the same time you need to have set up a total of three network recorder cards. *Multiple-Transponders* if you are streaming channels from several transponders (by using several instances of mumudvb) you have two options: 1) The obvious thing to do is to define a different network recorder for each transponder (with the appropriate playlist defined), each transponder has to be associated with a different video source (assuming each transponder contains different channels). However, this does not seem to work well, with regular crashes when changing channels, and it also requires that you first switch between video sources to be able to change between channels on different transponders [this may be due to my lack of skill at configuring mythtv] 2) An easier way is to generate a custom m3u file, that contains the channels of all the transponders. This also allows you to define the xmltvid of each channel as well - removing the need to do this manually in the channel editor. In this case when you set up the network recorders, you can enter a file path for the location of the m3u file, as opposed to accessing it via a web-server (e.g. file///home/nick/channels.m3u ). Once again you simply make multiple copies of the (identical) network recorder capture card if you want to record/watch multiple channels. An example of a m3u file is as follows (in this case the first four channels defined are from one mumudvb instance, and the last two from another - of course care has to be taken in configuring the various mumudvb instances to make sure none of the channels are assigned the same port etc): -------------------------------------------------- #EXTM3U #EXTINF:0,1 - TV1 #EXTMYTHTV:xmltvid=tv1.freeviewnz.tv udp://192.168.2.101:1233 #EXTINF:0,2 - TV2 #EXTMYTHTV:xmltvid=tv2.freeviewnz.tv udp://192.168.2.101:1235 #EXTINF:0,6 - TVNZ 6 #EXTMYTHTV:xmltvid=tvnz6.freeviewnz.tv udp://192.168.2.101:1236 #EXTINF:0,7 - TVNZ 7 #EXTMYTHTV:xmltvid=tvnz7.freeviewnz.tv udp://192.168.2.101:1237 #EXTINF:0,3 - TV3 #EXTMYTHTV:xmltvid=tv3.freeviewnz.tv udp://192.168.2.101:1238 #EXTINF:0,4 - c4 #EXTMYTHTV:xmltvid=c4.freeviewnz.tv udp://192.168.2.101:1239 -------------------------------------------------- Thanks to Nick Graham for the tutorial MuMuDVB-2.1.0/doc/README_CONF.txt000066400000000000000000000735621305714132500160170ustar00rootroot00000000000000MuMuDVB - README for the configuration file =========================================== Brice Dubost Version 2.0.0 General behavior ---------------- MuMuDVB needs a configuration file in order to run properly. The order of the parameters is most of the times not relevant. You can put comments everywhere in the configuration file: just start the line with `#`. In line comments are not allowed i.e. `port=1234 #The multicast port` is *not* a valid line. All parameters are in the form: `name=value` .Example -------------------------- #The tuning frequency freq=11987 -------------------------- The configuration file contains two parts Common part ~~~~~~~~~~~ This is the first part of the configuration file, it contains the parameters needed for tuning the DVB card and the global parameters. See the <> section for the list of parameters used to tune the card. and <> section for parameters like autoconfiguration, cam support etc ... Channels part ~~~~~~~~~~~~~ If you are not using autoconfiguration you need to set the list of the channels you want to stream. Each channel start with an `new_channel` line. .Example (unicast only) --------------------------- new_channel name=Barcelona TV unicast_port=8090 pids=272 --------------------------- .Example --------------------------- new_channel ip=239.100.0.0 port=1234 name=Barcelona TV pids=272 256 257 258 --------------------------- See <> section for a list of detailed parameters. Example configuration files --------------------------- You can find documented examples in the directory `doc/configuration_examples` [[tuning]] Parameters concerning the tuning of the card -------------------------------------------- [NOTE] You can use w_scan to see the channels you can receive see <>. Otherwise you can have a look at the initial tuning files given with linuxtv's dvb-apps. For european satellite users, you can have a look at http://www.kingofsat.net[King Of Sat] Parameters concerning all modes (terrestrial, satellite, cable, ATSC) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In the following list, only the parameter `freq` is mandatory [width="80%",cols="2,7,2,3",options="header"] |================================================================================================================== |Parameter name |Description | Default value | Comments |freq | transponder's frequency in MHz | | Mandatory |modulation | The kind of modulation used (can be : QPSK QAM16 QAM32 QAM64 QAM128 QAM256 QAMAUTO VSB8 VSB16 8PSK 16APSK 32APSK DQPSK) | ATSC: VSB_8, cable/terrestrial: QAM_AUTO, satellite: QPSK | Optional most of the times |delivery_system | the delivery system used (can be DVBT DVBT2 DVBS DVBS2 DVBC_ANNEX_AC DVBC_ANNEX_B ATSC) | Undefined | Set it if you want to use the new tuning API (DVB API 5/S2API). Mandatory for DVB-S2 and DVB-T2 |card | The DVB/ATSC card number | 0 | only limited by your OS |tuner | The tuner number | 0 | If you have a card with multiple tuners (ie there are several frontend* in /dev/dvb/adapter%card) |card_dev_path | The path of the DVB card devices. Use it if you have a personalised path like /dev/dvb/astra%card | /dev/dvb/adapter%card | The template %card can be used |tuning_timeout |tuning timeout in seconds. | 300 | 0 = no timeout |timeout_no_diff |If no channels are streamed, MuMuDVB will kill himself after this time (specified in seconds) | 600 | 0 = infinite timeout |check_status | Do we check the card status and display a message if lock is lost | 1 | 0 = no check. |================================================================================================================== Parameters specific to satellite ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [width="80%",cols="2,6,1,3,2",options="header"] |================================================================================================================== |Parameter name |Description | Default value | Possible values | Comments |pol |transponder's polarisation. One char. 'v' (vertical), 'h' (horizontal), 'l' (left circular), 'r' (right circular) | | h, H, v, V, l, L, r or R | Mandatory |srate |transponder's symbol rate | | | Mandatory |lnb_type |The LNB type | universal | universal, standard | Universal : two local oscilators. Standard : one local oscillator.Most of the LNBs are universal. |lnb_lof_standard |The frequency of the LNB's local oscillator when lnb_type=standard | 10750 | | In MHz, see below. |lnb_slof |The switching frequency frequency of the LNB (define the two bands). Valid when lnb_type=universal | 11700 | | In MHz, see below. |lnb_lof_low |The frequency of the LNB's local oscillator for the low band. Valid when lnb_type=universal | 9750 | | In MHz, see below. |lnb_lof_high |The frequency of the LNB's local oscillator for the high band. Valid when lnb_type=universal | 10600 | | In MHz, see below. |sat_number |The satellite number in case you have multiples lnb, no effect if 0 (only 22kHz tone and 13/18V), send a diseqc message if non 0 | 0 | 1 to 4 | If you have equipment which support more, please contact. For Unicable 0,1 : position A, 2 position B |switch_input |The switch input number in case you have multiples lnb, overrides sat_number, send a diseqc message if non 0, for unicable, this is the unicable ID | 0 | 0 to 15| If you have equipment which support more, please contact |switch_type | The DiSEqC switch type: Committed (C), Uncommitted (N) or uNicable (N) | C | C, c, U, u, N or n | |diseqc_repeat | Do we repeat the DiSEqC message (useful for some switches) | 0 | 0 or 1 | |uni_freq | For SCR/unicable: the translated frequency in MHz | | | Optional: needed if switch_type N |lnb_voltage_off |Force the LNB voltage to be 0V (instead of 13V or 18V). This is useful when your LNB have it's own power supply. | 0 | 0 or 1 | |coderate |coderate, also called FEC | auto | none, 1/2, 2/3, 3/4, 4/5, 5/6, 6/7, 7/8, 8/9, auto | |rolloff |rolloff important only for DVB-S2 | 35 | 35, 20, 25, auto | The default value should work most of the times |stream_id | the id of the substream for DVB-S2 | 0 | >0 | |pls_code | the PLS code for DVB-S2 (will modify the stream_id) | 0 | | |pls_type | the PLS type for DVB-S2 | root | root, gold, common | common not implemented please contact if needed |================================================================================================================== Local oscillator frequencies : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - S-Band 3650 MHz - C band (Hi) 5950 MHz - C band (Lo) 5150 MHz - Ku Band : this is the default band for MuMuDVB, you don't have to set the LO frequency. For information : Hi band : 10600, Low band : 9750, Single : 10750 Parameters specific to terrestrial (DVB-T) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [NOTE] `auto` usually works fine for all the parameters except `bandwidth` [width="80%",cols="2,8,1,4",options="header"] |================================================================================================================== |Parameter name |Description | Default value | Possible values |bandwidth |bandwidth | 8MHz | 8MHz, 7MHz, 6MHz, auto (DVB-T2: 5MHz, 10MHz, 1.712MHz) |trans_mode |transmission mode | auto | 2k, 8k, auto (DVB-T2: 4k, 16k, 32k) |guardinterval |guard interval | auto | 1/32, 1/16, 1/8, 1/4, auto (DVB-T2 : 1/128, 19/128, 19/256) |coderate |coderate, also called FEC | auto | none, 1/2, 2/3, 3/4, 4/5, 5/6, 6/7, 7/8, 8/9, auto |stream_id | the id of the substream for DVB-T2 | 0 | 0 to 255 | |================================================================================================================== Parameters specific to cable (DVB-C) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [width="80%",cols="2,6,1,3,2",options="header"] |================================================================================================================== |Parameter name |Description | Default value | Possible values | Comments |srate |transponder's symbol rate | | | Mandatory |coderate |coderate, also called FEC | auto | none, 1/2, 2/3, 3/4, 4/5, 5/6, 6/7, 7/8, 8/9, auto | |================================================================================================================== [NOTE] The http://www.rfcafe.com/references/electrical/spectral-inv.htm[spectral inversion] is fixed to OFF, it should work for most of the people, if you need to change this parameter, please contact. Parameters specific to ATSC (Cable or Terrestrial) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If needed, specify the modulation using the option `modulation`. [NOTE] VSB 8 is the default modulation for most of the terrestrial ATSC transmission [[other_global]] Other global parameters ----------------------- Various parameters ~~~~~~~~~~~~~~~~~~ [width="80%",cols="2,8,1,2,3",options="header"] |================================================================================================================== |Parameter name |Description | Default value | Possible values | Comments |show_traffic_interval | the interval in second between two displays of the traffic | 10 | | |compute_traffic_interval | the interval in second between two computations of the traffic | 10 | | |dvr_buffer_size | The size of the "DVR buffer" in packets | 20 | >=1 | see README |dvr_thread | Are the packets retrieved from the card in a thread | 0 | 0 or 1 | See README |dvr_thread_buffer_size | The size of the "DVR thread buffer" in packets | 5000 | >=1 | See README |server_id | The server number for the `%server` template | 0 | | Useful only if you use the %server template |filename_pid | Specify where MuMuDVB will write it's PID (Processus IDentifier) | /var/run/mumudvb/mumudvb_adapter%card_tuner%tuner.pid | | the templates %card %tuner and %server are allowed |check_cc | Do MuMuDVB check the discontibuities in the stream ? | 0 | | Displayed via the XML status pages or the signal display |store_eit | Do MuMuDVB store EIT (Electronic Program Guide) for the webservices ? | 0 | | beta, please report your results |debug_updown | Do MuMuDVB show debugging messages concerning up/down channel detection | 0 | | The threshold can be adjusted with up_threshold and down_threshold |================================================================================================================== Packets sending parameters ~~~~~~~~~~~~~~~~~~~~~~~~~~ [width="80%",cols="2,8,1,2,3",options="header"] |================================================================================================================== |Parameter name |Description | Default value | Possible values | Comments |dont_send_scrambled | If set to 1 don't send the packets detected as scrambled. This will also remove indirectly the sap announces for the scrambled channels |0 | | |filter_transport_error | If set to 1 don't send the packets tagged with errors by the demodulator. |0 | | |psi_tables_filtering | If set to 'pat', TS packets with PID from 0x01 to 0x1F are discarded. If set to 'pat_cat', TS packets with PID from 0x02 to 0x1F are discarded. | 'none' | Option to keep only mandatory PSI PID | |rewrite_pat | Do we rewrite the PAT PID | 0, 1 in autoconf | 0 or 1 | See README, important for some set top boxes |rewrite_sdt | Do we rewrite the SDT PID | 0, 1 in autoconf | 0 or 1 | See README |rewrite_pmt | Do we rewrite the PMT PID | 0 | 0 or 1 | See README, important if you don't stream all PIDs |rewrite_eit sort_eit | Do we rewrite/sort the EIT PID | 0 | 0 or 1 | See README |sdt_force_eit | Do we force the EIT_schedule_flag and EIT_present_following_flag in SDT | 0 | 0 or 1 | Set to 0 if you don't understand |rtp_header | Send the stream with the rtp headers (except for HTTP unicast) | 0 | 0 or 1 | |================================================================================================================== Logs parameters ~~~~~~~~~~~~~~~ [width="80%",cols="2,4,4,2,4",options="header"] |================================================================================================================== |Parameter name |Description | Default value | Possible values | Comments |log_header | specify the logging header | %priority: %module | | The implemented templates are %priority %module %timeepoch %date %pid |log_flush_interval | LogFile flushing interval (in seconds) | -1 : no periodic flushing | | |log_type | Where the log information will go | If neither this option and logfile are specified the log destination will be syslog if MuMuDVB run as a deamon, console otherwise | syslog, console | The first time you specify a logging way, it replaces the default one. Then, each time you sepcify a logging channel, it is added to the previous |log_file | The file in which the logs will be written to | no file log | | The following templates are allowed %card %tuner %server |================================================================================================================== Multicast parameters ~~~~~~~~~~~~~~~~~~~~ [width="80%",cols="2,8,1,2,3",options="header"] |================================================================================================================== |Parameter name |Description | Default value | Possible values | Comments |multicast_ipv4 |Do we activate IPv4 multicast | 1 | 0 or 1 | Put this option to 0 to disable multicast streaming |multicast_ipv6 |Do we activate IPv6 multicast | 0 | 0 or 1 | |multicast_iface4 |The network interface to send IPv4 multicast packets (eth1, eth2 etc...) | empty (let the system choose) | | |multicast_iface6 |The network interface to send IPv6 multicast packets (eth1, eth2 etc...) | empty (let the system choose) | | |common_port | Default port for the streaming | 1234 | | For autoconf, and avoiding typing port= for each channel. |multicast_ttl |The multicast Time To Live | 2 | | |multicast_auto_join | Set to 1 if you want MuMuDVB to join automatically the multicast groups | 0 | 0 or 1 | See known problems in the README |================================================================================================================== CAM support parameters ~~~~~~~~~~~~~~~~~~~~~~ [width="80%",cols="2,5,2,2,5",options="header"] |================================================================================================================== |Parameter name |Description | Default value | Possible values | Comments |cam_support |Specify if we wants the support for scrambled channels | 0 | 0 or 1 | |cam_number |the number of the CAM we want to use | 0 | | In case you have multiple CAMs on one DVB card |cam_reset_interval |The time (in seconds) we wait for the CAM to be initialized before resetting it. | 30 | | If the reset is not successful, MuMuDVB will reset the CAM again after this interval. The maximum number of resets before exiting is 5 |cam_delay_pmt_send |The time (in seconds) we wait between the initialization of the CAM and the sending of the first PMT This behavior is made for some "crazy" CAMs like powercam v4 which doesn't accept the PMT just after the ca_info\ _callback | 0 | | Normally this time doesn't have to be changed. |cam_interval_pmt_send |The time (in seconds) we wait between possible updates to the PMT sent to the CAM | 3 | | Normally this time doesn't have to be changed. |================================================================================================================== SCAM support parameters ~~~~~~~~~~~~~~~~~~~~~~ [width="80%",cols="2,5,2,2,5",options="header"] |================================================================================================================== |Parameter name |Description | Default value | Possible values | Comments |scam_support |Specify if we wants the support for software descrambling channels | 0 | 0 or 1 | |ring_buffer_default_size | default number of ts packets in ring buffer (when not specified by channel specific config) | 32768 |it gets rounded to the value that is power of 2 not lower than it| |decsa_default_delay | default delay time in us between getting packet and descrambling (when not specified by channel specific config) | 500000 | max is 10000000 | |send_default_delay | default delay time in us between getting packet and sending (when not specified by channel specific config) | 1500000 | mustn't be lower than decsa delay | |================================================================================================================== Autoconfiguration parameters ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [width="80%",cols="3,5,1,2,5",options="header"] |================================================================================================================== |Parameter name |Description | Default value | Possible values | Comments |autoconfiguration |autoconfiguration allows to detect channels and their parameters | none | none or full | see the README for more details |autoconf_ip4 |For autoconfiguration, the template for the ipv4 for streamed channel | 239.100.%card.%number | | You can use expressions with `+`, `*` , `%card`, `%tuner`, `%server`, `%sid_hi`, `%sid_lo` and `%number`. Ex: `239.100.150+%server*10+%card.%number` |autoconf_ip6 |For autoconfiguration, the template for the ipv6 for streamed channel | FF15:4242::%server:%card:%number | | You can use the keywords `%card`, `%tuner`, `%server`, `%sid` (the SID will be in hexadecimal) and `%number` |autoconf_radios |Do we consider radios as valid channels during autoconfiguration ? | 0 | 0 or 1 | |autoconf_scrambled |Do we consider scrambled channels valid channels during autoconfiguration ? | 0 | 0 or 1 | Automatic when cam_support=1 or scam_support=1. Sometimes a clear channel can be marked as scrambled. This option allows you to bypass the ckecking. |autoconf_unicast_start_port |The unicast port for the first discovered channel | | | `autoconf_unicast_start_port=value` is equivalent to `autoconf_unicast_port=value + %number` |autoconf_unicast_port |The unicast port for each discovered channel. Ex "2000+%number" | | | You can use expressions with `+` `*` `%card` `%tuner` `%server`, `%sid` and `%number`. Ex : `autoconf_unicast_port=2000+100*%card+%number` |autoconf_multicast_port |The multicast port for each discovered channel. Ex "2000+%number" | | | You can use expressions with `+` `*` `%card` `%tuner` `%server`, `%sid` and `%number`. Ex : `autoconf_multicast_port=2000+100*%card+%number` |autoconf_sid_list | If you don't want to configure all the channels of the transponder in autoconfiguration mode, specify with this option the list of the service ids of the channels you want to autoconfigure. | empty | | |autoconf_sid_list_ignore | If you don't want to configure all the channels of the transponder in autoconfiguration mode, specify with this option the list of the service ids of the channels you want to exclude from autoconfiguration. | empty | | |autoconf_name_template | The template for the channel name, ex `%number-%name` | empty | | See README for more details |================================================================================================================== SAP announces parameters ~~~~~~~~~~~~~~~~~~~~~~~~ [width="80%",cols="2,6,1,2,5",options="header"] |================================================================================================================== |Parameter name |Description | Default value | Possible values | Comments |sap | Generation of SAP announces | 0 (1 if autoconfiguration) | 0 or 1 | |sap_organisation |Organisation field sent in the SAP announces | MuMuDVB | | Optionnal |sap_uri |URI field sent in the SAP announces | | | Optionnal |sap_sending_ip4 |The SAP sender IPv4 address | 0.0.0.0 | | Optionnal, not autodetected, if set, enable RFC 4570 SDP Source Filters field |sap_sending_ip6 |The SAP sender IPv6 address | :: | | Optionnal, not autodetected, if set, enable RFC 4570 SDP Source Filters field |sap_interval |Interval in seconds between sap announces | 5 | positive integers | |sap_default_group | The default playlist group for sap announces | | string | Optional. You can use the keyword %type, see README |sap_ttl |The TTL for the multicast SAP packets | 255 | | The RFC 2974 says "SAP announcements ... SHOULD be sent with an IP time-to-live of 255 (the use of TTL scoping for multicast is discouraged [RFC 2365])." |================================================================================================================== HTTP unicast parameters ~~~~~~~~~~~~~~~~~~~~~~~ [width="80%",cols="2,8,1,5",options="header"] |================================================================================================================== |Parameter name |Description | Default value |Comments |unicast |Set this option to one to activate HTTP unicast | 0 | see the README for more details |ip_http |the listening ip for http unicast, if you want to listen to all interfaces put 0.0.0.0 | 0.0.0.0 | see the README for more details |port_http | The listening port for http unicast | 4242 | You can use mathematical expressions containing integers, * and +. You can use the `%card`, `%tuner` and %server template. Ex `port_http=2000+%card*100` |unicast_consecutive_errors_timeout | The timeout for disconnecting a client which is not responding | 5 | A client will be disconnected if no data have been sucessfully sent during this interval. A value of 0 deactivate the timeout (unadvised). |unicast_max_clients | The limit on the number of connected clients | 0 | 0 : no limit. |unicast_queue_size | The maximum size of the buffering when writting to a client fails | 512kBytes | in Bytes. |playlist_ignore_dead | Do we exclude dead channels (no traffic) from playlist? | 0 | 0 or 1 | Exclude dead and include alive channels on each playlist request. |================================================================================================================== [[channel_parameters]] Channel parameters ------------------ Each channel start with a `new_channel` line. All these options if they are used together with autoconfiguration will override the detected values. Eg. if the name is specified with name="my channel" this name will be kept even if autoconfiguration detectes that the service is called 'euronews'. [[NOTE]] The service id must be set with service_id to allow autoconfiguration to detect parameters which are not user specified. Concerning the PIDs see the <> section The column "Can be detected/autoset" specifies if this parameter can be ommitted while using autoconfiguration [width="80%",cols="2,6,1,2,1,4",options="header"] |================================================================================================================== |Parameter name |Description | Default value | Possible values | Can be detected/autoset | Comments |ip |multicast (can also be unicast, in raw UDP ) ipv4 where the channel will be streamed | | | Yes | |ip6 |multicast (can also be unicast, in raw UDP ) ipv6 where the channel will be streamed | | | Yes | |port | The port | 1234 or common_port | | Yes | Ports below 1024 needs root rights. |unicast_port | The HTTP unicast port for this channel | | | Yes |Ports below 1024 needs root rights. You need to activate HTTP unicast with `ip_http` |sap_group |The playlist group for SAP announces | | string | No |optionnal |pmt_pid |Only for scrambled channels without autoconf. The PMT PID for CAM support | | | Yes | This option needs to be specified for descrambling the channel. The pid will be added to the pid list if ommitted |service_id |The service id (program number), only for autoconfiguration, or rewrite (PAT or SDT) see README for more details | | | NO | Mandatory for autodetection of the other parameters |name | The name of the channel. Will be used for /var/run/mumudvb/channels_streamed_adapter%d_tuner%d, logging and SAP announces | | | Yes | templates %name %number %lcn %2lcn can be used, other may be added if necessary |pids | The PIDs list, separated by spaces | | | Yes | some pids are always sent (PAT CAT EIT SDT TDT NIT), see README for more details |oscam |Do we activate software descrambling for this channel| 0 | 0 or 1 |No | |ring_buffer_size | number of ts packets in ring buffer (for software CAM) | 131072 |it gets rounded to the value that is power of 2 not lower than it|No | |decsa_delay | delay time in us between getting packet and descrambling (for software CAM) | 4500000 | max is 10000000 |No | |send_delay | delay time in us between getting packet and sending (for software CAM) | 7000000 | mustn't be lower than decsa delay |No | | cam_ask | For CAM support, some providers announce scrambled channels as FTA, this parameter force asking the CAM to descramble | 0 | 0,1| No | |================================================================================================================== [[getpids]] Get the PID numbers ------------------- You use autoconfiguration ~~~~~~~~~~~~~~~~~~~~~~~~~ If you use autoconfiguration, you don't need to specify any channel and don't need any PID, this section does not concern you. You do not use autoconfiguration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ It is strongly advised to use autoconfiguration as the PIDs may change and manual PID setting need to maintain them. If you don't use autoconfiguration because of limitations of the autoconfiguration system pleas contact so we can see how to fix that. If you don't use autoconfiguration (see the README), you have to get the PIDs (Program Identifier) for each channel. For each channel it is advised to specify at least : - One video PID (except for radios) - One audio PID - The PMT PID - The PCR PID (if different from video/audio) If you don't have access to the PIDs via a website like http://www.kingofsat.net[King Of Sat], the easiest way is to use linuxtv's dvb-apps or w_scan. You don't know on which frequency to tune and the channels you can receive. In this case, you can use <> or using <> from dvb-apps if you have an initial tuning config file. [[w_scan]] Using w_scan to get an initial tuning file ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [NOTE] w_scan works for DVB-T, DVB-C, DVB-S/S2 and ATSC. You can find wscan in the http://wirbel.htpc-forum.de/w_scan/index2.html[w_scan website - German] or http://wirbel.htpc-forum.de/w_scan/index_en.html[w_scan website - English translation]. w_scan have one disavantage over dvb-apps scan: it takes (usually) more time. But it have several advantages: no need for initial tuning file, card autodection and deeper channel search. Once you compiled it (optional for x86), launch it with the options needed (country is mandatory for terrestrial and cable. for DVB-S/S2 you need to specify your satellite) [NOTE] Here's the main options for w_scan -------------------------------------------------------------- -f type frontend type What programs do you want to search for? a = atsc (vsb/qam) c = cable s = sat t = terrestrian [default] -c choose your country here: DE, GB, US, AU, .. ? for list -s choose your satellite here: S19E2, S13E0, S15W0, .. ? for list -------------------------------------------------------------- For more information, see w_scan's help Your will get lines channels with the file format described http://www.vdr-wiki.de/wiki/index.php/Vdr%285%29#CHANNELS[here] If you want to use autoconfiguration, this contains all the parameters you need. For example the second row is the frequency. [[scan_inital_tuning]] Using scan with an initial tuning file ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [NOTE] With satellite this allow you to find all the frequencies (if the broadcaster follow the norm). Because, every transponder announces the others. If you don't know where to find the inital tuning file, recent versions of scan give the default locations by calling scan without arguments. You need `scan` from linuxtv's dvb-apps Type -------------------------------------------------------- scan -o pids pathtoyourinitialtuningfile -------------------------------------------------------- You'll first get blocks like ---------------------------------------------------------------------------------------------------------------- >>> tune to: 514000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_2_3:FEC_2_3:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_4:HIERARCHY_NONE 0x0000 0x7850: pmt_pid 0x0110 Barcelona TV -- Barcelona TV (running) 0x0000 0x7851: pmt_pid 0x0710 COM Radio -- COM Radio (running) 0x0000 0x7855: pmt_pid 0x0210 TV L'Hospitalet -- TV L'Hospitalet (running) 0x0000 0x7856: pmt_pid 0x0510 Radio Hospitalet -- Radio Hospitalet (running) 0x0000 0x785a: pmt_pid 0x0310 Televisio Badalona -- Televisio Badalona (running) 0x0000 0x785b: pmt_pid 0x0610 Radio Ciutat Badalona -- Radio Ciutat Badal ---------------------------------------------------------------------------------------------------------------- You have now acces to the PMT PID (in hexadecimal) After this blocks, you'll get lines like ---------------------------------------------------------------------------------------------------------------- Sensacio FM (0x273f) 02: PCR == A A 0x0701 urBe TV (0x7864) 01: PCR == V V 0x0300 A 0x0301 (cat) Canal Catala Barcelona (0x7869) 01: PCR == V V 0x0200 A 0x0201 (cat) 25 TV (0x786e) 01: PCR == V V 0x0400 A 0x0401 (spa) TT 0x0402 ONDA RAMBLA PUNTO RADIO (0x786f) 02: PCR == A A 0x0601 (cat) Localia (0x7873) 01: PCR == V V 0x0100 A 0x0101 ONA FM (0x7874) 02: PCR == A A 0x0501 TV3 (0x0321) 01: PCR == V V 0x006f A 0x0070 (cat) 0x0072 (vo) 0x0074 (ad) TT 0x0071 AC3 0x0073 SUB 0x032b ---------------------------------------------------------------------------------------------------------------- You have now acces to the other PIDs MuMuDVB wants the PIDs in decimal, so you have to convert the pids from hexadecimal to decimal. Scan only one transponder ^^^^^^^^^^^^^^^^^^^^^^^^^ You first have to tune the card on the wanted frequency (with `tune`, `szap` or `tzap` for example). After you use the scan utility: ---------------------- scan -o pids -c -a 0 ---------------------- Where `0` is the card number And you'll get results like in the section <> MuMuDVB-2.1.0/doc/TODO000066400000000000000000000005231305714132500141670ustar00rootroot00000000000000 * HTTP unicast * Master connection not mandatory, option unicast=1 * Autoconfiguration * make the syntax autoconfiguration=1/2 obsolete and replace by full/partial * In partial autoconfiguration, add a step for channels with a service ID and no PMT (this step will be skipped in full autoconf since we get both automatically) MuMuDVB-2.1.0/doc/TRANSCODE_EXTERNAL.txt000066400000000000000000000174371305714132500171000ustar00rootroot00000000000000MuMuDVB - MuMuDVB and FFmpeg transcoding Tutorial ================================================= By Meftah Tayeb (Tayeb|DOT|Meftah:-)@G.M.A.I.L.C.O.M Reviewed by Brice Dubost (mumudvb@braice.net) Introduction ------------ In the context of TV over IP the necessary bandwidth of the IP network is an important issue. In particular with stream coming from terrestrial or satellite broadcasting which represent about 6MBit/s per service with standard definition. In this context it can be useful to transcode the stream to reduce itś bandwidth footprint. MuMuDVB is a « air to ip » streaming software. In the following, a method to set-up MuMuDVB and Ffmpeg to perform transcoding is described. Please note that this way can probably be improved, feel free to provide feedback. Step 1: Configure MumuDVB ------------------------- You need at least one service/channel up and running to perform transcoding. you have multiple choices to configure MuMuDVB, please refer to the main documentation for more details. An example configuration is provided here for "Almajd channels" on BadrSat (26.0E): ------------------------- unicast=1 port_http=8080 freq=12476 pol=v srate=27504 autoconf_radios=1 autoconfiguration=full multicast_ttl=16 dvr_buffer_size=40 ------------------------- Step 2: Start MuMuDVB --------------------- In order to start MuMuDVB with your configuration, use the following: -------------------------------------------------- mumudvb -c /path-to-config/mumudvb.conf -d -------------------------------------------------- The -d flag allow to obtain the message on the command line instead of the standard log. Once everything is working you can run without the -d flag alowing MuMuDVB to run as a deamon. With several cards you can use “--card=X” or add “card=X” to your configuration file where X is the card number. Step 3: FFserver configuration ------------------------------ With MuMuDVB up and running, we need to configure FFMpeg Server to perform the transcoding task. Before transcoding, please check that your stream is properly up and running in MPEG2TS over UDP Example FFserver configuration: ---------------------------------------------------------------------------------------------------- #specify the HTTP /RTSP Unicast port: Port 80 RTSPPort 554 #bind FFserver to a specific interface, better to be same as MuMu Interface BindAddress 192.168.100.100 #Max http connection limitation MaxHTTPConnections 1000 #how much IPTV client you want at the same time ? MaxClients 200 #max bandwith to process MaxBandwidth 1000000 CustomLog - #almajd01 channel feed configuration #specify the temporary file to use to dump the stream to FFserver File /tmp/almajd01.ffm FileMaxSize 1000K #all others feed's is similar; File /tmp/almajd02.ffm FileMaxSize 1000K File /tmp/almajd03.ffm FileMaxSize 1000K #Almajd01 Stream Definition #note the .asf reference, we're encapsulating our stream in ASF format. please check FFmpeg documentation for other formats. #referencing the previously defined feed, Almajd01 Feed almajd01.ffm #specify the streaming format Format asf #prevent looping on a live channel, this is a continuous stream and not a file. NoLoop #Video codec definition VideoCodec mpeg4 VideoFrameRate 25 VideoBufferSize 100000 videoBitRate 512k VideoQMin 1 VideoQMax 31 VideoSize 352x240 PreRoll 0 #Audio codec definition AudioCodec libmp3lame AudioBitRate 64 AudioChannels 2 AudioSampleRate 24000 #all others stream is similar. Feed almajd02.ffm Format asf NoLoop VideoCodec mpeg4 VideoFrameRate 25 VideoBufferSize 100000 videoBitRate 256k VideoQMin 1 VideoQMax 31 VideoSize 352x240 PreRoll 0 AudioCodec libmp3lame AudioBitRate 48 AudioChannels 2 AudioSampleRate 24000 Feed almajd03.ffm Format asf NoLoop VideoCodec mpeg4 VideoFrameRate 25 VideoBufferSize 100000 VideoBitRate 256k VideoQMin 1 VideoQMax 31 VideoSize 352x240 PreRoll 0 AudioCodec libmp3lame AudioBitRate 48 AudioChannels 2 AudioSampleRate 24000 #definition of the status stream to be able to see our FFserver status using a web browser Format status ---------------------------------------------------------------------------------------------------- For the moment we have defined the stream and the transcoding you need. From this configuration Ffserver will wait for clients on is socket to push the data on the ffm files. The transcoded channels will be availaible on the .asm files Step 4: start FFserver ---------------------- to start FFserver do: ------------------------------------------ ffserver -f Path-To-Config-File.cfg ------------------------------------------ Step 5: Push the streams to FFserver using FFmpeg ------------------------------------------------- For the moment, FFserver have no data to process, we need to push the data from MuMuDVB to FFserver, for this we can use ffmpeg. after starting the FFserver, run the following: ------------------------------------------------------------------------------------ ffmpeg -i udp://@239.100.0.0:1234 http://192.168.100.100/almajd01.ffm ------------------------------------------------------------------------------------ This line have to be changed according to your configuration where the first part is the access path to the UDP channel (the @ after udp:// specifies that the channel have to be accessed in multicast), the second part corresponds to the path defined in your ffserver configuration. You need multiple FFmpeg instances, one per channel. To start ffmpeg in background please use nohup ffmpeg -i ... Note that you can auto start FFMpeg per feed by adding the following inside your feed definition: launch `ffmpeg -i udp://@X.X.X.X:1234` where X.X.X.X is your Multicast group. Now the channels can be accessed in unicast on URLs like `http://192.168.100.100/almajd01.asf` Example AAC/H.264 transcoded stream inside a FLV container: ------------------------------------------------------------------------------------ Port 8888 BindAddress 0.0.0.0 MaxHTTPConnections 20000 MaxClients 10000 MaxBandwidth 1000000 CustomLog - File /tmp/al-quds.ffm FileMaxSize 100M ACL allow 127.0.0.1 launch ffmpeg -i udp://@239.100.1.13:1234 Feed al-quds.ffm Format flv AudioBitRate 64 AudioChannels 2 AudioSampleRate 44100 AVOptionAudio flags +global_header VideoBitRate 256 VideoBufferSize 400 VideoFrameRate 25 VideoBitRateTolerance 100 VideoSize 704x480 VideoGopSize 12 AudioCodec aac VideoCodec libx264 AVOptionVideo coder 0 AVOptionVideo bf 0 AVOptionVideo flags +loop AVOptionVideo partitions +parti8x8+parti4x4+partp8x8+partb8x8 AVOptionVideo me_method hex AVOptionVideo subq 7 AVOptionVideo me_range 16 AVOptionVideo g 250 AVOptionVideo keyint_min 10 AVOptionVideo sc_threshold 40 AVOptionVideo i_qfactor 0.71 AVOptionVideo b_strategy 1 AVOptionVideo qcomp 0.6 AVOptionVideo qmin 10 AVOptionVideo qmax 51 AVOptionVideo qdiff 4 AVOptionVideo refs 3 AVOptionVideo directpred 1 AVOptionVideo trellis 1 AVOptionVideo wpredp 0 AVOptionVideo flags +global_header Title 'Al-quds tv' comment 'Al-quds Islamic jihad tv channel' author 'Islamic Jihad' StartSendOnKey Format status ACL allow 192.168.0.0 192.168.255.255 ------------------------------------------------------------------------------------ Acknowledgements ---------------- thank you Brice and Matthias for helping me all the time it is very appreciated thank to everyone that helped me getting my home brew IPTV up and running, i can watch everywhere, anywhere. thank to Georgeus roger for helping me with Oscam setup so now i have my channels descrambled. if you need any help please don't hesitate to contact me on the mailing list! MuMuDVB-2.1.0/doc/WEBSERVICES.txt000066400000000000000000000324211305714132500160230ustar00rootroot00000000000000Webservices =========== Sebastien RAILLARD and Brice DUBOST To activate the webservices, just enable the unicast mode with something like that: ---------------- unicast=1 : Activate the internal webserver ip_http=127.0.0.1 : IP address for accepting the HTTP requests port_http=8005 : Listening port ---------------- [NOTE] When you use several card on one server you can use the template `%card` for the listening port. Ex: `port_http=4000+%card`. Ports higher than 1024 can be used by unprivileged users. The webservices responses are not SOAP compliant, but formatted in simple XML documents (UTF-8) or in JSON. The output can be easily parsed in PHP for example. Status monitoring : ------------------- There is no input parameters. URL : http://ip_http:port_http/monitor/state.xml Example of response with comments: ---------------- => adapter and frontend devices /dev/dvb/adapter5 => card device path => MuMuDVB version 19574 => process PID 45 => process uptime in seconds => frontend name 1 => 0 if adapter not tuned, 1 if adapter is tuned 11856000 => tuning frequency (always in kHz) => "-" if polarization isn't applicable, or "V" (Vertical), "H" (Horizontal", "L" (Left), "R" (Right) 27500000 => Satellite symbole rate in symbols per second (or 0 if not applicable) => System used : "DVB-C", "DVB-T", "DVB-S", "DVB-S2", "ATSC" => Tuner lock status: "S"/"-" (Signal), "C"/"-" (Carrier), "V"/"-" (Viterbi), "Y"/"-" (Synchro), "L"/"-" (Locked) 0 => RAW BER value from driver (unsigned 16-bits integer) 56955 => RAW Signal level value from driver (unsigned 16-bits integer) 54759 => RAW Signal to noise ratio from driver (unsigned 16-bits integer) 2 => Autoconfiguration status 0: none, 2: full => Part displayed only when autoconfiguration is enabled 2 => Transport stream id 8442 => network id (see ts_10261102v010201p.pdf p14 and ts_101162v010701p.pdf p18 p19) 8442 => original network id (see ts_10261102v010201p.pdf p14 and ts_101162v010701p.pdf p18 p19) 19 => Version of the PAT PID 2 => Version of the SDT PID 28 => Version of the NIT PID 0 => Version of the PSIP PID (ATSC only) => 1 => 0 if not autoconfiguration or autoconfiguration in progress, 1 if autoconfiguration is finished 1 => 0 if no CAM support asked, 1 if CAM support was asked 0 => CAM slot number => When CAM is initialized, CAM model 0 => 0 if CAM isn't initialized, 1 if CAM is initialized => Loop over channels, one node per channel, with MuMuDVB internal id (starting at 1) 0 => If present, Channel Logical Number (Channel number) => Channel name => See function "service_type_to_str" in "log.c" file for complete description => Multicast IP address (0.0.0.0 if multicast is disabled) 0 => Multicast UDP port (0 if multicast is disabled) 0 => 0 if channel is not streamed, 1 if channel is streamed 7 => Channel streamed IP bandwidth in kB (kilo-Bytes) per second 99 => Percentage of scrambled packets received 8201 => Service ID of channel 1280 => PMT PID of channel 1 => The version of the PMT PID in the TS stream 160 => PCR PID of channel 0 => Unicast port associated with the channle if unicast is setup by port => Loop over all the CA systems listed in the PMT for the channel => CA identifier and description if avaliable => End of CA systems loop => Loop over all PID related to the channel and declared in the PMT => PID number, Language associated (or "---" if no language associated), PID description if avaliable => End of PID loop => Loop over unicast clients => Client Information 80 => Local socket FD => Remote IP address of the client 438754 => Remote port 0 => Client Buffer 0 => Count of consecutive errors when writing to this client 1411392479 => 0 => => End of Client. => End of clients loop => End of channels loop => End of response ---------------- JSON files: ~~~~~~~~~~~ You can get similar information in the JSON files * `http://ip_http:port_http/channels_list.json` * `http://ip_http:port_http/monitor/signal_power.json` * `http://ip_http:port_http/channels_traffic.json` * `http://ip_http:port_http/monitor/state.json` Access to the CAM menu: ----------------------- These two webservices allow for accessing the CAM menu during streaming. This is usefull for checking rights or download status for example. The file `cam_menu.php` is a simple demonstration on how to use these webservices in order to make a web interface with AJAX compatible with the most important browsers (Firefox, Chrome, Internet Explorer). For using it, you just need a webserver (lighttpd, apache, etc.) with PHP activated. The web page accept one GET parameter: `port_server`. This is the unicast port setup for accessing MuMuDVB webservices. The CAM menu is refresded every 2 seconds and buttons can be used to navigate in the menus. MENU, LIST and ENQUIRY MMI objects are supported. * First webservice return the latest menu returned by the CAM. There is no input parameters. URL : http://ip_http:port_http/cam/menu.xml Below, some examples of response with comments. Case when the CAM isn't initialized: ---------------- => Last update time/date => No object to show <![CDATA[CAM not initialized!]]> => Message about CAM not initialized ---------------- Case when the CAM is initialized but there is no menu to display: ---------------- => Last update time/date => CAM model => No object to show <![CDATA[No menu to display]]> => Message about no menu to display ---------------- Case when a object is send by the CAM to be displayed: ---------------- => When the object was received => CAM model => Object: "MENU", "LIST" or "ENQUIRY" <![CDATA[Module Aston]]> => Object title => Object subtitle (when an "ENQUIRY" object is display, show the number of characters expected in the answer) => For "MENU" and "LIST" objects, contain the lines of information or the items to be choosen. The "num" attribute correspond to the key to press to choose the item. => Object bottom line ---------------- * Second webservice allows for sending response to the CAM. There is one integer GET paramter: `key`. Possible keys: `0` to `9` (numbers), `M` for asking the CAM menu, `C` for cancelling an `ENQUIRY` object. URL : http://ip_http:port_http/cam/action.xml?key=X There are 4 king of responses. OK: ---------------- ---------------- Unknown key: ---------------- ---------------- CAM not initialized: ---------------- ---------------- MuMuDVB compiled without CAM support: ---------------- ---------------- Electronic program guide ------------------------ The content of the EIT table (electronic programs guide) is now available via the Webservices. To enable it, put `store_eit=1` in your configuration file and get the file: * `http://ip_http:port_http/monitor/EIT.json` The structure follow the structure of the data descriptors of the DVB stream, so please consult the norm `EN 300 468` if you want to get more info see http://www.mumudvb.net/node/39[documentation]. An example result is available http://www.mumudvb.net/doc/EIT/EIT_TNT_PARIS_20141209.json[here]. MuMuDVB-2.1.0/doc/cam_menu.php000066400000000000000000000200231305714132500157710ustar00rootroot000000000000000 && ($query==1 || ($query==2 && $key!=""))) { // XML proxy reply header('Content-Type: application/xml; charset=UTF-8'); if ($query==1) $url="http://localhost:".strval($port_server)."/cam/menu.xml"; if ($query==2) $url="http://localhost:".strval($port_server)."/cam/action.xml?key=".$key; $cmdline="wget -T 1 -O - '".$url."'"; passthru ($cmdline,$error); if (intval($error)!=0) echo("wget error ".$error.""); die(); } else { // HTML page header('Content-type: text/html; charset="utf-8"'); // HTML en UTF-8 } ?> CAM Menu Management

CAM Management

0) echo('

Mumudvb HTTP port number : '.$port_server.'

'); else echo('

Mumudvb HTTP port number : (>0)

'); ?>

CAM Menu

Status: Not yet loaded

No menu to display

CAM actions

Status: No key sent

MuMuDVB-2.1.0/doc/configuration_examples/000077500000000000000000000000001305714132500202445ustar00rootroot00000000000000MuMuDVB-2.1.0/doc/configuration_examples/autoconf_full.conf000066400000000000000000000041121305714132500237510ustar00rootroot00000000000000#This is an example configuration file for mumudvb using full autoconfiguration #All the commented lines are optionnal (except for tuning you have to match your system) #If you want to set HTTP unicast, see the README and the README_CONF #------------ TUNING ------------- #The DVB/ATSC card we want to use #card=2 #The Transponder frequency freq=11137 # ---- SATELLITE (DVB-S) ----- #The polarisation (can be h, v, l, r) pol=h #The symbol rate srate=27500 # ----- CABLE (DVB-C) ---- #The symbol rate #srate=27500 # ---- TERRESTRIAL (DVB-T) ----- #For DVB-T if the bandwith is 8MHz you don't have to set other parameters # # ----- ATSC ---- #For ATSC you could have to set the modulation if it's different from VSB_8 # #---------- AUTOCONFIGURATION ----------- #We want the full autoconfiguration (ie we discover the channels and their pids) autoconfiguration=full #Do we want to add the radios to the list of channels (default 0) ? #autoconf_radios=1 #Do we want to configure channels marked as scrambled (automatically done if cam_support=1) #autoconf_scrambled=1 #Select here if you want to stream only some services #autoconf_sid_list= #--------- NETWORKING -------------- #What is the "ip template"? #Allow to select on which IP address each service will be sent #autoconf_ip4=239.%card.%sid_hi.%sid_lo # #Do we want to change the default port (optionnal) ? #common_port=4422 # #Do we need to change the default multicast TTL (if you have routers, default value : 2) ? #multicast_ttl=10 # #--------- SAP ANNOUNCES -------------- #The sap announces are sent automatically with full autoconfiguration #Do we want NOT to send the announces ? #sap=0 # #What is the default playlist group for the SAP announces (optionnal) ? sap_default_group=My channels #Who is the organisation wich send the stream (optionnal) ? #sap_organisation=my_organisation #The intervall between the SAP announces in second (default 5) #sap_interval=10 # ---------- SCRAMBLED CHANNELS ---------- #Do we want hadware descrambling ? #cam_support=1 # #If you have multiple CAMs you can specify the number of the one wich will be used #cam_number=2 MuMuDVB-2.1.0/doc/configuration_examples/autoconf_partial.conf000066400000000000000000000050001305714132500244400ustar00rootroot00000000000000#This is an example configuration file for mumudvb using partial autoconfiguration and sending sap announces #All the commented lines are optionnal (except for tuning you have to match your system) #To set unicast HTTP refer to README_CONF and README # #------------ TUNING ------------- #The DVB/ATSC card we want to use #card=2 #The Transponder frequency freq=12597 # ---- SATELLITE (DVB-S) ----- #The polarisation (can be h, v, l, r) pol=V #The symbol rate srate=27500 # ----- CABLE (DVB-C) ---- #The symbol rate #srate=27500 # ---- TERRESTRIAL (DVB-T) ----- #For DVB-T if the bandwith is 8MHz you don't have to set other parameters # # ----- ATSC ---- #For ATSC you could have to set the modulation if it's different from VSB_8 # #---------- AUTOCONFIGURATION ----------- #We want the partial autoconfiguration (ie we discover the pids of the defined channels) autoconfiguration=partial # #--------- NETWORKING -------------- #Do we want to have the same port for all the channels ? common_port=1234 # #Do we need to change the default multicast TTL (if you have routers, default value : 2) ? #multicast_ttl=10 # #--------- SAP ANNOUNCES -------------- #The sap announces are sent automatically with full autoconfiguration #Do we want to send the announces ? sap=1 # #What is the default playlist group for the SAP announces (optionnal) ? sap_default_group=My channels #Who is the organisation wich send the stream (optionnal) ? #sap_organisation=my_organisation #The intervall between the SAP announces in second (default 5) #sap_interval=10 # ---------- PAT REWRITING ---------- #If some of the clients are set top boxes we will probably need to rewrite the PAT pid #rewrite_pat=1 # # ---------- SCRAMBLED CHANNELS ---------- #Do we want hadware descrambling ? #cam_support=1 # #If you have multiple CAMs you can specify the number of the one wich will be used #cam_number=2 # # # ----------------------- THE CHANNELS --------------------- # #For each channel you have to define : # * The ip address # * The port (if you didn't used common_port) # * The name # * At least the PMT pid (if there is more than one pid, no autoconfiguration will be done for this chanel) # #Ip address ip=239.210.203.200 #Name of the channel name=BBC World News #The PMT pid pids=1027 # # ip=239.210.203.201 name=Euronews pids=1034 # #A channel WITHOUT autoconfiguration ip=239.210.203.202 name=eng Euronews pids=1034 2221 2232 768 # #A scrambled channel, add cam_support=1 before the channel lists #ip=239.210.203.203 #name=Japan satellite TV #cam_pmt_pid=1037 #pids=1037 MuMuDVB-2.1.0/doc/configuration_examples/dvb-s2.conf000066400000000000000000000037411305714132500222150ustar00rootroot00000000000000#This is an example configuration file for mumudvb using full autoconfiguration #All the commented lines are optionnal (except for tuning you have to match your system) #If you want to set HTTP unicast, see the README and the README_CONF #------------ TUNING ------------- #the delivery system delivery_system=DVBS2 #The DVB card we want to use #card=2 #The Transponder frequency freq=12674 # ---- SATELLITE (DVB-S) ----- #The polarisation (can be h, v, l, r) pol=h #The symbol rate srate=16935 #the FEC coderate=2/3 #---------- AUTOCONFIGURATION ----------- #We want the full autoconfiguration (ie we discover the channels and their pids) autoconfiguration=full #Do we want to add the radios to the list of channels (default 0) ? #autoconf_radios=1 #Do we want to configure channels marked as scrambled (automatically done if cam_support=1) #autoconf_scrambled=1 # #--------- NETWORKING -------------- #What is the "ip header"? #The autoconfigured multicast ip have the form header.card.channelnumber #The default header is 239.100 #autoconf_ip_header=239.10 # #Do we want to change the default port (optionnal) ? #common_port=4422 # #Do we need to change the default multicast TTL (if you have routers, default value : 2) ? #multicast_ttl=10 # #--------- SAP ANNOUNCES -------------- #The sap announces are sent automatically with full autoconfiguration #Do we want NOT to send the announces ? #sap=0 # #What is the default playlist group for the SAP announces (optionnal) ? sap_default_group=My channels #Who is the organisation wich send the stream (optionnal) ? #sap_organisation=my_organisation #The intervall between the SAP announces in second (default 5) #sap_interval=10 # ---------- PAT REWRITING ---------- #If some of the clients are set top boxes we will probably need to rewrite the PAT pid #rewrite_pat=1 # # ---------- SCRAMBLED CHANNELS ---------- #Do we want hadware descrambling ? #cam_support=1 # #If you have multiple CAMs you can specify the number of the one wich will be used #cam_number=2 MuMuDVB-2.1.0/doc/configuration_examples/example.conf000066400000000000000000000043341305714132500225520ustar00rootroot00000000000000#This is an example configuration file for mumudvb with sending of sap announces #All the commented lines are optionnal (except for tuning you have to match your system) #To set HTTP unicast refer to README and README_CONF # #------------ TUNING ------------- #The DVB/ATSC card we want to use #card=2 #The Transponder frequency freq=12597 # ---- SATELLITE (DVB-S) ----- #The polarisation (can be h, v, l, r) pol=V #The symbol rate srate=27500 # ----- CABLE (DVB-C) ---- #The symbol rate #srate=27500 # ---- TERRESTRIAL (DVB-T) ----- #For DVB-T if the bandwith is 8MHz you don't have to set other parameters # # ----- ATSC ---- #For ATSC you could have to set the modulation if it's different from VSB_8 # #--------- NETWORKING -------------- #Do we want to have the same port for all the channels ? common_port=1234 # #Do we need to change the default multicast TTL (if you have routers, default value : 2) ? #multicast_ttl=10 # #--------- SAP ANNOUNCES -------------- #Do we want to send the announces ? sap=1 # #What is the default playlist group for the SAP announces (optionnal) ? sap_default_group=My channels #Who is the organisation wich send the stream (optionnal) ? #sap_organisation=my_streamed_tv #The intervall between the SAP announces in second (default 5) #sap_interval=10 # ---------- PAT REWRITING ---------- #If some of the clients are set top boxes we will probably need to rewrite the PAT pid #rewrite_pat=1 # # ---------- SCRAMBLED CHANNELS ---------- #Do we want hadware descrambling ? #cam_support=1 # #If you have multiple CAMs you can specify the number of the one wich will be used #cam_number=2 # # # ----------------------- THE CHANNELS --------------------- # #For each channel you have to define : # * The ip address # * The port (if you didn't used common_port) # * The name # * At least the PMT, Video and Audio PIDs # #Ip address ip=239.210.203.200 #Name of the channel name=BBC World News #The PIDs pids=1027 163 92 41 # # ip=239.210.203.201 name=Euronews pids=1034 2221 2231 2232 2233 2234 2235 2236 2237 2238 2239 768 # ip=239.210.203.202 name=eng Euronews pids=1034 2221 2232 768 # #A scrambled channel, add cam_support=1 before the channel lists #ip=239.210.203.203 #name=Japan JSTV #cam_pmt_pid=1037 #pids=1037 2000 2001 2002 MuMuDVB-2.1.0/doc/configuration_examples/ipv6.conf000066400000000000000000000001111305714132500217700ustar00rootroot00000000000000freq=586 sap=1 multicast_ipv6=1 multicast_ipv4=0 autoconfiguration=full MuMuDVB-2.1.0/doc/configuration_examples/oscam.conf000066400000000000000000000047531305714132500222260ustar00rootroot00000000000000#------------ TUNING ------------- #The DVB/ATSC card we want to use card=0 #The Transponder frequency freq=11393.44 # ---- SATELLITE (DVB-S) ----- # Select LNB for DiSEqC 0=default 1-4 #The polarisation (for satellite, can be h, v, l, r) pol=v #The symbol rate (satellite) srate=27500 autoconfiguration=0 #--------- NETWORKING -------------- #Do we want to change the default port (optional) ? common_port=1234 # #Do we need to change the default multicast TTL (if you have routers, defaultvalue : 2) ? multicast_ttl=1 # Add RTP headers rtp_header=1 # ---------- PAT REWRITING ---------- #If some of the clients are set top boxes we will probably need to rewrite the PATpid rewrite_pat=1 rewrite_sdt=1 sort_eit=1 unicast=1 port_http=10000 scam_support=1 ring_buffer_default_size=16384 decsa_default_delay=500000 send_default_delay=1500000 # ----------------------- THE CHANNELS --------------------- # #For each channel you have to define : # * The ip address # * The port (if you didn't used common_port) # * The name # * At least the PMT pid (if there is more than one pid, no #autoconfiguration will bedone for this channel) # #End of global part # #Configuration for 10 channels #Channel number : 0 ip=127.0.0.1 port=11001 name=TVN service_id=4311 pids=260 512 650 651 576 6001 oscam=1 ring_buffer_size=32768 decsa_delay=1500000 send_delay=2500000 #End of config file #Channel number : 1 ip=127.0.0.1 port=11002 name=TVN24 service_id=4312 pids=261 513 660 661 6012 oscam=1 #End of config file #Channel number : 2 ip=127.0.0.1 port=11003 name=TVN7 service_id=4313 pids=262 514 670 671 578 6002 oscam=1 #End of config file #Channel number : 3 ip=127.0.0.1 port=11004 name=TVN Meteo service_id=4318 pids=267 519 720 721 6018 oscam=1 #End of config file #Channel number : 4 ip=127.0.0.1 port=11005 name=TVN Style service_id=4320 pids=269 521 740 741 584 6004 oscam=1 #End of config file #Channel number : 5 ip=127.0.0.1 port=11006 name=MANGO24 service_id=4316 pids=265 517 700 581 oscam=0 #End of config file #Channel number : 6 ip=127.0.0.1 port=11007 name=TVN Turbo service_id=4319 pids=268 520 730 731 583 6003 oscam=1 #End of config file #Channel number : 7 ip=127.0.0.1 port=11008 name=TVN CNBC Biznes service_id=4322 pids=271 523 760 oscam=1 #End of config file #Channel number : 8 ip=127.0.0.1 port=11009 name=n Sport service_id=4314 pids=263 515 680 oscam=1 #End of config file #Channel number : 9 ip=127.0.0.1 port=11010 name=ttv service_id=4317 pids=266 518 710 711 582 oscam=1 #End of config file MuMuDVB-2.1.0/doc/diagrams/000077500000000000000000000000001305714132500152665ustar00rootroot00000000000000MuMuDVB-2.1.0/doc/diagrams/TS_add_data_all_cases.dia000066400000000000000000000137331305714132500221110ustar00rootroot00000000000000]nHກJ/q72If;@N?m6eI+Ix\oGlp̾ %EY|_-<l\\g26NQNO~lup7@GOl4_VnTʈP1T8?_0Id~ )]n "󛳋xX79 &E׸u^\]fѥE(#ոP_=UXXS$[ʿ$~;W [Çr@zr;\`rL;o!"[?eKzBga{r"'kYm0@('&_ۛ5jz^kͰ`uUs¦JU .BH5'&h`rۨ Gja!pc:eR^vb|O-/b\lKFp?y=RQ$hwvq x %;ә}_ -|ppt{x>DׂRbEv3xzxm+M 6bTQ]nV68X=mT%:aI*qRrˍLqiՑ+>RB8nd+·^2׫PT.m(dq0T0M(Ͻlr Ҍ,ra0oV)RRkgďvP!|mQ$r/Or 4[0OO㓍6.J tWԂadL}/I.HԈAD(X[UmK\ rÔs]UJhNiT@.ر. @hʄFK+}mk+7/U=j6U-h.MΠι^,}7&*H B2Kx a\*絕Nu'fys<@3̏'//;cpĉm*m~'+xfJ%SԶY;:398}QMAXK98_Әdſc>נ}2V 0Rt&J;*Ng{e&2jXG?_"Ӹ_ &F apnǏD5 "C~>𬂺F.(spmiîR'yٓ\p\VS,+ ;vb4!s_ ?1E[mA?{q{v:hbM@4,h' (+tܥl*m ga*Op8#Syzzye?Iג]flr AoJoY6TO>烫+IVE oL!ZEE x%1rC1Kk#a۠ۀbp1p.6 p+v_VD4mWjrAsN.HՒgٞn^H`llX jua]V?ʺ*r[ݴQwwG=AG"]+NQiǃ$_{AdBd\MLjMӁC2" / V .1z1"8tdE i%0aT1q9K Fu%FLo`[-r Y#5ʕBbc<ƬO`Q,z= e^u77HN޼X^k&e%e pL.PGvBri_?}|BB\dZdc}K9vWDJRm:3 -}ȿ46%#'#aj=">Fӿv*2ĥ5l.) RD0:B0a BF ((q%%%C% оײ?|B;m҆txdCU%lN/>r.IȀOJ2Iۅ42j_ǸvLD`9:g-YHB+3g|V0l6tyT윉[*$ X~:j=)n鞬)tLǤfR%s݄ZrF6SIT9Ey\?Ts=q1yes-5jcn){ħ/.ǘw\b*ZBՋ=zG#ZņmxC)D:|C&TA9a[)X5ɍC[}bw*(T@E5ih* hd"vSyRE>]?&v\.b1禕c\& ajAC0B0B0B0:0 F-у *}K>c _>K>}C~H^yGUdx"O*(lu<8Y\Xft1Fu"(#iD#AcP l}`OuaL8;pXM9RJD\:F\, a¯Cb0.BXBXZJLjJW\hA+6Dqa1\.Ud/ւ f WBܴMVAc $1oe̚lqlVoSu ^~UһEj)@A-PƱZKmd /Nȃ$ abHRDn{46>0%_=ZQOIb|{lfAr;>5Vc; U+gh#ZbXTzD}.w=m(GbgZ芼vM"D#Dܓ2)ݓSI.$+%"SRDh:FhRMDDNS!%!$U,ADu=K7`9Zm5ttl1H2Dk0%т(a1"tHˏj]pY;"Tf-%dD52E%NltS+.ʘ13ϭ(u҃vD*]c$4o^ ]Q`2P.]QOsR+4ک+jKf?jg9" ThBywA '_2 v_F& qob $&fƃLF6)v$wH![Y CjH!ۡ5@!9\ fAxgr<7:9r;qH␼)))8XB*fdֶ!kMr;bM] GF=e//_޿M7oҤ{ #6Ȥ7:%#V d%2) SaFSx2iD-KR}c%OsRK*\k&2ɟL&Ȥs:8+bɹ$!0 L֞vd҉H &oY@09Mnidd;g}5a"lH& d\gH{ DT*(e Lr<7:2I^IL:#gd$a_5VCP1x()[Xյsx̷q.U K`U+‘ `iU72-\z5V*ըwmx&Іn͆n.)):VD 渗u]lT~&cЕ\ԖJ_\d*;qAqmi z,2*o7e- Bç !6c\hEtq i];k☳q2$Y=}x^L z4QM&&i멸hKjmbfH3 f;I0Cmˣw?7Ln.#ZO &ߧ~&K4c` "#$Oܟ($d9iInr7EMTR(_SlU[qR *HLlͭkQ@ Ed,ZѾKP纀,V%C-&L4^ rxU-4~mQ]!Rpar1WQa3kS.2ldpHCZSf1rv|Jց`ndz*T0|-HOcRFT声騞 CIZt%,-L9RT41IT=-Ge~Ę]_֓sgףa0ZyݡmްȂf4y9"<#<ΒF+i.=< "1&ɴNU頓d֟@NL>Fh6ݦ>D:iREإ#@)VWQ2 jJil^_5kg!6JYĩb]! )0q5"=ds&-Cb,T$}\1D(<.϶lfEcm}wzp0Wjt8.&IVoϔݖC05FvC&> stream x[M$ȳso` >=Ltv})UfwWbfR)C )ŋb];MO<~ifǯ_'3gp>Ӝ-)ln0η!jf ~Xost`OgdVOӦֹ1 i4̶d~9a͠BKy~9g9~ܺDF/h o}o<_df`5Dfk\pYЖl#u9"O&fW OA\"U"4cX -d2kvko{W1 ^h d6C-ڗSv%Ad5=&@J*94em`W/{FMD^AL@|B6/s~Wxx ٞQyx\*,RTpaJ>VZ-Éب:{%>qK^E"`4 جcQ;0o Q=n JX gM^`#6=ޑ6EYh Oޚ~4)J[>n\؊jVAn:X~ÜC@jk~IeiLWND@=sxp eXy4&c|u:RɊ5fEl4n1j (qވn NHF ֺJL\7JH>JF*4rא6F}d\hRkS#< L$75 "9`'3 1h BbӧCh\ۇFB*rd;m4vlNdXn YX$6brP{ML)* y0&+^,jRstmЖ'1a+O.z*`GV{B l\)JBtSD|EɕȟOH)(r0OOI@q V긎n7A<9S 2.ߒ hNԉ؉À<hIXΨYBK'7#Yӯb[M v# 5ZuuyE[L($y֢ 6W 2ea+qE(E.7I:mPΑ:ؕT 6[ Y%g6%MyThy#v8.?c29:)@tY 3@d-*l rFRm>ܹS5B$jlp'GR| ê=ާ1m,'9<+=u54)UܰV!.C>yg/l ƗOJovZQ%#,T^>s^i1F& 'Qk""؝]%1x r[#!;vZ#v$?9,dw V 8B !|`4WM!LZ9~ TT(bVؤ/H̬q0XNGˀ!3t꼺͠Z4qT0R[NO(Z?ŏΊ`!,йit'hH 05rm^]KHX֦.ɇq;aH. x@A6L!E{Ki>0%``]. Y[oElOJP*scu]WoH҈[^[U;ӐՏ>` s>M`1eNTwjY@=˜c! \27OE$rt੫ڦh:m ާʨSV-ɫHZ ![XD_/+2""o tr0@)Gsr>>&- #BrڇnC>Thw]=!sI2zrƢ-Q49º%7$]sQj׷~N 17B`gzD6HWBðzRiv]}uF=xD1|R#gP9P.厩޳# K>.ѥ(#( endstream endobj 4 0 obj 3544 endobj 2 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /Font << /f-0-0 5 0 R >> >> endobj 6 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 595.275591 841.889764 ] /Contents 3 0 R /Group << /Type /Group /S /Transparency /CS /DeviceRGB >> /Resources 2 0 R >> endobj 7 0 obj << /Length 8 0 R /Filter /FlateDecode /Length1 13632 >> stream xzy|U9W;ٗP4@ȨD Ĉ &q":xDpߩNs{yTwUu9*B !&)#@S4> !xn<0R,bW]B+TL!n SMFi(cLƘ6f3Ukܣp]טb79ț6n3 ] 0jӈ}ZsZoa6q=魵v!OC;DDi#:lѶzƯ}vwvY8bp> {|=‹-ॼ=6fk1UqSa(Wycl~{ II, EiFhKAogre`TyP jA}1l :αd, QNN@mM!Et*S|:]{Ęd{>9̡ b, RuVF9׶^ d]fYQݨ=3[;Nm^[ݭշ_vo(:Mg#{N(sbI64 gP'>?(0]nWjuzOP}MbI`Tt=q깾YG7@Btvkg9{v6&w㥬Ce5ᕔۅYN}ιRуa[]]Wo'vŧ޵_C6*DS_' *ux4I iE%" ';=ñIuvC%+!+ePZ0.L.q Ă.i3ӖUW$T*uYV֜u000P83~fIJ@YbDMoiFڧCIz$gG{|3uu;v7=ȄrK&>s0Oz{oyKW'-UyB؏| tr6M70Yns:-4]$Քue?L'z|_hXv78oni_Xj:c=:@zF^fnqߙ tY4A^ j覘?nɐd Xv}J+`0h.m>9)ouZ2X5z-g6/eA=k0QʦQ)iPZ;v)>{`ڔխꑯu&D)+'U+:2'u۔}n/&!&y,;q'cZ)[j_}}s~momٺ ׶ejQlGq90uΕ hØŊΡ22wf:1ENSceah^Ztv}}WJN%/mW~S4I4_0~Q/0!YAuc gѠN^w+:S'dQ(55Xg]O>9-ŽXN21dNCY1rׄ5}IKVNܻoTuDgg*7JJ:;~ԭ)%[+c  CT?{-4iΎgYp_ƒP Lgca 8!I𥺺_czluJ;)Ͱӧ5mm  )G&`Jfx3x`y~C'2ģ$玖w8̥/et$İ:`ӊ/.i')YrxOBZN*O>}}8#wÆѭ:nŲSކa]x%k +*U9)\AbÝ܌R<|f]*z<'/D.{00r)g*hU~c%NajzM{t((srMt`tڈ$I3YCPVT27GC%K*UUO5hiJ~:hTt2#Og"sIafP;jujlM`]Zu0Ԁ;| .D8rES #^ʑ&7,ngQ;4'%L %*@~x}fܫ7}AY|{?xUmya]G}l7$4ǔwoȮ^Dy3g$ >9hcaK6!"XW{;j|kRÈdԌp'B)%XRjz-fйtv1X>V[,sc*4(QJc#s9ѳc]BʣD/YS^&}߫@S do6ʙt:qRߐ{={̣k=aOܐ;'jۍ({)rY\ uT4ʸUV5!aŲLj'K]\壍!% xjJa2mghVRI*Mt%\)YP2P>L 'J^LscJ0B2Z XjRM7MQ7j~NoZΐw}wŽ-Fþ+5Vnp˾ MHgLa*ӨS_Ъ(V66;ǻ <ŴM3t>*]IcmQt=cT٪웜\m{{]=<힩 *Z[7ru6:'Qi,4|2u=bZLbϼ2F"uN#v LQT[~w?Wv"#n&ٛf͔Qu3Wn/j*KVH&yVd72Bu2,q5g8k ͇DNy>l]9}5%}#NqЙeey|dQBd>'GLJuŴ[:o *mtl l &˦@%*ozԋ׮=ecۺOR=𖇅׻>5.wEt-.) χ8-iSnejmD5Y1vT߱c}Վ:!Z&5j˝:w`G-:Wn=J|jnoyϔf@o=Ru@- H7TŌ S+oeaa B&y/!% UK?I<!; LL'% Ix](Pq{o0!/gCw:龷;7l¸4]Uk7M]2v|}7d y}z[رQ,\(rg3D.nE_Xby$4p*]咰mvVS&,m5'3BG(2"^z^j'ze B9lA͊)IZջeD]{тr~u@C/t = B, r}|y:]X.$0Ӊ6;>FnLcaL*ot?4踧lUQR^2954WzX} LROv jۢѶ Ñ&}!h"0j:E2Q7>{8MG>A^^R㦊} کV#8@ތ:P`i(]*'X>dm]>7 -{[GchT=UεxFb=(;^W{p ЬObnGU:nJ8]qyoj61=M3[WKdW?:Ml+k }>L o'/⣔N ;y3 tiǎi 6|ScˇlȮegTc&z!ı%Ѱ3ҰcARj~TT3`r"V-0m+a4hwHCDًxc>ݘ/@, ೞ0Ra5ݏt1-=Ei#?ݪï-<(Kifr3VReU^DhK ¢8qƆ؞*!8eN^W-shK*ItsϽ hk S.-!}ˎ}Qb2V,xt̝oR8^NRP ~DNMHd %kn9\o7- ѡ)MGS/~0G! ʓenfϦ?BSR^fV*W**GTS0h1Ӵg4ew;J"-'f- 8~`vm$P:!<|-_Acy]>+1 LjVEfmKK|< yL}^,g\ˌ'mΗt6AZ|;)*w?}ū\يh!mP.ARC_4])l;6kYtu^Q[dB02shDף$AuI5Ҙ-[-;C+H#^q ZrCT\ldgKnPԧwktXF> DwǦ\ ; MGۨ>јذ4 m:N'XfY|J!Ar.,Ug ((i|pnY@Hl[-~_Wm0:jŏD$FxUf:%ZRBr_FЃ}FUy#RYn/oVRd鲚T7bŋ;Gp8 kԨOUt |mܰpǴ^l;YU]lR$ŋ+@z`0\gUΕyܫǚ}6n-!lu0=p|?.! aͰ^qV|F5A~/Siގ綠M:P獖 L߈u9ј5$.Fɼ֝[? G!ĐXDU$I$]H2̺+Fe7AclH"7lk%Iҗ~Eבz!N<*35YFwqZz๝(xe9{P8qa>LG8Fkx:3|q8峖QG;_=cJ c dD>2KHJ acɽ0? #aGޖRm# 2o]SMf qVȍ|qr̒c$٢Ɯ%QH{N1"Hz#Ĺ5:/WnoN\n2[s.ss1;25Lȥʧ$Zܶ_B|-MYM}19=%Ĉĭ+a aŽ̎\ر'ֵ7^k&/ܶ o _NHh&5D¿/3_|N^ nO?D|,#'x~Bx0 x Cw#mo xSoh/O^{ xDZrO)`; *J^^P+e%'ۛ=^7xa7.zw 𢀝vxa9 ٰ A ^RS [lyηx⛋Mnllr3&l7v@֯s]ank^kY=y֔)J'T rEOR$MP+}xQS)OX× X (l/EEP2KR`;a0Gc-0mY-0S x( `'O 0m1< (0EdAa g0Aq&L;<ߝ ch?EHFQc!`n>RnMͭF wa0> stream x]M0@ Ɛ"jC?Դ?"m9_mFJ< 4ٟêqce2mT?U(kd|~p=MÜ*-PO_ _2T#!E=y=,UYӨ> v{{ *Oϧ~[/c $֔>ܖևNӨ},LUAZ76pED&Q 2) Gd Ujd / B#ONz"eyhl"]@_-ki*5~D8]ge ?+kiJnBgA_5@U7t?>#~܋q?r<@eiuDJeY9>gy=QqgV'yղgMYg+" endstream endobj 10 0 obj 486 endobj 11 0 obj << /Type /FontDescriptor /FontName /MUPHIO+DejaVuSans /FontFamily (DejaVu Sans) /Flags 4 /FontBBox [ -1020 -415 1680 1166 ] /ItalicAngle 0 /Ascent 928 /Descent -235 /CapHeight 1166 /StemV 80 /StemH 80 /FontFile2 7 0 R >> endobj 12 0 obj << /Type /Font /Subtype /CIDFontType2 /BaseFont /MUPHIO+DejaVuSans /CIDSystemInfo << /Registry (Adobe) /Ordering (Identity) /Supplement 0 >> /FontDescriptor 11 0 R /W [0 [ 600 748 615 817 317 634 612 392 294 352 633 634 411 277 277 549 579 520 633 633 698 694 636 636 591 684 274 611 634 688 317 974 634 591 500 770 837 636 787 634 629 634 530 629 837 610 631 610 751 774 862 686 557 988 591 966 400 603 390 390 731 ]] >> endobj 5 0 obj << /Type /Font /Subtype /Type0 /BaseFont /MUPHIO+DejaVuSans /Encoding /Identity-H /DescendantFonts [ 12 0 R] /ToUnicode 9 0 R >> endobj 1 0 obj << /Type /Pages /Kids [ 6 0 R ] /Count 1 >> endobj 13 0 obj << /Creator (cairo 1.10.0 (http://cairographics.org)) /Producer (cairo 1.10.0 (http://cairographics.org)) >> endobj 14 0 obj << /Type /Catalog /Pages 1 0 R >> endobj xref 0 15 0000000000 65535 f 0000015478 00000 n 0000003659 00000 n 0000000015 00000 n 0000003636 00000 n 0000015319 00000 n 0000003768 00000 n 0000003982 00000 n 0000013968 00000 n 0000013991 00000 n 0000014555 00000 n 0000014578 00000 n 0000014848 00000 n 0000015543 00000 n 0000015671 00000 n trailer << /Size 15 /Root 14 0 R /Info 13 0 R >> startxref 15724 %%EOF MuMuDVB-2.1.0/doc/diagrams/TS_packet_getting_all_cases.dia000066400000000000000000000133321305714132500233530ustar00rootroot00000000000000]rF@)U;[Hpb{&ubWݭ ! T͏}}}n)>rBHM4Km}Jq6<%Fjφqoߟ%";cw,{(&h$ϓvЋOhLfMʲ.'e erǠMٸQ>*OIksbv+qd^iG1ɭbwqfwC*4f6jl sƿ>{m{J!mR ?~yлA/FEY$Y)r4d8RUk1m܏p]ge9zdFI>3?}ʈg@`z@w<ٰ~Xx{0[%u*R?&Y??VTf6cWk׋ȓ(".O;P\٧2&)џ Y{O͢'v7(AT &?Mqy.H<]H^J*KX3yi^\rZ^ͩEM n{di&l|3b= rqC56ύOiT}޼[f G;ieQ{hXn~]'Y`.Oqn[JOi]%Xl_^]o ;[({"nD;Y*iq;A o_h:nջ6S4_,Cs}AZ  #&zT#l_KEPmfRu4)((Њ]2)v4 b*нvx%#75m!BX[C_TV HD*O iєh*1!@JJj͕GN`B0f0*W/|/&ìv^dþE!3M~Ry -vE B1'q#{)8ׄ4px~&{ͯz6WHv\ݭ?Ķ^gؿHbt~ź/t8إF{ (WnW] 2Ktc7 uˑwգ_ULWߌ7kO= v6lvg[$6ЌNYٙ@\𢼹xtgWo@qiA),)b"[>45“Fry`L|TK{e׸vLMDDŽh"-I ze=l8 @O&:~|2 #Uk$xekDjbn-uHLK1$YbŞ?. @xP U U2H4=;ד:IR*`+YDǙjUA ĥg0'zXOtÛ+f}ϕwӃtSZ44 QCCLG)ZC[$w՜靐E}# nKp#[8.M b-G'+4H œBi=:Y(UvFΚY(̺]Fpňdsچ,Y(n41 ΤBx$G;rz.6Is>7"˜# uйm'X3ّs&aƸ\3OP3-&NL<ˠEtaj`DXs@ܪuF$&!_ee3텵MTК\pȺ+@!2D&NJ1.gY"rr}=*(rE4Kp/r(ҺDK!C-=tb*z‰Рki>(5_y^'7,<"Ohnq' ee8A@"ŏgߚ}hdXo!T6>G/< H }T \7mنDt@3)cek̼EŮni< Le꣫pdkpE`]>0rg$;;MQ {򼆈UW{n%j8b:g4!OS:.nFEO3D+3%JrF Ba1M;4Rx2_pN Uۻ}ٱ6C"ϳZa5TX|$RiܢLXoox3ě޲ھpN&\MoKbԈmn@ $[_GIO( 3mbj0)YX<Ċk/H>,geXa1Gvwo!P n7vM8V׺tpK|XbA #Nk}/=;}=;EUS6%lR\&!z A*0=t*O߶{UݴA S8NV\Xڠ&fcnߎq\ld$}j?`=u\RąAЧXr kr% iqS-Z1*dQ֢\SW  bզvg(gV~4jM<;gI. }Vޜ~ j^FwmNԷ{#/Q1^d-Γ//>zp DāY4dJݪQGUk$DBHjkTX-0ML˟8'vPj(=kJ2bC:e8.E".B+q:`s`|Xn^I+ Y]k*ݰծ\9Ś`\wBб`r9 \Ⱦ}L8Ӹ*?&_;3ﬦ܂/m_өd> L"X5$7.>CM^&:t/F`A"\mŒ"Xm&>9D TF_/{lG2DAr(u܎m>U%DiU.%Ehad4ձT VԌ:w1ɚYkR`i1;˦Ca"(A1M3ML QŔyz˴2({8Bh$35 +XrT{SԄ5㽥K 0T.E8u;@7"ukabZ)KqНokjDΫ^^mUNڡ@5-'0 ݷ4Љ!]C6dv6tTW;&NՆ]̰21L-QLDeB@V&Zp`+(:(S[qgAhs&"ZѤXhrO#1#U6Ց~*N:0 sGo#VSAR Z z`R)Hgݶ69$Xuo|/|{"f0޺6 $dცs9 i*`bOhZ9[ҁ3Mpu5?qz9+;K(0e\V} RBA#K1N;wu`敶SR B ßaG:u|l?꬞I!7i(UYA{`fU9 >SG}vOQb(&+.3Wk0HlYr5w/l8D݃Ѩ?}77>w%E%o a6Io ߣa]N"ɮnq}urx§#OܯqWY/(O[z\&dA>Og>*'v+O={ɫ*-p(uכ8F덧0qpS?q{悧};7EX2Opߜ_o ϓu*ɭ?,:g.ZAü7~UyUiI!w7_rhlhdXo!T*p+! G.@@@DOӮ>a9您}"C`pJ<^$Tk+% *&SfжE )%fác4,iėN&Y+#) +C4̇a>&o1Z@vh9#Qd`R; :]W,R)$4e.۔Jiœ$f%`I;afcQ _=P#MM׬aO! @ªC ӄ(.*aδ%Xin)־}}u[6:b{*w!i؝1^t펒vyVw%UfӟN_߫{1T]=Z) Ip̯%œ6PpNQ^n_pPp<84t{E`gpܔ$M}7(¤)A\rW5ǝC(sy2݀Ė^LD< h]AT\Έˑ.#n!2۱ ;OXX /Y L4ԺL q;V"Йut[HPj Cdubq4_]79F4uYՄk)wN\ϱ6g iX9%Z0V,VG>>>Z38S<&) ~QN=2#.a~z1zٗg?{^9{󟢳wWg| K9SW!=0 u+Jݫ'-$1EoJ PPX  SUtHh1=0׺tcG YAZޒXy}fCc`J=fE U/k` pӞ8s j]@1Xhԑ%:A̱A(%MSy3EwNR8ǹ4ë"u9kWka7',BX+B,@;/6` s'*sYc# LZ5EB%Is5%7ܽLuCʔ`&E=%(FX(8at0Z֤5fа䈚 ehkx9r٧Ƥ{2z{ݴ򜛝'YQ亜u_CO\;qi7u |s(9Df& :tmVu)Up7tVBѽdF~Xpu䇇 WrA%GՂsAҥppr) 5[HR1M|rTgdQdೱ.& gt8ݤI}# |b-DBRe*!;0~qnh1ޒdE \`O@C> stream x\Ko$sd ,t009>j$ *C~b͑fFN`#X EV_&Aia Vaw>X]}ZsQ+r_\j䭍j FwxN*c;|~^~qBE/ sGGu!|sJvuNhM+)!eZ?異o/Wb_Ȁ%k\Q||'$x^~$T>Nws~X|?|">uΏ}MXU oqI^X֮!cJk8/5 E.m{ccdN3k/%=s#dP*I&ߌY5I[_W͇WmIx֯k0mJs KʺR: &ϱy #J';̀f,6q "} ύy^..DvD2solB^vEw:Rj4}ڍi.o{ͫdf5y:2w&Ic#)Xw~ IC0a gsO=T*Ƌ#]Q1Jrle*dmR  A 'ŕn @BkQ31*gb.;%/ p Rre0|3y4 9pt3^T.FZ)\g 8H@ez4KQSS&2x0ʰ*V1 Jj; 4$We*-jRdSRX~96\mA gPTl[~^ w; +'ppmN;?K:&x`y\곇cP# @Ϟqf+5qq T,x#Z{q1Nu40~;9~k;3L1rM)r9ȈNn|M8v./1s=1eEJI )tK4dPP艼hmDQ~0ָ1wDP.mCWan]H cߪ]e.IRW%dz60XrF۲)ަ4R`V3MB2NvÜ1 J|,(6k5 r~/̷¦:/.]d)_H=QP ;wktiZEEWڶ`8.*S6ݍi{oˉwIlcHue=¾)eU|1h9ХBcgQF"sCHn%V|Ry` "&Vjxda(yJnՈ^k!lĩ't%WN1E+r2;2\kSqʘglXemċAI}l%R.9b٭0M%ґ :ub#P`T3lJK(֥␅ɝ5rsQi7M- u[RnNlX=\'ɐ G4gFb*A3}H›6&(0LN=KBG?ՆkXxݨxDi?fU$ug V)VI]ruhp 8k2ꃺ.@f)P#Bq㸊sL(]j"! 5 6Vp0!OR 4ȎWm: A ITDBsWS544Yɍ=muL6;m~7.aufR08} . RA=Luws{zqkmt2vZ%x0 %49#Qk霵}&|L$OxHvܩhlmVM3jCN评ql>tRܫNwc' r` s7*P =xGȚ|*$q H#^ UJ}:w}L8Eh&p (ktY+9mAkyoHIT9boK9c^KMG[~jKcLmYŅGm݇-sKe6 .L6/;0}$ϸ,8B&eiGQn@eB/0fǿ]:y< "sVjkߥ1T[GewA`l^0˟W"fRq9Z7*逬jnl.5Ҭ]jQ.K`$QvIIS)[K?]viay큝kp'88ZS2ICy_;/*3 ro5io|((Ow/Nk(mˑ%=Jm[igWRᶾ&ڕ"D|(02,py?12RyQ7fB{|u(5Nw d3?*̎1MdG˄һC/*jsЮ7QII!C؞λbRp7T(_%W\gb77V Hx/@t|Sm8WXu.)JL es ZBjߪ6ԳC:Z]W+A_᧑lE|4C,.(?:kdAz]wׅG @62 t%QokSSa>,,<9^GtutmVM\iMU9~ ׻NfuKGl0*!bNILRdžs^xg4&-c'ξyMc[ ^s'(toz rL0NB|m_!, \$EkF)FnS3=>PPN9 ?ZdMڐ+A͒9~j,S;_u704TFiqwuʷ30Ю2ͧya0l T}a|R}k@= ߟOug5ߟw%ŰyV ?\gFK&uYP8w"W!u/ ؚ۾_D%o endstream endobj 4 0 obj 3970 endobj 2 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /Font << /f-0-0 5 0 R >> >> endobj 6 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 595.275591 841.889764 ] /Contents 3 0 R /Group << /Type /Group /S /Transparency /CS /DeviceRGB >> /Resources 2 0 R >> endobj 7 0 obj << /Length 8 0 R /Filter /FlateDecode /Length1 13884 >> stream x{y|TEoUξtF.jT`E  AL4DGpQn(3" I坺yzV[U9=^%Xd1|ęc.籷aIt%ʲStcw.kM2q3zMg7q;3#{q3&O$bABrQry3>m!xLB32{10R&y؁I|/5D$D{DSn/՗K-e6$|)u/?ܭe4Gq|qd~8YQFOӵ"yY"'ny[Z|WMy4VT@ ^> ogebkԂ4^Bkc)vmޯU6wJ}>|K;JQk(N^H5w]HAYg}+x9 23N\n'wbuՉ Af r {'z75`Mgu,v䆳&LIsҹ$1 M1rn 2`33 LMyz4-D|^G4M?2i/#4sױ+6׻٭_:ҳ.hj(zq[!D+%I 5aZ&m0rXl4etC>. Cg>`NϘoVֽEJBqo$G&#SEvl{œړ^ci3"Aԙ/ax%+kOMsд1u_}y/䇧)^R UP- mk&aƪ}!=q4\| a4,}ƅBV) 3m9R4_ƿo={8ll8G]NvddRR,Gr R|,!ǫȆu՝-GJN:%ĹqN5"\Fo+,x&ٟzu;F9}}6 Dd NY̡=hAh>l۷|vU~,L~qyO5Tn.-;^k񽓧u=uԧ9ch 'w^ӧ76y͒5ɟ&s:!U+E`i2ï$v:3o˟a}x'Tݺ_N |5L;s6Y\_9Kw\E2HC8+.cɓ1ZZ|b}Zou@4)`gZ>ˍv-盼o  } MMM vN 'S¡pjSqRqrqJq8Sq̬eIɕ)efdJ㢎 JKRJB%3g L]8eqhqjM\I{ P;e앟Z`kI/Pf/}6weOl,94jK/+4쑭)_WcOVVapuGrVX>^J.2,08r:)YO7aqڄA/3?5/\hol]sBv`_׮_?E׮{~7u=E 6 Є4E:4&( j!eo'}l>sY^ qf,eVƦ\Yh<05K YuiP\ JF =8 g~OGMzm~sG@XZ(oo4VEGJˁ-_mM76)s=t>U~4 'Kkf핕b|mMk6o +YCDUT|ԵF]9_ϐ&lN4+\,6KqQ8i/P!c<:ld18&yjp8P䷛<9D4 +b3 c i={7"biwD:EAe"뚃 1!z?wWǚ~ WnhiIVWfU(wV* o_w.wڲZos/Ϟ3G#lo&B:ݗHpTt eNᕲ&Vs+hK[/5-\X9v¶nҎJ^JwYư/a1=nmi#)8qoz+ݱ/E?hAswV*x6M aa-ƒBM"%QGKgk'_KY_, kɁ\ӛMQd#xPvyEX1SC*n'gIjo8VyIyk\"5GMn+ΫA.-tЖ3R8ڮ(]/ؼهyRvA%rZ}rC[wگĘYCW f9,B Ӈt0!*Ev9-Y6'u(zMm`ic-4I{w,U|9C3mŸ4Wkuuk9ޚnUֻE ud^1Vpƻ=Y$la;ҝY..7),>V/G/gWГ뻊i!̴l u w} 6y3ts{WF4v_1=ϳo.s,sttl2U͞νZ߻O|m)/v| 1rT~wJo=<-ůkw(mM2>Cϟȓ0ml`S&Y9cm~Kڢ :'sqzu+ʭ# s3~O]̜Wߤٮ։۶_W6V~3c\C9Soj7]WX3. n: miD"QyjM%Y*ޙh%:=0Yg99!Bkluvt DwNNMZn-w,w.w,Np<8HIfVN۲+gͮ>:뷄XK#n+'mظ翍?|G7O);yԨTwM+JK{` gxҫlݗL:0F~}$709]g6薆қcx[%E)Tݶ[&)n]^|ɓh_ Ӿ&QrEI'S]ӓM[IQGR2+1' $3>** G ܂ޢBȮI؅C7X B0!aT@d"hSw 6~lNiRu,3+5>mr̘`v't"Ùߌ-I:+BPEV3<ʼnF4;`DW9rӋgM韤[e_Bʒ_{Κ]w}`W} ʅ"'mQmˏ$e꤅<}trG[BcW{6hSÅ_<۹▗'%YA\#|ّg>x)[_rک$ܳt7*~oQd\8QxxRd[kXNtS.c$2 p1f/l7mnY(P8X 4fMDI_kʑ!PtiM;u*>仈Fwն 8-Bն1Z#OK$MW_Ad7(`F*ZQh`͒kp%s;}R5Ck!׮:ŵ=ɐL צ~ǝ^Gߣ^35E<.v'ͯrY)g|>pK{\zMA@I$t}[؂؃aL{띩dLFf\Վ#uLI?$ãt6 /W["-=`3/I+谍M;OlƢ>#TbyE>fM([GБjfS4Ooe%/F:Ja4&a;r&o;$|U=lBT(W2IGMt[tDˎ=|a'vt'=1ɭ-!$bML`];>IӤ+8x#ׅy]7`97YԽo8-08)߀;̀K{O?6>ß?!)T";-0.eaaj_Y{KM}iݴInt|Yy^밇@]bEHD03o$M6ȥaWGme=M'YW{L;siFId@﨎;i: ^Y#PNsfXbGuWx42Yh;F)֪j. 2Uu"u. eu0װ%lTگKy@{((g:FoK4!l*K8c{8 Nz,zv%ziz*|p 㜄2OSbsjk5~OgES릪޳T;U[?>ds[|mt_zr(UquΨOY:R4 s).__{; "/-=rȞ/tNrmN oA2,n;0aX8+r7?Ut]* eeL=gZ!^`r}-їXkY4 FAIc9ŘnkG.TG `[iQڝ.☬h'[ Hi!4f^+`嚟/Ƅĥk$r+'}ƊyP\` z{K.ڰQ%9#}-}Ohcηaϗj>GҸQ`i=fҥIS/gl9:8F gqK&qG))N&![}+6~M"b<,kDgWbX<]H&d<[dh!EomL|#c2v;], "9bueޥFF>=E# _VvFn]'B_5TBMa3W/b2_[nCĨE̹fcLf{`LY jZbMh}:mu(̐7):z +<5#%dߒ.{Bh,M21TmΑ l{\Y~}޼#;7t㾢!#q?dd"zv͝9<=`(ށ{-T+r&ᬸMD*KlD> Ũ-I CJ<+vsph8o4# qoBe 귯[vLFxʮ#hB8\N#rr/+AD+J|ϲNBcY9`b`DxnD †zdF)|s=ʑ /Жet%+rTӍl3< xh3υ(WJ2R4QBMދ~v<U)N4$I;IBKb;Kʯѱ㭷Z;x6wU m/CD$*H2Ɍ$z87Yō-k*fR R}墨Iji4DwMÆ|OEY“>Dő*ˬcfo=s,*.EwbK9Fr‹0Srĝ/~H듺it=>.h m4/^XS5;qX0Y3wб;u!.iyx<o?z|ZИ&[E:FliZ#ٵ [+~/Z%򍅢B,YH҉ɐIp Btc$xCHBAAֆ來K s=+@YRNdKnA#~NaDKH%HH9W£2\,a22{cc.}<=(We#(r(Zk(u 38g㼄Ϧ]̏B'd6y|h|ag81 帖A*0܈=Gq_3t+}W<]JNad+=r#?0U 2\8^FPǹ&I]_H<관(iԐe<Ț7k2:eWr5:K /'د+p΃F4`yQ~tĕ_q}q}JM ( [9OPMHZo^2qQϢќczN"ֲ᥵ƆڽoC^=TKk]Cummc錫aݏuvMPmA.}7ů 75iKjCޟ~#îe=;ko ݯKwmCtw$B\A / D --(o"Ud [E[Jl3Y|;Zi ɫ?If ?y^X$Gqr%'mMؿw=Wz=D߉9K8pտ!D9}AJu4^A?9i|bHlدbE"2AKv@s4b! q5yZbMw#$ z/gb;OH4Ơu|JH,}MHo>?X'O '_Iw%#x5},Y-X2G%'HףQa IxU+^%4HxA>_!%=ܡ П2ġ 68ʀP+i K)7ۛ!=~7I\Ͱ[vIv7> stream x]ˎ0@|fnCMMET*R">Lvr\]?:®y1\[y^ m](~+T|_p9.Z=gS*G⼜Nm.aUUtaJ۷T>eoA̚-׭Cs(U:uaC0}:W ]&!m!TPvPYN2_詡WH2{hH4A*5#_δƯƯe]k3~Nb4~VzxH5~VTd@[瘒ϲqdϱ3cfZ2񫙒J~F?$ ~NJ&~瘼gi1A+~bL<`~y ߠmUt endstream endobj 10 0 obj 485 endobj 11 0 obj << /Type /FontDescriptor /FontName /MAOTUD+DejaVuSans /FontFamily (DejaVu Sans) /Flags 4 /FontBBox [ -1020 -415 1680 1166 ] /ItalicAngle 0 /Ascent 928 /Descent -235 /CapHeight 1166 /StemV 80 /StemH 80 /FontFile2 7 0 R >> endobj 12 0 obj << /Type /Font /Subtype /CIDFontType2 /BaseFont /MAOTUD+DejaVuSans /CIDSystemInfo << /Registry (Adobe) /Ordering (Identity) /Supplement 0 >> /FontDescriptor 11 0 R /W [0 [ 600 748 615 817 317 610 634 634 612 549 579 392 277 634 611 633 629 277 603 591 500 633 520 411 698 634 530 974 634 352 837 636 633 688 770 837 629 787 684 694 610 636 336 500 274 294 524 655 631 862 390 390 684 557 636 636 591 751 774 686 988 685 360 ]] >> endobj 5 0 obj << /Type /Font /Subtype /Type0 /BaseFont /MAOTUD+DejaVuSans /Encoding /Identity-H /DescendantFonts [ 12 0 R] /ToUnicode 9 0 R >> endobj 1 0 obj << /Type /Pages /Kids [ 6 0 R ] /Count 1 >> endobj 13 0 obj << /Creator (cairo 1.10.0 (http://cairographics.org)) /Producer (cairo 1.10.0 (http://cairographics.org)) >> endobj 14 0 obj << /Type /Catalog /Pages 1 0 R >> endobj xref 0 15 0000000000 65535 f 0000016138 00000 n 0000004085 00000 n 0000000015 00000 n 0000004062 00000 n 0000015979 00000 n 0000004194 00000 n 0000004408 00000 n 0000014620 00000 n 0000014644 00000 n 0000015207 00000 n 0000015230 00000 n 0000015500 00000 n 0000016203 00000 n 0000016331 00000 n trailer << /Size 15 /Root 14 0 R /Info 13 0 R >> startxref 16384 %%EOF MuMuDVB-2.1.0/doc/diagrams/TS_packet_getting_cases123.dia000066400000000000000000000201031305714132500227430ustar00rootroot00000000000000]rȑ)Uwv<3=xS콸uNR/*H$)RERu>{܋]HY"EPVmR̯w᏿\t0<ft_w߸?~{=9~b4 ^^fWleZ6\ix^~{ew//fEl6\lT\/OO8_Xw:'oΪ˼XΆk_ɤ,>_\^j<ٗ{KjfjFֺ%2,&}:l!n~äW$`z|5&`vx<,ќlr]nOgzZ q{l3i^[nw6ptV MXy9< Ҋ|gǿ$Itɰ\wѬiNŷ Ղ}ߕԏA>͖\bCO}u]3ՊH /dqWwR~s5,F;^PV?߼X']~7>(&O_o )?"^ V2nu._}Q* P·-8`_ގb9,/OǓ}"_ Tv(&bVmq##6>^=, C=Ѹ=+VaaeMݓԻu+_>rVn:A>Q Ί \1fٗxs9 NX;~AnyqGtvQƕ,6X!B|tYBYIZ8uBŭx^^XyKPTd^=3wJQR)J IB!PipjV(egr'\8\:&݆m0Mrzz ͏:q1?^vOJya9:$B*nI< S_8+{ <, ĝ+=ߠk>,+wԞb4.W'XT=g+͌t)hy ErSIsyR;W߾Ɵ?ZOD+)RH63Y 9% < ɥK4M$eP;dR cq8t$a0GG$`01t1e1ZJ)b!eA4gkTKH` a2[ .-9uN wHA/fӃw|{80c^Y|sp|-"Fi2!ҁH)qNE@;Aܒdvq n{Q>ґL;'& 㨳 FrҒH}PJt#lzmpͻ|!E*pv&K)BI:τt)WJ{Z pt ?@Ajv7Rޤ= .`QPW$Z-+%$ه_K_Bh_I ,sII i!4y`zAΌ/H.PU[%Tz5[ijn$o+t]đ>qɄ'~׹fG)v!E+/GzQbL+QL:1w_(?QVD7.FI5υ OˍeV&o @x,„ 7#c e:BMm:Ѻ&סsJ9F7/ϳU4lymͣxw"QUA7\FF Q&4IILϤ]PB}2y\v$ DW9=*Wc󘐲Wni_r.j\~ Dˈ*MٟҔPsCt}`*e#-$pRKW2e (F*XH/Ei^+ €jBGVNA9Ss"PscBR8 LtB Ot tqLJ!gh?BeI0\(kᶕ$fZHؤ6q-a)O l]K$Q#D2wD6-FlTŖs޵hƖӌJ;9J:cHt%oKm7A:sc\ߑTL0 SvǐJ0<-G bԯN6(0,/ nX$ՁV&Q+F 2wK@D vML}w G8H8H8H8qrr6[; Y$)ӎCED5Rli_!Ng)!3D1X򓻔%-|8sY@ zrCcH $Ϊ?U%_5mf YE R1I.-b< wS1LUoSA$dD'S|y5@w_Q]/ôps:&Z* X}v8H"*ҫvTa6o ,WҫHJW=W'$-!T\\J|FD,yzjihBN2qQ#ED`:Ba3Wh1' WߝZ)M뿳|NI"  U-nӅ{nbbt4CE:WDR$=3:b㶇D.WKadX/)Ot(exW[TvN:=TT͝8\Z&{- !:Ll="q:!7yM_wElN˴7,^P6EBm/-/=nBøI;U`qFAZ&7.uooQ-UM6#LU]z5ܸAĆ,0%{lw;]ITk 쑒Y$ϤL0@L<܄IElvhu3IZkݱ\z{-wyR3o|QLF9aeEF&*tMGWj^V.m k[a|xQNy?FEr1uOyzVu4"V{Wo/_r{j|tDŸT.ݺ^1[h<%@}Eҽ@!L2mXgoȥ" |u 1u5ᅳ3hz⎧_-f|-4QFu4wTwlncSkعsEw(˖Pv3yolWkܦ1*7zۤ#A"g!tO]q5Q?NY6$(ٮZ ȍ [kw-8BF:QaЫ BumX(h惇?be '5[|dHM<nLzB4{@k5y@u<`aεLܴʤ@GдEn_80_ gɻ"8P_͝;)gr~qq]ETpaIy>rYƢ #[I#ہ>:czhP+6|›ߜĉs˵`^*̧ ;c sNh:CD#w<Ј:҇]ۤi<NI07P@(]~*/t/ݏdQnRkl0WE`TZܜ:*&tB7:gY!VKmN^o@ Vq|Pmk9]AUd_(!un?k e21-6m ,0=q ն0{-9JJd>fi^haǠ< *!ĩ{_IʽhB*B {cc >v*J\ATBeG* R`N$_Q.2J{R:JE$\lIL5K$k5|]uȺ,&A1˫eZNG"c[m,W5UQ6AQf$ɖǬZ"rvJ]UjDWZ"U8)*Vu(!4ᩞt ۑ {P]a|EQfBi )|p+I$0ܴ  }:Ɨ(s+KHZUtz+[͸[e9+tSkI=%27ʇ:"XCl06 qVwh PV I4K2'80%Q 1lF- oQx[- 9Rk!ƥif"+lE]I=svgY(햬J*(wީ,(Pvɔ~ [SUxe`B4]ITX3ktygsp攤GPu5&eaÑ:R ix%#Kgo6tV̮v]OR&?iFMť)>=$sP6[w%/3EH{Sozp⮞5ŽU38VTSANXm;^qp-cNIO(@.M+h!! {R**R\ Yځќ595jA5>Vɲ]OF'}7 ̃XQ]m+Fs ]V nT)EHm0'#tO!k.*1"ҊhyKr9Ar$$jX֜gp8,( a 0xֲA#ڄ!wÓu7w;,Qv}>$teA:S?QT)q6,XU5]&NJh-!ڣZMjbN8/ eW>Tk`}I;ي.ޛp^]`t9 !XJu+@TP[HMʻqۇ`Kd۪ɛY.Ȁֽw &D݆I{i:&2]C4sIZ$Cܞt.|xlSe\+zpto.s ,쬜wLa9 ߆׋I 'קkdb价3^룣 >/&%OO7o>||oY B_nY۵Hzz G;6CGмdF>Gy?0iȅ`& j&dBZҸ kw"{vI A $$$`|`ȅb:mBw;ppqPwbGW.H2iSvx 28NU^Y/He &dxyc\p'" =Hŭv\(esy(~ ͅeC[.XkC3;waO[3/&$R){qRm+KÐyRo0t[Yn J?l;FBB*)RNq@H:'+J d/HX3Xܴn!34Ӥu lFF8L\7aZ˕c:e1R I_ts ZaYh)@ɪ=I3܌4srpjeGGu&hLT-pU *7'l|%45 =C}E6EM(Iaϕ z*JZ8aL6SgR)o橚:& Y;s+^h.(IYu\DpcjܸT>C x,%?"\w!f7-'+t67ֽcliu;i*w?SBҥEAV%VxoFknagxHY^պ G9.­S"Lәiio4?!y#|y#B>>>g |u)Ba:es\5|&Pޙ`Z]nF)u|_Qג}#þ-wNI:БvDτrŸQnW|d^y}&Cs: s9,:H鴘'sYȦp8.6]l4Syw1^r K,]2HTZa|{0'a %^MuMuDVB-2.1.0/doc/diagrams/TS_packet_getting_cases123.pdf000066400000000000000000000462641305714132500227770ustar00rootroot00000000000000%PDF-1.5 % 3 0 obj << /Length 4 0 R /Filter /FlateDecode >> stream x]I$q篨Nq_ |=ӛ ”}32g &/>0k.Au:6˓v^~OBヒ_gq[%93X\ś?oӟrMR\w|Fm:R 닱sT" P?Oy<MfZFщ1;af6I< cYҋNbr ~_~"~? {y˷?Nq೙3J9huqrV_GQ2ͩ|O/<:~}K/)5'x}O=?|aOE0`UZwq]4ZS03]הrGNbqfSnz6[d{cPH>3W'M:jk|z?o|0G79[Z׷)|LY (fi$-Afs46LS$ vQiqGcvxqIFǎm1.Tƥϝ?F}|])]EQe/&:Ʃͭ*iAdl}ؽ$R1Hxx/ggUԇiOĄ,p L RVAB غň$/? ZDZL!s!M5c 5Lvn,Ul;h|67+RIkKl0J@`l&%aWhߗ,uzi+4VoN4dnBMڭQT1h}݋3i[vyoSȶ1lô%v6:jf#T,Yc5v_}Ř ]ޚMK凞%', oI-0t߭myH%u =)$F^@Yx&g)XlBa ) <=!m# 4!m Z3;uԇ^FRg4h<@ĝ 'X#x iT80qȨi)3{)AvKs<'%6qPT'wtEgɰA8| \62G=+1Drdj`K$$Hɳb i,ajJtq} ɐZݵ9;- :!@(Rf 橯uݾO0(QG.O"E7 {ǜ]<' :k0i8 tp-_u%Qgm k^^ {\7Ý­-f'p]*f QyVV?֣ !68Xf g kgy?ANhrkKv@]mkXbNiC-ako䶮[~*5&{O9 mG^~L+Ł7FV1yS-__P(fo9 |XfFBư&,Oi 9ENK.x5>G_ִ1Nll,@8ǤTG~ŹIQz/yDSjv2тbU0 Ҙ9)C+|P '>P^0 *mB˚3 Ӏaz}eγ-SBcX3yzlz{$: ۊma7zCUēghrt{c}w-p3gw$J`P Kӯ l2qk~-[٘ƒ2jvaj5Gk YjW04YշNRqQ2p_E_[:-;PTWPE8I#Z"'B-2؜skj-|gi!A)s Rzs53$uC=a1*\7|eD |W(r0r@r\6x*|E FX(fA-7Cl3D Ma-y"K"ߊ7ޚ&/BKRU80Uw)T&c=}d㺵T@r]y<8:hHI3V'5HK0Sn"tFrݠX7`BT] V_lZ?M ٹZOhWV8YtlIuEDjǀ:Ԅ DG )p^+rUnwy–pR'>͍҃u1I i?o#ˑ co]`!-f/Bar#/ߐ1ovj)A7ʇ7Z^{$$ ݆;Gi6调<Ha B㺦pW;6V2.kOAå&?Eq]ة0\ id埪j{E1'Ɠژw[+l.y ɧM3DQBp)g*+Tq4@^:CiO8{xqQ+/1Y1C"1=Ra+)A'& ֢mn}u%p MiSq,l04#PncEj7-Tso PL@`UK~sU7뛭` ET1puubX 8` Gz֭ Tbcv٩qmR 鞡V1ՉP"!G[3Sfjfd<SgSr2M殷We]RaSR un@+~PP@J*52p8$%6 64 \cpKqʧMʴ=#9hEvc#T>qFlQIgb%5iW5 PQG^/Ipg˚bb_ݚ;QD&c$SƂъg$P6<.j*K$Ys7̚Cҫ1aN"#Qy>N%g|i/~Zx,'8 ;q=\W%!PrMY:dHo|VT!0v߈TW"U*5RT ;s7Y=UB)BIh}HtO=.u+$)t#e4([ZIB)s_{ܘ*-ʼAN ҅dmz P+J{c*()DS"d&si &yyB!x?Kpg= MG6ԣѹI:nCe~vfiK @Jt >wrfΕY06jJFg[K8j RL/̸361:(:A?3K BmVKlH:g%L0h8(En5υޢl>&9 6XozC+g\7m; 5Zv}.¡#)uKVO_..MD=QtWK(Uը%gO@V1zfD2B':I =2 ~)VuWdǤT tWK2>nu_&Vu=q=9,ɺ2 .%YX[SJE9 G$Ɏ[j,oSeTGiwDfc˼R$".:w; u~PiEZ_e3:s$ pt:OI冿UYX~)jHnhai[a'BpؓNs,kN24&-[wI+/_HMuۢj3<K, &sMGcT>zu!cEiw{rj\4]&qv<(cbV A8p`g3rx1Ԇo̮=k*{ f]`G\?9i2tk~l ӉԒBoUFR?u?Yl}-< J3r謲1a(GːtcϸMISm6ZpphEj:&CyҊΞ,iqXnigTIjI"׳ ]HyM0V)9UJSAJ M eˮuET5%M'.% wGp%T_~+K[N+ZD>Ym Ku{gT]aPeZԜsř:3T=eAs pGMw_i<La}aHN[渾tKuSĺ+uD0ھb54u+RbS\iMc/);Z[k1bPčٍDSu[.~BmEq3(\6ƅڤIcLv}<Ha!'}A+J{ &sD:Q*q:;A2>Q [J@؈XaUケF]e<:|x{ְ:}VqsOF,\Sտ1wzgi$LQ"# J%V灖Mw_(`+y*@mŽ:'5ݙǗ/m/TõN,9KwrWb1qdg^^pRJK> >> /Font << /f-0-0 5 0 R >> >> endobj 6 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 595.275591 841.889764 ] /Contents 3 0 R /Group << /Type /Group /S /Transparency /CS /DeviceRGB >> /Resources 2 0 R >> endobj 7 0 obj << /Length 8 0 R /Filter /FlateDecode /Length1 14964 >> stream x{{|U̬:s~7PjT@BxTDhx  #RLDV?H?ZmHf_{u?799{Ϟf5B !YD$O|p ^g !TV̘ޏN#:NvO~`^EaBz2i|ޗ Lg$mʃ %xOOϝ>U苘QS Xm(MhTm>MVwB}>|K=JY^,N^J⟶O/%3/Ϋx% 82#FԬ6 T49kMF 3=Cq[}~ֳx;Bكf$'&BDAlPpPfk:Nq渙t $҂>}nL|^RO^4}N;2ao~./#437ojrƾqw{~Ԣ& n%& yqoB(MGY&Eai>Ѕ Й, țLCu=qK5{niyϘ&PRzKOpno[JEu.m~T \[n4tYH)Yp6\ B=1*b kbDaٓbu#H;e8L<8,"y3̀#L'4eB OݴnziY)Tg}"g{(CyC`s5rܣh:;ĝڝzq9H$6 &ib6MMfyl! |JWsyfYi=Xajg`3J<=o4Buέdζn[6;_r Dc1OY{AUhnS_~(toߝeu0MKP>m?u2"X-YiIHg]lϣjǼN B2 ۯ4A$EJҽfȜan5qLR4׎-]m'Em$ t9 KJJ,I{b=A_HCy yyIyy)yeBPr(%ԭ$$$$$[Ie 55I55)˺ɬϼuiE]%%%H4#yFʢEIDC,/[Fa>)BHƙ=oljlthK=Io r¬SoXb^_W]ʆ1V9U #t9wW[M>J.2,0$~65yq!8oܢ5qq^c]MJ~$W{os:''Fm{rr>?~]ii~?yD_ެp  Є4:"LMP CN4|6ꚰ+:~N~2"Y&9hV&2ֱ:xMajM2 *bCD-TKhzSCË45LgS$m{.vmdDkvU) e?y!WD(3qaj*DGn`fiԚ^@1A>or[HmvwQ%r61`t||Ӧe?%JK5OOc'zU_=te&`x,"ys:]Hh>.%Qn2qxasR4Fϊ672xϢtƯRŷQ^Ј04\VJu[[ƚciVkko2PቢA^eg;֓IhK"2ӭ4G3ݓK i!yU.n$!b!P'3-6X7{Bz%DF飍ͻrK=% ZXSS=eJc{gy\X\Z^h:jܛ<۝ݻ= |g|}_ 7͡ =pȂ90wx7 ok_([e=h_(a|Ak䧐.AY:{s BW=zEmC |XӃo)@8 \̠{[x˳~~Dn}c;Tbةf:#8LrISJS1h; n 7O\S ]yjM%*>o;❽0Y`88$%rt Gf%f%e'geV[Վjg˯4Θfip /@,AFOpMu> C1b† 1hAΞh&k+WKwzG2l(ʦ|\[I  hM^"7?戕sO@ߧ}i DmP_)nB q?<~qfe8§NI9xO*9KEsRaqCNRyXSg!Nq&&4e6f2<&dy'V`Iφ<*E/^]kQ^vq=L , `s{n}sRs[} >lopFvOogWzt{&N)PNOKvm7;j Aubb@ yT7B[vy(J:[wa:1!d> E ֽ$FaFUV@zWRj T%# k{-R~!ψ/|X~<vw &CY3eBY F*`kLGOBiWlmQvK@ YyPA 썇@efzP!3fHv)K;)t2'O.Oc\&'L44Y}G|74=@g덇g-:Ik]zVvǜ*2''v߂J:㡜dS(3&6]M>[Ũ-A KJ<[NQGb>D#Qmv쬸G◐%K$;|hV}Hg]#t{Y?{?1+rOk׮9tm7 SW|ӱzf$olH(_CYD^*'YoI(Wx"(gɲDїPq1Mf9bS9X'L-btVU[}DPsވѐpFe|3+aZ_OkO{D _Ծ?5SRTT܏m#b?: :V9?gu\w״$ԓ jCEE熊iH,jˁ逰x~:sw¼@jm[im4(`2+z2d=JzTUElZ"9u@T21MhԜdL35!}jSwPhDv ijUЖ# 'm v-8c׭1U'bJ0EƓdbWo(:טRr=U4r)SMq Mq7fZW>BWiW4VɪX5[ֲP721Q9@, HQ6O6 I!92(2| /[ Ĩ t*L̘MPY|mYFW BTkun`Iؠk [qTz}%me#aϥz}P]S0Iaȣ|13tL9!rJj?`o C#dG#[A*–afʧp--m>C|E63m3GIaח<.^k\A.1|p)1Br[]{'w6M{1#)f1FՒwu\t֮e|F8(AZHq .;d=;T "6BeBzV!Yų #vNc`roe47Do+ϺL[!bUf)] "Պ #=0E9 ILnYN⎅ 1N;d-YO6R4+ݑNvd`f,r R }`6Z^l9S=0a,w+d'2L/3r1ͅ91O1fsU*w5hVK{6y>\z;.WHw8/yՐx.k7bb*=\Wjq9|x31"Kip!qzn*{:!7A_Ү)kaN wy܊A+ú_gwc Q:??b=ΗXVAZc/sVoh\E4cِ!d ޺Zm:J\]si)^M \g\]DÔut)yPG}f51AjFuddV'$&j$&&$'DaEE!:@d鋈EE-;LЈYAFfO[arMt'B/fH: ~*תMP.Ƽv NE ~ܧ0簮"DzUݧ;D73;$N ?q)cQcJ&'V&m0j낵6L2}#әG3F&$gLmGtdsEGn =4k:GK#M?s,6[G!?VccsM~}~C~1i;&} 4L1t][fQWw:QᲒ(:Q]7auu^4ܨ t̘'b;~(myRB~nENpw^7}Lz#0jً,4E?vmT}%vaVm*L8>Yy[uϬDN Ed"h-g|{ƪDF}yAtÛҿWi єK)LikgG]g?[~Y/t% OѾRΓt펎FэA8l/{v%B12kiba$A"&I<%vJ=SDO#B)ޗn!SS::٧~V9׮]/k[9yRWhǟkVZ* 9c[/Hny?^\D"Q 9a YƐhpXm0|Ają/SobJ9ʹޗršppB;QE5;mtEt*<~ J%$*ruGC 0RJ91G̽r5Vt>,4ɨ,'OO vzZvNzk {._e/)9>/GHd1# "!r#)̯m g6{>ƞô`=o 1YCZ`8WQS!r$q"EȘ wF~'},~Yb"xΓH#=Cf5!>8x ZjT\t:N9"M[8t)9IΆ-$BAHVNU*pGpx&2 ZDbޮf`'@Oq~] Uxd֨TzjH='|Y8&uVA1_jt6]k^OU=;Q r͋2 `T@#x.^# QjBC!*^:G(j89F*y5xUG/o1&Ҕ=~5٫'7׼˗K8Q  h驟?㖒1 Cw:l05?o؍Cۿ6t7!yǼ;ϰ=sW{$+={O6GWtB\}I;݄Z!QJfj+hm"@jH% 36Tҗ&~rPX$WqCzN.b^k4dZ66udGb5~Ml>gp([ם98%ڭx'PONI:_?)tRc$Ҁmv=YnzT+( '؉8$9I8~ ^KlcHH7? ICHF6o_\@HVl8F_Ayz{''flk F"NAԓu #odB/Ih ?|ᆿK(;7._QU:Z6O _ᜄ/ዳw/,x.\y| J3s'?q!z p$cZ|8*e>^< ;xGޒ7$.ᐄ$ASuhkQ«ƉW_WNƅ.Áu:J /I[/atv/_hCs~.mnl>ls3PV [v-vbrxjW<т'%ls \Pun> ֹ6X5VšĚ`"Wb8XJ%ZKv#X+5QSըtX_JX'JXI /$,\ ʡrdPT| $u'^(t@D(pAu/::D rЫ)zy =!{)~=.ntHw ; MBnHA9S\Im"$C Q bKrBMEIċ"c (! !BOK𡬾b.O9%%g;#!) zrd^ 1z Dm9?%/o{ endstream endobj 8 0 obj 10980 endobj 9 0 obj << /Length 10 0 R /Filter /FlateDecode >> stream x]ˊ0@ -Bl胦[3mgsB HqtcǷ4f)xoG8ڨ0U(K|_x9N\-^tWO_/RBLtVO^Ot-GiUUq8-ݷn]*s1lz}_25-9}=P)4RޮU!ԐԶd*T;,';_ȩ$;;z$gmH"4@W5¯3-~TƯk-~I}jI_-9sҵ1S@iď^ ~NT7Ys0dOd~ҋakd~/NZ! 'aT!,՜ů?&mR?AHTp?NY̏tǤ[xwo)mC)~]˼> endobj 12 0 obj << /Type /Font /Subtype /CIDFontType2 /BaseFont /ZCZCXK+DejaVuSans /CIDSystemInfo << /Registry (Adobe) /Ordering (Identity) /Supplement 0 >> /FontDescriptor 11 0 R /W [0 [ 600 748 615 817 317 610 634 634 612 549 579 392 277 634 611 633 629 277 603 591 500 633 520 411 294 770 530 698 684 694 557 634 575 731 610 631 636 636 655 862 634 974 352 787 633 684 591 400 837 360 837 988 591 636 636 336 500 688 274 390 390 779 751 774 686 317 636 ]] >> endobj 5 0 obj << /Type /Font /Subtype /Type0 /BaseFont /ZCZCXK+DejaVuSans /Encoding /Identity-H /DescendantFonts [ 12 0 R] /ToUnicode 9 0 R >> endobj 1 0 obj << /Type /Pages /Kids [ 6 0 R ] /Count 1 >> endobj 13 0 obj << /Creator (cairo 1.10.0 (http://cairographics.org)) /Producer (cairo 1.10.0 (http://cairographics.org)) >> endobj 14 0 obj << /Type /Catalog /Pages 1 0 R >> endobj xref 0 15 0000000000 65535 f 0000019003 00000 n 0000006057 00000 n 0000000015 00000 n 0000006034 00000 n 0000018844 00000 n 0000006166 00000 n 0000006380 00000 n 0000017455 00000 n 0000017479 00000 n 0000018056 00000 n 0000018079 00000 n 0000018349 00000 n 0000019068 00000 n 0000019196 00000 n trailer << /Size 15 /Root 14 0 R /Info 13 0 R >> startxref 19249 %%EOF MuMuDVB-2.1.0/doc/diagrams/TS_packet_repartition.pdf000066400000000000000000010713251305714132500222670ustar00rootroot00000000000000%PDF-1.5 % 3 0 obj << /Length 4 0 R /Filter /FlateDecode >> stream x|ˮf=6b߀+Kg 0 qGP5o?9PҮn֫%E 󕾞o_|ӟ_ׯ_~RC5׿ׯ??~=-?"SΎjhmԯ?R~ھʿ_+_3O||+読_e՟/#rZ_N_rYz<F<񫽃;O`JRǿ@NwO} =:Q# x_ɋxߤfӯY; h غظ] ۖ57%8ǯ>( >]C}ugPUuP ",MIuM&ƝIj꿔IWAX/ui`_\R6KcsY G j2Ŋ>gp?'rM&HeY#KlXM2%r$iTп@ q&$?2[+Ohm>CuV4V;j6x`HA\X.+t+)+7V~ӼT苸u5bO`ouwigBNߖ6ɅX?zlxTtWɌ$vĆDÖ*G|Cnf;2^v`i/o mi\/wzD{#8c/8 '=P4,fߏ-eB8h9~xv#{MW@}t# ' zmoN/U?!dCcy8b\,a"6g2T@ueP1_kZh+]4k T,z^2<:{,XV>[a^XapT/sQoq08j"f;+앩c5SE[[&Wt]=BOFR|eTCa)RK7g04x/ع_?e׿}lxr ^ )Oc!Ns!fגy%?ך9ΚY"$ǵd #Evo Gd8RT`A q=-АtݟL|9g1s/-M۵zf?]\qڊu!6pn|Ax5/ Kk}ǙV"16s`l(^:?n9[V ow>Cxl7_=6}\ mf q`@:f ׾ mCX/t3c>/&6ȯM &3f yv ~:oɹ20`p,=1q6Kfs߆(֬ɿp }5X 2cwKY{cec9I@b-M[{X—`oY%wV20y! >>U :6#v1 -Ȭ Y!;՗0޴+6u0wgz0*a<"f<̖boL(6 BݳmOWF"IqWxs !z?fS"QZI'g3<6D .v v?>Bb_?_7F`:= `{@p A/0"ho -P&piW 9z&}E7/ʝ]l4$ޢw)t8e$|3c4 1>3sk.ʯNBc`D8F`Ejl˙O"XE?]Xc[_p;W*c :bӢ_#Rt֚=^0~`A InXRqSI,l&k*3<-?oݘN"T;m^5yFVokn盘+u[tF' NL1dc&ao}},SïUvA)>G_ R_w0$TJv &]PiqC!R7k쮏<:[Ǐ15JFsyTp$< mٮ 7C lG|ZhӰG)J h{OeEm{ywD>b8KyWuZS]ۡzjkP $>x$lzQ?a$F%=BܳڏN 4;w{J^Lo}CF#VAhCtv7>:OtP9S[hA.~;ɔX{oif7?&j xی|̝n]@MK"k)b3Iq2"< E?X9?rM@xQS.8Ə&ԕ- 1>Kb5 JVܵmژW|mykN`N[Gf>? ؤ(鱧{s>w <"Ahߧɡˎ9#J#&CZg9xL;LI!~߈;~N+֒]zut|.>R: ;j,/\SߠA&<̃fVhNz3{E]eG>@8i0 {"CP#VIvf{_K@|T޷86R:/r` \.G sC/>jL~,n;q[߾nq8 {"6) 06=5m5qiQ@.׭ֲ3l&T$vg /Z2Dz>:#זk}xO &;/).G|^Kmp4XBѳ@=<Ŀ-ٹSTJڶ@:P Au?#%Dyß NNYĞM.҉) ~N1uv%F| !s||1C?E׍P6wG kR{ܙ.x29d%km:SF'7NB|05Cn#EF1sƩ퉄wz=%rcO^`dv"zO,j/Pza~n2م-%29'M|_]Wl:[+|X|KD2;6+px*> ;.Mpa /FJ. @a;ÁzO:Em(3]@tx  Use`b&`f;GCZeu[q&[) ^]DϡGD H _H:c(lV|6ZWuWL=CoS5ILB&rbS9abyKv(0^Y6f) ci,,xEkJj E7[`Gě0GCbЌ<1"db6D1XVc(j`php½9^ũ=⽂Y c]--oa*08bWbql^PZ;r)vjAi\Գ) y)>|e9(׵_?{i/~1]moօ;0jxsư3ϘsTQb Ϊ(e!^eW2'ENsI\-Ⱒ H;2p69b`4T #7Pxy"قSyd]G ُE0~]~F Λ i jd̷J0: 8~=H /0  #zyk=<d) b"4%+7jKr/$7T_] B$jKr}IrW@ҀC}5$y %ȨI?ylі mjH%$a=u Ԟ=8P< Mb <5ZOKy_q ^]i#>#gqdƙ&rƘ1EzLơ7G)瑧<Go#ۋϑ'>;wăyx0yt<|>+FI@ȳ3AV<\g'lֱslYB>`TO>iP0}i_{@ α}{g.`zgt".O1DZ|rӎ=]O-Gp5Iӏ4v%:|QN8V]HD8'V}kgJ#i3uLUg2aէ߁@uoL"DߪjrDdXHk4 B-pnϻ4TAM#R_JP̗_L>Iq>[3Zs$=V>Bv.piTтq{fk$r0X@>NNJCTjb=|/Һw5on⣾;L&ç,Ԥ?7*t.ZRIXUR7 b"cFW{0pϢŃ^9`\bE[3$ v&b2&UiJ"g=XR 'ૅ4 z4WWI=4Rcr\)_ T/E#93etU/M_\33luZHfQBK2 ! YG*wL 酐V,k#NEmf3Ne8A5]a M¡hSӪFKEC?oͨS _Y]Kp y4){RAl~4_(~|)DuoŞnl`Ls6ߒ"|9-V,楁{CL) +0&N/@HQirc.2dR 4Be&O|kJ 129VОD[I[*SRE e\e7 ŋ*sN"\TͪT}./^x}Z$1J력DGRJ%h^ D49_(}ztcÓJ.Ʊ<<[|pHFټ|81/5{WcT[- woO Fen動t; $\R?uP1L\зyC܇=ll%8V&;JY[>'f޸Ad9]~)̄D- @i8M!fbiS8 |{֋ϭ2=jfKڣ _`t`A0P*8yF=${k7Be~8*^EO^ȇn7x}0KES ) y::1CX PJX&c Z8}t2|Xu@{(,tWfW5.I#V |ME)29λ Z=cq8 ؠQ ppO%N>tR$?6p:|933Ӓt鬋Ac[=hRWh~I3yS@6 FP.ҹCa0E 찼@ -qAԟa+\#uЏ\+Vp; '`=O'$tRۊ'dKж;$BV"]V^[b?NN(Tnz9X8 bI/ Əٰ\eruh(^Ȁ!  Gi-" 7e> /yɏTuɏT{ q`sF2NV23@X0#mC6H:+(8>E$<#UF9]/fK||27e %5z4^1sFP͙4wOŊh-B4ݜ e  C;lβneW9^&ݭ uv"XI̓2]y@Ne7)ȏΫܺ&a]кPUE0be-G]V~+c$/K VLPjql,x#a6:wkxL_ZL.t4,+{!`ex3dglY E,Z;ˠ$8\䒶:RmIqӥ*>n'"{9vGt7$CYZSE/lpR/5eƜymqO š!J aNaeݖ8-T;fuxVuqZܲ+ Ěv,n>,PpQJ ޏ0<iBPTߛ ^Qˇ$k6(S`Xe,!ܻ<{cBNM41h,qQ8AᚒCz6S:/i"NJW&X̦X \7S`dOAn)貔Ou dN)J tR(xͩ c L(Vhp1cOCnpi4j쵧z"yrW.a#hlF@♲.FЬyQ 8hAs b nx E\{c/M&߹ ,{chIZ0PESrɿC2.uRe] 0x6%!Hnũ rYEO_?#Jz 8Cq6o;dZ|2hz,@d`GbM>ÉőR%k̉0UxeQha- he1RL*:r[W?gc̽-vѕʾEpje6I1VʜBiI{ t;ԇZp]2E~S7 5wNdL/'񰄧 v7OYD aiAOZ:M|uRSdiNwF 7[[) Z чczMtM 2?ED02yuZp|pzsigH[NJx1ZE)۔MBMbą2` ܢVYEBY%:NɞOSާ3Th 3e@ J"n?9)4ij*ZM}D?[2uPYQg>yZ?Vӝ1ˌ%%^3-Z_^¹X# B&<qqgW:p}Qxinyj5]q=ɶg_ iGH \n"LZ61^>_cEa(j`6mh6!|O{G|Qlh[a<5M5/)XL(t\!bh_^ Y%CuP%:R轇e{2ךÄԹp7r1ARs!q ʐ:V9ażA"_f~Ay6 8v8lA΋mS.s%dw}^ѩ01q05/Ri<%%^ǩM0,a*/[mԘ/#5R(+|t9objc(Y Y]Y 1դ6W|F"faZ%F/0*[!-]0YE^khMr@g$5˶ U~$ &(g|PR/*i{9`;X$"{Ow)[U5Y.cg?8 }@> yT;goBph(] Vl.dYM]h~ py[^DhthP+j.;d]cUg{Y =3mZw{k0{ݕ`@`UvWU=\c6s׺K;ld#vc|3%&z5YbJػdwٓ͢ͲTζܙ& F|BNEIo X"\2g*rWEȌM:5 *ɪ;]?W)YK;d,J7[(l];DYR4!0և<}%Kf0m]zN[9k9j_F  t=ts{Z,/-"};-ꫨdHxRE U+( aȮ-1TMڲ^$)T?#EYfT+TUs\@̢'X40_Xe\.\Q4 2i}11BSKO>#]ԇON!ڍO~6J}D~[ WSQ7w~W|wkRq̀SveC^eSӟ*BBp K:SUgQ7L);uܮӟQ kϧ*]?Uo*;~D/) E〸*W)wh):eՉ2}v^k]njw޽&GNIA(HG)G7bE{X{E;馹٠kyzy>-=cOqx!:fB|UB%yy=]m_pUAnp{2a]0UvCUJtGF?vٿ(vs=+AˮeMzs7hi(B~_q@GvSzsz}I dRMN`Lc v?N[rP&g"8_bΡzXL<3BY-6+zPz]+T O@oyzێm`]-<=9^Sh&6Z˵?7V&Nߧ"ղUE]&5/J2׆2oU*'e;G,#x$DC}ɃdBQ\+\/ǹU)Ep Pj;eJR8" @:`}ݠ^3c r3I\ H/oo)H*7|[U]W.~b|tY]xUܝ:;l)S3 Jא,_9KNrc,^;s}DE)8|r}ɘcQVb3#ܿ4mOŻb*W~zR|A-.QGMGse +B1Tg;*;c-7p`wo;0y:t%yLd-n(wVFʖq3a׵o x+P_ љ{9(=+:ܕ3~J b`+Cze F.r_m&2? p@ji1]Z|Y{4#׸lQׁ;X=#N[V@~ V/Og)/Iy.t^wF%u"b: b+iEaE>"~+_UbI- F%hd}wm׭j^.Yƞzd=~'Rw,F%]I>6G zA|=+_FY20bG4GBUjwMá[=Bp#%s&"2#0 `xY{1f@sr=u5K{S]lY98"^Q'r0 fMGvU F54!Ue]Oow_5SF87XsYta.jN)F++M>)BC~Onvp`G3Dc{O6,8QE<s 0e Hc_JGN|$%orfV.4"PѮHŃ0 f C=}fۓ@s8?h*Q,MW~*&N.'뺲%حjԍAţXq2]#dX\]t}w kD3~BA/.Y|w^ c řyq8L-9|t?IUVtRY`M=b<-B,uG(69޲}6qv~63/n4AkX皢QbJ ͹(ofpMsZb8Qլw](Q?̄j+(m:⯧r Л!:zTp|tƢ rQevjl%5sY%JC7eׯ:3%,+y>+)&NƠ `Y]w1zz+ U Ò^r(sw7=BF6k%Ȑp |ԸF<ÎW FzC|=0`~pw_?/K%"i g4X>,i~o~X%E_?}ޞw[_v# sW(?U\7w?_,L97B9š1F]! 3GW814 xxZ)^gx=Ef<)\>U?RYQs3/I+ef@) XɲNi*@?wC}\K7+/>S@W9XN13.WXIdo ߅ңjgd7pٽ5@?zb^) v5`MQ|:[lXÙ]P+\ŗ}S&Cb:5'K_2.&b^^z5E1GGc1!}fY2`ۋ]\(X:,3x`bHo_*oڧ0r+L 6E~F^QM٘¬\:cg"N'FuMw6}9"j m#!F[aQ#ImhMBm`ia4`P+ {Y1^zapV}@Z BϷ_?@Ps H* SiG}s4ɴcWqf yIǣ|g{<6T/DfQ/л\DdT׺̇!Ԃ?&VW8WTw}m*T?Č%շX 7>cf Pm0jSu['6TpA77҆؜Kp(# Q0^0֠teNǹ`F 59@9yJm*xN~)U`ių9ݓ]zL!H]B]EURײJaEM0t-+L9Uޡ^q6*5Qry yh@x%yq$Kj ڝ xjѐut^>02K.Rj/`7V>MLla*߇#7) [/O8] \?Klgu 350Ql! r ]Z}>O ~.e*;RljKfh?ƥG3l8T'a,Zs %$O }Ds"^#y٘ R]e!e9mv/b8a)f[x}F8 U'wԂ݀{_?y]j|Eze~ml67t]mvv?"׶pxD|9gE7(%!6/+3w<2-;LG0BRχ/??Xcۺ?Cs rX_۝ v .mbۼ~c'M.O|k]6p&pK?:,r,CRn=6ps|+) 8n̽ Www^ߓ>'=5>\KAKNJuE'Ю7FyhMOuKx! X~`-kˬ-vLy z $?Ͳm7m>Xu7}}bx^77s JZnl#R/8er˅#0+nNu5@kuzMLٟSzqx**i֑]a90?YwU3xxq0B}ݬ$) 7t`f?80btpNLI 9=#~0;k?߶px`)uЦQ_^Tйx:ܕ9%1} MX=Gi m& +v)SFd&5bU? UG8f8U'8)A0`_wB@nx cdY{#3tgb[WNp_Z#+'GGL ?e `F2!SU }" oX1OJV>ðoc`̤G%"siw|s1`L`A(~dj\[VEtdf&TPt.D`HTW`vv9^أ¥t8JkjNβ&UώA0l=)K?]lZ+Z{wL-+TU`JL}$MbtP Ɋ/gk +Sa>G=d4|>n^wPhX}6f7)" A%f DMc\Y!j[U`a!` ̙sbaFg/=QWӞ} S3<GL]r5)RKIOprM|:Μc 81De(\v:g7`chHx\f.L{YCUP05Rgu]+D q; "=Z<1DUΕެwo^ܵl. d Weӌ}Ʒ7!Zsk[ _M6\ljD'h}E4[1_dj.}l1gl 1&|\r7AޟpmI@ð$A'"FɯFmnKna5z1Z.;)*(t(nQ:ֽ =baL~05#jaZGv F)4A'2xl}gPDmP~O#v3wSY[#lE%jhٝ]w/A#jJC[nZHlfNXlt66ڥ(vޒ?E%,[:@'°=^PPdNn#ɂ?&D`A9\/> }1%J7%ÒyT c8U_NT7sOL4F :F_¶ A/&+/D5h.[P@֠jAYTC2ҠozhPTJK!Ktk :G B0ҠQI~DA]ǻEeAYSKzԠhP~^?4h.xD Ѡ:b5hW &SKz ݢf 0JTn 1֠GIeMΥAri\77$ ?b{4(A;ZY4Ҡ39S0L|JZFpSOu#^*pZJk"9;B@*L|Ʉ$٣ ʧj$LenG]@H87I2ǥQDqp VNVMdK!\cQ)ۂ$FQ2OnUɺ# jAcXon_e$h'}a+8w*pS5Nk[xa)e^K>G5q@WϪ[Ꮗ2(i'J7l1o |cd >H }lB0D.D][Gmj0?قfK/Q L'/] 3_B;av $ Z!Y>'")nT<C|܆R !ҽƉb+$p*P)|UvR3i;sm$b'J^}N p$щfC0Ps|C{ kz0=8I' }ќz5n^= ~,KV͡vO0R>''SR(F]!^?b\->\Y0%໋PL"à 1 ] ?+¨hJ9K1&-AE2h^{ iQ ;@<'\?acw$0\.H[)s";R.=脶a8/D#xg,)cy2.~R2‰&?wGnHW֍õZlmƼ/wW뽻^ɾ*0f' wh 2ܦVh[Bu9|uwB>NƸ2U='9d\=8K$>2"S$F1)ށXq;Suv6yqr%G͟~I0+ǿ#ƹNjO6͌ EReSNpAm -ΓU۸@nȇz!8A~TUWd~)GH;s;[Z!Pr dj6<1}>ܲ03\C5{5QSbQ8圀SH:A߲ɦGqئsfyP_zs@$1'eEN]{8^%|d>'߃V9У9b3}tmȜ,'AqS4? P>Rӷ?Rp|ٻ.u\^w也MtjcpHE>e?K3u爚2K;|lg]͏QlKS'AZ/d$U'% w$n9E=4꣍|Q釯HwW8L5FuN15C{ꏏӏ#$(J:kdF'g@/>jC3QOE2`B 4?ЋFɔo_O{:v ⁺sScYp@y*ycũ7bNʳm\9`#hI>(,|$Zًk=Ӑ[[A3SN1ҕ(R||/SVN[}Y).: p0ſM`dy9 BY*p8SCg{ޘfY0]Mtc|ѭxb) V6[-NUh`idXjJU|g,fuZK*Gѭ=w*j]_5&ci3 /]֛8}F5Erљy3X+d.CEOE,ZV\Uf.t`h֡7l!pk|> ݽ3ގ)Vpmo\dLԾo5?VK!vrP +4߳Bd>ly"hWZ5qprt:1&J rnLkw|"bGh%8#ݷeCnxdK27,:z? O^ֺz}&/joׅ`1 >l =J@8r?g{F߁h>r|?0ctVaJ&,.r.ҮϦ4]9˛/6_x D<]QeM(2$C1Đ+utXX6{=sҜBSKmѕ/yMεKAm>!6*{xƥ*79w% lݼ=t.ݮQaf`gfzh8K/}̔Yaҏ /skB0G;gp2z=9 HU^MZrXV"L/Yz4mW/+ZCekd \J}:|@#BgVKD5$`@bV>UK῵φN0[+' fssdb@4_b}ZY`zs"}q2 "إ^@B=O,I'7 P8efe[,4~0{#z0ԼnEfqpI>=>8Wl.b4/^}|̫2h9^KO>vx,9[ُç$t&'>]5n A%k3d0P6@$HV8Qـ7R)Of꼆"{Nc$z5n61mW}P@߱?4V6{vsZgd`⑸#AHLXx!g`܉/ ܣoEޥAʌ븛u؅,5:s.D`&=Bxs?.7‚TkU4Facݠo$,"ZEyJcT[4X"1b  ">bBetm#p] x8ъF_4z h}ՙ@Tޡ>WFG{LO&RO'Nf9 SH)MYcِo3do8\ tBA߫}iN빁K9 N:bVB<Z3;ݵ / ޟhqƠFhvx#Nd 4 фCك^{Cpp7~'qL-EARt!Sg2>??yz tImjf,ƿ0hQԇp#"oh ̋F, ? ZCAyӳzXU,o1SҶ;% dWM=SшЫ8hɲ|G![e;*|})U5^)|b|l*ދg P?srq㚞 rH5=YfǮ{'&`d l^CZҳV0>%Cê*m|wZͻNs_O+$Fذ%ȳZ`bQg}dАLvkYu+3zNn{df_Js% l{exGlxi_2 8jd e^ 5/:mpr`w !k~DCgp8f]ssxʜ] P(q%5^ t[}wO.s>S=A¤eWCqLs+t`4 1g%A3*s?ZzI);q?+CD]a}vY.=ΩXN4j!`E\Ocn!HU M/#t4xڽ]\rT)LyʞC 4nq'Ǥۏǣ)ujQA?;A|6U^R~ AKP}z}rjpi4jszzx~sR {A5LG^}x˶!uqʛп <J >r#~mUZ.GSK}#lȳQF0Dc#wu;/=G84a:ͤ4'nY֦VH Y +t1a5d1cunnR>aͯ;+AO!ag-z7E?=Gį֯PS],fc͈ p28*i()Dնxg1DQ0ѧŧMOkGVYTݒ r5':\c3-)|)7_čkҔGC&r\ekWի$N8!${>kLO #t2p)uL W4Ҕcl~ja6w7,;W8G7ywȌSD0sruEĤY6q_!zR}.+Shُ̺s49ܒ\/YnfTs~g'o&(}nQ"GOD֣Q1K?w|9:Nx"$T{|u?.AT6*Y( ̤å&eYv&)QVkx_ .>Y1PӚ/ (`/89aCgHAp_ O@ tӕ<6Ãͫ8dls7|ֳ9_t_3I'?0#G@~Ш~Y:\"lZ=Ykz!3lM6GgIҎG ٬$-(* Rqz9t_'е/=tZCY )M>_K/ xOEB}߱r)Q4:>(*ku~'KRZL sB8w9Xj]hUMX!:>823gKC=`{qnj&PJnwM0^.:{e@ϘtO獃fNRsRD&0rn [/'׵ 4t_uyLp'4[0?zK\}-['UaF f`[p2A]'a#k|s5Cl޼󦯳 &$#Y* B<ڒI;!~DS9 1tz%& -<*z ΆۜSA/6>|0#Hmfz˳Ĉ`FJxmDy[^; zLJ%b𬝻O=I_ur^H՞tY!,ٵ:]Ŭ<ÓA?߱ޅ54uα(i_OjSpO?/]M#ygh7n '"HWb^F۟ gI|=­eoQUlHݳnIg/$wL9w@G[|^JwΣ y9|?zՉj\m+dO:n|3m/*,%@zNg"݃a:SN1bJJ㷐ߕ}Ҡ'myqv2g.[0TCt6^u Jܚg-r8fcwlfA C{Uxmcɩ}$Eilp]и*<y%$オ V~UJ/BћP C_; \٘;n{4=GCcK2R.zܭg[wT(E+OvЈƗ- 6 B/* kmͮ78U.㭨U=H16=,Ѻ;SH=`5<'&,:))@dR4Du~Z,8Z%p0hJ <7(sX01PK-Uj8-YND6;e?EN("^w,Kw#:]+]LqW+hsU]fU ρl@( .i܌[XAt%H!aͨxD,%k.Tz 倅QeE1L" I^&~~L:J)lSmvt9w\C&:i# 9Њ @!496U"o¼,G7sԨJ OƻQTx~kuDPSl8,S٪19AN_e"`c$%:PbLô xח$J$ 3]N΃'§_=ƚBhOfspt b7-4K^^Ykz#g +U`[ qdtt ^ Y&9=_/Xb/^fEhQ^w4p+ ^-q$ΜR0AN~#n!HI?6wUw-+x~SĉίL:Kg)ñ`AayqNZڃDiZ3z?ԺXor%~J:7 F6#bD:MNM#ݜ~wqƙvTY  Fr6sW έ_׹Ȑy&r4.NDUFWz>,ǐ/bn$|*J<+m$S'Y`SѴaw$j{塥u'80 ]ɢЏ<[̵Ӎ!jۓەnxdӧt!x -#pN&'qy=)x` S7بZОaq.RC'K)j) 'Q6e0.k`k: ؘe{ݪ}?nMua!O}Ќ|za}:lu @!Ͽ!F{-U.,MY Jyg}ņbQf kuЅ ۬1../e"%UĐQ/ rSgp|;6^8p S]TdY}l%FW; |'j!3ٛ.һBy0TkE}Q PpG_<^%=֋Fk MgV^qU\"<Ӗeboaz\a\ܘ_?XzGߖ7DxZ[=} KWtrh٧fnq/?5.o=ˈM*C E[6NZ.\a?-ވЉ5m ঢ়LhG[X]*L(Ӎwƕ8Wa0yro+i.!_G *yP1v=؍u "ٶc;i>Md&5n"Es2t3€PylaK_ѧ{ꐇ#gVmfQuNzTa;],*|^37s5tqw]Cя1`YFzܜWz@,#<_vN%>JN[3jݗy!銸pvみIz$9491f8m& Χwp$bg%(^vpcr|6Fo<)zG}㵃U=#zxۊ\z/!K] $䢳`{!vw,SeP̯"%Nyr̬1C pi!7!|uf.`e/}OX\9ޟ7_Diib}db(vBJеTp DÛc45 'ös||Řy=,]5wmե4L&ɻlKKxEvU_{,\g&BalWAĸChh_ރ!YpA y_ϡ-jmm} wXE*-IJ7«2Fx+UFPX(>>Ϥj|h`~n]5Мղr([ca)LMkւpyckՐHW_߀1 Tؽ1jVr%V.\*SsŦa )\MA0&xE"ކn/~8,hIyz`)~H2|F#3(t7ea:.EBÙo 6`̦&" ڿBU URn=TF2F ۪3f8 a B:AU6WYty _ed`XT3J:ˉ.#wѣC}Vx*{|J*D$$à,{:TIS3kV=.h-5-^WNٯ{-w VVOCha,K"++N b089:CYC鶈CNca&FmdRFzl홿܏,ܷ9fNFxk>{w CWQ7[ͫCʣ܏K驧~$XzܺTk3H93ÒM`  O8_x" w!ן''y݅l; _=8j\Uus+(9ut~8͸e 7F=ςE-g$K%?ؿP]~W M2a.`*JșKm@(zqfEκp=ʿTf#ά[6PF%˜&)Z*V ru{SeYE#Sw(8o`^AʀcY3.&{[Hʷ#738d%U-ĭ3qlᾹT7 Lp~gsu0 8b ?kӳcT禐2(VkQx.I-Qqz,(eylޯIsW _[ '3PXOd~eUs3$jL}MBD\ʮ&%IN^i冥8QhO#Nϰ `5"Zea#!ETGl1B%+i5mbF#6{*񹞀fY!BXʭaC=0rVJŭ[U)SF(#~W7RԪ$ϩ5?)SwmӦL'J伶]Y, Y[V )բǘ2(sPK v$ޱ"3H,aI|r9M @[!ȓ'sd铠n_ԬPԤ1CXJJ5͚A{N!w?A`fT/ cuO_'fR] M`z\FʮLC֧T؟YVArYCL3ChU.YJ-x$W\whu !{ťXXEi sݎ{GWBUs%|st1\9,9 bgwEЪRy\xїڪt, {V3ۻ=&Vj~ȗCQ:E̩B1 n|駡_+Gz85] rAwme[E bvflwCܶ Xtvbm#{k?mwd*eo>mD'h`mheM*r oe$M&tGyk[|Btl_{2)5щ&a[si>?-!#P2.}9}oRZ9zs<9k`{]`}O,:b4F:u6 it0$rǰ2uxEĞH@^ͮy*eL'bEhX୸oW/rgj)pt:4 \E9(3xYrt[ Du{!r]|=XZXn'3N#vu$ 9|zMcɱ4`6-͙G|ho{0q9I— +N ($hy$9XcrTW(W! L_!{SJy'&)T㒻=4akf9vl&-]xɳ ؔu};xvCu-q-kgJ5Ц$\G36 5c-oGG)*Yv&^([s᧶V\i[!o xQieO%ԍLa0"%/bf«&|޽ih)o6/Uyt#Wl;>% Qk ZU022/e,ֻj sY߅:Y>\r®9j1n.bIk"C##cm?229bz( yۿ"]/iSPٳdYS ~/nQ0J@q"`6s}Sdz7boԺW4Ş|(oj㨂\SSH MJg8,@`(MAIIv!9/ȲL*bEj|wu$WGvqeX><(@]O_Uvb0u6pfPi'le/HaIEgGQkSZ~=-%gsW #j! KGi([# SiG sUDyЎ(a q(HʞR El(ڎ_g9LAwؾ](?(eWoªtbKT#(C}.7PS<ArFJqÃUuRͼU>~"la6nyN/^:}FuTSy eص7B]v5p٦n׎}ރk6_?\7oqS.[==57c/j?GTc㎰Su%u((khI.>{<`Q6^yx Bp  QЋ9w z:OټgxyܛHQmca9u|K swӽ|QEak]xzmdu n zrM"v)3ֈuC'j ]ɍHxȥݏ]_8KG!hmcKGҵ`[SڄKGJ Kґ21ZqݹC59KG4#hf, iพN Bk-7q.{ <.͊kjfl~as9"wR! 16Lx KLߝ ΘUm]ںD;[{[moiq!۝5p#0G6C̿$ 7+q) MAFja& 6haRDe9a,CK^b$Q9NnO/5Bs4O,&-~Aø+㑱UH⺩ 4jjm6+]nH<">*V <ɰsۣ!7EΠDAJf1;QKa]'z%2ȴRHDl gn0++ʟ̇fEs+ʥDpcQ뜁l2AYqUMҿP`' $ΠS!n(Ո%uĿ"J . 2A߼rUfuH\a`nϤbz{4TvW 1H TWh#?"']e-g%Э-{Cj[ZתxSpO g)b(tO)Q=ߍnmt=9rLiZ\p_5tiS}7 Khm<͗l8Ia oxU}*̏9ytlh"%GLgt~CMATj;grӊŕ .?ӅcԬ|yoʴ^cJq'E)G9%1=RĨLE 3ΰ> D2xA} /\z:A NwWɤQM`[W +,fnEFYhS6$!tzU03VFKwء~p5(+ hX_%RVrN#F78h{-.+&^3X\i\dw+'jhJh544+ #F^An [zXIW_pveitGh`@[0XڒK믳'OքWQmAM).q[Wѕ!ϻbQvo~aS#ҕlf֠2+뫌Dot4uT~ xG,f`Qw9]*%C5(Iߍm'1V](sʳǐ倨 +by#o]Qx>V_ <}OiZVwCGU7]񐞫 ިm!fz$U.n#췲8=>$Ĉe18<IRyFWy-̨sDGqExC=EŹ(bQ݋k{69m]#>䰼gKmZAll(hN۹s^_Ўb36uS'K`hG}{=I9Mmsar" %d@|Ę#-yEʇz1 7!EHf iAIst @5}xC*W0n鑞+MƑsF=e S{ܸyӅפG ZL#ܰV:ꉗ ^VPp@Ţ(SɣTAWYnGQxtJw"LRZ%#ؾSF+A21hس6`xExK!DbUƨ WCl ̾pzDUH7piXh 0^ҡxOze]+n96^/_a) +PY#C@|4S(\ؔJu"|XPVE!(S-tCO0Lеaqpz}$T=+`"茸SiG(W^`5<pM4GXeTL*.Iߢ˱, ͐06߹y'# !7D.7UA#X^|J}Zyw7QGꓒp!1;HW ®$T%OY M٢iYM*2JΆZ=*cY1OUbmf5QAׇ4ɶ.urB*b+rfmRf6y|`mC W8F-U{F616m-*i C[L ^'G\M: Y~<#gP5IjBa.9t9{]r|o (ddẒkUR;G25 jTՒӪWr|wU 4B *bE{)zcL}W7>+uƢhlHZiB@=}$[- Z#:CܒR=#Đ9s gҞ'R5ŽyXuW ᱺ<۩V 4c^iiʫSSVyɢjƭe-5 d+Tqj}yXyB]e {%-aΘtW]aLJAk&bW2!ef(r'm%yWyu:BQO({gb#Ҭ&EyNn>*Oe|jTawD54wH$$l5 xWYIGr DAGDC:RӠ*ҕ74`&}VBrCD. b BHu(X-"@aTEa95+Ur72Wy I1>7nZjDU`u.gӕUm]63Ot־*sK?~^ !L>wlqgĵw&!áJ3Uop D%pV.'nkAjr+>uGv2G坷>q"6?{؃]~x.7P*<Û JmZP#5l *1C Be11-$D5,iԏ:*TC3?ew Xgf&{F͓@̢*B i)ov)FQƇU)MNFk4`:fjm{?jE z4xNmcu]nr](?S^W*1AU}8E|ȱ&hR_t>74Z%t<}5-x,N-pP]1m_Z9r\FcȎr ?T׶(Ve#ѽ lJ跮X.AaJaF6P ώd 8AWx8!{qZ*9]cT +!l'm:ʨaDEe75 J57h_uj2x6 bLg"[cؘ@9w'Vx ^ NܣKPR5Q)V}dbYcXI&/r ⹕;r4ŷPX+Vx~S%CAr+(AMuXΈ#VsGuoCQ񙽝Z mlO.znR',aXt]K͂JcUy-XYIYPՉieNw[Z\Ә"7cp):%CxqOv ~tWEE;*ݵ"< `\O Z:miy6&QiO)URZޝBԲNOL_NjE*Qp|̯Kjsmhڑ #J`L ח9f0,$[t8-Y#:Itf_2<nYUΫyGԆZX0(OZ݈C'L5,m5"O ɿ2fuJP:(6A1Ptf G =%lzE8BS3[#= ةةvK ڗ(G(8h3T*V&uTe[R-8z!g=le߿ 9z!=l6oo'^1;/(c{6@nwIՔB=Ҟ=~ 99AUbLj*k:FxB[AiY>s0F<<(W`i0ݙ\R=h0B @૨lqCqu;mǗAsnN6M۳<1#a0s/-ky7i{`nԈb[cP =`wz V $jQ(EjuAsrPtKLJ-*>4g-ꊄW/(1K憐SuUdHdZl0~\恧?u푔ONm9;_E'/ý5FX\*}P'iI,H?n0oE1XS ðF+N<A"߽ \l뛀U~܇#AiTv`;viuWdldAv4T5l2PQyP;Viqy}ԑ`ӄ Q?] ($uS `#yELL()jFtKkۈD%Ha[tr hstnpgh|@~OvF0_9u (JDOLl]Zn*ZuҍS/x9mmq{"|1A4?Kz`4j߱zWz%HWV׃loRʊ땠D_jz-]ڳ)V]C"F7Kt xϺk} uIlݥH;n8PP:@xZLoRX-x#W~`Ed8 x,t6^y2@w=vT] z߾YܺEH{JYf{`u\Ug|꺉W Dmw%'7I, 3 U ^'ʹ1;~ã/#C. 曵Kj,pCNuQI6 wW/؋W{-C ·@t`P0~/xF+Dp=bM7X,h 5p%saB.L/ _+ {p>=֎ȏ0t9w prSA8'2#|DP'8 ~ " ?OAk`Sw|3kŁeN0͈̬hdhqLCG6hjկ{UˀC[Sj`\/O )0I.'Z>RJB%җBN>}%54 CƻNS0 JX "Qik.E4¼8J(V=- ̈opR< ijSB{ 1lhҏr٠'{z. z^ %Fh$OA>/a{j1$2-f΁XJH8uTD}ME$|d/h]9L#R4&,~Q}p0˗F'Cyv8ao`&g( kDc$1q _\ ]B 9;_'׻?X4fcTB/XRXklH7͘C[4pQ<}M%G%!YӀF{c$'!,.\Y֨R۞(RP*݊5>/#tVsP.iT`W$ *2S-@3hF#Ns@y?Ft!`@ptP1t); Fk>U6ɄoRT^b1? x}&[E&/TQyH\q_+ ?- 4ݎ˃חޔNdb馉J\Et(Qv>uj=sTC[A6Idy;+rU4}x@"wr4qxVzج}…[l6(;ke9 L-nV"r1`*HtBǴJe7bUQ f2ctZZILY\l23-CuOc;8xF֮*Jslp,ﲅNVS%&ߡoyIKAk \9:*m)!~ݪGꩤX_?'CS>p^0.J)]g־6Ә?r*r?j(:ɳ_rzۺVKb>o^B(7\잪Sm _Y _'tMQOUn-x}S+b)|Rt`KSҥ{To`+h:˯惘G*+<(Rk?Jďx2N^FqG曦iщ'tUN$'ǫÖn(r%mb$+UCڼԔ uWmo_5[mPkSxݯpK%({zH>gI_ѳLNPxpBذjU/8$ղ_?rݔƭ?;T@ 4n:yr|.N=Uܷ{&6]H<ݤC n{ u([]M5I0Gk9x%wfxfyx"s?piO#aIciiHMR[v'{6n[pp; srLj?Ϥn =m3 .'UvjeeI,ųK۽!u/}(NTnFoW?+j|gT&Hb(T/{7޸Z*1kH+5 O)O7i|r(3\&5ھ;@~Lk=̑i$3<̏G +v뺛AY]Z%/UeU nw-}A1$'jW?^d۶:;E}U_ Q?Qh_j_k l>DOPx#lfR6+=Qki~n0Ay)RY҂҆`\M`{/uAw9viiL,^]V!k.GC-G]/zBA-'C~ Xt8divj) fc83P'pr=D<2ET!GȿlҘ4#R\X+-Tzv(Πpw f}TOlDEK(XuwH> mi#R?H5ס UvlbZA}~c |s_NgB=P,@(Pe[sԽtrqb(f\}tSxujɣlM| v$N[Hf0>\0/N@#9*'5,_?r`3kTAaV GBN 0OI_{H1 ]TAy VɿSz׼ M:oFy$y{X^}nn!xuM3j?^E3,660$x4j$}t9԰M`7"^?khwC^?[b⽱y{l杖H{W7-QPݳ*Qڋ>.>없[spDzʞv sz}H6֊flIs31ȇraǁ+ b;P^c7.'a26jp Rدӌ̽6!p J,;J%"D9{!w)j->rLhF,"L+q q0rR ȷ(Iqc#4.[a+j^G5ki5&#e90N:d朞n9/W[^lf!= ,ۂ hϼGŦ}H U،Q^9!=\J"nwPx̀ lZ s,"bWX0ͥ͡߃iՀYp*ovAFݔk9t4!]r @g}V)KhZ8HLbĦWh3#L tKgB-U,4-8m#$$'5χ|X'*꫘)gFDEQkF5^Y8#Vڧ<ͭ׌`+ጀ ++o FU=xm*6ָq qHO<ĻE#ym]ưeR(v?GL?[۟L;U *LU}bko9Y U%8NME*ge/[pa{; AZ "g'LIL$XzE0aЁF(OwŤz*x)D+V@{6L^i@+ӹf׾*.k͊sT7 Ԇi3-)UM(B,ڇ/G|o}^W9Q.D{adcﻔw|veu5t"4 èw+)Hkl4N<H1m)œXrj*=0lW8Xe-a?`P)&C{vdWBѝZzJPM56Coq`vgtT} vHk`)׏7ĠwWJ8k MRÖ4M3 {i0nWe Piz@vxgSaȭG Ā(n)q^'taXBPv q/)B#h.~O*a{V( qWDo_N~Ha+4lj֌Pxlu7Pt h WǧX;^+ G1(4>Х)ԍGXk`$*bNrqr I5]L08Ɲ8 lSS7!ah]1#B<9ڍky-4iHT HצKu(QiִrUR"헪n{P' k%0HN'PM|*>TfS x;@u8ܟދs3Z`Ռ~X^W]Ak%8b`Xs@6O" ^#TOψDǚ)o0KVk687hQP&A;63X0jj@45Rp+j2r $Ƭt|D!.cQvM-3"r`Wh'Q&,!iJksOā)Z;* qCjQT~C u_.b}CE*]-/sje 8]!O'$C+T3ٖX k%A([53A@82%g5bƕBH_VjuNxKgtSy$PV$j| kAeƁ۰||J;8u,Zר&VxF ۷hfuҦQs]2yPa/,Fhok MKԇgSs & ˴EYήl,AxzQ2 m/ĬsI%+C픆 cll6f!Z(L&ZMɥ(%@(.ҡQrNjo./aYdh@QMTCSWn+4#TcV#LMRv֥tq?1Ha/A]қ%Ԕ NJ)][HN}LF vMV) ?\j=_(Y2~'yhwUҨa%`uUWnfdu.ݥoDpB簾.tWll F,+nӔ)7msLykb;VRHLm r&Dڰg_Wm7r4HC/2 ~[ZLJUUF;r dUEgUeK'P1Ί-t!m8->M#j#nݿBc|z`S|wMz RQ.}4N˃B205%}$QՋ&w^9Lqck /Zi ´.'AsqBH\.Ѭ?2zM_} &4#2n!80ʂtpo 9A}Kkz\a * $(7naWI1[XɯB(ղzdv7 Z'y Ş{xWMiRnDU^s!Cn7F iSFDՕ]fVmJ5bRLSKkts[޸6#3Th׵eHpCPyB/.]Ψ[5tnU.F|%T(CMյJZZ\{8͍VD,}L^K\`CCu=qOKOj+CLɥY,R)K=#ʰp7 aˣH́Q×QPf%M: P n{(Ug@c(CUBRGi+4!k8:-25CiAԓ;&/f]g$$M8JAiCiTU[|r\c9{Ɨ~"g( 3e3nLL[|; `[[Q0LK:t%]L}>1Sȸhshg2TIM$+S\L|CWv[V=o3S HnwDje%U<+F>'LkOS`S'viQ [a+EmLf[EkEe" :dYUP|$bzN~΂^@? Dhucd; LP/ц)TT0G/r mozK5,H'D~ks=0bЏWv̢_2C.ی\[A,].SGtcť:I.^vGΏ bmVI% \jd_GH΅4rS,hqrt]*j% i\fh?>vlc렽tW[EưaWPX/:7ez7A#v nmU>b37k]c/.f{i )5ǁ[lYQrAmzpH {z@pPżޔ4E[CK)$Ұ n$>5 2^)t2]8RxSqQ5^["o bhq;vQ!!A x:hi DD ED2GpPBJT})u&3zջA?wȗ|DUx%MGCވntAJ W>2&zГ7P@HuL:w tb*SX+VԎR܍bDQG2y#95N,GP?Z y!48hֳ~{9lT> Vl8ݺA:v;Bg==8)KDjb{OGcL@OWCOdP)hNzt/<u&xMQ/-o) .J SX&$nc7N2&\cͣ4AO<36!Ŝ뒮d,NL^:E^`9i-1cͳަb'E,UX'>͠7]1Bq3Cu(OAJuO;,"IsEl (Tɕ ⱙ(Pq'`Z_ʒ‹bs8CY,i1Oڜl62EPS~lȅ'#,aL#~*7K sf GC3(VzcLA>A0痉 spa:4K//[ SW?x-}]~0 nA8]!#T4W$$pIHşMWsfhʓjI8&oC,-H0L=^x3rn\BMWNAK'%G$B^Og_@Dު'EqZ<:)IR3U{Hߌlì 6lIR6l;i5ʣ3ڝAj 2!N);"PZ |l+4u7ڑ%EDH-@2,/\;Cٖev>Q833=ҁ8Rβ9b%*aDPZB~'ӈ 8huSAݻ"QaWZ`K(vmrOHlvi:Q -D5~E)9I`9{pr"ɜ&+n"dV?vd4{hg~:EfD)h^(bt+Yu)tL+ͮUR*r!Ġ|vɩU QKS Q揎JR:{"TJmXA-R-hΙ5gf1w~!ԝ",hI2!yHl)&,7񅓺au~ߐՕhJk d>=³msp`@L!$k@Lߣb6!E/g;˰jюihYEt,@F; rCu6{n6T+]] :RF3gD ~}tH|朗R6?ZD[_Ɉy{,T l1vk*y|@2-&:`Ɉ̔gf-INR^' ԏX"O}@jzGul甂žV1AɌ ]h` ^]Fi<zBY 8]}7 57'R`y*HkW2!8!G&YJ9sM'nOQoOGG3o>>:9*  i%lZ 6Un)%0O)5r9' /tv ݀Wؐ嬿m5mWR]l@A'a,$=vTZ3jf_DTaeN/ $,"Q$: -Y%XGKLx%L|h$λ%[sC#4&]^lHYqEXT7&x=I_'Ovi3!^,(r`YvH4W&.Y{@g#$>V"*Em-D̓CU\&Ж0]T /%JDI 3D"'?]X6`j &Ny3^8 \20SA8RAO9K(m-"lf,"2c!g. Nv Z/d%aZ?4 U'3TLO^]tG \U/W }W>U@㰻P+G9%d{앤{b'FFOkލPW"ⱌIC,&ȿ^% 2nm)K{Y~qf,}l!ho4n`.m[OZÀWCX x{ʐ٣x.w8l[)x rtC5u4ÿ^'1ƻ[ܐ[EXcXYw@7>JvpEHEY5v#)g@jUf@V]/#Lʬ%i x mbxڈQmbyMCL آ6#c"yNo;ևPq<{*R7*u=:Ao%!~?oNXC7,P+arیY2qf;cO s=3сYihHiqhoϫ>ʵǞVgCx 5;NHݑ>oK t#Jec( vO !/aHS!! YdwgGsRZsNٝWaW*j=ugO`^^c(#"2/dS]~~]JLoAkiqlCrmMv=:jK8NH ]ܛ4X_ gG9:NWqF[$O"K H|s;@ le&RP\k؁+Bo̷݀!V?3#'?2E/JRa@Wѓhog`=!xETA'8j}o_(9 qJuPșz_B3icɛ hu(g+Sz ȼLܯ zcQorcUeB)V4-WpoFJ<2eG'9$؆-Q.|&CZ@72>[ v%h L eC8WLZLFp+@hYm؊d/RjPÅTj|d,4>"O+ eY b]̰ ~7DA. Q*vA偈^%SI֐7 kS>vEH"LfG[OaL̖cSQ Kƥ_bkAs k@xezD|_o\=F HerThg-UYNWϬƳ-Mr)a xd秹0 G7{p243*x0'IDmgq^AĂs(y/vFu[֕U] B@A-p=e.?֫m/dj{CH$+ G!:َݱ}?!aY=2'aa3c1뗟,"RѮs; 'Ril""{% h/WImb5+upH 1G{TPEKK- o[b"kt"06o.nh.K!舟_wGف,$Y4UBfb:d)nIU Bە_'OfΛ* A&|$R_݂䙿z,klnu9 $K;w=rvv!ft==A3O?a!aGѻ!$qxs0JMOXyGkj>Y7xas]{_ gke4cJJwb϶Dfn!5 [ H1tӓC~]xGYH'%mbf""W'ռ")q]R(nx<>߮Ԡ8<]9P|+]g8!ʢ4n =(;2?6oy"ܬ!\ʈz*h]!<(tsmCx> L'6F(,Z'5pi"mʂdmPE熁`aS%H/[. dk4BNm4vrEw}]NC; CKxu5q H;vA5QV$yX(qym?qQy6v>G[kA|R$Qǐ$"l!.zC 2Xmsڊ]66' 5†,f> Qg٣4dG>u9F&v0H?8~bC y6Ą|}#N)&?{t eo8 2x*wU4(55Hjٷon>)--3O hK = k/~}@(ņ!0\O"{y {T?whcf0x;j AѾ圎8lܟol x c7ThZʗi轱 A\UKx.~0\=Ԩ14JA ћW~bӷ6/R=fz`NwzM/u UC# svL7ЪIylKmFK[ܢ84YjJ8aZs7=!cSu@#ީpҏ @\䎠wŰ^;I>roAȫf-^cC U9v-Gŧ=y6$00)*(#g~*َ Z=Kk@R#e\+|4BhYdS?6(_ gO 6 pOO֍&vlUNkD"9w"1=J4,"t! 9 19KD3"Mac>Y i̜ HGdDtD!yɈ~9VUj_%?'?[|YLR|l%~ Ox[sFTJRnrOJl=D#'p4'~()Ts$ <22oCl4;-FN 勪v=,=AidjVNO]gNz 'xkw {=}zb݂^g<}h/k7- 8߁|xM ?A\ElCa  ;/LwanCEUQ;ɐfų!,후lF Yor,'+=ҲJvTj!Cz,C/tkfy Behei,uA%}ⳑS)!7ޠ'N]܎4n=[iױgKg9Ⱥ+fAd=Dv#Oo]B`ྵyaLDL8侕czcw0ѳl{H\ߒHL4Ei^SBr?+l~gW^mu~SJsؤ"Wgg سC{zשqm!ʗ={%^z;άn\[Yf5?~G}w1kazjH@k;>q`<.=>0 W\Ôv6e=5XҎv/P@5^/B 닐1?~kУC;[PM;;&z C E!̜.7XF\hbD:02sٚ'9D; @ 6"zش21qΦZfp@2)m\c(uF^jxɓs&"s=?~qE$$yWFmc_mȂ]xrC{){%Xlb1 W" xJTc=3S*w3|͋>XUڱvҲj۱sEwBr\WȾ{(يM[`KxTzlߐu37s)?n4~}>^E/ҭ4l}Dm.׼ǘ`ؕ]+ Vdh36.Qq^1їo^} 8Y=s2p'4qNKJtޜIۜXv"b|fY5,UTrΪi5笚#9G;8'A{ekß99Ȝj#`w!j Y56sOypNKs9=S|'}nqlIFc I]$̮RW$\2y4'$mosыΏ(o?VHp/G~bfHת7Ow۷\CN+ Lvy~;Ҷ.( /Oا8:bu?#ɛɞo/9Q+Tslld;DN$Js_T8mg;{ ԋ KL Y3C ϞM~lǀ}9?Me߶Ip\}8Gy᪮z}iKOtb9>\O'>`q9!!#TO#>F<‹QC{{GCkGlvSWx1̫!Dq1R,|YZB'zou Q267Dt$o>'D>qk}nkT&P:!2s@`gky=+Rn6]7.ɂ_zh4A'~thK{Oy ]& C`!7eV#`?$ak:%d']ZXJ @CüOX+`4Bl*$,nnΦY=&Jwq#o!N}pZU&Uż.$vfAa,0qV#Q.(AAͬ[ظH6cYERBȲG?xN/t Fqu(FMs'I$+h*X7pFY`hVKоXUe_D7UP |×^Ue SCɛeVC%nM%¯~JvŶ r9Ԑ*Iy%EA"@{Tu [T!<*mKQ 轝ph,5Ux! !xWie{X\ OY)l;p5fYy{_(Ŝo|c=EEIQMm<׺U^&jEkGa;'2E + (ӿⴛRB".$jcpϽ 7ю7~F%PRnMԬ^rT$l'.&6|2LU S)s[Ls-ܾYZkdR6z$ "u.DFf& S  }"/^yn\{Mեs!iNyb%7|+C0Q-VJz8(0SR}=~,(P,yÁs;!1CO'ޘKGD-TceX KAo5p>M_ܬ:'ncm^$ӂA([3"n8q ݩ T 87/r/E2ݗ, =dG=%"қi+7Y/2 ^*^_'M@>[" V"FDVAj3Ȯ2w,ĆJ\IumOa+3?'EMH˶ycH DMmz$#G]/=Bܺ;]y  0DLkΘ^aRz13IE8f<2jM7a7yxݺUHhf*s OQ[Pc(\tr^&bw3|#ҫWGxC+0w=-)ρKj=ɈneӗΦrK/!1E"s ,P !ѻ}!V.ֈU@Jq|4  P+k!%꒿aG NR%b)0cYm !jM%Kn b^):ʲ̓- jI &cZREOk"W5\-N vbWD% -I;d09ڐ>A9#r<۝iHAx}CYg_\,5kl)ca2B}|TMfᗱ>Cz-z^QGW}T0 8E'!|KrP7)_s aaYr  ?c5W+'e⬙t->@8@kWL*M4=}^Ar1R ܫӆ)գJxiSә;Mbe6etCvB84OE#8OK`F%I6cXtR)@͔Er"=Jsk:naϥrcWB(aV7RIT`B DM u Ѭfس4.2,VJfϵ73ɥgƅsۥI\p:҄< H[33q!nr:ڗ~!(<DTK} X1q2nVܙ. مpY&蛛|Ӧi 6X%r[9|E%Kě7"U5"9 ik|?fNY-~ mYfaHE{(1KS\bh8ځQ$q32[~ VM.6B'!fU tei}|-V7>!X᷏ 2cbV=a |~ڃ88uѸ:?O H}+d.Vb6'P-dx$/$zϦN|TonPWs_Dbr^|E zu$[^rt%Oc#j^ZuVp7dB(p(=!L1X҃DZ'dYg\DK֒l|-yɱHՔd%F dK ,e>@+ahk_ԥ`mALO]W4?#T84uW4_\U y8)\w/-wˤ <»մ>Yd6ʈ#SI1 5a0JH!&Zg!TqSp\h'|^GȠbfS.MDYs4lMbꍧEw mӜܪa^ i@|]u hy-).ݶ*?j Rms{ m4q.!x)`n{RAg^Q9ΓܞxVs+.S32ye:8>%6Tjʘdf/ڝP^=/)'OgVK@(6 +m`VYkϐrO( ;-HKұHϿZiFAHXh g3ZL_y&O`ݚHdv 9}R7-,m#B?J5li:{"*4,!͓AinD,z@!\Vrb%pu6E հUQ`빼',wEE AdfE%3FfޟPHsA ^4c'Y%26)m,/C$Mjz9=T&=JK^6T@s'%7j@/Z\u6vB?" k;'ˬaTT;,)/0эbJ8Du:ً^.\WZoq7wȦ-_\5/l>.LoŠ}HF'J>QVPR0̣A ]컘OlҺ1l *ޫ۸\ mA HnLc?kN~A {ܝ^Qڲ\Uf$In h憃ACqT-7j7OЮPy~C8>]˦qŀh##C0ZZFTI w Wm nݽ^ èw &-*JNoPE 6zޟXLqMI~ Z*7.رֹh|Е{/+Y!>{STXT=Fjц}ˬTjj}iSO(+ F7J6NB=!mzU+ QƂBp gZ |X.J1p.?,mBӘ7RwUyPUs`)q &f=A6D:# |= _꣋"=of|)(}e ^)`/G-8bF("AZAL9jN-W}dSTZk̓k Z:CIch6:/zOit@֖Z51~ibnۃEM,U@>בn mIl *&6r=8C K([OF4?5 l1j =bYA$=-nvo$1@ nj 1^&=h?t`дBӱBJ;)A *ջ?/_ftq] ],Ch@/k}DL+:C!Al^G\B>WUu`4bb)QŢnBA D7 # 1ƘՅ>{$Q!zK__{-_3z{"Vs}b9mjT: UYl{p9?`,j_ Pݎo#fA3G$ƐL=]m>ap EZAm]pN:t5uPca n9xm ge~E'3+ϱySx )f@ĝt=d_.Ies1oZHfAyp72>;1& MB_t3Mo~ nF9~TxaQ}#ڷ ="z|[+XD<GqxA/q\L'T6: [qY>f>G 3Ea0ZMOJ|)WNU?qN> e>+IE/,{y-+4&)˶g #(3q+oIqq|YMyf|vpf\|njuVQA׈dKsYO^-h;%W pk4le) !fAM2k^zGt rB+*L"ZcH-Jrb,tL\?r ;s/|S1{x9ȥё~?1SsN(0L(0Ssد9i#Gn;rs<25wf@̱t3wfR4DcYgfPq3RLͱ25Rb9ŝ!>pjHζv C( 3#h#'Gnze ;37]GnzrPNt&x9THH,QcIZO G9g9Av(ELG Gv4N'NJ~_F[c,G蛥@l=O)6`fOtY^N! o_ț#`u@>Np:Y$TH%v׎D )7ȍd.廐n^j²f5 B\i9nH׀(Y=r<)%m_m'@rF W";3Kl6ܑ1cN6/'X N<72 -A0V/G|_%x_;NpRjW}$Σ S] ~hlNd{YHKDR^"-Fx"=BȆ/αVy 5L"BĬܧcQ]t.$FPDqb"F)N%sO7"N;ɧCcvɋ -*LISt3UD2sIrFwؽoʈu4J.i>!ʽ2#=܇|]OQ,KR &R^e;)r7V4ȝN6VIZ2@O !q:{ Hwy( M$e!p 4Ӄ{߉`0҇ ^L׷C@p{ ~"y>¤1`^dB~je"Y (Ri=itYn6d tSLy}"w dp|ҕͱ2IwS1宅@ 7%sv"tZ&Kמg%cE UY|9/^[`kj x'+(m<ً"S胰zvE^ҞėabVl^\iUꀫ;cQݠl[e23môᕤ`+bxb=ag e/ k2)s9a|.WSbmǽ`b 2X܎gt(X2ᯬc%~BwptzB52M/"D(#zVPN^Hi9o!!ޫ§4.'h\ud8`$*P|:C\f {τ^Z8}9F2֟%&_ tw~њ71bȚn>teboŮ ++01EZ*ɼ0Q .>12_sVEoiĴtITZHk'1R-A= l&FZ͊%ȿSU~~15k>]jvNL.9>f)7wQ 3 :Bh%m'|[O_ 8қK4xZuۮݴ\ෲg[Q};-_Zaʥ]Q n (4|%ڒ+r^/f"5!/;AIA-aۧq>F(AA~8Rr: 7'G֬5KBY>V"~A+[WMQ80ƻaFM,DoGȝ\> )fiBF~1Ϫ3{ͫ盠Mލ0U9R hJ&(j/ C # Xa7qGgPN0ՅKIH}r 3 Oa 4bq}gZ jgkr%2z#_LulQuAO8<9 xޗvZɽ!bIǂ]#''#C'2H:1rәiwia/t/Zt3\ױD mEy̪wl;HjFa7gOa\w*HY"@r&Pޗs^nDe /Gsߠ}D'8̦tP7q䂝6UAXTyѐivVG34&E+;mvA}ɰg9o"M&fv^LKw Q޿)SJMNbXSyB*jEkQ;dvLESrāwnp¢^cٮ_}vjZH݊"IUN[kcc<QӜè{OA ~̈AAq ˼8S2~Xe7%o]be'euEE+b[yZ#V SĈ(D.ULx@;LSY_( &1C:#w@.y[;XӉJ΂E=K+Qm^#jrQuM[U!! O>7+oq%x#DKyNMyTv{;/acJzjLv3eJ}li\/ΦwN \mJXazSu NIN, P#Z2Ig+:aU@}*]5V>@p{dg Շ m:'L OW D̪"֢0/QO,QB< r-ǐ f=O*>N qx$6m~c, 4wO!%!(awų1=^; yP|bWÒYCS=ע(9m^d^Q6ekE٪CؗuO_co;W0 %hP]y_j _r3)(E_}muF5ЅvkL78MSUh>'UC bJuEZ3F^G"rh9uP3E)3ezuEXbH}_\”\d1?%'eqع=8G.y]KzCSv_t #tcחKbxjthÙP0 @B;$B.P}ߵfA#`*@$2РȔ]0# JZ܉P|PCVq(<48jYt\0Q)0XBVG"B?mge|3V~#61+XG5dDz4 = 5?/]%ER$NBCoId`u[".6c7O@kII1>bJβ>n8IۼdI^o*+- N(NU: *>t1LRȪIQ: qNwwd~^3KmY">qYHkDH J}KR)fC5vؾ=hOp{M񷳒4`l:ѼX7/"6"`2;A<;w"ZqN#s3 Ե*IJx ju%OPFڣ_=ֶ+4>^cDuvR^m`9JJN2qX𜱸hjyIO1G.0~a^ hR9vTWq!1EwIY㫳GU)R']vU<&kY5M>"K)p׿r?/q8KS_6ׯ~%U3[OןWSʺ 2V&buw\9z]e@%}߿ #OS|oCA<ͮv'1nՕ=#KeE^ߔ}USnW"x[c2nװdo6՝`3F T$MXlnJ;~=X(hi+q!hQ~SYԠ9Fgٞ]19+%kt-Z$ n}`Yj4⎻3p~lB貚$ =(̅lZA6I¨=a ifei{d{ZR^ oXv S>N<Ws'+;+ޓhr&/JD&+Фb+! PRh8@+gވm-CYr㾐!iNo =x )USR?ǥ1dXWtqO!bjܦ^|55f1vsα}^\܁x7zTiuk̤(R:4q8w 7IN;#[ʡ?cXhLJ/"ՙC1zi[z8a,!㮈C qlo xl j&!߫4+4Z[hB1'}Bbv߻7 W{AbV9[3~pjs5x.v,tnq7(@qL1a҉0.M9>nD]ܤlDK3ɏ_ #^}_HDO~x}^Rc&5@R<`AP+e40m H\ڶr}LF-j qVߟn"cc޽;89s;$ۺB;y5ztSKoѡdل!Gh!LO[>R{v|ִ<  m5xЗZ(% 5J+B 1[ o B F 5_|-u (="HRD[u/|GI^:R`5xvP($QۦQC1;%a Y Iv /Ykf?D~oExzPЃTu[ Lrz9KV9S4:|fZXY mTBd6#.@Vrp)IZ\ۚJ&j#h[RM_ L;|*J=[!>I xcH˗iʼnosbǒhi QJNhǮM4a<줤uțHW qU ᭜-W1HɟehZ+J5@c7IPw!Okɝt)ڇ#{dj$,7IĠW)$ p>"7L|uC*Ov}5ȯs"7-ÁmքK2KU8YCSAD=qC:uOȣS/0*>K<^Fp`^ض)! @(Cǣb+昺0O~4ڴuVt9M+4^2rn nmǺ}JimM#DܚH_`∐M{~Fu {C=FT=oOS Pȑ?;\ª Ѱ/J^1}Wn:A h^tAK{7ql]1 Du;f}h˘JkwQ}8%wBmO!~%R iya: [aU,JKP5Ò5VKi+.TctRݗRJבbS߿m [}2怄)kCkےuA-YͲda0Tai6,[1Ia)k0š'&UK)գC:LKFu U$*6^}}b+KQ1[aJ~%G?$K]7v f,i qidĽҩAtAD38XAKH!`ɲ9G U +ԸN%c|{!pF}/[׶2d2.@C!t%g!;T cGwOB7^G0j1QNY6 QwgpO%ԕ(qe?8^=.7ڐr9#|z"لu}Ŝ8f7q@lZxR6ߺ1jG]5WL?ccG3Ra;|9 g.j>7 +_ rw3YJ 2 rTҤ-o*#`MZ!V'4ᓆ5؀.6 846NpG=X]J䣆:=6{,m7XF|_sȤcf /1OhsvudHm pJIgD'Mrl/":=_eI:NcDa1W>0;P:|f0X=ǒǻփev<16Jo&/ϑ"ЍQp猌9fB=,6cOg+ MM2XHt>6(; ?X{,-EOD%>0Jl3s(T`)׼63l3^3ǵf"y ӹf0Ԋk&kLf `gG]=N8a %ƙ) `l6E>oֱ!93zjpT4 L ΙEn9Dp*8'9K95B\%ݡфl5CF;!!xpuNɎrNr8yK9'EC'p"@< ?8q9G.9=Yn9g=Tr>a&!w >a$#7gpo85s|[q[KZrV g t"ǩc8 zgh³e$9W3tƙj<`$#'GÝ^G:~9Eg舳R 1∃n~Kf8pi_8p A| fG)g 58|Vcpĉ&3n|^q)q!4Ki.[]ru!5Nnαsa$3_?Kj/raĀŪ4 !#1 Bp2@oEU-|WnOf+>Yz!@Va0Bgng O(e_ݛ 6pZOs+d;[UvE|by؈+Y1`SQVB'YEiiPu0L0eT(e53%ilae[HT3vfA2m`gU^ 4BF+sFUI΋ [89$lGph oR;NymZڮͅoH6AtmsA3+`4Zk2fcE|@lnJe'1PMP#N7ԫQnT*I-*p.l SrWrQ,B:3_\\@f46;OΈ0LFS߽`ŚY':b}ldܙ`xYϿ2Ø_-V(8U"N)0DIzGo*cG6wЌ)PXV Wb$3;i6 S 44VC; ?h:R`tC65>h>,"ȔCKW:U֊93}b]y' KBF?>\0q&t{d{}iHɷ ߩbS]HID0؈āIP ,0 dQDؽ k{9 4n % #0XnPۙ;Sf/X8n=;`&w :8ޢ}S (ܓ3BIF.Kvo38LiZ}lYW 6۬xe,mc)T8+Ŧ*+22C)@;Mm UgLN H:=;N-4Q/C4M-u`Efpa8˻3/ޟ,^0@~J-u:ąO}PWU|-w#3+q)ޔsFqEebH%2? (2 _=.z 됎J}`\D뼦aXEWh$ ew NxIއb&/L)v%s%OC$,(i+I ~ξϰT]Ln7566cU ~->IRy2i{J{;'Ң7U<>kDqZLzC8UFU@WvЮNT\!ShlYY*$tJ^kе 4aD6+v^% :N`UTX2_/¤:c5+A-H)35afȮKc˩ !u٭Z-*Ks7&Hl5Y3 :fWoKs_Z&a`qǺ(; uVK'4oZfz*5dR]ElH7J3zC9*p;|gZMP~ Uzq D+lCp.@\4:$![j9t5:x:^`} E<LB9:ܫk{}(OUqrRϠ#ku ;~xXf0 j@L Ҙjsߋ ɔ=f1=ËyΊMd^U|\L4rRj~cR2,oN0._؈}U)yb,%i)IDbvAZevn$Wx][5pQHX%#$f$53 Nei&&ƊӬVѵPSV$u[z5 '˥`8D0zz/"[Dat[4UWV4P ܶ_m!tά7'|ψ~sBPhLkZ+ v:GZzщ!Ȧk9xf ' Z͢ ; w9Ɇ(N'Zyo#&x|?GI~45GS *J OƖex h?fK4RnSwY5q"D+Id!!xnl] Tۭ3ԏv%!| 簗]m7{:`˕gv%JdKÀ`{tQ5SS Oz?(,9Wx+xޒ ,1kC¦xVWN d0H0s<-e=n = ̽Q~Eݻi;z id@"H9!}B F/t#,ؘfY;C@,f_NBH6[07=,w*^c vfEȩ>p%oo̸?_1k63 ћn81%IO4n^!FR1pܴ|<f?%(•ŭ1zP:Qa9ΫZ" n6W-j)~SיIƤК=lN$߿.jV8}Q` Иb]{yA@shBTm?  FeEf+݆Yc@x0 .$v0E²-S}qbyW\ XgHoYYrONbF &S x\찊@,Vol,HF3!Xm`F z3U_fp5/ߢi03 ;P ZF1bd-Ɋxq }[/H8>70c@]gQ3;ǚSeLK[` :>_y jZR6mw4D;TJdžUyC1<`[,FPQȰs`?]4T" cm\sl; W֫^@DD@] Hqɧa F$YA 4ͯ5(>֛MLV쌢jr'7pfo!䒻ٚ5&pߠ_MK&MM~֗gCh/n4p|JH9f(* c3︃ywZB?Ewx po|%1LQsp..chݻ8Z!v~t >9P?s)"ab^NrP>b@uK/ 7'm^ qaT %EKiC@,`(罤Qc4e=Êr,5|Xa?'_!Ǜ%Ǟpzˆf_=3[mZv-"(c^~7[I{Bq^|$  ֵ 9 /xh9o8Wf8bukl>`ܡبm8[Ֆ I:=!=r!{8z\Z]}`v k9/_n*)AV,-@ ¿=|o y7Kvw*ЖKp+3L ֢jǧI8``̳v9u&bSb%W?gI}\؁ÄxhŕakOJmĴg:kH {rAm0CyS gK)IZ"m<0|JBFB`lDi[W & If7G; FAg.h1SZuzJtq%| v*9(LwjyA ;;z,{O~zPzR!XLT{x;_Yw2SŭKcINT*?@;Uondb5H ;8Lp1(06j<$azW0U>abr;2Dj̷k>|3P+F\U h/,Mzz<6U=6Gl%_|9)xd>\_) u?,5Ϩ|;I".ĽΥAbV; ׯH75 U/W<ۤL|*.âۭ2rUzmy+dwwZ'^ٟuϝvΪZBgܗBcyD`B{܏BޯbC @o=>!oH9>(ɀoKfWk][4tJ?tőQኂow';F:|kϸK Ӯ])g,yeyFVpR.n<Oxc%u1M&y)x93lx'MδۺT\Mws6&4;g߈tmmZ趷T݋{GXs 6n\OO1f4e2V#ǡ/>pW.՜E/*Z>U 3J:z[p(wsGSY~ *(H, @Wv7:!Uvit_^?BS]Qס 5D gI ENX'b:iCL750KlnFf5*7MMt^l L&,.h^npW& oCcӗv8[x!?ᚗ~ݽGaqc'h󸷃9\ w#C8a-c_XsD ͅ_OYn~1)iq%kR97$뜆-gA房g;CqW0qA(+  .ܮh-/_k~f!@Q OoPB_G 3ipb_xT ty CӯuGHxW̎p.[5u{πE7W8Q.-㺅u/,t7)ۥؐA5ƠA>lK10egHBb36)r1V.w3NDc 5iօadBPǺſ :1F\FEx!±/D&x'U+Y2<&!h/Cl,|! x Wxwmzmz^Lohk^B| إ)gԍ7 }‘n Ktg$>Ϥ]JGJ8Te-r[ȊTu< 3&h_EVa/M }qruGjf]$hC̸DUȟ!FaU/MiRb*gM Cfp6<[SWՖ:b+?Q,QQɼf;+f5O' }t-'wʿxBTZY2>$v˳2C ҡPخU޶(wC0)E -a+@l%E/)ԐQ4jP֌0[u;ߴ'}ٿ_y+/on)yE jsQx_X gOVkQr 6(?Ja"_~ 0+`& jm;Ր>oSLKOI1s3)vkbzE/<5YoW.1]`/Ǥh?̍^5J e/^@4=\0 7Ɣ.q=kCJ`apIUkB$7ZhmГ#1-GSS=j[L `U96/zc GT <UL0?16!JU7f>KD"qSՆߵ邼6̣@Ogp=y!XܯXE#Q7Y Kh(J>& ն'FۇG̒X?0F G4RUĝz Z迡IR_-VLq(5 M3 p9'e3]ү4okZ9SM#8ƥZ+<]O>uP&UE2Ė1f}޿.Q5er5 ~q^Y_0;?4>Q1+3%vޅYҲz;: X5{ȗp|a Ҷf|3X"gJ jM[Ҋ`ՍQƮ%Q0<~$qU\,#E9.icA}qeGA={AVj39 @_ȭ7W(*)}` >'Xi-LL)d4` lpf'ObY*AU>*?N;Zv&iJ`HP}%`?+E N]!ml,$jԘ 9S8obq s`n1F6IAH1\pkDjᢪ@7>\hՈX`c^>7<[Y2SZmFԃ@+ l]=Ƣˆ\ς7'ɲ/ݨɾ# |H$w2Ts*KgVe ]ulbVhg z, *85|cqʀg\,\[T,U:BQy 0zڮ@XL wrEb Jx30=:AhPSta#n m'CkT7s|,=W %RW#d S;Sk@A++1W%TȘK`/6FpVz$Jԃh]q)j J F_`k~v\E09Cr~58~dUb1IwnR;ɻ M@ZJ 낹4}ᑆ(C;]֛]X -7O\I ™Wɪqԏ$ڽP~ˏލkgH=δz V|$yuC: ȭ QU^SERM}yV<>>iIf O0S䥺3M˭O];O:\uGƦO\*}䥹ϰQsqNi>K}?hV ]\~w_R}~-$VY>M@OcD?~`.2k\nYSy=F*ߐuk1*Pþ_ '\-м9y&Zh+e@It-1DV]f 5tяc=ۀ*|$^2QP7č f^;BbCD%@ڥa``"'Gc W8O+T~'ˏڣV/'zv˃^26;>vqJpa3S<,s6Q#_O0F.:fƃ~Bqas^;f3):qaLW50ĚO_-mҿI[PnW1[NldKބP$)zQQ\_Z8m1qXى%/sKCҙz/[% wf0["V4Aud|(KVq].n`6)6 Q6|?F*Q1Ɨ/p>%׼brmmVT!r3waEQSލ`KRbә ):]b~hp\$Ԣ_sk]ځ,?m1Tmy;tyJRcvPk~{dHݎcǶͅcʾ0KK]&]:Z1Ngk#Bgٓ@@+xku+wa*ea7yeckR:j&\4xZY= 3U]iV-jQPv-n%Z \&KBr;u0 E[_Y~X;Ƒg.+y 쪍uС׃/ӲdMTQSq4ev--G 6dωf/c~}qL"Mup5xS']2rGϪ) >@|`7 A:m;xą B'>\FJsl>J_3Pg{'# UB`HkȖ[IE ЄXWR+E?iD?)Hߴʭ[G){ {!#ƽhc z4{rG쥨 IAɧMa5{& '1Yݨ`Jgݵ؝_xjøVu1U/ټʞtOrnȟh&~ 1=K 4􉡚Z>m㾣 L{oK'T.ե,?n/6 3?!Ӱ"j SD#<{Ť 5Gc`>o.P辄Cz f~,]x~%.Lbb5ڿrĹwGl9'*3 8_xa\] >@`ax'|>Z_sAp1~8׎1,MX1,Bv ;7;11 i-,0ׯ ;wc ɀ`cDAk.+_$gr;pj,lG} Y֭ l|oMuM s5ޛa&2LFU5X!ge*`$/꽲` {NUާkaϸ}^`>6tE-^ ;@D V'baN鷙 |VfuA|]3YN=\ s ~k}Z󸲍~Z#9zu=G\κ>,Vցa u>wF_Du=>@r| $mi~3LoJMI&KxWwHh*X4Bx?[q4-CwՇsC􁹔 UIօ!2tx̩{]Fb2oOtz7z0KRawqA)Dܺ|I˼wcR4x]5qk*C}l 5KRRKʐf(eĚ=xpE֟k ?X5i!ѣbE+//8Ee*/5~w++ZXt歋 ~|GW2DNGVtSfGb{ |iݸhn F)M{("bR.l FeS̗%l) He{uTץ {YVNMb|n7JRdԱ~O>sYauıUqaq#\DշLp3'GX[?u5ՍjQ '{U?gp;fa[^YW%kG:|4i!fTw嘅ބKګRx?C\2p#"PƥbPu,,B+PAMeEe]8;[z9O\cQ*:2O ^8ώHIx)' /H 3*> 7rLx 49LkB%䥷+|2op,J[ݟimrҗt NWLGZ+5/\睛t)e?1cOJ B^ FH.F=FgAnM|c7Ӷ3O P^4TpD8zsbt&bv^>R[_]_ I{>qNw^| f2\=鸻%e6J\i ̚-bdi+tBLz]-]LeLZU:XM`S[+xǖ9PV8zdkE>pe|ܘ41'N2[ZK%SCb(r=x :^NQ288V1 2'賆"76} h_2?|#YP`GO<2DʹMrHzr XH-ʀiO~x`ZԷ(de@ݺ3GWd^t͠s4'tn"`03gn /,vi3*T#!Fp{[0ɩ7݃]dzGGɃX$J-T3[AV"AHn!&V •=x7#/>Qɪkƨ'Ivn͛/Mlss^HNcдV5sd%4ΎH:QY91%7y+P鱵_7MA\6}oo f(wJ,;PA*opN .)72tRb"G"o$bCYls ,K*]ovN֪RE³Dd:dbY"3s}c!+c^^ ̤uO=4ay?{jiH x, . h{54LS4a2Ѡ|٬vVD%&#TB Ա'?Z3T^n]^7dEdZcN>=Az>Hk Wyo׸ m `4nM5צ5n07ihJ2[VKPF2xv{e6d!2E W?f~H9-z iBG23,_GC/rgr2  3-oc⩑)a/ϳoJ"]UwvuW^lV#=0Kh333KOy/ ^ tDSVRqS L߬%T7au I3<' k O>OpN#a0U:2/ۦI:2[zQ bX[׾T@MYSu[`a(ehbW+GlpR`'D5y"Ru4f3af )a9€r.T |%2@wmj *뜢gy(a`ȈQ6jӉ#_:Os8/dU~[piI5t'ueG Q"2P 7AT$fYa.K" \Z=ݪ2"ֈN*.bxO ( Bֽ|I ]h(&pT d3bZ*3Ƚ5w&⶛2cb2o8DlE1~M.fr<墡th!Je%uWG4Q4&y(Fu pͳqBe .ŦW#G+[+>kјޘr9O(m˴֕YѩɈHRr FRBT;3ɪʼUf+gmvy( =ȎX?؞IadXE0'-OmAQ;*% &yEr_>XיkkS.XLmIhh^TVR#J&1DF"O3[|UO/Ϗ*G/;Ga{UM -V`ed52G, $7َ&`d;Xg p0W{Z(x4v5Y8_1D!4ge`ʻhRlP)$:ҲހЮ9ԟ9p`7]# }y/ S6a-rN tn)d"gcu}gfruGjZMgN^v <1fl *5X&wlv86a'0$GRĕ=WX}krP!_wC24ߕJ8-3D U E{ rZ zʻ*^y$% Y*!)8[W~l*'lc0R+nr5ce# H;s$ſI* dٸ˲"KibZ( Ą|e džAӇg wz;Me+\U=/Nl]R(4QOD}% V(+Z*2d?a5xCjUE  1EPo<<.:XCCJwj*WƫWKw6RkD֡7:sSYZ0E`;b# 5 5i<+CC7A\ …C11e^:D O:wGDG1avB͐= LJdR6߹ wwֽ@3NZKcM W" `}jPt[kR-aך2'%6(hT8pCvI\1ޝmp5  ~F(;ang;iu+^@vINo(\U3כo5Hy C0BĈ+Vs/Ҧ&Li>G'ia?]>ύ uRJk4].!#g~ֵD.D}CV&Id@Z/V#/o=dʹr:\A/׾eă:f+ :!Km`dTAf,i&rdhZoC7;w[į4y6^pyksijPnYvnXx] <9ۢ ^ ^%ņ8rX.%C!teba b]WxZ{Dgm Ol(`޷)-y>TD}~&M"K&j FoP?m$. ix yG}E N]0|I<.=EdBO 2 ~B>68]{DCka-փˌu lҡ5dձo&ݓnB)TJ"9s|D>`lУl8PMitj='(:N衭 6*{QK^I *WSJwZtc~ 뼨(BbemysqѴHųzeM'6iKYkd|1tZ\m]1^)eooqp"c!xb<0\jd*nv5I{Fw*B(<^B]>3+E6'<5muс77BqTWoaDxͷ=c-l[!kvkLSLWɢaEy0X5xv4īr|a ?SG4XeJ~+g9$^ 'Kb ҕ"`U%0Gj MShCNĸ)m0A tBt3`kl5^L bSs0 ^-SH*ќ2P3Ze1ؓ20vY3e&&1>X0YNMz~zv oGpE2k!whffPf'KJèKJ)`'_P'IΛ-Ȝ̓$1Ee4˕.R1@8spIv7w}qVP@1gA/Y$Z:J`78?و|Oe#zѯyEg'AG {yKc $>b!ĬET9Y XHk-0MRjp2ڧ3Qk84:O* )s RxJR˹`kfi]!iH8#I&y0وr܏ '#Ci-i|8'9 OaԀ'ẶQ5V@Mx!V*Œ_~(!Xz4Qa`{MYvd4=L>Dp|73q!,tVtԝ+D=p)hS?h[錬-'Ǭ:5R^v #kvyV$:4fþk7d3䌪a[Q~B}K.b3 *@0Q˚Ne;M/Js /Syb/1mM~\KaƷea xU) hlO]ۊYJ஦l}jgoɔƶ&f~ђ0GFVob zޝt AmUo1hRG5^Iw=iiJiN鐜IʽDFR*emF:mř.j+2h[_M:eɸoPQՋă]oW@vݱH>+Opa1JU^mUB,mm|)dC± 3b-&ڹ!lnH7ŵ$Nwn+<)r+O>E ? ۀ)&tE7 QSc7R#K7z)"!R'ޤS[LJvqrc&Fm!1G,H e>*j*Q# uJ56 łZ'Krdp*y)4u[SUBBy0o;(HOvfD m}kLҕQBi:GXfw̄q/h\4Nǧ 1eOYb{[ѭV|^CߕC$8d C)8s9].3/7%nIq~PNiː#];/U%ܪΡvN8,$ĢD`6Mv 8k]J| kM6OR<'7mk#`[[r œ-S>B GdѪ]LNP&ЉT8i(1P^q$kh5ڌ (* sXc*ykGu ȧݳT4O23+z@,Y-$}8]ECa0ɚ[ L:jPz|fS?jH&`ZY9Nڽ4ɐ8Tf)N/k6Rt;lT%Ce*J쇅 u,wpTA~UN9M[>kyKx bH9Tl`fh5W9}k7YCToSJ;2bw* c?_la^9ghⰧċW9\+pS ƌ8S  o`T1IjxIL7@yG|D+PbJ`0u1=LJ^H/JP5-j/}fg.b+gIuZ.pRjUhj]yި[9e)ۥ 8)_?ʍ%*$/]+MYMs*߅`kxYFї]oi+r9f;╫S)^<˾?5N!|z"[xz{$ߗ5.翾/o vyC*g`lh_X~Vh~hͽZQ_/$7;$Ґ$5/s_H9~y_`0^hz& T1f<9.ЄS ׃! P sa&طI &_@r}455ңhل/:L avcDa tEop)~='*$Nt&#s!Y^A1̨qF1>bas:9Vi!|^QݿEm7#덁/"0"-.{[f@O'IXIy J JI!@%G 0ZZ+7 [Q,5C8M5R!SGhmz^"[1 I}!( mP.H,ڪr/[IVD<[V^jvУpݚn,9N)rCyeM @42$L.h\0Yg+_5N5VX#&/G &}1Y([֙⯘KG׮ev0:EᬲW\ˬ!/3WPj\dOLs?R{hݢB~__7S~ҵh XxVQ/40~I z _tr Mu#4ll`+(H-s NG{׌M8e|c?k*# i'v$C9 a\G<:ÙTo81:9 n`\?*fD 5 ʭUh ;h^9+hͳ6yv}r`Tf~JiJ+Fhn授νUi]SeJCiό6rMK؈] Y 6nW7JJ;YR'$. %M;+NGieso360*3Ӥ3Mc+иRҮJK҇ξr+@7H6mzL>rL8p-{?mx8 ^F%K-ˇJGn!x ߲W?0PnӟGj?MgAHߙ8ys{a^&I֕qij7zEvs>c/5=uo &PI # -  !  A{ECdI0-: 0A`/Zz%aʰ.@5L S/.^7[]# Wx <BʘlC{qm֩u0_LhQ t80-ev)&v&ƛ_:Gg@ ^hH!ya %3Єyp=/8 5*,=Yo_SR0.! Hg1D Ӈ]:w?KI ma:s %#5u 4QEw%tTۦ(DY?wu9{T&;Lt;hXnX*u^bk'#lVG7xüU0C&|J֡ڛaIXqBOduXwa\"{(c+|O @WV )9*p]G;X/t; f0LcN-WC'ORunҀ b &]6nޑA-B:woH4@hhojc9IҜkPCzC]L I̪Be7|{Nt;1\C6:-[ʤRʦ(oo+n&rtEUp܌;/]Wm|dҥHxcݘކ)ӍC0PB W7|{(M͎5i};涰$|7`בu5>]j-&dmpὭVQ/ic'q|ws:}rRkl㳱֍a%ޫQژ+Dlb1q#OP_sbM" Z1-،xnBبrF<-/Pp.yry9kAU)dӵQUO_1<π@z lg:݃YB[\nsB]=5dwZfrc]&Vi#EL#ѿo| 3kQ3A6p^}Oaݎ%ߘ-atT "; X&9mx47(D]:67sPŋe^>Jb$ =xv}aYCLI>Y{+1oӏʼn5y:H ߄nr:BVcKb]M_YBgL+j r|᷉C;G29| `8PqBG{/dPaI)lvK;I`.s؅``\o/a6Y}ǎC<.Pir%b;~EيxWlIPgt3YD傍 `o7py"zt-wšri:! UR͛c/]>\71G92/ҙ m7['^~^a!0hkL UO{y(}d]|Bc:Ji]G@$5;d*[[]rI4Lo0̥y0gs*9aA( sGa̭0*\  9a@ɐ90gHڑ9q?wa2AnQQ"i U ,^b/Wk \hLZ^[7~PzKNdڻVBuYxhJa_f~ BpgEFO6> |Nz_!y6u e9.'8̤B,ĕgJJq8!WJz֡ a~Κh+:Crl?.PACmMS"s|=uD9Ts;I/edT?ofŽvS/O&[y3 A~鎡ky,g\| y9땍} UDZJ@iɉ+RA̖? QauqʤB%dh+o/lnAUb!J<#@d4Ez[79 1DW&"!j#r25(G"( D4Nsf9yhVb晟yݔxY'R'u $+n'}j5s [.F$g ܁xN`/;(s'U)7d_R P݌DF%,Pr_ f=)T Yxb @=s,:҆JjwKtQOj1dI/TV*U}˧8,exDwVfMUO!׋W:ヹhdw;B8Y5zkF"<#l_rT:>'=7^1򥺇0ܻQDBBQld։Pr2RQqRɆLuRh>LO[޾]w7{>Qd}qE‘=M+ׅTbE uR-NEגˠWzk޹!ȇk;HA}췟0w[7dU+ɒܽb;Sfy1i}CcɑIq$ })$TE ̢7l!H)Fů vW@)PeL'YYe)WcG1A!_9~ M5V*Sz-kLچhMP2K ,laf< }Kc0c-Ԙ1_Q\`~kDWF_-sq{r\1=9s&6L’2ev44Z|Ѱno} *thPva4ّI"CS^ڝ ĺE 4Y*2{]B,)C=2[ BocQ"Z>iԏ,H!q=؟']&cL3!;سR]LoWsw:"On*[b*ym(ryNg[QyBYŅJh#lߢsM!D6TZf$81B3I)~Yn~r,yG'iiyWkJ{T5i3ŴXT"QZw'yltwXy{0'mOfv5΂fB&csX"EIeЬҺt2A&Y.yϝ8[;gҏs&229pE=t1pv&&n~ yPPL.I]'Qv+k>, g}8O nB8 ,whEV  $&"(b)Sj= >`n>"3Ӏe%D,jUb"Oal:SnqܷhY<旕-sIX%֞m Pд^kԵIT%;bAadxf8̃tvGL2iA!J xNJj))Th\ [[ E=)qοڈh>v!,#z_dOxڬP9l_.ɓe3oaeށ¼ H\ʣMk1-2>BO2ʕ_m\#4aHRHʍG$_՝>`կ6RVi[eŤ'PvDHM[/K@ ,0lY8TΠ&ufQG𡝶1=gՒ3Ap &ilw}aI6x'T>.Gh{V1LT ܠPuRc5-JY-<\Zc,V3 Ype0H_x&ٿB!DygH\ ̚QHA /j*3% D{rPEC7Qq^ e}}d:S"@]Gj A"y6zy}[O4oB#IPpdL&" !Qx Cؼ!a*6줅DGi tretņd/*{ 62I5%]*{٣2.]DXx(CUwaL<&$Jǜب*##S h'F!6^kS%s}hvwMp&mVeJ. .2ra`?Ac50HPUdQ t+`B~bw4!סWUQGUW8V6@gNfF[>GM~]QTiy}TG X YY2>NV+!21&3)7(3,FJ~ihE:>n,IؚܶeEjХ08AJgTm])$''/mcݝEf9f|OXD9 C8͵-ި= -'EB9u }WX '̮W<ːRJl"Y.oD>K̺ YZ$ 1 "ok_xB:.IYZQf̝G4 M\cm?GvXoBdWNWMڠTA+:ElUͷEmUW_1Xҏpt@ v弲C8ڤ-?^ ϳ*U'[9 {4e<,joV_Z9R]!;^=ç3Nླྀ0(8nOnZ ښ'KTyOj3TW'0HʺX;DÙ|@qwjFIdҮfɡl)'V:Nƽ;bO(H. (B2Dawttl?DP&D[Oڔb=;%A уAn#ofZ"j5vVhc,*Xd- *~ADUju4D1aM&$A.?5,lBiΰ9 FdG!ZÃ)g8O2ٗU3A*o}MaH/7֘0)c0BUu[f Z{K81Dmt[|:}2rd:6t(ɇ $ACx:C׳XCP gikߠ%S۾ui."Sܯu/gar3!xH v0+>[d\4Q//U'I$ asLDB7/F8o`tJ'vo`ZMOQ8ڐ.q)x C#*/D-1@ :ff:ȱ{3p%F>%a8V(ڔݷ'k34ErEWZ[\Ȥv;wBf%H# ܟ5Q3lxk+Ea;- {%tp%@-O=^W6/&g7 xVd!OR|¼Ix]%}nJỽd1֤+{a}k:\zbr QVuc( L7+S?,4Szvs+@s>m7ma~崄9SXp{JnU7ۃT]8[{8Hv@~X'i:o~&XXb-17un'^@RK(7 MKB4h_JM,vqu+иio #_xE\F5QjI,جk /c@ak$cVO2ljI&!]eI֣\ ox"G UeЁ11 3:9ЁA/eSB@&VNY٧-c%imHmYQ t%1 tY$nGS`_t(-b5E؇<~ QVH@2§,Ó4KL#4/NfLXp95ц=kGj骩LU5X0Lc/f\{fґ$LS:7$HL=X91Z84L^R~ ` ?\kLJI auf\o֩BwQRScP ]+$ZC}g&KyugɢP6C#/OoރYB)dɉĝDC!Z< ȑ1ثHi ?,L-.8p¿'&JVrE~0ըSagWbum0.N$Bv*Xmi]l3çJ gY`+z$<Z5ג(~#5ӥSHۦٷ X)o]6(m̓qU}0Mry҇Ї *bgOk{?A f|mx{{j۬rC&]tuQCU_d/Yrd"<+~Nƫ)Նjw1;n}bG5SlaalSѨk&pMmmԯ{ASktU6[,ayمAar O]m̫mFG#$ PuL $f}JXhѝ*0޾*?1_ʊV1M7IʱKIӾtb+_=x=i>՟1uJ{-%}AV ͕4O@G]Nck\ԏ3%oȔ7TyӚ۝<̤aU=/ƌAse[ZAEm^Q#MZdQ#3GNϸܨ0}c1xJ]jSv_b@A;>׵[S%0h h`bSFљ%7Ga14R>UaHVRex10J aBfEm3@fH}!,!kV*1j^?_ƪ֎yy9]u7ʏ}l1 1MRR'MVX G8 In@򢓫m[ ^orx9`XH"`M,竇|Qhi+9]67ZG6z|弑C9rp{bgLY2@: 0m+UcKD햻w]7N9md d[Ӝ/@=KtɵF~dݩY1厙=cmDe_* mcRvfmOdv[k{G`_ nURc_B;"]q`ɓΧ]gic 5Dl1Smbf*m~#,Q׬Ch~ [#iQ_-_shhlꆒN$$/Bvo .ӓڼ9ڥ).xr߹Ȏlw&ę~kjvM_e%"-м6\5BgMu|9%V;\^̌^UPf쵻m2Shh͂tMBҋE>֦Y H Nwpx@Yz.(m\mm?\*%B+'-bAi5^t'~QnM^P;LY ȷ 4XVTyfuN{mRx-202:l`>lub#񁮾auc559d?}1eM[jMe%|nDBSS{Hv)VTS@ɤ9Էq.n]2X Y I~,3ug +pGqYW*HR@e`TnS O>>Wz pɫ I_WʵER`:L\r[A'MS {Fث;c eQ]|=bxjÏNvtX;f[:%0B-? RS7 k/Qr\ Qd;5<{gF<@b +#SOyWC/TcSY~A Ih E&}&C`Ì Nֶv,O.:쯻:BO5au4 'dQp}BZ'O`{7aR LqC̓3MCRR U\.u#/$v^ve0yP~z u<=lV1.`6ϭ25s#޼w%:1g[pF!Umsr/2_S L HCF Cnܾ1 xDcDb|n]='I0"2jwa]S#@TǗ}~"Kw;D B(m2B1U@+V7D[WCK:I9#8BjVg]S=P>c,/n&$}v@G#ɦ:9@p.6ΞPժ>Q5j2&~#Ci\zr*oծڽ/MHƺpG9m?'YIl9\.1vgv5>}Al@F9#i d(C"Ar=r^] \{X[%u[Edc bm7Y 7 |>X C2sЬ|uNG<{T [aChVAx\nyp;xExkIV9l-}ap: .`&yKfrKI7 r~Cqqs;[< ENI:%[7K>oo@/9FO[Q4j$'O|m׬W: *c[]uYK׮ܼҶvt:N|q4cu{'bm|$2|ھt'F9w&IiY9%!K ֳr^oW s}q]Qֳ[Oɷ%mm=#ط!xp.>Q>g<L%dYa :ȤfUGӕ"eZWWZ:=#s)"[!rP >mg|㖶7NU=8$3Ð~2of8ir>m_ǁHgzR5%ߚG=8Ԟ6(ߓNS[%K.K/C.ߧ:o#[ v"|*Hs#]WXNGkB.#]O|jGIB2_ԡqE0&9^H3y3vdo Ϛo2v a[GؤVfk) rV(*tYt삔ܿ:'=#4FƽC98~@.7~{QC$=~t7fܛ=;.~`.qe r"\ƽM]ƽfƽ-ƽy8˸7f1] ɸ7Wf+Pߍq?]"1 y9po9ue>DF{Mh~w ka|Eoz(}f`nG Ce9M%شX+[47sor-/ZFt3%z0RB>ȵb. ڔ8Wݒ܃9T,hTy̢ sr|K Pj씓?&d#ʴ㙠׳%ԛL BMyVJ|EHƚXR4pR[ߪ6A"(JR(=1\f0m$]6rk;/4RLO/EbN#S5N*V3[[Q\RNu7&lU^'z4ۺ"ζeD.Vt[dN$Iu[X⺱ݞsx?H.<'5a%UQ~ӇK:͒;q,OTJ훀0PwDVĕ˚.,nar8-\ 3O!kHI|)w "pbnh PB%1DŽ7e_Ί8E_T2jTT(Q;7+[SOr'ϭl,.z$T趲; Du Et@')eVX\𑷟cHgxgvA8iٿBM atڙgΊ|ɼMv`reSVCMTĨaNBy?81<QG͓`ϳm#X}0P\oԪW ޑuu:2@KU URp>BrP] BgG7`KBVm<0oGŞorlp*!XQ`Qr+UZhQnrBjaMRY3Ncu];N`FYO\s@uja,`&_|䫅o>FE }3}Wsƒ8b³KEpdpa\P.CvcDxAxLm.zlmGs"v,[G)=Yh|/X6 c@Maj]2զTF X}@R5ENZנd˘.F|iV#"pAP"=0⩻l]-/m9֍/b~Au_#wHx~ey01˗\"Ŧ^myԢ+xZ:&tr1[]ԯX|gEL{s1h)@4^2ctH h1}FGEڢPv Sdp1&%oUO0R:BWHVd+0lD]wCFä[J_>pcEՒb#0ҨO1:vQTYc33!&!)J bI1>5cWI_*s?vT*3Q Ⱥ^PXeGz $(3^\kN6FÚxź(CMBs_YzO4ǚb?&27~O fMsYmPVDVV=F Dc I>3?znsZ#\PJV<5MOͺX50xQ_*E Eih[tMbB,K&m-K7m֦fRK|G^Of΂ʕ p6֪U=m?6LdISil6bgZ.7<G{ 2"?뾡W[ u+j.Jf,ƇrtIʞ{bj;컑C޸Wy}RT' >L~Tof/I4j^E3d .l -I\ }_"tڼ?n tGQ[RABI6ufDnD:b:LS+Ñ/7gcȪ[o{S[s&YK|Nv|!<+Ӕsqh`-CmԽŭ܉(8KUT[gk۩<3r[Zǁf#ֶË:Z!M6&q%}?Khr˸8k,x+H)10wÈVs0|Kci cèDH6}*^IykħnŞnvkyvn!؛nvcυкUɦU#Җ\6C뤜:<0yeD,nݙ8Ѭ6W!訇I5Bl>t\m\Vť˦qskOCc 暈=/3.bm1$K#=wn^;։{'j鏆9}NhguH^Xh\&ԣmž#`]euý^{%}˯u+ AGT]gxWI ܳ-6nnTҒs|☘elV $VSA]9B՛YΚ7ߢDA-F"a"u]z'pk-H.dX Zn媟|Li-yi=vv*kcAp E r -4JN՛' 5y Q\Eym$A[V&`oS-1p>Ol;'ԶP۳£WG OOm 3_ >,ljmZQpL5'b^dAeK_pRLx_rŸ5%'xZL^6+ti~ oJu6b֞j/}ce%S~j[ٶV#MSDzUp:WJEd# $˙/[K*P r`+ ktaMC;`R;Ў-b!&B/l}Bo0s&;Xav;w iaZ=N'6_ C;gC;* cOaE椫xͬ'd8Wܝ>A.ҾFiT5=H j ߄9mWFsZnh BM&%ĭ$ .]|\]5}c*u("֩i=dy?+:G*Ȇ)e"`^VsB[GO0*tA bt#2>zc6ҽ+\W =^BEF)FybɊzALXARDUOUA'wfuw>,}n͙[Z1mLa!-n71SjԾ|b-n}CG*vkβ B0ppM{b06EM} ͕c"NД7dm)>x3"z{3=$Xu )W,QQ釳Dt}!MZJ*Z:YI EsOOyY Y/z;HbP81RQ*(YEFsw@;+`{Dv 4[ DU %C⡜~$=ב<я%AwxǮ+q {Hf uDV̠T&Wa : (,>'m%9SCfJʛ~Of3C\0e VdDf͚ 5vyL|zke;נ*0wh2 !#a  &\f֔xkR[q ؖԮk&&d%iO TF* -b}іSSx.AKWks}zc .6 b c&`]0|,]&> |5hKp*G&9օݷ Rl+U%blكWf $3ypTki'88mCR"^_/,73&/[&iw_meIs6zl.ORMy;@-plW$ZxG2A+>Knp9j\)SO,POt3AUE*sl.qZj!pM_0qhC,=6]-i8(ni$=p c ocнqr]t3;4rNgݪoΝ=q݉{YP4Rn NE;\W ZmP%i6 )Na<±!1Gܯ=39dT|LxYJgi-۸:v={4WĆBbD8o*(.W]wqCΚaLC %1Xȷ Z#L-;aI0+ěӀX搻]|z &$јt*$^؈|-Dp0ɒ&cX==0 )~2  Crv{(z*C.6D٘ PҪY9.2),|tF|#\Nx`/ܢݕ9lM"vLtboOh&kY}T"p9HT&Ju\ۦ_4h< Π.!/(7nZ 0 x^"c R?:YO+ĤO4MnoWC+ A< $luvY슶IWRz k/*^zM})q+_F֍V,1۬D )ko=0" ]!awN-d%5Vթ+ зn%o([&2TOH-b OtŠ%VD M,KJ,FyU\E~֮ŅK -m/0bJ0A%)9LOGZQM&ߩ J^q-dbjhd&)z4:<{L:A|Cpӆ-D竉6}mg@phFnT4vpV(lJi{ik7dzB9vhz=En,t6Ubv>Xv(yP ;B6{ҥtlޅ2d+r~aN׈T3NX;4eآ= vGQ\ [ $zFfSoT14Bl^kwҹC?] -D+k$9ˠЛu+Zu}_CQv'ZZ]en#Y,Iڒۀ5VlR9or1;MeN"}eO欝Q b�`W'7IwgqHcMJћ43vh4,{20EARIψ98Jl"-2)rkEdm g0`Ļ1a_R72T`b5U YCSE{:+ugɠp-,HR P*8Y3df(\or:kY{qL'hL/kH۹%6%z˼E.QV %)Dg\N3 E0k9F&50rڇ7y}g>U߰_07_rI_}Wamq0DɈc 1뿫_VjTk /t0t ͨЭb̑0-ZΕȋ굕]qU(PSգiEXG n_uQT)'0xbwby9lMٸCIfF`%mÒ&rfrxz@'}T,| d' .GM DTMŸkt\<{H}q%)KO b;gs Mdw)l zjFXh6Rʗ<\F`δ,BU RyEDoS`M6)dKTxcK=)2qJ{{TgJ(g,, 6#8([|f bTz1҃򗭹QoWy$`MZ$B6X 4$,tz{B5Gݙ(J@fhHK0\:AK,}tw:yoR禯f#7MHi_?12mu)RWttX:*C}1\b)~9zO`0Ӈ0tIlsnrESgm6n|׎)uD1ԩg*iR/,@FηzgKGmT_|.w.6f'r6$( JH W.ԙ0 pjk #v<B9y/9p.E@Q äVqgv:oR'NfDMLx[(b{kQs9-*Nޓ0lxbveME=^%8y` ; Hά 1RVgA+4w-jכ5Z[Xl^ZY_Tdח` FKL%] ȥܨ4ֺ=م~२ž#bLC !u{mAs!$& ɚglf]`˘yl'V1x~ߐ47e!8qXQܜteعUWBPW8qPvv 8ꣁNM1vߥzV붟]}1ŋ|-GխuK]w5!dWD{F s]WO?8v.:EEWM=W?m{. W^T1RsigwaFM*z.:`T9HyJZv *nT]EӗsږB_MDn415TX qUuup棯Hs~>Z:p4@;A!9E4ou\\uUؿz,貛X+f;յŚ;+2N̏Wg5\!z hM?yY^? Gc]}0V隫;.i;>[d}H '!vpq1_Xyq˂h'D.xs`kPlro@ű|]Hx_}t᱊q.z!w_Y.ܩqս>^N\JLfR=u6f}͐#&{LabG=\ŚXԐh hpDedCFl=Dd͹5f9=u"Laߍlټ  SD>8D$[ [%mß!`5@Qv dml)I$7cOZήe:ϦNA{ۯJDSs̒i\7;<=ډhzmmDYgl`Ʊڙd49CM ibXҋ?u҄>L9I!:5oLOk\)_Nٙ~_=VT,[ѳ?/H@lfε0\NQ~ D8(·ŭ+T_D.fj/&d+]Ы-Ɔm5~_. hP0t+c!MC_p[ KG[kW-/-HQ6@V6e+$&^ K -_tXcZ}!vGFۃʽxN`^I3DiSCCIr^D8Y#QhɨN>Wfa>2-$ I$EBц+Avgb|1PgxzI$D#/yN8cj\:'ui0Ma1 ~}"Ob.#iyGS6G*][0Xo= 1f )v>R\ >TniUKB`q8<-pDB6'uDLQ8&Q sW·'17Q09镺o0^ٮ-^ e= $+*={;#ڑN!U؞BZşIWz]D*ߢ"8,MTb 6!SrV h(v|?M[HKY#=cGg1n* :wz<Â5F{k#0*,HsF/A35 W".c{1jv@FT% .*'`f1'1DE Xi!MeU(f}d/{{{IeNe;IWOЋ?3A˄7xH3E$"w2 L"D CWz{+,j.uim˻ͩI]x`j5, 35@d 餦̪! 7dBTubԣհ1hC'"VH|Ȧ*Y;Rj#6=yU&-uAL.stvm C]f.dd\qn+|ymp>{r\Xl7¶YKtXAl;Dt%`Zi{c7]CAIcfHg TWo"ma0"8!/W^g Bz&줻W?0b3钡_a(&W LBORTpnn jTAf 5dA _SE`9AТ9<{4\P(.@T o0BͪHkH +*+&vN9?ډf1Vd_VoAQXs^e 4;,Ū*iL="0 sl3,^hwxm Ќ"yF\QYZy~Bl_ 6#!FhSb^2W?{HdLWh$疇 AΌTSV"CHkVh<؅&‡5)k%&@Tz(5R>.g.]=.ZP@P+4#AǮq/E"7 %< vW-, [嶣pe֥% n"Ќo(n< =wj6/j#D< lKq("f<1wV~⃴"Y@x^H}f|1tFfa`t" (»n'/G,._v h5-o$iHIv8+1Mz38 EkShߊ[qT2]jNAǚ(myˮSBhϘDb&yfO;NyM>`}g [r^#}ChB:mp?܎3b#+cGi;Ym>1"χ@ ̴[<~cWF?b9k3'Y`Hc ͟ TM0 +4HWI-k#%N? 29d%:^"0,b0hN)]b@&@'yWBunlAl2d2?ZeP&fUA资rJ, ʒCNGMF0=V4QkTKVo}^Y]m>q̊ǨKU,Ilk6?R$ W63) զOC5.MbRԏa>piѹ1pI Oj.i wRp*K&z{~17&m%,.̴h#0-IrXEm@eVP;M}% 33Y`  >LqS낳bR*w˹||k$cݠ$(Bm {CTsº;wS=HkIb_éqt;[\%~52%pQ QEuȷ3p+C|;_bažcyxytnE C)`P3U>71'r̐/b6J9jOyܭ뒛E3Vyd~JytSXbmvb8FI¢T=8rcZH.r&u20n ?UK<00kuuah $ ӕz%A4fp ζڎ;Ը2W$b&8Hki}ɕ 6D<"84Ӛ51P`v̯O Ͼd"fRp-/;~ .0ױ0ecfWtAiȲ!Ҷ[~dʠ8AK8U缄h3c8uSu\0O4$\ 8–DD FXB, pb ɉTҵ"u@X(ƃܡ/sh5d mMp[K՚褽~q6Z?_7+iIzzÅAZڵ3WEqj:,K"B3S`҃wk_5|5ј+V~G)\,Zm#6qDK4@Xx DQ'+j*CdҸƶrϧ 8#rŚύHnf"{,”:1qz}1/GJE5C(;9 6{9>EiP.GK9ۼXGv tsL5Caq:J1)+&?v0&?◃"Li/3ί/,{Љ6Qܓ_. A~QR,:/=Oo1 ca2e.(/aaCJKٹOL]9DGu=pȐ&JG Yi:S6HC8tS>'c^Hӏ > v=QeԉzX2147c<@ M%gb N#PEH?]$EL`dƁ毕G(c(_KJVHY2-S$Gy]&jeAk f 5+DL/f-%a9ԕeFrͳGD1׋9?_B " uݐhb6+y?1,f-&njGS0zcbI:]L'+WDBdsR,-fem>pfBߦmu\HxR|Nz̑ua;)c逼|.H1ۈuetQ,Anl&e98|-×x|ϢNWAM{=-՘QXipB_j緰}\CaK^eM#/>0H y]x!̊o``wH w6D-DlĊ2cEt ֊=IE%"/X dOYqO,,u`nl|os_.lZ6תjSi  :K 萂qQ0\1jT]%4&߰j<cJ_~ ~d' 8aKM8خ̩KR[GBt_b,gS? FWz,8îrVV8fzYj6`Vo7(n$s>=CNNM^;'Gq.l@kr([5 tĎ4brL'$uG<\1ߗf"ġ-J=UPƼ:ȇ S BattIT=Y! o`53QF q`,<$W$8/ČR3>59ŒZ&g 3v R.2 @#p9͍Yʰ>\4}ńB0+0bAoךb-7tKoP{1ZO&8˜Ơ> nL|<b3p1/CCA$Ҹ lS?Ͱ/dOH$h%ALx^z8~A|lԀLNlK&eArԩW k|}-<'en S6@_?  wV-Y DŽcz-ӄ'I?A[%1B*N׻ͣ(V39Y\lRs=D N[^n5N"_ӄ̥a獕˜X)'ֶ!,_J[ז76+oHt X y[ܺ|vL1α 罏}bmm\ )떓vj6&vpW $w(gvJzԁ xKbb~3Zs7X߮(Ěy}‘ M7ʅ':Ccܸ|^4]םMxֻGP{3z hk#S͕2M]{[mZYS9T)w~9` g%LԖVad2a=7,+cW2Y+h,Uz!H 0YWYYdA^xx!c˖H[X_/(\l6myV)%x29PɺSCJ?0t+m9t+ 3NZeմ: UqgV> <(HmT XHJ-rh٪)u0n) ]-s#`6vH4!0 -ɜ4XZM \i2దȎm&. Q(U`R7rߢlu ?JgăavWxh/PK,\ME&-Id0 ZI @i ]#' 9 1*+=XeӴgbdR|L==%WI6hɕdi:*;&r!|P2AOda5z-|4ӻ!'%mr9zOtxeKlnsB8gxG:s,{(14ecbVhpfF|t2cR1W*$IҵV]a.1O C ~eTbݝK`: <[ӀZԚFsiux~D} vJ`C?ZI{axY.`{&r?#M&5VMĻBaƶO8)|[~>"5Ghx=x .ao2r{D@~, Sznaѷ'Vtly>r{4o>һāYXYWnNIdr=A:,g6C|+;37\ת0 ,scBp !^sLe1|UA ߙ8 V72Zv'|iʢg芛 ~@}oA+ 5cq V;<1OlƆ&sѝݖȢI?|JԖ C}~ I>C%sPڣ7>"Ikb_xg>k &›pN:rB:f\Wɬ5ewϝ]pPa:#.WI w6%~μD|` eʺ02\}<3Fw<ž~SyP, me)E4dF5aٲ,pu!Ƭ$̅q[y(6aʲn*,w,U62Y^H[i[Dr =s$5vҒ#K5m,:!cքK 4xTjqLOc5y JL?d ˔&S?Bތ$?0eF,LY#, {CT|1GRU6z&.['XYlh% K֨_9y0 GwSD0Mm-<[{)桠,(&J4[Qt~{ qpޟ @#ҚW/uq?#=O4wfNӻqnbu;ޅN;b ׼F 6Vz&9%|P ;&9A6j?Lb ; pj&4ɼ$E0SX4Ezoゝ=Y!V'&]N0'&mh /I_6F柑.X(وc8*uRl 7YУ'd´#9G@rۋ/xeyppf9;M舩1{ D׌yGmc29 /Yw g(vB6=~}ͽ݂ߏݳwXf1"'f" L3S ffP؀XeyTՃk2L8\Bf%"N51\So"M!K9>viXv9׹x˷(oŎr.H!\<,}qжqx(bџ^G.flw9G{biXt f>1o<LqBĸ{Ǜ3t'j~mj[da{gw/M`th0X3:s6s dn7A!;]WlX3VE[y">9,3<3sDT.S3ܻmjfJ Ӂfh:XW5WlhB>ܓt{ĉf.y H33O# BSsN5WcGq 46kI'菭3t8Ӏ|q4=~9g 3a$sp(bݐs o8̭7X8k辔L3]S=<`{P3 ƙϪ*Նy7C-v24%޽t0JBrQSH'&R\`[Ϸ"Rf4DZM{2[J2e%e٣(¢"IɵXq0SEl.y`m eKQ"2mlb|ye!oH2&U`&©2кGboT=Od@0d3,\$ծXT9X2Y8ͤkaHsoY:ʐ2l:,6j[C<}U+1yR([R ĸNJFxˣhy ;;3_haJD7=NNAXuBIk!\, A&}[/-89N54^_1$Y#kIO$EKKj9ه@D. bɶyI)C|d$;e7mmn=S3 vD#'bN`yn5' 1'4f| MRk936lJfgd GO%19uRə{ka1;kmL䌙0JJ#xe"o \Iq/;cF~@t&.b0:H|@$¼7x. L~YW e13+Cf\0Ud d.*cbbmgAlM_33TcTe\y7 &D+ٜ.K) |H%6Q{)LVܺ+8vn;+pOP+zU#%}EXsg6 _tmK͍ڤ,bl`AV x)<@3|d»'P5&mSϣHVYf0OLF|apWP tR0ٿ\Tv`A6 765PJ&{UU% Nlj֞41xqmOj-"Ir` )5-ŎYwX>ʚΞ7HYl|U6:gy~$Ĺ+εgujmЦKnb{ 3{(-PaBAuVQF DzGDWY#Lfq%uFi,[`0'@%Clj6]`HC)y@PDSq>f{Ȳ Ue_s$bCj&eY1XB6cjY.6@G9sc]&>o0iuTZzoz/hi,ƹ!adI[Q4$g q.+'$& S7x*wQ j#O{WF14&p7VHh;+`moOh' "hp3?T޸-<3h'9)5x2 B5)f>`|i/SSyMTw i- 5(twcl4SQ&31.O/y*=r3wqfEiy^ɴbF-BfN}y%V,ZX3KZX$3*xiAȄ`3٘X!RL?7Bi)3ͺ DQgK+8ac3P%oX@u`: zoxW'Fԙk:]iT!͖Y,nف2gvAٛT N'Y<-2Ն &y9Sƙ. T1X&ԛ*lNjJ3ϪbhxOu ZU,z?kw ]Bgy$re(ð1G!7Lks_챓P qB"߳ &'Ey'|o-'j{`uc~&}WtFFϾmW7ضp^6\vF5\W!1@yC EGz S{ߔ86 5. ZԷM<|Wcmzr%3Є6q\<F:쮭l%[i_җ7([γ&SڗfC2?PC,HS`t0X$QWc#gn)kk+!U/jTɤ22eNt!d"d{copq;7t3ޮ[np;|὾S*hxkc2ŷwj6@0 Ƽyqm)^7a ,=̅lY jKmm'H<\ 3?(N۴Rt2xms/?Ƭ[Y,E&S8XE  es4 "8Ѷ Kq8KcX:Gr?o>njtP%-t:B.ey, {G*~+{4A[0亞aaڵ܅KBwwOwxG\U h3U標S3CV9*" Kg>ar $ozC0*jhYXeL 39Fޤ1p \S,.zKvX.H $|Cձ|C3 ehF2 ªk#HIȸ)rB)6ӹ]5W!:%5G#Q/~{njȂZ"[y HWY!tUqbZXxGm ޅBA&*+phԦ4VN ^2F )7mgtM7neQ kL:ɄݿG;b!xVm"HqRAتkLYލ`xmC+ >R`En^r<^,*ϙ[6*wUhҟx~}siЂmh1\t8~CÈ~cf{A3Ze_.+[8BK9Kon]0k٪QyȭI *z ix.p '!؜*lyΟ7%@7 eHMc5oVŻ:$|ZާS3[Pqj40l n C@ݷmuz{Ch&msĚ[,΍#ұy#fNiy$({k |>OX5cn\dVZݩ=鳰sFN5cYunr$- 3Z!/ଖ]\[Q `^@ȂDCnM^b!`s2n|Zovr%X;#} }ݶۖ?7&X-b&ZᑫV%p| 5QKK)-Zd[74L AƧ :cbL y a ;7su`;\۶͓rxv3zb]`zu`U nFD}֔ #$23]j@9\dBWɆfJؕط3nw*|e6r4wt"F= Zl}%ۉpeycMؒ:21%K[W@{g"uԾyDr&*gypf:~m2j-fn=0 AndžEyV5V h 6- ^(ҐA>쏍?'m/Z):Vͤa2tJANر%*,CLluϸ]& HHq3jh uz3 eG 6 iVw@l]ᕱK3n.$LUcۉ BCdnAD<^ZBR= Ө*c(pu ^Y%U'Pޞg9XAo9*/\< 14r0PY}bl0l㡁A岓B`hȓɰ1{%.wXԱX^*Մ<25q<7->s5AQ)BoZ]&u.?A,Zzb+j,ՊS|eG=^agQ?a7g'oC D>SrE>_G`)^.vJQRN><[wOD~NJc&D(砼9uZw6zf:a}^O}0EȾNȾ|v Iu?hp=[x~oΆLd1m0mhUCpD7\33(A5l]4$[zgMS@o%wKZ3~}@1f/-iI1Z |5m/Pt]3U+L"CUm0y& +v j~ф Ȍ~䟸͓m:=C 5j{FE '߳&t``|[BC;XWI Vvd|dr \d\nN魰bbVz)QE>dp <Û e3;*@H󻝼5ULփF_ yAޒ`!@} $H]7 C6Osfd\6YBvq,5ƶpw_p47/.Q2Vg:Ð[8F3enm#)z =_9"+,/;į$x>+.-hQ8iL"Ep`vMM_د43H-b5o\n;!MZ6-&j@o30FVF1Ș"T\r(+I\20{KvR[RG_ 1|_Wf}6E'C(TUq6WD3z[~>FښנuːB`"fEܸPX)i~ s' `^5~c¸[[Nʃ.Su=< jl6m5}xu[&BG23hG40jxnLDs}Zbk\V#~VNSKS3%onH=>bs*9D>7jU'L |UC36$ݳ2*.ݴ*Txן%ʵU~!j.qSy90\.ΤJHձdX+p-3JFtvT S_IƄ+o߿wB\Ǟ@i{i:-!Υ#3B+w17`U%sSfs` ={ fU.c (nVid` 7~~ۄ<_垄n5a&U[#E9.c"!H(;go0}bs6ⶵGolIQ?I[iQ2k&[Hįૢuj_܈Wy`TS@pHWY򱍘J`H<i*q1eQlUs8*Ncl Zlk17ߍ@ ݰIU@Ǩmmm}3JT-:0_рÄ^ǜxnxG& -x9Ks(WC!/.j{.:K!})Bs9P`B=OAr5/ XᆕF;kK{vaRŮ*3'fv`w a W1XIG. Xo :kYND^G/c_H_F#7ΐ/_^^ߐ|[Ju3[pvsΑ7&DL;BΪ W EQW@#NxuLYbW4mu(Tl ҽ6xŅFOz$jЃ[teV~ E,r 8< [ S?#F7_aS#`#SGŔmA Tsr҇+4sE?\H B̈}o% `WtO/NG]PXCYljnh,àW&}CTQt*/EVMU}-V*>>'iNG;3=UUu&{:>_$Uuz~0GG]Uaߐ>BQD x![ڟH M`Phz<׵5"&KU^@l!W)2Tu`U PQUFg2ԺsZ/&y~.#_OLݺ xg!3Zv0R_1TYWy֌#yT~/ɣ Ĺ \&A6Yr(!$ *7FE Зki3[0/kr0E~'KoP/u6{_S- w-&%/ 63҃ˢ-ٖL 0~6!vbGԦ?E\m"b[ Ɔ ,9q.'LD֢ x?:NNohIH2 : v[j=a7`M4 _r.Bv[&LUQn-΋HY6ͥ56pnz?Yylϓցj3%mnL1/y648$h4}]C-f:HgvXC삟䍡;a_* CpY/\QeF=}5 :JAr]Ƥx ;үVMw>:& nywqH ~%;v=f9M'씿 oZ L 7#ǘ‚r>c!9orB=:Ga-Vfݮ)bvV+Gzw>l@0QEp}^:, &ㄼ/=<]AMGt 47ˇy= 3s yn<A?KNvpp g 2aO j\v6ng؍iѲEcMm.(& g MRq1@nGCek):坤dᢢtn_]s& vK?ɺxG7/vw';X>0b^}<^4F>Em{-# y` biږI =7\;qz=wK^ai 3qN~ 8#.IaSTSNhSښjO| ܀u0 f)Z Xi6km( <^{j*:&(U@|74kSr3 :9v|#\;cN4Tlb!WZ{-$qxN 2yA sfM\*7K~Yt5alo&L݂?Q5103Ho9j(;Nqo0[n|N&- s{ -nX`8MHLG\nHG7]vaQ.Pn"px 4va=y>@`gOvv}<ԶQm$iVaq|_Er;ۅ3뀅¢]\`Fl mKn|η'\Ʋa6v-?rS;ozmqL[!QN _)}*`|=Kzd̻fw;vr_#q4 8T=z aFڛ_#T.Idag\rU8cPU=㾕ݘ~U#\|ZZGR3E>ZכW\Ī^U§>_gUZ㚜!6Ϊa-oF(:s#)nooxыPM@twJE 575Չ5#A1C֤Q ·;;Քy[e:)T}7;R B8 s祡iU/nR!礱 s8IK?NIT}sOw^D׳3cX0,ГF۷y^R@;tYȉ:c/X'V%w<4HmꮎϺ)_-YnЁtpG\R:!r~%cFkF?Vci\t,L̥KGu%Ӆw6]w=tᴍ|O01𙝑P^m~)uYa,GN]Vn+WR]4ʤJnuQ[EȔռ1ЂgxJz~]H WȮ GAR^DӉS{zW`BIvh[ewY`R9G"m2T$ŰSܺKog D]PZ -,2.0μ8v<w1[5232Z*<|mdERAwrH x}N"W7+_s)Ǵn Nh=\%\ qeU`zTwpEjt<LΣH}FiL &J百z|N^k꩛a.vx{q_𬜰qQ4mQH1! Ǖ5eʫjZVp'WRN#9JHws9l~e]nofTҩ 2wFEQӨL*^ʷ\\ b"1C3"z"C&/؃#4yGi6AK$w;(1fG>[zh`Ŏ{Y ||* k1!A>EoB@|V01)2<&+Ng`\$7HZ_Gmr,n,\HgɕwqLUCfOy+mR.skRwmj)ѷ % 3s13E#czRÞ-efR>$DҎJRF 0#Կ >"fv䍶@dbz?G@>smU})wHl9k;W2rk}]-c8e]5i}`Bݨ]|2|b&VY͕Y"aU&n$~toVdVC:#++XW%Q1{,wꙴ("lV3j,wfrr"K|ΪҨCVUxUfnACRKGSY&A_d$.xmvK(e]J[=:E"3YY%0A#KDeMET4x)wNY[|!9_a.Ϫ*3gStlYuɅsbIK0,FX;;iJΡՊ {rr@jڎ] pߔDx;10E7{5dd;Ra{gމtg˜,L}"H\fl#!1h%ق/]Ԡ&w5W⛯)<#N frCK1=rAIRRcTNuF)+N\ZLܨvG .? sEY?ia"v:GVq_*S&Œ-tpr@Z*!&4[1o2s ?ff<~XB'/϶TGKnNMJ>g߭L!Fcy&odm ;3 ]2R})lMZTpL͚O'ٰ{x://x})^4.=t; 4ړF*?ecC,M>[ uTƩ7P`?&am1i F%ZȈMqٕb)\BClZMO6 >Gʓ#}M &1ߔg4)RzZ#*ύy-D [rsޕMzeˬGv<v]\\KWI:a䥪P ռv<:ʵEت F|EFTX4J ebR'-Kvl} G*;Ե *Z @WzAw704N;yͳ H=EδĕHNny@u-ӹKV\NC[&С`d@wL#(#`#DH#h"OwBٺax=yjTnb_7% :,82-a`|umsw9nV<a8V|q-+>8}bӋWNűhn*mrCJ&TºFP@~b?*ַ4of>`1 `=m40)[놰NC1Ϩd~")S@!Dei-ʗFK$enE+!k+o{R s '2\w9Ѫ72,ƪotކC EH:мPlEs'`>3}F,[gKeΦI٤KGrY"D El֦&2dhy[:k?֫68Ļ6)K??pÙt ČaboiyT;M8 hF1"5fJ+E(#7W76/ͽT_XbeA4Fk3xg#Qz΅X" sfZ+bxeƇ 5Jb㮼kA{.T90A MP'b=P~Gun^=-I0P+tFh-U*i}ck@,*Db>^DI~8$KS$iST`*??]3Qn 0YQSI|]*PSW|gDl|">ƴA%K⇞h@|E/@nesxSy}N%fl,紐{E!vHK-EdWpQuf>/"l] 7f꼄`;.._ّ}<"- xU/7zp@hؘuK<_ &aD&_uNM6By #*^0߯7<}e“ 4\WSwcy0JJd\2@_qmX>cӵfJ]TN*:#5$[Y2hޕiQ qYXmhh4-5uF[SPEER(6X=^0nY+AȭkMq +ˋ4a8:|Yȴ2Mi=ܔZ.)S$S0q ζ 3sMtdsjh޹dLxhH)VE".zvQ#*e4*5еV|#N/lzRo3%Ⲭ zv)~],J \:zleĺeQCk| x3,"`s\Si68-F}oMdٯ#Y'N?jwZ(2 ƒ/vR:վ&-\،ΫF7ҿ!@lJMJrt"FsJKuo]^}ɟ5vkOřWFS ]lu߶h,Ilf(lcrf,P LlotI__Z&i\Nڪoi( }.e!ՄZwIm:mgec>l5mlCAq*Uޭ& ko/L7)dueE66 0ޘ;K(Ox=X"o N׻dKj}ř@ڼaΪ!UýQ/x]@6I~.U#73h~?ˮHZYZK_EJeDuJ`Fa3T6OSfcXJ*S,ofR)D2)r Agk{޳}}7 8kD!CptJFHz/֕]Ӡqi{00}Guw"4C#٭AwD8x)ebԉ brh7]AA~IWQj+ ܮ[:6(T9:!ceF;+"Ie&ii IM;ʃOUiƯ0==%-k*]oK~/tӢ-b^{M5kx%]5ӷF}4vD}??SkeX؃&^b٫(-ퟠ̧-P(6Ѭ0]dǒ({-xwars@F K_9RPB) 4;vMTtEy"w1J___oDWӏn"tfw<@n E?<`Yd[ohLS!=u9xQˀ+I" ,!ɣ;'Q)bCAhݟѠ.(ދ$>`GH h{\H @0n@ڸ#(3 A)F.B5 B p9 O|,uFj{J4tX5X^]>Q*ߪ 9˹1tıg Hp7;*ͫ]  t^Q" P/b[/{h[F2lb7!!Ar #!k:P/l!&]HIjZFA o#E˞TGv8IɑhS\~LBwij> E3V qJϤ)m9{E$U}n̓ %H#}7 )GXa)ZRp"va@!yRb`”/lY[taiKD=,tD!zЏ/AJ*aX::6R}c@8ÈG=Ru{ "T~6vKm4󍯍dBTTDgČ8GOo/Pk0J⟦ASU/&O`Apx"}*d(VAKZOU8rQr v<' Y'fNIvLH:ή{\R\Ӳ[ ^`ZuRRL@@őEH/dFDiʄ7q_%x67bh@EئzJ:xAp BМW؋gHRZjжO #RڕZY*) 塑e,5nDW36I0̲ o44Fà_,կ6ZI9GDZ M)_0fF&aح{;3EeJJ4EEJ*e4p Ml-`x prz򵩵;ܣjkOS(f ӊhD9V1!<~* BrgZ 2<_' KUAųknϛxH?Ip_X\DtHBRÝˡzB&ox1# qʍ狢!=*ie| kc3?&Fβa}(8T=wvRAB{ztOj5)@uiX7R8$P*[d>"q@'jj$ΗoIi"=#PvbCܱ18 j/xTaj^^NAaJxVDw`HcJ5TV(AZ 4?I_ddC_>䥩V=+ H2c P7n WcOMpn P'ʒ. Y6>Ng#]bԵ?K*Vk_ `AR@کʢ% enQbW굝v V/M.qPL?,N?_QL4OݷY~ª"4McM^lC*Z5$۰:-8VxYRYVwӀ! 0췕T .Ecyz DvR!!}'@rMGExq1z XD1e_/xI] ZɇW&P#.GQm-̃UtۣԿItC*,wo#y1))_tCq FZ}f21(;Ca%VG[r}M X0:q$I)dHkv߰"=b1xUO_=U8]vYF+̼P#7<<8WXيȽ ^xTˌ(+TǞKRM%)tlP6˓Lv􀚽+r{9Agd] ax#~rcƩDH!վ=Ғ=|$E,;]fZi=μ^Q2TjBQ$45!%9*żt^xN5wd 1(/ <|!>UXލ"̍}= Ymyc3ssFPlcFCYVOyHFHkxrjzbS_WX˯3(e4s Ay$`2NmSDFlN&zr,ٰ4MlOTQG<r,nfn:r=1 67DNj16J{v| !2G&}IJ~<ǒH6&ZںstZ_p!,|1j[xAžS"%iLi][Nl}x>8+:M.]%MSFf r$S|oA2r?r_$h7{EB4hBd\C ?lXS_~eIw|!n{[۫n2uE<+[>G}9(?(: AHyӸ(y䂋#(؋&%;+& J'փʸ"-=ӋbYET6D*Ewq\n#~Aiut'3İ]!o2:{*= <3Ur܍:q00wy0領p|RI6Yv`w'18ќ7~QU2.igce0;]T嬞JsSU[NWe8xmu'Lr[`7C#_/k?vzF8qz'kNy6'IpV`D)%sfRL8rbbb>4` P=tJZko>;1xzCDa%8cf䌳|@}O[Q^ <\`򎀦bM[HB[`pZoZBĺM0ֿ/0|ae^tQ^t>['=ʶӞsOʮ&ה^pjX@o)dY~P tS,e١̣JΤ܉8w28*}5X93V`$[=Ez"dHv*2"7e(%?0s}|9ñxp3[.sϥ*Γv,h\b()2Em* tʚb7e;$=AG" vvf/%3K,fʑ,ƙ_}s [wb lXEx)Fߔܯ{9+lt#%_{bЬn{2k`VQ~ZWpf ס2RwŚoqc9E(FfR8N~pPpGksЛY1߽5: q5ja?:<$#]zC۟E k}_A\tE$]/ ǕB!E:S n},æ<|EPG7J~ '}|tR\>bt%oZScA=N,'=NUnqYEǾ0!z}LHI/_<|+IW哓8Ŀ[㤏_^>κX]{HCGJLǗt+Pqxr1~ʪr-7:4哋@Ld'׺r;*I=VO;M1pD%0cMx/RĿ^~j!&맖^r 6cX&pof$%.X6wfnc;bA<{w_yK::A?AHp烢:pϵere) .efA.É0|D%@{ IA#ws?!ݬHeAcr ̟hVf(bQXUow9_!;q2oPʌPCK_醿˸"˂8G h[Acc[ʌzÑЈ n:rg#WY$G_6QEC T:9et9&Hx6a\=0ݿ;j(&&`ʠLcuHgŪSS:`=\%b(g% qY>t!@ܓ #EBeХxr_%"$oRMLA{.MvaԬsQ)}18' q%M`~?Ruku*A P]K52 b`jQ rJA DOx2rpQnC 0l)=tZ+:oJ]:UH۳S=ٯֶ]` F#˲_Dh)]P9VY ,Lф^ER_ҲV GdopOLRơNCa\k\DӐmkQļ ,>#WJB_bE0(j͌`"ng7YnQs^Qc0+. ?k^f|X^q fuv=(AXm1Ѿ+iG+=Wlb0( x14աpq=D\tt0a^dh'Wͫl^/mGf<HWqKH7d~z8HA.|Qc iV)J ]״:UfJ!vUCIzsSY/@l bxx5l/c١]y e/%O.=o8+/A8JpP-G'_j۔=UP^wUχըwwmWU)GLJTۇΫ'dyw%Ia@f]ޓ"iV~Hv7#6O*eUC>5x$^]p#B駕̣J{ lZ"  iMciӋ> .߃ 6]5qmlnelM/1y1jx1 \]R}F-:z•kWfF4E3z8^g=Nmp&44)Y!(zhj^\+Q1L輇ּe=MXCߍVpw.b)lUؿv'pݼM O0׵n$1T,8?se-K"S8@kcwV^j|ƿj?:0qwb8UE}>(x^Eƕ[u ((WE{eabX8\%\al̀M68|X(i^<% q!_jev?qf_tWpy-֮C46MWl}sƚ| 7o=O / 7aLVq-UwG\L8+ LGGd:l~9b^'7nvB؇ZNߺo|JdqPoQbë#l]%CQvz ;b&61bʏEWQlnMؓm'4"2M?鱷an~P$Iv#G۾ee7z~j& n5 J_㡩 hsٻYL2;NIn|8޷uR"vRwǸ ^Խ"[PF:8E8C8B: ૉ@rzHZ1TQ.^Dmܽdu/Wg.P3vJi4|8Ne9bQ=w(q ) ߦ7xnpgMx4J!N[&oc8e O:ـxfHɦĘ5 B5> qm/Q!iE{<&W@5.-UT7-)|UbѶXxE .Bޮ7k ]e,?znrcTąLj)nV<EM'T=8R]|d8\ b5E: ͩ) NvB[:Fry4^! ! zT,Cl)鎽=,f0r< cDEkkPTI*2jU.ʆM R)C*13BjaU#9w+HOਡ@q})' GFVxK@5m7 ;SX6>r )Dk7򧾐k'lQOL:LB#, SJN[*GN  8dt tpЩb3 ȣ5ՖˣL\֬KԜn/,U]{(T >mtFz!Li7BMqfy|@PXN#Y*N>Q 5z9L&g\}~5]dFFIsm!SvɚnǃnO? اхs6OV/HKwR>+gOUNcV>{ EJ j['kv@ЖMI}vcQGWcƏit>-A$ ᥸>AuF/*8И%aX>)f%Hb,k(?>1ˮԹ ,LxM(ՠﱳ~TTQ wȬ/Im"r/FԬa͇QoǮބj0Iuf>!v _[uxWfRx0S,FBA_+x,\S/&| @$H" u9 ";_ئ9"0? ZuzD3V'4@V 𣄔`:^ ۔Uv s)Jh~R9td`J# %e!eĺNufjHO-$`Tvbǰ&Y;XFz9pw1ّI̙{"fꘞn| sB4?N 0ug \ )tީ% jjf2:0b~@`ǖJ1:0OdvI7TC{-*R23,>c iZ}lx:xIFE抈rfǎ*QE%(aRH#bH<;D/% C<L@/@!LKFq; ր2eA2x#@HPPBJ$Ur G#F6Q@K[bN)P8)@_c);-U9Yr`rREmgLc` ØxmTŲdʝ.,ڀ5syeRɬ% xOda3Kq9UF9%@ݐq8F2aKrvc^EiKsr,cܱ>TJdkbbE^)A;HD<}$b<1 QMוtwT.^H=CP4@()vYRv-ּ;ߪ%$?0mFx!B`֭X 9) 4~f`Ğa*7'&H#ɿ9K⑍Ec%{js Ujtr/}V7twl#fvK}p6ӡDe(E x&CAX꟎R~%baqHW*xB+ya]\v0Ӎ:|WWX~*'E"W9TE{=jD7PfY F68kش}!@z[0h1eFR>~m lTE (?Ǎ,yՃE:Hmک}("ѯOX "QuȱE?ZI7>Z[n5j_azLe }I68~^+dy:Ic%%LxXmcC%{%/X*+ ,xB]cO")\Ņ/ B;#qn7A',9e_Hg4u&wd^Iu-DR#kSk/fŞ<1eG2sd-#e__#H\,evie(Zb{\oE3Ecn%NmGoLLGA[\ 9(epO ڐU C>M%aէeJS!kT\,nYg9=M/?aAِ}XEX/91OJSOd̦צ btȮrB6Zf%^r6*bV"<8Łem}o_%^%^!=MqȂQ,&]fӫ+hׄ|.E5eZ>Z1!ڮWUbh4/İ 1; nA GEYxoEAs03R~& , *E:P됦j >麯E!_Wdq7mIF< Ggw(z*xUx:JD R0ڡw=1*^ǪpΛ~бO2FR/J&b"32W_tB(V@ {2DhBTbQHYfLGB_ݢ6C<҄73^{(>Mlp踚 Jjuy)lB W)rIRe M_ac3Z"?[1⯼:0"Mq-K4QOCO[i98sۧN`}}<5~Olf>WJ_Z*ndoaU6BceuN[ 'JY15:UQ?C*8n{R͑0jIK !$-cxZqu6u8sjL,\[8[$_>L*tnr)5Rw@QO߭UB׎<\:4hK5񄭎g~0.MA2!0:~մRU3:/υ=D, iEKĄn AȏY7hK(MSWw]{+ekkWz^߇ׇ҃¼]VR޻}29lJW>ЍWiMO&?5@My7)R3Tb Ż>d%.cy K+S.UnR! W^FW.f,~ Bu耟(OqyڤmFgd DL.ѕ͌P]},3Ov)7!/`1 T>Q$yyUbeoqpP_ qfv޻a [8`C{wc~` +# +wjtrymyu@_9M]_J]LϘ5(4M~> {u9ؔ }Ħ64oUQ4+BIxiq)WjSXrc욠C5A}K%BMTʣ3Svs1.]%II &qŨ.9;7/e=C f)C*gL^/sһ\=F|`r㸥u,IhkpA }/|5i #5x-Iխ@1X8G{(î]?i[-G2~[;np%fR߰\ iGzV#vٺOM19Cƻⷻ ~q/`YMvv(rUaL3aVpDhcYfHhA2A↌ !T#yJ./)I3(H|Jo!?(G&ÀOxE(lXF:0FMO#ΞnHaN7%3 D`|V܇9QKϯrkhbysqyY8g`xdZ¡tp4CQ.tCCFSn3oni~c0tT %[QF7K_gQQpyՉCLVYGળ^IpQ^eB*{i 9-IDʢB-;]uwY6*s\)}PU넫~7+WUgǟ.shqōw'_:;ՎS}G99~&䭫x} +"`"b>H7< e1suu*n+i}PP&:[<ŭP,ukPbZI{h} )v7}YIi w1>cs5!eKoQ"^XC̾ؿtEu 92 :8fk.֝t.Sa+>q:U/d~A1wDԚG(u(_GEpi757CN#DQYV3o˧X Tׁw3(gsh# hl'G|!(<->& \h,۳NxzAC Nx}KmOt7){(kKo1Cir\3+X?JI9Fh){$)nm85}(qͥ]XxXW9r EUsn+ҶtT)rg~1O!1傗:ƻߟ JڙRΜfӋGq[D(d TܳD?zpn,ؤ=%fdzR;PrS %@B3ۃrs{]Y>:<Cye=@ M/qE)/_$5pѭC yй4W}z02mj>jH6zksTu{P7Ex7W fc\V)a]6"c1wNQl<D β.Ʈ GFAkǫI4rl l{9ewv, ]?  ޭҼ, fl=YÏٕE $@&Ė) hdo 5tGF;xN>y/qg"}&0TcXprz=) |X8_iOJ (7EX|/0 VwY{\ج,*]rڅRw(/TսuDUm//xӱ= SVW}yD T&I=xt:Y0^ܱ'#hNtCyqO7O9r(*avZJƔ>F'ٟmE qw lqn=0Y{W2|teˇ^hr PW|ڞncvZ4N/mo!y ń&F<çp'}bVo&Ĉica- i<>[H3yD_\eaӗ s+<71E8\ߺ|&au{#6I.3q|;~R%a_gLW'>c4_^+V[jY\syWt0uC x*B6y B5aln~h(T]ޔS+Q`G$qÌw<ˇ&MY0BFWMڊ~"b vL̇8V{DZ. sm . #OmzY±=dgPS@U^HzxkU ֞ =~h݌m|v$' r*½[b̼u6*E=uDnc 8z\9v/x3#XD~knM!JXzn^%p,>mw/'\!v7%&蚔Wç?{3z~}N&&w6WZ{1O9tPɓg=΁3>&ec)&)Pœ;`œS&?hHۆ#FC-5 crO>ݡc1ǎ[ۀ&kc6';UPՏOG)q(ɽ8bg2) iZgk ]`ܷν)pڣ"ûc?B~z m|l׳'} D_;0|t}L)iճjRwةߔ݁w?۩_N=b~ԯveԯ^.;~QEg0ԯ5N=rwy;\N1'HTIնBݭSѬ㭷St9NNVlǩGv?kDKeovЩ'Ma؁zSk9k*> ъsm}ď].J_"s^K_wuB%S{}D 9F rqTqzld|BnSIF64&)ϻ]u1 4p3'u};xNq;zy:ըݔn9k3ߎ(pzV~-4UܗfkS}G<vSDua솗xv~Y;ZX7s+جN񜧝1\C@V2R#Sp#bpNG-Н.L}Q; u+)ļĠ.2 BT9&e6,PRs$27 ͤDGv"1DvߊEB(w}/XhݟiI s=k4\Y0 %P 4EJ%Ь9 gXOFONTlE SaT[(?r;*$/ŝO o4wPw!R3niMQ]u v=DJV3\XN2Z:U"t9B=h|0~\ ~1G)\-ٰd)1L~PImiM)łB\(k9X)m}H(jv xTl zq4e h%ل,V3A$>"h<]VKree##cg@?fh}}&]? &F M?VOFdeE@g9*&QEU?U_y;<!H+0hǒ TuL=4iS3 `$414|V *.Z,-#{(/ ByjLf&( yc̱X|ū Pz/UÜJɨ?#mx9X--PJ3|mu] 5tv}Rj+zJ,XQ(ߤ){ G @Ωu$΋R.#IYݯϨ[BLJ~ߤх>*SC `'H~rBߔ/=xjewXS/U *&'V$P4JPAsyɱ [%p_%\2=u [jYNM{1iht1kTL' ( : ,OEԘ5BS݂Ʋ xEH䄏.a1 Jv*7Kkn! 3g$nWHfUU0PHIja\uE!R <2{a4^e4ez,gq)ZNVn8s 8*.W3[QY&՘6)45"+Q~Rֻ/)f7)ojw䲨e269_b xcBv2e"r{ mBf8ڈNi1{V̻̋|ů|X" RK8ttx57"ӉRہ3%30KU& 顼܏ΙR󉊬 =#~.@QsRҮ u>󗤳mp&rki6 E/xHϢiʣT }&ze˰DRT{#*MGjPxy%gXiKa``{9u4Z˘7ǷkzCڡ#>ͪ'P%`lO ֶ{8&0(Q j+gdG 1XttLA~hQp,G~|!S+Yj;$i阾&[IdFZ8Hԕ, ! dҞ7 */{bgHzjJRP 񄛘G}}SGPN*h+o(?%5_II)V\!t\5\&eNkn0f?K&-Sn0I)~rkL _MȜRݘۘ ] 73lN>o>&qʅI=œk0U R0bha@}ۘ)}T龽xl5UϩFJ$)(խܓ.?jVK468VE]m(|@8!=V̗=ARShJv52N 彽v&*Y!"esZIKl,·22e%gUMϡ› Qda_[#iڮqzVeI6#+::Ka:VGpdenDvWGZYZ0_U(ڋir deJV3nn(QTEwA$Hh}\Hq+JCcg 7Yx(,y2Z{wvs꤀ȆO}lP"\P)S &YEYwysuKtX&+Uk'M-iiӝ_^L}-c"*jt7kK)$H5U99Q >U. q5& d9, &G3~"Vk̰d>W(.!a4bIRpxfk{:aChcL-oIڪSS׭[uI9&ƒeC.ox#m'o :Mort _W~$vҤd<CX<)_e55]kkOL ]u 4J<>EC6H\N49·l,]|ĺ;_qw *g^+y_=%yES| >/x01cFZ&-TH1OqvB[%4Y~ޔbb.ﳜ|IlYtV ( }kM;s",ɓl: JNR"C]]Qd] {S|)XcnI7Z #\:>jҊYMOʀ,@}E@^$KS,q,\](qdj9o !5@‡,Wwr&F0`JuEz!%#(7[1Ns eN._P=W`^[l_Ȑ-]FLi9uEttT^c+Se ^5t>pcSe\/i:W K mOt%Kב9 6+"lՏrO>1^քmiP,)}K\08(@\Q/%uK437q2Y&7%FZ gяoE@ {G:E9Y򎄶$̔DJ]]fbsUg:6UY;n$R`"(8`(f!'gS>POqt9Ǔ@?+b8+Qڠ1MeX2 C!nLmc֪~6QbTae {`:W@$%(5 ʆ ƒ,Q_8QzLy_uQX9--RRI{C"b0\ZFĞKx-' EZ; eqsSAk^M2K(Uʋ24)nA8~D!$ hGS? ,<<(:R΀"|wbUh>ܫpwa'7L ,`3_*AP>h=8TQ C5T婁"mE媁ф8t]TDHՃ T2c`kq#NJNyR0@T۬/Od뵜~^F@i1V`P%ePcO)E %e<b qRGhiݳD7;jJG ¶@c :y A~21MuB f@bC\!wUpR%&oZˎhp(vk1c YFƀ^ɾd;LӲy]>DHpuYj; EX)B_90OEl:!%6$ے>V6hJfyHpUAmv8gD2&d/Or1`|p9=Epd(nYx0Ul-}"#Dh&8HPQһi+"Y> XC ?sǒqP/_a}5yW݅bj2*~k|{SZq5gĀyCQ :RQkl/\~_c:dLʞ~)PN*ysՠxF֑{w0Xw(OxP%?EGa?cM~ D|PQe oBA1b 3 GZK~}X[&=`dOz*X!g[~ŨG*βJaP;/bWO|ꊽLCv{2;O#3%*PS۵]nhH~>#9} R\zΒ}`Nj]ygwUzR i$C 9Lb۵z8BDU\A |x]ʚ-BZ+yRHYRZwMB[_ j"ŨI.yNA%Ng _TW6 'dt )zGWdFK3E️&q#}˱7/ q9~~+:xѶO֧Qaax:ˌIjگsZͤ:Jx\N?df؄VJ `Xڮ} Y[E=΅KN` 5]'I_0ͮ{pCYwϢ@~=[HٴATPQJ G-u+<%eSzT*} ̗̓-PF':+ &ŋ$H]"PNHY* nџxN*Z @z$!&S'KYQN7($R&G13B:[AfNiI <TkaR^a} ViH Q4rcS,mN8O +aYƅA7¤n2TwiB<,#7ܔ(S8c:P 0Y'=Haz6VjT4?Aj=c̞E4S<Yo/&P->'2ehU ^^8،pǖޝْ^8T7ߝ*ql;t) f)^gF*UfAX|/}O-f9ZSiGӍK?ihʄAnx.Qm_u)x( u)tκ\1HT@Mx v?ydgl^ k?i$ Rr09U 6.?a#`MRKh=\? R ^ypc.bCeh;h#6TӮXmWG rynpeUonZVw :`::V=?ւuV-t 9ӊ3DΌe0RSg #@v$`7|W![8e &0$ >ZE^/^5aTLkMrӘK ^YF=xDwi,FUYMU[zX˜SPNAR9R (ˀ[zIZMH3*;;ܗ+  Jg:i G]瀅ayin͑]#[`p(d#XN\+ [7߂>\-4c 5A yX6V>NH6:Egխh^m Rf I PL)U;bQ(:Î!XD<BhTrً1&A2 dTQqW QAIp7prS!M +(9*HB4хcD\H,FNBW{ʔFu]2E}}pp"[N#.0K"&K(0.Z:')-LG_çмZE-[eVHbDQIh##£".Y yPإB䒽Z?!er@ςtƲF.`7MR]UTY1Y aHCAwab֒kMb#HQcFJ30-] dc $EFU[QOm2EѡҐ]cE繉?)8g}Y V ,I*siigI:e%ۡEI=nxIi% a ив 0;LbfUOWX5lќP؆`55UOY3 ~QȤM~Cp QѨ~"BCdWnMfnC<` [NIQKB[9Š@ګhn?P=Gbӯcp?\5:: tUUc+m\n5V֌F5\j|r'rn#KTPی~㋩aVd5ML(lzlj(/cE]^Rv2lHaӵ\r4vTmNzLb7E/0hD=oΖf0%6[yOgv^ HC꒥ZvmzK>7CQz.1EٌwiL^m݌,SrİIiMrіMlL]RbE"ʾrH_܎5f&^J}_Cs&Tڣ!|Jⅲ_ Òdi%汲vq^CYOnBK'`"nxgHTdgnof}W޷c']8WtE[gAIL="D|<~q/ ؎WTQ4e|Qtce!D=#{ny NZ]~o2MЂ,!,o2cg4oAEO0Vzѐ_ eT΅ʣӆ\|>¦ҝůki^NYbSs]^Y (yk0ͅQ@)"EJN@8Oa(P[򈒆zpqE+O}h@ =&h\\MƇnAw8Aͫui4%W]UV4AP௥C׼0)tBQ(߬eBLÿӤ9kvˎko$N!P,.r/-4=>KOY4c6LWv}eC?ˌT{r ϓRp`=AޢΎsι;C/ΚMk쑇1[]y5OpS <׸r+>qEB sMo(}}[\!Sb!AU33MR/ Eo3&,, m@a[ۀ.=TʎoLB6yP<09ߗΕeX^OEN،u% >]%~'EB=X=PBu3׺k?վn eku%@ubSe1VA_S!,7K.igcPW` Z3ʋEEbT]{eŊ&%9oIsƞ|yLuo|7MX&U*֞ґSgJj,x6\|dO̝K~2s1l1?tb LJ |r,<&JfưRo~r1%NW h5xoXI?5l78.=2|cC(:}1M`/ Ŝ6~vYS0w,z+2^cqM(D$!<NBx?p}t|bPOYu&Ÿoez? A~ϳ#IB~#rg5Ls(Q,ȣw=r< c |{[.X \yrL8ȷ} B$ '% AX4DA4@(ERlTl8?@A r{KJpEC9y[G=p1/v$<' BVe<9cD2"lJڜmNK$1yh`LwQ[bG#u-΢,Cp_ߓgKƪCYIĝO(#AOrSP0f 3U<-YQ?fN ʅ|g1X.ފsߌD ʑMe%>í+ 5%E'Wr5%o`]9ͽi"Wߓ`uk,Fbo$'";/'19 ^e2a;O'O}`w{2bz? N'#rb9ҋ׽yq'5D+wd6d׮2A?ߣF=8[eĶ"!{mB4ZEU|d(9jNE-ZbpzWu+vz(ec2P.lۙ4-5w龦u[)Bu $WiT&%2Q1X54H ~GϰFœR!H4Tđ? VR#?ige|G"F./LVR7Eڬsǿ8JWO$2D{ۚXio}C$Fu<|cyՊ%%Q`s'*x^`p&ijxȫyn q0;PI*u6<`eFOOውmFyX-.CC?j:W ;AU`u[9 [vfa*l-aTKԗDtcJJd)mklZgbSɅµpФ+2c=d&޺nDaࠢhH+Znf sio&07AQQꋪY4 #ׅZtP|lLErZ `@ePV/UB*Q3DzSxuRVt5tzq~/Lv uu;|PVwMe}7yع2Bt2gXYLX]m8lN3< 'ʽIvJ,աZO+S\hdY@[r׋ro_gc@53Ue-s** 15ԙ[ݒ2*ڭ;%vBH%t/M8p6]jO^e&- .Te` U(܉̽?^ MI{%sR܋z  ť:ngKyx6e"S= Lן'\zqbڊa?Qœ)إ n6Ԧx c^ ^^qʼn9O +3y~r83k*PIk\J] ;j;h[&2Q }PR20y|N(屮)P%g:;K_^9DcB4I~Sf| o?MQr1vT,6Ux_]r#9,^QVaO>/|TX4D#Wz0VCʈ*3oRV D⯘Ld BAnso؅ n>b/^| n^ ֕浵gi]пߒRW1ěpѯLU߫xykq^s¦TV5 1zMN8)7.`A{?F] ,=B7؇U9RW@Sջ3,S!M5BٽB1 < AB;.媉å "RDS,#-')L\fnٯoɋZDzE-J,GQ6B9+ IVG(8{C:XUtxpB4+{y9g {tBst_Q*qe rliwyvƛIJuR.TzFV;_ia&0`ri] }q~)yͮ~ Py%H*Ⱦ3_'z |>In%+[J<[%vQDQ:jhy\Y %7|xsּqHjF5%"J=\@i\\B@E>4(^jaSnSvnnb #(55Ha\~~LPin>XT> {ekL-slAaݮ&ZF\{D39T-,k+|BYGz\n7BYVj}SN{T܈VRg?OYL7e/P O5TɛDG[yC uy0^Fj#G8}D?=6s}j'ʌ=AY 除=ܑ'fZO0ި3<鬝{N3- [}/c_ns/N(]kd7O(?ero ӝG)-/EE|+Ռ C*U-.IϦ(ZeW/t?~t_JL=͔ IP/ rb\Y5 YN j ݑʽ"~!WHV[BKvRۣǙJ&f~m얓Do Lt*:fiyTG9~bְ>iYF~/Ǥm)^- $f=K3X}T-lR^J,f6-6E&?p-Dx)d*uOW*Ǔ02"SPu~Qoc9{?t 4!Cgt+rQ4?nЫaI4fg0$^X们4WRci)x-?򌞑DgndjcbCƳ)d_L/f݊5&kfHcQ{:.ZЉ}]9[(" A2+րٿ԰􉳊Ga1|-Cf.wZV~v+.XH_ZzN¥Lh#OǶ MAU4#m g-;'ϭgȏT>uG8,RQYy؁L]z:óW971U̬R tr$P曬hEeVH;(/vbWg"N,u+VjG[ lFHܫCN\=C>\2+~Ȅn:qH;¬_?7:~R2pxG4~ R/HolJ2m[wZAhidVc3{@7Hjv.C4jInˀ}Fe1,Yn s=)yӂj>M- uLߞi܎h_t|J<3TͿ=>gP7#bю~ yx k%BY{vP4F[^uk\N&,cuv \y..섲{A_J 6mj>J6C)TY栄n< OQ7=A^{i0.@c!>WPڭxu6,1Q:~"8_ԱQ{`tt157pHAMe#|kا ѳ)R7n#D!ӻ LG^o|@E=&_5<֝~y[赒A1s&+a(IX e:Q{U(p  ]h)(NwA/} G)ۻ?i~,s*%LvDjAYOҷ`R9 (Mp }4[,gA!ԍ hc KȈD %'U?M J1 $ͪfQ>pëwn( #&66x]n{K/>"_CV7!(ڞF/<>rWP˂pkᵵ,(Z_ 8u/BPH~ -mV'ʏT9g$dxKOq8I V!6c=׆s'ed ݙjeg:PAP&Z)J/a4b\ԫ5v@5$#AVdCų6n|GȢneE9)|nڇIE ufV2ir} ́rѻBoQROS$CLNĴ!"HBߏ _5@˖'isSI aB膃F0a5س/bi ,CC9tc]O2|L^$`w7_[ITR!US,sZD"[V`,NY2\C*9+K ¢=Nƒ&<6FJ̣`Z#,$uJCQxleY]"(vʘ?. n H v/iaF%T-|H}7 Fk7ťx@ekȃ-HURݾ[|~;l[UBZG.(.;hZB+0?ށNΠzFZ` 1j7M^_Gk\A:{_}\иvJkfvSH<)zэgUEb"p_)GtIVxM:Qa61p˃@}ܬ1`xc3RJIS-*8AHξ$OiBVz(R0aHv,/a),I60/#OCb?Z4Rd1Jh?bJc;n80w@Tq}#چ;i2LSzz)ӚX}kS$*>YmFLYy7X|7=my 'Q4ІXuiŢ%fw;z]z$ " SYF/쁏)ZUM}φfh0ڣŸfVm]u$`YQV?Z{ϳq'j"6;ؼUZXG4T2SxOZoMq0{x 5JhL,,% &$]G6%8nv'#쟦F0ekͺ⮫Le\F=hk@d%}SRnzRSr3:uh7XlKpɼ%$2ˣ0djŰu XBtDf|F9ȋr4*,Cd!b-ui2xgWcꋋEw"#GХeHh{\}E-e3=f5 ]E00FfF4++d T+=̞I.MTJe`EѯeiW + G6 H/J@Ȝː9$`t黨F>b2EC]`hLť.ha2K>D&="Zm!ِb.^D}"(O>TcXr,5.51!K_i,!{% ?I,oWKg-嶃9ˇ`PVS ⵣq21ʈa %])d-*$mx_Q0"y區~CY?\C"QYSQb/ 5+8Q*u1 <5:<#`qEAZX*gc`;#s`vm=|#\̌uPF0\$Sef\RkO>_UyWbJ.',QfqӢ@^5W?InikDYeTo5vų9VCگۏ; Ba/~4Pn Y8vT-BTabTn :l/[=? ;փ7[XYL67 :̃_V[X=< NIz+x/Qe?#,V!0cn*I&3C w-YOjF":|18z-,ǒ~Gό9YZGcz 9C^mƦ *I2! |gP$xܟ<9ԫ4BBV+gy^7vS/"TAh왝`yRf7T+1+0\M{Wダ0O%8uP( 4/tt\:]JJf[R'f9Ի|lܗCp P0~v'y1ap.c]mn^R涺qcBnns.5~zSO{bzn(߆p\`@DdʡY8^:1Xv Ӳp˫O8`@JD蚻 ,3~,GPl`v'ןa5D 3I e'ղ VeCH.CR+D+1QH)dMuc<[EڽF/)o [{Ӻpczzx%X9lF&'/VI 2[ 7F%wX,s,%`DA#I P~FIPD!ʮI-%P j L?Uϓ_00PmA]H|L Q4MR`osOJ ȓ>11yY<crYOjٺz].:G ُbsmƾ)9lOFٟI 8vAhp//T\c9s]m0õw`E7|1e4S(km1utVXػ_̈*̮ؒэ=k%"(ݠBPܔ׷֨t>)V<L4lµ\ n\߄3SdsUEfhʱ{ l-gaXwj {۔ę>?MT|S_ vYvotXl02h{{dZж[ד|6( *(3*VllcGFL:,DVgN^mwf>4y.7MH <_^RF̠ayS-)?b>'yS(6~xEn4ˊGi9*3qOϧ9;%qgAڔ@=)jl#66 . Ɨ.rݡ8 7l=UѦĩ OC-{hsQnO.I$lؾ1moJ]>Hm>'.==Oq=Ӎ$=ڭSԒG_Q=:&=:8y%=:66eF ʡGGңCDGGУc+"xqQcMz~SR>=<F[ӼFը)[>v&Z> 0(q݇E[?ȢZ'ТТ3!FxlJgHhuv8kz?qL6`r' Ҫ*_;+A);RrZ}Q2:l^\;-{&W#yjt'fqKy U.o3$L~R?UZ6.I=(,OzJOp0? Ãpeed&xݧ>61-?I`KrC-/εU-4So+pujReϣ_Ԩnº85)d=CfE~cHYmfb'%v>vXAT{ȧrVG9&|߈mJ/{Dt39+Fbř%{* xJY?FzpNH nJ޸'}o>S\i5U?Wr{6?Fz6]9u،@Y Z>AyM@hxnpN0;@X „K1yqy:4By'V7z){70w__.Gne_^-)¿Y]w U7BV*;WA3|PlS6MA1o!=(Е Q)U=ёFv*ݨ߄XfULEg# O ۉ~zt9F?{P(8r`V ƫS=:łC7":Wi 9.p_,Vj29~G؍`Y 4 @z}5v\Bӛߴ_WIyUENJ٬WAyW56W>AԜAy)t_? v'<ɁS~kDlt_EE_o=HǠ4?H^UPW(H<:Vr|u!?IǴgs/.V: :]B\MMśP8bgep1ڔ]S$ $((x%i@cB-) 䬤aC6%>f,)M m82ce+PFs~ki[#vLC˰z@+cyx(XV`PDVIߪh"Y(ݽ|QYF0eC"e;l,+I{ e+hPb> s ݕ@ [s0= O3 i lצpf(o[*P$ONhw;I7b_!!%Hyޔd:_(y^R.Z$LaPJ| #yG3[߰b{3ǮelQC'} T+Hڌ*1Ó'KskoC=IDU/A,UlL TUW-sk,^fRw:*oOxIxx$/>s'@ **vB˜~e/ ra]|:Fc NlF#nL0TN!g̎_؜Jd:RqӞ%@m3cY*+a;G.L^wb6Ěk҄MjxdUmYE13䌗bՇ k+zjqd0*ZVN+>"ڱiɯR@J #ױV@ H7?+! U(_Bء[USfH,o&Gz/,T`)A! Ov?I"ysitrע:\1)t:*ZCIIm"!vpU9fx5b,B*J \ @nǮ`a?~1u iZFe[a\A)A.p,ޤ+(/K O4*66nSxF*j%VT%T9i&8C rJ%|\Z%WT㴈W$}_0Χx2dF C/~`N;]uhPBJuJyC/ 1!9L6JU\{>TIU]0XqE-#j\1*bP1*eؕw5FOm,aH^,ZFCQ29QP ȿwR[m"x$<(#0ŝ{ Yim nY 4CDG^T<@[~%rwo4mM\X+suIM mIu3;n º4C<tG}shoD<B@+ޅ-l YP&o66%c0tQxw9lVqiktͻ 7 &oz|oJm|@Hʒ_4kG*7N6V=UpWiG~p6RoEҊW1StbXqfZt).Ÿ1t?x Sh~͏@x/GGRd~ #|XƳ>϶> S<)98؊^Ǘm}0'1[m}$r}XH[>4u804>8>M|i~4W脫a} _!m#)i}LB'_yj1l؆184Yc|B=M/\[Gm~D9̏)u Jc < c^^ ?P*DC1-лiKWX y0mJ6@Hhpㆄ n XJnCkgJж? W0@i Σtڔ[EU Ġ 3JS -A:QVDo6z2oTєBr, 9n6rĜR?Wg<[<6n/]˒$hlxe ɨC2 NeX1[A$|s4te(aBnEd@NB'ڽ#.QR cPw7 Yt?BZ$Vg$91/ udD`+#8ء?h BZyɨǙ{!w1M=9(Ookik[}Pl?tzrrs]>?~gNAٓA: ,A5Wg<*92>A"),k/9X6h8y7\c&)oj;0R5AХ0 nk6H3!,[_I[xϵ ݔ̾aev}q۲/0[pcQf[In2}Θ,fWRٖgUNO KZb\ z"ԫ|(&PZ|$9#w5b c)JWLPx<*\1zz#nxWF :o!Ͻo) *;d#}޶d ϔؖn|`L򳭸TL0`_m:3(3^IDQF?72OƘ /=np9erѽZAz0pAlp廉WDܽ`HdRR2u4 f`;-7_,w#LB|CZN1#LZ_kApQYvy'Ϙ*"!e?E2XtyEHsSv1^2LP" ɤP;!{kѸ.B(s_^[!@mb#2iP9^$;^d/*"NI@|xJ|iu4aerEċx+I @`KQWȅF8 Yi#xPyAym W`m{5Pn@Jrbe*}!tw#т&z"{d1K=~A+ !Ĥ|.EO`w98S}ESúaݛ9O6ˑnò"4"L=H{mE9IMP&:'eڷDMRF/䙠(ltLKKqک):t*9P9 =ru9ZL3uۯ<)w33Im8Aٓv@dݩV#ES 9gdI,PDb:c+m %r][ɻsmlqY4xqk_QAj6EGhF\ FPnΦb}voYxxRHT!Րiۀr)NYss~ѳi'D+J>"3`yU윺-\0BhcAp,[.9 E@ F4=QKI/Y4/]jf(5-愀Vޣ]Vl2YV4hH!>($σ؊ϣ`7U2)YF [6ד~W Ip̍usw6s5Z!҆?Ɲ^FHď`nP ŽFSFsF9 0g07xs`^;ésSe9é6ET`hs|seSI?1ٻ_HӰvG܎`>ܝFܛTfs f^g07~ܝp}; 3ys7(;1W`xz88`n wM`n01y`n0>Gq˙nK(7lF|su+g̍ :^`G;)(={tH'J%!rrdC1YXFofDe ~ =/F<rß7[;HU5_lҁ'G y.(g=L5p?߂r 3)3txp91ܔ].Q!l& =OĽ`D[OF9e D42qV;|lbr~qְ}6i49e6q] :.ɉ5{~fdOnɔo+OYrJJX:OgIڔ&nW#-np~Q,mT߮5;~M lSn:񊲂s:}4B/tjvlG4IټjSN۰46ςr˄UuW~M 79ZUp\ j.vh١o I9FTb,(˶;N-K]h\#:T'L]Dy苩**r # Mȏ0W6q )g'[1AZvBQ/Ft`~WFb7c#K" 6~mdl{r@`{@95-%߶æݍw3)g.{-« l!t՟sQK\]$e/3e_]l.Pf. ĸx+baA"c7$rﻋ1 P\^|͏#.ExqPcI/ڗ@. Vڰ 82xƾ5|ǁ9ӑP17뙎M +uLez Ṯc%sxuta"s?ytl:d1~".@e;4_ϕ7,^jdo1a49H%Jŕ 1Gq7g@UUEID_xPA(YgnVlaz9NXvXޓ<]p2|yUP ؋_G2,85DZD?(]dR6g&_b9Q3k{J&EO=d^/*^^ӂNM=ߺu}i^3a;YKؗ% ^HyeՔPbJ{p ~) рWm0+![T-Jr+jc`u/x_/}&ꋠTCX)EOmR76$Brx"(5q\I$)uSQ%MYi/o2YуC&epA "]=~Em~3YVjόڄGBEa0wQi4v݅!Qe(y%ߋ1Q?:M/bp~KԀ?TBxYEڿ;&66l̦̝:ȘIK\lB9h/>|,vi[%[. F pMWtM8kB*гj!)-ԥ1 VHl̓_QMcyMh\ה{"ȷW'V|8T0 6]zƙMͩx _b|yUR][( Vt]_CCKU% FUUQbV1ϰDF0LiMXXZXq XYvK˜HvyT9<8сyz DghʸFtTnB_W[+taSrƔCxtr* -r{4(\ OSDgD2]vN'WL/Fe@!e0+$t& ղSG'WBH>@_'WD~Qm )f7sBJ嗔1 ȇfν+ ;x!L:n'6W~2=5 ޗlYE!;ڞps1GIx h#m<6? x6nقx"u:71GUl˜\ȗ$LYMa(rNfleo.6%vF&R5rm{oJE+ Z36S%{Gh{̚ \V O\oq+7צqI[,GǹNPÌ]mPZmN=oH&@/.IgfBuWZ]lW;Y3A"(ڥx:.txe`d:#Kal=8ۆ\OIN1ed"?UULSU 7R}VVqF [aI #-BEXg2, L, {Kۼ>zPȚ-٧YQiRiJ W6EPN YFltΤs 1S88~3u']{QSP"&(ɥV-ޟsPIJqJ<*\Z4w .9w VƙSlO3TFX(kf6DSs9ne$b ^`dnr BIiaշA6.cjӆF)*|Er06Qn+}N6$S{ CJWJk$(Eeރy'|L;*|ddY 4Im 5NH9M9E_I*LkW n&^TJRJz$Lޏ̓q3YmNޏAXD wϿOq%Q$eE{#}?Ͳpk7tW\ C3*R5I _l ?°p\R"*/5`g۴Z aQpB̯JGU}@<(PW!р.H_Иo H\(L1f,DBLG5D1EH),UC$@TKlH΀ RWEp n+woHr2( b솄>~:AfYx<#,iG.x0ӌ50L~ExW8 1 2rq*sRB7'GȓEܚ/ehEa(W{펱(aXE!+9zsWn"$A(@׃dT&e?d9wz{! bw|:+C~fYERًDq|o7T%9/7_ msf t5Avٰ5%@CZ7a1Q)O, 7CFTvW#X h/2"VAlz?{gxH%ߨ /aW38l@! FZLB (qH4݀lyFQJP@m" 80W(V7~p@OQT^2&ΧlfܐcU9Q<BIIOC^FM#SrETl>uH|Exȇ`qQH H?ۇL?bvC΄ ';C~ 47]v:60`nDg :t+ 1) !W* e⠿#fgh#0k[,>7o (9왓zl\2#b"qBc.@$eoU|"얜0V_7 nz{ @뱠]k|]'b{vH5,}*㮚҆78<}j|o3"H;ɼsMaտZ\̌b_Mӑ2g8ʘP_t, $L٣, 4]B/8Hݏ?MbK\}_7K?>БaN1㻴Lz,crA!ˏL~5p|XQEE҈s& Llh<ICN ~xIv uJLb1QAי?{̨q%qQFt +6~ V/\r-FZ &ٜ_z7ͩvs C`)98b˓VҍD'$s[*|b,Mt#9E6>J [D;jLTKdRO vnyI=I8 ̼ik6m71"R~č.ldreSL5 g=X<~Mva&m=̼gcX,K@SGlg2HO2I%J#JMAilBo[l)j+y,^RIb<i!'4$QnѕY,C#C)4y}}C]?? ү׏CKP[ﳷ5i~"|k4%h~R=MS&k]`.31.T7i<ҶvbTşsҵ FJw}iXˡX{$,Ns7 kQ#XIEԁl|–1 ”[in55|{xo_m/ d&BvN}#'Ԋz7j0K 6^=xUObE6)W:d'MYJ8| z&ؤ OP2;@ADl(8umNG"@MʠțS* ^azV8?wl_z cjDęWGl5C`N ݶy-e%쌜W79bܐi@FcM;0ӒDm\X)|99p7Rd'TYgӇ6h.L7PpAgO?7Z6ގ2ːAC@@#8# i0&[4zFp ,-9罓l7nj6L"d;E2ˢ?Q*E*M j0㾉wEA6'a!p:Mz`>0YBp鍯Y5]]cVN} iJB'a#g%¡׆G^.y&-1@,Q7Mno_} Rkд V_%E`AspB͹A[Dd7@({suhMGAf\wc^os^qDjI#4![%Jtf|Ҙn@_lG;ԮDF%0ҝr^^k`dK9Yc}F'h^x5@{ZK ?_iAJ_&)]auU~CV.U.O;o0y~_"s6#Iοn X\85BRnLnJ&c޶f*5ɺoph|5wԲ Oe%PB ;K2J,Z@XCI#- ۸-Z  /=rSQ= 4_ Z/.W (r堇X4fWv CNpKԀ>*#Љ慰ֺY7\u; Pj'COJ 肗yUPz]נnCڲV n.^;pS{g1^Jxmm3f$fV 34O Q7C5:pi#D+q!.}_R7]mY%/AN;Jt` ]1hz ])CY֑W2kKσ:2[aU4f{?}<T> 1+~.BH97#-n ƨ5>Kw#Gr7;-Hz­>B.B{[W|t: m3Z| ֌&j)Kme66_r[ݿ0eh8R㺉*u62̆tfDz2kYÿi]K`$mp4͈31j"cYB$aCzX^5Y2y\W;־j\z2Y0 %ᢆh15R aPHq&5 =mt#0XZoA <[˝Ԁ u$j0|>Ma(؏Bn7A n9$-ج[G06A [m"ͤ /"L*&.ImL<d="~6d W,{IRlTC=zeW@T\d ,Uke8=L'ƳCT~-K  A1-"!RAM=NKDæѯRc3%IZMXz䔙6ebܖ̇2lɟw-؏zMcfp}DvCA+n|>MG4g/:6]cq_E~90C$y?,On?ByP25B~"!],[jFL%~e]^L2V^#S0ϕ[\%S_pG عDU""DZ? !Ez2l%~j|Ǒ=u!z D!qCyl% 7P[[<32gهGLOLmwb0=b-x1S|-!Np 1~PPQJ /:b fnjqMױsQq.4,u2N̚s2Dc;RA(ݙK>+ @Zߘ+@ˁ= RRryD0] a8#qw\;@ i 2i*˷t<vb) P \9 ҵbL,_d*>0W)G!8ɉ`3b8(һ7 LL³3ȵ-I|U8ޗ\>]pW"6e[a[E\ N`2=$R&$½+@&퉳# ˿VeČt[iL<+}avX n$$*/cϺpŘz1hx:{5[̓R ׆]^ gy&[~]!/5P6n3rC+``Ir*xSg dڪw.6o1:ZYγyh`Qu`D ҥ+Ϧ&~dP81_M e)C[7%Dé̚}P'qȨ{f?[C /x:f,$H Y Y(Y~0,ewRLqha-P N[mkTYKD р Д =~aG*9\^u4Қ2AAyPbl !{C B; ^lci ]K,Fs5WN+Ecr=KeE&L☙_DuHM31i$pa%! \BI=O-޻3V4\DVh64g= i0'Nn:wMY@p)p \y8zfs3: 5iUJo5+ ٿ>Ć*-T paU&B2NrLjq<+3{ e;GbU.х`\ !XEza>HVd쓩 V8 js?n>庖 a2i/u . xWwLǝXjRY5p?}-~T\Q1Z&In`>,uc˼qMAb~nE'3H1QMK~XI=xM擓äu,aG'zRo -śnZh@5 5zVMV^U^|8֪϶ܵ e44yAS;y I~+1ыG.}'35m4"əNb'V|6?'bZ\t~LrQxj|ZM/pά{2LY,Ԍp]WJE BbsPݪfLVkd^"ïs݊'5?[k2JH`HӖ8&nL[‘xK!IJJ.l`)4$+/rS|qנFԖ)\H2棈'J92@# $Ppx*Ab X @\JM<'IʂbɁxe6U;Ml'Z D=titiGȕMP Jn8X3R{5g&$8 <.5400[Y^ <S'&ًLJg'֠tNRM&hx NJ' ('ghf{48 U*SV0e!>L;L-]C^G'5 g:v.1v`Eĺ~ kdή3f;PyWjnu敊)~S)/r!c UfJ-3lsJyZ Sj(+[f;(0f 陋v6UMz ;W7R{Ԩ1|:1t.߳;E |4^b$Hq=7I1ΦӨ\CX ֥@.C]zO^DJ'ڠAc^jx݅8MxZb -nDҤKOU?1abkh є){pWkPA2})\ u2tMɿđN(ӑ8RjݨIo gwW1`'j>V;bII1+M37'刱9 S mڴfTOL@sX.Xܓnv4j?^>'A8RNKviaHMnq{*N x5wI}d1P89s{ 5 T8te\g#r&PR^MY_Iү1-V`׶RWn m |E*_ŵvvk A4&uY;"WXa/+NKQĔu?j B<ٟ4uF\x(ч1mlb̻Pew%y6j ڵSd=@ ं eBӑk,OGHaFTEϲB PXt kw`al*rq]eZPJqcJdH)C>X}&WҔO=Oq)@ұz 2iSkchwyp~Cҭ\M%f`Yӝ3:8 -cJ}TyBNzTBc"ϯrN/99^RN'y?)SDٿ{%.SyݖGwRkQQ]nZ4r *Bb7ydl4;+G3eb b;(60 x"D:4@CLjW N}}6o,OF11a9q4iHk:eIJm1T)іxDqNk#].e`LzUC'&k\BS=Wǒ1 N+;`cNQ tT^("2UkA[qV+OtT(X>Y$nZ||l3]Sc./=;Y̬Wl43)C8R֮suQgC :*ȯESy.P9fÙ[ bkݚ0?8y/_.3|{- ndq]d1WBIdE诘'C\t]L6v>@=#.r*`5oGx{$`%F ;J=^:Uw,XEO>hhH '2uU>cwOr6+y.#K5QNLщ՘=^WɽʀY7$f L+y5 y a8yz1ǝƀѼM~IΪ+I9CA;F+J7P .IVnd6t`4aiNI G>-Ⓐvvf}71];C`<6`DmbU(-R} t8 }[PȢh_bN2f{Jhf9ZZ+ay=U:i+Ω$_\aA)mX:Ole{ 3`W޼L2s_ҦX6pXsW2JuHdz'>d],z I7tXhWS(^$IN9SN]aYciӖg'5:ͪ7D.K ~6P2Lf'_(:BEq|( [8;غ:a:ȣH#.I݁ W^A 'J CT̓\h[a9}`שNvLϫxB~R<]рD@78'1dkT@z 7Ի7 FL* 2/x@`6JtUp1rD# DмF|I~w#h~C+T̫BmnO^w4B')t1e3 Ҕ#数+"w`t4:hl/c>sC'@0ޞy9<.Qt`Eļ Fȼ͸1/W%3YA|/"@pp6p$\9SEȦ`U>ck˫N!6 %ᰉ]ÖF@'0}<&<8BtLJHGvNm)w#.|8NG8mi5,V^:bhS-au8`K;i^S'/x4һ/U>moRXHة%n2[.)ǧeO9"aiHL׍l7xDE]aMFqԩVLasha'Bo# )Hp]E_9ds .BI[nɿMފБ: qR(Ӭkq,zİJg˞S%2mQ*fIs q'e񀼵ǧz)x#UGʿr ;SxVLB{{7":2><`("~Y]eb) ?U*6hv\A4i:%yy:;kkKBbq*loJ*lYk=E̘]UvKrJ~AN%眷S\} ۯ&8-gMITo?bmާSytZq L#eݔTG7MZ//BsG7e^ ªuEJŖZvLł!a*oKMn[VH(1gV8*~CbWr0/@K oxjJ0ot9T E;A ry:3`[D BYź(L(txwkJChtu8HWi*$^&$;Qc5A'=dq*iVhL=KzW|]BH1¦]F-7ƑR[L Б8Kӈo@Ry LFT0ko8t3U=̶`$kF,П9(O*32H*#<.p|mI DgT!"6j0JEC ,^Lˍ jW㤆;K Dr. jhaP5;HZIz9HVzvH`2(W#E 8UFnפ".3gtaJrW~x u`.'9SGl-l!1E+*z^웳 &\LSkt#z 78pb:y5U8Y3OeUXJfBDX!A%E(|)`2Ksv)[+?GC 5@UR Q58evLV1@CQuM9!ڔTh ġ[jvbzV9`; -139pɖ+]c]ѽgem#U,/e=^̈́sLtqcS$=iSu%0UJy{ڦ̽nӅ% X’Bl(DKX^Oǫ`aLL՝\'ɕ;.Ul!f#ɏ^s*xڝ+ owt=zha6dz:-&O i Ο'3tf́{- Q@ViU,5tJIZ~!S&iҠg.7 !N6( INIJb.2]Z;U+IJ"oRUtCbԱm<MC< (ءp RJ{-!w%p@}(*0QNx"Z@+*Coz~/~3@ ''y7Jdپ|`O+D_?vKn|7v#geҝU~>2Vl{7$BD S X*~Wj4>;1 rIbw3'#C? }'[\w{Q%Q  /,F(.SWkAc.$Lη~_Xٵv6ƨG???j4K!peM-Q q >=.SJׇTEsmDuWק֕$Ț-eLײR($NJC=GU Xs=? ⅟Gs}N-p^ЈCIA纖\ Cd-x`OK+wFl;)E6\ח @ ס`fZ\#= 蚣] c*ZHWPݝqN0J MqA+L̋1b_nŮ}qVlJM 8\2~8y/VWG6ɾ}B8Dv3Te V[׎+-v^6u=P%WՊ)&~/1 AR3X=|%<2\ |- ,]IA{ǖ~/wl-N~o=WCL+=¯ ;_}gWwE8*|--Ly "뗋|I圬z~ZOי1_+E9T~9@φp90CcRGJLʡEUյ_dudT4DõPBvHs(Ռm34S!4 W3]m[,@ % '"0/FoeʥpzP ,d! fR^TD#O*mi'mS`d22M`l:pQUꕠ2@˻3Oo1(uJD[Vs RIh7Ld2*ޘ@秊_d:gݞ-sxrԽ]9-^FVvL Ak͏wU~ }l>TO _22~n\/[:0ȍHh}50<7a&ͥ?f+"iC\| k/Dh05T Z+SxϜ eڊxs/d턻H- EyDАLU =m8~^mE{mI7<Ia > P>gD|yu\[Dۮ!'6/lXEWMv(x ,h4BO]y+ܢL:hf7vCtABaJVU 4-%5ym!X?Ȥ2NWCޝ5_Ekl^h߬5nN߳Yښo;lT̏{ߴmF^^Y:@k=L-<c{ȡP<]pm.X@:`Z!6_Alexkdw~q `,(jyKH=z-ErG;gq?oTwAK gA](NwfVӠshhv]9 -g _ݳ8C/RBE"zTYb-EniM4oJZ~QPfQ7| (g$)2ux+Ѱ;9ks7VG74D E{t4BY:`/P`v0]>,ۃ?<=YOcvx=oOwχ˛{dZ/\ tt6kg`><!z6|t<{Dt.QqNqbp;3's mXr~j79>~!^kQbZR47bWWj8}荻؝] vcsvFGAs& ks9C؎{S 6764xo衏mo/m@u:_,ޜT7gmhonг fMuF]{^7;3{\v]؛3 kn\qP/=/k-{߆-O7lӊ@b>(N?^ɴ#^?"vwoNdKjU8zHX~w([ޚFݖ }Eo>6߉>69 1JJV#պ|6_%՞Jy.JYT{lSJYV- 'ˬ0%"DD@6?2SݐZgrM ׺[|Xh,R-HQsK""s$cz`ĦDUiKY<i=7]QMpo"(W8ae0+Ya\L~A7+hpO#~{]o;?I+w 5\VMΫ痼Qߧ*YZ*熘}.ލ'>PD}rn.E!c2c79!1!3!M%4?e9}2!.6 .؆`V\]W%.ӲFr4P FE6**kaϡ 3;W7@Zߗ˞H .;dVq&캘0C6UME~9g-ø!q{p%ie=1sa*bG4c[G$y̒IvÿHQQLrl*\IIN'\ wNz"\L5"'}G$$Nɖ<"'Ag#]lt99B߲sr+p9_{v^NH؊tD}{D/B'`']$PΖc$4,dtrsroDCM7茢J9hUFTTJd)UgƤ+p#HɏHԙ ^V)91SCK'|SNu)RvnZ^$]K4]PwH*<ɧ0 ;+=Y fIDѥth0W ݸs!;#Z{dJlEfe'aٍ| hIl۸&w e1WUc9Hiwq=݅٦l+#nzlOFf5^~fsʉMPKb7Ey.>+%aS9TZT)UR"̬ R,7$k}0}ƴSs\Fzi t|BWL_4]NК\+*EzX)-,. r IJ$.Vwwo)VEamxsh\τla%7K{grM%cu[F$.0T3}FK;,;3V6gU(y13\AK3BH9H\ۇ#pzVKbj5.!I-.Hg]XJRzX$-|^ T\%83j\.țHXICW&'=5s̮9Q7~(C*#y}+ ySγJX0c2!QrzС-c#@(<VyR 7y5U=k1WT@lNZ8 TNSqh_1nS6әFNubuFw6xdbӦW""r:w,!acKOvly"2>wD91@b%lfٽhF&UӅR8"ywU6gDmæE^D ѤLCirC6> %a[q54B˲Ldo_gl>su2*I- o2|qo1;]q>]NWBKJ0mǵ3RI$'>* SåىaAG. N[kIC朾GGjM, CMP(X˭ĿsG e-F/rF͖9*ak_c38v+69X5q</bcyU'z`<}XJG t4;~N.+g2g;{9^p{z%Mյ^$uD*%nG> *QLS/u:!~/SUjrlN+Z Mԃ>kNZ7o-#=^Y=D ݤ]52YƑ71aqn5&V \&Au>䤚 F~ y씺Fܮ"EE\uR#T@YPp~Uմ"z2^՟Fl e'] ,Ct"[Pןo=_VORkNuK=MZnm$Sf^G S,(TvJE2Hp%|G`SqK-#[ѽx̿74-5y!r΄jq=!kyC`v3(,<8(U38OZhb fLEob1\[x 3 zv,^vY&l{Umy701K^z$mB :x8$(STų\L߸Za6xѪeJo[LLͪZ$j\.te{T]MO,#M$oeDWZ]-դJ8pہD PUD*%kwzcn̮7~^4|92UQ@o84- !#6_E Bf )S{ +TE{kc(3jqlU$$[Ug4W?;p"vNgu68 xDAJKүsOY7ka$M ." XN(nʺ;J(E3$-rp:i:er|# 3038eJ^ZeR^̗#|kʃ.5-YEW,lݱ)]oD|ZVnZ-]qTfTxu%V`k c<З:IvGsUe(%$3xhו9&50KGIJ*,m.bzp;7,o-KzK9ّfR/'/>ٳҖ| ˯[;]7Cʪ+Ңaņ,Y ҆ⱖN 8'4p Q}f-̬BhjtHw ĺ t`Qӷ+ٷ #pK(t%zʮ{$dsfhSO.Ksr,W>zďJRΆoќOW uE6T`ɏpӖI8gy1(lfx"mߛ 5b"6^sk!0Fv8/G2NP\_ŏ,BVB@^6i!)~x1G +`Hg+=wWK]#eBlMg;.Y^zJ1P?G٧qg?FWײTSKR'+7Rpd'uS-҄a"s(\8zEb|3(U\*of D@5ݮ!7H=Gs]Mcȇ˟3Lx6?X koj,hռXf.?fϥVEĿJ'0Y5(ӤYYV]"\"Znd귆 u̸Z9InC-"΅߶:nVv9.nL􄺾dǪ'"av ^K0r6!hY5pӺ Q`hyԦ b 'U+VJE⦆j2mbj`t4DB"Jt^=r٭4]ze7|d>svmzN4OPqn],}NShbcBL3_Y,:^r24p"D]SMI{`pEEJHx/$5YX\OA?hjG㉎S}Eb ( 3mn 2= .[^8KwUZoUX˜ bUH Q9!bsܢe0OAs8Kwo:[}Jڊ+U*jdh bVBSq:W`ieG&$3 hwH:gnpIu(OZc:7)V]MTcp(4=c"ц]޽UknDY *xbIbwG:QL }lF*p~ _$m(r@ڽYHfuǷJiV3[9yHQ 5tD9 ZJ(fw&]lr߰UE^BB3اc:tI{(m=}6q!=QZT驜v]K.,}E8- WfW(qቡSKn>PR 1Nzy*ű{GSB;W = Xfl,gxUf ZWt@ c0Am%G H3:x1/ PJ`mqQJ݌H2lZ{9D]SYIUFM=BtJa%"EWy2b Yr%*I g͔^UqٜyP_ai`^wòWڟ}hBHsJuB5>eXnv/k9#B -M44Mj8o4?uK=]7H_wjnPGBH58t _mz٨qe{鬯R1;yV(aqAaX( ;@aNzL`RQB+C0:)|]Z&i58u:LZn7ŞF^YuԏX}B=8c‏xf(y kO(gtơGERˤGN;G|Z1PV BT[b}Y􍠶]X&:u:Jo3_ H8[pXחa9XĊ|z'viX;R_uUVaY=jS3ē^➊b+ApG{Oo8*U*k;˺" 7B&~fE+YGR[v ep\<GRnҧѥ>cUHUŔV.>hȴJ_2>) EC5=ꎸi 95kփ&)RţcB@FOqة9s`EU,Kp6.MM5.⎏ݯt^Y'˿Թ?H8}De :fX٦4ԬzNrG!}W0CU8#V`N!>n^?#li5oT?fvʿs2T9U K$|V_nUC-9 Ry! w SﺵAtPpx8,XN(R8kAw9f2]'q- B- >={O}c 0XNzRo4KFl`^iY NW?Jʂ=.X{VCJ(6J@=*z_Y:/74ӣ>؋rz*pIS `~¸sp0JѧV mcJ@"'=ϑaR 9xU=g{a)y* ݿN|%W{+%MjrO.}Y)d)jh?>2ؠ0vgޗ#Kك2{1wVʈsU$xR_%yx+|ptHwJT8˰> Zz'YplBZ*Ycyzެpjg{'٘\tDGAI#dGwZ;TjUy/V"c܇ GT  %"H>$GkSi0w~ƖI*c6%Ɖ='y1?=SsCQ -NH2YX|DŽ0-7%Knȱ&WW+jYJ"C]Yʘ0VB5$!E0-e@aH\1!!9Tf lUzGp4Fu# #D44;\2yfqZުߤ݊"4cꒋo3# gP~nfX}%)筩q@5:80n{xUZK76S}-T4Hm&ֈiU8k[w}54C}gԹAãbߋ jKᛴT}N]U2yfY+oL4{&wF5~8Fzrx6)TU=aJBR)^|(KNmW9p;E8h/;dϫ}bϊ73'EQUGY>+mAqC3m.zdE1H}#e-[ȆnVlX͟QW?ZbJޡw"_v4B"FJ7?̊ : g 8 Ҝc!-+\)*Su- *|(+hHRz%}(0 e0ŝf7ʤ>I\6UiWh>ijzF>\+;Ό|=+[8ւ[``xʎ$};Z~"&g{*NS/m*$KcN܈oXT?m FW=˘[I$|uo(<a,ޠSIlbɯ -)OvHd3U3X"ytH$o1;e0 ej9a"5rHJ5n5ӎ{j3m9#NLDCset:3}iTe-+3&v2WZtFb `[̣Cn_SBJQr']BtG!b zeUu<04=n^AplF> kp7Ԋ^iV2}:Hb]o[n,96;4Oy+o6$Nѝ ( oguB)O;CƐX AYgfo!𞎦DӫNO.NUx{\{:LxlXY eŊw@Aտ:R0 " QːqyXZ1B([")25SJ29Zdыhvatafᴐ]#(na^F9/(ŭM34@^V"GV VPkR)O%yޏ Y?W%DHj xׯ!ml4.YC*9NBRBUg$xI`dXI:]4X0pG>")f˭Ti <|y?`D4B#̛ODN21iX n՟8HyI"MKw"6N(IdUGwzuvfڳJul /=![yd/4)9% fTJs#'~VI=cׯhwN%؜z|wWh- #Kc/o/AP5)Y =<,+mgZȞ-^TJ\Xm0ffZ OZk_m/C섂5 Ѐ}rv]4*u4;ON^NHp esMvWV :4h&EZzEF"4}xqzdETBU?8'|w(tH O96!>;?:^'RߙV5wOl!SgqE-Q lgFoVO,3Mjljb)]i}lLՖ0?yRjZ`\&JB+^A{ C5|}Ke)]"'j0m!lu<}׊'$!@H'P#h]dQuլ׏AD yY!q_ߘ/}(+C+K:Ԡ>Ǿ҈pUEhn.O;3GPDwz\v/W<"{YדZ'vxlHr6Wj*",Nz Ω m>0h؈j'Ykڏ\z10s"noȶx]ʙD7B)zR\ȺsL.F^u Df' $|\@O6yUp٘SfN燺}J2>D*󓺶A0LMoԁX2g@\͎H R~jEG`;|p~֖8f(@Wă q}ܕIa=+Ϭi(NIv4 |^*nNz;.W vzC|4%/-uGͯ5^uAt{{k9g-MX&K T*R+?E׏ !M_m,qst}ZǽٺUy+v5%~U[F]`LDq/S//xIv~ m=mQj'&Av̈́.w#lcvsѫ[m۞;L=˘٫{< W UZkZ7"^؆ۆ;/0ݫ[RYP&|+=迸3TEI{`F(+b(=>op]5\ `p~Æc*e*6|F`<D_6|y(^\ 'LFw5Cg:831|Ź+ކok8vq\  hC;e><~| <2".fodO|h%WJyq6sp7Pƈݴ&~,J=:޵qeV.VU6Vu?=3gmɽ9ޘQtQٹu#u2a"{K P|6cD̄HiΨrExSx6 'L` ƾAX>9z@SX"A\@G͎3lҗkVfvf8Zqx_|A,T t cMZՈg')h+=-<?.-`L}JK % Cb4kڌ C`7Js? .?/ŧyW@yT>̔R6Ϣ1GmpsT( jw =pTtS 2!y3q,<w )JvB%MD{Tkzu|ћţN(:rīE1&ZPIjD})&.>l}{VQ<-)XGH80n>zW|`^/Pv~V$Τԯ렬l.RD߸LG_?X=iʍjPN9kRT *mK_7b z,D(fxCRp{-JZ݂q /OwΜ=\XkW "Ǔ6I4:?r҈p.%Cيzž@!{dwFr+0^[;";{.Ls஌{o6^D+R3n|}I5Ydk;>KwFx` }#xnߢ#- .{sۖ{G3́ 40_,YSL|i "b9Te>hz2lDKYA2]x;g<)ېUx )7#"1WL6TdI dSz : V?6sd:AWW;rùt!bEqҝw$v!ʮE@-JaZ|nu$on^ >*~; 8. }k]}qPݼy(:g)Ąx1N%s.-]{n!wi/}FiW^(x}8z : Jjg@FI[GﬓtXgW-[cU\ꕣ(4&@ݽ{.0S1xW淕V%"~_1i 4Fd?ꌦO iK9'z=yHk5 i3y~Ɲզ0Y eg\si' V=Ǡ` V.kH^ix{H߳&UyBhHb{s%>p6 Tٛo;;TeoYX`s ]Z}t|f. ğ?B&y ?>e30~;8P3#H|;uѳ7?5>_eVC_?1# %pP@lJ7BiR7E1kGgttC{gENvF6^ zQs iƦm&/~_z63`zZeJ~eEo1bnʅfpif}̧O׏Nw!{3״0x.3I7u9*v;N[\BfnpѾ`̅p1;_V?d6:owu{?G7k7H$ή]{vlt߼iCnv(b2 N~{H.g5=0J'0.ȅqux'譆x{(;^u`ԫCiq򔘯÷vW/$*(,yGÎxqr∙0)`˳k"|gPͷ>SԝZ#_V!+YJ^X 4_tM9u0e)k'5X!&+xjG/-r<lj!B/*ޔœmME悃+)}V}%FLl0]QA1yn╶d56MjܔC0uh ?nΧk1-oᐐryѓkTcdOJ#pÀ~`F귏#z(nJ)Ib'+$t,C\Ic #RYpxXj*k(f粋"T4k}H!VEY3&.w~a jI )ڬ㱂EKM(%$sbƗݛa?t*à$n'5B\uN>QeL(zmJ$TJFٞbX̏b9&h2PQoHB]}顨p Yy#&{,+G,t\\0s85F̒7<]_pJ>Pݾ uLF Z 3yIs+*@XA&'"`ă,*QUyIbx? GCraSŰ:r;DRv;똉|כvtytߤ~ZIeW+2wR;TrbP*"Ztv3&)n??ϑz *dgzG3CW 6aTḢ%ANEJB/juLu̴"mխ `HG@rD}KKqb(lE1q.P>Qgvmr?1#+n]f@\=kTCk>} IiӠ\Dm;DZtapI\ϜZ8|nGP_t׋wjWfxFP$)6}BToF?\<$K޳] ;û(&Xa-UpP)6ϗJ:^86_ _]"v謜e?:3eSPi7zN 'zca7J&NI?m$*=*I^iakTߥ+DjwrPZ5(9ȀTC|#J٣+u ~LuP@w` Ǩ˪|!`ntH֐- "{zzctXv``lyqڃ'Ge4KԤD, mǗgْ#L ]=uosOsvTӹU/Fn)'/>ix׃&&};4wLbYrDcQ1Ot7/͈n,S'Q/Xz|P/yt-Gtk 6k?e "L.? "$`LD|a<'5=!?&D3{U8̷A!m/5s6|< `ۃo6uffü0C>] >0RdA`לYy5M"o:99 1~62U _ @@ CYOA0O󟊢H :$uY k"Q+ڡ&R|dm/m^v:=41u:ZO z  ):LVa+18q~ ZORn4*%yQd fֶķ-UL:Y/^{ER* _4V2GӵTZ0yf?!-_[_e@U}lv`Bk.U^`ȅ*f?߭o+=Yٵh$wΏ 7C̨R*J8NmU]d%U ɕ(FNJrVZbuzSdKx_dg%^xVŜycDRc] & Y/4Ř7lE^ga.][/2 50x73Y3xjGMv++zӮh$SzBgdň}¡d_40Ȋj `cFQ'rW#4 .3ݴJfglDqB8T?aoF0*Fle(B|1yw8)+a?>uǢi]㥘YW|YۓbU`d}*1fa}+NL 7ʵ.zUn吸)DOY&gs xJ+q8\%8O!(_Ih_OFtA alMKMW!_ X\㸬|3Uw.)[JLx[P:GեzwO !7`zgˈhṉ~r`MA12ؑe{rBiJ]#9ԉ4U]:m]6jiqFepU;FdLE!QQ=Wy$TyG*Uï8&qs.ӸxS652ڥ@h Oolf@k/A q(k P˒n8{㉣k)lݕք!lRli 1M{ m # Rn΁(Q0y6P{^n ؋b,d-KB]s <ԕ2+̾vM޶ǰg9žoߚ%:]"Y W {C8diju#eE5,?L2 (]Z䜆oB墱#%;b _ Wf-Y)Lu˧=(v?v,b/uqD1IPr10lC0vʮ3y`7tb [Ga.:e{p*d{̈鳉!/´|Z6Axk3tыWy\ C ΉYfR"Ԯщlb?1{/qK;Q, SxTG(/3kjJه̈a%2+}s먞 .,yő>U0ũuy9}5u\Ʊċطi~M]|OHLׯ;aMZSąW]nofc}hxR<+;WW%kÓ\-c&tGVlvڮڮef(iϱ WNgVݥ|·bW_;S54ySy3D$}:ڢ:ۢ_0pUV?" x?~Vy*#LYz3jxV |s>uMZ5s6iQaۋU_;8}+ܝʵؾ"1U^Ie.1v^:AKnM:7ߌj]忮#O0ݝic=;RJ߶sM,DoKg "LjHdaY?ૂD$L ON:+ÆS]Q÷{5~}c޿p|?t@t\4aAǪԃJsu #i`XN='(; JYz!JIK IKf&.@Xlt 0HDJFd͕YIKg<.F '-9ino3z .i^MyCE,KvR Iê9#n YkYuRkXy; $^ikHPb#iR Zp3e_fJXJXIӫ|Xʙd,ee郓N=31P K4~+-{|мTPekAn0{+8qPwI ;7>wtox"1'Wydlɛ`).RhxzýYyv_?6b+.vq\Hw'%#ҏsmlw U%s[!(Wmtp7e# VKqVFsM ۩dVʤ 6s7#XPWiW= |icTT=?*']2M^e@ǡ3eن.Lef ]7p꺌M J{7ҍ3LrNº#PpEJ"%2nDrd^ `ubÖq :B\b-/}#=lۄ wg @F*o@ɘ /5ߋ_4o~x{j; /icãPd1a[Fc}ov]ux&5Q}l$j~3: !eEm[}ޅbo&.J6Wݳʪo75^Cr/@kKpcp~yݰ mbb~3*/=!7J(-_v-G l$N)GČVD0/Xo lx=: ǚ:@QHfvd(Uv~gr0$8/lgzH `pz\a}@Xx ogchM-`m[/ -XŲdjP) i|"^U_:`.ttz^VV~8`f1^IV[)8kY?N~% ?!9N ;ɽa!u})v.vEՙ!{ֶz&jCשRglz+LzG @+|{Ӳk*W'73k7̓n#8Bq84iz@},T w:~XY  .jڜ؁qz,/[7b ^ && A]oN Ъgi? ʆp3أ.=̉OBőWmq$_b2qV%[ 3ETvK$c6B}e)^Pl06XjM}^1)^1ͱؽi#[xs^}Ґ*Nm"rD#DDh7-VMYOqj(5}b~t@boÚi4՚9>l(1ϛeXA5S8I&н!.;pXSQA[k# /Bv4E~<%_<_"tB"ωw63a8+]!`}ʄ$ћ3mDb@I!x2QaE-,}k홾N- .ZW6u6XPn~kvu.tqL]vo tU_iR ~J6jS.^l' #<7Pt0< 6 },badgcHW3ŝIΒc< 1>Í轅G6q`VTn!Ipps5{U)$=[jpYNw2:yg3T1J#JaGT̸ISD"w$QV!ǩAXi#$̓'\D@* ,/ Q :ypiǭ002 D+Kan:+o7ݝ Οa*^xO7bQ}r>6ؽpp n|/Eً_a*u0Ym*n8F,8=#;ދ?{nݝ )&Tծal( ~û\:/ڨ8wlј ߤlˈ-^.qWCO:8u]GcѮ+`*R"!zuDTc[D7hذDTKzhIz܀H]+pxtЙ c"/UGDGǂ>'#&t؋]6 - D=[Dpk U[Dչ-8" A5凗q-N)]#D58C9am~^~_y-p =7Áh.(^":zCb)233\R OvVF*0JK[D[Dޕ;.=?Fa$_FHe;FaH^GRa=M@AH^-XF2|H6⌮W7W/ɫ)td=FRc$cpMɫǠ)9K1;HKlta$|H~݀/8Bk*:y!͹z8AO ݵBlp4}2;J?vGH{[Cw};NUīmcv-ng_igYOtvypq_ULJڸIFf|B?>0\J8=%!s­wv.CH0`ָ SDmu0~A\fJz2N$Jfe皱GP0k!0~:&KPɰc]B(^su{XŢRZf;g$hϦR͓$;A3i] E/ucw϶.bzb\V5~&T!IfM E#ܼ!/7p53U9-P3bg߿WcFasBZKYZYw?.M::uۡr>NKđ\l7Wb0W-> K^p/?.qnΤNr!,t[gxa-5FR|n2-2B{fM8دde hfYul%NCj%=\<EI돜3 0IG/,vR9e) ȿ)S)miWg{paE'oJKUrկ+y:ͺOVS|o8Jt USb:}uQ 6^ ID>/\DfzÃDհՀcuDDInSŋ YR_MϠp4ӝ^z%,axR/s3yJ\cH[~ c&Oo[%A:ONY`-U&G#e⷇QLcZ;cJv !D$ 3fy'xB-az߫IhMUYl1 Cn遉Yj5X[uVH6FAEQ Bl#H147֭)%7\m7%z[H/Dnml gUzxp }/*Ǟm%uK<~1w« YE26#:?ע!V`[2P#/ù0YLtY[ǡz4XmB#BAw^:=63\?JbJMMu̓ L[UEBBrkS>V6*syʿ^n1O])ܒv?if0 *et8IJ"s/BCe7e =WĔhK]VQdbu·x4IѬSߓrlk<#nMnvfRFt ɝڂ{"A'q4 аT-ph9|JZ ;!!ݰrY1i.tBcWvOE0ݳ(w%UiڬEUtw[K!$Ai/^Iu -oMq&'u?}tgUאCxLA'ckZavD1"WXe<Qȳ&"fZ{v s"GJNa|ֹj&]ON 'B AsBbe__ OsT¿(Q:K|sp#S78[Ut:;C3VSw3onukxL[7GEvW5dB_Yj~NWr,y)}ɮ.ࠚR'}( `Aw2}~śL]KP]lwEk#C' ?)'%nǰ[(}ݫ(d;*  0mIj^ޒu 'WIPLօk%(SD4oHIBDWҚ$[޼cDMwC&y>nd&5=t+`- A^"y+Ah&ԯhU-4졍jȯ{E"鲒TCq~0SX;HPڳ=֧ƄyԡǡMEjr g/|S9ǣS<)j% Q !W.FXVg,GDҬYVQ ZdRR%++a7<綗y;}>uay01}C ='-rxJl1'Ep#v=B΍:soV[w$>^fm9\+FBXS6NDj>U[\Vyz2 X $_RzC9ߐCdoq^0{ +ffzAVQ,DHl gX V3wl:W7?R:u_mb*M~<0&$00FwwK'H'X(#nq:㢪FU gL%q컻iq\ۊ5C;`^/7]pt]ݫgl/{vl|Z/;%?UC=LO(t?b&ggta!l{1U;{bYä2Rtp0u='bZdG)VWqBk~ Q 3Y'ю0ިa+KB'1\G(1{޽%S1W}QT&r,A׼"Ғ`rU5кb"[I*(6\ ,-1(^} \T!G FW@WIIaj<濚{P]A;]"PB=κ.QoU@WNϖd͕Y @k_d]G}0ݔ?yP4ǯV<$Ѻe7ᑈ1_"Α1A>~ H|KLE0QL1sFMcV̹{*Ob(PU&ZRpcv  T-M\C/#k9$4'@4>KQ4"ԋ@b8f5gv8УI.hP;<$Y&8 ]I1Ri|Yu34%JCzTUL1HQ|@GU[m'q>C"M" !6IJl$6(#yf$ SgSSXfP _t5Җ /f)jyQ(9H# C ^7|ܨ0CI2Z3M4`.U{OK[X4;W u${nj{_|cxH0U+Pմ(Pe2`iA !Ph0t`*VJ-u#. g'YHl29K 1`p["W#e91h,=,s|8SDL5l"j-t:բr,Ūn-n_۸oXZtEl[TƄů #k퉳5p7$=#J`Ro;U} XkM|ۓ~eW0t)9~(Wuy$nW!:v5~Ǽx'XОNydY$?0B)O0,NAG\Y5װj[GB G ]Uh㷍ksnIuS ٬34%'EglG^㪺hj8WmoԽa\H+d#Kà? #b/A0؜Bl#ᑴ/to!<D4ԟ:7CI`0& 3Wc;}!3:ELbm ֒ pu>A&]]*nsH D%;Z #+`0`"dFsbb)jj"AܝU-tgN4{{e<6J[g:QlzEhF "0wǠag']#'Mq`j={N+'ϩGY! 2!O9FMOI~pA]P)eqpe<SZG ҤK6JzKm!JtU_X;`Ֆx_DL~#>Tj(c5żϞ4h0|ʹ{"d#^Q((Nۗ'o* A\dR".a_)C C{@cw,Nz'gm ̡̆I"EϊqBsE #A7}Zіv-KǦ)<Ȥ,< iV$d#/4k˷G.uQ pKє(i3ƙX~7s :BDDp>b,Y$,NuEewR5=AEN^ lX^~9g*"+h"%Ӷ9H/18VV5981X?$Ffb#uX1B،K #~^ښ|J,JF떘8Ĕ5pZ2H%0iyE"3^ZL?30N@4+4{WhTҀQušH2]*hu .÷&5ϻo=㜹z-5f'9nR *IANGQ6KFrhUdה޾E7// 4Zqntl!% $Ci/E\%MQؽjRjD<ڏ*#N Vh4Q\nv9"Ҵ~$$?F8hU&(ȏS a75+ӃBxDpcâ(QxyyGOD A /ΰD9$/(m"Mf!gu8m_VI{c6&^:&gni.X8boS9J a/ &iֳ#R'9dqPUFkUP!&ޟhRT;uık{:x,9.<0T>2ڵc`9B$oiךp9@\ΰן~4J==Oֲԁ/5SXUF!G(ӷhqfJFEwSQv~GMS'&FhU-ٓ4*Wi rhNtQONh6h=?SCFpxd h8 F&HN3]!4 .M{uC^*`$^n1f\s$)|MxVUO 7؍i)UOJqQ|d* B74K(>܅7ob](?x@+.-(σfՂ-GGźFXJ (&Qߔr%+]D,#i|>E+Jڥ}V"ѫ<5NMy&[j!ŷqUݧ]*.t>G(F!PwE4J)Z!i "m7 SF^(l%UGoc:C^~Q,^AXʷ:iϑ_fg<{ AsFKʽZ^$]LTQb8|S"`tT`d$otPG0sCO84 ߯ ythϱPpMMxڵaX~Y˘Y<4SFD֪{}s\,$z:)ƞnJ~sKMOsum6E>Ǵr'a5:VV0AՈѶ&EcQ^!u_豼cVGkL Hf/?RX~Rzvp;.t`lہ ҹb%*)Vd#|-)ĪӜka>aZ{?"2%c yö|"Hh飡Zw׊FS>e f 0wtDɨu[Kv7ec]IX~I%8`Z)84Q;tk: ,$K}ʽQrv1_ЭXLF"PX>WVEA Qt`[biΝe]D 笮sAvOg.J_WR>\$6ؽgڻ5xI(^nQ";:{䛿I7,`*z:eo?ϏMÚQq"_?6&+w]t%bm8mNt=+ ,c)]tF4Fj"i7@11,ԔO>elI)K:slçO֑eu73G@uhh3G* 1đ"}VED*3o$f p eu XokLNX^kC%0)_L(??uTN!ꅫB!]raROφgWRHGd>Y5zrq<o+wᬖ9+2PXIlMi9^$ b²b J*٠X4`1ܑ3UycE cOlF&̤D32"vÕ$"mlf.b"-yCS01BLmA"8rE7GH0+.8,1LRX"=׏z珡717쌑ȖL`[#E{ )vkԓ0CJH{ےZ&p8δ& ]z5ʏ|3fԢy ,Z/)/M쩧j4L 0g늛ّ?rnFH]xG} *~q7:4p#Y0ߛ D )EP| )rUlϧ%C,z؏8*V 'i5ì<{5d BMAlȃQ.smJְilp8 cآڸ;pdT1u$Q"쓻:jX%p?a;bF_MhV94ZXl8UWu34Wy(mhOH`]jA 9i{q'\|FT#l,SܲflFuZ?\hdt0kSˆl4nSIZNyzb 7%Jht⊦kߴH?QLۧ\6s3!k҃V/@Dى .$.⚱)E\@BSL=\zdc5SM #zq϶QܬtoH\t21NQ9*lDF#z!E=Tջ FM0KMɒic)/ D`Tm3 uJ}' SJlj@`p8F"}}yhh6%-I0!zC C)0vcbg2G?sͭbEN3!7ܯ5)xu-gx|q.l ir-Ǝ `׃(rv"Hnr&7$`3hf1*Cr%>ftQ`4b]YO1]ArZ:%9dZnr~_rQqj,lթnaq145r@r_5^5.-'U~'гq*k[˳&Z*Ts\Gd9Oq }_ġ뿩>z7?HSYPpaQ#^+YTwIr|YHcWHo\?ԟR 0u4W+y{x9+= \ FK ЅK Wb{iI-7(r[G{ٵ8ML+43G Y&֕+ ʔEJEèEԣז vԋx"TpYH9PuzZk)}fOЯrԘ1{T/"d4T{q~^etBn b#єp5{URv"ËG ]ec;Ę)fTrq >8 b(wEw 1|8?Gix/r]|YXV]Sc)#1Ck:}aCe}geFSLVA118 aimw$*^da:PcttǾ=HQ3 \hXGi^ޯ]kwYq^dżGM ۈ.eŒ`|%uo82o+-!Don [)tVF ˻}>)rHQ A#gVb qV,  lLos3<(DM(bY+* \-=+#V5{EKoDeY9 ?2h<"]>67o]<]2y$7C/XnzZ_ 54Šf^TՋNUH^vxN0b]P?^2 oeYg%b\'+PhI1ސ~ú1 #i5*aZRt\{Hgݍ^@Qf ꁢUJְWn 㢳nKښU+/5U?WFfn.0"e7hgGඃ_7^Yu:AMzpSï/"{*M"v!]&RR^C(*"zRi1E f7*쮈c+6VBa^o[Uqre E\dG+"$pd)Bp2R%r#iա-$1<|Q+2X${UlK| m$TR.{&Y//@RR1ݒ 4 Мpϫ JYtA-3爣FނY?'].y#H.X;<\n}r^P _FzP9Ւڢ,UMKKѵ򱤂TI*7t78oЏoܺ>ywۘ*$ah<2;N)e$Vֹf%"WO@Oz.,"y];uJU+ oΥCieI'L<읙wLF̄yaqox@Y>pH#)IL+^hOϏ7d?ėfӅO`'"QC ;ڳF5-A4r qG> d6/zZCx#SFK,eiY;wdAnzE<}^m~놛xkcoI [5&(L(}e1] I]3L=Ձɴ;M6E#Ajhg xUG⋦! u %eq"{yTCc\ ȮN Pk3,A"TY=5ΰ@xvz" 1T!ݾjr3dc:W=V#%Br:a}i0G,e)M~>YƢk^i/ҷlm]1BAt,Z2&n&G_.v8t螜 C!?t=tO #qZ; CnMYw}׏(.eJ'_#JOu.L*[p7]VE]e1\G3]QY4-uOd#SKo>Jc:i6tC\Zns`a*VdT;ڢHo@jK~P'EP1Ęq~4]CnŅ E=l\| {*u%Iמ/E/O15hԊx{q˫p-]4+U S!U\M;c4qb^F`{ Z{im3gX91`vi{ Χ:oc/`Kt{Gsg'T!]g˱3!N:+v:.N708vC2]^gv]0_ցPװ<htmBwlR q)qt !kNY<yW$UGأ43DypՑW~&8[=4ҟ[FWcg큉E/7yMa}v_Zn_F2A媚>P3 _'k~V慇j0BVSm+;c \|SVJ?0MS !cwM<~zmbGm"dze3(v2 ]4wfLQ (FԊ?ER8Y2bLtS>n=S#┤Lj QcQ ʓUy>ӽ!<jH"<^+/Ag@5 qQajs㢋5.حNpEqi7et32qwi4A9; zVStXET(JBE*NXpY]nqSɬvQå!@bfI/ǐфX,yx5riٌ? J2 T'R-"bvq}FAm;qoe35na]׆#/=~w|H`/MJ~"1iSV4C)s[Vw[W((ܫrUp:x|oPNB@TGr㞋l/O@ n`ߟ_+!ɡ"ͽ8]Jr*2jv|Ex pNB:CX:G5pp]D Ge4 f\sKnɀj^٨V|i[;2ui!T^_j0"{FIb !xg`xa^UhDAgw!o 1`{XL ?\R̀RJHTLm+ӭԙw tD?gdV'MHn7@i"EwEov-tWEw8ݺ2f*~;J S.&0'd z9sME!]p:o%Q:P4%υYv*Vh75^ybajaw3K;;g6FWƞ&\VIޕa+6 вSX~׉}(˾vUI2zYwRMӻXbgMT_ք=J*faL"v^4T&#@c$囸ElIr j{xʿ H}b|7H/DnO[*m\s?q/Fi2iKl%}yG5tp-)2$^DE+j%nCYxmxIې~%$Ս2VQ\re]\3qy:Vญp\R_X#OAS`‰ЗTW8Z I+Kyđ~F_;Q1]0i,Tt"k%noE 3&0_B*gV< $rQ$I*!K2n5#F(2L!zWyϋ<ؘe+-yw#7wՖw(P6;nB޴X ~cj,cR&! .cp,LC^o,K#ik"*=$"Ը*&v`MMgN^U R|jok_S-kE'!/lzs=&Z'h0_^?E;@osYYm}5|h " nC_\r4%OgYMLA;ZmL(z"ˉ@qBo_ bKQvW+~}p:`K6Sfze1aG*=Kp%cM߃czp*9AZM_0w 88ee e"2|X1Q fLXXX5+o3VyCH^`yfI@5sL]qaGAG<|NHbVyyNϹGIljFt+\qx9ՒVwd6d@K.c_gj}`Vi_9 Q}qEEx 6 vy63U[J7#@H4r}/38gƩLǢqrʀL =#k {a+qj"*/T@,z&j]ʰP툐؈ U L)z6gQ5z*p`jH Lw֯O<$Dc> V ZwԹ$3G%s>%`N1TC'ڃfD#)uNVVh `mآt;+l%;VD"ZZ4^բX-\jrjpeZిL*BV;6XG~H&KAdmv3ՇhIssCA3 :p,t`PЁmTЁ ]ٽ qT*( )ZAPl_!G蝿VPICA;昩S(>'>M:P\ J:< N h'evG3=ϙBcqaf_iBv)ۢ9K;;e#(9EP4CP'J-g.T]k0Gۛ#t-D!9·I@'!lO"myиsj-6DO$Č`u Q7siji@Z1K7Oε'iBiCӄ-jkӄL {"H"f &ʳeE=;8$i`' '=Kh3JYi_gj- N̑g ahd,UiKw;$iJYϖc.ri{;K0?_"oZ_PDjsqO_#'-tڠWxrD5" !C_Frxi ;-Rjjb/Ñ,n><"N8EL_xRZt@.B0!2S8 Hd|IuB '>A#ƻ"%ˆ҉e%PXpk1T~~"0V|95aʃ @IB#2$Wוdl[D5UXHPFA^BBD0IK@jcAb=+a)|k#P0@PrigfMyb^y (|˜B*к=tU{!W_]؄*_a!G &'jǣ 5eZ*]ӫ^l0-%KfWp̀YTkEm mQ@߮H'!DC!G.~&,H3D(eU1lwN;c ?:pۿ"|cw&/|-0p(;_x.uHc]rOÄ2{4ؙtMݸQaD{ y^ n rw.Q7F5{kvNO`Y^~FTQ'{tsE0$Ͳ8T9!o(%[poZ(A&w+'2 "}d2j L[|,&%p4W_ ]#!rnoYC# ׍#!jڌBd`q %[-.BJEL%DᷚYBZj,ysQDVn]1d3]|Cf,*C"rzgJ& B!wtu| 2-vuDC2-Sww)0H&g!?V_'V{f6-\4#nCA Md30&Oszͱl@kX7JfxDSGb{4L*O6\0!V8<u/SF`KϦE2Z7'DuMi'ڷu~ 81x#b^UZ |E<O3S23/[&L"tѥr/%X͒&zɢպ\}CfӪTˡ/>3!zdc:vBD6u%Hyt5Cpx|ZQ۩"ƥS|xfSV#c%k"JO䖣K]oD]҆V|t+$LHL "DHI<Ř YpPf(ddJ-$ϚOƑ.DoDř{BjYؗ4O먶7#>lXKwP'z܈H8X8hmyY?/HjMTb5U >a-kCV(!f+~֛Wӎ~GZRI J'; H 0.VjJH/ZIPo<;.ڋUGLͼm9z99 qh͞6!? "5I~3c7~v3-DY>Q븀:?#>S"`1 F'_AiEɐI0gԇM\d w&c1ٕEpdSb:"_O+EIrtD_%QDނ8S0;´0֝$ B`Qa>6P$B'g˥x:=ucd\PѺdPl43qP|2XH@+5c u 'өrȬL;/Z`aYSd-\/φY^w[_#w+_3DܪDcy9+1Lb>tr9 fxԋ!,i؆(J*(zh QGV ;ƐclU:p*Z?,A*KVd![&^|+;@%P&0E(,DG K3AymGlS|[cHGa^eL?NhtЃ&&<T) 6EBR ]$-`A ]Z;` ulqBu!Ӳw{_hUmaW)[QhD.dC4&G}\# *lդP6KpU@2BncQGrHXL uržR餼5.Ս.h-s=Mi!u`9ԻLn{_t= , \d-s9 la*4tzXF~k61Oۃn] ~ @yhWv},F푄QpfVW][~T?(Sƅ_ g5׀ŬgVg@~݊ጻOs5ʤUPk *kwjҠr8.!u7]52xk֓WjP-fK8E#Ytws[8Iq^ m"cw- s —6bY @=U+#A#|sݣu4;Y lIL75"L{B s.7GBĪkc!z9ൿC^3K>Ȏ}IߗȌ' ﱏx'; ɀ껳vc74-&ϖx0F-\x4elZiL3WٳID;^JF͠/8e0ĩU,WqYv?X/0|zavĖgq2|N7ZM.MMڵv>.-Zv=-/-\em ܋7h[-X4|hHSL7mfvozoǣixtm=ʇ=ٛZi&MffmyeǓ5%"o=͞ Wfo+ާ-JaD׶).-[F9VՅ6{<ȶ{<pi&g!{3m>+nluE_2P.ؗ^R%8v[S_;g11ODZh7CQ@u'3sD1SՙJzlpLY>yj.^ 9 X X"Aofe豩[QNC*_U}*5ok$W9) {sbS-\> m)펧4oIyw.˓?)v.<*-w!f]vN,( Vt2 - &U#OSdqp9ú#|-MW-dt.Vt -g$g-c \e0wud.xUr09An7Vkg B`)9)OZ>v臮/Awܤ>dP(^u"*T{_@ۑI}-DjgZpsg$4 6Y\{FvQI 4왯Kܕp,v( >f/ˏrQMn/wzQOg?ebyرqG[`hFOۮ~dHB~J56uqy7Q7Qh^ C¾GQonp=pL!/0;hSӡV x==+>υf2E+3?Q|x&*kHP3u.Bqӎ#Ζq Dۢ\pU J;7eM/SM,:ro[u̎Sʍ;G9o1&l; E%ߖp,f/R}'(ϣ5 _9J8=wv3i3qVǯkDte9dmGϟ3CFW_-z$c@=%%:Cȝ_BWh&.-GFlDU%ddCԢ ӂ?\UE}́pvu@ƇűI&S@Ik޹b;^ir~Es~+-NO'sW0 ٦Ji6"S6|e0 I_/,@ҴlYE88[]<2<./"gh?U_{o[?CFAZSN;DįoߑNC>Abe7עok`0([ΉM!b!$ MtIӃ.!FM؄W&/M&\lkSgؤbJ )Ofs!t91ZPXMnB՜pjpIMŦ']lrx&4]lI&]lw4\l.RD:k#Kt1II˹]6],ݟ..-UBuNmMKؤ7b[5yb?!Vγ"^efIgM8G'X|mMB*?V5? sn_) lؤwA zjBtGQͬ*&L6/6yxk lRax1-bsJ'Xac'^lN&QƋbx1U܁ x&7^lr7x1a^Ƌj\X_2_lM7_lŶA7[lԨ Gb-:@lX$ZREZbbkF}d؂;E.F<Ć\L,6CxLh$4t&]2M$8,zj!XK1%X 9b6D0$ r!-CF+J\fJP?bMsU N9b$Ulb4bmL dEZL1fyNl)6 90Rl.13")6 c: RR&hT5bS)6/u!Mf|:KH A֝8[JPP%gpCB ZnAb C$u(H_Y?d8B:v-(|Eжǖ@/)"! EPC#)%Z ^mf +IV, "0*ɪ1XmI~ʆۥf85!$bC&VLlbŤAQ@<RlrFHDMU )&mH~6#6-'"b2R,T%JbllX1֍Md-&S,Z)S,B:[8n[XO*ABgqUBV!(bPx%A"-ƈEf?ŗ|mTZx ; I :D3U,t՟T1Zr[*!% l AbBbL1[Lhg<*gO`d`EfE4%=/&-9&TlGPPU>^}t;BÄ}D҅*|>A"NΖb 7%S,RR탻7gR\+oS-+q'U,zD>5:gTH^IH`fbƊEYLUinwƊCޅ[pКs b7$YlT6WIbK bU:th'bnX2z (|B~&<?uImP --T># y}hak@n27Yli=bY>i&e-XuŖ\q7Yl`غYlBqž˔'Y!oؒ&E3&aur X趰gObR`C~~f 61/7_W,̓8bY$[Ʃz5"Mz5tNz5LwN,WŖI[dd@r,Cb%bWDmX$X|k jarPl li$8aQ6Wb1M 02D;gq6cŢRnƁɅk.(( ],h1]P1I*.95]l=M.TN z|"/C%v贯/;7#!Axm{|* DDŽKt6%BZ4GAa#8=\6W ċETet$ Y{dRD߻ crto"k7{0gBLN nآb"QՌūHjmcTH!`,e4EU"uu~Ƣ\ x+? .L&)㍞&KHEka J<T,&gXz|ƢH S7򒷃.c|Ȇ0Eb!DE8h= g"a ^$Й7D^.؈0&3)B7<+bÛg9V0, g.1dopLк:BXIU$ c [MʸlتjB,Hc!'  \W b,[)U_1c Un%Lü8}/룄Wŝ@ :>jX$L- n7#&4XQN0I4_ll&⋅.&XNa |Ij4c7[-$b-V8bidX?wD [U#"sL{Y+q ^p1vAb9B8bIb -l1z Jplt.&] ,1ݏ$[l6K/ ?sBb!7&p,R+p,XZM[-!sE?`*H'Mtl6.kŢ#QGk 3a n!wM}iy܈進0EA]Y(R8AcoͿ#b$ލ 8{t V(?cXܭfi Ό1goXúU7b,Cػ 'K{H< c~@w3A6&@=WuSƔ8AĜ9o]d,K&)c.:R\ؓ2Lo}9ִ~IHmLUMͿe3ds#$Nx5=cƶ41?MLpvJ̩߬1/Ps$k̥'ޘ6yc³LhQ^L7_#zX5`#zi+MQ[P)s51G ^Jlj?bE_qa>]uč)iG"Pmc쮬F,ږ0ϛ-*3EIs錭WIsSwcq0pkA.xGsnNەr=efMo;} >1-Y<86x"r 6-6B՞s'f-=xl;. 0Xc N;c,-5[.𭔹V۝Ackp̘xTƶN"VkPre*x3MNƖ`&m*,{!Ne.R[1C=C#rR,d~>c.=EWgFƿx1eFg'>posH 8Y7P>5Yb1šB>.X#Ucw9mF]Rqazh7fp + ic~[f86k=Έ0QB-N`E#ndc[E J6.B$CJԘi,$i,cv_j,SF)Ϝ!)[; ƨ,9Ʋ\HVD"r5 bWb@r=yVVXĚyvAE ~Q=0qT c|#6 #S&X&}W<_MZqoAԝΚǜws2@/$f<̙#p[RvB`;!bNL)Ќ߇G8,.q~0a;!N %;kP@vBV[QU5 99^sTOX|7l cȾ +a;N _<%1XT 'XNxݭ1oX.*gel9~aNVϜf钶s(D(h;(wPs{}`n[+i;0 A[U]hN]*dܥ ߢ%Mi"̔ .^+@d)cG+92MxL[E9I[VecAQ8Wp"jB11[T)=Q ~Sވo?# nZR\z)/"%^yL+&Z!z9 w4Q*#:zC{azFo£ii"9b+mIܔrڼ,b^9l^)ŹD\b)'y[WҰxyɆ'M^m3eCJ&/z+ La\2y[`>U&`0y!'M^l/EU!7ശB{YLr epgŋV0a>+’/bX\["lݍHbػ|81_L%`ljj-tbpV"=cɯǀ1d\/op8nmX }[b iIۢ c;\zkvz c::r6[+hv+)cC3{cHƘϒ1&1&/U،1,? [=2s~<8ȏNy 2*2mQ;9)7C,%e WA[̘3&1cr90csMpd$/̍;Yۘ(|`b-ct`v\jEX fltLqČ)cQ2O%e{(mã%,d,e!!˟}1;8"0psX]o2bI6g#wc.=D0E1_EnVkAFgcrvczÄdnyݪ[>lM x B&Z|4N-dCucqPlDE)DZ({lUKCfxE. 2iֽ8cPVc(c3 hxsxߟc=1J1\3cLNbi!א߀gt?!cI{$cr2srU0,G ~'D<@eE>Džsܪ$8owd||8 7\0[As'il4`;@5$ER5Kc q(aֹi-co`߳NT4ݔw7` y>pS[OTd&@1:hc;okĘ,$blpӏS1c,jҞbc'S Q-!w1vp+Zxc)حʞ8fbĘD9`#ƴ}uw-g2 Q;ō9+f,c1f,c1g숶eJF5&Q ͏XդÆAmIúHXneG1Fl,7,?O%ıg#KD5uQX}!-=d'':cccN^G>#c8_$3+[uQ-NL̐luS2~}YwNkT_3;7"`{1+%cyS9+]:ns=p? 1$`n\; cGE~Mj:C `d뻹$Sǰ%>rԓRż\/'t KS;莹EC2`gaqrX.W@BǼ`X:b,cMzy²+ E8w>[B9-K'k?k?q?r} endstream endobj 4 0 obj 290650 endobj 2 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 5 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 841.889771 595.275574 ] /Contents 3 0 R /Group << /Type /Group /S /Transparency /CS /DeviceRGB >> /Resources 2 0 R >> endobj 1 0 obj << /Type /Pages /Kids [ 5 0 R ] /Count 1 >> endobj 6 0 obj << /Creator (cairo 1.10.0 (http://cairographics.org)) /Producer (cairo 1.10.0 (http://cairographics.org)) >> endobj 7 0 obj << /Type /Catalog /Pages 1 0 R >> endobj xref 0 8 0000000000 65535 f 0000291053 00000 n 0000290767 00000 n 0000000015 00000 n 0000290742 00000 n 0000290839 00000 n 0000291118 00000 n 0000291245 00000 n trailer << /Size 8 /Root 7 0 R /Info 6 0 R >> startxref 291297 %%EOF MuMuDVB-2.1.0/doc/diagrams/TS_packet_repartition.svg000066400000000000000000002366451305714132500223240ustar00rootroot00000000000000 image/svg+xml TS Header Section - Beginning payload_unit_start_indicator=1 pointer_field=0 TS Header Complete Section payload_unit_start_indicator=1 pointer_field=0 section_length Stuffing TS Header Section Following payload_unit_start_indicator=0 section_length TS Header Section End payload_unit_start_indicator=0 Stuffing { N TIMES TS Header Section - Beginning payload_unit_start_indicator=1 pointer_field=0 section_length TS Header Section - Beginning payload_unit_start_indicator=1 pointer_field ..... TS Header Section Following payload_unit_start_indicator=0 section_length TS Header Section End payload_unit_start_indicator=1 { N TIMES TS Header Section - Following payload_unit_start_indicator=0 section_length Section - End pointer_field ..... SectionBeginning TS Header Section - Beginning payload_unit_start_indicator=1 pointer_field ..... TS Header Section Following payload_unit_start_indicator=0 section_length TS Header SectionEnd payload_unit_start_indicator=1 { N TIMES TS Header Section - Following payload_unit_start_indicator=0 section_length Section - End pointer_field ..... SectionBeginning section_length CompleteSection Different cases for reparting sectionsin TS packets TS Header Section - Beginning payload_unit_start_indicator=1 pointer_field ..... TS Header Section Following payload_unit_start_indicator=0 section_length TS Header SectionEnd payload_unit_start_indicator=1 { N TIMES TS Header Section - Following payload_unit_start_indicator=0 section_length Section - End pointer_field ..... SectionBeginning section_length CompleteSection section_length CompleteSection MuMuDVB-2.1.0/doc/index.txt000066400000000000000000000005471305714132500153550ustar00rootroot00000000000000MuMuDVB - Documentation ======================= Brice Dubost link:QUICKSTART.html[QUICKSTART guide] link:FAQ.html[FAQ] link:README.html[README] link:README_CONF.html[README concerning the configuration file] link:TRANSCODE_EXTERNAL.html[External transcoding tutorial] link:WEBSERVICES.html[Information concerning the WEB services] MuMuDVB-2.1.0/doc/logo/000077500000000000000000000000001305714132500144375ustar00rootroot00000000000000MuMuDVB-2.1.0/doc/logo/logo_mumudvb.png000066400000000000000000000137221305714132500176510ustar00rootroot00000000000000PNG  IHDRG-TsBIT|d pHYs3tEXtSoftwarewww.inkscape.org<OIDATxyxǿܙyC la DEe'hF"iƽV۟ FkUԺu (("Be H䝹&"[6}?sw枹o83X `1p6/" hSY^y"rd7"H1x@ފ@O"M'X `^\ϐ@˿`Q{=ă_b=lO%R 8>t}) 8^uL@o`n\yzgT"jص MIkT"z"hK\ H o89`E;NDAD-t0ADA. z j߉@ < p/ž@pQW8Ddmk\#"|吲"^`gR.*މԢM|2MPǮ-إ \y'S`Pg4aS>f!ܪ )l*(eDrB Dt*U. >oic9jTB8KQ!@1J&pq-ɍ>]9ЍLpD+"Ttad٤Kp0[UVnWloﰒŋg aU;ϿNPkGX66:FD#{s#0T/MZ^fq 3}=?Ę1b{XF/ @{Z3>X5T~+x72 "dDRbyajkPG.Zu$jȵC%<=޿gZ{ h?MPdCTf -^ZF}7x ׭6OPG8-,*ٛnZѿpR_y>¨&A` 0nZ ꅛΉ@#+' u!ʱ}7zkh/A$'de}LPdI~2UȝQwNJtܧJ;J=ƢQҪUNsEحg?Vk]RkQWM]ʠ; i1r'Zv5>Rjb6\ώ:pl˹"7B0[]D`viCk,ͬu/eAӪ2/g+ǛZ8aG9&ԡ @J8}ؒJ(mv +)3/ C!TU0O]vP2B"z"4,jr*c5mhF{6'{Quzq)rDrcU1+KkC3fVW1bs=7Dt^.\31zh@ Gٹ ֕0m|/ndRVUaTÎy*%ԯ`@-ɂ5lbQܸw!4:tX"kh-6uS'޻VrC<"^獋%D,N$aUv fUR?o̩Es3lڏD)KWh=_F'۱k48'neeC, Z&'/?礊`-/Hss;,ޢ/BeEDZ~dr4k;^T&{wڇYDZla-<^VÒgH Q"jGDq>#kR՞hO5`; c1&^?z.]z[),B'KEdYِ^tG7GEY6r zpuHxpiA`lSDrA^"/J/ d>W`}a'Rd͕cVBl|EjVYyŻ- jWEVm")Ա;*Q;:Hb_u[un"cVYOR<aiZ8AێB+i| B`AYpwt͋itg~(3{e9sCNh_F)6FX R#~FySJRCZ@~hF=!H)fƊv7; P磊Mc2e> O.yĿ.\1"uYSdґmGu"yi#.D+I0,".#Xx0 &^"7zo4Ps~ÐoG2}WJ2iépnk1kC,QwPNMG$OO gZQl˪eɶԻ\bwl慿Z,OH9MVFx|ftK^@h *6,;3|0YA(T)ܝ|Wj iǪ3ůb ŎRXʊQ T(efaEu,X R+8{Q]ѫwgS2 4l h,g8,F5vN贎 ijr1u{q+E-/|>ͩϲV_YB-L;ߍ~q:\jvs9-$FYeTkDzacjG1[!# -ֲUXo,.+'.J[WŠyʲB^kEJeabE[%l;8mӶ AB3v9^c:$/f?:0IF#T9T@_{4 ~a-lgY1VV`VG*l+ֻoO1E rP|e/_cMFm޴?;dDXWlež[ pȜ \؛Ed ^9BrxE)tV gIڴ{=1T+Tf,oeǔG^ٷ:R_H|0[FVXʶ^7`ϻK+ʓf]ːesC c! 8t E+^'y= :Na ~Vvqa jBcm|b6Y+b2a+,[=aRjิ޵os!e ~*;-ǂqZM{Bx2)B%mUeţ7*$ . [bv QPSr+RfìRdTGI+"1sF:_XNE)ׯRQWd~$d:oD4JDD@"y \=.7r\D` DWu4l bQqìٰRaҊQDkQUܓ91vXV onvʑ 3?/t9En} n270D ѥtt.H'Jw:`S(_XM;usyCѦq#Ʊ\y7S*p+娆 3 ,+Hw@ø0VFZ{ZQ+mƞu4YU9lC`: ֋FF{/:I`*:k!A]]kK t=iIENDB`MuMuDVB-2.1.0/doc/logo/logo_mumudvb.svg000066400000000000000000000244571305714132500176730ustar00rootroot00000000000000 image/svg+xml DVB IP MuMuDVB IP IP IP MuMuDVB-2.1.0/doc/logo/logo_mumudvb_32x32.png000066400000000000000000000016011305714132500205030ustar00rootroot00000000000000PNG  IHDR sRGB pHYs3tIME  (WIDATHVKLQ3i>( 2@)PZCD&&H;F7.ܸsAt ?i•k @ |JKwfJ₻s{/"aY.˲CCC^wttrqgX+2Ƙ(:h٪A88.KE t"R2ƒ$|H4VV Zs" (v/y@O%`qhFgd$-s {Ñh\٬QDz4@"pZFUU1n*g=ls--Ҍ:;j^##o*M_B?`Wsn,]GwO޼} xŽSPT%W,B 5X!i dssd2= {8w\X%8"N?ղ4q{EI.؂VK_ *lW o813D[JBȇ^ș=cԬ$f$P\џ̃WST2`Iοch |iEٮ)!LqIQUFa @&uo'=(VVV9^ʓ}9tZR. B:MMVEB(r8(Ly(IXf4g f&a  93 ,ұt;2BJMy `R*TUem ?}*8C8Zf(euD$xQIENDB`MuMuDVB-2.1.0/doc/mumudvb.8000066400000000000000000000042441305714132500152530ustar00rootroot00000000000000.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH MUMUDVB 8 "June 14 2015" "MuMuDVB v2.0" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME MuMuDVB \- Multicast a DVB transponder over multiples ip addresses .SH SYNOPSIS .B mumudvb .RI [ options ] .B -c conf_file .br .B mumudvb .RI [ options ] \-\-config conf_file .SH DESCRIPTION \fBMuMuDVB\fP is a program who can redistribute stream from DVB on a network, in multicast or in HTTP unicast. It's main feature is to take a whole transponder and put each channel on a different multicast IP. Website : http://mumudvb.braice.net/ .SH OPTIONS The following options are provided by MuMuDVB : .TP .B \-c, \-\-config conf_file Path to the config file .TP .B \-s, \-\-signal Display signal power .TP .B \-t, \-\-traffic Display channels traffic .TP .B \-l, \-\-list\-cards List the DVB cards and exit .TP .B \-\-cards The DVB card to use (overrided by the configuration file) .TP .B \-\-server_id The server id (for autoconfiguration, overrided by the configuration file) .TP .B \-d, \-\-debug Don't deamonize .TP .B \-h, \-\-help Display Help .TP .B \-v More Verbose .TP .B \-q More quiet .TP .B \-\-dumpfile Debug option : Dump the stream into the specified file .SH SEE ALSO The program is documented in README and for french speaking people in README-fr. .SH AUTHOR Upstream author: .br Brice DUBOST .br Acknowledgements: .br All the contributors (see github), all users and bug reporters, Dave CHAPMAN (for writing dvbstream and contributions) .PP This manual page was written by Stephane Glondu and Brice DUBOST . MuMuDVB-2.1.0/doc/transcode/000077500000000000000000000000001305714132500154615ustar00rootroot00000000000000MuMuDVB-2.1.0/doc/transcode/examples/000077500000000000000000000000001305714132500172775ustar00rootroot00000000000000MuMuDVB-2.1.0/doc/transcode/examples/test-h.264-2.conf000066400000000000000000000013341305714132500220240ustar00rootroot00000000000000cam_support=1 freq=12574 pol=h srate=22000 card=0 multicast_ttl=16 timeout_accord=20 timeout_no_diff=60 #sap_sending_ip=217.117.229.229 #sap=1 #sap_organisation=iptv #sap_interval=5 #sap_group=UT TV common_port=0 #Forth ip=239.100.0.3 port=1234 name=Jetix/Veronica cam_pmt_pid=2220 transcode_enable=1 transcode_streaming_type=rtp transcode_rtp_port=9948 transcode_sdp_filename=/var/lib/dss/media/mumudvb4.sdp transcode_video_codec=libx264 transcode_video_scale=0.5 transcode_loop_filter=1 #transcode_x264_partitions=1 #transcode_enable_8x8dct=1 transcode_gop=250 transcode_keyint_min=25 transcode_coder_type=0 transcode_subq=1 transcode_video_bitrate=1024000 transcode_audio_codec=mp2 #transcode_aac_latm=1 pids=2220 92 518 8190 38MuMuDVB-2.1.0/doc/transcode/examples/test-h.264-3.conf000066400000000000000000000014011305714132500220200ustar00rootroot00000000000000cam_support=1 freq=12574 pol=h srate=22000 card=0 multicast_ttl=16 timeout_accord=20 timeout_no_diff=60 #sap_sending_ip=217.117.229.229 #sap=1 #sap_organisation=iptv #sap_interval=5 #sap_group=UT TV common_port=0 #1st channel ip=239.100.0.0 port=1234 name=NET5 cam_pmt_pid=2204 transcode_enable=1 transcode_streaming_type=ffm transcode_ffm_url=http://127.0.0.1:8090/feed1.ffm pids=2204 100 513 8190 37 #Second ip=239.100.0.1 port=1234 name=SBS6 cam_pmt_pid=2205 transcode_enable=1 transcode_streaming_type=ffm transcode_ffm_url=http://127.0.0.1:8090/feed2.ffm pids=2205 80 514 8190 32 #Third ip=239.100.0.2 port=1234 name=TMF cam_pmt_pid=2215 transcode_enable=1 transcode_streaming_type=ffm transcode_ffm_url=http://127.0.0.1:8090/feed3.ffm pids=2215 88 516 8190 34 MuMuDVB-2.1.0/doc/transcode/examples/test-h.264-4.conf000066400000000000000000000061531305714132500220320ustar00rootroot00000000000000cam_support=1 freq=12574 pol=h srate=22000 card=0 multicast_ttl=16 timeout_accord=20 timeout_no_diff=60 #sap_sending_ip=217.117.229.229 #sap=1 #sap_organisation=iptv #sap_interval=5 #sap_group=UT TV common_port=0 #1st channel ip=239.100.0.0 port=1234 name=NET5 cam_pmt_pid=2204 transcode_enable=1 transcode_streaming_type=rtp transcode_rtp_port=9918 transcode_sdp_filename=/var/lib/dss/media/mumudvb1.sdp transcode_video_codec=libx264 transcode_loop_filter=1 #transcode_x264_partitions=1 #transcode_enable_8x8dct=1 transcode_gop=250 transcode_keyint_min=25 transcode_coder_type=0 transcode_subq=1 transcode_video_scale=0.5 transcode_video_bitrate=512000 transcode_audio_codec=mp2 pids=2204 100 513 8190 37 #Second ip=239.100.0.1 port=1234 name=SBS6 cam_pmt_pid=2205 transcode_enable=1 transcode_streaming_type=rtp transcode_rtp_port=9928 transcode_sdp_filename=/var/lib/dss/media/mumudvb2.sdp transcode_video_codec=libx264 transcode_loop_filter=1 #transcode_x264_partitions=1 #transcode_enable_8x8dct=1 transcode_gop=250 transcode_keyint_min=25 transcode_coder_type=0 transcode_subq=1 transcode_video_scale=0.5 transcode_video_bitrate=512000 transcode_audio_codec=mp2 pids=2205 80 514 8190 32 #Third ip=239.100.0.2 port=1234 name=TMF-1 cam_pmt_pid=2215 transcode_enable=1 transcode_streaming_type=rtp transcode_rtp_port=9938 transcode_sdp_filename=/var/lib/dss/media/mumudvb3.sdp transcode_video_codec=libx264 transcode_loop_filter=1 #transcode_x264_partitions=1 #transcode_enable_8x8dct=1 transcode_gop=250 transcode_keyint_min=25 transcode_coder_type=0 transcode_subq=1 transcode_video_scale=0.5 transcode_video_bitrate=512000 transcode_audio_codec=mp2 pids=2215 88 516 8190 34 #Forth ip=239.100.0.3 port=1234 name=Jetix/Veronica cam_pmt_pid=2220 transcode_enable=1 transcode_streaming_type=rtp transcode_rtp_port=9948 transcode_sdp_filename=/var/lib/dss/media/mumudvb4.sdp transcode_video_codec=libx264 #transcode_video_scale=0.25 transcode_loop_filter=1 #transcode_x264_partitions=1 #transcode_enable_8x8dct=1 transcode_gop=250 transcode_keyint_min=25 transcode_coder_type=0 transcode_subq=1 transcode_video_scale=0.5 transcode_video_bitrate=512000 transcode_audio_codec=mp2 pids=2220 92 518 8190 38 #Sixt ip=239.100.0.5 port=1234 name=BVN cam_pmt_pid=2225 transcode_enable=1 transcode_streaming_type=rtp transcode_rtp_port=9968 transcode_sdp_filename=/var/lib/dss/media/mumudvb6.sdp transcode_video_codec=libx264 transcode_loop_filter=1 #transcode_x264_partitions=1 #transcode_enable_8x8dct=1 transcode_gop=250 transcode_keyint_min=25 transcode_coder_type=0 transcode_subq=1 transcode_video_scale=0.5 transcode_video_bitrate=512000 transcode_audio_codec=mp2 pids=2225 96 515 36 8190 #TMF2 ip=239.100.0.6 port=1235 name=TMF cam_pmt_pid=2215 transcode_enable=1 transcode_streaming_type=rtp transcode_rtp_port=9978 transcode_sdp_filename=/var/lib/dss/media/mumudvb7.sdp transcode_video_codec=libx264 transcode_loop_filter=1 #transcode_x264_partitions=1 #transcode_enable_8x8dct=1 transcode_gop=250 transcode_keyint_min=25 transcode_coder_type=0 transcode_subq=1 transcode_video_scale=0.5 transcode_video_bitrate=512000 transcode_audio_codec=mp2 pids=2215 88 516 8190 34 MuMuDVB-2.1.0/doc/transcode/examples/test-h.264.conf000066400000000000000000000062171305714132500216720ustar00rootroot00000000000000cam_support=1 freq=12574 pol=h srate=22000 card=0 multicast_ttl=16 timeout_accord=20 timeout_no_diff=60 #sap_sending_ip=217.117.229.229 #sap=1 #sap_organisation=iptv #sap_interval=5 #sap_group=UT TV common_port=0 #1st channel ip=239.100.0.0 port=1234 name=NET5 cam_pmt_pid=2204 transcode_enable=1 transcode_streaming_type=rtp transcode_rtp_port=9918 transcode_sdp_filename=/var/lib/dss/media/mumudvb1.sdp transcode_video_codec=libx264 transcode_loop_filter=1 #transcode_x264_partitions=1 #transcode_enable_8x8dct=1 transcode_gop=250 transcode_keyint_min=25 transcode_coder_type=0 transcode_subq=1 transcode_video_bitrate=1024000 transcode_audio_codec=mp2 transcode_audio_bitrate=128000 pids=2204 100 513 8190 37 #Second ip=239.100.0.1 port=1234 name=SBS6 cam_pmt_pid=2205 transcode_enable=1 transcode_streaming_type=rtp transcode_rtp_port=9928 transcode_sdp_filename=/var/lib/dss/media/mumudvb2.sdp transcode_video_codec=libx264 transcode_loop_filter=1 #transcode_x264_partitions=1 #transcode_enable_8x8dct=1 transcode_gop=250 transcode_keyint_min=25 transcode_coder_type=0 transcode_subq=1 transcode_video_bitrate=1024000 transcode_audio_codec=mp2 transcode_audio_bitrate=128000 pids=2205 80 514 8190 32 #Third ip=239.100.0.2 port=1234 name=TMF-1 cam_pmt_pid=2215 transcode_enable=1 transcode_streaming_type=rtp transcode_rtp_port=9938 transcode_sdp_filename=/var/lib/dss/media/mumudvb3.sdp transcode_video_codec=libx264 transcode_loop_filter=1 #transcode_x264_partitions=1 #transcode_enable_8x8dct=1 transcode_gop=250 transcode_keyint_min=25 transcode_coder_type=0 transcode_subq=1 transcode_video_bitrate=1024000 transcode_audio_codec=mp2 transcode_audio_bitrate=128000 pids=2215 88 516 8190 34 #Forth ip=239.100.0.3 port=1234 name=Jetix/Veronica cam_pmt_pid=2220 transcode_enable=1 transcode_streaming_type=rtp transcode_rtp_port=9948 transcode_sdp_filename=/var/lib/dss/media/mumudvb4.sdp transcode_video_codec=libx264 #transcode_video_scale=0.25 transcode_loop_filter=1 #transcode_x264_partitions=1 #transcode_enable_8x8dct=1 transcode_gop=250 transcode_keyint_min=25 transcode_coder_type=0 transcode_subq=1 transcode_video_bitrate=1024000 transcode_audio_codec=mp2 transcode_audio_bitrate=128000 pids=2220 92 518 8190 38 #Sixt ip=239.100.0.5 port=1234 name=BVN cam_pmt_pid=2225 transcode_enable=1 transcode_streaming_type=rtp transcode_rtp_port=9968 transcode_sdp_filename=/var/lib/dss/media/mumudvb6.sdp transcode_video_codec=libx264 transcode_loop_filter=1 #transcode_x264_partitions=1 #transcode_enable_8x8dct=1 transcode_gop=250 transcode_keyint_min=25 transcode_coder_type=0 transcode_subq=1 transcode_video_bitrate=1024000 transcode_audio_codec=mp2 transcode_audio_bitrate=128000 pids=2225 96 515 36 8190 #TMF2 ip=239.100.0.6 port=1235 name=TMF cam_pmt_pid=2215 transcode_enable=1 transcode_streaming_type=rtp transcode_rtp_port=9978 transcode_sdp_filename=/var/lib/dss/media/mumudvb7.sdp transcode_video_codec=libx264 transcode_loop_filter=1 #transcode_x264_partitions=1 #transcode_enable_8x8dct=1 transcode_gop=250 transcode_keyint_min=25 transcode_coder_type=0 transcode_subq=1 transcode_video_bitrate=1024000 transcode_audio_codec=mp2 transcode_audio_bitrate=128000 pids=2215 88 516 8190 34 MuMuDVB-2.1.0/doc/transcode/examples/test.conf000066400000000000000000000064621305714132500211350ustar00rootroot00000000000000cam_support=1 freq=12574 pol=h srate=22000 card=0 multicast_ttl=16 timeout_accord=20 timeout_no_diff=60 #sap_sending_ip=217.117.229.229 #sap=1 #sap_organisation=iptv #sap_interval=5 #sap_group=UT TV common_port=0 #1st channel ip=239.100.0.0 port=1234 name=NET5 cam_pmt_pid=2204 transcode_enable=1 transcode_streaming_type=rtp transcode_rtp_port=9918 transcode_sdp_filename=/var/lib/dss/media/mumudvb1.sdp transcode_video_codec=mpeg4 transcode_gop=12 transcode_keyint_min=12 transcode_mbd=2 transcode_video_bitrate=2000000 transcode_audio_codec=libfaac pids=2204 100 513 8190 37 #Second ip=239.100.0.1 port=1234 name=SBS6 cam_pmt_pid=2205 transcode_enable=1 transcode_streaming_type=rtp transcode_rtp_port=9928 transcode_sdp_filename=/var/lib/dss/media/mumudvb2.sdp transcode_video_codec=mpeg4 transcode_gop=12 transcode_keyint_min=12 transcode_mbd=2 transcode_video_bitrate=2000000 transcode_audio_codec=libfaac pids=2205 80 514 8190 32 #Third ip=239.100.0.2 port=1234 name=TMF-1 cam_pmt_pid=2215 transcode_enable=1 transcode_streaming_type=rtp transcode_rtp_port=9938 transcode_sdp_filename=/var/lib/dss/media/mumudvb3.sdp #transcode_video_codec=libx264 #transcode_video_scale=0.25 #transcode_x264_profile=high #transcode_loop_filter=1 #transcode_x264_partitions=1 #transcode_mixed_refs=1 #transcode_enable_8x8dct=1 #transcode_gop=250 #transcode_keyint_min=25 #transcode_mbd=0 #transcode_cmp=0 #transcode_subcmp=0 #transcode_refs=6 #transcode_b_strategy=0 #transcode_coder_type=1 #transcode_me_method=1 #transcode_me_range=0 #transcode_subq=1 #transcode_trellis=0 #transcode_crf=0 #transcode_level=30 transcode_video_codec=mpeg4 transcode_gop=12 transcode_keyint_min=12 transcode_mbd=2 transcode_video_bitrate=2000000 transcode_audio_codec=libfaac pids=2215 88 516 8190 34 #Forth ip=239.100.0.3 port=1234 name=Jetix/Veronica cam_pmt_pid=2220 transcode_enable=1 transcode_streaming_type=rtp transcode_rtp_port=9948 transcode_sdp_filename=/var/lib/dss/media/mumudvb4.sdp transcode_video_codec=mpeg4 transcode_gop=12 transcode_keyint_min=12 transcode_mbd=2 transcode_video_bitrate=2000000 transcode_audio_codec=libfaac pids=2220 92 518 8190 38 #Five ip=239.100.0.5 port=1234 name=Jetix/Veronica cam_pmt_pid=2220 transcode_enable=1 transcode_streaming_type=rtp transcode_rtp_port=9958 transcode_sdp_filename=/var/lib/dss/media/mumudvb5.sdp transcode_video_codec=mpeg4 transcode_gop=12 transcode_keyint_min=12 transcode_mbd=2 transcode_video_bitrate=2000000 transcode_audio_codec=libfaac pids=2220 92 518 8190 38 #Sixt ip=239.100.0.5 port=1234 name=BVN cam_pmt_pid=2225 transcode_enable=1 transcode_streaming_type=rtp transcode_rtp_port=9968 transcode_sdp_filename=/var/lib/dss/media/mumudvb6.sdp transcode_video_codec=mpeg4 transcode_gop=12 transcode_keyint_min=12 transcode_mbd=2 transcode_video_bitrate=2000000 transcode_audio_codec=libfaac pids=2225 96 515 36 8190 #TMF2 ip=239.100.0.6 port=1235 name=TMF cam_pmt_pid=2215 transcode_enable=1 transcode_streaming_type=rtp transcode_rtp_port=9978 transcode_sdp_filename=/var/lib/dss/media/mumudvb7.sdp transcode_video_codec=mpeg4 transcode_gop=12 transcode_keyint_min=12 transcode_mbd=2 transcode_video_bitrate=2000000 transcode_audio_codec=libfaac pids=2215 88 516 8190 34 #Radio #ip=239.100.0.7 #port=1234 #name=3FM #cam_pmt_pid=2233 #pids=2233 233 8190 #radio #ip=239.100.0.8 #port=1234 #name=Caz #pids=2250 222 8190 MuMuDVB-2.1.0/doc/transcode/examples/test2.conf000066400000000000000000000031621305714132500212110ustar00rootroot00000000000000cam_support=1 cam_number=0 freq=12343 pol=h srate=27500 card=1 multicast_ttl=16 timeout_accord=20 timeout_no_diff=60 #sap_sending_ip=217.117.229.229 #sap=1 #sap_organisation=iptv #sap_interval=5 #sap_group=UT TV common_port=0 #1st channel #ip=239.100.1.0 #port=1234 #name=RTL4 #cam_pmt_pid=2004 #name=TV Oranje #cam_pmt_pid=2010 #pids=2004 80 512 8190 32 #Second ip=239.100.1.1 port=1234 name=RTL5 cam_pmt_pid=2005 transcode_enable=1 #transcode_streaming_type=ffm #transcode_ffm_url=http://localhost:8091/feed1.ffm transcode_streaming_type=rtp transcode_rtp_port=2255 transcode_video_codec=libx264 transcode_video_scale=0.25 transcode_video_frames_per_second=15 transcode_gop=250 transcode_subq=1 transcode_audio_codec=libfaac transcode_audio_channels=2 transcode_audio_sample_rate=44100 transcode_aac_latm=1 transcode_sdp_filename=/var/lib/dss/media/andriy.sdp pids=2005 92 513 8190 33 #Third #ip=239.100.1.2 #port=1234 #name=RTL7 #cam_pmt_pid=2006 #pids=2006 90 518 8190 38 #Forth #ip=239.100.1.3 #port=1234 #name=TV Oranje #cam_pmt_pid=2010 #pids=2010 84 516 8190 #Fifth #ip=239.100.1.4 #port=1234 #name=Discovery Channel #cam_pmt_pid=2015 #pids=2015 88 515 8190 34 #Sixt #ip=239.100.1.5 #port=1234 #name=Animal Planet #cam_pmt_pid=2020 #pids=2020 96 514 8190 35 #Seven #ip=239.100.1.6 #port=1234 #name=Eurosport #cam_pmt_pid=2025 #pids=2025 112 517 8190 36 #Eight #ip=239.100.1.7 #port=1234 #name=Cartoon Network #cam_pmt_pid=2030 #pids=2030 116 520 8190 37 #Nine #ip=239.100.1.8 #port=1234 #name=RTL8 #cam_pmt_pid=2035 #pids=2035 108 519 8190 39 #Ten #ip=239.100.1.9 #port=1234 #name=Hallmark #cam_pmt_pid=2041 #pids=2041 118 8190 523 MuMuDVB-2.1.0/doc/transcode/transcode_configuration.txt000066400000000000000000000423121305714132500231350ustar00rootroot00000000000000transcode_enable - enables or disables transcoding 0 - disable (default); 1 - enable. ---------------------------------------------------------------------------- transcode_video_codec - video codec for encoding mpeg4 (for MPEG-4), libx264 (for H.264) etc. ---------------------------------------------------------------------------- transcode_audio_codec - audio codec for encoding libmp3lame (for MP3), libfaac (for AAC) etc. ---------------------------------------------------------------------------- transcode_streaming_type - streaming type mpegts - for MPEG-2 TS streaming. rtp - for RTP streaming. ffm - FFM feed to ffserver ---------------------------------------------------------------------------- transcode_ffm_url - URL of FFM feed (required for FFM streaming) ---------------------------------------------------------------------------- transcode_rtp_port - base port for RTP streaming Each RTP stream (audio or video) must go on an even port. Mumudvb will took for each media stream next even port starting from value specified in this option. ---------------------------------------------------------------------------- transcode_sdp_filename - path to generated SDP file (for RTP streaming) ---------------------------------------------------------------------------- transcode_video_scale - factor for video scaling ---------------------------------------------------------------------------- transcode_video_frames_per_second - FPS of output video ---------------------------------------------------------------------------- transcode_audio_channels - number of output audio channels Common values are: 1 - mono 2 - stereo ---------------------------------------------------------------------------- transcode_audio_sample_rate - output audio sample rate Common values are: 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350 ---------------------------------------------------------------------------- transcode_aac_latm - enable LATM payload type for AAC streams while RTP streaming 0 - disable (default) 1 - enable ---------------------------------------------------------------------------- transcode_aac_profile - profile in case of AAC audio encoding low - Low Complexity (LC) - the simplest and most widely used and supported. main - Main Profile (MAIN) - like the LC profile, with the addition of backwards prediction. ssl - Sample-Rate Scalable (SRS) - a.k.a. Scalable Sample Rate (MPEG-4 AAC-SSR). ltp - Long Term Prediction (LTP) - added in the MPEG-4 standard an improvement of the MAIN profile using a forward predictor with lower computational complexity. ---------------------------------------------------------------------------- transcode_video_bitrate - set video bitrate (int bits/s) Enables target bitrate mode for video. Attempts to reach a specific bitrate. Bitrate mode is generally the worst ratecontrol mode H.264 has. ---------------------------------------------------------------------------- transcode_audio_bitrate - set audio bitrate (int bits/s) Enables target bitrate mode for audio. ---------------------------------------------------------------------------- transcode_x264_profile - set H.264 encoding profile Supported values: baseline - Baseline Profile main - Main Profile high - High Profile Note: specify different video encoding options after declaration of transcode_x264_profile may change profile to higher one. For example option "enable_8x8dct=1" will enable 8x8 transform that is supported only by High Profile. ---------------------------------------------------------------------------- transcode_level - set level of encoding Example values: 10 for level 1.0 11 for level 1.1 12 for level 1.2 20 for level 2.0 21 for level 2.1 30 for level 3.0 etc. ---------------------------------------------------------------------------- transcode_x264_partitions - enables best use of partitions for H.264 0 - disable 1 - enable Reccomended default to enable it for H.264. FFmpeg equivalent: partitions +parti4x4+parti8x8+partp8x8+partb8x8 One of H.264's most useful features is the ability to choose among many combinations of inter and intra partitions. P-macroblocks can be subdivided into 16x8, 8x16, 8x8, 4x8, 8x4, and 4x4 partitions. B-macroblocks can be divided into 16x8, 8x16, and 8x8 partitions. I-macroblocks can be divided into 4x4 or 8x8 partitions. Analyzing more partition options improves quality at the cost of speed. The default is to analyze all partitions except p4x4 (p8x8, i8x8, i4x4, b8x8), since p4x4 is not particularly useful except at high bitrates and lower resolutions. Note that i8x8 requires 8x8dct, and is therefore a High Profile-only partition. p8x8 is the most costly, speed-wise, of the partitions, but also gives the most benefit. Generally, whenever possible, all partition types except p4x4 should be used. ---------------------------------------------------------------------------- transcode_loop_filter - enables loop filter 0 - disable 1 - enable Reccomended default to enable it for H.264. ---------------------------------------------------------------------------- transcode_mixed_refs - one reference per partition, as opposed to one reference per macroblock 0 - disable 1 - enable H.264 allows p8x8 blocks to select different references for each p8x8 block. This option allows this analysis to be done, and boosts quality with little speed impact. It should generally be used, though it obviously has no effect with only one reference frame. ---------------------------------------------------------------------------- enable_8x8dct - high profile 8x8 transform (H.264) 0 - disable 1 - enable Gives a notable quality boost by allowing x264 to choose between 8x8 and 4x4 frequency transform size. Required for i8x8 partitions. Speed cost for this option is near-zero both for encoding and decoding; the only reason to disable it is when one needs support on a device not compatible with High Profile. ---------------------------------------------------------------------------- transcode_gop - set the group of picture size Keyframe interval, also known as GOP length. This determines the maximum distance between I-frames. Very high GOP lengths will result in slightly more efficient compression, but will make seeking in the video somewhat more difficult. For H.264 recommended default: 250. ---------------------------------------------------------------------------- transcode_b_frames - use 'frames' B frames B-frames are a core element of H.264 and are more efficient in H.264 than any previous standard. Some specific targets, such as HD-DVD and Blu-Ray, have limitations on the number of consecutive B-frames. Most, however, do not; as a result, there is rarely any negative effect to setting this to the maximum (16) since x264 will, if B-adapt is used, automatically choose the best number of B-frames anyways. This parameter simply serves to limit the max number of B-frames. Note that Baseline Profile, such as that used by iPods, does not support B-frames. Recommended default for H.264: 16. ---------------------------------------------------------------------------- transcode_mbd - macroblock decision algorithm (high quality mode) 0 - simple - use mbcmp (default) 1 - bits - use fewest bits 2 - rd - use best rate distortion *FIXME* enables high quality mode for MPEG-4 compression. ---------------------------------------------------------------------------- transcode_cmp - full pel me compare function 0 - sad - sum of absolute differences, fast (default) 1 - sse - sum of squared errors 2 - satd - sum of absolute Hadamard transformed differences 3 - dct - sum of absolute DCT transformed differences 4 - psnr - sum of squared quantization errors (avoid, low quality) 5 - bit - number of bits needed for the block 6 - rd - rate distortion optimal, slow 7 - zero - 0 8 - vsad - sum of absolute vertical differences 9 - vsse - sum of squared vertical differences 10 - nsse - noise preserving sum of squared differences 11 - w53 - 5/3 wavelet, only used in snow 12 - w97 - 9/7 wavelet, only used in snow 13 - dctmax - 14 - dct264 - 256 - chroma - *FIXME* Used in MPEG-4 compression ---------------------------------------------------------------------------- transcode_subcmp - sub pel me compare function 0 - sad - sum of absolute differences, fast (default) 1 - sse - sum of squared errors 2 - satd - sum of absolute Hadamard transformed differences 3 - dct - sum of absolute DCT transformed differences 4 - psnr - sum of squared quantization errors (avoid, low quality) 5 - bit - number of bits needed for the block 6 - rd - rate distortion optimal, slow 7 - zero - 0 8 - vsad - sum of absolute vertical differences 9 - vsse - sum of squared vertical differences 10 - nsse - noise preserving sum of squared differences 11 - w53 - 5/3 wavelet, only used in snow 12 - w97 - 9/7 wavelet, only used in snow 13 - dctmax - 14 - dct264 - 256 - chroma - *FIXME* Used in MPEG-4 compression ---------------------------------------------------------------------------- transcode_crf - enables constant quality mode, and selects the quality (H.264 only) Constant quality mode (also known as constant ratefactor). Bitrate corresponds approximately to that of constant quantizer, but gives better quality overall at little speed cost. The best one-pass option in H.264. ---------------------------------------------------------------------------- transcode_refs - reference frames to consider for motion compensation (H.264 only) One of H.264's most useful features is the abillity to reference frames other than the one immediately prior to the current frame. This parameter lets one specify how many references can be used, through a maximum of 16. Increasing the number of refs increases the DPB (Decoded Picture Buffer) requirement, which means hardware playback devices will often have strict limits to the number of refs they can handle. In live-action sources, more reference have limited use beyond 4-8, but in cartoon sources up to the maximum value of 16 is often useful. More reference frames require more processing power because every frame is searched by the motion search (except when an early skip decision is made). The slowdown is especially apparent with slower motion estimation methods. Recommended default for H.264: 6. ---------------------------------------------------------------------------- transcode_b_strategy - strategy to choose between I/P/B-frames libx264, by default, adaptively decides through a low-resolution lookahead the best number of B-frames to use. It is possible to disable this adaptivity; this is not recommended. Recommended default for H.264: 1 0: Very fast, but not recommended. Does not work with pre-scenecut (scenecut must be off to force off b-adapt). 1: Fast, default mode in libx264. A good balance between speed and quality. 2: A much slower but more accurate B-frame decision mode that correctly detects fades and generally gives considerably better quality. Its speed gets considerably slower at high bframes values, so its recommended to keep bframes relatively low (perhaps around 3) when using this option. It also may slow down the first pass of libx264 when in threaded mode. ---------------------------------------------------------------------------- transcode_coder_type 0 = vlc variable length coder / huffman coder 1 = ac/CABAC arithmetic coder 2 = raw raw (no encoding) 3 = rle run-length coder 4 = deflate deflate-based coder CABAC is the default entropy encoder used by x264. Though somewhat slower on both the decoding and encoding end, it offers 10-15% improved compression on live-action sources and considerably higher improvements on animated sources, especially at low bitrates. It is also required for the use of trellis quantization. Disabling CABAC may somewhat improve decoding performance, especially at high bitrates. CABAC is not allowed in Baseline Profile. ---------------------------------------------------------------------------- transcode_me_method - set motion estimation method 1 - zero - zero motion estimation (fastest) 2 - full/esa - full motion estimation (slowest) 3 - log - log motion estimation 4 - phods - phods motion estimation 5 - epzs/dia - EPZS motion estimation (default) 6 - x1 - X1 motion estimation 7 - hex - hex motion estimation (x264 specific) 8 - umh - umh motion estimation (x264 specific) 9 - iter - iter motion estimation (snow specific) 10 - tesa - tesa motion estimation (x264 specific) One of the most important settings for x264, both speed and quality-wise. epzs - is the simplest search, consisting of starting at the best predictor, checking the motion vectors at one pixel upwards, left, down, and to the right, picking the best, and repeating the process until it no longer finds any better motion vector. hex - consists of a similar strategy, except it uses a range-2 search of 6 surrounding points, thus the name. It is considerably more efficient than DIA and hardly any slower, and therefore makes a good choice for general-use encoding. umh - is considerably slower than HEX, but searches a complex multi-hexagon pattern in order to avoid missing harder-to-find motion vectors. Unlike HEX and DIA, the merange parameter directly controls UMH's search radius, allowing one to increase or decrease the size of the wide search. full - is a highly optimized intelligent search of the entire motion search space within merange of the best predictor. It is mathematically equivalent to the bruteforce method of searching every single motion vector in that area, though faster. However, it is still considerably slower than UMH, with not too much benefit, so is not particularly useful for everyday encoding. ---------------------------------------------------------------------------- transcode_me_range - limit motion vectors range) MErange controls the max range of the motion search. For HEX and DIA, this is clamped to between 4 and 16, with a recommended of 16. For UMH and ESA, it can be increased beyond the 16 to allow for a wider-range motion search, which is useful on HD footage and for high-motion footage. Note that for UMH and ESA, increasing MErange will significantly slow down encoding. ---------------------------------------------------------------------------- transcode_subq - sub pel motion estimation quality An extremely important encoding parameter for H.264 which determines what algorithms are used for both subpixel motion searching and partition decision. 1: Fastest, but extremely low quality. Should be avoided except on first pass encoding. 2-5: Progressively better and slower, 5 serves as a good medium for higher speed encoding. 6-7: 6 is the default. Activates rate-distortion optimization for partition decision. This can considerably improve efficiency, though it has a notable speed cost. 6 activates it in I/P frames, and subme7 activates it in B frames. 8-9: Activates rate-distortion refinement, which uses RDO to refine both motion vectors and intra prediction modes. Slower than subme 6, but again, more efficient. ---------------------------------------------------------------------------- transcode_trellis - rate-distortion optimal quantization 0 - disabled 1 - enabled only on the final encode of a MB 2 - enabled on all mode decisions The main decision made in quantization is which coefficients to round up and which to round down. Trellis chooses the optimal rounding choices for the maximum rate-distortion score, to maximize PSNR relative to bitrate. This generally increases quality relative to bitrate by about 5% for a somewhat small speed cost. It should generally be enabled. Note that trellis requires CABAC. ---------------------------------------------------------------------------- transcode_sc_threshold - scene change threshold Adjusts the sensitivity of x264's scenecut detection. Rarely needs to be adjusted. Recommended default for H.264: 40. ---------------------------------------------------------------------------- transcode_rc_eq - set rate control equation Ratecontrol equation. Recommended default for H.264: 'blurCplx^(1-qComp)'. ---------------------------------------------------------------------------- transcode_qcomp - video quantizer scale compression QP curve compression: 0.0 => CBR, 1.0 => CQP. Recommended default for H.264: 0.60. ---------------------------------------------------------------------------- transcode_qmin - min video quantizer scale Minimum quantizer. Recommended default for H.264: 10. ---------------------------------------------------------------------------- transcode_qmax - max video quantizer scale Maximum quantizer. Recommended default for H.264: 51. ---------------------------------------------------------------------------- transcode_qdiff - max difference between the quantizer scale Set max QP step. Recommended default: 4. ---------------------------------------------------------------------------- transcode_keyint_min - key interval ----------------------------------------------------------------------------MuMuDVB-2.1.0/openwrt/000077500000000000000000000000001305714132500144305ustar00rootroot00000000000000MuMuDVB-2.1.0/openwrt/generate_dvbmk.py000077500000000000000000000255321305714132500177710ustar00rootroot00000000000000#!/usr/bin/env python """ This script is a generator of OpenWRT's Makefile for DVB USB devices This script uses the sources of the linux kernel to find what are the different supported DVB USB devices and the kernel parameters needed to compile them. In more details it is able to find * the module description * the module dependancies * the frontends needed and the tuner needed * the module generated files (including the frontend and the tuners) * the firmware needed by the module And it will generate a dvb.mk file with all these informations """ KERNEL_PATH = "/usr/src/linux-2.6.32/" DEST_DIR = "/tmp/" DEST_FILE = "dvb.2.6.32.mk" _NEXT_LINE = """ \\ """ CONFIG_FILE_HEADER = """ # # Copyright (C) 2009 Brice DUBOST # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. # # # !!!! This is a generated file !!!! # DVB_MENU:=DVB support # # General section # define KernelPackage/dvb-core SUBMENU:=$(DVB_MENU) TITLE:=DVB core support DEPENDS:=@LINUX_2_6 +kmod-i2c-core KCONFIG:= \\ CONFIG_MEDIA_SUPPORT \\ CONFIG_DVB_CORE \\ CONFIG_DVB_CAPTURE_DRIVERS=y \\ CONFIG_MEDIA_TUNER_CUSTOMIZE=y \\ CONFIG_DVB_FE_CUSTOMISE=y \\ CONFIG_DVB_DYNAMIC_MINORS=n \\ CONFIG_CRC32 FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-core/dvb-core.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,50,dvb-core) endef define KernelPackage/dvb-core/description Kernel module for DVB support endef $(eval $(call KernelPackage,dvb-core)) define KernelPackage/dvb-usb SUBMENU:=$(DVB_MENU) TITLE:=DVB USB Support DEPENDS:=@USB_SUPPORT +kmod-dvb-core +kmod-usb-core KCONFIG:= \\ CONFIG_DVB_USB \\ CONFIG_INPUT=y FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb.$(LINUX_KMOD_SUFFIX) # AUTOLOAD:=$(call AutoLoad,55,dvb-usb) endef define KernelPackage/dvb-usb/description Kernel module for DVB USB devices. Note you have to select at least a device. endef $(eval $(call KernelPackage,dvb-usb)) # # Devices section # """ def find_module_files(pre, filename, module): """This function is intended to act like a special grep in a Makefile""" makefile = open(filename,'r') lines_makefile = makefile.readlines() makefile.close() module_files = [] for index, line in enumerate(lines_makefile): if module in line: for module_object in lines_makefile[index].strip().split('=')[1].split(' '): #we remove thing without sence if len(module_object) <3 : continue module_files.append(pre + module_object) return module_files def deal_config(config, filedvbmk): """This function is called when the user wants to add a new module""" firmware_pattern = """%(name)s_FW_%(number)d:=%(filename)s """ firmware_install_pattern = """ $(INSTALL_DATA) $(DL_DIR)/$(%(name)s_FW_%(number)d) $(1)/lib/firmware/ """ firmware_install_main = """define KernelPackage/%(module_name)s/install $(INSTALL_DIR) $(1)/lib/firmware %(firmware_install)s endef """ device_structure = """ define KernelPackage/%(module_name)s SUBMENU:=$(DVB_MENU) TITLE:=%(module_title)s KCONFIG:= %(kconfig)s DEPENDS:=%(depends)s FILES:= %(module_files)s endef define KernelPackage/%(module_name)s/description Say Y here to support the %(module_title)s. The following modules will be compiled for this device : %(module_list)s %(firmware_files)s endef %(firmware_list)s %(firmware_install)s $(eval $(call KernelPackage,%(module_name)s)) """ #We search for the generated files in the main Makefile config["files"] = find_module_files("drivers/media/dvb/dvb-usb/", \ KERNEL_PATH + "drivers/media/dvb/dvb-usb/Makefile", \ config["name"]) config["files"] = [item[:-2] for item in config["files"]] print " * We search the needed source files for searching for a firmware" config["source_files"] = [] for obj in config["files"]: obj = obj.split('/')[-1]+'-objs' config["source_files"] += find_module_files("drivers/media/dvb/dvb-usb/", KERNEL_PATH + "drivers/media/dvb/dvb-usb/Makefile", obj) #We replace the .o by a .c config["source_files"] = [item[:-2] + ".c" for item in config["source_files"]] config["firmwares"] = [] temp_config_firmwares = [] for sourcefile in config["source_files"]: temp_config_firmwares += find_module_files("", KERNEL_PATH+sourcefile, ".firmware") #We remove the probable comma temp_config_firmwares = [item.replace(",",'') for item in temp_config_firmwares] #Dirty hack, since we don't completely parse the C code, we exclude false positive searching for .fw" in the name for item in temp_config_firmwares: if ".fw\"" in item and item.replace("\"", "") not in config["firmwares"]: config["firmwares"].append(item.replace("\"", "")) print " ** This object needs the firmwares : " + str(config["firmwares"]) firmware_list = "" firmware_install = "" for index, firmware in enumerate(config["firmwares"]): firmware_list += firmware_pattern % {"name" : config["name"], "number" : index, "filename" : firmware} firmware_install += firmware_install_pattern % {"name" : config["name"], "number" : index} #we look on the files needed by the tuners/ frontends if len(config["select"]): print " * We loop on the selected modules " for module in config["select"]: print " Module : " + module if(module.find("MEDIA")==0): new_files = find_module_files("drivers/media/common/tuners/", KERNEL_PATH+"drivers/media/common/tuners/Makefile", "CONFIG_" + module) config["files"] += [item[:-2] for item in new_files] elif(module.find("DVB")==0): new_files = find_module_files("drivers/media/dvb/frontends/", KERNEL_PATH+"drivers/media/dvb/frontends/Makefile", "CONFIG_" + module) config["files"] += [item[:-2] for item in new_files] print " New files : " + str(new_files) if len(config["select"]): print " * Final module files : " print config["files"] print " * Depends : " print config["depends"] #--------------- GENERATED device dvb.mk part --------------" #We have now all the needed information, we generate the config for the mk depends = ' '.join(['+kmod-' + item.lower().replace('_','-') for item in config["depends"]]) kconfig = "CONFIG_"+config["name"] if len(config["select"]): kconfig += _NEXT_LINE + _NEXT_LINE.join(["CONFIG_" + item for item in config["select"]]) if(len(config["firmwares"])): firmware_files = \ "You have to put the firmware files in the download dir : " + \ ' '.join(config["firmwares"]) + \ "\nThey can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware ." firmware_install = firmware_install_main % {"module_name" : config["name"].lower().replace('_','-'),"firmware_install" : firmware_install[:-1]} else: firmware_files = "" firmware_install = "" device_mk = device_structure % {"module_name_orig" : config["name"], \ "module_name" : config["name"].lower().replace('_', '-'), \ "module_title" : config["description"].replace('"', '')[:50], \ "kconfig" : kconfig, \ "module_files" : _NEXT_LINE.join(["$(LINUX_DIR)/" + item + ".$(LINUX_KMOD_SUFFIX)" for item in config["files"]]), \ "module_list" : ' '.join([item.split('/')[-1] for item in config["files"]]), \ "firmware_list" : firmware_list, \ "firmware_install" : firmware_install, \ "firmware_files" : firmware_files, \ "depends" : depends} #print device_mk print filedvbmk.write(device_mk) filedvbmk.flush() if __name__ == "__main__" : print "Openning of Kconfig" dvb_usb_kconfig = open(KERNEL_PATH+"drivers/media/dvb/dvb-usb/Kconfig",'r') print "The generated file will be put in : " + DEST_DIR + DEST_FILE dvb_mk = open(DEST_DIR + DEST_FILE,'w') #we write the header dvb_mk.write(CONFIG_FILE_HEADER) haveconfig = False current_config = {"name" : ""} #We loop on the lines of the Kconfig to find new devices characterized by the keyword "config" for line_Kconfig in dvb_usb_kconfig.readlines(): if(line_Kconfig.find("config")==0): if(haveconfig and current_config["name"] != "DVB_USB"): #We found a new "config" keyword, we parse the previous one print "We found config " + current_config["name"] print current_config["description"] answer = raw_input( "Do you want it (Y/n) ? ") if(answer.lower().find('y')==0 or len(answer)==0): deal_config(current_config, dvb_mk) print haveconfig = False current_config = {"name" : "","select" : [], "depends" : []} current_config["name"] = line_Kconfig.split(' ')[1].strip() #"real" modules are characterized by a tristate keyword if "tristate" in line_Kconfig: #Here we get the main CONFIG_ and the module description haveconfig = True current_config["description"] = line_Kconfig.split("tristate ")[1].strip().replace("support","") #We remove stuff between () to shorten the description while(current_config["description"].find('(') != -1 and current_config["description"].find(')') != -1): current_config["description"] = current_config["description"][:current_config["description"].find('(')] + \ current_config["description"][current_config["description"].find(')')+1:] #The select keyword allow us to find the tuners and frontends if "select" in line_Kconfig: current_config["select"].append(line_Kconfig.split("select ")[1].split(' ')[0].strip()) #We add the module dependancies if "depends on" in line_Kconfig: if line_Kconfig.split("depends on ")[1].split(' ')[0].strip() not in ['EXPERIMENTAL']: current_config["depends"].append(line_Kconfig.split("depends on ")[1].split(' ')[0].strip()) #We deal with the last one if(haveconfig and current_config["name"] != "DVB_USB"): #We found a new "config" keyword, we parse the previous one print "We found config " + current_config["name"] print current_config["description"] answer = raw_input( "Do you want it (Y/n) ? ") if(answer.lower().find('y')==0 or len(answer)==0): deal_config(current_config, dvb_mk) dvb_mk.close() dvb_usb_kconfig.close() MuMuDVB-2.1.0/openwrt/package/000077500000000000000000000000001305714132500160235ustar00rootroot00000000000000MuMuDVB-2.1.0/openwrt/package/kernel/000077500000000000000000000000001305714132500173035ustar00rootroot00000000000000MuMuDVB-2.1.0/openwrt/package/kernel/modules/000077500000000000000000000000001305714132500207535ustar00rootroot00000000000000MuMuDVB-2.1.0/openwrt/package/kernel/modules/dvb.2.6.21.7.mk000066400000000000000000000461031305714132500227550ustar00rootroot00000000000000 # # Copyright (C) 2009 Brice DUBOST # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. # # # !!!! This is a generated file !!!! # DVB_MENU:=DVB support # # General section # define KernelPackage/dvb-core SUBMENU:=$(DVB_MENU) TITLE:=DVB core support DEPENDS:=@LINUX_2_6 +kmod-i2c-core KCONFIG:= \ CONFIG_DVB_CORE \ CONFIG_DVB=y \ CONFIG_DVB_CAPTURE_DRIVERS=y \ MEDIA_TUNER_CUSTOMIZE=y \ DVB_FE_CUSTOMISE=y \ CONFIG_CRC32 FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-core/dvb-core.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,50,dvb-core) endef define KernelPackage/dvb-core/description Kernel module for DVB support endef $(eval $(call KernelPackage,dvb-core)) define KernelPackage/dvb-usb SUBMENU:=$(DVB_MENU) TITLE:=DVB USB Support DEPENDS:=@USB_SUPPORT +kmod-dvb-core +kmod-usb-core KCONFIG:= \ CONFIG_DVB_USB \ CONFIG_INPUT FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/input/input-core.$(LINUX_KMOD_SUFFIX) # AUTOLOAD:=$(call AutoLoad,55,dvb-usb) endef define KernelPackage/dvb-usb/description Kernel module for DVB USB devices. Note you have to select at least a device. endef $(eval $(call KernelPackage,dvb-usb)) # # Devices section # define KernelPackage/dvb-usb-a800 SUBMENU:=$(DVB_MENU) TITLE:=AVerMedia AverTV DVB-T USB 2.0 KCONFIG:= CONFIG_DVB_USB_A800 \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-a800.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-a800/description Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-a800 dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-avertv-a800-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_A800_FW_0:=dvb-usb-avertv-a800-02.fw define KernelPackage/dvb-usb-a800/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_A800_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-a800)) define KernelPackage/dvb-usb-dibusb-mb SUBMENU:=$(DVB_MENU) TITLE:=DiBcom USB DVB-T devices KCONFIG:= CONFIG_DVB_USB_DIBUSB_MB \ CONFIG_DVB_DIB3000MB \ CONFIG_DVB_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-mb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dibusb-mb/description Say Y here to support the DiBcom USB DVB-T devices . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-dibusb-mb dib3000mb mt2060 You have to put the firmware files in the download dir : dvb-usb-dibusb-5.0.0.11.fw dvb-usb-dibusb-an2235-01.fw dvb-usb-adstech-usb2-02.fw dvb-usb-dibusb-6.0.0.8.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIBUSB_MB_FW_0:=dvb-usb-dibusb-5.0.0.11.fw DVB_USB_DIBUSB_MB_FW_1:=dvb-usb-dibusb-an2235-01.fw DVB_USB_DIBUSB_MB_FW_2:=dvb-usb-adstech-usb2-02.fw DVB_USB_DIBUSB_MB_FW_3:=dvb-usb-dibusb-6.0.0.8.fw define KernelPackage/dvb-usb-dibusb-mb/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_3) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dibusb-mb)) define KernelPackage/dvb-usb-dibusb-mc SUBMENU:=$(DVB_MENU) TITLE:=DiBcom USB DVB-T devices KCONFIG:= CONFIG_DVB_USB_DIBUSB_MC \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dibusb-mc/description Say Y here to support the DiBcom USB DVB-T devices . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-dibusb-mc dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-dibusb-6.0.0.8.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIBUSB_MC_FW_0:=dvb-usb-dibusb-6.0.0.8.fw define KernelPackage/dvb-usb-dibusb-mc/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MC_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dibusb-mc)) define KernelPackage/dvb-usb-dib0700 SUBMENU:=$(DVB_MENU) TITLE:=DiBcom DiB0700 USB DVB devices KCONFIG:= CONFIG_DVB_USB_DIB0700 \ CONFIG_DVB_DIB7000P \ CONFIG_DVB_DIB7000M \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dib0700.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000p.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000m.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dib0700/description Say Y here to support the DiBcom DiB0700 USB DVB devices . The following modules will be compiled for this device : dvb-usb-dib0700 dib7000p dibx000_common dib7000m dibx000_common dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-dib0700-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIB0700_FW_0:=dvb-usb-dib0700-01.fw define KernelPackage/dvb-usb-dib0700/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIB0700_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dib0700)) define KernelPackage/dvb-usb-umt-010 SUBMENU:=$(DVB_MENU) TITLE:=HanfTek UMT-010 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_UMT_010 \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-umt-010.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-umt-010/description Say Y here to support the HanfTek UMT-010 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-umt-010 dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-umt-010-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_UMT_010_FW_0:=dvb-usb-umt-010-02.fw define KernelPackage/dvb-usb-umt-010/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_UMT_010_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-umt-010)) define KernelPackage/dvb-usb-cxusb SUBMENU:=$(DVB_MENU) TITLE:=Conexant USB2.0 hybrid reference design KCONFIG:= CONFIG_DVB_USB_CXUSB \ CONFIG_DVB_CX22702 \ CONFIG_DVB_LGDT330X \ CONFIG_DVB_TUNER_LGH06XF \ CONFIG_DVB_MT352 \ CONFIG_DVB_ZL10353 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-cxusb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/cx22702.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lgdt330x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lgh06xf.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-cxusb/description Say Y here to support the Conexant USB2.0 hybrid reference design . The following modules will be compiled for this device : dvb-usb-cxusb cx22702 lgdt330x lgh06xf mt352 zl10353 You have to put the firmware files in the download dir : dvb-usb-bluebird-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_CXUSB_FW_0:=dvb-usb-bluebird-01.fw define KernelPackage/dvb-usb-cxusb/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_CXUSB_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-cxusb)) define KernelPackage/dvb-usb-m920x SUBMENU:=$(DVB_MENU) TITLE:=Uli m920x DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_M920X \ CONFIG_DVB_MT352 \ CONFIG_DVB_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-m920x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-m920x/description Say Y here to support the Uli m920x DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-m920x mt352 qt1010 You have to put the firmware files in the download dir : dvb-usb-megasky-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_M920X_FW_0:=dvb-usb-megasky-02.fw define KernelPackage/dvb-usb-m920x/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-m920x)) define KernelPackage/dvb-usb-gl861 SUBMENU:=$(DVB_MENU) TITLE:=Genesys Logic GL861 USB2.0 KCONFIG:= CONFIG_DVB_USB_GL861 \ CONFIG_DVB_ZL10353 \ CONFIG_DVB_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-gl861.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-gl861/description Say Y here to support the Genesys Logic GL861 USB2.0 . The following modules will be compiled for this device : dvb-usb-gl861 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-gl861)) define KernelPackage/dvb-usb-au6610 SUBMENU:=$(DVB_MENU) TITLE:=Alcor Micro AU6610 USB2.0 KCONFIG:= CONFIG_DVB_USB_AU6610 \ CONFIG_DVB_ZL10353 \ CONFIG_DVB_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-au6610.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-au6610/description Say Y here to support the Alcor Micro AU6610 USB2.0 . The following modules will be compiled for this device : dvb-usb-au6610 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-au6610)) define KernelPackage/dvb-usb-digitv SUBMENU:=$(DVB_MENU) TITLE:=Nebula Electronics uDigiTV DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_DIGITV \ CONFIG_DVB_NXT6000 \ CONFIG_DVB_MT352 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-digitv.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/nxt6000.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-digitv/description Say Y here to support the Nebula Electronics uDigiTV DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-digitv nxt6000 mt352 You have to put the firmware files in the download dir : dvb-usb-digitv-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIGITV_FW_0:=dvb-usb-digitv-02.fw define KernelPackage/dvb-usb-digitv/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIGITV_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-digitv)) define KernelPackage/dvb-usb-vp7045 SUBMENU:=$(DVB_MENU) TITLE:=TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle KCONFIG:= CONFIG_DVB_USB_VP7045 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-vp7045.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-vp7045/description Say Y here to support the TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle. The following modules will be compiled for this device : dvb-usb-vp7045 You have to put the firmware files in the download dir : dvb-usb-vp7045-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_VP7045_FW_0:=dvb-usb-vp7045-01.fw define KernelPackage/dvb-usb-vp7045/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_VP7045_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-vp7045)) define KernelPackage/dvb-usb-vp702x SUBMENU:=$(DVB_MENU) TITLE:=TwinhanDTV StarBox and clones DVB-S USB2.0 KCONFIG:= CONFIG_DVB_USB_VP702X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-vp702x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-vp702x/description Say Y here to support the TwinhanDTV StarBox and clones DVB-S USB2.0 . The following modules will be compiled for this device : dvb-usb-vp702x You have to put the firmware files in the download dir : dvb-usb-vp702x-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_VP702X_FW_0:=dvb-usb-vp702x-02.fw define KernelPackage/dvb-usb-vp702x/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_VP702X_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-vp702x)) define KernelPackage/dvb-usb-gp8psk SUBMENU:=$(DVB_MENU) TITLE:=GENPIX 8PSK->USB module KCONFIG:= CONFIG_DVB_USB_GP8PSK DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-gp8psk.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-gp8psk/description Say Y here to support the GENPIX 8PSK->USB module . The following modules will be compiled for this device : dvb-usb-gp8psk You have to put the firmware files in the download dir : dvb-usb-gp8psk-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_GP8PSK_FW_0:=dvb-usb-gp8psk-01.fw define KernelPackage/dvb-usb-gp8psk/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_GP8PSK_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-gp8psk)) define KernelPackage/dvb-usb-nova-t-usb2 SUBMENU:=$(DVB_MENU) TITLE:=Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_NOVA_T_USB2 \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-nova-t-usb2.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-nova-t-usb2/description Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-nova-t-usb2 dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-nova-t-usb2-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_NOVA_T_USB2_FW_0:=dvb-usb-nova-t-usb2-02.fw define KernelPackage/dvb-usb-nova-t-usb2/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_NOVA_T_USB2_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-nova-t-usb2)) define KernelPackage/dvb-usb-ttusb2 SUBMENU:=$(DVB_MENU) TITLE:=Pinnacle 400e DVB-S USB2.0 KCONFIG:= CONFIG_DVB_USB_TTUSB2 \ CONFIG_DVB_TDA10086 \ CONFIG_DVB_LNBP21 \ CONFIG_DVB_TDA826X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-ttusb2.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda10086.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lnbp21.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda826x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-ttusb2/description Say Y here to support the Pinnacle 400e DVB-S USB2.0 . The following modules will be compiled for this device : dvb-usb-ttusb2 tda10086 lnbp21 tda826x You have to put the firmware files in the download dir : dvb-usb-pctv-400e-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_TTUSB2_FW_0:=dvb-usb-pctv-400e-01.fw define KernelPackage/dvb-usb-ttusb2/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_TTUSB2_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-ttusb2)) define KernelPackage/dvb-usb-dtt200u SUBMENU:=$(DVB_MENU) TITLE:=WideView WT-200U and WT-220U DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_DTT200U DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dtt200u.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dtt200u/description Say Y here to support the WideView WT-200U and WT-220U DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dtt200u You have to put the firmware files in the download dir : dvb-usb-dtt200u-01.fw dvb-usb-wt220u-02.fw dvb-usb-wt220u-fc03.fw dvb-usb-wt220u-zl0353-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DTT200U_FW_0:=dvb-usb-dtt200u-01.fw DVB_USB_DTT200U_FW_1:=dvb-usb-wt220u-02.fw DVB_USB_DTT200U_FW_2:=dvb-usb-wt220u-fc03.fw DVB_USB_DTT200U_FW_3:=dvb-usb-wt220u-zl0353-01.fw define KernelPackage/dvb-usb-dtt200u/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_3) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dtt200u)) MuMuDVB-2.1.0/openwrt/package/kernel/modules/dvb.2.6.22.19.mk000066400000000000000000000511231305714132500230370ustar00rootroot00000000000000 # # Copyright (C) 2009 Brice DUBOST # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. # # # !!!! This is a generated file !!!! # DVB_MENU:=DVB support # # General section # define KernelPackage/dvb-core SUBMENU:=$(DVB_MENU) TITLE:=DVB core support DEPENDS:=@LINUX_2_6 +kmod-i2c-core KCONFIG:= \ CONFIG_DVB_CORE \ CONFIG_DVB_CAPTURE_DRIVERS=y \ CONFIG_MEDIA_TUNER_CUSTOMIZE=y \ CONFIG_DVB_FE_CUSTOMISE=y \ CONFIG_CRC32 FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-core/dvb-core.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,50,dvb-core) endef define KernelPackage/dvb-core/description Kernel module for DVB support endef $(eval $(call KernelPackage,dvb-core)) define KernelPackage/dvb-usb SUBMENU:=$(DVB_MENU) TITLE:=DVB USB Support DEPENDS:=@USB_SUPPORT +kmod-dvb-core +kmod-usb-core KCONFIG:= \ CONFIG_DVB_USB \ CONFIG_INPUT=y FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb.$(LINUX_KMOD_SUFFIX) # AUTOLOAD:=$(call AutoLoad,55,dvb-usb) endef define KernelPackage/dvb-usb/description Kernel module for DVB USB devices. Note you have to select at least a device. endef $(eval $(call KernelPackage,dvb-usb)) # # Devices section # define KernelPackage/dvb-usb-a800 SUBMENU:=$(DVB_MENU) TITLE:=AVerMedia AverTV DVB-T USB 2.0 KCONFIG:= CONFIG_DVB_USB_A800 \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-a800.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-a800/description Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-a800 dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-avertv-a800-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_A800_FW_0:=dvb-usb-avertv-a800-02.fw define KernelPackage/dvb-usb-a800/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_A800_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-a800)) define KernelPackage/dvb-usb-dibusb-mb SUBMENU:=$(DVB_MENU) TITLE:=DiBcom USB DVB-T devices KCONFIG:= CONFIG_DVB_USB_DIBUSB_MB \ CONFIG_DVB_PLL \ CONFIG_DVB_DIB3000MB \ CONFIG_DVB_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-mb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dibusb-mb/description Say Y here to support the DiBcom USB DVB-T devices . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-dibusb-mb dvb-pll dib3000mb mt2060 You have to put the firmware files in the download dir : dvb-usb-dibusb-5.0.0.11.fw dvb-usb-dibusb-an2235-01.fw dvb-usb-adstech-usb2-02.fw dvb-usb-dibusb-6.0.0.8.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIBUSB_MB_FW_0:=dvb-usb-dibusb-5.0.0.11.fw DVB_USB_DIBUSB_MB_FW_1:=dvb-usb-dibusb-an2235-01.fw DVB_USB_DIBUSB_MB_FW_2:=dvb-usb-adstech-usb2-02.fw DVB_USB_DIBUSB_MB_FW_3:=dvb-usb-dibusb-6.0.0.8.fw define KernelPackage/dvb-usb-dibusb-mb/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_3) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dibusb-mb)) define KernelPackage/dvb-usb-dibusb-mc SUBMENU:=$(DVB_MENU) TITLE:=DiBcom USB DVB-T devices KCONFIG:= CONFIG_DVB_USB_DIBUSB_MC \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dibusb-mc/description Say Y here to support the DiBcom USB DVB-T devices . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-dibusb-mc dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-dibusb-6.0.0.8.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIBUSB_MC_FW_0:=dvb-usb-dibusb-6.0.0.8.fw define KernelPackage/dvb-usb-dibusb-mc/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MC_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dibusb-mc)) define KernelPackage/dvb-usb-dib0700 SUBMENU:=$(DVB_MENU) TITLE:=DiBcom DiB0700 USB DVB devices KCONFIG:= CONFIG_DVB_USB_DIB0700 \ CONFIG_DVB_DIB7000P \ CONFIG_DVB_DIB7000M \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dib0700.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000p.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000m.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dib0700/description Say Y here to support the DiBcom DiB0700 USB DVB devices . The following modules will be compiled for this device : dvb-usb-dib0700 dib7000p dibx000_common dib7000m dibx000_common dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-dib0700-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIB0700_FW_0:=dvb-usb-dib0700-01.fw define KernelPackage/dvb-usb-dib0700/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIB0700_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dib0700)) define KernelPackage/dvb-usb-umt-010 SUBMENU:=$(DVB_MENU) TITLE:=HanfTek UMT-010 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_UMT_010 \ CONFIG_DVB_PLL \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-umt-010.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-umt-010/description Say Y here to support the HanfTek UMT-010 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-umt-010 dvb-pll dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-umt-010-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_UMT_010_FW_0:=dvb-usb-umt-010-02.fw define KernelPackage/dvb-usb-umt-010/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_UMT_010_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-umt-010)) define KernelPackage/dvb-usb-cxusb SUBMENU:=$(DVB_MENU) TITLE:=Conexant USB2.0 hybrid reference design KCONFIG:= CONFIG_DVB_USB_CXUSB \ CONFIG_DVB_PLL \ CONFIG_DVB_CX22702 \ CONFIG_DVB_LGDT330X \ CONFIG_DVB_MT352 \ CONFIG_DVB_ZL10353 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-cxusb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/cx22702.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lgdt330x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-cxusb/description Say Y here to support the Conexant USB2.0 hybrid reference design . The following modules will be compiled for this device : dvb-usb-cxusb dvb-pll cx22702 lgdt330x mt352 zl10353 You have to put the firmware files in the download dir : dvb-usb-bluebird-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_CXUSB_FW_0:=dvb-usb-bluebird-01.fw define KernelPackage/dvb-usb-cxusb/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_CXUSB_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-cxusb)) define KernelPackage/dvb-usb-m920x SUBMENU:=$(DVB_MENU) TITLE:=Uli m920x DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_M920X \ CONFIG_DVB_MT352 \ CONFIG_DVB_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-m920x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-m920x/description Say Y here to support the Uli m920x DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-m920x mt352 qt1010 You have to put the firmware files in the download dir : dvb-usb-megasky-02.fw dvb-usb-digivox-02.fw dvb-usb-tvwalkert.fw dvb-usb-dposh-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_M920X_FW_0:=dvb-usb-megasky-02.fw DVB_USB_M920X_FW_1:=dvb-usb-digivox-02.fw DVB_USB_M920X_FW_2:=dvb-usb-tvwalkert.fw DVB_USB_M920X_FW_3:=dvb-usb-dposh-01.fw define KernelPackage/dvb-usb-m920x/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_3) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-m920x)) define KernelPackage/dvb-usb-gl861 SUBMENU:=$(DVB_MENU) TITLE:=Genesys Logic GL861 USB2.0 KCONFIG:= CONFIG_DVB_USB_GL861 \ CONFIG_DVB_ZL10353 \ CONFIG_DVB_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-gl861.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-gl861/description Say Y here to support the Genesys Logic GL861 USB2.0 . The following modules will be compiled for this device : dvb-usb-gl861 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-gl861)) define KernelPackage/dvb-usb-au6610 SUBMENU:=$(DVB_MENU) TITLE:=Alcor Micro AU6610 USB2.0 KCONFIG:= CONFIG_DVB_USB_AU6610 \ CONFIG_DVB_ZL10353 \ CONFIG_DVB_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-au6610.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-au6610/description Say Y here to support the Alcor Micro AU6610 USB2.0 . The following modules will be compiled for this device : dvb-usb-au6610 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-au6610)) define KernelPackage/dvb-usb-digitv SUBMENU:=$(DVB_MENU) TITLE:=Nebula Electronics uDigiTV DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_DIGITV \ CONFIG_DVB_PLL \ CONFIG_DVB_NXT6000 \ CONFIG_DVB_MT352 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-digitv.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/nxt6000.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-digitv/description Say Y here to support the Nebula Electronics uDigiTV DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-digitv dvb-pll nxt6000 mt352 You have to put the firmware files in the download dir : dvb-usb-digitv-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIGITV_FW_0:=dvb-usb-digitv-02.fw define KernelPackage/dvb-usb-digitv/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIGITV_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-digitv)) define KernelPackage/dvb-usb-vp7045 SUBMENU:=$(DVB_MENU) TITLE:=TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle KCONFIG:= CONFIG_DVB_USB_VP7045 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-vp7045.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-vp7045/description Say Y here to support the TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle. The following modules will be compiled for this device : dvb-usb-vp7045 You have to put the firmware files in the download dir : dvb-usb-vp7045-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_VP7045_FW_0:=dvb-usb-vp7045-01.fw define KernelPackage/dvb-usb-vp7045/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_VP7045_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-vp7045)) define KernelPackage/dvb-usb-vp702x SUBMENU:=$(DVB_MENU) TITLE:=TwinhanDTV StarBox and clones DVB-S USB2.0 KCONFIG:= CONFIG_DVB_USB_VP702X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-vp702x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-vp702x/description Say Y here to support the TwinhanDTV StarBox and clones DVB-S USB2.0 . The following modules will be compiled for this device : dvb-usb-vp702x You have to put the firmware files in the download dir : dvb-usb-vp702x-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_VP702X_FW_0:=dvb-usb-vp702x-02.fw define KernelPackage/dvb-usb-vp702x/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_VP702X_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-vp702x)) define KernelPackage/dvb-usb-gp8psk SUBMENU:=$(DVB_MENU) TITLE:=GENPIX 8PSK->USB module KCONFIG:= CONFIG_DVB_USB_GP8PSK DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-gp8psk.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-gp8psk/description Say Y here to support the GENPIX 8PSK->USB module . The following modules will be compiled for this device : dvb-usb-gp8psk You have to put the firmware files in the download dir : dvb-usb-gp8psk-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_GP8PSK_FW_0:=dvb-usb-gp8psk-01.fw define KernelPackage/dvb-usb-gp8psk/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_GP8PSK_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-gp8psk)) define KernelPackage/dvb-usb-nova-t-usb2 SUBMENU:=$(DVB_MENU) TITLE:=Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_NOVA_T_USB2 \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-nova-t-usb2.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-nova-t-usb2/description Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-nova-t-usb2 dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-nova-t-usb2-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_NOVA_T_USB2_FW_0:=dvb-usb-nova-t-usb2-02.fw define KernelPackage/dvb-usb-nova-t-usb2/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_NOVA_T_USB2_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-nova-t-usb2)) define KernelPackage/dvb-usb-ttusb2 SUBMENU:=$(DVB_MENU) TITLE:=Pinnacle 400e DVB-S USB2.0 KCONFIG:= CONFIG_DVB_USB_TTUSB2 \ CONFIG_DVB_TDA10086 \ CONFIG_DVB_LNBP21 \ CONFIG_DVB_TDA826X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-ttusb2.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda10086.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lnbp21.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda826x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-ttusb2/description Say Y here to support the Pinnacle 400e DVB-S USB2.0 . The following modules will be compiled for this device : dvb-usb-ttusb2 tda10086 lnbp21 tda826x You have to put the firmware files in the download dir : dvb-usb-pctv-400e-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_TTUSB2_FW_0:=dvb-usb-pctv-400e-01.fw define KernelPackage/dvb-usb-ttusb2/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_TTUSB2_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-ttusb2)) define KernelPackage/dvb-usb-dtt200u SUBMENU:=$(DVB_MENU) TITLE:=WideView WT-200U and WT-220U DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_DTT200U DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dtt200u.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dtt200u/description Say Y here to support the WideView WT-200U and WT-220U DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dtt200u You have to put the firmware files in the download dir : dvb-usb-dtt200u-01.fw dvb-usb-wt220u-02.fw dvb-usb-wt220u-fc03.fw dvb-usb-wt220u-zl0353-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DTT200U_FW_0:=dvb-usb-dtt200u-01.fw DVB_USB_DTT200U_FW_1:=dvb-usb-wt220u-02.fw DVB_USB_DTT200U_FW_2:=dvb-usb-wt220u-fc03.fw DVB_USB_DTT200U_FW_3:=dvb-usb-wt220u-zl0353-01.fw define KernelPackage/dvb-usb-dtt200u/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_3) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dtt200u)) define KernelPackage/dvb-usb-opera1 SUBMENU:=$(DVB_MENU) TITLE:=Opera1 DVB-S USB2.0 receiver KCONFIG:= CONFIG_DVB_USB_OPERA1 \ CONFIG_DVB_STV0299 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-opera.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/stv0299.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-opera1/description Say Y here to support the Opera1 DVB-S USB2.0 receiver. The following modules will be compiled for this device : dvb-usb-opera stv0299 You have to put the firmware files in the download dir : dvb-usb-opera-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_OPERA1_FW_0:=dvb-usb-opera-01.fw define KernelPackage/dvb-usb-opera1/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_OPERA1_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-opera1)) MuMuDVB-2.1.0/openwrt/package/kernel/modules/dvb.2.6.23.17.mk000066400000000000000000000550221305714132500230400ustar00rootroot00000000000000 # # Copyright (C) 2009 Brice DUBOST # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. # # # !!!! This is a generated file !!!! # DVB_MENU:=DVB support # # General section # define KernelPackage/dvb-core SUBMENU:=$(DVB_MENU) TITLE:=DVB core support DEPENDS:=@LINUX_2_6 +kmod-i2c-core KCONFIG:= \ CONFIG_DVB_CORE \ CONFIG_DVB_CAPTURE_DRIVERS=y \ CONFIG_MEDIA_TUNER_CUSTOMIZE=y \ CONFIG_DVB_FE_CUSTOMISE=y \ CONFIG_CRC32 FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-core/dvb-core.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,50,dvb-core) endef define KernelPackage/dvb-core/description Kernel module for DVB support endef $(eval $(call KernelPackage,dvb-core)) define KernelPackage/dvb-usb SUBMENU:=$(DVB_MENU) TITLE:=DVB USB Support DEPENDS:=@USB_SUPPORT +kmod-dvb-core +kmod-usb-core KCONFIG:= \ CONFIG_DVB_USB \ CONFIG_INPUT=y FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb.$(LINUX_KMOD_SUFFIX) # AUTOLOAD:=$(call AutoLoad,55,dvb-usb) endef define KernelPackage/dvb-usb/description Kernel module for DVB USB devices. Note you have to select at least a device. endef $(eval $(call KernelPackage,dvb-usb)) # # Devices section # define KernelPackage/dvb-usb-a800 SUBMENU:=$(DVB_MENU) TITLE:=AVerMedia AverTV DVB-T USB 2.0 KCONFIG:= CONFIG_DVB_USB_A800 \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_TUNER_MT2060 \ CONFIG_DVB_PLL DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-a800.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-a800/description Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-a800 dib3000mc dibx000_common mt2060 dvb-pll You have to put the firmware files in the download dir : dvb-usb-avertv-a800-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_A800_FW_0:=dvb-usb-avertv-a800-02.fw define KernelPackage/dvb-usb-a800/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_A800_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-a800)) define KernelPackage/dvb-usb-dibusb-mb SUBMENU:=$(DVB_MENU) TITLE:=DiBcom USB DVB-T devices KCONFIG:= CONFIG_DVB_USB_DIBUSB_MB \ CONFIG_DVB_PLL \ CONFIG_DVB_DIB3000MB \ CONFIG_DVB_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-mb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dibusb-mb/description Say Y here to support the DiBcom USB DVB-T devices . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-dibusb-mb dvb-pll dib3000mb mt2060 You have to put the firmware files in the download dir : dvb-usb-dibusb-5.0.0.11.fw dvb-usb-dibusb-an2235-01.fw dvb-usb-adstech-usb2-02.fw dvb-usb-dibusb-6.0.0.8.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIBUSB_MB_FW_0:=dvb-usb-dibusb-5.0.0.11.fw DVB_USB_DIBUSB_MB_FW_1:=dvb-usb-dibusb-an2235-01.fw DVB_USB_DIBUSB_MB_FW_2:=dvb-usb-adstech-usb2-02.fw DVB_USB_DIBUSB_MB_FW_3:=dvb-usb-dibusb-6.0.0.8.fw define KernelPackage/dvb-usb-dibusb-mb/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_3) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dibusb-mb)) define KernelPackage/dvb-usb-dibusb-mc SUBMENU:=$(DVB_MENU) TITLE:=DiBcom USB DVB-T devices KCONFIG:= CONFIG_DVB_USB_DIBUSB_MC \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dibusb-mc/description Say Y here to support the DiBcom USB DVB-T devices . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-dibusb-mc dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-dibusb-6.0.0.8.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIBUSB_MC_FW_0:=dvb-usb-dibusb-6.0.0.8.fw define KernelPackage/dvb-usb-dibusb-mc/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MC_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dibusb-mc)) define KernelPackage/dvb-usb-dib0700 SUBMENU:=$(DVB_MENU) TITLE:=DiBcom DiB0700 USB DVB devices KCONFIG:= CONFIG_DVB_USB_DIB0700 \ CONFIG_DVB_DIB7000P \ CONFIG_DVB_DIB7000M \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dib0700.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000p.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000m.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dib0700/description Say Y here to support the DiBcom DiB0700 USB DVB devices . The following modules will be compiled for this device : dvb-usb-dib0700 dib7000p dibx000_common dib7000m dibx000_common dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-dib0700-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIB0700_FW_0:=dvb-usb-dib0700-01.fw define KernelPackage/dvb-usb-dib0700/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIB0700_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dib0700)) define KernelPackage/dvb-usb-umt-010 SUBMENU:=$(DVB_MENU) TITLE:=HanfTek UMT-010 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_UMT_010 \ CONFIG_DVB_PLL \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-umt-010.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-umt-010/description Say Y here to support the HanfTek UMT-010 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-umt-010 dvb-pll dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-umt-010-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_UMT_010_FW_0:=dvb-usb-umt-010-02.fw define KernelPackage/dvb-usb-umt-010/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_UMT_010_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-umt-010)) define KernelPackage/dvb-usb-cxusb SUBMENU:=$(DVB_MENU) TITLE:=Conexant USB2.0 hybrid reference design KCONFIG:= CONFIG_DVB_USB_CXUSB \ CONFIG_DVB_PLL \ CONFIG_DVB_CX22702 \ CONFIG_DVB_LGDT330X \ CONFIG_DVB_MT352 \ CONFIG_DVB_ZL10353 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-cxusb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/cx22702.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lgdt330x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-cxusb/description Say Y here to support the Conexant USB2.0 hybrid reference design . The following modules will be compiled for this device : dvb-usb-cxusb dvb-pll cx22702 lgdt330x mt352 zl10353 You have to put the firmware files in the download dir : dvb-usb-bluebird-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_CXUSB_FW_0:=dvb-usb-bluebird-01.fw define KernelPackage/dvb-usb-cxusb/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_CXUSB_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-cxusb)) define KernelPackage/dvb-usb-m920x SUBMENU:=$(DVB_MENU) TITLE:=Uli m920x DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_M920X \ CONFIG_DVB_MT352 \ CONFIG_DVB_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-m920x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-m920x/description Say Y here to support the Uli m920x DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-m920x mt352 qt1010 You have to put the firmware files in the download dir : dvb-usb-megasky-02.fw dvb-usb-digivox-02.fw dvb-usb-tvwalkert.fw dvb-usb-dposh-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_M920X_FW_0:=dvb-usb-megasky-02.fw DVB_USB_M920X_FW_1:=dvb-usb-digivox-02.fw DVB_USB_M920X_FW_2:=dvb-usb-tvwalkert.fw DVB_USB_M920X_FW_3:=dvb-usb-dposh-01.fw define KernelPackage/dvb-usb-m920x/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_3) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-m920x)) define KernelPackage/dvb-usb-gl861 SUBMENU:=$(DVB_MENU) TITLE:=Genesys Logic GL861 USB2.0 KCONFIG:= CONFIG_DVB_USB_GL861 \ CONFIG_DVB_ZL10353 \ CONFIG_DVB_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-gl861.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-gl861/description Say Y here to support the Genesys Logic GL861 USB2.0 . The following modules will be compiled for this device : dvb-usb-gl861 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-gl861)) define KernelPackage/dvb-usb-au6610 SUBMENU:=$(DVB_MENU) TITLE:=Alcor Micro AU6610 USB2.0 KCONFIG:= CONFIG_DVB_USB_AU6610 \ CONFIG_DVB_ZL10353 \ CONFIG_DVB_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-au6610.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-au6610/description Say Y here to support the Alcor Micro AU6610 USB2.0 . The following modules will be compiled for this device : dvb-usb-au6610 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-au6610)) define KernelPackage/dvb-usb-digitv SUBMENU:=$(DVB_MENU) TITLE:=Nebula Electronics uDigiTV DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_DIGITV \ CONFIG_DVB_PLL \ CONFIG_DVB_NXT6000 \ CONFIG_DVB_MT352 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-digitv.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/nxt6000.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-digitv/description Say Y here to support the Nebula Electronics uDigiTV DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-digitv dvb-pll nxt6000 mt352 You have to put the firmware files in the download dir : dvb-usb-digitv-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIGITV_FW_0:=dvb-usb-digitv-02.fw define KernelPackage/dvb-usb-digitv/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIGITV_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-digitv)) define KernelPackage/dvb-usb-vp7045 SUBMENU:=$(DVB_MENU) TITLE:=TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle KCONFIG:= CONFIG_DVB_USB_VP7045 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-vp7045.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-vp7045/description Say Y here to support the TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle. The following modules will be compiled for this device : dvb-usb-vp7045 You have to put the firmware files in the download dir : dvb-usb-vp7045-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_VP7045_FW_0:=dvb-usb-vp7045-01.fw define KernelPackage/dvb-usb-vp7045/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_VP7045_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-vp7045)) define KernelPackage/dvb-usb-vp702x SUBMENU:=$(DVB_MENU) TITLE:=TwinhanDTV StarBox and clones DVB-S USB2.0 KCONFIG:= CONFIG_DVB_USB_VP702X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-vp702x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-vp702x/description Say Y here to support the TwinhanDTV StarBox and clones DVB-S USB2.0 . The following modules will be compiled for this device : dvb-usb-vp702x You have to put the firmware files in the download dir : dvb-usb-vp702x-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_VP702X_FW_0:=dvb-usb-vp702x-02.fw define KernelPackage/dvb-usb-vp702x/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_VP702X_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-vp702x)) define KernelPackage/dvb-usb-gp8psk SUBMENU:=$(DVB_MENU) TITLE:=GENPIX 8PSK->USB module KCONFIG:= CONFIG_DVB_USB_GP8PSK DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-gp8psk.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-gp8psk/description Say Y here to support the GENPIX 8PSK->USB module . The following modules will be compiled for this device : dvb-usb-gp8psk You have to put the firmware files in the download dir : dvb-usb-gp8psk-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_GP8PSK_FW_0:=dvb-usb-gp8psk-01.fw define KernelPackage/dvb-usb-gp8psk/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_GP8PSK_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-gp8psk)) define KernelPackage/dvb-usb-nova-t-usb2 SUBMENU:=$(DVB_MENU) TITLE:=Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_NOVA_T_USB2 \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_TUNER_MT2060 \ CONFIG_DVB_PLL DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-nova-t-usb2.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-nova-t-usb2/description Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-nova-t-usb2 dib3000mc dibx000_common mt2060 dvb-pll You have to put the firmware files in the download dir : dvb-usb-nova-t-usb2-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_NOVA_T_USB2_FW_0:=dvb-usb-nova-t-usb2-02.fw define KernelPackage/dvb-usb-nova-t-usb2/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_NOVA_T_USB2_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-nova-t-usb2)) define KernelPackage/dvb-usb-ttusb2 SUBMENU:=$(DVB_MENU) TITLE:=Pinnacle 400e DVB-S USB2.0 KCONFIG:= CONFIG_DVB_USB_TTUSB2 \ CONFIG_DVB_TDA10086 \ CONFIG_DVB_LNBP21 \ CONFIG_DVB_TDA826X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-ttusb2.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda10086.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lnbp21.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda826x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-ttusb2/description Say Y here to support the Pinnacle 400e DVB-S USB2.0 . The following modules will be compiled for this device : dvb-usb-ttusb2 tda10086 lnbp21 tda826x You have to put the firmware files in the download dir : dvb-usb-pctv-400e-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_TTUSB2_FW_0:=dvb-usb-pctv-400e-01.fw define KernelPackage/dvb-usb-ttusb2/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_TTUSB2_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-ttusb2)) define KernelPackage/dvb-usb-dtt200u SUBMENU:=$(DVB_MENU) TITLE:=WideView WT-200U and WT-220U DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_DTT200U DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dtt200u.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dtt200u/description Say Y here to support the WideView WT-200U and WT-220U DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dtt200u You have to put the firmware files in the download dir : dvb-usb-dtt200u-01.fw dvb-usb-wt220u-02.fw dvb-usb-wt220u-fc03.fw dvb-usb-wt220u-zl0353-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DTT200U_FW_0:=dvb-usb-dtt200u-01.fw DVB_USB_DTT200U_FW_1:=dvb-usb-wt220u-02.fw DVB_USB_DTT200U_FW_2:=dvb-usb-wt220u-fc03.fw DVB_USB_DTT200U_FW_3:=dvb-usb-wt220u-zl0353-01.fw define KernelPackage/dvb-usb-dtt200u/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_3) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dtt200u)) define KernelPackage/dvb-usb-opera1 SUBMENU:=$(DVB_MENU) TITLE:=Opera1 DVB-S USB2.0 receiver KCONFIG:= CONFIG_DVB_USB_OPERA1 \ CONFIG_DVB_STV0299 \ CONFIG_DVB_PLL DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-opera.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/stv0299.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-opera1/description Say Y here to support the Opera1 DVB-S USB2.0 receiver. The following modules will be compiled for this device : dvb-usb-opera stv0299 dvb-pll You have to put the firmware files in the download dir : dvb-usb-opera-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_OPERA1_FW_0:=dvb-usb-opera-01.fw define KernelPackage/dvb-usb-opera1/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_OPERA1_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-opera1)) define KernelPackage/dvb-usb-af9005 SUBMENU:=$(DVB_MENU) TITLE:=Afatech AF9005 DVB-T USB1.1 KCONFIG:= CONFIG_DVB_USB_AF9005 \ CONFIG_DVB_TUNER_MT2060 \ CONFIG_DVB_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-af9005/description Say Y here to support the Afatech AF9005 DVB-T USB1.1 . The following modules will be compiled for this device : dvb-usb-af9005 dvb-usb-af9005-remote mt2060 qt1010 You have to put the firmware files in the download dir : af9005.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_AF9005_FW_0:=af9005.fw define KernelPackage/dvb-usb-af9005/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_AF9005_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-af9005)) define KernelPackage/dvb-usb-af9005-remote SUBMENU:=$(DVB_MENU) TITLE:=Afatech AF9005 default remote control KCONFIG:= CONFIG_DVB_USB_AF9005_REMOTE DEPENDS:=+kmod-dvb-usb-af9005 FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-af9005-remote/description Say Y here to support the Afatech AF9005 default remote control . The following modules will be compiled for this device : dvb-usb-af9005-remote endef $(eval $(call KernelPackage,dvb-usb-af9005-remote)) MuMuDVB-2.1.0/openwrt/package/kernel/modules/dvb.2.6.24.7.mk000066400000000000000000000556011305714132500227630ustar00rootroot00000000000000 # # Copyright (C) 2009 Brice DUBOST # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. # # # !!!! This is a generated file !!!! # DVB_MENU:=DVB support # # General section # define KernelPackage/dvb-core SUBMENU:=$(DVB_MENU) TITLE:=DVB core support DEPENDS:=@LINUX_2_6 +kmod-i2c-core KCONFIG:= \ CONFIG_DVB_CORE \ CONFIG_DVB_CAPTURE_DRIVERS=y \ CONFIG_MEDIA_TUNER_CUSTOMIZE=y \ CONFIG_DVB_FE_CUSTOMISE=y \ CONFIG_CRC32 FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-core/dvb-core.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,50,dvb-core) endef define KernelPackage/dvb-core/description Kernel module for DVB support endef $(eval $(call KernelPackage,dvb-core)) define KernelPackage/dvb-usb SUBMENU:=$(DVB_MENU) TITLE:=DVB USB Support DEPENDS:=@USB_SUPPORT +kmod-dvb-core +kmod-usb-core KCONFIG:= \ CONFIG_DVB_USB \ CONFIG_INPUT=y FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb.$(LINUX_KMOD_SUFFIX) # AUTOLOAD:=$(call AutoLoad,55,dvb-usb) endef define KernelPackage/dvb-usb/description Kernel module for DVB USB devices. Note you have to select at least a device. endef $(eval $(call KernelPackage,dvb-usb)) # # Devices section # define KernelPackage/dvb-usb-a800 SUBMENU:=$(DVB_MENU) TITLE:=AVerMedia AverTV DVB-T USB 2.0 KCONFIG:= CONFIG_DVB_USB_A800 \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_TUNER_MT2060 \ CONFIG_DVB_PLL DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-a800.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-a800/description Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-a800 dib3000mc dibx000_common mt2060 dvb-pll You have to put the firmware files in the download dir : dvb-usb-avertv-a800-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_A800_FW_0:=dvb-usb-avertv-a800-02.fw define KernelPackage/dvb-usb-a800/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_A800_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-a800)) define KernelPackage/dvb-usb-dibusb-mb SUBMENU:=$(DVB_MENU) TITLE:=DiBcom USB DVB-T devices KCONFIG:= CONFIG_DVB_USB_DIBUSB_MB \ CONFIG_DVB_PLL \ CONFIG_DVB_DIB3000MB \ CONFIG_DVB_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-mb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dibusb-mb/description Say Y here to support the DiBcom USB DVB-T devices . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-dibusb-mb dvb-pll dib3000mb mt2060 You have to put the firmware files in the download dir : dvb-usb-dibusb-5.0.0.11.fw dvb-usb-dibusb-an2235-01.fw dvb-usb-adstech-usb2-02.fw dvb-usb-dibusb-6.0.0.8.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIBUSB_MB_FW_0:=dvb-usb-dibusb-5.0.0.11.fw DVB_USB_DIBUSB_MB_FW_1:=dvb-usb-dibusb-an2235-01.fw DVB_USB_DIBUSB_MB_FW_2:=dvb-usb-adstech-usb2-02.fw DVB_USB_DIBUSB_MB_FW_3:=dvb-usb-dibusb-6.0.0.8.fw define KernelPackage/dvb-usb-dibusb-mb/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_3) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dibusb-mb)) define KernelPackage/dvb-usb-dibusb-mc SUBMENU:=$(DVB_MENU) TITLE:=DiBcom USB DVB-T devices KCONFIG:= CONFIG_DVB_USB_DIBUSB_MC \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dibusb-mc/description Say Y here to support the DiBcom USB DVB-T devices . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-dibusb-mc dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-dibusb-6.0.0.8.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIBUSB_MC_FW_0:=dvb-usb-dibusb-6.0.0.8.fw define KernelPackage/dvb-usb-dibusb-mc/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MC_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dibusb-mc)) define KernelPackage/dvb-usb-dib0700 SUBMENU:=$(DVB_MENU) TITLE:=DiBcom DiB0700 USB DVB devices KCONFIG:= CONFIG_DVB_USB_DIB0700 \ CONFIG_DVB_DIB7000P \ CONFIG_DVB_DIB7000M \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_TUNER_MT2060 \ CONFIG_DVB_TUNER_MT2266 \ CONFIG_DVB_TUNER_DIB0070 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dib0700.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000p.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000m.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2266.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib0070.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dib0700/description Say Y here to support the DiBcom DiB0700 USB DVB devices . The following modules will be compiled for this device : dvb-usb-dib0700 dib7000p dibx000_common dib7000m dibx000_common dib3000mc dibx000_common mt2060 mt2266 dib0070 You have to put the firmware files in the download dir : dvb-usb-dib0700-1.10.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIB0700_FW_0:=dvb-usb-dib0700-1.10.fw define KernelPackage/dvb-usb-dib0700/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIB0700_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dib0700)) define KernelPackage/dvb-usb-umt-010 SUBMENU:=$(DVB_MENU) TITLE:=HanfTek UMT-010 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_UMT_010 \ CONFIG_DVB_PLL \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-umt-010.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-umt-010/description Say Y here to support the HanfTek UMT-010 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-umt-010 dvb-pll dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-umt-010-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_UMT_010_FW_0:=dvb-usb-umt-010-02.fw define KernelPackage/dvb-usb-umt-010/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_UMT_010_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-umt-010)) define KernelPackage/dvb-usb-cxusb SUBMENU:=$(DVB_MENU) TITLE:=Conexant USB2.0 hybrid reference design KCONFIG:= CONFIG_DVB_USB_CXUSB \ CONFIG_DVB_PLL \ CONFIG_DVB_CX22702 \ CONFIG_DVB_LGDT330X \ CONFIG_DVB_MT352 \ CONFIG_DVB_ZL10353 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-cxusb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/cx22702.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lgdt330x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-cxusb/description Say Y here to support the Conexant USB2.0 hybrid reference design . The following modules will be compiled for this device : dvb-usb-cxusb dvb-pll cx22702 lgdt330x mt352 zl10353 You have to put the firmware files in the download dir : dvb-usb-bluebird-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_CXUSB_FW_0:=dvb-usb-bluebird-01.fw define KernelPackage/dvb-usb-cxusb/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_CXUSB_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-cxusb)) define KernelPackage/dvb-usb-m920x SUBMENU:=$(DVB_MENU) TITLE:=Uli m920x DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_M920X \ CONFIG_DVB_MT352 \ CONFIG_DVB_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-m920x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-m920x/description Say Y here to support the Uli m920x DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-m920x mt352 qt1010 You have to put the firmware files in the download dir : dvb-usb-megasky-02.fw dvb-usb-digivox-02.fw dvb-usb-tvwalkert.fw dvb-usb-dposh-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_M920X_FW_0:=dvb-usb-megasky-02.fw DVB_USB_M920X_FW_1:=dvb-usb-digivox-02.fw DVB_USB_M920X_FW_2:=dvb-usb-tvwalkert.fw DVB_USB_M920X_FW_3:=dvb-usb-dposh-01.fw define KernelPackage/dvb-usb-m920x/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_3) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-m920x)) define KernelPackage/dvb-usb-gl861 SUBMENU:=$(DVB_MENU) TITLE:=Genesys Logic GL861 USB2.0 KCONFIG:= CONFIG_DVB_USB_GL861 \ CONFIG_DVB_ZL10353 \ CONFIG_DVB_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-gl861.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-gl861/description Say Y here to support the Genesys Logic GL861 USB2.0 . The following modules will be compiled for this device : dvb-usb-gl861 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-gl861)) define KernelPackage/dvb-usb-au6610 SUBMENU:=$(DVB_MENU) TITLE:=Alcor Micro AU6610 USB2.0 KCONFIG:= CONFIG_DVB_USB_AU6610 \ CONFIG_DVB_ZL10353 \ CONFIG_DVB_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-au6610.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-au6610/description Say Y here to support the Alcor Micro AU6610 USB2.0 . The following modules will be compiled for this device : dvb-usb-au6610 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-au6610)) define KernelPackage/dvb-usb-digitv SUBMENU:=$(DVB_MENU) TITLE:=Nebula Electronics uDigiTV DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_DIGITV \ CONFIG_DVB_PLL \ CONFIG_DVB_NXT6000 \ CONFIG_DVB_MT352 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-digitv.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/nxt6000.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-digitv/description Say Y here to support the Nebula Electronics uDigiTV DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-digitv dvb-pll nxt6000 mt352 You have to put the firmware files in the download dir : dvb-usb-digitv-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIGITV_FW_0:=dvb-usb-digitv-02.fw define KernelPackage/dvb-usb-digitv/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIGITV_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-digitv)) define KernelPackage/dvb-usb-vp7045 SUBMENU:=$(DVB_MENU) TITLE:=TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle KCONFIG:= CONFIG_DVB_USB_VP7045 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-vp7045.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-vp7045/description Say Y here to support the TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle. The following modules will be compiled for this device : dvb-usb-vp7045 You have to put the firmware files in the download dir : dvb-usb-vp7045-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_VP7045_FW_0:=dvb-usb-vp7045-01.fw define KernelPackage/dvb-usb-vp7045/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_VP7045_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-vp7045)) define KernelPackage/dvb-usb-vp702x SUBMENU:=$(DVB_MENU) TITLE:=TwinhanDTV StarBox and clones DVB-S USB2.0 KCONFIG:= CONFIG_DVB_USB_VP702X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-vp702x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-vp702x/description Say Y here to support the TwinhanDTV StarBox and clones DVB-S USB2.0 . The following modules will be compiled for this device : dvb-usb-vp702x You have to put the firmware files in the download dir : dvb-usb-vp702x-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_VP702X_FW_0:=dvb-usb-vp702x-02.fw define KernelPackage/dvb-usb-vp702x/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_VP702X_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-vp702x)) define KernelPackage/dvb-usb-gp8psk SUBMENU:=$(DVB_MENU) TITLE:=GENPIX 8PSK->USB module KCONFIG:= CONFIG_DVB_USB_GP8PSK DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-gp8psk.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-gp8psk/description Say Y here to support the GENPIX 8PSK->USB module . The following modules will be compiled for this device : dvb-usb-gp8psk You have to put the firmware files in the download dir : dvb-usb-gp8psk-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_GP8PSK_FW_0:=dvb-usb-gp8psk-01.fw define KernelPackage/dvb-usb-gp8psk/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_GP8PSK_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-gp8psk)) define KernelPackage/dvb-usb-nova-t-usb2 SUBMENU:=$(DVB_MENU) TITLE:=Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_NOVA_T_USB2 \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_TUNER_MT2060 \ CONFIG_DVB_PLL DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-nova-t-usb2.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-nova-t-usb2/description Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-nova-t-usb2 dib3000mc dibx000_common mt2060 dvb-pll You have to put the firmware files in the download dir : dvb-usb-nova-t-usb2-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_NOVA_T_USB2_FW_0:=dvb-usb-nova-t-usb2-02.fw define KernelPackage/dvb-usb-nova-t-usb2/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_NOVA_T_USB2_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-nova-t-usb2)) define KernelPackage/dvb-usb-ttusb2 SUBMENU:=$(DVB_MENU) TITLE:=Pinnacle 400e DVB-S USB2.0 KCONFIG:= CONFIG_DVB_USB_TTUSB2 \ CONFIG_DVB_TDA10086 \ CONFIG_DVB_LNBP21 \ CONFIG_DVB_TDA826X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-ttusb2.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda10086.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lnbp21.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda826x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-ttusb2/description Say Y here to support the Pinnacle 400e DVB-S USB2.0 . The following modules will be compiled for this device : dvb-usb-ttusb2 tda10086 lnbp21 tda826x You have to put the firmware files in the download dir : dvb-usb-pctv-400e-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_TTUSB2_FW_0:=dvb-usb-pctv-400e-01.fw define KernelPackage/dvb-usb-ttusb2/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_TTUSB2_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-ttusb2)) define KernelPackage/dvb-usb-dtt200u SUBMENU:=$(DVB_MENU) TITLE:=WideView WT-200U and WT-220U DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_DTT200U DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dtt200u.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dtt200u/description Say Y here to support the WideView WT-200U and WT-220U DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dtt200u You have to put the firmware files in the download dir : dvb-usb-dtt200u-01.fw dvb-usb-wt220u-02.fw dvb-usb-wt220u-fc03.fw dvb-usb-wt220u-zl0353-01.fw dvb-usb-wt220u-miglia-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DTT200U_FW_0:=dvb-usb-dtt200u-01.fw DVB_USB_DTT200U_FW_1:=dvb-usb-wt220u-02.fw DVB_USB_DTT200U_FW_2:=dvb-usb-wt220u-fc03.fw DVB_USB_DTT200U_FW_3:=dvb-usb-wt220u-zl0353-01.fw DVB_USB_DTT200U_FW_4:=dvb-usb-wt220u-miglia-01.fw define KernelPackage/dvb-usb-dtt200u/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_3) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_4) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dtt200u)) define KernelPackage/dvb-usb-opera1 SUBMENU:=$(DVB_MENU) TITLE:=Opera1 DVB-S USB2.0 receiver KCONFIG:= CONFIG_DVB_USB_OPERA1 \ CONFIG_DVB_STV0299 \ CONFIG_DVB_PLL DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-opera.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/stv0299.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-opera1/description Say Y here to support the Opera1 DVB-S USB2.0 receiver. The following modules will be compiled for this device : dvb-usb-opera stv0299 dvb-pll You have to put the firmware files in the download dir : dvb-usb-opera-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_OPERA1_FW_0:=dvb-usb-opera-01.fw define KernelPackage/dvb-usb-opera1/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_OPERA1_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-opera1)) define KernelPackage/dvb-usb-af9005 SUBMENU:=$(DVB_MENU) TITLE:=Afatech AF9005 DVB-T USB1.1 KCONFIG:= CONFIG_DVB_USB_AF9005 \ CONFIG_DVB_TUNER_MT2060 \ CONFIG_DVB_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-af9005/description Say Y here to support the Afatech AF9005 DVB-T USB1.1 . The following modules will be compiled for this device : dvb-usb-af9005 dvb-usb-af9005-remote mt2060 qt1010 You have to put the firmware files in the download dir : af9005.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_AF9005_FW_0:=af9005.fw define KernelPackage/dvb-usb-af9005/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_AF9005_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-af9005)) define KernelPackage/dvb-usb-af9005-remote SUBMENU:=$(DVB_MENU) TITLE:=Afatech AF9005 default remote control KCONFIG:= CONFIG_DVB_USB_AF9005_REMOTE DEPENDS:=+kmod-dvb-usb-af9005 FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-af9005-remote/description Say Y here to support the Afatech AF9005 default remote control . The following modules will be compiled for this device : dvb-usb-af9005-remote endef $(eval $(call KernelPackage,dvb-usb-af9005-remote)) MuMuDVB-2.1.0/openwrt/package/kernel/modules/dvb.2.6.25.20.mk000066400000000000000000000560071305714132500230400ustar00rootroot00000000000000 # # Copyright (C) 2009 Brice DUBOST # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. # # # !!!! This is a generated file !!!! # DVB_MENU:=DVB support # # General section # define KernelPackage/dvb-core SUBMENU:=$(DVB_MENU) TITLE:=DVB core support DEPENDS:=@LINUX_2_6 +kmod-i2c-core KCONFIG:= \ CONFIG_DVB_CORE \ CONFIG_DVB_CAPTURE_DRIVERS=y \ CONFIG_MEDIA_TUNER_CUSTOMIZE=y \ CONFIG_DVB_FE_CUSTOMISE=y \ CONFIG_CRC32 FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-core/dvb-core.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,50,dvb-core) endef define KernelPackage/dvb-core/description Kernel module for DVB support endef $(eval $(call KernelPackage,dvb-core)) define KernelPackage/dvb-usb SUBMENU:=$(DVB_MENU) TITLE:=DVB USB Support DEPENDS:=@USB_SUPPORT +kmod-dvb-core +kmod-usb-core KCONFIG:= \ CONFIG_DVB_USB \ CONFIG_INPUT=y FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb.$(LINUX_KMOD_SUFFIX) # AUTOLOAD:=$(call AutoLoad,55,dvb-usb) endef define KernelPackage/dvb-usb/description Kernel module for DVB USB devices. Note you have to select at least a device. endef $(eval $(call KernelPackage,dvb-usb)) # # Devices section # define KernelPackage/dvb-usb-a800 SUBMENU:=$(DVB_MENU) TITLE:=AVerMedia AverTV DVB-T USB 2.0 KCONFIG:= CONFIG_DVB_USB_A800 \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_TUNER_MT2060 \ CONFIG_DVB_PLL DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-a800.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-a800/description Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-a800 dib3000mc dibx000_common mt2060 dvb-pll You have to put the firmware files in the download dir : dvb-usb-avertv-a800-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_A800_FW_0:=dvb-usb-avertv-a800-02.fw define KernelPackage/dvb-usb-a800/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_A800_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-a800)) define KernelPackage/dvb-usb-dibusb-mb SUBMENU:=$(DVB_MENU) TITLE:=DiBcom USB DVB-T devices KCONFIG:= CONFIG_DVB_USB_DIBUSB_MB \ CONFIG_DVB_PLL \ CONFIG_DVB_DIB3000MB \ CONFIG_DVB_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-mb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dibusb-mb/description Say Y here to support the DiBcom USB DVB-T devices . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-dibusb-mb dvb-pll dib3000mb mt2060 You have to put the firmware files in the download dir : dvb-usb-dibusb-5.0.0.11.fw dvb-usb-dibusb-an2235-01.fw dvb-usb-adstech-usb2-02.fw dvb-usb-dibusb-6.0.0.8.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIBUSB_MB_FW_0:=dvb-usb-dibusb-5.0.0.11.fw DVB_USB_DIBUSB_MB_FW_1:=dvb-usb-dibusb-an2235-01.fw DVB_USB_DIBUSB_MB_FW_2:=dvb-usb-adstech-usb2-02.fw DVB_USB_DIBUSB_MB_FW_3:=dvb-usb-dibusb-6.0.0.8.fw define KernelPackage/dvb-usb-dibusb-mb/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_3) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dibusb-mb)) define KernelPackage/dvb-usb-dibusb-mc SUBMENU:=$(DVB_MENU) TITLE:=DiBcom USB DVB-T devices KCONFIG:= CONFIG_DVB_USB_DIBUSB_MC \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dibusb-mc/description Say Y here to support the DiBcom USB DVB-T devices . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-dibusb-mc dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-dibusb-6.0.0.8.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIBUSB_MC_FW_0:=dvb-usb-dibusb-6.0.0.8.fw define KernelPackage/dvb-usb-dibusb-mc/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MC_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dibusb-mc)) define KernelPackage/dvb-usb-dib0700 SUBMENU:=$(DVB_MENU) TITLE:=DiBcom DiB0700 USB DVB devices KCONFIG:= CONFIG_DVB_USB_DIB0700 \ CONFIG_DVB_DIB7000P \ CONFIG_DVB_DIB7000M \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_TUNER_MT2060 \ CONFIG_DVB_TUNER_MT2266 \ CONFIG_DVB_TUNER_DIB0070 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dib0700.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000p.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000m.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2266.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib0070.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dib0700/description Say Y here to support the DiBcom DiB0700 USB DVB devices . The following modules will be compiled for this device : dvb-usb-dib0700 dib7000p dibx000_common dib7000m dibx000_common dib3000mc dibx000_common mt2060 mt2266 dib0070 You have to put the firmware files in the download dir : dvb-usb-dib0700-1.10.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIB0700_FW_0:=dvb-usb-dib0700-1.10.fw define KernelPackage/dvb-usb-dib0700/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIB0700_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dib0700)) define KernelPackage/dvb-usb-umt-010 SUBMENU:=$(DVB_MENU) TITLE:=HanfTek UMT-010 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_UMT_010 \ CONFIG_DVB_PLL \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-umt-010.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-umt-010/description Say Y here to support the HanfTek UMT-010 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-umt-010 dvb-pll dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-umt-010-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_UMT_010_FW_0:=dvb-usb-umt-010-02.fw define KernelPackage/dvb-usb-umt-010/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_UMT_010_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-umt-010)) define KernelPackage/dvb-usb-cxusb SUBMENU:=$(DVB_MENU) TITLE:=Conexant USB2.0 hybrid reference design KCONFIG:= CONFIG_DVB_USB_CXUSB \ CONFIG_DVB_PLL \ CONFIG_DVB_CX22702 \ CONFIG_DVB_LGDT330X \ CONFIG_DVB_MT352 \ CONFIG_DVB_ZL10353 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-cxusb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/cx22702.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lgdt330x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-cxusb/description Say Y here to support the Conexant USB2.0 hybrid reference design . The following modules will be compiled for this device : dvb-usb-cxusb dvb-pll cx22702 lgdt330x mt352 zl10353 You have to put the firmware files in the download dir : dvb-usb-bluebird-01.fw dvb-usb-bluebird-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_CXUSB_FW_0:=dvb-usb-bluebird-01.fw DVB_USB_CXUSB_FW_1:=dvb-usb-bluebird-02.fw define KernelPackage/dvb-usb-cxusb/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_CXUSB_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_CXUSB_FW_1) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-cxusb)) define KernelPackage/dvb-usb-m920x SUBMENU:=$(DVB_MENU) TITLE:=Uli m920x DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_M920X \ CONFIG_DVB_MT352 \ CONFIG_DVB_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-m920x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-m920x/description Say Y here to support the Uli m920x DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-m920x mt352 qt1010 You have to put the firmware files in the download dir : dvb-usb-megasky-02.fw dvb-usb-digivox-02.fw dvb-usb-tvwalkert.fw dvb-usb-dposh-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_M920X_FW_0:=dvb-usb-megasky-02.fw DVB_USB_M920X_FW_1:=dvb-usb-digivox-02.fw DVB_USB_M920X_FW_2:=dvb-usb-tvwalkert.fw DVB_USB_M920X_FW_3:=dvb-usb-dposh-01.fw define KernelPackage/dvb-usb-m920x/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_3) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-m920x)) define KernelPackage/dvb-usb-gl861 SUBMENU:=$(DVB_MENU) TITLE:=Genesys Logic GL861 USB2.0 KCONFIG:= CONFIG_DVB_USB_GL861 \ CONFIG_DVB_ZL10353 \ CONFIG_DVB_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-gl861.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-gl861/description Say Y here to support the Genesys Logic GL861 USB2.0 . The following modules will be compiled for this device : dvb-usb-gl861 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-gl861)) define KernelPackage/dvb-usb-au6610 SUBMENU:=$(DVB_MENU) TITLE:=Alcor Micro AU6610 USB2.0 KCONFIG:= CONFIG_DVB_USB_AU6610 \ CONFIG_DVB_ZL10353 \ CONFIG_DVB_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-au6610.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-au6610/description Say Y here to support the Alcor Micro AU6610 USB2.0 . The following modules will be compiled for this device : dvb-usb-au6610 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-au6610)) define KernelPackage/dvb-usb-digitv SUBMENU:=$(DVB_MENU) TITLE:=Nebula Electronics uDigiTV DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_DIGITV \ CONFIG_DVB_PLL \ CONFIG_DVB_NXT6000 \ CONFIG_DVB_MT352 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-digitv.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/nxt6000.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-digitv/description Say Y here to support the Nebula Electronics uDigiTV DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-digitv dvb-pll nxt6000 mt352 You have to put the firmware files in the download dir : dvb-usb-digitv-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIGITV_FW_0:=dvb-usb-digitv-02.fw define KernelPackage/dvb-usb-digitv/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIGITV_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-digitv)) define KernelPackage/dvb-usb-vp7045 SUBMENU:=$(DVB_MENU) TITLE:=TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle KCONFIG:= CONFIG_DVB_USB_VP7045 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-vp7045.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-vp7045/description Say Y here to support the TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle. The following modules will be compiled for this device : dvb-usb-vp7045 You have to put the firmware files in the download dir : dvb-usb-vp7045-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_VP7045_FW_0:=dvb-usb-vp7045-01.fw define KernelPackage/dvb-usb-vp7045/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_VP7045_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-vp7045)) define KernelPackage/dvb-usb-vp702x SUBMENU:=$(DVB_MENU) TITLE:=TwinhanDTV StarBox and clones DVB-S USB2.0 KCONFIG:= CONFIG_DVB_USB_VP702X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-vp702x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-vp702x/description Say Y here to support the TwinhanDTV StarBox and clones DVB-S USB2.0 . The following modules will be compiled for this device : dvb-usb-vp702x You have to put the firmware files in the download dir : dvb-usb-vp702x-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_VP702X_FW_0:=dvb-usb-vp702x-02.fw define KernelPackage/dvb-usb-vp702x/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_VP702X_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-vp702x)) define KernelPackage/dvb-usb-gp8psk SUBMENU:=$(DVB_MENU) TITLE:=GENPIX 8PSK->USB module KCONFIG:= CONFIG_DVB_USB_GP8PSK DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-gp8psk.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-gp8psk/description Say Y here to support the GENPIX 8PSK->USB module . The following modules will be compiled for this device : dvb-usb-gp8psk You have to put the firmware files in the download dir : dvb-usb-gp8psk-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_GP8PSK_FW_0:=dvb-usb-gp8psk-01.fw define KernelPackage/dvb-usb-gp8psk/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_GP8PSK_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-gp8psk)) define KernelPackage/dvb-usb-nova-t-usb2 SUBMENU:=$(DVB_MENU) TITLE:=Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_NOVA_T_USB2 \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_TUNER_MT2060 \ CONFIG_DVB_PLL DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-nova-t-usb2.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-nova-t-usb2/description Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-nova-t-usb2 dib3000mc dibx000_common mt2060 dvb-pll You have to put the firmware files in the download dir : dvb-usb-nova-t-usb2-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_NOVA_T_USB2_FW_0:=dvb-usb-nova-t-usb2-02.fw define KernelPackage/dvb-usb-nova-t-usb2/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_NOVA_T_USB2_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-nova-t-usb2)) define KernelPackage/dvb-usb-ttusb2 SUBMENU:=$(DVB_MENU) TITLE:=Pinnacle 400e DVB-S USB2.0 KCONFIG:= CONFIG_DVB_USB_TTUSB2 \ CONFIG_DVB_TDA10086 \ CONFIG_DVB_LNBP21 \ CONFIG_DVB_TDA826X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-ttusb2.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda10086.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lnbp21.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda826x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-ttusb2/description Say Y here to support the Pinnacle 400e DVB-S USB2.0 . The following modules will be compiled for this device : dvb-usb-ttusb2 tda10086 lnbp21 tda826x You have to put the firmware files in the download dir : dvb-usb-pctv-400e-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_TTUSB2_FW_0:=dvb-usb-pctv-400e-01.fw define KernelPackage/dvb-usb-ttusb2/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_TTUSB2_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-ttusb2)) define KernelPackage/dvb-usb-dtt200u SUBMENU:=$(DVB_MENU) TITLE:=WideView WT-200U and WT-220U DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_DTT200U DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dtt200u.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dtt200u/description Say Y here to support the WideView WT-200U and WT-220U DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dtt200u You have to put the firmware files in the download dir : dvb-usb-dtt200u-01.fw dvb-usb-wt220u-02.fw dvb-usb-wt220u-fc03.fw dvb-usb-wt220u-zl0353-01.fw dvb-usb-wt220u-miglia-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DTT200U_FW_0:=dvb-usb-dtt200u-01.fw DVB_USB_DTT200U_FW_1:=dvb-usb-wt220u-02.fw DVB_USB_DTT200U_FW_2:=dvb-usb-wt220u-fc03.fw DVB_USB_DTT200U_FW_3:=dvb-usb-wt220u-zl0353-01.fw DVB_USB_DTT200U_FW_4:=dvb-usb-wt220u-miglia-01.fw define KernelPackage/dvb-usb-dtt200u/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_3) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_4) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dtt200u)) define KernelPackage/dvb-usb-opera1 SUBMENU:=$(DVB_MENU) TITLE:=Opera1 DVB-S USB2.0 receiver KCONFIG:= CONFIG_DVB_USB_OPERA1 \ CONFIG_DVB_STV0299 \ CONFIG_DVB_PLL DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-opera.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/stv0299.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-opera1/description Say Y here to support the Opera1 DVB-S USB2.0 receiver. The following modules will be compiled for this device : dvb-usb-opera stv0299 dvb-pll You have to put the firmware files in the download dir : dvb-usb-opera-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_OPERA1_FW_0:=dvb-usb-opera-01.fw define KernelPackage/dvb-usb-opera1/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_OPERA1_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-opera1)) define KernelPackage/dvb-usb-af9005 SUBMENU:=$(DVB_MENU) TITLE:=Afatech AF9005 DVB-T USB1.1 KCONFIG:= CONFIG_DVB_USB_AF9005 \ CONFIG_DVB_TUNER_MT2060 \ CONFIG_DVB_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-af9005/description Say Y here to support the Afatech AF9005 DVB-T USB1.1 . The following modules will be compiled for this device : dvb-usb-af9005 dvb-usb-af9005-remote mt2060 qt1010 You have to put the firmware files in the download dir : af9005.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_AF9005_FW_0:=af9005.fw define KernelPackage/dvb-usb-af9005/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_AF9005_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-af9005)) define KernelPackage/dvb-usb-af9005-remote SUBMENU:=$(DVB_MENU) TITLE:=Afatech AF9005 default remote control KCONFIG:= CONFIG_DVB_USB_AF9005_REMOTE DEPENDS:=+kmod-dvb-usb-af9005 FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-af9005-remote/description Say Y here to support the Afatech AF9005 default remote control . The following modules will be compiled for this device : dvb-usb-af9005-remote endef $(eval $(call KernelPackage,dvb-usb-af9005-remote)) MuMuDVB-2.1.0/openwrt/package/kernel/modules/dvb.2.6.26.8.mk000066400000000000000000000565701305714132500227740ustar00rootroot00000000000000 # # Copyright (C) 2009 Brice DUBOST # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. # # # !!!! This is a generated file !!!! # DVB_MENU:=DVB support # # General section # define KernelPackage/dvb-core SUBMENU:=$(DVB_MENU) TITLE:=DVB core support DEPENDS:=@LINUX_2_6 +kmod-i2c-core KCONFIG:= \ CONFIG_DVB_CORE \ CONFIG_DVB_CAPTURE_DRIVERS=y \ CONFIG_MEDIA_TUNER_CUSTOMIZE=y \ CONFIG_DVB_FE_CUSTOMISE=y \ CONFIG_CRC32 FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-core/dvb-core.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,50,dvb-core) endef define KernelPackage/dvb-core/description Kernel module for DVB support endef $(eval $(call KernelPackage,dvb-core)) define KernelPackage/dvb-usb SUBMENU:=$(DVB_MENU) TITLE:=DVB USB Support DEPENDS:=@USB_SUPPORT +kmod-dvb-core +kmod-usb-core KCONFIG:= \ CONFIG_DVB_USB \ CONFIG_INPUT=y FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb.$(LINUX_KMOD_SUFFIX) # AUTOLOAD:=$(call AutoLoad,55,dvb-usb) endef define KernelPackage/dvb-usb/description Kernel module for DVB USB devices. Note you have to select at least a device. endef $(eval $(call KernelPackage,dvb-usb)) # # Devices section # define KernelPackage/dvb-usb-a800 SUBMENU:=$(DVB_MENU) TITLE:=AVerMedia AverTV DVB-T USB 2.0 KCONFIG:= CONFIG_DVB_USB_A800 \ CONFIG_DVB_DIB3000MC \ CONFIG_MEDIA_TUNER_MT2060 \ CONFIG_DVB_PLL DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-a800.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-a800/description Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-a800 dib3000mc dibx000_common mt2060 dvb-pll You have to put the firmware files in the download dir : dvb-usb-avertv-a800-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_A800_FW_0:=dvb-usb-avertv-a800-02.fw define KernelPackage/dvb-usb-a800/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_A800_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-a800)) define KernelPackage/dvb-usb-dibusb-mb SUBMENU:=$(DVB_MENU) TITLE:=DiBcom USB DVB-T devices KCONFIG:= CONFIG_DVB_USB_DIBUSB_MB \ CONFIG_DVB_PLL \ CONFIG_DVB_DIB3000MB \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-mb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dibusb-mb/description Say Y here to support the DiBcom USB DVB-T devices . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-dibusb-mb dvb-pll dib3000mb mt2060 You have to put the firmware files in the download dir : dvb-usb-dibusb-5.0.0.11.fw dvb-usb-dibusb-an2235-01.fw dvb-usb-adstech-usb2-02.fw dvb-usb-dibusb-6.0.0.8.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIBUSB_MB_FW_0:=dvb-usb-dibusb-5.0.0.11.fw DVB_USB_DIBUSB_MB_FW_1:=dvb-usb-dibusb-an2235-01.fw DVB_USB_DIBUSB_MB_FW_2:=dvb-usb-adstech-usb2-02.fw DVB_USB_DIBUSB_MB_FW_3:=dvb-usb-dibusb-6.0.0.8.fw define KernelPackage/dvb-usb-dibusb-mb/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_3) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dibusb-mb)) define KernelPackage/dvb-usb-dibusb-mc SUBMENU:=$(DVB_MENU) TITLE:=DiBcom USB DVB-T devices KCONFIG:= CONFIG_DVB_USB_DIBUSB_MC \ CONFIG_DVB_DIB3000MC \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dibusb-mc/description Say Y here to support the DiBcom USB DVB-T devices . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-dibusb-mc dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-dibusb-6.0.0.8.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIBUSB_MC_FW_0:=dvb-usb-dibusb-6.0.0.8.fw define KernelPackage/dvb-usb-dibusb-mc/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MC_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dibusb-mc)) define KernelPackage/dvb-usb-dib0700 SUBMENU:=$(DVB_MENU) TITLE:=DiBcom DiB0700 USB DVB devices KCONFIG:= CONFIG_DVB_USB_DIB0700 \ CONFIG_DVB_DIB7000P \ CONFIG_DVB_DIB7000M \ CONFIG_DVB_DIB3000MC \ CONFIG_MEDIA_TUNER_MT2060 \ CONFIG_MEDIA_TUNER_MT2266 \ CONFIG_DVB_TUNER_DIB0070 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dib0700.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000p.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000m.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2266.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib0070.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dib0700/description Say Y here to support the DiBcom DiB0700 USB DVB devices . The following modules will be compiled for this device : dvb-usb-dib0700 dib7000p dibx000_common dib7000m dibx000_common dib3000mc dibx000_common mt2060 mt2266 dib0070 You have to put the firmware files in the download dir : dvb-usb-dib0700-1.10.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIB0700_FW_0:=dvb-usb-dib0700-1.10.fw define KernelPackage/dvb-usb-dib0700/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIB0700_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dib0700)) define KernelPackage/dvb-usb-umt-010 SUBMENU:=$(DVB_MENU) TITLE:=HanfTek UMT-010 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_UMT_010 \ CONFIG_DVB_PLL \ CONFIG_DVB_DIB3000MC \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-umt-010.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-umt-010/description Say Y here to support the HanfTek UMT-010 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-umt-010 dvb-pll dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-umt-010-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_UMT_010_FW_0:=dvb-usb-umt-010-02.fw define KernelPackage/dvb-usb-umt-010/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_UMT_010_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-umt-010)) define KernelPackage/dvb-usb-cxusb SUBMENU:=$(DVB_MENU) TITLE:=Conexant USB2.0 hybrid reference design KCONFIG:= CONFIG_DVB_USB_CXUSB \ CONFIG_DVB_PLL \ CONFIG_DVB_CX22702 \ CONFIG_DVB_LGDT330X \ CONFIG_DVB_MT352 \ CONFIG_DVB_ZL10353 \ CONFIG_MEDIA_TUNER_SIMPLE DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-cxusb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/cx22702.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lgdt330x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tuner-simple.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tuner-types.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-cxusb/description Say Y here to support the Conexant USB2.0 hybrid reference design . The following modules will be compiled for this device : dvb-usb-cxusb dvb-pll cx22702 lgdt330x mt352 zl10353 tuner-simple tuner-types You have to put the firmware files in the download dir : dvb-usb-bluebird-01.fw dvb-usb-bluebird-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_CXUSB_FW_0:=dvb-usb-bluebird-01.fw DVB_USB_CXUSB_FW_1:=dvb-usb-bluebird-02.fw define KernelPackage/dvb-usb-cxusb/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_CXUSB_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_CXUSB_FW_1) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-cxusb)) define KernelPackage/dvb-usb-m920x SUBMENU:=$(DVB_MENU) TITLE:=Uli m920x DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_M920X \ CONFIG_DVB_MT352 \ CONFIG_MEDIA_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-m920x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-m920x/description Say Y here to support the Uli m920x DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-m920x mt352 qt1010 You have to put the firmware files in the download dir : dvb-usb-megasky-02.fw dvb-usb-digivox-02.fw dvb-usb-tvwalkert.fw dvb-usb-dposh-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_M920X_FW_0:=dvb-usb-megasky-02.fw DVB_USB_M920X_FW_1:=dvb-usb-digivox-02.fw DVB_USB_M920X_FW_2:=dvb-usb-tvwalkert.fw DVB_USB_M920X_FW_3:=dvb-usb-dposh-01.fw define KernelPackage/dvb-usb-m920x/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_3) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-m920x)) define KernelPackage/dvb-usb-gl861 SUBMENU:=$(DVB_MENU) TITLE:=Genesys Logic GL861 USB2.0 KCONFIG:= CONFIG_DVB_USB_GL861 \ CONFIG_DVB_ZL10353 \ CONFIG_MEDIA_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-gl861.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-gl861/description Say Y here to support the Genesys Logic GL861 USB2.0 . The following modules will be compiled for this device : dvb-usb-gl861 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-gl861)) define KernelPackage/dvb-usb-au6610 SUBMENU:=$(DVB_MENU) TITLE:=Alcor Micro AU6610 USB2.0 KCONFIG:= CONFIG_DVB_USB_AU6610 \ CONFIG_DVB_ZL10353 \ CONFIG_MEDIA_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-au6610.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-au6610/description Say Y here to support the Alcor Micro AU6610 USB2.0 . The following modules will be compiled for this device : dvb-usb-au6610 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-au6610)) define KernelPackage/dvb-usb-digitv SUBMENU:=$(DVB_MENU) TITLE:=Nebula Electronics uDigiTV DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_DIGITV \ CONFIG_DVB_PLL \ CONFIG_DVB_NXT6000 \ CONFIG_DVB_MT352 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-digitv.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/nxt6000.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-digitv/description Say Y here to support the Nebula Electronics uDigiTV DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-digitv dvb-pll nxt6000 mt352 You have to put the firmware files in the download dir : dvb-usb-digitv-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIGITV_FW_0:=dvb-usb-digitv-02.fw define KernelPackage/dvb-usb-digitv/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIGITV_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-digitv)) define KernelPackage/dvb-usb-vp7045 SUBMENU:=$(DVB_MENU) TITLE:=TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle KCONFIG:= CONFIG_DVB_USB_VP7045 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-vp7045.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-vp7045/description Say Y here to support the TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle. The following modules will be compiled for this device : dvb-usb-vp7045 You have to put the firmware files in the download dir : dvb-usb-vp7045-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_VP7045_FW_0:=dvb-usb-vp7045-01.fw define KernelPackage/dvb-usb-vp7045/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_VP7045_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-vp7045)) define KernelPackage/dvb-usb-vp702x SUBMENU:=$(DVB_MENU) TITLE:=TwinhanDTV StarBox and clones DVB-S USB2.0 KCONFIG:= CONFIG_DVB_USB_VP702X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-vp702x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-vp702x/description Say Y here to support the TwinhanDTV StarBox and clones DVB-S USB2.0 . The following modules will be compiled for this device : dvb-usb-vp702x You have to put the firmware files in the download dir : dvb-usb-vp702x-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_VP702X_FW_0:=dvb-usb-vp702x-02.fw define KernelPackage/dvb-usb-vp702x/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_VP702X_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-vp702x)) define KernelPackage/dvb-usb-gp8psk SUBMENU:=$(DVB_MENU) TITLE:=GENPIX 8PSK->USB module KCONFIG:= CONFIG_DVB_USB_GP8PSK DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-gp8psk.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-gp8psk/description Say Y here to support the GENPIX 8PSK->USB module . The following modules will be compiled for this device : dvb-usb-gp8psk You have to put the firmware files in the download dir : dvb-usb-gp8psk-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_GP8PSK_FW_0:=dvb-usb-gp8psk-01.fw define KernelPackage/dvb-usb-gp8psk/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_GP8PSK_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-gp8psk)) define KernelPackage/dvb-usb-nova-t-usb2 SUBMENU:=$(DVB_MENU) TITLE:=Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_NOVA_T_USB2 \ CONFIG_DVB_DIB3000MC \ CONFIG_MEDIA_TUNER_MT2060 \ CONFIG_DVB_PLL DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-nova-t-usb2.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-nova-t-usb2/description Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-nova-t-usb2 dib3000mc dibx000_common mt2060 dvb-pll You have to put the firmware files in the download dir : dvb-usb-nova-t-usb2-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_NOVA_T_USB2_FW_0:=dvb-usb-nova-t-usb2-02.fw define KernelPackage/dvb-usb-nova-t-usb2/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_NOVA_T_USB2_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-nova-t-usb2)) define KernelPackage/dvb-usb-ttusb2 SUBMENU:=$(DVB_MENU) TITLE:=Pinnacle 400e DVB-S USB2.0 KCONFIG:= CONFIG_DVB_USB_TTUSB2 \ CONFIG_DVB_TDA10086 \ CONFIG_DVB_LNBP21 \ CONFIG_DVB_TDA826X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-ttusb2.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda10086.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lnbp21.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda826x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-ttusb2/description Say Y here to support the Pinnacle 400e DVB-S USB2.0 . The following modules will be compiled for this device : dvb-usb-ttusb2 tda10086 lnbp21 tda826x You have to put the firmware files in the download dir : dvb-usb-pctv-400e-01.fw dvb-usb-tt-s2400-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_TTUSB2_FW_0:=dvb-usb-pctv-400e-01.fw DVB_USB_TTUSB2_FW_1:=dvb-usb-tt-s2400-01.fw define KernelPackage/dvb-usb-ttusb2/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_TTUSB2_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_TTUSB2_FW_1) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-ttusb2)) define KernelPackage/dvb-usb-dtt200u SUBMENU:=$(DVB_MENU) TITLE:=WideView WT-200U and WT-220U DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_DTT200U DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dtt200u.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dtt200u/description Say Y here to support the WideView WT-200U and WT-220U DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dtt200u You have to put the firmware files in the download dir : dvb-usb-dtt200u-01.fw dvb-usb-wt220u-02.fw dvb-usb-wt220u-fc03.fw dvb-usb-wt220u-zl0353-01.fw dvb-usb-wt220u-miglia-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DTT200U_FW_0:=dvb-usb-dtt200u-01.fw DVB_USB_DTT200U_FW_1:=dvb-usb-wt220u-02.fw DVB_USB_DTT200U_FW_2:=dvb-usb-wt220u-fc03.fw DVB_USB_DTT200U_FW_3:=dvb-usb-wt220u-zl0353-01.fw DVB_USB_DTT200U_FW_4:=dvb-usb-wt220u-miglia-01.fw define KernelPackage/dvb-usb-dtt200u/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_3) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_4) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dtt200u)) define KernelPackage/dvb-usb-opera1 SUBMENU:=$(DVB_MENU) TITLE:=Opera1 DVB-S USB2.0 receiver KCONFIG:= CONFIG_DVB_USB_OPERA1 \ CONFIG_DVB_STV0299 \ CONFIG_DVB_PLL DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-opera.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/stv0299.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-opera1/description Say Y here to support the Opera1 DVB-S USB2.0 receiver. The following modules will be compiled for this device : dvb-usb-opera stv0299 dvb-pll You have to put the firmware files in the download dir : dvb-usb-opera-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_OPERA1_FW_0:=dvb-usb-opera-01.fw define KernelPackage/dvb-usb-opera1/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_OPERA1_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-opera1)) define KernelPackage/dvb-usb-af9005 SUBMENU:=$(DVB_MENU) TITLE:=Afatech AF9005 DVB-T USB1.1 KCONFIG:= CONFIG_DVB_USB_AF9005 \ CONFIG_MEDIA_TUNER_MT2060 \ CONFIG_MEDIA_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-af9005/description Say Y here to support the Afatech AF9005 DVB-T USB1.1 . The following modules will be compiled for this device : dvb-usb-af9005 dvb-usb-af9005-remote mt2060 qt1010 You have to put the firmware files in the download dir : af9005.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_AF9005_FW_0:=af9005.fw define KernelPackage/dvb-usb-af9005/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_AF9005_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-af9005)) define KernelPackage/dvb-usb-af9005-remote SUBMENU:=$(DVB_MENU) TITLE:=Afatech AF9005 default remote control KCONFIG:= CONFIG_DVB_USB_AF9005_REMOTE DEPENDS:=+kmod-dvb-usb-af9005 FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-af9005-remote/description Say Y here to support the Afatech AF9005 default remote control . The following modules will be compiled for this device : dvb-usb-af9005-remote endef $(eval $(call KernelPackage,dvb-usb-af9005-remote)) MuMuDVB-2.1.0/openwrt/package/kernel/modules/dvb.2.6.27.41.mk000066400000000000000000000634661305714132500230540ustar00rootroot00000000000000 # # Copyright (C) 2009 Brice DUBOST # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. # # # !!!! This is a generated file !!!! # DVB_MENU:=DVB support # # General section # define KernelPackage/dvb-core SUBMENU:=$(DVB_MENU) TITLE:=DVB core support DEPENDS:=@LINUX_2_6 +kmod-i2c-core KCONFIG:= \ CONFIG_DVB_CORE \ CONFIG_DVB_CAPTURE_DRIVERS=y \ CONFIG_MEDIA_TUNER_CUSTOMIZE=y \ CONFIG_DVB_FE_CUSTOMISE=y \ CONFIG_CRC32 FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-core/dvb-core.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,50,dvb-core) endef define KernelPackage/dvb-core/description Kernel module for DVB support endef $(eval $(call KernelPackage,dvb-core)) define KernelPackage/dvb-usb SUBMENU:=$(DVB_MENU) TITLE:=DVB USB Support DEPENDS:=@USB_SUPPORT +kmod-dvb-core +kmod-usb-core KCONFIG:= \ CONFIG_DVB_USB \ CONFIG_INPUT=y FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb.$(LINUX_KMOD_SUFFIX) # AUTOLOAD:=$(call AutoLoad,55,dvb-usb) endef define KernelPackage/dvb-usb/description Kernel module for DVB USB devices. Note you have to select at least a device. endef $(eval $(call KernelPackage,dvb-usb)) # # Devices section # define KernelPackage/dvb-usb-a800 SUBMENU:=$(DVB_MENU) TITLE:=AVerMedia AverTV DVB-T USB 2.0 KCONFIG:= CONFIG_DVB_USB_A800 \ CONFIG_DVB_DIB3000MC \ CONFIG_MEDIA_TUNER_MT2060 \ CONFIG_DVB_PLL DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-a800.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-a800/description Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-a800 dib3000mc dibx000_common mt2060 dvb-pll You have to put the firmware files in the download dir : dvb-usb-avertv-a800-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_A800_FW_0:=dvb-usb-avertv-a800-02.fw define KernelPackage/dvb-usb-a800/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_A800_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-a800)) define KernelPackage/dvb-usb-dibusb-mb SUBMENU:=$(DVB_MENU) TITLE:=DiBcom USB DVB-T devices KCONFIG:= CONFIG_DVB_USB_DIBUSB_MB \ CONFIG_DVB_PLL \ CONFIG_DVB_DIB3000MB \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-mb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dibusb-mb/description Say Y here to support the DiBcom USB DVB-T devices . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-dibusb-mb dvb-pll dib3000mb mt2060 You have to put the firmware files in the download dir : dvb-usb-dibusb-5.0.0.11.fw dvb-usb-dibusb-an2235-01.fw dvb-usb-adstech-usb2-02.fw dvb-usb-dibusb-6.0.0.8.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIBUSB_MB_FW_0:=dvb-usb-dibusb-5.0.0.11.fw DVB_USB_DIBUSB_MB_FW_1:=dvb-usb-dibusb-an2235-01.fw DVB_USB_DIBUSB_MB_FW_2:=dvb-usb-adstech-usb2-02.fw DVB_USB_DIBUSB_MB_FW_3:=dvb-usb-dibusb-6.0.0.8.fw define KernelPackage/dvb-usb-dibusb-mb/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_3) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dibusb-mb)) define KernelPackage/dvb-usb-dibusb-mc SUBMENU:=$(DVB_MENU) TITLE:=DiBcom USB DVB-T devices KCONFIG:= CONFIG_DVB_USB_DIBUSB_MC \ CONFIG_DVB_DIB3000MC \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dibusb-mc/description Say Y here to support the DiBcom USB DVB-T devices . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-dibusb-mc dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-dibusb-6.0.0.8.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIBUSB_MC_FW_0:=dvb-usb-dibusb-6.0.0.8.fw define KernelPackage/dvb-usb-dibusb-mc/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MC_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dibusb-mc)) define KernelPackage/dvb-usb-dib0700 SUBMENU:=$(DVB_MENU) TITLE:=DiBcom DiB0700 USB DVB devices KCONFIG:= CONFIG_DVB_USB_DIB0700 \ CONFIG_DVB_DIB7000P \ CONFIG_DVB_DIB7000M \ CONFIG_DVB_DIB3000MC \ CONFIG_MEDIA_TUNER_MT2060 \ CONFIG_MEDIA_TUNER_MT2266 \ CONFIG_MEDIA_TUNER_XC2028 \ CONFIG_DVB_TUNER_DIB0070 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dib0700.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000p.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000m.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2266.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tuner-xc2028.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib0070.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dib0700/description Say Y here to support the DiBcom DiB0700 USB DVB devices . The following modules will be compiled for this device : dvb-usb-dib0700 dib7000p dibx000_common dib7000m dibx000_common dib3000mc dibx000_common mt2060 mt2266 tuner-xc2028 dib0070 You have to put the firmware files in the download dir : dvb-usb-dib0700-1.10.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIB0700_FW_0:=dvb-usb-dib0700-1.10.fw define KernelPackage/dvb-usb-dib0700/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIB0700_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dib0700)) define KernelPackage/dvb-usb-umt-010 SUBMENU:=$(DVB_MENU) TITLE:=HanfTek UMT-010 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_UMT_010 \ CONFIG_DVB_PLL \ CONFIG_DVB_DIB3000MC \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-umt-010.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-umt-010/description Say Y here to support the HanfTek UMT-010 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-umt-010 dvb-pll dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-umt-010-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_UMT_010_FW_0:=dvb-usb-umt-010-02.fw define KernelPackage/dvb-usb-umt-010/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_UMT_010_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-umt-010)) define KernelPackage/dvb-usb-cxusb SUBMENU:=$(DVB_MENU) TITLE:=Conexant USB2.0 hybrid reference design KCONFIG:= CONFIG_DVB_USB_CXUSB \ CONFIG_DVB_PLL \ CONFIG_DVB_CX22702 \ CONFIG_DVB_LGDT330X \ CONFIG_DVB_MT352 \ CONFIG_DVB_ZL10353 \ CONFIG_MEDIA_TUNER_SIMPLE \ CONFIG_MEDIA_TUNER_XC2028 \ CONFIG_MEDIA_TUNER_MXL5005S DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-cxusb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/cx22702.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lgdt330x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tuner-simple.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tuner-types.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tuner-xc2028.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mxl5005s.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-cxusb/description Say Y here to support the Conexant USB2.0 hybrid reference design . The following modules will be compiled for this device : dvb-usb-cxusb dvb-pll cx22702 lgdt330x mt352 zl10353 tuner-simple tuner-types tuner-xc2028 mxl5005s You have to put the firmware files in the download dir : dvb-usb-bluebird-01.fw dvb-usb-bluebird-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_CXUSB_FW_0:=dvb-usb-bluebird-01.fw DVB_USB_CXUSB_FW_1:=dvb-usb-bluebird-02.fw define KernelPackage/dvb-usb-cxusb/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_CXUSB_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_CXUSB_FW_1) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-cxusb)) define KernelPackage/dvb-usb-m920x SUBMENU:=$(DVB_MENU) TITLE:=Uli m920x DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_M920X \ CONFIG_DVB_MT352 \ CONFIG_MEDIA_TUNER_QT1010 \ CONFIG_MEDIA_TUNER_TDA827X \ CONFIG_DVB_TDA1004X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-m920x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tda827x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda1004x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-m920x/description Say Y here to support the Uli m920x DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-m920x mt352 qt1010 tda827x tda1004x You have to put the firmware files in the download dir : dvb-usb-megasky-02.fw dvb-usb-digivox-02.fw dvb-usb-tvwalkert.fw dvb-usb-dposh-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_M920X_FW_0:=dvb-usb-megasky-02.fw DVB_USB_M920X_FW_1:=dvb-usb-digivox-02.fw DVB_USB_M920X_FW_2:=dvb-usb-tvwalkert.fw DVB_USB_M920X_FW_3:=dvb-usb-dposh-01.fw define KernelPackage/dvb-usb-m920x/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_3) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-m920x)) define KernelPackage/dvb-usb-gl861 SUBMENU:=$(DVB_MENU) TITLE:=Genesys Logic GL861 USB2.0 KCONFIG:= CONFIG_DVB_USB_GL861 \ CONFIG_DVB_ZL10353 \ CONFIG_MEDIA_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-gl861.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-gl861/description Say Y here to support the Genesys Logic GL861 USB2.0 . The following modules will be compiled for this device : dvb-usb-gl861 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-gl861)) define KernelPackage/dvb-usb-au6610 SUBMENU:=$(DVB_MENU) TITLE:=Alcor Micro AU6610 USB2.0 KCONFIG:= CONFIG_DVB_USB_AU6610 \ CONFIG_DVB_ZL10353 \ CONFIG_MEDIA_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-au6610.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-au6610/description Say Y here to support the Alcor Micro AU6610 USB2.0 . The following modules will be compiled for this device : dvb-usb-au6610 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-au6610)) define KernelPackage/dvb-usb-digitv SUBMENU:=$(DVB_MENU) TITLE:=Nebula Electronics uDigiTV DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_DIGITV \ CONFIG_DVB_PLL \ CONFIG_DVB_NXT6000 \ CONFIG_DVB_MT352 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-digitv.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/nxt6000.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-digitv/description Say Y here to support the Nebula Electronics uDigiTV DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-digitv dvb-pll nxt6000 mt352 You have to put the firmware files in the download dir : dvb-usb-digitv-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIGITV_FW_0:=dvb-usb-digitv-02.fw define KernelPackage/dvb-usb-digitv/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIGITV_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-digitv)) define KernelPackage/dvb-usb-vp7045 SUBMENU:=$(DVB_MENU) TITLE:=TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle KCONFIG:= CONFIG_DVB_USB_VP7045 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-vp7045.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-vp7045/description Say Y here to support the TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle. The following modules will be compiled for this device : dvb-usb-vp7045 You have to put the firmware files in the download dir : dvb-usb-vp7045-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_VP7045_FW_0:=dvb-usb-vp7045-01.fw define KernelPackage/dvb-usb-vp7045/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_VP7045_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-vp7045)) define KernelPackage/dvb-usb-vp702x SUBMENU:=$(DVB_MENU) TITLE:=TwinhanDTV StarBox and clones DVB-S USB2.0 KCONFIG:= CONFIG_DVB_USB_VP702X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-vp702x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-vp702x/description Say Y here to support the TwinhanDTV StarBox and clones DVB-S USB2.0 . The following modules will be compiled for this device : dvb-usb-vp702x You have to put the firmware files in the download dir : dvb-usb-vp702x-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_VP702X_FW_0:=dvb-usb-vp702x-02.fw define KernelPackage/dvb-usb-vp702x/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_VP702X_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-vp702x)) define KernelPackage/dvb-usb-gp8psk SUBMENU:=$(DVB_MENU) TITLE:=GENPIX 8PSK->USB module KCONFIG:= CONFIG_DVB_USB_GP8PSK DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-gp8psk.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-gp8psk/description Say Y here to support the GENPIX 8PSK->USB module . The following modules will be compiled for this device : dvb-usb-gp8psk You have to put the firmware files in the download dir : dvb-usb-gp8psk-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_GP8PSK_FW_0:=dvb-usb-gp8psk-01.fw define KernelPackage/dvb-usb-gp8psk/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_GP8PSK_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-gp8psk)) define KernelPackage/dvb-usb-nova-t-usb2 SUBMENU:=$(DVB_MENU) TITLE:=Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_NOVA_T_USB2 \ CONFIG_DVB_DIB3000MC \ CONFIG_MEDIA_TUNER_MT2060 \ CONFIG_DVB_PLL DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-nova-t-usb2.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-nova-t-usb2/description Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-nova-t-usb2 dib3000mc dibx000_common mt2060 dvb-pll You have to put the firmware files in the download dir : dvb-usb-nova-t-usb2-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_NOVA_T_USB2_FW_0:=dvb-usb-nova-t-usb2-02.fw define KernelPackage/dvb-usb-nova-t-usb2/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_NOVA_T_USB2_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-nova-t-usb2)) define KernelPackage/dvb-usb-ttusb2 SUBMENU:=$(DVB_MENU) TITLE:=Pinnacle 400e DVB-S USB2.0 KCONFIG:= CONFIG_DVB_USB_TTUSB2 \ CONFIG_DVB_TDA10086 \ CONFIG_DVB_LNBP21 \ CONFIG_DVB_TDA826X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-ttusb2.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda10086.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lnbp21.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda826x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-ttusb2/description Say Y here to support the Pinnacle 400e DVB-S USB2.0 . The following modules will be compiled for this device : dvb-usb-ttusb2 tda10086 lnbp21 tda826x You have to put the firmware files in the download dir : dvb-usb-pctv-400e-01.fw dvb-usb-tt-s2400-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_TTUSB2_FW_0:=dvb-usb-pctv-400e-01.fw DVB_USB_TTUSB2_FW_1:=dvb-usb-tt-s2400-01.fw define KernelPackage/dvb-usb-ttusb2/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_TTUSB2_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_TTUSB2_FW_1) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-ttusb2)) define KernelPackage/dvb-usb-dtt200u SUBMENU:=$(DVB_MENU) TITLE:=WideView WT-200U and WT-220U DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_DTT200U DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dtt200u.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dtt200u/description Say Y here to support the WideView WT-200U and WT-220U DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dtt200u You have to put the firmware files in the download dir : dvb-usb-dtt200u-01.fw dvb-usb-wt220u-02.fw dvb-usb-wt220u-fc03.fw dvb-usb-wt220u-zl0353-01.fw dvb-usb-wt220u-miglia-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DTT200U_FW_0:=dvb-usb-dtt200u-01.fw DVB_USB_DTT200U_FW_1:=dvb-usb-wt220u-02.fw DVB_USB_DTT200U_FW_2:=dvb-usb-wt220u-fc03.fw DVB_USB_DTT200U_FW_3:=dvb-usb-wt220u-zl0353-01.fw DVB_USB_DTT200U_FW_4:=dvb-usb-wt220u-miglia-01.fw define KernelPackage/dvb-usb-dtt200u/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_3) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_4) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dtt200u)) define KernelPackage/dvb-usb-opera1 SUBMENU:=$(DVB_MENU) TITLE:=Opera1 DVB-S USB2.0 receiver KCONFIG:= CONFIG_DVB_USB_OPERA1 \ CONFIG_DVB_STV0299 \ CONFIG_DVB_PLL DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-opera.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/stv0299.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-opera1/description Say Y here to support the Opera1 DVB-S USB2.0 receiver. The following modules will be compiled for this device : dvb-usb-opera stv0299 dvb-pll You have to put the firmware files in the download dir : dvb-usb-opera-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_OPERA1_FW_0:=dvb-usb-opera-01.fw define KernelPackage/dvb-usb-opera1/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_OPERA1_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-opera1)) define KernelPackage/dvb-usb-af9005 SUBMENU:=$(DVB_MENU) TITLE:=Afatech AF9005 DVB-T USB1.1 KCONFIG:= CONFIG_DVB_USB_AF9005 \ CONFIG_MEDIA_TUNER_MT2060 \ CONFIG_MEDIA_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-af9005/description Say Y here to support the Afatech AF9005 DVB-T USB1.1 . The following modules will be compiled for this device : dvb-usb-af9005 dvb-usb-af9005-remote mt2060 qt1010 You have to put the firmware files in the download dir : af9005.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_AF9005_FW_0:=af9005.fw define KernelPackage/dvb-usb-af9005/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_AF9005_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-af9005)) define KernelPackage/dvb-usb-af9005-remote SUBMENU:=$(DVB_MENU) TITLE:=Afatech AF9005 default remote control KCONFIG:= CONFIG_DVB_USB_AF9005_REMOTE DEPENDS:=+kmod-dvb-usb-af9005 FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-af9005-remote/description Say Y here to support the Afatech AF9005 default remote control . The following modules will be compiled for this device : dvb-usb-af9005-remote endef $(eval $(call KernelPackage,dvb-usb-af9005-remote)) define KernelPackage/dvb-usb-dw2102 SUBMENU:=$(DVB_MENU) TITLE:=DvbWorld 2102 DVB-S USB2.0 receiver KCONFIG:= CONFIG_DVB_USB_DW2102 \ CONFIG_DVB_STV0299 \ CONFIG_DVB_PLL DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dw2102.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/stv0299.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dw2102/description Say Y here to support the DvbWorld 2102 DVB-S USB2.0 receiver. The following modules will be compiled for this device : dvb-usb-dw2102 stv0299 dvb-pll You have to put the firmware files in the download dir : dvb-usb-dw2102.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DW2102_FW_0:=dvb-usb-dw2102.fw define KernelPackage/dvb-usb-dw2102/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DW2102_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dw2102)) define KernelPackage/dvb-usb-anysee SUBMENU:=$(DVB_MENU) TITLE:=Anysee DVB-T/C USB2.0 KCONFIG:= CONFIG_DVB_USB_ANYSEE \ CONFIG_DVB_PLL \ CONFIG_DVB_MT352 \ CONFIG_DVB_ZL10353 \ CONFIG_DVB_TDA10023 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-anysee.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda10023.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-anysee/description Say Y here to support the Anysee DVB-T/C USB2.0 . The following modules will be compiled for this device : dvb-usb-anysee dvb-pll mt352 zl10353 tda10023 endef $(eval $(call KernelPackage,dvb-usb-anysee)) MuMuDVB-2.1.0/openwrt/package/kernel/modules/dvb.2.6.28.10.mk000066400000000000000000000727301305714132500230430ustar00rootroot00000000000000 # # Copyright (C) 2009 Brice DUBOST # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. # # # !!!! This is a generated file !!!! # DVB_MENU:=DVB support # # General section # define KernelPackage/dvb-core SUBMENU:=$(DVB_MENU) TITLE:=DVB core support DEPENDS:=@LINUX_2_6 +kmod-i2c-core KCONFIG:= \ CONFIG_DVB_CORE \ CONFIG_DVB_CAPTURE_DRIVERS=y \ CONFIG_MEDIA_TUNER_CUSTOMIZE=y \ CONFIG_DVB_FE_CUSTOMISE=y \ CONFIG_CRC32 FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-core/dvb-core.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,50,dvb-core) endef define KernelPackage/dvb-core/description Kernel module for DVB support endef $(eval $(call KernelPackage,dvb-core)) define KernelPackage/dvb-usb SUBMENU:=$(DVB_MENU) TITLE:=DVB USB Support DEPENDS:=@USB_SUPPORT +kmod-dvb-core +kmod-usb-core KCONFIG:= \ CONFIG_DVB_USB \ CONFIG_INPUT=y FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb.$(LINUX_KMOD_SUFFIX) # AUTOLOAD:=$(call AutoLoad,55,dvb-usb) endef define KernelPackage/dvb-usb/description Kernel module for DVB USB devices. Note you have to select at least a device. endef $(eval $(call KernelPackage,dvb-usb)) # # Devices section # define KernelPackage/dvb-usb-a800 SUBMENU:=$(DVB_MENU) TITLE:=AVerMedia AverTV DVB-T USB 2.0 KCONFIG:= CONFIG_DVB_USB_A800 \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_PLL \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-a800.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-a800/description Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-a800 dib3000mc dibx000_common dvb-pll mt2060 You have to put the firmware files in the download dir : dvb-usb-avertv-a800-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_A800_FW_0:=dvb-usb-avertv-a800-02.fw define KernelPackage/dvb-usb-a800/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_A800_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-a800)) define KernelPackage/dvb-usb-dibusb-mb SUBMENU:=$(DVB_MENU) TITLE:=DiBcom USB DVB-T devices KCONFIG:= CONFIG_DVB_USB_DIBUSB_MB \ CONFIG_DVB_PLL \ CONFIG_DVB_DIB3000MB \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-mb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dibusb-mb/description Say Y here to support the DiBcom USB DVB-T devices . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-dibusb-mb dvb-pll dib3000mb mt2060 You have to put the firmware files in the download dir : dvb-usb-dibusb-5.0.0.11.fw dvb-usb-dibusb-an2235-01.fw dvb-usb-adstech-usb2-02.fw dvb-usb-dibusb-6.0.0.8.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIBUSB_MB_FW_0:=dvb-usb-dibusb-5.0.0.11.fw DVB_USB_DIBUSB_MB_FW_1:=dvb-usb-dibusb-an2235-01.fw DVB_USB_DIBUSB_MB_FW_2:=dvb-usb-adstech-usb2-02.fw DVB_USB_DIBUSB_MB_FW_3:=dvb-usb-dibusb-6.0.0.8.fw define KernelPackage/dvb-usb-dibusb-mb/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_3) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dibusb-mb)) define KernelPackage/dvb-usb-dibusb-mc SUBMENU:=$(DVB_MENU) TITLE:=DiBcom USB DVB-T devices KCONFIG:= CONFIG_DVB_USB_DIBUSB_MC \ CONFIG_DVB_DIB3000MC \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dibusb-mc/description Say Y here to support the DiBcom USB DVB-T devices . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-dibusb-mc dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-dibusb-6.0.0.8.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIBUSB_MC_FW_0:=dvb-usb-dibusb-6.0.0.8.fw define KernelPackage/dvb-usb-dibusb-mc/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MC_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dibusb-mc)) define KernelPackage/dvb-usb-dib0700 SUBMENU:=$(DVB_MENU) TITLE:=DiBcom DiB0700 USB DVB devices KCONFIG:= CONFIG_DVB_USB_DIB0700 \ CONFIG_DVB_DIB7000P \ CONFIG_DVB_DIB7000M \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_S5H1411 \ CONFIG_DVB_TUNER_DIB0070 \ CONFIG_MEDIA_TUNER_MT2060 \ CONFIG_MEDIA_TUNER_MT2266 \ CONFIG_MEDIA_TUNER_XC2028 \ CONFIG_MEDIA_TUNER_XC5000 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dib0700.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000p.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000m.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/s5h1411.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib0070.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2266.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tuner-xc2028.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/xc5000.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dib0700/description Say Y here to support the DiBcom DiB0700 USB DVB devices . The following modules will be compiled for this device : dvb-usb-dib0700 dib7000p dibx000_common dib7000m dibx000_common dib3000mc dibx000_common s5h1411 dib0070 mt2060 mt2266 tuner-xc2028 xc5000 You have to put the firmware files in the download dir : dvb-usb-dib0700-1.20.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIB0700_FW_0:=dvb-usb-dib0700-1.20.fw define KernelPackage/dvb-usb-dib0700/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIB0700_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dib0700)) define KernelPackage/dvb-usb-umt-010 SUBMENU:=$(DVB_MENU) TITLE:=HanfTek UMT-010 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_UMT_010 \ CONFIG_DVB_PLL \ CONFIG_DVB_DIB3000MC \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-umt-010.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-umt-010/description Say Y here to support the HanfTek UMT-010 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-umt-010 dvb-pll dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-umt-010-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_UMT_010_FW_0:=dvb-usb-umt-010-02.fw define KernelPackage/dvb-usb-umt-010/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_UMT_010_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-umt-010)) define KernelPackage/dvb-usb-cxusb SUBMENU:=$(DVB_MENU) TITLE:=Conexant USB2.0 hybrid reference design KCONFIG:= CONFIG_DVB_USB_CXUSB \ CONFIG_DVB_PLL \ CONFIG_DVB_CX22702 \ CONFIG_DVB_LGDT330X \ CONFIG_DVB_MT352 \ CONFIG_DVB_ZL10353 \ CONFIG_DVB_DIB7000P \ CONFIG_DVB_TUNER_DIB0070 \ CONFIG_MEDIA_TUNER_SIMPLE \ CONFIG_MEDIA_TUNER_XC2028 \ CONFIG_MEDIA_TUNER_MXL5005S DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-cxusb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/cx22702.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lgdt330x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000p.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib0070.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tuner-simple.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tuner-types.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tuner-xc2028.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mxl5005s.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-cxusb/description Say Y here to support the Conexant USB2.0 hybrid reference design . The following modules will be compiled for this device : dvb-usb-cxusb dvb-pll cx22702 lgdt330x mt352 zl10353 dib7000p dibx000_common dib0070 tuner-simple tuner-types tuner-xc2028 mxl5005s You have to put the firmware files in the download dir : dvb-usb-bluebird-01.fw dvb-usb-bluebird-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_CXUSB_FW_0:=dvb-usb-bluebird-01.fw DVB_USB_CXUSB_FW_1:=dvb-usb-bluebird-02.fw define KernelPackage/dvb-usb-cxusb/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_CXUSB_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_CXUSB_FW_1) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-cxusb)) define KernelPackage/dvb-usb-m920x SUBMENU:=$(DVB_MENU) TITLE:=Uli m920x DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_M920X \ CONFIG_DVB_MT352 \ CONFIG_DVB_TDA1004X \ CONFIG_MEDIA_TUNER_QT1010 \ CONFIG_MEDIA_TUNER_TDA827X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-m920x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda1004x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tda827x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-m920x/description Say Y here to support the Uli m920x DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-m920x mt352 tda1004x qt1010 tda827x You have to put the firmware files in the download dir : dvb-usb-megasky-02.fw dvb-usb-digivox-02.fw dvb-usb-tvwalkert.fw dvb-usb-dposh-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_M920X_FW_0:=dvb-usb-megasky-02.fw DVB_USB_M920X_FW_1:=dvb-usb-digivox-02.fw DVB_USB_M920X_FW_2:=dvb-usb-tvwalkert.fw DVB_USB_M920X_FW_3:=dvb-usb-dposh-01.fw define KernelPackage/dvb-usb-m920x/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_3) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-m920x)) define KernelPackage/dvb-usb-gl861 SUBMENU:=$(DVB_MENU) TITLE:=Genesys Logic GL861 USB2.0 KCONFIG:= CONFIG_DVB_USB_GL861 \ CONFIG_DVB_ZL10353 \ CONFIG_MEDIA_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-gl861.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-gl861/description Say Y here to support the Genesys Logic GL861 USB2.0 . The following modules will be compiled for this device : dvb-usb-gl861 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-gl861)) define KernelPackage/dvb-usb-au6610 SUBMENU:=$(DVB_MENU) TITLE:=Alcor Micro AU6610 USB2.0 KCONFIG:= CONFIG_DVB_USB_AU6610 \ CONFIG_DVB_ZL10353 \ CONFIG_MEDIA_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-au6610.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-au6610/description Say Y here to support the Alcor Micro AU6610 USB2.0 . The following modules will be compiled for this device : dvb-usb-au6610 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-au6610)) define KernelPackage/dvb-usb-digitv SUBMENU:=$(DVB_MENU) TITLE:=Nebula Electronics uDigiTV DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_DIGITV \ CONFIG_DVB_PLL \ CONFIG_DVB_NXT6000 \ CONFIG_DVB_MT352 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-digitv.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/nxt6000.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-digitv/description Say Y here to support the Nebula Electronics uDigiTV DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-digitv dvb-pll nxt6000 mt352 You have to put the firmware files in the download dir : dvb-usb-digitv-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIGITV_FW_0:=dvb-usb-digitv-02.fw define KernelPackage/dvb-usb-digitv/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIGITV_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-digitv)) define KernelPackage/dvb-usb-vp7045 SUBMENU:=$(DVB_MENU) TITLE:=TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle KCONFIG:= CONFIG_DVB_USB_VP7045 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-vp7045.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-vp7045/description Say Y here to support the TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle. The following modules will be compiled for this device : dvb-usb-vp7045 You have to put the firmware files in the download dir : dvb-usb-vp7045-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_VP7045_FW_0:=dvb-usb-vp7045-01.fw define KernelPackage/dvb-usb-vp7045/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_VP7045_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-vp7045)) define KernelPackage/dvb-usb-vp702x SUBMENU:=$(DVB_MENU) TITLE:=TwinhanDTV StarBox and clones DVB-S USB2.0 KCONFIG:= CONFIG_DVB_USB_VP702X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-vp702x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-vp702x/description Say Y here to support the TwinhanDTV StarBox and clones DVB-S USB2.0 . The following modules will be compiled for this device : dvb-usb-vp702x You have to put the firmware files in the download dir : dvb-usb-vp702x-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_VP702X_FW_0:=dvb-usb-vp702x-02.fw define KernelPackage/dvb-usb-vp702x/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_VP702X_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-vp702x)) define KernelPackage/dvb-usb-gp8psk SUBMENU:=$(DVB_MENU) TITLE:=GENPIX 8PSK->USB module KCONFIG:= CONFIG_DVB_USB_GP8PSK DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-gp8psk.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-gp8psk/description Say Y here to support the GENPIX 8PSK->USB module . The following modules will be compiled for this device : dvb-usb-gp8psk You have to put the firmware files in the download dir : dvb-usb-gp8psk-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_GP8PSK_FW_0:=dvb-usb-gp8psk-01.fw define KernelPackage/dvb-usb-gp8psk/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_GP8PSK_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-gp8psk)) define KernelPackage/dvb-usb-nova-t-usb2 SUBMENU:=$(DVB_MENU) TITLE:=Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_NOVA_T_USB2 \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_PLL \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-nova-t-usb2.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-nova-t-usb2/description Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-nova-t-usb2 dib3000mc dibx000_common dvb-pll mt2060 You have to put the firmware files in the download dir : dvb-usb-nova-t-usb2-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_NOVA_T_USB2_FW_0:=dvb-usb-nova-t-usb2-02.fw define KernelPackage/dvb-usb-nova-t-usb2/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_NOVA_T_USB2_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-nova-t-usb2)) define KernelPackage/dvb-usb-ttusb2 SUBMENU:=$(DVB_MENU) TITLE:=Pinnacle 400e DVB-S USB2.0 KCONFIG:= CONFIG_DVB_USB_TTUSB2 \ CONFIG_DVB_TDA10086 \ CONFIG_DVB_LNBP21 \ CONFIG_DVB_TDA826X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-ttusb2.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda10086.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lnbp21.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda826x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-ttusb2/description Say Y here to support the Pinnacle 400e DVB-S USB2.0 . The following modules will be compiled for this device : dvb-usb-ttusb2 tda10086 lnbp21 tda826x You have to put the firmware files in the download dir : dvb-usb-pctv-400e-01.fw dvb-usb-tt-s2400-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_TTUSB2_FW_0:=dvb-usb-pctv-400e-01.fw DVB_USB_TTUSB2_FW_1:=dvb-usb-tt-s2400-01.fw define KernelPackage/dvb-usb-ttusb2/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_TTUSB2_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_TTUSB2_FW_1) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-ttusb2)) define KernelPackage/dvb-usb-dtt200u SUBMENU:=$(DVB_MENU) TITLE:=WideView WT-200U and WT-220U DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_DTT200U DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dtt200u.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dtt200u/description Say Y here to support the WideView WT-200U and WT-220U DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dtt200u You have to put the firmware files in the download dir : dvb-usb-dtt200u-01.fw dvb-usb-wt220u-02.fw dvb-usb-wt220u-fc03.fw dvb-usb-wt220u-zl0353-01.fw dvb-usb-wt220u-miglia-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DTT200U_FW_0:=dvb-usb-dtt200u-01.fw DVB_USB_DTT200U_FW_1:=dvb-usb-wt220u-02.fw DVB_USB_DTT200U_FW_2:=dvb-usb-wt220u-fc03.fw DVB_USB_DTT200U_FW_3:=dvb-usb-wt220u-zl0353-01.fw DVB_USB_DTT200U_FW_4:=dvb-usb-wt220u-miglia-01.fw define KernelPackage/dvb-usb-dtt200u/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_3) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_4) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dtt200u)) define KernelPackage/dvb-usb-opera1 SUBMENU:=$(DVB_MENU) TITLE:=Opera1 DVB-S USB2.0 receiver KCONFIG:= CONFIG_DVB_USB_OPERA1 \ CONFIG_DVB_STV0299 \ CONFIG_DVB_PLL DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-opera.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/stv0299.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-opera1/description Say Y here to support the Opera1 DVB-S USB2.0 receiver. The following modules will be compiled for this device : dvb-usb-opera stv0299 dvb-pll You have to put the firmware files in the download dir : dvb-usb-opera-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_OPERA1_FW_0:=dvb-usb-opera-01.fw define KernelPackage/dvb-usb-opera1/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_OPERA1_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-opera1)) define KernelPackage/dvb-usb-af9005 SUBMENU:=$(DVB_MENU) TITLE:=Afatech AF9005 DVB-T USB1.1 KCONFIG:= CONFIG_DVB_USB_AF9005 \ CONFIG_MEDIA_TUNER_MT2060 \ CONFIG_MEDIA_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-af9005/description Say Y here to support the Afatech AF9005 DVB-T USB1.1 . The following modules will be compiled for this device : dvb-usb-af9005 dvb-usb-af9005-remote mt2060 qt1010 You have to put the firmware files in the download dir : af9005.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_AF9005_FW_0:=af9005.fw define KernelPackage/dvb-usb-af9005/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_AF9005_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-af9005)) define KernelPackage/dvb-usb-af9005-remote SUBMENU:=$(DVB_MENU) TITLE:=Afatech AF9005 default remote control KCONFIG:= CONFIG_DVB_USB_AF9005_REMOTE DEPENDS:=+kmod-dvb-usb-af9005 FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-af9005-remote/description Say Y here to support the Afatech AF9005 default remote control . The following modules will be compiled for this device : dvb-usb-af9005-remote endef $(eval $(call KernelPackage,dvb-usb-af9005-remote)) define KernelPackage/dvb-usb-dw2102 SUBMENU:=$(DVB_MENU) TITLE:=DvbWorld DVB-S/S2 USB2.0 KCONFIG:= CONFIG_DVB_USB_DW2102 \ CONFIG_DVB_PLL \ CONFIG_DVB_STV0299 \ CONFIG_DVB_STV0288 \ CONFIG_DVB_STB6000 \ CONFIG_DVB_CX24116 \ CONFIG_DVB_SI21XX DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dw2102.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/stv0299.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/stv0288.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/stb6000.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/cx24116.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/si21xx.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dw2102/description Say Y here to support the DvbWorld DVB-S/S2 USB2.0 . The following modules will be compiled for this device : dvb-usb-dw2102 dvb-pll stv0299 stv0288 stb6000 cx24116 si21xx You have to put the firmware files in the download dir : dvb-usb-dw2102.fw dvb-usb-dw2104.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DW2102_FW_0:=dvb-usb-dw2102.fw DVB_USB_DW2102_FW_1:=dvb-usb-dw2104.fw define KernelPackage/dvb-usb-dw2102/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DW2102_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DW2102_FW_1) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dw2102)) define KernelPackage/dvb-usb-cinergy-t2 SUBMENU:=$(DVB_MENU) TITLE:=Terratec CinergyT2/qanu USB 2.0 DVB-T receiver KCONFIG:= CONFIG_DVB_USB_CINERGY_T2 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-cinergyT2.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-cinergy-t2/description Say Y here to support the Terratec CinergyT2/qanu USB 2.0 DVB-T receiver. The following modules will be compiled for this device : dvb-usb-cinergyT2 endef $(eval $(call KernelPackage,dvb-usb-cinergy-t2)) define KernelPackage/dvb-usb-anysee SUBMENU:=$(DVB_MENU) TITLE:=Anysee DVB-T/C USB2.0 KCONFIG:= CONFIG_DVB_USB_ANYSEE \ CONFIG_DVB_PLL \ CONFIG_DVB_MT352 \ CONFIG_DVB_ZL10353 \ CONFIG_DVB_TDA10023 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-anysee.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda10023.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-anysee/description Say Y here to support the Anysee DVB-T/C USB2.0 . The following modules will be compiled for this device : dvb-usb-anysee dvb-pll mt352 zl10353 tda10023 endef $(eval $(call KernelPackage,dvb-usb-anysee)) define KernelPackage/dvb-usb-dtv5100 SUBMENU:=$(DVB_MENU) TITLE:=AME DTV-5100 USB2.0 DVB-T KCONFIG:= CONFIG_DVB_USB_DTV5100 \ CONFIG_DVB_ZL10353 \ CONFIG_MEDIA_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dtv5100.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dtv5100/description Say Y here to support the AME DTV-5100 USB2.0 DVB-T . The following modules will be compiled for this device : dvb-usb-dtv5100 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-dtv5100)) define KernelPackage/dvb-usb-af9015 SUBMENU:=$(DVB_MENU) TITLE:=Afatech AF9015 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_AF9015 \ CONFIG_DVB_AF9013 \ CONFIG_DVB_PLL \ CONFIG_MEDIA_TUNER_MT2060 \ CONFIG_MEDIA_TUNER_QT1010 \ CONFIG_MEDIA_TUNER_TDA18271 \ CONFIG_MEDIA_TUNER_MXL5005S DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9015.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/af9013.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tda18271.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mxl5005s.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-af9015/description Say Y here to support the Afatech AF9015 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-af9015 af9013 dvb-pll mt2060 qt1010 tda18271 mxl5005s You have to put the firmware files in the download dir : dvb-usb-af9015.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_AF9015_FW_0:=dvb-usb-af9015.fw define KernelPackage/dvb-usb-af9015/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_AF9015_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-af9015)) MuMuDVB-2.1.0/openwrt/package/kernel/modules/dvb.2.6.29.6.mk000066400000000000000000000727671305714132500230030ustar00rootroot00000000000000 # # Copyright (C) 2009 Brice DUBOST # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. # # # !!!! This is a generated file !!!! # DVB_MENU:=DVB support # # General section # define KernelPackage/dvb-core SUBMENU:=$(DVB_MENU) TITLE:=DVB core support DEPENDS:=@LINUX_2_6 +kmod-i2c-core KCONFIG:= \ CONFIG_DVB_CORE \ CONFIG_DVB_CAPTURE_DRIVERS=y \ CONFIG_MEDIA_TUNER_CUSTOMIZE=y \ CONFIG_DVB_FE_CUSTOMISE=y \ CONFIG_DVB_DYNAMIC_MINORS=n \ CONFIG_CRC32 FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-core/dvb-core.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,50,dvb-core) endef define KernelPackage/dvb-core/description Kernel module for DVB support endef $(eval $(call KernelPackage,dvb-core)) define KernelPackage/dvb-usb SUBMENU:=$(DVB_MENU) TITLE:=DVB USB Support DEPENDS:=@USB_SUPPORT +kmod-dvb-core +kmod-usb-core KCONFIG:= \ CONFIG_DVB_USB \ CONFIG_INPUT=y FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb.$(LINUX_KMOD_SUFFIX) # AUTOLOAD:=$(call AutoLoad,55,dvb-usb) endef define KernelPackage/dvb-usb/description Kernel module for DVB USB devices. Note you have to select at least a device. endef $(eval $(call KernelPackage,dvb-usb)) # # Devices section # define KernelPackage/dvb-usb-a800 SUBMENU:=$(DVB_MENU) TITLE:=AVerMedia AverTV DVB-T USB 2.0 KCONFIG:= CONFIG_DVB_USB_A800 \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_PLL \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-a800.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-a800/description Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-a800 dib3000mc dibx000_common dvb-pll mt2060 You have to put the firmware files in the download dir : dvb-usb-avertv-a800-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_A800_FW_0:=dvb-usb-avertv-a800-02.fw define KernelPackage/dvb-usb-a800/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_A800_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-a800)) define KernelPackage/dvb-usb-dibusb-mb SUBMENU:=$(DVB_MENU) TITLE:=DiBcom USB DVB-T devices KCONFIG:= CONFIG_DVB_USB_DIBUSB_MB \ CONFIG_DVB_PLL \ CONFIG_DVB_DIB3000MB \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-mb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dibusb-mb/description Say Y here to support the DiBcom USB DVB-T devices . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-dibusb-mb dvb-pll dib3000mb mt2060 You have to put the firmware files in the download dir : dvb-usb-dibusb-5.0.0.11.fw dvb-usb-dibusb-an2235-01.fw dvb-usb-adstech-usb2-02.fw dvb-usb-dibusb-6.0.0.8.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIBUSB_MB_FW_0:=dvb-usb-dibusb-5.0.0.11.fw DVB_USB_DIBUSB_MB_FW_1:=dvb-usb-dibusb-an2235-01.fw DVB_USB_DIBUSB_MB_FW_2:=dvb-usb-adstech-usb2-02.fw DVB_USB_DIBUSB_MB_FW_3:=dvb-usb-dibusb-6.0.0.8.fw define KernelPackage/dvb-usb-dibusb-mb/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_3) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dibusb-mb)) define KernelPackage/dvb-usb-dibusb-mc SUBMENU:=$(DVB_MENU) TITLE:=DiBcom USB DVB-T devices KCONFIG:= CONFIG_DVB_USB_DIBUSB_MC \ CONFIG_DVB_DIB3000MC \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dibusb-mc/description Say Y here to support the DiBcom USB DVB-T devices . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-dibusb-mc dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-dibusb-6.0.0.8.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIBUSB_MC_FW_0:=dvb-usb-dibusb-6.0.0.8.fw define KernelPackage/dvb-usb-dibusb-mc/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MC_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dibusb-mc)) define KernelPackage/dvb-usb-dib0700 SUBMENU:=$(DVB_MENU) TITLE:=DiBcom DiB0700 USB DVB devices KCONFIG:= CONFIG_DVB_USB_DIB0700 \ CONFIG_DVB_DIB7000P \ CONFIG_DVB_DIB7000M \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_S5H1411 \ CONFIG_DVB_TUNER_DIB0070 \ CONFIG_MEDIA_TUNER_MT2060 \ CONFIG_MEDIA_TUNER_MT2266 \ CONFIG_MEDIA_TUNER_XC2028 \ CONFIG_MEDIA_TUNER_XC5000 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dib0700.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000p.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000m.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/s5h1411.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib0070.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2266.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tuner-xc2028.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/xc5000.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dib0700/description Say Y here to support the DiBcom DiB0700 USB DVB devices . The following modules will be compiled for this device : dvb-usb-dib0700 dib7000p dibx000_common dib7000m dibx000_common dib3000mc dibx000_common s5h1411 dib0070 mt2060 mt2266 tuner-xc2028 xc5000 You have to put the firmware files in the download dir : dvb-usb-dib0700-1.20.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIB0700_FW_0:=dvb-usb-dib0700-1.20.fw define KernelPackage/dvb-usb-dib0700/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIB0700_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dib0700)) define KernelPackage/dvb-usb-umt-010 SUBMENU:=$(DVB_MENU) TITLE:=HanfTek UMT-010 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_UMT_010 \ CONFIG_DVB_PLL \ CONFIG_DVB_DIB3000MC \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-umt-010.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-umt-010/description Say Y here to support the HanfTek UMT-010 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-umt-010 dvb-pll dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-umt-010-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_UMT_010_FW_0:=dvb-usb-umt-010-02.fw define KernelPackage/dvb-usb-umt-010/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_UMT_010_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-umt-010)) define KernelPackage/dvb-usb-cxusb SUBMENU:=$(DVB_MENU) TITLE:=Conexant USB2.0 hybrid reference design KCONFIG:= CONFIG_DVB_USB_CXUSB \ CONFIG_DVB_PLL \ CONFIG_DVB_CX22702 \ CONFIG_DVB_LGDT330X \ CONFIG_DVB_MT352 \ CONFIG_DVB_ZL10353 \ CONFIG_DVB_DIB7000P \ CONFIG_DVB_TUNER_DIB0070 \ CONFIG_MEDIA_TUNER_SIMPLE \ CONFIG_MEDIA_TUNER_XC2028 \ CONFIG_MEDIA_TUNER_MXL5005S DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-cxusb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/cx22702.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lgdt330x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000p.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib0070.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tuner-simple.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tuner-types.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tuner-xc2028.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mxl5005s.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-cxusb/description Say Y here to support the Conexant USB2.0 hybrid reference design . The following modules will be compiled for this device : dvb-usb-cxusb dvb-pll cx22702 lgdt330x mt352 zl10353 dib7000p dibx000_common dib0070 tuner-simple tuner-types tuner-xc2028 mxl5005s You have to put the firmware files in the download dir : dvb-usb-bluebird-01.fw dvb-usb-bluebird-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_CXUSB_FW_0:=dvb-usb-bluebird-01.fw DVB_USB_CXUSB_FW_1:=dvb-usb-bluebird-02.fw define KernelPackage/dvb-usb-cxusb/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_CXUSB_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_CXUSB_FW_1) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-cxusb)) define KernelPackage/dvb-usb-m920x SUBMENU:=$(DVB_MENU) TITLE:=Uli m920x DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_M920X \ CONFIG_DVB_MT352 \ CONFIG_DVB_TDA1004X \ CONFIG_MEDIA_TUNER_QT1010 \ CONFIG_MEDIA_TUNER_TDA827X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-m920x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda1004x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tda827x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-m920x/description Say Y here to support the Uli m920x DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-m920x mt352 tda1004x qt1010 tda827x You have to put the firmware files in the download dir : dvb-usb-megasky-02.fw dvb-usb-digivox-02.fw dvb-usb-tvwalkert.fw dvb-usb-dposh-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_M920X_FW_0:=dvb-usb-megasky-02.fw DVB_USB_M920X_FW_1:=dvb-usb-digivox-02.fw DVB_USB_M920X_FW_2:=dvb-usb-tvwalkert.fw DVB_USB_M920X_FW_3:=dvb-usb-dposh-01.fw define KernelPackage/dvb-usb-m920x/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_3) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-m920x)) define KernelPackage/dvb-usb-gl861 SUBMENU:=$(DVB_MENU) TITLE:=Genesys Logic GL861 USB2.0 KCONFIG:= CONFIG_DVB_USB_GL861 \ CONFIG_DVB_ZL10353 \ CONFIG_MEDIA_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-gl861.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-gl861/description Say Y here to support the Genesys Logic GL861 USB2.0 . The following modules will be compiled for this device : dvb-usb-gl861 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-gl861)) define KernelPackage/dvb-usb-au6610 SUBMENU:=$(DVB_MENU) TITLE:=Alcor Micro AU6610 USB2.0 KCONFIG:= CONFIG_DVB_USB_AU6610 \ CONFIG_DVB_ZL10353 \ CONFIG_MEDIA_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-au6610.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-au6610/description Say Y here to support the Alcor Micro AU6610 USB2.0 . The following modules will be compiled for this device : dvb-usb-au6610 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-au6610)) define KernelPackage/dvb-usb-digitv SUBMENU:=$(DVB_MENU) TITLE:=Nebula Electronics uDigiTV DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_DIGITV \ CONFIG_DVB_PLL \ CONFIG_DVB_NXT6000 \ CONFIG_DVB_MT352 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-digitv.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/nxt6000.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-digitv/description Say Y here to support the Nebula Electronics uDigiTV DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-digitv dvb-pll nxt6000 mt352 You have to put the firmware files in the download dir : dvb-usb-digitv-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIGITV_FW_0:=dvb-usb-digitv-02.fw define KernelPackage/dvb-usb-digitv/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIGITV_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-digitv)) define KernelPackage/dvb-usb-vp7045 SUBMENU:=$(DVB_MENU) TITLE:=TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle KCONFIG:= CONFIG_DVB_USB_VP7045 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-vp7045.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-vp7045/description Say Y here to support the TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle. The following modules will be compiled for this device : dvb-usb-vp7045 You have to put the firmware files in the download dir : dvb-usb-vp7045-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_VP7045_FW_0:=dvb-usb-vp7045-01.fw define KernelPackage/dvb-usb-vp7045/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_VP7045_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-vp7045)) define KernelPackage/dvb-usb-vp702x SUBMENU:=$(DVB_MENU) TITLE:=TwinhanDTV StarBox and clones DVB-S USB2.0 KCONFIG:= CONFIG_DVB_USB_VP702X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-vp702x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-vp702x/description Say Y here to support the TwinhanDTV StarBox and clones DVB-S USB2.0 . The following modules will be compiled for this device : dvb-usb-vp702x You have to put the firmware files in the download dir : dvb-usb-vp702x-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_VP702X_FW_0:=dvb-usb-vp702x-02.fw define KernelPackage/dvb-usb-vp702x/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_VP702X_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-vp702x)) define KernelPackage/dvb-usb-gp8psk SUBMENU:=$(DVB_MENU) TITLE:=GENPIX 8PSK->USB module KCONFIG:= CONFIG_DVB_USB_GP8PSK DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-gp8psk.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-gp8psk/description Say Y here to support the GENPIX 8PSK->USB module . The following modules will be compiled for this device : dvb-usb-gp8psk You have to put the firmware files in the download dir : dvb-usb-gp8psk-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_GP8PSK_FW_0:=dvb-usb-gp8psk-01.fw define KernelPackage/dvb-usb-gp8psk/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_GP8PSK_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-gp8psk)) define KernelPackage/dvb-usb-nova-t-usb2 SUBMENU:=$(DVB_MENU) TITLE:=Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_NOVA_T_USB2 \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_PLL \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-nova-t-usb2.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-nova-t-usb2/description Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-nova-t-usb2 dib3000mc dibx000_common dvb-pll mt2060 You have to put the firmware files in the download dir : dvb-usb-nova-t-usb2-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_NOVA_T_USB2_FW_0:=dvb-usb-nova-t-usb2-02.fw define KernelPackage/dvb-usb-nova-t-usb2/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_NOVA_T_USB2_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-nova-t-usb2)) define KernelPackage/dvb-usb-ttusb2 SUBMENU:=$(DVB_MENU) TITLE:=Pinnacle 400e DVB-S USB2.0 KCONFIG:= CONFIG_DVB_USB_TTUSB2 \ CONFIG_DVB_TDA10086 \ CONFIG_DVB_LNBP21 \ CONFIG_DVB_TDA826X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-ttusb2.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda10086.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lnbp21.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda826x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-ttusb2/description Say Y here to support the Pinnacle 400e DVB-S USB2.0 . The following modules will be compiled for this device : dvb-usb-ttusb2 tda10086 lnbp21 tda826x You have to put the firmware files in the download dir : dvb-usb-pctv-400e-01.fw dvb-usb-tt-s2400-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_TTUSB2_FW_0:=dvb-usb-pctv-400e-01.fw DVB_USB_TTUSB2_FW_1:=dvb-usb-tt-s2400-01.fw define KernelPackage/dvb-usb-ttusb2/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_TTUSB2_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_TTUSB2_FW_1) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-ttusb2)) define KernelPackage/dvb-usb-dtt200u SUBMENU:=$(DVB_MENU) TITLE:=WideView WT-200U and WT-220U DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_DTT200U DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dtt200u.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dtt200u/description Say Y here to support the WideView WT-200U and WT-220U DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dtt200u You have to put the firmware files in the download dir : dvb-usb-dtt200u-01.fw dvb-usb-wt220u-02.fw dvb-usb-wt220u-fc03.fw dvb-usb-wt220u-zl0353-01.fw dvb-usb-wt220u-miglia-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DTT200U_FW_0:=dvb-usb-dtt200u-01.fw DVB_USB_DTT200U_FW_1:=dvb-usb-wt220u-02.fw DVB_USB_DTT200U_FW_2:=dvb-usb-wt220u-fc03.fw DVB_USB_DTT200U_FW_3:=dvb-usb-wt220u-zl0353-01.fw DVB_USB_DTT200U_FW_4:=dvb-usb-wt220u-miglia-01.fw define KernelPackage/dvb-usb-dtt200u/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_3) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_4) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dtt200u)) define KernelPackage/dvb-usb-opera1 SUBMENU:=$(DVB_MENU) TITLE:=Opera1 DVB-S USB2.0 receiver KCONFIG:= CONFIG_DVB_USB_OPERA1 \ CONFIG_DVB_STV0299 \ CONFIG_DVB_PLL DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-opera.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/stv0299.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-opera1/description Say Y here to support the Opera1 DVB-S USB2.0 receiver. The following modules will be compiled for this device : dvb-usb-opera stv0299 dvb-pll You have to put the firmware files in the download dir : dvb-usb-opera-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_OPERA1_FW_0:=dvb-usb-opera-01.fw define KernelPackage/dvb-usb-opera1/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_OPERA1_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-opera1)) define KernelPackage/dvb-usb-af9005 SUBMENU:=$(DVB_MENU) TITLE:=Afatech AF9005 DVB-T USB1.1 KCONFIG:= CONFIG_DVB_USB_AF9005 \ CONFIG_MEDIA_TUNER_MT2060 \ CONFIG_MEDIA_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-af9005/description Say Y here to support the Afatech AF9005 DVB-T USB1.1 . The following modules will be compiled for this device : dvb-usb-af9005 dvb-usb-af9005-remote mt2060 qt1010 You have to put the firmware files in the download dir : af9005.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_AF9005_FW_0:=af9005.fw define KernelPackage/dvb-usb-af9005/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_AF9005_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-af9005)) define KernelPackage/dvb-usb-af9005-remote SUBMENU:=$(DVB_MENU) TITLE:=Afatech AF9005 default remote control KCONFIG:= CONFIG_DVB_USB_AF9005_REMOTE DEPENDS:=+kmod-dvb-usb-af9005 FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-af9005-remote/description Say Y here to support the Afatech AF9005 default remote control . The following modules will be compiled for this device : dvb-usb-af9005-remote endef $(eval $(call KernelPackage,dvb-usb-af9005-remote)) define KernelPackage/dvb-usb-dw2102 SUBMENU:=$(DVB_MENU) TITLE:=DvbWorld DVB-S/S2 USB2.0 KCONFIG:= CONFIG_DVB_USB_DW2102 \ CONFIG_DVB_PLL \ CONFIG_DVB_STV0299 \ CONFIG_DVB_STV0288 \ CONFIG_DVB_STB6000 \ CONFIG_DVB_CX24116 \ CONFIG_DVB_SI21XX DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dw2102.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/stv0299.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/stv0288.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/stb6000.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/cx24116.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/si21xx.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dw2102/description Say Y here to support the DvbWorld DVB-S/S2 USB2.0 . The following modules will be compiled for this device : dvb-usb-dw2102 dvb-pll stv0299 stv0288 stb6000 cx24116 si21xx You have to put the firmware files in the download dir : dvb-usb-dw2102.fw dvb-usb-dw2104.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DW2102_FW_0:=dvb-usb-dw2102.fw DVB_USB_DW2102_FW_1:=dvb-usb-dw2104.fw define KernelPackage/dvb-usb-dw2102/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DW2102_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DW2102_FW_1) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dw2102)) define KernelPackage/dvb-usb-cinergy-t2 SUBMENU:=$(DVB_MENU) TITLE:=Terratec CinergyT2/qanu USB 2.0 DVB-T receiver KCONFIG:= CONFIG_DVB_USB_CINERGY_T2 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-cinergyT2.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-cinergy-t2/description Say Y here to support the Terratec CinergyT2/qanu USB 2.0 DVB-T receiver. The following modules will be compiled for this device : dvb-usb-cinergyT2 endef $(eval $(call KernelPackage,dvb-usb-cinergy-t2)) define KernelPackage/dvb-usb-anysee SUBMENU:=$(DVB_MENU) TITLE:=Anysee DVB-T/C USB2.0 KCONFIG:= CONFIG_DVB_USB_ANYSEE \ CONFIG_DVB_PLL \ CONFIG_DVB_MT352 \ CONFIG_DVB_ZL10353 \ CONFIG_DVB_TDA10023 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-anysee.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda10023.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-anysee/description Say Y here to support the Anysee DVB-T/C USB2.0 . The following modules will be compiled for this device : dvb-usb-anysee dvb-pll mt352 zl10353 tda10023 endef $(eval $(call KernelPackage,dvb-usb-anysee)) define KernelPackage/dvb-usb-dtv5100 SUBMENU:=$(DVB_MENU) TITLE:=AME DTV-5100 USB2.0 DVB-T KCONFIG:= CONFIG_DVB_USB_DTV5100 \ CONFIG_DVB_ZL10353 \ CONFIG_MEDIA_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dtv5100.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dtv5100/description Say Y here to support the AME DTV-5100 USB2.0 DVB-T . The following modules will be compiled for this device : dvb-usb-dtv5100 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-dtv5100)) define KernelPackage/dvb-usb-af9015 SUBMENU:=$(DVB_MENU) TITLE:=Afatech AF9015 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_AF9015 \ CONFIG_DVB_AF9013 \ CONFIG_DVB_PLL \ CONFIG_MEDIA_TUNER_MT2060 \ CONFIG_MEDIA_TUNER_QT1010 \ CONFIG_MEDIA_TUNER_TDA18271 \ CONFIG_MEDIA_TUNER_MXL5005S DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9015.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/af9013.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tda18271.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mxl5005s.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-af9015/description Say Y here to support the Afatech AF9015 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-af9015 af9013 dvb-pll mt2060 qt1010 tda18271 mxl5005s You have to put the firmware files in the download dir : dvb-usb-af9015.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_AF9015_FW_0:=dvb-usb-af9015.fw define KernelPackage/dvb-usb-af9015/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_AF9015_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-af9015)) MuMuDVB-2.1.0/openwrt/package/kernel/modules/dvb.2.6.30.8.mk000066400000000000000000000753041305714132500227630ustar00rootroot00000000000000 # # Copyright (C) 2009 Brice DUBOST # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. # # # !!!! This is a generated file !!!! # DVB_MENU:=DVB support # # General section # define KernelPackage/dvb-core SUBMENU:=$(DVB_MENU) TITLE:=DVB core support DEPENDS:=@LINUX_2_6 +kmod-i2c-core KCONFIG:= \ CONFIG_DVB_CORE \ CONFIG_DVB_CAPTURE_DRIVERS=y \ CONFIG_MEDIA_TUNER_CUSTOMIZE=y \ CONFIG_DVB_FE_CUSTOMISE=y \ CONFIG_DVB_DYNAMIC_MINORS=n \ CONFIG_CRC32 FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-core/dvb-core.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,50,dvb-core) endef define KernelPackage/dvb-core/description Kernel module for DVB support endef $(eval $(call KernelPackage,dvb-core)) define KernelPackage/dvb-usb SUBMENU:=$(DVB_MENU) TITLE:=DVB USB Support DEPENDS:=@USB_SUPPORT +kmod-dvb-core +kmod-usb-core KCONFIG:= \ CONFIG_DVB_USB \ CONFIG_INPUT=y FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb.$(LINUX_KMOD_SUFFIX) # AUTOLOAD:=$(call AutoLoad,55,dvb-usb) endef define KernelPackage/dvb-usb/description Kernel module for DVB USB devices. Note you have to select at least a device. endef $(eval $(call KernelPackage,dvb-usb)) # # Devices section # define KernelPackage/dvb-usb-a800 SUBMENU:=$(DVB_MENU) TITLE:=AVerMedia AverTV DVB-T USB 2.0 KCONFIG:= CONFIG_DVB_USB_A800 \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_PLL \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-a800.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-a800/description Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-a800 dib3000mc dibx000_common dvb-pll mt2060 You have to put the firmware files in the download dir : dvb-usb-avertv-a800-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_A800_FW_0:=dvb-usb-avertv-a800-02.fw define KernelPackage/dvb-usb-a800/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_A800_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-a800)) define KernelPackage/dvb-usb-dibusb-mb SUBMENU:=$(DVB_MENU) TITLE:=DiBcom USB DVB-T devices KCONFIG:= CONFIG_DVB_USB_DIBUSB_MB \ CONFIG_DVB_PLL \ CONFIG_DVB_DIB3000MB \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-mb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dibusb-mb/description Say Y here to support the DiBcom USB DVB-T devices . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-dibusb-mb dvb-pll dib3000mb mt2060 You have to put the firmware files in the download dir : dvb-usb-dibusb-5.0.0.11.fw dvb-usb-dibusb-an2235-01.fw dvb-usb-adstech-usb2-02.fw dvb-usb-dibusb-6.0.0.8.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIBUSB_MB_FW_0:=dvb-usb-dibusb-5.0.0.11.fw DVB_USB_DIBUSB_MB_FW_1:=dvb-usb-dibusb-an2235-01.fw DVB_USB_DIBUSB_MB_FW_2:=dvb-usb-adstech-usb2-02.fw DVB_USB_DIBUSB_MB_FW_3:=dvb-usb-dibusb-6.0.0.8.fw define KernelPackage/dvb-usb-dibusb-mb/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_3) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dibusb-mb)) define KernelPackage/dvb-usb-dibusb-mc SUBMENU:=$(DVB_MENU) TITLE:=DiBcom USB DVB-T devices KCONFIG:= CONFIG_DVB_USB_DIBUSB_MC \ CONFIG_DVB_DIB3000MC \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dibusb-mc/description Say Y here to support the DiBcom USB DVB-T devices . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-dibusb-mc dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-dibusb-6.0.0.8.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIBUSB_MC_FW_0:=dvb-usb-dibusb-6.0.0.8.fw define KernelPackage/dvb-usb-dibusb-mc/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MC_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dibusb-mc)) define KernelPackage/dvb-usb-dib0700 SUBMENU:=$(DVB_MENU) TITLE:=DiBcom DiB0700 USB DVB devices KCONFIG:= CONFIG_DVB_USB_DIB0700 \ CONFIG_DVB_DIB7000P \ CONFIG_DVB_DIB7000M \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_S5H1411 \ CONFIG_DVB_LGDT3305 \ CONFIG_DVB_TUNER_DIB0070 \ CONFIG_MEDIA_TUNER_MT2060 \ CONFIG_MEDIA_TUNER_MT2266 \ CONFIG_MEDIA_TUNER_XC2028 \ CONFIG_MEDIA_TUNER_XC5000 \ CONFIG_MEDIA_TUNER_MXL5007T DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dib0700.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000p.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000m.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/s5h1411.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lgdt3305.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib0070.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2266.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tuner-xc2028.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/xc5000.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mxl5007t.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dib0700/description Say Y here to support the DiBcom DiB0700 USB DVB devices . The following modules will be compiled for this device : dvb-usb-dib0700 dib7000p dibx000_common dib7000m dibx000_common dib3000mc dibx000_common s5h1411 lgdt3305 dib0070 mt2060 mt2266 tuner-xc2028 xc5000 mxl5007t You have to put the firmware files in the download dir : dvb-usb-dib0700-1.20.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIB0700_FW_0:=dvb-usb-dib0700-1.20.fw define KernelPackage/dvb-usb-dib0700/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIB0700_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dib0700)) define KernelPackage/dvb-usb-umt-010 SUBMENU:=$(DVB_MENU) TITLE:=HanfTek UMT-010 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_UMT_010 \ CONFIG_DVB_PLL \ CONFIG_DVB_DIB3000MC \ CONFIG_MEDIA_TUNER_MT2060 \ CONFIG_DVB_MT352 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-umt-010.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-umt-010/description Say Y here to support the HanfTek UMT-010 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-umt-010 dvb-pll dib3000mc dibx000_common mt2060 mt352 You have to put the firmware files in the download dir : dvb-usb-umt-010-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_UMT_010_FW_0:=dvb-usb-umt-010-02.fw define KernelPackage/dvb-usb-umt-010/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_UMT_010_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-umt-010)) define KernelPackage/dvb-usb-cxusb SUBMENU:=$(DVB_MENU) TITLE:=Conexant USB2.0 hybrid reference design KCONFIG:= CONFIG_DVB_USB_CXUSB \ CONFIG_DVB_PLL \ CONFIG_DVB_CX22702 \ CONFIG_DVB_LGDT330X \ CONFIG_DVB_MT352 \ CONFIG_DVB_ZL10353 \ CONFIG_DVB_DIB7000P \ CONFIG_DVB_LGS8GL5 \ CONFIG_DVB_TUNER_DIB0070 \ CONFIG_MEDIA_TUNER_SIMPLE \ CONFIG_MEDIA_TUNER_XC2028 \ CONFIG_MEDIA_TUNER_MXL5005S DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-cxusb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/cx22702.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lgdt330x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000p.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lgs8gl5.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib0070.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tuner-simple.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tuner-types.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tuner-xc2028.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mxl5005s.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-cxusb/description Say Y here to support the Conexant USB2.0 hybrid reference design . The following modules will be compiled for this device : dvb-usb-cxusb dvb-pll cx22702 lgdt330x mt352 zl10353 dib7000p dibx000_common lgs8gl5 dib0070 tuner-simple tuner-types tuner-xc2028 mxl5005s You have to put the firmware files in the download dir : dvb-usb-bluebird-01.fw dvb-usb-bluebird-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_CXUSB_FW_0:=dvb-usb-bluebird-01.fw DVB_USB_CXUSB_FW_1:=dvb-usb-bluebird-02.fw define KernelPackage/dvb-usb-cxusb/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_CXUSB_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_CXUSB_FW_1) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-cxusb)) define KernelPackage/dvb-usb-m920x SUBMENU:=$(DVB_MENU) TITLE:=Uli m920x DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_M920X \ CONFIG_DVB_MT352 \ CONFIG_DVB_TDA1004X \ CONFIG_MEDIA_TUNER_QT1010 \ CONFIG_MEDIA_TUNER_TDA827X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-m920x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda1004x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tda827x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-m920x/description Say Y here to support the Uli m920x DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-m920x mt352 tda1004x qt1010 tda827x You have to put the firmware files in the download dir : dvb-usb-megasky-02.fw dvb-usb-digivox-02.fw dvb-usb-tvwalkert.fw dvb-usb-dposh-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_M920X_FW_0:=dvb-usb-megasky-02.fw DVB_USB_M920X_FW_1:=dvb-usb-digivox-02.fw DVB_USB_M920X_FW_2:=dvb-usb-tvwalkert.fw DVB_USB_M920X_FW_3:=dvb-usb-dposh-01.fw define KernelPackage/dvb-usb-m920x/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_3) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-m920x)) define KernelPackage/dvb-usb-gl861 SUBMENU:=$(DVB_MENU) TITLE:=Genesys Logic GL861 USB2.0 KCONFIG:= CONFIG_DVB_USB_GL861 \ CONFIG_DVB_ZL10353 \ CONFIG_MEDIA_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-gl861.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-gl861/description Say Y here to support the Genesys Logic GL861 USB2.0 . The following modules will be compiled for this device : dvb-usb-gl861 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-gl861)) define KernelPackage/dvb-usb-au6610 SUBMENU:=$(DVB_MENU) TITLE:=Alcor Micro AU6610 USB2.0 KCONFIG:= CONFIG_DVB_USB_AU6610 \ CONFIG_DVB_ZL10353 \ CONFIG_MEDIA_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-au6610.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-au6610/description Say Y here to support the Alcor Micro AU6610 USB2.0 . The following modules will be compiled for this device : dvb-usb-au6610 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-au6610)) define KernelPackage/dvb-usb-digitv SUBMENU:=$(DVB_MENU) TITLE:=Nebula Electronics uDigiTV DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_DIGITV \ CONFIG_DVB_PLL \ CONFIG_DVB_NXT6000 \ CONFIG_DVB_MT352 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-digitv.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/nxt6000.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-digitv/description Say Y here to support the Nebula Electronics uDigiTV DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-digitv dvb-pll nxt6000 mt352 You have to put the firmware files in the download dir : dvb-usb-digitv-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIGITV_FW_0:=dvb-usb-digitv-02.fw define KernelPackage/dvb-usb-digitv/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIGITV_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-digitv)) define KernelPackage/dvb-usb-vp7045 SUBMENU:=$(DVB_MENU) TITLE:=TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle KCONFIG:= CONFIG_DVB_USB_VP7045 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-vp7045.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-vp7045/description Say Y here to support the TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle. The following modules will be compiled for this device : dvb-usb-vp7045 You have to put the firmware files in the download dir : dvb-usb-vp7045-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_VP7045_FW_0:=dvb-usb-vp7045-01.fw define KernelPackage/dvb-usb-vp7045/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_VP7045_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-vp7045)) define KernelPackage/dvb-usb-vp702x SUBMENU:=$(DVB_MENU) TITLE:=TwinhanDTV StarBox and clones DVB-S USB2.0 KCONFIG:= CONFIG_DVB_USB_VP702X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-vp702x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-vp702x/description Say Y here to support the TwinhanDTV StarBox and clones DVB-S USB2.0 . The following modules will be compiled for this device : dvb-usb-vp702x You have to put the firmware files in the download dir : dvb-usb-vp702x-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_VP702X_FW_0:=dvb-usb-vp702x-02.fw define KernelPackage/dvb-usb-vp702x/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_VP702X_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-vp702x)) define KernelPackage/dvb-usb-gp8psk SUBMENU:=$(DVB_MENU) TITLE:=GENPIX 8PSK->USB module KCONFIG:= CONFIG_DVB_USB_GP8PSK DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-gp8psk.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-gp8psk/description Say Y here to support the GENPIX 8PSK->USB module . The following modules will be compiled for this device : dvb-usb-gp8psk You have to put the firmware files in the download dir : dvb-usb-gp8psk-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_GP8PSK_FW_0:=dvb-usb-gp8psk-01.fw define KernelPackage/dvb-usb-gp8psk/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_GP8PSK_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-gp8psk)) define KernelPackage/dvb-usb-nova-t-usb2 SUBMENU:=$(DVB_MENU) TITLE:=Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_NOVA_T_USB2 \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_PLL \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-nova-t-usb2.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-nova-t-usb2/description Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-nova-t-usb2 dib3000mc dibx000_common dvb-pll mt2060 You have to put the firmware files in the download dir : dvb-usb-nova-t-usb2-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_NOVA_T_USB2_FW_0:=dvb-usb-nova-t-usb2-02.fw define KernelPackage/dvb-usb-nova-t-usb2/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_NOVA_T_USB2_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-nova-t-usb2)) define KernelPackage/dvb-usb-ttusb2 SUBMENU:=$(DVB_MENU) TITLE:=Pinnacle 400e DVB-S USB2.0 KCONFIG:= CONFIG_DVB_USB_TTUSB2 \ CONFIG_DVB_TDA10086 \ CONFIG_DVB_LNBP21 \ CONFIG_DVB_TDA826X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-ttusb2.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda10086.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lnbp21.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda826x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-ttusb2/description Say Y here to support the Pinnacle 400e DVB-S USB2.0 . The following modules will be compiled for this device : dvb-usb-ttusb2 tda10086 lnbp21 tda826x You have to put the firmware files in the download dir : dvb-usb-pctv-400e-01.fw dvb-usb-tt-s2400-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_TTUSB2_FW_0:=dvb-usb-pctv-400e-01.fw DVB_USB_TTUSB2_FW_1:=dvb-usb-tt-s2400-01.fw define KernelPackage/dvb-usb-ttusb2/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_TTUSB2_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_TTUSB2_FW_1) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-ttusb2)) define KernelPackage/dvb-usb-dtt200u SUBMENU:=$(DVB_MENU) TITLE:=WideView WT-200U and WT-220U DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_DTT200U DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dtt200u.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dtt200u/description Say Y here to support the WideView WT-200U and WT-220U DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dtt200u You have to put the firmware files in the download dir : dvb-usb-dtt200u-01.fw dvb-usb-wt220u-02.fw dvb-usb-wt220u-fc03.fw dvb-usb-wt220u-zl0353-01.fw dvb-usb-wt220u-miglia-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DTT200U_FW_0:=dvb-usb-dtt200u-01.fw DVB_USB_DTT200U_FW_1:=dvb-usb-wt220u-02.fw DVB_USB_DTT200U_FW_2:=dvb-usb-wt220u-fc03.fw DVB_USB_DTT200U_FW_3:=dvb-usb-wt220u-zl0353-01.fw DVB_USB_DTT200U_FW_4:=dvb-usb-wt220u-miglia-01.fw define KernelPackage/dvb-usb-dtt200u/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_3) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_4) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dtt200u)) define KernelPackage/dvb-usb-opera1 SUBMENU:=$(DVB_MENU) TITLE:=Opera1 DVB-S USB2.0 receiver KCONFIG:= CONFIG_DVB_USB_OPERA1 \ CONFIG_DVB_STV0299 \ CONFIG_DVB_PLL DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-opera.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/stv0299.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-opera1/description Say Y here to support the Opera1 DVB-S USB2.0 receiver. The following modules will be compiled for this device : dvb-usb-opera stv0299 dvb-pll You have to put the firmware files in the download dir : dvb-usb-opera-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_OPERA1_FW_0:=dvb-usb-opera-01.fw define KernelPackage/dvb-usb-opera1/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_OPERA1_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-opera1)) define KernelPackage/dvb-usb-af9005 SUBMENU:=$(DVB_MENU) TITLE:=Afatech AF9005 DVB-T USB1.1 KCONFIG:= CONFIG_DVB_USB_AF9005 \ CONFIG_MEDIA_TUNER_MT2060 \ CONFIG_MEDIA_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-af9005/description Say Y here to support the Afatech AF9005 DVB-T USB1.1 . The following modules will be compiled for this device : dvb-usb-af9005 dvb-usb-af9005-remote mt2060 qt1010 You have to put the firmware files in the download dir : af9005.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_AF9005_FW_0:=af9005.fw define KernelPackage/dvb-usb-af9005/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_AF9005_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-af9005)) define KernelPackage/dvb-usb-af9005-remote SUBMENU:=$(DVB_MENU) TITLE:=Afatech AF9005 default remote control KCONFIG:= CONFIG_DVB_USB_AF9005_REMOTE DEPENDS:=+kmod-dvb-usb-af9005 FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-af9005-remote/description Say Y here to support the Afatech AF9005 default remote control . The following modules will be compiled for this device : dvb-usb-af9005-remote endef $(eval $(call KernelPackage,dvb-usb-af9005-remote)) define KernelPackage/dvb-usb-dw2102 SUBMENU:=$(DVB_MENU) TITLE:=DvbWorld DVB-S/S2 USB2.0 KCONFIG:= CONFIG_DVB_USB_DW2102 \ CONFIG_DVB_PLL \ CONFIG_DVB_STV0299 \ CONFIG_DVB_STV0288 \ CONFIG_DVB_STB6000 \ CONFIG_DVB_CX24116 \ CONFIG_DVB_SI21XX DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dw2102.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/stv0299.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/stv0288.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/stb6000.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/cx24116.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/si21xx.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dw2102/description Say Y here to support the DvbWorld DVB-S/S2 USB2.0 . The following modules will be compiled for this device : dvb-usb-dw2102 dvb-pll stv0299 stv0288 stb6000 cx24116 si21xx You have to put the firmware files in the download dir : dvb-usb-dw2102.fw dvb-usb-dw2104.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DW2102_FW_0:=dvb-usb-dw2102.fw DVB_USB_DW2102_FW_1:=dvb-usb-dw2104.fw define KernelPackage/dvb-usb-dw2102/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DW2102_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DW2102_FW_1) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dw2102)) define KernelPackage/dvb-usb-cinergy-t2 SUBMENU:=$(DVB_MENU) TITLE:=Terratec CinergyT2/qanu USB 2.0 DVB-T receiver KCONFIG:= CONFIG_DVB_USB_CINERGY_T2 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-cinergyT2.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-cinergy-t2/description Say Y here to support the Terratec CinergyT2/qanu USB 2.0 DVB-T receiver. The following modules will be compiled for this device : dvb-usb-cinergyT2 endef $(eval $(call KernelPackage,dvb-usb-cinergy-t2)) define KernelPackage/dvb-usb-anysee SUBMENU:=$(DVB_MENU) TITLE:=Anysee DVB-T/C USB2.0 KCONFIG:= CONFIG_DVB_USB_ANYSEE \ CONFIG_DVB_PLL \ CONFIG_DVB_MT352 \ CONFIG_DVB_ZL10353 \ CONFIG_DVB_TDA10023 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-anysee.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda10023.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-anysee/description Say Y here to support the Anysee DVB-T/C USB2.0 . The following modules will be compiled for this device : dvb-usb-anysee dvb-pll mt352 zl10353 tda10023 endef $(eval $(call KernelPackage,dvb-usb-anysee)) define KernelPackage/dvb-usb-dtv5100 SUBMENU:=$(DVB_MENU) TITLE:=AME DTV-5100 USB2.0 DVB-T KCONFIG:= CONFIG_DVB_USB_DTV5100 \ CONFIG_DVB_ZL10353 \ CONFIG_MEDIA_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dtv5100.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dtv5100/description Say Y here to support the AME DTV-5100 USB2.0 DVB-T . The following modules will be compiled for this device : dvb-usb-dtv5100 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-dtv5100)) define KernelPackage/dvb-usb-af9015 SUBMENU:=$(DVB_MENU) TITLE:=Afatech AF9015 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_AF9015 \ CONFIG_DVB_AF9013 \ CONFIG_DVB_PLL \ CONFIG_MEDIA_TUNER_MT2060 \ CONFIG_MEDIA_TUNER_QT1010 \ CONFIG_MEDIA_TUNER_TDA18271 \ CONFIG_MEDIA_TUNER_MXL5005S \ CONFIG_MEDIA_TUNER_MC44S803 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9015.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/af9013.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tda18271.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mxl5005s.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mc44s803.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-af9015/description Say Y here to support the Afatech AF9015 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-af9015 af9013 dvb-pll mt2060 qt1010 tda18271 mxl5005s mc44s803 You have to put the firmware files in the download dir : dvb-usb-af9015.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_AF9015_FW_0:=dvb-usb-af9015.fw define KernelPackage/dvb-usb-af9015/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_AF9015_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-af9015)) define KernelPackage/dvb-usb-ce6230 SUBMENU:=$(DVB_MENU) TITLE:=Intel CE6230 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_CE6230 \ CONFIG_DVB_ZL10353 \ CONFIG_MEDIA_TUNER_MXL5005S DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-ce6230.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mxl5005s.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-ce6230/description Say Y here to support the Intel CE6230 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-ce6230 zl10353 mxl5005s endef $(eval $(call KernelPackage,dvb-usb-ce6230)) MuMuDVB-2.1.0/openwrt/package/kernel/modules/dvb.2.6.31.6.mk000066400000000000000000000757041305714132500227660ustar00rootroot00000000000000 # # Copyright (C) 2009 Brice DUBOST # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. # # # !!!! This is a generated file !!!! # DVB_MENU:=DVB support # # General section # define KernelPackage/dvb-core SUBMENU:=$(DVB_MENU) TITLE:=DVB core support DEPENDS:=@LINUX_2_6 +kmod-i2c-core KCONFIG:= \ CONFIG_MEDIA_SUPPORT \ CONFIG_DVB_CORE \ CONFIG_DVB_CAPTURE_DRIVERS=y \ CONFIG_MEDIA_TUNER_CUSTOMIZE=y \ CONFIG_DVB_FE_CUSTOMISE=y \ CONFIG_DVB_DYNAMIC_MINORS=n \ CONFIG_CRC32 FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-core/dvb-core.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,50,dvb-core) endef define KernelPackage/dvb-core/description Kernel module for DVB support endef $(eval $(call KernelPackage,dvb-core)) define KernelPackage/dvb-usb SUBMENU:=$(DVB_MENU) TITLE:=DVB USB Support DEPENDS:=@USB_SUPPORT +kmod-dvb-core +kmod-usb-core KCONFIG:= \ CONFIG_DVB_USB \ CONFIG_INPUT=y FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb.$(LINUX_KMOD_SUFFIX) # AUTOLOAD:=$(call AutoLoad,55,dvb-usb) endef define KernelPackage/dvb-usb/description Kernel module for DVB USB devices. Note you have to select at least a device. endef $(eval $(call KernelPackage,dvb-usb)) # # Devices section # define KernelPackage/dvb-usb-a800 SUBMENU:=$(DVB_MENU) TITLE:=AVerMedia AverTV DVB-T USB 2.0 KCONFIG:= CONFIG_DVB_USB_A800 \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_PLL \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-a800.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-a800/description Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-a800 dib3000mc dibx000_common dvb-pll mt2060 You have to put the firmware files in the download dir : dvb-usb-avertv-a800-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_A800_FW_0:=dvb-usb-avertv-a800-02.fw define KernelPackage/dvb-usb-a800/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_A800_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-a800)) define KernelPackage/dvb-usb-dibusb-mb SUBMENU:=$(DVB_MENU) TITLE:=DiBcom USB DVB-T devices KCONFIG:= CONFIG_DVB_USB_DIBUSB_MB \ CONFIG_DVB_PLL \ CONFIG_DVB_DIB3000MB \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-mb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dibusb-mb/description Say Y here to support the DiBcom USB DVB-T devices . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-dibusb-mb dvb-pll dib3000mb mt2060 You have to put the firmware files in the download dir : dvb-usb-dibusb-5.0.0.11.fw dvb-usb-dibusb-an2235-01.fw dvb-usb-adstech-usb2-02.fw dvb-usb-dibusb-6.0.0.8.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIBUSB_MB_FW_0:=dvb-usb-dibusb-5.0.0.11.fw DVB_USB_DIBUSB_MB_FW_1:=dvb-usb-dibusb-an2235-01.fw DVB_USB_DIBUSB_MB_FW_2:=dvb-usb-adstech-usb2-02.fw DVB_USB_DIBUSB_MB_FW_3:=dvb-usb-dibusb-6.0.0.8.fw define KernelPackage/dvb-usb-dibusb-mb/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_3) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dibusb-mb)) define KernelPackage/dvb-usb-dibusb-mc SUBMENU:=$(DVB_MENU) TITLE:=DiBcom USB DVB-T devices KCONFIG:= CONFIG_DVB_USB_DIBUSB_MC \ CONFIG_DVB_DIB3000MC \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dibusb-mc/description Say Y here to support the DiBcom USB DVB-T devices . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-dibusb-mc dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-dibusb-6.0.0.8.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIBUSB_MC_FW_0:=dvb-usb-dibusb-6.0.0.8.fw define KernelPackage/dvb-usb-dibusb-mc/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MC_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dibusb-mc)) define KernelPackage/dvb-usb-dib0700 SUBMENU:=$(DVB_MENU) TITLE:=DiBcom DiB0700 USB DVB devices KCONFIG:= CONFIG_DVB_USB_DIB0700 \ CONFIG_DVB_DIB7000P \ CONFIG_DVB_DIB7000M \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_S5H1411 \ CONFIG_DVB_LGDT3305 \ CONFIG_DVB_TUNER_DIB0070 \ CONFIG_MEDIA_TUNER_MT2060 \ CONFIG_MEDIA_TUNER_MT2266 \ CONFIG_MEDIA_TUNER_XC2028 \ CONFIG_MEDIA_TUNER_XC5000 \ CONFIG_MEDIA_TUNER_MXL5007T DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dib0700.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000p.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000m.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/s5h1411.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lgdt3305.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib0070.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2266.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tuner-xc2028.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/xc5000.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mxl5007t.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dib0700/description Say Y here to support the DiBcom DiB0700 USB DVB devices . The following modules will be compiled for this device : dvb-usb-dib0700 dib7000p dibx000_common dib7000m dibx000_common dib3000mc dibx000_common s5h1411 lgdt3305 dib0070 mt2060 mt2266 tuner-xc2028 xc5000 mxl5007t You have to put the firmware files in the download dir : dvb-usb-dib0700-1.20.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIB0700_FW_0:=dvb-usb-dib0700-1.20.fw define KernelPackage/dvb-usb-dib0700/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIB0700_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dib0700)) define KernelPackage/dvb-usb-umt-010 SUBMENU:=$(DVB_MENU) TITLE:=HanfTek UMT-010 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_UMT_010 \ CONFIG_DVB_PLL \ CONFIG_DVB_DIB3000MC \ CONFIG_MEDIA_TUNER_MT2060 \ CONFIG_DVB_MT352 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-umt-010.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-umt-010/description Say Y here to support the HanfTek UMT-010 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-umt-010 dvb-pll dib3000mc dibx000_common mt2060 mt352 You have to put the firmware files in the download dir : dvb-usb-umt-010-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_UMT_010_FW_0:=dvb-usb-umt-010-02.fw define KernelPackage/dvb-usb-umt-010/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_UMT_010_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-umt-010)) define KernelPackage/dvb-usb-cxusb SUBMENU:=$(DVB_MENU) TITLE:=Conexant USB2.0 hybrid reference design KCONFIG:= CONFIG_DVB_USB_CXUSB \ CONFIG_DVB_PLL \ CONFIG_DVB_CX22702 \ CONFIG_DVB_LGDT330X \ CONFIG_DVB_MT352 \ CONFIG_DVB_ZL10353 \ CONFIG_DVB_DIB7000P \ CONFIG_DVB_LGS8GL5 \ CONFIG_DVB_TUNER_DIB0070 \ CONFIG_MEDIA_TUNER_SIMPLE \ CONFIG_MEDIA_TUNER_XC2028 \ CONFIG_MEDIA_TUNER_MXL5005S DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-cxusb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/cx22702.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lgdt330x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000p.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lgs8gl5.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib0070.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tuner-simple.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tuner-types.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tuner-xc2028.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mxl5005s.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-cxusb/description Say Y here to support the Conexant USB2.0 hybrid reference design . The following modules will be compiled for this device : dvb-usb-cxusb dvb-pll cx22702 lgdt330x mt352 zl10353 dib7000p dibx000_common lgs8gl5 dib0070 tuner-simple tuner-types tuner-xc2028 mxl5005s You have to put the firmware files in the download dir : dvb-usb-bluebird-01.fw dvb-usb-bluebird-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_CXUSB_FW_0:=dvb-usb-bluebird-01.fw DVB_USB_CXUSB_FW_1:=dvb-usb-bluebird-02.fw define KernelPackage/dvb-usb-cxusb/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_CXUSB_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_CXUSB_FW_1) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-cxusb)) define KernelPackage/dvb-usb-m920x SUBMENU:=$(DVB_MENU) TITLE:=Uli m920x DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_M920X \ CONFIG_DVB_MT352 \ CONFIG_DVB_TDA1004X \ CONFIG_MEDIA_TUNER_QT1010 \ CONFIG_MEDIA_TUNER_TDA827X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-m920x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda1004x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tda827x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-m920x/description Say Y here to support the Uli m920x DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-m920x mt352 tda1004x qt1010 tda827x You have to put the firmware files in the download dir : dvb-usb-megasky-02.fw dvb-usb-digivox-02.fw dvb-usb-tvwalkert.fw dvb-usb-dposh-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_M920X_FW_0:=dvb-usb-megasky-02.fw DVB_USB_M920X_FW_1:=dvb-usb-digivox-02.fw DVB_USB_M920X_FW_2:=dvb-usb-tvwalkert.fw DVB_USB_M920X_FW_3:=dvb-usb-dposh-01.fw define KernelPackage/dvb-usb-m920x/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_3) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-m920x)) define KernelPackage/dvb-usb-gl861 SUBMENU:=$(DVB_MENU) TITLE:=Genesys Logic GL861 USB2.0 KCONFIG:= CONFIG_DVB_USB_GL861 \ CONFIG_DVB_ZL10353 \ CONFIG_MEDIA_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-gl861.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-gl861/description Say Y here to support the Genesys Logic GL861 USB2.0 . The following modules will be compiled for this device : dvb-usb-gl861 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-gl861)) define KernelPackage/dvb-usb-au6610 SUBMENU:=$(DVB_MENU) TITLE:=Alcor Micro AU6610 USB2.0 KCONFIG:= CONFIG_DVB_USB_AU6610 \ CONFIG_DVB_ZL10353 \ CONFIG_MEDIA_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-au6610.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-au6610/description Say Y here to support the Alcor Micro AU6610 USB2.0 . The following modules will be compiled for this device : dvb-usb-au6610 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-au6610)) define KernelPackage/dvb-usb-digitv SUBMENU:=$(DVB_MENU) TITLE:=Nebula Electronics uDigiTV DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_DIGITV \ CONFIG_DVB_PLL \ CONFIG_DVB_NXT6000 \ CONFIG_DVB_MT352 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-digitv.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/nxt6000.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-digitv/description Say Y here to support the Nebula Electronics uDigiTV DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-digitv dvb-pll nxt6000 mt352 You have to put the firmware files in the download dir : dvb-usb-digitv-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIGITV_FW_0:=dvb-usb-digitv-02.fw define KernelPackage/dvb-usb-digitv/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIGITV_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-digitv)) define KernelPackage/dvb-usb-vp7045 SUBMENU:=$(DVB_MENU) TITLE:=TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle KCONFIG:= CONFIG_DVB_USB_VP7045 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-vp7045.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-vp7045/description Say Y here to support the TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle. The following modules will be compiled for this device : dvb-usb-vp7045 You have to put the firmware files in the download dir : dvb-usb-vp7045-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_VP7045_FW_0:=dvb-usb-vp7045-01.fw define KernelPackage/dvb-usb-vp7045/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_VP7045_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-vp7045)) define KernelPackage/dvb-usb-vp702x SUBMENU:=$(DVB_MENU) TITLE:=TwinhanDTV StarBox and clones DVB-S USB2.0 KCONFIG:= CONFIG_DVB_USB_VP702X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-vp702x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-vp702x/description Say Y here to support the TwinhanDTV StarBox and clones DVB-S USB2.0 . The following modules will be compiled for this device : dvb-usb-vp702x You have to put the firmware files in the download dir : dvb-usb-vp702x-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_VP702X_FW_0:=dvb-usb-vp702x-02.fw define KernelPackage/dvb-usb-vp702x/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_VP702X_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-vp702x)) define KernelPackage/dvb-usb-gp8psk SUBMENU:=$(DVB_MENU) TITLE:=GENPIX 8PSK->USB module KCONFIG:= CONFIG_DVB_USB_GP8PSK DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-gp8psk.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-gp8psk/description Say Y here to support the GENPIX 8PSK->USB module . The following modules will be compiled for this device : dvb-usb-gp8psk You have to put the firmware files in the download dir : dvb-usb-gp8psk-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_GP8PSK_FW_0:=dvb-usb-gp8psk-01.fw define KernelPackage/dvb-usb-gp8psk/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_GP8PSK_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-gp8psk)) define KernelPackage/dvb-usb-nova-t-usb2 SUBMENU:=$(DVB_MENU) TITLE:=Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_NOVA_T_USB2 \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_PLL \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-nova-t-usb2.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-nova-t-usb2/description Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-nova-t-usb2 dib3000mc dibx000_common dvb-pll mt2060 You have to put the firmware files in the download dir : dvb-usb-nova-t-usb2-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_NOVA_T_USB2_FW_0:=dvb-usb-nova-t-usb2-02.fw define KernelPackage/dvb-usb-nova-t-usb2/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_NOVA_T_USB2_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-nova-t-usb2)) define KernelPackage/dvb-usb-ttusb2 SUBMENU:=$(DVB_MENU) TITLE:=Pinnacle 400e DVB-S USB2.0 KCONFIG:= CONFIG_DVB_USB_TTUSB2 \ CONFIG_DVB_TDA10086 \ CONFIG_DVB_LNBP21 \ CONFIG_DVB_TDA826X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-ttusb2.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda10086.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lnbp21.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda826x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-ttusb2/description Say Y here to support the Pinnacle 400e DVB-S USB2.0 . The following modules will be compiled for this device : dvb-usb-ttusb2 tda10086 lnbp21 tda826x You have to put the firmware files in the download dir : dvb-usb-pctv-400e-01.fw dvb-usb-tt-s2400-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_TTUSB2_FW_0:=dvb-usb-pctv-400e-01.fw DVB_USB_TTUSB2_FW_1:=dvb-usb-tt-s2400-01.fw define KernelPackage/dvb-usb-ttusb2/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_TTUSB2_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_TTUSB2_FW_1) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-ttusb2)) define KernelPackage/dvb-usb-dtt200u SUBMENU:=$(DVB_MENU) TITLE:=WideView WT-200U and WT-220U DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_DTT200U DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dtt200u.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dtt200u/description Say Y here to support the WideView WT-200U and WT-220U DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dtt200u You have to put the firmware files in the download dir : dvb-usb-dtt200u-01.fw dvb-usb-wt220u-02.fw dvb-usb-wt220u-fc03.fw dvb-usb-wt220u-zl0353-01.fw dvb-usb-wt220u-miglia-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DTT200U_FW_0:=dvb-usb-dtt200u-01.fw DVB_USB_DTT200U_FW_1:=dvb-usb-wt220u-02.fw DVB_USB_DTT200U_FW_2:=dvb-usb-wt220u-fc03.fw DVB_USB_DTT200U_FW_3:=dvb-usb-wt220u-zl0353-01.fw DVB_USB_DTT200U_FW_4:=dvb-usb-wt220u-miglia-01.fw define KernelPackage/dvb-usb-dtt200u/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_3) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_4) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dtt200u)) define KernelPackage/dvb-usb-opera1 SUBMENU:=$(DVB_MENU) TITLE:=Opera1 DVB-S USB2.0 receiver KCONFIG:= CONFIG_DVB_USB_OPERA1 \ CONFIG_DVB_STV0299 \ CONFIG_DVB_PLL DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-opera.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/stv0299.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-opera1/description Say Y here to support the Opera1 DVB-S USB2.0 receiver. The following modules will be compiled for this device : dvb-usb-opera stv0299 dvb-pll You have to put the firmware files in the download dir : dvb-usb-opera-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_OPERA1_FW_0:=dvb-usb-opera-01.fw define KernelPackage/dvb-usb-opera1/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_OPERA1_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-opera1)) define KernelPackage/dvb-usb-af9005 SUBMENU:=$(DVB_MENU) TITLE:=Afatech AF9005 DVB-T USB1.1 KCONFIG:= CONFIG_DVB_USB_AF9005 \ CONFIG_MEDIA_TUNER_MT2060 \ CONFIG_MEDIA_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-af9005/description Say Y here to support the Afatech AF9005 DVB-T USB1.1 . The following modules will be compiled for this device : dvb-usb-af9005 dvb-usb-af9005-remote mt2060 qt1010 You have to put the firmware files in the download dir : af9005.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_AF9005_FW_0:=af9005.fw define KernelPackage/dvb-usb-af9005/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_AF9005_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-af9005)) define KernelPackage/dvb-usb-af9005-remote SUBMENU:=$(DVB_MENU) TITLE:=Afatech AF9005 default remote control KCONFIG:= CONFIG_DVB_USB_AF9005_REMOTE DEPENDS:=+kmod-dvb-usb-af9005 FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-af9005-remote/description Say Y here to support the Afatech AF9005 default remote control . The following modules will be compiled for this device : dvb-usb-af9005-remote endef $(eval $(call KernelPackage,dvb-usb-af9005-remote)) define KernelPackage/dvb-usb-dw2102 SUBMENU:=$(DVB_MENU) TITLE:=DvbWorld DVB-S/S2 USB2.0 KCONFIG:= CONFIG_DVB_USB_DW2102 \ CONFIG_DVB_PLL \ CONFIG_DVB_STV0299 \ CONFIG_DVB_STV0288 \ CONFIG_DVB_STB6000 \ CONFIG_DVB_CX24116 \ CONFIG_DVB_SI21XX \ CONFIG_DVB_TDA10021 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dw2102.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/stv0299.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/stv0288.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/stb6000.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/cx24116.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/si21xx.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda10021.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dw2102/description Say Y here to support the DvbWorld DVB-S/S2 USB2.0 . The following modules will be compiled for this device : dvb-usb-dw2102 dvb-pll stv0299 stv0288 stb6000 cx24116 si21xx tda10021 You have to put the firmware files in the download dir : dvb-usb-dw2102.fw dvb-usb-dw2104.fw dvb-usb-dw3101.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DW2102_FW_0:=dvb-usb-dw2102.fw DVB_USB_DW2102_FW_1:=dvb-usb-dw2104.fw DVB_USB_DW2102_FW_2:=dvb-usb-dw3101.fw define KernelPackage/dvb-usb-dw2102/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DW2102_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DW2102_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DW2102_FW_2) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dw2102)) define KernelPackage/dvb-usb-cinergy-t2 SUBMENU:=$(DVB_MENU) TITLE:=Terratec CinergyT2/qanu USB 2.0 DVB-T receiver KCONFIG:= CONFIG_DVB_USB_CINERGY_T2 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-cinergyT2.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-cinergy-t2/description Say Y here to support the Terratec CinergyT2/qanu USB 2.0 DVB-T receiver. The following modules will be compiled for this device : dvb-usb-cinergyT2 endef $(eval $(call KernelPackage,dvb-usb-cinergy-t2)) define KernelPackage/dvb-usb-anysee SUBMENU:=$(DVB_MENU) TITLE:=Anysee DVB-T/C USB2.0 KCONFIG:= CONFIG_DVB_USB_ANYSEE \ CONFIG_DVB_PLL \ CONFIG_DVB_MT352 \ CONFIG_DVB_ZL10353 \ CONFIG_DVB_TDA10023 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-anysee.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda10023.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-anysee/description Say Y here to support the Anysee DVB-T/C USB2.0 . The following modules will be compiled for this device : dvb-usb-anysee dvb-pll mt352 zl10353 tda10023 endef $(eval $(call KernelPackage,dvb-usb-anysee)) define KernelPackage/dvb-usb-dtv5100 SUBMENU:=$(DVB_MENU) TITLE:=AME DTV-5100 USB2.0 DVB-T KCONFIG:= CONFIG_DVB_USB_DTV5100 \ CONFIG_DVB_ZL10353 \ CONFIG_MEDIA_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dtv5100.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dtv5100/description Say Y here to support the AME DTV-5100 USB2.0 DVB-T . The following modules will be compiled for this device : dvb-usb-dtv5100 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-dtv5100)) define KernelPackage/dvb-usb-af9015 SUBMENU:=$(DVB_MENU) TITLE:=Afatech AF9015 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_AF9015 \ CONFIG_DVB_AF9013 \ CONFIG_DVB_PLL \ CONFIG_MEDIA_TUNER_MT2060 \ CONFIG_MEDIA_TUNER_QT1010 \ CONFIG_MEDIA_TUNER_TDA18271 \ CONFIG_MEDIA_TUNER_MXL5005S \ CONFIG_MEDIA_TUNER_MC44S803 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9015.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/af9013.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tda18271.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mxl5005s.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mc44s803.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-af9015/description Say Y here to support the Afatech AF9015 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-af9015 af9013 dvb-pll mt2060 qt1010 tda18271 mxl5005s mc44s803 You have to put the firmware files in the download dir : dvb-usb-af9015.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_AF9015_FW_0:=dvb-usb-af9015.fw define KernelPackage/dvb-usb-af9015/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_AF9015_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-af9015)) define KernelPackage/dvb-usb-ce6230 SUBMENU:=$(DVB_MENU) TITLE:=Intel CE6230 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_CE6230 \ CONFIG_DVB_ZL10353 \ CONFIG_MEDIA_TUNER_MXL5005S DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-ce6230.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mxl5005s.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-ce6230/description Say Y here to support the Intel CE6230 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-ce6230 zl10353 mxl5005s endef $(eval $(call KernelPackage,dvb-usb-ce6230)) MuMuDVB-2.1.0/openwrt/package/kernel/modules/dvb.2.6.32.mk000066400000000000000000000776721305714132500226310ustar00rootroot00000000000000 # # Copyright (C) 2009 Brice DUBOST # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. # # # !!!! This is a generated file !!!! # DVB_MENU:=DVB support # # General section # define KernelPackage/dvb-core SUBMENU:=$(DVB_MENU) TITLE:=DVB core support DEPENDS:=@LINUX_2_6 +kmod-i2c-core KCONFIG:= \ CONFIG_MEDIA_SUPPORT \ CONFIG_DVB_CORE \ CONFIG_DVB_CAPTURE_DRIVERS=y \ CONFIG_MEDIA_TUNER_CUSTOMIZE=y \ CONFIG_DVB_FE_CUSTOMISE=y \ CONFIG_DVB_DYNAMIC_MINORS=n \ CONFIG_CRC32 FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-core/dvb-core.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,50,dvb-core) endef define KernelPackage/dvb-core/description Kernel module for DVB support endef $(eval $(call KernelPackage,dvb-core)) define KernelPackage/dvb-usb SUBMENU:=$(DVB_MENU) TITLE:=DVB USB Support DEPENDS:=@USB_SUPPORT +kmod-dvb-core +kmod-usb-core KCONFIG:= \ CONFIG_DVB_USB \ CONFIG_INPUT=y FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb.$(LINUX_KMOD_SUFFIX) # AUTOLOAD:=$(call AutoLoad,55,dvb-usb) endef define KernelPackage/dvb-usb/description Kernel module for DVB USB devices. Note you have to select at least a device. endef $(eval $(call KernelPackage,dvb-usb)) # # Devices section # define KernelPackage/dvb-usb-a800 SUBMENU:=$(DVB_MENU) TITLE:=AVerMedia AverTV DVB-T USB 2.0 KCONFIG:= CONFIG_DVB_USB_A800 \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_PLL \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-a800.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-a800/description Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-a800 dib3000mc dibx000_common dvb-pll mt2060 You have to put the firmware files in the download dir : dvb-usb-avertv-a800-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_A800_FW_0:=dvb-usb-avertv-a800-02.fw define KernelPackage/dvb-usb-a800/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_A800_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-a800)) define KernelPackage/dvb-usb-dibusb-mb SUBMENU:=$(DVB_MENU) TITLE:=DiBcom USB DVB-T devices KCONFIG:= CONFIG_DVB_USB_DIBUSB_MB \ CONFIG_DVB_PLL \ CONFIG_DVB_DIB3000MB \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-mb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dibusb-mb/description Say Y here to support the DiBcom USB DVB-T devices . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-dibusb-mb dvb-pll dib3000mb mt2060 You have to put the firmware files in the download dir : dvb-usb-dibusb-5.0.0.11.fw dvb-usb-dibusb-an2235-01.fw dvb-usb-adstech-usb2-02.fw dvb-usb-dibusb-6.0.0.8.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIBUSB_MB_FW_0:=dvb-usb-dibusb-5.0.0.11.fw DVB_USB_DIBUSB_MB_FW_1:=dvb-usb-dibusb-an2235-01.fw DVB_USB_DIBUSB_MB_FW_2:=dvb-usb-adstech-usb2-02.fw DVB_USB_DIBUSB_MB_FW_3:=dvb-usb-dibusb-6.0.0.8.fw define KernelPackage/dvb-usb-dibusb-mb/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MB_FW_3) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dibusb-mb)) define KernelPackage/dvb-usb-dibusb-mc SUBMENU:=$(DVB_MENU) TITLE:=DiBcom USB DVB-T devices KCONFIG:= CONFIG_DVB_USB_DIBUSB_MC \ CONFIG_DVB_DIB3000MC \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dibusb-mc/description Say Y here to support the DiBcom USB DVB-T devices . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-dibusb-mc dib3000mc dibx000_common mt2060 You have to put the firmware files in the download dir : dvb-usb-dibusb-6.0.0.8.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIBUSB_MC_FW_0:=dvb-usb-dibusb-6.0.0.8.fw define KernelPackage/dvb-usb-dibusb-mc/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIBUSB_MC_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dibusb-mc)) define KernelPackage/dvb-usb-dib0700 SUBMENU:=$(DVB_MENU) TITLE:=DiBcom DiB0700 USB DVB devices KCONFIG:= CONFIG_DVB_USB_DIB0700 \ CONFIG_DVB_DIB7000P \ CONFIG_DVB_DIB7000M \ CONFIG_DVB_DIB8000 \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_S5H1411 \ CONFIG_DVB_LGDT3305 \ CONFIG_DVB_TUNER_DIB0070 \ CONFIG_MEDIA_TUNER_MT2060 \ CONFIG_MEDIA_TUNER_MT2266 \ CONFIG_MEDIA_TUNER_XC2028 \ CONFIG_MEDIA_TUNER_XC5000 \ CONFIG_MEDIA_TUNER_MXL5007T DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dib0700.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000p.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000m.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib8000.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/s5h1411.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lgdt3305.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib0070.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2266.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tuner-xc2028.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/xc5000.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mxl5007t.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dib0700/description Say Y here to support the DiBcom DiB0700 USB DVB devices . The following modules will be compiled for this device : dvb-usb-dib0700 dib7000p dibx000_common dib7000m dibx000_common dib8000 dibx000_common dib3000mc dibx000_common s5h1411 lgdt3305 dib0070 mt2060 mt2266 tuner-xc2028 xc5000 mxl5007t You have to put the firmware files in the download dir : dvb-usb-dib0700-1.20.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIB0700_FW_0:=dvb-usb-dib0700-1.20.fw define KernelPackage/dvb-usb-dib0700/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIB0700_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dib0700)) define KernelPackage/dvb-usb-umt-010 SUBMENU:=$(DVB_MENU) TITLE:=HanfTek UMT-010 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_UMT_010 \ CONFIG_DVB_PLL \ CONFIG_DVB_DIB3000MC \ CONFIG_MEDIA_TUNER_MT2060 \ CONFIG_DVB_MT352 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-umt-010.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-umt-010/description Say Y here to support the HanfTek UMT-010 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-umt-010 dvb-pll dib3000mc dibx000_common mt2060 mt352 You have to put the firmware files in the download dir : dvb-usb-umt-010-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_UMT_010_FW_0:=dvb-usb-umt-010-02.fw define KernelPackage/dvb-usb-umt-010/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_UMT_010_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-umt-010)) define KernelPackage/dvb-usb-cxusb SUBMENU:=$(DVB_MENU) TITLE:=Conexant USB2.0 hybrid reference design KCONFIG:= CONFIG_DVB_USB_CXUSB \ CONFIG_DVB_PLL \ CONFIG_DVB_CX22702 \ CONFIG_DVB_LGDT330X \ CONFIG_DVB_MT352 \ CONFIG_DVB_ZL10353 \ CONFIG_DVB_DIB7000P \ CONFIG_DVB_LGS8GL5 \ CONFIG_DVB_TUNER_DIB0070 \ CONFIG_MEDIA_TUNER_SIMPLE \ CONFIG_MEDIA_TUNER_XC2028 \ CONFIG_MEDIA_TUNER_MXL5005S DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-cxusb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/cx22702.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lgdt330x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib7000p.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lgs8gl5.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib0070.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tuner-simple.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tuner-types.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tuner-xc2028.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mxl5005s.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-cxusb/description Say Y here to support the Conexant USB2.0 hybrid reference design . The following modules will be compiled for this device : dvb-usb-cxusb dvb-pll cx22702 lgdt330x mt352 zl10353 dib7000p dibx000_common lgs8gl5 dib0070 tuner-simple tuner-types tuner-xc2028 mxl5005s You have to put the firmware files in the download dir : dvb-usb-bluebird-01.fw dvb-usb-bluebird-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_CXUSB_FW_0:=dvb-usb-bluebird-01.fw DVB_USB_CXUSB_FW_1:=dvb-usb-bluebird-02.fw define KernelPackage/dvb-usb-cxusb/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_CXUSB_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_CXUSB_FW_1) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-cxusb)) define KernelPackage/dvb-usb-m920x SUBMENU:=$(DVB_MENU) TITLE:=Uli m920x DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_M920X \ CONFIG_DVB_MT352 \ CONFIG_DVB_TDA1004X \ CONFIG_MEDIA_TUNER_QT1010 \ CONFIG_MEDIA_TUNER_TDA827X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-m920x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda1004x.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tda827x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-m920x/description Say Y here to support the Uli m920x DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-m920x mt352 tda1004x qt1010 tda827x You have to put the firmware files in the download dir : dvb-usb-megasky-02.fw dvb-usb-digivox-02.fw dvb-usb-tvwalkert.fw dvb-usb-dposh-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_M920X_FW_0:=dvb-usb-megasky-02.fw DVB_USB_M920X_FW_1:=dvb-usb-digivox-02.fw DVB_USB_M920X_FW_2:=dvb-usb-tvwalkert.fw DVB_USB_M920X_FW_3:=dvb-usb-dposh-01.fw define KernelPackage/dvb-usb-m920x/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_M920X_FW_3) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-m920x)) define KernelPackage/dvb-usb-gl861 SUBMENU:=$(DVB_MENU) TITLE:=Genesys Logic GL861 USB2.0 KCONFIG:= CONFIG_DVB_USB_GL861 \ CONFIG_DVB_ZL10353 \ CONFIG_MEDIA_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-gl861.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-gl861/description Say Y here to support the Genesys Logic GL861 USB2.0 . The following modules will be compiled for this device : dvb-usb-gl861 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-gl861)) define KernelPackage/dvb-usb-au6610 SUBMENU:=$(DVB_MENU) TITLE:=Alcor Micro AU6610 USB2.0 KCONFIG:= CONFIG_DVB_USB_AU6610 \ CONFIG_DVB_ZL10353 \ CONFIG_MEDIA_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-au6610.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-au6610/description Say Y here to support the Alcor Micro AU6610 USB2.0 . The following modules will be compiled for this device : dvb-usb-au6610 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-au6610)) define KernelPackage/dvb-usb-digitv SUBMENU:=$(DVB_MENU) TITLE:=Nebula Electronics uDigiTV DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_DIGITV \ CONFIG_DVB_PLL \ CONFIG_DVB_NXT6000 \ CONFIG_DVB_MT352 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-digitv.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/nxt6000.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-digitv/description Say Y here to support the Nebula Electronics uDigiTV DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-digitv dvb-pll nxt6000 mt352 You have to put the firmware files in the download dir : dvb-usb-digitv-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DIGITV_FW_0:=dvb-usb-digitv-02.fw define KernelPackage/dvb-usb-digitv/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DIGITV_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-digitv)) define KernelPackage/dvb-usb-vp7045 SUBMENU:=$(DVB_MENU) TITLE:=TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle KCONFIG:= CONFIG_DVB_USB_VP7045 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-vp7045.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-vp7045/description Say Y here to support the TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle. The following modules will be compiled for this device : dvb-usb-vp7045 You have to put the firmware files in the download dir : dvb-usb-vp7045-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_VP7045_FW_0:=dvb-usb-vp7045-01.fw define KernelPackage/dvb-usb-vp7045/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_VP7045_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-vp7045)) define KernelPackage/dvb-usb-vp702x SUBMENU:=$(DVB_MENU) TITLE:=TwinhanDTV StarBox and clones DVB-S USB2.0 KCONFIG:= CONFIG_DVB_USB_VP702X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-vp702x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-vp702x/description Say Y here to support the TwinhanDTV StarBox and clones DVB-S USB2.0 . The following modules will be compiled for this device : dvb-usb-vp702x You have to put the firmware files in the download dir : dvb-usb-vp702x-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_VP702X_FW_0:=dvb-usb-vp702x-02.fw define KernelPackage/dvb-usb-vp702x/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_VP702X_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-vp702x)) define KernelPackage/dvb-usb-gp8psk SUBMENU:=$(DVB_MENU) TITLE:=GENPIX 8PSK->USB module KCONFIG:= CONFIG_DVB_USB_GP8PSK DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-gp8psk.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-gp8psk/description Say Y here to support the GENPIX 8PSK->USB module . The following modules will be compiled for this device : dvb-usb-gp8psk You have to put the firmware files in the download dir : dvb-usb-gp8psk-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_GP8PSK_FW_0:=dvb-usb-gp8psk-01.fw define KernelPackage/dvb-usb-gp8psk/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_GP8PSK_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-gp8psk)) define KernelPackage/dvb-usb-nova-t-usb2 SUBMENU:=$(DVB_MENU) TITLE:=Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_NOVA_T_USB2 \ CONFIG_DVB_DIB3000MC \ CONFIG_DVB_PLL \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-nova-t-usb2.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-nova-t-usb2/description Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dibusb-common dvb-usb-nova-t-usb2 dib3000mc dibx000_common dvb-pll mt2060 You have to put the firmware files in the download dir : dvb-usb-nova-t-usb2-02.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_NOVA_T_USB2_FW_0:=dvb-usb-nova-t-usb2-02.fw define KernelPackage/dvb-usb-nova-t-usb2/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_NOVA_T_USB2_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-nova-t-usb2)) define KernelPackage/dvb-usb-ttusb2 SUBMENU:=$(DVB_MENU) TITLE:=Pinnacle 400e DVB-S USB2.0 KCONFIG:= CONFIG_DVB_USB_TTUSB2 \ CONFIG_DVB_TDA10086 \ CONFIG_DVB_LNBP21 \ CONFIG_DVB_TDA826X DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-ttusb2.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda10086.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/lnbp21.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda826x.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-ttusb2/description Say Y here to support the Pinnacle 400e DVB-S USB2.0 . The following modules will be compiled for this device : dvb-usb-ttusb2 tda10086 lnbp21 tda826x You have to put the firmware files in the download dir : dvb-usb-pctv-400e-01.fw dvb-usb-tt-s2400-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_TTUSB2_FW_0:=dvb-usb-pctv-400e-01.fw DVB_USB_TTUSB2_FW_1:=dvb-usb-tt-s2400-01.fw define KernelPackage/dvb-usb-ttusb2/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_TTUSB2_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_TTUSB2_FW_1) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-ttusb2)) define KernelPackage/dvb-usb-dtt200u SUBMENU:=$(DVB_MENU) TITLE:=WideView WT-200U and WT-220U DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_DTT200U DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dtt200u.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dtt200u/description Say Y here to support the WideView WT-200U and WT-220U DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-dtt200u You have to put the firmware files in the download dir : dvb-usb-dtt200u-01.fw dvb-usb-wt220u-02.fw dvb-usb-wt220u-fc03.fw dvb-usb-wt220u-zl0353-01.fw dvb-usb-wt220u-miglia-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DTT200U_FW_0:=dvb-usb-dtt200u-01.fw DVB_USB_DTT200U_FW_1:=dvb-usb-wt220u-02.fw DVB_USB_DTT200U_FW_2:=dvb-usb-wt220u-fc03.fw DVB_USB_DTT200U_FW_3:=dvb-usb-wt220u-zl0353-01.fw DVB_USB_DTT200U_FW_4:=dvb-usb-wt220u-miglia-01.fw define KernelPackage/dvb-usb-dtt200u/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_3) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DTT200U_FW_4) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dtt200u)) define KernelPackage/dvb-usb-opera1 SUBMENU:=$(DVB_MENU) TITLE:=Opera1 DVB-S USB2.0 receiver KCONFIG:= CONFIG_DVB_USB_OPERA1 \ CONFIG_DVB_STV0299 \ CONFIG_DVB_PLL DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-opera.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/stv0299.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-opera1/description Say Y here to support the Opera1 DVB-S USB2.0 receiver. The following modules will be compiled for this device : dvb-usb-opera stv0299 dvb-pll You have to put the firmware files in the download dir : dvb-usb-opera-01.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_OPERA1_FW_0:=dvb-usb-opera-01.fw define KernelPackage/dvb-usb-opera1/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_OPERA1_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-opera1)) define KernelPackage/dvb-usb-af9005 SUBMENU:=$(DVB_MENU) TITLE:=Afatech AF9005 DVB-T USB1.1 KCONFIG:= CONFIG_DVB_USB_AF9005 \ CONFIG_MEDIA_TUNER_MT2060 \ CONFIG_MEDIA_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-af9005/description Say Y here to support the Afatech AF9005 DVB-T USB1.1 . The following modules will be compiled for this device : dvb-usb-af9005 dvb-usb-af9005-remote mt2060 qt1010 You have to put the firmware files in the download dir : af9005.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_AF9005_FW_0:=af9005.fw define KernelPackage/dvb-usb-af9005/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_AF9005_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-af9005)) define KernelPackage/dvb-usb-af9005-remote SUBMENU:=$(DVB_MENU) TITLE:=Afatech AF9005 default remote control KCONFIG:= CONFIG_DVB_USB_AF9005_REMOTE DEPENDS:=+kmod-dvb-usb-af9005 FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9005-remote.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-af9005-remote/description Say Y here to support the Afatech AF9005 default remote control . The following modules will be compiled for this device : dvb-usb-af9005-remote endef $(eval $(call KernelPackage,dvb-usb-af9005-remote)) define KernelPackage/dvb-usb-dw2102 SUBMENU:=$(DVB_MENU) TITLE:=DvbWorld & TeVii DVB-S/S2 USB2.0 KCONFIG:= CONFIG_DVB_USB_DW2102 \ CONFIG_DVB_PLL \ CONFIG_DVB_STV0299 \ CONFIG_DVB_STV0288 \ CONFIG_DVB_STB6000 \ CONFIG_DVB_CX24116 \ CONFIG_DVB_SI21XX \ CONFIG_DVB_TDA10021 \ CONFIG_DVB_MT312 \ CONFIG_DVB_ZL10039 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dw2102.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/stv0299.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/stv0288.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/stb6000.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/cx24116.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/si21xx.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda10021.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt312.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10039.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dw2102/description Say Y here to support the DvbWorld & TeVii DVB-S/S2 USB2.0 . The following modules will be compiled for this device : dvb-usb-dw2102 dvb-pll stv0299 stv0288 stb6000 cx24116 si21xx tda10021 mt312 zl10039 You have to put the firmware files in the download dir : dvb-usb-dw2102.fw dvb-usb-dw2104.fw dvb-usb-dw3101.fw dvb-usb-s630.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_DW2102_FW_0:=dvb-usb-dw2102.fw DVB_USB_DW2102_FW_1:=dvb-usb-dw2104.fw DVB_USB_DW2102_FW_2:=dvb-usb-dw3101.fw DVB_USB_DW2102_FW_3:=dvb-usb-s630.fw define KernelPackage/dvb-usb-dw2102/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DW2102_FW_0) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DW2102_FW_1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DW2102_FW_2) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_DW2102_FW_3) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-dw2102)) define KernelPackage/dvb-usb-cinergy-t2 SUBMENU:=$(DVB_MENU) TITLE:=Terratec CinergyT2/qanu USB 2.0 DVB-T receiver KCONFIG:= CONFIG_DVB_USB_CINERGY_T2 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-cinergyT2.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-cinergy-t2/description Say Y here to support the Terratec CinergyT2/qanu USB 2.0 DVB-T receiver. The following modules will be compiled for this device : dvb-usb-cinergyT2 endef $(eval $(call KernelPackage,dvb-usb-cinergy-t2)) define KernelPackage/dvb-usb-anysee SUBMENU:=$(DVB_MENU) TITLE:=Anysee DVB-T/C USB2.0 KCONFIG:= CONFIG_DVB_USB_ANYSEE \ CONFIG_DVB_PLL \ CONFIG_DVB_MT352 \ CONFIG_DVB_ZL10353 \ CONFIG_DVB_TDA10023 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-anysee.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/mt352.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/tda10023.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-anysee/description Say Y here to support the Anysee DVB-T/C USB2.0 . The following modules will be compiled for this device : dvb-usb-anysee dvb-pll mt352 zl10353 tda10023 endef $(eval $(call KernelPackage,dvb-usb-anysee)) define KernelPackage/dvb-usb-dtv5100 SUBMENU:=$(DVB_MENU) TITLE:=AME DTV-5100 USB2.0 DVB-T KCONFIG:= CONFIG_DVB_USB_DTV5100 \ CONFIG_DVB_ZL10353 \ CONFIG_MEDIA_TUNER_QT1010 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dtv5100.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-dtv5100/description Say Y here to support the AME DTV-5100 USB2.0 DVB-T . The following modules will be compiled for this device : dvb-usb-dtv5100 zl10353 qt1010 endef $(eval $(call KernelPackage,dvb-usb-dtv5100)) define KernelPackage/dvb-usb-af9015 SUBMENU:=$(DVB_MENU) TITLE:=Afatech AF9015 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_AF9015 \ CONFIG_DVB_AF9013 \ CONFIG_DVB_PLL \ CONFIG_MEDIA_TUNER_MT2060 \ CONFIG_MEDIA_TUNER_QT1010 \ CONFIG_MEDIA_TUNER_TDA18271 \ CONFIG_MEDIA_TUNER_MXL5005S \ CONFIG_MEDIA_TUNER_MC44S803 DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9015.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/af9013.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tda18271.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mxl5005s.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mc44s803.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-af9015/description Say Y here to support the Afatech AF9015 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-af9015 af9013 dvb-pll mt2060 qt1010 tda18271 mxl5005s mc44s803 You have to put the firmware files in the download dir : dvb-usb-af9015.fw They can be found in the package http://packages.ubuntu.com/jaunty/linux-firmware . endef DVB_USB_AF9015_FW_0:=dvb-usb-af9015.fw define KernelPackage/dvb-usb-af9015/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DVB_USB_AF9015_FW_0) $(1)/lib/firmware/ endef $(eval $(call KernelPackage,dvb-usb-af9015)) define KernelPackage/dvb-usb-ce6230 SUBMENU:=$(DVB_MENU) TITLE:=Intel CE6230 DVB-T USB2.0 KCONFIG:= CONFIG_DVB_USB_CE6230 \ CONFIG_DVB_ZL10353 \ CONFIG_MEDIA_TUNER_MXL5005S DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-ce6230.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/zl10353.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mxl5005s.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-ce6230/description Say Y here to support the Intel CE6230 DVB-T USB2.0 . The following modules will be compiled for this device : dvb-usb-ce6230 zl10353 mxl5005s endef $(eval $(call KernelPackage,dvb-usb-ce6230)) define KernelPackage/dvb-usb-friio SUBMENU:=$(DVB_MENU) TITLE:=Friio ISDB-T USB2.0 Receiver KCONFIG:= CONFIG_DVB_USB_FRIIO DEPENDS:=+kmod-dvb-usb FILES:= $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-friio.$(LINUX_KMOD_SUFFIX) endef define KernelPackage/dvb-usb-friio/description Say Y here to support the Friio ISDB-T USB2.0 Receiver . The following modules will be compiled for this device : dvb-usb-friio endef $(eval $(call KernelPackage,dvb-usb-friio)) MuMuDVB-2.1.0/openwrt/package/kernel/modules/dvb.mk000066400000000000000000000205231305714132500220610ustar00rootroot00000000000000# # Copyright (C) 2009 Brice DUBOST # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. # DVB_MENU:=DVB support define KernelPackage/dvb-core SUBMENU:=$(DVB_MENU) TITLE:=DVB core support DEPENDS:=@LINUX_2_6 +kmod-i2c-core KCONFIG:= \ CONFIG_DVB_CORE \ CONFIG_DVB_CAPTURE_DRIVERS=y \ CONFIG_CRC32 FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-core/dvb-core.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,50,dvb-core) endef define KernelPackage/dvb-core/description Kernel module for DVB support endef $(eval $(call KernelPackage,dvb-core)) define KernelPackage/dvb-usb SUBMENU:=$(DVB_MENU) TITLE:=DVB USB Support DEPENDS:=@USB_SUPPORT +kmod-dvb-core +kmod-usb-core +kmod-i2c-core KCONFIG:= \ CONFIG_DVB_USB \ CONFIG_INPUT=y FILES:=$(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb.$(LINUX_KMOD_SUFFIX) # AUTOLOAD:=$(call AutoLoad,55,dvb-usb) endef define KernelPackage/dvb-usb/description Kernel module for DVB USB devices. Note you have to select a device. endef $(eval $(call KernelPackage,dvb-usb)) define KernelPackage/dvb-usb-a800 SUBMENU:=$(DVB_MENU) TITLE:=AVerMedia AverTV DVB-T USB 2.0 (A800) receiver KCONFIG:= \ CONFIG_DVB_USB_A800 \ CONFIG_DVB_DIB3000MC \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=@USB_SUPPORT +kmod-dvb-core +kmod-dvb-usb +kmod-usb-core +kmod-i2c-core FILES:= \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-a800.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) # AUTOLOAD:=$(call Autoload,60, \ # dvb-pll \ # dibx000_common \ # dib3000mc \ # mt2060 \ # dvb-usb-dibusb-common \ # dvb-usb-a800 \ # ) endef A800_FW:=dvb-usb-avertv-a800-02.fw define KernelPackage/dvb-usb-a800/description Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver. The firmware will be downloaded from http://www.linuxtv.org/downloads/firmware/ If the download fail put the firmware $(A800_FW) in the openwrt download directory. endef define Download/dvb-usb-a800 FILE:=$(A800_FW) URL:=http://www.linuxtv.org/downloads/firmware/ endef define KernelPackage/dvb-usb-a800/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(A800_FW) $(1)/lib/firmware/ endef $(eval $(call Download,dvb-usb-a800)) $(eval $(call KernelPackage,dvb-usb-a800)) define KernelPackage/dvb-usb-af9015 SUBMENU:=$(DVB_MENU) TITLE:=Afatech AF9015 DVB-T USB2.0 support KCONFIG:= \ CONFIG_DVB_USB_AF9015 \ CONFIG_DVB_AF9013 \ CONFIG_DVB_PLL \ CONFIG_MEDIA_TUNER_MT2060 \ CONFIG_MEDIA_TUNER_QT1010 \ CONFIG_MEDIA_TUNER_TDA18271 \ CONFIG_MEDIA_TUNER_MXL5005S DEPENDS:=@USB_SUPPORT +kmod-dvb-core +kmod-dvb-usb +kmod-usb-core +kmod-i2c-core FILES:= \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-af9015.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/af9013.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/qt1010.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/tda18271.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mxl5005s.$(LINUX_KMOD_SUFFIX) endef AF9015_FW:=dvb-usb-af9015.fw define KernelPackage/dvb-usb-af9015/description Supported devices : * Afatech AF9015 DVB-T USB2.0 stick * Leadtek WinFast DTV Dongle Gold * Pinnacle PCTV 71e * KWorld PlusTV Dual DVB-T Stick (DVB-T 399U) * DigitalNow TinyTwin DVB-T Receiver * TwinHan AzureWave AD-TU700(704J) * TerraTec Cinergy T USB XE * KWorld PlusTV Dual DVB-T PCI (DVB-T PC160-2T) * AVerMedia AVerTV DVB-T Volar X * Xtensions XD-380 * MSI DIGIVOX Duo * Fujitsu-Siemens Slim Mobile USB DVB-T * Telestar Starstick 2 * AVerMedia A309 * MSI Digi VOX mini III The firmware will be downloaded from http://www.otit.fi/~crope/v4l-dvb/, version 4.65.0 If the download fail put the firmware $(AF9015_FW) in the openwrt download directory. endef define Download/dvb-usb-af9015 FILE:=$(AF9015_FW) URL:=http://www.otit.fi/~crope/v4l-dvb/af9015/af9015_firmware_cutter/firmware_files/4.65.0/ MD5SUM:=532b8e1eabd3b4e9f8ca084b767e4470 endef define KernelPackage/dvb-usb-af9015/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(AF9015_FW) $(1)/lib/firmware/ endef $(eval $(call Download,dvb-usb-af9015)) $(eval $(call KernelPackage,dvb-usb-af9015)) define KernelPackage/dvb-usb-dibusb-mc SUBMENU:=$(DVB_MENU) TITLE:=DiBcom USB DVB-T (DiB3000M-C/P based devices) KCONFIG:= \ CONFIG_DVB_USB_DIBUSB_MC \ CONFIG_DVB_DIB3000MC \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=@USB_SUPPORT +kmod-dvb-core +kmod-dvb-usb +kmod-usb-core +kmod-i2c-core FILES:= \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dibx000_common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mc.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef DIBUSB-MC_FW:=dvb-usb-dibusb-6.0.0.8.fw define KernelPackage/dvb-usb-dibusb-mc/description Supported devices : * DiBcom USB2.0 DVB-T reference design (MOD3000P) * Artec T1 USB2.0 TVBOX (please check the warm ID) * LITE-ON USB2.0 DVB-T Tuner * MSI Digivox Mini SL * GRAND - USB2.0 DVB-T adapter * Artec T14 - USB2.0 DVB-T * Leadtek - USB2.0 Winfast DTV dongle The firmware will be downloaded from http://www.linuxtv.org/downloads/firmware/ If the download fail put the firmware $(DIBUSB-MC_FW) in the openwrt download directory. endef define Download/dvb-usb-dibusb-mc FILE:=$(DIBUSB-MC_FW) URL:=http://www.linuxtv.org/downloads/firmware/ endef define KernelPackage/dvb-usb-dibusb-mc/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DIBUSB-MC_FW) $(1)/lib/firmware/ endef $(eval $(call Download,dvb-usb-dibusb-mc)) $(eval $(call KernelPackage,dvb-usb-dibusb-mc)) define KernelPackage/dvb-usb-dibusb-mb SUBMENU:=$(DVB_MENU) TITLE:=DiBcom USB DVB-T (DiB3000M-B based devices) KCONFIG:= \ CONFIG_DVB_USB_DIBUSB_MB \ CONFIG_DVB_PLL \ CONFIG_DVB_DIB3000MB \ CONFIG_MEDIA_TUNER_MT2060 DEPENDS:=@USB_SUPPORT +kmod-dvb-core +kmod-dvb-usb +kmod-usb-core +kmod-i2c-core FILES:= \ $(LINUX_DIR)/drivers/media/dvb/frontends/dvb-pll.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-dibusb-common.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/dvb-usb/dvb-usb-mb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/dvb/frontends/dib3000mb.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/media/common/tuners/mt2060.$(LINUX_KMOD_SUFFIX) endef DIBUSB-MB_FW1:=dvb-usb-dibusb-5.0.0.11.fw DIBUSB-MB_FW2:=dvb-usb-dibusb-6.0.0.8.fw define KernelPackage/dvb-usb-dibusb-mb/description Supported devices : * AVerMedia AverTV DVBT USB1.1 * Compro Videomate DVB-U2000 - DVB-T USB1.1 (please confirm to linux-dvb) * DiBcom USB1.1 DVB-T reference design (MOD3000) * KWorld V-Stream XPERT DTV - DVB-T USB1.1 * Grandtec USB1.1 DVB-T * TwinhanDTV USB-Ter USB1.1 / Magic Box I / HAMA USB1.1 DVB-T device * Artec T1 USB1.1 TVBOX with AN2135 * VideoWalker DVB-T USB * Artec T1 USB2.0 Supported but you have to add the firmware by hand : * KWorld Xpert DVB-T USB2.0 * KWorld/ADSTech Instant DVB-T USB2.0 * Artec T1 USB1.1 TVBOX with AN2235 The firmware will be downloaded from http://www.linuxtv.org/downloads/firmware/ If the download fail put the firmware $(DIBUSB-MB_FW1) $(DIBUSB-MB_FW2) in the openwrt download directory. endef define Download/dvb-usb-dibusb-mb1 FILE:=$(DIBUSB-MB_FW1) URL:=http://www.linuxtv.org/downloads/firmware/ endef define Download/dvb-usb-dibusb-mb2 FILE:=$(DIBUSB-MB_FW2) URL:=http://www.linuxtv.org/downloads/firmware/ endef define KernelPackage/dvb-usb-dibusb-mb/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) $(DL_DIR)/$(DIBUSB-MB_FW1) $(1)/lib/firmware/ $(INSTALL_DATA) $(DL_DIR)/$(DIBUSB-MB_FW2) $(1)/lib/firmware/ endef $(eval $(call Download,dvb-usb-dibusb-mb1)) $(eval $(call Download,dvb-usb-dibusb-mb2)) $(eval $(call KernelPackage,dvb-usb-dibusb-mb)) MuMuDVB-2.1.0/openwrt/packages/000077500000000000000000000000001305714132500162065ustar00rootroot00000000000000MuMuDVB-2.1.0/openwrt/packages/mumudvb/000077500000000000000000000000001305714132500176655ustar00rootroot00000000000000MuMuDVB-2.1.0/openwrt/packages/mumudvb/Makefile000066400000000000000000000017201305714132500213250ustar00rootroot00000000000000# # Copyright (C) 2009 Brice DUBOST # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. # include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=mumudvb PKG_VERSION:=1.6.1-openwrt PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=http://mumudvb.braice.net/mumudvb/mumudvb-beta PKG_BUILD_DIR:=$(BUILD_DIR)/mumudvb EXTRA_CPPFLAGS+=-std=gnu99 include $(INCLUDE_DIR)/package.mk define Package/mumudvb SECTION:=utils CATEGORY:=Utilities DEFAULT:=n TITLE:=MuMuDVB streaming software URL:=http://mumudvb.braice.net/ endef define Package/mumudvb/description MuMuDVB streaming software endef define Build/Configure $(call Build/Configure/Default,--with-linux-headers=$(LINUX_DIR)) endef define Package/mumudvb/install $(INSTALL_DIR) $(1)/usr/bin $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/mumudvb $(1)/usr/bin/mumudvb endef $(eval $(call BuildPackage,mumudvb)) MuMuDVB-2.1.0/scripts/000077500000000000000000000000001305714132500144215ustar00rootroot00000000000000MuMuDVB-2.1.0/scripts/android_build.sh000077500000000000000000000022421305714132500175570ustar00rootroot00000000000000#!/bin/sh # Build script to android. Change the variables on "Path block" to the correct path. API=8 # Path block ANDROID_NDK=/home/ounao/android-ndk-r9c # Android NDK path SRC_DIR=/home/ounao/source/MuMuDVB # Path to MuMuDVB source INSTALL_DIR=/home/ounao/source/out # Path to android MuMuDVB install INCLUDE_DIR=/home/ounao/source/out/include # Path to linux/dvb headers (obrigatory) and iconv.h (optional) LIB_DIR=/home/ounao/source/out/lib # Path to libiconv.a (optional) # Path block cd $SRC_DIR export PATH="$ANDROID_NDK/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/:$PATH" export SYS_ROOT="$ANDROID_NDK/platforms/android-$API/arch-arm/" export CC="arm-linux-androideabi-gcc --sysroot=$SYS_ROOT" export CXX="arm-linux-androideabi-g++ --sysroot=$SYS_ROOT" export CPP="arm-linux-androideabi-cpp --sysroot=$SYS_ROOT" export LD="arm-linux-androideabi-ld" export AR="arm-linux-androideabi-ar" export RANLIB="arm-linux-androideabi-ranlib" export STRIP="arm-linux-androideabi-strip" export LDFLAGS="-L$LIB_DIR" export CFLAGS="-I$INCLUDE_DIR" export LIBS="-lc -lgcc -liconv" ./configure --host=arm-eabi --enable-android --prefix=$INSTALL_DIR make make install MuMuDVB-2.1.0/scripts/debian/000077500000000000000000000000001305714132500156435ustar00rootroot00000000000000MuMuDVB-2.1.0/scripts/debian/README000066400000000000000000000003441305714132500165240ustar00rootroot00000000000000Startup scripts for mumudvb (Debian flavour) This script expects to find /etc/default/mumudvb, with the syntax specified in the example file These scripts can be used to use monit to monitor mumudvb (http://mmonit.com/monit/) MuMuDVB-2.1.0/scripts/debian/etc/000077500000000000000000000000001305714132500164165ustar00rootroot00000000000000MuMuDVB-2.1.0/scripts/debian/etc/default/000077500000000000000000000000001305714132500200425ustar00rootroot00000000000000MuMuDVB-2.1.0/scripts/debian/etc/default/mumudvb000066400000000000000000000011721305714132500214450ustar00rootroot00000000000000#Mumudvb init config file # # This file is used to specify the locations of mumudvb config files for each card # #If you don't want to automatically start mumudvb, uncomment this line #DONTSTARTMUMU=true #If you want to launch a command before mumudvb (for example for automatic configuration generation) #LAUNCH_BEFORE_MUMU="" #Options for mumudvb DAEMON_OPTS="" #The user to launch mumudvb DAEMONUSER=_mumudvb #Change this line to reflect your configuration #Ex : ADAPTERS="0 1 2 4" ADAPTERS="0" #Location of the config files #Ex : MUMUDVB_CONF_1="/etc/mumudvb/card1.conf" MUMUDVB_CONF_0="/etc/mumudvb/to_be_configured.conf" MuMuDVB-2.1.0/scripts/debian/etc/init.d/000077500000000000000000000000001305714132500176035ustar00rootroot00000000000000MuMuDVB-2.1.0/scripts/debian/etc/init.d/mumudvb000077500000000000000000000046311305714132500212140ustar00rootroot00000000000000#!/bin/sh ### BEGIN INIT INFO # Provides: mumudvb # Required-Start: $remote_fs $network $syslog # Required-Stop: $remote_fs $network $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: mumudvb # Description: Digital television streaming program ### END INIT INFO PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin DAEMON=/usr/bin/mumudvb PIDDIR=/var/run/mumudvb DEFAULT_FILE=/etc/default/mumudvb NAME=mumudvb DESC="television streaming program" #Reading of the config file if [ -f "$DEFAULT_FILE" ] ; then . "$DEFAULT_FILE" fi if [ "$DONTSTARTMUMU" = "true" ]; then exit 0; fi . /lib/lsb/init-functions test -x $DAEMON || exit 5 set -e do_start() { if [ ! -d $PIDDIR ]; then mkdir -p $PIDDIR fi chown $DAEMONUSER $PIDDIR if [ -x "$LAUNCH_BEFORE_MUMU" ]; then log_daemon_msg "Launching pre script ..." eval $LAUNCH_BEFORE_MUMU log_daemon_msg "Done." fi for ADAPTER in $ADAPTERS; do #Todo : fails if all card fails log_daemon_msg " Starting card $ADAPTER" eval CONFIG_FILE=\$MUMUDVB_CONF_$ADAPTER if [ ! -f $CONFIG_FILE ]; then log_warning_msg " Card $ADAPTER: Config file $CONFIG_FILE not found." else start-stop-daemon --start --oknodo --name mumudvb_$ADAPTER\ --make-pidfile --pidfile=$PIDDIR/mumudvb_init_$ADTAPTER.pid\ --chuid $DAEMONUSER --exec $DAEMON -- $DAEMON_OPTS --card $ADAPTER -c $CONFIG_FILE fi done } do_stop() { for PIDFILE in `ls $PIDDIR/mumudvb_init_*.pid 2> /dev/null`; do start-stop-daemon --stop --oknodo --pidfile "$PIDFILE" \ --exec $DAEMON done } case "$1" in start) if [ ! -f "$DEFAULT_FILE" ]; then log_failure_msg "$DEFAULT_FILE not found, Can't start $NAME" exit 6 fi log_daemon_msg "Starting $DESC: $NAME" do_start log_end_msg $? ;; stop) log_daemon_msg "Stopping $DESC: $NAME" do_stop log_end_msg $? ;; restart|force-reload) log_daemon_msg "Restarting $DESC: $NAME" do_stop sleep 1 do_start log_end_msg $? ;; status) status_of_proc "$DAEMON" "$DESC: $NAME" && exit 0 || exit $? ;; *) log_success_msg "Usage: $0 {start|stop|restart|force-reload|status}" >&2 exit 1 ;; esac exit 0 MuMuDVB-2.1.0/src/000077500000000000000000000000001305714132500135215ustar00rootroot00000000000000MuMuDVB-2.1.0/src/Makefile.am000066400000000000000000000030311305714132500155520ustar00rootroot00000000000000# what flags you want to pass to the C compiler & linker AM_CFLAGS = -Wall -Wextra AM_LDFLAGS = check_PROGRAMS = mumudvb_test mumudvb_test_SOURCES = mumudvb_test.c autoconf.c crc32.c dvb.h log.c log.h multicast.c mumudvb.h network.h rewrite.h \ rtp.h sap.h ts.h tune.h unicast_http.h autoconf.h dvb.c errors.h \ mumudvb_common.c network.c rewrite_pat.c rewrite.c rewrite_sdt.c rewrite_eit.c \ rtp.c sap.c ts.c tune.c unicast_http.c unicast_queue.c autoconf_sdt.c autoconf_atsc.c \ autoconf_pmt.c autoconf_nit.c unicast_clients.c bin_PROGRAMS = mumudvb mumudvb_SOURCES = autoconf.c crc32.c dvb.h log.c log.h multicast.c mumudvb.h network.h rewrite.h \ rtp.h sap.h ts.h tune.h unicast_http.h autoconf.h dvb.c errors.h \ mumudvb.c mumudvb_mon.c mumudvb_mon.h mumudvb_common.c network.c rewrite_pmt.c rewrite_pat.c rewrite.c rewrite_sdt.c rewrite_eit.c \ rtp.c sap.c ts.c tune.c unicast_http.c unicast_queue.c unicast_EIT.c autoconf_sdt.c autoconf_atsc.c \ autoconf_pmt.c autoconf_nit.c unicast_clients.c unicast_monit.c mumudvb_channels.c \ autoconf_pat.c mumudvb_LDADD = -lm if BUILD_CAMSUPPORT mumudvb_SOURCES += $(SOURCES_camsupport) endif SOURCES_camsupport = \ cam.c \ cam.h \ $(NULL) if BUILD_SCAMSUPPORT mumudvb_SOURCES += $(SOURCES_scamsupport) endif SOURCES_scamsupport = \ scam_capmt.c \ scam_capmt.h \ scam_common.c \ scam_common.h \ scam_getcw.c \ scam_getcw.h \ scam_decsa.c \ scam_decsa.h \ scam_send.c \ scam_send.h \ $(NULL) MuMuDVB-2.1.0/src/autoconf.c000066400000000000000000000574011305714132500155120ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * File for Autoconfiguration * * (C) 2008-2014 Brice DUBOST * * Parts of this code come from libdvb, modified for mumudvb * by Brice DUBOST * Libdvb part : Copyright (C) 2000 Klaus Schmidinger * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** @file * @brief This file contain the code related to the autoconfiguration of MuMudvb * * It contains the functions to extract the relevant informations from the PAT,PMT,SDT PIDs and from ATSC PSIP table * * The PAT contains the list of the channels in the actual stream, their service number and the PMT PID * * The SDT contains the name of the channels associated to a certain service number and the type of service * * The PSIP (ATSC only) table contains the same kind of information as the SDT * * The PMT contains the PIDs (audio video etc ...) of the channels, * * The idea is the following * All the channels are uniquely identified with their SID * For each parameter of the channel, it will not be updated by autoconf if user set (except templates) * From the PAT we extract the channel list with the PMT PID, this list is too complete, some services in the PAT are not TV/radio channels * The SDT table allow to extract the name of the service and the service type, from the service type we flag the channels we want * On these channels once all the PAT and SDT sections are read, we open the sockets and the filters and wait for their PMT * From the PMT PIDs we extract audio and video information. * All these functions are intended to be triggered at any time in case of update. * * When a channel is removed from the PAT, the information about the channel is kept, it is just marked as being removed. * This allows to keep the IP if the channel comes back */ #include #include #include #include #include #include #include #include #include #include #include #include #include "errors.h" #include "ts.h" #include "mumudvb.h" #include "dvb.h" #include "network.h" #include "autoconf.h" #include "rtp.h" #include "log.h" #ifdef ENABLE_SCAM_SUPPORT #include "scam_capmt.h" #include "scam_common.h" #include "scam_getcw.h" #include "scam_decsa.h" #endif static char *log_module="Autoconf: "; int autoconf_read_pat(auto_p_t *auto_p,mumu_chan_p_t *chan_p); int autoconf_read_sdt(auto_p_t *auto_p,mumu_chan_p_t *chan_p); int autoconf_read_psip(auto_p_t *auto_p,mumu_chan_p_t *chan_p); int autoconf_read_nit(auto_p_t *parameters,mumu_chan_p_t *chan_p); int autoconf_read_pmt(mumudvb_channel_t *channel, mumudvb_ts_packet_t *pmt); int autoconf_pat_need_update(auto_p_t *auto_p, unsigned char *buf); void autoconf_sdt_need_update(auto_p_t *auto_p, unsigned char *buf); int autoconf_nit_need_update(auto_p_t *auto_p, unsigned char *buf); void autoconf_psip_need_update(auto_p_t *auto_p, unsigned char *buf); /** Initialize Autoconf variables*/ void init_aconf_v(auto_p_t *aconf_p) { memset(aconf_p,0,sizeof(auto_p_t)); //Since we have 'memsetted' the structure we only set non zero values *aconf_p=(auto_p_t){ .autoconf_ip4="239.100.%card.%number", .autoconf_ip6="FF15:4242::%server:%card:%number", .transport_stream_id=-1, // see http://www.etsi.org/deliver/etsi_ts/102600_102699/10261102/01.02.01_60/ts_10261102v010201p.pdf p14 // see http://www.etsi.org/deliver/etsi_ts/101100_101199/101162/01.07.01_60/ts_101162v010701p.pdf p18 p19 .network_id=-1, .original_network_id=-1, .pat_version=-1, .sdt_version=-1, .nit_version=-1, }; } /** @brief Read a line of the configuration file to check if there is a autoconf parameter * * @param auto_p the autoconfiguration parameters * @param substring The currrent line */ int read_autoconfiguration_configuration(auto_p_t *auto_p, char *substring) { char delimiteurs[] = CONFIG_FILE_SEPARATOR; if (!strcmp (substring, "autoconf_scrambled")) { substring = strtok (NULL, delimiteurs); auto_p->autoconf_scrambled = atoi (substring); } else if (!strcmp (substring, "autoconfiguration")) { substring = strtok (NULL, delimiteurs); if(atoi (substring)==1) auto_p->autoconfiguration = AUTOCONF_MODE_FULL; else if (!strcmp (substring, "full")) auto_p->autoconfiguration = AUTOCONF_MODE_FULL; else if (!strcmp (substring, "none")) auto_p->autoconfiguration = AUTOCONF_MODE_NONE; if(!((auto_p->autoconfiguration==AUTOCONF_MODE_FULL)||(auto_p->autoconfiguration==AUTOCONF_MODE_NONE))) { log_message( log_module, MSG_WARN, "Bad value for autoconfiguration, autoconfiguration will not be run\n"); auto_p->autoconfiguration=AUTOCONF_MODE_NONE; } } else if (!strcmp (substring, "autoconf_radios")) { substring = strtok (NULL, delimiteurs); auto_p->autoconf_radios = atoi (substring); if(!(auto_p->autoconfiguration==AUTOCONF_MODE_FULL)) { log_message( log_module, MSG_INFO, "You have to set autoconfiguration in full mode to use autoconf of the radios\n"); } } else if ((!strcmp (substring, "autoconf_ip4"))) { substring = strtok (NULL, delimiteurs); if(strlen(substring)>79) { log_message( log_module, MSG_ERROR, "The autoconf ip v4 is too long\n"); return -1; } sscanf (substring, "%s\n", auto_p->autoconf_ip4); } else if (!strcmp (substring, "autoconf_ip6")) { substring = strtok (NULL, delimiteurs); if(strlen(substring)>79) { log_message( log_module, MSG_ERROR, "The autoconf ip v6 is too long\n"); return -1; } sscanf (substring, "%s\n", auto_p->autoconf_ip6); } /** option for the starting http unicast port (for autoconf full)*/ else if (!strcmp (substring, "autoconf_unicast_start_port")) { substring = strtok (NULL, delimiteurs); sprintf(auto_p->autoconf_unicast_port,"%d +%%number",atoi (substring)); } /** option for the http unicast port (for autoconf full) parsed version*/ else if (!strcmp (substring, "autoconf_unicast_port")) { substring = strtok (NULL, "="); if(strlen(substring)>255) { log_message( log_module, MSG_ERROR, "The autoconf_unicast_port is too long\n"); return -1; } strcpy(auto_p->autoconf_unicast_port,substring); } /** option for the http multicast port (for autoconf full) parsed version*/ else if (!strcmp (substring, "autoconf_multicast_port")) { substring = strtok (NULL, "="); if(strlen(substring)>255) { log_message( log_module, MSG_ERROR, "The autoconf_multicast_port is too long\n"); return -1; } strcpy(auto_p->autoconf_multicast_port,substring); } else if (!strcmp (substring, "autoconf_sid_list")) { while ((substring = strtok (NULL, delimiteurs)) != NULL) { if (auto_p->num_service_id >= MAX_CHANNELS) { log_message( log_module, MSG_ERROR, "Autoconfiguration : Too many ts id : %d\n", auto_p->num_service_id); return -1; } auto_p->service_id_list[auto_p->num_service_id] = atoi (substring); auto_p->num_service_id++; } } else if (!strcmp (substring, "autoconf_sid_list_ignore")) { while ((substring = strtok (NULL, delimiteurs)) != NULL) { if (auto_p->num_service_id_ignore >= MAX_CHANNELS) { log_message( log_module, MSG_ERROR, "Autoconfiguration : Too many ignored ts id : %d\n", auto_p->num_service_id_ignore); return -1; } auto_p->service_id_list_ignore[auto_p->num_service_id_ignore] = atoi (substring); auto_p->num_service_id_ignore++; } } else if (!strcmp (substring, "autoconf_name_template")) { // other substring extraction method in order to keep spaces substring = strtok (NULL, "="); strncpy(auto_p->name_template,strtok(substring,"\n"),MAX_NAME_LEN-1); auto_p->name_template[MAX_NAME_LEN-1]='\0'; if (strlen (substring) >= MAX_NAME_LEN - 1) log_message( log_module, MSG_WARN,"Autoconfiguration: Channel name template too long\n"); } else return 0; //Nothing concerning autoconfiguration, we return 0 to explore the other possibilities return 1;//We found something for autoconfiguration, we tell main to go for the next line } /** @brief initialize the autoconfiguration : alloc the memory etc... * */ int autoconf_init(auto_p_t *auto_p) { if(auto_p->autoconfiguration) { auto_p->autoconf_temp_pat=malloc(sizeof(mumudvb_ts_packet_t)); if(auto_p->autoconf_temp_pat==NULL) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); set_interrupted(ERROR_MEMORY<<8); return -1; } memset (auto_p->autoconf_temp_pat, 0, sizeof( mumudvb_ts_packet_t));//we clear it pthread_mutex_init(&auto_p->autoconf_temp_pat->packetmutex,NULL); auto_p->autoconf_temp_sdt=malloc(sizeof(mumudvb_ts_packet_t)); if(auto_p->autoconf_temp_sdt==NULL) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); set_interrupted(ERROR_MEMORY<<8); return -1; } memset (auto_p->autoconf_temp_sdt, 0, sizeof( mumudvb_ts_packet_t));//we clear it pthread_mutex_init(&auto_p->autoconf_temp_sdt->packetmutex,NULL); auto_p->autoconf_temp_psip=malloc(sizeof(mumudvb_ts_packet_t)); if(auto_p->autoconf_temp_psip==NULL) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); set_interrupted(ERROR_MEMORY<<8); return -1; } memset (auto_p->autoconf_temp_psip, 0, sizeof( mumudvb_ts_packet_t));//we clear it pthread_mutex_init(&auto_p->autoconf_temp_psip->packetmutex,NULL); auto_p->autoconf_temp_nit=malloc(sizeof(mumudvb_ts_packet_t)); if(auto_p->autoconf_temp_nit==NULL) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); set_interrupted(ERROR_MEMORY<<8); return -1; } memset (auto_p->autoconf_temp_nit, 0, sizeof( mumudvb_ts_packet_t));//we clear it pthread_mutex_init(&auto_p->autoconf_temp_nit->packetmutex,NULL); } return 0; } /****************************************************************************/ //Parts of this code (read of the pmt and read of the pat) // from libdvb, strongly modified, with commentaries added /****************************************************************************/ /**@brief Free the autoconf parameters. * * @param auto_p pointer to the autoconf structure */ void autoconf_freeing(auto_p_t *auto_p) { if(auto_p->autoconf_temp_sdt) { free(auto_p->autoconf_temp_sdt); auto_p->autoconf_temp_sdt=NULL; } if(auto_p->autoconf_temp_psip) { free(auto_p->autoconf_temp_psip); auto_p->autoconf_temp_psip=NULL; } if(auto_p->autoconf_temp_pat) { free(auto_p->autoconf_temp_pat); auto_p->autoconf_temp_pat=NULL; } } /** Update the status of the channels */ void autoconf_update_chan_status(auto_p_t *auto_p,mumu_chan_p_t *chan_p) { //TODO: this function is a duplicate of what is done at the init of the global program : merge it log_message( log_module, MSG_INFO,"Looking through all channels to see if they are ready for streaming"); pthread_mutex_lock(&chan_p->lock); for (int ichan = 0; ichan < chan_p->number_of_channels; ichan++) { //If service removed we let it like that if(chan_p->channels[ichan].channel_ready==REMOVED) continue; //If channel user specified, it's always up if( MU_F(chan_p->channels[ichan].service_id)!=F_DETECTED) continue; if(!auto_p->autoconf_scrambled && chan_p->channels[ichan].free_ca_mode) { log_message( log_module, MSG_DETAIL,"Channel scrambled, no CAM support and no autoconf_scrambled, we skip. Name \"%s\"", chan_p->channels[ichan].name); chan_p->channels[ichan].channel_ready=NO_STREAMING; continue; } if(!chan_p->channels[ichan].pid_i.pmt_pid) { log_message( log_module, MSG_DETAIL,"Service without a PMT PID, we skip. Name \"%s\"", chan_p->channels[ichan].name); chan_p->channels[ichan].channel_ready=NO_STREAMING; continue; } //The service was autodetected, we check it's present in the SID list if(auto_p->num_service_id) { int sid_i; int found_in_service_id_list=0; for(sid_i=0;sid_inum_service_id && !found_in_service_id_list;sid_i++) { if(auto_p->service_id_list[sid_i]==chan_p->channels[ichan].service_id) { found_in_service_id_list=1; log_message( log_module, MSG_DEBUG,"Service found in the service_id list. Name \"%s\"", chan_p->channels[ichan].name); } } if(found_in_service_id_list==0) { log_message( log_module, MSG_DETAIL,"Service NOT in the service_id list, we skip. Name \"%s\", id %d\n", chan_p->channels[ichan].name, chan_p->channels[ichan].service_id); chan_p->channels[ichan].channel_ready=NO_STREAMING; continue; } } //The service was autodetected, we check it's present in the ignore list if(auto_p->num_service_id_ignore) { int sid_i; int found_in_service_id_ignore_list=0; for(sid_i=0;sid_inum_service_id_ignore;sid_i++) { if(auto_p->service_id_list_ignore[sid_i]==chan_p->channels[ichan].service_id) { found_in_service_id_ignore_list=1; } } if(found_in_service_id_ignore_list==1) { log_message( log_module, MSG_DETAIL,"Service in ignore list, we skip. Name \"%s\", id %d\n", chan_p->channels[ichan].name, chan_p->channels[ichan].service_id); chan_p->channels[ichan].channel_ready=NO_STREAMING; continue; } } //Cf EN 300 468 v1.9.1 Table 81 //Everything seems to be OK, we check if this is a radio or a TV channel if((chan_p->channels[ichan].service_type==0x01|| chan_p->channels[ichan].service_type==0x11|| chan_p->channels[ichan].service_type==0x16|| chan_p->channels[ichan].service_type==0x19|| chan_p->channels[ichan].service_type==0x1f|| chan_p->channels[ichan].service_type==0xc0)|| ((chan_p->channels[ichan].service_type==0x02|| chan_p->channels[ichan].service_type==0x0a)&&auto_p->autoconf_radios)) { log_message( log_module, MSG_DETAIL,"Service OK becoming ready. Name \"%s\", id %d type %s", chan_p->channels[ichan].name, chan_p->channels[ichan].service_id, service_type_to_str(chan_p->channels[ichan].service_type)); //We set it to almost ready because network is not up yet chan_p->channels[ichan].channel_ready=ALMOST_READY; } else if(chan_p->channels[ichan].service_type==0x02||chan_p->channels[ichan].service_type==0x0a) //service_type digital radio sound service log_message( log_module, MSG_DETAIL,"Service type digital radio sound service, no autoconfigure. (if you want add autoconf_radios=1 to your configuration file) Name \"%s\"\n", chan_p->channels[ichan].name); else if(chan_p->channels[ichan].service_type!=0) //0 is an empty service { //We show the service type log_message( log_module, MSG_DETAIL,"No autoconfiguration because of service type : 0x%x %s. Name \"%s\"\n", chan_p->channels[ichan].service_type,service_type_to_str(chan_p->channels[ichan].service_type), chan_p->channels[ichan].name); } } pthread_mutex_unlock(&chan_p->lock); } /** @brief Set the networking for the channels almost ready */ void autoconf_update_chan_name(mumu_chan_p_t *chan_p, auto_p_t *auto_p) { //TODO: this function is a duplicate of what is done at the init of the global program : merge it for (int ichan = 0; ichan < chan_p->number_of_channels; ichan++) { int has_lcn; //We copy the good variable to the current channel name depending is this was user set or not if(strlen(auto_p->name_template) && MU_F(chan_p->channels[ichan].name)!=F_USER) { strcpy(chan_p->channels[ichan].name,auto_p->name_template); MU_F(chan_p->channels[ichan].name)=F_DETECTED; } else if(MU_F(chan_p->channels[ichan].name)!=F_USER) { strcpy(chan_p->channels[ichan].name,chan_p->channels[ichan].service_name); MU_F(chan_p->channels[ichan].name)=F_DETECTED; } else strcpy(chan_p->channels[ichan].name,chan_p->channels[ichan].user_name); //No we apply the templates int len=MAX_NAME_LEN; char number[10]; mumu_string_replace(chan_p->channels[ichan].name,&len,0,"%name",chan_p->channels[ichan].service_name); sprintf(number,"%d",ichan+1); mumu_string_replace(chan_p->channels[ichan].name,&len,0,"%number",number); char lcn[4]; //We store if the lcn is in the template if((strstr(chan_p->channels[ichan].name, "%lcn") != NULL) || (strstr(chan_p->channels[ichan].name, "%2lcn") != NULL)) has_lcn=1; else has_lcn=0; if(chan_p->channels[ichan].logical_channel_number) { sprintf(lcn,"%03d",chan_p->channels[ichan].logical_channel_number); mumu_string_replace(chan_p->channels[ichan].name,&len,0,"%lcn",lcn); sprintf(lcn,"%02d",chan_p->channels[ichan].logical_channel_number); mumu_string_replace(chan_p->channels[ichan].name,&len,0,"%2lcn",lcn); } else { mumu_string_replace(chan_p->channels[ichan].name,&len,0,"%lcn",""); mumu_string_replace(chan_p->channels[ichan].name,&len,0,"%2lcn",""); } /************************* * Language template **************************/ int found =0; len=MAX_NAME_LEN; for(int i=0;ichannels[ichan].pid_i.num_pids && !found;i++) { if(chan_p->channels[ichan].pid_i.pids_language[i][0]!='-') { log_message( log_module, MSG_FLOOD, "Primary language for channel: %s",chan_p->channels[ichan].pid_i.pids_language[i]); mumu_string_replace(chan_p->channels[ichan].name,&len,0,"%lang",chan_p->channels[ichan].pid_i.pids_language[i]); found=1; //we exit the loop } } //If we don't find a lang we replace by our "usual" --- if(!found) mumu_string_replace(chan_p->channels[ichan].name,&len,0,"%lang",chan_p->channels[ichan].pid_i.pids_language[0]); /************************* * Language template END **************************/ /************************* * Show the result **************************/ log_message( log_module, MSG_DEBUG, "Channel SID %d service name: \"%s\" user name: \"%s\" channel name: \"%s\"", chan_p->channels[ichan].service_id, chan_p->channels[ichan].service_name, chan_p->channels[ichan].user_name, chan_p->channels[ichan].name); /************************* * SAP update **************************/ chan_p->channels[ichan].sap_need_update=1; //We check if the NIT has been read before sending SAP if(has_lcn && ! auto_p->nit_all_sections_seen) { log_message( log_module, MSG_FLOOD, "Channel name: \"%s\" LCN asked but the NIT has not been seen yet, we delay SAP announces for this channel", chan_p->channels[ichan].name); chan_p->channels[ichan].sap_need_update=0; } else log_message( log_module, MSG_FLOOD, "Channel name: \"%s\" LCN asked and the NIT has been seen, SAP will be sent for this channel", chan_p->channels[ichan].name); } } /******************************************************************** * Autoconfiguration new packet functions ********************************************************************/ /** @brief This function is called when a new packet is there and the autoconf is not finished*/ int autoconf_new_packet(int pid, unsigned char *ts_packet, auto_p_t *auto_p, fds_t *fds, mumu_chan_p_t *chan_p, tune_p_t *tune_p, multi_p_t *multi_p, unicast_parameters_t *unicast_vars, int server_id, void *scam_vars) { if(auto_p->autoconfiguration==AUTOCONF_MODE_FULL) //Full autoconfiguration, we search the channels and their names { if(pid==0) //PAT : contains the services identifiers and the PMT PID for each service { if(auto_p->autoconfiguration==AUTOCONF_MODE_FULL) { //In case of wrong CRC32, at the next call it will go to 0 autoconf_pat_need_update(auto_p,ts_packet); while(auto_p->pat_need_update && get_ts_packet(ts_packet,auto_p->autoconf_temp_pat)) { ts_packet=NULL; // next call we only POP packets from the stack autoconf_read_pat(auto_p,chan_p); } } } else if(pid==17) //SDT : contains the names of the services { if(auto_p->pat_all_sections_seen) { autoconf_sdt_need_update(auto_p,ts_packet); while(auto_p->sdt_need_update && get_ts_packet(ts_packet,auto_p->autoconf_temp_sdt)) { ts_packet=NULL; // next call we only POP packets from the stack autoconf_read_sdt(auto_p,chan_p); } } } else if(pid==PSIP_PID && tune_p->fe_type==FE_ATSC) //PSIP : contains the names of the services { if(auto_p->pat_all_sections_seen) { if(!auto_p->psip_need_update) autoconf_psip_need_update(auto_p,ts_packet); while(auto_p->psip_need_update && get_ts_packet(ts_packet,auto_p->autoconf_temp_psip)) { ts_packet=NULL; // next call we only POP packets from the stack autoconf_read_psip(auto_p,chan_p); } } } else if(pid==16) //NIT : Network Information Table { if(auto_p->pat_all_sections_seen) { if(!auto_p->nit_need_update) autoconf_nit_need_update(auto_p,ts_packet); while(auto_p->nit_need_update && get_ts_packet(ts_packet,auto_p->autoconf_temp_nit)) { ts_packet=NULL; // next call we only POP packets from the stack if(autoconf_read_nit(auto_p, chan_p)) { //We update the names for the %lcn log_message( log_module, MSG_INFO,"We got the NIT, we update the channel names"); autoconf_update_chan_name(chan_p, auto_p); } } } } if(auto_p->need_filter_chan_update) { //We update all aspects of the channels log_message( log_module, MSG_INFO,"We update the channel names"); autoconf_update_chan_name(chan_p, auto_p); log_message( log_module, MSG_INFO,"We update the channel status"); autoconf_update_chan_status(auto_p,chan_p); log_message( log_module, MSG_INFO,"We update the channel filters"); update_chan_filters(chan_p, tune_p->card_dev_path, tune_p->tuner, fds); log_message( log_module, MSG_INFO,"We update the channel networking"); update_chan_net(chan_p, auto_p, multi_p, unicast_vars, server_id, tune_p->card, tune_p->tuner); auto_p->need_filter_chan_update=0; } //PMT PID analysis, only for channels being marked as ready if(auto_p->pat_all_sections_seen) { int ichan; int channel_updated=0; for(ichan=0;ichanchannels[ichan].pid_i.pmt_pid==pid)&& (chan_p->channels[ichan].channel_ready>=READY) && (chan_p->channels[ichan].autoconf_pmt_need_update)) { if(autoconf_read_pmt(&chan_p->channels[ichan], chan_p->channels[ichan].pmt_packet)) { chan_p->channels[ichan].autoconf_pmt_need_update=0; log_pids(log_module,&chan_p->channels[ichan],ichan); autoconf_update_chan_name(chan_p, auto_p); update_chan_filters(chan_p, tune_p->card_dev_path, tune_p->tuner, fds); log_message( log_module, MSG_INFO,"We update the channel CAM support"); chan_update_CAM(chan_p, auto_p, scam_vars); channel_updated=1; } } } if(channel_updated) { //check if all PMT PIDs seen and show channels int channel_left=0; for(ichan=0;ichanchannels[ichan].autoconf_pmt_need_update) channel_left=1; } if(!channel_left) log_streamed_channels(log_module,chan_p->number_of_channels, chan_p->channels, multi_p->multicast_ipv4, multi_p->multicast_ipv6, unicast_vars->unicast, unicast_vars->portOut, unicast_vars->ipOut); } } } //TODO : put PMT information in the pid_i structure of the channel return get_interrupted(); } MuMuDVB-2.1.0/src/autoconf.h000066400000000000000000000112631305714132500155130ustar00rootroot00000000000000/* * MuMuDVB -Stream a DVB transport stream. * * (C) 2008-2010 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /**@file * @brief Autoconfiguration structures */ #ifndef _AUTOCONF_H #define _AUTOCONF_H #include #include "mumudvb.h" #include "unicast_http.h" #include "ts.h" #include "tune.h" /**No autoconfiguration, only send specified PIDs */ #define AUTOCONF_MODE_NONE 0 /**find everything */ #define AUTOCONF_MODE_FULL 2 /**parse the NIT*/ #define AUTOCONF_MODE_NIT 4 //timeout for autoconfiguration #define AUTOCONFIGURE_TIME 10 /**@brief chained list of services for autoconfiguration * */ typedef struct mumudvb_service_t{ /**The channel name*/ char name[MAX_NAME_LEN]; /**The service type : television, radio, data, ...*/ int type; /**The PMT pid of the service*/ int pmt_pid; /**The program ID, also called program number in the PAT or in ATSC*/ int id; /**Tell if this service is scrambled*/ int free_ca_mode; /**The next service in the chained list*/ struct mumudvb_service_t *next; }mumudvb_service_t; /**@brief The different parameters used for autoconfiguration*/ typedef struct auto_p_t{ /**Do we use autoconfiguration ? Possible values for this variable 0 : none AUTOCONF_MODE_FULL : we have only the tuning parameters, we search the channels and their pmt pids*/ int autoconfiguration; /**do we autoconfigure the radios ?*/ int autoconf_radios; /** The template of autoconfigured multicast addresses*/ char autoconf_ip4[80]; char autoconf_ip6[80]; /**When did we started autoconfiguration ?*/ long time_start_autoconfiguration; /**The transport stream id (used to read ATSC PSIP tables and for webservices)*/ int transport_stream_id; /**The network id (used for webservices)*/ int network_id; int original_network_id; /** Do we autoconfigure scrambled channels ? */ int autoconf_scrambled; //Different packets used by autoconfiguration mumudvb_ts_packet_t *autoconf_temp_pat; int pat_need_update; int pat_version; int pat_sections_seen[256]; int pat_all_sections_seen; mumudvb_ts_packet_t *autoconf_temp_sdt; int sdt_need_update; int sdt_version; int sdt_all_sections_seen; int sdt_sections_seen[256]; mumudvb_ts_packet_t *autoconf_temp_nit; int nit_need_update; int nit_version; int nit_all_sections_seen; int nit_sections_seen[256]; /**For ATSC Program and System Information Protocol*/ mumudvb_ts_packet_t *autoconf_temp_psip; int psip_need_update; int psip_version; int psip_all_sections_seen; int psip_sections_seen[256]; //Tell if we added or removed PIDs and we need to update some card filters or file descriptors //We also update the filters and the chan int need_filter_chan_update; /**the http unicast port (string with %card %number, * and + ) */ char autoconf_unicast_port[256]; /**the multicast port (string with %card %number, * and + ) */ char autoconf_multicast_port[256]; /**the list of SID for full autoconfiguration*/ int service_id_list[MAX_CHANNELS]; /**number of SID*/ int num_service_id; /**the list of ignored SID for full autoconfiguration*/ int service_id_list_ignore[MAX_CHANNELS]; /**number of SID*/ int num_service_id_ignore; /** the template for the channel name*/ char name_template[MAX_NAME_LEN]; }auto_p_t; void init_aconf_v(auto_p_t *aconf_p); int autoconf_init(auto_p_t *auto_p); void autoconf_freeing(auto_p_t *); int read_autoconfiguration_configuration(auto_p_t *auto_p, char *substring); int autoconf_new_packet(int pid, unsigned char *ts_packet, auto_p_t *auto_p, fds_t *fds, mumu_chan_p_t *chan_p, tune_p_t *tune_p, multi_p_t *multi_p, unicast_parameters_t *unicast_vars, int server_id, void *scam_vars); int autoconf_poll(long now, auto_p_t *auto_p, mumu_chan_p_t *chan_p, tune_p_t *tune_p, multi_p_t *multi_p, fds_t *fds, unicast_parameters_t *unicast_vars, int server_id, void *scam_vars); void autoconf_pmt_follow( unsigned char *ts_packet, fds_t *fds, mumudvb_channel_t *actual_channel, char *card_base_path, int tuner, mumu_chan_p_t *chan_p ); #endif MuMuDVB-2.1.0/src/autoconf_atsc.c000066400000000000000000000321111305714132500165130ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * File for Autoconfiguration * * (C) 2008-2014 Brice DUBOST * * Parts of this code come from libdvb, modified for mumudvb * by Brice DUBOST * Libdvb part : Copyright (C) 2000 Klaus Schmidinger * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** @file * @brief This file contain the code related to the ATSC tables reading for autoconfiguration * */ #include #include #include #include "errors.h" #include "mumudvb.h" #include "autoconf.h" #include "log.h" #ifdef HAVE_ICONV #include #endif //LIBUCSI for long channel names #ifdef HAVE_LIBUCSI #include #endif int autoconf_parse_vct_channel(unsigned char *buf, auto_p_t *auto_p, mumu_chan_p_t *chan_p); static char *log_module="Autoconf: "; /******************************************************* ATSC ********************************************************/ void autoconf_psip_need_update(auto_p_t *auto_p, unsigned char *buf) { psip_t *psip=(psip_t*)(get_ts_begin(buf)); if(psip) //It's the beginning of a new packet if(psip->version_number!=auto_p->psip_version && !auto_p->psip_all_sections_seen) { /*current_next_indicator – A 1-bit indicator, which when set to '1' indicates that the Program Association Table sent is currently applicable. When the bit is set to '0', it indicates that the table sent is not yet applicable and shall be the next table to become valid.*/ if(psip->current_next_indicator == 0) { return; } log_message( log_module, MSG_DEBUG,"PSIP Need update. stored version : %d, new: %d\n", auto_p->psip_version,psip->version_number); auto_p->psip_need_update=1; } } /** @brief Read a PSIP table to find channels names * * We read the master PSIP pid, search for a (T/C)VCT table * If it find this table, searches for channels within the transport (check * the transport id found in the PAT) and for the extended channel name descriptor * For the moment if the name of the channel is compressed, it will use the short channel * * @param auto_p : the structure containing autoconfiguration parameters */ int autoconf_read_psip(auto_p_t *auto_p, mumu_chan_p_t *chan_p) { //DOC : www.atsc.org/cms/standards/a_65-2009.pdf‎ mumudvb_ts_packet_t *psip_mumu; int number_of_channels_in_section=0; int delta=0; int i=0; unsigned char *buf=NULL; //We get the packet psip_mumu=auto_p->autoconf_temp_psip; buf=psip_mumu->data_full; psip_t *psip=(psip_t*)(buf); //We look only for the following tables OxC8 : TVCT (Terrestrial Virtual Channel Table), 0XC9 : CVCT (Cable Virtual Channel Table) //We check the table id before the section number because the section numbers are for a given table_id //Since we don't have the two table_id in the same stream, we are safe if (psip->table_id != 0xc8 && psip->table_id != 0xc9) return 1; log_message( log_module, MSG_DEBUG,"---- ATSC : PSIP TVCT ot CVCT----\n"); if(auto_p->transport_stream_id<0) { log_message( log_module, MSG_DEBUG,"We don't have a transport id from the PAT, we skip this PSIP\n"); return 1; } log_message( log_module, MSG_DEBUG,"PSIP transport_stream_id : 0x%x PAT TSID 0x%x\n", HILO(psip->transport_stream_id), auto_p->transport_stream_id); if(HILO(psip->transport_stream_id)!=auto_p->transport_stream_id) { log_message( log_module, MSG_DEBUG,"This table belongs to another transponder, we skip\n"); return 1; } if(psip->version_number==auto_p->psip_version) { //check if we saw this section if(auto_p->psip_sections_seen[psip->section_number]) return 0; } else { //New version, no section seen for(int i=0;i<256;i++) auto_p->psip_sections_seen[i]=0; auto_p->psip_version=psip->version_number; auto_p->psip_all_sections_seen=0; if(auto_p->psip_version!=-1) log_message( log_module, MSG_INFO,"The PSIP version changed, channels description have changed"); } //we store the section auto_p->psip_sections_seen[psip->section_number]=1; number_of_channels_in_section=buf[PSIP_HEADER_LEN]; //This field is the byte just after the PSIP header delta=PSIP_HEADER_LEN+1; log_message( log_module, MSG_DEBUG,"VCT : number_of_channels_in_section %d\n", number_of_channels_in_section); //We parse the channels for(i=0;ilast_section_number;i++) if(auto_p->psip_sections_seen[i]==0) sections_missing++; if(sections_missing) { log_message( log_module, MSG_DETAIL,"PSIP %d sections on %d are missing", sections_missing,psip->last_section_number); return 0; } else { auto_p->psip_all_sections_seen=1; auto_p->psip_need_update=0; log_message( log_module, MSG_DEBUG,"It seems that we have finished to update get the channels basic info\n"); auto_p->need_filter_chan_update=1; //We have updated lots of stuff we need to update the filters and channels } return 0; } /** @brief Parse the contents of a (CT)VCT channel descriptor * * This function parse the channel and add it to the services list * * @param buf - The channel descriptor * @param auto_p - The structure containing autoconfiguration parameters */ int autoconf_parse_vct_channel(unsigned char *buf, auto_p_t *auto_p, mumu_chan_p_t *chan_p) { psip_vct_channel_t *vct_channel; char unconverted_short_name[15];//2*7 + 1 (for '\0') #ifdef HAVE_ICONV char *inbuf, *dest; //Pointers for iconv conversion #endif char utf8_short_name[15]; char *channel_name=NULL; char long_name[MAX_NAME_LEN]; int mpeg2_service_type=0; vct_channel=(psip_vct_channel_t *)buf; long_name[0]='\0'; // *********** We get the channel short name ******************* memcpy (unconverted_short_name, vct_channel->short_name, 14*sizeof(uint8_t)); unconverted_short_name[14] = '\0'; #ifdef HAVE_ICONV //Conversion to utf8 of the short name iconv_t cd; //we open the conversion table cd = iconv_open( "UTF8", "UTF-16BE" ); log_message( log_module, MSG_DEBUG,"We use big Endian UTF16 as source for channel name, if it give weird characters please contact\n"); size_t inSize, outSize=14; inSize=14; //pointers initialization dest=utf8_short_name; inbuf=unconverted_short_name; //conversion iconv(cd, &inbuf, &inSize, &dest, &outSize ); *dest = '\0'; iconv_close( cd ); #else log_message( log_module, MSG_DETAIL, "Iconv not present, no name encoding conversion the result will be probably bad\n"); memcpy (utf8_short_name, vct_channel->short_name, 14*sizeof(uint8_t)); utf8_short_name[14] = '\0'; #endif log_message( log_module, MSG_DEBUG, "\tchannel short_name : \"%s\"\n", utf8_short_name); //************ We skip "uninteresting" channels **************** if(vct_channel->modulation_mode==0x01) { log_message( log_module, MSG_DEBUG, "\tAnalog channel, we skip\n"); return PSIP_VCT_LEN + HILO(vct_channel->descriptor_length); //We return the length } if(HILO(vct_channel->channel_tsid)!=auto_p->transport_stream_id) { log_message( log_module, MSG_DEBUG,"Channel for another transponder, we skip : Channel TSID 0x%x , PAT TSID 0x%x\n", HILO(vct_channel->channel_tsid), auto_p->transport_stream_id); return PSIP_VCT_LEN + HILO(vct_channel->descriptor_length); //We return the length } if(vct_channel->hidden) { log_message( log_module, MSG_DEBUG,"This channel is supposed to be hidden, we skip. Please contact if you want to bypass\n"); return PSIP_VCT_LEN + HILO(vct_channel->descriptor_length); //We return the length } //We "convert" ATSC service type to the "equivalent" MPEG2 service type switch(vct_channel->service_type) { case 0x02://ATSC_digital_television — The virtual channel carries television programming (audio, video and //optional associated data) conforming to ATSC standards mpeg2_service_type=0x01; //service_type "digital television service" (0x01) log_message( log_module, MSG_DEBUG,"vct_channel->service_type ATSC_digital_television\n"); break; case 0x03://ATSC_audio — The virtual channel carries audio programming (audio service and optional //associated data) conforming to ATSC standards. mpeg2_service_type=0x02;//service_type digital radio sound service (0x02) log_message( log_module, MSG_DEBUG,"vct_channel->service_type ATSC_audio\n"); break; case 0x04://ATSC_data_only_service — The virtual channel carries a data service conforming to ATSC //standards, but no video of stream_type 0x02 or audio of stream_type 0x81. mpeg2_service_type=0x0c;//service_type data broadcast service log_message( log_module, MSG_DEBUG,"vct_channel->service_type ATSC_data_only_service\n"); break; default: log_message( log_module, MSG_DEBUG,"Unknown vct_channel->service_type 0x%02x\n",vct_channel->service_type); break; } #ifdef HAVE_LIBUCSI //used to decompress the atsc_text_descriptor int descriptor_delta; uint8_t *dest8=NULL; //Pointer for libusci conversion size_t destbufsize=MAX_NAME_LEN; size_t destbufpos=0; int descriptor_len; int atsc_decode_out; int delta_multiple_string_structure; //the beginning of tmultiple string structure //We loop on the different descriptors to find the long channel name for(descriptor_delta=0;descriptor_deltadescriptor_length);) { descriptor_len=buf[PSIP_VCT_LEN+descriptor_delta+1]; if(buf[PSIP_VCT_LEN+descriptor_delta]==0xA0) //Extended channel name descriptor { log_message( log_module, MSG_DEBUG, "Extended channel name descriptor, we try to decode long channel name\n"); dest8=(uint8_t *)long_name; //same type size, just the sign change but we don't care //check delta_multiple_string_structure=PSIP_VCT_LEN+descriptor_delta+2;//+2 to skip descriptor tag and descriptor len if (atsc_text_validate(((uint8_t*)(buf + delta_multiple_string_structure) ), buf[PSIP_VCT_LEN+descriptor_delta+1])) { log_message( log_module, MSG_DEBUG, "Error when VALIDATING long channel name, we take the short one\n"); } else { //If we have multiple strings for the channel name we ask people to report if(buf[delta_multiple_string_structure]!=1 || buf[delta_multiple_string_structure+1+3] !=1) { log_message( log_module, MSG_WARN, "!!!!! Please report : parsing of long name : number strings : %d number segments : %d\n", buf[delta_multiple_string_structure], buf[delta_multiple_string_structure+1+3]); } //Since it's only the channel name, we don't loop over strings and segments //We decode the text using LIBUCSI atsc_decode_out=atsc_text_segment_decode((struct atsc_text_string_segment *) (buf +delta_multiple_string_structure + MULTIPLE_STRING_STRUCTURE_HEADER), &dest8, &destbufsize, &destbufpos); if(atsc_decode_out!=-1) //No errors { dest8[atsc_decode_out]='\0'; //We take the long one log_message( log_module, MSG_DEBUG, "Decoded long channel name : \"%s\"\n",dest8); channel_name=long_name; } else log_message( log_module, MSG_DEBUG, "Error when decoding long channel name, we take the short one\n"); } } //Take the short name if error if(!channel_name) channel_name=utf8_short_name; //Next descriptor descriptor_delta+=descriptor_len+2;//We add the descriptor_len +2 for descriptor tag and descriptor len } #else //We don't use libusci, we don't try to get long channel name channel_name=utf8_short_name; #endif //************** We update a channel if stored channel ***************** //We base the detection of the services on the PAT, the PSIP gives extra information int chan=-1; for(int i=0;inumber_of_channels && i< MAX_CHANNELS;i++) { if(chan_p->channels[i].service_id==HILO(vct_channel->program_number)) chan=i; } if(chan!=-1) { log_message( log_module, MSG_DETAIL, "Updating channel %s, program number : 0x%x \n", channel_name, HILO(vct_channel->program_number)); //we store the data chan_p->channels[chan].service_type=mpeg2_service_type; chan_p->channels[chan].free_ca_mode=vct_channel->access_controlled; log_message( log_module, MSG_DEBUG, "access_controlled : 0x%x\n", chan_p->channels[chan].free_ca_mode); memcpy (chan_p->channels[chan].service_name, channel_name, strlen(channel_name)); chan_p->channels[chan].service_name[strlen(channel_name)] = '\0'; } //**************** Work done for this channel -- goodbye ********************* return PSIP_VCT_LEN + HILO(vct_channel->descriptor_length); //We return the length } MuMuDVB-2.1.0/src/autoconf_nit.c000066400000000000000000000212311305714132500163540ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * File for Autoconfiguration * * (C) 2008-2011 Brice DUBOST * * Parts of this code come from libdvb, modified for mumudvb * by Brice DUBOST * Libdvb part : Copyright (C) 2000 Klaus Schmidinger * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** @file * @brief This file contain the code related to the NIT reading for autoconfiguration * */ #include #include #include #include "errors.h" #include "mumudvb.h" #include "autoconf.h" #include "log.h" static char *log_module="Autoconf: "; void parse_nit_ts_descriptor(unsigned char *buf,int ts_descriptors_loop_len, mumudvb_channel_t *channels, int number_of_channels, int pat_tsid); void parse_lcn_descriptor(unsigned char *buf, mumudvb_channel_t *channels, int number_of_channels); void autoconf_nit_need_update(auto_p_t *auto_p, unsigned char *buf) { nit_t *nit=(nit_t*)(get_ts_begin(buf)); if(nit) //It's the beginning of a new packet if(nit->version_number!=auto_p->nit_version && nit->table_id == 0x40 && !auto_p->nit_all_sections_seen) { /*current_next_indicator – A 1-bit indicator, which when set to '1' indicates that the Program Association Table sent is currently applicable. When the bit is set to '0', it indicates that the table sent is not yet applicable and shall be the next table to become valid.*/ if(nit->current_next_indicator == 0) { return; } log_message( log_module, MSG_DEBUG,"NIT Need update. stored version : %d, new: %d\n",auto_p->nit_version,nit->version_number); auto_p->nit_need_update=1; } } /** @brief Read the network information table (cf EN 300 468) * */ int autoconf_read_nit(auto_p_t *auto_p, mumu_chan_p_t *chan_p) { mumudvb_ts_packet_t *nit_mumu; unsigned char *buf=NULL; log_message( log_module, MSG_FLOOD,"New NIT\n"); //We get the packet nit_mumu=auto_p->autoconf_temp_nit; buf=nit_mumu->data_full; nit_t *header=(nit_t*)(buf); //We look only for the following table Ox40 : network_information_section - actual_network if (header->table_id != 0x40) { log_message( log_module, MSG_FLOOD,"NIT : Bad table %d\n", header->table_id); return 1; } if(header->version_number==auto_p->nit_version) { //check if we saw this section if(auto_p->nit_sections_seen[header->section_number]) { log_message( log_module, MSG_FLOOD,"NIT section %d seen", header->section_number ); return 0; } } else { //New version, no section seen for(int i=0;i<256;i++) auto_p->nit_sections_seen[i]=0; auto_p->nit_version=header->version_number; auto_p->nit_all_sections_seen=0; if(auto_p->nit_version!=-1) log_message( log_module, MSG_INFO,"The NIT version changed, channels number could have changed !"); } //we store the section auto_p->nit_sections_seen[header->section_number]=1; /*current_next_indicator – A 1-bit indicator, which when set to '1' indicates that the Program Association Table sent is currently applicable. When the bit is set to '0', it indicates that the table sent is not yet applicable and shall be the next table to become valid.*/ if(header->current_next_indicator == 0) { log_message( log_module, MSG_FLOOD,"NIT not yet valid, we get a new one (current_next_indicator == 0)\n"); return 1; } log_message( log_module, MSG_FLOOD, "-- NIT : Network Information Table --\n"); log_message( log_module, MSG_FLOOD, "Network id 0x%02x see \"http://www.dvbservices.com/identifiers/export/network_id\"\n", HILO(header->network_id)); //We store the network ID auto_p->network_id=HILO(header->network_id); int network_descriptors_length = HILO(header->network_descriptor_length); //Loop over different descriptors in the NIT buf+=NIT_LEN; //We read the descriptors ts_display_nit_network_descriptors(log_module, buf,network_descriptors_length); buf += network_descriptors_length; nit_mid_t *middle=(nit_mid_t *)buf; int ts_loop_length=HILO(middle->transport_stream_loop_length); buf +=SIZE_NIT_MID; parse_nit_ts_descriptor(buf,ts_loop_length, chan_p->channels, chan_p->number_of_channels, auto_p->transport_stream_id); int sections_missing=0; //We check if we saw all sections for(int i=0;i<=header->last_section_number;i++) if(auto_p->nit_sections_seen[i]==0) sections_missing++; if(sections_missing) { log_message( log_module, MSG_DETAIL,"NIT %d sections on %d are missing", sections_missing,header->last_section_number); return 0; } else { auto_p->nit_all_sections_seen=1; auto_p->nit_need_update=0; log_message( log_module, MSG_DEBUG,"It seems that we have finished to get the logical channel number"); return 1; } return 0; } void parse_nit_ts_descriptor(unsigned char* buf, int ts_descriptors_loop_len, mumudvb_channel_t* channels, int number_of_channels, int pat_tsid) { int descriptors_loop_len; nit_ts_t *descr_header; int ts_id,orig_network_id; while (ts_descriptors_loop_len > 0) { descr_header=(nit_ts_t *)(buf); descriptors_loop_len=HILO(descr_header->transport_descriptors_length); log_message( log_module, MSG_FLOOD, " --- NIT ts_descriptors_loop_len %d descriptors_loop_len %d\n", ts_descriptors_loop_len, descriptors_loop_len); orig_network_id=HILO(descr_header->original_network_id); log_message( log_module, MSG_FLOOD, " --- NIT descriptor concerning the network id 0x%04x\n", orig_network_id); ts_id=HILO(descr_header->transport_stream_id); log_message( log_module, MSG_FLOOD, " --- NIT descriptor concerning the multiplex 0x%04x our multiplex 0x%04x\n", ts_id, pat_tsid); if(ts_id != pat_tsid) log_message( log_module, MSG_FLOOD, " --- Other multiplex, we skip"); buf +=NIT_TS_LEN; ts_descriptors_loop_len -= (descriptors_loop_len+NIT_TS_LEN); while (descriptors_loop_len > 0) { unsigned char descriptor_tag = buf[0]; unsigned char descriptor_len = buf[1] + 2; if (!descriptor_len) { log_message( log_module, MSG_FLOOD, " --- NIT descriptor --- descriptor_tag == 0x%02x, len is 0\n", descriptor_tag); break; } //We parse only descriptors with the right transport_stream_id if(pat_tsid==ts_id) { if(descriptor_tag==0x83) { ts_display_lcn_descriptor(log_module, buf); parse_lcn_descriptor(buf, channels, number_of_channels); } else if(descriptor_tag==0x41) ts_display_service_list_descriptor(log_module, buf); else if(descriptor_tag==0x43) ts_display_satellite_delivery_system_descriptor(log_module, buf); else if(descriptor_tag==0x5A) ts_display_terrestrial_delivery_system_descriptor(log_module, buf); else if(descriptor_tag==0x62) ts_display_frequency_list_descriptor(log_module, buf); else log_message( log_module, MSG_FLOOD, " --- NIT TS descriptor --- descriptor_tag == 0x%02x len %d descriptors_loop_len %d ------------\n", descriptor_tag, descriptor_len, descriptors_loop_len); } buf += descriptor_len; descriptors_loop_len -= descriptor_len; } } } /** @brief Parse the lcn descriptor * It's used to get the logical channel number * @param buf the buffer containing the descriptor */ void parse_lcn_descriptor(unsigned char* buf, mumudvb_channel_t* channels, int number_of_channels) { /* Service descriptor : descriptor_tag 8 descriptor_length 8 for (i=0;i 0) { lcn=(nit_lcn_t *)buf; buf+=NIT_LCN_LEN; service_id= HILO(lcn->service_id); i_lcn=HILO(lcn->logical_channel_number); for(curr_channel=0;curr_channel * * Parts of this code come from libdvb, modified for mumudvb * by Brice DUBOST * Libdvb part : Copyright (C) 2000 Klaus Schmidinger * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** @file * @brief This file contain the code related to the PAT reading for autoconfiguration * */ #include #include #include #include "errors.h" #include "mumudvb.h" #include "autoconf.h" #include "log.h" static char *log_module="Autoconf: "; int autoconf_pat_update_chan(pat_prog_t *prog,int pat_version,mumu_chan_p_t *chan_p); void autoconf_pat_need_update(auto_p_t *auto_p, unsigned char *buf) { pat_t *pat=(pat_t*)(get_ts_begin(buf)); if(pat) //It's the beginning of a new packet { if(pat->version_number!=auto_p->pat_version) { /*current_next_indicator – A 1-bit indicator, which when set to '1' indicates that the Program Association Table sent is currently applicable. When the bit is set to '0', it indicates that the table sent is not yet applicable and shall be the next table to become valid.*/ if(pat->current_next_indicator == 0) { return; } log_message( log_module, MSG_DEBUG,"PAT Need update. stored version : %d, new: %d\n",auto_p->pat_version,pat->version_number); auto_p->pat_need_update=1; } else if(auto_p->pat_all_sections_seen && auto_p->pat_need_update==1) //We can have a wrong need update if the packet was broken (the CRC32 is checked only if we think it's good) { log_message( log_module, MSG_DEBUG,"PAT Not needing update anymore (wrong CRC ?)"); auto_p->pat_need_update=0; } } } /** @brief read the PAT for autoconfiguration * This function extract the pmt from the pat * before doing so it checks if the service is already initialised (sdt packet) * * @param auto_p The autoconfiguration structure, containing all we need */ int autoconf_read_pat(auto_p_t *auto_p,mumu_chan_p_t *chan_p) { mumudvb_ts_packet_t *pat_mumu; unsigned char *buf=NULL; pat_mumu=auto_p->autoconf_temp_pat; buf=pat_mumu->data_full; pat_t *pat=(pat_t*)(buf); pat_prog_t *prog; int delta=PAT_LEN; int section_length=0; int i; if(pat->version_number==auto_p->pat_version) { //check if we saw this section if(auto_p->pat_sections_seen[pat->section_number]) return 0; } else { //New PAT version so we didn't got all PAT auto_p->pat_all_sections_seen=0; //We also force a re read of the SDT auto_p->sdt_version=-1; //New version, no section seen for(i=0;i<256;i++) auto_p->pat_sections_seen[i]=0; auto_p->pat_version=pat->version_number; if(auto_p->pat_version!=-1) { log_message( log_module, MSG_INFO,"The PAT version changed, channels have changed"); } log_message( log_module, MSG_INFO,"New PAT we force SDT update after all sections seen"); //We mark previously existing autodetected channels for cleanup after all PAT parsing //this flag will be set to READY if we see the channel again in this new PAT, otherwise it means the channel went down //See the end of this function for more details for(i=0;inumber_of_channels && i< MAX_CHANNELS;i++) { if(chan_p->channels[i].channel_ready==READY && MU_F(chan_p->channels[i].service_id)==F_DETECTED) { chan_p->channels[i].channel_ready=READY_EXISTING; log_message( log_module, MSG_DEBUG,"Channel %d SID %d autodetected before this new PAT, we mark it", i, chan_p->channels[i].service_id); } } } //we store the section auto_p->pat_sections_seen[pat->section_number]=1; log_message( log_module, MSG_DEBUG,"---- New PAT version %d section %d ----\n",pat->version_number, pat->section_number); //we display the contents ts_display_pat(log_module,buf); //PAT reading section_length=HILO(pat->section_length); /*current_next_indicator – A 1-bit indicator, which when set to '1' indicates that the Program Association Table sent is currently applicable. When the bit is set to '0', it indicates that the table sent is not yet applicable and shall be the next table to become valid.*/ if(pat->current_next_indicator == 0) { log_message( log_module, MSG_DEBUG,"The current_next_indicator is set to 0, this PAT is not valid for the current stream\n"); return 0; } //We store the transport stream ID auto_p->transport_stream_id=HILO(pat->transport_stream_id); //We loop over the different programs included in the pat while((delta+PAT_PROG_LEN)<(section_length)) { prog=(pat_prog_t*)((char*)buf+delta); if(HILO(prog->program_number)!=0) { //We check if we have to update a channel if(autoconf_pat_update_chan(prog,pat->version_number,chan_p)) { log_message( log_module, MSG_DETAIL,"channel updated ID 0x%d", HILO(prog->program_number)); } } delta+=PAT_PROG_LEN; } int sections_missing=0; //We check if we saw all sections for(i=0;i<=pat->last_section_number;i++) if(auto_p->pat_sections_seen[i]==0) sections_missing++; if(sections_missing) { log_message( log_module, MSG_DETAIL,"PAT %d sections on %d are missing", sections_missing,pat->last_section_number); return 0; } else { auto_p->pat_all_sections_seen=1; auto_p->pat_need_update=0; log_message( log_module, MSG_DEBUG,"It seems that we have finished to get the channel/services list"); //We say we have seen all PAT to update SDT //we see the channel which were READY_EXISTING and which are not READY meaning that they were not updated for(i=0;inumber_of_channels && i< MAX_CHANNELS;i++) { if(chan_p->channels[i].channel_ready==READY_EXISTING) { log_message( log_module, MSG_WARN,"Channel %d SID %d removed", i, chan_p->channels[i].service_id); chan_p->channels[i].channel_ready=REMOVED; //we don't clean everything up so if this is a blinking channel client will still be able to got it when it reappears } else { //Channel still here, we force PMT update log_message( log_module, MSG_WARN,"Channel %d SID %d Force PMT update", i, chan_p->channels[i].service_id); chan_p->channels[i].pmt_version=-1; } } if(auto_p->sdt_version!=-1) { //We force to re read the SDT as we updated the PAT log_message( log_module, MSG_DEBUG,"We force the SDT update as the PAT was updated"); auto_p->sdt_version=-1; } } return 0; } int autoconf_pat_update_chan(pat_prog_t *prog,int pat_version,mumu_chan_p_t *chan_p) { int i; int chan_num=-1; //we search if a channel already have the service_id for(i=0;inumber_of_channels && i< MAX_CHANNELS;i++) { if(chan_p->channels[i].service_id==HILO(prog->program_number)) { log_message( log_module, MSG_DEBUG,"Channel %d SID %d existing : %s", i, chan_p->channels[i].service_id, ready_f_to_str(chan_p->channels[i].channel_ready)); chan_num=i; } } //if chan num == -1 we create a new channel and update channel number if(chan_num==-1) { if(chan_p->number_of_channels>=(MAX_CHANNELS-1)) { //too many channels log_message( log_module, MSG_WARN,"PAT version %d program %d TOO MANY channel %d", pat_version, HILO(prog->program_number), chan_p->number_of_channels+1); return 0; } log_message( log_module, MSG_FLOOD,"PAT version %d program %d NEW channel %d", pat_version, HILO(prog->program_number), chan_p->number_of_channels+1); //increase number of channels chan_num=chan_p->number_of_channels; chan_p->number_of_channels++; //set the service ID chan_p->channels[chan_num].service_id=HILO(prog->program_number); MU_F(chan_p->channels[chan_num].service_id)=F_DETECTED; //NEW channel we clear some stuff mumu_init_chan(&chan_p->channels[i]); chan_p->channels[i].channel_ready=NOT_READY; } i=chan_num; //if it was an existing channel we keep it up if(chan_p->channels[i].channel_ready==READY_EXISTING) { chan_p->channels[i].channel_ready=READY; log_message( log_module, MSG_DEBUG,"Channel %d SID %d is still here we mark it as being still READY", i, chan_p->channels[i].service_id); } else if(chan_p->channels[i].channel_ready==REMOVED) { chan_p->channels[i].channel_ready=NOT_READY; log_message( log_module, MSG_DEBUG,"Channel %d SID %d is BACK", i, chan_p->channels[i].service_id); mumu_init_chan(&chan_p->channels[i]); } //check if PMT PID user set, if not set the PMT if(MU_F(chan_p->channels[i].pid_i.pmt_pid)!=F_USER) { int pid_i=-1; //Set the PMT PID chan_p->channels[i].pid_i.pmt_pid=HILO(prog->network_pid); //if old PMT in the PID list we replace for (int ipid = 0; ipid < chan_p->channels[i].pid_i.num_pids; ipid++) { if(chan_p->channels[i].pid_i.pids[ipid]==chan_p->channels[i].pid_i.pmt_pid) pid_i=ipid; } //not found, we add a new PID if(pid_i==-1) { pid_i=chan_p->channels[i].pid_i.num_pids; chan_p->channels[i].pid_i.num_pids++; } chan_p->channels[i].pid_i.pids[pid_i]=chan_p->channels[i].pid_i.pmt_pid; chan_p->channels[i].pid_i.pids_type[pid_i]=PID_PMT; snprintf(chan_p->channels[i].pid_i.pids_language[pid_i],4,"%s","---"); if(chan_p->channels[i].pmt_packet==NULL) { chan_p->channels[i].pmt_packet=malloc(sizeof(mumudvb_ts_packet_t)); if(chan_p->channels[i].pmt_packet==NULL) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); set_interrupted(ERROR_MEMORY<<8); return -1; } memset (chan_p->channels[i].pmt_packet, 0, sizeof( mumudvb_ts_packet_t));//we clear it pthread_mutex_init(&chan_p->channels[i].pmt_packet->packetmutex,NULL); } } else log_message( log_module, MSG_DEBUG,"PAT version %d program %d channel %d PMT user set to %d", pat_version, HILO(prog->program_number), i, chan_p->channels[i].pid_i.pmt_pid); //reset PMT version to force channel update chan_p->channels[chan_num].pmt_version=-1; return 0; } MuMuDVB-2.1.0/src/autoconf_pmt.c000066400000000000000000000432261305714132500163720ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * File for Autoconfiguration * * (C) 2008-2013 Brice DUBOST * * Parts of this code come from libdvb, modified for mumudvb * by Brice DUBOST * Libdvb part : Copyright (C) 2000 Klaus Schmidinger * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** @file * @brief This file contain the code related to the PMT reading for autoconfiguration * */ static char *log_module="Autoconf: "; #include #include #include "errors.h" #include "mumudvb.h" #include "autoconf.h" #include "log.h" #include "dvb.h" int pmt_find_descriptor(uint8_t tag, unsigned char *buf, int descriptors_loop_len, int *pos); void pmt_print_descriptor_tags(unsigned char *buf, int descriptors_loop_len); /****************************************************************************/ //Parts of this code (read of the pmt and read of the pat) // from libdvb, strongly modified, with commentaries added /****************************************************************************/ void autoconf_get_pmt_pids(mumudvb_ts_packet_t *pmt, int *pids, int *num_pids, int *pids_type, char (*pids_language)[4], int *ca_sys_id) { *num_pids=0; char temp_pids_language[MAX_PIDS][4]; memset(temp_pids_language,0,MAX_PIDS*4*sizeof(char)); pmt_t *header; pmt_info_t *descr_header; int program_info_length; int section_len,descr_section_len; int pid; int pid_type=0; section_len=pmt->len_full; header=(pmt_t *)pmt->data_full; program_info_length=HILO(header->program_info_length); //program_info_length char language[4]=""; int pos=0; //For CAM debugging purposes, we look if we can find a CA descriptor to display CA system IDs //Also find ECM pid... while(pmt_find_descriptor(0x09,pmt->data_full+PMT_LEN,PMT_LEN+program_info_length,&pos)) { descr_ca_t *ca_descriptor; ca_descriptor=(descr_ca_t *)(pmt->data_full+PMT_LEN+pos); pid=HILO(ca_descriptor->CA_PID); pid_type=PID_ECM; log_message( log_module, MSG_DEBUG," ECM \tPID %d\n",pid); pids[*num_pids]=pid; pids_type[*num_pids]=pid_type; snprintf(temp_pids_language[*num_pids],4,"%s",language); (*num_pids)++; int casysid = 0; while(casysid<32 && ca_sys_id[casysid] && ca_sys_id[casysid]!=HILO(ca_descriptor->CA_type) ) casysid++; if(casysid<32 && !ca_sys_id[casysid]) { ca_sys_id[casysid]=HILO(ca_descriptor->CA_type); log_message( log_module, MSG_DETAIL,"CA system id 0x%04x : %s\n", HILO(ca_descriptor->CA_type), ca_sys_id_to_str(HILO(ca_descriptor->CA_type)));//we display it with the description } if(casysid==32) log_message( log_module, MSG_WARN,"Too much CA system id line %d file %s\n", __LINE__,__FILE__); pos+=ca_descriptor->descriptor_length+2; } pos=0; //we read the different descriptors included in the pmt //for more information see ITU-T Rec. H.222.0 | ISO/IEC 13818 table 2-34 for (int i=program_info_length+PMT_LEN; i<=section_len-(PMT_INFO_LEN+4); i+=descr_section_len+PMT_INFO_LEN) { //we parse the part after the descriptors //we map the descriptor header descr_header=(pmt_info_t *)(pmt->data_full+i); //We get the length of the descriptor descr_section_len=HILO(descr_header->ES_info_length); //ES_info_length // Default language value if not found snprintf(language,4,"%s","---"); // Default, no position found pos=0; pid=HILO(descr_header->elementary_PID); //Depending of the stream type we'll take or not this pid switch(descr_header->stream_type) { case 0x01: pid_type=PID_VIDEO_MPEG1; log_message( log_module, MSG_DEBUG," Video MPEG1 \tPID %d\n",pid); break; case 0x02: pid_type=PID_VIDEO_MPEG2; log_message( log_module, MSG_DEBUG," Video MPEG2 \tPID %d\n",pid); break; case 0x10: /* ISO/IEC 14496-2 Visual - MPEG4 video */ pid_type=PID_VIDEO_MPEG4_ASP; log_message( log_module, MSG_DEBUG," Video MPEG4-ASP \tPID %d\n",pid); break; case 0x1b: /* AVC video stream as defined in ITU-T Rec. H.264 | ISO/IEC 14496-10 Video */ pid_type=PID_VIDEO_MPEG4_AVC; log_message( log_module, MSG_DEBUG," Video MPEG4-AVC \tPID %d\n",pid); break; case 0x24: /*HEVC video stream TODO: enter quote*/ pid_type=PID_VIDEO_MPEG4_HEVC; log_message( log_module, MSG_DEBUG," Video MPEG4-HVC \tPID %d\n",pid); break; case 0x03: pid_type=PID_AUDIO_MPEG1; log_message( log_module, MSG_DEBUG," Audio MPEG1 \tPID %d\n",pid); break; case 0x04: pid_type=PID_AUDIO_MPEG2; log_message( log_module, MSG_DEBUG," Audio MPEG2 \tPID %d\n",pid); break; case 0x11: /* ISO/IEC 14496-3 Audio with the LATM transport syntax as defined in ISO/IEC 14496-3 */ pid_type=PID_AUDIO_AAC_LATM; log_message( log_module, MSG_DEBUG," Audio AAC-LATM \tPID %d\n",pid); break; case 0x0f: /* ISO/IEC 13818-7 Audio with ADTS transport syntax - usually AAC */ pid_type=PID_AUDIO_AAC_ADTS; log_message( log_module, MSG_DEBUG," Audio AAC-ADTS \tPID %d\n",pid); break; case 0x81: /* Audio per ATSC A/53B [2] Annex B */ pid_type=PID_AUDIO_ATSC; log_message( log_module, MSG_DEBUG," Audio ATSC A/53B \tPID %d\n",pid); break; case 0x06: /* Descriptor defined in EN 300 468 */ if(descr_section_len) //If we have an accociated descriptor, we'll search inforation in it { if(pmt_find_descriptor(0x45,pmt->data_full+i+PMT_INFO_LEN,descr_section_len, NULL)){ log_message( log_module, MSG_DEBUG," VBI Data \tPID %d\n",pid); pid_type=PID_EXTRA_VBIDATA; }else if(pmt_find_descriptor(0x46,pmt->data_full+i+PMT_INFO_LEN,descr_section_len, NULL)){ log_message( log_module, MSG_DEBUG," VBI Teletext \tPID %d\n",pid); pid_type=PID_EXTRA_VBITELETEXT; }else if(pmt_find_descriptor(0x56,pmt->data_full+i+PMT_INFO_LEN,descr_section_len, NULL)){ log_message( log_module, MSG_DEBUG," Teletext \tPID %d\n",pid); pid_type=PID_EXTRA_TELETEXT; }else if(pmt_find_descriptor(0x59,pmt->data_full+i+PMT_INFO_LEN,descr_section_len, &pos)){ log_message( log_module, MSG_DEBUG," Subtitling \tPID %d\n",pid); pid_type=PID_EXTRA_SUBTITLE; char * lng=(char *)(pmt->data_full+i+PMT_INFO_LEN+pos+2); language[0]=lng[0]; language[1]=lng[1]; language[2]=lng[2]; language[3]=0; }else if(pmt_find_descriptor(0x6a,pmt->data_full+i+PMT_INFO_LEN,descr_section_len, NULL)){ log_message( log_module, MSG_DEBUG," AC3 (audio) \tPID %d\n",pid); pid_type=PID_AUDIO_AC3; }else if(pmt_find_descriptor(0x7a,pmt->data_full+i+PMT_INFO_LEN,descr_section_len, NULL)){ log_message( log_module, MSG_DEBUG," Enhanced AC3 (audio) \tPID %d\n",pid); pid_type=PID_AUDIO_EAC3; }else if(pmt_find_descriptor(0x7b,pmt->data_full+i+PMT_INFO_LEN,descr_section_len, NULL)){ log_message( log_module, MSG_DEBUG," DTS (audio) \tPID %d\n",pid); pid_type=PID_AUDIO_DTS; }else if(pmt_find_descriptor(0x7c,pmt->data_full+i+PMT_INFO_LEN,descr_section_len, NULL)){ log_message( log_module, MSG_DEBUG," AAC (audio) \tPID %d\n",pid); pid_type=PID_AUDIO_AAC; }else { log_message( log_module, MSG_DEBUG,"Unknown descriptor see EN 300 468 v1.9.1 table 12, PID %d descriptor tags : ", pid); pmt_print_descriptor_tags(pmt->data_full+i+PMT_INFO_LEN,descr_section_len); log_message( log_module, MSG_DEBUG,"\n"); continue; } } else { log_message( log_module, MSG_DEBUG,"PMT read : stream type 0x06 without descriptor\n"); continue; } break; //Now, the list of what we drop case 0x05: log_message( log_module, MSG_DEBUG, "Dropped PID %d, type : 0x05, ITU-T Rec. H.222.0 | ISO/IEC 13818-1 private_sections \n",pid); continue; //Digital Storage Medium Command and Control (DSM-CC) cf H.222.0 | ISO/IEC 13818-1 annex B case 0x0a: log_message( log_module, MSG_DEBUG, "Dropped PID %d, type : 0x0A ISO/IEC 13818-6 type A (DSM-CC)\n",pid); continue; case 0x0b: log_message( log_module, MSG_DEBUG, "Dropped PID %d, type : 0x0B ISO/IEC 13818-6 type B (DSM-CC)\n",pid); continue; case 0x0c: log_message( log_module, MSG_DEBUG, "Dropped PID %d, type : 0x0C ISO/IEC 13818-6 type C (DSM-CC)\n",pid); continue; case 0x0D: log_message( log_module, MSG_DEBUG, "Dropped PID %d, type : ISO/IEC 13818-6 type D",pid); continue; case 0x0E: log_message( log_module, MSG_DEBUG, "Dropped PID %d, type : ITU-T Rec. H.222.0 | ISO/IEC 13818-1 auxiliary",pid); continue; case 0x12: log_message( log_module, MSG_DEBUG, "Dropped PID %d, type : ISO/IEC 14496-1 SL-packetized stream or FlexMux stream carried in PES packets",pid); continue; case 0x13: log_message( log_module, MSG_DEBUG, "Dropped PID %d, type : ISO/IEC 14496-1 SL-packetized stream or FlexMux stream carried in ISO/IEC 14496_sections",pid); continue; case 0x14: log_message( log_module, MSG_DEBUG, "Dropped PID %d, type : ISO/IEC 13818-6 Synchronized Download Protocol",pid); continue; case 0x15: log_message( log_module, MSG_DEBUG, "Dropped PID %d, type : Metadata carried in PES packets",pid); continue; case 0x16: log_message( log_module, MSG_DEBUG, "Dropped PID %d, type : Metadata carried in metadata_sections",pid); continue; case 0x17: log_message( log_module, MSG_DEBUG, "Dropped PID %d, type : Metadata carried in ISO/IEC 13818-6 Data Carousel",pid); continue; case 0x18: log_message( log_module, MSG_DEBUG, "Dropped PID %d, type : Metadata carried in ISO/IEC 13818-6 Object Carousel",pid); continue; case 0x19: log_message( log_module, MSG_DEBUG, "Dropped PID %d, type : Metadata carried in ISO/IEC 13818-6 Synchronized Download Protocol",pid); continue; case 0x1A: log_message( log_module, MSG_DEBUG, "Dropped PID %d, type : IPMP stream (defined in ISO/IEC 13818-11, MPEG-2 IPMP)",pid); continue; case 0x7F: log_message( log_module, MSG_DEBUG, "Dropped PID %d, type : IPMP stream",pid); continue; default: if(descr_header->stream_type >= 0x1C && descr_header->stream_type <= 0x7E) log_message( log_module, MSG_DEBUG, "Dropped PID %d, stream type : 0x%02x : ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Reserved",pid,descr_header->stream_type); else if(descr_header->stream_type >= 0x80) log_message( log_module, MSG_DEBUG, "Dropped PID %d, stream type : 0x%02x : User Private",pid,descr_header->stream_type); else log_message( log_module, MSG_INFO, "!!!!Unknown stream type : 0x%02x, PID : %d cf ITU-T Rec. H.222.0 | ISO/IEC 13818\n",descr_header->stream_type,pid); continue; } //We keep this pid // We try to find a 0x0a (ISO639) descriptor to have language information about the stream pos=0; if(pmt_find_descriptor(0x0a,pmt->data_full+i+PMT_INFO_LEN,descr_section_len, &pos)){ char * lng=(char *)(pmt->data_full+i+PMT_INFO_LEN+pos+2); language[0]=lng[0]; language[1]=lng[1]; language[2]=lng[2]; language[3]=0; } log_message( log_module, MSG_DEBUG," PID Language Code = %s\n",language); pids[*num_pids]=pid; pids_type[*num_pids]=pid_type; snprintf(temp_pids_language[*num_pids],4,"%s",language); (*num_pids)++; if (*num_pids >= MAX_PIDS) { log_message( log_module, MSG_ERROR, "Too many PIDs : %d\n", *num_pids); (*num_pids)--; } } memcpy(pids_language,temp_pids_language,MAX_PIDS*4*sizeof(char)); } /** @brief Reads the program map table * * It's used to get the different "useful" pids of the channel * @param pmt the pmt packet * @param channel the associated channel */ int autoconf_read_pmt(mumudvb_channel_t *channel, mumudvb_ts_packet_t *pmt) { pmt_t *header; header=(pmt_t *)pmt->data_full; if(channel->service_id && (channel->service_id != HILO(header->program_number)) ) { log_message( log_module, MSG_DETAIL,"The PMT %d does not belongs to channel \"%s\"\n", pmt->pid, channel->name); return 0; } log_message( log_module, MSG_DEBUG,"PMT (PID %d) read for configuration of channel \"%s\" with SID %d", pmt->pid, channel->name,channel->service_id); #ifdef ENABLE_CAM_SUPPORT // Reset of the CA SYS saved for the channel for (int i=0; i<32; i++) channel->ca_sys_id[i]=0; #endif int temp_pids[MAX_PIDS]; int temp_pids_type[MAX_PIDS]; char temp_pids_language[MAX_PIDS][4]; //For channel update int temp_num_pids=0; temp_pids[0]=pmt->pid; temp_num_pids++; //We get the PIDs contained in the PMT autoconf_get_pmt_pids(pmt, temp_pids, &temp_num_pids, temp_pids_type, temp_pids_language, channel->ca_sys_id); /************************** * PCR PID **************************/ channel->pid_i.pcr_pid=HILO(header->PCR_PID); //The PCR pid. //we check if it's not already included (ie the pcr is carried with the video) int found=0; for(int i=0;ipid_i.num_pids;i++) { if(temp_pids[i]==channel->pid_i.pcr_pid) found=1; } if(!found) { temp_pids[temp_num_pids]=channel->pid_i.pcr_pid; temp_pids_type[temp_num_pids]=PID_PCR; snprintf(temp_pids_language[temp_num_pids],4,"%s","---"); temp_num_pids++; } log_message( log_module, MSG_DEBUG, "PCR pid %d\n",channel->pid_i.pcr_pid); /************************** * PCR PID - END **************************/ log_message( log_module, MSG_DEBUG,"Detected PIDs"); for(int curr_pid=0;curr_pidpid_i.num_pids); if(channel->pid_i.pid_f!=F_USER) { log_message( log_module, MSG_DETAIL, "PIDs update"); //We display it just for information the filter update is done elsewhere //We search for added PIDs for(int i=0,found=0;ipid_i.num_pids;j++) if(channel->pid_i.pids[j]==temp_pids[i]) found=1; if(!found) log_message( log_module, MSG_DETAIL, "PID %d added type %s lang %s", temp_pids[i], pid_type_to_str(temp_pids_type[i]), temp_pids_language[i]); } //We search for suppressed pids for(int i=0,found=0;ipid_i.num_pids;i++) { for(int j=0;jpid_i.pids[i]==temp_pids[j] || channel->pid_i.pids[i] == channel->pid_i.pmt_pid ) found=1; if(!found) log_message( log_module, MSG_DETAIL, "PID %d removed type %s lang %s", channel->pid_i.pids[i], pid_type_to_str(channel->pid_i.pids_type[i]), channel->pid_i.pids_language[i]); } for(int i=0;ipid_i.pids[i+1]=temp_pids[i]; channel->pid_i.pids_type[i+1]=temp_pids_type[i]; snprintf(channel->pid_i.pids_language[i+1],4,"%s",temp_pids_language[i]); } channel->pid_i.num_pids=temp_num_pids+1; log_message( log_module, MSG_DETAIL, " pids : \n");/**@todo Generate a strind and call log_message after, in syslog it generates one line per pid : use the toolbox unicast*/ int ipid; for (ipid = 0; ipid < channel->pid_i.num_pids; ipid++) log_message( log_module, MSG_DETAIL, " %d (%s) \n", channel->pid_i.pids[ipid], pid_type_to_str(channel->pid_i.pids_type[ipid])); } else log_message( log_module, MSG_DETAIL, "PIDs user set we keep intact"); /************************** * Channel update END **************************/ //Never more than one section in the PMT log_message( log_module, MSG_DEBUG,"It seems that we have finished to get the Program Map Table"); log_message( log_module, MSG_DEBUG,"Number of PIDs after autoconf %d\n", channel->pid_i.num_pids); return 1; } /** @brief Tells if the descriptor with tag in present in buf * * for more information see ITU-T Rec. H.222.0 | ISO/IEC 13818 * * @param tag the descriptor tag, cf EN 300 468 * @param buf the decriptors buffer (part of the PMT) * @param descriptors_loop_len the length of the descriptors * @param pos the position in the buffer */ int pmt_find_descriptor(uint8_t tag, unsigned char *buf, int descriptors_loop_len, int *pos) { if(pos!=NULL) { buf+=*pos; descriptors_loop_len -= *pos; } while (descriptors_loop_len > 0) { unsigned char descriptor_tag = buf[0]; unsigned char descriptor_len = buf[1] + 2; if (tag == descriptor_tag) return 1; if(pos!=NULL) *pos += descriptor_len; buf += descriptor_len; descriptors_loop_len -= descriptor_len; } return 0; } /** @brief Debugging function, Print the tags present in the descriptor * * for more information see ITU-T Rec. H.222.0 | ISO/IEC 13818 * @param buf the decriptors buffer (part of the PMT) * @param descriptors_loop_len the length of the descriptors */ void pmt_print_descriptor_tags(unsigned char *buf, int descriptors_loop_len) { while (descriptors_loop_len > 0) { unsigned char descriptor_tag = buf[0]; unsigned char descriptor_len = buf[1] + 2; log_message( log_module, MSG_DEBUG,"0x%02x - \n", descriptor_tag); buf += descriptor_len; descriptors_loop_len -= descriptor_len; } } MuMuDVB-2.1.0/src/autoconf_sdt.c000066400000000000000000000237171305714132500163670ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * File for Autoconfiguration * * (C) 2008-2010 Brice DUBOST * * Parts of this code come from libdvb, modified for mumudvb * by Brice DUBOST * Libdvb part : Copyright (C) 2000 Klaus Schmidinger * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** @file * @brief This file contain the code related to the SDT reading for autoconfiguration * */ #include #include #include #include "errors.h" #include "mumudvb.h" #include "autoconf.h" #include "log.h" static char *log_module="Autoconf: "; void parse_service_descriptor(unsigned char *buf, mumudvb_channel_t *chan); extern char *encodings_en300468[]; void parse_sdt_descriptor(unsigned char *buf,int descriptors_loop_len, mumudvb_channel_t *chan); void autoconf_sdt_need_update(auto_p_t *auto_p, unsigned char *buf) { sdt_t *sdt=(sdt_t*)(get_ts_begin(buf)); if(sdt) //It's the beginning of a new packet { if((sdt->version_number!=auto_p->sdt_version) && (sdt->table_id==0x42)) { /*current_next_indicator – A 1-bit indicator, which when set to '1' indicates that the Program Association Table sent is currently applicable. When the bit is set to '0', it indicates that the table sent is not yet applicable and shall be the next table to become valid.*/ if(sdt->current_next_indicator == 0) { return; } log_message( log_module, MSG_DEBUG,"SDT Need update. stored version : %d, new: %d\n",auto_p->sdt_version,sdt->version_number); auto_p->sdt_need_update=1; } else if(auto_p->sdt_all_sections_seen && auto_p->sdt_need_update==1) //We can have a wrong need update if the packet was broken (the CRC32 is checked only if we think it's good) { log_message( log_module, MSG_DEBUG,"SDT Not needing update anymore (wrong CRC ?)"); auto_p->sdt_need_update=0; } } } /** @brief Read the service description table (cf EN 300 468) * * This table is used to find the name of the services versus the service number * This function will fill the names and other info in the services */ int autoconf_read_sdt(auto_p_t *auto_p, mumu_chan_p_t *chan_p) { int delta; sdt_t *header; sdt_descr_t *descr_header; int chan; mumudvb_ts_packet_t *sdt_mumu; unsigned char *buf=NULL; sdt_mumu=auto_p->autoconf_temp_sdt; buf=sdt_mumu->data_full; int len; len=sdt_mumu->len_full; header=(sdt_t *)buf; //we map the packet over the header structure if(header->version_number==auto_p->sdt_version) { //check if we saw this section if(auto_p->sdt_sections_seen[header->section_number]) return 0; } else { //New version, no section seen for(int i=0;i<256;i++) auto_p->sdt_sections_seen[i]=0; auto_p->sdt_version=header->version_number; auto_p->sdt_all_sections_seen=0; if(auto_p->sdt_version!=-1) log_message( log_module, MSG_INFO,"The SDT version changed, channels description have changed"); } //we store the section auto_p->sdt_sections_seen[header->section_number]=1; //We look only for the following table //0x42 service_description_section - actual_transport_stream if(header->table_id==0x42) { log_message( log_module, MSG_DEBUG, "-- SDT : Service Description Table (id 0x%02x)--\n",header->table_id); log_message( log_module, MSG_FLOOD, "-- SDT: TSID 0x%04x original_network_id 0x%04x version %d section number %d last section number %d --\n", HILO(header->transport_stream_id), HILO(header->original_network_id), header->version_number, header->section_number, header->last_section_number); //We store the original network ID // http://www.dvbservices.com/identifiers/export/original_network_id auto_p->original_network_id=HILO(header->original_network_id); //Loop over different services in the SDT delta=SDT_LEN; while((len-delta)>=(4+SDT_DESCR_LEN)) { descr_header=(sdt_descr_t *)(buf +delta ); //we search if we already a channel with this have service id //We base the detection of the services on the PAT, the SDT gives extra information chan=-1; for(int i=0;inumber_of_channels && i< MAX_CHANNELS;i++) { if(chan_p->channels[i].service_id==HILO(descr_header->service_id)) chan=i; } if(chan!=-1) { log_message( log_module, MSG_DEBUG, "We will update service with id : 0x%x %d", HILO(descr_header->service_id), HILO(descr_header->service_id)); //For information only switch(descr_header->running_status) { case 0: log_message( log_module, MSG_DEBUG, "\trunning_status : undefined\n"); break; case 1: log_message( log_module, MSG_DEBUG, "\trunning_status : not running\n"); break; case 2: log_message( log_module, MSG_DEBUG, "\trunning_status : starts in a few seconds\n"); break; case 3: log_message( log_module, MSG_DEBUG, "\trunning_status : pausing\n"); break; case 4: log_message( log_module, MSG_FLOOD, "\trunning_status : running\n"); break; //too usual to be printed as debug case 5: log_message( log_module, MSG_DEBUG, "\trunning_status : service off-air\n"); break; } //we store the Free CA mode flag (tell if the channel is scrambled) chan_p->channels[chan].free_ca_mode=descr_header->free_ca_mode; log_message( log_module, MSG_DEBUG, "\tfree_ca_mode : 0x%x\n", descr_header->free_ca_mode); //We read the descriptor parse_sdt_descriptor(buf+delta+SDT_DESCR_LEN,HILO(descr_header->descriptors_loop_length),&chan_p->channels[chan]); } delta+=HILO(descr_header->descriptors_loop_length)+SDT_DESCR_LEN; } } else log_message( log_module, MSG_FLOOD, "-- SDT : bad table id 0x%02x--\n",header->table_id); int sections_missing=0; //We check if we saw all sections for(int i=0;i<=header->last_section_number;i++) if(auto_p->sdt_sections_seen[i]==0) sections_missing++; if(sections_missing) { log_message( log_module, MSG_DETAIL,"SDT %d sections on %d are missing", sections_missing,header->last_section_number); return 0; } else { auto_p->sdt_all_sections_seen=1; auto_p->sdt_need_update=0; log_message( log_module, MSG_DEBUG,"It seems that we have finished to update get the channels basic info\n"); auto_p->need_filter_chan_update=1; //We have updated lots of stuff we need to update the filters and channels } return 0; } /** @brief Parse the SDT descriptors * Loop over the sdt descriptors and call other parsing functions if necessary * @param buf the buffer containing the descriptors * @param descriptors_loop_len the len of buffer containing the descriptors * @param service the associated service */ void parse_sdt_descriptor(unsigned char *buf,int descriptors_loop_len, mumudvb_channel_t *chan) { while (descriptors_loop_len > 0) { unsigned char descriptor_tag = buf[0]; unsigned char descriptor_len = buf[1] + 2; if (!descriptor_len) { log_message( log_module, MSG_DEBUG, "--- SDT descriptor --- descriptor_tag == 0x%02x, len is 0\n", descriptor_tag); break; } //The service descriptor provides the names of the service provider and the service in text form together with the service_type. if(descriptor_tag==0x48) parse_service_descriptor(buf,chan); else if( descriptor_tag==0x53) //53 : CA identifier descriptor. This descriptor contains the CA_systems_id (the scrambling algorithms) show_CA_identifier_descriptor(buf); else if( descriptor_tag==0x49) //0x49 : Country availability descriptor. ts_display_country_avaibility_descriptor(log_module,buf); else /** @todo : Add descriptor 0x50 Component descriptor (multilingual 0x5E) and descriptor 0x5D multilingual_service_name_descriptor*/ log_message( log_module, MSG_FLOOD, "SDT descriptor_tag : 0x%2x, descriptor_len %d\n", descriptor_tag, descriptor_len); buf += descriptor_len; descriptors_loop_len -= descriptor_len; } } /** @brief Parse the service descriptor * It's used to get the channel name * @param buf the buffer containing the descriptor * @param service the associated service */ void parse_service_descriptor(unsigned char *buf, mumudvb_channel_t *chan) { /* Service descriptor : descriptor_tag 8 descriptor_length 8 service_type 8 service_provider_name_length 8 for (i=0;iservice_type=*buf; //We show the service type display_service_type(*buf, MSG_DEBUG,log_module); buf ++; //we skip the service_type len = *buf; //provider name len //we jump the provider_name + the provider_name_len buf += len + 1; //Channel name len len = *buf; buf++; //we jump the channel_name_len //We store the channel name with the raw encoding memcpy (chan->service_name, buf, len); chan->service_name[len] = '\0'; encoding_control_char=convert_en300468_string(chan->service_name,MAX_NAME_LEN,1); if(encoding_control_char==-1) return; if(MU_F(chan->name)!=F_USER) log_message( log_module, MSG_DEBUG, "Channel SID %d name will be updated",chan->service_id); else log_message( log_module, MSG_DEBUG, "Channel SID %d name user set, we keep",chan->service_id); log_message( log_module, MSG_DEBUG, "Channel SID %d name : \"%s\" (name encoding : %s)\n", chan->service_id, chan->service_name, encodings_en300468[encoding_control_char]); } MuMuDVB-2.1.0/src/cam.c000066400000000000000000001146741305714132500144420ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * File for Conditionnal Access Modules support * * (C) 2004-2011 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Code inspired by libdvben50221 examples from dvb apps * Copyright (C) 2004, 2005 Manu Abraham * Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net) * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include /* DVB Card Drivers */ #include #include #include /**@file * @brief cam support * * Code for talking with conditionnal access modules. This code uses the libdvben50221 from dvb-apps */ #include #include "errors.h" #include "cam.h" #include "ts.h" #include "mumudvb.h" #include "log.h" static char *log_module="CAM: "; int check_pmt_service_id(mumudvb_ts_packet_t *pmt, mumudvb_channel_t *channel); // in ts.c /***************************************************************************** * Code for dealing with cam using libdvben50221 *****************************************************************************/ static void *camthread_func(void* arg); //The polling thread static int mumudvb_cam_ai_callback(void *arg, uint8_t slot_id, uint16_t session_number, uint8_t application_type, uint16_t application_manufacturer, uint16_t manufacturer_code, uint8_t menu_string_length, uint8_t *menu_string); //The application information callback static int mumudvb_cam_ca_info_callback(void *arg, uint8_t slot_id, uint16_t session_number, uint32_t ca_id_count, uint16_t *ca_ids); static int mumudvb_cam_app_ca_pmt_reply_callback(void *arg, uint8_t slot_id, uint16_t session_number, struct en50221_app_pmt_reply *reply, uint32_t reply_size); static int mumudvb_cam_mmi_menu_callback(void *arg, uint8_t slot_id, uint16_t session_number, struct en50221_app_mmi_text *title, struct en50221_app_mmi_text *sub_title, struct en50221_app_mmi_text *bottom, uint32_t item_count, struct en50221_app_mmi_text *items, uint32_t item_raw_length, uint8_t *items_raw); static int mumudvb_cam_mmi_list_callback(void *arg, uint8_t slot_id, uint16_t session_number, struct en50221_app_mmi_text *title, struct en50221_app_mmi_text *sub_title, struct en50221_app_mmi_text *bottom, uint32_t item_count, struct en50221_app_mmi_text *items, uint32_t item_raw_length, uint8_t *items_raw); static int mumudvb_cam_mmi_menu_list_callback(void *arg, uint8_t slot_id, uint16_t session_number, struct en50221_app_mmi_text *title, struct en50221_app_mmi_text *sub_title, struct en50221_app_mmi_text *bottom, uint32_t item_count, struct en50221_app_mmi_text *items, uint32_t item_raw_length, uint8_t *items_raw, int object_type); static int mumudvb_cam_mmi_close_callback(void *arg, uint8_t slot_id, uint16_t session_number, uint8_t cmd_id, uint8_t delay); static int mumudvb_cam_mmi_display_control_callback(void *arg, uint8_t slot_id, uint16_t session_number, uint8_t cmd_id, uint8_t mmi_mode); static int mumudvb_cam_mmi_enq_callback(void *arg, uint8_t slot_id, uint16_t session_number, uint8_t blind_answer, uint8_t expected_answer_length, uint8_t *text, uint32_t text_size); static char *cam_status[] ={ "EN50221_STDCAM_CAM_NONE", "EN50221_STDCAM_CAM_INRESET", "EN50221_STDCAM_CAM_OK", "EN50221_STDCAM_CAM_BAD" }; /** Initialize CAM variables*/ void init_cam_v(cam_p_t *cam_p) { *cam_p=(cam_p_t){ .cam_support = 0, .cam_number=0, .cam_reask_interval=0, .need_reset=0, .reset_counts=0, .reset_interval=CAM_DEFAULT_RESET_INTERVAL, .timeout_no_cam_init=CAM_DEFAULT_RESET_INTERVAL, .max_reset_number=CAM_DEFAULT_MAX_RESET_NUM, .tl=NULL, .sl=NULL, .stdcam=NULL, .ca_resource_connected=0, .mmi_state = MMI_STATE_CLOSED, .ca_info_ok_time=0, .cam_delay_pmt_send=0, .cam_interval_pmt_send=3, .cam_pmt_send_time=0, .cam_mmi_autoresponse=1, .cam_pmt_follow=1, .cam_menulist_str = EMPTY_STRING, .cam_menu_string = EMPTY_STRING, }; mumu_string_append(&cam_p->cam_menu_string,"Not retrieved"); } /** @brief Read a line of the configuration file to check if there is a cam parameter * */ int read_cam_configuration(cam_p_t *cam_p, mumudvb_channel_t *c_chan, char *substring) { char delimiteurs[] = CONFIG_FILE_SEPARATOR; if (!strcmp (substring, "cam_support")) { substring = strtok (NULL, delimiteurs); cam_p->cam_support = atoi (substring); if(cam_p->cam_support) { log_message( log_module, MSG_INFO, "You have enabled the support for conditional access modules (scrambled channels)."); } } else if (!strcmp (substring, "cam_reask_interval")) { substring = strtok (NULL, delimiteurs); cam_p->cam_reask_interval = atoi (substring); } else if (!strcmp (substring, "cam_reset_interval")) { substring = strtok (NULL, delimiteurs); cam_p->reset_interval = atoi (substring); cam_p->timeout_no_cam_init = cam_p->reset_interval; } else if (!strcmp (substring, "cam_number")) { substring = strtok (NULL, delimiteurs); cam_p->cam_number = atoi (substring); } else if (!strcmp (substring, "cam_delay_pmt_send")) { substring = strtok (NULL, delimiteurs); cam_p->cam_delay_pmt_send = atoi (substring); } else if (!strcmp (substring, "cam_interval_pmt_send")) { substring = strtok (NULL, delimiteurs); cam_p->cam_interval_pmt_send = atoi (substring); } else if (!strcmp (substring, "cam_pmt_follow")) { substring = strtok (NULL, delimiteurs); cam_p->cam_pmt_follow = atoi (substring); } else if (!strcmp (substring, "cam_ask")) { if ( c_chan == NULL) { log_message( log_module, MSG_ERROR, "cam_ask : You have to start a channel first (using new_channel)\n"); return -1; } c_chan->need_cam_ask=CAM_NEED_ASK; MU_F(c_chan->need_cam_ask)=F_USER; } else if (!strcmp (substring, "cam_no_ask")) { if ( c_chan == NULL) { log_message( log_module, MSG_ERROR, "cam_no_ask : You have to start a channel first (using new_channel)\n"); return -1; } c_chan->need_cam_ask=CAM_NO_ASK; MU_F(c_chan->need_cam_ask)=F_USER; } else return 0; //Nothing concerning cam, we return 0 to explore the other possibilities return 1;//We found something for cam, we tell main to go for the next line } struct en50221_stdcam_llci { struct en50221_stdcam stdcam; int cafd; int slotnum; int state; }; /** @brief Reset the CAM */ void cam_reset_cam(cam_p_t *cam_p) { log_message( log_module, MSG_DEBUG,"CAM Reset\n"); struct en50221_stdcam *stdcam=cam_p->stdcam; struct en50221_stdcam_llci *llci = (struct en50221_stdcam_llci *) stdcam; if(ioctl(llci->cafd, CA_RESET, (1 << llci->slotnum))<0) { log_message( log_module, MSG_WARN, "Reset IOCTL failed : %s", strerror (errno)); return; } //This variable only exist for low level CAMs so we check the type if(cam_p->cam_type==DVBCA_INTERFACE_LINK) llci->state = EN50221_STDCAM_CAM_NONE; } /** @brief Get the CAM state */ int cam_debug_dvbca_get_cam_state(cam_p_t *cam_p) { struct en50221_stdcam *stdcam=cam_p->stdcam; struct en50221_stdcam_llci *llci = (struct en50221_stdcam_llci *) stdcam; ca_slot_info_t info; info.num = llci->slotnum; if (ioctl(llci->cafd, CA_GET_SLOT_INFO, &info)) return -1; if (info.flags == 0) return DVBCA_CAMSTATE_MISSING; if (info.flags & CA_CI_MODULE_READY) return DVBCA_CAMSTATE_READY; if (info.flags & CA_CI_MODULE_PRESENT) return DVBCA_CAMSTATE_INITIALISING; return -1; } /** @brief Get the CAM interface type */ int cam_debug_dvbca_get_interface_type(cam_p_t *cam_p) { struct en50221_stdcam *stdcam=cam_p->stdcam; struct en50221_stdcam_llci *llci = (struct en50221_stdcam_llci *) stdcam; ca_slot_info_t info; info.num = llci->slotnum; if (ioctl(llci->cafd, CA_GET_SLOT_INFO, &info)) return -1; if (info.type & CA_CI_LINK) return DVBCA_INTERFACE_LINK; if (info.type & CA_CI) return DVBCA_INTERFACE_HLCI; return -1; } typedef struct camthread_params_t{ cam_p_t *cam_p; mumu_chan_p_t *chan_p; }camthread_params_t; /** @brief start the cam * This function will create the communication layers and set the callbacks*/ int cam_start(cam_p_t *cam_p, int adapter_id,mumu_chan_p_t *chan_p) { // CAM Log log_message( log_module, MSG_DEBUG,"CAM Initialization\n"); log_message( log_module, MSG_DEBUG,"CONF cam_reask_interval=%d\n",cam_p->cam_reask_interval); log_message( log_module, MSG_DEBUG,"CONF cam_reset_interval=%d\n",cam_p->reset_interval); log_message( log_module, MSG_DEBUG,"CONF cam_number=%d\n",cam_p->cam_number); log_message( log_module, MSG_DEBUG,"CONF cam_delay_pmt_send=%d\n",cam_p->cam_delay_pmt_send); log_message( log_module, MSG_DEBUG,"CONF cam_interval_pmt_send=%d\n",cam_p->cam_interval_pmt_send); // create transport layer - 1 Slot and 16 sessions maximum cam_p->tl = en50221_tl_create(1, 16); if (cam_p->tl == NULL) { log_message( log_module, MSG_ERROR,"Failed to create transport layer\n"); return 1; } // create session layer cam_p->sl = en50221_sl_create(cam_p->tl, SL_MAX_SESSIONS); if (cam_p->sl == NULL) { log_message( log_module, MSG_ERROR, "Failed to create session layer\n"); en50221_tl_destroy(cam_p->tl); return 1; } // create the stdcam instance cam_p->stdcam = en50221_stdcam_create(adapter_id, cam_p->cam_number, cam_p->tl, cam_p->sl); if (cam_p->stdcam == NULL) { log_message( log_module, MSG_ERROR, "Failed to create the stdcam instance (no cam present ?)\n"); en50221_sl_destroy(cam_p->sl); en50221_tl_destroy(cam_p->tl); return 1; } // hook up the AI callbacks if (cam_p->stdcam->ai_resource) { en50221_app_ai_register_callback(cam_p->stdcam->ai_resource, mumudvb_cam_ai_callback, cam_p); } else { log_message( log_module, MSG_WARN, "No Application Information resource\n"); } // hook up the CA callbacks if (cam_p->stdcam->ca_resource) { en50221_app_ca_register_info_callback(cam_p->stdcam->ca_resource, mumudvb_cam_ca_info_callback, cam_p); en50221_app_ca_register_pmt_reply_callback(cam_p->stdcam->ca_resource, mumudvb_cam_app_ca_pmt_reply_callback, cam_p); } else { log_message( log_module, MSG_WARN, "No CA resource\n"); } // hook up the MMI callbacks if (cam_p->stdcam->mmi_resource) { en50221_app_mmi_register_close_callback(cam_p->stdcam->mmi_resource, mumudvb_cam_mmi_close_callback, cam_p); en50221_app_mmi_register_display_control_callback(cam_p->stdcam->mmi_resource, mumudvb_cam_mmi_display_control_callback, cam_p); en50221_app_mmi_register_enq_callback(cam_p->stdcam->mmi_resource, mumudvb_cam_mmi_enq_callback, cam_p); en50221_app_mmi_register_menu_callback(cam_p->stdcam->mmi_resource, mumudvb_cam_mmi_menu_callback, cam_p); en50221_app_mmi_register_list_callback(cam_p->stdcam->mmi_resource, mumudvb_cam_mmi_list_callback, cam_p); } else { log_message( log_module, MSG_WARN, "CAM Menus are not supported by this interface hardware\n"); } // any other stuff cam_p->moveca = 1; //see http://www.linuxtv.org/pipermail/linux-dvb/2007-May/018198.html cam_p->cam_type = cam_debug_dvbca_get_interface_type(cam_p); //The reset procedure have only been tested on LLCI cams switch(cam_p->cam_type) { case DVBCA_INTERFACE_LINK: log_message( log_module, MSG_DETAIL, "CAM type : low level interface\n"); break; case DVBCA_INTERFACE_HLCI: log_message( log_module, MSG_DETAIL, "CAM type : HIGH level interface\n"); break; } // start the cam thread camthread_params_t *camthread_params=malloc(sizeof(camthread_params_t)); camthread_params->cam_p=cam_p; camthread_params->chan_p=chan_p; pthread_create(&(cam_p->camthread), NULL, camthread_func, camthread_params); return 0; } /** @brief Stops the CAM*/ void cam_stop(cam_p_t *cam_p) { log_message( log_module, MSG_DEBUG, "CAM Stopping\n"); if (cam_p->stdcam == NULL) return; // shutdown the cam thread cam_p->camthread_shutdown = 1; pthread_join(cam_p->camthread, NULL); // destroy the stdcam if (cam_p->stdcam->destroy) cam_p->stdcam->destroy(cam_p->stdcam, 1); // destroy session layer en50221_sl_destroy(cam_p->sl); // destroy transport layer en50221_tl_destroy(cam_p->tl); } /** @brief The thread for polling the cam */ static void *camthread_func(void* arg) { camthread_params_t *camthread_params; camthread_params= (camthread_params_t *) arg; cam_p_t *cam_p; mumu_chan_p_t *chan_p; cam_p=camthread_params->cam_p; chan_p=camthread_params->chan_p; int i; int camstate; struct timeval tv; long real_start_time; long now; long last_channel_check; //We record the starting time gettimeofday (&tv, (struct timezone *) NULL); real_start_time = tv.tv_sec; now = 0; last_channel_check=0; log_message( log_module, MSG_DEBUG,"CAM Thread started\n"); // Variables for detecting changes of status and error int status_old=0; int status_new=0; int error_old=0; int error_new=0; //Loop while(!cam_p->camthread_shutdown) { usleep(100*1000); //some waiting - 100ms (see specs) gettimeofday (&tv, (struct timezone *) NULL); now = tv.tv_sec - real_start_time; //If the CAM is initialized (ie we received the CA_info) we check if the "safety" delay is over //This behavior is made for some "crazy" CAMs like powercam v4 which doesn't accept the PMT just after the ca_info_callback if(cam_p->ca_info_ok_time && cam_p->ca_resource_connected==0) if((tv.tv_sec - cam_p->ca_info_ok_time) > cam_p->cam_delay_pmt_send) cam_p->ca_resource_connected=1; /* Check for fully scrambled channels for a while, to re ask the CAM */ if(cam_p->ca_resource_connected && (cam_p->cam_reask_interval>0)) { //We don't check too often for the new asking of the highly scrambled channels if((now-last_channel_check)>2) { last_channel_check=now; for (int curr_channel = 0; curr_channel < chan_p->number_of_channels; curr_channel++) { // Check if new asking (ie sending a CAM PMT UPDATE) is needed. IE channel highly/partially scrambled or down and asked a while ago if((chan_p->channels[curr_channel].scrambled_channel == HIGHLY_SCRAMBLED || chan_p->channels[curr_channel].scrambled_channel == PARTIALLY_UNSCRAMBLED || chan_p->channels[curr_channel].has_traffic == 0)&& (chan_p->channels[curr_channel].need_cam_ask==CAM_ASKED)&& (chan_p->channels[curr_channel].channel_ready>=READY)&& ((tv.tv_sec-chan_p->channels[curr_channel].cam_asking_time)>cam_p->cam_reask_interval)) { chan_p->channels[curr_channel].need_cam_ask=CAM_NEED_UPDATE; //TODO : lock log_message( log_module, MSG_DETAIL, "Channel \"%s\" highly scrambled for more than %ds. We ask the CAM to update.\n", chan_p->channels[curr_channel].name,cam_p->cam_reask_interval); chan_p->channels[curr_channel].cam_asking_time=tv.tv_sec; } } } } // Polling CAM and checking status change - List of possible status: (en50221_stdcam.h) // 0: EN50221_STDCAM_CAM_NONE // 1: EN50221_STDCAM_CAM_INRESET // 2: EN50221_STDCAM_CAM_OK // 3: EN50221_STDCAM_CAM_BAD status_new=cam_p->stdcam->poll(cam_p->stdcam); if (status_new!=status_old) { if(status_new>3) log_message( log_module, MSG_WARN, "The CAM changed to an unknown status : %d, please contact\n",status_new); else if (status_old >3) log_message( log_module, MSG_DEBUG, "Status change from UNKNOWN (%d) to %s.\n",status_old,cam_status[status_new]); else log_message( log_module, MSG_DEBUG, "Status change from %s to %s.\n",cam_status[status_old],cam_status[status_new]); status_old=status_new; } // Try to get the Transport Layer structure from libdvben50221 if (cam_p->tl!=NULL) { // Get the last error code error_new=en50221_tl_get_error(cam_p->tl); } // Check if error code has changed - List of error codes: (en50221_errno.h) if (error_new!=error_old) { log_message( log_module, MSG_WARN, "Transport Layer Error change from %s (%s) to %s (%s)\n", liben50221_error_to_str(error_old),liben50221_error_to_str_descr(error_old), liben50221_error_to_str(error_new),liben50221_error_to_str_descr(error_new)); error_old=error_new; if(cam_p->ca_resource_connected) { // This is probably a CAM crash, as after initialization, a Transport Layer error isn't good... log_message( log_module, MSG_ERROR,"Transport Layer error after CAM initialization: CAM may have crash, it's better to exit and restart...\n"); set_interrupted(ERROR_CAM<<8); //the <<8 is to make difference beetween signals and errors } } //check if we need reset if ( cam_p->ca_info_ok_time==0 && cam_p->timeout_no_cam_init>0 && now>cam_p->timeout_no_cam_init && cam_p->reset_interval>0) { if(cam_p->cam_type==DVBCA_INTERFACE_LINK) { if(cam_p->need_reset==0 && cam_p->reset_countsmax_reset_number) { log_message( log_module, MSG_INFO, "No CAM initialization in %ds, WE FORCE A RESET. try %d on %d.\n", cam_p->timeout_no_cam_init, cam_p->reset_counts+1, cam_p->max_reset_number); cam_p->need_reset=1; cam_p->timeout_no_cam_init=now+cam_p->reset_interval; } else if (cam_p->reset_counts>=cam_p->max_reset_number) { log_message( log_module, MSG_INFO, "No CAM initialization in %ds, the %d resets didn't worked. Exiting.\n", cam_p->timeout_no_cam_init,cam_p->max_reset_number); set_interrupted(ERROR_NO_CAM_INIT<<8); //the <<8 is to make difference beetween signals and errors } } else { log_message( log_module, MSG_INFO, "No CAM initialization on in %ds and HLCI CAM, exiting.\n", cam_p->timeout_no_cam_init); set_interrupted(ERROR_NO_CAM_INIT<<8); //the <<8 is to make difference beetween signals and errors } } //We do the reset if needed if(cam_p->need_reset==1) { cam_reset_cam(cam_p); i=0; log_message( log_module, MSG_DEBUG, "We wait for the cam to be INITIALISING\n"); do { camstate=cam_debug_dvbca_get_cam_state(cam_p); switch(camstate) { case DVBCA_CAMSTATE_MISSING: log_message( log_module, MSG_DEBUG, "cam state : DVBCA_CAMSTATE_MISSING\n"); break; case DVBCA_CAMSTATE_READY: log_message( log_module, MSG_DEBUG, "cam state : DVBCA_CAMSTATE_READY\n"); break; case DVBCA_CAMSTATE_INITIALISING: log_message( log_module, MSG_DEBUG, "cam state : DVBCA_CAMSTATE_INITIALISING\n"); break; case -1: log_message( log_module, MSG_DEBUG, "cam state : Eroor during the query\n"); break; } usleep(10000); i++; } while(camstate!=DVBCA_CAMSTATE_INITIALISING && i < MAX_WAIT_AFTER_RESET); if(i==MAX_WAIT_AFTER_RESET) log_message( log_module, MSG_INFO, "The CAM isn't in a good state after reset, it will probably don't work :(\n"); else log_message( log_module, MSG_DEBUG, "state correct after reset\n"); cam_p->need_reset=0; cam_p->reset_counts++; } } // As we can't get the state of the session, // we try to close all of them with some polling to force communication log_message( log_module, MSG_DEBUG,"Closing the CAM sessions\n"); for (i=0;isl,i); usleep(50*1000); cam_p->stdcam->poll(cam_p->stdcam); usleep(50*1000); cam_p->stdcam->poll(cam_p->stdcam); } log_message( log_module, MSG_DEBUG,"CAM Thread stopped\n"); free(camthread_params); return 0; } /** @brief PMT sending to the cam * This function if called when mumudvb receive a new PMT pid. * This function will ask the cam to decrypt the associated channel */ int mumudvb_cam_new_pmt(cam_p_t *cam_p, mumudvb_ts_packet_t *cam_pmt_ptr, int need_cam_ask) { uint8_t capmt[MAX_TS_SIZE]; int size,list_managment; // parse section struct section *section = section_codec(cam_pmt_ptr->data_full,cam_pmt_ptr->len_full); if (section == NULL) { log_message( log_module, MSG_WARN,"section_codec parsing error\n"); return -1; } // parse section_ext struct section_ext *section_ext = section_ext_decode(section, 0); if (section_ext == NULL) { log_message( log_module, MSG_WARN,"section_ext parsing error\n"); return -1; } // parse PMT struct mpeg_pmt_section *pmt = mpeg_pmt_section_codec(section_ext); if (pmt == NULL) { log_message( log_module, MSG_WARN,"mpeg_pmt_section_codec parsing error\n"); return -1; } if(pmt->head.table_id!=0x02) { log_message( log_module, MSG_WARN,"Packet PID %d is not a PMT PID\n", cam_pmt_ptr->pid); return -1; } if (cam_p->stdcam == NULL) return -1; if (cam_p->ca_resource_connected) { log_message( log_module, MSG_INFO, "Received new PMT - sending to CAM...\n"); // translate it into a CA PMT // Concerning the list managment the simplest (since we don't want to remove channels is to do a CA_LIST_MANAGEMENT_ADD //Always. Doing FIRST, MORE ,MORE ... LAST is more complicated because the CAM will wait for the LAST // If the an update is needed the Aston cams will be happy with a ADD (it detects that the channel is already present and updates //It seems that the power cam don't really follow the norm (ie accept almost everything) // Doing also only update should work //an update should be equivalent to an add when the channel is not present //Note : The powercam HD V3.1 doesn't add channels with update, so we only do updates when the channel was added if(need_cam_ask==CAM_NEED_UPDATE) list_managment=CA_LIST_MANAGEMENT_UPDATE; else list_managment=CA_LIST_MANAGEMENT_ADD; if ((size = en50221_ca_format_pmt(pmt, capmt, sizeof(capmt), cam_p->moveca, list_managment, CA_PMT_CMD_ID_OK_DESCRAMBLING)) < 0) { /*CA_PMT_CMD_ID_QUERY)) < 0) { We don't do query, the query is never working very well. This is because the CAM cannot ask the card if you have the rights for the channel. So this answer is often not reliable. Much thanks to Aston www.aston-france.com for the explanation */ log_message( log_module, MSG_WARN, "Failed to format PMT\n"); return -1; } // set it if (en50221_app_ca_pmt(cam_p->stdcam->ca_resource, cam_p->stdcam->ca_session_number, capmt, size)) { log_message( log_module, MSG_WARN, "Failed to send PMT\n"); return -1; } // we've seen this PMT return 1; } return 0; } static int mumudvb_cam_ai_callback(void *arg, uint8_t slot_id, uint16_t session_number, uint8_t application_type, uint16_t application_manufacturer, uint16_t manufacturer_code, uint8_t menu_string_length, uint8_t *menu_string) { cam_p_t *cam_p; cam_p= (cam_p_t *) arg; (void) slot_id; (void) session_number; // Write information to log log_message( log_module, MSG_DEBUG, "CAM Application_Info_Callback\n"); log_message( log_module, MSG_INFO, "CAM Application type: %02x\n", application_type); log_message( log_module, MSG_INFO, "CAM Application manufacturer: %04x\n", application_manufacturer); log_message( log_module, MSG_INFO, "CAM Manufacturer code: %04x\n", manufacturer_code); log_message( log_module, MSG_INFO, "CAM Menu string: %.*s\n", menu_string_length, menu_string); // Store the CAM menu string for easy identification mumu_free_string(&cam_p->cam_menu_string); mumu_string_append(&cam_p->cam_menu_string, "%.*s", menu_string_length, menu_string); // Try to append the information to the cam_info log file FILE *file_cam_info; file_cam_info = fopen (cam_p->filename_cam_info, "a"); if (file_cam_info == NULL) { log_message( log_module, MSG_WARN, "%s: %s\n", cam_p->filename_cam_info, strerror (errno)); } else { fprintf (file_cam_info,"CAM_Application_Type=%02x\n",application_type); fprintf (file_cam_info,"CAM_Application_Manufacturer=%04x\n",application_manufacturer); fprintf (file_cam_info,"CAM_Manufacturer_Code=%04x\n",manufacturer_code); fprintf (file_cam_info,"CAM_Menu_String=%.*s\n",menu_string_length, menu_string); fclose (file_cam_info); } return 0; } static int mumudvb_cam_ca_info_callback(void *arg, uint8_t slot_id, uint16_t session_number, uint32_t ca_id_count, uint16_t *ca_ids) { cam_p_t *cam_p; cam_p= (cam_p_t *) arg; (void) slot_id; (void) session_number; struct timeval tv; // Write information to log log_message( log_module, MSG_DEBUG,"CA_Info_Callback: %d CA systems supported\n",ca_id_count); log_message( log_module, MSG_DETAIL, "CAM supports the following ca system ids:\n"); uint32_t i; for(i=0; i< ca_id_count; i++) { log_message( log_module, MSG_DETAIL,"Ca system id 0x%04x : %s\n",ca_ids[i], ca_sys_id_to_str(ca_ids[i])); //we display it with the description } // Try to append the information to the cam_info log file FILE *file_cam_info; file_cam_info = fopen (cam_p->filename_cam_info, "a"); if (file_cam_info == NULL) { log_message( log_module, MSG_WARN, "%s: %s\n", cam_p->filename_cam_info, strerror (errno)); } else { for(i=0; i< ca_id_count; i++) fprintf (file_cam_info,"ID_CA_Supported=%04x\n",ca_ids[i]); fclose (file_cam_info); } gettimeofday (&tv, (struct timezone *) NULL); cam_p->ca_info_ok_time=tv.tv_sec; return 0; } static int mumudvb_cam_app_ca_pmt_reply_callback(void *arg, uint8_t slot_id, uint16_t session_number, struct en50221_app_pmt_reply *reply, uint32_t reply_size) { struct en50221_app_pmt_stream *pos; (void) arg; (void) slot_id; (void) session_number; log_message( log_module, MSG_INFO, "CAM PMT reply\n"); log_message( log_module, MSG_INFO, " Program number %d\n",reply->program_number); switch(reply->CA_enable) { case CA_ENABLE_DESCRAMBLING_POSSIBLE: log_message( log_module, MSG_INFO," Descrambling possible\n"); break; case CA_ENABLE_DESCRAMBLING_POSSIBLE_PURCHASE: log_message( log_module, MSG_INFO," Descrambling possible under conditions (purchase dialogue)\n"); break; case CA_ENABLE_DESCRAMBLING_POSSIBLE_TECHNICAL: log_message( log_module, MSG_INFO," Descrambling possible under conditions (technical dialogue)\n"); break; case CA_ENABLE_DESCRAMBLING_NOT_POSSIBLE_NO_ENTITLEMENT: log_message( log_module, MSG_INFO," Descrambling not possible (because no entitlement)\n"); break; case CA_ENABLE_DESCRAMBLING_NOT_POSSIBLE_TECHNICAL: log_message( log_module, MSG_INFO," Descrambling not possible (for technical reasons)\n"); break; default: log_message( log_module, MSG_INFO," RFU\n"); } en50221_app_pmt_reply_streams_for_each(reply, pos, reply_size) { log_message( log_module, MSG_INFO, " ES pid %d\n",pos->es_pid); switch(pos->CA_enable) { case CA_ENABLE_DESCRAMBLING_POSSIBLE: log_message( log_module, MSG_INFO," Descrambling possible\n"); break; case CA_ENABLE_DESCRAMBLING_POSSIBLE_PURCHASE: log_message( log_module, MSG_INFO," Descrambling possible under conditions (purchase dialogue)\n"); break; case CA_ENABLE_DESCRAMBLING_POSSIBLE_TECHNICAL: log_message( log_module, MSG_INFO," Descrambling possible under conditions (technical dialogue)\n"); break; case CA_ENABLE_DESCRAMBLING_NOT_POSSIBLE_NO_ENTITLEMENT: log_message( log_module, MSG_INFO," Descrambling not possible (because no entitlement)\n"); break; case CA_ENABLE_DESCRAMBLING_NOT_POSSIBLE_TECHNICAL: log_message( log_module, MSG_INFO," Descrambling not possible (for technical reasons)\n"); break; default: log_message( log_module, MSG_INFO," RFU\n"); } } return 0; } /******************************* * MMI *******************************/ // List object - DISPLAY_TYPE_LIST static int mumudvb_cam_mmi_list_callback(void *arg, uint8_t slot_id, uint16_t session_number, struct en50221_app_mmi_text *title, struct en50221_app_mmi_text *sub_title, struct en50221_app_mmi_text *bottom, uint32_t item_count, struct en50221_app_mmi_text *items, uint32_t item_raw_length, uint8_t *items_raw) { return(mumudvb_cam_mmi_menu_list_callback(arg, slot_id, session_number, title, sub_title, bottom, item_count, items, item_raw_length, items_raw, DISPLAY_TYPE_LIST)); } // Menu object - DISPLAY_TYPE_MENU static int mumudvb_cam_mmi_menu_callback(void *arg, uint8_t slot_id, uint16_t session_number, struct en50221_app_mmi_text *title, struct en50221_app_mmi_text *sub_title, struct en50221_app_mmi_text *bottom, uint32_t item_count, struct en50221_app_mmi_text *items, uint32_t item_raw_length, uint8_t *items_raw) { return(mumudvb_cam_mmi_menu_list_callback(arg, slot_id, session_number, title, sub_title, bottom, item_count, items, item_raw_length, items_raw, DISPLAY_TYPE_MENU)); } // Menu or List objects static int mumudvb_cam_mmi_menu_list_callback(void *arg, uint8_t slot_id, uint16_t session_number, struct en50221_app_mmi_text *title, struct en50221_app_mmi_text *sub_title, struct en50221_app_mmi_text *bottom, uint32_t item_count, struct en50221_app_mmi_text *items, uint32_t item_raw_length, uint8_t *items_raw, int object_type) { cam_p_t *cam_p; cam_p= (cam_p_t *) arg; (void) slot_id; // (void) session_number; (void) item_raw_length; (void) items_raw; // New CAM menu received, we prepared its storage for future display mumu_free_string(&cam_p->cam_menulist_str); // We save the date/time when the menu was received time_t rawtime; time (&rawtime); // Add line to CAM menu storage - Date and Time mumu_string_append(&cam_p->cam_menulist_str,"\t\n",ctime(&rawtime)); // Add line to CAM menu storage - CAM Menu String (model) mumu_string_append(&cam_p->cam_menulist_str,"\t\n",cam_p->cam_menu_string.string); // Add line to CAM menu storage - CAM Object type : LIST or MENU if (object_type==DISPLAY_TYPE_LIST) mumu_string_append(&cam_p->cam_menulist_str,"\t\n"); if (object_type==DISPLAY_TYPE_MENU) mumu_string_append(&cam_p->cam_menulist_str,"\t\n"); // Showing beginning of CAM menu if (object_type==DISPLAY_TYPE_LIST) log_message( log_module, MSG_INFO, "------------------ NEW CAM LIST ------------------\n"); if (object_type==DISPLAY_TYPE_MENU) log_message( log_module, MSG_INFO, "------------------ NEW CAM MENU ------------------\n"); // Title if (title->text_length) { log_message( log_module, MSG_INFO, "Menu_Title : %.*s\n", title->text_length, title->text); // Add line to CAM menu storage - Title mumu_string_append(&cam_p->cam_menulist_str,"\t<![CDATA[%.*s]]>\n", title->text_length, title->text); } // Subtitle if (sub_title->text_length) { log_message( log_module, MSG_INFO, "Menu_Subtitle : %.*s\n", sub_title->text_length, sub_title->text); // Add line to CAM menu storage - Subtitle mumu_string_append(&cam_p->cam_menulist_str,"\t\n", sub_title->text_length, sub_title->text); } // Choice 0 is always for cancel/return/ok action in MENU and LIST log_message( log_module, MSG_INFO, "Menu_Item 0 : Return\n"); // Add line to CAM menu storage - Items mumu_string_append(&cam_p->cam_menulist_str,"\t\n"); // Items uint32_t i; for(i=0; i< item_count; i++) { log_message( log_module, MSG_INFO, "Menu_Item %d : %.*s\n", (i+1), items[i].text_length, items[i].text); // Add line to CAM menu storage - Items mumu_string_append(&cam_p->cam_menulist_str,"\t\n", (i+1), items[i].text_length, items[i].text); } // Bottom if (bottom->text_length) { log_message( log_module, MSG_INFO, "Menu_Bottom : %.*s\n", bottom->text_length, bottom->text); // Add line to CAM menu storage - Bottom mumu_string_append(&cam_p->cam_menulist_str,"\t\n", bottom->text_length, bottom->text); } // Showing end of CAM menu log_message( log_module, MSG_INFO, "--------------------------------------------------\n"); fflush(stdout); cam_p->stdcam->mmi_session_number=session_number; //We leave (action=0 => CANCEL) if autoresponse is active (default=yes if no menu asked) if (cam_p->cam_mmi_autoresponse==1) { // Autoresponse log_message( log_module, MSG_INFO, "Menu autoresponse, send CANCEL\n"); en50221_app_mmi_menu_answ(cam_p->stdcam->mmi_resource, cam_p->stdcam->mmi_session_number, 0); cam_p->mmi_state = MMI_STATE_OPEN; } else // We wait an answer from the user cam_p->mmi_state = MMI_STATE_MENU; return 0; } static int mumudvb_cam_mmi_close_callback(void *arg, uint8_t slot_id, uint16_t session_number, uint8_t cmd_id, uint8_t delay) { cam_p_t *cam_p; cam_p= (cam_p_t *) arg; (void) slot_id; (void) cmd_id; (void) delay; // The CAM told us that the menu was closed log_message( log_module, MSG_INFO, "Closing CAM Menu\n"); // Remove last stored menu content mumu_free_string(&cam_p->cam_menulist_str); // Indicate that the menu was closed (for our own record) cam_p->mmi_state = MMI_STATE_CLOSED; // Close the session with the CAM or a new session MMI will not be allowed en50221_sl_destroy_session(cam_p->sl,session_number); return 0; } static int mumudvb_cam_mmi_display_control_callback(void *arg, uint8_t slot_id, uint16_t session_number, uint8_t cmd_id, uint8_t mmi_mode) { struct en50221_app_mmi_display_reply_details reply; cam_p_t *cam_p; cam_p= (cam_p_t *) arg; (void) slot_id; // don't support any commands but set mode if (cmd_id != MMI_DISPLAY_CONTROL_CMD_ID_SET_MMI_MODE) { en50221_app_mmi_display_reply(cam_p->stdcam->mmi_resource, session_number, MMI_DISPLAY_REPLY_ID_UNKNOWN_CMD_ID, &reply); return 0; } // we only support high level mode if (mmi_mode != MMI_MODE_HIGH_LEVEL) { en50221_app_mmi_display_reply(cam_p->stdcam->mmi_resource, session_number, MMI_DISPLAY_REPLY_ID_UNKNOWN_MMI_MODE, &reply); return 0; } // ack the high level open reply.u.mode_ack.mmi_mode = mmi_mode; en50221_app_mmi_display_reply(cam_p->stdcam->mmi_resource, session_number, MMI_DISPLAY_REPLY_ID_MMI_MODE_ACK, &reply); cam_p->mmi_state = MMI_STATE_OPEN; return 0; } static int mumudvb_cam_mmi_enq_callback(void *arg, uint8_t slot_id, uint16_t session_number, uint8_t blind_answer, uint8_t expected_answer_length, uint8_t *text, uint32_t text_size) { cam_p_t *cam_p; cam_p= (cam_p_t *) arg; (void) slot_id; (void) session_number; // Show the enquiry informations log_message( log_module, MSG_INFO, "----------------- NEW CAM ENQUIRY-----------------\n"); log_message( log_module, MSG_INFO, "Question: %.*s\n", text_size, text); log_message( log_module, MSG_INFO, "Expected answer length: %d\n", expected_answer_length); log_message( log_module, MSG_INFO, "--------------------------------------------------\n"); // New CAM enquiry received, we prepared its storage for future display mumu_free_string(&cam_p->cam_menulist_str); // We save the date/time when the enquiry was received time_t rawtime; time(&rawtime); // Add line to CAM enquiry storage - Date and Time mumu_string_append(&cam_p->cam_menulist_str,"\t\n",ctime(&rawtime)); // Add line to CAM menu storage - CAM Menu String (model) mumu_string_append(&cam_p->cam_menulist_str,"\t\n",cam_p->cam_menu_string.string); // Add line to CAM menu storage - CAM Object type : ENQUIRY mumu_string_append(&cam_p->cam_menulist_str,"\t\n"); // We put the question in the "Title" field mumu_string_append(&cam_p->cam_menulist_str,"\t<![CDATA[%.*s]]>\n", text_size, text); // We put the answer length in the "Subtitle" field mumu_string_append(&cam_p->cam_menulist_str,"\t\n", expected_answer_length); // We don't care to hide or display the answer... cam_p->mmi_enq_blind = blind_answer; // The expected length of the answer (number of characters) cam_p->mmi_enq_length = expected_answer_length; // Limit the answer to MAX_ENQUIRY_ANSWER_LENGTH characters (enough for PIN code and changing maturity, for the most common usages) if (cam_p->mmi_enq_length>MAX_ENQUIRY_ANSWER_LENGTH) cam_p->mmi_enq_length=MAX_ENQUIRY_ANSWER_LENGTH; // The actual number of typed characters cam_p->mmi_enq_entered = 0; //We leave (CANCEL) if autoresponse is active (default=yes if no menu asked) if (cam_p->cam_mmi_autoresponse==1) { // Autoresponse log_message( log_module, MSG_INFO, "Enquiry autoresponse, send CANCEL\n"); en50221_app_mmi_answ(cam_p->stdcam->mmi_resource, cam_p->stdcam->mmi_session_number, MMI_ANSW_ID_CANCEL, NULL, 0); cam_p->mmi_state = MMI_STATE_OPEN; } else // We wait an answer from the user cam_p->mmi_state = MMI_STATE_ENQ; return 0; } /** @brief This function is called when a new PMT packet is there */ int cam_new_packet(int pid, int curr_channel, cam_p_t *cam_p, mumudvb_channel_t *actual_channel) { int iRet; int ret=0; struct timeval tv; gettimeofday (&tv, (struct timezone *) NULL); if (((actual_channel->need_cam_ask==CAM_NEED_ASK)||(actual_channel->need_cam_ask==CAM_NEED_UPDATE) || (actual_channel->need_scam_ask==CAM_NEED_ASK))&& (actual_channel->pid_i.pmt_pid == pid)) { //If we have a full and ok PMT, this PMT is updated commonly for autoconf and CAM if(actual_channel->pmt_packet->len_full>0 && !actual_channel->pmt_need_update) { //We check the transport stream id of the packet if(check_pmt_service_id(actual_channel->pmt_packet, actual_channel)) { iRet=mumudvb_cam_new_pmt(cam_p, actual_channel->pmt_packet,actual_channel->need_cam_ask); if(iRet==1) { if(actual_channel->need_cam_ask==CAM_NEED_UPDATE) log_message( log_module, MSG_INFO,"CA PMT (UPDATED) sent for channel %d : \"%s\"\n", curr_channel, actual_channel->name ); else log_message( log_module, MSG_INFO,"CA PMT (ADDED) sent for channel %d : \"%s\"\n", curr_channel, actual_channel->name ); actual_channel->need_cam_ask=CAM_ASKED; //once we have asked the CAM for this PID, we don't have to ask anymore //For the feature of reasking we initalise the time actual_channel->cam_asking_time = tv.tv_sec; ret=1; } else if(iRet==-1) { log_message( log_module, MSG_DETAIL,"Problem sending CA PMT for channel %d : \"%s\"\n", curr_channel, actual_channel->name ); } } } else //we force update of the PMT packet actual_channel->pmt_need_update=1; } return ret; } MuMuDVB-2.1.0/src/cam.h000066400000000000000000000103671305714132500144410ustar00rootroot00000000000000/* * MuMuDVB - UDP-ize a DVB transport stream. * File for Conditionnal Access Modules support * * (C) 2009-2011 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef _CAM_H #define _CAM_H #include #include #include #include #include #include #include #include #include #include #include "ts.h" #include "mumudvb.h" #include "autoconf.h" /**@file * @brief cam support * * Header file for cam support, contains mainly the structure for carrying cam parameters */ #include struct ca_info { int initialized; //are the cai complete ? int ready; //We wait a pool between each channel sending int sys_num; uint16_t sys_id[256]; char app_name[256]; }; #define MAX_ENQUIRY_ANSWER_LENGTH 20 #define DISPLAY_TYPE_LIST 1 #define DISPLAY_TYPE_MENU 2 /** @brief the parameters for the cam * This structure contain the parameters needed for the CAM */ typedef struct cam_p_t{ /**Do we activate the support for CAMs*/ int cam_support; /**The came number (in case of multiple cams)*/ int cam_number; /** Do we reask channels asked and keept scrambled and what is the interval between reasks*/ int cam_reask_interval; int cam_type; int need_reset; int reset_counts; int max_reset_number; int timeout_no_cam_init; int reset_interval; struct en50221_transport_layer *tl; struct en50221_session_layer *sl; struct en50221_stdcam *stdcam; int ca_resource_connected; int camthread_shutdown; pthread_t camthread; int moveca; int mmi_state; int mmi_enq_blind; int mmi_enq_length; int mmi_enq_entered; char mmi_enq_answer[10]; /** Used to say if we received the CA info callback */ long ca_info_ok_time; /** The delay for sending the PMT to the CAM*/ int cam_delay_pmt_send; /** The delay between two PMT asking */ int cam_interval_pmt_send; long cam_pmt_send_time; char filename_cam_info[DEFAULT_PATH_LEN]; mumu_string_t cam_menu_string; mumu_string_t cam_menulist_str; int cam_mmi_autoresponse; /** Do we follow the version of the PMT for the CAM ?*/ int cam_pmt_follow; }cam_p_t; /***************************************************************************** * Code for dealing with libdvben50221 *****************************************************************************/ #define SL_MAX_SESSIONS 16 #define MMI_STATE_CLOSED 0 #define MMI_STATE_OPEN 1 #define MMI_STATE_ENQ 2 #define MMI_STATE_MENU 3 #define MAX_WAIT_AFTER_RESET 30 #define CAM_DEFAULT_MAX_RESET_NUM 5 #define CAM_DEFAULT_RESET_INTERVAL 30 /** * States a CAM in a slot can be in. */ #define DVBCA_CAMSTATE_MISSING 0 #define DVBCA_CAMSTATE_INITIALISING 1 #define DVBCA_CAMSTATE_READY 2 /** * The types of CA interface we support. */ #define DVBCA_INTERFACE_LINK 0 #define DVBCA_INTERFACE_HLCI 1 void init_cam_v(cam_p_t *cam_p); int cam_send_ca_pmt( mumudvb_ts_packet_t *pmt, struct ca_info *cai); int convert_desc(struct ca_info *cai, uint8_t *out, uint8_t *buf, int dslen, uint8_t cmd, int quiet); int convert_pmt(struct ca_info *cai, mumudvb_ts_packet_t *pmt, uint8_t list, uint8_t cmd,int quiet); int cam_start(cam_p_t *, int, mumu_chan_p_t *); void cam_stop(cam_p_t *); int read_cam_configuration(cam_p_t *cam_p, mumudvb_channel_t *c_chan, char *substring); int cam_new_packet(int pid, int curr_channel, cam_p_t *cam_p, mumudvb_channel_t *actual_channel); void cam_pmt_follow(unsigned char *ts_packet, mumudvb_channel_t *actual_channel); #endif MuMuDVB-2.1.0/src/crc32.c000066400000000000000000000102101305714132500145730ustar00rootroot00000000000000/* * mumudvb - UDP-ize a DVB transport stream. * * (C) 2004-2009 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** @file * @brief File for CRC32 calculation * it contains the precomputed table */ #include /**CRC table for PAT rebuilding, cam support and autoconfiguration*/ uint32_t crc32_table[256] = { 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 }; MuMuDVB-2.1.0/src/dvb.c000066400000000000000000000436621305714132500144530ustar00rootroot00000000000000/* dvb.c * MuMuDVB - Stream a DVB transport stream. * * (C) 2004-2013 Brice DUBOST * (C) Dave Chapman 2001, 2002. * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /** @file * @brief dvb part (except tune) of mumudvb * Ie : setting the filters, openning the file descriptors etc... */ #define _GNU_SOURCE #include "dvb.h" #include #include #include #include #include #include #include "log.h" #include static char *log_module="DVB: "; /** * @brief Open the frontend associated with card * Return 1 in case of succes, -1 otherwise * * @param fd_frontend the file descriptor for the frontend * @param card the card number */ int open_fe (int *fd_frontend, char *base_path, int tuner, int rw, int full_path) { char *frontend_name=NULL; int asprintf_ret; int rw_flag; if(full_path) //used for pipe input asprintf_ret=asprintf(&frontend_name,"%s",base_path); else asprintf_ret=asprintf(&frontend_name,"%s/%s%d",base_path,FRONTEND_DEV_NAME,tuner); if(asprintf_ret==-1) return -1; if(rw) rw_flag=O_RDWR; else rw_flag=O_RDONLY; if ((*fd_frontend = open (frontend_name, rw_flag | O_NONBLOCK)) < 0) { log_message( log_module, MSG_ERROR, "FRONTEND DEVICE: %s : %s\n", frontend_name, strerror(errno)); free(frontend_name); return -1; } free(frontend_name); return 1; } /** * @brief Set a filter of the pid asked. The file descriptor has to be * opened before. Ie it will ask the card for this PID. * @param fd the file descriptor * @param pid the pid for the filter */ void set_ts_filt (int fd, uint16_t pid) { struct dmx_pes_filter_params pesFilterParams; log_message( log_module, MSG_DEBUG, "Setting filter for PID %d\n", pid); pesFilterParams.pid = pid; pesFilterParams.input = DMX_IN_FRONTEND; pesFilterParams.output = DMX_OUT_TS_TAP; pesFilterParams.pes_type = DMX_PES_OTHER; pesFilterParams.flags = DMX_IMMEDIATE_START; if (ioctl (fd, DMX_SET_PES_FILTER, &pesFilterParams) < 0) { log_message( log_module, MSG_ERROR, "FILTER %i: ", pid); log_message( log_module, MSG_ERROR, "DMX SET PES FILTER : %s\n", strerror(errno)); } } /** * @brief Show the reception power. * This information is not alway reliable * @param fds the file descriptors of the card */ void *show_power_func(void* arg) { strength_parameters_t *strengthparams; strengthparams= (strength_parameters_t *) arg; fe_status_t festatus_old; int lock_lost; int meas_ber_ok=1; int meas_strength_ok=1; int meas_snr_ok=1; int meas_ub_ok=1; int wait_time=20;//in units of 100ms int i; strengthparams->strength = 0; strengthparams->ber = 0; strengthparams->snr = 0; strengthparams->ub = 0; strengthparams->ts_discontinuities = 0; //could be initialized somewhere else but sounds fine here memset(&festatus_old,0,sizeof(fe_status_t)); lock_lost=0; while(!strengthparams->tune_p->strengththreadshutdown) { if(strengthparams->tune_p->card_tuned) { if(strengthparams->tune_p->display_strenght ) mumu_timing(); if (ioctl (strengthparams->fds->fd_frontend, FE_READ_BER, &strengthparams->ber) < 0) { if(meas_ber_ok) { meas_ber_ok=0; log_message( log_module, MSG_WARN, "An issue happened during the IOCTLS to take BER measurements error: %s",strerror(errno)); } } else meas_ber_ok=1; if (ioctl (strengthparams->fds->fd_frontend, FE_READ_SIGNAL_STRENGTH, &strengthparams->strength) < 0) { if(meas_strength_ok) { meas_strength_ok=0; log_message( log_module, MSG_WARN, "An issue happened during the IOCTLS to take strength measurements error: %s",strerror(errno)); } } else meas_strength_ok=1; if (ioctl (strengthparams->fds->fd_frontend, FE_READ_SNR, &strengthparams->snr) < 0) { if(meas_snr_ok) { meas_snr_ok=0; log_message( log_module, MSG_WARN, "An issue happened during the IOCTLS to take SNR measurements error: %s",strerror(errno)); } } else meas_snr_ok=1; if (ioctl (strengthparams->fds->fd_frontend, FE_READ_UNCORRECTED_BLOCKS, &strengthparams->ub) < 0 ) { if(meas_ub_ok) { meas_ub_ok=0; log_message( log_module, MSG_WARN, "An issue happened during the IOCTLS to take uncorrected blocks measurements error: %s",strerror(errno)); } } else meas_ub_ok=1; } if(strengthparams->tune_p->display_strenght && strengthparams->tune_p->card_tuned) { log_message( log_module, MSG_INFO, "Bit error rate: %10d Signal strength: %10d SNR: %10d Uncorrected blocks: %10d\n", strengthparams->ber,strengthparams->strength,strengthparams->snr,strengthparams->ub); log_message( log_module, MSG_INFO, "ts_discontinuities %10d",strengthparams->ts_discontinuities); log_message( log_module, MSG_FLOOD, "Timing: ioctls took %ld micro seconds\n",mumu_timing()); } if((strengthparams->tune_p->check_status ||strengthparams->tune_p->display_strenght) && strengthparams->tune_p->card_tuned) { if (ioctl (strengthparams->fds->fd_frontend, FE_READ_STATUS, &strengthparams->festatus) != -1) { if((!(strengthparams->festatus & FE_HAS_LOCK) ) && (festatus_old != strengthparams->festatus)) { if(!lock_lost) log_message( log_module, MSG_WARN, "The card has lost the lock (antenna unplugged ?). Detailed status"); else log_message( log_module, MSG_INFO, "Card is still not locked but status changed. Detailed status"); print_status(strengthparams->festatus); festatus_old = strengthparams->festatus; lock_lost=1; } if((strengthparams->festatus & FE_HAS_LOCK) && lock_lost) { log_message( log_module, MSG_INFO, "Card is locked again."); lock_lost=0; } } } for(i=0;itune_p->strengththreadshutdown;i++) usleep(100000); } return 0; } /** * @brief Open file descriptors for the card. open dvr and one demuxer fd per asked pid. This function can be called * more than one time if new pids are added (typical case autoconf) * return -1 in case of error * @param card the card number * @param asked_pid the array of asked pids * @param fds the structure with the file descriptors */ int create_card_fd(char *base_path, int tuner, uint8_t *asked_pid, fds_t *fds) { int curr_pid = 0; char *demuxdev_name=NULL; char *dvrdev_name=NULL; int asprintf_ret; asprintf_ret=asprintf(&demuxdev_name,"%s/%s%d",base_path,DEMUX_DEV_NAME,tuner); if(asprintf_ret==-1) return -1; for(curr_pid=0;curr_pid<8193;curr_pid++) //file descriptors for the demuxer (used to set the filters) //we check if we need to open the file descriptor (some cards are limited) if ((asked_pid[curr_pid] != 0)&& (fds->fd_demuxer[curr_pid]==0) ) if((fds->fd_demuxer[curr_pid] = open (demuxdev_name, O_RDWR)) < 0) { log_message( log_module, MSG_ERROR, "FD PID %i: ", curr_pid); log_message( log_module, MSG_ERROR, "DEMUX DEVICE: %s : %s\n", demuxdev_name, strerror(errno)); free(demuxdev_name); return -1; } asprintf_ret=asprintf(&dvrdev_name,"%s/%s%d",base_path,DVR_DEV_NAME,tuner); if(asprintf_ret==-1) return -1; if (fds->fd_dvr==0) //this function can be called more than one time, we check if we opened it before if ((fds->fd_dvr = open (dvrdev_name, O_RDONLY | O_NONBLOCK)) < 0) { log_message( log_module, MSG_ERROR, "DVR DEVICE: %s : %s\n", dvrdev_name, strerror(errno)); free(dvrdev_name); return -1; } free(dvrdev_name); free(demuxdev_name); return 0; } /** * @brief Open filters for the pids in asked_pid. This function update the asked_pid array and * can be called more than one time if new pids are added (typical case autoconf) * Ie it asks the card for the pid list by calling set_ts_filt * @param asked_pid the array of asked pids * @param fds the structure with the file descriptors */ void set_filters(uint8_t *asked_pid, fds_t *fds) { for(int curr_pid=0;curr_pid<8193;curr_pid++) if (asked_pid[curr_pid] == PID_ASKED ) { set_ts_filt (fds->fd_demuxer[curr_pid], curr_pid); asked_pid[curr_pid] = PID_FILTERED; } } /** * @brief Close the file descriptors associated with the card * @param fds the structure with the file descriptors */ void close_card_fd(fds_t *fds) { int curr_pid = 0; for(curr_pid=0;curr_pid<8193;curr_pid++) { if(fds->fd_demuxer[curr_pid]) { close(fds->fd_demuxer[curr_pid]); fds->fd_demuxer[curr_pid]=0; } } if(fds->fd_dvr) close (fds->fd_dvr); fds->fd_dvr=0; if(fds->fd_frontend) close (fds->fd_frontend); fds->fd_frontend=0; } /** * @brief Function for the tread reading data from the card * @param arg the structure with the thread parameters */ void *read_card_thread_func(void* arg) { card_thread_parameters_t *threadparams; threadparams= (card_thread_parameters_t *) arg; int poll_ret; pthread_mutex_lock(&threadparams->carddatamutex); threadparams->card_buffer->bytes_in_write_buffer=0; pthread_mutex_unlock(&threadparams->carddatamutex); int throwing_packets=0; log_message( log_module, MSG_DEBUG, "Reading thread start\n"); usleep(100000); //some waiting to be sure the main program is waiting //it is probably useless while(!threadparams->threadshutdown&& !get_interrupted()) { //Poll the DVB descriptors poll_ret=mumudvb_poll(threadparams->fds->pfds,threadparams->fds->pfdsnum,DVB_POLL_TIMEOUT); if(poll_ret<0) { log_message( log_module, MSG_ERROR, "Thread polling issue\n"); set_interrupted(-poll_ret); return NULL; } if((!(threadparams->fds->pfds[0].revents&POLLIN)) && (!(threadparams->fds->pfds[0].revents&POLLPRI))) //Timeout, we give the ball back to the main for unicast polling { if(threadparams->main_waiting) { pthread_cond_signal(&threadparams->threadcond); } //no DVB packet, we continue continue; } if((threadparams->card_buffer->bytes_in_write_buffer+TS_PACKET_SIZE*threadparams->card_buffer->dvr_buffer_size)>threadparams->card_buffer->write_buffer_size) { /**@todo : use a dynamic buffer ?*/ if(!throwing_packets) { throwing_packets=1; /** @todo count them*/ log_message( log_module, MSG_INFO, "Thread trowing dvb packets\n"); } if(threadparams->main_waiting) { pthread_cond_signal(&threadparams->threadcond); } continue; } throwing_packets=0; pthread_mutex_lock(&threadparams->carddatamutex); threadparams->card_buffer->bytes_in_write_buffer+=card_read(threadparams->fds->fd_dvr, threadparams->card_buffer->writing_buffer+threadparams->card_buffer->bytes_in_write_buffer, threadparams->card_buffer); if(threadparams->main_waiting) { pthread_cond_signal(&threadparams->threadcond); } pthread_mutex_unlock(&threadparams->carddatamutex); } return NULL; } /** @brief : Read data from the card * This function have to be called after a poll to ensure there is data to read * */ int card_read(int fd_dvr, unsigned char *dest_buffer, card_buffer_t *card_buffer) { /* Attempt to read 188 bytes * dvr_buffer_size from /dev/____/dvr */ int bytes_read; if ((bytes_read = read (fd_dvr, dest_buffer, TS_PACKET_SIZE*card_buffer->dvr_buffer_size)) > 0) { if((bytes_read>0 )&& (bytes_read % TS_PACKET_SIZE)) { log_message( log_module, MSG_WARN, "Warning : partial packet received len %d\n", bytes_read); card_buffer->partial_packet_number++; bytes_read-=bytes_read % TS_PACKET_SIZE; if(bytes_read<=0) return 0; } } if(bytes_read<0) { if(errno==EOVERFLOW) { log_message( log_module, MSG_WARN,"Error : DVR buffer overrun \n"); card_buffer->overflow_number++; } else if(errno!=EAGAIN) log_message( log_module, MSG_WARN,"Error : DVR Read error : %s \n",strerror(errno)); return 0; } return bytes_read; } typedef struct frontend_cap_t { long int flag; char descr[128]; }frontend_cap_t; /** @brief : List the capabilities of one card * * */ void show_card_capabilities( int card, int tuner ) { int frontend_fd; int i_ret; int display_sr; int frequency_factor; /** The path of the card */ char card_dev_path[256]; strncpy(card_dev_path,DVB_DEV_PATH,256); char number[10]; sprintf(number,"%d",card); int l=sizeof(card_dev_path); mumu_string_replace(card_dev_path,&l,0,"%card",number); //Open the frontend if(!open_fe (&frontend_fd, card_dev_path, tuner,0,0)) // we open the card readonly so we can get the capabilities event when used return; //get frontend info struct dvb_frontend_info fe_info; if ( (i_ret = ioctl(frontend_fd,FE_GET_INFO, &fe_info) < 0)){ log_message( log_module, MSG_ERROR, "FE_GET_INFO: %s \n", strerror(errno)); close (frontend_fd); return; } log_message( log_module, MSG_INFO, "=========== Card %d - Tuner %d ===========\n", card, tuner); log_message( log_module, MSG_INFO, " Frontend : %s\n", fe_info.name); display_sr=0; switch(fe_info.type) { case FE_OFDM: log_message( log_module, MSG_INFO, " Terrestrial (DVB-T) card\n"); break; case FE_QPSK: log_message( log_module, MSG_INFO, " Satellite (DVB-S) card\n"); display_sr=1; break; case FE_QAM: log_message( log_module, MSG_INFO, " Cable (DVB-C) card\n"); display_sr=1; break; case FE_ATSC: log_message( log_module, MSG_INFO, " ATSC card\n"); break; } if(fe_info.type==FE_QPSK) frequency_factor=1000; else frequency_factor=1; log_message( log_module, MSG_INFO, " Frequency: %d kHz to %d kHz\n",(int) fe_info.frequency_min/1000*frequency_factor,(int) fe_info.frequency_max/1000*frequency_factor); if(display_sr) log_message( log_module, MSG_INFO, " Symbol rate: %d k symbols/s to %d k symbols/s \n", (int)fe_info.symbol_rate_min/1000, (int)fe_info.symbol_rate_max/1000); log_message( log_module, MSG_DETAIL, " == Card capabilities =="); log_message( log_module, MSG_DEBUG, "caps 0x%x\n",fe_info.caps); frontend_cap_t caps[]={ {0x1,"FE_CAN_INVERSION_AUTO"}, {0x2,"FE_CAN_FEC_1_2"}, {0x4,"FE_CAN_FEC_2_3"}, {0x8,"FE_CAN_FEC_3_4"}, {0x10,"FE_CAN_FEC_4_5"}, {0x20,"FE_CAN_FEC_5_6"}, {0x40,"FE_CAN_FEC_6_7"}, {0x80,"FE_CAN_FEC_7_8"}, {0x100,"FE_CAN_FEC_8_9"}, {0x200,"FE_CAN_FEC_AUTO"}, {0x400,"FE_CAN_QPSK"}, {0x800,"FE_CAN_QAM_16"}, {0x1000,"FE_CAN_QAM_32"}, {0x2000,"FE_CAN_QAM_64"}, {0x4000,"FE_CAN_QAM_128"}, {0x8000,"FE_CAN_QAM_256"}, {0x10000,"FE_CAN_QAM_AUTO"}, {0x20000,"FE_CAN_TRANSMISSION_MODE_AUTO"}, {0x40000,"FE_CAN_BANDWIDTH_AUTO"}, {0x80000,"FE_CAN_GUARD_INTERVAL_AUTO"}, {0x100000,"FE_CAN_HIERARCHY_AUTO"}, {0x200000,"FE_CAN_8VSB"}, {0x400000,"FE_CAN_16VSB"}, {0x800000,"FE_HAS_EXTENDED_CAPS /* We need more bitspace for newer APIs, indicate this. */"}, {0x10000000,"FE_CAN_2G_MODULATION /* frontend supports '2nd generation modulation' (DVB-S2) */"}, {0x20000000,"FE_NEEDS_BENDING /* not supported anymore */"}, {0x40000000,"FE_CAN_RECOVER /* frontend can recover from a cable unplug automatically */"}, {0x80000000,"FE_CAN_MUTE_TS /* frontend can stop spurious TS data output */"}, }; int numcaps=28; int i; for(i=0;id_name)<8) continue; if(strncmp(d_adapter->d_name,"adapter",7)) continue; card_number= atoi(d_adapter->d_name+7); log_message( log_module, MSG_DEBUG, "found adapter %d\n", card_number); cards[num_cards]=card_number; num_cards++; if(num_cards==256) { log_message( log_module, MSG_ERROR, "Wow ! You have a system with more than 256 DVB cards, Please Contact me :D"); closedir(dvb_dir); return; } } closedir(dvb_dir); //Basic card sorting (O(N^2)) int i,j,old_card; old_card=-1; DIR *adapter_dir; /** The path of the card */ char card_dev_path[256]; int tuner_number; struct dirent *d_tuner; for(i=0;iold_card) && (cards[j]d_name)<(strlen(FRONTEND_DEV_NAME)+1)) continue; if(strncmp(d_tuner->d_name,FRONTEND_DEV_NAME,strlen(FRONTEND_DEV_NAME))) continue; tuner_number= atoi(d_tuner->d_name+strlen(FRONTEND_DEV_NAME)); log_message( log_module, MSG_DEBUG, "\tCard %d found Frontend %d\n", card_number, tuner_number); /** show the current tuner */ show_card_capabilities( card_number , tuner_number); } closedir(adapter_dir); } } MuMuDVB-2.1.0/src/dvb.h000066400000000000000000000056441305714132500144560ustar00rootroot00000000000000/* * mumudvb - UDP-ize a DVB transport stream. * Based on dvbstream by (C) Dave Chapman 2001, 2002. * * (C) 2004-2010 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /** @file * @brief dvb part (except tune) of mumudvb * Ie : setting the filters, openning the file descriptors etc... */ #ifndef _DVB_H #define _DVB_H #include #include #include #include #include #include #include #include // DVB includes: #include #include #include "mumudvb.h" #include "tune.h" #define DVB_DEV_PATH "/dev/dvb/adapter%card" #define FRONTEND_DEV_NAME "frontend" #define DEMUX_DEV_NAME "demux" #define DVR_DEV_NAME "dvr" //The timeout for DVB polling, must exist otherwise the program would block without data on the card #define DVB_POLL_TIMEOUT 100 enum { PID_NOT_ASKED=0, PID_ASKED, PID_FILTERED, }; /** The parameters for the thread for showing the strength */ typedef struct strength_parameters_t{ tune_p_t *tune_p; fds_t *fds; fe_status_t festatus; int strength, ber, snr, ub; int ts_discontinuities; }strength_parameters_t; /** The parameters for the thread for reading the data from the card */ typedef struct card_thread_parameters_t{ //mutex for the data buffer pthread_mutex_t carddatamutex; //Condition variable for locking the main program in order to wait for new data pthread_cond_t threadcond; //file descriptors fds_t *fds; //The shutdown for the thread volatile int threadshutdown; //The buffer for the card card_buffer_t *card_buffer; // int thread_running; /** Is main waiting ?*/ int main_waiting; }card_thread_parameters_t; void *read_card_thread_func(void* arg); int open_fe (int *fd_frontend, char *base_path, int tuner, int rw, int full_path); void set_ts_filt (int fd,uint16_t pid); int create_card_fd(char *base_path, int tuner, uint8_t *asked_pid, fds_t *fds); void set_filters(uint8_t *asked_pid, fds_t *fds); void close_card_fd(fds_t *fds); void *show_power_func(void* arg); int card_read(int fd_dvr, unsigned char *dest_buffer, card_buffer_t *card_buffer); void list_dvb_cards (); #endif MuMuDVB-2.1.0/src/errors.h000066400000000000000000000024701305714132500152110ustar00rootroot00000000000000/* * mumudvb - UDP-ize a DVB transport stream. * * (C) 2004-2009 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /**@file *File for the enumeration of the different possible errors *@todo : update it */ #ifndef _ERRORS_MUMUDVB_H #define _ERRORS_MUMUDVB_H enum { ERROR_ARGS=1, ERROR_CONF_FILE, ERROR_CONF, ERROR_TOO_CHANNELS, ERROR_CREATE_FILE, ERROR_DEL_FILE, ERROR_TUNE, ERROR_NO_DIFF, ERROR_NO_FIRST_CW, ERROR_MEMORY, ERROR_NETWORK, ERROR_CAM, ERROR_GENERIC, ERROR_NO_CAM_INIT, }; #endif MuMuDVB-2.1.0/src/log.c000066400000000000000000001126321305714132500144530ustar00rootroot00000000000000/* * mumudvb - Stream a DVB transport stream. * Based on dvbstream by (C) Dave Chapman 2001, 2002. * * (C) 2004-2013 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /** @file * @brief Log functions for mumudvb * * This file contains functions to log messages or write logging information to a file */ #include #include #include #include #include #include #include #include #include #include #include #include "mumudvb.h" #include "errors.h" #include "log.h" #include "tune.h" #ifdef HAVE_ICONV #include #endif #ifdef ENABLE_CAM_SUPPORT #include #endif #define LOG_HEAD_LEN 6 log_params_t log_params={ .verbosity = MSG_INFO+1, .log_type=LOGGING_UNDEFINED, .rotating_log_file=0, .syslog_initialised=0, .log_header=NULL, .log_file=NULL, .log_flush_interval = -1, }; static char *log_module="Logs: "; /** Initialize Rewrite variables*/ void init_stats_v(stats_infos_t *stats_p) { *stats_p=(stats_infos_t){ .stats_num_packets_received=0, .stats_num_reads=0, .show_buffer_stats=0, .show_buffer_stats_time = 0, .show_buffer_stats_interval = 120, .show_traffic = 0, .show_traffic_time = 0, .compute_traffic_time = 0, .show_traffic_interval = 10, .compute_traffic_interval = 10, .up_threshold = 80, .down_threshold = 30, .debug_updown = 0, }; } /** @brief Read a line of the configuration file to check if there is a logging parameter * * @param stats_infos the stats infos parameters * @param log_params the logging parameters * @param substring The currrent line */ int read_logging_configuration(stats_infos_t *stats_infos, char *substring) { char delimiteurs[] = CONFIG_FILE_SEPARATOR; if (!strcmp (substring, "show_traffic_interval")) { substring = strtok (NULL, delimiteurs); stats_infos->show_traffic_interval= atoi (substring); if(stats_infos->show_traffic_interval<1) { stats_infos->show_traffic_interval=1; log_message( log_module, MSG_WARN,"Sorry the minimum interval for showing the traffic is 1s\n"); } } else if (!strcmp (substring, "compute_traffic_interval")) { substring = strtok (NULL, delimiteurs); stats_infos->compute_traffic_interval= atoi (substring); if(stats_infos->compute_traffic_interval<1) { stats_infos->compute_traffic_interval=1; log_message( log_module, MSG_WARN,"Sorry the minimum interval for computing the traffic is 1s\n"); } } else if (!strcmp (substring, "up_threshold")) { substring = strtok (NULL, delimiteurs); stats_infos->up_threshold= atoi (substring); } else if (!strcmp (substring, "down_threshold")) { substring = strtok (NULL, delimiteurs); stats_infos->down_threshold= atoi (substring); } else if (!strcmp (substring, "debug_updown")) { substring = strtok (NULL, delimiteurs); stats_infos->debug_updown= atoi (substring); } else if (!strcmp (substring, "log_type")) { substring = strtok (NULL, delimiteurs); if (!strcmp (substring, "console")) log_params.log_type |= LOGGING_CONSOLE; else if (!strcmp (substring, "syslog")) { openlog ("MUMUDVB", LOG_PID, 0); log_params.log_type |= LOGGING_SYSLOG; log_params.syslog_initialised=1; } else log_message(log_module,MSG_WARN,"Invalid value for log_type\n"); } else if (!strcmp (substring, "log_file")) { substring = strtok (NULL, delimiteurs); log_params.log_file_path=malloc((strlen(substring)+1)*sizeof(char)); strncpy(log_params.log_file_path,substring,strlen(substring)+1); if(log_params.log_file_path==NULL) { log_message(log_module,MSG_WARN,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); return -1; } } else if (!strcmp (substring, "log_header")) { substring = strtok (NULL,"=" ); if(log_params.log_header!=NULL) free(log_params.log_header); log_params.log_header=malloc((strlen(substring)+1)*sizeof(char)); if(log_params.log_header==NULL) { log_message(log_module,MSG_WARN,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); return -1; } sprintf(log_params.log_header,"%s",substring); } else if (!strcmp (substring, "log_flush_interval")) { substring = strtok (NULL, delimiteurs); log_params.log_flush_interval = atof (substring); } else return 0; return 1; } /** * @brief Return a string description of the log priorities */ char *priorities(int type) { switch(type) { case MSG_ERROR: return "ERRO"; case MSG_WARN: return "WARN"; case MSG_INFO: return "Info"; case MSG_DETAIL: return "Deb0"; case MSG_DEBUG: return "Deb1"; case MSG_FLOOD: return "Deb2"; default: return ""; } } /** * @brief Return a string description of the channel status (readyness) flag */ char *ready_f_to_str(chan_status_t flag) { switch(flag) { case REMOVED: return "Channel removed by the provider"; case NO_STREAMING: return "Channel not streamed (bad service ID or scrambled)"; case NOT_READY: return "Channel detected but not ready"; case ALMOST_READY: return "Channel almost ready"; case READY: case READY_EXISTING: return "Channel ready"; default: return ""; } } /** * @brief Sync_log for logrotate * This function is called when a sighup is received. This function flushes the log and reopen the logfile * * */ void sync_logs() { if (((log_params.log_type & LOGGING_FILE) == LOGGING_FILE) && log_params.log_file) { fflush(log_params.log_file); log_params.log_file=freopen(log_params.log_file_path,"a",log_params.log_file); } } /** * @brief Print a log message * * @param log_module : the name of the part of MuMuDVB which send the message * @param type : message type MSG_* * @param psz_format : the message in the printf format */ void log_message( char* log_module, int type, const char *psz_format, ... ) { va_list args; int priority=0; char *tempchar; int message_size; mumu_string_t log_string; if(type>=log_params.verbosity) return; log_string.string=NULL; log_string.length=0; /*****************************************/ //if the log header is not initialised // we do it /*****************************************/ if(log_params.log_header==NULL) { log_params.log_header=malloc((strlen(DEFAULT_LOG_HEADER)+1)*sizeof(char)); if(log_params.log_header==NULL) { if (log_params.log_type == LOGGING_FILE) fprintf( log_params.log_file,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); else if (log_params.log_type == LOGGING_SYSLOG) syslog (MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); else fprintf( stderr,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); va_end( args ); set_interrupted(ERROR_MEMORY<<8); return; } sprintf(log_params.log_header,"%s",DEFAULT_LOG_HEADER); } /*****************************************/ //We apply the templates to the header /*****************************************/ mumu_string_append(&log_string, "%s",log_params.log_header); log_string.string=mumu_string_replace(log_string.string,&log_string.length,1,"%priority",priorities(type)); if(log_module!=NULL) log_string.string=mumu_string_replace(log_string.string,&log_string.length,1,"%module",log_module); else log_string.string=mumu_string_replace(log_string.string,&log_string.length,1,"%module",""); char timestring[40]; time_t actual_time; actual_time=time(NULL); sprintf(timestring,"%jd", (intmax_t)actual_time); log_string.string=mumu_string_replace(log_string.string,&log_string.length,1,"%timeepoch",timestring); asctime_r(localtime(&actual_time),timestring); timestring[strlen(timestring)-1]='\0'; //In order to remove the final '\n' but by asctime log_string.string=mumu_string_replace(log_string.string,&log_string.length,1,"%date",timestring); char pidstring[10]; sprintf (pidstring, "%d", getpid ()); log_string.string=mumu_string_replace(log_string.string,&log_string.length,1,"%pid",pidstring); /*****************************************/ //We append the log message /*****************************************/ //The length returned by mumu_string_replace is the allocated length not the string length //If we want mumu_string_append to work we need to update the length to the string length log_string.length=strlen(log_string.string); va_start( args, psz_format ); message_size=vsnprintf(NULL, 0, psz_format, args); va_end( args ); tempchar=calloc((message_size+1),sizeof(char)); if(tempchar==NULL) { if (log_params.log_type == LOGGING_FILE) fprintf( log_params.log_file,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); else if (log_params.log_type == LOGGING_SYSLOG) syslog (MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); else fprintf( stderr,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); va_end( args ); set_interrupted(ERROR_MEMORY<<8); return; } va_start( args, psz_format ); vsprintf(tempchar, psz_format, args ); va_end( args ); //If there is no \n at the end of the message we add it char terminator='\0'; if(tempchar[strlen(tempchar)-1] != '\n') terminator='\n'; mumu_string_append(&log_string,"%s%c",tempchar,terminator); free(tempchar); /*****************************************/ //We "display" the log message /*****************************************/ if(type=READY) num_chan_ready++; } log_message( log_module, MSG_INFO, "Diffusion %d channel%s\n", num_chan_ready, (number_of_channels <= 1 ? "" : "s")); for (curr_channel = 0; curr_channel < number_of_channels; curr_channel++) { if(channels[curr_channel].channel_readyname)))return; for (int curr_pid = 0; curr_pid < channel->pid_i.num_pids; curr_pid++) { if(set_interrupted(mumu_string_append(&string, " %d",channel->pid_i.pids[curr_pid])))return; } log_message( log_module, MSG_DETAIL,"%s\n",string.string); mumu_free_string(&string); /******** end of display the pids **********/ } /** * @brief Generate a file containing the list of the streamed channels * and a file containing a list of not streamed channels * * @param file_streamed_channels_filename The filename for the file containig the list of streamed channels * @param file_not_streamed_channels_filename The filename for the file containig the list of NOT streamed channels * @param number_of_channels the number of channels * @param channels the channels array */ void gen_file_streamed_channels (char *file_streamed_channels_filename, char *file_not_streamed_channels_filename, int number_of_channels, mumudvb_channel_t *channels) { /**todo : adapt it for unicast (json ?) */ FILE *file_streamed_channels; FILE *file_not_streamed_channels; int curr_channel; file_streamed_channels = fopen (file_streamed_channels_filename, "w"); if (file_streamed_channels == NULL) { log_message( log_module, MSG_WARN, "Error file_streamed_channels %s: %s\n", file_streamed_channels_filename, strerror (errno)); return; } file_not_streamed_channels = fopen (file_not_streamed_channels_filename, "w"); if (file_not_streamed_channels == NULL) { log_message( log_module, MSG_WARN, "Error file_not_streamed_channels %s: %s\n", file_not_streamed_channels_filename, strerror (errno)); fclose (file_streamed_channels); // the first fopen was successful! return; } for (curr_channel = 0; curr_channel < number_of_channels; curr_channel++) //We store the old to be sure that we store only channels over the minimum packets limit if (channels[curr_channel].has_traffic && (channels[curr_channel].channel_ready>=READY)) { fprintf (file_streamed_channels, "%s:%d:%s", channels[curr_channel].ip4Out, channels[curr_channel].portOut, channels[curr_channel].name); if (channels[curr_channel].scrambled_channel == FULLY_UNSCRAMBLED) fprintf (file_streamed_channels, ":FullyUnscrambled\n"); else if (channels[curr_channel].scrambled_channel == PARTIALLY_UNSCRAMBLED) fprintf (file_streamed_channels, ":PartiallyUnscrambled\n"); else //HIGHLY_SCRAMBLED fprintf (file_streamed_channels, ":HighlyScrambled\n"); } else fprintf (file_not_streamed_channels, "%s:%d:%s\n", channels[curr_channel].ip4Out, channels[curr_channel].portOut, channels[curr_channel].name); fclose (file_streamed_channels); fclose (file_not_streamed_channels); } typedef struct ca_sys_id_t { int beginning; int end; //if == 0 equivalent to have end=beginning char descr[128]; }ca_sys_id_t; //updated 2013 06 02 from http://www.dvbservices.com/identifiers/ca_system_id ca_sys_id_t casysids[]={ {0x01,0, "IPDC SPP (TS 102 474) Annex A "}, {0x02,0, "18Crypt (IPDC SPP (TS 102 474) Annex B)"}, {0x04,0, "OMA DRM Content Format"}, {0x05,0, "OMA BCAST 1.0"}, {0x06,0, "OMA BCAST 1.0 (U)SIM"}, {0x07,0, "Reserved for Open IPTV Forum"}, {0x08,0, "Open Mobile Alliance"}, {0x00,0xFF, "Standardized systems"}, {0x0100,0x01ff, "Canal Plus"}, {0x0200,0x02ff, "CCETT"}, {0x0300,0x03ff, "Kabel Deutschland"}, {0x0400,0x04ff, "Eurodec"}, {0x0500,0x05ff, "France Telecom"}, {0x0600,0x06ff, "Irdeto"}, {0x0700,0x07ff, "Jerrold/GI/Motorola"}, {0x0800,0x08ff, "Matra Communication"}, {0x0900,0x09ff, "News Datacom"}, {0x0A00,0x0Aff, "Nokia"}, {0x0B00,0x0Bff, "Norwegian Telekom"}, {0x0C00,0x0Cff, "NTL"}, {0x0D00,0x0Dff, "CrytoWorks (Irdeto)"}, {0x0E00,0x0Eff, "Scientific Atlanta"}, {0x0F00,0x0Fff, "Sony"}, {0x1000,0x10ff, "Tandberg Television"}, {0x1100,0x11ff, "Thomson"}, {0x1200,0x12ff, "TV/Com"}, {0x1300,0x13ff, "HPT - Croatian Post and Telecommunications"}, {0x1400,0x14ff, "HRT - Croatian Radio and Television"}, {0x1500,0x15ff, "IBM"}, {0x1600,0x16ff, "Nera"}, {0x1700,0x17ff, "BetaTechnik"}, {0x1800,0x18ff, "Kudelski SA"}, {0x1900,0x19ff, "Titan Information Systems"}, {0x1E00,0x1E07, "Alticast"}, {0x1EA0,0, "Monacrypt"}, {0x1EB0,0, "TELECAST TECHNOLOGY CO., LTD."}, {0x2000,0x20ff, "Telefonica Servicios Audiovisuales"}, {0x2100,0x21ff, "STENTOR (France Telecom, CNES and DGA)"}, {0x2200,0x22ff, "Scopus Network Technologies"}, {0x2300,0x23ff, "BARCO AS"}, {0x2400,0x24ff, "StarGuide Digital Networks"}, {0x2500,0x25ff, "Mentor Data System, Inc."}, {0x2600,0x26ff, "European Broadcasting Union"}, {0x2700,0x270F, "PolyCipher (NGNA, LLC)"}, {0x2710,0x2711, "Extended Secure Technologies B.V."}, {0x2712,0, "Signal elektronic"}, {0x2713,0x2714, "Wuhan Tianyu Information Industry Co., Ltd"}, {0x2715,0, "Network Broadcast"}, {0x2716,0, "Bromteck"}, {0x2717,0x2718, "LOGIWAYS"}, {0x2800,0x2809, "LCS LLC"}, {0x2810,0, "MULTIKOM DELTASAT GMBH KG"}, {0x4347,0, "Crypton"}, {0x4700,0x47FF, "General Instrument (Motorola)"}, {0x4800,0x48FF, "Telemann"}, {0x4900,0x49FF, "CrytoWorks (China) (Irdeto)"}, {0x4A10,0x4A1F, "Easycas"}, {0x4A20,0x4A2F, "AlphaCrypt"}, {0x4A30,0x4A3F, "DVN Holdings"}, {0x4A40,0x4A4F, "Shanghai Advanced Digital Technology Co. Ltd. (ADT)"}, {0x4A50,0x4A5F, "Shenzhen Kingsky Company (China) Ltd."}, {0x4A60,0x4A6F, "@Sky"}, {0x4A70,0x4A7F, "Dreamcrypt"}, {0x4A80,0x4A8F, "THALESCrypt"}, {0x4A90,0x4A9F, "Runcom Technologies"}, {0x4AA0,0x4AAF, "SIDSA"}, {0x4AB0,0x4ABF, "Beijing Compunicate Technology Inc."}, {0x4AC0,0x4ACF, "Latens Systems Ltd"}, {0x4AD0,0x4AD1, "XCrypt Inc."}, {0x4AD2,0x4AD3, "Beijing Digital Video Technology Co., Ltd."}, {0x4AD4,0x4AD5, "Widevine Technologies, Inc."}, {0x4AD6,0x4AD7, "SK Telecom Co., Ltd."}, {0x4AD8,0x4AD9, "Enigma Systems"}, {0x4ADA,0, "Wyplay SAS"}, {0x4ADB,0, "Jinan Taixin Electronics, Co., Ltd."}, {0x4ADC,0, "LogiWays"}, {0x4ADD,0, "ATSC System Renewability Message (SRM)"}, {0x4ADE,0, "CerberCrypt"}, {0x4ADF,0, "Caston Co., Ltd."}, {0x4AE0,0x4AE1, "Digi Raum Electronics Co. Ltd."}, {0x4AE2,0x4AE3, "Microsoft Corp."}, {0x4AE4,0, "Coretrust, Inc."}, {0x4AE5,0, "IK SATPROF"}, {0x4AE6,0, "SypherMedia International"}, {0x4AE7,0, "Guangzhou Ewider Technology Corporation Limited"}, {0x4AE8,0, "FG DIGITAL Ltd."}, {0x4AE9,0, "Dreamer-i Co., Ltd."}, {0x4AEA,0, "Cryptoguard AB"}, {0x4AEB,0, "Abel DRM Systems AS"}, {0x4AEC,0, "FTS DVL SRL"}, {0x4AED,0, "Unitend Technologies, Inc."}, {0x4AEE,0, "Deltacom Electronics OOD"}, {0x4AEF,0, "NetUP Inc."}, {0x4AF0,0, "Beijing Alliance Broadcast Vision Technology Co., Ltd."}, {0x4AF1,0, "China DTV Media Inc., Ltd. #1"}, {0x4AF2,0, "China DTV Media Inc., Ltd. #2"}, {0x4AF3,0, "Baustem Information Technologies, Ltd."}, {0x4AF4,0, "Marlin Developer Community, LLC"}, {0x4AF5,0, "SecureMedia"}, {0x4AF6,0, "Tongfang CAS"}, {0x4AF7,0, "MSA"}, {0x4AF8,0, "Griffin CAS"}, {0x4AF9,0x4AFA, "Beijing Topreal Technologies Co., Ltd"}, {0x4AFB,0, "NST"}, {0x4AFC,0, "Panaccess Systems GmbH"}, {0x4B00,0x4B02, "Tongfang CAS"}, {0x4B03,0, "DuoCrypt"}, {0x4B04,0, "Great Wall CAS"}, {0x4B05,0x4B06, "DIGICAP"}, {0x4B07,0, "Wuhan Reikost Technology Co., Ltd."}, {0x4B08,0, "Philips"}, {0x4B09,0, "Ambernetas"}, {0x4B0A,0x4B0B, "Beijing Sumavision Technologies CO. LTD."}, {0x4B0C,0x4B0F, "Sichuan changhong electric co.,ltd."}, {0x4B10,0, "Exterity Limited"}, {0x4B11,0x4B12, "Advanced Digital Platform Technologies"}, {0x4B13,0x4B14, "Microsoft Corporation"}, {0x4B20,0x4B22, "MULTIKOM DELTASAT GmbH Co KG"}, {0x4B23,0, "SkyNLand Video Networks Pvt Ltd"}, {0x5347,0, "GkWare e.K."}, {0x5601,0, "Verimatrix, Inc. #1"}, {0x5602,0, "Verimatrix, Inc. #2"}, {0x5603,0, "Verimatrix, Inc. #3"}, {0x5604,0, "Verimatrix, Inc. #4"}, {0x5605,0x5606, "Sichuan Juizhou Electronic Co. Ltd"}, {0x5607,0x5608, "Viewscenes"}, {0x5609,0, "Power On s.r.l"}, {0x7BE0,0x7BE1, "OOO"}, {0xAA00,0, "Best CAS Ltd"}, {0xAA01,0, "Best CAS Ltd"}, }; int num_casysids=130; /** @brief Display the ca system id according to ETR 162 * * @param id the id to display */ char *ca_sys_id_to_str(int id) { //cf ETR 162 and http://www.dvbservices.com/identifiers/ca_system_id for(int i=0;i= id)) return casysids[i].descr; } return "UNKNOWN, please report"; } flag_descr_t service_type_descr[]={ {0x01, "Television"}, {0x02, "Radio"}, {0x03, "Teletext"}, {0x04, "NVOD Reference service"}, {0x05, "NVOD Time shifted service"}, {0x06, "Mosaic service"}, {0x07, "FM radio service"}, {0x08, "DVB SRM service"}, {0x0a, "Advanced codec Radio"}, {0x0b, "Advanced codec mosaic"}, {0x0c, "Data broadcast service"}, {0x0d, "Reserved for common interface usage"}, {0x0e, "RCS Map"}, {0x0f, "RCS FLS"}, {0x10, "DVB MHP (multimedia home platform)"}, {0x11, "Television MPEG2-HD"}, {0x16, "Advanced codec SD Television"}, {0x17, "Advanced codec SD NVOD Time shifted service"}, {0x18, "Advanced codec SD NVOD Reference service"}, {0x19, "Advanced codec HD Television"}, {0x1a, "Advanced codec HD NVOD Time shifted service"}, {0x1b, "Advanced codec HD NVOD Reference service"}, {0x1c, "advanced codec frame compatible 3D HD digital television service"}, {0x1d, "advanced codec frame compatible 3D HD NVOD time-shifted service"}, {0x1e, "advanced codec frame compatible 3D HD NVOD reference service"}, }; /** @brief Convert the service type to str according to EN 300 468 v1.13.1 table 87 * * @param type the type to display * @param dest : the destination string */ char *service_type_to_str(int type) { if(type>=0x80 && type<=0xFE) return "User defined"; for(size_t i=0;i=0x80 && type<=0xFE) return "User defined"; switch(type) { case 0x01: case 0x11: case 0x16: case 0x19: case 0x1c: return "Television"; case 0x02: case 0x07: case 0x0a: return "Radio"; default: return ""; } } /** @brief Display the service type according to EN 300 468 v1.13.1 table 87 * * @param type the type to display * @param loglevel : the loglevel for displaying it */ void display_service_type(int type, int loglevel, char *log_module) { log_message( log_module, loglevel, "service type: 0x%x : %s \n", type, service_type_to_str(type)); } /** @brief Write the PID type into a string * * @param dest : the destination string * @param type the type to display */ char *pid_type_to_str(int type) { switch(type) { case PID_PMT: return "PMT"; case PID_PCR: return "PCR"; case PID_VIDEO_MPEG1: return "Video (MPEG1)"; case PID_VIDEO_MPEG2: return "Video (MPEG2)"; case PID_VIDEO_MPEG4_ASP: return "Video (MPEG4-ASP)"; case PID_VIDEO_MPEG4_AVC: return "Video (MPEG4-AVC)"; case PID_VIDEO_MPEG4_HEVC: return "Video (MPEG4-HVC)"; case PID_AUDIO_MPEG1: return "Audio (MPEG1)"; case PID_AUDIO_MPEG2: return "Audio (MPEG2)"; case PID_AUDIO_AAC_LATM: return "Audio (AAC-LATM)"; case PID_AUDIO_AAC_ADTS: return "Audio (AAC-ADTS)"; case PID_AUDIO_ATSC: return "Audio (ATSC A/53B)"; case PID_AUDIO_AC3: return "Audio (AC3)"; case PID_AUDIO_EAC3: return "Audio (E-AC3)"; case PID_AUDIO_DTS: return "Audio (DTS)"; case PID_AUDIO_AAC: return "Audio (AAC)"; case PID_EXTRA_VBIDATA: return "VBI Data"; case PID_EXTRA_VBITELETEXT: return "VBI Teletext"; case PID_EXTRA_TELETEXT: return "Teletext"; case PID_EXTRA_SUBTITLE: return "Subtitling"; case PID_ECM: return "CA information (ECM,EMM)"; case PID_UNKNOW: default: return "Unknown"; } } #ifdef ENABLE_CAM_SUPPORT /** @brief Write the error from the libdvben50221 into a string * * @param dest : the destination string * @param error the error to display */ char *liben50221_error_to_str(int error) { switch(error) { case 0: return "EN50221ERR_NONE"; case EN50221ERR_CAREAD: return "EN50221ERR_CAREAD"; case EN50221ERR_CAWRITE: return "EN50221ERR_CAWRITE"; case EN50221ERR_TIMEOUT: return "EN50221ERR_TIMEOUT"; case EN50221ERR_BADSLOTID: return "EN50221ERR_BADSLOTID"; case EN50221ERR_BADCONNECTIONID: return "EN50221ERR_BADCONNECTIONID"; case EN50221ERR_BADSTATE: return "EN50221ERR_BADSTATE"; case EN50221ERR_BADCAMDATA: return "EN50221ERR_BADCAMDATA"; case EN50221ERR_OUTOFMEMORY: return "EN50221ERR_OUTOFMEMORY"; case EN50221ERR_ASNENCODE: return "EN50221ERR_ASNENCODE"; case EN50221ERR_OUTOFCONNECTIONS: return "EN50221ERR_OUTOFCONNECTIONS"; case EN50221ERR_OUTOFSLOTS: return "EN50221ERR_OUTOFSLOTS"; case EN50221ERR_IOVLIMIT: return "EN50221ERR_IOVLIMIT"; case EN50221ERR_BADSESSIONNUMBER: return "EN50221ERR_BADSESSIONNUMBER"; case EN50221ERR_OUTOFSESSIONS: return "EN50221ERR_OUTOFSESSIONS"; default: return "UNKNOWN"; } } /** @brief Write the error from the libdvben50221 into a string containing the description of the error * * @param dest : the destination string * @param error the error to display */ char *liben50221_error_to_str_descr(int error) { switch(error) { case 0: return "No Error."; case EN50221ERR_CAREAD: return "error during read from CA device."; case EN50221ERR_CAWRITE: return "error during write to CA device."; case EN50221ERR_TIMEOUT: return "timeout occured waiting for a response from a device."; case EN50221ERR_BADSLOTID: return "bad slot ID supplied by user - the offending slot_id will not be set."; case EN50221ERR_BADCONNECTIONID: return "bad connection ID supplied by user."; case EN50221ERR_BADSTATE: return "slot/connection in the wrong state."; case EN50221ERR_BADCAMDATA: return "CAM supplied an invalid request."; case EN50221ERR_OUTOFMEMORY: return "memory allocation failed."; case EN50221ERR_ASNENCODE: return "ASN.1 encode failure - indicates library bug."; case EN50221ERR_OUTOFCONNECTIONS: return "no more connections available."; case EN50221ERR_OUTOFSLOTS: return "no more slots available - the offending slot_id will not be set."; case EN50221ERR_IOVLIMIT: return "Too many struct iovecs were used."; case EN50221ERR_BADSESSIONNUMBER: return "Bad session number suppplied by user."; case EN50221ERR_OUTOFSESSIONS: return "no more sessions available."; default: return "Unknown error, please contact"; } } #endif /** @brief : display mumudvb info*/ void print_info () { fprintf (stderr, "MuMuDVB Version " VERSION "\n --- Build information ---\n" #ifdef ENABLE_CAM_SUPPORT "Built with CAM support.\n" #else "Built without CAM support.\n" #endif #ifdef ENABLE_SCAM_SUPPORT "Built with SCAM support.\n" #else "Built without SCAM support.\n" #endif #ifdef ATSC "Built with ATSC support.\n" #ifdef HAVE_LIBUCSI "Built with ATSC long channel names support.\n" #endif #endif #if DVB_API_VERSION >= 5 "Built with support for DVB API Version %d.%d.\n" #ifdef DVBT2 "Built with support for DVB-T2.\n" #endif #endif "---------\n" "Originally based on dvbstream 0.6 by (C) Dave Chapman 2001-2004\n" "Released under the GPL.\n" "Latest version available from http://mumudvb.braice.net/\n" "Project from the cr@ns (http://www.crans.org)\n" "by Brice DUBOST (mumudvb@braice.net)\n\n", DVB_API_VERSION,DVB_API_VERSION_MINOR); } /** @brief : display mumudvb usage*/ void usage (char *name) { fprintf (stderr, "MuMuDVB is a program who can redistribute stream from DVB on a network, in multicast or in http unicast.\n" "It's main feature is to take a whole transponder and put each channel on a different multicast IP.\n\n" "Usage: %s [options] \n" "-c, --config : Config file\n" "-s, --signal : Display signal power\n" "-t, --traffic : Display channels traffic\n" "-l, --list-cards : List the DVB cards and exit\n" "--card : The DVB card to use (overrided by the configuration file)\n" "--server_id : The server id (for autoconfiguration, overrided by the configuration file)\n" "-d, --debug : Don't deamonize\n" "-v : More verbose\n" "-q : Less verbose\n" "--dumpfile : Debug option : Dump the stream into the specified file\n" "-h, --help : Help\n" "\n", name); print_info (); } void show_traffic( char *log_module, double now, int show_traffic_interval, mumu_chan_p_t *chan_p) { static long show_traffic_time=0; if(!show_traffic_time) show_traffic_time=now; if((now-show_traffic_time)>=show_traffic_interval) { show_traffic_time=now; for (int curr_channel = 0; curr_channel < chan_p->number_of_channels; curr_channel++) { log_message( log_module, MSG_INFO, "Traffic : %.2f kb/s \t for channel \"%s\"\n", chan_p->channels[curr_channel].traffic*8, chan_p->channels[curr_channel].name); } } } /** @brief The different encodings that can be used Cf EN 300 468 Annex A (I used v1.9.1) */ char *encodings_en300468[] ={ "ISO8859-1", "ISO8859-2", "ISO8859-3", "ISO8859-4", "ISO8859-5", "ISO8859-6", "ISO8859-7", "ISO8859-8", "ISO8859-9", "ISO8859-10", "ISO8859-11", "ISO8859-12", "ISO8859-13", "ISO8859-14", "ISO8859-15", "ISO-10646", //control char 0x11 "GB2312", //control char 0x13 "BIG5", //control char 0x14 "ISO-10646/UTF8", //control char 0x15 }; /**@brief Convert text according to EN 300 468 annex A * */ int convert_en300468_string(char *string, int max_len, int debug) { int encoding_control_char=8; //cf encodings_en300468 char *tempdest, *tempbuf; char *dest; unsigned char *realstart; unsigned char *src; /* remove control characters and convert to UTF-8 the channel name */ //If no channel encoding is specified, it seems that most of the broadcasters //uses ISO/IEC 8859-9. But the norm (EN 300 468) said that it should be Latin-1 (ISO/IEC 6937 + euro) log_message( log_module, MSG_FLOOD, "convert_en300468_string: String to be converted start 0x%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x ",string[0],string[1],string[2],string[3],string[4],string[5],string[6],string[7],string[8],string[9]); realstart = (unsigned char *)string; if(*realstart < 0x20) { log_message( log_module, MSG_FLOOD, "starting with encoding character 0x%02x",*realstart); if(debug) {log_message( log_module, MSG_FLOOD, "Encoding number 0x%02x, see EN 300 468 Annex A",*realstart);} //control character recognition based on EN 300 468 v1.9.1 Annex A if(*realstart<=0x0b) {encoding_control_char=(int) *realstart+4-1;} else if(*realstart==0x10) { //ISO/IEC 8859 : See table A.4 realstart++;//we skip the current byte realstart++;//This one is always set to 0 if(*realstart >= 0x01 && *realstart <=0x0f) encoding_control_char=(int) *realstart-1; } else if(*realstart==0x11)//ISO/IEC 10646 : Basic Multilingual Plane {encoding_control_char=15;} else if(*realstart==0x12)//KSX1001-2004 : Korean Character Set {if(debug) {log_message( log_module, MSG_WARN, "\t\t Encoding KSX1001-2004 (korean character set) not implemented yet by iconv, we'll use the default encoding for service name\n");}} else if(*realstart==0x13)//GB-2312-1980 : Simplified Chinese Character {encoding_control_char=16;} else if(*realstart==0x14)//Big5 subset of ISO/IEC 10646 : Traditional Chinese {encoding_control_char=17;} else if(*realstart==0x15)//UTF-8 encoding of ISO/IEC 10646 : Basic Multilingual Plane {encoding_control_char=18;} else if(*realstart==0x1f) { realstart++; log_message( log_module, MSG_WARN, "\t\t Encoding 0x1F from TS 101 162 not implemented yet (0x%02x), we'll use the default encoding for service name\n",*realstart); } else { log_message( log_module, MSG_WARN, "\t\t Encoding not implemented yet (0x%02x), we'll use the default encoding for service name\n",*realstart); } //we skip the encoding character realstart++; } //temporary buffers allocation int lenstring=0; //We count the len needed for the temporary buffer. //Due to the special structure of an EN300468 string a \0 can be present in the string //So we cannot use strlen for (src = realstart; *src; src++) { if ((*src < 0x80 || *src > 0x9f)) //One character lenstring++; } tempdest=tempbuf=malloc(sizeof(char)*lenstring+1); log_message( log_module, MSG_DEBUG,"String len %d offset %zd",lenstring, realstart-((unsigned char *)string)); if(tempdest==NULL) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); set_interrupted(ERROR_MEMORY<<8); return -1; } int len=0; for (src = realstart; *src; src++) { if ((*src < 0x80 || *src > 0x9f)) { //We copy non-control characters *tempdest++ = *src; len++; } else if (*src >= 0x80 && *src <= 0x9f) { //to encode in UTF-8 we add 0xc2 before this control character //but wh have to put it after iconv, it's a bit boring just for bold //we drop them if(*src==0x86) {if(debug) {log_message( log_module, MSG_DETAIL, "Control character \"Bold\", we drop");}} else if(*src==0x87) {if(debug) {log_message( log_module, MSG_DETAIL, "Control character \"UnBold\", we drop");}} else if(*src==0x8a) { if(debug) {log_message( log_module, MSG_DETAIL, "Control character \"CR/LF\", we replace by a standard newline");} *tempdest++ = '\n'; len++; } else if(*src>=0x8b ) {if(debug) {log_message( log_module, MSG_DETAIL, "Control character 0x%02x \"User defined\" at len %d. We drop",*src,len);}} else {if(debug) {log_message( log_module, MSG_DEBUG, "\tUnimplemented name control_character : %x \n", *src);}} } } log_message( log_module, MSG_DEBUG,"String len before conversion %d ",len); *tempdest = 0; #ifdef HAVE_ICONV //Conversion to utf8 iconv_t cd; //we open the conversion table cd = iconv_open( "UTF8", encodings_en300468[encoding_control_char] ); if (cd == (iconv_t) -1) { if(debug) {log_message( log_module, MSG_DETAIL, "\t\t UTF8 encoding not supported by iconv. Trying UTF-8.\n");} cd = iconv_open( "UTF-8", encodings_en300468[8]); if (cd == (iconv_t) -1) { if(debug) {log_message( log_module, MSG_DETAIL, "\t\t Neither UTF8 or UTF-8 encoding supported by iconv. No name encoding conversion.\n");} goto exit_iconv; } } size_t inSize, outSize=max_len; inSize=len; //pointers initialization because iconv change them, we store dest=string; tempdest=tempbuf; //conversion size_t nonreversible; nonreversible = iconv(cd, &tempdest, &inSize, &dest, &outSize ); *dest = '\0'; free(tempbuf); iconv_close( cd ); log_message( log_module, MSG_FLOOD, "Converted text : \"%s\" (text encoding : %s)\nnonreversible conversions %zd", string,encodings_en300468[encoding_control_char],nonreversible); #else if(debug) {log_message( log_module, MSG_DETAIL, "Iconv not present, no name encoding conversion \n");} #endif exit_iconv: if(debug) {log_message( log_module, MSG_FLOOD, "Converted text : \"%s\" (text encoding : %s)\n", string,encodings_en300468[encoding_control_char]);} return encoding_control_char; } /** @brief : show the contents of the CA identifier descriptor * * @param buf : the buffer containing the descriptor */ void show_CA_identifier_descriptor(unsigned char *buf) { int length,i,ca_id; log_message( log_module, MSG_DETAIL, "--- descriptor --- CA identifier descriptor\n"); log_message( log_module, MSG_DETAIL, "CA_system_ids : \n"); length=buf[1]; buf+=2; for(i=0;i 2001, 2002. * * (C) 2009 Brice DUBOST * * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include "mumudvb.h" #include "log.h" #include #include static char *log_module="Multicast: "; /** Initialize multicast variables*/ void init_multicast_v(multi_p_t *multi_p) { memset(multi_p,0,sizeof(multi_p_t)); *multi_p=(multi_p_t){ .multicast=1, .multicast_ipv6=0, .multicast_ipv4=1, .ttl=DEFAULT_TTL, .common_port = 1234, .auto_join=0, .rtp_header = 0, .iface4="\0", .iface6="\0", }; } /** @brief Read a line of the configuration file to check if there is a cam parameter * * @param multi_p the multicast parameters * @param substring The currrent line */ int read_multicast_configuration(multi_p_t *multi_p, mumudvb_channel_t *c_chan, char *substring) { char delimiteurs[] = CONFIG_FILE_SEPARATOR; if (!strcmp (substring, "common_port")) { substring = strtok (NULL, delimiteurs); multi_p->common_port = atoi (substring); } else if (!strcmp (substring, "multicast_ttl")) { substring = strtok (NULL, delimiteurs); multi_p->ttl = atoi (substring); } else if (!strcmp (substring, "multicast_ipv4")) { substring = strtok (NULL, delimiteurs); multi_p->multicast_ipv4 = atoi (substring); } else if (!strcmp (substring, "multicast_ipv6")) { substring = strtok (NULL, delimiteurs); multi_p->multicast_ipv6 = atoi (substring); } else if (!strcmp (substring, "multicast_auto_join")) { substring = strtok (NULL, delimiteurs); multi_p->auto_join = atoi (substring); } else if (!strcmp (substring, "ip")) { if ( c_chan == NULL) { log_message( log_module, MSG_ERROR, "ip : You have to start a channel first (using new_channel)\n"); return -1; } substring = strtok (NULL, delimiteurs); if(strlen(substring)>19) { log_message( log_module, MSG_ERROR, "The Ip address %s is too long.\n", substring); return -1; } sscanf (substring, "%s\n", c_chan->ip4Out); MU_F(c_chan->ip4Out)=F_USER; } else if (!strcmp (substring, "ip6")) { if ( c_chan == NULL) { log_message( log_module, MSG_ERROR, "ip6 : You have to start a channel first (using new_channel)\n"); return -1; } substring = strtok (NULL, delimiteurs); if(strlen(substring)>(IPV6_CHAR_LEN-1)) { log_message( log_module, MSG_ERROR, "The Ip v6 address %s is too long.\n", substring); return -1; } sscanf (substring, "%s\n", c_chan->ip6Out); MU_F(c_chan->ip6Out)=F_USER; } else if (!strcmp (substring, "port")) { if ( c_chan == NULL) { log_message( log_module, MSG_ERROR, "port : You have to start a channel first (using new_channel)\n"); return -1; } substring = strtok (NULL, delimiteurs); c_chan->portOut = atoi (substring); MU_F(c_chan->portOut)=F_USER; } else if (!strcmp (substring, "rtp_header")) { substring = strtok (NULL, delimiteurs); multi_p->rtp_header = atoi (substring); if (multi_p->rtp_header==1) log_message( log_module, MSG_INFO, "You decided to send the RTP header (multicast only).\n"); } else if (!strcmp (substring, "multicast_iface4")) { substring = strtok (NULL, delimiteurs); if(strlen(substring)>(IF_NAMESIZE)) { log_message( log_module, MSG_ERROR, "The interface name ipv4 address %s is too long.\n", substring); return -1; } sscanf (substring, "%s\n", multi_p->iface4); } else if (!strcmp (substring, "multicast_iface6")) { substring = strtok (NULL, delimiteurs); if(strlen(substring)>(IF_NAMESIZE)) { log_message( log_module, MSG_ERROR, "The interface name ipv6 address %s is too long.\n", substring); return -1; } sscanf (substring, "%s\n", multi_p->iface6); } else return 0; //Nothing concerning multicast, we return 0 to explore the other possibilities return 1;//We found something for multicast, we tell main to go for the next line } MuMuDVB-2.1.0/src/mumudvb.c000066400000000000000000001442671305714132500153620ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * Based on dvbstream by (C) Dave Chapman 2001, 2002. * * (C) 2004-2013 Brice DUBOST * * Code for dealing with libdvben50221 inspired from zap_ca * Copyright (C) 2004, 2005 Manu Abraham * Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net) * * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /** @file * @brief This file is the main file of MuMuDVB */ /** @mainpage Documentation for the mumudvb project * @section introduction * Mumudvb is a program that can redistribute streams from DVB on a network using * multicasting or HTTP unicast. It is able to multicast a whole DVB transponder by assigning * each channel to a different multicast IP. * * @section Main features * Stream channels from a transponder on different multicast IPs * The program can rewrite the PAT Pid in order to announce only present channels (useful for some set-top boxes) * Support for scrambled channels (if you don't have a CAM you can use sasc-ng, but check if it's allowed in you country) * Support for autoconfiguration * Generation of SAP announces *@section files * mumudvb.h header containing global information * * autoconf.c autoconf.h code related to autoconfiguration * * cam.c cam.h : code related to the support of scrambled channels * * crc32.c : the crc32 table * * dvb.c dvb.h functions related to the DVB card : oppening filters, file descriptors etc * * log.c logging functions * * pat_rewrite.c rewrite.h : the functions associated with the rewrite of the PAT pid * * sdt_rewrite.c rewrite.h : the functions associated with the rewrite of the SDT pid * * sap.c sap.h : sap announces * * ts.c ts.h : function related to the MPEG-TS parsing * * tune.c tune.h : tuning of the dvb card * * network.c network.h : networking ie openning sockets, sending packets * * unicast_http.c unicast_http.h : HTTP unicast */ #define _GNU_SOURCE //in order to use program_invocation_short_name and pthread_timedjoin_np #include "config.h" // Linux includes: #include #include #include #include #include #include #include #include #include #include #include #include #ifdef ANDROID #include #else #include #endif #include #include #include #include #include #include #include #include #include "mumudvb.h" #include "mumudvb_mon.h" #include "tune.h" #include "network.h" #include "dvb.h" #ifdef ENABLE_CAM_SUPPORT #include "cam.h" #endif #ifdef ENABLE_SCAM_SUPPORT #include "scam_capmt.h" #include "scam_common.h" #include "scam_getcw.h" #include "scam_decsa.h" #endif #include "ts.h" #include "errors.h" #include "autoconf.h" #include "sap.h" #include "rewrite.h" #include "unicast_http.h" #include "rtp.h" #include "log.h" #if defined __UCLIBC__ || defined ANDROID #define program_invocation_short_name "mumudvb" #else extern char *program_invocation_short_name; #endif static char *log_module="Main: "; /* Signal handling code shamelessly copied from VDR by Klaus Schmidinger - see http://www.cadsoft.de/people/kls/vdr/index.htm */ // global variables used by SignalHandler long now; long real_start_time; int *card_tuned; //Pointer to the card_tuned information int received_signal = 0; int timeout_no_diff = ALARM_TIME_TIMEOUT_NO_DIFF; int write_streamed_channels=1; /** Do we send scrambled packets ? */ int dont_send_scrambled=0; //logging extern log_params_t log_params; // prototypes static void SignalHandler (int signum);//below int read_multicast_configuration(multi_p_t *, mumudvb_channel_t *, char *); //in multicast.c void init_multicast_v(multi_p_t *multi_p); //in multicast.c void chan_new_pmt(unsigned char *ts_packet, mumu_chan_p_t *chan_p, int pid); int main (int argc, char **argv) { // file descriptors fds_t fds; /** File descriptors associated with the card */ memset(&fds,0,sizeof(fds_t)); //Thread information pthread_t signalpowerthread=0; pthread_t cardthread; pthread_t monitorthread=0; card_thread_parameters_t cardthreadparams; memset(&cardthreadparams,0,sizeof(card_thread_parameters_t)); //Channel information mumu_chan_p_t chan_p; memset(&chan_p,0,sizeof(chan_p)); pthread_mutex_init(&chan_p.lock,NULL); chan_p.psi_tables_filtering=PSI_TABLES_FILTERING_NONE; //sap announces variables sap_p_t sap_p; init_sap_v(&sap_p); //Statistics stats_infos_t stats_infos; init_stats_v(&stats_infos); //unicast //Parameters for HTTP unicast unicast_parameters_t unic_p; init_unicast_v(&unic_p); //multicast //multicast parameters multi_p_t multi_p; init_multicast_v(&multi_p); //tuning parameters tune_p_t tune_p; init_tune_v(&tune_p); card_tuned=&tune_p.card_tuned; #ifdef ENABLE_CAM_SUPPORT //CAM (Conditionnal Access Modules : for scrambled channels) cam_p_t cam_p; init_cam_v(&cam_p); cam_p_t *cam_p_ptr=&cam_p; #else void *cam_p_ptr=NULL; #endif #ifdef ENABLE_SCAM_SUPPORT //SCAM (software conditionnal Access Modules : for scrambled channels) scam_parameters_t scam_vars={ .scam_support = 0, .getcwthread_shutdown=0, }; scam_vars.epfd = epoll_create(MAX_CHANNELS); scam_parameters_t *scam_vars_ptr=&scam_vars; #else void *scam_vars_ptr=NULL; #endif //autoconfiguration auto_p_t auto_p; init_aconf_v(&auto_p); //Parameters for rewriting rewrite_parameters_t rewrite_vars; init_rewr_v(&rewrite_vars); int no_daemon = 0; char filename_channels_not_streamed[DEFAULT_PATH_LEN]; char filename_channels_streamed[DEFAULT_PATH_LEN]; char filename_pid[DEFAULT_PATH_LEN]=PIDFILE_PATH; int server_id = 0; /** The server id for the template %server */ int iRet; //MPEG2-TS reception and sort int pid; /** pid of the current mpeg2 packet */ int ScramblingControl; int continuity_counter; /** The buffer for the card */ card_buffer_t card_buffer; memset (&card_buffer, 0, sizeof (card_buffer_t)); card_buffer.dvr_buffer_size=DEFAULT_TS_BUFFER_SIZE; card_buffer.max_thread_buffer_size=DEFAULT_THREAD_BUFFER_SIZE; /** List of mandatory pids */ uint8_t mandatory_pid[MAX_MANDATORY_PID_NUMBER]; struct timeval tv; //files char *conf_filename = NULL; FILE *conf_file; FILE *channels_diff; FILE *channels_not_streamed; #ifdef ENABLE_CAM_SUPPORT FILE *cam_info; #endif FILE *pidfile; char *dump_filename = NULL; FILE *dump_file; int listingcards=0; //Getopt parse_cmd_line(argc,argv, &conf_filename, &tune_p, &stats_infos, &server_id, &no_daemon, &dump_filename, &listingcards); //List the detected cards if(listingcards) { print_info (); list_dvb_cards (); exit(0); } // DO NOT REMOVE (make MuMuDVB a deamon) if(!no_daemon) if(daemon(42,0)) { log_message( log_module, MSG_WARN, "Cannot daemonize: %s\n", strerror (errno)); exit(666); //Right code for a bad daemon no ? } //If the user didn't defined a preferred logging way, and we daemonize, we set to syslog if (!no_daemon) { if(log_params.log_type==LOGGING_UNDEFINED) { openlog ("MUMUDVB", LOG_PID, 0); log_params.log_type=LOGGING_SYSLOG; log_params.syslog_initialised=1; } } //Display general information print_info (); // configuration file parsing int ichan = 0; int ipid = 0; int send_packet=0; char current_line[CONF_LINELEN]; char *substring=NULL; char delimiteurs[] = CONFIG_FILE_SEPARATOR; /******************************************************/ // config file displaying /******************************************************/ if (conf_filename == NULL) { log_message( log_module, MSG_ERROR, "No configuration file specified"); exit(ERROR_CONF_FILE); } conf_file = fopen (conf_filename, "r"); if (conf_file == NULL) { log_message( log_module, MSG_ERROR, "%s: %s\n", conf_filename, strerror (errno)); free(conf_filename); exit(ERROR_CONF_FILE); } log_message( log_module, MSG_FLOOD,"==== Configuration file ===="); int line_num=1; while (fgets (current_line, CONF_LINELEN, conf_file)) { int line_len; //We suppress the end of line line_len=strlen(current_line); if(current_line[line_len-1]=='\r' ||current_line[line_len-1]=='\n') current_line[line_len-1]=0; log_message( log_module, MSG_FLOOD,"%03d %s\n",line_num,current_line); line_num++; } log_message( log_module, MSG_FLOOD,"============ done ===========\n"); fclose (conf_file); /******************************************************/ // config file reading /******************************************************/ conf_file = fopen (conf_filename, "r"); if (conf_file == NULL) { log_message( log_module, MSG_ERROR, "%s: %s\n", conf_filename, strerror (errno)); free(conf_filename); exit(ERROR_CONF_FILE); } ichan=-1; mumudvb_channel_t *c_chan; int curr_channel_old=-1; // we scan config file // see doc/README_CONF* for further information int line_len; while (fgets (current_line, CONF_LINELEN, conf_file)) { //We suppress the end of line (this can disturb atoi if there is spaces at the end of the line) //Thanks to Pierre Gronlier pierre.gronlier at gmail.com for finding that bug line_len=strlen(current_line); if(current_line[line_len-1]=='\r' ||current_line[line_len-1]=='\n') current_line[line_len-1]=0; //Line without "=" we continue if(strstr(current_line,"=")==NULL) { //We check if it's not a new_channel line substring = strtok (current_line, delimiteurs); //If nothing in the substring we avoid the segfault in the next line if(substring == NULL) continue; if(strcmp (substring, "new_channel") ) continue; } //commentary if (current_line[0] == '#') continue; //We split the line substring = strtok (current_line, delimiteurs); //If nothing in the substring we avoid the segfault in the next line if(substring == NULL) continue; //commentary if (substring[0] == '#') continue; if(ichan<0) c_chan=NULL; else c_chan=&chan_p.channels[ichan]; if((iRet=read_tuning_configuration(&tune_p, substring))) //Read the line concerning the tuning parameters { if(iRet==-1) exit(ERROR_CONF); } else if((iRet=read_autoconfiguration_configuration(&auto_p, substring))) //Read the line concerning the autoconfiguration parameters { if(iRet==-1) exit(ERROR_CONF); } else if((iRet=read_sap_configuration(&sap_p, c_chan, substring))) //Read the line concerning the sap parameters { if(iRet==-1) exit(ERROR_CONF); } #ifdef ENABLE_CAM_SUPPORT else if((iRet=read_cam_configuration(&cam_p, c_chan, substring))) //Read the line concerning the cam parameters { if(iRet==-1) exit(ERROR_CONF); } #endif #ifdef ENABLE_SCAM_SUPPORT else if((iRet=read_scam_configuration(scam_vars_ptr, c_chan, substring))) //Read the line concerning the software cam parameters { if(iRet==-1) exit(ERROR_CONF); } #endif else if((iRet=read_unicast_configuration(&unic_p, c_chan, substring))) //Read the line concerning the unicast parameters { if(iRet==-1) exit(ERROR_CONF); } else if((iRet=read_multicast_configuration(&multi_p, c_chan, substring))) //Read the line concerning the multicast parameters { if(iRet==-1) exit(ERROR_CONF); } else if((iRet=read_rewrite_configuration(&rewrite_vars, substring))) //Read the line concerning the rewrite parameters { if(iRet==-1) exit(ERROR_CONF); } else if((iRet=read_logging_configuration(&stats_infos, substring))) //Read the line concerning the logging parameters { if(iRet==-1) exit(ERROR_CONF); } else if (!strcmp (substring, "new_channel")) { ichan++; chan_p.channels[ichan].channel_ready=ALMOST_READY; log_message( log_module, MSG_INFO,"New channel, current number %d", ichan); } else if (!strcmp (substring, "timeout_no_diff")) { substring = strtok (NULL, delimiteurs); timeout_no_diff= atoi (substring); } else if (!strcmp (substring, "dont_send_scrambled")) { substring = strtok (NULL, delimiteurs); dont_send_scrambled = atoi (substring); } else if (!strcmp (substring, "filter_transport_error")) { substring = strtok (NULL, delimiteurs); chan_p.filter_transport_error = atoi (substring); } else if (!strcmp (substring, "psi_tables_filtering")) { substring = strtok (NULL, delimiteurs); if (!strcmp (substring, "pat")) chan_p.psi_tables_filtering = PSI_TABLES_FILTERING_PAT_ONLY; else if (!strcmp (substring, "pat_cat")) chan_p.psi_tables_filtering = PSI_TABLES_FILTERING_PAT_CAT_ONLY; else if (!strcmp (substring, "none")) chan_p.psi_tables_filtering = PSI_TABLES_FILTERING_NONE; if (chan_p.psi_tables_filtering == PSI_TABLES_FILTERING_PAT_ONLY) log_message( log_module, MSG_INFO, "You have enabled PSI tables filtering, only PAT will be send\n"); if (chan_p.psi_tables_filtering == PSI_TABLES_FILTERING_PAT_CAT_ONLY) log_message( log_module, MSG_INFO, "You have enabled PSI tables filtering, only PAT and CAT will be send\n"); } else if (!strcmp (substring, "dvr_buffer_size")) { substring = strtok (NULL, delimiteurs); card_buffer.dvr_buffer_size = atoi (substring); if(card_buffer.dvr_buffer_size<=0) { log_message( log_module, MSG_WARN, "The buffer size MUST be >0, forced to 1 packet\n"); card_buffer.dvr_buffer_size = 1; } stats_infos.show_buffer_stats=1; } else if (!strcmp (substring, "dvr_thread")) { substring = strtok (NULL, delimiteurs); card_buffer.threaded_read = atoi (substring); if(card_buffer.threaded_read) { log_message( log_module, MSG_WARN, "You want to use a thread for reading the card, please report bugs/problems\n"); } } else if (!strcmp (substring, "dvr_thread_buffer_size")) { substring = strtok (NULL, delimiteurs); card_buffer.max_thread_buffer_size = atoi (substring); } else if ((!strcmp (substring, "service_id")) || (!strcmp (substring, "ts_id"))) { if(!strcmp (substring, "ts_id")) log_message( log_module, MSG_WARN, "The option ts_id is depreciated, use service_id instead.\n"); if ( c_chan == NULL) { log_message( log_module, MSG_ERROR, "service_id : You have to start a channel first (using new_channel)\n"); exit(ERROR_CONF); } substring = strtok (NULL, delimiteurs); c_chan->service_id = atoi (substring); } else if (!strcmp (substring, "pids")) { ipid = 0; if ( c_chan == NULL) { log_message( log_module, MSG_ERROR, "pids : You have to start a channel first (using new_channel)\n"); exit(ERROR_CONF); } //Pids are now user set, they won't be overwritten by autoconfiguration c_chan->pid_i.pid_f=F_USER; //Enable PMT rewrite c_chan->pmt_rewrite = 1; while ((substring = strtok (NULL, delimiteurs)) != NULL) { c_chan->pid_i.pids[ipid] = atoi (substring); // we see if the given pid is good if (c_chan->pid_i.pids[ipid] < 10 || c_chan->pid_i.pids[ipid] >= 8193) { log_message( log_module, MSG_ERROR, "Config issue : %s in pids, given pid : %d\n", conf_filename, c_chan->pid_i.pids[ipid]); exit(ERROR_CONF); } ipid++; if (ipid >= MAX_PIDS) { log_message( log_module, MSG_ERROR, "Too many pids : %d channel : %d\n", ipid, ichan); exit(ERROR_CONF); } } c_chan->pid_i.num_pids = ipid; } else if (!strcmp (substring, "pmt_pid")) { if ( c_chan == NULL) { log_message( log_module, MSG_ERROR, "pmt_pid : You have to start a channel first (using new_channel)\n"); return -1; } substring = strtok (NULL, delimiteurs); c_chan->pid_i.pmt_pid = atoi (substring); if (c_chan->pid_i.pmt_pid < 10 || c_chan->pid_i.pmt_pid > 8191){ log_message( log_module, MSG_ERROR, "Configuration issue in pmt_pid, given PID : %d\n", c_chan->pid_i.pmt_pid); return -1; } MU_F(c_chan->pid_i.pmt_pid)=F_USER; } else if (!strcmp (substring, "name")) { if ( c_chan == NULL) { log_message( log_module, MSG_ERROR, "name : You have to start a channel first (using new_channel)\n"); exit(ERROR_CONF); } //name is now user set MU_F(c_chan->name)=F_USER; // other substring extraction method in order to keep spaces substring = strtok (NULL, "="); strncpy(c_chan->name,strtok(substring,"\n"),MAX_NAME_LEN-1); c_chan->name[MAX_NAME_LEN-1]='\0'; //We store the user name for being able to use templates strncpy(c_chan->user_name,strtok(substring,"\n"),MAX_NAME_LEN-1); c_chan->user_name[MAX_NAME_LEN-1]='\0'; if (strlen (substring) >= MAX_NAME_LEN - 1) log_message( log_module, MSG_WARN,"Channel name too long\n"); } else if (!strcmp (substring, "server_id")) { substring = strtok (NULL, delimiteurs); server_id = atoi (substring); } else if (!strcmp (substring, "filename_pid")) { substring = strtok (NULL, delimiteurs); if(strlen(substring)>=DEFAULT_PATH_LEN) { log_message(log_module,MSG_WARN,"filename_pid too long \n"); } else strcpy(filename_pid,substring); } else if (!strcmp (substring, "check_cc")) { substring = strtok (NULL, delimiteurs); chan_p.check_cc = atoi (substring); } else { if(strlen (current_line) > 1) log_message( log_module, MSG_WARN, "Config issue : unknow symbol : %s\n\n", substring); continue; } if (ichan > MAX_CHANNELS) { log_message( log_module, MSG_ERROR, "Too many channels : %d limit : %d\n", ichan, MAX_CHANNELS); exit(ERROR_TOO_CHANNELS); } //A new channel have been defined if(curr_channel_old != ichan) { curr_channel_old = ichan; } } fclose (conf_file); free(conf_filename); //Set default card if not specified if(tune_p.card==-1) tune_p.card=0; /*************************************/ //End of configuration file reading /*************************************/ //if Autoconfiguration, we set other option default if(auto_p.autoconfiguration!=AUTOCONF_MODE_NONE) { if((sap_p.sap == OPTION_UNDEFINED) && (multi_p.multicast)) { log_message( log_module, MSG_INFO, "Autoconfiguration, we activate SAP announces. if you want to disable them see the README.\n"); sap_p.sap=OPTION_ON; } if(rewrite_vars.rewrite_pat == OPTION_UNDEFINED) { rewrite_vars.rewrite_pat=OPTION_ON; log_message( log_module, MSG_INFO, "Autoconfiguration, we activate PAT rewriting. if you want to disable it see the README.\n"); } if(rewrite_vars.rewrite_sdt == OPTION_UNDEFINED) { rewrite_vars.rewrite_sdt=OPTION_ON; log_message( log_module, MSG_INFO, "Autoconfiguration, we activate SDT rewriting. if you want to disable it see the README.\n"); } } if(card_buffer.max_thread_buffer_size 1? 's':' '); printf("%s %p\n", __func__, &chan_p); /******************************************************/ // Monitor Thread /******************************************************/ monitor_parameters_t monitor_thread_params ={ .threadshutdown=0, .wait_time=10, .auto_p=&auto_p, .sap_p=&sap_p, .chan_p=&chan_p, .multi_p=&multi_p, .unicast_vars=&unic_p, .tune_p=&tune_p, .stats_infos=&stats_infos, #ifdef ENABLE_SCAM_SUPPORT .scam_vars_v=scam_vars_ptr, #endif .server_id=server_id, .filename_channels_not_streamed=filename_channels_not_streamed, .filename_channels_streamed=filename_channels_streamed, }; pthread_create(&(monitorthread), NULL, monitor_func, &monitor_thread_params); /*****************************************************/ //scam_support /*****************************************************/ #ifdef ENABLE_SCAM_SUPPORT if(scam_vars.scam_support){ if(scam_getcw_start(scam_vars_ptr, &chan_p)) { log_message("SCAM_GETCW: ", MSG_ERROR,"Cannot initialize scam"); scam_vars.scam_support=0; } else { //If the scam is properly initialized, we autoconfigure scrambled channels auto_p.autoconf_scrambled=1; } } #endif /*****************************************************/ //cam_support /*****************************************************/ #ifdef ENABLE_CAM_SUPPORT if(cam_p.cam_support){ //We initialize the cam. If fail, we remove cam support if(cam_start(&cam_p,tune_p.card,&chan_p)) { log_message("CAM: ", MSG_ERROR,"Cannot initalise cam\n"); cam_p.cam_support=0; } else { //If the cam is properly initialized, we autoconfigure scrambled channels auto_p.autoconf_scrambled=1; } } #endif /*****************************************************/ //autoconfiguration //memory allocation for MPEG2-TS //packet structures /*****************************************************/ iRet=autoconf_init(&auto_p); if(iRet) { set_interrupted(ERROR_GENERIC<<8); goto mumudvb_close_goto; } #ifdef ENABLE_SCAM_SUPPORT /*****************************************************/ //scam /*****************************************************/ if (auto_p.autoconfiguration==AUTOCONF_MODE_NONE) scam_init_no_autoconf(scam_vars_ptr, chan_p.channels,chan_p.number_of_channels); #endif /*****************************************************/ //Rewriting initialization and allocation /*****************************************************/ if(rewrite_init(&rewrite_vars)) goto mumudvb_close_goto; /*****************************************************/ //Some initializations /*****************************************************/ if(multi_p.rtp_header) multi_p.num_pack=(MAX_UDP_SIZE-TS_PACKET_SIZE)/TS_PACKET_SIZE; else multi_p.num_pack=(MAX_UDP_SIZE)/TS_PACKET_SIZE; // initialization of active channels list pthread_mutex_lock(&chan_p.lock); for (ichan = 0; ichan < chan_p.number_of_channels; ichan++) { if(mumu_init_chan(&chan_p.channels[ichan])<0) goto mumudvb_close_goto; } pthread_mutex_unlock(&chan_p.lock); //We initialize asked PID table memset (chan_p.asked_pid, 0, sizeof( uint8_t)*8193);//we clear it // We initialize the table for checking the TS discontinuities for (ipid = 0; ipid < 8193; ipid++) chan_p.continuity_counter_pid[ipid]=-1; //We initialize mandatory PID table memset (mandatory_pid, 0, sizeof( uint8_t)*MAX_MANDATORY_PID_NUMBER);//we clear it //mandatory PIDs (always sent with all channels) //PAT : Program Association Table mandatory_pid[0]=1; //CAT : Conditional Access Table mandatory_pid[1]=1; //NIT : Network Information Table //It is intended to provide information about the physical network. mandatory_pid[16]=1; //SDT : Service Description Table //the SDT contains data describing the services in the system e.g. names of services, the service provider, etc. mandatory_pid[17]=1; //EIT : Event Information Table //the EIT contains data concerning events or programs such as event name, start time, duration, etc. mandatory_pid[18]=1; //TDT : Time and Date Table //the TDT gives information relating to the present time and date. //This information is given in a separate table due to the frequent updating of this information. mandatory_pid[20]=1; for (ipid = 0; ipid < 21; ipid++) if(mandatory_pid[ipid]) chan_p.asked_pid[ipid]=PID_ASKED; //PSIP : Program and System Information Protocol //Specific to ATSC, this is more or less the equivalent of sdt plus other stuff if(tune_p.fe_type==FE_ATSC) chan_p.asked_pid[PSIP_PID]=PID_ASKED; /*****************************************************/ //Set the filters /*****************************************************/ update_chan_filters(&chan_p, tune_p.card_dev_path, tune_p.tuner, &fds); //We take care of the poll descriptors fds.pfds=NULL; fds.pfdsnum=1; //+1 for closing the pfd list, see man poll fds.pfds=realloc(fds.pfds,(fds.pfdsnum+1)*sizeof(struct pollfd)); if (fds.pfds==NULL) { log_message( log_module, MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); set_interrupted(ERROR_MEMORY<<8); goto mumudvb_close_goto; } //We fill the file descriptor information structure. the first one is irrelevant unic_p.fd_info=NULL; unic_p.fd_info=realloc(unic_p.fd_info,(fds.pfdsnum)*sizeof(unicast_fd_info_t)); if (unic_p.fd_info==NULL) { log_message( log_module, MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); set_interrupted(ERROR_MEMORY<<8); goto mumudvb_close_goto; } //File descriptor for polling the DVB card fds.pfds[0].fd = fds.fd_dvr; //POLLIN : data available for read fds.pfds[0].events = POLLIN | POLLPRI; fds.pfds[0].revents = 0; fds.pfds[1].fd = 0; fds.pfds[1].events = POLLIN | POLLPRI; fds.pfds[1].revents = 0; /*****************************************************/ // Init network, we open the sockets /*****************************************************/ //We open the socket for the http unicast if needed and we update the poll structure if(unic_p.unicast) { log_message("Unicast: ", MSG_INFO,"We open the Master http socket for address %s:%d\n",unic_p.ipOut, unic_p.portOut); unicast_create_listening_socket(UNICAST_MASTER, -1, unic_p.ipOut, unic_p.portOut, &unic_p.sIn, &unic_p.socketIn, &unic_p); } update_chan_net(&chan_p, &auto_p, &multi_p, &unic_p, server_id, tune_p.card, tune_p.tuner); /*****************************************************/ // init sap /*****************************************************/ iRet=init_sap(&sap_p, multi_p); if(iRet) { set_interrupted(ERROR_GENERIC<<8); goto mumudvb_close_goto; } /*****************************************************/ // Information about streamed channels /*****************************************************/ if(auto_p.autoconfiguration==AUTOCONF_MODE_NONE) log_streamed_channels(log_module, chan_p.number_of_channels, chan_p.channels, multi_p.multicast_ipv4, multi_p.multicast_ipv6, unic_p.unicast, unic_p.portOut, unic_p.ipOut); if(auto_p.autoconfiguration) log_message("Autoconf: ",MSG_INFO,"Autoconfiguration is now ready to work for you !"); //Thread for reading from the DVB card RUNNING if(card_buffer.threaded_read) { pthread_create(&(cardthread), NULL, read_card_thread_func, &cardthreadparams); //We alloc the buffers card_buffer.write_buffer_size=card_buffer.max_thread_buffer_size*TS_PACKET_SIZE; card_buffer.buffer1=malloc(sizeof(unsigned char)*card_buffer.write_buffer_size); card_buffer.buffer2=malloc(sizeof(unsigned char)*card_buffer.write_buffer_size); card_buffer.actual_read_buffer=1; card_buffer.reading_buffer=card_buffer.buffer1; card_buffer.writing_buffer=card_buffer.buffer2; cardthreadparams.main_waiting=0; }else { //We alloc the buffer card_buffer.reading_buffer=malloc(sizeof(unsigned char)*TS_PACKET_SIZE*card_buffer.dvr_buffer_size); } /******************************************************/ //We open the dump file if any /******************************************************/ dump_file = NULL; if(dump_filename) { dump_file = fopen (dump_filename, "w"); if (dump_file == NULL) { log_message( log_module, MSG_ERROR, "%s: %s\n", dump_filename, strerror (errno)); free(dump_filename); } } #ifndef ANDROID mlockall(MCL_CURRENT | MCL_FUTURE); #endif /******************************************************/ //Main loop where we get the packets and send them /******************************************************/ int poll_ret; /**Buffer containing one packet*/ unsigned char *actual_ts_packet; /**We must get a little bit special for PMT rewrite*/ unsigned char pmt_ts_packet[TS_PACKET_SIZE]; while (!get_interrupted()) { if(card_buffer.threaded_read) { if(!card_buffer.bytes_in_write_buffer) { pthread_mutex_lock(&cardthreadparams.carddatamutex); cardthreadparams.main_waiting=1; pthread_cond_wait(&cardthreadparams.threadcond,&cardthreadparams.carddatamutex); cardthreadparams.main_waiting=0; } else pthread_mutex_lock(&cardthreadparams.carddatamutex); if(card_buffer.bytes_in_write_buffer) { if(card_buffer.actual_read_buffer==1) { card_buffer.reading_buffer=card_buffer.buffer2; card_buffer.writing_buffer=card_buffer.buffer1; card_buffer.actual_read_buffer=2; } else { card_buffer.reading_buffer=card_buffer.buffer1; card_buffer.writing_buffer=card_buffer.buffer2; card_buffer.actual_read_buffer=1; } card_buffer.bytes_read=card_buffer.bytes_in_write_buffer; card_buffer.bytes_in_write_buffer=0; } pthread_mutex_unlock(&cardthreadparams.carddatamutex); /**************************************************************/ /* UNICAST HTTP */ /**************************************************************/ if(unic_p.pfdsnum) { if(mumudvb_poll(unic_p.pfds,unic_p.pfdsnum,0)>0) { iRet=unicast_handle_fd_event(&unic_p, chan_p.channels, chan_p.number_of_channels, &strengthparams, &auto_p, cam_p_ptr, scam_vars_ptr, rewrite_vars.eit_packets); if(iRet) { log_message( log_module, MSG_ERROR, "unicast fd error %d", iRet); set_interrupted(iRet); } } } /**************************************************************/ /* END OF UNICAST HTTP */ /**************************************************************/ } else { /* Poll the open file descriptors : we wait for data*/ poll_ret=mumudvb_poll(fds.pfds,fds.pfdsnum,DVB_POLL_TIMEOUT); if(poll_ret<0) { log_message( log_module, MSG_ERROR, "Poll error %d", poll_ret); set_interrupted(poll_ret); continue; } /**************************************************************/ /* UNICAST HTTP */ /**************************************************************/ if(unic_p.pfdsnum) { poll_ret=mumudvb_poll(unic_p.pfds,unic_p.pfdsnum,0); if(poll_ret>0) { iRet=unicast_handle_fd_event(&unic_p, chan_p.channels, chan_p.number_of_channels, &strengthparams, &auto_p, cam_p_ptr, scam_vars_ptr,rewrite_vars.eit_packets); if(iRet) { log_message( log_module, MSG_ERROR, "unicast fd error %d", iRet); set_interrupted(iRet); } } } /**************************************************************/ /* END OF UNICAST HTTP */ /**************************************************************/ if((card_buffer.bytes_read=card_read(fds.fd_dvr, card_buffer.reading_buffer, &card_buffer))==0) continue; } if(card_buffer.dvr_buffer_size!=1 && stats_infos.show_buffer_stats) { stats_infos.stats_num_packets_received+=(int) card_buffer.bytes_read/TS_PACKET_SIZE; stats_infos.stats_num_reads++; } for(card_buffer.read_buff_pos=0; (card_buffer.read_buff_pos+TS_PACKET_SIZE)<=card_buffer.bytes_read; card_buffer.read_buff_pos+=TS_PACKET_SIZE)//we loop on the subpackets { actual_ts_packet=card_buffer.reading_buffer+card_buffer.read_buff_pos; //If the user asked to dump the streams it's here that it should be done if(dump_file) if(fwrite(actual_ts_packet,sizeof(unsigned char),TS_PACKET_SIZE,dump_file)0) continue; } // Get the PID of the received TS packet pid = ((actual_ts_packet[1] & 0x1f) << 8) | (actual_ts_packet[2]); // Check the continuity if(chan_p.check_cc) { continuity_counter=actual_ts_packet[3] & 0x0f; if (chan_p.continuity_counter_pid[pid]!=-1 && chan_p.continuity_counter_pid[pid]!=continuity_counter && ((chan_p.continuity_counter_pid[pid]+1) & 0x0f)!=continuity_counter) strengthparams.ts_discontinuities++; chan_p.continuity_counter_pid[pid]=continuity_counter; } //Software filtering in case the card doesn't have hardware filtering if(chan_p.asked_pid[8192]==PID_NOT_ASKED && chan_p.asked_pid[pid]==PID_NOT_ASKED) continue; ScramblingControl = (actual_ts_packet[3] & 0xc0) >> 6; /* 0 = Not scrambled 1 = Reserved for future use 2 = Scrambled with even key 3 = Scrambled with odd key*/ /******************************************************/ // PMT UPDATE PART: Autoconf, CAM, SCAM /******************************************************/ chan_new_pmt(actual_ts_packet, &chan_p, pid); /******************************************************/ // PMT UPDATE PART FINISHED /******************************************************/ /******************************************************/ // AUTOCONFIGURATION PART /******************************************************/ if(!ScramblingControl && auto_p.autoconfiguration) { iRet = autoconf_new_packet(pid, actual_ts_packet, &auto_p, &fds, &chan_p, &tune_p, &multi_p, &unic_p, server_id, scam_vars_ptr); if(iRet) { log_message( log_module, MSG_ERROR, "Autoconf error %d", iRet); set_interrupted(iRet); } } /******************************************************/ // AUTOCONFIGURATION PART FINISHED /******************************************************/ /******************************************************/ //Pat rewrite /******************************************************/ if( (pid == 0) && //This is a PAT PID rewrite_vars.rewrite_pat == OPTION_ON ) //AND we asked for rewrite { pat_rewrite_new_global_packet(actual_ts_packet, &rewrite_vars); } /******************************************************/ //SDT rewrite /******************************************************/ if( (pid == 17) && //This is a SDT PID rewrite_vars.rewrite_sdt == OPTION_ON ) //AND we asked for rewrite { //we check the new packet and if it's fully updated we set the skip to 0 if(sdt_rewrite_new_global_packet(actual_ts_packet, &rewrite_vars)==1) { log_message( log_module, MSG_DETAIL,"The SDT version changed, we force the update of all the channels.\n"); for (ichan = 0; ichan < chan_p.number_of_channels; ichan++) chan_p.channels[ichan].sdt_rewrite_skip=0; //no lock needed, accessed only by main thread } } /******************************************************/ //EIT rewrite /******************************************************/ if( (pid == 18) && //This is an EIT PID (rewrite_vars.rewrite_eit == OPTION_ON || //AND we asked for rewrite rewrite_vars.store_eit == OPTION_ON )) //OR to store it { eit_rewrite_new_global_packet(actual_ts_packet, &rewrite_vars); } /******************************************************/ //for each channel we'll look if we must send this PID /******************************************************/ pthread_mutex_lock(&chan_p.lock); for (ichan = 0; ichan < chan_p.number_of_channels; ichan++) { //We test if the channel is ready (manually configured or autoconf) if(!(chan_p.channels[ichan].channel_ready>0)) continue; //we'll see if we must send this PID for this channel send_packet=0; //If it's a mandatory PID we send it if((pid=cam_p.cam_interval_pmt_send )) { if(cam_new_packet(pid, ichan, &cam_p, &chan_p.channels[ichan])) cam_p.cam_pmt_send_time=now; //A packet was sent to the CAM } #endif /******************************************************/ //Scam support // copy proper pmt to scam_pmt_packet /******************************************************/ #ifdef ENABLE_SCAM_SUPPORT if (scam_vars.scam_support && send_packet==1) //no need to check packets we don't send { scam_new_packet(pid, &chan_p.channels[ichan]); } #endif /******************************************************/ //Rewrite PMT /******************************************************/ if((send_packet==1) && //no need to check packets we don't send (pid == chan_p.channels[ichan].pid_i.pmt_pid) && //This is a PMT PID (chan_p.channels[ichan].pid_i.pmt_pid) && //we have the pmt_pid (rewrite_vars.rewrite_pmt == OPTION_ON ) && //AND we asked for rewrite (chan_p.channels[ichan].pmt_rewrite == 1)) //AND this channel's PMT shouldn't be skipped { send_packet=pmt_rewrite_new_channel_packet(actual_ts_packet, pmt_ts_packet, &chan_p.channels[ichan], ichan); } /******************************************************/ //Rewrite PAT /******************************************************/ if((send_packet==1) && //no need to check packets we don't send (pid == 0) && //This is a PAT PID rewrite_vars.rewrite_pat == OPTION_ON ) //AND we asked for rewrite send_packet=pat_rewrite_new_channel_packet(actual_ts_packet, &rewrite_vars, &chan_p.channels[ichan], ichan); /******************************************************/ //Rewrite SDT /******************************************************/ if((send_packet==1) && //no need to check packets we don't send (pid == 17) && //This is a SDT PID rewrite_vars.rewrite_sdt == OPTION_ON && //AND we asked for rewrite !chan_p.channels[ichan].sdt_rewrite_skip ) //AND the generation was successful send_packet=sdt_rewrite_new_channel_packet(actual_ts_packet, &rewrite_vars, &chan_p.channels[ichan], ichan); /******************************************************/ //Rewrite EIT /******************************************************/ if((send_packet==1) &&//no need to check packets we don't send (pid == 18) && //This is a EIT PID (chan_p.channels[ichan].service_id) && //we have the service_id rewrite_vars.rewrite_eit == OPTION_ON) //AND we asked for EIT sorting { eit_rewrite_new_channel_packet(actual_ts_packet, &rewrite_vars, &chan_p.channels[ichan], &unic_p, scam_vars_ptr); send_packet=0; //for EIT it is sent by the rewrite function itself } /******************************************************/ // Test if PSI tables filtering is activated /******************************************************/ if (send_packet==1 && chan_p.psi_tables_filtering>0 && pid<32) { // Keep only PAT and CAT if (chan_p.psi_tables_filtering==1 && pid>1) send_packet=0; // Keep only PAT if (chan_p.psi_tables_filtering==2 && pid>0) send_packet=0; } mumudvb_channel_t *channel = &chan_p.channels[ichan]; /******************************************************/ //Ok we must send this packet, // we add it to the channel buffer /******************************************************/ if(send_packet==1) { /**Special PMT case*/ if((pid == chan_p.channels[ichan].pid_i.pmt_pid) && (rewrite_vars.rewrite_pmt == OPTION_ON ) && (chan_p.channels[ichan].pmt_rewrite == 1)) buffer_func(channel, pmt_ts_packet, &unic_p, scam_vars_ptr); else buffer_func(channel, actual_ts_packet, &unic_p, scam_vars_ptr); } } pthread_mutex_unlock(&chan_p.lock); } } /******************************************************/ //End of main loop /******************************************************/ if(dump_file) fclose(dump_file); gettimeofday (&tv, (struct timezone *) NULL); log_message( log_module, MSG_INFO, "End of streaming. We streamed during %ldd %ld:%02ld:%02ld\n",(tv.tv_sec - real_start_time )/86400,((tv.tv_sec - real_start_time) % 86400 )/3600,((tv.tv_sec - real_start_time) % 3600)/60,(tv.tv_sec - real_start_time) %60 ); if(card_buffer.partial_packet_number) log_message( log_module, MSG_INFO, "We received %d partial packets :-( \n",card_buffer.partial_packet_number ); if(card_buffer.overflow_number) log_message( log_module, MSG_INFO, "We have got %d overflow errors\n",card_buffer.overflow_number ); mumudvb_close_goto: //If the thread is not started, we don't send the nonexistent address of monitor_thread_params return mumudvb_close(no_daemon, monitorthread == 0 ? NULL:&monitor_thread_params, &rewrite_vars, &auto_p, &unic_p, &tune_p.strengththreadshutdown, cam_p_ptr, scam_vars_ptr, filename_channels_not_streamed, filename_channels_streamed, filename_pid, get_interrupted(), &chan_p, &signalpowerthread, &monitorthread, &cardthreadparams, &fds); } /****************************************************** * Signal Handler Function * * This function is called periodically * It checks for the tuning timeouts * * This function also catches SIGPIPE, SIGUSR1, SIGUSR2 and SIGHUP * ******************************************************/ static void SignalHandler (int signum) { if (signum == SIGALRM && !get_interrupted()) { if (card_tuned && !*card_tuned) { log_message( log_module, MSG_INFO, "Card not tuned after timeout - exiting\n"); exit(ERROR_TUNE); } } else if (signum == SIGUSR1 || signum == SIGUSR2 || signum == SIGHUP) { received_signal=signum; } else if (signum != SIGPIPE) { log_message( log_module, MSG_ERROR, "Caught signal %d", signum); set_interrupted(signum); } signal (signum, SignalHandler); } MuMuDVB-2.1.0/src/mumudvb.h000066400000000000000000000412551305714132500153600ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * Based on dvbstream by (C) Dave Chapman 2001, 2002. * * (C) 2004-2010 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /**@file * @brief Global parameters and structures */ #ifndef _MUMUDVB_H #define _MUMUDVB_H #include "network.h" //for the sockaddr #include "ts.h" #include "config.h" #include #include #define MAX_FILENAME_LEN 256 #define IPV6_CHAR_LEN 64 /*Do we support ATSC ?*/ #undef ATSC #if defined(DVB_API_VERSION_MINOR) #if DVB_API_VERSION == 3 && DVB_API_VERSION_MINOR >= 1 #define ATSC 1 #endif #endif #if DVB_API_VERSION > 3 #define ATSC 1 #endif /*Do we support DVBT2 ?*/ #undef DVBT2 #if defined(DVB_API_VERSION_MINOR) #if DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 3 #define DVBT2 1 #endif #endif #if DVB_API_VERSION >= 6 #define DVBT2 1 #endif /**the number of pids by channel*/ #define MAX_PIDS 128 /**the maximum channel number*/ #define MAX_CHANNELS 128 /**Size of an MPEG2-TS packet*/ #define TS_PACKET_SIZE 188 /**Default Maximum Number of TS packets in the TS buffer*/ #define DEFAULT_TS_BUFFER_SIZE 20 /**Default Maximum Number of TS packets in the thread buffer*/ #define DEFAULT_THREAD_BUFFER_SIZE 5000 #define ALARM_TIME_TIMEOUT 60 #define ALARM_TIME_TIMEOUT_NO_DIFF 600 /** MTU 1500 bytes - ip header (12bytes) - TCP header (biggest between TCP and udp) 24 : 7 mpeg2-ts packet per ethernet frame We cannot discover easily the MTU with unconnected UDP http://linuxgazette.net/149/melinte.html 7*188 plus margin */ #define MAX_UDP_SIZE 1320 /**the max mandatory pid number*/ #define MAX_MANDATORY_PID_NUMBER 32 /**config line length*/ #define CONF_LINELEN 512 #define MAX_NAME_LEN 512 #define CONFIG_FILE_SEPARATOR " =" /**Maximum number of polling tries (excepted EINTR)*/ #define MAX_POLL_TRIES 5 #define DEFAULT_PATH_LEN 256 /**The path for the auto generated config file*/ #define GEN_CONF_PATH "/var/run/mumudvb/mumudvb_generated_conf_card%d_tuner%d" /**The path for the list of streamed channels*/ #define STREAMED_LIST_PATH "/var/run/mumudvb/channels_streamed_adapter%d_tuner%d" /**The path for the list of *not* streamed channels*/ #define NOT_STREAMED_LIST_PATH "/var/run/mumudvb/channels_unstreamed_adapter%d_tuner%d" /**The path for the cam_info*/ #define CAM_INFO_LIST_PATH "/var/run/mumudvb/caminfo_adapter%d_tuner%d" /** The path for the pid file */ #define PIDFILE_PATH "/var/run/mumudvb/mumudvb_adapter%card_tuner%tuner.pid" /**RTP header length*/ #define RTP_HEADER_LEN 12 #define SAP_GROUP_LENGTH 20 enum { FULLY_UNSCRAMBLED=0, PARTIALLY_UNSCRAMBLED, HIGHLY_SCRAMBLED }; //for need_cam_ask enum { CAM_NO_ASK=0, CAM_NEED_ASK, CAM_NEED_UPDATE, CAM_ASKED }; /** Enum to tell if the option is set*/ typedef enum option_status { OPTION_UNDEFINED, OPTION_OFF, OPTION_ON } option_status_t; /** Enum to tell if a channel parameter is user set or autodetected, to avoid erasing of user set params*/ typedef enum mumu_f { F_UNDEF, F_USER, F_DETECTED } mumu_f_t; //Macro helpers to specify if a channel variable is UNDEF:USER_DEFINED:AUTODETECTED #define MU_F_V(type, x) type x; mumu_f_t x##_f; #define MU_F_T(x) mumu_f_t x##_f; #define MU_F(x) x##_f /** The different PID types*/ enum { PID_UNKNOW=0, PID_PMT, PID_PCR, PID_VIDEO_MPEG1, PID_VIDEO_MPEG2, PID_VIDEO_MPEG4_ASP, PID_VIDEO_MPEG4_AVC, PID_VIDEO_MPEG4_HEVC, PID_AUDIO_MPEG1, PID_AUDIO_MPEG2, PID_AUDIO_AAC_LATM, PID_AUDIO_AAC_ADTS, PID_AUDIO_ATSC, PID_AUDIO_AC3, PID_AUDIO_EAC3, PID_AUDIO_DTS, PID_AUDIO_AAC, PID_EXTRA_VBIDATA, PID_EXTRA_VBITELETEXT, PID_EXTRA_TELETEXT, PID_EXTRA_SUBTITLE, PID_ECM }; /**@brief file descriptors*/ typedef struct { /** the dvb dvr*/ int fd_dvr; /** the dvb frontend*/ int fd_frontend; /** demuxer file descriptors */ int fd_demuxer[8193]; /** poll file descriptors */ struct pollfd *pfds; // DVR device int pfdsnum; }fds_t; #ifdef ENABLE_SCAM_SUPPORT /**@brief Structure containing ring buffer*/ typedef struct { /** A mutex protecting all the other members. */ pthread_mutex_t lock; /** Buffer with dvb packets*/ unsigned char * data; /** Write index of buffer */ unsigned int write_idx; /** Buffer with descrambling timestamps*/ uint64_t * time_decsa; /** Number of packets left to descramble*/ unsigned int to_descramble; /** Read index of buffer for descrambling thread */ unsigned int read_decsa_idx; /** Buffer with sending timestamps*/ uint64_t * time_send; /** Number of packets left to send*/ unsigned int to_send; /** Read index of buffer for sending thread */ unsigned int read_send_idx; }ring_buffer_t; #endif /**@brief Structure containing the card buffers*/ typedef struct card_buffer_t{ /** The two buffers (we put from the card with one, we read from the other one)*/ unsigned char *buffer1,*buffer2; int actual_read_buffer; /**The pointer to the reading buffer*/ unsigned char *reading_buffer; /**The pointer to the writing buffer*/ unsigned char *writing_buffer; /** The maximum number of packets in the buffer from DVR*/ int dvr_buffer_size; /** The position in the DVR buffer */ int read_buff_pos; /** number of bytes actually read */ int bytes_read; /** Do the read is made using a thread */ int threaded_read; /** The thread data buffer */ int bytes_in_write_buffer; int write_buffer_size; /** @todo put a size for each buffer*/ /** The number of partial packets received*/ int partial_packet_number; /** The number of overflow errors*/ int overflow_number; /**The maximum size of the thread buffer (in packets)*/ int max_thread_buffer_size; }card_buffer_t; typedef struct pid_i_t{ /* The flag for the PIDs*/ mumu_f_t pid_f; /**the channel pids*/ int pids[MAX_PIDS]; /**the channel pids type (PMT, audio, video etc)*/ int pids_type[MAX_PIDS]; /**the channel pids language (ISO639 - 3 characters)*/ char pids_language[MAX_PIDS][4]; /**count the number of scrambled packets for the PID*/ int pids_num_scrambled_packets[MAX_PIDS]; /**tell if the PID is scrambled (1) or not (0)*/ char pids_scrambled[MAX_PIDS]; /**number of channel pids*/ int num_pids; /**PMT PID number*/ MU_F_V(int,pmt_pid) /**PCR PID number*/ int pcr_pid; }pid_i_t; struct unicast_client_t; //Channel status, for autoconfiguration typedef enum chan_status { REMOVED=-3, //Service removed from the PAT (we keep them in case they become up again) NO_STREAMING, //Service not streaming, (eg bad service ID) NOT_READY, //Service not ready, we just autodetected it ALMOST_READY, //Service OK but network is down for example READY, //Service OK and streaming (first flag >0) READY_EXISTING, //Service OK, flag for detecting removed services } chan_status_t; /** @brief Structure for storing channels * * All members are protected by the global lock in chan_p, with the * following exceptions: * * - The EIT variables, since they are only ever accessed from the main thread. * - buf/nb_bytes, since they are only ever accessed from one thread: SCAM_SEND * if we are using scam, or the main thread otherwise. * - the odd/even keys, since they have their own locking. */ typedef struct mumu_chan_t{ /** Flag to say the channel is ready for streaming */ chan_status_t channel_ready; /** Mutex for statistics counters. */ pthread_mutex_t stats_lock; //TODO : structure stats /** The logical channel number*/ int logical_channel_number; /**Tell the total packet number (without pmt) for the scrambling ratio and up/down detection*/ int num_packet; /**Tell the scrambled packet number (without pmt) for the scrambling ratio*/ int num_scrambled_packets; /**tell if this channel is actually streamed ie packets are going out*/ int has_traffic; /**Ratio of scrambled packet versus all packets*/ int ratio_scrambled; /**Tell if at least one of the PID related to the channel is scrambled*/ int scrambled_channel; /**the channel name*/ char user_name[MAX_NAME_LEN]; char name[MAX_NAME_LEN]; MU_F_T(name); char service_name[MAX_NAME_LEN]; /* The PID information for this channel*/ pid_i_t pid_i; /** The service Type from the SDT */ int service_type; /**Transport stream ID*/ MU_F_V(int,service_id); /**Say if we need to ask this channel to the cam*/ MU_F_V(int,need_cam_ask); /** When did we asked the channel to the CAM */ long cam_asking_time; /**The ca system ids*/ int ca_sys_id[32]; //CAM and softcam int free_ca_mode; /**The PMT packet*/ mumudvb_ts_packet_t *pmt_packet; /** The version of the pmt */ int pmt_version; /** Do the pmt needs to be updated ? */ int pmt_need_update; /** Tells if the PMT was updated and autoconf nneds to read it */ int autoconf_pmt_need_update; /** Say if we need to ask this channel to the oscam*/ int need_scam_ask; #ifdef ENABLE_SCAM_SUPPORT /**The PMT packet copy for scam purposes*/ mumudvb_ts_packet_t *scam_pmt_packet; /** The camd socket for SCAM*/ int camd_socket; /** Say if this channel should be descrambled using scam*/ int scam_support; /** Say if we started the threads for oscam */ int scam_support_started; /** Mutex for odd_cw and even_cw. */ pthread_mutex_t cw_lock; /** Odd control word for descrambling */ unsigned char odd_cw[8]; /** Even control word for descrambling */ unsigned char even_cw[8]; /** Indicating if we have another odd cw for descrambling */ unsigned char got_key_odd; /** Indicating if we have another even cw for descrambling */ unsigned char got_key_even; unsigned int ca_idx; unsigned int ca_idx_refcnt; /** Thread for software descrambling */ pthread_t decsathread; /** Descrambling thread shutdown control */ int decsathread_shutdown; /**ring buffer for sending and software descrambling*/ ring_buffer_t* ring_buf; /** Thread for sending packets software descrambled */ pthread_t sendthread; /** Sending thread shutdown control */ int sendthread_shutdown; /** Size of ring buffer */ uint64_t ring_buffer_size; /** Delay of descrambling in us*/ uint64_t decsa_delay; /** Delay of sending in us*/ uint64_t send_delay; /** Says if we've got first cw for channel. * NOTE: This is _not_ under cw_lock, but under the regular chan_p lock. */ int got_cw_started; #endif //Do we send with RTP int rtp; /**the RTP header (just before the buffer so it can be sended together)*/ unsigned char buf_with_rtp_header[RTP_HEADER_LEN]; /**the buffer wich will be sent once it's full*/ unsigned char buf[MAX_UDP_SIZE]; /**number of bytes actually in the buffer*/ int nb_bytes; /**The data sent to this channel*/ long sent_data; /** The packet number for rtp*/ int rtp_packet_num; /**The multicast ip address*/ char ip4Out[20]; MU_F_T(ip4Out) /**The multicast port*/ MU_F_V(int,portOut) /**The multicast output socket*/ struct sockaddr_in sOut4; /**The multicast output socket*/ int socketOut4; /**The ipv6 multicast ip address*/ char ip6Out[IPV6_CHAR_LEN]; MU_F_T(ip6Out) /**The multicast output socket*/ struct sockaddr_in6 sOut6; /**The multicast output socket*/ int socketOut6; /**Unicast clients*/ struct unicast_client_t *clients; /**Count of unicast clients*/ int num_clients; /**Unicast port (listening socket per channel) */ MU_F_V(int,unicast_port) /**Unicast listening socket*/ struct sockaddr_in sIn; /**Unicast listening socket*/ int socketIn; /**The sap playlist group*/ char sap_group[SAP_GROUP_LENGTH]; MU_F_T(sap_group); //do we need to update the SAP announce (typically a name change) int sap_need_update; /**The generated PMT to be sent*/ unsigned char generated_pmt[TS_PACKET_SIZE]; /** Do we rewrite PMT for this channel? */ int pmt_rewrite; /** PMT can span over multiple TS packets */ int pmt_part_num; int pmt_part_count; unsigned char original_pmt[TS_PACKET_SIZE*10]; int original_pmt_ready; /** The version of the generated pmt */ int generated_pmt_version; /** The continuity counter for pmt packets */ int pmt_continuity_counter; /**The generated pat to be sent*/ unsigned char generated_pat[TS_PACKET_SIZE]; /** The version of the generated pat */ int generated_pat_version; /**The generated sdt to be sent*/ unsigned char generated_sdt[TS_PACKET_SIZE]; /** The version of the generated sdt */ int generated_sdt_version; /** If there is no service id for the channel found, we skip sdt rewrite */ int sdt_rewrite_skip; /** The version of the generated EIT */ int eit_section_to_send; /** The table we are currently sending */ uint8_t eit_table_id_to_send; /** the continuity counter for the EIT */ int eit_cc; /** The occupied traffic (in kB/s) */ float traffic; }mumudvb_channel_t; /**The parameters concerning the multicast*/ typedef struct multi_p_t{ /** Do we activate multicast ? */ int multicast; /** Do we activate multicast ? */ int multicast_ipv4; /** Do we activate multicast ? */ int multicast_ipv6; /** Time to live of sent packets */ int ttl; /** the default port*/ int common_port; /** Does MuMuDVB have to join the created multicast groups ?*/ int auto_join; /**Do we send the rtp header ? */ int rtp_header; /** The interface for IPv4 */ char iface4[IF_NAMESIZE+1]; /** The interface for IPv6 */ char iface6[IF_NAMESIZE+1]; /** num mpeg packets in one sent packet */ unsigned char num_pack; }multi_p_t; /** No PSI tables filtering */ #define PSI_TABLES_FILTERING_NONE 0 /** Keep only PAT and CAT */ #define PSI_TABLES_FILTERING_PAT_CAT_ONLY 1 /** Keep only PAT */ #define PSI_TABLES_FILTERING_PAT_ONLY 2 /** structure containing the channels and the asked pids information*/ typedef struct mumu_chan_p_t{ /** Protects all the members, including most of the channels (see the documentation * for mumudvb_channel_t for details). */ pthread_mutex_t lock; /** The number of channels ... */ int number_of_channels; /** Do we send packets with error bit set by decoder ? */ int filter_transport_error; /** Do we do filtering to keep only PSI tables (without DVB tables) ? **/ int psi_tables_filtering; /** The channels array */ mumudvb_channel_t channels[MAX_CHANNELS]; /**@todo use realloc*/ //Asked pids //used for filtering /** this array contains the pids we want to filter,*/ uint8_t asked_pid[8193]; /** The number of TS discontinuities per PID **/ int16_t continuity_counter_pid[8193]; //on 16 bits for storing the initial -1 uint8_t check_cc; }mumu_chan_p_t; typedef struct monitor_parameters_t{ volatile int threadshutdown; int wait_time; struct auto_p_t *auto_p; struct sap_p_t *sap_p; mumu_chan_p_t *chan_p; multi_p_t *multi_p; struct unicast_parameters_t *unicast_vars; struct tune_p_t *tune_p; struct stats_infos_t *stats_infos; void *scam_vars_v; int server_id; char *filename_channels_not_streamed; char *filename_channels_streamed; }monitor_parameters_t; /** struct containing a string */ typedef struct mumu_string_t{ char *string; int length; //string length (not including \0) }mumu_string_t; #define EMPTY_STRING {NULL,0} int mumu_string_append(mumu_string_t *string, const char *psz_format, ...); void mumu_free_string(mumu_string_t *string); int mumudvb_poll(struct pollfd *, int , int ); char *mumu_string_replace(char *source, int *length, int can_realloc, char *toreplace, char *replacement); int string_comput(char *string); uint64_t get_time(void); void buffer_func (mumudvb_channel_t *channel, unsigned char *ts_packet, struct unicast_parameters_t *unicast_vars, void *scam_vars_v); void send_func(mumudvb_channel_t *channel, uint64_t now_time, struct unicast_parameters_t *unicast_vars); int mumu_init_chan(mumudvb_channel_t *chan); void chan_update_CAM(mumu_chan_p_t *chan_p, struct auto_p_t *auto_p, void *scam_vars_v); void update_chan_net(mumu_chan_p_t *chan_p, struct auto_p_t *auto_p, multi_p_t *multi_p, struct unicast_parameters_t *unicast_vars, int server_id, int card, int tuner); void update_chan_filters(mumu_chan_p_t *chan_p, char *card_base_path, int tuner, fds_t *fds); long int mumu_timing(); /** Sets the interrupted flag if value != 0 and it is not already set. * In any case, returns the given value back. Thread- and signal-safe. */ int set_interrupted(int value); /** Gets the interrupted flag; 0 if we have not been interrupted. */ int get_interrupted(); #endif MuMuDVB-2.1.0/src/mumudvb_channels.c000077500000000000000000000440131305714132500172240ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * Based on dvbstream by (C) Dave Chapman 2001, 2002. * * (C) 2014 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include "mumudvb.h" #include "log.h" #include "errors.h" #include "dvb.h" #include "rtp.h" #include "unicast_http.h" #include #include #include #include #include #include #include "scam_common.h" static char *log_module="Common chan: "; int mumu_init_chan(mumudvb_channel_t *chan) { chan->num_packet = 0; chan->has_traffic = 1; chan->num_scrambled_packets = 0; chan->scrambled_channel = 0; chan->generated_pat_version=-1; chan->generated_sdt_version=-1; //We alloc the channel pmt_packet (useful for autoconf and cam) if(chan->pmt_packet==NULL) { chan->pmt_packet=malloc(sizeof(mumudvb_ts_packet_t)); if(chan->pmt_packet==NULL) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); set_interrupted(ERROR_MEMORY<<8); return -1; } memset (chan->pmt_packet, 0, sizeof( mumudvb_ts_packet_t));//we clear it pthread_mutex_init(&chan->pmt_packet->packetmutex,NULL); } //Add pmt pid to pid list if not done if(MU_F(chan->pid_i.pmt_pid)==F_USER) { int found=0; for(int i=0;ipid_i.num_pids;i++) { if(chan->pid_i.pids[i]==chan->pid_i.pmt_pid) found=1; } if(!found && chan->pid_i.num_pids<(MAX_PIDS-1)) { chan->pid_i.pids[chan->pid_i.num_pids]=chan->pid_i.pmt_pid; chan->pid_i.pids_type[chan->pid_i.num_pids]=PID_PMT; chan->pid_i.num_pids++; } } #ifdef ENABLE_SCAM_SUPPORT pthread_mutex_init(&chan->stats_lock, NULL); pthread_mutex_init(&chan->cw_lock, NULL); chan->camd_socket = -1; #endif return 0; } void chan_pmt_need_update( mumudvb_channel_t *chan, unsigned char *buf) { pmt_t *pmt=(pmt_t*)(get_ts_begin(buf)); if(pmt) //It's the beginning of a new packet { if(pmt->version_number!=chan->pmt_version && (pmt->table_id==0x02) && !chan->pmt_need_update) { /*current_next_indicator – A 1-bit indicator, which when set to '1' indicates that the Program Association Table sent is currently applicable. When the bit is set to '0', it indicates that the table sent is not yet applicable and shall be the next table to become valid.*/ if(pmt->current_next_indicator == 0) { return; } log_message( log_module, MSG_DEBUG,"PMT Need update. stored version : %d, new: %d\n",chan->pmt_version,pmt->version_number); //We check if the PMT belongs to this channel if(chan->service_id && (chan->service_id != HILO(pmt->program_number)) ) { return; } chan->pmt_need_update=1; } } } int chan_pmt_ok(mumudvb_channel_t *channel, mumudvb_ts_packet_t *pmt) { pmt_t *header; header=(pmt_t *)pmt->data_full; if(header->table_id!=0x02) { log_message( log_module, MSG_WARN,"Packet PID %d for channel \"%s\" is not a PMT PID. We remove the PMT PID for this channel\n", pmt->pid, channel->name); channel->pid_i.pmt_pid=0; return 0; } //We check if this PMT belongs to the current channel. if(channel->service_id && (channel->service_id != HILO(header->program_number)) ) { log_message( log_module, MSG_DETAIL,"The PMT %d does not belongs to channel \"%s\"\n", pmt->pid, channel->name); return 0; } //If everything seems fine we set update to 0 maybe a false alarm before if(header->version_number==channel->pmt_version && channel->pmt_need_update) { channel->pmt_need_update=0; log_message( log_module, MSG_DETAIL,"False PMT update alarm for channel \"%s\" sid %d", channel->name,channel->service_id); return 0; } else//We update the PMT version stored channel->pmt_version=header->version_number; return 1; } /** @brief This function is called when a new PMT packet is there, the PMT will be downloaded, * once done the proper flags will be set : Autoconfiguration and CAM (SCAM just need the packet) */ void chan_new_pmt(unsigned char *ts_packet, mumu_chan_p_t *chan_p, int pid) { for(int ichan=0;ichanchannels[ichan].pid_i.pmt_pid==pid)&& (chan_p->channels[ichan].channel_ready>=READY)) { if(!chan_p->channels[ichan].pmt_need_update) chan_pmt_need_update(&chan_p->channels[ichan],ts_packet); if(chan_p->channels[ichan].pmt_need_update) log_message( log_module, MSG_DEBUG,"We update the PMT for channel %d sid %d", ichan,chan_p->channels[ichan].service_id); //since we are looping on channels and modifing the packet pointer we need to copy it unsigned char *curr_ts_packet; curr_ts_packet=ts_packet; while(chan_p->channels[ichan].pmt_need_update && get_ts_packet(curr_ts_packet,chan_p->channels[ichan].pmt_packet)) { curr_ts_packet=NULL; // next call we only POP packets from the stack //If everything ok, we set the proper flags if(chan_pmt_ok(&chan_p->channels[ichan], chan_p->channels[ichan].pmt_packet)) { chan_p->channels[ichan].pmt_need_update=0; //We tell autoconf a new PMT is here chan_p->channels[ichan].autoconf_pmt_need_update=1; //We tell the CAM a new PMT is here if(chan_p->channels[ichan].need_cam_ask==CAM_ASKED) chan_p->channels[ichan].need_cam_ask=CAM_NEED_UPDATE; //We we send again this packet to the CAM } } } } } /** @brief Update the CAM information for the channels */ void chan_update_CAM(mumu_chan_p_t *chan_p, auto_p_t *auto_p, void *scam_vars_v) { int ichan=0; #ifndef ENABLE_SCAM_SUPPORT (void) scam_vars_v; //to make compiler happy #else scam_parameters_t *scam_vars=(scam_parameters_t *)scam_vars_v; #endif for (ichan = 0; ichan < chan_p->number_of_channels; ichan++) { if(chan_p->channels[ichan].channel_ready!=READY) continue; //This is a scrambled channel, we will have to ask the cam for descrambling it if(auto_p->autoconf_scrambled && chan_p->channels[ichan].free_ca_mode) { //It was not asked before, we ask it if(chan_p->channels[ichan].need_cam_ask==CAM_NO_ASK) chan_p->channels[ichan].need_cam_ask=CAM_NEED_ASK; //If it was asked we ask for refresh if(chan_p->channels[ichan].need_cam_ask==CAM_ASKED) chan_p->channels[ichan].need_cam_ask=CAM_NEED_UPDATE; } #ifdef ENABLE_SCAM_SUPPORT if (chan_p->channels[ichan].free_ca_mode && scam_vars->scam_support) { if (chan_p->channels[ichan].scam_support == 0) { auto_p->need_filter_chan_update = 1; chan_p->channels[ichan].scam_support=1; chan_p->channels[ichan].need_scam_ask=CAM_NEED_ASK; chan_p->channels[ichan].ring_buffer_size=scam_vars->ring_buffer_default_size; chan_p->channels[ichan].decsa_delay=scam_vars->decsa_default_delay; chan_p->channels[ichan].send_delay=scam_vars->send_default_delay; chan_p->channels[ichan].scam_pmt_packet=malloc(sizeof(mumudvb_ts_packet_t)); if(chan_p->channels[ichan].scam_pmt_packet==NULL) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); set_interrupted(ERROR_MEMORY<<8); return; } memset (chan_p->channels[ichan].scam_pmt_packet, 0, sizeof( mumudvb_ts_packet_t));//we clear it pthread_mutex_init(&chan_p->channels[ichan].scam_pmt_packet->packetmutex, NULL); } // need to send the new PMT to Oscam else if(chan_p->channels[ichan].need_scam_ask==CAM_ASKED) chan_p->channels[ichan].need_scam_ask=CAM_NEED_ASK; } #endif } } /** @brief Set the networking for the channels almost ready */ void update_chan_net(mumu_chan_p_t *chan_p, auto_p_t *auto_p, multi_p_t *multi_p, unicast_parameters_t *unicast_vars, int server_id, int card, int tuner) { pthread_mutex_lock(&chan_p->lock); int ichan; char tempstring[256]; int unicast_port_per_channel; unicast_port_per_channel=strlen(auto_p->autoconf_unicast_port)?1:0; for (ichan = 0; ichan < chan_p->number_of_channels; ichan++) { if(chan_p->channels[ichan].channel_ready!=ALMOST_READY) continue; chan_p->channels[ichan].channel_ready=READY; //RTP init (even if no RTP, costs nothing) if(chan_p->channels[ichan].buf_with_rtp_header[0]!=128) init_rtp_header(&chan_p->channels[ichan]); //We init the RTP header in all cases //We update the unicast port, the connection will be created in autoconf_finish_full if(unicast_port_per_channel && unicast_vars->unicast && MU_F(chan_p->channels[ichan].unicast_port)!=F_USER) { strcpy(tempstring,auto_p->autoconf_unicast_port); int len;len=256; char number[10]; sprintf(number,"%d",ichan); mumu_string_replace(tempstring,&len,0,"%number",number); sprintf(number,"%d",card); mumu_string_replace(tempstring,&len,0,"%card",number); sprintf(number,"%d",tuner); mumu_string_replace(tempstring,&len,0,"%tuner",number); sprintf(number,"%d",server_id); mumu_string_replace(tempstring,&len,0,"%server",number); //SID sprintf(number,"%d",chan_p->channels[ichan].service_id); mumu_string_replace(tempstring,&len,0,"%sid",number); chan_p->channels[ichan].unicast_port=string_comput(tempstring); log_message( log_module, MSG_DEBUG,"Channel (direct) unicast port %d\n",chan_p->channels[ichan].unicast_port); } // Set the number of unicast clients to zero chan_p->channels[ichan].num_clients = 0; if(multi_p->multicast) { char number[10]; char ip[80]; int len=80; //We store if we send this channel with RTP, later it can be made channel dependent. chan_p->channels[ichan].rtp=multi_p->rtp_header; if(auto_p->autoconfiguration && strlen(auto_p->autoconf_multicast_port) && MU_F(chan_p->channels[ichan].portOut)!=F_USER) { strcpy(tempstring,auto_p->autoconf_multicast_port); sprintf(number,"%d",ichan); mumu_string_replace(tempstring,&len,0,"%number",number); sprintf(number,"%d",card); mumu_string_replace(tempstring,&len,0,"%card",number); sprintf(number,"%d",tuner); mumu_string_replace(tempstring,&len,0,"%tuner",number); sprintf(number,"%d",server_id); mumu_string_replace(tempstring,&len,0,"%server",number); //SID sprintf(number,"%d",chan_p->channels[ichan].service_id); mumu_string_replace(tempstring,&len,0,"%sid",number); chan_p->channels[ichan].portOut=string_comput(tempstring); } else if(MU_F(chan_p->channels[ichan].portOut)!=F_USER) { chan_p->channels[ichan].portOut=multi_p->common_port;//do here the job for evaluating the string } if(auto_p->autoconfiguration && multi_p->multicast_ipv4 && MU_F(chan_p->channels[ichan].ip4Out)!=F_USER) { strcpy(ip,auto_p->autoconf_ip4); sprintf(number,"%d",ichan); mumu_string_replace(ip,&len,0,"%number",number); sprintf(number,"%d",card); mumu_string_replace(ip,&len,0,"%card",number); sprintf(number,"%d",tuner); mumu_string_replace(ip,&len,0,"%tuner",number); sprintf(number,"%d",server_id); mumu_string_replace(ip,&len,0,"%server",number); //SID sprintf(number,"%d",(chan_p->channels[ichan].service_id&0xFF00)>>8); mumu_string_replace(ip,&len,0,"%sid_hi",number); sprintf(number,"%d",chan_p->channels[ichan].service_id&0x00FF); mumu_string_replace(ip,&len,0,"%sid_lo",number); // Compute the string, ex: 239.255.130+0*10+2.1 log_message( log_module, MSG_DEBUG,"Computing expressions in string \"%s\"\n",ip); //Splitting and computing. use of strtok_r because it's safer int tn[4]; char *sptr; tn[0]=string_comput(strtok_r (ip,".",&sptr)); tn[1]=string_comput(strtok_r (NULL,".",&sptr)); tn[2]=string_comput(strtok_r (NULL,".",&sptr)); tn[3]=string_comput(strtok_r (NULL,".",&sptr)); sprintf(chan_p->channels[ichan].ip4Out,"%d.%d.%d.%d",tn[0],tn[1],tn[2],tn[3]); // In C the evaluation order of arguments in a fct is undefined, no more easy factoring } if(auto_p->autoconfiguration && multi_p->multicast_ipv6 && MU_F(chan_p->channels[ichan].ip6Out)!=F_USER ) { strcpy(ip,auto_p->autoconf_ip6); sprintf(number,"%d",ichan); mumu_string_replace(ip,&len,0,"%number",number); sprintf(number,"%d",card); mumu_string_replace(ip,&len,0,"%card",number); sprintf(number,"%d",tuner); mumu_string_replace(ip,&len,0,"%tuner",number); sprintf(number,"%d",server_id); mumu_string_replace(ip,&len,0,"%server",number); //SID sprintf(number,"%04x",chan_p->channels[ichan].service_id); mumu_string_replace(ip,&len,0,"%sid",number); strncpy(chan_p->channels[ichan].ip6Out,ip,IPV6_CHAR_LEN); chan_p->channels[ichan].ip6Out[IPV6_CHAR_LEN-1]='\0'; } } /** open the unicast listening connections for the channels which don't have one */ if(chan_p->channels[ichan].unicast_port && unicast_vars->unicast && (chan_p->channels[ichan].socketIn <=0)) { log_message( log_module, MSG_INFO,"Unicast : We open the channel %d http socket address %s:%d\n", ichan, unicast_vars->ipOut, chan_p->channels[ichan].unicast_port); unicast_create_listening_socket(UNICAST_LISTEN_CHANNEL, ichan, unicast_vars->ipOut, chan_p->channels[ichan].unicast_port, &chan_p->channels[ichan].sIn, &chan_p->channels[ichan].socketIn, unicast_vars); } //Open the multicast socket for the new channel which don't have them opened if(multi_p->multicast && multi_p->multicast_ipv4 && (chan_p->channels[ichan].socketOut4 <=0)) { log_message( log_module, MSG_INFO,"We open the channel %d multicast IPv4 socket address %s:%d\n", ichan, chan_p->channels[ichan].ip4Out, chan_p->channels[ichan].portOut); if(multi_p->auto_join) //See the README for the reason of this option chan_p->channels[ichan].socketOut4 = makeclientsocket (chan_p->channels[ichan].ip4Out, chan_p->channels[ichan].portOut, multi_p->ttl, multi_p->iface4, &chan_p->channels[ichan].sOut4); else chan_p->channels[ichan].socketOut4 = makesocket (chan_p->channels[ichan].ip4Out, chan_p->channels[ichan].portOut, multi_p->ttl, multi_p->iface4, &chan_p->channels[ichan].sOut4); } if(multi_p->multicast && multi_p->multicast_ipv6 && (chan_p->channels[ichan].socketOut6 <=0)) { log_message( log_module, MSG_INFO,"We open the channel %d multicast IPv6 socket address %s:%d\n", ichan, chan_p->channels[ichan].ip6Out, chan_p->channels[ichan].portOut); if(multi_p->auto_join) //See the README for the reason of this option chan_p->channels[ichan].socketOut6 = makeclientsocket6 (chan_p->channels[ichan].ip6Out, chan_p->channels[ichan].portOut, multi_p->ttl, multi_p->iface6, &chan_p->channels[ichan].sOut6); else chan_p->channels[ichan].socketOut6 = makesocket6 (chan_p->channels[ichan].ip6Out, chan_p->channels[ichan].portOut, multi_p->ttl, multi_p->iface6, &chan_p->channels[ichan].sOut6); } /******************************************************/ // SCAM START PART /******************************************************/ #ifdef ENABLE_SCAM_SUPPORT if (chan_p->channels[ichan].scam_support && !chan_p->channels[ichan].scam_support_started) { set_interrupted(scam_channel_start(&chan_p->channels[ichan], unicast_vars)); chan_p->channels[ichan].scam_support_started=1; } #endif /******************************************************/ // SCAM START PART FINISHED /******************************************************/ } pthread_mutex_unlock(&chan_p->lock); } /** Update the filters of the channels, this function also searches for closed PIDs */ void update_chan_filters(mumu_chan_p_t *chan_p, char *card_base_path, int tuner, fds_t *fds) { log_message( log_module, MSG_INFO,"Looking through all services to update their filters"); pthread_mutex_lock(&chan_p->lock); uint8_t asked_pid[8193]; //Clear memset(asked_pid,PID_NOT_ASKED,8193*sizeof(uint8_t)); //We store the PIDs which are needed by the channels for (int ichan = 0; ichan < chan_p->number_of_channels; ichan++) { //We add PIDs only for channels almost ready at least if(chan_p->channels[ichan].channel_ready>=ALMOST_READY) for (int ipid = 0; ipid < chan_p->channels[ichan].pid_i.num_pids; ipid++) { asked_pid[chan_p->channels[ichan].pid_i.pids[ipid]]=PID_ASKED; } } //Now we compare with the ones for the channels for (int ipid = MAX_MANDATORY_PID_NUMBER; ipid < 8193; ipid++) { //Now we have the PIDs we look for those who disappeared if(chan_p->asked_pid[ipid]==PID_ASKED && asked_pid[ipid]!=PID_ASKED) { log_message( log_module, MSG_DEBUG, "Update : PID %d does not belong to any channel anymore, we close the filter", ipid); close(fds->fd_demuxer[ipid]); fds->fd_demuxer[ipid]=0; chan_p->asked_pid[ipid]=PID_NOT_ASKED; } //And we look for the PIDs who are now asked else if(asked_pid[ipid]==PID_ASKED && chan_p->asked_pid[ipid]!=PID_ASKED && chan_p->asked_pid[ipid]!=PID_FILTERED) { log_message( log_module, MSG_DETAIL, " pid %d added \n",ipid); //If the PID is not on the list we add it for the filters chan_p->asked_pid[ipid]=PID_ASKED; } } log_message( log_module, MSG_DETAIL,"Open the new filters"); // we open the file descriptors if (create_card_fd (card_base_path, tuner, chan_p->asked_pid, fds) < 0) { log_message( log_module, MSG_ERROR,"ERROR : CANNOT open the new descriptors. Some channels will probably not work"); } set_filters(chan_p->asked_pid, fds); pthread_mutex_unlock(&chan_p->lock); } MuMuDVB-2.1.0/src/mumudvb_common.c000066400000000000000000000276251305714132500167300ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * Based on dvbstream by (C) Dave Chapman 2001, 2002. * * (C) 2004-2014 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include "mumudvb.h" #include "log.h" #include "errors.h" #include "rtp.h" #include "unicast_http.h" #include #include #include #include #include #include #include "scam_common.h" static char *log_module="Common: "; /** @brief : poll the file descriptors fds with a limit in the number of errors and timeout */ int mumudvb_poll(struct pollfd *pfds, int pfdsnum,int timeout) { int poll_try,poll_ret; int poll_eintr=0; int last_poll_error; int Interrupted; poll_ret=0; poll_try=0; poll_eintr=0; last_poll_error=0; do { poll_ret=poll (pfds, pfdsnum, timeout); if(poll_ret<0) { if(errno != EINTR) //EINTR means Interrupted System Call, it normally shouldn't matter so much so we don't count it for our Poll tries { poll_try++; last_poll_error=errno; } else { poll_eintr++; if(poll_eintr==10) { log_message( log_module, MSG_DEBUG, "Poll : 10 successive EINTR\n"); poll_eintr=0; } } } /**@todo : put a maximum number of interrupted system calls per unit time*/ }while(( poll_ret<0 )&&(poll_trylengthpattern) { tempstring=realloc(tempstring,sizeof(char)*(lengthtempstring+lengthreplacment-lengthpattern+1)); if(tempstring==NULL) { log_message(log_module, MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); return NULL; } pospattern=strstr(tempstring,toreplace); } memmove(pospattern+lengthreplacment,pospattern+lengthpattern,lengthtempstring-((int)(pospattern-tempstring))-lengthpattern); memcpy(pospattern,replacement,lengthreplacment); lengthtempstring+=lengthreplacment-lengthpattern; pospattern=strstr(tempstring,toreplace); } tempstring[lengthtempstring-1]='\0'; if(can_realloc) { if(lengthtempstring>*length) { reallocresult=realloc(source,sizeof(char)*(lengthtempstring)); if(reallocresult==NULL) { log_message(log_module, MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); return NULL; } source=reallocresult; *length=lengthtempstring; } strcpy(source,tempstring); } else if(lengthtempstring<=*length) { strcpy(source,tempstring); } else { strncpy(source,tempstring,*length-1); source[*length-1]='\0'; } free(tempstring); return source; } int string_mult(char *string); /** @brief Evaluate a string containing sum and mult keeping the priority of the mult over the + * Ex : string_sum("2+2*3") returns 8 * @param string the string to evaluate */ int string_comput(char *string) { int number1,len; char *pluspos=NULL; char *tempchar; if(string==NULL) return 0; pluspos=strchr(string,'+'); if(pluspos==NULL) { len=strlen(string); } else { len=pluspos-string; } tempchar=malloc(sizeof(char)*(len+1)); strncpy(tempchar,string,len); tempchar[len]='\0'; number1=string_mult(tempchar); free(tempchar); if(pluspos==NULL) return number1; if(strchr(pluspos+1,'+')!=NULL) return number1+string_comput(pluspos+1); return number1+string_mult(pluspos+1); } /** @brief Evaluate a string containing a multiplication. Doesn't work if there is a sum inside * Ex : string_sum("2*6") returns 6 * @param string the string to evaluate */ int string_mult(char *string) { int number1,len; char *multpos=NULL; char *tempchar; multpos=strchr(string,'*'); if(multpos==NULL) return atoi(string); len=multpos-string; tempchar=malloc(sizeof(char)*(len+1)); strncpy(tempchar,string,len); tempchar[len]='\0'; number1=atoi(tempchar); free(tempchar); if(strchr(multpos+1,'*')!=NULL) return number1*string_mult(multpos+1); return number1*atoi(multpos+1); } /** @brief Special sprintf wich append the text to an existing string and allocate the memory for it */ int mumu_string_append(mumu_string_t *string, const char *psz_format, ...) { int size; va_list args; va_start( args, psz_format ); size=vsnprintf(NULL, 0, psz_format, args); va_end( args ); string->string=realloc(string->string,(string->length+size+1)*sizeof(char)); if(string->string==NULL) { log_message(log_module,MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); return ERROR_MEMORY<<8; } va_start( args, psz_format ); vsnprintf(string->string+string->length, size+1, psz_format, args); string->length=string->length+size; va_end( args ); return 0; } /** @brief Free a MuMuDVB string */ void mumu_free_string(mumu_string_t *string) { if(string->string) { free(string->string); string->string=NULL; string->length=0; } } /** @brief return the time (in usec) elapsed between the two last calls of this function. */ long int mumu_timing() { static int started=0; static struct timeval oldtime; struct timeval tv; long delta; gettimeofday(&tv,NULL); if(started) { delta=(tv.tv_sec-oldtime.tv_sec)*1000000+(tv.tv_usec-oldtime.tv_usec); } else { delta=0; started=1; } oldtime=tv; return delta; } /** @brief getting current system time (in usec). */ uint64_t get_time(void) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return (ts.tv_sec * 1000000ll + ts.tv_nsec / 1000); } /** @brief function for buffering demultiplexed data. */ void buffer_func (mumudvb_channel_t *channel, unsigned char *ts_packet, struct unicast_parameters_t *unicast_vars, void *scam_vars_v) { int pid; /** pid of the current mpeg2 packet */ int ScramblingControl; int curr_pid = 0; int send_packet = 0; extern int dont_send_scrambled; #ifndef ENABLE_SCAM_SUPPORT (void) scam_vars_v; //to make compiler happy #else scam_parameters_t *scam_vars=(scam_parameters_t *)scam_vars_v; #endif uint64_t now_time; #ifdef ENABLE_SCAM_SUPPORT if (channel->scam_support && channel->scam_support_started && scam_vars->scam_support) { pthread_mutex_lock(&channel->ring_buf->lock); memcpy(channel->ring_buf->data+TS_PACKET_SIZE*channel->ring_buf->write_idx, ts_packet, TS_PACKET_SIZE); now_time=get_time(); channel->ring_buf->time_send[channel->ring_buf->write_idx]=now_time + channel->send_delay; channel->ring_buf->time_decsa[channel->ring_buf->write_idx]=now_time + channel->decsa_delay; ++channel->ring_buf->write_idx; channel->ring_buf->write_idx&=(channel->ring_buffer_size -1); ++channel->ring_buf->to_descramble; pthread_mutex_unlock(&channel->ring_buf->lock); } else #endif { pid = ((ts_packet[1] & 0x1f) << 8) | (ts_packet[2]); ScramblingControl = (ts_packet[3] & 0xc0) >> 6; pthread_mutex_lock(&channel->stats_lock); for (curr_pid = 0; (curr_pid < channel->pid_i.num_pids); curr_pid++) if ((channel->pid_i.pids[curr_pid] == pid) || (channel->pid_i.pids[curr_pid] == 8192)) //We can stream whole transponder using 8192 { if ((ScramblingControl>0) && (pid != channel->pid_i.pmt_pid) ) channel->num_scrambled_packets++; //check if the PID is scrambled for determining its state if (ScramblingControl>0) channel->pid_i.pids_num_scrambled_packets[curr_pid]++; //we don't count the PMT pid for up channels if (pid != channel->pid_i.pmt_pid) channel->num_packet++; break; } pthread_mutex_unlock(&channel->stats_lock); //avoid sending of scrambled channels if we asked to send_packet=1; if(dont_send_scrambled && (ScramblingControl>0)&& (channel->pid_i.pmt_pid) ) send_packet=0; if (send_packet) { // we fill the channel buffer memcpy(channel->buf + channel->nb_bytes, ts_packet, TS_PACKET_SIZE); channel->nb_bytes += TS_PACKET_SIZE; } //The buffer is full, we send it if ((!channel->rtp && ((channel->nb_bytes + TS_PACKET_SIZE) > MAX_UDP_SIZE)) ||(channel->rtp && ((channel->nb_bytes + RTP_HEADER_LEN + TS_PACKET_SIZE) > MAX_UDP_SIZE))) { now_time=get_time(); send_func(channel, now_time, unicast_vars); } } } /** @brief function for sending demultiplexed data. */ void send_func (mumudvb_channel_t *channel, uint64_t now_time, struct unicast_parameters_t *unicast_vars) { //For bandwith measurement (traffic) pthread_mutex_lock(&channel->stats_lock); channel->sent_data+=channel->nb_bytes+20+8; // IP=20 bytes header and UDP=8 bytes header if (channel->rtp) channel->sent_data+=RTP_HEADER_LEN; pthread_mutex_unlock(&channel->stats_lock); /********** MULTICAST *************/ //if the multicast TTL is set to 0 we don't send the multicast packets if((channel->socketOut4 >0 )|| (channel->socketOut6 >0 )) { unsigned char *data; int data_len; if(channel->rtp) { /****** RTP *******/ rtp_update_sequence_number(channel,now_time); data=channel->buf_with_rtp_header; data_len=channel->nb_bytes+RTP_HEADER_LEN; } else { data=channel->buf; data_len=channel->nb_bytes; } if(channel->socketOut4) sendudp (channel->socketOut4, &channel->sOut4, data, data_len); if(channel->socketOut6) sendudp6 (channel->socketOut6, &channel->sOut6, data, data_len); } /*********** UNICAST **************/ unicast_data_send(channel, unicast_vars); /********* END of UNICAST **********/ channel->nb_bytes = 0; } static int interrupted = 0; static pthread_mutex_t interrupted_mutex = PTHREAD_MUTEX_INITIALIZER; int set_interrupted(int value) { if (value != 0) { pthread_mutex_lock(&interrupted_mutex); if (interrupted == 0) { interrupted = value; } pthread_mutex_unlock(&interrupted_mutex); } return value; } int get_interrupted() { int ret; pthread_mutex_lock(&interrupted_mutex); ret = interrupted; pthread_mutex_unlock(&interrupted_mutex); return ret; } MuMuDVB-2.1.0/src/mumudvb_mon.c000066400000000000000000000556241305714132500162310ustar00rootroot00000000000000/* * mumudvb_mon.c * Monitor and init functions for MuMuDVB * Created on: Mar 29, 2014 * Author: braice */ #define _GNU_SOURCE //in order to use program_invocation_short_name and pthread_timedjoin_np #include "config.h" // Linux includes: #include #include #include #include #include #include #include #include #include #include #include #ifdef ANDROID #include #else #include #endif #include #include #include #include #include #include #include #include #include "mumudvb.h" #include "tune.h" #include "network.h" #include "dvb.h" #ifdef ENABLE_CAM_SUPPORT #include "cam.h" #endif #ifdef ENABLE_SCAM_SUPPORT #include "scam_capmt.h" #include "scam_common.h" #include "scam_getcw.h" #include "scam_decsa.h" #endif #include "ts.h" #include "errors.h" #include "autoconf.h" #include "sap.h" #include "rewrite.h" #include "unicast_http.h" #include "rtp.h" #include "log.h" #if defined __UCLIBC__ || defined ANDROID #define program_invocation_short_name "mumudvb" #else extern char *program_invocation_short_name; #endif static char *log_module="Main: "; extern long now; extern long real_start_time; extern int received_signal; //logging extern log_params_t log_params; extern int dont_send_scrambled; extern int write_streamed_channels; extern int timeout_no_diff; void parse_cmd_line(int argc, char **argv,char *(*conf_filename),tune_p_t *tune_p,stats_infos_t *stats_infos,int *server_id, int *no_daemon,char **dump_filename, int *listingcards) { const char short_options[] = "c:sdthvql"; const struct option long_options[] = { {"config", required_argument, NULL, 'c'}, {"signal", no_argument, NULL, 's'}, {"traffic", no_argument, NULL, 't'}, {"server_id", required_argument, NULL, 'i'}, {"debug", no_argument, NULL, 'd'}, {"help", no_argument, NULL, 'h'}, {"list-cards", no_argument, NULL, 'l'}, {"card", required_argument, NULL, 'a'}, {"dumpfile", required_argument, NULL, 'z'}, {0, 0, 0, 0} }; int c, option_index = 0; if (argc == 1) { usage (program_invocation_short_name); exit(ERROR_ARGS); } while (1) { c = getopt_long (argc, argv, short_options, long_options, &option_index); if (c == -1) { break; } switch (c) { case 'c': *conf_filename = (char *) malloc (strlen (optarg) + 1); if (!*conf_filename) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); exit(ERROR_MEMORY); } strncpy (*conf_filename, optarg, strlen (optarg) + 1); break; case 'a': tune_p->card=atoi(optarg); break; case 's': tune_p->display_strenght = 1; break; case 'i': *server_id = atoi(optarg); break; case 't': stats_infos->show_traffic = 1; break; case 'd': *no_daemon = 1; break; case 'v': log_params.verbosity++; break; case 'q': log_params.verbosity--; break; case 'h': usage (program_invocation_short_name); exit(ERROR_ARGS); break; case 'l': *listingcards=1; break; case 'z': *dump_filename = (char *) malloc (strlen (optarg) + 1); if (!*dump_filename) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); exit(ERROR_MEMORY); } strncpy (*dump_filename, optarg, strlen (optarg) + 1); log_message( log_module, MSG_WARN,"You've decided to dump the received stream into %s. Be warned, it can grow quite fast", *dump_filename); break; } } if (optind < argc) { usage (program_invocation_short_name); exit(ERROR_ARGS); } } /** @brief Clean closing and freeing * * */ int mumudvb_close(int no_daemon, monitor_parameters_t *monitor_thread_params, rewrite_parameters_t *rewrite_vars, auto_p_t *auto_p, unicast_parameters_t *unicast_vars, volatile int *strengththreadshutdown, void *cam_p_v, void *scam_vars_v, char *filename_channels_not_streamed, char *filename_channels_streamed, char *filename_pid, int Interrupted, mumu_chan_p_t *chan_p, pthread_t *signalpowerthread, pthread_t *monitorthread, card_thread_parameters_t *cardthreadparams, fds_t *fds) { int curr_channel; int iRet; #ifndef ENABLE_CAM_SUPPORT (void) cam_p_v; //to make compiler happy #else cam_p_t *cam_p=(cam_p_t *)cam_p_v; #endif #ifndef ENABLE_SCAM_SUPPORT (void) scam_vars_v; //to make compiler happy #else scam_parameters_t *scam_vars=(scam_parameters_t *)scam_vars_v; #endif if (Interrupted) { if(Interrupted< (1<<8)) //we check if it's a signal or a mumudvb error log_message( log_module, MSG_INFO, "Caught signal %d - closing cleanly.\n", Interrupted); else log_message( log_module, MSG_INFO, "Closing cleanly. Error %d\n",Interrupted>>8); } struct timespec ts; if(*signalpowerthread) { log_message(log_module,MSG_DEBUG,"Signal/power Thread closing\n"); *strengththreadshutdown=1; #if !defined __UCLIBC__ && !defined ANDROID clock_gettime(CLOCK_REALTIME, &ts); ts.tv_sec += 5; iRet=pthread_timedjoin_np(*signalpowerthread, NULL, &ts); #else iRet=pthread_join(*signalpowerthread, NULL); #endif if(iRet) log_message(log_module,MSG_WARN,"Signal/power Thread badly closed: %s\n", strerror(iRet)); } if(cardthreadparams->thread_running) { log_message(log_module,MSG_DEBUG,"Card reading Thread closing\n"); cardthreadparams->threadshutdown=1; pthread_mutex_destroy(&cardthreadparams->carddatamutex); pthread_cond_destroy(&cardthreadparams->threadcond); } //We shutdown the monitoring thread if(*monitorthread) { log_message(log_module,MSG_DEBUG,"Monitor Thread closing\n"); monitor_thread_params->threadshutdown=1; #if !defined __UCLIBC__ && !defined ANDROID clock_gettime(CLOCK_REALTIME, &ts); ts.tv_sec += 5; iRet=pthread_timedjoin_np(*monitorthread, NULL, &ts); #else iRet=pthread_join(*monitorthread, NULL); #endif if(iRet) log_message(log_module,MSG_WARN,"Monitor Thread badly closed: %s\n", strerror(iRet)); } for (curr_channel = 0; curr_channel < chan_p->number_of_channels; curr_channel++) { if(chan_p->channels[curr_channel].socketOut4>0) close (chan_p->channels[curr_channel].socketOut4); if(chan_p->channels[curr_channel].socketOut6>0) close (chan_p->channels[curr_channel].socketOut6); if(chan_p->channels[curr_channel].socketIn>0) close (chan_p->channels[curr_channel].socketIn); //Free the channel structures if(chan_p->channels[curr_channel].pmt_packet) free(chan_p->channels[curr_channel].pmt_packet); chan_p->channels[curr_channel].pmt_packet=NULL; #ifdef ENABLE_SCAM_SUPPORT //Free the channel structures if(chan_p->channels[curr_channel].scam_pmt_packet) free(chan_p->channels[curr_channel].scam_pmt_packet); chan_p->channels[curr_channel].scam_pmt_packet=NULL; if (chan_p->channels[curr_channel].scam_support && scam_vars->scam_support) { scam_channel_stop(&chan_p->channels[curr_channel]); } #endif } // we close the file descriptors close_card_fd(fds); //We close the unicast connections and free the clients unicast_freeing(unicast_vars); #ifdef ENABLE_CAM_SUPPORT if(cam_p->cam_support) { // stop CAM operation cam_stop(cam_p); // delete cam_info file if (remove (cam_p->filename_cam_info)) { log_message( log_module, MSG_WARN, "%s: %s\n", cam_p->filename_cam_info, strerror (errno)); } mumu_free_string(&cam_p->cam_menulist_str); mumu_free_string(&cam_p->cam_menu_string); } #endif #ifdef ENABLE_SCAM_SUPPORT if(scam_vars->scam_support) { scam_getcw_stop(scam_vars); } #endif //autoconf variables freeing autoconf_freeing(auto_p); //sap variables freeing if(monitor_thread_params && monitor_thread_params->sap_p->sap_messages4) free(monitor_thread_params->sap_p->sap_messages4); if(monitor_thread_params && monitor_thread_params->sap_p->sap_messages6) free(monitor_thread_params->sap_p->sap_messages6); //Pat rewrite freeing if(rewrite_vars->full_pat) free(rewrite_vars->full_pat); //SDT rewrite freeing if(rewrite_vars->full_sdt) free(rewrite_vars->full_sdt); if (strlen(filename_channels_streamed) && (write_streamed_channels)&&remove (filename_channels_streamed)) { log_message( log_module, MSG_WARN, "%s: %s\n", filename_channels_streamed, strerror (errno)); exit(ERROR_DEL_FILE); } if (strlen(filename_channels_not_streamed) && (write_streamed_channels)&&remove (filename_channels_not_streamed)) { log_message( log_module, MSG_WARN, "%s: %s\n", filename_channels_not_streamed, strerror (errno)); exit(ERROR_DEL_FILE); } if (!no_daemon) { if (remove (filename_pid)) { log_message( log_module, MSG_INFO, "%s: %s\n", filename_pid, strerror (errno)); exit(ERROR_DEL_FILE); } } /*free the file descriptors*/ if(fds->pfds) free(fds->pfds); fds->pfds=NULL; if(unicast_vars->fd_info) free(unicast_vars->fd_info); unicast_vars->fd_info=NULL; // Format ExitCode (normal exit) int ExitCode; if(Interrupted<(1<<8)) ExitCode=0; else ExitCode=Interrupted>>8; // Show in log that we are stopping log_message( log_module, MSG_INFO,"========== MuMuDVB version %s is stopping with ExitCode %d ==========",VERSION,ExitCode); // Freeing log ressources if(log_params.log_file) { fclose(log_params.log_file); free(log_params.log_file_path); } if(log_params.log_header!=NULL) free(log_params.log_header); #ifndef ANDROID munlockall(); #endif // End return(ExitCode); } void *monitor_func(void* arg) { monitor_parameters_t *params; params= (monitor_parameters_t *) arg; int i,curr_channel; struct timeval tv; double monitor_now; double monitor_start; double last_updown_check=0; double last_flush_time = 0; double time_no_diff=0; int num_big_buffer_show=0; gettimeofday (&tv, (struct timezone *) NULL); monitor_start = tv.tv_sec + tv.tv_usec/1000000; monitor_now = monitor_start; #ifdef ENABLE_SCAM_SUPPORT struct scam_parameters_t *scam_vars; scam_vars=(struct scam_parameters_t *) params->scam_vars_v; #endif while(!params->threadshutdown) { gettimeofday (&tv, (struct timezone *) NULL); monitor_now = tv.tv_sec + tv.tv_usec/1000000 -monitor_start; now = tv.tv_sec - real_start_time; /*******************************************/ /* We deal with the received signals */ /*******************************************/ if (received_signal == SIGUSR1) //Display signal strength { params->tune_p->display_strenght = params->tune_p->display_strenght ? 0 : 1; received_signal = 0; } else if (received_signal == SIGUSR2) //Display traffic { params->stats_infos->show_traffic = params->stats_infos->show_traffic ? 0 : 1; if(params->stats_infos->show_traffic) log_message( log_module, MSG_INFO,"The traffic will be shown every %d seconds\n",params->stats_infos->show_traffic_interval); else log_message( log_module, MSG_INFO,"The traffic will not be shown anymore\n"); received_signal = 0; } else if (received_signal == SIGHUP) //Sync logs { log_message( log_module, MSG_DEBUG,"Sync logs\n"); sync_logs(); received_signal = 0; } pthread_mutex_lock(¶ms->chan_p->lock); /*we are not doing autoconfiguration we can do something else*/ /*sap announces*/ sap_poll(params->sap_p,params->chan_p->number_of_channels,params->chan_p->channels,*params->multi_p, (long)monitor_now); /*******************************************/ /* compute the bandwidth occupied by */ /* each channel */ /*******************************************/ float time_interval; if(!params->stats_infos->compute_traffic_time) params->stats_infos->compute_traffic_time=monitor_now; if((monitor_now-params->stats_infos->compute_traffic_time)>=params->stats_infos->compute_traffic_interval) { time_interval=monitor_now-params->stats_infos->compute_traffic_time; params->stats_infos->compute_traffic_time=monitor_now; for (curr_channel = 0; curr_channel < params->chan_p->number_of_channels; curr_channel++) { mumudvb_channel_t *current; current=¶ms->chan_p->channels[curr_channel]; pthread_mutex_lock(¤t->stats_lock); if (time_interval!=0) params->chan_p->channels[curr_channel].traffic=((float)params->chan_p->channels[curr_channel].sent_data)/time_interval*1/1000; else params->chan_p->channels[curr_channel].traffic=0; params->chan_p->channels[curr_channel].sent_data=0; pthread_mutex_unlock(¤t->stats_lock); } } /*******************************************/ /*show the bandwidth measurement */ /*******************************************/ if(params->stats_infos->show_traffic) { show_traffic(log_module,monitor_now, params->stats_infos->show_traffic_interval, params->chan_p); } /*******************************************/ /* Show the statistics for the big buffer */ /*******************************************/ if(params->stats_infos->show_buffer_stats) { if(!params->stats_infos->show_buffer_stats_time) params->stats_infos->show_buffer_stats_time=monitor_now; if((monitor_now-params->stats_infos->show_buffer_stats_time)>=params->stats_infos->show_buffer_stats_interval) { params->stats_infos->show_buffer_stats_time=monitor_now; if (params->stats_infos->stats_num_reads!=0) log_message( log_module, MSG_DETAIL, "Average packets in the buffer %d\n", params->stats_infos->stats_num_packets_received/params->stats_infos->stats_num_reads); else log_message( log_module, MSG_DETAIL, "Average packets in the buffer cannot be calculated - No packets read!\n"); params->stats_infos->stats_num_packets_received=0; params->stats_infos->stats_num_reads=0; num_big_buffer_show++; if(num_big_buffer_show==10) params->stats_infos->show_buffer_stats=0; } } /*******************************************/ /* Periodically flush the logs if asked */ /*******************************************/ if((log_params.log_file) && (log_params.log_flush_interval !=-1)) { if(!last_flush_time) { last_flush_time=monitor_now; fflush(log_params.log_file); } if((monitor_now-last_flush_time)>=log_params.log_flush_interval) { log_message( log_module, MSG_FLOOD, "Flushing logs\n"); fflush(log_params.log_file); last_flush_time=monitor_now; } } /*******************************************/ /* Check if the channel scrambling state */ /* has changed */ /*******************************************/ // Current thresholds for calculation // (<2%) FULLY_UNSCRAMBLED // (5%<=ratio<=75%) PARTIALLY_UNSCRAMBLED // (>80%) HIGHLY_SCRAMBLED // The gap is an hysteresis to avoid excessive jumping between states for (curr_channel = 0; curr_channel < params->chan_p->number_of_channels; curr_channel++) { mumudvb_channel_t *current; current=¶ms->chan_p->channels[curr_channel]; if(current->channel_readystats_lock); /* Calculation of the ratio (percentage) of scrambled packets received*/ if (current->num_packet >0 && current->num_scrambled_packets>10) current->ratio_scrambled = (int)(current->num_scrambled_packets*100/(current->num_packet)); else current->ratio_scrambled = 0; /* Test if we have only unscrambled packets (<2%) - scrambled_channel=FULLY_UNSCRAMBLED : fully unscrambled*/ if ((current->ratio_scrambled < 2) && (current->scrambled_channel != FULLY_UNSCRAMBLED)) { log_message( log_module, MSG_INFO, "Channel \"%s\" is now fully unscrambled (%d%% of scrambled packets). Card %d\n", current->name, current->ratio_scrambled, params->tune_p->card); current->scrambled_channel = FULLY_UNSCRAMBLED;// update } /* Test if we have partially unscrambled packets (5%<=ratio<=75%) - scrambled_channel=PARTIALLY_UNSCRAMBLED : partially unscrambled*/ if ((current->ratio_scrambled >= 5) && (current->ratio_scrambled <= 75) && (current->scrambled_channel != PARTIALLY_UNSCRAMBLED)) { log_message( log_module, MSG_INFO, "Channel \"%s\" is now partially unscrambled (%d%% of scrambled packets). Card %d\n", current->name, current->ratio_scrambled, params->tune_p->card); current->scrambled_channel = PARTIALLY_UNSCRAMBLED;// update } /* Test if we have nearly only scrambled packets (>80%) - scrambled_channel=HIGHLY_SCRAMBLED : highly scrambled*/ if ((current->ratio_scrambled > 80) && current->scrambled_channel != HIGHLY_SCRAMBLED) { log_message( log_module, MSG_INFO, "Channel \"%s\" is now highly scrambled (%d%% of scrambled packets). Card %d\n", current->name, current->ratio_scrambled, params->tune_p->card); current->scrambled_channel = HIGHLY_SCRAMBLED;// update } /* Check the PID scrambling state */ int curr_pid; for (curr_pid = 0; curr_pid < current->pid_i.num_pids; curr_pid++) { if (current->pid_i.pids_num_scrambled_packets[curr_pid]>0) current->pid_i.pids_scrambled[curr_pid]=1; else current->pid_i.pids_scrambled[curr_pid]=0; current->pid_i.pids_num_scrambled_packets[curr_pid]=0; } pthread_mutex_unlock(¤t->stats_lock); } /*******************************************/ /* Check if the channel stream state */ /* has changed */ /*******************************************/ if(last_updown_check) { /* Check if the channel stream state has changed*/ for (curr_channel = 0; curr_channel < params->chan_p->number_of_channels; curr_channel++) { mumudvb_channel_t *current; current=¶ms->chan_p->channels[curr_channel]; if(current->channel_readystats_lock); if(dont_send_scrambled) { num_scrambled=current->num_scrambled_packets; } else num_scrambled=0; if (monitor_now>last_updown_check) packets_per_sec=((double)current->num_packet-num_scrambled)/(monitor_now-last_updown_check); else packets_per_sec=0; pthread_mutex_unlock(¤t->stats_lock); if( params->stats_infos->debug_updown) { log_message( log_module, MSG_FLOOD, "Channel \"%s\" streamed_channel %f packets/s\n", current->name,packets_per_sec); } if ((packets_per_sec >= params->stats_infos->up_threshold) && (!current->has_traffic)) { log_message( log_module, MSG_INFO, "Channel \"%s\" back.Card %d\n", current->name, params->tune_p->card); current->has_traffic = 1; // update } else if ((current->has_traffic) && (packets_per_sec < params->stats_infos->down_threshold)) { log_message( log_module, MSG_INFO, "Channel \"%s\" down.Card %d\n", current->name, params->tune_p->card); current->has_traffic = 0; // update } } } /* reinit */ for (curr_channel = 0; curr_channel < params->chan_p->number_of_channels; curr_channel++) { mumudvb_channel_t *current; current=¶ms->chan_p->channels[curr_channel]; if(current->channel_readystats_lock); params->chan_p->channels[curr_channel].num_packet = 0; params->chan_p->channels[curr_channel].num_scrambled_packets = 0; pthread_mutex_unlock(¤t->stats_lock); } last_updown_check=monitor_now; /*******************************************/ /* we count active channels */ /*******************************************/ int count_of_active_channels=0; for (curr_channel = 0; curr_channel < params->chan_p->number_of_channels; curr_channel++) if (params->chan_p->channels[curr_channel].has_traffic && params->chan_p->channels[curr_channel].channel_ready>=READY ) count_of_active_channels++; /*Time no diff is the time when we got 0 active channels*/ /*if we have active channels, we reinit this counter*/ if(count_of_active_channels) time_no_diff=0; /*If we don't have active channels and this is the first time, we store the time*/ else if(!time_no_diff) time_no_diff=(long)monitor_now; /*******************************************/ /* If we don't stream data for */ /* a too long time, we exit */ /*******************************************/ if((timeout_no_diff)&& (time_no_diff&&((monitor_now-time_no_diff)>timeout_no_diff))) { log_message( log_module, MSG_ERROR, "No data from card %d in %ds, exiting.\n", params->tune_p->card, timeout_no_diff); set_interrupted(ERROR_NO_DIFF<<8); //the <<8 is to make difference between signals and errors } #ifdef ENABLE_SCAM_SUPPORT if (scam_vars->scam_support) { /*******************************************/ /* we check num of packets in ring buffer */ /*******************************************/ for (curr_channel = 0; curr_channel < params->chan_p->number_of_channels; curr_channel++) { mumudvb_channel_t *channel = ¶ms->chan_p->channels[curr_channel]; if (channel->scam_support && channel->channel_ready>=READY) { //send capmt if needed if (channel->need_scam_ask==CAM_NEED_ASK) { if (channel->scam_support) { pthread_mutex_lock(&channel->scam_pmt_packet->packetmutex); if (channel->scam_pmt_packet->len_full != 0 ) { if (!scam_send_capmt(channel, scam_vars ,params->tune_p->card)) { channel->need_scam_ask=CAM_ASKED; } } pthread_mutex_unlock(&channel->scam_pmt_packet->packetmutex); } } unsigned int ring_buffer_num_packets = 0; unsigned int to_descramble = 0; unsigned int to_send = 0; if (channel->ring_buf) { pthread_mutex_lock(&channel->ring_buf->lock); to_descramble = channel->ring_buf->to_descramble; to_send = channel->ring_buf->to_send; ring_buffer_num_packets = to_descramble + to_send; pthread_mutex_unlock(&channel->ring_buf->lock); } if (ring_buffer_num_packets>=channel->ring_buffer_size) log_message( log_module, MSG_ERROR, "%s: ring buffer overflow, packets in ring buffer %u, ring buffer size %llu\n",channel->name, ring_buffer_num_packets, (long long unsigned int)channel->ring_buffer_size); else log_message( log_module, MSG_DEBUG, "%s: packets in ring buffer %u, ring buffer size %llu, to descramble %u, to send %u\n",channel->name, ring_buffer_num_packets, (long long unsigned int)channel->ring_buffer_size, to_descramble, to_send); } } } #endif /*******************************************/ /* generation of the file which says */ /* the streamed channels */ /*******************************************/ if (write_streamed_channels) gen_file_streamed_channels(params->filename_channels_streamed, params->filename_channels_not_streamed, params->chan_p->number_of_channels, params->chan_p->channels); pthread_mutex_unlock(¶ms->chan_p->lock); for(i=0;iwait_time && !params->threadshutdown;i++) usleep(100000); } log_message(log_module,MSG_DEBUG, "Monitor thread stopping, it lasted %f seconds\n", monitor_now); return 0; } MuMuDVB-2.1.0/src/mumudvb_mon.h000066400000000000000000000023151305714132500162230ustar00rootroot00000000000000 #ifndef _MUMUDVB_MON_H #define _MUMUDVB_MON_H #include "mumudvb.h" #include "tune.h" #include "network.h" #include "dvb.h" #ifdef ENABLE_CAM_SUPPORT #include "cam.h" #endif #ifdef ENABLE_SCAM_SUPPORT #include "scam_capmt.h" #include "scam_common.h" #include "scam_getcw.h" #include "scam_decsa.h" #endif #include "ts.h" #include "errors.h" #include "autoconf.h" #include "sap.h" #include "rewrite.h" #include "unicast_http.h" #include "rtp.h" #include "log.h" void *monitor_func(void* arg); int mumudvb_close(int no_daemon, monitor_parameters_t *monitor_thread_params, rewrite_parameters_t *rewrite_vars, auto_p_t *auto_p, unicast_parameters_t *unicast_vars, volatile int *strengththreadshutdown, void *cam_p_v, void *scam_vars_v, char *filename_channels_not_streamed, char *filename_channels_streamed, char *filename_pid, int Interrupted, mumu_chan_p_t *chan_p, pthread_t *signalpowerthread, pthread_t *monitorthread, card_thread_parameters_t *cardthreadparams, fds_t *fds); void parse_cmd_line(int argc, char **argv, char **conf_filename, tune_p_t *tune_p, stats_infos_t *stats_infos, int *server_id, int *no_daemon, char **dump_filename, int *listingcards); #endif MuMuDVB-2.1.0/src/mumudvb_test.c000066400000000000000000000470461305714132500164160ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * Testing suite * * (C) 2010 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* The test files can be found here : http://mumudvb.braice.net/mumudvb/test/ */ // To compile this code, run "make check" #define PRESS_ENTER 1 #define FILES_TEST_READ_SDT_TS "tests/BBC123_pids0_18.dump.ts", "tests/TestDump17.ts"//,"tests/test_autoconf_numericableparis_PAT_SDT.ts","tests/astra_TP_11856.00V_PAT_SDT.ts" #define NUM_READ_SDT 100 #define NUM_FILES_TEST_READ_SDT 2 #define FILES_TEST_READ_RAND "tests/random_1.ts","tests/random_2.ts" #define NUM_FILES_TEST_READ_RAND 2 #define TEST_STRING_COMPUT "2+2*3+100" #define TEST_STRING_COMPUT_RES 108 #define FILES_TEST_AUTOCONF "tests/astra_TP_11856.00V_pids_0_18.ts","tests/test_autoconf_numericableparis.ts","tests/astra_TP_11856.00V_pids_0_18__2.ts","tests/BBC123.dump.ts","tests/Astra19.2-12187.50-German.cap" #define NUM_FILES_TEST_AUTOCONF 5 #include #include #include #include "ts.h" #include "mumudvb.h" #include "log.h" #include "autoconf.h" #include "rewrite.h" //Prototypes void autoconf_free_services(mumudvb_service_t *services); int autoconf_read_sdt(unsigned char *buf,int len, mumudvb_service_t *services); void autoconf_sort_services(mumudvb_service_t *services); //Functions implemented here void autoconf_print_services(mumudvb_service_t *services); int autoconf_count_services(mumudvb_service_t *services); int Interrupted; long real_start_time; multicast_parameters_t multicast_vars; extern log_params_t log_params; static char *log_module="======TEST======: "; void press_enter_func(int press_enter) { if(press_enter) { log_message( log_module, MSG_INFO,"================= Press enter to continue =========================\n"); getchar(); } else log_message( log_module, MSG_INFO,"===================================================================\n"); } int main(void) { int press_enter = PRESS_ENTER; //We initalise the logging parameters log_params.verbosity = 999; log_params.log_type=LOGGING_CONSOLE; log_message( log_module, MSG_INFO,"===================================================================\n"); log_message( log_module, MSG_INFO,"Testing program for MuMuDVB\n"); log_message( log_module, MSG_INFO,"===================================================================\n"); /**************************** Very basic test ****************************************************/ log_message( log_module, MSG_INFO,"===================================================================\n"); log_message( log_module, MSG_INFO,"Display Ca system id 1\n" ); log_message( log_module, MSG_INFO,"===================================================================\n"); log_message( log_module, MSG_INFO,"%s\n\n" ,ca_sys_id_to_str(1)); /**************************** Testing string compute *********************************************/ log_message( log_module, MSG_INFO,"===================================================================\n"); log_message( log_module, MSG_INFO,"Testing string compute %s\n",TEST_STRING_COMPUT ); log_message( log_module, MSG_INFO,"===================================================================\n"); int resultat; resultat=string_comput(TEST_STRING_COMPUT); if(resultat==TEST_STRING_COMPUT_RES) log_message( log_module, MSG_INFO,"%d -- PASS\n\n" ,resultat); else log_message( log_module, MSG_INFO,"%d -- FAIL\n\n" ,resultat); char *ip0="239.100+3.%card+1.%number"; char ip[80]; char ipd[80]; strcpy(ip,ip0); int len=80; int n[4]; mumu_string_replace(ip,&len,0,"%number","1"); mumu_string_replace(ip,&len,0,"%card","42"); mumu_string_replace(ip,&len,0,"%tuner","0"); mumu_string_replace(ip,&len,0,"%server","0"); // Compute the string, ex: 239.255.130+0*10+2.1 log_message( log_module, MSG_DEBUG,"Computing expressions in string \"%s\"\n",ip); char *sptr; //Splitting and computing. use of strtok_r because it's safer n[0]=string_comput(strtok_r (ip,".",&sptr)); n[1]=string_comput(strtok_r (NULL,".",&sptr)); n[2]=string_comput(strtok_r (NULL,".",&sptr)); n[3]=string_comput(strtok_r (NULL,".",&sptr)); log_message( log_module, MSG_DEBUG,"%d.%d.%d.%d",n[0],n[1],n[2],n[3]); char *ip1="239.100+300.abcdef"; strcpy(ip,ip1); log_message( log_module, MSG_DEBUG,"Computing expressions in string \"%s\"\n",ip); //Splitting and computing. use of strtok_r because it's safer n[0]=string_comput(strtok_r (ip,".",&sptr)); n[1]=string_comput(strtok_r (NULL,".",&sptr)); n[2]=string_comput(strtok_r (NULL,".",&sptr)); n[3]=string_comput(strtok_r (NULL,".",&sptr)); log_message( log_module, MSG_DEBUG,"%d.%d.%d.%d",n[0],n[1],n[2],n[3]); /************************************* Testing the SDT parser *************************************/ char *files_sdt[NUM_FILES_TEST_READ_SDT]={FILES_TEST_READ_SDT_TS}; for(int i_file=0;i_filepid); if(pid != 17) continue; log_message( log_module, MSG_DEBUG,"New elementary (188bytes TS packet) pid %d continuity_counter %d", pid, ((ts_header_t *)ts_packet_raw)->continuity_counter ); iRet=get_ts_packet(ts_packet_raw, &ts_packet_mumu); //If it's the beginning of a new packet we display some information if(((ts_header_t *)ts_packet_raw)->payload_unit_start_indicator) log_message(log_module, MSG_FLOOD, "First two bytes of the packet 0x%02x %02x", ts_packet_mumu.data_partial[0], ts_packet_mumu.data_partial[1]); if(iRet==1)//packet is parsed { log_message( log_module, MSG_INFO,"New packet -- parsing\n" ); num_sdt_read++; autoconf_read_sdt(ts_packet_mumu.data_full,ts_packet_mumu.len_full,&services); } } log_message( log_module, MSG_INFO,"Final services list .... \n"); autoconf_print_services(&services); log_message( log_module, MSG_INFO,"===================================================================\n"); log_message( log_module, MSG_INFO,"Testing service sorting on this list\n" ); press_enter_func(press_enter); autoconf_sort_services(&services); autoconf_print_services(&services); //We free starting at the next since the first is not malloc'ed autoconf_free_services(services.next); fclose(testfile); } else log_message( log_module, MSG_INFO,"Test file %s cannot be open : %s\n", files_sdt[i_file],strerror(errno) ); } /************************************* Testing the resistance to strange data *********************/ log_message( log_module, MSG_INFO,"===================================================================\n"); char *files_rand[NUM_FILES_TEST_READ_RAND]={FILES_TEST_READ_RAND}; for(int i_file=0;i_filepacketmutex,NULL); while(fread(actual_ts_packet,TS_PACKET_SIZE,1, testfile)) { // get the pid of the received ts packet pid = ((actual_ts_packet[1] & 0x1f) << 8) | (actual_ts_packet[2]); if( (pid == 17) ) //This is a SDT PID { //we check the new packet and if it's fully updated we set the skip to 0 if(sdt_rewrite_new_global_packet(actual_ts_packet, &rewrite_vars)==1) { log_message( log_module, MSG_DETAIL,"The SDT version changed, we force the update of all the channels.\n"); for (int curr_channel = 0; curr_channel < chan_and_pids.number_of_channels; curr_channel++) chan_and_pids.channels[curr_channel].sdt_rewrite_skip=0; } for (int curr_channel = 0; curr_channel < chan_and_pids.number_of_channels; curr_channel++) { if(!chan_and_pids.channels[curr_channel].sdt_rewrite_skip ) //AND the generation was successful sdt_rewrite_new_channel_packet(actual_ts_packet, &rewrite_vars, &chan_and_pids.channels[curr_channel], curr_channel); } } } fclose(testfile); log_message( log_module, MSG_INFO,"===================================================================\n"); log_message( log_module, MSG_INFO,"End of testing SDT rewritef\n"); log_message( log_module, MSG_INFO,"===================================================================\n"); } } else log_message( log_module, MSG_INFO,"No channels generated by the autoconfiguration\n"); autoconf_freeing(&autoconf_vars); } else log_message( log_module, MSG_INFO,"Test file %s cannot be open : %s\n", files_rand[i_file], strerror(errno) ); } /**************************************************************************************************/ /**************************************************************************************************/ //log_message( log_module, MSG_INFO,"===================================================================\n"); //press_enter_func(press_enter); /**************************************************************************************************/ /**************************************************************************************************/ log_message( log_module, MSG_INFO,"===================================================================\n"); log_message( log_module, MSG_INFO,"=========================== Testing done ==========================\n"); } void autoconf_print_services(mumudvb_service_t *services) { mumudvb_service_t *act_service; if(services) act_service=services->next; else act_service=NULL; while(act_service!=NULL) { log_message( log_module, MSG_INFO,"Services listing\n"); log_message( log_module, MSG_INFO,"Service : id %d running_status %d free_ca_mode %d\n", act_service->id, act_service->running_status, act_service->free_ca_mode); log_message( log_module, MSG_INFO,"name %s\n", act_service->name); log_message( log_module, MSG_INFO,"pmt_pid %d\n", act_service->pmt_pid); display_service_type(act_service->type, MSG_DEBUG,log_module); act_service=act_service->next; } } MuMuDVB-2.1.0/src/network.c000066400000000000000000000252151305714132500153630ustar00rootroot00000000000000/* * udp.h fonction in order to send a multicast stream * mumudvb - UDP-ize a DVB transport stream. * * (C) 2004-2013 Brice DUBOST * (C) Dave Chapman 2001, 2002. * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /**@file * @brief Networking functions */ #include "network.h" #include "errors.h" #include #include #include #include "log.h" #include #include static char *log_module="Network: "; /**@brief Send data * just send the data over the socket fd */ void sendudp (int fd, struct sockaddr_in *sSockAddr, unsigned char *data, int len) { int ret; ret=sendto (fd, data, len, 0, (struct sockaddr *) sSockAddr, sizeof (*sSockAddr)); if(ret<0) log_message( log_module, MSG_WARN,"sendto failed : %s\n", strerror(errno)); } /**@brief Send data * just send the data over the socket fd */ void sendudp6 (int fd, struct sockaddr_in6 *sSockAddr, unsigned char *data, int len) { int ret; ret=sendto (fd, data, len, 0, (struct sockaddr *) sSockAddr, sizeof (*sSockAddr)); if(ret<0) log_message( log_module, MSG_WARN,"sendto failed : %s\n", strerror(errno)); } /** @brief create a sender socket. * * Create a socket for sending data, the socket is multicast, udp, with the options REUSE_ADDR et MULTICAST_LOOP set to 1 */ int makesocket (char *szAddr, unsigned short port, int TTL, char *iface, struct sockaddr_in *sSockAddr) { int iRet, iLoop = 1; struct sockaddr_in sin; int iReuse = 1; int iSocket = socket (AF_INET, SOCK_DGRAM, 0); if (iSocket < 0) { log_message( log_module, MSG_WARN, "socket() failed : %s\n",strerror(errno)); set_interrupted(ERROR_NETWORK<<8); return -1; } sSockAddr->sin_family = sin.sin_family = AF_INET; sSockAddr->sin_port = sin.sin_port = htons (port); iRet=inet_aton (szAddr,&sSockAddr->sin_addr); if (iRet == 0) { log_message( log_module, MSG_ERROR,"inet_aton failed : %s\n", strerror(errno)); set_interrupted(ERROR_NETWORK<<8); close(iSocket); return -1; } iRet = setsockopt (iSocket, SOL_SOCKET, SO_REUSEADDR, &iReuse, sizeof (int)); if (iRet < 0) { log_message( log_module, MSG_ERROR,"setsockopt SO_REUSEADDR failed : %s\n",strerror(errno)); set_interrupted(ERROR_NETWORK<<8); close(iSocket); return -1; } iRet = setsockopt (iSocket, IPPROTO_IP, IP_MULTICAST_TTL, &TTL, sizeof (int)); if (iRet < 0) { log_message( log_module, MSG_ERROR,"setsockopt IP_MULTICAST_TTL failed. multicast in kernel? error : %s \n",strerror(errno)); set_interrupted(ERROR_NETWORK<<8); close(iSocket); return -1; } iRet = setsockopt (iSocket, IPPROTO_IP, IP_MULTICAST_LOOP, &iLoop, sizeof (int)); if (iRet < 0) { log_message( log_module, MSG_ERROR,"setsockopt IP_MULTICAST_LOOP failed. multicast in kernel? error : %s\n",strerror(errno)); set_interrupted(ERROR_NETWORK<<8); close(iSocket); return -1; } if(strlen(iface)) { int iface_index; iface_index = if_nametoindex(iface); if(iface_index) { log_message( log_module, MSG_DEBUG, "Setting IPv4 multicast iface to %s, index %d",iface,iface_index); struct ip_mreqn iface_struct; iface_struct.imr_multiaddr.s_addr=INADDR_ANY; iface_struct.imr_address.s_addr=INADDR_ANY; iface_struct.imr_ifindex=iface_index; iRet = setsockopt (iSocket, IPPROTO_IP, IP_MULTICAST_IF, &iface_struct, sizeof (struct ip_mreqn)); if (iRet < 0) { log_message( log_module, MSG_ERROR,"setsockopt IP_MULTICAST_IF failed. multicast in kernel? error : %s \n",strerror(errno)); set_interrupted(ERROR_NETWORK<<8); close(iSocket); return -1; } } else log_message( log_module, MSG_ERROR,"Setting IPV4 multicast interface: Interface %s does not exist",iface); } return iSocket; } /** @brief create an IPv6 sender socket. * * Create a socket for sending data, the socket is multicast, udp, with the options REUSE_ADDR et MULTICAST_LOOP set to 1 */ int makesocket6 (char *szAddr, unsigned short port, int TTL, char *iface, struct sockaddr_in6 *sSockAddr) { int iRet; int iReuse=1; struct sockaddr_in6 sin; int iSocket = socket (AF_INET6, SOCK_DGRAM, IPPROTO_UDP); if (iSocket < 0) { log_message( log_module, MSG_WARN, "socket() failed : %s\n",strerror(errno)); set_interrupted(ERROR_NETWORK<<8); return -1; } sSockAddr->sin6_family = sin.sin6_family = AF_INET6; sSockAddr->sin6_port = sin.sin6_port = htons (port); iRet=inet_pton (AF_INET6, szAddr,&sSockAddr->sin6_addr); if (iRet != 1) { log_message( log_module, MSG_ERROR,"inet_pton failed : %s\n", strerror(errno)); set_interrupted(ERROR_NETWORK<<8); close(iSocket); return -1; } iRet = setsockopt (iSocket, SOL_SOCKET, SO_REUSEADDR, &iReuse, sizeof (int)); if (iRet < 0) { log_message( log_module, MSG_ERROR,"setsockopt SO_REUSEADDR failed : %s\n",strerror(errno)); set_interrupted(ERROR_NETWORK<<8); close(iSocket); return -1; } iRet = setsockopt (iSocket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &TTL, sizeof (int)); if (iRet < 0) { log_message( log_module, MSG_ERROR,"setsockopt IPV6_MULTICAST_HOPS failed. multicast in kernel? error : %s \n",strerror(errno)); set_interrupted(ERROR_NETWORK<<8); close(iSocket); return -1; } if(strlen(iface)) { int iface_index; iface_index = if_nametoindex(iface); if(iface_index) { log_message( log_module, MSG_DEBUG, "Setting IPv6 multicast iface to %s, index %d",iface,iface_index); iRet = setsockopt (iSocket, IPPROTO_IPV6, IPV6_MULTICAST_IF, &iface_index, sizeof (int)); if (iRet < 0) { log_message( log_module, MSG_ERROR,"setsockopt IPV6_MULTICAST_IF failed. multicast in kernel? error : %s \n",strerror(errno)); set_interrupted(ERROR_NETWORK<<8); close(iSocket); return -1; } } else log_message( log_module, MSG_ERROR,"Setting IPv6 multicast interface: Interface %s does not exist",iface); } return iSocket; } /** @brief create a receiver socket, i.e. join the multicast group. *@todo document */ int makeclientsocket (char *szAddr, unsigned short port, int TTL, char *iface, struct sockaddr_in *sSockAddr) { int socket; struct ip_mreqn blub; struct sockaddr_in sin; memset(&sin, 0, sizeof sin); unsigned int tempaddr; socket = makesocket (szAddr, port, TTL, iface, sSockAddr); if(socket<0) return 0; sin.sin_family = AF_INET; sin.sin_port = htons (port); sin.sin_addr.s_addr = inet_addr (szAddr); if (bind (socket, (struct sockaddr *) &sin, sizeof (sin))) { log_message( log_module, MSG_ERROR, "bind failed : %s\n", strerror(errno)); set_interrupted(ERROR_NETWORK<<8); } tempaddr = inet_addr (szAddr); if ((ntohl (tempaddr) >> 28) == 0xe) { blub.imr_multiaddr.s_addr = inet_addr (szAddr); if(strlen(iface)) blub.imr_ifindex=if_nametoindex(iface); else blub.imr_ifindex = 0; if (setsockopt (socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &blub, sizeof (blub))) { log_message( log_module, MSG_ERROR, "setsockopt IP_ADD_MEMBERSHIP ipv4 failed (multicast kernel?) : %s\n", strerror(errno)); set_interrupted(ERROR_NETWORK<<8); } } return socket; } /** @brief create a receiver socket, i.e. join the multicast group. *@todo document */ int makeclientsocket6 (char *szAddr, unsigned short port, int TTL, char *iface, struct sockaddr_in6 *sSockAddr) { int socket = makesocket6 (szAddr, port, TTL, iface, sSockAddr); if (socket < 0) return -1; struct ipv6_mreq blub; struct sockaddr_in6 sin; memset(&sin, 0, sizeof sin); int iRet; sin.sin6_family = AF_INET6; sin.sin6_port = htons (port); iRet=inet_pton (AF_INET6, szAddr,&sin.sin6_addr); if (iRet != 1) { log_message( log_module, MSG_ERROR,"inet_pton failed : %s\n", strerror(errno)); close(socket); set_interrupted(ERROR_NETWORK<<8); return 0; } if (bind (socket, (struct sockaddr *) &sin, sizeof (sin))) { log_message( log_module, MSG_ERROR, "bind failed : %s\n", strerror(errno)); close(socket); set_interrupted(ERROR_NETWORK<<8); return 0; } //join the group iRet=inet_pton (AF_INET6, szAddr,&blub.ipv6mr_multiaddr); if (iRet != 1) { log_message( log_module, MSG_ERROR,"inet_pton failed : %s\n", strerror(errno)); set_interrupted(ERROR_NETWORK<<8); close(socket); return -1; } if(strlen(iface)) blub.ipv6mr_interface=if_nametoindex(iface); else blub.ipv6mr_interface = 0; if (setsockopt (socket, IPPROTO_IPV6, IPV6_JOIN_GROUP, &blub, sizeof (blub))) { log_message( log_module, MSG_ERROR, "setsockopt IPV6_JOIN_GROUP (ipv6) failed (multicast kernel?) : %s\n", strerror(errno)); set_interrupted(ERROR_NETWORK<<8); } return socket; } /** @brief create a TCP receiver socket. * * Create a socket for waiting the HTTP connection */ int makeTCPclientsocket (char *szAddr, unsigned short port, struct sockaddr_in *sSockAddr) { int iRet, iLoop = 1; int iSocket = socket (AF_INET, SOCK_STREAM, 0); //TCP if (iSocket < 0) { log_message( log_module, MSG_ERROR, "socket() failed.\n"); return -1; } sSockAddr->sin_family = AF_INET; sSockAddr->sin_port = htons (port); iRet=inet_aton (szAddr,&sSockAddr->sin_addr); if (iRet == 0) { log_message( log_module, MSG_ERROR,"inet_aton failed : %s\n", strerror(errno)); close(iSocket); return -1; } iRet = setsockopt (iSocket, SOL_SOCKET, SO_REUSEADDR, &iLoop, sizeof (int)); if (iRet < 0) { log_message( log_module, MSG_ERROR,"setsockopt SO_REUSEADDR failed : %s\n", strerror(errno)); close(iSocket); return -1; } if (bind (iSocket, (struct sockaddr *) sSockAddr, sizeof (*sSockAddr))) { log_message( log_module, MSG_ERROR, "bind failed : %s\n", strerror(errno)); close(iSocket); return -1; } iRet = listen(iSocket,10); if (iRet < 0) { log_message( log_module, MSG_ERROR,"listen failed : %s\n",strerror(errno)); close(iSocket); return -1; } //Now we set this socket to be non blocking because we poll it int flags; flags = fcntl(iSocket, F_GETFL, 0); flags |= O_NONBLOCK; if (fcntl(iSocket, F_SETFL, flags) < 0) { log_message( log_module, MSG_ERROR,"Set non blocking failed : %s\n",strerror(errno)); close(iSocket); return -1; } return iSocket; } MuMuDVB-2.1.0/src/network.h000066400000000000000000000037041305714132500153670ustar00rootroot00000000000000/* * mumudvb - UDP-ize a DVB transport stream. * Based on dvbstream by (C) Dave Chapman 2001, 2002. * * (C) 2004-2009 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /**@file * @brief Networking functions */ #ifndef _NETWORK_H #define _NETWORK_H #include #include #include #include #include #include #include #include /** The default time to live*/ #define DEFAULT_TTL 2 int makeclientsocket (char *szAddr, unsigned short port, int TTL, char *iface, struct sockaddr_in *sSockAddr); void sendudp (int fd, struct sockaddr_in *sSockAddr, unsigned char *data, int len); int makesocket (char *szAddr, unsigned short port, int TTL, char *iface, struct sockaddr_in *sSockAddr); int makeTCPclientsocket (char *szAddr, unsigned short port, struct sockaddr_in *sSockAddr); int makeclientsocket6 (char *szAddr, unsigned short port, int TTL, char *iface, struct sockaddr_in6 *sSockAddr); void sendudp6 (int fd, struct sockaddr_in6 *sSockAddr, unsigned char *data, int len); int makesocket6 (char *szAddr, unsigned short port, int TTL, char *iface, struct sockaddr_in6 *sSockAddr); #endif MuMuDVB-2.1.0/src/rewrite.c000066400000000000000000000146651305714132500153620ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * * (C) 2004-2010 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /**@file * @brief This file contains the general functions for rewriting */ #include #include #include #include "mumudvb.h" #include "ts.h" #include "rewrite.h" #include "log.h" #include "errors.h" #include static char *log_module="Rewrite: "; /** Initialize Rewrite variables*/ void init_rewr_v(rewrite_parameters_t *rewr_p) { *rewr_p=(rewrite_parameters_t){ .rewrite_pmt = OPTION_UNDEFINED, .rewrite_pat = OPTION_UNDEFINED, .pat_version=-1, .full_pat=NULL, .pat_needs_update=1, .full_pat_ok=0, .pat_continuity_counter=0, .rewrite_sdt = OPTION_UNDEFINED, .sdt_version=-1, .full_sdt=NULL, .sdt_needs_update=1, .full_sdt_ok=0, .sdt_continuity_counter=0, .rewrite_eit=OPTION_UNDEFINED, .store_eit=OPTION_UNDEFINED, .eit_version=-1, .full_eit=NULL, .eit_needs_update=0, .sdt_force_eit=OPTION_UNDEFINED, .eit_packets=NULL, }; } int rewrite_init(rewrite_parameters_t *rewr_p) { /*****************************************************/ //Pat rewriting //memory allocation for MPEG2-TS //packet structures /*****************************************************/ if(rewr_p->rewrite_pat == OPTION_ON) { rewr_p->full_pat=malloc(sizeof(mumudvb_ts_packet_t)); if(rewr_p->full_pat==NULL) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); set_interrupted(ERROR_MEMORY<<8); return 1; } memset (rewr_p->full_pat, 0, sizeof( mumudvb_ts_packet_t));//we clear it pthread_mutex_init(&rewr_p->full_pat->packetmutex,NULL); } /*****************************************************/ //SDT rewriting //memory allocation for MPEG2-TS //packet structures /*****************************************************/ if(rewr_p->rewrite_sdt == OPTION_ON) { rewr_p->full_sdt=malloc(sizeof(mumudvb_ts_packet_t)); if(rewr_p->full_sdt==NULL) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); set_interrupted(ERROR_MEMORY<<8); return 1; } memset (rewr_p->full_sdt, 0, sizeof( mumudvb_ts_packet_t));//we clear it pthread_mutex_init(&rewr_p->full_sdt->packetmutex,NULL); } /*****************************************************/ //EIT rewriting //memory allocation for MPEG2-TS //packet structures /*****************************************************/ if(rewr_p->rewrite_eit == OPTION_ON || rewr_p->store_eit == OPTION_ON) { rewr_p->full_eit=malloc(sizeof(mumudvb_ts_packet_t)); if(rewr_p->full_eit==NULL) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); set_interrupted(ERROR_MEMORY<<8); return 1; } memset (rewr_p->full_eit, 0, sizeof( mumudvb_ts_packet_t));//we clear it pthread_mutex_init(&rewr_p->full_eit->packetmutex,NULL); } return 0; } /** @brief Read a line of the configuration file to check if there is a rewrite parameter * * @param rewrite_vars the autoconfiguration parameters * @param substring The currrent line */ int read_rewrite_configuration(rewrite_parameters_t *rewrite_vars, char *substring) { char delimiteurs[] = CONFIG_FILE_SEPARATOR; if (!strcmp (substring, "rewrite_pmt")) { substring = strtok (NULL, delimiteurs); if(atoi (substring)) { rewrite_vars->rewrite_pmt = OPTION_ON; log_message( log_module, MSG_INFO, "You have enabled the PMT Rewriting\n"); } else rewrite_vars->rewrite_pmt = OPTION_OFF; } else if (!strcmp (substring, "rewrite_pat")) { substring = strtok (NULL, delimiteurs); if(atoi (substring)) { rewrite_vars->rewrite_pat = OPTION_ON; log_message( log_module, MSG_INFO, "You have enabled the PAT Rewriting\n"); } else rewrite_vars->rewrite_pat = OPTION_OFF; } else if (!strcmp (substring, "rewrite_sdt")) { substring = strtok (NULL, delimiteurs); if(atoi (substring)) { rewrite_vars->rewrite_sdt = OPTION_ON; log_message( log_module, MSG_INFO, "You have enabled the SDT Rewriting\n"); } else rewrite_vars->rewrite_sdt = OPTION_OFF; } else if ( (!strcmp (substring, "sort_eit")) || (!strcmp (substring, "rewrite_eit"))) { substring = strtok (NULL, delimiteurs); if(atoi (substring)) { rewrite_vars->rewrite_eit = OPTION_ON; log_message( log_module, MSG_INFO, "You have enabled the EIT rewriting\n"); } else rewrite_vars->rewrite_eit = OPTION_OFF; } else if ((!strcmp (substring, "store_eit"))) { substring = strtok (NULL, delimiteurs); if(atoi (substring)) { rewrite_vars->store_eit = OPTION_ON; log_message( log_module, MSG_INFO, "You have enabled the EIT (EPG) storage for webservices"); } else rewrite_vars->store_eit = OPTION_OFF; } else if (!strcmp (substring, "sdt_force_eit")) { substring = strtok (NULL, delimiteurs); if(atoi (substring)) { rewrite_vars->sdt_force_eit = OPTION_ON; log_message( log_module, MSG_INFO, "You have enabled the forcing of the EIT flag in the SDT rewrite\n"); } else rewrite_vars->sdt_force_eit = OPTION_OFF; } else return 0; //Nothing concerning rewrite, we return 0 to explore the other possibilities return 1;//We found something for rewrite, we tell main to go for the next line } /** @brief Just a small function to change the continuity counter of a packet * This function will overwrite the continuity counter of the packet with the one given in argument * */ void set_continuity_counter(unsigned char *buf,int continuity_counter) { ts_header_t *ts_header=(ts_header_t *)buf; ts_header->continuity_counter=continuity_counter; } MuMuDVB-2.1.0/src/rewrite.h000066400000000000000000000116571305714132500153650ustar00rootroot00000000000000/* * mumudvb - UDP-ize a DVB transport stream. * * (C) 2009-2013 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /**@file * @brief This file contains the headers for the functions for rewriting the pat pid * * The pat rewrite is made to announce only the video stream associated with the channel in the PAT pid * Some set top boxes need it */ #ifndef _REWRITE_H #define _REWRITE_H #include #include #include #include "mumudvb.h" #include "ts.h" #include "unicast_http.h" #include /** @brief the structure for storing an EIT PID for a particular SID * This structure contains the packet and several flags around */ typedef struct eit_packet_t{ /**The service ID of the EIT*/ int service_id; /** The table ID */ uint8_t table_id; /**The actual version of the EIT PID*/ int version; /**Do the actual full EIT needs to be updated ?*/ int needs_update; /** Do we need to see other EIT ?*/ int need_others; /** The last_section_number of the current version */ int last_section_number; /** Array storing the section numbers we saw */ int sections_stored[256]; /**Do the full EIT is ok ?*/ int full_eit_ok; /** The Complete EIT PID for each section*/ mumudvb_ts_packet_t* full_eit_sections[256]; /** The continuity counter of the sent EIT*/ int continuity_counter; /** Pointer to the next one */ struct eit_packet_t *next; }eit_packet_t; /** @brief the parameters for the rewriting * This structure contain the parameters needed for rewriting */ typedef struct rewrite_parameters_t{ /**Do we rewrite the PMT pid ?*/ option_status_t rewrite_pmt; /**Do we rewrite the PAT pid ?*/ option_status_t rewrite_pat; /**The actual version of the PAT pid*/ int pat_version; /**Do the actual full PAT needs to be updated ?*/ int pat_needs_update; /**Do the full PAT is ok ?*/ int full_pat_ok; /** The Complete PAT PID */ mumudvb_ts_packet_t *full_pat; /** The continuity counter of the sent PAT*/ int pat_continuity_counter; /**Do we rewrite the SDT pid ?*/ option_status_t rewrite_sdt; /**The actual version of the SDT pid*/ int sdt_version; /**Do the actual full SDT needs to be updated ?*/ int sdt_needs_update; /** Do we need to see other SDT ?*/ int sdt_need_others; /** The last_section_number of the current version */ int sdt_last_section_number; /** Array storing the section numbers we saw */ int sdt_section_numbers_seen[256]; /**Do the full SDT is ok ?*/ int full_sdt_ok; /** The Complete SDT PID */ mumudvb_ts_packet_t *full_sdt; /** The continuity counter of the sent SDT*/ int sdt_continuity_counter; /** Do we force the EIT presence ? */ int sdt_force_eit; /** Do we sort the EIT PID ?*/ option_status_t rewrite_eit; /** Do we just store EIT without sorting/rewriting */ option_status_t store_eit; /**The actual version of the EIT pid*/ int eit_version; /**Do the actual full EIT needs to be updated ?*/ int eit_needs_update; /** The Complete EIT PID which we are storing*/ mumudvb_ts_packet_t *full_eit; eit_packet_t *eit_packets; }rewrite_parameters_t; void init_rewr_v(rewrite_parameters_t *rewr_p); int rewrite_init(rewrite_parameters_t *rewr_p); int read_rewrite_configuration(rewrite_parameters_t *rewrite_vars, char *substring); int pmt_rewrite_new_channel_packet(unsigned char *ts_packet, unsigned char *pmt_ts_packet, mumudvb_channel_t *channel, int curr_channel); void pat_rewrite_new_global_packet(unsigned char *ts_packet, rewrite_parameters_t *rewrite_vars); int pat_rewrite_new_channel_packet(unsigned char *ts_packet, rewrite_parameters_t *rewrite_vars, mumudvb_channel_t *channel, int curr_channel); int sdt_rewrite_new_global_packet(unsigned char *ts_packet, rewrite_parameters_t *rewrite_vars); int sdt_rewrite_new_channel_packet(unsigned char *ts_packet, rewrite_parameters_t *rewrite_vars, mumudvb_channel_t *channel, int curr_channel); void set_continuity_counter(unsigned char *buf,int continuity_counter); void eit_rewrite_new_global_packet(unsigned char *ts_packet, rewrite_parameters_t *rewrite_vars); void eit_rewrite_new_channel_packet(unsigned char *ts_packet, rewrite_parameters_t *rewrite_vars, mumudvb_channel_t *channel, unicast_parameters_t *unicast_vars, void *scam_vars_v); #endif MuMuDVB-2.1.0/src/rewrite_eit.c000066400000000000000000000355731305714132500162240ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * * (C) 2004-2013 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /**@file * @brief This file contains the function for rewriting the EIT pid * * The EIT rewrite is made to announce only the video stream associated with the channel in the EIT pid * It avoids to have ghost channels which can disturb the clients */ #include #include #include #include "mumudvb.h" #include "ts.h" #include "rewrite.h" #include "log.h" #include static char *log_module="EIT rewrite: "; /** @brief Display the contents of the EIT table * */ void eit_display_header(eit_t *eit) { log_message( log_module, MSG_DEBUG,"--- EIT TABLE ---"); log_message( log_module, MSG_DEBUG,"table_id\t\t\t 0x%x",eit->table_id); log_message( log_module, MSG_DEBUG,"section_length\t\t %d",HILO(eit->section_length)); log_message( log_module, MSG_DEBUG,"section_syntax_indicator\t 0x%x",eit->section_syntax_indicator); log_message( log_module, MSG_DEBUG,"service_id\t\t\t 0x%x",HILO(eit->service_id)); log_message( log_module, MSG_DEBUG,"current_next_indicator\t 0x%x",eit->current_next_indicator); log_message( log_module, MSG_DEBUG,"version_number\t\t 0x%x",eit->version_number); log_message( log_module, MSG_DEBUG,"section_number\t\t 0x%x",eit->section_number); log_message( log_module, MSG_DEBUG,"last_section_number\t 0x%x",eit->last_section_number); log_message( log_module, MSG_DEBUG,"transport_stream_id\t 0x%x",HILO(eit->transport_stream_id)); log_message( log_module, MSG_DEBUG,"original_network_id\t 0x%x",HILO(eit->original_network_id)); log_message( log_module, MSG_DEBUG,"segment_last_section_number\t 0x%x",eit->segment_last_section_number); log_message( log_module, MSG_DEBUG,"segment_last_table_id\t\t 0x%x",eit->segment_last_table_id); } void eit_show_stored(rewrite_parameters_t *rewrite_vars) { eit_packet_t *actual_eit=rewrite_vars->eit_packets; int i; while(actual_eit!=NULL) { log_message( log_module, MSG_FLOOD,"stored EIT SID %d table_id 0X%02x version %d last section number %d", actual_eit->service_id, actual_eit->table_id, actual_eit->version, actual_eit->last_section_number); for(i=0;i<=actual_eit->last_section_number;i++) if(actual_eit->sections_stored[i]) log_message( log_module, MSG_FLOOD,"\t stored section %d",i); actual_eit=actual_eit->next; } } /**@brief increment the table_id * */ uint8_t eit_next_table_id(uint8_t table_id) { if(table_id==0) return 0x4E; if(table_id==0x4E) return 0x50; if(table_id==0x5F) return 0x4E; return table_id+1; } void eit_free_packet_contents(eit_packet_t *eit_packet) { //free the different packets for(int i=0;i<256;i++) if(eit_packet->full_eit_sections[i]!=NULL) free(eit_packet->full_eit_sections[i]); //we don't break the chained list eit_packet_t *next; next=eit_packet->next; memset (eit_packet, 0, sizeof( eit_packet_t));//we clear it eit_packet->next=next; } /** @brief Try to find the eit specified by id, if not found create a new one. * if the service is not found, it returns a pointer to the new service, and NULL if * the service is found or run out of memory. * */ eit_packet_t *eit_new_packet(rewrite_parameters_t *rewrite_vars, int sid, uint8_t table_id) { eit_packet_t *actual_eit=rewrite_vars->eit_packets; //go to the last one or return the already found while(actual_eit && actual_eit->next!=NULL) { if((actual_eit->service_id==sid)&&(actual_eit->table_id==table_id)) return actual_eit; actual_eit=actual_eit->next; } log_message( log_module, MSG_FLOOD,"EIT Stored before allocation sid %d table id 0x%02x",sid,table_id); eit_show_stored(rewrite_vars); if(actual_eit==NULL) { rewrite_vars->eit_packets=calloc(1,sizeof(eit_packet_t)); actual_eit=rewrite_vars->eit_packets; } else { actual_eit->next=calloc(1,sizeof(eit_packet_t)); actual_eit=actual_eit->next; } if(actual_eit==NULL) { log_message( log_module, MSG_ERROR,"Problem with calloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); return NULL; } return actual_eit; } /** @brief, Search an EIT in the stored list * */ eit_packet_t *eit_find_by_tsid(rewrite_parameters_t *rewrite_vars,int service_id, uint8_t table_id) //and table id { eit_packet_t *found=NULL; eit_packet_t *actual_eit=rewrite_vars->eit_packets; while(found==NULL && actual_eit!=NULL) { if((actual_eit->service_id==service_id)&&(actual_eit->table_id==table_id)) found=actual_eit; else actual_eit=actual_eit->next; } return found; } /** @brief, tell if the eit have a newer version than the one recorded actually * In the EIT pid there is a field to say if the EIT was updated * This function check if it has changed (in order to rewrite the eit only once) * Note this function can give false positive since it doesn't check the CRC32 * *@param rewrite_vars the parameters for eit rewriting *@param buf : the received buffer */ int eit_need_update(rewrite_parameters_t *rewrite_vars, unsigned char *buf, int raw) { //Get the SID of the new EIT //loop over the stored EIT //if found and version > : need update //if not found need update eit_t *eit; //if it's a raw TS packet we search for the beginning if(raw) eit=(eit_t*)(get_ts_begin(buf)); else eit=(eit_t*)(buf); eit_packet_t *eit_packet; if(eit) //It's the beginning of a new packet { // 0x4E event_information_section - actual_transport_stream, present/following // 0x50 to 0x5F event_information_section - actual_transport_stream, schedule //all these table id_ which could have different version number for the same service if((eit->table_id!=0x4E)&&((eit->table_id&0xF0)!=0x50)) return 0; /*current_next_indicator – A 1-bit indicator, which when set to '1' indicates that the table sent is currently applicable.*/ if(eit->current_next_indicator == 0) return 0; eit_packet=eit_find_by_tsid(rewrite_vars,HILO(eit->service_id),eit->table_id); if(eit_packet==NULL) { log_message( log_module, MSG_DETAIL,"EIT sid %d table id 0x%02x not stored, need update.", HILO(eit->service_id),eit->table_id); return 1; } if(eit->version_number!=eit_packet->version) { log_message( log_module, MSG_DETAIL,"EIT sid %d need update. stored version : %d, new: %d", HILO(eit->service_id), eit_packet->version, eit->version_number); return 1; } if(!eit_packet->sections_stored[eit->section_number] ) { log_message( log_module, MSG_DETAIL,"EIT sid %d new section %d version : %d", HILO(eit->service_id), eit->section_number, eit->version_number); return 1; } } return 0; } /** @brief This function is called when a new EIT packet for all channels is there and we asked for rewrite * this function save the full EIT for each service. * @return return 1 when the packet is updated */ void eit_rewrite_new_global_packet(unsigned char *ts_packet, rewrite_parameters_t *rewrite_vars) { eit_t *eit=NULL; /*Check the version before getting the full packet*/ if(!rewrite_vars->eit_needs_update) rewrite_vars->eit_needs_update=eit_need_update(rewrite_vars,ts_packet,1); /*We need to update the full packet, we download it*/ if(rewrite_vars->eit_needs_update ) { //We pop all packets available while(get_ts_packet(ts_packet,rewrite_vars->full_eit)) { ts_packet=NULL; //next call we just pop packets if available //We check if we have to store this new EIT packet (CRC32 can make false alarms) if(!eit_need_update(rewrite_vars,rewrite_vars->full_eit->data_full,0)) { break; } log_message( log_module, MSG_DETAIL,"New full EIT for update"); //For debugging purposes eit=(eit_t*)(rewrite_vars->full_eit->data_full); eit_display_header(eit); eit_packet_t *eit_packet; eit_packet=eit_new_packet(rewrite_vars,HILO(eit->service_id), eit->table_id); if(NULL==eit_packet) break; if(eit->version_number!=eit_packet->version) { log_message( log_module, MSG_DETAIL,"New version for EIT sid %d need update. stored version : %d, new: %d", HILO(eit->service_id), eit_packet->version, eit->version_number); //New version so we clear all contents eit_free_packet_contents(eit_packet); } eit_packet->last_section_number = eit->last_section_number; eit_packet->version=eit->version_number; eit_packet->service_id = HILO(eit->service_id); eit_packet->table_id = eit->table_id; eit_packet->full_eit_ok=1; /*We've got the FULL EIT packet*/ //we copy the data to the right section if(eit_packet->full_eit_sections[eit->section_number]==NULL) eit_packet->full_eit_sections[eit->section_number]=calloc(1,sizeof(mumudvb_ts_packet_t)); if(eit_packet->full_eit_sections[eit->section_number]==NULL) { log_message( log_module, MSG_ERROR,"Problem with calloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); break; } memcpy(eit_packet->full_eit_sections[eit->section_number], rewrite_vars->full_eit,sizeof( mumudvb_ts_packet_t)); //We store that we saw this section number eit_packet->sections_stored[eit->section_number]=1; log_message( log_module, MSG_DETAIL,"Full EIT updated. sid %d section number %d, last_section_number %d\n", eit_packet->service_id, eit->section_number, eit_packet->last_section_number); rewrite_vars->eit_needs_update = 0; eit_show_stored(rewrite_vars); } } } /** @brief This function is called when a new EIT packet for a channel is there and we asked for rewrite * This function copy the rewritten EIT to the buffer. And checks if the EIT was changed so the rewritten version have to be updated */ void eit_rewrite_new_channel_packet(unsigned char *ts_packet, rewrite_parameters_t *rewrite_vars, mumudvb_channel_t *channel, unicast_parameters_t *unicast_vars, void *scam_vars_v) { int i=0; //If payload unit start indicator , we will send all the present EIT for this service, otherwise nothing //We generate the TS packets on by one, and for each one, we check if we have to send //Otherwise we skip the packet //if channel not ready we return if(channel->channel_readypayload_unit_start_indicator)) return; //If there is an EIT PID sorted for this channel eit_packet_t *eit_pkt; uint8_t section_start; //we check we start with a valid section if((channel->eit_table_id_to_send!=0x4E)&&((channel->eit_table_id_to_send&0xF0)!=0x50)) channel->eit_table_id_to_send=0x4E; //We search for the EIT packet to send, if not found we loop on the sections section_start=channel->eit_table_id_to_send; do { eit_pkt=eit_find_by_tsid(rewrite_vars,channel->service_id,channel->eit_table_id_to_send); //loop over the table id if((eit_pkt==NULL)||(!eit_pkt->full_eit_ok)) { channel->eit_table_id_to_send=eit_next_table_id(channel->eit_table_id_to_send); eit_pkt=NULL; } } while((eit_pkt==NULL)&&(channel->eit_table_id_to_send!=section_start)); //we go away if there is no EIT packet to send if(eit_pkt==NULL) return; //search for the next section we can send //just in case we have a new version with less sections channel->eit_section_to_send=channel->eit_section_to_send % (eit_pkt->last_section_number+1); //the real search while((i<=eit_pkt->last_section_number)&&(!eit_pkt->sections_stored[channel->eit_section_to_send])) { channel->eit_section_to_send++; channel->eit_section_to_send=channel->eit_section_to_send % (eit_pkt->last_section_number+1); i++; } //if nothing found if(!eit_pkt->sections_stored[channel->eit_section_to_send]) { //bye (we should be here BTW) but we avoid to stay on invalid packet by going to next section channel->eit_table_id_to_send=eit_next_table_id(channel->eit_table_id_to_send); return; } //ok we send this! mumudvb_ts_packet_t *pkt_to_send; int data_left_to_send,sent; unsigned char send_buf[TS_PACKET_SIZE]; ts_header=(ts_header_t *)send_buf; pkt_to_send=eit_pkt->full_eit_sections[channel->eit_section_to_send]; data_left_to_send=pkt_to_send->len_full; sent=0; //log_message(log_module,MSG_FLOOD,"Sending EIT to channel %s (sid %d) section %d table_id 0x%02x data_len %d", // channel->name, // channel->service_id, // channel->eit_section_to_send, // channel->eit_table_id_to_send, // data_left_to_send); while(data_left_to_send>0) { int header_len; memset(send_buf,0,TS_PACKET_SIZE*sizeof(unsigned char)); //we fill the TS header ts_header->sync_byte=0x47; if(sent==0) { ts_header->payload_unit_start_indicator=1; header_len=TS_HEADER_LEN; //includes the pointer field } else header_len=TS_HEADER_LEN-1; //the packet has started, we don't count the pointer field ts_header->pid_lo=18; //specify the PID ts_header->adaptation_field_control=1; //always one ts_header->continuity_counter=channel->eit_cc; //continuity counter channel->eit_cc++; channel->eit_cc= channel->eit_cc % 16; //We send the data //plus one because of pointer field if(data_left_to_send>=(TS_PACKET_SIZE-header_len)) { memcpy(send_buf+header_len,pkt_to_send->data_full+sent,(TS_PACKET_SIZE-header_len)*sizeof(unsigned char)); sent+=(TS_PACKET_SIZE-header_len); data_left_to_send-=(TS_PACKET_SIZE-header_len); } else { memcpy(send_buf+header_len,pkt_to_send->data_full+sent,data_left_to_send*sizeof(unsigned char)); sent+=data_left_to_send; //Padding with OxFF memset(send_buf+header_len+data_left_to_send, 0xFF, (TS_PACKET_SIZE-(header_len+data_left_to_send))*sizeof(unsigned char)); data_left_to_send=0; } //NOW we fill the channel buffer for sending buffer_func(channel, send_buf, unicast_vars, scam_vars_v); } //We update which section we want to send channel->eit_section_to_send++; channel->eit_section_to_send=channel->eit_section_to_send % (eit_pkt->last_section_number+1); //if we reached the end, we go to the next table_id if(channel->eit_section_to_send==0) channel->eit_table_id_to_send=eit_next_table_id(channel->eit_table_id_to_send); } MuMuDVB-2.1.0/src/rewrite_pat.c000066400000000000000000000270531305714132500162210ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * * (C) 2004-2013 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /**@file * @brief This file contains the function for rewriting the pat pid * * The pat rewrite is made to announce only the video stream associated with the channel in the PAT pid * Some set top boxes need it. */ #include #include #include "mumudvb.h" #include "ts.h" #include "rewrite.h" #include "log.h" #include extern uint32_t crc32_table[256]; static char *log_module="PAT Rewrite: "; /** @brief, tell if the pat have a newer version than the one recorded actually * In the PAT pid there is a field to say if the PAT was updated * This function check if it has changed (in order to rewrite the pat only once) * General Note : in case it change during streaming it can be a problem ane we would have to deal with re-autoconfiguration * Note this function can give flase positive since it doesn't check the CRC32 * *@param rewrite_vars the parameters for pat rewriting *@param buf : the received buffer */ int pat_need_update(rewrite_parameters_t *rewrite_vars, unsigned char *buf) { pat_t *pat=(pat_t*)(get_ts_begin(buf)); if(pat) //It's the beginning of a new packet { /*current_next_indicator – A 1-bit indicator, which when set to '1' indicates that the Program Association Table sent is currently applicable. When the bit is set to '0', it indicates that the table sent is not yet applicable and shall be the next table to become valid.*/ if(pat->current_next_indicator == 0) { return 0; } if(pat->version_number!=rewrite_vars->pat_version) { log_message( log_module, MSG_DEBUG,"Need update. stored version : %d, new: %d\n",rewrite_vars->pat_version,pat->version_number); return 1; } } return 0; } /** @brief update the version using the dowloaded pat*/ void update_pat_version(rewrite_parameters_t *rewrite_vars) { pat_t *pat=(pat_t*)(rewrite_vars->full_pat->data_full); if(rewrite_vars->pat_version!=pat->version_number) { log_message( log_module, MSG_DEBUG,"New pat version. Old : %d, new: %d\n",rewrite_vars->pat_version,pat->version_number); if(rewrite_vars->pat_version!=-1) log_message( log_module, MSG_WARN,"The PAT version changed, so the channels changed probably. If you are using autoconfiguration it's safer to relaunch MuMuDVB or if the PIDs are set manually, check the PMTs. It can also happend when services are added/removed\n"); } rewrite_vars->pat_version=pat->version_number; } /** @brief Main function for pat rewriting * The goal of this function is to make a new pat with only the announement for the streamed channel * by default it contains all the channels of the transponder. For each channel descriptor this function will search * the pmt pid of the channel in the given pid list. if found it keeps it otherwise it drops. * At the end, a new CRC32 is computed. The buffer is overwritten, so the caller have to save it before. * * @param rewrite_vars the parameters for pat rewriting * @param channels The array of channels * @param curr_channel the channel for wich we want to generate a PAT * @param buf : the received buffer, to get the TS header */ int pat_channel_rewrite(rewrite_parameters_t *rewrite_vars, mumudvb_channel_t *channel, unsigned char *buf, int curr_channel) { ts_header_t *ts_header=(ts_header_t *)buf; pat_t *pat=(pat_t*)(rewrite_vars->full_pat->data_full); pat_prog_t *prog; unsigned long crc32; //destination buffer unsigned char buf_dest[TS_PACKET_SIZE]; int buf_dest_pos=0; int delta=PAT_LEN; int section_length=0; int i; int new_section_length; if(ts_header->payload_unit_start_indicator) { log_message( log_module, MSG_DEBUG,"PAT rewrite : pointer field 0x%x \n", buf[TS_HEADER_LEN-1]); } section_length=HILO(pat->section_length); //lets start the copy //we copy the ts header and adapt it a bit //the continuity counter is updated elswhere ts_header->payload_unit_start_indicator=1; buf[TS_HEADER_LEN-1]=0;//we erase the pointer field memcpy(buf_dest,ts_header,TS_HEADER_LEN); //we copy the modified PAT header pat->current_next_indicator=1; //applicable immediately pat->section_number=0; //only one pat pat->last_section_number=0; memcpy(buf_dest+TS_HEADER_LEN,pat,PAT_LEN); buf_dest_pos=TS_HEADER_LEN+PAT_LEN; //We copy what we need : EIT announce and present PMT announce //strict comparaison due to the calc of section len cf down while((delta+PAT_PROG_LEN)<(section_length)) { prog=(pat_prog_t*)((char*)rewrite_vars->full_pat->data_full+delta); if(HILO(prog->program_number)!=0) { /*We check the transport stream id if present and the size of the packet*/ /* + 4 for the CRC32*/ if((buf_dest_pos+PAT_PROG_LEN+4service_id || (channel->service_id == HILO(prog->program_number)) )) { for(i=0;ipid_i.num_pids;i++) if(channel->pid_i.pids[i]==HILO(prog->network_pid)) { if(buf_dest_pos+PAT_PROG_LEN+4+1>TS_PACKET_SIZE) //The +4 is for CRC32 +1 is because indexing starts at 0 { log_message( log_module, MSG_WARN,"The generated PAT is too big for channel %d : \"%s\", we skip the other pids/programs\n", curr_channel, channel->name); i=channel->pid_i.num_pids; } else { log_message( log_module, MSG_DETAIL,"NEW program for channel %d : \"%s\". PMT pid : %d\n", curr_channel, channel->name,channel->pid_i.pids[i]); /*we found a announce for a PMT PID in our stream, we keep it*/ memcpy(buf_dest+buf_dest_pos,rewrite_vars->full_pat->data_full+delta,PAT_PROG_LEN); buf_dest_pos+=PAT_PROG_LEN; } } } else log_message( log_module, MSG_DEBUG,"Program dropped because of service_id. channel %d :\"%s\". service_id chan : %d service_id prog %d\n", curr_channel, channel->name, channel->service_id, HILO(prog->program_number)); } delta+=PAT_PROG_LEN; } //we compute the new section length //section length is the size of the section after section_length (crc32 included : 4 bytes) //so it's size of the crc32 + size of the pat prog + size of the pat header - 3 first bytes (the pat header until section length included) //Finally it's total_pat_data_size + 1 new_section_length=buf_dest_pos-TS_HEADER_LEN + 1; //We write the new section length buf_dest[1+TS_HEADER_LEN]=(((new_section_length)&0x0f00)>>8) | (0xf0 & buf_dest[1+TS_HEADER_LEN]); buf_dest[2+TS_HEADER_LEN]=new_section_length & 0xff; //CRC32 calculation inspired by the xine project //Now we must adjust the CRC32 //we compute the CRC32 crc32=0xffffffff; for(i = 0; i < new_section_length-1; i++) { crc32 = (crc32 << 8) ^ crc32_table[((crc32 >> 24) ^ buf_dest[i+TS_HEADER_LEN])&0xff]; } //We write the CRC32 to the buffer buf_dest[buf_dest_pos]=(crc32>>24) & 0xff; buf_dest_pos+=1; buf_dest[buf_dest_pos]=(crc32>>16) & 0xff; buf_dest_pos+=1; buf_dest[buf_dest_pos]=(crc32>>8) & 0xff; buf_dest_pos+=1; buf_dest[buf_dest_pos]=crc32 & 0xff; buf_dest_pos+=1; //Padding with 0xFF memset(buf_dest+buf_dest_pos,0xFF,TS_PACKET_SIZE-buf_dest_pos); //We copy the result to the intended buffer memcpy(channel->generated_pat,buf_dest,TS_PACKET_SIZE); //Everything is Ok .... return 1; } /** @brief This function is called when a new PAT packet for all channels is there and we asked for rewrite * this function save the full PAT which will be the source PAT for all the channels */ void pat_rewrite_new_global_packet(unsigned char *ts_packet, rewrite_parameters_t *rewrite_vars) { /*Check the version before getting the full packet*/ if(!rewrite_vars->pat_needs_update) { rewrite_vars->pat_needs_update=pat_need_update(rewrite_vars,ts_packet); } /*We need to update the full packet, we download it*/ if(rewrite_vars->pat_needs_update) { while(get_ts_packet(ts_packet,rewrite_vars->full_pat)) { ts_packet=NULL; // next call we only POP packets from the stack pat_t *pat=(pat_t*)(rewrite_vars->full_pat->data_full); /*current_next_indicator – A 1-bit indicator, which when set to '1' indicates that the Program Association Table sent is currently applicable. When the bit is set to '0', it indicates that the table sent is not yet applicable and shall be the next table to become valid.*/ if(pat->current_next_indicator == 0) { log_message( log_module, MSG_FLOOD,"PAT not yet valid, we get a new one (current_next_indicator == 0)\n"); } else { log_message( log_module, MSG_DEBUG,"Full PAT updated\n"); /*We've got the FULL PAT packet*/ update_pat_version(rewrite_vars); rewrite_vars->pat_needs_update=0; rewrite_vars->full_pat_ok=1; ts_display_pat(log_module,rewrite_vars->full_pat->data_full); } } } //To avoid the duplicates, we have to update the continuity counter rewrite_vars->pat_continuity_counter++; rewrite_vars->pat_continuity_counter= rewrite_vars->pat_continuity_counter % 32; } /** @brief This function is called when a new PAT packet for a channel is there and we asked for rewrite * This function copy the rewritten PAT to the buffer. And checks if the PAT was changed so the rewritten version have to be updated */ int pat_rewrite_new_channel_packet(unsigned char *ts_packet, rewrite_parameters_t *rewrite_vars, mumudvb_channel_t *channel, int curr_channel) { if(rewrite_vars->full_pat_ok ) //the global full pat is ok { /*We check if it's the first pat packet ? or we send it each time ?*/ /*We check if the versions corresponds*/ if(!rewrite_vars->pat_needs_update && channel->channel_ready>=READY && channel->generated_pat_version!=rewrite_vars->pat_version)//We check the version only if the PAT is not currently updated { log_message( log_module, MSG_DEBUG,"We need to rewrite the PAT for the channel %d : \"%s\"\n", curr_channel, channel->name); /*They mismatch*/ /*We generate the rewritten packet*/ if(pat_channel_rewrite(rewrite_vars, channel, ts_packet, curr_channel)) { /*We update the version*/ channel->generated_pat_version=rewrite_vars->pat_version; } else { log_message( log_module, MSG_DEBUG,"ERROR with the PAT for the channel %d : \"%s\"\n", curr_channel, channel->name); return 0; } } if(channel->generated_pat_version==rewrite_vars->pat_version) { /*We send the new PAT from channel->generated_pat*/ memcpy(ts_packet,channel->generated_pat,TS_PACKET_SIZE); //To avoid the duplicates, we have to update the continuity counter set_continuity_counter(ts_packet,rewrite_vars->pat_continuity_counter); } else { log_message( log_module, MSG_DEBUG,"Bad pat channel version, we don't send the pat for the channel %d : \"%s\"\n", curr_channel, channel->name); return 0; } } else { log_message( log_module, MSG_DEBUG,"We need a global pat update, we don't send the pat for the channel %d : \"%s\"\n", curr_channel, channel->name); return 0; } return 1; } MuMuDVB-2.1.0/src/rewrite_pmt.c000066400000000000000000000213501305714132500162270ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * PMT rewrite by Danijel Tudek, Dec 2016. * * (C) 2008-2013 Brice DUBOST * * Parts of this code come from libdvb, modified for mumudvb * by Brice DUBOST * Libdvb part : Copyright (C) 2000 Klaus Schmidinger * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** @file * @brief This file contains code for PMT rewrite * PMT must be rewritten if we don't stream all PIDs, otherwise some players * may get confused. * (See "Problem with streaming individual PIDs", Nov 2016 on mailing list.) * */ #include #include #include #include "mumudvb.h" #include "ts.h" #include "rewrite.h" #include "log.h" #include extern uint32_t crc32_table[256]; static char *log_module = "PMT rewrite: "; /** * @brief Check the streamed PMT version and compare to the stored PMT. * @param ts_packet * @param channel * @return return 1 if update is needed, 2 if multi-part PMT is being assembled */ int pmt_need_update(unsigned char *ts_packet, mumudvb_channel_t *channel) { pmt_t *pmt = (pmt_t *) (ts_packet + TS_HEADER_LEN); if (pmt->table_id == 0x02) { if (channel->original_pmt_ready) { if (pmt->version_number != channel->generated_pmt_version) { log_message(log_module, MSG_DEBUG, "PMT changed, old version: %d, new version: %d, rewriting...", channel->generated_pmt_version, pmt->version_number); channel->original_pmt_ready = 0; } else { return 0; } } if (!channel->original_pmt_ready) { float pmt_length = HILO(pmt->section_length) + 3; channel->pmt_part_num = (int) ceil(pmt_length/TS_PACKET_SIZE) - 1; channel->pmt_part_count = 0; memcpy(channel->original_pmt + (TS_PACKET_SIZE*channel->pmt_part_count), ts_packet, TS_PACKET_SIZE); if (channel->pmt_part_num == 0) { channel->original_pmt_ready = 1; return 1; } else { return 2; } } } else { if (!channel->original_pmt_ready && channel->pmt_part_num > 0) { channel->pmt_part_count++; log_message(log_module, MSG_DETAIL, "Got part %i of PMT", channel->pmt_part_count + 1); memcpy(channel->original_pmt + (TS_PACKET_SIZE*channel->pmt_part_count), ts_packet + 4, TS_PACKET_SIZE); if (channel->pmt_part_count == channel->pmt_part_num) { channel->original_pmt_ready = 1; return 1; } else { return 2; } } else if (!channel->original_pmt_ready && channel->pmt_part_num == 0) { log_message(log_module, MSG_DETAIL, "We didn't get the good PMT yet (wrong table ID 0x%02X), search for a new one", pmt->table_id); } return 0; } return 0; } /** @brief Main function for PMT rewrite. * The goal of this function is to make a new PMT with only the announcement for the streamed PIDs for each channel. * By default it contains all PIDs which confuses players if we don't actually stream all of them. * The PMT is read and the list of PIDs is compared to user-specified PID list for the channel. * If there is a match, PID is copied to generated PMT. * @param channel * @return 0 */ int pmt_channel_rewrite(mumudvb_channel_t *channel) { unsigned char *ts_packet = channel->original_pmt; ts_header_t *ts_header = (ts_header_t *) ts_packet; pmt_t *pmt = (pmt_t *) (ts_packet + TS_HEADER_LEN); if (pmt->table_id != 0x02) { log_message(log_module, MSG_DETAIL, "We didn't get the good PMT (wrong table ID 0x%02X), search for a new one", pmt->table_id); return 0; } pmt_info_t *pmt_info; unsigned long crc32; //destination buffer unsigned char buf_dest[TS_PACKET_SIZE]; int buf_dest_pos = 0; int section_length = 0, elem_pid = 0; int new_section_length = 0; int es_info_len = 0; int new_es_info_len = 0; int i = 0, j = 0; log_message(log_module, MSG_DEBUG, "PMT pid = %d; channel name = \"%s\"\n", channel->pmt_packet->pid, channel->name); section_length = HILO(pmt->section_length) + 3; //lets start the copy //we copy the ts header and adapt it a bit //the continuity counter is updated elsewhere if (ts_header->payload_unit_start_indicator) { if (ts_packet[TS_HEADER_LEN - 1]) log_message(log_module, MSG_DEBUG, "pointer field 0x%x \n", ts_packet[TS_HEADER_LEN - 1]); } ts_header->payload_unit_start_indicator = 1; ts_packet[TS_HEADER_LEN - 1] = 0; //we erase the pointer field //we copy the modified SDT header pmt->current_next_indicator = 1; //applicable immediately pmt->section_number = 0; pmt->last_section_number = 0; memcpy(buf_dest, ts_header, TS_HEADER_LEN + PMT_LEN); buf_dest_pos = TS_HEADER_LEN + PMT_LEN; /** * Parse PMT */ int es_len = section_length - PMT_LEN - 4; log_message(log_module, MSG_DEBUG, "Number of PIDs requested from PMT: %d\n", channel->pid_i.num_pids-1); // one of them is PMT PID itself for (i = 0; i < es_len; i += PMT_INFO_LEN + es_info_len) { pmt_info = (pmt_info_t *) ((char *) pmt + PMT_LEN + i); elem_pid = HILO(pmt_info->elementary_PID); es_info_len = HILO(pmt_info->ES_info_length); //Prevent write overflow if(buf_dest_pos + PMT_INFO_LEN + es_info_len >= TS_PACKET_SIZE - 4) { log_message(log_module, MSG_DEBUG, " Write overflow detected, aborting copy"); break; } for (j = 0; j < channel->pid_i.num_pids; j++) { if (elem_pid == channel->pid_i.pids[j]) { new_es_info_len += PMT_INFO_LEN + es_info_len; log_message(log_module, MSG_DEBUG, " PID %d found, copy to new PMT\n", channel->pid_i.pids[j]); memcpy(buf_dest + buf_dest_pos, pmt_info, PMT_INFO_LEN + es_info_len); buf_dest_pos += PMT_INFO_LEN + es_info_len; } } } new_section_length = buf_dest_pos - TS_HEADER_LEN + 1; //We write the new section length buf_dest[1 + TS_HEADER_LEN] = (((new_section_length) & 0x0f00) >> 8) | (0xf0 & buf_dest[1 + TS_HEADER_LEN]); buf_dest[2 + TS_HEADER_LEN] = new_section_length & 0xff; //CRC32 calculation inspired by the xine project //Now we must adjust the CRC32 //we compute the CRC32 crc32 = 0xffffffff; for (i = 0; i < new_section_length - 1; i++) { crc32 = (crc32 << 8) ^ crc32_table[((crc32 >> 24) ^ buf_dest[i + TS_HEADER_LEN]) & 0xff]; } //We write the CRC32 to the buffer buf_dest[buf_dest_pos] = (crc32 >> 24) & 0xff; buf_dest_pos += 1; buf_dest[buf_dest_pos] = (crc32 >> 16) & 0xff; buf_dest_pos += 1; buf_dest[buf_dest_pos] = (crc32 >> 8) & 0xff; buf_dest_pos += 1; buf_dest[buf_dest_pos] = crc32 & 0xff; buf_dest_pos += 1; //Padding with 0xFF memset(buf_dest + buf_dest_pos, 0xFF, TS_PACKET_SIZE - buf_dest_pos); //update generated PMT version (matches the original PMT version) log_message(log_module, MSG_DEBUG, "PMT rewritten\n"); channel->generated_pmt_version = pmt->version_number; memcpy(channel->generated_pmt, buf_dest, TS_PACKET_SIZE); //Everything is OK return 1; } int pmt_send_packet(unsigned char *pmt_ts_packet, mumudvb_channel_t *channel) { //Everything is good, send the generated packet channel->pmt_continuity_counter++; channel->pmt_continuity_counter = channel->pmt_continuity_counter % 32; memcpy(pmt_ts_packet, channel->generated_pmt, TS_PACKET_SIZE); set_continuity_counter(pmt_ts_packet, channel->pmt_continuity_counter); return 1; } int pmt_rewrite_new_channel_packet(unsigned char *ts_packet, unsigned char *pmt_ts_packet, mumudvb_channel_t *channel, int curr_channel) { if (channel->channel_ready >= READY) { int need_update = pmt_need_update(ts_packet, channel); if (need_update == 0) { return pmt_send_packet(pmt_ts_packet, channel); } else if (need_update == 1) { //Needs update, call rewrite function if (!pmt_channel_rewrite(channel)) { log_message(log_module, MSG_DEBUG, "Cannot rewrite (for the moment) the PMT for the channel %d : \"%s\"\n", curr_channel, channel->name); //In case of an error, send the previously generated PMT, if any, or skip sending if (channel->generated_pmt_version) { return pmt_send_packet(pmt_ts_packet, channel); } else { return 0; } } else { return 1; } } else if (need_update == 2) { //Multi-part PMT, we have to assemble it before processing log_message(log_module, MSG_DEBUG, "Assembling multi-part PMT for the channel %d : \"%s\"...\n", curr_channel, channel->name); return 0; } } return 0; } MuMuDVB-2.1.0/src/rewrite_sdt.c000066400000000000000000000402021305714132500162160ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * * (C) 2004-2013 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /**@file * @brief This file contains the function for rewriting the SDT PID * * The SDT rewrite is made to announce only the video stream associated with the channel in the SDT PID * It avoids to have ghost channels which can disturb the clients */ #include #include #include "mumudvb.h" #include "ts.h" #include "rewrite.h" #include "log.h" #include extern uint32_t crc32_table[256]; static char *log_module="SDT rewrite: "; /** @brief @TODO : document * */ int sdt_rewrite_all_sections_seen(rewrite_parameters_t *rewrite_vars) { int all_seen,i; all_seen=1; for(i=0;i<=rewrite_vars->sdt_last_section_number;i++) if(rewrite_vars->sdt_section_numbers_seen[i]==0) all_seen=0; return all_seen; } /** @brief, tell if the sdt have a newer version than the one recorded actually * In the SDT pid there is a field to say if the SDT was updated * This function check if it has changed (in order to rewrite the sdt only once) * General Note : in case it change during streaming it can be a problem ane we would have to deal with re-autoconfiguration * Note this function can give flase positive since it doesn't check the CRC32 * *@param rewrite_vars the parameters for sdt rewriting *@param buf : the received buffer */ int sdt_need_update(rewrite_parameters_t *rewrite_vars, unsigned char *buf) { sdt_t *sdt=(sdt_t*)(get_ts_begin(buf)); if(sdt) //It's the beginning of a new packet if((sdt->version_number!=rewrite_vars->sdt_version) && (sdt->table_id==0x42)) { /*current_next_indicator – A 1-bit indicator, which when set to '1' indicates that the Program Association Table sent is currently applicable. When the bit is set to '0', it indicates that the table sent is not yet applicable and shall be the next table to become valid.*/ if(sdt->current_next_indicator == 0) { return 0; } log_message( log_module, MSG_DEBUG,"Need update. stored version : %d, new: %d\n",rewrite_vars->sdt_version,sdt->version_number); if(rewrite_vars->sdt_version!=-1) log_message( log_module, MSG_INFO,"The SDT version changed, so the channels names changed probably.\n"); return 1; } return 0; } /** @brief update the version using the dowloaded SDT*/ void update_sdt_version(rewrite_parameters_t *rewrite_vars) { sdt_t *sdt=(sdt_t*)(rewrite_vars->full_sdt->data_full); if(rewrite_vars->sdt_version!=sdt->version_number) log_message( log_module, MSG_DEBUG,"New sdt version. Old : %d, new: %d\n",rewrite_vars->sdt_version,sdt->version_number); rewrite_vars->sdt_version=sdt->version_number; } /** @brief Tells if we copy this descriptor for the rewriting*/ int sdt_rewrite_copy_descriptor(int descriptor_tag) { /* * 0x47 bouquet_name_descriptor * 0x48 service_descriptor * 0x50 component_descriptor * 0x51 mosaic_descriptor * 0x53 CA_identifier_descriptor * 0x5D multilingual_service_name_descriptor * 0x6E announcement_support_descriptor */ int allowed_descriptors[]={0x47, 0x48, 0x50, 0x51, 0x53, 0x5D, 0x6E}; int num_allowed=sizeof(allowed_descriptors)/sizeof(int); for(int i=0;ifull_sdt->data_full); sdt_descr_t *sdt_descr; //was prog unsigned long crc32; int found=0; //destination buffer unsigned char buf_dest[TS_PACKET_SIZE]; int buf_dest_pos=0; int buffer_pos=SDT_LEN; int section_length=0; int new_section_length; int descriptors_length; if(!channel->service_id) { log_message( log_module, MSG_WARN,"Cannot rewrite a program without the service_id set. We deactivate SDT rewrititng for this channel %d : \"%s\"\n", curr_channel, channel->name); channel->sdt_rewrite_skip=1; return 0; } section_length=HILO(sdt->section_length); //lets start the copy //we copy the ts header and adapt it a bit //the continuity counter is updated elswhere if(ts_header->payload_unit_start_indicator) { if(buf[TS_HEADER_LEN-1]) log_message( log_module, MSG_DEBUG,"pointer field 0x%x \n", buf[TS_HEADER_LEN-1]); } ts_header->payload_unit_start_indicator=1; buf[TS_HEADER_LEN-1]=0;//we erase the pointer field memcpy(buf_dest,ts_header,TS_HEADER_LEN); //we copy the modified SDT header sdt->current_next_indicator=1; //applicable immediately sdt->section_number=0; //only one sdt sdt->last_section_number=0; memcpy(buf_dest+TS_HEADER_LEN,sdt,SDT_LEN); buf_dest_pos=TS_HEADER_LEN+SDT_LEN; log_message( log_module, MSG_DEBUG,"table id 0x%x \n", sdt->table_id); if(sdt->table_id!=0x42) { rewrite_vars->sdt_needs_update=1; log_message( log_module, MSG_DETAIL,"We didn't got the good SDT (wrong table id 0x%x) we search for a new one",sdt->table_id); return 0; } //We copy what we need : EIT announce and present PMT announce //strict comparaison due to the calc of section len cf down while((buffer_pos+SDT_DESCR_LEN)<(section_length) && !found) { sdt_descr=(sdt_descr_t *)((char*)rewrite_vars->full_sdt->data_full+buffer_pos); descriptors_length=HILO(sdt_descr->descriptors_loop_length); //We check the transport stream id if present and the size of the packet // + 4 for the CRC32 if(channel->service_id == HILO(sdt_descr->service_id)) { //Not much size checking here, the packet passed the CRC32, so it should be OK log_message( log_module, MSG_DEBUG,"Program found, we search for interesting descriptors\n"); //We loop on the descriptors int loop_length; loop_length=0; unsigned char t_buffer[MAX_TS_SIZE]; sdt_descr_t *t_buffer_ptr; t_buffer_ptr = ((sdt_descr_t *)t_buffer); int pos=0; //we copy the header memcpy(t_buffer,rewrite_vars->full_sdt->data_full+buffer_pos,SDT_DESCR_LEN); while(posfull_sdt->data_full[buffer_pos+SDT_DESCR_LEN+pos]; unsigned char descriptor_len; descriptor_len = rewrite_vars->full_sdt->data_full[buffer_pos+SDT_DESCR_LEN+pos+1]+2; if(sdt_rewrite_copy_descriptor(descriptor_tag)) { //We keep the descriptor we copy it log_message( log_module, MSG_FLOOD,"We copy this descriptor : descriptor_tag 0x%02x descriptor_len %d (on %d) loop length %d pos %d\n",descriptor_tag,descriptor_len,descriptors_length, loop_length, pos); memcpy(t_buffer+SDT_DESCR_LEN+loop_length,rewrite_vars->full_sdt->data_full+buffer_pos+SDT_DESCR_LEN+pos,descriptor_len); loop_length += descriptor_len; } else log_message( log_module, MSG_FLOOD,"descriptor_tag 0x%02x descriptor_len %d actual\n",descriptor_tag,descriptor_len); pos+=descriptor_len; } if(buf_dest_pos+SDT_DESCR_LEN+loop_length+4+1>TS_PACKET_SIZE) //The +4 is for CRC32 +1 is because indexing starts at 0 { log_message( log_module, MSG_WARN,"The generated SDT is too big for channel %d : \"%s\"\n", curr_channel, channel->name); } else { log_message( log_module, MSG_DETAIL,"NEW program for channel %d : \"%s\". service_id : %d\n", curr_channel, channel->name,channel->service_id); //we found a announce for a program in our stream, we keep it //We fill the descriptor loop length t_buffer_ptr->descriptors_loop_length_lo = (loop_length & 0x00FF); t_buffer_ptr->descriptors_loop_length_hi = (loop_length & 0xFF00)>>8; if(HILO(t_buffer_ptr->descriptors_loop_length) != loop_length) { log_message( log_module, MSG_WARN,"BUG file %s line %d\n",__FILE__,__LINE__); return 0; } // We force some flags if asked if(rewrite_vars->sdt_force_eit) { t_buffer_ptr->eit_present_following_flag=1; t_buffer_ptr->eit_schedule_flag=1; } //We copy the data memcpy(buf_dest+buf_dest_pos,t_buffer,SDT_DESCR_LEN+loop_length); buf_dest_pos+=SDT_DESCR_LEN+loop_length; found=1; } } else log_message( log_module, MSG_DEBUG,"Program dropped. channel %d :\"%s\". service_id chan : %d service_id prog %d\n", curr_channel, channel->name, channel->service_id, HILO(sdt_descr->service_id)); buffer_pos+=SDT_DESCR_LEN+descriptors_length; } //we compute the new section length //section lenght is the size of the section after section_length (crc32 included : 4 bytes) //so it's size of the crc32 + size of the sdt descriptors + size of the sdt header - 3 first bytes (the sdt header until section length included) //Finally it's total_sdt_data_size + 1 new_section_length=buf_dest_pos-TS_HEADER_LEN + 1; //We write the new section length buf_dest[1+TS_HEADER_LEN]=(((new_section_length)&0x0f00)>>8) | (0xf0 & buf_dest[1+TS_HEADER_LEN]); buf_dest[2+TS_HEADER_LEN]=new_section_length & 0xff; //CRC32 calculation inspired by the xine project //Now we must adjust the CRC32 //we compute the CRC32 crc32=0xffffffff; int i; for(i = 0; i < new_section_length-1; i++) { crc32 = (crc32 << 8) ^ crc32_table[((crc32 >> 24) ^ buf_dest[i+TS_HEADER_LEN])&0xff]; } //We write the CRC32 to the buffer buf_dest[buf_dest_pos]=(crc32>>24) & 0xff; buf_dest_pos+=1; buf_dest[buf_dest_pos]=(crc32>>16) & 0xff; buf_dest_pos+=1; buf_dest[buf_dest_pos]=(crc32>>8) & 0xff; buf_dest_pos+=1; buf_dest[buf_dest_pos]=crc32 & 0xff; buf_dest_pos+=1; //Padding with 0xFF memset(buf_dest+buf_dest_pos,0xFF,TS_PACKET_SIZE-buf_dest_pos); if(found) { //We copy the result to the intended buffer memcpy(channel->generated_sdt,buf_dest,TS_PACKET_SIZE); channel->sdt_rewrite_skip=0; } else { //We check if we saw all the section numbers if(sdt_rewrite_all_sections_seen(rewrite_vars)) { log_message( log_module, MSG_WARN,"The SDT rewrite failed (no program found, wrong service_id ?) we deactivate for this channel %d : \"%s\"\n", curr_channel, channel->name); channel->sdt_rewrite_skip=1; } else { log_message( log_module, MSG_DETAIL,"The program was not found in this SDT, we search for others. Channel %d : \"%s\"\n", curr_channel, channel->name); rewrite_vars->sdt_need_others = 1; return 0; //We indicate that there was a problem } } /*We update the version*/ channel->generated_sdt_version=rewrite_vars->sdt_version; //Everything is Ok .... return 1; } /** @brief This function is called when a new SDT packet for all channels is there and we asked for rewrite * this function save the full SDT wich will be the source SDT for all the channels * @return return 1 when the packet is updated */ int sdt_rewrite_new_global_packet(unsigned char *ts_packet, rewrite_parameters_t *rewrite_vars) { sdt_t *sdt=NULL; /*Check the version before getting the full packet*/ if(!rewrite_vars->sdt_needs_update) { rewrite_vars->sdt_needs_update=sdt_need_update(rewrite_vars,ts_packet); if(rewrite_vars->sdt_needs_update) //It needs update we mark the packet as empty and we clear the sections seen { //We clear the section numbers seen memset(&rewrite_vars->sdt_section_numbers_seen,0,sizeof(rewrite_vars->sdt_section_numbers_seen)); } } /*We need to update the full packet, we download it*/ if(rewrite_vars->sdt_needs_update || rewrite_vars->sdt_need_others) { while(get_ts_packet(ts_packet,rewrite_vars->full_sdt)) { ts_packet=NULL; // next call we only POP packets from the stack sdt=(sdt_t*)(rewrite_vars->full_sdt->data_full); /*current_next_indicator – A 1-bit indicator, which when set to '1' indicates that the Program Association Table sent is currently applicable. When the bit is set to '0', it indicates that the table sent is not yet applicable and shall be the next table to become valid.*/ if(sdt->current_next_indicator == 0) { log_message( log_module, MSG_FLOOD,"SDT not yet valid, we get a new one (current_next_indicator == 0)\n"); } else if(sdt->table_id!=0x42) { rewrite_vars->sdt_needs_update=1; log_message( log_module, MSG_DEBUG,"We didn't got the good SDT (wrong table id) we search for a new one\n"); break; } else { rewrite_vars->sdt_last_section_number = sdt->last_section_number; log_message( log_module, MSG_DETAIL,"Full SDT updated. section number %d, last_section_number %d\n", sdt->section_number, rewrite_vars->sdt_last_section_number); //We store that we saw this section number rewrite_vars->sdt_section_numbers_seen[sdt->section_number]=1; /*We've got the FULL SDT packet*/ update_sdt_version(rewrite_vars); rewrite_vars->sdt_needs_update = 0; rewrite_vars->full_sdt_ok=1; if(rewrite_vars->sdt_need_others == 0) return 1; //We force the update of all channels, see mumudvb.c else { rewrite_vars->sdt_need_others = 0; break; } } } } //To avoid the duplicates, we have to update the continuity counter rewrite_vars->sdt_continuity_counter++; rewrite_vars->sdt_continuity_counter= rewrite_vars->sdt_continuity_counter % 32; return 0; } /** @brief This function is called when a new SDT packet for a channel is there and we asked for rewrite * This function copy the rewritten SDT to the buffer. And checks if the SDT was changed so the rewritten version have to be updated */ int sdt_rewrite_new_channel_packet(unsigned char *ts_packet, rewrite_parameters_t *rewrite_vars, mumudvb_channel_t *channel, int curr_channel) { if(rewrite_vars->full_sdt_ok ) //the global full sdt is ok { /*We check if it's the first sdt packet ? or we send it each time ?*/ /*We check if the versions corresponds*/ if(!rewrite_vars->sdt_needs_update && channel->channel_ready>=READY && channel->generated_sdt_version!=rewrite_vars->sdt_version)//We check the version only if the SDT is not currently updated { log_message( log_module, MSG_DEBUG,"We need to rewrite the SDT for the channel %d : \"%s\"\n", curr_channel, channel->name); /*They mismatch*/ /*We generate the rewritten packet*/ if(!sdt_channel_rewrite(rewrite_vars, channel, ts_packet, curr_channel)) { log_message( log_module, MSG_DEBUG,"Cannot rewrite (for the moment) the SDT for the channel %d : \"%s\"\n", curr_channel, channel->name); return 0; } } if(channel->generated_sdt_version==rewrite_vars->sdt_version) { /*We send the rewritten SDT from channel->generated_sdt*/ memcpy(ts_packet,channel->generated_sdt,TS_PACKET_SIZE); //To avoid the duplicates, we have to update the continuity counter set_continuity_counter(ts_packet,rewrite_vars->sdt_continuity_counter); } else { log_message( log_module, MSG_DEBUG,"Bad SDT channel version, we don't send the SDT for the channel %d : \"%s\"\n", curr_channel, channel->name); return 0; } } else { log_message( log_module, MSG_DEBUG,"We need a global SDT update, we don't send the SDT for the channel %d : \"%s\"\n", curr_channel, channel->name); return 0; } return 1; } MuMuDVB-2.1.0/src/rtp.c000066400000000000000000000071031305714132500144730ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * * (C) 2009 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** @file * This file contains the functions concerning the RTP header */ #include "mumudvb.h" #include #include /**@brief : This function add the RTP header to a channel * * Note : it reset the buffer of the channel * * @param channel the channel to be initialised */ void init_rtp_header(mumudvb_channel_t *channel) { // See RFC 1889 channel->buf_with_rtp_header[0]=128; //version=2 padding=0 extension=0 CSRC=0 channel->buf_with_rtp_header[1]=33; // marker=0 payload type=33 (MP2T) channel->buf_with_rtp_header[2]=0; // sequence number channel->buf_with_rtp_header[3]=0; // sequence number channel->buf_with_rtp_header[4]=0; // timestamp channel->buf_with_rtp_header[5]=0; // timestamp channel->buf_with_rtp_header[6]=0; // timestamp channel->buf_with_rtp_header[7]=0; // timestamp channel->buf_with_rtp_header[8]= (char)(rand() % 256); // synchronization source channel->buf_with_rtp_header[9]= (char)(rand() % 256); // synchronization source channel->buf_with_rtp_header[10]=(char)(rand() % 256); // synchronization source channel->buf_with_rtp_header[11]=(char)(rand() % 256); // synchronization source } void rtp_update_sequence_number(mumudvb_channel_t *channel, uint64_t time) { /* From RFC 2250 RTP Format for MPEG1/MPEG2 Video January 1998 Each RTP packet will contain a timestamp derived from the sender's 90KHz clock reference. This clock is synchronized to the system stream Program Clock Reference (PCR) or System Clock Reference (SCR) and represents the target transmission time of the first byte of the packet payload. The RTP timestamp will not be passed to the MPEG decoder. This use of the timestamp is somewhat different than normally is the case in RTP, in that it is not considered to be the media display or presentation timestamp. The primary purposes of the RTP timestamp will be to estimate and reduce any network-induced jitter and to synchronize relative time drift between the transmitter and receiver.*/ uint32_t timestamp; timestamp=(uint32_t) (90000 * (time/1000000ll))+(9*(time%1000000ll))/100; // 90 kHz Clock // Change the header (sequence number) channel->buf_with_rtp_header[2]=(char)((channel->rtp_packet_num >> 8) & 0xff); // sequence number (high) channel->buf_with_rtp_header[3]=(char)(channel->rtp_packet_num & 0xff); // sequence number (low) channel->buf_with_rtp_header[4]=(timestamp>>24)&0x0FF; // timestamp channel->buf_with_rtp_header[5]=(timestamp>>16)&0x0FF; // timestamp channel->buf_with_rtp_header[6]=(timestamp>>8)&0x0FF; // timestamp channel->buf_with_rtp_header[7]=(timestamp)&0x0FF; // timestamp channel->rtp_packet_num++; channel->rtp_packet_num &= 0xffff; } MuMuDVB-2.1.0/src/rtp.h000066400000000000000000000021631305714132500145010ustar00rootroot00000000000000/* * MuMuDVB - UDP-ize a DVB transport stream. * * (C) 2009 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** @file * This file contains the headers concerning the RTP header */ #ifndef _RTP_H #define _RTP_H void init_rtp_header(mumudvb_channel_t *channel); void rtp_update_sequence_number(mumudvb_channel_t *channel, uint64_t time); #endifMuMuDVB-2.1.0/src/sap.c000066400000000000000000000473251305714132500144630ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * * (C) 2008-2010 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** @file * @brief File for Session Announcement Protocol Announces * @author Brice DUBOST * @date 2008-2013 */ #include "sap.h" #include "network.h" #include #include #include #include "log.h" extern uint32_t crc32_table[256]; static char *log_module="SAP: "; int sap_add_program(mumudvb_channel_t *channel, sap_p_t *sap_p, mumudvb_sap_message_t *sap_message4, mumudvb_sap_message_t *sap_message6, multi_p_t multi_p); /** Initialize sap variables*/ void init_sap_v(sap_p_t *sap_p) { *sap_p=(sap_p_t){ .sap_messages4=NULL, .sap_messages6=NULL, .sap=OPTION_UNDEFINED, //No sap by default .sap_interval=SAP_DEFAULT_INTERVAL, .sap_sending_ip4="0.0.0.0", .sap_sending_ip6="::", .sap_default_group="", .sap_organisation="MuMuDVB", .sap_uri="\0", .sap_ttl=SAP_DEFAULT_TTL, }; } /** @brief Read a line of the configuration file to check if there is a sap parameter * * @param sap_p the sap parameters * @param substring The currrent line */ int read_sap_configuration(sap_p_t *sap_p, mumudvb_channel_t *c_chan, char *substring) { char delimiteurs[] = CONFIG_FILE_SEPARATOR; if (!strcmp (substring, "sap")) { substring = strtok (NULL, delimiteurs); if(atoi (substring) != 0) sap_p->sap = OPTION_ON; else sap_p->sap = OPTION_OFF; if(sap_p->sap == OPTION_ON) { log_message( log_module, MSG_INFO, "Sap announces will be sent\n"); } } else if (!strcmp (substring, "sap_interval")) { substring = strtok (NULL, delimiteurs); sap_p->sap_interval = atoi (substring); } else if (!strcmp (substring, "sap_ttl")) { substring = strtok (NULL, delimiteurs); sap_p->sap_ttl = atoi (substring); } else if (!strcmp (substring, "sap_organisation")) { // other substring extraction method in order to keep spaces substring = strtok (NULL, "="); strncpy(sap_p->sap_organisation,strtok(substring,"\n"),255 - 1); sap_p->sap_organisation[255]='\0'; if ((strlen (substring) >= 255 - 1)) log_message( log_module, MSG_WARN,"SAP organization name too long\n"); } else if (!strcmp (substring, "sap_uri")) { // other substring extraction method in order to keep spaces substring = strtok (NULL, "="); strncpy(sap_p->sap_uri,strtok(substring,"\n"),255 - 1); sap_p->sap_uri[255]='\0'; if ((strlen (substring) >= 255 - 1)) log_message( log_module, MSG_WARN,"Sap URI too long\n"); } else if (!strcmp (substring, "sap_sending_ip4")) { substring = strtok (NULL, delimiteurs); if(strlen(substring)>19) { log_message( log_module, MSG_ERROR, "The sap sending ip is too long\n"); return -1; } sscanf (substring, "%s\n", sap_p->sap_sending_ip4); } else if (!strcmp (substring, "sap_sending_ip6")) { substring = strtok (NULL, delimiteurs); if(strlen(substring)>(IPV6_CHAR_LEN-1)) { log_message( log_module, MSG_ERROR, "The sap sending ipv6 is too long\n"); return -1; } sscanf (substring, "%s\n", sap_p->sap_sending_ip6); } else if (!strcmp (substring, "sap_group")) { if ( c_chan == NULL) { log_message( log_module, MSG_ERROR, "sap_group : this is a channel option, You have to start a channel first (using new_channel)\n"); return -1; } substring = strtok (NULL, "="); if(strlen(substring)>(SAP_GROUP_LENGTH-1)) { log_message( log_module, MSG_ERROR, "The sap group is too long\n"); return -1; } strcpy (c_chan->sap_group, substring); MU_F(c_chan->sap_group)=F_USER; } else if (!strcmp (substring, "sap_default_group")) { substring = strtok (NULL, "="); if(strlen(substring)>(SAP_GROUP_LENGTH-1)) { log_message( log_module, MSG_ERROR, "The sap default group is too long\n"); return -1; } strcpy (sap_p->sap_default_group, substring); } else return 0; //Nothing concerning sap, we return 0 to explore the other possibilities return 1;//We found something for sap, we tell main to go for the next line } /** @brief init the sap * Alloc the memory for the messages, open the socket */ int init_sap(sap_p_t *sap_p, multi_p_t multi_p) { if(sap_p->sap == OPTION_ON) { if(multi_p.multicast_ipv4) { log_message( log_module, MSG_DETAIL, "init sap v4\n"); sap_p->sap_messages4=malloc(sizeof(mumudvb_sap_message_t)*MAX_CHANNELS); if(sap_p->sap_messages4==NULL) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); return -1; } memset (sap_p->sap_messages4, 0, sizeof( mumudvb_sap_message_t)*MAX_CHANNELS);//we clear it //For sap announces, we open the socket //See the README about multicast_auto_join if(multi_p.auto_join) sap_p->sap_socketOut4 = makeclientsocket (SAP_IP4, SAP_PORT, sap_p->sap_ttl, multi_p.iface4, &sap_p->sap_sOut4); else sap_p->sap_socketOut4 = makesocket (SAP_IP4, SAP_PORT, sap_p->sap_ttl, multi_p.iface4, &sap_p->sap_sOut4); } if(multi_p.multicast_ipv6) { log_message( log_module, MSG_DETAIL, "init sap v6\n"); sap_p->sap_messages6=malloc(sizeof(mumudvb_sap_message_t)*MAX_CHANNELS); if(sap_p->sap_messages6==NULL) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); return -1; } memset (sap_p->sap_messages6, 0, sizeof( mumudvb_sap_message_t)*MAX_CHANNELS);//we clear it //For sap announces, we open the socket //See the README about multicast_auto_join if(multi_p.auto_join) sap_p->sap_socketOut6 = makeclientsocket6 (SAP_IP6, SAP_PORT, sap_p->sap_ttl, multi_p.iface6, &sap_p->sap_sOut6); else sap_p->sap_socketOut6 = makesocket6 (SAP_IP6, SAP_PORT, sap_p->sap_ttl, multi_p.iface6, &sap_p->sap_sOut6); } sap_p->sap_serial= 1 + (int) (424242.0 * (rand() / (RAND_MAX + 1.0))); sap_p->sap_last_time_sent = 0; /** @todo : loop to create the version*/ } return 0; } /** @brief Send the sap message * * @param sap_p the sap variables * @param num_messages the number of sap messages */ void sap_send(sap_p_t *sap_p, int num_messages) { int curr_message; mumudvb_sap_message_t *sap_messages4; mumudvb_sap_message_t *sap_messages6; sap_messages4=sap_p->sap_messages4; sap_messages6=sap_p->sap_messages6; for( curr_message=0; curr_messagesap_socketOut4, &sap_p->sap_sOut4, sap_messages4[curr_message].buf, sap_messages4[curr_message].len); if(sap_messages6 && sap_messages6[curr_message].to_be_sent) sendudp6 (sap_p->sap_socketOut6, &sap_p->sap_sOut6, sap_messages6[curr_message].buf, sap_messages6[curr_message].len); } return; } /** @brief update the contents of the sap message * This function read the informations of the channel and update the sap message * @param channel : the channel to be updated * @param sap_p the sap variables * @param curr_channel the number of the updated channel */ int sap_update(mumudvb_channel_t *channel, sap_p_t *sap_p, int curr_channel, multi_p_t multi_p) { /** @todo check PACKET Size < MTU*/ log_message( log_module, MSG_DEBUG,"sap update channel SID %d name \"%s\"",channel->service_id,channel->name); //This function is called when the channel changes so it increases the version and update the packet char temp_string[256]; struct in_addr ip_struct4; struct sockaddr_in6 ip_struct6; in_addr_t ip4; struct in6_addr ip6; mumudvb_sap_message_t *sap_message4=NULL; mumudvb_sap_message_t *sap_message6=NULL; if(channel->socketOut4) { sap_message4=&(sap_p->sap_messages4[curr_channel]); //paranoia memset(sap_message4->buf,0, MAX_UDP_SIZE * sizeof (unsigned char)); sap_message4->version=(sap_message4->version+1)&0x000f; sap_message4->buf[0]=SAP_HEADER4_BYTE0; sap_message4->buf[1]=SAP_HEADER4_BYTE1; //Hash of SAP message: see end of this function sap_message4->buf[2]=0; sap_message4->buf[3]=0; } if(channel->socketOut6) { sap_message6=&(sap_p->sap_messages6[curr_channel]); //paranoia memset(sap_message6->buf,0, MAX_UDP_SIZE * sizeof (unsigned char)); sap_message6->version=(sap_message6->version+1)&0x000f; sap_message6->buf[0]=SAP_HEADER6_BYTE0; sap_message6->buf[1]=SAP_HEADER6_BYTE1; //Hash of SAP message: see end of this function sap_message6->buf[2]=0; sap_message6->buf[3]=0; } if(channel->socketOut4) { if( inet_aton(sap_p->sap_sending_ip4, &ip_struct4)) { ip4=ip_struct4.s_addr; /* Bytes 4-7 (or 4-19) byte: Originating source */ log_message( log_module, MSG_DEBUG,"sap sending ipv4 address : %s (binary : 0x%x)\n",sap_p->sap_sending_ip4, ip4); memcpy (sap_message4->buf + 4, &ip4, 4); } else { log_message( log_module, MSG_WARN,"Invalid SAP sending Ip address, using 0.0.0.0 as Ip address\n"); sap_message4->buf[4]=0; sap_message4->buf[5]=0; sap_message4->buf[6]=0; sap_message4->buf[7]=0; } } if(channel->socketOut6) { if( inet_pton(AF_INET6, sap_p->sap_sending_ip6, &ip_struct6)) { ip6=ip_struct6.sin6_addr; log_message( log_module, MSG_DEBUG,"sap sending ipv6 address : %s\n",sap_p->sap_sending_ip6); /* Bytes 4-7 (or 4-19) byte: Originating source */ memcpy (sap_message6->buf + 4, &ip6.s6_addr, 16); } else { log_message( log_module, MSG_WARN,"Invalid SAP sending IPv6 address, using :: as IPv6 address\n"); memset(sap_message6->buf+4,0,16*sizeof(char)); } } //the mime type sprintf(temp_string,"application/sdp"); if(channel->socketOut4) { memcpy(sap_message4->buf + SAP_HEAD_LEN4, temp_string, strlen(temp_string)); sap_message4->len=SAP_HEAD_LEN4+strlen(temp_string); sap_message4->buf[sap_message4->len]=0; sap_message4->len++; } if(channel->socketOut6) { memcpy(sap_message6->buf + SAP_HEAD_LEN6, temp_string, strlen(temp_string)); sap_message6->len=SAP_HEAD_LEN6+strlen(temp_string); sap_message6->buf[sap_message6->len]=0; sap_message6->len++; } // one program per message sap_add_program(channel, sap_p, sap_message4, sap_message6, multi_p); //we compute the CRC32 of the message in order to generate a hash unsigned long crc32; int i; crc32=0xffffffff; if(channel->socketOut4) { for(i = 0; i < sap_message4->len-1; i++) { crc32 = (crc32 << 8) ^ crc32_table[((crc32 >> 24) ^ sap_message4->buf[i])&0xff]; } //Hash of SAP message : we use the CRC32 that we merge onto 16bits sap_message4->buf[2]=(((crc32>>24) & 0xff)+((crc32>>16) & 0xff)) & 0xff; sap_message4->buf[3]=(((crc32>>8) & 0xff)+(crc32 & 0xff)) & 0xff; } crc32=0xffffffff; if(channel->socketOut6) { for(i = 0; i < sap_message6->len-1; i++) { crc32 = (crc32 << 8) ^ crc32_table[((crc32 >> 24) ^ sap_message6->buf[i])&0xff]; } //Hash of SAP message : we use the CRC32 that we merge onto 16bits sap_message6->buf[2]=(((crc32>>24) & 0xff)+((crc32>>16) & 0xff)) & 0xff; sap_message6->buf[3]=(((crc32>>8) & 0xff)+(crc32 & 0xff)) & 0xff; } channel->sap_need_update=0; return 0; } /** @brief Add a program to a sap message * When this function is called the header of the sap message is already done * it adds the payload (sdp). For mare information refer to RFC 2327 and RFC 1890 * @param channel the channel * @param sap_p the sap variables * @param sap_message the sap message */ int sap_add_program(mumudvb_channel_t *channel, sap_p_t *sap_p, mumudvb_sap_message_t *sap_message4, mumudvb_sap_message_t *sap_message6, multi_p_t multi_p) { //See RFC 2327 mumu_string_t payload4; payload4.string=NULL; payload4.length=0; mumu_string_t payload6; payload6.string=NULL; payload6.length=0; if(channel->socketOut4) sap_message4->to_be_sent=0; if(channel->socketOut6) sap_message6->to_be_sent=0; //we check if it's an alive channel if(channel->channel_readysocketOut4) mumu_string_append(&payload4, "v=0\r\no=%s %d %d IN IP4 %s\r\ns=%s\r\n", sap_p->sap_organisation, sap_p->sap_serial, sap_message4->version, channel->ip4Out, channel->name); if(channel->socketOut6) mumu_string_append(&payload6, "v=0\r\no=%s %d %d IN IP6 %s\r\ns=%s\r\n", sap_p->sap_organisation, sap_p->sap_serial, sap_message6->version, channel->ip6Out, channel->name); /** @subsection URI ex : u=http://www.cs.ucl.ac.uk/staff/M.Handley/sdp.03.ps u= o A URI is a Universal Resource Identifier as used by WWW clients o The URI should be a pointer to additional information about the conference o This field is optional, but if it is present it should be specified before the first media field o No more than one URI field is allowed per session description */ if(strlen(sap_p->sap_uri)) { if(channel->socketOut4) mumu_string_append(&payload4, "u=%s\r\n", sap_p->sap_uri); if(channel->socketOut6) mumu_string_append(&payload6, "u=%s\r\n", sap_p->sap_uri); } /** @subsection connection information ex : c=IN IP4 235.214.225.1/2 the /2 is the TTL of the media (IPv4 only) */ if(channel->socketOut4) mumu_string_append(&payload4, "c=IN IP4 %s/%d\r\n", channel->ip4Out, multi_p.ttl); if(channel->socketOut6) mumu_string_append(&payload6, "c=IN IP6 %s\r\n", channel->ip6Out); /**@subsection time session : tell when the session is active t=... permanent program : t=0 0 @subsection attributes : group and co, we'll take the minisapserver ones a=... a=tool:mumudvb-VERSION a=type:broadcast a=x-plgroup: //channel's group */ if(channel->socketOut4) mumu_string_append(&payload4,"t=0 0\r\na=tool:mumudvb-%s\r\na=type:broadcast\r\n", VERSION); if(channel->socketOut6) mumu_string_append(&payload6,"t=0 0\r\na=tool:mumudvb-%s\r\na=type:broadcast\r\n", VERSION); /** @subsection "source-filter" attribute RFC 4570 SDP Source Filters ex : a=source-filter: incl IN IP4 235.255.215.1 192.168.1.1 only defined when the sending ip address is defined */ if(channel->socketOut4) { struct in_addr ip_struct4; if( inet_aton(sap_p->sap_sending_ip4, &ip_struct4) && ip_struct4.s_addr) mumu_string_append(&payload4, "a=source-filter: incl IN IP4 %s %s\r\n", channel->ip4Out, sap_p->sap_sending_ip4); } if(channel->socketOut6) { struct sockaddr_in6 ip_struct6; if( inet_pton(AF_INET6, sap_p->sap_sending_ip6, &ip_struct6)) { //ugly way to test non zero ipv6 addr but I didn found a better one u_int8_t *s6; s6=ip_struct6.sin6_addr.s6_addr; if(s6[0]||s6[1]||s6[2]||s6[3]||s6[4]||s6[5]||s6[6]||s6[7]||s6[8]||s6[9]||s6[10]||s6[11]||s6[12]||s6[13]||s6[14]||s6[15]) mumu_string_append(&payload6, "a=source-filter: incl IP6 %s %s\r\n", channel->ip6Out, sap_p->sap_sending_ip6); } } /**@subsection channel's group a=cat channel's group a=x-plgroup backward compatibility */ if(strlen(channel->sap_group)||strlen(sap_p->sap_default_group)) { if(!strlen(channel->sap_group)) { int len=SAP_GROUP_LENGTH; strcpy(channel->sap_group,sap_p->sap_default_group); mumu_string_replace(channel->sap_group,&len,0,"%type",simple_service_type_to_str(channel->service_type) ); } if(channel->socketOut4) mumu_string_append(&payload4,"a=cat:%s\r\n", channel->sap_group); /* backward compatibility with VLC 0.7.3-2.0.0 senders */ mumu_string_append(&payload4,"a=x-plgroup:%s\r\n", channel->sap_group); if(channel->socketOut6) mumu_string_append(&payload6,"a=cat:%s\r\n", channel->sap_group); /* backward compatibility with VLC 0.7.3-2.0.0 senders */ mumu_string_append(&payload6,"a=x-plgroup:%s\r\n", channel->sap_group); } /** @subsection media name and transport address See RFC 1890 m=... Without RTP m=video channel_port udp 33 With RTP m=video channel_port rtp/avp 33 */ if(!multi_p.rtp_header) { if(channel->socketOut4) mumu_string_append(&payload4,"m=video %d udp 33\r\n", channel->portOut); if(channel->socketOut6) mumu_string_append(&payload6,"m=video %d udp 33\r\n", channel->portOut); } else { if(channel->socketOut4) mumu_string_append(&payload4,"m=video %d RTP/AVP 33\r\na=rtpmap:33 MP2T/90000\r\n", channel->portOut); if(channel->socketOut6) mumu_string_append(&payload6,"m=video %d RTP/AVP 33\r\na=rtpmap:33 MP2T/90000\r\n", channel->portOut); } if(channel->socketOut4) { if( (sap_message4->len+payload4.length)>1024) { log_message( log_module, MSG_WARN,"SAP message v4 too long for channel %s\n",channel->name); goto epicfail; } memcpy(sap_message4->buf + sap_message4->len, payload4.string, payload4.length); log_message( log_module, MSG_DEBUG,"SAP payload v4"); log_message( log_module, MSG_DEBUG, "%s", (char *) &sap_message4->buf[sap_message4->len]); log_message( log_module, MSG_DEBUG,"end of SAP payload v4"); sap_message4->len+=payload4.length; sap_message4->to_be_sent=1; } if(channel->socketOut6) { if( (sap_message6->len+payload6.length)>1024) { log_message( log_module, MSG_WARN,"SAP message v4 too long for channel %s\n",channel->name); goto epicfail; } memcpy(sap_message6->buf + sap_message6->len, payload6.string, payload6.length); log_message( log_module, MSG_DEBUG,"SAP payload v6"); log_message( log_module, MSG_DEBUG, "%s", (char *) &sap_message6->buf[sap_message6->len]); log_message( log_module, MSG_DEBUG,"end of SAP payload v6"); sap_message6->len+=payload6.length; sap_message6->to_be_sent=1; } mumu_free_string(&payload4); mumu_free_string(&payload6); return 0; epicfail: mumu_free_string(&payload4); mumu_free_string(&payload6); return 1; } /** @brief Sap function called periodically * This function checks if there is sap messages to send * @param number_of_channels the number of channels * @param channels the channels * @param sap_p the sap variables * @param multi_p the multicast variables * @param now the time */ void sap_poll(sap_p_t *sap_p,int number_of_channels,mumudvb_channel_t *channels, multi_p_t multi_p, long now) { int curr_channel; //we check if SAP is initialized if(sap_p->sap_messages4==NULL && sap_p->sap_messages6==NULL) return; if(sap_p->sap == OPTION_ON) { if(!sap_p->sap_last_time_sent) { // it's the first time we are here, we initialize all the channels for (curr_channel = 0; curr_channel < number_of_channels; curr_channel++) if(channels[curr_channel].channel_ready>=READY) sap_update(&channels[curr_channel], sap_p, curr_channel, multi_p); sap_p->sap_last_time_sent=now-sap_p->sap_interval-1; } for (curr_channel = 0; curr_channel < number_of_channels; curr_channel++) if(channels[curr_channel].sap_need_update && (channels[curr_channel].channel_ready>=READY)) sap_update(&channels[curr_channel], sap_p, curr_channel, multi_p); if((now-sap_p->sap_last_time_sent)>=sap_p->sap_interval) { sap_send(sap_p, number_of_channels); sap_p->sap_last_time_sent=now; } } } MuMuDVB-2.1.0/src/sap.h000066400000000000000000000074451305714132500144670ustar00rootroot00000000000000/* * mumudvb - UDP-ize a DVB transport stream. * File for Session Announcement Protocol Announces * * (C) 2008-2009 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** @file * @brief Header File for Session Announcement Protocol Announces * @author Brice DUBOST * @date 2008-2009 */ #ifndef _SAP_H #define _SAP_H #include "mumudvb.h" /**refer to RFC 2974 : sap IP address*/ #define SAP_IP4 "224.2.127.254" /**refer to RFC 2974 : sap IP address*/ #define SAP_IP6 "FF05::2:7FFE" /**refer to RFC 2974 : sap port*/ #define SAP_PORT 9875 /**refer to RFC 2974 : sap time to live*/ #define SAP_DEFAULT_TTL 255 /**intervall between sap announces*/ #define SAP_DEFAULT_INTERVAL 5 #define SAP_HEADER4_BYTE0 0x20 /**00100000 : version 1 and nothing else*/ #define SAP_HEADER4_BYTE1 0x00 /**No auth header*/ #define SAP_HEADER6_BYTE0 0x30 /**00110000 : version 1 and IPv6*/ #define SAP_HEADER6_BYTE1 0x00 /**No auth header*/ #define SAP_HEAD_LEN4 8 #define SAP_HEAD_LEN6 20 /**@brief sap_message*/ typedef struct{ /**the buffer*/ unsigned char buf[MAX_UDP_SIZE]; /**Lenght of the sap message*/ int len; /**the version of the sap message, MUST be changed when sap changes*/ int version; /** Do we have to send this message ?*/ int to_be_sent; }mumudvb_sap_message_t; /**@brief General parameter for sap announces*/ typedef struct sap_p_t{ /**the sap messages array*/ mumudvb_sap_message_t *sap_messages4; /**the sap messages array*/ mumudvb_sap_message_t *sap_messages6; /**do we send sap announces ?*/ option_status_t sap; /**Interval between two sap announces in second*/ int sap_interval; /** The ip address of the server that sends the sap announces*/ char sap_sending_ip4[20]; /** The ip address of the server that sends the sap announces*/ char sap_sending_ip6[IPV6_CHAR_LEN]; /**the default cat : ie the playlist group (mainly for vlc)*/ char sap_default_group[SAP_GROUP_LENGTH]; /**The URI The URI should be a pointer to additional information about the conference*/ char sap_uri[256]; /**The organisation wich made the announces*/ char sap_organisation[256]; /** The socket for sending the announces*/ int sap_socketOut4; /** The socket for sending the announces*/ struct sockaddr_in sap_sOut4; /** The socket for sending the announces*/ int sap_socketOut6; /** The socket for sending the announces*/ struct sockaddr_in6 sap_sOut6; /** The serial number for the sap announces*/ int sap_serial; /** The time when the last sap announces have been sent*/ long sap_last_time_sent; /** The sap ttl (the norm ask it to be 255)*/ int sap_ttl; }sap_p_t; void init_sap_v(sap_p_t *sap_vars); int init_sap(sap_p_t *sap_vars, multi_p_t multi_p); void sap_send(sap_p_t *sap_vars, int num_messages); int sap_update(mumudvb_channel_t *channel, sap_p_t *sap_vars, int curr_channel, multi_p_t multi_p); int read_sap_configuration(sap_p_t *sap_vars, mumudvb_channel_t *c_chan, char *substring); void sap_poll(sap_p_t *sap_vars,int number_of_channels,mumudvb_channel_t *channels, multi_p_t multi_p, long now); #endif MuMuDVB-2.1.0/src/scam_capmt.c000077500000000000000000000116141305714132500160020ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * File for software descrambling connection with oscam * * (C) 2004-2010 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Code inspired by vdr plugin dvbapi * Copyright (C) 2011,2012 Mariusz Białończyk * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include "errors.h" #include "ts.h" #include "mumudvb.h" #include "log.h" #include "scam_common.h" /**@file * @brief scam support * * Code for asking oscam to begin geting cw's for channel */ static char *log_module="SCAM_CAPMT: "; /** @brief sending to oscam data to begin geting cw's for channel */ int scam_send_capmt(mumudvb_channel_t *channel, scam_parameters_t *scam_params, int adapter) { if (channel->camd_socket < 0) { channel->camd_socket = socket(AF_LOCAL, SOCK_STREAM, 0); struct sockaddr_un serv_addr_un; memset(&serv_addr_un, 0, sizeof(serv_addr_un)); serv_addr_un.sun_family = AF_LOCAL; snprintf(serv_addr_un.sun_path, sizeof(serv_addr_un.sun_path), "/tmp/camd.socket"); if (connect(channel->camd_socket, (const struct sockaddr *) &serv_addr_un, sizeof(serv_addr_un)) != 0) { log_message(log_module, MSG_DEBUG,"cannot connect to /tmp/camd.socket for channel %s. Do you have OSCam running?\n", channel->name); close(channel->camd_socket); channel->camd_socket = -1; return 1; } else log_message(log_module, MSG_DEBUG, "created socket for channel %s\n", channel->name); //moved this into this block since PMTs will now be sent more than once and this would cause errors with EPOLL_CTL_ADD int flags, s; flags = fcntl (channel->camd_socket, F_GETFL, 0); if (flags == -1) { log_message(log_module, MSG_ERROR,"channel %s: unsuccessful fcntl F_GETFL", channel->name); set_interrupted(ERROR_NETWORK<<8); return 1; } flags |= O_NONBLOCK; s = fcntl (channel->camd_socket, F_SETFL, flags); if (s == -1) { log_message(log_module, MSG_ERROR,"channel %s: unsuccessful fcntl F_SETFL", channel->name); set_interrupted(ERROR_NETWORK<<8); return 1; } struct epoll_event event = { 0 }; event.data.fd = channel->camd_socket; event.events = EPOLLIN | EPOLLPRI | EPOLLERR | EPOLLHUP; s = epoll_ctl(scam_params->epfd, EPOLL_CTL_ADD, channel->camd_socket, &event); if (s == -1) { log_message(log_module, MSG_ERROR,"channel %s: unsuccessful epoll_ctl EPOLL_CTL_ADD", channel->name); set_interrupted(ERROR_NETWORK<<8); return 1; } } char *caPMT = (char *) calloc(1024, 1); int length_field; int toWrite; caPMT[0] = 0x9F; caPMT[1] = 0x80; caPMT[2] = 0x32; caPMT[3] = 0x82; //2 following bytes for size caPMT[6] = 0x03; //list management = 3 caPMT[7] = channel->service_id >> 8; //program_number caPMT[8] = channel->service_id & 0xff; //program_number caPMT[9] = 0; //version_number, current_next_indicator caPMT[12] = 0x01; //ca_pmt_cmd_id = CAPMT_CMD_OK_DESCRAMBLING //adding own descriptor with demux and adapter_id caPMT[13] = 0x82; //CAPMT_DESC_DEMUX caPMT[14] = 0x02; //length caPMT[15] = 0x00; //demux id caPMT[16] = (char) adapter; //adapter id caPMT[10] = (*(channel->scam_pmt_packet)).data_full[10]; //reserved+program_info_length caPMT[11] = (*(channel->scam_pmt_packet)).data_full[11] + 1 + 4; //reserved+program_info_length (+1 for ca_pmt_cmd_id, +4 for above CAPMT_DESC_DEMUX) memcpy(caPMT + 17, (*(channel->scam_pmt_packet)).data_full + 12, (*(channel->scam_pmt_packet)).len_full -12 - 4); length_field = 17 + ((*(channel->scam_pmt_packet)).len_full - 11 - 4) - 6; caPMT[4] = length_field >> 8; caPMT[5] = length_field & 0xff; toWrite = length_field + 6; int wrote = write(channel->camd_socket, caPMT, toWrite); log_message( log_module, MSG_INFO, "sent CAPMT message to socket for channel %s, toWrite=%d wrote=%d\n", channel->name, toWrite, wrote); free(caPMT); if (wrote != toWrite) { log_message(log_module, MSG_ERROR,"channel %s:wrote != toWrite\n", channel->name); close(channel->camd_socket); channel->camd_socket = -1; return 1; } return 0; } MuMuDVB-2.1.0/src/scam_capmt.h000066400000000000000000000027621305714132500160100ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * Header file for software descrambling connection with oscam * * (C) 2004-2010 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Code inspired by vdr plugin dvbapi * Copyright (C) 2011,2012 Mariusz Białończyk * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef _SCAM_CAPMT_H #define _SCAM_CAPMT_H #include #include #include #include #include #include #include #include #include #include #include "scam_common.h" /**@file * @brief scam support * * Header file for asking oscam to begin geting cw's for channel */ int scam_send_capmt(mumudvb_channel_t *,scam_parameters_t *, int); #endif MuMuDVB-2.1.0/src/scam_common.c000066400000000000000000000220141305714132500161570ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * Header file for software descrambling common functions * * (C) 2004-2010 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Code inspired by vdr plugin dvbapi * Copyright (C) 2011,2012 Mariusz Białończyk * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "scam_common.h" #include "errors.h" #include "ts.h" #include "mumudvb.h" #include "log.h" #include "unicast_http.h" #include "rtp.h" #include "scam_decsa.h" #include "scam_send.h" /**@file * @brief scam support * * Code used by other software descrambling files */ static char *log_module="SCAM_COMMON: "; /* See http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2. */ int round_up(int x) { x--; x |= x >> 1; x |= x >> 2; x |= x >> 4; x |= x >> 8; x |= x >> 16; x++; return x; } /** @brief Read a line of the configuration file to check if there is a scam parameter * * @param scam_vars the scam parameters * @param substring The currrent line */ int read_scam_configuration(scam_parameters_t *scam_vars, mumudvb_channel_t *c_chan, char *substring) { char delimiteurs[] = CONFIG_FILE_SEPARATOR; if (!strcmp (substring, "scam_support")) { substring = strtok (NULL, delimiteurs); scam_vars->scam_support = atoi (substring); if(scam_vars->scam_support) { log_message( log_module, MSG_WARN, "You have enabled the support for software descrambling (scrambled channels). Please report any bug/comment\n"); } scam_vars->ring_buffer_default_size=RING_BUFFER_DEFAULT_SIZE; scam_vars->decsa_default_delay=DECSA_DEFAULT_DELAY; scam_vars->send_default_delay=SEND_DEFAULT_DELAY; } else if (!strcmp (substring, "ring_buffer_default_size")) { substring = strtok (NULL, delimiteurs); scam_vars->ring_buffer_default_size = round_up(atoi(substring)); log_message( log_module, MSG_DEBUG, "Ring buffer default size set to %llu",(long long unsigned int)scam_vars->ring_buffer_default_size); } else if (!strcmp (substring, "decsa_default_delay")) { substring = strtok (NULL, delimiteurs); scam_vars->decsa_default_delay = atoi (substring); if (scam_vars->decsa_default_delay > 10000000) scam_vars->decsa_default_delay = 10000000; } else if (!strcmp (substring, "send_default_delay")) { substring = strtok (NULL, delimiteurs); scam_vars->send_default_delay = atoi (substring); } else if (!strcmp (substring, "oscam")) { if ( c_chan == NULL ) { log_message( log_module, MSG_ERROR, "oscam : You have to start a channel first (using new_channel)\n"); return -1; } substring = strtok (NULL, delimiteurs); c_chan->scam_support = atoi (substring); if (c_chan->scam_support) { c_chan->need_scam_ask=CAM_NEED_ASK; c_chan->ring_buffer_size=scam_vars->ring_buffer_default_size; c_chan->decsa_delay=scam_vars->decsa_default_delay; c_chan->send_delay=scam_vars->send_default_delay; c_chan->scam_pmt_packet=malloc(sizeof(mumudvb_ts_packet_t)); if(c_chan->scam_pmt_packet==NULL) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); set_interrupted(ERROR_MEMORY<<8); return -1; } memset (c_chan->scam_pmt_packet, 0, sizeof( mumudvb_ts_packet_t));//we clear it pthread_mutex_init(&c_chan->scam_pmt_packet->packetmutex, NULL); } } else if (!strcmp (substring, "ring_buffer_size")) { if ( c_chan == NULL) { log_message( log_module, MSG_ERROR, "ring_buffer_size : You have to start a channel first (using new_channel)\n"); return -1; } substring = strtok (NULL, delimiteurs); c_chan->ring_buffer_size = round_up(atoi (substring)); } else if (!strcmp (substring, "decsa_delay")) { if ( c_chan == NULL) { log_message( log_module, MSG_ERROR, "decsa_delay : You have to start a channel first (using new_channel)\n"); return -1; } substring = strtok (NULL, delimiteurs); c_chan->decsa_delay = atoi (substring); if (c_chan->decsa_delay > 10000000) c_chan->decsa_delay = 10000000; } else if (!strcmp (substring, "send_delay")) { if ( c_chan == NULL) { log_message( log_module, MSG_ERROR, "send_delay : You have to start a channel first (using new_channel)\n"); return -1; } substring = strtok (NULL, delimiteurs); c_chan->send_delay = atoi (substring); } else return 0; //Nothing concerning scam, we return 0 to explore the other possibilities return 1;//We found something for scam, we tell main to go for the next line } /** @brief initialize the pmt get for scam descrambled channels * */ int scam_init_no_autoconf(scam_parameters_t *scam_vars, mumudvb_channel_t *channels,int number_of_channels) { int curr_channel; if (scam_vars->scam_support){ for (curr_channel = 0; curr_channel < number_of_channels; curr_channel++) { if (channels[curr_channel].scam_support==1 && channels[curr_channel].pid_i.num_pids>1) { if(!channels[curr_channel].pid_i.pmt_pid) { log_message( log_module, MSG_WARN, "channel %d with SCAM support and no PMT set I disable SCAM support for this channel",curr_channel); channels[curr_channel].scam_support=0; } } } } return 0; } /** @brief create ring buffer and threads for sending and descrambling * */ int scam_channel_start(mumudvb_channel_t *channel, unicast_parameters_t *unicast_vars) { channel->ring_buf=malloc(sizeof(ring_buffer_t)); if (channel->ring_buf == NULL) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); return ERROR_MEMORY<<8; } memset (channel->ring_buf, 0, sizeof( ring_buffer_t));//we clear it channel->ring_buf->data=malloc(channel->ring_buffer_size*TS_PACKET_SIZE); if (channel->ring_buf->data == NULL) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); return ERROR_MEMORY<<8; } channel->ring_buf->time_send=malloc(channel->ring_buffer_size * sizeof(uint64_t)); if (channel->ring_buf->time_send == NULL) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); return ERROR_MEMORY<<8; } channel->ring_buf->time_decsa=malloc(channel->ring_buffer_size * sizeof(uint64_t)); if (channel->ring_buf->time_decsa == NULL) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); return ERROR_MEMORY<<8; } memset (channel->ring_buf->time_send, 0, channel->ring_buffer_size * sizeof(uint64_t));//we clear it memset (channel->ring_buf->time_decsa, 0, channel->ring_buffer_size * sizeof(uint64_t));//we clear it pthread_mutex_init(&channel->ring_buf->lock, NULL); scam_send_start(channel, unicast_vars); scam_decsa_start(channel); return 0; } void scam_channel_stop(mumudvb_channel_t *channel) { scam_send_stop(channel); scam_decsa_stop(channel); free(channel->ring_buf->data); free(channel->ring_buf->time_send); free(channel->ring_buf->time_decsa); pthread_mutex_destroy(&channel->ring_buf->lock); free(channel->ring_buf); } /** @brief This function is called when a new PMT packet is there */ void scam_new_packet(int pid, mumudvb_channel_t *actual_channel) { if ((actual_channel->need_scam_ask==CAM_NEED_ASK) && (actual_channel->pid_i.pmt_pid == pid)) { if(actual_channel->pmt_packet->len_full > 0) { //We check the transport stream id of the packet if(check_pmt_service_id(actual_channel->pmt_packet, actual_channel)) { pthread_mutex_lock(&actual_channel->scam_pmt_packet->packetmutex); actual_channel->scam_pmt_packet->len_full = actual_channel->pmt_packet->len_full; memcpy(actual_channel->scam_pmt_packet->data_full, actual_channel->pmt_packet->data_full, actual_channel->pmt_packet->len_full); pthread_mutex_unlock(&actual_channel->scam_pmt_packet->packetmutex); } } } } MuMuDVB-2.1.0/src/scam_common.h000066400000000000000000000050611305714132500161670ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * Header file for software descrambling common functions * * (C) 2004-2010 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Code inspired by vdr plugin dvbapi * Copyright (C) 2011,2012 Mariusz Białończyk * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef _SCAM_COMMON_H #define _SCAM_COMMON_H #include #include #include #include #include #include #include #include #include #include #include "mumudvb.h" #include "log.h" #include "unicast_http.h" #include "rtp.h" #include "autoconf.h" /**@file * @brief scam support * * Header file for code used by other software descrambling files */ #define RING_BUFFER_DEFAULT_SIZE 32768 #define DECSA_DEFAULT_DELAY 500000 #define SEND_DEFAULT_DELAY 1500000 /** @brief the parameters for the scam * This structure contain the parameters needed for the SCAM */ typedef struct scam_parameters_t{ int scam_support; pthread_t getcwthread; int getcwthread_shutdown; ca_descr_t ca_descr; ca_pid_t ca_pid; uint64_t ring_buffer_default_size,decsa_default_delay,send_default_delay; int epfd; }scam_parameters_t; //The structure for argument passing to sendthread_func typedef struct scam_sendthread_p_t{ mumudvb_channel_t *channel; unicast_parameters_t *unicast_vars; }scam_sendthread_p_t; int scam_init_no_autoconf(scam_parameters_t *scam_vars, mumudvb_channel_t *channels, int number_of_channels); void scam_new_packet(int pid, mumudvb_channel_t *channels); int read_scam_configuration(scam_parameters_t *scam_vars, mumudvb_channel_t *c_chan, char *substring); int scam_channel_start(mumudvb_channel_t *channel, unicast_parameters_t *unicast_vars); void scam_channel_stop(mumudvb_channel_t *channel); #endif MuMuDVB-2.1.0/src/scam_decsa.c000066400000000000000000000222251305714132500157520ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * File for software descrambling libdvbcsa part * * (C) 2004-2010 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Code inspired by TSDECRYPT * Copyright (C) 2011,2012 Georgi Chorbadzhiyski * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include "errors.h" #include "ts.h" #include "mumudvb.h" #include "log.h" #include "scam_common.h" #include /**@file * @brief scam support * * Code concerning software descrambling */ static void *decsathread_func(void* arg); //The polling thread static char *log_module="SCAM_DECSA: "; /** @brief Getting ts payload starting point * * */ unsigned char ts_packet_get_payload_offset(unsigned char *ts_packet) { if (ts_packet[0] != 0x47) return 0; unsigned char adapt_field = (ts_packet[3] &~ 0xDF) >> 5; // 11x11111 unsigned char payload_field = (ts_packet[3] &~ 0xEF) >> 4; // 111x1111 if (!payload_field) // No payload return 0; if (adapt_field) { unsigned char adapt_len = ts_packet[4]; if (adapt_len > 182) //validity check return 0; return 4 + 1 + adapt_len; // ts header + adapt_field_len_byte + adapt_field_len } else { return 4; // No adaptation, data starts directly after TS header } } int scam_decsa_start(mumudvb_channel_t *channel) { pthread_attr_t attr; struct sched_param param; size_t stacksize; unsigned int batch_size = dvbcsa_bs_batch_size(); stacksize = sizeof(mumudvb_channel_t *)+3*sizeof(unsigned int)+2*batch_size*sizeof(struct dvbcsa_bs_batch_s)+4*sizeof(unsigned char)+2*sizeof(struct dvbcsa_bs_key_s *)+50000; pthread_attr_init(&attr); pthread_attr_setschedpolicy(&attr, SCHED_RR); param.sched_priority = sched_get_priority_max(SCHED_RR); pthread_attr_setschedparam(&attr, ¶m); pthread_attr_setstacksize (&attr, stacksize); pthread_create(&(channel->decsathread), &attr, decsathread_func, channel); log_message(log_module, MSG_DEBUG,"Decsa thread started, channel %s\n",channel->name); return 0; } void scam_decsa_stop(mumudvb_channel_t *channel) { log_message(log_module,MSG_DEBUG,"Decsa Thread closing, channel %s\n", channel->name); channel->decsathread_shutdown=1; pthread_join(channel->decsathread,NULL); log_message(log_module,MSG_DEBUG,"Decsa Thread closed, channel %s\n", channel->name); } static void *decsathread_func(void* arg) { unsigned char scrambling_control_packet=0; unsigned int ca_idx = 0; mumudvb_channel_t *channel; channel = ((mumudvb_channel_t *) arg); unsigned int batch_size = dvbcsa_bs_batch_size(); struct dvbcsa_bs_batch_s odd_batch[batch_size+1]; struct dvbcsa_bs_batch_s even_batch[batch_size+1]; unsigned char *odd_scnt_field[batch_size+1]; unsigned char *even_scnt_field[batch_size+1]; unsigned char odd_batch_idx=0; unsigned char even_batch_idx=0; unsigned char offset=0,len=0; unsigned int nscrambled=0, scrambled=0; unsigned int i; struct dvbcsa_bs_key_s *odd_key; struct dvbcsa_bs_key_s *even_key; odd_key=dvbcsa_bs_key_alloc(); even_key=dvbcsa_bs_key_alloc(); int first_run = 1; int got_first_even_key = 0, got_first_odd_key = 0; /* For simplicity, and to avoid taking the lock anew for every packet, * we only release the lock when sleeping or doing CPU-intensive work. */ pthread_mutex_lock(&channel->ring_buf->lock); while(!channel->decsathread_shutdown) { uint64_t now_time=get_time(); uint64_t decsa_time = channel->ring_buf->time_decsa[channel->ring_buf->read_decsa_idx]; if (channel->ring_buf->to_descramble == 0) { if (first_run) { first_run = 0; log_message( log_module, MSG_DEBUG, "first run waiting"); } else log_message( log_module, MSG_ERROR, "thread starved, channel %s %u %u\n",channel->name,channel->ring_buf->to_descramble,channel->ring_buf->to_send); pthread_mutex_unlock(&channel->ring_buf->lock); usleep(50000); pthread_mutex_lock(&channel->ring_buf->lock); continue; } if (now_time < decsa_time) { pthread_mutex_unlock(&channel->ring_buf->lock); usleep(decsa_time - now_time); pthread_mutex_lock(&channel->ring_buf->lock); } scrambling_control_packet = ((*(channel->ring_buf->data+TS_PACKET_SIZE*channel->ring_buf->read_decsa_idx+3) & 0xc0) >> 6); if (scrambling_control_packet) { offset = ts_packet_get_payload_offset(channel->ring_buf->data+TS_PACKET_SIZE*channel->ring_buf->read_decsa_idx); if (!offset) scrambling_control_packet = 0; len=188-offset; } switch (scrambling_control_packet) { case 2: ++scrambled; if (ca_idx && got_first_even_key) { even_batch[even_batch_idx].data = channel->ring_buf->data+TS_PACKET_SIZE*channel->ring_buf->read_decsa_idx + offset; even_batch[even_batch_idx].len = len; even_scnt_field[even_batch_idx] = channel->ring_buf->data+TS_PACKET_SIZE*channel->ring_buf->read_decsa_idx+3; ++even_batch_idx; } break; case 3: ++scrambled; if (ca_idx && got_first_odd_key) { odd_batch[odd_batch_idx].data = channel->ring_buf->data+TS_PACKET_SIZE*channel->ring_buf->read_decsa_idx + offset; odd_batch[odd_batch_idx].len = len; odd_scnt_field[odd_batch_idx] = channel->ring_buf->data+TS_PACKET_SIZE*channel->ring_buf->read_decsa_idx+3; ++odd_batch_idx; } break; default : ++nscrambled; break; } ++channel->ring_buf->read_decsa_idx; channel->ring_buf->read_decsa_idx&=(channel->ring_buffer_size -1); --channel->ring_buf->to_descramble; if ((scrambled==batch_size) || (nscrambled==batch_size)) { even_batch[even_batch_idx].data = NULL; odd_batch[odd_batch_idx].data = NULL; /* Load new keys if they are ready and we no longer use the old one. */ if ((odd_batch_idx != 0 && even_batch_idx == 0) || !got_first_even_key) { pthread_mutex_lock(&channel->cw_lock); if (channel->got_key_even) { dvbcsa_bs_key_set(channel->even_cw, even_key); log_message( log_module, MSG_DEBUG, "%016llx even key %02x %02x %02x %02x %02x %02x %02x %02x, channel %s\n", (long long unsigned int)now_time, channel->even_cw[0], channel->even_cw[1], channel->even_cw[2], channel->even_cw[3], channel->even_cw[4], channel->even_cw[5], channel->even_cw[6], channel->even_cw[7],channel->name); channel->got_key_even = 0; got_first_even_key = 1; } pthread_mutex_unlock(&channel->cw_lock); } if ((even_batch_idx != 0 && odd_batch_idx == 0) || !got_first_odd_key) { pthread_mutex_lock(&channel->cw_lock); if (channel->got_key_odd) { dvbcsa_bs_key_set(channel->odd_cw, odd_key); log_message( log_module, MSG_DEBUG, " %016llx odd key %02x %02x %02x %02x %02x %02x %02x %02x, channel %s\n",(long long unsigned int)now_time, channel->odd_cw[0], channel->odd_cw[1], channel->odd_cw[2], channel->odd_cw[3], channel->odd_cw[4], channel->odd_cw[5], channel->odd_cw[6], channel->odd_cw[7], channel->name); channel->got_key_odd = 0; got_first_odd_key = 1; } pthread_mutex_unlock(&channel->cw_lock); } pthread_mutex_unlock(&channel->ring_buf->lock); if (even_batch_idx) { dvbcsa_bs_decrypt(even_key, even_batch, 184); // We zero the scrambling control field to mark stream as unscrambled. for (i = 0; i < even_batch_idx; ++i) { *even_scnt_field[i] &= 0x3f; } } if (odd_batch_idx) { dvbcsa_bs_decrypt(odd_key, odd_batch, 184); // We zero the scrambling control field to mark stream as unscrambled. for (i = 0; i < odd_batch_idx; ++i) { *odd_scnt_field[i] &= 0x3f; } } even_batch_idx = 0; odd_batch_idx = 0; pthread_mutex_lock(&channel->ring_buf->lock); channel->ring_buf->to_send+= scrambled + nscrambled; nscrambled=0; scrambled=0; pthread_mutex_lock(&channel->cw_lock); ca_idx = channel->ca_idx; pthread_mutex_unlock(&channel->cw_lock); } } pthread_mutex_unlock(&channel->ring_buf->lock); if(odd_key) dvbcsa_bs_key_free(odd_key); if(even_key) dvbcsa_bs_key_free(even_key); return 0; } MuMuDVB-2.1.0/src/scam_decsa.h000066400000000000000000000027271305714132500157640ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * Header file for software descrambling libdvbcsa part * * (C) 2004-2010 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Code inspired by TSDECRYPT * Copyright (C) 2011,2012 Georgi Chorbadzhiyski * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef _SCAM_DECSA_H #define _SCAM_DECSA_H #include #include #include #include #include #include #include #include #include #include /**@file * @brief scam support * * Header file for code concerning software descrambling */ int scam_decsa_start(mumudvb_channel_t *); void scam_decsa_stop(mumudvb_channel_t *); #endifMuMuDVB-2.1.0/src/scam_getcw.c000066400000000000000000000205211305714132500160010ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * File for software descrambling connection with oscam * * (C) 2004-2010 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Code inspired by vdr plugin dvbapi * Copyright (C) 2011,2012 Mariusz Białończyk * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include #include "errors.h" #include "ts.h" #include "mumudvb.h" #include "log.h" #include "scam_common.h" #include #define DVBAPI_OPCODE_LEN 5 #define DVBAPI_CA_SET_DESCR_LEN 21 #define DVBAPI_CA_SET_PID_LEN 13 /**@file * @brief scam support * * Code for getting cw's from oscam */ static void *getcwthread_func(void* arg); //The polling thread static char *log_module="SCAM_GETCW: "; typedef struct getcw_params_t{ scam_parameters_t *scam_params; mumu_chan_p_t *chan_p; }getcw_params_t; /** @brief start the thread for getting cw's from oscam * This function will create the communication layers*/ int scam_getcw_start(scam_parameters_t *scam_params, mumu_chan_p_t *chan_p) { getcw_params_t *getcw_params=malloc(sizeof(getcw_params_t)); getcw_params->scam_params=scam_params; getcw_params->chan_p=chan_p; pthread_create(&(scam_params->getcwthread), NULL, getcwthread_func, getcw_params); log_message(log_module, MSG_DEBUG,"Getcw thread started\n"); return 0; } /** @brief stop the thread for getting cw's from oscam **/ void scam_getcw_stop(scam_parameters_t *scam_params) { log_message( log_module, MSG_DEBUG, "Getcw thread stopping\n"); // shutdown the getcw thread scam_params->getcwthread_shutdown = 1; pthread_cancel(scam_params->getcwthread); log_message( log_module, MSG_DEBUG, "Getcw thread stopped\n"); } /** @brief The thread function for getting cw's from oscam */ static void *getcwthread_func(void* arg) { struct getcw_params_t *getcw_params; getcw_params= (struct getcw_params_t *) arg; scam_parameters_t *scam_params; mumu_chan_p_t *chan_p; scam_params=getcw_params->scam_params; chan_p=getcw_params->chan_p; int curr_channel = 0; unsigned char buff[1 + sizeof(int) + sizeof(ca_descr_t)]; int cRead, *request; struct epoll_event events[MAX_CHANNELS]; int num_of_events; int i; //Loop while(!scam_params->getcwthread_shutdown) { num_of_events = epoll_wait (scam_params->epfd, events, MAX_CHANNELS, -1); if (num_of_events < 0) { set_interrupted(ERROR_NETWORK<<8); break; } pthread_mutex_lock(&chan_p->lock); for (i = 0; i < num_of_events; i++) { for (curr_channel = 0; curr_channel < chan_p->number_of_channels; curr_channel++) { mumudvb_channel_t *channel = &chan_p->channels[curr_channel]; if (events[i].data.fd == channel->camd_socket) { if (events[i].events & EPOLLERR || events[i].events & EPOLLHUP) { log_message(log_module, MSG_INFO,"channel %s socket not alive, will try to reconnect\n", channel->name); int s = epoll_ctl(scam_params->epfd, EPOLL_CTL_DEL, channel->camd_socket, &events[i]); if (s == -1) { log_message(log_module, MSG_ERROR,"channel %s: unsuccessful epoll_ctl EPOLL_CTL_DEL", channel->name); set_interrupted(ERROR_NETWORK<<8); free(getcw_params); pthread_mutex_unlock(&chan_p->lock); return 0; } close(channel->camd_socket); channel->camd_socket=-1; channel->need_scam_ask=CAM_NEED_ASK; pthread_mutex_lock(&channel->cw_lock); channel->ca_idx_refcnt = 0; channel->ca_idx = 0; pthread_mutex_unlock(&channel->cw_lock); } else { cRead = recv(channel->camd_socket, &buff, DVBAPI_OPCODE_LEN, 0); if (cRead <= 0) { log_message(log_module, MSG_ERROR,"channel: %s recv", channel->name); set_interrupted(ERROR_NETWORK<<8); free(getcw_params); pthread_mutex_unlock(&chan_p->lock); return 0; } request = (int *) (buff + 1); if (*request == CA_SET_DESCR) { //read upt to DVBAPI_CA_SET_DESCR_LEN cRead = recv(channel->camd_socket, (buff + DVBAPI_OPCODE_LEN), (DVBAPI_CA_SET_DESCR_LEN - DVBAPI_OPCODE_LEN), 0); if (cRead != (DVBAPI_CA_SET_DESCR_LEN - DVBAPI_OPCODE_LEN)) *request = 0; } else if (*request == CA_SET_PID) { //read upt to DVBAPI_CA_SET_PID_LEN cRead = recv(channel->camd_socket, (buff + DVBAPI_OPCODE_LEN), (DVBAPI_CA_SET_PID_LEN - DVBAPI_OPCODE_LEN), 0); if (cRead != (DVBAPI_CA_SET_PID_LEN - DVBAPI_OPCODE_LEN)) *request = 0; } if (*request == CA_SET_DESCR) { memcpy((&(scam_params->ca_descr)), buff + 1 + sizeof(int), sizeof(ca_descr_t)); log_message( log_module, MSG_DEBUG, "Got CA_SET_DESCR request for channel: %s, index: %d, parity %d, key %02x %02x %02x %02x %02x %02x %02x %02x\n", channel->name, scam_params->ca_descr.index, scam_params->ca_descr.parity, scam_params->ca_descr.cw[0], scam_params->ca_descr.cw[1], scam_params->ca_descr.cw[2], scam_params->ca_descr.cw[3], scam_params->ca_descr.cw[4], scam_params->ca_descr.cw[5], scam_params->ca_descr.cw[6], scam_params->ca_descr.cw[7]); if(scam_params->ca_descr.index != (unsigned) -1) { pthread_mutex_lock(&channel->cw_lock); if (scam_params->ca_descr.parity) { memcpy(channel->odd_cw,scam_params->ca_descr.cw,8); channel->got_key_odd=1; } else { memcpy(channel->even_cw,scam_params->ca_descr.cw,8); channel->got_key_even=1; } pthread_mutex_unlock(&channel->cw_lock); } else { log_message( log_module, MSG_DEBUG, "Got CA_SET_DESCR removal request, ignoring"); } } if (*request == CA_SET_PID) { memcpy((&(scam_params->ca_pid)), buff + 1 + sizeof(int), sizeof(ca_pid_t)); log_message( log_module, MSG_DEBUG, "Got CA_SET_PID request channel: %s, index: %d pid: %d\n", channel->name, scam_params->ca_pid.index, scam_params->ca_pid.pid); if(scam_params->ca_pid.index == -1) { pthread_mutex_lock(&channel->cw_lock); if (channel->ca_idx_refcnt) --channel->ca_idx_refcnt; if (!channel->ca_idx_refcnt) { channel->ca_idx = 0; log_message( log_module, MSG_INFO, "Got CA_SET_PID removal request: %d setting channel %s with ca_idx %d to 0\n", scam_params->ca_pid.pid, channel->name, scam_params->ca_pid.index+1); } pthread_mutex_unlock(&channel->cw_lock); } else { pthread_mutex_lock(&channel->cw_lock); if(!channel->ca_idx_refcnt) { channel->ca_idx = scam_params->ca_pid.index+1; log_message( log_module, MSG_INFO, "Got CA_SET_PID with pid: %d setting channel %s ca_idx %d\n", scam_params->ca_pid.pid, channel->name, scam_params->ca_pid.index+1); } ++channel->ca_idx_refcnt; pthread_mutex_unlock(&channel->cw_lock); } } } break; } } } pthread_mutex_unlock(&chan_p->lock); } free(getcw_params); return 0; } MuMuDVB-2.1.0/src/scam_getcw.h000066400000000000000000000030211305714132500160020ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * Header file for software descrambling connection with oscam * * (C) 2004-2010 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Code inspired by vdr plugin dvbapi * Copyright (C) 2011,2012 Mariusz Białończyk * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef _SCAM_GETCW_H #define _SCAM_GETCW_H #include #include #include #include #include #include #include #include #include #include #include "scam_common.h" #include "mumudvb.h" /**@file * @brief scam support * * Header for getting cw's from oscam */ int scam_getcw_start(scam_parameters_t *, mumu_chan_p_t *); void scam_getcw_stop(scam_parameters_t *); #endif MuMuDVB-2.1.0/src/scam_send.c000066400000000000000000000141551305714132500156270ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * File for software descrambling sending part * * (C) 2004-2010 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include "errors.h" #include "ts.h" #include "mumudvb.h" #include "log.h" #include "scam_common.h" /**@file * @brief scam support * * Code for sending thread */ static void *sendthread_func(void* arg); //The polling thread static char *log_module="SCAM_SEND: "; /** @brief Sending available data with given delay * * */ void *sendthread_func(void* arg) { int pid; /** pid of the current mpeg2 packet */ int ScramblingControl; int curr_pid = 0; int send_packet = 0; extern int dont_send_scrambled; scam_sendthread_p_t *params; params = ((scam_sendthread_p_t *) arg); mumudvb_channel_t *channel; channel = params->channel; unicast_parameters_t *unicast_vars; unicast_vars=params->unicast_vars; uint64_t res_time; struct timespec r_time; int first_run = 1; while(!channel->sendthread_shutdown) { int to_send; pthread_mutex_lock(&channel->ring_buf->lock); to_send = channel->ring_buf->to_send; pthread_mutex_unlock(&channel->ring_buf->lock); if (to_send) break; else usleep(50000); } while(!channel->sendthread_shutdown) { pthread_mutex_lock(&channel->ring_buf->lock); uint64_t now_time=get_time(); uint64_t send_time = channel->ring_buf->time_send[channel->ring_buf->read_send_idx]; int to_descramble = channel->ring_buf->to_descramble; int to_send = channel->ring_buf->to_send; pthread_mutex_unlock(&channel->ring_buf->lock); if (to_send == 0) { if (first_run) { first_run = 0; log_message( log_module, MSG_DEBUG, "first run waiting"); } else log_message( log_module, MSG_ERROR, "thread starved, channel %s %u %u\n",channel->name,to_descramble,to_send); usleep(50000); continue; } if (now_time < send_time) { res_time=send_time - now_time; r_time.tv_sec=res_time/(1000000ull); r_time.tv_nsec=1000*(res_time%(1000000ull)); while(nanosleep(&r_time, &r_time)); } pthread_mutex_lock(&channel->ring_buf->lock); pid = ((*(channel->ring_buf->data+TS_PACKET_SIZE*channel->ring_buf->read_send_idx+1) & 0x1f) << 8) | *(channel->ring_buf->data+TS_PACKET_SIZE*channel->ring_buf->read_send_idx+2); ScramblingControl = (*(channel->ring_buf->data+TS_PACKET_SIZE*channel->ring_buf->read_send_idx+3) & 0xc0) >> 6; pthread_mutex_lock(&channel->stats_lock); for (curr_pid = 0; (curr_pid < channel->pid_i.num_pids); curr_pid++) if ((channel->pid_i.pids[curr_pid] == pid) || (channel->pid_i.pids[curr_pid] == 8192)) //We can stream whole transponder using 8192 { if ((ScramblingControl>0) && (pid != channel->pid_i.pmt_pid) ) channel->num_scrambled_packets++; //check if the PID is scrambled for determining its state if (ScramblingControl>0) channel->pid_i.pids_num_scrambled_packets[curr_pid]++; //we don't count the PMT pid for up channels if (pid != channel->pid_i.pmt_pid) channel->num_packet++; break; } pthread_mutex_unlock(&channel->stats_lock); //avoid sending of scrambled channels if we asked to send_packet=1; if(dont_send_scrambled && (ScramblingControl>0)&& (channel->pid_i.pmt_pid) ) send_packet=0; if (send_packet) { // we fill the channel buffer memcpy(channel->buf + channel->nb_bytes, channel->ring_buf->data+TS_PACKET_SIZE*channel->ring_buf->read_send_idx, TS_PACKET_SIZE); channel->nb_bytes += TS_PACKET_SIZE; } ++channel->ring_buf->read_send_idx; channel->ring_buf->read_send_idx&=(channel->ring_buffer_size -1); --channel->ring_buf->to_send; pthread_mutex_unlock(&channel->ring_buf->lock); //The buffer is full, we send it if ((!channel->rtp && ((channel->nb_bytes + TS_PACKET_SIZE) > MAX_UDP_SIZE)) ||(channel->rtp && ((channel->nb_bytes + RTP_HEADER_LEN + TS_PACKET_SIZE) > MAX_UDP_SIZE))) { send_func(channel, send_time, unicast_vars); } } free(arg); return 0; } void scam_send_start(mumudvb_channel_t *channel, unicast_parameters_t *unicast_vars) { pthread_attr_t attr; struct sched_param param; size_t stacksize; stacksize = sizeof(mumudvb_channel_t)+sizeof(uint64_t)+sizeof(struct timespec)+50000; pthread_attr_init(&attr); pthread_attr_setschedpolicy(&attr, SCHED_RR); param.sched_priority = sched_get_priority_max(SCHED_RR); pthread_attr_setschedparam(&attr, ¶m); pthread_attr_setstacksize (&attr, stacksize); scam_sendthread_p_t *thread_params = malloc(sizeof(scam_sendthread_p_t)); thread_params->channel=channel; thread_params->unicast_vars=unicast_vars; pthread_create(&(channel->sendthread), &attr, sendthread_func, thread_params); log_message(log_module, MSG_DEBUG,"Send thread started, channel %s\n",channel->name); pthread_attr_destroy(&attr); } void scam_send_stop(mumudvb_channel_t *channel) { log_message(log_module,MSG_DEBUG,"Send Thread closing, channel %s\n", channel->name); channel->sendthread_shutdown=1; pthread_join(channel->sendthread,NULL); log_message(log_module,MSG_DEBUG,"Send Thread closed, channel %s\n", channel->name); } MuMuDVB-2.1.0/src/scam_send.h000066400000000000000000000027351305714132500156350ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * Header file for software descrambling sending part * * (C) 2004-2010 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef _SCAM_SEND_H #define _SCAM_SEND_H #include #include #include #include #include #include #include #include #include #include #include "unicast_http.h" /**@file * @brief scam support * * Header file for code concerning software descrambling */ void scam_send_start(mumudvb_channel_t *channel, unicast_parameters_t *unicast_vars); void scam_send_stop(mumudvb_channel_t *channel); void *sendthread_func(void* arg); #endif MuMuDVB-2.1.0/src/ts.c000066400000000000000000001166731305714132500143310ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * * (C) 2004-2011 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /**@file * @brief File for demuxing TS stream */ #include #include "ts.h" #include "mumudvb.h" #include "log.h" #include extern uint32_t crc32_table[256]; static char *log_module="TS: "; //Helper functions for get_ts_packet void ts_move_part_to_full(mumudvb_ts_packet_t *ts_packet); int ts_check_crc32(mumudvb_ts_packet_t *ts_packet); int ts_partial_full(mumudvb_ts_packet_t *ts_packet); #define NO_START 0 #define START_TS 1 #define START_SECTION 2 void add_ts_packet_data(unsigned char *buf, mumudvb_ts_packet_t *pkt, int data_left, int start_flag, int pid, int cc); /** @brief This function will join the 188 bytes packet until the PMT/PAT/SDT/EIT/... is full * Once it's full we check the CRC32 and say if it's ok or not * There is two important mpeg2-ts fields to do that * * the continuity counter which is incremented for each packet * * The payload_unit_start_indicator which says if it's the first packet * * When a packet is splitted in 188 bytes packets, there must be no other PID between two sub packets * * Return 1 when there is one packet full and OK * * @param buf : the received buffer from the card * @param ts_packet : the packet to be completed */ int get_ts_packet(unsigned char *buf, mumudvb_ts_packet_t *pkt) { int packet_avail=0; //see doc/diagrams/TS_packet_getting_all_cases.pdf for documentation pthread_mutex_lock(&pkt->packetmutex); //We check if there is already a full packet, in this case we remove one //and give it to the client if(pkt->full_number > 0) { log_message( log_module, MSG_FLOOD, "Full packet left: %d, we copy length %d\n", pkt->full_number, pkt->full_lengths[0]); //we copy the length pkt->len_full= pkt->full_lengths[0]; //we copy the data memcpy(pkt->data_full,pkt->buffer_full,pkt->len_full); pkt->full_number--; //We update the size of the buffer pkt->full_buffer_len-=pkt->len_full; //if there is one packet left, shift the packets left if(pkt->full_number > 0) { log_message( log_module, MSG_FLOOD, "Removed size %d, next size: %d\n",pkt->len_full, pkt->full_lengths[1]); //We move the data inside the buffer full memmove(pkt->buffer_full,pkt->buffer_full+pkt->len_full,pkt->full_buffer_len); //we update the lengths of the full packets memmove(pkt->full_lengths,pkt->full_lengths+1,(MAX_FULL_PACKETS-1)*sizeof(int)); } packet_avail=1; } //This function can be called with a NULL buffer in order to POP the packets from the stack if(buf==NULL) { pthread_mutex_unlock(&pkt->packetmutex); return packet_avail; } ts_header_t *header; //mapping of the buffer onto the TS header header=(ts_header_t *)buf; int buf_pid; buf_pid=HILO(header->pid); //the current packet position int offset; //delta used to remove TS HEADER offset = TS_HEADER_LEN-1; log_message(log_module, MSG_FLOOD, "General information PID %d adaptation_field_control %d payload_unit_start_indicator %d continuity_counter %d\n", buf_pid, header->adaptation_field_control, header->payload_unit_start_indicator, header->continuity_counter); //we skip the adaptation field //Sometimes there is some more data in the header, the adaptation field say it if (header->adaptation_field_control & 0x2) { log_message( log_module, MSG_DEBUG, "Read TS : Adaptation field \n"); offset += buf[offset] ; // add adapt.field.len //we check if the adapt.field.len is valid if(offset>=TS_PACKET_SIZE) { log_message( log_module, MSG_DEBUG, "Invalid adapt.field.len \n"); pthread_mutex_unlock(&pkt->packetmutex); return (pkt->full_number > 0); } } else if (header->adaptation_field_control & 0x1) { if (buf[offset]==0x00 && buf[offset+1]==0x00 && buf[offset+2]==0x01) { // -- PES/PS //tspid->id = buf[j+3]; log_message( log_module, MSG_FLOOD, "#PES/PS ----- We ignore \n"); pthread_mutex_unlock(&pkt->packetmutex); return (pkt->full_number > 0); } } if (header->adaptation_field_control == 3) { log_message( log_module, MSG_DEBUG, "adaptation_field_control 3\n"); pthread_mutex_unlock(&pkt->packetmutex); return (pkt->full_number > 0); } //We are now at the beginning of the Transport stream packet, we check if there is a pointer field //the pointer fields tells if there is the end of the previous packet before the beginning of a new one //and how long is this data if(header->payload_unit_start_indicator) //There is AT LEAST one packet beginning here { //Pointer field //This is an 8-bit field whose value shall be the number of bytes, immediately following the pointer_field //until the first byte of the first section that is present in the payload of the Transport Stream packet (so a value of 0x00 in //the pointer_field indicates that the section starts immediately after the pointer_field). When at least one section begins in //a given Transport Stream packet, then the payload_unit_start_indicator (refer to 2.4.3.2) shall be set to 1 and the first //byte of the payload of that Transport Stream packet shall contain the pointer. When no section begins in a given //Transport Stream packet, then the payload_unit_start_indicator shall be set to 0 and no pointer shall be sent in the //payload of that packet. int pointer_field=*(buf+offset); offset++; //we've read the pointer field if(pointer_field!=0) { log_message(log_module, MSG_FLOOD, "Pointer field 0x%02x %02d \n",pointer_field,pointer_field); if((TS_PACKET_SIZE-offset-pointer_field)<0) { log_message(log_module, MSG_DETAIL, "Pointer field too big 0x%02x, packet dropped\n",pointer_field); pkt->status_partial=EMPTY; pthread_mutex_unlock(&pkt->packetmutex); return (pkt->full_number > 0); } //We append the data of the ending packet add_ts_packet_data(buf+offset, pkt, pointer_field, NO_START, buf_pid, header->continuity_counter); } //we skip the pointer field_data offset+=pointer_field; //We add the data of the new packet add_ts_packet_data(buf+offset, pkt,TS_PACKET_SIZE-offset , START_TS, buf_pid, header->continuity_counter); } else //It's a continuing packet { //We append the data of the ending packet add_ts_packet_data(buf+offset, pkt,TS_PACKET_SIZE-offset , NO_START, buf_pid ,header->continuity_counter); } pthread_mutex_unlock(&pkt->packetmutex); return packet_avail; } /** @brief This function will log the start of a partial section * This assumes that at least the table header (8 bytes) is present */ void log_ts_packet_start(mumudvb_ts_packet_t *pkt) { tbl_h_t *tbl_struct=(tbl_h_t *)pkt->data_partial; log_message(log_module, MSG_FLOOD, "First bytes\t 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", pkt->data_partial[0], pkt->data_partial[1], pkt->data_partial[2], pkt->data_partial[3], pkt->data_partial[4], pkt->data_partial[5], pkt->data_partial[6], pkt->data_partial[7]); log_message(log_module, MSG_FLOOD, "Struct data\t table_id 0x%02x section_syntax_indicator 0x%02x section_length 0x%02x transport_stream_id 0x%02x version_number 0x%02x current_next_indicator 0x%02x last_section_number 0x%02x\n", tbl_struct->table_id, tbl_struct->section_syntax_indicator, HILO(tbl_struct->section_length), HILO(tbl_struct->transport_stream_id), tbl_struct->version_number, tbl_struct->current_next_indicator, tbl_struct->last_section_number); } /** @brief This function will add data to the current partial section * see doc/diagrams/TS_add_data_all_cases.pdf for documentation */ void add_ts_packet_data(unsigned char *buf, mumudvb_ts_packet_t *pkt, int data_left, int start_flag, int pid, int cc) { int copy_len; //We see if there is the start of a new section if(start_flag == START_TS || start_flag == START_SECTION) { //if the start was detected by the end of a section we check for stuffing bytes if(start_flag== START_SECTION) { /* Within a Transport Stream, packet stuffing bytes of value 0xFF may be found in the payload of Transport Stream packets carrying PSI and/or private_sections only after the last byte of a section. In this case all bytes until the end of the Transport Stream packet shall also be stuffing bytes of value 0xFF. These bytes may be discarded by a decoder. In such a case, the payload of the next Transport Stream packet with the same PID value shall begin with a pointer_field of value 0x00 indicating that the next section starts immediately thereafter. */ if(buf[0]==0xff) { log_message(log_module, MSG_FLOOD, "Stuffing bytes found data left %d\n",data_left); return; } } //We check if a packet has been started before, just for information if(pkt->status_partial!=EMPTY) log_message(log_module, MSG_FLOOD, "Unfinished packet and beginning of a new one, we drop the started one len: %d\n", pkt->len_partial); //We copy the data to the partial packet pkt->cc=cc; pkt->pid=pid; if(data_left<3) { pkt->status_partial=PARTIAL_HEADER; memcpy(pkt->data_partial,buf,data_left); pkt->len_partial=data_left; pkt->expected_len_partial=0; log_message(log_module, MSG_FLOOD, "Starting a packet with partial length header, PID %d cc %d len %d\n", pkt->pid, pkt->cc, pkt->len_partial); data_left=0; copy_len=0; } else { pkt->status_partial=STARTED; tbl_h_t *tbl_struct=(tbl_h_t *)buf; pkt->expected_len_partial=HILO(tbl_struct->section_length)+BYTES_BFR_SEC_LEN; //we copy the amount of data needed if(pkt->expected_len_partialexpected_len_partial; else copy_len=data_left; pkt->len_partial=copy_len; //The real copy memcpy(pkt->data_partial,buf,pkt->len_partial); //we update the amount of data left data_left-=copy_len; //lot of debugging information log_message(log_module, MSG_FLOOD, "Starting a packet PID %d cc %d len %d expected len %d\n", pkt->pid, pkt->cc, pkt->len_partial, pkt->expected_len_partial); if(pkt->len_partial>=8) log_ts_packet_start(pkt); } } else { log_message(log_module, MSG_FLOOD, "Continuing packet, data left %d\n",data_left); if(pkt->status_partial!=STARTED && pkt->status_partial!=PARTIAL_HEADER) { log_message(log_module, MSG_FLOOD, "Continuing packet and saved packet not started or full, can be a continuity error\n"); pkt->status_partial=EMPTY; return; } else if(pkt->cc==cc) { log_message(log_module, MSG_FLOOD, "Duplicate packet, continuity counter: %d\n", pkt->cc); return; } else if(((pkt->cc+1)%16)!=cc) { log_message(log_module, MSG_FLOOD, "The continuity counter is not valid saved packet cc %d actual cc %d\n", pkt->cc, cc); pkt->status_partial=EMPTY; return; } else if(pkt->pid!=pid) { log_message(log_module, MSG_FLOOD, "PID change. saved PID %d, actual pid %d\n", pkt->pid, pid); pkt->status_partial=EMPTY; return; } else { if(pkt->status_partial==PARTIAL_HEADER) { if(pkt->len_partial>=3) { log_message(log_module, MSG_FLOOD, "Partial length field %d is not valid in PARTIAL_HEADER state, PID %d\n", pkt->len_partial, pkt->pid); pkt->status_partial=EMPTY; return; } else if(3-pkt->len_partial>data_left) { log_message(log_module, MSG_FLOOD, "Packet length header could not be accumulated after two TS packets, PID %d\n", pkt->pid); pkt->status_partial=EMPTY; return; } //read up to the first 3 bytes, to get the packet length memcpy(pkt->data_partial+pkt->len_partial,buf,3-pkt->len_partial); tbl_h_t *tbl_struct=(tbl_h_t *)pkt->data_partial; pkt->expected_len_partial=HILO(tbl_struct->section_length)+BYTES_BFR_SEC_LEN; pkt->status_partial=STARTED; } //packet started and continuing packet, we append the data //we copy the minimum amount of data if((pkt->len_partial+data_left)> pkt->expected_len_partial) copy_len=pkt->expected_len_partial - pkt->len_partial; else copy_len=data_left; //if too big we skip if(pkt->len_partial+copy_len > MAX_TS_SIZE) { log_message(log_module, MSG_FLOOD, "The packet seems too big pkt->len_partial %d copy_len %d pkt->len_partial+copy_len %d\n", pkt->len_partial, copy_len, pkt->len_partial+copy_len); copy_len=MAX_TS_SIZE-pkt->len_partial; } //We don't have any starting packet we make sure we don't believe there is data_left=0; memcpy(pkt->data_partial+pkt->len_partial,buf,copy_len);//we add the packet to the buffer int prev_len_partial=pkt->len_partial; pkt->len_partial+=copy_len; pkt->cc=cc; //update cc //Log packet start if it has just become at least 8 bytes if(prev_len_partial<8 && pkt->len_partial>=8) log_ts_packet_start(pkt); log_message(log_module, MSG_FLOOD, "Continuing a packet PID %d cc %d len %d expected %d\n",pkt->pid,pkt->cc,pkt->len_partial,pkt->expected_len_partial); } } if(pkt->status_partial!=PARTIAL_HEADER) { //We check if the packet is full if(ts_partial_full(pkt)) { //The partial packet is full, we check the CRC32 if(ts_check_crc32(pkt)) ts_move_part_to_full(pkt); //Everything is perfect, the packet full is ok } //If there is still data, a new section could begin, we call recursively if(data_left) { log_message(log_module, MSG_FLOOD, "Calling recursively, data left %d\n",data_left); add_ts_packet_data(buf+copy_len, pkt, data_left,START_SECTION, pid,cc); } } } /** @brief move the partial packet to the full packet */ void ts_move_part_to_full(mumudvb_ts_packet_t *pkt) { //append the data if(pkt->full_number>=MAX_FULL_PACKETS) { log_message(log_module, MSG_WARN, "Too many full packets, we skip one size %d",pkt->len_partial); return; } if((pkt->full_buffer_len+pkt->len_partial)>=FULL_BUFFER_SIZE) { log_message(log_module, MSG_WARN, "Too much data, in full packets (%d), we skip one size %d",pkt->full_buffer_len,pkt->len_partial); return; } memcpy(pkt->buffer_full+pkt->full_buffer_len,pkt->data_partial,pkt->len_partial); pkt->full_buffer_len+=pkt->len_partial; pkt->full_lengths[pkt->full_number]=pkt->len_partial; pkt->full_number++; log_message(log_module, MSG_FLOOD, "New full packet len %d. There's now %d full packet%c\n",pkt->len_partial,pkt->full_number,pkt->full_number>1?'s':' '); //we don't copy it to the full, it will be popped at the next call of get_ts_packet //This delays of one TS packet the moment this one will be available to the client but //makes the code simpler pkt->len_partial=0; pkt->status_partial=EMPTY; } /**@brief Checking of the CRC32 of a raw buffer * return 1 if crc32 is ok, 0 otherwise * @param packet : the packet to be checked */ int ts_check_raw_crc32(unsigned char *data) { int i,len; uint32_t crc32; tbl_h_t *tbl_struct; tbl_struct=(tbl_h_t *)data; //the real length (it cannot overflow due to the way tbl_h_t is made) len=HILO(tbl_struct->section_length)+BYTES_BFR_SEC_LEN; //CRC32 calculation //Test of the crc32 crc32=0xffffffff; //we compute the CRC32 //we have two ways: either we compute until the end and it should be 0 //either we exclude the 4 last bits and in should be equal to the 4 last bits for(i = 0; i < len; i++) { crc32 = (crc32 << 8) ^ crc32_table[((crc32 >> 24) ^ data[i])&0xff]; } return (crc32 == 0); } /**@brief Checking of the CRC32 * return 1 if crc32 is ok, 0 otherwise * @param packet : the packet to be checked */ int ts_check_crc32( mumudvb_ts_packet_t *packet) { if(ts_check_raw_crc32(packet->data_partial)==0) { log_message( log_module, MSG_DETAIL,"\tpacket BAD CRC32 PID : %d\n", packet->pid); //Bad CRC32 packet->status_partial=EMPTY; packet->len_partial=0; return 0; } packet->status_partial=VALID; return 1; } /**@brief Tell if the partial packet is full * return 1 if full, 0 otherwise * @param packet : the packet to be checked */ int ts_partial_full( mumudvb_ts_packet_t *packet) { //the real length if(packet->len_partial>=packet->expected_len_partial) { //we set the good length packet->len_partial=packet->expected_len_partial; return 1; } return 0; } /** @brief This function will return a pointer to the beginning of the first payload of a TS packet and NULL if no payload or error * It returns NULL in case of error * * @param buf : the received buffer from the card */ unsigned char *get_ts_begin(unsigned char *buf) { ts_header_t *header; int delta; //mapping of the buffer onto the TS header header=(ts_header_t *)buf; //delta used to remove TS HEADER delta = TS_HEADER_LEN-1; //Sometimes there is some more data in the header, the adaptation field say it if (header->adaptation_field_control & 0x2) { log_message( log_module, MSG_DEBUG, "Read TS : Adaptation field, len %d \n",buf[delta]); if((TS_PACKET_SIZE-delta-buf[delta])<0) { log_message(log_module, MSG_DETAIL, "Adaptation field too big 0x%02x, packet dropped\n",buf[delta]); return NULL; } delta += buf[delta]; // add adapt.field.len } if (header->adaptation_field_control & 0x1) //There is a payload { if (buf[delta]==0x00 && buf[delta+1]==0x00 && buf[delta+2]==0x01) { // -- PES/PS //tspid->id = buf[j+3]; log_message( log_module, MSG_FLOOD, "#PES/PS ----- We ignore \n"); return NULL; } } if (header->adaptation_field_control == 3) log_message( log_module, MSG_DEBUG, "adaptation_field_control 3\n"); if ((header->adaptation_field_control == 2)||(header->adaptation_field_control == 0)) { log_message( log_module, MSG_DEBUG, "adaptation_field_control %d ie no payload\n", header->adaptation_field_control); return NULL; } if(header->payload_unit_start_indicator) //It's the beginning of a new packet { int pointer_field=*(buf+delta); delta++; if(pointer_field!=0) log_message(log_module, MSG_FLOOD, "Pointer field 0x%02x\n",pointer_field); if((TS_PACKET_SIZE-delta-pointer_field)<0) { log_message(log_module, MSG_DETAIL, "Pointer field too big 0x%02x, packet dropped\n",pointer_field); return NULL; } return buf+delta+pointer_field; //we give the address of the beginning of the payload /* * This is an 8-bit field whose value shall be the number of bytes, immediately following the pointer_field * until the first byte of the first section that is present in the payload of the Transport Stream packet (so a value of 0x00 in * the pointer_field indicates that the section starts immediately after the pointer_field). When at least one section begins in * a given Transport Stream packet, then the payload_unit_start_indicator (refer to 2.4.3.2) shall be set to 1 and the first * byte of the payload of that Transport Stream packet shall contain the pointer. When no section begins in a given * Transport Stream packet, then the payload_unit_start_indicator shall be set to 0 and no pointer shall be sent in the * payload of that packet. */ } return NULL; } /** @brief compare the SERVICE_ID contained in the channel and in the PMT * * Return 1 if match or no service_id info, 0 otherwise * * @param pmt the pmt packet * @param channel the channel to be checked */ int check_pmt_service_id(mumudvb_ts_packet_t *pmt, mumudvb_channel_t *channel) { pmt_t *header; header=(pmt_t *)pmt->data_full; if(header->table_id!=0x02) { log_message( log_module, MSG_INFO,"Packet PID %d for channel \"%s\" is not a PMT PID.\n", pmt->pid, channel->name); return 0; } /*current_next_indicator – A 1-bit indicator, which when set to '1' indicates that the Program Association Table sent is currently applicable. When the bit is set to '0', it indicates that the table sent is not yet applicable and shall be the next table to become valid.*/ if(header->current_next_indicator == 0) { log_message( log_module, MSG_DEBUG,"The current_next_indicator is set to 0, this PMT is not valid for the current stream\n"); return 0; } //We check if this PMT belongs to the current channel. (Only works with autoconfiguration full for the moment because it stores the service_id) if(channel->service_id && (channel->service_id != HILO(header->program_number)) ) { log_message( log_module, MSG_DETAIL,"The PMT %d not belongs to channel \"%s\"\n", pmt->pid, channel->name); log_message( log_module, MSG_DETAIL,"Debug channel->service_id %d pmt service_id %d\n", channel->service_id, HILO(header->program_number)); return 0; } else if(channel->service_id) log_message( log_module, MSG_DETAIL,"GOOD service_id for PMT %d and channel \"%s\"\n", pmt->pid, channel->name); if(!channel->service_id) log_message( log_module, MSG_DEBUG,"no service_id information for channel \"%s\"\n", channel->name); return 1; } /** @brief Display the PAT contents * * @param buf The buffer containing the PAT */ void ts_display_pat(char* log_module,unsigned char *buf) { pat_t *pat=(pat_t*)(buf); pat_prog_t *prog; int delta=PAT_LEN; int section_length=0; int number_of_services=0; log_message( log_module, MSG_FLOOD,"-------------- Display PAT ----------------\n"); section_length=HILO(pat->section_length); log_message( log_module, MSG_FLOOD, "transport stream id 0x%04x section_length %d version %i section_number %d last_section_number %d current_next_indicator %d\n", HILO(pat->transport_stream_id), HILO(pat->section_length), pat->version_number, pat->section_number, pat->last_section_number, pat->current_next_indicator); /*current_next_indicator – A 1-bit indicator, which when set to '1' indicates that the Program Association Table sent is currently applicable. When the bit is set to '0', it indicates that the table sent is not yet applicable and shall be the next table to become valid.*/ if(pat->current_next_indicator == 0) log_message( log_module, MSG_FLOOD,"The current_next_indicator is set to 0, this PAT is not valid for the current stream\n"); //We loop over the different programs included in the pat while((delta+PAT_PROG_LEN)<(section_length)) { prog=(pat_prog_t*)((char*)buf+delta); if(HILO(prog->program_number)==0) { log_message( log_module, MSG_DEBUG,"Network PID %d (PID of the NIT)\n", HILO(prog->network_pid)); } else { number_of_services++; log_message( log_module, MSG_DEBUG,"service %d id 0x%04x %d\t PMT PID : %d", number_of_services, HILO(prog->program_number), HILO(prog->program_number), HILO(prog->network_pid)); } delta+=PAT_PROG_LEN; } log_message( log_module, MSG_DEBUG,"This PAT contains %d services\n",number_of_services); log_message( log_module, MSG_FLOOD,"-------------- PAT Displayed ----------------\n"); } typedef struct { u_char descriptor_tag :8; u_char descriptor_length :8; #if BYTE_ORDER == BIG_ENDIAN u_char country_availability_flag :1; u_char :7; #else u_char :7; u_char country_availability_flag :1; #endif } country_avaibility_descr_t; /** @brief : show the contents of the country avaibility descriptor * * @param buf : the buffer containing the descriptor */ void ts_display_country_avaibility_descriptor(char* log_module,unsigned char *buf) { int length,i; country_avaibility_descr_t *descr; log_message( log_module, MSG_DETAIL, "--- descriptor --- country avaibility descriptor\n"); descr=(country_avaibility_descr_t *)buf; length=descr->descriptor_length-1; if(descr->country_availability_flag) log_message( log_module, MSG_DETAIL, "The reception is intended for the following countries : \n"); else log_message( log_module, MSG_DETAIL, "The reception is NOT intended for the following countries : \n"); for(i=0;i 0) { unsigned char descriptor_tag = buf[0]; unsigned char descriptor_len = buf[1] + 2; if (!descriptor_len) { log_message( log_module, MSG_FLOOD, " --- NIT descriptor --- descriptor_tag == 0x%02x, len is 0\n", descriptor_tag); break; } //The service descriptor provides the names of the service provider and the service in text form together with the service_type. if(descriptor_tag==0x40) ts_display_network_name_descriptor(log_module,buf); else if(descriptor_tag==0x5B) ts_display_multilingual_network_name_descriptor(log_module,buf); else log_message( log_module, MSG_FLOOD, "NIT network descriptor_tag : 0x%2x\n", descriptor_tag); buf += descriptor_len; descriptors_loop_len -= descriptor_len; } } /** @brief Parse the network name descriptor * It's used to get the network name * @param buf the buffer containing the descriptor */ void ts_display_network_name_descriptor(char* log_module,unsigned char *buf) { /* Service descriptor : descriptor_tag 8 descriptor_length 8 for (i=0;i 0) { language_code[0]=*buf;buf++; language_code[1]=*buf;buf++; language_code[2]=*buf;buf++; language_code[3]='\0'; name_len=*buf;buf++; log_message( log_module, MSG_FLOOD, "NIT network descriptor_len %d, name_len %d\n",descriptor_len , name_len); dest=malloc(sizeof(char)*(name_len+1)); memcpy (dest, buf, name_len); dest[name_len] = '\0'; buf += name_len; convert_en300468_string(dest,name_len,0); log_message( log_module, MSG_DEBUG, "lang code %s network name : \"%s\"\n",language_code, dest); descriptor_len -= (name_len+4); free(dest); } } /** */ void ts_display_service_list_descriptor(char* log_module,unsigned char *buf) { /* Service list descriptor : descriptor_tag 8 descriptor_length 8 for (i=0;ifrequency_4, descr->frequency_3, descr->frequency_2, descr->frequency_1); log_message( log_module, MSG_FLOOD, "Orbital position: %d%01d,%01d°", descr->orbital_position_hi,(descr->orbital_position_lo>>4)&0x0f, descr->orbital_position_lo&0x0f); if(descr->west_east_flag) log_message( log_module, MSG_FLOOD, "Estern position"); else log_message( log_module, MSG_FLOOD, "Western position"); switch(descr->polarization) { log_message( log_module, MSG_FLOOD, "Polarization: (0x%02x)", descr->polarization); case 0: log_message( log_module, MSG_FLOOD, "Polarization: linear - horizontal"); break; case 1: log_message( log_module, MSG_FLOOD, "Polarization: linear - vertical"); break; case 2: log_message( log_module, MSG_FLOOD, "Polarization: circular - left"); break; case 3: log_message( log_module, MSG_FLOOD, "Polarization: circular - right"); break; default: log_message( log_module, MSG_FLOOD, "Polarization: BUG"); break; } if(descr->modulation_system) log_message( log_module, MSG_FLOOD, "Modulation system: DVB-S2"); else log_message( log_module, MSG_FLOOD, "Modulation system: DVB-S"); if(descr->modulation_system) { switch(descr->roll_off) { case 0: log_message( log_module, MSG_FLOOD, "Roll-off factor: α = 0,35"); break; case 1: log_message( log_module, MSG_FLOOD, "Roll-off factor: α = 0,25"); break; case 2: log_message( log_module, MSG_FLOOD, "Roll-off factor: α = 0,20"); break; case 3: log_message( log_module, MSG_FLOOD, "Roll-off factor: reserved"); break; default: log_message( log_module, MSG_FLOOD, "Roll-off factor: BUG"); break; } } switch(descr->modulation_type) { case 0: log_message( log_module, MSG_FLOOD, "Constellation: Auto"); break; case 1: log_message( log_module, MSG_FLOOD, "Constellation: QPSK"); break; case 2: log_message( log_module, MSG_FLOOD, "Constellation: 8PSK"); break; case 3: log_message( log_module, MSG_FLOOD, "Constellation: 16-QAM"); break; default: log_message( log_module, MSG_FLOOD, "Constellation: BUG"); break; } log_message( log_module, MSG_FLOOD, "Symbol rate: %d%d%d,%d%d%d%d Msymbol/s", BCDHI(descr->symbol_rate_12), BCDLO(descr->symbol_rate_12), BCDHI(descr->symbol_rate_34), BCDLO(descr->symbol_rate_34), BCDHI(descr->symbol_rate_56), BCDLO(descr->symbol_rate_56), BCDLO(descr->symbol_rate_7) ); switch(descr->FEC_inner) { case 0: log_message( log_module, MSG_FLOOD, "Inner FEC scheme: not defined"); break; case 1: log_message( log_module, MSG_FLOOD, "Inner FEC scheme: 1/2"); break; case 2: log_message( log_module, MSG_FLOOD, "Inner FEC scheme: 2/3"); break; case 3: log_message( log_module, MSG_FLOOD, "Inner FEC scheme: 3/4"); break; case 4: log_message( log_module, MSG_FLOOD, "Inner FEC scheme: 5/6"); break; case 5: log_message( log_module, MSG_FLOOD, "Inner FEC scheme: 7/8"); break; case 6: log_message( log_module, MSG_FLOOD, "Inner FEC scheme: 8/9"); break; case 7: log_message( log_module, MSG_FLOOD, "Inner FEC scheme: 3/5"); break; case 8: log_message( log_module, MSG_FLOOD, "Inner FEC scheme: 4/5"); break; case 9: log_message( log_module, MSG_FLOOD, "Inner FEC scheme: 9/10"); break; case 10: log_message( log_module, MSG_FLOOD, "Inner FEC scheme: Reserved for future use"); break; case 11: log_message( log_module, MSG_FLOOD, "Inner FEC scheme: Reserved for future use"); break; case 12: log_message( log_module, MSG_FLOOD, "Inner FEC scheme: no convolutional coding"); break; default: log_message( log_module, MSG_FLOOD, "Inner FEC scheme: BUG please contact"); break; } log_message( log_module, MSG_FLOOD, "--- descriptor done ---\n"); } /** @brief display the contents of terrestrial_delivery_system_descriptor * EN 300 468 V1.10.1 6.2.13.4 Terrestrial delivery system descriptor */ void ts_display_terrestrial_delivery_system_descriptor(char *log_module, unsigned char *buf) { descr_terr_delivery_t *descr; descr=(descr_terr_delivery_t *)buf; log_message( log_module, MSG_FLOOD, "--- NIT descriptor --- terrestrial delivery system descriptor\n"); log_message( log_module, MSG_FLOOD, "Frequency: %d Hz", ((descr->frequency_4<<24)+(descr->frequency_3<<16)+(descr->frequency_2<<8)+descr->frequency_1) *10 ); if(descr->bandwidth<=3) log_message( log_module, MSG_FLOOD, "Bandwidth: %d MHz",8-descr->bandwidth); else log_message( log_module, MSG_FLOOD, "Bandwidth: Reserved for future use"); if(descr->priority) log_message( log_module, MSG_FLOOD, "Priority: HP (high priority)"); else log_message( log_module, MSG_FLOOD, "Priority: LP (low priority)"); log_message( log_module, MSG_FLOOD, "Time_Slicing_indicator: %d",descr->Time_Slicing_indicator); log_message( log_module, MSG_FLOOD, "MPE_FEC_indicator: %d",descr->MPE_FEC_indicator ); switch(descr->constellation) { case 0: log_message( log_module, MSG_FLOOD, "Constellation: QPSK"); break; case 1: log_message( log_module, MSG_FLOOD, "Constellation: 16-QAM"); break; case 2: log_message( log_module, MSG_FLOOD, "Constellation: 64-QAM"); break; case 3: log_message( log_module, MSG_FLOOD, "Constellation: RFU"); break; default: log_message( log_module, MSG_FLOOD, "Constellation: BUG"); break; } switch(descr->hierarchy_information) { case 0: log_message( log_module, MSG_FLOOD, "hierarchy_information: non-hierarchical, native interleaver"); break; case 1: log_message( log_module, MSG_FLOOD, "hierarchy_information: α = 1, native interleaver"); break; case 2: log_message( log_module, MSG_FLOOD, "hierarchy_information: α = 2, native interleaver"); break; case 3: log_message( log_module, MSG_FLOOD, "hierarchy_information: α = 4, native interleaver"); break; case 4: log_message( log_module, MSG_FLOOD, "hierarchy_information: non-hierarchical, in-depth interleaver"); break; case 5: log_message( log_module, MSG_FLOOD, "hierarchy_information: α = 1, in-depth interleaver"); break; case 6: log_message( log_module, MSG_FLOOD, "hierarchy_information: α = 2, in-depth interleaver"); break; case 7: log_message( log_module, MSG_FLOOD, "hierarchy_information: α = 4, in-depth interleaver"); break; default: log_message( log_module, MSG_FLOOD, "hierarchy_information: BUG please contact"); break; } switch(descr->code_rate_HP_stream) { case 0: log_message( log_module, MSG_FLOOD, "code_rate_HP_stream: 1/2"); break; case 1: log_message( log_module, MSG_FLOOD, "code_rate_HP_stream: 2/3"); break; case 2: log_message( log_module, MSG_FLOOD, "code_rate_HP_stream: 3/4"); break; case 3: log_message( log_module, MSG_FLOOD, "code_rate_HP_stream: 5/6"); break; case 4: log_message( log_module, MSG_FLOOD, "code_rate_HP_stream: 7/8"); break; case 5: case 6: case 7: default: log_message( log_module, MSG_FLOOD, "code_rate_HP_stream: RFU"); break; } switch(descr->code_rate_LP_stream) { case 0: log_message( log_module, MSG_FLOOD, "code_rate_LP_stream: 1/2"); break; case 1: log_message( log_module, MSG_FLOOD, "code_rate_LP_stream: 2/3"); break; case 2: log_message( log_module, MSG_FLOOD, "code_rate_LP_stream: 3/4"); break; case 3: log_message( log_module, MSG_FLOOD, "code_rate_LP_stream: 5/6"); break; case 4: log_message( log_module, MSG_FLOOD, "code_rate_LP_stream: 7/8"); break; case 5: case 6: case 7: default: log_message( log_module, MSG_FLOOD, "code_rate_LP_stream: RFU"); break; } switch(descr->guard_interval) { case 0: log_message( log_module, MSG_FLOOD, "guard_interval: 1/32"); break; case 1: log_message( log_module, MSG_FLOOD, "guard_interval: 1/16"); break; case 2: log_message( log_module, MSG_FLOOD, "guard_interval: 1/8"); break; case 3: log_message( log_module, MSG_FLOOD, "guard_interval: 1/4"); break; default: log_message( log_module, MSG_FLOOD, "guard_interval: BUG"); break; } switch(descr->transmission_mode) { case 0: log_message( log_module, MSG_FLOOD, "transmission_mode: 2k"); break; case 1: log_message( log_module, MSG_FLOOD, "transmission_mode: 8k"); break; case 2: log_message( log_module, MSG_FLOOD, "transmission_mode: 4k"); break; case 3: log_message( log_module, MSG_FLOOD, "transmission_mode: RFU"); break; default: log_message( log_module, MSG_FLOOD, "transmission_mode: BUG"); break; } if(descr->other_frequency_flag) log_message( log_module, MSG_FLOOD, "other_frequency_flag: one or more other frequencies are in use"); else log_message( log_module, MSG_FLOOD, "other_frequency_flag: no other frequency is in use"); log_message( log_module, MSG_FLOOD, "--- descriptor done ---\n"); } /** @brief Parse the lcn descriptor * It's used to get the logical channel number * @param buf the buffer containing the descriptor */ void ts_display_lcn_descriptor(char *log_module, unsigned char* buf) { /* Service descriptor : descriptor_tag 8 descriptor_length 8 for (i=0;i 0) { lcn=(nit_lcn_t *)buf; buf+=NIT_LCN_LEN; service_id= HILO(lcn->service_id); i_lcn=HILO(lcn->logical_channel_number); log_message( log_module, MSG_FLOOD, "NIT LCN channel number %d, service id %d visible %d\n",i_lcn ,service_id, lcn->visible_service_flag); descriptor_len -= NIT_LCN_LEN; } } /** */ void ts_display_frequency_list_descriptor(char* log_module,unsigned char *buf) { /* Service list descriptor : descriptor_tag 8 descriptor_length 8 RFU 6 coding type 2 for (i=0;i #include #include #include #include "config.h" //The maximum size for a TS packet #define MAX_TS_SIZE 4096 //0x1ffb=8187 It's the pid for the information tables in ATSC #define PSIP_PID 8187 //Part of this code comes from libsi // (C) 2001-03 Rolf Hakenes , under the // GNU GPL with contribution of Oleg Assovski, // www.satmania.com #define TS_HEADER_LEN 5 #define HILO(x) (x##_hi << 8 | x##_lo) #define BCDHI(x) (((x)>> 4) & 0x0f) #define BCDLO(x) ((x) & 0x0f) /* * * ETSI ISO/IEC 13818-1 specifies SI which is referred to as PSI. The PSI * data provides information to enable automatic configuration of the * receiver to demultiplex and decode the various streams of programs * within the multiplex. The PSI data is structured as four types of table. * The tables are transmitted in sections. */ /** * @brief Program Association Table (PAT): * * - for each service in the multiplex, the PAT indicates the location * (the Packet Identifier (PID) values of the Transport Stream (TS) * packets) of the corresponding Program Map Table (PMT). * It also gives the location of the Network Information Table (NIT). * */ #define PAT_LEN 8 /** @brief Program Association Table (PAT):*/ typedef struct { u_char table_id :8; #if BYTE_ORDER == BIG_ENDIAN u_char section_syntax_indicator :1; u_char dummy :1; // has to be 0 u_char :2; u_char section_length_hi :4; #else u_char section_length_hi :4; u_char :2; u_char dummy :1; // has to be 0 u_char section_syntax_indicator :1; #endif u_char section_length_lo :8; u_char transport_stream_id_hi :8; u_char transport_stream_id_lo :8; #if BYTE_ORDER == BIG_ENDIAN u_char :2; u_char version_number :5; u_char current_next_indicator :1; #else u_char current_next_indicator :1; u_char version_number :5; u_char :2; #endif u_char section_number :8; u_char last_section_number :8; } pat_t; #define PAT_PROG_LEN 4 /** @brief Program Association Table (PAT): program*/ typedef struct { u_char program_number_hi :8; u_char program_number_lo :8; #if BYTE_ORDER == BIG_ENDIAN u_char :3; u_char network_pid_hi :5; #else u_char network_pid_hi :5; u_char :3; #endif u_char network_pid_lo :8; /* or program_map_pid (if prog_num=0)*/ } pat_prog_t; //Used to generate the CA_PMT message and for autoconfiguration /** @brief Mpeg2-TS header*/ typedef struct { u_char sync_byte :8; #if BYTE_ORDER == BIG_ENDIAN u_char transport_error_indicator :1; u_char payload_unit_start_indicator :1; u_char transport_priority :1; u_char pid_hi :5; #else u_char pid_hi :5; u_char transport_priority :1; u_char payload_unit_start_indicator :1; u_char transport_error_indicator :1; #endif u_char pid_lo :8; #if BYTE_ORDER == BIG_ENDIAN u_char transport_scrambling_control :2; u_char adaptation_field_control :2; u_char continuity_counter :4; #else u_char continuity_counter :4; u_char adaptation_field_control :2; u_char transport_scrambling_control :2; #endif } ts_header_t; //For cam support and autoconfigure /** length of the PMT header */ #define PMT_LEN 12 /**@brief Program Map Table (PMT): * * - the PMT identifies and indicates the locations of the streams that * make up each service, and the location of the Program Clock * Reference fields for a service. * */ typedef struct { u_char table_id :8; #if BYTE_ORDER == BIG_ENDIAN u_char section_syntax_indicator :1; u_char dummy :1; // has to be 0 u_char :2; u_char section_length_hi :4; #else u_char section_length_hi :4; u_char :2; u_char dummy :1; // has to be 0 u_char section_syntax_indicator :1; #endif u_char section_length_lo :8; u_char program_number_hi :8; u_char program_number_lo :8; #if BYTE_ORDER == BIG_ENDIAN u_char :2; u_char version_number :5; u_char current_next_indicator :1; #else u_char current_next_indicator :1; u_char version_number :5; u_char :2; #endif u_char section_number :8; u_char last_section_number :8; #if BYTE_ORDER == BIG_ENDIAN u_char :3; u_char PCR_PID_hi :5; #else u_char PCR_PID_hi :5; u_char :3; #endif u_char PCR_PID_lo :8; #if BYTE_ORDER == BIG_ENDIAN u_char :4; u_char program_info_length_hi :4; #else u_char program_info_length_hi :4; u_char :4; #endif u_char program_info_length_lo :8; //descriptors } pmt_t; /** length of the PMT program information section header */ #define PMT_INFO_LEN 5 /** @brief Program Map Table (PMT) : program information section*/ typedef struct { u_char stream_type :8; #if BYTE_ORDER == BIG_ENDIAN u_char :3; u_char elementary_PID_hi :5; #else u_char elementary_PID_hi :5; u_char :3; #endif u_char elementary_PID_lo :8; #if BYTE_ORDER == BIG_ENDIAN u_char :4; u_char ES_info_length_hi :4; #else u_char ES_info_length_hi :4; u_char :4; #endif u_char ES_info_length_lo :8; // descriptors } pmt_info_t; #define DESCR_CA_LEN 6 /** @brief 0x09 ca_descriptor */ typedef struct { u_char descriptor_tag :8; u_char descriptor_length :8; u_char CA_type_hi :8; u_char CA_type_lo :8; #if BYTE_ORDER == BIG_ENDIAN u_char reserved :3; u_char CA_PID_hi :5; #else u_char CA_PID_hi :5; u_char reserved :3; #endif u_char CA_PID_lo :8; } descr_ca_t; /** length of the SDT header */ #define SDT_LEN 11 /** @brief Service Description Table (SDT): * * - the SDT contains data describing the services in the system e.g. * names of services, the service provider, etc. * */ typedef struct { u_char table_id :8; #if BYTE_ORDER == BIG_ENDIAN u_char section_syntax_indicator :1; u_char :3; u_char section_length_hi :4; #else u_char section_length_hi :4; u_char :3; u_char section_syntax_indicator :1; #endif u_char section_length_lo :8; u_char transport_stream_id_hi :8; u_char transport_stream_id_lo :8; #if BYTE_ORDER == BIG_ENDIAN u_char :2; u_char version_number :5; u_char current_next_indicator :1; #else u_char current_next_indicator :1; u_char version_number :5; u_char :2; #endif u_char section_number :8; u_char last_section_number :8; u_char original_network_id_hi :8; u_char original_network_id_lo :8; u_char :8; } sdt_t; #define GetSDTTransportStreamId(x) (HILO(((sdt_t *) x)->transport_stream_id)) #define GetSDTOriginalNetworkId(x) (HILO(((sdt_t *) x)->original_network_id)) #define SDT_DESCR_LEN 5 /**@brief Service Description Table (SDT), descriptor */ typedef struct { u_char service_id_hi :8; u_char service_id_lo :8; #if BYTE_ORDER == BIG_ENDIAN u_char :6; u_char eit_schedule_flag :1; u_char eit_present_following_flag :1; u_char running_status :3; u_char free_ca_mode :1; u_char descriptors_loop_length_hi :4; #else u_char eit_present_following_flag :1; u_char eit_schedule_flag :1; u_char :6; u_char descriptors_loop_length_hi :4; u_char free_ca_mode :1; u_char running_status :3; #endif u_char descriptors_loop_length_lo :8; } sdt_descr_t; /* * * 3) Event Information Table (EIT): * * - the EIT contains data concerning events or programmes such as event * name, start time, duration, etc.; - the use of different descriptors * allows the transmission of different kinds of event information e.g. * for different service types. * */ #define EIT_LEN 14 typedef struct { u_char table_id :8; #if BYTE_ORDER == BIG_ENDIAN u_char section_syntax_indicator :1; u_char :3; u_char section_length_hi :4; #else u_char section_length_hi :4; u_char :3; u_char section_syntax_indicator :1; #endif u_char section_length_lo :8; u_char service_id_hi :8; u_char service_id_lo :8; #if BYTE_ORDER == BIG_ENDIAN u_char :2; u_char version_number :5; u_char current_next_indicator :1; #else u_char current_next_indicator :1; u_char version_number :5; u_char :2; #endif u_char section_number :8; u_char last_section_number :8; u_char transport_stream_id_hi :8; u_char transport_stream_id_lo :8; u_char original_network_id_hi :8; u_char original_network_id_lo :8; u_char segment_last_section_number :8; u_char segment_last_table_id :8; } eit_t; #define EIT_EVENT_LEN 12 /**@brief Event Information Table (EIT), descriptor header*/ typedef struct { u_char event_id_hi :8; u_char event_id_lo :8; u_char start_time_0 :8; u_char start_time_1 :8; u_char start_time_2 :8; u_char start_time_3 :8; u_char start_time_4 :8; u_char duration_0 :8; u_char duration_1 :8; u_char duration_2 :8; #if BYTE_ORDER == BIG_ENDIAN u_char running_status :3; u_char free_ca_mode :1; u_char descriptors_loop_length_hi :4; #else u_char descriptors_loop_length_hi :4; u_char free_ca_mode :1; u_char running_status :3; #endif u_char descriptors_loop_length_lo :8; } eit_event_t; /* * * 5) Network Information Table (NIT): * * - the NIT is intended to provide information about the physical * network. The syntax and semantics of the NIT are defined in * ETSI EN 300 468. * */ #define NIT_LEN 10 typedef struct { u_char table_id :8; #if BYTE_ORDER == BIG_ENDIAN u_char section_syntax_indicator :1; u_char :3; u_char section_length_hi :4; #else u_char section_length_hi :4; u_char :3; u_char section_syntax_indicator :1; #endif u_char section_length_lo :8; u_char network_id_hi :8; u_char network_id_lo :8; #if BYTE_ORDER == BIG_ENDIAN u_char :2; u_char version_number :5; u_char current_next_indicator :1; #else u_char current_next_indicator :1; u_char version_number :5; u_char :2; #endif u_char section_number :8; u_char last_section_number :8; #if BYTE_ORDER == BIG_ENDIAN u_char :4; u_char network_descriptor_length_hi :4; #else u_char network_descriptor_length_hi :4; u_char :4; #endif u_char network_descriptor_length_lo :8; /* descriptors */ }nit_t; #define SIZE_NIT_MID 2 typedef struct { // after descriptors #if BYTE_ORDER == BIG_ENDIAN u_char :4; u_char transport_stream_loop_length_hi :4; #else u_char transport_stream_loop_length_hi :4; u_char :4; #endif u_char transport_stream_loop_length_lo :8; }nit_mid_t; #define NIT_TS_LEN 6 typedef struct { u_char transport_stream_id_hi :8; u_char transport_stream_id_lo :8; u_char original_network_id_hi :8; u_char original_network_id_lo :8; #if BYTE_ORDER == BIG_ENDIAN u_char :4; u_char transport_descriptors_length_hi :4; #else u_char transport_descriptors_length_hi :4; u_char :4; #endif u_char transport_descriptors_length_lo :8; /* descriptors */ }nit_ts_t; #define NIT_LCN_LEN 4 typedef struct { u_char service_id_hi :8; u_char service_id_lo :8; #if BYTE_ORDER == BIG_ENDIAN u_char visible_service_flag :1; u_char reserved :5; u_char logical_channel_number_hi :2; #else u_char logical_channel_number_hi :2; u_char reserved :5; u_char visible_service_flag :1; #endif u_char logical_channel_number_lo :8; }nit_lcn_t; /** length of the common tables header */ #define TABLE_LEN 8 #define BYTES_BFR_SEC_LEN 3 //the number of bytes before the section_length (so must be added to section_length to get full len) /** @brief Common Table headers (PAT, EIT, SDT, PMT, NIT): * This header is the first 8 bytes common to all tables * it's mainly used to get the section length */ typedef struct { u_char table_id :8; #if BYTE_ORDER == BIG_ENDIAN u_char section_syntax_indicator :1; u_char :3; u_char section_length_hi :4; #else u_char section_length_hi :4; u_char :3; u_char section_syntax_indicator :1; #endif u_char section_length_lo :8; u_char transport_stream_id_hi :8; u_char transport_stream_id_lo :8; #if BYTE_ORDER == BIG_ENDIAN u_char :2; u_char version_number :5; u_char current_next_indicator :1; #else u_char current_next_indicator :1; u_char version_number :5; u_char :2; #endif u_char section_number :8; u_char last_section_number :8; } tbl_h_t; /** @brief 0x5a terrestrial_delivery_system_descriptor */ typedef struct { u_char descriptor_tag :8; u_char descriptor_length :8; u_char frequency_4 :8; u_char frequency_3 :8; u_char frequency_2 :8; u_char frequency_1 :8; #if BYTE_ORDER == BIG_ENDIAN u_char bandwidth :3; u_char priority :1; u_char Time_Slicing_indicator :1; u_char MPE_FEC_indicator :1; u_char :2; #else u_char :2; u_char MPE_FEC_indicator :1; u_char Time_Slicing_indicator :1; u_char priority :1; u_char bandwidth :3; #endif #if BYTE_ORDER == BIG_ENDIAN u_char constellation :2; u_char hierarchy_information :3; u_char code_rate_HP_stream :3; #else u_char code_rate_HP_stream :3; u_char hierarchy_information :3; u_char constellation :2; #endif #if BYTE_ORDER == BIG_ENDIAN u_char code_rate_LP_stream :3; u_char guard_interval :2; u_char transmission_mode :2; u_char other_frequency_flag :1; #else u_char other_frequency_flag :1; u_char transmission_mode :2; u_char guard_interval :2; u_char code_rate_LP_stream :3; #endif } descr_terr_delivery_t; /** @brief 0x43 satellite_delivery_system_descriptor */ typedef struct { u_char descriptor_tag :8; u_char descriptor_length :8; u_char frequency_4 :8; u_char frequency_3 :8; u_char frequency_2 :8; u_char frequency_1 :8; u_char orbital_position_hi :8; u_char orbital_position_lo :8; #if BYTE_ORDER == BIG_ENDIAN u_char west_east_flag :1; u_char polarization :2; u_char roll_off :2; u_char modulation_system :1; u_char modulation_type :2; #else u_char modulation_type :2; u_char modulation_system :1; u_char roll_off :2; u_char polarization :2; u_char west_east_flag :1; #endif u_char symbol_rate_12 :8; u_char symbol_rate_34 :8; u_char symbol_rate_56 :8; #if BYTE_ORDER == BIG_ENDIAN u_char symbol_rate_7 :4; u_char FEC_inner :4; #else u_char FEC_inner :4; u_char symbol_rate_7 :4; #endif } descr_sat_delivery_t; /*************************************************** * ATSC PSIP tables * * See A/65C * * Atsc standard : * * Program and System Information Protocol for * * Terrestrial Broadcast and Cable (revision C). * ***************************************************/ #define PSIP_HEADER_LEN 9 /**@brief Header of an ATSC PSIP (Program and System Information Protocol) table*/ typedef struct { u_char table_id :8; #if BYTE_ORDER == BIG_ENDIAN u_char section_syntax_indicator :1; u_char private_indicator :1; u_char :2; u_char section_length_hi :4; #else u_char section_length_hi :4; u_char :2; u_char private_indicator :1; u_char section_syntax_indicator :1; #endif u_char section_length_lo :8; u_char transport_stream_id_hi :8; u_char transport_stream_id_lo :8; #if BYTE_ORDER == BIG_ENDIAN u_char :2; u_char version_number :5; u_char current_next_indicator :1; #else u_char current_next_indicator :1; u_char version_number :5; u_char :2; #endif u_char section_number :8; u_char last_section_number :8; u_char protocol_version :8; // u_char num_channels_in_section :8; //For information, in case of TVCT or CVCT } psip_t; #define PSIP_VCT_LEN 32 /**@brief PSIP (TC)VCT (Terrestrial/Cable Virtual Channel Table) channels descriptors*/ typedef struct { uint8_t short_name[14];//The channel short name in UTF-16 #if BYTE_ORDER == BIG_ENDIAN u_char :4; //reserved u_char major_channel_number_hi4 :4; #else u_char major_channel_number_hi4 :4; u_char :4; //reserved #endif #if BYTE_ORDER == BIG_ENDIAN u_char major_channel_number_lo6 :6; u_char minor_channel_number_hi :2; #else u_char minor_channel_number_hi :2; u_char major_channel_number_lo6 :6; #endif u_char minor_channel_number_lo :8; u_char modulation_mode :8; u_int8_t carrier_frequency[4]; u_char channel_tsid_hi :8; u_char channel_tsid_lo :8; u_char program_number_hi :8; u_char program_number_lo :8; #if BYTE_ORDER == BIG_ENDIAN u_char ETM_location :2; u_char access_controlled :1; u_char hidden :1; u_char path_select :1; //Only cable u_char out_of_band :1; //Only cable u_char hide_guide :1; u_char :1; //reserved #else u_char :1; //reserved u_char hide_guide :1; u_char out_of_band :1; //Only cable u_char path_select :1; //Only cable u_char hidden :1; u_char access_controlled :1; u_char ETM_location :2; #endif #if BYTE_ORDER == BIG_ENDIAN u_char :2; //reserved u_char service_type :6; #else u_char service_type :6; u_char :2; //reserved #endif u_char source_id_hi :8; u_char source_id_lo :8; #if BYTE_ORDER == BIG_ENDIAN u_char :6; u_char descriptor_length_hi :2; #else u_char descriptor_length_hi :2; u_char :6; #endif u_char descriptor_length_lo :8; } psip_vct_channel_t; //1 for number strings, 3 for language code,1 for number of segments #define MULTIPLE_STRING_STRUCTURE_HEADER 5 /***************************** * End of ATSC PSIP tables * *****************************/ /** Enum to tell if the option is set*/ typedef enum packet_status { EMPTY, //No data in the packet PARTIAL_HEADER, //An incomplete header is in the packet STARTED, //Some data are in the packet VALID //All the expected data are in the packet and the CRC32 is valid } packet_status_t; //The number of complete section we accept to have in one TS //A TS is 188bytes long minus 4 bytes for the header 184 bytes left //A section is at least 8 bytes long + one descriptor 3 bytes + CRC32 4 bytes //it's a total of 15bytes / section #define MAX_FULL_PACKETS 15 //A minimum is MAX_TS_SIZE + TS_PACKET_SIZE //Just to add flexibility on how to write the code I take some margin #define FULL_BUFFER_SIZE 2*MAX_TS_SIZE /**@brief structure for the build of a ts packet Since a packet can be finished and another one starts in the same elementary TS packet, there is two packets in this structure */ typedef struct { /** the buffer for the packet full (empty or contains a valid full packet)*/ unsigned char data_full[MAX_TS_SIZE]; /** the length of the data contained in data_full */ int len_full; //starting from here, these variables MUSN'T be accessed outside ts.c /** The number of full packets */ int full_number; /** The lengths of the full packets */ int full_lengths[MAX_FULL_PACKETS]; /** The amount of data in the full buffer */ int full_buffer_len; /** The buffer containing the full packets */ unsigned char buffer_full[FULL_BUFFER_SIZE]; /** the buffer for the partial packet (never valid, shouldn't be accessed by funtions other than get_ts_packet)*/ unsigned char data_partial[MAX_TS_SIZE]; /** the length of the data contained in data_partial */ int len_partial; /** the expected length of the data contained in data_partial */ int expected_len_partial; /** The packet status*/ packet_status_t status_partial; /**The PID of the packet*/ int pid; /**the countinuity counter, incremented in each packet*/ int cc; /** If we have threads, the lock on the packet */ pthread_mutex_t packetmutex; }mumudvb_ts_packet_t; int get_ts_packet(unsigned char *, mumudvb_ts_packet_t *); unsigned char *get_ts_begin(unsigned char *buf); struct mumudvb_channel_t; void ts_display_pat(char* log_module,unsigned char *buf); void ts_display_country_avaibility_descriptor(char* log_module,unsigned char *buf); void ts_display_nit_network_descriptors(char *log_module, unsigned char *buf,int descriptors_loop_len); void ts_display_network_name_descriptor(char* log_module, unsigned char *buf); void ts_display_multilingual_network_name_descriptor(char* log_module, unsigned char *buf); void ts_display_service_list_descriptor(char* log_module, unsigned char *buf); void ts_display_lcn_descriptor(char* log_module, unsigned char *buf); void ts_display_satellite_delivery_system_descriptor(char* log_module, unsigned char *buf); void ts_display_terrestrial_delivery_system_descriptor(char* log_module, unsigned char *buf); void ts_display_frequency_list_descriptor(char* log_module, unsigned char* buf); #endif MuMuDVB-2.1.0/src/tune.c000066400000000000000000001414461305714132500146520ustar00rootroot00000000000000/* MuMuDVB - Stream a DVB transport stream. * File for tuning DVB cards * * last version availaible from http://mumudvb.braice.net/ * * Copyright (C) 2004-2013 Brice DUBOST * Copyright (C) Dave Chapman 2001,2002 * Part of this code from Romolo Manfredini * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Or, point your browser to http://www.gnu.org/copyleft/gpl.html * */ /** @file * @brief Tuning of the dvb card * * This file contains functions for tuning the card, or displaying signal strength... */ #include #include #include #include #include #include #include #include "config.h" #ifdef ANDROID #include #else #include #endif #include #include #include #include #include #include "tune.h" #include "mumudvb.h" #include "errors.h" #include "log.h" #include "dvb.h" #include "math.h" static char *log_module="Tune: "; /** Initialize tune variables*/ void init_tune_v(tune_p_t *tune_p) { * tune_p=(tune_p_t){ .card = -1, .tuner = 0, .card_dev_path=DVB_DEV_PATH, .card_tuned = 0, .tuning_timeout = ALARM_TIME_TIMEOUT, .freq = 0, .srate = 0, .pol = 0, .lnb_voltage_off=0, .lnb_type=LNB_UNIVERSAL, .lnb_lof_standard=DEFAULT_LOF_STANDARD, .lnb_slof=DEFAULT_SLOF, .lnb_lof_low=DEFAULT_LOF1_UNIVERSAL, .lnb_lof_high=DEFAULT_LOF2_UNIVERSAL, .uni_freq = 0, .sat_number = 0, .switch_no = -1, .switch_type = 'C', .diseqc_repeat = 0, .modulation_set = 0, .display_strenght = 0, .check_status = 1, .strengththreadshutdown = 0, .HP_CodeRate = HP_CODERATE_DEFAULT,//cf tune.h .LP_CodeRate = LP_CODERATE_DEFAULT, .TransmissionMode = TRANSMISSION_MODE_DEFAULT, .guardInterval = GUARD_INTERVAL_DEFAULT, .bandwidth = BANDWIDTH_DEFAULT, .hier = HIERARCHY_DEFAULT, .fe_type=FE_QPSK, //sat by default #if DVB_API_VERSION >= 5 .delivery_system=SYS_UNDEFINED, .rolloff=ROLLOFF_35, #endif #if STREAM_ID .stream_id = 0, .pls_code = 0, .pls_type = PLS_ROOT, #endif .read_file_path = '\0' }; } /** @brief Read a line of the configuration file to check if there is a tuning parameter * * @param tuneparams the tuning parameters * @param substring The currrent line */ int read_tuning_configuration(tune_p_t *tuneparams, char *substring) { char delimiteurs[] = CONFIG_FILE_SEPARATOR; if (!strcmp (substring, "sat_number")) { substring = strtok (NULL, delimiteurs); tuneparams->sat_number = atoi (substring); if (tuneparams->sat_number > 4) { log_message( log_module, MSG_ERROR, "Config issue : sat_number. The satellite number must be between 0 and 4. Please report if you have an equipment wich support more\n"); return -1; } } else if (!strcmp (substring, "switch_input")) { substring = strtok (NULL, delimiteurs); tuneparams->switch_no = atoi (substring); if (tuneparams->switch_no > 15) { log_message( log_module, MSG_ERROR, "Configuration issue : switch_input. The diseqc switch input number must be between 0 and 15.\n"); return -1; } } else if (!strcmp (substring, "freq")) { double temp_freq; substring = strtok (NULL, delimiteurs); temp_freq = atof (substring); tuneparams->freq = (int)( 1000UL * temp_freq); } else if (!strcmp (substring, "uni_freq")) { double temp_freq; substring = strtok (NULL, delimiteurs); temp_freq = atof (substring); tuneparams->uni_freq = (int)( temp_freq); } else if (!strcmp (substring, "pol")) { substring = strtok (NULL, delimiteurs); if (tolower (substring[0]) == 'v') { tuneparams->pol = 'V'; } else if (tolower (substring[0]) == 'h') { tuneparams->pol = 'H'; } else if (tolower (substring[0]) == 'l') { tuneparams->pol = 'L'; } else if (tolower (substring[0]) == 'r') { tuneparams->pol = 'R'; } else { log_message( log_module, MSG_ERROR, "Config issue : polarisation\n"); return -1; } } else if (!strcmp (substring, "lnb_voltage_off")) { substring = strtok (NULL, delimiteurs); tuneparams->lnb_voltage_off = atoi(substring); } else if (!strcmp (substring, "lnb_type")) { substring = strtok (NULL, delimiteurs); if(!strcmp (substring, "universal")) tuneparams->lnb_type=LNB_UNIVERSAL; else if(!strcmp (substring, "standard")) tuneparams->lnb_type=LNB_STANDARD; else { log_message( log_module, MSG_ERROR, "Config issue : lnb_type\n"); return -1; } } else if (!strcmp (substring, "lnb_lof_standard")) { substring = strtok (NULL, delimiteurs); tuneparams->lnb_lof_standard = atoi(substring)*1000UL; } else if (!strcmp (substring, "lnb_slof")) { substring = strtok (NULL, delimiteurs); tuneparams->lnb_slof = atoi(substring)*1000UL; } else if (!strcmp (substring, "lnb_lof_high")) { substring = strtok (NULL, delimiteurs); tuneparams->lnb_lof_high = atoi(substring)*1000UL; } else if (!strcmp (substring, "lnb_lof_low")) { substring = strtok (NULL, delimiteurs); tuneparams->lnb_lof_low = atoi(substring)*1000UL; } else if (!strcmp (substring, "srate")) { substring = strtok (NULL, delimiteurs); tuneparams->srate = atol (substring); tuneparams->srate *= 1000UL; } else if (!strcmp (substring, "card")) { substring = strtok (NULL, delimiteurs); if(tuneparams->card!=-1) { log_message( log_module, MSG_ERROR, "Card defined on the command line: %d, overrides conf file %d",tuneparams->card,atoi (substring)); } else { tuneparams->card = atoi (substring); } } else if (!strcmp (substring, "check_status")) { substring = strtok (NULL, delimiteurs); tuneparams->check_status = atoi (substring); } else if (!strcmp (substring, "tuner")) { substring = strtok (NULL, delimiteurs); tuneparams->tuner = atoi (substring); } else if (!strcmp (substring, "card_dev_path")) { substring = strtok (NULL, delimiteurs); if(strlen(substring)>(256-1)) { log_message( log_module, MSG_ERROR, "The card dev path is too long\n"); return -1; } strcpy (tuneparams->card_dev_path, substring); } else if (!strcmp (substring, "trans_mode")) { // DVB-T substring = strtok (NULL, delimiteurs); sscanf (substring, "%s\n", substring); if (!strcmp (substring, "2k")) tuneparams->TransmissionMode=TRANSMISSION_MODE_2K; else if (!strcmp (substring, "8k")) tuneparams->TransmissionMode=TRANSMISSION_MODE_8K; else if (!strcmp (substring, "auto")) tuneparams->TransmissionMode=TRANSMISSION_MODE_AUTO; #ifdef TRANSMISSION_MODE_4K //DVB-T2 else if (!strcmp (substring, "4k")) tuneparams->TransmissionMode=TRANSMISSION_MODE_4K; #endif #ifdef TRANSMISSION_MODE_16K //DVB-T2 else if (!strcmp (substring, "16k")) tuneparams->TransmissionMode=TRANSMISSION_MODE_16K; #endif #ifdef TRANSMISSION_MODE_32K //DVB-T2 else if (!strcmp (substring, "32k")) tuneparams->TransmissionMode=TRANSMISSION_MODE_32K; #endif else { log_message( log_module, MSG_ERROR, "Config issue : trans_mode\n"); return -1; } } else if (!strcmp (substring, "bandwidth")) { // DVB-T substring = strtok (NULL, delimiteurs); sscanf (substring, "%s\n", substring); if (!strcmp (substring, "8MHz")) tuneparams->bandwidth=BANDWIDTH_8_MHZ; else if (!strcmp (substring, "7MHz")) tuneparams->bandwidth=BANDWIDTH_7_MHZ; else if (!strcmp (substring, "6MHz")) tuneparams->bandwidth=BANDWIDTH_6_MHZ; else if (!strcmp (substring, "auto")) tuneparams->bandwidth=BANDWIDTH_AUTO; // DVB-T2 // @See https://patchwork.kernel.org/patch/761652/ else if (!strcmp (substring, "5MHz")) #ifdef BANDWIDTH_5_MHZ tuneparams->bandwidth=BANDWIDTH_5_MHZ; #else { log_message( log_module, MSG_ERROR, "Config issue: 5MHz bandwidth is not supported on your system please check your drivers installation"); return -1; } #endif else if (!strcmp (substring, "10MHz")) #ifdef BANDWIDTH_10_MHZ tuneparams->bandwidth=BANDWIDTH_10_MHZ; #else { log_message( log_module, MSG_ERROR, "Config issue: 10MHz bandwidth is not supported on your system please check your drivers installation"); return -1; } #endif else if (!strcmp (substring, "1.712MHz")) #ifdef BANDWIDTH_1_712_MHZ tuneparams->bandwidth=BANDWIDTH_1_712_MHZ; #else { log_message( log_module, MSG_ERROR, "Config issue: 1.712MHz bandwidth is not supported on your system please check your drivers installation"); return -1; } #endif else { log_message( log_module, MSG_ERROR, "Config issue: bandwidth"); return -1; } } else if (!strcmp (substring, "guardinterval")) { // DVB-T substring = strtok (NULL, delimiteurs); sscanf (substring, "%s\n", substring); if (!strcmp (substring, "1/32")) tuneparams->guardInterval=GUARD_INTERVAL_1_32; else if (!strcmp (substring, "1/16")) tuneparams->guardInterval=GUARD_INTERVAL_1_16; else if (!strcmp (substring, "1/8")) tuneparams->guardInterval=GUARD_INTERVAL_1_8; else if (!strcmp (substring, "1/4")) tuneparams->guardInterval=GUARD_INTERVAL_1_4; else if (!strcmp (substring, "auto")) tuneparams->guardInterval=GUARD_INTERVAL_AUTO; // DVB-T2 #ifdef GUARD_INTERVAL_1_128 else if (!strcmp (substring, "1/128")) tuneparams->guardInterval=GUARD_INTERVAL_1_128; #endif #ifdef GUARD_INTERVAL_19_128 else if (!strcmp (substring, "19/128")) tuneparams->guardInterval=GUARD_INTERVAL_19_128; #endif #ifdef GUARD_INTERVAL_19_256 else if (!strcmp (substring, "19/256")) tuneparams->guardInterval=GUARD_INTERVAL_19_256; #endif else { log_message( log_module, MSG_ERROR, "Config issue : guardinterval\n"); return -1; } } else if (!strcmp (substring, "coderate")) { // DVB-T substring = strtok (NULL, delimiteurs); sscanf (substring, "%s\n", substring); if (!strcmp (substring, "none")) tuneparams->HP_CodeRate=FEC_NONE; else if (!strcmp (substring, "1/2")) tuneparams->HP_CodeRate=FEC_1_2; else if (!strcmp (substring, "2/3")) tuneparams->HP_CodeRate=FEC_2_3; else if (!strcmp (substring, "3/4")) tuneparams->HP_CodeRate=FEC_3_4; else if (!strcmp (substring, "4/5")) tuneparams->HP_CodeRate=FEC_4_5; else if (!strcmp (substring, "5/6")) tuneparams->HP_CodeRate=FEC_5_6; else if (!strcmp (substring, "6/7")) tuneparams->HP_CodeRate=FEC_6_7; else if (!strcmp (substring, "7/8")) tuneparams->HP_CodeRate=FEC_7_8; else if (!strcmp (substring, "8/9")) tuneparams->HP_CodeRate=FEC_8_9; else if (!strcmp (substring, "auto")) tuneparams->HP_CodeRate=FEC_AUTO; #if DVB_API_VERSION >= 5 else if (!strcmp (substring, "3/5")) tuneparams->HP_CodeRate=FEC_3_5; else if (!strcmp (substring, "9/10")) tuneparams->HP_CodeRate=FEC_9_10; #endif else { log_message( log_module, MSG_ERROR, "Config issue : coderate\n"); return -1; } tuneparams->LP_CodeRate=tuneparams->HP_CodeRate; // I found the following : //In order to achieve hierarchy, two different code rates may be applied to two different levels of the modulation. Since hierarchy is not implemented ... } else if (!strcmp (substring, "delivery_system")) { #if DVB_API_VERSION >= 5 substring = strtok (NULL, delimiteurs); sscanf (substring, "%s\n", substring); if (!strcmp (substring, "DVBC_ANNEX_AC")) tuneparams->delivery_system=SYS_DVBC_ANNEX_AC; else if (!strcmp (substring, "DVBC_ANNEX_B")) tuneparams->delivery_system=SYS_DVBC_ANNEX_B; else if (!strcmp (substring, "DVBT")) tuneparams->delivery_system=SYS_DVBT; #ifdef DVBT2 else if (!strcmp (substring, "DVBT2")) tuneparams->delivery_system=SYS_DVBT2; #endif else if (!strcmp (substring, "DSS")) tuneparams->delivery_system=SYS_DSS; else if (!strcmp (substring, "DVBS")) tuneparams->delivery_system=SYS_DVBS; else if (!strcmp (substring, "DVBS2")) tuneparams->delivery_system=SYS_DVBS2; else if (!strcmp (substring, "DVBH")) tuneparams->delivery_system=SYS_DVBH; else if (!strcmp (substring, "ISDBT")) tuneparams->delivery_system=SYS_ISDBT; else if (!strcmp (substring, "ISDBS")) tuneparams->delivery_system=SYS_ISDBS; else if (!strcmp (substring, "ISDBS")) tuneparams->delivery_system=SYS_ISDBS; else if (!strcmp (substring, "ISDBC")) tuneparams->delivery_system=SYS_ISDBC; else if (!strcmp (substring, "ATSC")) tuneparams->delivery_system=SYS_ATSC; else if (!strcmp (substring, "ATSCMH")) tuneparams->delivery_system=SYS_ATSCMH; else if (!strcmp (substring, "DMBTH")) tuneparams->delivery_system=SYS_DMBTH; else if (!strcmp (substring, "CMMB")) tuneparams->delivery_system=SYS_CMMB; else if (!strcmp (substring, "DAB")) tuneparams->delivery_system=SYS_DAB; else { log_message( log_module, MSG_ERROR, "Config issue : delivery_system. Unknown delivery_system : %s\n",substring); return -1; } log_message( log_module, MSG_INFO, "You will use DVB API version 5 for tuning your card.\n"); #else log_message( log_module, MSG_ERROR, "Config issue : delivery_system. You are trying to set the delivery system but your MuMuDVB have not been built with DVB-S2/DVB API 5 support.\n"); return -1; #endif } else if (!strcmp (substring, "rolloff")) { #if DVB_API_VERSION >= 5 substring = strtok (NULL, delimiteurs); sscanf (substring, "%s\n", substring); if (!strcmp (substring, "35")) tuneparams->rolloff=ROLLOFF_35; else if (!strcmp (substring, "20")) tuneparams->rolloff=ROLLOFF_20; else if (!strcmp (substring, "25")) tuneparams->rolloff=ROLLOFF_25; else if (!strcmp (substring, "auto")) tuneparams->rolloff=ROLLOFF_AUTO; else { log_message( log_module, MSG_ERROR, "Config issue : delivery_system. Unknown delivery_system : %s\n",substring); return -1; } log_message( log_module, MSG_INFO, "You will use DVB API version 5 for tuning your card.\n"); #else log_message( log_module, MSG_ERROR, "Config issue : delivery_system. You are trying to set the rolloff but your MuMuDVB have not been built with DVB-S2/DVB API 5 support.\n"); return -1; #endif } else if (!strcmp (substring, "modulation")) { tuneparams->modulation_set = 1; substring = strtok (NULL, delimiteurs); if (!strcmp (substring, "QPSK")) tuneparams->modulation = QPSK; else if (!strcmp (substring, "QAM16")) tuneparams->modulation = QAM_16; else if (!strcmp (substring, "QAM32")) tuneparams->modulation = QAM_32; else if (!strcmp (substring, "QAM64")) tuneparams->modulation = QAM_64; else if (!strcmp (substring, "QAM128")) tuneparams->modulation = QAM_128; else if (!strcmp (substring, "QAM256")) tuneparams->modulation = QAM_256; else if (!strcmp (substring, "QAMAUTO")) tuneparams->modulation = QAM_AUTO; #ifdef ATSC else if (!strcmp (substring, "VSB8")) tuneparams->modulation = VSB_8; else if (!strcmp (substring, "VSB16")) tuneparams->modulation = VSB_16; #endif #if DVB_API_VERSION >= 5 else if (!strcmp (substring, "8PSK")) tuneparams->modulation = PSK_8; else if (!strcmp (substring, "16APSK")) tuneparams->modulation = APSK_16; else if (!strcmp (substring, "32APSK")) tuneparams->modulation = APSK_32; else if (!strcmp (substring, "DQPSK")) tuneparams->modulation = DQPSK; #endif else { log_message( log_module, MSG_ERROR, "Config issue : Bad value for modulation\n"); tuneparams->modulation_set = 0; return -1; } } else if ((!strcmp (substring, "timeout_accord"))||(!strcmp (substring, "tuning_timeout"))) { substring = strtok (NULL, delimiteurs); //we extract the substring tuneparams->tuning_timeout = atoi (substring); } else if (!strcmp (substring, "switch_type")) { substring = strtok (NULL, delimiteurs); if (tolower (substring[0]) == 'u') { tuneparams->switch_type = 'U'; } else if (tolower (substring[0]) == 'c') { tuneparams->switch_type = 'C'; } else if (tolower (substring[0]) == 'n') { tuneparams->switch_type = 'N'; } else { log_message( log_module, MSG_ERROR, "Config issue : switch_type\n"); return -1; } } else if (!strcmp (substring, "diseqc_repeat")) { substring = strtok (NULL, delimiteurs); tuneparams->diseqc_repeat = atoi (substring); } else if (!strcmp (substring, "stream_id")) { #ifdef STREAM_ID substring = strtok (NULL, delimiteurs); tuneparams->stream_id = atoi (substring); if (tuneparams->stream_id<0) { log_message( log_module, MSG_ERROR, "Config issue : stream_id. wrong value : %d\n",tuneparams->stream_id); tuneparams->stream_id=0; } log_message( log_module, MSG_DEBUG, "MuMuDVB have been compiled with DTV_STREAM_ID = %d.",DTV_STREAM_ID); #else log_message( log_module, MSG_ERROR, "Config issue : delivery_system. You are trying to set the stream_id but your MuMuDVB have not been built with DVB-S2/DVB API > 5.8 support.\n"); return -1; #endif } else if (!strcmp (substring, "pls_code")) { #ifdef STREAM_ID substring = strtok (NULL, delimiteurs); tuneparams->pls_code = atoi (substring); if (tuneparams->pls_code<0) { log_message( log_module, MSG_ERROR, "Config issue : pls_code. wrong value : %d\n",tuneparams->pls_code); tuneparams->pls_code=0; } #else log_message( log_module, MSG_ERROR, "Config issue : delivery_system. You are trying to set the pls_code but your MuMuDVB have not been built with DVB-S2/DVB API > 5.8 support.\n"); #endif } else if (!strcmp (substring, "pls_type")) { #ifdef STREAM_ID substring = strtok (NULL, delimiteurs); if (!strcmp(substring, "root")) { tuneparams->pls_type = PLS_ROOT; } else if (!strcmp(substring, "gold")) { tuneparams->pls_type = PLS_GOLD; } else if (!strcmp(substring, "common")) { log_message( log_module, MSG_ERROR, "Config issue : pls_type common not implemented, please contact"); tuneparams->pls_type = PLS_COMMON; } else { log_message( log_module, MSG_ERROR, "Config issue : pls_type not valid %s \n",substring); } #else log_message( log_module, MSG_ERROR, "Config issue : delivery_system. You are trying to set the pls_type but your MuMuDVB have not been built with DVB-S2/DVB API > 5.8 support.\n"); #endif } else if (!strcmp (substring, "read_file_path")) { // other substring extraction method in order to keep spaces substring = strtok (NULL, "="); strncpy(tuneparams->read_file_path,strtok(substring,"\n"),MAX_FILENAME_LEN-1); tuneparams->read_file_path[MAX_FILENAME_LEN-1]='\0'; if (strlen (substring) >= MAX_NAME_LEN - 1) log_message( log_module, MSG_WARN,"File name too long\n"); } else return 0; //Nothing concerning tuning, we return 0 to explore the other possibilities return 1;//We found something for tuning, we tell main to go for the next line } /** @brief Print the status * Print the status contained in festatus, this status says if the card is lock, sync etc. * * @param festatus the status to display */ void print_status(fe_status_t festatus) { log_message( log_module, MSG_INFO, "FE_STATUS:\n"); if (festatus & FE_HAS_SIGNAL) log_message( log_module, MSG_INFO, " FE_HAS_SIGNAL : found something above the noise level\n"); if (festatus & FE_HAS_CARRIER) log_message( log_module, MSG_INFO, " FE_HAS_CARRIER : found a DVB signal\n"); if (festatus & FE_HAS_VITERBI) log_message( log_module, MSG_INFO, " FE_HAS_VITERBI : FEC is stable\n"); if (festatus & FE_HAS_SYNC) log_message( log_module, MSG_INFO, " FE_HAS_SYNC : found sync bytes\n"); if (festatus & FE_HAS_LOCK) log_message( log_module, MSG_INFO, " FE_HAS_LOCK : everything's working... \n"); if (festatus & FE_TIMEDOUT) log_message( log_module, MSG_INFO, " FE_TIMEDOUT : no lock within the last ... seconds\n"); if (festatus & FE_REINIT) log_message( log_module, MSG_INFO, " FE_REINIT : frontend was reinitialized\n"); } /** The structure for a diseqc command*/ struct diseqc_cmd { struct dvb_diseqc_master_cmd cmd; uint32_t wait; }; /** @brief Wait msec miliseconds */ static inline void msleep(uint32_t msec) { struct timespec req = { msec / 1000, 1000000 * (msec % 1000) }; while (nanosleep(&req, &req)); } /** @brief Send a diseqc message * * As defined in the DiseqC norm, we stop the 22kHz tone, we set the voltage. Wait. send the command. Wait. put back the 22kHz tone * */ static int diseqc_send_msg(int fd, fe_sec_voltage_t v, struct diseqc_cmd **cmd, fe_sec_tone_mode_t t, fe_sec_mini_cmd_t b, int diseqc_repeat, char switch_type) { int err; if((err = ioctl(fd, FE_SET_TONE, SEC_TONE_OFF))) { log_message( log_module, MSG_WARN, "problem Setting the Tone OFF\n"); return -1; } if (switch_type=='N') { if((err = ioctl(fd, FE_SET_VOLTAGE, SEC_VOLTAGE_18))) { log_message( log_module, MSG_WARN, "problem Setting the Voltage\n"); return -1; } } else if((err = ioctl(fd, FE_SET_VOLTAGE, v))) { log_message( log_module, MSG_WARN, "problem Setting the Voltage\n"); return -1; } msleep(15); if (switch_type=='N') //Extra time for Unicable msleep(65); //1.x compatible equipment while (*cmd) { if (switch_type=='N') //TODO: understand why the message len is reset here (*cmd)->cmd.msg_len=5; else (*cmd)->cmd.msg_len=4; log_message( log_module, MSG_DETAIL ,"Sending first Diseqc message %02x %02x %02x %02x %02x %02x len %d\n", (*cmd)->cmd.msg[0],(*cmd)->cmd.msg[1],(*cmd)->cmd.msg[2],(*cmd)->cmd.msg[3],(*cmd)->cmd.msg[4],(*cmd)->cmd.msg[5], (*cmd)->cmd.msg_len); if((err = ioctl(fd, FE_DISEQC_SEND_MASTER_CMD, &(*cmd)->cmd))) { log_message( log_module, MSG_WARN, "problem sending the DiseqC message\n"); return -1; } msleep((*cmd)->wait); msleep(15); if (switch_type=='N') { if((err = ioctl(fd, FE_SET_VOLTAGE, SEC_VOLTAGE_13))) { log_message( log_module, MSG_WARN, "problem Setting the Voltage\n"); return -1; } } if(diseqc_repeat) { msleep(100); //Framing byte : Command from master, no reply required, repeated transmission : 0xe1 cmd[0]->cmd.msg[0] = 0xe1; //cmd.msg[0] = 0xe1; /* framing: master, no reply, repeated TX */ log_message( log_module, MSG_DETAIL ,"Sending repeated Diseqc message %02x %02x %02x %02x %02x %02x len %d\n", (*cmd)->cmd.msg[0],(*cmd)->cmd.msg[1],(*cmd)->cmd.msg[2],(*cmd)->cmd.msg[3],(*cmd)->cmd.msg[4],(*cmd)->cmd.msg[5], (*cmd)->cmd.msg_len); if((err = ioctl(fd, FE_DISEQC_SEND_MASTER_CMD, &(*cmd)->cmd))) { log_message( log_module, MSG_WARN, "problem sending the repeated DiseqC message\n"); return -1; } msleep((*cmd)->wait); } cmd++; } msleep(15); if (switch_type=='N') //Extra time for Unicable msleep(65); if ((err = ioctl(fd, FE_DISEQC_SEND_BURST, b))) { log_message( log_module, MSG_WARN, "problem sending the Tone Burst\n"); return err; } msleep(15); if (switch_type=='N') //Extra time for Unicable msleep(65); if(ioctl(fd, FE_SET_TONE, t) < 0) { log_message( log_module, MSG_WARN, "problem Setting the Tone back\n"); return -1; } return 0; } /** @brief generate and sent the digital satellite equipment control "message", * specification is available from http://www.eutelsat.com/ * * This function will set the LNB voltage and the 22kHz tone. If a satellite switching is asked * it will send a diseqc message * * @param fd : the file descriptor of the frontend * @param sat_no : the satellite number (0 for non diseqc compliant hardware, 1 to 4 for diseqc compliant) * @param switch_type the switch type (commited or uncommited or unicqbe) * @param pol_v_r : 1 : vertical or circular right, 0 : horizontal or circular left * @param hi_lo : the band for a dual band lnb * @param lnb_voltage_off : if one, force the 13/18V voltage to be 0 independantly of polarization */ static int do_diseqc(int fd, unsigned char sat_no, int switch_no, char switch_type, int pol_v_r, int hi_lo, int lnb_voltage_off, int diseqc_repeat, uint32_t *fefrequency, uint32_t uni_freq) { fe_sec_voltage_t lnb_voltage; struct diseqc_cmd *cmd[2] = { NULL, NULL }; int ret; //Compute the lnb voltage : 0 if we asked, of 13V for vertical and circular right, 18 for horizontal and circular left if (lnb_voltage_off) { lnb_voltage=SEC_VOLTAGE_OFF; log_message( log_module, MSG_INFO, "LNB voltage 0V\n"); } else if(pol_v_r) { lnb_voltage=SEC_VOLTAGE_13; log_message( log_module, MSG_INFO, "LNB voltage 13V\n"); } else { lnb_voltage=SEC_VOLTAGE_18; log_message( log_module, MSG_INFO, "LNB voltage 18V\n"); } //Diseqc compliant hardware if((sat_no != 0)||(switch_no!=-1)||(switch_type=='N')) { if(sat_no == 0) sat_no = 1; cmd[0]=malloc(sizeof(struct diseqc_cmd)); if(cmd[0]==NULL) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); set_interrupted(ERROR_MEMORY<<8); return -1; } cmd[0]->wait=0; //Framing byte : Command from master, no reply required, first transmission : 0xe0 cmd[0]->cmd.msg[0] = 0xe0; //Address byte : Any LNB, switcher or SMATV cmd[0]->cmd.msg[1] = 0x10; //Command byte : Write to port group 1 (Uncommited switches) //Command byte : Write to port group 0 (Committed switches) 0x38 //Command byte : Unicable switch : 5A if(switch_type=='U') cmd[0]->cmd.msg[2] = 0x39; else if (switch_type=='N') cmd[0]->cmd.msg[2] = 0x5A; else cmd[0]->cmd.msg[2] = 0x38; /* param: high nibble: reset bits, low nibble set bits, * bits are: option, position, polarization, band */ cmd[0]->cmd.msg[3] = 0xf0 | ((((sat_no-1) * 4) & 0x0f) | (pol_v_r ? 0 : 2) | (hi_lo ? 1 : 0)); if(switch_no != -1) { log_message( log_module, MSG_INFO ,"Diseqc switch position specified, we force switch input to %d\n",switch_no); cmd[0]->cmd.msg[3] = 0xf0 | (switch_no& 0x0f); } // cmd[0]->cmd.msg[4] = 0x00; if (switch_type=='N') { //Unicable, we recompute the proper messages //see https://patchwork.linuxtv.org/patch/7994/ log_message( log_module, MSG_INFO, "SCR/UNICABLE message "); //*fefrequency uint8_t channel_byte_1, channel_byte_2; channel_byte_1 = (uint8_t) (switch_no<< 5); uint16_t t; if (sat_no != 1) channel_byte_1 |= (1<< 4); if (!pol_v_r ) /* horizontal*/ channel_byte_1 |= (1<< 3); if (hi_lo) /* high band*/ channel_byte_1 |= (1<< 2); //https://code.mythtv.org/trac/attachment/ticket/9726/0001-libmythtv-Unicable-SCR-DIN-EN-50494.patch //seems that we will have to tune to another frequency too and adjust the voltage //Then we will have to tune the card to the SCR frequency as the LNB change it //https://patchwork.linuxtv.org/patch/7994/ t = (uint16_t) ((((*fefrequency / 1000) + uni_freq + 2) / 4) - 350); channel_byte_1 |= (((uint8_t) (t>> 8))& 0x03); channel_byte_2 = (uint8_t) (t& 0x00FF); if(t>1024) log_message( log_module, MSG_ERROR, "SCR/UNICABLE T out of range (is the Scr frequency valid ?) "); log_message( log_module, MSG_DEBUG, "Unicable tuning information : unicable freq %d lo_freq %d channel byte 0x%02x 0x%02x t 0x%02x", uni_freq, *fefrequency, channel_byte_1, channel_byte_2, t); cmd[0]->cmd.msg[3] = channel_byte_1; cmd[0]->cmd.msg[4] = channel_byte_2; //We rewrite the frontend frequency *fefrequency = uni_freq*1000UL; } cmd[0]->cmd.msg[5] = 0x00; cmd[0]->cmd.msg_len=4; if (switch_type=='N') cmd[0]->cmd.msg_len=5; log_message( log_module, MSG_DETAIL ,"Test Diseqc message %02x %02x %02x %02x %02x %02x len %d\n", cmd[0]->cmd.msg[0],cmd[0]->cmd.msg[1],cmd[0]->cmd.msg[2],cmd[0]->cmd.msg[3],cmd[0]->cmd.msg[4],cmd[0]->cmd.msg[5], cmd[0]->cmd.msg_len); ret = diseqc_send_msg(fd, lnb_voltage, cmd, hi_lo ? SEC_TONE_ON : SEC_TONE_OFF, (sat_no) % 2 ? SEC_MINI_B : SEC_MINI_A, diseqc_repeat, switch_type); if(ret) { log_message( log_module, MSG_WARN, "problem sending the DiseqC message or setting tone/voltage\n"); } free(cmd[0]); return ret; } else //only tone and voltage { if(ioctl(fd, FE_SET_VOLTAGE, lnb_voltage) < 0) { log_message( log_module, MSG_WARN, "problem to set the LNB voltage\n"); return -1; } if(ioctl(fd, FE_SET_TONE, (hi_lo ? SEC_TONE_ON : SEC_TONE_OFF)) < 0) { log_message( log_module, MSG_WARN, "problem to set the 22kHz tone\n"); return -1; } msleep(15); return 0; } } /** @brief Check the status of the card */ int check_status(int fd_frontend,int type,uint32_t lo_frequency, int display_strength) { int32_t strength; fe_status_t festatus; //We keep the old tuning compatibility just in case, as the new one should work it is done via the configure #if TUNE_OLD struct dvb_frontend_event event; struct pollfd pfd[1]; int status; pfd[0].fd = fd_frontend; pfd[0].events = POLLPRI; event.status=0; while (((event.status & FE_TIMEDOUT)==0) && ((event.status & FE_HAS_LOCK)==0)) { log_message( log_module, MSG_DETAIL, "polling....\n"); if (poll(pfd,1,5000) > 0){ if (pfd[0].revents & POLLPRI){ log_message( log_module, MSG_DETAIL, "Getting frontend event\n"); if ((status = ioctl(fd_frontend, FE_GET_EVENT, &event)) < 0){ if (errno != EOVERFLOW) { log_message( log_module, MSG_ERROR, "FE_GET_EVENT %s. status = %d\n", strerror(errno), status); return -1; } else log_message( log_module, MSG_WARN, "Overflow error, trying again (status = %d, errno = %d)\n", status, errno); } } print_status(event.status); } if(display_strength) { strength=0; if(ioctl(fd_frontend,FE_READ_SIGNAL_STRENGTH,&strength) >= 0) log_message( log_module, MSG_INFO, "Strength: %10d\n",strength); strength=0; if(ioctl(fd_frontend,FE_READ_SNR,&strength) >= 0) log_message( log_module, MSG_INFO, "SNR: %10d\n",strength); } } if (event.status & FE_HAS_LOCK) { switch(type) { case FE_OFDM: log_message( log_module, MSG_INFO, "Event: Frequency: %d\n",event.parameters.frequency); break; case FE_QPSK: log_message( log_module, MSG_INFO, "Event: Frequency: %d (or %d)\n",(unsigned int)((event.parameters.frequency)+lo_frequency),(unsigned int) abs((event.parameters.frequency)-lo_frequency)); log_message( log_module, MSG_INFO, " SymbolRate: %d\n",event.parameters.u.qpsk.symbol_rate); log_message( log_module, MSG_INFO, " FEC_inner: %d\n",event.parameters.u.qpsk.fec_inner); break; case FE_QAM: log_message( log_module, MSG_INFO, "Event: Frequency: %d\n",event.parameters.frequency); log_message( log_module, MSG_INFO, " SymbolRate: %d\n",event.parameters.u.qpsk.symbol_rate); log_message( log_module, MSG_INFO, " FEC_inner: %d\n",event.parameters.u.qpsk.fec_inner); break; #ifdef ATSC case FE_ATSC: log_message( log_module, MSG_INFO, "Event: Frequency: %d\n",event.parameters.frequency); break; #endif default: break; } strength=0; if(ioctl(fd_frontend,FE_READ_BER,&strength) >= 0) log_message( log_module, MSG_INFO, "Bit error rate: %d\n",strength); strength=0; if(ioctl(fd_frontend,FE_READ_SIGNAL_STRENGTH,&strength) >= 0) log_message( log_module, MSG_INFO, "Signal strength: %d\n",strength); strength=0; if(ioctl(fd_frontend,FE_READ_SNR,&strength) >= 0) log_message( log_module, MSG_INFO, "SNR: %d\n",strength); festatus=0; if(ioctl(fd_frontend,FE_READ_STATUS,&festatus) >= 0) print_status(festatus); } else { log_message( log_module, MSG_ERROR, "Not able to lock to the signal on the given frequency\n"); return -1; } #else struct dvb_frontend_parameters parameters; do { log_message( log_module, MSG_DETAIL, "polling....\n"); if (ioctl(fd_frontend, FE_READ_STATUS, &festatus) < 0){ if (errno == EINTR) { continue; } log_message( log_module, MSG_ERROR, "FE_READ_STATUS %s\n", strerror(errno)); return -1; } print_status(festatus); if(display_strength) { strength=0; if(ioctl(fd_frontend,FE_READ_SIGNAL_STRENGTH,&strength) >= 0) log_message( log_module, MSG_INFO, "Strength: %10d\n",strength); strength=0; if(ioctl(fd_frontend,FE_READ_SNR,&strength) >= 0) log_message( log_module, MSG_INFO, "SNR: %10d\n",strength); } sleep(1); } while ((festatus & (FE_TIMEDOUT|FE_HAS_LOCK))==0); if (festatus & FE_HAS_LOCK) { int status; do { status = ioctl(fd_frontend, FE_GET_FRONTEND, ¶meters); } while (status == -1 && errno == EINTR); if (status < 0) { log_message( log_module, MSG_ERROR, "FE_GET_FRONTEND %s\n", strerror(errno)); } else { switch(type) { case FE_OFDM: log_message( log_module, MSG_INFO, "Event: Frequency: %d\n",parameters.frequency); break; case FE_QPSK: log_message( log_module, MSG_INFO, "Event: Frequency: %d (or %d)\n",(unsigned int)((parameters.frequency)+lo_frequency),(unsigned int) abs((parameters.frequency)-lo_frequency)); log_message( log_module, MSG_INFO, " SymbolRate: %d\n",parameters.u.qpsk.symbol_rate); log_message( log_module, MSG_INFO, " FEC_inner: %d\n",parameters.u.qpsk.fec_inner); break; case FE_QAM: log_message( log_module, MSG_INFO, "Event: Frequency: %d\n",parameters.frequency); log_message( log_module, MSG_INFO, " SymbolRate: %d\n",parameters.u.qpsk.symbol_rate); log_message( log_module, MSG_INFO, " FEC_inner: %d\n",parameters.u.qpsk.fec_inner); break; #ifdef ATSC case FE_ATSC: log_message( log_module, MSG_INFO, "Event: Frequency: %d\n",parameters.frequency); break; #endif default: break; } } strength=0; if(ioctl(fd_frontend,FE_READ_BER,&strength) >= 0) log_message( log_module, MSG_INFO, "Bit error rate: %d\n",strength); strength=0; if(ioctl(fd_frontend,FE_READ_SIGNAL_STRENGTH,&strength) >= 0) log_message( log_module, MSG_INFO, "Signal strength: %d\n",strength); strength=0; if(ioctl(fd_frontend,FE_READ_SNR,&strength) >= 0) log_message( log_module, MSG_INFO, "SNR: %d\n",strength); } else { log_message( log_module, MSG_ERROR, "Not able to lock to the signal on the given frequency\n"); return -1; } #endif return 0; } /** @brief change the delivery subsystem * */ int change_delivery_system(fe_delivery_system_t delivery_system,int fd_frontend) { #if DVB_API_VERSION >= 5 log_message( log_module, MSG_WARN, "We ask the card to change the delivery system (multi frontend cards)."); struct dtv_property pclear[] = { { .cmd = DTV_CLEAR,}, }; struct dtv_properties cmdclear = { .num = 1, .props = pclear }; struct dtv_property dvb_deliv[1]; struct dtv_properties cmddeliv = { .num = 1, .props = dvb_deliv }; dvb_deliv[0].cmd = DTV_DELIVERY_SYSTEM; dvb_deliv[0].u.data = delivery_system; if ((ioctl(fd_frontend, FE_SET_PROPERTY, &cmdclear)) == -1) { log_message( log_module, MSG_ERROR,"FE_SET_PROPERTY clear failed : %s\n", strerror(errno)); set_interrupted(ERROR_TUNE<<8); return -1; } if ((ioctl(fd_frontend, FE_SET_PROPERTY, &cmddeliv)) == -1) { log_message( log_module, MSG_ERROR,"FE_SET_PROPERTY failed : %s\n", strerror(errno)); set_interrupted(ERROR_TUNE<<8); return -1; } return 0; #else return 0; #endif } /** @brief Tune the card * */ int tune_it(int fd_frontend, tune_p_t *tuneparams) { int res, hi_lo, dfd; struct dvb_frontend_parameters feparams; struct dvb_frontend_info fe_info; uint32_t lo_frequency=0; struct dvb_frontend_event event; int dvbt_bandwidth=0; //no warning memset(&feparams, 0, sizeof (struct dvb_frontend_parameters)); hi_lo = 0; if ( (res = ioctl(fd_frontend,FE_GET_INFO, &fe_info) < 0)){ log_message( log_module, MSG_ERROR, "FE_GET_INFO: %s \n", strerror(errno)); return -1; } /** @todo here check the capabilities of the card*/ log_message( log_module, MSG_INFO, "Using DVB card \"%s\" tuner %d\n",fe_info.name, tuneparams->tuner); // Save the frontend name for easy identification snprintf(tuneparams->fe_name, 256, "%s", fe_info.name); tuneparams->fe_type=fe_info.type; feparams.inversion=INVERSION_AUTO; // see if we need to change the frontend type. @todo : mix between DVB APIv3 and V5 #if DVB_API_VERSION >= 5 int change_deliv=0; switch(fe_info.type) { case FE_OFDM: //DVB-T if((tuneparams->delivery_system!=SYS_UNDEFINED)&&(tuneparams->delivery_system!=SYS_DVBT) #ifdef DVBT2 &&(tuneparams->delivery_system!=SYS_DVBT2)) #else ) #endif { log_message( log_module, MSG_WARN, "The delivery system does not fit with the card frontend type (DVB-T/T2)."); change_deliv=1; } break; case FE_QPSK: //DVB-S if((tuneparams->delivery_system!=SYS_UNDEFINED)&&(tuneparams->delivery_system!=SYS_DVBS)&&(tuneparams->delivery_system!=SYS_DVBS2)) { log_message( log_module, MSG_WARN, "The delivery system does not fit with the card frontend type (DVB-S).\n"); change_deliv=1; } break; case FE_QAM: //DVB-C if((tuneparams->delivery_system!=SYS_UNDEFINED)&&(tuneparams->delivery_system!=SYS_DVBC_ANNEX_AC)&&(tuneparams->delivery_system!=SYS_DVBC_ANNEX_B)) { log_message( log_module, MSG_WARN, "The delivery system does not fit with the card frontend type (DVB-C).\n"); change_deliv=1; } break; #ifdef ATSC case FE_ATSC: //ATSC if((tuneparams->delivery_system!=SYS_UNDEFINED)&&(tuneparams->delivery_system!=SYS_ATSC)) { log_message( log_module, MSG_WARN, "The delivery system does not fit with the card frontend type (ATSC).\n"); change_deliv=1; } break; #endif default: break; } if(change_deliv) //delivery system needs to be changed { if(change_delivery_system(tuneparams->delivery_system,fd_frontend)) return -1; //get new info if ( (res = ioctl(fd_frontend,FE_GET_INFO, &fe_info) < 0)){ log_message( log_module, MSG_ERROR, "FE_GET_INFO: %s \n", strerror(errno)); return -1; } // Save the frontend name for easy identification snprintf(tuneparams->fe_name, 256, "%s", fe_info.name); tuneparams->fe_type=fe_info.type; feparams.inversion=INVERSION_AUTO; } #endif switch(fe_info.type) { case FE_OFDM: //DVB-T if (tuneparams->freq < 1000000) tuneparams->freq*=1000UL; feparams.frequency=tuneparams->freq; feparams.u.ofdm.bandwidth=tuneparams->bandwidth; feparams.u.ofdm.code_rate_HP=tuneparams->HP_CodeRate; feparams.u.ofdm.code_rate_LP=tuneparams->LP_CodeRate; if(!tuneparams->modulation_set) tuneparams->modulation=MODULATION_DEFAULT; feparams.u.ofdm.constellation=tuneparams->modulation; feparams.u.ofdm.transmission_mode=tuneparams->TransmissionMode; feparams.u.ofdm.guard_interval=tuneparams->guardInterval; feparams.u.ofdm.hierarchy_information=tuneparams->hier; switch(tuneparams->bandwidth) { case BANDWIDTH_8_MHZ: dvbt_bandwidth=8000000; break; case BANDWIDTH_7_MHZ: dvbt_bandwidth=7000000; break; case BANDWIDTH_6_MHZ: dvbt_bandwidth=6000000; break; case BANDWIDTH_AUTO: default: dvbt_bandwidth=0; break; } log_message( log_module, MSG_INFO, "Tuning DVB-T to %d Hz, Bandwidth: %d\n", tuneparams->freq,dvbt_bandwidth); break; case FE_QPSK: //DVB-S if(!tuneparams->modulation_set) tuneparams->modulation=SAT_MODULATION_DEFAULT; //Universal lnb : two bands, hi and low one and two local oscilators if(tuneparams->lnb_type==LNB_UNIVERSAL) { if (tuneparams->freq < tuneparams->lnb_slof) { lo_frequency=tuneparams->lnb_lof_low; hi_lo = 0; } else { lo_frequency=tuneparams->lnb_lof_high; hi_lo = 1; } } //LNB_STANDARD one band and one local oscillator else if (tuneparams->lnb_type==LNB_STANDARD) { hi_lo=0; lo_frequency=tuneparams->lnb_lof_standard; } feparams.frequency=abs(tuneparams->freq-lo_frequency); log_message( log_module, MSG_INFO, "Tuning DVB-S to Freq: %u kHz, LO frequency %u kHz Pol:%c Srate=%d, LNB number: %d\n", feparams.frequency, lo_frequency, tuneparams->pol, tuneparams->srate, tuneparams->sat_number); feparams.u.qpsk.symbol_rate=tuneparams->srate; feparams.u.qpsk.fec_inner=tuneparams->HP_CodeRate; dfd = fd_frontend; //For diseqc vertical==circular right and horizontal == circular left if(do_diseqc( dfd, tuneparams->sat_number, tuneparams->switch_no, tuneparams->switch_type, (tuneparams->pol == 'V' ? 1 : 0) + (tuneparams->pol == 'R' ? 1 : 0), hi_lo, tuneparams->lnb_voltage_off, tuneparams->diseqc_repeat, &feparams.frequency, tuneparams->uni_freq) == 0) log_message( log_module, MSG_INFO, "DISEQC SETTING SUCCEDED\n"); else { log_message( log_module, MSG_WARN, "DISEQC SETTING FAILED\n"); return -1; } break; case FE_QAM: //DVB-C log_message( log_module, MSG_INFO, "tuning DVB-C to %d Hz, srate=%d\n",tuneparams->freq,tuneparams->srate); feparams.frequency=tuneparams->freq; feparams.inversion=INVERSION_OFF; feparams.u.qam.symbol_rate = tuneparams->srate; feparams.u.qam.fec_inner = tuneparams->HP_CodeRate; if(!tuneparams->modulation_set) tuneparams->modulation=MODULATION_DEFAULT; feparams.u.qam.modulation = tuneparams->modulation; break; #ifdef ATSC case FE_ATSC: //ATSC log_message( log_module, MSG_INFO, "tuning ATSC to %d Hz, modulation=%d\n",tuneparams->freq,tuneparams->modulation); feparams.frequency=tuneparams->freq; if(!tuneparams->modulation_set) tuneparams->modulation=ATSC_MODULATION_DEFAULT; feparams.u.vsb.modulation = tuneparams->modulation; break; #endif default: log_message( log_module, MSG_ERROR, "Unknown FE type : %x. Aborting\n", fe_info.type); set_interrupted(ERROR_TUNE<<8); return -1; } usleep(100000); /* The tuning of the card*/ while(1) { if (ioctl(fd_frontend, FE_GET_EVENT, &event) < 0) //EMPTY THE EVENT QUEUE break; } //If we support DVB API version 5 we check if the delivery system was defined #if DVB_API_VERSION >= 5 if(tuneparams->delivery_system==SYS_UNDEFINED) #else if(1) #endif { if (ioctl(fd_frontend,FE_SET_FRONTEND,&feparams) < 0) { log_message( log_module, MSG_ERROR, "ERROR tuning channel : %s \n", strerror(errno)); set_interrupted(ERROR_TUNE<<8); return -1; } } #if DVB_API_VERSION >= 5 else { /* Memo : S2API Commands DTV_UNDEFINED DTV_TUNE DTV_CLEAR DTV_FREQUENCY DTV_MODULATION DTV_BANDWIDTH_HZ DTV_INVERSION DTV_DISEQC_MASTER DTV_SYMBOL_RATE DTV_INNER_FEC DTV_VOLTAGE DTV_TONE DTV_PILOT DTV_ROLLOFF DTV_DISEQC_SLAVE_REPLY DTV_FE_CAPABILITY_COUNT DTV_FE_CAPABILITY DTV_DELIVERY_SYSTEM DTV_API_VERSION DTV_API_VERSION DTV_CODE_RATE_HP DTV_CODE_RATE_LP DTV_GUARD_INTERVAL DTV_TRANSMISSION_MODE DTV_HIERARCHY */ //DVB api version 5 and delivery system defined, we do DVB-API-5 tuning log_message( log_module, MSG_INFO, "Tuning With DVB-API version 5. delivery system : %d\n",tuneparams->delivery_system); #ifdef STREAM_ID int tune_stream_id; tune_stream_id = tuneparams->stream_id; if( tuneparams->pls_code ) tune_stream_id = tuneparams->stream_id+(256 * tuneparams->pls_code); if( tuneparams->pls_type == PLS_GOLD) tune_stream_id = tune_stream_id + pow( 2, (int) log2(tuneparams->pls_code)+10 ); log_message( log_module, MSG_INFO, "Stream_id = %d, stream id with PLS parameters %d",tuneparams->stream_id, tune_stream_id); #endif struct dtv_property pclear[] = { { .cmd = DTV_CLEAR,}, }; struct dtv_properties cmdclear = { .num = 1, .props = pclear }; struct dtv_properties *cmdseq; int commandnum =0; cmdseq = (struct dtv_properties*) calloc(1, sizeof(*cmdseq)); if (!cmdseq) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); return -1; } cmdseq->props = (struct dtv_property*) calloc(MAX_CMDSEQ_PROPS_NUM, sizeof(*(cmdseq->props))); if (!(cmdseq->props)) { free(cmdseq); log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); return -1; } if((tuneparams->delivery_system==SYS_DVBS)||(tuneparams->delivery_system==SYS_DVBS2)) { cmdseq->props[commandnum].cmd = DTV_DELIVERY_SYSTEM; cmdseq->props[commandnum++].u.data = tuneparams->delivery_system; cmdseq->props[commandnum].cmd = DTV_FREQUENCY; cmdseq->props[commandnum++].u.data = feparams.frequency; cmdseq->props[commandnum].cmd = DTV_MODULATION; cmdseq->props[commandnum++].u.data = tuneparams->modulation; cmdseq->props[commandnum].cmd = DTV_SYMBOL_RATE; cmdseq->props[commandnum++].u.data = tuneparams->srate; cmdseq->props[commandnum].cmd = DTV_INNER_FEC; cmdseq->props[commandnum++].u.data = tuneparams->HP_CodeRate; cmdseq->props[commandnum].cmd = DTV_INVERSION; cmdseq->props[commandnum++].u.data = INVERSION_AUTO; cmdseq->props[commandnum].cmd = DTV_ROLLOFF; cmdseq->props[commandnum++].u.data = tuneparams->rolloff; cmdseq->props[commandnum].cmd = DTV_PILOT; cmdseq->props[commandnum++].u.data = PILOT_AUTO; #ifdef STREAM_ID if(tuneparams->stream_id) { cmdseq->props[commandnum].cmd = DTV_STREAM_ID; cmdseq->props[commandnum++].u.data = tune_stream_id; } #endif cmdseq->props[commandnum++].cmd = DTV_TUNE; } else if((tuneparams->delivery_system==SYS_DVBT) #ifdef DVBT2 ||(tuneparams->delivery_system==SYS_DVBT2)) #else ) #endif { cmdseq->props[commandnum].cmd = DTV_DELIVERY_SYSTEM; cmdseq->props[commandnum++].u.data = tuneparams->delivery_system; cmdseq->props[commandnum].cmd = DTV_FREQUENCY; cmdseq->props[commandnum++].u.data = feparams.frequency; cmdseq->props[commandnum].cmd = DTV_BANDWIDTH_HZ; cmdseq->props[commandnum++].u.data = dvbt_bandwidth; cmdseq->props[commandnum].cmd = DTV_CODE_RATE_HP; cmdseq->props[commandnum++].u.data = tuneparams->HP_CodeRate; cmdseq->props[commandnum].cmd = DTV_CODE_RATE_LP; cmdseq->props[commandnum++].u.data = tuneparams->LP_CodeRate; cmdseq->props[commandnum].cmd = DTV_MODULATION; cmdseq->props[commandnum++].u.data = tuneparams->modulation; cmdseq->props[commandnum].cmd = DTV_GUARD_INTERVAL; cmdseq->props[commandnum++].u.data = tuneparams->guardInterval; cmdseq->props[commandnum].cmd = DTV_TRANSMISSION_MODE; cmdseq->props[commandnum++].u.data = tuneparams->TransmissionMode; cmdseq->props[commandnum].cmd = DTV_HIERARCHY; cmdseq->props[commandnum++].u.data = tuneparams->hier; #ifdef STREAM_ID if(tuneparams->stream_id) { cmdseq->props[commandnum].cmd = DTV_STREAM_ID; cmdseq->props[commandnum++].u.data = tune_stream_id; } #endif cmdseq->props[commandnum++].cmd = DTV_TUNE; } else if((tuneparams->delivery_system==SYS_DVBC_ANNEX_AC)||(tuneparams->delivery_system==SYS_DVBC_ANNEX_B)) { cmdseq->props[commandnum].cmd = DTV_DELIVERY_SYSTEM; cmdseq->props[commandnum++].u.data = tuneparams->delivery_system; cmdseq->props[commandnum].cmd = DTV_FREQUENCY; cmdseq->props[commandnum++].u.data = feparams.frequency; cmdseq->props[commandnum].cmd = DTV_MODULATION; cmdseq->props[commandnum++].u.data = tuneparams->modulation; cmdseq->props[commandnum].cmd = DTV_SYMBOL_RATE; cmdseq->props[commandnum++].u.data = tuneparams->srate; cmdseq->props[commandnum].cmd = DTV_INVERSION; cmdseq->props[commandnum++].u.data = INVERSION_OFF; cmdseq->props[commandnum].cmd = DTV_INNER_FEC; cmdseq->props[commandnum++].u.data = tuneparams->HP_CodeRate; cmdseq->props[commandnum++].cmd = DTV_TUNE; } else if(tuneparams->delivery_system==SYS_ATSC) { cmdseq->props[commandnum].cmd = DTV_DELIVERY_SYSTEM; cmdseq->props[commandnum++].u.data = tuneparams->delivery_system; cmdseq->props[commandnum].cmd = DTV_FREQUENCY; cmdseq->props[commandnum++].u.data = feparams.frequency; cmdseq->props[commandnum].cmd = DTV_MODULATION; cmdseq->props[commandnum++].u.data = tuneparams->modulation; cmdseq->props[commandnum++].cmd = DTV_TUNE; } else { log_message( log_module, MSG_ERROR, "Unsupported delivery system. Try tuning using DVB API 3 (do not set delivery_system). And please contact so it can be implemented.\n"); set_interrupted(ERROR_TUNE<<8); free(cmdseq); return -1; } cmdseq->num = commandnum; if ((ioctl(fd_frontend, FE_SET_PROPERTY, &cmdclear)) == -1) { log_message( log_module, MSG_ERROR,"FE_SET_PROPERTY clear failed : %s\n", strerror(errno)); set_interrupted(ERROR_TUNE<<8); free(cmdseq); return -1; } if ((ioctl(fd_frontend, FE_SET_PROPERTY, cmdseq)) == -1) { log_message( log_module, MSG_ERROR,"FE_SET_PROPERTY failed : %s\n", strerror(errno)); set_interrupted(ERROR_TUNE<<8); free(cmdseq); return -1; } free(cmdseq); } #endif return(check_status(fd_frontend,fe_info.type,lo_frequency,tuneparams->display_strenght)); } MuMuDVB-2.1.0/src/tune.h000066400000000000000000000132301305714132500146440ustar00rootroot00000000000000/* dvbtune - tune.c part of MuMuDVB last version availaible from http://mumudvb.braice.net/ Copyright (C) 2004-2010 Brice DUBOST Copyright (C) Dave Chapman 2001,2002 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Or, point your browser to http://www.gnu.org/copyleft/gpl.html */ /** @file * @brief Tuning of the dvb card * * This file contains the definition of the parameters for tuning the card */ #ifndef _TUNE_H #define _TUNE_H #include #include /* DVB-S */ /** lnb_slof: switch frequency of LNB */ #define DEFAULT_SLOF (11700*1000UL) /** lnb_lof1: local frequency of lower LNB band */ #define DEFAULT_LOF1_UNIVERSAL (9750*1000UL) /** lnb_lof2: local frequency of upper LNB band */ #define DEFAULT_LOF2_UNIVERSAL (10600*1000UL) /** Lnb standard Local oscillator frequency*/ #define DEFAULT_LOF_STANDARD (10750*1000UL) /* DVB-T DVB-C */ /* default option : full auto except bandwith = 8MHz*/ /* AUTO settings */ #define BANDWIDTH_DEFAULT BANDWIDTH_8_MHZ #define HP_CODERATE_DEFAULT FEC_AUTO #define MODULATION_DEFAULT QAM_AUTO #define SAT_MODULATION_DEFAULT QPSK #define TRANSMISSION_MODE_DEFAULT TRANSMISSION_MODE_AUTO #define GUARD_INTERVAL_DEFAULT GUARD_INTERVAL_AUTO #define HIERARCHY_DEFAULT HIERARCHY_NONE #if HIERARCHY_DEFAULT == HIERARCHY_NONE && !defined (LP_CODERATE_DEFAULT) #define LP_CODERATE_DEFAULT (FEC_NONE) /* unused if HIERARCHY_NONE */ #endif /* ATSC */ #define ATSC_MODULATION_DEFAULT VSB_8 /* The lnb type*/ #define LNB_UNIVERSAL 0 #define LNB_STANDARD 1 #if DVB_API_VERSION >= 5 #define MAX_CMDSEQ_PROPS_NUM 12 #endif /*Do we support stream_id ?*/ #undef STREAM_ID #if defined(DVB_API_VERSION_MINOR) #if DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 8 #define STREAM_ID 1 #endif #endif #if DVB_API_VERSION >= 6 #define STREAM_ID 1 #endif typedef enum pls_type { PLS_ROOT = 0x00, PLS_GOLD = 0x01, PLS_COMMON = 0x02, } pls_type_t; /** @brief Parameters for tuning the card*/ typedef struct tune_p_t{ /**The card number*/ int card; /**The tuner number*/ int tuner; /** The path of the card */ char card_dev_path[256]; /**Is the card actually tuned ?*/ int card_tuned; /**The timeout for tuninh the card*/ int tuning_timeout; /** the frequency (in MHz for dvb-s in kHz for dvb-t) */ uint32_t freq; /** The symbol rate (QPSK and QAM modulation ie cable and satellite) in symbols per second*/ unsigned int srate; /**The polarisation H, V, L or R (for satellite)*/ char pol; /**The lnb type : universal (two local oscilator frequencies), standard (one)*/ int lnb_type; /**The lo frequency (in kHz) for single LO LNB*/ uint32_t lnb_lof_standard; /**The lo switch frequency for dual LO LNB*/ uint32_t lnb_slof; /**The low LO frequency (in kHz) for dual LO LNB*/ uint32_t lnb_lof_low; /**The HIGH LO frequency (in kHz) for dual LO LNB*/ uint32_t lnb_lof_high; /** Do we force the lnb voltage to be 0 ? (in case the LNB have it's own power supply (satellite only))*/ int lnb_voltage_off; /**The satellite number ie the LNB number*/ unsigned char sat_number; /** The switch input */ int switch_no; /**The type of switch U uncommitted C committed*/ char switch_type; /** Do we repeat DiseQC messages ? */ int diseqc_repeat; /** The frequency for SCR/unicable */ uint32_t uni_freq; /** The kind of modulation */ fe_modulation_t modulation; int modulation_set; /** high priority stream code rate ie error correction, FEC */ fe_code_rate_t HP_CodeRate; /** low priority stream code rate * In order to achieve hierarchy, two different code rates may be applied to two different levels of the modulation.*/ fe_code_rate_t LP_CodeRate; /** For DVB-T */ fe_transmit_mode_t TransmissionMode; /** For DVB-T */ fe_guard_interval_t guardInterval; /**For DVB-T : the bandwith (often 8MHz)*/ fe_bandwidth_t bandwidth; /**For DVB-T It seems that it's related to the capability to transmit information in parallel Not configurable for the moment, I have found no transponder to test it*/ fe_hierarchy_t hier; /** do we periodically display the strenght of the signal ?*/ int display_strenght; /** do we periodically check the status of the card ?*/ int check_status; /**shutdown the thread for display strength */ volatile int strengththreadshutdown; /**The frontend type*/ fe_type_t fe_type; /** The frontend name */ char fe_name[256]; #if DVB_API_VERSION >= 5 /** DVB API version 5*/ /**Delivery system : DVB-S DVB-T etc ...*/ fe_delivery_system_t delivery_system; /** Rolloff (For DVB-S and DVB-S2)*/ fe_rolloff_t rolloff; #endif #if STREAM_ID /** The substream id */ int stream_id; /** The PLS code */ int pls_code; /** The PLS type */ pls_type_t pls_type; #endif /** If we read directly from a file */ char read_file_path[256]; }tune_p_t; void init_tune_v(tune_p_t *); int tune_it(int, tune_p_t *); int read_tuning_configuration(tune_p_t *, char *); void print_status(fe_status_t festatus); #endif MuMuDVB-2.1.0/src/unicast_EIT.c000066400000000000000000000440331305714132500160400ustar00rootroot00000000000000/* * unicast_EIT.c * * Created on: 22 juin 2014 * Author: braice */ #include "unicast_http.h" #include "unicast_queue.h" #include "mumudvb.h" #include "errors.h" #include "log.h" #include "dvb.h" #include "tune.h" #include "rewrite.h" #include "autoconf.h" #ifdef ENABLE_CAM_SUPPORT #include "cam.h" #endif #ifdef ENABLE_SCAM_SUPPORT #include "scam_capmt.h" #include "scam_common.h" #include "scam_getcw.h" #include "scam_decsa.h" #endif static char *log_module="Unicast : "; void eit_display_contents(mumudvb_ts_packet_t *full_eit, struct unicast_reply* reply); void unicast_send_EIT_section (mumudvb_ts_packet_t *eit_section, int num, struct unicast_reply* reply) { unicast_reply_write(reply, "\n{\n"); unicast_reply_write(reply, "\t\"number\" : %d,\n",num); eit_display_contents(eit_section, reply); unicast_reply_write(reply, "}"); } char *running_status_descr[] ={ "undefined", "not running", "starts in a few seconds", "pausing", "running", "service off-air", "reserved for future use", "reserved for future use", }; void eit_display_descriptor(unsigned char *buf,int descriptors_loop_len, struct unicast_reply* reply); void eit_show_short_evt_descr(unsigned char *buf, struct unicast_reply* reply); void eit_show_ext_evt_descr(unsigned char *buf, struct unicast_reply* reply); void eit_show_component_descr(unsigned char *buf, struct unicast_reply* reply); void eit_show_parent_rating_descr(unsigned char *buf, struct unicast_reply* reply); void eit_show_multiling_comp_descr(unsigned char *buf, struct unicast_reply* reply); void eit_show_content_descriptor(unsigned char *buf, struct unicast_reply* reply); void eit_show_CA_identifier_descriptor(unsigned char *buf, struct unicast_reply* reply); #define MAX_DESCR_LEN 4096 // This function convert an UTF8 string into a JSON valid string, escaping the control characters. // For the moment it works only with static memory allocation //todo can realloc void mumu_string_to_json(char *in, int lin, char *out, int lout) { int offin, offout; char c; char hex[5]; offin=0; offout=0; while((offin3) && ((lin-offin)>3) && ((in[offin+1] & 0xC0) == 0x80) ) //Two byte (>3 for including the final '\0') { out[offout]=in[offin]; offout++; offin++; out[offout]=in[offin]; offout++; offin++; } else if(((c & 0xF0) == 0xE0) && ((lout-offout)>4) && ((lin-offin)>4) && ((in[offin+1] & 0xC0) == 0x80) && ((in[offin+2] & 0xC0) == 0x80) ) //Three byte { out[offout]=in[offin]; offout++; offin++; out[offout]=in[offin]; offout++; offin++; out[offout]=in[offin]; offout++; offin++; } else if(((c & 0xF8) == 0xF0) && ((lout-offout)>5) && ((lin-offin)>5) && ((in[offin+1] & 0xC0) == 0x80) && ((in[offin+2] & 0xC0) == 0x80) && ((in[offin+3] & 0xC0) == 0x80) ) //four byte { out[offout]=in[offin]; offout++; offin++; out[offout]=in[offin]; offout++; offin++; out[offout]=in[offin]; offout++; offin++; out[offout]=in[offin]; offout++; offin++; } else //Middle of byte sequence or invalid sequence we don't copy offin++; } if(offoutdata_full); unicast_reply_write(reply, "\t\"length\" : %d,\n",full_eit->len_full); unicast_reply_write(reply, "\t\"table_id\" :%d,\n",eit->table_id); unicast_reply_write(reply, "\t\"section_length\" : %d,\n",HILO(eit->section_length)); unicast_reply_write(reply, "\t\"section_syntax_indicator\" :%d,\n",eit->section_syntax_indicator); unicast_reply_write(reply, "\t\"service_id\" :%d,\n",HILO(eit->service_id)); unicast_reply_write(reply, "\t\"current_next_indicator\" :%d,\n",eit->current_next_indicator); unicast_reply_write(reply, "\t\"version_number\" :%d,\n",eit->version_number); unicast_reply_write(reply, "\t\"section_number\" :%d,\n",eit->section_number); unicast_reply_write(reply, "\t\"last_section_number\" :%d,\n",eit->last_section_number); unicast_reply_write(reply, "\t\"transport_stream_id\" :%d,\n",HILO(eit->transport_stream_id)); unicast_reply_write(reply, "\t\"original_network_id\" :%d,\n",HILO(eit->original_network_id)); unicast_reply_write(reply, "\t\"segment_last_section_number\" :%d,\n",eit->segment_last_section_number); unicast_reply_write(reply, "\t\"segment_last_table_id\" :%d,\n",eit->segment_last_table_id); //Loop over different events in the EIT int len,delta,first; unsigned char *buf; eit_event_t *event_header; len=full_eit->len_full; buf=full_eit->data_full; delta=EIT_LEN; first=1; unicast_reply_write(reply, "\"EIT_events\":[\n"); while((len-delta)>=(4+EIT_EVENT_LEN)) { if(!first) unicast_reply_write(reply, ","); else first=0; unicast_reply_write(reply, "{\n"); event_header=(eit_event_t *)(buf + delta ); unicast_reply_write(reply, "\t\t\"event_id\" :%d,\n",HILO(event_header->event_id)); //Compute and display start time //compute day int MJD; MJD=(event_header->start_time_0<<8)+(event_header->start_time_1); //MJD=0xC079; //1993-10-13 //MJD=45218; //1993-10-13 int YY,MM,D,Y,M,K; //see annex C ETSI EN 300 468 YY=(int)((MJD-15078.2)/365.25); MM=(int)((MJD-14956.1-(int)(YY*365.25))/30.6001); D=MJD-14956-(int)(YY*365.25)-(int)(MM*30.6001); K=(MM==14 || MM==15)?1:0; Y=YY+K+1900; M=MM-1-K*12; unicast_reply_write(reply, "\t\t\"start_time day \" : \"%d-%02d-%02d (yy-mm-dd)\",\n", Y,M,D); //compute hours int hh,mm,ss; hh=(event_header->start_time_2>>4)*10+(event_header->start_time_2&0x0F); mm=(event_header->start_time_3>>4)*10+(event_header->start_time_3&0x0F); ss=(event_header->start_time_4>>4)*10+(event_header->start_time_4&0x0F); unicast_reply_write(reply, "\t\t\"start_time\" : \"%02d:%02d:%02d\",\n",hh,mm,ss); //Compute and display duration int dhh,dmm,dss; dhh=(event_header->duration_0>>4)*10+(event_header->duration_0&0x0F); dmm=(event_header->duration_1>>4)*10+(event_header->duration_1&0x0F); dss=(event_header->duration_2>>4)*10+(event_header->duration_2&0x0F); unicast_reply_write(reply, "\t\t\"duration\" : \"%02d:%02d:%02d\",\n",dhh,dmm,dss); unicast_reply_write(reply, "\t\t\"running_status\" :%d,\n",event_header->running_status); unicast_reply_write(reply, "\t\t\"running_status_descr\" : \"%s\",\n",running_status_descr[event_header->running_status]); unicast_reply_write(reply, "\t\t\"free_ca_mode\" :%d,\n",event_header->free_ca_mode); unicast_reply_write(reply, "\t\t\"descriptors_loop_length\" : %d,\n",HILO(event_header->descriptors_loop_length)); eit_display_descriptor(buf+delta+EIT_EVENT_LEN,HILO(event_header->descriptors_loop_length),reply); delta+=HILO(event_header->descriptors_loop_length)+EIT_EVENT_LEN; unicast_reply_write(reply, "}"); } unicast_reply_write(reply, "\n]\n"); } /** @brief Display the contents of an EIT descriptor * */ void eit_display_descriptor(unsigned char *buf,int descriptors_loop_len, struct unicast_reply* reply) { int first; first=1; int descriptor_len; unicast_reply_write(reply, "\"EIT_descriptors\":[\n"); while (descriptors_loop_len > 0) { unsigned char descriptor_tag = buf[0]; unsigned char descriptor_len_u8 = buf[1]; descriptor_len = ((int)descriptor_len_u8) + 2; if(!first) unicast_reply_write(reply, ","); else first=0; unicast_reply_write(reply, "\n{\n"); unicast_reply_write(reply, "\t\t\"tag\" :%d,\n",descriptor_tag); unicast_reply_write(reply, "\t\t\"len\" : %d", descriptor_len); if (!descriptor_len) { unicast_reply_write(reply, "\n}\n"); break; } //The service descriptor provides the names of the service provider and the service in text form together with the service_type. switch(descriptor_tag) { case 0x4d: unicast_reply_write(reply, ",\n\t\t\"descr\" : \"Short event descriptor\",\n"); unicast_reply_write(reply, "\t\t\"short_evt\":{\n"); eit_show_short_evt_descr(buf,reply); unicast_reply_write(reply, "}\n"); break; case 0x4e: unicast_reply_write(reply, ",\n\t\t\"descr\" : \"Extended event descriptor\",\n"); unicast_reply_write(reply, "\t\t\"ext_evt\":{\n"); eit_show_ext_evt_descr(buf,reply); unicast_reply_write(reply, "}\n"); break; case 0x4f: unicast_reply_write(reply, ",\n\t\t\"descr\" : \"Time shifted event descriptor\"\n"); break; case 0x50: unicast_reply_write(reply, ",\n\t\t\"descr\" : \"Component descriptor\",\n"); unicast_reply_write(reply, "\t\t\"component\":{\n"); eit_show_component_descr(buf,reply); unicast_reply_write(reply, "}\n"); break; case 0x53: unicast_reply_write(reply, ",\n\t\t\"descr\" : \"CA identifier descriptor\",\n"); unicast_reply_write(reply, "\t\t\"CA_identifier\":{\n"); eit_show_CA_identifier_descriptor(buf,reply); unicast_reply_write(reply, "}\n"); break; case 0x54: unicast_reply_write(reply, ",\n\t\t\"descr\" : \"Content descriptor (type of program cf tabl 28 EN 300 468 V1.13.1)\",\n"); unicast_reply_write(reply, "\t\t\"content\":{\n"); eit_show_content_descriptor(buf,reply); unicast_reply_write(reply, "}\n"); break; case 0x55: unicast_reply_write(reply, ",\n\t\t\"descr\" : \"Parental rating descriptor\",\n"); unicast_reply_write(reply, "\t\t\"parental_rating\":[\n"); eit_show_parent_rating_descr(buf,reply); unicast_reply_write(reply, "]\n"); break; case 0x57: unicast_reply_write(reply, ",\n\t\t\"descr\" : \"Telephone descriptor\"\n"); break; case 0x5E: unicast_reply_write(reply, ",\n\t\t\"descr\" : \"Multilingual component descriptor\",\n"); unicast_reply_write(reply, "\t\t\"multiling_component\":{\n"); eit_show_multiling_comp_descr(buf,reply); unicast_reply_write(reply, "}\n"); break; case 0x5F: unicast_reply_write(reply, ",\n\t\t\"descr\" : \"Private data specifier descriptor\"\n"); break; case 0x61: unicast_reply_write(reply, ",\n\t\t\"descr\" : \"Short smoothing buffer descriptor\"\n"); break; case 0x69: unicast_reply_write(reply, ",\n\t\t\"descr\" : \"PDC descriptor\"\n"); break; default: //0X42 0X4A 0X64 0X75 0X76 7D 7E 7F unicast_reply_write(reply, ",\n\t\t\"descr\" : \"Unknown descriptor\"\n"); break; } buf += descriptor_len; descriptors_loop_len -= descriptor_len; unicast_reply_write(reply, "}"); } unicast_reply_write(reply, "]\n"); } /** @brief : show the contents of the CA identifier descriptor * * @param buf : the buffer containing the descriptor */ void eit_show_CA_identifier_descriptor(unsigned char *buf, struct unicast_reply* reply) { int length,i,ca_id; unicast_reply_write(reply, "\t\t\"CA_system_id\":[\n"); length=buf[1]; buf+=2; int first = 1; for(i=0;i>4); unicast_reply_write(reply, "\t\t\"content_nibble_lvl_2\" :%d,\n",buf[2]&0xF); delta++; unicast_reply_write(reply, "\t\t\"user byte\" :%d\n",buf[delta]); } void eit_show_parent_rating_descr(unsigned char *buf, struct unicast_reply* reply) { int delta,length; delta=2; length=(buf[1]); while(length>0) { if (delta>2) unicast_reply_write(reply, ",\n"); unicast_reply_write(reply, "\t\t{\n\t\t\t\"language\" : \"%c%c%c\",\n",buf[0+delta],buf[1+delta],buf[2+delta]); delta+=3; if(buf[delta]==0) unicast_reply_write(reply, "\t\t\"rating\" : \"undefined\"\n"); else if(buf[delta]<=0X0F) unicast_reply_write(reply, "\t\t\"rating\" : \"minimum age %d\"\n",buf[delta]+3); else unicast_reply_write(reply, "\t\t\"rating\" : \"defined by broadcaster\"\n"); unicast_reply_write(reply, "\t\t}"); delta++; length-=4; } } void eit_show_multiling_comp_descr(unsigned char *buf, struct unicast_reply* reply) { char text[MAX_DESCR_LEN]; char text2[MAX_DESCR_LEN]; int delta=2; int length; int text_length; length=(buf[1])-1; unicast_reply_write(reply, "\t\t\"component_tag\" :%d,\n",buf[delta]); delta++; unicast_reply_write(reply, "\t\t\"components\":[\n"); int first = 1; while(length>0) { if(first) { unicast_reply_write(reply, "{\n"); first = 0; } else unicast_reply_write(reply, ",\n{\n"); unicast_reply_write(reply, "\t\t\"language\" : \"%c%c%c\",\n",buf[0+delta],buf[1+delta],buf[2+delta]); delta+=3; length-=4; text_length=buf[delta]; delta++; memcpy(text,buf+delta,text_length*sizeof(char)); text[text_length]='\0'; convert_en300468_string(text, MAX_DESCR_LEN,1);mumu_string_to_json(text,MAX_DESCR_LEN,text2,MAX_DESCR_LEN); unicast_reply_write(reply, "\t\t\"text\" : \"%s\"}", text); delta+=text_length; length-=text_length; } unicast_reply_write(reply, "]\n"); } void eit_show_short_evt_descr(unsigned char *buf, struct unicast_reply* reply) { int delta=2; unicast_reply_write(reply, "\t\t\"language\" : \"%c%c%c\",\n",buf[0+delta],buf[1+delta],buf[2+delta]); delta+=3; char text[MAX_DESCR_LEN]; char text2[MAX_DESCR_LEN]; int text_length; text_length=buf[delta]&0xff; delta++; memcpy(text,buf+delta,text_length*sizeof(char)); text[text_length]='\0'; convert_en300468_string(text, MAX_DESCR_LEN,1);mumu_string_to_json(text,MAX_DESCR_LEN,text2,MAX_DESCR_LEN); unicast_reply_write(reply, "\t\t\"name\" : \"%s\",\n", text2); delta+=text_length; text_length=buf[delta]&0xff; delta++; memcpy(text,buf+delta,text_length*sizeof(char)); text[text_length]='\0'; convert_en300468_string(text, MAX_DESCR_LEN,1);mumu_string_to_json(text,MAX_DESCR_LEN,text2,MAX_DESCR_LEN); unicast_reply_write(reply, "\t\t\"text\" : \"%s\"\n", text2); } void eit_show_ext_evt_descr(unsigned char *buf, struct unicast_reply* reply) { int delta; delta=2; unicast_reply_write(reply, "\t\t\"descr_number\" : %d ,\n",(buf[delta]>>4)+1); unicast_reply_write(reply, "\t\t\"descr_total_number\" : %d,\n",(buf[delta]&0xF)+1); delta++; unicast_reply_write(reply, "\t\t\"language\" : \"%c%c%c\",\n",buf[0+delta],buf[1+delta],buf[2+delta]); delta+=3; int length_of_items,item_description_length,item_length,text_length; length_of_items=buf[delta]&0xff; delta++; char text[MAX_DESCR_LEN]; char text2[MAX_DESCR_LEN]; unicast_reply_write(reply, "\t\t\"items\":["); int first = 1; while(length_of_items>0) { if(first) { unicast_reply_write(reply, "{\n"); first = 0; } else unicast_reply_write(reply, ",\n{\n"); item_description_length=buf[delta]&0xff; delta++; memcpy(text,buf+delta,item_description_length*sizeof(char)); text[item_description_length]='\0'; convert_en300468_string(text, MAX_DESCR_LEN,1);mumu_string_to_json(text,MAX_DESCR_LEN,text2,MAX_DESCR_LEN); unicast_reply_write(reply, "\t\t\"item_descr\" : \"%s\",\n", text2); delta+=item_description_length; item_length=buf[delta]&0xff; delta++; memcpy(text,buf+delta,item_length*sizeof(char)); text[item_length]='\0'; convert_en300468_string(text, MAX_DESCR_LEN,1);mumu_string_to_json(text,MAX_DESCR_LEN,text2,MAX_DESCR_LEN); unicast_reply_write(reply, "\t\t\"item\" : \"%s\"}\n", text2); delta+=item_length; length_of_items-=(2+item_description_length+item_length); } unicast_reply_write(reply, "],\n"); text_length=buf[delta]&0xff; delta++; memcpy(text,buf+delta,text_length*sizeof(char)); text[text_length]='\0'; convert_en300468_string(text, MAX_DESCR_LEN,1);mumu_string_to_json(text,MAX_DESCR_LEN,text2,MAX_DESCR_LEN); unicast_reply_write(reply, "\t\t\"text\": \"%s\"\n", text2); } void eit_show_component_descr(unsigned char *buf, struct unicast_reply* reply) { int delta; delta=2; unicast_reply_write(reply, "\t\t\"len\" : %d",buf[1]&0xff); if((buf[1]&0xff)>5) { unicast_reply_write(reply, ",\n"); //stream_content // see EN 300 468 V1.13.1 table 26 unicast_reply_write(reply, "\t\t\"stream_content\" :%d,\n", buf[delta]&0x0F); delta++; // see EN 300 468 V1.13.1 table 26 unicast_reply_write(reply, "\t\t\"component_type\" :%d,\n", buf[delta]); delta++; unicast_reply_write(reply, "\t\t\"component_tag\" :%d,\n", buf[delta]); delta++; unicast_reply_write(reply, "\t\t\"language\" : \"%c%c%c\",\n",buf[0+delta],buf[1+delta],buf[2+delta]); delta+=3; int text_length; char text[MAX_DESCR_LEN]; char text2[MAX_DESCR_LEN]; text_length=(buf[1])-5; memcpy(text,buf+delta,text_length*sizeof(char)); text[text_length]='\0'; convert_en300468_string(text, MAX_DESCR_LEN,1);mumu_string_to_json(text,MAX_DESCR_LEN,text2,MAX_DESCR_LEN); unicast_reply_write(reply, "\t\t\"text\" : \"%s\"\n", text2); } else unicast_reply_write(reply, "\n"); } MuMuDVB-2.1.0/src/unicast_clients.c000066400000000000000000000164751305714132500170710ustar00rootroot00000000000000/* * MuMuDVB - UDP-ize a DVB transport stream. * * (C) 2009 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** @file * @brief File for HTTP unicast clients * @author Brice DUBOST * @date 2009 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "unicast_http.h" #include "unicast_queue.h" #include "mumudvb.h" #include "errors.h" #include "log.h" static char *log_module="Unicast : "; /** @brief Add a client to the chained list of clients * Will allocate the memory and fill the structure * * @param unicast_vars the unicast parameters * @param SocketAddr The socket address * @param Socket The socket number */ unicast_client_t *unicast_add_client(unicast_parameters_t *unicast_vars, struct sockaddr_in SocketAddr, int Socket) { unicast_client_t *client; unicast_client_t *prev_client; log_message( log_module, MSG_FLOOD,"We create a client associated with the socket %d\n",Socket); //We allocate a new client if(unicast_vars->clients==NULL) { log_message( log_module, MSG_FLOOD,"first client\n"); client=unicast_vars->clients=malloc(sizeof(unicast_client_t)); prev_client=NULL; } else { log_message( log_module, MSG_FLOOD,"there is already clients\n"); client=unicast_vars->clients; while(client->next!=NULL) client=client->next; client->next=malloc(sizeof(unicast_client_t)); prev_client=client; client=client->next; } if(client==NULL) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); close(Socket); return NULL; } // Disable the Nagle (TCP No Delay) algorithm int iRet; int on = 1; iRet=setsockopt(Socket, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)); if (iRet < 0) { log_message( log_module, MSG_WARN,"setsockopt TCP_NODELAY failed : %s\n", strerror(errno)); } int buffer_size; socklen_t size; size=sizeof(buffer_size); iRet=getsockopt( Socket, SOL_SOCKET, SO_SNDBUF, &buffer_size, &size); if (iRet < 0) { log_message( log_module, MSG_WARN,"get SO_SNDBUF failed : %s\n", strerror(errno)); } else log_message( log_module, MSG_FLOOD,"Actual SO_SNDBUF size : %d\n", buffer_size); if(unicast_vars->socket_sendbuf_size) { buffer_size = unicast_vars->socket_sendbuf_size; iRet=setsockopt(Socket, SOL_SOCKET, SO_SNDBUF, &buffer_size, sizeof(buffer_size)); if (iRet < 0) { log_message( log_module, MSG_WARN,"setsockopt SO_SNDBUF failed : %s\n", strerror(errno)); } else { size=sizeof(buffer_size); iRet=getsockopt( Socket, SOL_SOCKET, SO_SNDBUF, &buffer_size, &size); if (iRet < 0) log_message( log_module, MSG_WARN,"2nd get SO_SNDBUF failed : %s\n", strerror(errno)); else log_message( log_module, MSG_DETAIL,"New SO_SNDBUF size : %d\n", buffer_size); } } //We fill the client data client->SocketAddr=SocketAddr; client->Socket=Socket; client->buffer=NULL; client->buffersize=0; client->bufferpos=0; client->chan_ptr=NULL; client->askedChannel=-1; client->consecutive_errors=0; client->next=NULL; client->prev=prev_client; client->chan_next=NULL; client->chan_prev=NULL; //We init the queue client->queue.data_bytes_in_queue=0; client->queue.packets_in_queue=0; client->queue.first=NULL; client->queue.last=NULL; unicast_vars->client_number++; return client; } /** @brief Delete a client to the chained list of clients and in the associated channel * This function close the socket of the client * remove it from the associated channel if there is one * and free the memory of the client (including the buffer) * * @param unicast_vars the unicast parameters * @param client the client we want to delete */ int unicast_del_client(unicast_parameters_t *unicast_vars, unicast_client_t *client) { unicast_client_t *prev_client,*next_client; log_message( log_module, MSG_FLOOD,"We delete the client %s:%d, socket %d\n",inet_ntoa(client->SocketAddr.sin_addr), client->SocketAddr.sin_port, client->Socket); if (client->Socket >= 0) { close(client->Socket); } prev_client=client->prev; next_client=client->next; if(prev_client==NULL) { log_message( log_module, MSG_FLOOD,"We delete the first client\n"); unicast_vars->clients=client->next; } else prev_client->next=client->next; if(next_client) next_client->prev=prev_client; //We delete the client in the channel if(client->chan_ptr!=NULL) { log_message( log_module, MSG_DEBUG,"We remove the client from the channel \"%s\"\n",client->chan_ptr->name); // decrement the number of client connections client->chan_ptr->num_clients--; if(client->chan_prev==NULL) { client->chan_ptr->clients=client->chan_next; if(client->chan_ptr->clients) client->chan_ptr->clients->chan_prev=NULL; } else { client->chan_prev->chan_next=client->chan_next; if(client->chan_next) client->chan_next->chan_prev=client->chan_prev; } } if(client->buffer) free(client->buffer); unicast_queue_clear(&client->queue); free(client); unicast_vars->client_number--; return 0; } /** @brief This function add an unicast client to a channel * * @param client the client * @param channel the channel */ int channel_add_unicast_client(unicast_client_t *client,mumudvb_channel_t *channel) { unicast_client_t *last_client; int iRet; log_message( log_module, MSG_INFO,"We add the client %s:%d to the channel \"%s\"\n",inet_ntoa(client->SocketAddr.sin_addr), client->SocketAddr.sin_port,channel->name); iRet=write(client->Socket,HTTP_OK_REPLY, strlen(HTTP_OK_REPLY)); if(iRet!=strlen(HTTP_OK_REPLY)) { log_message( log_module, MSG_INFO,"Error when sending the HTTP reply\n"); return -1; } client->chan_next=NULL; // Increment the number of client connections channel->num_clients++; if(channel->clients==NULL) { channel->clients=client; client->chan_prev=NULL; } else { last_client=channel->clients; while(last_client->chan_next!=NULL) last_client=last_client->chan_next; last_client->chan_next=client; client->chan_prev=last_client; } return 0; } /** @brief Delete all the clients * * @param unicast_vars the unicast parameters */ void unicast_freeing(unicast_parameters_t *unicast_vars) { unicast_client_t *actual_client; unicast_client_t *next_client; for(actual_client=unicast_vars->clients; actual_client != NULL; actual_client=next_client) { next_client= actual_client->next; unicast_del_client(unicast_vars, actual_client); } } MuMuDVB-2.1.0/src/unicast_http.c000066400000000000000000001362121305714132500163770ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * * (C) 2009-2013 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** @file * @brief File for HTTP unicast * @author Brice DUBOST * @date 2009-2013 */ //in order to use asprintf (extension gnu) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "unicast_http.h" #include "unicast_queue.h" #include "mumudvb.h" #include "errors.h" #include "log.h" #include "dvb.h" #include "tune.h" #include "autoconf.h" #include "rewrite.h" #ifdef ENABLE_CAM_SUPPORT #include "cam.h" #endif #ifdef ENABLE_SCAM_SUPPORT #include "scam_capmt.h" #include "scam_common.h" #include "scam_getcw.h" #include "scam_decsa.h" #endif static char *log_module="Unicast : "; //from unicast_client.c unicast_client_t *unicast_add_client(unicast_parameters_t *unicast_vars, struct sockaddr_in SocketAddr, int Socket); int channel_add_unicast_client(unicast_client_t *client,mumudvb_channel_t *channel); unicast_client_t *unicast_accept_connection(unicast_parameters_t *unicast_vars, int socketIn); void unicast_close_connection(unicast_parameters_t *unicast_vars, int Socket); int unicast_send_streamed_channels_list (int number_of_channels, mumudvb_channel_t *channels, int Socket, char *host); int unicast_send_index_page (int Socket); int unicast_send_play_list_unicast (int number_of_channels, mumudvb_channel_t *channels, int Socket, int unicast_portOut, int perport, unicast_parameters_t *unicast_vars); int unicast_send_play_list_multicast (int number_of_channels, mumudvb_channel_t* channels, int Socket, int vlc, unicast_parameters_t *unicast_vars); int unicast_send_streamed_channels_list_js (int number_of_channels, mumudvb_channel_t *channels, void* cam_p_v, int Socket); int unicast_send_signal_power_js (int Socket, strength_parameters_t *strengthparams); int unicast_send_channel_traffic_js (int number_of_channels, mumudvb_channel_t *channels, int Socket); int unicast_send_json_state (int number_of_channels, mumudvb_channel_t* channels, int Socket, strength_parameters_t* strengthparams, auto_p_t* auto_p, void* cam_p_v, void* scam_vars_v); int unicast_send_xml_state (int number_of_channels, mumudvb_channel_t* channels, int Socket, strength_parameters_t* strengthparams, auto_p_t* auto_p, void* cam_p_v, void* scam_vars_v); int unicast_send_cam_menu (int Socket, void *cam_p); int unicast_send_cam_action (int Socket, char *Key, void *cam_p); int unicast_send_EIT (eit_packet_t *eit_packets, int Socket); int unicast_handle_message(unicast_parameters_t* unicast_vars, unicast_client_t* client, mumudvb_channel_t* channels, int number_of_channels, strength_parameters_t* strengthparams, auto_p_t* auto_p, void* cam_p, void* scam_vars, eit_packet_t *eit_packets); #define REPLY_HEADER 0 #define REPLY_BODY 1 #define REPLY_SIZE_STEP 256 /** Initialize unicast variables*/ void init_unicast_v(unicast_parameters_t *unicast_vars) { memset(unicast_vars,0,sizeof(unicast_parameters_t)); *unicast_vars=(unicast_parameters_t){ .unicast=0, .ipOut="0.0.0.0", .portOut=4242, .portOut_str=NULL, .consecutive_errors_timeout=UNICAST_CONSECUTIVE_ERROR_TIMEOUT, .max_clients=-1, .queue_max_size=UNICAST_DEFAULT_QUEUE_MAX, .socket_sendbuf_size=0, .flush_on_eagain=0, .pfdsnum=0, .playlist_ignore_dead=0, }; unicast_vars->pfds=NULL; //+1 for closing the pfd list, see man poll unicast_vars->pfds=malloc(sizeof(struct pollfd)); if (unicast_vars->pfds==NULL) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); set_interrupted(ERROR_MEMORY<<8); return; } unicast_vars->pfds[0].fd = 0; unicast_vars->pfds[0].events = POLLIN | POLLPRI; unicast_vars->pfds[0].revents = 0; } /** @brief Read a line of the configuration file to check if there is a unicast parameter * * @param unicast_vars the unicast parameters * @param substring The currrent line */ int read_unicast_configuration(unicast_parameters_t *unicast_vars, mumudvb_channel_t *c_chan, char *substring) { char delimiteurs[] = CONFIG_FILE_SEPARATOR; if (!strcmp (substring, "ip_http")) { substring = strtok (NULL, delimiteurs); if(strlen(substring)>19) { log_message( log_module, MSG_ERROR, "The Ip address %s is too long.\n", substring); exit(ERROR_CONF); } sscanf (substring, "%s\n", unicast_vars->ipOut); if(unicast_vars->ipOut[0]!='\0') { if(unicast_vars->unicast==0) { log_message( log_module, MSG_WARN,"You should use the option \"unicast=1\" before to activate unicast instead of ip_http\n"); unicast_vars->unicast=1; } } } else if (!strcmp (substring, "unicast")) { substring = strtok (NULL, delimiteurs); unicast_vars->unicast = atoi (substring); } else if (!strcmp (substring, "unicast_consecutive_errors_timeout")) { substring = strtok (NULL, delimiteurs); unicast_vars->consecutive_errors_timeout = atoi (substring); if(unicast_vars->consecutive_errors_timeout<=0) log_message( log_module, MSG_WARN, "Warning : You have deactivated the unicast timeout for disconnecting clients, this can lead to an accumulation of zombie clients, this is unadvised, prefer a long timeout\n"); } else if (!strcmp (substring, "unicast_max_clients")) { substring = strtok (NULL, delimiteurs); unicast_vars->max_clients = atoi (substring); } else if (!strcmp (substring, "unicast_queue_size")) { substring = strtok (NULL, delimiteurs); unicast_vars->queue_max_size = atoi (substring); } else if (!strcmp (substring, "port_http")) { substring = strtok (NULL, "="); // next we replace all the spaces as too many spaces are messing with the further parsing // like: " port_http = 2000 + %card" int len = strlen(substring)+1; substring = mumu_string_replace(substring, &len, 1, " ", ""); // if the string is empty after the replacement, we need to tokenize one more time to get the actual setting if (strlen(substring) == 0) { substring = strtok(NULL, "="); } if((strchr(substring,'*')!=NULL)||(strchr(substring,'+')!=NULL)||(strchr(substring,'%')!=NULL)) { unicast_vars->portOut_str=malloc(sizeof(char)*(strlen(substring)+1)); strcpy(unicast_vars->portOut_str,substring); } else unicast_vars->portOut = atoi (substring); } else if (!strcmp (substring, "unicast_port")) { if ( c_chan == NULL ) { log_message( log_module, MSG_ERROR, "unicast_port : You have to start a channel first (using new_channel)\n"); exit(ERROR_CONF); } substring = strtok (NULL, delimiteurs); c_chan->unicast_port = atoi (substring); MU_F(c_chan->unicast_port) = F_USER; } else if (!strcmp (substring, "socket_sendbuf_size")) { substring = strtok (NULL, delimiteurs); unicast_vars->socket_sendbuf_size = atoi (substring); } else if (!strcmp (substring, "flush_on_eagain")) { substring = strtok (NULL, delimiteurs); unicast_vars->flush_on_eagain = atoi (substring); if(unicast_vars->flush_on_eagain) log_message( log_module, MSG_INFO, "The unicast data WILL be dropped on eagain errors\n"); } else if (!strcmp (substring, "playlist_ignore_dead")) { substring = strtok (NULL, delimiteurs); unicast_vars->playlist_ignore_dead = atoi (substring); } else return 0; //Nothing concerning tuning, we return 0 to explore the other possibilities return 1;//We found something for tuning, we tell main to go for the next line } /** @brief Create a listening socket and add it to the list of polling file descriptors if success * * * */ int unicast_create_listening_socket(int socket_type, int socket_channel, char *ipOut, int port, struct sockaddr_in *sIn, int *socketIn, unicast_parameters_t *unicast_vars) { *socketIn= makeTCPclientsocket(ipOut, port, sIn); //We add them to the poll descriptors if(*socketIn>0) { unicast_vars->pfdsnum++; log_message( log_module, MSG_DEBUG, "unicast : unicast_vars->pfdsnum : %d\n", unicast_vars->pfdsnum); unicast_vars->pfds=realloc(unicast_vars->pfds,(unicast_vars->pfdsnum+1)*sizeof(struct pollfd)); if (unicast_vars->pfds==NULL) { log_message( log_module, MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); return -1; } unicast_vars->pfds[unicast_vars->pfdsnum-1].fd = *socketIn; unicast_vars->pfds[unicast_vars->pfdsnum-1].events = POLLIN | POLLPRI; unicast_vars->pfds[unicast_vars->pfdsnum-1].revents = 0; unicast_vars->pfds[unicast_vars->pfdsnum].fd = 0; unicast_vars->pfds[unicast_vars->pfdsnum].events = POLLIN | POLLPRI; unicast_vars->pfds[unicast_vars->pfdsnum].revents = 0; //Information about the descriptor unicast_vars->fd_info=realloc(unicast_vars->fd_info,(unicast_vars->pfdsnum)*sizeof(unicast_fd_info_t)); if (unicast_vars->fd_info==NULL) { log_message( log_module, MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); return -1; } //Master connection unicast_vars->fd_info[unicast_vars->pfdsnum-1].type=socket_type; unicast_vars->fd_info[unicast_vars->pfdsnum-1].channel=socket_channel; unicast_vars->fd_info[unicast_vars->pfdsnum-1].client=NULL; } else { log_message( log_module, MSG_WARN, "Problem creating the socket %s:%d : %s\n",ipOut,port,strerror(errno) ); return -1; } return 0; } /** @brief Handle an "event" on the unicast file descriptors * If the event is on an already open client connection, it handle the message * If the event is on the master connection, it accepts the new connection * If the event is on a channel specific socket, it accepts the new connection and starts streaming * */ int unicast_handle_fd_event(unicast_parameters_t *unicast_vars, mumudvb_channel_t *channels, int number_of_channels, strength_parameters_t *strengthparams, auto_p_t *auto_p, void *cam_p, void *scam_vars, eit_packet_t *eit_packets) { int iRet; //We look what happened for which connection int actual_fd; for(actual_fd=0;actual_fdpfdsnum;actual_fd++) { iRet=0; if(((unicast_vars->pfds[actual_fd].revents&POLLHUP)||(unicast_vars->pfds[actual_fd].revents&POLLERR)) &&(unicast_vars->fd_info[actual_fd].type==UNICAST_CLIENT)) { log_message( log_module, MSG_DEBUG,"We've got a POLLHUP or POLLERR. Actual_fd %d socket %d we close the connection \n", actual_fd, unicast_vars->pfds[actual_fd].fd ); unicast_close_connection(unicast_vars,unicast_vars->pfds[actual_fd].fd); //We check if we have to parse unicast_vars->pfds[actual_fd].revents (the last fd moved to the actual one) if(unicast_vars->pfds[actual_fd].revents) actual_fd--;//Yes, we force the loop to see it } if((unicast_vars->pfds[actual_fd].revents&POLLIN)||(unicast_vars->pfds[actual_fd].revents&POLLPRI)) { if((unicast_vars->fd_info[actual_fd].type==UNICAST_MASTER)|| (unicast_vars->fd_info[actual_fd].type==UNICAST_LISTEN_CHANNEL)) { //Event on the master connection or listening channel //New connection, we accept the connection log_message( log_module, MSG_FLOOD,"New client\n"); int tempSocket; unicast_client_t *tempClient; //we accept the incoming connection tempClient=unicast_accept_connection(unicast_vars, unicast_vars->pfds[actual_fd].fd); if(tempClient!=NULL) { tempSocket=tempClient->Socket; unicast_vars->pfdsnum++; unicast_vars->pfds=realloc(unicast_vars->pfds,(unicast_vars->pfdsnum+1)*sizeof(struct pollfd)); if (unicast_vars->pfds==NULL) { log_message( log_module, MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); set_interrupted(ERROR_MEMORY<<8); return -1; } //We poll the new socket unicast_vars->pfds[unicast_vars->pfdsnum-1].fd = tempSocket; unicast_vars->pfds[unicast_vars->pfdsnum-1].events = POLLIN | POLLPRI | POLLHUP | POLLERR; //We also poll the deconnections unicast_vars->pfds[unicast_vars->pfdsnum-1].revents = 0; unicast_vars->pfds[unicast_vars->pfdsnum].fd = 0; unicast_vars->pfds[unicast_vars->pfdsnum].events = POLLIN | POLLPRI; unicast_vars->pfds[unicast_vars->pfdsnum].revents = 0; //Information about the descriptor unicast_vars->fd_info=realloc(unicast_vars->fd_info,(unicast_vars->pfdsnum)*sizeof(unicast_fd_info_t)); if (unicast_vars->fd_info==NULL) { log_message( log_module, MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); set_interrupted(ERROR_MEMORY<<8); return -1; } //client connection unicast_vars->fd_info[unicast_vars->pfdsnum-1].type=UNICAST_CLIENT; unicast_vars->fd_info[unicast_vars->pfdsnum-1].channel=-1; unicast_vars->fd_info[unicast_vars->pfdsnum-1].client=tempClient; log_message( log_module, MSG_FLOOD,"Number of clients : %d\n", unicast_vars->client_number); if(unicast_vars->fd_info[actual_fd].type==UNICAST_LISTEN_CHANNEL) { //Event on a channel connection, we open a new socket for this client and //we store the wanted channel for when we will get the GET log_message( log_module, MSG_DEBUG,"Connection on a channel socket the client will get the channel %d\n", unicast_vars->fd_info[actual_fd].channel); tempClient->askedChannel=unicast_vars->fd_info[actual_fd].channel; } } } else if(unicast_vars->fd_info[actual_fd].type==UNICAST_CLIENT) { //Event on a client connection i.e. the client asked something log_message( log_module, MSG_FLOOD,"New message for socket %d\n", unicast_vars->pfds[actual_fd].fd); iRet=unicast_handle_message(unicast_vars,unicast_vars->fd_info[actual_fd].client, channels, number_of_channels, strengthparams, auto_p, cam_p, scam_vars,eit_packets); if (iRet==-2 ) //iRet==-2 --> 0 received data or error, we close the connection { unicast_close_connection(unicast_vars,unicast_vars->pfds[actual_fd].fd); //We check if we have to parse unicast_vars->pfds[actual_fd].revents (the last fd moved to the actual one) if(unicast_vars->pfds[actual_fd].revents) actual_fd--;//Yes, we force the loop to see it again } } else { log_message( log_module, MSG_WARN,"File descriptor with bad type, please contact\n Debug information : actual_fd %d unicast_vars->fd_info[actual_fd].type %d\n", actual_fd, unicast_vars->fd_info[actual_fd].type); } } } return 0; } /** @brief Accept an incoming connection * * * @param unicast_vars the unicast parameters * @param socketIn the socket on wich the connection was made */ unicast_client_t *unicast_accept_connection(unicast_parameters_t *unicast_vars, int socketIn) { unsigned int l; int tempSocket,iRet; unicast_client_t *tempClient; struct sockaddr_in tempSocketAddrIn; l = sizeof(struct sockaddr); tempSocket = accept(socketIn, (struct sockaddr *) &tempSocketAddrIn, &l); if (tempSocket < 0 ) { log_message( log_module, MSG_WARN,"Error when accepting the incoming connection : %s\n", strerror(errno)); return NULL; } struct sockaddr_in tempSocketAddr; l = sizeof(struct sockaddr); iRet=getsockname(tempSocket, (struct sockaddr *) &tempSocketAddr, &l); if (iRet < 0) { log_message( log_module, MSG_ERROR,"getsockname failed : %s while accepting incoming connection", strerror(errno)); close(tempSocket); return NULL; } log_message( log_module, MSG_FLOOD,"New connection from %s:%d to %s:%d \n",inet_ntoa(tempSocketAddrIn.sin_addr), tempSocketAddrIn.sin_port,inet_ntoa(tempSocketAddr.sin_addr), tempSocketAddr.sin_port); //Now we set this socket to be non blocking because we poll it int flags; flags = fcntl(tempSocket, F_GETFL, 0); flags |= O_NONBLOCK; if (fcntl(tempSocket, F_SETFL, flags) < 0) { log_message( log_module, MSG_ERROR,"Set non blocking failed : %s\n",strerror(errno)); close(tempSocket); return NULL; } /* if the maximum number of clients is reached, raise a temporary error*/ if((unicast_vars->max_clients>0)&&(unicast_vars->client_number>=unicast_vars->max_clients)) { int iRet; log_message( log_module, MSG_INFO,"Too many clients connected, we raise an error to %s\n", inet_ntoa(tempSocketAddrIn.sin_addr)); iRet=write(tempSocket,HTTP_503_REPLY, strlen(HTTP_503_REPLY)); if(iRet<0) log_message( log_module, MSG_INFO,"Error writing to %s\n", inet_ntoa(tempSocketAddrIn.sin_addr)); close(tempSocket); return NULL; } tempClient=unicast_add_client(unicast_vars, tempSocketAddrIn, tempSocket); return tempClient; } /** @brief Close an unicast connection and delete the client * * @param unicast_vars the unicast parameters * @param fds The polling file descriptors * @param Socket The socket of the client we want to disconnect */ void unicast_close_connection(unicast_parameters_t *unicast_vars, int Socket) { int actual_fd; actual_fd=0; //We find the FD correspondig to this client while((actual_fdpfdsnum) && (unicast_vars->pfds[actual_fd].fd!=Socket)) actual_fd++; if(actual_fd==unicast_vars->pfdsnum) { log_message( log_module, MSG_ERROR,"close connection : we did't find the file descriptor this should never happend, please contact\n"); actual_fd=0; //We find the FD correspondig to this client while(actual_fdpfdsnum) { log_message( log_module, MSG_ERROR,"unicast_vars->pfds[actual_fd].fd %d Socket %d \n", unicast_vars->pfds[actual_fd].fd,Socket); actual_fd++; } return; } log_message( log_module, MSG_FLOOD,"We close the connection\n"); //We delete the client unicast_del_client(unicast_vars, unicast_vars->fd_info[actual_fd].client); //We move the last fd to the actual/deleted one, and decrease the number of fds by one unicast_vars->pfds[actual_fd].fd = unicast_vars->pfds[unicast_vars->pfdsnum-1].fd; unicast_vars->pfds[actual_fd].events = unicast_vars->pfds[unicast_vars->pfdsnum-1].events; unicast_vars->pfds[actual_fd].revents = unicast_vars->pfds[unicast_vars->pfdsnum-1].revents; //we move the file descriptor information unicast_vars->fd_info[actual_fd] = unicast_vars->fd_info[unicast_vars->pfdsnum-1]; //last one set to 0 for poll() unicast_vars->pfds[unicast_vars->pfdsnum-1].fd=0; unicast_vars->pfds[unicast_vars->pfdsnum-1].events=POLLIN|POLLPRI; unicast_vars->pfds[unicast_vars->pfdsnum-1].revents=0; //We clear it to avoid nasty bugs ... unicast_vars->pfdsnum--; unicast_vars->pfds=realloc(unicast_vars->pfds,(unicast_vars->pfdsnum+1)*sizeof(struct pollfd)); if (unicast_vars->pfds==NULL) { log_message( log_module, MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); set_interrupted(ERROR_MEMORY<<8); } unicast_vars->fd_info=realloc(unicast_vars->fd_info,(unicast_vars->pfdsnum)*sizeof(unicast_fd_info_t)); if (unicast_vars->fd_info==NULL) { log_message( log_module, MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); set_interrupted(ERROR_MEMORY<<8); } log_message( log_module, MSG_FLOOD,"Number of clients : %d\n", unicast_vars->client_number); } /** @brief Deal with an incoming message on the unicast client connection * This function will store and answer the HTTP requests * * * @param unicast_vars the unicast parameters * @param client The client from which the message was received * @param channels the channel array * @param number_of_channels quite explicit ... */ int unicast_handle_message(unicast_parameters_t *unicast_vars, unicast_client_t *client, mumudvb_channel_t *channels, int number_of_channels, strength_parameters_t *strengthparams, auto_p_t *auto_p, void *cam_p, void *scam_vars, eit_packet_t *eit_packets) { int received_len; (void) unicast_vars; /************ auto increasing buffer to receive the message **************/ if((client->buffersize-client->bufferpos)buffer=realloc(client->buffer,(client->buffersize + RECV_BUFFER_MULTIPLE+1)*sizeof(char)); //the +1 if for the \0 at the end if(client->buffer==NULL) { log_message( log_module, MSG_ERROR,"Problem with realloc for the client buffer : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); client->buffersize=0; client->bufferpos=0; return -1; } memset (client->buffer+client->buffersize, 0, RECV_BUFFER_MULTIPLE*sizeof(char)); //We fill the buffer with zeros to be sure client->buffersize += RECV_BUFFER_MULTIPLE; } received_len=recv(client->Socket, client->buffer+client->bufferpos, RECV_BUFFER_MULTIPLE, 0); if(received_len>0) { if(client->bufferpos==0) { log_message( log_module, MSG_FLOOD,"beginning of buffer %c%c%c%c%c%c\n",client->buffer[0],client->buffer[1],client->buffer[2],client->buffer[3],client->buffer[4],client->buffer[5]); log_message( log_module, MSG_FLOOD,"beginning of buffer %d %d %d %d %d %d\n",client->buffer[0],client->buffer[1],client->buffer[2],client->buffer[3],client->buffer[4],client->buffer[5]); } client->bufferpos+=received_len; log_message( log_module, MSG_FLOOD,"We received %d, buffer len %d new buffer pos %d\n",received_len,client->buffersize, client->bufferpos); } if(received_len==-1) { log_message( log_module, MSG_ERROR,"Problem with recv : %s\n",strerror(errno)); return -1; } if(received_len==0) return -2; //To say to the main program to close the connection /***************** Now we parse the message to see if something was asked *****************/ client->buffer[client->buffersize]='\0'; //For avoiding strlen to look too far (other option is to use the gnu extension strnlen) //We search for the end of the HTTP request if(strlen(client->buffer)>5 && strstr(client->buffer, "\n\r\n\0")) { int pos,err404; char *substring=NULL; int requested_channel; int iRet; requested_channel=0; pos=0; err404=0; struct unicast_reply* reply=NULL; log_message( log_module, MSG_FLOOD,"End of HTTP request, we parse it\n"); if(strstr(client->buffer,"GET ")==client->buffer) { //to implement : //Information ??? //GET /monitor/??? pos=4; /* preselected channels via the port of the connection */ //if the client have already an asked channel we don't parse the GET if(client->askedChannel!=-1) { requested_channel=client->askedChannel+1; //+1 because requested channel starts at 1 and asked channel starts at 0 log_message( log_module, MSG_DEBUG,"Channel by socket, number %d\n",requested_channel); client->askedChannel=-1; } //Channel by number //GET /bynumber/channelnumber else if(strstr(client->buffer +pos ,"/bynumber/")==(client->buffer +pos)) { if(client->chan_ptr!=NULL) { log_message( log_module, MSG_INFO,"A channel (%s) is already streamed to this client, it shouldn't ask for a new one without closing the connection, error 501\n",client->chan_ptr->name); iRet=write(client->Socket,HTTP_501_REPLY, strlen(HTTP_501_REPLY)); if(iRet<0) log_message( log_module, MSG_INFO,"Error writing reply\n"); return -2; //to delete the client } pos+=strlen("/bynumber/"); substring = strtok (client->buffer+pos, " "); if(substring == NULL) err404=1; else { requested_channel=atoi(substring); if(requested_channel && requested_channel<=number_of_channels) log_message( log_module, MSG_DEBUG,"Channel by number, number %d\n",requested_channel); else { log_message( log_module, MSG_INFO,"Channel by number, number %d out of range\n",requested_channel); err404=1; requested_channel=0; } } } //Channel by autoconf_sid_list //GET /bysid/sid else if(strstr(client->buffer +pos ,"/bysid/")==(client->buffer +pos)) { if(client->chan_ptr!=NULL) { log_message( log_module, MSG_INFO,"A channel (%s) is already streamed to this client, it shouldn't ask for a new one without closing the connection, error 501\n",client->chan_ptr->name); iRet=write(client->Socket,HTTP_501_REPLY, strlen(HTTP_501_REPLY)); //iRet is to make the copiler happy we will close the connection anyways return -2; //to delete the client } pos+=strlen("/bysid/"); substring = strtok (client->buffer+pos, " "); if(substring == NULL) err404=1; else { int requested_sid; requested_sid=atoi(substring); for(int current_channel=0; current_channelbuffer +pos ,"/byname/")==(client->buffer +pos)) { if(client->chan_ptr!=NULL) { log_message( log_module, MSG_INFO,"A channel (%s) is already streamed to this client, it shouldn't ask for a new one without closing the connection, error 501\n",client->chan_ptr->name); iRet=write(client->Socket,HTTP_501_REPLY, strlen(HTTP_501_REPLY));//iRet is to make the copiler happy we will close the connection anyways return -2; //to delete the client } pos+=strlen("/byname/"); log_message( log_module, MSG_DEBUG,"Channel by name\n"); char *substring = client->buffer+pos; char *end = strstr(substring, " HTTP"); // find end of channel name (this way channel name can contain spaces) if(*substring == 0) { err404=1; } else if(end == NULL) { err404=1; log_message( log_module, MSG_DEBUG,"Channel name was not found in the URL `%s`\n", substring); } else { end[0] = '\0'; // add string terminator to be able to get channel name char requested_channel_name[MAX_NAME_LEN]; char current_channel_name[MAX_NAME_LEN]; strncpy(requested_channel_name, substring,MAX_NAME_LEN); requested_channel_name[MAX_NAME_LEN-1] = '\0'; process_channel_name(requested_channel_name); for(int current_channel=0; current_channelbuffer +pos ,"/channels_list.html ")==(client->buffer +pos)) { //We get the host name if availaible char *hoststr; hoststr=strstr(client->buffer ,"Host: "); if(hoststr) { substring = strtok (hoststr+6, "\r"); } else substring=NULL; log_message( log_module, MSG_DETAIL,"Channel list\n"); unicast_send_streamed_channels_list (number_of_channels, channels, client->Socket, substring); return -2; //We close the connection afterwards } //playlist, m3u else if(strstr(client->buffer +pos ,"/playlist.m3u ")==(client->buffer +pos)) { log_message( log_module, MSG_DETAIL,"play list\n"); unicast_send_play_list_unicast (number_of_channels, channels, client->Socket, unicast_vars->portOut, 0, unicast_vars ); return -2; //We close the connection afterwards } //playlist, m3u else if(strstr(client->buffer +pos ,"/playlist_port.m3u ")==(client->buffer +pos)) { log_message( log_module, MSG_DETAIL,"play list\n"); unicast_send_play_list_unicast (number_of_channels, channels, client->Socket, unicast_vars->portOut, 1, unicast_vars ); return -2; //We close the connection afterwards } else if(strstr(client->buffer +pos ,"/playlist_multicast.m3u ")==(client->buffer +pos)) { log_message( log_module, MSG_DETAIL,"play list\n"); unicast_send_play_list_multicast (number_of_channels, channels, client->Socket, 0, unicast_vars ); return -2; //We close the connection afterwards } else if(strstr(client->buffer +pos ,"/playlist_multicast_vlc.m3u ")==(client->buffer +pos)) { log_message( log_module, MSG_DETAIL,"play list\n"); unicast_send_play_list_multicast (number_of_channels, channels, client->Socket, 1, unicast_vars ); return -2; //We close the connection afterwards } //statistics, text version else if(strstr(client->buffer +pos ,"/channels_list.json ")==(client->buffer +pos)) { log_message( log_module, MSG_DETAIL,"Channel list Json\n"); unicast_send_streamed_channels_list_js (number_of_channels, channels, scam_vars, client->Socket); return -2; //We close the connection afterwards } else if(strstr(client->buffer +pos ,"/monitor/state.json ")==(client->buffer +pos)) { log_message( log_module, MSG_DETAIL,"HTTP request for state in Json\n"); unicast_send_json_state(number_of_channels, channels, client->Socket, strengthparams, auto_p, cam_p, scam_vars); return -2; //We close the connection afterwards } else if(strstr(client->buffer +pos ,"/monitor/signal_power.json ")==(client->buffer +pos)) { log_message( log_module, MSG_DETAIL,"Signal power json\n"); unicast_send_signal_power_js(client->Socket, strengthparams); return -2; //We close the connection afterwards } else if(strstr(client->buffer +pos ,"/monitor/channels_traffic.json ")==(client->buffer +pos)) { log_message( log_module, MSG_DETAIL,"Channel traffic json\n"); unicast_send_channel_traffic_js(number_of_channels, channels, client->Socket); return -2; //We close the connection afterwards } else if(strstr(client->buffer +pos ,"/monitor/state.xml ")==(client->buffer +pos)) { log_message( log_module, MSG_DETAIL,"HTTP request for XML State\n"); unicast_send_xml_state(number_of_channels, channels, client->Socket, strengthparams, auto_p, cam_p, scam_vars); return -2; //We close the connection afterwards } //statistics, text version else if(strstr(client->buffer +pos ,"/monitor/EIT.json ")==(client->buffer +pos)) { log_message( log_module, MSG_DETAIL,"EIT Json\n"); unicast_send_EIT (eit_packets, client->Socket); return -2; //We close the connection afterwards } else if(strstr(client->buffer +pos ,"/cam/menu.xml ")==(client->buffer +pos)) { log_message( log_module, MSG_DETAIL,"HTTP request for CAM menu display \n"); unicast_send_cam_menu(client->Socket, cam_p); return -2; //We close the connection afterwards } else if(strstr(client->buffer +pos ,"/cam/action.xml?key=")==(client->buffer +pos)) { log_message( log_module, MSG_DETAIL,"HTTP request for CAM menu action\n"); pos+=strlen("/cam/action.xml?key="); unicast_send_cam_action(client->Socket,client->buffer+pos, cam_p); return -2; //We close the connection afterwards } else if((strstr(client->buffer +pos ,"/index.html")==(client->buffer +pos))|| (strstr(client->buffer +pos ,"/index.htm")==(client->buffer +pos))|| (strstr(client->buffer +pos ,"/ ")==(client->buffer +pos))) { log_message( log_module, MSG_DETAIL,"Index page\n"); unicast_send_index_page(client->Socket); return -2; //We close the connection afterwards } //Not implemented path --> 404 else err404=1; if(err404) { log_message( log_module, MSG_INFO,"Path not found i.e. 404\n"); reply = unicast_reply_init(); if (NULL == reply) { log_message( log_module, MSG_INFO,"Error when creating the HTTP reply\n"); return -2; } unicast_reply_write(reply, HTTP_404_REPLY_HTML, VERSION); unicast_reply_send(reply, client->Socket, 404, "text/html"); if (0 != unicast_reply_free(reply)) { log_message( log_module, MSG_INFO,"Error when releasing the HTTP reply after sendinf it\n"); return -2; } return -2; //to delete the client } //We have found a channel, we add the client if(requested_channel) { if(!channel_add_unicast_client(client,&channels[requested_channel-1])) client->chan_ptr=&channels[requested_channel-1]; else return -2; } } else { //We don't implement this http method, but if the client is already connected, we keep the connection if(client->chan_ptr==NULL) { log_message( log_module, MSG_INFO,"Unhandled HTTP method : \"%s\", error 501\n", strtok (client->buffer+pos, " ")); iRet=write(client->Socket,HTTP_501_REPLY, strlen(HTTP_501_REPLY));//iRet is to make the copiler happy we will close the connection anyways return -2; //to delete the client } else { log_message( log_module, MSG_INFO,"Unhandled HTTP method : \"%s\", error 501 but we keep the client connected\n", strtok (client->buffer+pos, " ")); iRet=write(client->Socket,HTTP_501_REPLY, strlen(HTTP_501_REPLY));//iRet is to make the copiler happy we will close the connection anyways return 0; } } //We don't need the buffer anymore free(client->buffer); client->buffer=NULL; client->bufferpos=0; client->buffersize=0; } return 0; } ////////////////// // HTTP Toolbox // ////////////////// /** @brief Init reply structure * */ struct unicast_reply* unicast_reply_init() { struct unicast_reply* reply = malloc(sizeof (struct unicast_reply)); if (NULL == reply) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); return NULL; } reply->buffer_header = malloc(REPLY_SIZE_STEP * sizeof (char)); if (NULL == reply->buffer_header) { free(reply); log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); return NULL; } reply->length_header = REPLY_SIZE_STEP; reply->used_header = 0; reply->buffer_body = malloc(REPLY_SIZE_STEP * sizeof (char)); if (NULL == reply->buffer_body) { free(reply->buffer_header); free(reply); log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); return NULL; } reply->length_body = REPLY_SIZE_STEP; reply->used_body = 0; reply->type = REPLY_BODY; return reply; } /** @brief Release the reply structure * */ int unicast_reply_free(struct unicast_reply *reply) { if (NULL == reply) return 1; if ((NULL == reply->buffer_header)&&(NULL == reply->buffer_body)) return 1; if(reply->buffer_header != NULL) free(reply->buffer_header); if(reply->buffer_body != NULL) free(reply->buffer_body); free(reply); return 0; } /** @brief Write data in a buffer using the same syntax that printf() * * auto-realloc buffer if needed */ int unicast_reply_write(struct unicast_reply *reply, const char* msg, ...) { char **buffer; char *temp_buffer; int *length; int *used; buffer=NULL; va_list args; if (NULL == msg) return -1; switch(reply->type) { case REPLY_HEADER: buffer=&reply->buffer_header; length=&reply->length_header; used=&reply->used_header; break; case REPLY_BODY: buffer=&reply->buffer_body; length=&reply->length_body; used=&reply->used_body; break; default: log_message( log_module, MSG_WARN,"unicast_reply_write with wrong type, please contact\n"); return -1; } va_start(args, msg); int estimated_len = vsnprintf(NULL, 0, msg, args); /* !! imply gcc -std=c99 */ //Since vsnprintf put the mess we reinitiate the args va_end(args); va_start(args, msg); // Must add 1 byte more for the terminating zero (not counted) while (*length - *used < estimated_len + 1) { temp_buffer = realloc(*buffer, *length + REPLY_SIZE_STEP); if(temp_buffer == NULL) { log_message( log_module, MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); va_end(args); return -1; } *buffer=temp_buffer; *length += REPLY_SIZE_STEP; } int real_len = vsnprintf(*buffer+*used, *length - *used, msg, args); if (real_len != estimated_len) { log_message( log_module, MSG_WARN,"Error when writing the HTTP reply\n"); } *used += real_len; va_end(args); return 0; } /** @brief Dump the filled buffer on the socket adding HTTP header informations */ int unicast_reply_send(struct unicast_reply *reply, int socket, int code, const char* content_type) { int size=0; int temp_size=0; //we add the header information reply->type = REPLY_HEADER; unicast_reply_write(reply, "HTTP/1.0 "); switch(code) { case 200: unicast_reply_write(reply, "200 OK\r\n"); break; case 404: unicast_reply_write(reply, "404 Not found\r\n"); break; default: log_message( log_module, MSG_ERROR,"reply send with bad code please contact\n"); return 0; } unicast_reply_write(reply, "Access-Control-Allow-Origin: *\r\n"); unicast_reply_write(reply, "Server: mumudvb/" VERSION "\r\n"); unicast_reply_write(reply, "Content-type: %s; charset=utf-8\r\n", content_type); unicast_reply_write(reply, "Content-length: %d\r\n", reply->used_body); unicast_reply_write(reply, "\r\n"); /* end header */ //we merge the header and the body reply->buffer_header = realloc(reply->buffer_header, reply->used_header+reply->used_body); memcpy(&reply->buffer_header[reply->used_header],reply->buffer_body,sizeof(char)*reply->used_body); reply->used_header+=reply->used_body; //now we write the data while (sizeused_header){ temp_size = write(socket, reply->buffer_header+size, reply->used_header-size); size += temp_size!=-1 ? temp_size : 0 ; } return size; } ////////////////////// // End HTTP Toolbox // ////////////////////// /** @brief Send a basic html file containing the list of streamed channels * * @param number_of_channels the number of channels * @param channels the channels array * @param Socket the socket on wich the information have to be sent * @param host The server ip address/name (got in the HTTP GET request) */ int unicast_send_streamed_channels_list (int number_of_channels, mumudvb_channel_t *channels, int Socket, char *host) { struct unicast_reply* reply = unicast_reply_init(); if (NULL == reply) { log_message( log_module, MSG_INFO,"Error when creating the HTTP reply\n"); return -1; } unicast_reply_write(reply, HTTP_CHANNELS_REPLY_START); for (int curr_channel = 0; curr_channel < number_of_channels; curr_channel++) if (channels[curr_channel].channel_ready>=READY) { if(host) unicast_reply_write(reply, "Channel number %d : %s
Unicast link :
http://%s/bysid/%d
Multicast ip : %s:%d

\r\n", curr_channel+1, channels[curr_channel].name, host,channels[curr_channel].service_id, host,channels[curr_channel].service_id, channels[curr_channel].ip4Out,channels[curr_channel].portOut); else unicast_reply_write(reply, "Channel number %d : \"%s\"
Multicast ip : %s:%d

\r\n", curr_channel+1, channels[curr_channel].name, channels[curr_channel].ip4Out,channels[curr_channel].portOut); } unicast_reply_write(reply, HTTP_CHANNELS_REPLY_END); unicast_reply_send(reply, Socket, 200, "text/html"); if (0 != unicast_reply_free(reply)) { log_message( log_module, MSG_INFO,"Error when releasing the HTTP reply after sendinf it\n"); return -1; } return 0; } /** @brief Send a basic text file containig the playlist * * @param number_of_channels the number of channels * @param channels the channels array * @param Socket the socket on wich the information have to be sent * @param perport says if the channel have to be given by the url /bysid or by their port */ int unicast_send_play_list_unicast (int number_of_channels, mumudvb_channel_t *channels, int Socket, int unicast_portOut, int perport, unicast_parameters_t *unicast_vars) { int curr_channel,iRet; struct unicast_reply* reply = unicast_reply_init(); if (NULL == reply) { log_message( log_module, MSG_INFO,"Error when creating the HTTP reply\n"); return -1; } //We get the ip address on which the client is connected struct sockaddr_in tempSocketAddr; unsigned int l; l = sizeof(struct sockaddr); iRet=getsockname(Socket, (struct sockaddr *) &tempSocketAddr, &l); if (iRet < 0) { log_message( log_module, MSG_ERROR,"getsockname failed : %s while making HTTP reply", strerror(errno)); if (0 != unicast_reply_free(reply)) log_message( log_module, MSG_INFO,"Error when releasing the HTTP reply"); return -1; } //we write the playlist unicast_reply_write(reply, "#EXTM3U\r\n"); //"#EXTINF:0,title\r\nURL" for (curr_channel = 0; curr_channel < number_of_channels; curr_channel++) if (channels[curr_channel].channel_ready>=READY && (channels[curr_channel].has_traffic == 1 || unicast_vars->playlist_ignore_dead == 0)) { if(!perport) { unicast_reply_write(reply, "#EXTINF:0,%s\r\nhttp://%s:%d/bysid/%d\r\n", channels[curr_channel].name, inet_ntoa(tempSocketAddr.sin_addr) , unicast_portOut , channels[curr_channel].service_id); } else if(channels[curr_channel].unicast_port) { unicast_reply_write(reply, "#EXTINF:0,%s\r\nhttp://%s:%d/\r\n", channels[curr_channel].name, inet_ntoa(tempSocketAddr.sin_addr) , channels[curr_channel].unicast_port); } } unicast_reply_send(reply, Socket, 200, "audio/x-mpegurl"); if (0 != unicast_reply_free(reply)) { log_message( log_module, MSG_INFO,"Error when releasing the HTTP reply after sendinf it\n"); return -1; } return 0; } /** @brief Send a basic index.html * * @param number_of_channels the number of channels * @param channels the channels array * @param Socket the socket on wich the information have to be sent * @param perport says if the channel have to be given by the url /bysid or by their port */ int unicast_send_index_page (int Socket) { struct unicast_reply* reply = unicast_reply_init(); if (NULL == reply) { log_message( log_module, MSG_INFO,"Error when creating the HTTP reply\n"); return -1; } unicast_reply_write(reply, HTTP_INDEX_REPLY_START); unicast_reply_write(reply, "
Channels by number : /bynumber/[channel number]

\r\n"); unicast_reply_write(reply, "
Channels by service identifier : /bysid/[channel sid]

\r\n"); unicast_reply_write(reply, "
Channels by number : /byname/[channel name]

\r\n"); unicast_reply_write(reply, "
Channels list

\r\n"); unicast_reply_write(reply, "
Playlist (m3u)

\r\n"); unicast_reply_write(reply, "
Playlist by port(m3u)

\r\n"); unicast_reply_write(reply, "
Playlist multicast (m3u)

\r\n"); unicast_reply_write(reply, "
Playlist multicast for VLC(m3u)

\r\n"); unicast_reply_write(reply, "
Channels list (json)

\r\n"); unicast_reply_write(reply, "
Signal strength (json)

\r\n"); unicast_reply_write(reply, "
Channels traffic (json)

\r\n"); unicast_reply_write(reply, "
Server state : channel list, pids, traffic (XML)

\r\n"); unicast_reply_write(reply, "
Server state : channel list, pids, traffic (json)

\r\n"); unicast_reply_write(reply, "
Contents of the EIT tables (json)

\r\n"); unicast_reply_write(reply, "
CAM menu

\r\n"); unicast_reply_write(reply, "
make an action on the cam menu : /cam/action.xml?key=

\r\n"); unicast_reply_write(reply, HTTP_INDEX_REPLY_END); unicast_reply_send(reply, Socket, 200, "text/html"); if (0 != unicast_reply_free(reply)) { log_message( log_module, MSG_INFO,"Error when releasing the HTTP reply after sendinf it\n"); return -1; } return 0; } /** @brief Send a basic text file containig the playlist * * @param number_of_channels the number of channels * @param channels the channels array * @param Socket the socket on wich the information have to be sent */ int unicast_send_play_list_multicast (int number_of_channels, mumudvb_channel_t *channels, int Socket, int vlc, unicast_parameters_t *unicast_vars) { int curr_channel; char urlheader[4]; char vlcchar[2]; struct unicast_reply* reply = unicast_reply_init(); if (NULL == reply) { log_message( log_module, MSG_INFO,"Error when creating the HTTP reply\n"); return -1; } unicast_reply_write(reply, "#EXTM3U\r\n"); if(vlc) strcpy(vlcchar,"@"); else vlcchar[0]='\0'; //"#EXTINF:0,title\r\nURL" for (curr_channel = 0; curr_channel < number_of_channels; curr_channel++) if (channels[curr_channel].channel_ready>=READY && (channels[curr_channel].has_traffic == 1 || unicast_vars->playlist_ignore_dead == 0)) { if(channels[curr_channel].rtp) strcpy(urlheader,"rtp"); else strcpy(urlheader,"udp"); unicast_reply_write(reply, "#EXTINF:0,%s\r\n%s://%s%s:%d\r\n", channels[curr_channel].name, urlheader, vlcchar, channels[curr_channel].ip4Out, channels[curr_channel].portOut); } unicast_reply_send(reply, Socket, 200, "audio/x-mpegurl"); if (0 != unicast_reply_free(reply)) { log_message( log_module, MSG_INFO,"Error when releasing the HTTP reply after sendinf it\n"); return -1; } return 0; } /** @brief Trims name of a channel to remove leading and trailing spaces, and replaces all spaces by '-' character. * Note that the string will be modified so do a copy prior to running this function if modifications to the original shall be prevented. * * @param str Channel name to process */ void process_channel_name(char *str) { int i; int begin = 0; int end = strlen(str) - 1; while (isspace(str[begin])) begin++; while ((end >= begin) && isspace(str[end])) end--; // shift all characters back to the start of the string array for (i = begin; i <= end; i++) { if (isspace(str[i])) str[i - begin] = '-'; // replace spaces by '-' else str[i - begin] = str[i]; } str[i - begin] = '\0'; } MuMuDVB-2.1.0/src/unicast_http.h000066400000000000000000000215561305714132500164100ustar00rootroot00000000000000/* * mumudvb - UDP-ize a DVB transport stream. * * (C) 2009 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /**@file * @brief HTML unicast headers */ #ifndef _UNICAST_H #define _UNICAST_H #include "mumudvb.h" #include "unicast_queue.h" /** @brief The different fd/socket types */ enum { UNICAST_MASTER=1, UNICAST_LISTEN_CHANNEL, UNICAST_CLIENT, }; #define RECV_BUFFER_MULTIPLE 100 /**@brief the timeout for disconnecting a client with only consecutive errors*/ #define UNICAST_CONSECUTIVE_ERROR_TIMEOUT 5 #define HTTP_OK_REPLY "HTTP/1.0 200 OK\r\n"\ "Content-type: video/mpeg\r\n"\ "\r\n" #define HTTP_404_REPLY_HTML "\r\n"\ "\r\n"\ "\r\n"\ "Not found\r\n"\ "\r\n"\ "\r\n"\ "

404 Not found

\r\n"\ "
\r\n"\ "MuMuDVB version %s\r\n"\ "\r\n"\ "\r\n"\ "\r\n" #define HTTP_INDEX_REPLY_START "\r\n"\ "\r\n"\ "\r\n"\ "MuMuDVB Server index\r\n"\ "\r\n"\ "\r\n"\ "

available URLs

\r\n"\ "
\r\n"\ "This is the list of the implemented URLs\r\n"\ "
\r\n"\ #define HTTP_INDEX_REPLY_END "
\r\n"\ "See MuMuDVB website for more details.\r\n"\ "\r\n"\ "\r\n"\ "\r\n" #define HTTP_CHANNELS_REPLY_START "\r\n"\ "\r\n"\ "\r\n"\ "Channels list\r\n"\ "\r\n"\ "\r\n"\ "

Channel list

\r\n"\ "
\r\n"\ "This is the list of actually streamed channels by the MuMuDVB server. To open a channel copy the link to your client or use multicast.\r\n"\ "
\r\n"\ #define HTTP_CHANNELS_REPLY_END "
\r\n"\ "See MuMuDVB website for more details.\r\n"\ "\r\n"\ "\r\n"\ "\r\n" #define HTTP_501_REPLY "HTTP/1.0 501 Not implemented\r\n"\ "\r\n" #define HTTP_503_REPLY "HTTP/1.0 503 Too many clients\r\n"\ "\r\n" /** @brief A client connected to the unicast connection. * *There is two chained list of client : a global one wich contain all the clients. Another one in each channel wich contain the associated clients. */ typedef struct unicast_client_t{ /**HTTP socket*/ struct sockaddr_in SocketAddr; /**HTTP socket*/ int Socket; /**Reception buffer*/ char *buffer; /**Size of the buffer*/ int buffersize; /**Position in the buffer*/ int bufferpos; /**Is there consecutive errors ?*/ int consecutive_errors; /**When the first consecutive error happened*/ long first_error_time; /**Channel : NULL if not associated yet*/ mumudvb_channel_t *chan_ptr; /**Future channel : we will set the channel when we will receive the get*/ int askedChannel; /**Next client*/ struct unicast_client_t *next; /**Previous client*/ struct unicast_client_t *prev; /**Next client in the channel*/ struct unicast_client_t *chan_next; /**Previous client in the channel*/ struct unicast_client_t *chan_prev; /** The packets in queue*/ unicast_queue_header_t queue; /** The latest write error for this client*/ int last_write_error; }unicast_client_t; /** @brief The information on the unicast file descriptors/sockets * There is three kind of descriptors : * The master connection : this connection will interpret the HTTP path asked, to give the channel, the channel list or debugging information * Client connections : This is the connections for connected clients * Channel listening connections : When a client connect to one of these sockets, the associated channel will be given directly without interpreting the PATH * * The numbering of this socket information is the same as the file descriptors numbering */ typedef struct unicast_fd_info_t{ /**The fd/socket type*/ int type; /** The channel if it's a channel socket*/ int channel; /** The client if it's a client socket*/ unicast_client_t *client; }unicast_fd_info_t; /** @brief The parameters for unicast */ typedef struct unicast_parameters_t{ /** Do we activate unicast ?*/ int unicast; /**The "HTTP" ip address*/ char ipOut[20]; /** The "HTTP" port*/ int portOut; /** The "HTTP" port string version before parsing*/ char *portOut_str; /** The HTTP input socket*/ struct sockaddr_in sIn; /** The HTTP input socket*/ int socketIn; /** The clients, contains all the clients, associated to a channel or not*/ unicast_client_t *clients; /** The number of connected clients*/ int client_number; /** The maximum number of simultaneous clients allowed*/ int max_clients; /** The timeout before disconnecting a client which does only errors*/ int consecutive_errors_timeout; /** The maximum size of the queue */ int queue_max_size; /** The socket SO_SNDBUF size*/ int socket_sendbuf_size; /** Debug : do we flush the queue when we get eagain errors ? */ int flush_on_eagain; /** The information on the file descriptors : ie the type of FD, the client associated if it's a client fd, the channel if it's a channel fd */ unicast_fd_info_t *fd_info; /**File descriptors for pooling*/ struct pollfd *pfds; //unicast http clients int pfdsnum; int playlist_ignore_dead; }unicast_parameters_t; struct unicast_reply { char* buffer_header; char* buffer_body; int length_header; int length_body; int used_header; int used_body; int type; }; struct unicast_reply* unicast_reply_init(); int unicast_reply_free(struct unicast_reply *reply); int unicast_reply_write(struct unicast_reply *reply, const char* msg, ...); int unicast_reply_send(struct unicast_reply *reply, int socket, int code, const char* content_type); int unicast_create_listening_socket(int socket_type, int socket_channel, char *ipOut, int port, struct sockaddr_in *sIn, int *socketIn, unicast_parameters_t *unicast_vars); struct strength_parameters_t; //just to avoid including dvb.h for one structure struct eit_packet_t; //just to avoid including rewrite.h for one structure int unicast_handle_fd_event(unicast_parameters_t *unicast_vars, mumudvb_channel_t *channels, int number_of_channels, struct strength_parameters_t *strengthparams, struct auto_p_t *auto_p, void *cam_vars, void *scam_vars, struct eit_packet_t *eit_packets); int unicast_del_client(unicast_parameters_t *unicast_vars, unicast_client_t *client); int channel_add_unicast_client(unicast_client_t *client,mumudvb_channel_t *channel); void unicast_freeing(unicast_parameters_t *unicast_vars); int read_unicast_configuration(unicast_parameters_t *unicast_vars, mumudvb_channel_t *c_chan, char *substring); void unicast_data_send(mumudvb_channel_t *actual_channel, unicast_parameters_t *unicast_vars); void process_channel_name(char *str); void init_unicast_v(unicast_parameters_t *unicast_vars); #endif MuMuDVB-2.1.0/src/unicast_monit.c000066400000000000000000001203361305714132500165460ustar00rootroot00000000000000/* * MuMuDVB - Stream a DVB transport stream. * * (C) 2013 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** @file * @brief File for HTTP unicast monitoring functions * @author Brice DUBOST * @date 2013 */ #include "unicast_http.h" #include "unicast_queue.h" #include "mumudvb.h" #include "errors.h" #include "log.h" #include "dvb.h" #include "tune.h" #include "rewrite.h" #include "autoconf.h" #ifdef ENABLE_CAM_SUPPORT #include "cam.h" #endif #ifdef ENABLE_SCAM_SUPPORT #include "scam_capmt.h" #include "scam_common.h" #include "scam_getcw.h" #include "scam_decsa.h" #endif static char *log_module="Unicast : "; /** * @brief Send a list of clients. * @param unicast_client the client list to output */ int unicast_send_client_list_js (unicast_client_t *unicast_client, struct unicast_reply *reply) { int client = 0; while(unicast_client!=NULL) { unicast_reply_write(reply, "{\t\t\"client_number\": %d, \"socket\": %d, \"remote_address\": \"%s\", \"remote_port\": %d, \"buffer_size\": %d, \"consecutive_errors\":%d, \"first_error_time\":%d, \"last_error_time\":%d },\n", client, unicast_client->Socket, inet_ntoa(unicast_client->SocketAddr.sin_addr), unicast_client->SocketAddr.sin_port, unicast_client->buffersize, unicast_client->consecutive_errors, unicast_client->first_error_time, unicast_client->last_write_error); unicast_client=unicast_client->chan_next; client++; } return 0; } /** * @brief Send the json channel list * * @param number_of_channels the number of channels * @param channels the channels array * @param reply the unicast_reply where we will write the info. * **/ int unicast_send_channel_list_js (int number_of_channels, mumudvb_channel_t *channels, void *scam_vars_v, struct unicast_reply *reply) { int curr_channel; #ifndef ENABLE_SCAM_SUPPORT (void) scam_vars_v; //to make compiler happy #else scam_parameters_t *scam_vars=(scam_parameters_t *)scam_vars_v; #endif for (curr_channel = 0; curr_channel < number_of_channels; curr_channel++) { //We give only channels which are ready if(channels[curr_channel].channel_readyscam_support) { unicast_reply_write(reply, "\t\"scam\": {\n\t\t \"descrambled\": %d",channels[curr_channel].scam_support); if (channels[curr_channel].scam_support) { unsigned int ring_buffer_num_packets = 0; if (channels[curr_channel].ring_buf) { pthread_mutex_lock(&channels[curr_channel].ring_buf->lock); ring_buffer_num_packets = channels[curr_channel].ring_buf->to_descramble + channels[curr_channel].ring_buf->to_send; pthread_mutex_unlock(&channels[curr_channel].ring_buf->lock); } unicast_reply_write(reply, ",\n"); unicast_reply_write(reply, "\t\t\"ring_buffer_size\": %u,\n",channels[curr_channel].ring_buffer_size); unicast_reply_write(reply, "\t\t\"decsa_delay\": %u,\n",channels[curr_channel].decsa_delay); unicast_reply_write(reply, "\t\t\"send_delay\": %u,\n",channels[curr_channel].send_delay); unicast_reply_write(reply, "\t\t\"num_packets\": %u",ring_buffer_num_packets); } unicast_reply_write(reply, "\n\t},\n"); } #endif unicast_reply_write(reply, "\t\"pids\":[\n"); for(int i=0;i0) reply->used_body -= 2; // dirty hack to erase the last comma else unicast_reply_write(reply, "{}\n"); unicast_reply_write(reply, "\n\t\t],\n\t\"clients\": [\n"); unicast_send_client_list_js(channels[curr_channel].clients, reply); if(channels[curr_channel].num_clients) reply->used_body -= 2; // dirty hack to erase the last comma else unicast_reply_write(reply, "\t\t{}\n"); unicast_reply_write(reply, "\t\t]\n\t},\n"); } if(number_of_channels>0) reply->used_body -= 2; // dirty hack to erase the last comma else unicast_reply_write(reply, "{}\n"); return 0; } /** @brief Send a basic JSON file containig the list of streamed channels * * @param number_of_channels the number of channels * @param channels the channels array * @param Socket the socket on wich the information have to be sent */ int unicast_send_streamed_channels_list_js (int number_of_channels, mumudvb_channel_t *channels, void *scam_vars_v, int Socket) { #ifndef ENABLE_SCAM_SUPPORT (void) scam_vars_v; //to make compiler happy #else scam_parameters_t *scam_vars=(scam_parameters_t *)scam_vars_v; #endif /***************************** PLEASE KEEP IN SYNC WITH THE XML VERSIONS ************************/ struct unicast_reply* reply = unicast_reply_init(); if (NULL == reply) { log_message( log_module, MSG_INFO,"Error when creating the HTTP reply\n"); return -1; } unicast_reply_write(reply, "[\n"); #ifndef ENABLE_SCAM_SUPPORT unicast_send_channel_list_js (number_of_channels, channels, scam_vars_v, reply); #else unicast_send_channel_list_js (number_of_channels, channels, scam_vars, reply); #endif unicast_reply_write(reply, "]\n"); unicast_reply_send(reply, Socket, 200, "application/json"); if (0 != unicast_reply_free(reply)) { log_message( log_module, MSG_INFO,"Error when releasing the HTTP reply after sendinf it\n"); return -1; } return 0; } /** @brief Send a basic JSON file containig the reception power * * @param Socket the socket on wich the information have to be sent */ int unicast_send_signal_power_js (int Socket, strength_parameters_t *strengthparams) { struct unicast_reply* reply = unicast_reply_init(); if (NULL == reply) { log_message( log_module, MSG_INFO,"Error when creating the HTTP reply\n"); return -1; } unicast_reply_write(reply, "{\"ber\":%d, \"strength\":%d, \"snr\":%d, \"ub\":%d}\n", strengthparams->ber,strengthparams->strength,strengthparams->snr,strengthparams->ub); unicast_reply_send(reply, Socket, 200, "application/json"); if (0 != unicast_reply_free(reply)) { log_message( log_module, MSG_INFO,"Error when releasing the HTTP reply after sendinf it\n"); return -1; } return 0; } //in unicast_EIT.c void unicast_send_EIT_section (mumudvb_ts_packet_t *eit_section, int num, struct unicast_reply* reply); int unicast_send_EIT (eit_packet_t *eit_packets, int Socket) { struct unicast_reply* reply = unicast_reply_init(); if (NULL == reply) { log_message( log_module, MSG_INFO,"Error when creating the HTTP reply\n"); return -1; } // JSON header unicast_reply_write(reply, "{\n"); eit_packet_t *actual_eit=eit_packets; int i; unicast_reply_write(reply, "\"EIT_tables\":[\n"); while(actual_eit!=NULL) { unicast_reply_write(reply, "{\n"); unicast_reply_write(reply, "\t\"sid\" : \"%d\",\n",actual_eit->service_id); unicast_reply_write(reply, "\t\"table_id\" : %d,\n",actual_eit->table_id); unicast_reply_write(reply, "\t\"version\" : %d,\n",actual_eit->version); unicast_reply_write(reply, "\t\"last_section_number\" : %d,\n",actual_eit->last_section_number); int first_section; first_section=1; unicast_reply_write(reply, "\"EIT_sections\":[\n"); for(i=0;i<=actual_eit->last_section_number;i++) if(actual_eit->sections_stored[i]) { if(!first_section) unicast_reply_write(reply, ","); else first_section=0; unicast_send_EIT_section(actual_eit->full_eit_sections[i],i ,reply); } unicast_reply_write(reply, "]\n"); unicast_reply_write(reply, "}"); actual_eit=actual_eit->next; if(actual_eit!=NULL) unicast_reply_write(reply, ",\n"); } unicast_reply_write(reply, "]\n"); // Ending JSON content unicast_reply_write(reply, "}\n"); unicast_reply_send(reply, Socket, 200, "application/json"); if (0 != unicast_reply_free(reply)) { log_message( log_module, MSG_INFO,"Error when releasing the HTTP reply after sending it\n"); return -1; } return 0; } /** @brief Send a basic JSON file containig the channel traffic * * @param number_of_channels the number of channels * @param channels the channels array * @param Socket the socket on wich the information have to be sent */ int unicast_send_channel_traffic_js (int number_of_channels, mumudvb_channel_t *channels, int Socket) { int curr_channel; extern long real_start_time; struct unicast_reply* reply = unicast_reply_init(); if (NULL == reply) { log_message( log_module, MSG_INFO,"Error when creating the HTTP reply\n"); return -1; } if ((time((time_t*)0L) - real_start_time) >= 10) //10 seconds for the traffic calculation to be done { unicast_reply_write(reply, "["); for (curr_channel = 0; curr_channel < number_of_channels; curr_channel++) unicast_reply_write(reply, "{\"number\":%d, \"name\":\"%s\", \"traffic\":%.2f},\n", curr_channel+1, channels[curr_channel].name, channels[curr_channel].traffic); if(number_of_channels>0) reply->used_body -= 2; // dirty hack to erase the last comma else unicast_reply_write(reply, "{}\n"); unicast_reply_write(reply, "]\n"); } unicast_reply_send(reply, Socket, 200, "application/json"); if (0 != unicast_reply_free(reply)) { log_message( log_module, MSG_INFO,"Error when releasing the HTTP reply after sendinf it\n"); return -1; } return 0; } /** @brief Send a full json state of the mumudvb instance * * @param number_of_channels the number of channels * @param channels the channels array * @param Socket the socket on wich the information have to be sent * @param fds the frontend device structure */ int unicast_send_json_state (int number_of_channels, mumudvb_channel_t *channels, int Socket, strength_parameters_t *strengthparams, auto_p_t *auto_p, void *cam_p_v, void *scam_vars_v) { /***************************** PLEASE KEEP IN SYNC WITH THE XML VERSIONS ************************/ #ifndef ENABLE_CAM_SUPPORT (void) cam_p_v; //to make compiler happy #else cam_p_t *cam_p=(cam_p_t *)cam_p_v; #endif #ifndef ENABLE_SCAM_SUPPORT (void) scam_vars_v; //to make compiler happy #else scam_parameters_t *scam_vars=(scam_parameters_t *)scam_vars_v; #endif // Prepare the HTTP reply struct unicast_reply* reply = unicast_reply_init(); if (NULL == reply) { log_message( log_module, MSG_INFO,"Error when creating the HTTP reply\n"); return -1; } // Date time formatting time_t rawtime; time (&rawtime); char sdatetime[25]; snprintf(sdatetime,25,"%s",ctime(&rawtime)); // JSON header unicast_reply_write(reply, "{\n"); // ****************** SERVER ************************ unicast_reply_write(reply, "\"mumudvb\":{\n"); // Mumudvb information unicast_reply_write(reply, "\t\"version\" : \"%s\",\n",VERSION); unicast_reply_write(reply, "\t\"pid\" : %d,\n",getpid ()); // Uptime extern long real_start_time; struct timeval tv; gettimeofday (&tv, (struct timezone *) NULL); unicast_reply_write(reply, "\t\"global_uptime\" : %d\n",(tv.tv_sec - real_start_time)); unicast_reply_write(reply, "},\n"); // ****************** TUNE ************************ unicast_reply_write(reply, "\"tune\":{\n"); // Card unicast_reply_write(reply, "\t\"card\" : %d,\n",strengthparams->tune_p->card); unicast_reply_write(reply, "\t\"card_path\" : \"%s\",\n",strengthparams->tune_p->card_dev_path); unicast_reply_write(reply, "\t\"frontend\" : %d,\n",strengthparams->tune_p->tuner); // Frontend setup unicast_reply_write(reply, "\t\"frontend_name\" : \"%s\",\n",strengthparams->tune_p->fe_name); unicast_reply_write(reply, "\t\"frontend_tuned\" : %d ,\n",strengthparams->tune_p->card_tuned); if (strengthparams->tune_p->fe_type==FE_QPSK) // Do some test for always showing frequency in kHz { unicast_reply_write(reply, "\t\"frontend_frequency\" : %d,\n",strengthparams->tune_p->freq); unicast_reply_write(reply, "\t\"frontend_satnumber\" : %d,\n",strengthparams->tune_p->sat_number); } else unicast_reply_write(reply, "\t\"frontend_frequency\" : %d,\n",(strengthparams->tune_p->freq)/1000); if (strengthparams->tune_p->pol==0) unicast_reply_write(reply, "\t\"frontend_polarization\" : \"-\",\n"); else unicast_reply_write(reply, "\t\"frontend_polarization\" : \"%c\",\n",strengthparams->tune_p->pol); unicast_reply_write(reply, "\t\"frontend_symbolrate\" : %d,\n",strengthparams->tune_p->srate); // Frontend type char fetype[10]="Unkonwn"; if (strengthparams->tune_p->fe_type==FE_OFDM) #ifdef DVBT2 if (strengthparams->tune_p->delivery_system==SYS_DVBT2) snprintf(fetype,10,"DVB-T2"); else snprintf(fetype,10,"DVB-T"); #else snprintf(fetype,10,"DVB-T"); #endif if (strengthparams->tune_p->fe_type==FE_QAM) snprintf(fetype,10,"DVB-C"); if (strengthparams->tune_p->fe_type==FE_ATSC) snprintf(fetype,10,"ATSC"); if (strengthparams->tune_p->fe_type==FE_QPSK) { #if DVB_API_VERSION >= 5 if (strengthparams->tune_p->delivery_system==SYS_DVBS2) snprintf(fetype,10,"DVB-S2"); #ifdef DVBT2 else if (strengthparams->tune_p->delivery_system==SYS_DVBT2) snprintf(fetype,10,"DVB-T2"); #endif else snprintf(fetype,10,"DVB-S"); #else snprintf(fetype,10,"DVB-S"); #endif } unicast_reply_write(reply, "\t\"frontend_system\" : \"%s\",\n",fetype); // Frontend status char SCVYL[6]="-----"; if (strengthparams->festatus & FE_HAS_SIGNAL) SCVYL[0]=83; // S if (strengthparams->festatus & FE_HAS_CARRIER) SCVYL[1]=67; // C if (strengthparams->festatus & FE_HAS_VITERBI) SCVYL[2]=86; // V if (strengthparams->festatus & FE_HAS_SYNC) SCVYL[3]=89; // Y if (strengthparams->festatus & FE_HAS_LOCK) SCVYL[4]=76; // L SCVYL[5]=0; unicast_reply_write(reply, "\t\"frontend_status\": \"%s\",\n",SCVYL); // Frontend signal unicast_reply_write(reply, "\t\"frontend_ber\" : %d,\n",strengthparams->ber); unicast_reply_write(reply, "\t\"frontend_signal\" : %d,\n",strengthparams->strength); unicast_reply_write(reply, "\t\"frontend_snr\" : %d,\n",strengthparams->snr); unicast_reply_write(reply, "\t\"frontend_ub\" : %d,\n",strengthparams->ub); unicast_reply_write(reply, "\t\"ts_discontinuities\" : %d\n",strengthparams->ts_discontinuities); unicast_reply_write(reply, "},\n"); // ****************** AUTOCONF ************************ unicast_reply_write(reply, "\"autoconfiguration\":{\n"); // Autoconfiguration state unicast_reply_write(reply, "\t\"enabled\" : %d",auto_p->autoconfiguration); if(auto_p->autoconfiguration) { unicast_reply_write(reply, ",\n"); unicast_reply_write(reply, "\t\"transport_stream_id\" : %d,\n",auto_p->transport_stream_id); unicast_reply_write(reply, "\t\"network_id\" : %d,\n",auto_p->network_id); unicast_reply_write(reply, "\t\"original_network_id\" : %d,\n",auto_p->original_network_id); unicast_reply_write(reply, "\t\"pat_version\" : %d,\n",auto_p->pat_version); unicast_reply_write(reply, "\t\"sdt_version\" : %d,\n",auto_p->sdt_version); unicast_reply_write(reply, "\t\"nit_version\" : %d,\n",auto_p->nit_version); unicast_reply_write(reply, "\t\"psip_version\" : %d,\n",auto_p->psip_version); unicast_reply_write(reply, "\t\"finished\" : %d", auto_p->pat_all_sections_seen && (auto_p->sdt_all_sections_seen || auto_p->psip_all_sections_seen) && auto_p->nit_all_sections_seen); } unicast_reply_write(reply, "\n},\n"); // ****************** CAM ************************ unicast_reply_write(reply, "\"cam\":{\n"); // CAM information #ifdef ENABLE_CAM_SUPPORT unicast_reply_write(reply, "\t\"support\" : %d,\n",cam_p->cam_support); unicast_reply_write(reply, "\t\"number\" : %d,\n",cam_p->cam_number); unicast_reply_write(reply, "\t\"menustring\" : \"%s\",\n",cam_p->cam_menu_string.string); unicast_reply_write(reply, "\t\"initialized\" : %d\n",cam_p->ca_resource_connected); #else unicast_reply_write(reply, "\t\"support\" : %d,\n",0); unicast_reply_write(reply, "\t\"number\" : %d,\n",0); unicast_reply_write(reply, "\t\"menustring\" : \"No CAM support\",\n"); unicast_reply_write(reply, "\t\"initialized\" : %d\n",0); #endif unicast_reply_write(reply, "},\n"); // ****************** SCAM ************************ unicast_reply_write(reply, "\"scam\":{\n"); // SCAM information #ifdef ENABLE_SCAM_SUPPORT unicast_reply_write(reply, "\t\"support\" : %d,\n",scam_vars->scam_support); if (scam_vars->scam_support) { unicast_reply_write(reply, "\t\"ring_buffer_default_size\" : %u,\n",scam_vars->ring_buffer_default_size); unicast_reply_write(reply, "\t\"decsa_default_delay\" : %u,\n",scam_vars->decsa_default_delay); unicast_reply_write(reply, "\t\"send_default_delay\" : %u\n",scam_vars->send_default_delay); } else { unicast_reply_write(reply, "\t\"ring_buffer_default_size\" : %u,\n",0); unicast_reply_write(reply, "\t\"decsa_default_delay\" : %u,\n",0); unicast_reply_write(reply, "\t\"send_default_delay\" : %u\n",0); } #else unicast_reply_write(reply, "\t\"support\" : %d,\n",0); unicast_reply_write(reply, "\t\"ring_buffer_default_size\" : %u,\n",0); unicast_reply_write(reply, "\t\"decsa_default_delay\" : %u,\n",0); unicast_reply_write(reply, "\t\"send_default_delay\" : %u\n",0); #endif unicast_reply_write(reply, "},\n"); // Channels list unicast_reply_write(reply,"\"channels\": ["); #ifndef ENABLE_SCAM_SUPPORT unicast_send_channel_list_js (number_of_channels, channels, scam_vars_v, reply); #else unicast_send_channel_list_js (number_of_channels, channels, scam_vars, reply); #endif unicast_reply_write(reply, "]\n"); // Ending JSON content unicast_reply_write(reply, "}\n"); unicast_reply_send(reply, Socket, 200, "application/json"); // End of HTTP reply if (0 != unicast_reply_free(reply)) { log_message( log_module, MSG_INFO,"Error when releasing the HTTP reply after sendinf it\n"); return -1; } return 0; } /** * @brief Send a list of clients. * @param unicast_client the client list to output */ int unicast_send_client_list_xml (unicast_client_t *unicast_client, struct unicast_reply *reply) { int client = 0; while(unicast_client!=NULL) { unicast_reply_write(reply, "\t\t\t\n", client); unicast_reply_write(reply, "\t\t\t\t%d", unicast_client->Socket); unicast_reply_write(reply, "\t\t\t\t\n", inet_ntoa(unicast_client->SocketAddr.sin_addr)); unicast_reply_write(reply, "\t\t\t\t%d", unicast_client->SocketAddr.sin_port); unicast_reply_write(reply, "\t\t\t\t%u\n",unicast_client->buffersize); unicast_reply_write(reply, "\t\t\t\t%d\n", unicast_client->consecutive_errors); unicast_reply_write(reply, "\t\t\t\t%d\n", unicast_client->first_error_time); unicast_reply_write(reply, "\t\t\t\t%d\n", unicast_client->last_write_error); unicast_reply_write(reply, "\t\t\t\n"); unicast_client=unicast_client->chan_next; client++; } return 0; } /** * @brief send the channel list in xml * * @param number_of_channels the number of channels * @param channels the channels array * @param reply the unicast_reply where we will write the info. * **/ int unicast_send_channel_list_xml (int number_of_channels, mumudvb_channel_t *channels, void *scam_vars_v, struct unicast_reply *reply) { #ifndef ENABLE_SCAM_SUPPORT (void) scam_vars_v; //to make compiler happy char *scam_vars; #else scam_parameters_t *scam_vars=(scam_parameters_t *)scam_vars_v; #endif // Channels list int curr_channel; for (curr_channel = 0; curr_channel < number_of_channels; curr_channel++) { //We give only channels which are ready if(channels[curr_channel].channel_ready\n",curr_channel+1,channels[curr_channel].has_traffic); unicast_reply_write(reply, "\t\t%d\n",channels[curr_channel].logical_channel_number); unicast_reply_write(reply, "\t\t\n",channels[curr_channel].name); unicast_reply_write(reply, "\t\t\n",channels[curr_channel].service_type,service_type_to_str(channels[curr_channel].service_type)); if (channels[curr_channel].portOut==0) unicast_reply_write(reply, "\t\t\n"); else unicast_reply_write(reply, "\t\t\n",channels[curr_channel].ip4Out); unicast_reply_write(reply, "\t\t%d\n",channels[curr_channel].portOut); unicast_reply_write(reply, "\t\t%.0f\n",channels[curr_channel].traffic); unicast_reply_write(reply, "\t\t%d\n",channels[curr_channel].ratio_scrambled); unicast_reply_write(reply, "\t\t%d\n",channels[curr_channel].service_id); unicast_reply_write(reply, "\t\t%d\n",channels[curr_channel].pid_i.pmt_pid); unicast_reply_write(reply, "\t\t%d\n",channels[curr_channel].pmt_version); unicast_reply_write(reply, "\t\t%d\n",channels[curr_channel].pid_i.pcr_pid); unicast_reply_write(reply, "\t\t%d\n",channels[curr_channel].unicast_port); unicast_reply_write(reply, "\t\t%d\n", channels[curr_channel].num_clients); // SCAM information #ifdef ENABLE_SCAM_SUPPORT if (scam_vars->scam_support) { unicast_reply_write(reply, "\t\t\n",channels[curr_channel].scam_support); if (channels[curr_channel].scam_support) { unsigned int ring_buffer_num_packets = 0; if (channels[curr_channel].ring_buf) { pthread_mutex_lock(&channels[curr_channel].ring_buf->lock); ring_buffer_num_packets = channels[curr_channel].ring_buf->to_descramble + channels[curr_channel].ring_buf->to_send; pthread_mutex_unlock(&channels[curr_channel].ring_buf->lock); } unicast_reply_write(reply, "\t\t\t%u\n",channels[curr_channel].ring_buffer_size); unicast_reply_write(reply, "\t\t\t%u\n",channels[curr_channel].decsa_delay); unicast_reply_write(reply, "\t\t\t%u\n",channels[curr_channel].send_delay); unicast_reply_write(reply, "\t\t\t%u\n",ring_buffer_num_packets); } unicast_reply_write(reply, "\t\t\n"); } #endif unicast_reply_write(reply, "\t\t\n"); for(int i=0;i<32;i++) if(channels[curr_channel].ca_sys_id[i]!=0) unicast_reply_write(reply, "\t\t\t\n",channels[curr_channel].ca_sys_id[i],ca_sys_id_to_str(channels[curr_channel].ca_sys_id[i])); unicast_reply_write(reply, "\t\t\n"); unicast_reply_write(reply, "\t\t\n"); for(int i=0;i\n", channels[curr_channel].pid_i.pids[i], channels[curr_channel].pid_i.pids_language[i], channels[curr_channel].pid_i.pids_scrambled[i], pid_type_to_str(channels[curr_channel].pid_i.pids_type[i])); unicast_reply_write(reply, "\t\t\n"); unicast_reply_write(reply, "\t\t\n", channels[curr_channel].num_clients); unicast_send_client_list_xml(channels[curr_channel].clients, reply); unicast_reply_write(reply, "\t\t\n"); unicast_reply_write(reply, "\t\n"); } return 0; } /** @brief Send a full XML state of the mumudvb instance * * @param number_of_channels the number of channels * @param channels the channels array * @param Socket the socket on wich the information have to be sent * @param fds the frontend device structure */ int unicast_send_xml_state (int number_of_channels, mumudvb_channel_t *channels, int Socket, strength_parameters_t *strengthparams, auto_p_t *auto_p, void *cam_p_v, void *scam_vars_v) { /***************************** PLEASE KEEP IN SYNC WITH THE JSON VERSIONS ************************/ #ifndef ENABLE_CAM_SUPPORT (void) cam_p_v; //to make compiler happy #else cam_p_t *cam_p=(cam_p_t *)cam_p_v; #endif #ifndef ENABLE_SCAM_SUPPORT (void) scam_vars_v; //to make compiler happy #else scam_parameters_t *scam_vars=(scam_parameters_t *)scam_vars_v; #endif // Prepare the HTTP reply struct unicast_reply* reply = unicast_reply_init(); if (NULL == reply) { log_message( log_module, MSG_INFO,"Error when creating the HTTP reply\n"); return -1; } // Date time formatting time_t rawtime; time (&rawtime); char sdatetime[25]; snprintf(sdatetime,25,"%s",ctime(&rawtime)); // XML header unicast_reply_write(reply, "\n"); // Starting XML content unicast_reply_write(reply, "\n",strengthparams->tune_p->card,strengthparams->tune_p->tuner); unicast_reply_write(reply, "\n",strengthparams->tune_p->card_dev_path); // Mumudvb information unicast_reply_write(reply, "\t\n",VERSION); unicast_reply_write(reply, "\t%d\n",getpid ()); // Uptime extern long real_start_time; struct timeval tv; gettimeofday (&tv, (struct timezone *) NULL); unicast_reply_write(reply, "\t%d\n",(tv.tv_sec - real_start_time)); // Frontend setup unicast_reply_write(reply, "\t\n",strengthparams->tune_p->fe_name); unicast_reply_write(reply, "\t%d\n",strengthparams->tune_p->card_tuned); if (strengthparams->tune_p->fe_type==FE_QPSK) // Do some test for always showing frequency in kHz { unicast_reply_write(reply, "\t%d\n",strengthparams->tune_p->freq); unicast_reply_write(reply, "\t%d\n",strengthparams->tune_p->sat_number); } else unicast_reply_write(reply, "\t%d\n",(strengthparams->tune_p->freq)/1000); if (strengthparams->tune_p->pol==0) unicast_reply_write(reply, "\t\n"); else unicast_reply_write(reply, "\t\n",strengthparams->tune_p->pol); unicast_reply_write(reply, "\t%d\n",strengthparams->tune_p->srate); // Frontend type char fetype[10]="Unkonwn"; if (strengthparams->tune_p->fe_type==FE_OFDM) #ifdef DVBT2 if (strengthparams->tune_p->delivery_system==SYS_DVBT2) snprintf(fetype,10,"DVB-T2"); else snprintf(fetype,10,"DVB-T"); #else snprintf(fetype,10,"DVB-T"); #endif if (strengthparams->tune_p->fe_type==FE_QAM) snprintf(fetype,10,"DVB-C"); if (strengthparams->tune_p->fe_type==FE_ATSC) snprintf(fetype,10,"ATSC"); if (strengthparams->tune_p->fe_type==FE_QPSK) { #if DVB_API_VERSION >= 5 if (strengthparams->tune_p->delivery_system==SYS_DVBS2) snprintf(fetype,10,"DVB-S2"); #ifdef DVBT2 else if (strengthparams->tune_p->delivery_system==SYS_DVBT2) snprintf(fetype,10,"DVB-T2"); #endif else snprintf(fetype,10,"DVB-S"); #else snprintf(fetype,10,"DVB-S"); #endif } unicast_reply_write(reply, "\t\n",fetype); // Frontend status char SCVYL[6]="-----"; if (strengthparams->festatus & FE_HAS_SIGNAL) SCVYL[0]=83; // S if (strengthparams->festatus & FE_HAS_CARRIER) SCVYL[1]=67; // C if (strengthparams->festatus & FE_HAS_VITERBI) SCVYL[2]=86; // V if (strengthparams->festatus & FE_HAS_SYNC) SCVYL[3]=89; // Y if (strengthparams->festatus & FE_HAS_LOCK) SCVYL[4]=76; // L SCVYL[5]=0; unicast_reply_write(reply, "\t\n",SCVYL); // Frontend signal unicast_reply_write(reply, "\t%d\n",strengthparams->ber); unicast_reply_write(reply, "\t%d\n",strengthparams->strength); unicast_reply_write(reply, "\t%d\n",strengthparams->snr); unicast_reply_write(reply, "\t%d\n",strengthparams->ub); unicast_reply_write(reply, "\t%d\n",strengthparams->ts_discontinuities); // Autoconfiguration state unicast_reply_write(reply, "\t%d\n",auto_p->autoconfiguration); if(auto_p->autoconfiguration) { unicast_reply_write(reply, "\t\n"); unicast_reply_write(reply, "\t\t%d\n",auto_p->transport_stream_id); unicast_reply_write(reply, "\t\t%d\n",auto_p->network_id); unicast_reply_write(reply, "\t\t%d\n",auto_p->original_network_id); unicast_reply_write(reply, "\t\t%d\n",auto_p->pat_version); unicast_reply_write(reply, "\t\t%d\n",auto_p->sdt_version); unicast_reply_write(reply, "\t\t%d\n",auto_p->nit_version); unicast_reply_write(reply, "\t\t%d\n",auto_p->psip_version); unicast_reply_write(reply, "\t\n"); unicast_reply_write(reply, "\t%d\n", auto_p->pat_all_sections_seen && (auto_p->sdt_all_sections_seen || auto_p->psip_all_sections_seen) && auto_p->nit_all_sections_seen); } // CAM information #ifdef ENABLE_CAM_SUPPORT unicast_reply_write(reply, "\t%d\n",cam_p->cam_support); unicast_reply_write(reply, "\t%d\n",cam_p->cam_number); unicast_reply_write(reply, "\t\n",cam_p->cam_menu_string.string); unicast_reply_write(reply, "\t%d\n",cam_p->ca_resource_connected); #else unicast_reply_write(reply, "\t%d\n",0); unicast_reply_write(reply, "\t%d\n",0); unicast_reply_write(reply, "\t\n"); unicast_reply_write(reply, "\t%d\n",0); #endif // SCAM information #ifdef ENABLE_SCAM_SUPPORT unicast_reply_write(reply, "\t%d\n",scam_vars->scam_support); if (scam_vars->scam_support) { unicast_reply_write(reply, "\t%u\n",scam_vars->ring_buffer_default_size); unicast_reply_write(reply, "\t%u\n",scam_vars->decsa_default_delay); unicast_reply_write(reply, "\t%u\n",scam_vars->send_default_delay); } else { unicast_reply_write(reply, "\t%u\n",0); unicast_reply_write(reply, "\t%u\n",0); unicast_reply_write(reply, "\t%u\n",0); } #else unicast_reply_write(reply, "\t%d\n",0); unicast_reply_write(reply, "\t%u\n",0); unicast_reply_write(reply, "\t%u\n",0); unicast_reply_write(reply, "\t%u\n",0); #endif // channel list unicast_send_channel_list_xml (number_of_channels, channels, scam_vars_v, reply); // Ending XML content unicast_reply_write(reply, "\n"); unicast_reply_send(reply, Socket, 200, "application/xml; charset=UTF-8"); // End of HTTP reply if (0 != unicast_reply_free(reply)) { log_message( log_module, MSG_INFO,"Error when releasing the HTTP reply after sendinf it\n"); return -1; } return 0; } /** @brief Return the last MMI menu sent by CAM * * @param Socket the socket on wich the information have to be sent */ int unicast_send_cam_menu (int Socket, void *cam_p_v) { #ifndef ENABLE_CAM_SUPPORT (void) cam_p_v; //to make compiler happy #else cam_p_t *cam_p=(cam_p_t *)cam_p_v; #endif struct unicast_reply* reply = unicast_reply_init(); if (NULL == reply) { log_message( log_module, MSG_INFO,"Unicast : Error when creating the HTTP reply\n"); return -1; } // UTF-8 Byte Order Mark (BOM) unicast_reply_write(reply, "\xef\xbb\xbf"); // Date time formatting time_t rawtime; time (&rawtime); char sdatetime[25]; snprintf(sdatetime,25,"%s",ctime(&rawtime)); // XML header unicast_reply_write(reply, "\n"); // Starting XML content unicast_reply_write(reply, "\n"); #ifdef ENABLE_CAM_SUPPORT // Sending the last menu if existing if (cam_p->ca_resource_connected!=0) { if (cam_p->cam_menulist_str.length>0) { unicast_reply_write(reply, "%s",cam_p->cam_menulist_str.string); } else { unicast_reply_write(reply, "\t\n",sdatetime); unicast_reply_write(reply, "\t\n",cam_p->cam_menu_string.string); unicast_reply_write(reply, "\t\n"); unicast_reply_write(reply, "\t<![CDATA[No menu to display]]>\n"); } } else { unicast_reply_write(reply, "\t\n",sdatetime); unicast_reply_write(reply, "\t\n"); unicast_reply_write(reply, "\t<![CDATA[CAM not initialized!]]>\n"); } #else unicast_reply_write(reply, "\t\n",sdatetime); unicast_reply_write(reply, "\t\n"); unicast_reply_write(reply, "\t<![CDATA[Compiled without CAM support]]>\n"); #endif // Ending XML content unicast_reply_write(reply, "\n"); // Cleaning all non acceptable characters for pseudo UTF-8 (in fact, US-ASCII) - Skipping BOM and last zero character unsigned char c; int j; for (j=3; jused_body; j++) { c=reply->buffer_body[j]; if ((c<32 || c>127) && c!=9 && c!=10 && c!=13) reply->buffer_body[j]=32; } unicast_reply_send(reply, Socket, 200, "application/xml; charset=UTF-8"); // End of HTTP reply if (0 != unicast_reply_free(reply)) { log_message( log_module, MSG_INFO,"Unicast : Error when releasing the HTTP reply after sendinf it\n"); return -1; } return 0; } /** @brief Send an action to the CAM MMI menu * * @param Socket the socket on wich the information have to be sent */ int unicast_send_cam_action (int Socket, char *Key, void *cam_p_v) { #ifndef ENABLE_CAM_SUPPORT (void) cam_p_v; //to make compiler happy #else cam_p_t *cam_p=(cam_p_t *)cam_p_v; #endif struct unicast_reply* reply = unicast_reply_init(); if (NULL == reply) { log_message( log_module, MSG_INFO,"Unicast : Error when creating the HTTP reply\n"); return -1; } // UTF-8 Byte Order Mark (BOM) unicast_reply_write(reply, "\xef\xbb\xbf"); // Date time formatting time_t rawtime; time (&rawtime); char sdatetime[25]; snprintf(sdatetime,25,"%s",ctime(&rawtime)); // XML header unicast_reply_write(reply, "\n"); // Starting XML content unicast_reply_write(reply, "\n"); unicast_reply_write(reply, "\t\n",ctime(&rawtime)); unicast_reply_write(reply, "\t\n",*Key); #ifdef ENABLE_CAM_SUPPORT // Check if valid action to be done [0-9] and 'M' and 'C' and 'O' int iKey=(int)*Key; if ((iKey>=48 && iKey<=57) || iKey==77 || iKey==67 || iKey==79) { // Check if CAM is initialized if (cam_p->ca_resource_connected!=0) { // Disable auto response from now (as a manual action is asked) cam_p->cam_mmi_autoresponse=0; // Numbers for MENU/LIST answer if (cam_p->mmi_state==MMI_STATE_MENU && iKey>=48 && iKey<=57) { log_message( log_module, MSG_INFO, "Send CAM MENU key number %d\n",iKey-48); en50221_app_mmi_menu_answ(cam_p->stdcam->mmi_resource, cam_p->stdcam->mmi_session_number, iKey-48); cam_p->mmi_state=MMI_STATE_OPEN; } // 'M' = ask the menu - Always possible if (iKey==77) { log_message( log_module, MSG_INFO, "Ask CAM to enter MENU\n"); en50221_app_ai_entermenu(cam_p->stdcam->ai_resource, cam_p->stdcam->ai_session_number); cam_p->mmi_state=MMI_STATE_OPEN; } // Numbers for ENQUIRY answer if (cam_p->mmi_state==MMI_STATE_ENQ && iKey>=48 && iKey<=57) { // We store the new key cam_p->mmi_enq_answer[cam_p->mmi_enq_entered]=iKey; cam_p->mmi_enq_entered++; log_message( log_module, MSG_INFO, "Received CAM ENQUIRY key number %d (%d of %d expected)\n", iKey-48, cam_p->mmi_enq_entered, cam_p->mmi_enq_length); // Test if the expected length is received if (cam_p->mmi_enq_entered == cam_p->mmi_enq_length) { // We send the anwser log_message( log_module, MSG_INFO, "Sending ENQUIRY answer to CAM (answer has the expected length of %d)\n",cam_p->mmi_enq_entered); en50221_app_mmi_answ(cam_p->stdcam->mmi_resource, cam_p->stdcam->mmi_session_number, MMI_ANSW_ID_ANSWER, (uint8_t*)cam_p->mmi_enq_answer, cam_p->mmi_enq_entered); cam_p->mmi_state=MMI_STATE_OPEN; } } // 'C' = send CANCEL as an ENQUIRY answer if (cam_p->mmi_state==MMI_STATE_ENQ && iKey==67) { log_message( log_module, MSG_INFO, "Send CAM ENQUIRY key CANCEL\n"); en50221_app_mmi_answ(cam_p->stdcam->mmi_resource, cam_p->stdcam->mmi_session_number, MMI_ANSW_ID_CANCEL, NULL, 0); cam_p->mmi_state=MMI_STATE_OPEN; } // OK unicast_reply_write(reply, "\t\n"); } else { unicast_reply_write(reply, "\t\n"); } } else { unicast_reply_write(reply, "\t\n"); } #else unicast_reply_write(reply, "\t\n"); #endif // Ending XML content unicast_reply_write(reply, "\n"); // Cleaning all non acceptable characters for pseudo UTF-8 (in fact, US-ASCII) - Skipping BOM and last zero character unsigned char c; int j; for (j=3; jused_body; j++) { c=reply->buffer_body[j]; if ((c<32 || c>127) && c!=9 && c!=10 && c!=13) reply->buffer_body[j]=32; } unicast_reply_send(reply, Socket, 200, "application/xml; charset=UTF-8"); // End of HTTP reply if (0 != unicast_reply_free(reply)) { log_message( log_module, MSG_INFO,"Unicast : Error when releasing the HTTP reply after sendinf it\n"); return -1; } return 0; } MuMuDVB-2.1.0/src/unicast_queue.c000066400000000000000000000256551305714132500165540ustar00rootroot00000000000000/* * MuMuDVB - UDP-ize a DVB transport stream. * * (C) 2009 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** @file * @brief File for HTTP unicast Queue and data sending * @author Brice DUBOST * @date 2009-2010 */ #include #include #include #include #include #include "unicast_http.h" #include "unicast_queue.h" #include "mumudvb.h" #include "errors.h" #include "log.h" static char *log_module="Unicast : "; int unicast_queue_remove_data(unicast_queue_header_t *header); int unicast_queue_add_data(unicast_queue_header_t *header, unsigned char *data, int data_len); int unicast_queue_requeue(unicast_queue_header_t *header, unsigned char *data, int data_len); unsigned char *unicast_queue_get_data(unicast_queue_header_t* , int* ); void unicast_close_connection(unicast_parameters_t *unicast_vars, int Socket); /** @brief Send the buffer for the channel * * This function is called when a buffer for a channel is full and have to be sent to the clients * */ void unicast_data_send(mumudvb_channel_t *actual_channel, unicast_parameters_t *unicast_vars) { if(actual_channel->clients) { unicast_client_t *actual_client; unicast_client_t *temp_client; int written_len; unsigned char *buffer; int buffer_len; int data_from_queue; int packets_left; struct timeval tv; actual_client=actual_channel->clients; while(actual_client!=NULL) { buffer=actual_channel->buf; buffer_len=actual_channel->nb_bytes; data_from_queue=0; if(actual_client->queue.packets_in_queue!=0) { //already some packets in the queue we enqueue the new one and try to send the queued ones data_from_queue=1; packets_left=UNICAST_MULTIPLE_QUEUE_SEND; if((actual_client->queue.data_bytes_in_queue+buffer_len)< unicast_vars->queue_max_size) unicast_queue_add_data(&actual_client->queue, buffer, buffer_len ); else { if(!actual_client->queue.full) { actual_client->queue.full=1; log_message( log_module, MSG_DETAIL,"The queue is full, we now throw away new packets for client %s:%d\n", inet_ntoa(actual_client->SocketAddr.sin_addr), actual_client->SocketAddr.sin_port); } } buffer=unicast_queue_get_data(&actual_client->queue, &buffer_len); } else packets_left=1; while(packets_left>0) { //we send the data written_len=send(actual_client->Socket,buffer, buffer_len,MSG_NOSIGNAL); //We check if all the data was successfully written if(written_lenlast_write_error) { log_message( log_module, MSG_DEBUG,"New error when writing to client %s:%d : %s\n", inet_ntoa(actual_client->SocketAddr.sin_addr), actual_client->SocketAddr.sin_port, strerror(errno)); actual_client->last_write_error=errno; written_len=0; } } else { log_message( log_module, MSG_DEBUG,"Not all the data was written to %s:%d. Asked len : %d, written len %d\n", inet_ntoa(actual_client->SocketAddr.sin_addr), actual_client->SocketAddr.sin_port, actual_channel->nb_bytes, written_len); } if(!(unicast_vars->flush_on_eagain &&(errno==EAGAIN)))//Debug feature : we can drop data if eagain error { //No drop on eagain or no eagain if(!data_from_queue) { //We store the non sent data in the queue if((actual_client->queue.data_bytes_in_queue+buffer_len-written_len)< unicast_vars->queue_max_size) { unicast_queue_add_data(&actual_client->queue, buffer+written_len, buffer_len-written_len); log_message( log_module, MSG_DEBUG,"We start queuing packets ... \n"); } } else if(written_len > 0) { unicast_queue_remove_data(&actual_client->queue); unicast_queue_requeue(&actual_client->queue, buffer+written_len, buffer_len-written_len); log_message( log_module, MSG_DEBUG,"We requeue the non sent data ... \n"); } }else{ //this is an EAGAIN error and we want to drop the data if(!data_from_queue) { //Not from the queue we dont do anything log_message( log_module, MSG_DEBUG,"We drop not from queue ... \n"); } else { unicast_queue_clear(&actual_client->queue); log_message( log_module, MSG_DEBUG,"Eagain error we flush the queue ... \n"); } } if(!actual_client->consecutive_errors) { log_message( log_module, MSG_DETAIL,"Error when writing to client %s:%d : %s\n", inet_ntoa(actual_client->SocketAddr.sin_addr), actual_client->SocketAddr.sin_port, strerror(errno)); gettimeofday (&tv, (struct timezone *) NULL); actual_client->first_error_time = tv.tv_sec; actual_client->consecutive_errors=1; } else { //We have errors, we check if we reached the timeout gettimeofday (&tv, (struct timezone *) NULL); if((unicast_vars->consecutive_errors_timeout > 0) && (tv.tv_sec - actual_client->first_error_time) > unicast_vars->consecutive_errors_timeout) { log_message( log_module, MSG_INFO,"Consecutive errors when writing to client %s:%d during too much time, we disconnect\n", inet_ntoa(actual_client->SocketAddr.sin_addr), actual_client->SocketAddr.sin_port); temp_client=actual_client->chan_next; unicast_close_connection(unicast_vars,actual_client->Socket); actual_client=temp_client; } } } else { //data successfully written if (actual_client->consecutive_errors) { log_message( log_module, MSG_DETAIL,"We can write again to client %s:%d\n", inet_ntoa(actual_client->SocketAddr.sin_addr), actual_client->SocketAddr.sin_port); actual_client->consecutive_errors=0; actual_client->last_write_error=0; if(data_from_queue) log_message( log_module, MSG_DEBUG,"We start dequeuing packets Packets in queue: %d. Bytes in queue: %d\n", actual_client->queue.packets_in_queue, actual_client->queue.data_bytes_in_queue); } packets_left--; if(data_from_queue) { //The data was successfully sent, we can dequeue it unicast_queue_remove_data(&actual_client->queue); if(actual_client->queue.packets_in_queue!=0) { //log_message( log_module, MSG_DEBUG,"Still packets in the queue,next one\n"); //still packets in the queue, we continue sending if(packets_left) buffer=unicast_queue_get_data(&actual_client->queue, &buffer_len); } else //queue now empty { packets_left=0; log_message( log_module, MSG_DEBUG,"The queue is now empty :) client %s:%d \n", inet_ntoa(actual_client->SocketAddr.sin_addr), actual_client->SocketAddr.sin_port); } } } } if(actual_client) //Can be null if the client was destroyed actual_client=actual_client->chan_next; } } } /* ================= QUEUE ======================*/ /** @brief Add data to a queue * */ int unicast_queue_add_data(unicast_queue_header_t *header, unsigned char *data, int data_len) { unicast_queue_data_t *dest; if(header->packets_in_queue == 0) { //first packet in the queue header->first=malloc(sizeof(unicast_queue_data_t)); if(header->first==NULL) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); return -1; } dest=header->first; header->last=header->first; } else { //already packets in the queue header->last->next=malloc(sizeof(unicast_queue_data_t)); if(header->last->next==NULL) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); return -1; } dest=header->last->next; header->last=dest; } dest->next=NULL; dest->data=malloc(sizeof(unsigned char)*data_len); if(dest->data==NULL) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); return -1; } memcpy(dest->data,data,data_len); dest->data_length=data_len; header->packets_in_queue++; header->data_bytes_in_queue+=data_len; //log_message( log_module, MSG_DEBUG,"queuing new packet. Packets in queue: %d. Bytes in queue: %d\n",header->packets_in_queue,header->data_bytes_in_queue); return 0; } /** @brief Get data from a queue * */ unsigned char *unicast_queue_get_data(unicast_queue_header_t *header, int *data_len) { if(header->packets_in_queue == 0) { log_message( log_module, MSG_ERROR,"BUG : Cannot dequeue an empty queue\n"); return NULL; } *data_len=header->first->data_length; return header->first->data; } /** @brief Remove the first packet of the queue * */ int unicast_queue_remove_data(unicast_queue_header_t *header) { unicast_queue_data_t *tobedeleted; if(header->packets_in_queue == 0) { log_message( log_module, MSG_ERROR,"BUG : Cannot remove from an empty queue\n"); return -1; } tobedeleted=header->first; header->first=header->first->next; header->packets_in_queue--; header->full=0; header->data_bytes_in_queue-=tobedeleted->data_length; free(tobedeleted->data); free(tobedeleted); return 0; } /** @brief Clear the queue * */ void unicast_queue_clear(unicast_queue_header_t *header) { while(header->packets_in_queue > 0) unicast_queue_remove_data(header); } int unicast_queue_requeue(unicast_queue_header_t *header, unsigned char *data, int data_len) { int last_pkt_size; unicast_queue_data_t *dest; unsigned char *tempbuf; if(header->packets_in_queue == 0) { log_message(log_module, MSG_ERROR, "BUG: unicast_queue_requeue() called with no packets in the queue\n"); return -1; } tempbuf = malloc(sizeof(unsigned char)*data_len); if(tempbuf == NULL) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); return -1; } memcpy(tempbuf, data, data_len); dest=header->first; last_pkt_size = dest->data_length; free(dest->data); dest->data = tempbuf; dest->data_length = data_len; header->data_bytes_in_queue -= last_pkt_size; header->data_bytes_in_queue += data_len; return 0; } MuMuDVB-2.1.0/src/unicast_queue.h000066400000000000000000000031751305714132500165520ustar00rootroot00000000000000/* * mumudvb - UDP-ize a DVB transport stream. * * (C) 2009 Brice DUBOST * * The latest version can be found at http://mumudvb.braice.net * * Copyright notice: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /**@file * @brief HTML unicast headers for queue */ #ifndef _UNICAST_QUEUE_H #define _UNICAST_QUEUE_H #define UNICAST_DEFAULT_QUEUE_MAX 1024*512 /**How many packets we try to send from the queue per new packet. This value MUST be at least 2*/ #define UNICAST_MULTIPLE_QUEUE_SEND 3 /** @brief A data packet in queue. * */ typedef struct unicast_queue_data_t{ int data_length; unsigned char *data; struct unicast_queue_data_t *next; }unicast_queue_data_t; /** @brief The header of a data queue. * */ typedef struct unicast_queue_header_t{ int packets_in_queue; int data_bytes_in_queue; int full; unicast_queue_data_t *first; unicast_queue_data_t *last; }unicast_queue_header_t; void unicast_queue_clear(unicast_queue_header_t *header); #endifMuMuDVB-2.1.0/tests/000077500000000000000000000000001305714132500140745ustar00rootroot00000000000000MuMuDVB-2.1.0/tests/TestDump17.ts000066400000000000000000002674601305714132500164000ustar00rootroot00000000000000G@IHCSAT TV POLONIA_.fre*CHAINE POLONAISE A VOCATION INTERNATIONALE8HCSATTV TRWAM_freCHAINE RELIGIEUSE POLONAISEFvF.ABHCSATFRANCE 5_)frG C   C pu  C Cu  C    C P " C G $ C vP ' C  u 0 C Vu1 C ! PGe%LA CHAINE DU SAVOIR ET DE L'EDUCATIONBEHCSATC CINEMA EMOTION_$fre LE CINEMA DE TOUTES LES PASSIONSCNHCSATC CINEMA FRISSON_-fre)LE CINEMA ACTION, FANTASTIQUEG ET SUSPENSED:H CSATNRJ 12_#freTOUT L'ESPRIT NRJ DANS UNE TELEEDHCSATPARIS PREMIERE_%fre!L'ACTUALITE CULTURELLE PARISIENNEFFHCSAT 13EME RUE_,fre(LGA CHAINE DE L'INVESTIGATION ET DU CRIMEG;H CSATMEZZO_%fre!LA CHAINE DU JAZZ ET DU CLASSIQUEH?HCSATFRANCE 3_&fre"LA CHAINE GENERALISTE DE PROXIMITEI>H CSATG@N 0N"GC!MWfreBEST OF LE GRAND JOURNAL8Best of Le Grand Journal Prsent par Michel Denisot. NfreBest of Le Grand Journal Prsent par Michel Denisot. AidGSPORT+_'fre#POUR CEUX QUI VEULENT PLUS DE SPORTJ8H CSATI>TELE_!freL'INFORMATION AVEC UN GRAND ILH CSATMEZZO.MH CSATNCMESSU9H CSATI>TELE_"fG de ses comparses, Michel Denisot dcrypte les moments forts de l'actualit en recevant celles et ceux qui sont au coeur d'vnements rcents.P freAudioP freVideoP"freDVB subtGreL'INFORMATION AVEC UN GRAND I V:H CSATNRJ 12_#freTOUT L'ESPRIT NRJ DANS UNE TELEW?HCSATFRANCE 3_&fre"LA CHAINE GENERALISTE DE PROXIMITEXBHCSATFRANCEG@7 5_)fre%LA CHAINE DU SAVOIR ET DE L'EDUCATIONGE^FCCy2HCSATEURONEWS_freEURONEWS EN 9 LANGUES>(FFB|HCSAT ARIRANG TV_#freCHAGu< C  u@ C !huE C "ePuN C $AuR C %" V C % X C &P Z C &@ [ C &bu \ CGINE SUD COREENNE GENERALISTEdJHIMEDIAAL JAZEERA ENG_)fre%LA CHAINE INTERNATIONALE D'AL JAZEERAfFHCSAT NHK WORLD TV_)fre%LA CHAINE JAPONAISE D'INFO EN ANGLAISiGais ralis par Jos Bourgarel en 2007. Nfre& RalisateurJos BourgarelAnne2007(-10) La question : Le Pen et la torture Documentaire franais ralis par Jos Bourgarel en 2007G@EHCSATCANAL CANARIAS_&fre"CHAINE REGIONALE DES LES CANARIESjGHCSAT TV GALICIA_,fre(LA CHAINE REGIONALE ESPAGNOLE GALICIENNE1yJ2lA*    G. Jean-Marie Le Pen se serait rendu coupable d'actes de torture lors de la guerre d'Algrie : tmoins, journalisteN)fre#s, avocats et historiens dbattent.P freVideoP freAudioPG          _8 i   "    - 2 5 .4lA*_8Q!<~C2Gx636&A pppp_pppp74Amfmgmhmkmnmp_mfmgmhmkmnmp<BA$$$$$$$$_ $$*$|$h$G@/!freDVB subtitles (normal)TEUFRAbK OH.O1-0zMfre TOUT LE SPORT Multisports.Nfre Multisports.P freVideoP freAudioP!freDVB subtitles (normal)TG$@$$>BA        _ @IA%%%% %!%"%#%$%%_$%%E%U% %!I%"G%#y%$_%%XA-A..//G@pp"4G/:_..///:CAy_y5DA'_'nEAoFoG_oFoGFzA0B|B}B~BBBBBBBBBBBBB_@B|WB} B~G@aUFRAMO&T`O1-0zMfre TOUT LE SPORT Multisports.Nfre Multisports.P freVideoP freAudioP!freDVB subtitles (normal)TaUFRA HOy"d8O GJBMBBKBLB$BBoBBmBnBB,B7HA9!!!!!!!‡!Ç!ć!Ň!Ƈ!̄!̈́!΄!ϋ!Ћ!ы!ҋ!Ӌ_L!\!^!!!!!!!!!!!!!G@;!!!!JA ###_ ###~IJ EAoFoG_oFoGFzA0B|B}B~BBBBBBBBBBBBB_@B|WB} B~JBMBG@m("UU0^M%freLES SPECIALISTES EUROPE Football.Nfre Football.P freVideoP freAudioTaUFRAuVOU"w8OE2:Mpfre LES REGRETS`(-10) Ralis par Cdric Kahn GBKBLB$BBoBBmBnBB,B7H-A!!!!!_!\!^!!!eLPA!!!"""""""_(!+!!""S"?"F"j""gGen 2009. Avec Yvan Attal, Valeria Bruni Tedeschi. Drame franais. Nfre# Ralisateur Cdric KahnAnne2009(-10) Ralis par Cdric Kahn en 2009. Avec Yvan Attal, Valeria Bruni TedesGM&A mmmm_mmmmR`A#####$$$$ $ _(##'##$=$9$:$ >$ ?_(#$ S-AD\D]D^D_D`_D\D]GD^D_D`TBA/X/b/g////_ ./X-/b/g/4/;/#/4VdA$U$V$W$X$^$i$j$k$l$r_($Ub$V^$Wc$X$^$i $j$k $l$r_( $Wp$VGchi. Drame franais. Un architecte renoue avec son amour de jeunesse, qu'il n'a pas vue depuis quinze ans. Emports par leur passion, ils sN,fre&'aiment et se font souffrir nouveauG$UdWAz_zjX@A%%%%%%_%D%Y%%%)%>_(% ZBA""""""""_ ""("T""z"p"q"[A3-35G@_3-35`\dA&&&&&&&&&&_(&a&_&`& &&&& &&_( &E&&QؗJ ^aA'%%%%%%%%%%%%G@.P freVideoP freAudioP!freDVB subtitles (normal)TUFRA %"w8!"w8!"w8!!OBFOk"U%1G&G_0%%%%%%%!%"%%%%$`aA'&I&J&K&L&M&N&O&P&Q&R&S&T&_0&I&J&K&L&M&N&O &P&Q&R#&S&T%U5A_GMbfre&JAYCE ET LES CONQUERANTS DE LA LUMIERE7Jayce et les conqurants de la lumire "Le jardinier". Nfre( NationalitFrance - Etats-U...TDETDEJayce et les conqurants de la lumiG|AJ_JA_!A 3_ 3BBA#)#*#+#,#=#>#?#@_ #)#*#+#,#=#>#?H#@BNAe_eG &iP ] C &% ^ C & _ C '!u ` C '(P  C Pu2G@;DA'_'n#A_YJ,^gA'%%%%%%%%%%%%&G_0%-%.%/%9%1%=%@%A%5%6%7%C_`Gre "Le jardinier". Alors qu'ils font escale sur une plante dserte, Jayce et ses amis font la connaissance de Faro, un jardinier capable de redonner vie un monde mort...P freVidGgA'&I&J&K&L&M&N&O&P&Q&R&S&T&_0&I0&J:&K;&L<&M2&N>&O?&P3&Q4&RB&S8&TD_U5A_A_A_"QG@J.lA*ABCDEFGHIJUVWX_8ABfCeD%EFGHIPJ3U<V8W/X10PA          _( Z i G@8eoP freAudioT1UFRABF1!KOu!HO0ZM!freFOOTBALL EN CONTINU Football.Nfre Football.P freVideoP freAudioTaUFRAlI/Gg [ h d { f R 01&A n-n.n@nE_n-n.n@nE2lA*              _8 i   " Y X \ - 2 5 G.4lA*_8Q!<~C2]x636&A pppp_pppp74AmfmgmhmkmnG@O 2Oyc"E 0M?freZAP MCM COMPIL,Le meilleur des missions diffuses sur MCM.N2fre,Le meilleur des missions diffuses sur MCM.P freVideoP freAudioTUFRA,Gmp_mfmgmhmkmnmp8WA!"a"b"c"d"e"u"v"w"x"y"_,"a"b "c "d "e "u "v"w"x"y"<BA$$$$$$$$_ $$*$|$hG@BQO&\OBA        _ @IA%%%% %!%"%#%$%%_$%%E%U% %!I%"G%#y%$_%%XA-A../G@&//:_..///::DFH7H CSATGOD TV_ freCHAINE CHRETIENNE EN ANGLAISkF m HCSATqF! EHCSAT SONNENKLAR_G: String Quartet n14 Death and the Maiden (Part 4)P freVideoP freAudioT0UFRAҫG*fre&CHAINE ALLEMANDE: VOYAGE ET TELEACHAT3@H CSATTELE 5_)fre%LA CHAINE DE DIVERTISSEMENT ALLEMANDE?HCSATSPORT 1_'fre#LA CHAINE DE SPORT ALLEMANDE PRIVEEG@F,oiAHCSATCARTOON NETWORK_!freLA TELE PREFEREE DES CARTOONSoj:HCSATCNN INT._!freL'INFO AU-DELA DES FRONTIERESom7H CSATTCM_#freA LA DECOGUVERTE DU GRAND CINEMAooAHCSAT BOOMERANG_'fre#LA CHAINE DES DESSINS ANIMES CULTESoqHCSAT DATASYSTEM 68o8H CSATMTV HD_!freLA VERSION SPECIALE HD DE MTVoG@=8H CSATMTV HD_!freLA VERSION SPECIALE HD DE MTV F!6oHCSAT DATASYSTEM 78p8HCSAT MTV PULSE_freLA CHAINE EN MODE POP-ROCKp4HCSATMTV IDOL_G@freLA CHAINE VERSION CULTEp6H CSATVIVA_!freLA CHAINE MUSICALE ALLEMANDEpDHCSATNICKELODEON JR_%fre!LA CHAINE PRESCOLAIRE DES 3-7 ANSȥFiA.G@O$<O "51M freTITEUF"Le patron de papa". Nfre NationalitFranceTDETDE"Le patron de papa". Titeuf et ses parents sont invits manger chez le patron du pre GBHCSATRTL TELEVISION_#freLA CHAINE ALLEMANDE GENERALISTE.@H CSATRTL 2_*fre&LA CHAINE ALLEMANDE DES JEUNES ADULTES/>HCSAT SUPER RTL_$fre LA CHAINE AG@LLEMANDE DES 3-13 ANS/BH CSATVOX_.fre*LA CHAINE GENERALISTE FAMILIALE ALLEMANDE/:BH CSATN-TV_-fre)CHAINE DINFO EN CONTINU PRIVEE ALLEMANDE|,FEoFJGde Titeuf qui est gay. Titeuf dcide de faire un expos sur les homosexuels.P freVideoP freAudioT1UFRA$<1$<1U$<1G@@WJT JW @ASTRA 1JWJ TNOJW J ` JWJ`v C  pPu C Pu C Pu C  1Pu C G@HCSAT SR FERNSEHEN_-fre)LA CHAINE REGIONALE DE LA REGION RHENANIEoG:HCSATBR ALPHA_!freLA CHAINE EDUCATIVE ALLEMANDEW#'FH! HCSAT!+H CSATONZGEO_freLA TELE TOUT FOOT!4HCSATMOSAIQUE_freLES CHAINES DE CANALSAT!H CSATMOSA 2!H CSATMOSA 3!8HCSATYACHT AND SAIL_freLA CHAINE DU NAUG@3$<1E$<1!CrO"ZOj#00MSfre LE GRAND JTCLe journal tout en images et une rtrospective des courses du jour.NIfreCLe journal toGTISME!HCSATMOSAIQUE! H CSATMMD!H CSATMOSA 5!.HCSATCASH TV_freLA CHAINE DES JEUX!@HCSAT PRIVATE SPICE_"freLE MEILLEUR DU X INTERNATIONALG@`ut en images et une rtrospective des courses du jour.P freVideoP freAudioTUFRA |O4Om"5 1Mafre%LES NOUVELLES AVENTURES DE LUCKY LUKE7Les nouvelles aveG!H CSATMOSA 4! HCSAT!H CSATCDN12!HCSAT MOSAIQUE C+!HCSAT MOSAIQUE C+!HCSATMOSAIQUE!HCSAT MOSAIQUE C+!HCSATMOSAIQUE! HCSAGT!HCSAT MOSAIQUE C+!4HCSATMOSAIQUE_freLES CHAINES DE CANALSAT!H CSATMOSA 2!H CSATMOSA 3!H CSATMOSA 4!H CSATMOSA 5!HCSATBIENVEGntures de Lucky Luke "Dalton junior". Nfre NationalitFranceTDETDELes nouvelles aventures de Lucky Luke "Dalton junior". Lucky Luke poursuit les Dalton, vads du pnitencier. DGNUE SUR ASTRA!HCSAT 01 06 01 59!HCSAT 01 07 01 59!HCSAT 01 08 01 59!HCSAT 02 01 01 94!HCSAT 02 02 01 94!HCSAT 02 04 01 94!HIMEDIA 02 05G@< 01 94!HCSAT 02 06 01 94!HCSAT 01 06 04 587Fj-H CSATKTO_freTELEVISION CATHOLIQUE?HCSAT RUSSIA TODAY_"freCHAINE RUSSE D'INFO EN AGans leur fuite, une nounou leur a confi de force le bb qu'elle gardait. L'enfant s'est pris d'affection pourN:fre4 Joe, qui, lui, veut l'changer contre une ranon...P freVideoGNGLAIS?HCSAT FRANCE 24_%fre!L'ACTUALITE INTERNATIONALE 24H/24IHIMEDIA FRANCE 24 ENG_)fre%INFO INTERNATIONALE 24H/24 EN ANGLAIS8H IMEDIAEWTN_!freGLA CHAINE CATHOLIQUE MONDIALEGHCSATFRANCE 24 ARABE_'fre#INFO INTERNATIONALE 24H/24 EN ARABE;HCSATTELESUR_#freLA CHAINE PAN-LATINO-AMERICAINEAH CSATCG@P freAudioT1UFRAɬ O4O#E2kMfreNEW YORK POLICE JUDICIAIRE(-10) New York police judiciaire Srie policire amricaine avec Sam Waterston, Dennis Farina. G@ ¨%3A333 " 3A 3 3 3  @  &  (0  )  )@  6   G@CTVF_+fre'LA CHAINE CHINOISE EN VERSION FRANCAISEBHCSAT CCTV NEWS_(fre$LA CHAINE CHINOISE D'INFO EN ANGLAIS7JeXLPA!!!"""""""_GSaison 15. (24/24). "Faute de parcours". Nfre- Nationalit Etats-UnisTDEFaute de parcours(-10) New York police judiciaire Srie policire amricaine avec Sam Waterston, Dennis FarG(!+!!""S"?"F"j""gM&A mmmm_mmmmReA'######$$$$ $ $ $ _4##'###$=$9$:$ >G$ ?$ $ S-AD\D]D^D_D`_D\D]D^D_D`TBA/X/b/g////_ ./X-/b/g/4/;/#/4WAz_zjX4A%%%%%%Gina. Saison 15. (24/24). "Faute de parcours". Un train draille, entranant la mort de neuf personnes. Les policieN\freVrs ne savent pas s'il s'agit d'un acte terroriste ou si l'un dG_%D%Y%%%)%>ZBA""""""""_ ""("T""z"p"q"[A3-35_3-35`^^A$%%%%%%%%%%%%_G0%%%%%%%!%"%%%%$`^A$&I&J&K&L&M&N&O&P&Q&R&S&T_0&I&J&K&L&M&N&O &P&Q&R#&S&T%U5A_|AG@es passagers tait vis.P freVideoP freAudioP!freDVB subtitles (normal)TTUFRAE4T!!O.#ROS"U1M4freLES ZINZINS DE L'ESPACEG$`Pu C Pu  C !HPu C #%  C uPu C XPu! C $u C P  C 5  C gP G@SJ_JA_!A 3_ 38UJeXLPA!!!"""""""_(!+!!""S"?"F"j""gMG"Flashman contre Zork". Nfre NationalitFranceTDETDE"Flashman contre Zork". Le super hros Flashman et son frre Zork emmnagent dans la maison en location. Ils s'engagent dans G&A mmmm_mmmmReA'######$$$$ $ $ $ _4##'###$=$9$:$ >$ ?$ $ S-AD\D]D^D_D`_D\GD]D^D_D`TBA/X/b/g////_ ./X-/b/g/4/;/#/4WAz_zjX4A%%%%%%_%D%Y%%%)%>ZBA"""G@Aune lutte sans merci...P freVideoP freAudioT1UFRAN 0N(DC"Mpfre LES REGRETS`(-10) Ralis par Cdric Kahn en 2009. Avec Yvan Attal, Valeria Bruni TedeG"""""_ ""("T""z"p"q"[A3-35_3-35`^^A$%%%%%%%%%%%%_0%%%%%%%!%"%%%%G$`^A$&I&J&K&L&M&N&O&P&Q&R&S&T_0&I&J&K&L&M&N&O &P&Q&R#&S&T%U5A_|AJ_JA_!Gschi. Drame franais. Nfre# Ralisateur Cdric KahnAnne2009(-10) Ralis par Cdric Kahn en 2009. Avec Yvan Attal, Valeria Bruni Tedeschi. Drame franais. Un architecte renoue avG@$A 3_ 3WJ FzA0B|B}B~BBBBBBBBBBBBB_@B|WB} B~JBMBBKBLB$BBoBBmBnBB,B7H&AG !!!!_!\!^!!LPA!!!"""""""_(!+!!""S"?"F"j""gM&A mmmm_mmmmRPA###Gec son amour de jeunesse, qu'il n'a pas vue depuis quinze ans. Emports par leur passion, ils sN,fre&'aiment et se font souffrir nouveau.P freVideoP freAudioP!freDVB subtiG##$$$$ $ _(##'##$=$9$:$ >$ ?S-AD\D]D^D_D`_D\D]D^D_D`TBA/X/b/g////_ ./X-/b/g/4/;Gtles (normal)TUFRA % 0!0 0"0 0!P 0! 0!# 0!G/#/4WAz_zjX4A%%%%%%_%D%Y%%%)%>ZBA""""""""_ ""("T""z"p"q"[A3-35_3G-35`^aA'%%%%%%%%%%%%&G_0%%%%%%%!%"%%%%$`aA'&I&J&K&L&M&N&O&P&Q&R&S&T&_0&I&J&K&L&MG@(!E 0!"%N 0N#00MPfre LE JOURNALATous les quarts d'heure, un rsum de toute l'actualit sportive.NGfreATous les quarts d'heure, unG@m&N&O &P&Q&R#&S&T%U5A_|AJ_JA_}J2 %!A 3_ 3ـJ$AG@_<}[JBBA#)#*#+#,#=#>#?#@_ #)#*#+#,#=#>#?H#@BCAy_y5DA'_'nEAoFoG_oFoGFG@P rsum de toute l'actualit sportive.P freVideoP freAudioTaUFRA`OO$ ?S-AD\D]D^D_D`_D\D]D^D_D`TBA/X/b/g////_ ./X-/b/G C   C 8  C V ! C 2% # C au * C 9u, C xu. C u2 C u4 C 4GNationalitFranceTDETDE"Flashman contre Zork". Le super hros Flashman et son frre Zork emmnagent dans la maison en location. Ils s'engagent dans une lutte sans merci...P freVGg/4/;/#/4VgA!$U$V$W$X$^$i$j$k$l$r$_($Ub$V^$Wc$X$^$i $j$k $l$r_( $Wp$V$WdWAz_zjXCA%%%%%%%_G@t%D%Y%%%)%>_(% ZBA""""""""_ ""("T""z"p"q"æJ[A3-35_3-35`\dA&&&&&&G@!ideoP freAudioT1UFRAqO#>BO#U1Mfre"LA QUESTION : LE PEN ET LA TORTUREc(-10) La question : Le Pen et la torture Documentaire franais ralis par Jos BouG&&&&_(&a&_&`& &&&& &&_( &E&&Q^^A$%%%%%%%%%%%%_0%%%%%%%!%"%%%%$`G^A$&I&J&K&L&M&N&O&P&Q&R&S&T_0&I&J&K&L&M&N&O &P&Q&R#&S&T%U5A_|A_A_!A Grgarel en 2007. Nfre& RalisateurJos BourgarelAnne2007(-10) La question : Le Pen et la torture Documentaire franais ralis par Jos Bourgarel en 2007. Jean-Marie Le Pen se seG@3_ 3FuEHCSAT TV CATALUNYA_(fre$CHAINE REGIONALE ESPAGNOLE CATALANEuFHCSAT ANDALUCIA TV_)fre%CHAINE REGIONALE ESPAGNOLE ANGrait rendu coupable d'actes de torture lors de la guerre d'Algrie : tmoins, journalisteN)fre#s, avocats et historiens dbattent.P freVideoP freAudioP!freDVB subtitles (norG@RDALOUSEuBHCSAT TV MADRID_(fre$CHAINE REGIONALE ESPAGNOLE DE MADRIDkFJ'O|9H CSATTRAVEL_"freLA CHAINE DE VOYAGE EN ANGLAIS ZF;*oHCSATG DATASYSTEM 66o;H CSATMTV_'fre#LA CHAINE MUSICALE AMERICAINE EN VFoHHCSAT NICKELODEON_,fre(LA CHAINE QUI FERAIT DU BIEN AUX PARENTSo C !)uA C !PuB C "uC C "&PuD C "FuF C G DE L'OUTRE-MER$LHCSAT DIRECT STAR_0fre,LA CHAINE MUSICALE GENERATIONNELLE DE LA TNT$9H CSATLCP_%fre!LA CHAINE DE LA VIE PARLEMENTAIRE$AHCSATFRANCE 4_G@RALɱO#"e8Ob"PE2MfreMERES ET FILLESqRalis par Julie Lopes-Curval en 2009. Avec Catherine Deneuve, Marina Hands, Marie-Jose Croze. Drame franais. Nfre* RalisaG(fre$LA CHAINE PUBLIQUE DE DIVERTISSEMENT$8HCSAT A LA CARTE_freVOS PROGRAMMES A LA CARTE$ 8HCSAT A LA CARTE_freVOS PROGRAMMES A LA CARTE$ BH CSATGULLG@M0  gP hF j   k        -eGI_,fre(LA CHAINE JEUNESSE A REGARDER EN FAMILLE$ 5HCSATFRANCE _freLA CHAINE DE L'OUTRE-MER$ HCSAT A LA CARTE$ HCSAT A LA CARTE$SHCSATDATA SYSTEMGteurJulie Lopes-CurvalAnne2009Ralis par Julie Lopes-Curval en 2009. Avec Catherine Deneuve, Marina Hands, Marie-Jose Croze. Drame franais. Une trentenaire dcouvre le journal G@ [106],JDG TPS ABONNESJ 0 j(oI,^eI,^I,^nIA"#2_$1]"#2WA!YZG^`abcdfij_,YZt^]`za^bpcdifiwjxIA_$7h_qWA!!5!8!9!:!B!DGintime de sa grand-mre, qui a quitt sa famille il y a loN8fre2ngtemps. Elle tente de mieux comprendre son geste.P freVideoP freAudioP!freDVB subtitles (normal)TUFRG!E!!!!_,!5!8=!9V!:!B!DZ!E[!!!!IA'.'B'N'O'S'T'U'V'W_$'.;'B:'N'O'S8'Ty'Us'Vu'Wv-Ap1p2p3p4p5_p1p2G@A4O%XO#41McfreLE PROCES ANDREOTTIKDocumentaire allemand ralis par Maria Rosa Bobbi, Michael Busse en 1999. Nfre( RalisateurMaria Rosa BobbiAnne1999DoGp3p4p5#A_*BAoooooooo_ oo}oooooo,&A oiojomoo_oioj9omloo.lA*ABCDEFGGHIJUVWX_8ABfCeD%EFGHIPJ3U<V8W/X10^A$           h j_0  d {  R 0 hGcumentaire allemand ralis par Maria Rosa Bobbi, Michael Busse en 1999. Aprs avoir domin la vie politique italienne pendant un demi-sicle, Giulio Andreotti a failli devenir le symbG@5 j1&A n-n.n@nE_n-n.n@nEs0rAJGGTPS ALPHA TESTJ 0 j(oI,^eI,^I,^nIA"#<_$1G]"#<WA!YZ^`abcdfij_,YZt^]`za^bpcdifiwjxIA_$7hGole de la collusion du Nfrepouvoir et de la Mafia.P freVideoP freAudioTEUFRA%%XE!ρG_qWA!!5!8!9!:!B!D!E!!!!_,!5!8=!9V!:!B!DZ!E[!!!!IA'.'B'N'O'S'T'U'V'W_$'.;'B:'N'O'S8'Ty'UsG'Vu'Wv-Ap1p2p3p4p5_p1p2p3p4p5#A_*BAoooooooo_ oo}oooooo,&A oiojomoo_Goioj9omloo.lA*ABCDEFGHIJUVWX_8ABfCeD%EFGHIPJ3U<V8W/X10^A$           g j_G"uG C #PuH C #$uI5 C #CPuJ C #cuK C #PuL C $uM C 6PuQ5 C %% S C %Du TG@c0  d {  R 0 g j1&A n-n.n@nE_n-n.n@nERNJ G TNTSAT C1J0 o;A_1GO]WA!YZ^`abcdfij_,YZt^]`za^bpcdifiwjxIA_$7h_qGhA!5!8!9!:!D!E!G!H!I!J!K!L!M!N!O!P!Q!R!S!T!U!V!W!X!Y!Z![!\!]!^!_!`!a!b!c!d!f!g!h!k!l!m!n!o!p!r!s!t!u!v_!5!8=!9V!:G!DZ!E[!G!H!I!J!K!L!M!N!O!P!Q!R!S!T!U!V!W!X!Y!Z![!\!]!^!_!`!a!b!c!d!f!g!h!k!l!m!n!o!p!r!s!t!u!vGIA'.'B'N'O'S'T'U'V'W_$'.;'B:'N'O'S8'Ty'Us'Vu'Wv-Ap1p2p3p4p5_p1p2p3p4p5#A_*BAooooooG@`oo_ oo}oooooo,&A oiojomoo_oioj9omlooJ +G TNTSAT C2J0 _6( (0X;A_G1O]WA!YZ^`abcdfij_,YZt^]`za^bpcdifiwjxIA_$7Gh_qhA!5!8!9!:!D!E!G!H!I!J!K!L!M!N!O!P!Q!R!S!T!U!V!W!X!Y!Z![!\!]!^!_!`!a!b!c!d!f!g!h!k!l!m!n!o!p!r!s!t!u!v_G!5!8=!9V!:!DZ!E[!G!H!I!J!K!L!M!N!O!P!Q!R!S!T!U!V!W!X!Y!Z![!\!]!^!_!`!a!b!c!d!f!g!h!k!l!m!n!o!p!Gr!s!t!u!vIA'.'B'N'O'S'T'U'V'W_$'.;'B:'N'O'S8'Ty'Us'Vu'Wv&A p1p2p3p5_p1p2p3p5*BAoooooooo_ oG   30   3BG@\o}oooooo,4Aoiojomoooo_oioj9omlooo o̫J&G REDSAT CPLUSJ0 _630A+p_+p/A!G"#2<c_"IAZ`abcdfij_$Z`abcDdfij4A_OP4A'.'GS'T'U'V'W_'.'S'T'U'V'WAp4_p4#A_+,Aoj_oj.&A ADHJ_AD HJ04A    G   _ h 2-A     _ f e  j4A_ k8:A"a"b"c"d"e"u_"a"b,"c)"d*"e+"u(_G>BA        _ @A% _% /BA#)#*_#)#*CAy_yFA B|B}B_ B|}B}BG C %QP U5 C %t% W C &u Y C &3%  C $!PuڎG R9A#####_## ###!_(#T&A /X//_/X//VA$X_$XWAz_zZA"_"҂G@J%G REDSAT CSATJ0 _630A+p_+p4A_1]WA!YZ^`abcdfij_,YGZt^]`za^bpcdifiwjxIA_$7h_qhA!5!8!9!:!D!E!G!H!I!J!K!L!M!N!O!P!Q!R!SG@OIBFOw"V1.M*freLEONS DE STYLE"Quatre rnovations". Nfre"Quatre rnovations". De prcieux conseils en matire de mode, pour toujours avoir le bon look et tout coG!T!U!V!W!X!Y!Z![!\!]!^!_!`!a!b!c!d!f!g!h!k!l!m!n!o!p!r!s!t!u!v_!5!8=!9V!:!DZ!E[!G!H!I!J!K!L!M!N!O!P!Q!R!S!T!UG@nnatre sur les tendances du moment.P freVideoP freAudioTeUFRA#BFeBFeHBFe!3:NO% 2O"UU2 M|freBOG!V!W!X!Y!Z![!\!]!^!_!`!a!b!c!d!f!g!h!k!l!m!n!o!p!r!s!t!u!vIA'.'B'N'O'S'T'U'V'W_$'.;'B:'N'O'S8'TyG'Us'Vu'Wv&A p1p2p3p5_p1p2p3p5#A_*BAoooooooo_ oo}oooooo,4AoiojomooooGNESr(-10) Srie policire amricaine avec Emily Deschanel, David Boreanaz. Saison 2. (8/22). "La chance du dbutant". Nfre1 Nationalit Etats-UnisTDELa chance du dbutant(-10) SrG@$_oioj9omlooo onm[F!L-HCSATRFI INT_freLA RADIO DU MONDE!MGHCSATRADIO CLASSIQUE_'fre#LE MEILLEUR DE LA MUSIQUE CLASSIQUE!N5HCGSATEUROPE 1_freRADIO PRIVEE GENERALISTE!O'H CSATRMC_freINFO TALK SPORT!P&H CSATRTL_freVIVRE ENSEMBLE!QHHCSATRIRE & CHANSONS_(fre$DU RIRE Gie policire amricaine avec Emily Deschanel, David Boreanaz. Saison 2. (8/22). "La chance du dbutant". Pour mener une enqute sur des combats illgaux organiss par la mafia, Booth eGGARANTI TOUTES LES 3 MINUTES!R3HCSAT SUD RADIO_freLA RADIO DU GRAND SUD!SDHCSAT MC DOUALIYA_(fre$RADIO FRANCAISE GENERALISTE EN ARABE!T,HCSATTSF JAZZ_GfreRADIO 100% JAZZ!UO$#2tMfre%LAETITIA : BITES DURES POUR AMATRICESm5,95 E. REF. 1793342. (-18) Laetitia : bites dures pour amatrices Ralis par Laetitia. Film pornographiqueGS_,fre(LA CHAINE REGIONALE ALLEMANDE DE BAVIEREmJHCSAT HR FERNSEHEN_-fre)LA CHAINE REGIONALE GENERALISTE DE HESSE m6H CSATWDR_"freLA CHAINE REGIONALE DE G@ COLOGNE3>fFX%?HCSATHISTOIRE_&fre"LES CLES DU PRESENT PAR L'HISTOIRE%6HCSATMA CHAINE SPORT_freA CHACUN SON SPORT%BHCSATM6 MUSIC BLACK_G. Nfre RalisateurLaetitia5,95 E. REF. 1793342. (-18) Laetitia : bites dures pour amatrices Ralis par Laetitia. Film pornographique. Laetitia est en visite chez des petites amatG#freLA CHAINE DES MUSIQUES URBAINES%;HCSAT M6 MUSIC CLUB_freLA CHAINE 100% DANCEFLOOR%@HCSATVIVOLTA_(fre$LE BIEN-ETRE DES FEMMES AU QUOTIDIEN%JHCSATG@dPLANETE JUSTICE_*fre&CHAINE CONSACREE AU SYSTEME JUDICIAIRE%HCSATDATA SYSTEM 112z%F0AHCSATTV5MONDE_(fre$LA CHAINE FRANCOPHONE INTERNATIONALEGrices. Celles-ci sont encore plus cochonnes que les autres. Elles n'attendeNLfreFnt que des hommes bien monts pour se faire plaisir trs profondment.P freVideoP freAudioTG3H IMEDIA_ freLA PETITE CHAINE QUI DEMONTE;HCSAT TELEREALITE_freLA CHAINE DE LA TELEREALITE HCSAT9HCSATNRJ HITS_ freLA CHAINE MUSICALEG@qUFRA%"k% >@"k@ >! Ӂl]O%^O1-0zMfre TOUT LE SPORT Multisports.Nfre MultG DU TOP 50AHCSAT FRENCH LOVER_$fre L'EDUCATION SEXUELLE POUR ADULTE:HIMEDIA GIRONDINS TV_freLA CHAINE DES GIRONDINSHCSAT PLAYIN'Tvi" H IMEDIAG@p#HIMEDIA ACTU CANALSAT2HCSAT 01 03 01 59<HCSAT 01 03 04 58cHCSATDATA SYSTEM 18הJ GTNTSATJ0 .-A ADHJ_AD HG@Risports.P freVideoP freAudioP!freDVB subtitles (normal)TaUFRAVOo*O_B#U0Mfre HITS BASEClips. NAfre;Clips. Le meilleurs titres R'n'B, groove et GJH0A  _   2&A    _   4A_ <A$_$FAB_B R-A#####_G## ###TA /g//_ /g(//^_A$%%%%%%%%%%%%_1%e%f%g%q%i%u%x%y%m%n%o%{`_A$&I&J&K&LG@9soul du moment.P freVideoP freAudioTUFRAqL*O!LOgU"P51Mfre JEU FATALr(-12) Ralis par Roel Rein en 2008. Avec Steven Seagal, Lydia Jordan, Lance HenrikG@V&M&N&O&P&Q&R&S&T_1&Ih&Jr&Ks&Lt&Mj&Nv&Ow&Pk&Ql&Rz&Sp&T|YtJO G TNTSAT HDJ0 -.-A ADHJ_AD HJH0A  G_   2&A    _ 4 3 84A_ 9<A$_$BA#)#*_#)#*FAB_B R-A###Gsen. Film d'action amricain. Nfre" Ralisateur Roel ReinAnne2008(-12) Ralis par Roel Rein en 2008. Avec Steven Seagal, Lydia Jordan, Lance Henriksen. Film d'action amricainG##_## ###TA /g//_ /g(//VA$X$^_$X$^^bA'%%%%%%%%%%%%&G_1%e%f%g%q%i%u%G. Dpressif et alcoolique, un policier dmis de ses fonctions est contraint - officieusement - d'organiN0fre*ser l'assassinat d'un impitoyable mafieux.P freVideoP freAudioP G@x%y%m%n%o%{`bA'&I&J&K&L&M&N&O&P&Q&R&S&T&_1&Ih&Jr&Ks&Lt&Mj&Nv&Ow&Pk&Ql&Rz&Sp&T|JiJa TG TNTSAT SPS_6 (0 (0 G@.( (   2EJ*G TNTSAT C3J0 A_.-A ADHJ_AD HJH0A  _  GengAudioT!UFRAxBG2&A    _   4A_ <A$_$FAB_B R-A#####_## ###TA /g/G/_ /g(//^bA'%%%%%%%%%%%%&G_1%e%f%g%q%i%u%x%y%m%n%o%{`bA'&I&J&K&L&M&N&O&P&Q&R&S&T&_1G@4&Ih&Jr&Ks&Lt&Mj&Nv&Ow&Pk&Ql&Rz&Sp&T|~w-J`G TNTSAT C4J0 >A_.-A ADHJ_AD HJH0A  _ G 2&A    _ 4 3 84A_ 9<A$_$BA#)#*_#)#*FAB_B R-A#####_G## ###TA /g//_ /g(//VA$X$^_$X$^^_A$%%%%%%%%%%%%_1%e%f%g%q%i%u%x%y%m%n%G@po%{`_A$&I&J&K&L&M&N&O&P&Q&R&S&T_1&Ih&Jr&Ks&Lt&Mj&Nv&Ow&Pk&Ql&Rz&Sp&T|lgJ&G REDSAT BASICJ0 _630A_G"IAZ`abcdfij_$Z`abcDdfij4A_OP4A'.'S'T'U'V'W_'.'S'TG'U'V'WAp4_p4#A_+,Aoj_oj.&A ADHJ_AD HJ04A      _ h G 2-A     _ f e  j4A_ k84A"a"b"c"d"e"u_"a"b,"c)"d*"e*"u(@A% _% /BA#)#*_G#)#*CAy_yFA B|B}B_ B|}B}B R-A#####_## ###!T&A /X//_/X//VA$X_G$XWAz_zZA"_"^,A$%%%%%%%%%%%%_`/A'&I&J&K&L&M&N&O&P&Q&R&S&T&_U5A_G      _(  d {  R 01&A n-n.n@nE_n-n.n@nE2lA*              _8 i  G"UU2*MfreBONESDIFFUSE EN HD. (-10) Srie policire amricaine avec Emily Deschanel, David Boreanaz. Saison 2. (8/22). "La chance du dbutant". Nfre1 Nationalit Etats-UnisTDG  " Y X \ - 2 5 .4lA*_8Q!<~C2]x636&A pppp_pGppp74Amfmgmhmkmnmp_mfmgmhmkmnmp8wA!"a"b"c"d"e"u"v"w"x"y"_,"aZ"bi"cg"df"eh"u["v"w"x"y"_("a"b "cGELa chance du dbutantDIFFUSE EN HD. (-10) Srie policire amricaine avec Emily Deschanel, David Boreanaz. Saison 2. (8/22). "La chance du dbutant". Pour mener une enqute sur des Gu< C  u@ C !huE C "ePuN C $AuR C %" V C % X C &P Z C &@ [ C &bu \ CG "d "e "u <BA$$$$$$$$_ $$*$|$h$$@$$>BA        _ @IA%%%% %!%"%Gcombats illgaux organiss par la mafia,NRfreL Booth et Brennan se font passer pour un couple amateur de boxe clandestine.P freVideoP freAudioP!freDVB subtitles (normal)TTG@#%$%%_$%%E%U% %!I%"G%#y%$_%%XA-A..///:_..///:CAy_y5V̒FGp19HCSAT EINS EXTRA_freLA CHAGINE D'INFO ALLEMANDEp2HHCSAT EINS FESTIVAL_*fre&LA GENERALISTE ALLEMANDE DU RESEAU ARDp39HCSAT EINS PLUS_freLA CHAINE SAVOIR ALLEMANDE p4'H CSATARTE_G@0UFRAO"v8O0"EE1MWfreBEST OF LE GRAND JOURNAL8Best of Le Grand Journal Prsent par Michel Denisot. NfreBest of Le Grand Journal Prsent par MichG@]freVIVONS CURIEUXp5AHCSATPHOENIX_)fre%NEWS POLITIQUE DES 2 CHAINES ARD/ZDF %?MF).HCSATDATA SYSTEM[70]T⻨F41n-CHCSATRBB BRANDENBURG_G#freCHAINE REGIONALE DE BRANDENBURGn.HHCSAT RBB BERLIN_-fre)LA CHAINE REGIONALE GENERALISTE DE BERLINn@@H CSATNDR_,fre(LA CHAINE REGIONALE GENERALISTE DU NORDnG@QEIHCSAT MDR FERNSEHEN_+fre'LA CHAINE REGIONALE GENERALISTE DE SAXE/F4?HCSAT EUROSPORT_%fre!ON NE PLAISANTE PAS AVEC LE SPORT@H CSATTMC_G,fre(CHAINE GENERALISTE A L'ESPRIT MONEGASQUE8HCSATPLANETE_ freLE MEILLEUR DE LA DECOUVERTE9HCSATTELETOON_ freLA COUR DE RECRE A LA MAISON8H CSATVGOYAGE_!freLA TELE COMME POINT DE DEPART2H CSATLCI_fre24H/24, L'INFO VIT SUR LCI.H CSATTEVA_freTELEVISION D'EMOTIONS1HCSAT COMEDIE !_fGel Denisot. Aid de ses comparses, Michel Denisot dcrypte les moments forts de l'actualit en recevant celles et ceux qui sont au coeur d'vnements rcents.P freVideoP freAudioGreLA TELE QUI DECONNE8H CSATARTE_#freLA CHAINE CULTURELLE EUROPEENNE3HCSAT SERIE CLUB_freLA CHAINE DES SERIESAH CSATJUNE_,fre(LA TELE QUI DONGNE ENVIE D'ETRE UNE FILLE=H CSATTIJI_(fre$ET LES PETITS DEVIENNENT PLUS GRANDS@H CSATTMC_,fre(CHAINE GENERALISTE A L'ESPRIT MONEGASQUE8H CSATARTE_GP!freDVB subtitles (normal)TpUFRA"v8p!!$G@F#freLA CHAINE CULTURELLE EUROPEENNE HCSATDATA SYSTEM76RQ FYFB-H CSATNT1_freTOUT POUR SE DIVERTIRBHCSAT DATASYSTEM 94FL!6HCG@OBFOT#01Mfre FLICS DE CHOC}(-12) Ralis par Jean-Pierre Desagnat en 1983. Avec Pierre Massimi, Chantal Nobel, Jean-Luc Moreau. Film policier franais. Nfre, RalGSAT TELEMAISON_freLA PASSION DE LA MAISON!3H CSATJIMMY_freON A TOUS UNE SERIE CULTE!;HCSATSYFY UNIVERSAL_freLA CHAINE DU FANTASTIQUE"FHCSAT DGISNEY XD_,fre(LA CHAINE POUR LES GARCONS DE 8 A 14 ANS"5HCSAT L'EQUIPE TV_freAU PLUS PRES DU SPORT"?HCSATPLANETE NO LIMIT_freVOUS N'AVEZ ENCORE RIEN GisateurJean-Pierre DesagnatAnne1983(-12) Ralis par Jean-Pierre Desagnat en 1983. Avec Pierre Massimi, Chantal Nobel, Jean-Luc Moreau. Film policier franais. Une quipe de policGVU";HCSAT NATIONAL GEO_freLA CHAINE DE L'EXPLORATION";HCSATC CINEMA CLASSIC_freLE CINEMA DE REFERENCE":HCSATTRACE TV_!freMUSIQUES ET CULTURESG@p URBAINES"@HCSATC CINEMA FAMIZ_!freLE CINEMA DE TOUTE LA FAMILLE"_HCSATDATA SYSTEM[100]nF^%9HCSAT FR3 AMIENS_freCANAL REGIONAL DE FRANCEG@iers, la recherche du meurtrier de plusieurs femmes, dmantN$frele un rseau de prostitution.P freVideoP freAudioT!UFRAa+O!HO*"E0MTfreL.A. GIRG 3%;HCSAT FR3 BESANCON_freCANAL REGIONAL DE FRANCE 3%;HCSAT FR3 BORDEAUX_freCANAL REGIONAL DE FRANCE 3%8HCSAT FR3 NANCY_freCANAL REGIONAL DE FG &iP ] C &% ^ C & _ C '!u ` C '(P  C Pu2GRANCE 3%>HCSATFR3 CLERMONT FD_freCANAL REGIONAL DE FRANCE 3%8HCSAT FR3 PARIS_freCANAL REGIONAL DE FRANCE 3%9HCSAT FR3 RENNES_freCANAL REGIONAGLS LOVE BIG COCK7(-18) L.A. Girls Love Big Cock Tlfilm pornographique.N=fre7(-18) L.A. Girls Love Big Cock Tlfilm pornographique.P freVideoP freAudioP engAudioTUFRGL DE FRANCE 3%8HCSAT FR3 ROUEN_freCANAL REGIONAL DE FRANCE 3%:HCSAT FR3 LIMOGES_freCANAL REGIONAL DE FRANCE 3%7HCSATFR3 LYON_freCANAL REGIONAG@AG;O&\OK#52MfreALIEN INVASIONDIFFUSE EN HD. (-12) Ralis par Jesse V Johnson en 2007. Avec Mark Dacascos, Amelia Cooke, Emma Lahana. Film de science-fiction cGL DE FRANCE 3%BA        _ @IA%%%% %!%"%#%$%%_$%%E%U% %!I%"G canadien. Un guerrier intergalactique se rend sur Terre pour empcher un groupe dN5fre/'extraterrestres de conqurir la plante bleue.P freVideoP freAudioT0UFRA?0GG%#y%$_%%XA-A..///:_..///:CAy_y5DA'_'nEAoFoG_oFoGFzA0B|B}B~BBBBBBBBBG@O&\O>"@ 0MFfre'SCHUBERT : STRING QUARTET N14 DEAT...Information non disponibleN freInformation non disponibleP freVideoP freAudioT0UFRAf-mGBBBB_@B|WB} B~JBMBBKBLB$BBoBBmBnBB,B7HA9!!!!!!!‡!Ç!ć!Ň!Ƈ!̄!̈́!΄!ϋ!Ћ!ы!ҋ!Ӌ_L!\!^!!!!!G@[!!!!!!!!!!!!JA ###_ ###~IJ FzA0B|B}B~BBBBBBBBBBBBB_@B|WB} B~JBMG@O"ZOpI#%0M&freNAKED WILD ON 2"Bombas latinas". Nefre_"Bombas latinas". Une nouvelle saison de plaisirs sexy sous le soleil et dans les discothques.P freVideoPGBBKBLB$BBoBBmBnBB,B7H&A !!!!_!\!^!!LPA!!!"""""""_(!+!!""S"?"F"j""gM&GA mmmm_mmmmRPA#####$$$$ $ _(##'##$=$9$:$ >$ ?S-AD\D]D^D_D`_D\D]D^D_D`TBAG@5 freAudioTmUFRAP"Zm! bTO 4Oi"@01Mfre AFRICA TREKuDocumentaire franais ralis par Alexandre Poussin, Sonia Poussin, Florence Tran en 2G/X/b/g////_ ./X-/b/g/4/;/#/4WAz_zjX4A%%%%%%_%D%Y%%%)%>ZBA""""""""_ G""("T""z"p"q"[A3-35_3-35`^aA'%%%%%%%%%%%%&G_0%%%%%%%!%"%%%%$`aA'&I&J&K&LG001 (4/12). "Enfin le rift !". Nfre) RalisateurAlexandre PoussinAnne2001Documentaire franais ralis par Alexandre Poussin, Sonia Poussin, Florence Tran en 2001 (4/12). "EnfinG@&M&N&O&P&Q&R&S&T&_0&I&J&K&L&M&N&O &P&Q&R#&S&T%U5A_|AJ_JA_}J]PG TNT TRIG le rift !". Malgr les pluies diluviennes, Alexandre et Sonia continuent leur aventure et dcouvrent leN>fre8 travail des ONG au Malawi, o le sida fait des ravages.P freVideoP G@MAX10.B248FRTV^`J0  5[gwJ,^gA'%%%%%%%%%%%%&G_0%-%.%/%9%1%=%@%A%5%G6%7%C_`gA'&I&J&K&L&M&N&O&P&Q&R&S&T&_0&I0&J:&K;&L<&M2&N>&O?&P3&Q4&RB&S8&TD_U5A_A_A_G@freAudioTKUFRA&dOC4O#U1(M8freTRACKS-Propos par Jean-Marc Barbieux, David Combe. Nfre PrsentateurJean-Marc BarbieuxpPropos par Jean-Marc Barbieux, DG@ "QJ.lA*ABCDEFGHIJUVWX_8ABfCeD%EFGHIPJ3U<V8W/X10PA          _G( Z i g [ h d { f R 01&A n-n.n@nE_n-n.n@nE2lA*              _8 i   " Y X \G@avid Combe. Au sommaire : "Backstage". - "David Lynch". - "Atari Teenage Riot".P freVideoP freAudioTgUFRA4g4g!OyCOG - 2 5 .4lA*_8Q!<~C2]x636&A pppp_pppp74AmfGmgmhmkmnmp_mfmgmhmkmnmp8WA!"a"b"c"d"e"u"v"w"x"y"_,"a"b "c "d "e "u "v"w"x"y"<BA$$$$$$$$_ $G@?#0~M4freEURONEWS EN 8 LANGUESInformation non disponibleN freInformation non disponibleP freVideoP freAudioTUFRAmnXO2o*Oh{"U1M.freLE JT$(-1G$*$|$h$$@$$>BA        _ @IA%%%% %!%"%#%$%%_$%%E%U% %!I%"G%#y%$_%%XAG0) Prsent par Julien Tellouck. Nfre PrsentateurJulien Tellouck(-10) Prsent par Julien Tellouck. Du lundi au vendredi, Julien propose de dcouvrir toute l'actualit digitale, G@3-A..///:_..///::DF!^'H CSATNOVA_freLE GRAND MIX !!_4HCSATRADIO FG_freLA RADIO DE LA SCENE DJ!`4HCSAT VIBRATGION_freBIEN PLUS QUE DES HITS!a5HCSAT CONTACT FM_freLA RADIO DANCE DU NORD!b.HCSAT RADIO LATINA_fre LE SON LATINO!c1H CSATRFM_freLE MEILLEG@Ten compagnie de chroniqueurs et d'invits.P freVideoP freAudioTUFRAN@ 0N"PE2%MfreMERES ET FILLESqRalis par Julie Lopes-Curval en 2009. Avec CatherGUR DE LA MUSIQUE!d6HCSAT CHERIE FM_freVOS PLUS BELLES EMOTIONS!f+HCSATVOLTAGE_freHIT RADIO PARIS!g(H CSATOUI FM_fre LA RADIO ROCK!h0H CSATADG   30   3BGO_freLA RADIO HIP HOP & R'N'B!kDHCSATRADIO NOTRE-DAME_#fre1ERE RADIO CHRETIENNE DE FRANCE!l@HCSAT RADIO ALFA_%fre!LA RADIO DES PORTUGUAIS DE FRANCE!m>Gine Deneuve, Marina Hands, Marie-Jose Croze. Drame franais. Nfre* RalisateurJulie Lopes-CurvalAnne2009Ralis par Julie Lopes-Curval en 2009. Avec Catherine Deneuve, Marina HGHCSAT RCJ / SHALOM_!freRADIOS DE LA COMMUNAUTE JUIVE!n9HCSATBEUR FM_!freMUSIQUE ET CULTURE DU MAGHREB!o9HCSAT BBC ARABIC_freVERSION ARABE DE BBC WORGands, Marie-Jose Croze. Drame franais. Une trentenaire dcouvre le journal intime de sa grand-mre, qui a quitt sa famille il y a loN8fre2ngtemps. Elle tente de mieux comprendre sG@LD!p5HCSATRFI MULTILINGUE_freRFI EN 20 LANGUES!qHCSATRCI SAT!r4H CSATMEDI 1_freLA RADIO DU GRAND MAGHREBhF~!s=HCSATFRANCE CULTURE_GfreRADIO NATIONALE CULTURELLE!t;H CSATWRN_'fre#MIX DE RADIOS PUBLIQUES EN FRANAIS!u3HCSAT BBCW SERVICE_freLA RADIO DE LA BBC!v?HCSATRADIO COURTOISG@pon geste.P freVideoP freAudioP!freDVB subtitles (normal)TUFRAE 0!!--Ny 0NXc"U ^M%freLES SPECIALISTES EUROPE Football.NfreG@IE_freLA RADIO LIBRE FRANCOPHONE!HCSATRADIO 1!HCSATRADIO 2!HCSATRADIO 3!HCSAT RADIO FRANCE#HCSAT DATASYSTEM 24SIFRD'AHCSAGreLA TELE QUI DECONNE8H CSATARTE_#freLA CHAINE CULTURELLE EUROPEENNE3HCSAT SERIE CLUB_freLA CHAINE DES SERIESAH CSATJUNE_,fre(LA TELE QUI DONGNE ENVIE D'ETRE UNE FILLE=H CSATTIJI_(fre$ET LES PETITS DEVIENNENT PLUS GRANDS@H CSATTMC_,fre(CHAINE GENERALISTE A L'ESPRIT MONEGASQUE8H CSATARTE_G'M4freINFO 360'EN DIRECT. Prsent par Nathalie Lvy. Nfre Prsentateur Nathalie LvyEN DIRECT. Prsent par Nathalie Lvy. Tous les faits marquants de la journe, les rsultG@F#freLA CHAINE CULTURELLE EUROPEENNE HCSATDATA SYSTEM76RQ FYFB-H CSATNT1_freTOUT POUR SE DIVERTIRBHCSAT DATASYSTEM 94FL!6HCG@yats sportifs en images, l'info conomique, ainsi que la clture de Wall Street.P freVideoP freAudioTUFRAs! O 2Ob"MfreRIPOUX CONTRE RIPOUXkRalis pGSAT TELEMAISON_freLA PASSION DE LA MAISON!3H CSATJIMMY_freON A TOUS UNE SERIE CULTE!;HCSATSYFY UNIVERSAL_freLA CHAINE DU FANTASTIQUE"FHCSAT DGISNEY XD_,fre(LA CHAINE POUR LES GARCONS DE 8 A 14 ANS"5HCSAT L'EQUIPE TV_freAU PLUS PRES DU SPORT"?HCSATPLANETE NO LIMIT_freVOUS N'AVEZ ENCORE RIEN Gar Claude Zidi en 1989. Avec Philippe Noiret, Thierry Lhermitte, Guy Marchand. Comdie franaise. Nfre# Ralisateur Claude ZidiAnne1989Ralis par Claude Zidi en 1989. Avec PhiliGVU";HCSAT NATIONAL GEO_freLA CHAINE DE L'EXPLORATION";HCSATC CINEMA CLASSIC_freLE CINEMA DE REFERENCE":HCSATTRACE TV_!freMUSIQUES ET CULTURESG@p URBAINES"@HCSATC CINEMA FAMIZ_!freLE CINEMA DE TOUTE LA FAMILLE"_HCSATDATA SYSTEM[100]nF^%9HCSAT FR3 AMIENS_freCANAL REGIONAL DE FRANCEGppe Noiret, Thierry Lhermitte, Guy Marchand. Comdie franaise. Deux inspecteurs corrompus de Montmartre, dnoncs par une commerante du quartier, sont mis pied et rempN2fre,lacsG 3%;HCSAT FR3 BESANCON_freCANAL REGIONAL DE FRANCE 3%;HCSAT FR3 BORDEAUX_freCANAL REGIONAL DE FRANCE 3%8HCSAT FR3 NANCY_freCANAL REGIONAL DE FG@Q par deux confrres encore plus vreux.P freVideoP freAudioTUFRA &vOWo,O/"HCSATFR3 CLERMONT FD_freCANAL REGIONAL DE FRANCE 3%8HCSAT FR3 PARIS_freCANAL REGIONAL DE FRANCE 3%9HCSAT FR3 RENNES_freCANAL REGIONAGL DE FRANCE 3%8HCSAT FR3 ROUEN_freCANAL REGIONAL DE FRANCE 3%:HCSAT FR3 LIMOGES_freCANAL REGIONAL DE FRANCE 3%7HCSATFR3 LYON_freCANAL REGIONAGUn tour d'horizon des plus gros festivals en Europe. Zoom sur le festival Rock am Ring, qui a accueilli en juin 2010 Jay-Z, Muse, Kiss, Gossip, Rammstein, Dizzee Rascal, ou encore 30 GL DE FRANCE 3%BA        _ @IA%%%% %!%"%#%$%%_$%%E%U% %!I%"G Balfour. Saison 1. (4/13). "L'pidmie". Nfre& Nationalit Etats-UnisTDE L'pidmieDIFFUSE EN HD. (-10) Srie fantastique amricaine avec Emily Rose, Lucas Bryant, Eric Balfour. SGG%#y%$_%%XA-A..///:_..///:CAy_y5DA'_'nEAoFoG_oFoGFzA0B|B}B~BBBBBBBBBGaison 1. (4/13). "L'pidmie". Audrey dcouvre que la photo d'une femme a t publie dans le journal et pense qu'iN\freVl s'agit de sa mre. Avec l'aide de Nathan, elle dcide d'enqGBBBB_@B|WB} B~JBMBBKBLB$BBoBBmBnBB,B7HA9!!!!!!!‡!Ç!ć!Ň!Ƈ!̄!̈́!΄!ϋ!Ћ!ы!ҋ!Ӌ_L!\!^!!!!!G@[!!!!!!!!!!!!JA ###_ ###~IJ FzA0B|B}B~BBBBBBBBBBBBB_@B|WB} B~JBMG@uter sur ses origines...P freVideoP freAudioP engAudioTR0UFRA&\R0 &\R0#@&\R0!&O4O"0 GBBKBLB$BBoBBmBnBB,B7H&A !!!!_!\!^!!LPA!!!"""""""_(!+!!""S"?"F"j""gM&GA mmmm_mmmmRPA#####$$$$ $ _(##'##$=$9$:$ >$ ?S-AD\D]D^D_D`_D\D]D^D_D`TBAGMfrePOP 1000tPrsent par Thomas VDB. Avec la participation de Franck Lacombe, Sbastien Lipszyc, Emmanuel Lipszyc. "Episode 1". NfrePrsent par Thomas VDB. Avec la participatG/X/b/g////_ ./X-/b/g/4/;/#/4WAz_zjX4A%%%%%%_%D%Y%%%)%>ZBA""""""""_ G""("T""z"p"q"[A3-35_3-35`^aA'%%%%%%%%%%%%&G_0%%%%%%%!%"%%%%$`aA'&I&J&K&LGion de Franck Lacombe, Sbastien Lipszyc, Emmanuel Lipszyc. "Episode 1". Parodie du Top 50, institution musicale des annes 80, Pop 1000 propose le classement des 1000 meilleures venG@&M&N&O&P&Q&R&S&T&_0&I&J&K&L&M&N&O &P&Q&R#&S&T%U5A_|AJ_JA_}J,^gAG@tes de singles, prsenN:fre4t par Patrick Desvosges, interprt par Thomas VDB.P freVideoP freAudioTpUFRA4p! O;%^O1,"%E MfreBUG'%%%%%%%%%%%%&G_0%-%.%/%9%1%=%@%A%5%6%7%C_`gA'&I&J&K&L&M&N&O&P&Q&R&S&T&_0&I0&J:&K;&L<&M2&N>&OG@d?&P3&Q4&RB&S8&TD_U5A_A_A_"QJ.lA*ABCDEFGHIJUVWX_8ABfCeGLLITTBullitt (version remasterise) Ralis par Peter Yates en 1968. Avec Steve McQueen, R Vaughn, J Bisset. Film policier amricain. Nfre# Ralisateur Peter YatesAnne1968BullitGD%EFGHIPJ3U<V8W/X10PA          _( Z i g [ h d { f R 01&A n-n.n@nE_n-n.n@nE2lA* G             _8 i   " Y X \ - 2 5 .4lA*_8Q!<~CGt (version remasterise) Ralis par Peter Yates en 1968. Avec Steve McQueen, R Vaughn, J Bisset. Film policier amricain. Un policier, charg d'assurer la scurit d'un truand appel G2]x636&A pppp_pppp74Amfmgmhmkmnmp_mfmgmhmkmnmp8WA!"a"b"c"d"e"u"v"w"x"y"_,G tmoigner contre la maNHfreBfia, se lance dans une folle poursuite aprs le meurtre du tmoin.P freVideoP freAudioP!freDVB subtitles (normal)TUFRAl"G"a"b "c "d "e "u "v"w"x"y"<BA$$$$$$$$_ $$*$|$h$$@$$>BA        _ G C   C pu  C Cu  C    C P " C G $ C vP ' C  u 0 C Vu1 C ! PG@ @IA%%%% %!%"%#%$%%_$%%E%U% %!I%"G%#y%$_%%XA-A..///:_..///::DF!^'H CSATNOVA_freLE GG@OOkc MFfre'LA CHAINE DE L'ACTUALITE INTERNATION...Information non disponibleN freInformation non disponibleP freVideoP freAudioTUFRAO+GRAND MIX !!_4HCSATRADIO FG_freLA RADIO DE LA SCENE DJ!`4HCSAT VIBRATION_freBIEN PLUS QUE DES HITS!a5HCSAT CONTACT FM_freLA RADIO DANCE DU NORD!bG.HCSAT RADIO LATINA_fre LE SON LATINO!c1H CSATRFM_freLE MEILLEUR DE LA MUSIQUE!d6HCSAT CHERIE FM_freVOS PLUS BELLES EMOTIONS!f+HCSATVOLTAGE_G@N_ 0N!%%DM}fre MISSION GoRalis par Hoyt Yeatman en 2009. Avec Bill Nighy, Zach Galifianakis, Will Arnett. Film d'aventures amricain. Nfre$ Ralisateur Hoyt YeatmGfreHIT RADIO PARIS!g(H CSATOUI FM_fre LA RADIO ROCK!h0H CSATADO_freLA RADIO HIP HOP & R'N'B!kDHCSATRADIO NOTRE-DAME_#fre1ERE RADIO CHRETIEGNNE DE FRANCE!l@HCSAT RADIO ALFA_%fre!LA RADIO DES PORTUGUAIS DE FRANCE!m>HCSAT RCJ / SHALOM_!freRADIOS DE LA COMMUNAUTE JUIVE!n9HCSATBEUR FM_!freMUGanAnne2009Ralis par Hoyt Yeatman en 2009. Avec Bill Nighy, Zach Galifianakis, Will Arnett. Film d'aventures amricain. Des cochons d'Inde, auxiliaires du FBI, dcouvrent un complGSIQUE ET CULTURE DU MAGHREB!o9HCSAT BBC ARABIC_freVERSION ARABE DE BBC WORLD!p5HCSATRFI MULTILINGUE_freRFI EN 20 LANGUES!qHCSATRCI SAT!r4H CSATMEGot menaant les Etats-Unis. Ils tentent de N1fre+le djouer, en dpit de nombreux obstacles.P freVideoP freAudioP engAudioTUFRA5 0 0G@-DI 1_freLA RADIO DU GRAND MAGHREBhF~!s=HCSATFRANCE CULTURE_freRADIO NATIONALE CULTURELLE!t;H CSATWRN_'fre#MIX DE RADIOS PUBLIQUES EN FRANGAIS!u3HCSAT BBCW SERVICE_freLA RADIO DE LA BBC!v?HCSATRADIO COURTOISIE_freLA RADIO LIBRE FRANCOPHONE!HCSATRADIO 1!HCSATRADIO 2!HCSATRG@;E 0 0!%NN' 0NXb!T Mvfre$LES RENCONTRES DE LA SOIREE DE JEUDIMEN DIRECT. Phase de poules. 4e journe. Les rencontres G@?ADIO 3!HCSAT RADIO FRANCE#HCSAT DATASYSTEM 24SIFRD'AHCSAT YES ITALIA_&fre"LA CHAINE DES AMOUREUX DE L'ITALIE" FH!HCSAT 01 07 04 5G8!HCSAT 01 08 04 58!HCSAT 02 01 04 93!HCSAT 02 02 04 93!HCSAT 02 04 04 93!HCSAT 02 05 04 93!HCSAT 02 06 04 93!HCSATDATA SYSTEM[96]zGde la soire de jeudi.NSfreMEN DIRECT. Phase de poules. 4e journe. Les rencontres de la soire de jeudi.P freAudioP freVideoT!UFRA% 0!!M(kG@FtNeEHCSAT CANAL+ 3D_+fre'CANAL+ DONNE UNE 3EME DIMENSION A LA TVHCSATDATA SYSTEM[102]yx4FOT7HCSATLUXE.TV_freLA VITRINE DU MONDE GDU LUXE7HCSATSKY NEWS_freLa chane de news anglaise/X3HCSAT LIBERTY TV_freLA TELE DES VACANCES/bMHCSATCHAINE ETUDIANTE_,fre(LA CHAINE DE L'EMPLG@OO0i yM/freCANAL TV REALITEInformation non disponibleN freInformation non disponibleP freVideoP freAudioTUFRAv=O$ROR$"0%Mgfre GOI ET DE LA FORMATION/g@HCSATTV8 MONT-BLANC_!freLA CHAINE ALPINE DE PROXIMITE/5H CSATBFM TV_freL'INFO NOUVELLE GENERATION/5H CSATBFM TV_freL'INGTOUT DEPEND 2UPrsent par Benjamin Vincent. Invite : Aurlie Filippetti (dpute PS de Moselle). Nfre8 PrsentateurBenjamin VincentInvitAurlie FilippettiPrsent par BenjaminG@FO NOUVELLE GENERATION/>HCSATDIRECT 8_%fre!LA CHAINE GENERALISTE DE L'INEDIT/@HIMEDIADIRECT 8_%fre!LA CHAINE GENERALISTE DE L'INEDIT*4F`&I7HCGu< C  u@ C !huE C "ePuN C $AuR C %" V C % X C &P Z C &@ [ C &bu \ CGSATFR3 CAEN_freCANAL REGIONAL DE FRANCE 3&J9HCSAT FR3 NANTES_freCANAL REGIONAL DE FRANCE 3&K7HCSATFR3 NICE_freCANAL REGIONAL DE FRANCE 3&L:HCSAG Vincent. Invite : Aurlie Filippetti (dpute PS de Moselle). La dpute socialiste Aurlie Filippetti part la rencontre de Thibaut, 28 ans, qui a cr un cabinet de reNqfrekcrutGT FR3 ORLEANS_freCANAL REGIONAL DE FRANCE 3&M8HCSAT FR3 DIJON_freCANAL REGIONAL DE FRANCE 3&N;HCSAT FR3 POITIERS_freCANAL REGIONAL DE FRANCE 3&O8HGCSAT FR3 REIMS_freCANAL REGIONAL DE FRANCE 3&P;HCSAT FR3 GRENOBLE_freCANAL REGIONAL DE FRANCE 3&Q8HCSAT FR3 LILLE_freCANAL REGIONAL DE FRANCE 3&R=HGement pour les jeunes des quartiers. Endett, il doit dposer le bilan et dnonce l'absence de soutien.P freVideoP freAudioTkUFRA5#Rk#RkGCSATFR3 STRASBOURG_freCANAL REGIONAL DE FRANCE 3&S>HCSATFR3 MONTPELLIER_freCANAL REGIONAL DE FRANCE 3&T=HCSATFR3 VIA STELLA_freCANAL REGIONAL DEG@e0#Rk0#Rk0#Rk0#Rk!u|O#@BO""0PMxfrePERIL EN HAUTE MERaPril en haute mer (saison 5) DG@, FRANCE 3&HCSATDATA SYSTEM 120ɓJeXLPA!!!"""""""_(!+!!""S"?"F"j""gM&A mmmm_mmmmGReA'######$$$$ $ $ $ _4##'###$=$9$:$ >$ ?$ $ S-AD\D]D^D_D`_D\D]D^D_D`TBA/X/b/g/Gocumentaire amricain ralis en 2009 (Ep. 7). "Le sprint final". Nfre Anne2009Pril en haute mer (saison 5) Documentaire amricain ralis en 2009 (Ep. 7). "Le sprint final". LaG///_ ./X-/b/g/4/;/#/4WAz_zjX4A%%%%%%_%D%Y%%%)%>ZBA""""""""_ ""("T"G"z"p"q"[A3-35_3-35`^^A$%%%%%%%%%%%%_0%%%%%%%!%"%%%%$`^A$&I&J&K&L&M&N&O&P&Q&G saison du crabe royal s'achve : les quipes tentent de rentabiliser au maximum leurs dernires heures ; bord du Cornelia Marie, la frusNfretration est palpable.P freVideoP GR&S&T_0&I&J&K&L&M&N&O &P&Q&R#&S&T%U5A_|AJ_JA_!A 3_ 38UG@freAudioTKUFRAC5OTJ.Ou 9MfreLE POINT SUR L'INFOEN DIRECT. Prsent par T Dugeon, N Daynac. Avec la participation de F Pinet. Invite : La Seydoux (comG@JeXLPA!!!"""""""_(!+!!""S"?"F"j""gM&A mmmm_mmmmReA'######$$$$ $ G@ ¨%3A333 " 3A 3 3 3  @  &  (0  )  )@  6   G$ $ _4##'###$=$9$:$ >$ ?$ $ S-AD\D]D^D_D`_D\D]D^D_D`TBA/X/b/g////_ ./X-/b/g/4/;/Gdienne, pour Belle Epine). Nfre/ PrsentateurThierry DugeonInvit La SeydouxEN DIRECT. Prsent par T Dugeon, N Daynac. Avec la participation de F Pinet. Invite : La Seydoux G#/4WAz_zjX4A%%%%%%_%D%Y%%%)%>ZBA""""""""_ ""("T""z"p"q"[A3-35_3-G35`^^A$%%%%%%%%%%%%_0%%%%%%%!%"%%%%$`^A$&I&J&K&L&M&N&O&P&Q&R&S&T_0&I&J&K&L&M&N&O G(comdienne, pour Belle Epine). Chaque soir de la semaine, une synthse et une analyse des vnementNPfreJs de la journe. Les unes de la presse du lendemain sont passes en revue.G@&P&Q&R#&S&T%U5A_|AJ_JA_!A 3_ 3WJ2 %!A 3_ 3G@ـJ EAoFoG_oFoGFzA0B|B}B~BBBBBBBBBBBBB_@B|WB} B~JBMBBKBLB$BBoBBmBnBB,B7H-G@JP freVideoP freAudioP!freDVB subtitles (normal)TeUFRA\O;W.O1,"%E MfreBULLITTBullitt (version remasterise) Ralis par Peter Yates en 1968. Avec GA!!!!!_!\!^!!!eLPA!!!"""""""_(!+!!""S"?"F"j""gM&A mmmm_mmmmR`A#G &iP ] C &% ^ C & _ C '!u ` C '(P  C Pu2G####$$$$ $ _(##'##$=$9$:$ >$ ?_(#$ S-AD\D]D^D_D`_D\D]D^D_D`TBA/X/b/g////_ GSteve McQueen, R Vaughn, J Bisset. Film policier amricain. Nfre# Ralisateur Peter YatesAnne1968Bullitt (version remasterise) Ralis par Peter Yates en 1968. Avec Steve McQueeG./X-/b/g/4/;/#/4VdA$U$V$W$X$^$i$j$k$l$r_($Ub$V^$Wc$X$^$i $j$k $l$r_( $Wp$V$UdWAz_zjX@A%%%%%Gn, R Vaughn, J Bisset. Film policier amricain. Un policier, charg d'assurer la scurit d'un truand appel tmoigner contre la maNHfreBfia, se lance dans une folle poursuite aprG@M0  gP hF j   k        -eG%_%D%Y%%%)%>_(% ZBA""""""""_ ""("T""z"p"q"[A3-35_3-35`\dA&&&&&&&&&G@K&_(&a&_&`& &&&& &&_( &E&&QؗJ ^aA'%%%%%%%%%%%%&G_0%%%%%%%!%"%%%G@as le meurtre du tmoin.P freVideoP freAudioP!freDVB subtitles (normal)TUFRA2O$lVO]!05MUfreLES PAROIS DE L'EXTREME9Documentaire allemand ralis G%$`aA'&I&J&K&L&M&N&O&P&Q&R&S&T&_0&I&J&K&L&M&N&O &P&Q&R#&S&T%U5A_|AJ_JA_G!A 3_ 3BBA#)#*#+#,#=#>#?#@_ #)#*#+#,#=#>#?H#@BNAe_eDA'_'n#A_Gpar Pepe Danquart en 2007. Nfre% Ralisateur Pepe DanquartAnne2007Documentaire allemand ralis par Pepe Danquart en 2007. Les exploits des frres Alexander et Thomas Huber, des G@YJ$A_<}[JBBA#)#*#+#,#=#>#?#@_ #)#*#+#,#=#>#?H#@BCAy_y5DA'_'nEAG@passionns d'altitude qui n'hsitent pas prendre tous les risques pour assouvir leur got de l'extN frerme.P freVideoP freAudioTAUFRASUeOMBFO|!EP2MtGoFoG_oFoGFzA0B|B}B~BBBBBBBBBBBBB_@B|WB} B~JBMBBKBLB$BBoBBmBnBB,B7HBA!!!!!!!!_G !\!!^!!!!e!dJA ###_ ###LPA!!!"""""""_(!+!!""S"?"F"j""gM&A mmmm_GfreENTRE LA VIE ET LA MORGUEVDocumentaire franais ralis par Eric Wastiaux en 2004. "Entre la vie et la morgue". Nfre% Ralisateur Eric WastiauxAnne2004Documentaire franais rGmmmmRPA#####$$$$ $ _(##'##$=$9$:$ >$ ?S-AD\D]D^D_D`_D\D]D^D_D`TBA/X/b/g//G//_ ./X-/b/g/4/;/#/4VgA!$U$V$W$X$^$i$j$k$l$r$_($Ub$V^$Wc$X$^$i $j$k $l$r_( $Wp$V$WdWAz_zjXGalis par Eric Wastiaux en 2004. "Entre la vie et la morgue". L'histoire de quelques personnes qui travaillent l'Institut de science mdico-lgal de Richmond, l'une des morgues les G@CA%%%%%%%_%D%Y%%%)%>_(% ZBA""""""""_ ""("T""z"p"q"æJ[A3-35_3-3Gplus Nfrerputes des Etats-Unis.P freVideoP freAudioTEUFRAUBFE PBFEBFE BFE PBFEG5`\dA&&&&&&&&&&_(&a&_&`& &&&& &&_( &E&&Q^^A$%%%%%%%%%%%%_0%%%%%%G@ !1Or 2O )!WMfreCLOCKERS(-16) Ralis par Spike Lee en 1995. Avec Harvey Keitel, Mekhi Phifer, Isaiah Washington, John Turturro. Film policier amricain. GNfre! Ralisateur Spike LeeAnne1995(-16) Ralis par Spike Lee en 1995. Avec Harvey Keitel, Mekhi Phifer, Isaiah Washington, John Turturro. Film policier amricain. Deux frres dG%!%"%%%%$`^A$&I&J&K&L&M&N&O&P&Q&R&S&T_0&I&J&K&L&M&N&O &P&Q&R#&S&T%U5A_|A_Ge Brooklyn, l'un pre de famille, l'autre petit dlinquant, se retrouventNIfreC impliqus dans une affaire de meurtre et souponns par la police.P freVideoP freAudioP engAuG@:A_!A 3_ 3BM0 5H CSATCANAL+_freET TELLEMENT PLUS ENCORE ! 5HCSAT CANAL+ DECALE_freCOMPLETEMENT DECAG@ZdioTUFRA"E 2"P 2 2!..GOWo,O/"O$a"M/GALLEMANDEmk8HCSATZDF INFO_freLA CHAINE DE NEWS DE LA ZDFmn! ӅGoooo,&A oiojomoo_oioj9omloo.lA*ABCDEFGHIJUVWX_8ABfCeD%EFGHIPJ3U<V8W/X10^A$G$`Pu C Pu  C !HPu C #%  C uPu C XPu! C $u C P  C 5  C gP G@N" 0NO"E "Mfre30 ROCKuSrie humoristique amricaine avec Julianne Moore, Tina Fey, Alec Baldwin. Saison 4. (11/22). "Le blues de l'hiver". Nfre; NbEpSerie5 NationG@           g j_0  d {  R 0 g j1&A n-n.n@nE_n-n.n@nERNJ G TNTSAT C1J0 o;AG_1O]WA!YZ^`abcdfij_,YZt^]`za^bpcdifiwjxIA_Galit Etats-UnisTDELe blues de l'hiverSrie humoristique amricaine avec Julianne Moore, Tina Fey, Alec Baldwin. Saison 4. (11/22). "Le blues de l'hiver". Alors que Liz souhaiteraitG$7h_qhA!5!8!9!:!D!E!G!H!I!J!K!L!M!N!O!P!Q!R!S!T!U!V!W!X!Y!Z![!\!]!^!_!`!a!b!c!d!f!g!h!k!l!m!n!o!Gp!r!s!t!u!v_!5!8=!9V!:!DZ!E[!G!H!I!J!K!L!M!N!O!P!Q!R!S!T!U!V!W!X!Y!Z![!\!]!^!_!`!a!b!c!d!f!g!h!kG emmener toute l'quipe du Girlie Show MiamNLfreFi, Jack prfre prendre la direction de Boston pour y retrouver Nancy.P freVideoP freAudioP engAudioTS UFRA[!yG!l!m!n!o!p!r!s!t!u!vIA'.'B'N'O'S'T'U'V'W_$'.;'B:'N'O'S8'Ty'Us'Vu'Wv-Ap1p2p3p4p5_p1p2p3p4p5#AG@_*BAoooooooo_ oo}oooooo,&A oiojomoo_oioj9omlooJ +G TNTSAT C2J0 _6( G@Nj 0N"#% 2OMfre"PAR SUITE D'UN ARRET DE TRAVAIL...Par suite d'un arrt de travail... Ralis par Frdric Andri en 2008. Avec Charles Berling, Patrick Timsit. ComdiG(0X;A_1O]WA!YZ^`abcdfij_,YZt^]`za^bpcdifiwjxIAGe franaise. Nfre' RalisateurFrdric AndriAnne2008Par suite d'un arrt de travail... Ralis par Frdric Andri en 2008. Avec Charles Berling, Patrick Timsit. Comdie franaG_$7h_qhA!5!8!9!:!D!E!G!H!I!J!K!L!M!N!O!P!Q!R!S!T!U!V!W!X!Y!Z![!\!]!^!_!`!a!b!c!d!f!gG!h!k!l!m!n!o!p!r!s!t!u!v_!5!8=!9V!:!DZ!E[!G!H!I!J!K!L!M!N!O!P!Q!R!S!T!U!V!W!X!Y!Z![!\!]!^!_!`!a!b!cGise. Deux hommes que tout oppose voyagent ensemble en voiture pour se rendre Rome : NLfreFle premier est un doux rveur, l'autre a la tte bien sur les paules.P freVideoP frG!d!f!g!h!k!l!m!n!o!p!r!s!t!u!vIA'.'B'N'O'S'T'U'V'W_$'.;'B:'N'O'S8'Ty'Us'Vu'Wv&A p1p2p3p5_p1p2p3p5