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, eDVBFrontend *simulate_fe)
457 :m_simulate(simulate), m_enabled(false), m_type(-1), m_simulate_fe(simulate_fe), 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;
508 eDebug("opening frontend %d", m_dvbid);
511 m_fd = ::open(m_filename, O_RDWR|O_NONBLOCK);
514 eWarning("failed! (%s) %m", m_filename);
519 eWarning("frontend %d already opened", m_dvbid);
522 if (::ioctl(m_fd, FE_GET_INFO, &fe_info) < 0)
524 eWarning("ioctl FE_GET_INFO failed");
530 switch (fe_info.type)
533 m_type = iDVBFrontend::feSatellite;
536 m_type = iDVBFrontend::feCable;
539 m_type = iDVBFrontend::feTerrestrial;
542 eWarning("unknown frontend type.");
548 m_simulate_fe->m_type = m_type;
549 eDebugNoSimulate("detected %s frontend", "satellite\0cable\0 terrestrial"+fe_info.type*10);
552 #if HAVE_DVB_API_VERSION < 3
553 if (m_type == iDVBFrontend::feSatellite)
559 m_secfd = ::open(m_sec_filename, O_RDWR);
562 eWarning("failed! (%s) %m", m_sec_filename);
570 eWarning("sec %d already opened", m_dvbid);
574 m_sn = eSocketNotifier::create(eApp, m_fd, eSocketNotifier::Read, false);
575 CONNECT(m_sn->activated, eDVBFrontend::feEvent);
578 setTone(iDVBFrontend::toneOff);
579 setVoltage(iDVBFrontend::voltageOff);
584 int eDVBFrontend::closeFrontend(bool force, bool no_delayed)
586 if (!force && m_data[CUR_VOLTAGE] != -1 && m_data[CUR_VOLTAGE] != iDVBFrontend::voltageOff)
588 long tmp = m_data[LINKED_NEXT_PTR];
591 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
592 if (linked_fe->m_inuse)
594 eDebugNoSimulate("dont close frontend %d until the linked frontend %d in slot %d is still in use",
595 m_dvbid, linked_fe->m_frontend->getDVBID(), linked_fe->m_frontend->getSlotID());
598 linked_fe->m_frontend->getData(LINKED_NEXT_PTR, tmp);
604 eDebugNoSimulate("close frontend %d", m_dvbid);
605 if (m_data[SATCR] != -1)
609 m_sec->prepareTurnOffSatCR(*this, m_data[SATCR]);
610 m_tuneTimer->start(0, true);
611 if(!m_tuneTimer->isActive())
614 eDebug("[turnOffSatCR] no mainloop");
617 timeout = tuneLoopInt();
620 usleep(timeout*1000); // blockierendes wait.. eTimer gibts ja nicht mehr
624 eDebug("[turnOffSatCR] running mainloop");
628 m_data[ROTOR_CMD] = -1;
631 setTone(iDVBFrontend::toneOff);
632 setVoltage(iDVBFrontend::voltageOff);
635 if (m_sec && !m_simulate)
636 m_sec->setRotorMoving(m_slotid, false);
640 eWarning("couldnt close frontend %d", m_dvbid);
644 setTone(iDVBFrontend::toneOff);
645 setVoltage(iDVBFrontend::voltageOff);
647 #if HAVE_DVB_API_VERSION < 3
650 if (!::close(m_secfd))
653 eWarning("couldnt close sec %d", m_dvbid);
657 m_state = stateClosed;
662 eDVBFrontend::~eDVBFrontend()
664 m_data[LINKED_PREV_PTR] = m_data[LINKED_NEXT_PTR] = -1;
668 void eDVBFrontend::feEvent(int w)
670 eDVBFrontend *sec_fe = this;
671 long tmp = m_data[LINKED_PREV_PTR];
674 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
675 sec_fe = linked_fe->m_frontend;
676 sec_fe->getData(LINKED_NEXT_PTR, tmp);
680 #if HAVE_DVB_API_VERSION < 3
683 dvb_frontend_event event;
687 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
689 if (res && (errno == EAGAIN))
695 #if HAVE_DVB_API_VERSION < 3
696 if (event.type == FE_COMPLETION_EV)
698 eDebug("(%d)fe event: status %x, inversion %s, m_tuning %d", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off", m_tuning);
699 if (event.status & FE_HAS_LOCK)
707 #if HAVE_DVB_API_VERSION >= 3
708 if (event.status & FE_TIMEDOUT) {
709 eDebug("FE_TIMEDOUT! ..abort");
722 eDebug("stateLostLock");
723 state = stateLostLock;
725 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
728 if (m_state != state)
731 m_stateChanged(this);
736 void eDVBFrontend::timeout()
739 if (m_state == stateTuning)
741 m_state = stateFailed;
742 m_stateChanged(this);
746 #define INRANGE(X,Y,Z) (((X<=Y) && (Y<=Z))||((Z<=Y) && (Y<=X)) ? 1 : 0)
748 /* unsigned 32 bit division */
749 static inline uint32_t fe_udiv(uint32_t a, uint32_t b)
751 return (a + b / 2) / b;
754 int eDVBFrontend::readFrontendData(int type)
763 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
764 eDebug("FE_READ_BER failed (%m)");
769 case signalQualitydB: /* this will move into the driver */
771 int sat_max = 1600; // for stv0288 / bsbe2
772 int ret = 0x12345678;
776 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
777 eDebug("FE_READ_SNR failed (%m)");
778 else if (!strcmp(m_description, "BCM4501 (internal)"))
780 float SDS_SNRE = snr << 16;
783 if (oparm.sat.system == eDVBFrontendParametersSatellite::System_DVB_S) // DVB-S1 / QPSK
785 static float SNR_COEFF[6] = {
788 197418.0 / 4194304.0,
789 -2602183.0 / 4194304.0,
790 20377212.0 / 4194304.0,
791 -37791203.0 / 4194304.0,
793 float fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0)),
794 fval2 = pow(10.0, fval1)-1;
795 fval1 = 10.0 * log10(fval2);
799 fval2 = SNR_COEFF[0];
800 for (int i=1; i<6; ++i)
803 fval2 += SNR_COEFF[i];
809 #if HAVE_DVB_API_VERSION >= 3
812 float fval1 = SDS_SNRE / 268435456.0,
815 if (oparm.sat.modulation == eDVBFrontendParametersSatellite::Modulation_QPSK)
826 fval4 = -10.0 * log10(fval1);
828 for (int i=0; i < 5; ++i)
829 fval1 = fval4 - fval2 * log10(1.0+pow(10.0, (fval3-fval1)/fval2));
834 ret = (int)(snr_in_db * 100);
836 else if (strstr(m_description, "Alps BSBE1 C01A") ||
837 strstr(m_description, "Alps -S(STV0288)"))
841 else if (snr == 0xFFFF) // i think this should not happen
845 enum { REALVAL, REGVAL };
846 const long CN_lookup[31][2] = {
847 {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
848 {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
849 {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
850 {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
851 {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
852 {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
855 int add=strchr(m_description, '.') ? 0xA250 : 0xA100;
856 long regval = 0xFFFF - ((snr / 3) + add), // revert some dvb api calulations to get the real register value
860 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
865 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[i][REGVAL]))
870 ret = (((regval - CN_lookup[Imin][REGVAL])
871 * (CN_lookup[Imax][REALVAL] - CN_lookup[Imin][REALVAL])
872 / (CN_lookup[Imax][REGVAL] - CN_lookup[Imin][REGVAL]))
873 + CN_lookup[Imin][REALVAL]) * 10;
879 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
880 !strcmp(m_description, "Alps -S") ||
881 !strcmp(m_description, "Philips -S") ||
882 !strcmp(m_description, "LG -S") )
885 ret = (int)((snr-39075)/17.647);
886 } else if (!strcmp(m_description, "Alps BSBE2"))
888 ret = (int)((snr >> 7) * 10);
889 } else if (!strcmp(m_description, "Philips CU1216Mk3"))
891 int mse = (~snr) & 0xFF;
892 switch (parm_u_qam_modulation) {
893 case QAM_16: ret = fe_udiv(1950000, (32 * mse) + 138) + 1000; break;
894 case QAM_32: ret = fe_udiv(2150000, (40 * mse) + 500) + 1350; break;
895 case QAM_64: ret = fe_udiv(2100000, (40 * mse) + 500) + 1250; break;
896 case QAM_128: ret = fe_udiv(1850000, (38 * mse) + 400) + 1380; break;
897 case QAM_256: ret = fe_udiv(1800000, (100 * mse) + 40) + 2030; break;
900 } else if (!strcmp(m_description, "Philips TU1216"))
902 snr = 0xFF - (snr & 0xFF);
904 ret = 10 * (int)(-100 * (log10(snr) - log10(255)));
906 else if (strstr(m_description, "BCM4506") || strstr(m_description, "BCM4505"))
907 ret = (snr * 100) >> 8;
908 else if (!strcmp(m_description, "CXD1981"))
910 int mse = (~snr) & 0xFF;
911 switch (parm_u_qam_modulation) {
914 case QAM_256: ret = (int)(-950 * log(((double)mse) / 760)); break;
916 case QAM_128: ret = (int)(-875 * log(((double)mse) / 650)); break;
922 if (type == signalQuality)
924 if (ret == 0x12345678) // no snr db calculation avail.. return untouched snr value..
929 return ret >= sat_max ? 65536 : ret * 65536 / sat_max;
930 case feCable: // we assume a max of 42db here
931 return ret >= 4200 ? 65536 : ret * 65536 / 4200;
932 case feTerrestrial: // we assume a max of 24db here
933 return ret >= 2400 ? 65536 : ret * 65536 / 2400;
937 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
945 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
946 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
952 #if HAVE_DVB_API_VERSION < 3
953 FrontendStatus status=0;
959 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
960 eDebug("FE_READ_STATUS failed (%m)");
961 return !!(status&FE_HAS_LOCK);
967 #if HAVE_DVB_API_VERSION < 3
968 FrontendStatus status=0;
974 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
975 eDebug("FE_READ_STATUS failed (%m)");
976 return !!(status&FE_HAS_SYNC);
986 void PutToDict(ePyObject &dict, const char*key, long value)
988 ePyObject item = PyInt_FromLong(value);
991 if (PyDict_SetItemString(dict, key, item))
992 eDebug("put %s to dict failed", key);
996 eDebug("could not create PyObject for %s", key);
999 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
1003 if (PyDict_SetItemString(dict, key, item))
1004 eDebug("put %s to dict failed", key);
1008 eDebug("invalid PyObject for %s", key);
1011 void PutToDict(ePyObject &dict, const char*key, const char *value)
1013 ePyObject item = PyString_FromString(value);
1016 if (PyDict_SetItemString(dict, key, item))
1017 eDebug("put %s to dict failed", key);
1021 eDebug("could not create PyObject for %s", key);
1024 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
1026 PutToDict(dict, "tuner_type", "DVB-S");
1027 PutToDict(dict, "frequency", feparm.frequency);
1028 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
1029 PutToDict(dict, "orbital_position", feparm.orbital_position);
1030 PutToDict(dict, "inversion", feparm.inversion);
1031 PutToDict(dict, "fec_inner", feparm.fec);
1032 PutToDict(dict, "modulation", feparm.modulation);
1033 PutToDict(dict, "polarization", feparm.polarisation);
1034 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S2)
1036 PutToDict(dict, "rolloff", feparm.rolloff);
1037 PutToDict(dict, "pilot", feparm.pilot);
1039 PutToDict(dict, "system", feparm.system);
1042 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
1044 PutToDict(dict, "tuner_type", "DVB-T");
1045 PutToDict(dict, "frequency", feparm.frequency);
1046 PutToDict(dict, "bandwidth", feparm.bandwidth);
1047 PutToDict(dict, "code_rate_lp", feparm.code_rate_LP);
1048 PutToDict(dict, "code_rate_hp", feparm.code_rate_HP);
1049 PutToDict(dict, "constellation", feparm.modulation);
1050 PutToDict(dict, "transmission_mode", feparm.transmission_mode);
1051 PutToDict(dict, "guard_interval", feparm.guard_interval);
1052 PutToDict(dict, "hierarchy_information", feparm.hierarchy);
1053 PutToDict(dict, "inversion", feparm.inversion);
1056 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
1058 PutToDict(dict, "tuner_type", "DVB-C");
1059 PutToDict(dict, "frequency", feparm.frequency);
1060 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
1061 PutToDict(dict, "modulation", feparm.modulation);
1062 PutToDict(dict, "inversion", feparm.inversion);
1063 PutToDict(dict, "fec_inner", feparm.fec_inner);
1066 #if HAVE_DVB_API_VERSION >= 5
1067 static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, struct dtv_property *p, long freq_offset, int orb_pos, int polarization)
1070 int frequency = parm_frequency + freq_offset;
1071 PutToDict(dict, "frequency", frequency);
1072 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
1073 PutToDict(dict, "orbital_position", orb_pos);
1074 PutToDict(dict, "polarization", polarization);
1076 switch(parm_u_qpsk_fec_inner)
1078 case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1079 case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1080 case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1081 case FEC_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
1082 case FEC_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
1083 case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1084 case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1085 case FEC_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
1086 case FEC_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1087 case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
1088 case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
1089 default: eDebug("got unsupported FEC from frontend! report as FEC_AUTO!\n");
1091 PutToDict(dict, "fec_inner", tmp);
1093 switch (p[0].u.data)
1095 default: eDebug("got unsupported system from frontend! report as DVBS!");
1096 case SYS_DVBS: tmp = eDVBFrontendParametersSatellite::System_DVB_S; break;
1099 switch (p[2].u.data)
1101 default: eDebug("got unsupported rolloff from frontend! report as 0_20!");
1102 case ROLLOFF_20: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1103 case ROLLOFF_25: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1104 case ROLLOFF_35: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1106 PutToDict(dict, "rolloff", tmp);
1108 switch (p[3].u.data)
1110 case PILOT_OFF: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1111 case PILOT_ON: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1112 case PILOT_AUTO: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1114 PutToDict(dict, "pilot", tmp);
1116 tmp = eDVBFrontendParametersSatellite::System_DVB_S2; break;
1119 PutToDict(dict, "system", tmp);
1121 switch (p[1].u.data)
1123 default: eDebug("got unsupported modulation from frontend! report as QPSK!");
1124 case QPSK: tmp = eDVBFrontendParametersSatellite::Modulation_QPSK; break;
1125 case PSK_8: tmp = eDVBFrontendParametersSatellite::Modulation_8PSK; break;
1127 PutToDict(dict, "modulation", tmp);
1131 static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, long freq_offset, int orb_pos, int polarization)
1134 int frequency = parm_frequency + freq_offset;
1135 PutToDict(dict, "frequency", frequency);
1136 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
1137 PutToDict(dict, "orbital_position", orb_pos);
1138 PutToDict(dict, "polarization", polarization);
1140 switch((int)parm_u_qpsk_fec_inner)
1142 case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1143 case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1144 case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1145 case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1146 case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1147 case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
1149 case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
1150 #if HAVE_DVB_API_VERSION >=3
1151 case FEC_S2_8PSK_1_2:
1152 case FEC_S2_QPSK_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1153 case FEC_S2_8PSK_2_3:
1154 case FEC_S2_QPSK_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1155 case FEC_S2_8PSK_3_4:
1156 case FEC_S2_QPSK_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1157 case FEC_S2_8PSK_5_6:
1158 case FEC_S2_QPSK_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1159 case FEC_S2_8PSK_7_8:
1160 case FEC_S2_QPSK_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1161 case FEC_S2_8PSK_8_9:
1162 case FEC_S2_QPSK_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
1163 case FEC_S2_8PSK_3_5:
1164 case FEC_S2_QPSK_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
1165 case FEC_S2_8PSK_4_5:
1166 case FEC_S2_QPSK_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
1167 case FEC_S2_8PSK_9_10:
1168 case FEC_S2_QPSK_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1171 PutToDict(dict, "fec_inner", tmp);
1172 #if HAVE_DVB_API_VERSION >=3
1173 PutToDict(dict, "modulation",
1174 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ?
1175 eDVBFrontendParametersSatellite::Modulation_8PSK :
1176 eDVBFrontendParametersSatellite::Modulation_QPSK );
1177 if (parm_u_qpsk_fec_inner > FEC_AUTO)
1179 switch(parm_inversion & 0xc)
1181 default: // unknown rolloff
1182 case 0: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1183 case 4: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1184 case 8: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1186 PutToDict(dict, "rolloff", tmp);
1187 switch(parm_inversion & 0x30)
1189 case 0: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1190 case 0x10: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1191 case 0x20: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1193 PutToDict(dict, "pilot", tmp);
1194 tmp = eDVBFrontendParametersSatellite::System_DVB_S2;
1197 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1199 PutToDict(dict, "modulation", eDVBFrontendParametersSatellite::Modulation_QPSK );
1200 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1202 PutToDict(dict, "system", tmp);
1206 static void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1209 #if HAVE_DVB_API_VERSION < 3
1210 PutToDict(dict, "frequency", parm_frequency);
1212 PutToDict(dict, "frequency", parm_frequency/1000);
1214 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1215 switch(parm_u_qam_fec_inner)
1217 case FEC_NONE: tmp = eDVBFrontendParametersCable::FEC_None; break;
1218 case FEC_1_2: tmp = eDVBFrontendParametersCable::FEC_1_2; break;
1219 case FEC_2_3: tmp = eDVBFrontendParametersCable::FEC_2_3; break;
1220 case FEC_3_4: tmp = eDVBFrontendParametersCable::FEC_3_4; break;
1221 case FEC_5_6: tmp = eDVBFrontendParametersCable::FEC_5_6; break;
1222 case FEC_7_8: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1223 #if HAVE_DVB_API_VERSION >= 3
1224 case FEC_8_9: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1227 case FEC_AUTO: tmp = eDVBFrontendParametersCable::FEC_Auto; break;
1229 PutToDict(dict, "fec_inner", tmp);
1230 switch(parm_u_qam_modulation)
1232 case QAM_16: tmp = eDVBFrontendParametersCable::Modulation_QAM16; break;
1233 case QAM_32: tmp = eDVBFrontendParametersCable::Modulation_QAM32; break;
1234 case QAM_64: tmp = eDVBFrontendParametersCable::Modulation_QAM64; break;
1235 case QAM_128: tmp = eDVBFrontendParametersCable::Modulation_QAM128; break;
1236 case QAM_256: tmp = eDVBFrontendParametersCable::Modulation_QAM256; break;
1238 case QAM_AUTO: tmp = eDVBFrontendParametersCable::Modulation_Auto; break;
1240 PutToDict(dict, "modulation", tmp);
1243 static void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1246 PutToDict(dict, "frequency", parm_frequency);
1247 switch (parm_u_ofdm_bandwidth)
1249 case BANDWIDTH_8_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_8MHz; break;
1250 case BANDWIDTH_7_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_7MHz; break;
1251 case BANDWIDTH_6_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_6MHz; break;
1253 case BANDWIDTH_AUTO: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_Auto; break;
1255 PutToDict(dict, "bandwidth", tmp);
1256 switch (parm_u_ofdm_code_rate_LP)
1258 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1259 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1260 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1261 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1262 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1264 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1266 PutToDict(dict, "code_rate_lp", tmp);
1267 switch (parm_u_ofdm_code_rate_HP)
1269 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1270 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1271 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1272 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1273 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1275 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1277 PutToDict(dict, "code_rate_hp", tmp);
1278 switch (parm_u_ofdm_constellation)
1280 case QPSK: tmp = eDVBFrontendParametersTerrestrial::Modulation_QPSK; break;
1281 case QAM_16: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM16; break;
1282 case QAM_64: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM64; break;
1284 case QAM_AUTO: tmp = eDVBFrontendParametersTerrestrial::Modulation_Auto; break;
1286 PutToDict(dict, "constellation", tmp);
1287 switch (parm_u_ofdm_transmission_mode)
1289 case TRANSMISSION_MODE_2K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_2k; break;
1290 case TRANSMISSION_MODE_8K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_8k; break;
1292 case TRANSMISSION_MODE_AUTO: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto; break;
1294 PutToDict(dict, "transmission_mode", tmp);
1295 switch (parm_u_ofdm_guard_interval)
1297 case GUARD_INTERVAL_1_32: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_32; break;
1298 case GUARD_INTERVAL_1_16: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_16; break;
1299 case GUARD_INTERVAL_1_8: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_8; break;
1300 case GUARD_INTERVAL_1_4: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_4; break;
1302 case GUARD_INTERVAL_AUTO: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_Auto; break;
1304 PutToDict(dict, "guard_interval", tmp);
1305 switch (parm_u_ofdm_hierarchy_information)
1307 case HIERARCHY_NONE: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_None; break;
1308 case HIERARCHY_1: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_1; break;
1309 case HIERARCHY_2: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_2; break;
1310 case HIERARCHY_4: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_4; break;
1312 case HIERARCHY_AUTO: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_Auto; break;
1314 PutToDict(dict, "hierarchy_information", tmp);
1317 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1319 if (dest && PyDict_Check(dest))
1321 const char *tmp = "UNKNOWN";
1342 PutToDict(dest, "tuner_state", tmp);
1343 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1344 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1345 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1346 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1347 int sigQualitydB = readFrontendData(signalQualitydB);
1348 if (sigQualitydB == 0x12345678) // not support yet
1350 ePyObject obj=Py_None;
1352 PutToDict(dest, "tuner_signal_quality_db", obj);
1355 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1356 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1360 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1362 if (dest && PyDict_Check(dest))
1364 FRONTENDPARAMETERS front;
1365 #if HAVE_DVB_API_VERSION >= 5
1366 struct dtv_property p[4];
1367 struct dtv_properties cmdseq;
1370 p[0].cmd = DTV_DELIVERY_SYSTEM;
1371 p[1].cmd = DTV_MODULATION;
1372 p[2].cmd = DTV_ROLLOFF;
1373 p[3].cmd = DTV_PILOT;
1375 if (m_simulate || m_fd == -1 || original)
1377 #if HAVE_DVB_API_VERSION >= 5
1378 else if (m_type == feSatellite && // yet just use new api for DVB-S(2) only
1379 ioctl(m_fd, FE_GET_PROPERTY, &cmdseq)<0)
1381 eDebug("FE_GET_PROPERTY failed (%m)");
1385 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1387 eDebug("FE_GET_FRONTEND failed (%m)");
1395 PutSatelliteDataToDict(dest, oparm.sat);
1398 PutCableDataToDict(dest, oparm.cab);
1401 PutTerrestrialDataToDict(dest, oparm.ter);
1407 FRONTENDPARAMETERS &parm = front;
1408 long tmp = eDVBFrontendParametersSatellite::Inversion_Unknown;
1409 switch(parm_inversion & 3)
1412 tmp = eDVBFrontendParametersSatellite::Inversion_On;
1415 tmp = eDVBFrontendParametersSatellite::Inversion_Off;
1419 PutToDict(dest, "inversion", tmp);
1423 #if HAVE_DVB_API_VERSION >= 5
1424 fillDictWithSatelliteData(dest, parm, p, m_data[FREQ_OFFSET], oparm.sat.orbital_position, oparm.sat.polarisation);
1426 fillDictWithSatelliteData(dest, parm, m_data[FREQ_OFFSET], oparm.sat.orbital_position, oparm.sat.polarisation);
1430 fillDictWithCableData(dest, parm);
1433 fillDictWithTerrestrialData(dest, parm);
1440 void eDVBFrontend::getFrontendData(ePyObject dest)
1442 if (dest && PyDict_Check(dest))
1445 PutToDict(dest, "tuner_number", m_slotid);
1461 PutToDict(dest, "tuner_type", tmp);
1465 #ifndef FP_IOCTL_GET_ID
1466 #define FP_IOCTL_GET_ID 0
1468 int eDVBFrontend::readInputpower()
1472 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1474 char proc_name2[64];
1475 sprintf(proc_name, "/proc/stb/frontend/%d/lnb_sense", m_slotid);
1476 sprintf(proc_name2, "/proc/stb/fp/lnb_sense%d", m_slotid);
1478 if ((f=fopen(proc_name, "r")) || (f=fopen(proc_name2, "r")))
1480 if (fscanf(f, "%d", &power) != 1)
1481 eDebug("read %s failed!! (%m)", proc_name);
1483 eDebug("%s is %d\n", proc_name, power);
1488 // open front prozessor
1489 int fp=::open("/dev/dbox/fp0", O_RDWR);
1492 eDebug("couldn't open fp");
1495 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1496 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1498 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1507 bool eDVBFrontend::setSecSequencePos(int steps)
1509 eDebugNoSimulate("set sequence pos %d", steps);
1514 if (m_sec_sequence.current() != m_sec_sequence.end())
1515 ++m_sec_sequence.current();
1520 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1521 --m_sec_sequence.current();
1527 void eDVBFrontend::tuneLoop()
1532 int eDVBFrontend::tuneLoopInt() // called by m_tuneTimer
1535 eDVBFrontend *sec_fe = this;
1536 eDVBRegisteredFrontend *regFE = 0;
1537 long tmp = m_data[LINKED_PREV_PTR];
1540 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1541 sec_fe = prev->m_frontend;
1542 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1543 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1544 int state = sec_fe->m_state;
1545 // workaround to put the kernel frontend thread into idle state!
1546 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1548 sec_fe->closeFrontend(true);
1549 state = sec_fe->m_state;
1551 // sec_fe is closed... we must reopen it here..
1552 if (state == stateClosed)
1560 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1562 long *sec_fe_data = sec_fe->m_data;
1563 // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1565 switch (m_sec_sequence.current()->cmd)
1567 case eSecCommand::SLEEP:
1568 delay = m_sec_sequence.current()++->msec;
1569 eDebugNoSimulate("[SEC] sleep %dms", delay);
1571 case eSecCommand::GOTO:
1572 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1573 ++m_sec_sequence.current();
1575 case eSecCommand::SET_VOLTAGE:
1577 int voltage = m_sec_sequence.current()++->voltage;
1578 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1579 sec_fe->setVoltage(voltage);
1582 case eSecCommand::IF_VOLTAGE_GOTO:
1584 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1585 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1587 ++m_sec_sequence.current();
1590 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1592 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1593 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1595 ++m_sec_sequence.current();
1598 case eSecCommand::IF_TONE_GOTO:
1600 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1601 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1603 ++m_sec_sequence.current();
1606 case eSecCommand::IF_NOT_TONE_GOTO:
1608 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1609 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1611 ++m_sec_sequence.current();
1614 case eSecCommand::SET_TONE:
1615 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1616 sec_fe->setTone(m_sec_sequence.current()++->tone);
1618 case eSecCommand::SEND_DISEQC:
1619 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1620 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1621 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1622 eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1623 if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
1624 eDebugNoSimulate("(DiSEqC reset)");
1625 else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
1626 eDebugNoSimulate("(DiSEqC peripherial power on)");
1628 eDebugNoSimulate("");
1629 ++m_sec_sequence.current();
1631 case eSecCommand::SEND_TONEBURST:
1632 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1633 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1635 case eSecCommand::SET_FRONTEND:
1637 int enableEvents = (m_sec_sequence.current()++)->val;
1638 eDebugNoSimulate("[SEC] setFrontend %d", enableEvents);
1639 setFrontend(enableEvents);
1642 case eSecCommand::START_TUNE_TIMEOUT:
1644 int tuneTimeout = m_sec_sequence.current()->timeout;
1645 eDebugNoSimulate("[SEC] startTuneTimeout %d", tuneTimeout);
1647 m_timeout->start(tuneTimeout, 1);
1648 ++m_sec_sequence.current();
1651 case eSecCommand::SET_TIMEOUT:
1652 m_timeoutCount = m_sec_sequence.current()++->val;
1653 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1655 case eSecCommand::IF_TIMEOUT_GOTO:
1656 if (!m_timeoutCount)
1658 eDebugNoSimulate("[SEC] rotor timout");
1659 setSecSequencePos(m_sec_sequence.current()->steps);
1662 ++m_sec_sequence.current();
1664 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1666 int idx = m_sec_sequence.current()++->val;
1667 if ( idx == 0 || idx == 1 )
1669 m_idleInputpower[idx] = sec_fe->readInputpower();
1670 eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1673 eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1676 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1678 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1679 int idx = compare.val;
1680 if ( !m_simulate && (idx == 0 || idx == 1) )
1682 int idle = sec_fe->readInputpower();
1683 int diff = abs(idle-m_idleInputpower[idx]);
1686 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1687 setSecSequencePos(compare.steps);
1691 ++m_sec_sequence.current();
1694 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1696 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1699 setSecSequencePos(cmd.steps);
1703 int isLocked = readFrontendData(locked);
1704 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1706 if (!m_timeoutCount && m_retryCount > 0)
1708 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 40) || !cmd.lastSignal))
1711 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1714 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1716 cmd.lastSignal = signal;
1719 if (cmd.okcount > 4)
1721 eDebugNoSimulate("ok > 4 .. goto %d\n", cmd.steps);
1722 setSecSequencePos(cmd.steps);
1723 m_state = stateLock;
1724 m_stateChanged(this);
1725 feEvent(-1); // flush events
1733 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1735 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1739 ++m_sec_sequence.current();
1742 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1743 m_runningInputpower = sec_fe->readInputpower();
1744 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1745 ++m_sec_sequence.current();
1747 case eSecCommand::SET_ROTOR_MOVING:
1749 m_sec->setRotorMoving(m_slotid, true);
1750 ++m_sec_sequence.current();
1752 case eSecCommand::SET_ROTOR_STOPPED:
1754 m_sec->setRotorMoving(m_slotid, false);
1755 ++m_sec_sequence.current();
1757 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1759 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1762 setSecSequencePos(cmd.steps);
1765 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1766 const char *txt = cmd.direction ? "running" : "stopped";
1768 if (!m_timeoutCount && m_retryCount > 0)
1770 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1772 m_runningInputpower,
1775 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1776 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1779 eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1780 if ( cmd.okcount > 6 )
1782 eDebugNoSimulate("[SEC] rotor is %s", txt);
1783 if (setSecSequencePos(cmd.steps))
1789 eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1792 ++m_sec_sequence.current();
1795 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1796 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1797 setSecSequencePos(m_sec_sequence.current()->steps);
1799 ++m_sec_sequence.current();
1801 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1802 eDebugNoSimulate("[SEC] invalidate current switch params");
1803 sec_fe_data[CSW] = -1;
1804 sec_fe_data[UCSW] = -1;
1805 sec_fe_data[TONEBURST] = -1;
1806 ++m_sec_sequence.current();
1808 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1809 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1810 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1811 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1812 eDebugNoSimulate("[SEC] update current switch params");
1813 ++m_sec_sequence.current();
1815 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1816 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1817 sec_fe_data[ROTOR_CMD] = -1;
1818 sec_fe_data[ROTOR_POS] = -1;
1819 ++m_sec_sequence.current();
1821 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1822 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1823 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1824 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1825 ++m_sec_sequence.current();
1827 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1828 m_retryCount = m_sec_sequence.current()++->val;
1829 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1831 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1834 eDebugNoSimulate("[SEC] no more rotor retrys");
1835 setSecSequencePos(m_sec_sequence.current()->steps);
1838 ++m_sec_sequence.current();
1840 case eSecCommand::SET_POWER_LIMITING_MODE:
1845 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1846 FILE *f=fopen(proc_name, "w");
1847 if (f) // new interface exist?
1849 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1850 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1851 eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1853 eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1856 else if (sec_fe->m_need_rotor_workaround)
1859 int slotid = sec_fe->m_slotid;
1860 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1862 sprintf(dev, "/dev/i2c-%d", slotid);
1863 else if (slotid == 2)
1864 sprintf(dev, "/dev/i2c-2"); // first nim socket on DM8000 use /dev/i2c-2
1865 else if (slotid == 3)
1866 sprintf(dev, "/dev/i2c-4"); // second nim socket on DM8000 use /dev/i2c-4
1867 int fd = ::open(dev, O_RDWR);
1869 unsigned char data[2];
1870 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1871 if(::read(fd, data, 1) != 1)
1872 eDebugNoSimulate("[SEC] error read lnbp (%m)");
1873 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1875 data[0] |= 0x80; // enable static current limiting
1876 eDebugNoSimulate("[SEC] set static current limiting");
1880 data[0] &= ~0x80; // enable dynamic current limiting
1881 eDebugNoSimulate("[SEC] set dynamic current limiting");
1883 if(::write(fd, data, 1) != 1)
1884 eDebugNoSimulate("[SEC] error write lnbp (%m)");
1888 ++m_sec_sequence.current();
1891 case eSecCommand::DELAYED_CLOSE_FRONTEND:
1893 eDebugNoSimulate("[SEC] delayed close frontend");
1894 closeFrontend(false, true);
1895 ++m_sec_sequence.current();
1899 eDebugNoSimulate("[SEC] unhandled sec command %d",
1900 ++m_sec_sequence.current()->cmd);
1901 ++m_sec_sequence.current();
1904 m_tuneTimer->start(delay,true);
1908 if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1913 void eDVBFrontend::setFrontend(bool recvEvents)
1917 eDebug("setting frontend %d", m_dvbid);
1920 feEvent(-1); // flush events
1921 #if HAVE_DVB_API_VERSION >= 5
1922 if (m_type == iDVBFrontend::feSatellite)
1924 fe_rolloff_t rolloff = ROLLOFF_35;
1925 fe_pilot_t pilot = PILOT_OFF;
1926 fe_modulation_t modulation = QPSK;
1927 fe_delivery_system_t system = SYS_DVBS;
1928 switch(oparm.sat.system)
1930 case eDVBFrontendParametersSatellite::System_DVB_S: system = SYS_DVBS; break;
1931 case eDVBFrontendParametersSatellite::System_DVB_S2: system = SYS_DVBS2; break;
1933 switch(oparm.sat.modulation)
1935 case eDVBFrontendParametersSatellite::Modulation_QPSK: modulation = QPSK; break;
1936 case eDVBFrontendParametersSatellite::Modulation_8PSK: modulation = PSK_8; break;
1937 case eDVBFrontendParametersSatellite::Modulation_QAM16: modulation = QAM_16; break;
1939 switch(oparm.sat.pilot)
1941 case eDVBFrontendParametersSatellite::Pilot_Off: pilot = PILOT_OFF; break;
1942 case eDVBFrontendParametersSatellite::Pilot_On: pilot = PILOT_ON; break;
1943 case eDVBFrontendParametersSatellite::Pilot_Unknown: pilot = PILOT_AUTO; break;
1945 switch(oparm.sat.rolloff)
1947 case eDVBFrontendParametersSatellite::RollOff_alpha_0_20: rolloff = ROLLOFF_20; break;
1948 case eDVBFrontendParametersSatellite::RollOff_alpha_0_25: rolloff = ROLLOFF_25; break;
1949 case eDVBFrontendParametersSatellite::RollOff_alpha_0_35: rolloff = ROLLOFF_35; break;
1951 struct dtv_property p[10];
1952 struct dtv_properties cmdseq;
1954 p[0].cmd = DTV_CLEAR;
1955 p[1].cmd = DTV_DELIVERY_SYSTEM, p[1].u.data = system;
1956 p[2].cmd = DTV_FREQUENCY, p[2].u.data = parm_frequency;
1957 p[3].cmd = DTV_MODULATION, p[3].u.data = modulation;
1958 p[4].cmd = DTV_SYMBOL_RATE, p[4].u.data = parm_u_qpsk_symbol_rate;
1959 p[5].cmd = DTV_INNER_FEC, p[5].u.data = parm_u_qpsk_fec_inner;
1960 p[6].cmd = DTV_INVERSION, p[6].u.data = parm_inversion;
1961 if (system == SYS_DVBS2)
1963 p[7].cmd = DTV_ROLLOFF, p[7].u.data = rolloff;
1964 p[8].cmd = DTV_PILOT, p[8].u.data = pilot;
1965 p[9].cmd = DTV_TUNE;
1970 p[7].cmd = DTV_TUNE;
1973 if (ioctl(m_fd, FE_SET_PROPERTY, &cmdseq) == -1)
1975 perror("FE_SET_PROPERTY failed");
1982 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1984 perror("FE_SET_FRONTEND failed");
1991 RESULT eDVBFrontend::getFrontendType(int &t)
1999 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
2004 eWarning("no SEC module active!");
2007 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
2010 #if HAVE_DVB_API_VERSION >= 3
2011 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",
2014 feparm.polarisation,
2018 feparm.orbital_position,
2024 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
2027 feparm.polarisation,
2031 feparm.orbital_position);
2033 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
2034 switch (feparm.inversion)
2036 case eDVBFrontendParametersSatellite::Inversion_On:
2037 parm_inversion = INVERSION_ON;
2039 case eDVBFrontendParametersSatellite::Inversion_Off:
2040 parm_inversion = INVERSION_OFF;
2043 case eDVBFrontendParametersSatellite::Inversion_Unknown:
2044 parm_inversion = INVERSION_AUTO;
2047 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S)
2051 case eDVBFrontendParametersSatellite::FEC_None:
2052 parm_u_qpsk_fec_inner = FEC_NONE;
2054 case eDVBFrontendParametersSatellite::FEC_1_2:
2055 parm_u_qpsk_fec_inner = FEC_1_2;
2057 case eDVBFrontendParametersSatellite::FEC_2_3:
2058 parm_u_qpsk_fec_inner = FEC_2_3;
2060 case eDVBFrontendParametersSatellite::FEC_3_4:
2061 parm_u_qpsk_fec_inner = FEC_3_4;
2063 case eDVBFrontendParametersSatellite::FEC_5_6:
2064 parm_u_qpsk_fec_inner = FEC_5_6;
2066 case eDVBFrontendParametersSatellite::FEC_7_8:
2067 parm_u_qpsk_fec_inner = FEC_7_8;
2070 eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
2071 case eDVBFrontendParametersSatellite::FEC_Auto:
2072 parm_u_qpsk_fec_inner = FEC_AUTO;
2076 #if HAVE_DVB_API_VERSION >= 3
2081 case eDVBFrontendParametersSatellite::FEC_1_2:
2082 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
2084 case eDVBFrontendParametersSatellite::FEC_2_3:
2085 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
2087 case eDVBFrontendParametersSatellite::FEC_3_4:
2088 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
2090 case eDVBFrontendParametersSatellite::FEC_3_5:
2091 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
2093 case eDVBFrontendParametersSatellite::FEC_4_5:
2094 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
2096 case eDVBFrontendParametersSatellite::FEC_5_6:
2097 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
2099 case eDVBFrontendParametersSatellite::FEC_7_8:
2100 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
2102 case eDVBFrontendParametersSatellite::FEC_8_9:
2103 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
2105 case eDVBFrontendParametersSatellite::FEC_9_10:
2106 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
2109 eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
2112 #if HAVE_DVB_API_VERSION < 5
2113 parm_inversion = (fe_spectral_inversion_t)((feparm.rolloff << 2) | parm_inversion); // Hack.. we use bit 2..3 of inversion param for rolloff
2114 parm_inversion = (fe_spectral_inversion_t)((feparm.pilot << 4) | parm_inversion); // Hack.. we use bit 4..5 of inversion param for pilot
2115 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation_8PSK)
2117 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
2118 // 8PSK fec driver values are decimal 9 bigger
2123 // FIXME !!! get frequency range from tuner
2124 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
2126 eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
2129 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
2135 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
2137 #if HAVE_DVB_API_VERSION < 3
2138 parm_frequency = feparm.frequency;
2140 parm_frequency = feparm.frequency * 1000;
2142 parm_u_qam_symbol_rate = feparm.symbol_rate;
2143 switch (feparm.modulation)
2145 case eDVBFrontendParametersCable::Modulation_QAM16:
2146 parm_u_qam_modulation = QAM_16;
2148 case eDVBFrontendParametersCable::Modulation_QAM32:
2149 parm_u_qam_modulation = QAM_32;
2151 case eDVBFrontendParametersCable::Modulation_QAM64:
2152 parm_u_qam_modulation = QAM_64;
2154 case eDVBFrontendParametersCable::Modulation_QAM128:
2155 parm_u_qam_modulation = QAM_128;
2157 case eDVBFrontendParametersCable::Modulation_QAM256:
2158 parm_u_qam_modulation = QAM_256;
2161 case eDVBFrontendParametersCable::Modulation_Auto:
2162 parm_u_qam_modulation = QAM_AUTO;
2165 switch (feparm.inversion)
2167 case eDVBFrontendParametersCable::Inversion_On:
2168 parm_inversion = INVERSION_ON;
2170 case eDVBFrontendParametersCable::Inversion_Off:
2171 parm_inversion = INVERSION_OFF;
2174 case eDVBFrontendParametersCable::Inversion_Unknown:
2175 parm_inversion = INVERSION_AUTO;
2178 switch (feparm.fec_inner)
2180 case eDVBFrontendParametersCable::FEC_None:
2181 parm_u_qam_fec_inner = FEC_NONE;
2183 case eDVBFrontendParametersCable::FEC_1_2:
2184 parm_u_qam_fec_inner = FEC_1_2;
2186 case eDVBFrontendParametersCable::FEC_2_3:
2187 parm_u_qam_fec_inner = FEC_2_3;
2189 case eDVBFrontendParametersCable::FEC_3_4:
2190 parm_u_qam_fec_inner = FEC_3_4;
2192 case eDVBFrontendParametersCable::FEC_5_6:
2193 parm_u_qam_fec_inner = FEC_5_6;
2195 case eDVBFrontendParametersCable::FEC_7_8:
2196 parm_u_qam_fec_inner = FEC_7_8;
2198 #if HAVE_DVB_API_VERSION >= 3
2199 case eDVBFrontendParametersCable::FEC_8_9:
2200 parm_u_qam_fec_inner = FEC_8_9;
2204 case eDVBFrontendParametersCable::FEC_Auto:
2205 parm_u_qam_fec_inner = FEC_AUTO;
2208 eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
2209 parm_frequency/1000,
2210 parm_u_qam_symbol_rate,
2211 parm_u_qam_fec_inner,
2212 parm_u_qam_modulation,
2218 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
2220 parm_frequency = feparm.frequency;
2222 switch (feparm.bandwidth)
2224 case eDVBFrontendParametersTerrestrial::Bandwidth_8MHz:
2225 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
2227 case eDVBFrontendParametersTerrestrial::Bandwidth_7MHz:
2228 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
2230 case eDVBFrontendParametersTerrestrial::Bandwidth_6MHz:
2231 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
2234 case eDVBFrontendParametersTerrestrial::Bandwidth_Auto:
2235 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
2238 switch (feparm.code_rate_LP)
2240 case eDVBFrontendParametersTerrestrial::FEC_1_2:
2241 parm_u_ofdm_code_rate_LP = FEC_1_2;
2243 case eDVBFrontendParametersTerrestrial::FEC_2_3:
2244 parm_u_ofdm_code_rate_LP = FEC_2_3;
2246 case eDVBFrontendParametersTerrestrial::FEC_3_4:
2247 parm_u_ofdm_code_rate_LP = FEC_3_4;
2249 case eDVBFrontendParametersTerrestrial::FEC_5_6:
2250 parm_u_ofdm_code_rate_LP = FEC_5_6;
2252 case eDVBFrontendParametersTerrestrial::FEC_7_8:
2253 parm_u_ofdm_code_rate_LP = FEC_7_8;
2256 case eDVBFrontendParametersTerrestrial::FEC_Auto:
2257 parm_u_ofdm_code_rate_LP = FEC_AUTO;
2260 switch (feparm.code_rate_HP)
2262 case eDVBFrontendParametersTerrestrial::FEC_1_2:
2263 parm_u_ofdm_code_rate_HP = FEC_1_2;
2265 case eDVBFrontendParametersTerrestrial::FEC_2_3:
2266 parm_u_ofdm_code_rate_HP = FEC_2_3;
2268 case eDVBFrontendParametersTerrestrial::FEC_3_4:
2269 parm_u_ofdm_code_rate_HP = FEC_3_4;
2271 case eDVBFrontendParametersTerrestrial::FEC_5_6:
2272 parm_u_ofdm_code_rate_HP = FEC_5_6;
2274 case eDVBFrontendParametersTerrestrial::FEC_7_8:
2275 parm_u_ofdm_code_rate_HP = FEC_7_8;
2278 case eDVBFrontendParametersTerrestrial::FEC_Auto:
2279 parm_u_ofdm_code_rate_HP = FEC_AUTO;
2282 switch (feparm.modulation)
2284 case eDVBFrontendParametersTerrestrial::Modulation_QPSK:
2285 parm_u_ofdm_constellation = QPSK;
2287 case eDVBFrontendParametersTerrestrial::Modulation_QAM16:
2288 parm_u_ofdm_constellation = QAM_16;
2290 case eDVBFrontendParametersTerrestrial::Modulation_QAM64:
2291 parm_u_ofdm_constellation = QAM_64;
2294 case eDVBFrontendParametersTerrestrial::Modulation_Auto:
2295 parm_u_ofdm_constellation = QAM_AUTO;
2298 switch (feparm.transmission_mode)
2300 case eDVBFrontendParametersTerrestrial::TransmissionMode_2k:
2301 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2303 case eDVBFrontendParametersTerrestrial::TransmissionMode_8k:
2304 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2307 case eDVBFrontendParametersTerrestrial::TransmissionMode_Auto:
2308 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2311 switch (feparm.guard_interval)
2313 case eDVBFrontendParametersTerrestrial::GuardInterval_1_32:
2314 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2316 case eDVBFrontendParametersTerrestrial::GuardInterval_1_16:
2317 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2319 case eDVBFrontendParametersTerrestrial::GuardInterval_1_8:
2320 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2322 case eDVBFrontendParametersTerrestrial::GuardInterval_1_4:
2323 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2326 case eDVBFrontendParametersTerrestrial::GuardInterval_Auto:
2327 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2330 switch (feparm.hierarchy)
2332 case eDVBFrontendParametersTerrestrial::Hierarchy_None:
2333 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2335 case eDVBFrontendParametersTerrestrial::Hierarchy_1:
2336 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2338 case eDVBFrontendParametersTerrestrial::Hierarchy_2:
2339 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2341 case eDVBFrontendParametersTerrestrial::Hierarchy_4:
2342 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2345 case eDVBFrontendParametersTerrestrial::Hierarchy_Auto:
2346 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2349 switch (feparm.inversion)
2351 case eDVBFrontendParametersTerrestrial::Inversion_On:
2352 parm_inversion = INVERSION_ON;
2354 case eDVBFrontendParametersTerrestrial::Inversion_Off:
2355 parm_inversion = INVERSION_OFF;
2358 case eDVBFrontendParametersTerrestrial::Inversion_Unknown:
2359 parm_inversion = INVERSION_AUTO;
2366 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2368 unsigned int timeout = 5000;
2369 eDebugNoSimulate("(%d)tune", m_dvbid);
2375 if (!m_sn && !m_simulate)
2377 eDebug("no frontend device opened... do not try to tune !!!");
2391 m_sec_sequence.clear();
2393 where.calcLockTimeout(timeout);
2399 eDVBFrontendParametersSatellite feparm;
2400 if (where.getDVBS(feparm))
2402 eDebug("no dvbs data!");
2406 if (m_rotor_mode != feparm.no_rotor_command_on_tune && !feparm.no_rotor_command_on_tune)
2408 eDVBFrontend *sec_fe = this;
2409 long tmp = m_data[LINKED_PREV_PTR];
2412 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
2413 sec_fe = linked_fe->m_frontend;
2414 sec_fe->getData(LINKED_NEXT_PTR, tmp);
2416 eDebug("(fe%d) reset diseqc after leave rotor mode!", m_dvbid);
2417 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
2419 m_rotor_mode = feparm.no_rotor_command_on_tune;
2421 m_sec->setRotorMoving(m_slotid, false);
2422 res=prepare_sat(feparm, timeout);
2430 eDVBFrontendParametersCable feparm;
2431 if (where.getDVBC(feparm))
2436 res=prepare_cable(feparm);
2440 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2441 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2446 eDVBFrontendParametersTerrestrial feparm;
2447 if (where.getDVBT(feparm))
2449 eDebug("no -T data");
2453 res=prepare_terrestrial(feparm);
2457 std::string enable_5V;
2458 char configStr[255];
2459 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2460 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2461 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2462 if (enable_5V == "True")
2463 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2465 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2466 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2472 m_sec_sequence.current() = m_sec_sequence.begin();
2476 m_tuneTimer->start(0,true);
2478 if (m_state != stateTuning)
2480 m_state = stateTuning;
2481 m_stateChanged(this);
2490 m_tuneTimer->stop();
2494 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2496 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2500 RESULT eDVBFrontend::setVoltage(int voltage)
2502 if (m_type == feCable)
2504 #if HAVE_DVB_API_VERSION < 3
2507 bool increased=false;
2508 fe_sec_voltage_t vlt;
2510 m_data[CUR_VOLTAGE]=voltage;
2514 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2515 vlt = SEC_VOLTAGE_OFF;
2518 #if HAVE_DVB_API_VERSION < 3
2519 vlt = SEC_VOLTAGE_13_5;
2525 vlt = SEC_VOLTAGE_13;
2528 #if HAVE_DVB_API_VERSION < 3
2529 vlt = SEC_VOLTAGE_18_5;
2535 vlt = SEC_VOLTAGE_18;
2542 #if HAVE_DVB_API_VERSION < 3
2543 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2545 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2546 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2547 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2551 RESULT eDVBFrontend::getState(int &state)
2557 RESULT eDVBFrontend::setTone(int t)
2559 if (m_type != feSatellite)
2561 #if HAVE_DVB_API_VERSION < 3
2564 fe_sec_tone_mode_t tone;
2573 tone = SEC_TONE_OFF;
2580 #if HAVE_DVB_API_VERSION < 3
2581 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2583 return ::ioctl(m_fd, FE_SET_TONE, tone);
2587 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2588 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2591 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2595 #if HAVE_DVB_API_VERSION < 3
2596 struct secCommand cmd;
2597 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2598 cmd.u.diseqc.cmdtype = diseqc.data[0];
2599 cmd.u.diseqc.addr = diseqc.data[1];
2600 cmd.u.diseqc.cmd = diseqc.data[2];
2601 cmd.u.diseqc.numParams = diseqc.len-3;
2602 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2603 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2605 struct dvb_diseqc_master_cmd cmd;
2606 memcpy(cmd.msg, diseqc.data, diseqc.len);
2607 cmd.msg_len = diseqc.len;
2608 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2614 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2615 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2617 RESULT eDVBFrontend::sendToneburst(int burst)
2621 #if HAVE_DVB_API_VERSION < 3
2622 secMiniCmd cmd = SEC_MINI_NONE;
2624 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2626 if ( burst == eDVBSatelliteDiseqcParameters::A )
2628 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2630 #if HAVE_DVB_API_VERSION < 3
2631 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2634 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2640 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2646 RESULT eDVBFrontend::setSecSequence(eSecCommandList &list)
2648 if (m_data[SATCR] != -1 && m_sec_sequence.current() != m_sec_sequence.end())
2649 m_sec_sequence.push_back(list);
2651 m_sec_sequence = list;
2655 RESULT eDVBFrontend::getData(int num, long &data)
2657 if ( num < NUM_DATA_ENTRIES )
2665 RESULT eDVBFrontend::setData(int num, long val)
2667 if ( num < NUM_DATA_ENTRIES )
2675 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2678 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2680 if (m_type == eDVBFrontend::feSatellite)
2683 eDVBFrontendParametersSatellite sat_parm;
2684 int ret = feparm->getDVBS(sat_parm);
2686 if (sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S2 && !m_can_handle_dvbs2)
2688 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2689 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S && m_can_handle_dvbs2)
2693 else if (m_type == eDVBFrontend::feCable)
2694 return 2; // more prio for cable frontends
2695 else if (m_type == eDVBFrontend::feTerrestrial)
2700 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2702 ePyObject Id, Descr, Enabled, IsDVBS2, frontendId;
2703 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 5)
2705 Id = PyTuple_GET_ITEM(obj, 0);
2706 Descr = PyTuple_GET_ITEM(obj, 1);
2707 Enabled = PyTuple_GET_ITEM(obj, 2);
2708 IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2709 frontendId = PyTuple_GET_ITEM(obj, 4);
2710 m_slotid = PyInt_AsLong(Id);
2711 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2) || !PyInt_Check(frontendId))
2713 strcpy(m_description, PyString_AS_STRING(Descr));
2714 if (PyInt_AsLong(frontendId) == -1 || PyInt_AsLong(frontendId) != m_dvbid) {
2715 // eDebugNoSimulate("skip slotinfo for slotid %d, descr %s",
2716 // m_slotid, m_description);
2719 m_enabled = Enabled == Py_True;
2720 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2721 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2722 !!strstr(m_description, "Alps BSBE2") ||
2723 !!strstr(m_description, "Alps -S") ||
2724 !!strstr(m_description, "BCM4501");
2725 m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2726 eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2727 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2730 PyErr_SetString(PyExc_StandardError,
2731 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");