Remove check legacy dvbapi version.
[vuplus_dvbapp] / lib / dvb / frontend.cpp
index e980169..91c866c 100755 (executable)
@@ -1,3 +1,5 @@
+#include <linux/dvb/version.h>
+
 #include <lib/dvb/dvb.h>
 #include <lib/dvb/frontendparms.h>
 #include <lib/base/eerror.h>
 #define I2C_SLAVE_FORCE        0x0706
 #endif
 
-#if HAVE_DVB_API_VERSION < 3
-#include <ost/frontend.h>
-#include <ost/sec.h>
-#define QAM_AUTO                               (Modulation)6
-#define TRANSMISSION_MODE_AUTO (TransmitMode)2
-#define BANDWIDTH_AUTO                 (BandWidth)3
-#define GUARD_INTERVAL_AUTO            (GuardInterval)4
-#define HIERARCHY_AUTO                 (Hierarchy)4
-#define parm_frequency parm.Frequency
-#define parm_inversion parm.Inversion
-#define parm_u_qpsk_symbol_rate parm.u.qpsk.SymbolRate
-#define parm_u_qpsk_fec_inner parm.u.qpsk.FEC_inner
-#define parm_u_qam_symbol_rate parm.u.qam.SymbolRate
-#define parm_u_qam_fec_inner parm.u.qam.FEC_inner
-#define parm_u_qam_modulation parm.u.qam.QAM
-#define parm_u_ofdm_bandwidth parm.u.ofdm.bandWidth
-#define parm_u_ofdm_code_rate_LP parm.u.ofdm.LP_CodeRate
-#define parm_u_ofdm_code_rate_HP parm.u.ofdm.HP_CodeRate
-#define parm_u_ofdm_constellation parm.u.ofdm.Constellation
-#define parm_u_ofdm_transmission_mode parm.u.ofdm.TransmissionMode
-#define parm_u_ofdm_guard_interval parm.u.ofdm.guardInterval
-#define parm_u_ofdm_hierarchy_information parm.u.ofdm.HierarchyInformation
-#else
 #include <linux/dvb/frontend.h>
 #define parm_frequency parm.frequency
 #define parm_inversion parm.inversion
 #define parm_u_ofdm_transmission_mode parm.u.ofdm.transmission_mode
 #define parm_u_ofdm_guard_interval parm.u.ofdm.guard_interval
 #define parm_u_ofdm_hierarchy_information parm.u.ofdm.hierarchy_information
-#if HAVE_DVB_API_VERSION < 5
-       #define FEC_S2_QPSK_1_2 (fe_code_rate_t)(FEC_AUTO+1)
-       #define FEC_S2_QPSK_2_3 (fe_code_rate_t)(FEC_S2_QPSK_1_2+1)
-       #define FEC_S2_QPSK_3_4 (fe_code_rate_t)(FEC_S2_QPSK_2_3+1)
-       #define FEC_S2_QPSK_5_6 (fe_code_rate_t)(FEC_S2_QPSK_3_4+1)
-       #define FEC_S2_QPSK_7_8 (fe_code_rate_t)(FEC_S2_QPSK_5_6+1)
-       #define FEC_S2_QPSK_8_9 (fe_code_rate_t)(FEC_S2_QPSK_7_8+1)
-       #define FEC_S2_QPSK_3_5 (fe_code_rate_t)(FEC_S2_QPSK_8_9+1)
-       #define FEC_S2_QPSK_4_5 (fe_code_rate_t)(FEC_S2_QPSK_3_5+1)
-       #define FEC_S2_QPSK_9_10 (fe_code_rate_t)(FEC_S2_QPSK_4_5+1)
-       #define FEC_S2_8PSK_1_2 (fe_code_rate_t)(FEC_S2_QPSK_9_10+1)
-       #define FEC_S2_8PSK_2_3 (fe_code_rate_t)(FEC_S2_8PSK_1_2+1)
-       #define FEC_S2_8PSK_3_4 (fe_code_rate_t)(FEC_S2_8PSK_2_3+1)
-       #define FEC_S2_8PSK_5_6 (fe_code_rate_t)(FEC_S2_8PSK_3_4+1)
-       #define FEC_S2_8PSK_7_8 (fe_code_rate_t)(FEC_S2_8PSK_5_6+1)
-       #define FEC_S2_8PSK_8_9 (fe_code_rate_t)(FEC_S2_8PSK_7_8+1)
-       #define FEC_S2_8PSK_3_5 (fe_code_rate_t)(FEC_S2_8PSK_8_9+1)
-       #define FEC_S2_8PSK_4_5 (fe_code_rate_t)(FEC_S2_8PSK_3_5+1)
-       #define FEC_S2_8PSK_9_10 (fe_code_rate_t)(FEC_S2_8PSK_4_5+1)
-#else
-       #define FEC_S2_QPSK_1_2 (fe_code_rate_t)(FEC_1_2)
-       #define FEC_S2_QPSK_2_3 (fe_code_rate_t)(FEC_2_3)
-       #define FEC_S2_QPSK_3_4 (fe_code_rate_t)(FEC_3_4)
-       #define FEC_S2_QPSK_5_6 (fe_code_rate_t)(FEC_5_6)
-       #define FEC_S2_QPSK_7_8 (fe_code_rate_t)(FEC_7_8)
-       #define FEC_S2_QPSK_8_9 (fe_code_rate_t)(FEC_8_9)
-       #define FEC_S2_QPSK_3_5 (fe_code_rate_t)(FEC_3_5)
-       #define FEC_S2_QPSK_4_5 (fe_code_rate_t)(FEC_4_5)
-       #define FEC_S2_QPSK_9_10 (fe_code_rate_t)(FEC_9_10)
-#endif
-#endif
+#define FEC_S2_QPSK_1_2 (fe_code_rate_t)(FEC_1_2)
+#define FEC_S2_QPSK_2_3 (fe_code_rate_t)(FEC_2_3)
+#define FEC_S2_QPSK_3_4 (fe_code_rate_t)(FEC_3_4)
+#define FEC_S2_QPSK_5_6 (fe_code_rate_t)(FEC_5_6)
+#define FEC_S2_QPSK_7_8 (fe_code_rate_t)(FEC_7_8)
+#define FEC_S2_QPSK_8_9 (fe_code_rate_t)(FEC_8_9)
+#define FEC_S2_QPSK_3_5 (fe_code_rate_t)(FEC_3_5)
+#define FEC_S2_QPSK_4_5 (fe_code_rate_t)(FEC_4_5)
+#define FEC_S2_QPSK_9_10 (fe_code_rate_t)(FEC_9_10)
 
 #include <dvbsi++/satellite_delivery_system_descriptor.h>
 #include <dvbsi++/cable_delivery_system_descriptor.h>
@@ -213,27 +170,67 @@ void eDVBFrontendParametersCable::set(const CableDeliverySystemDescriptor &descr
 
 void eDVBFrontendParametersTerrestrial::set(const TerrestrialDeliverySystemDescriptor &descriptor)
 {
+       /* EN 300 468 V1.11.1 DVB-SI SPEC */
        frequency = descriptor.getCentreFrequency() * 10;
-       bandwidth = descriptor.getBandwidth();
-       if ( bandwidth > 2 ) // 5Mhz forced to auto
-               bandwidth = eDVBFrontendParametersTerrestrial::Bandwidth_Auto;
-       code_rate_HP = descriptor.getCodeRateHpStream();
-       if (code_rate_HP > 4)
-               code_rate_HP = eDVBFrontendParametersTerrestrial::FEC_Auto;
-       code_rate_LP = descriptor.getCodeRateLpStream();
-       if (code_rate_LP > 4)
-               code_rate_LP = eDVBFrontendParametersTerrestrial::FEC_Auto;
-       transmission_mode = descriptor.getTransmissionMode();
-       if (transmission_mode > 1) // TM4k forced to auto
-               transmission_mode = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto;
-       guard_interval = descriptor.getGuardInterval();
-       if (guard_interval > 3)
-               guard_interval = eDVBFrontendParametersTerrestrial::GuardInterval_Auto;
+       switch (descriptor.getBandwidth())
+       {
+               case 0: bandwidth = eDVBFrontendParametersTerrestrial::Bandwidth_8MHz; break;
+               case 1: bandwidth = eDVBFrontendParametersTerrestrial::Bandwidth_7MHz; break;
+               case 2: bandwidth = eDVBFrontendParametersTerrestrial::Bandwidth_6MHz; break;
+               case 3: bandwidth = eDVBFrontendParametersTerrestrial::Bandwidth_5MHz; break;
+               case 4: bandwidth = eDVBFrontendParametersTerrestrial::Bandwidth_10MHz; break;
+               case 5: bandwidth = eDVBFrontendParametersTerrestrial::Bandwidth_1_712MHz; break;
+               default: bandwidth = eDVBFrontendParametersTerrestrial::Bandwidth_Auto; break;
+       }
+       switch (descriptor.getCodeRateHpStream())
+       {
+               case 0: code_rate_HP = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
+               case 1: code_rate_HP = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
+               case 2: code_rate_HP = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
+               case 3: code_rate_HP = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
+               case 4: code_rate_HP = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
+               default: code_rate_HP = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
+       }
+       switch (descriptor.getCodeRateLpStream())
+       {
+               case 0: code_rate_LP = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
+               case 1: code_rate_LP = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
+               case 2: code_rate_LP = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
+               case 3: code_rate_LP = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
+               case 4: code_rate_LP = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
+               default: code_rate_LP = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
+       }
+       switch (descriptor.getTransmissionMode())
+       {
+               case 0: transmission_mode = eDVBFrontendParametersTerrestrial::TransmissionMode_2k; break;
+               case 1: transmission_mode = eDVBFrontendParametersTerrestrial::TransmissionMode_8k; break;
+               case 2: transmission_mode = eDVBFrontendParametersTerrestrial::TransmissionMode_4k; break;
+               case 3: transmission_mode = eDVBFrontendParametersTerrestrial::TransmissionMode_1k; break;
+               case 4: transmission_mode = eDVBFrontendParametersTerrestrial::TransmissionMode_16k; break;
+               case 5: transmission_mode = eDVBFrontendParametersTerrestrial::TransmissionMode_32k; break;
+               default: transmission_mode = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto; break;
+       }
+       switch (descriptor.getGuardInterval())
+       {
+               case 0: guard_interval = eDVBFrontendParametersTerrestrial::GuardInterval_1_32; break;
+               case 1: guard_interval = eDVBFrontendParametersTerrestrial::GuardInterval_1_16; break;
+               case 2: guard_interval = eDVBFrontendParametersTerrestrial::GuardInterval_1_8; break;
+               case 3: guard_interval = eDVBFrontendParametersTerrestrial::GuardInterval_1_4; break;
+               case 4: guard_interval = eDVBFrontendParametersTerrestrial::GuardInterval_1_128; break;
+               case 5: guard_interval = eDVBFrontendParametersTerrestrial::GuardInterval_19_128; break;
+               case 6: guard_interval = eDVBFrontendParametersTerrestrial::GuardInterval_19_256; break;
+               default: guard_interval = eDVBFrontendParametersTerrestrial::GuardInterval_Auto; break;
+       }
+//     hierarchy = descriptor.getHierarchyInformation();
        hierarchy = descriptor.getHierarchyInformation()&3;
+       if (hierarchy > eDVBFrontendParametersTerrestrial::Hierarchy_4)
+               hierarchy = eDVBFrontendParametersTerrestrial::Hierarchy_Auto;
        modulation = descriptor.getConstellation();
-       if (modulation > 2)
+       if (modulation > eDVBFrontendParametersTerrestrial::Modulation_QAM64)
                modulation = eDVBFrontendParametersTerrestrial::Modulation_Auto;
        inversion = eDVBFrontendParametersTerrestrial::Inversion_Unknown;
+       system = eDVBFrontendParametersTerrestrial::System_DVB_T;
+       plpid = 0;
        eDebug("Terr freq %d, bw %d, cr_hp %d, cr_lp %d, tm_mode %d, guard %d, hierarchy %d, const %d",
                frequency, bandwidth, code_rate_HP, code_rate_LP, transmission_mode,
                guard_interval, hierarchy, modulation);
@@ -248,10 +245,8 @@ DEFINE_REF(eDVBFrontendParameters);
 
 RESULT eDVBFrontendParameters::getSystem(int &t) const
 {
-       if (m_type == -1)
-               return -1;
        t = m_type;
-       return 0;
+       return (m_type == -1) ? -1 : 0;
 }
 
 RESULT eDVBFrontendParameters::getDVBS(eDVBFrontendParametersSatellite &p) const
@@ -357,7 +352,6 @@ RESULT eDVBFrontendParameters::calculateDifference(const iDVBFrontendParameters
                eDVBFrontendParametersTerrestrial oterrestrial;
                if (parm->getDVBT(oterrestrial))
                        return -2;
-
                if (exact && oterrestrial.bandwidth != terrestrial.bandwidth &&
                        oterrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth_Auto &&
                        terrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth_Auto)
@@ -386,6 +380,11 @@ RESULT eDVBFrontendParameters::calculateDifference(const iDVBFrontendParameters
                        oterrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC_Auto &&
                        terrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC_Auto)
                        diff = 1 << 30;
+               else if (oterrestrial.system != terrestrial.system)
+                       diff = 1 << 30;
+               else if (oterrestrial.system == terrestrial.System_DVB_T2 &&
+                       oterrestrial.plpid != terrestrial.plpid)
+                       diff = 1 << 30;
                else
                        diff = abs(terrestrial.frequency - oterrestrial.frequency) / 1000;
                return 0;
@@ -452,21 +451,15 @@ RESULT eDVBFrontendParameters::calcLockTimeout(unsigned int &timeout) const
 DEFINE_REF(eDVBFrontend);
 
 int eDVBFrontend::PriorityOrder=0;
+int eDVBFrontend::PreferredFrontendIndex=-1;
+
 
 eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok, bool simulate, eDVBFrontend *simulate_fe)
-       :m_simulate(simulate), m_enabled(false), m_type(-1), m_simulate_fe(simulate_fe), m_dvbid(fe), m_slotid(fe)
-       ,m_fd(-1), m_rotor_mode(false), m_need_rotor_workaround(false), m_can_handle_dvbs2(false)
-       ,m_state(stateClosed), m_timeout(0), m_tuneTimer(0)
-#if HAVE_DVB_API_VERSION < 3
-       ,m_secfd(-1)
-#endif
+       :m_simulate(simulate), m_enabled(false), m_simulate_fe(simulate_fe), m_dvbid(fe), m_slotid(fe)
+       ,m_fd(-1), m_rotor_mode(false), m_need_rotor_workaround(false)
+       ,m_state(stateClosed), m_timeout(0), m_tuneTimer(0), m_fbc(false), m_is_usbtuner(false)
 {
-#if HAVE_DVB_API_VERSION < 3
-       sprintf(m_filename, "/dev/dvb/card%d/frontend%d", adap, fe);
-       sprintf(m_sec_filename, "/dev/dvb/card%d/sec%d", adap, fe);
-#else
        sprintf(m_filename, "/dev/dvb/adapter%d/frontend%d", adap, fe);
-#endif
 
        m_timeout = eTimer::create(eApp);
        CONNECT(m_timeout->timeout, eDVBFrontend::timeout);
@@ -486,7 +479,7 @@ eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok, bool simulate, eDVBFronten
 void eDVBFrontend::reopenFrontend()
 {
        sleep(1);
-       m_type = -1;
+       m_delsys.clear();
        openFrontend();
 }
 
@@ -498,11 +491,7 @@ int eDVBFrontend::openFrontend()
        m_state=stateIdle;
        m_tuning=0;
 
-#if HAVE_DVB_API_VERSION < 3
-       FrontendInfo fe_info;
-#else
        dvb_frontend_info fe_info;
-#endif
        if (!m_simulate)
        {
                eDebug("opening frontend %d", m_dvbid);
@@ -517,8 +506,26 @@ int eDVBFrontend::openFrontend()
                }
                else
                        eWarning("frontend %d already opened", m_dvbid);
-               if (m_type == -1)
+
+               if (m_delsys.empty())
                {
+#ifdef DTV_ENUM_DELSYS
+                       struct dtv_property p[1];
+                       p[0].cmd = DTV_ENUM_DELSYS;
+                       struct dtv_properties cmdseq;
+                       cmdseq.num = 1;
+                       cmdseq.props = p;
+                       if (::ioctl(m_fd, FE_GET_PROPERTY, &cmdseq) >= 0)
+                       {
+                               m_delsys.clear();
+                               unsigned int i;
+                               for (i = 0; i < p[0].u.buffer.len ; i++)
+                               {
+                                       fe_delivery_system_t delsys = (fe_delivery_system_t)p[0].u.buffer.data[i];
+                                       m_delsys[delsys] = true;
+                               }
+                       }
+#else
                        if (::ioctl(m_fd, FE_GET_INFO, &fe_info) < 0)
                        {
                                eWarning("ioctl FE_GET_INFO failed");
@@ -526,50 +533,46 @@ int eDVBFrontend::openFrontend()
                                m_fd = -1;
                                return -1;
                        }
-
+                       /* old DVB API, fill delsys map with some defaults */
                        switch (fe_info.type)
                        {
-                       case FE_QPSK:
-                               m_type = iDVBFrontend::feSatellite;
-                               break;
-                       case FE_QAM:
-                               m_type = iDVBFrontend::feCable;
-                               break;
-                       case FE_OFDM:
-                               m_type = iDVBFrontend::feTerrestrial;
-                               break;
-                       default:
-                               eWarning("unknown frontend type.");
-                               ::close(m_fd);
-                               m_fd = -1;
-                               return -1;
+                               case FE_QPSK:
+                               {
+                                       m_delsys[SYS_DVBS] = true;
+#if DVB_API_VERSION >= 5
+                                       if (fe_info.caps & FE_CAN_2G_MODULATION) m_delsys[SYS_DVBS2] = true;
+#endif
+                                       break;
+                               }
+                               case FE_QAM:
+                               {
+#if defined SYS_DVBC_ANNEX_A
+                                       m_delsys[SYS_DVBC_ANNEX_A] = true;
+#else
+                                       m_delsys[SYS_DVBC_ANNEX_AC] = true;
+#endif
+                                       break;
+                               }
+                               case FE_OFDM:
+                               {
+                                       m_delsys[SYS_DVBT] = true;
+#if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 3
+                                       if (fe_info.caps & FE_CAN_2G_MODULATION) m_delsys[SYS_DVBT2] = true;
+#endif
+                                       break;
+                               }
+                               case FE_ATSC:   // placeholder to prevent warning
+                               {
+                                       break;
+                               }
                        }
-                       if (m_simulate_fe)
-                               m_simulate_fe->m_type = m_type;
-                       eDebugNoSimulate("detected %s frontend", "satellite\0cable\0    terrestrial"+fe_info.type*10);
+#endif
                }
 
-#if HAVE_DVB_API_VERSION < 3
-               if (m_type == iDVBFrontend::feSatellite)
+               if (m_simulate_fe)
                {
-                               if (m_secfd < 0)
-                               {
-                                       if (!m_simulate)
-                                       {
-                                               m_secfd = ::open(m_sec_filename, O_RDWR);
-                                               if (m_secfd < 0)
-                                               {
-                                                       eWarning("failed! (%s) %m", m_sec_filename);
-                                                       ::close(m_fd);
-                                                       m_fd=-1;
-                                                       return -1;
-                                               }
-                                       }
-                               }
-                               else
-                                       eWarning("sec %d already opened", m_dvbid);
+                       m_simulate_fe->m_delsys = m_delsys;
                }
-#endif
 
                m_sn = eSocketNotifier::create(eApp, m_fd, eSocketNotifier::Read, false);
                CONNECT(m_sn->activated, eDVBFrontend::feEvent);
@@ -606,7 +609,7 @@ int eDVBFrontend::closeFrontend(bool force, bool no_delayed)
                {
                        if (!no_delayed)
                        {
-                               m_sec->prepareTurnOffSatCR(*this, m_data[SATCR]);
+                               m_sec->prepareTurnOffSatCR(*this);
                                m_tuneTimer->start(0, true);
                                if(!m_tuneTimer->isActive())
                                {
@@ -644,15 +647,6 @@ int eDVBFrontend::closeFrontend(bool force, bool no_delayed)
                setTone(iDVBFrontend::toneOff);
                setVoltage(iDVBFrontend::voltageOff);
        }
-#if HAVE_DVB_API_VERSION < 3
-       if (m_secfd >= 0)
-       {
-               if (!::close(m_secfd))
-                       m_secfd=-1;
-               else
-                       eWarning("couldnt close sec %d", m_dvbid);
-       }
-#endif
        m_sn=0;
        m_state = stateClosed;
 
@@ -677,11 +671,7 @@ void eDVBFrontend::feEvent(int w)
        }
        while (1)
        {
-#if HAVE_DVB_API_VERSION < 3
-               FrontendEvent event;
-#else
                dvb_frontend_event event;
-#endif
                int res;
                int state;
                res = ::ioctl(m_fd, FE_GET_EVENT, &event);
@@ -692,19 +682,14 @@ void eDVBFrontend::feEvent(int w)
                if (w < 0)
                        continue;
 
-#if HAVE_DVB_API_VERSION < 3
-               if (event.type == FE_COMPLETION_EV)
-#else
                eDebug("(%d)fe event: status %x, inversion %s, m_tuning %d", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off", m_tuning);
                if (event.status & FE_HAS_LOCK)
-#endif
                {
                        state = stateLock;
                } else
                {
                        if (m_tuning) {
                                state = stateTuning;
-#if HAVE_DVB_API_VERSION >= 3
                                if (event.status & FE_TIMEDOUT) {
                                        eDebug("FE_TIMEDOUT! ..abort");
                                        m_tuneTimer->stop();
@@ -712,17 +697,16 @@ void eDVBFrontend::feEvent(int w)
                                        return;
                                }
                                ++m_tuning;
-#else
-                               m_tuneTimer->stop();
-                               timeout();
-#endif
                        }
                        else
                        {
                                eDebug("stateLostLock");
                                state = stateLostLock;
                                if (!m_rotor_mode)
+                               {
                                        sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
+                                       sec_fe->m_data[LINKABLE_CSW] = sec_fe->m_data[LINKABLE_UCSW] = sec_fe->m_data[LINKABLE_TONEBURST] = -1;
+                               }
                        }
                }
                if (m_state != state)
@@ -738,9 +722,10 @@ void eDVBFrontend::timeout()
        m_tuning = 0;
        if (m_state == stateTuning)
        {
-#ifdef BUILD_VUPLUS /* ikseong  */
+#ifdef BUILD_VUPLUS
                eDVBFrontend *sec_fe = this;
                sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
+               sec_fe->m_data[LINKABLE_CSW] = sec_fe->m_data[LINKABLE_UCSW] = sec_fe->m_data[LINKABLE_TONEBURST] = -1;
 #endif
                m_state = stateFailed;
                m_stateChanged(this);
@@ -784,7 +769,10 @@ int eDVBFrontend::readFrontendData(int type)
                                float SDS_SNRE = snr << 16;
                                float snr_in_db;
 
-                               if (oparm.sat.system == eDVBFrontendParametersSatellite::System_DVB_S) // DVB-S1 / QPSK
+                               eDVBFrontendParametersSatellite sparm;
+                               oparm.getDVBS(sparm);
+
+                               if (sparm.system == eDVBFrontendParametersSatellite::System_DVB_S) // DVB-S1 / QPSK
                                {
                                        static float SNR_COEFF[6] = {
                                                100.0 / 4194304.0,
@@ -810,13 +798,12 @@ int eDVBFrontend::readFrontendData(int type)
                                        }
                                        snr_in_db = fval1;
                                }
-#if HAVE_DVB_API_VERSION >= 3
                                else
                                {
                                        float fval1 = SDS_SNRE / 268435456.0,
                                                  fval2, fval3, fval4;
 
-                                       if (oparm.sat.modulation == eDVBFrontendParametersSatellite::Modulation_QPSK)
+                                       if (sparm.modulation == eDVBFrontendParametersSatellite::Modulation_QPSK)
                                        {
                                                fval2 = 6.76;
                                                fval3 = 4.35;
@@ -833,7 +820,6 @@ int eDVBFrontend::readFrontendData(int type)
                                                fval1 = fval4 - fval2 * log10(1.0+pow(10.0, (fval3-fval1)/fval2));
                                        snr_in_db = fval1;
                                }
-#endif
                                sat_max = 1750;
                                ret = (int)(snr_in_db * 100);
                        }
@@ -927,7 +913,10 @@ int eDVBFrontend::readFrontendData(int type)
                        {
                                if (ret == 0x12345678) // no snr db calculation avail.. return untouched snr value..
                                        return snr;
-                               switch(m_type)
+
+                               int type = -1;
+                               oparm.getSystem(type);
+                               switch(type)
                                {
                                        case feSatellite:
                                                return ret >= sat_max ? 65536 : ret * 65536 / sat_max;
@@ -953,11 +942,7 @@ int eDVBFrontend::readFrontendData(int type)
                }
                case locked:
                {
-#if HAVE_DVB_API_VERSION < 3
-                       FrontendStatus status=0;
-#else
                        fe_status_t status;
-#endif
                        if (!m_simulate)
                        {
                                if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
@@ -968,11 +953,7 @@ int eDVBFrontend::readFrontendData(int type)
                }
                case synced:
                {
-#if HAVE_DVB_API_VERSION < 3
-                       FrontendStatus status=0;
-#else
                        fe_status_t status;
-#endif
                        if (!m_simulate)
                        {
                                if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
@@ -983,6 +964,8 @@ int eDVBFrontend::readFrontendData(int type)
                }
                case frontendNumber:
                        return m_slotid;
+               case isUsbTuner:
+                       return m_is_usbtuner;
        }
        return 0;
 }
@@ -1055,6 +1038,11 @@ void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial
        PutToDict(dict, "guard_interval", feparm.guard_interval);
        PutToDict(dict, "hierarchy_information", feparm.hierarchy);
        PutToDict(dict, "inversion", feparm.inversion);
+       PutToDict(dict, "system", feparm.system);
+       if (feparm.system == eDVBFrontendParametersTerrestrial::System_DVB_T2)
+       {
+               PutToDict(dict, "plp_id", feparm.plpid);
+       }
 }
 
 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
@@ -1067,17 +1055,25 @@ void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
        PutToDict(dict, "fec_inner", feparm.fec_inner);
 }
 
-#if HAVE_DVB_API_VERSION >= 5
-static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, struct dtv_property *p, long freq_offset, int orb_pos, int polarization)
+static void fillDictWithSatelliteData(ePyObject dict, struct dtv_property *p, long freq_offset, int orbital_position, int polarization)
 {
        long tmp=0;
-       int frequency = parm_frequency + freq_offset;
+       int p_system = p[0].u.data;
+       int p_frequency = p[1].u.data;
+       int p_inversion = p[2].u.data;
+       int p_modulation = p[3].u.data;
+       int p_symbolrate = p[4].u.data;
+       int p_inner_fec = p[5].u.data;
+       int p_rolloff = p[6].u.data;
+       int p_pilot = p[7].u.data;
+
+       int frequency = p_frequency + freq_offset;
        PutToDict(dict, "frequency", frequency);
-       PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
-       PutToDict(dict, "orbital_position", orb_pos);
+       PutToDict(dict, "symbol_rate", p_symbolrate);
+       PutToDict(dict, "orbital_position", orbital_position);
        PutToDict(dict, "polarization", polarization);
 
-       switch(parm_u_qpsk_fec_inner)
+       switch(p_inner_fec)
        {
        case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
        case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
@@ -1094,13 +1090,13 @@ static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &
        }
        PutToDict(dict, "fec_inner", tmp);
 
-       switch (p[0].u.data)
+       switch (p_system)
        {
        default: eDebug("got unsupported system from frontend! report as DVBS!");
        case SYS_DVBS: tmp = eDVBFrontendParametersSatellite::System_DVB_S; break;
        case SYS_DVBS2:
        {
-               switch (p[2].u.data)
+               switch (p_rolloff)
                {
                default: eDebug("got unsupported rolloff from frontend! report as 0_20!");
                case ROLLOFF_20: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
@@ -1109,7 +1105,7 @@ static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &
                }
                PutToDict(dict, "rolloff", tmp);
 
-               switch (p[3].u.data)
+               switch (p_pilot)
                {
                case PILOT_OFF: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
                case PILOT_ON: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
@@ -1122,182 +1118,183 @@ static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &
        }
        PutToDict(dict, "system", tmp);
 
-       switch (p[1].u.data)
+       switch (p_modulation)
        {
        default: eDebug("got unsupported modulation from frontend! report as QPSK!");
        case QPSK: tmp = eDVBFrontendParametersSatellite::Modulation_QPSK; break;
        case PSK_8: tmp = eDVBFrontendParametersSatellite::Modulation_8PSK; break;
        }
        PutToDict(dict, "modulation", tmp);
-}
 
-#else
-static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, long freq_offset, int orb_pos, int polarization)
-{
-       long tmp=0;
-       int frequency = parm_frequency + freq_offset;
-       PutToDict(dict, "frequency", frequency);
-       PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
-       PutToDict(dict, "orbital_position", orb_pos);
-       PutToDict(dict, "polarization", polarization);
-
-       switch((int)parm_u_qpsk_fec_inner)
+       switch(p_inversion)
        {
-       case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
-       case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
-       case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
-       case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
-       case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
-       case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
-       default:
-       case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
-#if HAVE_DVB_API_VERSION >=3
-       case FEC_S2_8PSK_1_2:
-       case FEC_S2_QPSK_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
-       case FEC_S2_8PSK_2_3:
-       case FEC_S2_QPSK_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
-       case FEC_S2_8PSK_3_4:
-       case FEC_S2_QPSK_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
-       case FEC_S2_8PSK_5_6:
-       case FEC_S2_QPSK_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
-       case FEC_S2_8PSK_7_8:
-       case FEC_S2_QPSK_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
-       case FEC_S2_8PSK_8_9:
-       case FEC_S2_QPSK_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
-       case FEC_S2_8PSK_3_5:
-       case FEC_S2_QPSK_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
-       case FEC_S2_8PSK_4_5:
-       case FEC_S2_QPSK_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
-       case FEC_S2_8PSK_9_10:
-       case FEC_S2_QPSK_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
-#endif
+               case INVERSION_ON: tmp = eDVBFrontendParametersSatellite::Inversion_On; break;
+               case INVERSION_OFF: tmp = eDVBFrontendParametersSatellite::Inversion_Off; break;
+               default: tmp = eDVBFrontendParametersSatellite::Inversion_Unknown; break;
        }
-       PutToDict(dict, "fec_inner", tmp);
-#if HAVE_DVB_API_VERSION >=3
-       PutToDict(dict, "modulation",
-               parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ?
-                       eDVBFrontendParametersSatellite::Modulation_8PSK :
-                       eDVBFrontendParametersSatellite::Modulation_QPSK );
-       if (parm_u_qpsk_fec_inner > FEC_AUTO)
-       {
-               switch(parm_inversion & 0xc)
-               {
-               default: // unknown rolloff
-               case 0: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
-               case 4: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
-               case 8: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
-               }
-               PutToDict(dict, "rolloff", tmp);
-               switch(parm_inversion & 0x30)
-               {
-               case 0: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
-               case 0x10: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
-               case 0x20: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
-               }
-               PutToDict(dict, "pilot", tmp);
-               tmp = eDVBFrontendParametersSatellite::System_DVB_S2;
-       }
-       else
-               tmp = eDVBFrontendParametersSatellite::System_DVB_S;
-#else
-       PutToDict(dict, "modulation", eDVBFrontendParametersSatellite::Modulation_QPSK );
-       tmp = eDVBFrontendParametersSatellite::System_DVB_S;
-#endif
-       PutToDict(dict, "system", tmp);
+       PutToDict(dict, "inversion", tmp);
 }
-#endif
 
-static void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
+static void fillDictWithCableData(ePyObject dict, struct dtv_property *p)
 {
-       long 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)
-       {
-       case FEC_NONE: tmp = eDVBFrontendParametersCable::FEC_None; break;
-       case FEC_1_2: tmp = eDVBFrontendParametersCable::FEC_1_2; break;
-       case FEC_2_3: tmp = eDVBFrontendParametersCable::FEC_2_3; break;
-       case FEC_3_4: tmp = eDVBFrontendParametersCable::FEC_3_4; break;
-       case FEC_5_6: tmp = eDVBFrontendParametersCable::FEC_5_6; break;
-       case FEC_7_8: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
-#if HAVE_DVB_API_VERSION >= 3
-       case FEC_8_9: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
-#endif
-       default:
-       case FEC_AUTO: tmp = eDVBFrontendParametersCable::FEC_Auto; break;
+       long tmp = 0;
+       int p_system = p[0].u.data;
+       int p_frequency = p[1].u.data;
+       int p_inversion = p[2].u.data;
+       int p_modulation = p[3].u.data;
+       int p_symbolrate = p[4].u.data;
+       int p_inner_fec = p[5].u.data;
+// frequency
+       tmp = p_frequency/1000;
+       PutToDict(dict, "frequency", tmp);
+// sysbolrate
+       PutToDict(dict, "symbol_rate", p_inversion);
+// inner fec
+       switch (p_inner_fec)
+       {
+               case FEC_NONE: tmp = eDVBFrontendParametersCable::FEC_None; break;
+               case FEC_1_2: tmp = eDVBFrontendParametersCable::FEC_1_2; break;
+               case FEC_2_3: tmp = eDVBFrontendParametersCable::FEC_2_3; break;
+               case FEC_3_4: tmp = eDVBFrontendParametersCable::FEC_3_4; break;
+               case FEC_5_6: tmp = eDVBFrontendParametersCable::FEC_5_6; break;
+               case FEC_7_8: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
+               case FEC_8_9: tmp = eDVBFrontendParametersCable::FEC_8_9; break;
+               default:
+               case FEC_AUTO: tmp = eDVBFrontendParametersCable::FEC_Auto; break;
        }
        PutToDict(dict, "fec_inner", tmp);
-       switch(parm_u_qam_modulation)
-       {
-       case QAM_16: tmp = eDVBFrontendParametersCable::Modulation_QAM16; break;
-       case QAM_32: tmp = eDVBFrontendParametersCable::Modulation_QAM32; break;
-       case QAM_64: tmp = eDVBFrontendParametersCable::Modulation_QAM64; break;
-       case QAM_128: tmp = eDVBFrontendParametersCable::Modulation_QAM128; break;
-       case QAM_256: tmp = eDVBFrontendParametersCable::Modulation_QAM256; break;
-       default:
-       case QAM_AUTO:   tmp = eDVBFrontendParametersCable::Modulation_Auto; break;
+// modulation
+       switch (p_modulation)
+       {
+               case QAM_16: tmp = eDVBFrontendParametersCable::Modulation_QAM16; break;
+               case QAM_32: tmp = eDVBFrontendParametersCable::Modulation_QAM32; break;
+               case QAM_64: tmp = eDVBFrontendParametersCable::Modulation_QAM64; break;
+               case QAM_128: tmp = eDVBFrontendParametersCable::Modulation_QAM128; break;
+               case QAM_256: tmp = eDVBFrontendParametersCable::Modulation_QAM256; break;
+               default:
+               case QAM_AUTO: tmp = eDVBFrontendParametersCable::Modulation_Auto; break;
        }
        PutToDict(dict, "modulation", tmp);
+// inversion
+       switch (p_inversion)
+       {
+               case INVERSION_OFF: tmp = eDVBFrontendParametersTerrestrial::Inversion_Off; break;
+               case INVERSION_ON: tmp = eDVBFrontendParametersTerrestrial::Inversion_On; break;
+               default:
+               case INVERSION_AUTO: tmp = eDVBFrontendParametersTerrestrial::Inversion_Unknown; break;
+       }
+       PutToDict(dict, "inversion", tmp);
 }
 
-static void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
+static void fillDictWithTerrestrialData(ePyObject dict, struct dtv_property *p)
 {
-       long tmp=0;
-       PutToDict(dict, "frequency", parm_frequency);
-       switch (parm_u_ofdm_bandwidth)
+       long tmp =0;
+       int p_system = p[0].u.data;
+       int p_frequency = p[1].u.data;
+       int p_inversion = p[2].u.data;
+       int p_constellation = p[3].u.data;
+       int p_bandwidth = p[4].u.data;
+       int p_coderate_lp = p[5].u.data;
+       int p_coderate_hp = p[6].u.data;
+       int p_transmission_mode = p[7].u.data;
+       int p_guard_interval = p[8].u.data;
+       int p_hierarchy = p[9].u.data;
+#if (defined DTV_STREAM_ID) || (defined DTV_DVBT2_PLP_ID)
+       int p_plp_id = p[10].u.data;
+#endif
+
+// system
+       switch (p_system)
        {
-       case BANDWIDTH_8_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_8MHz; break;
-       case BANDWIDTH_7_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_7MHz; break;
-       case BANDWIDTH_6_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_6MHz; break;
-       default:
-       case BANDWIDTH_AUTO: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_Auto; break;
+               default: eDebug("got unsupported system from frontend! report as DVBT!");
+               case SYS_DVBT: tmp = eDVBFrontendParametersTerrestrial::System_DVB_T; break;
+               case SYS_DVBT2:
+               {
+#if (defined DTV_STREAM_ID) || (defined DTV_DVBT2_PLP_ID)
+                       tmp = p_plp_id;
+                       PutToDict(dict, "plp_id", tmp);
+#endif
+                       tmp = eDVBFrontendParametersTerrestrial::System_DVB_T2; break;
+               }
+       }
+       PutToDict(dict, "system", tmp);
+// frequency
+       tmp = p_frequency;
+       PutToDict(dict, "frequency", tmp);
+// bandwidth
+       switch (p_bandwidth)
+       {
+               case 8000000: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_8MHz; break;
+               case 7000000: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_7MHz; break;
+               case 6000000: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_6MHz; break;
+               case 5000000: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_5MHz; break;
+               case 10000000: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_10MHz; break;
+               case 1712000: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_1_712MHz; break;
+               default:
+               case BANDWIDTH_AUTO: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_Auto; break;
        }
        PutToDict(dict, "bandwidth", tmp);
-       switch (parm_u_ofdm_code_rate_LP)
-       {
-       case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
-       case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
-       case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
-       case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
-       case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
-       default:
-       case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
+// code rate LP
+       switch (p_coderate_lp)
+       {
+               case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
+               case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
+               case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
+               case FEC_4_5: tmp = eDVBFrontendParametersTerrestrial::FEC_4_5; break;
+               case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
+               case FEC_6_7: tmp = eDVBFrontendParametersTerrestrial::FEC_6_7; break;
+               case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
+               case FEC_8_9: tmp = eDVBFrontendParametersTerrestrial::FEC_8_9; break;
+               default:
+               case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
        }
        PutToDict(dict, "code_rate_lp", tmp);
-       switch (parm_u_ofdm_code_rate_HP)
-       {
-       case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
-       case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
-       case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
-       case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
-       case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
-       default:
-       case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
+// code rate HP
+       switch (p_coderate_hp)
+       {
+               case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
+               case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
+               case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
+               case FEC_4_5: tmp = eDVBFrontendParametersTerrestrial::FEC_4_5; break;
+               case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
+               case FEC_6_7: tmp = eDVBFrontendParametersTerrestrial::FEC_6_7; break;
+               case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
+               case FEC_8_9: tmp = eDVBFrontendParametersTerrestrial::FEC_8_9; break;
+               default:
+               case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
        }
        PutToDict(dict, "code_rate_hp", tmp);
-       switch (parm_u_ofdm_constellation)
+// constellation
+       switch (p_constellation)
        {
-       case QPSK: tmp = eDVBFrontendParametersTerrestrial::Modulation_QPSK; break;
-       case QAM_16: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM16; break;
-       case QAM_64: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM64; break;
-       default:
-       case QAM_AUTO: tmp = eDVBFrontendParametersTerrestrial::Modulation_Auto; break;
+               case QPSK: tmp = eDVBFrontendParametersTerrestrial::Modulation_QPSK; break;
+               case QAM_16: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM16; break;
+               case QAM_64: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM64; break;
+               case QAM_256: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM256; break;
+               default:
+               case QAM_AUTO: tmp = eDVBFrontendParametersTerrestrial::Modulation_Auto; break;
        }
        PutToDict(dict, "constellation", tmp);
-       switch (parm_u_ofdm_transmission_mode)
+
+// transmission
+       switch (p_transmission_mode)
        {
+       case TRANSMISSION_MODE_1K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_1k; break;
        case TRANSMISSION_MODE_2K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_2k; break;
+       case TRANSMISSION_MODE_4K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_4k; break;
        case TRANSMISSION_MODE_8K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_8k; break;
+       case TRANSMISSION_MODE_16K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_16k; break;
+       case TRANSMISSION_MODE_32K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_32k; break;
        default:
        case TRANSMISSION_MODE_AUTO: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto; break;
        }
        PutToDict(dict, "transmission_mode", tmp);
-       switch (parm_u_ofdm_guard_interval)
+// guard interval
+       switch (p_guard_interval)
        {
+               case GUARD_INTERVAL_19_256: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_19_256; break;
+               case GUARD_INTERVAL_19_128: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_19_128; break;
+               case GUARD_INTERVAL_1_128: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_128; break;
                case GUARD_INTERVAL_1_32: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_32; break;
                case GUARD_INTERVAL_1_16: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_16; break;
                case GUARD_INTERVAL_1_8: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_8; break;
@@ -1306,7 +1303,8 @@ static void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS
                case GUARD_INTERVAL_AUTO: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_Auto; break;
        }
        PutToDict(dict, "guard_interval", tmp);
-       switch (parm_u_ofdm_hierarchy_information)
+// hierarchy
+       switch (p_hierarchy)
        {
                case HIERARCHY_NONE: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_None; break;
                case HIERARCHY_1: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_1; break;
@@ -1316,6 +1314,15 @@ static void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS
                case HIERARCHY_AUTO: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_Auto; break;
        }
        PutToDict(dict, "hierarchy_information", tmp);
+// inversion
+       switch (p_inversion)
+       {
+               case INVERSION_OFF: tmp = eDVBFrontendParametersTerrestrial::Inversion_Off;  break;
+               case INVERSION_ON: tmp = eDVBFrontendParametersTerrestrial::Inversion_On;  break;
+               default:
+               case INVERSION_AUTO: tmp = eDVBFrontendParametersTerrestrial::Inversion_Unknown;  break;
+       }
+       PutToDict(dict, "inversion", tmp);
 }
 
 void eDVBFrontend::getFrontendStatus(ePyObject dest)
@@ -1365,76 +1372,96 @@ void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
 {
        if (dest && PyDict_Check(dest))
        {
+               int type = -1;
                FRONTENDPARAMETERS front;
-#if HAVE_DVB_API_VERSION >= 5
-               struct dtv_property p[4];
+               struct dtv_property p[16];
                struct dtv_properties cmdseq;
                cmdseq.props = p;
-               cmdseq.num = 4;
-               p[0].cmd = DTV_DELIVERY_SYSTEM;
-               p[1].cmd = DTV_MODULATION;
-               p[2].cmd = DTV_ROLLOFF;
-               p[3].cmd = DTV_PILOT;
+               cmdseq.num = 0;
+               oparm.getSystem(type);
+
+               p[cmdseq.num++].cmd = DTV_DELIVERY_SYSTEM;
+               p[cmdseq.num++].cmd = DTV_FREQUENCY;
+               p[cmdseq.num++].cmd = DTV_INVERSION;
+               p[cmdseq.num++].cmd = DTV_MODULATION;
+               if(type == feSatellite)
+               {
+                       p[cmdseq.num++].cmd = DTV_SYMBOL_RATE;
+                       p[cmdseq.num++].cmd = DTV_INNER_FEC;
+                       p[cmdseq.num++].cmd = DTV_ROLLOFF;
+                       p[cmdseq.num++].cmd = DTV_PILOT;
+               }
+               else if(type == feCable)
+               {
+                       p[cmdseq.num++].cmd = DTV_SYMBOL_RATE;
+                       p[cmdseq.num++].cmd = DTV_INNER_FEC;
+               }
+               else if(type == feTerrestrial)
+               {
+                       p[cmdseq.num++].cmd = DTV_BANDWIDTH_HZ;
+                       p[cmdseq.num++].cmd = DTV_CODE_RATE_LP;
+                       p[cmdseq.num++].cmd = DTV_CODE_RATE_HP;
+                       p[cmdseq.num++].cmd = DTV_TRANSMISSION_MODE;
+                       p[cmdseq.num++].cmd = DTV_GUARD_INTERVAL;
+                       p[cmdseq.num++].cmd = DTV_HIERARCHY;
+#if defined DTV_STREAM_ID
+                       p[cmdseq.num++].cmd = DTV_STREAM_ID;
+#elif defined DTV_DVBT2_PLP_ID
+                       p[cmdseq.num++].cmd = DTV_DVBT2_PLP_ID;
 #endif
+               }
+
                if (m_simulate || m_fd == -1 || original)
+               {
                        original = true;
-#if HAVE_DVB_API_VERSION >= 5
-               else if (m_type == feSatellite && // yet just use new api for DVB-S(2) only
-                       ioctl(m_fd, FE_GET_PROPERTY, &cmdseq)<0)
+               }
+               else if (ioctl(m_fd, FE_GET_PROPERTY, &cmdseq)<0)
                {
                        eDebug("FE_GET_PROPERTY failed (%m)");
                        original = true;
                }
-#endif
-               else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
+               else if (type == feSatellite && // use for DVB-S(2) only
+                       ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
                {
                        eDebug("FE_GET_FRONTEND failed (%m)");
                        original = true;
                }
                if (original)
                {
-                       switch(m_type)
+                       switch(type)
                        {
                                case feSatellite:
-                                       PutSatelliteDataToDict(dest, oparm.sat);
+                                       eDVBFrontendParametersSatellite sparm;
+                                       oparm.getDVBS(sparm);
+                                       PutSatelliteDataToDict(dest, sparm);
                                        break;
                                case feCable:
-                                       PutCableDataToDict(dest, oparm.cab);
+                                       eDVBFrontendParametersCable cparm;
+                                       oparm.getDVBC(cparm);
+                                       PutCableDataToDict(dest, cparm);
                                        break;
                                case feTerrestrial:
-                                       PutTerrestrialDataToDict(dest, oparm.ter);
+                                       eDVBFrontendParametersTerrestrial tparm;
+                                       oparm.getDVBT(tparm);
+                                       PutTerrestrialDataToDict(dest, tparm);
                                        break;
                        }
                }
                else
                {
                        FRONTENDPARAMETERS &parm = front;
-                       long tmp = eDVBFrontendParametersSatellite::Inversion_Unknown;
-                       switch(parm_inversion & 3)
-                       {
-                               case INVERSION_ON:
-                                       tmp = eDVBFrontendParametersSatellite::Inversion_On;
-                                       break;
-                               case INVERSION_OFF:
-                                       tmp = eDVBFrontendParametersSatellite::Inversion_Off;
-                               default:
-                                       break;
-                       }
-                       PutToDict(dest, "inversion", tmp);
-                       switch(m_type)
+                       switch(type)
                        {
                                case feSatellite:
-#if HAVE_DVB_API_VERSION >= 5
-                                       fillDictWithSatelliteData(dest, parm, p, m_data[FREQ_OFFSET], oparm.sat.orbital_position, oparm.sat.polarisation);
-#else
-                                       fillDictWithSatelliteData(dest, parm, m_data[FREQ_OFFSET], oparm.sat.orbital_position, oparm.sat.polarisation);
-#endif
+                                       eDVBFrontendParametersSatellite sparm;
+                                       oparm.getDVBS(sparm);
+                                       fillDictWithSatelliteData(dest, p, m_data[FREQ_OFFSET], sparm.orbital_position, sparm.polarisation);
                                        break;
                                case feCable:
-                                       fillDictWithCableData(dest, parm);
+                                       fillDictWithCableData(dest, p);
                                        break;
                                case feTerrestrial:
-                                       fillDictWithTerrestrialData(dest, parm);
+                                       fillDictWithTerrestrialData(dest, p);
                                        break;
                        }
                }
@@ -1447,20 +1474,26 @@ void eDVBFrontend::getFrontendData(ePyObject dest)
        {
                const char *tmp=0;
                PutToDict(dest, "tuner_number", m_slotid);
-               switch(m_type)
+
+               if (supportsDeliverySystem(SYS_DVBS, true) || supportsDeliverySystem(SYS_DVBS2, true))
                {
-                       case feSatellite:
-                               tmp = "DVB-S";
-                               break;
-                       case feCable:
-                               tmp = "DVB-C";
-                               break;
-                       case feTerrestrial:
-                               tmp = "DVB-T";
-                               break;
-                       default:
-                               tmp = "UNKNOWN";
-                               break;
+                       tmp = "DVB-S";
+               }
+#if defined SYS_DVBC_ANNEX_A
+               else if (supportsDeliverySystem(SYS_DVBC_ANNEX_A, true))
+#else
+               else if (supportsDeliverySystem(SYS_DVBC_ANNEX_AC, true))
+#endif
+               {
+                       tmp = "DVB-C";
+               }
+               else if (supportsDeliverySystem(SYS_DVBT, true) || supportsDeliverySystem(SYS_DVBT2, true))
+               {
+                       tmp = "DVB-T";
+               }
+               else
+               {
+                       tmp = "UNKNOWN";
                }
                PutToDict(dest, "tuner_type", tmp);
        }
@@ -1546,12 +1579,14 @@ int eDVBFrontend::tuneLoopInt()  // called by m_tuneTimer
                tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
                if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
                        int state = sec_fe->m_state;
+#if 0 // Since following code causes lock fail for linked tuners in certain conditions, it does not apply.
                        // workaround to put the kernel frontend thread into idle state!
                        if (state != eDVBFrontend::stateIdle && state != stateClosed)
                        {
                                sec_fe->closeFrontend(true);
                                state = sec_fe->m_state;
                        }
+#endif
                        // sec_fe is closed... we must reopen it here..
                        if (state == stateClosed)
                        {
@@ -1919,34 +1954,39 @@ void eDVBFrontend::setFrontend(bool recvEvents)
        if (!m_simulate)
        {
                eDebug("setting frontend %d", m_dvbid);
+
+               int type = -1;
+               oparm.getSystem(type);
+
                if (recvEvents)
                        m_sn->start();
                feEvent(-1); // flush events
-#if HAVE_DVB_API_VERSION >= 5
-               if (m_type == iDVBFrontend::feSatellite)
+               if (type == iDVBFrontend::feSatellite)
                {
                        fe_rolloff_t rolloff = ROLLOFF_35;
                        fe_pilot_t pilot = PILOT_OFF;
                        fe_modulation_t modulation = QPSK;
                        fe_delivery_system_t system = SYS_DVBS;
-                       switch(oparm.sat.system)
+                       eDVBFrontendParametersSatellite sparm;
+                       oparm.getDVBS(sparm);
+                       switch(sparm.system)
                        {
                        case eDVBFrontendParametersSatellite::System_DVB_S: system = SYS_DVBS; break;
                        case eDVBFrontendParametersSatellite::System_DVB_S2: system = SYS_DVBS2; break;
                        };
-                       switch(oparm.sat.modulation)
+                       switch(sparm.modulation)
                        {
                        case eDVBFrontendParametersSatellite::Modulation_QPSK: modulation = QPSK; break;
                        case eDVBFrontendParametersSatellite::Modulation_8PSK: modulation = PSK_8; break;
                        case eDVBFrontendParametersSatellite::Modulation_QAM16: modulation = QAM_16; break;
                        };
-                       switch(oparm.sat.pilot)
+                       switch(sparm.pilot)
                        {
                        case eDVBFrontendParametersSatellite::Pilot_Off: pilot = PILOT_OFF; break;
                        case eDVBFrontendParametersSatellite::Pilot_On: pilot = PILOT_ON; break;
                        case eDVBFrontendParametersSatellite::Pilot_Unknown: pilot = PILOT_AUTO; break;
                        };
-                       switch(oparm.sat.rolloff)
+                       switch(sparm.rolloff)
                        {
                        case eDVBFrontendParametersSatellite::RollOff_alpha_0_20: rolloff = ROLLOFF_20; break;
                        case eDVBFrontendParametersSatellite::RollOff_alpha_0_25: rolloff = ROLLOFF_25; break;
@@ -1980,8 +2020,81 @@ void eDVBFrontend::setFrontend(bool recvEvents)
                                return;
                        }
                }
-               else
+               else if (type == iDVBFrontend::feCable)
+               {
+                       struct dtv_property p[8];
+                       struct dtv_properties cmdseq;
+                       cmdseq.props = p;
+                       p[0].cmd = DTV_CLEAR;
+#if defined SYS_DVBC_ANNEX_A
+                       p[1].cmd = DTV_DELIVERY_SYSTEM, p[1].u.data = SYS_DVBC_ANNEX_A;
+#else
+                       p[1].cmd = DTV_DELIVERY_SYSTEM, p[1].u.data = SYS_DVBC_ANNEX_AC;
 #endif
+                       p[2].cmd = DTV_FREQUENCY,       p[2].u.data = parm_frequency;
+                       p[3].cmd = DTV_MODULATION,      p[3].u.data = parm_u_qam_modulation;
+                       p[4].cmd = DTV_SYMBOL_RATE,     p[4].u.data = parm_u_qam_symbol_rate;
+                       p[5].cmd = DTV_INNER_FEC,       p[5].u.data = parm_u_qam_fec_inner;
+                       p[6].cmd = DTV_INVERSION,       p[6].u.data = parm_inversion;
+                       p[7].cmd = DTV_TUNE;
+                       cmdseq.num = 8;
+                       if (ioctl(m_fd, FE_SET_PROPERTY, &cmdseq) == -1)
+                       {
+                               perror("FE_SET_PROPERTY failed");
+                               return;
+                       }
+               }
+               else if (type == iDVBFrontend::feTerrestrial)
+               {
+                       fe_delivery_system_t system = SYS_DVBT;
+                       eDVBFrontendParametersTerrestrial tparm;
+                       oparm.getDVBT(tparm);
+                       switch (tparm.system)
+                       {
+                               default:
+                               case eDVBFrontendParametersTerrestrial::System_DVB_T: system = SYS_DVBT; break;
+                               case eDVBFrontendParametersTerrestrial::System_DVB_T2: system = SYS_DVBT2; break;
+                       }
+                       int bandwidth = 0;
+                       switch (tparm.bandwidth)
+                       {
+                               case eDVBFrontendParametersTerrestrial::Bandwidth_8MHz: bandwidth = 8000000; break;
+                               case eDVBFrontendParametersTerrestrial::Bandwidth_7MHz: bandwidth = 7000000; break;
+                               case eDVBFrontendParametersTerrestrial::Bandwidth_6MHz: bandwidth = 6000000; break;
+                               default:
+                               case eDVBFrontendParametersTerrestrial::Bandwidth_Auto: bandwidth = 0; break;
+                               case eDVBFrontendParametersTerrestrial::Bandwidth_5MHz: bandwidth = 5000000; break;
+                               case eDVBFrontendParametersTerrestrial::Bandwidth_10MHz: bandwidth = 10000000; break;
+                               case eDVBFrontendParametersTerrestrial::Bandwidth_1_712MHz: bandwidth = 1712000; break;
+                       }
+                       struct dtv_property p[13];
+                       struct dtv_properties cmdseq;
+                       cmdseq.props = p;
+                       cmdseq.num = 0;
+                       p[cmdseq.num].cmd = DTV_CLEAR, cmdseq.num++;
+                       p[cmdseq.num].cmd = DTV_DELIVERY_SYSTEM, p[cmdseq.num].u.data = system, cmdseq.num++;
+                       p[cmdseq.num].cmd = DTV_FREQUENCY,      p[cmdseq.num].u.data = parm_frequency, cmdseq.num++;
+                       p[cmdseq.num].cmd = DTV_CODE_RATE_LP,   p[cmdseq.num].u.data = parm_u_ofdm_code_rate_LP, cmdseq.num++;
+                       p[cmdseq.num].cmd = DTV_CODE_RATE_HP,   p[cmdseq.num].u.data = parm_u_ofdm_code_rate_HP, cmdseq.num++;
+                       p[cmdseq.num].cmd = DTV_MODULATION,     p[cmdseq.num].u.data = parm_u_ofdm_constellation, cmdseq.num++;
+                       p[cmdseq.num].cmd = DTV_TRANSMISSION_MODE,      p[cmdseq.num].u.data = parm_u_ofdm_transmission_mode, cmdseq.num++;
+                       p[cmdseq.num].cmd = DTV_GUARD_INTERVAL, p[cmdseq.num].u.data = parm_u_ofdm_guard_interval, cmdseq.num++;
+                       p[cmdseq.num].cmd = DTV_HIERARCHY,      p[cmdseq.num].u.data = parm_u_ofdm_hierarchy_information, cmdseq.num++;
+                       p[cmdseq.num].cmd = DTV_BANDWIDTH_HZ,   p[cmdseq.num].u.data = bandwidth, cmdseq.num++;
+                       p[cmdseq.num].cmd = DTV_INVERSION,      p[cmdseq.num].u.data = parm_inversion, cmdseq.num++;
+#if defined DTV_STREAM_ID
+                       p[cmdseq.num].cmd = DTV_STREAM_ID       ,       p[cmdseq.num].u.data = tparm.plpid, cmdseq.num++;
+#elif defined DTV_DVBT2_PLP_ID
+                       p[cmdseq.num].cmd = DTV_DVBT2_PLP_ID    ,       p[cmdseq.num].u.data = tparm.plpid, cmdseq.num++;
+#endif
+                       p[cmdseq.num].cmd = DTV_TUNE, cmdseq.num++;
+                       if (ioctl(m_fd, FE_SET_PROPERTY, &cmdseq) == -1)
+                       {
+                               perror("FE_SET_PROPERTY failed");
+                               return;
+                       }
+               }
+               else
                {
                        if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
                        {
@@ -1992,14 +2105,6 @@ void eDVBFrontend::setFrontend(bool recvEvents)
        }
 }
 
-RESULT eDVBFrontend::getFrontendType(int &t)
-{
-       if (m_type == -1)
-               return -ENODEV;
-       t = m_type;
-       return 0;
-}
-
 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
 {
        int res;
@@ -2011,7 +2116,6 @@ RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm,
        res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
        if (!res)
        {
-#if HAVE_DVB_API_VERSION >= 3
                eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d system %d modulation %d pilot %d, rolloff %d",
                        feparm.system,
                        feparm.frequency,
@@ -2024,16 +2128,6 @@ RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm,
                        feparm.modulation,
                        feparm.pilot,
                        feparm.rolloff);
-#else
-               eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
-                       feparm.system,
-                       feparm.frequency,
-                       feparm.polarisation,
-                       feparm.symbol_rate,
-                       feparm.inversion,
-                       feparm.fec,
-                       feparm.orbital_position);
-#endif
                parm_u_qpsk_symbol_rate = feparm.symbol_rate;
                switch (feparm.inversion)
                {
@@ -2077,7 +2171,6 @@ RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm,
                                        break;
                        }
                }
-#if HAVE_DVB_API_VERSION >= 3
                else // DVB_S2
                {
                        switch (feparm.fec)
@@ -2113,17 +2206,7 @@ RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm,
                                        eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
                                        return -EINVAL;
                        }
-#if HAVE_DVB_API_VERSION < 5
-                       parm_inversion = (fe_spectral_inversion_t)((feparm.rolloff << 2) | parm_inversion); // Hack.. we use bit 2..3 of inversion param for rolloff
-                       parm_inversion = (fe_spectral_inversion_t)((feparm.pilot << 4) | parm_inversion); // Hack.. we use bit 4..5 of inversion param for pilot
-                       if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation_8PSK) 
-                       {
-                               parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
-                               // 8PSK fec driver values are decimal 9 bigger
-                       }
-#endif
                }
-#endif
                // FIXME !!! get frequency range from tuner
                if ( parm_frequency < 900000 || parm_frequency > 2200000 )
                {
@@ -2132,17 +2215,13 @@ RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm,
                }
                eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
        }
-       oparm.sat = feparm;
+       oparm.setDVBS(feparm, feparm.no_rotor_command_on_tune);
        return res;
 }
 
 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)
        {
@@ -2199,11 +2278,9 @@ RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
        case eDVBFrontendParametersCable::FEC_7_8:
                parm_u_qam_fec_inner = FEC_7_8;
                break;
-#if HAVE_DVB_API_VERSION >= 3
        case eDVBFrontendParametersCable::FEC_8_9:
                parm_u_qam_fec_inner = FEC_8_9;
                break;
-#endif
        default:
        case eDVBFrontendParametersCable::FEC_Auto:
                parm_u_qam_fec_inner = FEC_AUTO;
@@ -2215,7 +2292,7 @@ RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
                parm_u_qam_fec_inner,
                parm_u_qam_modulation,
                parm_inversion);
-       oparm.cab = feparm;
+       oparm.setDVBC(feparm);
        return 0;
 }
 
@@ -2234,6 +2311,15 @@ RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial
        case eDVBFrontendParametersTerrestrial::Bandwidth_6MHz:
                parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
                break;
+       case eDVBFrontendParametersTerrestrial::Bandwidth_5MHz:
+               parm_u_ofdm_bandwidth = BANDWIDTH_5_MHZ;
+               break;
+       case eDVBFrontendParametersTerrestrial::Bandwidth_10MHz:
+               parm_u_ofdm_bandwidth = BANDWIDTH_10_MHZ;
+               break;
+       case eDVBFrontendParametersTerrestrial::Bandwidth_1_712MHz:
+               parm_u_ofdm_bandwidth = BANDWIDTH_1_712_MHZ;
+               break;
        default:
        case eDVBFrontendParametersTerrestrial::Bandwidth_Auto:
                parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
@@ -2256,6 +2342,12 @@ RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial
        case eDVBFrontendParametersTerrestrial::FEC_7_8:
                parm_u_ofdm_code_rate_LP = FEC_7_8;
                break;
+       case eDVBFrontendParametersTerrestrial::FEC_6_7:
+               parm_u_ofdm_code_rate_LP = FEC_6_7;
+               break;
+       case eDVBFrontendParametersTerrestrial::FEC_8_9:
+               parm_u_ofdm_code_rate_LP = FEC_8_9;
+               break;
        default:
        case eDVBFrontendParametersTerrestrial::FEC_Auto:
                parm_u_ofdm_code_rate_LP = FEC_AUTO;
@@ -2278,6 +2370,12 @@ RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial
        case eDVBFrontendParametersTerrestrial::FEC_7_8:
                parm_u_ofdm_code_rate_HP = FEC_7_8;
                break;
+       case eDVBFrontendParametersTerrestrial::FEC_6_7:
+               parm_u_ofdm_code_rate_HP = FEC_6_7;
+               break;
+       case eDVBFrontendParametersTerrestrial::FEC_8_9:
+               parm_u_ofdm_code_rate_HP = FEC_8_9;
+               break;
        default:
        case eDVBFrontendParametersTerrestrial::FEC_Auto:
                parm_u_ofdm_code_rate_HP = FEC_AUTO;
@@ -2294,6 +2392,9 @@ RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial
        case eDVBFrontendParametersTerrestrial::Modulation_QAM64:
                parm_u_ofdm_constellation = QAM_64;
                break;
+       case eDVBFrontendParametersTerrestrial::Modulation_QAM256:
+               parm_u_ofdm_constellation = QAM_256;
+               break;
        default:
        case eDVBFrontendParametersTerrestrial::Modulation_Auto:
                parm_u_ofdm_constellation = QAM_AUTO;
@@ -2307,6 +2408,18 @@ RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial
        case eDVBFrontendParametersTerrestrial::TransmissionMode_8k:
                parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
                break;
+       case eDVBFrontendParametersTerrestrial::TransmissionMode_4k:
+               parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_4K;
+               break;
+       case eDVBFrontendParametersTerrestrial::TransmissionMode_1k:
+               parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_1K;
+               break;
+       case eDVBFrontendParametersTerrestrial::TransmissionMode_16k:
+               parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_16K;
+               break;
+       case eDVBFrontendParametersTerrestrial::TransmissionMode_32k:
+               parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_32K;
+               break;
        default:
        case eDVBFrontendParametersTerrestrial::TransmissionMode_Auto:
                parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
@@ -2326,6 +2439,15 @@ RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial
                case eDVBFrontendParametersTerrestrial::GuardInterval_1_4:
                        parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
                        break;
+               case eDVBFrontendParametersTerrestrial::GuardInterval_1_128:
+                       parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_128;
+                       break;
+               case eDVBFrontendParametersTerrestrial::GuardInterval_19_128:
+                       parm_u_ofdm_guard_interval = GUARD_INTERVAL_19_128;
+                       break;
+               case eDVBFrontendParametersTerrestrial::GuardInterval_19_256:
+                       parm_u_ofdm_guard_interval = GUARD_INTERVAL_19_256;
+                       break;
                default:
                case eDVBFrontendParametersTerrestrial::GuardInterval_Auto:
                        parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
@@ -2363,7 +2485,19 @@ RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial
                parm_inversion = INVERSION_AUTO;
                break;
        }
-       oparm.ter = feparm;
+       eDebug("tuning to %d khz, bandwidth %d, crl %d, crh %d, modulation %d, tm %d, guard %d, hierarchy %d, inversion %d, system %d, plpid %d",
+               parm_frequency/1000,
+               parm_u_ofdm_bandwidth,
+               parm_u_ofdm_code_rate_LP,
+               parm_u_ofdm_code_rate_HP,
+               parm_u_ofdm_constellation,
+               parm_u_ofdm_transmission_mode,
+               parm_u_ofdm_guard_interval,
+               parm_u_ofdm_hierarchy_information,
+               parm_inversion,
+               feparm.system,
+               feparm.plpid);
+       oparm.setDVBT(feparm);
        return 0;
 }
 
@@ -2376,15 +2510,16 @@ RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
 
        int res=0;
 
-       if (!m_sn && !m_simulate)
+       int type;
+       if (where.getSystem(type) < 0)
        {
-               eDebug("no frontend device opened... do not try to tune !!!");
-               res = -ENODEV;
+               res = -EINVAL;
                goto tune_error;
        }
 
-       if (m_type == -1)
+       if (!m_sn && !m_simulate)
        {
+               eDebug("no frontend device opened... do not try to tune !!!");
                res = -ENODEV;
                goto tune_error;
        }
@@ -2396,7 +2531,7 @@ RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
 
        where.calcLockTimeout(timeout);
 
-       switch (m_type)
+       switch (type)
        {
        case feSatellite:
        {
@@ -2471,6 +2606,11 @@ RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
 
                break;
        }
+       default:
+       {
+                       res = -EINVAL;
+                       goto tune_error;
+       }
        }
 
        m_sec_sequence.current() = m_sec_sequence.begin();
@@ -2503,14 +2643,8 @@ RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateCh
 
 RESULT eDVBFrontend::setVoltage(int voltage)
 {
-       if (m_type == feCable)
-               return -1;
-#if HAVE_DVB_API_VERSION < 3
-       secVoltage vlt;
-#else
        bool increased=false;
        fe_sec_voltage_t vlt;
-#endif
        m_data[CUR_VOLTAGE]=voltage;
        switch (voltage)
        {
@@ -2519,22 +2653,12 @@ RESULT eDVBFrontend::setVoltage(int voltage)
                vlt = SEC_VOLTAGE_OFF;
                break;
        case voltage13_5:
-#if HAVE_DVB_API_VERSION < 3
-               vlt = SEC_VOLTAGE_13_5;
-               break;
-#else
                increased = true;
-#endif
        case voltage13:
                vlt = SEC_VOLTAGE_13;
                break;
        case voltage18_5:
-#if HAVE_DVB_API_VERSION < 3
-               vlt = SEC_VOLTAGE_18_5;
-               break;
-#else
                increased = true;
-#endif
        case voltage18:
                vlt = SEC_VOLTAGE_18;
                break;
@@ -2543,13 +2667,9 @@ RESULT eDVBFrontend::setVoltage(int voltage)
        }
        if (m_simulate)
                return 0;
-#if HAVE_DVB_API_VERSION < 3
-       return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
-#else
-       if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
-               perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
+
+       ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased);
        return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
-#endif
 }
 
 RESULT eDVBFrontend::getState(int &state)
@@ -2560,13 +2680,7 @@ RESULT eDVBFrontend::getState(int &state)
 
 RESULT eDVBFrontend::setTone(int t)
 {
-       if (m_type != feSatellite)
-               return -1;
-#if HAVE_DVB_API_VERSION < 3
-       secToneMode_t tone;
-#else
        fe_sec_tone_mode_t tone;
-#endif
        m_data[CUR_TONE]=t;
        switch (t)
        {
@@ -2581,63 +2695,34 @@ RESULT eDVBFrontend::setTone(int t)
        }
        if (m_simulate)
                return 0;
-#if HAVE_DVB_API_VERSION < 3   
-       return ::ioctl(m_secfd, SEC_SET_TONE, tone);
-#else  
+       
        return ::ioctl(m_fd, FE_SET_TONE, tone);
-#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 (m_simulate)
                return 0;
-#if HAVE_DVB_API_VERSION < 3
-       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
+
        struct dvb_diseqc_master_cmd cmd;
        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 (m_simulate)
                return 0;
-#if HAVE_DVB_API_VERSION < 3
-       secMiniCmd cmd = SEC_MINI_NONE;
-#else
        fe_sec_mini_cmd_t cmd = SEC_MINI_A;
-#endif
        if ( burst == eDVBSatelliteDiseqcParameters::A )
                cmd = SEC_MINI_A;
        else if ( burst == eDVBSatelliteDiseqcParameters::B )
                cmd = SEC_MINI_B;
-#if HAVE_DVB_API_VERSION < 3
-       if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
-               return -EINVAL;
-#else
        if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
                return -EINVAL;
-#endif
        return 0;
 }
 
@@ -2656,6 +2741,24 @@ RESULT eDVBFrontend::setSecSequence(eSecCommandList &list)
        return 0;
 }
 
+bool eDVBFrontend::isScheduledSendDiseqc()
+{
+       bool has_senddiseqc = false;
+       if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
+       {
+               eSecCommandList::iterator cur = m_sec_sequence.current();
+               while(cur != m_sec_sequence.end())
+               {
+                       if (((cur++)->cmd == eSecCommand::SEND_DISEQC))
+                       {
+                               has_senddiseqc = true;
+                               break;
+                       }
+               }
+       }
+       return has_senddiseqc;
+}
+
 RESULT eDVBFrontend::getData(int num, long &data)
 {
        if ( num < NUM_DATA_ENTRIES )
@@ -2679,40 +2782,132 @@ RESULT eDVBFrontend::setData(int num, long val)
 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
 {
        int type;
-       if (feparm->getSystem(type) || type != m_type || !m_enabled)
+       int score = 0;
+       bool preferred = (eDVBFrontend::getPreferredFrontend() >= 0 && m_slotid == eDVBFrontend::getPreferredFrontend());
+
+       if (feparm->getSystem(type) || !m_enabled)
                return 0;
-       if (m_type == eDVBFrontend::feSatellite)
+
+       if (type == eDVBFrontend::feSatellite)
        {
-               ASSERT(m_sec);
                eDVBFrontendParametersSatellite sat_parm;
-               int ret = feparm->getDVBS(sat_parm);
-               ASSERT(!ret);
-               if (sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S2 && !m_can_handle_dvbs2)
+               bool can_handle_dvbs, can_handle_dvbs2;
+               can_handle_dvbs = supportsDeliverySystem(SYS_DVBS, true);
+               can_handle_dvbs2 = supportsDeliverySystem(SYS_DVBS2, true);
+               if (feparm->getDVBS(sat_parm) < 0)
+               {
                        return 0;
-               ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
-               if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S && m_can_handle_dvbs2)
-                       ret -= 1;
-               return ret;
-       }
-       else if (m_type == eDVBFrontend::feCable)
-               return 2;  // more prio for cable frontends
-       else if (m_type == eDVBFrontend::feTerrestrial)
-               return 1;
-       return 0;
+               }
+               if (sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S2 && !can_handle_dvbs2)
+               {
+                       return 0;
+               }
+               if (sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S && !can_handle_dvbs)
+               {
+                       return 0;
+               }
+               score = m_sec ? m_sec->canTune(sat_parm, this, 1 << m_slotid) : 0;
+               if (score > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S && can_handle_dvbs2)
+               {
+                       /* prefer to use a S tuner, try to keep S2 free for S2 transponders */
+                       score--;
+               }
+       }
+
+       else if (type == eDVBFrontend::feCable)
+       {
+               eDVBFrontendParametersCable cab_parm;
+               if (feparm->getDVBC(cab_parm) < 0)
+               {
+                       return 0;
+               }
+#if defined SYS_DVBC_ANNEX_A
+               if (!supportsDeliverySystem(SYS_DVBC_ANNEX_A, true))
+#else
+               if (!supportsDeliverySystem(SYS_DVBC_ANNEX_AC, true))
+#endif
+               {
+                       return 0;
+               }
+               score = 2;
+       }
+
+       else if (type == eDVBFrontend::feTerrestrial)
+       {
+               eDVBFrontendParametersTerrestrial ter_parm;
+               bool can_handle_dvbt, can_handle_dvbt2;
+               can_handle_dvbt = supportsDeliverySystem(SYS_DVBT, true);
+               can_handle_dvbt2 = supportsDeliverySystem(SYS_DVBT2, true);
+               if (feparm->getDVBT(ter_parm) < 0)
+               {
+                       return 0;
+               }
+               if (ter_parm.system == eDVBFrontendParametersTerrestrial::System_DVB_T && !can_handle_dvbt)
+               {
+                       return 0;
+               }
+               if (ter_parm.system == eDVBFrontendParametersTerrestrial::System_DVB_T2 && !can_handle_dvbt2)
+               {
+                       return 0;
+               }
+               score = 2;
+               if (ter_parm.system == eDVBFrontendParametersTerrestrial::System_DVB_T && can_handle_dvbt2)
+               {
+                       /* prefer to use a T tuner, try to keep T2 free for T2 transponders */
+                       score--;
+               }
+       }
+
+       if (score && preferred)
+       {
+               /* make 'sure' we always prefer this frontend */
+               score += 100000;
+       }
+
+       return score;
+}
+
+bool eDVBFrontend::supportsDeliverySystem(const fe_delivery_system_t &sys, bool obeywhitelist)
+{
+       std::map<fe_delivery_system_t, bool>::iterator it = m_delsys.find(sys);
+       if (it != m_delsys.end() && it->second)
+       {
+               if (obeywhitelist && !m_delsys_whitelist.empty())
+               {
+                       it = m_delsys_whitelist.find(sys);
+                       if (it == m_delsys_whitelist.end() || !it->second) return false;
+               }
+               return true;
+       }
+       return false;
+}
+
+void eDVBFrontend::setDeliverySystemWhitelist(const std::vector<fe_delivery_system_t> &whitelist)
+{
+       m_delsys_whitelist.clear();
+       for (unsigned int i = 0; i < whitelist.size(); i++)
+       {
+               m_delsys_whitelist[whitelist[i]] = true;
+       }
+       if (m_simulate_fe)
+       {
+               m_simulate_fe->setDeliverySystemWhitelist(whitelist);
+       }
 }
 
 bool eDVBFrontend::setSlotInfo(ePyObject obj)
 {
-       ePyObject Id, Descr, Enabled, IsDVBS2, frontendId;
-       if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 5)
+       ePyObject Id, Descr, Enabled, IsDVBS2, IsDVBT2, frontendId;
+       if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 6)
                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);
-       frontendId = PyTuple_GET_ITEM(obj, 4);
+       IsDVBT2 = PyTuple_GET_ITEM(obj, 4);
+       frontendId = PyTuple_GET_ITEM(obj, 5);
        m_slotid = PyInt_AsLong(Id);
-       if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2) || !PyInt_Check(frontendId))
+       if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2) || !PyBool_Check(IsDVBT2) || !PyInt_Check(frontendId))
                goto arg_error;
        strcpy(m_description, PyString_AS_STRING(Descr));
        if (PyInt_AsLong(frontendId) == -1 || PyInt_AsLong(frontendId) != m_dvbid) {
@@ -2720,15 +2915,25 @@ bool eDVBFrontend::setSlotInfo(ePyObject obj)
 //                     m_slotid, m_description);
                return false;
        }
-       m_enabled = Enabled == Py_True;
+       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") ||
                !!strstr(m_description, "Alps BSBE2") ||
                !!strstr(m_description, "Alps -S") ||
                !!strstr(m_description, "BCM4501");
-       m_can_handle_dvbs2 = IsDVBS2 == Py_True;
-       eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
-               m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
+       if (IsDVBS2 == Py_True)
+       {
+               /* HACK for legacy dvb api without DELSYS support */
+               m_delsys[SYS_DVBS2] = true;
+       }
+       if (IsDVBT2 == Py_True)
+       {
+               /* HACK for legacy dvb api without DELSYS support */
+               m_delsys[SYS_DVBT2] = true;
+       }
+
+       eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s, DVB-T2 %s",
+               m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", Enabled == Py_True ? "Yes" : "No", IsDVBS2 == Py_True ? "Yes" : "No", IsDVBT2 == Py_True ? "Yes" : "No" );
        return true;
 arg_error:
        PyErr_SetString(PyExc_StandardError,