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))
658 #if HAVE_DVB_API_VERSION < 3
659 if (event.type == FE_COMPLETION_EV)
661 eDebug("(%d)fe event: status %x, inversion %s", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off");
662 if (event.status & FE_HAS_LOCK)
672 eDebug("stateLostLock");
673 state = stateLostLock;
674 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
677 if (m_state != state)
680 m_stateChanged(this);
685 void eDVBFrontend::timeout()
688 if (m_state == stateTuning)
690 m_state = stateFailed;
691 m_stateChanged(this);
695 #define INRANGE(X,Y,Z) (((X<=Y) && (Y<=Z))||((Z<=Y) && (Y<=X)) ? 1 : 0)
697 /* unsigned 32 bit division */
698 static inline uint32_t fe_udiv(uint32_t a, uint32_t b)
700 return (a + b / 2) / b;
703 int eDVBFrontend::readFrontendData(int type)
712 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
713 eDebug("FE_READ_BER failed (%m)");
718 case signalQualitydB: /* this will move into the driver */
720 int sat_max = 1600; // for stv0288 / bsbe2
721 int ret = 0x12345678;
725 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
726 eDebug("FE_READ_SNR failed (%m)");
727 else if (!strcmp(m_description, "BCM4501 (internal)"))
729 float SDS_SNRE = snr << 16;
732 if (parm_u_qpsk_fec_inner <= FEC_AUTO) // DVB-S1 / QPSK
734 static float SNR_COEFF[6] = {
737 197418.0 / 4194304.0,
738 -2602183.0 / 4194304.0,
739 20377212.0 / 4194304.0,
740 -37791203.0 / 4194304.0,
742 float fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0)),
743 fval2 = pow(10.0, fval1)-1;
744 fval1 = 10.0 * log10(fval2);
748 fval2 = SNR_COEFF[0];
749 for (int i=1; i<6; ++i)
752 fval2 += SNR_COEFF[i];
758 #if HAVE_DVB_API_VERSION >= 3
761 float fval1 = SDS_SNRE / 268435456.0,
764 if (parm_u_qpsk_fec_inner <= FEC_S2_QPSK_9_10) // DVB-S2 QPSK
775 fval4 = -10.0 * log10(fval1);
777 for (int i=0; i < 5; ++i)
778 fval1 = fval4 - fval2 * log10(1.0+pow(10.0, (fval3-fval1)/fval2));
783 ret = (int)(snr_in_db * 100);
785 else if (strstr(m_description, "Alps BSBE1 C01A") ||
786 !strcmp(m_description, "Alps -S(STV0288)"))
790 else if (snr == 0xFFFF) // i think this should not happen
794 enum { REALVAL, REGVAL };
795 const long CN_lookup[31][2] = {
796 {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
797 {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
798 {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
799 {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
800 {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
801 {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
804 int add=strchr(m_description, '.') ? 0xA250 : 0xA100;
805 long regval = 0xFFFF - ((snr / 3) + add), // revert some dvb api calulations to get the real register value
809 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
814 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[i][REGVAL]))
819 ret = (((regval - CN_lookup[Imin][REGVAL])
820 * (CN_lookup[Imax][REALVAL] - CN_lookup[Imin][REALVAL])
821 / (CN_lookup[Imax][REGVAL] - CN_lookup[Imin][REGVAL]))
822 + CN_lookup[Imin][REALVAL]) * 10;
828 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
829 !strcmp(m_description, "Alps -S") ||
830 !strcmp(m_description, "Philips -S") ||
831 !strcmp(m_description, "LG -S") )
834 ret = (int)((snr-39075)/17.647);
835 } else if (!strcmp(m_description, "Alps BSBE2"))
837 ret = (int)((snr >> 7) * 10);
838 } else if (!strcmp(m_description, "Philips CU1216Mk3"))
840 int mse = (~snr) & 0xFF;
841 switch (parm_u_qam_modulation) {
842 case QAM_16: ret = fe_udiv(1950000, (32 * mse) + 138) + 1000; break;
843 case QAM_32: ret = fe_udiv(2150000, (40 * mse) + 500) + 1350; break;
844 case QAM_64: ret = fe_udiv(2100000, (40 * mse) + 500) + 1250; break;
845 case QAM_128: ret = fe_udiv(1850000, (38 * mse) + 400) + 1380; break;
846 case QAM_256: ret = fe_udiv(1800000, (100 * mse) + 40) + 2030; break;
849 } else if (!strcmp(m_description, "Philips TU1216"))
851 snr = 0xFF - (snr & 0xFF);
853 ret = 10 * (int)(-100 * (log10(snr) - log10(255)));
855 else if (!strcmp(m_description, "BCM4506"))
856 ret = (snr * 100) >> 8;
858 if (type == signalQuality)
860 if (ret == 0x12345678) // no snr db calculation avail.. return untouched snr value..
865 return ret >= sat_max ? 65536 : ret * 65536 / sat_max;
866 case feCable: // we assume a max of 42db here
867 return ret >= 4200 ? 65536 : ret * 65536 / 4200;
868 case feTerrestrial: // we assume a max of 24db here
869 return ret >= 2400 ? 65536 : ret * 65536 / 2400;
873 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
881 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
882 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
888 #if HAVE_DVB_API_VERSION < 3
889 FrontendStatus status=0;
895 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
896 eDebug("FE_READ_STATUS failed (%m)");
897 return !!(status&FE_HAS_LOCK);
903 #if HAVE_DVB_API_VERSION < 3
904 FrontendStatus status=0;
910 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
911 eDebug("FE_READ_STATUS failed (%m)");
912 return !!(status&FE_HAS_SYNC);
922 void PutToDict(ePyObject &dict, const char*key, long value)
924 ePyObject item = PyInt_FromLong(value);
927 if (PyDict_SetItemString(dict, key, item))
928 eDebug("put %s to dict failed", key);
932 eDebug("could not create PyObject for %s", key);
935 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
939 if (PyDict_SetItemString(dict, key, item))
940 eDebug("put %s to dict failed", key);
944 eDebug("invalid PyObject for %s", key);
947 void PutToDict(ePyObject &dict, const char*key, const char *value)
949 ePyObject item = PyString_FromString(value);
952 if (PyDict_SetItemString(dict, key, item))
953 eDebug("put %s to dict failed", key);
957 eDebug("could not create PyObject for %s", key);
960 void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, long freq_offset, int orb_pos, int polarization)
963 int frequency = parm_frequency + freq_offset;
964 PutToDict(dict, "frequency", frequency);
965 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
966 PutToDict(dict, "orbital_position", orb_pos);
967 PutToDict(dict, "polarization", polarization);
969 switch(parm_u_qpsk_fec_inner)
971 case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
972 case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
973 case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
974 case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
975 case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
976 case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
978 case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
979 #if HAVE_DVB_API_VERSION >=3
980 case FEC_S2_8PSK_1_2:
981 case FEC_S2_QPSK_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
982 case FEC_S2_8PSK_2_3:
983 case FEC_S2_QPSK_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
984 case FEC_S2_8PSK_3_4:
985 case FEC_S2_QPSK_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
986 case FEC_S2_8PSK_5_6:
987 case FEC_S2_QPSK_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
988 case FEC_S2_8PSK_7_8:
989 case FEC_S2_QPSK_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
990 case FEC_S2_8PSK_8_9:
991 case FEC_S2_QPSK_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
992 case FEC_S2_8PSK_3_5:
993 case FEC_S2_QPSK_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
994 case FEC_S2_8PSK_4_5:
995 case FEC_S2_QPSK_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
996 case FEC_S2_8PSK_9_10:
997 case FEC_S2_QPSK_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1000 PutToDict(dict, "fec_inner", tmp);
1001 #if HAVE_DVB_API_VERSION >=3
1002 PutToDict(dict, "modulation",
1003 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ?
1004 eDVBFrontendParametersSatellite::Modulation_8PSK :
1005 eDVBFrontendParametersSatellite::Modulation_QPSK );
1006 if (parm_u_qpsk_fec_inner > FEC_AUTO)
1008 switch(parm_inversion & 0xc)
1010 default: // unknown rolloff
1011 case 0: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1012 case 4: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1013 case 8: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1015 PutToDict(dict, "rolloff", tmp);
1016 switch(parm_inversion & 0x30)
1018 case 0: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1019 case 0x10: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1020 case 0x20: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1022 PutToDict(dict, "pilot", tmp);
1023 tmp = eDVBFrontendParametersSatellite::System_DVB_S2;
1026 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1028 PutToDict(dict, "modulation", eDVBFrontendParametersSatellite::Modulation_QPSK );
1029 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1031 PutToDict(dict, "system", tmp);
1034 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1037 #if HAVE_DVB_API_VERSION < 3
1038 PutToDict(dict, "frequency", parm_frequency);
1040 PutToDict(dict, "frequency", parm_frequency/1000);
1042 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1043 switch(parm_u_qam_fec_inner)
1045 case FEC_NONE: tmp = eDVBFrontendParametersCable::FEC_None; break;
1046 case FEC_1_2: tmp = eDVBFrontendParametersCable::FEC_1_2; break;
1047 case FEC_2_3: tmp = eDVBFrontendParametersCable::FEC_2_3; break;
1048 case FEC_3_4: tmp = eDVBFrontendParametersCable::FEC_3_4; break;
1049 case FEC_5_6: tmp = eDVBFrontendParametersCable::FEC_5_6; break;
1050 case FEC_7_8: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1051 #if HAVE_DVB_API_VERSION >= 3
1052 case FEC_8_9: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1055 case FEC_AUTO: tmp = eDVBFrontendParametersCable::FEC_Auto; break;
1057 PutToDict(dict, "fec_inner", tmp);
1058 switch(parm_u_qam_modulation)
1060 case QAM_16: tmp = eDVBFrontendParametersCable::Modulation_QAM16; break;
1061 case QAM_32: tmp = eDVBFrontendParametersCable::Modulation_QAM32; break;
1062 case QAM_64: tmp = eDVBFrontendParametersCable::Modulation_QAM64; break;
1063 case QAM_128: tmp = eDVBFrontendParametersCable::Modulation_QAM128; break;
1064 case QAM_256: tmp = eDVBFrontendParametersCable::Modulation_QAM256; break;
1066 case QAM_AUTO: tmp = eDVBFrontendParametersCable::Modulation_Auto; break;
1068 PutToDict(dict, "modulation", tmp);
1071 void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1074 PutToDict(dict, "frequency", parm_frequency);
1075 switch (parm_u_ofdm_bandwidth)
1077 case BANDWIDTH_8_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_8MHz; break;
1078 case BANDWIDTH_7_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_7MHz; break;
1079 case BANDWIDTH_6_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_6MHz; break;
1081 case BANDWIDTH_AUTO: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_Auto; break;
1083 PutToDict(dict, "bandwidth", tmp);
1084 switch (parm_u_ofdm_code_rate_LP)
1086 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1087 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1088 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1089 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1090 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1092 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1094 PutToDict(dict, "code_rate_lp", tmp);
1095 switch (parm_u_ofdm_code_rate_HP)
1097 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1098 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1099 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1100 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1101 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1103 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1105 PutToDict(dict, "code_rate_hp", tmp);
1106 switch (parm_u_ofdm_constellation)
1108 case QPSK: tmp = eDVBFrontendParametersTerrestrial::Modulation_QPSK; break;
1109 case QAM_16: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM16; break;
1110 case QAM_64: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM64; break;
1112 case QAM_AUTO: tmp = eDVBFrontendParametersTerrestrial::Modulation_Auto; break;
1114 PutToDict(dict, "constellation", tmp);
1115 switch (parm_u_ofdm_transmission_mode)
1117 case TRANSMISSION_MODE_2K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_2k; break;
1118 case TRANSMISSION_MODE_8K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_8k; break;
1120 case TRANSMISSION_MODE_AUTO: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto; break;
1122 PutToDict(dict, "transmission_mode", tmp);
1123 switch (parm_u_ofdm_guard_interval)
1125 case GUARD_INTERVAL_1_32: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_32; break;
1126 case GUARD_INTERVAL_1_16: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_16; break;
1127 case GUARD_INTERVAL_1_8: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_8; break;
1128 case GUARD_INTERVAL_1_4: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_4; break;
1130 case GUARD_INTERVAL_AUTO: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_Auto; break;
1132 PutToDict(dict, "guard_interval", tmp);
1133 switch (parm_u_ofdm_hierarchy_information)
1135 case HIERARCHY_NONE: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_None; break;
1136 case HIERARCHY_1: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_1; break;
1137 case HIERARCHY_2: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_2; break;
1138 case HIERARCHY_4: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_4; break;
1140 case HIERARCHY_AUTO: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_Auto; break;
1142 PutToDict(dict, "hierarchy_information", tmp);
1145 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1147 if (dest && PyDict_Check(dest))
1149 const char *tmp = "UNKNOWN";
1170 PutToDict(dest, "tuner_state", tmp);
1171 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1172 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1173 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1174 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1175 int sigQualitydB = readFrontendData(signalQualitydB);
1176 if (sigQualitydB == 0x12345678) // not support yet
1178 ePyObject obj=Py_None;
1180 PutToDict(dest, "tuner_signal_quality_db", obj);
1183 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1184 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1188 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1190 if (dest && PyDict_Check(dest))
1198 FRONTENDPARAMETERS front;
1199 if (m_fd == -1 && !original)
1201 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1203 eDebug("FE_GET_FRONTEND failed (%m)");
1207 const FRONTENDPARAMETERS &parm = original || m_simulate ? this->parm : front;
1208 long tmp = eDVBFrontendParametersSatellite::Inversion_Unknown;
1209 switch(parm_inversion & 3)
1212 tmp = eDVBFrontendParametersSatellite::Inversion_On;
1215 tmp = eDVBFrontendParametersSatellite::Inversion_Off;
1219 PutToDict(dest, "inversion", tmp);
1224 fillDictWithSatelliteData(dest, original?parm:front, m_data[FREQ_OFFSET], m_cur_orbpos, m_cur_pol);
1227 fillDictWithCableData(dest, original?parm:front);
1230 fillDictWithTerrestrialData(dest, original?parm:front);
1241 void eDVBFrontend::getFrontendData(ePyObject dest)
1243 if (dest && PyDict_Check(dest))
1246 PutToDict(dest, "tuner_number", m_slotid);
1262 PutToDict(dest, "tuner_type", tmp);
1266 #ifndef FP_IOCTL_GET_ID
1267 #define FP_IOCTL_GET_ID 0
1269 int eDVBFrontend::readInputpower()
1273 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1275 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1276 FILE *f=fopen(proc_name, "r");
1279 if (fscanf(f, "%d", &power) != 1)
1280 eDebug("read %s failed!! (%m)", proc_name);
1282 eDebug("%s is %d\n", proc_name, power);
1287 // open front prozessor
1288 int fp=::open("/dev/dbox/fp0", O_RDWR);
1291 eDebug("couldn't open fp");
1294 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1295 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1297 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1306 bool eDVBFrontend::setSecSequencePos(int steps)
1308 eDebugNoSimulate("set sequence pos %d", steps);
1313 if (m_sec_sequence.current() != m_sec_sequence.end())
1314 ++m_sec_sequence.current();
1319 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1320 --m_sec_sequence.current();
1326 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1329 eDVBFrontend *sec_fe = this;
1330 eDVBRegisteredFrontend *regFE = 0;
1331 long tmp = m_data[LINKED_PREV_PTR];
1334 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1335 sec_fe = prev->m_frontend;
1336 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1337 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1338 int state = sec_fe->m_state;
1339 // workaround to put the kernel frontend thread into idle state!
1340 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1342 sec_fe->closeFrontend(true);
1343 state = sec_fe->m_state;
1345 // sec_fe is closed... we must reopen it here..
1346 if (state == stateClosed)
1354 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1356 long *sec_fe_data = sec_fe->m_data;
1357 // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1358 switch (m_sec_sequence.current()->cmd)
1360 case eSecCommand::SLEEP:
1361 delay = m_sec_sequence.current()++->msec;
1362 eDebugNoSimulate("[SEC] sleep %dms", delay);
1364 case eSecCommand::GOTO:
1365 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1366 ++m_sec_sequence.current();
1368 case eSecCommand::SET_VOLTAGE:
1370 int voltage = m_sec_sequence.current()++->voltage;
1371 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1372 sec_fe->setVoltage(voltage);
1375 case eSecCommand::IF_VOLTAGE_GOTO:
1377 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1378 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1380 ++m_sec_sequence.current();
1383 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1385 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1386 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1388 ++m_sec_sequence.current();
1391 case eSecCommand::IF_TONE_GOTO:
1393 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1394 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1396 ++m_sec_sequence.current();
1399 case eSecCommand::IF_NOT_TONE_GOTO:
1401 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1402 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1404 ++m_sec_sequence.current();
1407 case eSecCommand::SET_TONE:
1408 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1409 sec_fe->setTone(m_sec_sequence.current()++->tone);
1411 case eSecCommand::SEND_DISEQC:
1412 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1413 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1414 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1415 eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1416 if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
1417 eDebugNoSimulate("(DiSEqC reset)");
1418 else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
1419 eDebugNoSimulate("(DiSEqC peripherial power on)");
1421 eDebugNoSimulate("");
1422 ++m_sec_sequence.current();
1424 case eSecCommand::SEND_TONEBURST:
1425 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1426 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1428 case eSecCommand::SET_FRONTEND:
1430 int enableEvents = (m_sec_sequence.current()++)->val;
1431 eDebugNoSimulate("[SEC] setFrontend %d", enableEvents);
1432 setFrontend(enableEvents);
1435 case eSecCommand::START_TUNE_TIMEOUT:
1437 int tuneTimeout = m_sec_sequence.current()->timeout;
1438 eDebugNoSimulate("[SEC] startTuneTimeout %d", tuneTimeout);
1440 m_timeout->start(tuneTimeout, 1);
1441 ++m_sec_sequence.current();
1444 case eSecCommand::SET_TIMEOUT:
1445 m_timeoutCount = m_sec_sequence.current()++->val;
1446 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1448 case eSecCommand::IF_TIMEOUT_GOTO:
1449 if (!m_timeoutCount)
1451 eDebugNoSimulate("[SEC] rotor timout");
1452 setSecSequencePos(m_sec_sequence.current()->steps);
1455 ++m_sec_sequence.current();
1457 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1459 int idx = m_sec_sequence.current()++->val;
1460 if ( idx == 0 || idx == 1 )
1462 m_idleInputpower[idx] = sec_fe->readInputpower();
1463 eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1466 eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1469 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1471 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1472 int idx = compare.val;
1473 if ( !m_simulate && (idx == 0 || idx == 1) )
1475 int idle = sec_fe->readInputpower();
1476 int diff = abs(idle-m_idleInputpower[idx]);
1479 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1480 setSecSequencePos(compare.steps);
1484 ++m_sec_sequence.current();
1487 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1489 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1492 setSecSequencePos(cmd.steps);
1496 int isLocked = readFrontendData(locked);
1497 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1499 if (!m_timeoutCount && m_retryCount > 0)
1501 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 40) || !cmd.lastSignal))
1504 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1507 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1509 cmd.lastSignal = signal;
1512 if (cmd.okcount > 4)
1514 eDebugNoSimulate("ok > 4 .. goto %d\n", cmd.steps);
1515 setSecSequencePos(cmd.steps);
1516 m_state = stateLock;
1517 m_stateChanged(this);
1518 feEvent(-1); // flush events
1526 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1528 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1532 ++m_sec_sequence.current();
1535 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1536 m_runningInputpower = sec_fe->readInputpower();
1537 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1538 ++m_sec_sequence.current();
1540 case eSecCommand::SET_ROTOR_MOVING:
1542 m_sec->setRotorMoving(true);
1543 ++m_sec_sequence.current();
1545 case eSecCommand::SET_ROTOR_STOPPED:
1547 m_sec->setRotorMoving(false);
1548 ++m_sec_sequence.current();
1550 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1552 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1555 setSecSequencePos(cmd.steps);
1558 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1559 const char *txt = cmd.direction ? "running" : "stopped";
1561 if (!m_timeoutCount && m_retryCount > 0)
1563 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1565 m_runningInputpower,
1568 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1569 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1572 eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1573 if ( cmd.okcount > 6 )
1575 eDebugNoSimulate("[SEC] rotor is %s", txt);
1576 if (setSecSequencePos(cmd.steps))
1582 eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1585 ++m_sec_sequence.current();
1588 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1589 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1590 setSecSequencePos(m_sec_sequence.current()->steps);
1592 ++m_sec_sequence.current();
1594 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1595 eDebugNoSimulate("[SEC] invalidate current switch params");
1596 sec_fe_data[CSW] = -1;
1597 sec_fe_data[UCSW] = -1;
1598 sec_fe_data[TONEBURST] = -1;
1599 ++m_sec_sequence.current();
1601 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1602 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1603 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1604 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1605 eDebugNoSimulate("[SEC] update current switch params");
1606 ++m_sec_sequence.current();
1608 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1609 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1610 sec_fe_data[ROTOR_CMD] = -1;
1611 sec_fe_data[ROTOR_POS] = -1;
1612 ++m_sec_sequence.current();
1614 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1615 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1616 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1617 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1618 ++m_sec_sequence.current();
1620 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1621 m_retryCount = m_sec_sequence.current()++->val;
1622 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1624 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1627 eDebugNoSimulate("[SEC] no more rotor retrys");
1628 setSecSequencePos(m_sec_sequence.current()->steps);
1631 ++m_sec_sequence.current();
1633 case eSecCommand::SET_POWER_LIMITING_MODE:
1638 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1639 FILE *f=fopen(proc_name, "w");
1640 if (f) // new interface exist?
1642 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1643 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1644 eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1646 eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1649 else if (sec_fe->m_need_rotor_workaround)
1652 int slotid = sec_fe->m_slotid;
1653 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1655 sprintf(dev, "/dev/i2c/%d", slotid);
1656 else if (slotid == 2)
1657 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1658 else if (slotid == 3)
1659 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1660 int fd = ::open(dev, O_RDWR);
1662 unsigned char data[2];
1663 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1664 if(::read(fd, data, 1) != 1)
1665 eDebugNoSimulate("[SEC] error read lnbp (%m)");
1666 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1668 data[0] |= 0x80; // enable static current limiting
1669 eDebugNoSimulate("[SEC] set static current limiting");
1673 data[0] &= ~0x80; // enable dynamic current limiting
1674 eDebugNoSimulate("[SEC] set dynamic current limiting");
1676 if(::write(fd, data, 1) != 1)
1677 eDebugNoSimulate("[SEC] error write lnbp (%m)");
1681 ++m_sec_sequence.current();
1685 eDebugNoSimulate("[SEC] unhandled sec command %d",
1686 ++m_sec_sequence.current()->cmd);
1687 ++m_sec_sequence.current();
1690 m_tuneTimer->start(delay,true);
1694 if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1698 void eDVBFrontend::setFrontend(bool recvEvents)
1702 eDebug("setting frontend %d", m_dvbid);
1705 feEvent(-1); // flush events
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, 1) );
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, 1) );
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);