]> www.vanbest.org Git - sasc-ng.git/commitdiff
handle channels with split ECM (see README addition!)
authorleslie <unknown>
Tue, 25 Aug 2009 22:03:49 +0000 (06:03 +0800)
committerleslie <unknown>
Tue, 25 Aug 2009 22:03:49 +0000 (06:03 +0800)
README
cam.c
cam.h
data.c
data.h
patches/vdr-1.6.0-2-streamca.diff [new file with mode: 0644]
systems/cardclient/cccam2.c
version.h

diff --git a/README b/README
index 111fd7ee48a0af0b7bc78fcb5ec37bc0d7f2792b..d7e4a4f12ea6c83adc8999762082021e5ac3ce09 100644 (file)
--- a/README
+++ b/README
@@ -55,8 +55,17 @@ only recent versions support concurrent recording! Recompile the driver, unload
 the modules, install the new ones and reload the DVB driver. If you suffer from
 ARM crashes, add "hw_sections=0" while loading the dvb-ttpci module.
 
-Contrary to older plugin versions (before 0.7.0) you MUST NOT apply any patches
-to the VDR core (neither vdr-sc nor ffdecsa/softcsa).
+Contrary to older plugin versions (before 0.7.0) you MUST NOT apply patches to
+the VDR core (neither vdr-sc nor ffdecsa/softcsa) except if:
+- you are using VDR 1.4.x (see section below)
+- you are using VDR 1.7.8 or lower and want to view channels with split ECM
+
+To correctly decode channels with split ECM (i.e. audio and video encrypted
+with different CW) you need to apply a patch to the VDR core if you are using
+a VDR version before 1.7.9. You can find the "vdr-1.6.0-2-streamca.diff" file
+in the patches subdirectory. It has been tested with VDR 1.6.0-2 only, but
+probably will apply to other VDR versions as well. This feature is explicitely
+not supported for VDR 1.4.x.
 
 You must have installed the openssl development files. For most distributions
 this means to install openssl-devel package. You should use a openssl package
diff --git a/cam.c b/cam.c
index 165771eadca9b8d410ec2ab3ca7b42c0f96f8f3d..e71de662bf764e399c1cefbe2cf3d00fe4f5d158 100644 (file)
--- a/cam.c
+++ b/cam.c
@@ -600,11 +600,12 @@ bool cEcmData::Parse(const char *buf)
   int nu=0, num, vers=0;
   Name[0]=0;
   if(sscanf(buf,"V%d:%d:%x:%x:%63[^:]:%x/%x:%x:%x/%x:%d:%d/%d%n",
-             &vers,&prgId,&source,&transponder,Name,&caId,&emmCaId,&provId,
+             &vers,&grPrgId,&source,&transponder,Name,&caId,&emmCaId,&provId,
              &ecm_pid,&ecm_table,&rewriterId,&nu,&dataIdx,&num)>=13
      && vers==CACHE_VERS) {
     SetName(Name);
     SetRewriter();
+    prgId=grPrgId%SIDGRP_SHIFT;
     const char *line=buf+num;
     if(nu>0 && *line++==':') {
       unsigned char *dat=AUTOMEM(nu);
@@ -629,7 +630,7 @@ cString cEcmData::ToString(bool hide)
     sprintf(str,"0/%d:",dataIdx);
     }
   return cString::sprintf("V%d:%d:%x:%x:%s:%x/%x:%x:%x/%x:%d:%s",
-                            CACHE_VERS,prgId,source,transponder,name,
+                            CACHE_VERS,grPrgId,source,transponder,name,
                             caId,emmCaId,provId,ecm_pid,ecm_table,rewriterId,
                             str);
 }
@@ -651,7 +652,7 @@ void cEcmCache::New(cEcmInfo *e)
     dat=new cEcmData(e);
     Add(dat);
     Modified();
-    PRINTF(L_CORE_ECM,"cache add prgId=%d source=%x transponder=%x ecm=%x/%x",e->prgId,e->source,e->transponder,e->ecm_pid,e->ecm_table);
+    PRINTF(L_CORE_ECM,"cache add prgId=%d source=%x transponder=%x ecm=%x/%x",e->grPrgId,e->source,e->transponder,e->ecm_pid,e->ecm_table);
     }
   else {
     if(strcasecmp(e->name,dat->name)) {
@@ -680,7 +681,7 @@ int cEcmCache::GetCached(cSimpleList<cEcmInfo> *list, int sid, int Source, int T
   if(ScSetup.EcmCache>1) return 0;
   ListLock(false);
   for(cEcmData *dat=First(); dat; dat=Next(dat)) {
-    if(dat->prgId==sid && dat->source==Source && dat->transponder==Transponder) {
+    if(dat->grPrgId==sid && dat->source==Source && dat->transponder==Transponder) {
       cEcmInfo *e=new cEcmInfo(dat);
       if(e) {
         PRINTF(L_CORE_ECM,"from cache: system %s (%04x) id %04x with ecm %x/%x",e->name,e->caId,e->provId,e->ecm_pid,e->ecm_table);
@@ -702,7 +703,7 @@ void cEcmCache::Delete(cEcmInfo *e)
   ListUnlock();
   if(dat) {
     DelItem(dat);
-    PRINTF(L_CORE_ECM,"invalidated cached prgId=%d source=%x transponder=%x ecm=%x/%x",dat->prgId,dat->source,dat->transponder,dat->ecm_pid,dat->ecm_table);
+    PRINTF(L_CORE_ECM,"invalidated cached prgId=%d source=%x transponder=%x ecm=%x/%x",dat->grPrgId,dat->source,dat->transponder,dat->ecm_pid,dat->ecm_table);
     }
 }
 
@@ -1474,6 +1475,7 @@ cCam::cCam(cScDvbDevice *dev, int CardNum)
   source=transponder=-1; liveVpid=liveApid=0; logger=0; hookman=0;
   memset(lastCW,0,sizeof(lastCW));
   memset(indexMap,0,sizeof(indexMap));
+  memset(splitSid,0,sizeof(splitSid));
 }
 
 cCam::~cCam()
@@ -1526,6 +1528,7 @@ void cCam::Stop(void)
     handler->Stop();
   if(logger) logger->Down();
   if(hookman) hookman->Down();
+  memset(splitSid,0,sizeof(splitSid));
 }
 
 void cCam::AddPrg(cPrg *prg)
@@ -1547,20 +1550,113 @@ void cCam::AddPrg(cPrg *prg)
       LBPUT(" %s=%04x",TYPENAME(pid->type),pid->pid);
     LBEND();
     }
-  if(prg->pids.Count()>0 && prg->SimplifyCaDescr()) {
-    PRINTF(L_GEN_WARN,"Stream specific caDescr (aka split-ecm) cannot be handled yet (SID %d)",prg->sid);
-    // take first caDescr and ignore the rest....
-    cPrgPid *pid=prg->pids.First();
-    prg->caDescr.Set(&pid->caDescr);
-    for(; pid; pid=prg->pids.Next(pid)) pid->caDescr.Clear();
-    prg->SetPidCaDescr(false);
-    }
-  cEcmHandler *handler=GetHandler(prg->sid,needZero,noshift);
-  if(handler) {
-    PRINTF(L_CORE_PIDS,"%d: found handler for SID %d (%s idle=%d idx=%d)",cardNum,prg->sid,handler->Id(),handler->IsIdle(),handler->CwIndex());
-    prg->source=source;
-    prg->transponder=transponder;
-    handler->SetPrg(prg);
+  bool isSplit=false;
+  if(prg->pids.Count()>0 && prg->SimplifyCaDescr()) isSplit=true;
+  else {
+    for(int i=0; splitSid[i]; i++)
+      if(splitSid[i]==prg->sid) { isSplit=true; break; }
+    }
+  if(!isSplit) {
+    cEcmHandler *handler=GetHandler(prg->sid,needZero,noshift);
+    if(handler) {
+      PRINTF(L_CORE_PIDS,"%d: found handler for SID %d (%s idle=%d idx=%d)",cardNum,prg->sid,handler->Id(),handler->IsIdle(),handler->CwIndex());
+      prg->source=source;
+      prg->transponder=transponder;
+      handler->SetPrg(prg);
+      }
+    }
+  else {
+    PRINTF(L_CORE_PIDS,"%d: SID %d is handled as splitted",cardNum,prg->sid);
+    // first update the splitSid list
+    if(prg->pids.Count()==0) { // delete
+      for(int i=0; splitSid[i]; i++)
+        if(splitSid[i]==prg->sid) {
+          memmove(&splitSid[i],&splitSid[i+1],sizeof(splitSid[0])*(MAX_SPLIT_SID-i));
+          break;
+          }
+      PRINTF(L_CORE_PIDS,"%d: deleted from list",cardNum);
+      }
+    else { // add
+      bool has=false;
+      int i;
+      for(i=0; splitSid[i]; i++) if(splitSid[i]==prg->sid) has=true;
+      if(!has) {
+        if(i<MAX_SPLIT_SID) {
+          splitSid[i]=prg->sid;
+          splitSid[i+1]=0;
+          PRINTF(L_CORE_PIDS,"%d: added to list",cardNum);
+          }
+        else PRINTF(L_CORE_PIDS,"%d: split SID list overflow",cardNum);
+        }
+      }
+    LBSTART(L_CORE_PIDS);
+    LBPUT("%d: split SID list now:",cardNum);
+    for(int i=0; i<=MAX_SPLIT_SID; i++) LBPUT(" %d",splitSid[i]);
+    LBEND();
+    // prepare an empty prg head
+    cPrg work;
+    work.source=source;
+    work.transponder=transponder;
+    // loop through pids
+    int group=1;
+    cPrgPid *first;
+    while((first=prg->pids.First())) {
+      LBSTARTF(L_CORE_PIDS);
+      LBPUT("%d: group %d pids",cardNum,group);
+      prg->pids.Del(first,false);
+      work.caDescr.Set(&first->caDescr);
+      first->caDescr.Clear();
+      work.pids.Add(first);
+      LBPUT(" %04x",first->pid);
+      for(cPrgPid *pid=prg->pids.First(); pid;) {
+        cPrgPid *next=prg->pids.Next(pid);
+        if(work.caDescr==pid->caDescr) { // same group
+          prg->pids.Del(pid,false);
+          pid->caDescr.Clear();
+          work.pids.Add(pid);
+          LBPUT(" %04x",pid->pid);
+          }
+        pid=next;
+        }
+      LBEND();
+      // get a handler for the group
+      int grsid=group*SIDGRP_SHIFT+prg->sid;
+      cEcmHandler *handler=0;
+      if(group==1) {
+        // in the first group check if we have a non-split handler
+        // for the sid
+        for(handler=handlerList.First(); handler; handler=handlerList.Next(handler))
+          if(handler->Sid()==prg->sid) {
+            // let GetHandler() take care of needZero/noshift stuff
+            handler=GetHandler(prg->sid,needZero,noshift);
+            break;
+            }
+        }
+      // otherwise get the group-sid handler
+      if(!handler) handler=GetHandler(grsid,needZero,noshift);
+      if(handler) {
+        PRINTF(L_CORE_PIDS,"%d: found handler for group-SID %d (%s idle=%d idx=%d)",cardNum,grsid,handler->Id(),handler->IsIdle(),handler->CwIndex());
+        work.sid=grsid;
+        handler->SetPrg(&work);
+        }
+      // prepare for next group
+      work.pids.Clear();
+      needZero=false; // only one group can have this
+      group++;
+      }
+    // now we scan the handler list for leftover group handlers
+    for(cEcmHandler *handler=handlerList.First(); handler; handler=handlerList.Next(handler)) {
+      int sid=handler->Sid();
+      if(!handler->IsIdle() && sid>SIDGRP_SHIFT) {
+        int gr=sid/SIDGRP_SHIFT;
+        sid%=SIDGRP_SHIFT;
+        if(sid==prg->sid && gr>=group) {
+          PRINTF(L_CORE_PIDS,"%d: idle group handler %s idx=%d",cardNum,handler->Id(),handler->CwIndex());
+          work.sid=handler->Sid();
+          handler->SetPrg(&work);
+          }
+        }
+      }
     }
 }
 
diff --git a/cam.h b/cam.h
index 56b81ff06c169ee158d0c9c647a38c810bb0b64c..15863321f58f8f45def534e648169685f28f6eba 100644 (file)
--- a/cam.h
+++ b/cam.h
@@ -125,6 +125,7 @@ typedef unsigned short caid_t;
 #else
 #define MAX_CI_SLOT_CAIDS 16
 #endif
+#define MAX_SPLIT_SID     16
 
 class cCam : private cMutex {
 private:
@@ -134,6 +135,7 @@ private:
   cLogger *logger;
   cHookManager *hookman;
   int source, transponder, liveVpid, liveApid;
+  int splitSid[MAX_SPLIT_SID+1];
   unsigned char indexMap[MAX_CW_IDX], lastCW[MAX_CW_IDX][2*8];
   //
   cEcmHandler *GetHandler(int sid, bool needZero, bool noshift);
diff --git a/data.c b/data.c
index 0027aaaccc60d7788dee1c8b4a18edef1617e75a..a24d86b9c5880d4ac7d9089dc130948886efd3dc 100644 (file)
--- a/data.c
+++ b/data.c
@@ -587,7 +587,7 @@ cEcmInfo::cEcmInfo(const cEcmInfo *e)
   provId=e->provId;
   AddCaDescr(e);
   dataIdx=e->dataIdx;
-  prgId=e->prgId;
+  grPrgId=e->grPrgId; prgId=grPrgId%SIDGRP_SHIFT;
   source=e->source;
   transponder=e->transponder;
   rewriterId=e->rewriterId;
@@ -613,20 +613,20 @@ void cEcmInfo::Setup(void)
 {
   cached=failed=false;
   name=0; caDescr=0; caDescrLen=0; dataIdx=-1;
-  prgId=source=transponder=-1;
+  prgId=grPrgId=source=transponder=-1;
   ecm_table=0x80; emmCaId=0;
   rewriter=0; rewriterId=0;
 }
 
 bool cEcmInfo::Compare(const cEcmInfo *e)
 {
-  return prgId==e->prgId && source==e->source && transponder==e->transponder &&
+  return grPrgId==e->grPrgId && source==e->source && transponder==e->transponder &&
          caId==e->caId && ecm_pid==e->ecm_pid && provId==e->provId;
 }
 
-void cEcmInfo::SetSource(int PrgId, int Source, int Transponder)
+void cEcmInfo::SetSource(int GrPrgId, int Source, int Transponder)
 {
-  prgId=PrgId;
+  grPrgId=GrPrgId; prgId=grPrgId%SIDGRP_SHIFT;
   source=Source;
   transponder=Transponder;
 }
diff --git a/data.h b/data.h
index 0c719bb4cff278c4150fe2947c1b7ce4b58923be..e11b83010fc795795a853fcc451310da1298fa76 100644 (file)
--- a/data.h
+++ b/data.h
@@ -217,6 +217,8 @@ public:
 
 // ----------------------------------------------------------------
 
+#define SIDGRP_SHIFT 100000 // for group in split ECM handling
+
 class cEcmInfo : public cStructItem {
 private:
   bool cached, failed;
@@ -231,7 +233,7 @@ public:
   char *name;
   int ecm_pid, ecm_table;
   int caId, provId, emmCaId;
-  int prgId, source, transponder;
+  int prgId, grPrgId, source, transponder;
   cRewriter *rewriter;
   int rewriterId;
   //
@@ -241,7 +243,7 @@ public:
   ~cEcmInfo();
   virtual cString ToString(bool hide=false) { return ""; }
   bool Compare(const cEcmInfo *e);
-  void SetSource(int PrgId, int Source, int Transponder);
+  void SetSource(int GrPrgId, int Source, int Transponder);
   void SetName(const char *Name);
   void SetDataIdx(int idx);
   const unsigned char *Data(void) const;
diff --git a/patches/vdr-1.6.0-2-streamca.diff b/patches/vdr-1.6.0-2-streamca.diff
new file mode 100644 (file)
index 0000000..2079843
--- /dev/null
@@ -0,0 +1,315 @@
+diff -u vdr-1.6.0-2-orig/ci.c vdr/ci.c
+--- vdr-1.6.0-2-orig/ci.c      2009-01-15 16:21:16.000000000 -0500
++++ vdr/ci.c   2009-08-17 05:56:38.000000000 -0400
+@@ -551,6 +551,8 @@
+ // --- cCiCaPmt --------------------------------------------------------------
++#define MAXCASYSTEMIDS 64
++
+ // Ca Pmt List Management:
+ #define CPLM_MORE    0x00
+@@ -574,9 +576,10 @@
+   int length;
+   int esInfoLengthPos;
+   uint8_t capmt[2048]; ///< XXX is there a specified maximum?
+-  int caDescriptorsLength;
+-  uint8_t caDescriptors[2048];
+-  bool streamFlag;
++  int source;
++  int transponder;
++  int programNumber;
++  int caSystemIds[MAXCASYSTEMIDS + 1]; // list is zero terminated!
+   void AddCaDescriptors(int Length, const uint8_t *Data);
+ public:
+   cCiCaPmt(uint8_t CmdId, int Source, int Transponder, int ProgramNumber, const int *CaSystemIds);
+@@ -589,7 +592,17 @@
+ cCiCaPmt::cCiCaPmt(uint8_t CmdId, int Source, int Transponder, int ProgramNumber, const int *CaSystemIds)
+ {
+   cmdId = CmdId;
+-  caDescriptorsLength = GetCaDescriptors(Source, Transponder, ProgramNumber, CaSystemIds, sizeof(caDescriptors), caDescriptors, streamFlag);
++  source = Source;
++  transponder = Transponder;
++  programNumber = ProgramNumber;
++  int i = 0;
++  if (CaSystemIds) {
++     for (; CaSystemIds[i]; i++)
++         caSystemIds[i] = CaSystemIds[i];
++     }
++  caSystemIds[i] = 0;
++  uint8_t caDescriptors[512];
++  int caDescriptorsLength = GetCaDescriptors(source, transponder, programNumber, caSystemIds, sizeof(caDescriptors), caDescriptors, 0);
+   length = 0;
+   capmt[length++] = CPLM_ONLY;
+   capmt[length++] = (ProgramNumber >> 8) & 0xFF;
+@@ -597,8 +610,9 @@
+   capmt[length++] = 0x01; // version_number, current_next_indicator - apparently vn doesn't matter, but cni must be 1
+   esInfoLengthPos = length;
+   capmt[length++] = 0x00; // program_info_length H (at program level)
+-  capmt[length++] = 0x00; // program_info_length L
+-  if (!streamFlag)
++  capmt[length++] = 0x01; // program_info_length L
++  capmt[length++] = cmdId;
++  if (caDescriptorsLength>0)
+      AddCaDescriptors(caDescriptorsLength, caDescriptors);
+ }
+@@ -610,14 +624,17 @@
+ void cCiCaPmt::AddPid(int Pid, uint8_t StreamType)
+ {
+   if (Pid) {
++     uint8_t caDescriptors[512];
++     int caDescriptorsLength = GetCaDescriptors(source, transponder, programNumber, caSystemIds, sizeof(caDescriptors), caDescriptors, Pid);
+      //XXX buffer overflow check???
+      capmt[length++] = StreamType;
+      capmt[length++] = (Pid >> 8) & 0xFF;
+      capmt[length++] =  Pid       & 0xFF;
+      esInfoLengthPos = length;
+      capmt[length++] = 0x00; // ES_info_length H (at ES level)
+-     capmt[length++] = 0x00; // ES_info_length L
+-     if (streamFlag)
++     capmt[length++] = 0x01; // ES_info_length L
++     capmt[length++] = cmdId;
++     if (caDescriptorsLength>0)
+         AddCaDescriptors(caDescriptorsLength, caDescriptors);
+      }
+ }
+@@ -625,8 +642,7 @@
+ void cCiCaPmt::AddCaDescriptors(int Length, const uint8_t *Data)
+ {
+   if (esInfoLengthPos) {
+-     if (length + Length < int(sizeof(capmt))) {
+-        capmt[length++] = cmdId;
++     if (length + Length <= int(sizeof(capmt))) {
+         memcpy(capmt + length, Data, Length);
+         length += Length;
+         int l = length - esInfoLengthPos - 2;
+@@ -643,8 +659,6 @@
+ // --- cCiConditionalAccessSupport -------------------------------------------
+-#define MAXCASYSTEMIDS 64
+-
+ // CA Enable Ids:
+ #define CAEI_POSSIBLE                  0x01
+diff -u vdr-1.6.0-2-orig/pat.c vdr/pat.c
+--- vdr-1.6.0-2-orig/pat.c     2008-02-08 08:48:30.000000000 -0500
++++ vdr/pat.c  2009-08-17 05:58:14.000000000 -0400
+@@ -21,23 +21,23 @@
+ class cCaDescriptor : public cListObject {
+ private:
+   int caSystem;
+-  bool stream;
++  int esPid;
+   int length;
+   uchar *data;
+ public:
+-  cCaDescriptor(int CaSystem, int CaPid, bool Stream, int Length, const uchar *Data);
++  cCaDescriptor(int CaSystem, int CaPid, int EsPid, int Length, const uchar *Data);
+   virtual ~cCaDescriptor();
+   bool operator== (const cCaDescriptor &arg) const;
+   int CaSystem(void) { return caSystem; }
+-  int Stream(void) { return stream; }
++  int EsPid(void) { return esPid; }
+   int Length(void) const { return length; }
+   const uchar *Data(void) const { return data; }
+   };
+-cCaDescriptor::cCaDescriptor(int CaSystem, int CaPid, bool Stream, int Length, const uchar *Data)
++cCaDescriptor::cCaDescriptor(int CaSystem, int CaPid, int EsPid, int Length, const uchar *Data)
+ {
+   caSystem = CaSystem;
+-  stream = Stream;
++  esPid = EsPid;
+   length = Length + 6;
+   data = MALLOC(uchar, length);
+   data[0] = SI::CaDescriptorTag;
+@@ -57,7 +57,7 @@
+ bool cCaDescriptor::operator== (const cCaDescriptor &arg) const
+ {
+-  return length == arg.length && memcmp(data, arg.data, length) == 0;
++  return esPid == arg.esPid && length == arg.length && memcmp(data, arg.data, length) == 0;
+ }
+ // --- cCaDescriptors --------------------------------------------------------
+@@ -77,8 +77,8 @@
+   bool Is(int Source, int Transponder, int ServiceId);
+   bool Is(cCaDescriptors * CaDescriptors);
+   bool Empty(void) { return caDescriptors.Count() == 0; }
+-  void AddCaDescriptor(SI::CaDescriptor *d, bool Stream);
+-  int GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag);
++  void AddCaDescriptor(SI::CaDescriptor *d, int EsPid);
++  int GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar *Data, int EsPid);
+   const int *CaIds(void) { return caIds; }
+   };
+@@ -126,9 +126,9 @@
+      }
+ }
+-void cCaDescriptors::AddCaDescriptor(SI::CaDescriptor *d, bool Stream)
++void cCaDescriptors::AddCaDescriptor(SI::CaDescriptor *d, int EsPid)
+ {
+-  cCaDescriptor *nca = new cCaDescriptor(d->getCaType(), d->getCaPid(), Stream, d->privateData.getLength(), d->privateData.getData());
++  cCaDescriptor *nca = new cCaDescriptor(d->getCaType(), d->getCaPid(), EsPid, d->privateData.getLength(), d->privateData.getData());
+   for (cCaDescriptor *ca = caDescriptors.First(); ca; ca = caDescriptors.Next(ca)) {
+       if (*ca == *nca) {
+          delete nca;
+@@ -141,28 +141,30 @@
+ #ifdef DEBUG_CA_DESCRIPTORS
+   char buffer[1024];
+   char *q = buffer;
+-  q += sprintf(q, "CAM: %04X %5d %5d %04X %d -", source, transponder, serviceId, d->getCaType(), Stream);
++  q += sprintf(q, "CAM: %04X %5d %5d %04X %04X -", source, transponder, serviceId, d->getCaType(), EsPid);
+   for (int i = 0; i < nca->Length(); i++)
+       q += sprintf(q, " %02X", nca->Data()[i]);
+   dsyslog(buffer);
+ #endif
+ }
+-int cCaDescriptors::GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag)
++// EsPid is to select the "type" of CaDescriptor to be returned
++// >0 - CaDescriptor for the particular esPid
++// =0 - common CaDescriptor
++// <0 - all CaDescriptors regardless of type (old default)
++
++int cCaDescriptors::GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar *Data, int EsPid)
+ {
+   if (!CaSystemIds || !*CaSystemIds)
+      return 0;
+   if (BufSize > 0 && Data) {
+      int length = 0;
+-     int IsStream = -1;
+      for (cCaDescriptor *d = caDescriptors.First(); d; d = caDescriptors.Next(d)) {
++       if(EsPid<0 || d->EsPid()==EsPid) {
+          const int *caids = CaSystemIds;
+          do {
+             if (d->CaSystem() == *caids) {
+                if (length + d->Length() <= BufSize) {
+-                  if (IsStream >= 0 && IsStream != d->Stream())
+-                     dsyslog("CAM: different stream flag in CA descriptors");
+-                  IsStream = d->Stream();
+                   memcpy(Data + length, d->Data(), d->Length());
+                   length += d->Length();
+                   }
+@@ -171,7 +173,7 @@
+                }
+             } while (*++caids);
+          }
+-     StreamFlag = IsStream == 1;
++       }
+      return length;
+      }
+   return -1;
+@@ -187,7 +189,7 @@
+       // Returns 0 if this is an already known descriptor,
+       // 1 if it is an all new descriptor with actual contents,
+       // and 2 if an existing descriptor was changed.
+-  int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag);
++  int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid);
+   };
+ int cCaDescriptorHandler::AddCaDescriptors(cCaDescriptors *CaDescriptors)
+@@ -208,22 +210,21 @@
+   return CaDescriptors->Empty() ? 0 : 1;
+ }
+-int cCaDescriptorHandler::GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag)
++int cCaDescriptorHandler::GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid)
+ {
+   cMutexLock MutexLock(&mutex);
+-  StreamFlag = false;
+   for (cCaDescriptors *ca = First(); ca; ca = Next(ca)) {
+       if (ca->Is(Source, Transponder, ServiceId))
+-         return ca->GetCaDescriptors(CaSystemIds, BufSize, Data, StreamFlag);
++         return ca->GetCaDescriptors(CaSystemIds, BufSize, Data, EsPid);
+       }
+   return 0;
+ }
+ cCaDescriptorHandler CaDescriptorHandler;
+-int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag)
++int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid)
+ {
+-  return CaDescriptorHandler.GetCaDescriptors(Source, Transponder, ServiceId, CaSystemIds, BufSize, Data, StreamFlag);
++  return CaDescriptorHandler.GetCaDescriptors(Source, Transponder, ServiceId, CaSystemIds, BufSize, Data, EsPid);
+ }
+ // --- cPatFilter ------------------------------------------------------------
+@@ -322,7 +323,7 @@
+         cCaDescriptors *CaDescriptors = new cCaDescriptors(Channel->Source(), Channel->Transponder(), Channel->Sid());
+         // Scan the common loop:
+         for (SI::Loop::Iterator it; (d = (SI::CaDescriptor*)pmt.commonDescriptors.getNext(it, SI::CaDescriptorTag)); ) {
+-            CaDescriptors->AddCaDescriptor(d, false);
++            CaDescriptors->AddCaDescriptor(d, 0);
+             delete d;
+             }
+         // Scan the stream-specific loop:
+@@ -340,16 +341,17 @@
+         int NumDpids = 0;
+         int NumSpids = 0;
+         for (SI::Loop::Iterator it; pmt.streamLoop.getNext(stream, it); ) {
++            int esPid = stream.getPid();
+             switch (stream.getStreamType()) {
+               case 1: // STREAMTYPE_11172_VIDEO
+               case 2: // STREAMTYPE_13818_VIDEO
+-                      Vpid = stream.getPid();
++                      Vpid = esPid;
+                       break;
+               case 3: // STREAMTYPE_11172_AUDIO
+               case 4: // STREAMTYPE_13818_AUDIO
+                       {
+                       if (NumApids < MAXAPIDS) {
+-                         Apids[NumApids] = stream.getPid();
++                         Apids[NumApids] = esPid;
+                          SI::Descriptor *d;
+                          for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
+                              switch (d->getDescriptorTag()) {
+@@ -388,11 +390,11 @@
+                       for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
+                           switch (d->getDescriptorTag()) {
+                             case SI::AC3DescriptorTag:
+-                                 dpid = stream.getPid();
++                                 dpid = esPid;
+                                  break;
+                             case SI::SubtitlingDescriptorTag:
+                                  if (NumSpids < MAXSPIDS) {
+-                                    Spids[NumSpids] = stream.getPid();
++                                    Spids[NumSpids] = esPid;
+                                     SI::SubtitlingDescriptor *sd = (SI::SubtitlingDescriptor *)d;
+                                     SI::SubtitlingDescriptor::Subtitling sub;
+                                     char *s = SLangs[NumSpids];
+@@ -411,7 +413,7 @@
+                                     }
+                                  break;
+                             case SI::TeletextDescriptorTag:
+-                                 Tpid = stream.getPid();
++                                 Tpid = esPid;
+                                  break;
+                             case SI::ISO639LanguageDescriptorTag: {
+                                  SI::ISO639LanguageDescriptor *ld = (SI::ISO639LanguageDescriptor *)d;
+@@ -434,7 +436,7 @@
+               //default: printf("PID: %5d %5d %2d %3d %3d\n", pmt.getServiceId(), stream.getPid(), stream.getStreamType(), pmt.getVersionNumber(), Channel->Number());//XXX
+               }
+             for (SI::Loop::Iterator it; (d = (SI::CaDescriptor*)stream.streamDescriptors.getNext(it, SI::CaDescriptorTag)); ) {
+-                CaDescriptors->AddCaDescriptor(d, true);
++                CaDescriptors->AddCaDescriptor(d, esPid);
+                 delete d;
+                 }
+             }
+diff -u vdr-1.6.0-2-orig/pat.h vdr/pat.h
+--- vdr-1.6.0-2-orig/pat.h     2007-01-05 05:42:10.000000000 -0500
++++ vdr/pat.h  2009-06-13 20:17:56.000000000 -0400
+@@ -32,7 +32,7 @@
+   void Trigger(void);
+   };
+-int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag);
++int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid);
+          ///< Gets all CA descriptors for a given channel.
+          ///< Copies all available CA descriptors for the given Source, Transponder and ServiceId
+          ///< into the provided buffer at Data (at most BufSize bytes). Only those CA descriptors
index 6589cc41e9104925ac6b8308b6a8c5463f360266..8868babaa8c1c28be4790a668705cd259882f582 100644 (file)
@@ -692,7 +692,7 @@ bool cCardClientCCcam2::ProcessECM(const cEcmInfo *ecm, const unsigned char *dat
   cMutexLock lock(this);
   if(!so.Connected() && !Login()) { Logout(); return false; }
   if(!CanHandle(ecm->caId)) return false;
-  PRINTF(L_CC_CCCAM2,"%d: ECM caid %04x prov %04x sid %04x pid %04x",cardnum,ecm->caId,ecm->provId,ecm->prgId,ecm->ecm_pid);
+  PRINTF(L_CC_CCCAM2,"%d: ECM caid %04x prov %04x sid %d pid %04x",cardnum,ecm->caId,ecm->provId,ecm->prgId,ecm->ecm_pid);
   int sctlen=SCT_LEN(data);
   if(sctlen>=256) {
     PRINTF(L_CC_CCCAM2,"ECM data length >=256 not supported by CCcam");
index 3af783e6bafdcc7f79b376f84a0a1916c98767ad..0afd27b48e7cb8f064e55abc2c1831fc896cc7bc 100644 (file)
--- a/version.h
+++ b/version.h
@@ -25,7 +25,7 @@
 extern const char *ScVersion;
 
 // SC API version number for loading shared libraries
-#define SCAPIVERS 26
+#define SCAPIVERS 27
 #ifndef STATICBUILD
 #define SCAPIVERSTAG() int ScLibApiVersion=SCAPIVERS
 #else