X-Git-Url: http://code.vuplus.com/gitweb/?p=vuplus_dvbapp;a=blobdiff_plain;f=lib%2Fdvb%2Ffrontend.cpp;h=a183e374f5fbd196e23a79be50229dd10193a9cf;hp=ea9e73854e38d51deb14c519e389fb906102ee77;hb=fe619dbed1c9bf14a0d442cc16d7e968769bbcc0;hpb=ce38faaf7ce4c1320fa42109c13a60d74ab8cd9c diff --git a/lib/dvb/frontend.cpp b/lib/dvb/frontend.cpp old mode 100644 new mode 100755 index ea9e738..a183e37 --- a/lib/dvb/frontend.cpp +++ b/lib/dvb/frontend.cpp @@ -1,3 +1,5 @@ +#include + #include #include #include @@ -213,27 +215,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); @@ -357,7 +399,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 +427,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,10 +498,12 @@ 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) - :m_simulate(simulate), m_enabled(false), m_type(-1), m_dvbid(fe), m_slotid(fe) - ,m_fd(-1), m_rotor_mode(false), m_need_rotor_workaround(false), m_can_handle_dvbs2(false) + +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_can_handle_dvbt2(false) ,m_state(stateClosed), m_timeout(0), m_tuneTimer(0) #if HAVE_DVB_API_VERSION < 3 ,m_secfd(-1) @@ -503,10 +551,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) @@ -515,70 +563,69 @@ 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; } @@ -739,6 +786,10 @@ void eDVBFrontend::timeout() m_tuning = 0; if (m_state == stateTuning) { +#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 +#endif m_state = stateFailed; m_stateChanged(this); } @@ -1052,6 +1103,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) @@ -1126,9 +1182,187 @@ static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS & case PSK_8: tmp = eDVBFrontendParametersSatellite::Modulation_8PSK; break; } PutToDict(dict, "modulation", tmp); + + switch(parm_inversion & 3) + { + case INVERSION_ON: tmp = eDVBFrontendParametersSatellite::Inversion_On; break; + case INVERSION_OFF: tmp = eDVBFrontendParametersSatellite::Inversion_Off; break; + default: tmp = eDVBFrontendParametersSatellite::Inversion_Unknown; break; + } + PutToDict(dict, "inversion", tmp); } -#else +static void fillDictWithCableData(ePyObject dict, struct dtv_property *p) +{ + long tmp = 0; +// frequency + tmp = p[1].u.data/1000; + PutToDict(dict, "frequency", tmp); +// sysbolrate + PutToDict(dict, "symbol_rate", p[2].u.data); +// inner fec + switch (p[3].u.data) + { + 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); +// modulation + switch (p[4].u.data) + { + 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[5].u.data) + { + 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, struct dtv_property *p) +{ + long tmp =0; +// system + switch (p[0].u.data) + { + default: eDebug("got unsupported system from frontend! report as DVBT!"); + case SYS_DVBT: tmp = eDVBFrontendParametersTerrestrial::System_DVB_T; break; + case SYS_DVBT2: + { +#if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 3 + tmp = p[10].u.data; + PutToDict(dict, "plp_id", tmp); +#endif + tmp = eDVBFrontendParametersTerrestrial::System_DVB_T2; break; + } + } + PutToDict(dict, "system", tmp); +// frequency + tmp = p[1].u.data; + PutToDict(dict, "frequency", tmp); +// bandwidth + switch (p[2].u.data) + { + 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); +// code rate LP + switch (p[3].u.data) + { + 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); +// code rate HP + switch (p[4].u.data) + { + 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); +// constellation + switch (p[5].u.data) + { + 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); + +// transmission + switch (p[6].u.data) + { + 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); +// guard interval + switch (p[7].u.data) + { + 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; + 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); +// hierarchy + switch (p[8].u.data) + { + 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); +// inversion + switch (p[9].u.data) + { + 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); +} + +#else // #if HAVE_DVB_API_VERSION >= 5 static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, long freq_offset, int orb_pos, int polarization) { long tmp=0; @@ -1202,7 +1436,6 @@ static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS & #endif PutToDict(dict, "system", tmp); } -#endif static void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm) { @@ -1315,6 +1548,8 @@ static void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS PutToDict(dict, "hierarchy_information", tmp); } +#endif // #if HAVE_DVB_API_VERSION >= 5 + void eDVBFrontend::getFrontendStatus(ePyObject dest) { if (dest && PyDict_Check(dest)) @@ -1364,30 +1599,74 @@ void eDVBFrontend::getTransponderData(ePyObject dest, bool original) { 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; + switch(m_type) + { + case feSatellite: + p[0].cmd = DTV_DELIVERY_SYSTEM; + p[1].cmd = DTV_MODULATION; + p[2].cmd = DTV_ROLLOFF; + p[3].cmd = DTV_PILOT; + cmdseq.num = 4; + break; + case feCable: + p[0].cmd = DTV_DELIVERY_SYSTEM; + p[1].cmd = DTV_FREQUENCY; + p[2].cmd = DTV_SYMBOL_RATE; + p[3].cmd = DTV_INNER_FEC; + p[4].cmd = DTV_MODULATION; + p[5].cmd = DTV_INVERSION; + cmdseq.num = 6; + break; + case feTerrestrial: + p[0].cmd = DTV_DELIVERY_SYSTEM; + p[1].cmd = DTV_FREQUENCY; + p[2].cmd = DTV_BANDWIDTH_HZ; + p[3].cmd = DTV_CODE_RATE_LP; + p[4].cmd = DTV_CODE_RATE_HP; + p[5].cmd = DTV_MODULATION; + p[6].cmd = DTV_TRANSMISSION_MODE; + p[7].cmd = DTV_GUARD_INTERVAL; + p[8].cmd = DTV_HIERARCHY; + p[9].cmd = DTV_INVERSION; +#if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 9 + p[10].cmd = DTV_STREAM_ID; + cmdseq.num = 11; +#elif DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 3 + p[10].cmd = DTV_DVBT2_PLP_ID; + cmdseq.num = 11; +#else + cmdseq.num = 10; +#endif + break; + } #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 (m_type == feSatellite && // use for DVB-S(2) only + ioctl(m_fd, FE_GET_FRONTEND, &front)<0) + { + eDebug("FE_GET_FRONTEND failed (%m)"); + original = true; + } +#else else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0) { eDebug("FE_GET_FRONTEND failed (%m)"); original = true; } +#endif if (original) { switch(m_type) @@ -1406,6 +1685,20 @@ void eDVBFrontend::getTransponderData(ePyObject dest, bool original) else { FRONTENDPARAMETERS &parm = front; +#if HAVE_DVB_API_VERSION >= 5 + switch(m_type) + { + case feSatellite: + fillDictWithSatelliteData(dest, parm, p, m_data[FREQ_OFFSET], oparm.sat.orbital_position, oparm.sat.polarisation); + break; + case feCable: + fillDictWithCableData(dest, p); + break; + case feTerrestrial: + fillDictWithTerrestrialData(dest, p); + break; + } +#else long tmp = eDVBFrontendParametersSatellite::Inversion_Unknown; switch(parm_inversion & 3) { @@ -1421,11 +1714,7 @@ void eDVBFrontend::getTransponderData(ePyObject dest, bool original) 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); @@ -1434,6 +1723,7 @@ void eDVBFrontend::getTransponderData(ePyObject dest, bool original) fillDictWithTerrestrialData(dest, parm); break; } +#endif } } } @@ -1860,11 +2150,11 @@ int eDVBFrontend::tuneLoopInt() // 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]; @@ -1977,6 +2267,78 @@ void eDVBFrontend::setFrontend(bool recvEvents) return; } } + else if (m_type == iDVBFrontend::feCable) + { + struct dtv_property p[8]; + struct dtv_properties cmdseq; + cmdseq.props = p; + p[0].cmd = DTV_CLEAR; +#if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 6 + 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 (m_type == iDVBFrontend::feTerrestrial) + { + fe_delivery_system_t system = SYS_DVBT; + switch (oparm.ter.system) + { + default: + case eDVBFrontendParametersTerrestrial::System_DVB_T: system = SYS_DVBT; break; + case eDVBFrontendParametersTerrestrial::System_DVB_T2: system = SYS_DVBT2; break; + } + int bandwidth = 0; + switch (oparm.ter.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 DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 9 + p[cmdseq.num].cmd = DTV_STREAM_ID , p[cmdseq.num].u.data = oparm.ter.plpid, cmdseq.num++; +#elif DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 3 + p[cmdseq.num].cmd = DTV_DVBT2_PLP_ID , p[cmdseq.num].u.data = oparm.ter.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 #endif { @@ -2231,6 +2593,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; @@ -2253,6 +2624,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; @@ -2275,6 +2652,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; @@ -2291,6 +2674,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; @@ -2304,6 +2690,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; @@ -2323,6 +2721,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; @@ -2360,6 +2767,18 @@ RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial parm_inversion = INVERSION_AUTO; break; } + 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.ter = feparm; return 0; } @@ -2676,40 +3095,82 @@ RESULT eDVBFrontend::setData(int num, long val) int eDVBFrontend::isCompatibleWith(ePtr &feparm) { int type; + int score = 0; + bool preferred = (eDVBFrontend::getPreferredFrontend() >= 0 && m_slotid == eDVBFrontend::getPreferredFrontend()); + if (feparm->getSystem(type) || type != m_type || !m_enabled) return 0; + if (m_type == eDVBFrontend::feSatellite) { - ASSERT(m_sec); eDVBFrontendParametersSatellite sat_parm; - int ret = feparm->getDVBS(sat_parm); - ASSERT(!ret); + if (feparm->getDVBS(sat_parm) < 0) + { + return 0; + } if (sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S2 && !m_can_handle_dvbs2) + { 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; + } + score = m_sec ? m_sec->canTune(sat_parm, this, 1 << m_slotid) : 0; + if (score > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S && m_can_handle_dvbs2) + { + /* prefer to use a S tuner, try to keep S2 free for S2 transponders */ + score--; + } } + else if (m_type == eDVBFrontend::feCable) - return 2; // more prio for cable frontends + { + eDVBFrontendParametersCable cab_parm; + if (feparm->getDVBC(cab_parm) < 0) + { + return 0; + } + score = 2; + } + else if (m_type == eDVBFrontend::feTerrestrial) - return 1; - return 0; + { + eDVBFrontendParametersTerrestrial ter_parm; + if (feparm->getDVBT(ter_parm) < 0) + { + return 0; + } + if (ter_parm.system == eDVBFrontendParametersTerrestrial::System_DVB_T2 && !m_can_handle_dvbt2) + { + return 0; + } + score = 2; + if (ter_parm.system == eDVBFrontendParametersTerrestrial::System_DVB_T && m_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::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) { @@ -2724,8 +3185,9 @@ bool eDVBFrontend::setSlotInfo(ePyObject obj) !!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" ); + m_can_handle_dvbt2 = IsDVBT2 == Py_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", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No", m_can_handle_dvbt2 ? "Yes" : "No" ); return true; arg_error: PyErr_SetString(PyExc_StandardError,