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);
563 #if HAVE_DVB_API_VERSION < 3
566 if (!::close(m_secfd))
569 eWarning("couldnt close sec %d", m_dvbid);
574 m_state = stateClosed;
579 eDVBFrontend::~eDVBFrontend()
581 m_data[LINKED_PREV_PTR] = m_data[LINKED_NEXT_PTR] = -1;
587 void eDVBFrontend::feEvent(int w)
591 #if HAVE_DVB_API_VERSION < 3
594 dvb_frontend_event event;
598 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
600 if (res && (errno == EAGAIN))
605 eWarning("FE_GET_EVENT failed! %m");
612 #if HAVE_DVB_API_VERSION < 3
613 if (event.type == FE_COMPLETION_EV)
615 eDebug("(%d)fe event: status %x, inversion %s", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off");
616 if (event.status & FE_HAS_LOCK)
626 eDVBFrontend *sec_fe = this;
627 long tmp = m_data[LINKED_PREV_PTR];
629 eDebug("stateLostLock");
630 state = stateLostLock;
634 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
635 sec_fe = linked_fe->m_frontend;
636 sec_fe->getData(LINKED_NEXT_PTR, tmp);
638 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
641 if (m_state != state)
644 m_stateChanged(this);
649 void eDVBFrontend::timeout()
652 if (m_state == stateTuning)
654 m_state = stateFailed;
655 m_stateChanged(this);
659 int eDVBFrontend::readFrontendData(int type)
666 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
667 eDebug("FE_READ_BER failed (%m)");
673 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
674 eDebug("FE_READ_SNR failed (%m)");
677 case signalQualitydB: /* this will move into the driver */
680 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
681 eDebug("FE_READ_SNR failed (%m)");
682 if (!strcmp(m_description, "BCM4501 (internal)"))
684 unsigned int SDS_SNRE = snr << 16;
686 static float SNR_COEFF[6] = {
689 197418.0 / 4194304.0,
690 -2602183.0 / 4194304.0,
691 20377212.0 / 4194304.0,
692 -37791203.0 / 4194304.0,
695 float fval1, fval2, snr_in_db;
697 fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0));
698 fval2 = pow(10.0, fval1)-1;
699 fval1 = 10.0 * log10(fval2);
703 fval2 = SNR_COEFF[0];
707 fval2 += SNR_COEFF[i];
713 return (int)(snr_in_db * 100.0);
715 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
716 !strcmp(m_description, "Alps -S") ||
717 !strcmp(m_description, "Philips -S") ||
718 !strcmp(m_description, "LG -S") )
720 float snr_in_db=(snr-39075)/1764.7;
721 return (int)(snr_in_db * 100.0);
722 } else if (!strcmp(m_description, "Alps BSBE2"))
724 return (int)((snr >> 7) * 10.0);
726 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
732 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
733 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
738 #if HAVE_DVB_API_VERSION < 3
739 FrontendStatus status=0;
743 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
744 eDebug("FE_READ_STATUS failed (%m)");
745 return !!(status&FE_HAS_LOCK);
749 #if HAVE_DVB_API_VERSION < 3
750 FrontendStatus status=0;
754 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
755 eDebug("FE_READ_STATUS failed (%m)");
756 return !!(status&FE_HAS_SYNC);
764 void PutToDict(ePyObject &dict, const char*key, long value)
766 ePyObject item = PyInt_FromLong(value);
769 if (PyDict_SetItemString(dict, key, item))
770 eDebug("put %s to dict failed", key);
774 eDebug("could not create PyObject for %s", key);
777 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
781 if (PyDict_SetItemString(dict, key, item))
782 eDebug("put %s to dict failed", key);
786 eDebug("invalid PyObject for %s", key);
789 void PutToDict(ePyObject &dict, const char*key, const char *value)
791 ePyObject item = PyString_FromString(value);
794 if (PyDict_SetItemString(dict, key, item))
795 eDebug("put %s to dict failed", key);
799 eDebug("could not create PyObject for %s", key);
802 void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, eDVBFrontend *fe)
806 fe->getData(eDVBFrontend::FREQ_OFFSET, freq_offset);
807 int frequency = parm_frequency + freq_offset;
808 PutToDict(dict, "frequency", frequency);
809 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
810 switch(parm_u_qpsk_fec_inner)
833 #if HAVE_DVB_API_VERSION >=3
834 case FEC_S2_8PSK_1_2:
835 case FEC_S2_QPSK_1_2:
838 case FEC_S2_8PSK_2_3:
839 case FEC_S2_QPSK_2_3:
842 case FEC_S2_8PSK_3_4:
843 case FEC_S2_QPSK_3_4:
846 case FEC_S2_8PSK_5_6:
847 case FEC_S2_QPSK_5_6:
850 case FEC_S2_8PSK_7_8:
851 case FEC_S2_QPSK_7_8:
854 case FEC_S2_8PSK_8_9:
855 case FEC_S2_QPSK_8_9:
858 case FEC_S2_8PSK_3_5:
859 case FEC_S2_QPSK_3_5:
862 case FEC_S2_8PSK_4_5:
863 case FEC_S2_QPSK_4_5:
866 case FEC_S2_8PSK_9_10:
867 case FEC_S2_QPSK_9_10:
872 PutToDict(dict, "fec_inner", tmp);
873 #if HAVE_DVB_API_VERSION >=3
874 PutToDict(dict, "modulation",
875 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ? "8PSK": "QPSK" );
876 if (parm_u_qpsk_fec_inner > FEC_AUTO)
878 switch(parm_inversion & 0xc)
880 default: // unknown rolloff
882 tmp = "ROLLOFF_0_35";
885 tmp = "ROLLOFF_0_25";
888 tmp = "ROLLOFF_0_20";
891 PutToDict(dict, "rolloff", tmp);
892 if (parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10)
894 switch(parm_inversion & 0x30)
899 case 0x10: // pilot on
902 case 0x20: // pilot auto
906 PutToDict(dict, "pilot", tmp);
913 PutToDict(dict, "modulation", "QPSK" );
916 PutToDict(dict, "system", tmp);
919 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
922 #if HAVE_DVB_API_VERSION < 3
923 PutToDict(dict, "frequency", parm_frequency);
925 PutToDict(dict, "frequency", parm_frequency/1000);
927 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
928 switch(parm_u_qam_fec_inner)
948 #if HAVE_DVB_API_VERSION >= 3
958 PutToDict(dict, "fec_inner", tmp);
959 switch(parm_u_qam_modulation)
981 PutToDict(dict, "modulation", tmp);
984 void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
987 PutToDict(dict, "frequency", parm_frequency);
988 switch (parm_u_ofdm_bandwidth)
990 case BANDWIDTH_8_MHZ:
991 tmp = "BANDWIDTH_8_MHZ";
993 case BANDWIDTH_7_MHZ:
994 tmp = "BANDWIDTH_7_MHZ";
996 case BANDWIDTH_6_MHZ:
997 tmp = "BANDWIDTH_6_MHZ";
1000 case BANDWIDTH_AUTO:
1001 tmp = "BANDWIDTH_AUTO";
1004 PutToDict(dict, "bandwidth", tmp);
1005 switch (parm_u_ofdm_code_rate_LP)
1027 PutToDict(dict, "code_rate_lp", tmp);
1028 switch (parm_u_ofdm_code_rate_HP)
1050 PutToDict(dict, "code_rate_hp", tmp);
1051 switch (parm_u_ofdm_constellation)
1067 PutToDict(dict, "constellation", tmp);
1068 switch (parm_u_ofdm_transmission_mode)
1070 case TRANSMISSION_MODE_2K:
1071 tmp = "TRANSMISSION_MODE_2K";
1073 case TRANSMISSION_MODE_8K:
1074 tmp = "TRANSMISSION_MODE_8K";
1077 case TRANSMISSION_MODE_AUTO:
1078 tmp = "TRANSMISSION_MODE_AUTO";
1081 PutToDict(dict, "transmission_mode", tmp);
1082 switch (parm_u_ofdm_guard_interval)
1084 case GUARD_INTERVAL_1_32:
1085 tmp = "GUARD_INTERVAL_1_32";
1087 case GUARD_INTERVAL_1_16:
1088 tmp = "GUARD_INTERVAL_1_16";
1090 case GUARD_INTERVAL_1_8:
1091 tmp = "GUARD_INTERVAL_1_8";
1093 case GUARD_INTERVAL_1_4:
1094 tmp = "GUARD_INTERVAL_1_4";
1097 case GUARD_INTERVAL_AUTO:
1098 tmp = "GUARD_INTERVAL_AUTO";
1101 PutToDict(dict, "guard_interval", tmp);
1102 switch (parm_u_ofdm_hierarchy_information)
1104 case HIERARCHY_NONE:
1105 tmp = "HIERARCHY_NONE";
1108 tmp = "HIERARCHY_1";
1111 tmp = "HIERARCHY_2";
1114 tmp = "HIERARCHY_4";
1117 case HIERARCHY_AUTO:
1118 tmp = "HIERARCHY_AUTO";
1121 PutToDict(dict, "hierarchy_information", tmp);
1124 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1126 if (dest && PyDict_Check(dest))
1128 const char *tmp = "UNKNOWN";
1149 PutToDict(dest, "tuner_state", tmp);
1150 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1151 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1152 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1153 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1154 int sigQualitydB = readFrontendData(signalQualitydB);
1155 if (sigQualitydB == 0x12345678) // not support yet
1157 ePyObject obj=Py_None;
1159 PutToDict(dest, "tuner_signal_quality_db", obj);
1162 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1163 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1167 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1169 if (m_fd != -1 && dest && PyDict_Check(dest))
1177 FRONTENDPARAMETERS front;
1178 if (!original && ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1179 eDebug("FE_GET_FRONTEND (%m)");
1182 const FRONTENDPARAMETERS &parm = original ? this->parm : front;
1183 const char *tmp = "INVERSION_AUTO";
1184 switch(parm_inversion)
1187 tmp = "INVERSION_ON";
1190 tmp = "INVERSION_OFF";
1196 PutToDict(dest, "inversion", tmp);
1201 fillDictWithSatelliteData(dest, original?parm:front, this);
1204 fillDictWithCableData(dest, original?parm:front);
1207 fillDictWithTerrestrialData(dest, original?parm:front);
1218 void eDVBFrontend::getFrontendData(ePyObject dest)
1220 if (dest && PyDict_Check(dest))
1223 PutToDict(dest, "tuner_number", m_slotid);
1239 PutToDict(dest, "tuner_type", tmp);
1243 #ifndef FP_IOCTL_GET_ID
1244 #define FP_IOCTL_GET_ID 0
1246 int eDVBFrontend::readInputpower()
1248 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1250 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1251 FILE *f=fopen(proc_name, "r");
1254 if (fscanf(f, "%d", &power) != 1)
1255 eDebug("read %s failed!! (%m)", proc_name);
1257 eDebug("%s is %d\n", proc_name, power);
1262 // open front prozessor
1263 int fp=::open("/dev/dbox/fp0", O_RDWR);
1266 eDebug("couldn't open fp");
1269 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1270 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1272 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1281 bool eDVBFrontend::setSecSequencePos(int steps)
1283 eDebug("set sequence pos %d", steps);
1288 if (m_sec_sequence.current() != m_sec_sequence.end())
1289 ++m_sec_sequence.current();
1294 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1295 --m_sec_sequence.current();
1301 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1304 eDVBFrontend *sec_fe = this;
1305 eDVBRegisteredFrontend *regFE = 0;
1306 long tmp = m_data[LINKED_PREV_PTR];
1309 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1310 sec_fe = prev->m_frontend;
1311 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1312 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1313 int state = sec_fe->m_state;
1314 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1316 sec_fe->closeFrontend(true);
1317 state = sec_fe->m_state;
1319 if (state == eDVBFrontend::stateClosed)
1327 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1329 long *sec_fe_data = sec_fe->m_data;
1330 // eDebug("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1331 switch (m_sec_sequence.current()->cmd)
1333 case eSecCommand::SLEEP:
1334 delay = m_sec_sequence.current()++->msec;
1335 eDebug("[SEC] sleep %dms", delay);
1337 case eSecCommand::GOTO:
1338 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1339 ++m_sec_sequence.current();
1341 case eSecCommand::SET_VOLTAGE:
1343 int voltage = m_sec_sequence.current()++->voltage;
1344 eDebug("[SEC] setVoltage %d", voltage);
1345 sec_fe->setVoltage(voltage);
1348 case eSecCommand::IF_VOLTAGE_GOTO:
1350 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1351 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1353 ++m_sec_sequence.current();
1356 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1358 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1359 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1361 ++m_sec_sequence.current();
1364 case eSecCommand::IF_TONE_GOTO:
1366 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1367 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1369 ++m_sec_sequence.current();
1372 case eSecCommand::IF_NOT_TONE_GOTO:
1374 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1375 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1377 ++m_sec_sequence.current();
1380 case eSecCommand::SET_TONE:
1381 eDebug("[SEC] setTone %d", m_sec_sequence.current()->tone);
1382 sec_fe->setTone(m_sec_sequence.current()++->tone);
1384 case eSecCommand::SEND_DISEQC:
1385 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1386 eDebugNoNewLine("[SEC] sendDiseqc: ");
1387 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1388 eDebugNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1390 ++m_sec_sequence.current();
1392 case eSecCommand::SEND_TONEBURST:
1393 eDebug("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1394 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1396 case eSecCommand::SET_FRONTEND:
1397 eDebug("[SEC] setFrontend");
1399 ++m_sec_sequence.current();
1401 case eSecCommand::START_TUNE_TIMEOUT:
1403 m_timeout->start(m_sec_sequence.current()->timeout, 1);
1404 ++m_sec_sequence.current();
1407 case eSecCommand::SET_TIMEOUT:
1408 m_timeoutCount = m_sec_sequence.current()++->val;
1409 eDebug("[SEC] set timeout %d", m_timeoutCount);
1411 case eSecCommand::IF_TIMEOUT_GOTO:
1412 if (!m_timeoutCount)
1414 eDebug("[SEC] rotor timout");
1415 m_sec->setRotorMoving(false);
1416 setSecSequencePos(m_sec_sequence.current()->steps);
1419 ++m_sec_sequence.current();
1421 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1423 int idx = m_sec_sequence.current()++->val;
1424 if ( idx == 0 || idx == 1 )
1426 m_idleInputpower[idx] = sec_fe->readInputpower();
1427 eDebug("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1430 eDebug("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1433 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1435 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1436 int idx = compare.val;
1437 if ( idx == 0 || idx == 1 )
1439 int idle = sec_fe->readInputpower();
1440 int diff = abs(idle-m_idleInputpower[idx]);
1443 eDebug("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1444 setSecSequencePos(compare.steps);
1448 ++m_sec_sequence.current();
1451 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1453 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1454 if (readFrontendData(locked))
1456 eDebug("[SEC] locked step %d ok", cmd.okcount);
1458 if (cmd.okcount > 12)
1460 eDebug("ok > 12 .. goto %d\n",m_sec_sequence.current()->steps);
1461 setSecSequencePos(cmd.steps);
1467 eDebug("[SEC] rotor locked step %d failed", cmd.okcount);
1469 if (!m_timeoutCount && m_retryCount > 0)
1473 ++m_sec_sequence.current();
1476 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1477 m_runningInputpower = sec_fe->readInputpower();
1478 eDebug("[SEC] runningInputpower is %d", m_runningInputpower);
1479 ++m_sec_sequence.current();
1481 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1483 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1484 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1485 const char *txt = cmd.direction ? "running" : "stopped";
1486 eDebug("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1488 m_runningInputpower,
1491 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1492 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1495 eDebug("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1496 if ( cmd.okcount > 6 )
1498 m_sec->setRotorMoving(cmd.direction);
1499 eDebug("[SEC] rotor is %s", txt);
1500 if (setSecSequencePos(cmd.steps))
1506 eDebug("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1508 if (!m_timeoutCount && m_retryCount > 0)
1512 ++m_sec_sequence.current();
1515 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1516 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1517 setSecSequencePos(m_sec_sequence.current()->steps);
1519 ++m_sec_sequence.current();
1521 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1522 eDebug("[SEC] invalidate current switch params");
1523 sec_fe_data[CSW] = -1;
1524 sec_fe_data[UCSW] = -1;
1525 sec_fe_data[TONEBURST] = -1;
1526 ++m_sec_sequence.current();
1528 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1529 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1530 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1531 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1532 eDebug("[SEC] update current switch params");
1533 ++m_sec_sequence.current();
1535 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1536 eDebug("[SEC] invalidate current rotorparams");
1537 sec_fe_data[ROTOR_CMD] = -1;
1538 sec_fe_data[ROTOR_POS] = -1;
1539 ++m_sec_sequence.current();
1541 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1542 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1543 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1544 eDebug("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1545 ++m_sec_sequence.current();
1547 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1548 m_retryCount = m_sec_sequence.current()++->val;
1549 eDebug("[SEC] set rotor retries %d", m_retryCount);
1551 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1554 eDebug("[SEC] no more rotor retrys");
1555 setSecSequencePos(m_sec_sequence.current()->steps);
1558 ++m_sec_sequence.current();
1560 case eSecCommand::SET_POWER_LIMITING_MODE:
1563 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1564 FILE *f=fopen(proc_name, "w");
1565 if (f) // new interface exist?
1567 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1568 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1569 eDebug("write %s failed!! (%m)", proc_name);
1571 eDebug("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1574 else if (sec_fe->m_need_rotor_workaround)
1577 int slotid = sec_fe->m_slotid;
1578 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1580 sprintf(dev, "/dev/i2c/%d", slotid);
1581 else if (slotid == 2)
1582 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1583 else if (slotid == 3)
1584 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1585 int fd = ::open(dev, O_RDWR);
1587 unsigned char data[2];
1588 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1589 if(::read(fd, data, 1) != 1)
1590 eDebug("[SEC] error read lnbp (%m)");
1591 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1593 data[0] |= 0x80; // enable static current limiting
1594 eDebug("[SEC] set static current limiting");
1598 data[0] &= ~0x80; // enable dynamic current limiting
1599 eDebug("[SEC] set dynamic current limiting");
1601 if(::write(fd, data, 1) != 1)
1602 eDebug("[SEC] error write lnbp (%m)");
1605 ++m_sec_sequence.current();
1609 eDebug("[SEC] unhandled sec command %d",
1610 ++m_sec_sequence.current()->cmd);
1611 ++m_sec_sequence.current();
1613 m_tuneTimer->start(delay,true);
1619 void eDVBFrontend::setFrontend()
1621 eDebug("setting frontend %d", m_dvbid);
1624 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1626 perror("FE_SET_FRONTEND failed");
1631 RESULT eDVBFrontend::getFrontendType(int &t)
1639 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1644 eWarning("no SEC module active!");
1647 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1650 eDebug("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1653 feparm.polarisation,
1657 feparm.orbital_position);
1658 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1659 switch (feparm.inversion)
1661 case eDVBFrontendParametersSatellite::Inversion::On:
1662 parm_inversion = INVERSION_ON;
1664 case eDVBFrontendParametersSatellite::Inversion::Off:
1665 parm_inversion = INVERSION_OFF;
1668 case eDVBFrontendParametersSatellite::Inversion::Unknown:
1669 parm_inversion = INVERSION_AUTO;
1672 if (feparm.system == eDVBFrontendParametersSatellite::System::DVB_S)
1675 case eDVBFrontendParametersSatellite::FEC::fNone:
1676 parm_u_qpsk_fec_inner = FEC_NONE;
1678 case eDVBFrontendParametersSatellite::FEC::f1_2:
1679 parm_u_qpsk_fec_inner = FEC_1_2;
1681 case eDVBFrontendParametersSatellite::FEC::f2_3:
1682 parm_u_qpsk_fec_inner = FEC_2_3;
1684 case eDVBFrontendParametersSatellite::FEC::f3_4:
1685 parm_u_qpsk_fec_inner = FEC_3_4;
1687 case eDVBFrontendParametersSatellite::FEC::f5_6:
1688 parm_u_qpsk_fec_inner = FEC_5_6;
1690 case eDVBFrontendParametersSatellite::FEC::f7_8:
1691 parm_u_qpsk_fec_inner = FEC_7_8;
1694 eDebug("no valid fec for DVB-S set.. assume auto");
1695 case eDVBFrontendParametersSatellite::FEC::fAuto:
1696 parm_u_qpsk_fec_inner = FEC_AUTO;
1699 #if HAVE_DVB_API_VERSION >= 3
1704 case eDVBFrontendParametersSatellite::FEC::f1_2:
1705 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1707 case eDVBFrontendParametersSatellite::FEC::f2_3:
1708 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1710 case eDVBFrontendParametersSatellite::FEC::f3_4:
1711 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1713 case eDVBFrontendParametersSatellite::FEC::f3_5:
1714 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1716 case eDVBFrontendParametersSatellite::FEC::f4_5:
1717 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1719 case eDVBFrontendParametersSatellite::FEC::f5_6:
1720 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1722 case eDVBFrontendParametersSatellite::FEC::f7_8:
1723 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1725 case eDVBFrontendParametersSatellite::FEC::f8_9:
1726 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1728 case eDVBFrontendParametersSatellite::FEC::f9_10:
1729 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1732 eDebug("no valid fec for DVB-S2 set.. abort !!");
1735 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1736 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK) {
1737 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1738 // 8PSK fec driver values are decimal 9 bigger
1739 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1743 // FIXME !!! get frequency range from tuner
1744 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1746 eDebug("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1749 eDebug("tuning to %d mhz", parm_frequency/1000);
1754 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1756 #if HAVE_DVB_API_VERSION < 3
1757 parm_frequency = feparm.frequency;
1759 parm_frequency = feparm.frequency * 1000;
1761 parm_u_qam_symbol_rate = feparm.symbol_rate;
1762 switch (feparm.modulation)
1764 case eDVBFrontendParametersCable::Modulation::QAM16:
1765 parm_u_qam_modulation = QAM_16;
1767 case eDVBFrontendParametersCable::Modulation::QAM32:
1768 parm_u_qam_modulation = QAM_32;
1770 case eDVBFrontendParametersCable::Modulation::QAM64:
1771 parm_u_qam_modulation = QAM_64;
1773 case eDVBFrontendParametersCable::Modulation::QAM128:
1774 parm_u_qam_modulation = QAM_128;
1776 case eDVBFrontendParametersCable::Modulation::QAM256:
1777 parm_u_qam_modulation = QAM_256;
1780 case eDVBFrontendParametersCable::Modulation::Auto:
1781 parm_u_qam_modulation = QAM_AUTO;
1784 switch (feparm.inversion)
1786 case eDVBFrontendParametersCable::Inversion::On:
1787 parm_inversion = INVERSION_ON;
1789 case eDVBFrontendParametersCable::Inversion::Off:
1790 parm_inversion = INVERSION_OFF;
1793 case eDVBFrontendParametersCable::Inversion::Unknown:
1794 parm_inversion = INVERSION_AUTO;
1797 switch (feparm.fec_inner)
1799 case eDVBFrontendParametersCable::FEC::fNone:
1800 parm_u_qam_fec_inner = FEC_NONE;
1802 case eDVBFrontendParametersCable::FEC::f1_2:
1803 parm_u_qam_fec_inner = FEC_1_2;
1805 case eDVBFrontendParametersCable::FEC::f2_3:
1806 parm_u_qam_fec_inner = FEC_2_3;
1808 case eDVBFrontendParametersCable::FEC::f3_4:
1809 parm_u_qam_fec_inner = FEC_3_4;
1811 case eDVBFrontendParametersCable::FEC::f5_6:
1812 parm_u_qam_fec_inner = FEC_5_6;
1814 case eDVBFrontendParametersCable::FEC::f7_8:
1815 parm_u_qam_fec_inner = FEC_7_8;
1817 #if HAVE_DVB_API_VERSION >= 3
1818 case eDVBFrontendParametersCable::FEC::f8_9:
1819 parm_u_qam_fec_inner = FEC_8_9;
1823 case eDVBFrontendParametersCable::FEC::fAuto:
1824 parm_u_qam_fec_inner = FEC_AUTO;
1827 eDebug("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
1828 parm_frequency/1000,
1829 parm_u_qam_symbol_rate,
1830 parm_u_qam_fec_inner,
1831 parm_u_qam_modulation,
1836 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
1838 parm_frequency = feparm.frequency;
1840 switch (feparm.bandwidth)
1842 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
1843 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
1845 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
1846 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
1848 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
1849 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
1852 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
1853 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
1856 switch (feparm.code_rate_LP)
1858 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1859 parm_u_ofdm_code_rate_LP = FEC_1_2;
1861 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1862 parm_u_ofdm_code_rate_LP = FEC_2_3;
1864 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1865 parm_u_ofdm_code_rate_LP = FEC_3_4;
1867 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1868 parm_u_ofdm_code_rate_LP = FEC_5_6;
1870 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1871 parm_u_ofdm_code_rate_LP = FEC_7_8;
1874 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1875 parm_u_ofdm_code_rate_LP = FEC_AUTO;
1878 switch (feparm.code_rate_HP)
1880 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1881 parm_u_ofdm_code_rate_HP = FEC_1_2;
1883 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1884 parm_u_ofdm_code_rate_HP = FEC_2_3;
1886 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1887 parm_u_ofdm_code_rate_HP = FEC_3_4;
1889 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1890 parm_u_ofdm_code_rate_HP = FEC_5_6;
1892 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1893 parm_u_ofdm_code_rate_HP = FEC_7_8;
1896 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1897 parm_u_ofdm_code_rate_HP = FEC_AUTO;
1900 switch (feparm.modulation)
1902 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
1903 parm_u_ofdm_constellation = QPSK;
1905 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
1906 parm_u_ofdm_constellation = QAM_16;
1908 case eDVBFrontendParametersTerrestrial::Modulation::QAM64:
1909 parm_u_ofdm_constellation = QAM_64;
1912 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
1913 parm_u_ofdm_constellation = QAM_AUTO;
1916 switch (feparm.transmission_mode)
1918 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
1919 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
1921 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
1922 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
1925 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
1926 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
1929 switch (feparm.guard_interval)
1931 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32:
1932 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
1934 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16:
1935 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
1937 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8:
1938 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
1940 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4:
1941 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
1944 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto:
1945 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
1948 switch (feparm.hierarchy)
1950 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone:
1951 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
1953 case eDVBFrontendParametersTerrestrial::Hierarchy::H1:
1954 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
1956 case eDVBFrontendParametersTerrestrial::Hierarchy::H2:
1957 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
1959 case eDVBFrontendParametersTerrestrial::Hierarchy::H4:
1960 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
1963 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto:
1964 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
1967 switch (feparm.inversion)
1969 case eDVBFrontendParametersTerrestrial::Inversion::On:
1970 parm_inversion = INVERSION_ON;
1972 case eDVBFrontendParametersTerrestrial::Inversion::Off:
1973 parm_inversion = INVERSION_OFF;
1976 case eDVBFrontendParametersTerrestrial::Inversion::Unknown:
1977 parm_inversion = INVERSION_AUTO;
1983 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
1985 unsigned int timeout = 5000;
1986 eDebug("(%d)tune", m_dvbid);
1994 eDebug("no frontend device opened... do not try to tune !!!");
2006 m_sec_sequence.clear();
2008 where.calcLockTimeout(timeout);
2014 eDVBFrontendParametersSatellite feparm;
2015 if (where.getDVBS(feparm))
2017 eDebug("no dvbs data!");
2021 m_sec->setRotorMoving(false);
2022 res=prepare_sat(feparm, timeout);
2030 eDVBFrontendParametersCable feparm;
2031 if (where.getDVBC(feparm))
2036 res=prepare_cable(feparm);
2040 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2041 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2046 eDVBFrontendParametersTerrestrial feparm;
2047 if (where.getDVBT(feparm))
2049 eDebug("no -T data");
2053 res=prepare_terrestrial(feparm);
2057 std::string enable_5V;
2058 char configStr[255];
2059 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2060 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2061 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2062 if (enable_5V == "True")
2063 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2065 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2066 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2072 m_tuneTimer->start(0,true);
2073 m_sec_sequence.current() = m_sec_sequence.begin();
2075 if (m_state != stateTuning)
2078 m_state = stateTuning;
2079 m_stateChanged(this);
2085 m_tuneTimer->stop();
2089 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2091 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2095 RESULT eDVBFrontend::setVoltage(int voltage)
2097 if (m_type == feCable)
2099 #if HAVE_DVB_API_VERSION < 3
2102 bool increased=false;
2103 fe_sec_voltage_t vlt;
2105 m_data[CUR_VOLTAGE]=voltage;
2109 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2110 vlt = SEC_VOLTAGE_OFF;
2113 #if HAVE_DVB_API_VERSION < 3
2114 vlt = SEC_VOLTAGE_13_5;
2120 vlt = SEC_VOLTAGE_13;
2123 #if HAVE_DVB_API_VERSION < 3
2124 vlt = SEC_VOLTAGE_18_5;
2130 vlt = SEC_VOLTAGE_18;
2135 #if HAVE_DVB_API_VERSION < 3
2136 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2138 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2139 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2140 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2144 RESULT eDVBFrontend::getState(int &state)
2150 RESULT eDVBFrontend::setTone(int t)
2152 if (m_type != feSatellite)
2154 #if HAVE_DVB_API_VERSION < 3
2157 fe_sec_tone_mode_t tone;
2166 tone = SEC_TONE_OFF;
2171 #if HAVE_DVB_API_VERSION < 3
2172 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2174 return ::ioctl(m_fd, FE_SET_TONE, tone);
2178 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2179 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2182 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2184 #if HAVE_DVB_API_VERSION < 3
2185 struct secCommand cmd;
2186 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2187 cmd.u.diseqc.cmdtype = diseqc.data[0];
2188 cmd.u.diseqc.addr = diseqc.data[1];
2189 cmd.u.diseqc.cmd = diseqc.data[2];
2190 cmd.u.diseqc.numParams = diseqc.len-3;
2191 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2192 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2194 struct dvb_diseqc_master_cmd cmd;
2195 memcpy(cmd.msg, diseqc.data, diseqc.len);
2196 cmd.msg_len = diseqc.len;
2197 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2203 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2204 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2206 RESULT eDVBFrontend::sendToneburst(int burst)
2208 #if HAVE_DVB_API_VERSION < 3
2209 secMiniCmd cmd = SEC_MINI_NONE;
2211 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2213 if ( burst == eDVBSatelliteDiseqcParameters::A )
2215 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2217 #if HAVE_DVB_API_VERSION < 3
2218 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2221 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2227 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2233 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2235 m_sec_sequence = list;
2239 RESULT eDVBFrontend::getData(int num, long &data)
2241 if ( num < NUM_DATA_ENTRIES )
2249 RESULT eDVBFrontend::setData(int num, long val)
2251 if ( num < NUM_DATA_ENTRIES )
2259 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2262 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2264 if (m_type == eDVBFrontend::feSatellite)
2267 eDVBFrontendParametersSatellite sat_parm;
2268 int ret = feparm->getDVBS(sat_parm);
2270 if (sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S2 && !m_can_handle_dvbs2)
2272 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2273 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S && m_can_handle_dvbs2)
2277 else if (m_type == eDVBFrontend::feCable)
2278 return 2; // more prio for cable frontends
2279 else if (m_type == eDVBFrontend::feTerrestrial)
2284 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2286 ePyObject Id, Descr, Enabled;
2287 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 3)
2289 Id = PyTuple_GET_ITEM(obj, 0);
2290 Descr = PyTuple_GET_ITEM(obj, 1);
2291 Enabled = PyTuple_GET_ITEM(obj, 2);
2292 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled))
2294 strcpy(m_description, PyString_AS_STRING(Descr));
2295 m_slotid = PyInt_AsLong(Id);
2296 m_enabled = Enabled == Py_True;
2297 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2298 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2299 !!strstr(m_description, "Alps BSBE2") ||
2300 !!strstr(m_description, "Alps -S") ||
2301 !!strstr(m_description, "BCM4501");
2302 m_can_handle_dvbs2 = !!strstr(m_description, "Alps BSBE2") || !!strstr(m_description, "BCM4501");
2303 eDebug("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2304 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2307 PyErr_SetString(PyExc_StandardError,
2308 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");