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 orbital_position = ((descriptor.getOrbitalPosition() >> 12) & 0xF) * 1000;
129 orbital_position += ((descriptor.getOrbitalPosition() >> 8) & 0xF) * 100;
130 orbital_position += ((descriptor.getOrbitalPosition() >> 4) & 0xF) * 10;
131 orbital_position += ((descriptor.getOrbitalPosition()) & 0xF);
132 if (orbital_position && (!descriptor.getWestEastFlag()))
133 orbital_position = 3600 - orbital_position;
134 system = descriptor.getModulationSystem();
135 modulation = descriptor.getModulation();
136 if (system == System::DVB_S && modulation == Modulation::M8PSK)
138 eDebug("satellite_delivery_descriptor non valid modulation type.. force QPSK");
141 roll_off = descriptor.getRollOff();
142 if (system == System::DVB_S2)
144 eDebug("SAT DVB-S2 freq %d, %s, pos %d, sr %d, fec %d, modulation %d, roll_off %d",
146 polarisation ? "hor" : "vert",
154 eDebug("SAT DVB-S freq %d, %s, pos %d, sr %d, fec %d",
156 polarisation ? "hor" : "vert",
162 void eDVBFrontendParametersCable::set(const CableDeliverySystemDescriptor &descriptor)
164 frequency = descriptor.getFrequency() / 10;
165 symbol_rate = descriptor.getSymbolRate() * 100;
166 fec_inner = descriptor.getFecInner();
167 if ( fec_inner == 0xF )
168 fec_inner = FEC::fNone;
169 modulation = descriptor.getModulation();
170 if ( modulation > 0x5 )
171 modulation = Modulation::Auto;
172 inversion = Inversion::Unknown;
173 eDebug("Cable freq %d, mod %d, sr %d, fec %d",
175 modulation, symbol_rate, fec_inner);
178 void eDVBFrontendParametersTerrestrial::set(const TerrestrialDeliverySystemDescriptor &descriptor)
180 frequency = descriptor.getCentreFrequency() * 10;
181 bandwidth = descriptor.getBandwidth();
182 if ( bandwidth > 2 ) // 5Mhz forced to auto
183 bandwidth = Bandwidth::BwAuto;
184 code_rate_HP = descriptor.getCodeRateHpStream();
185 if (code_rate_HP > 4)
186 code_rate_HP = FEC::fAuto;
187 code_rate_LP = descriptor.getCodeRateLpStream();
188 if (code_rate_LP > 4)
189 code_rate_LP = FEC::fAuto;
190 transmission_mode = descriptor.getTransmissionMode();
191 if (transmission_mode > 1) // TM4k forced to auto
192 transmission_mode = TransmissionMode::TMAuto;
193 guard_interval = descriptor.getGuardInterval();
194 if (guard_interval > 3)
195 guard_interval = GuardInterval::GI_Auto;
196 hierarchy = descriptor.getHierarchyInformation()&3;
197 modulation = descriptor.getConstellation();
199 modulation = Modulation::Auto;
200 inversion = Inversion::Unknown;
201 eDebug("Terr freq %d, bw %d, cr_hp %d, cr_lp %d, tm_mode %d, guard %d, hierarchy %d, const %d",
202 frequency, bandwidth, code_rate_HP, code_rate_LP, transmission_mode,
203 guard_interval, hierarchy, modulation);
206 eDVBFrontendParameters::eDVBFrontendParameters(): m_type(-1)
210 DEFINE_REF(eDVBFrontendParameters);
212 RESULT eDVBFrontendParameters::getSystem(int &t) const
220 RESULT eDVBFrontendParameters::getDVBS(eDVBFrontendParametersSatellite &p) const
222 if (m_type != iDVBFrontend::feSatellite)
228 RESULT eDVBFrontendParameters::getDVBC(eDVBFrontendParametersCable &p) const
230 if (m_type != iDVBFrontend::feCable)
236 RESULT eDVBFrontendParameters::getDVBT(eDVBFrontendParametersTerrestrial &p) const
238 if (m_type != iDVBFrontend::feTerrestrial)
244 RESULT eDVBFrontendParameters::setDVBS(const eDVBFrontendParametersSatellite &p, bool no_rotor_command_on_tune)
247 sat.no_rotor_command_on_tune = no_rotor_command_on_tune;
248 m_type = iDVBFrontend::feSatellite;
252 RESULT eDVBFrontendParameters::setDVBC(const eDVBFrontendParametersCable &p)
255 m_type = iDVBFrontend::feCable;
259 RESULT eDVBFrontendParameters::setDVBT(const eDVBFrontendParametersTerrestrial &p)
262 m_type = iDVBFrontend::feTerrestrial;
266 RESULT eDVBFrontendParameters::calculateDifference(const iDVBFrontendParameters *parm, int &diff, bool exact) const
271 if (parm->getSystem(type))
275 diff = 1<<30; // big difference
281 case iDVBFrontend::feSatellite:
283 eDVBFrontendParametersSatellite osat;
284 if (parm->getDVBS(osat))
287 if (sat.orbital_position != osat.orbital_position)
289 else if (sat.polarisation != osat.polarisation)
291 else if (exact && sat.fec != osat.fec && sat.fec != eDVBFrontendParametersSatellite::FEC::fAuto && osat.fec != eDVBFrontendParametersSatellite::FEC::fAuto)
293 else if (exact && sat.modulation != osat.modulation && sat.modulation != eDVBFrontendParametersSatellite::Modulation::Auto && osat.modulation != eDVBFrontendParametersSatellite::Modulation::Auto)
297 diff = abs(sat.frequency - osat.frequency);
298 diff += abs(sat.symbol_rate - osat.symbol_rate);
302 case iDVBFrontend::feCable:
303 eDVBFrontendParametersCable ocable;
304 if (parm->getDVBC(ocable))
307 if (exact && cable.modulation != ocable.modulation
308 && cable.modulation != eDVBFrontendParametersCable::Modulation::Auto
309 && ocable.modulation != eDVBFrontendParametersCable::Modulation::Auto)
311 else if (exact && cable.fec_inner != ocable.fec_inner && cable.fec_inner != eDVBFrontendParametersCable::FEC::fAuto && ocable.fec_inner != eDVBFrontendParametersCable::FEC::fAuto)
315 diff = abs(cable.frequency - ocable.frequency);
316 diff += abs(cable.symbol_rate - ocable.symbol_rate);
319 case iDVBFrontend::feTerrestrial:
320 eDVBFrontendParametersTerrestrial oterrestrial;
321 if (parm->getDVBT(oterrestrial))
325 if (exact && oterrestrial.bandwidth != terrestrial.bandwidth &&
326 oterrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto &&
327 terrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto)
329 else if (exact && oterrestrial.modulation != terrestrial.modulation &&
330 oterrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation::Auto &&
331 terrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation::Auto)
333 else if (exact && oterrestrial.transmission_mode != terrestrial.transmission_mode &&
334 oterrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto &&
335 terrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto)
337 else if (exact && oterrestrial.guard_interval != terrestrial.guard_interval &&
338 oterrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto &&
339 terrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto)
341 else if (exact && oterrestrial.hierarchy != terrestrial.hierarchy &&
342 oterrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy::HAuto &&
343 terrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy::HAuto)
345 else if (exact && oterrestrial.code_rate_LP != terrestrial.code_rate_LP &&
346 oterrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC::fAuto &&
347 terrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC::fAuto)
349 else if (exact && oterrestrial.code_rate_HP != terrestrial.code_rate_HP &&
350 oterrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC::fAuto &&
351 terrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC::fAuto)
354 diff = abs(terrestrial.frequency - oterrestrial.frequency);
362 RESULT eDVBFrontendParameters::getHash(unsigned long &hash) const
366 case iDVBFrontend::feSatellite:
368 hash = (sat.orbital_position << 16);
369 hash |= ((sat.frequency/1000)&0xFFFF)|((sat.polarisation&1) << 15);
372 case iDVBFrontend::feCable:
374 hash |= (cable.frequency/1000)&0xFFFF;
376 case iDVBFrontend::feTerrestrial:
378 hash |= (terrestrial.frequency/1000)&0xFFFF;
385 RESULT eDVBFrontendParameters::calcLockTimeout(unsigned int &timeout) const
389 case iDVBFrontend::feSatellite:
391 /* high symbol rate transponders tune faster, due to
392 requiring less zigzag and giving more symbols faster.
394 5s are definitely not enough on really low SR when
395 zigzag has to find the exact frequency first.
397 if (sat.symbol_rate > 20000000)
399 else if (sat.symbol_rate > 10000000)
405 case iDVBFrontend::feCable:
408 case iDVBFrontend::feTerrestrial:
416 DEFINE_REF(eDVBFrontend);
418 int eDVBFrontend::PriorityOrder=0;
420 eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok)
421 :m_enabled(false), m_type(-1), m_dvbid(fe), m_slotid(fe)
422 ,m_fd(-1), m_need_rotor_workaround(false), m_sn(0), m_timeout(0), m_tuneTimer(0)
423 #if HAVE_DVB_API_VERSION < 3
427 #if HAVE_DVB_API_VERSION < 3
428 sprintf(m_filename, "/dev/dvb/card%d/frontend%d", adap, fe);
429 sprintf(m_sec_filename, "/dev/dvb/card%d/sec%d", adap, fe);
431 sprintf(m_filename, "/dev/dvb/adapter%d/frontend%d", adap, fe);
433 m_timeout = new eTimer(eApp);
434 CONNECT(m_timeout->timeout, eDVBFrontend::timeout);
436 m_tuneTimer = new eTimer(eApp);
437 CONNECT(m_tuneTimer->timeout, eDVBFrontend::tuneLoop);
439 for (int i=0; i<eDVBFrontend::NUM_DATA_ENTRIES; ++i)
442 m_idleInputpower[0]=m_idleInputpower[1]=0;
444 ok = !openFrontend();
448 int eDVBFrontend::openFrontend()
451 return -1; // already opened
456 #if HAVE_DVB_API_VERSION < 3
457 FrontendInfo fe_info;
459 dvb_frontend_info fe_info;
461 eDebug("opening frontend %d", m_dvbid);
464 m_fd = ::open(m_filename, O_RDWR|O_NONBLOCK);
467 eWarning("failed! (%s) %m", m_filename);
472 eWarning("frontend %d already opened", m_dvbid);
475 if (::ioctl(m_fd, FE_GET_INFO, &fe_info) < 0)
477 eWarning("ioctl FE_GET_INFO failed");
483 switch (fe_info.type)
486 m_type = iDVBFrontend::feSatellite;
489 m_type = iDVBFrontend::feCable;
492 m_type = iDVBFrontend::feTerrestrial;
495 eWarning("unknown frontend type.");
500 eDebug("detected %s frontend", "satellite\0cable\0 terrestrial"+fe_info.type*10);
503 #if HAVE_DVB_API_VERSION < 3
504 if (m_type == iDVBFrontend::feSatellite)
508 m_secfd = ::open(m_sec_filename, O_RDWR);
511 eWarning("failed! (%s) %m", m_sec_filename);
518 eWarning("sec %d already opened", m_dvbid);
522 setTone(iDVBFrontend::toneOff);
523 setVoltage(iDVBFrontend::voltageOff);
525 m_sn = new eSocketNotifier(eApp, m_fd, eSocketNotifier::Read);
526 CONNECT(m_sn->activated, eDVBFrontend::feEvent);
531 int eDVBFrontend::closeFrontend()
533 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)m_data[LINKED_NEXT_PTR];
534 while (linked_fe != (eDVBRegisteredFrontend*)-1)
536 if (linked_fe->m_inuse)
538 eDebug("dont close frontend %d until the linked frontend %d in slot %d is still in use",
539 m_dvbid, linked_fe->m_frontend->getDVBID(), linked_fe->m_frontend->getSlotID());
542 linked_fe->m_frontend->getData(LINKED_NEXT_PTR, (long&)linked_fe);
546 eDebug("close frontend %d", m_dvbid);
548 setTone(iDVBFrontend::toneOff);
549 setVoltage(iDVBFrontend::voltageOff);
551 m_sec->setRotorMoving(false);
555 eWarning("couldnt close frontend %d", m_dvbid);
556 m_data[CSW] = m_data[UCSW] = m_data[TONEBURST] = -1;
558 #if HAVE_DVB_API_VERSION < 3
561 if (!::close(m_secfd))
564 eWarning("couldnt close sec %d", m_dvbid);
573 eDVBFrontend::~eDVBFrontend()
580 void eDVBFrontend::feEvent(int w)
584 #if HAVE_DVB_API_VERSION < 3
587 dvb_frontend_event event;
591 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
593 if (res && (errno == EAGAIN))
598 eWarning("FE_GET_EVENT failed! %m");
605 #if HAVE_DVB_API_VERSION < 3
606 if (event.type == FE_COMPLETION_EV)
608 eDebug("(%d)fe event: status %x, inversion %s", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off");
609 if (event.status & FE_HAS_LOCK)
619 eDebug("stateLostLock");
620 state = stateLostLock;
621 m_data[CSW] = m_data[UCSW] = m_data[TONEBURST] = -1; // reset diseqc
624 if (m_state != state)
627 m_stateChanged(this);
632 void eDVBFrontend::timeout()
635 if (m_state == stateTuning)
637 m_state = stateFailed;
638 m_stateChanged(this);
642 int eDVBFrontend::readFrontendData(int type)
649 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
650 eDebug("FE_READ_BER failed (%m)");
656 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
657 eDebug("FE_READ_SNR failed (%m)");
660 case signalQualitydB: /* this will move into the driver */
663 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
664 eDebug("FE_READ_SNR failed (%m)");
665 if (!strcmp(m_description, "BCM4501 (internal)"))
667 unsigned int SDS_SNRE = snr << 16;
669 static float SNR_COEFF[6] = {
672 197418.0 / 4194304.0,
673 -2602183.0 / 4194304.0,
674 20377212.0 / 4194304.0,
675 -37791203.0 / 4194304.0,
678 float fval1, fval2, snr_in_db;
680 fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0));
681 fval2 = pow(10.0, fval1)-1;
682 fval1 = 10.0 * log10(fval2);
686 fval2 = SNR_COEFF[0];
690 fval2 += SNR_COEFF[i];
696 return (int)(snr_in_db * 100.0);
698 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
699 !strcmp(m_description, "Alps -S") ||
700 !strcmp(m_description, "Philips -S") ||
701 !strcmp(m_description, "LG -S") )
703 float snr_in_db=(snr-39075)/1764.7;
704 return (int)(snr_in_db * 100.0);
705 } else if (!strcmp(m_description, "Alps BSBE2"))
707 return (int)((snr >> 7) * 10.0);
709 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
715 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
716 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
721 #if HAVE_DVB_API_VERSION < 3
722 FrontendStatus status=0;
726 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
727 eDebug("FE_READ_STATUS failed (%m)");
728 return !!(status&FE_HAS_LOCK);
732 #if HAVE_DVB_API_VERSION < 3
733 FrontendStatus status=0;
737 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
738 eDebug("FE_READ_STATUS failed (%m)");
739 return !!(status&FE_HAS_SYNC);
747 void PutToDict(ePyObject &dict, const char*key, long value)
749 ePyObject item = PyInt_FromLong(value);
752 if (PyDict_SetItemString(dict, key, item))
753 eDebug("put %s to dict failed", key);
757 eDebug("could not create PyObject for %s", key);
760 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
764 if (PyDict_SetItemString(dict, key, item))
765 eDebug("put %s to dict failed", key);
769 eDebug("invalid PyObject for %s", key);
772 void PutToDict(ePyObject &dict, const char*key, const char *value)
774 ePyObject item = PyString_FromString(value);
777 if (PyDict_SetItemString(dict, key, item))
778 eDebug("put %s to dict failed", key);
782 eDebug("could not create PyObject for %s", key);
785 void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, eDVBFrontend *fe)
790 fe->getData(eDVBFrontend::CSW, csw);
791 fe->getData(eDVBFrontend::FREQ_OFFSET, freq_offset);
792 int frequency = parm_frequency + freq_offset;
793 PutToDict(dict, "frequency", frequency);
794 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
795 switch(parm_u_qpsk_fec_inner)
818 #if HAVE_DVB_API_VERSION >=3
819 case FEC_S2_8PSK_1_2:
820 case FEC_S2_QPSK_1_2:
823 case FEC_S2_8PSK_2_3:
824 case FEC_S2_QPSK_2_3:
827 case FEC_S2_8PSK_3_4:
828 case FEC_S2_QPSK_3_4:
831 case FEC_S2_8PSK_5_6:
832 case FEC_S2_QPSK_5_6:
835 case FEC_S2_8PSK_7_8:
836 case FEC_S2_QPSK_7_8:
839 case FEC_S2_8PSK_8_9:
840 case FEC_S2_QPSK_8_9:
843 case FEC_S2_8PSK_3_5:
844 case FEC_S2_QPSK_3_5:
847 case FEC_S2_8PSK_4_5:
848 case FEC_S2_QPSK_4_5:
851 case FEC_S2_8PSK_9_10:
852 case FEC_S2_QPSK_9_10:
857 #if HAVE_DVB_API_VERSION >=3
858 PutToDict(dict, "modulation",
859 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ? "8PSK": "QPSK" );
861 PutToDict(dict, "modulation", "QPSK" );
863 PutToDict(dict, "fec_inner", tmp);
864 tmp = parm_u_qpsk_fec_inner > FEC_AUTO ?
866 PutToDict(dict, "system", tmp);
869 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
872 PutToDict(dict, "frequency", parm_frequency/1000);
873 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
874 switch(parm_u_qam_fec_inner)
894 #if HAVE_DVB_API_VERSION >= 3
904 PutToDict(dict, "fec_inner", tmp);
905 switch(parm_u_qam_modulation)
927 PutToDict(dict, "modulation", tmp);
930 void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
933 PutToDict(dict, "frequency", parm_frequency);
934 switch (parm_u_ofdm_bandwidth)
936 case BANDWIDTH_8_MHZ:
937 tmp = "BANDWIDTH_8_MHZ";
939 case BANDWIDTH_7_MHZ:
940 tmp = "BANDWIDTH_7_MHZ";
942 case BANDWIDTH_6_MHZ:
943 tmp = "BANDWIDTH_6_MHZ";
947 tmp = "BANDWIDTH_AUTO";
950 PutToDict(dict, "bandwidth", tmp);
951 switch (parm_u_ofdm_code_rate_LP)
973 PutToDict(dict, "code_rate_lp", tmp);
974 switch (parm_u_ofdm_code_rate_HP)
996 PutToDict(dict, "code_rate_hp", tmp);
997 switch (parm_u_ofdm_constellation)
1013 PutToDict(dict, "constellation", tmp);
1014 switch (parm_u_ofdm_transmission_mode)
1016 case TRANSMISSION_MODE_2K:
1017 tmp = "TRANSMISSION_MODE_2K";
1019 case TRANSMISSION_MODE_8K:
1020 tmp = "TRANSMISSION_MODE_8K";
1023 case TRANSMISSION_MODE_AUTO:
1024 tmp = "TRANSMISSION_MODE_AUTO";
1027 PutToDict(dict, "transmission_mode", tmp);
1028 switch (parm_u_ofdm_guard_interval)
1030 case GUARD_INTERVAL_1_32:
1031 tmp = "GUARD_INTERVAL_1_32";
1033 case GUARD_INTERVAL_1_16:
1034 tmp = "GUARD_INTERVAL_1_16";
1036 case GUARD_INTERVAL_1_8:
1037 tmp = "GUARD_INTERVAL_1_8";
1039 case GUARD_INTERVAL_1_4:
1040 tmp = "GUARD_INTERVAL_1_4";
1043 case GUARD_INTERVAL_AUTO:
1044 tmp = "GUARD_INTERVAL_AUTO";
1047 PutToDict(dict, "guard_interval", tmp);
1048 switch (parm_u_ofdm_hierarchy_information)
1050 case HIERARCHY_NONE:
1051 tmp = "HIERARCHY_NONE";
1054 tmp = "HIERARCHY_1";
1057 tmp = "HIERARCHY_2";
1060 tmp = "HIERARCHY_4";
1063 case HIERARCHY_AUTO:
1064 tmp = "HIERARCHY_AUTO";
1067 PutToDict(dict, "hierarchy_information", tmp);
1070 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1072 if (dest && PyDict_Check(dest))
1074 const char *tmp = "UNKNOWN";
1095 PutToDict(dest, "tuner_state", tmp);
1096 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1097 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1098 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1099 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1100 int sigQualitydB = readFrontendData(signalQualitydB);
1101 if (sigQualitydB == 0x12345678) // not support yet
1103 ePyObject obj=Py_None;
1105 PutToDict(dest, "tuner_signal_quality_db", obj);
1108 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1109 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1113 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1115 if (m_fd != -1 && dest && PyDict_Check(dest))
1123 FRONTENDPARAMETERS front;
1124 if (!original && ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1125 eDebug("FE_GET_FRONTEND (%m)");
1128 const FRONTENDPARAMETERS &parm = original ? this->parm : front;
1129 const char *tmp = "INVERSION_AUTO";
1130 switch(parm_inversion)
1133 tmp = "INVERSION_ON";
1136 tmp = "INVERSION_OFF";
1142 PutToDict(dest, "inversion", tmp);
1147 fillDictWithSatelliteData(dest, original?parm:front, this);
1150 fillDictWithCableData(dest, original?parm:front);
1153 fillDictWithTerrestrialData(dest, original?parm:front);
1164 void eDVBFrontend::getFrontendData(ePyObject dest)
1166 if (dest && PyDict_Check(dest))
1169 PutToDict(dest, "tuner_number", m_dvbid);
1185 PutToDict(dest, "tuner_type", tmp);
1189 #ifndef FP_IOCTL_GET_ID
1190 #define FP_IOCTL_GET_ID 0
1192 int eDVBFrontend::readInputpower()
1194 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1196 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1197 FILE *f=fopen(proc_name, "r");
1200 if (fscanf(f, "%08x", &power) != 1)
1201 eDebug("read %s failed!! (%m)", proc_name);
1203 eDebug("%s is %d\n", proc_name, power);
1208 // open front prozessor
1209 int fp=::open("/dev/dbox/fp0", O_RDWR);
1212 eDebug("couldn't open fp");
1215 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1216 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1218 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1227 bool eDVBFrontend::setSecSequencePos(int steps)
1229 eDebug("set sequence pos %d", steps);
1234 if (m_sec_sequence.current() != m_sec_sequence.end())
1235 ++m_sec_sequence.current();
1240 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1241 --m_sec_sequence.current();
1247 void eDVBFrontend::setRotorData(int pos, int cmd)
1249 m_data[ROTOR_CMD] = cmd;
1250 m_data[ROTOR_POS] = pos;
1251 if ( m_data[SATPOS_DEPENDS_PTR] != -1 )
1253 eDVBRegisteredFrontend *satpos_depends_to_fe = (eDVBRegisteredFrontend*) m_data[SATPOS_DEPENDS_PTR];
1254 satpos_depends_to_fe->m_frontend->m_data[ROTOR_CMD] = cmd;
1255 satpos_depends_to_fe->m_frontend->m_data[ROTOR_POS] = pos;
1259 eDVBRegisteredFrontend *next = (eDVBRegisteredFrontend *)m_data[LINKED_NEXT_PTR];
1260 while ( (long)next != -1 )
1262 next->m_frontend->m_data[ROTOR_CMD] = cmd;
1263 next->m_frontend->m_data[ROTOR_POS] = pos;
1264 next = (eDVBRegisteredFrontend *)next->m_frontend->m_data[LINKED_NEXT_PTR];
1266 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)m_data[LINKED_PREV_PTR];
1267 while ( (long)prev != -1 )
1269 prev->m_frontend->m_data[ROTOR_CMD] = cmd;
1270 prev->m_frontend->m_data[ROTOR_POS] = pos;
1271 prev = (eDVBRegisteredFrontend *)prev->m_frontend->m_data[LINKED_PREV_PTR];
1276 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1279 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1281 // eDebug("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1282 switch (m_sec_sequence.current()->cmd)
1284 case eSecCommand::SLEEP:
1285 delay = m_sec_sequence.current()++->msec;
1286 eDebug("[SEC] sleep %dms", delay);
1288 case eSecCommand::GOTO:
1289 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1290 ++m_sec_sequence.current();
1292 case eSecCommand::SET_VOLTAGE:
1294 int voltage = m_sec_sequence.current()++->voltage;
1295 eDebug("[SEC] setVoltage %d", voltage);
1296 setVoltage(voltage);
1299 case eSecCommand::IF_VOLTAGE_GOTO:
1301 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1302 if ( compare.voltage == m_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1304 ++m_sec_sequence.current();
1307 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1309 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1310 if ( compare.voltage != m_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1312 ++m_sec_sequence.current();
1315 case eSecCommand::IF_TONE_GOTO:
1317 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1318 if ( compare.tone == m_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1320 ++m_sec_sequence.current();
1323 case eSecCommand::IF_NOT_TONE_GOTO:
1325 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1326 if ( compare.tone != m_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1328 ++m_sec_sequence.current();
1331 case eSecCommand::SET_TONE:
1332 eDebug("[SEC] setTone %d", m_sec_sequence.current()->tone);
1333 setTone(m_sec_sequence.current()++->tone);
1335 case eSecCommand::SEND_DISEQC:
1336 sendDiseqc(m_sec_sequence.current()->diseqc);
1337 eDebugNoNewLine("[SEC] sendDiseqc: ");
1338 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1339 eDebugNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1341 ++m_sec_sequence.current();
1343 case eSecCommand::SEND_TONEBURST:
1344 eDebug("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1345 sendToneburst(m_sec_sequence.current()++->toneburst);
1347 case eSecCommand::SET_FRONTEND:
1348 eDebug("[SEC] setFrontend");
1350 ++m_sec_sequence.current();
1352 case eSecCommand::START_TUNE_TIMEOUT:
1354 m_timeout->start(m_sec_sequence.current()->timeout, 1);
1355 ++m_sec_sequence.current();
1358 case eSecCommand::SET_TIMEOUT:
1359 m_timeoutCount = m_sec_sequence.current()++->val;
1360 eDebug("[SEC] set timeout %d", m_timeoutCount);
1362 case eSecCommand::IF_TIMEOUT_GOTO:
1363 if (!m_timeoutCount)
1365 eDebug("[SEC] rotor timout");
1366 m_sec->setRotorMoving(false);
1367 setSecSequencePos(m_sec_sequence.current()->steps);
1370 ++m_sec_sequence.current();
1372 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1374 int idx = m_sec_sequence.current()++->val;
1375 if ( idx == 0 || idx == 1 )
1377 m_idleInputpower[idx] = readInputpower();
1378 eDebug("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1381 eDebug("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1384 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1386 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1387 int idx = compare.val;
1388 if ( idx == 0 || idx == 1 )
1390 int idle = readInputpower();
1391 int diff = abs(idle-m_idleInputpower[idx]);
1394 eDebug("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1395 setSecSequencePos(compare.steps);
1399 ++m_sec_sequence.current();
1402 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1404 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1405 if (readFrontendData(locked))
1407 eDebug("[SEC] locked step %d ok", cmd.okcount);
1409 if (cmd.okcount > 12)
1411 eDebug("ok > 12 .. goto %d\n",m_sec_sequence.current()->steps);
1412 setSecSequencePos(cmd.steps);
1418 eDebug("[SEC] rotor locked step %d failed", cmd.okcount);
1420 if (!m_timeoutCount && m_retryCount > 0)
1424 ++m_sec_sequence.current();
1427 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1428 m_runningInputpower = readInputpower();
1429 eDebug("[SEC] runningInputpower is %d", m_runningInputpower);
1430 ++m_sec_sequence.current();
1432 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1434 int idleInputpower = m_idleInputpower[ (m_data[CUR_VOLTAGE]&1) ? 0 : 1];
1435 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1436 const char *txt = cmd.direction ? "running" : "stopped";
1437 eDebug("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1439 m_runningInputpower,
1442 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1443 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1446 eDebug("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1447 if ( cmd.okcount > 6 )
1449 m_sec->setRotorMoving(cmd.direction);
1450 eDebug("[SEC] rotor is %s", txt);
1451 if (setSecSequencePos(cmd.steps))
1457 eDebug("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1459 if (!m_timeoutCount && m_retryCount > 0)
1463 ++m_sec_sequence.current();
1466 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1467 if (m_data[ROTOR_CMD] != -1 && m_data[ROTOR_POS] != -1)
1468 setSecSequencePos(m_sec_sequence.current()->steps);
1470 ++m_sec_sequence.current();
1472 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1473 eDebug("[SEC] invalidate current rotorparams");
1474 setRotorData(-1,-1);
1475 ++m_sec_sequence.current();
1477 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1478 setRotorData(m_data[NEW_ROTOR_POS], m_data[NEW_ROTOR_CMD]);
1479 eDebug("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, m_data[ROTOR_CMD], m_data[ROTOR_POS]);
1480 ++m_sec_sequence.current();
1482 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1483 m_retryCount = m_sec_sequence.current()++->val;
1484 eDebug("[SEC] set rotor retries %d", m_retryCount);
1486 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1489 eDebug("[SEC] no more rotor retrys");
1490 setSecSequencePos(m_sec_sequence.current()->steps);
1493 ++m_sec_sequence.current();
1495 case eSecCommand::SET_POWER_LIMITING_MODE:
1497 if (m_need_rotor_workaround)
1501 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1503 sprintf(dev, "/dev/i2c/%d", m_slotid);
1504 else if (m_slotid == 2)
1505 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1506 else if (m_slotid == 3)
1507 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1508 int fd = ::open(dev, O_RDWR);
1510 unsigned char data[2];
1511 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1512 if(::read(fd, data, 1) != 1)
1513 eDebug("[SEC] error read lnbp (%m)");
1514 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1516 data[0] |= 0x80; // enable static current limiting
1517 eDebug("[SEC] set static current limiting");
1521 data[0] &= ~0x80; // enable dynamic current limiting
1522 eDebug("[SEC] set dynamic current limiting");
1524 if(::write(fd, data, 1) != 1)
1525 eDebug("[SEC] error write lnbp (%m)");
1528 ++m_sec_sequence.current();
1532 eDebug("[SEC] unhandled sec command %d",
1533 ++m_sec_sequence.current()->cmd);
1534 ++m_sec_sequence.current();
1536 m_tuneTimer->start(delay,true);
1540 void eDVBFrontend::setFrontend()
1542 eDebug("setting frontend %d", m_dvbid);
1545 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1547 perror("FE_SET_FRONTEND failed");
1552 RESULT eDVBFrontend::getFrontendType(int &t)
1560 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1565 eWarning("no SEC module active!");
1568 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1571 eDebug("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1574 feparm.polarisation,
1578 feparm.orbital_position);
1579 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1580 switch (feparm.inversion)
1582 case eDVBFrontendParametersSatellite::Inversion::On:
1583 parm_inversion = INVERSION_ON;
1585 case eDVBFrontendParametersSatellite::Inversion::Off:
1586 parm_inversion = INVERSION_OFF;
1589 case eDVBFrontendParametersSatellite::Inversion::Unknown:
1590 parm_inversion = INVERSION_AUTO;
1593 if (feparm.system == eDVBFrontendParametersSatellite::System::DVB_S)
1596 case eDVBFrontendParametersSatellite::FEC::fNone:
1597 parm_u_qpsk_fec_inner = FEC_NONE;
1599 case eDVBFrontendParametersSatellite::FEC::f1_2:
1600 parm_u_qpsk_fec_inner = FEC_1_2;
1602 case eDVBFrontendParametersSatellite::FEC::f2_3:
1603 parm_u_qpsk_fec_inner = FEC_2_3;
1605 case eDVBFrontendParametersSatellite::FEC::f3_4:
1606 parm_u_qpsk_fec_inner = FEC_3_4;
1608 case eDVBFrontendParametersSatellite::FEC::f5_6:
1609 parm_u_qpsk_fec_inner = FEC_5_6;
1611 case eDVBFrontendParametersSatellite::FEC::f7_8:
1612 parm_u_qpsk_fec_inner = FEC_7_8;
1615 eDebug("no valid fec for DVB-S set.. assume auto");
1616 case eDVBFrontendParametersSatellite::FEC::fAuto:
1617 parm_u_qpsk_fec_inner = FEC_AUTO;
1620 #if HAVE_DVB_API_VERSION >= 3
1625 case eDVBFrontendParametersSatellite::FEC::f1_2:
1626 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1628 case eDVBFrontendParametersSatellite::FEC::f2_3:
1629 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1631 case eDVBFrontendParametersSatellite::FEC::f3_4:
1632 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1634 case eDVBFrontendParametersSatellite::FEC::f3_5:
1635 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1637 case eDVBFrontendParametersSatellite::FEC::f4_5:
1638 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1640 case eDVBFrontendParametersSatellite::FEC::f5_6:
1641 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1643 case eDVBFrontendParametersSatellite::FEC::f7_8:
1644 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1646 case eDVBFrontendParametersSatellite::FEC::f8_9:
1647 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1649 case eDVBFrontendParametersSatellite::FEC::f9_10:
1650 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1653 eDebug("no valid fec for DVB-S2 set.. abort !!");
1656 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK)
1657 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1658 // 8PSK fec driver values are decimal 9 bigger
1661 // FIXME !!! get frequency range from tuner
1662 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1664 eDebug("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1667 eDebug("tuning to %d mhz", parm_frequency/1000);
1672 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1674 parm_frequency = feparm.frequency * 1000;
1675 parm_u_qam_symbol_rate = feparm.symbol_rate;
1676 switch (feparm.modulation)
1678 case eDVBFrontendParametersCable::Modulation::QAM16:
1679 parm_u_qam_modulation = QAM_16;
1681 case eDVBFrontendParametersCable::Modulation::QAM32:
1682 parm_u_qam_modulation = QAM_32;
1684 case eDVBFrontendParametersCable::Modulation::QAM64:
1685 parm_u_qam_modulation = QAM_64;
1687 case eDVBFrontendParametersCable::Modulation::QAM128:
1688 parm_u_qam_modulation = QAM_128;
1690 case eDVBFrontendParametersCable::Modulation::QAM256:
1691 parm_u_qam_modulation = QAM_256;
1694 case eDVBFrontendParametersCable::Modulation::Auto:
1695 parm_u_qam_modulation = QAM_AUTO;
1698 switch (feparm.inversion)
1700 case eDVBFrontendParametersCable::Inversion::On:
1701 parm_inversion = INVERSION_ON;
1703 case eDVBFrontendParametersCable::Inversion::Off:
1704 parm_inversion = INVERSION_OFF;
1707 case eDVBFrontendParametersCable::Inversion::Unknown:
1708 parm_inversion = INVERSION_AUTO;
1711 switch (feparm.fec_inner)
1713 case eDVBFrontendParametersCable::FEC::fNone:
1714 parm_u_qam_fec_inner = FEC_NONE;
1716 case eDVBFrontendParametersCable::FEC::f1_2:
1717 parm_u_qam_fec_inner = FEC_1_2;
1719 case eDVBFrontendParametersCable::FEC::f2_3:
1720 parm_u_qam_fec_inner = FEC_2_3;
1722 case eDVBFrontendParametersCable::FEC::f3_4:
1723 parm_u_qam_fec_inner = FEC_3_4;
1725 case eDVBFrontendParametersCable::FEC::f5_6:
1726 parm_u_qam_fec_inner = FEC_5_6;
1728 case eDVBFrontendParametersCable::FEC::f7_8:
1729 parm_u_qam_fec_inner = FEC_7_8;
1731 #if HAVE_DVB_API_VERSION >= 3
1732 case eDVBFrontendParametersCable::FEC::f8_9:
1733 parm_u_qam_fec_inner = FEC_8_9;
1737 case eDVBFrontendParametersCable::FEC::fAuto:
1738 parm_u_qam_fec_inner = FEC_AUTO;
1741 eDebug("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
1742 parm_frequency/1000,
1743 parm_u_qam_symbol_rate,
1744 parm_u_qam_fec_inner,
1745 parm_u_qam_modulation,
1750 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
1752 parm_frequency = feparm.frequency;
1754 switch (feparm.bandwidth)
1756 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
1757 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
1759 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
1760 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
1762 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
1763 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
1766 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
1767 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
1770 switch (feparm.code_rate_LP)
1772 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1773 parm_u_ofdm_code_rate_LP = FEC_1_2;
1775 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1776 parm_u_ofdm_code_rate_LP = FEC_2_3;
1778 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1779 parm_u_ofdm_code_rate_LP = FEC_3_4;
1781 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1782 parm_u_ofdm_code_rate_LP = FEC_5_6;
1784 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1785 parm_u_ofdm_code_rate_LP = FEC_7_8;
1788 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1789 parm_u_ofdm_code_rate_LP = FEC_AUTO;
1792 switch (feparm.code_rate_HP)
1794 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1795 parm_u_ofdm_code_rate_HP = FEC_1_2;
1797 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1798 parm_u_ofdm_code_rate_HP = FEC_2_3;
1800 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1801 parm_u_ofdm_code_rate_HP = FEC_3_4;
1803 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1804 parm_u_ofdm_code_rate_HP = FEC_5_6;
1806 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1807 parm_u_ofdm_code_rate_HP = FEC_7_8;
1810 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1811 parm_u_ofdm_code_rate_HP = FEC_AUTO;
1814 switch (feparm.modulation)
1816 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
1817 parm_u_ofdm_constellation = QPSK;
1819 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
1820 parm_u_ofdm_constellation = QAM_16;
1822 case eDVBFrontendParametersTerrestrial::Modulation::QAM64:
1823 parm_u_ofdm_constellation = QAM_64;
1826 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
1827 parm_u_ofdm_constellation = QAM_AUTO;
1830 switch (feparm.transmission_mode)
1832 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
1833 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
1835 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
1836 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
1839 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
1840 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
1843 switch (feparm.guard_interval)
1845 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32:
1846 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
1848 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16:
1849 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
1851 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8:
1852 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
1854 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4:
1855 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
1858 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto:
1859 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
1862 switch (feparm.hierarchy)
1864 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone:
1865 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
1867 case eDVBFrontendParametersTerrestrial::Hierarchy::H1:
1868 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
1870 case eDVBFrontendParametersTerrestrial::Hierarchy::H2:
1871 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
1873 case eDVBFrontendParametersTerrestrial::Hierarchy::H4:
1874 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
1877 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto:
1878 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
1881 switch (feparm.inversion)
1883 case eDVBFrontendParametersTerrestrial::Inversion::On:
1884 parm_inversion = INVERSION_ON;
1886 case eDVBFrontendParametersTerrestrial::Inversion::Off:
1887 parm_inversion = INVERSION_OFF;
1890 case eDVBFrontendParametersTerrestrial::Inversion::Unknown:
1891 parm_inversion = INVERSION_AUTO;
1897 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
1899 unsigned int timeout = 5000;
1900 eDebug("(%d)tune", m_dvbid);
1908 eDebug("no frontend device opened... do not try to tune !!!");
1920 m_sec_sequence.clear();
1922 where.calcLockTimeout(timeout);
1928 eDVBFrontendParametersSatellite feparm;
1929 if (where.getDVBS(feparm))
1931 eDebug("no dvbs data!");
1935 m_sec->setRotorMoving(false);
1936 res=prepare_sat(feparm, timeout);
1944 eDVBFrontendParametersCable feparm;
1945 if (where.getDVBC(feparm))
1950 res=prepare_cable(feparm);
1954 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
1955 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
1960 eDVBFrontendParametersTerrestrial feparm;
1961 if (where.getDVBT(feparm))
1963 eDebug("no -T data");
1967 res=prepare_terrestrial(feparm);
1971 std::string enable_5V;
1972 char configStr[255];
1973 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
1974 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
1975 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
1976 if (enable_5V == "True")
1977 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
1979 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
1980 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
1986 m_tuneTimer->start(0,true);
1987 m_sec_sequence.current() = m_sec_sequence.begin();
1989 if (m_state != stateTuning)
1992 m_state = stateTuning;
1993 m_stateChanged(this);
1999 m_tuneTimer->stop();
2003 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2005 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2009 RESULT eDVBFrontend::setVoltage(int voltage)
2011 if (m_type == feCable)
2013 #if HAVE_DVB_API_VERSION < 3
2016 bool increased=false;
2017 fe_sec_voltage_t vlt;
2019 m_data[CUR_VOLTAGE]=voltage;
2023 for (int i=0; i < 3; ++i) // reset diseqc
2025 vlt = SEC_VOLTAGE_OFF;
2028 #if HAVE_DVB_API_VERSION < 3
2029 vlt = SEC_VOLTAGE_13_5;
2035 vlt = SEC_VOLTAGE_13;
2038 #if HAVE_DVB_API_VERSION < 3
2039 vlt = SEC_VOLTAGE_18_5;
2045 vlt = SEC_VOLTAGE_18;
2050 #if HAVE_DVB_API_VERSION < 3
2051 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2053 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2054 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2055 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2059 RESULT eDVBFrontend::getState(int &state)
2065 RESULT eDVBFrontend::setTone(int t)
2067 if (m_type != feSatellite)
2069 #if HAVE_DVB_API_VERSION < 3
2072 fe_sec_tone_mode_t tone;
2081 tone = SEC_TONE_OFF;
2086 #if HAVE_DVB_API_VERSION < 3
2087 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2089 return ::ioctl(m_fd, FE_SET_TONE, tone);
2093 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2094 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2097 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2099 #if HAVE_DVB_API_VERSION < 3
2100 struct secCommand cmd;
2101 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2102 cmd.u.diseqc.cmdtype = diseqc.data[0];
2103 cmd.u.diseqc.addr = diseqc.data[1];
2104 cmd.u.diseqc.cmd = diseqc.data[2];
2105 cmd.u.diseqc.numParams = diseqc.len-3;
2106 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2107 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2109 struct dvb_diseqc_master_cmd cmd;
2110 memcpy(cmd.msg, diseqc.data, diseqc.len);
2111 cmd.msg_len = diseqc.len;
2112 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2118 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2119 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2121 RESULT eDVBFrontend::sendToneburst(int burst)
2123 #if HAVE_DVB_API_VERSION < 3
2124 secMiniCmd cmd = SEC_MINI_NONE;
2126 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2128 if ( burst == eDVBSatelliteDiseqcParameters::A )
2130 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2132 #if HAVE_DVB_API_VERSION < 3
2133 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2136 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2142 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2148 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2150 m_sec_sequence = list;
2154 RESULT eDVBFrontend::getData(int num, long &data)
2156 if ( num < NUM_DATA_ENTRIES )
2164 RESULT eDVBFrontend::setData(int num, long val)
2166 if ( num < NUM_DATA_ENTRIES )
2174 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2177 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2180 if (m_type == eDVBFrontend::feSatellite)
2183 eDVBFrontendParametersSatellite sat_parm;
2184 int ret = feparm->getDVBS(sat_parm);
2186 return m_sec->canTune(sat_parm, this, 1 << m_slotid);
2188 else if (m_type == eDVBFrontend::feCable)
2189 return 2; // more prio for cable frontends
2193 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2195 ePyObject Id, Descr, Enabled;
2196 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 3)
2198 Id = PyTuple_GET_ITEM(obj, 0);
2199 Descr = PyTuple_GET_ITEM(obj, 1);
2200 Enabled = PyTuple_GET_ITEM(obj, 2);
2201 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled))
2203 strcpy(m_description, PyString_AS_STRING(Descr));
2204 m_slotid = PyInt_AsLong(Id);
2205 m_enabled = Enabled == Py_True;
2206 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2207 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2208 !!strstr(m_description, "Alps BSBE2") ||
2209 !!strstr(m_description, "Alps -S");
2210 eDebug("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s",
2211 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No" );
2214 PyErr_SetString(PyExc_StandardError,
2215 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");