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, eDVBFrontend *fe)
968 fe->getData(eDVBFrontend::FREQ_OFFSET, freq_offset);
969 int frequency = parm_frequency + freq_offset;
970 PutToDict(dict, "frequency", frequency);
971 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
972 switch(parm_u_qpsk_fec_inner)
974 case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
975 case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
976 case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
977 case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
978 case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
979 case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
981 case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
982 #if HAVE_DVB_API_VERSION >=3
983 case FEC_S2_8PSK_1_2:
984 case FEC_S2_QPSK_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
985 case FEC_S2_8PSK_2_3:
986 case FEC_S2_QPSK_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
987 case FEC_S2_8PSK_3_4:
988 case FEC_S2_QPSK_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
989 case FEC_S2_8PSK_5_6:
990 case FEC_S2_QPSK_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
991 case FEC_S2_8PSK_7_8:
992 case FEC_S2_QPSK_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
993 case FEC_S2_8PSK_8_9:
994 case FEC_S2_QPSK_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
995 case FEC_S2_8PSK_3_5:
996 case FEC_S2_QPSK_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
997 case FEC_S2_8PSK_4_5:
998 case FEC_S2_QPSK_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
999 case FEC_S2_8PSK_9_10:
1000 case FEC_S2_QPSK_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1003 PutToDict(dict, "fec_inner", tmp);
1004 #if HAVE_DVB_API_VERSION >=3
1005 PutToDict(dict, "modulation",
1006 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ?
1007 eDVBFrontendParametersSatellite::Modulation_8PSK :
1008 eDVBFrontendParametersSatellite::Modulation_QPSK );
1009 if (parm_u_qpsk_fec_inner > FEC_AUTO)
1011 switch(parm_inversion & 0xc)
1013 default: // unknown rolloff
1014 case 0: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1015 case 4: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1016 case 8: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1018 PutToDict(dict, "rolloff", tmp);
1019 switch(parm_inversion & 0x30)
1021 case 0: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1022 case 0x10: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1023 case 0x20: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1025 PutToDict(dict, "pilot", tmp);
1026 tmp = eDVBFrontendParametersSatellite::System_DVB_S2;
1029 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1031 PutToDict(dict, "modulation", eDVBFrontendParametersSatellite::Modulation_QPSK );
1032 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1034 PutToDict(dict, "system", tmp);
1037 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1040 #if HAVE_DVB_API_VERSION < 3
1041 PutToDict(dict, "frequency", parm_frequency);
1043 PutToDict(dict, "frequency", parm_frequency/1000);
1045 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1046 switch(parm_u_qam_fec_inner)
1048 case FEC_NONE: tmp = eDVBFrontendParametersCable::FEC_None; break;
1049 case FEC_1_2: tmp = eDVBFrontendParametersCable::FEC_1_2; break;
1050 case FEC_2_3: tmp = eDVBFrontendParametersCable::FEC_2_3; break;
1051 case FEC_3_4: tmp = eDVBFrontendParametersCable::FEC_3_4; break;
1052 case FEC_5_6: tmp = eDVBFrontendParametersCable::FEC_5_6; break;
1053 case FEC_7_8: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1054 #if HAVE_DVB_API_VERSION >= 3
1055 case FEC_8_9: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1058 case FEC_AUTO: tmp = eDVBFrontendParametersCable::FEC_Auto; break;
1060 PutToDict(dict, "fec_inner", tmp);
1061 switch(parm_u_qam_modulation)
1063 case QAM_16: tmp = eDVBFrontendParametersCable::Modulation_QAM16; break;
1064 case QAM_32: tmp = eDVBFrontendParametersCable::Modulation_QAM32; break;
1065 case QAM_64: tmp = eDVBFrontendParametersCable::Modulation_QAM64; break;
1066 case QAM_128: tmp = eDVBFrontendParametersCable::Modulation_QAM128; break;
1067 case QAM_256: tmp = eDVBFrontendParametersCable::Modulation_QAM256; break;
1069 case QAM_AUTO: tmp = eDVBFrontendParametersCable::Modulation_Auto; break;
1071 PutToDict(dict, "modulation", tmp);
1074 void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1077 PutToDict(dict, "frequency", parm_frequency);
1078 switch (parm_u_ofdm_bandwidth)
1080 case BANDWIDTH_8_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_8MHz; break;
1081 case BANDWIDTH_7_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_7MHz; break;
1082 case BANDWIDTH_6_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_6MHz; break;
1084 case BANDWIDTH_AUTO: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_Auto; break;
1086 PutToDict(dict, "bandwidth", tmp);
1087 switch (parm_u_ofdm_code_rate_LP)
1089 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1090 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1091 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1092 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1093 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1095 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1097 PutToDict(dict, "code_rate_lp", tmp);
1098 switch (parm_u_ofdm_code_rate_HP)
1100 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1101 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1102 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1103 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1104 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1106 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1108 PutToDict(dict, "code_rate_hp", tmp);
1109 switch (parm_u_ofdm_constellation)
1111 case QPSK: tmp = eDVBFrontendParametersTerrestrial::Modulation_QPSK; break;
1112 case QAM_16: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM16; break;
1113 case QAM_64: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM64; break;
1115 case QAM_AUTO: tmp = eDVBFrontendParametersTerrestrial::Modulation_Auto; break;
1117 PutToDict(dict, "constellation", tmp);
1118 switch (parm_u_ofdm_transmission_mode)
1120 case TRANSMISSION_MODE_2K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_2k; break;
1121 case TRANSMISSION_MODE_8K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_8k; break;
1123 case TRANSMISSION_MODE_AUTO: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto; break;
1125 PutToDict(dict, "transmission_mode", tmp);
1126 switch (parm_u_ofdm_guard_interval)
1128 case GUARD_INTERVAL_1_32: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_32; break;
1129 case GUARD_INTERVAL_1_16: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_16; break;
1130 case GUARD_INTERVAL_1_8: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_8; break;
1131 case GUARD_INTERVAL_1_4: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_4; break;
1133 case GUARD_INTERVAL_AUTO: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_Auto; break;
1135 PutToDict(dict, "guard_interval", tmp);
1136 switch (parm_u_ofdm_hierarchy_information)
1138 case HIERARCHY_NONE: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_None; break;
1139 case HIERARCHY_1: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_1; break;
1140 case HIERARCHY_2: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_2; break;
1141 case HIERARCHY_4: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_4; break;
1143 case HIERARCHY_AUTO: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_Auto; break;
1145 PutToDict(dict, "hierarchy_information", tmp);
1148 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1150 if (dest && PyDict_Check(dest))
1152 const char *tmp = "UNKNOWN";
1173 PutToDict(dest, "tuner_state", tmp);
1174 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1175 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1176 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1177 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1178 int sigQualitydB = readFrontendData(signalQualitydB);
1179 if (sigQualitydB == 0x12345678) // not support yet
1181 ePyObject obj=Py_None;
1183 PutToDict(dest, "tuner_signal_quality_db", obj);
1186 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1187 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1191 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1193 if (dest && PyDict_Check(dest))
1201 FRONTENDPARAMETERS front;
1202 if (m_fd == -1 && !original)
1204 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1206 eDebug("FE_GET_FRONTEND failed (%m)");
1210 const FRONTENDPARAMETERS &parm = original || m_simulate ? this->parm : front;
1211 long tmp = eDVBFrontendParametersSatellite::Inversion_Unknown;
1212 switch(parm_inversion & 3)
1215 tmp = eDVBFrontendParametersSatellite::Inversion_On;
1218 tmp = eDVBFrontendParametersSatellite::Inversion_Off;
1222 PutToDict(dest, "inversion", tmp);
1227 fillDictWithSatelliteData(dest, original?parm:front, this);
1230 fillDictWithCableData(dest, original?parm:front);
1233 fillDictWithTerrestrialData(dest, original?parm:front);
1244 void eDVBFrontend::getFrontendData(ePyObject dest)
1246 if (dest && PyDict_Check(dest))
1249 PutToDict(dest, "tuner_number", m_slotid);
1265 PutToDict(dest, "tuner_type", tmp);
1269 #ifndef FP_IOCTL_GET_ID
1270 #define FP_IOCTL_GET_ID 0
1272 int eDVBFrontend::readInputpower()
1276 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1278 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1279 FILE *f=fopen(proc_name, "r");
1282 if (fscanf(f, "%d", &power) != 1)
1283 eDebug("read %s failed!! (%m)", proc_name);
1285 eDebug("%s is %d\n", proc_name, power);
1290 // open front prozessor
1291 int fp=::open("/dev/dbox/fp0", O_RDWR);
1294 eDebug("couldn't open fp");
1297 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1298 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1300 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1309 bool eDVBFrontend::setSecSequencePos(int steps)
1311 eDebugNoSimulate("set sequence pos %d", steps);
1316 if (m_sec_sequence.current() != m_sec_sequence.end())
1317 ++m_sec_sequence.current();
1322 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1323 --m_sec_sequence.current();
1329 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1332 eDVBFrontend *sec_fe = this;
1333 eDVBRegisteredFrontend *regFE = 0;
1334 long tmp = m_data[LINKED_PREV_PTR];
1337 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1338 sec_fe = prev->m_frontend;
1339 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1340 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1341 int state = sec_fe->m_state;
1342 // workaround to put the kernel frontend thread into idle state!
1343 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1345 sec_fe->closeFrontend(true);
1346 state = sec_fe->m_state;
1348 // sec_fe is closed... we must reopen it here..
1349 if (state == eDVBFrontend::stateClosed)
1357 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1359 long *sec_fe_data = sec_fe->m_data;
1360 // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1361 switch (m_sec_sequence.current()->cmd)
1363 case eSecCommand::SLEEP:
1364 delay = m_sec_sequence.current()++->msec;
1365 eDebugNoSimulate("[SEC] sleep %dms", delay);
1367 case eSecCommand::GOTO:
1368 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1369 ++m_sec_sequence.current();
1371 case eSecCommand::SET_VOLTAGE:
1373 int voltage = m_sec_sequence.current()++->voltage;
1374 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1375 sec_fe->setVoltage(voltage);
1378 case eSecCommand::IF_VOLTAGE_GOTO:
1380 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1381 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1383 ++m_sec_sequence.current();
1386 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1388 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1389 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1391 ++m_sec_sequence.current();
1394 case eSecCommand::IF_TONE_GOTO:
1396 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1397 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1399 ++m_sec_sequence.current();
1402 case eSecCommand::IF_NOT_TONE_GOTO:
1404 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1405 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1407 ++m_sec_sequence.current();
1410 case eSecCommand::SET_TONE:
1411 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1412 sec_fe->setTone(m_sec_sequence.current()++->tone);
1414 case eSecCommand::SEND_DISEQC:
1415 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1416 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1417 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1418 eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1419 if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
1420 eDebugNoSimulate("(DiSEqC reset)");
1421 else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
1422 eDebugNoSimulate("(DiSEqC peripherial power on)");
1424 eDebugNoSimulate("");
1425 ++m_sec_sequence.current();
1427 case eSecCommand::SEND_TONEBURST:
1428 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1429 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1431 case eSecCommand::SET_FRONTEND:
1432 eDebugNoSimulate("[SEC] setFrontend");
1434 ++m_sec_sequence.current();
1436 case eSecCommand::START_TUNE_TIMEOUT:
1439 m_timeout->start(m_sec_sequence.current()->timeout, 1);
1440 ++m_sec_sequence.current();
1443 case eSecCommand::SET_TIMEOUT:
1444 m_timeoutCount = m_sec_sequence.current()++->val;
1445 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1447 case eSecCommand::IF_TIMEOUT_GOTO:
1448 if (!m_timeoutCount)
1450 eDebugNoSimulate("[SEC] rotor timout");
1451 setSecSequencePos(m_sec_sequence.current()->steps);
1454 ++m_sec_sequence.current();
1456 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1458 int idx = m_sec_sequence.current()++->val;
1459 if ( idx == 0 || idx == 1 )
1461 m_idleInputpower[idx] = sec_fe->readInputpower();
1462 eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1465 eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1468 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1470 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1471 int idx = compare.val;
1472 if ( !m_simulate && (idx == 0 || idx == 1) )
1474 int idle = sec_fe->readInputpower();
1475 int diff = abs(idle-m_idleInputpower[idx]);
1478 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1479 setSecSequencePos(compare.steps);
1483 ++m_sec_sequence.current();
1486 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1488 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1491 setSecSequencePos(cmd.steps);
1495 int isLocked = readFrontendData(locked);
1496 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1497 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 50) || !cmd.lastSignal))
1500 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1503 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1504 cmd.lastSignal = signal;
1507 if (cmd.okcount > 4)
1509 eDebugNoSimulate("ok > 4 .. goto %d\n",cmd.steps);
1510 setSecSequencePos(cmd.steps);
1511 m_state = stateLock;
1512 m_stateChanged(this);
1521 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1523 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1525 if (!m_timeoutCount && m_retryCount > 0)
1530 ++m_sec_sequence.current();
1533 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1534 m_runningInputpower = sec_fe->readInputpower();
1535 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1536 ++m_sec_sequence.current();
1538 case eSecCommand::SET_ROTOR_MOVING:
1540 m_sec->setRotorMoving(true);
1541 ++m_sec_sequence.current();
1543 case eSecCommand::SET_ROTOR_STOPPED:
1545 m_sec->setRotorMoving(false);
1546 ++m_sec_sequence.current();
1548 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1550 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1553 setSecSequencePos(cmd.steps);
1556 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1557 const char *txt = cmd.direction ? "running" : "stopped";
1558 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1560 m_runningInputpower,
1563 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1564 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1567 eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1568 if ( cmd.okcount > 6 )
1570 eDebugNoSimulate("[SEC] rotor is %s", txt);
1571 if (setSecSequencePos(cmd.steps))
1577 eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1579 if (!m_timeoutCount && m_retryCount > 0)
1583 ++m_sec_sequence.current();
1586 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1587 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1588 setSecSequencePos(m_sec_sequence.current()->steps);
1590 ++m_sec_sequence.current();
1592 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1593 eDebugNoSimulate("[SEC] invalidate current switch params");
1594 sec_fe_data[CSW] = -1;
1595 sec_fe_data[UCSW] = -1;
1596 sec_fe_data[TONEBURST] = -1;
1597 ++m_sec_sequence.current();
1599 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1600 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1601 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1602 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1603 eDebugNoSimulate("[SEC] update current switch params");
1604 ++m_sec_sequence.current();
1606 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1607 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1608 sec_fe_data[ROTOR_CMD] = -1;
1609 sec_fe_data[ROTOR_POS] = -1;
1610 ++m_sec_sequence.current();
1612 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1613 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1614 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1615 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1616 ++m_sec_sequence.current();
1618 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1619 m_retryCount = m_sec_sequence.current()++->val;
1620 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1622 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1625 eDebugNoSimulate("[SEC] no more rotor retrys");
1626 setSecSequencePos(m_sec_sequence.current()->steps);
1629 ++m_sec_sequence.current();
1631 case eSecCommand::SET_POWER_LIMITING_MODE:
1636 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1637 FILE *f=fopen(proc_name, "w");
1638 if (f) // new interface exist?
1640 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1641 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1642 eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1644 eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1647 else if (sec_fe->m_need_rotor_workaround)
1650 int slotid = sec_fe->m_slotid;
1651 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1653 sprintf(dev, "/dev/i2c/%d", slotid);
1654 else if (slotid == 2)
1655 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1656 else if (slotid == 3)
1657 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1658 int fd = ::open(dev, O_RDWR);
1660 unsigned char data[2];
1661 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1662 if(::read(fd, data, 1) != 1)
1663 eDebugNoSimulate("[SEC] error read lnbp (%m)");
1664 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1666 data[0] |= 0x80; // enable static current limiting
1667 eDebugNoSimulate("[SEC] set static current limiting");
1671 data[0] &= ~0x80; // enable dynamic current limiting
1672 eDebugNoSimulate("[SEC] set dynamic current limiting");
1674 if(::write(fd, data, 1) != 1)
1675 eDebugNoSimulate("[SEC] error write lnbp (%m)");
1679 ++m_sec_sequence.current();
1683 eDebugNoSimulate("[SEC] unhandled sec command %d",
1684 ++m_sec_sequence.current()->cmd);
1685 ++m_sec_sequence.current();
1688 m_tuneTimer->start(delay,true);
1692 if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1696 void eDVBFrontend::setFrontend()
1700 eDebug("setting frontend %d", m_dvbid);
1703 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1705 perror("FE_SET_FRONTEND failed");
1711 RESULT eDVBFrontend::getFrontendType(int &t)
1719 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1724 eWarning("no SEC module active!");
1727 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1730 #if HAVE_DVB_API_VERSION >= 3
1731 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",
1734 feparm.polarisation,
1738 feparm.orbital_position,
1744 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1747 feparm.polarisation,
1751 feparm.orbital_position);
1753 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1754 switch (feparm.inversion)
1756 case eDVBFrontendParametersSatellite::Inversion_On:
1757 parm_inversion = INVERSION_ON;
1759 case eDVBFrontendParametersSatellite::Inversion_Off:
1760 parm_inversion = INVERSION_OFF;
1763 case eDVBFrontendParametersSatellite::Inversion_Unknown:
1764 parm_inversion = INVERSION_AUTO;
1767 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S)
1770 case eDVBFrontendParametersSatellite::FEC_None:
1771 parm_u_qpsk_fec_inner = FEC_NONE;
1773 case eDVBFrontendParametersSatellite::FEC_1_2:
1774 parm_u_qpsk_fec_inner = FEC_1_2;
1776 case eDVBFrontendParametersSatellite::FEC_2_3:
1777 parm_u_qpsk_fec_inner = FEC_2_3;
1779 case eDVBFrontendParametersSatellite::FEC_3_4:
1780 parm_u_qpsk_fec_inner = FEC_3_4;
1782 case eDVBFrontendParametersSatellite::FEC_5_6:
1783 parm_u_qpsk_fec_inner = FEC_5_6;
1785 case eDVBFrontendParametersSatellite::FEC_7_8:
1786 parm_u_qpsk_fec_inner = FEC_7_8;
1789 eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
1790 case eDVBFrontendParametersSatellite::FEC_Auto:
1791 parm_u_qpsk_fec_inner = FEC_AUTO;
1794 #if HAVE_DVB_API_VERSION >= 3
1799 case eDVBFrontendParametersSatellite::FEC_1_2:
1800 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1802 case eDVBFrontendParametersSatellite::FEC_2_3:
1803 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1805 case eDVBFrontendParametersSatellite::FEC_3_4:
1806 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1808 case eDVBFrontendParametersSatellite::FEC_3_5:
1809 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1811 case eDVBFrontendParametersSatellite::FEC_4_5:
1812 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1814 case eDVBFrontendParametersSatellite::FEC_5_6:
1815 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1817 case eDVBFrontendParametersSatellite::FEC_7_8:
1818 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1820 case eDVBFrontendParametersSatellite::FEC_8_9:
1821 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1823 case eDVBFrontendParametersSatellite::FEC_9_10:
1824 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1827 eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
1830 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1831 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1832 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation_8PSK) {
1833 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1834 // 8PSK fec driver values are decimal 9 bigger
1838 // FIXME !!! get frequency range from tuner
1839 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1841 eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1844 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
1849 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1851 #if HAVE_DVB_API_VERSION < 3
1852 parm_frequency = feparm.frequency;
1854 parm_frequency = feparm.frequency * 1000;
1856 parm_u_qam_symbol_rate = feparm.symbol_rate;
1857 switch (feparm.modulation)
1859 case eDVBFrontendParametersCable::Modulation_QAM16:
1860 parm_u_qam_modulation = QAM_16;
1862 case eDVBFrontendParametersCable::Modulation_QAM32:
1863 parm_u_qam_modulation = QAM_32;
1865 case eDVBFrontendParametersCable::Modulation_QAM64:
1866 parm_u_qam_modulation = QAM_64;
1868 case eDVBFrontendParametersCable::Modulation_QAM128:
1869 parm_u_qam_modulation = QAM_128;
1871 case eDVBFrontendParametersCable::Modulation_QAM256:
1872 parm_u_qam_modulation = QAM_256;
1875 case eDVBFrontendParametersCable::Modulation_Auto:
1876 parm_u_qam_modulation = QAM_AUTO;
1879 switch (feparm.inversion)
1881 case eDVBFrontendParametersCable::Inversion_On:
1882 parm_inversion = INVERSION_ON;
1884 case eDVBFrontendParametersCable::Inversion_Off:
1885 parm_inversion = INVERSION_OFF;
1888 case eDVBFrontendParametersCable::Inversion_Unknown:
1889 parm_inversion = INVERSION_AUTO;
1892 switch (feparm.fec_inner)
1894 case eDVBFrontendParametersCable::FEC_None:
1895 parm_u_qam_fec_inner = FEC_NONE;
1897 case eDVBFrontendParametersCable::FEC_1_2:
1898 parm_u_qam_fec_inner = FEC_1_2;
1900 case eDVBFrontendParametersCable::FEC_2_3:
1901 parm_u_qam_fec_inner = FEC_2_3;
1903 case eDVBFrontendParametersCable::FEC_3_4:
1904 parm_u_qam_fec_inner = FEC_3_4;
1906 case eDVBFrontendParametersCable::FEC_5_6:
1907 parm_u_qam_fec_inner = FEC_5_6;
1909 case eDVBFrontendParametersCable::FEC_7_8:
1910 parm_u_qam_fec_inner = FEC_7_8;
1912 #if HAVE_DVB_API_VERSION >= 3
1913 case eDVBFrontendParametersCable::FEC_8_9:
1914 parm_u_qam_fec_inner = FEC_8_9;
1918 case eDVBFrontendParametersCable::FEC_Auto:
1919 parm_u_qam_fec_inner = FEC_AUTO;
1922 eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
1923 parm_frequency/1000,
1924 parm_u_qam_symbol_rate,
1925 parm_u_qam_fec_inner,
1926 parm_u_qam_modulation,
1931 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
1933 parm_frequency = feparm.frequency;
1935 switch (feparm.bandwidth)
1937 case eDVBFrontendParametersTerrestrial::Bandwidth_8MHz:
1938 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
1940 case eDVBFrontendParametersTerrestrial::Bandwidth_7MHz:
1941 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
1943 case eDVBFrontendParametersTerrestrial::Bandwidth_6MHz:
1944 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
1947 case eDVBFrontendParametersTerrestrial::Bandwidth_Auto:
1948 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
1951 switch (feparm.code_rate_LP)
1953 case eDVBFrontendParametersTerrestrial::FEC_1_2:
1954 parm_u_ofdm_code_rate_LP = FEC_1_2;
1956 case eDVBFrontendParametersTerrestrial::FEC_2_3:
1957 parm_u_ofdm_code_rate_LP = FEC_2_3;
1959 case eDVBFrontendParametersTerrestrial::FEC_3_4:
1960 parm_u_ofdm_code_rate_LP = FEC_3_4;
1962 case eDVBFrontendParametersTerrestrial::FEC_5_6:
1963 parm_u_ofdm_code_rate_LP = FEC_5_6;
1965 case eDVBFrontendParametersTerrestrial::FEC_7_8:
1966 parm_u_ofdm_code_rate_LP = FEC_7_8;
1969 case eDVBFrontendParametersTerrestrial::FEC_Auto:
1970 parm_u_ofdm_code_rate_LP = FEC_AUTO;
1973 switch (feparm.code_rate_HP)
1975 case eDVBFrontendParametersTerrestrial::FEC_1_2:
1976 parm_u_ofdm_code_rate_HP = FEC_1_2;
1978 case eDVBFrontendParametersTerrestrial::FEC_2_3:
1979 parm_u_ofdm_code_rate_HP = FEC_2_3;
1981 case eDVBFrontendParametersTerrestrial::FEC_3_4:
1982 parm_u_ofdm_code_rate_HP = FEC_3_4;
1984 case eDVBFrontendParametersTerrestrial::FEC_5_6:
1985 parm_u_ofdm_code_rate_HP = FEC_5_6;
1987 case eDVBFrontendParametersTerrestrial::FEC_7_8:
1988 parm_u_ofdm_code_rate_HP = FEC_7_8;
1991 case eDVBFrontendParametersTerrestrial::FEC_Auto:
1992 parm_u_ofdm_code_rate_HP = FEC_AUTO;
1995 switch (feparm.modulation)
1997 case eDVBFrontendParametersTerrestrial::Modulation_QPSK:
1998 parm_u_ofdm_constellation = QPSK;
2000 case eDVBFrontendParametersTerrestrial::Modulation_QAM16:
2001 parm_u_ofdm_constellation = QAM_16;
2003 case eDVBFrontendParametersTerrestrial::Modulation_QAM64:
2004 parm_u_ofdm_constellation = QAM_64;
2007 case eDVBFrontendParametersTerrestrial::Modulation_Auto:
2008 parm_u_ofdm_constellation = QAM_AUTO;
2011 switch (feparm.transmission_mode)
2013 case eDVBFrontendParametersTerrestrial::TransmissionMode_2k:
2014 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2016 case eDVBFrontendParametersTerrestrial::TransmissionMode_8k:
2017 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2020 case eDVBFrontendParametersTerrestrial::TransmissionMode_Auto:
2021 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2024 switch (feparm.guard_interval)
2026 case eDVBFrontendParametersTerrestrial::GuardInterval_1_32:
2027 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2029 case eDVBFrontendParametersTerrestrial::GuardInterval_1_16:
2030 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2032 case eDVBFrontendParametersTerrestrial::GuardInterval_1_8:
2033 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2035 case eDVBFrontendParametersTerrestrial::GuardInterval_1_4:
2036 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2039 case eDVBFrontendParametersTerrestrial::GuardInterval_Auto:
2040 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2043 switch (feparm.hierarchy)
2045 case eDVBFrontendParametersTerrestrial::Hierarchy_None:
2046 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2048 case eDVBFrontendParametersTerrestrial::Hierarchy_1:
2049 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2051 case eDVBFrontendParametersTerrestrial::Hierarchy_2:
2052 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2054 case eDVBFrontendParametersTerrestrial::Hierarchy_4:
2055 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2058 case eDVBFrontendParametersTerrestrial::Hierarchy_Auto:
2059 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2062 switch (feparm.inversion)
2064 case eDVBFrontendParametersTerrestrial::Inversion_On:
2065 parm_inversion = INVERSION_ON;
2067 case eDVBFrontendParametersTerrestrial::Inversion_Off:
2068 parm_inversion = INVERSION_OFF;
2071 case eDVBFrontendParametersTerrestrial::Inversion_Unknown:
2072 parm_inversion = INVERSION_AUTO;
2078 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2080 unsigned int timeout = 5000;
2081 eDebugNoSimulate("(%d)tune", m_dvbid);
2087 if (!m_sn && !m_simulate)
2089 eDebug("no frontend device opened... do not try to tune !!!");
2103 m_sec_sequence.clear();
2105 where.calcLockTimeout(timeout);
2111 eDVBFrontendParametersSatellite feparm;
2112 if (where.getDVBS(feparm))
2114 eDebug("no dvbs data!");
2119 m_sec->setRotorMoving(false);
2120 res=prepare_sat(feparm, timeout);
2128 eDVBFrontendParametersCable feparm;
2129 if (where.getDVBC(feparm))
2134 res=prepare_cable(feparm);
2138 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2139 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2144 eDVBFrontendParametersTerrestrial feparm;
2145 if (where.getDVBT(feparm))
2147 eDebug("no -T data");
2151 res=prepare_terrestrial(feparm);
2155 std::string enable_5V;
2156 char configStr[255];
2157 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2158 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2159 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2160 if (enable_5V == "True")
2161 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2163 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2164 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2170 m_sec_sequence.current() = m_sec_sequence.begin();
2174 m_tuneTimer->start(0,true);
2175 if (m_state != stateTuning)
2178 m_state = stateTuning;
2179 m_stateChanged(this);
2188 m_tuneTimer->stop();
2192 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2194 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2198 RESULT eDVBFrontend::setVoltage(int voltage)
2200 if (m_type == feCable)
2202 #if HAVE_DVB_API_VERSION < 3
2205 bool increased=false;
2206 fe_sec_voltage_t vlt;
2208 m_data[CUR_VOLTAGE]=voltage;
2212 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2213 vlt = SEC_VOLTAGE_OFF;
2216 #if HAVE_DVB_API_VERSION < 3
2217 vlt = SEC_VOLTAGE_13_5;
2223 vlt = SEC_VOLTAGE_13;
2226 #if HAVE_DVB_API_VERSION < 3
2227 vlt = SEC_VOLTAGE_18_5;
2233 vlt = SEC_VOLTAGE_18;
2240 #if HAVE_DVB_API_VERSION < 3
2241 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2243 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2244 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2245 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2249 RESULT eDVBFrontend::getState(int &state)
2255 RESULT eDVBFrontend::setTone(int t)
2257 if (m_type != feSatellite)
2259 #if HAVE_DVB_API_VERSION < 3
2262 fe_sec_tone_mode_t tone;
2271 tone = SEC_TONE_OFF;
2278 #if HAVE_DVB_API_VERSION < 3
2279 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2281 return ::ioctl(m_fd, FE_SET_TONE, tone);
2285 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2286 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2289 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2293 #if HAVE_DVB_API_VERSION < 3
2294 struct secCommand cmd;
2295 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2296 cmd.u.diseqc.cmdtype = diseqc.data[0];
2297 cmd.u.diseqc.addr = diseqc.data[1];
2298 cmd.u.diseqc.cmd = diseqc.data[2];
2299 cmd.u.diseqc.numParams = diseqc.len-3;
2300 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2301 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2303 struct dvb_diseqc_master_cmd cmd;
2304 memcpy(cmd.msg, diseqc.data, diseqc.len);
2305 cmd.msg_len = diseqc.len;
2306 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2312 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2313 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2315 RESULT eDVBFrontend::sendToneburst(int burst)
2319 #if HAVE_DVB_API_VERSION < 3
2320 secMiniCmd cmd = SEC_MINI_NONE;
2322 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2324 if ( burst == eDVBSatelliteDiseqcParameters::A )
2326 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2328 #if HAVE_DVB_API_VERSION < 3
2329 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2332 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2338 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2344 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2346 m_sec_sequence = list;
2350 RESULT eDVBFrontend::getData(int num, long &data)
2352 if ( num < NUM_DATA_ENTRIES )
2360 RESULT eDVBFrontend::setData(int num, long val)
2362 if ( num < NUM_DATA_ENTRIES )
2370 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2373 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2375 if (m_type == eDVBFrontend::feSatellite)
2378 eDVBFrontendParametersSatellite sat_parm;
2379 int ret = feparm->getDVBS(sat_parm);
2381 if (sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S2 && !m_can_handle_dvbs2)
2383 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2384 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S && m_can_handle_dvbs2)
2388 else if (m_type == eDVBFrontend::feCable)
2389 return 2; // more prio for cable frontends
2390 else if (m_type == eDVBFrontend::feTerrestrial)
2395 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2397 ePyObject Id, Descr, Enabled, IsDVBS2;
2398 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4)
2400 Id = PyTuple_GET_ITEM(obj, 0);
2401 Descr = PyTuple_GET_ITEM(obj, 1);
2402 Enabled = PyTuple_GET_ITEM(obj, 2);
2403 IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2404 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2))
2406 strcpy(m_description, PyString_AS_STRING(Descr));
2407 m_slotid = PyInt_AsLong(Id);
2408 m_enabled = Enabled == Py_True;
2409 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2410 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2411 !!strstr(m_description, "Alps BSBE2") ||
2412 !!strstr(m_description, "Alps -S") ||
2413 !!strstr(m_description, "BCM4501");
2414 m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2415 eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2416 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2419 PyErr_SetString(PyExc_StandardError,
2420 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");
2424 RESULT eDVBFrontend::turnOffSatCR(int satcr)
2426 eSecCommandList sec_sequence;
2427 // check if voltage is disabled
2428 eSecCommand::pair compare;
2429 compare.steps = +9; //nothing to do
2430 compare.voltage = iDVBFrontend::voltageOff;
2431 sec_sequence.push_back( eSecCommand(eSecCommand::IF_NOT_VOLTAGE_GOTO, compare) );
2432 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2433 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50 ) );
2435 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage18_5) );
2436 sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
2437 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 250) );
2439 eDVBDiseqcCommand diseqc;
2440 memset(diseqc.data, 0, MAX_DISEQC_LENGTH);
2442 diseqc.data[0] = 0xE0;
2443 diseqc.data[1] = 0x10;
2444 diseqc.data[2] = 0x5A;
2445 diseqc.data[3] = satcr << 5;
2446 diseqc.data[4] = 0x00;
2448 sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
2449 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50+20+14*diseqc.len) );
2450 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2451 setSecSequence(sec_sequence);
2455 RESULT eDVBFrontend::ScanSatCR()
2459 setTone(iDVBFrontend::toneOff);