1 #include <lib/dvb/dvb.h>
2 #include <lib/dvb/frontendparms.h>
3 #include <lib/base/eerror.h>
4 #include <lib/base/nconfig.h> // access to python config
10 #ifndef I2C_SLAVE_FORCE
11 #define I2C_SLAVE_FORCE 0x0706
14 #if HAVE_DVB_API_VERSION < 3
15 #include <ost/frontend.h>
17 #define QAM_AUTO (Modulation)6
18 #define TRANSMISSION_MODE_AUTO (TransmitMode)2
19 #define BANDWIDTH_AUTO (BandWidth)3
20 #define GUARD_INTERVAL_AUTO (GuardInterval)4
21 #define HIERARCHY_AUTO (Hierarchy)4
22 #define parm_frequency parm.Frequency
23 #define parm_inversion parm.Inversion
24 #define parm_u_qpsk_symbol_rate parm.u.qpsk.SymbolRate
25 #define parm_u_qpsk_fec_inner parm.u.qpsk.FEC_inner
26 #define parm_u_qam_symbol_rate parm.u.qam.SymbolRate
27 #define parm_u_qam_fec_inner parm.u.qam.FEC_inner
28 #define parm_u_qam_modulation parm.u.qam.QAM
29 #define parm_u_ofdm_bandwidth parm.u.ofdm.bandWidth
30 #define parm_u_ofdm_code_rate_LP parm.u.ofdm.LP_CodeRate
31 #define parm_u_ofdm_code_rate_HP parm.u.ofdm.HP_CodeRate
32 #define parm_u_ofdm_constellation parm.u.ofdm.Constellation
33 #define parm_u_ofdm_transmission_mode parm.u.ofdm.TransmissionMode
34 #define parm_u_ofdm_guard_interval parm.u.ofdm.guardInterval
35 #define parm_u_ofdm_hierarchy_information parm.u.ofdm.HierarchyInformation
37 #include <linux/dvb/frontend.h>
38 #define parm_frequency parm.frequency
39 #define parm_inversion parm.inversion
40 #define parm_u_qpsk_symbol_rate parm.u.qpsk.symbol_rate
41 #define parm_u_qpsk_fec_inner parm.u.qpsk.fec_inner
42 #define parm_u_qam_symbol_rate parm.u.qam.symbol_rate
43 #define parm_u_qam_fec_inner parm.u.qam.fec_inner
44 #define parm_u_qam_modulation parm.u.qam.modulation
45 #define parm_u_ofdm_bandwidth parm.u.ofdm.bandwidth
46 #define parm_u_ofdm_code_rate_LP parm.u.ofdm.code_rate_LP
47 #define parm_u_ofdm_code_rate_HP parm.u.ofdm.code_rate_HP
48 #define parm_u_ofdm_constellation parm.u.ofdm.constellation
49 #define parm_u_ofdm_transmission_mode parm.u.ofdm.transmission_mode
50 #define parm_u_ofdm_guard_interval parm.u.ofdm.guard_interval
51 #define parm_u_ofdm_hierarchy_information parm.u.ofdm.hierarchy_information
52 #if HAVE_DVB_API_VERSION < 5
53 #define FEC_S2_QPSK_1_2 (fe_code_rate_t)(FEC_AUTO+1)
54 #define FEC_S2_QPSK_2_3 (fe_code_rate_t)(FEC_S2_QPSK_1_2+1)
55 #define FEC_S2_QPSK_3_4 (fe_code_rate_t)(FEC_S2_QPSK_2_3+1)
56 #define FEC_S2_QPSK_5_6 (fe_code_rate_t)(FEC_S2_QPSK_3_4+1)
57 #define FEC_S2_QPSK_7_8 (fe_code_rate_t)(FEC_S2_QPSK_5_6+1)
58 #define FEC_S2_QPSK_8_9 (fe_code_rate_t)(FEC_S2_QPSK_7_8+1)
59 #define FEC_S2_QPSK_3_5 (fe_code_rate_t)(FEC_S2_QPSK_8_9+1)
60 #define FEC_S2_QPSK_4_5 (fe_code_rate_t)(FEC_S2_QPSK_3_5+1)
61 #define FEC_S2_QPSK_9_10 (fe_code_rate_t)(FEC_S2_QPSK_4_5+1)
62 #define FEC_S2_8PSK_1_2 (fe_code_rate_t)(FEC_S2_QPSK_9_10+1)
63 #define FEC_S2_8PSK_2_3 (fe_code_rate_t)(FEC_S2_8PSK_1_2+1)
64 #define FEC_S2_8PSK_3_4 (fe_code_rate_t)(FEC_S2_8PSK_2_3+1)
65 #define FEC_S2_8PSK_5_6 (fe_code_rate_t)(FEC_S2_8PSK_3_4+1)
66 #define FEC_S2_8PSK_7_8 (fe_code_rate_t)(FEC_S2_8PSK_5_6+1)
67 #define FEC_S2_8PSK_8_9 (fe_code_rate_t)(FEC_S2_8PSK_7_8+1)
68 #define FEC_S2_8PSK_3_5 (fe_code_rate_t)(FEC_S2_8PSK_8_9+1)
69 #define FEC_S2_8PSK_4_5 (fe_code_rate_t)(FEC_S2_8PSK_3_5+1)
70 #define FEC_S2_8PSK_9_10 (fe_code_rate_t)(FEC_S2_8PSK_4_5+1)
72 #define FEC_S2_QPSK_1_2 (fe_code_rate_t)(FEC_1_2)
73 #define FEC_S2_QPSK_2_3 (fe_code_rate_t)(FEC_2_3)
74 #define FEC_S2_QPSK_3_4 (fe_code_rate_t)(FEC_3_4)
75 #define FEC_S2_QPSK_5_6 (fe_code_rate_t)(FEC_5_6)
76 #define FEC_S2_QPSK_7_8 (fe_code_rate_t)(FEC_7_8)
77 #define FEC_S2_QPSK_8_9 (fe_code_rate_t)(FEC_8_9)
78 #define FEC_S2_QPSK_3_5 (fe_code_rate_t)(FEC_3_5)
79 #define FEC_S2_QPSK_4_5 (fe_code_rate_t)(FEC_4_5)
80 #define FEC_S2_QPSK_9_10 (fe_code_rate_t)(FEC_9_10)
84 #include <dvbsi++/satellite_delivery_system_descriptor.h>
85 #include <dvbsi++/cable_delivery_system_descriptor.h>
86 #include <dvbsi++/terrestrial_delivery_system_descriptor.h>
88 #define eDebugNoSimulate(x...) \
96 eDebugNoNewLine("SIMULATE:"); \
101 #define eDebugNoSimulateNoNewLine(x...) \
104 eDebugNoNewLine(x); \
109 eDebugNoNewLine("SIMULATE:"); \
110 eDebugNoNewLine(x); \
114 void eDVBDiseqcCommand::setCommandString(const char *str)
119 int slen = strlen(str);
122 eDebug("invalid diseqc command string length (not 2 byte aligned)");
125 if (slen > MAX_DISEQC_LENGTH*2)
127 eDebug("invalid diseqc command string length (string is to long)");
131 for (int i=0; i < slen; ++i)
133 unsigned char c = str[i];
136 case '0' ... '9': c-=48; break;
137 case 'a' ... 'f': c-=87; break;
138 case 'A' ... 'F': c-=55; break;
140 eDebug("invalid character in hex string..ignore complete diseqc command !");
154 void eDVBFrontendParametersSatellite::set(const SatelliteDeliverySystemDescriptor &descriptor)
156 frequency = descriptor.getFrequency() * 10;
157 symbol_rate = descriptor.getSymbolRate() * 100;
158 polarisation = descriptor.getPolarization();
159 fec = descriptor.getFecInner();
160 if ( fec != eDVBFrontendParametersSatellite::FEC_None && fec > eDVBFrontendParametersSatellite::FEC_9_10 )
161 fec = eDVBFrontendParametersSatellite::FEC_Auto;
162 inversion = eDVBFrontendParametersSatellite::Inversion_Unknown;
163 pilot = eDVBFrontendParametersSatellite::Pilot_Unknown;
164 orbital_position = ((descriptor.getOrbitalPosition() >> 12) & 0xF) * 1000;
165 orbital_position += ((descriptor.getOrbitalPosition() >> 8) & 0xF) * 100;
166 orbital_position += ((descriptor.getOrbitalPosition() >> 4) & 0xF) * 10;
167 orbital_position += ((descriptor.getOrbitalPosition()) & 0xF);
168 if (orbital_position && (!descriptor.getWestEastFlag()))
169 orbital_position = 3600 - orbital_position;
170 system = descriptor.getModulationSystem();
171 modulation = descriptor.getModulation();
172 if (system == eDVBFrontendParametersSatellite::System_DVB_S && modulation == eDVBFrontendParametersSatellite::Modulation_8PSK)
174 eDebug("satellite_delivery_descriptor non valid modulation type.. force QPSK");
175 modulation=eDVBFrontendParametersSatellite::Modulation_QPSK;
177 rolloff = descriptor.getRollOff();
178 if (system == eDVBFrontendParametersSatellite::System_DVB_S2)
180 eDebug("SAT DVB-S2 freq %d, %s, pos %d, sr %d, fec %d, modulation %d, rolloff %d",
182 polarisation ? "hor" : "vert",
190 eDebug("SAT DVB-S freq %d, %s, pos %d, sr %d, fec %d",
192 polarisation ? "hor" : "vert",
198 void eDVBFrontendParametersCable::set(const CableDeliverySystemDescriptor &descriptor)
200 frequency = descriptor.getFrequency() / 10;
201 symbol_rate = descriptor.getSymbolRate() * 100;
202 fec_inner = descriptor.getFecInner();
203 if ( fec_inner != eDVBFrontendParametersCable::FEC_None && fec_inner > eDVBFrontendParametersCable::FEC_8_9 )
204 fec_inner = eDVBFrontendParametersCable::FEC_Auto;
205 modulation = descriptor.getModulation();
206 if ( modulation > 0x5 )
207 modulation = eDVBFrontendParametersCable::Modulation_Auto;
208 inversion = eDVBFrontendParametersCable::Inversion_Unknown;
209 eDebug("Cable freq %d, mod %d, sr %d, fec %d",
211 modulation, symbol_rate, fec_inner);
214 void eDVBFrontendParametersTerrestrial::set(const TerrestrialDeliverySystemDescriptor &descriptor)
216 frequency = descriptor.getCentreFrequency() * 10;
217 bandwidth = descriptor.getBandwidth();
218 if ( bandwidth > 2 ) // 5Mhz forced to auto
219 bandwidth = eDVBFrontendParametersTerrestrial::Bandwidth_Auto;
220 code_rate_HP = descriptor.getCodeRateHpStream();
221 if (code_rate_HP > 4)
222 code_rate_HP = eDVBFrontendParametersTerrestrial::FEC_Auto;
223 code_rate_LP = descriptor.getCodeRateLpStream();
224 if (code_rate_LP > 4)
225 code_rate_LP = eDVBFrontendParametersTerrestrial::FEC_Auto;
226 transmission_mode = descriptor.getTransmissionMode();
227 if (transmission_mode > 1) // TM4k forced to auto
228 transmission_mode = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto;
229 guard_interval = descriptor.getGuardInterval();
230 if (guard_interval > 3)
231 guard_interval = eDVBFrontendParametersTerrestrial::GuardInterval_Auto;
232 hierarchy = descriptor.getHierarchyInformation()&3;
233 modulation = descriptor.getConstellation();
235 modulation = eDVBFrontendParametersTerrestrial::Modulation_Auto;
236 inversion = eDVBFrontendParametersTerrestrial::Inversion_Unknown;
237 eDebug("Terr freq %d, bw %d, cr_hp %d, cr_lp %d, tm_mode %d, guard %d, hierarchy %d, const %d",
238 frequency, bandwidth, code_rate_HP, code_rate_LP, transmission_mode,
239 guard_interval, hierarchy, modulation);
242 eDVBFrontendParameters::eDVBFrontendParameters()
243 :m_type(-1), m_flags(0)
247 DEFINE_REF(eDVBFrontendParameters);
249 RESULT eDVBFrontendParameters::getSystem(int &t) const
257 RESULT eDVBFrontendParameters::getDVBS(eDVBFrontendParametersSatellite &p) const
259 if (m_type != iDVBFrontend::feSatellite)
265 RESULT eDVBFrontendParameters::getDVBC(eDVBFrontendParametersCable &p) const
267 if (m_type != iDVBFrontend::feCable)
273 RESULT eDVBFrontendParameters::getDVBT(eDVBFrontendParametersTerrestrial &p) const
275 if (m_type != iDVBFrontend::feTerrestrial)
281 RESULT eDVBFrontendParameters::setDVBS(const eDVBFrontendParametersSatellite &p, bool no_rotor_command_on_tune)
284 sat.no_rotor_command_on_tune = no_rotor_command_on_tune;
285 m_type = iDVBFrontend::feSatellite;
289 RESULT eDVBFrontendParameters::setDVBC(const eDVBFrontendParametersCable &p)
292 m_type = iDVBFrontend::feCable;
296 RESULT eDVBFrontendParameters::setDVBT(const eDVBFrontendParametersTerrestrial &p)
299 m_type = iDVBFrontend::feTerrestrial;
303 RESULT eDVBFrontendParameters::calculateDifference(const iDVBFrontendParameters *parm, int &diff, bool exact) const
308 if (parm->getSystem(type))
312 diff = 1<<30; // big difference
318 case iDVBFrontend::feSatellite:
320 eDVBFrontendParametersSatellite osat;
321 if (parm->getDVBS(osat))
324 if (sat.orbital_position != osat.orbital_position)
326 else if (sat.polarisation != osat.polarisation)
328 else if (exact && sat.fec != osat.fec && sat.fec != eDVBFrontendParametersSatellite::FEC_Auto && osat.fec != eDVBFrontendParametersSatellite::FEC_Auto)
330 else if (exact && sat.modulation != osat.modulation && sat.modulation != eDVBFrontendParametersSatellite::Modulation_Auto && osat.modulation != eDVBFrontendParametersSatellite::Modulation_Auto)
334 diff = abs(sat.frequency - osat.frequency);
335 diff += abs(sat.symbol_rate - osat.symbol_rate);
339 case iDVBFrontend::feCable:
340 eDVBFrontendParametersCable ocable;
341 if (parm->getDVBC(ocable))
344 if (exact && cable.modulation != ocable.modulation
345 && cable.modulation != eDVBFrontendParametersCable::Modulation_Auto
346 && ocable.modulation != eDVBFrontendParametersCable::Modulation_Auto)
348 else if (exact && cable.fec_inner != ocable.fec_inner && cable.fec_inner != eDVBFrontendParametersCable::FEC_Auto && ocable.fec_inner != eDVBFrontendParametersCable::FEC_Auto)
352 diff = abs(cable.frequency - ocable.frequency);
353 diff += abs(cable.symbol_rate - ocable.symbol_rate);
356 case iDVBFrontend::feTerrestrial:
357 eDVBFrontendParametersTerrestrial oterrestrial;
358 if (parm->getDVBT(oterrestrial))
361 if (exact && oterrestrial.bandwidth != terrestrial.bandwidth &&
362 oterrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth_Auto &&
363 terrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth_Auto)
365 else if (exact && oterrestrial.modulation != terrestrial.modulation &&
366 oterrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation_Auto &&
367 terrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation_Auto)
369 else if (exact && oterrestrial.transmission_mode != terrestrial.transmission_mode &&
370 oterrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode_Auto &&
371 terrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode_Auto)
373 else if (exact && oterrestrial.guard_interval != terrestrial.guard_interval &&
374 oterrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval_Auto &&
375 terrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval_Auto)
377 else if (exact && oterrestrial.hierarchy != terrestrial.hierarchy &&
378 oterrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy_Auto &&
379 terrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy_Auto)
381 else if (exact && oterrestrial.code_rate_LP != terrestrial.code_rate_LP &&
382 oterrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC_Auto &&
383 terrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC_Auto)
385 else if (exact && oterrestrial.code_rate_HP != terrestrial.code_rate_HP &&
386 oterrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC_Auto &&
387 terrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC_Auto)
390 diff = abs(terrestrial.frequency - oterrestrial.frequency) / 1000;
398 RESULT eDVBFrontendParameters::getHash(unsigned long &hash) const
402 case iDVBFrontend::feSatellite:
404 hash = (sat.orbital_position << 16);
405 hash |= ((sat.frequency/1000)&0xFFFF)|((sat.polarisation&1) << 15);
408 case iDVBFrontend::feCable:
410 hash |= (cable.frequency/1000)&0xFFFF;
412 case iDVBFrontend::feTerrestrial:
414 hash |= (terrestrial.frequency/1000000)&0xFFFF;
421 RESULT eDVBFrontendParameters::calcLockTimeout(unsigned int &timeout) const
425 case iDVBFrontend::feSatellite:
427 /* high symbol rate transponders tune faster, due to
428 requiring less zigzag and giving more symbols faster.
430 5s are definitely not enough on really low SR when
431 zigzag has to find the exact frequency first.
433 if (sat.symbol_rate > 20000000)
435 else if (sat.symbol_rate > 10000000)
441 case iDVBFrontend::feCable:
444 case iDVBFrontend::feTerrestrial:
452 DEFINE_REF(eDVBFrontend);
454 int eDVBFrontend::PriorityOrder=0;
456 eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok, bool simulate)
457 :m_simulate(simulate), m_enabled(false), m_type(-1), m_dvbid(fe), m_slotid(fe)
458 ,m_fd(-1), m_rotor_mode(false), m_need_rotor_workaround(false), m_can_handle_dvbs2(false)
459 ,m_state(stateClosed), m_timeout(0), m_tuneTimer(0)
460 #if HAVE_DVB_API_VERSION < 3
464 #if HAVE_DVB_API_VERSION < 3
465 sprintf(m_filename, "/dev/dvb/card%d/frontend%d", adap, fe);
466 sprintf(m_sec_filename, "/dev/dvb/card%d/sec%d", adap, fe);
468 sprintf(m_filename, "/dev/dvb/adapter%d/frontend%d", adap, fe);
471 m_timeout = eTimer::create(eApp);
472 CONNECT(m_timeout->timeout, eDVBFrontend::timeout);
474 m_tuneTimer = eTimer::create(eApp);
475 CONNECT(m_tuneTimer->timeout, eDVBFrontend::tuneLoop);
477 for (int i=0; i<eDVBFrontend::NUM_DATA_ENTRIES; ++i)
480 m_idleInputpower[0]=m_idleInputpower[1]=0;
482 ok = !openFrontend();
486 void eDVBFrontend::reopenFrontend()
493 int eDVBFrontend::openFrontend()
495 if (m_state != stateClosed)
496 return -1; // already opened
501 #if HAVE_DVB_API_VERSION < 3
502 FrontendInfo fe_info;
504 dvb_frontend_info fe_info;
506 eDebugNoSimulate("opening frontend %d", m_dvbid);
509 if (!m_simulate || m_type == -1)
511 m_fd = ::open(m_filename, O_RDWR|O_NONBLOCK);
514 eWarning("failed! (%s) %m", m_filename);
520 eWarning("frontend %d already opened", m_dvbid);
523 if (::ioctl(m_fd, FE_GET_INFO, &fe_info) < 0)
525 eWarning("ioctl FE_GET_INFO failed");
531 switch (fe_info.type)
534 m_type = iDVBFrontend::feSatellite;
537 m_type = iDVBFrontend::feCable;
540 m_type = iDVBFrontend::feTerrestrial;
543 eWarning("unknown frontend type.");
548 eDebugNoSimulate("detected %s frontend", "satellite\0cable\0 terrestrial"+fe_info.type*10);
551 #if HAVE_DVB_API_VERSION < 3
552 if (m_type == iDVBFrontend::feSatellite)
558 m_secfd = ::open(m_sec_filename, O_RDWR);
561 eWarning("failed! (%s) %m", m_sec_filename);
569 eWarning("sec %d already opened", m_dvbid);
573 setTone(iDVBFrontend::toneOff);
574 setVoltage(iDVBFrontend::voltageOff);
578 m_sn = eSocketNotifier::create(eApp, m_fd, eSocketNotifier::Read, false);
579 CONNECT(m_sn->activated, eDVBFrontend::feEvent);
585 int eDVBFrontend::closeFrontend(bool force, bool no_delayed)
587 if (!force && m_data[CUR_VOLTAGE] != -1 && m_data[CUR_VOLTAGE] != iDVBFrontend::voltageOff)
589 long tmp = m_data[LINKED_NEXT_PTR];
592 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
593 if (linked_fe->m_inuse)
595 eDebugNoSimulate("dont close frontend %d until the linked frontend %d in slot %d is still in use",
596 m_dvbid, linked_fe->m_frontend->getDVBID(), linked_fe->m_frontend->getSlotID());
599 linked_fe->m_frontend->getData(LINKED_NEXT_PTR, tmp);
605 eDebugNoSimulate("close frontend %d", m_dvbid);
606 if (m_data[SATCR] != -1)
610 m_sec->prepareTurnOffSatCR(*this, m_data[SATCR]);
611 m_tuneTimer->start(0, true);
612 if(!m_tuneTimer->isActive())
615 eDebug("[turnOffSatCR] no mainloop");
618 timeout = tuneLoopInt();
621 usleep(timeout*1000); // blockierendes wait.. eTimer gibts ja nicht mehr
625 eDebug("[turnOffSatCR] running mainloop");
629 m_data[ROTOR_CMD] = -1;
632 setTone(iDVBFrontend::toneOff);
633 setVoltage(iDVBFrontend::voltageOff);
636 if (m_sec && !m_simulate)
637 m_sec->setRotorMoving(m_slotid, false);
641 eWarning("couldnt close frontend %d", m_dvbid);
645 setTone(iDVBFrontend::toneOff);
646 setVoltage(iDVBFrontend::voltageOff);
648 #if HAVE_DVB_API_VERSION < 3
651 if (!::close(m_secfd))
654 eWarning("couldnt close sec %d", m_dvbid);
658 m_state = stateClosed;
663 eDVBFrontend::~eDVBFrontend()
665 m_data[LINKED_PREV_PTR] = m_data[LINKED_NEXT_PTR] = -1;
669 void eDVBFrontend::feEvent(int w)
671 eDVBFrontend *sec_fe = this;
672 long tmp = m_data[LINKED_PREV_PTR];
675 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
676 sec_fe = linked_fe->m_frontend;
677 sec_fe->getData(LINKED_NEXT_PTR, tmp);
681 #if HAVE_DVB_API_VERSION < 3
684 dvb_frontend_event event;
688 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
690 if (res && (errno == EAGAIN))
696 #if HAVE_DVB_API_VERSION < 3
697 if (event.type == FE_COMPLETION_EV)
699 eDebug("(%d)fe event: status %x, inversion %s, m_tuning %d", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off", m_tuning);
700 if (event.status & FE_HAS_LOCK)
708 #if HAVE_DVB_API_VERSION >= 3
709 if (event.status & FE_TIMEDOUT) {
710 eDebug("FE_TIMEDOUT! ..abort");
723 eDebug("stateLostLock");
724 state = stateLostLock;
726 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
729 if (m_state != state)
732 m_stateChanged(this);
737 void eDVBFrontend::timeout()
740 if (m_state == stateTuning)
742 m_state = stateFailed;
743 m_stateChanged(this);
747 #define INRANGE(X,Y,Z) (((X<=Y) && (Y<=Z))||((Z<=Y) && (Y<=X)) ? 1 : 0)
749 /* unsigned 32 bit division */
750 static inline uint32_t fe_udiv(uint32_t a, uint32_t b)
752 return (a + b / 2) / b;
755 int eDVBFrontend::readFrontendData(int type)
764 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
765 eDebug("FE_READ_BER failed (%m)");
770 case signalQualitydB: /* this will move into the driver */
772 int sat_max = 1600; // for stv0288 / bsbe2
773 int ret = 0x12345678;
777 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
778 eDebug("FE_READ_SNR failed (%m)");
779 else if (!strcmp(m_description, "BCM4501 (internal)"))
781 float SDS_SNRE = snr << 16;
784 if (oparm.sat.system == eDVBFrontendParametersSatellite::System_DVB_S) // DVB-S1 / QPSK
786 static float SNR_COEFF[6] = {
789 197418.0 / 4194304.0,
790 -2602183.0 / 4194304.0,
791 20377212.0 / 4194304.0,
792 -37791203.0 / 4194304.0,
794 float fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0)),
795 fval2 = pow(10.0, fval1)-1;
796 fval1 = 10.0 * log10(fval2);
800 fval2 = SNR_COEFF[0];
801 for (int i=1; i<6; ++i)
804 fval2 += SNR_COEFF[i];
810 #if HAVE_DVB_API_VERSION >= 3
813 float fval1 = SDS_SNRE / 268435456.0,
816 if (parm_u_qpsk_fec_inner <= FEC_S2_QPSK_9_10) // DVB-S2 QPSK
827 fval4 = -10.0 * log10(fval1);
829 for (int i=0; i < 5; ++i)
830 fval1 = fval4 - fval2 * log10(1.0+pow(10.0, (fval3-fval1)/fval2));
835 ret = (int)(snr_in_db * 100);
837 else if (strstr(m_description, "Alps BSBE1 C01A") ||
838 strstr(m_description, "Alps -S(STV0288)"))
842 else if (snr == 0xFFFF) // i think this should not happen
846 enum { REALVAL, REGVAL };
847 const long CN_lookup[31][2] = {
848 {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
849 {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
850 {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
851 {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
852 {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
853 {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
856 int add=strchr(m_description, '.') ? 0xA250 : 0xA100;
857 long regval = 0xFFFF - ((snr / 3) + add), // revert some dvb api calulations to get the real register value
861 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
866 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[i][REGVAL]))
871 ret = (((regval - CN_lookup[Imin][REGVAL])
872 * (CN_lookup[Imax][REALVAL] - CN_lookup[Imin][REALVAL])
873 / (CN_lookup[Imax][REGVAL] - CN_lookup[Imin][REGVAL]))
874 + CN_lookup[Imin][REALVAL]) * 10;
880 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
881 !strcmp(m_description, "Alps -S") ||
882 !strcmp(m_description, "Philips -S") ||
883 !strcmp(m_description, "LG -S") )
886 ret = (int)((snr-39075)/17.647);
887 } else if (!strcmp(m_description, "Alps BSBE2"))
889 ret = (int)((snr >> 7) * 10);
890 } else if (!strcmp(m_description, "Philips CU1216Mk3"))
892 int mse = (~snr) & 0xFF;
893 switch (parm_u_qam_modulation) {
894 case QAM_16: ret = fe_udiv(1950000, (32 * mse) + 138) + 1000; break;
895 case QAM_32: ret = fe_udiv(2150000, (40 * mse) + 500) + 1350; break;
896 case QAM_64: ret = fe_udiv(2100000, (40 * mse) + 500) + 1250; break;
897 case QAM_128: ret = fe_udiv(1850000, (38 * mse) + 400) + 1380; break;
898 case QAM_256: ret = fe_udiv(1800000, (100 * mse) + 40) + 2030; break;
901 } else if (!strcmp(m_description, "Philips TU1216"))
903 snr = 0xFF - (snr & 0xFF);
905 ret = 10 * (int)(-100 * (log10(snr) - log10(255)));
907 else if (strstr(m_description, "BCM4506") || strstr(m_description, "BCM4505"))
908 ret = (snr * 100) >> 8;
910 if (type == signalQuality)
912 if (ret == 0x12345678) // no snr db calculation avail.. return untouched snr value..
917 return ret >= sat_max ? 65536 : ret * 65536 / sat_max;
918 case feCable: // we assume a max of 42db here
919 return ret >= 4200 ? 65536 : ret * 65536 / 4200;
920 case feTerrestrial: // we assume a max of 24db here
921 return ret >= 2400 ? 65536 : ret * 65536 / 2400;
925 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
933 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
934 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
940 #if HAVE_DVB_API_VERSION < 3
941 FrontendStatus status=0;
947 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
948 eDebug("FE_READ_STATUS failed (%m)");
949 return !!(status&FE_HAS_LOCK);
955 #if HAVE_DVB_API_VERSION < 3
956 FrontendStatus status=0;
962 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
963 eDebug("FE_READ_STATUS failed (%m)");
964 return !!(status&FE_HAS_SYNC);
974 void PutToDict(ePyObject &dict, const char*key, long value)
976 ePyObject item = PyInt_FromLong(value);
979 if (PyDict_SetItemString(dict, key, item))
980 eDebug("put %s to dict failed", key);
984 eDebug("could not create PyObject for %s", key);
987 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
991 if (PyDict_SetItemString(dict, key, item))
992 eDebug("put %s to dict failed", key);
996 eDebug("invalid PyObject for %s", key);
999 void PutToDict(ePyObject &dict, const char*key, const char *value)
1001 ePyObject item = PyString_FromString(value);
1004 if (PyDict_SetItemString(dict, key, item))
1005 eDebug("put %s to dict failed", key);
1009 eDebug("could not create PyObject for %s", key);
1012 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
1014 PutToDict(dict, "tuner_type", "DVB-S");
1015 PutToDict(dict, "frequency", feparm.frequency);
1016 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
1017 PutToDict(dict, "orbital_position", feparm.orbital_position);
1018 PutToDict(dict, "inversion", feparm.inversion);
1019 PutToDict(dict, "fec_inner", feparm.fec);
1020 PutToDict(dict, "modulation", feparm.modulation);
1021 PutToDict(dict, "polarization", feparm.polarisation);
1022 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S2)
1024 PutToDict(dict, "rolloff", feparm.rolloff);
1025 PutToDict(dict, "pilot", feparm.pilot);
1027 PutToDict(dict, "system", feparm.system);
1030 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
1032 PutToDict(dict, "tuner_type", "DVB-T");
1033 PutToDict(dict, "frequency", feparm.frequency);
1034 PutToDict(dict, "bandwidth", feparm.bandwidth);
1035 PutToDict(dict, "code_rate_lp", feparm.code_rate_LP);
1036 PutToDict(dict, "code_rate_hp", feparm.code_rate_HP);
1037 PutToDict(dict, "constellation", feparm.modulation);
1038 PutToDict(dict, "transmission_mode", feparm.transmission_mode);
1039 PutToDict(dict, "guard_interval", feparm.guard_interval);
1040 PutToDict(dict, "hierarchy_information", feparm.hierarchy);
1041 PutToDict(dict, "inversion", feparm.inversion);
1044 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
1046 PutToDict(dict, "tuner_type", "DVB-C");
1047 PutToDict(dict, "frequency", feparm.frequency);
1048 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
1049 PutToDict(dict, "modulation", feparm.modulation);
1050 PutToDict(dict, "inversion", feparm.inversion);
1051 PutToDict(dict, "fec_inner", feparm.fec_inner);
1054 #if HAVE_DVB_API_VERSION >= 5
1055 static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, struct dtv_property *p, long freq_offset, int orb_pos, int polarization)
1058 int frequency = parm_frequency + freq_offset;
1059 PutToDict(dict, "frequency", frequency);
1060 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
1061 PutToDict(dict, "orbital_position", orb_pos);
1062 PutToDict(dict, "polarization", polarization);
1064 switch(parm_u_qpsk_fec_inner)
1066 case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1067 case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1068 case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1069 case FEC_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
1070 case FEC_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
1071 case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1072 case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1073 case FEC_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
1074 case FEC_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1075 case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
1076 case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
1077 default: eDebug("got unsupported FEC from frontend! report as FEC_AUTO!\n");
1080 switch (p[0].u.data)
1082 default: eDebug("got unsupported system from frontend! report as DVBS!");
1083 case SYS_DVBS: tmp = eDVBFrontendParametersSatellite::System_DVB_S; break;
1086 switch (p[2].u.data)
1088 default: eDebug("got unsupported rolloff from frontend! report as 0_20!");
1089 case ROLLOFF_20: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1090 case ROLLOFF_25: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1091 case ROLLOFF_35: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1093 PutToDict(dict, "rolloff", tmp);
1095 switch (p[3].u.data)
1097 case PILOT_OFF: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1098 case PILOT_ON: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1099 case PILOT_AUTO: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1101 PutToDict(dict, "pilot", tmp);
1103 tmp = eDVBFrontendParametersSatellite::System_DVB_S2; break;
1106 PutToDict(dict, "system", tmp);
1108 switch (p[1].u.data)
1110 default: eDebug("got unsupported modulation from frontend! report as QPSK!");
1111 case QPSK: tmp = eDVBFrontendParametersSatellite::Modulation_QPSK; break;
1112 case PSK_8: tmp = eDVBFrontendParametersSatellite::Modulation_8PSK; break;
1114 PutToDict(dict, "modulation", tmp);
1118 static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, long freq_offset, int orb_pos, int polarization)
1121 int frequency = parm_frequency + freq_offset;
1122 PutToDict(dict, "frequency", frequency);
1123 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
1124 PutToDict(dict, "orbital_position", orb_pos);
1125 PutToDict(dict, "polarization", polarization);
1127 switch((int)parm_u_qpsk_fec_inner)
1129 case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1130 case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1131 case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1132 case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1133 case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1134 case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
1136 case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
1137 #if HAVE_DVB_API_VERSION >=3
1138 case FEC_S2_8PSK_1_2:
1139 case FEC_S2_QPSK_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1140 case FEC_S2_8PSK_2_3:
1141 case FEC_S2_QPSK_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1142 case FEC_S2_8PSK_3_4:
1143 case FEC_S2_QPSK_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1144 case FEC_S2_8PSK_5_6:
1145 case FEC_S2_QPSK_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1146 case FEC_S2_8PSK_7_8:
1147 case FEC_S2_QPSK_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1148 case FEC_S2_8PSK_8_9:
1149 case FEC_S2_QPSK_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
1150 case FEC_S2_8PSK_3_5:
1151 case FEC_S2_QPSK_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
1152 case FEC_S2_8PSK_4_5:
1153 case FEC_S2_QPSK_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
1154 case FEC_S2_8PSK_9_10:
1155 case FEC_S2_QPSK_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1158 PutToDict(dict, "fec_inner", tmp);
1159 #if HAVE_DVB_API_VERSION >=3
1160 PutToDict(dict, "modulation",
1161 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ?
1162 eDVBFrontendParametersSatellite::Modulation_8PSK :
1163 eDVBFrontendParametersSatellite::Modulation_QPSK );
1164 if (parm_u_qpsk_fec_inner > FEC_AUTO)
1166 switch(parm_inversion & 0xc)
1168 default: // unknown rolloff
1169 case 0: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1170 case 4: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1171 case 8: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1173 PutToDict(dict, "rolloff", tmp);
1174 switch(parm_inversion & 0x30)
1176 case 0: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1177 case 0x10: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1178 case 0x20: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1180 PutToDict(dict, "pilot", tmp);
1181 tmp = eDVBFrontendParametersSatellite::System_DVB_S2;
1184 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1186 PutToDict(dict, "modulation", eDVBFrontendParametersSatellite::Modulation_QPSK );
1187 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1189 PutToDict(dict, "system", tmp);
1193 static void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1196 #if HAVE_DVB_API_VERSION < 3
1197 PutToDict(dict, "frequency", parm_frequency);
1199 PutToDict(dict, "frequency", parm_frequency/1000);
1201 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1202 switch(parm_u_qam_fec_inner)
1204 case FEC_NONE: tmp = eDVBFrontendParametersCable::FEC_None; break;
1205 case FEC_1_2: tmp = eDVBFrontendParametersCable::FEC_1_2; break;
1206 case FEC_2_3: tmp = eDVBFrontendParametersCable::FEC_2_3; break;
1207 case FEC_3_4: tmp = eDVBFrontendParametersCable::FEC_3_4; break;
1208 case FEC_5_6: tmp = eDVBFrontendParametersCable::FEC_5_6; break;
1209 case FEC_7_8: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1210 #if HAVE_DVB_API_VERSION >= 3
1211 case FEC_8_9: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1214 case FEC_AUTO: tmp = eDVBFrontendParametersCable::FEC_Auto; break;
1216 PutToDict(dict, "fec_inner", tmp);
1217 switch(parm_u_qam_modulation)
1219 case QAM_16: tmp = eDVBFrontendParametersCable::Modulation_QAM16; break;
1220 case QAM_32: tmp = eDVBFrontendParametersCable::Modulation_QAM32; break;
1221 case QAM_64: tmp = eDVBFrontendParametersCable::Modulation_QAM64; break;
1222 case QAM_128: tmp = eDVBFrontendParametersCable::Modulation_QAM128; break;
1223 case QAM_256: tmp = eDVBFrontendParametersCable::Modulation_QAM256; break;
1225 case QAM_AUTO: tmp = eDVBFrontendParametersCable::Modulation_Auto; break;
1227 PutToDict(dict, "modulation", tmp);
1230 static void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1233 PutToDict(dict, "frequency", parm_frequency);
1234 switch (parm_u_ofdm_bandwidth)
1236 case BANDWIDTH_8_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_8MHz; break;
1237 case BANDWIDTH_7_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_7MHz; break;
1238 case BANDWIDTH_6_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_6MHz; break;
1240 case BANDWIDTH_AUTO: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_Auto; break;
1242 PutToDict(dict, "bandwidth", tmp);
1243 switch (parm_u_ofdm_code_rate_LP)
1245 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1246 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1247 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1248 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1249 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1251 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1253 PutToDict(dict, "code_rate_lp", tmp);
1254 switch (parm_u_ofdm_code_rate_HP)
1256 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1257 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1258 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1259 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1260 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1262 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1264 PutToDict(dict, "code_rate_hp", tmp);
1265 switch (parm_u_ofdm_constellation)
1267 case QPSK: tmp = eDVBFrontendParametersTerrestrial::Modulation_QPSK; break;
1268 case QAM_16: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM16; break;
1269 case QAM_64: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM64; break;
1271 case QAM_AUTO: tmp = eDVBFrontendParametersTerrestrial::Modulation_Auto; break;
1273 PutToDict(dict, "constellation", tmp);
1274 switch (parm_u_ofdm_transmission_mode)
1276 case TRANSMISSION_MODE_2K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_2k; break;
1277 case TRANSMISSION_MODE_8K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_8k; break;
1279 case TRANSMISSION_MODE_AUTO: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto; break;
1281 PutToDict(dict, "transmission_mode", tmp);
1282 switch (parm_u_ofdm_guard_interval)
1284 case GUARD_INTERVAL_1_32: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_32; break;
1285 case GUARD_INTERVAL_1_16: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_16; break;
1286 case GUARD_INTERVAL_1_8: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_8; break;
1287 case GUARD_INTERVAL_1_4: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_4; break;
1289 case GUARD_INTERVAL_AUTO: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_Auto; break;
1291 PutToDict(dict, "guard_interval", tmp);
1292 switch (parm_u_ofdm_hierarchy_information)
1294 case HIERARCHY_NONE: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_None; break;
1295 case HIERARCHY_1: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_1; break;
1296 case HIERARCHY_2: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_2; break;
1297 case HIERARCHY_4: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_4; break;
1299 case HIERARCHY_AUTO: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_Auto; break;
1301 PutToDict(dict, "hierarchy_information", tmp);
1304 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1306 if (dest && PyDict_Check(dest))
1308 const char *tmp = "UNKNOWN";
1329 PutToDict(dest, "tuner_state", tmp);
1330 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1331 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1332 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1333 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1334 int sigQualitydB = readFrontendData(signalQualitydB);
1335 if (sigQualitydB == 0x12345678) // not support yet
1337 ePyObject obj=Py_None;
1339 PutToDict(dest, "tuner_signal_quality_db", obj);
1342 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1343 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1347 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1349 if (dest && PyDict_Check(dest))
1351 FRONTENDPARAMETERS front;
1352 #if HAVE_DVB_API_VERSION >= 5
1353 struct dtv_property p[4];
1354 struct dtv_properties cmdseq;
1357 p[0].cmd = DTV_DELIVERY_SYSTEM;
1358 p[1].cmd = DTV_MODULATION;
1359 p[2].cmd = DTV_ROLLOFF;
1360 p[3].cmd = DTV_PILOT;
1362 if (m_simulate || m_fd == -1 || original)
1364 #if HAVE_DVB_API_VERSION >= 5
1365 else if (m_type == feSatellite && // yet just use new api for DVB-S(2) only
1366 ioctl(m_fd, FE_GET_PROPERTY, &cmdseq)<0)
1368 eDebug("FE_GET_PROPERTY failed (%m)");
1372 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1374 eDebug("FE_GET_FRONTEND failed (%m)");
1382 PutSatelliteDataToDict(dest, oparm.sat);
1385 PutCableDataToDict(dest, oparm.cab);
1388 PutTerrestrialDataToDict(dest, oparm.ter);
1394 FRONTENDPARAMETERS &parm = front;
1395 long tmp = eDVBFrontendParametersSatellite::Inversion_Unknown;
1396 switch(parm_inversion & 3)
1399 tmp = eDVBFrontendParametersSatellite::Inversion_On;
1402 tmp = eDVBFrontendParametersSatellite::Inversion_Off;
1406 PutToDict(dest, "inversion", tmp);
1410 #if HAVE_DVB_API_VERSION >= 5
1411 fillDictWithSatelliteData(dest, parm, p, m_data[FREQ_OFFSET], oparm.sat.orbital_position, oparm.sat.polarisation);
1413 fillDictWithSatelliteData(dest, parm, m_data[FREQ_OFFSET], oparm.sat.orbital_position, oparm.sat.polarisation);
1417 fillDictWithCableData(dest, parm);
1420 fillDictWithTerrestrialData(dest, parm);
1427 void eDVBFrontend::getFrontendData(ePyObject dest)
1429 if (dest && PyDict_Check(dest))
1432 PutToDict(dest, "tuner_number", m_slotid);
1448 PutToDict(dest, "tuner_type", tmp);
1452 #ifndef FP_IOCTL_GET_ID
1453 #define FP_IOCTL_GET_ID 0
1455 int eDVBFrontend::readInputpower()
1459 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1461 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1462 FILE *f=fopen(proc_name, "r");
1465 if (fscanf(f, "%d", &power) != 1)
1466 eDebug("read %s failed!! (%m)", proc_name);
1468 eDebug("%s is %d\n", proc_name, power);
1473 // open front prozessor
1474 int fp=::open("/dev/dbox/fp0", O_RDWR);
1477 eDebug("couldn't open fp");
1480 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1481 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1483 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1492 bool eDVBFrontend::setSecSequencePos(int steps)
1494 eDebugNoSimulate("set sequence pos %d", steps);
1499 if (m_sec_sequence.current() != m_sec_sequence.end())
1500 ++m_sec_sequence.current();
1505 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1506 --m_sec_sequence.current();
1512 void eDVBFrontend::tuneLoop()
1517 int eDVBFrontend::tuneLoopInt() // called by m_tuneTimer
1520 eDVBFrontend *sec_fe = this;
1521 eDVBRegisteredFrontend *regFE = 0;
1522 long tmp = m_data[LINKED_PREV_PTR];
1525 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1526 sec_fe = prev->m_frontend;
1527 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1528 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1529 int state = sec_fe->m_state;
1530 // workaround to put the kernel frontend thread into idle state!
1531 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1533 sec_fe->closeFrontend(true);
1534 state = sec_fe->m_state;
1536 // sec_fe is closed... we must reopen it here..
1537 if (state == stateClosed)
1545 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1547 long *sec_fe_data = sec_fe->m_data;
1548 // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1550 switch (m_sec_sequence.current()->cmd)
1552 case eSecCommand::SLEEP:
1553 delay = m_sec_sequence.current()++->msec;
1554 eDebugNoSimulate("[SEC] sleep %dms", delay);
1556 case eSecCommand::GOTO:
1557 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1558 ++m_sec_sequence.current();
1560 case eSecCommand::SET_VOLTAGE:
1562 int voltage = m_sec_sequence.current()++->voltage;
1563 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1564 sec_fe->setVoltage(voltage);
1567 case eSecCommand::IF_VOLTAGE_GOTO:
1569 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1570 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1572 ++m_sec_sequence.current();
1575 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1577 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1578 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1580 ++m_sec_sequence.current();
1583 case eSecCommand::IF_TONE_GOTO:
1585 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1586 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1588 ++m_sec_sequence.current();
1591 case eSecCommand::IF_NOT_TONE_GOTO:
1593 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1594 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1596 ++m_sec_sequence.current();
1599 case eSecCommand::SET_TONE:
1600 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1601 sec_fe->setTone(m_sec_sequence.current()++->tone);
1603 case eSecCommand::SEND_DISEQC:
1604 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1605 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1606 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1607 eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1608 if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
1609 eDebugNoSimulate("(DiSEqC reset)");
1610 else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
1611 eDebugNoSimulate("(DiSEqC peripherial power on)");
1613 eDebugNoSimulate("");
1614 ++m_sec_sequence.current();
1616 case eSecCommand::SEND_TONEBURST:
1617 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1618 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1620 case eSecCommand::SET_FRONTEND:
1622 int enableEvents = (m_sec_sequence.current()++)->val;
1623 eDebugNoSimulate("[SEC] setFrontend %d", enableEvents);
1624 setFrontend(enableEvents);
1627 case eSecCommand::START_TUNE_TIMEOUT:
1629 int tuneTimeout = m_sec_sequence.current()->timeout;
1630 eDebugNoSimulate("[SEC] startTuneTimeout %d", tuneTimeout);
1632 m_timeout->start(tuneTimeout, 1);
1633 ++m_sec_sequence.current();
1636 case eSecCommand::SET_TIMEOUT:
1637 m_timeoutCount = m_sec_sequence.current()++->val;
1638 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1640 case eSecCommand::IF_TIMEOUT_GOTO:
1641 if (!m_timeoutCount)
1643 eDebugNoSimulate("[SEC] rotor timout");
1644 setSecSequencePos(m_sec_sequence.current()->steps);
1647 ++m_sec_sequence.current();
1649 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1651 int idx = m_sec_sequence.current()++->val;
1652 if ( idx == 0 || idx == 1 )
1654 m_idleInputpower[idx] = sec_fe->readInputpower();
1655 eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1658 eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1661 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1663 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1664 int idx = compare.val;
1665 if ( !m_simulate && (idx == 0 || idx == 1) )
1667 int idle = sec_fe->readInputpower();
1668 int diff = abs(idle-m_idleInputpower[idx]);
1671 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1672 setSecSequencePos(compare.steps);
1676 ++m_sec_sequence.current();
1679 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1681 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1684 setSecSequencePos(cmd.steps);
1688 int isLocked = readFrontendData(locked);
1689 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1691 if (!m_timeoutCount && m_retryCount > 0)
1693 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 40) || !cmd.lastSignal))
1696 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1699 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1701 cmd.lastSignal = signal;
1704 if (cmd.okcount > 4)
1706 eDebugNoSimulate("ok > 4 .. goto %d\n", cmd.steps);
1707 setSecSequencePos(cmd.steps);
1708 m_state = stateLock;
1709 m_stateChanged(this);
1710 feEvent(-1); // flush events
1718 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1720 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1724 ++m_sec_sequence.current();
1727 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1728 m_runningInputpower = sec_fe->readInputpower();
1729 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1730 ++m_sec_sequence.current();
1732 case eSecCommand::SET_ROTOR_MOVING:
1734 m_sec->setRotorMoving(m_slotid, true);
1735 ++m_sec_sequence.current();
1737 case eSecCommand::SET_ROTOR_STOPPED:
1739 m_sec->setRotorMoving(m_slotid, false);
1740 ++m_sec_sequence.current();
1742 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1744 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1747 setSecSequencePos(cmd.steps);
1750 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1751 const char *txt = cmd.direction ? "running" : "stopped";
1753 if (!m_timeoutCount && m_retryCount > 0)
1755 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1757 m_runningInputpower,
1760 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1761 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1764 eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1765 if ( cmd.okcount > 6 )
1767 eDebugNoSimulate("[SEC] rotor is %s", txt);
1768 if (setSecSequencePos(cmd.steps))
1774 eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1777 ++m_sec_sequence.current();
1780 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1781 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1782 setSecSequencePos(m_sec_sequence.current()->steps);
1784 ++m_sec_sequence.current();
1786 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1787 eDebugNoSimulate("[SEC] invalidate current switch params");
1788 sec_fe_data[CSW] = -1;
1789 sec_fe_data[UCSW] = -1;
1790 sec_fe_data[TONEBURST] = -1;
1791 ++m_sec_sequence.current();
1793 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1794 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1795 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1796 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1797 eDebugNoSimulate("[SEC] update current switch params");
1798 ++m_sec_sequence.current();
1800 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1801 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1802 sec_fe_data[ROTOR_CMD] = -1;
1803 sec_fe_data[ROTOR_POS] = -1;
1804 ++m_sec_sequence.current();
1806 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1807 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1808 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1809 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1810 ++m_sec_sequence.current();
1812 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1813 m_retryCount = m_sec_sequence.current()++->val;
1814 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1816 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1819 eDebugNoSimulate("[SEC] no more rotor retrys");
1820 setSecSequencePos(m_sec_sequence.current()->steps);
1823 ++m_sec_sequence.current();
1825 case eSecCommand::SET_POWER_LIMITING_MODE:
1830 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1831 FILE *f=fopen(proc_name, "w");
1832 if (f) // new interface exist?
1834 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1835 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1836 eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1838 eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1841 else if (sec_fe->m_need_rotor_workaround)
1844 int slotid = sec_fe->m_slotid;
1845 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1847 sprintf(dev, "/dev/i2c/%d", slotid);
1848 else if (slotid == 2)
1849 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1850 else if (slotid == 3)
1851 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1852 int fd = ::open(dev, O_RDWR);
1854 unsigned char data[2];
1855 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1856 if(::read(fd, data, 1) != 1)
1857 eDebugNoSimulate("[SEC] error read lnbp (%m)");
1858 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1860 data[0] |= 0x80; // enable static current limiting
1861 eDebugNoSimulate("[SEC] set static current limiting");
1865 data[0] &= ~0x80; // enable dynamic current limiting
1866 eDebugNoSimulate("[SEC] set dynamic current limiting");
1868 if(::write(fd, data, 1) != 1)
1869 eDebugNoSimulate("[SEC] error write lnbp (%m)");
1873 ++m_sec_sequence.current();
1876 case eSecCommand::DELAYED_CLOSE_FRONTEND:
1878 eDebugNoSimulate("[SEC] delayed close frontend");
1879 closeFrontend(false, true);
1880 ++m_sec_sequence.current();
1884 eDebugNoSimulate("[SEC] unhandled sec command %d",
1885 ++m_sec_sequence.current()->cmd);
1886 ++m_sec_sequence.current();
1889 m_tuneTimer->start(delay,true);
1893 if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1898 void eDVBFrontend::setFrontend(bool recvEvents)
1902 eDebug("setting frontend %d", m_dvbid);
1905 feEvent(-1); // flush events
1906 #if HAVE_DVB_API_VERSION >= 5
1907 if (m_type == iDVBFrontend::feSatellite)
1909 fe_rolloff_t rolloff = ROLLOFF_35;
1910 fe_pilot_t pilot = PILOT_OFF;
1911 fe_modulation_t modulation = QPSK;
1912 fe_delivery_system_t system = SYS_DVBS;
1913 switch(oparm.sat.system)
1915 case eDVBFrontendParametersSatellite::System_DVB_S: system = SYS_DVBS; break;
1916 case eDVBFrontendParametersSatellite::System_DVB_S2: system = SYS_DVBS2; break;
1918 switch(oparm.sat.modulation)
1920 case eDVBFrontendParametersSatellite::Modulation_QPSK: modulation = QPSK; break;
1921 case eDVBFrontendParametersSatellite::Modulation_8PSK: modulation = PSK_8; break;
1922 case eDVBFrontendParametersSatellite::Modulation_QAM16: modulation = QAM_16; break;
1924 switch(oparm.sat.pilot)
1926 case eDVBFrontendParametersSatellite::Pilot_Off: pilot = PILOT_OFF; break;
1927 case eDVBFrontendParametersSatellite::Pilot_On: pilot = PILOT_ON; break;
1928 case eDVBFrontendParametersSatellite::Pilot_Unknown: pilot = PILOT_AUTO; break;
1930 switch(oparm.sat.rolloff)
1932 case eDVBFrontendParametersSatellite::RollOff_alpha_0_20: rolloff = ROLLOFF_20; break;
1933 case eDVBFrontendParametersSatellite::RollOff_alpha_0_25: rolloff = ROLLOFF_25; break;
1934 case eDVBFrontendParametersSatellite::RollOff_alpha_0_35: rolloff = ROLLOFF_35; break;
1936 struct dtv_property p[10];
1937 struct dtv_properties cmdseq;
1939 p[0].cmd = DTV_CLEAR;
1940 p[1].cmd = DTV_DELIVERY_SYSTEM, p[1].u.data = system;
1941 p[2].cmd = DTV_FREQUENCY, p[2].u.data = parm_frequency;
1942 p[3].cmd = DTV_MODULATION, p[3].u.data = modulation;
1943 p[4].cmd = DTV_SYMBOL_RATE, p[4].u.data = parm_u_qpsk_symbol_rate;
1944 p[5].cmd = DTV_INNER_FEC, p[5].u.data = parm_u_qpsk_fec_inner;
1945 p[6].cmd = DTV_INVERSION, p[6].u.data = parm_inversion;
1946 if (system == SYS_DVBS2)
1948 p[7].cmd = DTV_ROLLOFF, p[7].u.data = rolloff;
1949 p[8].cmd = DTV_PILOT, p[8].u.data = pilot;
1950 p[9].cmd = DTV_TUNE;
1955 p[7].cmd = DTV_TUNE;
1958 if (ioctl(m_fd, FE_SET_PROPERTY, &cmdseq) == -1)
1960 perror("FE_SET_PROPERTY failed");
1967 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1969 perror("FE_SET_FRONTEND failed");
1976 RESULT eDVBFrontend::getFrontendType(int &t)
1984 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1989 eWarning("no SEC module active!");
1992 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1995 #if HAVE_DVB_API_VERSION >= 3
1996 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",
1999 feparm.polarisation,
2003 feparm.orbital_position,
2009 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
2012 feparm.polarisation,
2016 feparm.orbital_position);
2018 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
2019 switch (feparm.inversion)
2021 case eDVBFrontendParametersSatellite::Inversion_On:
2022 parm_inversion = INVERSION_ON;
2024 case eDVBFrontendParametersSatellite::Inversion_Off:
2025 parm_inversion = INVERSION_OFF;
2028 case eDVBFrontendParametersSatellite::Inversion_Unknown:
2029 parm_inversion = INVERSION_AUTO;
2032 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S)
2036 case eDVBFrontendParametersSatellite::FEC_None:
2037 parm_u_qpsk_fec_inner = FEC_NONE;
2039 case eDVBFrontendParametersSatellite::FEC_1_2:
2040 parm_u_qpsk_fec_inner = FEC_1_2;
2042 case eDVBFrontendParametersSatellite::FEC_2_3:
2043 parm_u_qpsk_fec_inner = FEC_2_3;
2045 case eDVBFrontendParametersSatellite::FEC_3_4:
2046 parm_u_qpsk_fec_inner = FEC_3_4;
2048 case eDVBFrontendParametersSatellite::FEC_5_6:
2049 parm_u_qpsk_fec_inner = FEC_5_6;
2051 case eDVBFrontendParametersSatellite::FEC_7_8:
2052 parm_u_qpsk_fec_inner = FEC_7_8;
2055 eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
2056 case eDVBFrontendParametersSatellite::FEC_Auto:
2057 parm_u_qpsk_fec_inner = FEC_AUTO;
2061 #if HAVE_DVB_API_VERSION >= 3
2066 case eDVBFrontendParametersSatellite::FEC_1_2:
2067 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
2069 case eDVBFrontendParametersSatellite::FEC_2_3:
2070 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
2072 case eDVBFrontendParametersSatellite::FEC_3_4:
2073 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
2075 case eDVBFrontendParametersSatellite::FEC_3_5:
2076 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
2078 case eDVBFrontendParametersSatellite::FEC_4_5:
2079 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
2081 case eDVBFrontendParametersSatellite::FEC_5_6:
2082 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
2084 case eDVBFrontendParametersSatellite::FEC_7_8:
2085 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
2087 case eDVBFrontendParametersSatellite::FEC_8_9:
2088 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
2090 case eDVBFrontendParametersSatellite::FEC_9_10:
2091 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
2094 eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
2097 #if HAVE_DVB_API_VERSION < 5
2098 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
2099 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
2100 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation_8PSK)
2102 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
2103 // 8PSK fec driver values are decimal 9 bigger
2108 // FIXME !!! get frequency range from tuner
2109 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
2111 eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
2114 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
2120 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
2122 #if HAVE_DVB_API_VERSION < 3
2123 parm_frequency = feparm.frequency;
2125 parm_frequency = feparm.frequency * 1000;
2127 parm_u_qam_symbol_rate = feparm.symbol_rate;
2128 switch (feparm.modulation)
2130 case eDVBFrontendParametersCable::Modulation_QAM16:
2131 parm_u_qam_modulation = QAM_16;
2133 case eDVBFrontendParametersCable::Modulation_QAM32:
2134 parm_u_qam_modulation = QAM_32;
2136 case eDVBFrontendParametersCable::Modulation_QAM64:
2137 parm_u_qam_modulation = QAM_64;
2139 case eDVBFrontendParametersCable::Modulation_QAM128:
2140 parm_u_qam_modulation = QAM_128;
2142 case eDVBFrontendParametersCable::Modulation_QAM256:
2143 parm_u_qam_modulation = QAM_256;
2146 case eDVBFrontendParametersCable::Modulation_Auto:
2147 parm_u_qam_modulation = QAM_AUTO;
2150 switch (feparm.inversion)
2152 case eDVBFrontendParametersCable::Inversion_On:
2153 parm_inversion = INVERSION_ON;
2155 case eDVBFrontendParametersCable::Inversion_Off:
2156 parm_inversion = INVERSION_OFF;
2159 case eDVBFrontendParametersCable::Inversion_Unknown:
2160 parm_inversion = INVERSION_AUTO;
2163 switch (feparm.fec_inner)
2165 case eDVBFrontendParametersCable::FEC_None:
2166 parm_u_qam_fec_inner = FEC_NONE;
2168 case eDVBFrontendParametersCable::FEC_1_2:
2169 parm_u_qam_fec_inner = FEC_1_2;
2171 case eDVBFrontendParametersCable::FEC_2_3:
2172 parm_u_qam_fec_inner = FEC_2_3;
2174 case eDVBFrontendParametersCable::FEC_3_4:
2175 parm_u_qam_fec_inner = FEC_3_4;
2177 case eDVBFrontendParametersCable::FEC_5_6:
2178 parm_u_qam_fec_inner = FEC_5_6;
2180 case eDVBFrontendParametersCable::FEC_7_8:
2181 parm_u_qam_fec_inner = FEC_7_8;
2183 #if HAVE_DVB_API_VERSION >= 3
2184 case eDVBFrontendParametersCable::FEC_8_9:
2185 parm_u_qam_fec_inner = FEC_8_9;
2189 case eDVBFrontendParametersCable::FEC_Auto:
2190 parm_u_qam_fec_inner = FEC_AUTO;
2193 eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
2194 parm_frequency/1000,
2195 parm_u_qam_symbol_rate,
2196 parm_u_qam_fec_inner,
2197 parm_u_qam_modulation,
2203 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
2205 parm_frequency = feparm.frequency;
2207 switch (feparm.bandwidth)
2209 case eDVBFrontendParametersTerrestrial::Bandwidth_8MHz:
2210 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
2212 case eDVBFrontendParametersTerrestrial::Bandwidth_7MHz:
2213 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
2215 case eDVBFrontendParametersTerrestrial::Bandwidth_6MHz:
2216 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
2219 case eDVBFrontendParametersTerrestrial::Bandwidth_Auto:
2220 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
2223 switch (feparm.code_rate_LP)
2225 case eDVBFrontendParametersTerrestrial::FEC_1_2:
2226 parm_u_ofdm_code_rate_LP = FEC_1_2;
2228 case eDVBFrontendParametersTerrestrial::FEC_2_3:
2229 parm_u_ofdm_code_rate_LP = FEC_2_3;
2231 case eDVBFrontendParametersTerrestrial::FEC_3_4:
2232 parm_u_ofdm_code_rate_LP = FEC_3_4;
2234 case eDVBFrontendParametersTerrestrial::FEC_5_6:
2235 parm_u_ofdm_code_rate_LP = FEC_5_6;
2237 case eDVBFrontendParametersTerrestrial::FEC_7_8:
2238 parm_u_ofdm_code_rate_LP = FEC_7_8;
2241 case eDVBFrontendParametersTerrestrial::FEC_Auto:
2242 parm_u_ofdm_code_rate_LP = FEC_AUTO;
2245 switch (feparm.code_rate_HP)
2247 case eDVBFrontendParametersTerrestrial::FEC_1_2:
2248 parm_u_ofdm_code_rate_HP = FEC_1_2;
2250 case eDVBFrontendParametersTerrestrial::FEC_2_3:
2251 parm_u_ofdm_code_rate_HP = FEC_2_3;
2253 case eDVBFrontendParametersTerrestrial::FEC_3_4:
2254 parm_u_ofdm_code_rate_HP = FEC_3_4;
2256 case eDVBFrontendParametersTerrestrial::FEC_5_6:
2257 parm_u_ofdm_code_rate_HP = FEC_5_6;
2259 case eDVBFrontendParametersTerrestrial::FEC_7_8:
2260 parm_u_ofdm_code_rate_HP = FEC_7_8;
2263 case eDVBFrontendParametersTerrestrial::FEC_Auto:
2264 parm_u_ofdm_code_rate_HP = FEC_AUTO;
2267 switch (feparm.modulation)
2269 case eDVBFrontendParametersTerrestrial::Modulation_QPSK:
2270 parm_u_ofdm_constellation = QPSK;
2272 case eDVBFrontendParametersTerrestrial::Modulation_QAM16:
2273 parm_u_ofdm_constellation = QAM_16;
2275 case eDVBFrontendParametersTerrestrial::Modulation_QAM64:
2276 parm_u_ofdm_constellation = QAM_64;
2279 case eDVBFrontendParametersTerrestrial::Modulation_Auto:
2280 parm_u_ofdm_constellation = QAM_AUTO;
2283 switch (feparm.transmission_mode)
2285 case eDVBFrontendParametersTerrestrial::TransmissionMode_2k:
2286 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2288 case eDVBFrontendParametersTerrestrial::TransmissionMode_8k:
2289 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2292 case eDVBFrontendParametersTerrestrial::TransmissionMode_Auto:
2293 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2296 switch (feparm.guard_interval)
2298 case eDVBFrontendParametersTerrestrial::GuardInterval_1_32:
2299 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2301 case eDVBFrontendParametersTerrestrial::GuardInterval_1_16:
2302 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2304 case eDVBFrontendParametersTerrestrial::GuardInterval_1_8:
2305 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2307 case eDVBFrontendParametersTerrestrial::GuardInterval_1_4:
2308 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2311 case eDVBFrontendParametersTerrestrial::GuardInterval_Auto:
2312 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2315 switch (feparm.hierarchy)
2317 case eDVBFrontendParametersTerrestrial::Hierarchy_None:
2318 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2320 case eDVBFrontendParametersTerrestrial::Hierarchy_1:
2321 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2323 case eDVBFrontendParametersTerrestrial::Hierarchy_2:
2324 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2326 case eDVBFrontendParametersTerrestrial::Hierarchy_4:
2327 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2330 case eDVBFrontendParametersTerrestrial::Hierarchy_Auto:
2331 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2334 switch (feparm.inversion)
2336 case eDVBFrontendParametersTerrestrial::Inversion_On:
2337 parm_inversion = INVERSION_ON;
2339 case eDVBFrontendParametersTerrestrial::Inversion_Off:
2340 parm_inversion = INVERSION_OFF;
2343 case eDVBFrontendParametersTerrestrial::Inversion_Unknown:
2344 parm_inversion = INVERSION_AUTO;
2351 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2353 unsigned int timeout = 5000;
2354 eDebugNoSimulate("(%d)tune", m_dvbid);
2360 if (!m_sn && !m_simulate)
2362 eDebug("no frontend device opened... do not try to tune !!!");
2376 m_sec_sequence.clear();
2378 where.calcLockTimeout(timeout);
2384 eDVBFrontendParametersSatellite feparm;
2385 if (where.getDVBS(feparm))
2387 eDebug("no dvbs data!");
2391 if (m_rotor_mode != feparm.no_rotor_command_on_tune && !feparm.no_rotor_command_on_tune)
2393 eDVBFrontend *sec_fe = this;
2394 long tmp = m_data[LINKED_PREV_PTR];
2397 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
2398 sec_fe = linked_fe->m_frontend;
2399 sec_fe->getData(LINKED_NEXT_PTR, tmp);
2401 eDebug("(fe%d) reset diseqc after leave rotor mode!", m_dvbid);
2402 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
2404 m_rotor_mode = feparm.no_rotor_command_on_tune;
2406 m_sec->setRotorMoving(m_slotid, false);
2407 res=prepare_sat(feparm, timeout);
2415 eDVBFrontendParametersCable feparm;
2416 if (where.getDVBC(feparm))
2421 res=prepare_cable(feparm);
2425 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2426 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2431 eDVBFrontendParametersTerrestrial feparm;
2432 if (where.getDVBT(feparm))
2434 eDebug("no -T data");
2438 res=prepare_terrestrial(feparm);
2442 std::string enable_5V;
2443 char configStr[255];
2444 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2445 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2446 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2447 if (enable_5V == "True")
2448 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2450 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2451 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2457 m_sec_sequence.current() = m_sec_sequence.begin();
2461 m_tuneTimer->start(0,true);
2463 if (m_state != stateTuning)
2465 m_state = stateTuning;
2466 m_stateChanged(this);
2475 m_tuneTimer->stop();
2479 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2481 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2485 RESULT eDVBFrontend::setVoltage(int voltage)
2487 if (m_type == feCable)
2489 #if HAVE_DVB_API_VERSION < 3
2492 bool increased=false;
2493 fe_sec_voltage_t vlt;
2495 m_data[CUR_VOLTAGE]=voltage;
2499 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2500 vlt = SEC_VOLTAGE_OFF;
2503 #if HAVE_DVB_API_VERSION < 3
2504 vlt = SEC_VOLTAGE_13_5;
2510 vlt = SEC_VOLTAGE_13;
2513 #if HAVE_DVB_API_VERSION < 3
2514 vlt = SEC_VOLTAGE_18_5;
2520 vlt = SEC_VOLTAGE_18;
2527 #if HAVE_DVB_API_VERSION < 3
2528 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2530 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2531 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2532 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2536 RESULT eDVBFrontend::getState(int &state)
2542 RESULT eDVBFrontend::setTone(int t)
2544 if (m_type != feSatellite)
2546 #if HAVE_DVB_API_VERSION < 3
2549 fe_sec_tone_mode_t tone;
2558 tone = SEC_TONE_OFF;
2565 #if HAVE_DVB_API_VERSION < 3
2566 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2568 return ::ioctl(m_fd, FE_SET_TONE, tone);
2572 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2573 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2576 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2580 #if HAVE_DVB_API_VERSION < 3
2581 struct secCommand cmd;
2582 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2583 cmd.u.diseqc.cmdtype = diseqc.data[0];
2584 cmd.u.diseqc.addr = diseqc.data[1];
2585 cmd.u.diseqc.cmd = diseqc.data[2];
2586 cmd.u.diseqc.numParams = diseqc.len-3;
2587 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2588 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2590 struct dvb_diseqc_master_cmd cmd;
2591 memcpy(cmd.msg, diseqc.data, diseqc.len);
2592 cmd.msg_len = diseqc.len;
2593 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2599 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2600 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2602 RESULT eDVBFrontend::sendToneburst(int burst)
2606 #if HAVE_DVB_API_VERSION < 3
2607 secMiniCmd cmd = SEC_MINI_NONE;
2609 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2611 if ( burst == eDVBSatelliteDiseqcParameters::A )
2613 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2615 #if HAVE_DVB_API_VERSION < 3
2616 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2619 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2625 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2631 RESULT eDVBFrontend::setSecSequence(eSecCommandList &list)
2633 if (m_data[SATCR] != -1 && m_sec_sequence.current() != m_sec_sequence.end())
2634 m_sec_sequence.push_back(list);
2636 m_sec_sequence = list;
2640 RESULT eDVBFrontend::getData(int num, long &data)
2642 if ( num < NUM_DATA_ENTRIES )
2650 RESULT eDVBFrontend::setData(int num, long val)
2652 if ( num < NUM_DATA_ENTRIES )
2660 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2663 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2665 if (m_type == eDVBFrontend::feSatellite)
2668 eDVBFrontendParametersSatellite sat_parm;
2669 int ret = feparm->getDVBS(sat_parm);
2671 if (sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S2 && !m_can_handle_dvbs2)
2673 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2674 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S && m_can_handle_dvbs2)
2678 else if (m_type == eDVBFrontend::feCable)
2679 return 2; // more prio for cable frontends
2680 else if (m_type == eDVBFrontend::feTerrestrial)
2685 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2687 ePyObject Id, Descr, Enabled, IsDVBS2;
2688 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4)
2690 Id = PyTuple_GET_ITEM(obj, 0);
2691 Descr = PyTuple_GET_ITEM(obj, 1);
2692 Enabled = PyTuple_GET_ITEM(obj, 2);
2693 IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2694 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2))
2696 strcpy(m_description, PyString_AS_STRING(Descr));
2697 m_slotid = PyInt_AsLong(Id);
2698 m_enabled = Enabled == Py_True;
2699 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2700 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2701 !!strstr(m_description, "Alps BSBE2") ||
2702 !!strstr(m_description, "Alps -S") ||
2703 !!strstr(m_description, "BCM4501");
2704 m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2705 eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2706 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2709 PyErr_SetString(PyExc_StandardError,
2710 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");