1 #include <lib/dvb/dvb.h>
2 #include <lib/base/eerror.h>
3 #include <lib/base/nconfig.h> // access to python config
9 #ifndef I2C_SLAVE_FORCE
10 #define I2C_SLAVE_FORCE 0x0706
13 #if HAVE_DVB_API_VERSION < 3
14 #include <ost/frontend.h>
16 #define QAM_AUTO (Modulation)6
17 #define TRANSMISSION_MODE_AUTO (TransmitMode)2
18 #define BANDWIDTH_AUTO (BandWidth)3
19 #define GUARD_INTERVAL_AUTO (GuardInterval)4
20 #define HIERARCHY_AUTO (Hierarchy)4
21 #define parm_frequency parm.Frequency
22 #define parm_inversion parm.Inversion
23 #define parm_u_qpsk_symbol_rate parm.u.qpsk.SymbolRate
24 #define parm_u_qpsk_fec_inner parm.u.qpsk.FEC_inner
25 #define parm_u_qam_symbol_rate parm.u.qam.SymbolRate
26 #define parm_u_qam_fec_inner parm.u.qam.FEC_inner
27 #define parm_u_qam_modulation parm.u.qam.QAM
28 #define parm_u_ofdm_bandwidth parm.u.ofdm.bandWidth
29 #define parm_u_ofdm_code_rate_LP parm.u.ofdm.LP_CodeRate
30 #define parm_u_ofdm_code_rate_HP parm.u.ofdm.HP_CodeRate
31 #define parm_u_ofdm_constellation parm.u.ofdm.Constellation
32 #define parm_u_ofdm_transmission_mode parm.u.ofdm.TransmissionMode
33 #define parm_u_ofdm_guard_interval parm.u.ofdm.guardInterval
34 #define parm_u_ofdm_hierarchy_information parm.u.ofdm.HierarchyInformation
36 #include <linux/dvb/frontend.h>
37 #define parm_frequency parm.frequency
38 #define parm_inversion parm.inversion
39 #define parm_u_qpsk_symbol_rate parm.u.qpsk.symbol_rate
40 #define parm_u_qpsk_fec_inner parm.u.qpsk.fec_inner
41 #define parm_u_qam_symbol_rate parm.u.qam.symbol_rate
42 #define parm_u_qam_fec_inner parm.u.qam.fec_inner
43 #define parm_u_qam_modulation parm.u.qam.modulation
44 #define parm_u_ofdm_bandwidth parm.u.ofdm.bandwidth
45 #define parm_u_ofdm_code_rate_LP parm.u.ofdm.code_rate_LP
46 #define parm_u_ofdm_code_rate_HP parm.u.ofdm.code_rate_HP
47 #define parm_u_ofdm_constellation parm.u.ofdm.constellation
48 #define parm_u_ofdm_transmission_mode parm.u.ofdm.transmission_mode
49 #define parm_u_ofdm_guard_interval parm.u.ofdm.guard_interval
50 #define parm_u_ofdm_hierarchy_information parm.u.ofdm.hierarchy_information
52 #warning "FEC_9_10 already exist in dvb api ... it seems it is now ready for DVB-S2"
54 #define FEC_S2_QPSK_1_2 (fe_code_rate_t)(FEC_AUTO+1)
55 #define FEC_S2_QPSK_2_3 (fe_code_rate_t)(FEC_S2_QPSK_1_2+1)
56 #define FEC_S2_QPSK_3_4 (fe_code_rate_t)(FEC_S2_QPSK_2_3+1)
57 #define FEC_S2_QPSK_5_6 (fe_code_rate_t)(FEC_S2_QPSK_3_4+1)
58 #define FEC_S2_QPSK_7_8 (fe_code_rate_t)(FEC_S2_QPSK_5_6+1)
59 #define FEC_S2_QPSK_8_9 (fe_code_rate_t)(FEC_S2_QPSK_7_8+1)
60 #define FEC_S2_QPSK_3_5 (fe_code_rate_t)(FEC_S2_QPSK_8_9+1)
61 #define FEC_S2_QPSK_4_5 (fe_code_rate_t)(FEC_S2_QPSK_3_5+1)
62 #define FEC_S2_QPSK_9_10 (fe_code_rate_t)(FEC_S2_QPSK_4_5+1)
63 #define FEC_S2_8PSK_1_2 (fe_code_rate_t)(FEC_S2_QPSK_9_10+1)
64 #define FEC_S2_8PSK_2_3 (fe_code_rate_t)(FEC_S2_8PSK_1_2+1)
65 #define FEC_S2_8PSK_3_4 (fe_code_rate_t)(FEC_S2_8PSK_2_3+1)
66 #define FEC_S2_8PSK_5_6 (fe_code_rate_t)(FEC_S2_8PSK_3_4+1)
67 #define FEC_S2_8PSK_7_8 (fe_code_rate_t)(FEC_S2_8PSK_5_6+1)
68 #define FEC_S2_8PSK_8_9 (fe_code_rate_t)(FEC_S2_8PSK_7_8+1)
69 #define FEC_S2_8PSK_3_5 (fe_code_rate_t)(FEC_S2_8PSK_8_9+1)
70 #define FEC_S2_8PSK_4_5 (fe_code_rate_t)(FEC_S2_8PSK_3_5+1)
71 #define FEC_S2_8PSK_9_10 (fe_code_rate_t)(FEC_S2_8PSK_4_5+1)
75 #include <dvbsi++/satellite_delivery_system_descriptor.h>
76 #include <dvbsi++/cable_delivery_system_descriptor.h>
77 #include <dvbsi++/terrestrial_delivery_system_descriptor.h>
79 void eDVBDiseqcCommand::setCommandString(const char *str)
84 int slen = strlen(str);
87 eDebug("invalid diseqc command string length (not 2 byte aligned)");
90 if (slen > MAX_DISEQC_LENGTH*2)
92 eDebug("invalid diseqc command string length (string is to long)");
96 for (int i=0; i < slen; ++i)
98 unsigned char c = str[i];
101 case '0' ... '9': c-=48; break;
102 case 'a' ... 'f': c-=87; break;
103 case 'A' ... 'F': c-=55; break;
105 eDebug("invalid character in hex string..ignore complete diseqc command !");
119 void eDVBFrontendParametersSatellite::set(const SatelliteDeliverySystemDescriptor &descriptor)
121 frequency = descriptor.getFrequency() * 10;
122 symbol_rate = descriptor.getSymbolRate() * 100;
123 polarisation = descriptor.getPolarization();
124 fec = descriptor.getFecInner();
125 if ( fec != FEC::fNone && fec > FEC::f9_10 )
127 inversion = Inversion::Unknown;
128 pilot = Pilot::Unknown;
129 orbital_position = ((descriptor.getOrbitalPosition() >> 12) & 0xF) * 1000;
130 orbital_position += ((descriptor.getOrbitalPosition() >> 8) & 0xF) * 100;
131 orbital_position += ((descriptor.getOrbitalPosition() >> 4) & 0xF) * 10;
132 orbital_position += ((descriptor.getOrbitalPosition()) & 0xF);
133 if (orbital_position && (!descriptor.getWestEastFlag()))
134 orbital_position = 3600 - orbital_position;
135 system = descriptor.getModulationSystem();
136 modulation = descriptor.getModulation();
137 if (system == System::DVB_S && modulation == Modulation::M8PSK)
139 eDebug("satellite_delivery_descriptor non valid modulation type.. force QPSK");
142 rolloff = descriptor.getRollOff();
143 if (system == System::DVB_S2)
145 eDebug("SAT DVB-S2 freq %d, %s, pos %d, sr %d, fec %d, modulation %d, rolloff %d",
147 polarisation ? "hor" : "vert",
155 eDebug("SAT DVB-S freq %d, %s, pos %d, sr %d, fec %d",
157 polarisation ? "hor" : "vert",
163 void eDVBFrontendParametersCable::set(const CableDeliverySystemDescriptor &descriptor)
165 frequency = descriptor.getFrequency() / 10;
166 symbol_rate = descriptor.getSymbolRate() * 100;
167 fec_inner = descriptor.getFecInner();
168 if ( fec_inner == 0xF )
169 fec_inner = FEC::fNone;
170 modulation = descriptor.getModulation();
171 if ( modulation > 0x5 )
172 modulation = Modulation::Auto;
173 inversion = Inversion::Unknown;
174 eDebug("Cable freq %d, mod %d, sr %d, fec %d",
176 modulation, symbol_rate, fec_inner);
179 void eDVBFrontendParametersTerrestrial::set(const TerrestrialDeliverySystemDescriptor &descriptor)
181 frequency = descriptor.getCentreFrequency() * 10;
182 bandwidth = descriptor.getBandwidth();
183 if ( bandwidth > 2 ) // 5Mhz forced to auto
184 bandwidth = Bandwidth::BwAuto;
185 code_rate_HP = descriptor.getCodeRateHpStream();
186 if (code_rate_HP > 4)
187 code_rate_HP = FEC::fAuto;
188 code_rate_LP = descriptor.getCodeRateLpStream();
189 if (code_rate_LP > 4)
190 code_rate_LP = FEC::fAuto;
191 transmission_mode = descriptor.getTransmissionMode();
192 if (transmission_mode > 1) // TM4k forced to auto
193 transmission_mode = TransmissionMode::TMAuto;
194 guard_interval = descriptor.getGuardInterval();
195 if (guard_interval > 3)
196 guard_interval = GuardInterval::GI_Auto;
197 hierarchy = descriptor.getHierarchyInformation()&3;
198 modulation = descriptor.getConstellation();
200 modulation = Modulation::Auto;
201 inversion = Inversion::Unknown;
202 eDebug("Terr freq %d, bw %d, cr_hp %d, cr_lp %d, tm_mode %d, guard %d, hierarchy %d, const %d",
203 frequency, bandwidth, code_rate_HP, code_rate_LP, transmission_mode,
204 guard_interval, hierarchy, modulation);
207 eDVBFrontendParameters::eDVBFrontendParameters(): m_type(-1)
211 DEFINE_REF(eDVBFrontendParameters);
213 RESULT eDVBFrontendParameters::getSystem(int &t) const
221 RESULT eDVBFrontendParameters::getDVBS(eDVBFrontendParametersSatellite &p) const
223 if (m_type != iDVBFrontend::feSatellite)
229 RESULT eDVBFrontendParameters::getDVBC(eDVBFrontendParametersCable &p) const
231 if (m_type != iDVBFrontend::feCable)
237 RESULT eDVBFrontendParameters::getDVBT(eDVBFrontendParametersTerrestrial &p) const
239 if (m_type != iDVBFrontend::feTerrestrial)
245 RESULT eDVBFrontendParameters::setDVBS(const eDVBFrontendParametersSatellite &p, bool no_rotor_command_on_tune)
248 sat.no_rotor_command_on_tune = no_rotor_command_on_tune;
249 m_type = iDVBFrontend::feSatellite;
253 RESULT eDVBFrontendParameters::setDVBC(const eDVBFrontendParametersCable &p)
256 m_type = iDVBFrontend::feCable;
260 RESULT eDVBFrontendParameters::setDVBT(const eDVBFrontendParametersTerrestrial &p)
263 m_type = iDVBFrontend::feTerrestrial;
267 RESULT eDVBFrontendParameters::calculateDifference(const iDVBFrontendParameters *parm, int &diff, bool exact) const
272 if (parm->getSystem(type))
276 diff = 1<<30; // big difference
282 case iDVBFrontend::feSatellite:
284 eDVBFrontendParametersSatellite osat;
285 if (parm->getDVBS(osat))
288 if (sat.orbital_position != osat.orbital_position)
290 else if (sat.polarisation != osat.polarisation)
292 else if (exact && sat.fec != osat.fec && sat.fec != eDVBFrontendParametersSatellite::FEC::fAuto && osat.fec != eDVBFrontendParametersSatellite::FEC::fAuto)
294 else if (exact && sat.modulation != osat.modulation && sat.modulation != eDVBFrontendParametersSatellite::Modulation::Auto && osat.modulation != eDVBFrontendParametersSatellite::Modulation::Auto)
298 diff = abs(sat.frequency - osat.frequency);
299 diff += abs(sat.symbol_rate - osat.symbol_rate);
303 case iDVBFrontend::feCable:
304 eDVBFrontendParametersCable ocable;
305 if (parm->getDVBC(ocable))
308 if (exact && cable.modulation != ocable.modulation
309 && cable.modulation != eDVBFrontendParametersCable::Modulation::Auto
310 && ocable.modulation != eDVBFrontendParametersCable::Modulation::Auto)
312 else if (exact && cable.fec_inner != ocable.fec_inner && cable.fec_inner != eDVBFrontendParametersCable::FEC::fAuto && ocable.fec_inner != eDVBFrontendParametersCable::FEC::fAuto)
316 diff = abs(cable.frequency - ocable.frequency);
317 diff += abs(cable.symbol_rate - ocable.symbol_rate);
320 case iDVBFrontend::feTerrestrial:
321 eDVBFrontendParametersTerrestrial oterrestrial;
322 if (parm->getDVBT(oterrestrial))
326 if (exact && oterrestrial.bandwidth != terrestrial.bandwidth &&
327 oterrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto &&
328 terrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto)
330 else if (exact && oterrestrial.modulation != terrestrial.modulation &&
331 oterrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation::Auto &&
332 terrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation::Auto)
334 else if (exact && oterrestrial.transmission_mode != terrestrial.transmission_mode &&
335 oterrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto &&
336 terrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto)
338 else if (exact && oterrestrial.guard_interval != terrestrial.guard_interval &&
339 oterrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto &&
340 terrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto)
342 else if (exact && oterrestrial.hierarchy != terrestrial.hierarchy &&
343 oterrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy::HAuto &&
344 terrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy::HAuto)
346 else if (exact && oterrestrial.code_rate_LP != terrestrial.code_rate_LP &&
347 oterrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC::fAuto &&
348 terrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC::fAuto)
350 else if (exact && oterrestrial.code_rate_HP != terrestrial.code_rate_HP &&
351 oterrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC::fAuto &&
352 terrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC::fAuto)
355 diff = abs(terrestrial.frequency - oterrestrial.frequency);
363 RESULT eDVBFrontendParameters::getHash(unsigned long &hash) const
367 case iDVBFrontend::feSatellite:
369 hash = (sat.orbital_position << 16);
370 hash |= ((sat.frequency/1000)&0xFFFF)|((sat.polarisation&1) << 15);
373 case iDVBFrontend::feCable:
375 hash |= (cable.frequency/1000)&0xFFFF;
377 case iDVBFrontend::feTerrestrial:
379 hash |= (terrestrial.frequency/1000)&0xFFFF;
386 RESULT eDVBFrontendParameters::calcLockTimeout(unsigned int &timeout) const
390 case iDVBFrontend::feSatellite:
392 /* high symbol rate transponders tune faster, due to
393 requiring less zigzag and giving more symbols faster.
395 5s are definitely not enough on really low SR when
396 zigzag has to find the exact frequency first.
398 if (sat.symbol_rate > 20000000)
400 else if (sat.symbol_rate > 10000000)
406 case iDVBFrontend::feCable:
409 case iDVBFrontend::feTerrestrial:
417 DEFINE_REF(eDVBFrontend);
419 int eDVBFrontend::PriorityOrder=0;
421 eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok)
422 :m_enabled(false), m_type(-1), m_dvbid(fe), m_slotid(fe)
423 ,m_fd(-1), m_need_rotor_workaround(false), m_can_handle_dvbs2(false)
424 ,m_sn(0), m_timeout(0), m_tuneTimer(0)
425 #if HAVE_DVB_API_VERSION < 3
429 #if HAVE_DVB_API_VERSION < 3
430 sprintf(m_filename, "/dev/dvb/card%d/frontend%d", adap, fe);
431 sprintf(m_sec_filename, "/dev/dvb/card%d/sec%d", adap, fe);
433 sprintf(m_filename, "/dev/dvb/adapter%d/frontend%d", adap, fe);
435 m_timeout = new eTimer(eApp);
436 CONNECT(m_timeout->timeout, eDVBFrontend::timeout);
438 m_tuneTimer = new eTimer(eApp);
439 CONNECT(m_tuneTimer->timeout, eDVBFrontend::tuneLoop);
441 for (int i=0; i<eDVBFrontend::NUM_DATA_ENTRIES; ++i)
444 m_idleInputpower[0]=m_idleInputpower[1]=0;
446 ok = !openFrontend();
450 int eDVBFrontend::openFrontend()
453 return -1; // already opened
458 #if HAVE_DVB_API_VERSION < 3
459 FrontendInfo fe_info;
461 dvb_frontend_info fe_info;
463 eDebug("opening frontend %d", m_dvbid);
466 m_fd = ::open(m_filename, O_RDWR|O_NONBLOCK);
469 eWarning("failed! (%s) %m", m_filename);
474 eWarning("frontend %d already opened", m_dvbid);
477 if (::ioctl(m_fd, FE_GET_INFO, &fe_info) < 0)
479 eWarning("ioctl FE_GET_INFO failed");
485 switch (fe_info.type)
488 m_type = iDVBFrontend::feSatellite;
491 m_type = iDVBFrontend::feCable;
494 m_type = iDVBFrontend::feTerrestrial;
497 eWarning("unknown frontend type.");
502 eDebug("detected %s frontend", "satellite\0cable\0 terrestrial"+fe_info.type*10);
505 #if HAVE_DVB_API_VERSION < 3
506 if (m_type == iDVBFrontend::feSatellite)
510 m_secfd = ::open(m_sec_filename, O_RDWR);
513 eWarning("failed! (%s) %m", m_sec_filename);
520 eWarning("sec %d already opened", m_dvbid);
524 setTone(iDVBFrontend::toneOff);
525 setVoltage(iDVBFrontend::voltageOff);
527 m_sn = new eSocketNotifier(eApp, m_fd, eSocketNotifier::Read, false);
528 CONNECT(m_sn->activated, eDVBFrontend::feEvent);
533 int eDVBFrontend::closeFrontend(bool force)
535 if (!force && m_data[CUR_VOLTAGE] != -1 && m_data[CUR_VOLTAGE] != iDVBFrontend::voltageOff)
537 long tmp = m_data[LINKED_NEXT_PTR];
540 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
541 if (linked_fe->m_inuse)
543 eDebug("dont close frontend %d until the linked frontend %d in slot %d is still in use",
544 m_dvbid, linked_fe->m_frontend->getDVBID(), linked_fe->m_frontend->getSlotID());
547 linked_fe->m_frontend->getData(LINKED_NEXT_PTR, tmp);
552 eDebug("close frontend %d", m_dvbid);
554 setTone(iDVBFrontend::toneOff);
555 setVoltage(iDVBFrontend::voltageOff);
557 m_sec->setRotorMoving(false);
561 eWarning("couldnt close frontend %d", m_dvbid);
563 #if HAVE_DVB_API_VERSION < 3
566 if (!::close(m_secfd))
569 eWarning("couldnt close sec %d", m_dvbid);
574 m_state = stateClosed;
579 eDVBFrontend::~eDVBFrontend()
581 m_data[LINKED_PREV_PTR] = m_data[LINKED_NEXT_PTR] = -1;
587 void eDVBFrontend::feEvent(int w)
591 #if HAVE_DVB_API_VERSION < 3
594 dvb_frontend_event event;
598 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
600 if (res && (errno == EAGAIN))
605 eWarning("FE_GET_EVENT failed! %m");
612 #if HAVE_DVB_API_VERSION < 3
613 if (event.type == FE_COMPLETION_EV)
615 eDebug("(%d)fe event: status %x, inversion %s", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off");
616 if (event.status & FE_HAS_LOCK)
626 eDVBFrontend *sec_fe = this;
627 long tmp = m_data[LINKED_PREV_PTR];
629 eDebug("stateLostLock");
630 state = stateLostLock;
634 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
635 sec_fe = linked_fe->m_frontend;
636 sec_fe->getData(LINKED_NEXT_PTR, tmp);
638 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
641 if (m_state != state)
644 m_stateChanged(this);
649 void eDVBFrontend::timeout()
652 if (m_state == stateTuning)
654 m_state = stateFailed;
655 m_stateChanged(this);
659 #define INRANGE(X,Y,Z) (((X<=Y) && (Y<=Z))||((Z<=Y) && (Y<=X)) ? 1 : 0)
661 int eDVBFrontend::readFrontendData(int type)
668 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
669 eDebug("FE_READ_BER failed (%m)");
675 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
676 eDebug("FE_READ_SNR failed (%m)");
679 case signalQualitydB: /* this will move into the driver */
682 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
683 eDebug("FE_READ_SNR failed (%m)");
684 if (!strcmp(m_description, "BCM4501 (internal)"))
686 unsigned int SDS_SNRE = snr << 16;
688 static float SNR_COEFF[6] = {
691 197418.0 / 4194304.0,
692 -2602183.0 / 4194304.0,
693 20377212.0 / 4194304.0,
694 -37791203.0 / 4194304.0,
697 float fval1, fval2, snr_in_db;
699 fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0));
700 fval2 = pow(10.0, fval1)-1;
701 fval1 = 10.0 * log10(fval2);
705 fval2 = SNR_COEFF[0];
709 fval2 += SNR_COEFF[i];
715 return (int)(snr_in_db * 100.0);
717 else if (strstr(m_description, "Alps BSBE1 C01A") ||
718 !strcmp(m_description, "Alps -S(STV0288)"))
722 else if (snr == 0xFFFF) // i think this should not happen
726 enum { REALVAL, REGVAL };
727 const long CN_lookup[31][2] = {
728 {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
729 {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
730 {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
731 {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
732 {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
733 {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
736 long regval = 0xFFFF - ((snr / 3) + 0xA100), // revert some dvb api calulations to get the real register value
740 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
746 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[i][REGVAL]))
751 return (((regval - CN_lookup[Imin][REGVAL])
752 * (CN_lookup[Imax][REALVAL] - CN_lookup[Imin][REALVAL])
753 / (CN_lookup[Imax][REGVAL] - CN_lookup[Imin][REGVAL]))
754 + CN_lookup[Imin][REALVAL]) * 10;
760 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
761 !strcmp(m_description, "Alps -S") ||
762 !strcmp(m_description, "Philips -S") ||
763 !strcmp(m_description, "LG -S") )
765 float snr_in_db=(snr-39075)/1764.7;
766 return (int)(snr_in_db * 100.0);
767 } else if (!strcmp(m_description, "Alps BSBE2"))
769 return (int)((snr >> 7) * 10.0);
771 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
777 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
778 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
783 #if HAVE_DVB_API_VERSION < 3
784 FrontendStatus status=0;
788 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
789 eDebug("FE_READ_STATUS failed (%m)");
790 return !!(status&FE_HAS_LOCK);
794 #if HAVE_DVB_API_VERSION < 3
795 FrontendStatus status=0;
799 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
800 eDebug("FE_READ_STATUS failed (%m)");
801 return !!(status&FE_HAS_SYNC);
809 void PutToDict(ePyObject &dict, const char*key, long value)
811 ePyObject item = PyInt_FromLong(value);
814 if (PyDict_SetItemString(dict, key, item))
815 eDebug("put %s to dict failed", key);
819 eDebug("could not create PyObject for %s", key);
822 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
826 if (PyDict_SetItemString(dict, key, item))
827 eDebug("put %s to dict failed", key);
831 eDebug("invalid PyObject for %s", key);
834 void PutToDict(ePyObject &dict, const char*key, const char *value)
836 ePyObject item = PyString_FromString(value);
839 if (PyDict_SetItemString(dict, key, item))
840 eDebug("put %s to dict failed", key);
844 eDebug("could not create PyObject for %s", key);
847 void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, eDVBFrontend *fe)
851 fe->getData(eDVBFrontend::FREQ_OFFSET, freq_offset);
852 int frequency = parm_frequency + freq_offset;
853 PutToDict(dict, "frequency", frequency);
854 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
855 switch(parm_u_qpsk_fec_inner)
878 #if HAVE_DVB_API_VERSION >=3
879 case FEC_S2_8PSK_1_2:
880 case FEC_S2_QPSK_1_2:
883 case FEC_S2_8PSK_2_3:
884 case FEC_S2_QPSK_2_3:
887 case FEC_S2_8PSK_3_4:
888 case FEC_S2_QPSK_3_4:
891 case FEC_S2_8PSK_5_6:
892 case FEC_S2_QPSK_5_6:
895 case FEC_S2_8PSK_7_8:
896 case FEC_S2_QPSK_7_8:
899 case FEC_S2_8PSK_8_9:
900 case FEC_S2_QPSK_8_9:
903 case FEC_S2_8PSK_3_5:
904 case FEC_S2_QPSK_3_5:
907 case FEC_S2_8PSK_4_5:
908 case FEC_S2_QPSK_4_5:
911 case FEC_S2_8PSK_9_10:
912 case FEC_S2_QPSK_9_10:
917 PutToDict(dict, "fec_inner", tmp);
918 #if HAVE_DVB_API_VERSION >=3
919 PutToDict(dict, "modulation",
920 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ? "8PSK": "QPSK" );
921 if (parm_u_qpsk_fec_inner > FEC_AUTO)
923 switch(parm_inversion & 0xc)
925 default: // unknown rolloff
927 tmp = "ROLLOFF_0_35";
930 tmp = "ROLLOFF_0_25";
933 tmp = "ROLLOFF_0_20";
936 PutToDict(dict, "rolloff", tmp);
937 if (parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10)
939 switch(parm_inversion & 0x30)
944 case 0x10: // pilot on
947 case 0x20: // pilot auto
951 PutToDict(dict, "pilot", tmp);
958 PutToDict(dict, "modulation", "QPSK" );
961 PutToDict(dict, "system", tmp);
964 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
967 #if HAVE_DVB_API_VERSION < 3
968 PutToDict(dict, "frequency", parm_frequency);
970 PutToDict(dict, "frequency", parm_frequency/1000);
972 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
973 switch(parm_u_qam_fec_inner)
993 #if HAVE_DVB_API_VERSION >= 3
1003 PutToDict(dict, "fec_inner", tmp);
1004 switch(parm_u_qam_modulation)
1026 PutToDict(dict, "modulation", tmp);
1029 void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1032 PutToDict(dict, "frequency", parm_frequency);
1033 switch (parm_u_ofdm_bandwidth)
1035 case BANDWIDTH_8_MHZ:
1036 tmp = "BANDWIDTH_8_MHZ";
1038 case BANDWIDTH_7_MHZ:
1039 tmp = "BANDWIDTH_7_MHZ";
1041 case BANDWIDTH_6_MHZ:
1042 tmp = "BANDWIDTH_6_MHZ";
1045 case BANDWIDTH_AUTO:
1046 tmp = "BANDWIDTH_AUTO";
1049 PutToDict(dict, "bandwidth", tmp);
1050 switch (parm_u_ofdm_code_rate_LP)
1072 PutToDict(dict, "code_rate_lp", tmp);
1073 switch (parm_u_ofdm_code_rate_HP)
1095 PutToDict(dict, "code_rate_hp", tmp);
1096 switch (parm_u_ofdm_constellation)
1112 PutToDict(dict, "constellation", tmp);
1113 switch (parm_u_ofdm_transmission_mode)
1115 case TRANSMISSION_MODE_2K:
1116 tmp = "TRANSMISSION_MODE_2K";
1118 case TRANSMISSION_MODE_8K:
1119 tmp = "TRANSMISSION_MODE_8K";
1122 case TRANSMISSION_MODE_AUTO:
1123 tmp = "TRANSMISSION_MODE_AUTO";
1126 PutToDict(dict, "transmission_mode", tmp);
1127 switch (parm_u_ofdm_guard_interval)
1129 case GUARD_INTERVAL_1_32:
1130 tmp = "GUARD_INTERVAL_1_32";
1132 case GUARD_INTERVAL_1_16:
1133 tmp = "GUARD_INTERVAL_1_16";
1135 case GUARD_INTERVAL_1_8:
1136 tmp = "GUARD_INTERVAL_1_8";
1138 case GUARD_INTERVAL_1_4:
1139 tmp = "GUARD_INTERVAL_1_4";
1142 case GUARD_INTERVAL_AUTO:
1143 tmp = "GUARD_INTERVAL_AUTO";
1146 PutToDict(dict, "guard_interval", tmp);
1147 switch (parm_u_ofdm_hierarchy_information)
1149 case HIERARCHY_NONE:
1150 tmp = "HIERARCHY_NONE";
1153 tmp = "HIERARCHY_1";
1156 tmp = "HIERARCHY_2";
1159 tmp = "HIERARCHY_4";
1162 case HIERARCHY_AUTO:
1163 tmp = "HIERARCHY_AUTO";
1166 PutToDict(dict, "hierarchy_information", tmp);
1169 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1171 if (dest && PyDict_Check(dest))
1173 const char *tmp = "UNKNOWN";
1194 PutToDict(dest, "tuner_state", tmp);
1195 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1196 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1197 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1198 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1199 int sigQualitydB = readFrontendData(signalQualitydB);
1200 if (sigQualitydB == 0x12345678) // not support yet
1202 ePyObject obj=Py_None;
1204 PutToDict(dest, "tuner_signal_quality_db", obj);
1207 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1208 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1212 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1214 if (m_fd != -1 && dest && PyDict_Check(dest))
1222 FRONTENDPARAMETERS front;
1223 if (!original && ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1224 eDebug("FE_GET_FRONTEND (%m)");
1227 const FRONTENDPARAMETERS &parm = original ? this->parm : front;
1228 const char *tmp = "INVERSION_AUTO";
1229 switch(parm_inversion)
1232 tmp = "INVERSION_ON";
1235 tmp = "INVERSION_OFF";
1241 PutToDict(dest, "inversion", tmp);
1246 fillDictWithSatelliteData(dest, original?parm:front, this);
1249 fillDictWithCableData(dest, original?parm:front);
1252 fillDictWithTerrestrialData(dest, original?parm:front);
1263 void eDVBFrontend::getFrontendData(ePyObject dest)
1265 if (dest && PyDict_Check(dest))
1268 PutToDict(dest, "tuner_number", m_slotid);
1284 PutToDict(dest, "tuner_type", tmp);
1288 #ifndef FP_IOCTL_GET_ID
1289 #define FP_IOCTL_GET_ID 0
1291 int eDVBFrontend::readInputpower()
1293 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1295 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1296 FILE *f=fopen(proc_name, "r");
1299 if (fscanf(f, "%d", &power) != 1)
1300 eDebug("read %s failed!! (%m)", proc_name);
1302 eDebug("%s is %d\n", proc_name, power);
1307 // open front prozessor
1308 int fp=::open("/dev/dbox/fp0", O_RDWR);
1311 eDebug("couldn't open fp");
1314 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1315 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1317 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1326 bool eDVBFrontend::setSecSequencePos(int steps)
1328 eDebug("set sequence pos %d", steps);
1333 if (m_sec_sequence.current() != m_sec_sequence.end())
1334 ++m_sec_sequence.current();
1339 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1340 --m_sec_sequence.current();
1346 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1349 eDVBFrontend *sec_fe = this;
1350 eDVBRegisteredFrontend *regFE = 0;
1351 long tmp = m_data[LINKED_PREV_PTR];
1354 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1355 sec_fe = prev->m_frontend;
1356 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1357 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1358 int state = sec_fe->m_state;
1359 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1361 sec_fe->closeFrontend(true);
1362 state = sec_fe->m_state;
1364 if (state == eDVBFrontend::stateClosed)
1372 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1374 long *sec_fe_data = sec_fe->m_data;
1375 // eDebug("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1376 switch (m_sec_sequence.current()->cmd)
1378 case eSecCommand::SLEEP:
1379 delay = m_sec_sequence.current()++->msec;
1380 eDebug("[SEC] sleep %dms", delay);
1382 case eSecCommand::GOTO:
1383 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1384 ++m_sec_sequence.current();
1386 case eSecCommand::SET_VOLTAGE:
1388 int voltage = m_sec_sequence.current()++->voltage;
1389 eDebug("[SEC] setVoltage %d", voltage);
1390 sec_fe->setVoltage(voltage);
1393 case eSecCommand::IF_VOLTAGE_GOTO:
1395 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1396 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1398 ++m_sec_sequence.current();
1401 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1403 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1404 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1406 ++m_sec_sequence.current();
1409 case eSecCommand::IF_TONE_GOTO:
1411 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1412 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1414 ++m_sec_sequence.current();
1417 case eSecCommand::IF_NOT_TONE_GOTO:
1419 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1420 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1422 ++m_sec_sequence.current();
1425 case eSecCommand::SET_TONE:
1426 eDebug("[SEC] setTone %d", m_sec_sequence.current()->tone);
1427 sec_fe->setTone(m_sec_sequence.current()++->tone);
1429 case eSecCommand::SEND_DISEQC:
1430 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1431 eDebugNoNewLine("[SEC] sendDiseqc: ");
1432 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1433 eDebugNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1435 ++m_sec_sequence.current();
1437 case eSecCommand::SEND_TONEBURST:
1438 eDebug("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1439 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1441 case eSecCommand::SET_FRONTEND:
1442 eDebug("[SEC] setFrontend");
1444 ++m_sec_sequence.current();
1446 case eSecCommand::START_TUNE_TIMEOUT:
1448 m_timeout->start(m_sec_sequence.current()->timeout, 1);
1449 ++m_sec_sequence.current();
1452 case eSecCommand::SET_TIMEOUT:
1453 m_timeoutCount = m_sec_sequence.current()++->val;
1454 eDebug("[SEC] set timeout %d", m_timeoutCount);
1456 case eSecCommand::IF_TIMEOUT_GOTO:
1457 if (!m_timeoutCount)
1459 eDebug("[SEC] rotor timout");
1460 m_sec->setRotorMoving(false);
1461 setSecSequencePos(m_sec_sequence.current()->steps);
1464 ++m_sec_sequence.current();
1466 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1468 int idx = m_sec_sequence.current()++->val;
1469 if ( idx == 0 || idx == 1 )
1471 m_idleInputpower[idx] = sec_fe->readInputpower();
1472 eDebug("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1475 eDebug("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1478 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1480 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1481 int idx = compare.val;
1482 if ( idx == 0 || idx == 1 )
1484 int idle = sec_fe->readInputpower();
1485 int diff = abs(idle-m_idleInputpower[idx]);
1488 eDebug("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1489 setSecSequencePos(compare.steps);
1493 ++m_sec_sequence.current();
1496 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1498 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1499 if (readFrontendData(locked))
1501 eDebug("[SEC] locked step %d ok", cmd.okcount);
1503 if (cmd.okcount > 12)
1505 eDebug("ok > 12 .. goto %d\n",m_sec_sequence.current()->steps);
1506 setSecSequencePos(cmd.steps);
1512 eDebug("[SEC] rotor locked step %d failed", cmd.okcount);
1514 if (!m_timeoutCount && m_retryCount > 0)
1518 ++m_sec_sequence.current();
1521 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1522 m_runningInputpower = sec_fe->readInputpower();
1523 eDebug("[SEC] runningInputpower is %d", m_runningInputpower);
1524 ++m_sec_sequence.current();
1526 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1528 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1529 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1530 const char *txt = cmd.direction ? "running" : "stopped";
1531 eDebug("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1533 m_runningInputpower,
1536 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1537 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1540 eDebug("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1541 if ( cmd.okcount > 6 )
1543 m_sec->setRotorMoving(cmd.direction);
1544 eDebug("[SEC] rotor is %s", txt);
1545 if (setSecSequencePos(cmd.steps))
1551 eDebug("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1553 if (!m_timeoutCount && m_retryCount > 0)
1557 ++m_sec_sequence.current();
1560 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1561 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1562 setSecSequencePos(m_sec_sequence.current()->steps);
1564 ++m_sec_sequence.current();
1566 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1567 eDebug("[SEC] invalidate current switch params");
1568 sec_fe_data[CSW] = -1;
1569 sec_fe_data[UCSW] = -1;
1570 sec_fe_data[TONEBURST] = -1;
1571 ++m_sec_sequence.current();
1573 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1574 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1575 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1576 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1577 eDebug("[SEC] update current switch params");
1578 ++m_sec_sequence.current();
1580 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1581 eDebug("[SEC] invalidate current rotorparams");
1582 sec_fe_data[ROTOR_CMD] = -1;
1583 sec_fe_data[ROTOR_POS] = -1;
1584 ++m_sec_sequence.current();
1586 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1587 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1588 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1589 eDebug("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1590 ++m_sec_sequence.current();
1592 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1593 m_retryCount = m_sec_sequence.current()++->val;
1594 eDebug("[SEC] set rotor retries %d", m_retryCount);
1596 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1599 eDebug("[SEC] no more rotor retrys");
1600 setSecSequencePos(m_sec_sequence.current()->steps);
1603 ++m_sec_sequence.current();
1605 case eSecCommand::SET_POWER_LIMITING_MODE:
1608 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1609 FILE *f=fopen(proc_name, "w");
1610 if (f) // new interface exist?
1612 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1613 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1614 eDebug("write %s failed!! (%m)", proc_name);
1616 eDebug("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1619 else if (sec_fe->m_need_rotor_workaround)
1622 int slotid = sec_fe->m_slotid;
1623 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1625 sprintf(dev, "/dev/i2c/%d", slotid);
1626 else if (slotid == 2)
1627 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1628 else if (slotid == 3)
1629 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1630 int fd = ::open(dev, O_RDWR);
1632 unsigned char data[2];
1633 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1634 if(::read(fd, data, 1) != 1)
1635 eDebug("[SEC] error read lnbp (%m)");
1636 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1638 data[0] |= 0x80; // enable static current limiting
1639 eDebug("[SEC] set static current limiting");
1643 data[0] &= ~0x80; // enable dynamic current limiting
1644 eDebug("[SEC] set dynamic current limiting");
1646 if(::write(fd, data, 1) != 1)
1647 eDebug("[SEC] error write lnbp (%m)");
1650 ++m_sec_sequence.current();
1654 eDebug("[SEC] unhandled sec command %d",
1655 ++m_sec_sequence.current()->cmd);
1656 ++m_sec_sequence.current();
1658 m_tuneTimer->start(delay,true);
1664 void eDVBFrontend::setFrontend()
1666 eDebug("setting frontend %d", m_dvbid);
1669 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1671 perror("FE_SET_FRONTEND failed");
1676 RESULT eDVBFrontend::getFrontendType(int &t)
1684 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1689 eWarning("no SEC module active!");
1692 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1695 eDebug("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1698 feparm.polarisation,
1702 feparm.orbital_position);
1703 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1704 switch (feparm.inversion)
1706 case eDVBFrontendParametersSatellite::Inversion::On:
1707 parm_inversion = INVERSION_ON;
1709 case eDVBFrontendParametersSatellite::Inversion::Off:
1710 parm_inversion = INVERSION_OFF;
1713 case eDVBFrontendParametersSatellite::Inversion::Unknown:
1714 parm_inversion = INVERSION_AUTO;
1717 if (feparm.system == eDVBFrontendParametersSatellite::System::DVB_S)
1720 case eDVBFrontendParametersSatellite::FEC::fNone:
1721 parm_u_qpsk_fec_inner = FEC_NONE;
1723 case eDVBFrontendParametersSatellite::FEC::f1_2:
1724 parm_u_qpsk_fec_inner = FEC_1_2;
1726 case eDVBFrontendParametersSatellite::FEC::f2_3:
1727 parm_u_qpsk_fec_inner = FEC_2_3;
1729 case eDVBFrontendParametersSatellite::FEC::f3_4:
1730 parm_u_qpsk_fec_inner = FEC_3_4;
1732 case eDVBFrontendParametersSatellite::FEC::f5_6:
1733 parm_u_qpsk_fec_inner = FEC_5_6;
1735 case eDVBFrontendParametersSatellite::FEC::f7_8:
1736 parm_u_qpsk_fec_inner = FEC_7_8;
1739 eDebug("no valid fec for DVB-S set.. assume auto");
1740 case eDVBFrontendParametersSatellite::FEC::fAuto:
1741 parm_u_qpsk_fec_inner = FEC_AUTO;
1744 #if HAVE_DVB_API_VERSION >= 3
1749 case eDVBFrontendParametersSatellite::FEC::f1_2:
1750 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1752 case eDVBFrontendParametersSatellite::FEC::f2_3:
1753 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1755 case eDVBFrontendParametersSatellite::FEC::f3_4:
1756 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1758 case eDVBFrontendParametersSatellite::FEC::f3_5:
1759 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1761 case eDVBFrontendParametersSatellite::FEC::f4_5:
1762 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1764 case eDVBFrontendParametersSatellite::FEC::f5_6:
1765 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1767 case eDVBFrontendParametersSatellite::FEC::f7_8:
1768 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1770 case eDVBFrontendParametersSatellite::FEC::f8_9:
1771 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1773 case eDVBFrontendParametersSatellite::FEC::f9_10:
1774 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1777 eDebug("no valid fec for DVB-S2 set.. abort !!");
1780 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1781 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK) {
1782 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1783 // 8PSK fec driver values are decimal 9 bigger
1784 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1788 // FIXME !!! get frequency range from tuner
1789 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1791 eDebug("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1794 eDebug("tuning to %d mhz", parm_frequency/1000);
1799 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1801 #if HAVE_DVB_API_VERSION < 3
1802 parm_frequency = feparm.frequency;
1804 parm_frequency = feparm.frequency * 1000;
1806 parm_u_qam_symbol_rate = feparm.symbol_rate;
1807 switch (feparm.modulation)
1809 case eDVBFrontendParametersCable::Modulation::QAM16:
1810 parm_u_qam_modulation = QAM_16;
1812 case eDVBFrontendParametersCable::Modulation::QAM32:
1813 parm_u_qam_modulation = QAM_32;
1815 case eDVBFrontendParametersCable::Modulation::QAM64:
1816 parm_u_qam_modulation = QAM_64;
1818 case eDVBFrontendParametersCable::Modulation::QAM128:
1819 parm_u_qam_modulation = QAM_128;
1821 case eDVBFrontendParametersCable::Modulation::QAM256:
1822 parm_u_qam_modulation = QAM_256;
1825 case eDVBFrontendParametersCable::Modulation::Auto:
1826 parm_u_qam_modulation = QAM_AUTO;
1829 switch (feparm.inversion)
1831 case eDVBFrontendParametersCable::Inversion::On:
1832 parm_inversion = INVERSION_ON;
1834 case eDVBFrontendParametersCable::Inversion::Off:
1835 parm_inversion = INVERSION_OFF;
1838 case eDVBFrontendParametersCable::Inversion::Unknown:
1839 parm_inversion = INVERSION_AUTO;
1842 switch (feparm.fec_inner)
1844 case eDVBFrontendParametersCable::FEC::fNone:
1845 parm_u_qam_fec_inner = FEC_NONE;
1847 case eDVBFrontendParametersCable::FEC::f1_2:
1848 parm_u_qam_fec_inner = FEC_1_2;
1850 case eDVBFrontendParametersCable::FEC::f2_3:
1851 parm_u_qam_fec_inner = FEC_2_3;
1853 case eDVBFrontendParametersCable::FEC::f3_4:
1854 parm_u_qam_fec_inner = FEC_3_4;
1856 case eDVBFrontendParametersCable::FEC::f5_6:
1857 parm_u_qam_fec_inner = FEC_5_6;
1859 case eDVBFrontendParametersCable::FEC::f7_8:
1860 parm_u_qam_fec_inner = FEC_7_8;
1862 #if HAVE_DVB_API_VERSION >= 3
1863 case eDVBFrontendParametersCable::FEC::f8_9:
1864 parm_u_qam_fec_inner = FEC_8_9;
1868 case eDVBFrontendParametersCable::FEC::fAuto:
1869 parm_u_qam_fec_inner = FEC_AUTO;
1872 eDebug("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
1873 parm_frequency/1000,
1874 parm_u_qam_symbol_rate,
1875 parm_u_qam_fec_inner,
1876 parm_u_qam_modulation,
1881 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
1883 parm_frequency = feparm.frequency;
1885 switch (feparm.bandwidth)
1887 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
1888 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
1890 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
1891 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
1893 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
1894 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
1897 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
1898 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
1901 switch (feparm.code_rate_LP)
1903 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1904 parm_u_ofdm_code_rate_LP = FEC_1_2;
1906 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1907 parm_u_ofdm_code_rate_LP = FEC_2_3;
1909 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1910 parm_u_ofdm_code_rate_LP = FEC_3_4;
1912 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1913 parm_u_ofdm_code_rate_LP = FEC_5_6;
1915 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1916 parm_u_ofdm_code_rate_LP = FEC_7_8;
1919 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1920 parm_u_ofdm_code_rate_LP = FEC_AUTO;
1923 switch (feparm.code_rate_HP)
1925 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1926 parm_u_ofdm_code_rate_HP = FEC_1_2;
1928 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1929 parm_u_ofdm_code_rate_HP = FEC_2_3;
1931 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1932 parm_u_ofdm_code_rate_HP = FEC_3_4;
1934 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1935 parm_u_ofdm_code_rate_HP = FEC_5_6;
1937 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1938 parm_u_ofdm_code_rate_HP = FEC_7_8;
1941 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1942 parm_u_ofdm_code_rate_HP = FEC_AUTO;
1945 switch (feparm.modulation)
1947 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
1948 parm_u_ofdm_constellation = QPSK;
1950 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
1951 parm_u_ofdm_constellation = QAM_16;
1953 case eDVBFrontendParametersTerrestrial::Modulation::QAM64:
1954 parm_u_ofdm_constellation = QAM_64;
1957 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
1958 parm_u_ofdm_constellation = QAM_AUTO;
1961 switch (feparm.transmission_mode)
1963 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
1964 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
1966 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
1967 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
1970 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
1971 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
1974 switch (feparm.guard_interval)
1976 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32:
1977 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
1979 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16:
1980 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
1982 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8:
1983 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
1985 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4:
1986 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
1989 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto:
1990 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
1993 switch (feparm.hierarchy)
1995 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone:
1996 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
1998 case eDVBFrontendParametersTerrestrial::Hierarchy::H1:
1999 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2001 case eDVBFrontendParametersTerrestrial::Hierarchy::H2:
2002 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2004 case eDVBFrontendParametersTerrestrial::Hierarchy::H4:
2005 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2008 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto:
2009 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2012 switch (feparm.inversion)
2014 case eDVBFrontendParametersTerrestrial::Inversion::On:
2015 parm_inversion = INVERSION_ON;
2017 case eDVBFrontendParametersTerrestrial::Inversion::Off:
2018 parm_inversion = INVERSION_OFF;
2021 case eDVBFrontendParametersTerrestrial::Inversion::Unknown:
2022 parm_inversion = INVERSION_AUTO;
2028 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2030 unsigned int timeout = 5000;
2031 eDebug("(%d)tune", m_dvbid);
2039 eDebug("no frontend device opened... do not try to tune !!!");
2051 m_sec_sequence.clear();
2053 where.calcLockTimeout(timeout);
2059 eDVBFrontendParametersSatellite feparm;
2060 if (where.getDVBS(feparm))
2062 eDebug("no dvbs data!");
2066 m_sec->setRotorMoving(false);
2067 res=prepare_sat(feparm, timeout);
2075 eDVBFrontendParametersCable feparm;
2076 if (where.getDVBC(feparm))
2081 res=prepare_cable(feparm);
2085 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2086 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2091 eDVBFrontendParametersTerrestrial feparm;
2092 if (where.getDVBT(feparm))
2094 eDebug("no -T data");
2098 res=prepare_terrestrial(feparm);
2102 std::string enable_5V;
2103 char configStr[255];
2104 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2105 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2106 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2107 if (enable_5V == "True")
2108 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2110 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2111 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2117 m_tuneTimer->start(0,true);
2118 m_sec_sequence.current() = m_sec_sequence.begin();
2120 if (m_state != stateTuning)
2123 m_state = stateTuning;
2124 m_stateChanged(this);
2130 m_tuneTimer->stop();
2134 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2136 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2140 RESULT eDVBFrontend::setVoltage(int voltage)
2142 if (m_type == feCable)
2144 #if HAVE_DVB_API_VERSION < 3
2147 bool increased=false;
2148 fe_sec_voltage_t vlt;
2150 m_data[CUR_VOLTAGE]=voltage;
2154 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2155 vlt = SEC_VOLTAGE_OFF;
2158 #if HAVE_DVB_API_VERSION < 3
2159 vlt = SEC_VOLTAGE_13_5;
2165 vlt = SEC_VOLTAGE_13;
2168 #if HAVE_DVB_API_VERSION < 3
2169 vlt = SEC_VOLTAGE_18_5;
2175 vlt = SEC_VOLTAGE_18;
2180 #if HAVE_DVB_API_VERSION < 3
2181 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2183 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2184 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2185 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2189 RESULT eDVBFrontend::getState(int &state)
2195 RESULT eDVBFrontend::setTone(int t)
2197 if (m_type != feSatellite)
2199 #if HAVE_DVB_API_VERSION < 3
2202 fe_sec_tone_mode_t tone;
2211 tone = SEC_TONE_OFF;
2216 #if HAVE_DVB_API_VERSION < 3
2217 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2219 return ::ioctl(m_fd, FE_SET_TONE, tone);
2223 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2224 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2227 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2229 #if HAVE_DVB_API_VERSION < 3
2230 struct secCommand cmd;
2231 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2232 cmd.u.diseqc.cmdtype = diseqc.data[0];
2233 cmd.u.diseqc.addr = diseqc.data[1];
2234 cmd.u.diseqc.cmd = diseqc.data[2];
2235 cmd.u.diseqc.numParams = diseqc.len-3;
2236 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2237 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2239 struct dvb_diseqc_master_cmd cmd;
2240 memcpy(cmd.msg, diseqc.data, diseqc.len);
2241 cmd.msg_len = diseqc.len;
2242 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2248 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2249 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2251 RESULT eDVBFrontend::sendToneburst(int burst)
2253 #if HAVE_DVB_API_VERSION < 3
2254 secMiniCmd cmd = SEC_MINI_NONE;
2256 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2258 if ( burst == eDVBSatelliteDiseqcParameters::A )
2260 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2262 #if HAVE_DVB_API_VERSION < 3
2263 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2266 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2272 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2278 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2280 m_sec_sequence = list;
2284 RESULT eDVBFrontend::getData(int num, long &data)
2286 if ( num < NUM_DATA_ENTRIES )
2294 RESULT eDVBFrontend::setData(int num, long val)
2296 if ( num < NUM_DATA_ENTRIES )
2304 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2307 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2309 if (m_type == eDVBFrontend::feSatellite)
2312 eDVBFrontendParametersSatellite sat_parm;
2313 int ret = feparm->getDVBS(sat_parm);
2315 if (sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S2 && !m_can_handle_dvbs2)
2317 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2318 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S && m_can_handle_dvbs2)
2322 else if (m_type == eDVBFrontend::feCable)
2323 return 2; // more prio for cable frontends
2324 else if (m_type == eDVBFrontend::feTerrestrial)
2329 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2331 ePyObject Id, Descr, Enabled;
2332 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 3)
2334 Id = PyTuple_GET_ITEM(obj, 0);
2335 Descr = PyTuple_GET_ITEM(obj, 1);
2336 Enabled = PyTuple_GET_ITEM(obj, 2);
2337 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled))
2339 strcpy(m_description, PyString_AS_STRING(Descr));
2340 m_slotid = PyInt_AsLong(Id);
2341 m_enabled = Enabled == Py_True;
2342 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2343 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2344 !!strstr(m_description, "Alps BSBE2") ||
2345 !!strstr(m_description, "Alps -S") ||
2346 !!strstr(m_description, "BCM4501");
2347 m_can_handle_dvbs2 = !!strstr(m_description, "Alps BSBE2") || !!strstr(m_description, "BCM4501");
2348 eDebug("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2349 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2352 PyErr_SetString(PyExc_StandardError,
2353 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");