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 #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;
513 eDebug("opening frontend %d", m_dvbid);
516 m_fd = ::open(m_filename, O_RDWR|O_NONBLOCK);
519 eWarning("failed! (%s) %m", m_filename);
522 #ifdef BUILD_VUPLUS /* ikseong */
533 eWarning("frontend %d already opened", m_dvbid);
536 if (::ioctl(m_fd, FE_GET_INFO, &fe_info) < 0)
538 eWarning("ioctl FE_GET_INFO failed");
544 switch (fe_info.type)
547 m_type = iDVBFrontend::feSatellite;
550 m_type = iDVBFrontend::feCable;
553 m_type = iDVBFrontend::feTerrestrial;
556 eWarning("unknown frontend type.");
562 m_simulate_fe->m_type = m_type;
563 eDebugNoSimulate("detected %s frontend", "satellite\0cable\0 terrestrial"+fe_info.type*10);
566 #if HAVE_DVB_API_VERSION < 3
567 if (m_type == iDVBFrontend::feSatellite)
573 m_secfd = ::open(m_sec_filename, O_RDWR);
576 eWarning("failed! (%s) %m", m_sec_filename);
584 eWarning("sec %d already opened", m_dvbid);
588 m_sn = eSocketNotifier::create(eApp, m_fd, eSocketNotifier::Read, false);
589 CONNECT(m_sn->activated, eDVBFrontend::feEvent);
592 setTone(iDVBFrontend::toneOff);
593 setVoltage(iDVBFrontend::voltageOff);
598 int eDVBFrontend::closeFrontend(bool force, bool no_delayed)
600 if (!force && m_data[CUR_VOLTAGE] != -1 && m_data[CUR_VOLTAGE] != iDVBFrontend::voltageOff)
602 long tmp = m_data[LINKED_NEXT_PTR];
605 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
606 if (linked_fe->m_inuse)
608 eDebugNoSimulate("dont close frontend %d until the linked frontend %d in slot %d is still in use",
609 m_dvbid, linked_fe->m_frontend->getDVBID(), linked_fe->m_frontend->getSlotID());
612 linked_fe->m_frontend->getData(LINKED_NEXT_PTR, tmp);
618 eDebugNoSimulate("close frontend %d", m_dvbid);
619 if (m_data[SATCR] != -1)
623 m_sec->prepareTurnOffSatCR(*this, m_data[SATCR]);
624 m_tuneTimer->start(0, true);
625 if(!m_tuneTimer->isActive())
628 eDebug("[turnOffSatCR] no mainloop");
631 timeout = tuneLoopInt();
634 usleep(timeout*1000); // blockierendes wait.. eTimer gibts ja nicht mehr
638 eDebug("[turnOffSatCR] running mainloop");
642 m_data[ROTOR_CMD] = -1;
645 setTone(iDVBFrontend::toneOff);
646 setVoltage(iDVBFrontend::voltageOff);
649 if (m_sec && !m_simulate)
650 m_sec->setRotorMoving(m_slotid, false);
654 eWarning("couldnt close frontend %d", m_dvbid);
658 setTone(iDVBFrontend::toneOff);
659 setVoltage(iDVBFrontend::voltageOff);
661 #if HAVE_DVB_API_VERSION < 3
664 if (!::close(m_secfd))
667 eWarning("couldnt close sec %d", m_dvbid);
671 m_state = stateClosed;
676 eDVBFrontend::~eDVBFrontend()
678 m_data[LINKED_PREV_PTR] = m_data[LINKED_NEXT_PTR] = -1;
682 void eDVBFrontend::feEvent(int w)
684 eDVBFrontend *sec_fe = this;
685 long tmp = m_data[LINKED_PREV_PTR];
688 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
689 sec_fe = linked_fe->m_frontend;
690 sec_fe->getData(LINKED_NEXT_PTR, tmp);
694 #if HAVE_DVB_API_VERSION < 3
697 dvb_frontend_event event;
701 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
703 if (res && (errno == EAGAIN))
709 #if HAVE_DVB_API_VERSION < 3
710 if (event.type == FE_COMPLETION_EV)
712 eDebug("(%d)fe event: status %x, inversion %s, m_tuning %d", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off", m_tuning);
713 if (event.status & FE_HAS_LOCK)
721 #if HAVE_DVB_API_VERSION >= 3
722 if (event.status & FE_TIMEDOUT) {
723 eDebug("FE_TIMEDOUT! ..abort");
736 eDebug("stateLostLock");
737 state = stateLostLock;
739 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
742 if (m_state != state)
745 m_stateChanged(this);
750 void eDVBFrontend::timeout()
753 if (m_state == stateTuning)
755 #ifdef BUILD_VUPLUS /* ikseong */
756 eDVBFrontend *sec_fe = this;
757 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
759 m_state = stateFailed;
760 m_stateChanged(this);
764 #define INRANGE(X,Y,Z) (((X<=Y) && (Y<=Z))||((Z<=Y) && (Y<=X)) ? 1 : 0)
766 /* unsigned 32 bit division */
767 static inline uint32_t fe_udiv(uint32_t a, uint32_t b)
769 return (a + b / 2) / b;
772 int eDVBFrontend::readFrontendData(int type)
781 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
782 eDebug("FE_READ_BER failed (%m)");
787 case signalQualitydB: /* this will move into the driver */
789 int sat_max = 1600; // for stv0288 / bsbe2
790 int ret = 0x12345678;
794 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
795 eDebug("FE_READ_SNR failed (%m)");
796 else if (!strcmp(m_description, "BCM4501 (internal)"))
798 float SDS_SNRE = snr << 16;
801 if (oparm.sat.system == eDVBFrontendParametersSatellite::System_DVB_S) // DVB-S1 / QPSK
803 static float SNR_COEFF[6] = {
806 197418.0 / 4194304.0,
807 -2602183.0 / 4194304.0,
808 20377212.0 / 4194304.0,
809 -37791203.0 / 4194304.0,
811 float fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0)),
812 fval2 = pow(10.0, fval1)-1;
813 fval1 = 10.0 * log10(fval2);
817 fval2 = SNR_COEFF[0];
818 for (int i=1; i<6; ++i)
821 fval2 += SNR_COEFF[i];
827 #if HAVE_DVB_API_VERSION >= 3
830 float fval1 = SDS_SNRE / 268435456.0,
833 if (oparm.sat.modulation == eDVBFrontendParametersSatellite::Modulation_QPSK)
844 fval4 = -10.0 * log10(fval1);
846 for (int i=0; i < 5; ++i)
847 fval1 = fval4 - fval2 * log10(1.0+pow(10.0, (fval3-fval1)/fval2));
852 ret = (int)(snr_in_db * 100);
854 else if (strstr(m_description, "Alps BSBE1 C01A") ||
855 strstr(m_description, "Alps -S(STV0288)"))
859 else if (snr == 0xFFFF) // i think this should not happen
863 enum { REALVAL, REGVAL };
864 const long CN_lookup[31][2] = {
865 {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
866 {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
867 {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
868 {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
869 {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
870 {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
873 int add=strchr(m_description, '.') ? 0xA250 : 0xA100;
874 long regval = 0xFFFF - ((snr / 3) + add), // revert some dvb api calulations to get the real register value
878 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
883 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[i][REGVAL]))
888 ret = (((regval - CN_lookup[Imin][REGVAL])
889 * (CN_lookup[Imax][REALVAL] - CN_lookup[Imin][REALVAL])
890 / (CN_lookup[Imax][REGVAL] - CN_lookup[Imin][REGVAL]))
891 + CN_lookup[Imin][REALVAL]) * 10;
897 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
898 !strcmp(m_description, "Alps -S") ||
899 !strcmp(m_description, "Philips -S") ||
900 !strcmp(m_description, "LG -S") )
903 ret = (int)((snr-39075)/17.647);
904 } else if (!strcmp(m_description, "Alps BSBE2"))
906 ret = (int)((snr >> 7) * 10);
907 } else if (!strcmp(m_description, "Philips CU1216Mk3"))
909 int mse = (~snr) & 0xFF;
910 switch (parm_u_qam_modulation) {
911 case QAM_16: ret = fe_udiv(1950000, (32 * mse) + 138) + 1000; break;
912 case QAM_32: ret = fe_udiv(2150000, (40 * mse) + 500) + 1350; break;
913 case QAM_64: ret = fe_udiv(2100000, (40 * mse) + 500) + 1250; break;
914 case QAM_128: ret = fe_udiv(1850000, (38 * mse) + 400) + 1380; break;
915 case QAM_256: ret = fe_udiv(1800000, (100 * mse) + 40) + 2030; break;
918 } else if (!strcmp(m_description, "Philips TU1216"))
920 snr = 0xFF - (snr & 0xFF);
922 ret = 10 * (int)(-100 * (log10(snr) - log10(255)));
924 else if (strstr(m_description, "BCM4506") || strstr(m_description, "BCM4505"))
925 ret = (snr * 100) >> 8;
926 else if (!strcmp(m_description, "CXD1981"))
928 int mse = (~snr) & 0xFF;
929 switch (parm_u_qam_modulation) {
932 case QAM_256: ret = (int)(-950 * log(((double)mse) / 760)); break;
934 case QAM_128: ret = (int)(-875 * log(((double)mse) / 650)); break;
940 if (type == signalQuality)
942 if (ret == 0x12345678) // no snr db calculation avail.. return untouched snr value..
947 return ret >= sat_max ? 65536 : ret * 65536 / sat_max;
948 case feCable: // we assume a max of 42db here
949 return ret >= 4200 ? 65536 : ret * 65536 / 4200;
950 case feTerrestrial: // we assume a max of 24db here
951 return ret >= 2400 ? 65536 : ret * 65536 / 2400;
955 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
963 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
964 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
970 #if HAVE_DVB_API_VERSION < 3
971 FrontendStatus status=0;
977 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
978 eDebug("FE_READ_STATUS failed (%m)");
979 return !!(status&FE_HAS_LOCK);
985 #if HAVE_DVB_API_VERSION < 3
986 FrontendStatus status=0;
992 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
993 eDebug("FE_READ_STATUS failed (%m)");
994 return !!(status&FE_HAS_SYNC);
1004 void PutToDict(ePyObject &dict, const char*key, long value)
1006 ePyObject item = PyInt_FromLong(value);
1009 if (PyDict_SetItemString(dict, key, item))
1010 eDebug("put %s to dict failed", key);
1014 eDebug("could not create PyObject for %s", key);
1017 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
1021 if (PyDict_SetItemString(dict, key, item))
1022 eDebug("put %s to dict failed", key);
1026 eDebug("invalid PyObject for %s", key);
1029 void PutToDict(ePyObject &dict, const char*key, const char *value)
1031 ePyObject item = PyString_FromString(value);
1034 if (PyDict_SetItemString(dict, key, item))
1035 eDebug("put %s to dict failed", key);
1039 eDebug("could not create PyObject for %s", key);
1042 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
1044 PutToDict(dict, "tuner_type", "DVB-S");
1045 PutToDict(dict, "frequency", feparm.frequency);
1046 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
1047 PutToDict(dict, "orbital_position", feparm.orbital_position);
1048 PutToDict(dict, "inversion", feparm.inversion);
1049 PutToDict(dict, "fec_inner", feparm.fec);
1050 PutToDict(dict, "modulation", feparm.modulation);
1051 PutToDict(dict, "polarization", feparm.polarisation);
1052 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S2)
1054 PutToDict(dict, "rolloff", feparm.rolloff);
1055 PutToDict(dict, "pilot", feparm.pilot);
1057 PutToDict(dict, "system", feparm.system);
1060 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
1062 PutToDict(dict, "tuner_type", "DVB-T");
1063 PutToDict(dict, "frequency", feparm.frequency);
1064 PutToDict(dict, "bandwidth", feparm.bandwidth);
1065 PutToDict(dict, "code_rate_lp", feparm.code_rate_LP);
1066 PutToDict(dict, "code_rate_hp", feparm.code_rate_HP);
1067 PutToDict(dict, "constellation", feparm.modulation);
1068 PutToDict(dict, "transmission_mode", feparm.transmission_mode);
1069 PutToDict(dict, "guard_interval", feparm.guard_interval);
1070 PutToDict(dict, "hierarchy_information", feparm.hierarchy);
1071 PutToDict(dict, "inversion", feparm.inversion);
1074 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
1076 PutToDict(dict, "tuner_type", "DVB-C");
1077 PutToDict(dict, "frequency", feparm.frequency);
1078 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
1079 PutToDict(dict, "modulation", feparm.modulation);
1080 PutToDict(dict, "inversion", feparm.inversion);
1081 PutToDict(dict, "fec_inner", feparm.fec_inner);
1084 #if HAVE_DVB_API_VERSION >= 5
1085 static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, struct dtv_property *p, long freq_offset, int orb_pos, int polarization)
1088 int frequency = parm_frequency + freq_offset;
1089 PutToDict(dict, "frequency", frequency);
1090 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
1091 PutToDict(dict, "orbital_position", orb_pos);
1092 PutToDict(dict, "polarization", polarization);
1094 switch(parm_u_qpsk_fec_inner)
1096 case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1097 case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1098 case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1099 case FEC_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
1100 case FEC_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
1101 case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1102 case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1103 case FEC_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
1104 case FEC_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1105 case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
1106 case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
1107 default: eDebug("got unsupported FEC from frontend! report as FEC_AUTO!\n");
1109 PutToDict(dict, "fec_inner", tmp);
1111 switch (p[0].u.data)
1113 default: eDebug("got unsupported system from frontend! report as DVBS!");
1114 case SYS_DVBS: tmp = eDVBFrontendParametersSatellite::System_DVB_S; break;
1117 switch (p[2].u.data)
1119 default: eDebug("got unsupported rolloff from frontend! report as 0_20!");
1120 case ROLLOFF_20: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1121 case ROLLOFF_25: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1122 case ROLLOFF_35: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1124 PutToDict(dict, "rolloff", tmp);
1126 switch (p[3].u.data)
1128 case PILOT_OFF: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1129 case PILOT_ON: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1130 case PILOT_AUTO: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1132 PutToDict(dict, "pilot", tmp);
1134 tmp = eDVBFrontendParametersSatellite::System_DVB_S2; break;
1137 PutToDict(dict, "system", tmp);
1139 switch (p[1].u.data)
1141 default: eDebug("got unsupported modulation from frontend! report as QPSK!");
1142 case QPSK: tmp = eDVBFrontendParametersSatellite::Modulation_QPSK; break;
1143 case PSK_8: tmp = eDVBFrontendParametersSatellite::Modulation_8PSK; break;
1145 PutToDict(dict, "modulation", tmp);
1149 static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, long freq_offset, int orb_pos, int polarization)
1152 int frequency = parm_frequency + freq_offset;
1153 PutToDict(dict, "frequency", frequency);
1154 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
1155 PutToDict(dict, "orbital_position", orb_pos);
1156 PutToDict(dict, "polarization", polarization);
1158 switch((int)parm_u_qpsk_fec_inner)
1160 case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1161 case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1162 case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1163 case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1164 case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1165 case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
1167 case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
1168 #if HAVE_DVB_API_VERSION >=3
1169 case FEC_S2_8PSK_1_2:
1170 case FEC_S2_QPSK_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1171 case FEC_S2_8PSK_2_3:
1172 case FEC_S2_QPSK_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1173 case FEC_S2_8PSK_3_4:
1174 case FEC_S2_QPSK_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1175 case FEC_S2_8PSK_5_6:
1176 case FEC_S2_QPSK_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1177 case FEC_S2_8PSK_7_8:
1178 case FEC_S2_QPSK_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1179 case FEC_S2_8PSK_8_9:
1180 case FEC_S2_QPSK_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
1181 case FEC_S2_8PSK_3_5:
1182 case FEC_S2_QPSK_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
1183 case FEC_S2_8PSK_4_5:
1184 case FEC_S2_QPSK_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
1185 case FEC_S2_8PSK_9_10:
1186 case FEC_S2_QPSK_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1189 PutToDict(dict, "fec_inner", tmp);
1190 #if HAVE_DVB_API_VERSION >=3
1191 PutToDict(dict, "modulation",
1192 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ?
1193 eDVBFrontendParametersSatellite::Modulation_8PSK :
1194 eDVBFrontendParametersSatellite::Modulation_QPSK );
1195 if (parm_u_qpsk_fec_inner > FEC_AUTO)
1197 switch(parm_inversion & 0xc)
1199 default: // unknown rolloff
1200 case 0: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1201 case 4: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1202 case 8: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1204 PutToDict(dict, "rolloff", tmp);
1205 switch(parm_inversion & 0x30)
1207 case 0: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1208 case 0x10: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1209 case 0x20: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1211 PutToDict(dict, "pilot", tmp);
1212 tmp = eDVBFrontendParametersSatellite::System_DVB_S2;
1215 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1217 PutToDict(dict, "modulation", eDVBFrontendParametersSatellite::Modulation_QPSK );
1218 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1220 PutToDict(dict, "system", tmp);
1224 static void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1227 #if HAVE_DVB_API_VERSION < 3
1228 PutToDict(dict, "frequency", parm_frequency);
1230 PutToDict(dict, "frequency", parm_frequency/1000);
1232 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1233 switch(parm_u_qam_fec_inner)
1235 case FEC_NONE: tmp = eDVBFrontendParametersCable::FEC_None; break;
1236 case FEC_1_2: tmp = eDVBFrontendParametersCable::FEC_1_2; break;
1237 case FEC_2_3: tmp = eDVBFrontendParametersCable::FEC_2_3; break;
1238 case FEC_3_4: tmp = eDVBFrontendParametersCable::FEC_3_4; break;
1239 case FEC_5_6: tmp = eDVBFrontendParametersCable::FEC_5_6; break;
1240 case FEC_7_8: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1241 #if HAVE_DVB_API_VERSION >= 3
1242 case FEC_8_9: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1245 case FEC_AUTO: tmp = eDVBFrontendParametersCable::FEC_Auto; break;
1247 PutToDict(dict, "fec_inner", tmp);
1248 switch(parm_u_qam_modulation)
1250 case QAM_16: tmp = eDVBFrontendParametersCable::Modulation_QAM16; break;
1251 case QAM_32: tmp = eDVBFrontendParametersCable::Modulation_QAM32; break;
1252 case QAM_64: tmp = eDVBFrontendParametersCable::Modulation_QAM64; break;
1253 case QAM_128: tmp = eDVBFrontendParametersCable::Modulation_QAM128; break;
1254 case QAM_256: tmp = eDVBFrontendParametersCable::Modulation_QAM256; break;
1256 case QAM_AUTO: tmp = eDVBFrontendParametersCable::Modulation_Auto; break;
1258 PutToDict(dict, "modulation", tmp);
1261 static void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1264 PutToDict(dict, "frequency", parm_frequency);
1265 switch (parm_u_ofdm_bandwidth)
1267 case BANDWIDTH_8_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_8MHz; break;
1268 case BANDWIDTH_7_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_7MHz; break;
1269 case BANDWIDTH_6_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_6MHz; break;
1271 case BANDWIDTH_AUTO: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_Auto; break;
1273 PutToDict(dict, "bandwidth", tmp);
1274 switch (parm_u_ofdm_code_rate_LP)
1276 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1277 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1278 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1279 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1280 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1282 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1284 PutToDict(dict, "code_rate_lp", tmp);
1285 switch (parm_u_ofdm_code_rate_HP)
1287 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1288 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1289 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1290 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1291 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1293 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1295 PutToDict(dict, "code_rate_hp", tmp);
1296 switch (parm_u_ofdm_constellation)
1298 case QPSK: tmp = eDVBFrontendParametersTerrestrial::Modulation_QPSK; break;
1299 case QAM_16: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM16; break;
1300 case QAM_64: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM64; break;
1302 case QAM_AUTO: tmp = eDVBFrontendParametersTerrestrial::Modulation_Auto; break;
1304 PutToDict(dict, "constellation", tmp);
1305 switch (parm_u_ofdm_transmission_mode)
1307 case TRANSMISSION_MODE_2K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_2k; break;
1308 case TRANSMISSION_MODE_8K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_8k; break;
1310 case TRANSMISSION_MODE_AUTO: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto; break;
1312 PutToDict(dict, "transmission_mode", tmp);
1313 switch (parm_u_ofdm_guard_interval)
1315 case GUARD_INTERVAL_1_32: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_32; break;
1316 case GUARD_INTERVAL_1_16: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_16; break;
1317 case GUARD_INTERVAL_1_8: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_8; break;
1318 case GUARD_INTERVAL_1_4: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_4; break;
1320 case GUARD_INTERVAL_AUTO: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_Auto; break;
1322 PutToDict(dict, "guard_interval", tmp);
1323 switch (parm_u_ofdm_hierarchy_information)
1325 case HIERARCHY_NONE: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_None; break;
1326 case HIERARCHY_1: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_1; break;
1327 case HIERARCHY_2: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_2; break;
1328 case HIERARCHY_4: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_4; break;
1330 case HIERARCHY_AUTO: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_Auto; break;
1332 PutToDict(dict, "hierarchy_information", tmp);
1335 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1337 if (dest && PyDict_Check(dest))
1339 const char *tmp = "UNKNOWN";
1360 PutToDict(dest, "tuner_state", tmp);
1361 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1362 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1363 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1364 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1365 int sigQualitydB = readFrontendData(signalQualitydB);
1366 if (sigQualitydB == 0x12345678) // not support yet
1368 ePyObject obj=Py_None;
1370 PutToDict(dest, "tuner_signal_quality_db", obj);
1373 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1374 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1378 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1380 if (dest && PyDict_Check(dest))
1382 FRONTENDPARAMETERS front;
1383 #if HAVE_DVB_API_VERSION >= 5
1384 struct dtv_property p[4];
1385 struct dtv_properties cmdseq;
1388 p[0].cmd = DTV_DELIVERY_SYSTEM;
1389 p[1].cmd = DTV_MODULATION;
1390 p[2].cmd = DTV_ROLLOFF;
1391 p[3].cmd = DTV_PILOT;
1393 if (m_simulate || m_fd == -1 || original)
1395 #if HAVE_DVB_API_VERSION >= 5
1396 else if (m_type == feSatellite && // yet just use new api for DVB-S(2) only
1397 ioctl(m_fd, FE_GET_PROPERTY, &cmdseq)<0)
1399 eDebug("FE_GET_PROPERTY failed (%m)");
1403 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1405 eDebug("FE_GET_FRONTEND failed (%m)");
1413 PutSatelliteDataToDict(dest, oparm.sat);
1416 PutCableDataToDict(dest, oparm.cab);
1419 PutTerrestrialDataToDict(dest, oparm.ter);
1425 FRONTENDPARAMETERS &parm = front;
1426 long tmp = eDVBFrontendParametersSatellite::Inversion_Unknown;
1427 switch(parm_inversion & 3)
1430 tmp = eDVBFrontendParametersSatellite::Inversion_On;
1433 tmp = eDVBFrontendParametersSatellite::Inversion_Off;
1437 PutToDict(dest, "inversion", tmp);
1441 #if HAVE_DVB_API_VERSION >= 5
1442 fillDictWithSatelliteData(dest, parm, p, m_data[FREQ_OFFSET], oparm.sat.orbital_position, oparm.sat.polarisation);
1444 fillDictWithSatelliteData(dest, parm, m_data[FREQ_OFFSET], oparm.sat.orbital_position, oparm.sat.polarisation);
1448 fillDictWithCableData(dest, parm);
1451 fillDictWithTerrestrialData(dest, parm);
1458 void eDVBFrontend::getFrontendData(ePyObject dest)
1460 if (dest && PyDict_Check(dest))
1463 PutToDict(dest, "tuner_number", m_slotid);
1479 PutToDict(dest, "tuner_type", tmp);
1483 #ifndef FP_IOCTL_GET_ID
1484 #define FP_IOCTL_GET_ID 0
1486 int eDVBFrontend::readInputpower()
1490 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1492 char proc_name2[64];
1493 sprintf(proc_name, "/proc/stb/frontend/%d/lnb_sense", m_slotid);
1494 sprintf(proc_name2, "/proc/stb/fp/lnb_sense%d", m_slotid);
1496 if ((f=fopen(proc_name, "r")) || (f=fopen(proc_name2, "r")))
1498 if (fscanf(f, "%d", &power) != 1)
1499 eDebug("read %s failed!! (%m)", proc_name);
1501 eDebug("%s is %d\n", proc_name, power);
1506 // open front prozessor
1507 int fp=::open("/dev/dbox/fp0", O_RDWR);
1510 eDebug("couldn't open fp");
1513 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1514 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1516 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1525 bool eDVBFrontend::setSecSequencePos(int steps)
1527 eDebugNoSimulate("set sequence pos %d", steps);
1532 if (m_sec_sequence.current() != m_sec_sequence.end())
1533 ++m_sec_sequence.current();
1538 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1539 --m_sec_sequence.current();
1545 void eDVBFrontend::tuneLoop()
1550 int eDVBFrontend::tuneLoopInt() // called by m_tuneTimer
1553 eDVBFrontend *sec_fe = this;
1554 eDVBRegisteredFrontend *regFE = 0;
1555 long tmp = m_data[LINKED_PREV_PTR];
1558 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1559 sec_fe = prev->m_frontend;
1560 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1561 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1562 int state = sec_fe->m_state;
1563 // workaround to put the kernel frontend thread into idle state!
1564 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1566 sec_fe->closeFrontend(true);
1567 state = sec_fe->m_state;
1569 // sec_fe is closed... we must reopen it here..
1570 if (state == stateClosed)
1578 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1580 long *sec_fe_data = sec_fe->m_data;
1581 // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1583 switch (m_sec_sequence.current()->cmd)
1585 case eSecCommand::SLEEP:
1586 delay = m_sec_sequence.current()++->msec;
1587 eDebugNoSimulate("[SEC] sleep %dms", delay);
1589 case eSecCommand::GOTO:
1590 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1591 ++m_sec_sequence.current();
1593 case eSecCommand::SET_VOLTAGE:
1595 int voltage = m_sec_sequence.current()++->voltage;
1596 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1597 sec_fe->setVoltage(voltage);
1600 case eSecCommand::IF_VOLTAGE_GOTO:
1602 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1603 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1605 ++m_sec_sequence.current();
1608 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1610 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1611 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1613 ++m_sec_sequence.current();
1616 case eSecCommand::IF_TONE_GOTO:
1618 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1619 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1621 ++m_sec_sequence.current();
1624 case eSecCommand::IF_NOT_TONE_GOTO:
1626 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1627 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1629 ++m_sec_sequence.current();
1632 case eSecCommand::SET_TONE:
1633 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1634 sec_fe->setTone(m_sec_sequence.current()++->tone);
1636 case eSecCommand::SEND_DISEQC:
1637 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1638 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1639 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1640 eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1641 if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
1642 eDebugNoSimulate("(DiSEqC reset)");
1643 else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
1644 eDebugNoSimulate("(DiSEqC peripherial power on)");
1646 eDebugNoSimulate("");
1647 ++m_sec_sequence.current();
1649 case eSecCommand::SEND_TONEBURST:
1650 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1651 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1653 case eSecCommand::SET_FRONTEND:
1655 int enableEvents = (m_sec_sequence.current()++)->val;
1656 eDebugNoSimulate("[SEC] setFrontend %d", enableEvents);
1657 setFrontend(enableEvents);
1660 case eSecCommand::START_TUNE_TIMEOUT:
1662 int tuneTimeout = m_sec_sequence.current()->timeout;
1663 eDebugNoSimulate("[SEC] startTuneTimeout %d", tuneTimeout);
1665 m_timeout->start(tuneTimeout, 1);
1666 ++m_sec_sequence.current();
1669 case eSecCommand::SET_TIMEOUT:
1670 m_timeoutCount = m_sec_sequence.current()++->val;
1671 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1673 case eSecCommand::IF_TIMEOUT_GOTO:
1674 if (!m_timeoutCount)
1676 eDebugNoSimulate("[SEC] rotor timout");
1677 setSecSequencePos(m_sec_sequence.current()->steps);
1680 ++m_sec_sequence.current();
1682 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1684 int idx = m_sec_sequence.current()++->val;
1685 if ( idx == 0 || idx == 1 )
1687 m_idleInputpower[idx] = sec_fe->readInputpower();
1688 eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1691 eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1694 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1696 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1697 int idx = compare.val;
1698 if ( !m_simulate && (idx == 0 || idx == 1) )
1700 int idle = sec_fe->readInputpower();
1701 int diff = abs(idle-m_idleInputpower[idx]);
1704 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1705 setSecSequencePos(compare.steps);
1709 ++m_sec_sequence.current();
1712 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1714 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1717 setSecSequencePos(cmd.steps);
1721 int isLocked = readFrontendData(locked);
1722 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1724 if (!m_timeoutCount && m_retryCount > 0)
1726 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 40) || !cmd.lastSignal))
1729 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1732 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1734 cmd.lastSignal = signal;
1737 if (cmd.okcount > 4)
1739 eDebugNoSimulate("ok > 4 .. goto %d\n", cmd.steps);
1740 setSecSequencePos(cmd.steps);
1741 m_state = stateLock;
1742 m_stateChanged(this);
1743 feEvent(-1); // flush events
1751 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1753 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1757 ++m_sec_sequence.current();
1760 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1761 m_runningInputpower = sec_fe->readInputpower();
1762 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1763 ++m_sec_sequence.current();
1765 case eSecCommand::SET_ROTOR_MOVING:
1767 m_sec->setRotorMoving(m_slotid, true);
1768 ++m_sec_sequence.current();
1770 case eSecCommand::SET_ROTOR_STOPPED:
1772 m_sec->setRotorMoving(m_slotid, false);
1773 ++m_sec_sequence.current();
1775 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1777 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1780 setSecSequencePos(cmd.steps);
1783 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1784 const char *txt = cmd.direction ? "running" : "stopped";
1786 if (!m_timeoutCount && m_retryCount > 0)
1788 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1790 m_runningInputpower,
1793 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1794 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1797 eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1798 if ( cmd.okcount > 6 )
1800 eDebugNoSimulate("[SEC] rotor is %s", txt);
1801 if (setSecSequencePos(cmd.steps))
1807 eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1810 ++m_sec_sequence.current();
1813 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1814 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1815 setSecSequencePos(m_sec_sequence.current()->steps);
1817 ++m_sec_sequence.current();
1819 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1820 eDebugNoSimulate("[SEC] invalidate current switch params");
1821 sec_fe_data[CSW] = -1;
1822 sec_fe_data[UCSW] = -1;
1823 sec_fe_data[TONEBURST] = -1;
1824 ++m_sec_sequence.current();
1826 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1827 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1828 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1829 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1830 eDebugNoSimulate("[SEC] update current switch params");
1831 ++m_sec_sequence.current();
1833 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1834 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1835 sec_fe_data[ROTOR_CMD] = -1;
1836 sec_fe_data[ROTOR_POS] = -1;
1837 ++m_sec_sequence.current();
1839 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1840 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1841 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1842 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1843 ++m_sec_sequence.current();
1845 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1846 m_retryCount = m_sec_sequence.current()++->val;
1847 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1849 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1852 eDebugNoSimulate("[SEC] no more rotor retrys");
1853 setSecSequencePos(m_sec_sequence.current()->steps);
1856 ++m_sec_sequence.current();
1858 case eSecCommand::SET_POWER_LIMITING_MODE:
1863 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1864 FILE *f=fopen(proc_name, "w");
1865 if (f) // new interface exist?
1867 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1868 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1869 eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1871 eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1874 else if (sec_fe->m_need_rotor_workaround)
1877 int slotid = sec_fe->m_slotid;
1878 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1880 sprintf(dev, "/dev/i2c-%d", slotid);
1881 else if (slotid == 2)
1882 sprintf(dev, "/dev/i2c-2"); // first nim socket on DM8000 use /dev/i2c-2
1883 else if (slotid == 3)
1884 sprintf(dev, "/dev/i2c-4"); // second nim socket on DM8000 use /dev/i2c-4
1885 int fd = ::open(dev, O_RDWR);
1887 unsigned char data[2];
1888 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1889 if(::read(fd, data, 1) != 1)
1890 eDebugNoSimulate("[SEC] error read lnbp (%m)");
1891 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1893 data[0] |= 0x80; // enable static current limiting
1894 eDebugNoSimulate("[SEC] set static current limiting");
1898 data[0] &= ~0x80; // enable dynamic current limiting
1899 eDebugNoSimulate("[SEC] set dynamic current limiting");
1901 if(::write(fd, data, 1) != 1)
1902 eDebugNoSimulate("[SEC] error write lnbp (%m)");
1906 ++m_sec_sequence.current();
1909 case eSecCommand::DELAYED_CLOSE_FRONTEND:
1911 eDebugNoSimulate("[SEC] delayed close frontend");
1912 closeFrontend(false, true);
1913 ++m_sec_sequence.current();
1917 eDebugNoSimulate("[SEC] unhandled sec command %d",
1918 ++m_sec_sequence.current()->cmd);
1919 ++m_sec_sequence.current();
1922 m_tuneTimer->start(delay,true);
1926 if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1931 void eDVBFrontend::setFrontend(bool recvEvents)
1935 eDebug("setting frontend %d", m_dvbid);
1938 feEvent(-1); // flush events
1939 #if HAVE_DVB_API_VERSION >= 5
1940 if (m_type == iDVBFrontend::feSatellite)
1942 fe_rolloff_t rolloff = ROLLOFF_35;
1943 fe_pilot_t pilot = PILOT_OFF;
1944 fe_modulation_t modulation = QPSK;
1945 fe_delivery_system_t system = SYS_DVBS;
1946 switch(oparm.sat.system)
1948 case eDVBFrontendParametersSatellite::System_DVB_S: system = SYS_DVBS; break;
1949 case eDVBFrontendParametersSatellite::System_DVB_S2: system = SYS_DVBS2; break;
1951 switch(oparm.sat.modulation)
1953 case eDVBFrontendParametersSatellite::Modulation_QPSK: modulation = QPSK; break;
1954 case eDVBFrontendParametersSatellite::Modulation_8PSK: modulation = PSK_8; break;
1955 case eDVBFrontendParametersSatellite::Modulation_QAM16: modulation = QAM_16; break;
1957 switch(oparm.sat.pilot)
1959 case eDVBFrontendParametersSatellite::Pilot_Off: pilot = PILOT_OFF; break;
1960 case eDVBFrontendParametersSatellite::Pilot_On: pilot = PILOT_ON; break;
1961 case eDVBFrontendParametersSatellite::Pilot_Unknown: pilot = PILOT_AUTO; break;
1963 switch(oparm.sat.rolloff)
1965 case eDVBFrontendParametersSatellite::RollOff_alpha_0_20: rolloff = ROLLOFF_20; break;
1966 case eDVBFrontendParametersSatellite::RollOff_alpha_0_25: rolloff = ROLLOFF_25; break;
1967 case eDVBFrontendParametersSatellite::RollOff_alpha_0_35: rolloff = ROLLOFF_35; break;
1969 struct dtv_property p[10];
1970 struct dtv_properties cmdseq;
1972 p[0].cmd = DTV_CLEAR;
1973 p[1].cmd = DTV_DELIVERY_SYSTEM, p[1].u.data = system;
1974 p[2].cmd = DTV_FREQUENCY, p[2].u.data = parm_frequency;
1975 p[3].cmd = DTV_MODULATION, p[3].u.data = modulation;
1976 p[4].cmd = DTV_SYMBOL_RATE, p[4].u.data = parm_u_qpsk_symbol_rate;
1977 p[5].cmd = DTV_INNER_FEC, p[5].u.data = parm_u_qpsk_fec_inner;
1978 p[6].cmd = DTV_INVERSION, p[6].u.data = parm_inversion;
1979 if (system == SYS_DVBS2)
1981 p[7].cmd = DTV_ROLLOFF, p[7].u.data = rolloff;
1982 p[8].cmd = DTV_PILOT, p[8].u.data = pilot;
1983 p[9].cmd = DTV_TUNE;
1988 p[7].cmd = DTV_TUNE;
1991 if (ioctl(m_fd, FE_SET_PROPERTY, &cmdseq) == -1)
1993 perror("FE_SET_PROPERTY failed");
2000 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
2002 perror("FE_SET_FRONTEND failed");
2009 RESULT eDVBFrontend::getFrontendType(int &t)
2017 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
2022 eWarning("no SEC module active!");
2025 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
2028 #if HAVE_DVB_API_VERSION >= 3
2029 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",
2032 feparm.polarisation,
2036 feparm.orbital_position,
2042 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
2045 feparm.polarisation,
2049 feparm.orbital_position);
2051 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
2052 switch (feparm.inversion)
2054 case eDVBFrontendParametersSatellite::Inversion_On:
2055 parm_inversion = INVERSION_ON;
2057 case eDVBFrontendParametersSatellite::Inversion_Off:
2058 parm_inversion = INVERSION_OFF;
2061 case eDVBFrontendParametersSatellite::Inversion_Unknown:
2062 parm_inversion = INVERSION_AUTO;
2065 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S)
2069 case eDVBFrontendParametersSatellite::FEC_None:
2070 parm_u_qpsk_fec_inner = FEC_NONE;
2072 case eDVBFrontendParametersSatellite::FEC_1_2:
2073 parm_u_qpsk_fec_inner = FEC_1_2;
2075 case eDVBFrontendParametersSatellite::FEC_2_3:
2076 parm_u_qpsk_fec_inner = FEC_2_3;
2078 case eDVBFrontendParametersSatellite::FEC_3_4:
2079 parm_u_qpsk_fec_inner = FEC_3_4;
2081 case eDVBFrontendParametersSatellite::FEC_5_6:
2082 parm_u_qpsk_fec_inner = FEC_5_6;
2084 case eDVBFrontendParametersSatellite::FEC_7_8:
2085 parm_u_qpsk_fec_inner = FEC_7_8;
2088 eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
2089 case eDVBFrontendParametersSatellite::FEC_Auto:
2090 parm_u_qpsk_fec_inner = FEC_AUTO;
2094 #if HAVE_DVB_API_VERSION >= 3
2099 case eDVBFrontendParametersSatellite::FEC_1_2:
2100 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
2102 case eDVBFrontendParametersSatellite::FEC_2_3:
2103 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
2105 case eDVBFrontendParametersSatellite::FEC_3_4:
2106 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
2108 case eDVBFrontendParametersSatellite::FEC_3_5:
2109 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
2111 case eDVBFrontendParametersSatellite::FEC_4_5:
2112 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
2114 case eDVBFrontendParametersSatellite::FEC_5_6:
2115 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
2117 case eDVBFrontendParametersSatellite::FEC_7_8:
2118 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
2120 case eDVBFrontendParametersSatellite::FEC_8_9:
2121 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
2123 case eDVBFrontendParametersSatellite::FEC_9_10:
2124 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
2127 eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
2130 #if HAVE_DVB_API_VERSION < 5
2131 parm_inversion = (fe_spectral_inversion_t)((feparm.rolloff << 2) | parm_inversion); // Hack.. we use bit 2..3 of inversion param for rolloff
2132 parm_inversion = (fe_spectral_inversion_t)((feparm.pilot << 4) | parm_inversion); // Hack.. we use bit 4..5 of inversion param for pilot
2133 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation_8PSK)
2135 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
2136 // 8PSK fec driver values are decimal 9 bigger
2141 // FIXME !!! get frequency range from tuner
2142 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
2144 eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
2147 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
2153 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
2155 #if HAVE_DVB_API_VERSION < 3
2156 parm_frequency = feparm.frequency;
2158 parm_frequency = feparm.frequency * 1000;
2160 parm_u_qam_symbol_rate = feparm.symbol_rate;
2161 switch (feparm.modulation)
2163 case eDVBFrontendParametersCable::Modulation_QAM16:
2164 parm_u_qam_modulation = QAM_16;
2166 case eDVBFrontendParametersCable::Modulation_QAM32:
2167 parm_u_qam_modulation = QAM_32;
2169 case eDVBFrontendParametersCable::Modulation_QAM64:
2170 parm_u_qam_modulation = QAM_64;
2172 case eDVBFrontendParametersCable::Modulation_QAM128:
2173 parm_u_qam_modulation = QAM_128;
2175 case eDVBFrontendParametersCable::Modulation_QAM256:
2176 parm_u_qam_modulation = QAM_256;
2179 case eDVBFrontendParametersCable::Modulation_Auto:
2180 parm_u_qam_modulation = QAM_AUTO;
2183 switch (feparm.inversion)
2185 case eDVBFrontendParametersCable::Inversion_On:
2186 parm_inversion = INVERSION_ON;
2188 case eDVBFrontendParametersCable::Inversion_Off:
2189 parm_inversion = INVERSION_OFF;
2192 case eDVBFrontendParametersCable::Inversion_Unknown:
2193 parm_inversion = INVERSION_AUTO;
2196 switch (feparm.fec_inner)
2198 case eDVBFrontendParametersCable::FEC_None:
2199 parm_u_qam_fec_inner = FEC_NONE;
2201 case eDVBFrontendParametersCable::FEC_1_2:
2202 parm_u_qam_fec_inner = FEC_1_2;
2204 case eDVBFrontendParametersCable::FEC_2_3:
2205 parm_u_qam_fec_inner = FEC_2_3;
2207 case eDVBFrontendParametersCable::FEC_3_4:
2208 parm_u_qam_fec_inner = FEC_3_4;
2210 case eDVBFrontendParametersCable::FEC_5_6:
2211 parm_u_qam_fec_inner = FEC_5_6;
2213 case eDVBFrontendParametersCable::FEC_7_8:
2214 parm_u_qam_fec_inner = FEC_7_8;
2216 #if HAVE_DVB_API_VERSION >= 3
2217 case eDVBFrontendParametersCable::FEC_8_9:
2218 parm_u_qam_fec_inner = FEC_8_9;
2222 case eDVBFrontendParametersCable::FEC_Auto:
2223 parm_u_qam_fec_inner = FEC_AUTO;
2226 eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
2227 parm_frequency/1000,
2228 parm_u_qam_symbol_rate,
2229 parm_u_qam_fec_inner,
2230 parm_u_qam_modulation,
2236 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
2238 parm_frequency = feparm.frequency;
2240 switch (feparm.bandwidth)
2242 case eDVBFrontendParametersTerrestrial::Bandwidth_8MHz:
2243 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
2245 case eDVBFrontendParametersTerrestrial::Bandwidth_7MHz:
2246 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
2248 case eDVBFrontendParametersTerrestrial::Bandwidth_6MHz:
2249 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
2252 case eDVBFrontendParametersTerrestrial::Bandwidth_Auto:
2253 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
2256 switch (feparm.code_rate_LP)
2258 case eDVBFrontendParametersTerrestrial::FEC_1_2:
2259 parm_u_ofdm_code_rate_LP = FEC_1_2;
2261 case eDVBFrontendParametersTerrestrial::FEC_2_3:
2262 parm_u_ofdm_code_rate_LP = FEC_2_3;
2264 case eDVBFrontendParametersTerrestrial::FEC_3_4:
2265 parm_u_ofdm_code_rate_LP = FEC_3_4;
2267 case eDVBFrontendParametersTerrestrial::FEC_5_6:
2268 parm_u_ofdm_code_rate_LP = FEC_5_6;
2270 case eDVBFrontendParametersTerrestrial::FEC_7_8:
2271 parm_u_ofdm_code_rate_LP = FEC_7_8;
2274 case eDVBFrontendParametersTerrestrial::FEC_Auto:
2275 parm_u_ofdm_code_rate_LP = FEC_AUTO;
2278 switch (feparm.code_rate_HP)
2280 case eDVBFrontendParametersTerrestrial::FEC_1_2:
2281 parm_u_ofdm_code_rate_HP = FEC_1_2;
2283 case eDVBFrontendParametersTerrestrial::FEC_2_3:
2284 parm_u_ofdm_code_rate_HP = FEC_2_3;
2286 case eDVBFrontendParametersTerrestrial::FEC_3_4:
2287 parm_u_ofdm_code_rate_HP = FEC_3_4;
2289 case eDVBFrontendParametersTerrestrial::FEC_5_6:
2290 parm_u_ofdm_code_rate_HP = FEC_5_6;
2292 case eDVBFrontendParametersTerrestrial::FEC_7_8:
2293 parm_u_ofdm_code_rate_HP = FEC_7_8;
2296 case eDVBFrontendParametersTerrestrial::FEC_Auto:
2297 parm_u_ofdm_code_rate_HP = FEC_AUTO;
2300 switch (feparm.modulation)
2302 case eDVBFrontendParametersTerrestrial::Modulation_QPSK:
2303 parm_u_ofdm_constellation = QPSK;
2305 case eDVBFrontendParametersTerrestrial::Modulation_QAM16:
2306 parm_u_ofdm_constellation = QAM_16;
2308 case eDVBFrontendParametersTerrestrial::Modulation_QAM64:
2309 parm_u_ofdm_constellation = QAM_64;
2312 case eDVBFrontendParametersTerrestrial::Modulation_Auto:
2313 parm_u_ofdm_constellation = QAM_AUTO;
2316 switch (feparm.transmission_mode)
2318 case eDVBFrontendParametersTerrestrial::TransmissionMode_2k:
2319 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2321 case eDVBFrontendParametersTerrestrial::TransmissionMode_8k:
2322 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2325 case eDVBFrontendParametersTerrestrial::TransmissionMode_Auto:
2326 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2329 switch (feparm.guard_interval)
2331 case eDVBFrontendParametersTerrestrial::GuardInterval_1_32:
2332 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2334 case eDVBFrontendParametersTerrestrial::GuardInterval_1_16:
2335 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2337 case eDVBFrontendParametersTerrestrial::GuardInterval_1_8:
2338 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2340 case eDVBFrontendParametersTerrestrial::GuardInterval_1_4:
2341 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2344 case eDVBFrontendParametersTerrestrial::GuardInterval_Auto:
2345 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2348 switch (feparm.hierarchy)
2350 case eDVBFrontendParametersTerrestrial::Hierarchy_None:
2351 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2353 case eDVBFrontendParametersTerrestrial::Hierarchy_1:
2354 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2356 case eDVBFrontendParametersTerrestrial::Hierarchy_2:
2357 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2359 case eDVBFrontendParametersTerrestrial::Hierarchy_4:
2360 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2363 case eDVBFrontendParametersTerrestrial::Hierarchy_Auto:
2364 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2367 switch (feparm.inversion)
2369 case eDVBFrontendParametersTerrestrial::Inversion_On:
2370 parm_inversion = INVERSION_ON;
2372 case eDVBFrontendParametersTerrestrial::Inversion_Off:
2373 parm_inversion = INVERSION_OFF;
2376 case eDVBFrontendParametersTerrestrial::Inversion_Unknown:
2377 parm_inversion = INVERSION_AUTO;
2384 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2386 unsigned int timeout = 5000;
2387 eDebugNoSimulate("(%d)tune", m_dvbid);
2393 if (!m_sn && !m_simulate)
2395 eDebug("no frontend device opened... do not try to tune !!!");
2409 m_sec_sequence.clear();
2411 where.calcLockTimeout(timeout);
2417 eDVBFrontendParametersSatellite feparm;
2418 if (where.getDVBS(feparm))
2420 eDebug("no dvbs data!");
2424 if (m_rotor_mode != feparm.no_rotor_command_on_tune && !feparm.no_rotor_command_on_tune)
2426 eDVBFrontend *sec_fe = this;
2427 long tmp = m_data[LINKED_PREV_PTR];
2430 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
2431 sec_fe = linked_fe->m_frontend;
2432 sec_fe->getData(LINKED_NEXT_PTR, tmp);
2434 eDebug("(fe%d) reset diseqc after leave rotor mode!", m_dvbid);
2435 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
2437 m_rotor_mode = feparm.no_rotor_command_on_tune;
2439 m_sec->setRotorMoving(m_slotid, false);
2440 res=prepare_sat(feparm, timeout);
2448 eDVBFrontendParametersCable feparm;
2449 if (where.getDVBC(feparm))
2454 res=prepare_cable(feparm);
2458 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2459 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2464 eDVBFrontendParametersTerrestrial feparm;
2465 if (where.getDVBT(feparm))
2467 eDebug("no -T data");
2471 res=prepare_terrestrial(feparm);
2475 std::string enable_5V;
2476 char configStr[255];
2477 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2478 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2479 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2480 if (enable_5V == "True")
2481 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2483 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2484 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2490 m_sec_sequence.current() = m_sec_sequence.begin();
2494 m_tuneTimer->start(0,true);
2496 if (m_state != stateTuning)
2498 m_state = stateTuning;
2499 m_stateChanged(this);
2508 m_tuneTimer->stop();
2512 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2514 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2518 RESULT eDVBFrontend::setVoltage(int voltage)
2520 if (m_type == feCable)
2522 #if HAVE_DVB_API_VERSION < 3
2525 bool increased=false;
2526 fe_sec_voltage_t vlt;
2528 m_data[CUR_VOLTAGE]=voltage;
2532 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2533 vlt = SEC_VOLTAGE_OFF;
2536 #if HAVE_DVB_API_VERSION < 3
2537 vlt = SEC_VOLTAGE_13_5;
2543 vlt = SEC_VOLTAGE_13;
2546 #if HAVE_DVB_API_VERSION < 3
2547 vlt = SEC_VOLTAGE_18_5;
2553 vlt = SEC_VOLTAGE_18;
2560 #if HAVE_DVB_API_VERSION < 3
2561 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2563 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2564 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2565 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2569 RESULT eDVBFrontend::getState(int &state)
2575 RESULT eDVBFrontend::setTone(int t)
2577 if (m_type != feSatellite)
2579 #if HAVE_DVB_API_VERSION < 3
2582 fe_sec_tone_mode_t tone;
2591 tone = SEC_TONE_OFF;
2598 #if HAVE_DVB_API_VERSION < 3
2599 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2601 return ::ioctl(m_fd, FE_SET_TONE, tone);
2605 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2606 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2609 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2613 #if HAVE_DVB_API_VERSION < 3
2614 struct secCommand cmd;
2615 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2616 cmd.u.diseqc.cmdtype = diseqc.data[0];
2617 cmd.u.diseqc.addr = diseqc.data[1];
2618 cmd.u.diseqc.cmd = diseqc.data[2];
2619 cmd.u.diseqc.numParams = diseqc.len-3;
2620 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2621 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2623 struct dvb_diseqc_master_cmd cmd;
2624 memcpy(cmd.msg, diseqc.data, diseqc.len);
2625 cmd.msg_len = diseqc.len;
2626 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2632 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2633 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2635 RESULT eDVBFrontend::sendToneburst(int burst)
2639 #if HAVE_DVB_API_VERSION < 3
2640 secMiniCmd cmd = SEC_MINI_NONE;
2642 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2644 if ( burst == eDVBSatelliteDiseqcParameters::A )
2646 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2648 #if HAVE_DVB_API_VERSION < 3
2649 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2652 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2658 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2664 RESULT eDVBFrontend::setSecSequence(eSecCommandList &list)
2666 if (m_data[SATCR] != -1 && m_sec_sequence.current() != m_sec_sequence.end())
2667 m_sec_sequence.push_back(list);
2669 m_sec_sequence = list;
2673 RESULT eDVBFrontend::getData(int num, long &data)
2675 if ( num < NUM_DATA_ENTRIES )
2683 RESULT eDVBFrontend::setData(int num, long val)
2685 if ( num < NUM_DATA_ENTRIES )
2693 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2696 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2698 if (m_type == eDVBFrontend::feSatellite)
2701 eDVBFrontendParametersSatellite sat_parm;
2702 int ret = feparm->getDVBS(sat_parm);
2704 if (sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S2 && !m_can_handle_dvbs2)
2706 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2707 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S && m_can_handle_dvbs2)
2711 else if (m_type == eDVBFrontend::feCable)
2712 return 2; // more prio for cable frontends
2713 else if (m_type == eDVBFrontend::feTerrestrial)
2718 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2720 ePyObject Id, Descr, Enabled, IsDVBS2, frontendId;
2721 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 5)
2723 Id = PyTuple_GET_ITEM(obj, 0);
2724 Descr = PyTuple_GET_ITEM(obj, 1);
2725 Enabled = PyTuple_GET_ITEM(obj, 2);
2726 IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2727 frontendId = PyTuple_GET_ITEM(obj, 4);
2728 m_slotid = PyInt_AsLong(Id);
2729 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2) || !PyInt_Check(frontendId))
2731 strcpy(m_description, PyString_AS_STRING(Descr));
2732 if (PyInt_AsLong(frontendId) == -1 || PyInt_AsLong(frontendId) != m_dvbid) {
2733 // eDebugNoSimulate("skip slotinfo for slotid %d, descr %s",
2734 // m_slotid, m_description);
2737 m_enabled = Enabled == Py_True;
2738 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2739 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2740 !!strstr(m_description, "Alps BSBE2") ||
2741 !!strstr(m_description, "Alps -S") ||
2742 !!strstr(m_description, "BCM4501");
2743 m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2744 eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2745 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2748 PyErr_SetString(PyExc_StandardError,
2749 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");