📄 cam.c
字号:
if(!handler->IsIdle() && handler->Sid()==prg) return true; return false;}char *cCam::CurrentKeyStr(int num){ cMutexLock lock(this); cEcmHandler *handler; for(handler=handlerList.First(); handler; handler=handlerList.Next(handler)) if(--num<0) return handler->CurrentKeyStr(); return 0;}bool cCam::Active(void){ cMutexLock lock(this); for(cEcmHandler *handler=handlerList.First(); handler; handler=handlerList.Next(handler)) if(!handler->IsIdle()) { PRINTF(L_GEN_INFO,"handler %s on card %d is not idle",handler->Id(),cardNum); return true; } return false;}void cCam::HouseKeeping(void){ cMutexLock lock(this); for(cEcmHandler *handler=handlerList.First(); handler;) { cEcmHandler *next=handlerList.Next(handler); if(handler->IsRemoveable()) RemHandler(handler); handler=next; } if(handlerList.Count()<1) { delete hookman; hookman=0; delete logger; logger=0; }}bool cCam::GetPrgCaids(int source, int transponder, int prg, caid_t *c){ return device->GetPrgCaids(source,transponder,prg,c);}void cCam::LogEcmStatus(const cEcmInfo *ecm, bool on){ cMutexLock lock(this); if(!logger && on && ScSetup.AutoUpdate) { logger=new cLogger(cardNum,IsSoftCSA()); LogStatsUp(); } if(logger) logger->EcmStatus(ecm,on);}void cCam::AddHook(cLogHook *hook){ cMutexLock lock(this); if(!hookman) hookman=new cHookManager(cardNum); if(hookman) hookman->AddHook(hook);}bool cCam::TriggerHook(int id){ return hookman && hookman->TriggerHook(id);}void cCam::SetCWIndex(int pid, int index){ if(index<MAX_CW_IDX) { ca_pid_t ca_pid; ca_pid.pid=pid; ca_pid.index=index; PRINTF(L_CORE_PIDS,"%d: descrambling pid %04x on index %x",cardNum,pid,index); if(!device->SetCaPid(&ca_pid)) if(index>0) { PRINTF(L_GEN_ERROR,"CA_SET_PID failed (%s). Expect a black screen/bad recording. Do you use the patched DVB driver?",strerror(errno)); PRINTF(L_GEN_WARN,"Adjusting 'Concurrent FF streams' to NO"); ScSetup.ConcurrentFF=0; ScSetup.Store(true); } }}void cCam::WriteCW(int index, unsigned char *cw, bool force){ if(index<MAX_CW_IDX) { for(int i=0; i<16; i+=4) cw[i+3]=cw[i]+cw[i+1]+cw[i+2]; ca_descr_t ca_descr; ca_descr.index=index; unsigned char *last=lastCW[index]; if(force || memcmp(&cw[0],&last[0],8)) { memcpy(&last[0],&cw[0],8); ca_descr.parity=0; memcpy(ca_descr.cw,&cw[0],8); if(!device->SetCaDescr(&ca_descr)) PRINTF(L_GEN_ERROR,"CA_SET_DESCR failed (%s). Expect a black screen.",strerror(errno)); } if(force || memcmp(&cw[8],&last[8],8)) { memcpy(&last[8],&cw[8],8); ca_descr.parity=1; memcpy(ca_descr.cw,&cw[8],8); if(!device->SetCaDescr(&ca_descr)) PRINTF(L_GEN_ERROR,"CA_SET_DESCR failed (%s). Expect a black screen.",strerror(errno)); } }}void cCam::DumpAV7110(void){ device->DumpAV7110();}int cCam::GetFreeIndex(void){ for(int idx=0; idx<MAX_CW_IDX; idx++) if(!indexMap[idx]) return idx; return -1;}cEcmHandler *cCam::GetHandler(int sid, bool needZero, bool noshift){ cEcmHandler *zerohandler=0, *sidhandler=0, *idlehandler=0; for(cEcmHandler *handler=handlerList.First(); handler; handler=handlerList.Next(handler)) { if(handler->Sid()==sid) sidhandler=handler; if(handler->CwIndex()==0) zerohandler=handler; if(handler->IsIdle() && (!idlehandler || (!(needZero ^ (idlehandler->CwIndex()!=0)) && (needZero ^ (handler->CwIndex()!=0))) )) idlehandler=handler; } LBSTART(L_CORE_PIDS); LBPUT("%d: SID=%d zero=%d |",cardNum,sid,needZero); if(sidhandler) LBPUT(" sid=%d/%d/%d",sidhandler->CwIndex(),sidhandler->Sid(),sidhandler->IsIdle()); else LBPUT(" sid=-/-/-"); if(zerohandler) LBPUT(" zero=%d/%d/%d",zerohandler->CwIndex(),zerohandler->Sid(),zerohandler->IsIdle()); else LBPUT(" zero=-/-/-"); if(idlehandler) LBPUT(" idle=%d/%d/%d",idlehandler->CwIndex(),idlehandler->Sid(),idlehandler->IsIdle()); else LBPUT(" idle=-/-/-"); LBEND(); if(sidhandler) { if(needZero && sidhandler->CwIndex()!=0 && !noshift) { if(!sidhandler->IsIdle()) PRINTF(L_CORE_ECM,"%d: shifting cwindex on non-idle handler.",cardNum); if(zerohandler) { if(!zerohandler->IsIdle()) PRINTF(L_CORE_ECM,"%d: shifting non-idle zero handler. This shouldn't happen!",cardNum); zerohandler->ShiftCwIndex(sidhandler->CwIndex()); sidhandler->ShiftCwIndex(0); } else if(indexMap[0]==0) { indexMap[0]=1; indexMap[sidhandler->CwIndex()]=0; sidhandler->ShiftCwIndex(0); } else PRINTF(L_CORE_ECM,"%d: zero index not free.",cardNum); } if(!needZero && sidhandler->CwIndex()==0 && !noshift) { if(!sidhandler->IsIdle()) PRINTF(L_CORE_ECM,"%d: shifting cwindex on non-idle handler.",cardNum); int idx=GetFreeIndex(); if(idx>=0) { indexMap[idx]=1; sidhandler->ShiftCwIndex(idx); indexMap[0]=0; } else PRINTF(L_CORE_ECM,"%d: no free cwindex. Can't free zero index.",cardNum); } return sidhandler; } if(needZero && zerohandler) { if(!zerohandler->IsIdle()) PRINTF(L_CORE_ECM,"%d: changing SID on non-idle zero handler. This shouldn't happen!",cardNum); return zerohandler; } if(idlehandler) { if(needZero && idlehandler->CwIndex()!=0 && !noshift) { if(indexMap[0]==0) { indexMap[0]=1; indexMap[idlehandler->CwIndex()]=0; idlehandler->ShiftCwIndex(0); } else PRINTF(L_CORE_ECM,"%d: zero index not free. (2)",cardNum); } if(!needZero && idlehandler->CwIndex()==0 && !noshift) { int idx=GetFreeIndex(); if(idx>=0) { indexMap[idx]=1; idlehandler->ShiftCwIndex(idx); indexMap[0]=0; } else PRINTF(L_CORE_ECM,"%d: no free cwindex. Can't free zero index. (2)",cardNum); } if((needZero ^ (idlehandler->CwIndex()==0))) PRINTF(L_CORE_ECM,"%d: idlehandler index doesn't match needZero",cardNum); return idlehandler; } int idx=GetFreeIndex(); if(!needZero && idx==0) { indexMap[0]=1; idx=GetFreeIndex(); indexMap[0]=0; if(idx<0) { idx=0; PRINTF(L_CORE_ECM,"%d: can't respect !needZero for new handler",cardNum); } } if(idx<0) { PRINTF(L_CORE_ECM,"%d: no free cwindex",cardNum); return 0; } indexMap[idx]=1; idlehandler=new cEcmHandler(this,cardNum,idx); handlerList.Add(idlehandler); return idlehandler;}void cCam::RemHandler(cEcmHandler *handler){ int idx=handler->CwIndex(); PRINTF(L_CORE_PIDS,"%d: removing %s on cw index %d",cardNum,handler->Id(),idx); handlerList.Del(handler); indexMap[idx]=0;}// --- cChannelCaids -----------------------------------------------------------#if APIVERSNUM >= 10500class cChannelCaids : public cSimpleItem {private: int prg, source, transponder; int numcaids; caid_t caids[MAX_CI_SLOT_CAIDS+1];public: cChannelCaids(cChannel *channel); bool IsChannel(cChannel *channel); void Sort(void); void Del(caid_t caid); bool HasCaid(caid_t caid); bool Same(cChannelCaids *ch); void HistAdd(unsigned short *hist); void Dump(int n); const caid_t *Caids(void) { caids[numcaids]=0; return caids; } int NumCaids(void) { return numcaids; } };cChannelCaids::cChannelCaids(cChannel *channel){ prg=channel->Sid(); source=channel->Source(); transponder=channel->Transponder(); numcaids=0; for(const caid_t *ids=channel->Caids(); *ids; ids++) if(numcaids<MAX_CI_SLOT_CAIDS) caids[numcaids++]=*ids; Sort();}bool cChannelCaids::IsChannel(cChannel *channel){ return prg==channel->Sid() && source==channel->Source() && transponder==channel->Transponder();}void cChannelCaids::Sort(void){ caid_t tmp[MAX_CI_SLOT_CAIDS]; int c=0xFFFF; for(int i=0; i<numcaids; i++) { int d=0; for(int j=0; j<numcaids; j++) if(caids[j]>d && caids[j]<c) d=caids[j]; tmp[i]=d; c=d; } memcpy(caids,tmp,sizeof(caids));}void cChannelCaids::Del(caid_t caid){ for(int i=0; i<numcaids; i++) if(caids[i]==caid) { numcaids--; caids[i]=caids[numcaids]; if(numcaids>0) Sort(); caids[numcaids]=0; break; }}bool cChannelCaids::HasCaid(caid_t caid){ for(int i=0; i<numcaids; i++) if(caids[i]==caid) return true; return false;}bool cChannelCaids::Same(cChannelCaids *ch){ if(numcaids!=ch->numcaids) return false; return memcmp(caids,ch->caids,numcaids*sizeof(caid_t))==0;}void cChannelCaids::HistAdd(unsigned short *hist){ for(int i=numcaids-1; i>=0; i--) hist[caids[i]]++;}void cChannelCaids::Dump(int n){ LBSTART(L_CORE_CAIDS); LBPUT("%d: channel %d/%x/%x",n,prg,source,transponder); for(const caid_t *ids=Caids(); *ids; ids++) LBPUT(" %04x",*ids); LBEND();}// --- cChannelList ------------------------------------------------------------class cChannelList : public cSimpleList<cChannelCaids> {private: int n;public: cChannelList(int N); void Unique(void); void CheckIgnore(void); int Histo(void); void Purge(int caid); };cChannelList::cChannelList(int N){ n=N;}void cChannelList::CheckIgnore(void){ for(cChannelCaids *ch=First(); ch; ch=Next(ch)) { const caid_t *ids=ch->Caids(); while(*ids) { int pri=0; if(!cSystems::FindIdentBySysId(*ids,false,pri)) { for(cChannelCaids *ch2=Next(ch); ch2; ch2=Next(ch2)) ch2->Del(*ids); ch->Del(*ids); } else ids++; } } PRINTF(L_CORE_CAIDS,"%d: after check",n); for(cChannelCaids *ch=First(); ch; ch=Next(ch)) ch->Dump(n);}void cChannelList::Unique(void){ for(cChannelCaids *ch1=First(); ch1; ch1=Next(ch1)) { for(cChannelCaids *ch2=Next(ch1); ch2;) { if(ch1->Same(ch2) || ch2->NumCaids()<1) { cChannelCaids *t=Next(ch2); Del(ch2); ch2=t; } else ch2=Next(ch2); } } if(Count()==1 && First() && First()->NumCaids()<1) Del(First()); PRINTF(L_CORE_CAIDS,"%d: after unique",n); for(cChannelCaids *ch=First(); ch; ch=Next(ch)) ch->Dump(n);}int cChannelList::Histo(void){ int h=-1; unsigned short *hist=MALLOC(unsigned short,0x10000); if(hist) { memset(hist,0,sizeof(unsigned short)*0x10000); for(cChannelCaids *ch=First(); ch; ch=Next(ch)) ch->HistAdd(hist); int c=0; for(int i=0; i<0x10000; i++) if(hist[i]>c) { h=i; c=hist[i]; } free(hist); } else PRINTF(L_GEN_ERROR,"malloc failed in cChannelList::Histo"); return h;}void cChannelList::Purge(int caid){ for(cChannelCaids *ch=First(); ch;) { if(ch->NumCaids()<=0 || ch->HasCaid(caid)) { cChannelCaids *t=Next(ch); Del(ch); ch=t; } else ch=Next(ch); } if(Count()>0) { PRINTF(L_CORE_CAIDS,"%d: still left",n); for(cChannelCaids *ch=First(); ch; ch=Next(ch)) ch->Dump(n); }}// -- cScCiAdapter -------------------------------------------------------------struct TPDU { unsigned char slot; unsigned char tcid; unsigned char tag; unsigned char len; unsigned char data[1]; };class cScCamSlot;class cScCiAdapter : public cCiAdapter {private: cDevice *device; cCam *cam; cMutex ciMutex; int cardIndex; cRingBufferLinear *rb; cScCamSlot *slots[MAX_CI_SLOTS]; // cTimeMs caidTimer; int version[MAX_CI_SLOTS]; caid_t caids[MAX_CI_SLOTS][MAX_CI_SLOT_CAIDS+1]; int tcid; // cTimeMs readTimer, writeTimer; // void BuildCaids(bool force);protected: virtual int Read(unsigned char *Buffer, int MaxLength); virtual void Write(const unsigned char *Buffer, int Length); virtual bool Reset(int Slot); virtual eModuleStatus ModuleStatus(int Slot); virtual bool Assign(cDevice *Device, bool Query=false);public: cScCiAdapter(cDevice *Device, int CardIndex, cCam *Cam); ~cScCiAdapter(); void CamStop(void); void CamAddPrg(cPrg *prg); bool CamSoftCSA(void); int GetCaids(int slot, unsigned short *Caids, int max); };// -- cScCamSlot ---------------------------------------------------------------#define SLOT_CAID_CHECK 10000#define SLOT_RESET_TIME 600class cScCamSlot : public cCamSlot, public cRingBufferLinear {private: cScCiAdapter *ciadapter; unsigned short caids[MAX_CI_SLOT_CAIDS+1]; int slot, cardIndex, version; cTimeMs checkTimer; bool reset, doReply; cTimeMs resetTimer; eModuleStatus lastStatus; // int GetLength(const unsigned char * &data); void CaInfo(unsigned char *b, int tcid, int cid); bool Check(void);public: cScCamSlot(cScCiAdapter *ca, int CardIndex, int Slot); void Process(const unsigned char *data, int len); eModuleStatus Status(void); bool Reset(bool log=true); };cScCamSlot::cScCamSlot(cScCiAdapter *ca, int CardIndex, int Slot):cCamSlot(ca),cRingBufferLinear(KILOBYTE(2),5+1,false,"SC-CI slot answer"),checkTimer(-SLOT_CAID_CHECK-1000){ ciadapter=ca; cardIndex=CardIndex; slot=Slot; version=0; caids[0]=0; doReply=false; lastStatus=msReset; Reset(false);}eModuleStatus cScCamSlot::Status(void){ eModuleStatus status; if(reset) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -