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);
783 ret -= 150; // -1.5db for latest bcm4501 firmware..
785 else if (strstr(m_description, "Alps BSBE1 C01A") ||
786 !strcmp(m_description, "Alps -S(STV0288)"))
790 else if (snr == 0xFFFF) // i think this should not happen
794 enum { REALVAL, REGVAL };
795 const long CN_lookup[31][2] = {
796 {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
797 {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
798 {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
799 {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
800 {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
801 {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
804 int add=strchr(m_description, '.') ? 0xA250 : 0xA100;
805 long regval = 0xFFFF - ((snr / 3) + add), // revert some dvb api calulations to get the real register value
809 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
814 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[i][REGVAL]))
819 ret = (((regval - CN_lookup[Imin][REGVAL])
820 * (CN_lookup[Imax][REALVAL] - CN_lookup[Imin][REALVAL])
821 / (CN_lookup[Imax][REGVAL] - CN_lookup[Imin][REGVAL]))
822 + CN_lookup[Imin][REALVAL]) * 10;
828 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
829 !strcmp(m_description, "Alps -S") ||
830 !strcmp(m_description, "Philips -S") ||
831 !strcmp(m_description, "LG -S") )
833 ret = (int)((snr-39075)/17.647);
834 } else if (!strcmp(m_description, "Alps BSBE2"))
836 ret = (int)((snr >> 7) * 10);
837 } else if (!strcmp(m_description, "Philips CU1216Mk3"))
839 int mse = (~snr) & 0xFF;
840 switch (parm_u_qam_modulation) {
841 case QAM_16: ret = fe_udiv(1950000, (32 * mse) + 138) + 1000; break;
842 case QAM_32: ret = fe_udiv(2150000, (40 * mse) + 500) + 1350; break;
843 case QAM_64: ret = fe_udiv(2100000, (40 * mse) + 500) + 1250; break;
844 case QAM_128: ret = fe_udiv(1850000, (38 * mse) + 400) + 1380; break;
845 case QAM_256: ret = fe_udiv(1800000, (100 * mse) + 40) + 2030; break;
848 } else if (!strcmp(m_description, "Philips TU1216"))
850 snr = 0xFF - (snr & 0xFF);
852 ret = 10 * (int)(-100 * (log10(snr) - log10(255)));
855 if (type == signalQuality)
857 if (ret == 0x12345678) // no snr db calculation avail.. return untouched snr value..
861 case feSatellite: // we assume a max of 16.0db here
862 return ret >= 1600 ? 65536 : ret * 65536 / 1600;
863 case feCable: // we assume a max of 42db here
864 return ret >= 4200 ? 65536 : ret * 65536 / 4200;
865 case feTerrestrial: // we assume a max of 24db here
866 return ret >= 2400 ? 65536 : ret * 65536 / 2400;
870 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
878 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
879 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
885 #if HAVE_DVB_API_VERSION < 3
886 FrontendStatus status=0;
892 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
893 eDebug("FE_READ_STATUS failed (%m)");
894 return !!(status&FE_HAS_LOCK);
900 #if HAVE_DVB_API_VERSION < 3
901 FrontendStatus status=0;
907 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
908 eDebug("FE_READ_STATUS failed (%m)");
909 return !!(status&FE_HAS_SYNC);
919 void PutToDict(ePyObject &dict, const char*key, long value)
921 ePyObject item = PyInt_FromLong(value);
924 if (PyDict_SetItemString(dict, key, item))
925 eDebug("put %s to dict failed", key);
929 eDebug("could not create PyObject for %s", key);
932 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
936 if (PyDict_SetItemString(dict, key, item))
937 eDebug("put %s to dict failed", key);
941 eDebug("invalid PyObject for %s", key);
944 void PutToDict(ePyObject &dict, const char*key, const char *value)
946 ePyObject item = PyString_FromString(value);
949 if (PyDict_SetItemString(dict, key, item))
950 eDebug("put %s to dict failed", key);
954 eDebug("could not create PyObject for %s", key);
957 void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, eDVBFrontend *fe)
961 fe->getData(eDVBFrontend::FREQ_OFFSET, freq_offset);
962 int frequency = parm_frequency + freq_offset;
963 PutToDict(dict, "frequency", frequency);
964 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
965 switch(parm_u_qpsk_fec_inner)
988 #if HAVE_DVB_API_VERSION >=3
989 case FEC_S2_8PSK_1_2:
990 case FEC_S2_QPSK_1_2:
993 case FEC_S2_8PSK_2_3:
994 case FEC_S2_QPSK_2_3:
997 case FEC_S2_8PSK_3_4:
998 case FEC_S2_QPSK_3_4:
1001 case FEC_S2_8PSK_5_6:
1002 case FEC_S2_QPSK_5_6:
1005 case FEC_S2_8PSK_7_8:
1006 case FEC_S2_QPSK_7_8:
1009 case FEC_S2_8PSK_8_9:
1010 case FEC_S2_QPSK_8_9:
1013 case FEC_S2_8PSK_3_5:
1014 case FEC_S2_QPSK_3_5:
1017 case FEC_S2_8PSK_4_5:
1018 case FEC_S2_QPSK_4_5:
1021 case FEC_S2_8PSK_9_10:
1022 case FEC_S2_QPSK_9_10:
1027 PutToDict(dict, "fec_inner", tmp);
1028 #if HAVE_DVB_API_VERSION >=3
1029 PutToDict(dict, "modulation",
1030 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ? "8PSK": "QPSK" );
1031 if (parm_u_qpsk_fec_inner > FEC_AUTO)
1033 switch(parm_inversion & 0xc)
1035 default: // unknown rolloff
1037 tmp = "ROLLOFF_0_35";
1040 tmp = "ROLLOFF_0_25";
1043 tmp = "ROLLOFF_0_20";
1046 PutToDict(dict, "rolloff", tmp);
1047 switch(parm_inversion & 0x30)
1049 case 0: // pilot off
1052 case 0x10: // pilot on
1055 case 0x20: // pilot auto
1059 PutToDict(dict, "pilot", tmp);
1065 PutToDict(dict, "modulation", "QPSK" );
1068 PutToDict(dict, "system", tmp);
1071 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1074 #if HAVE_DVB_API_VERSION < 3
1075 PutToDict(dict, "frequency", parm_frequency);
1077 PutToDict(dict, "frequency", parm_frequency/1000);
1079 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1080 switch(parm_u_qam_fec_inner)
1100 #if HAVE_DVB_API_VERSION >= 3
1110 PutToDict(dict, "fec_inner", tmp);
1111 switch(parm_u_qam_modulation)
1133 PutToDict(dict, "modulation", tmp);
1136 void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1139 PutToDict(dict, "frequency", parm_frequency);
1140 switch (parm_u_ofdm_bandwidth)
1142 case BANDWIDTH_8_MHZ:
1143 tmp = "BANDWIDTH_8_MHZ";
1145 case BANDWIDTH_7_MHZ:
1146 tmp = "BANDWIDTH_7_MHZ";
1148 case BANDWIDTH_6_MHZ:
1149 tmp = "BANDWIDTH_6_MHZ";
1152 case BANDWIDTH_AUTO:
1153 tmp = "BANDWIDTH_AUTO";
1156 PutToDict(dict, "bandwidth", tmp);
1157 switch (parm_u_ofdm_code_rate_LP)
1179 PutToDict(dict, "code_rate_lp", tmp);
1180 switch (parm_u_ofdm_code_rate_HP)
1202 PutToDict(dict, "code_rate_hp", tmp);
1203 switch (parm_u_ofdm_constellation)
1219 PutToDict(dict, "constellation", tmp);
1220 switch (parm_u_ofdm_transmission_mode)
1222 case TRANSMISSION_MODE_2K:
1223 tmp = "TRANSMISSION_MODE_2K";
1225 case TRANSMISSION_MODE_8K:
1226 tmp = "TRANSMISSION_MODE_8K";
1229 case TRANSMISSION_MODE_AUTO:
1230 tmp = "TRANSMISSION_MODE_AUTO";
1233 PutToDict(dict, "transmission_mode", tmp);
1234 switch (parm_u_ofdm_guard_interval)
1236 case GUARD_INTERVAL_1_32:
1237 tmp = "GUARD_INTERVAL_1_32";
1239 case GUARD_INTERVAL_1_16:
1240 tmp = "GUARD_INTERVAL_1_16";
1242 case GUARD_INTERVAL_1_8:
1243 tmp = "GUARD_INTERVAL_1_8";
1245 case GUARD_INTERVAL_1_4:
1246 tmp = "GUARD_INTERVAL_1_4";
1249 case GUARD_INTERVAL_AUTO:
1250 tmp = "GUARD_INTERVAL_AUTO";
1253 PutToDict(dict, "guard_interval", tmp);
1254 switch (parm_u_ofdm_hierarchy_information)
1256 case HIERARCHY_NONE:
1257 tmp = "HIERARCHY_NONE";
1260 tmp = "HIERARCHY_1";
1263 tmp = "HIERARCHY_2";
1266 tmp = "HIERARCHY_4";
1269 case HIERARCHY_AUTO:
1270 tmp = "HIERARCHY_AUTO";
1273 PutToDict(dict, "hierarchy_information", tmp);
1276 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1278 if (dest && PyDict_Check(dest))
1280 const char *tmp = "UNKNOWN";
1301 PutToDict(dest, "tuner_state", tmp);
1302 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1303 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1304 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1305 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1306 int sigQualitydB = readFrontendData(signalQualitydB);
1307 if (sigQualitydB == 0x12345678) // not support yet
1309 ePyObject obj=Py_None;
1311 PutToDict(dest, "tuner_signal_quality_db", obj);
1314 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1315 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1319 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1321 if (dest && PyDict_Check(dest))
1329 FRONTENDPARAMETERS front;
1330 if (m_fd == -1 && !original)
1332 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1334 eDebug("FE_GET_FRONTEND failed (%m)");
1338 const FRONTENDPARAMETERS &parm = original || m_simulate ? this->parm : front;
1339 const char *tmp = "INVERSION_AUTO";
1340 switch(parm_inversion & 3)
1343 tmp = "INVERSION_ON";
1346 tmp = "INVERSION_OFF";
1352 PutToDict(dest, "inversion", tmp);
1357 fillDictWithSatelliteData(dest, original?parm:front, this);
1360 fillDictWithCableData(dest, original?parm:front);
1363 fillDictWithTerrestrialData(dest, original?parm:front);
1374 void eDVBFrontend::getFrontendData(ePyObject dest)
1376 if (dest && PyDict_Check(dest))
1379 PutToDict(dest, "tuner_number", m_slotid);
1395 PutToDict(dest, "tuner_type", tmp);
1399 #ifndef FP_IOCTL_GET_ID
1400 #define FP_IOCTL_GET_ID 0
1402 int eDVBFrontend::readInputpower()
1406 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1408 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1409 FILE *f=fopen(proc_name, "r");
1412 if (fscanf(f, "%d", &power) != 1)
1413 eDebug("read %s failed!! (%m)", proc_name);
1415 eDebug("%s is %d\n", proc_name, power);
1420 // open front prozessor
1421 int fp=::open("/dev/dbox/fp0", O_RDWR);
1424 eDebug("couldn't open fp");
1427 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1428 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1430 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1439 bool eDVBFrontend::setSecSequencePos(int steps)
1441 eDebugNoSimulate("set sequence pos %d", steps);
1446 if (m_sec_sequence.current() != m_sec_sequence.end())
1447 ++m_sec_sequence.current();
1452 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1453 --m_sec_sequence.current();
1459 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1462 eDVBFrontend *sec_fe = this;
1463 eDVBRegisteredFrontend *regFE = 0;
1464 long tmp = m_data[LINKED_PREV_PTR];
1467 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1468 sec_fe = prev->m_frontend;
1469 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1470 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1471 int state = sec_fe->m_state;
1472 // workaround to put the kernel frontend thread into idle state!
1473 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1475 sec_fe->closeFrontend(true);
1476 state = sec_fe->m_state;
1478 // sec_fe is closed... we must reopen it here..
1479 if (state == eDVBFrontend::stateClosed)
1487 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1489 long *sec_fe_data = sec_fe->m_data;
1490 // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1491 switch (m_sec_sequence.current()->cmd)
1493 case eSecCommand::SLEEP:
1494 delay = m_sec_sequence.current()++->msec;
1495 eDebugNoSimulate("[SEC] sleep %dms", delay);
1497 case eSecCommand::GOTO:
1498 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1499 ++m_sec_sequence.current();
1501 case eSecCommand::SET_VOLTAGE:
1503 int voltage = m_sec_sequence.current()++->voltage;
1504 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1505 sec_fe->setVoltage(voltage);
1508 case eSecCommand::IF_VOLTAGE_GOTO:
1510 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1511 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1513 ++m_sec_sequence.current();
1516 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1518 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1519 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1521 ++m_sec_sequence.current();
1524 case eSecCommand::IF_TONE_GOTO:
1526 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1527 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1529 ++m_sec_sequence.current();
1532 case eSecCommand::IF_NOT_TONE_GOTO:
1534 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1535 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1537 ++m_sec_sequence.current();
1540 case eSecCommand::SET_TONE:
1541 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1542 sec_fe->setTone(m_sec_sequence.current()++->tone);
1544 case eSecCommand::SEND_DISEQC:
1545 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1546 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1547 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1548 eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1549 if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
1550 eDebugNoSimulate("(DiSEqC reset)");
1551 else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
1552 eDebugNoSimulate("(DiSEqC peripherial power on)");
1554 eDebugNoSimulate("");
1555 ++m_sec_sequence.current();
1557 case eSecCommand::SEND_TONEBURST:
1558 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1559 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1561 case eSecCommand::SET_FRONTEND:
1562 eDebugNoSimulate("[SEC] setFrontend");
1564 ++m_sec_sequence.current();
1566 case eSecCommand::START_TUNE_TIMEOUT:
1569 m_timeout->start(m_sec_sequence.current()->timeout, 1);
1570 ++m_sec_sequence.current();
1573 case eSecCommand::SET_TIMEOUT:
1574 m_timeoutCount = m_sec_sequence.current()++->val;
1575 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1577 case eSecCommand::IF_TIMEOUT_GOTO:
1578 if (!m_timeoutCount)
1580 eDebugNoSimulate("[SEC] rotor timout");
1581 setSecSequencePos(m_sec_sequence.current()->steps);
1584 ++m_sec_sequence.current();
1586 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1588 int idx = m_sec_sequence.current()++->val;
1589 if ( idx == 0 || idx == 1 )
1591 m_idleInputpower[idx] = sec_fe->readInputpower();
1592 eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1595 eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1598 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1600 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1601 int idx = compare.val;
1602 if ( !m_simulate && (idx == 0 || idx == 1) )
1604 int idle = sec_fe->readInputpower();
1605 int diff = abs(idle-m_idleInputpower[idx]);
1608 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1609 setSecSequencePos(compare.steps);
1613 ++m_sec_sequence.current();
1616 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1618 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1621 setSecSequencePos(cmd.steps);
1625 int isLocked = readFrontendData(locked);
1626 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1627 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 50) || !cmd.lastSignal))
1630 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1633 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1634 cmd.lastSignal = signal;
1637 if (cmd.okcount > 4)
1639 eDebugNoSimulate("ok > 4 .. goto %d\n",cmd.steps);
1640 setSecSequencePos(cmd.steps);
1641 m_state = stateLock;
1642 m_stateChanged(this);
1651 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1653 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1655 if (!m_timeoutCount && m_retryCount > 0)
1660 ++m_sec_sequence.current();
1663 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1664 m_runningInputpower = sec_fe->readInputpower();
1665 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1666 ++m_sec_sequence.current();
1668 case eSecCommand::SET_ROTOR_MOVING:
1670 m_sec->setRotorMoving(true);
1671 ++m_sec_sequence.current();
1673 case eSecCommand::SET_ROTOR_STOPPED:
1675 m_sec->setRotorMoving(false);
1676 ++m_sec_sequence.current();
1678 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1680 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1683 setSecSequencePos(cmd.steps);
1686 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1687 const char *txt = cmd.direction ? "running" : "stopped";
1688 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1690 m_runningInputpower,
1693 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1694 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1697 eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1698 if ( cmd.okcount > 6 )
1700 eDebugNoSimulate("[SEC] rotor is %s", txt);
1701 if (setSecSequencePos(cmd.steps))
1707 eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1709 if (!m_timeoutCount && m_retryCount > 0)
1713 ++m_sec_sequence.current();
1716 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1717 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1718 setSecSequencePos(m_sec_sequence.current()->steps);
1720 ++m_sec_sequence.current();
1722 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1723 eDebugNoSimulate("[SEC] invalidate current switch params");
1724 sec_fe_data[CSW] = -1;
1725 sec_fe_data[UCSW] = -1;
1726 sec_fe_data[TONEBURST] = -1;
1727 ++m_sec_sequence.current();
1729 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1730 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1731 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1732 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1733 eDebugNoSimulate("[SEC] update current switch params");
1734 ++m_sec_sequence.current();
1736 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1737 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1738 sec_fe_data[ROTOR_CMD] = -1;
1739 sec_fe_data[ROTOR_POS] = -1;
1740 ++m_sec_sequence.current();
1742 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1743 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1744 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1745 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1746 ++m_sec_sequence.current();
1748 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1749 m_retryCount = m_sec_sequence.current()++->val;
1750 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1752 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1755 eDebugNoSimulate("[SEC] no more rotor retrys");
1756 setSecSequencePos(m_sec_sequence.current()->steps);
1759 ++m_sec_sequence.current();
1761 case eSecCommand::SET_POWER_LIMITING_MODE:
1766 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1767 FILE *f=fopen(proc_name, "w");
1768 if (f) // new interface exist?
1770 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1771 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1772 eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1774 eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1777 else if (sec_fe->m_need_rotor_workaround)
1780 int slotid = sec_fe->m_slotid;
1781 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1783 sprintf(dev, "/dev/i2c/%d", slotid);
1784 else if (slotid == 2)
1785 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1786 else if (slotid == 3)
1787 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1788 int fd = ::open(dev, O_RDWR);
1790 unsigned char data[2];
1791 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1792 if(::read(fd, data, 1) != 1)
1793 eDebugNoSimulate("[SEC] error read lnbp (%m)");
1794 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1796 data[0] |= 0x80; // enable static current limiting
1797 eDebugNoSimulate("[SEC] set static current limiting");
1801 data[0] &= ~0x80; // enable dynamic current limiting
1802 eDebugNoSimulate("[SEC] set dynamic current limiting");
1804 if(::write(fd, data, 1) != 1)
1805 eDebugNoSimulate("[SEC] error write lnbp (%m)");
1809 ++m_sec_sequence.current();
1813 eDebugNoSimulate("[SEC] unhandled sec command %d",
1814 ++m_sec_sequence.current()->cmd);
1815 ++m_sec_sequence.current();
1818 m_tuneTimer->start(delay,true);
1822 if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1826 void eDVBFrontend::setFrontend()
1830 eDebug("setting frontend %d", m_dvbid);
1833 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1835 perror("FE_SET_FRONTEND failed");
1841 RESULT eDVBFrontend::getFrontendType(int &t)
1849 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1854 eWarning("no SEC module active!");
1857 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1860 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1863 feparm.polarisation,
1867 feparm.orbital_position);
1868 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1869 switch (feparm.inversion)
1871 case eDVBFrontendParametersSatellite::Inversion::On:
1872 parm_inversion = INVERSION_ON;
1874 case eDVBFrontendParametersSatellite::Inversion::Off:
1875 parm_inversion = INVERSION_OFF;
1878 case eDVBFrontendParametersSatellite::Inversion::Unknown:
1879 parm_inversion = INVERSION_AUTO;
1882 if (feparm.system == eDVBFrontendParametersSatellite::System::DVB_S)
1885 case eDVBFrontendParametersSatellite::FEC::fNone:
1886 parm_u_qpsk_fec_inner = FEC_NONE;
1888 case eDVBFrontendParametersSatellite::FEC::f1_2:
1889 parm_u_qpsk_fec_inner = FEC_1_2;
1891 case eDVBFrontendParametersSatellite::FEC::f2_3:
1892 parm_u_qpsk_fec_inner = FEC_2_3;
1894 case eDVBFrontendParametersSatellite::FEC::f3_4:
1895 parm_u_qpsk_fec_inner = FEC_3_4;
1897 case eDVBFrontendParametersSatellite::FEC::f5_6:
1898 parm_u_qpsk_fec_inner = FEC_5_6;
1900 case eDVBFrontendParametersSatellite::FEC::f7_8:
1901 parm_u_qpsk_fec_inner = FEC_7_8;
1904 eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
1905 case eDVBFrontendParametersSatellite::FEC::fAuto:
1906 parm_u_qpsk_fec_inner = FEC_AUTO;
1909 #if HAVE_DVB_API_VERSION >= 3
1914 case eDVBFrontendParametersSatellite::FEC::f1_2:
1915 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1917 case eDVBFrontendParametersSatellite::FEC::f2_3:
1918 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1920 case eDVBFrontendParametersSatellite::FEC::f3_4:
1921 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1923 case eDVBFrontendParametersSatellite::FEC::f3_5:
1924 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1926 case eDVBFrontendParametersSatellite::FEC::f4_5:
1927 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1929 case eDVBFrontendParametersSatellite::FEC::f5_6:
1930 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1932 case eDVBFrontendParametersSatellite::FEC::f7_8:
1933 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1935 case eDVBFrontendParametersSatellite::FEC::f8_9:
1936 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1938 case eDVBFrontendParametersSatellite::FEC::f9_10:
1939 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1942 eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
1945 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1946 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1947 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK) {
1948 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1949 // 8PSK fec driver values are decimal 9 bigger
1953 // FIXME !!! get frequency range from tuner
1954 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1956 eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1959 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
1964 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1966 #if HAVE_DVB_API_VERSION < 3
1967 parm_frequency = feparm.frequency;
1969 parm_frequency = feparm.frequency * 1000;
1971 parm_u_qam_symbol_rate = feparm.symbol_rate;
1972 switch (feparm.modulation)
1974 case eDVBFrontendParametersCable::Modulation::QAM16:
1975 parm_u_qam_modulation = QAM_16;
1977 case eDVBFrontendParametersCable::Modulation::QAM32:
1978 parm_u_qam_modulation = QAM_32;
1980 case eDVBFrontendParametersCable::Modulation::QAM64:
1981 parm_u_qam_modulation = QAM_64;
1983 case eDVBFrontendParametersCable::Modulation::QAM128:
1984 parm_u_qam_modulation = QAM_128;
1986 case eDVBFrontendParametersCable::Modulation::QAM256:
1987 parm_u_qam_modulation = QAM_256;
1990 case eDVBFrontendParametersCable::Modulation::Auto:
1991 parm_u_qam_modulation = QAM_AUTO;
1994 switch (feparm.inversion)
1996 case eDVBFrontendParametersCable::Inversion::On:
1997 parm_inversion = INVERSION_ON;
1999 case eDVBFrontendParametersCable::Inversion::Off:
2000 parm_inversion = INVERSION_OFF;
2003 case eDVBFrontendParametersCable::Inversion::Unknown:
2004 parm_inversion = INVERSION_AUTO;
2007 switch (feparm.fec_inner)
2009 case eDVBFrontendParametersCable::FEC::fNone:
2010 parm_u_qam_fec_inner = FEC_NONE;
2012 case eDVBFrontendParametersCable::FEC::f1_2:
2013 parm_u_qam_fec_inner = FEC_1_2;
2015 case eDVBFrontendParametersCable::FEC::f2_3:
2016 parm_u_qam_fec_inner = FEC_2_3;
2018 case eDVBFrontendParametersCable::FEC::f3_4:
2019 parm_u_qam_fec_inner = FEC_3_4;
2021 case eDVBFrontendParametersCable::FEC::f5_6:
2022 parm_u_qam_fec_inner = FEC_5_6;
2024 case eDVBFrontendParametersCable::FEC::f7_8:
2025 parm_u_qam_fec_inner = FEC_7_8;
2027 #if HAVE_DVB_API_VERSION >= 3
2028 case eDVBFrontendParametersCable::FEC::f8_9:
2029 parm_u_qam_fec_inner = FEC_8_9;
2033 case eDVBFrontendParametersCable::FEC::fAuto:
2034 parm_u_qam_fec_inner = FEC_AUTO;
2037 eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
2038 parm_frequency/1000,
2039 parm_u_qam_symbol_rate,
2040 parm_u_qam_fec_inner,
2041 parm_u_qam_modulation,
2046 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
2048 parm_frequency = feparm.frequency;
2050 switch (feparm.bandwidth)
2052 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
2053 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
2055 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
2056 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
2058 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
2059 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
2062 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
2063 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
2066 switch (feparm.code_rate_LP)
2068 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
2069 parm_u_ofdm_code_rate_LP = FEC_1_2;
2071 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
2072 parm_u_ofdm_code_rate_LP = FEC_2_3;
2074 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
2075 parm_u_ofdm_code_rate_LP = FEC_3_4;
2077 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
2078 parm_u_ofdm_code_rate_LP = FEC_5_6;
2080 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
2081 parm_u_ofdm_code_rate_LP = FEC_7_8;
2084 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
2085 parm_u_ofdm_code_rate_LP = FEC_AUTO;
2088 switch (feparm.code_rate_HP)
2090 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
2091 parm_u_ofdm_code_rate_HP = FEC_1_2;
2093 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
2094 parm_u_ofdm_code_rate_HP = FEC_2_3;
2096 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
2097 parm_u_ofdm_code_rate_HP = FEC_3_4;
2099 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
2100 parm_u_ofdm_code_rate_HP = FEC_5_6;
2102 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
2103 parm_u_ofdm_code_rate_HP = FEC_7_8;
2106 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
2107 parm_u_ofdm_code_rate_HP = FEC_AUTO;
2110 switch (feparm.modulation)
2112 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
2113 parm_u_ofdm_constellation = QPSK;
2115 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
2116 parm_u_ofdm_constellation = QAM_16;
2118 case eDVBFrontendParametersTerrestrial::Modulation::QAM64:
2119 parm_u_ofdm_constellation = QAM_64;
2122 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
2123 parm_u_ofdm_constellation = QAM_AUTO;
2126 switch (feparm.transmission_mode)
2128 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
2129 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2131 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
2132 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2135 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
2136 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2139 switch (feparm.guard_interval)
2141 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32:
2142 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2144 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16:
2145 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2147 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8:
2148 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2150 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4:
2151 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2154 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto:
2155 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2158 switch (feparm.hierarchy)
2160 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone:
2161 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2163 case eDVBFrontendParametersTerrestrial::Hierarchy::H1:
2164 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2166 case eDVBFrontendParametersTerrestrial::Hierarchy::H2:
2167 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2169 case eDVBFrontendParametersTerrestrial::Hierarchy::H4:
2170 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2173 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto:
2174 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2177 switch (feparm.inversion)
2179 case eDVBFrontendParametersTerrestrial::Inversion::On:
2180 parm_inversion = INVERSION_ON;
2182 case eDVBFrontendParametersTerrestrial::Inversion::Off:
2183 parm_inversion = INVERSION_OFF;
2186 case eDVBFrontendParametersTerrestrial::Inversion::Unknown:
2187 parm_inversion = INVERSION_AUTO;
2193 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2195 unsigned int timeout = 5000;
2196 eDebugNoSimulate("(%d)tune", m_dvbid);
2202 if (!m_sn && !m_simulate)
2204 eDebug("no frontend device opened... do not try to tune !!!");
2218 m_sec_sequence.clear();
2220 where.calcLockTimeout(timeout);
2226 eDVBFrontendParametersSatellite feparm;
2227 if (where.getDVBS(feparm))
2229 eDebug("no dvbs data!");
2234 m_sec->setRotorMoving(false);
2235 res=prepare_sat(feparm, timeout);
2243 eDVBFrontendParametersCable feparm;
2244 if (where.getDVBC(feparm))
2249 res=prepare_cable(feparm);
2253 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2254 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2259 eDVBFrontendParametersTerrestrial feparm;
2260 if (where.getDVBT(feparm))
2262 eDebug("no -T data");
2266 res=prepare_terrestrial(feparm);
2270 std::string enable_5V;
2271 char configStr[255];
2272 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2273 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2274 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2275 if (enable_5V == "True")
2276 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2278 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2279 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2285 m_sec_sequence.current() = m_sec_sequence.begin();
2289 m_tuneTimer->start(0,true);
2290 if (m_state != stateTuning)
2293 m_state = stateTuning;
2294 m_stateChanged(this);
2303 m_tuneTimer->stop();
2307 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2309 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2313 RESULT eDVBFrontend::setVoltage(int voltage)
2315 if (m_type == feCable)
2317 #if HAVE_DVB_API_VERSION < 3
2320 bool increased=false;
2321 fe_sec_voltage_t vlt;
2323 m_data[CUR_VOLTAGE]=voltage;
2327 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2328 vlt = SEC_VOLTAGE_OFF;
2331 #if HAVE_DVB_API_VERSION < 3
2332 vlt = SEC_VOLTAGE_13_5;
2338 vlt = SEC_VOLTAGE_13;
2341 #if HAVE_DVB_API_VERSION < 3
2342 vlt = SEC_VOLTAGE_18_5;
2348 vlt = SEC_VOLTAGE_18;
2355 #if HAVE_DVB_API_VERSION < 3
2356 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2358 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2359 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2360 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2364 RESULT eDVBFrontend::getState(int &state)
2370 RESULT eDVBFrontend::setTone(int t)
2372 if (m_type != feSatellite)
2374 #if HAVE_DVB_API_VERSION < 3
2377 fe_sec_tone_mode_t tone;
2386 tone = SEC_TONE_OFF;
2393 #if HAVE_DVB_API_VERSION < 3
2394 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2396 return ::ioctl(m_fd, FE_SET_TONE, tone);
2400 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2401 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2404 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2408 #if HAVE_DVB_API_VERSION < 3
2409 struct secCommand cmd;
2410 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2411 cmd.u.diseqc.cmdtype = diseqc.data[0];
2412 cmd.u.diseqc.addr = diseqc.data[1];
2413 cmd.u.diseqc.cmd = diseqc.data[2];
2414 cmd.u.diseqc.numParams = diseqc.len-3;
2415 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2416 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2418 struct dvb_diseqc_master_cmd cmd;
2419 memcpy(cmd.msg, diseqc.data, diseqc.len);
2420 cmd.msg_len = diseqc.len;
2421 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2427 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2428 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2430 RESULT eDVBFrontend::sendToneburst(int burst)
2434 #if HAVE_DVB_API_VERSION < 3
2435 secMiniCmd cmd = SEC_MINI_NONE;
2437 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2439 if ( burst == eDVBSatelliteDiseqcParameters::A )
2441 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2443 #if HAVE_DVB_API_VERSION < 3
2444 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2447 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2453 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2459 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2461 m_sec_sequence = list;
2465 RESULT eDVBFrontend::getData(int num, long &data)
2467 if ( num < NUM_DATA_ENTRIES )
2475 RESULT eDVBFrontend::setData(int num, long val)
2477 if ( num < NUM_DATA_ENTRIES )
2485 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2488 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2490 if (m_type == eDVBFrontend::feSatellite)
2493 eDVBFrontendParametersSatellite sat_parm;
2494 int ret = feparm->getDVBS(sat_parm);
2496 if (sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S2 && !m_can_handle_dvbs2)
2498 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2499 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S && m_can_handle_dvbs2)
2503 else if (m_type == eDVBFrontend::feCable)
2504 return 2; // more prio for cable frontends
2505 else if (m_type == eDVBFrontend::feTerrestrial)
2510 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2512 ePyObject Id, Descr, Enabled, IsDVBS2;
2513 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4)
2515 Id = PyTuple_GET_ITEM(obj, 0);
2516 Descr = PyTuple_GET_ITEM(obj, 1);
2517 Enabled = PyTuple_GET_ITEM(obj, 2);
2518 IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2519 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2))
2521 strcpy(m_description, PyString_AS_STRING(Descr));
2522 m_slotid = PyInt_AsLong(Id);
2523 m_enabled = Enabled == Py_True;
2524 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2525 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2526 !!strstr(m_description, "Alps BSBE2") ||
2527 !!strstr(m_description, "Alps -S") ||
2528 !!strstr(m_description, "BCM4501");
2529 m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2530 eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2531 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2534 PyErr_SetString(PyExc_StandardError,
2535 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");