1 #include <lib/dvb/dvb.h>
2 #include <lib/dvb/frontendparms.h>
3 #include <lib/base/eerror.h>
4 #include <lib/base/nconfig.h> // access to python config
10 #ifndef I2C_SLAVE_FORCE
11 #define I2C_SLAVE_FORCE 0x0706
14 #if HAVE_DVB_API_VERSION < 3
15 #include <ost/frontend.h>
17 #define QAM_AUTO (Modulation)6
18 #define TRANSMISSION_MODE_AUTO (TransmitMode)2
19 #define BANDWIDTH_AUTO (BandWidth)3
20 #define GUARD_INTERVAL_AUTO (GuardInterval)4
21 #define HIERARCHY_AUTO (Hierarchy)4
22 #define parm_frequency parm.Frequency
23 #define parm_inversion parm.Inversion
24 #define parm_u_qpsk_symbol_rate parm.u.qpsk.SymbolRate
25 #define parm_u_qpsk_fec_inner parm.u.qpsk.FEC_inner
26 #define parm_u_qam_symbol_rate parm.u.qam.SymbolRate
27 #define parm_u_qam_fec_inner parm.u.qam.FEC_inner
28 #define parm_u_qam_modulation parm.u.qam.QAM
29 #define parm_u_ofdm_bandwidth parm.u.ofdm.bandWidth
30 #define parm_u_ofdm_code_rate_LP parm.u.ofdm.LP_CodeRate
31 #define parm_u_ofdm_code_rate_HP parm.u.ofdm.HP_CodeRate
32 #define parm_u_ofdm_constellation parm.u.ofdm.Constellation
33 #define parm_u_ofdm_transmission_mode parm.u.ofdm.TransmissionMode
34 #define parm_u_ofdm_guard_interval parm.u.ofdm.guardInterval
35 #define parm_u_ofdm_hierarchy_information parm.u.ofdm.HierarchyInformation
37 #include <linux/dvb/frontend.h>
38 #define parm_frequency parm.frequency
39 #define parm_inversion parm.inversion
40 #define parm_u_qpsk_symbol_rate parm.u.qpsk.symbol_rate
41 #define parm_u_qpsk_fec_inner parm.u.qpsk.fec_inner
42 #define parm_u_qam_symbol_rate parm.u.qam.symbol_rate
43 #define parm_u_qam_fec_inner parm.u.qam.fec_inner
44 #define parm_u_qam_modulation parm.u.qam.modulation
45 #define parm_u_ofdm_bandwidth parm.u.ofdm.bandwidth
46 #define parm_u_ofdm_code_rate_LP parm.u.ofdm.code_rate_LP
47 #define parm_u_ofdm_code_rate_HP parm.u.ofdm.code_rate_HP
48 #define parm_u_ofdm_constellation parm.u.ofdm.constellation
49 #define parm_u_ofdm_transmission_mode parm.u.ofdm.transmission_mode
50 #define parm_u_ofdm_guard_interval parm.u.ofdm.guard_interval
51 #define parm_u_ofdm_hierarchy_information parm.u.ofdm.hierarchy_information
52 #if HAVE_DVB_API_VERSION < 5
53 #define FEC_S2_QPSK_1_2 (fe_code_rate_t)(FEC_AUTO+1)
54 #define FEC_S2_QPSK_2_3 (fe_code_rate_t)(FEC_S2_QPSK_1_2+1)
55 #define FEC_S2_QPSK_3_4 (fe_code_rate_t)(FEC_S2_QPSK_2_3+1)
56 #define FEC_S2_QPSK_5_6 (fe_code_rate_t)(FEC_S2_QPSK_3_4+1)
57 #define FEC_S2_QPSK_7_8 (fe_code_rate_t)(FEC_S2_QPSK_5_6+1)
58 #define FEC_S2_QPSK_8_9 (fe_code_rate_t)(FEC_S2_QPSK_7_8+1)
59 #define FEC_S2_QPSK_3_5 (fe_code_rate_t)(FEC_S2_QPSK_8_9+1)
60 #define FEC_S2_QPSK_4_5 (fe_code_rate_t)(FEC_S2_QPSK_3_5+1)
61 #define FEC_S2_QPSK_9_10 (fe_code_rate_t)(FEC_S2_QPSK_4_5+1)
62 #define FEC_S2_8PSK_1_2 (fe_code_rate_t)(FEC_S2_QPSK_9_10+1)
63 #define FEC_S2_8PSK_2_3 (fe_code_rate_t)(FEC_S2_8PSK_1_2+1)
64 #define FEC_S2_8PSK_3_4 (fe_code_rate_t)(FEC_S2_8PSK_2_3+1)
65 #define FEC_S2_8PSK_5_6 (fe_code_rate_t)(FEC_S2_8PSK_3_4+1)
66 #define FEC_S2_8PSK_7_8 (fe_code_rate_t)(FEC_S2_8PSK_5_6+1)
67 #define FEC_S2_8PSK_8_9 (fe_code_rate_t)(FEC_S2_8PSK_7_8+1)
68 #define FEC_S2_8PSK_3_5 (fe_code_rate_t)(FEC_S2_8PSK_8_9+1)
69 #define FEC_S2_8PSK_4_5 (fe_code_rate_t)(FEC_S2_8PSK_3_5+1)
70 #define FEC_S2_8PSK_9_10 (fe_code_rate_t)(FEC_S2_8PSK_4_5+1)
72 #define FEC_S2_QPSK_1_2 (fe_code_rate_t)(FEC_1_2)
73 #define FEC_S2_QPSK_2_3 (fe_code_rate_t)(FEC_2_3)
74 #define FEC_S2_QPSK_3_4 (fe_code_rate_t)(FEC_3_4)
75 #define FEC_S2_QPSK_5_6 (fe_code_rate_t)(FEC_5_6)
76 #define FEC_S2_QPSK_7_8 (fe_code_rate_t)(FEC_7_8)
77 #define FEC_S2_QPSK_8_9 (fe_code_rate_t)(FEC_8_9)
78 #define FEC_S2_QPSK_3_5 (fe_code_rate_t)(FEC_3_5)
79 #define FEC_S2_QPSK_4_5 (fe_code_rate_t)(FEC_4_5)
80 #define FEC_S2_QPSK_9_10 (fe_code_rate_t)(FEC_9_10)
84 #include <dvbsi++/satellite_delivery_system_descriptor.h>
85 #include <dvbsi++/cable_delivery_system_descriptor.h>
86 #include <dvbsi++/terrestrial_delivery_system_descriptor.h>
88 #define eDebugNoSimulate(x...) \
96 eDebugNoNewLine("SIMULATE:"); \
101 #define eDebugNoSimulateNoNewLine(x...) \
104 eDebugNoNewLine(x); \
109 eDebugNoNewLine("SIMULATE:"); \
110 eDebugNoNewLine(x); \
114 void eDVBDiseqcCommand::setCommandString(const char *str)
119 int slen = strlen(str);
122 eDebug("invalid diseqc command string length (not 2 byte aligned)");
125 if (slen > MAX_DISEQC_LENGTH*2)
127 eDebug("invalid diseqc command string length (string is to long)");
131 for (int i=0; i < slen; ++i)
133 unsigned char c = str[i];
136 case '0' ... '9': c-=48; break;
137 case 'a' ... 'f': c-=87; break;
138 case 'A' ... 'F': c-=55; break;
140 eDebug("invalid character in hex string..ignore complete diseqc command !");
154 void eDVBFrontendParametersSatellite::set(const SatelliteDeliverySystemDescriptor &descriptor)
156 frequency = descriptor.getFrequency() * 10;
157 symbol_rate = descriptor.getSymbolRate() * 100;
158 polarisation = descriptor.getPolarization();
159 fec = descriptor.getFecInner();
160 if ( fec != eDVBFrontendParametersSatellite::FEC_None && fec > eDVBFrontendParametersSatellite::FEC_9_10 )
161 fec = eDVBFrontendParametersSatellite::FEC_Auto;
162 inversion = eDVBFrontendParametersSatellite::Inversion_Unknown;
163 pilot = eDVBFrontendParametersSatellite::Pilot_Unknown;
164 orbital_position = ((descriptor.getOrbitalPosition() >> 12) & 0xF) * 1000;
165 orbital_position += ((descriptor.getOrbitalPosition() >> 8) & 0xF) * 100;
166 orbital_position += ((descriptor.getOrbitalPosition() >> 4) & 0xF) * 10;
167 orbital_position += ((descriptor.getOrbitalPosition()) & 0xF);
168 if (orbital_position && (!descriptor.getWestEastFlag()))
169 orbital_position = 3600 - orbital_position;
170 system = descriptor.getModulationSystem();
171 modulation = descriptor.getModulation();
172 if (system == eDVBFrontendParametersSatellite::System_DVB_S && modulation == eDVBFrontendParametersSatellite::Modulation_8PSK)
174 eDebug("satellite_delivery_descriptor non valid modulation type.. force QPSK");
175 modulation=eDVBFrontendParametersSatellite::Modulation_QPSK;
177 rolloff = descriptor.getRollOff();
178 if (system == eDVBFrontendParametersSatellite::System_DVB_S2)
180 eDebug("SAT DVB-S2 freq %d, %s, pos %d, sr %d, fec %d, modulation %d, rolloff %d",
182 polarisation ? "hor" : "vert",
190 eDebug("SAT DVB-S freq %d, %s, pos %d, sr %d, fec %d",
192 polarisation ? "hor" : "vert",
198 void eDVBFrontendParametersCable::set(const CableDeliverySystemDescriptor &descriptor)
200 frequency = descriptor.getFrequency() / 10;
201 symbol_rate = descriptor.getSymbolRate() * 100;
202 fec_inner = descriptor.getFecInner();
203 if ( fec_inner != eDVBFrontendParametersCable::FEC_None && fec_inner > eDVBFrontendParametersCable::FEC_8_9 )
204 fec_inner = eDVBFrontendParametersCable::FEC_Auto;
205 modulation = descriptor.getModulation();
206 if ( modulation > 0x5 )
207 modulation = eDVBFrontendParametersCable::Modulation_Auto;
208 inversion = eDVBFrontendParametersCable::Inversion_Unknown;
209 eDebug("Cable freq %d, mod %d, sr %d, fec %d",
211 modulation, symbol_rate, fec_inner);
214 void eDVBFrontendParametersTerrestrial::set(const TerrestrialDeliverySystemDescriptor &descriptor)
216 frequency = descriptor.getCentreFrequency() * 10;
217 bandwidth = descriptor.getBandwidth();
218 if ( bandwidth > 2 ) // 5Mhz forced to auto
219 bandwidth = eDVBFrontendParametersTerrestrial::Bandwidth_Auto;
220 code_rate_HP = descriptor.getCodeRateHpStream();
221 if (code_rate_HP > 4)
222 code_rate_HP = eDVBFrontendParametersTerrestrial::FEC_Auto;
223 code_rate_LP = descriptor.getCodeRateLpStream();
224 if (code_rate_LP > 4)
225 code_rate_LP = eDVBFrontendParametersTerrestrial::FEC_Auto;
226 transmission_mode = descriptor.getTransmissionMode();
227 if (transmission_mode > 1) // TM4k forced to auto
228 transmission_mode = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto;
229 guard_interval = descriptor.getGuardInterval();
230 if (guard_interval > 3)
231 guard_interval = eDVBFrontendParametersTerrestrial::GuardInterval_Auto;
232 hierarchy = descriptor.getHierarchyInformation()&3;
233 modulation = descriptor.getConstellation();
235 modulation = eDVBFrontendParametersTerrestrial::Modulation_Auto;
236 inversion = eDVBFrontendParametersTerrestrial::Inversion_Unknown;
237 eDebug("Terr freq %d, bw %d, cr_hp %d, cr_lp %d, tm_mode %d, guard %d, hierarchy %d, const %d",
238 frequency, bandwidth, code_rate_HP, code_rate_LP, transmission_mode,
239 guard_interval, hierarchy, modulation);
242 eDVBFrontendParameters::eDVBFrontendParameters()
243 :m_type(-1), m_flags(0)
247 DEFINE_REF(eDVBFrontendParameters);
249 RESULT eDVBFrontendParameters::getSystem(int &t) const
257 RESULT eDVBFrontendParameters::getDVBS(eDVBFrontendParametersSatellite &p) const
259 if (m_type != iDVBFrontend::feSatellite)
265 RESULT eDVBFrontendParameters::getDVBC(eDVBFrontendParametersCable &p) const
267 if (m_type != iDVBFrontend::feCable)
273 RESULT eDVBFrontendParameters::getDVBT(eDVBFrontendParametersTerrestrial &p) const
275 if (m_type != iDVBFrontend::feTerrestrial)
281 RESULT eDVBFrontendParameters::setDVBS(const eDVBFrontendParametersSatellite &p, bool no_rotor_command_on_tune)
284 sat.no_rotor_command_on_tune = no_rotor_command_on_tune;
285 m_type = iDVBFrontend::feSatellite;
289 RESULT eDVBFrontendParameters::setDVBC(const eDVBFrontendParametersCable &p)
292 m_type = iDVBFrontend::feCable;
296 RESULT eDVBFrontendParameters::setDVBT(const eDVBFrontendParametersTerrestrial &p)
299 m_type = iDVBFrontend::feTerrestrial;
303 RESULT eDVBFrontendParameters::calculateDifference(const iDVBFrontendParameters *parm, int &diff, bool exact) const
308 if (parm->getSystem(type))
312 diff = 1<<30; // big difference
318 case iDVBFrontend::feSatellite:
320 eDVBFrontendParametersSatellite osat;
321 if (parm->getDVBS(osat))
324 if (sat.orbital_position != osat.orbital_position)
326 else if (sat.polarisation != osat.polarisation)
328 else if (exact && sat.fec != osat.fec && sat.fec != eDVBFrontendParametersSatellite::FEC_Auto && osat.fec != eDVBFrontendParametersSatellite::FEC_Auto)
330 else if (exact && sat.modulation != osat.modulation && sat.modulation != eDVBFrontendParametersSatellite::Modulation_Auto && osat.modulation != eDVBFrontendParametersSatellite::Modulation_Auto)
334 diff = abs(sat.frequency - osat.frequency);
335 diff += abs(sat.symbol_rate - osat.symbol_rate);
339 case iDVBFrontend::feCable:
340 eDVBFrontendParametersCable ocable;
341 if (parm->getDVBC(ocable))
344 if (exact && cable.modulation != ocable.modulation
345 && cable.modulation != eDVBFrontendParametersCable::Modulation_Auto
346 && ocable.modulation != eDVBFrontendParametersCable::Modulation_Auto)
348 else if (exact && cable.fec_inner != ocable.fec_inner && cable.fec_inner != eDVBFrontendParametersCable::FEC_Auto && ocable.fec_inner != eDVBFrontendParametersCable::FEC_Auto)
352 diff = abs(cable.frequency - ocable.frequency);
353 diff += abs(cable.symbol_rate - ocable.symbol_rate);
356 case iDVBFrontend::feTerrestrial:
357 eDVBFrontendParametersTerrestrial oterrestrial;
358 if (parm->getDVBT(oterrestrial))
361 if (exact && oterrestrial.bandwidth != terrestrial.bandwidth &&
362 oterrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth_Auto &&
363 terrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth_Auto)
365 else if (exact && oterrestrial.modulation != terrestrial.modulation &&
366 oterrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation_Auto &&
367 terrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation_Auto)
369 else if (exact && oterrestrial.transmission_mode != terrestrial.transmission_mode &&
370 oterrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode_Auto &&
371 terrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode_Auto)
373 else if (exact && oterrestrial.guard_interval != terrestrial.guard_interval &&
374 oterrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval_Auto &&
375 terrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval_Auto)
377 else if (exact && oterrestrial.hierarchy != terrestrial.hierarchy &&
378 oterrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy_Auto &&
379 terrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy_Auto)
381 else if (exact && oterrestrial.code_rate_LP != terrestrial.code_rate_LP &&
382 oterrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC_Auto &&
383 terrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC_Auto)
385 else if (exact && oterrestrial.code_rate_HP != terrestrial.code_rate_HP &&
386 oterrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC_Auto &&
387 terrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC_Auto)
390 diff = abs(terrestrial.frequency - oterrestrial.frequency) / 1000;
398 RESULT eDVBFrontendParameters::getHash(unsigned long &hash) const
402 case iDVBFrontend::feSatellite:
404 hash = (sat.orbital_position << 16);
405 hash |= ((sat.frequency/1000)&0xFFFF)|((sat.polarisation&1) << 15);
408 case iDVBFrontend::feCable:
410 hash |= (cable.frequency/1000)&0xFFFF;
412 case iDVBFrontend::feTerrestrial:
414 hash |= (terrestrial.frequency/1000000)&0xFFFF;
421 RESULT eDVBFrontendParameters::calcLockTimeout(unsigned int &timeout) const
425 case iDVBFrontend::feSatellite:
427 /* high symbol rate transponders tune faster, due to
428 requiring less zigzag and giving more symbols faster.
430 5s are definitely not enough on really low SR when
431 zigzag has to find the exact frequency first.
433 if (sat.symbol_rate > 20000000)
435 else if (sat.symbol_rate > 10000000)
441 case iDVBFrontend::feCable:
444 case iDVBFrontend::feTerrestrial:
452 DEFINE_REF(eDVBFrontend);
454 int eDVBFrontend::PriorityOrder=0;
456 eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok, bool simulate)
457 :m_simulate(simulate), m_enabled(false), m_type(-1), m_dvbid(fe), m_slotid(fe)
458 ,m_fd(-1), m_rotor_mode(false), m_need_rotor_workaround(false), m_can_handle_dvbs2(false)
459 ,m_state(stateClosed), m_timeout(0), m_tuneTimer(0)
460 #if HAVE_DVB_API_VERSION < 3
464 #if HAVE_DVB_API_VERSION < 3
465 sprintf(m_filename, "/dev/dvb/card%d/frontend%d", adap, fe);
466 sprintf(m_sec_filename, "/dev/dvb/card%d/sec%d", adap, fe);
468 sprintf(m_filename, "/dev/dvb/adapter%d/frontend%d", adap, fe);
471 m_timeout = eTimer::create(eApp);
472 CONNECT(m_timeout->timeout, eDVBFrontend::timeout);
474 m_tuneTimer = eTimer::create(eApp);
475 CONNECT(m_tuneTimer->timeout, eDVBFrontend::tuneLoop);
477 for (int i=0; i<eDVBFrontend::NUM_DATA_ENTRIES; ++i)
480 m_idleInputpower[0]=m_idleInputpower[1]=0;
482 ok = !openFrontend();
486 void eDVBFrontend::reopenFrontend()
493 #ifdef BUILD_VUPLUS /* ikseong */
498 int eDVBFrontend::openFrontend()
500 if (m_state != stateClosed)
501 return -1; // already opened
506 #if HAVE_DVB_API_VERSION < 3
507 FrontendInfo fe_info;
509 dvb_frontend_info fe_info;
511 eDebugNoSimulate("opening frontend %d", m_dvbid);
514 if (!m_simulate || m_type == -1)
516 m_fd = ::open(m_filename, O_RDWR|O_NONBLOCK);
519 eWarning("failed! (%s) %m", m_filename);
522 #ifdef BUILD_VUPLUS /* ikseong */
534 eWarning("frontend %d already opened", m_dvbid);
537 if (::ioctl(m_fd, FE_GET_INFO, &fe_info) < 0)
539 eWarning("ioctl FE_GET_INFO failed");
545 switch (fe_info.type)
548 m_type = iDVBFrontend::feSatellite;
551 m_type = iDVBFrontend::feCable;
554 m_type = iDVBFrontend::feTerrestrial;
557 eWarning("unknown frontend type.");
562 eDebugNoSimulate("detected %s frontend", "satellite\0cable\0 terrestrial"+fe_info.type*10);
565 #if HAVE_DVB_API_VERSION < 3
566 if (m_type == iDVBFrontend::feSatellite)
572 m_secfd = ::open(m_sec_filename, O_RDWR);
575 eWarning("failed! (%s) %m", m_sec_filename);
583 eWarning("sec %d already opened", m_dvbid);
587 setTone(iDVBFrontend::toneOff);
588 setVoltage(iDVBFrontend::voltageOff);
592 m_sn = eSocketNotifier::create(eApp, m_fd, eSocketNotifier::Read, false);
593 CONNECT(m_sn->activated, eDVBFrontend::feEvent);
599 int eDVBFrontend::closeFrontend(bool force, bool no_delayed)
601 if (!force && m_data[CUR_VOLTAGE] != -1 && m_data[CUR_VOLTAGE] != iDVBFrontend::voltageOff)
603 long tmp = m_data[LINKED_NEXT_PTR];
606 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
607 if (linked_fe->m_inuse)
609 eDebugNoSimulate("dont close frontend %d until the linked frontend %d in slot %d is still in use",
610 m_dvbid, linked_fe->m_frontend->getDVBID(), linked_fe->m_frontend->getSlotID());
613 linked_fe->m_frontend->getData(LINKED_NEXT_PTR, tmp);
619 eDebugNoSimulate("close frontend %d", m_dvbid);
620 if (m_data[SATCR] != -1)
624 m_sec->prepareTurnOffSatCR(*this, m_data[SATCR]);
625 m_tuneTimer->start(0, true);
626 if(!m_tuneTimer->isActive())
629 eDebug("[turnOffSatCR] no mainloop");
632 timeout = tuneLoopInt();
635 usleep(timeout*1000); // blockierendes wait.. eTimer gibts ja nicht mehr
639 eDebug("[turnOffSatCR] running mainloop");
643 m_data[ROTOR_CMD] = -1;
646 setTone(iDVBFrontend::toneOff);
647 setVoltage(iDVBFrontend::voltageOff);
650 if (m_sec && !m_simulate)
651 m_sec->setRotorMoving(m_slotid, false);
655 eWarning("couldnt close frontend %d", m_dvbid);
659 setTone(iDVBFrontend::toneOff);
660 setVoltage(iDVBFrontend::voltageOff);
662 #if HAVE_DVB_API_VERSION < 3
665 if (!::close(m_secfd))
668 eWarning("couldnt close sec %d", m_dvbid);
672 m_state = stateClosed;
677 eDVBFrontend::~eDVBFrontend()
679 m_data[LINKED_PREV_PTR] = m_data[LINKED_NEXT_PTR] = -1;
683 void eDVBFrontend::feEvent(int w)
685 eDVBFrontend *sec_fe = this;
686 long tmp = m_data[LINKED_PREV_PTR];
689 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
690 sec_fe = linked_fe->m_frontend;
691 sec_fe->getData(LINKED_NEXT_PTR, tmp);
695 #if HAVE_DVB_API_VERSION < 3
698 dvb_frontend_event event;
702 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
704 if (res && (errno == EAGAIN))
710 #if HAVE_DVB_API_VERSION < 3
711 if (event.type == FE_COMPLETION_EV)
713 eDebug("(%d)fe event: status %x, inversion %s, m_tuning %d", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off", m_tuning);
714 if (event.status & FE_HAS_LOCK)
722 #if HAVE_DVB_API_VERSION >= 3
723 if (event.status & FE_TIMEDOUT) {
724 eDebug("FE_TIMEDOUT! ..abort");
737 eDebug("stateLostLock");
738 state = stateLostLock;
740 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
743 if (m_state != state)
746 m_stateChanged(this);
751 void eDVBFrontend::timeout()
754 if (m_state == stateTuning)
756 #ifdef BUILD_VUPLUS /* ikseong */
757 eDVBFrontend *sec_fe = this;
758 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
760 m_state = stateFailed;
761 m_stateChanged(this);
765 #define INRANGE(X,Y,Z) (((X<=Y) && (Y<=Z))||((Z<=Y) && (Y<=X)) ? 1 : 0)
767 /* unsigned 32 bit division */
768 static inline uint32_t fe_udiv(uint32_t a, uint32_t b)
770 return (a + b / 2) / b;
773 int eDVBFrontend::readFrontendData(int type)
782 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
783 eDebug("FE_READ_BER failed (%m)");
788 case signalQualitydB: /* this will move into the driver */
790 int sat_max = 1600; // for stv0288 / bsbe2
791 int ret = 0x12345678;
795 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
796 eDebug("FE_READ_SNR failed (%m)");
797 else if (!strcmp(m_description, "BCM4501 (internal)"))
799 float SDS_SNRE = snr << 16;
802 if (oparm.sat.system == eDVBFrontendParametersSatellite::System_DVB_S) // DVB-S1 / QPSK
804 static float SNR_COEFF[6] = {
807 197418.0 / 4194304.0,
808 -2602183.0 / 4194304.0,
809 20377212.0 / 4194304.0,
810 -37791203.0 / 4194304.0,
812 float fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0)),
813 fval2 = pow(10.0, fval1)-1;
814 fval1 = 10.0 * log10(fval2);
818 fval2 = SNR_COEFF[0];
819 for (int i=1; i<6; ++i)
822 fval2 += SNR_COEFF[i];
828 #if HAVE_DVB_API_VERSION >= 3
831 float fval1 = SDS_SNRE / 268435456.0,
834 if (oparm.sat.modulation == eDVBFrontendParametersSatellite::Modulation_QPSK)
845 fval4 = -10.0 * log10(fval1);
847 for (int i=0; i < 5; ++i)
848 fval1 = fval4 - fval2 * log10(1.0+pow(10.0, (fval3-fval1)/fval2));
853 ret = (int)(snr_in_db * 100);
855 else if (strstr(m_description, "Alps BSBE1 C01A") ||
856 strstr(m_description, "Alps -S(STV0288)"))
860 else if (snr == 0xFFFF) // i think this should not happen
864 enum { REALVAL, REGVAL };
865 const long CN_lookup[31][2] = {
866 {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
867 {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
868 {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
869 {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
870 {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
871 {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
874 int add=strchr(m_description, '.') ? 0xA250 : 0xA100;
875 long regval = 0xFFFF - ((snr / 3) + add), // revert some dvb api calulations to get the real register value
879 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
884 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[i][REGVAL]))
889 ret = (((regval - CN_lookup[Imin][REGVAL])
890 * (CN_lookup[Imax][REALVAL] - CN_lookup[Imin][REALVAL])
891 / (CN_lookup[Imax][REGVAL] - CN_lookup[Imin][REGVAL]))
892 + CN_lookup[Imin][REALVAL]) * 10;
898 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
899 !strcmp(m_description, "Alps -S") ||
900 !strcmp(m_description, "Philips -S") ||
901 !strcmp(m_description, "LG -S") )
904 ret = (int)((snr-39075)/17.647);
905 } else if (!strcmp(m_description, "Alps BSBE2"))
907 ret = (int)((snr >> 7) * 10);
908 } else if (!strcmp(m_description, "Philips CU1216Mk3"))
910 int mse = (~snr) & 0xFF;
911 switch (parm_u_qam_modulation) {
912 case QAM_16: ret = fe_udiv(1950000, (32 * mse) + 138) + 1000; break;
913 case QAM_32: ret = fe_udiv(2150000, (40 * mse) + 500) + 1350; break;
914 case QAM_64: ret = fe_udiv(2100000, (40 * mse) + 500) + 1250; break;
915 case QAM_128: ret = fe_udiv(1850000, (38 * mse) + 400) + 1380; break;
916 case QAM_256: ret = fe_udiv(1800000, (100 * mse) + 40) + 2030; break;
919 } else if (!strcmp(m_description, "Philips TU1216"))
921 snr = 0xFF - (snr & 0xFF);
923 ret = 10 * (int)(-100 * (log10(snr) - log10(255)));
925 else if (strstr(m_description, "BCM4506") || strstr(m_description, "BCM4505"))
926 ret = (snr * 100) >> 8;
927 else if (!strcmp(m_description, "CXD1981"))
929 int mse = (~snr) & 0xFF;
930 switch (parm_u_qam_modulation) {
933 case QAM_256: ret = (int)(-950 * log(((double)mse) / 760)); break;
935 case QAM_128: ret = (int)(-875 * log(((double)mse) / 650)); break;
941 if (type == signalQuality)
943 if (ret == 0x12345678) // no snr db calculation avail.. return untouched snr value..
948 return ret >= sat_max ? 65536 : ret * 65536 / sat_max;
949 case feCable: // we assume a max of 42db here
950 return ret >= 4200 ? 65536 : ret * 65536 / 4200;
951 case feTerrestrial: // we assume a max of 24db here
952 return ret >= 2400 ? 65536 : ret * 65536 / 2400;
956 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
964 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
965 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
971 #if HAVE_DVB_API_VERSION < 3
972 FrontendStatus status=0;
978 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
979 eDebug("FE_READ_STATUS failed (%m)");
980 return !!(status&FE_HAS_LOCK);
986 #if HAVE_DVB_API_VERSION < 3
987 FrontendStatus status=0;
993 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
994 eDebug("FE_READ_STATUS failed (%m)");
995 return !!(status&FE_HAS_SYNC);
1005 void PutToDict(ePyObject &dict, const char*key, long value)
1007 ePyObject item = PyInt_FromLong(value);
1010 if (PyDict_SetItemString(dict, key, item))
1011 eDebug("put %s to dict failed", key);
1015 eDebug("could not create PyObject for %s", key);
1018 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
1022 if (PyDict_SetItemString(dict, key, item))
1023 eDebug("put %s to dict failed", key);
1027 eDebug("invalid PyObject for %s", key);
1030 void PutToDict(ePyObject &dict, const char*key, const char *value)
1032 ePyObject item = PyString_FromString(value);
1035 if (PyDict_SetItemString(dict, key, item))
1036 eDebug("put %s to dict failed", key);
1040 eDebug("could not create PyObject for %s", key);
1043 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
1045 PutToDict(dict, "tuner_type", "DVB-S");
1046 PutToDict(dict, "frequency", feparm.frequency);
1047 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
1048 PutToDict(dict, "orbital_position", feparm.orbital_position);
1049 PutToDict(dict, "inversion", feparm.inversion);
1050 PutToDict(dict, "fec_inner", feparm.fec);
1051 PutToDict(dict, "modulation", feparm.modulation);
1052 PutToDict(dict, "polarization", feparm.polarisation);
1053 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S2)
1055 PutToDict(dict, "rolloff", feparm.rolloff);
1056 PutToDict(dict, "pilot", feparm.pilot);
1058 PutToDict(dict, "system", feparm.system);
1061 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
1063 PutToDict(dict, "tuner_type", "DVB-T");
1064 PutToDict(dict, "frequency", feparm.frequency);
1065 PutToDict(dict, "bandwidth", feparm.bandwidth);
1066 PutToDict(dict, "code_rate_lp", feparm.code_rate_LP);
1067 PutToDict(dict, "code_rate_hp", feparm.code_rate_HP);
1068 PutToDict(dict, "constellation", feparm.modulation);
1069 PutToDict(dict, "transmission_mode", feparm.transmission_mode);
1070 PutToDict(dict, "guard_interval", feparm.guard_interval);
1071 PutToDict(dict, "hierarchy_information", feparm.hierarchy);
1072 PutToDict(dict, "inversion", feparm.inversion);
1075 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
1077 PutToDict(dict, "tuner_type", "DVB-C");
1078 PutToDict(dict, "frequency", feparm.frequency);
1079 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
1080 PutToDict(dict, "modulation", feparm.modulation);
1081 PutToDict(dict, "inversion", feparm.inversion);
1082 PutToDict(dict, "fec_inner", feparm.fec_inner);
1085 #if HAVE_DVB_API_VERSION >= 5
1086 static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, struct dtv_property *p, long freq_offset, int orb_pos, int polarization)
1089 int frequency = parm_frequency + freq_offset;
1090 PutToDict(dict, "frequency", frequency);
1091 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
1092 PutToDict(dict, "orbital_position", orb_pos);
1093 PutToDict(dict, "polarization", polarization);
1095 switch(parm_u_qpsk_fec_inner)
1097 case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1098 case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1099 case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1100 case FEC_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
1101 case FEC_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; 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_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
1105 case FEC_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1106 case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
1107 case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
1108 default: eDebug("got unsupported FEC from frontend! report as FEC_AUTO!\n");
1110 PutToDict(dict, "fec_inner", tmp);
1112 switch (p[0].u.data)
1114 default: eDebug("got unsupported system from frontend! report as DVBS!");
1115 case SYS_DVBS: tmp = eDVBFrontendParametersSatellite::System_DVB_S; break;
1118 switch (p[2].u.data)
1120 default: eDebug("got unsupported rolloff from frontend! report as 0_20!");
1121 case ROLLOFF_20: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1122 case ROLLOFF_25: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1123 case ROLLOFF_35: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1125 PutToDict(dict, "rolloff", tmp);
1127 switch (p[3].u.data)
1129 case PILOT_OFF: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1130 case PILOT_ON: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1131 case PILOT_AUTO: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1133 PutToDict(dict, "pilot", tmp);
1135 tmp = eDVBFrontendParametersSatellite::System_DVB_S2; break;
1138 PutToDict(dict, "system", tmp);
1140 switch (p[1].u.data)
1142 default: eDebug("got unsupported modulation from frontend! report as QPSK!");
1143 case QPSK: tmp = eDVBFrontendParametersSatellite::Modulation_QPSK; break;
1144 case PSK_8: tmp = eDVBFrontendParametersSatellite::Modulation_8PSK; break;
1146 PutToDict(dict, "modulation", tmp);
1150 static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, long freq_offset, int orb_pos, int polarization)
1153 int frequency = parm_frequency + freq_offset;
1154 PutToDict(dict, "frequency", frequency);
1155 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
1156 PutToDict(dict, "orbital_position", orb_pos);
1157 PutToDict(dict, "polarization", polarization);
1159 switch((int)parm_u_qpsk_fec_inner)
1161 case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1162 case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1163 case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1164 case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1165 case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1166 case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
1168 case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
1169 #if HAVE_DVB_API_VERSION >=3
1170 case FEC_S2_8PSK_1_2:
1171 case FEC_S2_QPSK_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1172 case FEC_S2_8PSK_2_3:
1173 case FEC_S2_QPSK_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1174 case FEC_S2_8PSK_3_4:
1175 case FEC_S2_QPSK_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1176 case FEC_S2_8PSK_5_6:
1177 case FEC_S2_QPSK_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1178 case FEC_S2_8PSK_7_8:
1179 case FEC_S2_QPSK_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1180 case FEC_S2_8PSK_8_9:
1181 case FEC_S2_QPSK_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
1182 case FEC_S2_8PSK_3_5:
1183 case FEC_S2_QPSK_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
1184 case FEC_S2_8PSK_4_5:
1185 case FEC_S2_QPSK_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
1186 case FEC_S2_8PSK_9_10:
1187 case FEC_S2_QPSK_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1190 PutToDict(dict, "fec_inner", tmp);
1191 #if HAVE_DVB_API_VERSION >=3
1192 PutToDict(dict, "modulation",
1193 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ?
1194 eDVBFrontendParametersSatellite::Modulation_8PSK :
1195 eDVBFrontendParametersSatellite::Modulation_QPSK );
1196 if (parm_u_qpsk_fec_inner > FEC_AUTO)
1198 switch(parm_inversion & 0xc)
1200 default: // unknown rolloff
1201 case 0: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1202 case 4: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1203 case 8: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1205 PutToDict(dict, "rolloff", tmp);
1206 switch(parm_inversion & 0x30)
1208 case 0: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1209 case 0x10: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1210 case 0x20: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1212 PutToDict(dict, "pilot", tmp);
1213 tmp = eDVBFrontendParametersSatellite::System_DVB_S2;
1216 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1218 PutToDict(dict, "modulation", eDVBFrontendParametersSatellite::Modulation_QPSK );
1219 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1221 PutToDict(dict, "system", tmp);
1225 static void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1228 #if HAVE_DVB_API_VERSION < 3
1229 PutToDict(dict, "frequency", parm_frequency);
1231 PutToDict(dict, "frequency", parm_frequency/1000);
1233 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1234 switch(parm_u_qam_fec_inner)
1236 case FEC_NONE: tmp = eDVBFrontendParametersCable::FEC_None; break;
1237 case FEC_1_2: tmp = eDVBFrontendParametersCable::FEC_1_2; break;
1238 case FEC_2_3: tmp = eDVBFrontendParametersCable::FEC_2_3; break;
1239 case FEC_3_4: tmp = eDVBFrontendParametersCable::FEC_3_4; break;
1240 case FEC_5_6: tmp = eDVBFrontendParametersCable::FEC_5_6; break;
1241 case FEC_7_8: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1242 #if HAVE_DVB_API_VERSION >= 3
1243 case FEC_8_9: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1246 case FEC_AUTO: tmp = eDVBFrontendParametersCable::FEC_Auto; break;
1248 PutToDict(dict, "fec_inner", tmp);
1249 switch(parm_u_qam_modulation)
1251 case QAM_16: tmp = eDVBFrontendParametersCable::Modulation_QAM16; break;
1252 case QAM_32: tmp = eDVBFrontendParametersCable::Modulation_QAM32; break;
1253 case QAM_64: tmp = eDVBFrontendParametersCable::Modulation_QAM64; break;
1254 case QAM_128: tmp = eDVBFrontendParametersCable::Modulation_QAM128; break;
1255 case QAM_256: tmp = eDVBFrontendParametersCable::Modulation_QAM256; break;
1257 case QAM_AUTO: tmp = eDVBFrontendParametersCable::Modulation_Auto; break;
1259 PutToDict(dict, "modulation", tmp);
1262 static void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1265 PutToDict(dict, "frequency", parm_frequency);
1266 switch (parm_u_ofdm_bandwidth)
1268 case BANDWIDTH_8_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_8MHz; break;
1269 case BANDWIDTH_7_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_7MHz; break;
1270 case BANDWIDTH_6_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_6MHz; break;
1272 case BANDWIDTH_AUTO: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_Auto; break;
1274 PutToDict(dict, "bandwidth", tmp);
1275 switch (parm_u_ofdm_code_rate_LP)
1277 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1278 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1279 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1280 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1281 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1283 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1285 PutToDict(dict, "code_rate_lp", tmp);
1286 switch (parm_u_ofdm_code_rate_HP)
1288 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1289 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1290 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1291 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1292 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1294 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1296 PutToDict(dict, "code_rate_hp", tmp);
1297 switch (parm_u_ofdm_constellation)
1299 case QPSK: tmp = eDVBFrontendParametersTerrestrial::Modulation_QPSK; break;
1300 case QAM_16: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM16; break;
1301 case QAM_64: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM64; break;
1303 case QAM_AUTO: tmp = eDVBFrontendParametersTerrestrial::Modulation_Auto; break;
1305 PutToDict(dict, "constellation", tmp);
1306 switch (parm_u_ofdm_transmission_mode)
1308 case TRANSMISSION_MODE_2K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_2k; break;
1309 case TRANSMISSION_MODE_8K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_8k; break;
1311 case TRANSMISSION_MODE_AUTO: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto; break;
1313 PutToDict(dict, "transmission_mode", tmp);
1314 switch (parm_u_ofdm_guard_interval)
1316 case GUARD_INTERVAL_1_32: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_32; break;
1317 case GUARD_INTERVAL_1_16: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_16; break;
1318 case GUARD_INTERVAL_1_8: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_8; break;
1319 case GUARD_INTERVAL_1_4: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_4; break;
1321 case GUARD_INTERVAL_AUTO: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_Auto; break;
1323 PutToDict(dict, "guard_interval", tmp);
1324 switch (parm_u_ofdm_hierarchy_information)
1326 case HIERARCHY_NONE: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_None; break;
1327 case HIERARCHY_1: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_1; break;
1328 case HIERARCHY_2: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_2; break;
1329 case HIERARCHY_4: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_4; break;
1331 case HIERARCHY_AUTO: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_Auto; break;
1333 PutToDict(dict, "hierarchy_information", tmp);
1336 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1338 if (dest && PyDict_Check(dest))
1340 const char *tmp = "UNKNOWN";
1361 PutToDict(dest, "tuner_state", tmp);
1362 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1363 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1364 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1365 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1366 int sigQualitydB = readFrontendData(signalQualitydB);
1367 if (sigQualitydB == 0x12345678) // not support yet
1369 ePyObject obj=Py_None;
1371 PutToDict(dest, "tuner_signal_quality_db", obj);
1374 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1375 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1379 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1381 if (dest && PyDict_Check(dest))
1383 FRONTENDPARAMETERS front;
1384 #if HAVE_DVB_API_VERSION >= 5
1385 struct dtv_property p[4];
1386 struct dtv_properties cmdseq;
1389 p[0].cmd = DTV_DELIVERY_SYSTEM;
1390 p[1].cmd = DTV_MODULATION;
1391 p[2].cmd = DTV_ROLLOFF;
1392 p[3].cmd = DTV_PILOT;
1394 if (m_simulate || m_fd == -1 || original)
1396 #if HAVE_DVB_API_VERSION >= 5
1397 else if (m_type == feSatellite && // yet just use new api for DVB-S(2) only
1398 ioctl(m_fd, FE_GET_PROPERTY, &cmdseq)<0)
1400 eDebug("FE_GET_PROPERTY failed (%m)");
1404 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1406 eDebug("FE_GET_FRONTEND failed (%m)");
1414 PutSatelliteDataToDict(dest, oparm.sat);
1417 PutCableDataToDict(dest, oparm.cab);
1420 PutTerrestrialDataToDict(dest, oparm.ter);
1426 FRONTENDPARAMETERS &parm = front;
1427 long tmp = eDVBFrontendParametersSatellite::Inversion_Unknown;
1428 switch(parm_inversion & 3)
1431 tmp = eDVBFrontendParametersSatellite::Inversion_On;
1434 tmp = eDVBFrontendParametersSatellite::Inversion_Off;
1438 PutToDict(dest, "inversion", tmp);
1442 #if HAVE_DVB_API_VERSION >= 5
1443 fillDictWithSatelliteData(dest, parm, p, m_data[FREQ_OFFSET], oparm.sat.orbital_position, oparm.sat.polarisation);
1445 fillDictWithSatelliteData(dest, parm, m_data[FREQ_OFFSET], oparm.sat.orbital_position, oparm.sat.polarisation);
1449 fillDictWithCableData(dest, parm);
1452 fillDictWithTerrestrialData(dest, parm);
1459 void eDVBFrontend::getFrontendData(ePyObject dest)
1461 if (dest && PyDict_Check(dest))
1464 PutToDict(dest, "tuner_number", m_slotid);
1480 PutToDict(dest, "tuner_type", tmp);
1484 #ifndef FP_IOCTL_GET_ID
1485 #define FP_IOCTL_GET_ID 0
1487 int eDVBFrontend::readInputpower()
1491 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1493 char proc_name2[64];
1494 sprintf(proc_name, "/proc/stb/frontend/%d/lnb_sense", m_slotid);
1495 sprintf(proc_name2, "/proc/stb/fp/lnb_sense%d", m_slotid);
1497 if ((f=fopen(proc_name, "r")) || (f=fopen(proc_name2, "r")))
1499 if (fscanf(f, "%d", &power) != 1)
1500 eDebug("read %s failed!! (%m)", proc_name);
1502 eDebug("%s is %d\n", proc_name, power);
1507 // open front prozessor
1508 int fp=::open("/dev/dbox/fp0", O_RDWR);
1511 eDebug("couldn't open fp");
1514 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1515 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1517 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1526 bool eDVBFrontend::setSecSequencePos(int steps)
1528 eDebugNoSimulate("set sequence pos %d", steps);
1533 if (m_sec_sequence.current() != m_sec_sequence.end())
1534 ++m_sec_sequence.current();
1539 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1540 --m_sec_sequence.current();
1546 void eDVBFrontend::tuneLoop()
1551 int eDVBFrontend::tuneLoopInt() // called by m_tuneTimer
1554 eDVBFrontend *sec_fe = this;
1555 eDVBRegisteredFrontend *regFE = 0;
1556 long tmp = m_data[LINKED_PREV_PTR];
1559 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1560 sec_fe = prev->m_frontend;
1561 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1562 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1563 int state = sec_fe->m_state;
1564 // workaround to put the kernel frontend thread into idle state!
1565 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1567 sec_fe->closeFrontend(true);
1568 state = sec_fe->m_state;
1570 // sec_fe is closed... we must reopen it here..
1571 if (state == stateClosed)
1579 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1581 long *sec_fe_data = sec_fe->m_data;
1582 // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1584 switch (m_sec_sequence.current()->cmd)
1586 case eSecCommand::SLEEP:
1587 delay = m_sec_sequence.current()++->msec;
1588 eDebugNoSimulate("[SEC] sleep %dms", delay);
1590 case eSecCommand::GOTO:
1591 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1592 ++m_sec_sequence.current();
1594 case eSecCommand::SET_VOLTAGE:
1596 int voltage = m_sec_sequence.current()++->voltage;
1597 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1598 sec_fe->setVoltage(voltage);
1601 case eSecCommand::IF_VOLTAGE_GOTO:
1603 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1604 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1606 ++m_sec_sequence.current();
1609 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1611 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1612 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1614 ++m_sec_sequence.current();
1617 case eSecCommand::IF_TONE_GOTO:
1619 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1620 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1622 ++m_sec_sequence.current();
1625 case eSecCommand::IF_NOT_TONE_GOTO:
1627 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1628 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1630 ++m_sec_sequence.current();
1633 case eSecCommand::SET_TONE:
1634 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1635 sec_fe->setTone(m_sec_sequence.current()++->tone);
1637 case eSecCommand::SEND_DISEQC:
1638 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1639 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1640 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1641 eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1642 if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
1643 eDebugNoSimulate("(DiSEqC reset)");
1644 else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
1645 eDebugNoSimulate("(DiSEqC peripherial power on)");
1647 eDebugNoSimulate("");
1648 ++m_sec_sequence.current();
1650 case eSecCommand::SEND_TONEBURST:
1651 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1652 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1654 case eSecCommand::SET_FRONTEND:
1656 int enableEvents = (m_sec_sequence.current()++)->val;
1657 eDebugNoSimulate("[SEC] setFrontend %d", enableEvents);
1658 setFrontend(enableEvents);
1661 case eSecCommand::START_TUNE_TIMEOUT:
1663 int tuneTimeout = m_sec_sequence.current()->timeout;
1664 eDebugNoSimulate("[SEC] startTuneTimeout %d", tuneTimeout);
1666 m_timeout->start(tuneTimeout, 1);
1667 ++m_sec_sequence.current();
1670 case eSecCommand::SET_TIMEOUT:
1671 m_timeoutCount = m_sec_sequence.current()++->val;
1672 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1674 case eSecCommand::IF_TIMEOUT_GOTO:
1675 if (!m_timeoutCount)
1677 eDebugNoSimulate("[SEC] rotor timout");
1678 setSecSequencePos(m_sec_sequence.current()->steps);
1681 ++m_sec_sequence.current();
1683 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1685 int idx = m_sec_sequence.current()++->val;
1686 if ( idx == 0 || idx == 1 )
1688 m_idleInputpower[idx] = sec_fe->readInputpower();
1689 eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1692 eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1695 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1697 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1698 int idx = compare.val;
1699 if ( !m_simulate && (idx == 0 || idx == 1) )
1701 int idle = sec_fe->readInputpower();
1702 int diff = abs(idle-m_idleInputpower[idx]);
1705 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1706 setSecSequencePos(compare.steps);
1710 ++m_sec_sequence.current();
1713 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1715 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1718 setSecSequencePos(cmd.steps);
1722 int isLocked = readFrontendData(locked);
1723 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1725 if (!m_timeoutCount && m_retryCount > 0)
1727 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 40) || !cmd.lastSignal))
1730 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1733 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1735 cmd.lastSignal = signal;
1738 if (cmd.okcount > 4)
1740 eDebugNoSimulate("ok > 4 .. goto %d\n", cmd.steps);
1741 setSecSequencePos(cmd.steps);
1742 m_state = stateLock;
1743 m_stateChanged(this);
1744 feEvent(-1); // flush events
1752 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1754 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1758 ++m_sec_sequence.current();
1761 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1762 m_runningInputpower = sec_fe->readInputpower();
1763 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1764 ++m_sec_sequence.current();
1766 case eSecCommand::SET_ROTOR_MOVING:
1768 m_sec->setRotorMoving(m_slotid, true);
1769 ++m_sec_sequence.current();
1771 case eSecCommand::SET_ROTOR_STOPPED:
1773 m_sec->setRotorMoving(m_slotid, false);
1774 ++m_sec_sequence.current();
1776 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1778 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1781 setSecSequencePos(cmd.steps);
1784 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1785 const char *txt = cmd.direction ? "running" : "stopped";
1787 if (!m_timeoutCount && m_retryCount > 0)
1789 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1791 m_runningInputpower,
1794 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1795 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1798 eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1799 if ( cmd.okcount > 6 )
1801 eDebugNoSimulate("[SEC] rotor is %s", txt);
1802 if (setSecSequencePos(cmd.steps))
1808 eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1811 ++m_sec_sequence.current();
1814 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1815 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1816 setSecSequencePos(m_sec_sequence.current()->steps);
1818 ++m_sec_sequence.current();
1820 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1821 eDebugNoSimulate("[SEC] invalidate current switch params");
1822 sec_fe_data[CSW] = -1;
1823 sec_fe_data[UCSW] = -1;
1824 sec_fe_data[TONEBURST] = -1;
1825 ++m_sec_sequence.current();
1827 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1828 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1829 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1830 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1831 eDebugNoSimulate("[SEC] update current switch params");
1832 ++m_sec_sequence.current();
1834 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1835 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1836 sec_fe_data[ROTOR_CMD] = -1;
1837 sec_fe_data[ROTOR_POS] = -1;
1838 ++m_sec_sequence.current();
1840 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1841 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1842 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1843 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1844 ++m_sec_sequence.current();
1846 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1847 m_retryCount = m_sec_sequence.current()++->val;
1848 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1850 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1853 eDebugNoSimulate("[SEC] no more rotor retrys");
1854 setSecSequencePos(m_sec_sequence.current()->steps);
1857 ++m_sec_sequence.current();
1859 case eSecCommand::SET_POWER_LIMITING_MODE:
1864 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1865 FILE *f=fopen(proc_name, "w");
1866 if (f) // new interface exist?
1868 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1869 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1870 eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1872 eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1875 else if (sec_fe->m_need_rotor_workaround)
1878 int slotid = sec_fe->m_slotid;
1879 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1881 sprintf(dev, "/dev/i2c/%d", slotid);
1882 else if (slotid == 2)
1883 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1884 else if (slotid == 3)
1885 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1886 int fd = ::open(dev, O_RDWR);
1888 unsigned char data[2];
1889 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1890 if(::read(fd, data, 1) != 1)
1891 eDebugNoSimulate("[SEC] error read lnbp (%m)");
1892 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1894 data[0] |= 0x80; // enable static current limiting
1895 eDebugNoSimulate("[SEC] set static current limiting");
1899 data[0] &= ~0x80; // enable dynamic current limiting
1900 eDebugNoSimulate("[SEC] set dynamic current limiting");
1902 if(::write(fd, data, 1) != 1)
1903 eDebugNoSimulate("[SEC] error write lnbp (%m)");
1907 ++m_sec_sequence.current();
1910 case eSecCommand::DELAYED_CLOSE_FRONTEND:
1912 eDebugNoSimulate("[SEC] delayed close frontend");
1913 closeFrontend(false, true);
1914 ++m_sec_sequence.current();
1918 eDebugNoSimulate("[SEC] unhandled sec command %d",
1919 ++m_sec_sequence.current()->cmd);
1920 ++m_sec_sequence.current();
1923 m_tuneTimer->start(delay,true);
1927 if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1932 void eDVBFrontend::setFrontend(bool recvEvents)
1936 eDebug("setting frontend %d", m_dvbid);
1939 feEvent(-1); // flush events
1940 #if HAVE_DVB_API_VERSION >= 5
1941 if (m_type == iDVBFrontend::feSatellite)
1943 fe_rolloff_t rolloff = ROLLOFF_35;
1944 fe_pilot_t pilot = PILOT_OFF;
1945 fe_modulation_t modulation = QPSK;
1946 fe_delivery_system_t system = SYS_DVBS;
1947 switch(oparm.sat.system)
1949 case eDVBFrontendParametersSatellite::System_DVB_S: system = SYS_DVBS; break;
1950 case eDVBFrontendParametersSatellite::System_DVB_S2: system = SYS_DVBS2; break;
1952 switch(oparm.sat.modulation)
1954 case eDVBFrontendParametersSatellite::Modulation_QPSK: modulation = QPSK; break;
1955 case eDVBFrontendParametersSatellite::Modulation_8PSK: modulation = PSK_8; break;
1956 case eDVBFrontendParametersSatellite::Modulation_QAM16: modulation = QAM_16; break;
1958 switch(oparm.sat.pilot)
1960 case eDVBFrontendParametersSatellite::Pilot_Off: pilot = PILOT_OFF; break;
1961 case eDVBFrontendParametersSatellite::Pilot_On: pilot = PILOT_ON; break;
1962 case eDVBFrontendParametersSatellite::Pilot_Unknown: pilot = PILOT_AUTO; break;
1964 switch(oparm.sat.rolloff)
1966 case eDVBFrontendParametersSatellite::RollOff_alpha_0_20: rolloff = ROLLOFF_20; break;
1967 case eDVBFrontendParametersSatellite::RollOff_alpha_0_25: rolloff = ROLLOFF_25; break;
1968 case eDVBFrontendParametersSatellite::RollOff_alpha_0_35: rolloff = ROLLOFF_35; break;
1970 struct dtv_property p[10];
1971 struct dtv_properties cmdseq;
1973 p[0].cmd = DTV_CLEAR;
1974 p[1].cmd = DTV_DELIVERY_SYSTEM, p[1].u.data = system;
1975 p[2].cmd = DTV_FREQUENCY, p[2].u.data = parm_frequency;
1976 p[3].cmd = DTV_MODULATION, p[3].u.data = modulation;
1977 p[4].cmd = DTV_SYMBOL_RATE, p[4].u.data = parm_u_qpsk_symbol_rate;
1978 p[5].cmd = DTV_INNER_FEC, p[5].u.data = parm_u_qpsk_fec_inner;
1979 p[6].cmd = DTV_INVERSION, p[6].u.data = parm_inversion;
1980 if (system == SYS_DVBS2)
1982 p[7].cmd = DTV_ROLLOFF, p[7].u.data = rolloff;
1983 p[8].cmd = DTV_PILOT, p[8].u.data = pilot;
1984 p[9].cmd = DTV_TUNE;
1989 p[7].cmd = DTV_TUNE;
1992 if (ioctl(m_fd, FE_SET_PROPERTY, &cmdseq) == -1)
1994 perror("FE_SET_PROPERTY failed");
2001 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
2003 perror("FE_SET_FRONTEND failed");
2010 RESULT eDVBFrontend::getFrontendType(int &t)
2018 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
2023 eWarning("no SEC module active!");
2026 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
2029 #if HAVE_DVB_API_VERSION >= 3
2030 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",
2033 feparm.polarisation,
2037 feparm.orbital_position,
2043 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
2046 feparm.polarisation,
2050 feparm.orbital_position);
2052 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
2053 switch (feparm.inversion)
2055 case eDVBFrontendParametersSatellite::Inversion_On:
2056 parm_inversion = INVERSION_ON;
2058 case eDVBFrontendParametersSatellite::Inversion_Off:
2059 parm_inversion = INVERSION_OFF;
2062 case eDVBFrontendParametersSatellite::Inversion_Unknown:
2063 parm_inversion = INVERSION_AUTO;
2066 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S)
2070 case eDVBFrontendParametersSatellite::FEC_None:
2071 parm_u_qpsk_fec_inner = FEC_NONE;
2073 case eDVBFrontendParametersSatellite::FEC_1_2:
2074 parm_u_qpsk_fec_inner = FEC_1_2;
2076 case eDVBFrontendParametersSatellite::FEC_2_3:
2077 parm_u_qpsk_fec_inner = FEC_2_3;
2079 case eDVBFrontendParametersSatellite::FEC_3_4:
2080 parm_u_qpsk_fec_inner = FEC_3_4;
2082 case eDVBFrontendParametersSatellite::FEC_5_6:
2083 parm_u_qpsk_fec_inner = FEC_5_6;
2085 case eDVBFrontendParametersSatellite::FEC_7_8:
2086 parm_u_qpsk_fec_inner = FEC_7_8;
2089 eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
2090 case eDVBFrontendParametersSatellite::FEC_Auto:
2091 parm_u_qpsk_fec_inner = FEC_AUTO;
2095 #if HAVE_DVB_API_VERSION >= 3
2100 case eDVBFrontendParametersSatellite::FEC_1_2:
2101 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
2103 case eDVBFrontendParametersSatellite::FEC_2_3:
2104 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
2106 case eDVBFrontendParametersSatellite::FEC_3_4:
2107 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
2109 case eDVBFrontendParametersSatellite::FEC_3_5:
2110 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
2112 case eDVBFrontendParametersSatellite::FEC_4_5:
2113 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
2115 case eDVBFrontendParametersSatellite::FEC_5_6:
2116 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
2118 case eDVBFrontendParametersSatellite::FEC_7_8:
2119 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
2121 case eDVBFrontendParametersSatellite::FEC_8_9:
2122 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
2124 case eDVBFrontendParametersSatellite::FEC_9_10:
2125 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
2128 eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
2131 #if HAVE_DVB_API_VERSION < 5
2132 parm_inversion = (fe_spectral_inversion_t)((feparm.rolloff << 2) | parm_inversion); // Hack.. we use bit 2..3 of inversion param for rolloff
2133 parm_inversion = (fe_spectral_inversion_t)((feparm.pilot << 4) | parm_inversion); // Hack.. we use bit 4..5 of inversion param for pilot
2134 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation_8PSK)
2136 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
2137 // 8PSK fec driver values are decimal 9 bigger
2142 // FIXME !!! get frequency range from tuner
2143 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
2145 eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
2148 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
2154 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
2156 #if HAVE_DVB_API_VERSION < 3
2157 parm_frequency = feparm.frequency;
2159 parm_frequency = feparm.frequency * 1000;
2161 parm_u_qam_symbol_rate = feparm.symbol_rate;
2162 switch (feparm.modulation)
2164 case eDVBFrontendParametersCable::Modulation_QAM16:
2165 parm_u_qam_modulation = QAM_16;
2167 case eDVBFrontendParametersCable::Modulation_QAM32:
2168 parm_u_qam_modulation = QAM_32;
2170 case eDVBFrontendParametersCable::Modulation_QAM64:
2171 parm_u_qam_modulation = QAM_64;
2173 case eDVBFrontendParametersCable::Modulation_QAM128:
2174 parm_u_qam_modulation = QAM_128;
2176 case eDVBFrontendParametersCable::Modulation_QAM256:
2177 parm_u_qam_modulation = QAM_256;
2180 case eDVBFrontendParametersCable::Modulation_Auto:
2181 parm_u_qam_modulation = QAM_AUTO;
2184 switch (feparm.inversion)
2186 case eDVBFrontendParametersCable::Inversion_On:
2187 parm_inversion = INVERSION_ON;
2189 case eDVBFrontendParametersCable::Inversion_Off:
2190 parm_inversion = INVERSION_OFF;
2193 case eDVBFrontendParametersCable::Inversion_Unknown:
2194 parm_inversion = INVERSION_AUTO;
2197 switch (feparm.fec_inner)
2199 case eDVBFrontendParametersCable::FEC_None:
2200 parm_u_qam_fec_inner = FEC_NONE;
2202 case eDVBFrontendParametersCable::FEC_1_2:
2203 parm_u_qam_fec_inner = FEC_1_2;
2205 case eDVBFrontendParametersCable::FEC_2_3:
2206 parm_u_qam_fec_inner = FEC_2_3;
2208 case eDVBFrontendParametersCable::FEC_3_4:
2209 parm_u_qam_fec_inner = FEC_3_4;
2211 case eDVBFrontendParametersCable::FEC_5_6:
2212 parm_u_qam_fec_inner = FEC_5_6;
2214 case eDVBFrontendParametersCable::FEC_7_8:
2215 parm_u_qam_fec_inner = FEC_7_8;
2217 #if HAVE_DVB_API_VERSION >= 3
2218 case eDVBFrontendParametersCable::FEC_8_9:
2219 parm_u_qam_fec_inner = FEC_8_9;
2223 case eDVBFrontendParametersCable::FEC_Auto:
2224 parm_u_qam_fec_inner = FEC_AUTO;
2227 eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
2228 parm_frequency/1000,
2229 parm_u_qam_symbol_rate,
2230 parm_u_qam_fec_inner,
2231 parm_u_qam_modulation,
2237 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
2239 parm_frequency = feparm.frequency;
2241 switch (feparm.bandwidth)
2243 case eDVBFrontendParametersTerrestrial::Bandwidth_8MHz:
2244 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
2246 case eDVBFrontendParametersTerrestrial::Bandwidth_7MHz:
2247 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
2249 case eDVBFrontendParametersTerrestrial::Bandwidth_6MHz:
2250 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
2253 case eDVBFrontendParametersTerrestrial::Bandwidth_Auto:
2254 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
2257 switch (feparm.code_rate_LP)
2259 case eDVBFrontendParametersTerrestrial::FEC_1_2:
2260 parm_u_ofdm_code_rate_LP = FEC_1_2;
2262 case eDVBFrontendParametersTerrestrial::FEC_2_3:
2263 parm_u_ofdm_code_rate_LP = FEC_2_3;
2265 case eDVBFrontendParametersTerrestrial::FEC_3_4:
2266 parm_u_ofdm_code_rate_LP = FEC_3_4;
2268 case eDVBFrontendParametersTerrestrial::FEC_5_6:
2269 parm_u_ofdm_code_rate_LP = FEC_5_6;
2271 case eDVBFrontendParametersTerrestrial::FEC_7_8:
2272 parm_u_ofdm_code_rate_LP = FEC_7_8;
2275 case eDVBFrontendParametersTerrestrial::FEC_Auto:
2276 parm_u_ofdm_code_rate_LP = FEC_AUTO;
2279 switch (feparm.code_rate_HP)
2281 case eDVBFrontendParametersTerrestrial::FEC_1_2:
2282 parm_u_ofdm_code_rate_HP = FEC_1_2;
2284 case eDVBFrontendParametersTerrestrial::FEC_2_3:
2285 parm_u_ofdm_code_rate_HP = FEC_2_3;
2287 case eDVBFrontendParametersTerrestrial::FEC_3_4:
2288 parm_u_ofdm_code_rate_HP = FEC_3_4;
2290 case eDVBFrontendParametersTerrestrial::FEC_5_6:
2291 parm_u_ofdm_code_rate_HP = FEC_5_6;
2293 case eDVBFrontendParametersTerrestrial::FEC_7_8:
2294 parm_u_ofdm_code_rate_HP = FEC_7_8;
2297 case eDVBFrontendParametersTerrestrial::FEC_Auto:
2298 parm_u_ofdm_code_rate_HP = FEC_AUTO;
2301 switch (feparm.modulation)
2303 case eDVBFrontendParametersTerrestrial::Modulation_QPSK:
2304 parm_u_ofdm_constellation = QPSK;
2306 case eDVBFrontendParametersTerrestrial::Modulation_QAM16:
2307 parm_u_ofdm_constellation = QAM_16;
2309 case eDVBFrontendParametersTerrestrial::Modulation_QAM64:
2310 parm_u_ofdm_constellation = QAM_64;
2313 case eDVBFrontendParametersTerrestrial::Modulation_Auto:
2314 parm_u_ofdm_constellation = QAM_AUTO;
2317 switch (feparm.transmission_mode)
2319 case eDVBFrontendParametersTerrestrial::TransmissionMode_2k:
2320 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2322 case eDVBFrontendParametersTerrestrial::TransmissionMode_8k:
2323 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2326 case eDVBFrontendParametersTerrestrial::TransmissionMode_Auto:
2327 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2330 switch (feparm.guard_interval)
2332 case eDVBFrontendParametersTerrestrial::GuardInterval_1_32:
2333 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2335 case eDVBFrontendParametersTerrestrial::GuardInterval_1_16:
2336 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2338 case eDVBFrontendParametersTerrestrial::GuardInterval_1_8:
2339 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2341 case eDVBFrontendParametersTerrestrial::GuardInterval_1_4:
2342 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2345 case eDVBFrontendParametersTerrestrial::GuardInterval_Auto:
2346 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2349 switch (feparm.hierarchy)
2351 case eDVBFrontendParametersTerrestrial::Hierarchy_None:
2352 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2354 case eDVBFrontendParametersTerrestrial::Hierarchy_1:
2355 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2357 case eDVBFrontendParametersTerrestrial::Hierarchy_2:
2358 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2360 case eDVBFrontendParametersTerrestrial::Hierarchy_4:
2361 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2364 case eDVBFrontendParametersTerrestrial::Hierarchy_Auto:
2365 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2368 switch (feparm.inversion)
2370 case eDVBFrontendParametersTerrestrial::Inversion_On:
2371 parm_inversion = INVERSION_ON;
2373 case eDVBFrontendParametersTerrestrial::Inversion_Off:
2374 parm_inversion = INVERSION_OFF;
2377 case eDVBFrontendParametersTerrestrial::Inversion_Unknown:
2378 parm_inversion = INVERSION_AUTO;
2385 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2387 unsigned int timeout = 5000;
2388 eDebugNoSimulate("(%d)tune", m_dvbid);
2394 if (!m_sn && !m_simulate)
2396 eDebug("no frontend device opened... do not try to tune !!!");
2410 m_sec_sequence.clear();
2412 where.calcLockTimeout(timeout);
2418 eDVBFrontendParametersSatellite feparm;
2419 if (where.getDVBS(feparm))
2421 eDebug("no dvbs data!");
2425 if (m_rotor_mode != feparm.no_rotor_command_on_tune && !feparm.no_rotor_command_on_tune)
2427 eDVBFrontend *sec_fe = this;
2428 long tmp = m_data[LINKED_PREV_PTR];
2431 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
2432 sec_fe = linked_fe->m_frontend;
2433 sec_fe->getData(LINKED_NEXT_PTR, tmp);
2435 eDebug("(fe%d) reset diseqc after leave rotor mode!", m_dvbid);
2436 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
2438 m_rotor_mode = feparm.no_rotor_command_on_tune;
2440 m_sec->setRotorMoving(m_slotid, false);
2441 res=prepare_sat(feparm, timeout);
2449 eDVBFrontendParametersCable feparm;
2450 if (where.getDVBC(feparm))
2455 res=prepare_cable(feparm);
2459 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2460 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2465 eDVBFrontendParametersTerrestrial feparm;
2466 if (where.getDVBT(feparm))
2468 eDebug("no -T data");
2472 res=prepare_terrestrial(feparm);
2476 std::string enable_5V;
2477 char configStr[255];
2478 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2479 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2480 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2481 if (enable_5V == "True")
2482 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2484 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2485 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2491 m_sec_sequence.current() = m_sec_sequence.begin();
2495 m_tuneTimer->start(0,true);
2497 if (m_state != stateTuning)
2499 m_state = stateTuning;
2500 m_stateChanged(this);
2509 m_tuneTimer->stop();
2513 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2515 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2519 RESULT eDVBFrontend::setVoltage(int voltage)
2521 if (m_type == feCable)
2523 #if HAVE_DVB_API_VERSION < 3
2526 bool increased=false;
2527 fe_sec_voltage_t vlt;
2529 m_data[CUR_VOLTAGE]=voltage;
2533 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2534 vlt = SEC_VOLTAGE_OFF;
2537 #if HAVE_DVB_API_VERSION < 3
2538 vlt = SEC_VOLTAGE_13_5;
2544 vlt = SEC_VOLTAGE_13;
2547 #if HAVE_DVB_API_VERSION < 3
2548 vlt = SEC_VOLTAGE_18_5;
2554 vlt = SEC_VOLTAGE_18;
2561 #if HAVE_DVB_API_VERSION < 3
2562 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2564 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2565 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2566 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2570 RESULT eDVBFrontend::getState(int &state)
2576 RESULT eDVBFrontend::setTone(int t)
2578 if (m_type != feSatellite)
2580 #if HAVE_DVB_API_VERSION < 3
2583 fe_sec_tone_mode_t tone;
2592 tone = SEC_TONE_OFF;
2599 #if HAVE_DVB_API_VERSION < 3
2600 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2602 return ::ioctl(m_fd, FE_SET_TONE, tone);
2606 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2607 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2610 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2614 #if HAVE_DVB_API_VERSION < 3
2615 struct secCommand cmd;
2616 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2617 cmd.u.diseqc.cmdtype = diseqc.data[0];
2618 cmd.u.diseqc.addr = diseqc.data[1];
2619 cmd.u.diseqc.cmd = diseqc.data[2];
2620 cmd.u.diseqc.numParams = diseqc.len-3;
2621 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2622 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2624 struct dvb_diseqc_master_cmd cmd;
2625 memcpy(cmd.msg, diseqc.data, diseqc.len);
2626 cmd.msg_len = diseqc.len;
2627 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2633 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2634 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2636 RESULT eDVBFrontend::sendToneburst(int burst)
2640 #if HAVE_DVB_API_VERSION < 3
2641 secMiniCmd cmd = SEC_MINI_NONE;
2643 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2645 if ( burst == eDVBSatelliteDiseqcParameters::A )
2647 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2649 #if HAVE_DVB_API_VERSION < 3
2650 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2653 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2659 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2665 RESULT eDVBFrontend::setSecSequence(eSecCommandList &list)
2667 if (m_data[SATCR] != -1 && m_sec_sequence.current() != m_sec_sequence.end())
2668 m_sec_sequence.push_back(list);
2670 m_sec_sequence = list;
2674 RESULT eDVBFrontend::getData(int num, long &data)
2676 if ( num < NUM_DATA_ENTRIES )
2684 RESULT eDVBFrontend::setData(int num, long val)
2686 if ( num < NUM_DATA_ENTRIES )
2694 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2697 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2699 if (m_type == eDVBFrontend::feSatellite)
2702 eDVBFrontendParametersSatellite sat_parm;
2703 int ret = feparm->getDVBS(sat_parm);
2705 if (sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S2 && !m_can_handle_dvbs2)
2707 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2708 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S && m_can_handle_dvbs2)
2712 else if (m_type == eDVBFrontend::feCable)
2713 return 2; // more prio for cable frontends
2714 else if (m_type == eDVBFrontend::feTerrestrial)
2719 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2721 ePyObject Id, Descr, Enabled, IsDVBS2, frontendId;
2722 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 5)
2724 Id = PyTuple_GET_ITEM(obj, 0);
2725 Descr = PyTuple_GET_ITEM(obj, 1);
2726 Enabled = PyTuple_GET_ITEM(obj, 2);
2727 IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2728 frontendId = PyTuple_GET_ITEM(obj, 4);
2729 m_slotid = PyInt_AsLong(Id);
2730 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2) || !PyInt_Check(frontendId))
2732 strcpy(m_description, PyString_AS_STRING(Descr));
2733 if (PyInt_AsLong(frontendId) == -1 || PyInt_AsLong(frontendId) != m_dvbid) {
2734 // eDebugNoSimulate("skip slotinfo for slotid %d, descr %s",
2735 // m_slotid, m_description);
2738 m_enabled = Enabled == Py_True;
2739 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2740 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2741 !!strstr(m_description, "Alps BSBE2") ||
2742 !!strstr(m_description, "Alps -S") ||
2743 !!strstr(m_description, "BCM4501");
2744 m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2745 eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2746 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2749 PyErr_SetString(PyExc_StandardError,
2750 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");