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()
582 void eDVBFrontend::feEvent(int w)
586 #if HAVE_DVB_API_VERSION < 3
589 dvb_frontend_event event;
593 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
595 if (res && (errno == EAGAIN))
600 eWarning("FE_GET_EVENT failed! %m");
607 #if HAVE_DVB_API_VERSION < 3
608 if (event.type == FE_COMPLETION_EV)
610 eDebug("(%d)fe event: status %x, inversion %s", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off");
611 if (event.status & FE_HAS_LOCK)
621 eDebug("stateLostLock");
622 state = stateLostLock;
623 m_data[CSW] = m_data[UCSW] = m_data[TONEBURST] = -1; // reset diseqc
626 if (m_state != state)
629 m_stateChanged(this);
634 void eDVBFrontend::timeout()
637 if (m_state == stateTuning)
639 m_state = stateFailed;
640 m_stateChanged(this);
644 int eDVBFrontend::readFrontendData(int type)
651 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
652 eDebug("FE_READ_BER failed (%m)");
658 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
659 eDebug("FE_READ_SNR failed (%m)");
662 case signalQualitydB: /* this will move into the driver */
665 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
666 eDebug("FE_READ_SNR failed (%m)");
667 if (!strcmp(m_description, "BCM4501 (internal)"))
669 unsigned int SDS_SNRE = snr << 16;
671 static float SNR_COEFF[6] = {
674 197418.0 / 4194304.0,
675 -2602183.0 / 4194304.0,
676 20377212.0 / 4194304.0,
677 -37791203.0 / 4194304.0,
680 float fval1, fval2, snr_in_db;
682 fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0));
683 fval2 = pow(10.0, fval1)-1;
684 fval1 = 10.0 * log10(fval2);
688 fval2 = SNR_COEFF[0];
692 fval2 += SNR_COEFF[i];
698 return (int)(snr_in_db * 100.0);
700 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
701 !strcmp(m_description, "Alps -S") ||
702 !strcmp(m_description, "Philips -S") ||
703 !strcmp(m_description, "LG -S") )
705 float snr_in_db=(snr-39075)/1764.7;
706 return (int)(snr_in_db * 100.0);
707 } else if (!strcmp(m_description, "Alps BSBE2"))
709 return (int)((snr >> 7) * 10.0);
711 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
717 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
718 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
723 #if HAVE_DVB_API_VERSION < 3
724 FrontendStatus status=0;
728 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
729 eDebug("FE_READ_STATUS failed (%m)");
730 return !!(status&FE_HAS_LOCK);
734 #if HAVE_DVB_API_VERSION < 3
735 FrontendStatus status=0;
739 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
740 eDebug("FE_READ_STATUS failed (%m)");
741 return !!(status&FE_HAS_SYNC);
749 void PutToDict(ePyObject &dict, const char*key, long value)
751 ePyObject item = PyInt_FromLong(value);
754 if (PyDict_SetItemString(dict, key, item))
755 eDebug("put %s to dict failed", key);
759 eDebug("could not create PyObject for %s", key);
762 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
766 if (PyDict_SetItemString(dict, key, item))
767 eDebug("put %s to dict failed", key);
771 eDebug("invalid PyObject for %s", key);
774 void PutToDict(ePyObject &dict, const char*key, const char *value)
776 ePyObject item = PyString_FromString(value);
779 if (PyDict_SetItemString(dict, key, item))
780 eDebug("put %s to dict failed", key);
784 eDebug("could not create PyObject for %s", key);
787 void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, eDVBFrontend *fe)
792 fe->getData(eDVBFrontend::CSW, csw);
793 fe->getData(eDVBFrontend::FREQ_OFFSET, freq_offset);
794 int frequency = parm_frequency + freq_offset;
795 PutToDict(dict, "frequency", frequency);
796 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
797 switch(parm_u_qpsk_fec_inner)
820 #if HAVE_DVB_API_VERSION >=3
821 case FEC_S2_8PSK_1_2:
822 case FEC_S2_QPSK_1_2:
825 case FEC_S2_8PSK_2_3:
826 case FEC_S2_QPSK_2_3:
829 case FEC_S2_8PSK_3_4:
830 case FEC_S2_QPSK_3_4:
833 case FEC_S2_8PSK_5_6:
834 case FEC_S2_QPSK_5_6:
837 case FEC_S2_8PSK_7_8:
838 case FEC_S2_QPSK_7_8:
841 case FEC_S2_8PSK_8_9:
842 case FEC_S2_QPSK_8_9:
845 case FEC_S2_8PSK_3_5:
846 case FEC_S2_QPSK_3_5:
849 case FEC_S2_8PSK_4_5:
850 case FEC_S2_QPSK_4_5:
853 case FEC_S2_8PSK_9_10:
854 case FEC_S2_QPSK_9_10:
859 PutToDict(dict, "fec_inner", tmp);
860 #if HAVE_DVB_API_VERSION >=3
861 PutToDict(dict, "modulation",
862 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ? "8PSK": "QPSK" );
863 if (parm_u_qpsk_fec_inner > FEC_AUTO)
865 switch(parm_inversion & 0xc)
867 default: // unknown rolloff
869 tmp = "ROLLOFF_0_35";
872 tmp = "ROLLOFF_0_25";
875 tmp = "ROLLOFF_0_20";
878 PutToDict(dict, "rolloff", tmp);
879 if (parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10)
881 switch(parm_inversion & 0x30)
886 case 0x10: // pilot on
889 case 0x20: // pilot auto
893 PutToDict(dict, "pilot", tmp);
900 PutToDict(dict, "modulation", "QPSK" );
903 PutToDict(dict, "system", tmp);
906 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
909 #if HAVE_DVB_API_VERSION < 3
910 PutToDict(dict, "frequency", parm_frequency);
912 PutToDict(dict, "frequency", parm_frequency/1000);
914 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
915 switch(parm_u_qam_fec_inner)
935 #if HAVE_DVB_API_VERSION >= 3
945 PutToDict(dict, "fec_inner", tmp);
946 switch(parm_u_qam_modulation)
968 PutToDict(dict, "modulation", tmp);
971 void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
974 PutToDict(dict, "frequency", parm_frequency);
975 switch (parm_u_ofdm_bandwidth)
977 case BANDWIDTH_8_MHZ:
978 tmp = "BANDWIDTH_8_MHZ";
980 case BANDWIDTH_7_MHZ:
981 tmp = "BANDWIDTH_7_MHZ";
983 case BANDWIDTH_6_MHZ:
984 tmp = "BANDWIDTH_6_MHZ";
988 tmp = "BANDWIDTH_AUTO";
991 PutToDict(dict, "bandwidth", tmp);
992 switch (parm_u_ofdm_code_rate_LP)
1014 PutToDict(dict, "code_rate_lp", tmp);
1015 switch (parm_u_ofdm_code_rate_HP)
1037 PutToDict(dict, "code_rate_hp", tmp);
1038 switch (parm_u_ofdm_constellation)
1054 PutToDict(dict, "constellation", tmp);
1055 switch (parm_u_ofdm_transmission_mode)
1057 case TRANSMISSION_MODE_2K:
1058 tmp = "TRANSMISSION_MODE_2K";
1060 case TRANSMISSION_MODE_8K:
1061 tmp = "TRANSMISSION_MODE_8K";
1064 case TRANSMISSION_MODE_AUTO:
1065 tmp = "TRANSMISSION_MODE_AUTO";
1068 PutToDict(dict, "transmission_mode", tmp);
1069 switch (parm_u_ofdm_guard_interval)
1071 case GUARD_INTERVAL_1_32:
1072 tmp = "GUARD_INTERVAL_1_32";
1074 case GUARD_INTERVAL_1_16:
1075 tmp = "GUARD_INTERVAL_1_16";
1077 case GUARD_INTERVAL_1_8:
1078 tmp = "GUARD_INTERVAL_1_8";
1080 case GUARD_INTERVAL_1_4:
1081 tmp = "GUARD_INTERVAL_1_4";
1084 case GUARD_INTERVAL_AUTO:
1085 tmp = "GUARD_INTERVAL_AUTO";
1088 PutToDict(dict, "guard_interval", tmp);
1089 switch (parm_u_ofdm_hierarchy_information)
1091 case HIERARCHY_NONE:
1092 tmp = "HIERARCHY_NONE";
1095 tmp = "HIERARCHY_1";
1098 tmp = "HIERARCHY_2";
1101 tmp = "HIERARCHY_4";
1104 case HIERARCHY_AUTO:
1105 tmp = "HIERARCHY_AUTO";
1108 PutToDict(dict, "hierarchy_information", tmp);
1111 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1113 if (dest && PyDict_Check(dest))
1115 const char *tmp = "UNKNOWN";
1136 PutToDict(dest, "tuner_state", tmp);
1137 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1138 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1139 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1140 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1141 int sigQualitydB = readFrontendData(signalQualitydB);
1142 if (sigQualitydB == 0x12345678) // not support yet
1144 ePyObject obj=Py_None;
1146 PutToDict(dest, "tuner_signal_quality_db", obj);
1149 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1150 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1154 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1156 if (m_fd != -1 && dest && PyDict_Check(dest))
1164 FRONTENDPARAMETERS front;
1165 if (!original && ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1166 eDebug("FE_GET_FRONTEND (%m)");
1169 const FRONTENDPARAMETERS &parm = original ? this->parm : front;
1170 const char *tmp = "INVERSION_AUTO";
1171 switch(parm_inversion)
1174 tmp = "INVERSION_ON";
1177 tmp = "INVERSION_OFF";
1183 PutToDict(dest, "inversion", tmp);
1188 fillDictWithSatelliteData(dest, original?parm:front, this);
1191 fillDictWithCableData(dest, original?parm:front);
1194 fillDictWithTerrestrialData(dest, original?parm:front);
1205 void eDVBFrontend::getFrontendData(ePyObject dest)
1207 if (dest && PyDict_Check(dest))
1210 PutToDict(dest, "tuner_number", m_dvbid);
1226 PutToDict(dest, "tuner_type", tmp);
1230 #ifndef FP_IOCTL_GET_ID
1231 #define FP_IOCTL_GET_ID 0
1233 int eDVBFrontend::readInputpower()
1235 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1237 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1238 FILE *f=fopen(proc_name, "r");
1241 if (fscanf(f, "%08x", &power) != 1)
1242 eDebug("read %s failed!! (%m)", proc_name);
1244 eDebug("%s is %d\n", proc_name, power);
1249 // open front prozessor
1250 int fp=::open("/dev/dbox/fp0", O_RDWR);
1253 eDebug("couldn't open fp");
1256 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1257 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1259 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1268 bool eDVBFrontend::setSecSequencePos(int steps)
1270 eDebug("set sequence pos %d", steps);
1275 if (m_sec_sequence.current() != m_sec_sequence.end())
1276 ++m_sec_sequence.current();
1281 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1282 --m_sec_sequence.current();
1288 void eDVBFrontend::setRotorData(int pos, int cmd)
1290 m_data[ROTOR_CMD] = cmd;
1291 m_data[ROTOR_POS] = pos;
1292 if ( m_data[SATPOS_DEPENDS_PTR] != -1 )
1294 eDVBRegisteredFrontend *satpos_depends_to_fe = (eDVBRegisteredFrontend*) m_data[SATPOS_DEPENDS_PTR];
1295 satpos_depends_to_fe->m_frontend->m_data[ROTOR_CMD] = cmd;
1296 satpos_depends_to_fe->m_frontend->m_data[ROTOR_POS] = pos;
1300 eDVBRegisteredFrontend *next = (eDVBRegisteredFrontend *)m_data[LINKED_NEXT_PTR];
1301 while ( (long)next != -1 )
1303 next->m_frontend->m_data[ROTOR_CMD] = cmd;
1304 next->m_frontend->m_data[ROTOR_POS] = pos;
1305 next = (eDVBRegisteredFrontend *)next->m_frontend->m_data[LINKED_NEXT_PTR];
1307 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)m_data[LINKED_PREV_PTR];
1308 while ( (long)prev != -1 )
1310 prev->m_frontend->m_data[ROTOR_CMD] = cmd;
1311 prev->m_frontend->m_data[ROTOR_POS] = pos;
1312 prev = (eDVBRegisteredFrontend *)prev->m_frontend->m_data[LINKED_PREV_PTR];
1317 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1320 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1322 // eDebug("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1323 switch (m_sec_sequence.current()->cmd)
1325 case eSecCommand::SLEEP:
1326 delay = m_sec_sequence.current()++->msec;
1327 eDebug("[SEC] sleep %dms", delay);
1329 case eSecCommand::GOTO:
1330 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1331 ++m_sec_sequence.current();
1333 case eSecCommand::SET_VOLTAGE:
1335 int voltage = m_sec_sequence.current()++->voltage;
1336 eDebug("[SEC] setVoltage %d", voltage);
1337 setVoltage(voltage);
1340 case eSecCommand::IF_VOLTAGE_GOTO:
1342 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1343 if ( compare.voltage == m_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1345 ++m_sec_sequence.current();
1348 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1350 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1351 if ( compare.voltage != m_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1353 ++m_sec_sequence.current();
1356 case eSecCommand::IF_TONE_GOTO:
1358 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1359 if ( compare.tone == m_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1361 ++m_sec_sequence.current();
1364 case eSecCommand::IF_NOT_TONE_GOTO:
1366 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1367 if ( compare.tone != m_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1369 ++m_sec_sequence.current();
1372 case eSecCommand::SET_TONE:
1373 eDebug("[SEC] setTone %d", m_sec_sequence.current()->tone);
1374 setTone(m_sec_sequence.current()++->tone);
1376 case eSecCommand::SEND_DISEQC:
1377 sendDiseqc(m_sec_sequence.current()->diseqc);
1378 eDebugNoNewLine("[SEC] sendDiseqc: ");
1379 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1380 eDebugNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1382 ++m_sec_sequence.current();
1384 case eSecCommand::SEND_TONEBURST:
1385 eDebug("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1386 sendToneburst(m_sec_sequence.current()++->toneburst);
1388 case eSecCommand::SET_FRONTEND:
1389 eDebug("[SEC] setFrontend");
1391 ++m_sec_sequence.current();
1393 case eSecCommand::START_TUNE_TIMEOUT:
1395 m_timeout->start(m_sec_sequence.current()->timeout, 1);
1396 ++m_sec_sequence.current();
1399 case eSecCommand::SET_TIMEOUT:
1400 m_timeoutCount = m_sec_sequence.current()++->val;
1401 eDebug("[SEC] set timeout %d", m_timeoutCount);
1403 case eSecCommand::IF_TIMEOUT_GOTO:
1404 if (!m_timeoutCount)
1406 eDebug("[SEC] rotor timout");
1407 m_sec->setRotorMoving(false);
1408 setSecSequencePos(m_sec_sequence.current()->steps);
1411 ++m_sec_sequence.current();
1413 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1415 int idx = m_sec_sequence.current()++->val;
1416 if ( idx == 0 || idx == 1 )
1418 m_idleInputpower[idx] = readInputpower();
1419 eDebug("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1422 eDebug("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1425 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1427 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1428 int idx = compare.val;
1429 if ( idx == 0 || idx == 1 )
1431 int idle = readInputpower();
1432 int diff = abs(idle-m_idleInputpower[idx]);
1435 eDebug("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1436 setSecSequencePos(compare.steps);
1440 ++m_sec_sequence.current();
1443 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1445 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1446 if (readFrontendData(locked))
1448 eDebug("[SEC] locked step %d ok", cmd.okcount);
1450 if (cmd.okcount > 12)
1452 eDebug("ok > 12 .. goto %d\n",m_sec_sequence.current()->steps);
1453 setSecSequencePos(cmd.steps);
1459 eDebug("[SEC] rotor locked step %d failed", cmd.okcount);
1461 if (!m_timeoutCount && m_retryCount > 0)
1465 ++m_sec_sequence.current();
1468 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1469 m_runningInputpower = readInputpower();
1470 eDebug("[SEC] runningInputpower is %d", m_runningInputpower);
1471 ++m_sec_sequence.current();
1473 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1475 int idleInputpower = m_idleInputpower[ (m_data[CUR_VOLTAGE]&1) ? 0 : 1];
1476 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1477 const char *txt = cmd.direction ? "running" : "stopped";
1478 eDebug("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1480 m_runningInputpower,
1483 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1484 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1487 eDebug("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1488 if ( cmd.okcount > 6 )
1490 m_sec->setRotorMoving(cmd.direction);
1491 eDebug("[SEC] rotor is %s", txt);
1492 if (setSecSequencePos(cmd.steps))
1498 eDebug("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1500 if (!m_timeoutCount && m_retryCount > 0)
1504 ++m_sec_sequence.current();
1507 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1508 if (m_data[ROTOR_CMD] != -1 && m_data[ROTOR_POS] != -1)
1509 setSecSequencePos(m_sec_sequence.current()->steps);
1511 ++m_sec_sequence.current();
1513 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1514 eDebug("[SEC] invalidate current rotorparams");
1515 setRotorData(-1,-1);
1516 ++m_sec_sequence.current();
1518 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1519 setRotorData(m_data[NEW_ROTOR_POS], m_data[NEW_ROTOR_CMD]);
1520 eDebug("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, m_data[ROTOR_CMD], m_data[ROTOR_POS]);
1521 ++m_sec_sequence.current();
1523 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1524 m_retryCount = m_sec_sequence.current()++->val;
1525 eDebug("[SEC] set rotor retries %d", m_retryCount);
1527 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1530 eDebug("[SEC] no more rotor retrys");
1531 setSecSequencePos(m_sec_sequence.current()->steps);
1534 ++m_sec_sequence.current();
1536 case eSecCommand::SET_POWER_LIMITING_MODE:
1538 if (m_need_rotor_workaround)
1542 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1544 sprintf(dev, "/dev/i2c/%d", m_slotid);
1545 else if (m_slotid == 2)
1546 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1547 else if (m_slotid == 3)
1548 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1549 int fd = ::open(dev, O_RDWR);
1551 unsigned char data[2];
1552 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1553 if(::read(fd, data, 1) != 1)
1554 eDebug("[SEC] error read lnbp (%m)");
1555 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1557 data[0] |= 0x80; // enable static current limiting
1558 eDebug("[SEC] set static current limiting");
1562 data[0] &= ~0x80; // enable dynamic current limiting
1563 eDebug("[SEC] set dynamic current limiting");
1565 if(::write(fd, data, 1) != 1)
1566 eDebug("[SEC] error write lnbp (%m)");
1569 ++m_sec_sequence.current();
1573 eDebug("[SEC] unhandled sec command %d",
1574 ++m_sec_sequence.current()->cmd);
1575 ++m_sec_sequence.current();
1577 m_tuneTimer->start(delay,true);
1581 void eDVBFrontend::setFrontend()
1583 eDebug("setting frontend %d", m_dvbid);
1586 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1588 perror("FE_SET_FRONTEND failed");
1593 RESULT eDVBFrontend::getFrontendType(int &t)
1601 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1606 eWarning("no SEC module active!");
1609 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1612 eDebug("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1615 feparm.polarisation,
1619 feparm.orbital_position);
1620 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1621 switch (feparm.inversion)
1623 case eDVBFrontendParametersSatellite::Inversion::On:
1624 parm_inversion = INVERSION_ON;
1626 case eDVBFrontendParametersSatellite::Inversion::Off:
1627 parm_inversion = INVERSION_OFF;
1630 case eDVBFrontendParametersSatellite::Inversion::Unknown:
1631 parm_inversion = INVERSION_AUTO;
1634 if (feparm.system == eDVBFrontendParametersSatellite::System::DVB_S)
1637 case eDVBFrontendParametersSatellite::FEC::fNone:
1638 parm_u_qpsk_fec_inner = FEC_NONE;
1640 case eDVBFrontendParametersSatellite::FEC::f1_2:
1641 parm_u_qpsk_fec_inner = FEC_1_2;
1643 case eDVBFrontendParametersSatellite::FEC::f2_3:
1644 parm_u_qpsk_fec_inner = FEC_2_3;
1646 case eDVBFrontendParametersSatellite::FEC::f3_4:
1647 parm_u_qpsk_fec_inner = FEC_3_4;
1649 case eDVBFrontendParametersSatellite::FEC::f5_6:
1650 parm_u_qpsk_fec_inner = FEC_5_6;
1652 case eDVBFrontendParametersSatellite::FEC::f7_8:
1653 parm_u_qpsk_fec_inner = FEC_7_8;
1656 eDebug("no valid fec for DVB-S set.. assume auto");
1657 case eDVBFrontendParametersSatellite::FEC::fAuto:
1658 parm_u_qpsk_fec_inner = FEC_AUTO;
1661 #if HAVE_DVB_API_VERSION >= 3
1666 case eDVBFrontendParametersSatellite::FEC::f1_2:
1667 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1669 case eDVBFrontendParametersSatellite::FEC::f2_3:
1670 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1672 case eDVBFrontendParametersSatellite::FEC::f3_4:
1673 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1675 case eDVBFrontendParametersSatellite::FEC::f3_5:
1676 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1678 case eDVBFrontendParametersSatellite::FEC::f4_5:
1679 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1681 case eDVBFrontendParametersSatellite::FEC::f5_6:
1682 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1684 case eDVBFrontendParametersSatellite::FEC::f7_8:
1685 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1687 case eDVBFrontendParametersSatellite::FEC::f8_9:
1688 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1690 case eDVBFrontendParametersSatellite::FEC::f9_10:
1691 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1694 eDebug("no valid fec for DVB-S2 set.. abort !!");
1697 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1698 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK) {
1699 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1700 // 8PSK fec driver values are decimal 9 bigger
1701 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1705 // FIXME !!! get frequency range from tuner
1706 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1708 eDebug("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1711 eDebug("tuning to %d mhz", parm_frequency/1000);
1716 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1718 #if HAVE_DVB_API_VERSION < 3
1719 parm_frequency = feparm.frequency;
1721 parm_frequency = feparm.frequency * 1000;
1723 parm_u_qam_symbol_rate = feparm.symbol_rate;
1724 switch (feparm.modulation)
1726 case eDVBFrontendParametersCable::Modulation::QAM16:
1727 parm_u_qam_modulation = QAM_16;
1729 case eDVBFrontendParametersCable::Modulation::QAM32:
1730 parm_u_qam_modulation = QAM_32;
1732 case eDVBFrontendParametersCable::Modulation::QAM64:
1733 parm_u_qam_modulation = QAM_64;
1735 case eDVBFrontendParametersCable::Modulation::QAM128:
1736 parm_u_qam_modulation = QAM_128;
1738 case eDVBFrontendParametersCable::Modulation::QAM256:
1739 parm_u_qam_modulation = QAM_256;
1742 case eDVBFrontendParametersCable::Modulation::Auto:
1743 parm_u_qam_modulation = QAM_AUTO;
1746 switch (feparm.inversion)
1748 case eDVBFrontendParametersCable::Inversion::On:
1749 parm_inversion = INVERSION_ON;
1751 case eDVBFrontendParametersCable::Inversion::Off:
1752 parm_inversion = INVERSION_OFF;
1755 case eDVBFrontendParametersCable::Inversion::Unknown:
1756 parm_inversion = INVERSION_AUTO;
1759 switch (feparm.fec_inner)
1761 case eDVBFrontendParametersCable::FEC::fNone:
1762 parm_u_qam_fec_inner = FEC_NONE;
1764 case eDVBFrontendParametersCable::FEC::f1_2:
1765 parm_u_qam_fec_inner = FEC_1_2;
1767 case eDVBFrontendParametersCable::FEC::f2_3:
1768 parm_u_qam_fec_inner = FEC_2_3;
1770 case eDVBFrontendParametersCable::FEC::f3_4:
1771 parm_u_qam_fec_inner = FEC_3_4;
1773 case eDVBFrontendParametersCable::FEC::f5_6:
1774 parm_u_qam_fec_inner = FEC_5_6;
1776 case eDVBFrontendParametersCable::FEC::f7_8:
1777 parm_u_qam_fec_inner = FEC_7_8;
1779 #if HAVE_DVB_API_VERSION >= 3
1780 case eDVBFrontendParametersCable::FEC::f8_9:
1781 parm_u_qam_fec_inner = FEC_8_9;
1785 case eDVBFrontendParametersCable::FEC::fAuto:
1786 parm_u_qam_fec_inner = FEC_AUTO;
1789 eDebug("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
1790 parm_frequency/1000,
1791 parm_u_qam_symbol_rate,
1792 parm_u_qam_fec_inner,
1793 parm_u_qam_modulation,
1798 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
1800 parm_frequency = feparm.frequency;
1802 switch (feparm.bandwidth)
1804 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
1805 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
1807 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
1808 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
1810 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
1811 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
1814 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
1815 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
1818 switch (feparm.code_rate_LP)
1820 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1821 parm_u_ofdm_code_rate_LP = FEC_1_2;
1823 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1824 parm_u_ofdm_code_rate_LP = FEC_2_3;
1826 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1827 parm_u_ofdm_code_rate_LP = FEC_3_4;
1829 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1830 parm_u_ofdm_code_rate_LP = FEC_5_6;
1832 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1833 parm_u_ofdm_code_rate_LP = FEC_7_8;
1836 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1837 parm_u_ofdm_code_rate_LP = FEC_AUTO;
1840 switch (feparm.code_rate_HP)
1842 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1843 parm_u_ofdm_code_rate_HP = FEC_1_2;
1845 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1846 parm_u_ofdm_code_rate_HP = FEC_2_3;
1848 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1849 parm_u_ofdm_code_rate_HP = FEC_3_4;
1851 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1852 parm_u_ofdm_code_rate_HP = FEC_5_6;
1854 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1855 parm_u_ofdm_code_rate_HP = FEC_7_8;
1858 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1859 parm_u_ofdm_code_rate_HP = FEC_AUTO;
1862 switch (feparm.modulation)
1864 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
1865 parm_u_ofdm_constellation = QPSK;
1867 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
1868 parm_u_ofdm_constellation = QAM_16;
1870 case eDVBFrontendParametersTerrestrial::Modulation::QAM64:
1871 parm_u_ofdm_constellation = QAM_64;
1874 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
1875 parm_u_ofdm_constellation = QAM_AUTO;
1878 switch (feparm.transmission_mode)
1880 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
1881 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
1883 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
1884 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
1887 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
1888 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
1891 switch (feparm.guard_interval)
1893 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32:
1894 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
1896 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16:
1897 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
1899 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8:
1900 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
1902 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4:
1903 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
1906 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto:
1907 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
1910 switch (feparm.hierarchy)
1912 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone:
1913 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
1915 case eDVBFrontendParametersTerrestrial::Hierarchy::H1:
1916 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
1918 case eDVBFrontendParametersTerrestrial::Hierarchy::H2:
1919 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
1921 case eDVBFrontendParametersTerrestrial::Hierarchy::H4:
1922 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
1925 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto:
1926 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
1929 switch (feparm.inversion)
1931 case eDVBFrontendParametersTerrestrial::Inversion::On:
1932 parm_inversion = INVERSION_ON;
1934 case eDVBFrontendParametersTerrestrial::Inversion::Off:
1935 parm_inversion = INVERSION_OFF;
1938 case eDVBFrontendParametersTerrestrial::Inversion::Unknown:
1939 parm_inversion = INVERSION_AUTO;
1945 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
1947 unsigned int timeout = 5000;
1948 eDebug("(%d)tune", m_dvbid);
1956 eDebug("no frontend device opened... do not try to tune !!!");
1968 m_sec_sequence.clear();
1970 where.calcLockTimeout(timeout);
1976 eDVBFrontendParametersSatellite feparm;
1977 if (where.getDVBS(feparm))
1979 eDebug("no dvbs data!");
1983 m_sec->setRotorMoving(false);
1984 res=prepare_sat(feparm, timeout);
1992 eDVBFrontendParametersCable feparm;
1993 if (where.getDVBC(feparm))
1998 res=prepare_cable(feparm);
2002 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2003 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2008 eDVBFrontendParametersTerrestrial feparm;
2009 if (where.getDVBT(feparm))
2011 eDebug("no -T data");
2015 res=prepare_terrestrial(feparm);
2019 std::string enable_5V;
2020 char configStr[255];
2021 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2022 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2023 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2024 if (enable_5V == "True")
2025 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2027 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2028 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2034 m_tuneTimer->start(0,true);
2035 m_sec_sequence.current() = m_sec_sequence.begin();
2037 if (m_state != stateTuning)
2040 m_state = stateTuning;
2041 m_stateChanged(this);
2047 m_tuneTimer->stop();
2051 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2053 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2057 RESULT eDVBFrontend::setVoltage(int voltage)
2059 if (m_type == feCable)
2061 #if HAVE_DVB_API_VERSION < 3
2064 bool increased=false;
2065 fe_sec_voltage_t vlt;
2067 m_data[CUR_VOLTAGE]=voltage;
2071 for (int i=0; i < 3; ++i) // reset diseqc
2073 vlt = SEC_VOLTAGE_OFF;
2076 #if HAVE_DVB_API_VERSION < 3
2077 vlt = SEC_VOLTAGE_13_5;
2083 vlt = SEC_VOLTAGE_13;
2086 #if HAVE_DVB_API_VERSION < 3
2087 vlt = SEC_VOLTAGE_18_5;
2093 vlt = SEC_VOLTAGE_18;
2098 #if HAVE_DVB_API_VERSION < 3
2099 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2101 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2102 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2103 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2107 RESULT eDVBFrontend::getState(int &state)
2113 RESULT eDVBFrontend::setTone(int t)
2115 if (m_type != feSatellite)
2117 #if HAVE_DVB_API_VERSION < 3
2120 fe_sec_tone_mode_t tone;
2129 tone = SEC_TONE_OFF;
2134 #if HAVE_DVB_API_VERSION < 3
2135 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2137 return ::ioctl(m_fd, FE_SET_TONE, tone);
2141 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2142 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2145 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2147 #if HAVE_DVB_API_VERSION < 3
2148 struct secCommand cmd;
2149 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2150 cmd.u.diseqc.cmdtype = diseqc.data[0];
2151 cmd.u.diseqc.addr = diseqc.data[1];
2152 cmd.u.diseqc.cmd = diseqc.data[2];
2153 cmd.u.diseqc.numParams = diseqc.len-3;
2154 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2155 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2157 struct dvb_diseqc_master_cmd cmd;
2158 memcpy(cmd.msg, diseqc.data, diseqc.len);
2159 cmd.msg_len = diseqc.len;
2160 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2166 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2167 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2169 RESULT eDVBFrontend::sendToneburst(int burst)
2171 #if HAVE_DVB_API_VERSION < 3
2172 secMiniCmd cmd = SEC_MINI_NONE;
2174 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2176 if ( burst == eDVBSatelliteDiseqcParameters::A )
2178 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2180 #if HAVE_DVB_API_VERSION < 3
2181 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2184 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2190 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2196 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2198 m_sec_sequence = list;
2202 RESULT eDVBFrontend::getData(int num, long &data)
2204 if ( num < NUM_DATA_ENTRIES )
2212 RESULT eDVBFrontend::setData(int num, long val)
2214 if ( num < NUM_DATA_ENTRIES )
2222 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2225 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2228 if (m_type == eDVBFrontend::feSatellite)
2231 eDVBFrontendParametersSatellite sat_parm;
2232 int ret = feparm->getDVBS(sat_parm);
2234 if (sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S2 && !m_can_handle_dvbs2)
2236 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2237 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S && m_can_handle_dvbs2)
2240 else if (m_type == eDVBFrontend::feCable)
2241 return 2; // more prio for cable frontends
2245 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2247 ePyObject Id, Descr, Enabled;
2248 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 3)
2250 Id = PyTuple_GET_ITEM(obj, 0);
2251 Descr = PyTuple_GET_ITEM(obj, 1);
2252 Enabled = PyTuple_GET_ITEM(obj, 2);
2253 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled))
2255 strcpy(m_description, PyString_AS_STRING(Descr));
2256 m_slotid = PyInt_AsLong(Id);
2257 m_enabled = Enabled == Py_True;
2258 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2259 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2260 !!strstr(m_description, "Alps BSBE2") ||
2261 !!strstr(m_description, "Alps -S");
2262 m_can_handle_dvbs2 = !!strstr(m_description, "Alps BSBE2") || !!strstr(m_description, "bcm4501");
2263 eDebug("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s",
2264 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No" );
2267 PyErr_SetString(PyExc_StandardError,
2268 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");