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) / 1000;
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/1000000)&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_state(stateClosed), 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()
480 if (m_state != stateClosed)
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)));
861 else if (!strcmp(m_description, "BCM4506"))
862 ret = (snr * 100) >> 8;
864 if (type == signalQuality)
866 if (ret == 0x12345678) // no snr db calculation avail.. return untouched snr value..
871 return ret >= sat_max ? 65536 : ret * 65536 / sat_max;
872 case feCable: // we assume a max of 42db here
873 return ret >= 4200 ? 65536 : ret * 65536 / 4200;
874 case feTerrestrial: // we assume a max of 24db here
875 return ret >= 2400 ? 65536 : ret * 65536 / 2400;
879 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
887 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
888 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
894 #if HAVE_DVB_API_VERSION < 3
895 FrontendStatus status=0;
901 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
902 eDebug("FE_READ_STATUS failed (%m)");
903 return !!(status&FE_HAS_LOCK);
909 #if HAVE_DVB_API_VERSION < 3
910 FrontendStatus status=0;
916 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
917 eDebug("FE_READ_STATUS failed (%m)");
918 return !!(status&FE_HAS_SYNC);
928 void PutToDict(ePyObject &dict, const char*key, long value)
930 ePyObject item = PyInt_FromLong(value);
933 if (PyDict_SetItemString(dict, key, item))
934 eDebug("put %s to dict failed", key);
938 eDebug("could not create PyObject for %s", key);
941 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
945 if (PyDict_SetItemString(dict, key, item))
946 eDebug("put %s to dict failed", key);
950 eDebug("invalid PyObject for %s", key);
953 void PutToDict(ePyObject &dict, const char*key, const char *value)
955 ePyObject item = PyString_FromString(value);
958 if (PyDict_SetItemString(dict, key, item))
959 eDebug("put %s to dict failed", key);
963 eDebug("could not create PyObject for %s", key);
966 void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, long freq_offset, int orb_pos, int polarization)
969 int frequency = parm_frequency + freq_offset;
970 PutToDict(dict, "frequency", frequency);
971 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
972 PutToDict(dict, "orbital_position", orb_pos);
973 PutToDict(dict, "polarization", polarization);
975 switch(parm_u_qpsk_fec_inner)
977 case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
978 case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
979 case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
980 case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
981 case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
982 case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
984 case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
985 #if HAVE_DVB_API_VERSION >=3
986 case FEC_S2_8PSK_1_2:
987 case FEC_S2_QPSK_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
988 case FEC_S2_8PSK_2_3:
989 case FEC_S2_QPSK_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
990 case FEC_S2_8PSK_3_4:
991 case FEC_S2_QPSK_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
992 case FEC_S2_8PSK_5_6:
993 case FEC_S2_QPSK_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
994 case FEC_S2_8PSK_7_8:
995 case FEC_S2_QPSK_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
996 case FEC_S2_8PSK_8_9:
997 case FEC_S2_QPSK_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
998 case FEC_S2_8PSK_3_5:
999 case FEC_S2_QPSK_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
1000 case FEC_S2_8PSK_4_5:
1001 case FEC_S2_QPSK_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
1002 case FEC_S2_8PSK_9_10:
1003 case FEC_S2_QPSK_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1006 PutToDict(dict, "fec_inner", tmp);
1007 #if HAVE_DVB_API_VERSION >=3
1008 PutToDict(dict, "modulation",
1009 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ?
1010 eDVBFrontendParametersSatellite::Modulation_8PSK :
1011 eDVBFrontendParametersSatellite::Modulation_QPSK );
1012 if (parm_u_qpsk_fec_inner > FEC_AUTO)
1014 switch(parm_inversion & 0xc)
1016 default: // unknown rolloff
1017 case 0: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1018 case 4: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1019 case 8: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1021 PutToDict(dict, "rolloff", tmp);
1022 switch(parm_inversion & 0x30)
1024 case 0: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1025 case 0x10: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1026 case 0x20: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1028 PutToDict(dict, "pilot", tmp);
1029 tmp = eDVBFrontendParametersSatellite::System_DVB_S2;
1032 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1034 PutToDict(dict, "modulation", eDVBFrontendParametersSatellite::Modulation_QPSK );
1035 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1037 PutToDict(dict, "system", tmp);
1040 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1043 #if HAVE_DVB_API_VERSION < 3
1044 PutToDict(dict, "frequency", parm_frequency);
1046 PutToDict(dict, "frequency", parm_frequency/1000);
1048 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1049 switch(parm_u_qam_fec_inner)
1051 case FEC_NONE: tmp = eDVBFrontendParametersCable::FEC_None; break;
1052 case FEC_1_2: tmp = eDVBFrontendParametersCable::FEC_1_2; break;
1053 case FEC_2_3: tmp = eDVBFrontendParametersCable::FEC_2_3; break;
1054 case FEC_3_4: tmp = eDVBFrontendParametersCable::FEC_3_4; break;
1055 case FEC_5_6: tmp = eDVBFrontendParametersCable::FEC_5_6; break;
1056 case FEC_7_8: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1057 #if HAVE_DVB_API_VERSION >= 3
1058 case FEC_8_9: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1061 case FEC_AUTO: tmp = eDVBFrontendParametersCable::FEC_Auto; break;
1063 PutToDict(dict, "fec_inner", tmp);
1064 switch(parm_u_qam_modulation)
1066 case QAM_16: tmp = eDVBFrontendParametersCable::Modulation_QAM16; break;
1067 case QAM_32: tmp = eDVBFrontendParametersCable::Modulation_QAM32; break;
1068 case QAM_64: tmp = eDVBFrontendParametersCable::Modulation_QAM64; break;
1069 case QAM_128: tmp = eDVBFrontendParametersCable::Modulation_QAM128; break;
1070 case QAM_256: tmp = eDVBFrontendParametersCable::Modulation_QAM256; break;
1072 case QAM_AUTO: tmp = eDVBFrontendParametersCable::Modulation_Auto; break;
1074 PutToDict(dict, "modulation", tmp);
1077 void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1080 PutToDict(dict, "frequency", parm_frequency);
1081 switch (parm_u_ofdm_bandwidth)
1083 case BANDWIDTH_8_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_8MHz; break;
1084 case BANDWIDTH_7_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_7MHz; break;
1085 case BANDWIDTH_6_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_6MHz; break;
1087 case BANDWIDTH_AUTO: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_Auto; break;
1089 PutToDict(dict, "bandwidth", tmp);
1090 switch (parm_u_ofdm_code_rate_LP)
1092 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1093 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1094 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1095 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1096 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1098 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1100 PutToDict(dict, "code_rate_lp", tmp);
1101 switch (parm_u_ofdm_code_rate_HP)
1103 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1104 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1105 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1106 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1107 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1109 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1111 PutToDict(dict, "code_rate_hp", tmp);
1112 switch (parm_u_ofdm_constellation)
1114 case QPSK: tmp = eDVBFrontendParametersTerrestrial::Modulation_QPSK; break;
1115 case QAM_16: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM16; break;
1116 case QAM_64: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM64; break;
1118 case QAM_AUTO: tmp = eDVBFrontendParametersTerrestrial::Modulation_Auto; break;
1120 PutToDict(dict, "constellation", tmp);
1121 switch (parm_u_ofdm_transmission_mode)
1123 case TRANSMISSION_MODE_2K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_2k; break;
1124 case TRANSMISSION_MODE_8K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_8k; break;
1126 case TRANSMISSION_MODE_AUTO: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto; break;
1128 PutToDict(dict, "transmission_mode", tmp);
1129 switch (parm_u_ofdm_guard_interval)
1131 case GUARD_INTERVAL_1_32: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_32; break;
1132 case GUARD_INTERVAL_1_16: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_16; break;
1133 case GUARD_INTERVAL_1_8: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_8; break;
1134 case GUARD_INTERVAL_1_4: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_4; break;
1136 case GUARD_INTERVAL_AUTO: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_Auto; break;
1138 PutToDict(dict, "guard_interval", tmp);
1139 switch (parm_u_ofdm_hierarchy_information)
1141 case HIERARCHY_NONE: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_None; break;
1142 case HIERARCHY_1: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_1; break;
1143 case HIERARCHY_2: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_2; break;
1144 case HIERARCHY_4: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_4; break;
1146 case HIERARCHY_AUTO: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_Auto; break;
1148 PutToDict(dict, "hierarchy_information", tmp);
1151 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1153 if (dest && PyDict_Check(dest))
1155 const char *tmp = "UNKNOWN";
1176 PutToDict(dest, "tuner_state", tmp);
1177 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1178 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1179 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1180 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1181 int sigQualitydB = readFrontendData(signalQualitydB);
1182 if (sigQualitydB == 0x12345678) // not support yet
1184 ePyObject obj=Py_None;
1186 PutToDict(dest, "tuner_signal_quality_db", obj);
1189 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1190 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1194 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1196 if (dest && PyDict_Check(dest))
1204 FRONTENDPARAMETERS front;
1205 if (m_fd == -1 && !original)
1207 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1209 eDebug("FE_GET_FRONTEND failed (%m)");
1213 const FRONTENDPARAMETERS &parm = original || m_simulate ? this->parm : front;
1214 long tmp = eDVBFrontendParametersSatellite::Inversion_Unknown;
1215 switch(parm_inversion & 3)
1218 tmp = eDVBFrontendParametersSatellite::Inversion_On;
1221 tmp = eDVBFrontendParametersSatellite::Inversion_Off;
1225 PutToDict(dest, "inversion", tmp);
1230 fillDictWithSatelliteData(dest, original?parm:front, m_data[FREQ_OFFSET], m_cur_orbpos, m_cur_pol);
1233 fillDictWithCableData(dest, original?parm:front);
1236 fillDictWithTerrestrialData(dest, original?parm:front);
1247 void eDVBFrontend::getFrontendData(ePyObject dest)
1249 if (dest && PyDict_Check(dest))
1252 PutToDict(dest, "tuner_number", m_slotid);
1268 PutToDict(dest, "tuner_type", tmp);
1272 #ifndef FP_IOCTL_GET_ID
1273 #define FP_IOCTL_GET_ID 0
1275 int eDVBFrontend::readInputpower()
1279 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1281 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1282 FILE *f=fopen(proc_name, "r");
1285 if (fscanf(f, "%d", &power) != 1)
1286 eDebug("read %s failed!! (%m)", proc_name);
1288 eDebug("%s is %d\n", proc_name, power);
1293 // open front prozessor
1294 int fp=::open("/dev/dbox/fp0", O_RDWR);
1297 eDebug("couldn't open fp");
1300 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1301 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1303 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1312 bool eDVBFrontend::setSecSequencePos(int steps)
1314 eDebugNoSimulate("set sequence pos %d", steps);
1319 if (m_sec_sequence.current() != m_sec_sequence.end())
1320 ++m_sec_sequence.current();
1325 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1326 --m_sec_sequence.current();
1332 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1335 eDVBFrontend *sec_fe = this;
1336 eDVBRegisteredFrontend *regFE = 0;
1337 long tmp = m_data[LINKED_PREV_PTR];
1340 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1341 sec_fe = prev->m_frontend;
1342 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1343 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1344 int state = sec_fe->m_state;
1345 // workaround to put the kernel frontend thread into idle state!
1346 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1348 sec_fe->closeFrontend(true);
1349 state = sec_fe->m_state;
1351 // sec_fe is closed... we must reopen it here..
1352 if (state == stateClosed)
1360 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1362 long *sec_fe_data = sec_fe->m_data;
1363 // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1364 switch (m_sec_sequence.current()->cmd)
1366 case eSecCommand::SLEEP:
1367 delay = m_sec_sequence.current()++->msec;
1368 eDebugNoSimulate("[SEC] sleep %dms", delay);
1370 case eSecCommand::GOTO:
1371 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1372 ++m_sec_sequence.current();
1374 case eSecCommand::SET_VOLTAGE:
1376 int voltage = m_sec_sequence.current()++->voltage;
1377 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1378 sec_fe->setVoltage(voltage);
1381 case eSecCommand::IF_VOLTAGE_GOTO:
1383 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1384 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1386 ++m_sec_sequence.current();
1389 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1391 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1392 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1394 ++m_sec_sequence.current();
1397 case eSecCommand::IF_TONE_GOTO:
1399 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1400 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1402 ++m_sec_sequence.current();
1405 case eSecCommand::IF_NOT_TONE_GOTO:
1407 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1408 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1410 ++m_sec_sequence.current();
1413 case eSecCommand::SET_TONE:
1414 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1415 sec_fe->setTone(m_sec_sequence.current()++->tone);
1417 case eSecCommand::SEND_DISEQC:
1418 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1419 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1420 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1421 eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1422 if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
1423 eDebugNoSimulate("(DiSEqC reset)");
1424 else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
1425 eDebugNoSimulate("(DiSEqC peripherial power on)");
1427 eDebugNoSimulate("");
1428 ++m_sec_sequence.current();
1430 case eSecCommand::SEND_TONEBURST:
1431 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1432 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1434 case eSecCommand::SET_FRONTEND:
1435 eDebugNoSimulate("[SEC] setFrontend");
1437 ++m_sec_sequence.current();
1439 case eSecCommand::START_TUNE_TIMEOUT:
1442 m_timeout->start(m_sec_sequence.current()->timeout, 1);
1443 ++m_sec_sequence.current();
1446 case eSecCommand::SET_TIMEOUT:
1447 m_timeoutCount = m_sec_sequence.current()++->val;
1448 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1450 case eSecCommand::IF_TIMEOUT_GOTO:
1451 if (!m_timeoutCount)
1453 eDebugNoSimulate("[SEC] rotor timout");
1454 setSecSequencePos(m_sec_sequence.current()->steps);
1457 ++m_sec_sequence.current();
1459 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1461 int idx = m_sec_sequence.current()++->val;
1462 if ( idx == 0 || idx == 1 )
1464 m_idleInputpower[idx] = sec_fe->readInputpower();
1465 eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1468 eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1471 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1473 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1474 int idx = compare.val;
1475 if ( !m_simulate && (idx == 0 || idx == 1) )
1477 int idle = sec_fe->readInputpower();
1478 int diff = abs(idle-m_idleInputpower[idx]);
1481 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1482 setSecSequencePos(compare.steps);
1486 ++m_sec_sequence.current();
1489 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1491 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1494 setSecSequencePos(cmd.steps);
1498 int isLocked = readFrontendData(locked);
1499 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1500 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 50) || !cmd.lastSignal))
1503 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1506 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1507 cmd.lastSignal = signal;
1510 if (cmd.okcount > 4)
1512 eDebugNoSimulate("ok > 4 .. goto %d\n",cmd.steps);
1513 setSecSequencePos(cmd.steps);
1514 m_state = stateLock;
1515 m_stateChanged(this);
1524 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1526 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1528 if (!m_timeoutCount && m_retryCount > 0)
1533 ++m_sec_sequence.current();
1536 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1537 m_runningInputpower = sec_fe->readInputpower();
1538 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1539 ++m_sec_sequence.current();
1541 case eSecCommand::SET_ROTOR_MOVING:
1543 m_sec->setRotorMoving(true);
1544 ++m_sec_sequence.current();
1546 case eSecCommand::SET_ROTOR_STOPPED:
1548 m_sec->setRotorMoving(false);
1549 ++m_sec_sequence.current();
1551 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1553 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1556 setSecSequencePos(cmd.steps);
1559 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1560 const char *txt = cmd.direction ? "running" : "stopped";
1561 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1563 m_runningInputpower,
1566 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1567 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1570 eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1571 if ( cmd.okcount > 6 )
1573 eDebugNoSimulate("[SEC] rotor is %s", txt);
1574 if (setSecSequencePos(cmd.steps))
1580 eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1582 if (!m_timeoutCount && m_retryCount > 0)
1586 ++m_sec_sequence.current();
1589 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1590 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1591 setSecSequencePos(m_sec_sequence.current()->steps);
1593 ++m_sec_sequence.current();
1595 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1596 eDebugNoSimulate("[SEC] invalidate current switch params");
1597 sec_fe_data[CSW] = -1;
1598 sec_fe_data[UCSW] = -1;
1599 sec_fe_data[TONEBURST] = -1;
1600 ++m_sec_sequence.current();
1602 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1603 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1604 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1605 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1606 eDebugNoSimulate("[SEC] update current switch params");
1607 ++m_sec_sequence.current();
1609 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1610 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1611 sec_fe_data[ROTOR_CMD] = -1;
1612 sec_fe_data[ROTOR_POS] = -1;
1613 ++m_sec_sequence.current();
1615 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1616 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1617 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1618 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1619 ++m_sec_sequence.current();
1621 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1622 m_retryCount = m_sec_sequence.current()++->val;
1623 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1625 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1628 eDebugNoSimulate("[SEC] no more rotor retrys");
1629 setSecSequencePos(m_sec_sequence.current()->steps);
1632 ++m_sec_sequence.current();
1634 case eSecCommand::SET_POWER_LIMITING_MODE:
1639 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1640 FILE *f=fopen(proc_name, "w");
1641 if (f) // new interface exist?
1643 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1644 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1645 eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1647 eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1650 else if (sec_fe->m_need_rotor_workaround)
1653 int slotid = sec_fe->m_slotid;
1654 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1656 sprintf(dev, "/dev/i2c/%d", slotid);
1657 else if (slotid == 2)
1658 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1659 else if (slotid == 3)
1660 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1661 int fd = ::open(dev, O_RDWR);
1663 unsigned char data[2];
1664 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1665 if(::read(fd, data, 1) != 1)
1666 eDebugNoSimulate("[SEC] error read lnbp (%m)");
1667 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1669 data[0] |= 0x80; // enable static current limiting
1670 eDebugNoSimulate("[SEC] set static current limiting");
1674 data[0] &= ~0x80; // enable dynamic current limiting
1675 eDebugNoSimulate("[SEC] set dynamic current limiting");
1677 if(::write(fd, data, 1) != 1)
1678 eDebugNoSimulate("[SEC] error write lnbp (%m)");
1682 ++m_sec_sequence.current();
1686 eDebugNoSimulate("[SEC] unhandled sec command %d",
1687 ++m_sec_sequence.current()->cmd);
1688 ++m_sec_sequence.current();
1691 m_tuneTimer->start(delay,true);
1695 if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1699 void eDVBFrontend::setFrontend()
1703 eDebug("setting frontend %d", m_dvbid);
1706 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1708 perror("FE_SET_FRONTEND failed");
1714 RESULT eDVBFrontend::getFrontendType(int &t)
1722 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1727 eWarning("no SEC module active!");
1730 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1733 #if HAVE_DVB_API_VERSION >= 3
1734 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",
1737 feparm.polarisation,
1741 feparm.orbital_position,
1747 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1750 feparm.polarisation,
1754 feparm.orbital_position);
1756 m_cur_pol = feparm.polarisation;
1757 m_cur_orbpos = feparm.orbital_position;
1758 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1759 switch (feparm.inversion)
1761 case eDVBFrontendParametersSatellite::Inversion_On:
1762 parm_inversion = INVERSION_ON;
1764 case eDVBFrontendParametersSatellite::Inversion_Off:
1765 parm_inversion = INVERSION_OFF;
1768 case eDVBFrontendParametersSatellite::Inversion_Unknown:
1769 parm_inversion = INVERSION_AUTO;
1772 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S)
1775 case eDVBFrontendParametersSatellite::FEC_None:
1776 parm_u_qpsk_fec_inner = FEC_NONE;
1778 case eDVBFrontendParametersSatellite::FEC_1_2:
1779 parm_u_qpsk_fec_inner = FEC_1_2;
1781 case eDVBFrontendParametersSatellite::FEC_2_3:
1782 parm_u_qpsk_fec_inner = FEC_2_3;
1784 case eDVBFrontendParametersSatellite::FEC_3_4:
1785 parm_u_qpsk_fec_inner = FEC_3_4;
1787 case eDVBFrontendParametersSatellite::FEC_5_6:
1788 parm_u_qpsk_fec_inner = FEC_5_6;
1790 case eDVBFrontendParametersSatellite::FEC_7_8:
1791 parm_u_qpsk_fec_inner = FEC_7_8;
1794 eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
1795 case eDVBFrontendParametersSatellite::FEC_Auto:
1796 parm_u_qpsk_fec_inner = FEC_AUTO;
1799 #if HAVE_DVB_API_VERSION >= 3
1804 case eDVBFrontendParametersSatellite::FEC_1_2:
1805 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1807 case eDVBFrontendParametersSatellite::FEC_2_3:
1808 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1810 case eDVBFrontendParametersSatellite::FEC_3_4:
1811 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1813 case eDVBFrontendParametersSatellite::FEC_3_5:
1814 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1816 case eDVBFrontendParametersSatellite::FEC_4_5:
1817 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1819 case eDVBFrontendParametersSatellite::FEC_5_6:
1820 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1822 case eDVBFrontendParametersSatellite::FEC_7_8:
1823 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1825 case eDVBFrontendParametersSatellite::FEC_8_9:
1826 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1828 case eDVBFrontendParametersSatellite::FEC_9_10:
1829 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1832 eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
1835 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1836 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1837 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation_8PSK) {
1838 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1839 // 8PSK fec driver values are decimal 9 bigger
1843 // FIXME !!! get frequency range from tuner
1844 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1846 eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1849 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
1854 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1856 #if HAVE_DVB_API_VERSION < 3
1857 parm_frequency = feparm.frequency;
1859 parm_frequency = feparm.frequency * 1000;
1861 parm_u_qam_symbol_rate = feparm.symbol_rate;
1862 switch (feparm.modulation)
1864 case eDVBFrontendParametersCable::Modulation_QAM16:
1865 parm_u_qam_modulation = QAM_16;
1867 case eDVBFrontendParametersCable::Modulation_QAM32:
1868 parm_u_qam_modulation = QAM_32;
1870 case eDVBFrontendParametersCable::Modulation_QAM64:
1871 parm_u_qam_modulation = QAM_64;
1873 case eDVBFrontendParametersCable::Modulation_QAM128:
1874 parm_u_qam_modulation = QAM_128;
1876 case eDVBFrontendParametersCable::Modulation_QAM256:
1877 parm_u_qam_modulation = QAM_256;
1880 case eDVBFrontendParametersCable::Modulation_Auto:
1881 parm_u_qam_modulation = QAM_AUTO;
1884 switch (feparm.inversion)
1886 case eDVBFrontendParametersCable::Inversion_On:
1887 parm_inversion = INVERSION_ON;
1889 case eDVBFrontendParametersCable::Inversion_Off:
1890 parm_inversion = INVERSION_OFF;
1893 case eDVBFrontendParametersCable::Inversion_Unknown:
1894 parm_inversion = INVERSION_AUTO;
1897 switch (feparm.fec_inner)
1899 case eDVBFrontendParametersCable::FEC_None:
1900 parm_u_qam_fec_inner = FEC_NONE;
1902 case eDVBFrontendParametersCable::FEC_1_2:
1903 parm_u_qam_fec_inner = FEC_1_2;
1905 case eDVBFrontendParametersCable::FEC_2_3:
1906 parm_u_qam_fec_inner = FEC_2_3;
1908 case eDVBFrontendParametersCable::FEC_3_4:
1909 parm_u_qam_fec_inner = FEC_3_4;
1911 case eDVBFrontendParametersCable::FEC_5_6:
1912 parm_u_qam_fec_inner = FEC_5_6;
1914 case eDVBFrontendParametersCable::FEC_7_8:
1915 parm_u_qam_fec_inner = FEC_7_8;
1917 #if HAVE_DVB_API_VERSION >= 3
1918 case eDVBFrontendParametersCable::FEC_8_9:
1919 parm_u_qam_fec_inner = FEC_8_9;
1923 case eDVBFrontendParametersCable::FEC_Auto:
1924 parm_u_qam_fec_inner = FEC_AUTO;
1927 eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
1928 parm_frequency/1000,
1929 parm_u_qam_symbol_rate,
1930 parm_u_qam_fec_inner,
1931 parm_u_qam_modulation,
1936 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
1938 parm_frequency = feparm.frequency;
1940 switch (feparm.bandwidth)
1942 case eDVBFrontendParametersTerrestrial::Bandwidth_8MHz:
1943 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
1945 case eDVBFrontendParametersTerrestrial::Bandwidth_7MHz:
1946 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
1948 case eDVBFrontendParametersTerrestrial::Bandwidth_6MHz:
1949 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
1952 case eDVBFrontendParametersTerrestrial::Bandwidth_Auto:
1953 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
1956 switch (feparm.code_rate_LP)
1958 case eDVBFrontendParametersTerrestrial::FEC_1_2:
1959 parm_u_ofdm_code_rate_LP = FEC_1_2;
1961 case eDVBFrontendParametersTerrestrial::FEC_2_3:
1962 parm_u_ofdm_code_rate_LP = FEC_2_3;
1964 case eDVBFrontendParametersTerrestrial::FEC_3_4:
1965 parm_u_ofdm_code_rate_LP = FEC_3_4;
1967 case eDVBFrontendParametersTerrestrial::FEC_5_6:
1968 parm_u_ofdm_code_rate_LP = FEC_5_6;
1970 case eDVBFrontendParametersTerrestrial::FEC_7_8:
1971 parm_u_ofdm_code_rate_LP = FEC_7_8;
1974 case eDVBFrontendParametersTerrestrial::FEC_Auto:
1975 parm_u_ofdm_code_rate_LP = FEC_AUTO;
1978 switch (feparm.code_rate_HP)
1980 case eDVBFrontendParametersTerrestrial::FEC_1_2:
1981 parm_u_ofdm_code_rate_HP = FEC_1_2;
1983 case eDVBFrontendParametersTerrestrial::FEC_2_3:
1984 parm_u_ofdm_code_rate_HP = FEC_2_3;
1986 case eDVBFrontendParametersTerrestrial::FEC_3_4:
1987 parm_u_ofdm_code_rate_HP = FEC_3_4;
1989 case eDVBFrontendParametersTerrestrial::FEC_5_6:
1990 parm_u_ofdm_code_rate_HP = FEC_5_6;
1992 case eDVBFrontendParametersTerrestrial::FEC_7_8:
1993 parm_u_ofdm_code_rate_HP = FEC_7_8;
1996 case eDVBFrontendParametersTerrestrial::FEC_Auto:
1997 parm_u_ofdm_code_rate_HP = FEC_AUTO;
2000 switch (feparm.modulation)
2002 case eDVBFrontendParametersTerrestrial::Modulation_QPSK:
2003 parm_u_ofdm_constellation = QPSK;
2005 case eDVBFrontendParametersTerrestrial::Modulation_QAM16:
2006 parm_u_ofdm_constellation = QAM_16;
2008 case eDVBFrontendParametersTerrestrial::Modulation_QAM64:
2009 parm_u_ofdm_constellation = QAM_64;
2012 case eDVBFrontendParametersTerrestrial::Modulation_Auto:
2013 parm_u_ofdm_constellation = QAM_AUTO;
2016 switch (feparm.transmission_mode)
2018 case eDVBFrontendParametersTerrestrial::TransmissionMode_2k:
2019 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2021 case eDVBFrontendParametersTerrestrial::TransmissionMode_8k:
2022 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2025 case eDVBFrontendParametersTerrestrial::TransmissionMode_Auto:
2026 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2029 switch (feparm.guard_interval)
2031 case eDVBFrontendParametersTerrestrial::GuardInterval_1_32:
2032 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2034 case eDVBFrontendParametersTerrestrial::GuardInterval_1_16:
2035 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2037 case eDVBFrontendParametersTerrestrial::GuardInterval_1_8:
2038 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2040 case eDVBFrontendParametersTerrestrial::GuardInterval_1_4:
2041 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2044 case eDVBFrontendParametersTerrestrial::GuardInterval_Auto:
2045 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2048 switch (feparm.hierarchy)
2050 case eDVBFrontendParametersTerrestrial::Hierarchy_None:
2051 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2053 case eDVBFrontendParametersTerrestrial::Hierarchy_1:
2054 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2056 case eDVBFrontendParametersTerrestrial::Hierarchy_2:
2057 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2059 case eDVBFrontendParametersTerrestrial::Hierarchy_4:
2060 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2063 case eDVBFrontendParametersTerrestrial::Hierarchy_Auto:
2064 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2067 switch (feparm.inversion)
2069 case eDVBFrontendParametersTerrestrial::Inversion_On:
2070 parm_inversion = INVERSION_ON;
2072 case eDVBFrontendParametersTerrestrial::Inversion_Off:
2073 parm_inversion = INVERSION_OFF;
2076 case eDVBFrontendParametersTerrestrial::Inversion_Unknown:
2077 parm_inversion = INVERSION_AUTO;
2083 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2085 unsigned int timeout = 5000;
2086 eDebugNoSimulate("(%d)tune", m_dvbid);
2092 if (!m_sn && !m_simulate)
2094 eDebug("no frontend device opened... do not try to tune !!!");
2108 m_sec_sequence.clear();
2110 where.calcLockTimeout(timeout);
2116 eDVBFrontendParametersSatellite feparm;
2117 if (where.getDVBS(feparm))
2119 eDebug("no dvbs data!");
2124 m_sec->setRotorMoving(false);
2125 res=prepare_sat(feparm, timeout);
2133 eDVBFrontendParametersCable feparm;
2134 if (where.getDVBC(feparm))
2139 res=prepare_cable(feparm);
2143 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2144 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2149 eDVBFrontendParametersTerrestrial feparm;
2150 if (where.getDVBT(feparm))
2152 eDebug("no -T data");
2156 res=prepare_terrestrial(feparm);
2160 std::string enable_5V;
2161 char configStr[255];
2162 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2163 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2164 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2165 if (enable_5V == "True")
2166 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2168 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2169 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2175 m_sec_sequence.current() = m_sec_sequence.begin();
2179 m_tuneTimer->start(0,true);
2180 if (m_state != stateTuning)
2183 m_state = stateTuning;
2184 m_stateChanged(this);
2193 m_tuneTimer->stop();
2197 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2199 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2203 RESULT eDVBFrontend::setVoltage(int voltage)
2205 if (m_type == feCable)
2207 #if HAVE_DVB_API_VERSION < 3
2210 bool increased=false;
2211 fe_sec_voltage_t vlt;
2213 m_data[CUR_VOLTAGE]=voltage;
2217 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2218 vlt = SEC_VOLTAGE_OFF;
2221 #if HAVE_DVB_API_VERSION < 3
2222 vlt = SEC_VOLTAGE_13_5;
2228 vlt = SEC_VOLTAGE_13;
2231 #if HAVE_DVB_API_VERSION < 3
2232 vlt = SEC_VOLTAGE_18_5;
2238 vlt = SEC_VOLTAGE_18;
2245 #if HAVE_DVB_API_VERSION < 3
2246 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2248 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2249 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2250 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2254 RESULT eDVBFrontend::getState(int &state)
2260 RESULT eDVBFrontend::setTone(int t)
2262 if (m_type != feSatellite)
2264 #if HAVE_DVB_API_VERSION < 3
2267 fe_sec_tone_mode_t tone;
2276 tone = SEC_TONE_OFF;
2283 #if HAVE_DVB_API_VERSION < 3
2284 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2286 return ::ioctl(m_fd, FE_SET_TONE, tone);
2290 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2291 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2294 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2298 #if HAVE_DVB_API_VERSION < 3
2299 struct secCommand cmd;
2300 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2301 cmd.u.diseqc.cmdtype = diseqc.data[0];
2302 cmd.u.diseqc.addr = diseqc.data[1];
2303 cmd.u.diseqc.cmd = diseqc.data[2];
2304 cmd.u.diseqc.numParams = diseqc.len-3;
2305 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2306 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2308 struct dvb_diseqc_master_cmd cmd;
2309 memcpy(cmd.msg, diseqc.data, diseqc.len);
2310 cmd.msg_len = diseqc.len;
2311 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2317 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2318 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2320 RESULT eDVBFrontend::sendToneburst(int burst)
2324 #if HAVE_DVB_API_VERSION < 3
2325 secMiniCmd cmd = SEC_MINI_NONE;
2327 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2329 if ( burst == eDVBSatelliteDiseqcParameters::A )
2331 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2333 #if HAVE_DVB_API_VERSION < 3
2334 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2337 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2343 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2349 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2351 m_sec_sequence = list;
2355 RESULT eDVBFrontend::getData(int num, long &data)
2357 if ( num < NUM_DATA_ENTRIES )
2365 RESULT eDVBFrontend::setData(int num, long val)
2367 if ( num < NUM_DATA_ENTRIES )
2375 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2378 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2380 if (m_type == eDVBFrontend::feSatellite)
2383 eDVBFrontendParametersSatellite sat_parm;
2384 int ret = feparm->getDVBS(sat_parm);
2386 if (sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S2 && !m_can_handle_dvbs2)
2388 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2389 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S && m_can_handle_dvbs2)
2393 else if (m_type == eDVBFrontend::feCable)
2394 return 2; // more prio for cable frontends
2395 else if (m_type == eDVBFrontend::feTerrestrial)
2400 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2402 ePyObject Id, Descr, Enabled, IsDVBS2;
2403 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4)
2405 Id = PyTuple_GET_ITEM(obj, 0);
2406 Descr = PyTuple_GET_ITEM(obj, 1);
2407 Enabled = PyTuple_GET_ITEM(obj, 2);
2408 IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2409 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2))
2411 strcpy(m_description, PyString_AS_STRING(Descr));
2412 m_slotid = PyInt_AsLong(Id);
2413 m_enabled = Enabled == Py_True;
2414 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2415 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2416 !!strstr(m_description, "Alps BSBE2") ||
2417 !!strstr(m_description, "Alps -S") ||
2418 !!strstr(m_description, "BCM4501");
2419 m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2420 eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2421 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2424 PyErr_SetString(PyExc_StandardError,
2425 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");
2429 RESULT eDVBFrontend::turnOffSatCR(int satcr)
2431 eSecCommandList sec_sequence;
2432 // check if voltage is disabled
2433 eSecCommand::pair compare;
2434 compare.steps = +9; //nothing to do
2435 compare.voltage = iDVBFrontend::voltageOff;
2436 sec_sequence.push_back( eSecCommand(eSecCommand::IF_NOT_VOLTAGE_GOTO, compare) );
2437 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2438 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50 ) );
2440 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage18_5) );
2441 sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
2442 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 250) );
2444 eDVBDiseqcCommand diseqc;
2445 memset(diseqc.data, 0, MAX_DISEQC_LENGTH);
2447 diseqc.data[0] = 0xE0;
2448 diseqc.data[1] = 0x10;
2449 diseqc.data[2] = 0x5A;
2450 diseqc.data[3] = satcr << 5;
2451 diseqc.data[4] = 0x00;
2453 sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
2454 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50+20+14*diseqc.len) );
2455 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2456 setSecSequence(sec_sequence);
2460 RESULT eDVBFrontend::ScanSatCR()
2464 setTone(iDVBFrontend::toneOff);