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 eDVBFrontend *sec_fe = this;
628 long tmp = m_data[LINKED_PREV_PTR];
630 eDebug("stateLostLock");
631 state = stateLostLock;
635 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
636 sec_fe = linked_fe->m_frontend;
637 sec_fe->getData(LINKED_NEXT_PTR, tmp);
639 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
642 if (m_state != state)
645 m_stateChanged(this);
650 void eDVBFrontend::timeout()
653 if (m_state == stateTuning)
655 m_state = stateFailed;
656 m_stateChanged(this);
660 int eDVBFrontend::readFrontendData(int type)
667 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
668 eDebug("FE_READ_BER failed (%m)");
674 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
675 eDebug("FE_READ_SNR failed (%m)");
678 case signalQualitydB: /* this will move into the driver */
681 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
682 eDebug("FE_READ_SNR failed (%m)");
683 if (!strcmp(m_description, "BCM4501 (internal)"))
685 unsigned int SDS_SNRE = snr << 16;
687 static float SNR_COEFF[6] = {
690 197418.0 / 4194304.0,
691 -2602183.0 / 4194304.0,
692 20377212.0 / 4194304.0,
693 -37791203.0 / 4194304.0,
696 float fval1, fval2, snr_in_db;
698 fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0));
699 fval2 = pow(10.0, fval1)-1;
700 fval1 = 10.0 * log10(fval2);
704 fval2 = SNR_COEFF[0];
708 fval2 += SNR_COEFF[i];
714 return (int)(snr_in_db * 100.0);
716 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
717 !strcmp(m_description, "Alps -S") ||
718 !strcmp(m_description, "Philips -S") ||
719 !strcmp(m_description, "LG -S") )
721 float snr_in_db=(snr-39075)/1764.7;
722 return (int)(snr_in_db * 100.0);
723 } else if (!strcmp(m_description, "Alps BSBE2"))
725 return (int)((snr >> 7) * 10.0);
727 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
733 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
734 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
739 #if HAVE_DVB_API_VERSION < 3
740 FrontendStatus status=0;
744 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
745 eDebug("FE_READ_STATUS failed (%m)");
746 return !!(status&FE_HAS_LOCK);
750 #if HAVE_DVB_API_VERSION < 3
751 FrontendStatus status=0;
755 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
756 eDebug("FE_READ_STATUS failed (%m)");
757 return !!(status&FE_HAS_SYNC);
765 void PutToDict(ePyObject &dict, const char*key, long value)
767 ePyObject item = PyInt_FromLong(value);
770 if (PyDict_SetItemString(dict, key, item))
771 eDebug("put %s to dict failed", key);
775 eDebug("could not create PyObject for %s", key);
778 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
782 if (PyDict_SetItemString(dict, key, item))
783 eDebug("put %s to dict failed", key);
787 eDebug("invalid PyObject for %s", key);
790 void PutToDict(ePyObject &dict, const char*key, const char *value)
792 ePyObject item = PyString_FromString(value);
795 if (PyDict_SetItemString(dict, key, item))
796 eDebug("put %s to dict failed", key);
800 eDebug("could not create PyObject for %s", key);
803 void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, eDVBFrontend *fe)
807 fe->getData(eDVBFrontend::FREQ_OFFSET, freq_offset);
808 int frequency = parm_frequency + freq_offset;
809 PutToDict(dict, "frequency", frequency);
810 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
811 switch(parm_u_qpsk_fec_inner)
834 #if HAVE_DVB_API_VERSION >=3
835 case FEC_S2_8PSK_1_2:
836 case FEC_S2_QPSK_1_2:
839 case FEC_S2_8PSK_2_3:
840 case FEC_S2_QPSK_2_3:
843 case FEC_S2_8PSK_3_4:
844 case FEC_S2_QPSK_3_4:
847 case FEC_S2_8PSK_5_6:
848 case FEC_S2_QPSK_5_6:
851 case FEC_S2_8PSK_7_8:
852 case FEC_S2_QPSK_7_8:
855 case FEC_S2_8PSK_8_9:
856 case FEC_S2_QPSK_8_9:
859 case FEC_S2_8PSK_3_5:
860 case FEC_S2_QPSK_3_5:
863 case FEC_S2_8PSK_4_5:
864 case FEC_S2_QPSK_4_5:
867 case FEC_S2_8PSK_9_10:
868 case FEC_S2_QPSK_9_10:
873 PutToDict(dict, "fec_inner", tmp);
874 #if HAVE_DVB_API_VERSION >=3
875 PutToDict(dict, "modulation",
876 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ? "8PSK": "QPSK" );
877 if (parm_u_qpsk_fec_inner > FEC_AUTO)
879 switch(parm_inversion & 0xc)
881 default: // unknown rolloff
883 tmp = "ROLLOFF_0_35";
886 tmp = "ROLLOFF_0_25";
889 tmp = "ROLLOFF_0_20";
892 PutToDict(dict, "rolloff", tmp);
893 if (parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10)
895 switch(parm_inversion & 0x30)
900 case 0x10: // pilot on
903 case 0x20: // pilot auto
907 PutToDict(dict, "pilot", tmp);
914 PutToDict(dict, "modulation", "QPSK" );
917 PutToDict(dict, "system", tmp);
920 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
923 #if HAVE_DVB_API_VERSION < 3
924 PutToDict(dict, "frequency", parm_frequency);
926 PutToDict(dict, "frequency", parm_frequency/1000);
928 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
929 switch(parm_u_qam_fec_inner)
949 #if HAVE_DVB_API_VERSION >= 3
959 PutToDict(dict, "fec_inner", tmp);
960 switch(parm_u_qam_modulation)
982 PutToDict(dict, "modulation", tmp);
985 void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
988 PutToDict(dict, "frequency", parm_frequency);
989 switch (parm_u_ofdm_bandwidth)
991 case BANDWIDTH_8_MHZ:
992 tmp = "BANDWIDTH_8_MHZ";
994 case BANDWIDTH_7_MHZ:
995 tmp = "BANDWIDTH_7_MHZ";
997 case BANDWIDTH_6_MHZ:
998 tmp = "BANDWIDTH_6_MHZ";
1001 case BANDWIDTH_AUTO:
1002 tmp = "BANDWIDTH_AUTO";
1005 PutToDict(dict, "bandwidth", tmp);
1006 switch (parm_u_ofdm_code_rate_LP)
1028 PutToDict(dict, "code_rate_lp", tmp);
1029 switch (parm_u_ofdm_code_rate_HP)
1051 PutToDict(dict, "code_rate_hp", tmp);
1052 switch (parm_u_ofdm_constellation)
1068 PutToDict(dict, "constellation", tmp);
1069 switch (parm_u_ofdm_transmission_mode)
1071 case TRANSMISSION_MODE_2K:
1072 tmp = "TRANSMISSION_MODE_2K";
1074 case TRANSMISSION_MODE_8K:
1075 tmp = "TRANSMISSION_MODE_8K";
1078 case TRANSMISSION_MODE_AUTO:
1079 tmp = "TRANSMISSION_MODE_AUTO";
1082 PutToDict(dict, "transmission_mode", tmp);
1083 switch (parm_u_ofdm_guard_interval)
1085 case GUARD_INTERVAL_1_32:
1086 tmp = "GUARD_INTERVAL_1_32";
1088 case GUARD_INTERVAL_1_16:
1089 tmp = "GUARD_INTERVAL_1_16";
1091 case GUARD_INTERVAL_1_8:
1092 tmp = "GUARD_INTERVAL_1_8";
1094 case GUARD_INTERVAL_1_4:
1095 tmp = "GUARD_INTERVAL_1_4";
1098 case GUARD_INTERVAL_AUTO:
1099 tmp = "GUARD_INTERVAL_AUTO";
1102 PutToDict(dict, "guard_interval", tmp);
1103 switch (parm_u_ofdm_hierarchy_information)
1105 case HIERARCHY_NONE:
1106 tmp = "HIERARCHY_NONE";
1109 tmp = "HIERARCHY_1";
1112 tmp = "HIERARCHY_2";
1115 tmp = "HIERARCHY_4";
1118 case HIERARCHY_AUTO:
1119 tmp = "HIERARCHY_AUTO";
1122 PutToDict(dict, "hierarchy_information", tmp);
1125 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1127 if (dest && PyDict_Check(dest))
1129 const char *tmp = "UNKNOWN";
1150 PutToDict(dest, "tuner_state", tmp);
1151 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1152 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1153 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1154 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1155 int sigQualitydB = readFrontendData(signalQualitydB);
1156 if (sigQualitydB == 0x12345678) // not support yet
1158 ePyObject obj=Py_None;
1160 PutToDict(dest, "tuner_signal_quality_db", obj);
1163 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1164 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1168 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1170 if (m_fd != -1 && dest && PyDict_Check(dest))
1178 FRONTENDPARAMETERS front;
1179 if (!original && ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1180 eDebug("FE_GET_FRONTEND (%m)");
1183 const FRONTENDPARAMETERS &parm = original ? this->parm : front;
1184 const char *tmp = "INVERSION_AUTO";
1185 switch(parm_inversion)
1188 tmp = "INVERSION_ON";
1191 tmp = "INVERSION_OFF";
1197 PutToDict(dest, "inversion", tmp);
1202 fillDictWithSatelliteData(dest, original?parm:front, this);
1205 fillDictWithCableData(dest, original?parm:front);
1208 fillDictWithTerrestrialData(dest, original?parm:front);
1219 void eDVBFrontend::getFrontendData(ePyObject dest)
1221 if (dest && PyDict_Check(dest))
1224 PutToDict(dest, "tuner_number", m_slotid);
1240 PutToDict(dest, "tuner_type", tmp);
1244 #ifndef FP_IOCTL_GET_ID
1245 #define FP_IOCTL_GET_ID 0
1247 int eDVBFrontend::readInputpower()
1249 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1251 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1252 FILE *f=fopen(proc_name, "r");
1255 if (fscanf(f, "%d", &power) != 1)
1256 eDebug("read %s failed!! (%m)", proc_name);
1258 eDebug("%s is %d\n", proc_name, power);
1263 // open front prozessor
1264 int fp=::open("/dev/dbox/fp0", O_RDWR);
1267 eDebug("couldn't open fp");
1270 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1271 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1273 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1282 bool eDVBFrontend::setSecSequencePos(int steps)
1284 eDebug("set sequence pos %d", steps);
1289 if (m_sec_sequence.current() != m_sec_sequence.end())
1290 ++m_sec_sequence.current();
1295 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1296 --m_sec_sequence.current();
1302 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1305 eDVBFrontend *sec_fe = this;
1306 eDVBRegisteredFrontend *regFE = 0;
1307 long tmp = m_data[LINKED_PREV_PTR];
1310 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1311 sec_fe = prev->m_frontend;
1312 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1313 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1314 int state = sec_fe->m_state;
1315 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1317 sec_fe->closeFrontend(true);
1318 state = sec_fe->m_state;
1320 if (state == eDVBFrontend::stateClosed)
1328 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1330 long *sec_fe_data = sec_fe->m_data;
1331 // eDebug("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1332 switch (m_sec_sequence.current()->cmd)
1334 case eSecCommand::SLEEP:
1335 delay = m_sec_sequence.current()++->msec;
1336 eDebug("[SEC] sleep %dms", delay);
1338 case eSecCommand::GOTO:
1339 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1340 ++m_sec_sequence.current();
1342 case eSecCommand::SET_VOLTAGE:
1344 int voltage = m_sec_sequence.current()++->voltage;
1345 eDebug("[SEC] setVoltage %d", voltage);
1346 sec_fe->setVoltage(voltage);
1349 case eSecCommand::IF_VOLTAGE_GOTO:
1351 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1352 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1354 ++m_sec_sequence.current();
1357 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1359 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1360 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1362 ++m_sec_sequence.current();
1365 case eSecCommand::IF_TONE_GOTO:
1367 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1368 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1370 ++m_sec_sequence.current();
1373 case eSecCommand::IF_NOT_TONE_GOTO:
1375 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1376 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1378 ++m_sec_sequence.current();
1381 case eSecCommand::SET_TONE:
1382 eDebug("[SEC] setTone %d", m_sec_sequence.current()->tone);
1383 sec_fe->setTone(m_sec_sequence.current()++->tone);
1385 case eSecCommand::SEND_DISEQC:
1386 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1387 eDebugNoNewLine("[SEC] sendDiseqc: ");
1388 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1389 eDebugNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1391 ++m_sec_sequence.current();
1393 case eSecCommand::SEND_TONEBURST:
1394 eDebug("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1395 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1397 case eSecCommand::SET_FRONTEND:
1398 eDebug("[SEC] setFrontend");
1400 ++m_sec_sequence.current();
1402 case eSecCommand::START_TUNE_TIMEOUT:
1404 m_timeout->start(m_sec_sequence.current()->timeout, 1);
1405 ++m_sec_sequence.current();
1408 case eSecCommand::SET_TIMEOUT:
1409 m_timeoutCount = m_sec_sequence.current()++->val;
1410 eDebug("[SEC] set timeout %d", m_timeoutCount);
1412 case eSecCommand::IF_TIMEOUT_GOTO:
1413 if (!m_timeoutCount)
1415 eDebug("[SEC] rotor timout");
1416 m_sec->setRotorMoving(false);
1417 setSecSequencePos(m_sec_sequence.current()->steps);
1420 ++m_sec_sequence.current();
1422 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1424 int idx = m_sec_sequence.current()++->val;
1425 if ( idx == 0 || idx == 1 )
1427 m_idleInputpower[idx] = sec_fe->readInputpower();
1428 eDebug("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1431 eDebug("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1434 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1436 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1437 int idx = compare.val;
1438 if ( idx == 0 || idx == 1 )
1440 int idle = sec_fe->readInputpower();
1441 int diff = abs(idle-m_idleInputpower[idx]);
1444 eDebug("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1445 setSecSequencePos(compare.steps);
1449 ++m_sec_sequence.current();
1452 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1454 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1455 if (readFrontendData(locked))
1457 eDebug("[SEC] locked step %d ok", cmd.okcount);
1459 if (cmd.okcount > 12)
1461 eDebug("ok > 12 .. goto %d\n",m_sec_sequence.current()->steps);
1462 setSecSequencePos(cmd.steps);
1468 eDebug("[SEC] rotor locked step %d failed", cmd.okcount);
1470 if (!m_timeoutCount && m_retryCount > 0)
1474 ++m_sec_sequence.current();
1477 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1478 m_runningInputpower = sec_fe->readInputpower();
1479 eDebug("[SEC] runningInputpower is %d", m_runningInputpower);
1480 ++m_sec_sequence.current();
1482 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1484 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1485 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1486 const char *txt = cmd.direction ? "running" : "stopped";
1487 eDebug("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1489 m_runningInputpower,
1492 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1493 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1496 eDebug("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1497 if ( cmd.okcount > 6 )
1499 m_sec->setRotorMoving(cmd.direction);
1500 eDebug("[SEC] rotor is %s", txt);
1501 if (setSecSequencePos(cmd.steps))
1507 eDebug("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1509 if (!m_timeoutCount && m_retryCount > 0)
1513 ++m_sec_sequence.current();
1516 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1517 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1518 setSecSequencePos(m_sec_sequence.current()->steps);
1520 ++m_sec_sequence.current();
1522 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1523 eDebug("[SEC] invalidate current rotorparams");
1524 sec_fe_data[ROTOR_CMD] = -1;
1525 sec_fe_data[ROTOR_POS] = -1;
1526 ++m_sec_sequence.current();
1528 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1529 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1530 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1531 eDebug("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1532 ++m_sec_sequence.current();
1534 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1535 m_retryCount = m_sec_sequence.current()++->val;
1536 eDebug("[SEC] set rotor retries %d", m_retryCount);
1538 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1541 eDebug("[SEC] no more rotor retrys");
1542 setSecSequencePos(m_sec_sequence.current()->steps);
1545 ++m_sec_sequence.current();
1547 case eSecCommand::SET_POWER_LIMITING_MODE:
1550 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1551 FILE *f=fopen(proc_name, "w");
1552 if (f) // new interface exist?
1554 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1555 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1556 eDebug("write %s failed!! (%m)", proc_name);
1558 eDebug("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1561 else if (sec_fe->m_need_rotor_workaround)
1564 int slotid = sec_fe->m_slotid;
1565 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1567 sprintf(dev, "/dev/i2c/%d", slotid);
1568 else if (slotid == 2)
1569 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1570 else if (slotid == 3)
1571 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1572 int fd = ::open(dev, O_RDWR);
1574 unsigned char data[2];
1575 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1576 if(::read(fd, data, 1) != 1)
1577 eDebug("[SEC] error read lnbp (%m)");
1578 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1580 data[0] |= 0x80; // enable static current limiting
1581 eDebug("[SEC] set static current limiting");
1585 data[0] &= ~0x80; // enable dynamic current limiting
1586 eDebug("[SEC] set dynamic current limiting");
1588 if(::write(fd, data, 1) != 1)
1589 eDebug("[SEC] error write lnbp (%m)");
1592 ++m_sec_sequence.current();
1596 eDebug("[SEC] unhandled sec command %d",
1597 ++m_sec_sequence.current()->cmd);
1598 ++m_sec_sequence.current();
1600 m_tuneTimer->start(delay,true);
1606 void eDVBFrontend::setFrontend()
1608 eDebug("setting frontend %d", m_dvbid);
1611 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1613 perror("FE_SET_FRONTEND failed");
1618 RESULT eDVBFrontend::getFrontendType(int &t)
1626 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1631 eWarning("no SEC module active!");
1634 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1637 eDebug("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1640 feparm.polarisation,
1644 feparm.orbital_position);
1645 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1646 switch (feparm.inversion)
1648 case eDVBFrontendParametersSatellite::Inversion::On:
1649 parm_inversion = INVERSION_ON;
1651 case eDVBFrontendParametersSatellite::Inversion::Off:
1652 parm_inversion = INVERSION_OFF;
1655 case eDVBFrontendParametersSatellite::Inversion::Unknown:
1656 parm_inversion = INVERSION_AUTO;
1659 if (feparm.system == eDVBFrontendParametersSatellite::System::DVB_S)
1662 case eDVBFrontendParametersSatellite::FEC::fNone:
1663 parm_u_qpsk_fec_inner = FEC_NONE;
1665 case eDVBFrontendParametersSatellite::FEC::f1_2:
1666 parm_u_qpsk_fec_inner = FEC_1_2;
1668 case eDVBFrontendParametersSatellite::FEC::f2_3:
1669 parm_u_qpsk_fec_inner = FEC_2_3;
1671 case eDVBFrontendParametersSatellite::FEC::f3_4:
1672 parm_u_qpsk_fec_inner = FEC_3_4;
1674 case eDVBFrontendParametersSatellite::FEC::f5_6:
1675 parm_u_qpsk_fec_inner = FEC_5_6;
1677 case eDVBFrontendParametersSatellite::FEC::f7_8:
1678 parm_u_qpsk_fec_inner = FEC_7_8;
1681 eDebug("no valid fec for DVB-S set.. assume auto");
1682 case eDVBFrontendParametersSatellite::FEC::fAuto:
1683 parm_u_qpsk_fec_inner = FEC_AUTO;
1686 #if HAVE_DVB_API_VERSION >= 3
1691 case eDVBFrontendParametersSatellite::FEC::f1_2:
1692 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1694 case eDVBFrontendParametersSatellite::FEC::f2_3:
1695 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1697 case eDVBFrontendParametersSatellite::FEC::f3_4:
1698 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1700 case eDVBFrontendParametersSatellite::FEC::f3_5:
1701 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1703 case eDVBFrontendParametersSatellite::FEC::f4_5:
1704 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1706 case eDVBFrontendParametersSatellite::FEC::f5_6:
1707 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1709 case eDVBFrontendParametersSatellite::FEC::f7_8:
1710 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1712 case eDVBFrontendParametersSatellite::FEC::f8_9:
1713 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1715 case eDVBFrontendParametersSatellite::FEC::f9_10:
1716 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1719 eDebug("no valid fec for DVB-S2 set.. abort !!");
1722 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1723 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK) {
1724 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1725 // 8PSK fec driver values are decimal 9 bigger
1726 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1730 // FIXME !!! get frequency range from tuner
1731 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1733 eDebug("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1736 eDebug("tuning to %d mhz", parm_frequency/1000);
1741 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1743 #if HAVE_DVB_API_VERSION < 3
1744 parm_frequency = feparm.frequency;
1746 parm_frequency = feparm.frequency * 1000;
1748 parm_u_qam_symbol_rate = feparm.symbol_rate;
1749 switch (feparm.modulation)
1751 case eDVBFrontendParametersCable::Modulation::QAM16:
1752 parm_u_qam_modulation = QAM_16;
1754 case eDVBFrontendParametersCable::Modulation::QAM32:
1755 parm_u_qam_modulation = QAM_32;
1757 case eDVBFrontendParametersCable::Modulation::QAM64:
1758 parm_u_qam_modulation = QAM_64;
1760 case eDVBFrontendParametersCable::Modulation::QAM128:
1761 parm_u_qam_modulation = QAM_128;
1763 case eDVBFrontendParametersCable::Modulation::QAM256:
1764 parm_u_qam_modulation = QAM_256;
1767 case eDVBFrontendParametersCable::Modulation::Auto:
1768 parm_u_qam_modulation = QAM_AUTO;
1771 switch (feparm.inversion)
1773 case eDVBFrontendParametersCable::Inversion::On:
1774 parm_inversion = INVERSION_ON;
1776 case eDVBFrontendParametersCable::Inversion::Off:
1777 parm_inversion = INVERSION_OFF;
1780 case eDVBFrontendParametersCable::Inversion::Unknown:
1781 parm_inversion = INVERSION_AUTO;
1784 switch (feparm.fec_inner)
1786 case eDVBFrontendParametersCable::FEC::fNone:
1787 parm_u_qam_fec_inner = FEC_NONE;
1789 case eDVBFrontendParametersCable::FEC::f1_2:
1790 parm_u_qam_fec_inner = FEC_1_2;
1792 case eDVBFrontendParametersCable::FEC::f2_3:
1793 parm_u_qam_fec_inner = FEC_2_3;
1795 case eDVBFrontendParametersCable::FEC::f3_4:
1796 parm_u_qam_fec_inner = FEC_3_4;
1798 case eDVBFrontendParametersCable::FEC::f5_6:
1799 parm_u_qam_fec_inner = FEC_5_6;
1801 case eDVBFrontendParametersCable::FEC::f7_8:
1802 parm_u_qam_fec_inner = FEC_7_8;
1804 #if HAVE_DVB_API_VERSION >= 3
1805 case eDVBFrontendParametersCable::FEC::f8_9:
1806 parm_u_qam_fec_inner = FEC_8_9;
1810 case eDVBFrontendParametersCable::FEC::fAuto:
1811 parm_u_qam_fec_inner = FEC_AUTO;
1814 eDebug("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
1815 parm_frequency/1000,
1816 parm_u_qam_symbol_rate,
1817 parm_u_qam_fec_inner,
1818 parm_u_qam_modulation,
1823 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
1825 parm_frequency = feparm.frequency;
1827 switch (feparm.bandwidth)
1829 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
1830 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
1832 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
1833 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
1835 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
1836 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
1839 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
1840 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
1843 switch (feparm.code_rate_LP)
1845 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1846 parm_u_ofdm_code_rate_LP = FEC_1_2;
1848 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1849 parm_u_ofdm_code_rate_LP = FEC_2_3;
1851 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1852 parm_u_ofdm_code_rate_LP = FEC_3_4;
1854 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1855 parm_u_ofdm_code_rate_LP = FEC_5_6;
1857 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1858 parm_u_ofdm_code_rate_LP = FEC_7_8;
1861 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1862 parm_u_ofdm_code_rate_LP = FEC_AUTO;
1865 switch (feparm.code_rate_HP)
1867 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1868 parm_u_ofdm_code_rate_HP = FEC_1_2;
1870 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1871 parm_u_ofdm_code_rate_HP = FEC_2_3;
1873 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1874 parm_u_ofdm_code_rate_HP = FEC_3_4;
1876 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1877 parm_u_ofdm_code_rate_HP = FEC_5_6;
1879 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1880 parm_u_ofdm_code_rate_HP = FEC_7_8;
1883 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1884 parm_u_ofdm_code_rate_HP = FEC_AUTO;
1887 switch (feparm.modulation)
1889 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
1890 parm_u_ofdm_constellation = QPSK;
1892 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
1893 parm_u_ofdm_constellation = QAM_16;
1895 case eDVBFrontendParametersTerrestrial::Modulation::QAM64:
1896 parm_u_ofdm_constellation = QAM_64;
1899 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
1900 parm_u_ofdm_constellation = QAM_AUTO;
1903 switch (feparm.transmission_mode)
1905 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
1906 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
1908 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
1909 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
1912 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
1913 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
1916 switch (feparm.guard_interval)
1918 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32:
1919 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
1921 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16:
1922 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
1924 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8:
1925 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
1927 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4:
1928 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
1931 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto:
1932 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
1935 switch (feparm.hierarchy)
1937 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone:
1938 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
1940 case eDVBFrontendParametersTerrestrial::Hierarchy::H1:
1941 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
1943 case eDVBFrontendParametersTerrestrial::Hierarchy::H2:
1944 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
1946 case eDVBFrontendParametersTerrestrial::Hierarchy::H4:
1947 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
1950 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto:
1951 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
1954 switch (feparm.inversion)
1956 case eDVBFrontendParametersTerrestrial::Inversion::On:
1957 parm_inversion = INVERSION_ON;
1959 case eDVBFrontendParametersTerrestrial::Inversion::Off:
1960 parm_inversion = INVERSION_OFF;
1963 case eDVBFrontendParametersTerrestrial::Inversion::Unknown:
1964 parm_inversion = INVERSION_AUTO;
1970 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
1972 unsigned int timeout = 5000;
1973 eDebug("(%d)tune", m_dvbid);
1981 eDebug("no frontend device opened... do not try to tune !!!");
1993 m_sec_sequence.clear();
1995 where.calcLockTimeout(timeout);
2001 eDVBFrontendParametersSatellite feparm;
2002 if (where.getDVBS(feparm))
2004 eDebug("no dvbs data!");
2008 m_sec->setRotorMoving(false);
2009 res=prepare_sat(feparm, timeout);
2017 eDVBFrontendParametersCable feparm;
2018 if (where.getDVBC(feparm))
2023 res=prepare_cable(feparm);
2027 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2028 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2033 eDVBFrontendParametersTerrestrial feparm;
2034 if (where.getDVBT(feparm))
2036 eDebug("no -T data");
2040 res=prepare_terrestrial(feparm);
2044 std::string enable_5V;
2045 char configStr[255];
2046 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2047 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2048 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2049 if (enable_5V == "True")
2050 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2052 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2053 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2059 m_tuneTimer->start(0,true);
2060 m_sec_sequence.current() = m_sec_sequence.begin();
2062 if (m_state != stateTuning)
2065 m_state = stateTuning;
2066 m_stateChanged(this);
2072 m_tuneTimer->stop();
2076 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2078 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2082 RESULT eDVBFrontend::setVoltage(int voltage)
2084 if (m_type == feCable)
2086 #if HAVE_DVB_API_VERSION < 3
2089 bool increased=false;
2090 fe_sec_voltage_t vlt;
2092 m_data[CUR_VOLTAGE]=voltage;
2096 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2097 vlt = SEC_VOLTAGE_OFF;
2100 #if HAVE_DVB_API_VERSION < 3
2101 vlt = SEC_VOLTAGE_13_5;
2107 vlt = SEC_VOLTAGE_13;
2110 #if HAVE_DVB_API_VERSION < 3
2111 vlt = SEC_VOLTAGE_18_5;
2117 vlt = SEC_VOLTAGE_18;
2122 #if HAVE_DVB_API_VERSION < 3
2123 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2125 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2126 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2127 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2131 RESULT eDVBFrontend::getState(int &state)
2137 RESULT eDVBFrontend::setTone(int t)
2139 if (m_type != feSatellite)
2141 #if HAVE_DVB_API_VERSION < 3
2144 fe_sec_tone_mode_t tone;
2153 tone = SEC_TONE_OFF;
2158 #if HAVE_DVB_API_VERSION < 3
2159 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2161 return ::ioctl(m_fd, FE_SET_TONE, tone);
2165 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2166 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2169 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2171 #if HAVE_DVB_API_VERSION < 3
2172 struct secCommand cmd;
2173 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2174 cmd.u.diseqc.cmdtype = diseqc.data[0];
2175 cmd.u.diseqc.addr = diseqc.data[1];
2176 cmd.u.diseqc.cmd = diseqc.data[2];
2177 cmd.u.diseqc.numParams = diseqc.len-3;
2178 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2179 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2181 struct dvb_diseqc_master_cmd cmd;
2182 memcpy(cmd.msg, diseqc.data, diseqc.len);
2183 cmd.msg_len = diseqc.len;
2184 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2190 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2191 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2193 RESULT eDVBFrontend::sendToneburst(int burst)
2195 #if HAVE_DVB_API_VERSION < 3
2196 secMiniCmd cmd = SEC_MINI_NONE;
2198 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2200 if ( burst == eDVBSatelliteDiseqcParameters::A )
2202 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2204 #if HAVE_DVB_API_VERSION < 3
2205 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2208 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2214 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2220 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2222 m_sec_sequence = list;
2226 RESULT eDVBFrontend::getData(int num, long &data)
2228 if ( num < NUM_DATA_ENTRIES )
2236 RESULT eDVBFrontend::setData(int num, long val)
2238 if ( num < NUM_DATA_ENTRIES )
2246 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2249 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2251 if (m_type == eDVBFrontend::feSatellite)
2254 eDVBFrontendParametersSatellite sat_parm;
2255 int ret = feparm->getDVBS(sat_parm);
2257 if (sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S2 && !m_can_handle_dvbs2)
2259 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2260 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S && m_can_handle_dvbs2)
2264 else if (m_type == eDVBFrontend::feCable)
2265 return 2; // more prio for cable frontends
2266 else if (m_type == eDVBFrontend::feTerrestrial)
2271 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2273 ePyObject Id, Descr, Enabled;
2274 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 3)
2276 Id = PyTuple_GET_ITEM(obj, 0);
2277 Descr = PyTuple_GET_ITEM(obj, 1);
2278 Enabled = PyTuple_GET_ITEM(obj, 2);
2279 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled))
2281 strcpy(m_description, PyString_AS_STRING(Descr));
2282 m_slotid = PyInt_AsLong(Id);
2283 m_enabled = Enabled == Py_True;
2284 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2285 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2286 !!strstr(m_description, "Alps BSBE2") ||
2287 !!strstr(m_description, "Alps -S") ||
2288 !!strstr(m_description, "BCM4501");
2289 m_can_handle_dvbs2 = !!strstr(m_description, "Alps BSBE2") || !!strstr(m_description, "BCM4501");
2290 eDebug("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2291 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2294 PyErr_SetString(PyExc_StandardError,
2295 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");