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");
1056 PutToDict(dict, "fec_inner", tmp);
1058 switch (p[0].u.data)
1060 default: eDebug("got unsupported system from frontend! report as DVBS!");
1061 case SYS_DVBS: tmp = eDVBFrontendParametersSatellite::System_DVB_S; break;
1064 switch (p[2].u.data)
1066 default: eDebug("got unsupported rolloff from frontend! report as 0_20!");
1067 case ROLLOFF_20: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1068 case ROLLOFF_25: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1069 case ROLLOFF_35: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1071 PutToDict(dict, "rolloff", tmp);
1073 switch (p[3].u.data)
1075 case PILOT_OFF: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1076 case PILOT_ON: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1077 case PILOT_AUTO: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1079 PutToDict(dict, "pilot", tmp);
1081 tmp = eDVBFrontendParametersSatellite::System_DVB_S2; break;
1084 PutToDict(dict, "system", tmp);
1086 switch (p[1].u.data)
1088 default: eDebug("got unsupported modulation from frontend! report as QPSK!");
1089 case QPSK: tmp = eDVBFrontendParametersSatellite::Modulation_QPSK; break;
1090 case PSK_8: tmp = eDVBFrontendParametersSatellite::Modulation_8PSK; break;
1092 PutToDict(dict, "modulation", tmp);
1096 static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, long freq_offset, int orb_pos, int polarization)
1099 int frequency = parm_frequency + freq_offset;
1100 PutToDict(dict, "frequency", frequency);
1101 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
1102 PutToDict(dict, "orbital_position", orb_pos);
1103 PutToDict(dict, "polarization", polarization);
1105 switch((int)parm_u_qpsk_fec_inner)
1107 case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1108 case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1109 case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1110 case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1111 case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1112 case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
1114 case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
1115 #if HAVE_DVB_API_VERSION >=3
1116 case FEC_S2_8PSK_1_2:
1117 case FEC_S2_QPSK_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1118 case FEC_S2_8PSK_2_3:
1119 case FEC_S2_QPSK_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1120 case FEC_S2_8PSK_3_4:
1121 case FEC_S2_QPSK_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1122 case FEC_S2_8PSK_5_6:
1123 case FEC_S2_QPSK_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1124 case FEC_S2_8PSK_7_8:
1125 case FEC_S2_QPSK_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1126 case FEC_S2_8PSK_8_9:
1127 case FEC_S2_QPSK_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
1128 case FEC_S2_8PSK_3_5:
1129 case FEC_S2_QPSK_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
1130 case FEC_S2_8PSK_4_5:
1131 case FEC_S2_QPSK_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
1132 case FEC_S2_8PSK_9_10:
1133 case FEC_S2_QPSK_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1136 PutToDict(dict, "fec_inner", tmp);
1137 #if HAVE_DVB_API_VERSION >=3
1138 PutToDict(dict, "modulation",
1139 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ?
1140 eDVBFrontendParametersSatellite::Modulation_8PSK :
1141 eDVBFrontendParametersSatellite::Modulation_QPSK );
1142 if (parm_u_qpsk_fec_inner > FEC_AUTO)
1144 switch(parm_inversion & 0xc)
1146 default: // unknown rolloff
1147 case 0: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1148 case 4: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1149 case 8: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1151 PutToDict(dict, "rolloff", tmp);
1152 switch(parm_inversion & 0x30)
1154 case 0: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1155 case 0x10: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1156 case 0x20: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1158 PutToDict(dict, "pilot", tmp);
1159 tmp = eDVBFrontendParametersSatellite::System_DVB_S2;
1162 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1164 PutToDict(dict, "modulation", eDVBFrontendParametersSatellite::Modulation_QPSK );
1165 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1167 PutToDict(dict, "system", tmp);
1171 static void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1174 #if HAVE_DVB_API_VERSION < 3
1175 PutToDict(dict, "frequency", parm_frequency);
1177 PutToDict(dict, "frequency", parm_frequency/1000);
1179 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1180 switch(parm_u_qam_fec_inner)
1182 case FEC_NONE: tmp = eDVBFrontendParametersCable::FEC_None; break;
1183 case FEC_1_2: tmp = eDVBFrontendParametersCable::FEC_1_2; break;
1184 case FEC_2_3: tmp = eDVBFrontendParametersCable::FEC_2_3; break;
1185 case FEC_3_4: tmp = eDVBFrontendParametersCable::FEC_3_4; break;
1186 case FEC_5_6: tmp = eDVBFrontendParametersCable::FEC_5_6; break;
1187 case FEC_7_8: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1188 #if HAVE_DVB_API_VERSION >= 3
1189 case FEC_8_9: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1192 case FEC_AUTO: tmp = eDVBFrontendParametersCable::FEC_Auto; break;
1194 PutToDict(dict, "fec_inner", tmp);
1195 switch(parm_u_qam_modulation)
1197 case QAM_16: tmp = eDVBFrontendParametersCable::Modulation_QAM16; break;
1198 case QAM_32: tmp = eDVBFrontendParametersCable::Modulation_QAM32; break;
1199 case QAM_64: tmp = eDVBFrontendParametersCable::Modulation_QAM64; break;
1200 case QAM_128: tmp = eDVBFrontendParametersCable::Modulation_QAM128; break;
1201 case QAM_256: tmp = eDVBFrontendParametersCable::Modulation_QAM256; break;
1203 case QAM_AUTO: tmp = eDVBFrontendParametersCable::Modulation_Auto; break;
1205 PutToDict(dict, "modulation", tmp);
1208 static void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1211 PutToDict(dict, "frequency", parm_frequency);
1212 switch (parm_u_ofdm_bandwidth)
1214 case BANDWIDTH_8_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_8MHz; break;
1215 case BANDWIDTH_7_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_7MHz; break;
1216 case BANDWIDTH_6_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_6MHz; break;
1218 case BANDWIDTH_AUTO: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_Auto; break;
1220 PutToDict(dict, "bandwidth", tmp);
1221 switch (parm_u_ofdm_code_rate_LP)
1223 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1224 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1225 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1226 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1227 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1229 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1231 PutToDict(dict, "code_rate_lp", tmp);
1232 switch (parm_u_ofdm_code_rate_HP)
1234 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1235 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1236 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1237 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1238 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1240 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1242 PutToDict(dict, "code_rate_hp", tmp);
1243 switch (parm_u_ofdm_constellation)
1245 case QPSK: tmp = eDVBFrontendParametersTerrestrial::Modulation_QPSK; break;
1246 case QAM_16: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM16; break;
1247 case QAM_64: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM64; break;
1249 case QAM_AUTO: tmp = eDVBFrontendParametersTerrestrial::Modulation_Auto; break;
1251 PutToDict(dict, "constellation", tmp);
1252 switch (parm_u_ofdm_transmission_mode)
1254 case TRANSMISSION_MODE_2K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_2k; break;
1255 case TRANSMISSION_MODE_8K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_8k; break;
1257 case TRANSMISSION_MODE_AUTO: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto; break;
1259 PutToDict(dict, "transmission_mode", tmp);
1260 switch (parm_u_ofdm_guard_interval)
1262 case GUARD_INTERVAL_1_32: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_32; break;
1263 case GUARD_INTERVAL_1_16: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_16; break;
1264 case GUARD_INTERVAL_1_8: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_8; break;
1265 case GUARD_INTERVAL_1_4: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_4; break;
1267 case GUARD_INTERVAL_AUTO: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_Auto; break;
1269 PutToDict(dict, "guard_interval", tmp);
1270 switch (parm_u_ofdm_hierarchy_information)
1272 case HIERARCHY_NONE: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_None; break;
1273 case HIERARCHY_1: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_1; break;
1274 case HIERARCHY_2: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_2; break;
1275 case HIERARCHY_4: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_4; break;
1277 case HIERARCHY_AUTO: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_Auto; break;
1279 PutToDict(dict, "hierarchy_information", tmp);
1282 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1284 if (dest && PyDict_Check(dest))
1286 const char *tmp = "UNKNOWN";
1307 PutToDict(dest, "tuner_state", tmp);
1308 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1309 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1310 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1311 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1312 int sigQualitydB = readFrontendData(signalQualitydB);
1313 if (sigQualitydB == 0x12345678) // not support yet
1315 ePyObject obj=Py_None;
1317 PutToDict(dest, "tuner_signal_quality_db", obj);
1320 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1321 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1325 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1327 if (dest && PyDict_Check(dest))
1329 FRONTENDPARAMETERS front;
1330 #if HAVE_DVB_API_VERSION >= 5
1331 struct dtv_property p[4];
1332 struct dtv_properties cmdseq;
1335 p[0].cmd = DTV_DELIVERY_SYSTEM;
1336 p[1].cmd = DTV_MODULATION;
1337 p[2].cmd = DTV_ROLLOFF;
1338 p[3].cmd = DTV_PILOT;
1340 if (m_simulate || m_fd == -1 || original)
1342 #if HAVE_DVB_API_VERSION >= 5
1343 else if (m_type == feSatellite && // yet just use new api for DVB-S(2) only
1344 ioctl(m_fd, FE_GET_PROPERTY, &cmdseq)<0)
1346 eDebug("FE_GET_PROPERTY failed (%m)");
1350 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1352 eDebug("FE_GET_FRONTEND failed (%m)");
1360 PutSatelliteDataToDict(dest, oparm.sat);
1363 PutCableDataToDict(dest, oparm.cab);
1366 PutTerrestrialDataToDict(dest, oparm.ter);
1372 FRONTENDPARAMETERS &parm = front;
1373 long tmp = eDVBFrontendParametersSatellite::Inversion_Unknown;
1374 switch(parm_inversion & 3)
1377 tmp = eDVBFrontendParametersSatellite::Inversion_On;
1380 tmp = eDVBFrontendParametersSatellite::Inversion_Off;
1384 PutToDict(dest, "inversion", tmp);
1388 #if HAVE_DVB_API_VERSION >= 5
1389 fillDictWithSatelliteData(dest, parm, p, m_data[FREQ_OFFSET], oparm.sat.orbital_position, oparm.sat.polarisation);
1391 fillDictWithSatelliteData(dest, parm, m_data[FREQ_OFFSET], oparm.sat.orbital_position, oparm.sat.polarisation);
1395 fillDictWithCableData(dest, parm);
1398 fillDictWithTerrestrialData(dest, parm);
1405 void eDVBFrontend::getFrontendData(ePyObject dest)
1407 if (dest && PyDict_Check(dest))
1410 PutToDict(dest, "tuner_number", m_slotid);
1426 PutToDict(dest, "tuner_type", tmp);
1430 #ifndef FP_IOCTL_GET_ID
1431 #define FP_IOCTL_GET_ID 0
1433 int eDVBFrontend::readInputpower()
1437 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1439 char proc_name2[64];
1440 sprintf(proc_name, "/proc/stb/frontend/%d/lnb_sense", m_slotid);
1441 sprintf(proc_name2, "/proc/stb/fp/lnb_sense%d", m_slotid);
1443 if ((f=fopen(proc_name, "r")) || (f=fopen(proc_name2, "r")))
1445 if (fscanf(f, "%d", &power) != 1)
1446 eDebug("read %s failed!! (%m)", proc_name);
1448 eDebug("%s is %d\n", proc_name, power);
1453 // open front prozessor
1454 int fp=::open("/dev/dbox/fp0", O_RDWR);
1457 eDebug("couldn't open fp");
1460 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1461 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1463 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1472 bool eDVBFrontend::setSecSequencePos(int steps)
1474 eDebugNoSimulate("set sequence pos %d", steps);
1479 if (m_sec_sequence.current() != m_sec_sequence.end())
1480 ++m_sec_sequence.current();
1485 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1486 --m_sec_sequence.current();
1492 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1495 eDVBFrontend *sec_fe = this;
1496 eDVBRegisteredFrontend *regFE = 0;
1497 long tmp = m_data[LINKED_PREV_PTR];
1500 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1501 sec_fe = prev->m_frontend;
1502 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1503 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1504 int state = sec_fe->m_state;
1505 // workaround to put the kernel frontend thread into idle state!
1506 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1508 sec_fe->closeFrontend(true);
1509 state = sec_fe->m_state;
1511 // sec_fe is closed... we must reopen it here..
1512 if (state == stateClosed)
1520 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1522 long *sec_fe_data = sec_fe->m_data;
1523 // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1524 switch (m_sec_sequence.current()->cmd)
1526 case eSecCommand::SLEEP:
1527 delay = m_sec_sequence.current()++->msec;
1528 eDebugNoSimulate("[SEC] sleep %dms", delay);
1530 case eSecCommand::GOTO:
1531 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1532 ++m_sec_sequence.current();
1534 case eSecCommand::SET_VOLTAGE:
1536 int voltage = m_sec_sequence.current()++->voltage;
1537 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1538 sec_fe->setVoltage(voltage);
1541 case eSecCommand::IF_VOLTAGE_GOTO:
1543 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1544 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1546 ++m_sec_sequence.current();
1549 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1551 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1552 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1554 ++m_sec_sequence.current();
1557 case eSecCommand::IF_TONE_GOTO:
1559 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1560 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1562 ++m_sec_sequence.current();
1565 case eSecCommand::IF_NOT_TONE_GOTO:
1567 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1568 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1570 ++m_sec_sequence.current();
1573 case eSecCommand::SET_TONE:
1574 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1575 sec_fe->setTone(m_sec_sequence.current()++->tone);
1577 case eSecCommand::SEND_DISEQC:
1578 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1579 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1580 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1581 eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1582 if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
1583 eDebugNoSimulate("(DiSEqC reset)");
1584 else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
1585 eDebugNoSimulate("(DiSEqC peripherial power on)");
1587 eDebugNoSimulate("");
1588 ++m_sec_sequence.current();
1590 case eSecCommand::SEND_TONEBURST:
1591 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1592 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1594 case eSecCommand::SET_FRONTEND:
1596 int enableEvents = (m_sec_sequence.current()++)->val;
1597 eDebugNoSimulate("[SEC] setFrontend %d", enableEvents);
1598 setFrontend(enableEvents);
1601 case eSecCommand::START_TUNE_TIMEOUT:
1603 int tuneTimeout = m_sec_sequence.current()->timeout;
1604 eDebugNoSimulate("[SEC] startTuneTimeout %d", tuneTimeout);
1606 m_timeout->start(tuneTimeout, 1);
1607 ++m_sec_sequence.current();
1610 case eSecCommand::SET_TIMEOUT:
1611 m_timeoutCount = m_sec_sequence.current()++->val;
1612 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1614 case eSecCommand::IF_TIMEOUT_GOTO:
1615 if (!m_timeoutCount)
1617 eDebugNoSimulate("[SEC] rotor timout");
1618 setSecSequencePos(m_sec_sequence.current()->steps);
1621 ++m_sec_sequence.current();
1623 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1625 int idx = m_sec_sequence.current()++->val;
1626 if ( idx == 0 || idx == 1 )
1628 m_idleInputpower[idx] = sec_fe->readInputpower();
1629 eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1632 eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1635 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1637 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1638 int idx = compare.val;
1639 if ( !m_simulate && (idx == 0 || idx == 1) )
1641 int idle = sec_fe->readInputpower();
1642 int diff = abs(idle-m_idleInputpower[idx]);
1645 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1646 setSecSequencePos(compare.steps);
1650 ++m_sec_sequence.current();
1653 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1655 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1658 setSecSequencePos(cmd.steps);
1662 int isLocked = readFrontendData(locked);
1663 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1665 if (!m_timeoutCount && m_retryCount > 0)
1667 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 40) || !cmd.lastSignal))
1670 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1673 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1675 cmd.lastSignal = signal;
1678 if (cmd.okcount > 4)
1680 eDebugNoSimulate("ok > 4 .. goto %d\n", cmd.steps);
1681 setSecSequencePos(cmd.steps);
1682 m_state = stateLock;
1683 m_stateChanged(this);
1684 feEvent(-1); // flush events
1692 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1694 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1698 ++m_sec_sequence.current();
1701 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1702 m_runningInputpower = sec_fe->readInputpower();
1703 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1704 ++m_sec_sequence.current();
1706 case eSecCommand::SET_ROTOR_MOVING:
1708 m_sec->setRotorMoving(m_slotid, true);
1709 ++m_sec_sequence.current();
1711 case eSecCommand::SET_ROTOR_STOPPED:
1713 m_sec->setRotorMoving(m_slotid, false);
1714 ++m_sec_sequence.current();
1716 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1718 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1721 setSecSequencePos(cmd.steps);
1724 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1725 const char *txt = cmd.direction ? "running" : "stopped";
1727 if (!m_timeoutCount && m_retryCount > 0)
1729 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1731 m_runningInputpower,
1734 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1735 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1738 eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1739 if ( cmd.okcount > 6 )
1741 eDebugNoSimulate("[SEC] rotor is %s", txt);
1742 if (setSecSequencePos(cmd.steps))
1748 eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1751 ++m_sec_sequence.current();
1754 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1755 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1756 setSecSequencePos(m_sec_sequence.current()->steps);
1758 ++m_sec_sequence.current();
1760 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1761 eDebugNoSimulate("[SEC] invalidate current switch params");
1762 sec_fe_data[CSW] = -1;
1763 sec_fe_data[UCSW] = -1;
1764 sec_fe_data[TONEBURST] = -1;
1765 ++m_sec_sequence.current();
1767 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1768 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1769 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1770 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1771 eDebugNoSimulate("[SEC] update current switch params");
1772 ++m_sec_sequence.current();
1774 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1775 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1776 sec_fe_data[ROTOR_CMD] = -1;
1777 sec_fe_data[ROTOR_POS] = -1;
1778 ++m_sec_sequence.current();
1780 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1781 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1782 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1783 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1784 ++m_sec_sequence.current();
1786 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1787 m_retryCount = m_sec_sequence.current()++->val;
1788 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1790 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1793 eDebugNoSimulate("[SEC] no more rotor retrys");
1794 setSecSequencePos(m_sec_sequence.current()->steps);
1797 ++m_sec_sequence.current();
1799 case eSecCommand::SET_POWER_LIMITING_MODE:
1804 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1805 FILE *f=fopen(proc_name, "w");
1806 if (f) // new interface exist?
1808 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1809 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1810 eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1812 eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1815 else if (sec_fe->m_need_rotor_workaround)
1818 int slotid = sec_fe->m_slotid;
1819 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1821 sprintf(dev, "/dev/i2c/%d", slotid);
1822 else if (slotid == 2)
1823 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1824 else if (slotid == 3)
1825 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1826 int fd = ::open(dev, O_RDWR);
1828 unsigned char data[2];
1829 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1830 if(::read(fd, data, 1) != 1)
1831 eDebugNoSimulate("[SEC] error read lnbp (%m)");
1832 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1834 data[0] |= 0x80; // enable static current limiting
1835 eDebugNoSimulate("[SEC] set static current limiting");
1839 data[0] &= ~0x80; // enable dynamic current limiting
1840 eDebugNoSimulate("[SEC] set dynamic current limiting");
1842 if(::write(fd, data, 1) != 1)
1843 eDebugNoSimulate("[SEC] error write lnbp (%m)");
1847 ++m_sec_sequence.current();
1851 eDebugNoSimulate("[SEC] unhandled sec command %d",
1852 ++m_sec_sequence.current()->cmd);
1853 ++m_sec_sequence.current();
1856 m_tuneTimer->start(delay,true);
1860 if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1864 void eDVBFrontend::setFrontend(bool recvEvents)
1868 eDebug("setting frontend %d", m_dvbid);
1871 feEvent(-1); // flush events
1872 #if HAVE_DVB_API_VERSION >= 5
1873 if (m_type == iDVBFrontend::feSatellite)
1875 fe_rolloff_t rolloff = ROLLOFF_35;
1876 fe_pilot_t pilot = PILOT_OFF;
1877 fe_modulation_t modulation = QPSK;
1878 fe_delivery_system_t system = SYS_DVBS;
1879 switch(oparm.sat.system)
1881 case eDVBFrontendParametersSatellite::System_DVB_S: system = SYS_DVBS; break;
1882 case eDVBFrontendParametersSatellite::System_DVB_S2: system = SYS_DVBS2; break;
1884 switch(oparm.sat.modulation)
1886 case eDVBFrontendParametersSatellite::Modulation_QPSK: modulation = QPSK; break;
1887 case eDVBFrontendParametersSatellite::Modulation_8PSK: modulation = PSK_8; break;
1888 case eDVBFrontendParametersSatellite::Modulation_QAM16: modulation = QAM_16; break;
1890 switch(oparm.sat.pilot)
1892 case eDVBFrontendParametersSatellite::Pilot_Off: pilot = PILOT_OFF; break;
1893 case eDVBFrontendParametersSatellite::Pilot_On: pilot = PILOT_ON; break;
1894 case eDVBFrontendParametersSatellite::Pilot_Unknown: pilot = PILOT_AUTO; break;
1896 switch(oparm.sat.rolloff)
1898 case eDVBFrontendParametersSatellite::RollOff_alpha_0_20: rolloff = ROLLOFF_20; break;
1899 case eDVBFrontendParametersSatellite::RollOff_alpha_0_25: rolloff = ROLLOFF_25; break;
1900 case eDVBFrontendParametersSatellite::RollOff_alpha_0_35: rolloff = ROLLOFF_35; break;
1902 struct dtv_property p[10];
1903 struct dtv_properties cmdseq;
1905 p[0].cmd = DTV_CLEAR;
1906 p[1].cmd = DTV_DELIVERY_SYSTEM, p[1].u.data = system;
1907 p[2].cmd = DTV_FREQUENCY, p[2].u.data = parm_frequency;
1908 p[3].cmd = DTV_MODULATION, p[3].u.data = modulation;
1909 p[4].cmd = DTV_SYMBOL_RATE, p[4].u.data = parm_u_qpsk_symbol_rate;
1910 p[5].cmd = DTV_INNER_FEC, p[5].u.data = parm_u_qpsk_fec_inner;
1911 p[6].cmd = DTV_INVERSION, p[6].u.data = parm_inversion;
1912 if (system == SYS_DVBS2)
1914 p[7].cmd = DTV_ROLLOFF, p[7].u.data = rolloff;
1915 p[8].cmd = DTV_PILOT, p[8].u.data = pilot;
1916 p[9].cmd = DTV_TUNE;
1921 p[7].cmd = DTV_TUNE;
1924 if (ioctl(m_fd, FE_SET_PROPERTY, &cmdseq) == -1)
1926 perror("FE_SET_PROPERTY failed");
1933 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1935 perror("FE_SET_FRONTEND failed");
1942 RESULT eDVBFrontend::getFrontendType(int &t)
1950 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1955 eWarning("no SEC module active!");
1958 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1961 #if HAVE_DVB_API_VERSION >= 3
1962 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",
1965 feparm.polarisation,
1969 feparm.orbital_position,
1975 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1978 feparm.polarisation,
1982 feparm.orbital_position);
1984 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1985 switch (feparm.inversion)
1987 case eDVBFrontendParametersSatellite::Inversion_On:
1988 parm_inversion = INVERSION_ON;
1990 case eDVBFrontendParametersSatellite::Inversion_Off:
1991 parm_inversion = INVERSION_OFF;
1994 case eDVBFrontendParametersSatellite::Inversion_Unknown:
1995 parm_inversion = INVERSION_AUTO;
1998 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S)
2002 case eDVBFrontendParametersSatellite::FEC_None:
2003 parm_u_qpsk_fec_inner = FEC_NONE;
2005 case eDVBFrontendParametersSatellite::FEC_1_2:
2006 parm_u_qpsk_fec_inner = FEC_1_2;
2008 case eDVBFrontendParametersSatellite::FEC_2_3:
2009 parm_u_qpsk_fec_inner = FEC_2_3;
2011 case eDVBFrontendParametersSatellite::FEC_3_4:
2012 parm_u_qpsk_fec_inner = FEC_3_4;
2014 case eDVBFrontendParametersSatellite::FEC_5_6:
2015 parm_u_qpsk_fec_inner = FEC_5_6;
2017 case eDVBFrontendParametersSatellite::FEC_7_8:
2018 parm_u_qpsk_fec_inner = FEC_7_8;
2021 eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
2022 case eDVBFrontendParametersSatellite::FEC_Auto:
2023 parm_u_qpsk_fec_inner = FEC_AUTO;
2027 #if HAVE_DVB_API_VERSION >= 3
2032 case eDVBFrontendParametersSatellite::FEC_1_2:
2033 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
2035 case eDVBFrontendParametersSatellite::FEC_2_3:
2036 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
2038 case eDVBFrontendParametersSatellite::FEC_3_4:
2039 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
2041 case eDVBFrontendParametersSatellite::FEC_3_5:
2042 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
2044 case eDVBFrontendParametersSatellite::FEC_4_5:
2045 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
2047 case eDVBFrontendParametersSatellite::FEC_5_6:
2048 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
2050 case eDVBFrontendParametersSatellite::FEC_7_8:
2051 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
2053 case eDVBFrontendParametersSatellite::FEC_8_9:
2054 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
2056 case eDVBFrontendParametersSatellite::FEC_9_10:
2057 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
2060 eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
2063 #if HAVE_DVB_API_VERSION < 5
2064 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
2065 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
2066 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation_8PSK)
2068 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
2069 // 8PSK fec driver values are decimal 9 bigger
2074 // FIXME !!! get frequency range from tuner
2075 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
2077 eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
2080 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
2086 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
2088 #if HAVE_DVB_API_VERSION < 3
2089 parm_frequency = feparm.frequency;
2091 parm_frequency = feparm.frequency * 1000;
2093 parm_u_qam_symbol_rate = feparm.symbol_rate;
2094 switch (feparm.modulation)
2096 case eDVBFrontendParametersCable::Modulation_QAM16:
2097 parm_u_qam_modulation = QAM_16;
2099 case eDVBFrontendParametersCable::Modulation_QAM32:
2100 parm_u_qam_modulation = QAM_32;
2102 case eDVBFrontendParametersCable::Modulation_QAM64:
2103 parm_u_qam_modulation = QAM_64;
2105 case eDVBFrontendParametersCable::Modulation_QAM128:
2106 parm_u_qam_modulation = QAM_128;
2108 case eDVBFrontendParametersCable::Modulation_QAM256:
2109 parm_u_qam_modulation = QAM_256;
2112 case eDVBFrontendParametersCable::Modulation_Auto:
2113 parm_u_qam_modulation = QAM_AUTO;
2116 switch (feparm.inversion)
2118 case eDVBFrontendParametersCable::Inversion_On:
2119 parm_inversion = INVERSION_ON;
2121 case eDVBFrontendParametersCable::Inversion_Off:
2122 parm_inversion = INVERSION_OFF;
2125 case eDVBFrontendParametersCable::Inversion_Unknown:
2126 parm_inversion = INVERSION_AUTO;
2129 switch (feparm.fec_inner)
2131 case eDVBFrontendParametersCable::FEC_None:
2132 parm_u_qam_fec_inner = FEC_NONE;
2134 case eDVBFrontendParametersCable::FEC_1_2:
2135 parm_u_qam_fec_inner = FEC_1_2;
2137 case eDVBFrontendParametersCable::FEC_2_3:
2138 parm_u_qam_fec_inner = FEC_2_3;
2140 case eDVBFrontendParametersCable::FEC_3_4:
2141 parm_u_qam_fec_inner = FEC_3_4;
2143 case eDVBFrontendParametersCable::FEC_5_6:
2144 parm_u_qam_fec_inner = FEC_5_6;
2146 case eDVBFrontendParametersCable::FEC_7_8:
2147 parm_u_qam_fec_inner = FEC_7_8;
2149 #if HAVE_DVB_API_VERSION >= 3
2150 case eDVBFrontendParametersCable::FEC_8_9:
2151 parm_u_qam_fec_inner = FEC_8_9;
2155 case eDVBFrontendParametersCable::FEC_Auto:
2156 parm_u_qam_fec_inner = FEC_AUTO;
2159 eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
2160 parm_frequency/1000,
2161 parm_u_qam_symbol_rate,
2162 parm_u_qam_fec_inner,
2163 parm_u_qam_modulation,
2169 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
2171 parm_frequency = feparm.frequency;
2173 switch (feparm.bandwidth)
2175 case eDVBFrontendParametersTerrestrial::Bandwidth_8MHz:
2176 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
2178 case eDVBFrontendParametersTerrestrial::Bandwidth_7MHz:
2179 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
2181 case eDVBFrontendParametersTerrestrial::Bandwidth_6MHz:
2182 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
2185 case eDVBFrontendParametersTerrestrial::Bandwidth_Auto:
2186 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
2189 switch (feparm.code_rate_LP)
2191 case eDVBFrontendParametersTerrestrial::FEC_1_2:
2192 parm_u_ofdm_code_rate_LP = FEC_1_2;
2194 case eDVBFrontendParametersTerrestrial::FEC_2_3:
2195 parm_u_ofdm_code_rate_LP = FEC_2_3;
2197 case eDVBFrontendParametersTerrestrial::FEC_3_4:
2198 parm_u_ofdm_code_rate_LP = FEC_3_4;
2200 case eDVBFrontendParametersTerrestrial::FEC_5_6:
2201 parm_u_ofdm_code_rate_LP = FEC_5_6;
2203 case eDVBFrontendParametersTerrestrial::FEC_7_8:
2204 parm_u_ofdm_code_rate_LP = FEC_7_8;
2207 case eDVBFrontendParametersTerrestrial::FEC_Auto:
2208 parm_u_ofdm_code_rate_LP = FEC_AUTO;
2211 switch (feparm.code_rate_HP)
2213 case eDVBFrontendParametersTerrestrial::FEC_1_2:
2214 parm_u_ofdm_code_rate_HP = FEC_1_2;
2216 case eDVBFrontendParametersTerrestrial::FEC_2_3:
2217 parm_u_ofdm_code_rate_HP = FEC_2_3;
2219 case eDVBFrontendParametersTerrestrial::FEC_3_4:
2220 parm_u_ofdm_code_rate_HP = FEC_3_4;
2222 case eDVBFrontendParametersTerrestrial::FEC_5_6:
2223 parm_u_ofdm_code_rate_HP = FEC_5_6;
2225 case eDVBFrontendParametersTerrestrial::FEC_7_8:
2226 parm_u_ofdm_code_rate_HP = FEC_7_8;
2229 case eDVBFrontendParametersTerrestrial::FEC_Auto:
2230 parm_u_ofdm_code_rate_HP = FEC_AUTO;
2233 switch (feparm.modulation)
2235 case eDVBFrontendParametersTerrestrial::Modulation_QPSK:
2236 parm_u_ofdm_constellation = QPSK;
2238 case eDVBFrontendParametersTerrestrial::Modulation_QAM16:
2239 parm_u_ofdm_constellation = QAM_16;
2241 case eDVBFrontendParametersTerrestrial::Modulation_QAM64:
2242 parm_u_ofdm_constellation = QAM_64;
2245 case eDVBFrontendParametersTerrestrial::Modulation_Auto:
2246 parm_u_ofdm_constellation = QAM_AUTO;
2249 switch (feparm.transmission_mode)
2251 case eDVBFrontendParametersTerrestrial::TransmissionMode_2k:
2252 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2254 case eDVBFrontendParametersTerrestrial::TransmissionMode_8k:
2255 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2258 case eDVBFrontendParametersTerrestrial::TransmissionMode_Auto:
2259 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2262 switch (feparm.guard_interval)
2264 case eDVBFrontendParametersTerrestrial::GuardInterval_1_32:
2265 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2267 case eDVBFrontendParametersTerrestrial::GuardInterval_1_16:
2268 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2270 case eDVBFrontendParametersTerrestrial::GuardInterval_1_8:
2271 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2273 case eDVBFrontendParametersTerrestrial::GuardInterval_1_4:
2274 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2277 case eDVBFrontendParametersTerrestrial::GuardInterval_Auto:
2278 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2281 switch (feparm.hierarchy)
2283 case eDVBFrontendParametersTerrestrial::Hierarchy_None:
2284 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2286 case eDVBFrontendParametersTerrestrial::Hierarchy_1:
2287 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2289 case eDVBFrontendParametersTerrestrial::Hierarchy_2:
2290 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2292 case eDVBFrontendParametersTerrestrial::Hierarchy_4:
2293 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2296 case eDVBFrontendParametersTerrestrial::Hierarchy_Auto:
2297 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2300 switch (feparm.inversion)
2302 case eDVBFrontendParametersTerrestrial::Inversion_On:
2303 parm_inversion = INVERSION_ON;
2305 case eDVBFrontendParametersTerrestrial::Inversion_Off:
2306 parm_inversion = INVERSION_OFF;
2309 case eDVBFrontendParametersTerrestrial::Inversion_Unknown:
2310 parm_inversion = INVERSION_AUTO;
2317 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2319 unsigned int timeout = 5000;
2320 eDebugNoSimulate("(%d)tune", m_dvbid);
2326 if (!m_sn && !m_simulate)
2328 eDebug("no frontend device opened... do not try to tune !!!");
2342 m_sec_sequence.clear();
2344 where.calcLockTimeout(timeout);
2350 eDVBFrontendParametersSatellite feparm;
2351 if (where.getDVBS(feparm))
2353 eDebug("no dvbs data!");
2357 if (m_rotor_mode != feparm.no_rotor_command_on_tune && !feparm.no_rotor_command_on_tune)
2359 eDVBFrontend *sec_fe = this;
2360 long tmp = m_data[LINKED_PREV_PTR];
2363 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
2364 sec_fe = linked_fe->m_frontend;
2365 sec_fe->getData(LINKED_NEXT_PTR, tmp);
2367 eDebug("(fe%d) reset diseqc after leave rotor mode!", m_dvbid);
2368 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
2370 m_rotor_mode = feparm.no_rotor_command_on_tune;
2372 m_sec->setRotorMoving(m_slotid, false);
2373 res=prepare_sat(feparm, timeout);
2381 eDVBFrontendParametersCable feparm;
2382 if (where.getDVBC(feparm))
2387 res=prepare_cable(feparm);
2391 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2392 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2397 eDVBFrontendParametersTerrestrial feparm;
2398 if (where.getDVBT(feparm))
2400 eDebug("no -T data");
2404 res=prepare_terrestrial(feparm);
2408 std::string enable_5V;
2409 char configStr[255];
2410 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2411 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2412 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2413 if (enable_5V == "True")
2414 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2416 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2417 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2423 m_sec_sequence.current() = m_sec_sequence.begin();
2427 m_tuneTimer->start(0,true);
2429 if (m_state != stateTuning)
2431 m_state = stateTuning;
2432 m_stateChanged(this);
2441 m_tuneTimer->stop();
2445 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2447 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2451 RESULT eDVBFrontend::setVoltage(int voltage)
2453 if (m_type == feCable)
2455 #if HAVE_DVB_API_VERSION < 3
2458 bool increased=false;
2459 fe_sec_voltage_t vlt;
2461 m_data[CUR_VOLTAGE]=voltage;
2465 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2466 vlt = SEC_VOLTAGE_OFF;
2469 #if HAVE_DVB_API_VERSION < 3
2470 vlt = SEC_VOLTAGE_13_5;
2476 vlt = SEC_VOLTAGE_13;
2479 #if HAVE_DVB_API_VERSION < 3
2480 vlt = SEC_VOLTAGE_18_5;
2486 vlt = SEC_VOLTAGE_18;
2493 #if HAVE_DVB_API_VERSION < 3
2494 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2496 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2497 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2498 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2502 RESULT eDVBFrontend::getState(int &state)
2508 RESULT eDVBFrontend::setTone(int t)
2510 if (m_type != feSatellite)
2512 #if HAVE_DVB_API_VERSION < 3
2515 fe_sec_tone_mode_t tone;
2524 tone = SEC_TONE_OFF;
2531 #if HAVE_DVB_API_VERSION < 3
2532 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2534 return ::ioctl(m_fd, FE_SET_TONE, tone);
2538 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2539 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2542 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2546 #if HAVE_DVB_API_VERSION < 3
2547 struct secCommand cmd;
2548 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2549 cmd.u.diseqc.cmdtype = diseqc.data[0];
2550 cmd.u.diseqc.addr = diseqc.data[1];
2551 cmd.u.diseqc.cmd = diseqc.data[2];
2552 cmd.u.diseqc.numParams = diseqc.len-3;
2553 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2554 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2556 struct dvb_diseqc_master_cmd cmd;
2557 memcpy(cmd.msg, diseqc.data, diseqc.len);
2558 cmd.msg_len = diseqc.len;
2559 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2565 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2566 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2568 RESULT eDVBFrontend::sendToneburst(int burst)
2572 #if HAVE_DVB_API_VERSION < 3
2573 secMiniCmd cmd = SEC_MINI_NONE;
2575 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2577 if ( burst == eDVBSatelliteDiseqcParameters::A )
2579 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2581 #if HAVE_DVB_API_VERSION < 3
2582 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2585 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2591 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2597 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2599 m_sec_sequence = list;
2603 RESULT eDVBFrontend::getData(int num, long &data)
2605 if ( num < NUM_DATA_ENTRIES )
2613 RESULT eDVBFrontend::setData(int num, long val)
2615 if ( num < NUM_DATA_ENTRIES )
2623 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2626 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2628 if (m_type == eDVBFrontend::feSatellite)
2631 eDVBFrontendParametersSatellite sat_parm;
2632 int ret = feparm->getDVBS(sat_parm);
2634 if (sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S2 && !m_can_handle_dvbs2)
2636 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2637 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S && m_can_handle_dvbs2)
2641 else if (m_type == eDVBFrontend::feCable)
2642 return 2; // more prio for cable frontends
2643 else if (m_type == eDVBFrontend::feTerrestrial)
2648 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2650 ePyObject Id, Descr, Enabled, IsDVBS2;
2651 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4)
2653 Id = PyTuple_GET_ITEM(obj, 0);
2654 Descr = PyTuple_GET_ITEM(obj, 1);
2655 Enabled = PyTuple_GET_ITEM(obj, 2);
2656 IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2657 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2))
2659 strcpy(m_description, PyString_AS_STRING(Descr));
2660 m_slotid = PyInt_AsLong(Id);
2661 m_enabled = Enabled == Py_True;
2662 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2663 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2664 !!strstr(m_description, "Alps BSBE2") ||
2665 !!strstr(m_description, "Alps -S") ||
2666 !!strstr(m_description, "BCM4501");
2667 m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2668 eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2669 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2672 PyErr_SetString(PyExc_StandardError,
2673 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");
2677 RESULT eDVBFrontend::turnOffSatCR(int satcr)
2679 eSecCommandList sec_sequence;
2680 // check if voltage is disabled
2681 eSecCommand::pair compare;
2682 compare.steps = +9; //nothing to do
2683 compare.voltage = iDVBFrontend::voltageOff;
2684 sec_sequence.push_back( eSecCommand(eSecCommand::IF_NOT_VOLTAGE_GOTO, compare) );
2685 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2686 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50 ) );
2688 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage18_5) );
2689 sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
2690 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 250) );
2692 eDVBDiseqcCommand diseqc;
2693 memset(diseqc.data, 0, MAX_DISEQC_LENGTH);
2695 diseqc.data[0] = 0xE0;
2696 diseqc.data[1] = 0x10;
2697 diseqc.data[2] = 0x5A;
2698 diseqc.data[3] = satcr << 5;
2699 diseqc.data[4] = 0x00;
2701 sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
2702 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50+20+14*diseqc.len) );
2703 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2704 setSecSequence(sec_sequence);
2708 RESULT eDVBFrontend::ScanSatCR()
2712 setTone(iDVBFrontend::toneOff);