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

📄 cam.c

📁 这是一个LINUX环境的 VDR 插件源代码,可支持Irdeto, Seca, Viaccess, Nagra, Conax & Cryptoworks等CA系统的读卡、共享等操作。
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * 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 */#include <stdlib.h>#include <stdio.h>#include <unistd.h>#include <errno.h>#include <sys/ioctl.h>#include <sys/time.h>#include <dlfcn.h>#include <linux/dvb/ca.h>#include <vdr/ci.h>#include <vdr/dvbdevice.h>#if APIVERSNUM >= 10500#include <vdr/dvbci.h>#endif#include <vdr/channels.h>#include <vdr/thread.h>#include "FFdecsa/FFdecsa.h"#include "cam.h"#include "scsetup.h"#include "filter.h"#include "system.h"#include "data.h"#include "misc.h"#include "log-core.h"#define IDLE_SLEEP          0 // idleTime when sleeping#define IDLE_GETCA        200 // idleTime when waiting for ca descriptors#define IDLE_GETCA_SLOW 20000 // idleTime if no enc. system#define IDLE_NO_SYNC      800 // idleTime when not in sync#define IDLE_SYNC        2000 // idleTime when in sync#define CW_REPEAT_TIME   2000 // rewrite CW after X ms#define LOG_COUNT           3 // stop logging after X complete ECM cycles#define CHAIN_HOLD     120000 // min. time to hold a logger chain#define ECM_DATA_TIME    6000 // time to wait for ECM data updates#define ECM_UPD_TIME   120000 // delay between ECM data updates#define MAX_ECM_IDLE   300000 // delay before an idle handler can be removed#define MAX_ECM_HOLD    15000 // delay before an idle handler stops processing#define CAID_TIME      300000 // time between caid scans#define L_HEX       2#define L_HEX_ECM   LCLASS(L_HEX,2)#define L_HEX_EMM   LCLASS(L_HEX,4)#define L_HEX_CAT   LCLASS(L_HEX,8)#define L_HEX_PMT   LCLASS(L_HEX,16)#define L_HEX_HOOK  LCLASS(L_HEX,32)#define L_HEX_ALL   LALL(L_HEX_HOOK)static const struct LogModule lm_hex = {  (LMOD_ENABLE|L_HEX_ALL)&LOPT_MASK,  (LMOD_ENABLE)&LOPT_MASK,  "hexdata",  { "ecm","emm","cat","pmt","hook" }  };ADD_MODULE(L_HEX,lm_hex)static const char *typeNames[] = { "typ0","typ1","VIDEO","typ3","AUDIO","typ5","DOLBY","typ6+" };#define TYPENAME(type) (typeNames[(type)<=7?(type):7])// -- cLogStats ---------------------------------------------------------------#define COUNTS  20#define SAMPLE (30*1000)#define AVR1   (60*1000)#define AVR2   (4*60*1000)#define AVR3   (10*60*1000)#define REPORT (60*1000)class cLogStats : public cThread {private:  cTimeMs sTime, repTime;  int sCount, sIdx, sCounts[COUNTS][2];protected:  virtual void Action(void);public:  cLogStats(void);  ~cLogStats();  void Count(void);  };static cMutex logstatsMutex;static cLogStats *logstats=0;void LogStatsUp(void){  logstatsMutex.Lock();  if(LOG(L_CORE_AUSTATS) && !logstats) logstats=new cLogStats;  logstatsMutex.Unlock();}void LogStatsDown(void){  logstatsMutex.Lock();  if(logstats) { delete logstats; logstats=0; }  logstatsMutex.Unlock();}cLogStats::cLogStats(void){  sCount=sIdx=0;  for(int i=0; i<COUNTS; i++) { sCounts[i][0]=0; sCounts[i][1]=SAMPLE; }  SetDescription("logger stats");  Start();}cLogStats::~cLogStats(){  Cancel(2);}void cLogStats::Count(void){  sCount++;}void cLogStats::Action(void){  while(Running()) {    cCondWait::SleepMs(50);    if(sTime.Elapsed()>SAMPLE) {      sCounts[sIdx][0]=sCount;          sCount=0;      sCounts[sIdx][1]=sTime.Elapsed(); sTime.Set();      if(++sIdx >= COUNTS) sIdx=0;      }    if(repTime.Elapsed()>REPORT) {      repTime.Set();      if(sCounts[(sIdx+COUNTS-1)%COUNTS][0]>0) {        LBSTART(L_CORE_AUSTATS);        LBPUT("EMM packet load average (%d/%d/%dmin)",AVR1/60000,AVR2/60000,AVR3/60000);        int s=0, t=0;        for(int i=1; i<=COUNTS; i++) {          s+=sCounts[(sIdx+COUNTS-i)%COUNTS][0];          t+=sCounts[(sIdx+COUNTS-i)%COUNTS][1];          if(i==(AVR1/SAMPLE) || i==(AVR2/SAMPLE) || i==(AVR3/SAMPLE))            LBPUT(" %4d",(int)((float)s/(float)t*1000.0));          }        LBPUT(" pks/s");        LBEND();        }      }    }}// -- cHookManager -------------------------------------------------------------class cHookManager : public cAction {  int cardNum;  cSimpleList<cLogHook> hooks;  //  cPidFilter *AddFilter(int Pid, int Section, int Mask, int Mode, int IdleTime, bool Crc);  void ClearHooks(void);  void DelHook(cLogHook *hook);protected:  virtual void Process(cPidFilter *filter, unsigned char *data, int len);public:  cHookManager(int CardNum);  virtual ~cHookManager();  void AddHook(cLogHook *hook);  bool TriggerHook(int id);  void Down(void);  };cHookManager::cHookManager(int CardNum):cAction("hookmanager",CardNum){  cardNum=CardNum;  Priority(10);}cHookManager::~cHookManager(){  Down();}void cHookManager::Down(void){  Lock();  while(cLogHook *hook=hooks.First()) DelHook(hook);  DelAllFilter();  Unlock();}bool cHookManager::TriggerHook(int id){  Lock();  for(cLogHook *hook=hooks.First(); hook; hook=hooks.Next(hook))    if(hook->id==id) {      hook->delay.Set(CHAIN_HOLD);      Unlock();      return true;      }  Unlock();  return false;}void cHookManager::AddHook(cLogHook *hook){  Lock();  PRINTF(L_CORE_HOOK,"%d: starting hook '%s' (%04x)",cardNum,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);    if(filter) {      filter->userData=(void *)hook;      pid->filter=filter;      }    }  Unlock();}void cHookManager::DelHook(cLogHook *hook){  PRINTF(L_CORE_HOOK,"%d: stopping hook '%s' (%04x)",cardNum,hook->name,hook->id);  for(cPid *pid=hook->pids.First(); pid; pid=hook->pids.Next(pid)) {    cPidFilter *filter=pid->filter;    if(filter) {      DelFilter(filter);      pid->filter=0;      }    }  hooks.Del(hook);}cPidFilter *cHookManager::AddFilter(int Pid, int Section, int Mask, int Mode, int IdleTime, bool Crc){  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);    }  else PRINTF(L_GEN_ERROR,"no free slot or filter failed to open for hookmanager %d",cardNum);  return filter;}void cHookManager::Process(cPidFilter *filter, unsigned char *data, int len){  if(data && len>0) {    HEXDUMP(L_HEX_HOOK,data,len,"HOOK pid 0x%04x",filter->Pid());    if(SCT_LEN(data)==len) {      cLogHook *hook=(cLogHook *)(filter->userData);      if(hook) {        hook->Process(filter->Pid(),data);        if(hook->bailOut || hook->delay.TimedOut()) DelHook(hook);        }      }    else PRINTF(L_CORE_HOOK,"%d: incomplete section %d != %d",cardNum,len,SCT_LEN(data));    }  else {    cLogHook *hook=(cLogHook *)(filter->userData);    if(hook && (hook->bailOut || hook->delay.TimedOut())) DelHook(hook);    }}// -- cLogChain ----------------------------------------------------------------class cLogChain : public cSimpleItem {public:  int cardNum, caid;  bool softCSA, active, delayed;  cTimeMs delay;  cPids pids;  cSimpleList<cSystem> systems;  //  cLogChain(int CardNum, bool soft);  void Process(int pid, unsigned char *data);  bool Parse(const unsigned char *cat);  };cLogChain::cLogChain(int CardNum, bool soft){  cardNum=CardNum; softCSA=soft; active=delayed=false;}void cLogChain::Process(int pid, unsigned char *data){  if(active) {    for(cSystem *sys=systems.First(); sys; sys=systems.Next(sys))      sys->ProcessEMM(pid,caid,data);    }}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);    cSystem *sys;    if(systems.Count()>0) {      LBPUT(" ++");      for(sys=systems.First(); sys; sys=systems.Next(sys))        sys->ParseCAT(&pids,cat);      }    else {      LBPUT(" ->");      int Pri=0;      while((sys=cSystems::FindBySysId(caid,!softCSA,Pri))) {        Pri=sys->Pri();        if(sys->HasLogger()) {          sys->CardNum(cardNum);          sys->ParseCAT(&pids,cat);          systems.Add(sys);          LBPUT(" %s(%d)",sys->Name(),sys->Pri());          }        else          delete sys;        }      }    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);    LBEND();    if(systems.Count()>0 && pids.Count()>0)      return true;    }  return false;}// -- cLogger ------------------------------------------------------------------class cLogger : public cAction {private:  int cardNum;  bool softCSA, up;  cSimpleList<cLogChain> chains;  cSimpleList<cEcmInfo> active;  //  cPidFilter *catfilt;  int catVers;  //  cPidFilter *AddFilter(int Pid, int Section, int Mask, int Mode, int IdleTime, bool Crc);  void SetChains(void);  void ClearChains(void);  void StartChain(cLogChain *chain);  void StopChain(cLogChain *chain, bool force);protected:  virtual void Process(cPidFilter *filter, unsigned char *data, int len);public:  cLogger(int CardNum, bool soft);  virtual ~cLogger();  void EcmStatus(const cEcmInfo *ecm, bool on);  void Up(void);  void Down(void);  };cLogger::cLogger(int CardNum, bool soft):cAction("logger",CardNum){  cardNum=CardNum; softCSA=soft;  catfilt=0; up=false;  Priority(10);}cLogger::~cLogger(){  Down();}void cLogger::Up(void){  Lock();  if(!up) {    PRINTF(L_CORE_AUEXTRA,"%d: UP",cardNum);    catVers=-1;    catfilt=AddFilter(1,0x01,0xFF,0,0,true);    up=true;    }  Unlock();}void cLogger::Down(void){  Lock();  if(up) {    PRINTF(L_CORE_AUEXTRA,"%d: DOWN",cardNum);    ClearChains();    DelAllFilter();    catfilt=0; up=false;    }  Unlock();}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");  cEcmInfo *e;  if(on) {    e=new cEcmInfo(ecm);    active.Add(e);    if(!up) Up();    }  else {    for(e=active.First(); e; e=active.Next(e))      if(e->Compare(ecm)) {        active.Del(e);        break;        }    }  SetChains();  Unlock();}void cLogger::SetChains(void){  for(cLogChain *chain=chains.First(); chain; chain=chains.Next(chain)) {    bool act=false;    if(ScSetup.AutoUpdate>1) act=true;    else if(ScSetup.AutoUpdate==1) {      for(cEcmInfo *e=active.First(); e; e=active.Next(e))        if((e->emmCaId && chain->caid==e->emmCaId) || chain->caid==e->caId) {          act=true; break;          }       }    if(act) StartChain(chain);    else StopChain(chain,false);    }}void cLogger::ClearChains(void){  for(cLogChain *chain=chains.First(); chain; chain=chains.Next(chain))    StopChain(chain,true);  chains.Clear();}void cLogger::StartChain(cLogChain *chain){  if(chain->delayed)    PRINTF(L_CORE_AUEXTRA,"%d: restarting delayed chain %04x",cardNum,chain->caid);  chain->delayed=false;  if(!chain->active) {    PRINTF(L_CORE_AU,"%d: starting chain %04x",cardNum,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);      if(filter) {        filter->userData=(void *)chain;        pid->filter=filter;        }      }    }}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);      chain->active=false;      for(cPid *pid=chain->pids.First(); pid; pid=chain->pids.Next(pid)) {        cPidFilter *filter=pid->filter;        if(filter) {          DelFilter(filter);          pid->filter=0;          }        }      }

⌨️ 快捷键说明

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