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 int eDVBFrontend::openFrontend()
488 if (m_state != stateClosed)
489 return -1; // already opened
494 #if HAVE_DVB_API_VERSION < 3
495 FrontendInfo fe_info;
497 dvb_frontend_info fe_info;
499 eDebugNoSimulate("opening frontend %d", m_dvbid);
502 if (!m_simulate || m_type == -1)
504 m_fd = ::open(m_filename, O_RDWR|O_NONBLOCK);
507 eWarning("failed! (%s) %m", m_filename);
513 eWarning("frontend %d already opened", m_dvbid);
516 if (::ioctl(m_fd, FE_GET_INFO, &fe_info) < 0)
518 eWarning("ioctl FE_GET_INFO failed");
524 switch (fe_info.type)
527 m_type = iDVBFrontend::feSatellite;
530 m_type = iDVBFrontend::feCable;
533 m_type = iDVBFrontend::feTerrestrial;
536 eWarning("unknown frontend type.");
541 eDebugNoSimulate("detected %s frontend", "satellite\0cable\0 terrestrial"+fe_info.type*10);
544 #if HAVE_DVB_API_VERSION < 3
545 if (m_type == iDVBFrontend::feSatellite)
551 m_secfd = ::open(m_sec_filename, O_RDWR);
554 eWarning("failed! (%s) %m", m_sec_filename);
562 eWarning("sec %d already opened", m_dvbid);
566 setTone(iDVBFrontend::toneOff);
567 setVoltage(iDVBFrontend::voltageOff);
571 m_sn = eSocketNotifier::create(eApp, m_fd, eSocketNotifier::Read, false);
572 CONNECT(m_sn->activated, eDVBFrontend::feEvent);
578 int eDVBFrontend::closeFrontend(bool force)
580 if (!force && m_data[CUR_VOLTAGE] != -1 && m_data[CUR_VOLTAGE] != iDVBFrontend::voltageOff)
582 long tmp = m_data[LINKED_NEXT_PTR];
585 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
586 if (linked_fe->m_inuse)
588 eDebugNoSimulate("dont close frontend %d until the linked frontend %d in slot %d is still in use",
589 m_dvbid, linked_fe->m_frontend->getDVBID(), linked_fe->m_frontend->getSlotID());
592 linked_fe->m_frontend->getData(LINKED_NEXT_PTR, tmp);
598 eDebugNoSimulate("close frontend %d", m_dvbid);
599 if (m_data[SATCR] != -1)
601 turnOffSatCR(m_data[SATCR]);
603 setTone(iDVBFrontend::toneOff);
604 setVoltage(iDVBFrontend::voltageOff);
606 if (m_sec && !m_simulate)
607 m_sec->setRotorMoving(m_slotid, false);
611 eWarning("couldnt close frontend %d", m_dvbid);
615 setTone(iDVBFrontend::toneOff);
616 setVoltage(iDVBFrontend::voltageOff);
618 #if HAVE_DVB_API_VERSION < 3
621 if (!::close(m_secfd))
624 eWarning("couldnt close sec %d", m_dvbid);
628 m_state = stateClosed;
633 eDVBFrontend::~eDVBFrontend()
635 m_data[LINKED_PREV_PTR] = m_data[LINKED_NEXT_PTR] = -1;
639 void eDVBFrontend::feEvent(int w)
641 eDVBFrontend *sec_fe = this;
642 long tmp = m_data[LINKED_PREV_PTR];
645 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
646 sec_fe = linked_fe->m_frontend;
647 sec_fe->getData(LINKED_NEXT_PTR, tmp);
651 #if HAVE_DVB_API_VERSION < 3
654 dvb_frontend_event event;
658 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
660 if (res && (errno == EAGAIN))
666 #if HAVE_DVB_API_VERSION < 3
667 if (event.type == FE_COMPLETION_EV)
669 eDebug("(%d)fe event: status %x, inversion %s, m_tuning %d", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off", m_tuning);
670 if (event.status & FE_HAS_LOCK)
678 #if HAVE_DVB_API_VERSION >= 3
679 if (event.status & FE_TIMEDOUT) {
680 eDebug("FE_TIMEDOUT! ..abort");
693 eDebug("stateLostLock");
694 state = stateLostLock;
696 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
699 if (m_state != state)
702 m_stateChanged(this);
707 void eDVBFrontend::timeout()
710 if (m_state == stateTuning)
712 m_state = stateFailed;
713 m_stateChanged(this);
717 #define INRANGE(X,Y,Z) (((X<=Y) && (Y<=Z))||((Z<=Y) && (Y<=X)) ? 1 : 0)
719 /* unsigned 32 bit division */
720 static inline uint32_t fe_udiv(uint32_t a, uint32_t b)
722 return (a + b / 2) / b;
725 int eDVBFrontend::readFrontendData(int type)
734 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
735 eDebug("FE_READ_BER failed (%m)");
740 case signalQualitydB: /* this will move into the driver */
742 int sat_max = 1600; // for stv0288 / bsbe2
743 int ret = 0x12345678;
747 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
748 eDebug("FE_READ_SNR failed (%m)");
749 else if (!strcmp(m_description, "BCM4501 (internal)"))
751 float SDS_SNRE = snr << 16;
754 if (oparm.sat.system == eDVBFrontendParametersSatellite::System_DVB_S) // DVB-S1 / QPSK
756 static float SNR_COEFF[6] = {
759 197418.0 / 4194304.0,
760 -2602183.0 / 4194304.0,
761 20377212.0 / 4194304.0,
762 -37791203.0 / 4194304.0,
764 float fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0)),
765 fval2 = pow(10.0, fval1)-1;
766 fval1 = 10.0 * log10(fval2);
770 fval2 = SNR_COEFF[0];
771 for (int i=1; i<6; ++i)
774 fval2 += SNR_COEFF[i];
780 #if HAVE_DVB_API_VERSION >= 3
783 float fval1 = SDS_SNRE / 268435456.0,
786 if (parm_u_qpsk_fec_inner <= FEC_S2_QPSK_9_10) // DVB-S2 QPSK
797 fval4 = -10.0 * log10(fval1);
799 for (int i=0; i < 5; ++i)
800 fval1 = fval4 - fval2 * log10(1.0+pow(10.0, (fval3-fval1)/fval2));
805 ret = (int)(snr_in_db * 100);
807 else if (strstr(m_description, "Alps BSBE1 C01A") ||
808 strstr(m_description, "Alps -S(STV0288)"))
812 else if (snr == 0xFFFF) // i think this should not happen
816 enum { REALVAL, REGVAL };
817 const long CN_lookup[31][2] = {
818 {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
819 {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
820 {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
821 {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
822 {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
823 {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
826 int add=strchr(m_description, '.') ? 0xA250 : 0xA100;
827 long regval = 0xFFFF - ((snr / 3) + add), // revert some dvb api calulations to get the real register value
831 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
836 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[i][REGVAL]))
841 ret = (((regval - CN_lookup[Imin][REGVAL])
842 * (CN_lookup[Imax][REALVAL] - CN_lookup[Imin][REALVAL])
843 / (CN_lookup[Imax][REGVAL] - CN_lookup[Imin][REGVAL]))
844 + CN_lookup[Imin][REALVAL]) * 10;
850 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
851 !strcmp(m_description, "Alps -S") ||
852 !strcmp(m_description, "Philips -S") ||
853 !strcmp(m_description, "LG -S") )
856 ret = (int)((snr-39075)/17.647);
857 } else if (!strcmp(m_description, "Alps BSBE2"))
859 ret = (int)((snr >> 7) * 10);
860 } else if (!strcmp(m_description, "Philips CU1216Mk3"))
862 int mse = (~snr) & 0xFF;
863 switch (parm_u_qam_modulation) {
864 case QAM_16: ret = fe_udiv(1950000, (32 * mse) + 138) + 1000; break;
865 case QAM_32: ret = fe_udiv(2150000, (40 * mse) + 500) + 1350; break;
866 case QAM_64: ret = fe_udiv(2100000, (40 * mse) + 500) + 1250; break;
867 case QAM_128: ret = fe_udiv(1850000, (38 * mse) + 400) + 1380; break;
868 case QAM_256: ret = fe_udiv(1800000, (100 * mse) + 40) + 2030; break;
871 } else if (!strcmp(m_description, "Philips TU1216"))
873 snr = 0xFF - (snr & 0xFF);
875 ret = 10 * (int)(-100 * (log10(snr) - log10(255)));
877 else if (strstr(m_description, "BCM4506") || strstr(m_description, "BCM4505"))
878 ret = (snr * 100) >> 8;
880 if (type == signalQuality)
882 if (ret == 0x12345678) // no snr db calculation avail.. return untouched snr value..
887 return ret >= sat_max ? 65536 : ret * 65536 / sat_max;
888 case feCable: // we assume a max of 42db here
889 return ret >= 4200 ? 65536 : ret * 65536 / 4200;
890 case feTerrestrial: // we assume a max of 24db here
891 return ret >= 2400 ? 65536 : ret * 65536 / 2400;
895 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
903 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
904 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
910 #if HAVE_DVB_API_VERSION < 3
911 FrontendStatus status=0;
917 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
918 eDebug("FE_READ_STATUS failed (%m)");
919 return !!(status&FE_HAS_LOCK);
925 #if HAVE_DVB_API_VERSION < 3
926 FrontendStatus status=0;
932 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
933 eDebug("FE_READ_STATUS failed (%m)");
934 return !!(status&FE_HAS_SYNC);
944 void PutToDict(ePyObject &dict, const char*key, long value)
946 ePyObject item = PyInt_FromLong(value);
949 if (PyDict_SetItemString(dict, key, item))
950 eDebug("put %s to dict failed", key);
954 eDebug("could not create PyObject for %s", key);
957 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
961 if (PyDict_SetItemString(dict, key, item))
962 eDebug("put %s to dict failed", key);
966 eDebug("invalid PyObject for %s", key);
969 void PutToDict(ePyObject &dict, const char*key, const char *value)
971 ePyObject item = PyString_FromString(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 PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
984 PutToDict(dict, "tuner_type", "DVB-S");
985 PutToDict(dict, "frequency", feparm.frequency);
986 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
987 PutToDict(dict, "orbital_position", feparm.orbital_position);
988 PutToDict(dict, "inversion", feparm.inversion);
989 PutToDict(dict, "fec_inner", feparm.fec);
990 PutToDict(dict, "modulation", feparm.modulation);
991 PutToDict(dict, "polarization", feparm.polarisation);
992 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S2)
994 PutToDict(dict, "rolloff", feparm.rolloff);
995 PutToDict(dict, "pilot", feparm.pilot);
997 PutToDict(dict, "system", feparm.system);
1000 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
1002 PutToDict(dict, "tuner_type", "DVB-T");
1003 PutToDict(dict, "frequency", feparm.frequency);
1004 PutToDict(dict, "bandwidth", feparm.bandwidth);
1005 PutToDict(dict, "code_rate_lp", feparm.code_rate_LP);
1006 PutToDict(dict, "code_rate_hp", feparm.code_rate_HP);
1007 PutToDict(dict, "constellation", feparm.modulation);
1008 PutToDict(dict, "transmission_mode", feparm.transmission_mode);
1009 PutToDict(dict, "guard_interval", feparm.guard_interval);
1010 PutToDict(dict, "hierarchy_information", feparm.hierarchy);
1011 PutToDict(dict, "inversion", feparm.inversion);
1014 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
1016 PutToDict(dict, "tuner_type", "DVB-C");
1017 PutToDict(dict, "frequency", feparm.frequency);
1018 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
1019 PutToDict(dict, "modulation", feparm.modulation);
1020 PutToDict(dict, "inversion", feparm.inversion);
1021 PutToDict(dict, "fec_inner", feparm.fec_inner);
1024 #if HAVE_DVB_API_VERSION >= 5
1025 static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, struct dtv_property *p, long freq_offset, int orb_pos, int polarization)
1028 int frequency = parm_frequency + freq_offset;
1029 PutToDict(dict, "frequency", frequency);
1030 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
1031 PutToDict(dict, "orbital_position", orb_pos);
1032 PutToDict(dict, "polarization", polarization);
1034 switch(parm_u_qpsk_fec_inner)
1036 case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1037 case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1038 case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1039 case FEC_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
1040 case FEC_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
1041 case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1042 case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1043 case FEC_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
1044 case FEC_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1045 case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
1046 case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
1047 default: eDebug("got unsupported FEC from frontend! report as FEC_AUTO!\n");
1050 switch (p[0].u.data)
1052 default: eDebug("got unsupported system from frontend! report as DVBS!");
1053 case SYS_DVBS: tmp = eDVBFrontendParametersSatellite::System_DVB_S; break;
1056 switch (p[2].u.data)
1058 default: eDebug("got unsupported rolloff from frontend! report as 0_20!");
1059 case ROLLOFF_20: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1060 case ROLLOFF_25: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1061 case ROLLOFF_35: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1063 PutToDict(dict, "rolloff", tmp);
1065 switch (p[3].u.data)
1067 case PILOT_OFF: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1068 case PILOT_ON: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1069 case PILOT_AUTO: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1071 PutToDict(dict, "pilot", tmp);
1073 tmp = eDVBFrontendParametersSatellite::System_DVB_S2; break;
1076 PutToDict(dict, "system", tmp);
1078 switch (p[1].u.data)
1080 default: eDebug("got unsupported modulation from frontend! report as QPSK!");
1081 case QPSK: tmp = eDVBFrontendParametersSatellite::Modulation_QPSK; break;
1082 case PSK_8: tmp = eDVBFrontendParametersSatellite::Modulation_8PSK; break;
1084 PutToDict(dict, "modulation", tmp);
1088 static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, long freq_offset, int orb_pos, int polarization)
1091 int frequency = parm_frequency + freq_offset;
1092 PutToDict(dict, "frequency", frequency);
1093 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
1094 PutToDict(dict, "orbital_position", orb_pos);
1095 PutToDict(dict, "polarization", polarization);
1097 switch(parm_u_qpsk_fec_inner)
1099 case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1100 case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1101 case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1102 case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1103 case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1104 case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
1106 case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
1107 #if HAVE_DVB_API_VERSION >=3
1108 case FEC_S2_8PSK_1_2:
1109 case FEC_S2_QPSK_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1110 case FEC_S2_8PSK_2_3:
1111 case FEC_S2_QPSK_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1112 case FEC_S2_8PSK_3_4:
1113 case FEC_S2_QPSK_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1114 case FEC_S2_8PSK_5_6:
1115 case FEC_S2_QPSK_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1116 case FEC_S2_8PSK_7_8:
1117 case FEC_S2_QPSK_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1118 case FEC_S2_8PSK_8_9:
1119 case FEC_S2_QPSK_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
1120 case FEC_S2_8PSK_3_5:
1121 case FEC_S2_QPSK_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
1122 case FEC_S2_8PSK_4_5:
1123 case FEC_S2_QPSK_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
1124 case FEC_S2_8PSK_9_10:
1125 case FEC_S2_QPSK_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1128 PutToDict(dict, "fec_inner", tmp);
1129 #if HAVE_DVB_API_VERSION >=3
1130 PutToDict(dict, "modulation",
1131 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ?
1132 eDVBFrontendParametersSatellite::Modulation_8PSK :
1133 eDVBFrontendParametersSatellite::Modulation_QPSK );
1134 if (parm_u_qpsk_fec_inner > FEC_AUTO)
1136 switch(parm_inversion & 0xc)
1138 default: // unknown rolloff
1139 case 0: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1140 case 4: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1141 case 8: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1143 PutToDict(dict, "rolloff", tmp);
1144 switch(parm_inversion & 0x30)
1146 case 0: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1147 case 0x10: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1148 case 0x20: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1150 PutToDict(dict, "pilot", tmp);
1151 tmp = eDVBFrontendParametersSatellite::System_DVB_S2;
1154 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1156 PutToDict(dict, "modulation", eDVBFrontendParametersSatellite::Modulation_QPSK );
1157 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1159 PutToDict(dict, "system", tmp);
1163 static void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1166 #if HAVE_DVB_API_VERSION < 3
1167 PutToDict(dict, "frequency", parm_frequency);
1169 PutToDict(dict, "frequency", parm_frequency/1000);
1171 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1172 switch(parm_u_qam_fec_inner)
1174 case FEC_NONE: tmp = eDVBFrontendParametersCable::FEC_None; break;
1175 case FEC_1_2: tmp = eDVBFrontendParametersCable::FEC_1_2; break;
1176 case FEC_2_3: tmp = eDVBFrontendParametersCable::FEC_2_3; break;
1177 case FEC_3_4: tmp = eDVBFrontendParametersCable::FEC_3_4; break;
1178 case FEC_5_6: tmp = eDVBFrontendParametersCable::FEC_5_6; break;
1179 case FEC_7_8: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1180 #if HAVE_DVB_API_VERSION >= 3
1181 case FEC_8_9: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1184 case FEC_AUTO: tmp = eDVBFrontendParametersCable::FEC_Auto; break;
1186 PutToDict(dict, "fec_inner", tmp);
1187 switch(parm_u_qam_modulation)
1189 case QAM_16: tmp = eDVBFrontendParametersCable::Modulation_QAM16; break;
1190 case QAM_32: tmp = eDVBFrontendParametersCable::Modulation_QAM32; break;
1191 case QAM_64: tmp = eDVBFrontendParametersCable::Modulation_QAM64; break;
1192 case QAM_128: tmp = eDVBFrontendParametersCable::Modulation_QAM128; break;
1193 case QAM_256: tmp = eDVBFrontendParametersCable::Modulation_QAM256; break;
1195 case QAM_AUTO: tmp = eDVBFrontendParametersCable::Modulation_Auto; break;
1197 PutToDict(dict, "modulation", tmp);
1200 static void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1203 PutToDict(dict, "frequency", parm_frequency);
1204 switch (parm_u_ofdm_bandwidth)
1206 case BANDWIDTH_8_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_8MHz; break;
1207 case BANDWIDTH_7_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_7MHz; break;
1208 case BANDWIDTH_6_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_6MHz; break;
1210 case BANDWIDTH_AUTO: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_Auto; break;
1212 PutToDict(dict, "bandwidth", tmp);
1213 switch (parm_u_ofdm_code_rate_LP)
1215 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1216 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1217 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1218 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1219 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1221 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1223 PutToDict(dict, "code_rate_lp", tmp);
1224 switch (parm_u_ofdm_code_rate_HP)
1226 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1227 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1228 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1229 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1230 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1232 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1234 PutToDict(dict, "code_rate_hp", tmp);
1235 switch (parm_u_ofdm_constellation)
1237 case QPSK: tmp = eDVBFrontendParametersTerrestrial::Modulation_QPSK; break;
1238 case QAM_16: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM16; break;
1239 case QAM_64: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM64; break;
1241 case QAM_AUTO: tmp = eDVBFrontendParametersTerrestrial::Modulation_Auto; break;
1243 PutToDict(dict, "constellation", tmp);
1244 switch (parm_u_ofdm_transmission_mode)
1246 case TRANSMISSION_MODE_2K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_2k; break;
1247 case TRANSMISSION_MODE_8K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_8k; break;
1249 case TRANSMISSION_MODE_AUTO: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto; break;
1251 PutToDict(dict, "transmission_mode", tmp);
1252 switch (parm_u_ofdm_guard_interval)
1254 case GUARD_INTERVAL_1_32: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_32; break;
1255 case GUARD_INTERVAL_1_16: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_16; break;
1256 case GUARD_INTERVAL_1_8: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_8; break;
1257 case GUARD_INTERVAL_1_4: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_4; break;
1259 case GUARD_INTERVAL_AUTO: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_Auto; break;
1261 PutToDict(dict, "guard_interval", tmp);
1262 switch (parm_u_ofdm_hierarchy_information)
1264 case HIERARCHY_NONE: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_None; break;
1265 case HIERARCHY_1: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_1; break;
1266 case HIERARCHY_2: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_2; break;
1267 case HIERARCHY_4: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_4; break;
1269 case HIERARCHY_AUTO: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_Auto; break;
1271 PutToDict(dict, "hierarchy_information", tmp);
1274 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1276 if (dest && PyDict_Check(dest))
1278 const char *tmp = "UNKNOWN";
1299 PutToDict(dest, "tuner_state", tmp);
1300 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1301 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1302 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1303 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1304 int sigQualitydB = readFrontendData(signalQualitydB);
1305 if (sigQualitydB == 0x12345678) // not support yet
1307 ePyObject obj=Py_None;
1309 PutToDict(dest, "tuner_signal_quality_db", obj);
1312 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1313 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1317 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1319 if (dest && PyDict_Check(dest))
1321 FRONTENDPARAMETERS front;
1322 #if HAVE_DVB_API_VERSION >= 5
1323 struct dtv_property p[4];
1324 struct dtv_properties cmdseq;
1327 p[0].cmd = DTV_DELIVERY_SYSTEM;
1328 p[1].cmd = DTV_MODULATION;
1329 p[2].cmd = DTV_ROLLOFF;
1330 p[3].cmd = DTV_PILOT;
1332 if (m_simulate || m_fd == -1 || original)
1334 #if HAVE_DVB_API_VERSION >= 5
1335 else if (m_type == feSatellite && // yet just use new api for DVB-S(2) only
1336 ioctl(m_fd, FE_GET_PROPERTY, &cmdseq)<0)
1338 eDebug("FE_GET_PROPERTY failed (%m)");
1342 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1344 eDebug("FE_GET_FRONTEND failed (%m)");
1352 PutSatelliteDataToDict(dest, oparm.sat);
1355 PutCableDataToDict(dest, oparm.cab);
1358 PutTerrestrialDataToDict(dest, oparm.ter);
1364 FRONTENDPARAMETERS &parm = front;
1365 long tmp = eDVBFrontendParametersSatellite::Inversion_Unknown;
1366 switch(parm_inversion & 3)
1369 tmp = eDVBFrontendParametersSatellite::Inversion_On;
1372 tmp = eDVBFrontendParametersSatellite::Inversion_Off;
1376 PutToDict(dest, "inversion", tmp);
1380 #if HAVE_DVB_API_VERSION >= 5
1381 fillDictWithSatelliteData(dest, parm, p, m_data[FREQ_OFFSET], oparm.sat.orbital_position, oparm.sat.polarisation);
1383 fillDictWithSatelliteData(dest, parm, m_data[FREQ_OFFSET], oparm.sat.orbital_position, oparm.sat.polarisation);
1387 fillDictWithCableData(dest, parm);
1390 fillDictWithTerrestrialData(dest, parm);
1397 void eDVBFrontend::getFrontendData(ePyObject dest)
1399 if (dest && PyDict_Check(dest))
1402 PutToDict(dest, "tuner_number", m_slotid);
1418 PutToDict(dest, "tuner_type", tmp);
1422 #ifndef FP_IOCTL_GET_ID
1423 #define FP_IOCTL_GET_ID 0
1425 int eDVBFrontend::readInputpower()
1429 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1431 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1432 FILE *f=fopen(proc_name, "r");
1435 if (fscanf(f, "%d", &power) != 1)
1436 eDebug("read %s failed!! (%m)", proc_name);
1438 eDebug("%s is %d\n", proc_name, power);
1443 // open front prozessor
1444 int fp=::open("/dev/dbox/fp0", O_RDWR);
1447 eDebug("couldn't open fp");
1450 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1451 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1453 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1462 bool eDVBFrontend::setSecSequencePos(int steps)
1464 eDebugNoSimulate("set sequence pos %d", steps);
1469 if (m_sec_sequence.current() != m_sec_sequence.end())
1470 ++m_sec_sequence.current();
1475 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1476 --m_sec_sequence.current();
1482 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1485 eDVBFrontend *sec_fe = this;
1486 eDVBRegisteredFrontend *regFE = 0;
1487 long tmp = m_data[LINKED_PREV_PTR];
1490 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1491 sec_fe = prev->m_frontend;
1492 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1493 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1494 int state = sec_fe->m_state;
1495 // workaround to put the kernel frontend thread into idle state!
1496 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1498 sec_fe->closeFrontend(true);
1499 state = sec_fe->m_state;
1501 // sec_fe is closed... we must reopen it here..
1502 if (state == stateClosed)
1510 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1512 long *sec_fe_data = sec_fe->m_data;
1513 // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1514 switch (m_sec_sequence.current()->cmd)
1516 case eSecCommand::SLEEP:
1517 delay = m_sec_sequence.current()++->msec;
1518 eDebugNoSimulate("[SEC] sleep %dms", delay);
1520 case eSecCommand::GOTO:
1521 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1522 ++m_sec_sequence.current();
1524 case eSecCommand::SET_VOLTAGE:
1526 int voltage = m_sec_sequence.current()++->voltage;
1527 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1528 sec_fe->setVoltage(voltage);
1531 case eSecCommand::IF_VOLTAGE_GOTO:
1533 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1534 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1536 ++m_sec_sequence.current();
1539 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1541 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1542 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1544 ++m_sec_sequence.current();
1547 case eSecCommand::IF_TONE_GOTO:
1549 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1550 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1552 ++m_sec_sequence.current();
1555 case eSecCommand::IF_NOT_TONE_GOTO:
1557 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1558 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1560 ++m_sec_sequence.current();
1563 case eSecCommand::SET_TONE:
1564 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1565 sec_fe->setTone(m_sec_sequence.current()++->tone);
1567 case eSecCommand::SEND_DISEQC:
1568 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1569 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1570 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1571 eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1572 if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
1573 eDebugNoSimulate("(DiSEqC reset)");
1574 else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
1575 eDebugNoSimulate("(DiSEqC peripherial power on)");
1577 eDebugNoSimulate("");
1578 ++m_sec_sequence.current();
1580 case eSecCommand::SEND_TONEBURST:
1581 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1582 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1584 case eSecCommand::SET_FRONTEND:
1586 int enableEvents = (m_sec_sequence.current()++)->val;
1587 eDebugNoSimulate("[SEC] setFrontend %d", enableEvents);
1588 setFrontend(enableEvents);
1591 case eSecCommand::START_TUNE_TIMEOUT:
1593 int tuneTimeout = m_sec_sequence.current()->timeout;
1594 eDebugNoSimulate("[SEC] startTuneTimeout %d", tuneTimeout);
1596 m_timeout->start(tuneTimeout, 1);
1597 ++m_sec_sequence.current();
1600 case eSecCommand::SET_TIMEOUT:
1601 m_timeoutCount = m_sec_sequence.current()++->val;
1602 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1604 case eSecCommand::IF_TIMEOUT_GOTO:
1605 if (!m_timeoutCount)
1607 eDebugNoSimulate("[SEC] rotor timout");
1608 setSecSequencePos(m_sec_sequence.current()->steps);
1611 ++m_sec_sequence.current();
1613 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1615 int idx = m_sec_sequence.current()++->val;
1616 if ( idx == 0 || idx == 1 )
1618 m_idleInputpower[idx] = sec_fe->readInputpower();
1619 eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1622 eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1625 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1627 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1628 int idx = compare.val;
1629 if ( !m_simulate && (idx == 0 || idx == 1) )
1631 int idle = sec_fe->readInputpower();
1632 int diff = abs(idle-m_idleInputpower[idx]);
1635 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1636 setSecSequencePos(compare.steps);
1640 ++m_sec_sequence.current();
1643 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1645 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1648 setSecSequencePos(cmd.steps);
1652 int isLocked = readFrontendData(locked);
1653 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1655 if (!m_timeoutCount && m_retryCount > 0)
1657 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 40) || !cmd.lastSignal))
1660 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1663 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1665 cmd.lastSignal = signal;
1668 if (cmd.okcount > 4)
1670 eDebugNoSimulate("ok > 4 .. goto %d\n", cmd.steps);
1671 setSecSequencePos(cmd.steps);
1672 m_state = stateLock;
1673 m_stateChanged(this);
1674 feEvent(-1); // flush events
1682 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1684 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1688 ++m_sec_sequence.current();
1691 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1692 m_runningInputpower = sec_fe->readInputpower();
1693 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1694 ++m_sec_sequence.current();
1696 case eSecCommand::SET_ROTOR_MOVING:
1698 m_sec->setRotorMoving(m_slotid, true);
1699 ++m_sec_sequence.current();
1701 case eSecCommand::SET_ROTOR_STOPPED:
1703 m_sec->setRotorMoving(m_slotid, false);
1704 ++m_sec_sequence.current();
1706 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1708 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1711 setSecSequencePos(cmd.steps);
1714 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1715 const char *txt = cmd.direction ? "running" : "stopped";
1717 if (!m_timeoutCount && m_retryCount > 0)
1719 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1721 m_runningInputpower,
1724 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1725 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1728 eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1729 if ( cmd.okcount > 6 )
1731 eDebugNoSimulate("[SEC] rotor is %s", txt);
1732 if (setSecSequencePos(cmd.steps))
1738 eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1741 ++m_sec_sequence.current();
1744 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1745 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1746 setSecSequencePos(m_sec_sequence.current()->steps);
1748 ++m_sec_sequence.current();
1750 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1751 eDebugNoSimulate("[SEC] invalidate current switch params");
1752 sec_fe_data[CSW] = -1;
1753 sec_fe_data[UCSW] = -1;
1754 sec_fe_data[TONEBURST] = -1;
1755 ++m_sec_sequence.current();
1757 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1758 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1759 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1760 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1761 eDebugNoSimulate("[SEC] update current switch params");
1762 ++m_sec_sequence.current();
1764 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1765 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1766 sec_fe_data[ROTOR_CMD] = -1;
1767 sec_fe_data[ROTOR_POS] = -1;
1768 ++m_sec_sequence.current();
1770 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1771 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1772 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1773 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1774 ++m_sec_sequence.current();
1776 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1777 m_retryCount = m_sec_sequence.current()++->val;
1778 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1780 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1783 eDebugNoSimulate("[SEC] no more rotor retrys");
1784 setSecSequencePos(m_sec_sequence.current()->steps);
1787 ++m_sec_sequence.current();
1789 case eSecCommand::SET_POWER_LIMITING_MODE:
1794 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1795 FILE *f=fopen(proc_name, "w");
1796 if (f) // new interface exist?
1798 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1799 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1800 eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1802 eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1805 else if (sec_fe->m_need_rotor_workaround)
1808 int slotid = sec_fe->m_slotid;
1809 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1811 sprintf(dev, "/dev/i2c/%d", slotid);
1812 else if (slotid == 2)
1813 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1814 else if (slotid == 3)
1815 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1816 int fd = ::open(dev, O_RDWR);
1818 unsigned char data[2];
1819 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1820 if(::read(fd, data, 1) != 1)
1821 eDebugNoSimulate("[SEC] error read lnbp (%m)");
1822 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1824 data[0] |= 0x80; // enable static current limiting
1825 eDebugNoSimulate("[SEC] set static current limiting");
1829 data[0] &= ~0x80; // enable dynamic current limiting
1830 eDebugNoSimulate("[SEC] set dynamic current limiting");
1832 if(::write(fd, data, 1) != 1)
1833 eDebugNoSimulate("[SEC] error write lnbp (%m)");
1837 ++m_sec_sequence.current();
1841 eDebugNoSimulate("[SEC] unhandled sec command %d",
1842 ++m_sec_sequence.current()->cmd);
1843 ++m_sec_sequence.current();
1846 m_tuneTimer->start(delay,true);
1850 if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1854 void eDVBFrontend::setFrontend(bool recvEvents)
1858 eDebug("setting frontend %d", m_dvbid);
1861 feEvent(-1); // flush events
1862 #if HAVE_DVB_API_VERSION >= 5
1863 if (m_type == iDVBFrontend::feSatellite)
1865 fe_rolloff_t rolloff = ROLLOFF_35;
1866 fe_pilot_t pilot = PILOT_OFF;
1867 fe_modulation_t modulation = QPSK;
1868 fe_delivery_system_t system = SYS_DVBS;
1869 switch(oparm.sat.system)
1871 case eDVBFrontendParametersSatellite::System_DVB_S: system = SYS_DVBS; break;
1872 case eDVBFrontendParametersSatellite::System_DVB_S2: system = SYS_DVBS2; break;
1874 switch(oparm.sat.modulation)
1876 case eDVBFrontendParametersSatellite::Modulation_QPSK: modulation = QPSK; break;
1877 case eDVBFrontendParametersSatellite::Modulation_8PSK: modulation = PSK_8; break;
1878 case eDVBFrontendParametersSatellite::Modulation_QAM16: modulation = QAM_16; break;
1880 switch(oparm.sat.pilot)
1882 case eDVBFrontendParametersSatellite::Pilot_Off: pilot = PILOT_OFF; break;
1883 case eDVBFrontendParametersSatellite::Pilot_On: pilot = PILOT_ON; break;
1884 case eDVBFrontendParametersSatellite::Pilot_Unknown: pilot = PILOT_AUTO; break;
1886 switch(oparm.sat.rolloff)
1888 case eDVBFrontendParametersSatellite::RollOff_alpha_0_20: rolloff = ROLLOFF_20; break;
1889 case eDVBFrontendParametersSatellite::RollOff_alpha_0_25: rolloff = ROLLOFF_25; break;
1890 case eDVBFrontendParametersSatellite::RollOff_alpha_0_35: rolloff = ROLLOFF_35; break;
1892 struct dtv_property p[10];
1893 struct dtv_properties cmdseq;
1895 p[0].cmd = DTV_CLEAR;
1896 p[1].cmd = DTV_DELIVERY_SYSTEM, p[1].u.data = system;
1897 p[2].cmd = DTV_FREQUENCY, p[2].u.data = parm_frequency;
1898 p[3].cmd = DTV_MODULATION, p[3].u.data = modulation;
1899 p[4].cmd = DTV_SYMBOL_RATE, p[4].u.data = parm_u_qpsk_symbol_rate;
1900 p[5].cmd = DTV_INNER_FEC, p[5].u.data = parm_u_qpsk_fec_inner;
1901 p[6].cmd = DTV_INVERSION, p[6].u.data = parm_inversion;
1902 if (system == SYS_DVBS2)
1904 p[7].cmd = DTV_ROLLOFF, p[7].u.data = rolloff;
1905 p[8].cmd = DTV_PILOT, p[8].u.data = pilot;
1906 p[9].cmd = DTV_TUNE;
1911 p[7].cmd = DTV_TUNE;
1914 if (ioctl(m_fd, FE_SET_PROPERTY, &cmdseq) == -1)
1916 perror("FE_SET_PROPERTY failed");
1923 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1925 perror("FE_SET_FRONTEND failed");
1932 RESULT eDVBFrontend::getFrontendType(int &t)
1940 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1945 eWarning("no SEC module active!");
1948 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1951 #if HAVE_DVB_API_VERSION >= 3
1952 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",
1955 feparm.polarisation,
1959 feparm.orbital_position,
1965 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1968 feparm.polarisation,
1972 feparm.orbital_position);
1974 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1975 switch (feparm.inversion)
1977 case eDVBFrontendParametersSatellite::Inversion_On:
1978 parm_inversion = INVERSION_ON;
1980 case eDVBFrontendParametersSatellite::Inversion_Off:
1981 parm_inversion = INVERSION_OFF;
1984 case eDVBFrontendParametersSatellite::Inversion_Unknown:
1985 parm_inversion = INVERSION_AUTO;
1988 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S)
1992 case eDVBFrontendParametersSatellite::FEC_None:
1993 parm_u_qpsk_fec_inner = FEC_NONE;
1995 case eDVBFrontendParametersSatellite::FEC_1_2:
1996 parm_u_qpsk_fec_inner = FEC_1_2;
1998 case eDVBFrontendParametersSatellite::FEC_2_3:
1999 parm_u_qpsk_fec_inner = FEC_2_3;
2001 case eDVBFrontendParametersSatellite::FEC_3_4:
2002 parm_u_qpsk_fec_inner = FEC_3_4;
2004 case eDVBFrontendParametersSatellite::FEC_5_6:
2005 parm_u_qpsk_fec_inner = FEC_5_6;
2007 case eDVBFrontendParametersSatellite::FEC_7_8:
2008 parm_u_qpsk_fec_inner = FEC_7_8;
2011 eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
2012 case eDVBFrontendParametersSatellite::FEC_Auto:
2013 parm_u_qpsk_fec_inner = FEC_AUTO;
2017 #if HAVE_DVB_API_VERSION >= 3
2022 case eDVBFrontendParametersSatellite::FEC_1_2:
2023 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
2025 case eDVBFrontendParametersSatellite::FEC_2_3:
2026 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
2028 case eDVBFrontendParametersSatellite::FEC_3_4:
2029 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
2031 case eDVBFrontendParametersSatellite::FEC_3_5:
2032 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
2034 case eDVBFrontendParametersSatellite::FEC_4_5:
2035 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
2037 case eDVBFrontendParametersSatellite::FEC_5_6:
2038 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
2040 case eDVBFrontendParametersSatellite::FEC_7_8:
2041 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
2043 case eDVBFrontendParametersSatellite::FEC_8_9:
2044 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
2046 case eDVBFrontendParametersSatellite::FEC_9_10:
2047 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
2050 eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
2053 #if HAVE_DVB_API_VERSION < 5
2054 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
2055 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
2056 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation_8PSK)
2058 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
2059 // 8PSK fec driver values are decimal 9 bigger
2064 // FIXME !!! get frequency range from tuner
2065 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
2067 eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
2070 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
2076 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
2078 #if HAVE_DVB_API_VERSION < 3
2079 parm_frequency = feparm.frequency;
2081 parm_frequency = feparm.frequency * 1000;
2083 parm_u_qam_symbol_rate = feparm.symbol_rate;
2084 switch (feparm.modulation)
2086 case eDVBFrontendParametersCable::Modulation_QAM16:
2087 parm_u_qam_modulation = QAM_16;
2089 case eDVBFrontendParametersCable::Modulation_QAM32:
2090 parm_u_qam_modulation = QAM_32;
2092 case eDVBFrontendParametersCable::Modulation_QAM64:
2093 parm_u_qam_modulation = QAM_64;
2095 case eDVBFrontendParametersCable::Modulation_QAM128:
2096 parm_u_qam_modulation = QAM_128;
2098 case eDVBFrontendParametersCable::Modulation_QAM256:
2099 parm_u_qam_modulation = QAM_256;
2102 case eDVBFrontendParametersCable::Modulation_Auto:
2103 parm_u_qam_modulation = QAM_AUTO;
2106 switch (feparm.inversion)
2108 case eDVBFrontendParametersCable::Inversion_On:
2109 parm_inversion = INVERSION_ON;
2111 case eDVBFrontendParametersCable::Inversion_Off:
2112 parm_inversion = INVERSION_OFF;
2115 case eDVBFrontendParametersCable::Inversion_Unknown:
2116 parm_inversion = INVERSION_AUTO;
2119 switch (feparm.fec_inner)
2121 case eDVBFrontendParametersCable::FEC_None:
2122 parm_u_qam_fec_inner = FEC_NONE;
2124 case eDVBFrontendParametersCable::FEC_1_2:
2125 parm_u_qam_fec_inner = FEC_1_2;
2127 case eDVBFrontendParametersCable::FEC_2_3:
2128 parm_u_qam_fec_inner = FEC_2_3;
2130 case eDVBFrontendParametersCable::FEC_3_4:
2131 parm_u_qam_fec_inner = FEC_3_4;
2133 case eDVBFrontendParametersCable::FEC_5_6:
2134 parm_u_qam_fec_inner = FEC_5_6;
2136 case eDVBFrontendParametersCable::FEC_7_8:
2137 parm_u_qam_fec_inner = FEC_7_8;
2139 #if HAVE_DVB_API_VERSION >= 3
2140 case eDVBFrontendParametersCable::FEC_8_9:
2141 parm_u_qam_fec_inner = FEC_8_9;
2145 case eDVBFrontendParametersCable::FEC_Auto:
2146 parm_u_qam_fec_inner = FEC_AUTO;
2149 eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
2150 parm_frequency/1000,
2151 parm_u_qam_symbol_rate,
2152 parm_u_qam_fec_inner,
2153 parm_u_qam_modulation,
2159 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
2161 parm_frequency = feparm.frequency;
2163 switch (feparm.bandwidth)
2165 case eDVBFrontendParametersTerrestrial::Bandwidth_8MHz:
2166 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
2168 case eDVBFrontendParametersTerrestrial::Bandwidth_7MHz:
2169 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
2171 case eDVBFrontendParametersTerrestrial::Bandwidth_6MHz:
2172 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
2175 case eDVBFrontendParametersTerrestrial::Bandwidth_Auto:
2176 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
2179 switch (feparm.code_rate_LP)
2181 case eDVBFrontendParametersTerrestrial::FEC_1_2:
2182 parm_u_ofdm_code_rate_LP = FEC_1_2;
2184 case eDVBFrontendParametersTerrestrial::FEC_2_3:
2185 parm_u_ofdm_code_rate_LP = FEC_2_3;
2187 case eDVBFrontendParametersTerrestrial::FEC_3_4:
2188 parm_u_ofdm_code_rate_LP = FEC_3_4;
2190 case eDVBFrontendParametersTerrestrial::FEC_5_6:
2191 parm_u_ofdm_code_rate_LP = FEC_5_6;
2193 case eDVBFrontendParametersTerrestrial::FEC_7_8:
2194 parm_u_ofdm_code_rate_LP = FEC_7_8;
2197 case eDVBFrontendParametersTerrestrial::FEC_Auto:
2198 parm_u_ofdm_code_rate_LP = FEC_AUTO;
2201 switch (feparm.code_rate_HP)
2203 case eDVBFrontendParametersTerrestrial::FEC_1_2:
2204 parm_u_ofdm_code_rate_HP = FEC_1_2;
2206 case eDVBFrontendParametersTerrestrial::FEC_2_3:
2207 parm_u_ofdm_code_rate_HP = FEC_2_3;
2209 case eDVBFrontendParametersTerrestrial::FEC_3_4:
2210 parm_u_ofdm_code_rate_HP = FEC_3_4;
2212 case eDVBFrontendParametersTerrestrial::FEC_5_6:
2213 parm_u_ofdm_code_rate_HP = FEC_5_6;
2215 case eDVBFrontendParametersTerrestrial::FEC_7_8:
2216 parm_u_ofdm_code_rate_HP = FEC_7_8;
2219 case eDVBFrontendParametersTerrestrial::FEC_Auto:
2220 parm_u_ofdm_code_rate_HP = FEC_AUTO;
2223 switch (feparm.modulation)
2225 case eDVBFrontendParametersTerrestrial::Modulation_QPSK:
2226 parm_u_ofdm_constellation = QPSK;
2228 case eDVBFrontendParametersTerrestrial::Modulation_QAM16:
2229 parm_u_ofdm_constellation = QAM_16;
2231 case eDVBFrontendParametersTerrestrial::Modulation_QAM64:
2232 parm_u_ofdm_constellation = QAM_64;
2235 case eDVBFrontendParametersTerrestrial::Modulation_Auto:
2236 parm_u_ofdm_constellation = QAM_AUTO;
2239 switch (feparm.transmission_mode)
2241 case eDVBFrontendParametersTerrestrial::TransmissionMode_2k:
2242 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2244 case eDVBFrontendParametersTerrestrial::TransmissionMode_8k:
2245 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2248 case eDVBFrontendParametersTerrestrial::TransmissionMode_Auto:
2249 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2252 switch (feparm.guard_interval)
2254 case eDVBFrontendParametersTerrestrial::GuardInterval_1_32:
2255 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2257 case eDVBFrontendParametersTerrestrial::GuardInterval_1_16:
2258 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2260 case eDVBFrontendParametersTerrestrial::GuardInterval_1_8:
2261 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2263 case eDVBFrontendParametersTerrestrial::GuardInterval_1_4:
2264 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2267 case eDVBFrontendParametersTerrestrial::GuardInterval_Auto:
2268 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2271 switch (feparm.hierarchy)
2273 case eDVBFrontendParametersTerrestrial::Hierarchy_None:
2274 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2276 case eDVBFrontendParametersTerrestrial::Hierarchy_1:
2277 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2279 case eDVBFrontendParametersTerrestrial::Hierarchy_2:
2280 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2282 case eDVBFrontendParametersTerrestrial::Hierarchy_4:
2283 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2286 case eDVBFrontendParametersTerrestrial::Hierarchy_Auto:
2287 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2290 switch (feparm.inversion)
2292 case eDVBFrontendParametersTerrestrial::Inversion_On:
2293 parm_inversion = INVERSION_ON;
2295 case eDVBFrontendParametersTerrestrial::Inversion_Off:
2296 parm_inversion = INVERSION_OFF;
2299 case eDVBFrontendParametersTerrestrial::Inversion_Unknown:
2300 parm_inversion = INVERSION_AUTO;
2307 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2309 unsigned int timeout = 5000;
2310 eDebugNoSimulate("(%d)tune", m_dvbid);
2316 if (!m_sn && !m_simulate)
2318 eDebug("no frontend device opened... do not try to tune !!!");
2332 m_sec_sequence.clear();
2334 where.calcLockTimeout(timeout);
2340 eDVBFrontendParametersSatellite feparm;
2341 if (where.getDVBS(feparm))
2343 eDebug("no dvbs data!");
2347 if (m_rotor_mode != feparm.no_rotor_command_on_tune && !feparm.no_rotor_command_on_tune)
2349 eDVBFrontend *sec_fe = this;
2350 long tmp = m_data[LINKED_PREV_PTR];
2353 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
2354 sec_fe = linked_fe->m_frontend;
2355 sec_fe->getData(LINKED_NEXT_PTR, tmp);
2357 eDebug("(fe%d) reset diseqc after leave rotor mode!", m_dvbid);
2358 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
2360 m_rotor_mode = feparm.no_rotor_command_on_tune;
2362 m_sec->setRotorMoving(m_slotid, false);
2363 res=prepare_sat(feparm, timeout);
2371 eDVBFrontendParametersCable feparm;
2372 if (where.getDVBC(feparm))
2377 res=prepare_cable(feparm);
2381 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2382 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2387 eDVBFrontendParametersTerrestrial feparm;
2388 if (where.getDVBT(feparm))
2390 eDebug("no -T data");
2394 res=prepare_terrestrial(feparm);
2398 std::string enable_5V;
2399 char configStr[255];
2400 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2401 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2402 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2403 if (enable_5V == "True")
2404 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2406 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2407 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2413 m_sec_sequence.current() = m_sec_sequence.begin();
2417 m_tuneTimer->start(0,true);
2419 if (m_state != stateTuning)
2421 m_state = stateTuning;
2422 m_stateChanged(this);
2431 m_tuneTimer->stop();
2435 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2437 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2441 RESULT eDVBFrontend::setVoltage(int voltage)
2443 if (m_type == feCable)
2445 #if HAVE_DVB_API_VERSION < 3
2448 bool increased=false;
2449 fe_sec_voltage_t vlt;
2451 m_data[CUR_VOLTAGE]=voltage;
2455 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2456 vlt = SEC_VOLTAGE_OFF;
2459 #if HAVE_DVB_API_VERSION < 3
2460 vlt = SEC_VOLTAGE_13_5;
2466 vlt = SEC_VOLTAGE_13;
2469 #if HAVE_DVB_API_VERSION < 3
2470 vlt = SEC_VOLTAGE_18_5;
2476 vlt = SEC_VOLTAGE_18;
2483 #if HAVE_DVB_API_VERSION < 3
2484 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2486 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2487 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2488 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2492 RESULT eDVBFrontend::getState(int &state)
2498 RESULT eDVBFrontend::setTone(int t)
2500 if (m_type != feSatellite)
2502 #if HAVE_DVB_API_VERSION < 3
2505 fe_sec_tone_mode_t tone;
2514 tone = SEC_TONE_OFF;
2521 #if HAVE_DVB_API_VERSION < 3
2522 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2524 return ::ioctl(m_fd, FE_SET_TONE, tone);
2528 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2529 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2532 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2536 #if HAVE_DVB_API_VERSION < 3
2537 struct secCommand cmd;
2538 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2539 cmd.u.diseqc.cmdtype = diseqc.data[0];
2540 cmd.u.diseqc.addr = diseqc.data[1];
2541 cmd.u.diseqc.cmd = diseqc.data[2];
2542 cmd.u.diseqc.numParams = diseqc.len-3;
2543 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2544 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2546 struct dvb_diseqc_master_cmd cmd;
2547 memcpy(cmd.msg, diseqc.data, diseqc.len);
2548 cmd.msg_len = diseqc.len;
2549 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2555 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2556 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2558 RESULT eDVBFrontend::sendToneburst(int burst)
2562 #if HAVE_DVB_API_VERSION < 3
2563 secMiniCmd cmd = SEC_MINI_NONE;
2565 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2567 if ( burst == eDVBSatelliteDiseqcParameters::A )
2569 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2571 #if HAVE_DVB_API_VERSION < 3
2572 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2575 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2581 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2587 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2589 m_sec_sequence = list;
2593 RESULT eDVBFrontend::getData(int num, long &data)
2595 if ( num < NUM_DATA_ENTRIES )
2603 RESULT eDVBFrontend::setData(int num, long val)
2605 if ( num < NUM_DATA_ENTRIES )
2613 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2616 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2618 if (m_type == eDVBFrontend::feSatellite)
2621 eDVBFrontendParametersSatellite sat_parm;
2622 int ret = feparm->getDVBS(sat_parm);
2624 if (sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S2 && !m_can_handle_dvbs2)
2626 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2627 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S && m_can_handle_dvbs2)
2631 else if (m_type == eDVBFrontend::feCable)
2632 return 2; // more prio for cable frontends
2633 else if (m_type == eDVBFrontend::feTerrestrial)
2638 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2640 ePyObject Id, Descr, Enabled, IsDVBS2;
2641 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4)
2643 Id = PyTuple_GET_ITEM(obj, 0);
2644 Descr = PyTuple_GET_ITEM(obj, 1);
2645 Enabled = PyTuple_GET_ITEM(obj, 2);
2646 IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2647 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2))
2649 strcpy(m_description, PyString_AS_STRING(Descr));
2650 m_slotid = PyInt_AsLong(Id);
2651 m_enabled = Enabled == Py_True;
2652 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2653 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2654 !!strstr(m_description, "Alps BSBE2") ||
2655 !!strstr(m_description, "Alps -S") ||
2656 !!strstr(m_description, "BCM4501");
2657 m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2658 eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2659 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2662 PyErr_SetString(PyExc_StandardError,
2663 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");
2667 RESULT eDVBFrontend::turnOffSatCR(int satcr)
2669 eSecCommandList sec_sequence;
2670 // check if voltage is disabled
2671 eSecCommand::pair compare;
2672 compare.steps = +9; //nothing to do
2673 compare.voltage = iDVBFrontend::voltageOff;
2674 sec_sequence.push_back( eSecCommand(eSecCommand::IF_NOT_VOLTAGE_GOTO, compare) );
2675 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2676 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50 ) );
2678 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage18_5) );
2679 sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
2680 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 250) );
2682 eDVBDiseqcCommand diseqc;
2683 memset(diseqc.data, 0, MAX_DISEQC_LENGTH);
2685 diseqc.data[0] = 0xE0;
2686 diseqc.data[1] = 0x10;
2687 diseqc.data[2] = 0x5A;
2688 diseqc.data[3] = satcr << 5;
2689 diseqc.data[4] = 0x00;
2691 sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
2692 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50+20+14*diseqc.len) );
2693 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2694 setSecSequence(sec_sequence);
2698 RESULT eDVBFrontend::ScanSatCR()
2702 setTone(iDVBFrontend::toneOff);