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");
1079 PutToDict(dict, "fec_inner", tmp);
1081 switch (p[0].u.data)
1083 default: eDebug("got unsupported system from frontend! report as DVBS!");
1084 case SYS_DVBS: tmp = eDVBFrontendParametersSatellite::System_DVB_S; break;
1087 switch (p[2].u.data)
1089 default: eDebug("got unsupported rolloff from frontend! report as 0_20!");
1090 case ROLLOFF_20: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1091 case ROLLOFF_25: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1092 case ROLLOFF_35: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1094 PutToDict(dict, "rolloff", tmp);
1096 switch (p[3].u.data)
1098 case PILOT_OFF: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1099 case PILOT_ON: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1100 case PILOT_AUTO: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1102 PutToDict(dict, "pilot", tmp);
1104 tmp = eDVBFrontendParametersSatellite::System_DVB_S2; break;
1107 PutToDict(dict, "system", tmp);
1109 switch (p[1].u.data)
1111 default: eDebug("got unsupported modulation from frontend! report as QPSK!");
1112 case QPSK: tmp = eDVBFrontendParametersSatellite::Modulation_QPSK; break;
1113 case PSK_8: tmp = eDVBFrontendParametersSatellite::Modulation_8PSK; break;
1115 PutToDict(dict, "modulation", tmp);
1119 static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, long freq_offset, int orb_pos, int polarization)
1122 int frequency = parm_frequency + freq_offset;
1123 PutToDict(dict, "frequency", frequency);
1124 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
1125 PutToDict(dict, "orbital_position", orb_pos);
1126 PutToDict(dict, "polarization", polarization);
1128 switch((int)parm_u_qpsk_fec_inner)
1130 case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1131 case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1132 case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1133 case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1134 case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1135 case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
1137 case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
1138 #if HAVE_DVB_API_VERSION >=3
1139 case FEC_S2_8PSK_1_2:
1140 case FEC_S2_QPSK_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1141 case FEC_S2_8PSK_2_3:
1142 case FEC_S2_QPSK_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1143 case FEC_S2_8PSK_3_4:
1144 case FEC_S2_QPSK_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1145 case FEC_S2_8PSK_5_6:
1146 case FEC_S2_QPSK_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1147 case FEC_S2_8PSK_7_8:
1148 case FEC_S2_QPSK_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1149 case FEC_S2_8PSK_8_9:
1150 case FEC_S2_QPSK_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
1151 case FEC_S2_8PSK_3_5:
1152 case FEC_S2_QPSK_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
1153 case FEC_S2_8PSK_4_5:
1154 case FEC_S2_QPSK_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
1155 case FEC_S2_8PSK_9_10:
1156 case FEC_S2_QPSK_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1159 PutToDict(dict, "fec_inner", tmp);
1160 #if HAVE_DVB_API_VERSION >=3
1161 PutToDict(dict, "modulation",
1162 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ?
1163 eDVBFrontendParametersSatellite::Modulation_8PSK :
1164 eDVBFrontendParametersSatellite::Modulation_QPSK );
1165 if (parm_u_qpsk_fec_inner > FEC_AUTO)
1167 switch(parm_inversion & 0xc)
1169 default: // unknown rolloff
1170 case 0: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1171 case 4: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1172 case 8: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1174 PutToDict(dict, "rolloff", tmp);
1175 switch(parm_inversion & 0x30)
1177 case 0: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1178 case 0x10: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1179 case 0x20: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1181 PutToDict(dict, "pilot", tmp);
1182 tmp = eDVBFrontendParametersSatellite::System_DVB_S2;
1185 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1187 PutToDict(dict, "modulation", eDVBFrontendParametersSatellite::Modulation_QPSK );
1188 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1190 PutToDict(dict, "system", tmp);
1194 static void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1197 #if HAVE_DVB_API_VERSION < 3
1198 PutToDict(dict, "frequency", parm_frequency);
1200 PutToDict(dict, "frequency", parm_frequency/1000);
1202 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1203 switch(parm_u_qam_fec_inner)
1205 case FEC_NONE: tmp = eDVBFrontendParametersCable::FEC_None; break;
1206 case FEC_1_2: tmp = eDVBFrontendParametersCable::FEC_1_2; break;
1207 case FEC_2_3: tmp = eDVBFrontendParametersCable::FEC_2_3; break;
1208 case FEC_3_4: tmp = eDVBFrontendParametersCable::FEC_3_4; break;
1209 case FEC_5_6: tmp = eDVBFrontendParametersCable::FEC_5_6; break;
1210 case FEC_7_8: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1211 #if HAVE_DVB_API_VERSION >= 3
1212 case FEC_8_9: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1215 case FEC_AUTO: tmp = eDVBFrontendParametersCable::FEC_Auto; break;
1217 PutToDict(dict, "fec_inner", tmp);
1218 switch(parm_u_qam_modulation)
1220 case QAM_16: tmp = eDVBFrontendParametersCable::Modulation_QAM16; break;
1221 case QAM_32: tmp = eDVBFrontendParametersCable::Modulation_QAM32; break;
1222 case QAM_64: tmp = eDVBFrontendParametersCable::Modulation_QAM64; break;
1223 case QAM_128: tmp = eDVBFrontendParametersCable::Modulation_QAM128; break;
1224 case QAM_256: tmp = eDVBFrontendParametersCable::Modulation_QAM256; break;
1226 case QAM_AUTO: tmp = eDVBFrontendParametersCable::Modulation_Auto; break;
1228 PutToDict(dict, "modulation", tmp);
1231 static void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1234 PutToDict(dict, "frequency", parm_frequency);
1235 switch (parm_u_ofdm_bandwidth)
1237 case BANDWIDTH_8_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_8MHz; break;
1238 case BANDWIDTH_7_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_7MHz; break;
1239 case BANDWIDTH_6_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_6MHz; break;
1241 case BANDWIDTH_AUTO: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_Auto; break;
1243 PutToDict(dict, "bandwidth", tmp);
1244 switch (parm_u_ofdm_code_rate_LP)
1246 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1247 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1248 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1249 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1250 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1252 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1254 PutToDict(dict, "code_rate_lp", tmp);
1255 switch (parm_u_ofdm_code_rate_HP)
1257 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1258 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1259 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1260 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1261 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1263 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1265 PutToDict(dict, "code_rate_hp", tmp);
1266 switch (parm_u_ofdm_constellation)
1268 case QPSK: tmp = eDVBFrontendParametersTerrestrial::Modulation_QPSK; break;
1269 case QAM_16: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM16; break;
1270 case QAM_64: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM64; break;
1272 case QAM_AUTO: tmp = eDVBFrontendParametersTerrestrial::Modulation_Auto; break;
1274 PutToDict(dict, "constellation", tmp);
1275 switch (parm_u_ofdm_transmission_mode)
1277 case TRANSMISSION_MODE_2K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_2k; break;
1278 case TRANSMISSION_MODE_8K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_8k; break;
1280 case TRANSMISSION_MODE_AUTO: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto; break;
1282 PutToDict(dict, "transmission_mode", tmp);
1283 switch (parm_u_ofdm_guard_interval)
1285 case GUARD_INTERVAL_1_32: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_32; break;
1286 case GUARD_INTERVAL_1_16: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_16; break;
1287 case GUARD_INTERVAL_1_8: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_8; break;
1288 case GUARD_INTERVAL_1_4: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_4; break;
1290 case GUARD_INTERVAL_AUTO: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_Auto; break;
1292 PutToDict(dict, "guard_interval", tmp);
1293 switch (parm_u_ofdm_hierarchy_information)
1295 case HIERARCHY_NONE: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_None; break;
1296 case HIERARCHY_1: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_1; break;
1297 case HIERARCHY_2: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_2; break;
1298 case HIERARCHY_4: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_4; break;
1300 case HIERARCHY_AUTO: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_Auto; break;
1302 PutToDict(dict, "hierarchy_information", tmp);
1305 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1307 if (dest && PyDict_Check(dest))
1309 const char *tmp = "UNKNOWN";
1330 PutToDict(dest, "tuner_state", tmp);
1331 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1332 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1333 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1334 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1335 int sigQualitydB = readFrontendData(signalQualitydB);
1336 if (sigQualitydB == 0x12345678) // not support yet
1338 ePyObject obj=Py_None;
1340 PutToDict(dest, "tuner_signal_quality_db", obj);
1343 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1344 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1348 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1350 if (dest && PyDict_Check(dest))
1352 FRONTENDPARAMETERS front;
1353 #if HAVE_DVB_API_VERSION >= 5
1354 struct dtv_property p[4];
1355 struct dtv_properties cmdseq;
1358 p[0].cmd = DTV_DELIVERY_SYSTEM;
1359 p[1].cmd = DTV_MODULATION;
1360 p[2].cmd = DTV_ROLLOFF;
1361 p[3].cmd = DTV_PILOT;
1363 if (m_simulate || m_fd == -1 || original)
1365 #if HAVE_DVB_API_VERSION >= 5
1366 else if (m_type == feSatellite && // yet just use new api for DVB-S(2) only
1367 ioctl(m_fd, FE_GET_PROPERTY, &cmdseq)<0)
1369 eDebug("FE_GET_PROPERTY failed (%m)");
1373 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1375 eDebug("FE_GET_FRONTEND failed (%m)");
1383 PutSatelliteDataToDict(dest, oparm.sat);
1386 PutCableDataToDict(dest, oparm.cab);
1389 PutTerrestrialDataToDict(dest, oparm.ter);
1395 FRONTENDPARAMETERS &parm = front;
1396 long tmp = eDVBFrontendParametersSatellite::Inversion_Unknown;
1397 switch(parm_inversion & 3)
1400 tmp = eDVBFrontendParametersSatellite::Inversion_On;
1403 tmp = eDVBFrontendParametersSatellite::Inversion_Off;
1407 PutToDict(dest, "inversion", tmp);
1411 #if HAVE_DVB_API_VERSION >= 5
1412 fillDictWithSatelliteData(dest, parm, p, m_data[FREQ_OFFSET], oparm.sat.orbital_position, oparm.sat.polarisation);
1414 fillDictWithSatelliteData(dest, parm, m_data[FREQ_OFFSET], oparm.sat.orbital_position, oparm.sat.polarisation);
1418 fillDictWithCableData(dest, parm);
1421 fillDictWithTerrestrialData(dest, parm);
1428 void eDVBFrontend::getFrontendData(ePyObject dest)
1430 if (dest && PyDict_Check(dest))
1433 PutToDict(dest, "tuner_number", m_slotid);
1449 PutToDict(dest, "tuner_type", tmp);
1453 #ifndef FP_IOCTL_GET_ID
1454 #define FP_IOCTL_GET_ID 0
1456 int eDVBFrontend::readInputpower()
1460 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1462 char proc_name2[64];
1463 sprintf(proc_name, "/proc/stb/frontend/%d/lnb_sense", m_slotid);
1464 sprintf(proc_name2, "/proc/stb/fp/lnb_sense%d", m_slotid);
1466 if ((f=fopen(proc_name, "r")) || (f=fopen(proc_name2, "r")))
1468 if (fscanf(f, "%d", &power) != 1)
1469 eDebug("read %s failed!! (%m)", proc_name);
1471 eDebug("%s is %d\n", proc_name, power);
1476 // open front prozessor
1477 int fp=::open("/dev/dbox/fp0", O_RDWR);
1480 eDebug("couldn't open fp");
1483 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1484 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1486 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1495 bool eDVBFrontend::setSecSequencePos(int steps)
1497 eDebugNoSimulate("set sequence pos %d", steps);
1502 if (m_sec_sequence.current() != m_sec_sequence.end())
1503 ++m_sec_sequence.current();
1508 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1509 --m_sec_sequence.current();
1515 void eDVBFrontend::tuneLoop()
1520 int eDVBFrontend::tuneLoopInt() // called by m_tuneTimer
1523 eDVBFrontend *sec_fe = this;
1524 eDVBRegisteredFrontend *regFE = 0;
1525 long tmp = m_data[LINKED_PREV_PTR];
1528 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1529 sec_fe = prev->m_frontend;
1530 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1531 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1532 int state = sec_fe->m_state;
1533 // workaround to put the kernel frontend thread into idle state!
1534 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1536 sec_fe->closeFrontend(true);
1537 state = sec_fe->m_state;
1539 // sec_fe is closed... we must reopen it here..
1540 if (state == stateClosed)
1548 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1550 long *sec_fe_data = sec_fe->m_data;
1551 // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1553 switch (m_sec_sequence.current()->cmd)
1555 case eSecCommand::SLEEP:
1556 delay = m_sec_sequence.current()++->msec;
1557 eDebugNoSimulate("[SEC] sleep %dms", delay);
1559 case eSecCommand::GOTO:
1560 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1561 ++m_sec_sequence.current();
1563 case eSecCommand::SET_VOLTAGE:
1565 int voltage = m_sec_sequence.current()++->voltage;
1566 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1567 sec_fe->setVoltage(voltage);
1570 case eSecCommand::IF_VOLTAGE_GOTO:
1572 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1573 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1575 ++m_sec_sequence.current();
1578 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1580 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1581 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1583 ++m_sec_sequence.current();
1586 case eSecCommand::IF_TONE_GOTO:
1588 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1589 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1591 ++m_sec_sequence.current();
1594 case eSecCommand::IF_NOT_TONE_GOTO:
1596 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1597 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1599 ++m_sec_sequence.current();
1602 case eSecCommand::SET_TONE:
1603 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1604 sec_fe->setTone(m_sec_sequence.current()++->tone);
1606 case eSecCommand::SEND_DISEQC:
1607 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1608 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1609 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1610 eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1611 if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
1612 eDebugNoSimulate("(DiSEqC reset)");
1613 else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
1614 eDebugNoSimulate("(DiSEqC peripherial power on)");
1616 eDebugNoSimulate("");
1617 ++m_sec_sequence.current();
1619 case eSecCommand::SEND_TONEBURST:
1620 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1621 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1623 case eSecCommand::SET_FRONTEND:
1625 int enableEvents = (m_sec_sequence.current()++)->val;
1626 eDebugNoSimulate("[SEC] setFrontend %d", enableEvents);
1627 setFrontend(enableEvents);
1630 case eSecCommand::START_TUNE_TIMEOUT:
1632 int tuneTimeout = m_sec_sequence.current()->timeout;
1633 eDebugNoSimulate("[SEC] startTuneTimeout %d", tuneTimeout);
1635 m_timeout->start(tuneTimeout, 1);
1636 ++m_sec_sequence.current();
1639 case eSecCommand::SET_TIMEOUT:
1640 m_timeoutCount = m_sec_sequence.current()++->val;
1641 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1643 case eSecCommand::IF_TIMEOUT_GOTO:
1644 if (!m_timeoutCount)
1646 eDebugNoSimulate("[SEC] rotor timout");
1647 setSecSequencePos(m_sec_sequence.current()->steps);
1650 ++m_sec_sequence.current();
1652 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1654 int idx = m_sec_sequence.current()++->val;
1655 if ( idx == 0 || idx == 1 )
1657 m_idleInputpower[idx] = sec_fe->readInputpower();
1658 eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1661 eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1664 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1666 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1667 int idx = compare.val;
1668 if ( !m_simulate && (idx == 0 || idx == 1) )
1670 int idle = sec_fe->readInputpower();
1671 int diff = abs(idle-m_idleInputpower[idx]);
1674 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1675 setSecSequencePos(compare.steps);
1679 ++m_sec_sequence.current();
1682 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1684 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1687 setSecSequencePos(cmd.steps);
1691 int isLocked = readFrontendData(locked);
1692 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1694 if (!m_timeoutCount && m_retryCount > 0)
1696 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 40) || !cmd.lastSignal))
1699 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1702 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1704 cmd.lastSignal = signal;
1707 if (cmd.okcount > 4)
1709 eDebugNoSimulate("ok > 4 .. goto %d\n", cmd.steps);
1710 setSecSequencePos(cmd.steps);
1711 m_state = stateLock;
1712 m_stateChanged(this);
1713 feEvent(-1); // flush events
1721 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1723 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1727 ++m_sec_sequence.current();
1730 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1731 m_runningInputpower = sec_fe->readInputpower();
1732 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1733 ++m_sec_sequence.current();
1735 case eSecCommand::SET_ROTOR_MOVING:
1737 m_sec->setRotorMoving(m_slotid, true);
1738 ++m_sec_sequence.current();
1740 case eSecCommand::SET_ROTOR_STOPPED:
1742 m_sec->setRotorMoving(m_slotid, false);
1743 ++m_sec_sequence.current();
1745 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1747 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1750 setSecSequencePos(cmd.steps);
1753 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1754 const char *txt = cmd.direction ? "running" : "stopped";
1756 if (!m_timeoutCount && m_retryCount > 0)
1758 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1760 m_runningInputpower,
1763 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1764 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1767 eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1768 if ( cmd.okcount > 6 )
1770 eDebugNoSimulate("[SEC] rotor is %s", txt);
1771 if (setSecSequencePos(cmd.steps))
1777 eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1780 ++m_sec_sequence.current();
1783 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1784 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1785 setSecSequencePos(m_sec_sequence.current()->steps);
1787 ++m_sec_sequence.current();
1789 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1790 eDebugNoSimulate("[SEC] invalidate current switch params");
1791 sec_fe_data[CSW] = -1;
1792 sec_fe_data[UCSW] = -1;
1793 sec_fe_data[TONEBURST] = -1;
1794 ++m_sec_sequence.current();
1796 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1797 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1798 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1799 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1800 eDebugNoSimulate("[SEC] update current switch params");
1801 ++m_sec_sequence.current();
1803 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1804 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1805 sec_fe_data[ROTOR_CMD] = -1;
1806 sec_fe_data[ROTOR_POS] = -1;
1807 ++m_sec_sequence.current();
1809 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1810 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1811 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1812 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1813 ++m_sec_sequence.current();
1815 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1816 m_retryCount = m_sec_sequence.current()++->val;
1817 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1819 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1822 eDebugNoSimulate("[SEC] no more rotor retrys");
1823 setSecSequencePos(m_sec_sequence.current()->steps);
1826 ++m_sec_sequence.current();
1828 case eSecCommand::SET_POWER_LIMITING_MODE:
1833 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1834 FILE *f=fopen(proc_name, "w");
1835 if (f) // new interface exist?
1837 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1838 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1839 eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1841 eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1844 else if (sec_fe->m_need_rotor_workaround)
1847 int slotid = sec_fe->m_slotid;
1848 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1850 sprintf(dev, "/dev/i2c/%d", slotid);
1851 else if (slotid == 2)
1852 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1853 else if (slotid == 3)
1854 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1855 int fd = ::open(dev, O_RDWR);
1857 unsigned char data[2];
1858 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1859 if(::read(fd, data, 1) != 1)
1860 eDebugNoSimulate("[SEC] error read lnbp (%m)");
1861 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1863 data[0] |= 0x80; // enable static current limiting
1864 eDebugNoSimulate("[SEC] set static current limiting");
1868 data[0] &= ~0x80; // enable dynamic current limiting
1869 eDebugNoSimulate("[SEC] set dynamic current limiting");
1871 if(::write(fd, data, 1) != 1)
1872 eDebugNoSimulate("[SEC] error write lnbp (%m)");
1876 ++m_sec_sequence.current();
1879 case eSecCommand::DELAYED_CLOSE_FRONTEND:
1881 eDebugNoSimulate("[SEC] delayed close frontend");
1882 closeFrontend(false, true);
1883 ++m_sec_sequence.current();
1887 eDebugNoSimulate("[SEC] unhandled sec command %d",
1888 ++m_sec_sequence.current()->cmd);
1889 ++m_sec_sequence.current();
1892 m_tuneTimer->start(delay,true);
1896 if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1901 void eDVBFrontend::setFrontend(bool recvEvents)
1905 eDebug("setting frontend %d", m_dvbid);
1908 feEvent(-1); // flush events
1909 #if HAVE_DVB_API_VERSION >= 5
1910 if (m_type == iDVBFrontend::feSatellite)
1912 fe_rolloff_t rolloff = ROLLOFF_35;
1913 fe_pilot_t pilot = PILOT_OFF;
1914 fe_modulation_t modulation = QPSK;
1915 fe_delivery_system_t system = SYS_DVBS;
1916 switch(oparm.sat.system)
1918 case eDVBFrontendParametersSatellite::System_DVB_S: system = SYS_DVBS; break;
1919 case eDVBFrontendParametersSatellite::System_DVB_S2: system = SYS_DVBS2; break;
1921 switch(oparm.sat.modulation)
1923 case eDVBFrontendParametersSatellite::Modulation_QPSK: modulation = QPSK; break;
1924 case eDVBFrontendParametersSatellite::Modulation_8PSK: modulation = PSK_8; break;
1925 case eDVBFrontendParametersSatellite::Modulation_QAM16: modulation = QAM_16; break;
1927 switch(oparm.sat.pilot)
1929 case eDVBFrontendParametersSatellite::Pilot_Off: pilot = PILOT_OFF; break;
1930 case eDVBFrontendParametersSatellite::Pilot_On: pilot = PILOT_ON; break;
1931 case eDVBFrontendParametersSatellite::Pilot_Unknown: pilot = PILOT_AUTO; break;
1933 switch(oparm.sat.rolloff)
1935 case eDVBFrontendParametersSatellite::RollOff_alpha_0_20: rolloff = ROLLOFF_20; break;
1936 case eDVBFrontendParametersSatellite::RollOff_alpha_0_25: rolloff = ROLLOFF_25; break;
1937 case eDVBFrontendParametersSatellite::RollOff_alpha_0_35: rolloff = ROLLOFF_35; break;
1939 struct dtv_property p[10];
1940 struct dtv_properties cmdseq;
1942 p[0].cmd = DTV_CLEAR;
1943 p[1].cmd = DTV_DELIVERY_SYSTEM, p[1].u.data = system;
1944 p[2].cmd = DTV_FREQUENCY, p[2].u.data = parm_frequency;
1945 p[3].cmd = DTV_MODULATION, p[3].u.data = modulation;
1946 p[4].cmd = DTV_SYMBOL_RATE, p[4].u.data = parm_u_qpsk_symbol_rate;
1947 p[5].cmd = DTV_INNER_FEC, p[5].u.data = parm_u_qpsk_fec_inner;
1948 p[6].cmd = DTV_INVERSION, p[6].u.data = parm_inversion;
1949 if (system == SYS_DVBS2)
1951 p[7].cmd = DTV_ROLLOFF, p[7].u.data = rolloff;
1952 p[8].cmd = DTV_PILOT, p[8].u.data = pilot;
1953 p[9].cmd = DTV_TUNE;
1958 p[7].cmd = DTV_TUNE;
1961 if (ioctl(m_fd, FE_SET_PROPERTY, &cmdseq) == -1)
1963 perror("FE_SET_PROPERTY failed");
1970 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1972 perror("FE_SET_FRONTEND failed");
1979 RESULT eDVBFrontend::getFrontendType(int &t)
1987 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1992 eWarning("no SEC module active!");
1995 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1998 #if HAVE_DVB_API_VERSION >= 3
1999 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",
2002 feparm.polarisation,
2006 feparm.orbital_position,
2012 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
2015 feparm.polarisation,
2019 feparm.orbital_position);
2021 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
2022 switch (feparm.inversion)
2024 case eDVBFrontendParametersSatellite::Inversion_On:
2025 parm_inversion = INVERSION_ON;
2027 case eDVBFrontendParametersSatellite::Inversion_Off:
2028 parm_inversion = INVERSION_OFF;
2031 case eDVBFrontendParametersSatellite::Inversion_Unknown:
2032 parm_inversion = INVERSION_AUTO;
2035 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S)
2039 case eDVBFrontendParametersSatellite::FEC_None:
2040 parm_u_qpsk_fec_inner = FEC_NONE;
2042 case eDVBFrontendParametersSatellite::FEC_1_2:
2043 parm_u_qpsk_fec_inner = FEC_1_2;
2045 case eDVBFrontendParametersSatellite::FEC_2_3:
2046 parm_u_qpsk_fec_inner = FEC_2_3;
2048 case eDVBFrontendParametersSatellite::FEC_3_4:
2049 parm_u_qpsk_fec_inner = FEC_3_4;
2051 case eDVBFrontendParametersSatellite::FEC_5_6:
2052 parm_u_qpsk_fec_inner = FEC_5_6;
2054 case eDVBFrontendParametersSatellite::FEC_7_8:
2055 parm_u_qpsk_fec_inner = FEC_7_8;
2058 eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
2059 case eDVBFrontendParametersSatellite::FEC_Auto:
2060 parm_u_qpsk_fec_inner = FEC_AUTO;
2064 #if HAVE_DVB_API_VERSION >= 3
2069 case eDVBFrontendParametersSatellite::FEC_1_2:
2070 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
2072 case eDVBFrontendParametersSatellite::FEC_2_3:
2073 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
2075 case eDVBFrontendParametersSatellite::FEC_3_4:
2076 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
2078 case eDVBFrontendParametersSatellite::FEC_3_5:
2079 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
2081 case eDVBFrontendParametersSatellite::FEC_4_5:
2082 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
2084 case eDVBFrontendParametersSatellite::FEC_5_6:
2085 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
2087 case eDVBFrontendParametersSatellite::FEC_7_8:
2088 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
2090 case eDVBFrontendParametersSatellite::FEC_8_9:
2091 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
2093 case eDVBFrontendParametersSatellite::FEC_9_10:
2094 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
2097 eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
2100 #if HAVE_DVB_API_VERSION < 5
2101 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
2102 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
2103 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation_8PSK)
2105 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
2106 // 8PSK fec driver values are decimal 9 bigger
2111 // FIXME !!! get frequency range from tuner
2112 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
2114 eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
2117 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
2123 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
2125 #if HAVE_DVB_API_VERSION < 3
2126 parm_frequency = feparm.frequency;
2128 parm_frequency = feparm.frequency * 1000;
2130 parm_u_qam_symbol_rate = feparm.symbol_rate;
2131 switch (feparm.modulation)
2133 case eDVBFrontendParametersCable::Modulation_QAM16:
2134 parm_u_qam_modulation = QAM_16;
2136 case eDVBFrontendParametersCable::Modulation_QAM32:
2137 parm_u_qam_modulation = QAM_32;
2139 case eDVBFrontendParametersCable::Modulation_QAM64:
2140 parm_u_qam_modulation = QAM_64;
2142 case eDVBFrontendParametersCable::Modulation_QAM128:
2143 parm_u_qam_modulation = QAM_128;
2145 case eDVBFrontendParametersCable::Modulation_QAM256:
2146 parm_u_qam_modulation = QAM_256;
2149 case eDVBFrontendParametersCable::Modulation_Auto:
2150 parm_u_qam_modulation = QAM_AUTO;
2153 switch (feparm.inversion)
2155 case eDVBFrontendParametersCable::Inversion_On:
2156 parm_inversion = INVERSION_ON;
2158 case eDVBFrontendParametersCable::Inversion_Off:
2159 parm_inversion = INVERSION_OFF;
2162 case eDVBFrontendParametersCable::Inversion_Unknown:
2163 parm_inversion = INVERSION_AUTO;
2166 switch (feparm.fec_inner)
2168 case eDVBFrontendParametersCable::FEC_None:
2169 parm_u_qam_fec_inner = FEC_NONE;
2171 case eDVBFrontendParametersCable::FEC_1_2:
2172 parm_u_qam_fec_inner = FEC_1_2;
2174 case eDVBFrontendParametersCable::FEC_2_3:
2175 parm_u_qam_fec_inner = FEC_2_3;
2177 case eDVBFrontendParametersCable::FEC_3_4:
2178 parm_u_qam_fec_inner = FEC_3_4;
2180 case eDVBFrontendParametersCable::FEC_5_6:
2181 parm_u_qam_fec_inner = FEC_5_6;
2183 case eDVBFrontendParametersCable::FEC_7_8:
2184 parm_u_qam_fec_inner = FEC_7_8;
2186 #if HAVE_DVB_API_VERSION >= 3
2187 case eDVBFrontendParametersCable::FEC_8_9:
2188 parm_u_qam_fec_inner = FEC_8_9;
2192 case eDVBFrontendParametersCable::FEC_Auto:
2193 parm_u_qam_fec_inner = FEC_AUTO;
2196 eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
2197 parm_frequency/1000,
2198 parm_u_qam_symbol_rate,
2199 parm_u_qam_fec_inner,
2200 parm_u_qam_modulation,
2206 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
2208 parm_frequency = feparm.frequency;
2210 switch (feparm.bandwidth)
2212 case eDVBFrontendParametersTerrestrial::Bandwidth_8MHz:
2213 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
2215 case eDVBFrontendParametersTerrestrial::Bandwidth_7MHz:
2216 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
2218 case eDVBFrontendParametersTerrestrial::Bandwidth_6MHz:
2219 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
2222 case eDVBFrontendParametersTerrestrial::Bandwidth_Auto:
2223 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
2226 switch (feparm.code_rate_LP)
2228 case eDVBFrontendParametersTerrestrial::FEC_1_2:
2229 parm_u_ofdm_code_rate_LP = FEC_1_2;
2231 case eDVBFrontendParametersTerrestrial::FEC_2_3:
2232 parm_u_ofdm_code_rate_LP = FEC_2_3;
2234 case eDVBFrontendParametersTerrestrial::FEC_3_4:
2235 parm_u_ofdm_code_rate_LP = FEC_3_4;
2237 case eDVBFrontendParametersTerrestrial::FEC_5_6:
2238 parm_u_ofdm_code_rate_LP = FEC_5_6;
2240 case eDVBFrontendParametersTerrestrial::FEC_7_8:
2241 parm_u_ofdm_code_rate_LP = FEC_7_8;
2244 case eDVBFrontendParametersTerrestrial::FEC_Auto:
2245 parm_u_ofdm_code_rate_LP = FEC_AUTO;
2248 switch (feparm.code_rate_HP)
2250 case eDVBFrontendParametersTerrestrial::FEC_1_2:
2251 parm_u_ofdm_code_rate_HP = FEC_1_2;
2253 case eDVBFrontendParametersTerrestrial::FEC_2_3:
2254 parm_u_ofdm_code_rate_HP = FEC_2_3;
2256 case eDVBFrontendParametersTerrestrial::FEC_3_4:
2257 parm_u_ofdm_code_rate_HP = FEC_3_4;
2259 case eDVBFrontendParametersTerrestrial::FEC_5_6:
2260 parm_u_ofdm_code_rate_HP = FEC_5_6;
2262 case eDVBFrontendParametersTerrestrial::FEC_7_8:
2263 parm_u_ofdm_code_rate_HP = FEC_7_8;
2266 case eDVBFrontendParametersTerrestrial::FEC_Auto:
2267 parm_u_ofdm_code_rate_HP = FEC_AUTO;
2270 switch (feparm.modulation)
2272 case eDVBFrontendParametersTerrestrial::Modulation_QPSK:
2273 parm_u_ofdm_constellation = QPSK;
2275 case eDVBFrontendParametersTerrestrial::Modulation_QAM16:
2276 parm_u_ofdm_constellation = QAM_16;
2278 case eDVBFrontendParametersTerrestrial::Modulation_QAM64:
2279 parm_u_ofdm_constellation = QAM_64;
2282 case eDVBFrontendParametersTerrestrial::Modulation_Auto:
2283 parm_u_ofdm_constellation = QAM_AUTO;
2286 switch (feparm.transmission_mode)
2288 case eDVBFrontendParametersTerrestrial::TransmissionMode_2k:
2289 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2291 case eDVBFrontendParametersTerrestrial::TransmissionMode_8k:
2292 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2295 case eDVBFrontendParametersTerrestrial::TransmissionMode_Auto:
2296 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2299 switch (feparm.guard_interval)
2301 case eDVBFrontendParametersTerrestrial::GuardInterval_1_32:
2302 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2304 case eDVBFrontendParametersTerrestrial::GuardInterval_1_16:
2305 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2307 case eDVBFrontendParametersTerrestrial::GuardInterval_1_8:
2308 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2310 case eDVBFrontendParametersTerrestrial::GuardInterval_1_4:
2311 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2314 case eDVBFrontendParametersTerrestrial::GuardInterval_Auto:
2315 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2318 switch (feparm.hierarchy)
2320 case eDVBFrontendParametersTerrestrial::Hierarchy_None:
2321 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2323 case eDVBFrontendParametersTerrestrial::Hierarchy_1:
2324 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2326 case eDVBFrontendParametersTerrestrial::Hierarchy_2:
2327 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2329 case eDVBFrontendParametersTerrestrial::Hierarchy_4:
2330 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2333 case eDVBFrontendParametersTerrestrial::Hierarchy_Auto:
2334 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2337 switch (feparm.inversion)
2339 case eDVBFrontendParametersTerrestrial::Inversion_On:
2340 parm_inversion = INVERSION_ON;
2342 case eDVBFrontendParametersTerrestrial::Inversion_Off:
2343 parm_inversion = INVERSION_OFF;
2346 case eDVBFrontendParametersTerrestrial::Inversion_Unknown:
2347 parm_inversion = INVERSION_AUTO;
2354 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2356 unsigned int timeout = 5000;
2357 eDebugNoSimulate("(%d)tune", m_dvbid);
2363 if (!m_sn && !m_simulate)
2365 eDebug("no frontend device opened... do not try to tune !!!");
2379 m_sec_sequence.clear();
2381 where.calcLockTimeout(timeout);
2387 eDVBFrontendParametersSatellite feparm;
2388 if (where.getDVBS(feparm))
2390 eDebug("no dvbs data!");
2394 if (m_rotor_mode != feparm.no_rotor_command_on_tune && !feparm.no_rotor_command_on_tune)
2396 eDVBFrontend *sec_fe = this;
2397 long tmp = m_data[LINKED_PREV_PTR];
2400 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
2401 sec_fe = linked_fe->m_frontend;
2402 sec_fe->getData(LINKED_NEXT_PTR, tmp);
2404 eDebug("(fe%d) reset diseqc after leave rotor mode!", m_dvbid);
2405 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
2407 m_rotor_mode = feparm.no_rotor_command_on_tune;
2409 m_sec->setRotorMoving(m_slotid, false);
2410 res=prepare_sat(feparm, timeout);
2418 eDVBFrontendParametersCable feparm;
2419 if (where.getDVBC(feparm))
2424 res=prepare_cable(feparm);
2428 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2429 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2434 eDVBFrontendParametersTerrestrial feparm;
2435 if (where.getDVBT(feparm))
2437 eDebug("no -T data");
2441 res=prepare_terrestrial(feparm);
2445 std::string enable_5V;
2446 char configStr[255];
2447 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2448 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2449 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2450 if (enable_5V == "True")
2451 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2453 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2454 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2460 m_sec_sequence.current() = m_sec_sequence.begin();
2464 m_tuneTimer->start(0,true);
2466 if (m_state != stateTuning)
2468 m_state = stateTuning;
2469 m_stateChanged(this);
2478 m_tuneTimer->stop();
2482 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2484 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2488 RESULT eDVBFrontend::setVoltage(int voltage)
2490 if (m_type == feCable)
2492 #if HAVE_DVB_API_VERSION < 3
2495 bool increased=false;
2496 fe_sec_voltage_t vlt;
2498 m_data[CUR_VOLTAGE]=voltage;
2502 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2503 vlt = SEC_VOLTAGE_OFF;
2506 #if HAVE_DVB_API_VERSION < 3
2507 vlt = SEC_VOLTAGE_13_5;
2513 vlt = SEC_VOLTAGE_13;
2516 #if HAVE_DVB_API_VERSION < 3
2517 vlt = SEC_VOLTAGE_18_5;
2523 vlt = SEC_VOLTAGE_18;
2530 #if HAVE_DVB_API_VERSION < 3
2531 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2533 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2534 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2535 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2539 RESULT eDVBFrontend::getState(int &state)
2545 RESULT eDVBFrontend::setTone(int t)
2547 if (m_type != feSatellite)
2549 #if HAVE_DVB_API_VERSION < 3
2552 fe_sec_tone_mode_t tone;
2561 tone = SEC_TONE_OFF;
2568 #if HAVE_DVB_API_VERSION < 3
2569 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2571 return ::ioctl(m_fd, FE_SET_TONE, tone);
2575 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2576 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2579 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2583 #if HAVE_DVB_API_VERSION < 3
2584 struct secCommand cmd;
2585 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2586 cmd.u.diseqc.cmdtype = diseqc.data[0];
2587 cmd.u.diseqc.addr = diseqc.data[1];
2588 cmd.u.diseqc.cmd = diseqc.data[2];
2589 cmd.u.diseqc.numParams = diseqc.len-3;
2590 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2591 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2593 struct dvb_diseqc_master_cmd cmd;
2594 memcpy(cmd.msg, diseqc.data, diseqc.len);
2595 cmd.msg_len = diseqc.len;
2596 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2602 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2603 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2605 RESULT eDVBFrontend::sendToneburst(int burst)
2609 #if HAVE_DVB_API_VERSION < 3
2610 secMiniCmd cmd = SEC_MINI_NONE;
2612 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2614 if ( burst == eDVBSatelliteDiseqcParameters::A )
2616 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2618 #if HAVE_DVB_API_VERSION < 3
2619 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2622 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2628 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2634 RESULT eDVBFrontend::setSecSequence(eSecCommandList &list)
2636 if (m_data[SATCR] != -1 && m_sec_sequence.current() != m_sec_sequence.end())
2637 m_sec_sequence.push_back(list);
2639 m_sec_sequence = list;
2643 RESULT eDVBFrontend::getData(int num, long &data)
2645 if ( num < NUM_DATA_ENTRIES )
2653 RESULT eDVBFrontend::setData(int num, long val)
2655 if ( num < NUM_DATA_ENTRIES )
2663 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2666 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2668 if (m_type == eDVBFrontend::feSatellite)
2671 eDVBFrontendParametersSatellite sat_parm;
2672 int ret = feparm->getDVBS(sat_parm);
2674 if (sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S2 && !m_can_handle_dvbs2)
2676 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2677 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S && m_can_handle_dvbs2)
2681 else if (m_type == eDVBFrontend::feCable)
2682 return 2; // more prio for cable frontends
2683 else if (m_type == eDVBFrontend::feTerrestrial)
2688 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2690 ePyObject Id, Descr, Enabled, IsDVBS2;
2691 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4)
2693 Id = PyTuple_GET_ITEM(obj, 0);
2694 Descr = PyTuple_GET_ITEM(obj, 1);
2695 Enabled = PyTuple_GET_ITEM(obj, 2);
2696 IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2697 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2))
2699 strcpy(m_description, PyString_AS_STRING(Descr));
2700 m_slotid = PyInt_AsLong(Id);
2701 m_enabled = Enabled == Py_True;
2702 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2703 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2704 !!strstr(m_description, "Alps BSBE2") ||
2705 !!strstr(m_description, "Alps -S") ||
2706 !!strstr(m_description, "BCM4501");
2707 m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2708 eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2709 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2712 PyErr_SetString(PyExc_StandardError,
2713 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");