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 int eDVBFrontend::readFrontendData(int type)
707 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
708 eDebug("FE_READ_BER failed (%m)");
717 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
718 eDebug("FE_READ_SNR failed (%m)");
722 case signalQualitydB: /* this will move into the driver */
727 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
728 eDebug("FE_READ_SNR failed (%m)");
729 if (!strcmp(m_description, "BCM4501 (internal)"))
731 unsigned int SDS_SNRE = snr << 16;
734 if (parm_u_qpsk_fec_inner <= FEC_AUTO) // DVB-S1 / QPSK
736 static float SNR_COEFF[6] = {
739 197418.0 / 4194304.0,
740 -2602183.0 / 4194304.0,
741 20377212.0 / 4194304.0,
742 -37791203.0 / 4194304.0,
744 float fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0)),
745 fval2 = pow(10.0, fval1)-1;
746 fval1 = 10.0 * log10(fval2);
750 fval2 = SNR_COEFF[0];
751 for (int i=0; i<6; ++i)
754 fval2 += SNR_COEFF[i];
760 #if HAVE_DVB_API_VERSION >= 3
763 float fval1 = SDS_SNRE / 268435456.0,
766 if (parm_u_qpsk_fec_inner <= FEC_S2_QPSK_9_10) // DVB-S2 QPSK
777 fval4 = -10.0 * log10(fval1);
779 for (int i=0; i < 5; ++i)
780 fval1 = fval4 - fval2 * log10(1.0+pow(10.0, (fval3-fval1)/fval2));
784 return (int)(snr_in_db * 100.0);
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 return (((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") )
834 float snr_in_db=(snr-39075)/1764.7;
835 return (int)(snr_in_db * 100.0);
836 } else if (!strcmp(m_description, "Alps BSBE2"))
838 return (int)((snr >> 7) * 10.0);
840 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
848 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
849 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
855 #if HAVE_DVB_API_VERSION < 3
856 FrontendStatus status=0;
862 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
863 eDebug("FE_READ_STATUS failed (%m)");
864 return !!(status&FE_HAS_LOCK);
870 #if HAVE_DVB_API_VERSION < 3
871 FrontendStatus status=0;
877 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
878 eDebug("FE_READ_STATUS failed (%m)");
879 return !!(status&FE_HAS_SYNC);
889 void PutToDict(ePyObject &dict, const char*key, long value)
891 ePyObject item = PyInt_FromLong(value);
894 if (PyDict_SetItemString(dict, key, item))
895 eDebug("put %s to dict failed", key);
899 eDebug("could not create PyObject for %s", key);
902 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
906 if (PyDict_SetItemString(dict, key, item))
907 eDebug("put %s to dict failed", key);
911 eDebug("invalid PyObject for %s", key);
914 void PutToDict(ePyObject &dict, const char*key, const char *value)
916 ePyObject item = PyString_FromString(value);
919 if (PyDict_SetItemString(dict, key, item))
920 eDebug("put %s to dict failed", key);
924 eDebug("could not create PyObject for %s", key);
927 void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, eDVBFrontend *fe)
931 fe->getData(eDVBFrontend::FREQ_OFFSET, freq_offset);
932 int frequency = parm_frequency + freq_offset;
933 PutToDict(dict, "frequency", frequency);
934 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
935 switch(parm_u_qpsk_fec_inner)
958 #if HAVE_DVB_API_VERSION >=3
959 case FEC_S2_8PSK_1_2:
960 case FEC_S2_QPSK_1_2:
963 case FEC_S2_8PSK_2_3:
964 case FEC_S2_QPSK_2_3:
967 case FEC_S2_8PSK_3_4:
968 case FEC_S2_QPSK_3_4:
971 case FEC_S2_8PSK_5_6:
972 case FEC_S2_QPSK_5_6:
975 case FEC_S2_8PSK_7_8:
976 case FEC_S2_QPSK_7_8:
979 case FEC_S2_8PSK_8_9:
980 case FEC_S2_QPSK_8_9:
983 case FEC_S2_8PSK_3_5:
984 case FEC_S2_QPSK_3_5:
987 case FEC_S2_8PSK_4_5:
988 case FEC_S2_QPSK_4_5:
991 case FEC_S2_8PSK_9_10:
992 case FEC_S2_QPSK_9_10:
997 PutToDict(dict, "fec_inner", tmp);
998 #if HAVE_DVB_API_VERSION >=3
999 PutToDict(dict, "modulation",
1000 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ? "8PSK": "QPSK" );
1001 if (parm_u_qpsk_fec_inner > FEC_AUTO)
1003 switch(parm_inversion & 0xc)
1005 default: // unknown rolloff
1007 tmp = "ROLLOFF_0_35";
1010 tmp = "ROLLOFF_0_25";
1013 tmp = "ROLLOFF_0_20";
1016 PutToDict(dict, "rolloff", tmp);
1017 if (parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10)
1019 switch(parm_inversion & 0x30)
1021 case 0: // pilot off
1024 case 0x10: // pilot on
1027 case 0x20: // pilot auto
1031 PutToDict(dict, "pilot", tmp);
1038 PutToDict(dict, "modulation", "QPSK" );
1041 PutToDict(dict, "system", tmp);
1044 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1047 #if HAVE_DVB_API_VERSION < 3
1048 PutToDict(dict, "frequency", parm_frequency);
1050 PutToDict(dict, "frequency", parm_frequency/1000);
1052 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1053 switch(parm_u_qam_fec_inner)
1073 #if HAVE_DVB_API_VERSION >= 3
1083 PutToDict(dict, "fec_inner", tmp);
1084 switch(parm_u_qam_modulation)
1106 PutToDict(dict, "modulation", tmp);
1109 void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1112 PutToDict(dict, "frequency", parm_frequency);
1113 switch (parm_u_ofdm_bandwidth)
1115 case BANDWIDTH_8_MHZ:
1116 tmp = "BANDWIDTH_8_MHZ";
1118 case BANDWIDTH_7_MHZ:
1119 tmp = "BANDWIDTH_7_MHZ";
1121 case BANDWIDTH_6_MHZ:
1122 tmp = "BANDWIDTH_6_MHZ";
1125 case BANDWIDTH_AUTO:
1126 tmp = "BANDWIDTH_AUTO";
1129 PutToDict(dict, "bandwidth", tmp);
1130 switch (parm_u_ofdm_code_rate_LP)
1152 PutToDict(dict, "code_rate_lp", tmp);
1153 switch (parm_u_ofdm_code_rate_HP)
1175 PutToDict(dict, "code_rate_hp", tmp);
1176 switch (parm_u_ofdm_constellation)
1192 PutToDict(dict, "constellation", tmp);
1193 switch (parm_u_ofdm_transmission_mode)
1195 case TRANSMISSION_MODE_2K:
1196 tmp = "TRANSMISSION_MODE_2K";
1198 case TRANSMISSION_MODE_8K:
1199 tmp = "TRANSMISSION_MODE_8K";
1202 case TRANSMISSION_MODE_AUTO:
1203 tmp = "TRANSMISSION_MODE_AUTO";
1206 PutToDict(dict, "transmission_mode", tmp);
1207 switch (parm_u_ofdm_guard_interval)
1209 case GUARD_INTERVAL_1_32:
1210 tmp = "GUARD_INTERVAL_1_32";
1212 case GUARD_INTERVAL_1_16:
1213 tmp = "GUARD_INTERVAL_1_16";
1215 case GUARD_INTERVAL_1_8:
1216 tmp = "GUARD_INTERVAL_1_8";
1218 case GUARD_INTERVAL_1_4:
1219 tmp = "GUARD_INTERVAL_1_4";
1222 case GUARD_INTERVAL_AUTO:
1223 tmp = "GUARD_INTERVAL_AUTO";
1226 PutToDict(dict, "guard_interval", tmp);
1227 switch (parm_u_ofdm_hierarchy_information)
1229 case HIERARCHY_NONE:
1230 tmp = "HIERARCHY_NONE";
1233 tmp = "HIERARCHY_1";
1236 tmp = "HIERARCHY_2";
1239 tmp = "HIERARCHY_4";
1242 case HIERARCHY_AUTO:
1243 tmp = "HIERARCHY_AUTO";
1246 PutToDict(dict, "hierarchy_information", tmp);
1249 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1251 if (dest && PyDict_Check(dest))
1253 const char *tmp = "UNKNOWN";
1274 PutToDict(dest, "tuner_state", tmp);
1275 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1276 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1277 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1278 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1279 int sigQualitydB = readFrontendData(signalQualitydB);
1280 if (sigQualitydB == 0x12345678) // not support yet
1282 ePyObject obj=Py_None;
1284 PutToDict(dest, "tuner_signal_quality_db", obj);
1287 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1288 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1292 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1294 if (dest && PyDict_Check(dest))
1302 FRONTENDPARAMETERS front;
1303 if (m_fd == -1 && !original)
1305 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1307 eDebug("FE_GET_FRONTEND failed (%m)");
1311 const FRONTENDPARAMETERS &parm = original || m_simulate ? this->parm : front;
1312 const char *tmp = "INVERSION_AUTO";
1313 switch(parm_inversion)
1316 tmp = "INVERSION_ON";
1319 tmp = "INVERSION_OFF";
1325 PutToDict(dest, "inversion", tmp);
1330 fillDictWithSatelliteData(dest, original?parm:front, this);
1333 fillDictWithCableData(dest, original?parm:front);
1336 fillDictWithTerrestrialData(dest, original?parm:front);
1347 void eDVBFrontend::getFrontendData(ePyObject dest)
1349 if (dest && PyDict_Check(dest))
1352 PutToDict(dest, "tuner_number", m_slotid);
1368 PutToDict(dest, "tuner_type", tmp);
1372 #ifndef FP_IOCTL_GET_ID
1373 #define FP_IOCTL_GET_ID 0
1375 int eDVBFrontend::readInputpower()
1379 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1381 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1382 FILE *f=fopen(proc_name, "r");
1385 if (fscanf(f, "%d", &power) != 1)
1386 eDebug("read %s failed!! (%m)", proc_name);
1388 eDebug("%s is %d\n", proc_name, power);
1393 // open front prozessor
1394 int fp=::open("/dev/dbox/fp0", O_RDWR);
1397 eDebug("couldn't open fp");
1400 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1401 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1403 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1412 bool eDVBFrontend::setSecSequencePos(int steps)
1414 eDebugNoSimulate("set sequence pos %d", steps);
1419 if (m_sec_sequence.current() != m_sec_sequence.end())
1420 ++m_sec_sequence.current();
1425 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1426 --m_sec_sequence.current();
1432 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1435 eDVBFrontend *sec_fe = this;
1436 eDVBRegisteredFrontend *regFE = 0;
1437 long tmp = m_data[LINKED_PREV_PTR];
1440 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1441 sec_fe = prev->m_frontend;
1442 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1443 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1444 int state = sec_fe->m_state;
1445 // workaround to put the kernel frontend thread into idle state!
1446 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1448 sec_fe->closeFrontend(true);
1449 state = sec_fe->m_state;
1451 // sec_fe is closed... we must reopen it here..
1452 if (state == eDVBFrontend::stateClosed)
1460 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1462 long *sec_fe_data = sec_fe->m_data;
1463 // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1464 switch (m_sec_sequence.current()->cmd)
1466 case eSecCommand::SLEEP:
1467 delay = m_sec_sequence.current()++->msec;
1468 eDebugNoSimulate("[SEC] sleep %dms", delay);
1470 case eSecCommand::GOTO:
1471 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1472 ++m_sec_sequence.current();
1474 case eSecCommand::SET_VOLTAGE:
1476 int voltage = m_sec_sequence.current()++->voltage;
1477 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1478 sec_fe->setVoltage(voltage);
1481 case eSecCommand::IF_VOLTAGE_GOTO:
1483 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1484 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1486 ++m_sec_sequence.current();
1489 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1491 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1492 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1494 ++m_sec_sequence.current();
1497 case eSecCommand::IF_TONE_GOTO:
1499 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1500 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1502 ++m_sec_sequence.current();
1505 case eSecCommand::IF_NOT_TONE_GOTO:
1507 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1508 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1510 ++m_sec_sequence.current();
1513 case eSecCommand::SET_TONE:
1514 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1515 sec_fe->setTone(m_sec_sequence.current()++->tone);
1517 case eSecCommand::SEND_DISEQC:
1518 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1519 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1520 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1521 eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1522 if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
1523 eDebugNoSimulate("(DiSEqC reset)");
1524 else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
1525 eDebugNoSimulate("(DiSEqC peripherial power on)");
1527 eDebugNoSimulate("");
1528 ++m_sec_sequence.current();
1530 case eSecCommand::SEND_TONEBURST:
1531 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1532 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1534 case eSecCommand::SET_FRONTEND:
1535 eDebugNoSimulate("[SEC] setFrontend");
1537 ++m_sec_sequence.current();
1539 case eSecCommand::START_TUNE_TIMEOUT:
1542 m_timeout->start(m_sec_sequence.current()->timeout, 1);
1543 ++m_sec_sequence.current();
1546 case eSecCommand::SET_TIMEOUT:
1547 m_timeoutCount = m_sec_sequence.current()++->val;
1548 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1550 case eSecCommand::IF_TIMEOUT_GOTO:
1551 if (!m_timeoutCount)
1553 eDebugNoSimulate("[SEC] rotor timout");
1554 setSecSequencePos(m_sec_sequence.current()->steps);
1557 ++m_sec_sequence.current();
1559 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1561 int idx = m_sec_sequence.current()++->val;
1562 if ( idx == 0 || idx == 1 )
1564 m_idleInputpower[idx] = sec_fe->readInputpower();
1565 eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1568 eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1571 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1573 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1574 int idx = compare.val;
1575 if ( !m_simulate && (idx == 0 || idx == 1) )
1577 int idle = sec_fe->readInputpower();
1578 int diff = abs(idle-m_idleInputpower[idx]);
1581 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1582 setSecSequencePos(compare.steps);
1586 ++m_sec_sequence.current();
1589 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1591 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1594 setSecSequencePos(cmd.steps);
1598 int isLocked = readFrontendData(locked);
1599 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1600 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 50) || !cmd.lastSignal))
1603 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1606 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1607 cmd.lastSignal = signal;
1610 if (cmd.okcount > 4)
1612 eDebugNoSimulate("ok > 4 .. goto %d\n",cmd.steps);
1613 setSecSequencePos(cmd.steps);
1614 m_state = stateLock;
1615 m_stateChanged(this);
1624 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1626 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1628 if (!m_timeoutCount && m_retryCount > 0)
1633 ++m_sec_sequence.current();
1636 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1637 m_runningInputpower = sec_fe->readInputpower();
1638 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1639 ++m_sec_sequence.current();
1641 case eSecCommand::SET_ROTOR_MOVING:
1643 m_sec->setRotorMoving(true);
1644 ++m_sec_sequence.current();
1646 case eSecCommand::SET_ROTOR_STOPPED:
1648 m_sec->setRotorMoving(false);
1649 ++m_sec_sequence.current();
1651 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1653 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1656 setSecSequencePos(cmd.steps);
1659 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1660 const char *txt = cmd.direction ? "running" : "stopped";
1661 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1663 m_runningInputpower,
1666 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1667 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1670 eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1671 if ( cmd.okcount > 6 )
1673 eDebugNoSimulate("[SEC] rotor is %s", txt);
1674 if (setSecSequencePos(cmd.steps))
1680 eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1682 if (!m_timeoutCount && m_retryCount > 0)
1686 ++m_sec_sequence.current();
1689 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1690 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1691 setSecSequencePos(m_sec_sequence.current()->steps);
1693 ++m_sec_sequence.current();
1695 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1696 eDebugNoSimulate("[SEC] invalidate current switch params");
1697 sec_fe_data[CSW] = -1;
1698 sec_fe_data[UCSW] = -1;
1699 sec_fe_data[TONEBURST] = -1;
1700 ++m_sec_sequence.current();
1702 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1703 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1704 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1705 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1706 eDebugNoSimulate("[SEC] update current switch params");
1707 ++m_sec_sequence.current();
1709 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1710 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1711 sec_fe_data[ROTOR_CMD] = -1;
1712 sec_fe_data[ROTOR_POS] = -1;
1713 ++m_sec_sequence.current();
1715 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1716 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1717 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1718 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1719 ++m_sec_sequence.current();
1721 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1722 m_retryCount = m_sec_sequence.current()++->val;
1723 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1725 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1728 eDebugNoSimulate("[SEC] no more rotor retrys");
1729 setSecSequencePos(m_sec_sequence.current()->steps);
1732 ++m_sec_sequence.current();
1734 case eSecCommand::SET_POWER_LIMITING_MODE:
1739 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1740 FILE *f=fopen(proc_name, "w");
1741 if (f) // new interface exist?
1743 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1744 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1745 eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1747 eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1750 else if (sec_fe->m_need_rotor_workaround)
1753 int slotid = sec_fe->m_slotid;
1754 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1756 sprintf(dev, "/dev/i2c/%d", slotid);
1757 else if (slotid == 2)
1758 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1759 else if (slotid == 3)
1760 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1761 int fd = ::open(dev, O_RDWR);
1763 unsigned char data[2];
1764 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1765 if(::read(fd, data, 1) != 1)
1766 eDebugNoSimulate("[SEC] error read lnbp (%m)");
1767 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1769 data[0] |= 0x80; // enable static current limiting
1770 eDebugNoSimulate("[SEC] set static current limiting");
1774 data[0] &= ~0x80; // enable dynamic current limiting
1775 eDebugNoSimulate("[SEC] set dynamic current limiting");
1777 if(::write(fd, data, 1) != 1)
1778 eDebugNoSimulate("[SEC] error write lnbp (%m)");
1782 ++m_sec_sequence.current();
1786 eDebugNoSimulate("[SEC] unhandled sec command %d",
1787 ++m_sec_sequence.current()->cmd);
1788 ++m_sec_sequence.current();
1791 m_tuneTimer->start(delay,true);
1795 if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1799 void eDVBFrontend::setFrontend()
1803 eDebug("setting frontend %d", m_dvbid);
1806 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1808 perror("FE_SET_FRONTEND failed");
1814 RESULT eDVBFrontend::getFrontendType(int &t)
1822 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1827 eWarning("no SEC module active!");
1830 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1833 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1836 feparm.polarisation,
1840 feparm.orbital_position);
1841 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1842 switch (feparm.inversion)
1844 case eDVBFrontendParametersSatellite::Inversion::On:
1845 parm_inversion = INVERSION_ON;
1847 case eDVBFrontendParametersSatellite::Inversion::Off:
1848 parm_inversion = INVERSION_OFF;
1851 case eDVBFrontendParametersSatellite::Inversion::Unknown:
1852 parm_inversion = INVERSION_AUTO;
1855 if (feparm.system == eDVBFrontendParametersSatellite::System::DVB_S)
1858 case eDVBFrontendParametersSatellite::FEC::fNone:
1859 parm_u_qpsk_fec_inner = FEC_NONE;
1861 case eDVBFrontendParametersSatellite::FEC::f1_2:
1862 parm_u_qpsk_fec_inner = FEC_1_2;
1864 case eDVBFrontendParametersSatellite::FEC::f2_3:
1865 parm_u_qpsk_fec_inner = FEC_2_3;
1867 case eDVBFrontendParametersSatellite::FEC::f3_4:
1868 parm_u_qpsk_fec_inner = FEC_3_4;
1870 case eDVBFrontendParametersSatellite::FEC::f5_6:
1871 parm_u_qpsk_fec_inner = FEC_5_6;
1873 case eDVBFrontendParametersSatellite::FEC::f7_8:
1874 parm_u_qpsk_fec_inner = FEC_7_8;
1877 eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
1878 case eDVBFrontendParametersSatellite::FEC::fAuto:
1879 parm_u_qpsk_fec_inner = FEC_AUTO;
1882 #if HAVE_DVB_API_VERSION >= 3
1887 case eDVBFrontendParametersSatellite::FEC::f1_2:
1888 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1890 case eDVBFrontendParametersSatellite::FEC::f2_3:
1891 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1893 case eDVBFrontendParametersSatellite::FEC::f3_4:
1894 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1896 case eDVBFrontendParametersSatellite::FEC::f3_5:
1897 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1899 case eDVBFrontendParametersSatellite::FEC::f4_5:
1900 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1902 case eDVBFrontendParametersSatellite::FEC::f5_6:
1903 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1905 case eDVBFrontendParametersSatellite::FEC::f7_8:
1906 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1908 case eDVBFrontendParametersSatellite::FEC::f8_9:
1909 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1911 case eDVBFrontendParametersSatellite::FEC::f9_10:
1912 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1915 eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
1918 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1919 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK) {
1920 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1921 // 8PSK fec driver values are decimal 9 bigger
1922 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1926 // FIXME !!! get frequency range from tuner
1927 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1929 eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1932 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
1937 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1939 #if HAVE_DVB_API_VERSION < 3
1940 parm_frequency = feparm.frequency;
1942 parm_frequency = feparm.frequency * 1000;
1944 parm_u_qam_symbol_rate = feparm.symbol_rate;
1945 switch (feparm.modulation)
1947 case eDVBFrontendParametersCable::Modulation::QAM16:
1948 parm_u_qam_modulation = QAM_16;
1950 case eDVBFrontendParametersCable::Modulation::QAM32:
1951 parm_u_qam_modulation = QAM_32;
1953 case eDVBFrontendParametersCable::Modulation::QAM64:
1954 parm_u_qam_modulation = QAM_64;
1956 case eDVBFrontendParametersCable::Modulation::QAM128:
1957 parm_u_qam_modulation = QAM_128;
1959 case eDVBFrontendParametersCable::Modulation::QAM256:
1960 parm_u_qam_modulation = QAM_256;
1963 case eDVBFrontendParametersCable::Modulation::Auto:
1964 parm_u_qam_modulation = QAM_AUTO;
1967 switch (feparm.inversion)
1969 case eDVBFrontendParametersCable::Inversion::On:
1970 parm_inversion = INVERSION_ON;
1972 case eDVBFrontendParametersCable::Inversion::Off:
1973 parm_inversion = INVERSION_OFF;
1976 case eDVBFrontendParametersCable::Inversion::Unknown:
1977 parm_inversion = INVERSION_AUTO;
1980 switch (feparm.fec_inner)
1982 case eDVBFrontendParametersCable::FEC::fNone:
1983 parm_u_qam_fec_inner = FEC_NONE;
1985 case eDVBFrontendParametersCable::FEC::f1_2:
1986 parm_u_qam_fec_inner = FEC_1_2;
1988 case eDVBFrontendParametersCable::FEC::f2_3:
1989 parm_u_qam_fec_inner = FEC_2_3;
1991 case eDVBFrontendParametersCable::FEC::f3_4:
1992 parm_u_qam_fec_inner = FEC_3_4;
1994 case eDVBFrontendParametersCable::FEC::f5_6:
1995 parm_u_qam_fec_inner = FEC_5_6;
1997 case eDVBFrontendParametersCable::FEC::f7_8:
1998 parm_u_qam_fec_inner = FEC_7_8;
2000 #if HAVE_DVB_API_VERSION >= 3
2001 case eDVBFrontendParametersCable::FEC::f8_9:
2002 parm_u_qam_fec_inner = FEC_8_9;
2006 case eDVBFrontendParametersCable::FEC::fAuto:
2007 parm_u_qam_fec_inner = FEC_AUTO;
2010 eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
2011 parm_frequency/1000,
2012 parm_u_qam_symbol_rate,
2013 parm_u_qam_fec_inner,
2014 parm_u_qam_modulation,
2019 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
2021 parm_frequency = feparm.frequency;
2023 switch (feparm.bandwidth)
2025 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
2026 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
2028 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
2029 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
2031 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
2032 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
2035 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
2036 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
2039 switch (feparm.code_rate_LP)
2041 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
2042 parm_u_ofdm_code_rate_LP = FEC_1_2;
2044 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
2045 parm_u_ofdm_code_rate_LP = FEC_2_3;
2047 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
2048 parm_u_ofdm_code_rate_LP = FEC_3_4;
2050 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
2051 parm_u_ofdm_code_rate_LP = FEC_5_6;
2053 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
2054 parm_u_ofdm_code_rate_LP = FEC_7_8;
2057 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
2058 parm_u_ofdm_code_rate_LP = FEC_AUTO;
2061 switch (feparm.code_rate_HP)
2063 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
2064 parm_u_ofdm_code_rate_HP = FEC_1_2;
2066 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
2067 parm_u_ofdm_code_rate_HP = FEC_2_3;
2069 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
2070 parm_u_ofdm_code_rate_HP = FEC_3_4;
2072 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
2073 parm_u_ofdm_code_rate_HP = FEC_5_6;
2075 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
2076 parm_u_ofdm_code_rate_HP = FEC_7_8;
2079 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
2080 parm_u_ofdm_code_rate_HP = FEC_AUTO;
2083 switch (feparm.modulation)
2085 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
2086 parm_u_ofdm_constellation = QPSK;
2088 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
2089 parm_u_ofdm_constellation = QAM_16;
2091 case eDVBFrontendParametersTerrestrial::Modulation::QAM64:
2092 parm_u_ofdm_constellation = QAM_64;
2095 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
2096 parm_u_ofdm_constellation = QAM_AUTO;
2099 switch (feparm.transmission_mode)
2101 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
2102 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2104 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
2105 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2108 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
2109 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2112 switch (feparm.guard_interval)
2114 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32:
2115 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2117 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16:
2118 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2120 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8:
2121 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2123 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4:
2124 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2127 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto:
2128 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2131 switch (feparm.hierarchy)
2133 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone:
2134 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2136 case eDVBFrontendParametersTerrestrial::Hierarchy::H1:
2137 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2139 case eDVBFrontendParametersTerrestrial::Hierarchy::H2:
2140 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2142 case eDVBFrontendParametersTerrestrial::Hierarchy::H4:
2143 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2146 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto:
2147 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2150 switch (feparm.inversion)
2152 case eDVBFrontendParametersTerrestrial::Inversion::On:
2153 parm_inversion = INVERSION_ON;
2155 case eDVBFrontendParametersTerrestrial::Inversion::Off:
2156 parm_inversion = INVERSION_OFF;
2159 case eDVBFrontendParametersTerrestrial::Inversion::Unknown:
2160 parm_inversion = INVERSION_AUTO;
2166 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2168 unsigned int timeout = 5000;
2169 eDebugNoSimulate("(%d)tune", m_dvbid);
2175 if (!m_sn && !m_simulate)
2177 eDebug("no frontend device opened... do not try to tune !!!");
2191 m_sec_sequence.clear();
2193 where.calcLockTimeout(timeout);
2199 eDVBFrontendParametersSatellite feparm;
2200 if (where.getDVBS(feparm))
2202 eDebug("no dvbs data!");
2207 m_sec->setRotorMoving(false);
2208 res=prepare_sat(feparm, timeout);
2216 eDVBFrontendParametersCable feparm;
2217 if (where.getDVBC(feparm))
2222 res=prepare_cable(feparm);
2226 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2227 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2232 eDVBFrontendParametersTerrestrial feparm;
2233 if (where.getDVBT(feparm))
2235 eDebug("no -T data");
2239 res=prepare_terrestrial(feparm);
2243 std::string enable_5V;
2244 char configStr[255];
2245 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2246 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2247 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2248 if (enable_5V == "True")
2249 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2251 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2252 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2258 m_sec_sequence.current() = m_sec_sequence.begin();
2262 m_tuneTimer->start(0,true);
2263 if (m_state != stateTuning)
2266 m_state = stateTuning;
2267 m_stateChanged(this);
2276 m_tuneTimer->stop();
2280 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2282 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2286 RESULT eDVBFrontend::setVoltage(int voltage)
2288 if (m_type == feCable)
2290 #if HAVE_DVB_API_VERSION < 3
2293 bool increased=false;
2294 fe_sec_voltage_t vlt;
2296 m_data[CUR_VOLTAGE]=voltage;
2300 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2301 vlt = SEC_VOLTAGE_OFF;
2304 #if HAVE_DVB_API_VERSION < 3
2305 vlt = SEC_VOLTAGE_13_5;
2311 vlt = SEC_VOLTAGE_13;
2314 #if HAVE_DVB_API_VERSION < 3
2315 vlt = SEC_VOLTAGE_18_5;
2321 vlt = SEC_VOLTAGE_18;
2328 #if HAVE_DVB_API_VERSION < 3
2329 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2331 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2332 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2333 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2337 RESULT eDVBFrontend::getState(int &state)
2343 RESULT eDVBFrontend::setTone(int t)
2345 if (m_type != feSatellite)
2347 #if HAVE_DVB_API_VERSION < 3
2350 fe_sec_tone_mode_t tone;
2359 tone = SEC_TONE_OFF;
2366 #if HAVE_DVB_API_VERSION < 3
2367 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2369 return ::ioctl(m_fd, FE_SET_TONE, tone);
2373 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2374 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2377 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2381 #if HAVE_DVB_API_VERSION < 3
2382 struct secCommand cmd;
2383 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2384 cmd.u.diseqc.cmdtype = diseqc.data[0];
2385 cmd.u.diseqc.addr = diseqc.data[1];
2386 cmd.u.diseqc.cmd = diseqc.data[2];
2387 cmd.u.diseqc.numParams = diseqc.len-3;
2388 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2389 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2391 struct dvb_diseqc_master_cmd cmd;
2392 memcpy(cmd.msg, diseqc.data, diseqc.len);
2393 cmd.msg_len = diseqc.len;
2394 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2400 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2401 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2403 RESULT eDVBFrontend::sendToneburst(int burst)
2407 #if HAVE_DVB_API_VERSION < 3
2408 secMiniCmd cmd = SEC_MINI_NONE;
2410 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2412 if ( burst == eDVBSatelliteDiseqcParameters::A )
2414 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2416 #if HAVE_DVB_API_VERSION < 3
2417 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2420 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2426 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2432 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2434 m_sec_sequence = list;
2438 RESULT eDVBFrontend::getData(int num, long &data)
2440 if ( num < NUM_DATA_ENTRIES )
2448 RESULT eDVBFrontend::setData(int num, long val)
2450 if ( num < NUM_DATA_ENTRIES )
2458 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2461 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2463 if (m_type == eDVBFrontend::feSatellite)
2466 eDVBFrontendParametersSatellite sat_parm;
2467 int ret = feparm->getDVBS(sat_parm);
2469 if (sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S2 && !m_can_handle_dvbs2)
2471 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2472 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S && m_can_handle_dvbs2)
2476 else if (m_type == eDVBFrontend::feCable)
2477 return 2; // more prio for cable frontends
2478 else if (m_type == eDVBFrontend::feTerrestrial)
2483 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2485 ePyObject Id, Descr, Enabled, IsDVBS2;
2486 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4)
2488 Id = PyTuple_GET_ITEM(obj, 0);
2489 Descr = PyTuple_GET_ITEM(obj, 1);
2490 Enabled = PyTuple_GET_ITEM(obj, 2);
2491 IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2492 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2))
2494 strcpy(m_description, PyString_AS_STRING(Descr));
2495 m_slotid = PyInt_AsLong(Id);
2496 m_enabled = Enabled == Py_True;
2497 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2498 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2499 !!strstr(m_description, "Alps BSBE2") ||
2500 !!strstr(m_description, "Alps -S") ||
2501 !!strstr(m_description, "BCM4501");
2502 m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2503 eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2504 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2507 PyErr_SetString(PyExc_StandardError,
2508 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");