SASC-NG
DVBSoftCAM

plugin_dss.c

Go to the documentation of this file.
00001 /*
00002    DVBLoopback
00003    Copyright Alan Nisota 2006
00004 
00005    This file is part of DVBLoopback.
00006 
00007     DVBLoopback is free software; you can redistribute it and/or modify
00008     it under the terms of the GNU General Public License as published by
00009     the Free Software Foundation; either version 2 of the License, or
00010     (at your option) any later version.
00011 
00012     DVBLoopback is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015     GNU General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with DVBLoopback; if not, write to the Free Software
00019     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 */
00021 #ifdef USE_DSS
00022 
00023 #include <stdlib.h>
00024 #include <stdio.h>
00025 #include <stdint.h>
00026 #include <fcntl.h>
00027 #include <sys/ioctl.h>
00028 #include <signal.h>
00029 #include <string.h>
00030 #include <getopt.h>
00031 #include <unistd.h>
00032 #include <errno.h>
00033 #include <assert.h>
00034 #include <pthread.h>
00035 
00036 #include <netinet/in.h>
00037 
00038 #include "list.h"
00039 #include <linux/dvb/dmx.h>
00040 #include <linux/dvb/frontend.h>
00041 #include "msg_passing.h"
00042 #include "process_req.h"
00043 
00044 #define PLUGIN_ID 14
00045 #define DBG_NAME "DSS"
00046 #include "debug.h" //This is required to happen AFTER PLUGIN_ID is defined
00047 
00048 #define DSS_SYMBOLRATE 22211000
00049 #define DSS_PMTPID 0x20
00050 #define DSS_NITPID 0x10
00051 #define DSS_NETWORKID 0x1f0f
00052 #define TS_SIZE 188
00053 #define PTS_ONLY         0x80
00054 #define PTS_DTS          0xC0
00055 
00056 struct dss_hdr {
00057   int packet_framing;
00058   int bundle_boundary;
00059   int control_flag;
00060   int control_sync;
00061   int scid;
00062   int continuity_counter;
00063   int header_designator_type;
00064   int header_designator_id;
00065   int toggle_flag;
00066 };
00067 
00068 struct dss_pkt {
00069   struct list_head list;
00070   struct dss_hdr hdr;
00071   int64_t        rts;
00072   uint8_t        buf[184+127+1];
00073   int            buf_len;
00074   int            cont;
00075   int            start;
00076   int            fd;
00077   //Audio related stuff
00078   int            is_video;
00079   int            audio_len;
00080   int            audio_packlen;
00081   uint8_t        audio_pack[16];
00082   int            audio_tmp_len;
00083   uint8_t        audio_tmp[4];
00084 };
00085 
00086 struct cir {
00087   int pip_flag;
00088   int dip_flag;
00089   int use_heap;
00090   int long_name_flag;
00091   int logo_flag;
00092   int scid_size_flag;
00093   int service_paradigm_indicator;
00094   int number_of_scids;
00095   int pip_transponder;
00096   int dip_transponder;
00097   int channel_transponder;
00098   int virt_channel_number;
00099   int network_id;
00100   uint8_t short_name[4];
00101   int scid[16];
00102   int scid_type[16];
00103 };
00104 
00105 struct cssm {
00106   int number_of_channels;
00107   int segment_size;
00108   int buf_len;
00109   uint8_t buf[65536];
00110 };
00111 
00112 struct segment_list {
00113   int number_of_segments;
00114   int up_scid;
00115   int pip_scid;
00116   int dip_scid;
00117   int default_network_id;
00118   int provider_id;
00119   int checksum;
00120 };
00121 
00122 struct mpg {
00123   struct segment_list segl;
00124   struct cssm cssm;
00125   struct cir *cir;
00126   int cir_len;
00127   int num_channels;
00128   int current_transponder;
00129 };
00130 
00131 struct dss {
00132   struct list_head list;
00133   int adapt;
00134   pthread_mutex_t lock;
00135   struct list_head pkt_ll; //struct dss_pkt
00136   struct mpg mpg;
00137   uint32_t old_standard;
00138   int is_dss;
00139   uint8_t *buf;
00140   uint32_t buf_len;
00141   uint32_t buf_used;
00142   uint8_t unused[131];
00143   uint8_t unused_len;
00144   
00145 };
00146 
00147 static int dss_opt = 0;
00148 static int opt_enable = 0;
00149 static char * opt_file = NULL;
00150 static struct option dss_Opts[] = {
00151   {"dss-enable", 0, &dss_opt, 'e'},
00152   {"dss-file", 1, &dss_opt, 'f'},
00153   {0, 0, 0, 0},
00154 };
00155 
00156 LIST_HEAD(dsslist);
00157 LIST_HEAD(dsspkt_empty_queue);
00158 
00159 //taken and adapted from libdtv, (c) Rolf Hakenes
00160 // CRC32 lookup table for polynomial 0x04c11db7
00161 static unsigned int crc_table[256] = {
00162    0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
00163    0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
00164    0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
00165    0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
00166    0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
00167    0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
00168    0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
00169    0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
00170    0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
00171    0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
00172    0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
00173    0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
00174    0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
00175    0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
00176    0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
00177    0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
00178    0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
00179    0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
00180    0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
00181    0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
00182    0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
00183    0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
00184    0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
00185    0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
00186    0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
00187    0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
00188    0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
00189    0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
00190    0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
00191    0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
00192    0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
00193    0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
00194    0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
00195    0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
00196    0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
00197    0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
00198    0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
00199    0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
00200    0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
00201    0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
00202    0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
00203    0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
00204    0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4};
00205 
00206 unsigned int crc32_04c11db7 (const unsigned char *d, int len, unsigned int crc)
00207 {
00208    register int i;
00209    const unsigned char *u=(unsigned char*)d; // Saves '& 0xff'
00210 
00211    for (i=0; i<len; i++)
00212       crc = (crc << 8) ^ crc_table[((crc >> 24) ^ *u++)];
00213 
00214    return crc;
00215 }
00216 static void get_pespts(uint8_t *spts,uint8_t *pts)
00217 {
00218 
00219         pts[0] = 0x01 |
00220                 ((spts[0] & 0xC0) >>5);
00221         pts[1] = ((spts[0] & 0x3F) << 2) |
00222                 ((spts[1] & 0xC0) >> 6);
00223         pts[2] = 0x01 | ((spts[1] & 0x3F) << 2) |
00224                 ((spts[2] & 0x80) >> 6);
00225         pts[3] = ((spts[2] & 0x7F) << 1) |
00226                 ((spts[3] & 0x80) >> 7);
00227         pts[4] = 0x01 | ((spts[3] & 0x7F) << 1);
00228 }
00229 static int write_pes_header(uint8_t id, int length , uint64_t PTS, uint64_t DTS,
00230                      uint8_t *obuf, int stuffing, uint8_t ptsdts)
00231 {
00232         uint8_t le[2];
00233         uint8_t dummy[3];
00234         uint8_t *pts;
00235         uint8_t ppts[5];
00236         uint32_t lpts;
00237         uint8_t *dts;
00238         uint8_t pdts[5];
00239         uint32_t ldts;
00240         int c;
00241         uint8_t headr[3] = {0x00, 0x00, 0x01};
00242         
00243         lpts = htonl((PTS/300ULL) & 0x00000000FFFFFFFFULL);
00244         pts = (uint8_t *) &lpts;
00245         get_pespts(pts,ppts);
00246         if ((PTS/300ULL) & 0x0000000100000000ULL) ppts[0] |= 0x80;
00247 
00248         ldts = htonl((DTS/300ULL) & 0x00000000FFFFFFFFULL);
00249         dts = (uint8_t *) &ldts;
00250         get_pespts(dts,pdts);
00251         if ((DTS/300ULL) & 0x0000000100000000ULL) pdts[0] |= 0x80;
00252 
00253         c = 0;
00254         memcpy(obuf+c,headr,3);
00255         c += 3;
00256         memcpy(obuf+c,&id,1);
00257         c++;
00258 
00259         le[0] = 0;
00260         le[1] = 0;
00261         length -= 6;
00262 
00263         le[0] |= ((uint8_t)(length >> 8) & 0xFF); 
00264         le[1] |= ((uint8_t)(length) & 0xFF); 
00265         memcpy(obuf+c,le,2);
00266         c += 2;
00267 
00268         dummy[0] = 0x80;
00269         dummy[1] = 0;
00270         dummy[2] = stuffing;
00271         
00272         if (ptsdts == PTS_ONLY){
00273                 dummy[2] += 5;
00274                 dummy[1] |= PTS_ONLY;
00275                 ppts[0] |= 0x20;
00276         } else  if (ptsdts == PTS_DTS){
00277                 dummy[2] += 10;
00278                 dummy[1] |= PTS_DTS;
00279                 ppts[0] |= 0x30;
00280                 pdts[0] |= 0x10;
00281         }
00282                 
00283 
00284         memcpy(obuf+c,dummy,3);
00285         c += 3;
00286 
00287         if (ptsdts == PTS_ONLY){
00288                 memcpy(obuf+c,ppts,5);
00289                 c += 5;
00290         } else if ( ptsdts == PTS_DTS ){
00291                 memcpy(obuf+c,ppts,5);
00292                 c += 5;
00293                 memcpy(obuf+c,pdts,5);
00294                 c += 5;
00295         }
00296 
00297         memset(obuf+c,0xFF,stuffing);
00298         c += stuffing;
00299 
00300         return c;
00301 }
00302 static int write_ts_header(int pid, int payload_start, int count,
00303                     int64_t SCR, uint8_t *obuf, int stuff)
00304 {
00305         int c = 0;
00306         uint8_t *scr;
00307         uint32_t lscr;
00308         uint16_t scr_ext = 0;
00309 
00310         obuf[c++] = 0x47;
00311         obuf[c++] = (payload_start ? 0x40 : 0x00) | ((pid >> 8) & 0x1f);
00312         obuf[c++] = pid & 0xff;
00313         obuf[c++] = ((SCR >= 0 || stuff) ? 0x30 : 0x10) | count;
00314         if (SCR >= 0|| stuff) {
00315                 if (stuff)
00316                         stuff--;
00317                 int size = stuff;
00318                 unsigned char flags = 0;
00319                 if(SCR >= 0) {
00320                         if(size < 7)
00321                                 size = 7;
00322                         flags |= 0x10;
00323                 }
00324                 obuf[c++] = size;
00325                 if(size) {
00326                         obuf[c++] = flags;
00327                         size--;
00328                 }
00329                 if(SCR >= 0) {
00330                         uint8_t bit;
00331                         lscr = (uint32_t) ((SCR/300ULL) & 0xFFFFFFFFULL);
00332                         bit = (lscr & 0x01) << 7;
00333                         lscr = htonl(lscr >> 1);
00334 
00335                         scr = (uint8_t *) &lscr;
00336                         scr_ext = (uint16_t) ((SCR%300ULL) & 0x1FFULL);
00337                         obuf[c++] = scr[0];
00338                         obuf[c++] = scr[1];
00339                         obuf[c++] = scr[2];
00340                         obuf[c++] = scr[3];
00341                         obuf[c++] = bit | 0x7e | (scr_ext >> 8);
00342                         obuf[c++] = scr_ext & 0xff;
00343                         size -= 6;
00344                 }
00345                 while(size-- > 0)
00346                         obuf[c++] = 0xff;
00347         }
00348         return c;
00349 }
00350 //extract PTS from Picture frame
00351 int get_ptsdts(unsigned char *buf, int len, uint64_t *pts, uint64_t *dts)
00352 {
00353   int picture_coding_type;
00354   int hdr_len;
00355   uint32_t pts1, dts1;
00356   picture_coding_type = (buf[5] >> 3) & 0x07;
00357   hdr_len = (picture_coding_type > 1) ? 9 : 8;
00358   if(buf[hdr_len + 3] == 0xb5)
00359     hdr_len += 9;
00360   if(buf[hdr_len + 3] == 0xb2) {
00361     pts1 = ((buf[hdr_len+6] & 0x03)   << 30) +
00362            ((buf[hdr_len+7] & 0x7f) << 23) +
00363            ((buf[hdr_len+8])          << 15) +
00364            ((buf[hdr_len+9] & 0x7f) << 8) +
00365            buf[hdr_len+10];
00366     dts1 = ((buf[hdr_len+13] & 0x03)   << 30) +
00367            ((buf[hdr_len+14] & 0x7f) << 23) +
00368            ((buf[hdr_len+15])          << 15) +
00369            ((buf[hdr_len+16] & 0x7f) << 8) +
00370            buf[hdr_len+17];
00371     //NOTE:  This is wrong.  DSS timestamps only have a resolution of 2^32/300
00372     dprintf2("pts: %08x/%f dts: %08x/%f\n", pts1, pts1 / 27000000.0, dts1, dts1 / 27000000.0);
00373     *pts = pts1;
00374     *dts = dts1;
00375     return 1;
00376   }
00377   return 0;
00378 }
00379 struct dss_pkt *parse_dss_hdr(unsigned char *buf, struct dss *dss)
00380 {
00381   struct dss_pkt *pkt;
00382   int scid = ((buf[1] << 8) + buf[2]) & 0x0fff;
00383   
00384   ll_find_elem(pkt, dss->pkt_ll, hdr.scid, scid, struct dss_pkt);
00385   if(! pkt) {
00386     //dprintf0("Found unexpected scid: %d %02x %02x %02x ...\n", scid, buf[0], buf[1], buf[2]);
00387     return NULL;
00388   }
00389   pkt->hdr.packet_framing         = buf[1] >> 7;
00390   pkt->hdr.bundle_boundary        = (buf[1] >> 6) & 0x01;
00391   pkt->hdr.control_flag           = (buf[1] >> 5) & 0x01;
00392   pkt->hdr.control_sync           = (buf[1] >> 4) & 0x01;
00393   pkt->hdr.continuity_counter     = (buf[3] >> 4);
00394   pkt->hdr.header_designator_type = (buf[3] >> 2) & 0x03;
00395   pkt->hdr.header_designator_id   = buf[3] & 0x03;
00396   return pkt;
00397 }
00398 
00399 void write_dummy_ts(uint8_t *ts)
00400 {
00401   static const uint8_t data[TS_SIZE] = {0x47, 0x1f, 0xff, 0x10};
00402   memcpy(ts, data, TS_SIZE);
00403 }
00404 
00405 
00406 //We should always write out a frame here
00407 int write_ts_frame(struct dss_pkt *pkt, uint8_t *ts)
00408 {
00409   int len;
00410   int stuff;
00411   int pos = 0;
00412 
00413   stuff = (pkt->buf_len < TS_SIZE - 4) ? TS_SIZE - 4 - pkt->buf_len : 0;
00414 
00415   pos = write_ts_header(pkt->hdr.scid, pkt->start, pkt->cont,
00416                         pkt->rts, ts, stuff);
00417   pkt->cont = (pkt->cont + 1) & 0x0f;
00418   len = TS_SIZE - pos;
00419   pkt->rts = -1;
00420   pkt->start = 0;
00421   memcpy(ts+pos, pkt->buf, len);
00422   pkt->buf_len -= len;
00423   //This is horribly inefficient!
00424   if(pkt->buf_len > 0)
00425     memmove(pkt->buf, pkt->buf + len, pkt->buf_len);
00426   else 
00427     pkt->buf_len = 0;
00428   return 1;
00429 }
00430 
00431 void write_ts(uint8_t **out, uint8_t *buf, int len, struct dss_pkt *pkt)
00432 {
00433   uint8_t ts[188];
00434 
00435   if(pkt->hdr.bundle_boundary) {
00436     while(pkt->buf_len != 0) {
00437       if(write_ts_frame(pkt, ts)) {
00438         memcpy(*out,  ts, TS_SIZE);
00439         *out += TS_SIZE;
00440       }
00441     }
00442     pkt->start = 1;
00443     pkt->hdr.bundle_boundary = 0;
00444   }
00445   memcpy(pkt->buf + pkt->buf_len, buf, len);
00446   pkt->buf_len += len;
00447   if(pkt->buf_len >= 184) {
00448     if(write_ts_frame(pkt, ts)) {
00449       memcpy(*out,  ts, TS_SIZE);
00450       *out += TS_SIZE;
00451     }
00452   }
00453 }
00454 
00455 int make_pes(uint8_t *outbuf, uint8_t *inbuf, struct dss_pkt *pkt)
00456 {
00457   int ptsdts;
00458   uint64_t pts, dts;
00459   if(get_ptsdts(inbuf, 127, &pts, &dts))
00460     ptsdts = PTS_DTS;
00461   else
00462     ptsdts = 0;
00463   if(ptsdts && pkt)
00464     pkt->rts = dts;
00465   return write_pes_header(0xE0, 6, pts, dts, outbuf, 0, ptsdts);
00466 }
00467 
00468 void parse_aux(uint8_t *buf, struct dss_pkt *pkt)
00469 {
00470   if((buf[0] & 0x3f) > 0x01)
00471     return;
00472   pkt->rts = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6];
00473 }
00474 void get_scids(struct cir *cir, int basescid)
00475 {
00476   static const uint8_t sc[16][17] = {
00477     {}, //0x00
00478     {2, 0x0f, 0}, //0x01
00479     {9, 0x0f, 0, 1, 2, 3, 4, 5, 6, 7}, //0x02
00480     {9, 0x0f, 1, 1, 2, 3, 4, 5, 6, 7}, //0x03
00481     {9, 0x0f, 2, 1, 2, 3, 4, 5, 6, 7}, //0x04
00482     {9, 0x0f, 3, 1, 2, 3, 4, 5, 6, 7}, //0x05
00483     {}, //0x06
00484     {}, //0x07
00485     {}, //0x08
00486     {}, //0x09
00487     {9, 0x0f, 0, 1, 2, 3, 4, 5, 6, 7}, //0x0a
00488     {}, //0x0b
00489     {1, 0x00}, //0x0c
00490     {1, 0x0d}, //0x0d
00491     {1, 0x0c}, //0x0e
00492     {1, 0x0f}, //0x0f
00493   };
00494   int spi = cir->service_paradigm_indicator;
00495   int i;
00496 
00497   for(i = 0; i < cir->number_of_scids; i++) {
00498     cir->scid[i] = basescid+i;
00499     if(i < sc[spi][0])
00500       cir->scid_type[i] = sc[spi][i+1];
00501     else
00502       cir->scid_type[i] = sc[spi][sc[spi][0]];
00503   }
00504   if(spi == 0x0a)
00505     cir->scid_type[cir->number_of_scids-1] = 0x09;
00506 }
00507 void read_extended_chaninfo(struct cir *cir, uint8_t *heap)
00508 {
00509   int i, offset;
00510 
00511   if(cir->service_paradigm_indicator == 0) {
00512     for(i=0; i < cir->number_of_scids; i++) {
00513       if(! cir->scid_size_flag) {
00514         if((i & 0x01) == 0) {
00515           cir->scid[i] = heap[0];
00516           cir->scid_type[i] = heap[1] >> 4;
00517           heap++;
00518         } else {
00519           cir->scid[i] = heap[1];
00520           cir->scid_type[i] = heap[0] & 0x0f;
00521           heap+=2;
00522         }
00523       } else {
00524         if((i & 0x01) == 0) {
00525           cir->scid[i] = (heap[0] << 4) | (heap[1] >> 4);
00526           cir->scid_type[i] = heap[1] & 0x0f;
00527         } else {
00528           cir->scid[i] = ((heap[0] << 8) | heap[1] >> 4) & 0xfff;
00529           cir->scid_type[i] = heap[0] >> 4;
00530         }
00531         heap+=2;
00532       }
00533     }
00534   } else {
00535     int basescid;
00536     basescid = cir->scid_size_flag ? ((heap[0] << 4) | (heap[1] >> 4)) :
00537                                      heap[0];
00538     get_scids(cir, basescid);
00539     heap+=2;
00540   }
00541   if(cir->pip_flag == 0x02)
00542     heap+=2;
00543   if(cir->dip_flag == 0x02)
00544     heap+=2;
00545   if(cir->long_name_flag) {
00546     //we could do a strcpy here
00547     while(*heap)
00548       heap++;
00549     heap++;
00550   }
00551   if(cir->logo_flag)
00552     heap++;
00553   offset = 1;
00554   if(*heap & 0x20) offset+=2; //altcn_flag
00555   if(*heap & 0x10) offset+=2; //ext4_flag
00556   if(*heap & 0x08) offset+=1; //altci_flag
00557   if(*heap & 0x04) cir->network_id = heap[offset]; //altni_flag
00558 }
00559 
00560 void process_cir(struct cir *cir, uint8_t *cssm, int satid,
00561                  int provid, uint8_t *heap)
00562 {
00563   int i;
00564   int offset = provid ? 1 : 0;
00565   cir->network_id = satid;
00566   cir->pip_flag = (cssm[0] >> 2) & 0x03;
00567   cir->dip_flag = cssm[0] & 0x03;
00568   cir->use_heap = cssm[1] & 0x80 ? 1 : 0;
00569   cir->long_name_flag = cssm[1] & 0x40;
00570   cir->logo_flag = cssm[1] & 0x20;
00571   cir->scid_size_flag = (cssm[1] >> 4) & 0x01;
00572   cir->service_paradigm_indicator = cssm[1] & 0x0f;
00573   cir->number_of_scids = cssm[2+offset];
00574   cir->pip_transponder = cssm[3+offset];
00575   cir->dip_transponder = cssm[4+offset];
00576   cir->channel_transponder = cssm[5+offset];
00577   cir->virt_channel_number = cssm[6+offset] << 8 | cssm[7+offset];
00578   memcpy(cir->short_name, &cssm[8+offset], 4);
00579   if(cir->use_heap) {
00580     int index = (cssm[15+4*offset] << 8) | cssm[16+4*offset];
00581     read_extended_chaninfo(cir, heap + index);
00582   } else {
00583     get_scids(cir, cssm[15+4*offset]);
00584   }
00585   //we have added a channel
00586   dprintf2("%d(%c%c%c%c) tp:%d sat:%02x", cir->virt_channel_number,
00587          cir->short_name[0], cir->short_name[1], cir->short_name[2],
00588          cir->short_name[3], cir->channel_transponder, cir->network_id);
00589   for(i = 0; i < cir->number_of_scids; i++)
00590     dprintf2(" %03x:%02x", cir->scid[i], cir->scid_type[i]);
00591   dprintf2("\n");
00592 }
00593 
00594 int get_avail_chan(struct mpg *mpg, uint32_t *indices, int max_chan)
00595 {
00596   int i, j = 0;
00597   int cur_tp = mpg->current_transponder;
00598   dprintf2("Searching %d channels on sat:%d tp:%d\n", mpg->num_channels, mpg->segl.default_network_id, cur_tp);
00599   for(i = 0; i < mpg->num_channels && j < max_chan; i++) {
00600     if(mpg->cir[i].network_id != mpg->segl.default_network_id ||
00601        mpg->cir[i].channel_transponder != cur_tp)
00602       continue;
00603     indices[j++] = i;
00604     dprintf2("  Found channel: %d\n", mpg->cir[i].virt_channel_number);
00605   }
00606   dprintf2("Found %d channels\n", j);
00607   return j;
00608 }
00609 
00610 void write_chaninfo(uint8_t **out, struct mpg *mpg)
00611 {
00612   static int patcount = 0, pmtcount = 0, nitcount = 0;
00613   int pos, i, j, pmtpos, patpos = 9, chan_cnt;
00614   uint8_t buf[188];
00615   //PMT Program number = 1
00616   //PMT PID = 0x20
00617   uint8_t pat[184] = {0x00, 0x00, 0xb0, 0x00, 0xfe, 0xef, 0xc1, 0x00, 0x00};
00618   uint8_t pmt[184] ={0x00, 0x02, 0xb0, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00,
00619                      0x00, 0x00, 0xf0, 0x00};
00620   uint8_t nit[184] ={0x00, 0x40, 0xf0, 0x0d, 0x00, 0x00, 0xff, 0x00, 0x00,
00621                      0xf0, 0x00, 0xf0, 0x00};
00622   uint32_t chanidx[40]; //40 is max channels in a single PAT frame
00623 
00624   chan_cnt = get_avail_chan(mpg, chanidx, 40);
00625   if(!chan_cnt)
00626     return;
00627   patcount = (patcount + 1) & 0x0f;
00628   //PAT
00629   //add NIT info
00630   pat[patpos++] = 0;
00631   pat[patpos++] = 0;
00632   pat[patpos++] = 0xe0 | ((DSS_NITPID >> 8) & 0x1f);
00633   pat[patpos++] = DSS_NITPID & 0xff;
00634   for(i = 0; i < chan_cnt; i++) {
00635     pat[patpos++] = (mpg->cir[chanidx[i]].virt_channel_number >> 8) & 0xff;
00636     pat[patpos++] = mpg->cir[chanidx[i]].virt_channel_number & 0xff;
00637     pat[patpos++] = 0xe0 | ((DSS_PMTPID >> 8) & 0x1f);
00638     pat[patpos++] = DSS_PMTPID & 0xff;
00639   }
00640   pat[3] = (patpos + 4 - 3 - 1);
00641   *(uint32_t *)(pat+patpos)= htonl(crc32_04c11db7(pat+1, patpos-1, 0xffffffff));
00642   patpos+=4;
00643   pos = write_ts_header(0x00, 1, patcount, -1, buf, 0);
00644   memcpy(buf+pos, pat, patpos);
00645   pos += patpos;
00646   memset(buf+pos, 0xff, TS_SIZE - pos);
00647   memcpy(*out,  buf, TS_SIZE);
00648   *out += TS_SIZE;
00649   //PMT
00650   for(i = 0; i < chan_cnt; i++) {
00651     pos = 0;
00652     pmtpos = 13;
00653     pos += write_ts_header(DSS_PMTPID, 1, pmtcount, -1, buf+pos, 0);
00654     for(j = 0; j < mpg->cir[i].number_of_scids; j++) {
00655       uint8_t type;
00656       uint32_t pid = mpg->cir[i].scid[j];
00657       uint8_t lang[3] = {0, 0, 0};
00658       switch(mpg->cir[i].scid_type[j]) {
00659         case 0x08:
00660         case 0x0f:
00661           type = 0x02;
00662           break;
00663         case 0x09:
00664           type = 0x81;
00665           break;
00666         case 0x00:
00667           type = 0x04;
00668           lang[0] = 'e'; lang[1] = 'n'; lang[2] = 'g';
00669           break;
00670         case 0x01:
00671           type = 0x04;
00672           lang[0] = 's'; lang[1] = 'p'; lang[2] = 'a';
00673           break;
00674         case 0x02:
00675           type = 0x04;
00676           lang[0] = 'f'; lang[1] = 'r'; lang[2] = 'e';
00677           break;
00678         case 0x03:
00679           type = 0x04;
00680           lang[0] = 'd'; lang[1] = 'e'; lang[2] = 'u';
00681           break;
00682         case 0x04:
00683           type = 0x04;
00684           lang[0] = 'i'; lang[1] = 't'; lang[2] = 'a';
00685           break;
00686         case 0x05:
00687           type = 0x04;
00688           lang[0] = 'j'; lang[1] = 'p'; lang[2] = 'n';
00689           break;
00690         case 0x06:
00691           type = 0x04;
00692           lang[0] = 'k'; lang[1] = 'o'; lang[2] = 'r';
00693           break;
00694         case 0x07:
00695           type = 0x04;
00696           lang[0] = 'z'; lang[1] = 'h'; lang[2] = 'o';
00697           break;
00698       }
00699       pmt[pmtpos++] = type;
00700       pmt[pmtpos++] = 0xe0 | (0xff & (pid >> 8));
00701       pmt[pmtpos++] = 0xff & pid;
00702       pmt[pmtpos++] = 0xf0;
00703       if(lang[0]) {
00704         pmt[pmtpos++] = 0x06;
00705         pmt[pmtpos++] = 0x0a;
00706         pmt[pmtpos++] = 0x04;
00707         pmt[pmtpos++] = lang[0];
00708         pmt[pmtpos++] = lang[1];
00709         pmt[pmtpos++] = lang[2];
00710         pmt[pmtpos++] = 0x00;
00711       } else {
00712         pmt[pmtpos++] = 0x00;
00713       }
00714     }
00715     pmt[3] = pmtpos + 4/*crc*/ - 3 - 1/*pointer_field*/;
00716     pmt[4] = (mpg->cir[i].virt_channel_number >> 8) & 0xff;
00717     pmt[5] = mpg->cir[i].virt_channel_number & 0xff;
00718     pmt[9] = 0xf0 | (0xff & (mpg->cir[i].scid[0] >> 8));
00719     pmt[10] = 0xff & mpg->cir[i].scid[0];
00720     *(uint32_t *)&pmt[pmtpos] = htonl(crc32_04c11db7(&pmt[1], pmtpos -1,
00721                                       0xffffffff));
00722     pmtpos+=4;
00723     memcpy(buf+pos, pmt, pmtpos);
00724     pos += pmtpos;
00725     memset(buf+pos, 0xff, TS_SIZE - pos);
00726     memcpy(*out,  buf, TS_SIZE);
00727     *out += TS_SIZE;
00728     pmtcount = (pmtcount+1) & 0x0f;
00729   }
00730   //NIT
00731   pos = 0;
00732   nit[4] |= (DSS_NETWORKID >> 8) & 0xff;
00733   nit[5] |= DSS_NETWORKID & 0xff;
00734   *(uint32_t *)&nit[13] = htonl(crc32_04c11db7(&nit[1], 12, 0xffffffff));
00735   pos += write_ts_header(DSS_NITPID, 1, nitcount, -1, *out, 0);
00736   memcpy(*out + pos, nit, 17);
00737   pos+=17;
00738   memset(*out+pos, 0xff, TS_SIZE - pos);
00739   *out += TS_SIZE;
00740   nitcount = (nitcount+1) & 0x0f;
00741 }
00742 
00743 void parse_mpg(uint8_t **out, struct mpg *mpg, uint8_t *buf)
00744 {
00745   uint8_t seg_sync[4] = {0xaa, 0x55, 0xa5, 0xa5};
00746   uint32_t *segsync = (uint32_t *)seg_sync;
00747   uint8_t cssm_sync[4] = {0x55, 0xaa, 0x5a, 0x5a};
00748   uint32_t *cssmsync = (uint32_t *)cssm_sync;
00749   struct segment_list *segl = &mpg->segl;
00750   struct cssm         *cssm = &mpg->cssm;
00751   uint8_t *p, *heap;
00752   int i, offset;
00753 
00754   if(segl->number_of_segments == 0) {
00755     if (*(uint32_t *)buf == *segsync && (buf[4] & 0xf0) == 0) {
00756       segl->number_of_segments = buf[19];
00757       segl->up_scid            = (buf[53] << 8 | buf[54]) & 0xfff;
00758       segl->pip_scid           = (buf[55] << 8 | buf[56]) & 0xfff;
00759       segl->dip_scid           = (buf[57] << 8 | buf[58]) & 0xfff;
00760       segl->default_network_id = buf[97];
00761       segl->provider_id        = buf[107];
00762       segl->checksum           = buf[125] << 8 | buf[126];
00763       segl->number_of_segments--;
00764       mpg->num_channels = 0;
00765     }
00766     return;
00767   }
00768   if(cssm->segment_size == 0 && *(uint32_t *)buf == *cssmsync) {
00769     cssm->number_of_channels = buf[5];
00770     cssm->segment_size       = buf[6] << 8 | buf[7];
00771     cssm->buf_len = 0;
00772     dprintf2("Searching for %d channels in %d bytes (ns:%d)\n",
00773            cssm->number_of_channels, cssm->segment_size,segl->number_of_segments);
00774   }
00775   if(cssm->segment_size) {
00776     memcpy(cssm->buf + cssm->buf_len, buf, 127);
00777     cssm->buf_len += 127;
00778     if(cssm->segment_size > 127) {
00779       cssm->segment_size -= 127;
00780       return;
00781     }
00782     p = &cssm->buf[8];
00783     offset = segl->provider_id ? 1 : 0;
00784     heap = &p[(17 + 4 * offset) * cssm->number_of_channels];
00785     mpg->num_channels += cssm->number_of_channels;
00786     if(mpg->cir_len < mpg->num_channels) {
00787       dprintf1("Reallocating CIR: %d < %d\n", mpg->cir_len, mpg->num_channels);
00788       mpg->cir = (struct cir *)realloc(mpg->cir,
00789                                        mpg->num_channels * sizeof(struct cir));
00790       mpg->cir_len = mpg->num_channels;
00791     }
00792     for(i = cssm->number_of_channels; i > 0; i--) {
00793       process_cir(&mpg->cir[mpg->num_channels-i], p, segl->default_network_id,
00794                   segl->provider_id, heap);
00795       p += 17 + 4*offset;
00796     }
00797     cssm->segment_size = 0;
00798   }
00799   if(--segl->number_of_segments == 0)
00800     write_chaninfo(out, mpg);
00801 }
00802 
00803 void write_audio_pack(uint8_t **out, uint8_t *pack, struct dss_pkt *pkt)
00804 {
00805   pkt->audio_len = (pack[4] << 8) | pack[5];
00806   assert(pkt->audio_len);
00807   pkt->hdr.bundle_boundary = 1;
00808   if(pack[3] == 0xbf) {
00809     //This is already a PES stream
00810     write_ts(out, pack, 11, pkt);
00811   } else {
00812     //Need to convert MPEG1 pkt to MPEG2-PES
00813     //for our purpose the only difference is that the PES is 3 bytes longer
00814     int i, len;
00815     for(i = 10; i >= 6; i--)
00816       pack[i+3] = pack[i];
00817     len = pkt->audio_len + 3;
00818     pack[4] = (len >> 8) & 0xff;
00819     pack[5] = len & 0xff;
00820     pack[6] = 0x80;
00821     pack[7] = 0x80;
00822     pack[8] = 0x05;
00823     write_ts(out, pack, 14, pkt);
00824   }
00825   pkt->audio_len -=5;
00826   pkt->audio_packlen = 0;
00827 }
00828 
00829 //Try to find a start code, since audio frames aren't aligned to DSS
00830 //boundaries
00831 void find_audio(uint8_t **out, uint8_t *buf, int buflen, struct dss_pkt *pkt)
00832 {
00833   int len;
00834   int ok = 0;
00835   if(pkt->audio_packlen) {
00836     memcpy(pkt->audio_pack + pkt->audio_packlen, buf, 11 - pkt->audio_packlen);
00837     buf += 11 - pkt->audio_packlen;
00838     buflen -= 11 - pkt->audio_packlen;
00839     write_audio_pack(out, pkt->audio_pack, pkt);
00840   }
00841   len = (pkt->audio_len < buflen) ? pkt->audio_len : buflen;
00842   if(len) {
00843     write_ts(out, buf, len, pkt);
00844     pkt->audio_len -= len;
00845     ok = 1;
00846   }
00847   if(len == buflen || pkt->audio_len)
00848     return;
00849   if(pkt->audio_tmp_len) {
00850     //we know there are 4 bytes of header in front of buf, so let's overwrite
00851     buf = buf - pkt->audio_tmp_len;
00852     buflen += pkt->audio_tmp_len;
00853     memcpy(buf, pkt->audio_tmp, pkt->audio_tmp_len);
00854     pkt->audio_tmp_len = 0;
00855   }
00856   while(len + 4 <= buflen) {
00857     if(buf[len] == 0x00  && buf[len+1] == 0x00 && buf[len+2] == 0x01 &&
00858        ((buf[len+3] & 0xe0) == 0xc0 || buf[len+3] == 0xbf)) {
00859       int packlen = (11 < buflen - len) ? 11 : buflen - len;
00860       memcpy(pkt->audio_pack, buf + len, packlen);
00861       pkt->audio_packlen = packlen;
00862       if(packlen == 11) {
00863         write_audio_pack(out, pkt->audio_pack, pkt);
00864         len += 11;
00865         if(len < buflen) {
00866           write_ts(out, buf + len, buflen - len, pkt);
00867           pkt->audio_len -= buflen - len;
00868         }
00869       }
00870       return;
00871     }
00872     assert(ok != 1);
00873     len++;
00874   }
00875   if (len == buflen)
00876     return;
00877   pkt->audio_tmp_len = buflen - len;
00878   memcpy(pkt->audio_tmp, buf + len, pkt->audio_tmp_len);
00879   return;
00880 }
00881 
00882 void parse_dss(struct dss *dss, uint8_t *data, int len) {
00883   int pos;
00884   uint8_t *buf, *nextbuf, *out = dss->buf + dss->buf_used;
00885   struct dss_pkt *pktptr;
00886   if(dss->unused_len) {
00887     memcpy(dss->unused + dss->unused_len, data, 131 - dss->unused_len);
00888     nextbuf = dss->unused;
00889     pos = -dss->unused_len;
00890   } else {
00891     nextbuf = data;
00892     pos = 0;
00893   }
00894   while (pos <= len - 131) {
00895     pos+= 131;
00896     buf = nextbuf;
00897     if(dss->unused_len) {
00898       nextbuf = data + (131 - dss->unused_len);
00899       dss->unused_len = 0;
00900     } else {
00901       nextbuf = buf + 131;
00902     }
00903     if((pktptr = parse_dss_hdr(buf, dss)) == NULL)
00904       continue;
00905     if(pktptr->hdr.control_flag == 0) {
00906       //can't handle encrypted streams
00907       continue;
00908     }
00909     if(pktptr->hdr.header_designator_type == 0) {
00910       //Check the aux packet to see if there's an RTS in there
00911       //We're currently using the DTS for the SCR, so no need to parse
00912       //AUX packets at the moment
00913       //parse_aux(buf+4, pktptr);
00914       continue;
00915     }
00916     if(pktptr->hdr.scid == 0x009) {
00917         //do pat/pmt stuff here
00918         parse_mpg(&out, &dss->mpg, buf+4);
00919         continue;
00920     }
00921     if(pktptr->hdr.bundle_boundary) {
00922       //We should only get here for PES or ES data packets
00923       pktptr->is_video = 1;
00924       if(buf[7] >= 0xb9) {
00925         //This is a PES packet nothing else to do
00926         write_ts(&out, buf+4, 127, pktptr);
00927       } else {
00928         //This is an ES frame, and we need to add a PES to it
00929         uint8_t peshdr[TS_SIZE];
00930         int peslen;
00931         peslen = make_pes(peshdr, buf+4, pktptr);
00932         write_ts(&out, peshdr, peslen, pktptr);
00933         write_ts(&out, buf+4, 127, pktptr);
00934       }
00935     } else {
00936       //This is a continuation of the previous frame
00937       //Do we need to find the end 1st?
00938       if(! pktptr->is_video) {
00939         find_audio(&out, buf+4, 127, pktptr);
00940       } else {
00941         write_ts(&out, buf+4, 127, pktptr);
00942       }
00943     }
00944   }
00945   dss->buf_used = out - dss->buf;
00946   if(pos < len) {
00947     dprintf3("Storing %d bytes %02x %02x %02x...\n", len - pos, data[pos], data[pos+1], data[pos+2]);
00948     memcpy(dss->unused, data + pos, len - pos);
00949     dss->unused_len = len - pos;
00950   }
00951 }
00952 
00953 static uint32_t get_transponder(uint32_t freq)
00954 {
00955 #define DSS_LOF 11250000L
00956   int i;
00957   static uint32_t freqmap[] = {
00958     12224, 12239, 12253, 12268, 12282, 12297, 12311, 12326, 12341, 12355,
00959     12370, 12381, 12399, 12414, 12428, 12443, 12457, 12472, 12486, 12501,
00960     12516, 12530, 12545, 12559, 12574, 12588, 12603, 12618, 12632, 12647,
00961     12661, 12676};
00962   freq = (freq + DSS_LOF) / 1000L;
00963   for(i = 0; i < 32; i++) {
00964     if(freq >= freqmap[i] - 2 && freq <= freqmap[i] + 2) {
00965       dprintf0("Tuned to transponder: %d\n", i);
00966       return i;
00967     }
00968   }
00969   return 32;
00970 }
00971 static struct dss *find_dss_from_pc(struct parser_cmds *pc)
00972 {
00973   struct list_head *ptr;
00974   list_for_each(ptr, &dsslist) {
00975     struct dss *dss = list_entry(ptr, struct dss);
00976     if(dss->adapt == pc->common->virt_adapt);
00977       return dss;
00978   }
00979   return NULL;
00980 }
00981 static void fe_tune(struct parser_cmds *pc, struct poll_ll *fdptr,
00982                     cmdret_t *result, int *ret,
00983                     unsigned long int cmd, unsigned char *data)
00984 {
00985   int is_dss = 0;
00986   uint32_t freq;
00987   struct dvb_frontend_parameters_new fep2;
00988   struct dss *dss = find_dss_from_pc(pc);
00989   
00990   if(cmd == FE_SET_FRONTEND) {
00991     dprintf1("Tuning frontend\n");
00992     struct dvb_frontend_parameters *fep =(struct dvb_frontend_parameters *)data;
00993     is_dss = (fep->u.qpsk.symbol_rate == DSS_SYMBOLRATE);
00994     freq = fep->frequency;
00995   } else if(cmd == FE_SET_FRONTEND2) {
00996     dprintf1("Tuning frontend\n");
00997     struct dvb_frontend_parameters_new *fep =
00998           (struct dvb_frontend_parameters_new *)data;
00999     if(dss->old_standard == FE_DVB_S || dss->old_standard == FE_QPSK)
01000       is_dss = (fep->u.qpsk.symbol_rate == DSS_SYMBOLRATE);
01001     else if(dss->old_standard == FE_DVB_S2)
01002       is_dss = (fep->u.qpsk2.symbol_rate == DSS_SYMBOLRATE);
01003     else
01004       return;
01005     freq = fep->frequency;
01006   } else if(cmd == FE_SET_STANDARD) {
01007     dprintf1("Setting standard to %u\n", (uint32_t)data);
01008     dss->old_standard = (*(unsigned long *)data) & 0xffffffff;
01009     return;
01010   }
01011   if(! is_dss) {
01012     dprintf1("Got non DSS frontend message\n");
01013 //    if(dss->is_dss)
01014 //      ioctl(fdptr->fd, FE_SET_STANDARD, dss->old_standard);
01015     return;
01016   }
01017   pthread_mutex_lock(&dss->lock);
01018   if(ioctl(fdptr->fd, FE_SET_STANDARD, FE_DSS))
01019     return;
01020   dss->mpg.current_transponder = get_transponder(freq);
01021   dss->is_dss = 1;
01022   dss->buf_used = 0;
01023   dss->unused_len = 0;
01024   fep2.frequency = freq;
01025   fep2.inversion = INVERSION_AUTO;
01026   fep2.u.qpsk2.symbol_rate = 20000000;
01027   fep2.u.qpsk2.fec_inner = FEC_5_6;
01028   fep2.u.qpsk2.modulation = MOD_DSS_QPSK;
01029   usleep(200000);
01030   *ret = ioctl(fdptr->fd, FE_SET_FRONTEND2, &fep2);
01031   usleep(200000);
01032   pthread_mutex_unlock(&dss->lock);
01033   *result = CMD_STOPALL;
01034   dprintf0("Switched to DSS mode\n");
01035   return;
01036 }
01037 
01038 static void fe_close(struct parser_cmds *pc, struct poll_ll *fdptr,
01039                      cmdret_t *result, int *ret,
01040                      unsigned long int cmd, unsigned char *data)
01041 {
01042   struct dss *dss = find_dss_from_pc(pc);
01043   dss->is_dss = 0;
01044   pthread_mutex_lock(&dss->lock);
01045   while(! list_empty(&dss->pkt_ll)) {
01046     struct dss_pkt * pkt = list_entry(dss->pkt_ll.next, struct dss_pkt);
01047     list_del(&pkt->list);
01048     list_add(&pkt->list, &dsspkt_empty_queue);
01049   }
01050   pthread_mutex_unlock(&dss->lock);
01051 }
01052 
01053 static void close_demux(struct parser_cmds *pc, struct poll_ll *fdptr,
01054                         cmdret_t *result, int *ret,
01055                         unsigned long int cmd, unsigned char *data)
01056 {
01057   struct dss_pkt *pkt;
01058   struct dss *dss = find_dss_from_pc(pc);
01059   pthread_mutex_lock(&dss->lock);
01060   ll_find_elem(pkt, dss->pkt_ll, fd, fdptr->fd, struct dss_pkt);
01061   if(pkt) {
01062     list_del(&pkt->list);
01063     list_add(&pkt->list, &dsspkt_empty_queue);
01064   }
01065   pthread_mutex_unlock(&dss->lock);
01066 }
01067 static void set_demux(struct parser_cmds *pc, struct poll_ll *fdptr,
01068                       cmdret_t *result, int *ret,
01069                       unsigned long int cmd, unsigned char *data)
01070 {
01071   struct dss_pkt *pkt;
01072   struct dmx_pes_filter_params *dmx;
01073   struct dss *dss= find_dss_from_pc(pc);
01074   if(! dss->is_dss) {
01075     dprintf2("Ignoring demux ioctl\n");
01076     return;
01077   }
01078   if(cmd == DMX_SET_PES_FILTER) {
01079     dmx = (struct dmx_pes_filter_params *)data;
01080     if(dmx->output != DMX_OUT_TS_TAP) {
01081       dprintf0("Tried to open DMX in non TAP mode\n");
01082       *ret = 1;
01083       *result = CMD_STOPALL;
01084       return;
01085     }
01086     if(dmx->pid == 0x00) {
01087       //PAT requested let's open 009
01088       ll_find_elem(pkt, dss->pkt_ll, hdr.scid, 0x009, struct dss_pkt);
01089       if(pkt) {
01090         *ret = 0;
01091         *result = CMD_STOPALL;
01092         return;
01093       }
01094       dmx->pid = 0x009;
01095     } else if(dmx->pid == DSS_PMTPID) {
01096       *ret = 0;
01097       *result = CMD_STOPALL;
01098       return;
01099     }
01100     pthread_mutex_lock(&dss->lock);
01101     pop_entry_from_queue(pkt, &dsspkt_empty_queue, struct dss_pkt);
01102     bzero(pkt, sizeof( struct dss_pkt));
01103     pkt->hdr.scid = dmx->pid;
01104     pkt->fd = fdptr->fd;
01105     pkt->rts = -1;
01106     list_add(&pkt->list, &dss->pkt_ll);
01107     *ret = ioctl(fdptr->fd, cmd, dmx);
01108     pthread_mutex_unlock(&dss->lock);
01109     *result = CMD_STOPALL;
01110     dprintf0("Set demux ioctl on pid %d\n", pkt->hdr.scid);
01111   }
01112 }
01113 
01114 static void dvr_open(struct parser_cmds *pc, struct poll_ll *fdptr,
01115                      cmdret_t *result, int *ret,
01116                      unsigned long int cmd, unsigned char *data)
01117 {
01118   struct dss *dss= find_dss_from_pc(pc);
01119   dss->buf_used = 0;
01120   dss->unused_len = 0;
01121 }
01122 static void dvr_preread(struct parser_cmds *pc, struct poll_ll *fdptr,
01123                      cmdret_t *result, int *ret,
01124                      unsigned long int cmd, unsigned char *data)
01125 {
01126   struct dss *dss= find_dss_from_pc(pc);
01127   struct dvblb_custommsg *ci = (struct dvblb_custommsg *)data;
01128   static int fd = -1;
01129   int bytes;
01130 
01131   if(! dss->is_dss)
01132     return;
01133   if(fd == -1) {
01134     fd = open(opt_file, O_RDONLY);
01135   }
01136   bytes = read(fd, pc->mmap, ci->u.count);
01137   if(bytes == 0)
01138     lseek(fd, 0, SEEK_SET);
01139   ci->u.count = bytes;
01140   *ret = bytes;
01141   *result = CMD_SKIPCALL;
01142 }
01143 //NOTE: This is very broken.  We don't return the number of bytes requested ever
01144 static void dvr_read(struct parser_cmds *pc, struct poll_ll *fdptr,
01145                      cmdret_t *result, int *ret,
01146                      unsigned long int cmd, unsigned char *data)
01147 {
01148   struct dvblb_custommsg *ci = (struct dvblb_custommsg *)data;
01149   struct dss *dss= find_dss_from_pc(pc);
01150   if(! dss->is_dss)
01151     return;
01152   if(dss->buf_len < ci->u.count + dss->buf_used) {
01153     dprintf2("Reallocating %d < %d\n", dss->buf_len + dss->buf_used, ci->u.count);
01154     dss->buf = (uint8_t *)realloc(dss->buf, dss->buf_used + ci->u.count);
01155     dss->buf_len = ci->u.count;
01156   }
01157   if(*ret > 0) {
01158     dprintf3("Reading %d bytes(%08x): %02x %02x %02x %02x ...\n", *ret, pc->mmap, pc->mmap[0], pc->mmap[1], pc->mmap[2], pc->mmap[3]);
01159     parse_dss(dss, pc->mmap, *ret);
01160     if(dss->buf_used) {
01161       int max = ((int)dss->buf_used < *ret) ? dss->buf_used : *ret;
01162       memcpy(pc->mmap, dss->buf, max);
01163       *ret = max;
01164       memmove(dss->buf, dss->buf + max, dss->buf_used - max);
01165       dss->buf_used -= max;
01166     } else {
01167       write_dummy_ts(pc->mmap);
01168       if(*ret < TS_SIZE) {
01169         memcpy(dss->buf, pc->mmap + *ret, TS_SIZE - *ret);
01170         dss->buf_used = TS_SIZE - *ret;
01171       } else {
01172         *ret = TS_SIZE;
01173       }
01174     }
01175     dprintf3("Writing %d bytes(%08x): %02x %02x %02x %02x ...\n", *ret, pc->mmap, pc->mmap[0], pc->mmap[1], pc->mmap[2], pc->mmap[3]);
01176   }
01177 }
01178 
01179 static void connect_dss(struct parser_adpt *pc_all)
01180 {
01181   struct cmd_list *fe_preioctl = register_cmd(fe_tune);
01182   struct cmd_list *demux_preioctl =  register_cmd(set_demux);
01183   struct cmd_list *demux_postclose = register_cmd(close_demux);
01184   struct cmd_list *fe_postclose = register_cmd(fe_close);
01185   struct cmd_list *dvr_postread = register_cmd(dvr_read);
01186   struct cmd_list *dvr_preread1 = register_cmd(dvr_preread);
01187   struct cmd_list *dvr_postopen = register_cmd(dvr_open);
01188   struct dss *dss;
01189 
01190   if(! opt_enable)
01191     return;
01192   dprintf0("Enabling DSS for adapter %d\n", pc_all->frontend->common->virt_adapt);
01193   dss = (struct dss *)malloc(sizeof(struct dss));
01194   bzero(dss, sizeof(struct dss));
01195   INIT_LIST_HEAD(&dss->pkt_ll);
01196   dss->buf = (uint8_t *)malloc(2000000);
01197   dss->buf_len = 2000000;
01198   dss->adapt = pc_all->frontend->common->virt_adapt;
01199   pthread_mutex_init(&dss->lock, NULL);
01200   list_add(&fe_preioctl->list, &pc_all->frontend->pre_ioctl);
01201   list_add(&fe_postclose->list, &pc_all->frontend->post_close);
01202   list_add(&demux_preioctl->list, &pc_all->demux->pre_ioctl);
01203   list_add(&demux_postclose->list, &pc_all->demux->post_close);
01204   list_add(&dvr_postread->list, &pc_all->dvr->post_read);
01205   list_add(&dvr_postopen->list, &pc_all->dvr->post_open);
01206   if(opt_file != NULL)
01207     list_add(&dvr_preread1->list, &pc_all->dvr->pre_read);
01208   list_add_tail(&dss->list, &dsslist);
01209 }
01210 
01211 static struct option *parseopt_dss(arg_enum_t cmd)
01212 {
01213   if(cmd == ARG_INIT) {
01214     return dss_Opts;
01215   } 
01216   if(cmd == ARG_HELP) {
01217     printf("   --dss-file <file> : Read DSS stream from <file> instead of adapter\n");
01218     printf("   --dss-enable      : Enable DSS to DVB mapping\n");
01219   } 
01220   if(! dss_opt)
01221     return NULL;
01222 
01223   switch(dss_opt) {
01224     case 'e':
01225       opt_enable = 1;
01226       break;
01227     case 'f':
01228       opt_file = optarg;
01229       break;
01230   }
01231   dss_opt = 0;
01232   return NULL;
01233 }
01234 
01235 //list, plugin_id, name, parse_args, connect, launch, message, send_msg
01236 static struct plugin_cmd plugin_cmds = {{NULL, NULL}, PLUGIN_ID, "dss",
01237                 parseopt_dss, connect_dss, NULL, NULL, NULL, NULL, NULL};
01238 int __attribute__((constructor)) __dss_init(void)
01239 {
01240   list_add(&plugin_cmds.list, &plugin_cmdlist);
01241   return 0;
01242 }
01243 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines