1 #include <lib/dvb/dvb.h>
2 #include <lib/dvb/frontendparms.h>
3 #include <lib/base/eerror.h>
4 #include <lib/base/nconfig.h> // access to python config
10 #ifndef I2C_SLAVE_FORCE
11 #define I2C_SLAVE_FORCE 0x0706
14 #if HAVE_DVB_API_VERSION < 3
15 #include <ost/frontend.h>
17 #define QAM_AUTO (Modulation)6
18 #define TRANSMISSION_MODE_AUTO (TransmitMode)2
19 #define BANDWIDTH_AUTO (BandWidth)3
20 #define GUARD_INTERVAL_AUTO (GuardInterval)4
21 #define HIERARCHY_AUTO (Hierarchy)4
22 #define parm_frequency parm.Frequency
23 #define parm_inversion parm.Inversion
24 #define parm_u_qpsk_symbol_rate parm.u.qpsk.SymbolRate
25 #define parm_u_qpsk_fec_inner parm.u.qpsk.FEC_inner
26 #define parm_u_qam_symbol_rate parm.u.qam.SymbolRate
27 #define parm_u_qam_fec_inner parm.u.qam.FEC_inner
28 #define parm_u_qam_modulation parm.u.qam.QAM
29 #define parm_u_ofdm_bandwidth parm.u.ofdm.bandWidth
30 #define parm_u_ofdm_code_rate_LP parm.u.ofdm.LP_CodeRate
31 #define parm_u_ofdm_code_rate_HP parm.u.ofdm.HP_CodeRate
32 #define parm_u_ofdm_constellation parm.u.ofdm.Constellation
33 #define parm_u_ofdm_transmission_mode parm.u.ofdm.TransmissionMode
34 #define parm_u_ofdm_guard_interval parm.u.ofdm.guardInterval
35 #define parm_u_ofdm_hierarchy_information parm.u.ofdm.HierarchyInformation
37 #include <linux/dvb/frontend.h>
38 #define parm_frequency parm.frequency
39 #define parm_inversion parm.inversion
40 #define parm_u_qpsk_symbol_rate parm.u.qpsk.symbol_rate
41 #define parm_u_qpsk_fec_inner parm.u.qpsk.fec_inner
42 #define parm_u_qam_symbol_rate parm.u.qam.symbol_rate
43 #define parm_u_qam_fec_inner parm.u.qam.fec_inner
44 #define parm_u_qam_modulation parm.u.qam.modulation
45 #define parm_u_ofdm_bandwidth parm.u.ofdm.bandwidth
46 #define parm_u_ofdm_code_rate_LP parm.u.ofdm.code_rate_LP
47 #define parm_u_ofdm_code_rate_HP parm.u.ofdm.code_rate_HP
48 #define parm_u_ofdm_constellation parm.u.ofdm.constellation
49 #define parm_u_ofdm_transmission_mode parm.u.ofdm.transmission_mode
50 #define parm_u_ofdm_guard_interval parm.u.ofdm.guard_interval
51 #define parm_u_ofdm_hierarchy_information parm.u.ofdm.hierarchy_information
53 #warning "FEC_9_10 already exist in dvb api ... it seems it is now ready for DVB-S2"
55 #define FEC_S2_QPSK_1_2 (fe_code_rate_t)(FEC_AUTO+1)
56 #define FEC_S2_QPSK_2_3 (fe_code_rate_t)(FEC_S2_QPSK_1_2+1)
57 #define FEC_S2_QPSK_3_4 (fe_code_rate_t)(FEC_S2_QPSK_2_3+1)
58 #define FEC_S2_QPSK_5_6 (fe_code_rate_t)(FEC_S2_QPSK_3_4+1)
59 #define FEC_S2_QPSK_7_8 (fe_code_rate_t)(FEC_S2_QPSK_5_6+1)
60 #define FEC_S2_QPSK_8_9 (fe_code_rate_t)(FEC_S2_QPSK_7_8+1)
61 #define FEC_S2_QPSK_3_5 (fe_code_rate_t)(FEC_S2_QPSK_8_9+1)
62 #define FEC_S2_QPSK_4_5 (fe_code_rate_t)(FEC_S2_QPSK_3_5+1)
63 #define FEC_S2_QPSK_9_10 (fe_code_rate_t)(FEC_S2_QPSK_4_5+1)
64 #define FEC_S2_8PSK_1_2 (fe_code_rate_t)(FEC_S2_QPSK_9_10+1)
65 #define FEC_S2_8PSK_2_3 (fe_code_rate_t)(FEC_S2_8PSK_1_2+1)
66 #define FEC_S2_8PSK_3_4 (fe_code_rate_t)(FEC_S2_8PSK_2_3+1)
67 #define FEC_S2_8PSK_5_6 (fe_code_rate_t)(FEC_S2_8PSK_3_4+1)
68 #define FEC_S2_8PSK_7_8 (fe_code_rate_t)(FEC_S2_8PSK_5_6+1)
69 #define FEC_S2_8PSK_8_9 (fe_code_rate_t)(FEC_S2_8PSK_7_8+1)
70 #define FEC_S2_8PSK_3_5 (fe_code_rate_t)(FEC_S2_8PSK_8_9+1)
71 #define FEC_S2_8PSK_4_5 (fe_code_rate_t)(FEC_S2_8PSK_3_5+1)
72 #define FEC_S2_8PSK_9_10 (fe_code_rate_t)(FEC_S2_8PSK_4_5+1)
76 #include <dvbsi++/satellite_delivery_system_descriptor.h>
77 #include <dvbsi++/cable_delivery_system_descriptor.h>
78 #include <dvbsi++/terrestrial_delivery_system_descriptor.h>
80 #define eDebugNoSimulate(x...) \
88 eDebugNoNewLine("SIMULATE:"); \
93 #define eDebugNoSimulateNoNewLine(x...) \
101 eDebugNoNewLine("SIMULATE:"); \
102 eDebugNoNewLine(x); \
106 void eDVBDiseqcCommand::setCommandString(const char *str)
111 int slen = strlen(str);
114 eDebug("invalid diseqc command string length (not 2 byte aligned)");
117 if (slen > MAX_DISEQC_LENGTH*2)
119 eDebug("invalid diseqc command string length (string is to long)");
123 for (int i=0; i < slen; ++i)
125 unsigned char c = str[i];
128 case '0' ... '9': c-=48; break;
129 case 'a' ... 'f': c-=87; break;
130 case 'A' ... 'F': c-=55; break;
132 eDebug("invalid character in hex string..ignore complete diseqc command !");
146 void eDVBFrontendParametersSatellite::set(const SatelliteDeliverySystemDescriptor &descriptor)
148 frequency = descriptor.getFrequency() * 10;
149 symbol_rate = descriptor.getSymbolRate() * 100;
150 polarisation = descriptor.getPolarization();
151 fec = descriptor.getFecInner();
152 if ( fec != eDVBFrontendParametersSatellite::FEC_None && fec > eDVBFrontendParametersSatellite::FEC_9_10 )
153 fec = eDVBFrontendParametersSatellite::FEC_Auto;
154 inversion = eDVBFrontendParametersSatellite::Inversion_Unknown;
155 pilot = eDVBFrontendParametersSatellite::Pilot_Unknown;
156 orbital_position = ((descriptor.getOrbitalPosition() >> 12) & 0xF) * 1000;
157 orbital_position += ((descriptor.getOrbitalPosition() >> 8) & 0xF) * 100;
158 orbital_position += ((descriptor.getOrbitalPosition() >> 4) & 0xF) * 10;
159 orbital_position += ((descriptor.getOrbitalPosition()) & 0xF);
160 if (orbital_position && (!descriptor.getWestEastFlag()))
161 orbital_position = 3600 - orbital_position;
162 system = descriptor.getModulationSystem();
163 modulation = descriptor.getModulation();
164 if (system == eDVBFrontendParametersSatellite::System_DVB_S && modulation == eDVBFrontendParametersSatellite::Modulation_8PSK)
166 eDebug("satellite_delivery_descriptor non valid modulation type.. force QPSK");
167 modulation=eDVBFrontendParametersSatellite::Modulation_QPSK;
169 rolloff = descriptor.getRollOff();
170 if (system == eDVBFrontendParametersSatellite::System_DVB_S2)
172 eDebug("SAT DVB-S2 freq %d, %s, pos %d, sr %d, fec %d, modulation %d, rolloff %d",
174 polarisation ? "hor" : "vert",
182 eDebug("SAT DVB-S freq %d, %s, pos %d, sr %d, fec %d",
184 polarisation ? "hor" : "vert",
190 void eDVBFrontendParametersCable::set(const CableDeliverySystemDescriptor &descriptor)
192 frequency = descriptor.getFrequency() / 10;
193 symbol_rate = descriptor.getSymbolRate() * 100;
194 fec_inner = descriptor.getFecInner();
195 if ( fec_inner != eDVBFrontendParametersCable::FEC_None && fec_inner > eDVBFrontendParametersCable::FEC_8_9 )
196 fec_inner = eDVBFrontendParametersCable::FEC_Auto;
197 modulation = descriptor.getModulation();
198 if ( modulation > 0x5 )
199 modulation = eDVBFrontendParametersCable::Modulation_Auto;
200 inversion = eDVBFrontendParametersCable::Inversion_Unknown;
201 eDebug("Cable freq %d, mod %d, sr %d, fec %d",
203 modulation, symbol_rate, fec_inner);
206 void eDVBFrontendParametersTerrestrial::set(const TerrestrialDeliverySystemDescriptor &descriptor)
208 frequency = descriptor.getCentreFrequency() * 10;
209 bandwidth = descriptor.getBandwidth();
210 if ( bandwidth > 2 ) // 5Mhz forced to auto
211 bandwidth = eDVBFrontendParametersTerrestrial::Bandwidth_Auto;
212 code_rate_HP = descriptor.getCodeRateHpStream();
213 if (code_rate_HP > 4)
214 code_rate_HP = eDVBFrontendParametersTerrestrial::FEC_Auto;
215 code_rate_LP = descriptor.getCodeRateLpStream();
216 if (code_rate_LP > 4)
217 code_rate_LP = eDVBFrontendParametersTerrestrial::FEC_Auto;
218 transmission_mode = descriptor.getTransmissionMode();
219 if (transmission_mode > 1) // TM4k forced to auto
220 transmission_mode = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto;
221 guard_interval = descriptor.getGuardInterval();
222 if (guard_interval > 3)
223 guard_interval = eDVBFrontendParametersTerrestrial::GuardInterval_Auto;
224 hierarchy = descriptor.getHierarchyInformation()&3;
225 modulation = descriptor.getConstellation();
227 modulation = eDVBFrontendParametersTerrestrial::Modulation_Auto;
228 inversion = eDVBFrontendParametersTerrestrial::Inversion_Unknown;
229 eDebug("Terr freq %d, bw %d, cr_hp %d, cr_lp %d, tm_mode %d, guard %d, hierarchy %d, const %d",
230 frequency, bandwidth, code_rate_HP, code_rate_LP, transmission_mode,
231 guard_interval, hierarchy, modulation);
234 eDVBFrontendParameters::eDVBFrontendParameters()
235 :m_type(-1), m_flags(0)
239 DEFINE_REF(eDVBFrontendParameters);
241 RESULT eDVBFrontendParameters::getSystem(int &t) const
249 RESULT eDVBFrontendParameters::getDVBS(eDVBFrontendParametersSatellite &p) const
251 if (m_type != iDVBFrontend::feSatellite)
257 RESULT eDVBFrontendParameters::getDVBC(eDVBFrontendParametersCable &p) const
259 if (m_type != iDVBFrontend::feCable)
265 RESULT eDVBFrontendParameters::getDVBT(eDVBFrontendParametersTerrestrial &p) const
267 if (m_type != iDVBFrontend::feTerrestrial)
273 RESULT eDVBFrontendParameters::setDVBS(const eDVBFrontendParametersSatellite &p, bool no_rotor_command_on_tune)
276 sat.no_rotor_command_on_tune = no_rotor_command_on_tune;
277 m_type = iDVBFrontend::feSatellite;
281 RESULT eDVBFrontendParameters::setDVBC(const eDVBFrontendParametersCable &p)
284 m_type = iDVBFrontend::feCable;
288 RESULT eDVBFrontendParameters::setDVBT(const eDVBFrontendParametersTerrestrial &p)
291 m_type = iDVBFrontend::feTerrestrial;
295 RESULT eDVBFrontendParameters::calculateDifference(const iDVBFrontendParameters *parm, int &diff, bool exact) const
300 if (parm->getSystem(type))
304 diff = 1<<30; // big difference
310 case iDVBFrontend::feSatellite:
312 eDVBFrontendParametersSatellite osat;
313 if (parm->getDVBS(osat))
316 if (sat.orbital_position != osat.orbital_position)
318 else if (sat.polarisation != osat.polarisation)
320 else if (exact && sat.fec != osat.fec && sat.fec != eDVBFrontendParametersSatellite::FEC_Auto && osat.fec != eDVBFrontendParametersSatellite::FEC_Auto)
322 else if (exact && sat.modulation != osat.modulation && sat.modulation != eDVBFrontendParametersSatellite::Modulation_Auto && osat.modulation != eDVBFrontendParametersSatellite::Modulation_Auto)
326 diff = abs(sat.frequency - osat.frequency);
327 diff += abs(sat.symbol_rate - osat.symbol_rate);
331 case iDVBFrontend::feCable:
332 eDVBFrontendParametersCable ocable;
333 if (parm->getDVBC(ocable))
336 if (exact && cable.modulation != ocable.modulation
337 && cable.modulation != eDVBFrontendParametersCable::Modulation_Auto
338 && ocable.modulation != eDVBFrontendParametersCable::Modulation_Auto)
340 else if (exact && cable.fec_inner != ocable.fec_inner && cable.fec_inner != eDVBFrontendParametersCable::FEC_Auto && ocable.fec_inner != eDVBFrontendParametersCable::FEC_Auto)
344 diff = abs(cable.frequency - ocable.frequency);
345 diff += abs(cable.symbol_rate - ocable.symbol_rate);
348 case iDVBFrontend::feTerrestrial:
349 eDVBFrontendParametersTerrestrial oterrestrial;
350 if (parm->getDVBT(oterrestrial))
353 if (exact && oterrestrial.bandwidth != terrestrial.bandwidth &&
354 oterrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth_Auto &&
355 terrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth_Auto)
357 else if (exact && oterrestrial.modulation != terrestrial.modulation &&
358 oterrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation_Auto &&
359 terrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation_Auto)
361 else if (exact && oterrestrial.transmission_mode != terrestrial.transmission_mode &&
362 oterrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode_Auto &&
363 terrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode_Auto)
365 else if (exact && oterrestrial.guard_interval != terrestrial.guard_interval &&
366 oterrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval_Auto &&
367 terrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval_Auto)
369 else if (exact && oterrestrial.hierarchy != terrestrial.hierarchy &&
370 oterrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy_Auto &&
371 terrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy_Auto)
373 else if (exact && oterrestrial.code_rate_LP != terrestrial.code_rate_LP &&
374 oterrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC_Auto &&
375 terrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC_Auto)
377 else if (exact && oterrestrial.code_rate_HP != terrestrial.code_rate_HP &&
378 oterrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC_Auto &&
379 terrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC_Auto)
382 diff = abs(terrestrial.frequency - oterrestrial.frequency);
390 RESULT eDVBFrontendParameters::getHash(unsigned long &hash) const
394 case iDVBFrontend::feSatellite:
396 hash = (sat.orbital_position << 16);
397 hash |= ((sat.frequency/1000)&0xFFFF)|((sat.polarisation&1) << 15);
400 case iDVBFrontend::feCable:
402 hash |= (cable.frequency/1000)&0xFFFF;
404 case iDVBFrontend::feTerrestrial:
406 hash |= (terrestrial.frequency/1000)&0xFFFF;
413 RESULT eDVBFrontendParameters::calcLockTimeout(unsigned int &timeout) const
417 case iDVBFrontend::feSatellite:
419 /* high symbol rate transponders tune faster, due to
420 requiring less zigzag and giving more symbols faster.
422 5s are definitely not enough on really low SR when
423 zigzag has to find the exact frequency first.
425 if (sat.symbol_rate > 20000000)
427 else if (sat.symbol_rate > 10000000)
433 case iDVBFrontend::feCable:
436 case iDVBFrontend::feTerrestrial:
444 DEFINE_REF(eDVBFrontend);
446 int eDVBFrontend::PriorityOrder=0;
448 eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok, bool simulate)
449 :m_simulate(simulate), m_enabled(false), m_type(-1), m_dvbid(fe), m_slotid(fe)
450 ,m_fd(-1), m_need_rotor_workaround(false), m_can_handle_dvbs2(false)
451 , m_timeout(0), m_tuneTimer(0)
452 #if HAVE_DVB_API_VERSION < 3
456 #if HAVE_DVB_API_VERSION < 3
457 sprintf(m_filename, "/dev/dvb/card%d/frontend%d", adap, fe);
458 sprintf(m_sec_filename, "/dev/dvb/card%d/sec%d", adap, fe);
460 sprintf(m_filename, "/dev/dvb/adapter%d/frontend%d", adap, fe);
463 m_timeout = eTimer::create(eApp);
464 CONNECT(m_timeout->timeout, eDVBFrontend::timeout);
466 m_tuneTimer = eTimer::create(eApp);
467 CONNECT(m_tuneTimer->timeout, eDVBFrontend::tuneLoop);
469 for (int i=0; i<eDVBFrontend::NUM_DATA_ENTRIES; ++i)
472 m_idleInputpower[0]=m_idleInputpower[1]=0;
474 ok = !openFrontend();
478 int eDVBFrontend::openFrontend()
481 return -1; // already opened
486 #if HAVE_DVB_API_VERSION < 3
487 FrontendInfo fe_info;
489 dvb_frontend_info fe_info;
491 eDebugNoSimulate("opening frontend %d", m_dvbid);
494 if (!m_simulate || m_type == -1)
496 m_fd = ::open(m_filename, O_RDWR|O_NONBLOCK);
499 eWarning("failed! (%s) %m", m_filename);
505 eWarning("frontend %d already opened", m_dvbid);
508 if (::ioctl(m_fd, FE_GET_INFO, &fe_info) < 0)
510 eWarning("ioctl FE_GET_INFO failed");
516 switch (fe_info.type)
519 m_type = iDVBFrontend::feSatellite;
522 m_type = iDVBFrontend::feCable;
525 m_type = iDVBFrontend::feTerrestrial;
528 eWarning("unknown frontend type.");
533 eDebugNoSimulate("detected %s frontend", "satellite\0cable\0 terrestrial"+fe_info.type*10);
536 #if HAVE_DVB_API_VERSION < 3
537 if (m_type == iDVBFrontend::feSatellite)
543 m_secfd = ::open(m_sec_filename, O_RDWR);
546 eWarning("failed! (%s) %m", m_sec_filename);
554 eWarning("sec %d already opened", m_dvbid);
558 setTone(iDVBFrontend::toneOff);
559 setVoltage(iDVBFrontend::voltageOff);
563 m_sn = eSocketNotifier::create(eApp, m_fd, eSocketNotifier::Read, false);
564 CONNECT(m_sn->activated, eDVBFrontend::feEvent);
570 int eDVBFrontend::closeFrontend(bool force)
572 if (!force && m_data[CUR_VOLTAGE] != -1 && m_data[CUR_VOLTAGE] != iDVBFrontend::voltageOff)
574 long tmp = m_data[LINKED_NEXT_PTR];
577 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
578 if (linked_fe->m_inuse)
580 eDebugNoSimulate("dont close frontend %d until the linked frontend %d in slot %d is still in use",
581 m_dvbid, linked_fe->m_frontend->getDVBID(), linked_fe->m_frontend->getSlotID());
584 linked_fe->m_frontend->getData(LINKED_NEXT_PTR, tmp);
590 eDebugNoSimulate("close frontend %d", m_dvbid);
591 if (m_data[SATCR] != -1)
593 turnOffSatCR(m_data[SATCR]);
595 setTone(iDVBFrontend::toneOff);
596 setVoltage(iDVBFrontend::voltageOff);
598 if (m_sec && !m_simulate)
599 m_sec->setRotorMoving(false);
603 eWarning("couldnt close frontend %d", m_dvbid);
607 setTone(iDVBFrontend::toneOff);
608 setVoltage(iDVBFrontend::voltageOff);
610 #if HAVE_DVB_API_VERSION < 3
613 if (!::close(m_secfd))
616 eWarning("couldnt close sec %d", m_dvbid);
620 m_state = stateClosed;
625 eDVBFrontend::~eDVBFrontend()
627 m_data[LINKED_PREV_PTR] = m_data[LINKED_NEXT_PTR] = -1;
631 void eDVBFrontend::feEvent(int w)
633 eDVBFrontend *sec_fe = this;
634 long tmp = m_data[LINKED_PREV_PTR];
637 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
638 sec_fe = linked_fe->m_frontend;
639 sec_fe->getData(LINKED_NEXT_PTR, tmp);
643 #if HAVE_DVB_API_VERSION < 3
646 dvb_frontend_event event;
650 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
652 if (res && (errno == EAGAIN))
657 eWarning("FE_GET_EVENT failed! %m");
664 #if HAVE_DVB_API_VERSION < 3
665 if (event.type == FE_COMPLETION_EV)
667 eDebug("(%d)fe event: status %x, inversion %s", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off");
668 if (event.status & FE_HAS_LOCK)
678 eDebug("stateLostLock");
679 state = stateLostLock;
680 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
683 if (m_state != state)
686 m_stateChanged(this);
691 void eDVBFrontend::timeout()
694 if (m_state == stateTuning)
696 m_state = stateFailed;
697 m_stateChanged(this);
701 #define INRANGE(X,Y,Z) (((X<=Y) && (Y<=Z))||((Z<=Y) && (Y<=X)) ? 1 : 0)
703 /* unsigned 32 bit division */
704 static inline uint32_t fe_udiv(uint32_t a, uint32_t b)
706 return (a + b / 2) / b;
709 int eDVBFrontend::readFrontendData(int type)
718 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
719 eDebug("FE_READ_BER failed (%m)");
724 case signalQualitydB: /* this will move into the driver */
726 int sat_max = 1600; // for stv0288 / bsbe2
727 int ret = 0x12345678;
731 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
732 eDebug("FE_READ_SNR failed (%m)");
733 else if (!strcmp(m_description, "BCM4501 (internal)"))
735 float SDS_SNRE = snr << 16;
738 if (parm_u_qpsk_fec_inner <= FEC_AUTO) // DVB-S1 / QPSK
740 static float SNR_COEFF[6] = {
743 197418.0 / 4194304.0,
744 -2602183.0 / 4194304.0,
745 20377212.0 / 4194304.0,
746 -37791203.0 / 4194304.0,
748 float fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0)),
749 fval2 = pow(10.0, fval1)-1;
750 fval1 = 10.0 * log10(fval2);
754 fval2 = SNR_COEFF[0];
755 for (int i=1; i<6; ++i)
758 fval2 += SNR_COEFF[i];
764 #if HAVE_DVB_API_VERSION >= 3
767 float fval1 = SDS_SNRE / 268435456.0,
770 if (parm_u_qpsk_fec_inner <= FEC_S2_QPSK_9_10) // DVB-S2 QPSK
781 fval4 = -10.0 * log10(fval1);
783 for (int i=0; i < 5; ++i)
784 fval1 = fval4 - fval2 * log10(1.0+pow(10.0, (fval3-fval1)/fval2));
789 ret = (int)(snr_in_db * 100);
791 else if (strstr(m_description, "Alps BSBE1 C01A") ||
792 !strcmp(m_description, "Alps -S(STV0288)"))
796 else if (snr == 0xFFFF) // i think this should not happen
800 enum { REALVAL, REGVAL };
801 const long CN_lookup[31][2] = {
802 {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
803 {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
804 {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
805 {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
806 {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
807 {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
810 int add=strchr(m_description, '.') ? 0xA250 : 0xA100;
811 long regval = 0xFFFF - ((snr / 3) + add), // revert some dvb api calulations to get the real register value
815 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
820 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[i][REGVAL]))
825 ret = (((regval - CN_lookup[Imin][REGVAL])
826 * (CN_lookup[Imax][REALVAL] - CN_lookup[Imin][REALVAL])
827 / (CN_lookup[Imax][REGVAL] - CN_lookup[Imin][REGVAL]))
828 + CN_lookup[Imin][REALVAL]) * 10;
834 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
835 !strcmp(m_description, "Alps -S") ||
836 !strcmp(m_description, "Philips -S") ||
837 !strcmp(m_description, "LG -S") )
840 ret = (int)((snr-39075)/17.647);
841 } else if (!strcmp(m_description, "Alps BSBE2"))
843 ret = (int)((snr >> 7) * 10);
844 } else if (!strcmp(m_description, "Philips CU1216Mk3"))
846 int mse = (~snr) & 0xFF;
847 switch (parm_u_qam_modulation) {
848 case QAM_16: ret = fe_udiv(1950000, (32 * mse) + 138) + 1000; break;
849 case QAM_32: ret = fe_udiv(2150000, (40 * mse) + 500) + 1350; break;
850 case QAM_64: ret = fe_udiv(2100000, (40 * mse) + 500) + 1250; break;
851 case QAM_128: ret = fe_udiv(1850000, (38 * mse) + 400) + 1380; break;
852 case QAM_256: ret = fe_udiv(1800000, (100 * mse) + 40) + 2030; break;
855 } else if (!strcmp(m_description, "Philips TU1216"))
857 snr = 0xFF - (snr & 0xFF);
859 ret = 10 * (int)(-100 * (log10(snr) - log10(255)));
862 if (type == signalQuality)
864 if (ret == 0x12345678) // no snr db calculation avail.. return untouched snr value..
869 return ret >= sat_max ? 65536 : ret * 65536 / sat_max;
870 case feCable: // we assume a max of 42db here
871 return ret >= 4200 ? 65536 : ret * 65536 / 4200;
872 case feTerrestrial: // we assume a max of 24db here
873 return ret >= 2400 ? 65536 : ret * 65536 / 2400;
877 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
885 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
886 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
892 #if HAVE_DVB_API_VERSION < 3
893 FrontendStatus status=0;
899 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
900 eDebug("FE_READ_STATUS failed (%m)");
901 return !!(status&FE_HAS_LOCK);
907 #if HAVE_DVB_API_VERSION < 3
908 FrontendStatus status=0;
914 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
915 eDebug("FE_READ_STATUS failed (%m)");
916 return !!(status&FE_HAS_SYNC);
926 void PutToDict(ePyObject &dict, const char*key, long value)
928 ePyObject item = PyInt_FromLong(value);
931 if (PyDict_SetItemString(dict, key, item))
932 eDebug("put %s to dict failed", key);
936 eDebug("could not create PyObject for %s", key);
939 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
943 if (PyDict_SetItemString(dict, key, item))
944 eDebug("put %s to dict failed", key);
948 eDebug("invalid PyObject for %s", key);
951 void PutToDict(ePyObject &dict, const char*key, const char *value)
953 ePyObject item = PyString_FromString(value);
956 if (PyDict_SetItemString(dict, key, item))
957 eDebug("put %s to dict failed", key);
961 eDebug("could not create PyObject for %s", key);
964 void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, long freq_offset, int orb_pos, int polarization)
967 int frequency = parm_frequency + freq_offset;
968 PutToDict(dict, "frequency", frequency);
969 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
970 PutToDict(dict, "orbital_position", orb_pos);
971 PutToDict(dict, "polarization", polarization);
973 switch(parm_u_qpsk_fec_inner)
975 case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
976 case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
977 case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
978 case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
979 case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
980 case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
982 case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
983 #if HAVE_DVB_API_VERSION >=3
984 case FEC_S2_8PSK_1_2:
985 case FEC_S2_QPSK_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
986 case FEC_S2_8PSK_2_3:
987 case FEC_S2_QPSK_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
988 case FEC_S2_8PSK_3_4:
989 case FEC_S2_QPSK_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
990 case FEC_S2_8PSK_5_6:
991 case FEC_S2_QPSK_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
992 case FEC_S2_8PSK_7_8:
993 case FEC_S2_QPSK_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
994 case FEC_S2_8PSK_8_9:
995 case FEC_S2_QPSK_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
996 case FEC_S2_8PSK_3_5:
997 case FEC_S2_QPSK_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
998 case FEC_S2_8PSK_4_5:
999 case FEC_S2_QPSK_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
1000 case FEC_S2_8PSK_9_10:
1001 case FEC_S2_QPSK_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1004 PutToDict(dict, "fec_inner", tmp);
1005 #if HAVE_DVB_API_VERSION >=3
1006 PutToDict(dict, "modulation",
1007 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ?
1008 eDVBFrontendParametersSatellite::Modulation_8PSK :
1009 eDVBFrontendParametersSatellite::Modulation_QPSK );
1010 if (parm_u_qpsk_fec_inner > FEC_AUTO)
1012 switch(parm_inversion & 0xc)
1014 default: // unknown rolloff
1015 case 0: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1016 case 4: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1017 case 8: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1019 PutToDict(dict, "rolloff", tmp);
1020 switch(parm_inversion & 0x30)
1022 case 0: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1023 case 0x10: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1024 case 0x20: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1026 PutToDict(dict, "pilot", tmp);
1027 tmp = eDVBFrontendParametersSatellite::System_DVB_S2;
1030 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1032 PutToDict(dict, "modulation", eDVBFrontendParametersSatellite::Modulation_QPSK );
1033 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1035 PutToDict(dict, "system", tmp);
1038 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1041 #if HAVE_DVB_API_VERSION < 3
1042 PutToDict(dict, "frequency", parm_frequency);
1044 PutToDict(dict, "frequency", parm_frequency/1000);
1046 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1047 switch(parm_u_qam_fec_inner)
1049 case FEC_NONE: tmp = eDVBFrontendParametersCable::FEC_None; break;
1050 case FEC_1_2: tmp = eDVBFrontendParametersCable::FEC_1_2; break;
1051 case FEC_2_3: tmp = eDVBFrontendParametersCable::FEC_2_3; break;
1052 case FEC_3_4: tmp = eDVBFrontendParametersCable::FEC_3_4; break;
1053 case FEC_5_6: tmp = eDVBFrontendParametersCable::FEC_5_6; break;
1054 case FEC_7_8: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1055 #if HAVE_DVB_API_VERSION >= 3
1056 case FEC_8_9: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1059 case FEC_AUTO: tmp = eDVBFrontendParametersCable::FEC_Auto; break;
1061 PutToDict(dict, "fec_inner", tmp);
1062 switch(parm_u_qam_modulation)
1064 case QAM_16: tmp = eDVBFrontendParametersCable::Modulation_QAM16; break;
1065 case QAM_32: tmp = eDVBFrontendParametersCable::Modulation_QAM32; break;
1066 case QAM_64: tmp = eDVBFrontendParametersCable::Modulation_QAM64; break;
1067 case QAM_128: tmp = eDVBFrontendParametersCable::Modulation_QAM128; break;
1068 case QAM_256: tmp = eDVBFrontendParametersCable::Modulation_QAM256; break;
1070 case QAM_AUTO: tmp = eDVBFrontendParametersCable::Modulation_Auto; break;
1072 PutToDict(dict, "modulation", tmp);
1075 void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1078 PutToDict(dict, "frequency", parm_frequency);
1079 switch (parm_u_ofdm_bandwidth)
1081 case BANDWIDTH_8_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_8MHz; break;
1082 case BANDWIDTH_7_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_7MHz; break;
1083 case BANDWIDTH_6_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_6MHz; break;
1085 case BANDWIDTH_AUTO: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_Auto; break;
1087 PutToDict(dict, "bandwidth", tmp);
1088 switch (parm_u_ofdm_code_rate_LP)
1090 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1091 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1092 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1093 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1094 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1096 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1098 PutToDict(dict, "code_rate_lp", tmp);
1099 switch (parm_u_ofdm_code_rate_HP)
1101 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1102 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1103 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1104 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1105 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1107 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1109 PutToDict(dict, "code_rate_hp", tmp);
1110 switch (parm_u_ofdm_constellation)
1112 case QPSK: tmp = eDVBFrontendParametersTerrestrial::Modulation_QPSK; break;
1113 case QAM_16: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM16; break;
1114 case QAM_64: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM64; break;
1116 case QAM_AUTO: tmp = eDVBFrontendParametersTerrestrial::Modulation_Auto; break;
1118 PutToDict(dict, "constellation", tmp);
1119 switch (parm_u_ofdm_transmission_mode)
1121 case TRANSMISSION_MODE_2K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_2k; break;
1122 case TRANSMISSION_MODE_8K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_8k; break;
1124 case TRANSMISSION_MODE_AUTO: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto; break;
1126 PutToDict(dict, "transmission_mode", tmp);
1127 switch (parm_u_ofdm_guard_interval)
1129 case GUARD_INTERVAL_1_32: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_32; break;
1130 case GUARD_INTERVAL_1_16: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_16; break;
1131 case GUARD_INTERVAL_1_8: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_8; break;
1132 case GUARD_INTERVAL_1_4: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_4; break;
1134 case GUARD_INTERVAL_AUTO: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_Auto; break;
1136 PutToDict(dict, "guard_interval", tmp);
1137 switch (parm_u_ofdm_hierarchy_information)
1139 case HIERARCHY_NONE: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_None; break;
1140 case HIERARCHY_1: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_1; break;
1141 case HIERARCHY_2: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_2; break;
1142 case HIERARCHY_4: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_4; break;
1144 case HIERARCHY_AUTO: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_Auto; break;
1146 PutToDict(dict, "hierarchy_information", tmp);
1149 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1151 if (dest && PyDict_Check(dest))
1153 const char *tmp = "UNKNOWN";
1174 PutToDict(dest, "tuner_state", tmp);
1175 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1176 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1177 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1178 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1179 int sigQualitydB = readFrontendData(signalQualitydB);
1180 if (sigQualitydB == 0x12345678) // not support yet
1182 ePyObject obj=Py_None;
1184 PutToDict(dest, "tuner_signal_quality_db", obj);
1187 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1188 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1192 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1194 if (dest && PyDict_Check(dest))
1202 FRONTENDPARAMETERS front;
1203 if (m_fd == -1 && !original)
1205 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1207 eDebug("FE_GET_FRONTEND failed (%m)");
1211 const FRONTENDPARAMETERS &parm = original || m_simulate ? this->parm : front;
1212 long tmp = eDVBFrontendParametersSatellite::Inversion_Unknown;
1213 switch(parm_inversion & 3)
1216 tmp = eDVBFrontendParametersSatellite::Inversion_On;
1219 tmp = eDVBFrontendParametersSatellite::Inversion_Off;
1223 PutToDict(dest, "inversion", tmp);
1228 fillDictWithSatelliteData(dest, original?parm:front, m_data[FREQ_OFFSET], m_cur_orbpos, m_cur_pol);
1231 fillDictWithCableData(dest, original?parm:front);
1234 fillDictWithTerrestrialData(dest, original?parm:front);
1245 void eDVBFrontend::getFrontendData(ePyObject dest)
1247 if (dest && PyDict_Check(dest))
1250 PutToDict(dest, "tuner_number", m_slotid);
1266 PutToDict(dest, "tuner_type", tmp);
1270 #ifndef FP_IOCTL_GET_ID
1271 #define FP_IOCTL_GET_ID 0
1273 int eDVBFrontend::readInputpower()
1277 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1279 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1280 FILE *f=fopen(proc_name, "r");
1283 if (fscanf(f, "%d", &power) != 1)
1284 eDebug("read %s failed!! (%m)", proc_name);
1286 eDebug("%s is %d\n", proc_name, power);
1291 // open front prozessor
1292 int fp=::open("/dev/dbox/fp0", O_RDWR);
1295 eDebug("couldn't open fp");
1298 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1299 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1301 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1310 bool eDVBFrontend::setSecSequencePos(int steps)
1312 eDebugNoSimulate("set sequence pos %d", steps);
1317 if (m_sec_sequence.current() != m_sec_sequence.end())
1318 ++m_sec_sequence.current();
1323 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1324 --m_sec_sequence.current();
1330 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1333 eDVBFrontend *sec_fe = this;
1334 eDVBRegisteredFrontend *regFE = 0;
1335 long tmp = m_data[LINKED_PREV_PTR];
1338 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1339 sec_fe = prev->m_frontend;
1340 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1341 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1342 int state = sec_fe->m_state;
1343 // workaround to put the kernel frontend thread into idle state!
1344 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1346 sec_fe->closeFrontend(true);
1347 state = sec_fe->m_state;
1349 // sec_fe is closed... we must reopen it here..
1350 if (state == eDVBFrontend::stateClosed)
1358 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1360 long *sec_fe_data = sec_fe->m_data;
1361 // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1362 switch (m_sec_sequence.current()->cmd)
1364 case eSecCommand::SLEEP:
1365 delay = m_sec_sequence.current()++->msec;
1366 eDebugNoSimulate("[SEC] sleep %dms", delay);
1368 case eSecCommand::GOTO:
1369 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1370 ++m_sec_sequence.current();
1372 case eSecCommand::SET_VOLTAGE:
1374 int voltage = m_sec_sequence.current()++->voltage;
1375 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1376 sec_fe->setVoltage(voltage);
1379 case eSecCommand::IF_VOLTAGE_GOTO:
1381 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1382 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1384 ++m_sec_sequence.current();
1387 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1389 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1390 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1392 ++m_sec_sequence.current();
1395 case eSecCommand::IF_TONE_GOTO:
1397 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1398 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1400 ++m_sec_sequence.current();
1403 case eSecCommand::IF_NOT_TONE_GOTO:
1405 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1406 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1408 ++m_sec_sequence.current();
1411 case eSecCommand::SET_TONE:
1412 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1413 sec_fe->setTone(m_sec_sequence.current()++->tone);
1415 case eSecCommand::SEND_DISEQC:
1416 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1417 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1418 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1419 eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1420 if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
1421 eDebugNoSimulate("(DiSEqC reset)");
1422 else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
1423 eDebugNoSimulate("(DiSEqC peripherial power on)");
1425 eDebugNoSimulate("");
1426 ++m_sec_sequence.current();
1428 case eSecCommand::SEND_TONEBURST:
1429 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1430 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1432 case eSecCommand::SET_FRONTEND:
1433 eDebugNoSimulate("[SEC] setFrontend");
1435 ++m_sec_sequence.current();
1437 case eSecCommand::START_TUNE_TIMEOUT:
1440 m_timeout->start(m_sec_sequence.current()->timeout, 1);
1441 ++m_sec_sequence.current();
1444 case eSecCommand::SET_TIMEOUT:
1445 m_timeoutCount = m_sec_sequence.current()++->val;
1446 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1448 case eSecCommand::IF_TIMEOUT_GOTO:
1449 if (!m_timeoutCount)
1451 eDebugNoSimulate("[SEC] rotor timout");
1452 setSecSequencePos(m_sec_sequence.current()->steps);
1455 ++m_sec_sequence.current();
1457 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1459 int idx = m_sec_sequence.current()++->val;
1460 if ( idx == 0 || idx == 1 )
1462 m_idleInputpower[idx] = sec_fe->readInputpower();
1463 eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1466 eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1469 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1471 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1472 int idx = compare.val;
1473 if ( !m_simulate && (idx == 0 || idx == 1) )
1475 int idle = sec_fe->readInputpower();
1476 int diff = abs(idle-m_idleInputpower[idx]);
1479 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1480 setSecSequencePos(compare.steps);
1484 ++m_sec_sequence.current();
1487 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1489 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1492 setSecSequencePos(cmd.steps);
1496 int isLocked = readFrontendData(locked);
1497 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1498 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 50) || !cmd.lastSignal))
1501 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1504 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1505 cmd.lastSignal = signal;
1508 if (cmd.okcount > 4)
1510 eDebugNoSimulate("ok > 4 .. goto %d\n",cmd.steps);
1511 setSecSequencePos(cmd.steps);
1512 m_state = stateLock;
1513 m_stateChanged(this);
1522 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1524 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1526 if (!m_timeoutCount && m_retryCount > 0)
1531 ++m_sec_sequence.current();
1534 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1535 m_runningInputpower = sec_fe->readInputpower();
1536 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1537 ++m_sec_sequence.current();
1539 case eSecCommand::SET_ROTOR_MOVING:
1541 m_sec->setRotorMoving(true);
1542 ++m_sec_sequence.current();
1544 case eSecCommand::SET_ROTOR_STOPPED:
1546 m_sec->setRotorMoving(false);
1547 ++m_sec_sequence.current();
1549 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1551 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1554 setSecSequencePos(cmd.steps);
1557 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1558 const char *txt = cmd.direction ? "running" : "stopped";
1559 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1561 m_runningInputpower,
1564 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1565 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1568 eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1569 if ( cmd.okcount > 6 )
1571 eDebugNoSimulate("[SEC] rotor is %s", txt);
1572 if (setSecSequencePos(cmd.steps))
1578 eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1580 if (!m_timeoutCount && m_retryCount > 0)
1584 ++m_sec_sequence.current();
1587 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1588 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1589 setSecSequencePos(m_sec_sequence.current()->steps);
1591 ++m_sec_sequence.current();
1593 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1594 eDebugNoSimulate("[SEC] invalidate current switch params");
1595 sec_fe_data[CSW] = -1;
1596 sec_fe_data[UCSW] = -1;
1597 sec_fe_data[TONEBURST] = -1;
1598 ++m_sec_sequence.current();
1600 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1601 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1602 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1603 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1604 eDebugNoSimulate("[SEC] update current switch params");
1605 ++m_sec_sequence.current();
1607 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1608 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1609 sec_fe_data[ROTOR_CMD] = -1;
1610 sec_fe_data[ROTOR_POS] = -1;
1611 ++m_sec_sequence.current();
1613 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1614 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1615 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1616 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1617 ++m_sec_sequence.current();
1619 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1620 m_retryCount = m_sec_sequence.current()++->val;
1621 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1623 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1626 eDebugNoSimulate("[SEC] no more rotor retrys");
1627 setSecSequencePos(m_sec_sequence.current()->steps);
1630 ++m_sec_sequence.current();
1632 case eSecCommand::SET_POWER_LIMITING_MODE:
1637 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1638 FILE *f=fopen(proc_name, "w");
1639 if (f) // new interface exist?
1641 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1642 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1643 eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1645 eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1648 else if (sec_fe->m_need_rotor_workaround)
1651 int slotid = sec_fe->m_slotid;
1652 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1654 sprintf(dev, "/dev/i2c/%d", slotid);
1655 else if (slotid == 2)
1656 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1657 else if (slotid == 3)
1658 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1659 int fd = ::open(dev, O_RDWR);
1661 unsigned char data[2];
1662 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1663 if(::read(fd, data, 1) != 1)
1664 eDebugNoSimulate("[SEC] error read lnbp (%m)");
1665 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1667 data[0] |= 0x80; // enable static current limiting
1668 eDebugNoSimulate("[SEC] set static current limiting");
1672 data[0] &= ~0x80; // enable dynamic current limiting
1673 eDebugNoSimulate("[SEC] set dynamic current limiting");
1675 if(::write(fd, data, 1) != 1)
1676 eDebugNoSimulate("[SEC] error write lnbp (%m)");
1680 ++m_sec_sequence.current();
1684 eDebugNoSimulate("[SEC] unhandled sec command %d",
1685 ++m_sec_sequence.current()->cmd);
1686 ++m_sec_sequence.current();
1689 m_tuneTimer->start(delay,true);
1693 if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1697 void eDVBFrontend::setFrontend()
1701 eDebug("setting frontend %d", m_dvbid);
1704 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1706 perror("FE_SET_FRONTEND failed");
1712 RESULT eDVBFrontend::getFrontendType(int &t)
1720 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1725 eWarning("no SEC module active!");
1728 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1731 #if HAVE_DVB_API_VERSION >= 3
1732 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d system %d modulation %d pilot %d, rolloff %d",
1735 feparm.polarisation,
1739 feparm.orbital_position,
1745 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1748 feparm.polarisation,
1752 feparm.orbital_position);
1754 m_cur_pol = feparm.polarisation;
1755 m_cur_orbpos = feparm.orbital_position;
1756 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1757 switch (feparm.inversion)
1759 case eDVBFrontendParametersSatellite::Inversion_On:
1760 parm_inversion = INVERSION_ON;
1762 case eDVBFrontendParametersSatellite::Inversion_Off:
1763 parm_inversion = INVERSION_OFF;
1766 case eDVBFrontendParametersSatellite::Inversion_Unknown:
1767 parm_inversion = INVERSION_AUTO;
1770 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S)
1773 case eDVBFrontendParametersSatellite::FEC_None:
1774 parm_u_qpsk_fec_inner = FEC_NONE;
1776 case eDVBFrontendParametersSatellite::FEC_1_2:
1777 parm_u_qpsk_fec_inner = FEC_1_2;
1779 case eDVBFrontendParametersSatellite::FEC_2_3:
1780 parm_u_qpsk_fec_inner = FEC_2_3;
1782 case eDVBFrontendParametersSatellite::FEC_3_4:
1783 parm_u_qpsk_fec_inner = FEC_3_4;
1785 case eDVBFrontendParametersSatellite::FEC_5_6:
1786 parm_u_qpsk_fec_inner = FEC_5_6;
1788 case eDVBFrontendParametersSatellite::FEC_7_8:
1789 parm_u_qpsk_fec_inner = FEC_7_8;
1792 eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
1793 case eDVBFrontendParametersSatellite::FEC_Auto:
1794 parm_u_qpsk_fec_inner = FEC_AUTO;
1797 #if HAVE_DVB_API_VERSION >= 3
1802 case eDVBFrontendParametersSatellite::FEC_1_2:
1803 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1805 case eDVBFrontendParametersSatellite::FEC_2_3:
1806 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1808 case eDVBFrontendParametersSatellite::FEC_3_4:
1809 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1811 case eDVBFrontendParametersSatellite::FEC_3_5:
1812 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1814 case eDVBFrontendParametersSatellite::FEC_4_5:
1815 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1817 case eDVBFrontendParametersSatellite::FEC_5_6:
1818 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1820 case eDVBFrontendParametersSatellite::FEC_7_8:
1821 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1823 case eDVBFrontendParametersSatellite::FEC_8_9:
1824 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1826 case eDVBFrontendParametersSatellite::FEC_9_10:
1827 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1830 eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
1833 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1834 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1835 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation_8PSK) {
1836 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1837 // 8PSK fec driver values are decimal 9 bigger
1841 // FIXME !!! get frequency range from tuner
1842 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1844 eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1847 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
1852 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1854 #if HAVE_DVB_API_VERSION < 3
1855 parm_frequency = feparm.frequency;
1857 parm_frequency = feparm.frequency * 1000;
1859 parm_u_qam_symbol_rate = feparm.symbol_rate;
1860 switch (feparm.modulation)
1862 case eDVBFrontendParametersCable::Modulation_QAM16:
1863 parm_u_qam_modulation = QAM_16;
1865 case eDVBFrontendParametersCable::Modulation_QAM32:
1866 parm_u_qam_modulation = QAM_32;
1868 case eDVBFrontendParametersCable::Modulation_QAM64:
1869 parm_u_qam_modulation = QAM_64;
1871 case eDVBFrontendParametersCable::Modulation_QAM128:
1872 parm_u_qam_modulation = QAM_128;
1874 case eDVBFrontendParametersCable::Modulation_QAM256:
1875 parm_u_qam_modulation = QAM_256;
1878 case eDVBFrontendParametersCable::Modulation_Auto:
1879 parm_u_qam_modulation = QAM_AUTO;
1882 switch (feparm.inversion)
1884 case eDVBFrontendParametersCable::Inversion_On:
1885 parm_inversion = INVERSION_ON;
1887 case eDVBFrontendParametersCable::Inversion_Off:
1888 parm_inversion = INVERSION_OFF;
1891 case eDVBFrontendParametersCable::Inversion_Unknown:
1892 parm_inversion = INVERSION_AUTO;
1895 switch (feparm.fec_inner)
1897 case eDVBFrontendParametersCable::FEC_None:
1898 parm_u_qam_fec_inner = FEC_NONE;
1900 case eDVBFrontendParametersCable::FEC_1_2:
1901 parm_u_qam_fec_inner = FEC_1_2;
1903 case eDVBFrontendParametersCable::FEC_2_3:
1904 parm_u_qam_fec_inner = FEC_2_3;
1906 case eDVBFrontendParametersCable::FEC_3_4:
1907 parm_u_qam_fec_inner = FEC_3_4;
1909 case eDVBFrontendParametersCable::FEC_5_6:
1910 parm_u_qam_fec_inner = FEC_5_6;
1912 case eDVBFrontendParametersCable::FEC_7_8:
1913 parm_u_qam_fec_inner = FEC_7_8;
1915 #if HAVE_DVB_API_VERSION >= 3
1916 case eDVBFrontendParametersCable::FEC_8_9:
1917 parm_u_qam_fec_inner = FEC_8_9;
1921 case eDVBFrontendParametersCable::FEC_Auto:
1922 parm_u_qam_fec_inner = FEC_AUTO;
1925 eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
1926 parm_frequency/1000,
1927 parm_u_qam_symbol_rate,
1928 parm_u_qam_fec_inner,
1929 parm_u_qam_modulation,
1934 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
1936 parm_frequency = feparm.frequency;
1938 switch (feparm.bandwidth)
1940 case eDVBFrontendParametersTerrestrial::Bandwidth_8MHz:
1941 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
1943 case eDVBFrontendParametersTerrestrial::Bandwidth_7MHz:
1944 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
1946 case eDVBFrontendParametersTerrestrial::Bandwidth_6MHz:
1947 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
1950 case eDVBFrontendParametersTerrestrial::Bandwidth_Auto:
1951 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
1954 switch (feparm.code_rate_LP)
1956 case eDVBFrontendParametersTerrestrial::FEC_1_2:
1957 parm_u_ofdm_code_rate_LP = FEC_1_2;
1959 case eDVBFrontendParametersTerrestrial::FEC_2_3:
1960 parm_u_ofdm_code_rate_LP = FEC_2_3;
1962 case eDVBFrontendParametersTerrestrial::FEC_3_4:
1963 parm_u_ofdm_code_rate_LP = FEC_3_4;
1965 case eDVBFrontendParametersTerrestrial::FEC_5_6:
1966 parm_u_ofdm_code_rate_LP = FEC_5_6;
1968 case eDVBFrontendParametersTerrestrial::FEC_7_8:
1969 parm_u_ofdm_code_rate_LP = FEC_7_8;
1972 case eDVBFrontendParametersTerrestrial::FEC_Auto:
1973 parm_u_ofdm_code_rate_LP = FEC_AUTO;
1976 switch (feparm.code_rate_HP)
1978 case eDVBFrontendParametersTerrestrial::FEC_1_2:
1979 parm_u_ofdm_code_rate_HP = FEC_1_2;
1981 case eDVBFrontendParametersTerrestrial::FEC_2_3:
1982 parm_u_ofdm_code_rate_HP = FEC_2_3;
1984 case eDVBFrontendParametersTerrestrial::FEC_3_4:
1985 parm_u_ofdm_code_rate_HP = FEC_3_4;
1987 case eDVBFrontendParametersTerrestrial::FEC_5_6:
1988 parm_u_ofdm_code_rate_HP = FEC_5_6;
1990 case eDVBFrontendParametersTerrestrial::FEC_7_8:
1991 parm_u_ofdm_code_rate_HP = FEC_7_8;
1994 case eDVBFrontendParametersTerrestrial::FEC_Auto:
1995 parm_u_ofdm_code_rate_HP = FEC_AUTO;
1998 switch (feparm.modulation)
2000 case eDVBFrontendParametersTerrestrial::Modulation_QPSK:
2001 parm_u_ofdm_constellation = QPSK;
2003 case eDVBFrontendParametersTerrestrial::Modulation_QAM16:
2004 parm_u_ofdm_constellation = QAM_16;
2006 case eDVBFrontendParametersTerrestrial::Modulation_QAM64:
2007 parm_u_ofdm_constellation = QAM_64;
2010 case eDVBFrontendParametersTerrestrial::Modulation_Auto:
2011 parm_u_ofdm_constellation = QAM_AUTO;
2014 switch (feparm.transmission_mode)
2016 case eDVBFrontendParametersTerrestrial::TransmissionMode_2k:
2017 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2019 case eDVBFrontendParametersTerrestrial::TransmissionMode_8k:
2020 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2023 case eDVBFrontendParametersTerrestrial::TransmissionMode_Auto:
2024 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2027 switch (feparm.guard_interval)
2029 case eDVBFrontendParametersTerrestrial::GuardInterval_1_32:
2030 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2032 case eDVBFrontendParametersTerrestrial::GuardInterval_1_16:
2033 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2035 case eDVBFrontendParametersTerrestrial::GuardInterval_1_8:
2036 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2038 case eDVBFrontendParametersTerrestrial::GuardInterval_1_4:
2039 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2042 case eDVBFrontendParametersTerrestrial::GuardInterval_Auto:
2043 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2046 switch (feparm.hierarchy)
2048 case eDVBFrontendParametersTerrestrial::Hierarchy_None:
2049 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2051 case eDVBFrontendParametersTerrestrial::Hierarchy_1:
2052 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2054 case eDVBFrontendParametersTerrestrial::Hierarchy_2:
2055 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2057 case eDVBFrontendParametersTerrestrial::Hierarchy_4:
2058 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2061 case eDVBFrontendParametersTerrestrial::Hierarchy_Auto:
2062 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2065 switch (feparm.inversion)
2067 case eDVBFrontendParametersTerrestrial::Inversion_On:
2068 parm_inversion = INVERSION_ON;
2070 case eDVBFrontendParametersTerrestrial::Inversion_Off:
2071 parm_inversion = INVERSION_OFF;
2074 case eDVBFrontendParametersTerrestrial::Inversion_Unknown:
2075 parm_inversion = INVERSION_AUTO;
2081 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2083 unsigned int timeout = 5000;
2084 eDebugNoSimulate("(%d)tune", m_dvbid);
2090 if (!m_sn && !m_simulate)
2092 eDebug("no frontend device opened... do not try to tune !!!");
2106 m_sec_sequence.clear();
2108 where.calcLockTimeout(timeout);
2114 eDVBFrontendParametersSatellite feparm;
2115 if (where.getDVBS(feparm))
2117 eDebug("no dvbs data!");
2122 m_sec->setRotorMoving(false);
2123 res=prepare_sat(feparm, timeout);
2131 eDVBFrontendParametersCable feparm;
2132 if (where.getDVBC(feparm))
2137 res=prepare_cable(feparm);
2141 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2142 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2147 eDVBFrontendParametersTerrestrial feparm;
2148 if (where.getDVBT(feparm))
2150 eDebug("no -T data");
2154 res=prepare_terrestrial(feparm);
2158 std::string enable_5V;
2159 char configStr[255];
2160 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2161 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2162 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2163 if (enable_5V == "True")
2164 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2166 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2167 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2173 m_sec_sequence.current() = m_sec_sequence.begin();
2177 m_tuneTimer->start(0,true);
2178 if (m_state != stateTuning)
2181 m_state = stateTuning;
2182 m_stateChanged(this);
2191 m_tuneTimer->stop();
2195 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2197 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2201 RESULT eDVBFrontend::setVoltage(int voltage)
2203 if (m_type == feCable)
2205 #if HAVE_DVB_API_VERSION < 3
2208 bool increased=false;
2209 fe_sec_voltage_t vlt;
2211 m_data[CUR_VOLTAGE]=voltage;
2215 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2216 vlt = SEC_VOLTAGE_OFF;
2219 #if HAVE_DVB_API_VERSION < 3
2220 vlt = SEC_VOLTAGE_13_5;
2226 vlt = SEC_VOLTAGE_13;
2229 #if HAVE_DVB_API_VERSION < 3
2230 vlt = SEC_VOLTAGE_18_5;
2236 vlt = SEC_VOLTAGE_18;
2243 #if HAVE_DVB_API_VERSION < 3
2244 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2246 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2247 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2248 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2252 RESULT eDVBFrontend::getState(int &state)
2258 RESULT eDVBFrontend::setTone(int t)
2260 if (m_type != feSatellite)
2262 #if HAVE_DVB_API_VERSION < 3
2265 fe_sec_tone_mode_t tone;
2274 tone = SEC_TONE_OFF;
2281 #if HAVE_DVB_API_VERSION < 3
2282 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2284 return ::ioctl(m_fd, FE_SET_TONE, tone);
2288 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2289 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2292 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2296 #if HAVE_DVB_API_VERSION < 3
2297 struct secCommand cmd;
2298 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2299 cmd.u.diseqc.cmdtype = diseqc.data[0];
2300 cmd.u.diseqc.addr = diseqc.data[1];
2301 cmd.u.diseqc.cmd = diseqc.data[2];
2302 cmd.u.diseqc.numParams = diseqc.len-3;
2303 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2304 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2306 struct dvb_diseqc_master_cmd cmd;
2307 memcpy(cmd.msg, diseqc.data, diseqc.len);
2308 cmd.msg_len = diseqc.len;
2309 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2315 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2316 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2318 RESULT eDVBFrontend::sendToneburst(int burst)
2322 #if HAVE_DVB_API_VERSION < 3
2323 secMiniCmd cmd = SEC_MINI_NONE;
2325 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2327 if ( burst == eDVBSatelliteDiseqcParameters::A )
2329 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2331 #if HAVE_DVB_API_VERSION < 3
2332 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2335 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2341 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2347 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2349 m_sec_sequence = list;
2353 RESULT eDVBFrontend::getData(int num, long &data)
2355 if ( num < NUM_DATA_ENTRIES )
2363 RESULT eDVBFrontend::setData(int num, long val)
2365 if ( num < NUM_DATA_ENTRIES )
2373 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2376 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2378 if (m_type == eDVBFrontend::feSatellite)
2381 eDVBFrontendParametersSatellite sat_parm;
2382 int ret = feparm->getDVBS(sat_parm);
2384 if (sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S2 && !m_can_handle_dvbs2)
2386 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2387 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S && m_can_handle_dvbs2)
2391 else if (m_type == eDVBFrontend::feCable)
2392 return 2; // more prio for cable frontends
2393 else if (m_type == eDVBFrontend::feTerrestrial)
2398 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2400 ePyObject Id, Descr, Enabled, IsDVBS2;
2401 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4)
2403 Id = PyTuple_GET_ITEM(obj, 0);
2404 Descr = PyTuple_GET_ITEM(obj, 1);
2405 Enabled = PyTuple_GET_ITEM(obj, 2);
2406 IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2407 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2))
2409 strcpy(m_description, PyString_AS_STRING(Descr));
2410 m_slotid = PyInt_AsLong(Id);
2411 m_enabled = Enabled == Py_True;
2412 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2413 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2414 !!strstr(m_description, "Alps BSBE2") ||
2415 !!strstr(m_description, "Alps -S") ||
2416 !!strstr(m_description, "BCM4501");
2417 m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2418 eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2419 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2422 PyErr_SetString(PyExc_StandardError,
2423 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");
2427 RESULT eDVBFrontend::turnOffSatCR(int satcr)
2429 eSecCommandList sec_sequence;
2430 // check if voltage is disabled
2431 eSecCommand::pair compare;
2432 compare.steps = +9; //nothing to do
2433 compare.voltage = iDVBFrontend::voltageOff;
2434 sec_sequence.push_back( eSecCommand(eSecCommand::IF_NOT_VOLTAGE_GOTO, compare) );
2435 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2436 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50 ) );
2438 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage18_5) );
2439 sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
2440 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 250) );
2442 eDVBDiseqcCommand diseqc;
2443 memset(diseqc.data, 0, MAX_DISEQC_LENGTH);
2445 diseqc.data[0] = 0xE0;
2446 diseqc.data[1] = 0x10;
2447 diseqc.data[2] = 0x5A;
2448 diseqc.data[3] = satcr << 5;
2449 diseqc.data[4] = 0x00;
2451 sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
2452 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50+20+14*diseqc.len) );
2453 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2454 setSecSequence(sec_sequence);
2458 RESULT eDVBFrontend::ScanSatCR()
2462 setTone(iDVBFrontend::toneOff);