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 && ((m_idleInputpower[0] && m_idleInputpower[1]) || (sec_fe->m_data[ROTOR_POS] == sec_fe->m_data[NEW_ROTOR_POS])))
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 long regval = 0xFFFF - ((snr / 3) + 0xA100), // revert some dvb api calulations to get the real register value
739 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
745 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[i][REGVAL]))
750 return (((regval - CN_lookup[Imin][REGVAL])
751 * (CN_lookup[Imax][REALVAL] - CN_lookup[Imin][REALVAL])
752 / (CN_lookup[Imax][REGVAL] - CN_lookup[Imin][REGVAL]))
753 + CN_lookup[Imin][REALVAL]) * 10;
759 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
760 !strcmp(m_description, "Alps -S") ||
761 !strcmp(m_description, "Philips -S") ||
762 !strcmp(m_description, "LG -S") )
764 float snr_in_db=(snr-39075)/1764.7;
765 return (int)(snr_in_db * 100.0);
766 } else if (!strcmp(m_description, "Alps BSBE2"))
768 return (int)((snr >> 7) * 10.0);
770 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
776 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
777 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
782 #if HAVE_DVB_API_VERSION < 3
783 FrontendStatus status=0;
787 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
788 eDebug("FE_READ_STATUS failed (%m)");
789 return !!(status&FE_HAS_LOCK);
793 #if HAVE_DVB_API_VERSION < 3
794 FrontendStatus status=0;
798 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
799 eDebug("FE_READ_STATUS failed (%m)");
800 return !!(status&FE_HAS_SYNC);
808 void PutToDict(ePyObject &dict, const char*key, long value)
810 ePyObject item = PyInt_FromLong(value);
813 if (PyDict_SetItemString(dict, key, item))
814 eDebug("put %s to dict failed", key);
818 eDebug("could not create PyObject for %s", key);
821 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
825 if (PyDict_SetItemString(dict, key, item))
826 eDebug("put %s to dict failed", key);
830 eDebug("invalid PyObject for %s", key);
833 void PutToDict(ePyObject &dict, const char*key, const char *value)
835 ePyObject item = PyString_FromString(value);
838 if (PyDict_SetItemString(dict, key, item))
839 eDebug("put %s to dict failed", key);
843 eDebug("could not create PyObject for %s", key);
846 void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, eDVBFrontend *fe)
850 fe->getData(eDVBFrontend::FREQ_OFFSET, freq_offset);
851 int frequency = parm_frequency + freq_offset;
852 PutToDict(dict, "frequency", frequency);
853 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
854 switch(parm_u_qpsk_fec_inner)
877 #if HAVE_DVB_API_VERSION >=3
878 case FEC_S2_8PSK_1_2:
879 case FEC_S2_QPSK_1_2:
882 case FEC_S2_8PSK_2_3:
883 case FEC_S2_QPSK_2_3:
886 case FEC_S2_8PSK_3_4:
887 case FEC_S2_QPSK_3_4:
890 case FEC_S2_8PSK_5_6:
891 case FEC_S2_QPSK_5_6:
894 case FEC_S2_8PSK_7_8:
895 case FEC_S2_QPSK_7_8:
898 case FEC_S2_8PSK_8_9:
899 case FEC_S2_QPSK_8_9:
902 case FEC_S2_8PSK_3_5:
903 case FEC_S2_QPSK_3_5:
906 case FEC_S2_8PSK_4_5:
907 case FEC_S2_QPSK_4_5:
910 case FEC_S2_8PSK_9_10:
911 case FEC_S2_QPSK_9_10:
916 PutToDict(dict, "fec_inner", tmp);
917 #if HAVE_DVB_API_VERSION >=3
918 PutToDict(dict, "modulation",
919 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ? "8PSK": "QPSK" );
920 if (parm_u_qpsk_fec_inner > FEC_AUTO)
922 switch(parm_inversion & 0xc)
924 default: // unknown rolloff
926 tmp = "ROLLOFF_0_35";
929 tmp = "ROLLOFF_0_25";
932 tmp = "ROLLOFF_0_20";
935 PutToDict(dict, "rolloff", tmp);
936 if (parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10)
938 switch(parm_inversion & 0x30)
943 case 0x10: // pilot on
946 case 0x20: // pilot auto
950 PutToDict(dict, "pilot", tmp);
957 PutToDict(dict, "modulation", "QPSK" );
960 PutToDict(dict, "system", tmp);
963 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
966 #if HAVE_DVB_API_VERSION < 3
967 PutToDict(dict, "frequency", parm_frequency);
969 PutToDict(dict, "frequency", parm_frequency/1000);
971 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
972 switch(parm_u_qam_fec_inner)
992 #if HAVE_DVB_API_VERSION >= 3
1002 PutToDict(dict, "fec_inner", tmp);
1003 switch(parm_u_qam_modulation)
1025 PutToDict(dict, "modulation", tmp);
1028 void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1031 PutToDict(dict, "frequency", parm_frequency);
1032 switch (parm_u_ofdm_bandwidth)
1034 case BANDWIDTH_8_MHZ:
1035 tmp = "BANDWIDTH_8_MHZ";
1037 case BANDWIDTH_7_MHZ:
1038 tmp = "BANDWIDTH_7_MHZ";
1040 case BANDWIDTH_6_MHZ:
1041 tmp = "BANDWIDTH_6_MHZ";
1044 case BANDWIDTH_AUTO:
1045 tmp = "BANDWIDTH_AUTO";
1048 PutToDict(dict, "bandwidth", tmp);
1049 switch (parm_u_ofdm_code_rate_LP)
1071 PutToDict(dict, "code_rate_lp", tmp);
1072 switch (parm_u_ofdm_code_rate_HP)
1094 PutToDict(dict, "code_rate_hp", tmp);
1095 switch (parm_u_ofdm_constellation)
1111 PutToDict(dict, "constellation", tmp);
1112 switch (parm_u_ofdm_transmission_mode)
1114 case TRANSMISSION_MODE_2K:
1115 tmp = "TRANSMISSION_MODE_2K";
1117 case TRANSMISSION_MODE_8K:
1118 tmp = "TRANSMISSION_MODE_8K";
1121 case TRANSMISSION_MODE_AUTO:
1122 tmp = "TRANSMISSION_MODE_AUTO";
1125 PutToDict(dict, "transmission_mode", tmp);
1126 switch (parm_u_ofdm_guard_interval)
1128 case GUARD_INTERVAL_1_32:
1129 tmp = "GUARD_INTERVAL_1_32";
1131 case GUARD_INTERVAL_1_16:
1132 tmp = "GUARD_INTERVAL_1_16";
1134 case GUARD_INTERVAL_1_8:
1135 tmp = "GUARD_INTERVAL_1_8";
1137 case GUARD_INTERVAL_1_4:
1138 tmp = "GUARD_INTERVAL_1_4";
1141 case GUARD_INTERVAL_AUTO:
1142 tmp = "GUARD_INTERVAL_AUTO";
1145 PutToDict(dict, "guard_interval", tmp);
1146 switch (parm_u_ofdm_hierarchy_information)
1148 case HIERARCHY_NONE:
1149 tmp = "HIERARCHY_NONE";
1152 tmp = "HIERARCHY_1";
1155 tmp = "HIERARCHY_2";
1158 tmp = "HIERARCHY_4";
1161 case HIERARCHY_AUTO:
1162 tmp = "HIERARCHY_AUTO";
1165 PutToDict(dict, "hierarchy_information", tmp);
1168 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1170 if (dest && PyDict_Check(dest))
1172 const char *tmp = "UNKNOWN";
1193 PutToDict(dest, "tuner_state", tmp);
1194 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1195 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1196 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1197 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1198 int sigQualitydB = readFrontendData(signalQualitydB);
1199 if (sigQualitydB == 0x12345678) // not support yet
1201 ePyObject obj=Py_None;
1203 PutToDict(dest, "tuner_signal_quality_db", obj);
1206 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1207 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1211 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1213 if (m_fd != -1 && dest && PyDict_Check(dest))
1221 FRONTENDPARAMETERS front;
1222 if (!original && ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1223 eDebug("FE_GET_FRONTEND (%m)");
1226 const FRONTENDPARAMETERS &parm = original ? this->parm : front;
1227 const char *tmp = "INVERSION_AUTO";
1228 switch(parm_inversion)
1231 tmp = "INVERSION_ON";
1234 tmp = "INVERSION_OFF";
1240 PutToDict(dest, "inversion", tmp);
1245 fillDictWithSatelliteData(dest, original?parm:front, this);
1248 fillDictWithCableData(dest, original?parm:front);
1251 fillDictWithTerrestrialData(dest, original?parm:front);
1262 void eDVBFrontend::getFrontendData(ePyObject dest)
1264 if (dest && PyDict_Check(dest))
1267 PutToDict(dest, "tuner_number", m_slotid);
1283 PutToDict(dest, "tuner_type", tmp);
1287 #ifndef FP_IOCTL_GET_ID
1288 #define FP_IOCTL_GET_ID 0
1290 int eDVBFrontend::readInputpower()
1292 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1294 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1295 FILE *f=fopen(proc_name, "r");
1298 if (fscanf(f, "%d", &power) != 1)
1299 eDebug("read %s failed!! (%m)", proc_name);
1301 eDebug("%s is %d\n", proc_name, power);
1306 // open front prozessor
1307 int fp=::open("/dev/dbox/fp0", O_RDWR);
1310 eDebug("couldn't open fp");
1313 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1314 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1316 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1325 bool eDVBFrontend::setSecSequencePos(int steps)
1327 eDebug("set sequence pos %d", steps);
1332 if (m_sec_sequence.current() != m_sec_sequence.end())
1333 ++m_sec_sequence.current();
1338 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1339 --m_sec_sequence.current();
1345 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1348 eDVBFrontend *sec_fe = this;
1349 eDVBRegisteredFrontend *regFE = 0;
1350 long tmp = m_data[LINKED_PREV_PTR];
1353 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1354 sec_fe = prev->m_frontend;
1355 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1356 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1357 int state = sec_fe->m_state;
1358 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1360 sec_fe->closeFrontend(true);
1361 state = sec_fe->m_state;
1363 if (state == eDVBFrontend::stateClosed)
1371 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1373 long *sec_fe_data = sec_fe->m_data;
1374 // eDebug("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1375 switch (m_sec_sequence.current()->cmd)
1377 case eSecCommand::SLEEP:
1378 delay = m_sec_sequence.current()++->msec;
1379 eDebug("[SEC] sleep %dms", delay);
1381 case eSecCommand::GOTO:
1382 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1383 ++m_sec_sequence.current();
1385 case eSecCommand::SET_VOLTAGE:
1387 int voltage = m_sec_sequence.current()++->voltage;
1388 eDebug("[SEC] setVoltage %d", voltage);
1389 sec_fe->setVoltage(voltage);
1392 case eSecCommand::IF_VOLTAGE_GOTO:
1394 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1395 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1397 ++m_sec_sequence.current();
1400 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1402 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1403 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1405 ++m_sec_sequence.current();
1408 case eSecCommand::IF_TONE_GOTO:
1410 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1411 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1413 ++m_sec_sequence.current();
1416 case eSecCommand::IF_NOT_TONE_GOTO:
1418 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1419 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1421 ++m_sec_sequence.current();
1424 case eSecCommand::SET_TONE:
1425 eDebug("[SEC] setTone %d", m_sec_sequence.current()->tone);
1426 sec_fe->setTone(m_sec_sequence.current()++->tone);
1428 case eSecCommand::SEND_DISEQC:
1429 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1430 eDebugNoNewLine("[SEC] sendDiseqc: ");
1431 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1432 eDebugNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1434 ++m_sec_sequence.current();
1436 case eSecCommand::SEND_TONEBURST:
1437 eDebug("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1438 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1440 case eSecCommand::SET_FRONTEND:
1441 eDebug("[SEC] setFrontend");
1443 ++m_sec_sequence.current();
1445 case eSecCommand::START_TUNE_TIMEOUT:
1447 m_timeout->start(m_sec_sequence.current()->timeout, 1);
1448 ++m_sec_sequence.current();
1451 case eSecCommand::SET_TIMEOUT:
1452 m_timeoutCount = m_sec_sequence.current()++->val;
1453 eDebug("[SEC] set timeout %d", m_timeoutCount);
1455 case eSecCommand::IF_TIMEOUT_GOTO:
1456 if (!m_timeoutCount)
1458 eDebug("[SEC] rotor timout");
1459 setSecSequencePos(m_sec_sequence.current()->steps);
1462 ++m_sec_sequence.current();
1464 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1466 int idx = m_sec_sequence.current()++->val;
1467 if ( idx == 0 || idx == 1 )
1469 m_idleInputpower[idx] = sec_fe->readInputpower();
1470 eDebug("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1473 eDebug("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1476 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1478 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1479 int idx = compare.val;
1480 if ( idx == 0 || idx == 1 )
1482 int idle = sec_fe->readInputpower();
1483 int diff = abs(idle-m_idleInputpower[idx]);
1486 eDebug("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1487 setSecSequencePos(compare.steps);
1491 ++m_sec_sequence.current();
1494 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1497 int isLocked = readFrontendData(locked);
1498 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1499 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1500 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 50) || !cmd.lastSignal))
1503 eDebug("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1506 eDebug("[SEC] locked step %d ok", cmd.okcount);
1507 cmd.lastSignal = signal;
1510 if (cmd.okcount > 4)
1512 eDebug("ok > 4 .. goto %d\n",cmd.steps);
1513 setSecSequencePos(cmd.steps);
1514 m_state = stateLock;
1515 m_stateChanged(this);
1522 eDebug("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1524 eDebug("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1526 if (!m_timeoutCount && m_retryCount > 0)
1531 ++m_sec_sequence.current();
1534 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1535 m_runningInputpower = sec_fe->readInputpower();
1536 eDebug("[SEC] runningInputpower is %d", m_runningInputpower);
1537 ++m_sec_sequence.current();
1539 case eSecCommand::SET_ROTOR_MOVING:
1540 m_sec->setRotorMoving(true);
1541 ++m_sec_sequence.current();
1543 case eSecCommand::SET_ROTOR_STOPPED:
1544 m_sec->setRotorMoving(false);
1545 ++m_sec_sequence.current();
1547 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1549 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1550 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1551 const char *txt = cmd.direction ? "running" : "stopped";
1552 eDebug("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1554 m_runningInputpower,
1557 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1558 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1561 eDebug("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1562 if ( cmd.okcount > 6 )
1564 eDebug("[SEC] rotor is %s", txt);
1565 if (setSecSequencePos(cmd.steps))
1571 eDebug("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1573 if (!m_timeoutCount && m_retryCount > 0)
1577 ++m_sec_sequence.current();
1580 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1581 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1582 setSecSequencePos(m_sec_sequence.current()->steps);
1584 ++m_sec_sequence.current();
1586 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1587 eDebug("[SEC] invalidate current switch params");
1588 sec_fe_data[CSW] = -1;
1589 sec_fe_data[UCSW] = -1;
1590 sec_fe_data[TONEBURST] = -1;
1591 ++m_sec_sequence.current();
1593 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1594 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1595 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1596 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1597 eDebug("[SEC] update current switch params");
1598 ++m_sec_sequence.current();
1600 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1601 eDebug("[SEC] invalidate current rotorparams");
1602 sec_fe_data[ROTOR_CMD] = -1;
1603 sec_fe_data[ROTOR_POS] = -1;
1604 ++m_sec_sequence.current();
1606 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1607 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1608 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1609 eDebug("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1610 ++m_sec_sequence.current();
1612 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1613 m_retryCount = m_sec_sequence.current()++->val;
1614 eDebug("[SEC] set rotor retries %d", m_retryCount);
1616 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1619 eDebug("[SEC] no more rotor retrys");
1620 setSecSequencePos(m_sec_sequence.current()->steps);
1623 ++m_sec_sequence.current();
1625 case eSecCommand::SET_POWER_LIMITING_MODE:
1628 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1629 FILE *f=fopen(proc_name, "w");
1630 if (f) // new interface exist?
1632 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1633 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1634 eDebug("write %s failed!! (%m)", proc_name);
1636 eDebug("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1639 else if (sec_fe->m_need_rotor_workaround)
1642 int slotid = sec_fe->m_slotid;
1643 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1645 sprintf(dev, "/dev/i2c/%d", slotid);
1646 else if (slotid == 2)
1647 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1648 else if (slotid == 3)
1649 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1650 int fd = ::open(dev, O_RDWR);
1652 unsigned char data[2];
1653 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1654 if(::read(fd, data, 1) != 1)
1655 eDebug("[SEC] error read lnbp (%m)");
1656 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1658 data[0] |= 0x80; // enable static current limiting
1659 eDebug("[SEC] set static current limiting");
1663 data[0] &= ~0x80; // enable dynamic current limiting
1664 eDebug("[SEC] set dynamic current limiting");
1666 if(::write(fd, data, 1) != 1)
1667 eDebug("[SEC] error write lnbp (%m)");
1670 ++m_sec_sequence.current();
1674 eDebug("[SEC] unhandled sec command %d",
1675 ++m_sec_sequence.current()->cmd);
1676 ++m_sec_sequence.current();
1678 m_tuneTimer->start(delay,true);
1684 void eDVBFrontend::setFrontend()
1686 eDebug("setting frontend %d", m_dvbid);
1689 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1691 perror("FE_SET_FRONTEND failed");
1696 RESULT eDVBFrontend::getFrontendType(int &t)
1704 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1709 eWarning("no SEC module active!");
1712 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1715 eDebug("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1718 feparm.polarisation,
1722 feparm.orbital_position);
1723 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1724 switch (feparm.inversion)
1726 case eDVBFrontendParametersSatellite::Inversion::On:
1727 parm_inversion = INVERSION_ON;
1729 case eDVBFrontendParametersSatellite::Inversion::Off:
1730 parm_inversion = INVERSION_OFF;
1733 case eDVBFrontendParametersSatellite::Inversion::Unknown:
1734 parm_inversion = INVERSION_AUTO;
1737 if (feparm.system == eDVBFrontendParametersSatellite::System::DVB_S)
1740 case eDVBFrontendParametersSatellite::FEC::fNone:
1741 parm_u_qpsk_fec_inner = FEC_NONE;
1743 case eDVBFrontendParametersSatellite::FEC::f1_2:
1744 parm_u_qpsk_fec_inner = FEC_1_2;
1746 case eDVBFrontendParametersSatellite::FEC::f2_3:
1747 parm_u_qpsk_fec_inner = FEC_2_3;
1749 case eDVBFrontendParametersSatellite::FEC::f3_4:
1750 parm_u_qpsk_fec_inner = FEC_3_4;
1752 case eDVBFrontendParametersSatellite::FEC::f5_6:
1753 parm_u_qpsk_fec_inner = FEC_5_6;
1755 case eDVBFrontendParametersSatellite::FEC::f7_8:
1756 parm_u_qpsk_fec_inner = FEC_7_8;
1759 eDebug("no valid fec for DVB-S set.. assume auto");
1760 case eDVBFrontendParametersSatellite::FEC::fAuto:
1761 parm_u_qpsk_fec_inner = FEC_AUTO;
1764 #if HAVE_DVB_API_VERSION >= 3
1769 case eDVBFrontendParametersSatellite::FEC::f1_2:
1770 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1772 case eDVBFrontendParametersSatellite::FEC::f2_3:
1773 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1775 case eDVBFrontendParametersSatellite::FEC::f3_4:
1776 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1778 case eDVBFrontendParametersSatellite::FEC::f3_5:
1779 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1781 case eDVBFrontendParametersSatellite::FEC::f4_5:
1782 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1784 case eDVBFrontendParametersSatellite::FEC::f5_6:
1785 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1787 case eDVBFrontendParametersSatellite::FEC::f7_8:
1788 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1790 case eDVBFrontendParametersSatellite::FEC::f8_9:
1791 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1793 case eDVBFrontendParametersSatellite::FEC::f9_10:
1794 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1797 eDebug("no valid fec for DVB-S2 set.. abort !!");
1800 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1801 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK) {
1802 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1803 // 8PSK fec driver values are decimal 9 bigger
1804 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1808 // FIXME !!! get frequency range from tuner
1809 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1811 eDebug("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1814 eDebug("tuning to %d mhz", parm_frequency/1000);
1819 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1821 #if HAVE_DVB_API_VERSION < 3
1822 parm_frequency = feparm.frequency;
1824 parm_frequency = feparm.frequency * 1000;
1826 parm_u_qam_symbol_rate = feparm.symbol_rate;
1827 switch (feparm.modulation)
1829 case eDVBFrontendParametersCable::Modulation::QAM16:
1830 parm_u_qam_modulation = QAM_16;
1832 case eDVBFrontendParametersCable::Modulation::QAM32:
1833 parm_u_qam_modulation = QAM_32;
1835 case eDVBFrontendParametersCable::Modulation::QAM64:
1836 parm_u_qam_modulation = QAM_64;
1838 case eDVBFrontendParametersCable::Modulation::QAM128:
1839 parm_u_qam_modulation = QAM_128;
1841 case eDVBFrontendParametersCable::Modulation::QAM256:
1842 parm_u_qam_modulation = QAM_256;
1845 case eDVBFrontendParametersCable::Modulation::Auto:
1846 parm_u_qam_modulation = QAM_AUTO;
1849 switch (feparm.inversion)
1851 case eDVBFrontendParametersCable::Inversion::On:
1852 parm_inversion = INVERSION_ON;
1854 case eDVBFrontendParametersCable::Inversion::Off:
1855 parm_inversion = INVERSION_OFF;
1858 case eDVBFrontendParametersCable::Inversion::Unknown:
1859 parm_inversion = INVERSION_AUTO;
1862 switch (feparm.fec_inner)
1864 case eDVBFrontendParametersCable::FEC::fNone:
1865 parm_u_qam_fec_inner = FEC_NONE;
1867 case eDVBFrontendParametersCable::FEC::f1_2:
1868 parm_u_qam_fec_inner = FEC_1_2;
1870 case eDVBFrontendParametersCable::FEC::f2_3:
1871 parm_u_qam_fec_inner = FEC_2_3;
1873 case eDVBFrontendParametersCable::FEC::f3_4:
1874 parm_u_qam_fec_inner = FEC_3_4;
1876 case eDVBFrontendParametersCable::FEC::f5_6:
1877 parm_u_qam_fec_inner = FEC_5_6;
1879 case eDVBFrontendParametersCable::FEC::f7_8:
1880 parm_u_qam_fec_inner = FEC_7_8;
1882 #if HAVE_DVB_API_VERSION >= 3
1883 case eDVBFrontendParametersCable::FEC::f8_9:
1884 parm_u_qam_fec_inner = FEC_8_9;
1888 case eDVBFrontendParametersCable::FEC::fAuto:
1889 parm_u_qam_fec_inner = FEC_AUTO;
1892 eDebug("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
1893 parm_frequency/1000,
1894 parm_u_qam_symbol_rate,
1895 parm_u_qam_fec_inner,
1896 parm_u_qam_modulation,
1901 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
1903 parm_frequency = feparm.frequency;
1905 switch (feparm.bandwidth)
1907 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
1908 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
1910 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
1911 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
1913 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
1914 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
1917 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
1918 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
1921 switch (feparm.code_rate_LP)
1923 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1924 parm_u_ofdm_code_rate_LP = FEC_1_2;
1926 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1927 parm_u_ofdm_code_rate_LP = FEC_2_3;
1929 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1930 parm_u_ofdm_code_rate_LP = FEC_3_4;
1932 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1933 parm_u_ofdm_code_rate_LP = FEC_5_6;
1935 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1936 parm_u_ofdm_code_rate_LP = FEC_7_8;
1939 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1940 parm_u_ofdm_code_rate_LP = FEC_AUTO;
1943 switch (feparm.code_rate_HP)
1945 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1946 parm_u_ofdm_code_rate_HP = FEC_1_2;
1948 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1949 parm_u_ofdm_code_rate_HP = FEC_2_3;
1951 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1952 parm_u_ofdm_code_rate_HP = FEC_3_4;
1954 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1955 parm_u_ofdm_code_rate_HP = FEC_5_6;
1957 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1958 parm_u_ofdm_code_rate_HP = FEC_7_8;
1961 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1962 parm_u_ofdm_code_rate_HP = FEC_AUTO;
1965 switch (feparm.modulation)
1967 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
1968 parm_u_ofdm_constellation = QPSK;
1970 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
1971 parm_u_ofdm_constellation = QAM_16;
1973 case eDVBFrontendParametersTerrestrial::Modulation::QAM64:
1974 parm_u_ofdm_constellation = QAM_64;
1977 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
1978 parm_u_ofdm_constellation = QAM_AUTO;
1981 switch (feparm.transmission_mode)
1983 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
1984 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
1986 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
1987 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
1990 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
1991 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
1994 switch (feparm.guard_interval)
1996 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32:
1997 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
1999 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16:
2000 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2002 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8:
2003 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2005 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4:
2006 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2009 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto:
2010 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2013 switch (feparm.hierarchy)
2015 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone:
2016 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2018 case eDVBFrontendParametersTerrestrial::Hierarchy::H1:
2019 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2021 case eDVBFrontendParametersTerrestrial::Hierarchy::H2:
2022 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2024 case eDVBFrontendParametersTerrestrial::Hierarchy::H4:
2025 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2028 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto:
2029 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2032 switch (feparm.inversion)
2034 case eDVBFrontendParametersTerrestrial::Inversion::On:
2035 parm_inversion = INVERSION_ON;
2037 case eDVBFrontendParametersTerrestrial::Inversion::Off:
2038 parm_inversion = INVERSION_OFF;
2041 case eDVBFrontendParametersTerrestrial::Inversion::Unknown:
2042 parm_inversion = INVERSION_AUTO;
2048 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2050 unsigned int timeout = 5000;
2051 eDebug("(%d)tune", m_dvbid);
2059 eDebug("no frontend device opened... do not try to tune !!!");
2071 m_sec_sequence.clear();
2073 where.calcLockTimeout(timeout);
2079 eDVBFrontendParametersSatellite feparm;
2080 if (where.getDVBS(feparm))
2082 eDebug("no dvbs data!");
2086 m_sec->setRotorMoving(false);
2087 res=prepare_sat(feparm, timeout);
2095 eDVBFrontendParametersCable feparm;
2096 if (where.getDVBC(feparm))
2101 res=prepare_cable(feparm);
2105 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2106 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2111 eDVBFrontendParametersTerrestrial feparm;
2112 if (where.getDVBT(feparm))
2114 eDebug("no -T data");
2118 res=prepare_terrestrial(feparm);
2122 std::string enable_5V;
2123 char configStr[255];
2124 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2125 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2126 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2127 if (enable_5V == "True")
2128 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2130 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2131 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2137 m_tuneTimer->start(0,true);
2138 m_sec_sequence.current() = m_sec_sequence.begin();
2140 if (m_state != stateTuning)
2143 m_state = stateTuning;
2144 m_stateChanged(this);
2150 m_tuneTimer->stop();
2154 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2156 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2160 RESULT eDVBFrontend::setVoltage(int voltage)
2162 if (m_type == feCable)
2164 #if HAVE_DVB_API_VERSION < 3
2167 bool increased=false;
2168 fe_sec_voltage_t vlt;
2170 m_data[CUR_VOLTAGE]=voltage;
2174 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2175 vlt = SEC_VOLTAGE_OFF;
2178 #if HAVE_DVB_API_VERSION < 3
2179 vlt = SEC_VOLTAGE_13_5;
2185 vlt = SEC_VOLTAGE_13;
2188 #if HAVE_DVB_API_VERSION < 3
2189 vlt = SEC_VOLTAGE_18_5;
2195 vlt = SEC_VOLTAGE_18;
2200 #if HAVE_DVB_API_VERSION < 3
2201 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2203 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2204 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2205 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2209 RESULT eDVBFrontend::getState(int &state)
2215 RESULT eDVBFrontend::setTone(int t)
2217 if (m_type != feSatellite)
2219 #if HAVE_DVB_API_VERSION < 3
2222 fe_sec_tone_mode_t tone;
2231 tone = SEC_TONE_OFF;
2236 #if HAVE_DVB_API_VERSION < 3
2237 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2239 return ::ioctl(m_fd, FE_SET_TONE, tone);
2243 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2244 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2247 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2249 #if HAVE_DVB_API_VERSION < 3
2250 struct secCommand cmd;
2251 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2252 cmd.u.diseqc.cmdtype = diseqc.data[0];
2253 cmd.u.diseqc.addr = diseqc.data[1];
2254 cmd.u.diseqc.cmd = diseqc.data[2];
2255 cmd.u.diseqc.numParams = diseqc.len-3;
2256 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2257 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2259 struct dvb_diseqc_master_cmd cmd;
2260 memcpy(cmd.msg, diseqc.data, diseqc.len);
2261 cmd.msg_len = diseqc.len;
2262 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2268 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2269 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2271 RESULT eDVBFrontend::sendToneburst(int burst)
2273 #if HAVE_DVB_API_VERSION < 3
2274 secMiniCmd cmd = SEC_MINI_NONE;
2276 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2278 if ( burst == eDVBSatelliteDiseqcParameters::A )
2280 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2282 #if HAVE_DVB_API_VERSION < 3
2283 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2286 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2292 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2298 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2300 m_sec_sequence = list;
2304 RESULT eDVBFrontend::getData(int num, long &data)
2306 if ( num < NUM_DATA_ENTRIES )
2314 RESULT eDVBFrontend::setData(int num, long val)
2316 if ( num < NUM_DATA_ENTRIES )
2324 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2327 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2329 if (m_type == eDVBFrontend::feSatellite)
2332 eDVBFrontendParametersSatellite sat_parm;
2333 int ret = feparm->getDVBS(sat_parm);
2335 if (sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S2 && !m_can_handle_dvbs2)
2337 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2338 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S && m_can_handle_dvbs2)
2342 else if (m_type == eDVBFrontend::feCable)
2343 return 2; // more prio for cable frontends
2344 else if (m_type == eDVBFrontend::feTerrestrial)
2349 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2351 ePyObject Id, Descr, Enabled;
2352 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 3)
2354 Id = PyTuple_GET_ITEM(obj, 0);
2355 Descr = PyTuple_GET_ITEM(obj, 1);
2356 Enabled = PyTuple_GET_ITEM(obj, 2);
2357 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled))
2359 strcpy(m_description, PyString_AS_STRING(Descr));
2360 m_slotid = PyInt_AsLong(Id);
2361 m_enabled = Enabled == Py_True;
2362 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2363 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2364 !!strstr(m_description, "Alps BSBE2") ||
2365 !!strstr(m_description, "Alps -S") ||
2366 !!strstr(m_description, "BCM4501");
2367 m_can_handle_dvbs2 = !!strstr(m_description, "Alps BSBE2") || !!strstr(m_description, "BCM4501");
2368 eDebug("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2369 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2372 PyErr_SetString(PyExc_StandardError,
2373 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");