for cards like Cine-C/T with multiple frontends but only one shared demux/dvr

Message ID 4EBB0680.8020108@flensrocker.de
State New
Headers

Commit Message

L. Hanisch Nov. 9, 2011, 11:02 p.m. UTC
  Hi,

  Since the driver doesn't allow to create only the frontend of the desired delivery type, here's a patch for 
cDvbDevice. If there's no demux/dvr device with the frontend number it looks for one with a lower number.
  Now it's possible to use "-D 0" for DVB-C or "-D 1" for DVB-T (change device numbers to your setup).

  Of course the dynamite-plugin can also be used. Just set "dynamite_attach=no" at the unwanted frontend with a udev 
rule (please look at the dynamite README).

  It's not really tested, since I have not such a card, but the patch is almost trivial. Feedback is welcome.

  I hope the dvb/v4l developers will someday agree on a standard layout for hybrid tuners...

Regards,
Lars.
  

Patch

diff --git a/dvbdevice.c b/dvbdevice.c
index a97f274..459bf9a 100644
--- a/dvbdevice.c
+++ b/dvbdevice.c
@@ -781,7 +781,7 @@  const char *DeliverySystems[] = {
 cDvbDevice::cDvbDevice(int Adapter, int Frontend)
 {
   adapter = Adapter;
-  frontend = Frontend;
+  demux = dvr = frontend = Frontend;
   ciAdapter = NULL;
   dvbTuner = NULL;
   frontendType = SYS_UNDEFINED;
@@ -804,6 +804,26 @@  cDvbDevice::cDvbDevice(int Adapter, int Frontend)
   // We only check the devices that must be present - the others will be checked before accessing them://XXX
 
   if (fd_frontend >= 0) {
+     // workaround vor Cine-C/T-cards which creates multiple mutually exclusive frontends with only one demux/dvr
+     while ((demux >= 0) && !Exists(DEV_DVB_DEMUX, adapter, demux))
+           demux--;
+     if (demux < 0) {
+        demux = frontend;
+        esyslog("frontend %d/%d has no demux device", adapter, frontend);
+        }
+     else if (demux != frontend)
+        isyslog("frontend %d/%d will use demux%d", adapter, frontend, demux);
+
+     while ((dvr >= 0) && !Exists(DEV_DVB_DVR, adapter, dvr))
+           dvr--;
+     if (dvr < 0) {
+        dvr = frontend;
+        esyslog("frontend %d/%d has no dvr device", adapter, frontend);
+        }
+     else if (dvr != frontend)
+        isyslog("frontend %d/%d will use dvr%d", adapter, frontend, dvr);
+     // end workaround
+
      if (ioctl(fd_frontend, FE_GET_INFO, &frontendInfo) >= 0) {
         switch (frontendInfo.type) {
           case FE_QPSK: frontendType = (frontendInfo.caps & FE_CAN_2G_MODULATION) ? SYS_DVBS2 : SYS_DVBS; break;
@@ -869,7 +889,12 @@  int cDvbDevice::DvbOpen(const char *Name, int Adapter, int Frontend, int Mode, b
 
 bool cDvbDevice::Exists(int Adapter, int Frontend)
 {
-  cString FileName = DvbName(DEV_DVB_FRONTEND, Adapter, Frontend);
+  return Exists(DEV_DVB_FRONTEND, Adapter, Frontend);
+}
+
+bool cDvbDevice::Exists(const char *Name, int Adapter, int Frontend)
+{
+  cString FileName = DvbName(Name, Adapter, Frontend);
   if (access(FileName, F_OK) == 0) {
      int f = open(FileName, O_RDONLY);
      if (f >= 0) {
@@ -952,7 +977,7 @@  bool cDvbDevice::SetPid(cPidHandle *Handle, int Type, bool On)
      memset(&pesFilterParams, 0, sizeof(pesFilterParams));
      if (On) {
         if (Handle->handle < 0) {
-           Handle->handle = DvbOpen(DEV_DVB_DEMUX, adapter, frontend, O_RDWR | O_NONBLOCK, true);
+           Handle->handle = DvbOpen(DEV_DVB_DEMUX, adapter, demux, O_RDWR | O_NONBLOCK, true);
            if (Handle->handle < 0) {
               LOG_ERROR;
               return false;
@@ -987,7 +1012,7 @@  bool cDvbDevice::SetPid(cPidHandle *Handle, int Type, bool On)
 
 int cDvbDevice::OpenFilter(u_short Pid, u_char Tid, u_char Mask)
 {
-  cString FileName = DvbName(DEV_DVB_DEMUX, adapter, frontend);
+  cString FileName = DvbName(DEV_DVB_DEMUX, adapter, demux);
   int f = open(FileName, O_RDWR | O_NONBLOCK);
   if (f >= 0) {
      dmx_sct_filter_params sctFilterParams;
@@ -1131,7 +1156,7 @@  void cDvbDevice::SetTransferModeForDolbyDigital(int Mode)
 bool cDvbDevice::OpenDvr(void)
 {
   CloseDvr();
-  fd_dvr = DvbOpen(DEV_DVB_DVR, adapter, frontend, O_RDONLY | O_NONBLOCK, true);
+  fd_dvr = DvbOpen(DEV_DVB_DVR, adapter, dvr, O_RDONLY | O_NONBLOCK, true);
   if (fd_dvr >= 0)
      tsBuffer = new cTSBuffer(fd_dvr, MEGABYTE(2), CardIndex() + 1);
   return fd_dvr >= 0;
diff --git a/dvbdevice.h b/dvbdevice.h
index e1842b7..1eb8cf2 100644
--- a/dvbdevice.h
+++ b/dvbdevice.h
@@ -106,6 +106,7 @@  protected:
   static cString DvbName(const char *Name, int Adapter, int Frontend);
   static int DvbOpen(const char *Name, int Adapter, int Frontend, int Mode, bool ReportError = false);
 private:
+  static bool Exists(const char *Name, int Adapter, int Frontend);
   static bool Exists(int Adapter, int Frontend);
          ///< Checks whether the given adapter/frontend exists.
   static bool Probe(int Adapter, int Frontend);
@@ -116,7 +117,7 @@  public:
          ///< Must be called before accessing any DVB functions.
          ///< \return True if any devices are available.
 protected:
-  int adapter, frontend;
+  int adapter, frontend, demux, dvr;
 private:
   dvb_frontend_info frontendInfo;
   int numProvidedSystems;