X-Git-Url: http://code.vuplus.com/gitweb/?p=vuplus_dvbapp;a=blobdiff_plain;f=lib%2Fdvb%2Ffrontend.cpp;h=bc3a88da3c00827fe167ddad414d71f29986ae9a;hp=e0291ec1731eb91ae4477d2df67c813dcb817b56;hb=a4d95aed350cfe26a278ad7f9475bc8be77ff9ff;hpb=8d85982d460e7cc0eb26f1bf79dc345d12a11858 diff --git a/lib/dvb/frontend.cpp b/lib/dvb/frontend.cpp index e0291ec..5718896 100644 --- a/lib/dvb/frontend.cpp +++ b/lib/dvb/frontend.cpp @@ -49,9 +49,7 @@ #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 -#ifdef FEC_9_10 - #warning "FEC_9_10 already exist in dvb api ... it seems it is now ready for DVB-S2" -#else +#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) @@ -70,6 +68,16 @@ #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 @@ -379,7 +387,7 @@ RESULT eDVBFrontendParameters::calculateDifference(const iDVBFrontendParameters terrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC_Auto) diff = 1 << 30; else - diff = abs(terrestrial.frequency - oterrestrial.frequency); + diff = abs(terrestrial.frequency - oterrestrial.frequency) / 1000; return 0; default: return -1; @@ -403,7 +411,7 @@ RESULT eDVBFrontendParameters::getHash(unsigned long &hash) const return 0; case iDVBFrontend::feTerrestrial: hash = 0xEEEE0000; - hash |= (terrestrial.frequency/1000)&0xFFFF; + hash |= (terrestrial.frequency/1000000)&0xFFFF; return 0; default: return -1; @@ -445,10 +453,10 @@ DEFINE_REF(eDVBFrontend); int eDVBFrontend::PriorityOrder=0; -eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok, bool simulate) - :m_simulate(simulate), m_enabled(false), m_type(-1), m_dvbid(fe), m_slotid(fe) - ,m_fd(-1), m_need_rotor_workaround(false), m_can_handle_dvbs2(false) - , m_timeout(0), m_tuneTimer(0) +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 @@ -475,9 +483,16 @@ eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok, bool simulate) closeFrontend(); } +void eDVBFrontend::reopenFrontend() +{ + sleep(1); + m_type = -1; + openFrontend(); +} + int eDVBFrontend::openFrontend() { - if (m_sn) + if (m_state != stateClosed) return -1; // already opened m_state=stateIdle; @@ -488,10 +503,10 @@ int eDVBFrontend::openFrontend() #else dvb_frontend_info fe_info; #endif - eDebugNoSimulate("opening frontend %d", m_dvbid); - if (m_fd < 0) + if (!m_simulate) { - if (!m_simulate || m_type == -1) + eDebug("opening frontend %d", m_dvbid); + if (m_fd < 0) { m_fd = ::open(m_filename, O_RDWR|O_NONBLOCK); if (m_fd < 0) @@ -500,74 +515,73 @@ int eDVBFrontend::openFrontend() return -1; } } - } - else - eWarning("frontend %d already opened", m_dvbid); - if (m_type == -1) - { - if (::ioctl(m_fd, FE_GET_INFO, &fe_info) < 0) + else + eWarning("frontend %d already opened", m_dvbid); + if (m_type == -1) { - eWarning("ioctl FE_GET_INFO failed"); - ::close(m_fd); - m_fd = -1; - return -1; - } + if (::ioctl(m_fd, FE_GET_INFO, &fe_info) < 0) + { + eWarning("ioctl FE_GET_INFO failed"); + ::close(m_fd); + m_fd = -1; + return -1; + } - 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; + 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; + } + if (m_simulate_fe) + m_simulate_fe->m_type = m_type; + eDebugNoSimulate("detected %s frontend", "satellite\0cable\0 terrestrial"+fe_info.type*10); } - eDebugNoSimulate("detected %s frontend", "satellite\0cable\0 terrestrial"+fe_info.type*10); - } #if HAVE_DVB_API_VERSION < 3 - if (m_type == iDVBFrontend::feSatellite) - { - if (m_secfd < 0) - { - if (!m_simulate) + if (m_type == iDVBFrontend::feSatellite) + { + if (m_secfd < 0) { - m_secfd = ::open(m_sec_filename, O_RDWR); - if (m_secfd < 0) + if (!m_simulate) { - eWarning("failed! (%s) %m", m_sec_filename); - ::close(m_fd); - m_fd=-1; - return -1; + 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); - } + else + eWarning("sec %d already opened", m_dvbid); + } #endif - setTone(iDVBFrontend::toneOff); - setVoltage(iDVBFrontend::voltageOff); - - if (!m_simulate) - { m_sn = eSocketNotifier::create(eApp, m_fd, eSocketNotifier::Read, false); CONNECT(m_sn->activated, eDVBFrontend::feEvent); } + setTone(iDVBFrontend::toneOff); + setVoltage(iDVBFrontend::voltageOff); + return 0; } -int eDVBFrontend::closeFrontend(bool force) +int eDVBFrontend::closeFrontend(bool force, bool no_delayed) { if (!force && m_data[CUR_VOLTAGE] != -1 && m_data[CUR_VOLTAGE] != iDVBFrontend::voltageOff) { @@ -590,13 +604,36 @@ int eDVBFrontend::closeFrontend(bool force) eDebugNoSimulate("close frontend %d", m_dvbid); if (m_data[SATCR] != -1) { - turnOffSatCR(m_data[SATCR]); + if (!no_delayed) + { + m_sec->prepareTurnOffSatCR(*this, m_data[SATCR]); + m_tuneTimer->start(0, true); + if(!m_tuneTimer->isActive()) + { + int timeout=0; + eDebug("[turnOffSatCR] no mainloop"); + while(true) + { + timeout = tuneLoopInt(); + if (timeout == -1) + break; + usleep(timeout*1000); // blockierendes wait.. eTimer gibts ja nicht mehr + } + } + else + eDebug("[turnOffSatCR] running mainloop"); + return 0; + } + else + m_data[ROTOR_CMD] = -1; } + setTone(iDVBFrontend::toneOff); setVoltage(iDVBFrontend::voltageOff); m_tuneTimer->stop(); + if (m_sec && !m_simulate) - m_sec->setRotorMoving(false); + m_sec->setRotorMoving(m_slotid, false); if (!::close(m_fd)) m_fd=-1; else @@ -652,32 +689,40 @@ void eDVBFrontend::feEvent(int w) if (res && (errno == EAGAIN)) break; - if (res) - { - eWarning("FE_GET_EVENT failed! %m"); - return; - } - 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_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off"); + 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) + if (m_tuning) { state = stateTuning; +#if HAVE_DVB_API_VERSION >= 3 + if (event.status & FE_TIMEDOUT) { + eDebug("FE_TIMEDOUT! ..abort"); + m_tuneTimer->stop(); + timeout(); + return; + } + ++m_tuning; +#else + m_tuneTimer->stop(); + timeout(); +#endif + } else { eDebug("stateLostLock"); state = stateLostLock; - sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc + if (!m_rotor_mode) + sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc } } if (m_state != state) @@ -735,7 +780,7 @@ int eDVBFrontend::readFrontendData(int type) float SDS_SNRE = snr << 16; float snr_in_db; - if (parm_u_qpsk_fec_inner <= FEC_AUTO) // DVB-S1 / QPSK + if (oparm.sat.system == eDVBFrontendParametersSatellite::System_DVB_S) // DVB-S1 / QPSK { static float SNR_COEFF[6] = { 100.0 / 4194304.0, @@ -767,7 +812,7 @@ int eDVBFrontend::readFrontendData(int type) float fval1 = SDS_SNRE / 268435456.0, fval2, fval3, fval4; - if (parm_u_qpsk_fec_inner <= FEC_S2_QPSK_9_10) // DVB-S2 QPSK + if (oparm.sat.modulation == eDVBFrontendParametersSatellite::Modulation_QPSK) { fval2 = 6.76; fval3 = 4.35; @@ -789,7 +834,7 @@ int eDVBFrontend::readFrontendData(int type) ret = (int)(snr_in_db * 100); } else if (strstr(m_description, "Alps BSBE1 C01A") || - !strcmp(m_description, "Alps -S(STV0288)")) + strstr(m_description, "Alps -S(STV0288)")) { if (snr == 0) ret = 0; @@ -858,6 +903,21 @@ int eDVBFrontend::readFrontendData(int type) 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; + else if (!strcmp(m_description, "CXD1981")) + { + int mse = (~snr) & 0xFF; + switch (parm_u_qam_modulation) { + case QAM_16: + case QAM_64: + case QAM_256: ret = (int)(-950 * log(((double)mse) / 760)); break; + case QAM_32: + case QAM_128: ret = (int)(-875 * log(((double)mse) / 650)); break; + + default: break; + } + } if (type == signalQuality) { @@ -961,26 +1021,134 @@ void PutToDict(ePyObject &dict, const char*key, const char *value) eDebug("could not create PyObject for %s", key); } -void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, eDVBFrontend *fe) +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 freq_offset=0; long tmp=0; - fe->getData(eDVBFrontend::FREQ_OFFSET, freq_offset); 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"); + } + PutToDict(dict, "fec_inner", tmp); + + 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((int)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_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; @@ -1033,8 +1201,9 @@ void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, e #endif PutToDict(dict, "system", tmp); } +#endif -void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm) +static void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm) { long tmp=0; #if HAVE_DVB_API_VERSION < 3 @@ -1071,7 +1240,7 @@ void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm) PutToDict(dict, "modulation", tmp); } -void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm) +static void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm) { long tmp=0; PutToDict(dict, "frequency", parm_frequency); @@ -1192,51 +1361,78 @@ void eDVBFrontend::getTransponderData(ePyObject dest, bool original) { if (dest && PyDict_Check(dest)) { - switch(m_type) + 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) { - case feSatellite: - case feCable: - case feTerrestrial: + 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) { - FRONTENDPARAMETERS front; - if (m_fd == -1 && !original) - original = true; - else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0) - { - eDebug("FE_GET_FRONTEND failed (%m)"); - original = true; - } - { - const FRONTENDPARAMETERS &parm = original || m_simulate ? this->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: - fillDictWithSatelliteData(dest, original?parm:front, this); - break; - case feCable: - fillDictWithCableData(dest, original?parm:front); - break; - case feTerrestrial: - fillDictWithTerrestrialData(dest, original?parm:front); - break; - } - } + 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; } - default: - break; } } } @@ -1275,9 +1471,11 @@ int eDVBFrontend::readInputpower() 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) + char proc_name2[64]; + sprintf(proc_name, "/proc/stb/frontend/%d/lnb_sense", m_slotid); + sprintf(proc_name2, "/proc/stb/fp/lnb_sense%d", m_slotid); + FILE *f; + if ((f=fopen(proc_name, "r")) || (f=fopen(proc_name2, "r"))) { if (fscanf(f, "%d", &power) != 1) eDebug("read %s failed!! (%m)", proc_name); @@ -1326,9 +1524,14 @@ bool eDVBFrontend::setSecSequencePos(int steps) return true; } -void eDVBFrontend::tuneLoop() // called by m_tuneTimer +void eDVBFrontend::tuneLoop() { - int delay=0; + tuneLoopInt(); +} + +int eDVBFrontend::tuneLoopInt() // called by m_tuneTimer +{ + int delay=-1; eDVBFrontend *sec_fe = this; eDVBRegisteredFrontend *regFE = 0; long tmp = m_data[LINKED_PREV_PTR]; @@ -1346,7 +1549,7 @@ void eDVBFrontend::tuneLoop() // called by m_tuneTimer state = sec_fe->m_state; } // sec_fe is closed... we must reopen it here.. - if (state == eDVBFrontend::stateClosed) + if (state == stateClosed) { regFE = prev; prev->inc_use(); @@ -1358,6 +1561,7 @@ void eDVBFrontend::tuneLoop() // called by m_tuneTimer { long *sec_fe_data = sec_fe->m_data; // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd); + delay = 0; switch (m_sec_sequence.current()->cmd) { case eSecCommand::SLEEP: @@ -1429,14 +1633,18 @@ void eDVBFrontend::tuneLoop() // called by m_tuneTimer sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst); break; case eSecCommand::SET_FRONTEND: - eDebugNoSimulate("[SEC] setFrontend"); - setFrontend(); - ++m_sec_sequence.current(); + { + 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(m_sec_sequence.current()->timeout, 1); + m_timeout->start(tuneTimeout, 1); ++m_sec_sequence.current(); break; } @@ -1494,23 +1702,27 @@ void eDVBFrontend::tuneLoop() // called by m_tuneTimer int signal = 0; int isLocked = readFrontendData(locked); m_idleInputpower[0] = m_idleInputpower[1] = 0; - if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 50) || !cmd.lastSignal)) + --m_timeoutCount; + if (!m_timeoutCount && m_retryCount > 0) + --m_retryCount; + if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 40) || !cmd.lastSignal)) { if (cmd.lastSignal) eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal); else { eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount); - cmd.lastSignal = signal; + if (!cmd.okcount) + cmd.lastSignal = signal; } ++cmd.okcount; if (cmd.okcount > 4) { - eDebugNoSimulate("ok > 4 .. goto %d\n",cmd.steps); + eDebugNoSimulate("ok > 4 .. goto %d\n", cmd.steps); setSecSequencePos(cmd.steps); m_state = stateLock; m_stateChanged(this); - feEvent(-1); + feEvent(-1); // flush events m_sn->start(); break; } @@ -1521,9 +1733,6 @@ void eDVBFrontend::tuneLoop() // called by m_tuneTimer eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal); else eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount); - --m_timeoutCount; - if (!m_timeoutCount && m_retryCount > 0) - --m_retryCount; cmd.okcount=0; cmd.lastSignal=0; } @@ -1537,12 +1746,12 @@ void eDVBFrontend::tuneLoop() // called by m_tuneTimer break; case eSecCommand::SET_ROTOR_MOVING: if (!m_simulate) - m_sec->setRotorMoving(true); + m_sec->setRotorMoving(m_slotid, true); ++m_sec_sequence.current(); break; case eSecCommand::SET_ROTOR_STOPPED: if (!m_simulate) - m_sec->setRotorMoving(false); + m_sec->setRotorMoving(m_slotid, false); ++m_sec_sequence.current(); break; case eSecCommand::IF_INPUTPOWER_DELTA_GOTO: @@ -1555,6 +1764,9 @@ void eDVBFrontend::tuneLoop() // called by m_tuneTimer } int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1]; const char *txt = cmd.direction ? "running" : "stopped"; + --m_timeoutCount; + if (!m_timeoutCount && m_retryCount > 0) + --m_retryCount; eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d", txt, m_runningInputpower, @@ -1575,9 +1787,6 @@ void eDVBFrontend::tuneLoop() // called by m_tuneTimer else { eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt); - --m_timeoutCount; - if (!m_timeoutCount && m_retryCount > 0) - --m_retryCount; cmd.okcount=0; } ++m_sec_sequence.current(); @@ -1650,11 +1859,11 @@ void eDVBFrontend::tuneLoop() // called by m_tuneTimer int slotid = sec_fe->m_slotid; // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000 if (slotid < 2) - sprintf(dev, "/dev/i2c/%d", slotid); + sprintf(dev, "/dev/i2c-%d", slotid); else if (slotid == 2) - sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2 + sprintf(dev, "/dev/i2c-2"); // first nim socket on DM8000 use /dev/i2c-2 else if (slotid == 3) - sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4 + sprintf(dev, "/dev/i2c-4"); // second nim socket on DM8000 use /dev/i2c-4 int fd = ::open(dev, O_RDWR); unsigned char data[2]; @@ -1679,6 +1888,13 @@ void eDVBFrontend::tuneLoop() // called by m_tuneTimer ++m_sec_sequence.current(); break; } + case eSecCommand::DELAYED_CLOSE_FRONTEND: + { + eDebugNoSimulate("[SEC] delayed close frontend"); + closeFrontend(false, true); + ++m_sec_sequence.current(); + break; + } default: eDebugNoSimulate("[SEC] unhandled sec command %d", ++m_sec_sequence.current()->cmd); @@ -1691,19 +1907,83 @@ void eDVBFrontend::tuneLoop() // called by m_tuneTimer regFE->dec_use(); if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end()) tuneLoop(); + return delay; } -void eDVBFrontend::setFrontend() +void eDVBFrontend::setFrontend(bool recvEvents) { if (!m_simulate) { eDebug("setting frontend %d", m_dvbid); - m_sn->start(); - feEvent(-1); - if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1) + if (recvEvents) + m_sn->start(); + feEvent(-1); // flush events +#if HAVE_DVB_API_VERSION >= 5 + if (m_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) + { + case eDVBFrontendParametersSatellite::System_DVB_S: system = SYS_DVBS; break; + case eDVBFrontendParametersSatellite::System_DVB_S2: system = SYS_DVBS2; break; + }; + switch(oparm.sat.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) + { + 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) + { + case eDVBFrontendParametersSatellite::RollOff_alpha_0_20: rolloff = ROLLOFF_20; break; + case eDVBFrontendParametersSatellite::RollOff_alpha_0_25: rolloff = ROLLOFF_25; break; + case eDVBFrontendParametersSatellite::RollOff_alpha_0_35: rolloff = ROLLOFF_35; break; + }; + struct dtv_property p[10]; + struct dtv_properties cmdseq; + cmdseq.props = p; + p[0].cmd = DTV_CLEAR; + p[1].cmd = DTV_DELIVERY_SYSTEM, p[1].u.data = system; + p[2].cmd = DTV_FREQUENCY, p[2].u.data = parm_frequency; + p[3].cmd = DTV_MODULATION, p[3].u.data = modulation; + p[4].cmd = DTV_SYMBOL_RATE, p[4].u.data = parm_u_qpsk_symbol_rate; + p[5].cmd = DTV_INNER_FEC, p[5].u.data = parm_u_qpsk_fec_inner; + p[6].cmd = DTV_INVERSION, p[6].u.data = parm_inversion; + if (system == SYS_DVBS2) + { + p[7].cmd = DTV_ROLLOFF, p[7].u.data = rolloff; + p[8].cmd = DTV_PILOT, p[8].u.data = pilot; + p[9].cmd = DTV_TUNE; + cmdseq.num = 10; + } + else + { + p[7].cmd = DTV_TUNE; + cmdseq.num = 8; + } + if (ioctl(m_fd, FE_SET_PROPERTY, &cmdseq) == -1) + { + perror("FE_SET_PROPERTY failed"); + return; + } + } + else +#endif { - perror("FE_SET_FRONTEND failed"); - return; + if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1) + { + perror("FE_SET_FRONTEND failed"); + return; + } } } } @@ -1765,6 +2045,7 @@ RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, break; } if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S) + { switch (feparm.fec) { case eDVBFrontendParametersSatellite::FEC_None: @@ -1791,6 +2072,7 @@ RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, parm_u_qpsk_fec_inner = FEC_AUTO; break; } + } #if HAVE_DVB_API_VERSION >= 3 else // DVB_S2 { @@ -1827,12 +2109,15 @@ RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!"); return -EINVAL; } - parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff - parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot - if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation_8PSK) { +#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 @@ -1843,6 +2128,7 @@ RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, } eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000); } + oparm.sat = feparm; return res; } @@ -1925,6 +2211,7 @@ RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm) parm_u_qam_fec_inner, parm_u_qam_modulation, parm_inversion); + oparm.cab = feparm; return 0; } @@ -2072,6 +2359,7 @@ RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial parm_inversion = INVERSION_AUTO; break; } + oparm.ter = feparm; return 0; } @@ -2115,8 +2403,22 @@ RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where) res = -EINVAL; goto tune_error; } + if (m_rotor_mode != feparm.no_rotor_command_on_tune && !feparm.no_rotor_command_on_tune) + { + eDVBFrontend *sec_fe = this; + long tmp = m_data[LINKED_PREV_PTR]; + while (tmp != -1) + { + eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp; + sec_fe = linked_fe->m_frontend; + sec_fe->getData(LINKED_NEXT_PTR, tmp); + } + eDebug("(fe%d) reset diseqc after leave rotor mode!", m_dvbid); + sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = sec_fe->m_data[ROTOR_CMD] = sec_fe->m_data[ROTOR_POS] = -1; // reset diseqc + } + m_rotor_mode = feparm.no_rotor_command_on_tune; if (!m_simulate) - m_sec->setRotorMoving(false); + m_sec->setRotorMoving(m_slotid, false); res=prepare_sat(feparm, timeout); if (res) goto tune_error; @@ -2136,7 +2438,7 @@ RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where) goto tune_error; m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) ); - m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) ); + m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) ); break; } case feTerrestrial: @@ -2161,7 +2463,7 @@ RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where) m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) ); else m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) ); - m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) ); + m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) ); break; } @@ -2172,9 +2474,9 @@ RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where) if (!m_simulate) { m_tuneTimer->start(0,true); + m_tuning = 1; if (m_state != stateTuning) { - m_tuning = 1; m_state = stateTuning; m_stateChanged(this); } @@ -2341,9 +2643,12 @@ RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec) return 0; } -RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list) +RESULT eDVBFrontend::setSecSequence(eSecCommandList &list) { - m_sec_sequence = list; + if (m_data[SATCR] != -1 && m_sec_sequence.current() != m_sec_sequence.end()) + m_sec_sequence.push_back(list); + else + m_sec_sequence = list; return 0; } @@ -2394,17 +2699,23 @@ int eDVBFrontend::isCompatibleWith(ePtr &feparm) bool eDVBFrontend::setSlotInfo(ePyObject obj) { - ePyObject Id, Descr, Enabled, IsDVBS2; - if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4) + ePyObject Id, Descr, Enabled, IsDVBS2, frontendId; + if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 5) goto arg_error; Id = PyTuple_GET_ITEM(obj, 0); Descr = PyTuple_GET_ITEM(obj, 1); Enabled = PyTuple_GET_ITEM(obj, 2); IsDVBS2 = PyTuple_GET_ITEM(obj, 3); - if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2)) + frontendId = PyTuple_GET_ITEM(obj, 4); + m_slotid = PyInt_AsLong(Id); + if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2) || !PyInt_Check(frontendId)) goto arg_error; strcpy(m_description, PyString_AS_STRING(Descr)); - m_slotid = PyInt_AsLong(Id); + if (PyInt_AsLong(frontendId) == -1 || PyInt_AsLong(frontendId) != m_dvbid) { +// eDebugNoSimulate("skip slotinfo for slotid %d, descr %s", +// m_slotid, m_description); + return false; + } m_enabled = Enabled == Py_True; // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator... m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") || @@ -2420,42 +2731,3 @@ arg_error: "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean"); return false; } - -RESULT eDVBFrontend::turnOffSatCR(int satcr) -{ - eSecCommandList sec_sequence; - // check if voltage is disabled - eSecCommand::pair compare; - compare.steps = +9; //nothing to do - compare.voltage = iDVBFrontend::voltageOff; - sec_sequence.push_back( eSecCommand(eSecCommand::IF_NOT_VOLTAGE_GOTO, compare) ); - sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) ); - sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50 ) ); - - sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage18_5) ); - sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) ); - sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 250) ); - - eDVBDiseqcCommand diseqc; - memset(diseqc.data, 0, MAX_DISEQC_LENGTH); - diseqc.len = 5; - diseqc.data[0] = 0xE0; - diseqc.data[1] = 0x10; - diseqc.data[2] = 0x5A; - diseqc.data[3] = satcr << 5; - diseqc.data[4] = 0x00; - - sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) ); - sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50+20+14*diseqc.len) ); - sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) ); - setSecSequence(sec_sequence); - return 0; -} - -RESULT eDVBFrontend::ScanSatCR() -{ - setFrontend(); - usleep(20000); - setTone(iDVBFrontend::toneOff); - return 0; -}