Merge branch 'master' into experimental
[enigma2.git] / lib / dvb / frontend.cpp
index 519b5fee87255b9874bb8da20eb8d99f1932d552..ebdad8a7599e734b0d6902df8deaee096ba715c0 100644 (file)
@@ -582,7 +582,7 @@ int eDVBFrontend::openFrontend()
        return 0;
 }
 
-int eDVBFrontend::closeFrontend(bool force)
+int eDVBFrontend::closeFrontend(bool force, bool no_delayed)
 {
        if (!force && m_data[CUR_VOLTAGE] != -1 && m_data[CUR_VOLTAGE] != iDVBFrontend::voltageOff)
        {
@@ -605,11 +605,34 @@ int eDVBFrontend::closeFrontend(bool force)
                eDebugNoSimulate("close frontend %d", m_dvbid);
                if (m_data[SATCR] != -1)
                {
-                       turnOffSatCR(m_data[SATCR]);
+                       if (!no_delayed)
+                       {
+                               m_sec->prepareTurnOffSatCR(*this, m_data[SATCR]);
+                               m_tuneTimer->start(0, true);
+                               if(!m_tuneTimer->isActive())
+                               {
+                                       int timeout=0;
+                                       eDebug("[turnOffSatCR] no mainloop");
+                                       while(true)
+                                       {
+                                               timeout = tuneLoopInt();
+                                               if (timeout == -1)
+                                                       break;
+                                               usleep(timeout*1000); // blockierendes wait.. eTimer gibts ja nicht mehr
+                                       }
+                               }
+                               else
+                                       eDebug("[turnOffSatCR] running mainloop");
+                               return 0;
+                       }
+                       else
+                               m_data[ROTOR_CMD] = -1;
                }
+
                setTone(iDVBFrontend::toneOff);
                setVoltage(iDVBFrontend::voltageOff);
                m_tuneTimer->stop();
+
                if (m_sec && !m_simulate)
                        m_sec->setRotorMoving(m_slotid, false);
                if (!::close(m_fd))
@@ -790,7 +813,7 @@ int eDVBFrontend::readFrontendData(int type)
                                        float fval1 = SDS_SNRE / 268435456.0,
                                                  fval2, fval3, fval4;
 
-                                       if (parm_u_qpsk_fec_inner <= FEC_S2_QPSK_9_10) // DVB-S2 QPSK
+                                       if (oparm.sat.modulation == eDVBFrontendParametersSatellite::Modulation_QPSK)
                                        {
                                                fval2 = 6.76;
                                                fval3 = 4.35;
@@ -883,6 +906,19 @@ int eDVBFrontend::readFrontendData(int type)
                        }
                        else if (strstr(m_description, "BCM4506") || strstr(m_description, "BCM4505"))
                                ret = (snr * 100) >> 8;
+                       else if (!strcmp(m_description, "CXD1981"))
+                       {
+                               int mse = (~snr) & 0xFF;
+                               switch (parm_u_qam_modulation) {
+                                       case QAM_16:
+                                       case QAM_64:
+                                       case QAM_256: ret = (int)(-950 * log(((double)mse) / 760)); break;
+                                       case QAM_32:
+                                       case QAM_128: ret = (int)(-875 * log(((double)mse) / 650)); break;
+
+                                       default: break;
+                               }
+                       }
 
                        if (type == signalQuality)
                        {
@@ -1489,9 +1525,14 @@ bool eDVBFrontend::setSecSequencePos(int steps)
        return true;
 }
 
-void eDVBFrontend::tuneLoop()  // called by m_tuneTimer
+void eDVBFrontend::tuneLoop()
 {
-       int delay=0;
+       tuneLoopInt();
+}
+
+int eDVBFrontend::tuneLoopInt()  // called by m_tuneTimer
+{
+       int delay=-1;
        eDVBFrontend *sec_fe = this;
        eDVBRegisteredFrontend *regFE = 0;
        long tmp = m_data[LINKED_PREV_PTR];
@@ -1521,6 +1562,7 @@ void eDVBFrontend::tuneLoop()  // called by m_tuneTimer
        {
                long *sec_fe_data = sec_fe->m_data;
 //             eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
+               delay = 0;
                switch (m_sec_sequence.current()->cmd)
                {
                        case eSecCommand::SLEEP:
@@ -1847,6 +1889,13 @@ void eDVBFrontend::tuneLoop()  // called by m_tuneTimer
                                ++m_sec_sequence.current();
                                break;
                        }
+                       case eSecCommand::DELAYED_CLOSE_FRONTEND:
+                       {
+                               eDebugNoSimulate("[SEC] delayed close frontend");
+                               closeFrontend(false, true);
+                               ++m_sec_sequence.current();
+                               break;
+                       }
                        default:
                                eDebugNoSimulate("[SEC] unhandled sec command %d",
                                        ++m_sec_sequence.current()->cmd);
@@ -1859,6 +1908,7 @@ void eDVBFrontend::tuneLoop()  // called by m_tuneTimer
                regFE->dec_use();
        if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
                tuneLoop();
+       return delay;
 }
 
 void eDVBFrontend::setFrontend(bool recvEvents)
@@ -2594,9 +2644,12 @@ RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
        return 0;
 }
 
-RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
+RESULT eDVBFrontend::setSecSequence(eSecCommandList &list)
 {
-       m_sec_sequence = list;
+       if (m_data[SATCR] != -1 && m_sec_sequence.current() != m_sec_sequence.end())
+               m_sec_sequence.push_back(list);
+       else
+               m_sec_sequence = list;
        return 0;
 }
 
@@ -2647,17 +2700,23 @@ int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
 
 bool eDVBFrontend::setSlotInfo(ePyObject obj)
 {
-       ePyObject Id, Descr, Enabled, IsDVBS2;
-       if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4)
+       ePyObject Id, Descr, Enabled, IsDVBS2, frontendId;
+       if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 5)
                goto arg_error;
        Id = PyTuple_GET_ITEM(obj, 0);
        Descr = PyTuple_GET_ITEM(obj, 1);
        Enabled = PyTuple_GET_ITEM(obj, 2);
        IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
-       if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2))
+       frontendId = PyTuple_GET_ITEM(obj, 4);
+       m_slotid = PyInt_AsLong(Id);
+       if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2) || !PyInt_Check(frontendId))
                goto arg_error;
        strcpy(m_description, PyString_AS_STRING(Descr));
-       m_slotid = PyInt_AsLong(Id);
+       if (PyInt_AsLong(frontendId) == -1 || PyInt_AsLong(frontendId) != m_dvbid) {
+//             eDebugNoSimulate("skip slotinfo for slotid %d, descr %s",
+//                     m_slotid, m_description);
+               return false;
+       }
        m_enabled = Enabled == Py_True;
        // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
        m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
@@ -2673,42 +2732,3 @@ arg_error:
                "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");
        return false;
 }
-
-RESULT eDVBFrontend::turnOffSatCR(int satcr)
-{
-       eSecCommandList sec_sequence;
-       // check if voltage is disabled
-       eSecCommand::pair compare;
-       compare.steps = +9;     //nothing to do
-       compare.voltage = iDVBFrontend::voltageOff;
-       sec_sequence.push_back( eSecCommand(eSecCommand::IF_NOT_VOLTAGE_GOTO, compare) );
-       sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
-       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50 ) );
-
-       sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage18_5) );
-       sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
-       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 250) );
-
-       eDVBDiseqcCommand diseqc;
-       memset(diseqc.data, 0, MAX_DISEQC_LENGTH);
-       diseqc.len = 5;
-       diseqc.data[0] = 0xE0;
-       diseqc.data[1] = 0x10;
-       diseqc.data[2] = 0x5A;
-       diseqc.data[3] = satcr << 5;
-       diseqc.data[4] = 0x00;
-
-       sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
-       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50+20+14*diseqc.len) );
-       sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
-       setSecSequence(sec_sequence);
-       return 0;
-}
-
-RESULT eDVBFrontend::ScanSatCR()
-{
-       setFrontend();
-       usleep(20000);
-       setTone(iDVBFrontend::toneOff);
-       return 0;
-}