]> www.vanbest.org Git - sasc-ng.git/commitdiff
use CA descriptor out of CAM msg
authorleslie <unknown>
Tue, 21 Jul 2009 03:04:15 +0000 (11:04 +0800)
committerleslie <unknown>
Tue, 21 Jul 2009 03:04:15 +0000 (11:04 +0800)
cam.c
cam.h
data.c
data.h
system.c
systems/cardclient/cccam.c
systems/cardclient/gbox.c

diff --git a/cam.c b/cam.c
index 8b384f2de1d824c3b5b039f89fe2e136469d9b5d..1005452a5d5134212fa1f704fdb49b6bd8ff6364 100644 (file)
--- a/cam.c
+++ b/cam.c
@@ -599,12 +599,13 @@ bool cEcmData::Parse(const char *buf)
   char Name[64];
   int nu=0, num;
   Name[0]=0;
-  if(sscanf(buf,"%d:%x:%x:%63[^:]:%x/%x:%x:%x/%x:%d%n",&prgId,&source,&transponder,Name,&caId,&emmCaId,&provId,&ecm_pid,&ecm_table,&nu,&num)>=9) {
+  if(sscanf(buf,"%d:%x:%x:%63[^:]:%x/%x:%x:%x/%x:%d/%d%n",&prgId,&source,&transponder,Name,&caId,&emmCaId,&provId,&ecm_pid,&ecm_table,&nu,&dataIdx,&num)>=9) {
     SetName(Name);
     const char *line=buf+num;
     if(nu>0 && *line++==':') {
       unsigned char *dat=AUTOMEM(nu);
-      if(GetHex(line,dat,nu,true)==nu) AddData(dat,nu);
+      if(GetHex(line,dat,nu,true)==nu && dat[0]==0x09 && dat[1]==nu-2)
+        AddCaDescr(dat,nu);
       }
     return true;
     }
@@ -614,9 +615,9 @@ bool cEcmData::Parse(const char *buf)
 cString cEcmData::ToString(bool hide)
 {
   char *str;
-  if(data) {
-    str=AUTOARRAY(char,dataLen*2+2);
-    sprintf(str,":%d:%s",dataLen,HexStr(str,data,dataLen));
+  if(caDescr) {
+    str=AUTOARRAY(char,caDescrLen*2+16);
+    sprintf(str,":%d/%d:%s",caDescrLen,dataIdx,HexStr(str,caDescr,caDescrLen));
     }
   else {
     str=AUTOARRAY(char,4);
@@ -652,7 +653,7 @@ void cEcmCache::New(cEcmInfo *e)
       dat->SetName(e->name);
       Modified();
       }
-    if(dat->Update(e))
+    if(dat->AddCaDescr(e))
       Modified();
     }
   ListUnlock();
@@ -717,6 +718,153 @@ bool cEcmCache::ParseLinePlain(const char *line)
   return false;
 }
 
+// -- cCaDescr -----------------------------------------------------------------
+
+cCaDescr::cCaDescr(void)
+{
+  descr=0; len=0;
+}
+
+cCaDescr::cCaDescr(const cCaDescr &cd)
+{
+  descr=0; len=0;
+  Set(cd.descr,cd.len);
+}
+
+cCaDescr::~cCaDescr()
+{
+  Clear();
+}
+
+const unsigned char *cCaDescr::Get(int &l) const
+{
+  l=len;
+  return descr;
+}
+
+void cCaDescr::Set(const cCaDescr *d)
+{
+  Set(d->descr,d->len);
+}
+
+void cCaDescr::Set(const unsigned char *de, int l)
+{
+  Clear();
+  if(l) {
+    descr=MALLOC(unsigned char,l);
+    if(descr) {
+      memcpy(descr,de,l);
+      len=l;
+      }
+    }
+}
+
+void cCaDescr::Clear(void)
+{
+  free(descr); descr=0; len=0;
+}
+
+void cCaDescr::Join(const cCaDescr *cd, bool rev)
+{
+  if(cd->descr) {
+    int l=len+cd->len;
+    unsigned char *m=MALLOC(unsigned char,l);
+    if(m) {
+      if(!rev) {
+        if(descr) memcpy(m,descr,len);
+        memcpy(m+len,cd->descr,cd->len);
+        }
+      else {
+        memcpy(m,cd->descr,cd->len);
+        if(descr) memcpy(m+cd->len,descr,len);
+        }
+      Clear();
+      descr=m; len=l;
+      }
+    }
+}
+
+bool cCaDescr::operator== (const cCaDescr &cd) const
+{
+  return len==cd.len && (len==0 || memcmp(descr,cd.descr,len)==0);
+}
+
+// -- cPrg ---------------------------------------------------------------------
+
+cPrg::cPrg(void)
+{
+  Setup();
+}
+
+cPrg::cPrg(int Sid, bool IsUpdate)
+{
+  Setup();
+  sid=Sid; isUpdate=IsUpdate;
+}
+
+void cPrg::Setup(void)
+{
+  sid=-1; source=-1; transponder=-1;
+  isUpdate=pidCaDescr=false;
+}
+
+bool cPrg::SimplifyCaDescr(void)
+{
+//XXX
+{
+PRINTF(L_CORE_PIDS,"SimplyCa entry pidCa=%d",HasPidCaDescr());
+const unsigned char *d;
+int l;
+d=caDescr.Get(l);
+if(d) LDUMP(L_CORE_PIDS,d,l,"prgca:");
+else PRINTF(L_CORE_PIDS,"prgca: <empty>");
+for(cPrgPid *pid=pids.First(); pid; pid=pids.Next(pid)) {
+  d=pid->caDescr.Get(l);
+  if(d) LDUMP(L_CORE_PIDS,d,l,"pidca %04x:",pid->pid);
+  else PRINTF(L_CORE_PIDS,"pidca %04x: <empty>",pid->pid);
+  }
+}
+//XXX
+
+  if(HasPidCaDescr()) {
+    bool equal=true;
+    if(pids.Count()>1) {
+      cPrgPid *pid0=pids.First();
+      for(cPrgPid *pid1=pids.Next(pid0); pid1; pid1=pids.Next(pid1))
+        if(!(pid0->caDescr==pid1->caDescr)) { equal=false; break; }
+      }
+    if(equal) {
+      cPrgPid *pid=pids.First();
+      caDescr.Join(&pid->caDescr);
+      for(; pid; pid=pids.Next(pid)) pid->caDescr.Clear();
+      SetPidCaDescr(false);
+      }
+    }
+  if(HasPidCaDescr()) {
+    for(cPrgPid *pid=pids.First(); pid; pid=pids.Next(pid))
+      pid->caDescr.Join(&caDescr,true);
+    caDescr.Clear();
+    }
+
+//XXX
+{
+PRINTF(L_CORE_PIDS,"SimplyCa exit pidCa=%d",HasPidCaDescr());
+const unsigned char *d;
+int l;
+d=caDescr.Get(l);
+if(d) LDUMP(L_CORE_PIDS,d,l,"prgca:");
+else PRINTF(L_CORE_PIDS,"prgca: <empty>");
+for(cPrgPid *pid=pids.First(); pid; pid=pids.Next(pid)) {
+  d=pid->caDescr.Get(l);
+  if(d) LDUMP(L_CORE_PIDS,d,l,"pidca %04x:",pid->pid);
+  else PRINTF(L_CORE_PIDS,"pidca %04x: <empty>",pid->pid);
+  }
+}
+//XXX
+
+  return HasPidCaDescr();
+}
+
 // -- cEcmSys ------------------------------------------------------------------
 
 class cEcmPri : public cSimpleItem {
@@ -735,12 +883,12 @@ private:
   cTimeMs idleTime;
   //
   cMutex dataMutex;
-  int sid;
-  cSimpleList<cPrgPid> pids;
+  cPrg prg;
   //
   cSystem *sys;
   cPidFilter *filter;
   int filterCwIndex, filterSource, filterTransponder, filterSid;
+  cCaDescr filterCaDescr;
   unsigned char lastCw[16];
   bool sync, noKey, trigger;
   int triggerMode;
@@ -774,12 +922,12 @@ public:
   cEcmHandler(cCam *Cam, int CardNum, int cwindex);
   virtual ~cEcmHandler();
   void Stop(void);
-  void SetPrg(cPrg *prg);
+  void SetPrg(cPrg *Prg);
   void ShiftCwIndex(int cwindex);
   char *CurrentKeyStr(void) const;
   bool IsRemoveable(void);
   bool IsIdle(void);
-  int Sid(void) const { return sid; }
+  int Sid(void) const { return prg.sid; }
   int CwIndex(void) const { return cwIndex; }
   const char *Id(void) const { return id; }
   };
@@ -791,7 +939,7 @@ cEcmHandler::cEcmHandler(cCam *Cam, int CardNum, int cwindex)
   cam=Cam;
   cardNum=CardNum;
   cwIndex=cwindex;
-  sys=0; filter=0; ecm=0; ecmPri=0; mode=-1; sid=-1;
+  sys=0; filter=0; ecm=0; ecmPri=0; mode=-1;
   trigger=false; triggerMode=-1;
   filterSource=filterTransponder=0; filterCwIndex=-1; filterSid=-1;
   id=bprintf("%d.%d",cardNum,cwindex);
@@ -810,7 +958,7 @@ cEcmHandler::~cEcmHandler()
 bool cEcmHandler::IsIdle(void)
 {
   dataMutex.Lock();
-  int n=pids.Count();
+  int n=prg.pids.Count();
   dataMutex.Unlock();
   return n==0;
 }
@@ -823,11 +971,11 @@ bool cEcmHandler::IsRemoveable(void)
 void cEcmHandler::Stop(void)
 {
   dataMutex.Lock();
-  if(!IsIdle() || sid!=-1) {
+  if(!IsIdle() || prg.sid!=-1) {
     PRINTF(L_CORE_ECM,"%s: stop",id);
-    sid=-1;
+    prg.sid=-1;
     idleTime.Set();
-    pids.Clear();
+    prg.pids.Clear();
     trigger=true;
     }
   dataMutex.Unlock();
@@ -843,61 +991,69 @@ void cEcmHandler::ShiftCwIndex(int cwindex)
     dataMutex.Lock();
     trigger=true;
     cwIndex=cwindex;
-    for(cPrgPid *pid=pids.First(); pid; pid=pids.Next(pid))
-      cam->SetCWIndex(pid->Pid(),cwIndex);
+    for(cPrgPid *pid=prg.pids.First(); pid; pid=prg.pids.Next(pid))
+      cam->SetCWIndex(pid->pid,cwIndex);
     dataMutex.Unlock();
     if(filter) filter->Wakeup();
     }
 }
 
-void cEcmHandler::SetPrg(cPrg *prg)
+void cEcmHandler::SetPrg(cPrg *Prg)
 {
   dataMutex.Lock();
   bool wasIdle=IsIdle();
-  if(prg->Prg()!=sid) {
-    PRINTF(L_CORE_ECM,"%s: setting new SID %d",id,prg->Prg());
-    sid=prg->Prg();
+  if(Prg->sid!=prg.sid) {
+    PRINTF(L_CORE_ECM,"%s: setting new SID %d",id,Prg->sid);
+    prg.sid=Prg->sid;
+    prg.source=Prg->source;
+    prg.transponder=Prg->transponder;
     idleTime.Set();
-    pids.Clear();
+    prg.pids.Clear();
+    trigger=true;
+    }
+  if(!(prg.caDescr==Prg->caDescr)) {
+    prg.caDescr.Set(&Prg->caDescr);
     trigger=true;
     }
+  if(Prg->HasPidCaDescr())
+    PRINTF(L_GEN_DEBUG,"internal: pid specific caDescr not supported at this point (sid=%d)",Prg->sid);
   LBSTART(L_CORE_PIDS);
   LBPUT("%s: pids on entry",id);
-  for(cPrgPid *pid=pids.First(); pid; pid=pids.Next(pid))
-    LBPUT(" %s=%04x",TYPENAME(pid->Type()),pid->Pid());
+  for(cPrgPid *pid=prg.pids.First(); pid; pid=prg.pids.Next(pid))
+    LBPUT(" %s=%04x",TYPENAME(pid->type),pid->pid);
   LBEND();
 
-  for(cPrgPid *pid=pids.First(); pid;) {
+  for(cPrgPid *pid=prg.pids.First(); pid;) {
     cPrgPid *npid;
-    for(npid=prg->pids.First(); npid; npid=prg->pids.Next(npid)) {
-      if(pid->Pid()==npid->Pid()) {
+    for(npid=Prg->pids.First(); npid; npid=Prg->pids.Next(npid)) {
+      if(pid->pid==npid->pid) {
         npid->Proc(true);
         break;
         }
       }
     if(!npid) {
-      npid=pids.Next(pid);
-      pids.Del(pid);
+      npid=prg.pids.Next(pid);
+      prg.pids.Del(pid);
       pid=npid;
       }
-    else pid=pids.Next(pid);
+    else pid=prg.pids.Next(pid);
     }
   LBSTART(L_CORE_PIDS);
   LBPUT("%s: pids after delete",id);
-  for(cPrgPid *pid=pids.First(); pid; pid=pids.Next(pid))
-    LBPUT(" %s=%04x",TYPENAME(pid->Type()),pid->Pid());
+  for(cPrgPid *pid=prg.pids.First(); pid; pid=prg.pids.Next(pid))
+    LBPUT(" %s=%04x",TYPENAME(pid->type),pid->pid);
   LBEND();
-  for(cPrgPid *npid=prg->pids.First(); npid; npid=prg->pids.Next(npid)) {
+  for(cPrgPid *npid=Prg->pids.First(); npid; npid=Prg->pids.Next(npid)) {
     if(!npid->Proc()) {
-      cPrgPid *pid=new cPrgPid(npid->Type(),npid->Pid());
-      pids.Add(pid);
-      cam->SetCWIndex(pid->Pid(),cwIndex);
+      cPrgPid *pid=new cPrgPid(npid->type,npid->pid);
+      prg.pids.Add(pid);
+      cam->SetCWIndex(pid->pid,cwIndex);
       }
     }
   LBSTART(L_CORE_PIDS);
   LBPUT("%s: pids after add",id);
-  for(cPrgPid *pid=pids.First(); pid; pid=pids.Next(pid))
-    LBPUT(" %s=%04x",TYPENAME(pid->Type()),pid->Pid());
+  for(cPrgPid *pid=prg.pids.First(); pid; pid=prg.pids.Next(pid))
+    LBPUT(" %s=%04x",TYPENAME(pid->type),pid->pid);
   LBEND();
   if(!IsIdle()) {
     trigger=true;
@@ -922,12 +1078,12 @@ void cEcmHandler::Process(cPidFilter *filter, unsigned char *data, int len)
   dataMutex.Lock();
   if(trigger) {
     PRINTF(L_CORE_ECM,"%s: triggered SID %d/%d idx %d/%d mode %d/%d %s",
-      id,filterSid,sid,filterCwIndex,cwIndex,mode,triggerMode,(mode==3 && sync)?"sync":"-");
+      id,filterSid,prg.sid,filterCwIndex,cwIndex,mode,triggerMode,(mode==3 && sync)?"sync":"-");
     trigger=false;
-    if(filterSid!=sid) {
-      filterSid=sid;
-      filterSource=cam->Source();
-      filterTransponder=cam->Transponder();
+    if(filterSid!=prg.sid) {
+      filterSid=prg.sid;
+      filterSource=prg.source;
+      filterTransponder=prg.transponder;
       filterCwIndex=cwIndex;
       noKey=true; mode=0;
       }
@@ -937,6 +1093,10 @@ void cEcmHandler::Process(cPidFilter *filter, unsigned char *data, int len)
         if(mode==3 && sync)
           cam->WriteCW(filterCwIndex,lastCw,true);
         }
+      if(!(prg.caDescr==filterCaDescr)) {
+        filterCaDescr.Set(&prg.caDescr);
+        //XXX do we need to trigger something here??
+        }
       if(mode<triggerMode) mode=triggerMode;
       }
     triggerMode=-1;
@@ -1239,27 +1399,16 @@ void cEcmHandler::EcmFail(void)
 
 void cEcmHandler::ParseCAInfo(int SysId)
 {
-  unsigned char buff[2048];
-  caid_t casys[MAXCAIDS+1];
-  if(SysId==0xFFFF) {
-    if(!cam->GetPrgCaids(filterSource,filterTransponder,filterSid,casys)) {
-      PRINTF(L_CORE_ECM,"%s: no CAIDs for SID %d",id,sid);
-      return;
-      }
-    }
-  else {
-    casys[0]=SysId;
-    casys[1]=0;
-    }
-  bool streamFlag;
-  int len=GetCaDescriptors(filterSource,filterTransponder,filterSid,casys,sizeof(buff),buff,streamFlag);
-  if(len>0) {
-    if(dolog) PRINTF(L_CORE_ECM,"%s: got CaDescriptors for SID %d (len=%d)",id,sid,len);
+  int len;
+  const unsigned char *buff=filterCaDescr.Get(len);
+  if(buff && len>0) {
+    if(dolog) PRINTF(L_CORE_ECM,"%s: CA descriptors for SID %d (len=%d)",id,filterSid,len);
     HEXDUMP(L_HEX_PMT,buff,len,"PMT");
     for(int index=0; index<len; index+=buff[index+1]+2) {
       if(buff[index]==0x09) {
-        if(dolog) LDUMP(L_CORE_ECM,&buff[index+2],buff[index+1],"%s: descriptor",id);
         int sysId=WORD(buff,index+2,0xFFFF);
+        if(SysId!=0xFFFF && sysId!=SysId) continue;
+        if(dolog) LDUMP(L_CORE_ECM,&buff[index+2],buff[index+1],"%s: descriptor",id);
         int sysPri=0;
         cSystem *sys;
         while((sys=cSystems::FindBySysId(sysId,!cam->IsSoftCSA(filterCwIndex==0),sysPri))) {
@@ -1278,9 +1427,7 @@ void cEcmHandler::ParseCAInfo(int SysId)
               while(e) {
                 if(e->ecm_pid==n->ecm_pid) {
                   if(e->caId==n->caId && e->provId==n->provId) {
-                    if(n->Data()) {
-                      if(e->Update(n) && dolog) LBPUT("(updated) ");
-                      }
+                    if(e->AddCaDescr(n) && dolog) LBPUT("(updated) ");
                     if(dolog) LBPUT("(already present)");
                     delete n; n=0;
                     break;
@@ -1294,7 +1441,8 @@ void cEcmHandler::ParseCAInfo(int SysId)
                 }
               if(n) {
                 if(dolog) LBPUT("(new)");
-                n->SetSource(sid,filterSource,filterTransponder);
+                n->SetSource(filterSid,filterSource,filterTransponder);
+                n->AddCaDescr(&buff[index+2],buff[index+1]);
                 ecmList.Add(n);
                 AddEcmPri(n);
                 }
@@ -1383,23 +1531,33 @@ void cCam::AddPrg(cPrg *prg)
   cMutexLock lock(this);
   bool islive=false;
   for(cPrgPid *pid=prg->pids.First(); pid; pid=prg->pids.Next(pid))
-    if(pid->Pid()==liveVpid || pid->Pid()==liveApid) {
+    if(pid->pid==liveVpid || pid->pid==liveApid) {
       islive=true;
       break;
       }
   bool needZero=!IsSoftCSA(islive) && (islive || !ScSetup.ConcurrentFF);
   bool noshift=IsSoftCSA(true) || (prg->IsUpdate() && prg->pids.Count()==0);
-  PRINTF(L_CORE_PIDS,"%d: %s SID %d (zero=%d noshift=%d)",cardNum,prg->IsUpdate()?"update":"add",prg->Prg(),needZero,noshift);
+  PRINTF(L_CORE_PIDS,"%d: %s SID %d (zero=%d noshift=%d)",cardNum,prg->IsUpdate()?"update":"add",prg->sid,needZero,noshift);
   if(prg->pids.Count()>0) {
     LBSTART(L_CORE_PIDS);
     LBPUT("%d: pids",cardNum);
     for(cPrgPid *pid=prg->pids.First(); pid; pid=prg->pids.Next(pid))
-      LBPUT(" %s=%04x",TYPENAME(pid->Type()),pid->Pid());
+      LBPUT(" %s=%04x",TYPENAME(pid->type),pid->pid);
     LBEND();
     }
-  cEcmHandler *handler=GetHandler(prg->Prg(),needZero,noshift);
+  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->Prg(),handler->Id(),handler->IsIdle(),handler->CwIndex());
+    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);
     }
 }
@@ -1447,11 +1605,6 @@ void cCam::HouseKeeping(void)
     }
 }
 
-bool cCam::GetPrgCaids(int source, int transponder, int prg, caid_t *c)
-{
-  return device->GetPrgCaids(source,transponder,prg,c);
-}
-
 void cCam::LogStartup(void)
 {
   cMutexLock lock(this);
@@ -2015,6 +2168,7 @@ void cScCamSlot::Process(const unsigned char *data, int len)
         LBPUT("/%x",dlen);
         if(ilen>0 && dlen>=ilen) {
           ci_cmd=data[0];
+          prg->caDescr.Set(&data[1],ilen-1);
           LBPUT(" ci_cmd(G)=%02x",ci_cmd);
           }
         data+=ilen; dlen-=ilen;
@@ -2027,6 +2181,8 @@ void cScCamSlot::Process(const unsigned char *data, int len)
           LBPUT("/%x",dlen);
           if(ilen>0 && dlen>=ilen) {
             ci_cmd=data[0];
+            pid->caDescr.Set(&data[1],ilen-1);
+            prg->SetPidCaDescr(true);
             LBPUT(" ci_cmd(S)=%x",ci_cmd);
             }
           data+=ilen; dlen-=ilen;
@@ -2038,20 +2194,20 @@ void cScCamSlot::Process(const unsigned char *data, int len)
           b[3]=0x90;
           b[4]=0x02; b[5]=cid<<8; b[6]=cid&0xff;
           b[7]=0x9f; b[8]=0x80; b[9]=0x33; // AOT_CA_PMT_REPLY
-          b[11]=prg->Prg()<<8;
-          b[12]=prg->Prg()&0xff;
+          b[11]=prg->sid<<8;
+          b[12]=prg->sid&0xff;
           b[13]=0x00;
           b[14]=0x81;  // CA_ENABLE
           b[10]=4; b[1]=4+9; a[0]=4+11; Put(a,4+12);
           PRINTF(L_CORE_CI,"%d.%d answer to query",cardIndex,slot);
           }
-        if(prg->Prg()!=0) {
+        if(prg->sid!=0) {
           if(ci_cmd==0x04) {
             PRINTF(L_CORE_CI,"%d.%d stop decrypt",cardIndex,slot);
             ciadapter->CamStop();
             }
           if(ci_cmd==0x01 || (ci_cmd==-1 && (ca_lm==0x04 || ca_lm==0x05))) {
-            PRINTF(L_CORE_CI,"%d.%d set CAM decrypt (prg %d)",cardIndex,slot,prg->Prg());
+            PRINTF(L_CORE_CI,"%d.%d set CAM decrypt (prg %d)",cardIndex,slot,prg->sid);
             ciadapter->CamAddPrg(prg);
             }
           }
@@ -2575,7 +2731,6 @@ cScDvbDevice::cScDvbDevice(int n, int cafd)
 #if APIVERSNUM >= 10500
   ciadapter=0; hwciadapter=0;
 #endif
-  memset(lrucaid,0,sizeof(lrucaid));
   fd_ca=cafd; fd_ca2=dup(fd_ca); fd_dvr=-1;
   softcsa=(fd_ca<0);
 }
@@ -2758,46 +2913,12 @@ bool cScDvbDevice::SetPid(cPidHandle *Handle, int Type, bool On)
 
 bool cScDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
 {
-  lruMutex.Lock();
-  int i=FindLRUPrg(Channel->Source(),Channel->Transponder(),Channel->Sid());
-  if(i<0) i=MAX_LRU_CAID-1;
-  if(i>0) memmove(&lrucaid[1],&lrucaid[0],sizeof(struct LruCaid)*i);
-#if APIVERSNUM >= 10500
-  const caid_t *c=Channel->Caids();
-  for(i=0; i<MAXCAIDS && *c; i++) lrucaid[0].caids[i]=*c++;
-  lrucaid[0].caids[i]=0;
-#else
-  for(i=0; i<=MAXCAIDS; i++) if((lrucaid[0].caids[i]=Channel->Ca(i))==0) break;
-#endif
-  lrucaid[0].src=Channel->Source();
-  lrucaid[0].tr=Channel->Transponder();
-  lrucaid[0].prg=Channel->Sid();
-  lruMutex.Unlock();
   if(cam) cam->Tune(Channel);
   bool ret=cDvbDevice::SetChannelDevice(Channel,LiveView);
   if(ret && cam) cam->PostTune();
   return ret;
 }
 
-bool cScDvbDevice::GetPrgCaids(int source, int transponder, int prg, caid_t *c)
-{
-  cMutexLock lock(&lruMutex);
-  int i=FindLRUPrg(source,transponder,prg);
-  if(i>=0) {
-    for(int j=0; j<MAXCAIDS && lrucaid[i].caids[j]; j++) *c++=lrucaid[i].caids[j];
-    *c=0;
-    return true;
-    }
-  return false;
-}
-
-int cScDvbDevice::FindLRUPrg(int source, int transponder, int prg)
-{
-  for(int i=0; i<MAX_LRU_CAID; i++)
-    if(lrucaid[i].src==source && lrucaid[i].tr==transponder && lrucaid[i].prg==prg) return i;
-  return -1;
-}
-
 #if APIVERSNUM < 10500
 int cScDvbDevice::ProvidesCa(const cChannel *Channel) const
 {
@@ -3014,11 +3135,6 @@ bool cScDvbDevice::Initialize(void)
   return true;
 }
 
-bool cScDvbDevice::GetPrgCaids(int source, int transponder, int prg, caid_t *c)
-{
-  return false;
-}
-
 bool cScDvbDevice::SoftCSA(bool live)
 {
   return softcsa && !live;
diff --git a/cam.h b/cam.h
index 25c587012bee3c73b595d00089461754dbf374fc..ed828e367e4a6972c84a40eec36b486f2e8b7c12 100644 (file)
--- a/cam.h
+++ b/cam.h
@@ -58,30 +58,54 @@ extern cEcmCache ecmcache;
 
 // ----------------------------------------------------------------
 
+class cCaDescr {
+private:
+  unsigned char *descr;
+  int len;
+public:
+  cCaDescr(void);
+  cCaDescr(const cCaDescr &arg);
+  ~cCaDescr();
+  const unsigned char *Get(int &l) const;
+  void Set(const cCaDescr *d);
+  void Set(const unsigned char *de, int l);
+  void Clear(void);
+  bool operator== (const cCaDescr &arg) const;
+  void Join(const cCaDescr *cd, bool rev=false);
+  };
+
+// ----------------------------------------------------------------
+
 class cPrgPid : public cSimpleItem {
 private:
-  int type, pid;
   bool proc;
 public:
+  int type, pid;
+  cCaDescr caDescr;
+  //
   cPrgPid(int Type, int Pid) { type=Type; pid=Pid; proc=false; }
-  int Pid(void) { return pid; }
-  int Type(void) { return type; }
-  bool Proc(void) { return proc; }
+  bool Proc(void) const { return proc; }
   void Proc(bool is) { proc=is; };
   };
 
 // ----------------------------------------------------------------
 
-class cPrg : public cSimpleItem {
+class cPrg {
 private:
-  int prg;
-  bool isUpdate;
+  bool isUpdate, pidCaDescr;
+  //
+  void Setup(void);
 public:
+  int sid, source, transponder;
   cSimpleList<cPrgPid> pids;
+  cCaDescr caDescr;
   //
-  cPrg(int Prg, bool IsUpdate) { prg=Prg; isUpdate=IsUpdate; }
-  int Prg(void) { return prg; }
-  bool IsUpdate(void) { return isUpdate; }
+  cPrg(void);
+  cPrg(int Sid, bool IsUpdate);
+  bool IsUpdate(void) const { return isUpdate; }
+  bool HasPidCaDescr(void) const { return pidCaDescr; }
+  void SetPidCaDescr(bool val) { pidCaDescr=val; }
+  bool SimplifyCaDescr(void);
   };
 
 // ----------------------------------------------------------------
@@ -122,7 +146,6 @@ public:
   void SetCWIndex(int pid, int index);
   void DumpAV7110(void);
   void LogEcmStatus(const cEcmInfo *ecm, bool on);
-  bool GetPrgCaids(int source, int transponder, int prg, caid_t *c);
   void AddHook(cLogHook *hook);
   bool TriggerHook(int id);
   // Plugin API
@@ -137,16 +160,12 @@ public:
   char *CurrentKeyStr(int num);
   //
   bool IsSoftCSA(bool live);
-  int Source(void) { return source; }
-  int Transponder(void) { return transponder; }
   };
 
 void LogStatsDown(void);
 
 // ----------------------------------------------------------------
 
-#define MAX_LRU_CAID 10
-
 class cScDvbDevice : public cDvbDevice {
 private:
   cDeCSA *decsa;
@@ -161,17 +180,11 @@ private:
   bool softcsa, fullts;
   cMutex cafdMutex;
   cTimeMs lastDump;
-  struct LruCaid {
-    int src, tr, prg;
-    caid_t caids[MAXCAIDS+1];
-    } lrucaid[MAX_LRU_CAID];
-  cMutex lruMutex;
   static int budget;
   //
 #ifndef SASC
   void LateInit(void);
   void EarlyShutdown(void);
-  int FindLRUPrg(int source, int transponder, int prg);
   bool ScActive(void);
 #endif //SASC
 protected:
@@ -210,7 +223,6 @@ public:
   void DumpAV7110(void);
   cCam *Cam(void) { return cam; }
   bool SoftCSA(bool live);
-  virtual bool GetPrgCaids(int source, int transponder, int prg, caid_t *c);
   };
 
 #endif // ___CAM_H
diff --git a/data.c b/data.c
index 4261f0bc0bcbdc3c89499474d76797247a38f275..875c86d3911b2595775cb621d7e237e8d18b1673 100644 (file)
--- a/data.c
+++ b/data.c
@@ -584,7 +584,8 @@ cEcmInfo::cEcmInfo(const cEcmInfo *e)
   caId=e->caId;
   emmCaId=e->emmCaId;
   provId=e->provId;
-  Update(e);
+  AddCaDescr(e);
+  dataIdx=e->dataIdx;
   prgId=e->prgId;
   source=e->source;
   transponder=e->transponder;
@@ -600,14 +601,14 @@ cEcmInfo::cEcmInfo(const char *Name, int Pid, int CaId, int ProvId)
 
 cEcmInfo::~cEcmInfo()
 {
-  ClearData();
+  ClearCaDescr();
   free(name);
 }
 
 void cEcmInfo::Setup(void)
 {
   cached=failed=false;
-  name=0; data=0;
+  name=0; caDescr=0; caDescrLen=0; dataIdx=-1;
   prgId=source=transponder=-1;
   ecm_table=0x80; emmCaId=0;
 }
@@ -618,11 +619,6 @@ bool cEcmInfo::Compare(const cEcmInfo *e)
          caId==e->caId && ecm_pid==e->ecm_pid && provId==e->provId;
 }
 
-bool cEcmInfo::Update(const cEcmInfo *e)
-{
-  return (e->data && (!data || e->dataLen!=dataLen)) ? AddData(e->data,e->dataLen) : false;
-}
-
 void cEcmInfo::SetSource(int PrgId, int Source, int Transponder)
 {
   prgId=PrgId;
@@ -630,21 +626,49 @@ void cEcmInfo::SetSource(int PrgId, int Source, int Transponder)
   transponder=Transponder;
 }
 
-void cEcmInfo::ClearData(void)
+void cEcmInfo::ClearCaDescr(void)
+{
+  free(caDescr); caDescr=0; caDescrLen=0;
+}
+
+bool cEcmInfo::AddCaDescr(const cEcmInfo *e)
 {
-  free(data); data=0;
+  bool res=AddCaDescr(e->caDescr,e->caDescrLen);
+  if(e->dataIdx>=0 && (dataIdx<0 || e->dataIdx!=dataIdx)) res=true;
+  dataIdx=e->dataIdx;
+  return res;
 }
 
-bool cEcmInfo::AddData(const unsigned char *Data, int DataLen)
+bool cEcmInfo::AddCaDescr(const unsigned char *descr, int len)
 {
-  ClearData();
-  data=MALLOC(unsigned char,DataLen);
-  if(data) {
-    memcpy(data,Data,DataLen);
-    dataLen=DataLen;
+  bool res=false;
+  if(descr && (!caDescr || caDescrLen!=len || memcmp(caDescr,descr,len)!=0)) {
+    unsigned char *mem=MALLOC(unsigned char,len);
+    if(mem) {
+      ClearCaDescr();
+      memcpy(mem,descr,len);
+      caDescr=mem; caDescrLen=len;
+      res=true;
+      }
+    else PRINTF(L_GEN_ERROR,"malloc failed in cEcmInfo::AddCaDescr()");
     }
-  else PRINTF(L_GEN_ERROR,"malloc failed in cEcmInfo::AddData()");
-  return (data!=0);
+  return res;
+}
+
+const unsigned char *cEcmInfo::GetCaDescr(int *l) const
+{
+  if(l) *l=caDescrLen;
+  return caDescr;
+}
+
+void cEcmInfo::SetDataIdx(int idx)
+{
+  dataIdx=idx;
+}
+
+const unsigned char *cEcmInfo::Data(void) const
+{
+  return (dataIdx>=0 && caDescr && caDescrLen>dataIdx) ? &caDescr[dataIdx] : 0;
 }
 
 void cEcmInfo::SetName(const char *Name)
diff --git a/data.h b/data.h
index e5f7c5cfd9f41c15df71a1bface9133a3cabd33a..26140ecc403a131750a70ef326f2cae55ef7cf30 100644 (file)
--- a/data.h
+++ b/data.h
@@ -222,10 +222,10 @@ private:
   //
   void Setup(void);
 protected:
-  int dataLen;
-  unsigned char *data;
+  int caDescrLen, dataIdx;
+  unsigned char *caDescr;
   //
-  void ClearData(void);
+  void ClearCaDescr(void);
 public:
   char *name;
   int ecm_pid, ecm_table;
@@ -238,11 +238,13 @@ public:
   ~cEcmInfo();
   virtual cString ToString(bool hide=false) { return ""; }
   bool Compare(const cEcmInfo *e);
-  bool Update(const cEcmInfo *e);
   void SetSource(int PrgId, int Source, int Transponder);
   void SetName(const char *Name);
-  bool AddData(const unsigned char *Data, int DataLen);
-  const unsigned char *Data(void) const { return data; }
+  void SetDataIdx(int idx);
+  const unsigned char *Data(void) const;
+  bool AddCaDescr(const cEcmInfo *e);
+  bool AddCaDescr(const unsigned char *descr, int len);
+  const unsigned char *GetCaDescr(int *l) const;
   void Fail(bool st) { failed=st; }
   bool Failed(void) const { return failed; }
   void SetCached(void) { cached=true; }
index 28ed4cef06bc44ccab5550d33e07a917b9bd3dbe..ab6d2c67f3dc9dd9e6f3a456ae9cc87e35bb6077 100644 (file)
--- a/system.c
+++ b/system.c
@@ -136,7 +136,7 @@ void cSystem::ParseCADescriptor(cSimpleList<cEcmInfo> *ecms, unsigned short sysI
     case 0x01: // Seca style
       for(int p=2; p<len; p+=15) {
         cEcmInfo *n=new cEcmInfo(name,WORD(data,p,0x1FFF),sysId,WORD(data,p+2,0xFFFF));
-        if(data[p+4]==0xFF) n->AddData(&data[p+5],10);
+        if(data[p+4]==0xFF) n->SetDataIdx(p+5);
         ecms->Add(n);
         }
       break;
index f1c1aedb3a88dcd96a0af9649a9461d746028702..920392ae22a04b78e6c50bdd6e65cff9abaae7db 100644 (file)
@@ -227,6 +227,13 @@ bool cCardClientCCcam::ProcessECM(const cEcmInfo *ecm, const unsigned char *data
   cCCcamCard *c=&card[cardnum];\r
   int timeout=3000;\r
   if(ecm->ecm_pid!=c->Pid() || !c->Connected()) { // channel change\r
+    int n;\r
+    const unsigned char *descr=ecm->GetCaDescr(&n);\r
+    if(!descr) {\r
+      PRINTF(L_CC_CCCAM,"%d: no CA descriptor for caid %04x sid %d prov %04x",cardnum,ecm->caId,ecm->prgId,ecm->provId);\r
+      return false;\r
+      }\r
+\r
     static const unsigned char pmt[] = {\r
       0x9f,0x80,0x32,0x82,0xFF,0xFF,\r
       0x01,\r
@@ -244,7 +251,7 @@ bool cCardClientCCcam::ProcessECM(const cEcmInfo *ecm, const unsigned char *data
 #define PID_POS 27\r
       0x84,0x02,0xFF,0xFF                                 // pmt pid\r
       };\r
-    unsigned char capmt[2048];\r
+    unsigned char *capmt=AUTOMEM(sizeof(pmt)+n+32);\r
     memcpy(capmt,pmt,sizeof(pmt));\r
     int wp=sizeof(pmt);\r
     int len=wp-LEN_POS-2;\r
@@ -261,19 +268,7 @@ bool cCardClientCCcam::ProcessECM(const cEcmInfo *ecm, const unsigned char *data
     capmt[DMX_POS+3]=cardnum ;\r
     capmt[PID_POS+2]=ecm->ecm_pid>>8;\r
     capmt[PID_POS+3]=ecm->ecm_pid&0xFF;\r
-    bool streamflag=1;\r
-#if APIVERSNUM >= 10500\r
-    int casys[2];\r
-#else\r
-    unsigned short casys[2];\r
-#endif\r
-    casys[0]=ecm->caId;\r
-    casys[1]=0;\r
-    int n=GetCaDescriptors(ecm->source,ecm->transponder,ecm->prgId,casys,sizeof(capmt)-wp,&capmt[wp],streamflag);\r
-    if(n<=0) {\r
-      PRINTF(L_CC_CCCAM,"%d: no CA descriptor for caid %04x sid %d prov %04x",cardnum,ecm->caId,ecm->prgId,ecm->provId);\r
-      return false;\r
-      }\r
+    memcpy(&capmt[wp],descr,n);\r
     len+=n; wp+=n;\r
     capmt[wp++]=0x01;\r
     capmt[wp++]=0x0f;\r
index 81d08c598b05eb38d74cc6c943841eb49ea84c8a..7be1a47ea1f69dd2cf64c3fd45e3a33718271c7c 100644 (file)
@@ -89,6 +89,12 @@ bool cCardClientGbox::ProcessECM(const cEcmInfo *ecm, const unsigned char *data,
 
   const int caid=ecm->caId;
   const int pid =ecm->ecm_pid;
+  int n;
+  const unsigned char *descr=ecm->GetCaDescr(&n);
+  if(!descr) {
+    PRINTF(L_CC_GBOX,"no CA descriptor for caid %04x sid %d prov %04x",caid,ecm->prgId,ecm->provId);
+    return false;
+    }
 
   static const unsigned char pmt[] = {
     0x87,
@@ -99,23 +105,11 @@ bool cCardClientGbox::ProcessECM(const cEcmInfo *ecm, const unsigned char *data,
     0xf0,0x00,         // prg info len
     0x02, 0xff,0xec, 0xf0,0x00
     };
-  unsigned char buff[512];
+  unsigned char *buff=AUTOMEM(sizeof(pmt)+8+n);
   memcpy(buff,pmt,sizeof(pmt));
   buff[4]=ecm->prgId >> 8;
   buff[5]=ecm->prgId & 0xFF;
-#if APIVERSNUM >= 10500
-  int casys[2];
-#else
-  unsigned short casys[2];
-#endif
-  casys[0]=caid;
-  casys[1]=0;
-  bool streamFlag;
-  int n=GetCaDescriptors(ecm->source,ecm->transponder,ecm->prgId,casys,sizeof(buff)-sizeof(pmt),&buff[sizeof(pmt)],streamFlag);
-  if(n<=0) {
-    PRINTF(L_CC_GBOX,"no CA descriptor for caid %04x sid %d prov %04x",caid,ecm->prgId,ecm->provId);
-    return false;
-    }
+  memcpy(&buff[sizeof(pmt)],descr,n);
   buff[16]=0xF0 | ((n>>8)&0x0F);
   buff[17]=n & 0xFF;
   SetSctLen(&buff[1],sizeof(pmt)-4+n+4);