+ enum { REALVAL, REGVAL };
+ const long CN_lookup[31][2] = {
+ {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
+ {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
+ {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
+ {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
+ {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
+ {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
+ {300,890}
+ };
+ int add=strchr(m_description, '.') ? 0xA250 : 0xA100;
+ long regval = 0xFFFF - ((snr / 3) + add), // revert some dvb api calulations to get the real register value
+ Imin=0,
+ Imax=30,
+ i;
+ if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
+ {
+ while((Imax-Imin)>1)
+ {
+ i=(Imax+Imin)/2;
+ if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[i][REGVAL]))
+ Imax = i;
+ else
+ Imin = i;
+ }
+ ret = (((regval - CN_lookup[Imin][REGVAL])
+ * (CN_lookup[Imax][REALVAL] - CN_lookup[Imin][REALVAL])
+ / (CN_lookup[Imax][REGVAL] - CN_lookup[Imin][REGVAL]))
+ + CN_lookup[Imin][REALVAL]) * 10;
+ }
+ else
+ ret = 100;
+ }
+ }
+ else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
+ !strcmp(m_description, "Alps -S") ||
+ !strcmp(m_description, "Philips -S") ||
+ !strcmp(m_description, "LG -S") )
+ {
+ sat_max = 1500;
+ ret = (int)((snr-39075)/17.647);
+ } else if (!strcmp(m_description, "Alps BSBE2"))
+ {
+ ret = (int)((snr >> 7) * 10);
+ } else if (!strcmp(m_description, "Philips CU1216Mk3"))
+ {
+ int mse = (~snr) & 0xFF;
+ switch (parm_u_qam_modulation) {
+ case QAM_16: ret = fe_udiv(1950000, (32 * mse) + 138) + 1000; break;
+ case QAM_32: ret = fe_udiv(2150000, (40 * mse) + 500) + 1350; break;
+ case QAM_64: ret = fe_udiv(2100000, (40 * mse) + 500) + 1250; break;
+ case QAM_128: ret = fe_udiv(1850000, (38 * mse) + 400) + 1380; break;
+ case QAM_256: ret = fe_udiv(1800000, (100 * mse) + 40) + 2030; break;
+ default: break;
+ }
+ } else if (!strcmp(m_description, "Philips TU1216"))
+ {
+ snr = 0xFF - (snr & 0xFF);
+ if (snr != 0)
+ ret = 10 * (int)(-100 * (log10(snr) - log10(255)));
+ }
+ else if (strstr(m_description, "BCM4506") || strstr(m_description, "BCM4505"))
+ ret = (snr * 100) >> 8;
+
+ if (type == signalQuality)
+ {
+ if (ret == 0x12345678) // no snr db calculation avail.. return untouched snr value..
+ return snr;
+ switch(m_type)
+ {
+ case feSatellite:
+ return ret >= sat_max ? 65536 : ret * 65536 / sat_max;
+ case feCable: // we assume a max of 42db here
+ return ret >= 4200 ? 65536 : ret * 65536 / 4200;
+ case feTerrestrial: // we assume a max of 24db here
+ return ret >= 2400 ? 65536 : ret * 65536 / 2400;
+ }
+ }
+/* else
+ eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
+ return ret;
+ }
+ case signalPower:
+ {
+ uint16_t strength=0;
+ if (!m_simulate)
+ {
+ if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
+ eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
+ }
+ return strength;
+ }
+ 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 )
+ eDebug("FE_READ_STATUS failed (%m)");
+ return !!(status&FE_HAS_LOCK);
+ }
+ return 1;
+ }
+ 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 )
+ eDebug("FE_READ_STATUS failed (%m)");
+ return !!(status&FE_HAS_SYNC);
+ }
+ return 1;
+ }
+ case frontendNumber:
+ return m_slotid;
+ }
+ return 0;
+}
+
+void PutToDict(ePyObject &dict, const char*key, long value)
+{
+ ePyObject item = PyInt_FromLong(value);
+ if (item)
+ {
+ if (PyDict_SetItemString(dict, key, item))
+ eDebug("put %s to dict failed", key);
+ Py_DECREF(item);
+ }
+ else
+ eDebug("could not create PyObject for %s", key);
+}
+
+void PutToDict(ePyObject &dict, const char*key, ePyObject item)
+{
+ if (item)
+ {
+ if (PyDict_SetItemString(dict, key, item))
+ eDebug("put %s to dict failed", key);
+ Py_DECREF(item);
+ }
+ else
+ eDebug("invalid PyObject for %s", key);
+}
+
+void PutToDict(ePyObject &dict, const char*key, const char *value)
+{
+ ePyObject item = PyString_FromString(value);
+ if (item)
+ {
+ if (PyDict_SetItemString(dict, key, item))
+ eDebug("put %s to dict failed", key);
+ Py_DECREF(item);
+ }
+ else
+ eDebug("could not create PyObject for %s", key);
+}
+
+void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
+{
+ PutToDict(dict, "tuner_type", "DVB-S");
+ PutToDict(dict, "frequency", feparm.frequency);
+ PutToDict(dict, "symbol_rate", feparm.symbol_rate);
+ PutToDict(dict, "orbital_position", feparm.orbital_position);
+ PutToDict(dict, "inversion", feparm.inversion);
+ PutToDict(dict, "fec_inner", feparm.fec);
+ PutToDict(dict, "modulation", feparm.modulation);
+ PutToDict(dict, "polarization", feparm.polarisation);
+ if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S2)
+ {
+ PutToDict(dict, "rolloff", feparm.rolloff);
+ PutToDict(dict, "pilot", feparm.pilot);
+ }
+ PutToDict(dict, "system", feparm.system);
+}
+
+void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
+{
+ PutToDict(dict, "tuner_type", "DVB-T");
+ PutToDict(dict, "frequency", feparm.frequency);
+ PutToDict(dict, "bandwidth", feparm.bandwidth);
+ PutToDict(dict, "code_rate_lp", feparm.code_rate_LP);
+ PutToDict(dict, "code_rate_hp", feparm.code_rate_HP);
+ PutToDict(dict, "constellation", feparm.modulation);
+ PutToDict(dict, "transmission_mode", feparm.transmission_mode);
+ PutToDict(dict, "guard_interval", feparm.guard_interval);
+ PutToDict(dict, "hierarchy_information", feparm.hierarchy);
+ PutToDict(dict, "inversion", feparm.inversion);
+}
+
+void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
+{
+ PutToDict(dict, "tuner_type", "DVB-C");
+ PutToDict(dict, "frequency", feparm.frequency);
+ PutToDict(dict, "symbol_rate", feparm.symbol_rate);
+ PutToDict(dict, "modulation", feparm.modulation);
+ PutToDict(dict, "inversion", feparm.inversion);
+ 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)
+{
+ 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(parm_u_qpsk_fec_inner)
+ {
+ 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_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
+ case FEC_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
+ case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
+ case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
+ case FEC_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
+ case FEC_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
+ case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
+ case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
+ default: eDebug("got unsupported FEC from frontend! report as FEC_AUTO!\n");
+ }
+
+ switch (p[0].u.data)
+ {
+ 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)
+ {
+ default: eDebug("got unsupported rolloff from frontend! report as 0_20!");
+ case ROLLOFF_20: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
+ case ROLLOFF_25: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
+ case ROLLOFF_35: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
+ }
+ PutToDict(dict, "rolloff", tmp);
+
+ switch (p[3].u.data)
+ {
+ case PILOT_OFF: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
+ case PILOT_ON: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
+ case PILOT_AUTO: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
+ }
+ PutToDict(dict, "pilot", tmp);
+
+ tmp = eDVBFrontendParametersSatellite::System_DVB_S2; break;
+ }
+ }
+ PutToDict(dict, "system", tmp);
+
+ switch (p[1].u.data)
+ {
+ 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(parm_u_qpsk_fec_inner)
+ {
+ 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
+ }
+ 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);
+}
+#endif
+
+static void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
+{
+ 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;
+ }
+ 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;
+ }
+ PutToDict(dict, "modulation", tmp);
+}
+
+static void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
+{
+ long tmp=0;
+ PutToDict(dict, "frequency", parm_frequency);
+ switch (parm_u_ofdm_bandwidth)
+ {
+ 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;
+ }
+ 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;
+ }
+ 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;
+ }
+ PutToDict(dict, "code_rate_hp", tmp);
+ switch (parm_u_ofdm_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;
+ }
+ PutToDict(dict, "constellation", tmp);
+ switch (parm_u_ofdm_transmission_mode)
+ {
+ case TRANSMISSION_MODE_2K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_2k; break;
+ case TRANSMISSION_MODE_8K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_8k; break;
+ default:
+ case TRANSMISSION_MODE_AUTO: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto; break;
+ }
+ PutToDict(dict, "transmission_mode", tmp);
+ switch (parm_u_ofdm_guard_interval)
+ {
+ 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;
+ case GUARD_INTERVAL_1_4: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_4; break;
+ default:
+ case GUARD_INTERVAL_AUTO: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_Auto; break;
+ }
+ PutToDict(dict, "guard_interval", tmp);
+ switch (parm_u_ofdm_hierarchy_information)
+ {
+ case HIERARCHY_NONE: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_None; break;
+ case HIERARCHY_1: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_1; break;
+ case HIERARCHY_2: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_2; break;
+ case HIERARCHY_4: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_4; break;
+ default:
+ case HIERARCHY_AUTO: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_Auto; break;
+ }
+ PutToDict(dict, "hierarchy_information", tmp);
+}
+
+void eDVBFrontend::getFrontendStatus(ePyObject dest)
+{
+ if (dest && PyDict_Check(dest))
+ {
+ const char *tmp = "UNKNOWN";
+ switch(m_state)
+ {
+ case stateIdle:
+ tmp="IDLE";
+ break;
+ case stateTuning:
+ tmp="TUNING";
+ break;
+ case stateFailed:
+ tmp="FAILED";
+ break;
+ case stateLock:
+ tmp="LOCKED";
+ break;
+ case stateLostLock:
+ tmp="LOSTLOCK";
+ break;
+ default:
+ break;
+ }
+ PutToDict(dest, "tuner_state", tmp);
+ PutToDict(dest, "tuner_locked", readFrontendData(locked));
+ PutToDict(dest, "tuner_synced", readFrontendData(synced));
+ PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
+ PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
+ int sigQualitydB = readFrontendData(signalQualitydB);
+ if (sigQualitydB == 0x12345678) // not support yet
+ {
+ ePyObject obj=Py_None;
+ Py_INCREF(obj);
+ PutToDict(dest, "tuner_signal_quality_db", obj);
+ }
+ else
+ PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
+ PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
+ }
+}
+
+void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
+{
+ if (dest && PyDict_Check(dest))
+ {
+ FRONTENDPARAMETERS front;
+#if HAVE_DVB_API_VERSION >= 5
+ struct dtv_property p[4];
+ 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;
+#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)
+ {
+ eDebug("FE_GET_PROPERTY failed (%m)");
+ original = true;
+ }
+#endif
+ else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
+ {
+ eDebug("FE_GET_FRONTEND failed (%m)");
+ original = true;
+ }
+ if (original)
+ {
+ switch(m_type)
+ {
+ case feSatellite:
+ PutSatelliteDataToDict(dest, oparm.sat);
+ break;
+ case feCable:
+ PutCableDataToDict(dest, oparm.cab);
+ break;
+ case feTerrestrial:
+ PutTerrestrialDataToDict(dest, oparm.ter);
+ 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)
+ {
+ 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
+ break;
+ case feCable:
+ fillDictWithCableData(dest, parm);
+ break;
+ case feTerrestrial:
+ fillDictWithTerrestrialData(dest, parm);
+ break;
+ }
+ }
+ }
+}
+
+void eDVBFrontend::getFrontendData(ePyObject dest)
+{
+ if (dest && PyDict_Check(dest))
+ {
+ const char *tmp=0;
+ PutToDict(dest, "tuner_number", m_slotid);
+ switch(m_type)
+ {
+ case feSatellite:
+ tmp = "DVB-S";
+ break;
+ case feCable:
+ tmp = "DVB-C";
+ break;
+ case feTerrestrial:
+ tmp = "DVB-T";
+ break;
+ default:
+ tmp = "UNKNOWN";
+ break;
+ }
+ PutToDict(dest, "tuner_type", tmp);
+ }
+}
+
+#ifndef FP_IOCTL_GET_ID
+#define FP_IOCTL_GET_ID 0
+#endif
+int eDVBFrontend::readInputpower()
+{
+ if (m_simulate)
+ return 0;
+ int power=m_slotid; // this is needed for read inputpower from the correct tuner !
+ char proc_name[64];
+ sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
+ FILE *f=fopen(proc_name, "r");
+ if (f)
+ {
+ if (fscanf(f, "%d", &power) != 1)
+ eDebug("read %s failed!! (%m)", proc_name);
+ else
+ eDebug("%s is %d\n", proc_name, power);
+ fclose(f);
+ }
+ else
+ {
+ // open front prozessor
+ int fp=::open("/dev/dbox/fp0", O_RDWR);
+ if (fp < 0)
+ {
+ eDebug("couldn't open fp");
+ return -1;
+ }
+ static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
+ if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
+ {
+ eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
+ return -1;
+ }
+ ::close(fp);
+ }
+
+ return power;
+}
+
+bool eDVBFrontend::setSecSequencePos(int steps)
+{
+ eDebugNoSimulate("set sequence pos %d", steps);
+ if (!steps)
+ return false;
+ while( steps > 0 )
+ {
+ if (m_sec_sequence.current() != m_sec_sequence.end())
+ ++m_sec_sequence.current();
+ --steps;
+ }
+ while( steps < 0 )
+ {
+ if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
+ --m_sec_sequence.current();
+ ++steps;
+ }
+ return true;
+}
+
+void eDVBFrontend::tuneLoop() // called by m_tuneTimer
+{
+ int delay=0;
+ eDVBFrontend *sec_fe = this;
+ eDVBRegisteredFrontend *regFE = 0;
+ long tmp = m_data[LINKED_PREV_PTR];
+ while ( tmp != -1 )
+ {
+ eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
+ sec_fe = prev->m_frontend;
+ tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
+ if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
+ int state = sec_fe->m_state;
+ // 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;
+ }
+ // sec_fe is closed... we must reopen it here..
+ if (state == stateClosed)
+ {
+ regFE = prev;
+ prev->inc_use();
+ }
+ }
+ }
+
+ if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
+ {
+ long *sec_fe_data = sec_fe->m_data;
+// eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
+ switch (m_sec_sequence.current()->cmd)
+ {
+ case eSecCommand::SLEEP:
+ delay = m_sec_sequence.current()++->msec;
+ eDebugNoSimulate("[SEC] sleep %dms", delay);
+ break;
+ case eSecCommand::GOTO:
+ if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
+ ++m_sec_sequence.current();
+ break;
+ case eSecCommand::SET_VOLTAGE:
+ {
+ int voltage = m_sec_sequence.current()++->voltage;
+ eDebugNoSimulate("[SEC] setVoltage %d", voltage);
+ sec_fe->setVoltage(voltage);
+ break;
+ }
+ case eSecCommand::IF_VOLTAGE_GOTO:
+ {
+ eSecCommand::pair &compare = m_sec_sequence.current()->compare;
+ if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
+ break;
+ ++m_sec_sequence.current();
+ break;
+ }
+ case eSecCommand::IF_NOT_VOLTAGE_GOTO:
+ {
+ eSecCommand::pair &compare = m_sec_sequence.current()->compare;
+ if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
+ break;
+ ++m_sec_sequence.current();
+ break;
+ }
+ case eSecCommand::IF_TONE_GOTO:
+ {
+ eSecCommand::pair &compare = m_sec_sequence.current()->compare;
+ if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
+ break;
+ ++m_sec_sequence.current();
+ break;
+ }
+ case eSecCommand::IF_NOT_TONE_GOTO:
+ {
+ eSecCommand::pair &compare = m_sec_sequence.current()->compare;
+ if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
+ break;
+ ++m_sec_sequence.current();
+ break;
+ }
+ case eSecCommand::SET_TONE:
+ eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
+ sec_fe->setTone(m_sec_sequence.current()++->tone);
+ break;
+ case eSecCommand::SEND_DISEQC:
+ sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
+ eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
+ for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
+ eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
+ if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
+ eDebugNoSimulate("(DiSEqC reset)");
+ else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
+ eDebugNoSimulate("(DiSEqC peripherial power on)");
+ else
+ eDebugNoSimulate("");
+ ++m_sec_sequence.current();
+ break;
+ case eSecCommand::SEND_TONEBURST:
+ eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
+ sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
+ break;
+ case eSecCommand::SET_FRONTEND:
+ {
+ int enableEvents = (m_sec_sequence.current()++)->val;
+ eDebugNoSimulate("[SEC] setFrontend %d", enableEvents);
+ setFrontend(enableEvents);
+ break;
+ }
+ case eSecCommand::START_TUNE_TIMEOUT:
+ {
+ int tuneTimeout = m_sec_sequence.current()->timeout;
+ eDebugNoSimulate("[SEC] startTuneTimeout %d", tuneTimeout);
+ if (!m_simulate)
+ m_timeout->start(tuneTimeout, 1);
+ ++m_sec_sequence.current();
+ break;
+ }
+ case eSecCommand::SET_TIMEOUT:
+ m_timeoutCount = m_sec_sequence.current()++->val;
+ eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
+ break;
+ case eSecCommand::IF_TIMEOUT_GOTO:
+ if (!m_timeoutCount)
+ {
+ eDebugNoSimulate("[SEC] rotor timout");
+ setSecSequencePos(m_sec_sequence.current()->steps);