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)
589 eDVBFrontend *sec_fe = this;
590 long tmp = m_data[LINKED_PREV_PTR];
593 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
594 sec_fe = linked_fe->m_frontend;
595 sec_fe->getData(LINKED_NEXT_PTR, tmp);
599 #if HAVE_DVB_API_VERSION < 3
602 dvb_frontend_event event;
606 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
608 if (res && (errno == EAGAIN))
613 eWarning("FE_GET_EVENT failed! %m");
620 #if HAVE_DVB_API_VERSION < 3
621 if (event.type == FE_COMPLETION_EV)
623 eDebug("(%d)fe event: status %x, inversion %s", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off");
624 if (event.status & FE_HAS_LOCK)
634 eDebug("stateLostLock");
635 state = stateLostLock;
636 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
639 if (m_state != state && ((m_idleInputpower[0] && m_idleInputpower[1]) || (sec_fe->m_data[ROTOR_POS] == sec_fe->m_data[NEW_ROTOR_POS])))
642 m_stateChanged(this);
647 void eDVBFrontend::timeout()
650 if (m_state == stateTuning)
652 m_state = stateFailed;
653 m_stateChanged(this);
657 #define INRANGE(X,Y,Z) (((X<=Y) && (Y<=Z))||((Z<=Y) && (Y<=X)) ? 1 : 0)
659 int eDVBFrontend::readFrontendData(int type)
666 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
667 eDebug("FE_READ_BER failed (%m)");
673 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
674 eDebug("FE_READ_SNR failed (%m)");
677 case signalQualitydB: /* this will move into the driver */
680 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
681 eDebug("FE_READ_SNR failed (%m)");
682 if (!strcmp(m_description, "BCM4501 (internal)"))
684 unsigned int SDS_SNRE = snr << 16;
686 static float SNR_COEFF[6] = {
689 197418.0 / 4194304.0,
690 -2602183.0 / 4194304.0,
691 20377212.0 / 4194304.0,
692 -37791203.0 / 4194304.0,
695 float fval1, fval2, snr_in_db;
697 fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0));
698 fval2 = pow(10.0, fval1)-1;
699 fval1 = 10.0 * log10(fval2);
703 fval2 = SNR_COEFF[0];
707 fval2 += SNR_COEFF[i];
713 return (int)(snr_in_db * 100.0);
715 else if (strstr(m_description, "Alps BSBE1 C01A") ||
716 !strcmp(m_description, "Alps -S(STV0288)"))
720 else if (snr == 0xFFFF) // i think this should not happen
724 enum { REALVAL, REGVAL };
725 const long CN_lookup[31][2] = {
726 {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
727 {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
728 {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
729 {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
730 {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
731 {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
734 long regval = 0xFFFF - ((snr / 3) + 0xA100), // revert some dvb api calulations to get the real register value
738 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
744 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[i][REGVAL]))
749 return (((regval - CN_lookup[Imin][REGVAL])
750 * (CN_lookup[Imax][REALVAL] - CN_lookup[Imin][REALVAL])
751 / (CN_lookup[Imax][REGVAL] - CN_lookup[Imin][REGVAL]))
752 + CN_lookup[Imin][REALVAL]) * 10;
758 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
759 !strcmp(m_description, "Alps -S") ||
760 !strcmp(m_description, "Philips -S") ||
761 !strcmp(m_description, "LG -S") )
763 float snr_in_db=(snr-39075)/1764.7;
764 return (int)(snr_in_db * 100.0);
765 } else if (!strcmp(m_description, "Alps BSBE2"))
767 return (int)((snr >> 7) * 10.0);
769 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
775 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
776 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
781 #if HAVE_DVB_API_VERSION < 3
782 FrontendStatus status=0;
786 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
787 eDebug("FE_READ_STATUS failed (%m)");
788 return !!(status&FE_HAS_LOCK);
792 #if HAVE_DVB_API_VERSION < 3
793 FrontendStatus status=0;
797 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
798 eDebug("FE_READ_STATUS failed (%m)");
799 return !!(status&FE_HAS_SYNC);
807 void PutToDict(ePyObject &dict, const char*key, long value)
809 ePyObject item = PyInt_FromLong(value);
812 if (PyDict_SetItemString(dict, key, item))
813 eDebug("put %s to dict failed", key);
817 eDebug("could not create PyObject for %s", key);
820 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
824 if (PyDict_SetItemString(dict, key, item))
825 eDebug("put %s to dict failed", key);
829 eDebug("invalid PyObject for %s", key);
832 void PutToDict(ePyObject &dict, const char*key, const char *value)
834 ePyObject item = PyString_FromString(value);
837 if (PyDict_SetItemString(dict, key, item))
838 eDebug("put %s to dict failed", key);
842 eDebug("could not create PyObject for %s", key);
845 void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, eDVBFrontend *fe)
849 fe->getData(eDVBFrontend::FREQ_OFFSET, freq_offset);
850 int frequency = parm_frequency + freq_offset;
851 PutToDict(dict, "frequency", frequency);
852 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
853 switch(parm_u_qpsk_fec_inner)
876 #if HAVE_DVB_API_VERSION >=3
877 case FEC_S2_8PSK_1_2:
878 case FEC_S2_QPSK_1_2:
881 case FEC_S2_8PSK_2_3:
882 case FEC_S2_QPSK_2_3:
885 case FEC_S2_8PSK_3_4:
886 case FEC_S2_QPSK_3_4:
889 case FEC_S2_8PSK_5_6:
890 case FEC_S2_QPSK_5_6:
893 case FEC_S2_8PSK_7_8:
894 case FEC_S2_QPSK_7_8:
897 case FEC_S2_8PSK_8_9:
898 case FEC_S2_QPSK_8_9:
901 case FEC_S2_8PSK_3_5:
902 case FEC_S2_QPSK_3_5:
905 case FEC_S2_8PSK_4_5:
906 case FEC_S2_QPSK_4_5:
909 case FEC_S2_8PSK_9_10:
910 case FEC_S2_QPSK_9_10:
915 PutToDict(dict, "fec_inner", tmp);
916 #if HAVE_DVB_API_VERSION >=3
917 PutToDict(dict, "modulation",
918 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ? "8PSK": "QPSK" );
919 if (parm_u_qpsk_fec_inner > FEC_AUTO)
921 switch(parm_inversion & 0xc)
923 default: // unknown rolloff
925 tmp = "ROLLOFF_0_35";
928 tmp = "ROLLOFF_0_25";
931 tmp = "ROLLOFF_0_20";
934 PutToDict(dict, "rolloff", tmp);
935 if (parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10)
937 switch(parm_inversion & 0x30)
942 case 0x10: // pilot on
945 case 0x20: // pilot auto
949 PutToDict(dict, "pilot", tmp);
956 PutToDict(dict, "modulation", "QPSK" );
959 PutToDict(dict, "system", tmp);
962 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
965 #if HAVE_DVB_API_VERSION < 3
966 PutToDict(dict, "frequency", parm_frequency);
968 PutToDict(dict, "frequency", parm_frequency/1000);
970 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
971 switch(parm_u_qam_fec_inner)
991 #if HAVE_DVB_API_VERSION >= 3
1001 PutToDict(dict, "fec_inner", tmp);
1002 switch(parm_u_qam_modulation)
1024 PutToDict(dict, "modulation", tmp);
1027 void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1030 PutToDict(dict, "frequency", parm_frequency);
1031 switch (parm_u_ofdm_bandwidth)
1033 case BANDWIDTH_8_MHZ:
1034 tmp = "BANDWIDTH_8_MHZ";
1036 case BANDWIDTH_7_MHZ:
1037 tmp = "BANDWIDTH_7_MHZ";
1039 case BANDWIDTH_6_MHZ:
1040 tmp = "BANDWIDTH_6_MHZ";
1043 case BANDWIDTH_AUTO:
1044 tmp = "BANDWIDTH_AUTO";
1047 PutToDict(dict, "bandwidth", tmp);
1048 switch (parm_u_ofdm_code_rate_LP)
1070 PutToDict(dict, "code_rate_lp", tmp);
1071 switch (parm_u_ofdm_code_rate_HP)
1093 PutToDict(dict, "code_rate_hp", tmp);
1094 switch (parm_u_ofdm_constellation)
1110 PutToDict(dict, "constellation", tmp);
1111 switch (parm_u_ofdm_transmission_mode)
1113 case TRANSMISSION_MODE_2K:
1114 tmp = "TRANSMISSION_MODE_2K";
1116 case TRANSMISSION_MODE_8K:
1117 tmp = "TRANSMISSION_MODE_8K";
1120 case TRANSMISSION_MODE_AUTO:
1121 tmp = "TRANSMISSION_MODE_AUTO";
1124 PutToDict(dict, "transmission_mode", tmp);
1125 switch (parm_u_ofdm_guard_interval)
1127 case GUARD_INTERVAL_1_32:
1128 tmp = "GUARD_INTERVAL_1_32";
1130 case GUARD_INTERVAL_1_16:
1131 tmp = "GUARD_INTERVAL_1_16";
1133 case GUARD_INTERVAL_1_8:
1134 tmp = "GUARD_INTERVAL_1_8";
1136 case GUARD_INTERVAL_1_4:
1137 tmp = "GUARD_INTERVAL_1_4";
1140 case GUARD_INTERVAL_AUTO:
1141 tmp = "GUARD_INTERVAL_AUTO";
1144 PutToDict(dict, "guard_interval", tmp);
1145 switch (parm_u_ofdm_hierarchy_information)
1147 case HIERARCHY_NONE:
1148 tmp = "HIERARCHY_NONE";
1151 tmp = "HIERARCHY_1";
1154 tmp = "HIERARCHY_2";
1157 tmp = "HIERARCHY_4";
1160 case HIERARCHY_AUTO:
1161 tmp = "HIERARCHY_AUTO";
1164 PutToDict(dict, "hierarchy_information", tmp);
1167 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1169 if (dest && PyDict_Check(dest))
1171 const char *tmp = "UNKNOWN";
1192 PutToDict(dest, "tuner_state", tmp);
1193 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1194 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1195 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1196 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1197 int sigQualitydB = readFrontendData(signalQualitydB);
1198 if (sigQualitydB == 0x12345678) // not support yet
1200 ePyObject obj=Py_None;
1202 PutToDict(dest, "tuner_signal_quality_db", obj);
1205 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1206 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1210 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1212 if (m_fd != -1 && dest && PyDict_Check(dest))
1220 FRONTENDPARAMETERS front;
1221 if (!original && ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1222 eDebug("FE_GET_FRONTEND (%m)");
1225 const FRONTENDPARAMETERS &parm = original ? this->parm : front;
1226 const char *tmp = "INVERSION_AUTO";
1227 switch(parm_inversion)
1230 tmp = "INVERSION_ON";
1233 tmp = "INVERSION_OFF";
1239 PutToDict(dest, "inversion", tmp);
1244 fillDictWithSatelliteData(dest, original?parm:front, this);
1247 fillDictWithCableData(dest, original?parm:front);
1250 fillDictWithTerrestrialData(dest, original?parm:front);
1261 void eDVBFrontend::getFrontendData(ePyObject dest)
1263 if (dest && PyDict_Check(dest))
1266 PutToDict(dest, "tuner_number", m_slotid);
1282 PutToDict(dest, "tuner_type", tmp);
1286 #ifndef FP_IOCTL_GET_ID
1287 #define FP_IOCTL_GET_ID 0
1289 int eDVBFrontend::readInputpower()
1291 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1293 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1294 FILE *f=fopen(proc_name, "r");
1297 if (fscanf(f, "%d", &power) != 1)
1298 eDebug("read %s failed!! (%m)", proc_name);
1300 eDebug("%s is %d\n", proc_name, power);
1305 // open front prozessor
1306 int fp=::open("/dev/dbox/fp0", O_RDWR);
1309 eDebug("couldn't open fp");
1312 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1313 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1315 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1324 bool eDVBFrontend::setSecSequencePos(int steps)
1326 eDebug("set sequence pos %d", steps);
1331 if (m_sec_sequence.current() != m_sec_sequence.end())
1332 ++m_sec_sequence.current();
1337 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1338 --m_sec_sequence.current();
1344 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1347 eDVBFrontend *sec_fe = this;
1348 eDVBRegisteredFrontend *regFE = 0;
1349 long tmp = m_data[LINKED_PREV_PTR];
1352 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1353 sec_fe = prev->m_frontend;
1354 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1355 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1356 int state = sec_fe->m_state;
1357 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1359 sec_fe->closeFrontend(true);
1360 state = sec_fe->m_state;
1362 if (state == eDVBFrontend::stateClosed)
1370 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1372 long *sec_fe_data = sec_fe->m_data;
1373 // eDebug("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1374 switch (m_sec_sequence.current()->cmd)
1376 case eSecCommand::SLEEP:
1377 delay = m_sec_sequence.current()++->msec;
1378 eDebug("[SEC] sleep %dms", delay);
1380 case eSecCommand::GOTO:
1381 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1382 ++m_sec_sequence.current();
1384 case eSecCommand::SET_VOLTAGE:
1386 int voltage = m_sec_sequence.current()++->voltage;
1387 eDebug("[SEC] setVoltage %d", voltage);
1388 sec_fe->setVoltage(voltage);
1391 case eSecCommand::IF_VOLTAGE_GOTO:
1393 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1394 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1396 ++m_sec_sequence.current();
1399 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1401 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1402 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1404 ++m_sec_sequence.current();
1407 case eSecCommand::IF_TONE_GOTO:
1409 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1410 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1412 ++m_sec_sequence.current();
1415 case eSecCommand::IF_NOT_TONE_GOTO:
1417 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1418 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1420 ++m_sec_sequence.current();
1423 case eSecCommand::SET_TONE:
1424 eDebug("[SEC] setTone %d", m_sec_sequence.current()->tone);
1425 sec_fe->setTone(m_sec_sequence.current()++->tone);
1427 case eSecCommand::SEND_DISEQC:
1428 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1429 eDebugNoNewLine("[SEC] sendDiseqc: ");
1430 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1431 eDebugNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1433 ++m_sec_sequence.current();
1435 case eSecCommand::SEND_TONEBURST:
1436 eDebug("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1437 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1439 case eSecCommand::SET_FRONTEND:
1440 eDebug("[SEC] setFrontend");
1442 ++m_sec_sequence.current();
1444 case eSecCommand::START_TUNE_TIMEOUT:
1446 m_timeout->start(m_sec_sequence.current()->timeout, 1);
1447 ++m_sec_sequence.current();
1450 case eSecCommand::SET_TIMEOUT:
1451 m_timeoutCount = m_sec_sequence.current()++->val;
1452 eDebug("[SEC] set timeout %d", m_timeoutCount);
1454 case eSecCommand::IF_TIMEOUT_GOTO:
1455 if (!m_timeoutCount)
1457 eDebug("[SEC] rotor timout");
1458 setSecSequencePos(m_sec_sequence.current()->steps);
1461 ++m_sec_sequence.current();
1463 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1465 int idx = m_sec_sequence.current()++->val;
1466 if ( idx == 0 || idx == 1 )
1468 m_idleInputpower[idx] = sec_fe->readInputpower();
1469 eDebug("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1472 eDebug("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1475 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1477 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1478 int idx = compare.val;
1479 if ( idx == 0 || idx == 1 )
1481 int idle = sec_fe->readInputpower();
1482 int diff = abs(idle-m_idleInputpower[idx]);
1485 eDebug("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1486 setSecSequencePos(compare.steps);
1490 ++m_sec_sequence.current();
1493 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1496 int isLocked = readFrontendData(locked);
1497 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1498 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1499 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 50) || !cmd.lastSignal))
1502 eDebug("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1505 eDebug("[SEC] locked step %d ok", cmd.okcount);
1506 cmd.lastSignal = signal;
1509 if (cmd.okcount > 4)
1511 eDebug("ok > 4 .. goto %d\n",cmd.steps);
1512 setSecSequencePos(cmd.steps);
1513 m_state = stateLock;
1514 m_stateChanged(this);
1521 eDebug("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1523 eDebug("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1525 if (!m_timeoutCount && m_retryCount > 0)
1530 ++m_sec_sequence.current();
1533 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1534 m_runningInputpower = sec_fe->readInputpower();
1535 eDebug("[SEC] runningInputpower is %d", m_runningInputpower);
1536 ++m_sec_sequence.current();
1538 case eSecCommand::SET_ROTOR_MOVING:
1539 m_sec->setRotorMoving(true);
1540 ++m_sec_sequence.current();
1542 case eSecCommand::SET_ROTOR_STOPPED:
1543 m_sec->setRotorMoving(false);
1544 ++m_sec_sequence.current();
1546 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1548 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1549 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1550 const char *txt = cmd.direction ? "running" : "stopped";
1551 eDebug("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1553 m_runningInputpower,
1556 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1557 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1560 eDebug("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1561 if ( cmd.okcount > 6 )
1563 eDebug("[SEC] rotor is %s", txt);
1564 if (setSecSequencePos(cmd.steps))
1570 eDebug("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1572 if (!m_timeoutCount && m_retryCount > 0)
1576 ++m_sec_sequence.current();
1579 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1580 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1581 setSecSequencePos(m_sec_sequence.current()->steps);
1583 ++m_sec_sequence.current();
1585 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1586 eDebug("[SEC] invalidate current switch params");
1587 sec_fe_data[CSW] = -1;
1588 sec_fe_data[UCSW] = -1;
1589 sec_fe_data[TONEBURST] = -1;
1590 ++m_sec_sequence.current();
1592 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1593 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1594 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1595 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1596 eDebug("[SEC] update current switch params");
1597 ++m_sec_sequence.current();
1599 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1600 eDebug("[SEC] invalidate current rotorparams");
1601 sec_fe_data[ROTOR_CMD] = -1;
1602 sec_fe_data[ROTOR_POS] = -1;
1603 ++m_sec_sequence.current();
1605 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1606 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1607 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1608 eDebug("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1609 ++m_sec_sequence.current();
1611 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1612 m_retryCount = m_sec_sequence.current()++->val;
1613 eDebug("[SEC] set rotor retries %d", m_retryCount);
1615 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1618 eDebug("[SEC] no more rotor retrys");
1619 setSecSequencePos(m_sec_sequence.current()->steps);
1622 ++m_sec_sequence.current();
1624 case eSecCommand::SET_POWER_LIMITING_MODE:
1627 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1628 FILE *f=fopen(proc_name, "w");
1629 if (f) // new interface exist?
1631 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1632 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1633 eDebug("write %s failed!! (%m)", proc_name);
1635 eDebug("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1638 else if (sec_fe->m_need_rotor_workaround)
1641 int slotid = sec_fe->m_slotid;
1642 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1644 sprintf(dev, "/dev/i2c/%d", slotid);
1645 else if (slotid == 2)
1646 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1647 else if (slotid == 3)
1648 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1649 int fd = ::open(dev, O_RDWR);
1651 unsigned char data[2];
1652 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1653 if(::read(fd, data, 1) != 1)
1654 eDebug("[SEC] error read lnbp (%m)");
1655 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1657 data[0] |= 0x80; // enable static current limiting
1658 eDebug("[SEC] set static current limiting");
1662 data[0] &= ~0x80; // enable dynamic current limiting
1663 eDebug("[SEC] set dynamic current limiting");
1665 if(::write(fd, data, 1) != 1)
1666 eDebug("[SEC] error write lnbp (%m)");
1669 ++m_sec_sequence.current();
1673 eDebug("[SEC] unhandled sec command %d",
1674 ++m_sec_sequence.current()->cmd);
1675 ++m_sec_sequence.current();
1677 m_tuneTimer->start(delay,true);
1683 void eDVBFrontend::setFrontend()
1685 eDebug("setting frontend %d", m_dvbid);
1688 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1690 perror("FE_SET_FRONTEND failed");
1695 RESULT eDVBFrontend::getFrontendType(int &t)
1703 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1708 eWarning("no SEC module active!");
1711 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1714 eDebug("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1717 feparm.polarisation,
1721 feparm.orbital_position);
1722 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1723 switch (feparm.inversion)
1725 case eDVBFrontendParametersSatellite::Inversion::On:
1726 parm_inversion = INVERSION_ON;
1728 case eDVBFrontendParametersSatellite::Inversion::Off:
1729 parm_inversion = INVERSION_OFF;
1732 case eDVBFrontendParametersSatellite::Inversion::Unknown:
1733 parm_inversion = INVERSION_AUTO;
1736 if (feparm.system == eDVBFrontendParametersSatellite::System::DVB_S)
1739 case eDVBFrontendParametersSatellite::FEC::fNone:
1740 parm_u_qpsk_fec_inner = FEC_NONE;
1742 case eDVBFrontendParametersSatellite::FEC::f1_2:
1743 parm_u_qpsk_fec_inner = FEC_1_2;
1745 case eDVBFrontendParametersSatellite::FEC::f2_3:
1746 parm_u_qpsk_fec_inner = FEC_2_3;
1748 case eDVBFrontendParametersSatellite::FEC::f3_4:
1749 parm_u_qpsk_fec_inner = FEC_3_4;
1751 case eDVBFrontendParametersSatellite::FEC::f5_6:
1752 parm_u_qpsk_fec_inner = FEC_5_6;
1754 case eDVBFrontendParametersSatellite::FEC::f7_8:
1755 parm_u_qpsk_fec_inner = FEC_7_8;
1758 eDebug("no valid fec for DVB-S set.. assume auto");
1759 case eDVBFrontendParametersSatellite::FEC::fAuto:
1760 parm_u_qpsk_fec_inner = FEC_AUTO;
1763 #if HAVE_DVB_API_VERSION >= 3
1768 case eDVBFrontendParametersSatellite::FEC::f1_2:
1769 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1771 case eDVBFrontendParametersSatellite::FEC::f2_3:
1772 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1774 case eDVBFrontendParametersSatellite::FEC::f3_4:
1775 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1777 case eDVBFrontendParametersSatellite::FEC::f3_5:
1778 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1780 case eDVBFrontendParametersSatellite::FEC::f4_5:
1781 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1783 case eDVBFrontendParametersSatellite::FEC::f5_6:
1784 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1786 case eDVBFrontendParametersSatellite::FEC::f7_8:
1787 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1789 case eDVBFrontendParametersSatellite::FEC::f8_9:
1790 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1792 case eDVBFrontendParametersSatellite::FEC::f9_10:
1793 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1796 eDebug("no valid fec for DVB-S2 set.. abort !!");
1799 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1800 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK) {
1801 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1802 // 8PSK fec driver values are decimal 9 bigger
1803 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1807 // FIXME !!! get frequency range from tuner
1808 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1810 eDebug("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1813 eDebug("tuning to %d mhz", parm_frequency/1000);
1818 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1820 #if HAVE_DVB_API_VERSION < 3
1821 parm_frequency = feparm.frequency;
1823 parm_frequency = feparm.frequency * 1000;
1825 parm_u_qam_symbol_rate = feparm.symbol_rate;
1826 switch (feparm.modulation)
1828 case eDVBFrontendParametersCable::Modulation::QAM16:
1829 parm_u_qam_modulation = QAM_16;
1831 case eDVBFrontendParametersCable::Modulation::QAM32:
1832 parm_u_qam_modulation = QAM_32;
1834 case eDVBFrontendParametersCable::Modulation::QAM64:
1835 parm_u_qam_modulation = QAM_64;
1837 case eDVBFrontendParametersCable::Modulation::QAM128:
1838 parm_u_qam_modulation = QAM_128;
1840 case eDVBFrontendParametersCable::Modulation::QAM256:
1841 parm_u_qam_modulation = QAM_256;
1844 case eDVBFrontendParametersCable::Modulation::Auto:
1845 parm_u_qam_modulation = QAM_AUTO;
1848 switch (feparm.inversion)
1850 case eDVBFrontendParametersCable::Inversion::On:
1851 parm_inversion = INVERSION_ON;
1853 case eDVBFrontendParametersCable::Inversion::Off:
1854 parm_inversion = INVERSION_OFF;
1857 case eDVBFrontendParametersCable::Inversion::Unknown:
1858 parm_inversion = INVERSION_AUTO;
1861 switch (feparm.fec_inner)
1863 case eDVBFrontendParametersCable::FEC::fNone:
1864 parm_u_qam_fec_inner = FEC_NONE;
1866 case eDVBFrontendParametersCable::FEC::f1_2:
1867 parm_u_qam_fec_inner = FEC_1_2;
1869 case eDVBFrontendParametersCable::FEC::f2_3:
1870 parm_u_qam_fec_inner = FEC_2_3;
1872 case eDVBFrontendParametersCable::FEC::f3_4:
1873 parm_u_qam_fec_inner = FEC_3_4;
1875 case eDVBFrontendParametersCable::FEC::f5_6:
1876 parm_u_qam_fec_inner = FEC_5_6;
1878 case eDVBFrontendParametersCable::FEC::f7_8:
1879 parm_u_qam_fec_inner = FEC_7_8;
1881 #if HAVE_DVB_API_VERSION >= 3
1882 case eDVBFrontendParametersCable::FEC::f8_9:
1883 parm_u_qam_fec_inner = FEC_8_9;
1887 case eDVBFrontendParametersCable::FEC::fAuto:
1888 parm_u_qam_fec_inner = FEC_AUTO;
1891 eDebug("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
1892 parm_frequency/1000,
1893 parm_u_qam_symbol_rate,
1894 parm_u_qam_fec_inner,
1895 parm_u_qam_modulation,
1900 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
1902 parm_frequency = feparm.frequency;
1904 switch (feparm.bandwidth)
1906 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
1907 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
1909 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
1910 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
1912 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
1913 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
1916 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
1917 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
1920 switch (feparm.code_rate_LP)
1922 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1923 parm_u_ofdm_code_rate_LP = FEC_1_2;
1925 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1926 parm_u_ofdm_code_rate_LP = FEC_2_3;
1928 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1929 parm_u_ofdm_code_rate_LP = FEC_3_4;
1931 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1932 parm_u_ofdm_code_rate_LP = FEC_5_6;
1934 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1935 parm_u_ofdm_code_rate_LP = FEC_7_8;
1938 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1939 parm_u_ofdm_code_rate_LP = FEC_AUTO;
1942 switch (feparm.code_rate_HP)
1944 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1945 parm_u_ofdm_code_rate_HP = FEC_1_2;
1947 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1948 parm_u_ofdm_code_rate_HP = FEC_2_3;
1950 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1951 parm_u_ofdm_code_rate_HP = FEC_3_4;
1953 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1954 parm_u_ofdm_code_rate_HP = FEC_5_6;
1956 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1957 parm_u_ofdm_code_rate_HP = FEC_7_8;
1960 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1961 parm_u_ofdm_code_rate_HP = FEC_AUTO;
1964 switch (feparm.modulation)
1966 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
1967 parm_u_ofdm_constellation = QPSK;
1969 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
1970 parm_u_ofdm_constellation = QAM_16;
1972 case eDVBFrontendParametersTerrestrial::Modulation::QAM64:
1973 parm_u_ofdm_constellation = QAM_64;
1976 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
1977 parm_u_ofdm_constellation = QAM_AUTO;
1980 switch (feparm.transmission_mode)
1982 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
1983 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
1985 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
1986 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
1989 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
1990 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
1993 switch (feparm.guard_interval)
1995 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32:
1996 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
1998 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16:
1999 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2001 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8:
2002 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2004 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4:
2005 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2008 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto:
2009 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2012 switch (feparm.hierarchy)
2014 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone:
2015 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2017 case eDVBFrontendParametersTerrestrial::Hierarchy::H1:
2018 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2020 case eDVBFrontendParametersTerrestrial::Hierarchy::H2:
2021 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2023 case eDVBFrontendParametersTerrestrial::Hierarchy::H4:
2024 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2027 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto:
2028 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2031 switch (feparm.inversion)
2033 case eDVBFrontendParametersTerrestrial::Inversion::On:
2034 parm_inversion = INVERSION_ON;
2036 case eDVBFrontendParametersTerrestrial::Inversion::Off:
2037 parm_inversion = INVERSION_OFF;
2040 case eDVBFrontendParametersTerrestrial::Inversion::Unknown:
2041 parm_inversion = INVERSION_AUTO;
2047 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2049 unsigned int timeout = 5000;
2050 eDebug("(%d)tune", m_dvbid);
2058 eDebug("no frontend device opened... do not try to tune !!!");
2070 m_sec_sequence.clear();
2072 where.calcLockTimeout(timeout);
2078 eDVBFrontendParametersSatellite feparm;
2079 if (where.getDVBS(feparm))
2081 eDebug("no dvbs data!");
2085 m_sec->setRotorMoving(false);
2086 res=prepare_sat(feparm, timeout);
2094 eDVBFrontendParametersCable feparm;
2095 if (where.getDVBC(feparm))
2100 res=prepare_cable(feparm);
2104 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2105 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2110 eDVBFrontendParametersTerrestrial feparm;
2111 if (where.getDVBT(feparm))
2113 eDebug("no -T data");
2117 res=prepare_terrestrial(feparm);
2121 std::string enable_5V;
2122 char configStr[255];
2123 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2124 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2125 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2126 if (enable_5V == "True")
2127 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2129 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2130 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2136 m_tuneTimer->start(0,true);
2137 m_sec_sequence.current() = m_sec_sequence.begin();
2139 if (m_state != stateTuning)
2142 m_state = stateTuning;
2143 m_stateChanged(this);
2149 m_tuneTimer->stop();
2153 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2155 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2159 RESULT eDVBFrontend::setVoltage(int voltage)
2161 if (m_type == feCable)
2163 #if HAVE_DVB_API_VERSION < 3
2166 bool increased=false;
2167 fe_sec_voltage_t vlt;
2169 m_data[CUR_VOLTAGE]=voltage;
2173 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2174 vlt = SEC_VOLTAGE_OFF;
2177 #if HAVE_DVB_API_VERSION < 3
2178 vlt = SEC_VOLTAGE_13_5;
2184 vlt = SEC_VOLTAGE_13;
2187 #if HAVE_DVB_API_VERSION < 3
2188 vlt = SEC_VOLTAGE_18_5;
2194 vlt = SEC_VOLTAGE_18;
2199 #if HAVE_DVB_API_VERSION < 3
2200 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2202 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2203 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2204 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2208 RESULT eDVBFrontend::getState(int &state)
2214 RESULT eDVBFrontend::setTone(int t)
2216 if (m_type != feSatellite)
2218 #if HAVE_DVB_API_VERSION < 3
2221 fe_sec_tone_mode_t tone;
2230 tone = SEC_TONE_OFF;
2235 #if HAVE_DVB_API_VERSION < 3
2236 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2238 return ::ioctl(m_fd, FE_SET_TONE, tone);
2242 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2243 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2246 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2248 #if HAVE_DVB_API_VERSION < 3
2249 struct secCommand cmd;
2250 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2251 cmd.u.diseqc.cmdtype = diseqc.data[0];
2252 cmd.u.diseqc.addr = diseqc.data[1];
2253 cmd.u.diseqc.cmd = diseqc.data[2];
2254 cmd.u.diseqc.numParams = diseqc.len-3;
2255 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2256 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2258 struct dvb_diseqc_master_cmd cmd;
2259 memcpy(cmd.msg, diseqc.data, diseqc.len);
2260 cmd.msg_len = diseqc.len;
2261 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2267 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2268 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2270 RESULT eDVBFrontend::sendToneburst(int burst)
2272 #if HAVE_DVB_API_VERSION < 3
2273 secMiniCmd cmd = SEC_MINI_NONE;
2275 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2277 if ( burst == eDVBSatelliteDiseqcParameters::A )
2279 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2281 #if HAVE_DVB_API_VERSION < 3
2282 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2285 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2291 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2297 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2299 m_sec_sequence = list;
2303 RESULT eDVBFrontend::getData(int num, long &data)
2305 if ( num < NUM_DATA_ENTRIES )
2313 RESULT eDVBFrontend::setData(int num, long val)
2315 if ( num < NUM_DATA_ENTRIES )
2323 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2326 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2328 if (m_type == eDVBFrontend::feSatellite)
2331 eDVBFrontendParametersSatellite sat_parm;
2332 int ret = feparm->getDVBS(sat_parm);
2334 if (sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S2 && !m_can_handle_dvbs2)
2336 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2337 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S && m_can_handle_dvbs2)
2341 else if (m_type == eDVBFrontend::feCable)
2342 return 2; // more prio for cable frontends
2343 else if (m_type == eDVBFrontend::feTerrestrial)
2348 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2350 ePyObject Id, Descr, Enabled;
2351 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 3)
2353 Id = PyTuple_GET_ITEM(obj, 0);
2354 Descr = PyTuple_GET_ITEM(obj, 1);
2355 Enabled = PyTuple_GET_ITEM(obj, 2);
2356 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled))
2358 strcpy(m_description, PyString_AS_STRING(Descr));
2359 m_slotid = PyInt_AsLong(Id);
2360 m_enabled = Enabled == Py_True;
2361 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2362 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2363 !!strstr(m_description, "Alps BSBE2") ||
2364 !!strstr(m_description, "Alps -S") ||
2365 !!strstr(m_description, "BCM4501");
2366 m_can_handle_dvbs2 = !!strstr(m_description, "Alps BSBE2") || !!strstr(m_description, "BCM4501");
2367 eDebug("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2368 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2371 PyErr_SetString(PyExc_StandardError,
2372 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");