From: leslie Date: Mon, 8 Aug 2011 18:49:04 +0000 (+0200) Subject: device/cam structural change (experimental) X-Git-Tag: upstream/620~50 X-Git-Url: http://www.vanbest.org/gitweb/?a=commitdiff_plain;h=23b6003656ed5b833b4d84faf47e205cb77c3434;p=sasc-ng.git device/cam structural change (experimental) --- diff --git a/cam.c b/cam.c index 1e8a9c2..0bc5c68 100644 --- a/cam.c +++ b/cam.c @@ -20,11 +20,15 @@ #include #include #include +#include +#include #include #include +#include #include "cam.h" +#include "global.h" #include "device.h" #include "scsetup.h" #include "filter.h" @@ -33,6 +37,7 @@ #include "override.h" #include "misc.h" #include "log-core.h" +#include "FFdecsa/FFdecsa.h" #define IDLE_SLEEP 0 // idleTime when sleeping #define IDLE_GETCA 200 // idleTime when waiting for ca descriptors @@ -155,26 +160,26 @@ void cLogStats::Action(void) // -- cHookManager ------------------------------------------------------------- class cHookManager : public cAction { - int cardNum; + const char *devId; cSimpleList hooks; // - cPidFilter *AddFilter(int Pid, int Section, int Mask, int Mode, int IdleTime, bool Crc); + cPidFilter *AddFilter(int Pid, int Section, int Mask, int IdleTime); void ClearHooks(void); void DelHook(cLogHook *hook); protected: virtual void Process(cPidFilter *filter, unsigned char *data, int len); public: - cHookManager(int CardNum); + cHookManager(cDevice *Device, const char *DevId); virtual ~cHookManager(); void AddHook(cLogHook *hook); bool TriggerHook(int id); void Down(void); }; -cHookManager::cHookManager(int CardNum) -:cAction("hookmanager",CardNum) +cHookManager::cHookManager(cDevice *Device, const char *DevId) +:cAction("hookmanager",Device,DevId) { - cardNum=CardNum; + devId=DevId; Priority(10); } @@ -207,12 +212,11 @@ bool cHookManager::TriggerHook(int id) void cHookManager::AddHook(cLogHook *hook) { Lock(); - PRINTF(L_CORE_HOOK,"%d: starting hook '%s' (%04x)",cardNum,hook->name,hook->id); + PRINTF(L_CORE_HOOK,"%s: starting hook '%s' (%04x)",devId,hook->name,hook->id); hook->delay.Set(CHAIN_HOLD); - hook->cardNum=cardNum; hooks.Add(hook); for(cPid *pid=hook->pids.First(); pid; pid=hook->pids.Next(pid)) { - cPidFilter *filter=AddFilter(pid->pid,pid->sct,pid->mask,pid->mode,CHAIN_HOLD/8,false); + cPidFilter *filter=AddFilter(pid->pid,pid->sct,pid->mask,CHAIN_HOLD/8); if(filter) { filter->userData=(void *)hook; pid->filter=filter; @@ -223,7 +227,7 @@ void cHookManager::AddHook(cLogHook *hook) void cHookManager::DelHook(cLogHook *hook) { - PRINTF(L_CORE_HOOK,"%d: stopping hook '%s' (%04x)",cardNum,hook->name,hook->id); + PRINTF(L_CORE_HOOK,"%s: stopping hook '%s' (%04x)",devId,hook->name,hook->id); for(cPid *pid=hook->pids.First(); pid; pid=hook->pids.Next(pid)) { cPidFilter *filter=pid->filter; if(filter) { @@ -234,15 +238,15 @@ void cHookManager::DelHook(cLogHook *hook) hooks.Del(hook); } -cPidFilter *cHookManager::AddFilter(int Pid, int Section, int Mask, int Mode, int IdleTime, bool Crc) +cPidFilter *cHookManager::AddFilter(int Pid, int Section, int Mask, int IdleTime) { cPidFilter *filter=NewFilter(IdleTime); if(filter) { filter->SetBuffSize(32768); - filter->Start(Pid,Section,Mask,Mode,Crc); - PRINTF(L_CORE_HOOK,"%d: added filter pid=0x%.4x sct=0x%.2x/0x%.2x/0x%.2x idle=%d crc=%d",cardNum,Pid,Section,Mask,Mode,IdleTime,Crc); + filter->Start(Pid,Section,Mask); + PRINTF(L_CORE_HOOK,"%s: added filter pid=0x%.4x sct=0x%.2x/0x%.2x idle=%d",devId,Pid,Section,Mask,IdleTime); } - else PRINTF(L_GEN_ERROR,"no free slot or filter failed to open for hookmanager %d",cardNum); + else PRINTF(L_GEN_ERROR,"no free slot or filter failed to open for hookmanager %s",devId); return filter; } @@ -257,7 +261,7 @@ void cHookManager::Process(cPidFilter *filter, unsigned char *data, int len) if(hook->bailOut || hook->delay.TimedOut()) DelHook(hook); } } - else PRINTF(L_CORE_HOOK,"%d: incomplete section %d != %d",cardNum,len,SCT_LEN(data)); + else PRINTF(L_CORE_HOOK,"%s: incomplete section %d != %d",devId,len,SCT_LEN(data)); } else { cLogHook *hook=(cLogHook *)(filter->userData); @@ -269,20 +273,22 @@ void cHookManager::Process(cPidFilter *filter, unsigned char *data, int len) class cLogChain : public cSimpleItem { public: - int cardNum, caid, source, transponder; + cCam *cam; + const char *devId; + int caid, source, transponder; bool softCSA, active, delayed; cTimeMs delay; cPids pids; cSimpleList systems; // - cLogChain(int CardNum, bool soft, int src, int tr); + cLogChain(cCam *Cam, const char *DevId, bool soft, int src, int tr); void Process(int pid, const unsigned char *data); bool Parse(const unsigned char *cat); }; -cLogChain::cLogChain(int CardNum, bool soft, int src, int tr) +cLogChain::cLogChain(cCam *Cam, const char *DevId, bool soft, int src, int tr) { - cardNum=CardNum; softCSA=soft; source=src; transponder=tr; + cam=Cam; devId=DevId; softCSA=soft; source=src; transponder=tr; active=delayed=false; } @@ -299,7 +305,7 @@ bool cLogChain::Parse(const unsigned char *cat) if(cat[0]==0x09) { caid=WORD(cat,2,0xFFFF); LBSTARTF(L_CORE_AU); - LBPUT("%d: chain caid %04x",cardNum,caid); + LBPUT("%s: chain caid %04x",devId,caid); cSystem *sys; if(systems.Count()>0) { LBPUT(" ++"); @@ -313,7 +319,7 @@ bool cLogChain::Parse(const unsigned char *cat) while((sys=cSystems::FindBySysId(caid,!softCSA,Pri))) { Pri=sys->Pri(); if(sys->HasLogger()) { - sys->CardNum(cardNum); + sys->SetOwner(cam); sys->ParseCAT(&pids,cat,source,transponder); systems.Add(sys); LBPUT(" %s(%d)",sys->Name(),sys->Pri()); @@ -325,7 +331,7 @@ bool cLogChain::Parse(const unsigned char *cat) } if(systems.Count()==0) LBPUT(" none available"); for(cPid *pid=pids.First(); pid; pid=pids.Next(pid)) - LBPUT(" [%04x-%02x/%02x/%02x]",pid->pid,pid->sct,pid->mask,pid->mode); + LBPUT(" [%04x-%02x/%02x]",pid->pid,pid->sct,pid->mask); LBEND(); if(systems.Count()>0 && pids.Count()>0) return true; @@ -337,7 +343,8 @@ bool cLogChain::Parse(const unsigned char *cat) class cLogger : public cAction { private: - int cardNum; + cCam *cam; + const char *devId; bool softCSA, up; cSimpleList chains; cSimpleList active; @@ -350,7 +357,7 @@ private: ePreMode prescan; cTimeMs pretime; // - cPidFilter *AddFilter(int Pid, int Section, int Mask, int Mode, int IdleTime, bool Crc); + cPidFilter *AddFilter(int Pid, int Section, int Mask, int IdleTime); void SetChains(void); void ClearChains(void); void StartChain(cLogChain *chain); @@ -359,7 +366,7 @@ private: protected: virtual void Process(cPidFilter *filter, unsigned char *data, int len); public: - cLogger(int CardNum, bool soft); + cLogger(cCam *Cam, cDevice *Device, const char *DevId, bool soft); virtual ~cLogger(); void EcmStatus(const cEcmInfo *ecm, bool on); void Up(void); @@ -367,10 +374,10 @@ public: void PreScan(int src, int tr); }; -cLogger::cLogger(int CardNum, bool soft) -:cAction("logger",CardNum) +cLogger::cLogger(cCam *Cam, cDevice *Device, const char *DevId, bool soft) +:cAction("logger",Device,DevId) { - cardNum=CardNum; softCSA=soft; + cam=Cam; devId=DevId; softCSA=soft; catfilt=0; up=false; prescan=pmNone; Priority(10); } @@ -384,9 +391,9 @@ void cLogger::Up(void) { Lock(); if(!up) { - PRINTF(L_CORE_AUEXTRA,"%d: UP",cardNum); + PRINTF(L_CORE_AUEXTRA,"%s: UP",devId); catVers=-1; - catfilt=AddFilter(1,0x01,0xFF,0,0,true); + catfilt=AddFilter(1,0x01,0xFF,0); up=true; } Unlock(); @@ -396,7 +403,7 @@ void cLogger::Down(void) { Lock(); if(up) { - PRINTF(L_CORE_AUEXTRA,"%d: DOWN",cardNum); + PRINTF(L_CORE_AUEXTRA,"%s: DOWN",devId); ClearChains(); DelAllFilter(); catfilt=0; up=false; prescan=pmNone; @@ -415,7 +422,7 @@ void cLogger::PreScan(int src, int tr) void cLogger::EcmStatus(const cEcmInfo *ecm, bool on) { Lock(); - PRINTF(L_CORE_AUEXTRA,"%d: ecm prgid=%d caid=%04x prov=%.4x %s",cardNum,ecm->prgId,ecm->caId,ecm->provId,on ? "active":"inactive"); + PRINTF(L_CORE_AUEXTRA,"%s: ecm prgid=%d caid=%04x prov=%.4x %s",devId,ecm->prgId,ecm->caId,ecm->provId,on ? "active":"inactive"); source=ecm->source; transponder=ecm->transponder; cEcmInfo *e; if(on) { @@ -462,13 +469,13 @@ void cLogger::ClearChains(void) void cLogger::StartChain(cLogChain *chain) { if(chain->delayed) - PRINTF(L_CORE_AUEXTRA,"%d: restarting delayed chain %04x",cardNum,chain->caid); + PRINTF(L_CORE_AUEXTRA,"%s: restarting delayed chain %04x",devId,chain->caid); chain->delayed=false; if(!chain->active) { - PRINTF(L_CORE_AU,"%d: starting chain %04x",cardNum,chain->caid); + PRINTF(L_CORE_AU,"%s: starting chain %04x",devId,chain->caid); chain->active=true; for(cPid *pid=chain->pids.First(); pid; pid=chain->pids.Next(pid)) { - cPidFilter *filter=AddFilter(pid->pid,pid->sct,pid->mask,pid->mode,CHAIN_HOLD/8,false); + cPidFilter *filter=AddFilter(pid->pid,pid->sct,pid->mask,CHAIN_HOLD/8); if(filter) { filter->userData=(void *)chain; pid->filter=filter; @@ -481,7 +488,7 @@ void cLogger::StopChain(cLogChain *chain, bool force) { if(chain->active) { if(force || (chain->delayed && chain->delay.TimedOut())) { - PRINTF(L_CORE_AU,"%d: stopping chain %04x",cardNum,chain->caid); + PRINTF(L_CORE_AU,"%s: stopping chain %04x",devId,chain->caid); chain->active=false; for(cPid *pid=chain->pids.First(); pid; pid=chain->pids.Next(pid)) { cPidFilter *filter=pid->filter; @@ -492,22 +499,22 @@ void cLogger::StopChain(cLogChain *chain, bool force) } } else if(!chain->delayed) { - PRINTF(L_CORE_AUEXTRA,"%d: delaying chain %04x",cardNum,chain->caid); + PRINTF(L_CORE_AUEXTRA,"%s: delaying chain %04x",devId,chain->caid); chain->delayed=true; chain->delay.Set(CHAIN_HOLD); } } } -cPidFilter *cLogger::AddFilter(int Pid, int Section, int Mask, int Mode, int IdleTime, bool Crc) +cPidFilter *cLogger::AddFilter(int Pid, int Section, int Mask, int IdleTime) { cPidFilter *filter=NewFilter(IdleTime); if(filter) { if(Pid>1) filter->SetBuffSize(KILOBYTE(64)); - filter->Start(Pid,Section,Mask,Mode,Crc); - PRINTF(L_CORE_AUEXTRA,"%d: added filter pid=0x%.4x sct=0x%.2x/0x%.2x/0x%.2x idle=%d crc=%d",cardNum,Pid,Section,Mask,Mode,IdleTime,Crc); + filter->Start(Pid,Section,Mask); + PRINTF(L_CORE_AUEXTRA,"%s: added filter pid=0x%.4x sct=0x%.2x/0x%.2x idle=%d",devId,Pid,Section,Mask,IdleTime); } - else PRINTF(L_GEN_ERROR,"no free slot or filter failed to open for logger %d",cardNum); + else PRINTF(L_GEN_ERROR,"no free slot or filter failed to open for logger %s",devId); return filter; } @@ -522,7 +529,7 @@ void cLogger::ProcessCat(unsigned char *data, int len) if(chain) chain->Parse(&data[i]); else { - chain=new cLogChain(cardNum,softCSA,source,transponder); + chain=new cLogChain(cam,devId,softCSA,source,transponder); if(chain->Parse(&data[i])) chains.Add(chain); else @@ -538,7 +545,7 @@ void cLogger::Process(cPidFilter *filter, unsigned char *data, int len) if(filter==catfilt) { int vers=(data[5]&0x3E)>>1; if(data[0]==0x01 && vers!=catVers) { - PRINTF(L_CORE_AUEXTRA,"%d: got CAT version %02x",cardNum,vers); + PRINTF(L_CORE_AUEXTRA,"%s: got CAT version %02x",devId,vers); catVers=vers; HEXDUMP(L_HEX_CAT,data,len,"CAT vers %02x",catVers); ClearChains(); @@ -563,7 +570,7 @@ void cLogger::Process(cPidFilter *filter, unsigned char *data, int len) if(chain->delayed) StopChain(chain,false); } } - else PRINTF(L_CORE_AU,"%d: incomplete section %d != %d",cardNum,len,SCT_LEN(data)); + else PRINTF(L_CORE_AU,"%s: incomplete section %d != %d",devId,len,SCT_LEN(data)); } } else { @@ -714,6 +721,197 @@ bool cEcmCache::ParseLinePlain(const char *line) return true; } +// -- cCaDescr ----------------------------------------------------------------- + +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); + cString ToString(void); + }; + +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); +} + +cString cCaDescr::ToString(void) +{ + if(!descr) return ""; + char *str=AUTOARRAY(char,len*3+8); + int q=sprintf(str,"%02X",descr[0]); + for(int i=1; i pids; + cCaDescr caDescr; + // + 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); + void DumpCaDescr(int c); + }; + +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; +} + +void cPrg::DumpCaDescr(int c) +{ + PRINTF(c,"prgca: %s",*caDescr.ToString()); + for(cPrgPid *pid=pids.First(); pid; pid=pids.Next(pid)) + PRINTF(c,"pidca %04x: %s",pid->pid,*pid->caDescr.ToString()); +} + +bool cPrg::SimplifyCaDescr(void) +{ +//XXX +PRINTF(L_CORE_PIDS,"SimplyCa entry pidCa=%d",HasPidCaDescr()); +DumpCaDescr(L_CORE_PIDS); +//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()); +DumpCaDescr(L_CORE_PIDS); +//XXX + + return HasPidCaDescr(); +} + // -- cEcmPri ------------------------------------------------------------------ class cEcmPri : public cSimpleItem { @@ -726,7 +924,8 @@ public: class cEcmHandler : public cSimpleItem, public cAction { private: - int cardNum, cwIndex; + const char *devId; + int cwIndex; cCam *cam; char *id; cTimeMs idleTime; @@ -767,7 +966,7 @@ private: protected: virtual void Process(cPidFilter *filter, unsigned char *data, int len); public: - cEcmHandler(cCam *Cam, int CardNum, int cwindex); + cEcmHandler(cCam *Cam, cDevice *Device, const char *DevId, int cwindex); virtual ~cEcmHandler(); void Stop(void); void SetPrg(cPrg *Prg); @@ -780,17 +979,17 @@ public: const char *Id(void) const { return id; } }; -cEcmHandler::cEcmHandler(cCam *Cam, int CardNum, int cwindex) -:cAction("ecmhandler",CardNum) +cEcmHandler::cEcmHandler(cCam *Cam, cDevice *Device, const char *DevId, int cwindex) +:cAction("ecmhandler",Device,DevId) ,failed(32,0) { cam=Cam; - cardNum=CardNum; + devId=DevId; cwIndex=cwindex; sys=0; filter=0; ecm=0; ecmPri=0; mode=-1; trigger=ecmUpd=false; triggerMode=-1; filterSource=filterTransponder=0; filterCwIndex=-1; filterSid=-1; - id=bprintf("%d.%d",cardNum,cwindex); + id=bprintf("%s.%d",devId,cwindex); } cEcmHandler::~cEcmHandler() @@ -835,7 +1034,7 @@ void cEcmHandler::ShiftCwIndex(int cwindex) if(cwIndex!=cwindex) { PRINTF(L_CORE_PIDS,"%s: shifting cwIndex from %d to %d",id,cwIndex,cwindex); free(id); - id=bprintf("%d.%d",cardNum,cwindex); + id=bprintf("%s.%d",devId,cwindex); dataMutex.Lock(); trigger=true; cwIndex=cwindex; @@ -1218,7 +1417,7 @@ cEcmInfo *cEcmHandler::JumpEcm(void) if(ecmPri->ecm!=ecm) { StopEcm(); ecm=ecmPri->ecm; - filter->Start(ecm->ecm_pid,ecm->ecm_table,0xfe,0,false); + filter->Start(ecm->ecm_pid,ecm->ecm_table,0xfe); cam->LogEcmStatus(ecm,true); } else { @@ -1230,7 +1429,8 @@ cEcmInfo *cEcmHandler::JumpEcm(void) 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); + sys->DoLog(dolog!=0); + sys->SetOwner(cam); failed.SetMaxFail(sys->MaxEcmTry()); if(dolog) PRINTF(L_CORE_ECM,"%s: try system %s (%04x) id %04x with ecm %x%s (pri=%d)", @@ -1289,6 +1489,7 @@ void cEcmHandler::ParseCAInfo(int SysId) while((n=ecms.First())) { ecms.Del(n,false); n->SetSource(filterSid,filterSource,filterTransponder); + n->SetDvb(cam->Adapter(),cam->Frontend()); n->AddCaDescr(&buff[index],buff[index+1]+2); overrides.UpdateEcm(n,dolog); LBSTARTF(L_CORE_ECM); @@ -1330,38 +1531,803 @@ void cEcmHandler::ParseCAInfo(int SysId) PRINTF(L_CORE_ECMPROC,"%s: ecmPri list end",id); } -// -- cCam --------------------------------------------------------------- +// --- cChannelCaids ----------------------------------------------------------- + +#ifndef SASC + +class 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, bool full); + void HistAdd(unsigned short *hist); + void Dump(const char *devId); + const caid_t *Caids(void) { caids[numcaids]=0; return caids; } + int NumCaids(void) { return numcaids; } + int Source(void) const { return source; } + int Transponder(void) const { return transponder; } + }; + +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(numcaidsSid() && source==channel->Source() && transponder==channel->Transponder(); +} + +void cChannelCaids::Sort(void) +{ + caid_t tmp[MAX_CI_SLOT_CAIDS]; + int c=0xFFFF; + for(int i=0; id && caids[j]0) Sort(); + caids[numcaids]=0; + break; + } +} + +bool cChannelCaids::HasCaid(caid_t caid) +{ + for(int i=0; isource || transponder!=ch->transponder)) return false; + 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(const char *devId) +{ + LBSTART(L_CORE_CAIDS); + LBPUT("%s: channel %d/%x/%x",devId,prg,source,transponder); + for(const caid_t *ids=Caids(); *ids; ids++) LBPUT(" %04x",*ids); + LBEND(); +} + +// --- cChannelList ------------------------------------------------------------ + +class cChannelList : public cSimpleList { +private: + const char *devId; +public: + cChannelList(const char *DevId); + void Unique(bool full); + void CheckIgnore(void); + int Histo(void); + void Purge(int caid, bool fullch); + }; + +cChannelList::cChannelList(const char *DevId) +{ + devId=DevId; +} + +void cChannelList::CheckIgnore(void) +{ + char *cache=MALLOC(char,0x10000); + if(!cache) return; + memset(cache,0,sizeof(char)*0x10000); + int cTotal=0, cHits=0; + for(cChannelCaids *ch=First(); ch; ch=Next(ch)) { + const caid_t *ids=ch->Caids(); + while(*ids) { + int pri=0; + if(overrides.Ignore(ch->Source(),ch->Transponder(),*ids)) + ch->Del(*ids); + else { + char c=cache[*ids]; + if(c==0) cache[*ids]=c=(cSystems::FindIdentBySysId(*ids,false,pri) ? 1 : -1); + else cHits++; + cTotal++; + if(c<0) { + for(cChannelCaids *ch2=Next(ch); ch2; ch2=Next(ch2)) ch2->Del(*ids); + ch->Del(*ids); + } + else ids++; + } + } + } + free(cache); + PRINTF(L_CORE_CAIDS,"%s: after check",devId); + for(cChannelCaids *ch=First(); ch; ch=Next(ch)) ch->Dump(devId); + PRINTF(L_CORE_CAIDS,"%s: check cache usage: %d requests, %d hits, %d%% hits",devId,cTotal,cHits,(cTotal>0)?(cHits*100/cTotal):0); +} + +void cChannelList::Unique(bool full) +{ + for(cChannelCaids *ch1=First(); ch1; ch1=Next(ch1)) { + for(cChannelCaids *ch2=Next(ch1); ch2;) { + if(ch1->Same(ch2,full) || 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,"%s: after unique (%d)",devId,full); + for(cChannelCaids *ch=First(); ch; ch=Next(ch)) ch->Dump(devId); +} + +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, bool fullch) +{ + for(cChannelCaids *ch=First(); ch;) { + if(!fullch) ch->Del(caid); + if(ch->NumCaids()<=0 || (fullch && ch->HasCaid(caid))) { + cChannelCaids *t=Next(ch); + Del(ch); + ch=t; + } + else ch=Next(ch); + } + if(Count()>0) { + PRINTF(L_CORE_CAIDS,"%s: still left",devId); + for(cChannelCaids *ch=First(); ch; ch=Next(ch)) ch->Dump(devId); + } +} + +// -- cCiFrame ----------------------------------------------------------------- + +#define LEN_OFF 2 + +cCiFrame::cCiFrame(void) +{ + rb=0; mem=0; len=alen=glen=0; +} + +cCiFrame::~cCiFrame() +{ + free(mem); +} + +unsigned char *cCiFrame::GetBuff(int l) +{ + if(!mem || l>alen) { + free(mem); mem=0; alen=0; + mem=MALLOC(unsigned char,l+LEN_OFF); + if(mem) alen=l; + } + len=l; + if(!mem) { + PRINTF(L_GEN_DEBUG,"internal: ci-frame alloc failed"); + return 0; + } + return mem+LEN_OFF; +} + +void cCiFrame::Put(void) +{ + if(rb && mem) { + *((short *)mem)=len; + rb->Put(mem,len+LEN_OFF); + } +} + +unsigned char *cCiFrame::Get(int &l) +{ + if(rb) { + int c; + unsigned char *data=rb->Get(c); + if(data) { + if(c>LEN_OFF) { + int s=*((short *)data); + if(c>=s+LEN_OFF) { + l=glen=s; + return data+LEN_OFF; + } + } + LDUMP(L_GEN_DEBUG,data,c,"internal: ci rb frame sync got=%d avail=%d -",c,rb->Available()); + rb->Clear(); + } + } + return 0; +} + +int cCiFrame::Avail(void) +{ + return rb ? rb->Available() : 0; +} + +void cCiFrame::Del(void) +{ + if(rb && glen) { + rb->Del(glen+LEN_OFF); + glen=0; + } +} + +// -- cScCamSlot --------------------------------------------------------------- + +#define TDPU_SIZE_INDICATOR 0x80 + +#define CAID_TIME 300000 // time between caid scans +#define TRIGGER_TIME 10000 // min. time between caid scan trigger +#define SLOT_CAID_CHECK 10000 +#define SLOT_RESET_TIME 600 + +class cScCamSlot : public cCamSlot { +private: + cCam *cam; + unsigned short caids[MAX_CI_SLOT_CAIDS+1]; + int slot, version; + const char *devId; + cTimeMs checkTimer; + bool reset, doReply; + cTimeMs resetTimer; + eModuleStatus lastStatus; + cRingBufferLinear rb; + cCiFrame frame; + // + int GetLength(const unsigned char * &data); + int LengthSize(int n); + void SetSize(int n, unsigned char * &p); + void CaInfo(int tcid, int cid); + bool Check(void); +public: + cScCamSlot(cCam *Cam, const char *DevId, int Slot); + void Process(const unsigned char *data, int len); + eModuleStatus Status(void); + bool Reset(bool log=true); + cCiFrame *Frame(void) { return &frame; } + }; + +cScCamSlot::cScCamSlot(cCam *Cam, const char *DevId, int Slot) +:cCamSlot(Cam) +,checkTimer(-SLOT_CAID_CHECK-1000) +,rb(KILOBYTE(4),5+LEN_OFF,false,"SC-CI slot answer") +{ + cam=Cam; devId=DevId; slot=Slot; + version=0; caids[0]=0; doReply=false; lastStatus=msReset; + frame.SetRb(&rb); + Reset(false); +} + +eModuleStatus cScCamSlot::Status(void) +{ + eModuleStatus status; + if(reset) { + status=msReset; + if(resetTimer.TimedOut()) reset=false; + } + else if(caids[0]) status=msReady; + else { + status=msPresent; //msNone; + Check(); + } + if(status!=lastStatus) { + static const char *stext[] = { "none","reset","present","ready" }; + PRINTF(L_CORE_CI,"%s.%d: status '%s'",devId,slot,stext[status]); + lastStatus=status; + } + return status; +} + +bool cScCamSlot::Reset(bool log) +{ + reset=true; resetTimer.Set(SLOT_RESET_TIME); + rb.Clear(); + if(log) PRINTF(L_CORE_CI,"%s.%d: reset",devId,slot); + return true; +} + +bool cScCamSlot::Check(void) +{ + bool res=false; + bool dr=cam->IsSoftCSA(false) || ScSetup.ConcurrentFF>0; + if(dr!=doReply && !IsDecrypting()) { + PRINTF(L_CORE_CI,"%s.%d: doReply changed, reset triggered",devId,slot); + Reset(false); + doReply=dr; + } + if(checkTimer.TimedOut()) { + if(version!=cam->GetCaids(slot,0,0)) { + version=cam->GetCaids(slot,caids,MAX_CI_SLOT_CAIDS); + PRINTF(L_CORE_CI,"%s.%d: now using CAIDs version %d",devId,slot,version); + res=true; + } + checkTimer.Set(SLOT_CAID_CHECK); + } + return res; +} + +int cScCamSlot::GetLength(const unsigned char * &data) +{ + int len=*data++; + if(len&TDPU_SIZE_INDICATOR) { + int i; + for(i=len&~TDPU_SIZE_INDICATOR, len=0; i>0; i--) len=(len<<8) + *data++; + } + return len; +} + +int cScCamSlot::LengthSize(int n) +{ + return n>8; *p++=n&0xFF; } +} + +void cScCamSlot::CaInfo(int tcid, int cid) +{ + int cn=0; + for(int i=0; caids[i]; i++) cn+=2; + int n=cn+8+LengthSize(cn); + unsigned char *p; + if(!(p=frame.GetBuff(n+1+LengthSize(n)))) return; + *p++=0xa0; + SetSize(n,p); + *p++=tcid; + *p++=0x90; + *p++=0x02; *p++=cid>>8; *p++=cid&0xff; + *p++=0x9f; *p++=0x80; *p++=0x31; // AOT_CA_INFO + SetSize(cn,p); + for(int i=0; caids[i]; i++) { *p++=caids[i]>>8; *p++=caids[i]&0xff; } + frame.Put(); + PRINTF(L_CORE_CI,"%s.%d sending CA info",devId,slot); +} + +void cScCamSlot::Process(const unsigned char *data, int len) +{ + const unsigned char *save=data; + data+=3; + int dlen=GetLength(data); + if(dlen>len-(data-save)) { + PRINTF(L_CORE_CI,"%s.%d TDPU length exceeds data length",devId,slot); + dlen=len-(data-save); + } + int tcid=data[0]; + + if(Check()) CaInfo(tcid,0x01); + + if(dlen<8 || data[1]!=0x90) return; + int cid=(data[3]<<8)+data[4]; + int tag=(data[5]<<16)+(data[6]<<8)+data[7]; + data+=8; + dlen=GetLength(data); + if(dlen>len-(data-save)) { + PRINTF(L_CORE_CI,"%s.%d tag length exceeds data length",devId,slot); + dlen=len-(data-save); + } + switch(tag) { + case 0x9f8030: // AOT_CA_INFO_ENQ + CaInfo(tcid,cid); + break; + + case 0x9f8032: // AOT_CA_PMT + if(dlen>=6) { + int ca_lm=data[0]; + int ci_cmd=-1; + cPrg *prg=new cPrg((data[1]<<8)+data[2],ca_lm==5); + int ilen=(data[4]<<8)+data[5]; + LBSTARTF(L_CORE_CI); + LBPUT("%s.%d CA_PMT decoding len=%x lm=%x prg=%d len=%x",devId,slot,dlen,ca_lm,(data[1]<<8)+data[2],ilen); + data+=6; dlen-=6; + LBPUT("/%x",dlen); + if(ilen>0 && dlen>=ilen) { + ci_cmd=data[0]; + if(ilen>1) + prg->caDescr.Set(&data[1],ilen-1); + LBPUT(" ci_cmd(G)=%02x",ci_cmd); + } + data+=ilen; dlen-=ilen; + while(dlen>=5) { + cPrgPid *pid=new cPrgPid(data[0],(data[1]<<8)+data[2]); + prg->pids.Add(pid); + ilen=(data[3]<<8)+data[4]; + LBPUT(" pid=%d,%x len=%x",data[0],(data[1]<<8)+data[2],ilen); + data+=5; dlen-=5; + LBPUT("/%x",dlen); + if(ilen>0 && dlen>=ilen) { + ci_cmd=data[0]; + if(ilen>1) { + pid->caDescr.Set(&data[1],ilen-1); + prg->SetPidCaDescr(true); + } + LBPUT(" ci_cmd(S)=%x",ci_cmd); + } + data+=ilen; dlen-=ilen; + } + LBEND(); + PRINTF(L_CORE_CI,"%s.%d got CA pmt ciCmd=%d caLm=%d",devId,slot,ci_cmd,ca_lm); + if(doReply && (ci_cmd==0x03 || (ci_cmd==0x01 && ca_lm==0x03))) { + unsigned char *b; + if((b=frame.GetBuff(4+11))) { + b[0]=0xa0; b[2]=tcid; + 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->sid<<8; + b[12]=prg->sid&0xff; + b[13]=0x00; + b[14]=0x81; // CA_ENABLE + b[10]=4; b[1]=4+9; + frame.Put(); + PRINTF(L_CORE_CI,"%s.%d answer to query",devId,slot); + } + } + if(prg->sid!=0) { + if(ci_cmd==0x04) { + PRINTF(L_CORE_CI,"%s.%d stop decrypt",devId,slot); + cam->Stop(); + } + if(ci_cmd==0x01 || (ci_cmd==-1 && (ca_lm==0x04 || ca_lm==0x05))) { + PRINTF(L_CORE_CI,"%s.%d set CAM decrypt (prg %d)",devId,slot,prg->sid); + cam->AddPrg(prg); + } + } + delete prg; + } + break; + } +} + +#endif //SASC + +// -- cCams -------------------------------------------------------------------- + +class cCams : public cSimpleList { +public: + cMutex listMutex; + // + void Register(cCam *cam); + void Unregister(cCam *cam); + }; + +static cCams cams; + +void cCams::Register(cCam *cam) +{ + cMutexLock lock(&listMutex); + Add(cam); +} -cCam::cCam(cScDevice *dev, int CardNum) +void cCams::Unregister(cCam *cam) { - device=dev; cardNum=CardNum; + cMutexLock lock(&listMutex); + Del(cam,false); +} + +// -- cGlobal ------------------------------------------------------------------ + +char *cGlobal::CurrKeyStr(int camindex, int num, const char **id) +{ + cMutexLock lock(&cams.listMutex); + char *str=0; + cCam *c; + for(c=cams.First(); c && camindex>0; c=cams.Next(c), camindex--); + if(c) { + str=c->CurrentKeyStr(num,id); + if(!str && num==0) str=strdup(tr("(none)")); + } + return str; +} + +void cGlobal::HouseKeeping(void) +{ + cMutexLock lock(&cams.listMutex); + for(cCam *c=cams.First(); c; c=cams.Next(c)) c->HouseKeeping(); +} + +bool cGlobal::Active(bool log) +{ + cMutexLock lock(&cams.listMutex); + for(cCam *c=cams.First(); c; c=cams.Next(c)) if(c->Active(log)) return true; + return false; +} + +void cGlobal::CaidsChanged(void) +{ + cMutexLock lock(&cams.listMutex); + PRINTF(L_CORE_CAIDS,"caid list rebuild triggered"); + for(cCam *c=cams.First(); c; c=cams.Next(c)) c->CaidsChanged(); +} + +// -- cCam --------------------------------------------------------------- + +struct TPDU { + unsigned char slot; + unsigned char tcid; + unsigned char tag; + unsigned char len; + unsigned char data[1]; + }; + +cCam::cCam(cDevice *Device, int Adapter, int Frontend, const char *DevId, int Cafd, bool SoftCSA, bool FullTS) +{ + device=Device; adapter=Adapter; frontend=Frontend; devId=DevId; cafd=Cafd; + softcsa=SoftCSA; fullts=FullTS; + tcid=0; rebuildcaids=false; + memset(version,0,sizeof(version)); + memset(slots,0,sizeof(slots)); + SetDescription("SC-CI adapter on device %s",devId); + rb=new cRingBufferLinear(KILOBYTE(8),6+LEN_OFF,false,"SC-CI adapter read"); + if(rb) { + rb->SetTimeouts(0,CAM_READ_TIMEOUT); + frame.SetRb(rb); + BuildCaids(true); + slots[0]=new cScCamSlot(this,devId,0); + Start(); + } + else PRINTF(L_GEN_ERROR,"failed to create ringbuffer for SC-CI adapter %s.",devId); + + decsa=new cDeCSA(devId); + 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)); + cams.Register(this); } cCam::~cCam() { + cams.Unregister(this); handlerList.Clear(); delete hookman; delete logger; + Cancel(3); + ciMutex.Lock(); + delete rb; rb=0; + ciMutex.Unlock(); + delete decsa; decsa=0; +} + +bool cCam::OwnSlot(const cCamSlot *slot) const +{ + if(slots[0]==slot) return true; + //for(int i=0; iGroupSep() && channel->Ca()>=CA_ENCRYPTED_MIN && device->ProvidesTransponder(channel)) { + cChannelCaids *ch=new cChannelCaids(channel); + if(ch) list.Add(ch); + } + } + Channels.Unlock(); + list.Unique(true); + list.CheckIgnore(); + list.Unique(false); + + int n=0, h; + caid_t c[MAX_CI_SLOT_CAIDS+1]; + memset(c,0,sizeof(c)); + do { + if((h=list.Histo())<0) break; + c[n++]=h; + LBSTART(L_CORE_CAIDS); + LBPUT("%s: added %04x caids now",devId,h); for(int i=0; i0); + c[n]=0; + if(n==0) PRINTF(L_CORE_CI,"%s: no active CAIDs",devId); + else if(list.Count()>0) PRINTF(L_GEN_ERROR,"too many CAIDs. You should ignore some CAIDs."); + + ciMutex.Lock(); + if((version[0]==0 && c[0]!=0) || memcmp(caids[0],c,sizeof(caids[0]))) { + memcpy(caids[0],c,sizeof(caids[0])); + version[0]++; + if(version[0]>0) { + LBSTART(L_CORE_CI); + LBPUT("card %s, slot %d (v=%2d) caids:",devId,0,version[0]); + for(int i=0; caids[0][i]; i++) LBPUT(" %04x",caids[0][i]); + LBEND(); + } + } + ciMutex.Unlock(); + + caidTimer.Set(CAID_TIME); + triggerTimer.Set(TRIGGER_TIME); + rebuildcaids=false; + } +} + +int cCam::Read(unsigned char *Buffer, int MaxLength) +{ + cMutexLock lock(&ciMutex); + if(rb && Buffer && MaxLength>0) { + int s; + unsigned char *data=frame.Get(s); + if(data) { + if(s<=MaxLength) memcpy(Buffer,data,s); + else PRINTF(L_GEN_DEBUG,"internal: sc-ci %s rb frame size exceeded %d",devId,s); + frame.Del(); + if(Buffer[2]!=0x80 || LOG(L_CORE_CIFULL)) { + LDUMP(L_CORE_CI,Buffer,s,"%s.%d <-",devId,Buffer[0]); + readTimer.Set(); + } + return s; + } + } + else cCondWait::SleepMs(CAM_READ_TIMEOUT); + if(LOG(L_CORE_CIFULL) && readTimer.Elapsed()>2000) { + PRINTF(L_CORE_CIFULL,"%s: read heartbeat",devId); + readTimer.Set(); + } + return 0; +} + +#define TPDU(data,slot) do { unsigned char *_d=(data); _d[0]=(slot); _d[1]=tcid; } while(0) +#define TAG(data,tag,len) do { unsigned char *_d=(data); _d[0]=(tag); _d[1]=(len); } while(0) +#define SB_TAG(data,sb) do { unsigned char *_d=(data); _d[0]=0x80; _d[1]=0x02; _d[2]=tcid; _d[3]=(sb); } while(0) + +void cCam::Write(const unsigned char *buff, int len) +{ + cMutexLock lock(&ciMutex); + if(buff && len>=5) { + struct TPDU *tpdu=(struct TPDU *)buff; + int slot=tpdu->slot; + cCiFrame *slotframe=slots[slot]->Frame(); + if(buff[2]!=0xA0 || buff[3]>0x01 || LOG(L_CORE_CIFULL)) + LDUMP(L_CORE_CI,buff,len,"%s.%d ->",devId,slot); + if(slots[slot]) { + switch(tpdu->tag) { + case 0x81: // T_RCV + { + int s; + unsigned char *d=slotframe->Get(s); + if(d) { + unsigned char *b; + if((b=frame.GetBuff(s+6))) { + TPDU(b,slot); + memcpy(b+2,d,s); + slotframe->Del(); // delete from rb before Avail() + SB_TAG(b+2+s,slotframe->Avail()>0 ? 0x80:0x00); + frame.Put(); + } + else slotframe->Del(); + } + break; + } + case 0x82: // T_CREATE_TC + { + tcid=tpdu->data[0]; + unsigned char *b; + static const unsigned char reqCAS[] = { 0xA0,0x07,0x01,0x91,0x04,0x00,0x03,0x00,0x41 }; + if((b=slotframe->GetBuff(sizeof(reqCAS)))) { + memcpy(b,reqCAS,sizeof(reqCAS)); + b[2]=tcid; + slotframe->Put(); + } + if((b=frame.GetBuff(9))) { + TPDU(b,slot); + TAG(&b[2],0x83,0x01); b[4]=tcid; + SB_TAG(&b[5],slotframe->Avail()>0 ? 0x80:0x00); + frame.Put(); + } + break; + } + case 0xA0: // T_DATA_LAST + { + slots[slot]->Process(buff,len); + unsigned char *b; + if((b=frame.GetBuff(6))) { + TPDU(b,slot); + SB_TAG(&b[2],slotframe->Avail()>0 ? 0x80:0x00); + frame.Put(); + } + break; + } + } + } + } + else PRINTF(L_CORE_CIFULL,"%s: short write (buff=%d len=%d)",devId,buff!=0,len); +} + +bool cCam::Reset(int Slot) +{ + cMutexLock lock(&ciMutex); + PRINTF(L_CORE_CI,"%s: reset of slot %d requested",devId,Slot); + return slots[Slot] ? slots[Slot]->Reset():false; +} + +eModuleStatus cCam::ModuleStatus(int Slot) +{ + cMutexLock lock(&ciMutex); + bool enable=ScSetup.CapCheck(device->CardIndex()); + if(!enable) Stop(); + return (enable && slots[Slot]) ? slots[Slot]->Status():msNone; +} + +bool cCam::Assign(cDevice *Device, bool Query) +{ + return Device ? (Device==device) : true; } bool cCam::IsSoftCSA(bool live) { - return device->SoftCSA(live); + return softcsa && (!fullts || !live); } void cCam::Tune(const cChannel *channel) { - cMutexLock lock(this); + cMutexLock lock(&camMutex); if(source!=channel->Source() || transponder!=channel->Transponder()) { source=channel->Source(); transponder=channel->Transponder(); - PRINTF(L_CORE_PIDS,"%d: now tuned to source %x(%s) transponder %x",cardNum,source,*cSource::ToString(source),transponder); + PRINTF(L_CORE_PIDS,"%s: now tuned to source %x(%s) transponder %x",devId,source,*cSource::ToString(source),transponder); Stop(); } - else PRINTF(L_CORE_PIDS,"%d: tune to same source/transponder",cardNum); + else PRINTF(L_CORE_PIDS,"%s: tune to same source/transponder",devId); } void cCam::PostTune(void) @@ -1374,19 +2340,19 @@ void cCam::PostTune(void) void cCam::SetPid(int type, int pid, bool on) { - cMutexLock lock(this); + cMutexLock lock(&camMutex); 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); + PRINTF(L_CORE_PIDS,"%s: livepids video=%04x audio=%04x",devId,liveVpid,liveApid); } void cCam::Stop(void) { - cMutexLock lock(this); + cMutexLock lock(&camMutex); for(cEcmHandler *handler=handlerList.First(); handler; handler=handlerList.Next(handler)) handler->Stop(); if(logger) logger->Down(); @@ -1396,7 +2362,7 @@ void cCam::Stop(void) void cCam::AddPrg(cPrg *prg) { - cMutexLock lock(this); + cMutexLock lock(&camMutex); bool islive=false; for(cPrgPid *pid=prg->pids.First(); pid; pid=prg->pids.Next(pid)) if(pid->pid==liveVpid || pid->pid==liveApid) { @@ -1405,10 +2371,10 @@ void cCam::AddPrg(cPrg *prg) } 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->sid,needZero,noshift); + PRINTF(L_CORE_PIDS,"%s: %s SID %d (zero=%d noshift=%d)",devId,prg->IsUpdate()?"update":"add",prg->sid,needZero,noshift); if(prg->pids.Count()>0) { LBSTART(L_CORE_PIDS); - LBPUT("%d: pids",cardNum); + LBPUT("%s: pids",devId); for(cPrgPid *pid=prg->pids.First(); pid; pid=prg->pids.Next(pid)) LBPUT(" %s=%04x",TYPENAME(pid->type),pid->pid); LBEND(); @@ -1422,14 +2388,14 @@ void cCam::AddPrg(cPrg *prg) 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()); + PRINTF(L_CORE_PIDS,"%s: found handler for SID %d (%s idle=%d idx=%d)",devId,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); + PRINTF(L_CORE_PIDS,"%s: SID %d is handled as splitted",devId,prg->sid); // first update the splitSid list if(prg->pids.Count()==0) { // delete for(int i=0; splitSid[i]; i++) @@ -1437,7 +2403,7 @@ void cCam::AddPrg(cPrg *prg) memmove(&splitSid[i],&splitSid[i+1],sizeof(splitSid[0])*(MAX_SPLIT_SID-i)); break; } - PRINTF(L_CORE_PIDS,"%d: deleted from list",cardNum); + PRINTF(L_CORE_PIDS,"%s: deleted from list",devId); } else { // add bool has=false; @@ -1447,13 +2413,13 @@ void cCam::AddPrg(cPrg *prg) if(isid; splitSid[i+1]=0; - PRINTF(L_CORE_PIDS,"%d: added to list",cardNum); + PRINTF(L_CORE_PIDS,"%s: added to list",devId); } - else PRINTF(L_CORE_PIDS,"%d: split SID list overflow",cardNum); + else PRINTF(L_CORE_PIDS,"%s: split SID list overflow",devId); } } LBSTART(L_CORE_PIDS); - LBPUT("%d: split SID list now:",cardNum); + LBPUT("%s: split SID list now:",devId); for(int i=0; i<=MAX_SPLIT_SID; i++) LBPUT(" %d",splitSid[i]); LBEND(); // prepare an empty prg head @@ -1465,7 +2431,7 @@ void cCam::AddPrg(cPrg *prg) cPrgPid *first; while((first=prg->pids.First())) { LBSTARTF(L_CORE_PIDS); - LBPUT("%d: group %d pids",cardNum,group); + LBPUT("%s: group %d pids",devId,group); prg->pids.Del(first,false); work.caDescr.Set(&first->caDescr); first->caDescr.Clear(); @@ -1498,7 +2464,7 @@ void cCam::AddPrg(cPrg *prg) // 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()); + PRINTF(L_CORE_PIDS,"%s: found handler for group-SID %d (%s idle=%d idx=%d)",devId,grsid,handler->Id(),handler->IsIdle(),handler->CwIndex()); work.sid=grsid; handler->SetPrg(&work); } @@ -1514,7 +2480,7 @@ void cCam::AddPrg(cPrg *prg) 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()); + PRINTF(L_CORE_PIDS,"%s: idle group handler %s idx=%d",devId,handler->Id(),handler->CwIndex()); work.sid=handler->Sid(); handler->SetPrg(&work); } @@ -1525,16 +2491,17 @@ void cCam::AddPrg(cPrg *prg) bool cCam::HasPrg(int prg) { - cMutexLock lock(this); + cMutexLock lock(&camMutex); for(cEcmHandler *handler=handlerList.First(); handler; handler=handlerList.Next(handler)) if(!handler->IsIdle() && handler->Sid()==prg) return true; return false; } -char *cCam::CurrentKeyStr(int num) +char *cCam::CurrentKeyStr(int num, const char **id) { - cMutexLock lock(this); + cMutexLock lock(&camMutex); + if(id) *id=devId; cEcmHandler *handler; for(handler=handlerList.First(); handler; handler=handlerList.Next(handler)) if(--num<0) return handler->CurrentKeyStr(); @@ -1543,10 +2510,10 @@ char *cCam::CurrentKeyStr(int num) bool cCam::Active(bool log) { - cMutexLock lock(this); + cMutexLock lock(&camMutex); for(cEcmHandler *handler=handlerList.First(); handler; handler=handlerList.Next(handler)) if(!handler->IsIdle()) { - if(log) PRINTF(L_GEN_INFO,"handler %s on card %d is not idle",handler->Id(),cardNum); + if(log) PRINTF(L_GEN_INFO,"handler %s on card %s is not idle",handler->Id(),devId); return true; } return false; @@ -1554,7 +2521,7 @@ bool cCam::Active(bool log) void cCam::HouseKeeping(void) { - cMutexLock lock(this); + cMutexLock lock(&camMutex); for(cEcmHandler *handler=handlerList.First(); handler;) { cEcmHandler *next=handlerList.Next(handler); if(handler->IsRemoveable()) RemHandler(handler); @@ -1568,24 +2535,24 @@ void cCam::HouseKeeping(void) void cCam::LogStartup(void) { - cMutexLock lock(this); + cMutexLock lock(&camMutex); if(!logger && ScSetup.AutoUpdate) { - logger=new cLogger(cardNum,IsSoftCSA(false)); + logger=new cLogger(this,device,devId,IsSoftCSA(false)); LogStatsUp(); } } void cCam::LogEcmStatus(const cEcmInfo *ecm, bool on) { - cMutexLock lock(this); + cMutexLock lock(&camMutex); if(on) LogStartup(); if(logger) logger->EcmStatus(ecm,on); } void cCam::AddHook(cLogHook *hook) { - cMutexLock lock(this); - if(!hookman) hookman=new cHookManager(cardNum); + cMutexLock lock(&camMutex); + if(!hookman) hookman=new cHookManager(device,devId); if(hookman) hookman->AddHook(hook); } @@ -1600,8 +2567,8 @@ void cCam::SetCWIndex(int pid, int index) 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)) + PRINTF(L_CORE_PIDS,"%s: descrambling pid %04x on index %x",devId,pid,index); + if(!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"); @@ -1622,7 +2589,7 @@ void cCam::WriteCW(int index, unsigned char *cw, bool force) memcpy(&last[0],&cw[0],8); ca_descr.parity=0; memcpy(ca_descr.cw,&cw[0],8); - if(!device->SetCaDescr(&ca_descr,force)) + if(!SetCaDescr(&ca_descr,force)) PRINTF(L_GEN_ERROR,"CA_SET_DESCR failed (%s). Expect a black screen.",strerror(errno)); } @@ -1630,15 +2597,115 @@ void cCam::WriteCW(int index, unsigned char *cw, bool force) memcpy(&last[8],&cw[8],8); ca_descr.parity=1; memcpy(ca_descr.cw,&cw[8],8); - if(!device->SetCaDescr(&ca_descr,force)) + if(!SetCaDescr(&ca_descr,force)) PRINTF(L_GEN_ERROR,"CA_SET_DESCR failed (%s). Expect a black screen.",strerror(errno)); } } } +bool cCam::SetCaDescr(ca_descr_t *ca_descr, bool initial) +{ +#ifndef SASC + if(!softcsa || (fullts && ca_descr->index==0)) { + cMutexLock lock(&cafdMutex); + return ioctl(cafd,CA_SET_DESCR,ca_descr)>=0; + } + else if(decsa) return decsa->SetDescr(ca_descr,initial); +#endif // !SASC + return false; +} + +bool cCam::SetCaPid(ca_pid_t *ca_pid) +{ +#ifndef SASC + if(!softcsa || (fullts && ca_pid->index==0)) { + cMutexLock lock(&cafdMutex); + return ioctl(cafd,CA_SET_PID,ca_pid)>=0; + } + else if(decsa) return decsa->SetCaPid(ca_pid); +#endif // !SASC + return false; +} + +#ifndef SASC +static unsigned int av7110_read(int fd, unsigned int addr) +{ + ca_pid_t arg; + arg.pid=addr; + ioctl(fd,CA_GET_MSG,&arg); + return arg.index; +} +#endif // !SASC + +#if 0 +static void av7110_write(int fd, unsigned int addr, unsigned int val) +{ + ca_pid_t arg; + arg.pid=addr; + arg.index=val; + ioctl(fd,CA_SEND_MSG,&arg); +} +#endif + void cCam::DumpAV7110(void) { - device->DumpAV7110(); +#ifndef SASC + if(LOG(L_CORE_AV7110)) { +#define CODEBASE (0x2e000404+0x1ce00) + cMutexLock lock(&cafdMutex); + if(device->HasDecoder() && lastDump.Elapsed()>20000) { + lastDump.Set(); + static unsigned int handles=0, hw_handles=0; + static const unsigned int code[] = { + 0xb5100040,0x4a095a12,0x48094282,0xd00b4b09,0x20000044, + 0x5b1c4294,0xd0033001,0x281cdbf8,0xe001f7fe,0xfd14bc10 + }; + static const unsigned int mask[] = { + 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff, + 0xffffffff,0xffffffff,0xffffffff,0xfffff800,0xf800ffff + }; + if(!handles) { + handles=1; + PRINTF(L_CORE_AV7110,"searching handle tables"); + for(int i=0; i<0x2000; i+=4) { + int j; + for(j=0; j<20; j+=4) { + int r=av7110_read(cafd,CODEBASE+i+j); + if((r&mask[j/4])!=(code[j/4]&mask[j/4])) break; + } + if(j==20) { + handles=av7110_read(cafd,CODEBASE+i+44); + hw_handles=av7110_read(cafd,CODEBASE+i+52); + PRINTF(L_CORE_AV7110,"found handles=%08x hw_handles=%08x at 0x%08x",handles,hw_handles,CODEBASE+i); + if((handles>>16)!=0x2e08 || (hw_handles>>16)!=0x2e08) { + PRINTF(L_CORE_AV7110,"seems to be invalid"); + } + break; + } + } + } + + unsigned int hdl=0, hwhdl=0; + PRINTF(L_CORE_AV7110," : 64000080 64000400"); + for(int i=0; i<=31; i++) { + unsigned int off80 =av7110_read(cafd,0x64000080+i*4); + unsigned int off400=av7110_read(cafd,0x64000400+i*8); + LBSTART(L_CORE_AV7110); + LBPUT("handle %2d: %08x %08x %s pid=%04x idx=%d", + i,off80,off400,off80&0x2000?"ACT":"---",off80&0x1fff,(off400&0x1e)>>1); + if(handles>1 && i<=27) { + if((i&1)==0) { + hdl=av7110_read(cafd,handles+i*2); + hwhdl=av7110_read(cafd,hw_handles+i*2); + } + unsigned int s=((~i)&1)<<4; + LBPUT(" | %02d hdl=%04x hwfilt=%04x",i,(hdl>>s)&0xffff,(hwhdl>>s)&0xffff); + } + LBEND(); + } + } + } +#endif // !SASC } int cCam::GetFreeIndex(void) @@ -1660,7 +2727,7 @@ cEcmHandler *cCam::GetHandler(int sid, bool needZero, bool noshift) idlehandler=handler; } LBSTART(L_CORE_PIDS); - LBPUT("%d: SID=%d zero=%d |",cardNum,sid,needZero); + LBPUT("%s: SID=%d zero=%d |",devId,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()); @@ -1672,10 +2739,10 @@ cEcmHandler *cCam::GetHandler(int sid, bool needZero, bool noshift) if(sidhandler) { if(needZero && sidhandler->CwIndex()!=0 && !noshift) { if(!sidhandler->IsIdle()) - PRINTF(L_CORE_ECM,"%d: shifting cwindex on non-idle handler.",cardNum); + PRINTF(L_CORE_ECM,"%s: shifting cwindex on non-idle handler.",devId); if(zerohandler) { if(!zerohandler->IsIdle()) - PRINTF(L_CORE_ECM,"%d: shifting non-idle zero handler. This shouldn't happen!",cardNum); + PRINTF(L_CORE_ECM,"%s: shifting non-idle zero handler. This shouldn't happen!",devId); zerohandler->ShiftCwIndex(sidhandler->CwIndex()); sidhandler->ShiftCwIndex(0); } @@ -1684,19 +2751,19 @@ cEcmHandler *cCam::GetHandler(int sid, bool needZero, bool noshift) indexMap[sidhandler->CwIndex()]=0; sidhandler->ShiftCwIndex(0); } - else PRINTF(L_CORE_ECM,"%d: zero index not free.",cardNum); + else PRINTF(L_CORE_ECM,"%s: zero index not free.",devId); } if(!needZero && sidhandler->CwIndex()==0 && !noshift) { if(!sidhandler->IsIdle()) - PRINTF(L_CORE_ECM,"%d: shifting cwindex on non-idle handler.",cardNum); + PRINTF(L_CORE_ECM,"%s: shifting cwindex on non-idle handler.",devId); 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); + else PRINTF(L_CORE_ECM,"%s: no free cwindex. Can't free zero index.",devId); } return sidhandler; @@ -1704,7 +2771,7 @@ cEcmHandler *cCam::GetHandler(int sid, bool needZero, bool noshift) if(needZero && zerohandler) { if(!zerohandler->IsIdle()) - PRINTF(L_CORE_ECM,"%d: changing SID on non-idle zero handler. This shouldn't happen!",cardNum); + PRINTF(L_CORE_ECM,"%s: changing SID on non-idle zero handler. This shouldn't happen!",devId); return zerohandler; } @@ -1715,7 +2782,7 @@ cEcmHandler *cCam::GetHandler(int sid, bool needZero, bool noshift) indexMap[idlehandler->CwIndex()]=0; idlehandler->ShiftCwIndex(0); } - else PRINTF(L_CORE_ECM,"%d: zero index not free. (2)",cardNum); + else PRINTF(L_CORE_ECM,"%s: zero index not free. (2)",devId); } if(!needZero && idlehandler->CwIndex()==0 && !noshift) { int idx=GetFreeIndex(); @@ -1724,10 +2791,10 @@ cEcmHandler *cCam::GetHandler(int sid, bool needZero, bool noshift) idlehandler->ShiftCwIndex(idx); indexMap[0]=0; } - else PRINTF(L_CORE_ECM,"%d: no free cwindex. Can't free zero index. (2)",cardNum); + else PRINTF(L_CORE_ECM,"%s: no free cwindex. Can't free zero index. (2)",devId); } if((needZero ^ (idlehandler->CwIndex()==0))) - PRINTF(L_CORE_ECM,"%d: idlehandler index doesn't match needZero",cardNum); + PRINTF(L_CORE_ECM,"%s: idlehandler index doesn't match needZero",devId); return idlehandler; } @@ -1738,15 +2805,15 @@ cEcmHandler *cCam::GetHandler(int sid, bool needZero, bool noshift) indexMap[0]=0; if(idx<0) { idx=0; - PRINTF(L_CORE_ECM,"%d: can't respect !needZero for new handler",cardNum); + PRINTF(L_CORE_ECM,"%s: can't respect !needZero for new handler",devId); } } if(idx<0) { - PRINTF(L_CORE_ECM,"%d: no free cwindex",cardNum); + PRINTF(L_CORE_ECM,"%s: no free cwindex",devId); return 0; } indexMap[idx]=1; - idlehandler=new cEcmHandler(this,cardNum,idx); + idlehandler=new cEcmHandler(this,device,devId,idx); handlerList.Add(idlehandler); return idlehandler; } @@ -1754,7 +2821,204 @@ cEcmHandler *cCam::GetHandler(int sid, bool needZero, bool noshift) void cCam::RemHandler(cEcmHandler *handler) { int idx=handler->CwIndex(); - PRINTF(L_CORE_PIDS,"%d: removing %s on cw index %d",cardNum,handler->Id(),idx); + PRINTF(L_CORE_PIDS,"%s: removing %s on cw index %d",devId,handler->Id(),idx); handlerList.Del(handler); indexMap[idx]=0; } + +// -- cDeCSA ------------------------------------------------------------------- + +#define MAX_STALL_MS 70 + +#define MAX_REL_WAIT 100 // time to wait if key in used on set +#define MAX_KEY_WAIT 500 // time to wait if key not ready on change + +#define FL_EVEN_GOOD 1 +#define FL_ODD_GOOD 2 +#define FL_ACTIVITY 4 + + +cDeCSA::cDeCSA(const char *DevId) +:stall(MAX_STALL_MS) +{ + devId=DevId; + cs=get_suggested_cluster_size(); + PRINTF(L_CORE_CSA,"%s: clustersize=%d rangesize=%d",devId,cs,cs*2+5); + range=MALLOC(unsigned char *,(cs*2+5)); + memset(keys,0,sizeof(keys)); + memset(pidmap,0,sizeof(pidmap)); + ResetState(); +} + +cDeCSA::~cDeCSA() +{ + for(int i=0; iindex; + if(idxparity==(even_odd[idx]&0x40)>>6) { + if(flags[idx] & (ca_descr->parity?FL_ODD_GOOD:FL_EVEN_GOOD)) { + PRINTF(L_CORE_CSA,"%s.%d: %s key in use (%d ms)",devId,idx,ca_descr->parity?"odd":"even",MAX_REL_WAIT); + if(wait.TimedWait(mutex,MAX_REL_WAIT)) PRINTF(L_CORE_CSA,"%s.%d: successfully waited for release",devId,idx); + else PRINTF(L_CORE_CSA,"%s.%d: timed out. setting anyways",devId,idx); + } + else PRINTF(L_CORE_CSA,"%s.%d: late key set...",devId,idx); + } + LDUMP(L_CORE_CSA,ca_descr->cw,8,"%s.%d: %4s key set",devId,idx,ca_descr->parity?"odd":"even"); + if(ca_descr->parity==0) { + set_even_control_word(keys[idx],ca_descr->cw); + if(!CheckNull(ca_descr->cw,8)) flags[idx]|=FL_EVEN_GOOD|FL_ACTIVITY; + else PRINTF(L_CORE_CSA,"%s.%d: zero even CW",devId,idx); + wait.Broadcast(); + } + else { + set_odd_control_word(keys[idx],ca_descr->cw); + if(!CheckNull(ca_descr->cw,8)) flags[idx]|=FL_ODD_GOOD|FL_ACTIVITY; + else PRINTF(L_CORE_CSA,"%s.%d: zero odd CW",devId,idx); + wait.Broadcast(); + } + } + return true; +} + +bool cDeCSA::SetCaPid(ca_pid_t *ca_pid) +{ + cMutexLock lock(&mutex); + if(ca_pid->indexpidpid]=ca_pid->index; + PRINTF(L_CORE_CSA,"%s.%d: set pid %04x",devId,ca_pid->index,ca_pid->pid); + } + return true; +} + +bool cDeCSA::Decrypt(unsigned char *data, int len, bool force) +{ + cMutexLock lock(&mutex); + int r=-2, ccs=0, currIdx=-1; + bool newRange=true; + range[0]=0; + len-=(TS_SIZE-1); + int l; + for(l=0; l=cs) break; + } + else newRange=true; // other index, create hole + } + else { // unencrypted + // nothing, we don't create holes for unencrypted packets + } + } + int scanTS=l/TS_SIZE; + int stallP=ccs*100/scanTS; + + LBSTART(L_CORE_CSAVERB); + LBPUT("%s: %s-%d-%d : %d-%d-%d stall=%d :: ", + devId,data==lastData?"SAME":"MOVE",(len+(TS_SIZE-1))/TS_SIZE,force, + currIdx,ccs,scanTS,stallP); + for(int l=0; l=0 && ccs forced",devId); + force=true; + } + else if(stallP<=10 && scanTS>=cs) { + PRINTF(L_CORE_CSAVERB,"%s: flow factor stall -> forced",devId); + force=true; + } + } + lastData=data; + + if(r>=0) { // we have some range + if(ccs>=cs || force) { + if(GetKeyStruct(currIdx)) { + int n=decrypt_packets(keys[currIdx],range); + PRINTF(L_CORE_CSAVERB,"%s.%d: decrypting ccs=%3d cs=%3d %s -> %3d decrypted",devId,currIdx,ccs,cs,ccs>=cs?"OK ":"INC",n); + if(n>0) { + stall.Set(MAX_STALL_MS); + return true; + } + } + } + else PRINTF(L_CORE_CSAVERB,"%s.%d: incomplete ccs=%3d cs=%3d",devId,currIdx,ccs,cs); + } + return false; +} diff --git a/cam.h b/cam.h index 41ed871..de6b1e4 100644 --- a/cam.h +++ b/cam.h @@ -20,18 +20,24 @@ #ifndef ___CAM_H #define ___CAM_H +#include +#include #include #include "data.h" #include "misc.h" class cChannel; +class cRingBufferLinear; +class cDevice; class cEcmHandler; class cEcmData; class cLogger; class cHookManager; class cLogHook; -class cScDevice; +class cScCamSlot; +class cCiFrame; +class cDeCSA; class cPrg; // ---------------------------------------------------------------- @@ -53,13 +59,61 @@ extern cEcmCache ecmcache; // ---------------------------------------------------------------- +class cCiFrame { +private: + cRingBufferLinear *rb; + unsigned char *mem; + int len, alen, glen; +public: + cCiFrame(void); + ~cCiFrame(); + void SetRb(cRingBufferLinear *Rb) { rb=Rb; } + unsigned char *GetBuff(int l); + void Put(void); + unsigned char *Get(int &l); + void Del(void); + int Avail(void); + }; + +// ---------------------------------------------------------------- + +typedef int caid_t; + +#define MAX_CI_SLOTS 8 +#ifdef VDR_MAXCAID +#define MAX_CI_SLOT_CAIDS VDR_MAXCAID +#else +#define MAX_CI_SLOT_CAIDS 16 +#endif + #define MAX_CW_IDX 16 #define MAX_SPLIT_SID 16 -class cCam : private cMutex { +class cCam : public cCiAdapter, public cSimpleItem { private: - int cardNum; - cScDevice *device; + cDevice *device; + cMutex ciMutex; + const char *devId; + int adapter, frontend; + cRingBufferLinear *rb; + cScCamSlot *slots[MAX_CI_SLOTS]; + cCiFrame frame; + // + cDeCSA *decsa; + int cafd; + cMutex cafdMutex; + bool softcsa, fullts; + // + cTimeMs caidTimer, triggerTimer; + int version[MAX_CI_SLOTS]; + caid_t caids[MAX_CI_SLOTS][MAX_CI_SLOT_CAIDS+1]; + int tcid; + bool rebuildcaids; + // + cTimeMs readTimer, writeTimer; + cTimeMs lastDump; + // + cMutex camMutex; cSimpleList handlerList; cLogger *logger; cHookManager *hookman; @@ -67,17 +121,36 @@ private: int splitSid[MAX_SPLIT_SID+1]; unsigned char indexMap[MAX_CW_IDX], lastCW[MAX_CW_IDX][2*8]; // + void BuildCaids(bool force); cEcmHandler *GetHandler(int sid, bool needZero, bool noshift); void RemHandler(cEcmHandler *handler); int GetFreeIndex(void); void LogStartup(void); +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: - cCam(cScDevice *dev, int CardNum); + cCam(cDevice *Device, int Adapter, int Frontend, const char *DevId, int Cafd, bool SoftCSA, bool FullTS); virtual ~cCam(); + // CI adapter API + int GetCaids(int slot, unsigned short *Caids, int max); + void CaidsChanged(void); + virtual bool SetCaDescr(ca_descr_t *ca_descr, bool initial); + virtual bool SetCaPid(ca_pid_t *ca_pid); + void Stop(void); + void AddPrg(cPrg *prg); + bool HasPrg(int prg); // EcmHandler API void WriteCW(int index, unsigned char *cw, bool force); void SetCWIndex(int pid, int index); void DumpAV7110(void); + bool IsSoftCSA(bool live); + int Adapter(void) { return adapter; } + int Frontend(void) { return frontend; } + // System API void LogEcmStatus(const cEcmInfo *ecm, bool on); void AddHook(cLogHook *hook); bool TriggerHook(int id); @@ -87,14 +160,40 @@ public: void Tune(const cChannel *channel); void PostTune(void); void SetPid(int type, int pid, bool on); - void Stop(void); - void AddPrg(cPrg *prg); - bool HasPrg(int prg); - char *CurrentKeyStr(int num); - // - bool IsSoftCSA(bool live); + char *CurrentKeyStr(int num, const char **id); + bool OwnSlot(const cCamSlot *slot) const; + cDeCSA *DeCSA(void) const { return decsa; } }; void LogStatsDown(void); +// ---------------------------------------------------------------- + +#define MAX_CSA_PIDS 8192 +#define MAX_CSA_IDX 16 + +class cDeCSA { +private: + int cs; + unsigned char **range, *lastData; + unsigned char pidmap[MAX_CSA_PIDS]; + void *keys[MAX_CSA_IDX]; + unsigned int even_odd[MAX_CSA_IDX], flags[MAX_CSA_IDX]; + cMutex mutex; + cCondVar wait; + cTimeMs stall; + bool active; + const char *devId; + // + bool GetKeyStruct(int idx); + void ResetState(void); +public: + cDeCSA(const char *DevId); + ~cDeCSA(); + bool Decrypt(unsigned char *data, int len, bool force); + bool SetDescr(ca_descr_t *ca_descr, bool initial); + bool SetCaPid(ca_pid_t *ca_pid); + void SetActive(bool on); + }; + #endif // ___CAM_H diff --git a/data.c b/data.c index 588b013..4e9f21e 100644 --- a/data.c +++ b/data.c @@ -544,29 +544,28 @@ void cStructLoaders::Purge(void) // -- cPid --------------------------------------------------------------------- -cPid::cPid(int Pid, int Section, int Mask, int Mode) +cPid::cPid(int Pid, int Section, int Mask) { pid=Pid; sct=Section; mask=Mask; - mode=Mode; filter=0; } // -- cPids -------------------------------------------------------------------- -void cPids::AddPid(int Pid, int Section, int Mask, int Mode) +void cPids::AddPid(int Pid, int Section, int Mask) { - if(!HasPid(Pid,Section,Mask,Mode)) { - cPid *pid=new cPid(Pid,Section,Mask,Mode); + if(!HasPid(Pid,Section,Mask)) { + cPid *pid=new cPid(Pid,Section,Mask); Add(pid); } } -bool cPids::HasPid(int Pid, int Section, int Mask, int Mode) +bool cPids::HasPid(int Pid, int Section, int Mask) { for(cPid *pid=First(); pid; pid=Next(pid)) - if(pid->pid==Pid && pid->sct==Section && pid->mask==Mask && pid->mode==Mode) + if(pid->pid==Pid && pid->sct==Section && pid->mask==Mask) return true; return false; } @@ -593,6 +592,7 @@ cEcmInfo::cEcmInfo(const cEcmInfo *e) transponder=e->transponder; rewriterId=e->rewriterId; SetRewriter(); + dvbAdapter=e->dvbAdapter; dvbFrontend=e->dvbFrontend; } cEcmInfo::cEcmInfo(const char *Name, int Pid, int CaId, int ProvId) @@ -617,6 +617,7 @@ void cEcmInfo::Setup(void) prgId=grPrgId=source=transponder=-1; ecm_table=0x80; emmCaId=0; rewriter=0; rewriterId=0; + dvbAdapter=dvbFrontend=-1; } bool cEcmInfo::Compare(const cEcmInfo *e) @@ -625,6 +626,11 @@ bool cEcmInfo::Compare(const cEcmInfo *e) caId==e->caId && ecm_pid==e->ecm_pid && provId==e->provId; } +void cEcmInfo::SetDvb(int DvbAdapter, int DvbFrontend) +{ + dvbAdapter=DvbAdapter; dvbFrontend=DvbFrontend; +} + void cEcmInfo::SetSource(int GrPrgId, int Source, int Transponder) { grPrgId=GrPrgId; prgId=grPrgId%SIDGRP_SHIFT; diff --git a/data.h b/data.h index c93c9d2..191d9f2 100644 --- a/data.h +++ b/data.h @@ -202,18 +202,18 @@ public: class cPid : public cSimpleItem { public: - int pid, sct, mask, mode; + int pid, sct, mask; cPidFilter *filter; // - cPid(int Pid, int Section, int Mask, int Mode); + cPid(int Pid, int Section, int Mask); }; // ---------------------------------------------------------------- class cPids : public cSimpleList { public: - void AddPid(int Pid, int Section, int Mask, int Mode=0); - bool HasPid(int Pid, int Section, int Mask, int Mode=0); + void AddPid(int Pid, int Section, int Mask); + bool HasPid(int Pid, int Section, int Mask); }; // ---------------------------------------------------------------- @@ -237,6 +237,7 @@ public: int prgId, grPrgId, source, transponder; cRewriter *rewriter; int rewriterId; + int dvbAdapter, dvbFrontend; // cEcmInfo(void); cEcmInfo(const cEcmInfo *e); @@ -244,6 +245,7 @@ public: ~cEcmInfo(); virtual cString ToString(bool hide=false) { return ""; } bool Compare(const cEcmInfo *e); + void SetDvb(int DvbAdapter, int DvbFrontend); void SetSource(int GrPrgId, int Source, int Transponder); void SetName(const char *Name); void SetDataIdx(int idx); diff --git a/device.c b/device.c index 2c1a5ec..73e567e 100644 --- a/device.c +++ b/device.c @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -44,1158 +43,6 @@ #include "misc.h" #include "log-core.h" -#define MAX_CI_SLOTS 8 - -#ifdef VDR_MAXCAID -#define MAX_CI_SLOT_CAIDS VDR_MAXCAID -#else -#define MAX_CI_SLOT_CAIDS 16 -#endif - -// -- 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); -} - -cString cCaDescr::ToString(void) -{ - if(!descr) return ""; - char *str=AUTOARRAY(char,len*3+8); - int q=sprintf(str,"%02X",descr[0]); - for(int i=1; ipid,*pid->caDescr.ToString()); -} - -bool cPrg::SimplifyCaDescr(void) -{ -//XXX -PRINTF(L_CORE_PIDS,"SimplyCa entry pidCa=%d",HasPidCaDescr()); -DumpCaDescr(L_CORE_PIDS); -//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()); -DumpCaDescr(L_CORE_PIDS); -//XXX - - return HasPidCaDescr(); -} - -// --- cChannelCaids ----------------------------------------------------------- - -#ifndef SASC - -class 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, bool full); - void HistAdd(unsigned short *hist); - void Dump(int n); - const caid_t *Caids(void) { caids[numcaids]=0; return caids; } - int NumCaids(void) { return numcaids; } - int Source(void) const { return source; } - int Transponder(void) const { return transponder; } - }; - -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(numcaidsSid() && source==channel->Source() && transponder==channel->Transponder(); -} - -void cChannelCaids::Sort(void) -{ - caid_t tmp[MAX_CI_SLOT_CAIDS]; - int c=0xFFFF; - for(int i=0; id && caids[j]0) Sort(); - caids[numcaids]=0; - break; - } -} - -bool cChannelCaids::HasCaid(caid_t caid) -{ - for(int i=0; isource || transponder!=ch->transponder)) return false; - 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 { -private: - int n; -public: - cChannelList(int N); - void Unique(bool full); - void CheckIgnore(void); - int Histo(void); - void Purge(int caid, bool fullch); - }; - -cChannelList::cChannelList(int N) -{ - n=N; -} - -void cChannelList::CheckIgnore(void) -{ - char *cache=MALLOC(char,0x10000); - if(!cache) return; - memset(cache,0,sizeof(char)*0x10000); - int cTotal=0, cHits=0; - for(cChannelCaids *ch=First(); ch; ch=Next(ch)) { - const caid_t *ids=ch->Caids(); - while(*ids) { - int pri=0; - if(overrides.Ignore(ch->Source(),ch->Transponder(),*ids)) - ch->Del(*ids); - else { - char c=cache[*ids]; - if(c==0) cache[*ids]=c=(cSystems::FindIdentBySysId(*ids,false,pri) ? 1 : -1); - else cHits++; - cTotal++; - if(c<0) { - for(cChannelCaids *ch2=Next(ch); ch2; ch2=Next(ch2)) ch2->Del(*ids); - ch->Del(*ids); - } - else ids++; - } - } - } - free(cache); - PRINTF(L_CORE_CAIDS,"%d: after check",n); - for(cChannelCaids *ch=First(); ch; ch=Next(ch)) ch->Dump(n); - PRINTF(L_CORE_CAIDS,"%d: check cache usage: %d requests, %d hits, %d%% hits",n,cTotal,cHits,(cTotal>0)?(cHits*100/cTotal):0); -} - -void cChannelList::Unique(bool full) -{ - for(cChannelCaids *ch1=First(); ch1; ch1=Next(ch1)) { - for(cChannelCaids *ch2=Next(ch1); ch2;) { - if(ch1->Same(ch2,full) || 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 (%d)",n,full); - 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, bool fullch) -{ - for(cChannelCaids *ch=First(); ch;) { - if(!fullch) ch->Del(caid); - if(ch->NumCaids()<=0 || (fullch && 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); - } -} - -// -- cCiFrame ----------------------------------------------------------------- - -#define LEN_OFF 2 - -class cCiFrame { -private: - cRingBufferLinear *rb; - unsigned char *mem; - int len, alen, glen; -public: - cCiFrame(void); - ~cCiFrame(); - void SetRb(cRingBufferLinear *Rb) { rb=Rb; } - unsigned char *GetBuff(int l); - void Put(void); - unsigned char *Get(int &l); - void Del(void); - int Avail(void); - }; - -cCiFrame::cCiFrame(void) -{ - rb=0; mem=0; len=alen=glen=0; -} - -cCiFrame::~cCiFrame() -{ - free(mem); -} - -unsigned char *cCiFrame::GetBuff(int l) -{ - if(!mem || l>alen) { - free(mem); mem=0; alen=0; - mem=MALLOC(unsigned char,l+LEN_OFF); - if(mem) alen=l; - } - len=l; - if(!mem) { - PRINTF(L_GEN_DEBUG,"internal: ci-frame alloc failed"); - return 0; - } - return mem+LEN_OFF; -} - -void cCiFrame::Put(void) -{ - if(rb && mem) { - *((short *)mem)=len; - rb->Put(mem,len+LEN_OFF); - } -} - -unsigned char *cCiFrame::Get(int &l) -{ - if(rb) { - int c; - unsigned char *data=rb->Get(c); - if(data) { - if(c>LEN_OFF) { - int s=*((short *)data); - if(c>=s+LEN_OFF) { - l=glen=s; - return data+LEN_OFF; - } - } - LDUMP(L_GEN_DEBUG,data,c,"internal: ci rb frame sync got=%d avail=%d -",c,rb->Available()); - rb->Clear(); - } - } - return 0; -} - -int cCiFrame::Avail(void) -{ - return rb ? rb->Available() : 0; -} - -void cCiFrame::Del(void) -{ - if(rb && glen) { - rb->Del(glen+LEN_OFF); - glen=0; - } -} - -// -- cScCiAdapter ------------------------------------------------------------- - -#define CAID_TIME 300000 // time between caid scans -#define TRIGGER_TIME 10000 // min. time between caid scan trigger - -#define TDPU_SIZE_INDICATOR 0x80 - -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]; - cCiFrame frame; - // - cTimeMs caidTimer, triggerTimer; - int version[MAX_CI_SLOTS]; - caid_t caids[MAX_CI_SLOTS][MAX_CI_SLOT_CAIDS+1]; - int tcid; - bool rebuildcaids; - // - 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); - void CaidsChanged(void); - }; - -// -- cScCamSlot --------------------------------------------------------------- - -#define SLOT_CAID_CHECK 10000 -#define SLOT_RESET_TIME 600 - -class cScCamSlot : public cCamSlot { -private: - cScCiAdapter *ciadapter; - unsigned short caids[MAX_CI_SLOT_CAIDS+1]; - int slot, cardIndex, version; - cTimeMs checkTimer; - bool reset, doReply; - cTimeMs resetTimer; - eModuleStatus lastStatus; - cRingBufferLinear rb; - cCiFrame frame; - // - int GetLength(const unsigned char * &data); - int LengthSize(int n); - void SetSize(int n, unsigned char * &p); - void CaInfo(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); - cCiFrame *Frame(void) { return &frame; } - }; - -cScCamSlot::cScCamSlot(cScCiAdapter *ca, int CardIndex, int Slot) -:cCamSlot(ca) -,checkTimer(-SLOT_CAID_CHECK-1000) -,rb(KILOBYTE(4),5+LEN_OFF,false,"SC-CI slot answer") -{ - ciadapter=ca; cardIndex=CardIndex; slot=Slot; - version=0; caids[0]=0; doReply=false; lastStatus=msReset; - frame.SetRb(&rb); - Reset(false); -} - -eModuleStatus cScCamSlot::Status(void) -{ - eModuleStatus status; - if(reset) { - status=msReset; - if(resetTimer.TimedOut()) reset=false; - } - else if(caids[0]) status=msReady; - else { - status=msPresent; //msNone; - Check(); - } - if(status!=lastStatus) { - static const char *stext[] = { "none","reset","present","ready" }; - PRINTF(L_CORE_CI,"%d.%d: status '%s'",cardIndex,slot,stext[status]); - lastStatus=status; - } - return status; -} - -bool cScCamSlot::Reset(bool log) -{ - reset=true; resetTimer.Set(SLOT_RESET_TIME); - rb.Clear(); - if(log) PRINTF(L_CORE_CI,"%d.%d: reset",cardIndex,slot); - return true; -} - -bool cScCamSlot::Check(void) -{ - bool res=false; - bool dr=ciadapter->CamSoftCSA() || ScSetup.ConcurrentFF>0; - if(dr!=doReply && !IsDecrypting()) { - PRINTF(L_CORE_CI,"%d.%d: doReply changed, reset triggered",cardIndex,slot); - Reset(false); - doReply=dr; - } - if(checkTimer.TimedOut()) { - if(version!=ciadapter->GetCaids(slot,0,0)) { - version=ciadapter->GetCaids(slot,caids,MAX_CI_SLOT_CAIDS); - PRINTF(L_CORE_CI,"%d.%d: now using CAIDs version %d",cardIndex,slot,version); - res=true; - } - checkTimer.Set(SLOT_CAID_CHECK); - } - return res; -} - -int cScCamSlot::GetLength(const unsigned char * &data) -{ - int len=*data++; - if(len&TDPU_SIZE_INDICATOR) { - int i; - for(i=len&~TDPU_SIZE_INDICATOR, len=0; i>0; i--) len=(len<<8) + *data++; - } - return len; -} - -int cScCamSlot::LengthSize(int n) -{ - return n>8; *p++=n&0xFF; } -} - -void cScCamSlot::CaInfo(int tcid, int cid) -{ - int cn=0; - for(int i=0; caids[i]; i++) cn+=2; - int n=cn+8+LengthSize(cn); - unsigned char *p; - if(!(p=frame.GetBuff(n+1+LengthSize(n)))) return; - *p++=0xa0; - SetSize(n,p); - *p++=tcid; - *p++=0x90; - *p++=0x02; *p++=cid>>8; *p++=cid&0xff; - *p++=0x9f; *p++=0x80; *p++=0x31; // AOT_CA_INFO - SetSize(cn,p); - for(int i=0; caids[i]; i++) { *p++=caids[i]>>8; *p++=caids[i]&0xff; } - frame.Put(); - PRINTF(L_CORE_CI,"%d.%d sending CA info",cardIndex,slot); -} - -void cScCamSlot::Process(const unsigned char *data, int len) -{ - const unsigned char *save=data; - data+=3; - int dlen=GetLength(data); - if(dlen>len-(data-save)) { - PRINTF(L_CORE_CI,"%d.%d TDPU length exceeds data length",cardIndex,slot); - dlen=len-(data-save); - } - int tcid=data[0]; - - if(Check()) CaInfo(tcid,0x01); - - if(dlen<8 || data[1]!=0x90) return; - int cid=(data[3]<<8)+data[4]; - int tag=(data[5]<<16)+(data[6]<<8)+data[7]; - data+=8; - dlen=GetLength(data); - if(dlen>len-(data-save)) { - PRINTF(L_CORE_CI,"%d.%d tag length exceeds data length",cardIndex,slot); - dlen=len-(data-save); - } - switch(tag) { - case 0x9f8030: // AOT_CA_INFO_ENQ - CaInfo(tcid,cid); - break; - - case 0x9f8032: // AOT_CA_PMT - if(dlen>=6) { - int ca_lm=data[0]; - int ci_cmd=-1; - cPrg *prg=new cPrg((data[1]<<8)+data[2],ca_lm==5); - int ilen=(data[4]<<8)+data[5]; - LBSTARTF(L_CORE_CI); - LBPUT("%d.%d CA_PMT decoding len=%x lm=%x prg=%d len=%x",cardIndex,slot,dlen,ca_lm,(data[1]<<8)+data[2],ilen); - data+=6; dlen-=6; - LBPUT("/%x",dlen); - if(ilen>0 && dlen>=ilen) { - ci_cmd=data[0]; - if(ilen>1) - prg->caDescr.Set(&data[1],ilen-1); - LBPUT(" ci_cmd(G)=%02x",ci_cmd); - } - data+=ilen; dlen-=ilen; - while(dlen>=5) { - cPrgPid *pid=new cPrgPid(data[0],(data[1]<<8)+data[2]); - prg->pids.Add(pid); - ilen=(data[3]<<8)+data[4]; - LBPUT(" pid=%d,%x len=%x",data[0],(data[1]<<8)+data[2],ilen); - data+=5; dlen-=5; - LBPUT("/%x",dlen); - if(ilen>0 && dlen>=ilen) { - ci_cmd=data[0]; - if(ilen>1) { - pid->caDescr.Set(&data[1],ilen-1); - prg->SetPidCaDescr(true); - } - LBPUT(" ci_cmd(S)=%x",ci_cmd); - } - data+=ilen; dlen-=ilen; - } - LBEND(); - PRINTF(L_CORE_CI,"%d.%d got CA pmt ciCmd=%d caLm=%d",cardIndex,slot,ci_cmd,ca_lm); - if(doReply && (ci_cmd==0x03 || (ci_cmd==0x01 && ca_lm==0x03))) { - unsigned char *b; - if((b=frame.GetBuff(4+11))) { - b[0]=0xa0; b[2]=tcid; - 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->sid<<8; - b[12]=prg->sid&0xff; - b[13]=0x00; - b[14]=0x81; // CA_ENABLE - b[10]=4; b[1]=4+9; - frame.Put(); - PRINTF(L_CORE_CI,"%d.%d answer to query",cardIndex,slot); - } - } - 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->sid); - ciadapter->CamAddPrg(prg); - } - } - delete prg; - } - break; - } -} - -// -- cScCiAdapter ------------------------------------------------------------- - -cScCiAdapter::cScCiAdapter(cDevice *Device, int CardIndex, cCam *Cam) -{ - device=Device; cardIndex=CardIndex; cam=Cam; - tcid=0; rebuildcaids=false; - memset(version,0,sizeof(version)); - memset(slots,0,sizeof(slots)); - SetDescription("SC-CI adapter on device %d",cardIndex); - rb=new cRingBufferLinear(KILOBYTE(8),6+LEN_OFF,false,"SC-CI adapter read"); - if(rb) { - rb->SetTimeouts(0,CAM_READ_TIMEOUT); - frame.SetRb(rb); -/* - bool spare=true; - for(int i=0; iStop(); -} - -void cScCiAdapter::CamAddPrg(cPrg *prg) -{ - if(cam) cam->AddPrg(prg); -} - -bool cScCiAdapter::CamSoftCSA(void) -{ - return cam && cam->IsSoftCSA(false); -} - -int cScCiAdapter::GetCaids(int slot, unsigned short *Caids, int max) -{ - BuildCaids(false); - cMutexLock lock(&ciMutex); - if(Caids) { - int i; - for(i=0; iGroupSep() && channel->Ca()>=CA_ENCRYPTED_MIN && device->ProvidesTransponder(channel)) { - cChannelCaids *ch=new cChannelCaids(channel); - if(ch) list.Add(ch); - } - } - Channels.Unlock(); - list.Unique(true); - list.CheckIgnore(); - list.Unique(false); - - int n=0, h; - caid_t c[MAX_CI_SLOT_CAIDS+1]; - memset(c,0,sizeof(c)); - do { - if((h=list.Histo())<0) break; - c[n++]=h; - LBSTART(L_CORE_CAIDS); - LBPUT("%d: added %04x caids now",cardIndex,h); for(int i=0; i0); - c[n]=0; - if(n==0) PRINTF(L_CORE_CI,"no active CAIDs"); - else if(list.Count()>0) PRINTF(L_GEN_ERROR,"too many CAIDs. You should ignore some CAIDs."); - - ciMutex.Lock(); - if((version[0]==0 && c[0]!=0) || memcmp(caids[0],c,sizeof(caids[0]))) { - memcpy(caids[0],c,sizeof(caids[0])); - version[0]++; - if(version[0]>0) { - LBSTART(L_CORE_CI); - LBPUT("card %d, slot %d (v=%2d) caids:",cardIndex,0,version[0]); - for(int i=0; caids[0][i]; i++) LBPUT(" %04x",caids[0][i]); - LBEND(); - } - } - ciMutex.Unlock(); - - caidTimer.Set(CAID_TIME); - triggerTimer.Set(TRIGGER_TIME); - rebuildcaids=false; - } -} - -int cScCiAdapter::Read(unsigned char *Buffer, int MaxLength) -{ - cMutexLock lock(&ciMutex); - if(cam && rb && Buffer && MaxLength>0) { - int s; - unsigned char *data=frame.Get(s); - if(data) { - if(s<=MaxLength) memcpy(Buffer,data,s); - else PRINTF(L_GEN_DEBUG,"internal: sc-ci %d rb frame size exceeded %d",cardIndex,s); - frame.Del(); - if(Buffer[2]!=0x80 || LOG(L_CORE_CIFULL)) { - LDUMP(L_CORE_CI,Buffer,s,"%d.%d <-",cardIndex,Buffer[0]); - readTimer.Set(); - } - return s; - } - } - else cCondWait::SleepMs(CAM_READ_TIMEOUT); - if(LOG(L_CORE_CIFULL) && readTimer.Elapsed()>2000) { - PRINTF(L_CORE_CIFULL,"%d: read heartbeat",cardIndex); - readTimer.Set(); - } - return 0; -} - -#define TPDU(data,slot) do { unsigned char *_d=(data); _d[0]=(slot); _d[1]=tcid; } while(0) -#define TAG(data,tag,len) do { unsigned char *_d=(data); _d[0]=(tag); _d[1]=(len); } while(0) -#define SB_TAG(data,sb) do { unsigned char *_d=(data); _d[0]=0x80; _d[1]=0x02; _d[2]=tcid; _d[3]=(sb); } while(0) - -void cScCiAdapter::Write(const unsigned char *buff, int len) -{ - cMutexLock lock(&ciMutex); - if(cam && buff && len>=5) { - struct TPDU *tpdu=(struct TPDU *)buff; - int slot=tpdu->slot; - cCiFrame *slotframe=slots[slot]->Frame(); - if(buff[2]!=0xA0 || buff[3]>0x01 || LOG(L_CORE_CIFULL)) - LDUMP(L_CORE_CI,buff,len,"%d.%d ->",cardIndex,slot); - if(slots[slot]) { - switch(tpdu->tag) { - case 0x81: // T_RCV - { - int s; - unsigned char *d=slotframe->Get(s); - if(d) { - unsigned char *b; - if((b=frame.GetBuff(s+6))) { - TPDU(b,slot); - memcpy(b+2,d,s); - slotframe->Del(); // delete from rb before Avail() - SB_TAG(b+2+s,slotframe->Avail()>0 ? 0x80:0x00); - frame.Put(); - } - else slotframe->Del(); - } - break; - } - case 0x82: // T_CREATE_TC - { - tcid=tpdu->data[0]; - unsigned char *b; - static const unsigned char reqCAS[] = { 0xA0,0x07,0x01,0x91,0x04,0x00,0x03,0x00,0x41 }; - if((b=slotframe->GetBuff(sizeof(reqCAS)))) { - memcpy(b,reqCAS,sizeof(reqCAS)); - b[2]=tcid; - slotframe->Put(); - } - if((b=frame.GetBuff(9))) { - TPDU(b,slot); - TAG(&b[2],0x83,0x01); b[4]=tcid; - SB_TAG(&b[5],slotframe->Avail()>0 ? 0x80:0x00); - frame.Put(); - } - break; - } - case 0xA0: // T_DATA_LAST - { - slots[slot]->Process(buff,len); - unsigned char *b; - if((b=frame.GetBuff(6))) { - TPDU(b,slot); - SB_TAG(&b[2],slotframe->Avail()>0 ? 0x80:0x00); - frame.Put(); - } - break; - } - } - } - } - else PRINTF(L_CORE_CIFULL,"%d: short write (cam=%d buff=%d len=%d)",cardIndex,cam!=0,buff!=0,len); -} - -bool cScCiAdapter::Reset(int Slot) -{ - cMutexLock lock(&ciMutex); - PRINTF(L_CORE_CI,"%d: reset of slot %d requested",cardIndex,Slot); - return slots[Slot] ? slots[Slot]->Reset():false; -} - -eModuleStatus cScCiAdapter::ModuleStatus(int Slot) -{ - cMutexLock lock(&ciMutex); - bool enable=ScSetup.CapCheck(cardIndex); - if(!enable) CamStop(); - return (enable && cam && slots[Slot]) ? slots[Slot]->Status():msNone; -} - -bool cScCiAdapter::Assign(cDevice *Device, bool Query) -{ - return Device ? (Device==device) : true; -} - -// -- cDeCSA ------------------------------------------------------------------- - -#define MAX_CSA_PIDS 8192 -#define MAX_CSA_IDX 16 -#define MAX_STALL_MS 70 - -#define MAX_REL_WAIT 100 // time to wait if key in used on set -#define MAX_KEY_WAIT 500 // time to wait if key not ready on change - -#define FL_EVEN_GOOD 1 -#define FL_ODD_GOOD 2 -#define FL_ACTIVITY 4 - -class cDeCSA { -private: - int cs; - unsigned char **range, *lastData; - unsigned char pidmap[MAX_CSA_PIDS]; - void *keys[MAX_CSA_IDX]; - unsigned int even_odd[MAX_CSA_IDX], flags[MAX_CSA_IDX]; - cMutex mutex; - cCondVar wait; - cTimeMs stall; - bool active; - int cardindex; - // - bool GetKeyStruct(int idx); - void ResetState(void); -public: - cDeCSA(int CardIndex); - ~cDeCSA(); - bool Decrypt(unsigned char *data, int len, bool force); - bool SetDescr(ca_descr_t *ca_descr, bool initial); - bool SetCaPid(ca_pid_t *ca_pid); - void SetActive(bool on); - }; - -cDeCSA::cDeCSA(int CardIndex) -:stall(MAX_STALL_MS) -{ - cardindex=CardIndex; - cs=get_suggested_cluster_size(); - PRINTF(L_CORE_CSA,"%d: clustersize=%d rangesize=%d",cardindex,cs,cs*2+5); - range=MALLOC(unsigned char *,(cs*2+5)); - memset(keys,0,sizeof(keys)); - memset(pidmap,0,sizeof(pidmap)); - ResetState(); -} - -cDeCSA::~cDeCSA() -{ - for(int i=0; iindex; - if(idxparity==(even_odd[idx]&0x40)>>6) { - if(flags[idx] & (ca_descr->parity?FL_ODD_GOOD:FL_EVEN_GOOD)) { - PRINTF(L_CORE_CSA,"%d.%d: %s key in use (%d ms)",cardindex,idx,ca_descr->parity?"odd":"even",MAX_REL_WAIT); - if(wait.TimedWait(mutex,MAX_REL_WAIT)) PRINTF(L_CORE_CSA,"%d.%d: successfully waited for release",cardindex,idx); - else PRINTF(L_CORE_CSA,"%d.%d: timed out. setting anyways",cardindex,idx); - } - else PRINTF(L_CORE_CSA,"%d.%d: late key set...",cardindex,idx); - } - LDUMP(L_CORE_CSA,ca_descr->cw,8,"%d.%d: %4s key set",cardindex,idx,ca_descr->parity?"odd":"even"); - if(ca_descr->parity==0) { - set_even_control_word(keys[idx],ca_descr->cw); - if(!CheckNull(ca_descr->cw,8)) flags[idx]|=FL_EVEN_GOOD|FL_ACTIVITY; - else PRINTF(L_CORE_CSA,"%d.%d: zero even CW",cardindex,idx); - wait.Broadcast(); - } - else { - set_odd_control_word(keys[idx],ca_descr->cw); - if(!CheckNull(ca_descr->cw,8)) flags[idx]|=FL_ODD_GOOD|FL_ACTIVITY; - else PRINTF(L_CORE_CSA,"%d.%d: zero odd CW",cardindex,idx); - wait.Broadcast(); - } - } - return true; -} - -bool cDeCSA::SetCaPid(ca_pid_t *ca_pid) -{ - cMutexLock lock(&mutex); - if(ca_pid->indexpidpid]=ca_pid->index; - PRINTF(L_CORE_CSA,"%d.%d: set pid %04x",cardindex,ca_pid->index,ca_pid->pid); - } - return true; -} - -bool cDeCSA::Decrypt(unsigned char *data, int len, bool force) -{ - cMutexLock lock(&mutex); - int r=-2, ccs=0, currIdx=-1; - bool newRange=true; - range[0]=0; - len-=(TS_SIZE-1); - int l; - for(l=0; l=cs) break; - } - else newRange=true; // other index, create hole - } - else { // unencrypted - // nothing, we don't create holes for unencrypted packets - } - } - int scanTS=l/TS_SIZE; - int stallP=ccs*100/scanTS; - - LBSTART(L_CORE_CSAVERB); - LBPUT("%d: %s-%d-%d : %d-%d-%d stall=%d :: ", - cardindex,data==lastData?"SAME":"MOVE",(len+(TS_SIZE-1))/TS_SIZE,force, - currIdx,ccs,scanTS,stallP); - for(int l=0; l=0 && ccs forced",cardindex); - force=true; - } - else if(stallP<=10 && scanTS>=cs) { - PRINTF(L_CORE_CSAVERB,"%d: flow factor stall -> forced",cardindex); - force=true; - } - } - lastData=data; - - if(r>=0) { // we have some range - if(ccs>=cs || force) { - if(GetKeyStruct(currIdx)) { - int n=decrypt_packets(keys[currIdx],range); - PRINTF(L_CORE_CSAVERB,"%d.%d: decrypting ccs=%3d cs=%3d %s -> %3d decrypted",cardindex,currIdx,ccs,cs,ccs>=cs?"OK ":"INC",n); - if(n>0) { - stall.Set(MAX_STALL_MS); - return true; - } - } - } - else PRINTF(L_CORE_CSAVERB,"%d.%d: incomplete ccs=%3d cs=%3d",cardindex,currIdx,ccs,cs); - } - return false; -} - // -- cDeCsaTSBuffer ----------------------------------------------------------- class cDeCsaTSBuffer : public cThread { @@ -1290,8 +137,6 @@ uchar *cDeCsaTSBuffer::Get(void) return NULL; } -#endif //SASC - // --- cScDeviceProbe ---------------------------------------------------------- #define DEV_DVB_ADAPTER "/dev/dvb/adapter" @@ -1358,8 +203,10 @@ static int *vdr_nci=0, *vdr_ud=0, vdr_save_ud; void cScDevices::OnPluginLoad(void) { #if APIVERSNUM >= 10711 + PRINTF(L_GEN_DEBUG,"using new 1.7.11+ capture code"); cScDeviceProbe::Install(); #else + PRINTF(L_GEN_DEBUG,"using old pre1.7.11 capture code"); /* This is an extremly ugly hack to access VDRs device scan parameters, which are protected in this context. Heavily dependant on the actual symbol names @@ -1490,15 +337,17 @@ cScDevice::cScDevice(int Adapter, int Frontend, int cafd) :cDvbDevice(Adapter) #endif { -#ifndef SASC - decsa=0; tsBuffer=0; cam=0; fullts=false; - ciadapter=0; hwciadapter=0; + tsBuffer=0; softcsa=fullts=false; + cam=0; hwciadapter=0; fd_ca=cafd; fd_ca2=dup(fd_ca); fd_dvr=-1; - softcsa=(fd_ca<0); -#else - softcsa=fullts=false; +#ifdef SASC cam=new cCam(this,Adapter); #endif // !SASC +#if APIVERSNUM >= 10711 + snprintf(devId,sizeof(devId),"%d/%d",Adapter,FrontEnd); +#else + snprintf(devId,sizeof(devId),"%d",Adapter); +#endif } cScDevice::~cScDevice() @@ -1507,7 +356,6 @@ cScDevice::~cScDevice() DetachAllReceivers(); Cancel(3); EarlyShutdown(); - delete decsa; if(fd_ca>=0) close(fd_ca); if(fd_ca2>=0) close(fd_ca2); #else @@ -1520,10 +368,8 @@ cScDevice::~cScDevice() void cScDevice::EarlyShutdown(void) { SetCamSlot(0); - delete ciadapter; ciadapter=0; - delete hwciadapter; hwciadapter=0; - if(cam) cam->Stop(); delete cam; cam=0; + delete hwciadapter; hwciadapter=0; } void cScDevice::LateInit(void) @@ -1531,35 +377,33 @@ void cScDevice::LateInit(void) int n=CardIndex(); if(DeviceNumber()!=n) PRINTF(L_GEN_ERROR,"CardIndex - DeviceNumber mismatch! Put SC plugin first on VDR commandline!"); + softcsa=(fd_ca<0); if(softcsa) { - if(HasDecoder()) PRINTF(L_GEN_ERROR,"Card %d is a full-featured card but no ca device found!",n); + if(HasDecoder()) PRINTF(L_GEN_ERROR,"Card %s is a full-featured card but no ca device found!",devId); } else if(cScDevices::ForceBudget(n)) { - PRINTF(L_GEN_INFO,"Budget mode forced on card %d",n); + PRINTF(L_GEN_INFO,"Budget mode forced on card %s",devId); softcsa=true; } - - if(fd_ca2>=0) hwciadapter=cDvbCiAdapter::CreateCiAdapter(this,fd_ca2); - cam=new cCam(this,n); - ciadapter=new cScCiAdapter(this,n,cam); if(softcsa) { - decsa=new cDeCSA(n); if(IsPrimaryDevice() && HasDecoder()) { - PRINTF(L_GEN_INFO,"Enabling hybrid full-ts mode on card %d",n); + PRINTF(L_GEN_INFO,"Enabling hybrid full-ts mode on card %s",devId); fullts=true; } - else PRINTF(L_GEN_INFO,"Using software decryption on card %d",n); + else PRINTF(L_GEN_INFO,"Using software decryption on card %s",devId); } + if(fd_ca2>=0) hwciadapter=cDvbCiAdapter::CreateCiAdapter(this,fd_ca2); + cam=new cCam(this,DVB_DEV_SPEC,devId,fd_ca,softcsa,fullts); } bool cScDevice::HasCi(void) { - return ciadapter || hwciadapter; + return cam || hwciadapter; } bool cScDevice::Ready(void) { - return (ciadapter ? ciadapter->Ready():true) && + return (cam ? cam->Ready():true) && (hwciadapter ? hwciadapter->Ready():true); } @@ -1582,7 +426,7 @@ bool cScDevice::SetChannelDevice(const cChannel *Channel, bool LiveView) bool cScDevice::ScActive(void) { - return dynamic_cast(CamSlot())!=0; + return cam && cam->OwnSlot(CamSlot()); } bool cScDevice::OpenDvr(void) @@ -1590,6 +434,7 @@ bool cScDevice::OpenDvr(void) CloseDvr(); fd_dvr=cScDevices::DvbOpen(DEV_DVB_DVR,DVB_DEV_SPEC,O_RDONLY|O_NONBLOCK,true); if(fd_dvr>=0) { + cDeCSA *decsa=cam ? cam->DeCSA() : 0; tsMutex.Lock(); tsBuffer=new cDeCsaTSBuffer(fd_dvr,MEGABYTE(ScSetup.DeCsaTsBuffSize),CardIndex()+1,decsa,ScActive()); tsMutex.Unlock(); @@ -1612,126 +457,3 @@ bool cScDevice::GetTSPacket(uchar *&Data) } #endif // !SASC - -bool cScDevice::SoftCSA(bool live) -{ - return softcsa && (!fullts || !live); -} - -void cScDevice::CaidsChanged(void) -{ -#ifndef SASC - if(ciadapter) ciadapter->CaidsChanged(); - PRINTF(L_CORE_CAIDS,"caid list rebuild triggered"); -#endif // !SASC -} - -bool cScDevice::SetCaDescr(ca_descr_t *ca_descr, bool initial) -{ -#ifndef SASC - if(!softcsa || (fullts && ca_descr->index==0)) { - cMutexLock lock(&cafdMutex); - return ioctl(fd_ca,CA_SET_DESCR,ca_descr)>=0; - } - else if(decsa) return decsa->SetDescr(ca_descr,initial); -#endif // !SASC - return false; -} - -bool cScDevice::SetCaPid(ca_pid_t *ca_pid) -{ -#ifndef SASC - if(!softcsa || (fullts && ca_pid->index==0)) { - cMutexLock lock(&cafdMutex); - return ioctl(fd_ca,CA_SET_PID,ca_pid)>=0; - } - else if(decsa) return decsa->SetCaPid(ca_pid); -#endif // !SASC - return false; -} - -int cScDevice::FilterHandle(void) -{ - return cScDevices::DvbOpen(DEV_DVB_DEMUX,DVB_DEV_SPEC,O_RDWR|O_NONBLOCK); -} - -#ifndef SASC -static unsigned int av7110_read(int fd, unsigned int addr) -{ - ca_pid_t arg; - arg.pid=addr; - ioctl(fd,CA_GET_MSG,&arg); - return arg.index; -} -#endif // !SASC - -#if 0 -static void av7110_write(int fd, unsigned int addr, unsigned int val) -{ - ca_pid_t arg; - arg.pid=addr; - arg.index=val; - ioctl(fd,CA_SEND_MSG,&arg); -} -#endif - -void cScDevice::DumpAV7110(void) -{ -#ifndef SASC - if(LOG(L_CORE_AV7110)) { -#define CODEBASE (0x2e000404+0x1ce00) - cMutexLock lock(&cafdMutex); - if(HasDecoder() && lastDump.Elapsed()>20000) { - lastDump.Set(); - static unsigned int handles=0, hw_handles=0; - static const unsigned int code[] = { - 0xb5100040,0x4a095a12,0x48094282,0xd00b4b09,0x20000044, - 0x5b1c4294,0xd0033001,0x281cdbf8,0xe001f7fe,0xfd14bc10 - }; - static const unsigned int mask[] = { - 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff, - 0xffffffff,0xffffffff,0xffffffff,0xfffff800,0xf800ffff - }; - if(!handles) { - handles=1; - PRINTF(L_CORE_AV7110,"searching handle tables"); - for(int i=0; i<0x2000; i+=4) { - int j; - for(j=0; j<20; j+=4) { - int r=av7110_read(fd_ca,CODEBASE+i+j); - if((r&mask[j/4])!=(code[j/4]&mask[j/4])) break; - } - if(j==20) { - handles=av7110_read(fd_ca,CODEBASE+i+44); - hw_handles=av7110_read(fd_ca,CODEBASE+i+52); - PRINTF(L_CORE_AV7110,"found handles=%08x hw_handles=%08x at 0x%08x",handles,hw_handles,CODEBASE+i); - if((handles>>16)!=0x2e08 || (hw_handles>>16)!=0x2e08) { - PRINTF(L_CORE_AV7110,"seems to be invalid"); - } - break; - } - } - } - - unsigned int hdl=0, hwhdl=0; - PRINTF(L_CORE_AV7110," : 64000080 64000400"); - for(int i=0; i<=31; i++) { - unsigned int off80 =av7110_read(fd_ca,0x64000080+i*4); - unsigned int off400=av7110_read(fd_ca,0x64000400+i*8); - LBSTART(L_CORE_AV7110); - LBPUT("handle %2d: %08x %08x %s pid=%04x idx=%d", - i,off80,off400,off80&0x2000?"ACT":"---",off80&0x1fff,(off400&0x1e)>>1); - if(handles>1 && i<=27) { - if((i&1)==0) { - hdl=av7110_read(fd_ca,handles+i*2); - hwhdl=av7110_read(fd_ca,hw_handles+i*2); - } - unsigned int s=((~i)&1)<<4; - LBPUT(" | %02d hdl=%04x hwfilt=%04x",i,(hdl>>s)&0xffff,(hwhdl>>s)&0xffff); - } - LBEND(); - } - } - } -#endif // !SASC -} diff --git a/device.h b/device.h index 5ad83f9..737f1f9 100644 --- a/device.h +++ b/device.h @@ -20,12 +20,8 @@ #ifndef ___DEVICE_H #define ___DEVICE_H -#include #include #include -#include "misc.h" - -typedef int caid_t; class cCam; class cDeCSA; @@ -34,60 +30,6 @@ class cScCiAdapter; // ---------------------------------------------------------------- -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); - cString ToString(void); - }; - -// ---------------------------------------------------------------- - -class cPrgPid : public cSimpleItem { -private: - bool proc; -public: - int type, pid; - cCaDescr caDescr; - // - cPrgPid(int Type, int Pid) { type=Type; pid=Pid; proc=false; } - bool Proc(void) const { return proc; } - void Proc(bool is) { proc=is; }; - }; - -// ---------------------------------------------------------------- - -class cPrg : public cSimpleItem { -private: - bool isUpdate, pidCaDescr; - // - void Setup(void); -public: - int sid, source, transponder; - cSimpleList pids; - cCaDescr caDescr; - // - 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); - void DumpCaDescr(int c); - }; - -// ---------------------------------------------------------------- - class cScDevices : public cDvbDevice { private: static int budget; @@ -113,16 +55,13 @@ public: class cScDevice : public cDvbDevice { friend class cScDevices; private: - cDeCSA *decsa; cDeCsaTSBuffer *tsBuffer; cMutex tsMutex; - cScCiAdapter *ciadapter; - cCiAdapter *hwciadapter; cCam *cam; + cCiAdapter *hwciadapter; int fd_dvr, fd_ca, fd_ca2; bool softcsa, fullts; - cMutex cafdMutex; - cTimeMs lastDump; + char devId[8]; // #ifndef SASC void LateInit(void); @@ -145,13 +84,6 @@ public: #ifndef SASC virtual bool HasCi(void); #endif //SASC - virtual bool SetCaDescr(ca_descr_t *ca_descr, bool initial); - virtual bool SetCaPid(ca_pid_t *ca_pid); - int FilterHandle(void); - void DumpAV7110(void); - cCam *Cam(void) { return cam; } - bool SoftCSA(bool live); - void CaidsChanged(void); }; #endif // ___DEVICE_H diff --git a/filter.c b/filter.c index fd69536..c124774 100644 --- a/filter.c +++ b/filter.c @@ -27,45 +27,32 @@ #include +#include #include #include "filter.h" -#include "sc.h" #include "misc.h" #include "log-core.h" // -- cPidFilter ------------------------------------------------------------------ -cPidFilter::cPidFilter(const char *Id, int Num, int DvbNum, unsigned int IdleTime) +cPidFilter::cPidFilter(const char *Id, int Num, cDevice *Device, unsigned int IdleTime) { - dvbNum=DvbNum; + device=Device; idleTime=IdleTime; - id=0; fd=-1; active=false; forceRun=false; userData=0; + id=0; fd=-1; forceRun=false; userData=0; id=bprintf("%s/%d",Id,Num); - PRINTF(L_CORE_ACTION,"new filter '%s' on card %d (%d ms)",id,dvbNum,idleTime); + PRINTF(L_CORE_ACTION,"new filter '%s' (%d ms)",id,idleTime); } cPidFilter::~cPidFilter() { cMutexLock lock(this); - if(fd>=0) { - Stop(); - close(fd); - } - PRINTF(L_CORE_ACTION,"filter '%s' on card %d removed",id,dvbNum); + Stop(); + PRINTF(L_CORE_ACTION,"filter '%s' removed",id); free(id); } -bool cPidFilter::Open(void) -{ - cMutexLock lock(this); - if(fd<0) { - fd=cSoftCAM::FilterHandle(dvbNum); - if(fd>=0) return true; - } - return false; -} - void cPidFilter::Flush(void) { cMutexLock lock(this); @@ -75,28 +62,17 @@ void cPidFilter::Flush(void) } } -void cPidFilter::Start(int Pid, int Section, int Mask, int Mode, bool Crc) +void cPidFilter::Start(int Pid, int Section, int Mask) { cMutexLock lock(this); + Stop(); + fd=device->OpenFilter(Pid,Section,Mask); if(fd>=0) { - Stop(); - struct dmx_sct_filter_params FilterParams; - memset(&FilterParams,0,sizeof(FilterParams)); - FilterParams.filter.filter[0]=Section; - FilterParams.filter.mask[0]=Mask; - FilterParams.filter.mode[0]=Mode; - FilterParams.flags=DMX_IMMEDIATE_START; - if(Crc) FilterParams.flags|=DMX_CHECK_CRC; - FilterParams.pid=Pid; - if(ioctl(fd,DMX_SET_FILTER,&FilterParams)<0) { - PRINTF(L_GEN_ERROR,"filter '%s': DMX_SET_FILTER failed: %s",id,strerror(errno)); - return; - } pid=Pid; - active=true; LBSTART(L_CORE_ACTION); - LBPUT("filter '%s' -> pid=0x%04x sct=0x%02x/0x%02x/0x%02x crc=%d matching",id,Pid,Section,Mask,Mode,Crc); + LBPUT("filter '%s' -> pid=0x%04x sct=0x%02x/0x%02x matching",id,Pid,Section,Mask); + int Mode=0; int mam =Mask & (~Mode); int manm=Mask & ~(~Mode); for(int i=0; i<256; i++) { @@ -112,10 +88,7 @@ void cPidFilter::Start(int Pid, int Section, int Mask, int Mode, bool Crc) void cPidFilter::Stop(void) { cMutexLock lock(this); - if(fd>=0) { - CHECK(ioctl(fd,DMX_STOP)); - active=false; - } + if(fd>=0) { device->CloseFilter(fd); fd=-1; } } void cPidFilter::SetBuffSize(int BuffSize) @@ -144,15 +117,15 @@ void cPidFilter::Wakeup(void) int cPidFilter::Pid(void) { - return active ? pid : -1; + return Active() ? pid : -1; } // -- cAction ------------------------------------------------------------------ -cAction::cAction(const char *Id, int DvbNum) +cAction::cAction(const char *Id, cDevice *Device, const char *DevId) { - id=bprintf("%s %d",Id,DvbNum); - dvbNum=DvbNum; + device=Device; devId=DevId; + id=bprintf("%s %s",Id,DevId); unique=0; pri=-1; SetDescription("%s filter",id); } @@ -165,27 +138,24 @@ cAction::~cAction() free(id); } -cPidFilter *cAction::CreateFilter(const char *Id, int Num, int DvbNum, int IdleTime) +cPidFilter *cAction::CreateFilter(int Num, int IdleTime) { - return new cPidFilter(Id,Num,DvbNum,IdleTime); + return new cPidFilter(id,Num,device,IdleTime); } cPidFilter *cAction::NewFilter(int IdleTime) { Lock(); - cPidFilter *filter=CreateFilter(id,unique++,dvbNum,IdleTime); - if(filter && filter->Open()) { + cPidFilter *filter=CreateFilter(unique++,IdleTime); + if(filter) { if(!Active()) { Start(); PRINTF(L_CORE_ACTION,"%s: started",id); } filters.Add(filter); } - else { - PRINTF(L_CORE_ACTION,"%s: filter '%s' failed to open",id,filter?filter->id:"XxX"); - delete filter; - filter=0; - } + else + PRINTF(L_CORE_ACTION,"%s: failed to create filter",id); Unlock(); return filter; } @@ -238,12 +208,13 @@ void cAction::Action(void) } int num=0; cPidFilter *filter; - for(filter=filters.First(); filter; filter=filters.Next(filter)) { - memset(&pfd[num],0,sizeof(struct pollfd)); - pfd[num].fd=filter->fd; - pfd[num].events=POLLIN; - num++; - } + for(filter=filters.First(); filter; filter=filters.Next(filter)) + if(filter->Active()) { + memset(&pfd[num],0,sizeof(struct pollfd)); + pfd[num].fd=filter->fd; + pfd[num].events=POLLIN; + num++; + } Unlock(); // now poll for data @@ -261,7 +232,10 @@ void cAction::Action(void) unsigned char buff[MAX_SECT_SIZE]; int n=read(filter->fd,buff,sizeof(buff)); if(n<0 && errno!=EAGAIN) { - if(errno==EOVERFLOW) PRINTF(L_GEN_ERROR,"action %s read: Buffer overflow",filter->id); + if(errno==EOVERFLOW) { + filter->Flush(); + //PRINTF(L_GEN_ERROR,"action %s read: Buffer overflow",filter->id); + } else PRINTF(L_GEN_ERROR,"action %s read: %s",filter->id,strerror(errno)); } if(n>0) { diff --git a/filter.h b/filter.h index f93c671..329a29c 100644 --- a/filter.h +++ b/filter.h @@ -23,6 +23,7 @@ #include #include "misc.h" +class cDevice; class cPidFilter; // ---------------------------------------------------------------- @@ -31,13 +32,16 @@ class cPidFilter; class cAction : protected cThread { private: - char *id; - int dvbNum, unique, pri; + const char *devId; + int unique, pri; cSimpleList filters; protected: + cDevice *device; + char *id; + // virtual void Process(cPidFilter *filter, unsigned char *data, int len)=0; virtual void Action(void); - virtual cPidFilter *CreateFilter(const char *Id, int Num, int DvbNum, int IdleTime); + virtual cPidFilter *CreateFilter(int Num, int IdleTime); // cPidFilter *NewFilter(int IdleTime); cPidFilter *IdleFilter(void); @@ -45,7 +49,7 @@ protected: void DelAllFilter(void); void Priority(int Pri); public: - cAction(const char *Id, int DvbNum); + cAction(const char *Id, cDevice *Device, const char *DevId); virtual ~cAction(); }; @@ -54,30 +58,27 @@ public: class cPidFilter : public cSimpleItem, private cMutex { friend class cAction; private: - int dvbNum; + cDevice *device; unsigned int idleTime; cTimeMs lastTime; bool forceRun; - // - bool Open(void); protected: char *id; int fd; int pid; - bool active; public: void *userData; // - cPidFilter(const char *Id, int Num, int DvbNum, unsigned int IdleTime); + cPidFilter(const char *Id, int Num, cDevice *Device, unsigned int IdleTime); virtual ~cPidFilter(); void Flush(void); - virtual void Start(int Pid, int Section, int Mask, int Mode, bool Crc); + virtual void Start(int Pid, int Section, int Mask); void Stop(void); - void Wakeup(void); void SetBuffSize(int BuffSize); + void Wakeup(void); int SetIdleTime(unsigned int IdleTime); int Pid(void); - bool Active(void) { return active; } + bool Active(void) { return fd>=0; } }; #endif //___FILTER_H diff --git a/global.h b/global.h new file mode 100644 index 0000000..a2defce --- /dev/null +++ b/global.h @@ -0,0 +1,33 @@ +/* + * Softcam plugin to VDR (C++) + * + * This code is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + */ + +#ifndef ___GLOBAL_H +#define ___GLOBAL_H + +// ---------------------------------------------------------------- + +class cGlobal { +public: + static bool Active(bool log); + static void HouseKeeping(void); + static char *CurrKeyStr(int cardindex, int num, const char **id); + static void CaidsChanged(void); + }; + +#endif // ___GLOBAL_H diff --git a/override.c b/override.c index d4e8743..2619385 100644 --- a/override.c +++ b/override.c @@ -24,7 +24,7 @@ #include #include "override.h" -#include "sc.h" +#include "global.h" #include "misc.h" #include "log-core.h" @@ -563,7 +563,7 @@ void cOverrides::PreLoad(void) void cOverrides::PostLoad(void) { - if(caidTrigger) cSoftCAM::CaidsChanged(); + if(caidTrigger) cGlobal::CaidsChanged(); } cOverride *cOverrides::ParseLine(char *line) diff --git a/po/de_DE.po b/po/de_DE.po index 48bf38c..994964a 100644 --- a/po/de_DE.po +++ b/po/de_DE.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.5.9\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-12-12 13:24+0100\n" +"POT-Creation-Date: 2011-08-06 20:19+0200\n" "PO-Revision-Date: 2007-08-27 12:45+0200\n" "Last-Translator: somebody\n" "Language-Team: somebody\n" @@ -14,6 +14,9 @@ msgstr "" "Content-Type: text/plain; charset=ISO-8859-15\n" "Content-Transfer-Encoding: 8bit\n" +msgid "(none)" +msgstr "(keiner)" + msgid "Key update" msgstr "Key Update" @@ -106,9 +109,6 @@ msgstr "Dateien wirklich neu laden?" msgid "Active! Can't reload files now" msgstr "Aktiv! Kann Dateien jetzt nicht neu laden" -msgid "(none)" -msgstr "(keiner)" - msgid "active CAIDs" msgstr "aktive CAIDs" diff --git a/po/fi_FI.po b/po/fi_FI.po index 16f4ad5..e740907 100644 --- a/po/fi_FI.po +++ b/po/fi_FI.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.5.9\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-12-12 13:24+0100\n" +"POT-Creation-Date: 2011-08-06 20:19+0200\n" "PO-Revision-Date: 2008-11-19 13:45+0200\n" "Last-Translator: somebody\n" "Language-Team: somebody\n" @@ -14,6 +14,9 @@ msgstr "" "Content-Type: text/plain; charset=ISO-8859-15\n" "Content-Transfer-Encoding: 8bit\n" +msgid "(none)" +msgstr "(ei)" + msgid "Key update" msgstr "Avaimen päivitys" @@ -106,9 +109,6 @@ msgstr "Ladataanko avaintiedostot uudelleen?" msgid "Active! Can't reload files now" msgstr "Aktiivinen! Uudelleen lataus ei onnistu" -msgid "(none)" -msgstr "(ei)" - msgid "active CAIDs" msgstr "aktiiviset CAID:t" diff --git a/po/fr_FR.po b/po/fr_FR.po index 34ba344..c2a10e1 100644 --- a/po/fr_FR.po +++ b/po/fr_FR.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.5.9\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-12-12 13:24+0100\n" +"POT-Creation-Date: 2011-08-06 20:19+0200\n" "PO-Revision-Date: 2007-08-27 12:45+0200\n" "Last-Translator: somebody\n" "Language-Team: somebody\n" @@ -14,6 +14,9 @@ msgstr "" "Content-Type: text/plain; charset=ISO-8859-1\n" "Content-Transfer-Encoding: 8bit\n" +msgid "(none)" +msgstr "(aucune)" + msgid "Key update" msgstr "Mise à jour des clés" @@ -106,9 +109,6 @@ msgstr "Recharger les fichiers?" msgid "Active! Can't reload files now" msgstr "Actif! Impossible de recharger les fichiers" -msgid "(none)" -msgstr "(aucune)" - msgid "active CAIDs" msgstr "CAIDs actifs" diff --git a/po/hu_HU.po b/po/hu_HU.po index 269aed9..d7ff80b 100644 --- a/po/hu_HU.po +++ b/po/hu_HU.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.5.11\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-12-12 13:24+0100\n" +"POT-Creation-Date: 2011-08-06 20:19+0200\n" "PO-Revision-Date: 2009-05-17 11:09+0800\n" "Last-Translator: jv\n" "Language-Team: somebody\n" @@ -14,6 +14,9 @@ msgstr "" "Content-Type: text/plain; charset=ISO-8859-2\n" "Content-Transfer-Encoding: 8bit\n" +msgid "(none)" +msgstr "(nincs)" + msgid "Key update" msgstr "" @@ -106,9 +109,6 @@ msgstr "Biztos, hogy msgid "Active! Can't reload files now" msgstr "SC aktív! Nem tud újraolvasni." -msgid "(none)" -msgstr "(nincs)" - msgid "active CAIDs" msgstr "aktív CAIDok" diff --git a/po/it_IT.po b/po/it_IT.po index 5e8e1ce..2f5d3c4 100644 --- a/po/it_IT.po +++ b/po/it_IT.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.5.9\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-12-12 13:24+0100\n" +"POT-Creation-Date: 2011-08-06 20:19+0200\n" "PO-Revision-Date: 2008-11-19 12:23+0200\n" "Last-Translator: somebody\n" "Language-Team: somebody\n" @@ -14,6 +14,9 @@ msgstr "" "Content-Type: text/plain; charset=ISO-8859-15\n" "Content-Transfer-Encoding: 8bit\n" +msgid "(none)" +msgstr "(nessuna)" + msgid "Key update" msgstr "Aggiornamento chiavi" @@ -106,9 +109,6 @@ msgstr "Ricaricare il file delle chiavi?" msgid "Active! Can't reload files now" msgstr "Chiave in uso! Impossibile ricaricare adesso" -msgid "(none)" -msgstr "(nessuna)" - msgid "active CAIDs" msgstr "CAIDs attivi" diff --git a/po/lt_LT.po b/po/lt_LT.po index ff0fcb9..5723256 100644 --- a/po/lt_LT.po +++ b/po/lt_LT.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.7.10\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-12-12 13:24+0100\n" +"POT-Creation-Date: 2011-08-06 20:19+0200\n" "PO-Revision-Date: 2007-08-27 12:45+0200\n" "Last-Translator: somebody\n" "Language-Team: somebody\n" @@ -14,6 +14,9 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +msgid "(none)" +msgstr "(nėra)" + msgid "Key update" msgstr "Raktų atnaujinimas" @@ -106,9 +109,6 @@ msgstr "Tikrai perkrauti failus?" msgid "Active! Can't reload files now" msgstr "Servisas aktyvus! Dabar negali perkrauti failų" -msgid "(none)" -msgstr "(nėra)" - msgid "active CAIDs" msgstr "aktyvÅ«s CAIDai" diff --git a/po/nl_NL.po b/po/nl_NL.po index 023df14..76709a0 100644 --- a/po/nl_NL.po +++ b/po/nl_NL.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.5.9\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-12-12 13:24+0100\n" +"POT-Creation-Date: 2011-08-06 20:19+0200\n" "PO-Revision-Date: 2007-08-27 12:45+0200\n" "Last-Translator: somebody\n" "Language-Team: somebody\n" @@ -14,6 +14,9 @@ msgstr "" "Content-Type: text/plain; charset=ISO-8859-15\n" "Content-Transfer-Encoding: 8bit\n" +msgid "(none)" +msgstr "(geen)" + msgid "Key update" msgstr "" @@ -106,9 +109,6 @@ msgstr "Werkelijk opnieuw laden bestanden?" msgid "Active! Can't reload files now" msgstr "Actief! Kan bestanden niet herladen" -msgid "(none)" -msgstr "(geen)" - msgid "active CAIDs" msgstr "actieve CAIDS" diff --git a/po/pl_PL.po b/po/pl_PL.po index 38efa53..3a58049 100644 --- a/po/pl_PL.po +++ b/po/pl_PL.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.5.9\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-12-12 13:24+0100\n" +"POT-Creation-Date: 2011-08-06 20:19+0200\n" "PO-Revision-Date: 2007-08-27 12:45+0200\n" "Last-Translator: somebody\n" "Language-Team: somebody\n" @@ -14,6 +14,9 @@ msgstr "" "Content-Type: text/plain; charset=ISO-8859-2\n" "Content-Transfer-Encoding: 8bit\n" +msgid "(none)" +msgstr "(brak)" + msgid "Key update" msgstr "" @@ -106,9 +109,6 @@ msgstr "Na pewno prze msgid "Active! Can't reload files now" msgstr "Aktywny! Nie mo¿na teraz prze³adowaæ plików." -msgid "(none)" -msgstr "(brak)" - msgid "active CAIDs" msgstr "aktywne CAID" diff --git a/po/ru_RU.po b/po/ru_RU.po index 25e7d1b..cbd4108 100644 --- a/po/ru_RU.po +++ b/po/ru_RU.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.5.9\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-12-12 13:24+0100\n" +"POT-Creation-Date: 2011-08-06 20:19+0200\n" "PO-Revision-Date: 2009-05-14 19:33+0100\n" "Last-Translator: somebody\n" "Language-Team: ru\n" @@ -15,6 +15,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: KBabel 1.11.4\n" +msgid "(none)" +msgstr "(ÝÕâ)" + msgid "Key update" msgstr "¾ÑÝÞÒÛÕÝØÕ ÚÛîçÐ" @@ -107,9 +110,6 @@ msgstr " msgid "Active! Can't reload files now" msgstr "·ÐÝïâ! ½Õ ÜÞÓã ßÕàÕ×ÐÓàãרâì äÐÙÛë" -msgid "(none)" -msgstr "(ÝÕâ)" - msgid "active CAIDs" msgstr "ÐÚâØÒÝëÕ CAID" diff --git a/po/sv_SE.po b/po/sv_SE.po index a683ff1..1ab7c0c 100644 --- a/po/sv_SE.po +++ b/po/sv_SE.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.5.9\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-12-12 13:24+0100\n" +"POT-Creation-Date: 2011-08-06 20:19+0200\n" "PO-Revision-Date: 2007-08-27 12:45+0200\n" "Last-Translator: somebody\n" "Language-Team: somebody\n" @@ -14,6 +14,9 @@ msgstr "" "Content-Type: text/plain; charset=ISO-8859-1\n" "Content-Transfer-Encoding: 8bit\n" +msgid "(none)" +msgstr "(ingen)" + msgid "Key update" msgstr "" @@ -106,9 +109,6 @@ msgstr "Bekr msgid "Active! Can't reload files now" msgstr "Aktiv! Kan inte ladda om filer nu" -msgid "(none)" -msgstr "(ingen)" - msgid "active CAIDs" msgstr "aktiva CAID" diff --git a/sc.c b/sc.c index d0678a2..f19928d 100644 --- a/sc.c +++ b/sc.c @@ -38,11 +38,11 @@ #include #include -#include "sc.h" #include "scsetup.h" #include "filter.h" #include "system.h" #include "cam.h" +#include "global.h" #include "device.h" #include "smartcard.h" #include "data.h" @@ -525,6 +525,34 @@ void cOpts::Create(cOsdMenu *menu) } } +// --- cSoftCAM --------------------------------------------------------------- + +class cSoftCAM { +public: + static bool Load(const char *cfgdir); + static void Shutdown(void); + }; + +bool cSoftCAM::Load(const char *cfgdir) +{ + if(!Feature.KeyFile()) keys.Disable(); + if(!Feature.SmartCard()) smartcards.Disable(); + cStructLoaders::Load(false); + if(Feature.KeyFile() && keys.Count()<1) + PRINTF(L_GEN_ERROR,"no keys loaded for softcam!"); + if(!cSystems::Init(cfgdir)) return false; + srand(time(0)); + return true; +} + +void cSoftCAM::Shutdown(void) +{ + cStructLoaders::Save(true); + cSystems::Clean(); + smartcards.Shutdown(); + keys.SafeClear(); +} + // --- cMenuInfoSc ------------------------------------------------------------- class cMenuInfoSc : public cOsdMenu { @@ -537,19 +565,22 @@ cMenuInfoSc::cMenuInfoSc(void) :cOsdMenu(tr("SoftCAM"),25) { Add(new cScInfoItem(tr("Current keys:"))); - for(int d=0; d0); if(Feature.KeyFile()) { Add(new cScInfoItem(tr("Key update status:"))); int fk, nk; @@ -901,7 +932,7 @@ eOSState cMenuSetupSc::ProcessKey(eKeys Key) case osUser9: state=osContinue; - if(!cSoftCAM::Active(true)) { + if(!cGlobal::Active(true)) { if(Interface->Confirm(tr("Really reload files?"))) { Store(); cSoftCAM::Load(cfgdir); @@ -987,80 +1018,6 @@ bool cScSetup::CapCheck(int n) return false; } -// --- cSoftCAM --------------------------------------------------------------- - -bool cSoftCAM::Load(const char *cfgdir) -{ - if(!Feature.KeyFile()) keys.Disable(); - if(!Feature.SmartCard()) smartcards.Disable(); - cStructLoaders::Load(false); - if(Feature.KeyFile() && keys.Count()<1) - PRINTF(L_GEN_ERROR,"no keys loaded for softcam!"); - if(!cSystems::Init(cfgdir)) return false; - srand(time(0)); - return true; -} - -void cSoftCAM::Shutdown(void) -{ - cStructLoaders::Save(true); - cSystems::Clean(); - smartcards.Shutdown(); - keys.SafeClear(); -} - -char *cSoftCAM::CurrKeyStr(int CardNum, int num) -{ - cScDevice *dev=dynamic_cast(cDevice::GetDevice(CardNum)); - char *str=0; - if(dev) { - if(dev->Cam()) str=dev->Cam()->CurrentKeyStr(num); - if(!str && num==0 && ScSetup.CapCheck(CardNum)) str=strdup(tr("(none)")); - } - return str; -} - -bool cSoftCAM::Active(bool log) -{ - for(int n=cDevice::NumDevices(); --n>=0;) { - cScDevice *dev=dynamic_cast(cDevice::GetDevice(n)); - if(dev && dev->Cam() && dev->Cam()->Active(log)) return true; - } - return false; -} - -void cSoftCAM::SetLogStatus(int CardNum, const cEcmInfo *ecm, bool on) -{ - cScDevice *dev=dynamic_cast(cDevice::GetDevice(CardNum)); - if(dev && dev->Cam()) dev->Cam()->LogEcmStatus(ecm,on); -} - -void cSoftCAM::AddHook(int CardNum, cLogHook *hook) -{ - cScDevice *dev=dynamic_cast(cDevice::GetDevice(CardNum)); - if(dev && dev->Cam()) dev->Cam()->AddHook(hook); -} - -bool cSoftCAM::TriggerHook(int CardNum, int id) -{ - cScDevice *dev=dynamic_cast(cDevice::GetDevice(CardNum)); - return dev && dev->Cam() && dev->Cam()->TriggerHook(id); -} - -void cSoftCAM::CaidsChanged(void) -{ - for(int n=cDevice::NumDevices(); --n>=0;) { - cScDevice *dev=dynamic_cast(cDevice::GetDevice(n)); - if(dev) dev->CaidsChanged(); - } -} - -int cSoftCAM::FilterHandle(int CardNum) -{ - cScDevice *dev=dynamic_cast(cDevice::GetDevice(CardNum)); - return dev ? dev->FilterHandle() : -1; -} - // --- cScHousekeeper ---------------------------------------------------------- class cScHousekeeper : public cThread { @@ -1088,17 +1045,12 @@ void cScHousekeeper::Action(void) while(Running()) { if(++c==20) { c=0; - for(int n=cDevice::NumDevices(); --n>=0;) { - cScDevice *dev=dynamic_cast(cDevice::GetDevice(n)); - if(dev && dev->Cam()) dev->Cam()->HouseKeeping(); - } + cGlobal::HouseKeeping(); } - if(Feature.KeyFile()) keys.HouseKeeping(); - if(!cSoftCAM::Active(false)) cStructLoaders::Purge(); + if(!cGlobal::Active(false)) cStructLoaders::Purge(); cStructLoaders::Load(true); cStructLoaders::Save(); - cCondWait::SleepMs(987); } } @@ -1415,7 +1367,7 @@ const char **cScPlugin::SVDRPHelpPages(void) cString cScPlugin::SVDRPCommand(const char *Command, const char *Option, int &ReplyCode) { if(!strcasecmp(Command,"RELOAD")) { - if(cSoftCAM::Active(true)) { + if(cGlobal::Active(true)) { ReplyCode=550; return "Softcam active. Can't reload files now"; } diff --git a/sc.h b/sc.h deleted file mode 100644 index 5e0717e..0000000 --- a/sc.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Softcam plugin to VDR (C++) - * - * This code is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This code is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * Or, point your browser to http://www.gnu.org/copyleft/gpl.html - */ - -#ifndef ___SC_H -#define ___SC_H - -class cEcmInfo; -class cLogHook; - -// ---------------------------------------------------------------- - -class cSoftCAM { -public: - static bool Load(const char *cfgdir); - static void Shutdown(void); - // - static bool Active(bool log); - static char *CurrKeyStr(int CardNum, int num); - static void SetLogStatus(int CardNum, const cEcmInfo *ecm, bool on); - static void AddHook(int CardNum, cLogHook *hook); - static bool TriggerHook(int CardNum, int id); - static void CaidsChanged(void); - static int FilterHandle(int CardNum); - }; - -#endif // ___SC_H diff --git a/smartcard.c b/smartcard.c index 55e6d42..ea50088 100644 --- a/smartcard.c +++ b/smartcard.c @@ -32,7 +32,7 @@ #include #include "smartcard.h" -#include "sc.h" +#include "global.h" #include "misc.h" #include "log-core.h" @@ -2001,7 +2001,7 @@ int cSmartCard::CheckSctLen(const unsigned char *data, int off) void cSmartCard::CaidsChanged(void) { - cSoftCAM::CaidsChanged(); + cGlobal::CaidsChanged(); } // -- cSmartCardLink ----------------------------------------------------------- diff --git a/system.c b/system.c index f8c3a1b..3e96c9a 100644 --- a/system.c +++ b/system.c @@ -25,8 +25,9 @@ #include -#include "sc.h" #include "system.h" +#include "cam.h" +#include "global.h" #include "data.h" #include "override.h" #include "opts.h" @@ -98,7 +99,7 @@ int cSystem::newKeys=0; cSystem::cSystem(const char *Name, int Pri) { name=Name; pri=Pri; - currentKeyStr[0]=0; doLog=true; cardNum=-1; logecm=0; + currentKeyStr[0]=0; doLog=true; cam=0; logecm=0; check=new struct EcmCheck; memset(check,0,sizeof(struct EcmCheck)); memset(cw,0,sizeof(cw)); @@ -114,21 +115,36 @@ cSystem::cSystem(const char *Name, int Pri) cSystem::~cSystem() { delete check; - if(logecm) cSoftCAM::SetLogStatus(cardNum,logecm,false); + if(logecm && cam) cam->LogEcmStatus(logecm,false); delete logecm; } void cSystem::StartLog(const cEcmInfo *ecm, int caid) { if(!logecm || logecm->caId!=caid) { - if(logecm) cSoftCAM::SetLogStatus(cardNum,logecm,false); + if(logecm && cam) cam->LogEcmStatus(logecm,false); delete logecm; logecm=new cEcmInfo(ecm); logecm->caId=caid; logecm->emmCaId=0; - cSoftCAM::SetLogStatus(cardNum,logecm,true); + if(cam) cam->LogEcmStatus(logecm,true); } } +void cSystem::AddHook(cLogHook *hook) +{ + if(cam) cam->AddHook(hook); +} + +bool cSystem::TriggerHook(int id) +{ + return cam && cam->TriggerHook(id); +} + +void cSystem::CaidsChanged(void) +{ + cGlobal::CaidsChanged(); +} + void cSystem::ParseCADescriptor(cSimpleList *ecms, unsigned short sysId, int source, const unsigned char *data, int len) { const int pid=WORD(data,2,0x1FFF); @@ -166,10 +182,11 @@ void cSystem::ParseCAT(cPids *pids, const unsigned char *buffer, int source, int } break; case 0x05: // Viaccess style (88/8c/8d/8e) - pids->AddPid(pid,0x8B,0xFE,0x07); // mismatching 89/8f + pids->AddPid(pid,0x88,0xF9); // mismatching 8a + pids->AddPid(pid,0x8D,0xFF); break; case 0x0d: // Cryptoworks style (82/84/86/88/89) - pids->AddPid(pid,0x80,0xFF,0x06); + pids->AddPid(pid,0x82,0xF9); // mismatching 80 pids->AddPid(pid,0x88,0xFE); break; case 0x18: // Nagra style (82/83) diff --git a/system.h b/system.h index 524ad57..f22e4a9 100644 --- a/system.h +++ b/system.h @@ -38,6 +38,7 @@ class cSystems; class cLogger; class cOpts; class cHookManager; +class cCam; // ---------------------------------------------------------------- @@ -71,7 +72,8 @@ public: class cLogHook : public cSimpleItem { friend class cHookManager; private: - int cardNum, id; +// int cardNum, id; + int id; const char *name; cTimeMs delay; bool bailOut; @@ -92,12 +94,13 @@ class cSystem : public cSimpleItem { friend class cKeySnoop; private: static int foundKeys, newKeys; - int pri, cardNum; + int pri; cLastKey lastkey; char *lastTxt; char currentKeyStr[48]; struct EcmCheck *check; cEcmInfo *logecm; + cCam *cam; protected: const char *name; unsigned char cw[16]; @@ -113,25 +116,31 @@ protected: public: cSystem(const char *Name, int Pri); virtual ~cSystem(); + void SetOwner(cCam *Cam) { cam=Cam; } + static void CaidsChanged(void); + // virtual int CheckECM(const cEcmInfo *ecm, const unsigned char *data, bool sync); virtual void CheckECMResult(const cEcmInfo *ecm, const unsigned char *data, bool result); virtual bool ProcessECM(const cEcmInfo *ecm, unsigned char *buffer)=0; virtual void ProcessEMM(int pid, int caid, const unsigned char *buffer) {}; virtual void ParseCADescriptor(cSimpleList *ecms, unsigned short sysId, int source, const unsigned char *data, int len); virtual void ParseCAT(cPids *pids, const unsigned char *buffer, int source, int transponder); + // + void AddHook(cLogHook *hook); + bool TriggerHook(int id); + // unsigned char *CW(void) { return cw; } void DoLog(bool Log) { doLog=Log; } int Pri(void) { return pri; } const char *CurrentKeyStr(void) { return currentKeyStr; } const char *Name(void) { return name; } - int CardNum(void) { return cardNum; } - void CardNum(int CardNum) { cardNum=CardNum; } int MaxEcmTry(void) { return maxEcmTry; } bool HasLogger(void) { return hasLogger; } bool NeedsLogger(void) { return needsLogger; } bool Local(void) { return local; } bool NeedsData(void) { return needsDescrData; } bool Constant(void) { return constant; } + // static void FoundKey(void) { foundKeys++; } static void NewKey(void) { newKeys++; } static void KeyStats(int &fk, int &nk) { fk=foundKeys; nk=newKeys; } diff --git a/systems/cardclient/aroureos.c b/systems/cardclient/aroureos.c index 608f9c8..75b16f4 100644 --- a/systems/cardclient/aroureos.c +++ b/systems/cardclient/aroureos.c @@ -32,7 +32,7 @@ public: cCardClientAroureos(const char *Name); virtual bool Init(const char *config); virtual bool Login(void); - virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw, int cardnum); + virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw); virtual bool ProcessEMM(int caSys, const unsigned char *source); }; @@ -99,7 +99,7 @@ bool cCardClientAroureos::ProcessEMM(int caSys, const unsigned char *source) return false; } -bool cCardClientAroureos::ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw, int cardnum) +bool cCardClientAroureos::ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw) { cMutexLock lock(this); so.Flush(); diff --git a/systems/cardclient/camd.c b/systems/cardclient/camd.c index e779aab..9c86a8d 100644 --- a/systems/cardclient/camd.c +++ b/systems/cardclient/camd.c @@ -56,7 +56,7 @@ public: virtual bool Init(const char *config); virtual bool Login(void); virtual bool Immediate(void); - virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw, int cardnum); + virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw); virtual bool ProcessEMM(int caSys, const unsigned char *source); }; @@ -200,7 +200,7 @@ bool cCardClientCommon::ProcessEMM(int caSys, const unsigned char *source) return false; } -bool cCardClientCommon::ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw, int cardnum) +bool cCardClientCommon::ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw) { Lock(); bool res=false; @@ -442,7 +442,7 @@ public: cCardClientCamd35(const char *Name); virtual bool Init(const char *config); virtual bool Login(void); - virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw, int cardnum); + virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw); virtual bool ProcessEMM(int caSys, const unsigned char *data); }; @@ -673,7 +673,7 @@ bool cCardClientCamd35::ProcessEMM(int caSys, const unsigned char *data) return false; } -bool cCardClientCamd35::ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw, int cardnum) +bool cCardClientCamd35::ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw) { bool res=false; const int length=SCT_LEN(data); diff --git a/systems/cardclient/cc.c b/systems/cardclient/cc.c index 26430c0..2fb4f46 100644 --- a/systems/cardclient/cc.c +++ b/systems/cardclient/cc.c @@ -25,7 +25,6 @@ #include "system.h" #include "cc.h" -#include "sc.h" #include "misc.h" #include "opts.h" #include "log-core.h" @@ -67,7 +66,7 @@ bool cCardClient::Immediate(void) void cCardClient::CaidsChanged(void) { - cSoftCAM::CaidsChanged(); + cSystem::CaidsChanged(); } bool cCardClient::ParseStdConfig(const char *config, int *num) @@ -212,7 +211,7 @@ bool cSystemCardClient::ProcessECM(const cEcmInfo *ecm, unsigned char *data) if(cc) { cTimeMs start; int id=cc->msECM.Get(data,SCT_LEN(data),cw); - if(id==0 || (id>0 && cc->ProcessECM(ecm,data,cw,CardNum()))) { + if(id==0 || (id>0 && cc->ProcessECM(ecm,data,cw))) { int dur=start.Elapsed(); if(dur>2000) { char bb[32]; diff --git a/systems/cardclient/cc.h b/systems/cardclient/cc.h index 645c46d..de968e0 100644 --- a/systems/cardclient/cc.h +++ b/systems/cardclient/cc.h @@ -78,7 +78,7 @@ public: virtual bool Login(void)=0; virtual bool Immediate(void); virtual bool CanHandle(unsigned short SysId); - virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw, int cardnum)=0; + virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw)=0; virtual bool ProcessEMM(int caSys, const unsigned char *data) { return false; } const char *Name(void) { return name; } }; diff --git a/systems/cardclient/cccam.c b/systems/cardclient/cccam.c index 9f5cb52..f352372 100644 --- a/systems/cardclient/cccam.c +++ b/systems/cardclient/cccam.c @@ -174,7 +174,7 @@ public: ~cCardClientCCcam(); virtual bool Init(const char *CfgDir); virtual bool Login(void); - virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *Cw, int cardnum); + virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *Cw); }; static cCardClientLinkReg __ncd("cccam"); @@ -218,11 +218,17 @@ bool cCardClientCCcam::Login(void) return true; } -bool cCardClientCCcam::ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw, int cardnum) +bool cCardClientCCcam::ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw) { cMutexLock lock(this); if((!so.Connected() && !Login()) || !CanHandle(ecm->caId)) return false; + if(ecm->dvbAdapter<0 || ecm->dvbFrontend!=0) { + PRINTF(L_CC_CCCAM,"cannot handle DVB adapter %d, frontend %d",ecm->dvbAdapter,ecm->dvbFrontend); + return false; + } + int cardnum=ecm->dvbAdapter; + cCCcamCard *c=&card[cardnum]; int timeout=3000; if(ecm->ecm_pid!=c->Pid() || !c->Connected()) { // channel change diff --git a/systems/cardclient/cccam2.c b/systems/cardclient/cccam2.c index 1d4e4e6..c6d5401 100644 --- a/systems/cardclient/cccam2.c +++ b/systems/cardclient/cccam2.c @@ -680,7 +680,7 @@ public: virtual bool Init(const char *CfgDir); virtual bool Login(void); virtual bool CanHandle(unsigned short SysId); - virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *Cw, int cardnum); + virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *Cw); virtual bool ProcessEMM(int caSys, const unsigned char *data); }; @@ -1147,12 +1147,12 @@ bool cCardClientCCcam2::Login(void) return true; } -bool cCardClientCCcam2::ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *Cw, int cardnum) +bool cCardClientCCcam2::ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *Cw) { 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 %d pid %04x",cardnum,ecm->caId,ecm->provId,ecm->prgId,ecm->ecm_pid); + PRINTF(L_CC_CCCAM2,"ECM caid %04x prov %04x sid %d pid %04x",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"); diff --git a/systems/cardclient/gbox.c b/systems/cardclient/gbox.c index 558efdc..8453402 100644 --- a/systems/cardclient/gbox.c +++ b/systems/cardclient/gbox.c @@ -39,7 +39,7 @@ public: cCardClientGbox(const char *Name); virtual bool Init(const char *CfgDir); virtual bool Login(void); - virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *Cw, int cardnum); + virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *Cw); }; static cCardClientLinkReg __ncd("gbox"); @@ -76,7 +76,7 @@ int cCardClientGbox::GetMsg(int cmd, unsigned char *buff, int len) return n; } -bool cCardClientGbox::ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw, int cardnum) +bool cCardClientGbox::ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw) { cMutexLock lock(this); if((!so.Connected() && !Login()) || !CanHandle(ecm->caId)) return false; diff --git a/systems/cardclient/newcamd.c b/systems/cardclient/newcamd.c index d68a8f6..5a08419 100644 --- a/systems/cardclient/newcamd.c +++ b/systems/cardclient/newcamd.c @@ -189,7 +189,7 @@ public: virtual bool Init(const char *CfgDir); virtual bool Login(void); virtual bool CanHandle(unsigned short SysId); - virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *Cw, int cardnum); + virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *Cw); virtual bool ProcessEMM(int caSys, const unsigned char *data); }; @@ -470,7 +470,7 @@ bool cCardClientNewCamd::Login(void) return true; } -bool cCardClientNewCamd::ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw, int cardnum) +bool cCardClientNewCamd::ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw) { cMutexLock lock(this); if((!so.Connected() && !Login()) || !CanHandle(ecm->caId)) return false; diff --git a/systems/cardclient/radegast.c b/systems/cardclient/radegast.c index 5519d94..4b80078 100644 --- a/systems/cardclient/radegast.c +++ b/systems/cardclient/radegast.c @@ -50,7 +50,7 @@ public: virtual bool Init(const char *config); virtual bool Login(void); virtual bool CanHandle(unsigned short SysId); - virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw, int cardnum); + virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw); virtual bool ProcessEMM(int caSys, const unsigned char *data); }; @@ -218,7 +218,7 @@ bool cCardClientRadegast::Login(void) return true; } -bool cCardClientRadegast::ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw, int cardnum) +bool cCardClientRadegast::ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw) { cMutexLock lock(this); if((!so.Connected() && !Login()) || !CanHandle(ecm->caId)) return false; diff --git a/systems/irdeto/irdeto1.c b/systems/irdeto/irdeto1.c index 81b89aa..0d0ca27 100644 --- a/systems/irdeto/irdeto1.c +++ b/systems/irdeto/irdeto1.c @@ -295,7 +295,7 @@ void cSystemIrd::ProcessEMM(int pid, int caid, const unsigned char *data) int slen=buffer[index-1]-5; // save packet length, 5 signature bytes int maxIndex=index+slen; if(maxIndex>n-5) { - PRINTF(L_SYS_EMM,"%d: bad packet length (%d > %d)",CardNum(),maxIndex,n-5); + PRINTF(L_SYS_EMM,"bad packet length (%d > %d)",maxIndex,n-5); maxIndex=n-5; } bool badnano=false; @@ -372,13 +372,13 @@ void cSystemIrd::ProcessEMM(int pid, int caid, const unsigned char *data) break; default: - PRINTF(L_SYS_EMM,"%d: unhandled nano 0x%02x",CardNum(),nano); + PRINTF(L_SYS_EMM,"unhandled nano 0x%02x",nano); break; } index+=nlen+2; } if(badnano || index!=maxIndex) { - PRINTF(L_SYS_EMM,"%d: bad nano/bad paket",CardNum()); + PRINTF(L_SYS_EMM,"bad nano/bad paket"); return; } diff --git a/systems/nagra/nagra1.c b/systems/nagra/nagra1.c index 0ef7771..a45696a 100644 --- a/systems/nagra/nagra1.c +++ b/systems/nagra/nagra1.c @@ -868,7 +868,7 @@ void cSystemNagra::ProcessEMM(int pid, int caid, const unsigned char *buffer) const int id=buffer[10]*256+buffer[11]; static const unsigned char tester[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x4B }; if(memcmp(&buffer[3],tester,sizeof(tester)) || SCT_LEN(buffer)<(12+9+64)) { - PRINTF(L_SYS_EMM,"%d: not a valid EMM structure",CardNum()); + PRINTF(L_SYS_EMM,"not a valid EMM structure"); return; } const int pkey=(buffer[12]&3); @@ -943,24 +943,24 @@ void cSystemNagra::ProcessEMM(int pid, int caid, const unsigned char *buffer) const int romNr=emmdata[i]&0x0F; if(!emu || !emu->Matches(romNr,id)) { delete emu; emu=0; - PRINTF(L_SYS_EMM,"%d: setting defaults for ROM %d",CardNum(),romNr); + PRINTF(L_SYS_EMM,"setting defaults for ROM %d",romNr); switch(romNr) { case 3: emu=new cEmuRom3; break; case 7: emu=new cEmuRom7; break; case 10: emu=new cEmuRom10; break; case 11: emu=new cEmuRom11; break; - default: PRINTF(L_SYS_EMM,"%d: unsupported ROM",CardNum()); return; + default: PRINTF(L_SYS_EMM,"unsupported ROM"); return; } if(!emu || !emu->Init(romNr,id)) { delete emu; emu=0; - PRINTF(L_SYS_EMM,"%d: initialization failed for ROM %d",CardNum(),romNr); + PRINTF(L_SYS_EMM,"initialization failed for ROM %d",romNr); return; } } unsigned char ki[2]; if((gotKeys=emu->GetOpKeys(emmdata,ki,key0,key1))) { keyId=(ki[0]<<8)+ki[1]; - PRINTF(L_SYS_EMM,"%d: got keys for %04X (ROM %d)",CardNum(),keyId,romNr); + PRINTF(L_SYS_EMM,"got keys for %04X (ROM %d)",keyId,romNr); } unsigned char select[3], pkset[3][15]; select[0]=(keyId>>8)|0x01; // always high id for ECM RSA keys @@ -968,7 +968,7 @@ void cSystemNagra::ProcessEMM(int pid, int caid, const unsigned char *buffer) select[2]=0; // type 0 if(emu->GetPkKeys(&select[0],&pkset[0][0])) { int pkKeyId=((select[0]<<8)+select[1]); - PRINTF(L_SYS_EMM,"%d: got PK keys for %04X (ROM %d)",CardNum(),pkKeyId,romNr); + PRINTF(L_SYS_EMM,"got PK keys for %04X (ROM %d)",pkKeyId,romNr); for(int i=0; i<3; i++) { CreateRSAPair(pkset[i],0,e1,n1); FoundKey(); @@ -998,12 +998,12 @@ void cSystemNagra::ProcessEMM(int pid, int caid, const unsigned char *buffer) i+=10; if(++nrKeys==2) { gotKeys=true; - PRINTF(L_SYS_EMM,"%d: got keys for %04X (plain)",CardNum(),keyId); + PRINTF(L_SYS_EMM,"got keys for %04X (plain)",keyId); break; } } else { - PRINTF(L_SYS_EMM,"%d: ignored nano %02x",CardNum(),emmdata[i]); + PRINTF(L_SYS_EMM,"ignored nano %02x",emmdata[i]); break; } } diff --git a/systems/shl/shl.c b/systems/shl/shl.c index d5e7fa3..f8c80b1 100644 --- a/systems/shl/shl.c +++ b/systems/shl/shl.c @@ -55,7 +55,11 @@ static const struct LogModule lm_sys = { }; ADD_MODULE(L_SYS,lm_sys) -// evil hack, but it's not worth to put much effort in a dead system ... +// This system is dead. +// Not worth to invest time to keep it compilig.... + +#if 0 + static cTimeMs __time; #define time_ms() ((int)__time.Elapsed()) @@ -657,3 +661,5 @@ bool cSystemLinkShl::CanHandle(unsigned short SysId) SysId&=0xFFF0; return SYSTEM_CAN_HANDLE(SysId); } + +#endif //#if 0 diff --git a/systems/viaccess/tps.c b/systems/viaccess/tps.c index 1c7896a..8b03a5b 100644 --- a/systems/viaccess/tps.c +++ b/systems/viaccess/tps.c @@ -28,7 +28,7 @@ #include "opentv.h" #include "st20.h" -#include "sc.h" +#include "global.h" #include "scsetup.h" #include "system-common.h" #include "filter.h" @@ -127,7 +127,7 @@ cSatTimeHook::cSatTimeHook(cTransponderTime *Ttime) :cLogHook(HOOK_SATTIME,"sattime") { ttime=Ttime; - pids.AddPid(0x14,0x71,0xff,0x03); + pids.AddPid(0x14,0x70,0xfc); ttime->SetHasHandler(true); } @@ -161,21 +161,19 @@ private: static cMutex mutex; static cSimpleList list; // - int cardNum; cTransponderTime *ttime; // void CheckHandler(void); public: - cSatTime(int CardNum, int Source, int Transponder); - time_t Now(void); + cSatTime(int Source, int Transponder); + time_t Now(cSystem *sys); }; cMutex cSatTime::mutex; cSimpleList cSatTime::list; -cSatTime::cSatTime(int CardNum, int Source, int Transponder) +cSatTime::cSatTime(int Source, int Transponder) { - cardNum=CardNum; cMutexLock lock(&mutex); for(ttime=list.First(); ttime; ttime=list.Next(ttime)) if(ttime->Is(Source,Transponder)) break; @@ -185,24 +183,19 @@ cSatTime::cSatTime(int CardNum, int Source, int Transponder) PRINTF(L_SYS_TIME,"%x:%x: created new transpondertime",Source,Transponder); } else PRINTF(L_SYS_TIME,"%x:%x: using existing transpondertime",Source,Transponder); - CheckHandler(); -} - -time_t cSatTime::Now(void) -{ - CheckHandler(); - return ttime ? ttime->Now() : -1; } -void cSatTime::CheckHandler(void) +time_t cSatTime::Now(cSystem *sys) { if(ttime) { - if(!cSoftCAM::TriggerHook(cardNum,HOOK_SATTIME) && !ttime->HasHandler()) { + if(!sys->TriggerHook(HOOK_SATTIME) && !ttime->HasHandler()) { cSatTimeHook *hook=new cSatTimeHook(ttime); - cSoftCAM::AddHook(cardNum,hook); + sys->AddHook(hook); PRINTF(L_SYS_TIME,"added hook"); } + return ttime->Now(); } + return -1; } // -- cOpenTVModule ------------------------------------------------------------ @@ -572,7 +565,7 @@ const cTpsKey *cTpsKeys::GetV2Key(int id) return 0; } -void cTpsKeys::Check(time_t now, int cardnum) +void cTpsKeys::Check(time_t now, cSystem *sys) { checkMutex.Lock(); if(first==0 && last==0 && Count()>0) @@ -591,9 +584,9 @@ void cTpsKeys::Check(time_t now, int cardnum) if(tpsAuMode==AU_STREAM && lastAu.Elapsed()>(nokey ? TPSAU_TIME/60 : TPSAU_TIME)) { if(ScSetup.AutoUpdate>0) { PRINTF(L_SYS_TPSAU,"TPS AU triggered"); - if(!cSoftCAM::TriggerHook(cardnum,HOOK_TPSAU)) { + if(!sys->TriggerHook(HOOK_TPSAU)) { cTpsAuHook *hook=new cTpsAuHook; - cSoftCAM::AddHook(cardnum,hook); + sys->AddHook(hook); PRINTF(L_SYS_TPSAU,"TPS AU hook added"); } } @@ -989,7 +982,7 @@ void cTpsAuHook::Process(int pid, unsigned char *data) PRINTF(L_SYS_TPSAU,"got PMT pid %04x for SID %04x",pmtpid,AUSID); cPid *pid=pids.First(); if(pid && pid->filter) { - pid->filter->Start(pmtpid,0x02,0xFF,0x00,false); + pid->filter->Start(pmtpid,0x02,0xFF); pid->filter->Flush(); } else PRINTF(L_GEN_DEBUG,"internal: no pid/filter in cTpsAuHook/pat"); @@ -1010,7 +1003,7 @@ void cTpsAuHook::Process(int pid, unsigned char *data) PRINTF(L_SYS_TPSAU,"got AU pid %04x",aupid); cPid *pid=pids.First(); if(pid && pid->filter) { - pid->filter->Start(aupid,0x87,0xFF,0x00,false); + pid->filter->Start(aupid,0x87,0xFF); pid->filter->Flush(); } else PRINTF(L_GEN_DEBUG,"internal: no pid/filter in cTpsAuHook/pmt"); @@ -1161,17 +1154,17 @@ cTPS::~cTPS() delete sattime; } -int cTPS::Decrypt(int cardNum, int Source, int Transponder, unsigned char *data, int len) +int cTPS::Decrypt(cSystem *sys, int Source, int Transponder, unsigned char *data, int len) { if(!sattime) { - sattime=new cSatTime(cardNum,Source,Transponder); + sattime=new cSatTime(Source,Transponder); if(!sattime) { PRINTF(L_SYS_TPS,"failed to create time class"); return -1; } } - time_t now=sattime->Now(); - tpskeys.Check(now,cardNum); + time_t now=sattime->Now(sys); + tpskeys.Check(now,sys); if(now<0) return -1; const cTpsKey *k=tpskeys.GetKey(now); diff --git a/systems/viaccess/tps.h b/systems/viaccess/tps.h index c8e40f8..d8d9f3c 100644 --- a/systems/viaccess/tps.h +++ b/systems/viaccess/tps.h @@ -26,6 +26,7 @@ #include "data.h" #include "crypto.h" +class cSystem; class cSatTime; class cTpsAuHook; class cOpenTVModule; @@ -61,7 +62,7 @@ private: public: cTPS(void); ~cTPS(); - int Decrypt(int cardNum, int Source, int Transponder, unsigned char *data, int len); + int Decrypt(cSystem *sys, int Source, int Transponder, unsigned char *data, int len); void PostProc(unsigned char *cw); }; @@ -119,7 +120,7 @@ public: ~cTpsKeys(); const cTpsKey *GetKey(time_t t); const cTpsKey *GetV2Key(int id); - void Check(time_t now, int cardnum); + void Check(time_t now, cSystem *sys); }; extern cTpsKeys tpskeys; diff --git a/systems/viaccess/viaccess.c b/systems/viaccess/viaccess.c index 01f5b54..85fed32 100644 --- a/systems/viaccess/viaccess.c +++ b/systems/viaccess/viaccess.c @@ -385,7 +385,7 @@ bool cSystemViaccess::ProcessECM(const cEcmInfo *ecm, unsigned char *data) if(ecm->provId==0x007c00) { // TPS maxEcmTry=4; mayHaveTps=true; - int num=tps.Decrypt(CardNum(),ecm->source,ecm->transponder,nanos,len); + int num=tps.Decrypt(this,ecm->source,ecm->transponder,nanos,len); if(num<0) return false; nanos+=num; len-=num; } @@ -479,7 +479,7 @@ void cSystemViaccess::ProcessEMM(int pid, int caid, const unsigned char *data) numKeys++; } else { - PRINTF(L_SYS_EMM,"%d: key length mismatch %d!=%d",CardNum(),plen,(int)sizeof(newKey[0])); + PRINTF(L_SYS_EMM,"key length mismatch %d!=%d",plen,(int)sizeof(newKey[0])); cnt=scanlen; } break; diff --git a/testing/filterhelper.c b/testing/filterhelper.c index bdbd8e8..e928f9d 100644 --- a/testing/filterhelper.c +++ b/testing/filterhelper.c @@ -34,7 +34,8 @@ int main(int argc, char *argv[]) printf("\n"); max=5; - for(mode=0; mode<256; mode++) { + int mode=0; + //for(mode=0; mode<256; mode++) { for(mask=0; mask<256; mask++) { mam =mask & (~mode); manm=mask & ~(~mode); @@ -72,7 +73,7 @@ int main(int argc, char *argv[]) } } } - } + //} printf("no exact settings found\n"); exit(1); } diff --git a/version.h b/version.h index b650687..d338026 100644 --- a/version.h +++ b/version.h @@ -25,7 +25,7 @@ extern const char *ScVersion; // SC API version number for loading shared libraries -#define SCAPIVERS 29 +#define SCAPIVERS 30 #ifndef STATICBUILD #define SCAPIVERSTAG() int ScLibApiVersion=SCAPIVERS #else