1 #include <lib/dvb/dvb.h>
2 #include <lib/base/eerror.h>
3 #include <lib/base/nconfig.h> // access to python config
9 #ifndef I2C_SLAVE_FORCE
10 #define I2C_SLAVE_FORCE 0x0706
13 #if HAVE_DVB_API_VERSION < 3
14 #include <ost/frontend.h>
16 #define QAM_AUTO (Modulation)6
17 #define TRANSMISSION_MODE_AUTO (TransmitMode)2
18 #define BANDWIDTH_AUTO (BandWidth)3
19 #define GUARD_INTERVAL_AUTO (GuardInterval)4
20 #define HIERARCHY_AUTO (Hierarchy)4
21 #define parm_frequency parm.Frequency
22 #define parm_inversion parm.Inversion
23 #define parm_u_qpsk_symbol_rate parm.u.qpsk.SymbolRate
24 #define parm_u_qpsk_fec_inner parm.u.qpsk.FEC_inner
25 #define parm_u_qam_symbol_rate parm.u.qam.SymbolRate
26 #define parm_u_qam_fec_inner parm.u.qam.FEC_inner
27 #define parm_u_qam_modulation parm.u.qam.QAM
28 #define parm_u_ofdm_bandwidth parm.u.ofdm.bandWidth
29 #define parm_u_ofdm_code_rate_LP parm.u.ofdm.LP_CodeRate
30 #define parm_u_ofdm_code_rate_HP parm.u.ofdm.HP_CodeRate
31 #define parm_u_ofdm_constellation parm.u.ofdm.Constellation
32 #define parm_u_ofdm_transmission_mode parm.u.ofdm.TransmissionMode
33 #define parm_u_ofdm_guard_interval parm.u.ofdm.guardInterval
34 #define parm_u_ofdm_hierarchy_information parm.u.ofdm.HierarchyInformation
36 #include <linux/dvb/frontend.h>
37 #define parm_frequency parm.frequency
38 #define parm_inversion parm.inversion
39 #define parm_u_qpsk_symbol_rate parm.u.qpsk.symbol_rate
40 #define parm_u_qpsk_fec_inner parm.u.qpsk.fec_inner
41 #define parm_u_qam_symbol_rate parm.u.qam.symbol_rate
42 #define parm_u_qam_fec_inner parm.u.qam.fec_inner
43 #define parm_u_qam_modulation parm.u.qam.modulation
44 #define parm_u_ofdm_bandwidth parm.u.ofdm.bandwidth
45 #define parm_u_ofdm_code_rate_LP parm.u.ofdm.code_rate_LP
46 #define parm_u_ofdm_code_rate_HP parm.u.ofdm.code_rate_HP
47 #define parm_u_ofdm_constellation parm.u.ofdm.constellation
48 #define parm_u_ofdm_transmission_mode parm.u.ofdm.transmission_mode
49 #define parm_u_ofdm_guard_interval parm.u.ofdm.guard_interval
50 #define parm_u_ofdm_hierarchy_information parm.u.ofdm.hierarchy_information
52 #warning "FEC_9_10 already exist in dvb api ... it seems it is now ready for DVB-S2"
54 #define FEC_S2_QPSK_1_2 (fe_code_rate_t)(FEC_AUTO+1)
55 #define FEC_S2_QPSK_2_3 (fe_code_rate_t)(FEC_S2_QPSK_1_2+1)
56 #define FEC_S2_QPSK_3_4 (fe_code_rate_t)(FEC_S2_QPSK_2_3+1)
57 #define FEC_S2_QPSK_5_6 (fe_code_rate_t)(FEC_S2_QPSK_3_4+1)
58 #define FEC_S2_QPSK_7_8 (fe_code_rate_t)(FEC_S2_QPSK_5_6+1)
59 #define FEC_S2_QPSK_8_9 (fe_code_rate_t)(FEC_S2_QPSK_7_8+1)
60 #define FEC_S2_QPSK_3_5 (fe_code_rate_t)(FEC_S2_QPSK_8_9+1)
61 #define FEC_S2_QPSK_4_5 (fe_code_rate_t)(FEC_S2_QPSK_3_5+1)
62 #define FEC_S2_QPSK_9_10 (fe_code_rate_t)(FEC_S2_QPSK_4_5+1)
63 #define FEC_S2_8PSK_1_2 (fe_code_rate_t)(FEC_S2_QPSK_9_10+1)
64 #define FEC_S2_8PSK_2_3 (fe_code_rate_t)(FEC_S2_8PSK_1_2+1)
65 #define FEC_S2_8PSK_3_4 (fe_code_rate_t)(FEC_S2_8PSK_2_3+1)
66 #define FEC_S2_8PSK_5_6 (fe_code_rate_t)(FEC_S2_8PSK_3_4+1)
67 #define FEC_S2_8PSK_7_8 (fe_code_rate_t)(FEC_S2_8PSK_5_6+1)
68 #define FEC_S2_8PSK_8_9 (fe_code_rate_t)(FEC_S2_8PSK_7_8+1)
69 #define FEC_S2_8PSK_3_5 (fe_code_rate_t)(FEC_S2_8PSK_8_9+1)
70 #define FEC_S2_8PSK_4_5 (fe_code_rate_t)(FEC_S2_8PSK_3_5+1)
71 #define FEC_S2_8PSK_9_10 (fe_code_rate_t)(FEC_S2_8PSK_4_5+1)
75 #include <dvbsi++/satellite_delivery_system_descriptor.h>
76 #include <dvbsi++/cable_delivery_system_descriptor.h>
77 #include <dvbsi++/terrestrial_delivery_system_descriptor.h>
79 void eDVBDiseqcCommand::setCommandString(const char *str)
84 int slen = strlen(str);
87 eDebug("invalid diseqc command string length (not 2 byte aligned)");
90 if (slen > MAX_DISEQC_LENGTH*2)
92 eDebug("invalid diseqc command string length (string is to long)");
96 for (int i=0; i < slen; ++i)
98 unsigned char c = str[i];
101 case '0' ... '9': c-=48; break;
102 case 'a' ... 'f': c-=87; break;
103 case 'A' ... 'F': c-=55; break;
105 eDebug("invalid character in hex string..ignore complete diseqc command !");
119 void eDVBFrontendParametersSatellite::set(const SatelliteDeliverySystemDescriptor &descriptor)
121 frequency = descriptor.getFrequency() * 10;
122 symbol_rate = descriptor.getSymbolRate() * 100;
123 polarisation = descriptor.getPolarization();
124 fec = descriptor.getFecInner();
125 if ( fec != FEC::fNone && fec > FEC::f9_10 )
127 inversion = Inversion::Unknown;
128 pilot = Pilot::Unknown;
129 orbital_position = ((descriptor.getOrbitalPosition() >> 12) & 0xF) * 1000;
130 orbital_position += ((descriptor.getOrbitalPosition() >> 8) & 0xF) * 100;
131 orbital_position += ((descriptor.getOrbitalPosition() >> 4) & 0xF) * 10;
132 orbital_position += ((descriptor.getOrbitalPosition()) & 0xF);
133 if (orbital_position && (!descriptor.getWestEastFlag()))
134 orbital_position = 3600 - orbital_position;
135 system = descriptor.getModulationSystem();
136 modulation = descriptor.getModulation();
137 if (system == System::DVB_S && modulation == Modulation::M8PSK)
139 eDebug("satellite_delivery_descriptor non valid modulation type.. force QPSK");
142 rolloff = descriptor.getRollOff();
143 if (system == System::DVB_S2)
145 eDebug("SAT DVB-S2 freq %d, %s, pos %d, sr %d, fec %d, modulation %d, rolloff %d",
147 polarisation ? "hor" : "vert",
155 eDebug("SAT DVB-S freq %d, %s, pos %d, sr %d, fec %d",
157 polarisation ? "hor" : "vert",
163 void eDVBFrontendParametersCable::set(const CableDeliverySystemDescriptor &descriptor)
165 frequency = descriptor.getFrequency() / 10;
166 symbol_rate = descriptor.getSymbolRate() * 100;
167 fec_inner = descriptor.getFecInner();
168 if ( fec_inner == 0xF )
169 fec_inner = FEC::fNone;
170 modulation = descriptor.getModulation();
171 if ( modulation > 0x5 )
172 modulation = Modulation::Auto;
173 inversion = Inversion::Unknown;
174 eDebug("Cable freq %d, mod %d, sr %d, fec %d",
176 modulation, symbol_rate, fec_inner);
179 void eDVBFrontendParametersTerrestrial::set(const TerrestrialDeliverySystemDescriptor &descriptor)
181 frequency = descriptor.getCentreFrequency() * 10;
182 bandwidth = descriptor.getBandwidth();
183 if ( bandwidth > 2 ) // 5Mhz forced to auto
184 bandwidth = Bandwidth::BwAuto;
185 code_rate_HP = descriptor.getCodeRateHpStream();
186 if (code_rate_HP > 4)
187 code_rate_HP = FEC::fAuto;
188 code_rate_LP = descriptor.getCodeRateLpStream();
189 if (code_rate_LP > 4)
190 code_rate_LP = FEC::fAuto;
191 transmission_mode = descriptor.getTransmissionMode();
192 if (transmission_mode > 1) // TM4k forced to auto
193 transmission_mode = TransmissionMode::TMAuto;
194 guard_interval = descriptor.getGuardInterval();
195 if (guard_interval > 3)
196 guard_interval = GuardInterval::GI_Auto;
197 hierarchy = descriptor.getHierarchyInformation()&3;
198 modulation = descriptor.getConstellation();
200 modulation = Modulation::Auto;
201 inversion = Inversion::Unknown;
202 eDebug("Terr freq %d, bw %d, cr_hp %d, cr_lp %d, tm_mode %d, guard %d, hierarchy %d, const %d",
203 frequency, bandwidth, code_rate_HP, code_rate_LP, transmission_mode,
204 guard_interval, hierarchy, modulation);
207 eDVBFrontendParameters::eDVBFrontendParameters(): m_type(-1)
211 DEFINE_REF(eDVBFrontendParameters);
213 RESULT eDVBFrontendParameters::getSystem(int &t) const
221 RESULT eDVBFrontendParameters::getDVBS(eDVBFrontendParametersSatellite &p) const
223 if (m_type != iDVBFrontend::feSatellite)
229 RESULT eDVBFrontendParameters::getDVBC(eDVBFrontendParametersCable &p) const
231 if (m_type != iDVBFrontend::feCable)
237 RESULT eDVBFrontendParameters::getDVBT(eDVBFrontendParametersTerrestrial &p) const
239 if (m_type != iDVBFrontend::feTerrestrial)
245 RESULT eDVBFrontendParameters::setDVBS(const eDVBFrontendParametersSatellite &p, bool no_rotor_command_on_tune)
248 sat.no_rotor_command_on_tune = no_rotor_command_on_tune;
249 m_type = iDVBFrontend::feSatellite;
253 RESULT eDVBFrontendParameters::setDVBC(const eDVBFrontendParametersCable &p)
256 m_type = iDVBFrontend::feCable;
260 RESULT eDVBFrontendParameters::setDVBT(const eDVBFrontendParametersTerrestrial &p)
263 m_type = iDVBFrontend::feTerrestrial;
267 RESULT eDVBFrontendParameters::calculateDifference(const iDVBFrontendParameters *parm, int &diff, bool exact) const
272 if (parm->getSystem(type))
276 diff = 1<<30; // big difference
282 case iDVBFrontend::feSatellite:
284 eDVBFrontendParametersSatellite osat;
285 if (parm->getDVBS(osat))
288 if (sat.orbital_position != osat.orbital_position)
290 else if (sat.polarisation != osat.polarisation)
292 else if (exact && sat.fec != osat.fec && sat.fec != eDVBFrontendParametersSatellite::FEC::fAuto && osat.fec != eDVBFrontendParametersSatellite::FEC::fAuto)
294 else if (exact && sat.modulation != osat.modulation && sat.modulation != eDVBFrontendParametersSatellite::Modulation::Auto && osat.modulation != eDVBFrontendParametersSatellite::Modulation::Auto)
298 diff = abs(sat.frequency - osat.frequency);
299 diff += abs(sat.symbol_rate - osat.symbol_rate);
303 case iDVBFrontend::feCable:
304 eDVBFrontendParametersCable ocable;
305 if (parm->getDVBC(ocable))
308 if (exact && cable.modulation != ocable.modulation
309 && cable.modulation != eDVBFrontendParametersCable::Modulation::Auto
310 && ocable.modulation != eDVBFrontendParametersCable::Modulation::Auto)
312 else if (exact && cable.fec_inner != ocable.fec_inner && cable.fec_inner != eDVBFrontendParametersCable::FEC::fAuto && ocable.fec_inner != eDVBFrontendParametersCable::FEC::fAuto)
316 diff = abs(cable.frequency - ocable.frequency);
317 diff += abs(cable.symbol_rate - ocable.symbol_rate);
320 case iDVBFrontend::feTerrestrial:
321 eDVBFrontendParametersTerrestrial oterrestrial;
322 if (parm->getDVBT(oterrestrial))
326 if (exact && oterrestrial.bandwidth != terrestrial.bandwidth &&
327 oterrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto &&
328 terrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto)
330 else if (exact && oterrestrial.modulation != terrestrial.modulation &&
331 oterrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation::Auto &&
332 terrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation::Auto)
334 else if (exact && oterrestrial.transmission_mode != terrestrial.transmission_mode &&
335 oterrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto &&
336 terrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto)
338 else if (exact && oterrestrial.guard_interval != terrestrial.guard_interval &&
339 oterrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto &&
340 terrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto)
342 else if (exact && oterrestrial.hierarchy != terrestrial.hierarchy &&
343 oterrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy::HAuto &&
344 terrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy::HAuto)
346 else if (exact && oterrestrial.code_rate_LP != terrestrial.code_rate_LP &&
347 oterrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC::fAuto &&
348 terrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC::fAuto)
350 else if (exact && oterrestrial.code_rate_HP != terrestrial.code_rate_HP &&
351 oterrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC::fAuto &&
352 terrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC::fAuto)
355 diff = abs(terrestrial.frequency - oterrestrial.frequency);
363 RESULT eDVBFrontendParameters::getHash(unsigned long &hash) const
367 case iDVBFrontend::feSatellite:
369 hash = (sat.orbital_position << 16);
370 hash |= ((sat.frequency/1000)&0xFFFF)|((sat.polarisation&1) << 15);
373 case iDVBFrontend::feCable:
375 hash |= (cable.frequency/1000)&0xFFFF;
377 case iDVBFrontend::feTerrestrial:
379 hash |= (terrestrial.frequency/1000)&0xFFFF;
386 RESULT eDVBFrontendParameters::calcLockTimeout(unsigned int &timeout) const
390 case iDVBFrontend::feSatellite:
392 /* high symbol rate transponders tune faster, due to
393 requiring less zigzag and giving more symbols faster.
395 5s are definitely not enough on really low SR when
396 zigzag has to find the exact frequency first.
398 if (sat.symbol_rate > 20000000)
400 else if (sat.symbol_rate > 10000000)
406 case iDVBFrontend::feCable:
409 case iDVBFrontend::feTerrestrial:
417 DEFINE_REF(eDVBFrontend);
419 int eDVBFrontend::PriorityOrder=0;
421 eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok)
422 :m_enabled(false), m_type(-1), m_dvbid(fe), m_slotid(fe)
423 ,m_fd(-1), m_need_rotor_workaround(false), m_sn(0), m_timeout(0), m_tuneTimer(0)
424 #if HAVE_DVB_API_VERSION < 3
428 #if HAVE_DVB_API_VERSION < 3
429 sprintf(m_filename, "/dev/dvb/card%d/frontend%d", adap, fe);
430 sprintf(m_sec_filename, "/dev/dvb/card%d/sec%d", adap, fe);
432 sprintf(m_filename, "/dev/dvb/adapter%d/frontend%d", adap, fe);
434 m_timeout = new eTimer(eApp);
435 CONNECT(m_timeout->timeout, eDVBFrontend::timeout);
437 m_tuneTimer = new eTimer(eApp);
438 CONNECT(m_tuneTimer->timeout, eDVBFrontend::tuneLoop);
440 for (int i=0; i<eDVBFrontend::NUM_DATA_ENTRIES; ++i)
443 m_idleInputpower[0]=m_idleInputpower[1]=0;
445 ok = !openFrontend();
449 int eDVBFrontend::openFrontend()
452 return -1; // already opened
457 #if HAVE_DVB_API_VERSION < 3
458 FrontendInfo fe_info;
460 dvb_frontend_info fe_info;
462 eDebug("opening frontend %d", m_dvbid);
465 m_fd = ::open(m_filename, O_RDWR|O_NONBLOCK);
468 eWarning("failed! (%s) %m", m_filename);
473 eWarning("frontend %d already opened", m_dvbid);
476 if (::ioctl(m_fd, FE_GET_INFO, &fe_info) < 0)
478 eWarning("ioctl FE_GET_INFO failed");
484 switch (fe_info.type)
487 m_type = iDVBFrontend::feSatellite;
490 m_type = iDVBFrontend::feCable;
493 m_type = iDVBFrontend::feTerrestrial;
496 eWarning("unknown frontend type.");
501 eDebug("detected %s frontend", "satellite\0cable\0 terrestrial"+fe_info.type*10);
504 #if HAVE_DVB_API_VERSION < 3
505 if (m_type == iDVBFrontend::feSatellite)
509 m_secfd = ::open(m_sec_filename, O_RDWR);
512 eWarning("failed! (%s) %m", m_sec_filename);
519 eWarning("sec %d already opened", m_dvbid);
523 setTone(iDVBFrontend::toneOff);
524 setVoltage(iDVBFrontend::voltageOff);
526 m_sn = new eSocketNotifier(eApp, m_fd, eSocketNotifier::Read);
527 CONNECT(m_sn->activated, eDVBFrontend::feEvent);
532 int eDVBFrontend::closeFrontend()
534 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)m_data[LINKED_NEXT_PTR];
535 while (linked_fe != (eDVBRegisteredFrontend*)-1)
537 if (linked_fe->m_inuse)
539 eDebug("dont close frontend %d until the linked frontend %d in slot %d is still in use",
540 m_dvbid, linked_fe->m_frontend->getDVBID(), linked_fe->m_frontend->getSlotID());
543 linked_fe->m_frontend->getData(LINKED_NEXT_PTR, (long&)linked_fe);
547 eDebug("close frontend %d", m_dvbid);
549 setTone(iDVBFrontend::toneOff);
550 setVoltage(iDVBFrontend::voltageOff);
552 m_sec->setRotorMoving(false);
556 eWarning("couldnt close frontend %d", m_dvbid);
557 m_data[CSW] = m_data[UCSW] = m_data[TONEBURST] = -1;
559 #if HAVE_DVB_API_VERSION < 3
562 if (!::close(m_secfd))
565 eWarning("couldnt close sec %d", m_dvbid);
574 eDVBFrontend::~eDVBFrontend()
581 void eDVBFrontend::feEvent(int w)
585 #if HAVE_DVB_API_VERSION < 3
588 dvb_frontend_event event;
592 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
594 if (res && (errno == EAGAIN))
599 eWarning("FE_GET_EVENT failed! %m");
606 #if HAVE_DVB_API_VERSION < 3
607 if (event.type == FE_COMPLETION_EV)
609 eDebug("(%d)fe event: status %x, inversion %s", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off");
610 if (event.status & FE_HAS_LOCK)
620 eDebug("stateLostLock");
621 state = stateLostLock;
622 m_data[CSW] = m_data[UCSW] = m_data[TONEBURST] = -1; // reset diseqc
625 if (m_state != state)
628 m_stateChanged(this);
633 void eDVBFrontend::timeout()
636 if (m_state == stateTuning)
638 m_state = stateFailed;
639 m_stateChanged(this);
643 int eDVBFrontend::readFrontendData(int type)
650 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
651 eDebug("FE_READ_BER failed (%m)");
657 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
658 eDebug("FE_READ_SNR failed (%m)");
661 case signalQualitydB: /* this will move into the driver */
664 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
665 eDebug("FE_READ_SNR failed (%m)");
666 if (!strcmp(m_description, "BCM4501 (internal)"))
668 unsigned int SDS_SNRE = snr << 16;
670 static float SNR_COEFF[6] = {
673 197418.0 / 4194304.0,
674 -2602183.0 / 4194304.0,
675 20377212.0 / 4194304.0,
676 -37791203.0 / 4194304.0,
679 float fval1, fval2, snr_in_db;
681 fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0));
682 fval2 = pow(10.0, fval1)-1;
683 fval1 = 10.0 * log10(fval2);
687 fval2 = SNR_COEFF[0];
691 fval2 += SNR_COEFF[i];
697 return (int)(snr_in_db * 100.0);
699 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
700 !strcmp(m_description, "Alps -S") ||
701 !strcmp(m_description, "Philips -S") ||
702 !strcmp(m_description, "LG -S") )
704 float snr_in_db=(snr-39075)/1764.7;
705 return (int)(snr_in_db * 100.0);
706 } else if (!strcmp(m_description, "Alps BSBE2"))
708 return (int)((snr >> 7) * 10.0);
710 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
716 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
717 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
722 #if HAVE_DVB_API_VERSION < 3
723 FrontendStatus status=0;
727 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
728 eDebug("FE_READ_STATUS failed (%m)");
729 return !!(status&FE_HAS_LOCK);
733 #if HAVE_DVB_API_VERSION < 3
734 FrontendStatus status=0;
738 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
739 eDebug("FE_READ_STATUS failed (%m)");
740 return !!(status&FE_HAS_SYNC);
748 void PutToDict(ePyObject &dict, const char*key, long value)
750 ePyObject item = PyInt_FromLong(value);
753 if (PyDict_SetItemString(dict, key, item))
754 eDebug("put %s to dict failed", key);
758 eDebug("could not create PyObject for %s", key);
761 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
765 if (PyDict_SetItemString(dict, key, item))
766 eDebug("put %s to dict failed", key);
770 eDebug("invalid PyObject for %s", key);
773 void PutToDict(ePyObject &dict, const char*key, const char *value)
775 ePyObject item = PyString_FromString(value);
778 if (PyDict_SetItemString(dict, key, item))
779 eDebug("put %s to dict failed", key);
783 eDebug("could not create PyObject for %s", key);
786 void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, eDVBFrontend *fe)
791 fe->getData(eDVBFrontend::CSW, csw);
792 fe->getData(eDVBFrontend::FREQ_OFFSET, freq_offset);
793 int frequency = parm_frequency + freq_offset;
794 PutToDict(dict, "frequency", frequency);
795 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
796 switch(parm_u_qpsk_fec_inner)
819 #if HAVE_DVB_API_VERSION >=3
820 case FEC_S2_8PSK_1_2:
821 case FEC_S2_QPSK_1_2:
824 case FEC_S2_8PSK_2_3:
825 case FEC_S2_QPSK_2_3:
828 case FEC_S2_8PSK_3_4:
829 case FEC_S2_QPSK_3_4:
832 case FEC_S2_8PSK_5_6:
833 case FEC_S2_QPSK_5_6:
836 case FEC_S2_8PSK_7_8:
837 case FEC_S2_QPSK_7_8:
840 case FEC_S2_8PSK_8_9:
841 case FEC_S2_QPSK_8_9:
844 case FEC_S2_8PSK_3_5:
845 case FEC_S2_QPSK_3_5:
848 case FEC_S2_8PSK_4_5:
849 case FEC_S2_QPSK_4_5:
852 case FEC_S2_8PSK_9_10:
853 case FEC_S2_QPSK_9_10:
858 PutToDict(dict, "fec_inner", tmp);
859 #if HAVE_DVB_API_VERSION >=3
860 PutToDict(dict, "modulation",
861 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ? "8PSK": "QPSK" );
862 if (parm_u_qpsk_fec_inner > FEC_AUTO)
864 switch(parm_inversion & 0xc)
866 default: // unknown rolloff
868 tmp = "ROLLOFF_0_35";
871 tmp = "ROLLOFF_0_25";
874 tmp = "ROLLOFF_0_20";
877 PutToDict(dict, "rolloff", tmp);
878 if (parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10)
880 switch(parm_inversion & 0x30)
885 case 0x10: // pilot on
888 case 0x20: // pilot auto
892 PutToDict(dict, "pilot", tmp);
899 PutToDict(dict, "modulation", "QPSK" );
902 PutToDict(dict, "system", tmp);
905 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
908 #if HAVE_DVB_API_VERSION < 3
909 PutToDict(dict, "frequency", parm_frequency);
911 PutToDict(dict, "frequency", parm_frequency/1000);
913 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
914 switch(parm_u_qam_fec_inner)
934 #if HAVE_DVB_API_VERSION >= 3
944 PutToDict(dict, "fec_inner", tmp);
945 switch(parm_u_qam_modulation)
967 PutToDict(dict, "modulation", tmp);
970 void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
973 PutToDict(dict, "frequency", parm_frequency);
974 switch (parm_u_ofdm_bandwidth)
976 case BANDWIDTH_8_MHZ:
977 tmp = "BANDWIDTH_8_MHZ";
979 case BANDWIDTH_7_MHZ:
980 tmp = "BANDWIDTH_7_MHZ";
982 case BANDWIDTH_6_MHZ:
983 tmp = "BANDWIDTH_6_MHZ";
987 tmp = "BANDWIDTH_AUTO";
990 PutToDict(dict, "bandwidth", tmp);
991 switch (parm_u_ofdm_code_rate_LP)
1013 PutToDict(dict, "code_rate_lp", tmp);
1014 switch (parm_u_ofdm_code_rate_HP)
1036 PutToDict(dict, "code_rate_hp", tmp);
1037 switch (parm_u_ofdm_constellation)
1053 PutToDict(dict, "constellation", tmp);
1054 switch (parm_u_ofdm_transmission_mode)
1056 case TRANSMISSION_MODE_2K:
1057 tmp = "TRANSMISSION_MODE_2K";
1059 case TRANSMISSION_MODE_8K:
1060 tmp = "TRANSMISSION_MODE_8K";
1063 case TRANSMISSION_MODE_AUTO:
1064 tmp = "TRANSMISSION_MODE_AUTO";
1067 PutToDict(dict, "transmission_mode", tmp);
1068 switch (parm_u_ofdm_guard_interval)
1070 case GUARD_INTERVAL_1_32:
1071 tmp = "GUARD_INTERVAL_1_32";
1073 case GUARD_INTERVAL_1_16:
1074 tmp = "GUARD_INTERVAL_1_16";
1076 case GUARD_INTERVAL_1_8:
1077 tmp = "GUARD_INTERVAL_1_8";
1079 case GUARD_INTERVAL_1_4:
1080 tmp = "GUARD_INTERVAL_1_4";
1083 case GUARD_INTERVAL_AUTO:
1084 tmp = "GUARD_INTERVAL_AUTO";
1087 PutToDict(dict, "guard_interval", tmp);
1088 switch (parm_u_ofdm_hierarchy_information)
1090 case HIERARCHY_NONE:
1091 tmp = "HIERARCHY_NONE";
1094 tmp = "HIERARCHY_1";
1097 tmp = "HIERARCHY_2";
1100 tmp = "HIERARCHY_4";
1103 case HIERARCHY_AUTO:
1104 tmp = "HIERARCHY_AUTO";
1107 PutToDict(dict, "hierarchy_information", tmp);
1110 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1112 if (dest && PyDict_Check(dest))
1114 const char *tmp = "UNKNOWN";
1135 PutToDict(dest, "tuner_state", tmp);
1136 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1137 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1138 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1139 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1140 int sigQualitydB = readFrontendData(signalQualitydB);
1141 if (sigQualitydB == 0x12345678) // not support yet
1143 ePyObject obj=Py_None;
1145 PutToDict(dest, "tuner_signal_quality_db", obj);
1148 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1149 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1153 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1155 if (m_fd != -1 && dest && PyDict_Check(dest))
1163 FRONTENDPARAMETERS front;
1164 if (!original && ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1165 eDebug("FE_GET_FRONTEND (%m)");
1168 const FRONTENDPARAMETERS &parm = original ? this->parm : front;
1169 const char *tmp = "INVERSION_AUTO";
1170 switch(parm_inversion)
1173 tmp = "INVERSION_ON";
1176 tmp = "INVERSION_OFF";
1182 PutToDict(dest, "inversion", tmp);
1187 fillDictWithSatelliteData(dest, original?parm:front, this);
1190 fillDictWithCableData(dest, original?parm:front);
1193 fillDictWithTerrestrialData(dest, original?parm:front);
1204 void eDVBFrontend::getFrontendData(ePyObject dest)
1206 if (dest && PyDict_Check(dest))
1209 PutToDict(dest, "tuner_number", m_dvbid);
1225 PutToDict(dest, "tuner_type", tmp);
1229 #ifndef FP_IOCTL_GET_ID
1230 #define FP_IOCTL_GET_ID 0
1232 int eDVBFrontend::readInputpower()
1234 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1236 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1237 FILE *f=fopen(proc_name, "r");
1240 if (fscanf(f, "%08x", &power) != 1)
1241 eDebug("read %s failed!! (%m)", proc_name);
1243 eDebug("%s is %d\n", proc_name, power);
1248 // open front prozessor
1249 int fp=::open("/dev/dbox/fp0", O_RDWR);
1252 eDebug("couldn't open fp");
1255 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1256 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1258 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1267 bool eDVBFrontend::setSecSequencePos(int steps)
1269 eDebug("set sequence pos %d", steps);
1274 if (m_sec_sequence.current() != m_sec_sequence.end())
1275 ++m_sec_sequence.current();
1280 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1281 --m_sec_sequence.current();
1287 void eDVBFrontend::setRotorData(int pos, int cmd)
1289 m_data[ROTOR_CMD] = cmd;
1290 m_data[ROTOR_POS] = pos;
1291 if ( m_data[SATPOS_DEPENDS_PTR] != -1 )
1293 eDVBRegisteredFrontend *satpos_depends_to_fe = (eDVBRegisteredFrontend*) m_data[SATPOS_DEPENDS_PTR];
1294 satpos_depends_to_fe->m_frontend->m_data[ROTOR_CMD] = cmd;
1295 satpos_depends_to_fe->m_frontend->m_data[ROTOR_POS] = pos;
1299 eDVBRegisteredFrontend *next = (eDVBRegisteredFrontend *)m_data[LINKED_NEXT_PTR];
1300 while ( (long)next != -1 )
1302 next->m_frontend->m_data[ROTOR_CMD] = cmd;
1303 next->m_frontend->m_data[ROTOR_POS] = pos;
1304 next = (eDVBRegisteredFrontend *)next->m_frontend->m_data[LINKED_NEXT_PTR];
1306 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)m_data[LINKED_PREV_PTR];
1307 while ( (long)prev != -1 )
1309 prev->m_frontend->m_data[ROTOR_CMD] = cmd;
1310 prev->m_frontend->m_data[ROTOR_POS] = pos;
1311 prev = (eDVBRegisteredFrontend *)prev->m_frontend->m_data[LINKED_PREV_PTR];
1316 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1319 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1321 // eDebug("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1322 switch (m_sec_sequence.current()->cmd)
1324 case eSecCommand::SLEEP:
1325 delay = m_sec_sequence.current()++->msec;
1326 eDebug("[SEC] sleep %dms", delay);
1328 case eSecCommand::GOTO:
1329 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1330 ++m_sec_sequence.current();
1332 case eSecCommand::SET_VOLTAGE:
1334 int voltage = m_sec_sequence.current()++->voltage;
1335 eDebug("[SEC] setVoltage %d", voltage);
1336 setVoltage(voltage);
1339 case eSecCommand::IF_VOLTAGE_GOTO:
1341 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1342 if ( compare.voltage == m_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1344 ++m_sec_sequence.current();
1347 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1349 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1350 if ( compare.voltage != m_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1352 ++m_sec_sequence.current();
1355 case eSecCommand::IF_TONE_GOTO:
1357 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1358 if ( compare.tone == m_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1360 ++m_sec_sequence.current();
1363 case eSecCommand::IF_NOT_TONE_GOTO:
1365 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1366 if ( compare.tone != m_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1368 ++m_sec_sequence.current();
1371 case eSecCommand::SET_TONE:
1372 eDebug("[SEC] setTone %d", m_sec_sequence.current()->tone);
1373 setTone(m_sec_sequence.current()++->tone);
1375 case eSecCommand::SEND_DISEQC:
1376 sendDiseqc(m_sec_sequence.current()->diseqc);
1377 eDebugNoNewLine("[SEC] sendDiseqc: ");
1378 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1379 eDebugNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1381 ++m_sec_sequence.current();
1383 case eSecCommand::SEND_TONEBURST:
1384 eDebug("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1385 sendToneburst(m_sec_sequence.current()++->toneburst);
1387 case eSecCommand::SET_FRONTEND:
1388 eDebug("[SEC] setFrontend");
1390 ++m_sec_sequence.current();
1392 case eSecCommand::START_TUNE_TIMEOUT:
1394 m_timeout->start(m_sec_sequence.current()->timeout, 1);
1395 ++m_sec_sequence.current();
1398 case eSecCommand::SET_TIMEOUT:
1399 m_timeoutCount = m_sec_sequence.current()++->val;
1400 eDebug("[SEC] set timeout %d", m_timeoutCount);
1402 case eSecCommand::IF_TIMEOUT_GOTO:
1403 if (!m_timeoutCount)
1405 eDebug("[SEC] rotor timout");
1406 m_sec->setRotorMoving(false);
1407 setSecSequencePos(m_sec_sequence.current()->steps);
1410 ++m_sec_sequence.current();
1412 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1414 int idx = m_sec_sequence.current()++->val;
1415 if ( idx == 0 || idx == 1 )
1417 m_idleInputpower[idx] = readInputpower();
1418 eDebug("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1421 eDebug("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1424 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1426 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1427 int idx = compare.val;
1428 if ( idx == 0 || idx == 1 )
1430 int idle = readInputpower();
1431 int diff = abs(idle-m_idleInputpower[idx]);
1434 eDebug("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1435 setSecSequencePos(compare.steps);
1439 ++m_sec_sequence.current();
1442 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1444 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1445 if (readFrontendData(locked))
1447 eDebug("[SEC] locked step %d ok", cmd.okcount);
1449 if (cmd.okcount > 12)
1451 eDebug("ok > 12 .. goto %d\n",m_sec_sequence.current()->steps);
1452 setSecSequencePos(cmd.steps);
1458 eDebug("[SEC] rotor locked step %d failed", cmd.okcount);
1460 if (!m_timeoutCount && m_retryCount > 0)
1464 ++m_sec_sequence.current();
1467 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1468 m_runningInputpower = readInputpower();
1469 eDebug("[SEC] runningInputpower is %d", m_runningInputpower);
1470 ++m_sec_sequence.current();
1472 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1474 int idleInputpower = m_idleInputpower[ (m_data[CUR_VOLTAGE]&1) ? 0 : 1];
1475 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1476 const char *txt = cmd.direction ? "running" : "stopped";
1477 eDebug("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1479 m_runningInputpower,
1482 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1483 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1486 eDebug("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1487 if ( cmd.okcount > 6 )
1489 m_sec->setRotorMoving(cmd.direction);
1490 eDebug("[SEC] rotor is %s", txt);
1491 if (setSecSequencePos(cmd.steps))
1497 eDebug("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1499 if (!m_timeoutCount && m_retryCount > 0)
1503 ++m_sec_sequence.current();
1506 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1507 if (m_data[ROTOR_CMD] != -1 && m_data[ROTOR_POS] != -1)
1508 setSecSequencePos(m_sec_sequence.current()->steps);
1510 ++m_sec_sequence.current();
1512 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1513 eDebug("[SEC] invalidate current rotorparams");
1514 setRotorData(-1,-1);
1515 ++m_sec_sequence.current();
1517 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1518 setRotorData(m_data[NEW_ROTOR_POS], m_data[NEW_ROTOR_CMD]);
1519 eDebug("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, m_data[ROTOR_CMD], m_data[ROTOR_POS]);
1520 ++m_sec_sequence.current();
1522 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1523 m_retryCount = m_sec_sequence.current()++->val;
1524 eDebug("[SEC] set rotor retries %d", m_retryCount);
1526 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1529 eDebug("[SEC] no more rotor retrys");
1530 setSecSequencePos(m_sec_sequence.current()->steps);
1533 ++m_sec_sequence.current();
1535 case eSecCommand::SET_POWER_LIMITING_MODE:
1537 if (m_need_rotor_workaround)
1541 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1543 sprintf(dev, "/dev/i2c/%d", m_slotid);
1544 else if (m_slotid == 2)
1545 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1546 else if (m_slotid == 3)
1547 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1548 int fd = ::open(dev, O_RDWR);
1550 unsigned char data[2];
1551 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1552 if(::read(fd, data, 1) != 1)
1553 eDebug("[SEC] error read lnbp (%m)");
1554 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1556 data[0] |= 0x80; // enable static current limiting
1557 eDebug("[SEC] set static current limiting");
1561 data[0] &= ~0x80; // enable dynamic current limiting
1562 eDebug("[SEC] set dynamic current limiting");
1564 if(::write(fd, data, 1) != 1)
1565 eDebug("[SEC] error write lnbp (%m)");
1568 ++m_sec_sequence.current();
1572 eDebug("[SEC] unhandled sec command %d",
1573 ++m_sec_sequence.current()->cmd);
1574 ++m_sec_sequence.current();
1576 m_tuneTimer->start(delay,true);
1580 void eDVBFrontend::setFrontend()
1582 eDebug("setting frontend %d", m_dvbid);
1585 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1587 perror("FE_SET_FRONTEND failed");
1592 RESULT eDVBFrontend::getFrontendType(int &t)
1600 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1605 eWarning("no SEC module active!");
1608 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1611 eDebug("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1614 feparm.polarisation,
1618 feparm.orbital_position);
1619 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1620 switch (feparm.inversion)
1622 case eDVBFrontendParametersSatellite::Inversion::On:
1623 parm_inversion = INVERSION_ON;
1625 case eDVBFrontendParametersSatellite::Inversion::Off:
1626 parm_inversion = INVERSION_OFF;
1629 case eDVBFrontendParametersSatellite::Inversion::Unknown:
1630 parm_inversion = INVERSION_AUTO;
1633 if (feparm.system == eDVBFrontendParametersSatellite::System::DVB_S)
1636 case eDVBFrontendParametersSatellite::FEC::fNone:
1637 parm_u_qpsk_fec_inner = FEC_NONE;
1639 case eDVBFrontendParametersSatellite::FEC::f1_2:
1640 parm_u_qpsk_fec_inner = FEC_1_2;
1642 case eDVBFrontendParametersSatellite::FEC::f2_3:
1643 parm_u_qpsk_fec_inner = FEC_2_3;
1645 case eDVBFrontendParametersSatellite::FEC::f3_4:
1646 parm_u_qpsk_fec_inner = FEC_3_4;
1648 case eDVBFrontendParametersSatellite::FEC::f5_6:
1649 parm_u_qpsk_fec_inner = FEC_5_6;
1651 case eDVBFrontendParametersSatellite::FEC::f7_8:
1652 parm_u_qpsk_fec_inner = FEC_7_8;
1655 eDebug("no valid fec for DVB-S set.. assume auto");
1656 case eDVBFrontendParametersSatellite::FEC::fAuto:
1657 parm_u_qpsk_fec_inner = FEC_AUTO;
1660 #if HAVE_DVB_API_VERSION >= 3
1665 case eDVBFrontendParametersSatellite::FEC::f1_2:
1666 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1668 case eDVBFrontendParametersSatellite::FEC::f2_3:
1669 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1671 case eDVBFrontendParametersSatellite::FEC::f3_4:
1672 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1674 case eDVBFrontendParametersSatellite::FEC::f3_5:
1675 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1677 case eDVBFrontendParametersSatellite::FEC::f4_5:
1678 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1680 case eDVBFrontendParametersSatellite::FEC::f5_6:
1681 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1683 case eDVBFrontendParametersSatellite::FEC::f7_8:
1684 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1686 case eDVBFrontendParametersSatellite::FEC::f8_9:
1687 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1689 case eDVBFrontendParametersSatellite::FEC::f9_10:
1690 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1693 eDebug("no valid fec for DVB-S2 set.. abort !!");
1696 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1697 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK) {
1698 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1699 // 8PSK fec driver values are decimal 9 bigger
1700 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1704 // FIXME !!! get frequency range from tuner
1705 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1707 eDebug("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1710 eDebug("tuning to %d mhz", parm_frequency/1000);
1715 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1717 #if HAVE_DVB_API_VERSION < 3
1718 parm_frequency = feparm.frequency;
1720 parm_frequency = feparm.frequency * 1000;
1722 parm_u_qam_symbol_rate = feparm.symbol_rate;
1723 switch (feparm.modulation)
1725 case eDVBFrontendParametersCable::Modulation::QAM16:
1726 parm_u_qam_modulation = QAM_16;
1728 case eDVBFrontendParametersCable::Modulation::QAM32:
1729 parm_u_qam_modulation = QAM_32;
1731 case eDVBFrontendParametersCable::Modulation::QAM64:
1732 parm_u_qam_modulation = QAM_64;
1734 case eDVBFrontendParametersCable::Modulation::QAM128:
1735 parm_u_qam_modulation = QAM_128;
1737 case eDVBFrontendParametersCable::Modulation::QAM256:
1738 parm_u_qam_modulation = QAM_256;
1741 case eDVBFrontendParametersCable::Modulation::Auto:
1742 parm_u_qam_modulation = QAM_AUTO;
1745 switch (feparm.inversion)
1747 case eDVBFrontendParametersCable::Inversion::On:
1748 parm_inversion = INVERSION_ON;
1750 case eDVBFrontendParametersCable::Inversion::Off:
1751 parm_inversion = INVERSION_OFF;
1754 case eDVBFrontendParametersCable::Inversion::Unknown:
1755 parm_inversion = INVERSION_AUTO;
1758 switch (feparm.fec_inner)
1760 case eDVBFrontendParametersCable::FEC::fNone:
1761 parm_u_qam_fec_inner = FEC_NONE;
1763 case eDVBFrontendParametersCable::FEC::f1_2:
1764 parm_u_qam_fec_inner = FEC_1_2;
1766 case eDVBFrontendParametersCable::FEC::f2_3:
1767 parm_u_qam_fec_inner = FEC_2_3;
1769 case eDVBFrontendParametersCable::FEC::f3_4:
1770 parm_u_qam_fec_inner = FEC_3_4;
1772 case eDVBFrontendParametersCable::FEC::f5_6:
1773 parm_u_qam_fec_inner = FEC_5_6;
1775 case eDVBFrontendParametersCable::FEC::f7_8:
1776 parm_u_qam_fec_inner = FEC_7_8;
1778 #if HAVE_DVB_API_VERSION >= 3
1779 case eDVBFrontendParametersCable::FEC::f8_9:
1780 parm_u_qam_fec_inner = FEC_8_9;
1784 case eDVBFrontendParametersCable::FEC::fAuto:
1785 parm_u_qam_fec_inner = FEC_AUTO;
1788 eDebug("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
1789 parm_frequency/1000,
1790 parm_u_qam_symbol_rate,
1791 parm_u_qam_fec_inner,
1792 parm_u_qam_modulation,
1797 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
1799 parm_frequency = feparm.frequency;
1801 switch (feparm.bandwidth)
1803 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
1804 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
1806 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
1807 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
1809 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
1810 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
1813 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
1814 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
1817 switch (feparm.code_rate_LP)
1819 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1820 parm_u_ofdm_code_rate_LP = FEC_1_2;
1822 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1823 parm_u_ofdm_code_rate_LP = FEC_2_3;
1825 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1826 parm_u_ofdm_code_rate_LP = FEC_3_4;
1828 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1829 parm_u_ofdm_code_rate_LP = FEC_5_6;
1831 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1832 parm_u_ofdm_code_rate_LP = FEC_7_8;
1835 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1836 parm_u_ofdm_code_rate_LP = FEC_AUTO;
1839 switch (feparm.code_rate_HP)
1841 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1842 parm_u_ofdm_code_rate_HP = FEC_1_2;
1844 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1845 parm_u_ofdm_code_rate_HP = FEC_2_3;
1847 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1848 parm_u_ofdm_code_rate_HP = FEC_3_4;
1850 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1851 parm_u_ofdm_code_rate_HP = FEC_5_6;
1853 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1854 parm_u_ofdm_code_rate_HP = FEC_7_8;
1857 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1858 parm_u_ofdm_code_rate_HP = FEC_AUTO;
1861 switch (feparm.modulation)
1863 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
1864 parm_u_ofdm_constellation = QPSK;
1866 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
1867 parm_u_ofdm_constellation = QAM_16;
1869 case eDVBFrontendParametersTerrestrial::Modulation::QAM64:
1870 parm_u_ofdm_constellation = QAM_64;
1873 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
1874 parm_u_ofdm_constellation = QAM_AUTO;
1877 switch (feparm.transmission_mode)
1879 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
1880 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
1882 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
1883 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
1886 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
1887 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
1890 switch (feparm.guard_interval)
1892 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32:
1893 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
1895 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16:
1896 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
1898 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8:
1899 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
1901 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4:
1902 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
1905 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto:
1906 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
1909 switch (feparm.hierarchy)
1911 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone:
1912 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
1914 case eDVBFrontendParametersTerrestrial::Hierarchy::H1:
1915 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
1917 case eDVBFrontendParametersTerrestrial::Hierarchy::H2:
1918 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
1920 case eDVBFrontendParametersTerrestrial::Hierarchy::H4:
1921 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
1924 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto:
1925 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
1928 switch (feparm.inversion)
1930 case eDVBFrontendParametersTerrestrial::Inversion::On:
1931 parm_inversion = INVERSION_ON;
1933 case eDVBFrontendParametersTerrestrial::Inversion::Off:
1934 parm_inversion = INVERSION_OFF;
1937 case eDVBFrontendParametersTerrestrial::Inversion::Unknown:
1938 parm_inversion = INVERSION_AUTO;
1944 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
1946 unsigned int timeout = 5000;
1947 eDebug("(%d)tune", m_dvbid);
1955 eDebug("no frontend device opened... do not try to tune !!!");
1967 m_sec_sequence.clear();
1969 where.calcLockTimeout(timeout);
1975 eDVBFrontendParametersSatellite feparm;
1976 if (where.getDVBS(feparm))
1978 eDebug("no dvbs data!");
1982 m_sec->setRotorMoving(false);
1983 res=prepare_sat(feparm, timeout);
1991 eDVBFrontendParametersCable feparm;
1992 if (where.getDVBC(feparm))
1997 res=prepare_cable(feparm);
2001 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2002 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2007 eDVBFrontendParametersTerrestrial feparm;
2008 if (where.getDVBT(feparm))
2010 eDebug("no -T data");
2014 res=prepare_terrestrial(feparm);
2018 std::string enable_5V;
2019 char configStr[255];
2020 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2021 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2022 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2023 if (enable_5V == "True")
2024 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2026 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2027 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2033 m_tuneTimer->start(0,true);
2034 m_sec_sequence.current() = m_sec_sequence.begin();
2036 if (m_state != stateTuning)
2039 m_state = stateTuning;
2040 m_stateChanged(this);
2046 m_tuneTimer->stop();
2050 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2052 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2056 RESULT eDVBFrontend::setVoltage(int voltage)
2058 if (m_type == feCable)
2060 #if HAVE_DVB_API_VERSION < 3
2063 bool increased=false;
2064 fe_sec_voltage_t vlt;
2066 m_data[CUR_VOLTAGE]=voltage;
2070 for (int i=0; i < 3; ++i) // reset diseqc
2072 vlt = SEC_VOLTAGE_OFF;
2075 #if HAVE_DVB_API_VERSION < 3
2076 vlt = SEC_VOLTAGE_13_5;
2082 vlt = SEC_VOLTAGE_13;
2085 #if HAVE_DVB_API_VERSION < 3
2086 vlt = SEC_VOLTAGE_18_5;
2092 vlt = SEC_VOLTAGE_18;
2097 #if HAVE_DVB_API_VERSION < 3
2098 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2100 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2101 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2102 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2106 RESULT eDVBFrontend::getState(int &state)
2112 RESULT eDVBFrontend::setTone(int t)
2114 if (m_type != feSatellite)
2116 #if HAVE_DVB_API_VERSION < 3
2119 fe_sec_tone_mode_t tone;
2128 tone = SEC_TONE_OFF;
2133 #if HAVE_DVB_API_VERSION < 3
2134 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2136 return ::ioctl(m_fd, FE_SET_TONE, tone);
2140 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2141 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2144 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2146 #if HAVE_DVB_API_VERSION < 3
2147 struct secCommand cmd;
2148 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2149 cmd.u.diseqc.cmdtype = diseqc.data[0];
2150 cmd.u.diseqc.addr = diseqc.data[1];
2151 cmd.u.diseqc.cmd = diseqc.data[2];
2152 cmd.u.diseqc.numParams = diseqc.len-3;
2153 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2154 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2156 struct dvb_diseqc_master_cmd cmd;
2157 memcpy(cmd.msg, diseqc.data, diseqc.len);
2158 cmd.msg_len = diseqc.len;
2159 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2165 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2166 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2168 RESULT eDVBFrontend::sendToneburst(int burst)
2170 #if HAVE_DVB_API_VERSION < 3
2171 secMiniCmd cmd = SEC_MINI_NONE;
2173 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2175 if ( burst == eDVBSatelliteDiseqcParameters::A )
2177 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2179 #if HAVE_DVB_API_VERSION < 3
2180 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2183 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2189 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2195 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2197 m_sec_sequence = list;
2201 RESULT eDVBFrontend::getData(int num, long &data)
2203 if ( num < NUM_DATA_ENTRIES )
2211 RESULT eDVBFrontend::setData(int num, long val)
2213 if ( num < NUM_DATA_ENTRIES )
2221 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2224 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2227 if (m_type == eDVBFrontend::feSatellite)
2230 eDVBFrontendParametersSatellite sat_parm;
2231 int ret = feparm->getDVBS(sat_parm);
2233 return m_sec->canTune(sat_parm, this, 1 << m_slotid);
2235 else if (m_type == eDVBFrontend::feCable)
2236 return 2; // more prio for cable frontends
2240 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2242 ePyObject Id, Descr, Enabled;
2243 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 3)
2245 Id = PyTuple_GET_ITEM(obj, 0);
2246 Descr = PyTuple_GET_ITEM(obj, 1);
2247 Enabled = PyTuple_GET_ITEM(obj, 2);
2248 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled))
2250 strcpy(m_description, PyString_AS_STRING(Descr));
2251 m_slotid = PyInt_AsLong(Id);
2252 m_enabled = Enabled == Py_True;
2253 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2254 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2255 !!strstr(m_description, "Alps BSBE2") ||
2256 !!strstr(m_description, "Alps -S");
2257 eDebug("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s",
2258 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No" );
2261 PyErr_SetString(PyExc_StandardError,
2262 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");