1 #include <lib/dvb/dvb.h>
2 #include <lib/base/eerror.h>
3 #include <lib/base/nconfig.h> // access to python config
9 #ifndef I2C_SLAVE_FORCE
10 #define I2C_SLAVE_FORCE 0x0706
13 #if HAVE_DVB_API_VERSION < 3
14 #include <ost/frontend.h>
16 #define QAM_AUTO (Modulation)6
17 #define TRANSMISSION_MODE_AUTO (TransmitMode)2
18 #define BANDWIDTH_AUTO (BandWidth)3
19 #define GUARD_INTERVAL_AUTO (GuardInterval)4
20 #define HIERARCHY_AUTO (Hierarchy)4
21 #define parm_frequency parm.Frequency
22 #define parm_inversion parm.Inversion
23 #define parm_u_qpsk_symbol_rate parm.u.qpsk.SymbolRate
24 #define parm_u_qpsk_fec_inner parm.u.qpsk.FEC_inner
25 #define parm_u_qam_symbol_rate parm.u.qam.SymbolRate
26 #define parm_u_qam_fec_inner parm.u.qam.FEC_inner
27 #define parm_u_qam_modulation parm.u.qam.QAM
28 #define parm_u_ofdm_bandwidth parm.u.ofdm.bandWidth
29 #define parm_u_ofdm_code_rate_LP parm.u.ofdm.LP_CodeRate
30 #define parm_u_ofdm_code_rate_HP parm.u.ofdm.HP_CodeRate
31 #define parm_u_ofdm_constellation parm.u.ofdm.Constellation
32 #define parm_u_ofdm_transmission_mode parm.u.ofdm.TransmissionMode
33 #define parm_u_ofdm_guard_interval parm.u.ofdm.guardInterval
34 #define parm_u_ofdm_hierarchy_information parm.u.ofdm.HierarchyInformation
36 #include <linux/dvb/frontend.h>
37 #define parm_frequency parm.frequency
38 #define parm_inversion parm.inversion
39 #define parm_u_qpsk_symbol_rate parm.u.qpsk.symbol_rate
40 #define parm_u_qpsk_fec_inner parm.u.qpsk.fec_inner
41 #define parm_u_qam_symbol_rate parm.u.qam.symbol_rate
42 #define parm_u_qam_fec_inner parm.u.qam.fec_inner
43 #define parm_u_qam_modulation parm.u.qam.modulation
44 #define parm_u_ofdm_bandwidth parm.u.ofdm.bandwidth
45 #define parm_u_ofdm_code_rate_LP parm.u.ofdm.code_rate_LP
46 #define parm_u_ofdm_code_rate_HP parm.u.ofdm.code_rate_HP
47 #define parm_u_ofdm_constellation parm.u.ofdm.constellation
48 #define parm_u_ofdm_transmission_mode parm.u.ofdm.transmission_mode
49 #define parm_u_ofdm_guard_interval parm.u.ofdm.guard_interval
50 #define parm_u_ofdm_hierarchy_information parm.u.ofdm.hierarchy_information
52 #warning "FEC_9_10 already exist in dvb api ... it seems it is now ready for DVB-S2"
54 #define FEC_S2_QPSK_1_2 (fe_code_rate_t)(FEC_AUTO+1)
55 #define FEC_S2_QPSK_2_3 (fe_code_rate_t)(FEC_S2_QPSK_1_2+1)
56 #define FEC_S2_QPSK_3_4 (fe_code_rate_t)(FEC_S2_QPSK_2_3+1)
57 #define FEC_S2_QPSK_5_6 (fe_code_rate_t)(FEC_S2_QPSK_3_4+1)
58 #define FEC_S2_QPSK_7_8 (fe_code_rate_t)(FEC_S2_QPSK_5_6+1)
59 #define FEC_S2_QPSK_8_9 (fe_code_rate_t)(FEC_S2_QPSK_7_8+1)
60 #define FEC_S2_QPSK_3_5 (fe_code_rate_t)(FEC_S2_QPSK_8_9+1)
61 #define FEC_S2_QPSK_4_5 (fe_code_rate_t)(FEC_S2_QPSK_3_5+1)
62 #define FEC_S2_QPSK_9_10 (fe_code_rate_t)(FEC_S2_QPSK_4_5+1)
63 #define FEC_S2_8PSK_1_2 (fe_code_rate_t)(FEC_S2_QPSK_9_10+1)
64 #define FEC_S2_8PSK_2_3 (fe_code_rate_t)(FEC_S2_8PSK_1_2+1)
65 #define FEC_S2_8PSK_3_4 (fe_code_rate_t)(FEC_S2_8PSK_2_3+1)
66 #define FEC_S2_8PSK_5_6 (fe_code_rate_t)(FEC_S2_8PSK_3_4+1)
67 #define FEC_S2_8PSK_7_8 (fe_code_rate_t)(FEC_S2_8PSK_5_6+1)
68 #define FEC_S2_8PSK_8_9 (fe_code_rate_t)(FEC_S2_8PSK_7_8+1)
69 #define FEC_S2_8PSK_3_5 (fe_code_rate_t)(FEC_S2_8PSK_8_9+1)
70 #define FEC_S2_8PSK_4_5 (fe_code_rate_t)(FEC_S2_8PSK_3_5+1)
71 #define FEC_S2_8PSK_9_10 (fe_code_rate_t)(FEC_S2_8PSK_4_5+1)
75 #include <dvbsi++/satellite_delivery_system_descriptor.h>
76 #include <dvbsi++/cable_delivery_system_descriptor.h>
77 #include <dvbsi++/terrestrial_delivery_system_descriptor.h>
79 void eDVBDiseqcCommand::setCommandString(const char *str)
84 int slen = strlen(str);
87 eDebug("invalid diseqc command string length (not 2 byte aligned)");
90 if (slen > MAX_DISEQC_LENGTH*2)
92 eDebug("invalid diseqc command string length (string is to long)");
96 for (int i=0; i < slen; ++i)
98 unsigned char c = str[i];
101 case '0' ... '9': c-=48; break;
102 case 'a' ... 'f': c-=87; break;
103 case 'A' ... 'F': c-=55; break;
105 eDebug("invalid character in hex string..ignore complete diseqc command !");
119 void eDVBFrontendParametersSatellite::set(const SatelliteDeliverySystemDescriptor &descriptor)
121 frequency = descriptor.getFrequency() * 10;
122 symbol_rate = descriptor.getSymbolRate() * 100;
123 polarisation = descriptor.getPolarization();
124 fec = descriptor.getFecInner();
125 if ( fec != FEC::fNone && fec > FEC::f9_10 )
127 inversion = Inversion::Unknown;
128 pilot = Pilot::Unknown;
129 orbital_position = ((descriptor.getOrbitalPosition() >> 12) & 0xF) * 1000;
130 orbital_position += ((descriptor.getOrbitalPosition() >> 8) & 0xF) * 100;
131 orbital_position += ((descriptor.getOrbitalPosition() >> 4) & 0xF) * 10;
132 orbital_position += ((descriptor.getOrbitalPosition()) & 0xF);
133 if (orbital_position && (!descriptor.getWestEastFlag()))
134 orbital_position = 3600 - orbital_position;
135 system = descriptor.getModulationSystem();
136 modulation = descriptor.getModulation();
137 if (system == System::DVB_S && modulation == Modulation::M8PSK)
139 eDebug("satellite_delivery_descriptor non valid modulation type.. force QPSK");
142 rolloff = descriptor.getRollOff();
143 if (system == System::DVB_S2)
145 eDebug("SAT DVB-S2 freq %d, %s, pos %d, sr %d, fec %d, modulation %d, rolloff %d",
147 polarisation ? "hor" : "vert",
155 eDebug("SAT DVB-S freq %d, %s, pos %d, sr %d, fec %d",
157 polarisation ? "hor" : "vert",
163 void eDVBFrontendParametersCable::set(const CableDeliverySystemDescriptor &descriptor)
165 frequency = descriptor.getFrequency() / 10;
166 symbol_rate = descriptor.getSymbolRate() * 100;
167 fec_inner = descriptor.getFecInner();
168 if ( fec_inner == 0xF )
169 fec_inner = FEC::fNone;
170 modulation = descriptor.getModulation();
171 if ( modulation > 0x5 )
172 modulation = Modulation::Auto;
173 inversion = Inversion::Unknown;
174 eDebug("Cable freq %d, mod %d, sr %d, fec %d",
176 modulation, symbol_rate, fec_inner);
179 void eDVBFrontendParametersTerrestrial::set(const TerrestrialDeliverySystemDescriptor &descriptor)
181 frequency = descriptor.getCentreFrequency() * 10;
182 bandwidth = descriptor.getBandwidth();
183 if ( bandwidth > 2 ) // 5Mhz forced to auto
184 bandwidth = Bandwidth::BwAuto;
185 code_rate_HP = descriptor.getCodeRateHpStream();
186 if (code_rate_HP > 4)
187 code_rate_HP = FEC::fAuto;
188 code_rate_LP = descriptor.getCodeRateLpStream();
189 if (code_rate_LP > 4)
190 code_rate_LP = FEC::fAuto;
191 transmission_mode = descriptor.getTransmissionMode();
192 if (transmission_mode > 1) // TM4k forced to auto
193 transmission_mode = TransmissionMode::TMAuto;
194 guard_interval = descriptor.getGuardInterval();
195 if (guard_interval > 3)
196 guard_interval = GuardInterval::GI_Auto;
197 hierarchy = descriptor.getHierarchyInformation()&3;
198 modulation = descriptor.getConstellation();
200 modulation = Modulation::Auto;
201 inversion = Inversion::Unknown;
202 eDebug("Terr freq %d, bw %d, cr_hp %d, cr_lp %d, tm_mode %d, guard %d, hierarchy %d, const %d",
203 frequency, bandwidth, code_rate_HP, code_rate_LP, transmission_mode,
204 guard_interval, hierarchy, modulation);
207 eDVBFrontendParameters::eDVBFrontendParameters(): m_type(-1)
211 DEFINE_REF(eDVBFrontendParameters);
213 RESULT eDVBFrontendParameters::getSystem(int &t) const
221 RESULT eDVBFrontendParameters::getDVBS(eDVBFrontendParametersSatellite &p) const
223 if (m_type != iDVBFrontend::feSatellite)
229 RESULT eDVBFrontendParameters::getDVBC(eDVBFrontendParametersCable &p) const
231 if (m_type != iDVBFrontend::feCable)
237 RESULT eDVBFrontendParameters::getDVBT(eDVBFrontendParametersTerrestrial &p) const
239 if (m_type != iDVBFrontend::feTerrestrial)
245 RESULT eDVBFrontendParameters::setDVBS(const eDVBFrontendParametersSatellite &p, bool no_rotor_command_on_tune)
248 sat.no_rotor_command_on_tune = no_rotor_command_on_tune;
249 m_type = iDVBFrontend::feSatellite;
253 RESULT eDVBFrontendParameters::setDVBC(const eDVBFrontendParametersCable &p)
256 m_type = iDVBFrontend::feCable;
260 RESULT eDVBFrontendParameters::setDVBT(const eDVBFrontendParametersTerrestrial &p)
263 m_type = iDVBFrontend::feTerrestrial;
267 RESULT eDVBFrontendParameters::calculateDifference(const iDVBFrontendParameters *parm, int &diff, bool exact) const
272 if (parm->getSystem(type))
276 diff = 1<<30; // big difference
282 case iDVBFrontend::feSatellite:
284 eDVBFrontendParametersSatellite osat;
285 if (parm->getDVBS(osat))
288 if (sat.orbital_position != osat.orbital_position)
290 else if (sat.polarisation != osat.polarisation)
292 else if (exact && sat.fec != osat.fec && sat.fec != eDVBFrontendParametersSatellite::FEC::fAuto && osat.fec != eDVBFrontendParametersSatellite::FEC::fAuto)
294 else if (exact && sat.modulation != osat.modulation && sat.modulation != eDVBFrontendParametersSatellite::Modulation::Auto && osat.modulation != eDVBFrontendParametersSatellite::Modulation::Auto)
298 diff = abs(sat.frequency - osat.frequency);
299 diff += abs(sat.symbol_rate - osat.symbol_rate);
303 case iDVBFrontend::feCable:
304 eDVBFrontendParametersCable ocable;
305 if (parm->getDVBC(ocable))
308 if (exact && cable.modulation != ocable.modulation
309 && cable.modulation != eDVBFrontendParametersCable::Modulation::Auto
310 && ocable.modulation != eDVBFrontendParametersCable::Modulation::Auto)
312 else if (exact && cable.fec_inner != ocable.fec_inner && cable.fec_inner != eDVBFrontendParametersCable::FEC::fAuto && ocable.fec_inner != eDVBFrontendParametersCable::FEC::fAuto)
316 diff = abs(cable.frequency - ocable.frequency);
317 diff += abs(cable.symbol_rate - ocable.symbol_rate);
320 case iDVBFrontend::feTerrestrial:
321 eDVBFrontendParametersTerrestrial oterrestrial;
322 if (parm->getDVBT(oterrestrial))
326 if (exact && oterrestrial.bandwidth != terrestrial.bandwidth &&
327 oterrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto &&
328 terrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto)
330 else if (exact && oterrestrial.modulation != terrestrial.modulation &&
331 oterrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation::Auto &&
332 terrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation::Auto)
334 else if (exact && oterrestrial.transmission_mode != terrestrial.transmission_mode &&
335 oterrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto &&
336 terrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto)
338 else if (exact && oterrestrial.guard_interval != terrestrial.guard_interval &&
339 oterrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto &&
340 terrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto)
342 else if (exact && oterrestrial.hierarchy != terrestrial.hierarchy &&
343 oterrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy::HAuto &&
344 terrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy::HAuto)
346 else if (exact && oterrestrial.code_rate_LP != terrestrial.code_rate_LP &&
347 oterrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC::fAuto &&
348 terrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC::fAuto)
350 else if (exact && oterrestrial.code_rate_HP != terrestrial.code_rate_HP &&
351 oterrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC::fAuto &&
352 terrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC::fAuto)
355 diff = abs(terrestrial.frequency - oterrestrial.frequency);
363 RESULT eDVBFrontendParameters::getHash(unsigned long &hash) const
367 case iDVBFrontend::feSatellite:
369 hash = (sat.orbital_position << 16);
370 hash |= ((sat.frequency/1000)&0xFFFF)|((sat.polarisation&1) << 15);
373 case iDVBFrontend::feCable:
375 hash |= (cable.frequency/1000)&0xFFFF;
377 case iDVBFrontend::feTerrestrial:
379 hash |= (terrestrial.frequency/1000)&0xFFFF;
386 RESULT eDVBFrontendParameters::calcLockTimeout(unsigned int &timeout) const
390 case iDVBFrontend::feSatellite:
392 /* high symbol rate transponders tune faster, due to
393 requiring less zigzag and giving more symbols faster.
395 5s are definitely not enough on really low SR when
396 zigzag has to find the exact frequency first.
398 if (sat.symbol_rate > 20000000)
400 else if (sat.symbol_rate > 10000000)
406 case iDVBFrontend::feCable:
409 case iDVBFrontend::feTerrestrial:
417 DEFINE_REF(eDVBFrontend);
419 int eDVBFrontend::PriorityOrder=0;
421 eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok)
422 :m_enabled(false), m_type(-1), m_dvbid(fe), m_slotid(fe)
423 ,m_fd(-1), m_need_rotor_workaround(false), m_can_handle_dvbs2(false)
424 ,m_sn(0), m_timeout(0), m_tuneTimer(0)
425 #if HAVE_DVB_API_VERSION < 3
429 #if HAVE_DVB_API_VERSION < 3
430 sprintf(m_filename, "/dev/dvb/card%d/frontend%d", adap, fe);
431 sprintf(m_sec_filename, "/dev/dvb/card%d/sec%d", adap, fe);
433 sprintf(m_filename, "/dev/dvb/adapter%d/frontend%d", adap, fe);
435 m_timeout = new eTimer(eApp);
436 CONNECT(m_timeout->timeout, eDVBFrontend::timeout);
438 m_tuneTimer = new eTimer(eApp);
439 CONNECT(m_tuneTimer->timeout, eDVBFrontend::tuneLoop);
441 for (int i=0; i<eDVBFrontend::NUM_DATA_ENTRIES; ++i)
444 m_idleInputpower[0]=m_idleInputpower[1]=0;
446 ok = !openFrontend();
450 int eDVBFrontend::openFrontend()
453 return -1; // already opened
458 #if HAVE_DVB_API_VERSION < 3
459 FrontendInfo fe_info;
461 dvb_frontend_info fe_info;
463 eDebug("opening frontend %d", m_dvbid);
466 m_fd = ::open(m_filename, O_RDWR|O_NONBLOCK);
469 eWarning("failed! (%s) %m", m_filename);
474 eWarning("frontend %d already opened", m_dvbid);
477 if (::ioctl(m_fd, FE_GET_INFO, &fe_info) < 0)
479 eWarning("ioctl FE_GET_INFO failed");
485 switch (fe_info.type)
488 m_type = iDVBFrontend::feSatellite;
491 m_type = iDVBFrontend::feCable;
494 m_type = iDVBFrontend::feTerrestrial;
497 eWarning("unknown frontend type.");
502 eDebug("detected %s frontend", "satellite\0cable\0 terrestrial"+fe_info.type*10);
505 #if HAVE_DVB_API_VERSION < 3
506 if (m_type == iDVBFrontend::feSatellite)
510 m_secfd = ::open(m_sec_filename, O_RDWR);
513 eWarning("failed! (%s) %m", m_sec_filename);
520 eWarning("sec %d already opened", m_dvbid);
524 setTone(iDVBFrontend::toneOff);
525 setVoltage(iDVBFrontend::voltageOff);
527 m_sn = new eSocketNotifier(eApp, m_fd, eSocketNotifier::Read, false);
528 CONNECT(m_sn->activated, eDVBFrontend::feEvent);
533 int eDVBFrontend::closeFrontend(bool force)
535 if (!force && m_data[CUR_VOLTAGE] != -1 && m_data[CUR_VOLTAGE] != iDVBFrontend::voltageOff)
537 long tmp = m_data[LINKED_NEXT_PTR];
540 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
541 if (linked_fe->m_inuse)
543 eDebug("dont close frontend %d until the linked frontend %d in slot %d is still in use",
544 m_dvbid, linked_fe->m_frontend->getDVBID(), linked_fe->m_frontend->getSlotID());
547 linked_fe->m_frontend->getData(LINKED_NEXT_PTR, tmp);
552 eDebug("close frontend %d", m_dvbid);
554 setTone(iDVBFrontend::toneOff);
555 setVoltage(iDVBFrontend::voltageOff);
557 m_sec->setRotorMoving(false);
561 eWarning("couldnt close frontend %d", m_dvbid);
562 m_data[CSW] = m_data[UCSW] = m_data[TONEBURST] = -1;
564 #if HAVE_DVB_API_VERSION < 3
567 if (!::close(m_secfd))
570 eWarning("couldnt close sec %d", m_dvbid);
575 m_state = stateClosed;
580 eDVBFrontend::~eDVBFrontend()
582 m_data[LINKED_PREV_PTR] = m_data[LINKED_NEXT_PTR] = -1;
588 void eDVBFrontend::feEvent(int w)
592 #if HAVE_DVB_API_VERSION < 3
595 dvb_frontend_event event;
599 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
601 if (res && (errno == EAGAIN))
606 eWarning("FE_GET_EVENT failed! %m");
613 #if HAVE_DVB_API_VERSION < 3
614 if (event.type == FE_COMPLETION_EV)
616 eDebug("(%d)fe event: status %x, inversion %s", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off");
617 if (event.status & FE_HAS_LOCK)
627 eDebug("stateLostLock");
628 state = stateLostLock;
629 m_data[CSW] = m_data[UCSW] = m_data[TONEBURST] = -1; // reset diseqc
632 if (m_state != state)
635 m_stateChanged(this);
640 void eDVBFrontend::timeout()
643 if (m_state == stateTuning)
645 m_state = stateFailed;
646 m_stateChanged(this);
650 int eDVBFrontend::readFrontendData(int type)
657 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
658 eDebug("FE_READ_BER failed (%m)");
664 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
665 eDebug("FE_READ_SNR failed (%m)");
668 case signalQualitydB: /* this will move into the driver */
671 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
672 eDebug("FE_READ_SNR failed (%m)");
673 if (!strcmp(m_description, "BCM4501 (internal)"))
675 unsigned int SDS_SNRE = snr << 16;
677 static float SNR_COEFF[6] = {
680 197418.0 / 4194304.0,
681 -2602183.0 / 4194304.0,
682 20377212.0 / 4194304.0,
683 -37791203.0 / 4194304.0,
686 float fval1, fval2, snr_in_db;
688 fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0));
689 fval2 = pow(10.0, fval1)-1;
690 fval1 = 10.0 * log10(fval2);
694 fval2 = SNR_COEFF[0];
698 fval2 += SNR_COEFF[i];
704 return (int)(snr_in_db * 100.0);
706 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
707 !strcmp(m_description, "Alps -S") ||
708 !strcmp(m_description, "Philips -S") ||
709 !strcmp(m_description, "LG -S") )
711 float snr_in_db=(snr-39075)/1764.7;
712 return (int)(snr_in_db * 100.0);
713 } else if (!strcmp(m_description, "Alps BSBE2"))
715 return (int)((snr >> 7) * 10.0);
717 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
723 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
724 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
729 #if HAVE_DVB_API_VERSION < 3
730 FrontendStatus status=0;
734 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
735 eDebug("FE_READ_STATUS failed (%m)");
736 return !!(status&FE_HAS_LOCK);
740 #if HAVE_DVB_API_VERSION < 3
741 FrontendStatus status=0;
745 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
746 eDebug("FE_READ_STATUS failed (%m)");
747 return !!(status&FE_HAS_SYNC);
755 void PutToDict(ePyObject &dict, const char*key, long value)
757 ePyObject item = PyInt_FromLong(value);
760 if (PyDict_SetItemString(dict, key, item))
761 eDebug("put %s to dict failed", key);
765 eDebug("could not create PyObject for %s", key);
768 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
772 if (PyDict_SetItemString(dict, key, item))
773 eDebug("put %s to dict failed", key);
777 eDebug("invalid PyObject for %s", key);
780 void PutToDict(ePyObject &dict, const char*key, const char *value)
782 ePyObject item = PyString_FromString(value);
785 if (PyDict_SetItemString(dict, key, item))
786 eDebug("put %s to dict failed", key);
790 eDebug("could not create PyObject for %s", key);
793 void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, eDVBFrontend *fe)
798 fe->getData(eDVBFrontend::CSW, csw);
799 fe->getData(eDVBFrontend::FREQ_OFFSET, freq_offset);
800 int frequency = parm_frequency + freq_offset;
801 PutToDict(dict, "frequency", frequency);
802 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
803 switch(parm_u_qpsk_fec_inner)
826 #if HAVE_DVB_API_VERSION >=3
827 case FEC_S2_8PSK_1_2:
828 case FEC_S2_QPSK_1_2:
831 case FEC_S2_8PSK_2_3:
832 case FEC_S2_QPSK_2_3:
835 case FEC_S2_8PSK_3_4:
836 case FEC_S2_QPSK_3_4:
839 case FEC_S2_8PSK_5_6:
840 case FEC_S2_QPSK_5_6:
843 case FEC_S2_8PSK_7_8:
844 case FEC_S2_QPSK_7_8:
847 case FEC_S2_8PSK_8_9:
848 case FEC_S2_QPSK_8_9:
851 case FEC_S2_8PSK_3_5:
852 case FEC_S2_QPSK_3_5:
855 case FEC_S2_8PSK_4_5:
856 case FEC_S2_QPSK_4_5:
859 case FEC_S2_8PSK_9_10:
860 case FEC_S2_QPSK_9_10:
865 PutToDict(dict, "fec_inner", tmp);
866 #if HAVE_DVB_API_VERSION >=3
867 PutToDict(dict, "modulation",
868 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ? "8PSK": "QPSK" );
869 if (parm_u_qpsk_fec_inner > FEC_AUTO)
871 switch(parm_inversion & 0xc)
873 default: // unknown rolloff
875 tmp = "ROLLOFF_0_35";
878 tmp = "ROLLOFF_0_25";
881 tmp = "ROLLOFF_0_20";
884 PutToDict(dict, "rolloff", tmp);
885 if (parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10)
887 switch(parm_inversion & 0x30)
892 case 0x10: // pilot on
895 case 0x20: // pilot auto
899 PutToDict(dict, "pilot", tmp);
906 PutToDict(dict, "modulation", "QPSK" );
909 PutToDict(dict, "system", tmp);
912 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
915 #if HAVE_DVB_API_VERSION < 3
916 PutToDict(dict, "frequency", parm_frequency);
918 PutToDict(dict, "frequency", parm_frequency/1000);
920 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
921 switch(parm_u_qam_fec_inner)
941 #if HAVE_DVB_API_VERSION >= 3
951 PutToDict(dict, "fec_inner", tmp);
952 switch(parm_u_qam_modulation)
974 PutToDict(dict, "modulation", tmp);
977 void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
980 PutToDict(dict, "frequency", parm_frequency);
981 switch (parm_u_ofdm_bandwidth)
983 case BANDWIDTH_8_MHZ:
984 tmp = "BANDWIDTH_8_MHZ";
986 case BANDWIDTH_7_MHZ:
987 tmp = "BANDWIDTH_7_MHZ";
989 case BANDWIDTH_6_MHZ:
990 tmp = "BANDWIDTH_6_MHZ";
994 tmp = "BANDWIDTH_AUTO";
997 PutToDict(dict, "bandwidth", tmp);
998 switch (parm_u_ofdm_code_rate_LP)
1020 PutToDict(dict, "code_rate_lp", tmp);
1021 switch (parm_u_ofdm_code_rate_HP)
1043 PutToDict(dict, "code_rate_hp", tmp);
1044 switch (parm_u_ofdm_constellation)
1060 PutToDict(dict, "constellation", tmp);
1061 switch (parm_u_ofdm_transmission_mode)
1063 case TRANSMISSION_MODE_2K:
1064 tmp = "TRANSMISSION_MODE_2K";
1066 case TRANSMISSION_MODE_8K:
1067 tmp = "TRANSMISSION_MODE_8K";
1070 case TRANSMISSION_MODE_AUTO:
1071 tmp = "TRANSMISSION_MODE_AUTO";
1074 PutToDict(dict, "transmission_mode", tmp);
1075 switch (parm_u_ofdm_guard_interval)
1077 case GUARD_INTERVAL_1_32:
1078 tmp = "GUARD_INTERVAL_1_32";
1080 case GUARD_INTERVAL_1_16:
1081 tmp = "GUARD_INTERVAL_1_16";
1083 case GUARD_INTERVAL_1_8:
1084 tmp = "GUARD_INTERVAL_1_8";
1086 case GUARD_INTERVAL_1_4:
1087 tmp = "GUARD_INTERVAL_1_4";
1090 case GUARD_INTERVAL_AUTO:
1091 tmp = "GUARD_INTERVAL_AUTO";
1094 PutToDict(dict, "guard_interval", tmp);
1095 switch (parm_u_ofdm_hierarchy_information)
1097 case HIERARCHY_NONE:
1098 tmp = "HIERARCHY_NONE";
1101 tmp = "HIERARCHY_1";
1104 tmp = "HIERARCHY_2";
1107 tmp = "HIERARCHY_4";
1110 case HIERARCHY_AUTO:
1111 tmp = "HIERARCHY_AUTO";
1114 PutToDict(dict, "hierarchy_information", tmp);
1117 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1119 if (dest && PyDict_Check(dest))
1121 const char *tmp = "UNKNOWN";
1142 PutToDict(dest, "tuner_state", tmp);
1143 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1144 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1145 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1146 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1147 int sigQualitydB = readFrontendData(signalQualitydB);
1148 if (sigQualitydB == 0x12345678) // not support yet
1150 ePyObject obj=Py_None;
1152 PutToDict(dest, "tuner_signal_quality_db", obj);
1155 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1156 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1160 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1162 if (m_fd != -1 && dest && PyDict_Check(dest))
1170 FRONTENDPARAMETERS front;
1171 if (!original && ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1172 eDebug("FE_GET_FRONTEND (%m)");
1175 const FRONTENDPARAMETERS &parm = original ? this->parm : front;
1176 const char *tmp = "INVERSION_AUTO";
1177 switch(parm_inversion)
1180 tmp = "INVERSION_ON";
1183 tmp = "INVERSION_OFF";
1189 PutToDict(dest, "inversion", tmp);
1194 fillDictWithSatelliteData(dest, original?parm:front, this);
1197 fillDictWithCableData(dest, original?parm:front);
1200 fillDictWithTerrestrialData(dest, original?parm:front);
1211 void eDVBFrontend::getFrontendData(ePyObject dest)
1213 if (dest && PyDict_Check(dest))
1216 PutToDict(dest, "tuner_number", m_slotid);
1232 PutToDict(dest, "tuner_type", tmp);
1236 #ifndef FP_IOCTL_GET_ID
1237 #define FP_IOCTL_GET_ID 0
1239 int eDVBFrontend::readInputpower()
1241 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1243 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1244 FILE *f=fopen(proc_name, "r");
1247 if (fscanf(f, "%08x", &power) != 1)
1248 eDebug("read %s failed!! (%m)", proc_name);
1250 eDebug("%s is %d\n", proc_name, power);
1255 // open front prozessor
1256 int fp=::open("/dev/dbox/fp0", O_RDWR);
1259 eDebug("couldn't open fp");
1262 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1263 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1265 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1274 bool eDVBFrontend::setSecSequencePos(int steps)
1276 eDebug("set sequence pos %d", steps);
1281 if (m_sec_sequence.current() != m_sec_sequence.end())
1282 ++m_sec_sequence.current();
1287 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1288 --m_sec_sequence.current();
1294 void eDVBFrontend::setRotorData(int pos, int cmd)
1296 m_data[ROTOR_CMD] = cmd;
1297 m_data[ROTOR_POS] = pos;
1298 if ( m_data[SATPOS_DEPENDS_PTR] != -1 )
1300 eDVBRegisteredFrontend *satpos_depends_to_fe = (eDVBRegisteredFrontend*) m_data[SATPOS_DEPENDS_PTR];
1301 satpos_depends_to_fe->m_frontend->m_data[ROTOR_CMD] = cmd;
1302 satpos_depends_to_fe->m_frontend->m_data[ROTOR_POS] = pos;
1306 eDVBRegisteredFrontend *next = (eDVBRegisteredFrontend *)m_data[LINKED_NEXT_PTR];
1307 while ( (long)next != -1 )
1309 next->m_frontend->m_data[ROTOR_CMD] = cmd;
1310 next->m_frontend->m_data[ROTOR_POS] = pos;
1311 next = (eDVBRegisteredFrontend *)next->m_frontend->m_data[LINKED_NEXT_PTR];
1313 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)m_data[LINKED_PREV_PTR];
1314 while ( (long)prev != -1 )
1316 prev->m_frontend->m_data[ROTOR_CMD] = cmd;
1317 prev->m_frontend->m_data[ROTOR_POS] = pos;
1318 prev = (eDVBRegisteredFrontend *)prev->m_frontend->m_data[LINKED_PREV_PTR];
1323 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1326 eDVBFrontend *fe = this;
1327 eDVBRegisteredFrontend *regFE = 0;
1328 long tmp = m_data[LINKED_PREV_PTR];
1331 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1332 fe = prev->m_frontend;
1333 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1334 if (tmp == -1 && fe != this && !prev->m_inuse) {
1335 int state = fe->m_state;
1336 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1338 fe->closeFrontend(true);
1339 state = fe->m_state;
1341 if (state == eDVBFrontend::stateClosed)
1349 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1351 long *m_data = fe->m_data;
1352 // eDebug("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1353 switch (m_sec_sequence.current()->cmd)
1355 case eSecCommand::SLEEP:
1356 delay = m_sec_sequence.current()++->msec;
1357 eDebug("[SEC] sleep %dms", delay);
1359 case eSecCommand::GOTO:
1360 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1361 ++m_sec_sequence.current();
1363 case eSecCommand::SET_VOLTAGE:
1365 int voltage = m_sec_sequence.current()++->voltage;
1366 eDebug("[SEC] setVoltage %d", voltage);
1367 fe->setVoltage(voltage);
1370 case eSecCommand::IF_VOLTAGE_GOTO:
1372 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1373 if ( compare.voltage == m_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1375 ++m_sec_sequence.current();
1378 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1380 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1381 if ( compare.voltage != m_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1383 ++m_sec_sequence.current();
1386 case eSecCommand::IF_TONE_GOTO:
1388 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1389 if ( compare.tone == m_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1391 ++m_sec_sequence.current();
1394 case eSecCommand::IF_NOT_TONE_GOTO:
1396 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1397 if ( compare.tone != m_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1399 ++m_sec_sequence.current();
1402 case eSecCommand::SET_TONE:
1403 eDebug("[SEC] setTone %d", m_sec_sequence.current()->tone);
1404 fe->setTone(m_sec_sequence.current()++->tone);
1406 case eSecCommand::SEND_DISEQC:
1407 fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1408 eDebugNoNewLine("[SEC] sendDiseqc: ");
1409 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1410 eDebugNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1412 ++m_sec_sequence.current();
1414 case eSecCommand::SEND_TONEBURST:
1415 eDebug("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1416 fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1418 case eSecCommand::SET_FRONTEND:
1419 eDebug("[SEC] setFrontend");
1421 ++m_sec_sequence.current();
1423 case eSecCommand::START_TUNE_TIMEOUT:
1425 m_timeout->start(m_sec_sequence.current()->timeout, 1);
1426 ++m_sec_sequence.current();
1429 case eSecCommand::SET_TIMEOUT:
1430 m_timeoutCount = m_sec_sequence.current()++->val;
1431 eDebug("[SEC] set timeout %d", m_timeoutCount);
1433 case eSecCommand::IF_TIMEOUT_GOTO:
1434 if (!m_timeoutCount)
1436 eDebug("[SEC] rotor timout");
1437 m_sec->setRotorMoving(false);
1438 setSecSequencePos(m_sec_sequence.current()->steps);
1441 ++m_sec_sequence.current();
1443 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1445 int idx = m_sec_sequence.current()++->val;
1446 if ( idx == 0 || idx == 1 )
1448 m_idleInputpower[idx] = fe->readInputpower();
1449 eDebug("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1452 eDebug("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1455 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1457 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1458 int idx = compare.val;
1459 if ( idx == 0 || idx == 1 )
1461 int idle = fe->readInputpower();
1462 int diff = abs(idle-m_idleInputpower[idx]);
1465 eDebug("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1466 setSecSequencePos(compare.steps);
1470 ++m_sec_sequence.current();
1473 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1475 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1476 if (readFrontendData(locked))
1478 eDebug("[SEC] locked step %d ok", cmd.okcount);
1480 if (cmd.okcount > 12)
1482 eDebug("ok > 12 .. goto %d\n",m_sec_sequence.current()->steps);
1483 setSecSequencePos(cmd.steps);
1489 eDebug("[SEC] rotor locked step %d failed", cmd.okcount);
1491 if (!m_timeoutCount && m_retryCount > 0)
1495 ++m_sec_sequence.current();
1498 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1499 m_runningInputpower = fe->readInputpower();
1500 eDebug("[SEC] runningInputpower is %d", m_runningInputpower);
1501 ++m_sec_sequence.current();
1503 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1505 int idleInputpower = m_idleInputpower[ (m_data[CUR_VOLTAGE]&1) ? 0 : 1];
1506 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1507 const char *txt = cmd.direction ? "running" : "stopped";
1508 eDebug("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1510 m_runningInputpower,
1513 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1514 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1517 eDebug("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1518 if ( cmd.okcount > 6 )
1520 m_sec->setRotorMoving(cmd.direction);
1521 eDebug("[SEC] rotor is %s", txt);
1522 if (setSecSequencePos(cmd.steps))
1528 eDebug("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1530 if (!m_timeoutCount && m_retryCount > 0)
1534 ++m_sec_sequence.current();
1537 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1538 if (m_data[ROTOR_CMD] != -1 && m_data[ROTOR_POS] != -1)
1539 setSecSequencePos(m_sec_sequence.current()->steps);
1541 ++m_sec_sequence.current();
1543 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1544 eDebug("[SEC] invalidate current rotorparams");
1545 fe->setRotorData(-1,-1);
1546 ++m_sec_sequence.current();
1548 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1549 fe->setRotorData(m_data[NEW_ROTOR_POS], m_data[NEW_ROTOR_CMD]);
1550 eDebug("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, m_data[ROTOR_CMD], m_data[ROTOR_POS]);
1551 ++m_sec_sequence.current();
1553 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1554 m_retryCount = m_sec_sequence.current()++->val;
1555 eDebug("[SEC] set rotor retries %d", m_retryCount);
1557 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1560 eDebug("[SEC] no more rotor retrys");
1561 setSecSequencePos(m_sec_sequence.current()->steps);
1564 ++m_sec_sequence.current();
1566 case eSecCommand::SET_POWER_LIMITING_MODE:
1569 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", fe->m_dvbid);
1570 FILE *f=fopen(proc_name, "w");
1571 if (f) // new interface exist?
1573 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1574 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1575 eDebug("write %s failed!! (%m)", proc_name);
1577 eDebug("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1580 else if (fe->m_need_rotor_workaround)
1583 int slotid = fe->m_slotid;
1584 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1586 sprintf(dev, "/dev/i2c/%d", slotid);
1587 else if (slotid == 2)
1588 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1589 else if (slotid == 3)
1590 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1591 int fd = ::open(dev, O_RDWR);
1593 unsigned char data[2];
1594 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1595 if(::read(fd, data, 1) != 1)
1596 eDebug("[SEC] error read lnbp (%m)");
1597 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1599 data[0] |= 0x80; // enable static current limiting
1600 eDebug("[SEC] set static current limiting");
1604 data[0] &= ~0x80; // enable dynamic current limiting
1605 eDebug("[SEC] set dynamic current limiting");
1607 if(::write(fd, data, 1) != 1)
1608 eDebug("[SEC] error write lnbp (%m)");
1611 ++m_sec_sequence.current();
1615 eDebug("[SEC] unhandled sec command %d",
1616 ++m_sec_sequence.current()->cmd);
1617 ++m_sec_sequence.current();
1619 m_tuneTimer->start(delay,true);
1625 void eDVBFrontend::setFrontend()
1627 eDebug("setting frontend %d", m_dvbid);
1630 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1632 perror("FE_SET_FRONTEND failed");
1637 RESULT eDVBFrontend::getFrontendType(int &t)
1645 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1650 eWarning("no SEC module active!");
1653 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1656 eDebug("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1659 feparm.polarisation,
1663 feparm.orbital_position);
1664 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1665 switch (feparm.inversion)
1667 case eDVBFrontendParametersSatellite::Inversion::On:
1668 parm_inversion = INVERSION_ON;
1670 case eDVBFrontendParametersSatellite::Inversion::Off:
1671 parm_inversion = INVERSION_OFF;
1674 case eDVBFrontendParametersSatellite::Inversion::Unknown:
1675 parm_inversion = INVERSION_AUTO;
1678 if (feparm.system == eDVBFrontendParametersSatellite::System::DVB_S)
1681 case eDVBFrontendParametersSatellite::FEC::fNone:
1682 parm_u_qpsk_fec_inner = FEC_NONE;
1684 case eDVBFrontendParametersSatellite::FEC::f1_2:
1685 parm_u_qpsk_fec_inner = FEC_1_2;
1687 case eDVBFrontendParametersSatellite::FEC::f2_3:
1688 parm_u_qpsk_fec_inner = FEC_2_3;
1690 case eDVBFrontendParametersSatellite::FEC::f3_4:
1691 parm_u_qpsk_fec_inner = FEC_3_4;
1693 case eDVBFrontendParametersSatellite::FEC::f5_6:
1694 parm_u_qpsk_fec_inner = FEC_5_6;
1696 case eDVBFrontendParametersSatellite::FEC::f7_8:
1697 parm_u_qpsk_fec_inner = FEC_7_8;
1700 eDebug("no valid fec for DVB-S set.. assume auto");
1701 case eDVBFrontendParametersSatellite::FEC::fAuto:
1702 parm_u_qpsk_fec_inner = FEC_AUTO;
1705 #if HAVE_DVB_API_VERSION >= 3
1710 case eDVBFrontendParametersSatellite::FEC::f1_2:
1711 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1713 case eDVBFrontendParametersSatellite::FEC::f2_3:
1714 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1716 case eDVBFrontendParametersSatellite::FEC::f3_4:
1717 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1719 case eDVBFrontendParametersSatellite::FEC::f3_5:
1720 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1722 case eDVBFrontendParametersSatellite::FEC::f4_5:
1723 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1725 case eDVBFrontendParametersSatellite::FEC::f5_6:
1726 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1728 case eDVBFrontendParametersSatellite::FEC::f7_8:
1729 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1731 case eDVBFrontendParametersSatellite::FEC::f8_9:
1732 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1734 case eDVBFrontendParametersSatellite::FEC::f9_10:
1735 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1738 eDebug("no valid fec for DVB-S2 set.. abort !!");
1741 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1742 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK) {
1743 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1744 // 8PSK fec driver values are decimal 9 bigger
1745 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1749 // FIXME !!! get frequency range from tuner
1750 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1752 eDebug("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1755 eDebug("tuning to %d mhz", parm_frequency/1000);
1760 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1762 #if HAVE_DVB_API_VERSION < 3
1763 parm_frequency = feparm.frequency;
1765 parm_frequency = feparm.frequency * 1000;
1767 parm_u_qam_symbol_rate = feparm.symbol_rate;
1768 switch (feparm.modulation)
1770 case eDVBFrontendParametersCable::Modulation::QAM16:
1771 parm_u_qam_modulation = QAM_16;
1773 case eDVBFrontendParametersCable::Modulation::QAM32:
1774 parm_u_qam_modulation = QAM_32;
1776 case eDVBFrontendParametersCable::Modulation::QAM64:
1777 parm_u_qam_modulation = QAM_64;
1779 case eDVBFrontendParametersCable::Modulation::QAM128:
1780 parm_u_qam_modulation = QAM_128;
1782 case eDVBFrontendParametersCable::Modulation::QAM256:
1783 parm_u_qam_modulation = QAM_256;
1786 case eDVBFrontendParametersCable::Modulation::Auto:
1787 parm_u_qam_modulation = QAM_AUTO;
1790 switch (feparm.inversion)
1792 case eDVBFrontendParametersCable::Inversion::On:
1793 parm_inversion = INVERSION_ON;
1795 case eDVBFrontendParametersCable::Inversion::Off:
1796 parm_inversion = INVERSION_OFF;
1799 case eDVBFrontendParametersCable::Inversion::Unknown:
1800 parm_inversion = INVERSION_AUTO;
1803 switch (feparm.fec_inner)
1805 case eDVBFrontendParametersCable::FEC::fNone:
1806 parm_u_qam_fec_inner = FEC_NONE;
1808 case eDVBFrontendParametersCable::FEC::f1_2:
1809 parm_u_qam_fec_inner = FEC_1_2;
1811 case eDVBFrontendParametersCable::FEC::f2_3:
1812 parm_u_qam_fec_inner = FEC_2_3;
1814 case eDVBFrontendParametersCable::FEC::f3_4:
1815 parm_u_qam_fec_inner = FEC_3_4;
1817 case eDVBFrontendParametersCable::FEC::f5_6:
1818 parm_u_qam_fec_inner = FEC_5_6;
1820 case eDVBFrontendParametersCable::FEC::f7_8:
1821 parm_u_qam_fec_inner = FEC_7_8;
1823 #if HAVE_DVB_API_VERSION >= 3
1824 case eDVBFrontendParametersCable::FEC::f8_9:
1825 parm_u_qam_fec_inner = FEC_8_9;
1829 case eDVBFrontendParametersCable::FEC::fAuto:
1830 parm_u_qam_fec_inner = FEC_AUTO;
1833 eDebug("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
1834 parm_frequency/1000,
1835 parm_u_qam_symbol_rate,
1836 parm_u_qam_fec_inner,
1837 parm_u_qam_modulation,
1842 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
1844 parm_frequency = feparm.frequency;
1846 switch (feparm.bandwidth)
1848 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
1849 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
1851 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
1852 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
1854 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
1855 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
1858 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
1859 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
1862 switch (feparm.code_rate_LP)
1864 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1865 parm_u_ofdm_code_rate_LP = FEC_1_2;
1867 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1868 parm_u_ofdm_code_rate_LP = FEC_2_3;
1870 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1871 parm_u_ofdm_code_rate_LP = FEC_3_4;
1873 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1874 parm_u_ofdm_code_rate_LP = FEC_5_6;
1876 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1877 parm_u_ofdm_code_rate_LP = FEC_7_8;
1880 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1881 parm_u_ofdm_code_rate_LP = FEC_AUTO;
1884 switch (feparm.code_rate_HP)
1886 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1887 parm_u_ofdm_code_rate_HP = FEC_1_2;
1889 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1890 parm_u_ofdm_code_rate_HP = FEC_2_3;
1892 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1893 parm_u_ofdm_code_rate_HP = FEC_3_4;
1895 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1896 parm_u_ofdm_code_rate_HP = FEC_5_6;
1898 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1899 parm_u_ofdm_code_rate_HP = FEC_7_8;
1902 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1903 parm_u_ofdm_code_rate_HP = FEC_AUTO;
1906 switch (feparm.modulation)
1908 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
1909 parm_u_ofdm_constellation = QPSK;
1911 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
1912 parm_u_ofdm_constellation = QAM_16;
1914 case eDVBFrontendParametersTerrestrial::Modulation::QAM64:
1915 parm_u_ofdm_constellation = QAM_64;
1918 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
1919 parm_u_ofdm_constellation = QAM_AUTO;
1922 switch (feparm.transmission_mode)
1924 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
1925 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
1927 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
1928 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
1931 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
1932 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
1935 switch (feparm.guard_interval)
1937 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32:
1938 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
1940 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16:
1941 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
1943 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8:
1944 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
1946 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4:
1947 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
1950 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto:
1951 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
1954 switch (feparm.hierarchy)
1956 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone:
1957 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
1959 case eDVBFrontendParametersTerrestrial::Hierarchy::H1:
1960 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
1962 case eDVBFrontendParametersTerrestrial::Hierarchy::H2:
1963 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
1965 case eDVBFrontendParametersTerrestrial::Hierarchy::H4:
1966 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
1969 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto:
1970 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
1973 switch (feparm.inversion)
1975 case eDVBFrontendParametersTerrestrial::Inversion::On:
1976 parm_inversion = INVERSION_ON;
1978 case eDVBFrontendParametersTerrestrial::Inversion::Off:
1979 parm_inversion = INVERSION_OFF;
1982 case eDVBFrontendParametersTerrestrial::Inversion::Unknown:
1983 parm_inversion = INVERSION_AUTO;
1989 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
1991 unsigned int timeout = 5000;
1992 eDebug("(%d)tune", m_dvbid);
2000 eDebug("no frontend device opened... do not try to tune !!!");
2012 m_sec_sequence.clear();
2014 where.calcLockTimeout(timeout);
2020 eDVBFrontendParametersSatellite feparm;
2021 if (where.getDVBS(feparm))
2023 eDebug("no dvbs data!");
2027 m_sec->setRotorMoving(false);
2028 res=prepare_sat(feparm, timeout);
2036 eDVBFrontendParametersCable feparm;
2037 if (where.getDVBC(feparm))
2042 res=prepare_cable(feparm);
2046 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2047 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2052 eDVBFrontendParametersTerrestrial feparm;
2053 if (where.getDVBT(feparm))
2055 eDebug("no -T data");
2059 res=prepare_terrestrial(feparm);
2063 std::string enable_5V;
2064 char configStr[255];
2065 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2066 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2067 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2068 if (enable_5V == "True")
2069 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2071 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2072 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2078 m_tuneTimer->start(0,true);
2079 m_sec_sequence.current() = m_sec_sequence.begin();
2081 if (m_state != stateTuning)
2084 m_state = stateTuning;
2085 m_stateChanged(this);
2091 m_tuneTimer->stop();
2095 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2097 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2101 RESULT eDVBFrontend::setVoltage(int voltage)
2103 if (m_type == feCable)
2105 #if HAVE_DVB_API_VERSION < 3
2108 bool increased=false;
2109 fe_sec_voltage_t vlt;
2111 m_data[CUR_VOLTAGE]=voltage;
2115 for (int i=0; i < 3; ++i) // reset diseqc
2117 vlt = SEC_VOLTAGE_OFF;
2120 #if HAVE_DVB_API_VERSION < 3
2121 vlt = SEC_VOLTAGE_13_5;
2127 vlt = SEC_VOLTAGE_13;
2130 #if HAVE_DVB_API_VERSION < 3
2131 vlt = SEC_VOLTAGE_18_5;
2137 vlt = SEC_VOLTAGE_18;
2142 #if HAVE_DVB_API_VERSION < 3
2143 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2145 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2146 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2147 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2151 RESULT eDVBFrontend::getState(int &state)
2157 RESULT eDVBFrontend::setTone(int t)
2159 if (m_type != feSatellite)
2161 #if HAVE_DVB_API_VERSION < 3
2164 fe_sec_tone_mode_t tone;
2173 tone = SEC_TONE_OFF;
2178 #if HAVE_DVB_API_VERSION < 3
2179 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2181 return ::ioctl(m_fd, FE_SET_TONE, tone);
2185 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2186 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2189 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2191 #if HAVE_DVB_API_VERSION < 3
2192 struct secCommand cmd;
2193 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2194 cmd.u.diseqc.cmdtype = diseqc.data[0];
2195 cmd.u.diseqc.addr = diseqc.data[1];
2196 cmd.u.diseqc.cmd = diseqc.data[2];
2197 cmd.u.diseqc.numParams = diseqc.len-3;
2198 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2199 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2201 struct dvb_diseqc_master_cmd cmd;
2202 memcpy(cmd.msg, diseqc.data, diseqc.len);
2203 cmd.msg_len = diseqc.len;
2204 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2210 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2211 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2213 RESULT eDVBFrontend::sendToneburst(int burst)
2215 #if HAVE_DVB_API_VERSION < 3
2216 secMiniCmd cmd = SEC_MINI_NONE;
2218 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2220 if ( burst == eDVBSatelliteDiseqcParameters::A )
2222 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2224 #if HAVE_DVB_API_VERSION < 3
2225 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2228 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2234 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2240 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2242 m_sec_sequence = list;
2246 RESULT eDVBFrontend::getData(int num, long &data)
2248 if ( num < NUM_DATA_ENTRIES )
2256 RESULT eDVBFrontend::setData(int num, long val)
2258 if ( num < NUM_DATA_ENTRIES )
2266 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2269 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2271 if (m_type == eDVBFrontend::feSatellite)
2274 eDVBFrontendParametersSatellite sat_parm;
2275 int ret = feparm->getDVBS(sat_parm);
2277 if (sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S2 && !m_can_handle_dvbs2)
2279 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2280 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S && m_can_handle_dvbs2)
2284 else if (m_type == eDVBFrontend::feCable)
2285 return 2; // more prio for cable frontends
2286 else if (m_type == eDVBFrontend::feTerrestrial)
2291 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2293 ePyObject Id, Descr, Enabled;
2294 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 3)
2296 Id = PyTuple_GET_ITEM(obj, 0);
2297 Descr = PyTuple_GET_ITEM(obj, 1);
2298 Enabled = PyTuple_GET_ITEM(obj, 2);
2299 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled))
2301 strcpy(m_description, PyString_AS_STRING(Descr));
2302 m_slotid = PyInt_AsLong(Id);
2303 m_enabled = Enabled == Py_True;
2304 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2305 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2306 !!strstr(m_description, "Alps BSBE2") ||
2307 !!strstr(m_description, "Alps -S") ||
2308 !!strstr(m_description, "BCM4501");
2309 m_can_handle_dvbs2 = !!strstr(m_description, "Alps BSBE2") || !!strstr(m_description, "BCM4501");
2310 eDebug("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2311 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2314 PyErr_SetString(PyExc_StandardError,
2315 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");