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 orbital_position = ((descriptor.getOrbitalPosition() >> 12) & 0xF) * 1000;
129 orbital_position += ((descriptor.getOrbitalPosition() >> 8) & 0xF) * 100;
130 orbital_position += ((descriptor.getOrbitalPosition() >> 4) & 0xF) * 10;
131 orbital_position += ((descriptor.getOrbitalPosition()) & 0xF);
132 if (orbital_position && (!descriptor.getWestEastFlag()))
133 orbital_position = 3600 - orbital_position;
134 system = descriptor.getModulationSystem();
135 modulation = descriptor.getModulation();
136 if (system == System::DVB_S && modulation == Modulation::M8PSK)
138 eDebug("satellite_delivery_descriptor non valid modulation type.. force QPSK");
141 roll_off = descriptor.getRollOff();
142 if (system == System::DVB_S2)
144 eDebug("SAT DVB-S2 freq %d, %s, pos %d, sr %d, fec %d, modulation %d, roll_off %d",
146 polarisation ? "hor" : "vert",
154 eDebug("SAT DVB-S freq %d, %s, pos %d, sr %d, fec %d",
156 polarisation ? "hor" : "vert",
162 void eDVBFrontendParametersCable::set(const CableDeliverySystemDescriptor &descriptor)
164 frequency = descriptor.getFrequency() / 10;
165 symbol_rate = descriptor.getSymbolRate() * 100;
166 fec_inner = descriptor.getFecInner();
167 if ( fec_inner == 0xF )
168 fec_inner = FEC::fNone;
169 modulation = descriptor.getModulation();
170 if ( modulation > 0x5 )
171 modulation = Modulation::Auto;
172 inversion = Inversion::Unknown;
173 eDebug("Cable freq %d, mod %d, sr %d, fec %d",
175 modulation, symbol_rate, fec_inner);
178 void eDVBFrontendParametersTerrestrial::set(const TerrestrialDeliverySystemDescriptor &descriptor)
180 frequency = descriptor.getCentreFrequency() * 10;
181 bandwidth = descriptor.getBandwidth();
182 if ( bandwidth > 2 ) // 5Mhz forced to auto
183 bandwidth = Bandwidth::BwAuto;
184 code_rate_HP = descriptor.getCodeRateHpStream();
185 if (code_rate_HP > 4)
186 code_rate_HP = FEC::fAuto;
187 code_rate_LP = descriptor.getCodeRateLpStream();
188 if (code_rate_LP > 4)
189 code_rate_LP = FEC::fAuto;
190 transmission_mode = descriptor.getTransmissionMode();
191 if (transmission_mode > 1) // TM4k forced to auto
192 transmission_mode = TransmissionMode::TMAuto;
193 guard_interval = descriptor.getGuardInterval();
194 if (guard_interval > 3)
195 guard_interval = GuardInterval::GI_Auto;
196 hierarchy = descriptor.getHierarchyInformation()&3;
197 modulation = descriptor.getConstellation();
199 modulation = Modulation::Auto;
200 inversion = Inversion::Unknown;
201 eDebug("Terr freq %d, bw %d, cr_hp %d, cr_lp %d, tm_mode %d, guard %d, hierarchy %d, const %d",
202 frequency, bandwidth, code_rate_HP, code_rate_LP, transmission_mode,
203 guard_interval, hierarchy, modulation);
206 eDVBFrontendParameters::eDVBFrontendParameters(): m_type(-1)
210 DEFINE_REF(eDVBFrontendParameters);
212 RESULT eDVBFrontendParameters::getSystem(int &t) const
220 RESULT eDVBFrontendParameters::getDVBS(eDVBFrontendParametersSatellite &p) const
222 if (m_type != iDVBFrontend::feSatellite)
228 RESULT eDVBFrontendParameters::getDVBC(eDVBFrontendParametersCable &p) const
230 if (m_type != iDVBFrontend::feCable)
236 RESULT eDVBFrontendParameters::getDVBT(eDVBFrontendParametersTerrestrial &p) const
238 if (m_type != iDVBFrontend::feTerrestrial)
244 RESULT eDVBFrontendParameters::setDVBS(const eDVBFrontendParametersSatellite &p, bool no_rotor_command_on_tune)
247 sat.no_rotor_command_on_tune = no_rotor_command_on_tune;
248 m_type = iDVBFrontend::feSatellite;
252 RESULT eDVBFrontendParameters::setDVBC(const eDVBFrontendParametersCable &p)
255 m_type = iDVBFrontend::feCable;
259 RESULT eDVBFrontendParameters::setDVBT(const eDVBFrontendParametersTerrestrial &p)
262 m_type = iDVBFrontend::feTerrestrial;
266 RESULT eDVBFrontendParameters::calculateDifference(const iDVBFrontendParameters *parm, int &diff, bool exact) const
271 if (parm->getSystem(type))
275 diff = 1<<30; // big difference
281 case iDVBFrontend::feSatellite:
283 eDVBFrontendParametersSatellite osat;
284 if (parm->getDVBS(osat))
287 if (sat.orbital_position != osat.orbital_position)
289 else if (sat.polarisation != osat.polarisation)
291 else if (exact && sat.fec != osat.fec && sat.fec != eDVBFrontendParametersSatellite::FEC::fAuto && osat.fec != eDVBFrontendParametersSatellite::FEC::fAuto)
293 else if (exact && sat.modulation != osat.modulation && sat.modulation != eDVBFrontendParametersSatellite::Modulation::Auto && osat.modulation != eDVBFrontendParametersSatellite::Modulation::Auto)
297 diff = abs(sat.frequency - osat.frequency);
298 diff += abs(sat.symbol_rate - osat.symbol_rate);
302 case iDVBFrontend::feCable:
303 eDVBFrontendParametersCable ocable;
304 if (parm->getDVBC(ocable))
307 if (exact && cable.modulation != ocable.modulation
308 && cable.modulation != eDVBFrontendParametersCable::Modulation::Auto
309 && ocable.modulation != eDVBFrontendParametersCable::Modulation::Auto)
311 else if (exact && cable.fec_inner != ocable.fec_inner && cable.fec_inner != eDVBFrontendParametersCable::FEC::fAuto && ocable.fec_inner != eDVBFrontendParametersCable::FEC::fAuto)
315 diff = abs(cable.frequency - ocable.frequency);
316 diff += abs(cable.symbol_rate - ocable.symbol_rate);
319 case iDVBFrontend::feTerrestrial:
320 eDVBFrontendParametersTerrestrial oterrestrial;
321 if (parm->getDVBT(oterrestrial))
325 if (exact && oterrestrial.bandwidth != terrestrial.bandwidth &&
326 oterrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto &&
327 terrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto)
329 else if (exact && oterrestrial.modulation != terrestrial.modulation &&
330 oterrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation::Auto &&
331 terrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation::Auto)
333 else if (exact && oterrestrial.transmission_mode != terrestrial.transmission_mode &&
334 oterrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto &&
335 terrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto)
337 else if (exact && oterrestrial.guard_interval != terrestrial.guard_interval &&
338 oterrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto &&
339 terrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto)
341 else if (exact && oterrestrial.hierarchy != terrestrial.hierarchy &&
342 oterrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy::HAuto &&
343 terrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy::HAuto)
345 else if (exact && oterrestrial.code_rate_LP != terrestrial.code_rate_LP &&
346 oterrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC::fAuto &&
347 terrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC::fAuto)
349 else if (exact && oterrestrial.code_rate_HP != terrestrial.code_rate_HP &&
350 oterrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC::fAuto &&
351 terrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC::fAuto)
354 diff = abs(terrestrial.frequency - oterrestrial.frequency);
362 RESULT eDVBFrontendParameters::getHash(unsigned long &hash) const
366 case iDVBFrontend::feSatellite:
368 hash = (sat.orbital_position << 16);
369 hash |= ((sat.frequency/1000)&0xFFFF)|((sat.polarisation&1) << 15);
372 case iDVBFrontend::feCable:
374 hash |= (cable.frequency/1000)&0xFFFF;
376 case iDVBFrontend::feTerrestrial:
378 hash |= (terrestrial.frequency/1000)&0xFFFF;
385 RESULT eDVBFrontendParameters::calcLockTimeout(unsigned int &timeout) const
389 case iDVBFrontend::feSatellite:
391 /* high symbol rate transponders tune faster, due to
392 requiring less zigzag and giving more symbols faster.
394 5s are definitely not enough on really low SR when
395 zigzag has to find the exact frequency first.
397 if (sat.symbol_rate > 20000000)
399 else if (sat.symbol_rate > 10000000)
405 case iDVBFrontend::feCable:
408 case iDVBFrontend::feTerrestrial:
416 DEFINE_REF(eDVBFrontend);
418 int eDVBFrontend::PriorityOrder=0;
420 eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok)
421 :m_enabled(false), m_type(-1), m_dvbid(fe), m_slotid(fe)
422 ,m_fd(-1), m_need_rotor_workaround(false), m_sn(0), m_timeout(0), m_tuneTimer(0)
423 #if HAVE_DVB_API_VERSION < 3
427 #if HAVE_DVB_API_VERSION < 3
428 sprintf(m_filename, "/dev/dvb/card%d/frontend%d", adap, fe);
429 sprintf(m_sec_filename, "/dev/dvb/card%d/sec%d", adap, fe);
431 sprintf(m_filename, "/dev/dvb/adapter%d/frontend%d", adap, fe);
433 m_timeout = new eTimer(eApp);
434 CONNECT(m_timeout->timeout, eDVBFrontend::timeout);
436 m_tuneTimer = new eTimer(eApp);
437 CONNECT(m_tuneTimer->timeout, eDVBFrontend::tuneLoop);
439 for (int i=0; i<eDVBFrontend::NUM_DATA_ENTRIES; ++i)
442 m_idleInputpower[0]=m_idleInputpower[1]=0;
444 ok = !openFrontend();
448 int eDVBFrontend::openFrontend()
451 return -1; // already opened
456 #if HAVE_DVB_API_VERSION < 3
457 FrontendInfo fe_info;
459 dvb_frontend_info fe_info;
461 eDebug("opening frontend %d", m_dvbid);
464 m_fd = ::open(m_filename, O_RDWR|O_NONBLOCK);
467 eWarning("failed! (%s) %m", m_filename);
472 eWarning("frontend %d already opened", m_dvbid);
475 if (::ioctl(m_fd, FE_GET_INFO, &fe_info) < 0)
477 eWarning("ioctl FE_GET_INFO failed");
483 switch (fe_info.type)
486 m_type = iDVBFrontend::feSatellite;
489 m_type = iDVBFrontend::feCable;
492 m_type = iDVBFrontend::feTerrestrial;
495 eWarning("unknown frontend type.");
500 eDebug("detected %s frontend", "satellite\0cable\0 terrestrial"+fe_info.type*10);
503 #if HAVE_DVB_API_VERSION < 3
504 if (m_type == iDVBFrontend::feSatellite)
508 m_secfd = ::open(m_sec_filename, O_RDWR);
511 eWarning("failed! (%s) %m", m_sec_filename);
518 eWarning("sec %d already opened", m_dvbid);
522 setTone(iDVBFrontend::toneOff);
523 setVoltage(iDVBFrontend::voltageOff);
525 m_sn = new eSocketNotifier(eApp, m_fd, eSocketNotifier::Read);
526 CONNECT(m_sn->activated, eDVBFrontend::feEvent);
531 int eDVBFrontend::closeFrontend()
533 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)m_data[LINKED_NEXT_PTR];
534 while (linked_fe != (eDVBRegisteredFrontend*)-1)
536 if (linked_fe->m_inuse)
538 eDebug("dont close frontend %d until the linked frontend %d in slot %d is still in use",
539 m_dvbid, linked_fe->m_frontend->getDVBID(), linked_fe->m_frontend->getSlotID());
542 linked_fe->m_frontend->getData(LINKED_NEXT_PTR, (long&)linked_fe);
546 eDebug("close frontend %d", m_dvbid);
548 setTone(iDVBFrontend::toneOff);
549 setVoltage(iDVBFrontend::voltageOff);
551 m_sec->setRotorMoving(false);
555 eWarning("couldnt close frontend %d", m_dvbid);
556 m_data[CSW] = m_data[UCSW] = m_data[TONEBURST] = -1;
558 #if HAVE_DVB_API_VERSION < 3
561 if (!::close(m_secfd))
564 eWarning("couldnt close sec %d", m_dvbid);
573 eDVBFrontend::~eDVBFrontend()
580 void eDVBFrontend::feEvent(int w)
584 #if HAVE_DVB_API_VERSION < 3
587 dvb_frontend_event event;
591 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
593 if (res && (errno == EAGAIN))
598 eWarning("FE_GET_EVENT failed! %m");
605 #if HAVE_DVB_API_VERSION < 3
606 if (event.type == FE_COMPLETION_EV)
608 eDebug("(%d)fe event: status %x, inversion %s", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off");
609 if (event.status & FE_HAS_LOCK)
619 eDebug("stateLostLock");
620 state = stateLostLock;
621 m_data[CSW] = m_data[UCSW] = m_data[TONEBURST] = -1; // reset diseqc
624 if (m_state != state)
627 m_stateChanged(this);
632 void eDVBFrontend::timeout()
635 if (m_state == stateTuning)
637 m_state = stateFailed;
638 m_stateChanged(this);
642 int eDVBFrontend::readFrontendData(int type)
649 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
650 eDebug("FE_READ_BER failed (%m)");
656 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
657 eDebug("FE_READ_SNR failed (%m)");
660 case signalQualitydB: /* this will move into the driver */
663 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
664 eDebug("FE_READ_SNR failed (%m)");
665 if (!strcmp(m_description, "BCM4501 (internal)"))
667 unsigned int SDS_SNRE = snr << 16;
669 static float SNR_COEFF[6] = {
672 197418.0 / 4194304.0,
673 -2602183.0 / 4194304.0,
674 20377212.0 / 4194304.0,
675 -37791203.0 / 4194304.0,
678 float fval1, fval2, snr_in_db;
680 fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0));
681 fval2 = pow(10.0, fval1)-1;
682 fval1 = 10.0 * log10(fval2);
686 fval2 = SNR_COEFF[0];
690 fval2 += SNR_COEFF[i];
696 return (int)(snr_in_db * 100.0);
698 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
699 !strcmp(m_description, "Alps -S") ||
700 !strcmp(m_description, "Philips -S") ||
701 !strcmp(m_description, "LG -S") )
703 float snr_in_db=(snr-39075)/1764.7;
704 return (int)(snr_in_db * 100.0);
705 } else if (!strcmp(m_description, "Alps BSBE2"))
707 return (int)((snr >> 7) * 10.0);
709 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
715 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
716 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
721 #if HAVE_DVB_API_VERSION < 3
722 FrontendStatus status=0;
726 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
727 eDebug("FE_READ_STATUS failed (%m)");
728 return !!(status&FE_HAS_LOCK);
732 #if HAVE_DVB_API_VERSION < 3
733 FrontendStatus status=0;
737 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
738 eDebug("FE_READ_STATUS failed (%m)");
739 return !!(status&FE_HAS_SYNC);
747 void PutToDict(ePyObject &dict, const char*key, long value)
749 ePyObject item = PyInt_FromLong(value);
752 if (PyDict_SetItemString(dict, key, item))
753 eDebug("put %s to dict failed", key);
757 eDebug("could not create PyObject for %s", key);
760 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
764 if (PyDict_SetItemString(dict, key, item))
765 eDebug("put %s to dict failed", key);
769 eDebug("invalid PyObject for %s", key);
772 void PutToDict(ePyObject &dict, const char*key, const char *value)
774 ePyObject item = PyString_FromString(value);
777 if (PyDict_SetItemString(dict, key, item))
778 eDebug("put %s to dict failed", key);
782 eDebug("could not create PyObject for %s", key);
785 void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, eDVBFrontend *fe)
790 fe->getData(eDVBFrontend::CSW, csw);
791 fe->getData(eDVBFrontend::FREQ_OFFSET, freq_offset);
792 int frequency = parm_frequency + freq_offset;
793 PutToDict(dict, "frequency", frequency);
794 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
795 switch(parm_u_qpsk_fec_inner)
818 #if HAVE_DVB_API_VERSION >=3
819 case FEC_S2_8PSK_1_2:
820 case FEC_S2_QPSK_1_2:
823 case FEC_S2_8PSK_2_3:
824 case FEC_S2_QPSK_2_3:
827 case FEC_S2_8PSK_3_4:
828 case FEC_S2_QPSK_3_4:
831 case FEC_S2_8PSK_5_6:
832 case FEC_S2_QPSK_5_6:
835 case FEC_S2_8PSK_7_8:
836 case FEC_S2_QPSK_7_8:
839 case FEC_S2_8PSK_8_9:
840 case FEC_S2_QPSK_8_9:
843 case FEC_S2_8PSK_3_5:
844 case FEC_S2_QPSK_3_5:
847 case FEC_S2_8PSK_4_5:
848 case FEC_S2_QPSK_4_5:
851 case FEC_S2_8PSK_9_10:
852 case FEC_S2_QPSK_9_10:
857 #if HAVE_DVB_API_VERSION >=3
858 PutToDict(dict, "modulation",
859 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ? "8PSK": "QPSK" );
861 PutToDict(dict, "modulation", "QPSK" );
863 PutToDict(dict, "fec_inner", tmp);
864 tmp = parm_u_qpsk_fec_inner > FEC_AUTO ?
866 PutToDict(dict, "system", tmp);
869 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
872 #if HAVE_DVB_API_VERSION < 3
873 PutToDict(dict, "frequency", parm_frequency);
875 PutToDict(dict, "frequency", parm_frequency/1000);
877 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
878 switch(parm_u_qam_fec_inner)
898 #if HAVE_DVB_API_VERSION >= 3
908 PutToDict(dict, "fec_inner", tmp);
909 switch(parm_u_qam_modulation)
931 PutToDict(dict, "modulation", tmp);
934 void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
937 PutToDict(dict, "frequency", parm_frequency);
938 switch (parm_u_ofdm_bandwidth)
940 case BANDWIDTH_8_MHZ:
941 tmp = "BANDWIDTH_8_MHZ";
943 case BANDWIDTH_7_MHZ:
944 tmp = "BANDWIDTH_7_MHZ";
946 case BANDWIDTH_6_MHZ:
947 tmp = "BANDWIDTH_6_MHZ";
951 tmp = "BANDWIDTH_AUTO";
954 PutToDict(dict, "bandwidth", tmp);
955 switch (parm_u_ofdm_code_rate_LP)
977 PutToDict(dict, "code_rate_lp", tmp);
978 switch (parm_u_ofdm_code_rate_HP)
1000 PutToDict(dict, "code_rate_hp", tmp);
1001 switch (parm_u_ofdm_constellation)
1017 PutToDict(dict, "constellation", tmp);
1018 switch (parm_u_ofdm_transmission_mode)
1020 case TRANSMISSION_MODE_2K:
1021 tmp = "TRANSMISSION_MODE_2K";
1023 case TRANSMISSION_MODE_8K:
1024 tmp = "TRANSMISSION_MODE_8K";
1027 case TRANSMISSION_MODE_AUTO:
1028 tmp = "TRANSMISSION_MODE_AUTO";
1031 PutToDict(dict, "transmission_mode", tmp);
1032 switch (parm_u_ofdm_guard_interval)
1034 case GUARD_INTERVAL_1_32:
1035 tmp = "GUARD_INTERVAL_1_32";
1037 case GUARD_INTERVAL_1_16:
1038 tmp = "GUARD_INTERVAL_1_16";
1040 case GUARD_INTERVAL_1_8:
1041 tmp = "GUARD_INTERVAL_1_8";
1043 case GUARD_INTERVAL_1_4:
1044 tmp = "GUARD_INTERVAL_1_4";
1047 case GUARD_INTERVAL_AUTO:
1048 tmp = "GUARD_INTERVAL_AUTO";
1051 PutToDict(dict, "guard_interval", tmp);
1052 switch (parm_u_ofdm_hierarchy_information)
1054 case HIERARCHY_NONE:
1055 tmp = "HIERARCHY_NONE";
1058 tmp = "HIERARCHY_1";
1061 tmp = "HIERARCHY_2";
1064 tmp = "HIERARCHY_4";
1067 case HIERARCHY_AUTO:
1068 tmp = "HIERARCHY_AUTO";
1071 PutToDict(dict, "hierarchy_information", tmp);
1074 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1076 if (dest && PyDict_Check(dest))
1078 const char *tmp = "UNKNOWN";
1099 PutToDict(dest, "tuner_state", tmp);
1100 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1101 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1102 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1103 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1104 int sigQualitydB = readFrontendData(signalQualitydB);
1105 if (sigQualitydB == 0x12345678) // not support yet
1107 ePyObject obj=Py_None;
1109 PutToDict(dest, "tuner_signal_quality_db", obj);
1112 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1113 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1117 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1119 if (m_fd != -1 && dest && PyDict_Check(dest))
1127 FRONTENDPARAMETERS front;
1128 if (!original && ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1129 eDebug("FE_GET_FRONTEND (%m)");
1132 const FRONTENDPARAMETERS &parm = original ? this->parm : front;
1133 const char *tmp = "INVERSION_AUTO";
1134 switch(parm_inversion)
1137 tmp = "INVERSION_ON";
1140 tmp = "INVERSION_OFF";
1146 PutToDict(dest, "inversion", tmp);
1151 fillDictWithSatelliteData(dest, original?parm:front, this);
1154 fillDictWithCableData(dest, original?parm:front);
1157 fillDictWithTerrestrialData(dest, original?parm:front);
1168 void eDVBFrontend::getFrontendData(ePyObject dest)
1170 if (dest && PyDict_Check(dest))
1173 PutToDict(dest, "tuner_number", m_dvbid);
1189 PutToDict(dest, "tuner_type", tmp);
1193 #ifndef FP_IOCTL_GET_ID
1194 #define FP_IOCTL_GET_ID 0
1196 int eDVBFrontend::readInputpower()
1198 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1200 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1201 FILE *f=fopen(proc_name, "r");
1204 if (fscanf(f, "%08x", &power) != 1)
1205 eDebug("read %s failed!! (%m)", proc_name);
1207 eDebug("%s is %d\n", proc_name, power);
1212 // open front prozessor
1213 int fp=::open("/dev/dbox/fp0", O_RDWR);
1216 eDebug("couldn't open fp");
1219 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1220 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1222 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1231 bool eDVBFrontend::setSecSequencePos(int steps)
1233 eDebug("set sequence pos %d", steps);
1238 if (m_sec_sequence.current() != m_sec_sequence.end())
1239 ++m_sec_sequence.current();
1244 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1245 --m_sec_sequence.current();
1251 void eDVBFrontend::setRotorData(int pos, int cmd)
1253 m_data[ROTOR_CMD] = cmd;
1254 m_data[ROTOR_POS] = pos;
1255 if ( m_data[SATPOS_DEPENDS_PTR] != -1 )
1257 eDVBRegisteredFrontend *satpos_depends_to_fe = (eDVBRegisteredFrontend*) m_data[SATPOS_DEPENDS_PTR];
1258 satpos_depends_to_fe->m_frontend->m_data[ROTOR_CMD] = cmd;
1259 satpos_depends_to_fe->m_frontend->m_data[ROTOR_POS] = pos;
1263 eDVBRegisteredFrontend *next = (eDVBRegisteredFrontend *)m_data[LINKED_NEXT_PTR];
1264 while ( (long)next != -1 )
1266 next->m_frontend->m_data[ROTOR_CMD] = cmd;
1267 next->m_frontend->m_data[ROTOR_POS] = pos;
1268 next = (eDVBRegisteredFrontend *)next->m_frontend->m_data[LINKED_NEXT_PTR];
1270 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)m_data[LINKED_PREV_PTR];
1271 while ( (long)prev != -1 )
1273 prev->m_frontend->m_data[ROTOR_CMD] = cmd;
1274 prev->m_frontend->m_data[ROTOR_POS] = pos;
1275 prev = (eDVBRegisteredFrontend *)prev->m_frontend->m_data[LINKED_PREV_PTR];
1280 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1283 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1285 // eDebug("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1286 switch (m_sec_sequence.current()->cmd)
1288 case eSecCommand::SLEEP:
1289 delay = m_sec_sequence.current()++->msec;
1290 eDebug("[SEC] sleep %dms", delay);
1292 case eSecCommand::GOTO:
1293 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1294 ++m_sec_sequence.current();
1296 case eSecCommand::SET_VOLTAGE:
1298 int voltage = m_sec_sequence.current()++->voltage;
1299 eDebug("[SEC] setVoltage %d", voltage);
1300 setVoltage(voltage);
1303 case eSecCommand::IF_VOLTAGE_GOTO:
1305 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1306 if ( compare.voltage == m_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1308 ++m_sec_sequence.current();
1311 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1313 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1314 if ( compare.voltage != m_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1316 ++m_sec_sequence.current();
1319 case eSecCommand::IF_TONE_GOTO:
1321 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1322 if ( compare.tone == m_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1324 ++m_sec_sequence.current();
1327 case eSecCommand::IF_NOT_TONE_GOTO:
1329 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1330 if ( compare.tone != m_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1332 ++m_sec_sequence.current();
1335 case eSecCommand::SET_TONE:
1336 eDebug("[SEC] setTone %d", m_sec_sequence.current()->tone);
1337 setTone(m_sec_sequence.current()++->tone);
1339 case eSecCommand::SEND_DISEQC:
1340 sendDiseqc(m_sec_sequence.current()->diseqc);
1341 eDebugNoNewLine("[SEC] sendDiseqc: ");
1342 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1343 eDebugNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1345 ++m_sec_sequence.current();
1347 case eSecCommand::SEND_TONEBURST:
1348 eDebug("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1349 sendToneburst(m_sec_sequence.current()++->toneburst);
1351 case eSecCommand::SET_FRONTEND:
1352 eDebug("[SEC] setFrontend");
1354 ++m_sec_sequence.current();
1356 case eSecCommand::START_TUNE_TIMEOUT:
1358 m_timeout->start(m_sec_sequence.current()->timeout, 1);
1359 ++m_sec_sequence.current();
1362 case eSecCommand::SET_TIMEOUT:
1363 m_timeoutCount = m_sec_sequence.current()++->val;
1364 eDebug("[SEC] set timeout %d", m_timeoutCount);
1366 case eSecCommand::IF_TIMEOUT_GOTO:
1367 if (!m_timeoutCount)
1369 eDebug("[SEC] rotor timout");
1370 m_sec->setRotorMoving(false);
1371 setSecSequencePos(m_sec_sequence.current()->steps);
1374 ++m_sec_sequence.current();
1376 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1378 int idx = m_sec_sequence.current()++->val;
1379 if ( idx == 0 || idx == 1 )
1381 m_idleInputpower[idx] = readInputpower();
1382 eDebug("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1385 eDebug("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1388 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1390 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1391 int idx = compare.val;
1392 if ( idx == 0 || idx == 1 )
1394 int idle = readInputpower();
1395 int diff = abs(idle-m_idleInputpower[idx]);
1398 eDebug("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1399 setSecSequencePos(compare.steps);
1403 ++m_sec_sequence.current();
1406 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1408 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1409 if (readFrontendData(locked))
1411 eDebug("[SEC] locked step %d ok", cmd.okcount);
1413 if (cmd.okcount > 12)
1415 eDebug("ok > 12 .. goto %d\n",m_sec_sequence.current()->steps);
1416 setSecSequencePos(cmd.steps);
1422 eDebug("[SEC] rotor locked step %d failed", cmd.okcount);
1424 if (!m_timeoutCount && m_retryCount > 0)
1428 ++m_sec_sequence.current();
1431 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1432 m_runningInputpower = readInputpower();
1433 eDebug("[SEC] runningInputpower is %d", m_runningInputpower);
1434 ++m_sec_sequence.current();
1436 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1438 int idleInputpower = m_idleInputpower[ (m_data[CUR_VOLTAGE]&1) ? 0 : 1];
1439 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1440 const char *txt = cmd.direction ? "running" : "stopped";
1441 eDebug("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1443 m_runningInputpower,
1446 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1447 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1450 eDebug("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1451 if ( cmd.okcount > 6 )
1453 m_sec->setRotorMoving(cmd.direction);
1454 eDebug("[SEC] rotor is %s", txt);
1455 if (setSecSequencePos(cmd.steps))
1461 eDebug("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1463 if (!m_timeoutCount && m_retryCount > 0)
1467 ++m_sec_sequence.current();
1470 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1471 if (m_data[ROTOR_CMD] != -1 && m_data[ROTOR_POS] != -1)
1472 setSecSequencePos(m_sec_sequence.current()->steps);
1474 ++m_sec_sequence.current();
1476 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1477 eDebug("[SEC] invalidate current rotorparams");
1478 setRotorData(-1,-1);
1479 ++m_sec_sequence.current();
1481 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1482 setRotorData(m_data[NEW_ROTOR_POS], m_data[NEW_ROTOR_CMD]);
1483 eDebug("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, m_data[ROTOR_CMD], m_data[ROTOR_POS]);
1484 ++m_sec_sequence.current();
1486 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1487 m_retryCount = m_sec_sequence.current()++->val;
1488 eDebug("[SEC] set rotor retries %d", m_retryCount);
1490 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1493 eDebug("[SEC] no more rotor retrys");
1494 setSecSequencePos(m_sec_sequence.current()->steps);
1497 ++m_sec_sequence.current();
1499 case eSecCommand::SET_POWER_LIMITING_MODE:
1501 if (m_need_rotor_workaround)
1505 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1507 sprintf(dev, "/dev/i2c/%d", m_slotid);
1508 else if (m_slotid == 2)
1509 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1510 else if (m_slotid == 3)
1511 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1512 int fd = ::open(dev, O_RDWR);
1514 unsigned char data[2];
1515 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1516 if(::read(fd, data, 1) != 1)
1517 eDebug("[SEC] error read lnbp (%m)");
1518 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1520 data[0] |= 0x80; // enable static current limiting
1521 eDebug("[SEC] set static current limiting");
1525 data[0] &= ~0x80; // enable dynamic current limiting
1526 eDebug("[SEC] set dynamic current limiting");
1528 if(::write(fd, data, 1) != 1)
1529 eDebug("[SEC] error write lnbp (%m)");
1532 ++m_sec_sequence.current();
1536 eDebug("[SEC] unhandled sec command %d",
1537 ++m_sec_sequence.current()->cmd);
1538 ++m_sec_sequence.current();
1540 m_tuneTimer->start(delay,true);
1544 void eDVBFrontend::setFrontend()
1546 eDebug("setting frontend %d", m_dvbid);
1549 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1551 perror("FE_SET_FRONTEND failed");
1556 RESULT eDVBFrontend::getFrontendType(int &t)
1564 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1569 eWarning("no SEC module active!");
1572 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1575 eDebug("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1578 feparm.polarisation,
1582 feparm.orbital_position);
1583 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1584 switch (feparm.inversion)
1586 case eDVBFrontendParametersSatellite::Inversion::On:
1587 parm_inversion = INVERSION_ON;
1589 case eDVBFrontendParametersSatellite::Inversion::Off:
1590 parm_inversion = INVERSION_OFF;
1593 case eDVBFrontendParametersSatellite::Inversion::Unknown:
1594 parm_inversion = INVERSION_AUTO;
1597 if (feparm.system == eDVBFrontendParametersSatellite::System::DVB_S)
1600 case eDVBFrontendParametersSatellite::FEC::fNone:
1601 parm_u_qpsk_fec_inner = FEC_NONE;
1603 case eDVBFrontendParametersSatellite::FEC::f1_2:
1604 parm_u_qpsk_fec_inner = FEC_1_2;
1606 case eDVBFrontendParametersSatellite::FEC::f2_3:
1607 parm_u_qpsk_fec_inner = FEC_2_3;
1609 case eDVBFrontendParametersSatellite::FEC::f3_4:
1610 parm_u_qpsk_fec_inner = FEC_3_4;
1612 case eDVBFrontendParametersSatellite::FEC::f5_6:
1613 parm_u_qpsk_fec_inner = FEC_5_6;
1615 case eDVBFrontendParametersSatellite::FEC::f7_8:
1616 parm_u_qpsk_fec_inner = FEC_7_8;
1619 eDebug("no valid fec for DVB-S set.. assume auto");
1620 case eDVBFrontendParametersSatellite::FEC::fAuto:
1621 parm_u_qpsk_fec_inner = FEC_AUTO;
1624 #if HAVE_DVB_API_VERSION >= 3
1629 case eDVBFrontendParametersSatellite::FEC::f1_2:
1630 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1632 case eDVBFrontendParametersSatellite::FEC::f2_3:
1633 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1635 case eDVBFrontendParametersSatellite::FEC::f3_4:
1636 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1638 case eDVBFrontendParametersSatellite::FEC::f3_5:
1639 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1641 case eDVBFrontendParametersSatellite::FEC::f4_5:
1642 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1644 case eDVBFrontendParametersSatellite::FEC::f5_6:
1645 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1647 case eDVBFrontendParametersSatellite::FEC::f7_8:
1648 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1650 case eDVBFrontendParametersSatellite::FEC::f8_9:
1651 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1653 case eDVBFrontendParametersSatellite::FEC::f9_10:
1654 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1657 eDebug("no valid fec for DVB-S2 set.. abort !!");
1660 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK)
1661 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1662 // 8PSK fec driver values are decimal 9 bigger
1665 // FIXME !!! get frequency range from tuner
1666 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1668 eDebug("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1671 eDebug("tuning to %d mhz", parm_frequency/1000);
1676 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1678 #if HAVE_DVB_API_VERSION < 3
1679 parm_frequency = feparm.frequency;
1681 parm_frequency = feparm.frequency * 1000;
1683 parm_u_qam_symbol_rate = feparm.symbol_rate;
1684 switch (feparm.modulation)
1686 case eDVBFrontendParametersCable::Modulation::QAM16:
1687 parm_u_qam_modulation = QAM_16;
1689 case eDVBFrontendParametersCable::Modulation::QAM32:
1690 parm_u_qam_modulation = QAM_32;
1692 case eDVBFrontendParametersCable::Modulation::QAM64:
1693 parm_u_qam_modulation = QAM_64;
1695 case eDVBFrontendParametersCable::Modulation::QAM128:
1696 parm_u_qam_modulation = QAM_128;
1698 case eDVBFrontendParametersCable::Modulation::QAM256:
1699 parm_u_qam_modulation = QAM_256;
1702 case eDVBFrontendParametersCable::Modulation::Auto:
1703 parm_u_qam_modulation = QAM_AUTO;
1706 switch (feparm.inversion)
1708 case eDVBFrontendParametersCable::Inversion::On:
1709 parm_inversion = INVERSION_ON;
1711 case eDVBFrontendParametersCable::Inversion::Off:
1712 parm_inversion = INVERSION_OFF;
1715 case eDVBFrontendParametersCable::Inversion::Unknown:
1716 parm_inversion = INVERSION_AUTO;
1719 switch (feparm.fec_inner)
1721 case eDVBFrontendParametersCable::FEC::fNone:
1722 parm_u_qam_fec_inner = FEC_NONE;
1724 case eDVBFrontendParametersCable::FEC::f1_2:
1725 parm_u_qam_fec_inner = FEC_1_2;
1727 case eDVBFrontendParametersCable::FEC::f2_3:
1728 parm_u_qam_fec_inner = FEC_2_3;
1730 case eDVBFrontendParametersCable::FEC::f3_4:
1731 parm_u_qam_fec_inner = FEC_3_4;
1733 case eDVBFrontendParametersCable::FEC::f5_6:
1734 parm_u_qam_fec_inner = FEC_5_6;
1736 case eDVBFrontendParametersCable::FEC::f7_8:
1737 parm_u_qam_fec_inner = FEC_7_8;
1739 #if HAVE_DVB_API_VERSION >= 3
1740 case eDVBFrontendParametersCable::FEC::f8_9:
1741 parm_u_qam_fec_inner = FEC_8_9;
1745 case eDVBFrontendParametersCable::FEC::fAuto:
1746 parm_u_qam_fec_inner = FEC_AUTO;
1749 eDebug("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
1750 parm_frequency/1000,
1751 parm_u_qam_symbol_rate,
1752 parm_u_qam_fec_inner,
1753 parm_u_qam_modulation,
1758 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
1760 parm_frequency = feparm.frequency;
1762 switch (feparm.bandwidth)
1764 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
1765 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
1767 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
1768 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
1770 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
1771 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
1774 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
1775 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
1778 switch (feparm.code_rate_LP)
1780 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1781 parm_u_ofdm_code_rate_LP = FEC_1_2;
1783 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1784 parm_u_ofdm_code_rate_LP = FEC_2_3;
1786 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1787 parm_u_ofdm_code_rate_LP = FEC_3_4;
1789 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1790 parm_u_ofdm_code_rate_LP = FEC_5_6;
1792 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1793 parm_u_ofdm_code_rate_LP = FEC_7_8;
1796 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1797 parm_u_ofdm_code_rate_LP = FEC_AUTO;
1800 switch (feparm.code_rate_HP)
1802 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1803 parm_u_ofdm_code_rate_HP = FEC_1_2;
1805 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1806 parm_u_ofdm_code_rate_HP = FEC_2_3;
1808 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1809 parm_u_ofdm_code_rate_HP = FEC_3_4;
1811 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1812 parm_u_ofdm_code_rate_HP = FEC_5_6;
1814 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1815 parm_u_ofdm_code_rate_HP = FEC_7_8;
1818 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1819 parm_u_ofdm_code_rate_HP = FEC_AUTO;
1822 switch (feparm.modulation)
1824 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
1825 parm_u_ofdm_constellation = QPSK;
1827 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
1828 parm_u_ofdm_constellation = QAM_16;
1830 case eDVBFrontendParametersTerrestrial::Modulation::QAM64:
1831 parm_u_ofdm_constellation = QAM_64;
1834 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
1835 parm_u_ofdm_constellation = QAM_AUTO;
1838 switch (feparm.transmission_mode)
1840 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
1841 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
1843 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
1844 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
1847 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
1848 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
1851 switch (feparm.guard_interval)
1853 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32:
1854 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
1856 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16:
1857 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
1859 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8:
1860 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
1862 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4:
1863 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
1866 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto:
1867 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
1870 switch (feparm.hierarchy)
1872 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone:
1873 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
1875 case eDVBFrontendParametersTerrestrial::Hierarchy::H1:
1876 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
1878 case eDVBFrontendParametersTerrestrial::Hierarchy::H2:
1879 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
1881 case eDVBFrontendParametersTerrestrial::Hierarchy::H4:
1882 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
1885 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto:
1886 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
1889 switch (feparm.inversion)
1891 case eDVBFrontendParametersTerrestrial::Inversion::On:
1892 parm_inversion = INVERSION_ON;
1894 case eDVBFrontendParametersTerrestrial::Inversion::Off:
1895 parm_inversion = INVERSION_OFF;
1898 case eDVBFrontendParametersTerrestrial::Inversion::Unknown:
1899 parm_inversion = INVERSION_AUTO;
1905 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
1907 unsigned int timeout = 5000;
1908 eDebug("(%d)tune", m_dvbid);
1916 eDebug("no frontend device opened... do not try to tune !!!");
1928 m_sec_sequence.clear();
1930 where.calcLockTimeout(timeout);
1936 eDVBFrontendParametersSatellite feparm;
1937 if (where.getDVBS(feparm))
1939 eDebug("no dvbs data!");
1943 m_sec->setRotorMoving(false);
1944 res=prepare_sat(feparm, timeout);
1952 eDVBFrontendParametersCable feparm;
1953 if (where.getDVBC(feparm))
1958 res=prepare_cable(feparm);
1962 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
1963 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
1968 eDVBFrontendParametersTerrestrial feparm;
1969 if (where.getDVBT(feparm))
1971 eDebug("no -T data");
1975 res=prepare_terrestrial(feparm);
1979 std::string enable_5V;
1980 char configStr[255];
1981 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
1982 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
1983 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
1984 if (enable_5V == "True")
1985 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
1987 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
1988 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
1994 m_tuneTimer->start(0,true);
1995 m_sec_sequence.current() = m_sec_sequence.begin();
1997 if (m_state != stateTuning)
2000 m_state = stateTuning;
2001 m_stateChanged(this);
2007 m_tuneTimer->stop();
2011 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2013 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2017 RESULT eDVBFrontend::setVoltage(int voltage)
2019 if (m_type == feCable)
2021 #if HAVE_DVB_API_VERSION < 3
2024 bool increased=false;
2025 fe_sec_voltage_t vlt;
2027 m_data[CUR_VOLTAGE]=voltage;
2031 for (int i=0; i < 3; ++i) // reset diseqc
2033 vlt = SEC_VOLTAGE_OFF;
2036 #if HAVE_DVB_API_VERSION < 3
2037 vlt = SEC_VOLTAGE_13_5;
2043 vlt = SEC_VOLTAGE_13;
2046 #if HAVE_DVB_API_VERSION < 3
2047 vlt = SEC_VOLTAGE_18_5;
2053 vlt = SEC_VOLTAGE_18;
2058 #if HAVE_DVB_API_VERSION < 3
2059 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2061 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2062 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2063 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2067 RESULT eDVBFrontend::getState(int &state)
2073 RESULT eDVBFrontend::setTone(int t)
2075 if (m_type != feSatellite)
2077 #if HAVE_DVB_API_VERSION < 3
2080 fe_sec_tone_mode_t tone;
2089 tone = SEC_TONE_OFF;
2094 #if HAVE_DVB_API_VERSION < 3
2095 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2097 return ::ioctl(m_fd, FE_SET_TONE, tone);
2101 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2102 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2105 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2107 #if HAVE_DVB_API_VERSION < 3
2108 struct secCommand cmd;
2109 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2110 cmd.u.diseqc.cmdtype = diseqc.data[0];
2111 cmd.u.diseqc.addr = diseqc.data[1];
2112 cmd.u.diseqc.cmd = diseqc.data[2];
2113 cmd.u.diseqc.numParams = diseqc.len-3;
2114 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2115 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2117 struct dvb_diseqc_master_cmd cmd;
2118 memcpy(cmd.msg, diseqc.data, diseqc.len);
2119 cmd.msg_len = diseqc.len;
2120 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2126 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2127 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2129 RESULT eDVBFrontend::sendToneburst(int burst)
2131 #if HAVE_DVB_API_VERSION < 3
2132 secMiniCmd cmd = SEC_MINI_NONE;
2134 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2136 if ( burst == eDVBSatelliteDiseqcParameters::A )
2138 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2140 #if HAVE_DVB_API_VERSION < 3
2141 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2144 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2150 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2156 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2158 m_sec_sequence = list;
2162 RESULT eDVBFrontend::getData(int num, long &data)
2164 if ( num < NUM_DATA_ENTRIES )
2172 RESULT eDVBFrontend::setData(int num, long val)
2174 if ( num < NUM_DATA_ENTRIES )
2182 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2185 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2188 if (m_type == eDVBFrontend::feSatellite)
2191 eDVBFrontendParametersSatellite sat_parm;
2192 int ret = feparm->getDVBS(sat_parm);
2194 return m_sec->canTune(sat_parm, this, 1 << m_slotid);
2196 else if (m_type == eDVBFrontend::feCable)
2197 return 2; // more prio for cable frontends
2201 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2203 ePyObject Id, Descr, Enabled;
2204 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 3)
2206 Id = PyTuple_GET_ITEM(obj, 0);
2207 Descr = PyTuple_GET_ITEM(obj, 1);
2208 Enabled = PyTuple_GET_ITEM(obj, 2);
2209 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled))
2211 strcpy(m_description, PyString_AS_STRING(Descr));
2212 m_slotid = PyInt_AsLong(Id);
2213 m_enabled = Enabled == Py_True;
2214 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2215 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2216 !!strstr(m_description, "Alps BSBE2") ||
2217 !!strstr(m_description, "Alps -S");
2218 eDebug("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s",
2219 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No" );
2222 PyErr_SetString(PyExc_StandardError,
2223 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");