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_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;
695 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
698 if (m_state != state)
701 m_stateChanged(this);
706 void eDVBFrontend::timeout()
709 if (m_state == stateTuning)
711 m_state = stateFailed;
712 m_stateChanged(this);
716 #define INRANGE(X,Y,Z) (((X<=Y) && (Y<=Z))||((Z<=Y) && (Y<=X)) ? 1 : 0)
718 /* unsigned 32 bit division */
719 static inline uint32_t fe_udiv(uint32_t a, uint32_t b)
721 return (a + b / 2) / b;
724 int eDVBFrontend::readFrontendData(int type)
733 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
734 eDebug("FE_READ_BER failed (%m)");
739 case signalQualitydB: /* this will move into the driver */
741 int sat_max = 1600; // for stv0288 / bsbe2
742 int ret = 0x12345678;
746 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
747 eDebug("FE_READ_SNR failed (%m)");
748 else if (!strcmp(m_description, "BCM4501 (internal)"))
750 float SDS_SNRE = snr << 16;
753 if (oparm.sat.system == eDVBFrontendParametersSatellite::System_DVB_S) // DVB-S1 / QPSK
755 static float SNR_COEFF[6] = {
758 197418.0 / 4194304.0,
759 -2602183.0 / 4194304.0,
760 20377212.0 / 4194304.0,
761 -37791203.0 / 4194304.0,
763 float fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0)),
764 fval2 = pow(10.0, fval1)-1;
765 fval1 = 10.0 * log10(fval2);
769 fval2 = SNR_COEFF[0];
770 for (int i=1; i<6; ++i)
773 fval2 += SNR_COEFF[i];
779 #if HAVE_DVB_API_VERSION >= 3
782 float fval1 = SDS_SNRE / 268435456.0,
785 if (parm_u_qpsk_fec_inner <= FEC_S2_QPSK_9_10) // DVB-S2 QPSK
796 fval4 = -10.0 * log10(fval1);
798 for (int i=0; i < 5; ++i)
799 fval1 = fval4 - fval2 * log10(1.0+pow(10.0, (fval3-fval1)/fval2));
804 ret = (int)(snr_in_db * 100);
806 else if (strstr(m_description, "Alps BSBE1 C01A") ||
807 strstr(m_description, "Alps -S(STV0288)"))
811 else if (snr == 0xFFFF) // i think this should not happen
815 enum { REALVAL, REGVAL };
816 const long CN_lookup[31][2] = {
817 {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
818 {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
819 {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
820 {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
821 {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
822 {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
825 int add=strchr(m_description, '.') ? 0xA250 : 0xA100;
826 long regval = 0xFFFF - ((snr / 3) + add), // revert some dvb api calulations to get the real register value
830 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
835 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[i][REGVAL]))
840 ret = (((regval - CN_lookup[Imin][REGVAL])
841 * (CN_lookup[Imax][REALVAL] - CN_lookup[Imin][REALVAL])
842 / (CN_lookup[Imax][REGVAL] - CN_lookup[Imin][REGVAL]))
843 + CN_lookup[Imin][REALVAL]) * 10;
849 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
850 !strcmp(m_description, "Alps -S") ||
851 !strcmp(m_description, "Philips -S") ||
852 !strcmp(m_description, "LG -S") )
855 ret = (int)((snr-39075)/17.647);
856 } else if (!strcmp(m_description, "Alps BSBE2"))
858 ret = (int)((snr >> 7) * 10);
859 } else if (!strcmp(m_description, "Philips CU1216Mk3"))
861 int mse = (~snr) & 0xFF;
862 switch (parm_u_qam_modulation) {
863 case QAM_16: ret = fe_udiv(1950000, (32 * mse) + 138) + 1000; break;
864 case QAM_32: ret = fe_udiv(2150000, (40 * mse) + 500) + 1350; break;
865 case QAM_64: ret = fe_udiv(2100000, (40 * mse) + 500) + 1250; break;
866 case QAM_128: ret = fe_udiv(1850000, (38 * mse) + 400) + 1380; break;
867 case QAM_256: ret = fe_udiv(1800000, (100 * mse) + 40) + 2030; break;
870 } else if (!strcmp(m_description, "Philips TU1216"))
872 snr = 0xFF - (snr & 0xFF);
874 ret = 10 * (int)(-100 * (log10(snr) - log10(255)));
876 else if (strstr(m_description, "BCM4506") || strstr(m_description, "BCM4505"))
877 ret = (snr * 100) >> 8;
879 if (type == signalQuality)
881 if (ret == 0x12345678) // no snr db calculation avail.. return untouched snr value..
886 return ret >= sat_max ? 65536 : ret * 65536 / sat_max;
887 case feCable: // we assume a max of 42db here
888 return ret >= 4200 ? 65536 : ret * 65536 / 4200;
889 case feTerrestrial: // we assume a max of 24db here
890 return ret >= 2400 ? 65536 : ret * 65536 / 2400;
894 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
902 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
903 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
909 #if HAVE_DVB_API_VERSION < 3
910 FrontendStatus status=0;
916 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
917 eDebug("FE_READ_STATUS failed (%m)");
918 return !!(status&FE_HAS_LOCK);
924 #if HAVE_DVB_API_VERSION < 3
925 FrontendStatus status=0;
931 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
932 eDebug("FE_READ_STATUS failed (%m)");
933 return !!(status&FE_HAS_SYNC);
943 void PutToDict(ePyObject &dict, const char*key, long value)
945 ePyObject item = PyInt_FromLong(value);
948 if (PyDict_SetItemString(dict, key, item))
949 eDebug("put %s to dict failed", key);
953 eDebug("could not create PyObject for %s", key);
956 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
960 if (PyDict_SetItemString(dict, key, item))
961 eDebug("put %s to dict failed", key);
965 eDebug("invalid PyObject for %s", key);
968 void PutToDict(ePyObject &dict, const char*key, const char *value)
970 ePyObject item = PyString_FromString(value);
973 if (PyDict_SetItemString(dict, key, item))
974 eDebug("put %s to dict failed", key);
978 eDebug("could not create PyObject for %s", key);
981 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
983 PutToDict(dict, "tuner_type", "DVB-S");
984 PutToDict(dict, "frequency", feparm.frequency);
985 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
986 PutToDict(dict, "orbital_position", feparm.orbital_position);
987 PutToDict(dict, "inversion", feparm.inversion);
988 PutToDict(dict, "fec_inner", feparm.fec);
989 PutToDict(dict, "modulation", feparm.modulation);
990 PutToDict(dict, "polarization", feparm.polarisation);
991 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S2)
993 PutToDict(dict, "rolloff", feparm.rolloff);
994 PutToDict(dict, "pilot", feparm.pilot);
996 PutToDict(dict, "system", feparm.system);
999 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
1001 PutToDict(dict, "tuner_type", "DVB-T");
1002 PutToDict(dict, "frequency", feparm.frequency);
1003 PutToDict(dict, "bandwidth", feparm.bandwidth);
1004 PutToDict(dict, "code_rate_lp", feparm.code_rate_LP);
1005 PutToDict(dict, "code_rate_hp", feparm.code_rate_HP);
1006 PutToDict(dict, "constellation", feparm.modulation);
1007 PutToDict(dict, "transmission_mode", feparm.transmission_mode);
1008 PutToDict(dict, "guard_interval", feparm.guard_interval);
1009 PutToDict(dict, "hierarchy_information", feparm.hierarchy);
1010 PutToDict(dict, "inversion", feparm.inversion);
1013 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
1015 PutToDict(dict, "tuner_type", "DVB-C");
1016 PutToDict(dict, "frequency", feparm.frequency);
1017 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
1018 PutToDict(dict, "modulation", feparm.modulation);
1019 PutToDict(dict, "inversion", feparm.inversion);
1020 PutToDict(dict, "fec_inner", feparm.fec_inner);
1023 #if HAVE_DVB_API_VERSION >= 5
1024 static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, struct dtv_property *p, long freq_offset, int orb_pos, int polarization)
1027 int frequency = parm_frequency + freq_offset;
1028 PutToDict(dict, "frequency", frequency);
1029 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
1030 PutToDict(dict, "orbital_position", orb_pos);
1031 PutToDict(dict, "polarization", polarization);
1033 switch(parm_u_qpsk_fec_inner)
1035 case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1036 case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1037 case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1038 case FEC_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
1039 case FEC_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
1040 case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1041 case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1042 case FEC_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
1043 case FEC_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1044 case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
1045 case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
1046 default: eDebug("got unsupported FEC from frontend! report as FEC_AUTO!\n");
1049 switch (p[0].u.data)
1051 default: eDebug("got unsupported system from frontend! report as DVBS!");
1052 case SYS_DVBS: tmp = eDVBFrontendParametersSatellite::System_DVB_S; break;
1055 switch (p[2].u.data)
1057 default: eDebug("got unsupported rolloff from frontend! report as 0_20!");
1058 case ROLLOFF_20: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1059 case ROLLOFF_25: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1060 case ROLLOFF_35: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1062 PutToDict(dict, "rolloff", tmp);
1064 switch (p[3].u.data)
1066 case PILOT_OFF: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1067 case PILOT_ON: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1068 case PILOT_AUTO: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1070 PutToDict(dict, "pilot", tmp);
1072 tmp = eDVBFrontendParametersSatellite::System_DVB_S2; break;
1075 PutToDict(dict, "system", tmp);
1077 switch (p[1].u.data)
1079 default: eDebug("got unsupported modulation from frontend! report as QPSK!");
1080 case QPSK: tmp = eDVBFrontendParametersSatellite::Modulation_QPSK; break;
1081 case PSK_8: tmp = eDVBFrontendParametersSatellite::Modulation_8PSK; break;
1083 PutToDict(dict, "modulation", tmp);
1087 static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, long freq_offset, int orb_pos, int polarization)
1090 int frequency = parm_frequency + freq_offset;
1091 PutToDict(dict, "frequency", frequency);
1092 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
1093 PutToDict(dict, "orbital_position", orb_pos);
1094 PutToDict(dict, "polarization", polarization);
1096 switch(parm_u_qpsk_fec_inner)
1098 case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1099 case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1100 case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1101 case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1102 case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1103 case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
1105 case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
1106 #if HAVE_DVB_API_VERSION >=3
1107 case FEC_S2_8PSK_1_2:
1108 case FEC_S2_QPSK_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1109 case FEC_S2_8PSK_2_3:
1110 case FEC_S2_QPSK_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1111 case FEC_S2_8PSK_3_4:
1112 case FEC_S2_QPSK_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1113 case FEC_S2_8PSK_5_6:
1114 case FEC_S2_QPSK_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1115 case FEC_S2_8PSK_7_8:
1116 case FEC_S2_QPSK_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1117 case FEC_S2_8PSK_8_9:
1118 case FEC_S2_QPSK_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
1119 case FEC_S2_8PSK_3_5:
1120 case FEC_S2_QPSK_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
1121 case FEC_S2_8PSK_4_5:
1122 case FEC_S2_QPSK_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
1123 case FEC_S2_8PSK_9_10:
1124 case FEC_S2_QPSK_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1127 PutToDict(dict, "fec_inner", tmp);
1128 #if HAVE_DVB_API_VERSION >=3
1129 PutToDict(dict, "modulation",
1130 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ?
1131 eDVBFrontendParametersSatellite::Modulation_8PSK :
1132 eDVBFrontendParametersSatellite::Modulation_QPSK );
1133 if (parm_u_qpsk_fec_inner > FEC_AUTO)
1135 switch(parm_inversion & 0xc)
1137 default: // unknown rolloff
1138 case 0: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1139 case 4: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1140 case 8: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1142 PutToDict(dict, "rolloff", tmp);
1143 switch(parm_inversion & 0x30)
1145 case 0: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1146 case 0x10: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1147 case 0x20: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1149 PutToDict(dict, "pilot", tmp);
1150 tmp = eDVBFrontendParametersSatellite::System_DVB_S2;
1153 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1155 PutToDict(dict, "modulation", eDVBFrontendParametersSatellite::Modulation_QPSK );
1156 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1158 PutToDict(dict, "system", tmp);
1162 static void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1165 #if HAVE_DVB_API_VERSION < 3
1166 PutToDict(dict, "frequency", parm_frequency);
1168 PutToDict(dict, "frequency", parm_frequency/1000);
1170 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1171 switch(parm_u_qam_fec_inner)
1173 case FEC_NONE: tmp = eDVBFrontendParametersCable::FEC_None; break;
1174 case FEC_1_2: tmp = eDVBFrontendParametersCable::FEC_1_2; break;
1175 case FEC_2_3: tmp = eDVBFrontendParametersCable::FEC_2_3; break;
1176 case FEC_3_4: tmp = eDVBFrontendParametersCable::FEC_3_4; break;
1177 case FEC_5_6: tmp = eDVBFrontendParametersCable::FEC_5_6; break;
1178 case FEC_7_8: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1179 #if HAVE_DVB_API_VERSION >= 3
1180 case FEC_8_9: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1183 case FEC_AUTO: tmp = eDVBFrontendParametersCable::FEC_Auto; break;
1185 PutToDict(dict, "fec_inner", tmp);
1186 switch(parm_u_qam_modulation)
1188 case QAM_16: tmp = eDVBFrontendParametersCable::Modulation_QAM16; break;
1189 case QAM_32: tmp = eDVBFrontendParametersCable::Modulation_QAM32; break;
1190 case QAM_64: tmp = eDVBFrontendParametersCable::Modulation_QAM64; break;
1191 case QAM_128: tmp = eDVBFrontendParametersCable::Modulation_QAM128; break;
1192 case QAM_256: tmp = eDVBFrontendParametersCable::Modulation_QAM256; break;
1194 case QAM_AUTO: tmp = eDVBFrontendParametersCable::Modulation_Auto; break;
1196 PutToDict(dict, "modulation", tmp);
1199 static void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1202 PutToDict(dict, "frequency", parm_frequency);
1203 switch (parm_u_ofdm_bandwidth)
1205 case BANDWIDTH_8_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_8MHz; break;
1206 case BANDWIDTH_7_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_7MHz; break;
1207 case BANDWIDTH_6_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_6MHz; break;
1209 case BANDWIDTH_AUTO: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_Auto; break;
1211 PutToDict(dict, "bandwidth", tmp);
1212 switch (parm_u_ofdm_code_rate_LP)
1214 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1215 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1216 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1217 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1218 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1220 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1222 PutToDict(dict, "code_rate_lp", tmp);
1223 switch (parm_u_ofdm_code_rate_HP)
1225 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1226 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1227 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1228 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1229 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1231 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1233 PutToDict(dict, "code_rate_hp", tmp);
1234 switch (parm_u_ofdm_constellation)
1236 case QPSK: tmp = eDVBFrontendParametersTerrestrial::Modulation_QPSK; break;
1237 case QAM_16: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM16; break;
1238 case QAM_64: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM64; break;
1240 case QAM_AUTO: tmp = eDVBFrontendParametersTerrestrial::Modulation_Auto; break;
1242 PutToDict(dict, "constellation", tmp);
1243 switch (parm_u_ofdm_transmission_mode)
1245 case TRANSMISSION_MODE_2K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_2k; break;
1246 case TRANSMISSION_MODE_8K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_8k; break;
1248 case TRANSMISSION_MODE_AUTO: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto; break;
1250 PutToDict(dict, "transmission_mode", tmp);
1251 switch (parm_u_ofdm_guard_interval)
1253 case GUARD_INTERVAL_1_32: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_32; break;
1254 case GUARD_INTERVAL_1_16: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_16; break;
1255 case GUARD_INTERVAL_1_8: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_8; break;
1256 case GUARD_INTERVAL_1_4: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_4; break;
1258 case GUARD_INTERVAL_AUTO: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_Auto; break;
1260 PutToDict(dict, "guard_interval", tmp);
1261 switch (parm_u_ofdm_hierarchy_information)
1263 case HIERARCHY_NONE: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_None; break;
1264 case HIERARCHY_1: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_1; break;
1265 case HIERARCHY_2: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_2; break;
1266 case HIERARCHY_4: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_4; break;
1268 case HIERARCHY_AUTO: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_Auto; break;
1270 PutToDict(dict, "hierarchy_information", tmp);
1273 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1275 if (dest && PyDict_Check(dest))
1277 const char *tmp = "UNKNOWN";
1298 PutToDict(dest, "tuner_state", tmp);
1299 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1300 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1301 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1302 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1303 int sigQualitydB = readFrontendData(signalQualitydB);
1304 if (sigQualitydB == 0x12345678) // not support yet
1306 ePyObject obj=Py_None;
1308 PutToDict(dest, "tuner_signal_quality_db", obj);
1311 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1312 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1316 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1318 if (dest && PyDict_Check(dest))
1320 FRONTENDPARAMETERS front;
1321 #if HAVE_DVB_API_VERSION >= 5
1322 struct dtv_property p[4];
1323 struct dtv_properties cmdseq;
1326 p[0].cmd = DTV_DELIVERY_SYSTEM;
1327 p[1].cmd = DTV_MODULATION;
1328 p[2].cmd = DTV_ROLLOFF;
1329 p[3].cmd = DTV_PILOT;
1331 if (m_simulate || m_fd == -1 || original)
1333 #if HAVE_DVB_API_VERSION >= 5
1334 else if (m_type == feSatellite && // yet just use new api for DVB-S(2) only
1335 ioctl(m_fd, FE_GET_PROPERTY, &cmdseq)<0)
1337 eDebug("FE_GET_PROPERTY failed (%m)");
1341 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1343 eDebug("FE_GET_FRONTEND failed (%m)");
1351 PutSatelliteDataToDict(dest, oparm.sat);
1354 PutCableDataToDict(dest, oparm.cab);
1357 PutTerrestrialDataToDict(dest, oparm.ter);
1363 FRONTENDPARAMETERS &parm = front;
1364 long tmp = eDVBFrontendParametersSatellite::Inversion_Unknown;
1365 switch(parm_inversion & 3)
1368 tmp = eDVBFrontendParametersSatellite::Inversion_On;
1371 tmp = eDVBFrontendParametersSatellite::Inversion_Off;
1375 PutToDict(dest, "inversion", tmp);
1379 #if HAVE_DVB_API_VERSION >= 5
1380 fillDictWithSatelliteData(dest, parm, p, m_data[FREQ_OFFSET], oparm.sat.orbital_position, oparm.sat.polarisation);
1382 fillDictWithSatelliteData(dest, parm, m_data[FREQ_OFFSET], oparm.sat.orbital_position, oparm.sat.polarisation);
1386 fillDictWithCableData(dest, parm);
1389 fillDictWithTerrestrialData(dest, parm);
1396 void eDVBFrontend::getFrontendData(ePyObject dest)
1398 if (dest && PyDict_Check(dest))
1401 PutToDict(dest, "tuner_number", m_slotid);
1417 PutToDict(dest, "tuner_type", tmp);
1421 #ifndef FP_IOCTL_GET_ID
1422 #define FP_IOCTL_GET_ID 0
1424 int eDVBFrontend::readInputpower()
1428 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1430 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1431 FILE *f=fopen(proc_name, "r");
1434 if (fscanf(f, "%d", &power) != 1)
1435 eDebug("read %s failed!! (%m)", proc_name);
1437 eDebug("%s is %d\n", proc_name, power);
1442 // open front prozessor
1443 int fp=::open("/dev/dbox/fp0", O_RDWR);
1446 eDebug("couldn't open fp");
1449 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1450 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1452 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1461 bool eDVBFrontend::setSecSequencePos(int steps)
1463 eDebugNoSimulate("set sequence pos %d", steps);
1468 if (m_sec_sequence.current() != m_sec_sequence.end())
1469 ++m_sec_sequence.current();
1474 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1475 --m_sec_sequence.current();
1481 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1484 eDVBFrontend *sec_fe = this;
1485 eDVBRegisteredFrontend *regFE = 0;
1486 long tmp = m_data[LINKED_PREV_PTR];
1489 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1490 sec_fe = prev->m_frontend;
1491 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1492 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1493 int state = sec_fe->m_state;
1494 // workaround to put the kernel frontend thread into idle state!
1495 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1497 sec_fe->closeFrontend(true);
1498 state = sec_fe->m_state;
1500 // sec_fe is closed... we must reopen it here..
1501 if (state == stateClosed)
1509 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1511 long *sec_fe_data = sec_fe->m_data;
1512 // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1513 switch (m_sec_sequence.current()->cmd)
1515 case eSecCommand::SLEEP:
1516 delay = m_sec_sequence.current()++->msec;
1517 eDebugNoSimulate("[SEC] sleep %dms", delay);
1519 case eSecCommand::GOTO:
1520 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1521 ++m_sec_sequence.current();
1523 case eSecCommand::SET_VOLTAGE:
1525 int voltage = m_sec_sequence.current()++->voltage;
1526 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1527 sec_fe->setVoltage(voltage);
1530 case eSecCommand::IF_VOLTAGE_GOTO:
1532 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1533 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1535 ++m_sec_sequence.current();
1538 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1540 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1541 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1543 ++m_sec_sequence.current();
1546 case eSecCommand::IF_TONE_GOTO:
1548 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1549 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1551 ++m_sec_sequence.current();
1554 case eSecCommand::IF_NOT_TONE_GOTO:
1556 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1557 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1559 ++m_sec_sequence.current();
1562 case eSecCommand::SET_TONE:
1563 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1564 sec_fe->setTone(m_sec_sequence.current()++->tone);
1566 case eSecCommand::SEND_DISEQC:
1567 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1568 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1569 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1570 eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1571 if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
1572 eDebugNoSimulate("(DiSEqC reset)");
1573 else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
1574 eDebugNoSimulate("(DiSEqC peripherial power on)");
1576 eDebugNoSimulate("");
1577 ++m_sec_sequence.current();
1579 case eSecCommand::SEND_TONEBURST:
1580 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1581 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1583 case eSecCommand::SET_FRONTEND:
1585 int enableEvents = (m_sec_sequence.current()++)->val;
1586 eDebugNoSimulate("[SEC] setFrontend %d", enableEvents);
1587 setFrontend(enableEvents);
1590 case eSecCommand::START_TUNE_TIMEOUT:
1592 int tuneTimeout = m_sec_sequence.current()->timeout;
1593 eDebugNoSimulate("[SEC] startTuneTimeout %d", tuneTimeout);
1595 m_timeout->start(tuneTimeout, 1);
1596 ++m_sec_sequence.current();
1599 case eSecCommand::SET_TIMEOUT:
1600 m_timeoutCount = m_sec_sequence.current()++->val;
1601 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1603 case eSecCommand::IF_TIMEOUT_GOTO:
1604 if (!m_timeoutCount)
1606 eDebugNoSimulate("[SEC] rotor timout");
1607 setSecSequencePos(m_sec_sequence.current()->steps);
1610 ++m_sec_sequence.current();
1612 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1614 int idx = m_sec_sequence.current()++->val;
1615 if ( idx == 0 || idx == 1 )
1617 m_idleInputpower[idx] = sec_fe->readInputpower();
1618 eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1621 eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1624 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1626 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1627 int idx = compare.val;
1628 if ( !m_simulate && (idx == 0 || idx == 1) )
1630 int idle = sec_fe->readInputpower();
1631 int diff = abs(idle-m_idleInputpower[idx]);
1634 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1635 setSecSequencePos(compare.steps);
1639 ++m_sec_sequence.current();
1642 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1644 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1647 setSecSequencePos(cmd.steps);
1651 int isLocked = readFrontendData(locked);
1652 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1654 if (!m_timeoutCount && m_retryCount > 0)
1656 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 40) || !cmd.lastSignal))
1659 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1662 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1664 cmd.lastSignal = signal;
1667 if (cmd.okcount > 4)
1669 eDebugNoSimulate("ok > 4 .. goto %d\n", cmd.steps);
1670 setSecSequencePos(cmd.steps);
1671 m_state = stateLock;
1672 m_stateChanged(this);
1673 feEvent(-1); // flush events
1681 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1683 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1687 ++m_sec_sequence.current();
1690 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1691 m_runningInputpower = sec_fe->readInputpower();
1692 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1693 ++m_sec_sequence.current();
1695 case eSecCommand::SET_ROTOR_MOVING:
1697 m_sec->setRotorMoving(m_slotid, true);
1698 ++m_sec_sequence.current();
1700 case eSecCommand::SET_ROTOR_STOPPED:
1702 m_sec->setRotorMoving(m_slotid, false);
1703 ++m_sec_sequence.current();
1705 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1707 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1710 setSecSequencePos(cmd.steps);
1713 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1714 const char *txt = cmd.direction ? "running" : "stopped";
1716 if (!m_timeoutCount && m_retryCount > 0)
1718 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1720 m_runningInputpower,
1723 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1724 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1727 eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1728 if ( cmd.okcount > 6 )
1730 eDebugNoSimulate("[SEC] rotor is %s", txt);
1731 if (setSecSequencePos(cmd.steps))
1737 eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1740 ++m_sec_sequence.current();
1743 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1744 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1745 setSecSequencePos(m_sec_sequence.current()->steps);
1747 ++m_sec_sequence.current();
1749 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1750 eDebugNoSimulate("[SEC] invalidate current switch params");
1751 sec_fe_data[CSW] = -1;
1752 sec_fe_data[UCSW] = -1;
1753 sec_fe_data[TONEBURST] = -1;
1754 ++m_sec_sequence.current();
1756 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1757 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1758 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1759 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1760 eDebugNoSimulate("[SEC] update current switch params");
1761 ++m_sec_sequence.current();
1763 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1764 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1765 sec_fe_data[ROTOR_CMD] = -1;
1766 sec_fe_data[ROTOR_POS] = -1;
1767 ++m_sec_sequence.current();
1769 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1770 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1771 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1772 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1773 ++m_sec_sequence.current();
1775 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1776 m_retryCount = m_sec_sequence.current()++->val;
1777 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1779 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1782 eDebugNoSimulate("[SEC] no more rotor retrys");
1783 setSecSequencePos(m_sec_sequence.current()->steps);
1786 ++m_sec_sequence.current();
1788 case eSecCommand::SET_POWER_LIMITING_MODE:
1793 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1794 FILE *f=fopen(proc_name, "w");
1795 if (f) // new interface exist?
1797 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1798 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1799 eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1801 eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1804 else if (sec_fe->m_need_rotor_workaround)
1807 int slotid = sec_fe->m_slotid;
1808 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1810 sprintf(dev, "/dev/i2c/%d", slotid);
1811 else if (slotid == 2)
1812 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1813 else if (slotid == 3)
1814 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1815 int fd = ::open(dev, O_RDWR);
1817 unsigned char data[2];
1818 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1819 if(::read(fd, data, 1) != 1)
1820 eDebugNoSimulate("[SEC] error read lnbp (%m)");
1821 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1823 data[0] |= 0x80; // enable static current limiting
1824 eDebugNoSimulate("[SEC] set static current limiting");
1828 data[0] &= ~0x80; // enable dynamic current limiting
1829 eDebugNoSimulate("[SEC] set dynamic current limiting");
1831 if(::write(fd, data, 1) != 1)
1832 eDebugNoSimulate("[SEC] error write lnbp (%m)");
1836 ++m_sec_sequence.current();
1840 eDebugNoSimulate("[SEC] unhandled sec command %d",
1841 ++m_sec_sequence.current()->cmd);
1842 ++m_sec_sequence.current();
1845 m_tuneTimer->start(delay,true);
1849 if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1853 void eDVBFrontend::setFrontend(bool recvEvents)
1857 eDebug("setting frontend %d", m_dvbid);
1860 feEvent(-1); // flush events
1861 #if HAVE_DVB_API_VERSION >= 5
1862 if (m_type == iDVBFrontend::feSatellite)
1864 fe_rolloff_t rolloff = ROLLOFF_35;
1865 fe_pilot_t pilot = PILOT_OFF;
1866 fe_modulation_t modulation = QPSK;
1867 fe_delivery_system_t system = SYS_DVBS;
1868 switch(oparm.sat.system)
1870 case eDVBFrontendParametersSatellite::System_DVB_S: system = SYS_DVBS; break;
1871 case eDVBFrontendParametersSatellite::System_DVB_S2: system = SYS_DVBS2; break;
1873 switch(oparm.sat.modulation)
1875 case eDVBFrontendParametersSatellite::Modulation_QPSK: modulation = QPSK; break;
1876 case eDVBFrontendParametersSatellite::Modulation_8PSK: modulation = PSK_8; break;
1877 case eDVBFrontendParametersSatellite::Modulation_QAM16: modulation = QAM_16; break;
1879 switch(oparm.sat.pilot)
1881 case eDVBFrontendParametersSatellite::Pilot_Off: pilot = PILOT_OFF; break;
1882 case eDVBFrontendParametersSatellite::Pilot_On: pilot = PILOT_ON; break;
1883 case eDVBFrontendParametersSatellite::Pilot_Unknown: pilot = PILOT_AUTO; break;
1885 switch(oparm.sat.rolloff)
1887 case eDVBFrontendParametersSatellite::RollOff_alpha_0_20: rolloff = ROLLOFF_20; break;
1888 case eDVBFrontendParametersSatellite::RollOff_alpha_0_25: rolloff = ROLLOFF_25; break;
1889 case eDVBFrontendParametersSatellite::RollOff_alpha_0_35: rolloff = ROLLOFF_35; break;
1891 struct dtv_property p[10];
1892 struct dtv_properties cmdseq;
1894 p[0].cmd = DTV_CLEAR;
1895 p[1].cmd = DTV_DELIVERY_SYSTEM, p[1].u.data = system;
1896 p[2].cmd = DTV_FREQUENCY, p[2].u.data = parm_frequency;
1897 p[3].cmd = DTV_MODULATION, p[3].u.data = modulation;
1898 p[4].cmd = DTV_SYMBOL_RATE, p[4].u.data = parm_u_qpsk_symbol_rate;
1899 p[5].cmd = DTV_INNER_FEC, p[5].u.data = parm_u_qpsk_fec_inner;
1900 p[6].cmd = DTV_INVERSION, p[6].u.data = parm_inversion;
1901 if (system == SYS_DVBS2)
1903 p[7].cmd = DTV_ROLLOFF, p[7].u.data = rolloff;
1904 p[8].cmd = DTV_PILOT, p[8].u.data = pilot;
1905 p[9].cmd = DTV_TUNE;
1910 p[7].cmd = DTV_TUNE;
1913 if (ioctl(m_fd, FE_SET_PROPERTY, &cmdseq) == -1)
1915 perror("FE_SET_PROPERTY failed");
1922 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1924 perror("FE_SET_FRONTEND failed");
1931 RESULT eDVBFrontend::getFrontendType(int &t)
1939 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1944 eWarning("no SEC module active!");
1947 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1950 #if HAVE_DVB_API_VERSION >= 3
1951 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",
1954 feparm.polarisation,
1958 feparm.orbital_position,
1964 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1967 feparm.polarisation,
1971 feparm.orbital_position);
1973 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1974 switch (feparm.inversion)
1976 case eDVBFrontendParametersSatellite::Inversion_On:
1977 parm_inversion = INVERSION_ON;
1979 case eDVBFrontendParametersSatellite::Inversion_Off:
1980 parm_inversion = INVERSION_OFF;
1983 case eDVBFrontendParametersSatellite::Inversion_Unknown:
1984 parm_inversion = INVERSION_AUTO;
1987 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S)
1991 case eDVBFrontendParametersSatellite::FEC_None:
1992 parm_u_qpsk_fec_inner = FEC_NONE;
1994 case eDVBFrontendParametersSatellite::FEC_1_2:
1995 parm_u_qpsk_fec_inner = FEC_1_2;
1997 case eDVBFrontendParametersSatellite::FEC_2_3:
1998 parm_u_qpsk_fec_inner = FEC_2_3;
2000 case eDVBFrontendParametersSatellite::FEC_3_4:
2001 parm_u_qpsk_fec_inner = FEC_3_4;
2003 case eDVBFrontendParametersSatellite::FEC_5_6:
2004 parm_u_qpsk_fec_inner = FEC_5_6;
2006 case eDVBFrontendParametersSatellite::FEC_7_8:
2007 parm_u_qpsk_fec_inner = FEC_7_8;
2010 eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
2011 case eDVBFrontendParametersSatellite::FEC_Auto:
2012 parm_u_qpsk_fec_inner = FEC_AUTO;
2016 #if HAVE_DVB_API_VERSION >= 3
2021 case eDVBFrontendParametersSatellite::FEC_1_2:
2022 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
2024 case eDVBFrontendParametersSatellite::FEC_2_3:
2025 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
2027 case eDVBFrontendParametersSatellite::FEC_3_4:
2028 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
2030 case eDVBFrontendParametersSatellite::FEC_3_5:
2031 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
2033 case eDVBFrontendParametersSatellite::FEC_4_5:
2034 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
2036 case eDVBFrontendParametersSatellite::FEC_5_6:
2037 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
2039 case eDVBFrontendParametersSatellite::FEC_7_8:
2040 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
2042 case eDVBFrontendParametersSatellite::FEC_8_9:
2043 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
2045 case eDVBFrontendParametersSatellite::FEC_9_10:
2046 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
2049 eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
2052 #if HAVE_DVB_API_VERSION < 5
2053 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
2054 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
2055 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation_8PSK)
2057 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
2058 // 8PSK fec driver values are decimal 9 bigger
2063 // FIXME !!! get frequency range from tuner
2064 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
2066 eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
2069 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
2075 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
2077 #if HAVE_DVB_API_VERSION < 3
2078 parm_frequency = feparm.frequency;
2080 parm_frequency = feparm.frequency * 1000;
2082 parm_u_qam_symbol_rate = feparm.symbol_rate;
2083 switch (feparm.modulation)
2085 case eDVBFrontendParametersCable::Modulation_QAM16:
2086 parm_u_qam_modulation = QAM_16;
2088 case eDVBFrontendParametersCable::Modulation_QAM32:
2089 parm_u_qam_modulation = QAM_32;
2091 case eDVBFrontendParametersCable::Modulation_QAM64:
2092 parm_u_qam_modulation = QAM_64;
2094 case eDVBFrontendParametersCable::Modulation_QAM128:
2095 parm_u_qam_modulation = QAM_128;
2097 case eDVBFrontendParametersCable::Modulation_QAM256:
2098 parm_u_qam_modulation = QAM_256;
2101 case eDVBFrontendParametersCable::Modulation_Auto:
2102 parm_u_qam_modulation = QAM_AUTO;
2105 switch (feparm.inversion)
2107 case eDVBFrontendParametersCable::Inversion_On:
2108 parm_inversion = INVERSION_ON;
2110 case eDVBFrontendParametersCable::Inversion_Off:
2111 parm_inversion = INVERSION_OFF;
2114 case eDVBFrontendParametersCable::Inversion_Unknown:
2115 parm_inversion = INVERSION_AUTO;
2118 switch (feparm.fec_inner)
2120 case eDVBFrontendParametersCable::FEC_None:
2121 parm_u_qam_fec_inner = FEC_NONE;
2123 case eDVBFrontendParametersCable::FEC_1_2:
2124 parm_u_qam_fec_inner = FEC_1_2;
2126 case eDVBFrontendParametersCable::FEC_2_3:
2127 parm_u_qam_fec_inner = FEC_2_3;
2129 case eDVBFrontendParametersCable::FEC_3_4:
2130 parm_u_qam_fec_inner = FEC_3_4;
2132 case eDVBFrontendParametersCable::FEC_5_6:
2133 parm_u_qam_fec_inner = FEC_5_6;
2135 case eDVBFrontendParametersCable::FEC_7_8:
2136 parm_u_qam_fec_inner = FEC_7_8;
2138 #if HAVE_DVB_API_VERSION >= 3
2139 case eDVBFrontendParametersCable::FEC_8_9:
2140 parm_u_qam_fec_inner = FEC_8_9;
2144 case eDVBFrontendParametersCable::FEC_Auto:
2145 parm_u_qam_fec_inner = FEC_AUTO;
2148 eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
2149 parm_frequency/1000,
2150 parm_u_qam_symbol_rate,
2151 parm_u_qam_fec_inner,
2152 parm_u_qam_modulation,
2158 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
2160 parm_frequency = feparm.frequency;
2162 switch (feparm.bandwidth)
2164 case eDVBFrontendParametersTerrestrial::Bandwidth_8MHz:
2165 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
2167 case eDVBFrontendParametersTerrestrial::Bandwidth_7MHz:
2168 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
2170 case eDVBFrontendParametersTerrestrial::Bandwidth_6MHz:
2171 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
2174 case eDVBFrontendParametersTerrestrial::Bandwidth_Auto:
2175 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
2178 switch (feparm.code_rate_LP)
2180 case eDVBFrontendParametersTerrestrial::FEC_1_2:
2181 parm_u_ofdm_code_rate_LP = FEC_1_2;
2183 case eDVBFrontendParametersTerrestrial::FEC_2_3:
2184 parm_u_ofdm_code_rate_LP = FEC_2_3;
2186 case eDVBFrontendParametersTerrestrial::FEC_3_4:
2187 parm_u_ofdm_code_rate_LP = FEC_3_4;
2189 case eDVBFrontendParametersTerrestrial::FEC_5_6:
2190 parm_u_ofdm_code_rate_LP = FEC_5_6;
2192 case eDVBFrontendParametersTerrestrial::FEC_7_8:
2193 parm_u_ofdm_code_rate_LP = FEC_7_8;
2196 case eDVBFrontendParametersTerrestrial::FEC_Auto:
2197 parm_u_ofdm_code_rate_LP = FEC_AUTO;
2200 switch (feparm.code_rate_HP)
2202 case eDVBFrontendParametersTerrestrial::FEC_1_2:
2203 parm_u_ofdm_code_rate_HP = FEC_1_2;
2205 case eDVBFrontendParametersTerrestrial::FEC_2_3:
2206 parm_u_ofdm_code_rate_HP = FEC_2_3;
2208 case eDVBFrontendParametersTerrestrial::FEC_3_4:
2209 parm_u_ofdm_code_rate_HP = FEC_3_4;
2211 case eDVBFrontendParametersTerrestrial::FEC_5_6:
2212 parm_u_ofdm_code_rate_HP = FEC_5_6;
2214 case eDVBFrontendParametersTerrestrial::FEC_7_8:
2215 parm_u_ofdm_code_rate_HP = FEC_7_8;
2218 case eDVBFrontendParametersTerrestrial::FEC_Auto:
2219 parm_u_ofdm_code_rate_HP = FEC_AUTO;
2222 switch (feparm.modulation)
2224 case eDVBFrontendParametersTerrestrial::Modulation_QPSK:
2225 parm_u_ofdm_constellation = QPSK;
2227 case eDVBFrontendParametersTerrestrial::Modulation_QAM16:
2228 parm_u_ofdm_constellation = QAM_16;
2230 case eDVBFrontendParametersTerrestrial::Modulation_QAM64:
2231 parm_u_ofdm_constellation = QAM_64;
2234 case eDVBFrontendParametersTerrestrial::Modulation_Auto:
2235 parm_u_ofdm_constellation = QAM_AUTO;
2238 switch (feparm.transmission_mode)
2240 case eDVBFrontendParametersTerrestrial::TransmissionMode_2k:
2241 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2243 case eDVBFrontendParametersTerrestrial::TransmissionMode_8k:
2244 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2247 case eDVBFrontendParametersTerrestrial::TransmissionMode_Auto:
2248 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2251 switch (feparm.guard_interval)
2253 case eDVBFrontendParametersTerrestrial::GuardInterval_1_32:
2254 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2256 case eDVBFrontendParametersTerrestrial::GuardInterval_1_16:
2257 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2259 case eDVBFrontendParametersTerrestrial::GuardInterval_1_8:
2260 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2262 case eDVBFrontendParametersTerrestrial::GuardInterval_1_4:
2263 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2266 case eDVBFrontendParametersTerrestrial::GuardInterval_Auto:
2267 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2270 switch (feparm.hierarchy)
2272 case eDVBFrontendParametersTerrestrial::Hierarchy_None:
2273 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2275 case eDVBFrontendParametersTerrestrial::Hierarchy_1:
2276 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2278 case eDVBFrontendParametersTerrestrial::Hierarchy_2:
2279 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2281 case eDVBFrontendParametersTerrestrial::Hierarchy_4:
2282 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2285 case eDVBFrontendParametersTerrestrial::Hierarchy_Auto:
2286 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2289 switch (feparm.inversion)
2291 case eDVBFrontendParametersTerrestrial::Inversion_On:
2292 parm_inversion = INVERSION_ON;
2294 case eDVBFrontendParametersTerrestrial::Inversion_Off:
2295 parm_inversion = INVERSION_OFF;
2298 case eDVBFrontendParametersTerrestrial::Inversion_Unknown:
2299 parm_inversion = INVERSION_AUTO;
2306 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2308 unsigned int timeout = 5000;
2309 eDebugNoSimulate("(%d)tune", m_dvbid);
2315 if (!m_sn && !m_simulate)
2317 eDebug("no frontend device opened... do not try to tune !!!");
2331 m_sec_sequence.clear();
2333 where.calcLockTimeout(timeout);
2339 eDVBFrontendParametersSatellite feparm;
2340 if (where.getDVBS(feparm))
2342 eDebug("no dvbs data!");
2347 m_sec->setRotorMoving(m_slotid, false);
2348 res=prepare_sat(feparm, timeout);
2356 eDVBFrontendParametersCable feparm;
2357 if (where.getDVBC(feparm))
2362 res=prepare_cable(feparm);
2366 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2367 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2372 eDVBFrontendParametersTerrestrial feparm;
2373 if (where.getDVBT(feparm))
2375 eDebug("no -T data");
2379 res=prepare_terrestrial(feparm);
2383 std::string enable_5V;
2384 char configStr[255];
2385 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2386 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2387 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2388 if (enable_5V == "True")
2389 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2391 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2392 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2398 m_sec_sequence.current() = m_sec_sequence.begin();
2402 m_tuneTimer->start(0,true);
2404 if (m_state != stateTuning)
2406 m_state = stateTuning;
2407 m_stateChanged(this);
2416 m_tuneTimer->stop();
2420 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2422 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2426 RESULT eDVBFrontend::setVoltage(int voltage)
2428 if (m_type == feCable)
2430 #if HAVE_DVB_API_VERSION < 3
2433 bool increased=false;
2434 fe_sec_voltage_t vlt;
2436 m_data[CUR_VOLTAGE]=voltage;
2440 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2441 vlt = SEC_VOLTAGE_OFF;
2444 #if HAVE_DVB_API_VERSION < 3
2445 vlt = SEC_VOLTAGE_13_5;
2451 vlt = SEC_VOLTAGE_13;
2454 #if HAVE_DVB_API_VERSION < 3
2455 vlt = SEC_VOLTAGE_18_5;
2461 vlt = SEC_VOLTAGE_18;
2468 #if HAVE_DVB_API_VERSION < 3
2469 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2471 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2472 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2473 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2477 RESULT eDVBFrontend::getState(int &state)
2483 RESULT eDVBFrontend::setTone(int t)
2485 if (m_type != feSatellite)
2487 #if HAVE_DVB_API_VERSION < 3
2490 fe_sec_tone_mode_t tone;
2499 tone = SEC_TONE_OFF;
2506 #if HAVE_DVB_API_VERSION < 3
2507 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2509 return ::ioctl(m_fd, FE_SET_TONE, tone);
2513 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2514 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2517 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2521 #if HAVE_DVB_API_VERSION < 3
2522 struct secCommand cmd;
2523 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2524 cmd.u.diseqc.cmdtype = diseqc.data[0];
2525 cmd.u.diseqc.addr = diseqc.data[1];
2526 cmd.u.diseqc.cmd = diseqc.data[2];
2527 cmd.u.diseqc.numParams = diseqc.len-3;
2528 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2529 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2531 struct dvb_diseqc_master_cmd cmd;
2532 memcpy(cmd.msg, diseqc.data, diseqc.len);
2533 cmd.msg_len = diseqc.len;
2534 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2540 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2541 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2543 RESULT eDVBFrontend::sendToneburst(int burst)
2547 #if HAVE_DVB_API_VERSION < 3
2548 secMiniCmd cmd = SEC_MINI_NONE;
2550 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2552 if ( burst == eDVBSatelliteDiseqcParameters::A )
2554 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2556 #if HAVE_DVB_API_VERSION < 3
2557 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2560 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2566 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2572 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2574 m_sec_sequence = list;
2578 RESULT eDVBFrontend::getData(int num, long &data)
2580 if ( num < NUM_DATA_ENTRIES )
2588 RESULT eDVBFrontend::setData(int num, long val)
2590 if ( num < NUM_DATA_ENTRIES )
2598 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2601 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2603 if (m_type == eDVBFrontend::feSatellite)
2606 eDVBFrontendParametersSatellite sat_parm;
2607 int ret = feparm->getDVBS(sat_parm);
2609 if (sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S2 && !m_can_handle_dvbs2)
2611 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2612 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S && m_can_handle_dvbs2)
2616 else if (m_type == eDVBFrontend::feCable)
2617 return 2; // more prio for cable frontends
2618 else if (m_type == eDVBFrontend::feTerrestrial)
2623 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2625 ePyObject Id, Descr, Enabled, IsDVBS2;
2626 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4)
2628 Id = PyTuple_GET_ITEM(obj, 0);
2629 Descr = PyTuple_GET_ITEM(obj, 1);
2630 Enabled = PyTuple_GET_ITEM(obj, 2);
2631 IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2632 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2))
2634 strcpy(m_description, PyString_AS_STRING(Descr));
2635 m_slotid = PyInt_AsLong(Id);
2636 m_enabled = Enabled == Py_True;
2637 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2638 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2639 !!strstr(m_description, "Alps BSBE2") ||
2640 !!strstr(m_description, "Alps -S") ||
2641 !!strstr(m_description, "BCM4501");
2642 m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2643 eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2644 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2647 PyErr_SetString(PyExc_StandardError,
2648 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");
2652 RESULT eDVBFrontend::turnOffSatCR(int satcr)
2654 eSecCommandList sec_sequence;
2655 // check if voltage is disabled
2656 eSecCommand::pair compare;
2657 compare.steps = +9; //nothing to do
2658 compare.voltage = iDVBFrontend::voltageOff;
2659 sec_sequence.push_back( eSecCommand(eSecCommand::IF_NOT_VOLTAGE_GOTO, compare) );
2660 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2661 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50 ) );
2663 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage18_5) );
2664 sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
2665 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 250) );
2667 eDVBDiseqcCommand diseqc;
2668 memset(diseqc.data, 0, MAX_DISEQC_LENGTH);
2670 diseqc.data[0] = 0xE0;
2671 diseqc.data[1] = 0x10;
2672 diseqc.data[2] = 0x5A;
2673 diseqc.data[3] = satcr << 5;
2674 diseqc.data[4] = 0x00;
2676 sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
2677 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50+20+14*diseqc.len) );
2678 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2679 setSecSequence(sec_sequence);
2683 RESULT eDVBFrontend::ScanSatCR()
2687 setTone(iDVBFrontend::toneOff);