non blocking diseqc and sec stuff
authorAndreas Monzner <andreas.monzner@multimedia-labs.de>
Tue, 17 May 2005 17:33:14 +0000 (17:33 +0000)
committerAndreas Monzner <andreas.monzner@multimedia-labs.de>
Tue, 17 May 2005 17:33:14 +0000 (17:33 +0000)
lib/dvb/frontend.cpp
lib/dvb/frontend.h
lib/dvb/idvb.h
lib/dvb/sec.cpp
lib/dvb/sec.h

index 9ec9a9e35fef41b44de8bb8b2f57ebe424578aad..cdbf8a58f4cfebbc6a760def4d387888bf584e43 100644 (file)
@@ -277,10 +277,13 @@ eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok): m_type(-1)
        m_sn = new eSocketNotifier(eApp, m_fd, eSocketNotifier::Read);
        CONNECT(m_sn->activated, eDVBFrontend::feEvent);
        m_sn->start();
-       
+
        m_timeout = new eTimer(eApp);
        CONNECT(m_timeout->timeout, eDVBFrontend::timeout);
-       
+
+       m_tuneTimer = new eTimer(eApp);
+       CONNECT(m_tuneTimer->timeout, eDVBFrontend::tuneLoop);
+
        return;
 }
 
@@ -358,6 +361,59 @@ void eDVBFrontend::timeout()
                m_tuning = 0;
 }
 
+void eDVBFrontend::tuneLoop()  // called by m_tuneTimer
+{
+       int delay=0;
+       if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
+       {
+               switch (m_sec_sequence.current()->cmd)
+               {
+                       case eSecCommand::SLEEP:
+                               delay = m_sec_sequence.current()->msec;
+                               break;
+                       case eSecCommand::SET_VOLTAGE:
+                               setVoltage(m_sec_sequence.current()->voltage);
+                               break;
+                       case eSecCommand::SET_TONE:
+                               setTone(m_sec_sequence.current()->tone);
+                               break;
+                       case eSecCommand::SEND_DISEQC:
+                               sendDiseqc(m_sec_sequence.current()->diseqc);
+                               break;
+                       case eSecCommand::SEND_TONEBURST:
+                               sendToneburst(m_sec_sequence.current()->toneburst);
+                               break;
+                       case eSecCommand::SET_FRONTEND:
+                               setFrontend();
+                               break;
+                       case eSecCommand::IF_LOCK_GOTO:
+                       case eSecCommand::IF_NOT_LOCK_GOTO:
+                       default:
+                               eDebug("unhandled sec command");
+               }
+               m_sec_sequence.current()++;
+               m_tuneTimer->start(delay,true);
+       }
+}
+
+void eDVBFrontend::setFrontend()
+{
+       eDebug("setting frontend..\n");
+       if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
+       {
+               perror("FE_SET_FRONTEND failed");
+               return;
+       }
+
+       if (m_state != stateTuning)
+       {
+               m_tuning = 1;
+               m_state = stateTuning;
+               m_stateChanged(this);
+       }
+       m_timeout->start(5000, 1); // 5 sec timeout. TODO: symbolrate dependent
+}
+
 RESULT eDVBFrontend::getFrontendType(int &t)
 {
        if (m_type == -1)
@@ -371,12 +427,12 @@ RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
        if (m_type == -1)
                return -ENODEV;
 
-       FRONTENDPARAMETERS parm;
-
        feEvent(-1);
-       
+
+       m_sec_sequence.clear();
+
        eDebug("eDVBFrontend::tune. type: %d", m_type);
-       
+
        switch (m_type)
        {
        case feSatellite:
@@ -519,23 +575,10 @@ RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
                break;
        }
        }
-       
-       eDebug("setting frontend..\n");
-       
-       if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
-       {
-               perror("FE_SET_FRONTEND failed");
-               return errno;
-       }
-       
-       if (m_state != stateTuning)
-       {
-               m_tuning = 1;
-               m_state = stateTuning;
-               m_stateChanged(this);
-       }
-       
-       m_timeout->start(5000, 1); // 5 sec timeout. TODO: symbolrate dependent
+
+       m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 0) );
+       m_tuneTimer->start(0,true);
+       m_sec_sequence.current() = m_sec_sequence.begin();
 
        return 0;
 }
@@ -607,70 +650,45 @@ RESULT eDVBFrontend::setTone(int t)
 #endif
 }
 
+#if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
+       #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
+#endif
+
 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
 {
 #if HAVE_DVB_API_VERSION < 3
-       secCmdSequence seq;
-       secCommand cmd;
-
-       if ( diseqc.len > 3 )
-       {
-               seq.numCommands=1;
-               cmd.type = SEC_CMDTYPE_DISEQC_RAW;
-               cmd.u.diseqc.cmdtype = diseqc.data[0];
-               eDebug("cmdtype is %02x", diseqc.data[0]);
-               cmd.u.diseqc.addr = diseqc.data[1];
-               eDebug("cmdaddr is %02x", diseqc.data[1]);
-               cmd.u.diseqc.cmd = diseqc.data[2];
-               eDebug("cmd is %02x", diseqc.data[2]);
-               cmd.u.diseqc.numParams = diseqc.len-3;
-               eDebug("numparams %d", diseqc.len-3);
-
-               memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
-               for (int i=0; i < diseqc.len-3; ++i )
-                       eDebugNoNewLine("%02x ", diseqc.data[3+i]);
-               eDebug("");
-       }
-       else
-               seq.numCommands=0;
-
-       seq.continuousTone = diseqc.tone == toneOn ? SEC_TONE_ON : SEC_TONE_OFF;
-       switch ( diseqc.voltage )
-       {
-               case voltageOff:
-                       seq.voltage = SEC_VOLTAGE_OFF;
-                       break;
-               case voltage13:
-                       seq.voltage = SEC_VOLTAGE_13;
-                       break;
-               case voltage18:
-                       seq.voltage = SEC_VOLTAGE_18;
-                       break;
-       }
-       seq.miniCommand = SEC_MINI_NONE;
-       seq.commands=&cmd;
-
-       if ( ioctl(m_secfd, SEC_SEND_SEQUENCE, &seq) < 0 )
-       {
-               eDebug("SEC_SEND_SEQUENCE failed ( %m )");
-               return -EINVAL;
-       }
-       return 0;
+       struct secCommand cmd;
+       cmd.type = SEC_CMDTYPE_DISEQC_RAW;
+       cmd.u.diseqc.cmdtype = diseqc.data[0];
+       cmd.u.diseqc.addr = diseqc.data[1];
+       cmd.u.diseqc.cmd = diseqc.data[2];
+       cmd.u.diseqc.numParams = diseqc.len-3;
+       memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
+       if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
 #else
-       if ( !diseqc.len )
-               return 0;
        struct dvb_diseqc_master_cmd cmd;
-       if (::ioctl(m_fd, FE_SET_TONE, SEC_TONE_OFF))
-               return -EINVAL;
-       usleep(15 * 1000);
        memcpy(cmd.msg, diseqc.data, diseqc.len);
        cmd.msg_len = diseqc.len;
-       
        if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
+#endif
+               return -EINVAL;
+       return 0;
+}
+
+#if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
+       #define SEC_DISEQC_SEND_BURST _IO('o', 96)
+#endif
+RESULT eDVBFrontend::sendToneburst(int burst)
+{
+#if HAVE_DVB_API_VERSION < 3
+       secMiniCmd cmd = SEC_MINI_NONE;
+       if ( burst == eDVBSatelliteDiseqcParameters::A )
+               cmd = SEC_MINI_A;
+       else if ( burst == eDVBSatelliteDiseqcParameters::B )
+               cmd = SEC_MINI_B;
+       if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
                return -EINVAL;
-       usleep(15 * 1000);
 #endif
-       eDebug("diseqc ok");
        return 0;
 }
 
@@ -679,3 +697,9 @@ RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
        m_sec = sec;
        return 0;
 }
+
+RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
+{
+       m_sec_sequence = list;
+       return 0;
+}
index f4e99fae3b626a3d471fc5df7a30aece0e2eca71..1a68f89e2e1d61578fc3b8eafd7c2fc00d5aa469 100644 (file)
@@ -3,6 +3,9 @@
 
 #include <config.h>
 #include <lib/dvb/idvb.h>
+#include <lib/dvb/sec.h>
+
+class eSecCommandList;
 
 class eDVBFrontendParameters: public iDVBFrontendParameters
 {
@@ -39,15 +42,20 @@ class eDVBFrontend: public iDVBFrontend, public Object
 #if HAVE_DVB_API_VERSION < 3
        int m_secfd;
 #endif
+       FRONTENDPARAMETERS parm;
        int m_state;
        Signal1<void,iDVBFrontend*> m_stateChanged;
        ePtr<iDVBSatelliteEquipmentControl> m_sec;
        eSocketNotifier *m_sn;
        int m_tuning;
        eTimer *m_timeout;
-       
+       eTimer *m_tuneTimer;
+
        void feEvent(int);
        void timeout();
+       eSecCommandList m_sec_sequence;
+       void tuneLoop();  // called by m_tuneTimer
+       void setFrontend();
 public:
        eDVBFrontend(int adap, int fe, int &ok);        
        virtual ~eDVBFrontend();
@@ -59,7 +67,9 @@ public:
        RESULT setTone(int tone);
        RESULT setVoltage(int voltage);
        RESULT sendDiseqc(const eDVBDiseqcCommand &diseqc);
+       RESULT sendToneburst(int burst);
        RESULT setSEC(iDVBSatelliteEquipmentControl *sec);
+       RESULT setSecSequence(const eSecCommandList &list);
 };
 
 #endif
index ef052d42eddfc9145e4d9750a4b7a768451aa3f6..638aef91a42e47c39df4cc8b2cedfd3cfe8cba92 100644 (file)
@@ -361,6 +361,7 @@ public:
 };
 
 class iDVBSatelliteEquipmentControl;
+class eSecCommandList;
 
 class iDVBFrontend: public iObject
 {
@@ -387,7 +388,9 @@ public:
        };
        virtual RESULT setVoltage(int voltage)=0;
        virtual RESULT sendDiseqc(const eDVBDiseqcCommand &diseqc)=0;
+       virtual RESULT sendToneburst(int burst)=0;
        virtual RESULT setSEC(iDVBSatelliteEquipmentControl *sec)=0;
+       virtual RESULT setSecSequence(const eSecCommandList &list)=0;
 };
 
 class iDVBSatelliteEquipmentControl: public iObject
index a90e1c0ddb899373226e220e94b582b034c994f0..78e5949e4e7be3bcbe933fb09958965c3efeb674 100644 (file)
@@ -1,13 +1,11 @@
 #include <config.h>
 #include <lib/dvb/sec.h>
 #if HAVE_DVB_API_VERSION < 3
-#include <ost/frontend.h>
 #define INVERSION Inversion
 #define FREQUENCY Frequency
 #define FEC_INNER FEC_inner
 #define SYMBOLRATE SymbolRate
 #else
-#include <linux/dvb/frontend.h>
 #define INVERSION inversion
 #define FREQUENCY frequency
 #define FEC_INNER fec_inner
@@ -25,7 +23,7 @@ eDVBSatelliteEquipmentControl::eDVBSatelliteEquipmentControl()
        eDVBSatelliteDiseqcParameters &diseqc_ref = astra1.m_diseqc_parameters;
        eDVBSatelliteSwitchParameters &switch_ref = astra1.m_switch_parameters;
 
-       lnb_ref.m_lof_hi = 10600000;
+       lnb_ref.m_lof_hi = 10607000;
        lnb_ref.m_lof_lo = 9750000;
        lnb_ref.m_lof_threshold = 11700000;
 
@@ -96,37 +94,58 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA
                                || ( sw_param.m_22khz_signal == eDVBSatelliteSwitchParameters::HILO && !hi ) )
                                tone = iDVBFrontend::toneOff;
 
-                       eDVBDiseqcCommand diseqc;
+                       eSecCommandList sec_sequence;
 
-#if HAVE_DVB_API_VERSION < 3
-                       diseqc.voltage = voltage;
-                       diseqc.tone = tone;
-#else
-                       frontend.setVoltage(voltage);
-#endif
-
-                       if ( di_param.m_commited_cmd < eDVBSatelliteDiseqcParameters::NO )
+                       if ( di_param.m_diseqc_mode == eDVBSatelliteDiseqcParameters::V1_2 )
                        {
-                               diseqc.len = 4;
-                               diseqc.data[0] = 0xe0;
-                               diseqc.data[1] = 0x10;
-                               diseqc.data[2] = 0x38;
-                               diseqc.data[3] = di_param.m_commited_cmd;
-
-                               if (hi)
-                                       diseqc.data[3] |= 1;
-
-                               if (sat.polarisation == eDVBFrontendParametersSatellite::Polarisation::Horizontal)
-                                       diseqc.data[3] |= 2;
+                               eDebug("rotor...");
+                       }
+                       else if (di_param.m_diseqc_mode >= eDVBSatelliteDiseqcParameters::V1_0)
+                       {
+                               if ( di_param.m_commited_cmd < eDVBSatelliteDiseqcParameters::SENDNO ||
+                                       di_param.m_toneburst_param != eDVBSatelliteDiseqcParameters::NO )
+                               {
+                                       sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
+                                       sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, voltage) );
+                                       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 30) );
+                               }
+
+                               if ( di_param.m_commited_cmd < eDVBSatelliteDiseqcParameters::SENDNO )
+                               {
+                                       eDVBDiseqcCommand diseqc;
+                                       diseqc.len = 4;
+                                       diseqc.data[0] = 0xe0;
+                                       diseqc.data[1] = 0x10;
+                                       diseqc.data[2] = 0x38;
+                                       diseqc.data[3] = 0xF0 | (di_param.m_commited_cmd << 2);
+
+                                       if (hi)
+                                               diseqc.data[3] |= 1;
+
+                                       if (sat.polarisation == eDVBFrontendParametersSatellite::Polarisation::Horizontal)
+                                               diseqc.data[3] |= 2;
+
+                                       sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
+                                       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 30) );
+                               }
+
+                               if ( di_param.m_toneburst_param != eDVBSatelliteDiseqcParameters::NO )
+                               {
+                                       sec_sequence.push_back( eSecCommand(eSecCommand::SEND_TONEBURST, di_param.m_toneburst_param) );
+                                       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 30) );
+                               }
                        }
                        else
-                               diseqc.len = 0;
+                       {
+                               sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, voltage) );
+                               sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 10) );
+                       }
 
-                       frontend.sendDiseqc(diseqc);
+                       sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, tone) );
+                       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 15) );
+
+                       frontend.setSecSequence(sec_sequence);
 
-#if HAVE_DVB_API_VERSION > 2
-                       frontend.setTone(tone);
-#endif
                        return 0;
                }
        }
index 6ce1349295076fdd08b25517efee2fab66f2698b..6b205a9dceb7bb9ee3459c9fd169c0c6def9d0ba 100644 (file)
@@ -3,6 +3,77 @@
 
 #include <config.h>
 #include <lib/dvb/idvb.h>
+#include <list>
+
+class eSecCommand
+{
+public:
+       enum {
+               NONE, SLEEP, SET_VOLTAGE, SET_TONE, SEND_DISEQC, SEND_TONEBURST, IF_LOCK_GOTO, IF_NOT_LOCK_GOTO, SET_FRONTEND
+       };
+       int cmd;
+       union
+       {
+               int voltage;
+               int tone;
+               int toneburst;
+               int msec;
+               eDVBDiseqcCommand diseqc;
+       };
+       eSecCommand( int cmd, int val )
+               :cmd(cmd), voltage(val)
+       {}
+       eSecCommand( int cmd, eDVBDiseqcCommand diseqc )
+               :cmd(cmd), diseqc(diseqc)
+       {}
+       eSecCommand()
+               :cmd(NONE)
+       {}
+};
+
+class eSecCommandList
+{
+       std::list<eSecCommand> secSequence;
+       std::list<eSecCommand>::iterator cur;
+public:
+       eSecCommandList()
+               :cur(secSequence.end())
+       {
+       }
+       void push_front(const eSecCommand &cmd)
+       {
+               secSequence.push_front(cmd);
+       }
+       void push_back(const eSecCommand &cmd)
+       {
+               secSequence.push_back(cmd);
+       }
+       void clear()
+       {
+               secSequence.clear();
+               cur=secSequence.end();
+       }
+       inline std::list<eSecCommand>::iterator &current()
+       {
+               return cur;
+       }
+       inline std::list<eSecCommand>::iterator begin()
+       {
+               return secSequence.begin();
+       }
+       inline std::list<eSecCommand>::iterator end()
+       {
+               return secSequence.end();
+       }
+       int size() const
+       {
+               return secSequence.size();
+       }
+       operator bool() const
+       {
+               return secSequence.size();
+       }
+};
 
 class eDVBSatelliteDiseqcParameters
 {