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)");
723 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
724 eDebug("FE_READ_SNR failed (%m)");
728 case signalQualitydB: /* this will move into the driver */
733 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
734 eDebug("FE_READ_SNR failed (%m)");
735 if (!strcmp(m_description, "BCM4501 (internal)"))
737 float SDS_SNRE = snr << 16;
740 if (parm_u_qpsk_fec_inner <= FEC_AUTO) // DVB-S1 / QPSK
742 static float SNR_COEFF[6] = {
745 197418.0 / 4194304.0,
746 -2602183.0 / 4194304.0,
747 20377212.0 / 4194304.0,
748 -37791203.0 / 4194304.0,
750 float fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0)),
751 fval2 = pow(10.0, fval1)-1;
752 fval1 = 10.0 * log10(fval2);
756 fval2 = SNR_COEFF[0];
757 for (int i=1; i<6; ++i)
760 fval2 += SNR_COEFF[i];
766 #if HAVE_DVB_API_VERSION >= 3
769 float fval1 = SDS_SNRE / 268435456.0,
772 if (parm_u_qpsk_fec_inner <= FEC_S2_QPSK_9_10) // DVB-S2 QPSK
783 fval4 = -10.0 * log10(fval1);
785 for (int i=0; i < 5; ++i)
786 fval1 = fval4 - fval2 * log10(1.0+pow(10.0, (fval3-fval1)/fval2));
790 return (int)(snr_in_db * 100);
792 else if (strstr(m_description, "Alps BSBE1 C01A") ||
793 !strcmp(m_description, "Alps -S(STV0288)"))
797 else if (snr == 0xFFFF) // i think this should not happen
801 enum { REALVAL, REGVAL };
802 const long CN_lookup[31][2] = {
803 {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
804 {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
805 {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
806 {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
807 {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
808 {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
811 int add=strchr(m_description, '.') ? 0xA250 : 0xA100;
812 long regval = 0xFFFF - ((snr / 3) + add), // revert some dvb api calulations to get the real register value
816 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
821 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[i][REGVAL]))
826 return (((regval - CN_lookup[Imin][REGVAL])
827 * (CN_lookup[Imax][REALVAL] - CN_lookup[Imin][REALVAL])
828 / (CN_lookup[Imax][REGVAL] - CN_lookup[Imin][REGVAL]))
829 + CN_lookup[Imin][REALVAL]) * 10;
835 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
836 !strcmp(m_description, "Alps -S") ||
837 !strcmp(m_description, "Philips -S") ||
838 !strcmp(m_description, "LG -S") )
840 return (int)((snr-39075)/17.647);
841 } else if (!strcmp(m_description, "Alps BSBE2"))
843 return (int)((snr >> 7) * 10);
844 } else if (!strcmp(m_description, "Philips CU1216Mk3"))
846 int mse = (~snr) & 0xFF;
847 switch (parm_u_qam_modulation) {
848 case QAM_16: return fe_udiv(1950000, (32 * mse) + 138) + 1000;
849 case QAM_32: return fe_udiv(2150000, (40 * mse) + 500) + 1350;
850 case QAM_64: return fe_udiv(2100000, (40 * mse) + 500) + 1250;
851 case QAM_128: return fe_udiv(1850000, (38 * mse) + 400) + 1380;
852 case QAM_256: return fe_udiv(1800000, (100 * mse) + 40) + 2030;
856 } else if (!strcmp(m_description, "Philips TU1216"))
858 snr = 0xFF - (snr & 0xFF);
860 return 10 * (int)(-100 * (log10(snr) - log10(255)));
864 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
872 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
873 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
879 #if HAVE_DVB_API_VERSION < 3
880 FrontendStatus status=0;
886 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
887 eDebug("FE_READ_STATUS failed (%m)");
888 return !!(status&FE_HAS_LOCK);
894 #if HAVE_DVB_API_VERSION < 3
895 FrontendStatus status=0;
901 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
902 eDebug("FE_READ_STATUS failed (%m)");
903 return !!(status&FE_HAS_SYNC);
913 void PutToDict(ePyObject &dict, const char*key, long value)
915 ePyObject item = PyInt_FromLong(value);
918 if (PyDict_SetItemString(dict, key, item))
919 eDebug("put %s to dict failed", key);
923 eDebug("could not create PyObject for %s", key);
926 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
930 if (PyDict_SetItemString(dict, key, item))
931 eDebug("put %s to dict failed", key);
935 eDebug("invalid PyObject for %s", key);
938 void PutToDict(ePyObject &dict, const char*key, const char *value)
940 ePyObject item = PyString_FromString(value);
943 if (PyDict_SetItemString(dict, key, item))
944 eDebug("put %s to dict failed", key);
948 eDebug("could not create PyObject for %s", key);
951 void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, eDVBFrontend *fe)
955 fe->getData(eDVBFrontend::FREQ_OFFSET, freq_offset);
956 int frequency = parm_frequency + freq_offset;
957 PutToDict(dict, "frequency", frequency);
958 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
959 switch(parm_u_qpsk_fec_inner)
982 #if HAVE_DVB_API_VERSION >=3
983 case FEC_S2_8PSK_1_2:
984 case FEC_S2_QPSK_1_2:
987 case FEC_S2_8PSK_2_3:
988 case FEC_S2_QPSK_2_3:
991 case FEC_S2_8PSK_3_4:
992 case FEC_S2_QPSK_3_4:
995 case FEC_S2_8PSK_5_6:
996 case FEC_S2_QPSK_5_6:
999 case FEC_S2_8PSK_7_8:
1000 case FEC_S2_QPSK_7_8:
1003 case FEC_S2_8PSK_8_9:
1004 case FEC_S2_QPSK_8_9:
1007 case FEC_S2_8PSK_3_5:
1008 case FEC_S2_QPSK_3_5:
1011 case FEC_S2_8PSK_4_5:
1012 case FEC_S2_QPSK_4_5:
1015 case FEC_S2_8PSK_9_10:
1016 case FEC_S2_QPSK_9_10:
1021 PutToDict(dict, "fec_inner", tmp);
1022 #if HAVE_DVB_API_VERSION >=3
1023 PutToDict(dict, "modulation",
1024 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ? "8PSK": "QPSK" );
1025 if (parm_u_qpsk_fec_inner > FEC_AUTO)
1027 switch(parm_inversion & 0xc)
1029 default: // unknown rolloff
1031 tmp = "ROLLOFF_0_35";
1034 tmp = "ROLLOFF_0_25";
1037 tmp = "ROLLOFF_0_20";
1040 PutToDict(dict, "rolloff", tmp);
1041 switch(parm_inversion & 0x30)
1043 case 0: // pilot off
1046 case 0x10: // pilot on
1049 case 0x20: // pilot auto
1053 PutToDict(dict, "pilot", tmp);
1059 PutToDict(dict, "modulation", "QPSK" );
1062 PutToDict(dict, "system", tmp);
1065 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1068 #if HAVE_DVB_API_VERSION < 3
1069 PutToDict(dict, "frequency", parm_frequency);
1071 PutToDict(dict, "frequency", parm_frequency/1000);
1073 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1074 switch(parm_u_qam_fec_inner)
1094 #if HAVE_DVB_API_VERSION >= 3
1104 PutToDict(dict, "fec_inner", tmp);
1105 switch(parm_u_qam_modulation)
1127 PutToDict(dict, "modulation", tmp);
1130 void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1133 PutToDict(dict, "frequency", parm_frequency);
1134 switch (parm_u_ofdm_bandwidth)
1136 case BANDWIDTH_8_MHZ:
1137 tmp = "BANDWIDTH_8_MHZ";
1139 case BANDWIDTH_7_MHZ:
1140 tmp = "BANDWIDTH_7_MHZ";
1142 case BANDWIDTH_6_MHZ:
1143 tmp = "BANDWIDTH_6_MHZ";
1146 case BANDWIDTH_AUTO:
1147 tmp = "BANDWIDTH_AUTO";
1150 PutToDict(dict, "bandwidth", tmp);
1151 switch (parm_u_ofdm_code_rate_LP)
1173 PutToDict(dict, "code_rate_lp", tmp);
1174 switch (parm_u_ofdm_code_rate_HP)
1196 PutToDict(dict, "code_rate_hp", tmp);
1197 switch (parm_u_ofdm_constellation)
1213 PutToDict(dict, "constellation", tmp);
1214 switch (parm_u_ofdm_transmission_mode)
1216 case TRANSMISSION_MODE_2K:
1217 tmp = "TRANSMISSION_MODE_2K";
1219 case TRANSMISSION_MODE_8K:
1220 tmp = "TRANSMISSION_MODE_8K";
1223 case TRANSMISSION_MODE_AUTO:
1224 tmp = "TRANSMISSION_MODE_AUTO";
1227 PutToDict(dict, "transmission_mode", tmp);
1228 switch (parm_u_ofdm_guard_interval)
1230 case GUARD_INTERVAL_1_32:
1231 tmp = "GUARD_INTERVAL_1_32";
1233 case GUARD_INTERVAL_1_16:
1234 tmp = "GUARD_INTERVAL_1_16";
1236 case GUARD_INTERVAL_1_8:
1237 tmp = "GUARD_INTERVAL_1_8";
1239 case GUARD_INTERVAL_1_4:
1240 tmp = "GUARD_INTERVAL_1_4";
1243 case GUARD_INTERVAL_AUTO:
1244 tmp = "GUARD_INTERVAL_AUTO";
1247 PutToDict(dict, "guard_interval", tmp);
1248 switch (parm_u_ofdm_hierarchy_information)
1250 case HIERARCHY_NONE:
1251 tmp = "HIERARCHY_NONE";
1254 tmp = "HIERARCHY_1";
1257 tmp = "HIERARCHY_2";
1260 tmp = "HIERARCHY_4";
1263 case HIERARCHY_AUTO:
1264 tmp = "HIERARCHY_AUTO";
1267 PutToDict(dict, "hierarchy_information", tmp);
1270 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1272 if (dest && PyDict_Check(dest))
1274 const char *tmp = "UNKNOWN";
1295 PutToDict(dest, "tuner_state", tmp);
1296 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1297 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1298 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1299 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1300 int sigQualitydB = readFrontendData(signalQualitydB);
1301 if (sigQualitydB == 0x12345678) // not support yet
1303 ePyObject obj=Py_None;
1305 PutToDict(dest, "tuner_signal_quality_db", obj);
1308 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1309 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1313 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1315 if (dest && PyDict_Check(dest))
1323 FRONTENDPARAMETERS front;
1324 if (m_fd == -1 && !original)
1326 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1328 eDebug("FE_GET_FRONTEND failed (%m)");
1332 const FRONTENDPARAMETERS &parm = original || m_simulate ? this->parm : front;
1333 const char *tmp = "INVERSION_AUTO";
1334 switch(parm_inversion & 3)
1337 tmp = "INVERSION_ON";
1340 tmp = "INVERSION_OFF";
1346 PutToDict(dest, "inversion", tmp);
1351 fillDictWithSatelliteData(dest, original?parm:front, this);
1354 fillDictWithCableData(dest, original?parm:front);
1357 fillDictWithTerrestrialData(dest, original?parm:front);
1368 void eDVBFrontend::getFrontendData(ePyObject dest)
1370 if (dest && PyDict_Check(dest))
1373 PutToDict(dest, "tuner_number", m_slotid);
1389 PutToDict(dest, "tuner_type", tmp);
1393 #ifndef FP_IOCTL_GET_ID
1394 #define FP_IOCTL_GET_ID 0
1396 int eDVBFrontend::readInputpower()
1400 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1402 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1403 FILE *f=fopen(proc_name, "r");
1406 if (fscanf(f, "%d", &power) != 1)
1407 eDebug("read %s failed!! (%m)", proc_name);
1409 eDebug("%s is %d\n", proc_name, power);
1414 // open front prozessor
1415 int fp=::open("/dev/dbox/fp0", O_RDWR);
1418 eDebug("couldn't open fp");
1421 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1422 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1424 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1433 bool eDVBFrontend::setSecSequencePos(int steps)
1435 eDebugNoSimulate("set sequence pos %d", steps);
1440 if (m_sec_sequence.current() != m_sec_sequence.end())
1441 ++m_sec_sequence.current();
1446 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1447 --m_sec_sequence.current();
1453 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1456 eDVBFrontend *sec_fe = this;
1457 eDVBRegisteredFrontend *regFE = 0;
1458 long tmp = m_data[LINKED_PREV_PTR];
1461 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1462 sec_fe = prev->m_frontend;
1463 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1464 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1465 int state = sec_fe->m_state;
1466 // workaround to put the kernel frontend thread into idle state!
1467 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1469 sec_fe->closeFrontend(true);
1470 state = sec_fe->m_state;
1472 // sec_fe is closed... we must reopen it here..
1473 if (state == eDVBFrontend::stateClosed)
1481 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1483 long *sec_fe_data = sec_fe->m_data;
1484 // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1485 switch (m_sec_sequence.current()->cmd)
1487 case eSecCommand::SLEEP:
1488 delay = m_sec_sequence.current()++->msec;
1489 eDebugNoSimulate("[SEC] sleep %dms", delay);
1491 case eSecCommand::GOTO:
1492 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1493 ++m_sec_sequence.current();
1495 case eSecCommand::SET_VOLTAGE:
1497 int voltage = m_sec_sequence.current()++->voltage;
1498 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1499 sec_fe->setVoltage(voltage);
1502 case eSecCommand::IF_VOLTAGE_GOTO:
1504 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1505 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1507 ++m_sec_sequence.current();
1510 case eSecCommand::IF_NOT_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_TONE_GOTO:
1520 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1521 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1523 ++m_sec_sequence.current();
1526 case eSecCommand::IF_NOT_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::SET_TONE:
1535 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1536 sec_fe->setTone(m_sec_sequence.current()++->tone);
1538 case eSecCommand::SEND_DISEQC:
1539 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1540 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1541 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1542 eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1543 if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
1544 eDebugNoSimulate("(DiSEqC reset)");
1545 else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
1546 eDebugNoSimulate("(DiSEqC peripherial power on)");
1548 eDebugNoSimulate("");
1549 ++m_sec_sequence.current();
1551 case eSecCommand::SEND_TONEBURST:
1552 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1553 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1555 case eSecCommand::SET_FRONTEND:
1556 eDebugNoSimulate("[SEC] setFrontend");
1558 ++m_sec_sequence.current();
1560 case eSecCommand::START_TUNE_TIMEOUT:
1563 m_timeout->start(m_sec_sequence.current()->timeout, 1);
1564 ++m_sec_sequence.current();
1567 case eSecCommand::SET_TIMEOUT:
1568 m_timeoutCount = m_sec_sequence.current()++->val;
1569 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1571 case eSecCommand::IF_TIMEOUT_GOTO:
1572 if (!m_timeoutCount)
1574 eDebugNoSimulate("[SEC] rotor timout");
1575 setSecSequencePos(m_sec_sequence.current()->steps);
1578 ++m_sec_sequence.current();
1580 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1582 int idx = m_sec_sequence.current()++->val;
1583 if ( idx == 0 || idx == 1 )
1585 m_idleInputpower[idx] = sec_fe->readInputpower();
1586 eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1589 eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1592 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1594 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1595 int idx = compare.val;
1596 if ( !m_simulate && (idx == 0 || idx == 1) )
1598 int idle = sec_fe->readInputpower();
1599 int diff = abs(idle-m_idleInputpower[idx]);
1602 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1603 setSecSequencePos(compare.steps);
1607 ++m_sec_sequence.current();
1610 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1612 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1615 setSecSequencePos(cmd.steps);
1619 int isLocked = readFrontendData(locked);
1620 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1621 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 50) || !cmd.lastSignal))
1624 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1627 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1628 cmd.lastSignal = signal;
1631 if (cmd.okcount > 4)
1633 eDebugNoSimulate("ok > 4 .. goto %d\n",cmd.steps);
1634 setSecSequencePos(cmd.steps);
1635 m_state = stateLock;
1636 m_stateChanged(this);
1645 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1647 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1649 if (!m_timeoutCount && m_retryCount > 0)
1654 ++m_sec_sequence.current();
1657 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1658 m_runningInputpower = sec_fe->readInputpower();
1659 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1660 ++m_sec_sequence.current();
1662 case eSecCommand::SET_ROTOR_MOVING:
1664 m_sec->setRotorMoving(true);
1665 ++m_sec_sequence.current();
1667 case eSecCommand::SET_ROTOR_STOPPED:
1669 m_sec->setRotorMoving(false);
1670 ++m_sec_sequence.current();
1672 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1674 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1677 setSecSequencePos(cmd.steps);
1680 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1681 const char *txt = cmd.direction ? "running" : "stopped";
1682 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1684 m_runningInputpower,
1687 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1688 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1691 eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1692 if ( cmd.okcount > 6 )
1694 eDebugNoSimulate("[SEC] rotor is %s", txt);
1695 if (setSecSequencePos(cmd.steps))
1701 eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1703 if (!m_timeoutCount && m_retryCount > 0)
1707 ++m_sec_sequence.current();
1710 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1711 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1712 setSecSequencePos(m_sec_sequence.current()->steps);
1714 ++m_sec_sequence.current();
1716 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1717 eDebugNoSimulate("[SEC] invalidate current switch params");
1718 sec_fe_data[CSW] = -1;
1719 sec_fe_data[UCSW] = -1;
1720 sec_fe_data[TONEBURST] = -1;
1721 ++m_sec_sequence.current();
1723 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1724 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1725 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1726 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1727 eDebugNoSimulate("[SEC] update current switch params");
1728 ++m_sec_sequence.current();
1730 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1731 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1732 sec_fe_data[ROTOR_CMD] = -1;
1733 sec_fe_data[ROTOR_POS] = -1;
1734 ++m_sec_sequence.current();
1736 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1737 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1738 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1739 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1740 ++m_sec_sequence.current();
1742 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1743 m_retryCount = m_sec_sequence.current()++->val;
1744 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1746 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1749 eDebugNoSimulate("[SEC] no more rotor retrys");
1750 setSecSequencePos(m_sec_sequence.current()->steps);
1753 ++m_sec_sequence.current();
1755 case eSecCommand::SET_POWER_LIMITING_MODE:
1760 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1761 FILE *f=fopen(proc_name, "w");
1762 if (f) // new interface exist?
1764 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1765 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1766 eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1768 eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1771 else if (sec_fe->m_need_rotor_workaround)
1774 int slotid = sec_fe->m_slotid;
1775 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1777 sprintf(dev, "/dev/i2c/%d", slotid);
1778 else if (slotid == 2)
1779 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1780 else if (slotid == 3)
1781 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1782 int fd = ::open(dev, O_RDWR);
1784 unsigned char data[2];
1785 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1786 if(::read(fd, data, 1) != 1)
1787 eDebugNoSimulate("[SEC] error read lnbp (%m)");
1788 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1790 data[0] |= 0x80; // enable static current limiting
1791 eDebugNoSimulate("[SEC] set static current limiting");
1795 data[0] &= ~0x80; // enable dynamic current limiting
1796 eDebugNoSimulate("[SEC] set dynamic current limiting");
1798 if(::write(fd, data, 1) != 1)
1799 eDebugNoSimulate("[SEC] error write lnbp (%m)");
1803 ++m_sec_sequence.current();
1807 eDebugNoSimulate("[SEC] unhandled sec command %d",
1808 ++m_sec_sequence.current()->cmd);
1809 ++m_sec_sequence.current();
1812 m_tuneTimer->start(delay,true);
1816 if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1820 void eDVBFrontend::setFrontend()
1824 eDebug("setting frontend %d", m_dvbid);
1827 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1829 perror("FE_SET_FRONTEND failed");
1835 RESULT eDVBFrontend::getFrontendType(int &t)
1843 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1848 eWarning("no SEC module active!");
1851 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1854 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1857 feparm.polarisation,
1861 feparm.orbital_position);
1862 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1863 switch (feparm.inversion)
1865 case eDVBFrontendParametersSatellite::Inversion::On:
1866 parm_inversion = INVERSION_ON;
1868 case eDVBFrontendParametersSatellite::Inversion::Off:
1869 parm_inversion = INVERSION_OFF;
1872 case eDVBFrontendParametersSatellite::Inversion::Unknown:
1873 parm_inversion = INVERSION_AUTO;
1876 if (feparm.system == eDVBFrontendParametersSatellite::System::DVB_S)
1879 case eDVBFrontendParametersSatellite::FEC::fNone:
1880 parm_u_qpsk_fec_inner = FEC_NONE;
1882 case eDVBFrontendParametersSatellite::FEC::f1_2:
1883 parm_u_qpsk_fec_inner = FEC_1_2;
1885 case eDVBFrontendParametersSatellite::FEC::f2_3:
1886 parm_u_qpsk_fec_inner = FEC_2_3;
1888 case eDVBFrontendParametersSatellite::FEC::f3_4:
1889 parm_u_qpsk_fec_inner = FEC_3_4;
1891 case eDVBFrontendParametersSatellite::FEC::f5_6:
1892 parm_u_qpsk_fec_inner = FEC_5_6;
1894 case eDVBFrontendParametersSatellite::FEC::f7_8:
1895 parm_u_qpsk_fec_inner = FEC_7_8;
1898 eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
1899 case eDVBFrontendParametersSatellite::FEC::fAuto:
1900 parm_u_qpsk_fec_inner = FEC_AUTO;
1903 #if HAVE_DVB_API_VERSION >= 3
1908 case eDVBFrontendParametersSatellite::FEC::f1_2:
1909 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1911 case eDVBFrontendParametersSatellite::FEC::f2_3:
1912 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1914 case eDVBFrontendParametersSatellite::FEC::f3_4:
1915 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1917 case eDVBFrontendParametersSatellite::FEC::f3_5:
1918 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1920 case eDVBFrontendParametersSatellite::FEC::f4_5:
1921 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1923 case eDVBFrontendParametersSatellite::FEC::f5_6:
1924 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1926 case eDVBFrontendParametersSatellite::FEC::f7_8:
1927 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1929 case eDVBFrontendParametersSatellite::FEC::f8_9:
1930 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1932 case eDVBFrontendParametersSatellite::FEC::f9_10:
1933 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1936 eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
1939 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1940 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1941 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK) {
1942 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1943 // 8PSK fec driver values are decimal 9 bigger
1947 // FIXME !!! get frequency range from tuner
1948 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1950 eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1953 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
1958 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1960 #if HAVE_DVB_API_VERSION < 3
1961 parm_frequency = feparm.frequency;
1963 parm_frequency = feparm.frequency * 1000;
1965 parm_u_qam_symbol_rate = feparm.symbol_rate;
1966 switch (feparm.modulation)
1968 case eDVBFrontendParametersCable::Modulation::QAM16:
1969 parm_u_qam_modulation = QAM_16;
1971 case eDVBFrontendParametersCable::Modulation::QAM32:
1972 parm_u_qam_modulation = QAM_32;
1974 case eDVBFrontendParametersCable::Modulation::QAM64:
1975 parm_u_qam_modulation = QAM_64;
1977 case eDVBFrontendParametersCable::Modulation::QAM128:
1978 parm_u_qam_modulation = QAM_128;
1980 case eDVBFrontendParametersCable::Modulation::QAM256:
1981 parm_u_qam_modulation = QAM_256;
1984 case eDVBFrontendParametersCable::Modulation::Auto:
1985 parm_u_qam_modulation = QAM_AUTO;
1988 switch (feparm.inversion)
1990 case eDVBFrontendParametersCable::Inversion::On:
1991 parm_inversion = INVERSION_ON;
1993 case eDVBFrontendParametersCable::Inversion::Off:
1994 parm_inversion = INVERSION_OFF;
1997 case eDVBFrontendParametersCable::Inversion::Unknown:
1998 parm_inversion = INVERSION_AUTO;
2001 switch (feparm.fec_inner)
2003 case eDVBFrontendParametersCable::FEC::fNone:
2004 parm_u_qam_fec_inner = FEC_NONE;
2006 case eDVBFrontendParametersCable::FEC::f1_2:
2007 parm_u_qam_fec_inner = FEC_1_2;
2009 case eDVBFrontendParametersCable::FEC::f2_3:
2010 parm_u_qam_fec_inner = FEC_2_3;
2012 case eDVBFrontendParametersCable::FEC::f3_4:
2013 parm_u_qam_fec_inner = FEC_3_4;
2015 case eDVBFrontendParametersCable::FEC::f5_6:
2016 parm_u_qam_fec_inner = FEC_5_6;
2018 case eDVBFrontendParametersCable::FEC::f7_8:
2019 parm_u_qam_fec_inner = FEC_7_8;
2021 #if HAVE_DVB_API_VERSION >= 3
2022 case eDVBFrontendParametersCable::FEC::f8_9:
2023 parm_u_qam_fec_inner = FEC_8_9;
2027 case eDVBFrontendParametersCable::FEC::fAuto:
2028 parm_u_qam_fec_inner = FEC_AUTO;
2031 eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
2032 parm_frequency/1000,
2033 parm_u_qam_symbol_rate,
2034 parm_u_qam_fec_inner,
2035 parm_u_qam_modulation,
2040 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
2042 parm_frequency = feparm.frequency;
2044 switch (feparm.bandwidth)
2046 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
2047 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
2049 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
2050 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
2052 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
2053 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
2056 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
2057 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
2060 switch (feparm.code_rate_LP)
2062 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
2063 parm_u_ofdm_code_rate_LP = FEC_1_2;
2065 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
2066 parm_u_ofdm_code_rate_LP = FEC_2_3;
2068 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
2069 parm_u_ofdm_code_rate_LP = FEC_3_4;
2071 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
2072 parm_u_ofdm_code_rate_LP = FEC_5_6;
2074 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
2075 parm_u_ofdm_code_rate_LP = FEC_7_8;
2078 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
2079 parm_u_ofdm_code_rate_LP = FEC_AUTO;
2082 switch (feparm.code_rate_HP)
2084 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
2085 parm_u_ofdm_code_rate_HP = FEC_1_2;
2087 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
2088 parm_u_ofdm_code_rate_HP = FEC_2_3;
2090 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
2091 parm_u_ofdm_code_rate_HP = FEC_3_4;
2093 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
2094 parm_u_ofdm_code_rate_HP = FEC_5_6;
2096 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
2097 parm_u_ofdm_code_rate_HP = FEC_7_8;
2100 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
2101 parm_u_ofdm_code_rate_HP = FEC_AUTO;
2104 switch (feparm.modulation)
2106 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
2107 parm_u_ofdm_constellation = QPSK;
2109 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
2110 parm_u_ofdm_constellation = QAM_16;
2112 case eDVBFrontendParametersTerrestrial::Modulation::QAM64:
2113 parm_u_ofdm_constellation = QAM_64;
2116 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
2117 parm_u_ofdm_constellation = QAM_AUTO;
2120 switch (feparm.transmission_mode)
2122 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
2123 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2125 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
2126 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2129 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
2130 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2133 switch (feparm.guard_interval)
2135 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32:
2136 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2138 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16:
2139 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2141 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8:
2142 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2144 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4:
2145 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2148 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto:
2149 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2152 switch (feparm.hierarchy)
2154 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone:
2155 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2157 case eDVBFrontendParametersTerrestrial::Hierarchy::H1:
2158 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2160 case eDVBFrontendParametersTerrestrial::Hierarchy::H2:
2161 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2163 case eDVBFrontendParametersTerrestrial::Hierarchy::H4:
2164 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2167 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto:
2168 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2171 switch (feparm.inversion)
2173 case eDVBFrontendParametersTerrestrial::Inversion::On:
2174 parm_inversion = INVERSION_ON;
2176 case eDVBFrontendParametersTerrestrial::Inversion::Off:
2177 parm_inversion = INVERSION_OFF;
2180 case eDVBFrontendParametersTerrestrial::Inversion::Unknown:
2181 parm_inversion = INVERSION_AUTO;
2187 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2189 unsigned int timeout = 5000;
2190 eDebugNoSimulate("(%d)tune", m_dvbid);
2196 if (!m_sn && !m_simulate)
2198 eDebug("no frontend device opened... do not try to tune !!!");
2212 m_sec_sequence.clear();
2214 where.calcLockTimeout(timeout);
2220 eDVBFrontendParametersSatellite feparm;
2221 if (where.getDVBS(feparm))
2223 eDebug("no dvbs data!");
2228 m_sec->setRotorMoving(false);
2229 res=prepare_sat(feparm, timeout);
2237 eDVBFrontendParametersCable feparm;
2238 if (where.getDVBC(feparm))
2243 res=prepare_cable(feparm);
2247 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2248 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2253 eDVBFrontendParametersTerrestrial feparm;
2254 if (where.getDVBT(feparm))
2256 eDebug("no -T data");
2260 res=prepare_terrestrial(feparm);
2264 std::string enable_5V;
2265 char configStr[255];
2266 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2267 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2268 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2269 if (enable_5V == "True")
2270 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2272 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2273 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2279 m_sec_sequence.current() = m_sec_sequence.begin();
2283 m_tuneTimer->start(0,true);
2284 if (m_state != stateTuning)
2287 m_state = stateTuning;
2288 m_stateChanged(this);
2297 m_tuneTimer->stop();
2301 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2303 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2307 RESULT eDVBFrontend::setVoltage(int voltage)
2309 if (m_type == feCable)
2311 #if HAVE_DVB_API_VERSION < 3
2314 bool increased=false;
2315 fe_sec_voltage_t vlt;
2317 m_data[CUR_VOLTAGE]=voltage;
2321 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2322 vlt = SEC_VOLTAGE_OFF;
2325 #if HAVE_DVB_API_VERSION < 3
2326 vlt = SEC_VOLTAGE_13_5;
2332 vlt = SEC_VOLTAGE_13;
2335 #if HAVE_DVB_API_VERSION < 3
2336 vlt = SEC_VOLTAGE_18_5;
2342 vlt = SEC_VOLTAGE_18;
2349 #if HAVE_DVB_API_VERSION < 3
2350 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2352 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2353 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2354 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2358 RESULT eDVBFrontend::getState(int &state)
2364 RESULT eDVBFrontend::setTone(int t)
2366 if (m_type != feSatellite)
2368 #if HAVE_DVB_API_VERSION < 3
2371 fe_sec_tone_mode_t tone;
2380 tone = SEC_TONE_OFF;
2387 #if HAVE_DVB_API_VERSION < 3
2388 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2390 return ::ioctl(m_fd, FE_SET_TONE, tone);
2394 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2395 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2398 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2402 #if HAVE_DVB_API_VERSION < 3
2403 struct secCommand cmd;
2404 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2405 cmd.u.diseqc.cmdtype = diseqc.data[0];
2406 cmd.u.diseqc.addr = diseqc.data[1];
2407 cmd.u.diseqc.cmd = diseqc.data[2];
2408 cmd.u.diseqc.numParams = diseqc.len-3;
2409 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2410 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2412 struct dvb_diseqc_master_cmd cmd;
2413 memcpy(cmd.msg, diseqc.data, diseqc.len);
2414 cmd.msg_len = diseqc.len;
2415 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2421 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2422 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2424 RESULT eDVBFrontend::sendToneburst(int burst)
2428 #if HAVE_DVB_API_VERSION < 3
2429 secMiniCmd cmd = SEC_MINI_NONE;
2431 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2433 if ( burst == eDVBSatelliteDiseqcParameters::A )
2435 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2437 #if HAVE_DVB_API_VERSION < 3
2438 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2441 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2447 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2453 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2455 m_sec_sequence = list;
2459 RESULT eDVBFrontend::getData(int num, long &data)
2461 if ( num < NUM_DATA_ENTRIES )
2469 RESULT eDVBFrontend::setData(int num, long val)
2471 if ( num < NUM_DATA_ENTRIES )
2479 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2482 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2484 if (m_type == eDVBFrontend::feSatellite)
2487 eDVBFrontendParametersSatellite sat_parm;
2488 int ret = feparm->getDVBS(sat_parm);
2490 if (sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S2 && !m_can_handle_dvbs2)
2492 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2493 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S && m_can_handle_dvbs2)
2497 else if (m_type == eDVBFrontend::feCable)
2498 return 2; // more prio for cable frontends
2499 else if (m_type == eDVBFrontend::feTerrestrial)
2504 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2506 ePyObject Id, Descr, Enabled, IsDVBS2;
2507 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4)
2509 Id = PyTuple_GET_ITEM(obj, 0);
2510 Descr = PyTuple_GET_ITEM(obj, 1);
2511 Enabled = PyTuple_GET_ITEM(obj, 2);
2512 IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2513 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2))
2515 strcpy(m_description, PyString_AS_STRING(Descr));
2516 m_slotid = PyInt_AsLong(Id);
2517 m_enabled = Enabled == Py_True;
2518 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2519 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2520 !!strstr(m_description, "Alps BSBE2") ||
2521 !!strstr(m_description, "Alps -S") ||
2522 !!strstr(m_description, "BCM4501");
2523 m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2524 eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2525 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2528 PyErr_SetString(PyExc_StandardError,
2529 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");