1 #include <lib/dvb/dvb.h>
2 #include <lib/dvb/frontendparms.h>
3 #include <lib/base/eerror.h>
4 #include <lib/base/nconfig.h> // access to python config
10 #ifndef I2C_SLAVE_FORCE
11 #define I2C_SLAVE_FORCE 0x0706
14 #if HAVE_DVB_API_VERSION < 3
15 #include <ost/frontend.h>
17 #define QAM_AUTO (Modulation)6
18 #define TRANSMISSION_MODE_AUTO (TransmitMode)2
19 #define BANDWIDTH_AUTO (BandWidth)3
20 #define GUARD_INTERVAL_AUTO (GuardInterval)4
21 #define HIERARCHY_AUTO (Hierarchy)4
22 #define parm_frequency parm.Frequency
23 #define parm_inversion parm.Inversion
24 #define parm_u_qpsk_symbol_rate parm.u.qpsk.SymbolRate
25 #define parm_u_qpsk_fec_inner parm.u.qpsk.FEC_inner
26 #define parm_u_qam_symbol_rate parm.u.qam.SymbolRate
27 #define parm_u_qam_fec_inner parm.u.qam.FEC_inner
28 #define parm_u_qam_modulation parm.u.qam.QAM
29 #define parm_u_ofdm_bandwidth parm.u.ofdm.bandWidth
30 #define parm_u_ofdm_code_rate_LP parm.u.ofdm.LP_CodeRate
31 #define parm_u_ofdm_code_rate_HP parm.u.ofdm.HP_CodeRate
32 #define parm_u_ofdm_constellation parm.u.ofdm.Constellation
33 #define parm_u_ofdm_transmission_mode parm.u.ofdm.TransmissionMode
34 #define parm_u_ofdm_guard_interval parm.u.ofdm.guardInterval
35 #define parm_u_ofdm_hierarchy_information parm.u.ofdm.HierarchyInformation
37 #include <linux/dvb/frontend.h>
38 #define parm_frequency parm.frequency
39 #define parm_inversion parm.inversion
40 #define parm_u_qpsk_symbol_rate parm.u.qpsk.symbol_rate
41 #define parm_u_qpsk_fec_inner parm.u.qpsk.fec_inner
42 #define parm_u_qam_symbol_rate parm.u.qam.symbol_rate
43 #define parm_u_qam_fec_inner parm.u.qam.fec_inner
44 #define parm_u_qam_modulation parm.u.qam.modulation
45 #define parm_u_ofdm_bandwidth parm.u.ofdm.bandwidth
46 #define parm_u_ofdm_code_rate_LP parm.u.ofdm.code_rate_LP
47 #define parm_u_ofdm_code_rate_HP parm.u.ofdm.code_rate_HP
48 #define parm_u_ofdm_constellation parm.u.ofdm.constellation
49 #define parm_u_ofdm_transmission_mode parm.u.ofdm.transmission_mode
50 #define parm_u_ofdm_guard_interval parm.u.ofdm.guard_interval
51 #define parm_u_ofdm_hierarchy_information parm.u.ofdm.hierarchy_information
52 #if HAVE_DVB_API_VERSION < 5
53 #define FEC_S2_QPSK_1_2 (fe_code_rate_t)(FEC_AUTO+1)
54 #define FEC_S2_QPSK_2_3 (fe_code_rate_t)(FEC_S2_QPSK_1_2+1)
55 #define FEC_S2_QPSK_3_4 (fe_code_rate_t)(FEC_S2_QPSK_2_3+1)
56 #define FEC_S2_QPSK_5_6 (fe_code_rate_t)(FEC_S2_QPSK_3_4+1)
57 #define FEC_S2_QPSK_7_8 (fe_code_rate_t)(FEC_S2_QPSK_5_6+1)
58 #define FEC_S2_QPSK_8_9 (fe_code_rate_t)(FEC_S2_QPSK_7_8+1)
59 #define FEC_S2_QPSK_3_5 (fe_code_rate_t)(FEC_S2_QPSK_8_9+1)
60 #define FEC_S2_QPSK_4_5 (fe_code_rate_t)(FEC_S2_QPSK_3_5+1)
61 #define FEC_S2_QPSK_9_10 (fe_code_rate_t)(FEC_S2_QPSK_4_5+1)
62 #define FEC_S2_8PSK_1_2 (fe_code_rate_t)(FEC_S2_QPSK_9_10+1)
63 #define FEC_S2_8PSK_2_3 (fe_code_rate_t)(FEC_S2_8PSK_1_2+1)
64 #define FEC_S2_8PSK_3_4 (fe_code_rate_t)(FEC_S2_8PSK_2_3+1)
65 #define FEC_S2_8PSK_5_6 (fe_code_rate_t)(FEC_S2_8PSK_3_4+1)
66 #define FEC_S2_8PSK_7_8 (fe_code_rate_t)(FEC_S2_8PSK_5_6+1)
67 #define FEC_S2_8PSK_8_9 (fe_code_rate_t)(FEC_S2_8PSK_7_8+1)
68 #define FEC_S2_8PSK_3_5 (fe_code_rate_t)(FEC_S2_8PSK_8_9+1)
69 #define FEC_S2_8PSK_4_5 (fe_code_rate_t)(FEC_S2_8PSK_3_5+1)
70 #define FEC_S2_8PSK_9_10 (fe_code_rate_t)(FEC_S2_8PSK_4_5+1)
72 #define FEC_S2_QPSK_1_2 (fe_code_rate_t)(FEC_1_2)
73 #define FEC_S2_QPSK_2_3 (fe_code_rate_t)(FEC_2_3)
74 #define FEC_S2_QPSK_3_4 (fe_code_rate_t)(FEC_3_4)
75 #define FEC_S2_QPSK_5_6 (fe_code_rate_t)(FEC_5_6)
76 #define FEC_S2_QPSK_7_8 (fe_code_rate_t)(FEC_7_8)
77 #define FEC_S2_QPSK_8_9 (fe_code_rate_t)(FEC_8_9)
78 #define FEC_S2_QPSK_3_5 (fe_code_rate_t)(FEC_3_5)
79 #define FEC_S2_QPSK_4_5 (fe_code_rate_t)(FEC_4_5)
80 #define FEC_S2_QPSK_9_10 (fe_code_rate_t)(FEC_9_10)
84 #include <dvbsi++/satellite_delivery_system_descriptor.h>
85 #include <dvbsi++/cable_delivery_system_descriptor.h>
86 #include <dvbsi++/terrestrial_delivery_system_descriptor.h>
88 #define eDebugNoSimulate(x...) \
96 eDebugNoNewLine("SIMULATE:"); \
101 #define eDebugNoSimulateNoNewLine(x...) \
104 eDebugNoNewLine(x); \
109 eDebugNoNewLine("SIMULATE:"); \
110 eDebugNoNewLine(x); \
114 void eDVBDiseqcCommand::setCommandString(const char *str)
119 int slen = strlen(str);
122 eDebug("invalid diseqc command string length (not 2 byte aligned)");
125 if (slen > MAX_DISEQC_LENGTH*2)
127 eDebug("invalid diseqc command string length (string is to long)");
131 for (int i=0; i < slen; ++i)
133 unsigned char c = str[i];
136 case '0' ... '9': c-=48; break;
137 case 'a' ... 'f': c-=87; break;
138 case 'A' ... 'F': c-=55; break;
140 eDebug("invalid character in hex string..ignore complete diseqc command !");
154 void eDVBFrontendParametersSatellite::set(const SatelliteDeliverySystemDescriptor &descriptor)
156 frequency = descriptor.getFrequency() * 10;
157 symbol_rate = descriptor.getSymbolRate() * 100;
158 polarisation = descriptor.getPolarization();
159 fec = descriptor.getFecInner();
160 if ( fec != eDVBFrontendParametersSatellite::FEC_None && fec > eDVBFrontendParametersSatellite::FEC_9_10 )
161 fec = eDVBFrontendParametersSatellite::FEC_Auto;
162 inversion = eDVBFrontendParametersSatellite::Inversion_Unknown;
163 pilot = eDVBFrontendParametersSatellite::Pilot_Unknown;
164 orbital_position = ((descriptor.getOrbitalPosition() >> 12) & 0xF) * 1000;
165 orbital_position += ((descriptor.getOrbitalPosition() >> 8) & 0xF) * 100;
166 orbital_position += ((descriptor.getOrbitalPosition() >> 4) & 0xF) * 10;
167 orbital_position += ((descriptor.getOrbitalPosition()) & 0xF);
168 if (orbital_position && (!descriptor.getWestEastFlag()))
169 orbital_position = 3600 - orbital_position;
170 system = descriptor.getModulationSystem();
171 modulation = descriptor.getModulation();
172 if (system == eDVBFrontendParametersSatellite::System_DVB_S && modulation == eDVBFrontendParametersSatellite::Modulation_8PSK)
174 eDebug("satellite_delivery_descriptor non valid modulation type.. force QPSK");
175 modulation=eDVBFrontendParametersSatellite::Modulation_QPSK;
177 rolloff = descriptor.getRollOff();
178 if (system == eDVBFrontendParametersSatellite::System_DVB_S2)
180 eDebug("SAT DVB-S2 freq %d, %s, pos %d, sr %d, fec %d, modulation %d, rolloff %d",
182 polarisation ? "hor" : "vert",
190 eDebug("SAT DVB-S freq %d, %s, pos %d, sr %d, fec %d",
192 polarisation ? "hor" : "vert",
198 void eDVBFrontendParametersCable::set(const CableDeliverySystemDescriptor &descriptor)
200 frequency = descriptor.getFrequency() / 10;
201 symbol_rate = descriptor.getSymbolRate() * 100;
202 fec_inner = descriptor.getFecInner();
203 if ( fec_inner != eDVBFrontendParametersCable::FEC_None && fec_inner > eDVBFrontendParametersCable::FEC_8_9 )
204 fec_inner = eDVBFrontendParametersCable::FEC_Auto;
205 modulation = descriptor.getModulation();
206 if ( modulation > 0x5 )
207 modulation = eDVBFrontendParametersCable::Modulation_Auto;
208 inversion = eDVBFrontendParametersCable::Inversion_Unknown;
209 eDebug("Cable freq %d, mod %d, sr %d, fec %d",
211 modulation, symbol_rate, fec_inner);
214 void eDVBFrontendParametersTerrestrial::set(const TerrestrialDeliverySystemDescriptor &descriptor)
216 frequency = descriptor.getCentreFrequency() * 10;
217 bandwidth = descriptor.getBandwidth();
218 if ( bandwidth > 2 ) // 5Mhz forced to auto
219 bandwidth = eDVBFrontendParametersTerrestrial::Bandwidth_Auto;
220 code_rate_HP = descriptor.getCodeRateHpStream();
221 if (code_rate_HP > 4)
222 code_rate_HP = eDVBFrontendParametersTerrestrial::FEC_Auto;
223 code_rate_LP = descriptor.getCodeRateLpStream();
224 if (code_rate_LP > 4)
225 code_rate_LP = eDVBFrontendParametersTerrestrial::FEC_Auto;
226 transmission_mode = descriptor.getTransmissionMode();
227 if (transmission_mode > 1) // TM4k forced to auto
228 transmission_mode = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto;
229 guard_interval = descriptor.getGuardInterval();
230 if (guard_interval > 3)
231 guard_interval = eDVBFrontendParametersTerrestrial::GuardInterval_Auto;
232 hierarchy = descriptor.getHierarchyInformation()&3;
233 modulation = descriptor.getConstellation();
235 modulation = eDVBFrontendParametersTerrestrial::Modulation_Auto;
236 inversion = eDVBFrontendParametersTerrestrial::Inversion_Unknown;
237 eDebug("Terr freq %d, bw %d, cr_hp %d, cr_lp %d, tm_mode %d, guard %d, hierarchy %d, const %d",
238 frequency, bandwidth, code_rate_HP, code_rate_LP, transmission_mode,
239 guard_interval, hierarchy, modulation);
242 eDVBFrontendParameters::eDVBFrontendParameters()
243 :m_type(-1), m_flags(0)
247 DEFINE_REF(eDVBFrontendParameters);
249 RESULT eDVBFrontendParameters::getSystem(int &t) const
257 RESULT eDVBFrontendParameters::getDVBS(eDVBFrontendParametersSatellite &p) const
259 if (m_type != iDVBFrontend::feSatellite)
265 RESULT eDVBFrontendParameters::getDVBC(eDVBFrontendParametersCable &p) const
267 if (m_type != iDVBFrontend::feCable)
273 RESULT eDVBFrontendParameters::getDVBT(eDVBFrontendParametersTerrestrial &p) const
275 if (m_type != iDVBFrontend::feTerrestrial)
281 RESULT eDVBFrontendParameters::setDVBS(const eDVBFrontendParametersSatellite &p, bool no_rotor_command_on_tune)
284 sat.no_rotor_command_on_tune = no_rotor_command_on_tune;
285 m_type = iDVBFrontend::feSatellite;
289 RESULT eDVBFrontendParameters::setDVBC(const eDVBFrontendParametersCable &p)
292 m_type = iDVBFrontend::feCable;
296 RESULT eDVBFrontendParameters::setDVBT(const eDVBFrontendParametersTerrestrial &p)
299 m_type = iDVBFrontend::feTerrestrial;
303 RESULT eDVBFrontendParameters::calculateDifference(const iDVBFrontendParameters *parm, int &diff, bool exact) const
308 if (parm->getSystem(type))
312 diff = 1<<30; // big difference
318 case iDVBFrontend::feSatellite:
320 eDVBFrontendParametersSatellite osat;
321 if (parm->getDVBS(osat))
324 if (sat.orbital_position != osat.orbital_position)
326 else if (sat.polarisation != osat.polarisation)
328 else if (exact && sat.fec != osat.fec && sat.fec != eDVBFrontendParametersSatellite::FEC_Auto && osat.fec != eDVBFrontendParametersSatellite::FEC_Auto)
330 else if (exact && sat.modulation != osat.modulation && sat.modulation != eDVBFrontendParametersSatellite::Modulation_Auto && osat.modulation != eDVBFrontendParametersSatellite::Modulation_Auto)
334 diff = abs(sat.frequency - osat.frequency);
335 diff += abs(sat.symbol_rate - osat.symbol_rate);
339 case iDVBFrontend::feCable:
340 eDVBFrontendParametersCable ocable;
341 if (parm->getDVBC(ocable))
344 if (exact && cable.modulation != ocable.modulation
345 && cable.modulation != eDVBFrontendParametersCable::Modulation_Auto
346 && ocable.modulation != eDVBFrontendParametersCable::Modulation_Auto)
348 else if (exact && cable.fec_inner != ocable.fec_inner && cable.fec_inner != eDVBFrontendParametersCable::FEC_Auto && ocable.fec_inner != eDVBFrontendParametersCable::FEC_Auto)
352 diff = abs(cable.frequency - ocable.frequency);
353 diff += abs(cable.symbol_rate - ocable.symbol_rate);
356 case iDVBFrontend::feTerrestrial:
357 eDVBFrontendParametersTerrestrial oterrestrial;
358 if (parm->getDVBT(oterrestrial))
361 if (exact && oterrestrial.bandwidth != terrestrial.bandwidth &&
362 oterrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth_Auto &&
363 terrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth_Auto)
365 else if (exact && oterrestrial.modulation != terrestrial.modulation &&
366 oterrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation_Auto &&
367 terrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation_Auto)
369 else if (exact && oterrestrial.transmission_mode != terrestrial.transmission_mode &&
370 oterrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode_Auto &&
371 terrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode_Auto)
373 else if (exact && oterrestrial.guard_interval != terrestrial.guard_interval &&
374 oterrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval_Auto &&
375 terrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval_Auto)
377 else if (exact && oterrestrial.hierarchy != terrestrial.hierarchy &&
378 oterrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy_Auto &&
379 terrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy_Auto)
381 else if (exact && oterrestrial.code_rate_LP != terrestrial.code_rate_LP &&
382 oterrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC_Auto &&
383 terrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC_Auto)
385 else if (exact && oterrestrial.code_rate_HP != terrestrial.code_rate_HP &&
386 oterrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC_Auto &&
387 terrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC_Auto)
390 diff = abs(terrestrial.frequency - oterrestrial.frequency) / 1000;
398 RESULT eDVBFrontendParameters::getHash(unsigned long &hash) const
402 case iDVBFrontend::feSatellite:
404 hash = (sat.orbital_position << 16);
405 hash |= ((sat.frequency/1000)&0xFFFF)|((sat.polarisation&1) << 15);
408 case iDVBFrontend::feCable:
410 hash |= (cable.frequency/1000)&0xFFFF;
412 case iDVBFrontend::feTerrestrial:
414 hash |= (terrestrial.frequency/1000000)&0xFFFF;
421 RESULT eDVBFrontendParameters::calcLockTimeout(unsigned int &timeout) const
425 case iDVBFrontend::feSatellite:
427 /* high symbol rate transponders tune faster, due to
428 requiring less zigzag and giving more symbols faster.
430 5s are definitely not enough on really low SR when
431 zigzag has to find the exact frequency first.
433 if (sat.symbol_rate > 20000000)
435 else if (sat.symbol_rate > 10000000)
441 case iDVBFrontend::feCable:
444 case iDVBFrontend::feTerrestrial:
452 DEFINE_REF(eDVBFrontend);
454 int eDVBFrontend::PriorityOrder=0;
456 eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok, bool simulate)
457 :m_simulate(simulate), m_enabled(false), m_type(-1), m_dvbid(fe), m_slotid(fe)
458 ,m_fd(-1), m_rotor_mode(false), m_need_rotor_workaround(false), m_can_handle_dvbs2(false)
459 ,m_state(stateClosed), m_timeout(0), m_tuneTimer(0)
460 #if HAVE_DVB_API_VERSION < 3
464 #if HAVE_DVB_API_VERSION < 3
465 sprintf(m_filename, "/dev/dvb/card%d/frontend%d", adap, fe);
466 sprintf(m_sec_filename, "/dev/dvb/card%d/sec%d", adap, fe);
468 sprintf(m_filename, "/dev/dvb/adapter%d/frontend%d", adap, fe);
471 m_timeout = eTimer::create(eApp);
472 CONNECT(m_timeout->timeout, eDVBFrontend::timeout);
474 m_tuneTimer = eTimer::create(eApp);
475 CONNECT(m_tuneTimer->timeout, eDVBFrontend::tuneLoop);
477 for (int i=0; i<eDVBFrontend::NUM_DATA_ENTRIES; ++i)
480 m_idleInputpower[0]=m_idleInputpower[1]=0;
482 ok = !openFrontend();
486 void eDVBFrontend::reopenFrontend()
493 int eDVBFrontend::openFrontend()
495 if (m_state != stateClosed)
496 return -1; // already opened
501 #if HAVE_DVB_API_VERSION < 3
502 FrontendInfo fe_info;
504 dvb_frontend_info fe_info;
506 eDebugNoSimulate("opening frontend %d", m_dvbid);
509 if (!m_simulate || m_type == -1)
511 m_fd = ::open(m_filename, O_RDWR|O_NONBLOCK);
514 eWarning("failed! (%s) %m", m_filename);
520 eWarning("frontend %d already opened", m_dvbid);
523 if (::ioctl(m_fd, FE_GET_INFO, &fe_info) < 0)
525 eWarning("ioctl FE_GET_INFO failed");
531 switch (fe_info.type)
534 m_type = iDVBFrontend::feSatellite;
537 m_type = iDVBFrontend::feCable;
540 m_type = iDVBFrontend::feTerrestrial;
543 eWarning("unknown frontend type.");
548 eDebugNoSimulate("detected %s frontend", "satellite\0cable\0 terrestrial"+fe_info.type*10);
551 #if HAVE_DVB_API_VERSION < 3
552 if (m_type == iDVBFrontend::feSatellite)
558 m_secfd = ::open(m_sec_filename, O_RDWR);
561 eWarning("failed! (%s) %m", m_sec_filename);
569 eWarning("sec %d already opened", m_dvbid);
573 setTone(iDVBFrontend::toneOff);
574 setVoltage(iDVBFrontend::voltageOff);
578 m_sn = eSocketNotifier::create(eApp, m_fd, eSocketNotifier::Read, false);
579 CONNECT(m_sn->activated, eDVBFrontend::feEvent);
585 int eDVBFrontend::closeFrontend(bool force)
587 if (!force && m_data[CUR_VOLTAGE] != -1 && m_data[CUR_VOLTAGE] != iDVBFrontend::voltageOff)
589 long tmp = m_data[LINKED_NEXT_PTR];
592 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
593 if (linked_fe->m_inuse)
595 eDebugNoSimulate("dont close frontend %d until the linked frontend %d in slot %d is still in use",
596 m_dvbid, linked_fe->m_frontend->getDVBID(), linked_fe->m_frontend->getSlotID());
599 linked_fe->m_frontend->getData(LINKED_NEXT_PTR, tmp);
605 eDebugNoSimulate("close frontend %d", m_dvbid);
606 if (m_data[SATCR] != -1)
608 turnOffSatCR(m_data[SATCR]);
610 setTone(iDVBFrontend::toneOff);
611 setVoltage(iDVBFrontend::voltageOff);
613 if (m_sec && !m_simulate)
614 m_sec->setRotorMoving(m_slotid, false);
618 eWarning("couldnt close frontend %d", m_dvbid);
622 setTone(iDVBFrontend::toneOff);
623 setVoltage(iDVBFrontend::voltageOff);
625 #if HAVE_DVB_API_VERSION < 3
628 if (!::close(m_secfd))
631 eWarning("couldnt close sec %d", m_dvbid);
635 m_state = stateClosed;
640 eDVBFrontend::~eDVBFrontend()
642 m_data[LINKED_PREV_PTR] = m_data[LINKED_NEXT_PTR] = -1;
646 void eDVBFrontend::feEvent(int w)
648 eDVBFrontend *sec_fe = this;
649 long tmp = m_data[LINKED_PREV_PTR];
652 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
653 sec_fe = linked_fe->m_frontend;
654 sec_fe->getData(LINKED_NEXT_PTR, tmp);
658 #if HAVE_DVB_API_VERSION < 3
661 dvb_frontend_event event;
665 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
667 if (res && (errno == EAGAIN))
673 #if HAVE_DVB_API_VERSION < 3
674 if (event.type == FE_COMPLETION_EV)
676 eDebug("(%d)fe event: status %x, inversion %s, m_tuning %d", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off", m_tuning);
677 if (event.status & FE_HAS_LOCK)
685 #if HAVE_DVB_API_VERSION >= 3
686 if (event.status & FE_TIMEDOUT) {
687 eDebug("FE_TIMEDOUT! ..abort");
700 eDebug("stateLostLock");
701 state = stateLostLock;
703 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
706 if (m_state != state)
709 m_stateChanged(this);
714 void eDVBFrontend::timeout()
717 if (m_state == stateTuning)
719 m_state = stateFailed;
720 m_stateChanged(this);
724 #define INRANGE(X,Y,Z) (((X<=Y) && (Y<=Z))||((Z<=Y) && (Y<=X)) ? 1 : 0)
726 /* unsigned 32 bit division */
727 static inline uint32_t fe_udiv(uint32_t a, uint32_t b)
729 return (a + b / 2) / b;
732 int eDVBFrontend::readFrontendData(int type)
741 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
742 eDebug("FE_READ_BER failed (%m)");
747 case signalQualitydB: /* this will move into the driver */
749 int sat_max = 1600; // for stv0288 / bsbe2
750 int ret = 0x12345678;
754 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
755 eDebug("FE_READ_SNR failed (%m)");
756 else if (!strcmp(m_description, "BCM4501 (internal)"))
758 float SDS_SNRE = snr << 16;
761 if (oparm.sat.system == eDVBFrontendParametersSatellite::System_DVB_S) // DVB-S1 / QPSK
763 static float SNR_COEFF[6] = {
766 197418.0 / 4194304.0,
767 -2602183.0 / 4194304.0,
768 20377212.0 / 4194304.0,
769 -37791203.0 / 4194304.0,
771 float fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0)),
772 fval2 = pow(10.0, fval1)-1;
773 fval1 = 10.0 * log10(fval2);
777 fval2 = SNR_COEFF[0];
778 for (int i=1; i<6; ++i)
781 fval2 += SNR_COEFF[i];
787 #if HAVE_DVB_API_VERSION >= 3
790 float fval1 = SDS_SNRE / 268435456.0,
793 if (parm_u_qpsk_fec_inner <= FEC_S2_QPSK_9_10) // DVB-S2 QPSK
804 fval4 = -10.0 * log10(fval1);
806 for (int i=0; i < 5; ++i)
807 fval1 = fval4 - fval2 * log10(1.0+pow(10.0, (fval3-fval1)/fval2));
812 ret = (int)(snr_in_db * 100);
814 else if (strstr(m_description, "Alps BSBE1 C01A") ||
815 strstr(m_description, "Alps -S(STV0288)"))
819 else if (snr == 0xFFFF) // i think this should not happen
823 enum { REALVAL, REGVAL };
824 const long CN_lookup[31][2] = {
825 {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
826 {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
827 {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
828 {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
829 {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
830 {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
833 int add=strchr(m_description, '.') ? 0xA250 : 0xA100;
834 long regval = 0xFFFF - ((snr / 3) + add), // revert some dvb api calulations to get the real register value
838 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
843 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[i][REGVAL]))
848 ret = (((regval - CN_lookup[Imin][REGVAL])
849 * (CN_lookup[Imax][REALVAL] - CN_lookup[Imin][REALVAL])
850 / (CN_lookup[Imax][REGVAL] - CN_lookup[Imin][REGVAL]))
851 + CN_lookup[Imin][REALVAL]) * 10;
857 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
858 !strcmp(m_description, "Alps -S") ||
859 !strcmp(m_description, "Philips -S") ||
860 !strcmp(m_description, "LG -S") )
863 ret = (int)((snr-39075)/17.647);
864 } else if (!strcmp(m_description, "Alps BSBE2"))
866 ret = (int)((snr >> 7) * 10);
867 } else if (!strcmp(m_description, "Philips CU1216Mk3"))
869 int mse = (~snr) & 0xFF;
870 switch (parm_u_qam_modulation) {
871 case QAM_16: ret = fe_udiv(1950000, (32 * mse) + 138) + 1000; break;
872 case QAM_32: ret = fe_udiv(2150000, (40 * mse) + 500) + 1350; break;
873 case QAM_64: ret = fe_udiv(2100000, (40 * mse) + 500) + 1250; break;
874 case QAM_128: ret = fe_udiv(1850000, (38 * mse) + 400) + 1380; break;
875 case QAM_256: ret = fe_udiv(1800000, (100 * mse) + 40) + 2030; break;
878 } else if (!strcmp(m_description, "Philips TU1216"))
880 snr = 0xFF - (snr & 0xFF);
882 ret = 10 * (int)(-100 * (log10(snr) - log10(255)));
884 else if (strstr(m_description, "BCM4506") || strstr(m_description, "BCM4505"))
885 ret = (snr * 100) >> 8;
887 if (type == signalQuality)
889 if (ret == 0x12345678) // no snr db calculation avail.. return untouched snr value..
894 return ret >= sat_max ? 65536 : ret * 65536 / sat_max;
895 case feCable: // we assume a max of 42db here
896 return ret >= 4200 ? 65536 : ret * 65536 / 4200;
897 case feTerrestrial: // we assume a max of 24db here
898 return ret >= 2400 ? 65536 : ret * 65536 / 2400;
902 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
910 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
911 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
917 #if HAVE_DVB_API_VERSION < 3
918 FrontendStatus status=0;
924 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
925 eDebug("FE_READ_STATUS failed (%m)");
926 return !!(status&FE_HAS_LOCK);
932 #if HAVE_DVB_API_VERSION < 3
933 FrontendStatus status=0;
939 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
940 eDebug("FE_READ_STATUS failed (%m)");
941 return !!(status&FE_HAS_SYNC);
951 void PutToDict(ePyObject &dict, const char*key, long value)
953 ePyObject item = PyInt_FromLong(value);
956 if (PyDict_SetItemString(dict, key, item))
957 eDebug("put %s to dict failed", key);
961 eDebug("could not create PyObject for %s", key);
964 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
968 if (PyDict_SetItemString(dict, key, item))
969 eDebug("put %s to dict failed", key);
973 eDebug("invalid PyObject for %s", key);
976 void PutToDict(ePyObject &dict, const char*key, const char *value)
978 ePyObject item = PyString_FromString(value);
981 if (PyDict_SetItemString(dict, key, item))
982 eDebug("put %s to dict failed", key);
986 eDebug("could not create PyObject for %s", key);
989 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
991 PutToDict(dict, "tuner_type", "DVB-S");
992 PutToDict(dict, "frequency", feparm.frequency);
993 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
994 PutToDict(dict, "orbital_position", feparm.orbital_position);
995 PutToDict(dict, "inversion", feparm.inversion);
996 PutToDict(dict, "fec_inner", feparm.fec);
997 PutToDict(dict, "modulation", feparm.modulation);
998 PutToDict(dict, "polarization", feparm.polarisation);
999 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S2)
1001 PutToDict(dict, "rolloff", feparm.rolloff);
1002 PutToDict(dict, "pilot", feparm.pilot);
1004 PutToDict(dict, "system", feparm.system);
1007 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
1009 PutToDict(dict, "tuner_type", "DVB-T");
1010 PutToDict(dict, "frequency", feparm.frequency);
1011 PutToDict(dict, "bandwidth", feparm.bandwidth);
1012 PutToDict(dict, "code_rate_lp", feparm.code_rate_LP);
1013 PutToDict(dict, "code_rate_hp", feparm.code_rate_HP);
1014 PutToDict(dict, "constellation", feparm.modulation);
1015 PutToDict(dict, "transmission_mode", feparm.transmission_mode);
1016 PutToDict(dict, "guard_interval", feparm.guard_interval);
1017 PutToDict(dict, "hierarchy_information", feparm.hierarchy);
1018 PutToDict(dict, "inversion", feparm.inversion);
1021 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
1023 PutToDict(dict, "tuner_type", "DVB-C");
1024 PutToDict(dict, "frequency", feparm.frequency);
1025 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
1026 PutToDict(dict, "modulation", feparm.modulation);
1027 PutToDict(dict, "inversion", feparm.inversion);
1028 PutToDict(dict, "fec_inner", feparm.fec_inner);
1031 #if HAVE_DVB_API_VERSION >= 5
1032 static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, struct dtv_property *p, long freq_offset, int orb_pos, int polarization)
1035 int frequency = parm_frequency + freq_offset;
1036 PutToDict(dict, "frequency", frequency);
1037 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
1038 PutToDict(dict, "orbital_position", orb_pos);
1039 PutToDict(dict, "polarization", polarization);
1041 switch(parm_u_qpsk_fec_inner)
1043 case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1044 case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1045 case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1046 case FEC_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
1047 case FEC_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
1048 case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1049 case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1050 case FEC_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
1051 case FEC_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1052 case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
1053 case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
1054 default: eDebug("got unsupported FEC from frontend! report as FEC_AUTO!\n");
1057 switch (p[0].u.data)
1059 default: eDebug("got unsupported system from frontend! report as DVBS!");
1060 case SYS_DVBS: tmp = eDVBFrontendParametersSatellite::System_DVB_S; break;
1063 switch (p[2].u.data)
1065 default: eDebug("got unsupported rolloff from frontend! report as 0_20!");
1066 case ROLLOFF_20: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1067 case ROLLOFF_25: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1068 case ROLLOFF_35: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1070 PutToDict(dict, "rolloff", tmp);
1072 switch (p[3].u.data)
1074 case PILOT_OFF: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1075 case PILOT_ON: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1076 case PILOT_AUTO: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1078 PutToDict(dict, "pilot", tmp);
1080 tmp = eDVBFrontendParametersSatellite::System_DVB_S2; break;
1083 PutToDict(dict, "system", tmp);
1085 switch (p[1].u.data)
1087 default: eDebug("got unsupported modulation from frontend! report as QPSK!");
1088 case QPSK: tmp = eDVBFrontendParametersSatellite::Modulation_QPSK; break;
1089 case PSK_8: tmp = eDVBFrontendParametersSatellite::Modulation_8PSK; break;
1091 PutToDict(dict, "modulation", tmp);
1095 static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, long freq_offset, int orb_pos, int polarization)
1098 int frequency = parm_frequency + freq_offset;
1099 PutToDict(dict, "frequency", frequency);
1100 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
1101 PutToDict(dict, "orbital_position", orb_pos);
1102 PutToDict(dict, "polarization", polarization);
1104 switch((int)parm_u_qpsk_fec_inner)
1106 case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1107 case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1108 case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1109 case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1110 case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1111 case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
1113 case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
1114 #if HAVE_DVB_API_VERSION >=3
1115 case FEC_S2_8PSK_1_2:
1116 case FEC_S2_QPSK_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1117 case FEC_S2_8PSK_2_3:
1118 case FEC_S2_QPSK_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1119 case FEC_S2_8PSK_3_4:
1120 case FEC_S2_QPSK_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1121 case FEC_S2_8PSK_5_6:
1122 case FEC_S2_QPSK_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1123 case FEC_S2_8PSK_7_8:
1124 case FEC_S2_QPSK_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1125 case FEC_S2_8PSK_8_9:
1126 case FEC_S2_QPSK_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
1127 case FEC_S2_8PSK_3_5:
1128 case FEC_S2_QPSK_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
1129 case FEC_S2_8PSK_4_5:
1130 case FEC_S2_QPSK_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
1131 case FEC_S2_8PSK_9_10:
1132 case FEC_S2_QPSK_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1135 PutToDict(dict, "fec_inner", tmp);
1136 #if HAVE_DVB_API_VERSION >=3
1137 PutToDict(dict, "modulation",
1138 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ?
1139 eDVBFrontendParametersSatellite::Modulation_8PSK :
1140 eDVBFrontendParametersSatellite::Modulation_QPSK );
1141 if (parm_u_qpsk_fec_inner > FEC_AUTO)
1143 switch(parm_inversion & 0xc)
1145 default: // unknown rolloff
1146 case 0: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1147 case 4: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1148 case 8: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1150 PutToDict(dict, "rolloff", tmp);
1151 switch(parm_inversion & 0x30)
1153 case 0: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1154 case 0x10: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1155 case 0x20: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1157 PutToDict(dict, "pilot", tmp);
1158 tmp = eDVBFrontendParametersSatellite::System_DVB_S2;
1161 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1163 PutToDict(dict, "modulation", eDVBFrontendParametersSatellite::Modulation_QPSK );
1164 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1166 PutToDict(dict, "system", tmp);
1170 static void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1173 #if HAVE_DVB_API_VERSION < 3
1174 PutToDict(dict, "frequency", parm_frequency);
1176 PutToDict(dict, "frequency", parm_frequency/1000);
1178 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1179 switch(parm_u_qam_fec_inner)
1181 case FEC_NONE: tmp = eDVBFrontendParametersCable::FEC_None; break;
1182 case FEC_1_2: tmp = eDVBFrontendParametersCable::FEC_1_2; break;
1183 case FEC_2_3: tmp = eDVBFrontendParametersCable::FEC_2_3; break;
1184 case FEC_3_4: tmp = eDVBFrontendParametersCable::FEC_3_4; break;
1185 case FEC_5_6: tmp = eDVBFrontendParametersCable::FEC_5_6; break;
1186 case FEC_7_8: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1187 #if HAVE_DVB_API_VERSION >= 3
1188 case FEC_8_9: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1191 case FEC_AUTO: tmp = eDVBFrontendParametersCable::FEC_Auto; break;
1193 PutToDict(dict, "fec_inner", tmp);
1194 switch(parm_u_qam_modulation)
1196 case QAM_16: tmp = eDVBFrontendParametersCable::Modulation_QAM16; break;
1197 case QAM_32: tmp = eDVBFrontendParametersCable::Modulation_QAM32; break;
1198 case QAM_64: tmp = eDVBFrontendParametersCable::Modulation_QAM64; break;
1199 case QAM_128: tmp = eDVBFrontendParametersCable::Modulation_QAM128; break;
1200 case QAM_256: tmp = eDVBFrontendParametersCable::Modulation_QAM256; break;
1202 case QAM_AUTO: tmp = eDVBFrontendParametersCable::Modulation_Auto; break;
1204 PutToDict(dict, "modulation", tmp);
1207 static void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1210 PutToDict(dict, "frequency", parm_frequency);
1211 switch (parm_u_ofdm_bandwidth)
1213 case BANDWIDTH_8_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_8MHz; break;
1214 case BANDWIDTH_7_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_7MHz; break;
1215 case BANDWIDTH_6_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_6MHz; break;
1217 case BANDWIDTH_AUTO: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_Auto; break;
1219 PutToDict(dict, "bandwidth", tmp);
1220 switch (parm_u_ofdm_code_rate_LP)
1222 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1223 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1224 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1225 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1226 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1228 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1230 PutToDict(dict, "code_rate_lp", tmp);
1231 switch (parm_u_ofdm_code_rate_HP)
1233 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1234 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1235 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1236 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1237 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1239 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1241 PutToDict(dict, "code_rate_hp", tmp);
1242 switch (parm_u_ofdm_constellation)
1244 case QPSK: tmp = eDVBFrontendParametersTerrestrial::Modulation_QPSK; break;
1245 case QAM_16: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM16; break;
1246 case QAM_64: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM64; break;
1248 case QAM_AUTO: tmp = eDVBFrontendParametersTerrestrial::Modulation_Auto; break;
1250 PutToDict(dict, "constellation", tmp);
1251 switch (parm_u_ofdm_transmission_mode)
1253 case TRANSMISSION_MODE_2K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_2k; break;
1254 case TRANSMISSION_MODE_8K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_8k; break;
1256 case TRANSMISSION_MODE_AUTO: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto; break;
1258 PutToDict(dict, "transmission_mode", tmp);
1259 switch (parm_u_ofdm_guard_interval)
1261 case GUARD_INTERVAL_1_32: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_32; break;
1262 case GUARD_INTERVAL_1_16: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_16; break;
1263 case GUARD_INTERVAL_1_8: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_8; break;
1264 case GUARD_INTERVAL_1_4: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_4; break;
1266 case GUARD_INTERVAL_AUTO: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_Auto; break;
1268 PutToDict(dict, "guard_interval", tmp);
1269 switch (parm_u_ofdm_hierarchy_information)
1271 case HIERARCHY_NONE: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_None; break;
1272 case HIERARCHY_1: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_1; break;
1273 case HIERARCHY_2: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_2; break;
1274 case HIERARCHY_4: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_4; break;
1276 case HIERARCHY_AUTO: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_Auto; break;
1278 PutToDict(dict, "hierarchy_information", tmp);
1281 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1283 if (dest && PyDict_Check(dest))
1285 const char *tmp = "UNKNOWN";
1306 PutToDict(dest, "tuner_state", tmp);
1307 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1308 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1309 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1310 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1311 int sigQualitydB = readFrontendData(signalQualitydB);
1312 if (sigQualitydB == 0x12345678) // not support yet
1314 ePyObject obj=Py_None;
1316 PutToDict(dest, "tuner_signal_quality_db", obj);
1319 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1320 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1324 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1326 if (dest && PyDict_Check(dest))
1328 FRONTENDPARAMETERS front;
1329 #if HAVE_DVB_API_VERSION >= 5
1330 struct dtv_property p[4];
1331 struct dtv_properties cmdseq;
1334 p[0].cmd = DTV_DELIVERY_SYSTEM;
1335 p[1].cmd = DTV_MODULATION;
1336 p[2].cmd = DTV_ROLLOFF;
1337 p[3].cmd = DTV_PILOT;
1339 if (m_simulate || m_fd == -1 || original)
1341 #if HAVE_DVB_API_VERSION >= 5
1342 else if (m_type == feSatellite && // yet just use new api for DVB-S(2) only
1343 ioctl(m_fd, FE_GET_PROPERTY, &cmdseq)<0)
1345 eDebug("FE_GET_PROPERTY failed (%m)");
1349 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1351 eDebug("FE_GET_FRONTEND failed (%m)");
1359 PutSatelliteDataToDict(dest, oparm.sat);
1362 PutCableDataToDict(dest, oparm.cab);
1365 PutTerrestrialDataToDict(dest, oparm.ter);
1371 FRONTENDPARAMETERS &parm = front;
1372 long tmp = eDVBFrontendParametersSatellite::Inversion_Unknown;
1373 switch(parm_inversion & 3)
1376 tmp = eDVBFrontendParametersSatellite::Inversion_On;
1379 tmp = eDVBFrontendParametersSatellite::Inversion_Off;
1383 PutToDict(dest, "inversion", tmp);
1387 #if HAVE_DVB_API_VERSION >= 5
1388 fillDictWithSatelliteData(dest, parm, p, m_data[FREQ_OFFSET], oparm.sat.orbital_position, oparm.sat.polarisation);
1390 fillDictWithSatelliteData(dest, parm, m_data[FREQ_OFFSET], oparm.sat.orbital_position, oparm.sat.polarisation);
1394 fillDictWithCableData(dest, parm);
1397 fillDictWithTerrestrialData(dest, parm);
1404 void eDVBFrontend::getFrontendData(ePyObject dest)
1406 if (dest && PyDict_Check(dest))
1409 PutToDict(dest, "tuner_number", m_slotid);
1425 PutToDict(dest, "tuner_type", tmp);
1429 #ifndef FP_IOCTL_GET_ID
1430 #define FP_IOCTL_GET_ID 0
1432 int eDVBFrontend::readInputpower()
1436 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1438 char proc_name2[64];
1439 sprintf(proc_name, "/proc/stb/frontend/%d/lnb_sense", m_slotid);
1440 sprintf(proc_name2, "/proc/stb/fp/lnb_sense%d", m_slotid);
1442 if ((f=fopen(proc_name, "r")) || (f=fopen(proc_name2, "r")))
1444 if (fscanf(f, "%d", &power) != 1)
1445 eDebug("read %s failed!! (%m)", proc_name);
1447 eDebug("%s is %d\n", proc_name, power);
1452 // open front prozessor
1453 int fp=::open("/dev/dbox/fp0", O_RDWR);
1456 eDebug("couldn't open fp");
1459 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1460 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1462 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1471 bool eDVBFrontend::setSecSequencePos(int steps)
1473 eDebugNoSimulate("set sequence pos %d", steps);
1478 if (m_sec_sequence.current() != m_sec_sequence.end())
1479 ++m_sec_sequence.current();
1484 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1485 --m_sec_sequence.current();
1491 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1494 eDVBFrontend *sec_fe = this;
1495 eDVBRegisteredFrontend *regFE = 0;
1496 long tmp = m_data[LINKED_PREV_PTR];
1499 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1500 sec_fe = prev->m_frontend;
1501 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1502 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1503 int state = sec_fe->m_state;
1504 // workaround to put the kernel frontend thread into idle state!
1505 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1507 sec_fe->closeFrontend(true);
1508 state = sec_fe->m_state;
1510 // sec_fe is closed... we must reopen it here..
1511 if (state == stateClosed)
1519 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1521 long *sec_fe_data = sec_fe->m_data;
1522 // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1523 switch (m_sec_sequence.current()->cmd)
1525 case eSecCommand::SLEEP:
1526 delay = m_sec_sequence.current()++->msec;
1527 eDebugNoSimulate("[SEC] sleep %dms", delay);
1529 case eSecCommand::GOTO:
1530 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1531 ++m_sec_sequence.current();
1533 case eSecCommand::SET_VOLTAGE:
1535 int voltage = m_sec_sequence.current()++->voltage;
1536 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1537 sec_fe->setVoltage(voltage);
1540 case eSecCommand::IF_VOLTAGE_GOTO:
1542 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1543 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1545 ++m_sec_sequence.current();
1548 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1550 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1551 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1553 ++m_sec_sequence.current();
1556 case eSecCommand::IF_TONE_GOTO:
1558 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1559 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1561 ++m_sec_sequence.current();
1564 case eSecCommand::IF_NOT_TONE_GOTO:
1566 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1567 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1569 ++m_sec_sequence.current();
1572 case eSecCommand::SET_TONE:
1573 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1574 sec_fe->setTone(m_sec_sequence.current()++->tone);
1576 case eSecCommand::SEND_DISEQC:
1577 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1578 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1579 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1580 eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1581 if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
1582 eDebugNoSimulate("(DiSEqC reset)");
1583 else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
1584 eDebugNoSimulate("(DiSEqC peripherial power on)");
1586 eDebugNoSimulate("");
1587 ++m_sec_sequence.current();
1589 case eSecCommand::SEND_TONEBURST:
1590 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1591 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1593 case eSecCommand::SET_FRONTEND:
1595 int enableEvents = (m_sec_sequence.current()++)->val;
1596 eDebugNoSimulate("[SEC] setFrontend %d", enableEvents);
1597 setFrontend(enableEvents);
1600 case eSecCommand::START_TUNE_TIMEOUT:
1602 int tuneTimeout = m_sec_sequence.current()->timeout;
1603 eDebugNoSimulate("[SEC] startTuneTimeout %d", tuneTimeout);
1605 m_timeout->start(tuneTimeout, 1);
1606 ++m_sec_sequence.current();
1609 case eSecCommand::SET_TIMEOUT:
1610 m_timeoutCount = m_sec_sequence.current()++->val;
1611 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1613 case eSecCommand::IF_TIMEOUT_GOTO:
1614 if (!m_timeoutCount)
1616 eDebugNoSimulate("[SEC] rotor timout");
1617 setSecSequencePos(m_sec_sequence.current()->steps);
1620 ++m_sec_sequence.current();
1622 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1624 int idx = m_sec_sequence.current()++->val;
1625 if ( idx == 0 || idx == 1 )
1627 m_idleInputpower[idx] = sec_fe->readInputpower();
1628 eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1631 eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1634 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1636 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1637 int idx = compare.val;
1638 if ( !m_simulate && (idx == 0 || idx == 1) )
1640 int idle = sec_fe->readInputpower();
1641 int diff = abs(idle-m_idleInputpower[idx]);
1644 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1645 setSecSequencePos(compare.steps);
1649 ++m_sec_sequence.current();
1652 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1654 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1657 setSecSequencePos(cmd.steps);
1661 int isLocked = readFrontendData(locked);
1662 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1664 if (!m_timeoutCount && m_retryCount > 0)
1666 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 40) || !cmd.lastSignal))
1669 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1672 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1674 cmd.lastSignal = signal;
1677 if (cmd.okcount > 4)
1679 eDebugNoSimulate("ok > 4 .. goto %d\n", cmd.steps);
1680 setSecSequencePos(cmd.steps);
1681 m_state = stateLock;
1682 m_stateChanged(this);
1683 feEvent(-1); // flush events
1691 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1693 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1697 ++m_sec_sequence.current();
1700 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1701 m_runningInputpower = sec_fe->readInputpower();
1702 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1703 ++m_sec_sequence.current();
1705 case eSecCommand::SET_ROTOR_MOVING:
1707 m_sec->setRotorMoving(m_slotid, true);
1708 ++m_sec_sequence.current();
1710 case eSecCommand::SET_ROTOR_STOPPED:
1712 m_sec->setRotorMoving(m_slotid, false);
1713 ++m_sec_sequence.current();
1715 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1717 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1720 setSecSequencePos(cmd.steps);
1723 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1724 const char *txt = cmd.direction ? "running" : "stopped";
1726 if (!m_timeoutCount && m_retryCount > 0)
1728 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1730 m_runningInputpower,
1733 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1734 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1737 eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1738 if ( cmd.okcount > 6 )
1740 eDebugNoSimulate("[SEC] rotor is %s", txt);
1741 if (setSecSequencePos(cmd.steps))
1747 eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1750 ++m_sec_sequence.current();
1753 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1754 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1755 setSecSequencePos(m_sec_sequence.current()->steps);
1757 ++m_sec_sequence.current();
1759 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1760 eDebugNoSimulate("[SEC] invalidate current switch params");
1761 sec_fe_data[CSW] = -1;
1762 sec_fe_data[UCSW] = -1;
1763 sec_fe_data[TONEBURST] = -1;
1764 ++m_sec_sequence.current();
1766 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1767 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1768 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1769 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1770 eDebugNoSimulate("[SEC] update current switch params");
1771 ++m_sec_sequence.current();
1773 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1774 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1775 sec_fe_data[ROTOR_CMD] = -1;
1776 sec_fe_data[ROTOR_POS] = -1;
1777 ++m_sec_sequence.current();
1779 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1780 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1781 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1782 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1783 ++m_sec_sequence.current();
1785 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1786 m_retryCount = m_sec_sequence.current()++->val;
1787 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1789 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1792 eDebugNoSimulate("[SEC] no more rotor retrys");
1793 setSecSequencePos(m_sec_sequence.current()->steps);
1796 ++m_sec_sequence.current();
1798 case eSecCommand::SET_POWER_LIMITING_MODE:
1803 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1804 FILE *f=fopen(proc_name, "w");
1805 if (f) // new interface exist?
1807 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1808 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1809 eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1811 eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1814 else if (sec_fe->m_need_rotor_workaround)
1817 int slotid = sec_fe->m_slotid;
1818 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1820 sprintf(dev, "/dev/i2c/%d", slotid);
1821 else if (slotid == 2)
1822 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1823 else if (slotid == 3)
1824 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1825 int fd = ::open(dev, O_RDWR);
1827 unsigned char data[2];
1828 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1829 if(::read(fd, data, 1) != 1)
1830 eDebugNoSimulate("[SEC] error read lnbp (%m)");
1831 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1833 data[0] |= 0x80; // enable static current limiting
1834 eDebugNoSimulate("[SEC] set static current limiting");
1838 data[0] &= ~0x80; // enable dynamic current limiting
1839 eDebugNoSimulate("[SEC] set dynamic current limiting");
1841 if(::write(fd, data, 1) != 1)
1842 eDebugNoSimulate("[SEC] error write lnbp (%m)");
1846 ++m_sec_sequence.current();
1850 eDebugNoSimulate("[SEC] unhandled sec command %d",
1851 ++m_sec_sequence.current()->cmd);
1852 ++m_sec_sequence.current();
1855 m_tuneTimer->start(delay,true);
1859 if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1863 void eDVBFrontend::setFrontend(bool recvEvents)
1867 eDebug("setting frontend %d", m_dvbid);
1870 feEvent(-1); // flush events
1871 #if HAVE_DVB_API_VERSION >= 5
1872 if (m_type == iDVBFrontend::feSatellite)
1874 fe_rolloff_t rolloff = ROLLOFF_35;
1875 fe_pilot_t pilot = PILOT_OFF;
1876 fe_modulation_t modulation = QPSK;
1877 fe_delivery_system_t system = SYS_DVBS;
1878 switch(oparm.sat.system)
1880 case eDVBFrontendParametersSatellite::System_DVB_S: system = SYS_DVBS; break;
1881 case eDVBFrontendParametersSatellite::System_DVB_S2: system = SYS_DVBS2; break;
1883 switch(oparm.sat.modulation)
1885 case eDVBFrontendParametersSatellite::Modulation_QPSK: modulation = QPSK; break;
1886 case eDVBFrontendParametersSatellite::Modulation_8PSK: modulation = PSK_8; break;
1887 case eDVBFrontendParametersSatellite::Modulation_QAM16: modulation = QAM_16; break;
1889 switch(oparm.sat.pilot)
1891 case eDVBFrontendParametersSatellite::Pilot_Off: pilot = PILOT_OFF; break;
1892 case eDVBFrontendParametersSatellite::Pilot_On: pilot = PILOT_ON; break;
1893 case eDVBFrontendParametersSatellite::Pilot_Unknown: pilot = PILOT_AUTO; break;
1895 switch(oparm.sat.rolloff)
1897 case eDVBFrontendParametersSatellite::RollOff_alpha_0_20: rolloff = ROLLOFF_20; break;
1898 case eDVBFrontendParametersSatellite::RollOff_alpha_0_25: rolloff = ROLLOFF_25; break;
1899 case eDVBFrontendParametersSatellite::RollOff_alpha_0_35: rolloff = ROLLOFF_35; break;
1901 struct dtv_property p[10];
1902 struct dtv_properties cmdseq;
1904 p[0].cmd = DTV_CLEAR;
1905 p[1].cmd = DTV_DELIVERY_SYSTEM, p[1].u.data = system;
1906 p[2].cmd = DTV_FREQUENCY, p[2].u.data = parm_frequency;
1907 p[3].cmd = DTV_MODULATION, p[3].u.data = modulation;
1908 p[4].cmd = DTV_SYMBOL_RATE, p[4].u.data = parm_u_qpsk_symbol_rate;
1909 p[5].cmd = DTV_INNER_FEC, p[5].u.data = parm_u_qpsk_fec_inner;
1910 p[6].cmd = DTV_INVERSION, p[6].u.data = parm_inversion;
1911 if (system == SYS_DVBS2)
1913 p[7].cmd = DTV_ROLLOFF, p[7].u.data = rolloff;
1914 p[8].cmd = DTV_PILOT, p[8].u.data = pilot;
1915 p[9].cmd = DTV_TUNE;
1920 p[7].cmd = DTV_TUNE;
1923 if (ioctl(m_fd, FE_SET_PROPERTY, &cmdseq) == -1)
1925 perror("FE_SET_PROPERTY failed");
1932 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1934 perror("FE_SET_FRONTEND failed");
1941 RESULT eDVBFrontend::getFrontendType(int &t)
1949 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1954 eWarning("no SEC module active!");
1957 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1960 #if HAVE_DVB_API_VERSION >= 3
1961 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d system %d modulation %d pilot %d, rolloff %d",
1964 feparm.polarisation,
1968 feparm.orbital_position,
1974 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1977 feparm.polarisation,
1981 feparm.orbital_position);
1983 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1984 switch (feparm.inversion)
1986 case eDVBFrontendParametersSatellite::Inversion_On:
1987 parm_inversion = INVERSION_ON;
1989 case eDVBFrontendParametersSatellite::Inversion_Off:
1990 parm_inversion = INVERSION_OFF;
1993 case eDVBFrontendParametersSatellite::Inversion_Unknown:
1994 parm_inversion = INVERSION_AUTO;
1997 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S)
2001 case eDVBFrontendParametersSatellite::FEC_None:
2002 parm_u_qpsk_fec_inner = FEC_NONE;
2004 case eDVBFrontendParametersSatellite::FEC_1_2:
2005 parm_u_qpsk_fec_inner = FEC_1_2;
2007 case eDVBFrontendParametersSatellite::FEC_2_3:
2008 parm_u_qpsk_fec_inner = FEC_2_3;
2010 case eDVBFrontendParametersSatellite::FEC_3_4:
2011 parm_u_qpsk_fec_inner = FEC_3_4;
2013 case eDVBFrontendParametersSatellite::FEC_5_6:
2014 parm_u_qpsk_fec_inner = FEC_5_6;
2016 case eDVBFrontendParametersSatellite::FEC_7_8:
2017 parm_u_qpsk_fec_inner = FEC_7_8;
2020 eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
2021 case eDVBFrontendParametersSatellite::FEC_Auto:
2022 parm_u_qpsk_fec_inner = FEC_AUTO;
2026 #if HAVE_DVB_API_VERSION >= 3
2031 case eDVBFrontendParametersSatellite::FEC_1_2:
2032 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
2034 case eDVBFrontendParametersSatellite::FEC_2_3:
2035 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
2037 case eDVBFrontendParametersSatellite::FEC_3_4:
2038 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
2040 case eDVBFrontendParametersSatellite::FEC_3_5:
2041 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
2043 case eDVBFrontendParametersSatellite::FEC_4_5:
2044 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
2046 case eDVBFrontendParametersSatellite::FEC_5_6:
2047 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
2049 case eDVBFrontendParametersSatellite::FEC_7_8:
2050 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
2052 case eDVBFrontendParametersSatellite::FEC_8_9:
2053 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
2055 case eDVBFrontendParametersSatellite::FEC_9_10:
2056 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
2059 eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
2062 #if HAVE_DVB_API_VERSION < 5
2063 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
2064 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
2065 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation_8PSK)
2067 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
2068 // 8PSK fec driver values are decimal 9 bigger
2073 // FIXME !!! get frequency range from tuner
2074 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
2076 eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
2079 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
2085 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
2087 #if HAVE_DVB_API_VERSION < 3
2088 parm_frequency = feparm.frequency;
2090 parm_frequency = feparm.frequency * 1000;
2092 parm_u_qam_symbol_rate = feparm.symbol_rate;
2093 switch (feparm.modulation)
2095 case eDVBFrontendParametersCable::Modulation_QAM16:
2096 parm_u_qam_modulation = QAM_16;
2098 case eDVBFrontendParametersCable::Modulation_QAM32:
2099 parm_u_qam_modulation = QAM_32;
2101 case eDVBFrontendParametersCable::Modulation_QAM64:
2102 parm_u_qam_modulation = QAM_64;
2104 case eDVBFrontendParametersCable::Modulation_QAM128:
2105 parm_u_qam_modulation = QAM_128;
2107 case eDVBFrontendParametersCable::Modulation_QAM256:
2108 parm_u_qam_modulation = QAM_256;
2111 case eDVBFrontendParametersCable::Modulation_Auto:
2112 parm_u_qam_modulation = QAM_AUTO;
2115 switch (feparm.inversion)
2117 case eDVBFrontendParametersCable::Inversion_On:
2118 parm_inversion = INVERSION_ON;
2120 case eDVBFrontendParametersCable::Inversion_Off:
2121 parm_inversion = INVERSION_OFF;
2124 case eDVBFrontendParametersCable::Inversion_Unknown:
2125 parm_inversion = INVERSION_AUTO;
2128 switch (feparm.fec_inner)
2130 case eDVBFrontendParametersCable::FEC_None:
2131 parm_u_qam_fec_inner = FEC_NONE;
2133 case eDVBFrontendParametersCable::FEC_1_2:
2134 parm_u_qam_fec_inner = FEC_1_2;
2136 case eDVBFrontendParametersCable::FEC_2_3:
2137 parm_u_qam_fec_inner = FEC_2_3;
2139 case eDVBFrontendParametersCable::FEC_3_4:
2140 parm_u_qam_fec_inner = FEC_3_4;
2142 case eDVBFrontendParametersCable::FEC_5_6:
2143 parm_u_qam_fec_inner = FEC_5_6;
2145 case eDVBFrontendParametersCable::FEC_7_8:
2146 parm_u_qam_fec_inner = FEC_7_8;
2148 #if HAVE_DVB_API_VERSION >= 3
2149 case eDVBFrontendParametersCable::FEC_8_9:
2150 parm_u_qam_fec_inner = FEC_8_9;
2154 case eDVBFrontendParametersCable::FEC_Auto:
2155 parm_u_qam_fec_inner = FEC_AUTO;
2158 eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
2159 parm_frequency/1000,
2160 parm_u_qam_symbol_rate,
2161 parm_u_qam_fec_inner,
2162 parm_u_qam_modulation,
2168 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
2170 parm_frequency = feparm.frequency;
2172 switch (feparm.bandwidth)
2174 case eDVBFrontendParametersTerrestrial::Bandwidth_8MHz:
2175 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
2177 case eDVBFrontendParametersTerrestrial::Bandwidth_7MHz:
2178 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
2180 case eDVBFrontendParametersTerrestrial::Bandwidth_6MHz:
2181 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
2184 case eDVBFrontendParametersTerrestrial::Bandwidth_Auto:
2185 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
2188 switch (feparm.code_rate_LP)
2190 case eDVBFrontendParametersTerrestrial::FEC_1_2:
2191 parm_u_ofdm_code_rate_LP = FEC_1_2;
2193 case eDVBFrontendParametersTerrestrial::FEC_2_3:
2194 parm_u_ofdm_code_rate_LP = FEC_2_3;
2196 case eDVBFrontendParametersTerrestrial::FEC_3_4:
2197 parm_u_ofdm_code_rate_LP = FEC_3_4;
2199 case eDVBFrontendParametersTerrestrial::FEC_5_6:
2200 parm_u_ofdm_code_rate_LP = FEC_5_6;
2202 case eDVBFrontendParametersTerrestrial::FEC_7_8:
2203 parm_u_ofdm_code_rate_LP = FEC_7_8;
2206 case eDVBFrontendParametersTerrestrial::FEC_Auto:
2207 parm_u_ofdm_code_rate_LP = FEC_AUTO;
2210 switch (feparm.code_rate_HP)
2212 case eDVBFrontendParametersTerrestrial::FEC_1_2:
2213 parm_u_ofdm_code_rate_HP = FEC_1_2;
2215 case eDVBFrontendParametersTerrestrial::FEC_2_3:
2216 parm_u_ofdm_code_rate_HP = FEC_2_3;
2218 case eDVBFrontendParametersTerrestrial::FEC_3_4:
2219 parm_u_ofdm_code_rate_HP = FEC_3_4;
2221 case eDVBFrontendParametersTerrestrial::FEC_5_6:
2222 parm_u_ofdm_code_rate_HP = FEC_5_6;
2224 case eDVBFrontendParametersTerrestrial::FEC_7_8:
2225 parm_u_ofdm_code_rate_HP = FEC_7_8;
2228 case eDVBFrontendParametersTerrestrial::FEC_Auto:
2229 parm_u_ofdm_code_rate_HP = FEC_AUTO;
2232 switch (feparm.modulation)
2234 case eDVBFrontendParametersTerrestrial::Modulation_QPSK:
2235 parm_u_ofdm_constellation = QPSK;
2237 case eDVBFrontendParametersTerrestrial::Modulation_QAM16:
2238 parm_u_ofdm_constellation = QAM_16;
2240 case eDVBFrontendParametersTerrestrial::Modulation_QAM64:
2241 parm_u_ofdm_constellation = QAM_64;
2244 case eDVBFrontendParametersTerrestrial::Modulation_Auto:
2245 parm_u_ofdm_constellation = QAM_AUTO;
2248 switch (feparm.transmission_mode)
2250 case eDVBFrontendParametersTerrestrial::TransmissionMode_2k:
2251 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2253 case eDVBFrontendParametersTerrestrial::TransmissionMode_8k:
2254 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2257 case eDVBFrontendParametersTerrestrial::TransmissionMode_Auto:
2258 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2261 switch (feparm.guard_interval)
2263 case eDVBFrontendParametersTerrestrial::GuardInterval_1_32:
2264 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2266 case eDVBFrontendParametersTerrestrial::GuardInterval_1_16:
2267 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2269 case eDVBFrontendParametersTerrestrial::GuardInterval_1_8:
2270 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2272 case eDVBFrontendParametersTerrestrial::GuardInterval_1_4:
2273 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2276 case eDVBFrontendParametersTerrestrial::GuardInterval_Auto:
2277 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2280 switch (feparm.hierarchy)
2282 case eDVBFrontendParametersTerrestrial::Hierarchy_None:
2283 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2285 case eDVBFrontendParametersTerrestrial::Hierarchy_1:
2286 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2288 case eDVBFrontendParametersTerrestrial::Hierarchy_2:
2289 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2291 case eDVBFrontendParametersTerrestrial::Hierarchy_4:
2292 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2295 case eDVBFrontendParametersTerrestrial::Hierarchy_Auto:
2296 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2299 switch (feparm.inversion)
2301 case eDVBFrontendParametersTerrestrial::Inversion_On:
2302 parm_inversion = INVERSION_ON;
2304 case eDVBFrontendParametersTerrestrial::Inversion_Off:
2305 parm_inversion = INVERSION_OFF;
2308 case eDVBFrontendParametersTerrestrial::Inversion_Unknown:
2309 parm_inversion = INVERSION_AUTO;
2316 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2318 unsigned int timeout = 5000;
2319 eDebugNoSimulate("(%d)tune", m_dvbid);
2325 if (!m_sn && !m_simulate)
2327 eDebug("no frontend device opened... do not try to tune !!!");
2341 m_sec_sequence.clear();
2343 where.calcLockTimeout(timeout);
2349 eDVBFrontendParametersSatellite feparm;
2350 if (where.getDVBS(feparm))
2352 eDebug("no dvbs data!");
2356 if (m_rotor_mode != feparm.no_rotor_command_on_tune && !feparm.no_rotor_command_on_tune)
2358 eDVBFrontend *sec_fe = this;
2359 long tmp = m_data[LINKED_PREV_PTR];
2362 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
2363 sec_fe = linked_fe->m_frontend;
2364 sec_fe->getData(LINKED_NEXT_PTR, tmp);
2366 eDebug("(fe%d) reset diseqc after leave rotor mode!", m_dvbid);
2367 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = sec_fe->m_data[ROTOR_CMD] = sec_fe->m_data[ROTOR_POS] = -1; // reset diseqc
2369 m_rotor_mode = feparm.no_rotor_command_on_tune;
2371 m_sec->setRotorMoving(m_slotid, false);
2372 res=prepare_sat(feparm, timeout);
2380 eDVBFrontendParametersCable feparm;
2381 if (where.getDVBC(feparm))
2386 res=prepare_cable(feparm);
2390 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2391 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2396 eDVBFrontendParametersTerrestrial feparm;
2397 if (where.getDVBT(feparm))
2399 eDebug("no -T data");
2403 res=prepare_terrestrial(feparm);
2407 std::string enable_5V;
2408 char configStr[255];
2409 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2410 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2411 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2412 if (enable_5V == "True")
2413 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2415 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2416 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2422 m_sec_sequence.current() = m_sec_sequence.begin();
2426 m_tuneTimer->start(0,true);
2428 if (m_state != stateTuning)
2430 m_state = stateTuning;
2431 m_stateChanged(this);
2440 m_tuneTimer->stop();
2444 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2446 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2450 RESULT eDVBFrontend::setVoltage(int voltage)
2452 if (m_type == feCable)
2454 #if HAVE_DVB_API_VERSION < 3
2457 bool increased=false;
2458 fe_sec_voltage_t vlt;
2460 m_data[CUR_VOLTAGE]=voltage;
2464 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2465 vlt = SEC_VOLTAGE_OFF;
2468 #if HAVE_DVB_API_VERSION < 3
2469 vlt = SEC_VOLTAGE_13_5;
2475 vlt = SEC_VOLTAGE_13;
2478 #if HAVE_DVB_API_VERSION < 3
2479 vlt = SEC_VOLTAGE_18_5;
2485 vlt = SEC_VOLTAGE_18;
2492 #if HAVE_DVB_API_VERSION < 3
2493 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2495 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2496 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2497 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2501 RESULT eDVBFrontend::getState(int &state)
2507 RESULT eDVBFrontend::setTone(int t)
2509 if (m_type != feSatellite)
2511 #if HAVE_DVB_API_VERSION < 3
2514 fe_sec_tone_mode_t tone;
2523 tone = SEC_TONE_OFF;
2530 #if HAVE_DVB_API_VERSION < 3
2531 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2533 return ::ioctl(m_fd, FE_SET_TONE, tone);
2537 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2538 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2541 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2545 #if HAVE_DVB_API_VERSION < 3
2546 struct secCommand cmd;
2547 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2548 cmd.u.diseqc.cmdtype = diseqc.data[0];
2549 cmd.u.diseqc.addr = diseqc.data[1];
2550 cmd.u.diseqc.cmd = diseqc.data[2];
2551 cmd.u.diseqc.numParams = diseqc.len-3;
2552 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2553 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2555 struct dvb_diseqc_master_cmd cmd;
2556 memcpy(cmd.msg, diseqc.data, diseqc.len);
2557 cmd.msg_len = diseqc.len;
2558 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2564 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2565 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2567 RESULT eDVBFrontend::sendToneburst(int burst)
2571 #if HAVE_DVB_API_VERSION < 3
2572 secMiniCmd cmd = SEC_MINI_NONE;
2574 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2576 if ( burst == eDVBSatelliteDiseqcParameters::A )
2578 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2580 #if HAVE_DVB_API_VERSION < 3
2581 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2584 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2590 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2596 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2598 m_sec_sequence = list;
2602 RESULT eDVBFrontend::getData(int num, long &data)
2604 if ( num < NUM_DATA_ENTRIES )
2612 RESULT eDVBFrontend::setData(int num, long val)
2614 if ( num < NUM_DATA_ENTRIES )
2622 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2625 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2627 if (m_type == eDVBFrontend::feSatellite)
2630 eDVBFrontendParametersSatellite sat_parm;
2631 int ret = feparm->getDVBS(sat_parm);
2633 if (sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S2 && !m_can_handle_dvbs2)
2635 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2636 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S && m_can_handle_dvbs2)
2640 else if (m_type == eDVBFrontend::feCable)
2641 return 2; // more prio for cable frontends
2642 else if (m_type == eDVBFrontend::feTerrestrial)
2647 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2649 ePyObject Id, Descr, Enabled, IsDVBS2;
2650 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4)
2652 Id = PyTuple_GET_ITEM(obj, 0);
2653 Descr = PyTuple_GET_ITEM(obj, 1);
2654 Enabled = PyTuple_GET_ITEM(obj, 2);
2655 IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2656 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2))
2658 strcpy(m_description, PyString_AS_STRING(Descr));
2659 m_slotid = PyInt_AsLong(Id);
2660 m_enabled = Enabled == Py_True;
2661 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2662 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2663 !!strstr(m_description, "Alps BSBE2") ||
2664 !!strstr(m_description, "Alps -S") ||
2665 !!strstr(m_description, "BCM4501");
2666 m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2667 eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2668 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2671 PyErr_SetString(PyExc_StandardError,
2672 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");
2676 RESULT eDVBFrontend::turnOffSatCR(int satcr)
2678 eSecCommandList sec_sequence;
2679 // check if voltage is disabled
2680 eSecCommand::pair compare;
2681 compare.steps = +9; //nothing to do
2682 compare.voltage = iDVBFrontend::voltageOff;
2683 sec_sequence.push_back( eSecCommand(eSecCommand::IF_NOT_VOLTAGE_GOTO, compare) );
2684 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2685 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50 ) );
2687 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage18_5) );
2688 sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
2689 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 250) );
2691 eDVBDiseqcCommand diseqc;
2692 memset(diseqc.data, 0, MAX_DISEQC_LENGTH);
2694 diseqc.data[0] = 0xE0;
2695 diseqc.data[1] = 0x10;
2696 diseqc.data[2] = 0x5A;
2697 diseqc.data[3] = satcr << 5;
2698 diseqc.data[4] = 0x00;
2700 sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
2701 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50+20+14*diseqc.len) );
2702 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2703 setSecSequence(sec_sequence);
2707 RESULT eDVBFrontend::ScanSatCR()
2711 setTone(iDVBFrontend::toneOff);