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:
375 case iDVBFrontend::feTerrestrial:
383 RESULT eDVBFrontendParameters::calcLockTimeout(unsigned int &timeout) const
387 case iDVBFrontend::feSatellite:
389 /* high symbol rate transponders tune faster, due to
390 requiring less zigzag and giving more symbols faster.
392 5s are definitely not enough on really low SR when
393 zigzag has to find the exact frequency first.
395 if (sat.symbol_rate > 20000000)
397 else if (sat.symbol_rate > 10000000)
403 case iDVBFrontend::feCable:
406 case iDVBFrontend::feTerrestrial:
414 DEFINE_REF(eDVBFrontend);
416 int eDVBFrontend::PriorityOrder=0;
418 eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok)
419 :m_enabled(false), m_type(-1), m_dvbid(fe), m_slotid(fe)
420 ,m_fd(-1), m_need_rotor_workaround(false), m_sn(0), m_timeout(0), m_tuneTimer(0)
421 #if HAVE_DVB_API_VERSION < 3
425 #if HAVE_DVB_API_VERSION < 3
426 sprintf(m_filename, "/dev/dvb/card%d/frontend%d", adap, fe);
427 sprintf(m_sec_filename, "/dev/dvb/card%d/sec%d", adap, fe);
429 sprintf(m_filename, "/dev/dvb/adapter%d/frontend%d", adap, fe);
431 m_timeout = new eTimer(eApp);
432 CONNECT(m_timeout->timeout, eDVBFrontend::timeout);
434 m_tuneTimer = new eTimer(eApp);
435 CONNECT(m_tuneTimer->timeout, eDVBFrontend::tuneLoop);
437 for (int i=0; i<eDVBFrontend::NUM_DATA_ENTRIES; ++i)
440 m_idleInputpower[0]=m_idleInputpower[1]=0;
442 ok = !openFrontend();
446 int eDVBFrontend::openFrontend()
449 return -1; // already opened
454 #if HAVE_DVB_API_VERSION < 3
455 FrontendInfo fe_info;
457 dvb_frontend_info fe_info;
459 eDebug("opening frontend %d", m_dvbid);
462 m_fd = ::open(m_filename, O_RDWR|O_NONBLOCK);
465 eWarning("failed! (%s) %m", m_filename);
470 eWarning("frontend %d already opened", m_dvbid);
473 if (::ioctl(m_fd, FE_GET_INFO, &fe_info) < 0)
475 eWarning("ioctl FE_GET_INFO failed");
481 switch (fe_info.type)
484 m_type = iDVBFrontend::feSatellite;
487 m_type = iDVBFrontend::feCable;
490 m_type = iDVBFrontend::feTerrestrial;
493 eWarning("unknown frontend type.");
498 eDebug("detected %s frontend", "satellite\0cable\0 terrestrial"+fe_info.type*10);
501 #if HAVE_DVB_API_VERSION < 3
502 if (m_type == iDVBFrontend::feSatellite)
506 m_secfd = ::open(m_sec_filename, O_RDWR);
509 eWarning("failed! (%s) %m", m_sec_filename);
516 eWarning("sec %d already opened", m_dvbid);
520 setTone(iDVBFrontend::toneOff);
521 setVoltage(iDVBFrontend::voltageOff);
523 m_sn = new eSocketNotifier(eApp, m_fd, eSocketNotifier::Read);
524 CONNECT(m_sn->activated, eDVBFrontend::feEvent);
529 int eDVBFrontend::closeFrontend()
531 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)m_data[LINKED_NEXT_PTR];
532 while (linked_fe != (eDVBRegisteredFrontend*)-1)
534 if (linked_fe->m_inuse)
536 eDebug("dont close frontend %d until the linked frontend %d in slot %d is still in use",
537 m_dvbid, linked_fe->m_frontend->getDVBID(), linked_fe->m_frontend->getSlotID());
540 linked_fe->m_frontend->getData(LINKED_NEXT_PTR, (long&)linked_fe);
544 eDebug("close frontend %d", m_dvbid);
546 setTone(iDVBFrontend::toneOff);
547 setVoltage(iDVBFrontend::voltageOff);
549 m_sec->setRotorMoving(false);
553 eWarning("couldnt close frontend %d", m_dvbid);
554 m_data[CSW] = m_data[UCSW] = m_data[TONEBURST] = -1;
556 #if HAVE_DVB_API_VERSION < 3
559 if (!::close(m_secfd))
562 eWarning("couldnt close sec %d", m_dvbid);
571 eDVBFrontend::~eDVBFrontend()
578 void eDVBFrontend::feEvent(int w)
582 #if HAVE_DVB_API_VERSION < 3
585 dvb_frontend_event event;
589 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
591 if (res && (errno == EAGAIN))
596 eWarning("FE_GET_EVENT failed! %m");
603 #if HAVE_DVB_API_VERSION < 3
604 if (event.type == FE_COMPLETION_EV)
606 eDebug("(%d)fe event: status %x, inversion %s", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off");
607 if (event.status & FE_HAS_LOCK)
617 eDebug("stateLostLock");
618 state = stateLostLock;
619 m_data[CSW] = m_data[UCSW] = m_data[TONEBURST] = -1; // reset diseqc
622 if (m_state != state)
625 m_stateChanged(this);
630 void eDVBFrontend::timeout()
633 if (m_state == stateTuning)
635 m_state = stateFailed;
636 m_stateChanged(this);
640 int eDVBFrontend::readFrontendData(int type)
647 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
648 eDebug("FE_READ_BER failed (%m)");
654 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
655 eDebug("FE_READ_SNR failed (%m)");
658 case signalQualitydB: /* this will move into the driver */
661 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
662 eDebug("FE_READ_SNR failed (%m)");
663 if (!strcmp(m_description, "BCM4501 (internal)"))
665 unsigned int SDS_SNRE = snr << 16;
667 static float SNR_COEFF[6] = {
670 197418.0 / 4194304.0,
671 -2602183.0 / 4194304.0,
672 20377212.0 / 4194304.0,
673 -37791203.0 / 4194304.0,
676 float fval1, fval2, snr_in_db;
678 fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0));
679 fval2 = pow(10.0, fval1)-1;
680 fval1 = 10.0 * log10(fval2);
684 fval2 = SNR_COEFF[0];
688 fval2 += SNR_COEFF[i];
694 return (int)(snr_in_db * 100.0);
696 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
697 !strcmp(m_description, "Alps -S") ||
698 !strcmp(m_description, "Philips -S") ||
699 !strcmp(m_description, "LG -S") )
701 float snr_in_db=(snr-39075)/1764.7;
702 return (int)(snr_in_db * 100.0);
703 } else if (!strcmp(m_description, "Alps BSBE2"))
705 return (int)((snr >> 7) * 10.0);
707 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
713 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
714 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
719 #if HAVE_DVB_API_VERSION < 3
720 FrontendStatus status=0;
724 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
725 eDebug("FE_READ_STATUS failed (%m)");
726 return !!(status&FE_HAS_LOCK);
730 #if HAVE_DVB_API_VERSION < 3
731 FrontendStatus status=0;
735 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
736 eDebug("FE_READ_STATUS failed (%m)");
737 return !!(status&FE_HAS_SYNC);
745 void PutToDict(ePyObject &dict, const char*key, long value)
747 ePyObject item = PyInt_FromLong(value);
750 if (PyDict_SetItemString(dict, key, item))
751 eDebug("put %s to dict failed", key);
755 eDebug("could not create PyObject for %s", key);
758 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
762 if (PyDict_SetItemString(dict, key, item))
763 eDebug("put %s to dict failed", key);
767 eDebug("invalid PyObject for %s", key);
770 void PutToDict(ePyObject &dict, const char*key, const char *value)
772 ePyObject item = PyString_FromString(value);
775 if (PyDict_SetItemString(dict, key, item))
776 eDebug("put %s to dict failed", key);
780 eDebug("could not create PyObject for %s", key);
783 void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, eDVBFrontend *fe)
788 fe->getData(eDVBFrontend::CSW, csw);
789 fe->getData(eDVBFrontend::FREQ_OFFSET, freq_offset);
790 int frequency = parm_frequency + freq_offset;
791 PutToDict(dict, "frequency", frequency);
792 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
793 switch(parm_u_qpsk_fec_inner)
816 #if HAVE_DVB_API_VERSION >=3
817 case FEC_S2_8PSK_1_2:
818 case FEC_S2_QPSK_1_2:
821 case FEC_S2_8PSK_2_3:
822 case FEC_S2_QPSK_2_3:
825 case FEC_S2_8PSK_3_4:
826 case FEC_S2_QPSK_3_4:
829 case FEC_S2_8PSK_5_6:
830 case FEC_S2_QPSK_5_6:
833 case FEC_S2_8PSK_7_8:
834 case FEC_S2_QPSK_7_8:
837 case FEC_S2_8PSK_8_9:
838 case FEC_S2_QPSK_8_9:
841 case FEC_S2_8PSK_3_5:
842 case FEC_S2_QPSK_3_5:
845 case FEC_S2_8PSK_4_5:
846 case FEC_S2_QPSK_4_5:
849 case FEC_S2_8PSK_9_10:
850 case FEC_S2_QPSK_9_10:
855 #if HAVE_DVB_API_VERSION >=3
856 PutToDict(dict, "modulation",
857 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ? "8PSK": "QPSK" );
859 PutToDict(dict, "modulation", "QPSK" );
861 PutToDict(dict, "fec_inner", tmp);
862 tmp = parm_u_qpsk_fec_inner > FEC_AUTO ?
864 PutToDict(dict, "system", tmp);
867 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
870 PutToDict(dict, "frequency", parm_frequency/1000);
871 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
872 switch(parm_u_qam_fec_inner)
892 #if HAVE_DVB_API_VERSION >= 3
902 PutToDict(dict, "fec_inner", tmp);
903 switch(parm_u_qam_modulation)
925 PutToDict(dict, "modulation", tmp);
928 void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
931 PutToDict(dict, "frequency", parm_frequency);
932 switch (parm_u_ofdm_bandwidth)
934 case BANDWIDTH_8_MHZ:
935 tmp = "BANDWIDTH_8_MHZ";
937 case BANDWIDTH_7_MHZ:
938 tmp = "BANDWIDTH_7_MHZ";
940 case BANDWIDTH_6_MHZ:
941 tmp = "BANDWIDTH_6_MHZ";
945 tmp = "BANDWIDTH_AUTO";
948 PutToDict(dict, "bandwidth", tmp);
949 switch (parm_u_ofdm_code_rate_LP)
971 PutToDict(dict, "code_rate_lp", tmp);
972 switch (parm_u_ofdm_code_rate_HP)
994 PutToDict(dict, "code_rate_hp", tmp);
995 switch (parm_u_ofdm_constellation)
1011 PutToDict(dict, "constellation", tmp);
1012 switch (parm_u_ofdm_transmission_mode)
1014 case TRANSMISSION_MODE_2K:
1015 tmp = "TRANSMISSION_MODE_2K";
1017 case TRANSMISSION_MODE_8K:
1018 tmp = "TRANSMISSION_MODE_8K";
1021 case TRANSMISSION_MODE_AUTO:
1022 tmp = "TRANSMISSION_MODE_AUTO";
1025 PutToDict(dict, "transmission_mode", tmp);
1026 switch (parm_u_ofdm_guard_interval)
1028 case GUARD_INTERVAL_1_32:
1029 tmp = "GUARD_INTERVAL_1_32";
1031 case GUARD_INTERVAL_1_16:
1032 tmp = "GUARD_INTERVAL_1_16";
1034 case GUARD_INTERVAL_1_8:
1035 tmp = "GUARD_INTERVAL_1_8";
1037 case GUARD_INTERVAL_1_4:
1038 tmp = "GUARD_INTERVAL_1_4";
1041 case GUARD_INTERVAL_AUTO:
1042 tmp = "GUARD_INTERVAL_AUTO";
1045 PutToDict(dict, "guard_interval", tmp);
1046 switch (parm_u_ofdm_hierarchy_information)
1048 case HIERARCHY_NONE:
1049 tmp = "HIERARCHY_NONE";
1052 tmp = "HIERARCHY_1";
1055 tmp = "HIERARCHY_2";
1058 tmp = "HIERARCHY_4";
1061 case HIERARCHY_AUTO:
1062 tmp = "HIERARCHY_AUTO";
1065 PutToDict(dict, "hierarchy_information", tmp);
1068 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1070 if (dest && PyDict_Check(dest))
1072 const char *tmp = "UNKNOWN";
1093 PutToDict(dest, "tuner_state", tmp);
1094 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1095 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1096 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1097 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1098 int sigQualitydB = readFrontendData(signalQualitydB);
1099 if (sigQualitydB == 0x12345678) // not support yet
1101 ePyObject obj=Py_None;
1103 PutToDict(dest, "tuner_signal_quality_db", obj);
1106 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1107 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1111 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1113 if (m_fd != -1 && dest && PyDict_Check(dest))
1121 FRONTENDPARAMETERS front;
1122 if (!original && ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1123 eDebug("FE_GET_FRONTEND (%m)");
1126 const FRONTENDPARAMETERS &parm = original ? this->parm : front;
1127 const char *tmp = "INVERSION_AUTO";
1128 switch(parm_inversion)
1131 tmp = "INVERSION_ON";
1134 tmp = "INVERSION_OFF";
1140 PutToDict(dest, "inversion", tmp);
1145 fillDictWithSatelliteData(dest, original?parm:front, this);
1148 fillDictWithCableData(dest, original?parm:front);
1151 fillDictWithTerrestrialData(dest, original?parm:front);
1162 void eDVBFrontend::getFrontendData(ePyObject dest)
1164 if (dest && PyDict_Check(dest))
1167 PutToDict(dest, "tuner_number", m_dvbid);
1183 PutToDict(dest, "tuner_type", tmp);
1187 #ifndef FP_IOCTL_GET_ID
1188 #define FP_IOCTL_GET_ID 0
1190 int eDVBFrontend::readInputpower()
1192 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1194 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1195 FILE *f=fopen(proc_name, "r");
1198 if (fscanf(f, "%08x", &power) != 1)
1199 eDebug("read %s failed!! (%m)", proc_name);
1201 eDebug("%s is %d\n", proc_name, power);
1206 // open front prozessor
1207 int fp=::open("/dev/dbox/fp0", O_RDWR);
1210 eDebug("couldn't open fp");
1213 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1214 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1216 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1225 bool eDVBFrontend::setSecSequencePos(int steps)
1227 eDebug("set sequence pos %d", steps);
1232 if (m_sec_sequence.current() != m_sec_sequence.end())
1233 ++m_sec_sequence.current();
1238 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1239 --m_sec_sequence.current();
1245 void eDVBFrontend::setRotorData(int pos, int cmd)
1247 m_data[ROTOR_CMD] = cmd;
1248 m_data[ROTOR_POS] = pos;
1249 if ( m_data[SATPOS_DEPENDS_PTR] != -1 )
1251 eDVBRegisteredFrontend *satpos_depends_to_fe = (eDVBRegisteredFrontend*) m_data[SATPOS_DEPENDS_PTR];
1252 satpos_depends_to_fe->m_frontend->m_data[ROTOR_CMD] = cmd;
1253 satpos_depends_to_fe->m_frontend->m_data[ROTOR_POS] = pos;
1257 eDVBRegisteredFrontend *next = (eDVBRegisteredFrontend *)m_data[LINKED_NEXT_PTR];
1258 while ( (long)next != -1 )
1260 next->m_frontend->m_data[ROTOR_CMD] = cmd;
1261 next->m_frontend->m_data[ROTOR_POS] = pos;
1262 next = (eDVBRegisteredFrontend *)next->m_frontend->m_data[LINKED_NEXT_PTR];
1264 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)m_data[LINKED_PREV_PTR];
1265 while ( (long)prev != -1 )
1267 prev->m_frontend->m_data[ROTOR_CMD] = cmd;
1268 prev->m_frontend->m_data[ROTOR_POS] = pos;
1269 prev = (eDVBRegisteredFrontend *)prev->m_frontend->m_data[LINKED_PREV_PTR];
1274 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1277 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1279 // eDebug("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1280 switch (m_sec_sequence.current()->cmd)
1282 case eSecCommand::SLEEP:
1283 delay = m_sec_sequence.current()++->msec;
1284 eDebug("[SEC] sleep %dms", delay);
1286 case eSecCommand::GOTO:
1287 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1288 ++m_sec_sequence.current();
1290 case eSecCommand::SET_VOLTAGE:
1292 int voltage = m_sec_sequence.current()++->voltage;
1293 eDebug("[SEC] setVoltage %d", voltage);
1294 setVoltage(voltage);
1297 case eSecCommand::IF_VOLTAGE_GOTO:
1299 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1300 if ( compare.voltage == m_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1302 ++m_sec_sequence.current();
1305 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1307 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1308 if ( compare.voltage != m_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1310 ++m_sec_sequence.current();
1313 case eSecCommand::IF_TONE_GOTO:
1315 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1316 if ( compare.tone == m_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1318 ++m_sec_sequence.current();
1321 case eSecCommand::IF_NOT_TONE_GOTO:
1323 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1324 if ( compare.tone != m_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1326 ++m_sec_sequence.current();
1329 case eSecCommand::SET_TONE:
1330 eDebug("[SEC] setTone %d", m_sec_sequence.current()->tone);
1331 setTone(m_sec_sequence.current()++->tone);
1333 case eSecCommand::SEND_DISEQC:
1334 sendDiseqc(m_sec_sequence.current()->diseqc);
1335 eDebugNoNewLine("[SEC] sendDiseqc: ");
1336 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1337 eDebugNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1339 ++m_sec_sequence.current();
1341 case eSecCommand::SEND_TONEBURST:
1342 eDebug("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1343 sendToneburst(m_sec_sequence.current()++->toneburst);
1345 case eSecCommand::SET_FRONTEND:
1346 eDebug("[SEC] setFrontend");
1348 ++m_sec_sequence.current();
1350 case eSecCommand::START_TUNE_TIMEOUT:
1352 m_timeout->start(m_sec_sequence.current()->timeout, 1);
1353 ++m_sec_sequence.current();
1356 case eSecCommand::SET_TIMEOUT:
1357 m_timeoutCount = m_sec_sequence.current()++->val;
1358 eDebug("[SEC] set timeout %d", m_timeoutCount);
1360 case eSecCommand::IF_TIMEOUT_GOTO:
1361 if (!m_timeoutCount)
1363 eDebug("[SEC] rotor timout");
1364 m_sec->setRotorMoving(false);
1365 setSecSequencePos(m_sec_sequence.current()->steps);
1368 ++m_sec_sequence.current();
1370 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1372 int idx = m_sec_sequence.current()++->val;
1373 if ( idx == 0 || idx == 1 )
1375 m_idleInputpower[idx] = readInputpower();
1376 eDebug("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1379 eDebug("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1382 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1384 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1385 int idx = compare.val;
1386 if ( idx == 0 || idx == 1 )
1388 int idle = readInputpower();
1389 int diff = abs(idle-m_idleInputpower[idx]);
1392 eDebug("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1393 setSecSequencePos(compare.steps);
1397 ++m_sec_sequence.current();
1400 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1402 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1403 if (readFrontendData(locked))
1405 eDebug("[SEC] locked step %d ok", cmd.okcount);
1407 if (cmd.okcount > 12)
1409 eDebug("ok > 12 .. goto %d\n",m_sec_sequence.current()->steps);
1410 setSecSequencePos(cmd.steps);
1416 eDebug("[SEC] rotor locked step %d failed", cmd.okcount);
1418 if (!m_timeoutCount && m_retryCount > 0)
1422 ++m_sec_sequence.current();
1425 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1426 m_runningInputpower = readInputpower();
1427 eDebug("[SEC] runningInputpower is %d", m_runningInputpower);
1428 ++m_sec_sequence.current();
1430 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1432 int idleInputpower = m_idleInputpower[ (m_data[CUR_VOLTAGE]&1) ? 0 : 1];
1433 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1434 const char *txt = cmd.direction ? "running" : "stopped";
1435 eDebug("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1437 m_runningInputpower,
1440 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1441 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1444 eDebug("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1445 if ( cmd.okcount > 6 )
1447 m_sec->setRotorMoving(cmd.direction);
1448 eDebug("[SEC] rotor is %s", txt);
1449 if (setSecSequencePos(cmd.steps))
1455 eDebug("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1457 if (!m_timeoutCount && m_retryCount > 0)
1461 ++m_sec_sequence.current();
1464 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1465 if (m_data[ROTOR_CMD] != -1 && m_data[ROTOR_POS] != -1)
1466 setSecSequencePos(m_sec_sequence.current()->steps);
1468 ++m_sec_sequence.current();
1470 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1471 eDebug("[SEC] invalidate current rotorparams");
1472 setRotorData(-1,-1);
1473 ++m_sec_sequence.current();
1475 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1476 setRotorData(m_data[NEW_ROTOR_POS], m_data[NEW_ROTOR_CMD]);
1477 eDebug("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, m_data[ROTOR_CMD], m_data[ROTOR_POS]);
1478 ++m_sec_sequence.current();
1480 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1481 m_retryCount = m_sec_sequence.current()++->val;
1482 eDebug("[SEC] set rotor retries %d", m_retryCount);
1484 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1487 eDebug("[SEC] no more rotor retrys");
1488 setSecSequencePos(m_sec_sequence.current()->steps);
1491 ++m_sec_sequence.current();
1493 case eSecCommand::SET_POWER_LIMITING_MODE:
1495 if (m_need_rotor_workaround)
1499 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1501 sprintf(dev, "/dev/i2c/%d", m_slotid);
1502 else if (m_slotid == 2)
1503 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1504 else if (m_slotid == 3)
1505 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1506 int fd = ::open(dev, O_RDWR);
1508 unsigned char data[2];
1509 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1510 if(::read(fd, data, 1) != 1)
1511 eDebug("[SEC] error read lnbp (%m)");
1512 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1514 data[0] |= 0x80; // enable static current limiting
1515 eDebug("[SEC] set static current limiting");
1519 data[0] &= ~0x80; // enable dynamic current limiting
1520 eDebug("[SEC] set dynamic current limiting");
1522 if(::write(fd, data, 1) != 1)
1523 eDebug("[SEC] error write lnbp (%m)");
1526 ++m_sec_sequence.current();
1530 eDebug("[SEC] unhandled sec command %d",
1531 ++m_sec_sequence.current()->cmd);
1532 ++m_sec_sequence.current();
1534 m_tuneTimer->start(delay,true);
1538 void eDVBFrontend::setFrontend()
1540 eDebug("setting frontend %d", m_dvbid);
1543 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1545 perror("FE_SET_FRONTEND failed");
1550 RESULT eDVBFrontend::getFrontendType(int &t)
1558 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1563 eWarning("no SEC module active!");
1566 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1569 eDebug("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1572 feparm.polarisation,
1576 feparm.orbital_position);
1577 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1578 switch (feparm.inversion)
1580 case eDVBFrontendParametersSatellite::Inversion::On:
1581 parm_inversion = INVERSION_ON;
1583 case eDVBFrontendParametersSatellite::Inversion::Off:
1584 parm_inversion = INVERSION_OFF;
1587 case eDVBFrontendParametersSatellite::Inversion::Unknown:
1588 parm_inversion = INVERSION_AUTO;
1591 if (feparm.system == eDVBFrontendParametersSatellite::System::DVB_S)
1594 case eDVBFrontendParametersSatellite::FEC::fNone:
1595 parm_u_qpsk_fec_inner = FEC_NONE;
1597 case eDVBFrontendParametersSatellite::FEC::f1_2:
1598 parm_u_qpsk_fec_inner = FEC_1_2;
1600 case eDVBFrontendParametersSatellite::FEC::f2_3:
1601 parm_u_qpsk_fec_inner = FEC_2_3;
1603 case eDVBFrontendParametersSatellite::FEC::f3_4:
1604 parm_u_qpsk_fec_inner = FEC_3_4;
1606 case eDVBFrontendParametersSatellite::FEC::f5_6:
1607 parm_u_qpsk_fec_inner = FEC_5_6;
1609 case eDVBFrontendParametersSatellite::FEC::f7_8:
1610 parm_u_qpsk_fec_inner = FEC_7_8;
1613 eDebug("no valid fec for DVB-S set.. assume auto");
1614 case eDVBFrontendParametersSatellite::FEC::fAuto:
1615 parm_u_qpsk_fec_inner = FEC_AUTO;
1618 #if HAVE_DVB_API_VERSION >= 3
1623 case eDVBFrontendParametersSatellite::FEC::f1_2:
1624 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1626 case eDVBFrontendParametersSatellite::FEC::f2_3:
1627 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1629 case eDVBFrontendParametersSatellite::FEC::f3_4:
1630 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1632 case eDVBFrontendParametersSatellite::FEC::f3_5:
1633 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1635 case eDVBFrontendParametersSatellite::FEC::f4_5:
1636 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1638 case eDVBFrontendParametersSatellite::FEC::f5_6:
1639 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1641 case eDVBFrontendParametersSatellite::FEC::f7_8:
1642 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1644 case eDVBFrontendParametersSatellite::FEC::f8_9:
1645 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1647 case eDVBFrontendParametersSatellite::FEC::f9_10:
1648 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1651 eDebug("no valid fec for DVB-S2 set.. abort !!");
1654 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK)
1655 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1656 // 8PSK fec driver values are decimal 9 bigger
1659 // FIXME !!! get frequency range from tuner
1660 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1662 eDebug("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1665 eDebug("tuning to %d mhz", parm_frequency/1000);
1670 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1672 parm_frequency = feparm.frequency * 1000;
1673 parm_u_qam_symbol_rate = feparm.symbol_rate;
1674 switch (feparm.modulation)
1676 case eDVBFrontendParametersCable::Modulation::QAM16:
1677 parm_u_qam_modulation = QAM_16;
1679 case eDVBFrontendParametersCable::Modulation::QAM32:
1680 parm_u_qam_modulation = QAM_32;
1682 case eDVBFrontendParametersCable::Modulation::QAM64:
1683 parm_u_qam_modulation = QAM_64;
1685 case eDVBFrontendParametersCable::Modulation::QAM128:
1686 parm_u_qam_modulation = QAM_128;
1688 case eDVBFrontendParametersCable::Modulation::QAM256:
1689 parm_u_qam_modulation = QAM_256;
1692 case eDVBFrontendParametersCable::Modulation::Auto:
1693 parm_u_qam_modulation = QAM_AUTO;
1696 switch (feparm.inversion)
1698 case eDVBFrontendParametersCable::Inversion::On:
1699 parm_inversion = INVERSION_ON;
1701 case eDVBFrontendParametersCable::Inversion::Off:
1702 parm_inversion = INVERSION_OFF;
1705 case eDVBFrontendParametersCable::Inversion::Unknown:
1706 parm_inversion = INVERSION_AUTO;
1709 switch (feparm.fec_inner)
1711 case eDVBFrontendParametersCable::FEC::fNone:
1712 parm_u_qam_fec_inner = FEC_NONE;
1714 case eDVBFrontendParametersCable::FEC::f1_2:
1715 parm_u_qam_fec_inner = FEC_1_2;
1717 case eDVBFrontendParametersCable::FEC::f2_3:
1718 parm_u_qam_fec_inner = FEC_2_3;
1720 case eDVBFrontendParametersCable::FEC::f3_4:
1721 parm_u_qam_fec_inner = FEC_3_4;
1723 case eDVBFrontendParametersCable::FEC::f5_6:
1724 parm_u_qam_fec_inner = FEC_5_6;
1726 case eDVBFrontendParametersCable::FEC::f7_8:
1727 parm_u_qam_fec_inner = FEC_7_8;
1729 #if HAVE_DVB_API_VERSION >= 3
1730 case eDVBFrontendParametersCable::FEC::f8_9:
1731 parm_u_qam_fec_inner = FEC_8_9;
1735 case eDVBFrontendParametersCable::FEC::fAuto:
1736 parm_u_qam_fec_inner = FEC_AUTO;
1739 eDebug("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
1740 parm_frequency/1000,
1741 parm_u_qam_symbol_rate,
1742 parm_u_qam_fec_inner,
1743 parm_u_qam_modulation,
1748 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
1750 parm_frequency = feparm.frequency;
1752 switch (feparm.bandwidth)
1754 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
1755 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
1757 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
1758 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
1760 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
1761 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
1764 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
1765 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
1768 switch (feparm.code_rate_LP)
1770 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1771 parm_u_ofdm_code_rate_LP = FEC_1_2;
1773 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1774 parm_u_ofdm_code_rate_LP = FEC_2_3;
1776 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1777 parm_u_ofdm_code_rate_LP = FEC_3_4;
1779 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1780 parm_u_ofdm_code_rate_LP = FEC_5_6;
1782 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1783 parm_u_ofdm_code_rate_LP = FEC_7_8;
1786 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1787 parm_u_ofdm_code_rate_LP = FEC_AUTO;
1790 switch (feparm.code_rate_HP)
1792 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1793 parm_u_ofdm_code_rate_HP = FEC_1_2;
1795 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1796 parm_u_ofdm_code_rate_HP = FEC_2_3;
1798 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1799 parm_u_ofdm_code_rate_HP = FEC_3_4;
1801 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1802 parm_u_ofdm_code_rate_HP = FEC_5_6;
1804 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1805 parm_u_ofdm_code_rate_HP = FEC_7_8;
1808 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1809 parm_u_ofdm_code_rate_HP = FEC_AUTO;
1812 switch (feparm.modulation)
1814 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
1815 parm_u_ofdm_constellation = QPSK;
1817 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
1818 parm_u_ofdm_constellation = QAM_16;
1820 case eDVBFrontendParametersTerrestrial::Modulation::QAM64:
1821 parm_u_ofdm_constellation = QAM_64;
1824 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
1825 parm_u_ofdm_constellation = QAM_AUTO;
1828 switch (feparm.transmission_mode)
1830 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
1831 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
1833 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
1834 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
1837 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
1838 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
1841 switch (feparm.guard_interval)
1843 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32:
1844 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
1846 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16:
1847 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
1849 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8:
1850 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
1852 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4:
1853 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
1856 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto:
1857 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
1860 switch (feparm.hierarchy)
1862 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone:
1863 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
1865 case eDVBFrontendParametersTerrestrial::Hierarchy::H1:
1866 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
1868 case eDVBFrontendParametersTerrestrial::Hierarchy::H2:
1869 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
1871 case eDVBFrontendParametersTerrestrial::Hierarchy::H4:
1872 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
1875 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto:
1876 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
1879 switch (feparm.inversion)
1881 case eDVBFrontendParametersTerrestrial::Inversion::On:
1882 parm_inversion = INVERSION_ON;
1884 case eDVBFrontendParametersTerrestrial::Inversion::Off:
1885 parm_inversion = INVERSION_OFF;
1888 case eDVBFrontendParametersTerrestrial::Inversion::Unknown:
1889 parm_inversion = INVERSION_AUTO;
1895 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
1897 unsigned int timeout = 5000;
1898 eDebug("(%d)tune", m_dvbid);
1906 eDebug("no frontend device opened... do not try to tune !!!");
1918 m_sec_sequence.clear();
1920 where.calcLockTimeout(timeout);
1926 eDVBFrontendParametersSatellite feparm;
1927 if (where.getDVBS(feparm))
1929 eDebug("no dvbs data!");
1933 m_sec->setRotorMoving(false);
1934 res=prepare_sat(feparm, timeout);
1942 eDVBFrontendParametersCable feparm;
1943 if (where.getDVBC(feparm))
1948 res=prepare_cable(feparm);
1952 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
1953 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
1958 eDVBFrontendParametersTerrestrial feparm;
1959 if (where.getDVBT(feparm))
1961 eDebug("no -T data");
1965 res=prepare_terrestrial(feparm);
1969 std::string enable_5V;
1970 char configStr[255];
1971 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
1972 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
1973 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
1974 if (enable_5V == "True")
1975 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
1977 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
1978 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
1984 m_tuneTimer->start(0,true);
1985 m_sec_sequence.current() = m_sec_sequence.begin();
1987 if (m_state != stateTuning)
1990 m_state = stateTuning;
1991 m_stateChanged(this);
1997 m_tuneTimer->stop();
2001 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2003 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2007 RESULT eDVBFrontend::setVoltage(int voltage)
2009 if (m_type == feCable)
2011 #if HAVE_DVB_API_VERSION < 3
2014 bool increased=false;
2015 fe_sec_voltage_t vlt;
2017 m_data[CUR_VOLTAGE]=voltage;
2021 for (int i=0; i < 3; ++i) // reset diseqc
2023 vlt = SEC_VOLTAGE_OFF;
2026 #if HAVE_DVB_API_VERSION < 3
2027 vlt = SEC_VOLTAGE_13_5;
2033 vlt = SEC_VOLTAGE_13;
2036 #if HAVE_DVB_API_VERSION < 3
2037 vlt = SEC_VOLTAGE_18_5;
2043 vlt = SEC_VOLTAGE_18;
2048 #if HAVE_DVB_API_VERSION < 3
2049 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2051 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2052 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2053 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2057 RESULT eDVBFrontend::getState(int &state)
2063 RESULT eDVBFrontend::setTone(int t)
2065 if (m_type != feSatellite)
2067 #if HAVE_DVB_API_VERSION < 3
2070 fe_sec_tone_mode_t tone;
2079 tone = SEC_TONE_OFF;
2084 #if HAVE_DVB_API_VERSION < 3
2085 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2087 return ::ioctl(m_fd, FE_SET_TONE, tone);
2091 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2092 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2095 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2097 #if HAVE_DVB_API_VERSION < 3
2098 struct secCommand cmd;
2099 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2100 cmd.u.diseqc.cmdtype = diseqc.data[0];
2101 cmd.u.diseqc.addr = diseqc.data[1];
2102 cmd.u.diseqc.cmd = diseqc.data[2];
2103 cmd.u.diseqc.numParams = diseqc.len-3;
2104 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2105 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2107 struct dvb_diseqc_master_cmd cmd;
2108 memcpy(cmd.msg, diseqc.data, diseqc.len);
2109 cmd.msg_len = diseqc.len;
2110 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2116 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2117 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2119 RESULT eDVBFrontend::sendToneburst(int burst)
2121 #if HAVE_DVB_API_VERSION < 3
2122 secMiniCmd cmd = SEC_MINI_NONE;
2124 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2126 if ( burst == eDVBSatelliteDiseqcParameters::A )
2128 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2130 #if HAVE_DVB_API_VERSION < 3
2131 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2134 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2140 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2146 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2148 m_sec_sequence = list;
2152 RESULT eDVBFrontend::getData(int num, long &data)
2154 if ( num < NUM_DATA_ENTRIES )
2162 RESULT eDVBFrontend::setData(int num, long val)
2164 if ( num < NUM_DATA_ENTRIES )
2172 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2175 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2178 if (m_type == eDVBFrontend::feSatellite)
2181 eDVBFrontendParametersSatellite sat_parm;
2182 int ret = feparm->getDVBS(sat_parm);
2184 return m_sec->canTune(sat_parm, this, 1 << m_slotid);
2186 else if (m_type == eDVBFrontend::feCable)
2187 return 2; // more prio for cable frontends
2191 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2193 ePyObject Id, Descr, Enabled;
2194 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 3)
2196 Id = PyTuple_GET_ITEM(obj, 0);
2197 Descr = PyTuple_GET_ITEM(obj, 1);
2198 Enabled = PyTuple_GET_ITEM(obj, 2);
2199 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled))
2201 strcpy(m_description, PyString_AS_STRING(Descr));
2202 m_slotid = PyInt_AsLong(Id);
2203 m_enabled = Enabled == Py_True;
2204 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2205 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2206 !!strstr(m_description, "Alps BSBE2") ||
2207 !!strstr(m_description, "Alps -S");
2208 eDebug("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s",
2209 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No" );
2212 PyErr_SetString(PyExc_StandardError,
2213 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");