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:
1539 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", m_dvbid);
1540 FILE *f=fopen(proc_name, "w");
1541 if (f) // new interface exist?
1543 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1544 if (fprintf(f, "%s", slimiting ? "on" : "off") != 1)
1545 eDebug("write %s failed!! (%m)", proc_name);
1547 eDebug("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1550 else if (m_need_rotor_workaround)
1554 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1556 sprintf(dev, "/dev/i2c/%d", m_slotid);
1557 else if (m_slotid == 2)
1558 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1559 else if (m_slotid == 3)
1560 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1561 int fd = ::open(dev, O_RDWR);
1563 unsigned char data[2];
1564 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1565 if(::read(fd, data, 1) != 1)
1566 eDebug("[SEC] error read lnbp (%m)");
1567 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1569 data[0] |= 0x80; // enable static current limiting
1570 eDebug("[SEC] set static current limiting");
1574 data[0] &= ~0x80; // enable dynamic current limiting
1575 eDebug("[SEC] set dynamic current limiting");
1577 if(::write(fd, data, 1) != 1)
1578 eDebug("[SEC] error write lnbp (%m)");
1581 ++m_sec_sequence.current();
1585 eDebug("[SEC] unhandled sec command %d",
1586 ++m_sec_sequence.current()->cmd);
1587 ++m_sec_sequence.current();
1589 m_tuneTimer->start(delay,true);
1593 void eDVBFrontend::setFrontend()
1595 eDebug("setting frontend %d", m_dvbid);
1598 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1600 perror("FE_SET_FRONTEND failed");
1605 RESULT eDVBFrontend::getFrontendType(int &t)
1613 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1618 eWarning("no SEC module active!");
1621 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1624 eDebug("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1627 feparm.polarisation,
1631 feparm.orbital_position);
1632 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1633 switch (feparm.inversion)
1635 case eDVBFrontendParametersSatellite::Inversion::On:
1636 parm_inversion = INVERSION_ON;
1638 case eDVBFrontendParametersSatellite::Inversion::Off:
1639 parm_inversion = INVERSION_OFF;
1642 case eDVBFrontendParametersSatellite::Inversion::Unknown:
1643 parm_inversion = INVERSION_AUTO;
1646 if (feparm.system == eDVBFrontendParametersSatellite::System::DVB_S)
1649 case eDVBFrontendParametersSatellite::FEC::fNone:
1650 parm_u_qpsk_fec_inner = FEC_NONE;
1652 case eDVBFrontendParametersSatellite::FEC::f1_2:
1653 parm_u_qpsk_fec_inner = FEC_1_2;
1655 case eDVBFrontendParametersSatellite::FEC::f2_3:
1656 parm_u_qpsk_fec_inner = FEC_2_3;
1658 case eDVBFrontendParametersSatellite::FEC::f3_4:
1659 parm_u_qpsk_fec_inner = FEC_3_4;
1661 case eDVBFrontendParametersSatellite::FEC::f5_6:
1662 parm_u_qpsk_fec_inner = FEC_5_6;
1664 case eDVBFrontendParametersSatellite::FEC::f7_8:
1665 parm_u_qpsk_fec_inner = FEC_7_8;
1668 eDebug("no valid fec for DVB-S set.. assume auto");
1669 case eDVBFrontendParametersSatellite::FEC::fAuto:
1670 parm_u_qpsk_fec_inner = FEC_AUTO;
1673 #if HAVE_DVB_API_VERSION >= 3
1678 case eDVBFrontendParametersSatellite::FEC::f1_2:
1679 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1681 case eDVBFrontendParametersSatellite::FEC::f2_3:
1682 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1684 case eDVBFrontendParametersSatellite::FEC::f3_4:
1685 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1687 case eDVBFrontendParametersSatellite::FEC::f3_5:
1688 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1690 case eDVBFrontendParametersSatellite::FEC::f4_5:
1691 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1693 case eDVBFrontendParametersSatellite::FEC::f5_6:
1694 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1696 case eDVBFrontendParametersSatellite::FEC::f7_8:
1697 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1699 case eDVBFrontendParametersSatellite::FEC::f8_9:
1700 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1702 case eDVBFrontendParametersSatellite::FEC::f9_10:
1703 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1706 eDebug("no valid fec for DVB-S2 set.. abort !!");
1709 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1710 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK) {
1711 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1712 // 8PSK fec driver values are decimal 9 bigger
1713 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1717 // FIXME !!! get frequency range from tuner
1718 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1720 eDebug("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1723 eDebug("tuning to %d mhz", parm_frequency/1000);
1728 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1730 #if HAVE_DVB_API_VERSION < 3
1731 parm_frequency = feparm.frequency;
1733 parm_frequency = feparm.frequency * 1000;
1735 parm_u_qam_symbol_rate = feparm.symbol_rate;
1736 switch (feparm.modulation)
1738 case eDVBFrontendParametersCable::Modulation::QAM16:
1739 parm_u_qam_modulation = QAM_16;
1741 case eDVBFrontendParametersCable::Modulation::QAM32:
1742 parm_u_qam_modulation = QAM_32;
1744 case eDVBFrontendParametersCable::Modulation::QAM64:
1745 parm_u_qam_modulation = QAM_64;
1747 case eDVBFrontendParametersCable::Modulation::QAM128:
1748 parm_u_qam_modulation = QAM_128;
1750 case eDVBFrontendParametersCable::Modulation::QAM256:
1751 parm_u_qam_modulation = QAM_256;
1754 case eDVBFrontendParametersCable::Modulation::Auto:
1755 parm_u_qam_modulation = QAM_AUTO;
1758 switch (feparm.inversion)
1760 case eDVBFrontendParametersCable::Inversion::On:
1761 parm_inversion = INVERSION_ON;
1763 case eDVBFrontendParametersCable::Inversion::Off:
1764 parm_inversion = INVERSION_OFF;
1767 case eDVBFrontendParametersCable::Inversion::Unknown:
1768 parm_inversion = INVERSION_AUTO;
1771 switch (feparm.fec_inner)
1773 case eDVBFrontendParametersCable::FEC::fNone:
1774 parm_u_qam_fec_inner = FEC_NONE;
1776 case eDVBFrontendParametersCable::FEC::f1_2:
1777 parm_u_qam_fec_inner = FEC_1_2;
1779 case eDVBFrontendParametersCable::FEC::f2_3:
1780 parm_u_qam_fec_inner = FEC_2_3;
1782 case eDVBFrontendParametersCable::FEC::f3_4:
1783 parm_u_qam_fec_inner = FEC_3_4;
1785 case eDVBFrontendParametersCable::FEC::f5_6:
1786 parm_u_qam_fec_inner = FEC_5_6;
1788 case eDVBFrontendParametersCable::FEC::f7_8:
1789 parm_u_qam_fec_inner = FEC_7_8;
1791 #if HAVE_DVB_API_VERSION >= 3
1792 case eDVBFrontendParametersCable::FEC::f8_9:
1793 parm_u_qam_fec_inner = FEC_8_9;
1797 case eDVBFrontendParametersCable::FEC::fAuto:
1798 parm_u_qam_fec_inner = FEC_AUTO;
1801 eDebug("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
1802 parm_frequency/1000,
1803 parm_u_qam_symbol_rate,
1804 parm_u_qam_fec_inner,
1805 parm_u_qam_modulation,
1810 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
1812 parm_frequency = feparm.frequency;
1814 switch (feparm.bandwidth)
1816 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
1817 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
1819 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
1820 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
1822 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
1823 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
1826 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
1827 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
1830 switch (feparm.code_rate_LP)
1832 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1833 parm_u_ofdm_code_rate_LP = FEC_1_2;
1835 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1836 parm_u_ofdm_code_rate_LP = FEC_2_3;
1838 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1839 parm_u_ofdm_code_rate_LP = FEC_3_4;
1841 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1842 parm_u_ofdm_code_rate_LP = FEC_5_6;
1844 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1845 parm_u_ofdm_code_rate_LP = FEC_7_8;
1848 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1849 parm_u_ofdm_code_rate_LP = FEC_AUTO;
1852 switch (feparm.code_rate_HP)
1854 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1855 parm_u_ofdm_code_rate_HP = FEC_1_2;
1857 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1858 parm_u_ofdm_code_rate_HP = FEC_2_3;
1860 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1861 parm_u_ofdm_code_rate_HP = FEC_3_4;
1863 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1864 parm_u_ofdm_code_rate_HP = FEC_5_6;
1866 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1867 parm_u_ofdm_code_rate_HP = FEC_7_8;
1870 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1871 parm_u_ofdm_code_rate_HP = FEC_AUTO;
1874 switch (feparm.modulation)
1876 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
1877 parm_u_ofdm_constellation = QPSK;
1879 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
1880 parm_u_ofdm_constellation = QAM_16;
1882 case eDVBFrontendParametersTerrestrial::Modulation::QAM64:
1883 parm_u_ofdm_constellation = QAM_64;
1886 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
1887 parm_u_ofdm_constellation = QAM_AUTO;
1890 switch (feparm.transmission_mode)
1892 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
1893 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
1895 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
1896 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
1899 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
1900 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
1903 switch (feparm.guard_interval)
1905 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32:
1906 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
1908 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16:
1909 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
1911 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8:
1912 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
1914 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4:
1915 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
1918 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto:
1919 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
1922 switch (feparm.hierarchy)
1924 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone:
1925 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
1927 case eDVBFrontendParametersTerrestrial::Hierarchy::H1:
1928 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
1930 case eDVBFrontendParametersTerrestrial::Hierarchy::H2:
1931 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
1933 case eDVBFrontendParametersTerrestrial::Hierarchy::H4:
1934 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
1937 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto:
1938 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
1941 switch (feparm.inversion)
1943 case eDVBFrontendParametersTerrestrial::Inversion::On:
1944 parm_inversion = INVERSION_ON;
1946 case eDVBFrontendParametersTerrestrial::Inversion::Off:
1947 parm_inversion = INVERSION_OFF;
1950 case eDVBFrontendParametersTerrestrial::Inversion::Unknown:
1951 parm_inversion = INVERSION_AUTO;
1957 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
1959 unsigned int timeout = 5000;
1960 eDebug("(%d)tune", m_dvbid);
1968 eDebug("no frontend device opened... do not try to tune !!!");
1980 m_sec_sequence.clear();
1982 where.calcLockTimeout(timeout);
1988 eDVBFrontendParametersSatellite feparm;
1989 if (where.getDVBS(feparm))
1991 eDebug("no dvbs data!");
1995 m_sec->setRotorMoving(false);
1996 res=prepare_sat(feparm, timeout);
2004 eDVBFrontendParametersCable feparm;
2005 if (where.getDVBC(feparm))
2010 res=prepare_cable(feparm);
2014 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2015 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2020 eDVBFrontendParametersTerrestrial feparm;
2021 if (where.getDVBT(feparm))
2023 eDebug("no -T data");
2027 res=prepare_terrestrial(feparm);
2031 std::string enable_5V;
2032 char configStr[255];
2033 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2034 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2035 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2036 if (enable_5V == "True")
2037 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2039 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2040 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2046 m_tuneTimer->start(0,true);
2047 m_sec_sequence.current() = m_sec_sequence.begin();
2049 if (m_state != stateTuning)
2052 m_state = stateTuning;
2053 m_stateChanged(this);
2059 m_tuneTimer->stop();
2063 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2065 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2069 RESULT eDVBFrontend::setVoltage(int voltage)
2071 if (m_type == feCable)
2073 #if HAVE_DVB_API_VERSION < 3
2076 bool increased=false;
2077 fe_sec_voltage_t vlt;
2079 m_data[CUR_VOLTAGE]=voltage;
2083 for (int i=0; i < 3; ++i) // reset diseqc
2085 vlt = SEC_VOLTAGE_OFF;
2088 #if HAVE_DVB_API_VERSION < 3
2089 vlt = SEC_VOLTAGE_13_5;
2095 vlt = SEC_VOLTAGE_13;
2098 #if HAVE_DVB_API_VERSION < 3
2099 vlt = SEC_VOLTAGE_18_5;
2105 vlt = SEC_VOLTAGE_18;
2110 #if HAVE_DVB_API_VERSION < 3
2111 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2113 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2114 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2115 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2119 RESULT eDVBFrontend::getState(int &state)
2125 RESULT eDVBFrontend::setTone(int t)
2127 if (m_type != feSatellite)
2129 #if HAVE_DVB_API_VERSION < 3
2132 fe_sec_tone_mode_t tone;
2141 tone = SEC_TONE_OFF;
2146 #if HAVE_DVB_API_VERSION < 3
2147 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2149 return ::ioctl(m_fd, FE_SET_TONE, tone);
2153 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2154 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2157 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2159 #if HAVE_DVB_API_VERSION < 3
2160 struct secCommand cmd;
2161 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2162 cmd.u.diseqc.cmdtype = diseqc.data[0];
2163 cmd.u.diseqc.addr = diseqc.data[1];
2164 cmd.u.diseqc.cmd = diseqc.data[2];
2165 cmd.u.diseqc.numParams = diseqc.len-3;
2166 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2167 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2169 struct dvb_diseqc_master_cmd cmd;
2170 memcpy(cmd.msg, diseqc.data, diseqc.len);
2171 cmd.msg_len = diseqc.len;
2172 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2178 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2179 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2181 RESULT eDVBFrontend::sendToneburst(int burst)
2183 #if HAVE_DVB_API_VERSION < 3
2184 secMiniCmd cmd = SEC_MINI_NONE;
2186 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2188 if ( burst == eDVBSatelliteDiseqcParameters::A )
2190 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2192 #if HAVE_DVB_API_VERSION < 3
2193 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2196 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2202 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2208 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2210 m_sec_sequence = list;
2214 RESULT eDVBFrontend::getData(int num, long &data)
2216 if ( num < NUM_DATA_ENTRIES )
2224 RESULT eDVBFrontend::setData(int num, long val)
2226 if ( num < NUM_DATA_ENTRIES )
2234 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2237 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2240 if (m_type == eDVBFrontend::feSatellite)
2243 eDVBFrontendParametersSatellite sat_parm;
2244 int ret = feparm->getDVBS(sat_parm);
2246 if (sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S2 && !m_can_handle_dvbs2)
2248 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2249 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S && m_can_handle_dvbs2)
2252 else if (m_type == eDVBFrontend::feCable)
2253 return 2; // more prio for cable frontends
2257 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2259 ePyObject Id, Descr, Enabled;
2260 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 3)
2262 Id = PyTuple_GET_ITEM(obj, 0);
2263 Descr = PyTuple_GET_ITEM(obj, 1);
2264 Enabled = PyTuple_GET_ITEM(obj, 2);
2265 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled))
2267 strcpy(m_description, PyString_AS_STRING(Descr));
2268 m_slotid = PyInt_AsLong(Id);
2269 m_enabled = Enabled == Py_True;
2270 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2271 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2272 !!strstr(m_description, "Alps BSBE2") ||
2273 !!strstr(m_description, "Alps -S") ||
2274 !!strstr(m_description, "BCM4501");
2275 m_can_handle_dvbs2 = !!strstr(m_description, "Alps BSBE2") || !!strstr(m_description, "BCM4501");
2276 eDebug("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2277 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2280 PyErr_SetString(PyExc_StandardError,
2281 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");