📄 sc.c
字号:
void cScSetup::Check(void){ if(AutoUpdate==0) PRINTF(L_GEN_WARN,"Keys updates (AU) are disabled."); for(int i=0; i<MAXSCCAPS; i++) if(ScCaps[i]>=16) { PRINTF(L_GEN_WARN,"ScCaps contains unusual value. Check your config! (You can ignore this message if you have more than 16 dvb cards in your system ;)"); break; } PRINTF(L_CORE_LOAD,"** Plugin config:"); PRINTF(L_CORE_LOAD,"** Key updates (AU) are %s",AutoUpdate?(AutoUpdate==1?"enabled (active CAIDs)":"enabled (all CAIDs)"):"DISABLED"); PRINTF(L_CORE_LOAD,"** Local systems %stake priority over cached remote",LocalPriority?"":"DON'T "); PRINTF(L_CORE_LOAD,"** Concurrent FF recordings are %sallowed",ConcurrentFF?"":"NOT "); PRINTF(L_CORE_LOAD,"** %sorce transfermode with digital auido",ForceTransfer?"F":"DON'T f"); LBSTART(L_CORE_LOAD); LBPUT("** ScCaps are"); for(int i=0; i<MAXSCCAPS ; i++) LBPUT(" %d",ScCaps[i]); LBFLUSH(); LBPUT("** Ignored CAIDs"); for(int i=0; i<MAXCAIGN ; i++) LBPUT(" %04X",CaIgnore[i]); LBEND();}void cScSetup::Store(bool AsIs){ if(ScOpts) ScOpts->Store(AsIs); cSystems::ConfigStore(AsIs); if(LogOpts) LogOpts->Store(AsIs); cLineBuff lb(128); if(cLogging::GetConfig(&lb)) ScPlugin->SetupStore("LogConfig",lb.Line());}bool cScSetup::CapCheck(int n){ 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: tI18nPhrase *phrases;#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[] = { "off","active CAIDs","all CAIDs" }; ScOpts=new cOpts(0,6); ScOpts->Add(new cOptSel ("AutoUpdate" ,"Update keys (AU)" ,&ScSetup.AutoUpdate,3,logg)); ScOpts->Add(new cOptBool ("ConcurrentFF" ,"Concurrent FF streams",&ScSetup.ConcurrentFF)); ScOpts->Add(new cOptBool ("ForceTranfer" ,"Force TransferMode" ,&ScSetup.ForceTransfer)); ScOpts->Add(new cOptBool ("LocalPriority","Prefer local systems" ,&ScSetup.LocalPriority)); ScOpts->Add(new cOptMInt ("ScCaps" ,"Active on DVB card" , ScSetup.ScCaps,MAXSCCAPS,0)); ScOpts->Add(new cOptMInt ("CaIgnore" ,"Ignore CAID" , ScSetup.CaIgnore,MAXCAIGN,2)); LogOpts=new cOpts(0,4); LogOpts->Add(new cOptBool ("LogConsole" ,"Log to console" ,&logcfg.logCon)); LogOpts->Add(new cOptBool ("LogFile" ,"Log to file" ,&logcfg.logFile)); LogOpts->Add(new cOptStr ("LogFileName" ,"Filename" ,logcfg.logFilename,sizeof(logcfg.logFilename),FileNameChars)); LogOpts->Add(new cOptBool ("LogSyslog" ,"Log to syslog" ,&logcfg.logSys)); phrases=0;#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; Feature.AddPhrases(ScPhrases); RegisterI18n((phrases=Feature.GetPhrases())); filemaps.SetCfgDir(ConfigDirectory()); ScSetup.Check(); if(!cSoftCAM::Load(ConfigDirectory())) 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(); RegisterI18n(NULL); free(phrases); 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," -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", "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' }, { NULL } }; int c, option_index=0; bool invCD=false, invRST=false; int clock=0; while((c=getopt_long(argc,argv,"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; default: return false; } } return true;}cMenuSetupPage *cScPlugin::SetupMenu(void){ return new cMenuSetupSc(ConfigDirectory());}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.", "LOG <on|off> <class>[,<class>...]\n" " Turn the given message class(es) on or off.", "LOGCFG\n" " Display available message classes and their status.", 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())) return "Files reloaded successfully"; else { ReplyCode=901; return "Reloading files not entirely successfull"; } } } else if(!strcasecmp(Command,"LOG")) { if(Option && *Option) { char *opt=strdup(Option); 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"; } return NULL;}VDRPLUGINCREATOR(cScPlugin); // Don't touch this!
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -