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 setTone(iDVBFrontend::toneOff);
591 setVoltage(iDVBFrontend::voltageOff);
593 if (m_sec && !m_simulate)
594 m_sec->setRotorMoving(false);
598 eWarning("couldnt close frontend %d", m_dvbid);
602 setTone(iDVBFrontend::toneOff);
603 setVoltage(iDVBFrontend::voltageOff);
605 #if HAVE_DVB_API_VERSION < 3
608 if (!::close(m_secfd))
611 eWarning("couldnt close sec %d", m_dvbid);
615 m_state = stateClosed;
620 eDVBFrontend::~eDVBFrontend()
622 m_data[LINKED_PREV_PTR] = m_data[LINKED_NEXT_PTR] = -1;
626 void eDVBFrontend::feEvent(int w)
628 eDVBFrontend *sec_fe = this;
629 long tmp = m_data[LINKED_PREV_PTR];
632 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
633 sec_fe = linked_fe->m_frontend;
634 sec_fe->getData(LINKED_NEXT_PTR, tmp);
638 #if HAVE_DVB_API_VERSION < 3
641 dvb_frontend_event event;
645 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
647 if (res && (errno == EAGAIN))
652 eWarning("FE_GET_EVENT failed! %m");
659 #if HAVE_DVB_API_VERSION < 3
660 if (event.type == FE_COMPLETION_EV)
662 eDebug("(%d)fe event: status %x, inversion %s", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off");
663 if (event.status & FE_HAS_LOCK)
673 eDebug("stateLostLock");
674 state = stateLostLock;
675 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
678 if (m_state != state)
681 m_stateChanged(this);
686 void eDVBFrontend::timeout()
689 if (m_state == stateTuning)
691 m_state = stateFailed;
692 m_stateChanged(this);
696 #define INRANGE(X,Y,Z) (((X<=Y) && (Y<=Z))||((Z<=Y) && (Y<=X)) ? 1 : 0)
698 /* unsigned 32 bit division */
699 static inline uint32_t fe_udiv(uint32_t a, uint32_t b)
701 return (a + b / 2) / b;
704 int eDVBFrontend::readFrontendData(int type)
713 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
714 eDebug("FE_READ_BER failed (%m)");
719 case signalQualitydB: /* this will move into the driver */
721 int sat_max = 1600; // for stv0288 / bsbe2
722 int ret = 0x12345678;
726 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
727 eDebug("FE_READ_SNR failed (%m)");
728 else if (!strcmp(m_description, "BCM4501 (internal)"))
730 float SDS_SNRE = snr << 16;
733 if (parm_u_qpsk_fec_inner <= FEC_AUTO) // DVB-S1 / QPSK
735 static float SNR_COEFF[6] = {
738 197418.0 / 4194304.0,
739 -2602183.0 / 4194304.0,
740 20377212.0 / 4194304.0,
741 -37791203.0 / 4194304.0,
743 float fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0)),
744 fval2 = pow(10.0, fval1)-1;
745 fval1 = 10.0 * log10(fval2);
749 fval2 = SNR_COEFF[0];
750 for (int i=1; i<6; ++i)
753 fval2 += SNR_COEFF[i];
759 #if HAVE_DVB_API_VERSION >= 3
762 float fval1 = SDS_SNRE / 268435456.0,
765 if (parm_u_qpsk_fec_inner <= FEC_S2_QPSK_9_10) // DVB-S2 QPSK
776 fval4 = -10.0 * log10(fval1);
778 for (int i=0; i < 5; ++i)
779 fval1 = fval4 - fval2 * log10(1.0+pow(10.0, (fval3-fval1)/fval2));
784 ret = (int)(snr_in_db * 100);
786 else if (strstr(m_description, "Alps BSBE1 C01A") ||
787 !strcmp(m_description, "Alps -S(STV0288)"))
791 else if (snr == 0xFFFF) // i think this should not happen
795 enum { REALVAL, REGVAL };
796 const long CN_lookup[31][2] = {
797 {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
798 {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
799 {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
800 {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
801 {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
802 {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
805 int add=strchr(m_description, '.') ? 0xA250 : 0xA100;
806 long regval = 0xFFFF - ((snr / 3) + add), // revert some dvb api calulations to get the real register value
810 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
815 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[i][REGVAL]))
820 ret = (((regval - CN_lookup[Imin][REGVAL])
821 * (CN_lookup[Imax][REALVAL] - CN_lookup[Imin][REALVAL])
822 / (CN_lookup[Imax][REGVAL] - CN_lookup[Imin][REGVAL]))
823 + CN_lookup[Imin][REALVAL]) * 10;
829 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
830 !strcmp(m_description, "Alps -S") ||
831 !strcmp(m_description, "Philips -S") ||
832 !strcmp(m_description, "LG -S") )
835 ret = (int)((snr-39075)/17.647);
836 } else if (!strcmp(m_description, "Alps BSBE2"))
838 ret = (int)((snr >> 7) * 10);
839 } else if (!strcmp(m_description, "Philips CU1216Mk3"))
841 int mse = (~snr) & 0xFF;
842 switch (parm_u_qam_modulation) {
843 case QAM_16: ret = fe_udiv(1950000, (32 * mse) + 138) + 1000; break;
844 case QAM_32: ret = fe_udiv(2150000, (40 * mse) + 500) + 1350; break;
845 case QAM_64: ret = fe_udiv(2100000, (40 * mse) + 500) + 1250; break;
846 case QAM_128: ret = fe_udiv(1850000, (38 * mse) + 400) + 1380; break;
847 case QAM_256: ret = fe_udiv(1800000, (100 * mse) + 40) + 2030; break;
850 } else if (!strcmp(m_description, "Philips TU1216"))
852 snr = 0xFF - (snr & 0xFF);
854 ret = 10 * (int)(-100 * (log10(snr) - log10(255)));
857 if (type == signalQuality)
859 if (ret == 0x12345678) // no snr db calculation avail.. return untouched snr value..
864 return ret >= sat_max ? 65536 : ret * 65536 / sat_max;
865 case feCable: // we assume a max of 42db here
866 return ret >= 4200 ? 65536 : ret * 65536 / 4200;
867 case feTerrestrial: // we assume a max of 24db here
868 return ret >= 2400 ? 65536 : ret * 65536 / 2400;
872 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
880 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
881 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
887 #if HAVE_DVB_API_VERSION < 3
888 FrontendStatus status=0;
894 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
895 eDebug("FE_READ_STATUS failed (%m)");
896 return !!(status&FE_HAS_LOCK);
902 #if HAVE_DVB_API_VERSION < 3
903 FrontendStatus status=0;
909 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
910 eDebug("FE_READ_STATUS failed (%m)");
911 return !!(status&FE_HAS_SYNC);
921 void PutToDict(ePyObject &dict, const char*key, long value)
923 ePyObject item = PyInt_FromLong(value);
926 if (PyDict_SetItemString(dict, key, item))
927 eDebug("put %s to dict failed", key);
931 eDebug("could not create PyObject for %s", key);
934 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
938 if (PyDict_SetItemString(dict, key, item))
939 eDebug("put %s to dict failed", key);
943 eDebug("invalid PyObject for %s", key);
946 void PutToDict(ePyObject &dict, const char*key, const char *value)
948 ePyObject item = PyString_FromString(value);
951 if (PyDict_SetItemString(dict, key, item))
952 eDebug("put %s to dict failed", key);
956 eDebug("could not create PyObject for %s", key);
959 void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, eDVBFrontend *fe)
963 fe->getData(eDVBFrontend::FREQ_OFFSET, freq_offset);
964 int frequency = parm_frequency + freq_offset;
965 PutToDict(dict, "frequency", frequency);
966 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
967 switch(parm_u_qpsk_fec_inner)
990 #if HAVE_DVB_API_VERSION >=3
991 case FEC_S2_8PSK_1_2:
992 case FEC_S2_QPSK_1_2:
995 case FEC_S2_8PSK_2_3:
996 case FEC_S2_QPSK_2_3:
999 case FEC_S2_8PSK_3_4:
1000 case FEC_S2_QPSK_3_4:
1003 case FEC_S2_8PSK_5_6:
1004 case FEC_S2_QPSK_5_6:
1007 case FEC_S2_8PSK_7_8:
1008 case FEC_S2_QPSK_7_8:
1011 case FEC_S2_8PSK_8_9:
1012 case FEC_S2_QPSK_8_9:
1015 case FEC_S2_8PSK_3_5:
1016 case FEC_S2_QPSK_3_5:
1019 case FEC_S2_8PSK_4_5:
1020 case FEC_S2_QPSK_4_5:
1023 case FEC_S2_8PSK_9_10:
1024 case FEC_S2_QPSK_9_10:
1029 PutToDict(dict, "fec_inner", tmp);
1030 #if HAVE_DVB_API_VERSION >=3
1031 PutToDict(dict, "modulation",
1032 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ? "8PSK": "QPSK" );
1033 if (parm_u_qpsk_fec_inner > FEC_AUTO)
1035 switch(parm_inversion & 0xc)
1037 default: // unknown rolloff
1039 tmp = "ROLLOFF_0_35";
1042 tmp = "ROLLOFF_0_25";
1045 tmp = "ROLLOFF_0_20";
1048 PutToDict(dict, "rolloff", tmp);
1049 switch(parm_inversion & 0x30)
1051 case 0: // pilot off
1054 case 0x10: // pilot on
1057 case 0x20: // pilot auto
1061 PutToDict(dict, "pilot", tmp);
1067 PutToDict(dict, "modulation", "QPSK" );
1070 PutToDict(dict, "system", tmp);
1073 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1076 #if HAVE_DVB_API_VERSION < 3
1077 PutToDict(dict, "frequency", parm_frequency);
1079 PutToDict(dict, "frequency", parm_frequency/1000);
1081 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1082 switch(parm_u_qam_fec_inner)
1102 #if HAVE_DVB_API_VERSION >= 3
1112 PutToDict(dict, "fec_inner", tmp);
1113 switch(parm_u_qam_modulation)
1135 PutToDict(dict, "modulation", tmp);
1138 void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1141 PutToDict(dict, "frequency", parm_frequency);
1142 switch (parm_u_ofdm_bandwidth)
1144 case BANDWIDTH_8_MHZ:
1145 tmp = "BANDWIDTH_8_MHZ";
1147 case BANDWIDTH_7_MHZ:
1148 tmp = "BANDWIDTH_7_MHZ";
1150 case BANDWIDTH_6_MHZ:
1151 tmp = "BANDWIDTH_6_MHZ";
1154 case BANDWIDTH_AUTO:
1155 tmp = "BANDWIDTH_AUTO";
1158 PutToDict(dict, "bandwidth", tmp);
1159 switch (parm_u_ofdm_code_rate_LP)
1181 PutToDict(dict, "code_rate_lp", tmp);
1182 switch (parm_u_ofdm_code_rate_HP)
1204 PutToDict(dict, "code_rate_hp", tmp);
1205 switch (parm_u_ofdm_constellation)
1221 PutToDict(dict, "constellation", tmp);
1222 switch (parm_u_ofdm_transmission_mode)
1224 case TRANSMISSION_MODE_2K:
1225 tmp = "TRANSMISSION_MODE_2K";
1227 case TRANSMISSION_MODE_8K:
1228 tmp = "TRANSMISSION_MODE_8K";
1231 case TRANSMISSION_MODE_AUTO:
1232 tmp = "TRANSMISSION_MODE_AUTO";
1235 PutToDict(dict, "transmission_mode", tmp);
1236 switch (parm_u_ofdm_guard_interval)
1238 case GUARD_INTERVAL_1_32:
1239 tmp = "GUARD_INTERVAL_1_32";
1241 case GUARD_INTERVAL_1_16:
1242 tmp = "GUARD_INTERVAL_1_16";
1244 case GUARD_INTERVAL_1_8:
1245 tmp = "GUARD_INTERVAL_1_8";
1247 case GUARD_INTERVAL_1_4:
1248 tmp = "GUARD_INTERVAL_1_4";
1251 case GUARD_INTERVAL_AUTO:
1252 tmp = "GUARD_INTERVAL_AUTO";
1255 PutToDict(dict, "guard_interval", tmp);
1256 switch (parm_u_ofdm_hierarchy_information)
1258 case HIERARCHY_NONE:
1259 tmp = "HIERARCHY_NONE";
1262 tmp = "HIERARCHY_1";
1265 tmp = "HIERARCHY_2";
1268 tmp = "HIERARCHY_4";
1271 case HIERARCHY_AUTO:
1272 tmp = "HIERARCHY_AUTO";
1275 PutToDict(dict, "hierarchy_information", tmp);
1278 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1280 if (dest && PyDict_Check(dest))
1282 const char *tmp = "UNKNOWN";
1303 PutToDict(dest, "tuner_state", tmp);
1304 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1305 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1306 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1307 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1308 int sigQualitydB = readFrontendData(signalQualitydB);
1309 if (sigQualitydB == 0x12345678) // not support yet
1311 ePyObject obj=Py_None;
1313 PutToDict(dest, "tuner_signal_quality_db", obj);
1316 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1317 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1321 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1323 if (dest && PyDict_Check(dest))
1331 FRONTENDPARAMETERS front;
1332 if (m_fd == -1 && !original)
1334 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1336 eDebug("FE_GET_FRONTEND failed (%m)");
1340 const FRONTENDPARAMETERS &parm = original || m_simulate ? this->parm : front;
1341 const char *tmp = "INVERSION_AUTO";
1342 switch(parm_inversion & 3)
1345 tmp = "INVERSION_ON";
1348 tmp = "INVERSION_OFF";
1354 PutToDict(dest, "inversion", tmp);
1359 fillDictWithSatelliteData(dest, original?parm:front, this);
1362 fillDictWithCableData(dest, original?parm:front);
1365 fillDictWithTerrestrialData(dest, original?parm:front);
1376 void eDVBFrontend::getFrontendData(ePyObject dest)
1378 if (dest && PyDict_Check(dest))
1381 PutToDict(dest, "tuner_number", m_slotid);
1397 PutToDict(dest, "tuner_type", tmp);
1401 #ifndef FP_IOCTL_GET_ID
1402 #define FP_IOCTL_GET_ID 0
1404 int eDVBFrontend::readInputpower()
1408 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1410 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1411 FILE *f=fopen(proc_name, "r");
1414 if (fscanf(f, "%d", &power) != 1)
1415 eDebug("read %s failed!! (%m)", proc_name);
1417 eDebug("%s is %d\n", proc_name, power);
1422 // open front prozessor
1423 int fp=::open("/dev/dbox/fp0", O_RDWR);
1426 eDebug("couldn't open fp");
1429 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1430 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1432 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1441 bool eDVBFrontend::setSecSequencePos(int steps)
1443 eDebugNoSimulate("set sequence pos %d", steps);
1448 if (m_sec_sequence.current() != m_sec_sequence.end())
1449 ++m_sec_sequence.current();
1454 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1455 --m_sec_sequence.current();
1461 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1464 eDVBFrontend *sec_fe = this;
1465 eDVBRegisteredFrontend *regFE = 0;
1466 long tmp = m_data[LINKED_PREV_PTR];
1469 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1470 sec_fe = prev->m_frontend;
1471 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1472 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1473 int state = sec_fe->m_state;
1474 // workaround to put the kernel frontend thread into idle state!
1475 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1477 sec_fe->closeFrontend(true);
1478 state = sec_fe->m_state;
1480 // sec_fe is closed... we must reopen it here..
1481 if (state == eDVBFrontend::stateClosed)
1489 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1491 long *sec_fe_data = sec_fe->m_data;
1492 // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1493 switch (m_sec_sequence.current()->cmd)
1495 case eSecCommand::SLEEP:
1496 delay = m_sec_sequence.current()++->msec;
1497 eDebugNoSimulate("[SEC] sleep %dms", delay);
1499 case eSecCommand::GOTO:
1500 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1501 ++m_sec_sequence.current();
1503 case eSecCommand::SET_VOLTAGE:
1505 int voltage = m_sec_sequence.current()++->voltage;
1506 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1507 sec_fe->setVoltage(voltage);
1510 case eSecCommand::IF_VOLTAGE_GOTO:
1512 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1513 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1515 ++m_sec_sequence.current();
1518 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1520 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1521 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1523 ++m_sec_sequence.current();
1526 case eSecCommand::IF_TONE_GOTO:
1528 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1529 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1531 ++m_sec_sequence.current();
1534 case eSecCommand::IF_NOT_TONE_GOTO:
1536 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1537 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1539 ++m_sec_sequence.current();
1542 case eSecCommand::SET_TONE:
1543 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1544 sec_fe->setTone(m_sec_sequence.current()++->tone);
1546 case eSecCommand::SEND_DISEQC:
1547 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1548 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1549 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1550 eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1551 if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
1552 eDebugNoSimulate("(DiSEqC reset)");
1553 else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
1554 eDebugNoSimulate("(DiSEqC peripherial power on)");
1556 eDebugNoSimulate("");
1557 ++m_sec_sequence.current();
1559 case eSecCommand::SEND_TONEBURST:
1560 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1561 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1563 case eSecCommand::SET_FRONTEND:
1564 eDebugNoSimulate("[SEC] setFrontend");
1566 ++m_sec_sequence.current();
1568 case eSecCommand::START_TUNE_TIMEOUT:
1571 m_timeout->start(m_sec_sequence.current()->timeout, 1);
1572 ++m_sec_sequence.current();
1575 case eSecCommand::SET_TIMEOUT:
1576 m_timeoutCount = m_sec_sequence.current()++->val;
1577 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1579 case eSecCommand::IF_TIMEOUT_GOTO:
1580 if (!m_timeoutCount)
1582 eDebugNoSimulate("[SEC] rotor timout");
1583 setSecSequencePos(m_sec_sequence.current()->steps);
1586 ++m_sec_sequence.current();
1588 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1590 int idx = m_sec_sequence.current()++->val;
1591 if ( idx == 0 || idx == 1 )
1593 m_idleInputpower[idx] = sec_fe->readInputpower();
1594 eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1597 eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1600 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1602 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1603 int idx = compare.val;
1604 if ( !m_simulate && (idx == 0 || idx == 1) )
1606 int idle = sec_fe->readInputpower();
1607 int diff = abs(idle-m_idleInputpower[idx]);
1610 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1611 setSecSequencePos(compare.steps);
1615 ++m_sec_sequence.current();
1618 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1620 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1623 setSecSequencePos(cmd.steps);
1627 int isLocked = readFrontendData(locked);
1628 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1629 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 50) || !cmd.lastSignal))
1632 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1635 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1636 cmd.lastSignal = signal;
1639 if (cmd.okcount > 4)
1641 eDebugNoSimulate("ok > 4 .. goto %d\n",cmd.steps);
1642 setSecSequencePos(cmd.steps);
1643 m_state = stateLock;
1644 m_stateChanged(this);
1653 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1655 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1657 if (!m_timeoutCount && m_retryCount > 0)
1662 ++m_sec_sequence.current();
1665 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1666 m_runningInputpower = sec_fe->readInputpower();
1667 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1668 ++m_sec_sequence.current();
1670 case eSecCommand::SET_ROTOR_MOVING:
1672 m_sec->setRotorMoving(true);
1673 ++m_sec_sequence.current();
1675 case eSecCommand::SET_ROTOR_STOPPED:
1677 m_sec->setRotorMoving(false);
1678 ++m_sec_sequence.current();
1680 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1682 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1685 setSecSequencePos(cmd.steps);
1688 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1689 const char *txt = cmd.direction ? "running" : "stopped";
1690 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1692 m_runningInputpower,
1695 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1696 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1699 eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1700 if ( cmd.okcount > 6 )
1702 eDebugNoSimulate("[SEC] rotor is %s", txt);
1703 if (setSecSequencePos(cmd.steps))
1709 eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1711 if (!m_timeoutCount && m_retryCount > 0)
1715 ++m_sec_sequence.current();
1718 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1719 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1720 setSecSequencePos(m_sec_sequence.current()->steps);
1722 ++m_sec_sequence.current();
1724 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1725 eDebugNoSimulate("[SEC] invalidate current switch params");
1726 sec_fe_data[CSW] = -1;
1727 sec_fe_data[UCSW] = -1;
1728 sec_fe_data[TONEBURST] = -1;
1729 ++m_sec_sequence.current();
1731 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1732 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1733 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1734 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1735 eDebugNoSimulate("[SEC] update current switch params");
1736 ++m_sec_sequence.current();
1738 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1739 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1740 sec_fe_data[ROTOR_CMD] = -1;
1741 sec_fe_data[ROTOR_POS] = -1;
1742 ++m_sec_sequence.current();
1744 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1745 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1746 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1747 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1748 ++m_sec_sequence.current();
1750 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1751 m_retryCount = m_sec_sequence.current()++->val;
1752 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1754 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1757 eDebugNoSimulate("[SEC] no more rotor retrys");
1758 setSecSequencePos(m_sec_sequence.current()->steps);
1761 ++m_sec_sequence.current();
1763 case eSecCommand::SET_POWER_LIMITING_MODE:
1768 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1769 FILE *f=fopen(proc_name, "w");
1770 if (f) // new interface exist?
1772 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1773 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1774 eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1776 eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1779 else if (sec_fe->m_need_rotor_workaround)
1782 int slotid = sec_fe->m_slotid;
1783 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1785 sprintf(dev, "/dev/i2c/%d", slotid);
1786 else if (slotid == 2)
1787 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1788 else if (slotid == 3)
1789 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1790 int fd = ::open(dev, O_RDWR);
1792 unsigned char data[2];
1793 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1794 if(::read(fd, data, 1) != 1)
1795 eDebugNoSimulate("[SEC] error read lnbp (%m)");
1796 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1798 data[0] |= 0x80; // enable static current limiting
1799 eDebugNoSimulate("[SEC] set static current limiting");
1803 data[0] &= ~0x80; // enable dynamic current limiting
1804 eDebugNoSimulate("[SEC] set dynamic current limiting");
1806 if(::write(fd, data, 1) != 1)
1807 eDebugNoSimulate("[SEC] error write lnbp (%m)");
1811 ++m_sec_sequence.current();
1815 eDebugNoSimulate("[SEC] unhandled sec command %d",
1816 ++m_sec_sequence.current()->cmd);
1817 ++m_sec_sequence.current();
1820 m_tuneTimer->start(delay,true);
1824 if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1828 void eDVBFrontend::setFrontend()
1832 eDebug("setting frontend %d", m_dvbid);
1835 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1837 perror("FE_SET_FRONTEND failed");
1843 RESULT eDVBFrontend::getFrontendType(int &t)
1851 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1856 eWarning("no SEC module active!");
1859 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1862 #if HAVE_DVB_API_VERSION >= 3
1863 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",
1866 feparm.polarisation,
1870 feparm.orbital_position,
1876 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1879 feparm.polarisation,
1883 feparm.orbital_position);
1885 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1886 switch (feparm.inversion)
1888 case eDVBFrontendParametersSatellite::Inversion::On:
1889 parm_inversion = INVERSION_ON;
1891 case eDVBFrontendParametersSatellite::Inversion::Off:
1892 parm_inversion = INVERSION_OFF;
1895 case eDVBFrontendParametersSatellite::Inversion::Unknown:
1896 parm_inversion = INVERSION_AUTO;
1899 if (feparm.system == eDVBFrontendParametersSatellite::System::DVB_S)
1902 case eDVBFrontendParametersSatellite::FEC::fNone:
1903 parm_u_qpsk_fec_inner = FEC_NONE;
1905 case eDVBFrontendParametersSatellite::FEC::f1_2:
1906 parm_u_qpsk_fec_inner = FEC_1_2;
1908 case eDVBFrontendParametersSatellite::FEC::f2_3:
1909 parm_u_qpsk_fec_inner = FEC_2_3;
1911 case eDVBFrontendParametersSatellite::FEC::f3_4:
1912 parm_u_qpsk_fec_inner = FEC_3_4;
1914 case eDVBFrontendParametersSatellite::FEC::f5_6:
1915 parm_u_qpsk_fec_inner = FEC_5_6;
1917 case eDVBFrontendParametersSatellite::FEC::f7_8:
1918 parm_u_qpsk_fec_inner = FEC_7_8;
1921 eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
1922 case eDVBFrontendParametersSatellite::FEC::fAuto:
1923 parm_u_qpsk_fec_inner = FEC_AUTO;
1926 #if HAVE_DVB_API_VERSION >= 3
1931 case eDVBFrontendParametersSatellite::FEC::f1_2:
1932 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1934 case eDVBFrontendParametersSatellite::FEC::f2_3:
1935 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1937 case eDVBFrontendParametersSatellite::FEC::f3_4:
1938 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1940 case eDVBFrontendParametersSatellite::FEC::f3_5:
1941 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1943 case eDVBFrontendParametersSatellite::FEC::f4_5:
1944 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1946 case eDVBFrontendParametersSatellite::FEC::f5_6:
1947 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1949 case eDVBFrontendParametersSatellite::FEC::f7_8:
1950 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1952 case eDVBFrontendParametersSatellite::FEC::f8_9:
1953 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1955 case eDVBFrontendParametersSatellite::FEC::f9_10:
1956 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1959 eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
1962 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1963 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1964 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK) {
1965 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1966 // 8PSK fec driver values are decimal 9 bigger
1970 // FIXME !!! get frequency range from tuner
1971 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1973 eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1976 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
1981 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1983 #if HAVE_DVB_API_VERSION < 3
1984 parm_frequency = feparm.frequency;
1986 parm_frequency = feparm.frequency * 1000;
1988 parm_u_qam_symbol_rate = feparm.symbol_rate;
1989 switch (feparm.modulation)
1991 case eDVBFrontendParametersCable::Modulation::QAM16:
1992 parm_u_qam_modulation = QAM_16;
1994 case eDVBFrontendParametersCable::Modulation::QAM32:
1995 parm_u_qam_modulation = QAM_32;
1997 case eDVBFrontendParametersCable::Modulation::QAM64:
1998 parm_u_qam_modulation = QAM_64;
2000 case eDVBFrontendParametersCable::Modulation::QAM128:
2001 parm_u_qam_modulation = QAM_128;
2003 case eDVBFrontendParametersCable::Modulation::QAM256:
2004 parm_u_qam_modulation = QAM_256;
2007 case eDVBFrontendParametersCable::Modulation::Auto:
2008 parm_u_qam_modulation = QAM_AUTO;
2011 switch (feparm.inversion)
2013 case eDVBFrontendParametersCable::Inversion::On:
2014 parm_inversion = INVERSION_ON;
2016 case eDVBFrontendParametersCable::Inversion::Off:
2017 parm_inversion = INVERSION_OFF;
2020 case eDVBFrontendParametersCable::Inversion::Unknown:
2021 parm_inversion = INVERSION_AUTO;
2024 switch (feparm.fec_inner)
2026 case eDVBFrontendParametersCable::FEC::fNone:
2027 parm_u_qam_fec_inner = FEC_NONE;
2029 case eDVBFrontendParametersCable::FEC::f1_2:
2030 parm_u_qam_fec_inner = FEC_1_2;
2032 case eDVBFrontendParametersCable::FEC::f2_3:
2033 parm_u_qam_fec_inner = FEC_2_3;
2035 case eDVBFrontendParametersCable::FEC::f3_4:
2036 parm_u_qam_fec_inner = FEC_3_4;
2038 case eDVBFrontendParametersCable::FEC::f5_6:
2039 parm_u_qam_fec_inner = FEC_5_6;
2041 case eDVBFrontendParametersCable::FEC::f7_8:
2042 parm_u_qam_fec_inner = FEC_7_8;
2044 #if HAVE_DVB_API_VERSION >= 3
2045 case eDVBFrontendParametersCable::FEC::f8_9:
2046 parm_u_qam_fec_inner = FEC_8_9;
2050 case eDVBFrontendParametersCable::FEC::fAuto:
2051 parm_u_qam_fec_inner = FEC_AUTO;
2054 eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
2055 parm_frequency/1000,
2056 parm_u_qam_symbol_rate,
2057 parm_u_qam_fec_inner,
2058 parm_u_qam_modulation,
2063 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
2065 parm_frequency = feparm.frequency;
2067 switch (feparm.bandwidth)
2069 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
2070 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
2072 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
2073 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
2075 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
2076 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
2079 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
2080 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
2083 switch (feparm.code_rate_LP)
2085 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
2086 parm_u_ofdm_code_rate_LP = FEC_1_2;
2088 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
2089 parm_u_ofdm_code_rate_LP = FEC_2_3;
2091 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
2092 parm_u_ofdm_code_rate_LP = FEC_3_4;
2094 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
2095 parm_u_ofdm_code_rate_LP = FEC_5_6;
2097 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
2098 parm_u_ofdm_code_rate_LP = FEC_7_8;
2101 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
2102 parm_u_ofdm_code_rate_LP = FEC_AUTO;
2105 switch (feparm.code_rate_HP)
2107 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
2108 parm_u_ofdm_code_rate_HP = FEC_1_2;
2110 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
2111 parm_u_ofdm_code_rate_HP = FEC_2_3;
2113 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
2114 parm_u_ofdm_code_rate_HP = FEC_3_4;
2116 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
2117 parm_u_ofdm_code_rate_HP = FEC_5_6;
2119 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
2120 parm_u_ofdm_code_rate_HP = FEC_7_8;
2123 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
2124 parm_u_ofdm_code_rate_HP = FEC_AUTO;
2127 switch (feparm.modulation)
2129 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
2130 parm_u_ofdm_constellation = QPSK;
2132 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
2133 parm_u_ofdm_constellation = QAM_16;
2135 case eDVBFrontendParametersTerrestrial::Modulation::QAM64:
2136 parm_u_ofdm_constellation = QAM_64;
2139 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
2140 parm_u_ofdm_constellation = QAM_AUTO;
2143 switch (feparm.transmission_mode)
2145 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
2146 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2148 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
2149 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2152 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
2153 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2156 switch (feparm.guard_interval)
2158 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32:
2159 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2161 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16:
2162 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2164 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8:
2165 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2167 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4:
2168 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2171 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto:
2172 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2175 switch (feparm.hierarchy)
2177 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone:
2178 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2180 case eDVBFrontendParametersTerrestrial::Hierarchy::H1:
2181 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2183 case eDVBFrontendParametersTerrestrial::Hierarchy::H2:
2184 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2186 case eDVBFrontendParametersTerrestrial::Hierarchy::H4:
2187 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2190 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto:
2191 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2194 switch (feparm.inversion)
2196 case eDVBFrontendParametersTerrestrial::Inversion::On:
2197 parm_inversion = INVERSION_ON;
2199 case eDVBFrontendParametersTerrestrial::Inversion::Off:
2200 parm_inversion = INVERSION_OFF;
2203 case eDVBFrontendParametersTerrestrial::Inversion::Unknown:
2204 parm_inversion = INVERSION_AUTO;
2210 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2212 unsigned int timeout = 5000;
2213 eDebugNoSimulate("(%d)tune", m_dvbid);
2219 if (!m_sn && !m_simulate)
2221 eDebug("no frontend device opened... do not try to tune !!!");
2235 m_sec_sequence.clear();
2237 where.calcLockTimeout(timeout);
2243 eDVBFrontendParametersSatellite feparm;
2244 if (where.getDVBS(feparm))
2246 eDebug("no dvbs data!");
2251 m_sec->setRotorMoving(false);
2252 res=prepare_sat(feparm, timeout);
2260 eDVBFrontendParametersCable feparm;
2261 if (where.getDVBC(feparm))
2266 res=prepare_cable(feparm);
2270 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2271 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2276 eDVBFrontendParametersTerrestrial feparm;
2277 if (where.getDVBT(feparm))
2279 eDebug("no -T data");
2283 res=prepare_terrestrial(feparm);
2287 std::string enable_5V;
2288 char configStr[255];
2289 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2290 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2291 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2292 if (enable_5V == "True")
2293 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2295 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2296 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2302 m_sec_sequence.current() = m_sec_sequence.begin();
2306 m_tuneTimer->start(0,true);
2307 if (m_state != stateTuning)
2310 m_state = stateTuning;
2311 m_stateChanged(this);
2320 m_tuneTimer->stop();
2324 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2326 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2330 RESULT eDVBFrontend::setVoltage(int voltage)
2332 if (m_type == feCable)
2334 #if HAVE_DVB_API_VERSION < 3
2337 bool increased=false;
2338 fe_sec_voltage_t vlt;
2340 m_data[CUR_VOLTAGE]=voltage;
2344 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2345 vlt = SEC_VOLTAGE_OFF;
2348 #if HAVE_DVB_API_VERSION < 3
2349 vlt = SEC_VOLTAGE_13_5;
2355 vlt = SEC_VOLTAGE_13;
2358 #if HAVE_DVB_API_VERSION < 3
2359 vlt = SEC_VOLTAGE_18_5;
2365 vlt = SEC_VOLTAGE_18;
2372 #if HAVE_DVB_API_VERSION < 3
2373 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2375 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2376 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2377 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2381 RESULT eDVBFrontend::getState(int &state)
2387 RESULT eDVBFrontend::setTone(int t)
2389 if (m_type != feSatellite)
2391 #if HAVE_DVB_API_VERSION < 3
2394 fe_sec_tone_mode_t tone;
2403 tone = SEC_TONE_OFF;
2410 #if HAVE_DVB_API_VERSION < 3
2411 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2413 return ::ioctl(m_fd, FE_SET_TONE, tone);
2417 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2418 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2421 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2425 #if HAVE_DVB_API_VERSION < 3
2426 struct secCommand cmd;
2427 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2428 cmd.u.diseqc.cmdtype = diseqc.data[0];
2429 cmd.u.diseqc.addr = diseqc.data[1];
2430 cmd.u.diseqc.cmd = diseqc.data[2];
2431 cmd.u.diseqc.numParams = diseqc.len-3;
2432 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2433 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2435 struct dvb_diseqc_master_cmd cmd;
2436 memcpy(cmd.msg, diseqc.data, diseqc.len);
2437 cmd.msg_len = diseqc.len;
2438 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2444 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2445 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2447 RESULT eDVBFrontend::sendToneburst(int burst)
2451 #if HAVE_DVB_API_VERSION < 3
2452 secMiniCmd cmd = SEC_MINI_NONE;
2454 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2456 if ( burst == eDVBSatelliteDiseqcParameters::A )
2458 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2460 #if HAVE_DVB_API_VERSION < 3
2461 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2464 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2470 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2476 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2478 m_sec_sequence = list;
2482 RESULT eDVBFrontend::getData(int num, long &data)
2484 if ( num < NUM_DATA_ENTRIES )
2492 RESULT eDVBFrontend::setData(int num, long val)
2494 if ( num < NUM_DATA_ENTRIES )
2502 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2505 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2507 if (m_type == eDVBFrontend::feSatellite)
2510 eDVBFrontendParametersSatellite sat_parm;
2511 int ret = feparm->getDVBS(sat_parm);
2513 if (sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S2 && !m_can_handle_dvbs2)
2515 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2516 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S && m_can_handle_dvbs2)
2520 else if (m_type == eDVBFrontend::feCable)
2521 return 2; // more prio for cable frontends
2522 else if (m_type == eDVBFrontend::feTerrestrial)
2527 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2529 ePyObject Id, Descr, Enabled, IsDVBS2;
2530 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4)
2532 Id = PyTuple_GET_ITEM(obj, 0);
2533 Descr = PyTuple_GET_ITEM(obj, 1);
2534 Enabled = PyTuple_GET_ITEM(obj, 2);
2535 IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2536 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2))
2538 strcpy(m_description, PyString_AS_STRING(Descr));
2539 m_slotid = PyInt_AsLong(Id);
2540 m_enabled = Enabled == Py_True;
2541 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2542 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2543 !!strstr(m_description, "Alps BSBE2") ||
2544 !!strstr(m_description, "Alps -S") ||
2545 !!strstr(m_description, "BCM4501");
2546 m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2547 eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2548 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2551 PyErr_SetString(PyExc_StandardError,
2552 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");