1 #include <lib/dvb/dvb.h>
2 #include <lib/base/eerror.h>
3 #include <lib/base/nconfig.h> // access to python config
9 #ifndef I2C_SLAVE_FORCE
10 #define I2C_SLAVE_FORCE 0x0706
13 #if HAVE_DVB_API_VERSION < 3
14 #include <ost/frontend.h>
16 #define QAM_AUTO (Modulation)6
17 #define TRANSMISSION_MODE_AUTO (TransmitMode)2
18 #define BANDWIDTH_AUTO (BandWidth)3
19 #define GUARD_INTERVAL_AUTO (GuardInterval)4
20 #define HIERARCHY_AUTO (Hierarchy)4
21 #define parm_frequency parm.Frequency
22 #define parm_inversion parm.Inversion
23 #define parm_u_qpsk_symbol_rate parm.u.qpsk.SymbolRate
24 #define parm_u_qpsk_fec_inner parm.u.qpsk.FEC_inner
25 #define parm_u_qam_symbol_rate parm.u.qam.SymbolRate
26 #define parm_u_qam_fec_inner parm.u.qam.FEC_inner
27 #define parm_u_qam_modulation parm.u.qam.QAM
28 #define parm_u_ofdm_bandwidth parm.u.ofdm.bandWidth
29 #define parm_u_ofdm_code_rate_LP parm.u.ofdm.LP_CodeRate
30 #define parm_u_ofdm_code_rate_HP parm.u.ofdm.HP_CodeRate
31 #define parm_u_ofdm_constellation parm.u.ofdm.Constellation
32 #define parm_u_ofdm_transmission_mode parm.u.ofdm.TransmissionMode
33 #define parm_u_ofdm_guard_interval parm.u.ofdm.guardInterval
34 #define parm_u_ofdm_hierarchy_information parm.u.ofdm.HierarchyInformation
36 #include <linux/dvb/frontend.h>
37 #define parm_frequency parm.frequency
38 #define parm_inversion parm.inversion
39 #define parm_u_qpsk_symbol_rate parm.u.qpsk.symbol_rate
40 #define parm_u_qpsk_fec_inner parm.u.qpsk.fec_inner
41 #define parm_u_qam_symbol_rate parm.u.qam.symbol_rate
42 #define parm_u_qam_fec_inner parm.u.qam.fec_inner
43 #define parm_u_qam_modulation parm.u.qam.modulation
44 #define parm_u_ofdm_bandwidth parm.u.ofdm.bandwidth
45 #define parm_u_ofdm_code_rate_LP parm.u.ofdm.code_rate_LP
46 #define parm_u_ofdm_code_rate_HP parm.u.ofdm.code_rate_HP
47 #define parm_u_ofdm_constellation parm.u.ofdm.constellation
48 #define parm_u_ofdm_transmission_mode parm.u.ofdm.transmission_mode
49 #define parm_u_ofdm_guard_interval parm.u.ofdm.guard_interval
50 #define parm_u_ofdm_hierarchy_information parm.u.ofdm.hierarchy_information
52 #warning "FEC_9_10 already exist in dvb api ... it seems it is now ready for DVB-S2"
54 #define FEC_S2_QPSK_1_2 (fe_code_rate_t)(FEC_AUTO+1)
55 #define FEC_S2_QPSK_2_3 (fe_code_rate_t)(FEC_S2_QPSK_1_2+1)
56 #define FEC_S2_QPSK_3_4 (fe_code_rate_t)(FEC_S2_QPSK_2_3+1)
57 #define FEC_S2_QPSK_5_6 (fe_code_rate_t)(FEC_S2_QPSK_3_4+1)
58 #define FEC_S2_QPSK_7_8 (fe_code_rate_t)(FEC_S2_QPSK_5_6+1)
59 #define FEC_S2_QPSK_8_9 (fe_code_rate_t)(FEC_S2_QPSK_7_8+1)
60 #define FEC_S2_QPSK_3_5 (fe_code_rate_t)(FEC_S2_QPSK_8_9+1)
61 #define FEC_S2_QPSK_4_5 (fe_code_rate_t)(FEC_S2_QPSK_3_5+1)
62 #define FEC_S2_QPSK_9_10 (fe_code_rate_t)(FEC_S2_QPSK_4_5+1)
63 #define FEC_S2_8PSK_1_2 (fe_code_rate_t)(FEC_S2_QPSK_9_10+1)
64 #define FEC_S2_8PSK_2_3 (fe_code_rate_t)(FEC_S2_8PSK_1_2+1)
65 #define FEC_S2_8PSK_3_4 (fe_code_rate_t)(FEC_S2_8PSK_2_3+1)
66 #define FEC_S2_8PSK_5_6 (fe_code_rate_t)(FEC_S2_8PSK_3_4+1)
67 #define FEC_S2_8PSK_7_8 (fe_code_rate_t)(FEC_S2_8PSK_5_6+1)
68 #define FEC_S2_8PSK_8_9 (fe_code_rate_t)(FEC_S2_8PSK_7_8+1)
69 #define FEC_S2_8PSK_3_5 (fe_code_rate_t)(FEC_S2_8PSK_8_9+1)
70 #define FEC_S2_8PSK_4_5 (fe_code_rate_t)(FEC_S2_8PSK_3_5+1)
71 #define FEC_S2_8PSK_9_10 (fe_code_rate_t)(FEC_S2_8PSK_4_5+1)
75 #include <dvbsi++/satellite_delivery_system_descriptor.h>
76 #include <dvbsi++/cable_delivery_system_descriptor.h>
77 #include <dvbsi++/terrestrial_delivery_system_descriptor.h>
79 #define eDebugNoSimulate(x...) \
87 eDebugNoNewLine("SIMULATE:"); \
92 #define eDebugNoSimulateNoNewLine(x...) \
100 eDebugNoNewLine("SIMULATE:"); \
101 eDebugNoNewLine(x); \
105 void eDVBDiseqcCommand::setCommandString(const char *str)
110 int slen = strlen(str);
113 eDebug("invalid diseqc command string length (not 2 byte aligned)");
116 if (slen > MAX_DISEQC_LENGTH*2)
118 eDebug("invalid diseqc command string length (string is to long)");
122 for (int i=0; i < slen; ++i)
124 unsigned char c = str[i];
127 case '0' ... '9': c-=48; break;
128 case 'a' ... 'f': c-=87; break;
129 case 'A' ... 'F': c-=55; break;
131 eDebug("invalid character in hex string..ignore complete diseqc command !");
145 void eDVBFrontendParametersSatellite::set(const SatelliteDeliverySystemDescriptor &descriptor)
147 frequency = descriptor.getFrequency() * 10;
148 symbol_rate = descriptor.getSymbolRate() * 100;
149 polarisation = descriptor.getPolarization();
150 fec = descriptor.getFecInner();
151 if ( fec != FEC::fNone && fec > FEC::f9_10 )
153 inversion = Inversion::Unknown;
154 pilot = Pilot::Unknown;
155 orbital_position = ((descriptor.getOrbitalPosition() >> 12) & 0xF) * 1000;
156 orbital_position += ((descriptor.getOrbitalPosition() >> 8) & 0xF) * 100;
157 orbital_position += ((descriptor.getOrbitalPosition() >> 4) & 0xF) * 10;
158 orbital_position += ((descriptor.getOrbitalPosition()) & 0xF);
159 if (orbital_position && (!descriptor.getWestEastFlag()))
160 orbital_position = 3600 - orbital_position;
161 system = descriptor.getModulationSystem();
162 modulation = descriptor.getModulation();
163 if (system == System::DVB_S && modulation == Modulation::M8PSK)
165 eDebug("satellite_delivery_descriptor non valid modulation type.. force QPSK");
168 rolloff = descriptor.getRollOff();
169 if (system == System::DVB_S2)
171 eDebug("SAT DVB-S2 freq %d, %s, pos %d, sr %d, fec %d, modulation %d, rolloff %d",
173 polarisation ? "hor" : "vert",
181 eDebug("SAT DVB-S freq %d, %s, pos %d, sr %d, fec %d",
183 polarisation ? "hor" : "vert",
189 void eDVBFrontendParametersCable::set(const CableDeliverySystemDescriptor &descriptor)
191 frequency = descriptor.getFrequency() / 10;
192 symbol_rate = descriptor.getSymbolRate() * 100;
193 fec_inner = descriptor.getFecInner();
194 if ( fec_inner == 0xF )
195 fec_inner = FEC::fNone;
196 modulation = descriptor.getModulation();
197 if ( modulation > 0x5 )
198 modulation = Modulation::Auto;
199 inversion = Inversion::Unknown;
200 eDebug("Cable freq %d, mod %d, sr %d, fec %d",
202 modulation, symbol_rate, fec_inner);
205 void eDVBFrontendParametersTerrestrial::set(const TerrestrialDeliverySystemDescriptor &descriptor)
207 frequency = descriptor.getCentreFrequency() * 10;
208 bandwidth = descriptor.getBandwidth();
209 if ( bandwidth > 2 ) // 5Mhz forced to auto
210 bandwidth = Bandwidth::BwAuto;
211 code_rate_HP = descriptor.getCodeRateHpStream();
212 if (code_rate_HP > 4)
213 code_rate_HP = FEC::fAuto;
214 code_rate_LP = descriptor.getCodeRateLpStream();
215 if (code_rate_LP > 4)
216 code_rate_LP = FEC::fAuto;
217 transmission_mode = descriptor.getTransmissionMode();
218 if (transmission_mode > 1) // TM4k forced to auto
219 transmission_mode = TransmissionMode::TMAuto;
220 guard_interval = descriptor.getGuardInterval();
221 if (guard_interval > 3)
222 guard_interval = GuardInterval::GI_Auto;
223 hierarchy = descriptor.getHierarchyInformation()&3;
224 modulation = descriptor.getConstellation();
226 modulation = Modulation::Auto;
227 inversion = Inversion::Unknown;
228 eDebug("Terr freq %d, bw %d, cr_hp %d, cr_lp %d, tm_mode %d, guard %d, hierarchy %d, const %d",
229 frequency, bandwidth, code_rate_HP, code_rate_LP, transmission_mode,
230 guard_interval, hierarchy, modulation);
233 eDVBFrontendParameters::eDVBFrontendParameters()
234 :m_type(-1), m_flags(0)
238 DEFINE_REF(eDVBFrontendParameters);
240 RESULT eDVBFrontendParameters::getSystem(int &t) const
248 RESULT eDVBFrontendParameters::getDVBS(eDVBFrontendParametersSatellite &p) const
250 if (m_type != iDVBFrontend::feSatellite)
256 RESULT eDVBFrontendParameters::getDVBC(eDVBFrontendParametersCable &p) const
258 if (m_type != iDVBFrontend::feCable)
264 RESULT eDVBFrontendParameters::getDVBT(eDVBFrontendParametersTerrestrial &p) const
266 if (m_type != iDVBFrontend::feTerrestrial)
272 RESULT eDVBFrontendParameters::setDVBS(const eDVBFrontendParametersSatellite &p, bool no_rotor_command_on_tune)
275 sat.no_rotor_command_on_tune = no_rotor_command_on_tune;
276 m_type = iDVBFrontend::feSatellite;
280 RESULT eDVBFrontendParameters::setDVBC(const eDVBFrontendParametersCable &p)
283 m_type = iDVBFrontend::feCable;
287 RESULT eDVBFrontendParameters::setDVBT(const eDVBFrontendParametersTerrestrial &p)
290 m_type = iDVBFrontend::feTerrestrial;
294 RESULT eDVBFrontendParameters::calculateDifference(const iDVBFrontendParameters *parm, int &diff, bool exact) const
299 if (parm->getSystem(type))
303 diff = 1<<30; // big difference
309 case iDVBFrontend::feSatellite:
311 eDVBFrontendParametersSatellite osat;
312 if (parm->getDVBS(osat))
315 if (sat.orbital_position != osat.orbital_position)
317 else if (sat.polarisation != osat.polarisation)
319 else if (exact && sat.fec != osat.fec && sat.fec != eDVBFrontendParametersSatellite::FEC::fAuto && osat.fec != eDVBFrontendParametersSatellite::FEC::fAuto)
321 else if (exact && sat.modulation != osat.modulation && sat.modulation != eDVBFrontendParametersSatellite::Modulation::Auto && osat.modulation != eDVBFrontendParametersSatellite::Modulation::Auto)
325 diff = abs(sat.frequency - osat.frequency);
326 diff += abs(sat.symbol_rate - osat.symbol_rate);
330 case iDVBFrontend::feCable:
331 eDVBFrontendParametersCable ocable;
332 if (parm->getDVBC(ocable))
335 if (exact && cable.modulation != ocable.modulation
336 && cable.modulation != eDVBFrontendParametersCable::Modulation::Auto
337 && ocable.modulation != eDVBFrontendParametersCable::Modulation::Auto)
339 else if (exact && cable.fec_inner != ocable.fec_inner && cable.fec_inner != eDVBFrontendParametersCable::FEC::fAuto && ocable.fec_inner != eDVBFrontendParametersCable::FEC::fAuto)
343 diff = abs(cable.frequency - ocable.frequency);
344 diff += abs(cable.symbol_rate - ocable.symbol_rate);
347 case iDVBFrontend::feTerrestrial:
348 eDVBFrontendParametersTerrestrial oterrestrial;
349 if (parm->getDVBT(oterrestrial))
352 if (exact && oterrestrial.bandwidth != terrestrial.bandwidth &&
353 oterrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto &&
354 terrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto)
356 else if (exact && oterrestrial.modulation != terrestrial.modulation &&
357 oterrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation::Auto &&
358 terrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation::Auto)
360 else if (exact && oterrestrial.transmission_mode != terrestrial.transmission_mode &&
361 oterrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto &&
362 terrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto)
364 else if (exact && oterrestrial.guard_interval != terrestrial.guard_interval &&
365 oterrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto &&
366 terrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto)
368 else if (exact && oterrestrial.hierarchy != terrestrial.hierarchy &&
369 oterrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy::HAuto &&
370 terrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy::HAuto)
372 else if (exact && oterrestrial.code_rate_LP != terrestrial.code_rate_LP &&
373 oterrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC::fAuto &&
374 terrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC::fAuto)
376 else if (exact && oterrestrial.code_rate_HP != terrestrial.code_rate_HP &&
377 oterrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC::fAuto &&
378 terrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC::fAuto)
381 diff = abs(terrestrial.frequency - oterrestrial.frequency);
389 RESULT eDVBFrontendParameters::getHash(unsigned long &hash) const
393 case iDVBFrontend::feSatellite:
395 hash = (sat.orbital_position << 16);
396 hash |= ((sat.frequency/1000)&0xFFFF)|((sat.polarisation&1) << 15);
399 case iDVBFrontend::feCable:
401 hash |= (cable.frequency/1000)&0xFFFF;
403 case iDVBFrontend::feTerrestrial:
405 hash |= (terrestrial.frequency/1000)&0xFFFF;
412 RESULT eDVBFrontendParameters::calcLockTimeout(unsigned int &timeout) const
416 case iDVBFrontend::feSatellite:
418 /* high symbol rate transponders tune faster, due to
419 requiring less zigzag and giving more symbols faster.
421 5s are definitely not enough on really low SR when
422 zigzag has to find the exact frequency first.
424 if (sat.symbol_rate > 20000000)
426 else if (sat.symbol_rate > 10000000)
432 case iDVBFrontend::feCable:
435 case iDVBFrontend::feTerrestrial:
443 DEFINE_REF(eDVBFrontend);
445 int eDVBFrontend::PriorityOrder=0;
447 eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok, bool simulate)
448 :m_simulate(simulate), m_enabled(false), m_type(-1), m_dvbid(fe), m_slotid(fe)
449 ,m_fd(-1), m_need_rotor_workaround(false), m_can_handle_dvbs2(false)
450 , m_timeout(0), m_tuneTimer(0)
451 #if HAVE_DVB_API_VERSION < 3
455 #if HAVE_DVB_API_VERSION < 3
456 sprintf(m_filename, "/dev/dvb/card%d/frontend%d", adap, fe);
457 sprintf(m_sec_filename, "/dev/dvb/card%d/sec%d", adap, fe);
459 sprintf(m_filename, "/dev/dvb/adapter%d/frontend%d", adap, fe);
462 m_timeout = eTimer::create(eApp);
463 CONNECT(m_timeout->timeout, eDVBFrontend::timeout);
465 m_tuneTimer = eTimer::create(eApp);
466 CONNECT(m_tuneTimer->timeout, eDVBFrontend::tuneLoop);
468 for (int i=0; i<eDVBFrontend::NUM_DATA_ENTRIES; ++i)
471 m_idleInputpower[0]=m_idleInputpower[1]=0;
473 ok = !openFrontend();
477 int eDVBFrontend::openFrontend()
480 return -1; // already opened
485 #if HAVE_DVB_API_VERSION < 3
486 FrontendInfo fe_info;
488 dvb_frontend_info fe_info;
490 eDebugNoSimulate("opening frontend %d", m_dvbid);
493 if (!m_simulate || m_type == -1)
495 m_fd = ::open(m_filename, O_RDWR|O_NONBLOCK);
498 eWarning("failed! (%s) %m", m_filename);
504 eWarning("frontend %d already opened", m_dvbid);
507 if (::ioctl(m_fd, FE_GET_INFO, &fe_info) < 0)
509 eWarning("ioctl FE_GET_INFO failed");
515 switch (fe_info.type)
518 m_type = iDVBFrontend::feSatellite;
521 m_type = iDVBFrontend::feCable;
524 m_type = iDVBFrontend::feTerrestrial;
527 eWarning("unknown frontend type.");
532 eDebugNoSimulate("detected %s frontend", "satellite\0cable\0 terrestrial"+fe_info.type*10);
535 #if HAVE_DVB_API_VERSION < 3
536 if (m_type == iDVBFrontend::feSatellite)
542 m_secfd = ::open(m_sec_filename, O_RDWR);
545 eWarning("failed! (%s) %m", m_sec_filename);
553 eWarning("sec %d already opened", m_dvbid);
557 setTone(iDVBFrontend::toneOff);
558 setVoltage(iDVBFrontend::voltageOff);
562 m_sn = eSocketNotifier::create(eApp, m_fd, eSocketNotifier::Read, false);
563 CONNECT(m_sn->activated, eDVBFrontend::feEvent);
569 int eDVBFrontend::closeFrontend(bool force)
571 if (!force && m_data[CUR_VOLTAGE] != -1 && m_data[CUR_VOLTAGE] != iDVBFrontend::voltageOff)
573 long tmp = m_data[LINKED_NEXT_PTR];
576 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
577 if (linked_fe->m_inuse)
579 eDebugNoSimulate("dont close frontend %d until the linked frontend %d in slot %d is still in use",
580 m_dvbid, linked_fe->m_frontend->getDVBID(), linked_fe->m_frontend->getSlotID());
583 linked_fe->m_frontend->getData(LINKED_NEXT_PTR, tmp);
589 eDebugNoSimulate("close frontend %d", m_dvbid);
590 setTone(iDVBFrontend::toneOff);
591 setVoltage(iDVBFrontend::voltageOff);
593 if (m_sec && !m_simulate)
594 m_sec->setRotorMoving(false);
598 eWarning("couldnt close frontend %d", m_dvbid);
602 setTone(iDVBFrontend::toneOff);
603 setVoltage(iDVBFrontend::voltageOff);
605 #if HAVE_DVB_API_VERSION < 3
608 if (!::close(m_secfd))
611 eWarning("couldnt close sec %d", m_dvbid);
615 m_state = stateClosed;
620 eDVBFrontend::~eDVBFrontend()
622 m_data[LINKED_PREV_PTR] = m_data[LINKED_NEXT_PTR] = -1;
626 void eDVBFrontend::feEvent(int w)
628 eDVBFrontend *sec_fe = this;
629 long tmp = m_data[LINKED_PREV_PTR];
632 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
633 sec_fe = linked_fe->m_frontend;
634 sec_fe->getData(LINKED_NEXT_PTR, tmp);
638 #if HAVE_DVB_API_VERSION < 3
641 dvb_frontend_event event;
645 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
647 if (res && (errno == EAGAIN))
652 eWarning("FE_GET_EVENT failed! %m");
659 #if HAVE_DVB_API_VERSION < 3
660 if (event.type == FE_COMPLETION_EV)
662 eDebug("(%d)fe event: status %x, inversion %s", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off");
663 if (event.status & FE_HAS_LOCK)
673 eDebug("stateLostLock");
674 state = stateLostLock;
675 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
678 if (m_state != state)
681 m_stateChanged(this);
686 void eDVBFrontend::timeout()
689 if (m_state == stateTuning)
691 m_state = stateFailed;
692 m_stateChanged(this);
696 #define INRANGE(X,Y,Z) (((X<=Y) && (Y<=Z))||((Z<=Y) && (Y<=X)) ? 1 : 0)
698 /* unsigned 32 bit division */
699 static inline uint32_t fe_udiv(uint32_t a, uint32_t b)
701 return (a + b / 2) / b;
704 int eDVBFrontend::readFrontendData(int type)
713 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
714 eDebug("FE_READ_BER failed (%m)");
719 case signalQualitydB: /* this will move into the driver */
721 int ret = 0x12345678;
725 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
726 eDebug("FE_READ_SNR failed (%m)");
727 else if (!strcmp(m_description, "BCM4501 (internal)"))
729 float SDS_SNRE = snr << 16;
732 if (parm_u_qpsk_fec_inner <= FEC_AUTO) // DVB-S1 / QPSK
734 static float SNR_COEFF[6] = {
737 197418.0 / 4194304.0,
738 -2602183.0 / 4194304.0,
739 20377212.0 / 4194304.0,
740 -37791203.0 / 4194304.0,
742 float fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0)),
743 fval2 = pow(10.0, fval1)-1;
744 fval1 = 10.0 * log10(fval2);
748 fval2 = SNR_COEFF[0];
749 for (int i=1; i<6; ++i)
752 fval2 += SNR_COEFF[i];
758 #if HAVE_DVB_API_VERSION >= 3
761 float fval1 = SDS_SNRE / 268435456.0,
764 if (parm_u_qpsk_fec_inner <= FEC_S2_QPSK_9_10) // DVB-S2 QPSK
775 fval4 = -10.0 * log10(fval1);
777 for (int i=0; i < 5; ++i)
778 fval1 = fval4 - fval2 * log10(1.0+pow(10.0, (fval3-fval1)/fval2));
782 ret = (int)(snr_in_db * 100);
784 else if (strstr(m_description, "Alps BSBE1 C01A") ||
785 !strcmp(m_description, "Alps -S(STV0288)"))
789 else if (snr == 0xFFFF) // i think this should not happen
793 enum { REALVAL, REGVAL };
794 const long CN_lookup[31][2] = {
795 {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
796 {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
797 {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
798 {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
799 {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
800 {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
803 int add=strchr(m_description, '.') ? 0xA250 : 0xA100;
804 long regval = 0xFFFF - ((snr / 3) + add), // revert some dvb api calulations to get the real register value
808 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
813 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[i][REGVAL]))
818 ret = (((regval - CN_lookup[Imin][REGVAL])
819 * (CN_lookup[Imax][REALVAL] - CN_lookup[Imin][REALVAL])
820 / (CN_lookup[Imax][REGVAL] - CN_lookup[Imin][REGVAL]))
821 + CN_lookup[Imin][REALVAL]) * 10;
827 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
828 !strcmp(m_description, "Alps -S") ||
829 !strcmp(m_description, "Philips -S") ||
830 !strcmp(m_description, "LG -S") )
832 ret = (int)((snr-39075)/17.647);
833 } else if (!strcmp(m_description, "Alps BSBE2"))
835 ret = (int)((snr >> 7) * 10);
836 } else if (!strcmp(m_description, "Philips CU1216Mk3"))
838 int mse = (~snr) & 0xFF;
839 switch (parm_u_qam_modulation) {
840 case QAM_16: ret = fe_udiv(1950000, (32 * mse) + 138) + 1000; break;
841 case QAM_32: ret = fe_udiv(2150000, (40 * mse) + 500) + 1350; break;
842 case QAM_64: ret = fe_udiv(2100000, (40 * mse) + 500) + 1250; break;
843 case QAM_128: ret = fe_udiv(1850000, (38 * mse) + 400) + 1380; break;
844 case QAM_256: ret = fe_udiv(1800000, (100 * mse) + 40) + 2030; break;
847 } else if (!strcmp(m_description, "Philips TU1216"))
849 snr = 0xFF - (snr & 0xFF);
851 ret = 10 * (int)(-100 * (log10(snr) - log10(255)));
854 if (type == signalQuality)
856 if (ret == 0x12345678) // no snr db calculation avail.. return untouched snr value..
860 case feSatellite: // we assume a max of 17.5db here
861 return ret >= 1750 ? 65536 : ret * 65536 / 1750;
862 case feCable: // we assume a max of 42db here
863 return ret >= 4200 ? 65536 : ret * 65536 / 4200;
864 case feTerrestrial: // we assume a max of 24db here
865 return ret >= 2400 ? 65536 : ret * 65536 / 2400;
869 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
877 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
878 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
884 #if HAVE_DVB_API_VERSION < 3
885 FrontendStatus status=0;
891 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
892 eDebug("FE_READ_STATUS failed (%m)");
893 return !!(status&FE_HAS_LOCK);
899 #if HAVE_DVB_API_VERSION < 3
900 FrontendStatus status=0;
906 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
907 eDebug("FE_READ_STATUS failed (%m)");
908 return !!(status&FE_HAS_SYNC);
918 void PutToDict(ePyObject &dict, const char*key, long value)
920 ePyObject item = PyInt_FromLong(value);
923 if (PyDict_SetItemString(dict, key, item))
924 eDebug("put %s to dict failed", key);
928 eDebug("could not create PyObject for %s", key);
931 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
935 if (PyDict_SetItemString(dict, key, item))
936 eDebug("put %s to dict failed", key);
940 eDebug("invalid PyObject for %s", key);
943 void PutToDict(ePyObject &dict, const char*key, const char *value)
945 ePyObject item = PyString_FromString(value);
948 if (PyDict_SetItemString(dict, key, item))
949 eDebug("put %s to dict failed", key);
953 eDebug("could not create PyObject for %s", key);
956 void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, eDVBFrontend *fe)
960 fe->getData(eDVBFrontend::FREQ_OFFSET, freq_offset);
961 int frequency = parm_frequency + freq_offset;
962 PutToDict(dict, "frequency", frequency);
963 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
964 switch(parm_u_qpsk_fec_inner)
987 #if HAVE_DVB_API_VERSION >=3
988 case FEC_S2_8PSK_1_2:
989 case FEC_S2_QPSK_1_2:
992 case FEC_S2_8PSK_2_3:
993 case FEC_S2_QPSK_2_3:
996 case FEC_S2_8PSK_3_4:
997 case FEC_S2_QPSK_3_4:
1000 case FEC_S2_8PSK_5_6:
1001 case FEC_S2_QPSK_5_6:
1004 case FEC_S2_8PSK_7_8:
1005 case FEC_S2_QPSK_7_8:
1008 case FEC_S2_8PSK_8_9:
1009 case FEC_S2_QPSK_8_9:
1012 case FEC_S2_8PSK_3_5:
1013 case FEC_S2_QPSK_3_5:
1016 case FEC_S2_8PSK_4_5:
1017 case FEC_S2_QPSK_4_5:
1020 case FEC_S2_8PSK_9_10:
1021 case FEC_S2_QPSK_9_10:
1026 PutToDict(dict, "fec_inner", tmp);
1027 #if HAVE_DVB_API_VERSION >=3
1028 PutToDict(dict, "modulation",
1029 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ? "8PSK": "QPSK" );
1030 if (parm_u_qpsk_fec_inner > FEC_AUTO)
1032 switch(parm_inversion & 0xc)
1034 default: // unknown rolloff
1036 tmp = "ROLLOFF_0_35";
1039 tmp = "ROLLOFF_0_25";
1042 tmp = "ROLLOFF_0_20";
1045 PutToDict(dict, "rolloff", tmp);
1046 switch(parm_inversion & 0x30)
1048 case 0: // pilot off
1051 case 0x10: // pilot on
1054 case 0x20: // pilot auto
1058 PutToDict(dict, "pilot", tmp);
1064 PutToDict(dict, "modulation", "QPSK" );
1067 PutToDict(dict, "system", tmp);
1070 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1073 #if HAVE_DVB_API_VERSION < 3
1074 PutToDict(dict, "frequency", parm_frequency);
1076 PutToDict(dict, "frequency", parm_frequency/1000);
1078 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1079 switch(parm_u_qam_fec_inner)
1099 #if HAVE_DVB_API_VERSION >= 3
1109 PutToDict(dict, "fec_inner", tmp);
1110 switch(parm_u_qam_modulation)
1132 PutToDict(dict, "modulation", tmp);
1135 void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1138 PutToDict(dict, "frequency", parm_frequency);
1139 switch (parm_u_ofdm_bandwidth)
1141 case BANDWIDTH_8_MHZ:
1142 tmp = "BANDWIDTH_8_MHZ";
1144 case BANDWIDTH_7_MHZ:
1145 tmp = "BANDWIDTH_7_MHZ";
1147 case BANDWIDTH_6_MHZ:
1148 tmp = "BANDWIDTH_6_MHZ";
1151 case BANDWIDTH_AUTO:
1152 tmp = "BANDWIDTH_AUTO";
1155 PutToDict(dict, "bandwidth", tmp);
1156 switch (parm_u_ofdm_code_rate_LP)
1178 PutToDict(dict, "code_rate_lp", tmp);
1179 switch (parm_u_ofdm_code_rate_HP)
1201 PutToDict(dict, "code_rate_hp", tmp);
1202 switch (parm_u_ofdm_constellation)
1218 PutToDict(dict, "constellation", tmp);
1219 switch (parm_u_ofdm_transmission_mode)
1221 case TRANSMISSION_MODE_2K:
1222 tmp = "TRANSMISSION_MODE_2K";
1224 case TRANSMISSION_MODE_8K:
1225 tmp = "TRANSMISSION_MODE_8K";
1228 case TRANSMISSION_MODE_AUTO:
1229 tmp = "TRANSMISSION_MODE_AUTO";
1232 PutToDict(dict, "transmission_mode", tmp);
1233 switch (parm_u_ofdm_guard_interval)
1235 case GUARD_INTERVAL_1_32:
1236 tmp = "GUARD_INTERVAL_1_32";
1238 case GUARD_INTERVAL_1_16:
1239 tmp = "GUARD_INTERVAL_1_16";
1241 case GUARD_INTERVAL_1_8:
1242 tmp = "GUARD_INTERVAL_1_8";
1244 case GUARD_INTERVAL_1_4:
1245 tmp = "GUARD_INTERVAL_1_4";
1248 case GUARD_INTERVAL_AUTO:
1249 tmp = "GUARD_INTERVAL_AUTO";
1252 PutToDict(dict, "guard_interval", tmp);
1253 switch (parm_u_ofdm_hierarchy_information)
1255 case HIERARCHY_NONE:
1256 tmp = "HIERARCHY_NONE";
1259 tmp = "HIERARCHY_1";
1262 tmp = "HIERARCHY_2";
1265 tmp = "HIERARCHY_4";
1268 case HIERARCHY_AUTO:
1269 tmp = "HIERARCHY_AUTO";
1272 PutToDict(dict, "hierarchy_information", tmp);
1275 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1277 if (dest && PyDict_Check(dest))
1279 const char *tmp = "UNKNOWN";
1300 PutToDict(dest, "tuner_state", tmp);
1301 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1302 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1303 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1304 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1305 int sigQualitydB = readFrontendData(signalQualitydB);
1306 if (sigQualitydB == 0x12345678) // not support yet
1308 ePyObject obj=Py_None;
1310 PutToDict(dest, "tuner_signal_quality_db", obj);
1313 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1314 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1318 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1320 if (dest && PyDict_Check(dest))
1328 FRONTENDPARAMETERS front;
1329 if (m_fd == -1 && !original)
1331 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1333 eDebug("FE_GET_FRONTEND failed (%m)");
1337 const FRONTENDPARAMETERS &parm = original || m_simulate ? this->parm : front;
1338 const char *tmp = "INVERSION_AUTO";
1339 switch(parm_inversion & 3)
1342 tmp = "INVERSION_ON";
1345 tmp = "INVERSION_OFF";
1351 PutToDict(dest, "inversion", tmp);
1356 fillDictWithSatelliteData(dest, original?parm:front, this);
1359 fillDictWithCableData(dest, original?parm:front);
1362 fillDictWithTerrestrialData(dest, original?parm:front);
1373 void eDVBFrontend::getFrontendData(ePyObject dest)
1375 if (dest && PyDict_Check(dest))
1378 PutToDict(dest, "tuner_number", m_slotid);
1394 PutToDict(dest, "tuner_type", tmp);
1398 #ifndef FP_IOCTL_GET_ID
1399 #define FP_IOCTL_GET_ID 0
1401 int eDVBFrontend::readInputpower()
1405 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1407 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1408 FILE *f=fopen(proc_name, "r");
1411 if (fscanf(f, "%d", &power) != 1)
1412 eDebug("read %s failed!! (%m)", proc_name);
1414 eDebug("%s is %d\n", proc_name, power);
1419 // open front prozessor
1420 int fp=::open("/dev/dbox/fp0", O_RDWR);
1423 eDebug("couldn't open fp");
1426 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1427 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1429 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1438 bool eDVBFrontend::setSecSequencePos(int steps)
1440 eDebugNoSimulate("set sequence pos %d", steps);
1445 if (m_sec_sequence.current() != m_sec_sequence.end())
1446 ++m_sec_sequence.current();
1451 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1452 --m_sec_sequence.current();
1458 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1461 eDVBFrontend *sec_fe = this;
1462 eDVBRegisteredFrontend *regFE = 0;
1463 long tmp = m_data[LINKED_PREV_PTR];
1466 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1467 sec_fe = prev->m_frontend;
1468 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1469 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1470 int state = sec_fe->m_state;
1471 // workaround to put the kernel frontend thread into idle state!
1472 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1474 sec_fe->closeFrontend(true);
1475 state = sec_fe->m_state;
1477 // sec_fe is closed... we must reopen it here..
1478 if (state == eDVBFrontend::stateClosed)
1486 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1488 long *sec_fe_data = sec_fe->m_data;
1489 // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1490 switch (m_sec_sequence.current()->cmd)
1492 case eSecCommand::SLEEP:
1493 delay = m_sec_sequence.current()++->msec;
1494 eDebugNoSimulate("[SEC] sleep %dms", delay);
1496 case eSecCommand::GOTO:
1497 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1498 ++m_sec_sequence.current();
1500 case eSecCommand::SET_VOLTAGE:
1502 int voltage = m_sec_sequence.current()++->voltage;
1503 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1504 sec_fe->setVoltage(voltage);
1507 case eSecCommand::IF_VOLTAGE_GOTO:
1509 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1510 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1512 ++m_sec_sequence.current();
1515 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1517 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1518 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1520 ++m_sec_sequence.current();
1523 case eSecCommand::IF_TONE_GOTO:
1525 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1526 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1528 ++m_sec_sequence.current();
1531 case eSecCommand::IF_NOT_TONE_GOTO:
1533 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1534 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1536 ++m_sec_sequence.current();
1539 case eSecCommand::SET_TONE:
1540 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1541 sec_fe->setTone(m_sec_sequence.current()++->tone);
1543 case eSecCommand::SEND_DISEQC:
1544 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1545 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1546 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1547 eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1548 if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
1549 eDebugNoSimulate("(DiSEqC reset)");
1550 else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
1551 eDebugNoSimulate("(DiSEqC peripherial power on)");
1553 eDebugNoSimulate("");
1554 ++m_sec_sequence.current();
1556 case eSecCommand::SEND_TONEBURST:
1557 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1558 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1560 case eSecCommand::SET_FRONTEND:
1561 eDebugNoSimulate("[SEC] setFrontend");
1563 ++m_sec_sequence.current();
1565 case eSecCommand::START_TUNE_TIMEOUT:
1568 m_timeout->start(m_sec_sequence.current()->timeout, 1);
1569 ++m_sec_sequence.current();
1572 case eSecCommand::SET_TIMEOUT:
1573 m_timeoutCount = m_sec_sequence.current()++->val;
1574 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1576 case eSecCommand::IF_TIMEOUT_GOTO:
1577 if (!m_timeoutCount)
1579 eDebugNoSimulate("[SEC] rotor timout");
1580 setSecSequencePos(m_sec_sequence.current()->steps);
1583 ++m_sec_sequence.current();
1585 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1587 int idx = m_sec_sequence.current()++->val;
1588 if ( idx == 0 || idx == 1 )
1590 m_idleInputpower[idx] = sec_fe->readInputpower();
1591 eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1594 eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1597 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1599 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1600 int idx = compare.val;
1601 if ( !m_simulate && (idx == 0 || idx == 1) )
1603 int idle = sec_fe->readInputpower();
1604 int diff = abs(idle-m_idleInputpower[idx]);
1607 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1608 setSecSequencePos(compare.steps);
1612 ++m_sec_sequence.current();
1615 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1617 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1620 setSecSequencePos(cmd.steps);
1624 int isLocked = readFrontendData(locked);
1625 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1626 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 50) || !cmd.lastSignal))
1629 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1632 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1633 cmd.lastSignal = signal;
1636 if (cmd.okcount > 4)
1638 eDebugNoSimulate("ok > 4 .. goto %d\n",cmd.steps);
1639 setSecSequencePos(cmd.steps);
1640 m_state = stateLock;
1641 m_stateChanged(this);
1650 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1652 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1654 if (!m_timeoutCount && m_retryCount > 0)
1659 ++m_sec_sequence.current();
1662 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1663 m_runningInputpower = sec_fe->readInputpower();
1664 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1665 ++m_sec_sequence.current();
1667 case eSecCommand::SET_ROTOR_MOVING:
1669 m_sec->setRotorMoving(true);
1670 ++m_sec_sequence.current();
1672 case eSecCommand::SET_ROTOR_STOPPED:
1674 m_sec->setRotorMoving(false);
1675 ++m_sec_sequence.current();
1677 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1679 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1682 setSecSequencePos(cmd.steps);
1685 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1686 const char *txt = cmd.direction ? "running" : "stopped";
1687 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1689 m_runningInputpower,
1692 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1693 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1696 eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1697 if ( cmd.okcount > 6 )
1699 eDebugNoSimulate("[SEC] rotor is %s", txt);
1700 if (setSecSequencePos(cmd.steps))
1706 eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1708 if (!m_timeoutCount && m_retryCount > 0)
1712 ++m_sec_sequence.current();
1715 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1716 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1717 setSecSequencePos(m_sec_sequence.current()->steps);
1719 ++m_sec_sequence.current();
1721 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1722 eDebugNoSimulate("[SEC] invalidate current switch params");
1723 sec_fe_data[CSW] = -1;
1724 sec_fe_data[UCSW] = -1;
1725 sec_fe_data[TONEBURST] = -1;
1726 ++m_sec_sequence.current();
1728 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1729 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1730 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1731 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1732 eDebugNoSimulate("[SEC] update current switch params");
1733 ++m_sec_sequence.current();
1735 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1736 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1737 sec_fe_data[ROTOR_CMD] = -1;
1738 sec_fe_data[ROTOR_POS] = -1;
1739 ++m_sec_sequence.current();
1741 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1742 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1743 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1744 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1745 ++m_sec_sequence.current();
1747 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1748 m_retryCount = m_sec_sequence.current()++->val;
1749 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1751 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1754 eDebugNoSimulate("[SEC] no more rotor retrys");
1755 setSecSequencePos(m_sec_sequence.current()->steps);
1758 ++m_sec_sequence.current();
1760 case eSecCommand::SET_POWER_LIMITING_MODE:
1765 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1766 FILE *f=fopen(proc_name, "w");
1767 if (f) // new interface exist?
1769 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1770 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1771 eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1773 eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1776 else if (sec_fe->m_need_rotor_workaround)
1779 int slotid = sec_fe->m_slotid;
1780 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1782 sprintf(dev, "/dev/i2c/%d", slotid);
1783 else if (slotid == 2)
1784 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1785 else if (slotid == 3)
1786 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1787 int fd = ::open(dev, O_RDWR);
1789 unsigned char data[2];
1790 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1791 if(::read(fd, data, 1) != 1)
1792 eDebugNoSimulate("[SEC] error read lnbp (%m)");
1793 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1795 data[0] |= 0x80; // enable static current limiting
1796 eDebugNoSimulate("[SEC] set static current limiting");
1800 data[0] &= ~0x80; // enable dynamic current limiting
1801 eDebugNoSimulate("[SEC] set dynamic current limiting");
1803 if(::write(fd, data, 1) != 1)
1804 eDebugNoSimulate("[SEC] error write lnbp (%m)");
1808 ++m_sec_sequence.current();
1812 eDebugNoSimulate("[SEC] unhandled sec command %d",
1813 ++m_sec_sequence.current()->cmd);
1814 ++m_sec_sequence.current();
1817 m_tuneTimer->start(delay,true);
1821 if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1825 void eDVBFrontend::setFrontend()
1829 eDebug("setting frontend %d", m_dvbid);
1832 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1834 perror("FE_SET_FRONTEND failed");
1840 RESULT eDVBFrontend::getFrontendType(int &t)
1848 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1853 eWarning("no SEC module active!");
1856 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1859 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1862 feparm.polarisation,
1866 feparm.orbital_position);
1867 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1868 switch (feparm.inversion)
1870 case eDVBFrontendParametersSatellite::Inversion::On:
1871 parm_inversion = INVERSION_ON;
1873 case eDVBFrontendParametersSatellite::Inversion::Off:
1874 parm_inversion = INVERSION_OFF;
1877 case eDVBFrontendParametersSatellite::Inversion::Unknown:
1878 parm_inversion = INVERSION_AUTO;
1881 if (feparm.system == eDVBFrontendParametersSatellite::System::DVB_S)
1884 case eDVBFrontendParametersSatellite::FEC::fNone:
1885 parm_u_qpsk_fec_inner = FEC_NONE;
1887 case eDVBFrontendParametersSatellite::FEC::f1_2:
1888 parm_u_qpsk_fec_inner = FEC_1_2;
1890 case eDVBFrontendParametersSatellite::FEC::f2_3:
1891 parm_u_qpsk_fec_inner = FEC_2_3;
1893 case eDVBFrontendParametersSatellite::FEC::f3_4:
1894 parm_u_qpsk_fec_inner = FEC_3_4;
1896 case eDVBFrontendParametersSatellite::FEC::f5_6:
1897 parm_u_qpsk_fec_inner = FEC_5_6;
1899 case eDVBFrontendParametersSatellite::FEC::f7_8:
1900 parm_u_qpsk_fec_inner = FEC_7_8;
1903 eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
1904 case eDVBFrontendParametersSatellite::FEC::fAuto:
1905 parm_u_qpsk_fec_inner = FEC_AUTO;
1908 #if HAVE_DVB_API_VERSION >= 3
1913 case eDVBFrontendParametersSatellite::FEC::f1_2:
1914 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1916 case eDVBFrontendParametersSatellite::FEC::f2_3:
1917 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1919 case eDVBFrontendParametersSatellite::FEC::f3_4:
1920 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1922 case eDVBFrontendParametersSatellite::FEC::f3_5:
1923 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1925 case eDVBFrontendParametersSatellite::FEC::f4_5:
1926 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1928 case eDVBFrontendParametersSatellite::FEC::f5_6:
1929 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1931 case eDVBFrontendParametersSatellite::FEC::f7_8:
1932 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1934 case eDVBFrontendParametersSatellite::FEC::f8_9:
1935 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1937 case eDVBFrontendParametersSatellite::FEC::f9_10:
1938 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1941 eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
1944 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1945 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1946 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK) {
1947 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1948 // 8PSK fec driver values are decimal 9 bigger
1952 // FIXME !!! get frequency range from tuner
1953 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1955 eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1958 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
1963 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1965 #if HAVE_DVB_API_VERSION < 3
1966 parm_frequency = feparm.frequency;
1968 parm_frequency = feparm.frequency * 1000;
1970 parm_u_qam_symbol_rate = feparm.symbol_rate;
1971 switch (feparm.modulation)
1973 case eDVBFrontendParametersCable::Modulation::QAM16:
1974 parm_u_qam_modulation = QAM_16;
1976 case eDVBFrontendParametersCable::Modulation::QAM32:
1977 parm_u_qam_modulation = QAM_32;
1979 case eDVBFrontendParametersCable::Modulation::QAM64:
1980 parm_u_qam_modulation = QAM_64;
1982 case eDVBFrontendParametersCable::Modulation::QAM128:
1983 parm_u_qam_modulation = QAM_128;
1985 case eDVBFrontendParametersCable::Modulation::QAM256:
1986 parm_u_qam_modulation = QAM_256;
1989 case eDVBFrontendParametersCable::Modulation::Auto:
1990 parm_u_qam_modulation = QAM_AUTO;
1993 switch (feparm.inversion)
1995 case eDVBFrontendParametersCable::Inversion::On:
1996 parm_inversion = INVERSION_ON;
1998 case eDVBFrontendParametersCable::Inversion::Off:
1999 parm_inversion = INVERSION_OFF;
2002 case eDVBFrontendParametersCable::Inversion::Unknown:
2003 parm_inversion = INVERSION_AUTO;
2006 switch (feparm.fec_inner)
2008 case eDVBFrontendParametersCable::FEC::fNone:
2009 parm_u_qam_fec_inner = FEC_NONE;
2011 case eDVBFrontendParametersCable::FEC::f1_2:
2012 parm_u_qam_fec_inner = FEC_1_2;
2014 case eDVBFrontendParametersCable::FEC::f2_3:
2015 parm_u_qam_fec_inner = FEC_2_3;
2017 case eDVBFrontendParametersCable::FEC::f3_4:
2018 parm_u_qam_fec_inner = FEC_3_4;
2020 case eDVBFrontendParametersCable::FEC::f5_6:
2021 parm_u_qam_fec_inner = FEC_5_6;
2023 case eDVBFrontendParametersCable::FEC::f7_8:
2024 parm_u_qam_fec_inner = FEC_7_8;
2026 #if HAVE_DVB_API_VERSION >= 3
2027 case eDVBFrontendParametersCable::FEC::f8_9:
2028 parm_u_qam_fec_inner = FEC_8_9;
2032 case eDVBFrontendParametersCable::FEC::fAuto:
2033 parm_u_qam_fec_inner = FEC_AUTO;
2036 eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
2037 parm_frequency/1000,
2038 parm_u_qam_symbol_rate,
2039 parm_u_qam_fec_inner,
2040 parm_u_qam_modulation,
2045 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
2047 parm_frequency = feparm.frequency;
2049 switch (feparm.bandwidth)
2051 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
2052 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
2054 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
2055 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
2057 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
2058 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
2061 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
2062 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
2065 switch (feparm.code_rate_LP)
2067 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
2068 parm_u_ofdm_code_rate_LP = FEC_1_2;
2070 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
2071 parm_u_ofdm_code_rate_LP = FEC_2_3;
2073 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
2074 parm_u_ofdm_code_rate_LP = FEC_3_4;
2076 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
2077 parm_u_ofdm_code_rate_LP = FEC_5_6;
2079 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
2080 parm_u_ofdm_code_rate_LP = FEC_7_8;
2083 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
2084 parm_u_ofdm_code_rate_LP = FEC_AUTO;
2087 switch (feparm.code_rate_HP)
2089 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
2090 parm_u_ofdm_code_rate_HP = FEC_1_2;
2092 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
2093 parm_u_ofdm_code_rate_HP = FEC_2_3;
2095 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
2096 parm_u_ofdm_code_rate_HP = FEC_3_4;
2098 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
2099 parm_u_ofdm_code_rate_HP = FEC_5_6;
2101 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
2102 parm_u_ofdm_code_rate_HP = FEC_7_8;
2105 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
2106 parm_u_ofdm_code_rate_HP = FEC_AUTO;
2109 switch (feparm.modulation)
2111 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
2112 parm_u_ofdm_constellation = QPSK;
2114 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
2115 parm_u_ofdm_constellation = QAM_16;
2117 case eDVBFrontendParametersTerrestrial::Modulation::QAM64:
2118 parm_u_ofdm_constellation = QAM_64;
2121 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
2122 parm_u_ofdm_constellation = QAM_AUTO;
2125 switch (feparm.transmission_mode)
2127 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
2128 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2130 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
2131 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2134 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
2135 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2138 switch (feparm.guard_interval)
2140 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32:
2141 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2143 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16:
2144 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2146 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8:
2147 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2149 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4:
2150 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2153 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto:
2154 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2157 switch (feparm.hierarchy)
2159 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone:
2160 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2162 case eDVBFrontendParametersTerrestrial::Hierarchy::H1:
2163 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2165 case eDVBFrontendParametersTerrestrial::Hierarchy::H2:
2166 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2168 case eDVBFrontendParametersTerrestrial::Hierarchy::H4:
2169 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2172 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto:
2173 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2176 switch (feparm.inversion)
2178 case eDVBFrontendParametersTerrestrial::Inversion::On:
2179 parm_inversion = INVERSION_ON;
2181 case eDVBFrontendParametersTerrestrial::Inversion::Off:
2182 parm_inversion = INVERSION_OFF;
2185 case eDVBFrontendParametersTerrestrial::Inversion::Unknown:
2186 parm_inversion = INVERSION_AUTO;
2192 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2194 unsigned int timeout = 5000;
2195 eDebugNoSimulate("(%d)tune", m_dvbid);
2201 if (!m_sn && !m_simulate)
2203 eDebug("no frontend device opened... do not try to tune !!!");
2217 m_sec_sequence.clear();
2219 where.calcLockTimeout(timeout);
2225 eDVBFrontendParametersSatellite feparm;
2226 if (where.getDVBS(feparm))
2228 eDebug("no dvbs data!");
2233 m_sec->setRotorMoving(false);
2234 res=prepare_sat(feparm, timeout);
2242 eDVBFrontendParametersCable feparm;
2243 if (where.getDVBC(feparm))
2248 res=prepare_cable(feparm);
2252 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2253 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2258 eDVBFrontendParametersTerrestrial feparm;
2259 if (where.getDVBT(feparm))
2261 eDebug("no -T data");
2265 res=prepare_terrestrial(feparm);
2269 std::string enable_5V;
2270 char configStr[255];
2271 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2272 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2273 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2274 if (enable_5V == "True")
2275 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2277 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2278 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2284 m_sec_sequence.current() = m_sec_sequence.begin();
2288 m_tuneTimer->start(0,true);
2289 if (m_state != stateTuning)
2292 m_state = stateTuning;
2293 m_stateChanged(this);
2302 m_tuneTimer->stop();
2306 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2308 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2312 RESULT eDVBFrontend::setVoltage(int voltage)
2314 if (m_type == feCable)
2316 #if HAVE_DVB_API_VERSION < 3
2319 bool increased=false;
2320 fe_sec_voltage_t vlt;
2322 m_data[CUR_VOLTAGE]=voltage;
2326 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2327 vlt = SEC_VOLTAGE_OFF;
2330 #if HAVE_DVB_API_VERSION < 3
2331 vlt = SEC_VOLTAGE_13_5;
2337 vlt = SEC_VOLTAGE_13;
2340 #if HAVE_DVB_API_VERSION < 3
2341 vlt = SEC_VOLTAGE_18_5;
2347 vlt = SEC_VOLTAGE_18;
2354 #if HAVE_DVB_API_VERSION < 3
2355 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2357 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2358 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2359 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2363 RESULT eDVBFrontend::getState(int &state)
2369 RESULT eDVBFrontend::setTone(int t)
2371 if (m_type != feSatellite)
2373 #if HAVE_DVB_API_VERSION < 3
2376 fe_sec_tone_mode_t tone;
2385 tone = SEC_TONE_OFF;
2392 #if HAVE_DVB_API_VERSION < 3
2393 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2395 return ::ioctl(m_fd, FE_SET_TONE, tone);
2399 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2400 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2403 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2407 #if HAVE_DVB_API_VERSION < 3
2408 struct secCommand cmd;
2409 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2410 cmd.u.diseqc.cmdtype = diseqc.data[0];
2411 cmd.u.diseqc.addr = diseqc.data[1];
2412 cmd.u.diseqc.cmd = diseqc.data[2];
2413 cmd.u.diseqc.numParams = diseqc.len-3;
2414 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2415 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2417 struct dvb_diseqc_master_cmd cmd;
2418 memcpy(cmd.msg, diseqc.data, diseqc.len);
2419 cmd.msg_len = diseqc.len;
2420 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2426 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2427 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2429 RESULT eDVBFrontend::sendToneburst(int burst)
2433 #if HAVE_DVB_API_VERSION < 3
2434 secMiniCmd cmd = SEC_MINI_NONE;
2436 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2438 if ( burst == eDVBSatelliteDiseqcParameters::A )
2440 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2442 #if HAVE_DVB_API_VERSION < 3
2443 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2446 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2452 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2458 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2460 m_sec_sequence = list;
2464 RESULT eDVBFrontend::getData(int num, long &data)
2466 if ( num < NUM_DATA_ENTRIES )
2474 RESULT eDVBFrontend::setData(int num, long val)
2476 if ( num < NUM_DATA_ENTRIES )
2484 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2487 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2489 if (m_type == eDVBFrontend::feSatellite)
2492 eDVBFrontendParametersSatellite sat_parm;
2493 int ret = feparm->getDVBS(sat_parm);
2495 if (sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S2 && !m_can_handle_dvbs2)
2497 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2498 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S && m_can_handle_dvbs2)
2502 else if (m_type == eDVBFrontend::feCable)
2503 return 2; // more prio for cable frontends
2504 else if (m_type == eDVBFrontend::feTerrestrial)
2509 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2511 ePyObject Id, Descr, Enabled, IsDVBS2;
2512 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4)
2514 Id = PyTuple_GET_ITEM(obj, 0);
2515 Descr = PyTuple_GET_ITEM(obj, 1);
2516 Enabled = PyTuple_GET_ITEM(obj, 2);
2517 IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2518 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2))
2520 strcpy(m_description, PyString_AS_STRING(Descr));
2521 m_slotid = PyInt_AsLong(Id);
2522 m_enabled = Enabled == Py_True;
2523 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2524 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2525 !!strstr(m_description, "Alps BSBE2") ||
2526 !!strstr(m_description, "Alps -S") ||
2527 !!strstr(m_description, "BCM4501");
2528 m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2529 eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2530 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2533 PyErr_SetString(PyExc_StandardError,
2534 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");