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);
528 CONNECT(m_sn->activated, eDVBFrontend::feEvent);
533 int eDVBFrontend::closeFrontend()
535 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)m_data[LINKED_NEXT_PTR];
536 while (linked_fe != (eDVBRegisteredFrontend*)-1)
538 if (linked_fe->m_inuse)
540 eDebug("dont close frontend %d until the linked frontend %d in slot %d is still in use",
541 m_dvbid, linked_fe->m_frontend->getDVBID(), linked_fe->m_frontend->getSlotID());
544 linked_fe->m_frontend->getData(LINKED_NEXT_PTR, (long&)linked_fe);
548 eDebug("close frontend %d", m_dvbid);
550 setTone(iDVBFrontend::toneOff);
551 setVoltage(iDVBFrontend::voltageOff);
553 m_sec->setRotorMoving(false);
557 eWarning("couldnt close frontend %d", m_dvbid);
558 m_data[CSW] = m_data[UCSW] = m_data[TONEBURST] = -1;
560 #if HAVE_DVB_API_VERSION < 3
563 if (!::close(m_secfd))
566 eWarning("couldnt close sec %d", m_dvbid);
575 eDVBFrontend::~eDVBFrontend()
577 m_data[LINKED_PREV_PTR] = m_data[LINKED_NEXT_PTR] = -1;
583 void eDVBFrontend::feEvent(int w)
587 #if HAVE_DVB_API_VERSION < 3
590 dvb_frontend_event event;
594 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
596 if (res && (errno == EAGAIN))
601 eWarning("FE_GET_EVENT failed! %m");
608 #if HAVE_DVB_API_VERSION < 3
609 if (event.type == FE_COMPLETION_EV)
611 eDebug("(%d)fe event: status %x, inversion %s", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off");
612 if (event.status & FE_HAS_LOCK)
622 eDebug("stateLostLock");
623 state = stateLostLock;
624 m_data[CSW] = m_data[UCSW] = m_data[TONEBURST] = -1; // reset diseqc
627 if (m_state != state)
630 m_stateChanged(this);
635 void eDVBFrontend::timeout()
638 if (m_state == stateTuning)
640 m_state = stateFailed;
641 m_stateChanged(this);
645 int eDVBFrontend::readFrontendData(int type)
652 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
653 eDebug("FE_READ_BER failed (%m)");
659 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
660 eDebug("FE_READ_SNR failed (%m)");
663 case signalQualitydB: /* this will move into the driver */
666 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
667 eDebug("FE_READ_SNR failed (%m)");
668 if (!strcmp(m_description, "BCM4501 (internal)"))
670 unsigned int SDS_SNRE = snr << 16;
672 static float SNR_COEFF[6] = {
675 197418.0 / 4194304.0,
676 -2602183.0 / 4194304.0,
677 20377212.0 / 4194304.0,
678 -37791203.0 / 4194304.0,
681 float fval1, fval2, snr_in_db;
683 fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0));
684 fval2 = pow(10.0, fval1)-1;
685 fval1 = 10.0 * log10(fval2);
689 fval2 = SNR_COEFF[0];
693 fval2 += SNR_COEFF[i];
699 return (int)(snr_in_db * 100.0);
701 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
702 !strcmp(m_description, "Alps -S") ||
703 !strcmp(m_description, "Philips -S") ||
704 !strcmp(m_description, "LG -S") )
706 float snr_in_db=(snr-39075)/1764.7;
707 return (int)(snr_in_db * 100.0);
708 } else if (!strcmp(m_description, "Alps BSBE2"))
710 return (int)((snr >> 7) * 10.0);
712 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
718 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
719 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
724 #if HAVE_DVB_API_VERSION < 3
725 FrontendStatus status=0;
729 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
730 eDebug("FE_READ_STATUS failed (%m)");
731 return !!(status&FE_HAS_LOCK);
735 #if HAVE_DVB_API_VERSION < 3
736 FrontendStatus status=0;
740 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
741 eDebug("FE_READ_STATUS failed (%m)");
742 return !!(status&FE_HAS_SYNC);
750 void PutToDict(ePyObject &dict, const char*key, long value)
752 ePyObject item = PyInt_FromLong(value);
755 if (PyDict_SetItemString(dict, key, item))
756 eDebug("put %s to dict failed", key);
760 eDebug("could not create PyObject for %s", key);
763 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
767 if (PyDict_SetItemString(dict, key, item))
768 eDebug("put %s to dict failed", key);
772 eDebug("invalid PyObject for %s", key);
775 void PutToDict(ePyObject &dict, const char*key, const char *value)
777 ePyObject item = PyString_FromString(value);
780 if (PyDict_SetItemString(dict, key, item))
781 eDebug("put %s to dict failed", key);
785 eDebug("could not create PyObject for %s", key);
788 void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, eDVBFrontend *fe)
793 fe->getData(eDVBFrontend::CSW, csw);
794 fe->getData(eDVBFrontend::FREQ_OFFSET, freq_offset);
795 int frequency = parm_frequency + freq_offset;
796 PutToDict(dict, "frequency", frequency);
797 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
798 switch(parm_u_qpsk_fec_inner)
821 #if HAVE_DVB_API_VERSION >=3
822 case FEC_S2_8PSK_1_2:
823 case FEC_S2_QPSK_1_2:
826 case FEC_S2_8PSK_2_3:
827 case FEC_S2_QPSK_2_3:
830 case FEC_S2_8PSK_3_4:
831 case FEC_S2_QPSK_3_4:
834 case FEC_S2_8PSK_5_6:
835 case FEC_S2_QPSK_5_6:
838 case FEC_S2_8PSK_7_8:
839 case FEC_S2_QPSK_7_8:
842 case FEC_S2_8PSK_8_9:
843 case FEC_S2_QPSK_8_9:
846 case FEC_S2_8PSK_3_5:
847 case FEC_S2_QPSK_3_5:
850 case FEC_S2_8PSK_4_5:
851 case FEC_S2_QPSK_4_5:
854 case FEC_S2_8PSK_9_10:
855 case FEC_S2_QPSK_9_10:
860 PutToDict(dict, "fec_inner", tmp);
861 #if HAVE_DVB_API_VERSION >=3
862 PutToDict(dict, "modulation",
863 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ? "8PSK": "QPSK" );
864 if (parm_u_qpsk_fec_inner > FEC_AUTO)
866 switch(parm_inversion & 0xc)
868 default: // unknown rolloff
870 tmp = "ROLLOFF_0_35";
873 tmp = "ROLLOFF_0_25";
876 tmp = "ROLLOFF_0_20";
879 PutToDict(dict, "rolloff", tmp);
880 if (parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10)
882 switch(parm_inversion & 0x30)
887 case 0x10: // pilot on
890 case 0x20: // pilot auto
894 PutToDict(dict, "pilot", tmp);
901 PutToDict(dict, "modulation", "QPSK" );
904 PutToDict(dict, "system", tmp);
907 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
910 #if HAVE_DVB_API_VERSION < 3
911 PutToDict(dict, "frequency", parm_frequency);
913 PutToDict(dict, "frequency", parm_frequency/1000);
915 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
916 switch(parm_u_qam_fec_inner)
936 #if HAVE_DVB_API_VERSION >= 3
946 PutToDict(dict, "fec_inner", tmp);
947 switch(parm_u_qam_modulation)
969 PutToDict(dict, "modulation", tmp);
972 void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
975 PutToDict(dict, "frequency", parm_frequency);
976 switch (parm_u_ofdm_bandwidth)
978 case BANDWIDTH_8_MHZ:
979 tmp = "BANDWIDTH_8_MHZ";
981 case BANDWIDTH_7_MHZ:
982 tmp = "BANDWIDTH_7_MHZ";
984 case BANDWIDTH_6_MHZ:
985 tmp = "BANDWIDTH_6_MHZ";
989 tmp = "BANDWIDTH_AUTO";
992 PutToDict(dict, "bandwidth", tmp);
993 switch (parm_u_ofdm_code_rate_LP)
1015 PutToDict(dict, "code_rate_lp", tmp);
1016 switch (parm_u_ofdm_code_rate_HP)
1038 PutToDict(dict, "code_rate_hp", tmp);
1039 switch (parm_u_ofdm_constellation)
1055 PutToDict(dict, "constellation", tmp);
1056 switch (parm_u_ofdm_transmission_mode)
1058 case TRANSMISSION_MODE_2K:
1059 tmp = "TRANSMISSION_MODE_2K";
1061 case TRANSMISSION_MODE_8K:
1062 tmp = "TRANSMISSION_MODE_8K";
1065 case TRANSMISSION_MODE_AUTO:
1066 tmp = "TRANSMISSION_MODE_AUTO";
1069 PutToDict(dict, "transmission_mode", tmp);
1070 switch (parm_u_ofdm_guard_interval)
1072 case GUARD_INTERVAL_1_32:
1073 tmp = "GUARD_INTERVAL_1_32";
1075 case GUARD_INTERVAL_1_16:
1076 tmp = "GUARD_INTERVAL_1_16";
1078 case GUARD_INTERVAL_1_8:
1079 tmp = "GUARD_INTERVAL_1_8";
1081 case GUARD_INTERVAL_1_4:
1082 tmp = "GUARD_INTERVAL_1_4";
1085 case GUARD_INTERVAL_AUTO:
1086 tmp = "GUARD_INTERVAL_AUTO";
1089 PutToDict(dict, "guard_interval", tmp);
1090 switch (parm_u_ofdm_hierarchy_information)
1092 case HIERARCHY_NONE:
1093 tmp = "HIERARCHY_NONE";
1096 tmp = "HIERARCHY_1";
1099 tmp = "HIERARCHY_2";
1102 tmp = "HIERARCHY_4";
1105 case HIERARCHY_AUTO:
1106 tmp = "HIERARCHY_AUTO";
1109 PutToDict(dict, "hierarchy_information", tmp);
1112 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1114 if (dest && PyDict_Check(dest))
1116 const char *tmp = "UNKNOWN";
1137 PutToDict(dest, "tuner_state", tmp);
1138 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1139 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1140 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1141 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1142 int sigQualitydB = readFrontendData(signalQualitydB);
1143 if (sigQualitydB == 0x12345678) // not support yet
1145 ePyObject obj=Py_None;
1147 PutToDict(dest, "tuner_signal_quality_db", obj);
1150 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1151 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1155 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1157 if (m_fd != -1 && dest && PyDict_Check(dest))
1165 FRONTENDPARAMETERS front;
1166 if (!original && ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1167 eDebug("FE_GET_FRONTEND (%m)");
1170 const FRONTENDPARAMETERS &parm = original ? this->parm : front;
1171 const char *tmp = "INVERSION_AUTO";
1172 switch(parm_inversion)
1175 tmp = "INVERSION_ON";
1178 tmp = "INVERSION_OFF";
1184 PutToDict(dest, "inversion", tmp);
1189 fillDictWithSatelliteData(dest, original?parm:front, this);
1192 fillDictWithCableData(dest, original?parm:front);
1195 fillDictWithTerrestrialData(dest, original?parm:front);
1206 void eDVBFrontend::getFrontendData(ePyObject dest)
1208 if (dest && PyDict_Check(dest))
1211 PutToDict(dest, "tuner_number", m_dvbid);
1227 PutToDict(dest, "tuner_type", tmp);
1231 #ifndef FP_IOCTL_GET_ID
1232 #define FP_IOCTL_GET_ID 0
1234 int eDVBFrontend::readInputpower()
1236 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1238 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1239 FILE *f=fopen(proc_name, "r");
1242 if (fscanf(f, "%08x", &power) != 1)
1243 eDebug("read %s failed!! (%m)", proc_name);
1245 eDebug("%s is %d\n", proc_name, power);
1250 // open front prozessor
1251 int fp=::open("/dev/dbox/fp0", O_RDWR);
1254 eDebug("couldn't open fp");
1257 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1258 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1260 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1269 bool eDVBFrontend::setSecSequencePos(int steps)
1271 eDebug("set sequence pos %d", steps);
1276 if (m_sec_sequence.current() != m_sec_sequence.end())
1277 ++m_sec_sequence.current();
1282 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1283 --m_sec_sequence.current();
1289 void eDVBFrontend::setRotorData(int pos, int cmd)
1291 m_data[ROTOR_CMD] = cmd;
1292 m_data[ROTOR_POS] = pos;
1293 if ( m_data[SATPOS_DEPENDS_PTR] != -1 )
1295 eDVBRegisteredFrontend *satpos_depends_to_fe = (eDVBRegisteredFrontend*) m_data[SATPOS_DEPENDS_PTR];
1296 satpos_depends_to_fe->m_frontend->m_data[ROTOR_CMD] = cmd;
1297 satpos_depends_to_fe->m_frontend->m_data[ROTOR_POS] = pos;
1301 eDVBRegisteredFrontend *next = (eDVBRegisteredFrontend *)m_data[LINKED_NEXT_PTR];
1302 while ( (long)next != -1 )
1304 next->m_frontend->m_data[ROTOR_CMD] = cmd;
1305 next->m_frontend->m_data[ROTOR_POS] = pos;
1306 next = (eDVBRegisteredFrontend *)next->m_frontend->m_data[LINKED_NEXT_PTR];
1308 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)m_data[LINKED_PREV_PTR];
1309 while ( (long)prev != -1 )
1311 prev->m_frontend->m_data[ROTOR_CMD] = cmd;
1312 prev->m_frontend->m_data[ROTOR_POS] = pos;
1313 prev = (eDVBRegisteredFrontend *)prev->m_frontend->m_data[LINKED_PREV_PTR];
1318 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1321 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1323 // eDebug("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1324 switch (m_sec_sequence.current()->cmd)
1326 case eSecCommand::SLEEP:
1327 delay = m_sec_sequence.current()++->msec;
1328 eDebug("[SEC] sleep %dms", delay);
1330 case eSecCommand::GOTO:
1331 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1332 ++m_sec_sequence.current();
1334 case eSecCommand::SET_VOLTAGE:
1336 int voltage = m_sec_sequence.current()++->voltage;
1337 eDebug("[SEC] setVoltage %d", voltage);
1338 setVoltage(voltage);
1341 case eSecCommand::IF_VOLTAGE_GOTO:
1343 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1344 if ( compare.voltage == m_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1346 ++m_sec_sequence.current();
1349 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1351 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1352 if ( compare.voltage != m_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1354 ++m_sec_sequence.current();
1357 case eSecCommand::IF_TONE_GOTO:
1359 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1360 if ( compare.tone == m_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1362 ++m_sec_sequence.current();
1365 case eSecCommand::IF_NOT_TONE_GOTO:
1367 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1368 if ( compare.tone != m_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1370 ++m_sec_sequence.current();
1373 case eSecCommand::SET_TONE:
1374 eDebug("[SEC] setTone %d", m_sec_sequence.current()->tone);
1375 setTone(m_sec_sequence.current()++->tone);
1377 case eSecCommand::SEND_DISEQC:
1378 sendDiseqc(m_sec_sequence.current()->diseqc);
1379 eDebugNoNewLine("[SEC] sendDiseqc: ");
1380 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1381 eDebugNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1383 ++m_sec_sequence.current();
1385 case eSecCommand::SEND_TONEBURST:
1386 eDebug("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1387 sendToneburst(m_sec_sequence.current()++->toneburst);
1389 case eSecCommand::SET_FRONTEND:
1390 eDebug("[SEC] setFrontend");
1392 ++m_sec_sequence.current();
1394 case eSecCommand::START_TUNE_TIMEOUT:
1396 m_timeout->start(m_sec_sequence.current()->timeout, 1);
1397 ++m_sec_sequence.current();
1400 case eSecCommand::SET_TIMEOUT:
1401 m_timeoutCount = m_sec_sequence.current()++->val;
1402 eDebug("[SEC] set timeout %d", m_timeoutCount);
1404 case eSecCommand::IF_TIMEOUT_GOTO:
1405 if (!m_timeoutCount)
1407 eDebug("[SEC] rotor timout");
1408 m_sec->setRotorMoving(false);
1409 setSecSequencePos(m_sec_sequence.current()->steps);
1412 ++m_sec_sequence.current();
1414 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1416 int idx = m_sec_sequence.current()++->val;
1417 if ( idx == 0 || idx == 1 )
1419 m_idleInputpower[idx] = readInputpower();
1420 eDebug("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1423 eDebug("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1426 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1428 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1429 int idx = compare.val;
1430 if ( idx == 0 || idx == 1 )
1432 int idle = readInputpower();
1433 int diff = abs(idle-m_idleInputpower[idx]);
1436 eDebug("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1437 setSecSequencePos(compare.steps);
1441 ++m_sec_sequence.current();
1444 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1446 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1447 if (readFrontendData(locked))
1449 eDebug("[SEC] locked step %d ok", cmd.okcount);
1451 if (cmd.okcount > 12)
1453 eDebug("ok > 12 .. goto %d\n",m_sec_sequence.current()->steps);
1454 setSecSequencePos(cmd.steps);
1460 eDebug("[SEC] rotor locked step %d failed", cmd.okcount);
1462 if (!m_timeoutCount && m_retryCount > 0)
1466 ++m_sec_sequence.current();
1469 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1470 m_runningInputpower = readInputpower();
1471 eDebug("[SEC] runningInputpower is %d", m_runningInputpower);
1472 ++m_sec_sequence.current();
1474 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1476 int idleInputpower = m_idleInputpower[ (m_data[CUR_VOLTAGE]&1) ? 0 : 1];
1477 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1478 const char *txt = cmd.direction ? "running" : "stopped";
1479 eDebug("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1481 m_runningInputpower,
1484 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1485 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1488 eDebug("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1489 if ( cmd.okcount > 6 )
1491 m_sec->setRotorMoving(cmd.direction);
1492 eDebug("[SEC] rotor is %s", txt);
1493 if (setSecSequencePos(cmd.steps))
1499 eDebug("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1501 if (!m_timeoutCount && m_retryCount > 0)
1505 ++m_sec_sequence.current();
1508 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1509 if (m_data[ROTOR_CMD] != -1 && m_data[ROTOR_POS] != -1)
1510 setSecSequencePos(m_sec_sequence.current()->steps);
1512 ++m_sec_sequence.current();
1514 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1515 eDebug("[SEC] invalidate current rotorparams");
1516 setRotorData(-1,-1);
1517 ++m_sec_sequence.current();
1519 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1520 setRotorData(m_data[NEW_ROTOR_POS], m_data[NEW_ROTOR_CMD]);
1521 eDebug("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, m_data[ROTOR_CMD], m_data[ROTOR_POS]);
1522 ++m_sec_sequence.current();
1524 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1525 m_retryCount = m_sec_sequence.current()++->val;
1526 eDebug("[SEC] set rotor retries %d", m_retryCount);
1528 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1531 eDebug("[SEC] no more rotor retrys");
1532 setSecSequencePos(m_sec_sequence.current()->steps);
1535 ++m_sec_sequence.current();
1537 case eSecCommand::SET_POWER_LIMITING_MODE:
1540 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", m_dvbid);
1541 FILE *f=fopen(proc_name, "w");
1542 if (f) // new interface exist?
1544 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1545 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1546 eDebug("write %s failed!! (%m)", proc_name);
1548 eDebug("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1551 else if (m_need_rotor_workaround)
1555 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1557 sprintf(dev, "/dev/i2c/%d", m_slotid);
1558 else if (m_slotid == 2)
1559 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1560 else if (m_slotid == 3)
1561 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1562 int fd = ::open(dev, O_RDWR);
1564 unsigned char data[2];
1565 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1566 if(::read(fd, data, 1) != 1)
1567 eDebug("[SEC] error read lnbp (%m)");
1568 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1570 data[0] |= 0x80; // enable static current limiting
1571 eDebug("[SEC] set static current limiting");
1575 data[0] &= ~0x80; // enable dynamic current limiting
1576 eDebug("[SEC] set dynamic current limiting");
1578 if(::write(fd, data, 1) != 1)
1579 eDebug("[SEC] error write lnbp (%m)");
1582 ++m_sec_sequence.current();
1586 eDebug("[SEC] unhandled sec command %d",
1587 ++m_sec_sequence.current()->cmd);
1588 ++m_sec_sequence.current();
1590 m_tuneTimer->start(delay,true);
1594 void eDVBFrontend::setFrontend()
1596 eDebug("setting frontend %d", m_dvbid);
1599 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1601 perror("FE_SET_FRONTEND failed");
1606 RESULT eDVBFrontend::getFrontendType(int &t)
1614 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1619 eWarning("no SEC module active!");
1622 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1625 eDebug("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1628 feparm.polarisation,
1632 feparm.orbital_position);
1633 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1634 switch (feparm.inversion)
1636 case eDVBFrontendParametersSatellite::Inversion::On:
1637 parm_inversion = INVERSION_ON;
1639 case eDVBFrontendParametersSatellite::Inversion::Off:
1640 parm_inversion = INVERSION_OFF;
1643 case eDVBFrontendParametersSatellite::Inversion::Unknown:
1644 parm_inversion = INVERSION_AUTO;
1647 if (feparm.system == eDVBFrontendParametersSatellite::System::DVB_S)
1650 case eDVBFrontendParametersSatellite::FEC::fNone:
1651 parm_u_qpsk_fec_inner = FEC_NONE;
1653 case eDVBFrontendParametersSatellite::FEC::f1_2:
1654 parm_u_qpsk_fec_inner = FEC_1_2;
1656 case eDVBFrontendParametersSatellite::FEC::f2_3:
1657 parm_u_qpsk_fec_inner = FEC_2_3;
1659 case eDVBFrontendParametersSatellite::FEC::f3_4:
1660 parm_u_qpsk_fec_inner = FEC_3_4;
1662 case eDVBFrontendParametersSatellite::FEC::f5_6:
1663 parm_u_qpsk_fec_inner = FEC_5_6;
1665 case eDVBFrontendParametersSatellite::FEC::f7_8:
1666 parm_u_qpsk_fec_inner = FEC_7_8;
1669 eDebug("no valid fec for DVB-S set.. assume auto");
1670 case eDVBFrontendParametersSatellite::FEC::fAuto:
1671 parm_u_qpsk_fec_inner = FEC_AUTO;
1674 #if HAVE_DVB_API_VERSION >= 3
1679 case eDVBFrontendParametersSatellite::FEC::f1_2:
1680 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1682 case eDVBFrontendParametersSatellite::FEC::f2_3:
1683 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1685 case eDVBFrontendParametersSatellite::FEC::f3_4:
1686 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1688 case eDVBFrontendParametersSatellite::FEC::f3_5:
1689 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1691 case eDVBFrontendParametersSatellite::FEC::f4_5:
1692 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1694 case eDVBFrontendParametersSatellite::FEC::f5_6:
1695 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1697 case eDVBFrontendParametersSatellite::FEC::f7_8:
1698 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1700 case eDVBFrontendParametersSatellite::FEC::f8_9:
1701 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1703 case eDVBFrontendParametersSatellite::FEC::f9_10:
1704 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1707 eDebug("no valid fec for DVB-S2 set.. abort !!");
1710 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1711 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK) {
1712 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1713 // 8PSK fec driver values are decimal 9 bigger
1714 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1718 // FIXME !!! get frequency range from tuner
1719 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1721 eDebug("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1724 eDebug("tuning to %d mhz", parm_frequency/1000);
1729 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1731 #if HAVE_DVB_API_VERSION < 3
1732 parm_frequency = feparm.frequency;
1734 parm_frequency = feparm.frequency * 1000;
1736 parm_u_qam_symbol_rate = feparm.symbol_rate;
1737 switch (feparm.modulation)
1739 case eDVBFrontendParametersCable::Modulation::QAM16:
1740 parm_u_qam_modulation = QAM_16;
1742 case eDVBFrontendParametersCable::Modulation::QAM32:
1743 parm_u_qam_modulation = QAM_32;
1745 case eDVBFrontendParametersCable::Modulation::QAM64:
1746 parm_u_qam_modulation = QAM_64;
1748 case eDVBFrontendParametersCable::Modulation::QAM128:
1749 parm_u_qam_modulation = QAM_128;
1751 case eDVBFrontendParametersCable::Modulation::QAM256:
1752 parm_u_qam_modulation = QAM_256;
1755 case eDVBFrontendParametersCable::Modulation::Auto:
1756 parm_u_qam_modulation = QAM_AUTO;
1759 switch (feparm.inversion)
1761 case eDVBFrontendParametersCable::Inversion::On:
1762 parm_inversion = INVERSION_ON;
1764 case eDVBFrontendParametersCable::Inversion::Off:
1765 parm_inversion = INVERSION_OFF;
1768 case eDVBFrontendParametersCable::Inversion::Unknown:
1769 parm_inversion = INVERSION_AUTO;
1772 switch (feparm.fec_inner)
1774 case eDVBFrontendParametersCable::FEC::fNone:
1775 parm_u_qam_fec_inner = FEC_NONE;
1777 case eDVBFrontendParametersCable::FEC::f1_2:
1778 parm_u_qam_fec_inner = FEC_1_2;
1780 case eDVBFrontendParametersCable::FEC::f2_3:
1781 parm_u_qam_fec_inner = FEC_2_3;
1783 case eDVBFrontendParametersCable::FEC::f3_4:
1784 parm_u_qam_fec_inner = FEC_3_4;
1786 case eDVBFrontendParametersCable::FEC::f5_6:
1787 parm_u_qam_fec_inner = FEC_5_6;
1789 case eDVBFrontendParametersCable::FEC::f7_8:
1790 parm_u_qam_fec_inner = FEC_7_8;
1792 #if HAVE_DVB_API_VERSION >= 3
1793 case eDVBFrontendParametersCable::FEC::f8_9:
1794 parm_u_qam_fec_inner = FEC_8_9;
1798 case eDVBFrontendParametersCable::FEC::fAuto:
1799 parm_u_qam_fec_inner = FEC_AUTO;
1802 eDebug("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
1803 parm_frequency/1000,
1804 parm_u_qam_symbol_rate,
1805 parm_u_qam_fec_inner,
1806 parm_u_qam_modulation,
1811 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
1813 parm_frequency = feparm.frequency;
1815 switch (feparm.bandwidth)
1817 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
1818 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
1820 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
1821 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
1823 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
1824 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
1827 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
1828 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
1831 switch (feparm.code_rate_LP)
1833 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1834 parm_u_ofdm_code_rate_LP = FEC_1_2;
1836 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1837 parm_u_ofdm_code_rate_LP = FEC_2_3;
1839 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1840 parm_u_ofdm_code_rate_LP = FEC_3_4;
1842 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1843 parm_u_ofdm_code_rate_LP = FEC_5_6;
1845 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1846 parm_u_ofdm_code_rate_LP = FEC_7_8;
1849 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1850 parm_u_ofdm_code_rate_LP = FEC_AUTO;
1853 switch (feparm.code_rate_HP)
1855 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1856 parm_u_ofdm_code_rate_HP = FEC_1_2;
1858 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1859 parm_u_ofdm_code_rate_HP = FEC_2_3;
1861 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1862 parm_u_ofdm_code_rate_HP = FEC_3_4;
1864 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1865 parm_u_ofdm_code_rate_HP = FEC_5_6;
1867 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1868 parm_u_ofdm_code_rate_HP = FEC_7_8;
1871 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1872 parm_u_ofdm_code_rate_HP = FEC_AUTO;
1875 switch (feparm.modulation)
1877 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
1878 parm_u_ofdm_constellation = QPSK;
1880 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
1881 parm_u_ofdm_constellation = QAM_16;
1883 case eDVBFrontendParametersTerrestrial::Modulation::QAM64:
1884 parm_u_ofdm_constellation = QAM_64;
1887 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
1888 parm_u_ofdm_constellation = QAM_AUTO;
1891 switch (feparm.transmission_mode)
1893 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
1894 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
1896 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
1897 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
1900 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
1901 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
1904 switch (feparm.guard_interval)
1906 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32:
1907 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
1909 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16:
1910 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
1912 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8:
1913 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
1915 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4:
1916 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
1919 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto:
1920 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
1923 switch (feparm.hierarchy)
1925 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone:
1926 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
1928 case eDVBFrontendParametersTerrestrial::Hierarchy::H1:
1929 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
1931 case eDVBFrontendParametersTerrestrial::Hierarchy::H2:
1932 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
1934 case eDVBFrontendParametersTerrestrial::Hierarchy::H4:
1935 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
1938 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto:
1939 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
1942 switch (feparm.inversion)
1944 case eDVBFrontendParametersTerrestrial::Inversion::On:
1945 parm_inversion = INVERSION_ON;
1947 case eDVBFrontendParametersTerrestrial::Inversion::Off:
1948 parm_inversion = INVERSION_OFF;
1951 case eDVBFrontendParametersTerrestrial::Inversion::Unknown:
1952 parm_inversion = INVERSION_AUTO;
1958 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
1960 unsigned int timeout = 5000;
1961 eDebug("(%d)tune", m_dvbid);
1969 eDebug("no frontend device opened... do not try to tune !!!");
1981 m_sec_sequence.clear();
1983 where.calcLockTimeout(timeout);
1989 eDVBFrontendParametersSatellite feparm;
1990 if (where.getDVBS(feparm))
1992 eDebug("no dvbs data!");
1996 m_sec->setRotorMoving(false);
1997 res=prepare_sat(feparm, timeout);
2005 eDVBFrontendParametersCable feparm;
2006 if (where.getDVBC(feparm))
2011 res=prepare_cable(feparm);
2015 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2016 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2021 eDVBFrontendParametersTerrestrial feparm;
2022 if (where.getDVBT(feparm))
2024 eDebug("no -T data");
2028 res=prepare_terrestrial(feparm);
2032 std::string enable_5V;
2033 char configStr[255];
2034 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2035 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2036 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2037 if (enable_5V == "True")
2038 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2040 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2041 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2047 m_tuneTimer->start(0,true);
2048 m_sec_sequence.current() = m_sec_sequence.begin();
2050 if (m_state != stateTuning)
2053 m_state = stateTuning;
2054 m_stateChanged(this);
2060 m_tuneTimer->stop();
2064 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2066 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2070 RESULT eDVBFrontend::setVoltage(int voltage)
2072 if (m_type == feCable)
2074 #if HAVE_DVB_API_VERSION < 3
2077 bool increased=false;
2078 fe_sec_voltage_t vlt;
2080 m_data[CUR_VOLTAGE]=voltage;
2084 for (int i=0; i < 3; ++i) // reset diseqc
2086 vlt = SEC_VOLTAGE_OFF;
2089 #if HAVE_DVB_API_VERSION < 3
2090 vlt = SEC_VOLTAGE_13_5;
2096 vlt = SEC_VOLTAGE_13;
2099 #if HAVE_DVB_API_VERSION < 3
2100 vlt = SEC_VOLTAGE_18_5;
2106 vlt = SEC_VOLTAGE_18;
2111 #if HAVE_DVB_API_VERSION < 3
2112 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2114 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2115 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2116 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2120 RESULT eDVBFrontend::getState(int &state)
2126 RESULT eDVBFrontend::setTone(int t)
2128 if (m_type != feSatellite)
2130 #if HAVE_DVB_API_VERSION < 3
2133 fe_sec_tone_mode_t tone;
2142 tone = SEC_TONE_OFF;
2147 #if HAVE_DVB_API_VERSION < 3
2148 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2150 return ::ioctl(m_fd, FE_SET_TONE, tone);
2154 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2155 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2158 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2160 #if HAVE_DVB_API_VERSION < 3
2161 struct secCommand cmd;
2162 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2163 cmd.u.diseqc.cmdtype = diseqc.data[0];
2164 cmd.u.diseqc.addr = diseqc.data[1];
2165 cmd.u.diseqc.cmd = diseqc.data[2];
2166 cmd.u.diseqc.numParams = diseqc.len-3;
2167 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2168 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2170 struct dvb_diseqc_master_cmd cmd;
2171 memcpy(cmd.msg, diseqc.data, diseqc.len);
2172 cmd.msg_len = diseqc.len;
2173 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2179 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2180 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2182 RESULT eDVBFrontend::sendToneburst(int burst)
2184 #if HAVE_DVB_API_VERSION < 3
2185 secMiniCmd cmd = SEC_MINI_NONE;
2187 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2189 if ( burst == eDVBSatelliteDiseqcParameters::A )
2191 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2193 #if HAVE_DVB_API_VERSION < 3
2194 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2197 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2203 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2209 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2211 m_sec_sequence = list;
2215 RESULT eDVBFrontend::getData(int num, long &data)
2217 if ( num < NUM_DATA_ENTRIES )
2225 RESULT eDVBFrontend::setData(int num, long val)
2227 if ( num < NUM_DATA_ENTRIES )
2235 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2238 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2240 if (m_type == eDVBFrontend::feSatellite)
2243 eDVBFrontendParametersSatellite sat_parm;
2244 int ret = feparm->getDVBS(sat_parm);
2246 if (sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S2 && !m_can_handle_dvbs2)
2248 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2249 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S && m_can_handle_dvbs2)
2253 else if (m_type == eDVBFrontend::feCable)
2254 return 2; // more prio for cable frontends
2255 else if (m_type == eDVBFrontend::feTerrestrial)
2260 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2262 ePyObject Id, Descr, Enabled;
2263 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 3)
2265 Id = PyTuple_GET_ITEM(obj, 0);
2266 Descr = PyTuple_GET_ITEM(obj, 1);
2267 Enabled = PyTuple_GET_ITEM(obj, 2);
2268 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled))
2270 strcpy(m_description, PyString_AS_STRING(Descr));
2271 m_slotid = PyInt_AsLong(Id);
2272 m_enabled = Enabled == Py_True;
2273 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2274 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2275 !!strstr(m_description, "Alps BSBE2") ||
2276 !!strstr(m_description, "Alps -S") ||
2277 !!strstr(m_description, "BCM4501");
2278 m_can_handle_dvbs2 = !!strstr(m_description, "Alps BSBE2") || !!strstr(m_description, "BCM4501");
2279 eDebug("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2280 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2283 PyErr_SetString(PyExc_StandardError,
2284 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");