From f694ef8d2eb7a8c65684e34cf68b365d680df026 Mon Sep 17 00:00:00 2001 From: leslie Date: Sun, 14 Aug 2011 20:57:55 +0200 Subject: [PATCH] VDR 1.7.11+ full-featured device support --- Makefile | 25 ++++- README | 12 +++ device-hd.c | 92 ++++++++++++++++++ device-sd.c | 101 +++++++++++++++++++ device-tmpl.c | 180 ++++++++++++++++++++++++++++++++++ device.c | 262 ++++++++++++++++++-------------------------------- device.h | 76 ++++++++------- sc.c | 41 ++++++-- 8 files changed, 579 insertions(+), 210 deletions(-) create mode 100644 device-hd.c create mode 100644 device-sd.c create mode 100644 device-tmpl.c diff --git a/Makefile b/Makefile index b9f303f..643e730 100644 --- a/Makefile +++ b/Makefile @@ -117,6 +117,17 @@ ifdef WITH_PCSC LIBS += -lpcsclite endif +HAVE_SD := $(wildcard ../dvbsddevice/dvbsddevice.c) +ifneq ($(strip $(HAVE_SD)),) + DEFINES += -DWITH_SDDVB + DEVPLUGTARGETS += $(LIBDIR)/libsc-dvbsddevice-$(SCAPIVERS).so.$(APIVERSION) +endif +HAVE_HD := $(wildcard ../dvbhddevice/dvbhddevice.c) +ifneq ($(strip $(HAVE_HD)),) + DEFINES += -DWITH_HDDVB + DEVPLUGTARGETS += $(LIBDIR)/libsc-dvbhddevice-$(SCAPIVERS).so.$(APIVERSION) +endif + # max number of CAIDs per slot MAXCAID := $(shell sed -ne '/define MAXCASYSTEMIDS/ s/^.[a-zA-Z ]*\([0-9]*\).*$$/\1/p' $(VDRDIR)/ci.c) ifneq ($(strip $(MAXCAID)),) @@ -153,7 +164,7 @@ ifdef STATIC BUILDTARGETS = $(LIBDIR)/libvdr-$(PLUGIN).a SHAREDDEFINES += -DSTATICBUILD else -BUILDTARGETS = $(LIBDIR)/libvdr-$(PLUGIN).so.$(APIVERSION) systems-pre +BUILDTARGETS = $(LIBDIR)/libvdr-$(PLUGIN).so.$(APIVERSION) systems-pre $(DEVPLUGTARGETS) endif BUILDTARGETS += $(FFDECSATEST) systems i18n @@ -184,6 +195,18 @@ $(LIBDIR)/libvdr-$(PLUGIN).so.$(APIVERSION): libvdr-$(PLUGIN).so $(LIBDIR)/libvdr-$(PLUGIN).a: $(OBJS) $(AR) r $@ $(OBJS) +libsc-dvbsddevice.so: device-sd.o + $(CXX) $(CXXFLAGS) -shared $< $(SHAREDLIBS) -o $@ + +$(LIBDIR)/libsc-dvbsddevice-$(SCAPIVERS).so.$(APIVERSION): libsc-dvbsddevice.so + @cp -p $< $@ + +libsc-dvbhddevice.so: device-hd.o + $(CXX) $(CXXFLAGS) -shared $< $(SHAREDLIBS) -o $@ + +$(LIBDIR)/libsc-dvbhddevice-$(SCAPIVERS).so.$(APIVERSION): libsc-dvbhddevice.so + @cp -p $< $@ + $(FFDECSA) $(FFDECSATEST): $(FFDECSADIR)/*.c $(FFDECSADIR)/*.h @$(MAKE) COMPILER="$(CXX)" FLAGS="$(CSAFLAGS) -march=$(CPUOPT)" PARALLEL_MODE=$(PARALLEL) -C $(FFDECSADIR) all diff --git a/README b/README index 6db7668..823c599 100644 --- a/README +++ b/README @@ -70,6 +70,18 @@ this means to install openssl-devel package. You should use a openssl package with AES and IDEA enabled, as support for openssl without these will be removed in the near future. +**** VDR 1.7.11+ notes **** +If you want to use VDR 1.7.11+ together with a full-featured DVB card: +- the source code for the dvbhddevice and/or dvbsddevice has to be available in + the VDR plugin source directory, i.e. at the parent directory level of this + plugin source. The presence of these plugin sources will be detected + automatically and support for them will be enabled at compile time. +- the compiled dvbhddevice and/or dvbsddevice plugin libraries (i.e. the *.so + files) have to be available in the VDR plugin library directory at runtime. +- DO NOT load the dvbhddevice and/or dvbsddevice on the VDR commandline (i.e. + with parameter -P). They will be loaded internaly from this plugin. It will + not work correctly if you load them from commandline! + Now follow the VDR instruction to compile plugins (make plugins). Beside the core plugin (libvdr-sc.so), the make process (if successfull) creates an additional shared library object for every supported system (libsc-*.so). You diff --git a/device-hd.c b/device-hd.c new file mode 100644 index 0000000..78239d0 --- /dev/null +++ b/device-hd.c @@ -0,0 +1,92 @@ +/* + * 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 +#include + +#ifndef SASC + +#include +#include +#include + +#include "device.h" +#include "cam.h" +#include "scsetup.h" +#include "log-core.h" +#include "version.h" + +SCAPIVERSTAG(); + +#if APIVERSNUM >= 10711 +#ifdef WITH_HDDVB + +// -- cScDvbSdFfDevice --------------------------------------------------------- + +#include "../dvbhddevice/dvbhdffdevice.h" +#define SCDEVICE cScDvbHdFfDevice +#define DVBDEVICE cDvbHdFfDevice +#include "device-tmpl.c" +#undef SCDEVICE +#undef DVBDEVICE + +// -- cScHdDevicePlugin -------------------------------------------------------- + +class cScHdDevicePlugin : public cScDevicePlugin { +public: + virtual cDevice *Probe(int Adapter, int Frontend, uint32_t SubSystemId); + virtual bool LateInit(cDevice *dev); + virtual bool EarlyShutdown(cDevice *dev); + }; + +static cScHdDevicePlugin _hddevplugin; + +cDevice *cScHdDevicePlugin::Probe(int Adapter, int Frontend, uint32_t SubSystemId) +{ + static uint32_t SubsystemIds[] = { + 0x13C23009, // Technotrend S2-6400 HDFF development samples + 0x13C2300A, // Technotrend S2-6400 HDFF production version + 0x00000000 + }; + for(uint32_t *sid=SubsystemIds; *sid; sid++) { + if(*sid==SubSystemId) { + PRINTF(L_GEN_DEBUG,"creating HD-FF device %d/%d",Adapter,Frontend); + return new cScDvbHdFfDevice(Adapter,Frontend,cScDevices::DvbOpen(DEV_DVB_CA,Adapter,Frontend,O_RDWR)); + } + } + return 0; +} + +bool cScHdDevicePlugin::LateInit(cDevice *dev) +{ + cScDvbHdFfDevice *d=dynamic_cast(dev); + if(d) d->LateInit(); + return d!=0; +} + +bool cScHdDevicePlugin::EarlyShutdown(cDevice *dev) +{ + cScDvbHdFfDevice *d=dynamic_cast(dev); + if(d) d->EarlyShutdown(); + return d!=0; +} + +#endif //WITH_HDDVB +#endif //APIVERSNUM >= 10711 +#endif //SASC diff --git a/device-sd.c b/device-sd.c new file mode 100644 index 0000000..38e7389 --- /dev/null +++ b/device-sd.c @@ -0,0 +1,101 @@ +/* + * 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 +#include + +#ifndef SASC + +#include +#include +#include + +#include "device.h" +#include "cam.h" +#include "scsetup.h" +#include "log-core.h" +#include "version.h" + +SCAPIVERSTAG(); + +#if APIVERSNUM >= 10711 +#ifdef WITH_SDDVB + +// -- cScDvbSdFfDevice --------------------------------------------------------- + +#include "../dvbsddevice/dvbsdffdevice.h" +#define SCDEVICE cScDvbSdFfDevice +#define DVBDEVICE cDvbSdFfDevice +#include "device-tmpl.c" +#undef SCDEVICE +#undef DVBDEVICE + +// -- cScSdDevicePlugin -------------------------------------------------------- + +class cScSdDevicePlugin : public cScDevicePlugin { +public: + virtual cDevice *Probe(int Adapter, int Frontend, uint32_t SubSystemId); + virtual bool LateInit(cDevice *dev); + virtual bool EarlyShutdown(cDevice *dev); + }; + +static cScSdDevicePlugin _sddevplugin; + +cDevice *cScSdDevicePlugin::Probe(int Adapter, int Frontend, uint32_t SubSystemId) +{ + static uint32_t SubsystemIds[] = { + 0x110A0000, // Fujitsu Siemens DVB-C + 0x13C20000, // Technotrend/Hauppauge WinTV DVB-S rev1.X or Fujitsu Siemens DVB-C + 0x13C20001, // Technotrend/Hauppauge WinTV DVB-T rev1.X + 0x13C20002, // Technotrend/Hauppauge WinTV DVB-C rev2.X + 0x13C20003, // Technotrend/Hauppauge WinTV Nexus-S rev2.X + 0x13C20004, // Galaxis DVB-S rev1.3 + 0x13C20006, // Fujitsu Siemens DVB-S rev1.6 + 0x13C20008, // Technotrend/Hauppauge DVB-T + 0x13C2000A, // Technotrend/Hauppauge WinTV Nexus-CA rev1.X + 0x13C2000E, // Technotrend/Hauppauge WinTV Nexus-S rev2.3 + 0x13C21002, // Technotrend/Hauppauge WinTV DVB-S rev1.3 SE + 0x00000000 + }; + for(uint32_t *sid=SubsystemIds; *sid; sid++) { + if(*sid==SubSystemId) { + PRINTF(L_GEN_DEBUG,"creating SD-FF device %d/%d",Adapter,Frontend); + return new cScDvbSdFfDevice(Adapter,Frontend,cScDevices::DvbOpen(DEV_DVB_CA,Adapter,Frontend,O_RDWR)); + } + } + return 0; +} + +bool cScSdDevicePlugin::LateInit(cDevice *dev) +{ + cScDvbSdFfDevice *d=dynamic_cast(dev); + if(d) d->LateInit(); + return d!=0; +} + +bool cScSdDevicePlugin::EarlyShutdown(cDevice *dev) +{ + cScDvbSdFfDevice *d=dynamic_cast(dev); + if(d) d->EarlyShutdown(); + return d!=0; +} + +#endif //WITH_SDDVB +#endif //APIVERSNUM >= 10711 +#endif //SASC diff --git a/device-tmpl.c b/device-tmpl.c new file mode 100644 index 0000000..8bf65be --- /dev/null +++ b/device-tmpl.c @@ -0,0 +1,180 @@ +/* + * 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 + */ + +// -- cScDevice ---------------------------------------------------------------- + +class SCDEVICE : public DVBDEVICE { +private: + cDeCsaTSBuffer *tsBuffer; + cMutex tsMutex; + cCam *cam; + cCiAdapter *hwciadapter; + int fd_dvr, fd_ca, fd_ca2; + bool softcsa, fullts; + char devId[8]; + // +#ifndef SASC + bool ScActive(void); +#endif //SASC +protected: +#ifndef SASC + virtual bool Ready(void); + virtual bool SetPid(cPidHandle *Handle, int Type, bool On); + virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView); + virtual bool OpenDvr(void); + virtual void CloseDvr(void); + virtual bool GetTSPacket(uchar *&Data); +#endif //SASC +public: + SCDEVICE(int Adapter, int Frontend, int cafd); + ~SCDEVICE(); +#ifndef SASC + virtual bool HasCi(void); + void LateInit(void); + void EarlyShutdown(void); +#endif //SASC + }; + +SCDEVICE::SCDEVICE(int Adapter, int Frontend, int cafd) +#if APIVERSNUM >= 10711 +:DVBDEVICE(Adapter,Frontend) +#else +:DVBDEVICE(Adapter) +#endif +{ + tsBuffer=0; softcsa=fullts=false; + cam=0; hwciadapter=0; + fd_ca=cafd; fd_ca2=dup(fd_ca); fd_dvr=-1; +#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 +} + +SCDEVICE::~SCDEVICE() +{ +#ifndef SASC + DetachAllReceivers(); + Cancel(3); + EarlyShutdown(); + if(fd_ca>=0) close(fd_ca); + if(fd_ca2>=0) close(fd_ca2); +#else + delete cam; +#endif // !SASC +} + +#ifndef SASC + +void SCDEVICE::EarlyShutdown(void) +{ + SetCamSlot(0); + delete cam; cam=0; + delete hwciadapter; hwciadapter=0; +} + +void SCDEVICE::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 %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 %s",devId); + softcsa=true; + } + if(softcsa) { + if(IsPrimaryDevice() && HasDecoder()) { + 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 %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 SCDEVICE::HasCi(void) +{ + return cam || hwciadapter; +} + +bool SCDEVICE::Ready(void) +{ + return (cam ? cam->Ready():true) && + (hwciadapter ? hwciadapter->Ready():true); +} + +bool SCDEVICE::SetPid(cPidHandle *Handle, int Type, bool On) +{ + if(cam) cam->SetPid(Type,Handle->pid,On); + tsMutex.Lock(); + if(tsBuffer) tsBuffer->SetActive(ScActive()); + tsMutex.Unlock(); + return DVBDEVICE::SetPid(Handle,Type,On); +} + +bool SCDEVICE::SetChannelDevice(const cChannel *Channel, bool LiveView) +{ + if(cam) cam->Tune(Channel); + bool ret=DVBDEVICE::SetChannelDevice(Channel,LiveView); + if(ret && cam) cam->PostTune(); + return ret; +} + +bool SCDEVICE::ScActive(void) +{ + return cam && cam->OwnSlot(CamSlot()); +} + +bool SCDEVICE::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(); + } + return fd_dvr>=0; +} + +void SCDEVICE::CloseDvr(void) +{ + tsMutex.Lock(); + delete tsBuffer; tsBuffer=0; + tsMutex.Unlock(); + if(fd_dvr>=0) { close(fd_dvr); fd_dvr=-1; } +} + +bool SCDEVICE::GetTSPacket(uchar *&Data) +{ + if(tsBuffer) { Data=tsBuffer->Get(); return true; } + return false; +} + +#endif // !SASC diff --git a/device.c b/device.c index 33e154d..fb10406 100644 --- a/device.c +++ b/device.c @@ -45,24 +45,6 @@ // -- cDeCsaTSBuffer ----------------------------------------------------------- -class cDeCsaTSBuffer : public cThread { -private: - int f; - int cardIndex, size; - bool delivered; - cRingBufferLinear *ringBuffer; - // - cDeCSA *decsa; - bool scActive; - // - virtual void Action(void); -public: - cDeCsaTSBuffer(int File, int Size, int CardIndex, cDeCSA *DeCsa, bool ScActive); - ~cDeCsaTSBuffer(); - uchar *Get(void); - void SetActive(bool ScActive); - }; - cDeCsaTSBuffer::cDeCsaTSBuffer(int File, int Size, int CardIndex, cDeCSA *DeCsa, bool ScActive) { SetDescription("TS buffer on device %d", CardIndex); @@ -137,13 +119,58 @@ uchar *cDeCsaTSBuffer::Get(void) return NULL; } -// --- cScDeviceProbe ---------------------------------------------------------- +// --- cScDevicePlugin --------------------------------------------------------- + +static cSimpleList devplugins; + +cScDevicePlugin::cScDevicePlugin(void) +{ + devplugins.Add(this); +} + +cScDevicePlugin::~cScDevicePlugin() +{ + devplugins.Del(this,false); +} + +// -- cScDvbDevice ------------------------------------------------------------- + +#define SCDEVICE cScDvbDevice +#define DVBDEVICE cDvbDevice +#include "device-tmpl.c" +#undef SCDEVICE +#undef DVBDEVICE + +// -- cScDvbDevicePlugin ------------------------------------------------------- + +class cScDvbDevicePlugin : public cScDevicePlugin { +public: + virtual cDevice *Probe(int Adapter, int Frontend, uint32_t SubSystemId); + virtual bool LateInit(cDevice *dev); + virtual bool EarlyShutdown(cDevice *dev); + }; + +cDevice *cScDvbDevicePlugin::Probe(int Adapter, int Frontend, uint32_t SubSystemId) +{ + PRINTF(L_GEN_DEBUG,"creating standard device %d/%d",Adapter,Frontend); + return new cScDvbDevice(Adapter,Frontend,cScDevices::DvbOpen(DEV_DVB_CA,Adapter,Frontend,O_RDWR)); +} + +bool cScDvbDevicePlugin::LateInit(cDevice *dev) +{ + cScDvbDevice *d=dynamic_cast(dev); + if(d) d->LateInit(); + return d!=0; +} -#define DEV_DVB_ADAPTER "/dev/dvb/adapter" -#define DEV_DVB_FRONTEND "frontend" -#define DEV_DVB_DVR "dvr" -#define DEV_DVB_DEMUX "demux" -#define DEV_DVB_CA "ca" +bool cScDvbDevicePlugin::EarlyShutdown(cDevice *dev) +{ + cScDvbDevice *d=dynamic_cast(dev); + if(d) d->EarlyShutdown(); + return d!=0; +} + +// --- cScDeviceProbe ---------------------------------------------------------- #if APIVERSNUM >= 10711 @@ -154,6 +181,9 @@ public: virtual bool Probe(int Adapter, int Frontend); static void Install(void); static void Remove(void); +#if APIVERSNUM < 10719 + uint32_t GetSubsystemId(int Adapter, int Frontend); +#endif }; cScDeviceProbe *cScDeviceProbe::probe=0; @@ -170,11 +200,37 @@ void cScDeviceProbe::Remove(void) bool cScDeviceProbe::Probe(int Adapter, int Frontend) { - 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; + uint32_t subid=GetSubsystemId(Adapter,Frontend); + PRINTF(L_GEN_DEBUG,"capturing device %d/%d (subsystem ID %08x)",Adapter,Frontend,subid); + for(cScDevicePlugin *dp=devplugins.First(); dp; dp=devplugins.Next(dp)) + if(dp->Probe(Adapter,Frontend,subid)) return true; + return false; } -#endif + +#if APIVERSNUM < 10719 +uint32_t cScDeviceProbe::GetSubsystemId(int Adapter, int Frontend) +{ + cString FileName; + cReadLine ReadLine; + FILE *f = NULL; + uint32_t SubsystemId = 0; + FileName = cString::sprintf("/sys/class/dvb/dvb%d.frontend%d/device/subsystem_vendor", Adapter, Frontend); + if ((f = fopen(FileName, "r")) != NULL) { + if (char *s = ReadLine.Read(f)) + SubsystemId = strtoul(s, NULL, 0) << 16; + fclose(f); + } + FileName = cString::sprintf("/sys/class/dvb/dvb%d.frontend%d/device/subsystem_device", Adapter, Frontend); + if ((f = fopen(FileName, "r")) != NULL) { + if (char *s = ReadLine.Read(f)) + SubsystemId |= strtoul(s, NULL, 0); + fclose(f); + } + return SubsystemId; +} +#endif //APIVERSNUM < 10719 + +#endif //APIVERSNUM >= 10711 // -- cScDevices --------------------------------------------------------------- @@ -225,6 +281,8 @@ void cScDevices::OnPluginLoad(void) #endif if(vdr_nci && vdr_ud) { vdr_save_ud=*vdr_ud; *vdr_ud=1<<30; } #endif + // default device plugin must be last in the list + new cScDvbDevicePlugin; } void cScDevices::OnPluginUnload(void) @@ -260,7 +318,7 @@ bool cScDevices::Initialize(void) if(f>=0) { close(f); PRINTF(L_GEN_DEBUG,"capturing device %d",i); - new cScDevice(i,0,cScDevices::DvbOpen(DEV_DVB_CA,i,0,O_RDWR)); + devplugins.First()->Probe(i,0,0); found++; } else { @@ -287,16 +345,18 @@ void cScDevices::Startup(void) if(ScSetup.ForceTransfer) SetTransferModeForDolbyDigital(2); for(int n=cDevice::NumDevices(); --n>=0;) { - cScDevice *dev=dynamic_cast(cDevice::GetDevice(n)); - if(dev) dev->LateInit(); + cDevice *dev=cDevice::GetDevice(n); + for(cScDevicePlugin *dp=devplugins.First(); dp; dp=devplugins.Next(dp)) + if(dp->LateInit(dev)) break; } } void cScDevices::Shutdown(void) { for(int n=cDevice::NumDevices(); --n>=0;) { - cScDevice *dev=dynamic_cast(cDevice::GetDevice(n)); - if(dev) dev->EarlyShutdown(); + cDevice *dev=cDevice::GetDevice(n); + for(cScDevicePlugin *dp=devplugins.First(); dp; dp=devplugins.Next(dp)) + if(dp->EarlyShutdown(dev)) break; } } @@ -321,139 +381,3 @@ void cScDevices::SetForceBudget(int n) {} bool cScDevices::ForceBudget(int n) { return true; } #endif //SASC - -// -- cScDevice ---------------------------------------------------------------- - -#if APIVERSNUM >= 10711 -#define DVB_DEV_SPEC adapter,frontend -#else -#define DVB_DEV_SPEC CardIndex(),0 -#endif - -cScDevice::cScDevice(int Adapter, int Frontend, int cafd) -#if APIVERSNUM >= 10711 -:cDvbDevice(Adapter,Frontend) -#else -:cDvbDevice(Adapter) -#endif -{ - tsBuffer=0; softcsa=fullts=false; - cam=0; hwciadapter=0; - fd_ca=cafd; fd_ca2=dup(fd_ca); fd_dvr=-1; -#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() -{ -#ifndef SASC - DetachAllReceivers(); - Cancel(3); - EarlyShutdown(); - if(fd_ca>=0) close(fd_ca); - if(fd_ca2>=0) close(fd_ca2); -#else - delete cam; -#endif // !SASC -} - -#ifndef SASC - -void cScDevice::EarlyShutdown(void) -{ - SetCamSlot(0); - delete cam; cam=0; - delete hwciadapter; hwciadapter=0; -} - -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 %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 %s",devId); - softcsa=true; - } - if(softcsa) { - if(IsPrimaryDevice() && HasDecoder()) { - 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 %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 cam || hwciadapter; -} - -bool cScDevice::Ready(void) -{ - return (cam ? cam->Ready():true) && - (hwciadapter ? hwciadapter->Ready():true); -} - -bool cScDevice::SetPid(cPidHandle *Handle, int Type, bool On) -{ - if(cam) cam->SetPid(Type,Handle->pid,On); - tsMutex.Lock(); - if(tsBuffer) tsBuffer->SetActive(ScActive()); - tsMutex.Unlock(); - return cDvbDevice::SetPid(Handle,Type,On); -} - -bool cScDevice::SetChannelDevice(const cChannel *Channel, bool LiveView) -{ - if(cam) cam->Tune(Channel); - bool ret=cDvbDevice::SetChannelDevice(Channel,LiveView); - if(ret && cam) cam->PostTune(); - return ret; -} - -bool cScDevice::ScActive(void) -{ - return cam && cam->OwnSlot(CamSlot()); -} - -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(); - } - return fd_dvr>=0; -} - -void cScDevice::CloseDvr(void) -{ - tsMutex.Lock(); - delete tsBuffer; tsBuffer=0; - tsMutex.Unlock(); - if(fd_dvr>=0) { close(fd_dvr); fd_dvr=-1; } -} - -bool cScDevice::GetTSPacket(uchar *&Data) -{ - if(tsBuffer) { Data=tsBuffer->Get(); return true; } - return false; -} - -#endif // !SASC diff --git a/device.h b/device.h index 737f1f9..7837184 100644 --- a/device.h +++ b/device.h @@ -22,11 +22,44 @@ #include #include +#include "misc.h" -class cCam; class cDeCSA; -class cDeCsaTSBuffer; -class cScCiAdapter; + +// ---------------------------------------------------------------- + +#define DEV_DVB_ADAPTER "/dev/dvb/adapter" +#define DEV_DVB_FRONTEND "frontend" +#define DEV_DVB_DVR "dvr" +#define DEV_DVB_DEMUX "demux" +#define DEV_DVB_CA "ca" +#define DEV_DVB_OSD "osd" + +#if APIVERSNUM >= 10711 +#define DVB_DEV_SPEC adapter,frontend +#else +#define DVB_DEV_SPEC CardIndex(),0 +#endif + +// ---------------------------------------------------------------- + +class cDeCsaTSBuffer : public cThread { +private: + int f; + int cardIndex, size; + bool delivered; + cRingBufferLinear *ringBuffer; + // + cDeCSA *decsa; + bool scActive; + // + virtual void Action(void); +public: + cDeCsaTSBuffer(int File, int Size, int CardIndex, cDeCSA *DeCsa, bool ScActive); + ~cDeCsaTSBuffer(); + uchar *Get(void); + void SetActive(bool ScActive); + }; // ---------------------------------------------------------------- @@ -52,38 +85,13 @@ public: // ---------------------------------------------------------------- -class cScDevice : public cDvbDevice { -friend class cScDevices; -private: - cDeCsaTSBuffer *tsBuffer; - cMutex tsMutex; - cCam *cam; - cCiAdapter *hwciadapter; - int fd_dvr, fd_ca, fd_ca2; - bool softcsa, fullts; - char devId[8]; - // -#ifndef SASC - void LateInit(void); - void EarlyShutdown(void); - bool ScActive(void); -#endif //SASC - // -protected: -#ifndef SASC - virtual bool Ready(void); - virtual bool SetPid(cPidHandle *Handle, int Type, bool On); - virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView); - virtual bool OpenDvr(void); - virtual void CloseDvr(void); - virtual bool GetTSPacket(uchar *&Data); -#endif //SASC +class cScDevicePlugin : public cSimpleItem { public: - cScDevice(int Adapter, int Frontend, int cafd); - ~cScDevice(); -#ifndef SASC - virtual bool HasCi(void); -#endif //SASC + cScDevicePlugin(void); + virtual ~cScDevicePlugin(); + virtual cDevice *Probe(int Adapter, int Frontend, uint32_t SubSystemId)=0; + virtual bool LateInit(cDevice *dev)=0; + virtual bool EarlyShutdown(cDevice *dev)=0; }; #endif // ___DEVICE_H diff --git a/sc.c b/sc.c index f19928d..099392c 100644 --- a/sc.c +++ b/sc.c @@ -1066,7 +1066,7 @@ private: public: cScDll(const char *FileName); ~cScDll(); - bool Load(void); + bool Load(bool check); }; cScDll::cScDll(const char *FileName) @@ -1081,14 +1081,15 @@ cScDll::~cScDll() free(fileName); } -bool cScDll::Load(void) +bool cScDll::Load(bool check) { char *base=rindex(fileName,'/'); if(base) base++; else base=fileName; PRINTF(L_CORE_DYN,"loading library: %s",base); if(!handle) { - handle=dlopen(fileName,RTLD_NOW|RTLD_LOCAL); + handle=dlopen(fileName,RTLD_NOW|(check?RTLD_LOCAL:RTLD_GLOBAL)); if(handle) { + if(!check) return true; dlerror(); int *libapivers=(int *)dlsym(handle,"ScLibApiVersion"); const char *error=dlerror(); @@ -1102,6 +1103,7 @@ bool cScDll::Load(void) // --- cScDlls ----------------------------------------------------------------- +#define LIBVDR_PREFIX "libvdr-" #define LIBSC_PREFIX "libsc-" #define SO_INDICATOR ".so." @@ -1148,7 +1150,34 @@ bool cScDlls::Load(void) if((p=rindex(path,'/'))) *p=0; PRINTF(L_CORE_DYN,"library path %sn",path); - char pat[32]; + char pat[64]; +#if APIVERSNUM >= 10711 +#ifdef WITH_SDDVB + { + snprintf(pat,sizeof(pat),"%s%s%s%s",LIBVDR_PREFIX,"dvbsddevice",SO_INDICATOR,APIVERSION); + cScDll *dll=new cScDll(AddDirectory(path,pat)); + if(dll) { + if(dll->Load(false)) { + PRINTF(L_GEN_INFO,"VDR dvbsddevice plugin loaded as subplugin"); + } + Ins(dll); + } + } +#endif //WITH_SDDVB +#ifdef WITH_HDDVB + { + snprintf(pat,sizeof(pat),"%s%s%s%s",LIBVDR_PREFIX,"dvbhddevice",SO_INDICATOR,APIVERSION); + cScDll *dll=new cScDll(AddDirectory(path,pat)); + if(dll) { + if(dll->Load(false)) { + PRINTF(L_GEN_INFO,"VDR dvbhddevice plugin loaded as subplugin"); + } + Ins(dll); + } + } +#endif //WITH_HDDVB +#endif //APIVERSNUM >= 10711 + snprintf(pat,sizeof(pat),"%s*-%d%s%s",LIBSC_PREFIX,SCAPIVERS,SO_INDICATOR,APIVERSION); bool res=true; cReadDir dir(path); @@ -1157,7 +1186,7 @@ bool cScDlls::Load(void) 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; + if(!dll->Load(true)) res=false; Ins(dll); } } @@ -1166,7 +1195,7 @@ bool cScDlls::Load(void) return res; } -#endif +#endif //STATICBUILD // --- cScPlugin --------------------------------------------------------------- -- 2.39.5