sc.c

来自「linux softcam emulator for using with vd」· C语言 代码 · 共 1,487 行 · 第 1/3 页

C
1,487
字号
  for(int j=0; j<MAXSCCAPS; j++)    if(ScCaps[j] && ScCaps[j]==n+1) return true;  return false;}bool cScSetup::Ignore(unsigned short caid){  for(int i=0; i<MAXCAIGN; i++)    if(CaIgnore[i]==caid) return true;  return false;}// --- cSoftCAM ---------------------------------------------------------------bool cSoftCAM::Load(const char *cfgdir){  ecmcache.Load();  if(Feature.KeyFile() && !keys.Load(cfgdir))     PRINTF(L_GEN_ERROR,"no keys loaded for softcam!");  if(!cSystems::Init(cfgdir)) return false;  if(Feature.SmartCard()) smartcards.LoadData(cfgdir);  cLoaders::LoadCache(cfgdir);  cLoaders::SaveCache();  return true;}void cSoftCAM::Shutdown(void){  cSystems::Clean();  smartcards.Shutdown();  keys.Clear();}char *cSoftCAM::CurrKeyStr(int CardNum, int num){  cScDvbDevice *dev=dynamic_cast<cScDvbDevice *>(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(void){  for(int n=cDevice::NumDevices(); --n>=0;) {    cScDvbDevice *dev=dynamic_cast<cScDvbDevice *>(cDevice::GetDevice(n));    if(dev && dev->Cam() && dev->Cam()->Active()) return true;    }  return false;}void cSoftCAM::SetLogStatus(int CardNum, const cEcmInfo *ecm, bool on){  cScDvbDevice *dev=dynamic_cast<cScDvbDevice *>(cDevice::GetDevice(CardNum));  if(dev && dev->Cam()) dev->Cam()->LogEcmStatus(ecm,on);}void cSoftCAM::AddHook(int CardNum, cLogHook *hook){  cScDvbDevice *dev=dynamic_cast<cScDvbDevice *>(cDevice::GetDevice(CardNum));  if(dev && dev->Cam()) dev->Cam()->AddHook(hook);}bool cSoftCAM::TriggerHook(int CardNum, int id){  cScDvbDevice *dev=dynamic_cast<cScDvbDevice *>(cDevice::GetDevice(CardNum));  return dev && dev->Cam() && dev->Cam()->TriggerHook(id);}#ifndef STATICBUILD// --- cScDll ------------------------------------------------------------------class cScDll : public cSimpleItem {private:  char *fileName;  void *handle;public:  cScDll(const char *FileName);  ~cScDll();  bool Load(void);  };cScDll::cScDll(const char *FileName){  fileName=strdup(FileName);  handle=0;}cScDll::~cScDll(){  if(handle) dlclose(handle);  free(fileName);}bool cScDll::Load(void){  char *base=rindex(fileName,'/');  if(!base) base=fileName;  PRINTF(L_CORE_DYN,"loading library: %s",base);  if(!handle) {    handle=dlopen(fileName,RTLD_NOW|RTLD_LOCAL);    if(handle) return true;    PRINTF(L_GEN_ERROR,"dload: %s: %s",base,dlerror());    }  return false;}// --- cScDlls -----------------------------------------------------------------#define LIBSC_PREFIX  "libsc-"#define SO_INDICATOR   ".so."class cScDlls : public cSimpleList<cScDll> {private:  void *handle;public:  cScDlls(void);  ~cScDlls();  bool Load(void);  };cScDlls::cScDlls(void){  handle=0;}cScDlls::~cScDlls(){  Clear();  if(handle) dlclose(handle);  PRINTF(L_CORE_DYN,"unload done");}bool cScDlls::Load(void){  Dl_info info;  static int marker=0;  if(!dladdr((void *)&marker,&info)) {    PRINTF(L_GEN_ERROR,"dladdr: %s",dlerror());    return false;    }  // we have to re-dlopen our selfs as VDR doesn't use RTLD_GLOBAL  // but our symbols have to be available to the sub libs.  handle=dlopen(info.dli_fname,RTLD_NOW|RTLD_GLOBAL);  if(!handle) {    PRINTF(L_GEN_ERROR,"dlopen myself: %s",dlerror());    return false;    }  char *path=strdup(info.dli_fname);  char *p;  if((p=rindex(path,'/'))) *p=0;  PRINTF(L_CORE_DYN,"library path %sn",path);  char pat[32];  snprintf(pat,sizeof(pat),"%s*-%d%s%s",LIBSC_PREFIX,SCAPIVERS,SO_INDICATOR,APIVERSION);  bool res=true;  cReadDir dir(path);  struct dirent *e;  while((e=dir.Next())) {    if(!fnmatch(pat,e->d_name,FNM_PATHNAME|FNM_NOESCAPE)) {      cScDll *dll=new cScDll(AddDirectory(path,e->d_name));      if(dll) {        if(!dll->Load()) res=false;        Ins(dll);        }      }    }  free(path);  return res;}#endif// --- cScPlugin ---------------------------------------------------------------class cScPlugin : public cPlugin {private:#ifndef STATICBUILD  cScDlls dlls;#endifpublic:  cScPlugin(void);  virtual ~cScPlugin();  virtual const char *Version(void);  virtual const char *Description(void);  virtual const char *CommandLineHelp(void);  virtual bool ProcessArgs(int argc, char *argv[]);  virtual bool Initialize(void);  virtual bool Start(void);  virtual void Stop(void);  virtual void Housekeeping(void);  virtual cMenuSetupPage *SetupMenu(void);  virtual bool SetupParse(const char *Name, const char *Value);  virtual const char **SVDRPHelpPages(void);  virtual cString SVDRPCommand(const char *Command, const char *Option, int &ReplyCode);  };cScPlugin::cScPlugin(void){  static const char *logg[] = { trNOOP("off"),trNOOP("active CAIDs"),trNOOP("all CAIDs") };  ScOpts=new cOpts(0,7);  ScOpts->Add(new cOptSel  ("AutoUpdate"   ,trNOOP("Update keys (AU)")     ,&ScSetup.AutoUpdate,3,logg));  ScOpts->Add(new cOptBool ("PrestartAU"   ,trNOOP("Start AU on EPG scan") ,&ScSetup.PrestartAU));  ScOpts->Add(new cOptBool ("ConcurrentFF" ,trNOOP("Concurrent FF streams"),&ScSetup.ConcurrentFF));  ScOpts->Add(new cOptBool ("ForceTranfer" ,trNOOP("Force TransferMode")   ,&ScSetup.ForceTransfer));  ScOpts->Add(new cOptBool ("LocalPriority",trNOOP("Prefer local systems") ,&ScSetup.LocalPriority));  ScOpts->Add(new cOptMInt ("ScCaps"       ,trNOOP("Active on DVB card")   , ScSetup.ScCaps,MAXSCCAPS,0));  ScOpts->Add(new cOptMInt ("CaIgnore"     ,trNOOP("Ignore CAID")          , ScSetup.CaIgnore,MAXCAIGN,2));  LogOpts=new cOpts(0,5);  LogOpts->Add(new cOptBool ("LogConsole"  ,trNOOP("Log to console")      ,&logcfg.logCon));  LogOpts->Add(new cOptBool ("LogFile"     ,trNOOP("Log to file")         ,&logcfg.logFile));  LogOpts->Add(new cOptStr  ("LogFileName" ,trNOOP("Filename")            ,logcfg.logFilename,sizeof(logcfg.logFilename),FileNameChars));  LogOpts->Add(new cOptInt  ("LogFileLimit",trNOOP("Filesize limit (KB)") ,&logcfg.maxFilesize,0,2000000));  LogOpts->Add(new cOptBool ("LogSyslog"   ,trNOOP("Log to syslog")       ,&logcfg.logSys));#ifndef STATICBUILD  dlls.Load();#endif  cScDvbDevice::Capture();}cScPlugin::~cScPlugin(){  delete ScOpts;  delete LogOpts;}bool cScPlugin::Initialize(void){  PRINTF(L_GEN_INFO,"SC version %s initializing",ScVersion);  return cScDvbDevice::Initialize();}bool cScPlugin::Start(void){  PRINTF(L_GEN_INFO,"SC version %s starting",ScVersion);  if(APIVERSNUM<MINAPIVERSNUM) {    PRINTF(L_GEN_ERROR,"SC plugin needs at least VDR API version %d.%d.%d",MIN_VERS,MIN_MAJOR,MIN_MINOR);    return false;    }  if(sizeof(int)!=4) {    PRINTF(L_GEN_ERROR,"compiled with 'int' as %d bit. Only supporting 32 bit.",(int)sizeof(int)*8);    return false;    }  if(sizeof(long long)!=8) {    PRINTF(L_GEN_ERROR,"compiled with 'long long' as %d bit. Only supporting 64 bit.",(int)sizeof(long long)*8);    return false;    }      ScPlugin=this;#if APIVERSNUM < 10507  RegisterI18n(ScPhrases);#endif  filemaps.SetCfgDir(ConfigDirectory(cfgsub));  ScSetup.Check();  if(!cSoftCAM::Load(ConfigDirectory(cfgsub))) return false;  if(Feature.SmartCard()) {#ifdef DEFAULT_PORT    smartcards.AddPort(DEFAULT_PORT);#endif    smartcards.LaunchWatcher();    }  cScDvbDevice::Startup();  return true;}void cScPlugin::Stop(void){  cScDvbDevice::Shutdown();  LogStatsDown();  cSoftCAM::Shutdown();#if APIVERSNUM < 10507  RegisterI18n(NULL);#endif  PRINTF(L_GEN_DEBUG,"SC cleanup done");}const char *cScPlugin::Version(void){  return ScVersion;}const char *cScPlugin::Description(void){  return tr("A software emulated CAM");}const char *cScPlugin::CommandLineHelp(void){  static char *help_str=0;    free(help_str);    //                                     for easier orientation, this is column 80|  asprintf(&help_str,"  -c DIR    --config=DIR   search config files in subdir DIR\n"                     "                           (default: %s)\n"                     "  -B N      --budget=N     forces DVB device N to budget mode (using FFdecsa)\n"                     "  -I        --inverse-cd   use inverse CD detection for the next serial device\n"                     "  -R        --inverse-rst  use inverse RESET for the next serial device\n"                     "  -C FREQ   --clock=FREQ   use FREQ as clock for the card reader on the next\n"                     "                           serial device (rather than 3.5712 MHz\n"                     "  -s DEV    --serial=DEV   activate Phoenix ISO interface on serial device DEV\n"                     "                           (default: %s)\n"                     "  -d CMD    --dialup=CMD   call CMD to start/stop dialup-network\n"                     "                           (default: %s)\n"                     "  -t SECS   --timeout=SECS shutdown timeout for dialup-network\n"                     "                           (default: %d secs)\n",                     cfgsub?cfgsub:"none","none","none",netTimeout/1000                     );  return help_str;}bool cScPlugin::ProcessArgs(int argc, char *argv[]){  static struct option long_options[] = {      { "serial",      required_argument, NULL, 's' },      { "inverse-cd",  no_argument,       NULL, 'I' },      { "inverse-rst", no_argument,       NULL, 'R' },      { "clock",       required_argument, NULL, 'C' },      { "dialup",      required_argument, NULL, 'd' },      { "external-au", required_argument, NULL, 'E' },      { "budget",      required_argument, NULL, 'B' },      { "config",      required_argument, NULL, 'c' },      { NULL }    };  int c, option_index=0;  bool invCD=false, invRST=false;  int clock=0;  while((c=getopt_long(argc,argv,"c:d:s:t:B:C:E:IR",long_options,&option_index))!=-1) {    switch (c) {      case 'I': invCD=true; break;      case 'R': invRST=true; break;      case 'C': clock=atoi(optarg); break;      case 's': smartcards.AddPort(optarg,invCD,invRST,clock); invCD=false; invRST=false; clock=0; break;      case 'd': netscript=optarg; break;      case 't': netTimeout=atoi(optarg)*1000; break;      case 'E': externalAU=optarg; break;      case 'B': cScDvbDevice::SetForceBudget(atoi(optarg)); break;      case 'c': cfgsub=optarg; break;      default:  return false;      }    }  return true;}cMenuSetupPage *cScPlugin::SetupMenu(void){  return new cMenuSetupSc(ConfigDirectory(cfgsub));}bool cScPlugin::SetupParse(const char *Name, const char *Value){  if((ScOpts && ScOpts->Parse(Name,Value)) ||     (LogOpts && LogOpts->Parse(Name,Value)) ||     cSystems::ConfigParse(Name,Value)) ;  else if(!strcasecmp(Name,"LogConfig")) cLogging::ParseConfig(Value);  else return false;  return true;}void cScPlugin::Housekeeping(void){  for(int n=cDevice::NumDevices(); --n>=0;) {    cScDvbDevice *dev=dynamic_cast<cScDvbDevice *>(cDevice::GetDevice(n));    if(dev && dev->Cam()) dev->Cam()->HouseKeeping();    }  if(Feature.KeyFile()) keys.HouseKeeping();}const char **cScPlugin::SVDRPHelpPages(void){  static const char *HelpPages[] = {    "RELOAD\n"    "    Reload all configuration files.",    "KEY <string>\n",    "    Add key to the key database (as if it was received from EMM stream).",    "LOG <on|off> <class>[,<class>...]\n"    "    Turn the given message class(es) on or off.",    "LOGCFG\n"    "    Display available message classes and their status.",    "LOGFILE <on|off> [<filename>]\n"    "    Enables/disables logging to file and optionaly sets the filename.",    NULL    };  return HelpPages;}cString cScPlugin::SVDRPCommand(const char *Command, const char *Option, int &ReplyCode){  if(!strcasecmp(Command,"RELOAD")) {    if(cSoftCAM::Active()) {      ReplyCode=550;      return "Softcam active. Can't reload files now";      }    else {      if(cSoftCAM::Load(ConfigDirectory(cfgsub)))        return "Files reloaded successfully";      else {        ReplyCode=901;        return "Reloading files not entirely successfull";        }      }    }  else if(!strcasecmp(Command,"KEY")) {    if(Option && *Option) {      if(keys.NewKeyParse(skipspace(Option)))        return "Key update successfull";      else {        ReplyCode=901;        return "Key already known or invalid key format";        }      }    else { ReplyCode=501; return "Missing args"; }    }  else if(!strcasecmp(Command,"LOG")) {    if(Option && *Option) {      char tmp[1024];      strn0cpy(tmp,Option,sizeof(tmp));      char *opt=tmp;      opt=skipspace(opt);      bool mode;      if(!strncasecmp(opt,"ON ",3)) { mode=true; opt+=3; }      else if(!strncasecmp(opt,"OFF ",4)) { mode=false; opt+=4; }      else { ReplyCode=501; return "Bad mode, valid: on off"; }      do {        char *s=index(opt,',');        if(s) *s++=0;        int c=cLogging::GetClassByName(opt);        if(c>=0) cLogging::SetModuleOption(c,mode);        else { ReplyCode=501; return "Unknown message class"; }        opt=s;        } while(opt);      ScSetup.Store(true);      Setup.Save();      return "Done";      }    else { ReplyCode=501; return "Missing args"; }    }  else if(!strcasecmp(Command,"LOGCFG")) {    cLineBuff lb(256);    for(int m=1; m<LMOD_MAX; m++) {      const char *name=cLogging::GetModuleName(LCLASS(m,0));      if(name) {        int o=cLogging::GetModuleOptions(LCLASS(m,0));        if(o>=0) {          for(int i=0; i<LOPT_NUM; i++) {            const char *opt;            if(i==0) opt="enable";            else opt=cLogging::GetOptionName(LCLASS(m,1<<i));            if(opt)              lb.Printf("%s.%s %s\n",name,opt,(o&(1<<i))?"on":"off");            }          }        }      }    if(lb.Length()>0) return lb.Line();    ReplyCode=901; return "No config available";    }  else if(!strcasecmp(Command,"LOGFILE")){    if(Option && *Option) {      char tmp[1024];      strn0cpy(tmp,Option,sizeof(tmp));      char *opt=tmp;      opt=skipspace(opt);      bool mode;      if(!strncasecmp(opt,"ON",2)) { mode=true; opt+=2; }      else if(!strncasecmp(opt,"OFF",3)) { mode=false; opt+=3; }      else { ReplyCode=501; return "Bad mode, valid: on off"; }      cLineBuff lb(256);      if(mode) {        logcfg.logFile=true;        if(*opt==' ' || *opt=='\t') {          opt=stripspace(skipspace(opt));          strn0cpy(logcfg.logFilename,opt,sizeof(logcfg.logFilename));          }        lb.Printf("logging to file enabled, file %s",logcfg.logFilename);        }      else {        logcfg.logFile=false;        lb.Printf("logging to file disabled");        }      ScSetup.Store(true);      Setup.Save();      return lb.Line();      }    else { ReplyCode=501; return "Missing args"; }    }  return NULL;}VDRPLUGINCREATOR(cScPlugin); // Don't touch this!

⌨️ 快捷键说明

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