⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cam.c

📁 这是一个LINUX环境的 VDR 插件源代码,可支持Irdeto, Seca, Viaccess, Nagra, Conax & Cryptoworks等CA系统的读卡、共享等操作。
💻 C
📖 第 1 页 / 共 5 页
字号:
{  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":"-");    trigger=false;    if(filterSid!=sid) {      filterSid=sid;      filterSource=cam->Source();      filterTransponder=cam->Transponder();      filterCwIndex=cwIndex;      noKey=true; mode=0;      }    else {      if(filterCwIndex!=cwIndex) {        filterCwIndex=cwIndex;        if(mode==3 && sync)          cam->WriteCW(filterCwIndex,lastCw,true);        }      if(mode<triggerMode) mode=triggerMode;      }    triggerMode=-1;    }  dataMutex.Unlock();  switch(mode) {    case -1:      filter->SetIdleTime(IDLE_SLEEP);      break;    case 0:      StopEcm();      if(IsIdle()) { mode=-1; break; }      dolog=LOG_COUNT;      NewEcm();      filter->SetIdleTime(IDLE_GETCA);      startecm.Set();      mode=1;      break;    case 1:      if(!ecm && !JumpEcm()) {        if(startecm.Elapsed()>IDLE_GETCA_SLOW) {          if(IsIdle()) { mode=0; break; }          PRINTF(L_CORE_ECM,"%s: no encryption system found",id);          filter->SetIdleTime(IDLE_GETCA_SLOW/4);          startecm.Set();          }        break;        }      mode=4;      // fall through    case 4:    case 5:      NoSync(mode==4);      failed.Clear();      filter->SetIdleTime(IDLE_NO_SYNC/2);      lastsync.Set();      cryptPeriod=20*1000;      mode=2;      // fall through              case 2:      if(sys->NeedsData()) {        if(!UpdateEcm()) {          if(lastsync.Elapsed()<ECM_DATA_TIME) break;          PRINTF(L_CORE_ECM,"%s: no ecm extra data update (waited %d ms)",id,(int)lastsync.Elapsed());          }        if(lastsync.Elapsed()>IDLE_NO_SYNC/4 && dolog)          PRINTF(L_CORE_ECM,"%s: ecm extra data update took %d ms",id,(int)lastsync.Elapsed());        }      filter->SetIdleTime(IDLE_NO_SYNC);      mode=3;      // fall through    case 3:      {      bool resend=false, cwok=false;      if(resendTime.TimedOut()) {        resend=sync; resendTime.Set(8*24*60*60*1000);        }      if(startecm.Elapsed()<3*60*1000) cam->DumpAV7110();      if(data && len>0) {        HEXDUMP(L_HEX_ECM,data,len,"ECM sys 0x%04x id 0x%02x pid 0x%04x",ecm->caId,ecm->provId,filter->Pid());        if(SCT_LEN(data)==len) {          LDUMP(L_CORE_ECMPROC,data,16,"%s: ECM",id);          int n;          if(!(n=sys->CheckECM(ecm,data,sync))) {            if(resend || parity!=(data[0]&1)) {              int ecmid;              cTimeMs procTime;              cwok=(ecmid=failed.Get(data,len,0))>=0 && sys->ProcessECM(ecm,data);              n=(ecmid>0)?failed.Cache(ecmid,cwok,0):99;              sys->CheckECMResult(ecm,data,cwok);              if(cwok) {                parity=data[0]&1;                }              else {                if(procTime.Elapsed()>6000) {                  PRINTF(L_CORE_ECM,"%s: filter flush (elapsed %d)",id,(int)procTime.Elapsed());                  filter->Flush();                  }                if(n>=2) { count++; if(n==2) count++; }                parity=0xFF;                if(sync && lastsync.Elapsed()>cryptPeriod*2) {                  PRINTF(L_CORE_ECM,"%s: lost sync (period %d, elapsed %d)",id,cryptPeriod,(int)lastsync.Elapsed());                  NoSync(true);                  }                }              PRINTF(L_CORE_ECMPROC,"%s: (%s) cwok=%d ecmid=%d n=%d sync=%d parity=%d count=%d ELA=%d",                    id,sys->Name(),cwok,ecmid,n,sync,parity,count,(int)procTime.Elapsed());              }            }          else {            PRINTF(L_CORE_ECMPROC,"%s: check result %d\n",id,n);            switch(n) {              case 1: NoSync(true); break;              case 2: count++; break;              case 3: break;              }            }          }        else {          PRINTF(L_CORE_ECM,"%s: incomplete section %d != %d",id,len,SCT_LEN(data));          count++;          }        }      else if(sys->Constant()) {        if(sys->ProcessECM(ecm,NULL)) {          cwok=true;          if(sync) filter->SetIdleTime(IDLE_SYNC*10);           }        else count++;        }      else count++;      if(cwok) {        dolog=LOG_COUNT; sys->DoLog(true);        cam->WriteCW(filterCwIndex,sys->CW(),resend || !sync);        memcpy(lastCw,sys->CW(),sizeof(lastCw));        noKey=false; count=0;        UpdateEcm(); EcmOk();        if(!sync) {          sync=true;          filter->SetIdleTime(IDLE_SYNC);          PRINTF(L_CORE_ECM,"%s: correct key found",id);          if(!cam->IsSoftCSA())            resendTime.Set(CW_REPEAT_TIME);          }        else if(!resend)          cryptPeriod=max(5000,min(60000,(int)lastsync.Elapsed()));        lastsync.Set();        }      if(!sync && !trigger) {        if(count>=sys->MaxEcmTry()) {          EcmFail(); JumpEcm();          mode=4;          if(!ecm) {            JumpEcm();            if(!ecm) { // this should not happen!              PRINTF(L_GEN_DEBUG,"internal: handler %s, empty ecm list in sync loop",id);              mode=0; break;              }            // if we looped through all systems, we wait until the next parity            // change before we try again.            if(dolog!=LOG_COUNT && data) { parity=data[0]&1; mode=5; }            if(dolog && !--dolog) {              sys->DoLog(false);              PRINTF(L_CORE_ECM,"%s: stopping message log until valid key is found",id);              }            }          break;          }        }              if(IsIdle() && idleTime.Elapsed()>MAX_ECM_HOLD) {        PRINTF(L_CORE_ECM,"%s: hold timeout expired",id);        mode=0;        }      break;      }    }}void cEcmHandler::NoSync(bool clearParity){  if(clearParity) parity=0xFF;  count=0; sync=false;}void cEcmHandler::DeleteSys(void){  delete sys; sys=0;}char *cEcmHandler::CurrentKeyStr(void) const{  if(noKey || !sys) return 0;  return strdup(sys->CurrentKeyStr());}cEcmInfo *cEcmHandler::NewEcm(void){  ecmcache.GetCached(&ecmList,filterSid,filterSource,filterTransponder);  ecmPriList.Clear();  for(cEcmInfo *n=ecmList.First(); n; n=ecmList.Next(n)) AddEcmPri(n);  ecm=0; ecmPri=0;  return JumpEcm();}void cEcmHandler::AddEcmPri(cEcmInfo *n){  int ident, pri=0;  while((ident=cSystems::FindIdentBySysId(n->caId,!cam->IsSoftCSA(),pri))>0) {    cEcmPri *ep=new cEcmPri;    if(ep) {      ep->ecm=n;       ep->pri=pri;      ep->sysIdent=ident;      if(n->Cached() && (!ScSetup.LocalPriority || pri!=-15)) ep->pri+=20;      // keep ecmPriList sorted      cEcmPri *eppp, *epp=ecmPriList.First();      if(!epp || epp->pri<ep->pri)        ecmPriList.Ins(ep);      else {        do {          eppp=ecmPriList.Next(epp);          if(!eppp || eppp->pri<ep->pri) {            ecmPriList.Add(ep,epp);            break;            }          } while((epp=eppp));        }      }    }}void cEcmHandler::StopEcm(void){  filter->Stop(); filter->Flush();  if(ecm) cam->LogEcmStatus(ecm,false);  DeleteSys();}bool cEcmHandler::UpdateEcm(void){  if(!ecm->Data() || ecmUpdTime.TimedOut()) {    bool log=dolog;    dolog=(sys && sys->NeedsData() && ecm->Data()==0);    if(dolog) PRINTF(L_CORE_ECM,"%s: try to update ecm extra data",id);    ParseCAInfo(ecm->caId);    ecmUpdTime.Set(ECM_UPD_TIME);    dolog=log;    if(!ecm->Data()) return false;    }  return true;}cEcmInfo *cEcmHandler::JumpEcm(void){  noKey=true;  if(!ecmPri) {    ParseCAInfo(0xFFFF); // all systems    ecmPri=ecmPriList.First();    }  else ecmPri=ecmPriList.Next(ecmPri);  if(ecmPri) {    if(ecmPri->ecm!=ecm) {      StopEcm(); ecmUpdTime.Set();      ecm=ecmPri->ecm;      filter->Start(ecm->ecm_pid,ecm->ecm_table,0xfe,0,false);      cam->LogEcmStatus(ecm,true);      }    else {      DeleteSys();      filter->Flush();      }    sys=cSystems::FindBySysIdent(ecmPri->sysIdent);    if(!sys) {      if(dolog) PRINTF(L_GEN_DEBUG,"internal: handler %s, no system found for ident %04x (caid %04x pri %d)",id,ecmPri->sysIdent,ecmPri->ecm->caId,ecmPri->pri);      return JumpEcm();      }    sys->DoLog(dolog!=0); sys->CardNum(cardNum);    failed.SetMaxFail(sys->MaxEcmTry());    if(dolog) PRINTF(L_CORE_ECM,"%s: try system %s (%04x) id %04x with ecm %x%s (pri=%d)",                     id,sys->Name(),ecm->caId,ecm->provId,ecm->ecm_pid,ecm->Cached()?" (cached)":"",sys->Pri());    }  else {    StopEcm();    ecm=0;    }  return ecm;}void cEcmHandler::EcmOk(void){  ecm->SetName(sys->Name());  ecm->Fail(false);  ecmcache.New(ecm);  cEcmInfo *e=ecmList.First();  while(e) {    if(e->Cached() && e->Failed()) ecmcache.Delete(e);    e=ecmList.Next(e);    }  cLoaders::SaveCache();}void cEcmHandler::EcmFail(void){  ecm->Fail(true);}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);    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);        int sysPri=0;        cSystem *sys;        while((sys=cSystems::FindBySysId(sysId,!cam->IsSoftCSA(),sysPri))) {          sysPri=sys->Pri();          cSimpleList<cEcmInfo> ecms;          sys->ParseCADescriptor(&ecms,sysId,&buff[index+2],buff[index+1]);          delete sys;          if(ecms.Count()) {            cEcmInfo *n;            while((n=ecms.First())) {              ecms.Del(n,false);              LBSTARTF(L_CORE_ECM);              if(dolog) LBPUT("%s: found %04x (%s) id %04x with ecm %x ",id,n->caId,n->name,n->provId,n->ecm_pid);              cEcmInfo *e=ecmList.First();              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(dolog) LBPUT("(already present)");                    delete n; n=0;                    break;                    }                  else {                    e->Fail(true);                    if(dolog) LBPUT("(dup) ");                    }                  }                e=ecmList.Next(e);                }              if(n) {                if(dolog) LBPUT("(new)");                n->SetSource(sid,filterSource,filterTransponder);                ecmList.Add(n);                AddEcmPri(n);                }              LBEND();              }            break;            }          }        if(sysPri==0 && dolog) PRINTF(L_CORE_ECM,"%s: no module available for system %04x",id,sysId);        }      }    }  else if(len<0)    PRINTF(L_CORE_ECM,"%s: CA parse buffer overflow",id);  if(SysId==0xFFFF) {    for(cEcmPri *ep=ecmPriList.First(); ep; ep=ecmPriList.Next(ep))      PRINTF(L_CORE_ECMPROC,"%s: ecmPriList pri=%d ident=%04x caid=%04x pid=%04x",id,ep->pri,ep->sysIdent,ep->ecm->caId,ep->ecm->ecm_pid);    PRINTF(L_CORE_ECMPROC,"%s: ecmPri list end",id);    }}// -- cCam ---------------------------------------------------------------cCam::cCam(cScDvbDevice *dev, int CardNum){  device=dev; cardNum=CardNum;  source=transponder=-1; liveVpid=liveApid=0; logger=0; hookman=0;  memset(lastCW,0,sizeof(lastCW));  memset(indexMap,0,sizeof(indexMap));}cCam::~cCam(){  handlerList.Clear();  delete hookman;  delete logger;}bool cCam::IsSoftCSA(void){  return device->SoftCSA();}void cCam::Tune(const cChannel *channel){  cMutexLock lock(this);  if(source!=channel->Source() || transponder!=channel->Transponder()) {    source=channel->Source(); transponder=channel->Transponder();    PRINTF(L_CORE_PIDS,"%d: now tuned to source %x transponder %x",cardNum,source,transponder);    Stop();    }  else PRINTF(L_CORE_PIDS,"%d: tune to same source/transponder",cardNum);}void cCam::SetPid(int type, int pid, bool on){  cMutexLock lock(this);  int oldA=liveApid, oldV=liveVpid;  if(type==1) liveVpid=on ? pid:0;  else if(type==0) liveApid=on ? pid:0;  else if(liveVpid==pid && on) liveVpid=0;  else if(liveApid==pid && on) liveApid=0;  if(oldA!=liveApid || oldV!=liveVpid)    PRINTF(L_CORE_PIDS,"%d: livepids video=%04x audio=%04x",cardNum,liveVpid,liveApid);}void cCam::Stop(void){  cMutexLock lock(this);  for(cEcmHandler *handler=handlerList.First(); handler; handler=handlerList.Next(handler))    handler->Stop();  if(logger) logger->Down();  if(hookman) hookman->Down();}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) {      islive=true;      break;      }  bool needZero=!IsSoftCSA() && (islive || !ScSetup.ConcurrentFF);  bool noshift=IsSoftCSA() || (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);  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());    LBEND();    }  cEcmHandler *handler=GetHandler(prg->Prg(),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());    handler->SetPrg(prg);    }}bool cCam::HasPrg(int prg){  cMutexLock lock(this);  for(cEcmHandler *handler=handlerList.First(); handler; handler=handlerList.Next(handler))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -