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()
208 :m_type(-1), m_flags(0)
212 DEFINE_REF(eDVBFrontendParameters);
214 RESULT eDVBFrontendParameters::getSystem(int &t) const
222 RESULT eDVBFrontendParameters::getDVBS(eDVBFrontendParametersSatellite &p) const
224 if (m_type != iDVBFrontend::feSatellite)
230 RESULT eDVBFrontendParameters::getDVBC(eDVBFrontendParametersCable &p) const
232 if (m_type != iDVBFrontend::feCable)
238 RESULT eDVBFrontendParameters::getDVBT(eDVBFrontendParametersTerrestrial &p) const
240 if (m_type != iDVBFrontend::feTerrestrial)
246 RESULT eDVBFrontendParameters::setDVBS(const eDVBFrontendParametersSatellite &p, bool no_rotor_command_on_tune)
249 sat.no_rotor_command_on_tune = no_rotor_command_on_tune;
250 m_type = iDVBFrontend::feSatellite;
254 RESULT eDVBFrontendParameters::setDVBC(const eDVBFrontendParametersCable &p)
257 m_type = iDVBFrontend::feCable;
261 RESULT eDVBFrontendParameters::setDVBT(const eDVBFrontendParametersTerrestrial &p)
264 m_type = iDVBFrontend::feTerrestrial;
268 RESULT eDVBFrontendParameters::calculateDifference(const iDVBFrontendParameters *parm, int &diff, bool exact) const
273 if (parm->getSystem(type))
277 diff = 1<<30; // big difference
283 case iDVBFrontend::feSatellite:
285 eDVBFrontendParametersSatellite osat;
286 if (parm->getDVBS(osat))
289 if (sat.orbital_position != osat.orbital_position)
291 else if (sat.polarisation != osat.polarisation)
293 else if (exact && sat.fec != osat.fec && sat.fec != eDVBFrontendParametersSatellite::FEC::fAuto && osat.fec != eDVBFrontendParametersSatellite::FEC::fAuto)
295 else if (exact && sat.modulation != osat.modulation && sat.modulation != eDVBFrontendParametersSatellite::Modulation::Auto && osat.modulation != eDVBFrontendParametersSatellite::Modulation::Auto)
299 diff = abs(sat.frequency - osat.frequency);
300 diff += abs(sat.symbol_rate - osat.symbol_rate);
304 case iDVBFrontend::feCable:
305 eDVBFrontendParametersCable ocable;
306 if (parm->getDVBC(ocable))
309 if (exact && cable.modulation != ocable.modulation
310 && cable.modulation != eDVBFrontendParametersCable::Modulation::Auto
311 && ocable.modulation != eDVBFrontendParametersCable::Modulation::Auto)
313 else if (exact && cable.fec_inner != ocable.fec_inner && cable.fec_inner != eDVBFrontendParametersCable::FEC::fAuto && ocable.fec_inner != eDVBFrontendParametersCable::FEC::fAuto)
317 diff = abs(cable.frequency - ocable.frequency);
318 diff += abs(cable.symbol_rate - ocable.symbol_rate);
321 case iDVBFrontend::feTerrestrial:
322 eDVBFrontendParametersTerrestrial oterrestrial;
323 if (parm->getDVBT(oterrestrial))
327 if (exact && oterrestrial.bandwidth != terrestrial.bandwidth &&
328 oterrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto &&
329 terrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto)
331 else if (exact && oterrestrial.modulation != terrestrial.modulation &&
332 oterrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation::Auto &&
333 terrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation::Auto)
335 else if (exact && oterrestrial.transmission_mode != terrestrial.transmission_mode &&
336 oterrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto &&
337 terrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto)
339 else if (exact && oterrestrial.guard_interval != terrestrial.guard_interval &&
340 oterrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto &&
341 terrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto)
343 else if (exact && oterrestrial.hierarchy != terrestrial.hierarchy &&
344 oterrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy::HAuto &&
345 terrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy::HAuto)
347 else if (exact && oterrestrial.code_rate_LP != terrestrial.code_rate_LP &&
348 oterrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC::fAuto &&
349 terrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC::fAuto)
351 else if (exact && oterrestrial.code_rate_HP != terrestrial.code_rate_HP &&
352 oterrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC::fAuto &&
353 terrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC::fAuto)
356 diff = abs(terrestrial.frequency - oterrestrial.frequency);
364 RESULT eDVBFrontendParameters::getHash(unsigned long &hash) const
368 case iDVBFrontend::feSatellite:
370 hash = (sat.orbital_position << 16);
371 hash |= ((sat.frequency/1000)&0xFFFF)|((sat.polarisation&1) << 15);
374 case iDVBFrontend::feCable:
376 hash |= (cable.frequency/1000)&0xFFFF;
378 case iDVBFrontend::feTerrestrial:
380 hash |= (terrestrial.frequency/1000)&0xFFFF;
387 RESULT eDVBFrontendParameters::calcLockTimeout(unsigned int &timeout) const
391 case iDVBFrontend::feSatellite:
393 /* high symbol rate transponders tune faster, due to
394 requiring less zigzag and giving more symbols faster.
396 5s are definitely not enough on really low SR when
397 zigzag has to find the exact frequency first.
399 if (sat.symbol_rate > 20000000)
401 else if (sat.symbol_rate > 10000000)
407 case iDVBFrontend::feCable:
410 case iDVBFrontend::feTerrestrial:
418 DEFINE_REF(eDVBFrontend);
420 int eDVBFrontend::PriorityOrder=0;
422 eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok)
423 :m_enabled(false), m_type(-1), m_dvbid(fe), m_slotid(fe)
424 ,m_fd(-1), m_need_rotor_workaround(false), m_can_handle_dvbs2(false)
425 ,m_sn(0), m_timeout(0), m_tuneTimer(0)
426 #if HAVE_DVB_API_VERSION < 3
430 #if HAVE_DVB_API_VERSION < 3
431 sprintf(m_filename, "/dev/dvb/card%d/frontend%d", adap, fe);
432 sprintf(m_sec_filename, "/dev/dvb/card%d/sec%d", adap, fe);
434 sprintf(m_filename, "/dev/dvb/adapter%d/frontend%d", adap, fe);
436 m_timeout = new eTimer(eApp);
437 CONNECT(m_timeout->timeout, eDVBFrontend::timeout);
439 m_tuneTimer = new eTimer(eApp);
440 CONNECT(m_tuneTimer->timeout, eDVBFrontend::tuneLoop);
442 for (int i=0; i<eDVBFrontend::NUM_DATA_ENTRIES; ++i)
445 m_idleInputpower[0]=m_idleInputpower[1]=0;
447 ok = !openFrontend();
451 int eDVBFrontend::openFrontend()
454 return -1; // already opened
459 #if HAVE_DVB_API_VERSION < 3
460 FrontendInfo fe_info;
462 dvb_frontend_info fe_info;
464 eDebug("opening frontend %d", m_dvbid);
467 m_fd = ::open(m_filename, O_RDWR|O_NONBLOCK);
470 eWarning("failed! (%s) %m", m_filename);
475 eWarning("frontend %d already opened", m_dvbid);
478 if (::ioctl(m_fd, FE_GET_INFO, &fe_info) < 0)
480 eWarning("ioctl FE_GET_INFO failed");
486 switch (fe_info.type)
489 m_type = iDVBFrontend::feSatellite;
492 m_type = iDVBFrontend::feCable;
495 m_type = iDVBFrontend::feTerrestrial;
498 eWarning("unknown frontend type.");
503 eDebug("detected %s frontend", "satellite\0cable\0 terrestrial"+fe_info.type*10);
506 #if HAVE_DVB_API_VERSION < 3
507 if (m_type == iDVBFrontend::feSatellite)
511 m_secfd = ::open(m_sec_filename, O_RDWR);
514 eWarning("failed! (%s) %m", m_sec_filename);
521 eWarning("sec %d already opened", m_dvbid);
525 setTone(iDVBFrontend::toneOff);
526 setVoltage(iDVBFrontend::voltageOff);
528 m_sn = new eSocketNotifier(eApp, m_fd, eSocketNotifier::Read, false);
529 CONNECT(m_sn->activated, eDVBFrontend::feEvent);
534 int eDVBFrontend::closeFrontend(bool force)
536 if (!force && m_data[CUR_VOLTAGE] != -1 && m_data[CUR_VOLTAGE] != iDVBFrontend::voltageOff)
538 long tmp = m_data[LINKED_NEXT_PTR];
541 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
542 if (linked_fe->m_inuse)
544 eDebug("dont close frontend %d until the linked frontend %d in slot %d is still in use",
545 m_dvbid, linked_fe->m_frontend->getDVBID(), linked_fe->m_frontend->getSlotID());
548 linked_fe->m_frontend->getData(LINKED_NEXT_PTR, tmp);
553 eDebug("close frontend %d", m_dvbid);
555 setTone(iDVBFrontend::toneOff);
556 setVoltage(iDVBFrontend::voltageOff);
558 m_sec->setRotorMoving(false);
562 eWarning("couldnt close frontend %d", m_dvbid);
564 #if HAVE_DVB_API_VERSION < 3
567 if (!::close(m_secfd))
570 eWarning("couldnt close sec %d", m_dvbid);
575 m_state = stateClosed;
580 eDVBFrontend::~eDVBFrontend()
582 m_data[LINKED_PREV_PTR] = m_data[LINKED_NEXT_PTR] = -1;
588 void eDVBFrontend::feEvent(int w)
590 eDVBFrontend *sec_fe = this;
591 long tmp = m_data[LINKED_PREV_PTR];
594 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
595 sec_fe = linked_fe->m_frontend;
596 sec_fe->getData(LINKED_NEXT_PTR, tmp);
600 #if HAVE_DVB_API_VERSION < 3
603 dvb_frontend_event event;
607 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
609 if (res && (errno == EAGAIN))
614 eWarning("FE_GET_EVENT failed! %m");
621 #if HAVE_DVB_API_VERSION < 3
622 if (event.type == FE_COMPLETION_EV)
624 eDebug("(%d)fe event: status %x, inversion %s", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off");
625 if (event.status & FE_HAS_LOCK)
635 eDebug("stateLostLock");
636 state = stateLostLock;
637 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
640 if (m_state != state)
643 m_stateChanged(this);
648 void eDVBFrontend::timeout()
651 if (m_state == stateTuning)
653 m_state = stateFailed;
654 m_stateChanged(this);
658 #define INRANGE(X,Y,Z) (((X<=Y) && (Y<=Z))||((Z<=Y) && (Y<=X)) ? 1 : 0)
660 int eDVBFrontend::readFrontendData(int type)
667 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
668 eDebug("FE_READ_BER failed (%m)");
674 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
675 eDebug("FE_READ_SNR failed (%m)");
678 case signalQualitydB: /* this will move into the driver */
681 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
682 eDebug("FE_READ_SNR failed (%m)");
683 if (!strcmp(m_description, "BCM4501 (internal)"))
685 unsigned int SDS_SNRE = snr << 16;
687 static float SNR_COEFF[6] = {
690 197418.0 / 4194304.0,
691 -2602183.0 / 4194304.0,
692 20377212.0 / 4194304.0,
693 -37791203.0 / 4194304.0,
696 float fval1, fval2, snr_in_db;
698 fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0));
699 fval2 = pow(10.0, fval1)-1;
700 fval1 = 10.0 * log10(fval2);
704 fval2 = SNR_COEFF[0];
708 fval2 += SNR_COEFF[i];
714 return (int)(snr_in_db * 100.0);
716 else if (strstr(m_description, "Alps BSBE1 C01A") ||
717 !strcmp(m_description, "Alps -S(STV0288)"))
721 else if (snr == 0xFFFF) // i think this should not happen
725 enum { REALVAL, REGVAL };
726 const long CN_lookup[31][2] = {
727 {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
728 {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
729 {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
730 {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
731 {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
732 {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
735 int add=strchr(m_description, '.') ? 0xA250 : 0xA100;
736 long regval = 0xFFFF - ((snr / 3) + add), // 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 setSecSequencePos(m_sec_sequence.current()->steps);
1463 ++m_sec_sequence.current();
1465 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1467 int idx = m_sec_sequence.current()++->val;
1468 if ( idx == 0 || idx == 1 )
1470 m_idleInputpower[idx] = sec_fe->readInputpower();
1471 eDebug("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1474 eDebug("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1477 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1479 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1480 int idx = compare.val;
1481 if ( idx == 0 || idx == 1 )
1483 int idle = sec_fe->readInputpower();
1484 int diff = abs(idle-m_idleInputpower[idx]);
1487 eDebug("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1488 setSecSequencePos(compare.steps);
1492 ++m_sec_sequence.current();
1495 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1498 int isLocked = readFrontendData(locked);
1499 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1500 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1501 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 50) || !cmd.lastSignal))
1504 eDebug("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1507 eDebug("[SEC] locked step %d ok", cmd.okcount);
1508 cmd.lastSignal = signal;
1511 if (cmd.okcount > 4)
1513 eDebug("ok > 4 .. goto %d\n",cmd.steps);
1514 setSecSequencePos(cmd.steps);
1515 m_state = stateLock;
1516 m_stateChanged(this);
1525 eDebug("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1527 eDebug("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1529 if (!m_timeoutCount && m_retryCount > 0)
1534 ++m_sec_sequence.current();
1537 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1538 m_runningInputpower = sec_fe->readInputpower();
1539 eDebug("[SEC] runningInputpower is %d", m_runningInputpower);
1540 ++m_sec_sequence.current();
1542 case eSecCommand::SET_ROTOR_MOVING:
1543 m_sec->setRotorMoving(true);
1544 ++m_sec_sequence.current();
1546 case eSecCommand::SET_ROTOR_STOPPED:
1547 m_sec->setRotorMoving(false);
1548 ++m_sec_sequence.current();
1550 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1552 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1553 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1554 const char *txt = cmd.direction ? "running" : "stopped";
1555 eDebug("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1557 m_runningInputpower,
1560 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1561 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1564 eDebug("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1565 if ( cmd.okcount > 6 )
1567 eDebug("[SEC] rotor is %s", txt);
1568 if (setSecSequencePos(cmd.steps))
1574 eDebug("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1576 if (!m_timeoutCount && m_retryCount > 0)
1580 ++m_sec_sequence.current();
1583 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1584 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1585 setSecSequencePos(m_sec_sequence.current()->steps);
1587 ++m_sec_sequence.current();
1589 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1590 eDebug("[SEC] invalidate current switch params");
1591 sec_fe_data[CSW] = -1;
1592 sec_fe_data[UCSW] = -1;
1593 sec_fe_data[TONEBURST] = -1;
1594 ++m_sec_sequence.current();
1596 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1597 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1598 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1599 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1600 eDebug("[SEC] update current switch params");
1601 ++m_sec_sequence.current();
1603 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1604 eDebug("[SEC] invalidate current rotorparams");
1605 sec_fe_data[ROTOR_CMD] = -1;
1606 sec_fe_data[ROTOR_POS] = -1;
1607 ++m_sec_sequence.current();
1609 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1610 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1611 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1612 eDebug("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1613 ++m_sec_sequence.current();
1615 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1616 m_retryCount = m_sec_sequence.current()++->val;
1617 eDebug("[SEC] set rotor retries %d", m_retryCount);
1619 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1622 eDebug("[SEC] no more rotor retrys");
1623 setSecSequencePos(m_sec_sequence.current()->steps);
1626 ++m_sec_sequence.current();
1628 case eSecCommand::SET_POWER_LIMITING_MODE:
1631 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1632 FILE *f=fopen(proc_name, "w");
1633 if (f) // new interface exist?
1635 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1636 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1637 eDebug("write %s failed!! (%m)", proc_name);
1639 eDebug("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1642 else if (sec_fe->m_need_rotor_workaround)
1645 int slotid = sec_fe->m_slotid;
1646 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1648 sprintf(dev, "/dev/i2c/%d", slotid);
1649 else if (slotid == 2)
1650 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1651 else if (slotid == 3)
1652 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1653 int fd = ::open(dev, O_RDWR);
1655 unsigned char data[2];
1656 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1657 if(::read(fd, data, 1) != 1)
1658 eDebug("[SEC] error read lnbp (%m)");
1659 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1661 data[0] |= 0x80; // enable static current limiting
1662 eDebug("[SEC] set static current limiting");
1666 data[0] &= ~0x80; // enable dynamic current limiting
1667 eDebug("[SEC] set dynamic current limiting");
1669 if(::write(fd, data, 1) != 1)
1670 eDebug("[SEC] error write lnbp (%m)");
1673 ++m_sec_sequence.current();
1677 eDebug("[SEC] unhandled sec command %d",
1678 ++m_sec_sequence.current()->cmd);
1679 ++m_sec_sequence.current();
1681 m_tuneTimer->start(delay,true);
1687 void eDVBFrontend::setFrontend()
1689 eDebug("setting frontend %d", m_dvbid);
1692 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1694 perror("FE_SET_FRONTEND failed");
1699 RESULT eDVBFrontend::getFrontendType(int &t)
1707 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1712 eWarning("no SEC module active!");
1715 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1718 eDebug("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1721 feparm.polarisation,
1725 feparm.orbital_position);
1726 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1727 switch (feparm.inversion)
1729 case eDVBFrontendParametersSatellite::Inversion::On:
1730 parm_inversion = INVERSION_ON;
1732 case eDVBFrontendParametersSatellite::Inversion::Off:
1733 parm_inversion = INVERSION_OFF;
1736 case eDVBFrontendParametersSatellite::Inversion::Unknown:
1737 parm_inversion = INVERSION_AUTO;
1740 if (feparm.system == eDVBFrontendParametersSatellite::System::DVB_S)
1743 case eDVBFrontendParametersSatellite::FEC::fNone:
1744 parm_u_qpsk_fec_inner = FEC_NONE;
1746 case eDVBFrontendParametersSatellite::FEC::f1_2:
1747 parm_u_qpsk_fec_inner = FEC_1_2;
1749 case eDVBFrontendParametersSatellite::FEC::f2_3:
1750 parm_u_qpsk_fec_inner = FEC_2_3;
1752 case eDVBFrontendParametersSatellite::FEC::f3_4:
1753 parm_u_qpsk_fec_inner = FEC_3_4;
1755 case eDVBFrontendParametersSatellite::FEC::f5_6:
1756 parm_u_qpsk_fec_inner = FEC_5_6;
1758 case eDVBFrontendParametersSatellite::FEC::f7_8:
1759 parm_u_qpsk_fec_inner = FEC_7_8;
1762 eDebug("no valid fec for DVB-S set.. assume auto");
1763 case eDVBFrontendParametersSatellite::FEC::fAuto:
1764 parm_u_qpsk_fec_inner = FEC_AUTO;
1767 #if HAVE_DVB_API_VERSION >= 3
1772 case eDVBFrontendParametersSatellite::FEC::f1_2:
1773 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1775 case eDVBFrontendParametersSatellite::FEC::f2_3:
1776 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1778 case eDVBFrontendParametersSatellite::FEC::f3_4:
1779 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1781 case eDVBFrontendParametersSatellite::FEC::f3_5:
1782 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1784 case eDVBFrontendParametersSatellite::FEC::f4_5:
1785 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1787 case eDVBFrontendParametersSatellite::FEC::f5_6:
1788 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1790 case eDVBFrontendParametersSatellite::FEC::f7_8:
1791 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1793 case eDVBFrontendParametersSatellite::FEC::f8_9:
1794 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1796 case eDVBFrontendParametersSatellite::FEC::f9_10:
1797 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1800 eDebug("no valid fec for DVB-S2 set.. abort !!");
1803 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1804 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK) {
1805 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1806 // 8PSK fec driver values are decimal 9 bigger
1807 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1811 // FIXME !!! get frequency range from tuner
1812 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1814 eDebug("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1817 eDebug("tuning to %d mhz", parm_frequency/1000);
1822 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1824 #if HAVE_DVB_API_VERSION < 3
1825 parm_frequency = feparm.frequency;
1827 parm_frequency = feparm.frequency * 1000;
1829 parm_u_qam_symbol_rate = feparm.symbol_rate;
1830 switch (feparm.modulation)
1832 case eDVBFrontendParametersCable::Modulation::QAM16:
1833 parm_u_qam_modulation = QAM_16;
1835 case eDVBFrontendParametersCable::Modulation::QAM32:
1836 parm_u_qam_modulation = QAM_32;
1838 case eDVBFrontendParametersCable::Modulation::QAM64:
1839 parm_u_qam_modulation = QAM_64;
1841 case eDVBFrontendParametersCable::Modulation::QAM128:
1842 parm_u_qam_modulation = QAM_128;
1844 case eDVBFrontendParametersCable::Modulation::QAM256:
1845 parm_u_qam_modulation = QAM_256;
1848 case eDVBFrontendParametersCable::Modulation::Auto:
1849 parm_u_qam_modulation = QAM_AUTO;
1852 switch (feparm.inversion)
1854 case eDVBFrontendParametersCable::Inversion::On:
1855 parm_inversion = INVERSION_ON;
1857 case eDVBFrontendParametersCable::Inversion::Off:
1858 parm_inversion = INVERSION_OFF;
1861 case eDVBFrontendParametersCable::Inversion::Unknown:
1862 parm_inversion = INVERSION_AUTO;
1865 switch (feparm.fec_inner)
1867 case eDVBFrontendParametersCable::FEC::fNone:
1868 parm_u_qam_fec_inner = FEC_NONE;
1870 case eDVBFrontendParametersCable::FEC::f1_2:
1871 parm_u_qam_fec_inner = FEC_1_2;
1873 case eDVBFrontendParametersCable::FEC::f2_3:
1874 parm_u_qam_fec_inner = FEC_2_3;
1876 case eDVBFrontendParametersCable::FEC::f3_4:
1877 parm_u_qam_fec_inner = FEC_3_4;
1879 case eDVBFrontendParametersCable::FEC::f5_6:
1880 parm_u_qam_fec_inner = FEC_5_6;
1882 case eDVBFrontendParametersCable::FEC::f7_8:
1883 parm_u_qam_fec_inner = FEC_7_8;
1885 #if HAVE_DVB_API_VERSION >= 3
1886 case eDVBFrontendParametersCable::FEC::f8_9:
1887 parm_u_qam_fec_inner = FEC_8_9;
1891 case eDVBFrontendParametersCable::FEC::fAuto:
1892 parm_u_qam_fec_inner = FEC_AUTO;
1895 eDebug("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
1896 parm_frequency/1000,
1897 parm_u_qam_symbol_rate,
1898 parm_u_qam_fec_inner,
1899 parm_u_qam_modulation,
1904 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
1906 parm_frequency = feparm.frequency;
1908 switch (feparm.bandwidth)
1910 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
1911 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
1913 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
1914 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
1916 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
1917 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
1920 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
1921 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
1924 switch (feparm.code_rate_LP)
1926 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1927 parm_u_ofdm_code_rate_LP = FEC_1_2;
1929 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1930 parm_u_ofdm_code_rate_LP = FEC_2_3;
1932 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1933 parm_u_ofdm_code_rate_LP = FEC_3_4;
1935 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1936 parm_u_ofdm_code_rate_LP = FEC_5_6;
1938 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1939 parm_u_ofdm_code_rate_LP = FEC_7_8;
1942 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1943 parm_u_ofdm_code_rate_LP = FEC_AUTO;
1946 switch (feparm.code_rate_HP)
1948 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1949 parm_u_ofdm_code_rate_HP = FEC_1_2;
1951 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1952 parm_u_ofdm_code_rate_HP = FEC_2_3;
1954 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1955 parm_u_ofdm_code_rate_HP = FEC_3_4;
1957 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1958 parm_u_ofdm_code_rate_HP = FEC_5_6;
1960 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1961 parm_u_ofdm_code_rate_HP = FEC_7_8;
1964 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1965 parm_u_ofdm_code_rate_HP = FEC_AUTO;
1968 switch (feparm.modulation)
1970 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
1971 parm_u_ofdm_constellation = QPSK;
1973 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
1974 parm_u_ofdm_constellation = QAM_16;
1976 case eDVBFrontendParametersTerrestrial::Modulation::QAM64:
1977 parm_u_ofdm_constellation = QAM_64;
1980 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
1981 parm_u_ofdm_constellation = QAM_AUTO;
1984 switch (feparm.transmission_mode)
1986 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
1987 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
1989 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
1990 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
1993 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
1994 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
1997 switch (feparm.guard_interval)
1999 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32:
2000 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2002 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16:
2003 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2005 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8:
2006 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2008 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4:
2009 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2012 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto:
2013 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2016 switch (feparm.hierarchy)
2018 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone:
2019 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2021 case eDVBFrontendParametersTerrestrial::Hierarchy::H1:
2022 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2024 case eDVBFrontendParametersTerrestrial::Hierarchy::H2:
2025 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2027 case eDVBFrontendParametersTerrestrial::Hierarchy::H4:
2028 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2031 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto:
2032 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2035 switch (feparm.inversion)
2037 case eDVBFrontendParametersTerrestrial::Inversion::On:
2038 parm_inversion = INVERSION_ON;
2040 case eDVBFrontendParametersTerrestrial::Inversion::Off:
2041 parm_inversion = INVERSION_OFF;
2044 case eDVBFrontendParametersTerrestrial::Inversion::Unknown:
2045 parm_inversion = INVERSION_AUTO;
2051 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2053 unsigned int timeout = 5000;
2054 eDebug("(%d)tune", m_dvbid);
2062 eDebug("no frontend device opened... do not try to tune !!!");
2074 m_sec_sequence.clear();
2076 where.calcLockTimeout(timeout);
2082 eDVBFrontendParametersSatellite feparm;
2083 if (where.getDVBS(feparm))
2085 eDebug("no dvbs data!");
2089 m_sec->setRotorMoving(false);
2090 res=prepare_sat(feparm, timeout);
2098 eDVBFrontendParametersCable feparm;
2099 if (where.getDVBC(feparm))
2104 res=prepare_cable(feparm);
2108 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2109 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2114 eDVBFrontendParametersTerrestrial feparm;
2115 if (where.getDVBT(feparm))
2117 eDebug("no -T data");
2121 res=prepare_terrestrial(feparm);
2125 std::string enable_5V;
2126 char configStr[255];
2127 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2128 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2129 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2130 if (enable_5V == "True")
2131 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2133 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2134 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2140 m_tuneTimer->start(0,true);
2141 m_sec_sequence.current() = m_sec_sequence.begin();
2143 if (m_state != stateTuning)
2146 m_state = stateTuning;
2147 m_stateChanged(this);
2153 m_tuneTimer->stop();
2157 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2159 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2163 RESULT eDVBFrontend::setVoltage(int voltage)
2165 if (m_type == feCable)
2167 #if HAVE_DVB_API_VERSION < 3
2170 bool increased=false;
2171 fe_sec_voltage_t vlt;
2173 m_data[CUR_VOLTAGE]=voltage;
2177 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2178 vlt = SEC_VOLTAGE_OFF;
2181 #if HAVE_DVB_API_VERSION < 3
2182 vlt = SEC_VOLTAGE_13_5;
2188 vlt = SEC_VOLTAGE_13;
2191 #if HAVE_DVB_API_VERSION < 3
2192 vlt = SEC_VOLTAGE_18_5;
2198 vlt = SEC_VOLTAGE_18;
2203 #if HAVE_DVB_API_VERSION < 3
2204 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2206 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2207 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2208 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2212 RESULT eDVBFrontend::getState(int &state)
2218 RESULT eDVBFrontend::setTone(int t)
2220 if (m_type != feSatellite)
2222 #if HAVE_DVB_API_VERSION < 3
2225 fe_sec_tone_mode_t tone;
2234 tone = SEC_TONE_OFF;
2239 #if HAVE_DVB_API_VERSION < 3
2240 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2242 return ::ioctl(m_fd, FE_SET_TONE, tone);
2246 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2247 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2250 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2252 #if HAVE_DVB_API_VERSION < 3
2253 struct secCommand cmd;
2254 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2255 cmd.u.diseqc.cmdtype = diseqc.data[0];
2256 cmd.u.diseqc.addr = diseqc.data[1];
2257 cmd.u.diseqc.cmd = diseqc.data[2];
2258 cmd.u.diseqc.numParams = diseqc.len-3;
2259 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2260 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2262 struct dvb_diseqc_master_cmd cmd;
2263 memcpy(cmd.msg, diseqc.data, diseqc.len);
2264 cmd.msg_len = diseqc.len;
2265 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2271 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2272 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2274 RESULT eDVBFrontend::sendToneburst(int burst)
2276 #if HAVE_DVB_API_VERSION < 3
2277 secMiniCmd cmd = SEC_MINI_NONE;
2279 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2281 if ( burst == eDVBSatelliteDiseqcParameters::A )
2283 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2285 #if HAVE_DVB_API_VERSION < 3
2286 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2289 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2295 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2301 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2303 m_sec_sequence = list;
2307 RESULT eDVBFrontend::getData(int num, long &data)
2309 if ( num < NUM_DATA_ENTRIES )
2317 RESULT eDVBFrontend::setData(int num, long val)
2319 if ( num < NUM_DATA_ENTRIES )
2327 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2330 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2332 if (m_type == eDVBFrontend::feSatellite)
2335 eDVBFrontendParametersSatellite sat_parm;
2336 int ret = feparm->getDVBS(sat_parm);
2338 if (sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S2 && !m_can_handle_dvbs2)
2340 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2341 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S && m_can_handle_dvbs2)
2345 else if (m_type == eDVBFrontend::feCable)
2346 return 2; // more prio for cable frontends
2347 else if (m_type == eDVBFrontend::feTerrestrial)
2352 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2354 ePyObject Id, Descr, Enabled, IsDVBS2;
2355 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4)
2357 Id = PyTuple_GET_ITEM(obj, 0);
2358 Descr = PyTuple_GET_ITEM(obj, 1);
2359 Enabled = PyTuple_GET_ITEM(obj, 2);
2360 IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2361 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2))
2363 strcpy(m_description, PyString_AS_STRING(Descr));
2364 m_slotid = PyInt_AsLong(Id);
2365 m_enabled = Enabled == Py_True;
2366 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2367 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2368 !!strstr(m_description, "Alps BSBE2") ||
2369 !!strstr(m_description, "Alps -S") ||
2370 !!strstr(m_description, "BCM4501");
2371 m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2372 eDebug("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2373 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2376 PyErr_SetString(PyExc_StandardError,
2377 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");