diff --git a/device.c b/device.c index fe10d5e..5aa1808 100644 --- a/device.c +++ b/device.c @@ -1325,6 +1325,8 @@ void cScDeviceProbe::Remove(void) bool cScDeviceProbe::Probe(int Adapter, int Frontend) { + if (cScDevices::SkipAdapter(Adapter)) + return false; PRINTF(L_GEN_DEBUG,"capturing device %d/%d",Adapter,Frontend); new cScDevice(Adapter,Frontend,cScDevices::DvbOpen(DEV_DVB_CA,Adapter,Frontend,O_RDWR)); return true; @@ -1334,6 +1336,19 @@ bool cScDeviceProbe::Probe(int Adapter, int Frontend) // -- cScDevices --------------------------------------------------------------- int cScDevices::budget=0; +int cScDevices::skipAdapter=0; +bool cScDevices::autoLateInit = false; +int cScDevices::numScDevices = 0; +cScDevice *cScDevices::scdevice[MAXDEVICES] = { NULL }; + +cScDevice *cScDevices::GetScDevice(int CardIndex) +{ + for (int n = 0; n < numScDevices; n++) { + if (scdevice[n] && (scdevice[n]->CardIndex() == CardIndex)) + return scdevice[n]; + } + return NULL; +} void cScDevices::DvbName(const char *Name, int a, int f, char *buffer, int len) { @@ -1439,16 +1454,17 @@ void cScDevices::Startup(void) { if(ScSetup.ForceTransfer) SetTransferModeForDolbyDigital(2); - for(int n=cDevice::NumDevices(); --n>=0;) { - cScDevice *dev=dynamic_cast(cDevice::GetDevice(n)); + for(int n=cScDevices::numScDevices; --n>=0;) { + cScDevice *dev=cScDevices::scdevice[n]; if(dev) dev->LateInit(); } + autoLateInit = true; } void cScDevices::Shutdown(void) { - for(int n=cDevice::NumDevices(); --n>=0;) { - cScDevice *dev=dynamic_cast(cDevice::GetDevice(n)); + for(int n=cScDevices::numScDevices; --n>=0;) { + cScDevice *dev=cScDevices::scdevice[n]; if(dev) dev->EarlyShutdown(); } } @@ -1458,11 +1474,21 @@ void cScDevices::SetForceBudget(int n) if(n>=0 && n=0 && adapter= 0) && (index < MAXDEVICES) && (cScDevices::scdevice[index] == this)) + cScDevices::scdevice[index] = NULL; #ifndef SASC DetachAllReceivers(); Cancel(3); @@ -1528,9 +1571,11 @@ void cScDevice::EarlyShutdown(void) void cScDevice::LateInit(void) { + if (lateInit) return; + lateInit = true; int n=CardIndex(); if(DeviceNumber()!=n) - PRINTF(L_GEN_ERROR,"CardIndex - DeviceNumber mismatch! Put SC plugin first on VDR commandline!"); + PRINTF(L_GEN_ERROR,"CardIndex %d - DeviceNumber %d mismatch! Put SC plugin first on VDR commandline!", n, DeviceNumber()); if(softcsa) { if(HasDecoder()) PRINTF(L_GEN_ERROR,"Card %d is a full-featured card but no ca device found!",n); } @@ -1538,10 +1583,17 @@ void cScDevice::LateInit(void) PRINTF(L_GEN_INFO,"Budget mode forced on card %d",n); softcsa=true; } - +#ifdef __DYNAMIC_DEVICE_PROBE + cDevice *cidev = parentDevice ? parentDevice : this; + if(fd_ca2>=0) hwciadapter=cDvbCiAdapter::CreateCiAdapter(cidev,fd_ca2,adapter,frontend); + fd_ca2=-1; // will be closed by patched cDvbCiAdapter + cam=new cCam(this,n); + ciadapter=new cScCiAdapter(cidev,n,cam); +#else if(fd_ca2>=0) hwciadapter=cDvbCiAdapter::CreateCiAdapter(this,fd_ca2); cam=new cCam(this,n); ciadapter=new cScCiAdapter(this,n,cam); +#endif if(softcsa) { decsa=new cDeCSA(n); if(IsPrimaryDevice() && HasDecoder()) { @@ -1552,6 +1604,34 @@ void cScDevice::LateInit(void) } } +#ifdef __DYNAMIC_DEVICE_PROBE +bool cScDevice::SetIdleDevice(bool Idle, bool TestOnly) +{ + if (TestOnly) { + if (hwciadapter) + return hwciadapter->SetIdle(Idle, true); + return cDvbDevice::SetIdleDevice(Idle, true); + } + if (hwciadapter && !hwciadapter->SetIdle(Idle, false)) + return false; + if (!cDvbDevice::SetIdleDevice(Idle, false)) { + if (hwciadapter) + hwciadapter->SetIdle(!Idle, false); + return false; + } + if (Idle) { + if (fd_ca >= 0) + close(fd_ca); + fd_ca = -1; + } + else { + if (fd_ca < 0) + fd_ca = cScDevices::DvbOpen(DEV_DVB_CA,adapter,frontend,O_RDWR); + } + return true; +} +#endif + bool cScDevice::HasCi(void) { return ciadapter || hwciadapter; @@ -1631,6 +1711,7 @@ bool cScDevice::SetCaDescr(ca_descr_t *ca_descr, bool initial) #ifndef SASC if(!softcsa || (fullts && ca_descr->index==0)) { cMutexLock lock(&cafdMutex); + if(fd_ca < 0) return false; return ioctl(fd_ca,CA_SET_DESCR,ca_descr)>=0; } else if(decsa) return decsa->SetDescr(ca_descr,initial); @@ -1643,6 +1724,7 @@ bool cScDevice::SetCaPid(ca_pid_t *ca_pid) #ifndef SASC if(!softcsa || (fullts && ca_pid->index==0)) { cMutexLock lock(&cafdMutex); + if(fd_ca < 0) return false; return ioctl(fd_ca,CA_SET_PID,ca_pid)>=0; } else if(decsa) return decsa->SetCaPid(ca_pid); @@ -1677,6 +1759,7 @@ static void av7110_write(int fd, unsigned int addr, unsigned int val) void cScDevice::DumpAV7110(void) { + if(fd_ca < 0) return; #ifndef SASC if(LOG(L_CORE_AV7110)) { #define CODEBASE (0x2e000404+0x1ce00) diff --git a/device.h b/device.h index 5ad83f9..93392a1 100644 --- a/device.h +++ b/device.h @@ -88,9 +88,12 @@ public: // ---------------------------------------------------------------- +class cScDevice; + class cScDevices : public cDvbDevice { private: static int budget; + static int skipAdapter; public: #if APIVERSNUM >= 10711 // make compiler happy. These are never used! cScDevices(void):cDvbDevice(0,0) {} @@ -103,9 +106,16 @@ public: static void Startup(void); static void Shutdown(void); static void SetForceBudget(int n); + static void SetSkipAdapter(int adapter); static bool ForceBudget(int n); + static bool SkipAdapter(int adapter); static void DvbName(const char *Name, int a, int f, char *buffer, int len); static int DvbOpen(const char *Name, int a, int f, int Mode, bool ReportError=false); + + static int numScDevices; + static cScDevice *scdevice[MAXDEVICES]; + static cScDevice *GetScDevice(int CardIndex); + static bool autoLateInit; }; // ---------------------------------------------------------------- @@ -123,6 +133,8 @@ private: bool softcsa, fullts; cMutex cafdMutex; cTimeMs lastDump; + int index; + bool lateInit; // #ifndef SASC void LateInit(void); @@ -147,6 +159,9 @@ public: #endif //SASC virtual bool SetCaDescr(ca_descr_t *ca_descr, bool initial); virtual bool SetCaPid(ca_pid_t *ca_pid); +#ifdef __DYNAMIC_DEVICE_PROBE + virtual bool SetIdleDevice(bool Idle, bool TestOnly); +#endif int FilterHandle(void); void DumpAV7110(void); cCam *Cam(void) { return cam; } diff --git a/sc.c b/sc.c index 82960bf..e33d99b 100644 --- a/sc.c +++ b/sc.c @@ -1009,7 +1009,7 @@ void cSoftCAM::Shutdown(void) char *cSoftCAM::CurrKeyStr(int CardNum, int num) { - cScDevice *dev=dynamic_cast(cDevice::GetDevice(CardNum)); + cScDevice *dev=cScDevices::GetScDevice(CardNum); char *str=0; if(dev) { if(dev->Cam()) str=dev->Cam()->CurrentKeyStr(num); @@ -1020,8 +1020,8 @@ char *cSoftCAM::CurrKeyStr(int CardNum, int num) bool cSoftCAM::Active(bool log) { - for(int n=cDevice::NumDevices(); --n>=0;) { - cScDevice *dev=dynamic_cast(cDevice::GetDevice(n)); + for(int n=cScDevices::numScDevices; --n>=0;) { + cScDevice *dev=cScDevices::scdevice[n]; if(dev && dev->Cam() && dev->Cam()->Active(log)) return true; } return false; @@ -1029,33 +1029,33 @@ bool cSoftCAM::Active(bool log) void cSoftCAM::SetLogStatus(int CardNum, const cEcmInfo *ecm, bool on) { - cScDevice *dev=dynamic_cast(cDevice::GetDevice(CardNum)); + cScDevice *dev=cScDevices::GetScDevice(CardNum); if(dev && dev->Cam()) dev->Cam()->LogEcmStatus(ecm,on); } void cSoftCAM::AddHook(int CardNum, cLogHook *hook) { - cScDevice *dev=dynamic_cast(cDevice::GetDevice(CardNum)); + cScDevice *dev=cScDevices::GetScDevice(CardNum); if(dev && dev->Cam()) dev->Cam()->AddHook(hook); } bool cSoftCAM::TriggerHook(int CardNum, int id) { - cScDevice *dev=dynamic_cast(cDevice::GetDevice(CardNum)); + cScDevice *dev=cScDevices::GetScDevice(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)); + for(int n=cScDevices::numScDevices; --n>=0;) { + cScDevice *dev=cScDevices::scdevice[n]; if(dev) dev->CaidsChanged(); } } int cSoftCAM::FilterHandle(int CardNum) { - cScDevice *dev=dynamic_cast(cDevice::GetDevice(CardNum)); + cScDevice *dev=cScDevices::GetScDevice(CardNum); return dev ? dev->FilterHandle() : -1; } @@ -1086,8 +1086,8 @@ 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)); + for(int n=cScDevices::numScDevices; --n>=0;) { + cScDevice *dev=cScDevices::scdevice[n]; if(dev && dev->Cam()) dev->Cam()->HouseKeeping(); } } @@ -1339,6 +1339,7 @@ const char *cScPlugin::CommandLineHelp(void) free(help_str); // for easier orientation, this is column 80| help_str=bprintf( " -B N --budget=N forces DVB device N to budget mode (using FFdecsa)\n" " -E CMD --external-au=CMD script for external key updates\n" + " -S N --skip=N skip DVB adapter N\n" ); return help_str; } @@ -1348,14 +1349,16 @@ bool cScPlugin::ProcessArgs(int argc, char *argv[]) static struct option long_options[] = { { "external-au", required_argument, NULL, 'E' }, { "budget", required_argument, NULL, 'B' }, + { "skip", required_argument, NULL, 'S' }, { NULL } }; int c, option_index=0; - while((c=getopt_long(argc,argv,"B:E:",long_options,&option_index))!=-1) { + while((c=getopt_long(argc,argv,"B:E:S:",long_options,&option_index))!=-1) { switch (c) { case 'E': externalAU=optarg; break; case 'B': cScDevices::SetForceBudget(atoi(optarg)); break; + case 'S': cScDevices::SetSkipAdapter(atoi(optarg)); break; default: return false; } }