-C fixes for V1 drivers
[enigma2.git] / lib / dvb / frontend.cpp
index c8d6d15fe074879200f0f49b5285162c56c8ba5a..9f19ada1154ea8800df886400420aa94fd59cbb1 100644 (file)
@@ -371,9 +371,42 @@ RESULT eDVBFrontendParameters::getHash(unsigned long &hash) const
        }
        case iDVBFrontend::feCable:
                hash = 0xFFFF0000;
+               hash |= (cable.frequency/1000)&0xFFFF;
                return 0;
        case iDVBFrontend::feTerrestrial:
                hash = 0xEEEE0000;
+               hash |= (terrestrial.frequency/1000)&0xFFFF;
+               return 0;
+       default:
+               return -1;
+       }
+}
+
+RESULT eDVBFrontendParameters::calcLockTimeout(unsigned int &timeout) const
+{
+       switch (m_type)
+       {
+       case iDVBFrontend::feSatellite:
+       {
+                       /* high symbol rate transponders tune faster, due to 
+                               requiring less zigzag and giving more symbols faster. 
+
+                               5s are definitely not enough on really low SR when
+                               zigzag has to find the exact frequency first.
+                       */
+               if (sat.symbol_rate > 20000000)
+                       timeout = 5000;
+               else if (sat.symbol_rate > 10000000)
+                       timeout = 10000;
+               else
+                       timeout = 20000;
+               return 0;
+       }
+       case iDVBFrontend::feCable:
+               timeout = 5000;
+               return 0;
+       case iDVBFrontend::feTerrestrial:
+               timeout = 5000;
                return 0;
        default:
                return -1;
@@ -506,7 +539,7 @@ int eDVBFrontend::closeFrontend()
                                m_dvbid, linked_fe->m_frontend->getDVBID(), linked_fe->m_frontend->getSlotID());
                        return -1;
                }
-               linked_fe->m_frontend->getData(LINKED_NEXT_PTR, (int&)linked_fe);
+               linked_fe->m_frontend->getData(LINKED_NEXT_PTR, (long&)linked_fe);
        }
        if (m_fd >= 0)
        {
@@ -751,8 +784,8 @@ void PutToDict(ePyObject &dict, const char*key, const char *value)
 
 void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, eDVBFrontend *fe)
 {
-       int freq_offset=0;
-       int csw=0;
+       long freq_offset=0;
+       long csw=0;
        const char *tmp=0;
        fe->getData(eDVBFrontend::CSW, csw);
        fe->getData(eDVBFrontend::FREQ_OFFSET, freq_offset);
@@ -836,7 +869,11 @@ void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, e
 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
 {
        const char *tmp=0;
+#if HAVE_DVB_API_VERSION < 3
+       PutToDict(dict, "frequency", parm_frequency);
+#else
        PutToDict(dict, "frequency", parm_frequency/1000);
+#endif
        PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
        switch(parm_u_qam_fec_inner)
        {
@@ -1159,21 +1196,34 @@ void eDVBFrontend::getFrontendData(ePyObject dest)
 int eDVBFrontend::readInputpower()
 {
        int power=m_slotid;  // this is needed for read inputpower from the correct tuner !
-
-       // open front prozessor
-       int fp=::open("/dev/dbox/fp0", O_RDWR);
-       if (fp < 0)
+       char proc_name[64];
+       sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
+       FILE *f=fopen(proc_name, "r");
+       if (f)
        {
-               eDebug("couldn't open fp");
-               return -1;
+               if (fscanf(f, "%08x", &power) != 1)
+                       eDebug("read %s failed!! (%m)", proc_name);
+               else
+                       eDebug("%s is %d\n", proc_name, power);
+               fclose(f);
        }
-       static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
-       if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
+       else
        {
-               eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
-               return -1;
+               // open front prozessor
+               int fp=::open("/dev/dbox/fp0", O_RDWR);
+               if (fp < 0)
+               {
+                       eDebug("couldn't open fp");
+                       return -1;
+               }
+               static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
+               if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
+               {
+                       eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
+                       return -1;
+               }
+               ::close(fp);
        }
-       ::close(fp);
 
        return power;
 }
@@ -1211,14 +1261,14 @@ void eDVBFrontend::setRotorData(int pos, int cmd)
        else
        {
                eDVBRegisteredFrontend *next = (eDVBRegisteredFrontend *)m_data[LINKED_NEXT_PTR];
-               while ( (int)next != -1 )
+               while ( (long)next != -1 )
                {
                        next->m_frontend->m_data[ROTOR_CMD] = cmd;
                        next->m_frontend->m_data[ROTOR_POS] = pos;
                        next = (eDVBRegisteredFrontend *)next->m_frontend->m_data[LINKED_NEXT_PTR];
                }
                eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)m_data[LINKED_PREV_PTR];
-               while ( (int)prev != -1 )
+               while ( (long)prev != -1 )
                {
                        prev->m_frontend->m_data[ROTOR_CMD] = cmd;
                        prev->m_frontend->m_data[ROTOR_POS] = pos;
@@ -1304,9 +1354,11 @@ void eDVBFrontend::tuneLoop()  // called by m_tuneTimer
                                ++m_sec_sequence.current();
                                break;
                        case eSecCommand::START_TUNE_TIMEOUT:
-                               m_timeout->start(5000, 1); // 5 sec timeout. TODO: symbolrate dependent
+                       {
+                               m_timeout->start(m_sec_sequence.current()->timeout, 1);
                                ++m_sec_sequence.current();
                                break;
+                       }
                        case eSecCommand::SET_TIMEOUT:
                                m_timeoutCount = m_sec_sequence.current()++->val;
                                eDebug("[SEC] set timeout %d", m_timeoutCount);
@@ -1428,7 +1480,7 @@ void eDVBFrontend::tuneLoop()  // called by m_tuneTimer
                                break;
                        case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
                                setRotorData(m_data[NEW_ROTOR_POS], m_data[NEW_ROTOR_CMD]);
-                               eDebug("[SEC] update current rotorparams %d %04x %d", m_timeoutCount, m_data[ROTOR_CMD], m_data[ROTOR_POS]);
+                               eDebug("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, m_data[ROTOR_CMD], m_data[ROTOR_POS]);
                                ++m_sec_sequence.current();
                                break;
                        case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
@@ -1446,37 +1498,37 @@ void eDVBFrontend::tuneLoop()  // called by m_tuneTimer
                                break;
                        case eSecCommand::SET_POWER_LIMITING_MODE:
                        {
-                               if (!m_need_rotor_workaround)
-                                       break;
-
-                               char dev[16];
-
-                               // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
-                               if (m_slotid < 2)
-                                       sprintf(dev, "/dev/i2c/%d", m_slotid);
-                               else if (m_slotid == 2)
-                                       sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
-                               else if (m_slotid == 3)
-                                       sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
-                               int fd = ::open(dev, O_RDWR);
-
-                               unsigned char data[2];
-                               ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
-                               if(::read(fd, data, 1) != 1)
-                                       eDebug("[SEC] error read lnbp (%m)");
-                               if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
+                               if (m_need_rotor_workaround)
                                {
-                                       data[0] |= 0x80;  // enable static current limiting
-                                       eDebug("[SEC] set static current limiting");
-                               }
-                               else
-                               {
-                                       data[0] &= ~0x80;  // enable dynamic current limiting
-                                       eDebug("[SEC] set dynamic current limiting");
+                                       char dev[16];
+
+                                       // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
+                                       if (m_slotid < 2)
+                                               sprintf(dev, "/dev/i2c/%d", m_slotid);
+                                       else if (m_slotid == 2)
+                                               sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
+                                       else if (m_slotid == 3)
+                                               sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
+                                       int fd = ::open(dev, O_RDWR);
+
+                                       unsigned char data[2];
+                                       ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
+                                       if(::read(fd, data, 1) != 1)
+                                               eDebug("[SEC] error read lnbp (%m)");
+                                       if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
+                                       {
+                                               data[0] |= 0x80;  // enable static current limiting
+                                               eDebug("[SEC] set static current limiting");
+                                       }
+                                       else
+                                       {
+                                               data[0] &= ~0x80;  // enable dynamic current limiting
+                                               eDebug("[SEC] set dynamic current limiting");
+                                       }
+                                       if(::write(fd, data, 1) != 1)
+                                               eDebug("[SEC] error write lnbp (%m)");
+                                       ::close(fd);
                                }
-                               if(::write(fd, data, 1) != 1)
-                                       eDebug("[SEC] error write lnbp (%m)");
-                               ::close(fd);
                                ++m_sec_sequence.current();
                                break;
                        }
@@ -1509,7 +1561,7 @@ RESULT eDVBFrontend::getFrontendType(int &t)
        return 0;
 }
 
-RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm)
+RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
 {
        int res;
        if (!m_sec)
@@ -1517,7 +1569,7 @@ RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm)
                eWarning("no SEC module active!");
                return -ENOENT;
        }
-       res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid);
+       res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
        if (!res)
        {
                eDebug("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
@@ -1623,7 +1675,11 @@ RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm)
 
 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
 {
+#if HAVE_DVB_API_VERSION < 3
+       parm_frequency = feparm.frequency;
+#else
        parm_frequency = feparm.frequency * 1000;
+#endif
        parm_u_qam_symbol_rate = feparm.symbol_rate;
        switch (feparm.modulation)
        {
@@ -1848,6 +1904,7 @@ RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial
 
 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
 {
+       unsigned int timeout = 5000;
        eDebug("(%d)tune", m_dvbid);
 
        m_timeout->stop();
@@ -1870,6 +1927,8 @@ RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
        m_sn->stop();
        m_sec_sequence.clear();
 
+       where.calcLockTimeout(timeout);
+
        switch (m_type)
        {
        case feSatellite:
@@ -1882,7 +1941,7 @@ RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
                        goto tune_error;
                }
                m_sec->setRotorMoving(false);
-               res=prepare_sat(feparm);
+               res=prepare_sat(feparm, timeout);
                if (res)
                        goto tune_error;
 
@@ -1900,7 +1959,7 @@ RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
                if (res)
                        goto tune_error;
 
-               m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT) );
+               m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
                m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
                break;
        }
@@ -1920,7 +1979,7 @@ RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
                std::string enable_5V;
                char configStr[255];
                snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
-               m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT) );
+               m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
                ePythonConfigQuery::getConfigValue(configStr, enable_5V);
                if (enable_5V == "True")
                        m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
@@ -2100,7 +2159,7 @@ RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
        return 0;
 }
 
-RESULT eDVBFrontend::getData(int num, int &data)
+RESULT eDVBFrontend::getData(int num, long &data)
 {
        if ( num < NUM_DATA_ENTRIES )
        {
@@ -2110,7 +2169,7 @@ RESULT eDVBFrontend::getData(int num, int &data)
        return -EINVAL;
 }
 
-RESULT eDVBFrontend::setData(int num, int val)
+RESULT eDVBFrontend::setData(int num, long val)
 {
        if ( num < NUM_DATA_ENTRIES )
        {