1 #include <lib/dvb/dvb.h>
2 #include <lib/base/eerror.h>
3 #include <lib/base/nconfig.h> // access to python config
9 #ifndef I2C_SLAVE_FORCE
10 #define I2C_SLAVE_FORCE 0x0706
13 #if HAVE_DVB_API_VERSION < 3
14 #include <ost/frontend.h>
16 #define QAM_AUTO (Modulation)6
17 #define TRANSMISSION_MODE_AUTO (TransmitMode)2
18 #define BANDWIDTH_AUTO (BandWidth)3
19 #define GUARD_INTERVAL_AUTO (GuardInterval)4
20 #define HIERARCHY_AUTO (Hierarchy)4
21 #define parm_frequency parm.Frequency
22 #define parm_inversion parm.Inversion
23 #define parm_u_qpsk_symbol_rate parm.u.qpsk.SymbolRate
24 #define parm_u_qpsk_fec_inner parm.u.qpsk.FEC_inner
25 #define parm_u_qam_symbol_rate parm.u.qam.SymbolRate
26 #define parm_u_qam_fec_inner parm.u.qam.FEC_inner
27 #define parm_u_qam_modulation parm.u.qam.QAM
28 #define parm_u_ofdm_bandwidth parm.u.ofdm.bandWidth
29 #define parm_u_ofdm_code_rate_LP parm.u.ofdm.LP_CodeRate
30 #define parm_u_ofdm_code_rate_HP parm.u.ofdm.HP_CodeRate
31 #define parm_u_ofdm_constellation parm.u.ofdm.Constellation
32 #define parm_u_ofdm_transmission_mode parm.u.ofdm.TransmissionMode
33 #define parm_u_ofdm_guard_interval parm.u.ofdm.guardInterval
34 #define parm_u_ofdm_hierarchy_information parm.u.ofdm.HierarchyInformation
36 #include <linux/dvb/frontend.h>
37 #define parm_frequency parm.frequency
38 #define parm_inversion parm.inversion
39 #define parm_u_qpsk_symbol_rate parm.u.qpsk.symbol_rate
40 #define parm_u_qpsk_fec_inner parm.u.qpsk.fec_inner
41 #define parm_u_qam_symbol_rate parm.u.qam.symbol_rate
42 #define parm_u_qam_fec_inner parm.u.qam.fec_inner
43 #define parm_u_qam_modulation parm.u.qam.modulation
44 #define parm_u_ofdm_bandwidth parm.u.ofdm.bandwidth
45 #define parm_u_ofdm_code_rate_LP parm.u.ofdm.code_rate_LP
46 #define parm_u_ofdm_code_rate_HP parm.u.ofdm.code_rate_HP
47 #define parm_u_ofdm_constellation parm.u.ofdm.constellation
48 #define parm_u_ofdm_transmission_mode parm.u.ofdm.transmission_mode
49 #define parm_u_ofdm_guard_interval parm.u.ofdm.guard_interval
50 #define parm_u_ofdm_hierarchy_information parm.u.ofdm.hierarchy_information
52 #warning "FEC_9_10 already exist in dvb api ... it seems it is now ready for DVB-S2"
54 #define FEC_S2_QPSK_1_2 (fe_code_rate_t)(FEC_AUTO+1)
55 #define FEC_S2_QPSK_2_3 (fe_code_rate_t)(FEC_S2_QPSK_1_2+1)
56 #define FEC_S2_QPSK_3_4 (fe_code_rate_t)(FEC_S2_QPSK_2_3+1)
57 #define FEC_S2_QPSK_5_6 (fe_code_rate_t)(FEC_S2_QPSK_3_4+1)
58 #define FEC_S2_QPSK_7_8 (fe_code_rate_t)(FEC_S2_QPSK_5_6+1)
59 #define FEC_S2_QPSK_8_9 (fe_code_rate_t)(FEC_S2_QPSK_7_8+1)
60 #define FEC_S2_QPSK_3_5 (fe_code_rate_t)(FEC_S2_QPSK_8_9+1)
61 #define FEC_S2_QPSK_4_5 (fe_code_rate_t)(FEC_S2_QPSK_3_5+1)
62 #define FEC_S2_QPSK_9_10 (fe_code_rate_t)(FEC_S2_QPSK_4_5+1)
63 #define FEC_S2_8PSK_1_2 (fe_code_rate_t)(FEC_S2_QPSK_9_10+1)
64 #define FEC_S2_8PSK_2_3 (fe_code_rate_t)(FEC_S2_8PSK_1_2+1)
65 #define FEC_S2_8PSK_3_4 (fe_code_rate_t)(FEC_S2_8PSK_2_3+1)
66 #define FEC_S2_8PSK_5_6 (fe_code_rate_t)(FEC_S2_8PSK_3_4+1)
67 #define FEC_S2_8PSK_7_8 (fe_code_rate_t)(FEC_S2_8PSK_5_6+1)
68 #define FEC_S2_8PSK_8_9 (fe_code_rate_t)(FEC_S2_8PSK_7_8+1)
69 #define FEC_S2_8PSK_3_5 (fe_code_rate_t)(FEC_S2_8PSK_8_9+1)
70 #define FEC_S2_8PSK_4_5 (fe_code_rate_t)(FEC_S2_8PSK_3_5+1)
71 #define FEC_S2_8PSK_9_10 (fe_code_rate_t)(FEC_S2_8PSK_4_5+1)
75 #include <dvbsi++/satellite_delivery_system_descriptor.h>
76 #include <dvbsi++/cable_delivery_system_descriptor.h>
77 #include <dvbsi++/terrestrial_delivery_system_descriptor.h>
79 #define eDebugNoSimulate(x...) \
87 eDebugNoNewLine("SIMULATE:"); \
92 #define eDebugNoSimulateNoNewLine(x...) \
100 eDebugNoNewLine("SIMULATE:"); \
101 eDebugNoNewLine(x); \
105 void eDVBDiseqcCommand::setCommandString(const char *str)
110 int slen = strlen(str);
113 eDebug("invalid diseqc command string length (not 2 byte aligned)");
116 if (slen > MAX_DISEQC_LENGTH*2)
118 eDebug("invalid diseqc command string length (string is to long)");
122 for (int i=0; i < slen; ++i)
124 unsigned char c = str[i];
127 case '0' ... '9': c-=48; break;
128 case 'a' ... 'f': c-=87; break;
129 case 'A' ... 'F': c-=55; break;
131 eDebug("invalid character in hex string..ignore complete diseqc command !");
145 void eDVBFrontendParametersSatellite::set(const SatelliteDeliverySystemDescriptor &descriptor)
147 frequency = descriptor.getFrequency() * 10;
148 symbol_rate = descriptor.getSymbolRate() * 100;
149 polarisation = descriptor.getPolarization();
150 fec = descriptor.getFecInner();
151 if ( fec != FEC::fNone && fec > FEC::f9_10 )
153 inversion = Inversion::Unknown;
154 pilot = Pilot::Unknown;
155 orbital_position = ((descriptor.getOrbitalPosition() >> 12) & 0xF) * 1000;
156 orbital_position += ((descriptor.getOrbitalPosition() >> 8) & 0xF) * 100;
157 orbital_position += ((descriptor.getOrbitalPosition() >> 4) & 0xF) * 10;
158 orbital_position += ((descriptor.getOrbitalPosition()) & 0xF);
159 if (orbital_position && (!descriptor.getWestEastFlag()))
160 orbital_position = 3600 - orbital_position;
161 system = descriptor.getModulationSystem();
162 modulation = descriptor.getModulation();
163 if (system == System::DVB_S && modulation == Modulation::M8PSK)
165 eDebug("satellite_delivery_descriptor non valid modulation type.. force QPSK");
168 rolloff = descriptor.getRollOff();
169 if (system == System::DVB_S2)
171 eDebug("SAT DVB-S2 freq %d, %s, pos %d, sr %d, fec %d, modulation %d, rolloff %d",
173 polarisation ? "hor" : "vert",
181 eDebug("SAT DVB-S freq %d, %s, pos %d, sr %d, fec %d",
183 polarisation ? "hor" : "vert",
189 void eDVBFrontendParametersCable::set(const CableDeliverySystemDescriptor &descriptor)
191 frequency = descriptor.getFrequency() / 10;
192 symbol_rate = descriptor.getSymbolRate() * 100;
193 fec_inner = descriptor.getFecInner();
194 if ( fec_inner == 0xF )
195 fec_inner = FEC::fNone;
196 modulation = descriptor.getModulation();
197 if ( modulation > 0x5 )
198 modulation = Modulation::Auto;
199 inversion = Inversion::Unknown;
200 eDebug("Cable freq %d, mod %d, sr %d, fec %d",
202 modulation, symbol_rate, fec_inner);
205 void eDVBFrontendParametersTerrestrial::set(const TerrestrialDeliverySystemDescriptor &descriptor)
207 frequency = descriptor.getCentreFrequency() * 10;
208 bandwidth = descriptor.getBandwidth();
209 if ( bandwidth > 2 ) // 5Mhz forced to auto
210 bandwidth = Bandwidth::BwAuto;
211 code_rate_HP = descriptor.getCodeRateHpStream();
212 if (code_rate_HP > 4)
213 code_rate_HP = FEC::fAuto;
214 code_rate_LP = descriptor.getCodeRateLpStream();
215 if (code_rate_LP > 4)
216 code_rate_LP = FEC::fAuto;
217 transmission_mode = descriptor.getTransmissionMode();
218 if (transmission_mode > 1) // TM4k forced to auto
219 transmission_mode = TransmissionMode::TMAuto;
220 guard_interval = descriptor.getGuardInterval();
221 if (guard_interval > 3)
222 guard_interval = GuardInterval::GI_Auto;
223 hierarchy = descriptor.getHierarchyInformation()&3;
224 modulation = descriptor.getConstellation();
226 modulation = Modulation::Auto;
227 inversion = Inversion::Unknown;
228 eDebug("Terr freq %d, bw %d, cr_hp %d, cr_lp %d, tm_mode %d, guard %d, hierarchy %d, const %d",
229 frequency, bandwidth, code_rate_HP, code_rate_LP, transmission_mode,
230 guard_interval, hierarchy, modulation);
233 eDVBFrontendParameters::eDVBFrontendParameters()
234 :m_type(-1), m_flags(0)
238 DEFINE_REF(eDVBFrontendParameters);
240 RESULT eDVBFrontendParameters::getSystem(int &t) const
248 RESULT eDVBFrontendParameters::getDVBS(eDVBFrontendParametersSatellite &p) const
250 if (m_type != iDVBFrontend::feSatellite)
256 RESULT eDVBFrontendParameters::getDVBC(eDVBFrontendParametersCable &p) const
258 if (m_type != iDVBFrontend::feCable)
264 RESULT eDVBFrontendParameters::getDVBT(eDVBFrontendParametersTerrestrial &p) const
266 if (m_type != iDVBFrontend::feTerrestrial)
272 RESULT eDVBFrontendParameters::setDVBS(const eDVBFrontendParametersSatellite &p, bool no_rotor_command_on_tune)
275 sat.no_rotor_command_on_tune = no_rotor_command_on_tune;
276 m_type = iDVBFrontend::feSatellite;
280 RESULT eDVBFrontendParameters::setDVBC(const eDVBFrontendParametersCable &p)
283 m_type = iDVBFrontend::feCable;
287 RESULT eDVBFrontendParameters::setDVBT(const eDVBFrontendParametersTerrestrial &p)
290 m_type = iDVBFrontend::feTerrestrial;
294 RESULT eDVBFrontendParameters::calculateDifference(const iDVBFrontendParameters *parm, int &diff, bool exact) const
299 if (parm->getSystem(type))
303 diff = 1<<30; // big difference
309 case iDVBFrontend::feSatellite:
311 eDVBFrontendParametersSatellite osat;
312 if (parm->getDVBS(osat))
315 if (sat.orbital_position != osat.orbital_position)
317 else if (sat.polarisation != osat.polarisation)
319 else if (exact && sat.fec != osat.fec && sat.fec != eDVBFrontendParametersSatellite::FEC::fAuto && osat.fec != eDVBFrontendParametersSatellite::FEC::fAuto)
321 else if (exact && sat.modulation != osat.modulation && sat.modulation != eDVBFrontendParametersSatellite::Modulation::Auto && osat.modulation != eDVBFrontendParametersSatellite::Modulation::Auto)
325 diff = abs(sat.frequency - osat.frequency);
326 diff += abs(sat.symbol_rate - osat.symbol_rate);
330 case iDVBFrontend::feCable:
331 eDVBFrontendParametersCable ocable;
332 if (parm->getDVBC(ocable))
335 if (exact && cable.modulation != ocable.modulation
336 && cable.modulation != eDVBFrontendParametersCable::Modulation::Auto
337 && ocable.modulation != eDVBFrontendParametersCable::Modulation::Auto)
339 else if (exact && cable.fec_inner != ocable.fec_inner && cable.fec_inner != eDVBFrontendParametersCable::FEC::fAuto && ocable.fec_inner != eDVBFrontendParametersCable::FEC::fAuto)
343 diff = abs(cable.frequency - ocable.frequency);
344 diff += abs(cable.symbol_rate - ocable.symbol_rate);
347 case iDVBFrontend::feTerrestrial:
348 eDVBFrontendParametersTerrestrial oterrestrial;
349 if (parm->getDVBT(oterrestrial))
352 if (exact && oterrestrial.bandwidth != terrestrial.bandwidth &&
353 oterrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto &&
354 terrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto)
356 else if (exact && oterrestrial.modulation != terrestrial.modulation &&
357 oterrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation::Auto &&
358 terrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation::Auto)
360 else if (exact && oterrestrial.transmission_mode != terrestrial.transmission_mode &&
361 oterrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto &&
362 terrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto)
364 else if (exact && oterrestrial.guard_interval != terrestrial.guard_interval &&
365 oterrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto &&
366 terrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto)
368 else if (exact && oterrestrial.hierarchy != terrestrial.hierarchy &&
369 oterrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy::HAuto &&
370 terrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy::HAuto)
372 else if (exact && oterrestrial.code_rate_LP != terrestrial.code_rate_LP &&
373 oterrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC::fAuto &&
374 terrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC::fAuto)
376 else if (exact && oterrestrial.code_rate_HP != terrestrial.code_rate_HP &&
377 oterrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC::fAuto &&
378 terrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC::fAuto)
381 diff = abs(terrestrial.frequency - oterrestrial.frequency);
389 RESULT eDVBFrontendParameters::getHash(unsigned long &hash) const
393 case iDVBFrontend::feSatellite:
395 hash = (sat.orbital_position << 16);
396 hash |= ((sat.frequency/1000)&0xFFFF)|((sat.polarisation&1) << 15);
399 case iDVBFrontend::feCable:
401 hash |= (cable.frequency/1000)&0xFFFF;
403 case iDVBFrontend::feTerrestrial:
405 hash |= (terrestrial.frequency/1000)&0xFFFF;
412 RESULT eDVBFrontendParameters::calcLockTimeout(unsigned int &timeout) const
416 case iDVBFrontend::feSatellite:
418 /* high symbol rate transponders tune faster, due to
419 requiring less zigzag and giving more symbols faster.
421 5s are definitely not enough on really low SR when
422 zigzag has to find the exact frequency first.
424 if (sat.symbol_rate > 20000000)
426 else if (sat.symbol_rate > 10000000)
432 case iDVBFrontend::feCable:
435 case iDVBFrontend::feTerrestrial:
443 DEFINE_REF(eDVBFrontend);
445 int eDVBFrontend::PriorityOrder=0;
447 eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok, bool simulate)
448 :m_simulate(simulate), m_enabled(false), m_type(-1), m_dvbid(fe), m_slotid(fe)
449 ,m_fd(-1), m_need_rotor_workaround(false), m_can_handle_dvbs2(false)
450 , m_timeout(0), m_tuneTimer(0)
451 #if HAVE_DVB_API_VERSION < 3
455 #if HAVE_DVB_API_VERSION < 3
456 sprintf(m_filename, "/dev/dvb/card%d/frontend%d", adap, fe);
457 sprintf(m_sec_filename, "/dev/dvb/card%d/sec%d", adap, fe);
459 sprintf(m_filename, "/dev/dvb/adapter%d/frontend%d", adap, fe);
462 m_timeout = eTimer::create(eApp);
463 CONNECT(m_timeout->timeout, eDVBFrontend::timeout);
465 m_tuneTimer = eTimer::create(eApp);
466 CONNECT(m_tuneTimer->timeout, eDVBFrontend::tuneLoop);
468 for (int i=0; i<eDVBFrontend::NUM_DATA_ENTRIES; ++i)
471 m_idleInputpower[0]=m_idleInputpower[1]=0;
473 ok = !openFrontend();
477 int eDVBFrontend::openFrontend()
480 return -1; // already opened
485 #if HAVE_DVB_API_VERSION < 3
486 FrontendInfo fe_info;
488 dvb_frontend_info fe_info;
490 eDebugNoSimulate("opening frontend %d", m_dvbid);
493 if (!m_simulate || m_type == -1)
495 m_fd = ::open(m_filename, O_RDWR|O_NONBLOCK);
498 eWarning("failed! (%s) %m", m_filename);
504 eWarning("frontend %d already opened", m_dvbid);
507 if (::ioctl(m_fd, FE_GET_INFO, &fe_info) < 0)
509 eWarning("ioctl FE_GET_INFO failed");
515 switch (fe_info.type)
518 m_type = iDVBFrontend::feSatellite;
521 m_type = iDVBFrontend::feCable;
524 m_type = iDVBFrontend::feTerrestrial;
527 eWarning("unknown frontend type.");
532 eDebugNoSimulate("detected %s frontend", "satellite\0cable\0 terrestrial"+fe_info.type*10);
535 #if HAVE_DVB_API_VERSION < 3
536 if (m_type == iDVBFrontend::feSatellite)
542 m_secfd = ::open(m_sec_filename, O_RDWR);
545 eWarning("failed! (%s) %m", m_sec_filename);
553 eWarning("sec %d already opened", m_dvbid);
557 setTone(iDVBFrontend::toneOff);
558 setVoltage(iDVBFrontend::voltageOff);
562 m_sn = eSocketNotifier::create(eApp, m_fd, eSocketNotifier::Read, false);
563 CONNECT(m_sn->activated, eDVBFrontend::feEvent);
569 int eDVBFrontend::closeFrontend(bool force)
571 if (!force && m_data[CUR_VOLTAGE] != -1 && m_data[CUR_VOLTAGE] != iDVBFrontend::voltageOff)
573 long tmp = m_data[LINKED_NEXT_PTR];
576 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
577 if (linked_fe->m_inuse)
579 eDebugNoSimulate("dont close frontend %d until the linked frontend %d in slot %d is still in use",
580 m_dvbid, linked_fe->m_frontend->getDVBID(), linked_fe->m_frontend->getSlotID());
583 linked_fe->m_frontend->getData(LINKED_NEXT_PTR, tmp);
589 eDebugNoSimulate("close frontend %d", m_dvbid);
590 if (m_data[SATCR] != -1)
592 turnOffSatCR(m_data[SATCR]);
594 setTone(iDVBFrontend::toneOff);
595 setVoltage(iDVBFrontend::voltageOff);
597 if (m_sec && !m_simulate)
598 m_sec->setRotorMoving(false);
602 eWarning("couldnt close frontend %d", m_dvbid);
606 setTone(iDVBFrontend::toneOff);
607 setVoltage(iDVBFrontend::voltageOff);
609 #if HAVE_DVB_API_VERSION < 3
612 if (!::close(m_secfd))
615 eWarning("couldnt close sec %d", m_dvbid);
619 m_state = stateClosed;
624 eDVBFrontend::~eDVBFrontend()
626 m_data[LINKED_PREV_PTR] = m_data[LINKED_NEXT_PTR] = -1;
630 void eDVBFrontend::feEvent(int w)
632 eDVBFrontend *sec_fe = this;
633 long tmp = m_data[LINKED_PREV_PTR];
636 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
637 sec_fe = linked_fe->m_frontend;
638 sec_fe->getData(LINKED_NEXT_PTR, tmp);
642 #if HAVE_DVB_API_VERSION < 3
645 dvb_frontend_event event;
649 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
651 if (res && (errno == EAGAIN))
656 eWarning("FE_GET_EVENT failed! %m");
663 #if HAVE_DVB_API_VERSION < 3
664 if (event.type == FE_COMPLETION_EV)
666 eDebug("(%d)fe event: status %x, inversion %s", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off");
667 if (event.status & FE_HAS_LOCK)
677 eDebug("stateLostLock");
678 state = stateLostLock;
679 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
682 if (m_state != state)
685 m_stateChanged(this);
690 void eDVBFrontend::timeout()
693 if (m_state == stateTuning)
695 m_state = stateFailed;
696 m_stateChanged(this);
700 #define INRANGE(X,Y,Z) (((X<=Y) && (Y<=Z))||((Z<=Y) && (Y<=X)) ? 1 : 0)
702 /* unsigned 32 bit division */
703 static inline uint32_t fe_udiv(uint32_t a, uint32_t b)
705 return (a + b / 2) / b;
708 int eDVBFrontend::readFrontendData(int type)
717 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
718 eDebug("FE_READ_BER failed (%m)");
723 case signalQualitydB: /* this will move into the driver */
725 int sat_max = 1600; // for stv0288 / bsbe2
726 int ret = 0x12345678;
730 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
731 eDebug("FE_READ_SNR failed (%m)");
732 else if (!strcmp(m_description, "BCM4501 (internal)"))
734 float SDS_SNRE = snr << 16;
737 if (parm_u_qpsk_fec_inner <= FEC_AUTO) // DVB-S1 / QPSK
739 static float SNR_COEFF[6] = {
742 197418.0 / 4194304.0,
743 -2602183.0 / 4194304.0,
744 20377212.0 / 4194304.0,
745 -37791203.0 / 4194304.0,
747 float fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0)),
748 fval2 = pow(10.0, fval1)-1;
749 fval1 = 10.0 * log10(fval2);
753 fval2 = SNR_COEFF[0];
754 for (int i=1; i<6; ++i)
757 fval2 += SNR_COEFF[i];
763 #if HAVE_DVB_API_VERSION >= 3
766 float fval1 = SDS_SNRE / 268435456.0,
769 if (parm_u_qpsk_fec_inner <= FEC_S2_QPSK_9_10) // DVB-S2 QPSK
780 fval4 = -10.0 * log10(fval1);
782 for (int i=0; i < 5; ++i)
783 fval1 = fval4 - fval2 * log10(1.0+pow(10.0, (fval3-fval1)/fval2));
788 ret = (int)(snr_in_db * 100);
790 else if (strstr(m_description, "Alps BSBE1 C01A") ||
791 !strcmp(m_description, "Alps -S(STV0288)"))
795 else if (snr == 0xFFFF) // i think this should not happen
799 enum { REALVAL, REGVAL };
800 const long CN_lookup[31][2] = {
801 {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
802 {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
803 {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
804 {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
805 {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
806 {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
809 int add=strchr(m_description, '.') ? 0xA250 : 0xA100;
810 long regval = 0xFFFF - ((snr / 3) + add), // revert some dvb api calulations to get the real register value
814 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
819 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[i][REGVAL]))
824 ret = (((regval - CN_lookup[Imin][REGVAL])
825 * (CN_lookup[Imax][REALVAL] - CN_lookup[Imin][REALVAL])
826 / (CN_lookup[Imax][REGVAL] - CN_lookup[Imin][REGVAL]))
827 + CN_lookup[Imin][REALVAL]) * 10;
833 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
834 !strcmp(m_description, "Alps -S") ||
835 !strcmp(m_description, "Philips -S") ||
836 !strcmp(m_description, "LG -S") )
839 ret = (int)((snr-39075)/17.647);
840 } else if (!strcmp(m_description, "Alps BSBE2"))
842 ret = (int)((snr >> 7) * 10);
843 } else if (!strcmp(m_description, "Philips CU1216Mk3"))
845 int mse = (~snr) & 0xFF;
846 switch (parm_u_qam_modulation) {
847 case QAM_16: ret = fe_udiv(1950000, (32 * mse) + 138) + 1000; break;
848 case QAM_32: ret = fe_udiv(2150000, (40 * mse) + 500) + 1350; break;
849 case QAM_64: ret = fe_udiv(2100000, (40 * mse) + 500) + 1250; break;
850 case QAM_128: ret = fe_udiv(1850000, (38 * mse) + 400) + 1380; break;
851 case QAM_256: ret = fe_udiv(1800000, (100 * mse) + 40) + 2030; break;
854 } else if (!strcmp(m_description, "Philips TU1216"))
856 snr = 0xFF - (snr & 0xFF);
858 ret = 10 * (int)(-100 * (log10(snr) - log10(255)));
861 if (type == signalQuality)
863 if (ret == 0x12345678) // no snr db calculation avail.. return untouched snr value..
868 return ret >= sat_max ? 65536 : ret * 65536 / sat_max;
869 case feCable: // we assume a max of 42db here
870 return ret >= 4200 ? 65536 : ret * 65536 / 4200;
871 case feTerrestrial: // we assume a max of 24db here
872 return ret >= 2400 ? 65536 : ret * 65536 / 2400;
876 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
884 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
885 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
891 #if HAVE_DVB_API_VERSION < 3
892 FrontendStatus status=0;
898 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
899 eDebug("FE_READ_STATUS failed (%m)");
900 return !!(status&FE_HAS_LOCK);
906 #if HAVE_DVB_API_VERSION < 3
907 FrontendStatus status=0;
913 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
914 eDebug("FE_READ_STATUS failed (%m)");
915 return !!(status&FE_HAS_SYNC);
925 void PutToDict(ePyObject &dict, const char*key, long value)
927 ePyObject item = PyInt_FromLong(value);
930 if (PyDict_SetItemString(dict, key, item))
931 eDebug("put %s to dict failed", key);
935 eDebug("could not create PyObject for %s", key);
938 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
942 if (PyDict_SetItemString(dict, key, item))
943 eDebug("put %s to dict failed", key);
947 eDebug("invalid PyObject for %s", key);
950 void PutToDict(ePyObject &dict, const char*key, const char *value)
952 ePyObject item = PyString_FromString(value);
955 if (PyDict_SetItemString(dict, key, item))
956 eDebug("put %s to dict failed", key);
960 eDebug("could not create PyObject for %s", key);
963 void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, eDVBFrontend *fe)
967 fe->getData(eDVBFrontend::FREQ_OFFSET, freq_offset);
968 int frequency = parm_frequency + freq_offset;
969 PutToDict(dict, "frequency", frequency);
970 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
971 switch(parm_u_qpsk_fec_inner)
994 #if HAVE_DVB_API_VERSION >=3
995 case FEC_S2_8PSK_1_2:
996 case FEC_S2_QPSK_1_2:
999 case FEC_S2_8PSK_2_3:
1000 case FEC_S2_QPSK_2_3:
1003 case FEC_S2_8PSK_3_4:
1004 case FEC_S2_QPSK_3_4:
1007 case FEC_S2_8PSK_5_6:
1008 case FEC_S2_QPSK_5_6:
1011 case FEC_S2_8PSK_7_8:
1012 case FEC_S2_QPSK_7_8:
1015 case FEC_S2_8PSK_8_9:
1016 case FEC_S2_QPSK_8_9:
1019 case FEC_S2_8PSK_3_5:
1020 case FEC_S2_QPSK_3_5:
1023 case FEC_S2_8PSK_4_5:
1024 case FEC_S2_QPSK_4_5:
1027 case FEC_S2_8PSK_9_10:
1028 case FEC_S2_QPSK_9_10:
1033 PutToDict(dict, "fec_inner", tmp);
1034 #if HAVE_DVB_API_VERSION >=3
1035 PutToDict(dict, "modulation",
1036 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ? "8PSK": "QPSK" );
1037 if (parm_u_qpsk_fec_inner > FEC_AUTO)
1039 switch(parm_inversion & 0xc)
1041 default: // unknown rolloff
1043 tmp = "ROLLOFF_0_35";
1046 tmp = "ROLLOFF_0_25";
1049 tmp = "ROLLOFF_0_20";
1052 PutToDict(dict, "rolloff", tmp);
1053 switch(parm_inversion & 0x30)
1055 case 0: // pilot off
1058 case 0x10: // pilot on
1061 case 0x20: // pilot auto
1065 PutToDict(dict, "pilot", tmp);
1071 PutToDict(dict, "modulation", "QPSK" );
1074 PutToDict(dict, "system", tmp);
1077 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1080 #if HAVE_DVB_API_VERSION < 3
1081 PutToDict(dict, "frequency", parm_frequency);
1083 PutToDict(dict, "frequency", parm_frequency/1000);
1085 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1086 switch(parm_u_qam_fec_inner)
1106 #if HAVE_DVB_API_VERSION >= 3
1116 PutToDict(dict, "fec_inner", tmp);
1117 switch(parm_u_qam_modulation)
1139 PutToDict(dict, "modulation", tmp);
1142 void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1145 PutToDict(dict, "frequency", parm_frequency);
1146 switch (parm_u_ofdm_bandwidth)
1148 case BANDWIDTH_8_MHZ:
1149 tmp = "BANDWIDTH_8_MHZ";
1151 case BANDWIDTH_7_MHZ:
1152 tmp = "BANDWIDTH_7_MHZ";
1154 case BANDWIDTH_6_MHZ:
1155 tmp = "BANDWIDTH_6_MHZ";
1158 case BANDWIDTH_AUTO:
1159 tmp = "BANDWIDTH_AUTO";
1162 PutToDict(dict, "bandwidth", tmp);
1163 switch (parm_u_ofdm_code_rate_LP)
1185 PutToDict(dict, "code_rate_lp", tmp);
1186 switch (parm_u_ofdm_code_rate_HP)
1208 PutToDict(dict, "code_rate_hp", tmp);
1209 switch (parm_u_ofdm_constellation)
1225 PutToDict(dict, "constellation", tmp);
1226 switch (parm_u_ofdm_transmission_mode)
1228 case TRANSMISSION_MODE_2K:
1229 tmp = "TRANSMISSION_MODE_2K";
1231 case TRANSMISSION_MODE_8K:
1232 tmp = "TRANSMISSION_MODE_8K";
1235 case TRANSMISSION_MODE_AUTO:
1236 tmp = "TRANSMISSION_MODE_AUTO";
1239 PutToDict(dict, "transmission_mode", tmp);
1240 switch (parm_u_ofdm_guard_interval)
1242 case GUARD_INTERVAL_1_32:
1243 tmp = "GUARD_INTERVAL_1_32";
1245 case GUARD_INTERVAL_1_16:
1246 tmp = "GUARD_INTERVAL_1_16";
1248 case GUARD_INTERVAL_1_8:
1249 tmp = "GUARD_INTERVAL_1_8";
1251 case GUARD_INTERVAL_1_4:
1252 tmp = "GUARD_INTERVAL_1_4";
1255 case GUARD_INTERVAL_AUTO:
1256 tmp = "GUARD_INTERVAL_AUTO";
1259 PutToDict(dict, "guard_interval", tmp);
1260 switch (parm_u_ofdm_hierarchy_information)
1262 case HIERARCHY_NONE:
1263 tmp = "HIERARCHY_NONE";
1266 tmp = "HIERARCHY_1";
1269 tmp = "HIERARCHY_2";
1272 tmp = "HIERARCHY_4";
1275 case HIERARCHY_AUTO:
1276 tmp = "HIERARCHY_AUTO";
1279 PutToDict(dict, "hierarchy_information", tmp);
1282 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1284 if (dest && PyDict_Check(dest))
1286 const char *tmp = "UNKNOWN";
1307 PutToDict(dest, "tuner_state", tmp);
1308 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1309 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1310 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1311 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1312 int sigQualitydB = readFrontendData(signalQualitydB);
1313 if (sigQualitydB == 0x12345678) // not support yet
1315 ePyObject obj=Py_None;
1317 PutToDict(dest, "tuner_signal_quality_db", obj);
1320 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1321 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1325 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1327 if (dest && PyDict_Check(dest))
1335 FRONTENDPARAMETERS front;
1336 if (m_fd == -1 && !original)
1338 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1340 eDebug("FE_GET_FRONTEND failed (%m)");
1344 const FRONTENDPARAMETERS &parm = original || m_simulate ? this->parm : front;
1345 const char *tmp = "INVERSION_AUTO";
1346 switch(parm_inversion & 3)
1349 tmp = "INVERSION_ON";
1352 tmp = "INVERSION_OFF";
1358 PutToDict(dest, "inversion", tmp);
1363 fillDictWithSatelliteData(dest, original?parm:front, this);
1366 fillDictWithCableData(dest, original?parm:front);
1369 fillDictWithTerrestrialData(dest, original?parm:front);
1380 void eDVBFrontend::getFrontendData(ePyObject dest)
1382 if (dest && PyDict_Check(dest))
1385 PutToDict(dest, "tuner_number", m_slotid);
1401 PutToDict(dest, "tuner_type", tmp);
1405 #ifndef FP_IOCTL_GET_ID
1406 #define FP_IOCTL_GET_ID 0
1408 int eDVBFrontend::readInputpower()
1412 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1414 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1415 FILE *f=fopen(proc_name, "r");
1418 if (fscanf(f, "%d", &power) != 1)
1419 eDebug("read %s failed!! (%m)", proc_name);
1421 eDebug("%s is %d\n", proc_name, power);
1426 // open front prozessor
1427 int fp=::open("/dev/dbox/fp0", O_RDWR);
1430 eDebug("couldn't open fp");
1433 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1434 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1436 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1445 bool eDVBFrontend::setSecSequencePos(int steps)
1447 eDebugNoSimulate("set sequence pos %d", steps);
1452 if (m_sec_sequence.current() != m_sec_sequence.end())
1453 ++m_sec_sequence.current();
1458 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1459 --m_sec_sequence.current();
1465 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1468 eDVBFrontend *sec_fe = this;
1469 eDVBRegisteredFrontend *regFE = 0;
1470 long tmp = m_data[LINKED_PREV_PTR];
1473 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1474 sec_fe = prev->m_frontend;
1475 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1476 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1477 int state = sec_fe->m_state;
1478 // workaround to put the kernel frontend thread into idle state!
1479 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1481 sec_fe->closeFrontend(true);
1482 state = sec_fe->m_state;
1484 // sec_fe is closed... we must reopen it here..
1485 if (state == eDVBFrontend::stateClosed)
1493 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1495 long *sec_fe_data = sec_fe->m_data;
1496 // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1497 switch (m_sec_sequence.current()->cmd)
1499 case eSecCommand::SLEEP:
1500 delay = m_sec_sequence.current()++->msec;
1501 eDebugNoSimulate("[SEC] sleep %dms", delay);
1503 case eSecCommand::GOTO:
1504 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1505 ++m_sec_sequence.current();
1507 case eSecCommand::SET_VOLTAGE:
1509 int voltage = m_sec_sequence.current()++->voltage;
1510 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1511 sec_fe->setVoltage(voltage);
1514 case eSecCommand::IF_VOLTAGE_GOTO:
1516 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1517 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1519 ++m_sec_sequence.current();
1522 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1524 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1525 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1527 ++m_sec_sequence.current();
1530 case eSecCommand::IF_TONE_GOTO:
1532 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1533 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1535 ++m_sec_sequence.current();
1538 case eSecCommand::IF_NOT_TONE_GOTO:
1540 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1541 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1543 ++m_sec_sequence.current();
1546 case eSecCommand::SET_TONE:
1547 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1548 sec_fe->setTone(m_sec_sequence.current()++->tone);
1550 case eSecCommand::SEND_DISEQC:
1551 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1552 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1553 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1554 eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1555 if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
1556 eDebugNoSimulate("(DiSEqC reset)");
1557 else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
1558 eDebugNoSimulate("(DiSEqC peripherial power on)");
1560 eDebugNoSimulate("");
1561 ++m_sec_sequence.current();
1563 case eSecCommand::SEND_TONEBURST:
1564 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1565 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1567 case eSecCommand::SET_FRONTEND:
1568 eDebugNoSimulate("[SEC] setFrontend");
1570 ++m_sec_sequence.current();
1572 case eSecCommand::START_TUNE_TIMEOUT:
1575 m_timeout->start(m_sec_sequence.current()->timeout, 1);
1576 ++m_sec_sequence.current();
1579 case eSecCommand::SET_TIMEOUT:
1580 m_timeoutCount = m_sec_sequence.current()++->val;
1581 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1583 case eSecCommand::IF_TIMEOUT_GOTO:
1584 if (!m_timeoutCount)
1586 eDebugNoSimulate("[SEC] rotor timout");
1587 setSecSequencePos(m_sec_sequence.current()->steps);
1590 ++m_sec_sequence.current();
1592 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1594 int idx = m_sec_sequence.current()++->val;
1595 if ( idx == 0 || idx == 1 )
1597 m_idleInputpower[idx] = sec_fe->readInputpower();
1598 eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1601 eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1604 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1606 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1607 int idx = compare.val;
1608 if ( !m_simulate && (idx == 0 || idx == 1) )
1610 int idle = sec_fe->readInputpower();
1611 int diff = abs(idle-m_idleInputpower[idx]);
1614 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1615 setSecSequencePos(compare.steps);
1619 ++m_sec_sequence.current();
1622 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1624 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1627 setSecSequencePos(cmd.steps);
1631 int isLocked = readFrontendData(locked);
1632 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1633 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 50) || !cmd.lastSignal))
1636 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1639 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1640 cmd.lastSignal = signal;
1643 if (cmd.okcount > 4)
1645 eDebugNoSimulate("ok > 4 .. goto %d\n",cmd.steps);
1646 setSecSequencePos(cmd.steps);
1647 m_state = stateLock;
1648 m_stateChanged(this);
1657 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1659 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1661 if (!m_timeoutCount && m_retryCount > 0)
1666 ++m_sec_sequence.current();
1669 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1670 m_runningInputpower = sec_fe->readInputpower();
1671 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1672 ++m_sec_sequence.current();
1674 case eSecCommand::SET_ROTOR_MOVING:
1676 m_sec->setRotorMoving(true);
1677 ++m_sec_sequence.current();
1679 case eSecCommand::SET_ROTOR_STOPPED:
1681 m_sec->setRotorMoving(false);
1682 ++m_sec_sequence.current();
1684 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1686 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1689 setSecSequencePos(cmd.steps);
1692 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1693 const char *txt = cmd.direction ? "running" : "stopped";
1694 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1696 m_runningInputpower,
1699 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1700 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1703 eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1704 if ( cmd.okcount > 6 )
1706 eDebugNoSimulate("[SEC] rotor is %s", txt);
1707 if (setSecSequencePos(cmd.steps))
1713 eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1715 if (!m_timeoutCount && m_retryCount > 0)
1719 ++m_sec_sequence.current();
1722 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1723 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1724 setSecSequencePos(m_sec_sequence.current()->steps);
1726 ++m_sec_sequence.current();
1728 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1729 eDebugNoSimulate("[SEC] invalidate current switch params");
1730 sec_fe_data[CSW] = -1;
1731 sec_fe_data[UCSW] = -1;
1732 sec_fe_data[TONEBURST] = -1;
1733 ++m_sec_sequence.current();
1735 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1736 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1737 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1738 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1739 eDebugNoSimulate("[SEC] update current switch params");
1740 ++m_sec_sequence.current();
1742 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1743 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1744 sec_fe_data[ROTOR_CMD] = -1;
1745 sec_fe_data[ROTOR_POS] = -1;
1746 ++m_sec_sequence.current();
1748 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1749 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1750 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1751 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1752 ++m_sec_sequence.current();
1754 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1755 m_retryCount = m_sec_sequence.current()++->val;
1756 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1758 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1761 eDebugNoSimulate("[SEC] no more rotor retrys");
1762 setSecSequencePos(m_sec_sequence.current()->steps);
1765 ++m_sec_sequence.current();
1767 case eSecCommand::SET_POWER_LIMITING_MODE:
1772 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1773 FILE *f=fopen(proc_name, "w");
1774 if (f) // new interface exist?
1776 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1777 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1778 eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1780 eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1783 else if (sec_fe->m_need_rotor_workaround)
1786 int slotid = sec_fe->m_slotid;
1787 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1789 sprintf(dev, "/dev/i2c/%d", slotid);
1790 else if (slotid == 2)
1791 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1792 else if (slotid == 3)
1793 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1794 int fd = ::open(dev, O_RDWR);
1796 unsigned char data[2];
1797 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1798 if(::read(fd, data, 1) != 1)
1799 eDebugNoSimulate("[SEC] error read lnbp (%m)");
1800 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1802 data[0] |= 0x80; // enable static current limiting
1803 eDebugNoSimulate("[SEC] set static current limiting");
1807 data[0] &= ~0x80; // enable dynamic current limiting
1808 eDebugNoSimulate("[SEC] set dynamic current limiting");
1810 if(::write(fd, data, 1) != 1)
1811 eDebugNoSimulate("[SEC] error write lnbp (%m)");
1815 ++m_sec_sequence.current();
1819 eDebugNoSimulate("[SEC] unhandled sec command %d",
1820 ++m_sec_sequence.current()->cmd);
1821 ++m_sec_sequence.current();
1824 m_tuneTimer->start(delay,true);
1828 if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1832 void eDVBFrontend::setFrontend()
1836 eDebug("setting frontend %d", m_dvbid);
1839 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1841 perror("FE_SET_FRONTEND failed");
1847 RESULT eDVBFrontend::getFrontendType(int &t)
1855 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1860 eWarning("no SEC module active!");
1863 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1866 #if HAVE_DVB_API_VERSION >= 3
1867 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d system %d modulation %d pilot %d, rolloff %d",
1870 feparm.polarisation,
1874 feparm.orbital_position,
1880 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1883 feparm.polarisation,
1887 feparm.orbital_position);
1889 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1890 switch (feparm.inversion)
1892 case eDVBFrontendParametersSatellite::Inversion::On:
1893 parm_inversion = INVERSION_ON;
1895 case eDVBFrontendParametersSatellite::Inversion::Off:
1896 parm_inversion = INVERSION_OFF;
1899 case eDVBFrontendParametersSatellite::Inversion::Unknown:
1900 parm_inversion = INVERSION_AUTO;
1903 if (feparm.system == eDVBFrontendParametersSatellite::System::DVB_S)
1906 case eDVBFrontendParametersSatellite::FEC::fNone:
1907 parm_u_qpsk_fec_inner = FEC_NONE;
1909 case eDVBFrontendParametersSatellite::FEC::f1_2:
1910 parm_u_qpsk_fec_inner = FEC_1_2;
1912 case eDVBFrontendParametersSatellite::FEC::f2_3:
1913 parm_u_qpsk_fec_inner = FEC_2_3;
1915 case eDVBFrontendParametersSatellite::FEC::f3_4:
1916 parm_u_qpsk_fec_inner = FEC_3_4;
1918 case eDVBFrontendParametersSatellite::FEC::f5_6:
1919 parm_u_qpsk_fec_inner = FEC_5_6;
1921 case eDVBFrontendParametersSatellite::FEC::f7_8:
1922 parm_u_qpsk_fec_inner = FEC_7_8;
1925 eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
1926 case eDVBFrontendParametersSatellite::FEC::fAuto:
1927 parm_u_qpsk_fec_inner = FEC_AUTO;
1930 #if HAVE_DVB_API_VERSION >= 3
1935 case eDVBFrontendParametersSatellite::FEC::f1_2:
1936 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1938 case eDVBFrontendParametersSatellite::FEC::f2_3:
1939 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1941 case eDVBFrontendParametersSatellite::FEC::f3_4:
1942 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1944 case eDVBFrontendParametersSatellite::FEC::f3_5:
1945 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1947 case eDVBFrontendParametersSatellite::FEC::f4_5:
1948 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1950 case eDVBFrontendParametersSatellite::FEC::f5_6:
1951 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1953 case eDVBFrontendParametersSatellite::FEC::f7_8:
1954 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1956 case eDVBFrontendParametersSatellite::FEC::f8_9:
1957 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1959 case eDVBFrontendParametersSatellite::FEC::f9_10:
1960 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1963 eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
1966 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1967 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1968 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK) {
1969 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1970 // 8PSK fec driver values are decimal 9 bigger
1974 // FIXME !!! get frequency range from tuner
1975 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1977 eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1980 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
1985 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1987 #if HAVE_DVB_API_VERSION < 3
1988 parm_frequency = feparm.frequency;
1990 parm_frequency = feparm.frequency * 1000;
1992 parm_u_qam_symbol_rate = feparm.symbol_rate;
1993 switch (feparm.modulation)
1995 case eDVBFrontendParametersCable::Modulation::QAM16:
1996 parm_u_qam_modulation = QAM_16;
1998 case eDVBFrontendParametersCable::Modulation::QAM32:
1999 parm_u_qam_modulation = QAM_32;
2001 case eDVBFrontendParametersCable::Modulation::QAM64:
2002 parm_u_qam_modulation = QAM_64;
2004 case eDVBFrontendParametersCable::Modulation::QAM128:
2005 parm_u_qam_modulation = QAM_128;
2007 case eDVBFrontendParametersCable::Modulation::QAM256:
2008 parm_u_qam_modulation = QAM_256;
2011 case eDVBFrontendParametersCable::Modulation::Auto:
2012 parm_u_qam_modulation = QAM_AUTO;
2015 switch (feparm.inversion)
2017 case eDVBFrontendParametersCable::Inversion::On:
2018 parm_inversion = INVERSION_ON;
2020 case eDVBFrontendParametersCable::Inversion::Off:
2021 parm_inversion = INVERSION_OFF;
2024 case eDVBFrontendParametersCable::Inversion::Unknown:
2025 parm_inversion = INVERSION_AUTO;
2028 switch (feparm.fec_inner)
2030 case eDVBFrontendParametersCable::FEC::fNone:
2031 parm_u_qam_fec_inner = FEC_NONE;
2033 case eDVBFrontendParametersCable::FEC::f1_2:
2034 parm_u_qam_fec_inner = FEC_1_2;
2036 case eDVBFrontendParametersCable::FEC::f2_3:
2037 parm_u_qam_fec_inner = FEC_2_3;
2039 case eDVBFrontendParametersCable::FEC::f3_4:
2040 parm_u_qam_fec_inner = FEC_3_4;
2042 case eDVBFrontendParametersCable::FEC::f5_6:
2043 parm_u_qam_fec_inner = FEC_5_6;
2045 case eDVBFrontendParametersCable::FEC::f7_8:
2046 parm_u_qam_fec_inner = FEC_7_8;
2048 #if HAVE_DVB_API_VERSION >= 3
2049 case eDVBFrontendParametersCable::FEC::f8_9:
2050 parm_u_qam_fec_inner = FEC_8_9;
2054 case eDVBFrontendParametersCable::FEC::fAuto:
2055 parm_u_qam_fec_inner = FEC_AUTO;
2058 eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
2059 parm_frequency/1000,
2060 parm_u_qam_symbol_rate,
2061 parm_u_qam_fec_inner,
2062 parm_u_qam_modulation,
2067 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
2069 parm_frequency = feparm.frequency;
2071 switch (feparm.bandwidth)
2073 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
2074 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
2076 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
2077 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
2079 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
2080 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
2083 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
2084 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
2087 switch (feparm.code_rate_LP)
2089 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
2090 parm_u_ofdm_code_rate_LP = FEC_1_2;
2092 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
2093 parm_u_ofdm_code_rate_LP = FEC_2_3;
2095 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
2096 parm_u_ofdm_code_rate_LP = FEC_3_4;
2098 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
2099 parm_u_ofdm_code_rate_LP = FEC_5_6;
2101 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
2102 parm_u_ofdm_code_rate_LP = FEC_7_8;
2105 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
2106 parm_u_ofdm_code_rate_LP = FEC_AUTO;
2109 switch (feparm.code_rate_HP)
2111 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
2112 parm_u_ofdm_code_rate_HP = FEC_1_2;
2114 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
2115 parm_u_ofdm_code_rate_HP = FEC_2_3;
2117 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
2118 parm_u_ofdm_code_rate_HP = FEC_3_4;
2120 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
2121 parm_u_ofdm_code_rate_HP = FEC_5_6;
2123 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
2124 parm_u_ofdm_code_rate_HP = FEC_7_8;
2127 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
2128 parm_u_ofdm_code_rate_HP = FEC_AUTO;
2131 switch (feparm.modulation)
2133 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
2134 parm_u_ofdm_constellation = QPSK;
2136 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
2137 parm_u_ofdm_constellation = QAM_16;
2139 case eDVBFrontendParametersTerrestrial::Modulation::QAM64:
2140 parm_u_ofdm_constellation = QAM_64;
2143 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
2144 parm_u_ofdm_constellation = QAM_AUTO;
2147 switch (feparm.transmission_mode)
2149 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
2150 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2152 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
2153 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2156 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
2157 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2160 switch (feparm.guard_interval)
2162 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32:
2163 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2165 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16:
2166 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2168 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8:
2169 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2171 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4:
2172 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2175 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto:
2176 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2179 switch (feparm.hierarchy)
2181 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone:
2182 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2184 case eDVBFrontendParametersTerrestrial::Hierarchy::H1:
2185 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2187 case eDVBFrontendParametersTerrestrial::Hierarchy::H2:
2188 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2190 case eDVBFrontendParametersTerrestrial::Hierarchy::H4:
2191 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2194 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto:
2195 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2198 switch (feparm.inversion)
2200 case eDVBFrontendParametersTerrestrial::Inversion::On:
2201 parm_inversion = INVERSION_ON;
2203 case eDVBFrontendParametersTerrestrial::Inversion::Off:
2204 parm_inversion = INVERSION_OFF;
2207 case eDVBFrontendParametersTerrestrial::Inversion::Unknown:
2208 parm_inversion = INVERSION_AUTO;
2214 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2216 unsigned int timeout = 5000;
2217 eDebugNoSimulate("(%d)tune", m_dvbid);
2223 if (!m_sn && !m_simulate)
2225 eDebug("no frontend device opened... do not try to tune !!!");
2239 m_sec_sequence.clear();
2241 where.calcLockTimeout(timeout);
2247 eDVBFrontendParametersSatellite feparm;
2248 if (where.getDVBS(feparm))
2250 eDebug("no dvbs data!");
2255 m_sec->setRotorMoving(false);
2256 res=prepare_sat(feparm, timeout);
2264 eDVBFrontendParametersCable feparm;
2265 if (where.getDVBC(feparm))
2270 res=prepare_cable(feparm);
2274 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2275 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2280 eDVBFrontendParametersTerrestrial feparm;
2281 if (where.getDVBT(feparm))
2283 eDebug("no -T data");
2287 res=prepare_terrestrial(feparm);
2291 std::string enable_5V;
2292 char configStr[255];
2293 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2294 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2295 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2296 if (enable_5V == "True")
2297 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2299 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2300 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2306 m_sec_sequence.current() = m_sec_sequence.begin();
2310 m_tuneTimer->start(0,true);
2311 if (m_state != stateTuning)
2314 m_state = stateTuning;
2315 m_stateChanged(this);
2324 m_tuneTimer->stop();
2328 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2330 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2334 RESULT eDVBFrontend::setVoltage(int voltage)
2336 if (m_type == feCable)
2338 #if HAVE_DVB_API_VERSION < 3
2341 bool increased=false;
2342 fe_sec_voltage_t vlt;
2344 m_data[CUR_VOLTAGE]=voltage;
2348 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2349 vlt = SEC_VOLTAGE_OFF;
2352 #if HAVE_DVB_API_VERSION < 3
2353 vlt = SEC_VOLTAGE_13_5;
2359 vlt = SEC_VOLTAGE_13;
2362 #if HAVE_DVB_API_VERSION < 3
2363 vlt = SEC_VOLTAGE_18_5;
2369 vlt = SEC_VOLTAGE_18;
2376 #if HAVE_DVB_API_VERSION < 3
2377 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2379 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2380 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2381 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2385 RESULT eDVBFrontend::getState(int &state)
2391 RESULT eDVBFrontend::setTone(int t)
2393 if (m_type != feSatellite)
2395 #if HAVE_DVB_API_VERSION < 3
2398 fe_sec_tone_mode_t tone;
2407 tone = SEC_TONE_OFF;
2414 #if HAVE_DVB_API_VERSION < 3
2415 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2417 return ::ioctl(m_fd, FE_SET_TONE, tone);
2421 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2422 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2425 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2429 #if HAVE_DVB_API_VERSION < 3
2430 struct secCommand cmd;
2431 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2432 cmd.u.diseqc.cmdtype = diseqc.data[0];
2433 cmd.u.diseqc.addr = diseqc.data[1];
2434 cmd.u.diseqc.cmd = diseqc.data[2];
2435 cmd.u.diseqc.numParams = diseqc.len-3;
2436 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2437 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2439 struct dvb_diseqc_master_cmd cmd;
2440 memcpy(cmd.msg, diseqc.data, diseqc.len);
2441 cmd.msg_len = diseqc.len;
2442 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2448 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2449 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2451 RESULT eDVBFrontend::sendToneburst(int burst)
2455 #if HAVE_DVB_API_VERSION < 3
2456 secMiniCmd cmd = SEC_MINI_NONE;
2458 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2460 if ( burst == eDVBSatelliteDiseqcParameters::A )
2462 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2464 #if HAVE_DVB_API_VERSION < 3
2465 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2468 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2474 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2480 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2482 m_sec_sequence = list;
2486 RESULT eDVBFrontend::getData(int num, long &data)
2488 if ( num < NUM_DATA_ENTRIES )
2496 RESULT eDVBFrontend::setData(int num, long val)
2498 if ( num < NUM_DATA_ENTRIES )
2506 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2509 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2511 if (m_type == eDVBFrontend::feSatellite)
2514 eDVBFrontendParametersSatellite sat_parm;
2515 int ret = feparm->getDVBS(sat_parm);
2517 if (sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S2 && !m_can_handle_dvbs2)
2519 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2520 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S && m_can_handle_dvbs2)
2524 else if (m_type == eDVBFrontend::feCable)
2525 return 2; // more prio for cable frontends
2526 else if (m_type == eDVBFrontend::feTerrestrial)
2531 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2533 ePyObject Id, Descr, Enabled, IsDVBS2;
2534 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4)
2536 Id = PyTuple_GET_ITEM(obj, 0);
2537 Descr = PyTuple_GET_ITEM(obj, 1);
2538 Enabled = PyTuple_GET_ITEM(obj, 2);
2539 IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2540 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2))
2542 strcpy(m_description, PyString_AS_STRING(Descr));
2543 m_slotid = PyInt_AsLong(Id);
2544 m_enabled = Enabled == Py_True;
2545 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2546 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2547 !!strstr(m_description, "Alps BSBE2") ||
2548 !!strstr(m_description, "Alps -S") ||
2549 !!strstr(m_description, "BCM4501");
2550 m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2551 eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2552 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2555 PyErr_SetString(PyExc_StandardError,
2556 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");
2560 RESULT eDVBFrontend::turnOffSatCR(int satcr)
2562 eSecCommandList sec_sequence;
2563 // check if voltage is disabled
2564 eSecCommand::pair compare;
2565 compare.steps = +9; //nothing to do
2566 compare.voltage = iDVBFrontend::voltageOff;
2567 sec_sequence.push_back( eSecCommand(eSecCommand::IF_NOT_VOLTAGE_GOTO, compare) );
2568 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2569 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50 ) );
2571 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage18_5) );
2572 sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
2573 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 250) );
2575 eDVBDiseqcCommand diseqc;
2576 memset(diseqc.data, 0, MAX_DISEQC_LENGTH);
2578 diseqc.data[0] = 0xE0;
2579 diseqc.data[1] = 0x10;
2580 diseqc.data[2] = 0x5A;
2581 diseqc.data[3] = satcr << 5;
2582 diseqc.data[4] = 0x00;
2584 sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
2585 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50+20+14*diseqc.len) );
2586 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2587 setSecSequence(sec_sequence);
2591 RESULT eDVBFrontend::ScanSatCR()
2595 setTone(iDVBFrontend::toneOff);