1 #include <lib/dvb/dvb.h>
2 #include <lib/base/eerror.h>
3 #include <lib/base/nconfig.h> // access to python config
9 #ifndef I2C_SLAVE_FORCE
10 #define I2C_SLAVE_FORCE 0x0706
13 #if HAVE_DVB_API_VERSION < 3
14 #include <ost/frontend.h>
16 #define QAM_AUTO (Modulation)6
17 #define TRANSMISSION_MODE_AUTO (TransmitMode)2
18 #define BANDWIDTH_AUTO (BandWidth)3
19 #define GUARD_INTERVAL_AUTO (GuardInterval)4
20 #define HIERARCHY_AUTO (Hierarchy)4
21 #define parm_frequency parm.Frequency
22 #define parm_inversion parm.Inversion
23 #define parm_u_qpsk_symbol_rate parm.u.qpsk.SymbolRate
24 #define parm_u_qpsk_fec_inner parm.u.qpsk.FEC_inner
25 #define parm_u_qam_symbol_rate parm.u.qam.SymbolRate
26 #define parm_u_qam_fec_inner parm.u.qam.FEC_inner
27 #define parm_u_qam_modulation parm.u.qam.QAM
28 #define parm_u_ofdm_bandwidth parm.u.ofdm.bandWidth
29 #define parm_u_ofdm_code_rate_LP parm.u.ofdm.LP_CodeRate
30 #define parm_u_ofdm_code_rate_HP parm.u.ofdm.HP_CodeRate
31 #define parm_u_ofdm_constellation parm.u.ofdm.Constellation
32 #define parm_u_ofdm_transmission_mode parm.u.ofdm.TransmissionMode
33 #define parm_u_ofdm_guard_interval parm.u.ofdm.guardInterval
34 #define parm_u_ofdm_hierarchy_information parm.u.ofdm.HierarchyInformation
36 #include <linux/dvb/frontend.h>
37 #define parm_frequency parm.frequency
38 #define parm_inversion parm.inversion
39 #define parm_u_qpsk_symbol_rate parm.u.qpsk.symbol_rate
40 #define parm_u_qpsk_fec_inner parm.u.qpsk.fec_inner
41 #define parm_u_qam_symbol_rate parm.u.qam.symbol_rate
42 #define parm_u_qam_fec_inner parm.u.qam.fec_inner
43 #define parm_u_qam_modulation parm.u.qam.modulation
44 #define parm_u_ofdm_bandwidth parm.u.ofdm.bandwidth
45 #define parm_u_ofdm_code_rate_LP parm.u.ofdm.code_rate_LP
46 #define parm_u_ofdm_code_rate_HP parm.u.ofdm.code_rate_HP
47 #define parm_u_ofdm_constellation parm.u.ofdm.constellation
48 #define parm_u_ofdm_transmission_mode parm.u.ofdm.transmission_mode
49 #define parm_u_ofdm_guard_interval parm.u.ofdm.guard_interval
50 #define parm_u_ofdm_hierarchy_information parm.u.ofdm.hierarchy_information
52 #warning "FEC_9_10 already exist in dvb api ... it seems it is now ready for DVB-S2"
54 #define FEC_S2_QPSK_1_2 (fe_code_rate_t)(FEC_AUTO+1)
55 #define FEC_S2_QPSK_2_3 (fe_code_rate_t)(FEC_S2_QPSK_1_2+1)
56 #define FEC_S2_QPSK_3_4 (fe_code_rate_t)(FEC_S2_QPSK_2_3+1)
57 #define FEC_S2_QPSK_5_6 (fe_code_rate_t)(FEC_S2_QPSK_3_4+1)
58 #define FEC_S2_QPSK_7_8 (fe_code_rate_t)(FEC_S2_QPSK_5_6+1)
59 #define FEC_S2_QPSK_8_9 (fe_code_rate_t)(FEC_S2_QPSK_7_8+1)
60 #define FEC_S2_QPSK_3_5 (fe_code_rate_t)(FEC_S2_QPSK_8_9+1)
61 #define FEC_S2_QPSK_4_5 (fe_code_rate_t)(FEC_S2_QPSK_3_5+1)
62 #define FEC_S2_QPSK_9_10 (fe_code_rate_t)(FEC_S2_QPSK_4_5+1)
63 #define FEC_S2_8PSK_1_2 (fe_code_rate_t)(FEC_S2_QPSK_9_10+1)
64 #define FEC_S2_8PSK_2_3 (fe_code_rate_t)(FEC_S2_8PSK_1_2+1)
65 #define FEC_S2_8PSK_3_4 (fe_code_rate_t)(FEC_S2_8PSK_2_3+1)
66 #define FEC_S2_8PSK_5_6 (fe_code_rate_t)(FEC_S2_8PSK_3_4+1)
67 #define FEC_S2_8PSK_7_8 (fe_code_rate_t)(FEC_S2_8PSK_5_6+1)
68 #define FEC_S2_8PSK_8_9 (fe_code_rate_t)(FEC_S2_8PSK_7_8+1)
69 #define FEC_S2_8PSK_3_5 (fe_code_rate_t)(FEC_S2_8PSK_8_9+1)
70 #define FEC_S2_8PSK_4_5 (fe_code_rate_t)(FEC_S2_8PSK_3_5+1)
71 #define FEC_S2_8PSK_9_10 (fe_code_rate_t)(FEC_S2_8PSK_4_5+1)
75 #include <dvbsi++/satellite_delivery_system_descriptor.h>
76 #include <dvbsi++/cable_delivery_system_descriptor.h>
77 #include <dvbsi++/terrestrial_delivery_system_descriptor.h>
79 void eDVBDiseqcCommand::setCommandString(const char *str)
84 int slen = strlen(str);
87 eDebug("invalid diseqc command string length (not 2 byte aligned)");
90 if (slen > MAX_DISEQC_LENGTH*2)
92 eDebug("invalid diseqc command string length (string is to long)");
96 for (int i=0; i < slen; ++i)
98 unsigned char c = str[i];
101 case '0' ... '9': c-=48; break;
102 case 'a' ... 'f': c-=87; break;
103 case 'A' ... 'F': c-=55; break;
105 eDebug("invalid character in hex string..ignore complete diseqc command !");
119 void eDVBFrontendParametersSatellite::set(const SatelliteDeliverySystemDescriptor &descriptor)
121 frequency = descriptor.getFrequency() * 10;
122 symbol_rate = descriptor.getSymbolRate() * 100;
123 polarisation = descriptor.getPolarization();
124 fec = descriptor.getFecInner();
125 if ( fec != FEC::fNone && fec > FEC::f9_10 )
127 inversion = Inversion::Unknown;
128 pilot = Pilot::Unknown;
129 orbital_position = ((descriptor.getOrbitalPosition() >> 12) & 0xF) * 1000;
130 orbital_position += ((descriptor.getOrbitalPosition() >> 8) & 0xF) * 100;
131 orbital_position += ((descriptor.getOrbitalPosition() >> 4) & 0xF) * 10;
132 orbital_position += ((descriptor.getOrbitalPosition()) & 0xF);
133 if (orbital_position && (!descriptor.getWestEastFlag()))
134 orbital_position = 3600 - orbital_position;
135 system = descriptor.getModulationSystem();
136 modulation = descriptor.getModulation();
137 if (system == System::DVB_S && modulation == Modulation::M8PSK)
139 eDebug("satellite_delivery_descriptor non valid modulation type.. force QPSK");
142 rolloff = descriptor.getRollOff();
143 if (system == System::DVB_S2)
145 eDebug("SAT DVB-S2 freq %d, %s, pos %d, sr %d, fec %d, modulation %d, rolloff %d",
147 polarisation ? "hor" : "vert",
155 eDebug("SAT DVB-S freq %d, %s, pos %d, sr %d, fec %d",
157 polarisation ? "hor" : "vert",
163 void eDVBFrontendParametersCable::set(const CableDeliverySystemDescriptor &descriptor)
165 frequency = descriptor.getFrequency() / 10;
166 symbol_rate = descriptor.getSymbolRate() * 100;
167 fec_inner = descriptor.getFecInner();
168 if ( fec_inner == 0xF )
169 fec_inner = FEC::fNone;
170 modulation = descriptor.getModulation();
171 if ( modulation > 0x5 )
172 modulation = Modulation::Auto;
173 inversion = Inversion::Unknown;
174 eDebug("Cable freq %d, mod %d, sr %d, fec %d",
176 modulation, symbol_rate, fec_inner);
179 void eDVBFrontendParametersTerrestrial::set(const TerrestrialDeliverySystemDescriptor &descriptor)
181 frequency = descriptor.getCentreFrequency() * 10;
182 bandwidth = descriptor.getBandwidth();
183 if ( bandwidth > 2 ) // 5Mhz forced to auto
184 bandwidth = Bandwidth::BwAuto;
185 code_rate_HP = descriptor.getCodeRateHpStream();
186 if (code_rate_HP > 4)
187 code_rate_HP = FEC::fAuto;
188 code_rate_LP = descriptor.getCodeRateLpStream();
189 if (code_rate_LP > 4)
190 code_rate_LP = FEC::fAuto;
191 transmission_mode = descriptor.getTransmissionMode();
192 if (transmission_mode > 1) // TM4k forced to auto
193 transmission_mode = TransmissionMode::TMAuto;
194 guard_interval = descriptor.getGuardInterval();
195 if (guard_interval > 3)
196 guard_interval = GuardInterval::GI_Auto;
197 hierarchy = descriptor.getHierarchyInformation()&3;
198 modulation = descriptor.getConstellation();
200 modulation = Modulation::Auto;
201 inversion = Inversion::Unknown;
202 eDebug("Terr freq %d, bw %d, cr_hp %d, cr_lp %d, tm_mode %d, guard %d, hierarchy %d, const %d",
203 frequency, bandwidth, code_rate_HP, code_rate_LP, transmission_mode,
204 guard_interval, hierarchy, modulation);
207 eDVBFrontendParameters::eDVBFrontendParameters()
208 :m_type(-1), m_flags(0)
212 DEFINE_REF(eDVBFrontendParameters);
214 RESULT eDVBFrontendParameters::getSystem(int &t) const
222 RESULT eDVBFrontendParameters::getDVBS(eDVBFrontendParametersSatellite &p) const
224 if (m_type != iDVBFrontend::feSatellite)
230 RESULT eDVBFrontendParameters::getDVBC(eDVBFrontendParametersCable &p) const
232 if (m_type != iDVBFrontend::feCable)
238 RESULT eDVBFrontendParameters::getDVBT(eDVBFrontendParametersTerrestrial &p) const
240 if (m_type != iDVBFrontend::feTerrestrial)
246 RESULT eDVBFrontendParameters::setDVBS(const eDVBFrontendParametersSatellite &p, bool no_rotor_command_on_tune)
249 sat.no_rotor_command_on_tune = no_rotor_command_on_tune;
250 m_type = iDVBFrontend::feSatellite;
254 RESULT eDVBFrontendParameters::setDVBC(const eDVBFrontendParametersCable &p)
257 m_type = iDVBFrontend::feCable;
261 RESULT eDVBFrontendParameters::setDVBT(const eDVBFrontendParametersTerrestrial &p)
264 m_type = iDVBFrontend::feTerrestrial;
268 RESULT eDVBFrontendParameters::calculateDifference(const iDVBFrontendParameters *parm, int &diff, bool exact) const
273 if (parm->getSystem(type))
277 diff = 1<<30; // big difference
283 case iDVBFrontend::feSatellite:
285 eDVBFrontendParametersSatellite osat;
286 if (parm->getDVBS(osat))
289 if (sat.orbital_position != osat.orbital_position)
291 else if (sat.polarisation != osat.polarisation)
293 else if (exact && sat.fec != osat.fec && sat.fec != eDVBFrontendParametersSatellite::FEC::fAuto && osat.fec != eDVBFrontendParametersSatellite::FEC::fAuto)
295 else if (exact && sat.modulation != osat.modulation && sat.modulation != eDVBFrontendParametersSatellite::Modulation::Auto && osat.modulation != eDVBFrontendParametersSatellite::Modulation::Auto)
299 diff = abs(sat.frequency - osat.frequency);
300 diff += abs(sat.symbol_rate - osat.symbol_rate);
304 case iDVBFrontend::feCable:
305 eDVBFrontendParametersCable ocable;
306 if (parm->getDVBC(ocable))
309 if (exact && cable.modulation != ocable.modulation
310 && cable.modulation != eDVBFrontendParametersCable::Modulation::Auto
311 && ocable.modulation != eDVBFrontendParametersCable::Modulation::Auto)
313 else if (exact && cable.fec_inner != ocable.fec_inner && cable.fec_inner != eDVBFrontendParametersCable::FEC::fAuto && ocable.fec_inner != eDVBFrontendParametersCable::FEC::fAuto)
317 diff = abs(cable.frequency - ocable.frequency);
318 diff += abs(cable.symbol_rate - ocable.symbol_rate);
321 case iDVBFrontend::feTerrestrial:
322 eDVBFrontendParametersTerrestrial oterrestrial;
323 if (parm->getDVBT(oterrestrial))
327 if (exact && oterrestrial.bandwidth != terrestrial.bandwidth &&
328 oterrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto &&
329 terrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto)
331 else if (exact && oterrestrial.modulation != terrestrial.modulation &&
332 oterrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation::Auto &&
333 terrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation::Auto)
335 else if (exact && oterrestrial.transmission_mode != terrestrial.transmission_mode &&
336 oterrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto &&
337 terrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto)
339 else if (exact && oterrestrial.guard_interval != terrestrial.guard_interval &&
340 oterrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto &&
341 terrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto)
343 else if (exact && oterrestrial.hierarchy != terrestrial.hierarchy &&
344 oterrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy::HAuto &&
345 terrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy::HAuto)
347 else if (exact && oterrestrial.code_rate_LP != terrestrial.code_rate_LP &&
348 oterrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC::fAuto &&
349 terrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC::fAuto)
351 else if (exact && oterrestrial.code_rate_HP != terrestrial.code_rate_HP &&
352 oterrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC::fAuto &&
353 terrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC::fAuto)
356 diff = abs(terrestrial.frequency - oterrestrial.frequency);
364 RESULT eDVBFrontendParameters::getHash(unsigned long &hash) const
368 case iDVBFrontend::feSatellite:
370 hash = (sat.orbital_position << 16);
371 hash |= ((sat.frequency/1000)&0xFFFF)|((sat.polarisation&1) << 15);
374 case iDVBFrontend::feCable:
376 hash |= (cable.frequency/1000)&0xFFFF;
378 case iDVBFrontend::feTerrestrial:
380 hash |= (terrestrial.frequency/1000)&0xFFFF;
387 RESULT eDVBFrontendParameters::calcLockTimeout(unsigned int &timeout) const
391 case iDVBFrontend::feSatellite:
393 /* high symbol rate transponders tune faster, due to
394 requiring less zigzag and giving more symbols faster.
396 5s are definitely not enough on really low SR when
397 zigzag has to find the exact frequency first.
399 if (sat.symbol_rate > 20000000)
401 else if (sat.symbol_rate > 10000000)
407 case iDVBFrontend::feCable:
410 case iDVBFrontend::feTerrestrial:
418 DEFINE_REF(eDVBFrontend);
420 int eDVBFrontend::PriorityOrder=0;
422 eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok)
423 :m_enabled(false), m_type(-1), m_dvbid(fe), m_slotid(fe)
424 ,m_fd(-1), m_need_rotor_workaround(false), m_can_handle_dvbs2(false)
425 ,m_sn(0), m_timeout(0), m_tuneTimer(0)
426 #if HAVE_DVB_API_VERSION < 3
430 #if HAVE_DVB_API_VERSION < 3
431 sprintf(m_filename, "/dev/dvb/card%d/frontend%d", adap, fe);
432 sprintf(m_sec_filename, "/dev/dvb/card%d/sec%d", adap, fe);
434 sprintf(m_filename, "/dev/dvb/adapter%d/frontend%d", adap, fe);
436 m_timeout = new eTimer(eApp);
437 CONNECT(m_timeout->timeout, eDVBFrontend::timeout);
439 m_tuneTimer = new eTimer(eApp);
440 CONNECT(m_tuneTimer->timeout, eDVBFrontend::tuneLoop);
442 for (int i=0; i<eDVBFrontend::NUM_DATA_ENTRIES; ++i)
445 m_idleInputpower[0]=m_idleInputpower[1]=0;
447 ok = !openFrontend();
451 int eDVBFrontend::openFrontend()
454 return -1; // already opened
459 #if HAVE_DVB_API_VERSION < 3
460 FrontendInfo fe_info;
462 dvb_frontend_info fe_info;
464 eDebug("opening frontend %d", m_dvbid);
467 m_fd = ::open(m_filename, O_RDWR|O_NONBLOCK);
470 eWarning("failed! (%s) %m", m_filename);
475 eWarning("frontend %d already opened", m_dvbid);
478 if (::ioctl(m_fd, FE_GET_INFO, &fe_info) < 0)
480 eWarning("ioctl FE_GET_INFO failed");
486 switch (fe_info.type)
489 m_type = iDVBFrontend::feSatellite;
492 m_type = iDVBFrontend::feCable;
495 m_type = iDVBFrontend::feTerrestrial;
498 eWarning("unknown frontend type.");
503 eDebug("detected %s frontend", "satellite\0cable\0 terrestrial"+fe_info.type*10);
506 #if HAVE_DVB_API_VERSION < 3
507 if (m_type == iDVBFrontend::feSatellite)
511 m_secfd = ::open(m_sec_filename, O_RDWR);
514 eWarning("failed! (%s) %m", m_sec_filename);
521 eWarning("sec %d already opened", m_dvbid);
525 setTone(iDVBFrontend::toneOff);
526 setVoltage(iDVBFrontend::voltageOff);
528 m_sn = new eSocketNotifier(eApp, m_fd, eSocketNotifier::Read, false);
529 CONNECT(m_sn->activated, eDVBFrontend::feEvent);
534 int eDVBFrontend::closeFrontend(bool force)
536 if (!force && m_data[CUR_VOLTAGE] != -1 && m_data[CUR_VOLTAGE] != iDVBFrontend::voltageOff)
538 long tmp = m_data[LINKED_NEXT_PTR];
541 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
542 if (linked_fe->m_inuse)
544 eDebug("dont close frontend %d until the linked frontend %d in slot %d is still in use",
545 m_dvbid, linked_fe->m_frontend->getDVBID(), linked_fe->m_frontend->getSlotID());
548 linked_fe->m_frontend->getData(LINKED_NEXT_PTR, tmp);
553 eDebug("close frontend %d", m_dvbid);
555 setTone(iDVBFrontend::toneOff);
556 setVoltage(iDVBFrontend::voltageOff);
558 m_sec->setRotorMoving(false);
562 eWarning("couldnt close frontend %d", m_dvbid);
564 #if HAVE_DVB_API_VERSION < 3
567 if (!::close(m_secfd))
570 eWarning("couldnt close sec %d", m_dvbid);
575 m_state = stateClosed;
580 eDVBFrontend::~eDVBFrontend()
582 m_data[LINKED_PREV_PTR] = m_data[LINKED_NEXT_PTR] = -1;
588 void eDVBFrontend::feEvent(int w)
590 eDVBFrontend *sec_fe = this;
591 long tmp = m_data[LINKED_PREV_PTR];
594 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
595 sec_fe = linked_fe->m_frontend;
596 sec_fe->getData(LINKED_NEXT_PTR, tmp);
600 #if HAVE_DVB_API_VERSION < 3
603 dvb_frontend_event event;
607 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
609 if (res && (errno == EAGAIN))
614 eWarning("FE_GET_EVENT failed! %m");
621 #if HAVE_DVB_API_VERSION < 3
622 if (event.type == FE_COMPLETION_EV)
624 eDebug("(%d)fe event: status %x, inversion %s", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off");
625 if (event.status & FE_HAS_LOCK)
635 eDebug("stateLostLock");
636 state = stateLostLock;
637 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
640 if (m_state != state)
643 m_stateChanged(this);
648 void eDVBFrontend::timeout()
651 if (m_state == stateTuning)
653 m_state = stateFailed;
654 m_stateChanged(this);
658 #define INRANGE(X,Y,Z) (((X<=Y) && (Y<=Z))||((Z<=Y) && (Y<=X)) ? 1 : 0)
660 int eDVBFrontend::readFrontendData(int type)
667 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
668 eDebug("FE_READ_BER failed (%m)");
674 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
675 eDebug("FE_READ_SNR failed (%m)");
678 case signalQualitydB: /* this will move into the driver */
681 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
682 eDebug("FE_READ_SNR failed (%m)");
683 if (!strcmp(m_description, "BCM4501 (internal)"))
685 unsigned int SDS_SNRE = snr << 16;
687 static float SNR_COEFF[6] = {
690 197418.0 / 4194304.0,
691 -2602183.0 / 4194304.0,
692 20377212.0 / 4194304.0,
693 -37791203.0 / 4194304.0,
696 float fval1, fval2, snr_in_db;
698 fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0));
699 fval2 = pow(10.0, fval1)-1;
700 fval1 = 10.0 * log10(fval2);
704 fval2 = SNR_COEFF[0];
708 fval2 += SNR_COEFF[i];
714 return (int)(snr_in_db * 100.0);
716 else if (strstr(m_description, "Alps BSBE1 C01A") ||
717 !strcmp(m_description, "Alps -S(STV0288)"))
721 else if (snr == 0xFFFF) // i think this should not happen
725 enum { REALVAL, REGVAL };
726 const long CN_lookup[31][2] = {
727 {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
728 {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
729 {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
730 {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
731 {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
732 {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
735 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);
1524 eDebug("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1526 eDebug("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1528 if (!m_timeoutCount && m_retryCount > 0)
1533 ++m_sec_sequence.current();
1536 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1537 m_runningInputpower = sec_fe->readInputpower();
1538 eDebug("[SEC] runningInputpower is %d", m_runningInputpower);
1539 ++m_sec_sequence.current();
1541 case eSecCommand::SET_ROTOR_MOVING:
1542 m_sec->setRotorMoving(true);
1543 ++m_sec_sequence.current();
1545 case eSecCommand::SET_ROTOR_STOPPED:
1546 m_sec->setRotorMoving(false);
1547 ++m_sec_sequence.current();
1549 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1551 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1552 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1553 const char *txt = cmd.direction ? "running" : "stopped";
1554 eDebug("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1556 m_runningInputpower,
1559 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1560 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1563 eDebug("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1564 if ( cmd.okcount > 6 )
1566 eDebug("[SEC] rotor is %s", txt);
1567 if (setSecSequencePos(cmd.steps))
1573 eDebug("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1575 if (!m_timeoutCount && m_retryCount > 0)
1579 ++m_sec_sequence.current();
1582 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1583 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1584 setSecSequencePos(m_sec_sequence.current()->steps);
1586 ++m_sec_sequence.current();
1588 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1589 eDebug("[SEC] invalidate current switch params");
1590 sec_fe_data[CSW] = -1;
1591 sec_fe_data[UCSW] = -1;
1592 sec_fe_data[TONEBURST] = -1;
1593 ++m_sec_sequence.current();
1595 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1596 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1597 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1598 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1599 eDebug("[SEC] update current switch params");
1600 ++m_sec_sequence.current();
1602 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1603 eDebug("[SEC] invalidate current rotorparams");
1604 sec_fe_data[ROTOR_CMD] = -1;
1605 sec_fe_data[ROTOR_POS] = -1;
1606 ++m_sec_sequence.current();
1608 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1609 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1610 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1611 eDebug("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1612 ++m_sec_sequence.current();
1614 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1615 m_retryCount = m_sec_sequence.current()++->val;
1616 eDebug("[SEC] set rotor retries %d", m_retryCount);
1618 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1621 eDebug("[SEC] no more rotor retrys");
1622 setSecSequencePos(m_sec_sequence.current()->steps);
1625 ++m_sec_sequence.current();
1627 case eSecCommand::SET_POWER_LIMITING_MODE:
1630 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1631 FILE *f=fopen(proc_name, "w");
1632 if (f) // new interface exist?
1634 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1635 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1636 eDebug("write %s failed!! (%m)", proc_name);
1638 eDebug("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1641 else if (sec_fe->m_need_rotor_workaround)
1644 int slotid = sec_fe->m_slotid;
1645 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1647 sprintf(dev, "/dev/i2c/%d", slotid);
1648 else if (slotid == 2)
1649 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1650 else if (slotid == 3)
1651 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1652 int fd = ::open(dev, O_RDWR);
1654 unsigned char data[2];
1655 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1656 if(::read(fd, data, 1) != 1)
1657 eDebug("[SEC] error read lnbp (%m)");
1658 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1660 data[0] |= 0x80; // enable static current limiting
1661 eDebug("[SEC] set static current limiting");
1665 data[0] &= ~0x80; // enable dynamic current limiting
1666 eDebug("[SEC] set dynamic current limiting");
1668 if(::write(fd, data, 1) != 1)
1669 eDebug("[SEC] error write lnbp (%m)");
1672 ++m_sec_sequence.current();
1676 eDebug("[SEC] unhandled sec command %d",
1677 ++m_sec_sequence.current()->cmd);
1678 ++m_sec_sequence.current();
1680 m_tuneTimer->start(delay,true);
1686 void eDVBFrontend::setFrontend()
1688 eDebug("setting frontend %d", m_dvbid);
1691 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1693 perror("FE_SET_FRONTEND failed");
1698 RESULT eDVBFrontend::getFrontendType(int &t)
1706 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1711 eWarning("no SEC module active!");
1714 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1717 eDebug("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1720 feparm.polarisation,
1724 feparm.orbital_position);
1725 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1726 switch (feparm.inversion)
1728 case eDVBFrontendParametersSatellite::Inversion::On:
1729 parm_inversion = INVERSION_ON;
1731 case eDVBFrontendParametersSatellite::Inversion::Off:
1732 parm_inversion = INVERSION_OFF;
1735 case eDVBFrontendParametersSatellite::Inversion::Unknown:
1736 parm_inversion = INVERSION_AUTO;
1739 if (feparm.system == eDVBFrontendParametersSatellite::System::DVB_S)
1742 case eDVBFrontendParametersSatellite::FEC::fNone:
1743 parm_u_qpsk_fec_inner = FEC_NONE;
1745 case eDVBFrontendParametersSatellite::FEC::f1_2:
1746 parm_u_qpsk_fec_inner = FEC_1_2;
1748 case eDVBFrontendParametersSatellite::FEC::f2_3:
1749 parm_u_qpsk_fec_inner = FEC_2_3;
1751 case eDVBFrontendParametersSatellite::FEC::f3_4:
1752 parm_u_qpsk_fec_inner = FEC_3_4;
1754 case eDVBFrontendParametersSatellite::FEC::f5_6:
1755 parm_u_qpsk_fec_inner = FEC_5_6;
1757 case eDVBFrontendParametersSatellite::FEC::f7_8:
1758 parm_u_qpsk_fec_inner = FEC_7_8;
1761 eDebug("no valid fec for DVB-S set.. assume auto");
1762 case eDVBFrontendParametersSatellite::FEC::fAuto:
1763 parm_u_qpsk_fec_inner = FEC_AUTO;
1766 #if HAVE_DVB_API_VERSION >= 3
1771 case eDVBFrontendParametersSatellite::FEC::f1_2:
1772 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1774 case eDVBFrontendParametersSatellite::FEC::f2_3:
1775 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1777 case eDVBFrontendParametersSatellite::FEC::f3_4:
1778 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1780 case eDVBFrontendParametersSatellite::FEC::f3_5:
1781 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1783 case eDVBFrontendParametersSatellite::FEC::f4_5:
1784 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1786 case eDVBFrontendParametersSatellite::FEC::f5_6:
1787 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1789 case eDVBFrontendParametersSatellite::FEC::f7_8:
1790 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1792 case eDVBFrontendParametersSatellite::FEC::f8_9:
1793 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1795 case eDVBFrontendParametersSatellite::FEC::f9_10:
1796 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1799 eDebug("no valid fec for DVB-S2 set.. abort !!");
1802 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1803 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK) {
1804 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1805 // 8PSK fec driver values are decimal 9 bigger
1806 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1810 // FIXME !!! get frequency range from tuner
1811 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1813 eDebug("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1816 eDebug("tuning to %d mhz", parm_frequency/1000);
1821 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1823 #if HAVE_DVB_API_VERSION < 3
1824 parm_frequency = feparm.frequency;
1826 parm_frequency = feparm.frequency * 1000;
1828 parm_u_qam_symbol_rate = feparm.symbol_rate;
1829 switch (feparm.modulation)
1831 case eDVBFrontendParametersCable::Modulation::QAM16:
1832 parm_u_qam_modulation = QAM_16;
1834 case eDVBFrontendParametersCable::Modulation::QAM32:
1835 parm_u_qam_modulation = QAM_32;
1837 case eDVBFrontendParametersCable::Modulation::QAM64:
1838 parm_u_qam_modulation = QAM_64;
1840 case eDVBFrontendParametersCable::Modulation::QAM128:
1841 parm_u_qam_modulation = QAM_128;
1843 case eDVBFrontendParametersCable::Modulation::QAM256:
1844 parm_u_qam_modulation = QAM_256;
1847 case eDVBFrontendParametersCable::Modulation::Auto:
1848 parm_u_qam_modulation = QAM_AUTO;
1851 switch (feparm.inversion)
1853 case eDVBFrontendParametersCable::Inversion::On:
1854 parm_inversion = INVERSION_ON;
1856 case eDVBFrontendParametersCable::Inversion::Off:
1857 parm_inversion = INVERSION_OFF;
1860 case eDVBFrontendParametersCable::Inversion::Unknown:
1861 parm_inversion = INVERSION_AUTO;
1864 switch (feparm.fec_inner)
1866 case eDVBFrontendParametersCable::FEC::fNone:
1867 parm_u_qam_fec_inner = FEC_NONE;
1869 case eDVBFrontendParametersCable::FEC::f1_2:
1870 parm_u_qam_fec_inner = FEC_1_2;
1872 case eDVBFrontendParametersCable::FEC::f2_3:
1873 parm_u_qam_fec_inner = FEC_2_3;
1875 case eDVBFrontendParametersCable::FEC::f3_4:
1876 parm_u_qam_fec_inner = FEC_3_4;
1878 case eDVBFrontendParametersCable::FEC::f5_6:
1879 parm_u_qam_fec_inner = FEC_5_6;
1881 case eDVBFrontendParametersCable::FEC::f7_8:
1882 parm_u_qam_fec_inner = FEC_7_8;
1884 #if HAVE_DVB_API_VERSION >= 3
1885 case eDVBFrontendParametersCable::FEC::f8_9:
1886 parm_u_qam_fec_inner = FEC_8_9;
1890 case eDVBFrontendParametersCable::FEC::fAuto:
1891 parm_u_qam_fec_inner = FEC_AUTO;
1894 eDebug("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
1895 parm_frequency/1000,
1896 parm_u_qam_symbol_rate,
1897 parm_u_qam_fec_inner,
1898 parm_u_qam_modulation,
1903 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
1905 parm_frequency = feparm.frequency;
1907 switch (feparm.bandwidth)
1909 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
1910 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
1912 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
1913 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
1915 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
1916 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
1919 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
1920 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
1923 switch (feparm.code_rate_LP)
1925 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1926 parm_u_ofdm_code_rate_LP = FEC_1_2;
1928 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1929 parm_u_ofdm_code_rate_LP = FEC_2_3;
1931 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1932 parm_u_ofdm_code_rate_LP = FEC_3_4;
1934 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1935 parm_u_ofdm_code_rate_LP = FEC_5_6;
1937 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1938 parm_u_ofdm_code_rate_LP = FEC_7_8;
1941 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1942 parm_u_ofdm_code_rate_LP = FEC_AUTO;
1945 switch (feparm.code_rate_HP)
1947 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1948 parm_u_ofdm_code_rate_HP = FEC_1_2;
1950 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1951 parm_u_ofdm_code_rate_HP = FEC_2_3;
1953 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1954 parm_u_ofdm_code_rate_HP = FEC_3_4;
1956 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1957 parm_u_ofdm_code_rate_HP = FEC_5_6;
1959 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1960 parm_u_ofdm_code_rate_HP = FEC_7_8;
1963 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1964 parm_u_ofdm_code_rate_HP = FEC_AUTO;
1967 switch (feparm.modulation)
1969 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
1970 parm_u_ofdm_constellation = QPSK;
1972 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
1973 parm_u_ofdm_constellation = QAM_16;
1975 case eDVBFrontendParametersTerrestrial::Modulation::QAM64:
1976 parm_u_ofdm_constellation = QAM_64;
1979 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
1980 parm_u_ofdm_constellation = QAM_AUTO;
1983 switch (feparm.transmission_mode)
1985 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
1986 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
1988 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
1989 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
1992 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
1993 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
1996 switch (feparm.guard_interval)
1998 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32:
1999 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2001 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16:
2002 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2004 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8:
2005 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2007 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4:
2008 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2011 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto:
2012 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2015 switch (feparm.hierarchy)
2017 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone:
2018 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2020 case eDVBFrontendParametersTerrestrial::Hierarchy::H1:
2021 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2023 case eDVBFrontendParametersTerrestrial::Hierarchy::H2:
2024 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2026 case eDVBFrontendParametersTerrestrial::Hierarchy::H4:
2027 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2030 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto:
2031 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2034 switch (feparm.inversion)
2036 case eDVBFrontendParametersTerrestrial::Inversion::On:
2037 parm_inversion = INVERSION_ON;
2039 case eDVBFrontendParametersTerrestrial::Inversion::Off:
2040 parm_inversion = INVERSION_OFF;
2043 case eDVBFrontendParametersTerrestrial::Inversion::Unknown:
2044 parm_inversion = INVERSION_AUTO;
2050 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2052 unsigned int timeout = 5000;
2053 eDebug("(%d)tune", m_dvbid);
2061 eDebug("no frontend device opened... do not try to tune !!!");
2073 m_sec_sequence.clear();
2075 where.calcLockTimeout(timeout);
2081 eDVBFrontendParametersSatellite feparm;
2082 if (where.getDVBS(feparm))
2084 eDebug("no dvbs data!");
2088 m_sec->setRotorMoving(false);
2089 res=prepare_sat(feparm, timeout);
2097 eDVBFrontendParametersCable feparm;
2098 if (where.getDVBC(feparm))
2103 res=prepare_cable(feparm);
2107 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2108 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2113 eDVBFrontendParametersTerrestrial feparm;
2114 if (where.getDVBT(feparm))
2116 eDebug("no -T data");
2120 res=prepare_terrestrial(feparm);
2124 std::string enable_5V;
2125 char configStr[255];
2126 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2127 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2128 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2129 if (enable_5V == "True")
2130 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2132 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2133 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2139 m_tuneTimer->start(0,true);
2140 m_sec_sequence.current() = m_sec_sequence.begin();
2142 if (m_state != stateTuning)
2145 m_state = stateTuning;
2146 m_stateChanged(this);
2152 m_tuneTimer->stop();
2156 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2158 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2162 RESULT eDVBFrontend::setVoltage(int voltage)
2164 if (m_type == feCable)
2166 #if HAVE_DVB_API_VERSION < 3
2169 bool increased=false;
2170 fe_sec_voltage_t vlt;
2172 m_data[CUR_VOLTAGE]=voltage;
2176 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2177 vlt = SEC_VOLTAGE_OFF;
2180 #if HAVE_DVB_API_VERSION < 3
2181 vlt = SEC_VOLTAGE_13_5;
2187 vlt = SEC_VOLTAGE_13;
2190 #if HAVE_DVB_API_VERSION < 3
2191 vlt = SEC_VOLTAGE_18_5;
2197 vlt = SEC_VOLTAGE_18;
2202 #if HAVE_DVB_API_VERSION < 3
2203 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2205 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2206 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2207 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2211 RESULT eDVBFrontend::getState(int &state)
2217 RESULT eDVBFrontend::setTone(int t)
2219 if (m_type != feSatellite)
2221 #if HAVE_DVB_API_VERSION < 3
2224 fe_sec_tone_mode_t tone;
2233 tone = SEC_TONE_OFF;
2238 #if HAVE_DVB_API_VERSION < 3
2239 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2241 return ::ioctl(m_fd, FE_SET_TONE, tone);
2245 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2246 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2249 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2251 #if HAVE_DVB_API_VERSION < 3
2252 struct secCommand cmd;
2253 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2254 cmd.u.diseqc.cmdtype = diseqc.data[0];
2255 cmd.u.diseqc.addr = diseqc.data[1];
2256 cmd.u.diseqc.cmd = diseqc.data[2];
2257 cmd.u.diseqc.numParams = diseqc.len-3;
2258 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2259 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2261 struct dvb_diseqc_master_cmd cmd;
2262 memcpy(cmd.msg, diseqc.data, diseqc.len);
2263 cmd.msg_len = diseqc.len;
2264 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2270 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2271 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2273 RESULT eDVBFrontend::sendToneburst(int burst)
2275 #if HAVE_DVB_API_VERSION < 3
2276 secMiniCmd cmd = SEC_MINI_NONE;
2278 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2280 if ( burst == eDVBSatelliteDiseqcParameters::A )
2282 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2284 #if HAVE_DVB_API_VERSION < 3
2285 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2288 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2294 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2300 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2302 m_sec_sequence = list;
2306 RESULT eDVBFrontend::getData(int num, long &data)
2308 if ( num < NUM_DATA_ENTRIES )
2316 RESULT eDVBFrontend::setData(int num, long val)
2318 if ( num < NUM_DATA_ENTRIES )
2326 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2329 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2331 if (m_type == eDVBFrontend::feSatellite)
2334 eDVBFrontendParametersSatellite sat_parm;
2335 int ret = feparm->getDVBS(sat_parm);
2337 if (sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S2 && !m_can_handle_dvbs2)
2339 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2340 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S && m_can_handle_dvbs2)
2344 else if (m_type == eDVBFrontend::feCable)
2345 return 2; // more prio for cable frontends
2346 else if (m_type == eDVBFrontend::feTerrestrial)
2351 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2353 ePyObject Id, Descr, Enabled;
2354 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 3)
2356 Id = PyTuple_GET_ITEM(obj, 0);
2357 Descr = PyTuple_GET_ITEM(obj, 1);
2358 Enabled = PyTuple_GET_ITEM(obj, 2);
2359 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled))
2361 strcpy(m_description, PyString_AS_STRING(Descr));
2362 m_slotid = PyInt_AsLong(Id);
2363 m_enabled = Enabled == Py_True;
2364 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2365 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2366 !!strstr(m_description, "Alps BSBE2") ||
2367 !!strstr(m_description, "Alps -S") ||
2368 !!strstr(m_description, "BCM4501");
2369 m_can_handle_dvbs2 = !!strstr(m_description, "Alps BSBE2") || !!strstr(m_description, "BCM4501");
2370 eDebug("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2371 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2374 PyErr_SetString(PyExc_StandardError,
2375 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");