]> www.vanbest.org Git - sasc-ng.git/commitdiff
VDR 1.7.11+ full-featured device support
authorleslie <unknown>
Sun, 14 Aug 2011 18:57:55 +0000 (20:57 +0200)
committerleslie <unknown>
Sun, 14 Aug 2011 18:57:55 +0000 (20:57 +0200)
Makefile
README
device-hd.c [new file with mode: 0644]
device-sd.c [new file with mode: 0644]
device-tmpl.c [new file with mode: 0644]
device.c
device.h
sc.c

index b9f303fc6861f0e4468712cff407a81b54c93059..643e7301fca15471473e44bfbf1436b96b1d9c37 100644 (file)
--- 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 6db76688f839b691aa65489e8181e2d6ed17c4c5..823c59974e19617f8fbafa7664f61f1ccaf4b548 100644 (file)
--- 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 (file)
index 0000000..78239d0
--- /dev/null
@@ -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 <stdlib.h>
+#include <stdio.h>
+
+#ifndef SASC
+
+#include <vdr/channels.h>
+#include <vdr/ci.h>
+#include <vdr/dvbci.h>
+
+#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<cScDvbHdFfDevice *>(dev);
+  if(d) d->LateInit();
+  return d!=0;
+}
+
+bool cScHdDevicePlugin::EarlyShutdown(cDevice *dev)
+{
+  cScDvbHdFfDevice *d=dynamic_cast<cScDvbHdFfDevice *>(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 (file)
index 0000000..38e7389
--- /dev/null
@@ -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 <stdlib.h>
+#include <stdio.h>
+
+#ifndef SASC
+
+#include <vdr/channels.h>
+#include <vdr/ci.h>
+#include <vdr/dvbci.h>
+
+#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<cScDvbSdFfDevice *>(dev);
+  if(d) d->LateInit();
+  return d!=0;
+}
+
+bool cScSdDevicePlugin::EarlyShutdown(cDevice *dev)
+{
+  cScDvbSdFfDevice *d=dynamic_cast<cScDvbSdFfDevice *>(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 (file)
index 0000000..8bf65be
--- /dev/null
@@ -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
index 33e154d26155b3ff33ae362ce59a114ef589d331..fb10406ebb70f4cf2c1485aba15b816c5460a518 100644 (file)
--- a/device.c
+++ b/device.c
 
 // -- 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<cScDevicePlugin> 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<cScDvbDevice *>(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<cScDvbDevice *>(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<cScDevice *>(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<cScDevice *>(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
index 737f1f9134cddc96b86b6ec6b42d8f321c51746d..78371844e77b8b1c4c17ae6b68f41be59d0d8fb4 100644 (file)
--- a/device.h
+++ b/device.h
 
 #include <vdr/dvbdevice.h>
 #include <vdr/thread.h>
+#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 f19928dd89ba11a0625d026e8bde7ecc3e22473b..099392c40006686c6e09bc43b332ad86a1fe01a1 100644 (file)
--- 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 ---------------------------------------------------------------