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, eDVBFrontend *simulate_fe)
457 :m_simulate(simulate), m_enabled(false), m_type(-1), m_simulate_fe(simulate_fe), m_dvbid(fe), m_slotid(fe)
458 ,m_fd(-1), m_rotor_mode(false), m_need_rotor_workaround(false), m_can_handle_dvbs2(false)
459 ,m_state(stateClosed), m_timeout(0), m_tuneTimer(0)
460 #if HAVE_DVB_API_VERSION < 3
464 #if HAVE_DVB_API_VERSION < 3
465 sprintf(m_filename, "/dev/dvb/card%d/frontend%d", adap, fe);
466 sprintf(m_sec_filename, "/dev/dvb/card%d/sec%d", adap, fe);
468 sprintf(m_filename, "/dev/dvb/adapter%d/frontend%d", adap, fe);
471 m_timeout = eTimer::create(eApp);
472 CONNECT(m_timeout->timeout, eDVBFrontend::timeout);
474 m_tuneTimer = eTimer::create(eApp);
475 CONNECT(m_tuneTimer->timeout, eDVBFrontend::tuneLoop);
477 for (int i=0; i<eDVBFrontend::NUM_DATA_ENTRIES; ++i)
480 m_idleInputpower[0]=m_idleInputpower[1]=0;
482 ok = !openFrontend();
486 void eDVBFrontend::reopenFrontend()
493 int eDVBFrontend::openFrontend()
495 if (m_state != stateClosed)
496 return -1; // already opened
501 #if HAVE_DVB_API_VERSION < 3
502 FrontendInfo fe_info;
504 dvb_frontend_info fe_info;
508 eDebug("opening frontend %d", m_dvbid);
511 m_fd = ::open(m_filename, O_RDWR|O_NONBLOCK);
514 eWarning("failed! (%s) %m", m_filename);
519 eWarning("frontend %d already opened", m_dvbid);
522 if (::ioctl(m_fd, FE_GET_INFO, &fe_info) < 0)
524 eWarning("ioctl FE_GET_INFO failed");
530 switch (fe_info.type)
533 m_type = iDVBFrontend::feSatellite;
536 m_type = iDVBFrontend::feCable;
539 m_type = iDVBFrontend::feTerrestrial;
542 eWarning("unknown frontend type.");
548 m_simulate_fe->m_type = m_type;
549 eDebugNoSimulate("detected %s frontend", "satellite\0cable\0 terrestrial"+fe_info.type*10);
552 #if HAVE_DVB_API_VERSION < 3
553 if (m_type == iDVBFrontend::feSatellite)
559 m_secfd = ::open(m_sec_filename, O_RDWR);
562 eWarning("failed! (%s) %m", m_sec_filename);
570 eWarning("sec %d already opened", m_dvbid);
574 m_sn = eSocketNotifier::create(eApp, m_fd, eSocketNotifier::Read, false);
575 CONNECT(m_sn->activated, eDVBFrontend::feEvent);
578 setTone(iDVBFrontend::toneOff);
579 setVoltage(iDVBFrontend::voltageOff);
584 int eDVBFrontend::closeFrontend(bool force, bool no_delayed)
586 if (!force && m_data[CUR_VOLTAGE] != -1 && m_data[CUR_VOLTAGE] != iDVBFrontend::voltageOff)
588 long tmp = m_data[LINKED_NEXT_PTR];
591 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
592 if (linked_fe->m_inuse)
594 eDebugNoSimulate("dont close frontend %d until the linked frontend %d in slot %d is still in use",
595 m_dvbid, linked_fe->m_frontend->getDVBID(), linked_fe->m_frontend->getSlotID());
598 linked_fe->m_frontend->getData(LINKED_NEXT_PTR, tmp);
604 eDebugNoSimulate("close frontend %d", m_dvbid);
605 if (m_data[SATCR] != -1)
609 m_sec->prepareTurnOffSatCR(*this, m_data[SATCR]);
610 m_tuneTimer->start(0, true);
611 if(!m_tuneTimer->isActive())
614 eDebug("[turnOffSatCR] no mainloop");
617 timeout = tuneLoopInt();
620 usleep(timeout*1000); // blockierendes wait.. eTimer gibts ja nicht mehr
624 eDebug("[turnOffSatCR] running mainloop");
628 m_data[ROTOR_CMD] = -1;
631 setTone(iDVBFrontend::toneOff);
632 setVoltage(iDVBFrontend::voltageOff);
635 if (m_sec && !m_simulate)
636 m_sec->setRotorMoving(m_slotid, false);
640 eWarning("couldnt close frontend %d", m_dvbid);
644 setTone(iDVBFrontend::toneOff);
645 setVoltage(iDVBFrontend::voltageOff);
647 #if HAVE_DVB_API_VERSION < 3
650 if (!::close(m_secfd))
653 eWarning("couldnt close sec %d", m_dvbid);
657 m_state = stateClosed;
662 eDVBFrontend::~eDVBFrontend()
664 m_data[LINKED_PREV_PTR] = m_data[LINKED_NEXT_PTR] = -1;
668 void eDVBFrontend::feEvent(int w)
670 eDVBFrontend *sec_fe = this;
671 long tmp = m_data[LINKED_PREV_PTR];
674 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
675 sec_fe = linked_fe->m_frontend;
676 sec_fe->getData(LINKED_NEXT_PTR, tmp);
680 #if HAVE_DVB_API_VERSION < 3
683 dvb_frontend_event event;
687 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
689 if (res && (errno == EAGAIN))
695 #if HAVE_DVB_API_VERSION < 3
696 if (event.type == FE_COMPLETION_EV)
698 eDebug("(%d)fe event: status %x, inversion %s, m_tuning %d", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off", m_tuning);
699 if (event.status & FE_HAS_LOCK)
707 #if HAVE_DVB_API_VERSION >= 3
708 if (event.status & FE_TIMEDOUT) {
709 eDebug("FE_TIMEDOUT! ..abort");
722 eDebug("stateLostLock");
723 state = stateLostLock;
725 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
728 if (m_state != state)
731 m_stateChanged(this);
736 void eDVBFrontend::timeout()
739 if (m_state == stateTuning)
741 #ifdef BUILD_VUPLUS /* ikseong */
742 eDVBFrontend *sec_fe = this;
743 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
745 m_state = stateFailed;
746 m_stateChanged(this);
750 #define INRANGE(X,Y,Z) (((X<=Y) && (Y<=Z))||((Z<=Y) && (Y<=X)) ? 1 : 0)
752 /* unsigned 32 bit division */
753 static inline uint32_t fe_udiv(uint32_t a, uint32_t b)
755 return (a + b / 2) / b;
758 int eDVBFrontend::readFrontendData(int type)
767 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
768 eDebug("FE_READ_BER failed (%m)");
773 case signalQualitydB: /* this will move into the driver */
775 int sat_max = 1600; // for stv0288 / bsbe2
776 int ret = 0x12345678;
780 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
781 eDebug("FE_READ_SNR failed (%m)");
782 else if (!strcmp(m_description, "BCM4501 (internal)"))
784 float SDS_SNRE = snr << 16;
787 if (oparm.sat.system == eDVBFrontendParametersSatellite::System_DVB_S) // DVB-S1 / QPSK
789 static float SNR_COEFF[6] = {
792 197418.0 / 4194304.0,
793 -2602183.0 / 4194304.0,
794 20377212.0 / 4194304.0,
795 -37791203.0 / 4194304.0,
797 float fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0)),
798 fval2 = pow(10.0, fval1)-1;
799 fval1 = 10.0 * log10(fval2);
803 fval2 = SNR_COEFF[0];
804 for (int i=1; i<6; ++i)
807 fval2 += SNR_COEFF[i];
813 #if HAVE_DVB_API_VERSION >= 3
816 float fval1 = SDS_SNRE / 268435456.0,
819 if (oparm.sat.modulation == eDVBFrontendParametersSatellite::Modulation_QPSK)
830 fval4 = -10.0 * log10(fval1);
832 for (int i=0; i < 5; ++i)
833 fval1 = fval4 - fval2 * log10(1.0+pow(10.0, (fval3-fval1)/fval2));
838 ret = (int)(snr_in_db * 100);
840 else if (strstr(m_description, "Alps BSBE1 C01A") ||
841 strstr(m_description, "Alps -S(STV0288)"))
845 else if (snr == 0xFFFF) // i think this should not happen
849 enum { REALVAL, REGVAL };
850 const long CN_lookup[31][2] = {
851 {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
852 {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
853 {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
854 {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
855 {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
856 {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
859 int add=strchr(m_description, '.') ? 0xA250 : 0xA100;
860 long regval = 0xFFFF - ((snr / 3) + add), // revert some dvb api calulations to get the real register value
864 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
869 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[i][REGVAL]))
874 ret = (((regval - CN_lookup[Imin][REGVAL])
875 * (CN_lookup[Imax][REALVAL] - CN_lookup[Imin][REALVAL])
876 / (CN_lookup[Imax][REGVAL] - CN_lookup[Imin][REGVAL]))
877 + CN_lookup[Imin][REALVAL]) * 10;
883 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
884 !strcmp(m_description, "Alps -S") ||
885 !strcmp(m_description, "Philips -S") ||
886 !strcmp(m_description, "LG -S") )
889 ret = (int)((snr-39075)/17.647);
890 } else if (!strcmp(m_description, "Alps BSBE2"))
892 ret = (int)((snr >> 7) * 10);
893 } else if (!strcmp(m_description, "Philips CU1216Mk3"))
895 int mse = (~snr) & 0xFF;
896 switch (parm_u_qam_modulation) {
897 case QAM_16: ret = fe_udiv(1950000, (32 * mse) + 138) + 1000; break;
898 case QAM_32: ret = fe_udiv(2150000, (40 * mse) + 500) + 1350; break;
899 case QAM_64: ret = fe_udiv(2100000, (40 * mse) + 500) + 1250; break;
900 case QAM_128: ret = fe_udiv(1850000, (38 * mse) + 400) + 1380; break;
901 case QAM_256: ret = fe_udiv(1800000, (100 * mse) + 40) + 2030; break;
904 } else if (!strcmp(m_description, "Philips TU1216"))
906 snr = 0xFF - (snr & 0xFF);
908 ret = 10 * (int)(-100 * (log10(snr) - log10(255)));
910 else if (strstr(m_description, "BCM4506") || strstr(m_description, "BCM4505"))
911 ret = (snr * 100) >> 8;
912 else if (!strcmp(m_description, "CXD1981"))
914 int mse = (~snr) & 0xFF;
915 switch (parm_u_qam_modulation) {
918 case QAM_256: ret = (int)(-950 * log(((double)mse) / 760)); break;
920 case QAM_128: ret = (int)(-875 * log(((double)mse) / 650)); break;
926 if (type == signalQuality)
928 if (ret == 0x12345678) // no snr db calculation avail.. return untouched snr value..
933 return ret >= sat_max ? 65536 : ret * 65536 / sat_max;
934 case feCable: // we assume a max of 42db here
935 return ret >= 4200 ? 65536 : ret * 65536 / 4200;
936 case feTerrestrial: // we assume a max of 24db here
937 return ret >= 2400 ? 65536 : ret * 65536 / 2400;
941 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
949 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
950 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
956 #if HAVE_DVB_API_VERSION < 3
957 FrontendStatus status=0;
963 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
964 eDebug("FE_READ_STATUS failed (%m)");
965 return !!(status&FE_HAS_LOCK);
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_SYNC);
990 void PutToDict(ePyObject &dict, const char*key, long value)
992 ePyObject item = PyInt_FromLong(value);
995 if (PyDict_SetItemString(dict, key, item))
996 eDebug("put %s to dict failed", key);
1000 eDebug("could not create PyObject for %s", key);
1003 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
1007 if (PyDict_SetItemString(dict, key, item))
1008 eDebug("put %s to dict failed", key);
1012 eDebug("invalid PyObject for %s", key);
1015 void PutToDict(ePyObject &dict, const char*key, const char *value)
1017 ePyObject item = PyString_FromString(value);
1020 if (PyDict_SetItemString(dict, key, item))
1021 eDebug("put %s to dict failed", key);
1025 eDebug("could not create PyObject for %s", key);
1028 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
1030 PutToDict(dict, "tuner_type", "DVB-S");
1031 PutToDict(dict, "frequency", feparm.frequency);
1032 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
1033 PutToDict(dict, "orbital_position", feparm.orbital_position);
1034 PutToDict(dict, "inversion", feparm.inversion);
1035 PutToDict(dict, "fec_inner", feparm.fec);
1036 PutToDict(dict, "modulation", feparm.modulation);
1037 PutToDict(dict, "polarization", feparm.polarisation);
1038 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S2)
1040 PutToDict(dict, "rolloff", feparm.rolloff);
1041 PutToDict(dict, "pilot", feparm.pilot);
1043 PutToDict(dict, "system", feparm.system);
1046 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
1048 PutToDict(dict, "tuner_type", "DVB-T");
1049 PutToDict(dict, "frequency", feparm.frequency);
1050 PutToDict(dict, "bandwidth", feparm.bandwidth);
1051 PutToDict(dict, "code_rate_lp", feparm.code_rate_LP);
1052 PutToDict(dict, "code_rate_hp", feparm.code_rate_HP);
1053 PutToDict(dict, "constellation", feparm.modulation);
1054 PutToDict(dict, "transmission_mode", feparm.transmission_mode);
1055 PutToDict(dict, "guard_interval", feparm.guard_interval);
1056 PutToDict(dict, "hierarchy_information", feparm.hierarchy);
1057 PutToDict(dict, "inversion", feparm.inversion);
1060 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
1062 PutToDict(dict, "tuner_type", "DVB-C");
1063 PutToDict(dict, "frequency", feparm.frequency);
1064 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
1065 PutToDict(dict, "modulation", feparm.modulation);
1066 PutToDict(dict, "inversion", feparm.inversion);
1067 PutToDict(dict, "fec_inner", feparm.fec_inner);
1070 #if HAVE_DVB_API_VERSION >= 5
1071 static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, struct dtv_property *p, long freq_offset, int orb_pos, int polarization)
1074 int frequency = parm_frequency + freq_offset;
1075 PutToDict(dict, "frequency", frequency);
1076 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
1077 PutToDict(dict, "orbital_position", orb_pos);
1078 PutToDict(dict, "polarization", polarization);
1080 switch(parm_u_qpsk_fec_inner)
1082 case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1083 case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1084 case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1085 case FEC_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
1086 case FEC_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
1087 case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1088 case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1089 case FEC_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
1090 case FEC_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1091 case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
1092 case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
1093 default: eDebug("got unsupported FEC from frontend! report as FEC_AUTO!\n");
1095 PutToDict(dict, "fec_inner", tmp);
1097 switch (p[0].u.data)
1099 default: eDebug("got unsupported system from frontend! report as DVBS!");
1100 case SYS_DVBS: tmp = eDVBFrontendParametersSatellite::System_DVB_S; break;
1103 switch (p[2].u.data)
1105 default: eDebug("got unsupported rolloff from frontend! report as 0_20!");
1106 case ROLLOFF_20: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1107 case ROLLOFF_25: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1108 case ROLLOFF_35: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1110 PutToDict(dict, "rolloff", tmp);
1112 switch (p[3].u.data)
1114 case PILOT_OFF: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1115 case PILOT_ON: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1116 case PILOT_AUTO: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1118 PutToDict(dict, "pilot", tmp);
1120 tmp = eDVBFrontendParametersSatellite::System_DVB_S2; break;
1123 PutToDict(dict, "system", tmp);
1125 switch (p[1].u.data)
1127 default: eDebug("got unsupported modulation from frontend! report as QPSK!");
1128 case QPSK: tmp = eDVBFrontendParametersSatellite::Modulation_QPSK; break;
1129 case PSK_8: tmp = eDVBFrontendParametersSatellite::Modulation_8PSK; break;
1131 PutToDict(dict, "modulation", tmp);
1135 static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, long freq_offset, int orb_pos, int polarization)
1138 int frequency = parm_frequency + freq_offset;
1139 PutToDict(dict, "frequency", frequency);
1140 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
1141 PutToDict(dict, "orbital_position", orb_pos);
1142 PutToDict(dict, "polarization", polarization);
1144 switch((int)parm_u_qpsk_fec_inner)
1146 case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1147 case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1148 case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1149 case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1150 case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1151 case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
1153 case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
1154 #if HAVE_DVB_API_VERSION >=3
1155 case FEC_S2_8PSK_1_2:
1156 case FEC_S2_QPSK_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1157 case FEC_S2_8PSK_2_3:
1158 case FEC_S2_QPSK_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1159 case FEC_S2_8PSK_3_4:
1160 case FEC_S2_QPSK_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1161 case FEC_S2_8PSK_5_6:
1162 case FEC_S2_QPSK_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1163 case FEC_S2_8PSK_7_8:
1164 case FEC_S2_QPSK_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1165 case FEC_S2_8PSK_8_9:
1166 case FEC_S2_QPSK_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
1167 case FEC_S2_8PSK_3_5:
1168 case FEC_S2_QPSK_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
1169 case FEC_S2_8PSK_4_5:
1170 case FEC_S2_QPSK_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
1171 case FEC_S2_8PSK_9_10:
1172 case FEC_S2_QPSK_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1175 PutToDict(dict, "fec_inner", tmp);
1176 #if HAVE_DVB_API_VERSION >=3
1177 PutToDict(dict, "modulation",
1178 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ?
1179 eDVBFrontendParametersSatellite::Modulation_8PSK :
1180 eDVBFrontendParametersSatellite::Modulation_QPSK );
1181 if (parm_u_qpsk_fec_inner > FEC_AUTO)
1183 switch(parm_inversion & 0xc)
1185 default: // unknown rolloff
1186 case 0: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1187 case 4: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1188 case 8: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1190 PutToDict(dict, "rolloff", tmp);
1191 switch(parm_inversion & 0x30)
1193 case 0: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1194 case 0x10: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1195 case 0x20: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1197 PutToDict(dict, "pilot", tmp);
1198 tmp = eDVBFrontendParametersSatellite::System_DVB_S2;
1201 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1203 PutToDict(dict, "modulation", eDVBFrontendParametersSatellite::Modulation_QPSK );
1204 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1206 PutToDict(dict, "system", tmp);
1210 static void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1213 #if HAVE_DVB_API_VERSION < 3
1214 PutToDict(dict, "frequency", parm_frequency);
1216 PutToDict(dict, "frequency", parm_frequency/1000);
1218 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1219 switch(parm_u_qam_fec_inner)
1221 case FEC_NONE: tmp = eDVBFrontendParametersCable::FEC_None; break;
1222 case FEC_1_2: tmp = eDVBFrontendParametersCable::FEC_1_2; break;
1223 case FEC_2_3: tmp = eDVBFrontendParametersCable::FEC_2_3; break;
1224 case FEC_3_4: tmp = eDVBFrontendParametersCable::FEC_3_4; break;
1225 case FEC_5_6: tmp = eDVBFrontendParametersCable::FEC_5_6; break;
1226 case FEC_7_8: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1227 #if HAVE_DVB_API_VERSION >= 3
1228 case FEC_8_9: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1231 case FEC_AUTO: tmp = eDVBFrontendParametersCable::FEC_Auto; break;
1233 PutToDict(dict, "fec_inner", tmp);
1234 switch(parm_u_qam_modulation)
1236 case QAM_16: tmp = eDVBFrontendParametersCable::Modulation_QAM16; break;
1237 case QAM_32: tmp = eDVBFrontendParametersCable::Modulation_QAM32; break;
1238 case QAM_64: tmp = eDVBFrontendParametersCable::Modulation_QAM64; break;
1239 case QAM_128: tmp = eDVBFrontendParametersCable::Modulation_QAM128; break;
1240 case QAM_256: tmp = eDVBFrontendParametersCable::Modulation_QAM256; break;
1242 case QAM_AUTO: tmp = eDVBFrontendParametersCable::Modulation_Auto; break;
1244 PutToDict(dict, "modulation", tmp);
1247 static void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1250 PutToDict(dict, "frequency", parm_frequency);
1251 switch (parm_u_ofdm_bandwidth)
1253 case BANDWIDTH_8_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_8MHz; break;
1254 case BANDWIDTH_7_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_7MHz; break;
1255 case BANDWIDTH_6_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_6MHz; break;
1257 case BANDWIDTH_AUTO: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_Auto; break;
1259 PutToDict(dict, "bandwidth", tmp);
1260 switch (parm_u_ofdm_code_rate_LP)
1262 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1263 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1264 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1265 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1266 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1268 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1270 PutToDict(dict, "code_rate_lp", tmp);
1271 switch (parm_u_ofdm_code_rate_HP)
1273 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1274 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1275 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1276 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1277 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1279 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1281 PutToDict(dict, "code_rate_hp", tmp);
1282 switch (parm_u_ofdm_constellation)
1284 case QPSK: tmp = eDVBFrontendParametersTerrestrial::Modulation_QPSK; break;
1285 case QAM_16: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM16; break;
1286 case QAM_64: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM64; break;
1288 case QAM_AUTO: tmp = eDVBFrontendParametersTerrestrial::Modulation_Auto; break;
1290 PutToDict(dict, "constellation", tmp);
1291 switch (parm_u_ofdm_transmission_mode)
1293 case TRANSMISSION_MODE_2K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_2k; break;
1294 case TRANSMISSION_MODE_8K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_8k; break;
1296 case TRANSMISSION_MODE_AUTO: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto; break;
1298 PutToDict(dict, "transmission_mode", tmp);
1299 switch (parm_u_ofdm_guard_interval)
1301 case GUARD_INTERVAL_1_32: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_32; break;
1302 case GUARD_INTERVAL_1_16: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_16; break;
1303 case GUARD_INTERVAL_1_8: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_8; break;
1304 case GUARD_INTERVAL_1_4: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_4; break;
1306 case GUARD_INTERVAL_AUTO: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_Auto; break;
1308 PutToDict(dict, "guard_interval", tmp);
1309 switch (parm_u_ofdm_hierarchy_information)
1311 case HIERARCHY_NONE: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_None; break;
1312 case HIERARCHY_1: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_1; break;
1313 case HIERARCHY_2: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_2; break;
1314 case HIERARCHY_4: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_4; break;
1316 case HIERARCHY_AUTO: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_Auto; break;
1318 PutToDict(dict, "hierarchy_information", tmp);
1321 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1323 if (dest && PyDict_Check(dest))
1325 const char *tmp = "UNKNOWN";
1346 PutToDict(dest, "tuner_state", tmp);
1347 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1348 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1349 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1350 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1351 int sigQualitydB = readFrontendData(signalQualitydB);
1352 if (sigQualitydB == 0x12345678) // not support yet
1354 ePyObject obj=Py_None;
1356 PutToDict(dest, "tuner_signal_quality_db", obj);
1359 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1360 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1364 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1366 if (dest && PyDict_Check(dest))
1368 FRONTENDPARAMETERS front;
1369 #if HAVE_DVB_API_VERSION >= 5
1370 struct dtv_property p[4];
1371 struct dtv_properties cmdseq;
1374 p[0].cmd = DTV_DELIVERY_SYSTEM;
1375 p[1].cmd = DTV_MODULATION;
1376 p[2].cmd = DTV_ROLLOFF;
1377 p[3].cmd = DTV_PILOT;
1379 if (m_simulate || m_fd == -1 || original)
1381 #if HAVE_DVB_API_VERSION >= 5
1382 else if (m_type == feSatellite && // yet just use new api for DVB-S(2) only
1383 ioctl(m_fd, FE_GET_PROPERTY, &cmdseq)<0)
1385 eDebug("FE_GET_PROPERTY failed (%m)");
1389 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1391 eDebug("FE_GET_FRONTEND failed (%m)");
1399 PutSatelliteDataToDict(dest, oparm.sat);
1402 PutCableDataToDict(dest, oparm.cab);
1405 PutTerrestrialDataToDict(dest, oparm.ter);
1411 FRONTENDPARAMETERS &parm = front;
1412 long tmp = eDVBFrontendParametersSatellite::Inversion_Unknown;
1413 switch(parm_inversion & 3)
1416 tmp = eDVBFrontendParametersSatellite::Inversion_On;
1419 tmp = eDVBFrontendParametersSatellite::Inversion_Off;
1423 PutToDict(dest, "inversion", tmp);
1427 #if HAVE_DVB_API_VERSION >= 5
1428 fillDictWithSatelliteData(dest, parm, p, m_data[FREQ_OFFSET], oparm.sat.orbital_position, oparm.sat.polarisation);
1430 fillDictWithSatelliteData(dest, parm, m_data[FREQ_OFFSET], oparm.sat.orbital_position, oparm.sat.polarisation);
1434 fillDictWithCableData(dest, parm);
1437 fillDictWithTerrestrialData(dest, parm);
1444 void eDVBFrontend::getFrontendData(ePyObject dest)
1446 if (dest && PyDict_Check(dest))
1449 PutToDict(dest, "tuner_number", m_slotid);
1465 PutToDict(dest, "tuner_type", tmp);
1469 #ifndef FP_IOCTL_GET_ID
1470 #define FP_IOCTL_GET_ID 0
1472 int eDVBFrontend::readInputpower()
1476 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1478 char proc_name2[64];
1479 sprintf(proc_name, "/proc/stb/frontend/%d/lnb_sense", m_slotid);
1480 sprintf(proc_name2, "/proc/stb/fp/lnb_sense%d", m_slotid);
1482 if ((f=fopen(proc_name, "r")) || (f=fopen(proc_name2, "r")))
1484 if (fscanf(f, "%d", &power) != 1)
1485 eDebug("read %s failed!! (%m)", proc_name);
1487 eDebug("%s is %d\n", proc_name, power);
1492 // open front prozessor
1493 int fp=::open("/dev/dbox/fp0", O_RDWR);
1496 eDebug("couldn't open fp");
1499 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1500 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1502 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1511 bool eDVBFrontend::setSecSequencePos(int steps)
1513 eDebugNoSimulate("set sequence pos %d", steps);
1518 if (m_sec_sequence.current() != m_sec_sequence.end())
1519 ++m_sec_sequence.current();
1524 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1525 --m_sec_sequence.current();
1531 void eDVBFrontend::tuneLoop()
1536 int eDVBFrontend::tuneLoopInt() // called by m_tuneTimer
1539 eDVBFrontend *sec_fe = this;
1540 eDVBRegisteredFrontend *regFE = 0;
1541 long tmp = m_data[LINKED_PREV_PTR];
1544 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1545 sec_fe = prev->m_frontend;
1546 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1547 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1548 int state = sec_fe->m_state;
1549 // workaround to put the kernel frontend thread into idle state!
1550 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1552 sec_fe->closeFrontend(true);
1553 state = sec_fe->m_state;
1555 // sec_fe is closed... we must reopen it here..
1556 if (state == stateClosed)
1564 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1566 long *sec_fe_data = sec_fe->m_data;
1567 // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1569 switch (m_sec_sequence.current()->cmd)
1571 case eSecCommand::SLEEP:
1572 delay = m_sec_sequence.current()++->msec;
1573 eDebugNoSimulate("[SEC] sleep %dms", delay);
1575 case eSecCommand::GOTO:
1576 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1577 ++m_sec_sequence.current();
1579 case eSecCommand::SET_VOLTAGE:
1581 int voltage = m_sec_sequence.current()++->voltage;
1582 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1583 sec_fe->setVoltage(voltage);
1586 case eSecCommand::IF_VOLTAGE_GOTO:
1588 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1589 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1591 ++m_sec_sequence.current();
1594 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1596 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1597 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1599 ++m_sec_sequence.current();
1602 case eSecCommand::IF_TONE_GOTO:
1604 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1605 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1607 ++m_sec_sequence.current();
1610 case eSecCommand::IF_NOT_TONE_GOTO:
1612 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1613 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1615 ++m_sec_sequence.current();
1618 case eSecCommand::SET_TONE:
1619 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1620 sec_fe->setTone(m_sec_sequence.current()++->tone);
1622 case eSecCommand::SEND_DISEQC:
1623 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1624 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1625 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1626 eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1627 if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
1628 eDebugNoSimulate("(DiSEqC reset)");
1629 else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
1630 eDebugNoSimulate("(DiSEqC peripherial power on)");
1632 eDebugNoSimulate("");
1633 ++m_sec_sequence.current();
1635 case eSecCommand::SEND_TONEBURST:
1636 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1637 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1639 case eSecCommand::SET_FRONTEND:
1641 int enableEvents = (m_sec_sequence.current()++)->val;
1642 eDebugNoSimulate("[SEC] setFrontend %d", enableEvents);
1643 setFrontend(enableEvents);
1646 case eSecCommand::START_TUNE_TIMEOUT:
1648 int tuneTimeout = m_sec_sequence.current()->timeout;
1649 eDebugNoSimulate("[SEC] startTuneTimeout %d", tuneTimeout);
1651 m_timeout->start(tuneTimeout, 1);
1652 ++m_sec_sequence.current();
1655 case eSecCommand::SET_TIMEOUT:
1656 m_timeoutCount = m_sec_sequence.current()++->val;
1657 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1659 case eSecCommand::IF_TIMEOUT_GOTO:
1660 if (!m_timeoutCount)
1662 eDebugNoSimulate("[SEC] rotor timout");
1663 setSecSequencePos(m_sec_sequence.current()->steps);
1666 ++m_sec_sequence.current();
1668 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1670 int idx = m_sec_sequence.current()++->val;
1671 if ( idx == 0 || idx == 1 )
1673 m_idleInputpower[idx] = sec_fe->readInputpower();
1674 eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1677 eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1680 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1682 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1683 int idx = compare.val;
1684 if ( !m_simulate && (idx == 0 || idx == 1) )
1686 int idle = sec_fe->readInputpower();
1687 int diff = abs(idle-m_idleInputpower[idx]);
1690 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1691 setSecSequencePos(compare.steps);
1695 ++m_sec_sequence.current();
1698 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1700 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1703 setSecSequencePos(cmd.steps);
1707 int isLocked = readFrontendData(locked);
1708 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1710 if (!m_timeoutCount && m_retryCount > 0)
1712 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 40) || !cmd.lastSignal))
1715 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1718 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1720 cmd.lastSignal = signal;
1723 if (cmd.okcount > 4)
1725 eDebugNoSimulate("ok > 4 .. goto %d\n", cmd.steps);
1726 setSecSequencePos(cmd.steps);
1727 m_state = stateLock;
1728 m_stateChanged(this);
1729 feEvent(-1); // flush events
1737 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1739 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1743 ++m_sec_sequence.current();
1746 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1747 m_runningInputpower = sec_fe->readInputpower();
1748 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1749 ++m_sec_sequence.current();
1751 case eSecCommand::SET_ROTOR_MOVING:
1753 m_sec->setRotorMoving(m_slotid, true);
1754 ++m_sec_sequence.current();
1756 case eSecCommand::SET_ROTOR_STOPPED:
1758 m_sec->setRotorMoving(m_slotid, false);
1759 ++m_sec_sequence.current();
1761 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1763 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1766 setSecSequencePos(cmd.steps);
1769 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1770 const char *txt = cmd.direction ? "running" : "stopped";
1772 if (!m_timeoutCount && m_retryCount > 0)
1774 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1776 m_runningInputpower,
1779 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1780 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1783 eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1784 if ( cmd.okcount > 6 )
1786 eDebugNoSimulate("[SEC] rotor is %s", txt);
1787 if (setSecSequencePos(cmd.steps))
1793 eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1796 ++m_sec_sequence.current();
1799 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1800 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1801 setSecSequencePos(m_sec_sequence.current()->steps);
1803 ++m_sec_sequence.current();
1805 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1806 eDebugNoSimulate("[SEC] invalidate current switch params");
1807 sec_fe_data[CSW] = -1;
1808 sec_fe_data[UCSW] = -1;
1809 sec_fe_data[TONEBURST] = -1;
1810 ++m_sec_sequence.current();
1812 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1813 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1814 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1815 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1816 eDebugNoSimulate("[SEC] update current switch params");
1817 ++m_sec_sequence.current();
1819 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1820 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1821 sec_fe_data[ROTOR_CMD] = -1;
1822 sec_fe_data[ROTOR_POS] = -1;
1823 ++m_sec_sequence.current();
1825 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1826 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1827 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1828 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1829 ++m_sec_sequence.current();
1831 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1832 m_retryCount = m_sec_sequence.current()++->val;
1833 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1835 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1838 eDebugNoSimulate("[SEC] no more rotor retrys");
1839 setSecSequencePos(m_sec_sequence.current()->steps);
1842 ++m_sec_sequence.current();
1844 case eSecCommand::SET_POWER_LIMITING_MODE:
1849 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1850 FILE *f=fopen(proc_name, "w");
1851 if (f) // new interface exist?
1853 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1854 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1855 eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1857 eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1860 else if (sec_fe->m_need_rotor_workaround)
1863 int slotid = sec_fe->m_slotid;
1864 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1866 sprintf(dev, "/dev/i2c-%d", slotid);
1867 else if (slotid == 2)
1868 sprintf(dev, "/dev/i2c-2"); // first nim socket on DM8000 use /dev/i2c-2
1869 else if (slotid == 3)
1870 sprintf(dev, "/dev/i2c-4"); // second nim socket on DM8000 use /dev/i2c-4
1871 int fd = ::open(dev, O_RDWR);
1873 unsigned char data[2];
1874 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1875 if(::read(fd, data, 1) != 1)
1876 eDebugNoSimulate("[SEC] error read lnbp (%m)");
1877 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1879 data[0] |= 0x80; // enable static current limiting
1880 eDebugNoSimulate("[SEC] set static current limiting");
1884 data[0] &= ~0x80; // enable dynamic current limiting
1885 eDebugNoSimulate("[SEC] set dynamic current limiting");
1887 if(::write(fd, data, 1) != 1)
1888 eDebugNoSimulate("[SEC] error write lnbp (%m)");
1892 ++m_sec_sequence.current();
1895 case eSecCommand::DELAYED_CLOSE_FRONTEND:
1897 eDebugNoSimulate("[SEC] delayed close frontend");
1898 closeFrontend(false, true);
1899 ++m_sec_sequence.current();
1903 eDebugNoSimulate("[SEC] unhandled sec command %d",
1904 ++m_sec_sequence.current()->cmd);
1905 ++m_sec_sequence.current();
1908 m_tuneTimer->start(delay,true);
1912 if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1917 void eDVBFrontend::setFrontend(bool recvEvents)
1921 eDebug("setting frontend %d", m_dvbid);
1924 feEvent(-1); // flush events
1925 #if HAVE_DVB_API_VERSION >= 5
1926 if (m_type == iDVBFrontend::feSatellite)
1928 fe_rolloff_t rolloff = ROLLOFF_35;
1929 fe_pilot_t pilot = PILOT_OFF;
1930 fe_modulation_t modulation = QPSK;
1931 fe_delivery_system_t system = SYS_DVBS;
1932 switch(oparm.sat.system)
1934 case eDVBFrontendParametersSatellite::System_DVB_S: system = SYS_DVBS; break;
1935 case eDVBFrontendParametersSatellite::System_DVB_S2: system = SYS_DVBS2; break;
1937 switch(oparm.sat.modulation)
1939 case eDVBFrontendParametersSatellite::Modulation_QPSK: modulation = QPSK; break;
1940 case eDVBFrontendParametersSatellite::Modulation_8PSK: modulation = PSK_8; break;
1941 case eDVBFrontendParametersSatellite::Modulation_QAM16: modulation = QAM_16; break;
1943 switch(oparm.sat.pilot)
1945 case eDVBFrontendParametersSatellite::Pilot_Off: pilot = PILOT_OFF; break;
1946 case eDVBFrontendParametersSatellite::Pilot_On: pilot = PILOT_ON; break;
1947 case eDVBFrontendParametersSatellite::Pilot_Unknown: pilot = PILOT_AUTO; break;
1949 switch(oparm.sat.rolloff)
1951 case eDVBFrontendParametersSatellite::RollOff_alpha_0_20: rolloff = ROLLOFF_20; break;
1952 case eDVBFrontendParametersSatellite::RollOff_alpha_0_25: rolloff = ROLLOFF_25; break;
1953 case eDVBFrontendParametersSatellite::RollOff_alpha_0_35: rolloff = ROLLOFF_35; break;
1955 struct dtv_property p[10];
1956 struct dtv_properties cmdseq;
1958 p[0].cmd = DTV_CLEAR;
1959 p[1].cmd = DTV_DELIVERY_SYSTEM, p[1].u.data = system;
1960 p[2].cmd = DTV_FREQUENCY, p[2].u.data = parm_frequency;
1961 p[3].cmd = DTV_MODULATION, p[3].u.data = modulation;
1962 p[4].cmd = DTV_SYMBOL_RATE, p[4].u.data = parm_u_qpsk_symbol_rate;
1963 p[5].cmd = DTV_INNER_FEC, p[5].u.data = parm_u_qpsk_fec_inner;
1964 p[6].cmd = DTV_INVERSION, p[6].u.data = parm_inversion;
1965 if (system == SYS_DVBS2)
1967 p[7].cmd = DTV_ROLLOFF, p[7].u.data = rolloff;
1968 p[8].cmd = DTV_PILOT, p[8].u.data = pilot;
1969 p[9].cmd = DTV_TUNE;
1974 p[7].cmd = DTV_TUNE;
1977 if (ioctl(m_fd, FE_SET_PROPERTY, &cmdseq) == -1)
1979 perror("FE_SET_PROPERTY failed");
1986 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1988 perror("FE_SET_FRONTEND failed");
1995 RESULT eDVBFrontend::getFrontendType(int &t)
2003 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
2008 eWarning("no SEC module active!");
2011 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
2014 #if HAVE_DVB_API_VERSION >= 3
2015 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",
2018 feparm.polarisation,
2022 feparm.orbital_position,
2028 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
2031 feparm.polarisation,
2035 feparm.orbital_position);
2037 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
2038 switch (feparm.inversion)
2040 case eDVBFrontendParametersSatellite::Inversion_On:
2041 parm_inversion = INVERSION_ON;
2043 case eDVBFrontendParametersSatellite::Inversion_Off:
2044 parm_inversion = INVERSION_OFF;
2047 case eDVBFrontendParametersSatellite::Inversion_Unknown:
2048 parm_inversion = INVERSION_AUTO;
2051 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S)
2055 case eDVBFrontendParametersSatellite::FEC_None:
2056 parm_u_qpsk_fec_inner = FEC_NONE;
2058 case eDVBFrontendParametersSatellite::FEC_1_2:
2059 parm_u_qpsk_fec_inner = FEC_1_2;
2061 case eDVBFrontendParametersSatellite::FEC_2_3:
2062 parm_u_qpsk_fec_inner = FEC_2_3;
2064 case eDVBFrontendParametersSatellite::FEC_3_4:
2065 parm_u_qpsk_fec_inner = FEC_3_4;
2067 case eDVBFrontendParametersSatellite::FEC_5_6:
2068 parm_u_qpsk_fec_inner = FEC_5_6;
2070 case eDVBFrontendParametersSatellite::FEC_7_8:
2071 parm_u_qpsk_fec_inner = FEC_7_8;
2074 eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
2075 case eDVBFrontendParametersSatellite::FEC_Auto:
2076 parm_u_qpsk_fec_inner = FEC_AUTO;
2080 #if HAVE_DVB_API_VERSION >= 3
2085 case eDVBFrontendParametersSatellite::FEC_1_2:
2086 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
2088 case eDVBFrontendParametersSatellite::FEC_2_3:
2089 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
2091 case eDVBFrontendParametersSatellite::FEC_3_4:
2092 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
2094 case eDVBFrontendParametersSatellite::FEC_3_5:
2095 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
2097 case eDVBFrontendParametersSatellite::FEC_4_5:
2098 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
2100 case eDVBFrontendParametersSatellite::FEC_5_6:
2101 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
2103 case eDVBFrontendParametersSatellite::FEC_7_8:
2104 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
2106 case eDVBFrontendParametersSatellite::FEC_8_9:
2107 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
2109 case eDVBFrontendParametersSatellite::FEC_9_10:
2110 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
2113 eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
2116 #if HAVE_DVB_API_VERSION < 5
2117 parm_inversion = (fe_spectral_inversion_t)((feparm.rolloff << 2) | parm_inversion); // Hack.. we use bit 2..3 of inversion param for rolloff
2118 parm_inversion = (fe_spectral_inversion_t)((feparm.pilot << 4) | parm_inversion); // Hack.. we use bit 4..5 of inversion param for pilot
2119 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation_8PSK)
2121 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
2122 // 8PSK fec driver values are decimal 9 bigger
2127 // FIXME !!! get frequency range from tuner
2128 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
2130 eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
2133 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
2139 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
2141 #if HAVE_DVB_API_VERSION < 3
2142 parm_frequency = feparm.frequency;
2144 parm_frequency = feparm.frequency * 1000;
2146 parm_u_qam_symbol_rate = feparm.symbol_rate;
2147 switch (feparm.modulation)
2149 case eDVBFrontendParametersCable::Modulation_QAM16:
2150 parm_u_qam_modulation = QAM_16;
2152 case eDVBFrontendParametersCable::Modulation_QAM32:
2153 parm_u_qam_modulation = QAM_32;
2155 case eDVBFrontendParametersCable::Modulation_QAM64:
2156 parm_u_qam_modulation = QAM_64;
2158 case eDVBFrontendParametersCable::Modulation_QAM128:
2159 parm_u_qam_modulation = QAM_128;
2161 case eDVBFrontendParametersCable::Modulation_QAM256:
2162 parm_u_qam_modulation = QAM_256;
2165 case eDVBFrontendParametersCable::Modulation_Auto:
2166 parm_u_qam_modulation = QAM_AUTO;
2169 switch (feparm.inversion)
2171 case eDVBFrontendParametersCable::Inversion_On:
2172 parm_inversion = INVERSION_ON;
2174 case eDVBFrontendParametersCable::Inversion_Off:
2175 parm_inversion = INVERSION_OFF;
2178 case eDVBFrontendParametersCable::Inversion_Unknown:
2179 parm_inversion = INVERSION_AUTO;
2182 switch (feparm.fec_inner)
2184 case eDVBFrontendParametersCable::FEC_None:
2185 parm_u_qam_fec_inner = FEC_NONE;
2187 case eDVBFrontendParametersCable::FEC_1_2:
2188 parm_u_qam_fec_inner = FEC_1_2;
2190 case eDVBFrontendParametersCable::FEC_2_3:
2191 parm_u_qam_fec_inner = FEC_2_3;
2193 case eDVBFrontendParametersCable::FEC_3_4:
2194 parm_u_qam_fec_inner = FEC_3_4;
2196 case eDVBFrontendParametersCable::FEC_5_6:
2197 parm_u_qam_fec_inner = FEC_5_6;
2199 case eDVBFrontendParametersCable::FEC_7_8:
2200 parm_u_qam_fec_inner = FEC_7_8;
2202 #if HAVE_DVB_API_VERSION >= 3
2203 case eDVBFrontendParametersCable::FEC_8_9:
2204 parm_u_qam_fec_inner = FEC_8_9;
2208 case eDVBFrontendParametersCable::FEC_Auto:
2209 parm_u_qam_fec_inner = FEC_AUTO;
2212 eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
2213 parm_frequency/1000,
2214 parm_u_qam_symbol_rate,
2215 parm_u_qam_fec_inner,
2216 parm_u_qam_modulation,
2222 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
2224 parm_frequency = feparm.frequency;
2226 switch (feparm.bandwidth)
2228 case eDVBFrontendParametersTerrestrial::Bandwidth_8MHz:
2229 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
2231 case eDVBFrontendParametersTerrestrial::Bandwidth_7MHz:
2232 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
2234 case eDVBFrontendParametersTerrestrial::Bandwidth_6MHz:
2235 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
2238 case eDVBFrontendParametersTerrestrial::Bandwidth_Auto:
2239 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
2242 switch (feparm.code_rate_LP)
2244 case eDVBFrontendParametersTerrestrial::FEC_1_2:
2245 parm_u_ofdm_code_rate_LP = FEC_1_2;
2247 case eDVBFrontendParametersTerrestrial::FEC_2_3:
2248 parm_u_ofdm_code_rate_LP = FEC_2_3;
2250 case eDVBFrontendParametersTerrestrial::FEC_3_4:
2251 parm_u_ofdm_code_rate_LP = FEC_3_4;
2253 case eDVBFrontendParametersTerrestrial::FEC_5_6:
2254 parm_u_ofdm_code_rate_LP = FEC_5_6;
2256 case eDVBFrontendParametersTerrestrial::FEC_7_8:
2257 parm_u_ofdm_code_rate_LP = FEC_7_8;
2260 case eDVBFrontendParametersTerrestrial::FEC_Auto:
2261 parm_u_ofdm_code_rate_LP = FEC_AUTO;
2264 switch (feparm.code_rate_HP)
2266 case eDVBFrontendParametersTerrestrial::FEC_1_2:
2267 parm_u_ofdm_code_rate_HP = FEC_1_2;
2269 case eDVBFrontendParametersTerrestrial::FEC_2_3:
2270 parm_u_ofdm_code_rate_HP = FEC_2_3;
2272 case eDVBFrontendParametersTerrestrial::FEC_3_4:
2273 parm_u_ofdm_code_rate_HP = FEC_3_4;
2275 case eDVBFrontendParametersTerrestrial::FEC_5_6:
2276 parm_u_ofdm_code_rate_HP = FEC_5_6;
2278 case eDVBFrontendParametersTerrestrial::FEC_7_8:
2279 parm_u_ofdm_code_rate_HP = FEC_7_8;
2282 case eDVBFrontendParametersTerrestrial::FEC_Auto:
2283 parm_u_ofdm_code_rate_HP = FEC_AUTO;
2286 switch (feparm.modulation)
2288 case eDVBFrontendParametersTerrestrial::Modulation_QPSK:
2289 parm_u_ofdm_constellation = QPSK;
2291 case eDVBFrontendParametersTerrestrial::Modulation_QAM16:
2292 parm_u_ofdm_constellation = QAM_16;
2294 case eDVBFrontendParametersTerrestrial::Modulation_QAM64:
2295 parm_u_ofdm_constellation = QAM_64;
2298 case eDVBFrontendParametersTerrestrial::Modulation_Auto:
2299 parm_u_ofdm_constellation = QAM_AUTO;
2302 switch (feparm.transmission_mode)
2304 case eDVBFrontendParametersTerrestrial::TransmissionMode_2k:
2305 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2307 case eDVBFrontendParametersTerrestrial::TransmissionMode_8k:
2308 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2311 case eDVBFrontendParametersTerrestrial::TransmissionMode_Auto:
2312 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2315 switch (feparm.guard_interval)
2317 case eDVBFrontendParametersTerrestrial::GuardInterval_1_32:
2318 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2320 case eDVBFrontendParametersTerrestrial::GuardInterval_1_16:
2321 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2323 case eDVBFrontendParametersTerrestrial::GuardInterval_1_8:
2324 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2326 case eDVBFrontendParametersTerrestrial::GuardInterval_1_4:
2327 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2330 case eDVBFrontendParametersTerrestrial::GuardInterval_Auto:
2331 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2334 switch (feparm.hierarchy)
2336 case eDVBFrontendParametersTerrestrial::Hierarchy_None:
2337 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2339 case eDVBFrontendParametersTerrestrial::Hierarchy_1:
2340 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2342 case eDVBFrontendParametersTerrestrial::Hierarchy_2:
2343 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2345 case eDVBFrontendParametersTerrestrial::Hierarchy_4:
2346 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2349 case eDVBFrontendParametersTerrestrial::Hierarchy_Auto:
2350 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2353 switch (feparm.inversion)
2355 case eDVBFrontendParametersTerrestrial::Inversion_On:
2356 parm_inversion = INVERSION_ON;
2358 case eDVBFrontendParametersTerrestrial::Inversion_Off:
2359 parm_inversion = INVERSION_OFF;
2362 case eDVBFrontendParametersTerrestrial::Inversion_Unknown:
2363 parm_inversion = INVERSION_AUTO;
2370 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2372 unsigned int timeout = 5000;
2373 eDebugNoSimulate("(%d)tune", m_dvbid);
2379 if (!m_sn && !m_simulate)
2381 eDebug("no frontend device opened... do not try to tune !!!");
2395 m_sec_sequence.clear();
2397 where.calcLockTimeout(timeout);
2403 eDVBFrontendParametersSatellite feparm;
2404 if (where.getDVBS(feparm))
2406 eDebug("no dvbs data!");
2410 if (m_rotor_mode != feparm.no_rotor_command_on_tune && !feparm.no_rotor_command_on_tune)
2412 eDVBFrontend *sec_fe = this;
2413 long tmp = m_data[LINKED_PREV_PTR];
2416 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
2417 sec_fe = linked_fe->m_frontend;
2418 sec_fe->getData(LINKED_NEXT_PTR, tmp);
2420 eDebug("(fe%d) reset diseqc after leave rotor mode!", m_dvbid);
2421 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
2423 m_rotor_mode = feparm.no_rotor_command_on_tune;
2425 m_sec->setRotorMoving(m_slotid, false);
2426 res=prepare_sat(feparm, timeout);
2434 eDVBFrontendParametersCable feparm;
2435 if (where.getDVBC(feparm))
2440 res=prepare_cable(feparm);
2444 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2445 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2450 eDVBFrontendParametersTerrestrial feparm;
2451 if (where.getDVBT(feparm))
2453 eDebug("no -T data");
2457 res=prepare_terrestrial(feparm);
2461 std::string enable_5V;
2462 char configStr[255];
2463 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2464 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2465 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2466 if (enable_5V == "True")
2467 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2469 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2470 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2476 m_sec_sequence.current() = m_sec_sequence.begin();
2480 m_tuneTimer->start(0,true);
2482 if (m_state != stateTuning)
2484 m_state = stateTuning;
2485 m_stateChanged(this);
2494 m_tuneTimer->stop();
2498 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2500 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2504 RESULT eDVBFrontend::setVoltage(int voltage)
2506 if (m_type == feCable)
2508 #if HAVE_DVB_API_VERSION < 3
2511 bool increased=false;
2512 fe_sec_voltage_t vlt;
2514 m_data[CUR_VOLTAGE]=voltage;
2518 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2519 vlt = SEC_VOLTAGE_OFF;
2522 #if HAVE_DVB_API_VERSION < 3
2523 vlt = SEC_VOLTAGE_13_5;
2529 vlt = SEC_VOLTAGE_13;
2532 #if HAVE_DVB_API_VERSION < 3
2533 vlt = SEC_VOLTAGE_18_5;
2539 vlt = SEC_VOLTAGE_18;
2546 #if HAVE_DVB_API_VERSION < 3
2547 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2549 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2550 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2551 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2555 RESULT eDVBFrontend::getState(int &state)
2561 RESULT eDVBFrontend::setTone(int t)
2563 if (m_type != feSatellite)
2565 #if HAVE_DVB_API_VERSION < 3
2568 fe_sec_tone_mode_t tone;
2577 tone = SEC_TONE_OFF;
2584 #if HAVE_DVB_API_VERSION < 3
2585 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2587 return ::ioctl(m_fd, FE_SET_TONE, tone);
2591 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2592 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2595 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2599 #if HAVE_DVB_API_VERSION < 3
2600 struct secCommand cmd;
2601 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2602 cmd.u.diseqc.cmdtype = diseqc.data[0];
2603 cmd.u.diseqc.addr = diseqc.data[1];
2604 cmd.u.diseqc.cmd = diseqc.data[2];
2605 cmd.u.diseqc.numParams = diseqc.len-3;
2606 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2607 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2609 struct dvb_diseqc_master_cmd cmd;
2610 memcpy(cmd.msg, diseqc.data, diseqc.len);
2611 cmd.msg_len = diseqc.len;
2612 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2618 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2619 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2621 RESULT eDVBFrontend::sendToneburst(int burst)
2625 #if HAVE_DVB_API_VERSION < 3
2626 secMiniCmd cmd = SEC_MINI_NONE;
2628 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2630 if ( burst == eDVBSatelliteDiseqcParameters::A )
2632 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2634 #if HAVE_DVB_API_VERSION < 3
2635 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2638 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2644 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2650 RESULT eDVBFrontend::setSecSequence(eSecCommandList &list)
2652 if (m_data[SATCR] != -1 && m_sec_sequence.current() != m_sec_sequence.end())
2653 m_sec_sequence.push_back(list);
2655 m_sec_sequence = list;
2659 RESULT eDVBFrontend::getData(int num, long &data)
2661 if ( num < NUM_DATA_ENTRIES )
2669 RESULT eDVBFrontend::setData(int num, long val)
2671 if ( num < NUM_DATA_ENTRIES )
2679 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2682 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2684 if (m_type == eDVBFrontend::feSatellite)
2687 eDVBFrontendParametersSatellite sat_parm;
2688 int ret = feparm->getDVBS(sat_parm);
2690 if (sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S2 && !m_can_handle_dvbs2)
2692 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2693 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S && m_can_handle_dvbs2)
2697 else if (m_type == eDVBFrontend::feCable)
2698 return 2; // more prio for cable frontends
2699 else if (m_type == eDVBFrontend::feTerrestrial)
2704 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2706 ePyObject Id, Descr, Enabled, IsDVBS2, frontendId;
2707 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 5)
2709 Id = PyTuple_GET_ITEM(obj, 0);
2710 Descr = PyTuple_GET_ITEM(obj, 1);
2711 Enabled = PyTuple_GET_ITEM(obj, 2);
2712 IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2713 frontendId = PyTuple_GET_ITEM(obj, 4);
2714 m_slotid = PyInt_AsLong(Id);
2715 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2) || !PyInt_Check(frontendId))
2717 strcpy(m_description, PyString_AS_STRING(Descr));
2718 if (PyInt_AsLong(frontendId) == -1 || PyInt_AsLong(frontendId) != m_dvbid) {
2719 // eDebugNoSimulate("skip slotinfo for slotid %d, descr %s",
2720 // m_slotid, m_description);
2723 m_enabled = Enabled == Py_True;
2724 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2725 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2726 !!strstr(m_description, "Alps BSBE2") ||
2727 !!strstr(m_description, "Alps -S") ||
2728 !!strstr(m_description, "BCM4501");
2729 m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2730 eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2731 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2734 PyErr_SetString(PyExc_StandardError,
2735 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");