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 #ifdef BUILD_VUPLUS /* ikseong */
498 int eDVBFrontend::openFrontend()
500 if (m_state != stateClosed)
501 return -1; // already opened
506 #if HAVE_DVB_API_VERSION < 3
507 FrontendInfo fe_info;
509 dvb_frontend_info fe_info;
511 eDebugNoSimulate("opening frontend %d", m_dvbid);
514 if (!m_simulate || m_type == -1)
516 m_fd = ::open(m_filename, O_RDWR|O_NONBLOCK);
519 eWarning("failed! (%s) %m", m_filename);
522 #ifdef BUILD_VUPLUS /* ikseong */
534 eWarning("frontend %d already opened", m_dvbid);
537 if (::ioctl(m_fd, FE_GET_INFO, &fe_info) < 0)
539 eWarning("ioctl FE_GET_INFO failed");
545 switch (fe_info.type)
548 m_type = iDVBFrontend::feSatellite;
551 m_type = iDVBFrontend::feCable;
554 m_type = iDVBFrontend::feTerrestrial;
557 eWarning("unknown frontend type.");
562 eDebugNoSimulate("detected %s frontend", "satellite\0cable\0 terrestrial"+fe_info.type*10);
565 #if HAVE_DVB_API_VERSION < 3
566 if (m_type == iDVBFrontend::feSatellite)
572 m_secfd = ::open(m_sec_filename, O_RDWR);
575 eWarning("failed! (%s) %m", m_sec_filename);
583 eWarning("sec %d already opened", m_dvbid);
587 setTone(iDVBFrontend::toneOff);
588 setVoltage(iDVBFrontend::voltageOff);
592 m_sn = eSocketNotifier::create(eApp, m_fd, eSocketNotifier::Read, false);
593 CONNECT(m_sn->activated, eDVBFrontend::feEvent);
599 int eDVBFrontend::closeFrontend(bool force)
601 if (!force && m_data[CUR_VOLTAGE] != -1 && m_data[CUR_VOLTAGE] != iDVBFrontend::voltageOff)
603 long tmp = m_data[LINKED_NEXT_PTR];
606 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
607 if (linked_fe->m_inuse)
609 eDebugNoSimulate("dont close frontend %d until the linked frontend %d in slot %d is still in use",
610 m_dvbid, linked_fe->m_frontend->getDVBID(), linked_fe->m_frontend->getSlotID());
613 linked_fe->m_frontend->getData(LINKED_NEXT_PTR, tmp);
619 eDebugNoSimulate("close frontend %d", m_dvbid);
620 if (m_data[SATCR] != -1)
622 turnOffSatCR(m_data[SATCR]);
624 setTone(iDVBFrontend::toneOff);
625 setVoltage(iDVBFrontend::voltageOff);
627 if (m_sec && !m_simulate)
628 m_sec->setRotorMoving(m_slotid, false);
632 eWarning("couldnt close frontend %d", m_dvbid);
636 setTone(iDVBFrontend::toneOff);
637 setVoltage(iDVBFrontend::voltageOff);
639 #if HAVE_DVB_API_VERSION < 3
642 if (!::close(m_secfd))
645 eWarning("couldnt close sec %d", m_dvbid);
649 m_state = stateClosed;
654 eDVBFrontend::~eDVBFrontend()
656 m_data[LINKED_PREV_PTR] = m_data[LINKED_NEXT_PTR] = -1;
660 void eDVBFrontend::feEvent(int w)
662 eDVBFrontend *sec_fe = this;
663 long tmp = m_data[LINKED_PREV_PTR];
666 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
667 sec_fe = linked_fe->m_frontend;
668 sec_fe->getData(LINKED_NEXT_PTR, tmp);
672 #if HAVE_DVB_API_VERSION < 3
675 dvb_frontend_event event;
679 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
681 if (res && (errno == EAGAIN))
687 #if HAVE_DVB_API_VERSION < 3
688 if (event.type == FE_COMPLETION_EV)
690 eDebug("(%d)fe event: status %x, inversion %s, m_tuning %d", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off", m_tuning);
691 if (event.status & FE_HAS_LOCK)
699 #if HAVE_DVB_API_VERSION >= 3
700 if (event.status & FE_TIMEDOUT) {
701 eDebug("FE_TIMEDOUT! ..abort");
714 eDebug("stateLostLock");
715 state = stateLostLock;
717 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
720 if (m_state != state)
723 m_stateChanged(this);
728 void eDVBFrontend::timeout()
731 if (m_state == stateTuning)
733 #ifdef BUILD_VUPLUS /* ikseong */
734 eDVBFrontend *sec_fe = this;
735 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
737 m_state = stateFailed;
738 m_stateChanged(this);
742 #define INRANGE(X,Y,Z) (((X<=Y) && (Y<=Z))||((Z<=Y) && (Y<=X)) ? 1 : 0)
744 /* unsigned 32 bit division */
745 static inline uint32_t fe_udiv(uint32_t a, uint32_t b)
747 return (a + b / 2) / b;
750 int eDVBFrontend::readFrontendData(int type)
759 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
760 eDebug("FE_READ_BER failed (%m)");
765 case signalQualitydB: /* this will move into the driver */
767 int sat_max = 1600; // for stv0288 / bsbe2
768 int ret = 0x12345678;
772 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
773 eDebug("FE_READ_SNR failed (%m)");
774 else if (!strcmp(m_description, "BCM4501 (internal)"))
776 float SDS_SNRE = snr << 16;
779 if (oparm.sat.system == eDVBFrontendParametersSatellite::System_DVB_S) // DVB-S1 / QPSK
781 static float SNR_COEFF[6] = {
784 197418.0 / 4194304.0,
785 -2602183.0 / 4194304.0,
786 20377212.0 / 4194304.0,
787 -37791203.0 / 4194304.0,
789 float fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0)),
790 fval2 = pow(10.0, fval1)-1;
791 fval1 = 10.0 * log10(fval2);
795 fval2 = SNR_COEFF[0];
796 for (int i=1; i<6; ++i)
799 fval2 += SNR_COEFF[i];
805 #if HAVE_DVB_API_VERSION >= 3
808 float fval1 = SDS_SNRE / 268435456.0,
811 if (parm_u_qpsk_fec_inner <= FEC_S2_QPSK_9_10) // DVB-S2 QPSK
822 fval4 = -10.0 * log10(fval1);
824 for (int i=0; i < 5; ++i)
825 fval1 = fval4 - fval2 * log10(1.0+pow(10.0, (fval3-fval1)/fval2));
830 ret = (int)(snr_in_db * 100);
832 else if (strstr(m_description, "Alps BSBE1 C01A") ||
833 strstr(m_description, "Alps -S(STV0288)"))
837 else if (snr == 0xFFFF) // i think this should not happen
841 enum { REALVAL, REGVAL };
842 const long CN_lookup[31][2] = {
843 {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
844 {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
845 {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
846 {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
847 {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
848 {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
851 int add=strchr(m_description, '.') ? 0xA250 : 0xA100;
852 long regval = 0xFFFF - ((snr / 3) + add), // revert some dvb api calulations to get the real register value
856 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
861 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[i][REGVAL]))
866 ret = (((regval - CN_lookup[Imin][REGVAL])
867 * (CN_lookup[Imax][REALVAL] - CN_lookup[Imin][REALVAL])
868 / (CN_lookup[Imax][REGVAL] - CN_lookup[Imin][REGVAL]))
869 + CN_lookup[Imin][REALVAL]) * 10;
875 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
876 !strcmp(m_description, "Alps -S") ||
877 !strcmp(m_description, "Philips -S") ||
878 !strcmp(m_description, "LG -S") )
881 ret = (int)((snr-39075)/17.647);
882 } else if (!strcmp(m_description, "Alps BSBE2"))
884 ret = (int)((snr >> 7) * 10);
885 } else if (!strcmp(m_description, "Philips CU1216Mk3"))
887 int mse = (~snr) & 0xFF;
888 switch (parm_u_qam_modulation) {
889 case QAM_16: ret = fe_udiv(1950000, (32 * mse) + 138) + 1000; break;
890 case QAM_32: ret = fe_udiv(2150000, (40 * mse) + 500) + 1350; break;
891 case QAM_64: ret = fe_udiv(2100000, (40 * mse) + 500) + 1250; break;
892 case QAM_128: ret = fe_udiv(1850000, (38 * mse) + 400) + 1380; break;
893 case QAM_256: ret = fe_udiv(1800000, (100 * mse) + 40) + 2030; break;
896 } else if (!strcmp(m_description, "Philips TU1216"))
898 snr = 0xFF - (snr & 0xFF);
900 ret = 10 * (int)(-100 * (log10(snr) - log10(255)));
902 else if (strstr(m_description, "BCM4506") || strstr(m_description, "BCM4505"))
903 ret = (snr * 100) >> 8;
905 if (type == signalQuality)
907 if (ret == 0x12345678) // no snr db calculation avail.. return untouched snr value..
912 return ret >= sat_max ? 65536 : ret * 65536 / sat_max;
913 case feCable: // we assume a max of 42db here
914 return ret >= 4200 ? 65536 : ret * 65536 / 4200;
915 case feTerrestrial: // we assume a max of 24db here
916 return ret >= 2400 ? 65536 : ret * 65536 / 2400;
920 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
928 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
929 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
935 #if HAVE_DVB_API_VERSION < 3
936 FrontendStatus status=0;
942 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
943 eDebug("FE_READ_STATUS failed (%m)");
944 return !!(status&FE_HAS_LOCK);
950 #if HAVE_DVB_API_VERSION < 3
951 FrontendStatus status=0;
957 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
958 eDebug("FE_READ_STATUS failed (%m)");
959 return !!(status&FE_HAS_SYNC);
969 void PutToDict(ePyObject &dict, const char*key, long value)
971 ePyObject item = PyInt_FromLong(value);
974 if (PyDict_SetItemString(dict, key, item))
975 eDebug("put %s to dict failed", key);
979 eDebug("could not create PyObject for %s", key);
982 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
986 if (PyDict_SetItemString(dict, key, item))
987 eDebug("put %s to dict failed", key);
991 eDebug("invalid PyObject for %s", key);
994 void PutToDict(ePyObject &dict, const char*key, const char *value)
996 ePyObject item = PyString_FromString(value);
999 if (PyDict_SetItemString(dict, key, item))
1000 eDebug("put %s to dict failed", key);
1004 eDebug("could not create PyObject for %s", key);
1007 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
1009 PutToDict(dict, "tuner_type", "DVB-S");
1010 PutToDict(dict, "frequency", feparm.frequency);
1011 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
1012 PutToDict(dict, "orbital_position", feparm.orbital_position);
1013 PutToDict(dict, "inversion", feparm.inversion);
1014 PutToDict(dict, "fec_inner", feparm.fec);
1015 PutToDict(dict, "modulation", feparm.modulation);
1016 PutToDict(dict, "polarization", feparm.polarisation);
1017 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S2)
1019 PutToDict(dict, "rolloff", feparm.rolloff);
1020 PutToDict(dict, "pilot", feparm.pilot);
1022 PutToDict(dict, "system", feparm.system);
1025 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
1027 PutToDict(dict, "tuner_type", "DVB-T");
1028 PutToDict(dict, "frequency", feparm.frequency);
1029 PutToDict(dict, "bandwidth", feparm.bandwidth);
1030 PutToDict(dict, "code_rate_lp", feparm.code_rate_LP);
1031 PutToDict(dict, "code_rate_hp", feparm.code_rate_HP);
1032 PutToDict(dict, "constellation", feparm.modulation);
1033 PutToDict(dict, "transmission_mode", feparm.transmission_mode);
1034 PutToDict(dict, "guard_interval", feparm.guard_interval);
1035 PutToDict(dict, "hierarchy_information", feparm.hierarchy);
1036 PutToDict(dict, "inversion", feparm.inversion);
1039 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
1041 PutToDict(dict, "tuner_type", "DVB-C");
1042 PutToDict(dict, "frequency", feparm.frequency);
1043 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
1044 PutToDict(dict, "modulation", feparm.modulation);
1045 PutToDict(dict, "inversion", feparm.inversion);
1046 PutToDict(dict, "fec_inner", feparm.fec_inner);
1049 #if HAVE_DVB_API_VERSION >= 5
1050 static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, struct dtv_property *p, long freq_offset, int orb_pos, int polarization)
1053 int frequency = parm_frequency + freq_offset;
1054 PutToDict(dict, "frequency", frequency);
1055 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
1056 PutToDict(dict, "orbital_position", orb_pos);
1057 PutToDict(dict, "polarization", polarization);
1059 switch(parm_u_qpsk_fec_inner)
1061 case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1062 case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1063 case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1064 case FEC_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
1065 case FEC_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
1066 case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1067 case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1068 case FEC_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
1069 case FEC_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1070 case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
1071 case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
1072 default: eDebug("got unsupported FEC from frontend! report as FEC_AUTO!\n");
1075 switch (p[0].u.data)
1077 default: eDebug("got unsupported system from frontend! report as DVBS!");
1078 case SYS_DVBS: tmp = eDVBFrontendParametersSatellite::System_DVB_S; break;
1081 switch (p[2].u.data)
1083 default: eDebug("got unsupported rolloff from frontend! report as 0_20!");
1084 case ROLLOFF_20: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1085 case ROLLOFF_25: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1086 case ROLLOFF_35: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1088 PutToDict(dict, "rolloff", tmp);
1090 switch (p[3].u.data)
1092 case PILOT_OFF: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1093 case PILOT_ON: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1094 case PILOT_AUTO: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1096 PutToDict(dict, "pilot", tmp);
1098 tmp = eDVBFrontendParametersSatellite::System_DVB_S2; break;
1101 PutToDict(dict, "system", tmp);
1103 switch (p[1].u.data)
1105 default: eDebug("got unsupported modulation from frontend! report as QPSK!");
1106 case QPSK: tmp = eDVBFrontendParametersSatellite::Modulation_QPSK; break;
1107 case PSK_8: tmp = eDVBFrontendParametersSatellite::Modulation_8PSK; break;
1109 PutToDict(dict, "modulation", tmp);
1113 static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, long freq_offset, int orb_pos, int polarization)
1116 int frequency = parm_frequency + freq_offset;
1117 PutToDict(dict, "frequency", frequency);
1118 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
1119 PutToDict(dict, "orbital_position", orb_pos);
1120 PutToDict(dict, "polarization", polarization);
1122 switch(parm_u_qpsk_fec_inner)
1124 case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1125 case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1126 case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1127 case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1128 case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1129 case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
1131 case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
1132 #if HAVE_DVB_API_VERSION >=3
1133 case FEC_S2_8PSK_1_2:
1134 case FEC_S2_QPSK_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1135 case FEC_S2_8PSK_2_3:
1136 case FEC_S2_QPSK_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1137 case FEC_S2_8PSK_3_4:
1138 case FEC_S2_QPSK_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1139 case FEC_S2_8PSK_5_6:
1140 case FEC_S2_QPSK_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1141 case FEC_S2_8PSK_7_8:
1142 case FEC_S2_QPSK_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1143 case FEC_S2_8PSK_8_9:
1144 case FEC_S2_QPSK_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
1145 case FEC_S2_8PSK_3_5:
1146 case FEC_S2_QPSK_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
1147 case FEC_S2_8PSK_4_5:
1148 case FEC_S2_QPSK_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
1149 case FEC_S2_8PSK_9_10:
1150 case FEC_S2_QPSK_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1153 PutToDict(dict, "fec_inner", tmp);
1154 #if HAVE_DVB_API_VERSION >=3
1155 PutToDict(dict, "modulation",
1156 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ?
1157 eDVBFrontendParametersSatellite::Modulation_8PSK :
1158 eDVBFrontendParametersSatellite::Modulation_QPSK );
1159 if (parm_u_qpsk_fec_inner > FEC_AUTO)
1161 switch(parm_inversion & 0xc)
1163 default: // unknown rolloff
1164 case 0: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1165 case 4: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1166 case 8: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1168 PutToDict(dict, "rolloff", tmp);
1169 switch(parm_inversion & 0x30)
1171 case 0: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1172 case 0x10: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1173 case 0x20: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1175 PutToDict(dict, "pilot", tmp);
1176 tmp = eDVBFrontendParametersSatellite::System_DVB_S2;
1179 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1181 PutToDict(dict, "modulation", eDVBFrontendParametersSatellite::Modulation_QPSK );
1182 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1184 PutToDict(dict, "system", tmp);
1188 static void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1191 #if HAVE_DVB_API_VERSION < 3
1192 PutToDict(dict, "frequency", parm_frequency);
1194 PutToDict(dict, "frequency", parm_frequency/1000);
1196 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1197 switch(parm_u_qam_fec_inner)
1199 case FEC_NONE: tmp = eDVBFrontendParametersCable::FEC_None; break;
1200 case FEC_1_2: tmp = eDVBFrontendParametersCable::FEC_1_2; break;
1201 case FEC_2_3: tmp = eDVBFrontendParametersCable::FEC_2_3; break;
1202 case FEC_3_4: tmp = eDVBFrontendParametersCable::FEC_3_4; break;
1203 case FEC_5_6: tmp = eDVBFrontendParametersCable::FEC_5_6; break;
1204 case FEC_7_8: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1205 #if HAVE_DVB_API_VERSION >= 3
1206 case FEC_8_9: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1209 case FEC_AUTO: tmp = eDVBFrontendParametersCable::FEC_Auto; break;
1211 PutToDict(dict, "fec_inner", tmp);
1212 switch(parm_u_qam_modulation)
1214 case QAM_16: tmp = eDVBFrontendParametersCable::Modulation_QAM16; break;
1215 case QAM_32: tmp = eDVBFrontendParametersCable::Modulation_QAM32; break;
1216 case QAM_64: tmp = eDVBFrontendParametersCable::Modulation_QAM64; break;
1217 case QAM_128: tmp = eDVBFrontendParametersCable::Modulation_QAM128; break;
1218 case QAM_256: tmp = eDVBFrontendParametersCable::Modulation_QAM256; break;
1220 case QAM_AUTO: tmp = eDVBFrontendParametersCable::Modulation_Auto; break;
1222 PutToDict(dict, "modulation", tmp);
1225 static void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1228 PutToDict(dict, "frequency", parm_frequency);
1229 switch (parm_u_ofdm_bandwidth)
1231 case BANDWIDTH_8_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_8MHz; break;
1232 case BANDWIDTH_7_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_7MHz; break;
1233 case BANDWIDTH_6_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_6MHz; break;
1235 case BANDWIDTH_AUTO: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_Auto; break;
1237 PutToDict(dict, "bandwidth", tmp);
1238 switch (parm_u_ofdm_code_rate_LP)
1240 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1241 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1242 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1243 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1244 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1246 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1248 PutToDict(dict, "code_rate_lp", tmp);
1249 switch (parm_u_ofdm_code_rate_HP)
1251 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1252 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1253 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1254 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1255 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1257 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1259 PutToDict(dict, "code_rate_hp", tmp);
1260 switch (parm_u_ofdm_constellation)
1262 case QPSK: tmp = eDVBFrontendParametersTerrestrial::Modulation_QPSK; break;
1263 case QAM_16: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM16; break;
1264 case QAM_64: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM64; break;
1266 case QAM_AUTO: tmp = eDVBFrontendParametersTerrestrial::Modulation_Auto; break;
1268 PutToDict(dict, "constellation", tmp);
1269 switch (parm_u_ofdm_transmission_mode)
1271 case TRANSMISSION_MODE_2K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_2k; break;
1272 case TRANSMISSION_MODE_8K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_8k; break;
1274 case TRANSMISSION_MODE_AUTO: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto; break;
1276 PutToDict(dict, "transmission_mode", tmp);
1277 switch (parm_u_ofdm_guard_interval)
1279 case GUARD_INTERVAL_1_32: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_32; break;
1280 case GUARD_INTERVAL_1_16: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_16; break;
1281 case GUARD_INTERVAL_1_8: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_8; break;
1282 case GUARD_INTERVAL_1_4: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_4; break;
1284 case GUARD_INTERVAL_AUTO: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_Auto; break;
1286 PutToDict(dict, "guard_interval", tmp);
1287 switch (parm_u_ofdm_hierarchy_information)
1289 case HIERARCHY_NONE: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_None; break;
1290 case HIERARCHY_1: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_1; break;
1291 case HIERARCHY_2: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_2; break;
1292 case HIERARCHY_4: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_4; break;
1294 case HIERARCHY_AUTO: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_Auto; break;
1296 PutToDict(dict, "hierarchy_information", tmp);
1299 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1301 if (dest && PyDict_Check(dest))
1303 const char *tmp = "UNKNOWN";
1324 PutToDict(dest, "tuner_state", tmp);
1325 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1326 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1327 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1328 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1329 int sigQualitydB = readFrontendData(signalQualitydB);
1330 if (sigQualitydB == 0x12345678) // not support yet
1332 ePyObject obj=Py_None;
1334 PutToDict(dest, "tuner_signal_quality_db", obj);
1337 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1338 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1342 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1344 if (dest && PyDict_Check(dest))
1346 FRONTENDPARAMETERS front;
1347 #if HAVE_DVB_API_VERSION >= 5
1348 struct dtv_property p[4];
1349 struct dtv_properties cmdseq;
1352 p[0].cmd = DTV_DELIVERY_SYSTEM;
1353 p[1].cmd = DTV_MODULATION;
1354 p[2].cmd = DTV_ROLLOFF;
1355 p[3].cmd = DTV_PILOT;
1357 if (m_simulate || m_fd == -1 || original)
1359 #if HAVE_DVB_API_VERSION >= 5
1360 else if (m_type == feSatellite && // yet just use new api for DVB-S(2) only
1361 ioctl(m_fd, FE_GET_PROPERTY, &cmdseq)<0)
1363 eDebug("FE_GET_PROPERTY failed (%m)");
1367 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1369 eDebug("FE_GET_FRONTEND failed (%m)");
1377 PutSatelliteDataToDict(dest, oparm.sat);
1380 PutCableDataToDict(dest, oparm.cab);
1383 PutTerrestrialDataToDict(dest, oparm.ter);
1389 FRONTENDPARAMETERS &parm = front;
1390 long tmp = eDVBFrontendParametersSatellite::Inversion_Unknown;
1391 switch(parm_inversion & 3)
1394 tmp = eDVBFrontendParametersSatellite::Inversion_On;
1397 tmp = eDVBFrontendParametersSatellite::Inversion_Off;
1401 PutToDict(dest, "inversion", tmp);
1405 #if HAVE_DVB_API_VERSION >= 5
1406 fillDictWithSatelliteData(dest, parm, p, m_data[FREQ_OFFSET], oparm.sat.orbital_position, oparm.sat.polarisation);
1408 fillDictWithSatelliteData(dest, parm, m_data[FREQ_OFFSET], oparm.sat.orbital_position, oparm.sat.polarisation);
1412 fillDictWithCableData(dest, parm);
1415 fillDictWithTerrestrialData(dest, parm);
1422 void eDVBFrontend::getFrontendData(ePyObject dest)
1424 if (dest && PyDict_Check(dest))
1427 PutToDict(dest, "tuner_number", m_slotid);
1443 PutToDict(dest, "tuner_type", tmp);
1447 #ifndef FP_IOCTL_GET_ID
1448 #define FP_IOCTL_GET_ID 0
1450 int eDVBFrontend::readInputpower()
1454 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1456 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1457 FILE *f=fopen(proc_name, "r");
1460 if (fscanf(f, "%d", &power) != 1)
1461 eDebug("read %s failed!! (%m)", proc_name);
1463 eDebug("%s is %d\n", proc_name, power);
1468 // open front prozessor
1469 int fp=::open("/dev/dbox/fp0", O_RDWR);
1472 eDebug("couldn't open fp");
1475 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1476 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1478 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1487 bool eDVBFrontend::setSecSequencePos(int steps)
1489 eDebugNoSimulate("set sequence pos %d", steps);
1494 if (m_sec_sequence.current() != m_sec_sequence.end())
1495 ++m_sec_sequence.current();
1500 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1501 --m_sec_sequence.current();
1507 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1510 eDVBFrontend *sec_fe = this;
1511 eDVBRegisteredFrontend *regFE = 0;
1512 long tmp = m_data[LINKED_PREV_PTR];
1515 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1516 sec_fe = prev->m_frontend;
1517 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1518 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1519 int state = sec_fe->m_state;
1520 // workaround to put the kernel frontend thread into idle state!
1521 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1523 sec_fe->closeFrontend(true);
1524 state = sec_fe->m_state;
1526 // sec_fe is closed... we must reopen it here..
1527 if (state == stateClosed)
1535 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1537 long *sec_fe_data = sec_fe->m_data;
1538 // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1539 switch (m_sec_sequence.current()->cmd)
1541 case eSecCommand::SLEEP:
1542 delay = m_sec_sequence.current()++->msec;
1543 eDebugNoSimulate("[SEC] sleep %dms", delay);
1545 case eSecCommand::GOTO:
1546 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1547 ++m_sec_sequence.current();
1549 case eSecCommand::SET_VOLTAGE:
1551 int voltage = m_sec_sequence.current()++->voltage;
1552 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1553 sec_fe->setVoltage(voltage);
1556 case eSecCommand::IF_VOLTAGE_GOTO:
1558 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1559 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1561 ++m_sec_sequence.current();
1564 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1566 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1567 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1569 ++m_sec_sequence.current();
1572 case eSecCommand::IF_TONE_GOTO:
1574 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1575 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1577 ++m_sec_sequence.current();
1580 case eSecCommand::IF_NOT_TONE_GOTO:
1582 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1583 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1585 ++m_sec_sequence.current();
1588 case eSecCommand::SET_TONE:
1589 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1590 sec_fe->setTone(m_sec_sequence.current()++->tone);
1592 case eSecCommand::SEND_DISEQC:
1593 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1594 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1595 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1596 eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1597 if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
1598 eDebugNoSimulate("(DiSEqC reset)");
1599 else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
1600 eDebugNoSimulate("(DiSEqC peripherial power on)");
1602 eDebugNoSimulate("");
1603 ++m_sec_sequence.current();
1605 case eSecCommand::SEND_TONEBURST:
1606 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1607 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1609 case eSecCommand::SET_FRONTEND:
1611 int enableEvents = (m_sec_sequence.current()++)->val;
1612 eDebugNoSimulate("[SEC] setFrontend %d", enableEvents);
1613 setFrontend(enableEvents);
1616 case eSecCommand::START_TUNE_TIMEOUT:
1618 int tuneTimeout = m_sec_sequence.current()->timeout;
1619 eDebugNoSimulate("[SEC] startTuneTimeout %d", tuneTimeout);
1621 m_timeout->start(tuneTimeout, 1);
1622 ++m_sec_sequence.current();
1625 case eSecCommand::SET_TIMEOUT:
1626 m_timeoutCount = m_sec_sequence.current()++->val;
1627 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1629 case eSecCommand::IF_TIMEOUT_GOTO:
1630 if (!m_timeoutCount)
1632 eDebugNoSimulate("[SEC] rotor timout");
1633 setSecSequencePos(m_sec_sequence.current()->steps);
1636 ++m_sec_sequence.current();
1638 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1640 int idx = m_sec_sequence.current()++->val;
1641 if ( idx == 0 || idx == 1 )
1643 m_idleInputpower[idx] = sec_fe->readInputpower();
1644 eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1647 eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1650 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1652 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1653 int idx = compare.val;
1654 if ( !m_simulate && (idx == 0 || idx == 1) )
1656 int idle = sec_fe->readInputpower();
1657 int diff = abs(idle-m_idleInputpower[idx]);
1660 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1661 setSecSequencePos(compare.steps);
1665 ++m_sec_sequence.current();
1668 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1670 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1673 setSecSequencePos(cmd.steps);
1677 int isLocked = readFrontendData(locked);
1678 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1680 if (!m_timeoutCount && m_retryCount > 0)
1682 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 40) || !cmd.lastSignal))
1685 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1688 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1690 cmd.lastSignal = signal;
1693 if (cmd.okcount > 4)
1695 eDebugNoSimulate("ok > 4 .. goto %d\n", cmd.steps);
1696 setSecSequencePos(cmd.steps);
1697 m_state = stateLock;
1698 m_stateChanged(this);
1699 feEvent(-1); // flush events
1707 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1709 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1713 ++m_sec_sequence.current();
1716 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1717 m_runningInputpower = sec_fe->readInputpower();
1718 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1719 ++m_sec_sequence.current();
1721 case eSecCommand::SET_ROTOR_MOVING:
1723 m_sec->setRotorMoving(m_slotid, true);
1724 ++m_sec_sequence.current();
1726 case eSecCommand::SET_ROTOR_STOPPED:
1728 m_sec->setRotorMoving(m_slotid, false);
1729 ++m_sec_sequence.current();
1731 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1733 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1736 setSecSequencePos(cmd.steps);
1739 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1740 const char *txt = cmd.direction ? "running" : "stopped";
1742 if (!m_timeoutCount && m_retryCount > 0)
1744 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1746 m_runningInputpower,
1749 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1750 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1753 eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1754 if ( cmd.okcount > 6 )
1756 eDebugNoSimulate("[SEC] rotor is %s", txt);
1757 if (setSecSequencePos(cmd.steps))
1763 eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1766 ++m_sec_sequence.current();
1769 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1770 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1771 setSecSequencePos(m_sec_sequence.current()->steps);
1773 ++m_sec_sequence.current();
1775 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1776 eDebugNoSimulate("[SEC] invalidate current switch params");
1777 sec_fe_data[CSW] = -1;
1778 sec_fe_data[UCSW] = -1;
1779 sec_fe_data[TONEBURST] = -1;
1780 ++m_sec_sequence.current();
1782 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1783 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1784 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1785 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1786 eDebugNoSimulate("[SEC] update current switch params");
1787 ++m_sec_sequence.current();
1789 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1790 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1791 sec_fe_data[ROTOR_CMD] = -1;
1792 sec_fe_data[ROTOR_POS] = -1;
1793 ++m_sec_sequence.current();
1795 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1796 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1797 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1798 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1799 ++m_sec_sequence.current();
1801 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1802 m_retryCount = m_sec_sequence.current()++->val;
1803 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1805 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1808 eDebugNoSimulate("[SEC] no more rotor retrys");
1809 setSecSequencePos(m_sec_sequence.current()->steps);
1812 ++m_sec_sequence.current();
1814 case eSecCommand::SET_POWER_LIMITING_MODE:
1819 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1820 FILE *f=fopen(proc_name, "w");
1821 if (f) // new interface exist?
1823 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1824 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1825 eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1827 eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1830 else if (sec_fe->m_need_rotor_workaround)
1833 int slotid = sec_fe->m_slotid;
1834 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1836 sprintf(dev, "/dev/i2c/%d", slotid);
1837 else if (slotid == 2)
1838 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1839 else if (slotid == 3)
1840 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1841 int fd = ::open(dev, O_RDWR);
1843 unsigned char data[2];
1844 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1845 if(::read(fd, data, 1) != 1)
1846 eDebugNoSimulate("[SEC] error read lnbp (%m)");
1847 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1849 data[0] |= 0x80; // enable static current limiting
1850 eDebugNoSimulate("[SEC] set static current limiting");
1854 data[0] &= ~0x80; // enable dynamic current limiting
1855 eDebugNoSimulate("[SEC] set dynamic current limiting");
1857 if(::write(fd, data, 1) != 1)
1858 eDebugNoSimulate("[SEC] error write lnbp (%m)");
1862 ++m_sec_sequence.current();
1866 eDebugNoSimulate("[SEC] unhandled sec command %d",
1867 ++m_sec_sequence.current()->cmd);
1868 ++m_sec_sequence.current();
1871 m_tuneTimer->start(delay,true);
1875 if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1879 void eDVBFrontend::setFrontend(bool recvEvents)
1883 eDebug("setting frontend %d", m_dvbid);
1886 feEvent(-1); // flush events
1887 #if HAVE_DVB_API_VERSION >= 5
1888 if (m_type == iDVBFrontend::feSatellite)
1890 fe_rolloff_t rolloff = ROLLOFF_35;
1891 fe_pilot_t pilot = PILOT_OFF;
1892 fe_modulation_t modulation = QPSK;
1893 fe_delivery_system_t system = SYS_DVBS;
1894 switch(oparm.sat.system)
1896 case eDVBFrontendParametersSatellite::System_DVB_S: system = SYS_DVBS; break;
1897 case eDVBFrontendParametersSatellite::System_DVB_S2: system = SYS_DVBS2; break;
1899 switch(oparm.sat.modulation)
1901 case eDVBFrontendParametersSatellite::Modulation_QPSK: modulation = QPSK; break;
1902 case eDVBFrontendParametersSatellite::Modulation_8PSK: modulation = PSK_8; break;
1903 case eDVBFrontendParametersSatellite::Modulation_QAM16: modulation = QAM_16; break;
1905 switch(oparm.sat.pilot)
1907 case eDVBFrontendParametersSatellite::Pilot_Off: pilot = PILOT_OFF; break;
1908 case eDVBFrontendParametersSatellite::Pilot_On: pilot = PILOT_ON; break;
1909 case eDVBFrontendParametersSatellite::Pilot_Unknown: pilot = PILOT_AUTO; break;
1911 switch(oparm.sat.rolloff)
1913 case eDVBFrontendParametersSatellite::RollOff_alpha_0_20: rolloff = ROLLOFF_20; break;
1914 case eDVBFrontendParametersSatellite::RollOff_alpha_0_25: rolloff = ROLLOFF_25; break;
1915 case eDVBFrontendParametersSatellite::RollOff_alpha_0_35: rolloff = ROLLOFF_35; break;
1917 struct dtv_property p[10];
1918 struct dtv_properties cmdseq;
1920 p[0].cmd = DTV_CLEAR;
1921 p[1].cmd = DTV_DELIVERY_SYSTEM, p[1].u.data = system;
1922 p[2].cmd = DTV_FREQUENCY, p[2].u.data = parm_frequency;
1923 p[3].cmd = DTV_MODULATION, p[3].u.data = modulation;
1924 p[4].cmd = DTV_SYMBOL_RATE, p[4].u.data = parm_u_qpsk_symbol_rate;
1925 p[5].cmd = DTV_INNER_FEC, p[5].u.data = parm_u_qpsk_fec_inner;
1926 p[6].cmd = DTV_INVERSION, p[6].u.data = parm_inversion;
1927 if (system == SYS_DVBS2)
1929 p[7].cmd = DTV_ROLLOFF, p[7].u.data = rolloff;
1930 p[8].cmd = DTV_PILOT, p[8].u.data = pilot;
1931 p[9].cmd = DTV_TUNE;
1936 p[7].cmd = DTV_TUNE;
1939 if (ioctl(m_fd, FE_SET_PROPERTY, &cmdseq) == -1)
1941 perror("FE_SET_PROPERTY failed");
1948 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1950 perror("FE_SET_FRONTEND failed");
1957 RESULT eDVBFrontend::getFrontendType(int &t)
1965 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1970 eWarning("no SEC module active!");
1973 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1976 #if HAVE_DVB_API_VERSION >= 3
1977 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",
1980 feparm.polarisation,
1984 feparm.orbital_position,
1990 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1993 feparm.polarisation,
1997 feparm.orbital_position);
1999 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
2000 switch (feparm.inversion)
2002 case eDVBFrontendParametersSatellite::Inversion_On:
2003 parm_inversion = INVERSION_ON;
2005 case eDVBFrontendParametersSatellite::Inversion_Off:
2006 parm_inversion = INVERSION_OFF;
2009 case eDVBFrontendParametersSatellite::Inversion_Unknown:
2010 parm_inversion = INVERSION_AUTO;
2013 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S)
2017 case eDVBFrontendParametersSatellite::FEC_None:
2018 parm_u_qpsk_fec_inner = FEC_NONE;
2020 case eDVBFrontendParametersSatellite::FEC_1_2:
2021 parm_u_qpsk_fec_inner = FEC_1_2;
2023 case eDVBFrontendParametersSatellite::FEC_2_3:
2024 parm_u_qpsk_fec_inner = FEC_2_3;
2026 case eDVBFrontendParametersSatellite::FEC_3_4:
2027 parm_u_qpsk_fec_inner = FEC_3_4;
2029 case eDVBFrontendParametersSatellite::FEC_5_6:
2030 parm_u_qpsk_fec_inner = FEC_5_6;
2032 case eDVBFrontendParametersSatellite::FEC_7_8:
2033 parm_u_qpsk_fec_inner = FEC_7_8;
2036 eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
2037 case eDVBFrontendParametersSatellite::FEC_Auto:
2038 parm_u_qpsk_fec_inner = FEC_AUTO;
2042 #if HAVE_DVB_API_VERSION >= 3
2047 case eDVBFrontendParametersSatellite::FEC_1_2:
2048 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
2050 case eDVBFrontendParametersSatellite::FEC_2_3:
2051 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
2053 case eDVBFrontendParametersSatellite::FEC_3_4:
2054 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
2056 case eDVBFrontendParametersSatellite::FEC_3_5:
2057 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
2059 case eDVBFrontendParametersSatellite::FEC_4_5:
2060 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
2062 case eDVBFrontendParametersSatellite::FEC_5_6:
2063 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
2065 case eDVBFrontendParametersSatellite::FEC_7_8:
2066 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
2068 case eDVBFrontendParametersSatellite::FEC_8_9:
2069 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
2071 case eDVBFrontendParametersSatellite::FEC_9_10:
2072 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
2075 eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
2078 #if HAVE_DVB_API_VERSION < 5
2079 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
2080 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
2081 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation_8PSK)
2083 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
2084 // 8PSK fec driver values are decimal 9 bigger
2089 // FIXME !!! get frequency range from tuner
2090 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
2092 eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
2095 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
2101 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
2103 #if HAVE_DVB_API_VERSION < 3
2104 parm_frequency = feparm.frequency;
2106 parm_frequency = feparm.frequency * 1000;
2108 parm_u_qam_symbol_rate = feparm.symbol_rate;
2109 switch (feparm.modulation)
2111 case eDVBFrontendParametersCable::Modulation_QAM16:
2112 parm_u_qam_modulation = QAM_16;
2114 case eDVBFrontendParametersCable::Modulation_QAM32:
2115 parm_u_qam_modulation = QAM_32;
2117 case eDVBFrontendParametersCable::Modulation_QAM64:
2118 parm_u_qam_modulation = QAM_64;
2120 case eDVBFrontendParametersCable::Modulation_QAM128:
2121 parm_u_qam_modulation = QAM_128;
2123 case eDVBFrontendParametersCable::Modulation_QAM256:
2124 parm_u_qam_modulation = QAM_256;
2127 case eDVBFrontendParametersCable::Modulation_Auto:
2128 parm_u_qam_modulation = QAM_AUTO;
2131 switch (feparm.inversion)
2133 case eDVBFrontendParametersCable::Inversion_On:
2134 parm_inversion = INVERSION_ON;
2136 case eDVBFrontendParametersCable::Inversion_Off:
2137 parm_inversion = INVERSION_OFF;
2140 case eDVBFrontendParametersCable::Inversion_Unknown:
2141 parm_inversion = INVERSION_AUTO;
2144 switch (feparm.fec_inner)
2146 case eDVBFrontendParametersCable::FEC_None:
2147 parm_u_qam_fec_inner = FEC_NONE;
2149 case eDVBFrontendParametersCable::FEC_1_2:
2150 parm_u_qam_fec_inner = FEC_1_2;
2152 case eDVBFrontendParametersCable::FEC_2_3:
2153 parm_u_qam_fec_inner = FEC_2_3;
2155 case eDVBFrontendParametersCable::FEC_3_4:
2156 parm_u_qam_fec_inner = FEC_3_4;
2158 case eDVBFrontendParametersCable::FEC_5_6:
2159 parm_u_qam_fec_inner = FEC_5_6;
2161 case eDVBFrontendParametersCable::FEC_7_8:
2162 parm_u_qam_fec_inner = FEC_7_8;
2164 #if HAVE_DVB_API_VERSION >= 3
2165 case eDVBFrontendParametersCable::FEC_8_9:
2166 parm_u_qam_fec_inner = FEC_8_9;
2170 case eDVBFrontendParametersCable::FEC_Auto:
2171 parm_u_qam_fec_inner = FEC_AUTO;
2174 eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
2175 parm_frequency/1000,
2176 parm_u_qam_symbol_rate,
2177 parm_u_qam_fec_inner,
2178 parm_u_qam_modulation,
2184 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
2186 parm_frequency = feparm.frequency;
2188 switch (feparm.bandwidth)
2190 case eDVBFrontendParametersTerrestrial::Bandwidth_8MHz:
2191 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
2193 case eDVBFrontendParametersTerrestrial::Bandwidth_7MHz:
2194 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
2196 case eDVBFrontendParametersTerrestrial::Bandwidth_6MHz:
2197 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
2200 case eDVBFrontendParametersTerrestrial::Bandwidth_Auto:
2201 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
2204 switch (feparm.code_rate_LP)
2206 case eDVBFrontendParametersTerrestrial::FEC_1_2:
2207 parm_u_ofdm_code_rate_LP = FEC_1_2;
2209 case eDVBFrontendParametersTerrestrial::FEC_2_3:
2210 parm_u_ofdm_code_rate_LP = FEC_2_3;
2212 case eDVBFrontendParametersTerrestrial::FEC_3_4:
2213 parm_u_ofdm_code_rate_LP = FEC_3_4;
2215 case eDVBFrontendParametersTerrestrial::FEC_5_6:
2216 parm_u_ofdm_code_rate_LP = FEC_5_6;
2218 case eDVBFrontendParametersTerrestrial::FEC_7_8:
2219 parm_u_ofdm_code_rate_LP = FEC_7_8;
2222 case eDVBFrontendParametersTerrestrial::FEC_Auto:
2223 parm_u_ofdm_code_rate_LP = FEC_AUTO;
2226 switch (feparm.code_rate_HP)
2228 case eDVBFrontendParametersTerrestrial::FEC_1_2:
2229 parm_u_ofdm_code_rate_HP = FEC_1_2;
2231 case eDVBFrontendParametersTerrestrial::FEC_2_3:
2232 parm_u_ofdm_code_rate_HP = FEC_2_3;
2234 case eDVBFrontendParametersTerrestrial::FEC_3_4:
2235 parm_u_ofdm_code_rate_HP = FEC_3_4;
2237 case eDVBFrontendParametersTerrestrial::FEC_5_6:
2238 parm_u_ofdm_code_rate_HP = FEC_5_6;
2240 case eDVBFrontendParametersTerrestrial::FEC_7_8:
2241 parm_u_ofdm_code_rate_HP = FEC_7_8;
2244 case eDVBFrontendParametersTerrestrial::FEC_Auto:
2245 parm_u_ofdm_code_rate_HP = FEC_AUTO;
2248 switch (feparm.modulation)
2250 case eDVBFrontendParametersTerrestrial::Modulation_QPSK:
2251 parm_u_ofdm_constellation = QPSK;
2253 case eDVBFrontendParametersTerrestrial::Modulation_QAM16:
2254 parm_u_ofdm_constellation = QAM_16;
2256 case eDVBFrontendParametersTerrestrial::Modulation_QAM64:
2257 parm_u_ofdm_constellation = QAM_64;
2260 case eDVBFrontendParametersTerrestrial::Modulation_Auto:
2261 parm_u_ofdm_constellation = QAM_AUTO;
2264 switch (feparm.transmission_mode)
2266 case eDVBFrontendParametersTerrestrial::TransmissionMode_2k:
2267 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2269 case eDVBFrontendParametersTerrestrial::TransmissionMode_8k:
2270 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2273 case eDVBFrontendParametersTerrestrial::TransmissionMode_Auto:
2274 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2277 switch (feparm.guard_interval)
2279 case eDVBFrontendParametersTerrestrial::GuardInterval_1_32:
2280 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2282 case eDVBFrontendParametersTerrestrial::GuardInterval_1_16:
2283 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2285 case eDVBFrontendParametersTerrestrial::GuardInterval_1_8:
2286 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2288 case eDVBFrontendParametersTerrestrial::GuardInterval_1_4:
2289 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2292 case eDVBFrontendParametersTerrestrial::GuardInterval_Auto:
2293 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2296 switch (feparm.hierarchy)
2298 case eDVBFrontendParametersTerrestrial::Hierarchy_None:
2299 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2301 case eDVBFrontendParametersTerrestrial::Hierarchy_1:
2302 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2304 case eDVBFrontendParametersTerrestrial::Hierarchy_2:
2305 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2307 case eDVBFrontendParametersTerrestrial::Hierarchy_4:
2308 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2311 case eDVBFrontendParametersTerrestrial::Hierarchy_Auto:
2312 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2315 switch (feparm.inversion)
2317 case eDVBFrontendParametersTerrestrial::Inversion_On:
2318 parm_inversion = INVERSION_ON;
2320 case eDVBFrontendParametersTerrestrial::Inversion_Off:
2321 parm_inversion = INVERSION_OFF;
2324 case eDVBFrontendParametersTerrestrial::Inversion_Unknown:
2325 parm_inversion = INVERSION_AUTO;
2332 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2334 unsigned int timeout = 5000;
2335 eDebugNoSimulate("(%d)tune", m_dvbid);
2341 if (!m_sn && !m_simulate)
2343 eDebug("no frontend device opened... do not try to tune !!!");
2357 m_sec_sequence.clear();
2359 where.calcLockTimeout(timeout);
2365 eDVBFrontendParametersSatellite feparm;
2366 if (where.getDVBS(feparm))
2368 eDebug("no dvbs data!");
2372 if (m_rotor_mode != feparm.no_rotor_command_on_tune && !feparm.no_rotor_command_on_tune)
2374 eDVBFrontend *sec_fe = this;
2375 long tmp = m_data[LINKED_PREV_PTR];
2378 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
2379 sec_fe = linked_fe->m_frontend;
2380 sec_fe->getData(LINKED_NEXT_PTR, tmp);
2382 eDebug("(fe%d) reset diseqc after leave rotor mode!", m_dvbid);
2383 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
2385 m_rotor_mode = feparm.no_rotor_command_on_tune;
2387 m_sec->setRotorMoving(m_slotid, false);
2388 res=prepare_sat(feparm, timeout);
2396 eDVBFrontendParametersCable feparm;
2397 if (where.getDVBC(feparm))
2402 res=prepare_cable(feparm);
2406 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2407 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2412 eDVBFrontendParametersTerrestrial feparm;
2413 if (where.getDVBT(feparm))
2415 eDebug("no -T data");
2419 res=prepare_terrestrial(feparm);
2423 std::string enable_5V;
2424 char configStr[255];
2425 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2426 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2427 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2428 if (enable_5V == "True")
2429 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2431 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2432 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2438 m_sec_sequence.current() = m_sec_sequence.begin();
2442 m_tuneTimer->start(0,true);
2444 if (m_state != stateTuning)
2446 m_state = stateTuning;
2447 m_stateChanged(this);
2456 m_tuneTimer->stop();
2460 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2462 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2466 RESULT eDVBFrontend::setVoltage(int voltage)
2468 if (m_type == feCable)
2470 #if HAVE_DVB_API_VERSION < 3
2473 bool increased=false;
2474 fe_sec_voltage_t vlt;
2476 m_data[CUR_VOLTAGE]=voltage;
2480 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2481 vlt = SEC_VOLTAGE_OFF;
2484 #if HAVE_DVB_API_VERSION < 3
2485 vlt = SEC_VOLTAGE_13_5;
2491 vlt = SEC_VOLTAGE_13;
2494 #if HAVE_DVB_API_VERSION < 3
2495 vlt = SEC_VOLTAGE_18_5;
2501 vlt = SEC_VOLTAGE_18;
2508 #if HAVE_DVB_API_VERSION < 3
2509 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2511 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2512 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2513 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2517 RESULT eDVBFrontend::getState(int &state)
2523 RESULT eDVBFrontend::setTone(int t)
2525 if (m_type != feSatellite)
2527 #if HAVE_DVB_API_VERSION < 3
2530 fe_sec_tone_mode_t tone;
2539 tone = SEC_TONE_OFF;
2546 #if HAVE_DVB_API_VERSION < 3
2547 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2549 return ::ioctl(m_fd, FE_SET_TONE, tone);
2553 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2554 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2557 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2561 #if HAVE_DVB_API_VERSION < 3
2562 struct secCommand cmd;
2563 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2564 cmd.u.diseqc.cmdtype = diseqc.data[0];
2565 cmd.u.diseqc.addr = diseqc.data[1];
2566 cmd.u.diseqc.cmd = diseqc.data[2];
2567 cmd.u.diseqc.numParams = diseqc.len-3;
2568 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2569 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2571 struct dvb_diseqc_master_cmd cmd;
2572 memcpy(cmd.msg, diseqc.data, diseqc.len);
2573 cmd.msg_len = diseqc.len;
2574 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2580 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2581 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2583 RESULT eDVBFrontend::sendToneburst(int burst)
2587 #if HAVE_DVB_API_VERSION < 3
2588 secMiniCmd cmd = SEC_MINI_NONE;
2590 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2592 if ( burst == eDVBSatelliteDiseqcParameters::A )
2594 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2596 #if HAVE_DVB_API_VERSION < 3
2597 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2600 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2606 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2612 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2614 m_sec_sequence = list;
2618 RESULT eDVBFrontend::getData(int num, long &data)
2620 if ( num < NUM_DATA_ENTRIES )
2628 RESULT eDVBFrontend::setData(int num, long val)
2630 if ( num < NUM_DATA_ENTRIES )
2638 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2641 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2643 if (m_type == eDVBFrontend::feSatellite)
2646 eDVBFrontendParametersSatellite sat_parm;
2647 int ret = feparm->getDVBS(sat_parm);
2649 if (sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S2 && !m_can_handle_dvbs2)
2651 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2652 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S && m_can_handle_dvbs2)
2656 else if (m_type == eDVBFrontend::feCable)
2657 return 2; // more prio for cable frontends
2658 else if (m_type == eDVBFrontend::feTerrestrial)
2663 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2665 ePyObject Id, Descr, Enabled, IsDVBS2;
2666 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4)
2668 Id = PyTuple_GET_ITEM(obj, 0);
2669 Descr = PyTuple_GET_ITEM(obj, 1);
2670 Enabled = PyTuple_GET_ITEM(obj, 2);
2671 IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2672 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2))
2674 strcpy(m_description, PyString_AS_STRING(Descr));
2675 m_slotid = PyInt_AsLong(Id);
2676 m_enabled = Enabled == Py_True;
2677 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2678 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2679 !!strstr(m_description, "Alps BSBE2") ||
2680 !!strstr(m_description, "Alps -S") ||
2681 !!strstr(m_description, "BCM4501");
2682 m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2683 eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2684 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2687 PyErr_SetString(PyExc_StandardError,
2688 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");
2692 RESULT eDVBFrontend::turnOffSatCR(int satcr)
2694 eSecCommandList sec_sequence;
2695 // check if voltage is disabled
2696 eSecCommand::pair compare;
2697 compare.steps = +9; //nothing to do
2698 compare.voltage = iDVBFrontend::voltageOff;
2699 sec_sequence.push_back( eSecCommand(eSecCommand::IF_NOT_VOLTAGE_GOTO, compare) );
2700 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2701 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50 ) );
2703 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage18_5) );
2704 sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
2705 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 250) );
2707 eDVBDiseqcCommand diseqc;
2708 memset(diseqc.data, 0, MAX_DISEQC_LENGTH);
2710 diseqc.data[0] = 0xE0;
2711 diseqc.data[1] = 0x10;
2712 diseqc.data[2] = 0x5A;
2713 diseqc.data[3] = satcr << 5;
2714 diseqc.data[4] = 0x00;
2716 sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
2717 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50+20+14*diseqc.len) );
2718 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2719 setSecSequence(sec_sequence);
2723 RESULT eDVBFrontend::ScanSatCR()
2727 setTone(iDVBFrontend::toneOff);