📄 cam.c
字号:
{ 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 + -