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, bool no_delayed)
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)
610 m_sec->prepareTurnOffSatCR(*this, m_data[SATCR]);
611 m_tuneTimer->start(0, true);
612 if(!m_tuneTimer->isActive())
615 eDebug("[turnOffSatCR] no mainloop");
618 timeout = tuneLoopInt();
621 usleep(timeout*1000); // blockierendes wait.. eTimer gibts ja nicht mehr
625 eDebug("[turnOffSatCR] running mainloop");
629 m_data[ROTOR_CMD] = -1;
632 setTone(iDVBFrontend::toneOff);
633 setVoltage(iDVBFrontend::voltageOff);
636 if (m_sec && !m_simulate)
637 m_sec->setRotorMoving(m_slotid, false);
641 eWarning("couldnt close frontend %d", m_dvbid);
645 setTone(iDVBFrontend::toneOff);
646 setVoltage(iDVBFrontend::voltageOff);
648 #if HAVE_DVB_API_VERSION < 3
651 if (!::close(m_secfd))
654 eWarning("couldnt close sec %d", m_dvbid);
658 m_state = stateClosed;
663 eDVBFrontend::~eDVBFrontend()
665 m_data[LINKED_PREV_PTR] = m_data[LINKED_NEXT_PTR] = -1;
669 void eDVBFrontend::feEvent(int w)
671 eDVBFrontend *sec_fe = this;
672 long tmp = m_data[LINKED_PREV_PTR];
675 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
676 sec_fe = linked_fe->m_frontend;
677 sec_fe->getData(LINKED_NEXT_PTR, tmp);
681 #if HAVE_DVB_API_VERSION < 3
684 dvb_frontend_event event;
688 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
690 if (res && (errno == EAGAIN))
696 #if HAVE_DVB_API_VERSION < 3
697 if (event.type == FE_COMPLETION_EV)
699 eDebug("(%d)fe event: status %x, inversion %s, m_tuning %d", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off", m_tuning);
700 if (event.status & FE_HAS_LOCK)
708 #if HAVE_DVB_API_VERSION >= 3
709 if (event.status & FE_TIMEDOUT) {
710 eDebug("FE_TIMEDOUT! ..abort");
723 eDebug("stateLostLock");
724 state = stateLostLock;
726 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
729 if (m_state != state)
732 m_stateChanged(this);
737 void eDVBFrontend::timeout()
740 if (m_state == stateTuning)
742 m_state = stateFailed;
743 m_stateChanged(this);
747 #define INRANGE(X,Y,Z) (((X<=Y) && (Y<=Z))||((Z<=Y) && (Y<=X)) ? 1 : 0)
749 /* unsigned 32 bit division */
750 static inline uint32_t fe_udiv(uint32_t a, uint32_t b)
752 return (a + b / 2) / b;
755 int eDVBFrontend::readFrontendData(int type)
764 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
765 eDebug("FE_READ_BER failed (%m)");
770 case signalQualitydB: /* this will move into the driver */
772 int sat_max = 1600; // for stv0288 / bsbe2
773 int ret = 0x12345678;
777 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
778 eDebug("FE_READ_SNR failed (%m)");
779 else if (!strcmp(m_description, "BCM4501 (internal)"))
781 float SDS_SNRE = snr << 16;
784 if (oparm.sat.system == eDVBFrontendParametersSatellite::System_DVB_S) // DVB-S1 / QPSK
786 static float SNR_COEFF[6] = {
789 197418.0 / 4194304.0,
790 -2602183.0 / 4194304.0,
791 20377212.0 / 4194304.0,
792 -37791203.0 / 4194304.0,
794 float fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0)),
795 fval2 = pow(10.0, fval1)-1;
796 fval1 = 10.0 * log10(fval2);
800 fval2 = SNR_COEFF[0];
801 for (int i=1; i<6; ++i)
804 fval2 += SNR_COEFF[i];
810 #if HAVE_DVB_API_VERSION >= 3
813 float fval1 = SDS_SNRE / 268435456.0,
816 if (parm_u_qpsk_fec_inner <= FEC_S2_QPSK_9_10) // DVB-S2 QPSK
827 fval4 = -10.0 * log10(fval1);
829 for (int i=0; i < 5; ++i)
830 fval1 = fval4 - fval2 * log10(1.0+pow(10.0, (fval3-fval1)/fval2));
835 ret = (int)(snr_in_db * 100);
837 else if (strstr(m_description, "Alps BSBE1 C01A") ||
838 strstr(m_description, "Alps -S(STV0288)"))
842 else if (snr == 0xFFFF) // i think this should not happen
846 enum { REALVAL, REGVAL };
847 const long CN_lookup[31][2] = {
848 {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
849 {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
850 {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
851 {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
852 {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
853 {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
856 int add=strchr(m_description, '.') ? 0xA250 : 0xA100;
857 long regval = 0xFFFF - ((snr / 3) + add), // revert some dvb api calulations to get the real register value
861 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
866 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[i][REGVAL]))
871 ret = (((regval - CN_lookup[Imin][REGVAL])
872 * (CN_lookup[Imax][REALVAL] - CN_lookup[Imin][REALVAL])
873 / (CN_lookup[Imax][REGVAL] - CN_lookup[Imin][REGVAL]))
874 + CN_lookup[Imin][REALVAL]) * 10;
880 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
881 !strcmp(m_description, "Alps -S") ||
882 !strcmp(m_description, "Philips -S") ||
883 !strcmp(m_description, "LG -S") )
886 ret = (int)((snr-39075)/17.647);
887 } else if (!strcmp(m_description, "Alps BSBE2"))
889 ret = (int)((snr >> 7) * 10);
890 } else if (!strcmp(m_description, "Philips CU1216Mk3"))
892 int mse = (~snr) & 0xFF;
893 switch (parm_u_qam_modulation) {
894 case QAM_16: ret = fe_udiv(1950000, (32 * mse) + 138) + 1000; break;
895 case QAM_32: ret = fe_udiv(2150000, (40 * mse) + 500) + 1350; break;
896 case QAM_64: ret = fe_udiv(2100000, (40 * mse) + 500) + 1250; break;
897 case QAM_128: ret = fe_udiv(1850000, (38 * mse) + 400) + 1380; break;
898 case QAM_256: ret = fe_udiv(1800000, (100 * mse) + 40) + 2030; break;
901 } else if (!strcmp(m_description, "Philips TU1216"))
903 snr = 0xFF - (snr & 0xFF);
905 ret = 10 * (int)(-100 * (log10(snr) - log10(255)));
907 else if (strstr(m_description, "BCM4506") || strstr(m_description, "BCM4505"))
908 ret = (snr * 100) >> 8;
910 if (type == signalQuality)
912 if (ret == 0x12345678) // no snr db calculation avail.. return untouched snr value..
917 return ret >= sat_max ? 65536 : ret * 65536 / sat_max;
918 case feCable: // we assume a max of 42db here
919 return ret >= 4200 ? 65536 : ret * 65536 / 4200;
920 case feTerrestrial: // we assume a max of 24db here
921 return ret >= 2400 ? 65536 : ret * 65536 / 2400;
925 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
933 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
934 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
940 #if HAVE_DVB_API_VERSION < 3
941 FrontendStatus status=0;
947 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
948 eDebug("FE_READ_STATUS failed (%m)");
949 return !!(status&FE_HAS_LOCK);
955 #if HAVE_DVB_API_VERSION < 3
956 FrontendStatus status=0;
962 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
963 eDebug("FE_READ_STATUS failed (%m)");
964 return !!(status&FE_HAS_SYNC);
974 void PutToDict(ePyObject &dict, const char*key, long value)
976 ePyObject item = PyInt_FromLong(value);
979 if (PyDict_SetItemString(dict, key, item))
980 eDebug("put %s to dict failed", key);
984 eDebug("could not create PyObject for %s", key);
987 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
991 if (PyDict_SetItemString(dict, key, item))
992 eDebug("put %s to dict failed", key);
996 eDebug("invalid PyObject for %s", key);
999 void PutToDict(ePyObject &dict, const char*key, const char *value)
1001 ePyObject item = PyString_FromString(value);
1004 if (PyDict_SetItemString(dict, key, item))
1005 eDebug("put %s to dict failed", key);
1009 eDebug("could not create PyObject for %s", key);
1012 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
1014 PutToDict(dict, "tuner_type", "DVB-S");
1015 PutToDict(dict, "frequency", feparm.frequency);
1016 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
1017 PutToDict(dict, "orbital_position", feparm.orbital_position);
1018 PutToDict(dict, "inversion", feparm.inversion);
1019 PutToDict(dict, "fec_inner", feparm.fec);
1020 PutToDict(dict, "modulation", feparm.modulation);
1021 PutToDict(dict, "polarization", feparm.polarisation);
1022 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S2)
1024 PutToDict(dict, "rolloff", feparm.rolloff);
1025 PutToDict(dict, "pilot", feparm.pilot);
1027 PutToDict(dict, "system", feparm.system);
1030 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
1032 PutToDict(dict, "tuner_type", "DVB-T");
1033 PutToDict(dict, "frequency", feparm.frequency);
1034 PutToDict(dict, "bandwidth", feparm.bandwidth);
1035 PutToDict(dict, "code_rate_lp", feparm.code_rate_LP);
1036 PutToDict(dict, "code_rate_hp", feparm.code_rate_HP);
1037 PutToDict(dict, "constellation", feparm.modulation);
1038 PutToDict(dict, "transmission_mode", feparm.transmission_mode);
1039 PutToDict(dict, "guard_interval", feparm.guard_interval);
1040 PutToDict(dict, "hierarchy_information", feparm.hierarchy);
1041 PutToDict(dict, "inversion", feparm.inversion);
1044 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
1046 PutToDict(dict, "tuner_type", "DVB-C");
1047 PutToDict(dict, "frequency", feparm.frequency);
1048 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
1049 PutToDict(dict, "modulation", feparm.modulation);
1050 PutToDict(dict, "inversion", feparm.inversion);
1051 PutToDict(dict, "fec_inner", feparm.fec_inner);
1054 #if HAVE_DVB_API_VERSION >= 5
1055 static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, struct dtv_property *p, long freq_offset, int orb_pos, int polarization)
1058 int frequency = parm_frequency + freq_offset;
1059 PutToDict(dict, "frequency", frequency);
1060 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
1061 PutToDict(dict, "orbital_position", orb_pos);
1062 PutToDict(dict, "polarization", polarization);
1064 switch(parm_u_qpsk_fec_inner)
1066 case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1067 case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1068 case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1069 case FEC_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
1070 case FEC_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
1071 case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1072 case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1073 case FEC_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
1074 case FEC_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1075 case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
1076 case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
1077 default: eDebug("got unsupported FEC from frontend! report as FEC_AUTO!\n");
1080 switch (p[0].u.data)
1082 default: eDebug("got unsupported system from frontend! report as DVBS!");
1083 case SYS_DVBS: tmp = eDVBFrontendParametersSatellite::System_DVB_S; break;
1086 switch (p[2].u.data)
1088 default: eDebug("got unsupported rolloff from frontend! report as 0_20!");
1089 case ROLLOFF_20: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1090 case ROLLOFF_25: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1091 case ROLLOFF_35: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1093 PutToDict(dict, "rolloff", tmp);
1095 switch (p[3].u.data)
1097 case PILOT_OFF: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1098 case PILOT_ON: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1099 case PILOT_AUTO: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1101 PutToDict(dict, "pilot", tmp);
1103 tmp = eDVBFrontendParametersSatellite::System_DVB_S2; break;
1106 PutToDict(dict, "system", tmp);
1108 switch (p[1].u.data)
1110 default: eDebug("got unsupported modulation from frontend! report as QPSK!");
1111 case QPSK: tmp = eDVBFrontendParametersSatellite::Modulation_QPSK; break;
1112 case PSK_8: tmp = eDVBFrontendParametersSatellite::Modulation_8PSK; break;
1114 PutToDict(dict, "modulation", tmp);
1118 static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, long freq_offset, int orb_pos, int polarization)
1121 int frequency = parm_frequency + freq_offset;
1122 PutToDict(dict, "frequency", frequency);
1123 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
1124 PutToDict(dict, "orbital_position", orb_pos);
1125 PutToDict(dict, "polarization", polarization);
1127 switch((int)parm_u_qpsk_fec_inner)
1129 case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1130 case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1131 case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1132 case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1133 case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1134 case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
1136 case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
1137 #if HAVE_DVB_API_VERSION >=3
1138 case FEC_S2_8PSK_1_2:
1139 case FEC_S2_QPSK_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1140 case FEC_S2_8PSK_2_3:
1141 case FEC_S2_QPSK_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1142 case FEC_S2_8PSK_3_4:
1143 case FEC_S2_QPSK_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1144 case FEC_S2_8PSK_5_6:
1145 case FEC_S2_QPSK_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1146 case FEC_S2_8PSK_7_8:
1147 case FEC_S2_QPSK_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1148 case FEC_S2_8PSK_8_9:
1149 case FEC_S2_QPSK_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
1150 case FEC_S2_8PSK_3_5:
1151 case FEC_S2_QPSK_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
1152 case FEC_S2_8PSK_4_5:
1153 case FEC_S2_QPSK_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
1154 case FEC_S2_8PSK_9_10:
1155 case FEC_S2_QPSK_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1158 PutToDict(dict, "fec_inner", tmp);
1159 #if HAVE_DVB_API_VERSION >=3
1160 PutToDict(dict, "modulation",
1161 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ?
1162 eDVBFrontendParametersSatellite::Modulation_8PSK :
1163 eDVBFrontendParametersSatellite::Modulation_QPSK );
1164 if (parm_u_qpsk_fec_inner > FEC_AUTO)
1166 switch(parm_inversion & 0xc)
1168 default: // unknown rolloff
1169 case 0: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1170 case 4: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1171 case 8: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1173 PutToDict(dict, "rolloff", tmp);
1174 switch(parm_inversion & 0x30)
1176 case 0: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1177 case 0x10: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1178 case 0x20: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1180 PutToDict(dict, "pilot", tmp);
1181 tmp = eDVBFrontendParametersSatellite::System_DVB_S2;
1184 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1186 PutToDict(dict, "modulation", eDVBFrontendParametersSatellite::Modulation_QPSK );
1187 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1189 PutToDict(dict, "system", tmp);
1193 static void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1196 #if HAVE_DVB_API_VERSION < 3
1197 PutToDict(dict, "frequency", parm_frequency);
1199 PutToDict(dict, "frequency", parm_frequency/1000);
1201 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1202 switch(parm_u_qam_fec_inner)
1204 case FEC_NONE: tmp = eDVBFrontendParametersCable::FEC_None; break;
1205 case FEC_1_2: tmp = eDVBFrontendParametersCable::FEC_1_2; break;
1206 case FEC_2_3: tmp = eDVBFrontendParametersCable::FEC_2_3; break;
1207 case FEC_3_4: tmp = eDVBFrontendParametersCable::FEC_3_4; break;
1208 case FEC_5_6: tmp = eDVBFrontendParametersCable::FEC_5_6; break;
1209 case FEC_7_8: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1210 #if HAVE_DVB_API_VERSION >= 3
1211 case FEC_8_9: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1214 case FEC_AUTO: tmp = eDVBFrontendParametersCable::FEC_Auto; break;
1216 PutToDict(dict, "fec_inner", tmp);
1217 switch(parm_u_qam_modulation)
1219 case QAM_16: tmp = eDVBFrontendParametersCable::Modulation_QAM16; break;
1220 case QAM_32: tmp = eDVBFrontendParametersCable::Modulation_QAM32; break;
1221 case QAM_64: tmp = eDVBFrontendParametersCable::Modulation_QAM64; break;
1222 case QAM_128: tmp = eDVBFrontendParametersCable::Modulation_QAM128; break;
1223 case QAM_256: tmp = eDVBFrontendParametersCable::Modulation_QAM256; break;
1225 case QAM_AUTO: tmp = eDVBFrontendParametersCable::Modulation_Auto; break;
1227 PutToDict(dict, "modulation", tmp);
1230 static void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1233 PutToDict(dict, "frequency", parm_frequency);
1234 switch (parm_u_ofdm_bandwidth)
1236 case BANDWIDTH_8_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_8MHz; break;
1237 case BANDWIDTH_7_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_7MHz; break;
1238 case BANDWIDTH_6_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_6MHz; break;
1240 case BANDWIDTH_AUTO: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_Auto; break;
1242 PutToDict(dict, "bandwidth", tmp);
1243 switch (parm_u_ofdm_code_rate_LP)
1245 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1246 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1247 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1248 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1249 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1251 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1253 PutToDict(dict, "code_rate_lp", tmp);
1254 switch (parm_u_ofdm_code_rate_HP)
1256 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1257 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1258 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1259 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1260 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1262 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1264 PutToDict(dict, "code_rate_hp", tmp);
1265 switch (parm_u_ofdm_constellation)
1267 case QPSK: tmp = eDVBFrontendParametersTerrestrial::Modulation_QPSK; break;
1268 case QAM_16: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM16; break;
1269 case QAM_64: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM64; break;
1271 case QAM_AUTO: tmp = eDVBFrontendParametersTerrestrial::Modulation_Auto; break;
1273 PutToDict(dict, "constellation", tmp);
1274 switch (parm_u_ofdm_transmission_mode)
1276 case TRANSMISSION_MODE_2K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_2k; break;
1277 case TRANSMISSION_MODE_8K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_8k; break;
1279 case TRANSMISSION_MODE_AUTO: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto; break;
1281 PutToDict(dict, "transmission_mode", tmp);
1282 switch (parm_u_ofdm_guard_interval)
1284 case GUARD_INTERVAL_1_32: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_32; break;
1285 case GUARD_INTERVAL_1_16: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_16; break;
1286 case GUARD_INTERVAL_1_8: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_8; break;
1287 case GUARD_INTERVAL_1_4: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_4; break;
1289 case GUARD_INTERVAL_AUTO: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_Auto; break;
1291 PutToDict(dict, "guard_interval", tmp);
1292 switch (parm_u_ofdm_hierarchy_information)
1294 case HIERARCHY_NONE: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_None; break;
1295 case HIERARCHY_1: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_1; break;
1296 case HIERARCHY_2: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_2; break;
1297 case HIERARCHY_4: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_4; break;
1299 case HIERARCHY_AUTO: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_Auto; break;
1301 PutToDict(dict, "hierarchy_information", tmp);
1304 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1306 if (dest && PyDict_Check(dest))
1308 const char *tmp = "UNKNOWN";
1329 PutToDict(dest, "tuner_state", tmp);
1330 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1331 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1332 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1333 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1334 int sigQualitydB = readFrontendData(signalQualitydB);
1335 if (sigQualitydB == 0x12345678) // not support yet
1337 ePyObject obj=Py_None;
1339 PutToDict(dest, "tuner_signal_quality_db", obj);
1342 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1343 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1347 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1349 if (dest && PyDict_Check(dest))
1351 FRONTENDPARAMETERS front;
1352 #if HAVE_DVB_API_VERSION >= 5
1353 struct dtv_property p[4];
1354 struct dtv_properties cmdseq;
1357 p[0].cmd = DTV_DELIVERY_SYSTEM;
1358 p[1].cmd = DTV_MODULATION;
1359 p[2].cmd = DTV_ROLLOFF;
1360 p[3].cmd = DTV_PILOT;
1362 if (m_simulate || m_fd == -1 || original)
1364 #if HAVE_DVB_API_VERSION >= 5
1365 else if (m_type == feSatellite && // yet just use new api for DVB-S(2) only
1366 ioctl(m_fd, FE_GET_PROPERTY, &cmdseq)<0)
1368 eDebug("FE_GET_PROPERTY failed (%m)");
1372 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1374 eDebug("FE_GET_FRONTEND failed (%m)");
1382 PutSatelliteDataToDict(dest, oparm.sat);
1385 PutCableDataToDict(dest, oparm.cab);
1388 PutTerrestrialDataToDict(dest, oparm.ter);
1394 FRONTENDPARAMETERS &parm = front;
1395 long tmp = eDVBFrontendParametersSatellite::Inversion_Unknown;
1396 switch(parm_inversion & 3)
1399 tmp = eDVBFrontendParametersSatellite::Inversion_On;
1402 tmp = eDVBFrontendParametersSatellite::Inversion_Off;
1406 PutToDict(dest, "inversion", tmp);
1410 #if HAVE_DVB_API_VERSION >= 5
1411 fillDictWithSatelliteData(dest, parm, p, m_data[FREQ_OFFSET], oparm.sat.orbital_position, oparm.sat.polarisation);
1413 fillDictWithSatelliteData(dest, parm, m_data[FREQ_OFFSET], oparm.sat.orbital_position, oparm.sat.polarisation);
1417 fillDictWithCableData(dest, parm);
1420 fillDictWithTerrestrialData(dest, parm);
1427 void eDVBFrontend::getFrontendData(ePyObject dest)
1429 if (dest && PyDict_Check(dest))
1432 PutToDict(dest, "tuner_number", m_slotid);
1448 PutToDict(dest, "tuner_type", tmp);
1452 #ifndef FP_IOCTL_GET_ID
1453 #define FP_IOCTL_GET_ID 0
1455 int eDVBFrontend::readInputpower()
1459 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1461 char proc_name2[64];
1462 sprintf(proc_name, "/proc/stb/frontend/%d/lnb_sense", m_slotid);
1463 sprintf(proc_name2, "/proc/stb/fp/lnb_sense%d", m_slotid);
1465 if ((f=fopen(proc_name, "r")) || (f=fopen(proc_name2, "r")))
1467 if (fscanf(f, "%d", &power) != 1)
1468 eDebug("read %s failed!! (%m)", proc_name);
1470 eDebug("%s is %d\n", proc_name, power);
1475 // open front prozessor
1476 int fp=::open("/dev/dbox/fp0", O_RDWR);
1479 eDebug("couldn't open fp");
1482 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1483 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1485 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1494 bool eDVBFrontend::setSecSequencePos(int steps)
1496 eDebugNoSimulate("set sequence pos %d", steps);
1501 if (m_sec_sequence.current() != m_sec_sequence.end())
1502 ++m_sec_sequence.current();
1507 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1508 --m_sec_sequence.current();
1514 void eDVBFrontend::tuneLoop()
1519 int eDVBFrontend::tuneLoopInt() // called by m_tuneTimer
1522 eDVBFrontend *sec_fe = this;
1523 eDVBRegisteredFrontend *regFE = 0;
1524 long tmp = m_data[LINKED_PREV_PTR];
1527 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1528 sec_fe = prev->m_frontend;
1529 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1530 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1531 int state = sec_fe->m_state;
1532 // workaround to put the kernel frontend thread into idle state!
1533 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1535 sec_fe->closeFrontend(true);
1536 state = sec_fe->m_state;
1538 // sec_fe is closed... we must reopen it here..
1539 if (state == stateClosed)
1547 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1549 long *sec_fe_data = sec_fe->m_data;
1550 // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1552 switch (m_sec_sequence.current()->cmd)
1554 case eSecCommand::SLEEP:
1555 delay = m_sec_sequence.current()++->msec;
1556 eDebugNoSimulate("[SEC] sleep %dms", delay);
1558 case eSecCommand::GOTO:
1559 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1560 ++m_sec_sequence.current();
1562 case eSecCommand::SET_VOLTAGE:
1564 int voltage = m_sec_sequence.current()++->voltage;
1565 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1566 sec_fe->setVoltage(voltage);
1569 case eSecCommand::IF_VOLTAGE_GOTO:
1571 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1572 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1574 ++m_sec_sequence.current();
1577 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1579 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1580 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1582 ++m_sec_sequence.current();
1585 case eSecCommand::IF_TONE_GOTO:
1587 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1588 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1590 ++m_sec_sequence.current();
1593 case eSecCommand::IF_NOT_TONE_GOTO:
1595 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1596 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1598 ++m_sec_sequence.current();
1601 case eSecCommand::SET_TONE:
1602 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1603 sec_fe->setTone(m_sec_sequence.current()++->tone);
1605 case eSecCommand::SEND_DISEQC:
1606 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1607 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1608 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1609 eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1610 if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
1611 eDebugNoSimulate("(DiSEqC reset)");
1612 else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
1613 eDebugNoSimulate("(DiSEqC peripherial power on)");
1615 eDebugNoSimulate("");
1616 ++m_sec_sequence.current();
1618 case eSecCommand::SEND_TONEBURST:
1619 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1620 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1622 case eSecCommand::SET_FRONTEND:
1624 int enableEvents = (m_sec_sequence.current()++)->val;
1625 eDebugNoSimulate("[SEC] setFrontend %d", enableEvents);
1626 setFrontend(enableEvents);
1629 case eSecCommand::START_TUNE_TIMEOUT:
1631 int tuneTimeout = m_sec_sequence.current()->timeout;
1632 eDebugNoSimulate("[SEC] startTuneTimeout %d", tuneTimeout);
1634 m_timeout->start(tuneTimeout, 1);
1635 ++m_sec_sequence.current();
1638 case eSecCommand::SET_TIMEOUT:
1639 m_timeoutCount = m_sec_sequence.current()++->val;
1640 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1642 case eSecCommand::IF_TIMEOUT_GOTO:
1643 if (!m_timeoutCount)
1645 eDebugNoSimulate("[SEC] rotor timout");
1646 setSecSequencePos(m_sec_sequence.current()->steps);
1649 ++m_sec_sequence.current();
1651 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1653 int idx = m_sec_sequence.current()++->val;
1654 if ( idx == 0 || idx == 1 )
1656 m_idleInputpower[idx] = sec_fe->readInputpower();
1657 eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1660 eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1663 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1665 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1666 int idx = compare.val;
1667 if ( !m_simulate && (idx == 0 || idx == 1) )
1669 int idle = sec_fe->readInputpower();
1670 int diff = abs(idle-m_idleInputpower[idx]);
1673 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1674 setSecSequencePos(compare.steps);
1678 ++m_sec_sequence.current();
1681 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1683 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1686 setSecSequencePos(cmd.steps);
1690 int isLocked = readFrontendData(locked);
1691 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1693 if (!m_timeoutCount && m_retryCount > 0)
1695 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 40) || !cmd.lastSignal))
1698 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1701 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1703 cmd.lastSignal = signal;
1706 if (cmd.okcount > 4)
1708 eDebugNoSimulate("ok > 4 .. goto %d\n", cmd.steps);
1709 setSecSequencePos(cmd.steps);
1710 m_state = stateLock;
1711 m_stateChanged(this);
1712 feEvent(-1); // flush events
1720 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1722 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1726 ++m_sec_sequence.current();
1729 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1730 m_runningInputpower = sec_fe->readInputpower();
1731 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1732 ++m_sec_sequence.current();
1734 case eSecCommand::SET_ROTOR_MOVING:
1736 m_sec->setRotorMoving(m_slotid, true);
1737 ++m_sec_sequence.current();
1739 case eSecCommand::SET_ROTOR_STOPPED:
1741 m_sec->setRotorMoving(m_slotid, false);
1742 ++m_sec_sequence.current();
1744 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1746 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1749 setSecSequencePos(cmd.steps);
1752 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1753 const char *txt = cmd.direction ? "running" : "stopped";
1755 if (!m_timeoutCount && m_retryCount > 0)
1757 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1759 m_runningInputpower,
1762 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1763 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1766 eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1767 if ( cmd.okcount > 6 )
1769 eDebugNoSimulate("[SEC] rotor is %s", txt);
1770 if (setSecSequencePos(cmd.steps))
1776 eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1779 ++m_sec_sequence.current();
1782 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1783 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1784 setSecSequencePos(m_sec_sequence.current()->steps);
1786 ++m_sec_sequence.current();
1788 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1789 eDebugNoSimulate("[SEC] invalidate current switch params");
1790 sec_fe_data[CSW] = -1;
1791 sec_fe_data[UCSW] = -1;
1792 sec_fe_data[TONEBURST] = -1;
1793 ++m_sec_sequence.current();
1795 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1796 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1797 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1798 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1799 eDebugNoSimulate("[SEC] update current switch params");
1800 ++m_sec_sequence.current();
1802 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1803 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1804 sec_fe_data[ROTOR_CMD] = -1;
1805 sec_fe_data[ROTOR_POS] = -1;
1806 ++m_sec_sequence.current();
1808 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1809 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1810 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1811 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1812 ++m_sec_sequence.current();
1814 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1815 m_retryCount = m_sec_sequence.current()++->val;
1816 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1818 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1821 eDebugNoSimulate("[SEC] no more rotor retrys");
1822 setSecSequencePos(m_sec_sequence.current()->steps);
1825 ++m_sec_sequence.current();
1827 case eSecCommand::SET_POWER_LIMITING_MODE:
1832 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1833 FILE *f=fopen(proc_name, "w");
1834 if (f) // new interface exist?
1836 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1837 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1838 eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1840 eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1843 else if (sec_fe->m_need_rotor_workaround)
1846 int slotid = sec_fe->m_slotid;
1847 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1849 sprintf(dev, "/dev/i2c/%d", slotid);
1850 else if (slotid == 2)
1851 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1852 else if (slotid == 3)
1853 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1854 int fd = ::open(dev, O_RDWR);
1856 unsigned char data[2];
1857 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1858 if(::read(fd, data, 1) != 1)
1859 eDebugNoSimulate("[SEC] error read lnbp (%m)");
1860 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1862 data[0] |= 0x80; // enable static current limiting
1863 eDebugNoSimulate("[SEC] set static current limiting");
1867 data[0] &= ~0x80; // enable dynamic current limiting
1868 eDebugNoSimulate("[SEC] set dynamic current limiting");
1870 if(::write(fd, data, 1) != 1)
1871 eDebugNoSimulate("[SEC] error write lnbp (%m)");
1875 ++m_sec_sequence.current();
1878 case eSecCommand::DELAYED_CLOSE_FRONTEND:
1880 eDebugNoSimulate("[SEC] delayed close frontend");
1881 closeFrontend(false, true);
1882 ++m_sec_sequence.current();
1886 eDebugNoSimulate("[SEC] unhandled sec command %d",
1887 ++m_sec_sequence.current()->cmd);
1888 ++m_sec_sequence.current();
1891 m_tuneTimer->start(delay,true);
1895 if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1900 void eDVBFrontend::setFrontend(bool recvEvents)
1904 eDebug("setting frontend %d", m_dvbid);
1907 feEvent(-1); // flush events
1908 #if HAVE_DVB_API_VERSION >= 5
1909 if (m_type == iDVBFrontend::feSatellite)
1911 fe_rolloff_t rolloff = ROLLOFF_35;
1912 fe_pilot_t pilot = PILOT_OFF;
1913 fe_modulation_t modulation = QPSK;
1914 fe_delivery_system_t system = SYS_DVBS;
1915 switch(oparm.sat.system)
1917 case eDVBFrontendParametersSatellite::System_DVB_S: system = SYS_DVBS; break;
1918 case eDVBFrontendParametersSatellite::System_DVB_S2: system = SYS_DVBS2; break;
1920 switch(oparm.sat.modulation)
1922 case eDVBFrontendParametersSatellite::Modulation_QPSK: modulation = QPSK; break;
1923 case eDVBFrontendParametersSatellite::Modulation_8PSK: modulation = PSK_8; break;
1924 case eDVBFrontendParametersSatellite::Modulation_QAM16: modulation = QAM_16; break;
1926 switch(oparm.sat.pilot)
1928 case eDVBFrontendParametersSatellite::Pilot_Off: pilot = PILOT_OFF; break;
1929 case eDVBFrontendParametersSatellite::Pilot_On: pilot = PILOT_ON; break;
1930 case eDVBFrontendParametersSatellite::Pilot_Unknown: pilot = PILOT_AUTO; break;
1932 switch(oparm.sat.rolloff)
1934 case eDVBFrontendParametersSatellite::RollOff_alpha_0_20: rolloff = ROLLOFF_20; break;
1935 case eDVBFrontendParametersSatellite::RollOff_alpha_0_25: rolloff = ROLLOFF_25; break;
1936 case eDVBFrontendParametersSatellite::RollOff_alpha_0_35: rolloff = ROLLOFF_35; break;
1938 struct dtv_property p[10];
1939 struct dtv_properties cmdseq;
1941 p[0].cmd = DTV_CLEAR;
1942 p[1].cmd = DTV_DELIVERY_SYSTEM, p[1].u.data = system;
1943 p[2].cmd = DTV_FREQUENCY, p[2].u.data = parm_frequency;
1944 p[3].cmd = DTV_MODULATION, p[3].u.data = modulation;
1945 p[4].cmd = DTV_SYMBOL_RATE, p[4].u.data = parm_u_qpsk_symbol_rate;
1946 p[5].cmd = DTV_INNER_FEC, p[5].u.data = parm_u_qpsk_fec_inner;
1947 p[6].cmd = DTV_INVERSION, p[6].u.data = parm_inversion;
1948 if (system == SYS_DVBS2)
1950 p[7].cmd = DTV_ROLLOFF, p[7].u.data = rolloff;
1951 p[8].cmd = DTV_PILOT, p[8].u.data = pilot;
1952 p[9].cmd = DTV_TUNE;
1957 p[7].cmd = DTV_TUNE;
1960 if (ioctl(m_fd, FE_SET_PROPERTY, &cmdseq) == -1)
1962 perror("FE_SET_PROPERTY failed");
1969 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1971 perror("FE_SET_FRONTEND failed");
1978 RESULT eDVBFrontend::getFrontendType(int &t)
1986 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1991 eWarning("no SEC module active!");
1994 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1997 #if HAVE_DVB_API_VERSION >= 3
1998 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",
2001 feparm.polarisation,
2005 feparm.orbital_position,
2011 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
2014 feparm.polarisation,
2018 feparm.orbital_position);
2020 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
2021 switch (feparm.inversion)
2023 case eDVBFrontendParametersSatellite::Inversion_On:
2024 parm_inversion = INVERSION_ON;
2026 case eDVBFrontendParametersSatellite::Inversion_Off:
2027 parm_inversion = INVERSION_OFF;
2030 case eDVBFrontendParametersSatellite::Inversion_Unknown:
2031 parm_inversion = INVERSION_AUTO;
2034 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S)
2038 case eDVBFrontendParametersSatellite::FEC_None:
2039 parm_u_qpsk_fec_inner = FEC_NONE;
2041 case eDVBFrontendParametersSatellite::FEC_1_2:
2042 parm_u_qpsk_fec_inner = FEC_1_2;
2044 case eDVBFrontendParametersSatellite::FEC_2_3:
2045 parm_u_qpsk_fec_inner = FEC_2_3;
2047 case eDVBFrontendParametersSatellite::FEC_3_4:
2048 parm_u_qpsk_fec_inner = FEC_3_4;
2050 case eDVBFrontendParametersSatellite::FEC_5_6:
2051 parm_u_qpsk_fec_inner = FEC_5_6;
2053 case eDVBFrontendParametersSatellite::FEC_7_8:
2054 parm_u_qpsk_fec_inner = FEC_7_8;
2057 eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
2058 case eDVBFrontendParametersSatellite::FEC_Auto:
2059 parm_u_qpsk_fec_inner = FEC_AUTO;
2063 #if HAVE_DVB_API_VERSION >= 3
2068 case eDVBFrontendParametersSatellite::FEC_1_2:
2069 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
2071 case eDVBFrontendParametersSatellite::FEC_2_3:
2072 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
2074 case eDVBFrontendParametersSatellite::FEC_3_4:
2075 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
2077 case eDVBFrontendParametersSatellite::FEC_3_5:
2078 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
2080 case eDVBFrontendParametersSatellite::FEC_4_5:
2081 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
2083 case eDVBFrontendParametersSatellite::FEC_5_6:
2084 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
2086 case eDVBFrontendParametersSatellite::FEC_7_8:
2087 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
2089 case eDVBFrontendParametersSatellite::FEC_8_9:
2090 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
2092 case eDVBFrontendParametersSatellite::FEC_9_10:
2093 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
2096 eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
2099 #if HAVE_DVB_API_VERSION < 5
2100 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
2101 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
2102 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation_8PSK)
2104 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
2105 // 8PSK fec driver values are decimal 9 bigger
2110 // FIXME !!! get frequency range from tuner
2111 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
2113 eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
2116 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
2122 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
2124 #if HAVE_DVB_API_VERSION < 3
2125 parm_frequency = feparm.frequency;
2127 parm_frequency = feparm.frequency * 1000;
2129 parm_u_qam_symbol_rate = feparm.symbol_rate;
2130 switch (feparm.modulation)
2132 case eDVBFrontendParametersCable::Modulation_QAM16:
2133 parm_u_qam_modulation = QAM_16;
2135 case eDVBFrontendParametersCable::Modulation_QAM32:
2136 parm_u_qam_modulation = QAM_32;
2138 case eDVBFrontendParametersCable::Modulation_QAM64:
2139 parm_u_qam_modulation = QAM_64;
2141 case eDVBFrontendParametersCable::Modulation_QAM128:
2142 parm_u_qam_modulation = QAM_128;
2144 case eDVBFrontendParametersCable::Modulation_QAM256:
2145 parm_u_qam_modulation = QAM_256;
2148 case eDVBFrontendParametersCable::Modulation_Auto:
2149 parm_u_qam_modulation = QAM_AUTO;
2152 switch (feparm.inversion)
2154 case eDVBFrontendParametersCable::Inversion_On:
2155 parm_inversion = INVERSION_ON;
2157 case eDVBFrontendParametersCable::Inversion_Off:
2158 parm_inversion = INVERSION_OFF;
2161 case eDVBFrontendParametersCable::Inversion_Unknown:
2162 parm_inversion = INVERSION_AUTO;
2165 switch (feparm.fec_inner)
2167 case eDVBFrontendParametersCable::FEC_None:
2168 parm_u_qam_fec_inner = FEC_NONE;
2170 case eDVBFrontendParametersCable::FEC_1_2:
2171 parm_u_qam_fec_inner = FEC_1_2;
2173 case eDVBFrontendParametersCable::FEC_2_3:
2174 parm_u_qam_fec_inner = FEC_2_3;
2176 case eDVBFrontendParametersCable::FEC_3_4:
2177 parm_u_qam_fec_inner = FEC_3_4;
2179 case eDVBFrontendParametersCable::FEC_5_6:
2180 parm_u_qam_fec_inner = FEC_5_6;
2182 case eDVBFrontendParametersCable::FEC_7_8:
2183 parm_u_qam_fec_inner = FEC_7_8;
2185 #if HAVE_DVB_API_VERSION >= 3
2186 case eDVBFrontendParametersCable::FEC_8_9:
2187 parm_u_qam_fec_inner = FEC_8_9;
2191 case eDVBFrontendParametersCable::FEC_Auto:
2192 parm_u_qam_fec_inner = FEC_AUTO;
2195 eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
2196 parm_frequency/1000,
2197 parm_u_qam_symbol_rate,
2198 parm_u_qam_fec_inner,
2199 parm_u_qam_modulation,
2205 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
2207 parm_frequency = feparm.frequency;
2209 switch (feparm.bandwidth)
2211 case eDVBFrontendParametersTerrestrial::Bandwidth_8MHz:
2212 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
2214 case eDVBFrontendParametersTerrestrial::Bandwidth_7MHz:
2215 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
2217 case eDVBFrontendParametersTerrestrial::Bandwidth_6MHz:
2218 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
2221 case eDVBFrontendParametersTerrestrial::Bandwidth_Auto:
2222 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
2225 switch (feparm.code_rate_LP)
2227 case eDVBFrontendParametersTerrestrial::FEC_1_2:
2228 parm_u_ofdm_code_rate_LP = FEC_1_2;
2230 case eDVBFrontendParametersTerrestrial::FEC_2_3:
2231 parm_u_ofdm_code_rate_LP = FEC_2_3;
2233 case eDVBFrontendParametersTerrestrial::FEC_3_4:
2234 parm_u_ofdm_code_rate_LP = FEC_3_4;
2236 case eDVBFrontendParametersTerrestrial::FEC_5_6:
2237 parm_u_ofdm_code_rate_LP = FEC_5_6;
2239 case eDVBFrontendParametersTerrestrial::FEC_7_8:
2240 parm_u_ofdm_code_rate_LP = FEC_7_8;
2243 case eDVBFrontendParametersTerrestrial::FEC_Auto:
2244 parm_u_ofdm_code_rate_LP = FEC_AUTO;
2247 switch (feparm.code_rate_HP)
2249 case eDVBFrontendParametersTerrestrial::FEC_1_2:
2250 parm_u_ofdm_code_rate_HP = FEC_1_2;
2252 case eDVBFrontendParametersTerrestrial::FEC_2_3:
2253 parm_u_ofdm_code_rate_HP = FEC_2_3;
2255 case eDVBFrontendParametersTerrestrial::FEC_3_4:
2256 parm_u_ofdm_code_rate_HP = FEC_3_4;
2258 case eDVBFrontendParametersTerrestrial::FEC_5_6:
2259 parm_u_ofdm_code_rate_HP = FEC_5_6;
2261 case eDVBFrontendParametersTerrestrial::FEC_7_8:
2262 parm_u_ofdm_code_rate_HP = FEC_7_8;
2265 case eDVBFrontendParametersTerrestrial::FEC_Auto:
2266 parm_u_ofdm_code_rate_HP = FEC_AUTO;
2269 switch (feparm.modulation)
2271 case eDVBFrontendParametersTerrestrial::Modulation_QPSK:
2272 parm_u_ofdm_constellation = QPSK;
2274 case eDVBFrontendParametersTerrestrial::Modulation_QAM16:
2275 parm_u_ofdm_constellation = QAM_16;
2277 case eDVBFrontendParametersTerrestrial::Modulation_QAM64:
2278 parm_u_ofdm_constellation = QAM_64;
2281 case eDVBFrontendParametersTerrestrial::Modulation_Auto:
2282 parm_u_ofdm_constellation = QAM_AUTO;
2285 switch (feparm.transmission_mode)
2287 case eDVBFrontendParametersTerrestrial::TransmissionMode_2k:
2288 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2290 case eDVBFrontendParametersTerrestrial::TransmissionMode_8k:
2291 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2294 case eDVBFrontendParametersTerrestrial::TransmissionMode_Auto:
2295 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2298 switch (feparm.guard_interval)
2300 case eDVBFrontendParametersTerrestrial::GuardInterval_1_32:
2301 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2303 case eDVBFrontendParametersTerrestrial::GuardInterval_1_16:
2304 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2306 case eDVBFrontendParametersTerrestrial::GuardInterval_1_8:
2307 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2309 case eDVBFrontendParametersTerrestrial::GuardInterval_1_4:
2310 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2313 case eDVBFrontendParametersTerrestrial::GuardInterval_Auto:
2314 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2317 switch (feparm.hierarchy)
2319 case eDVBFrontendParametersTerrestrial::Hierarchy_None:
2320 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2322 case eDVBFrontendParametersTerrestrial::Hierarchy_1:
2323 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2325 case eDVBFrontendParametersTerrestrial::Hierarchy_2:
2326 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2328 case eDVBFrontendParametersTerrestrial::Hierarchy_4:
2329 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2332 case eDVBFrontendParametersTerrestrial::Hierarchy_Auto:
2333 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2336 switch (feparm.inversion)
2338 case eDVBFrontendParametersTerrestrial::Inversion_On:
2339 parm_inversion = INVERSION_ON;
2341 case eDVBFrontendParametersTerrestrial::Inversion_Off:
2342 parm_inversion = INVERSION_OFF;
2345 case eDVBFrontendParametersTerrestrial::Inversion_Unknown:
2346 parm_inversion = INVERSION_AUTO;
2353 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2355 unsigned int timeout = 5000;
2356 eDebugNoSimulate("(%d)tune", m_dvbid);
2362 if (!m_sn && !m_simulate)
2364 eDebug("no frontend device opened... do not try to tune !!!");
2378 m_sec_sequence.clear();
2380 where.calcLockTimeout(timeout);
2386 eDVBFrontendParametersSatellite feparm;
2387 if (where.getDVBS(feparm))
2389 eDebug("no dvbs data!");
2393 if (m_rotor_mode != feparm.no_rotor_command_on_tune && !feparm.no_rotor_command_on_tune)
2395 eDVBFrontend *sec_fe = this;
2396 long tmp = m_data[LINKED_PREV_PTR];
2399 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
2400 sec_fe = linked_fe->m_frontend;
2401 sec_fe->getData(LINKED_NEXT_PTR, tmp);
2403 eDebug("(fe%d) reset diseqc after leave rotor mode!", m_dvbid);
2404 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
2406 m_rotor_mode = feparm.no_rotor_command_on_tune;
2408 m_sec->setRotorMoving(m_slotid, false);
2409 res=prepare_sat(feparm, timeout);
2417 eDVBFrontendParametersCable feparm;
2418 if (where.getDVBC(feparm))
2423 res=prepare_cable(feparm);
2427 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2428 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2433 eDVBFrontendParametersTerrestrial feparm;
2434 if (where.getDVBT(feparm))
2436 eDebug("no -T data");
2440 res=prepare_terrestrial(feparm);
2444 std::string enable_5V;
2445 char configStr[255];
2446 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2447 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2448 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2449 if (enable_5V == "True")
2450 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2452 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2453 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2459 m_sec_sequence.current() = m_sec_sequence.begin();
2463 m_tuneTimer->start(0,true);
2465 if (m_state != stateTuning)
2467 m_state = stateTuning;
2468 m_stateChanged(this);
2477 m_tuneTimer->stop();
2481 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2483 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2487 RESULT eDVBFrontend::setVoltage(int voltage)
2489 if (m_type == feCable)
2491 #if HAVE_DVB_API_VERSION < 3
2494 bool increased=false;
2495 fe_sec_voltage_t vlt;
2497 m_data[CUR_VOLTAGE]=voltage;
2501 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2502 vlt = SEC_VOLTAGE_OFF;
2505 #if HAVE_DVB_API_VERSION < 3
2506 vlt = SEC_VOLTAGE_13_5;
2512 vlt = SEC_VOLTAGE_13;
2515 #if HAVE_DVB_API_VERSION < 3
2516 vlt = SEC_VOLTAGE_18_5;
2522 vlt = SEC_VOLTAGE_18;
2529 #if HAVE_DVB_API_VERSION < 3
2530 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2532 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2533 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2534 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2538 RESULT eDVBFrontend::getState(int &state)
2544 RESULT eDVBFrontend::setTone(int t)
2546 if (m_type != feSatellite)
2548 #if HAVE_DVB_API_VERSION < 3
2551 fe_sec_tone_mode_t tone;
2560 tone = SEC_TONE_OFF;
2567 #if HAVE_DVB_API_VERSION < 3
2568 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2570 return ::ioctl(m_fd, FE_SET_TONE, tone);
2574 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2575 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2578 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2582 #if HAVE_DVB_API_VERSION < 3
2583 struct secCommand cmd;
2584 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2585 cmd.u.diseqc.cmdtype = diseqc.data[0];
2586 cmd.u.diseqc.addr = diseqc.data[1];
2587 cmd.u.diseqc.cmd = diseqc.data[2];
2588 cmd.u.diseqc.numParams = diseqc.len-3;
2589 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2590 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2592 struct dvb_diseqc_master_cmd cmd;
2593 memcpy(cmd.msg, diseqc.data, diseqc.len);
2594 cmd.msg_len = diseqc.len;
2595 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2601 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2602 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2604 RESULT eDVBFrontend::sendToneburst(int burst)
2608 #if HAVE_DVB_API_VERSION < 3
2609 secMiniCmd cmd = SEC_MINI_NONE;
2611 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2613 if ( burst == eDVBSatelliteDiseqcParameters::A )
2615 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2617 #if HAVE_DVB_API_VERSION < 3
2618 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2621 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2627 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2633 RESULT eDVBFrontend::setSecSequence(eSecCommandList &list)
2635 if (m_data[SATCR] != -1 && m_sec_sequence.current() != m_sec_sequence.end())
2636 m_sec_sequence.push_back(list);
2638 m_sec_sequence = list;
2642 RESULT eDVBFrontend::getData(int num, long &data)
2644 if ( num < NUM_DATA_ENTRIES )
2652 RESULT eDVBFrontend::setData(int num, long val)
2654 if ( num < NUM_DATA_ENTRIES )
2662 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2665 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2667 if (m_type == eDVBFrontend::feSatellite)
2670 eDVBFrontendParametersSatellite sat_parm;
2671 int ret = feparm->getDVBS(sat_parm);
2673 if (sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S2 && !m_can_handle_dvbs2)
2675 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2676 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S && m_can_handle_dvbs2)
2680 else if (m_type == eDVBFrontend::feCable)
2681 return 2; // more prio for cable frontends
2682 else if (m_type == eDVBFrontend::feTerrestrial)
2687 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2689 ePyObject Id, Descr, Enabled, IsDVBS2;
2690 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4)
2692 Id = PyTuple_GET_ITEM(obj, 0);
2693 Descr = PyTuple_GET_ITEM(obj, 1);
2694 Enabled = PyTuple_GET_ITEM(obj, 2);
2695 IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2696 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2))
2698 strcpy(m_description, PyString_AS_STRING(Descr));
2699 m_slotid = PyInt_AsLong(Id);
2700 m_enabled = Enabled == Py_True;
2701 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2702 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2703 !!strstr(m_description, "Alps BSBE2") ||
2704 !!strstr(m_description, "Alps -S") ||
2705 !!strstr(m_description, "BCM4501");
2706 m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2707 eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2708 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2711 PyErr_SetString(PyExc_StandardError,
2712 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");