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 #define eDebugNoSimulate(x...) \
86 // eDebugNoNewLine("SIMULATE:"); \
90 #define eDebugNoSimulateNoNewLine(x...) \
97 // eDebugNoNewLine("SIMULATE:"); \
98 // eDebugNoNewLine(x); \
101 void eDVBDiseqcCommand::setCommandString(const char *str)
106 int slen = strlen(str);
109 eDebug("invalid diseqc command string length (not 2 byte aligned)");
112 if (slen > MAX_DISEQC_LENGTH*2)
114 eDebug("invalid diseqc command string length (string is to long)");
118 for (int i=0; i < slen; ++i)
120 unsigned char c = str[i];
123 case '0' ... '9': c-=48; break;
124 case 'a' ... 'f': c-=87; break;
125 case 'A' ... 'F': c-=55; break;
127 eDebug("invalid character in hex string..ignore complete diseqc command !");
141 void eDVBFrontendParametersSatellite::set(const SatelliteDeliverySystemDescriptor &descriptor)
143 frequency = descriptor.getFrequency() * 10;
144 symbol_rate = descriptor.getSymbolRate() * 100;
145 polarisation = descriptor.getPolarization();
146 fec = descriptor.getFecInner();
147 if ( fec != FEC::fNone && fec > FEC::f9_10 )
149 inversion = Inversion::Unknown;
150 pilot = Pilot::Unknown;
151 orbital_position = ((descriptor.getOrbitalPosition() >> 12) & 0xF) * 1000;
152 orbital_position += ((descriptor.getOrbitalPosition() >> 8) & 0xF) * 100;
153 orbital_position += ((descriptor.getOrbitalPosition() >> 4) & 0xF) * 10;
154 orbital_position += ((descriptor.getOrbitalPosition()) & 0xF);
155 if (orbital_position && (!descriptor.getWestEastFlag()))
156 orbital_position = 3600 - orbital_position;
157 system = descriptor.getModulationSystem();
158 modulation = descriptor.getModulation();
159 if (system == System::DVB_S && modulation == Modulation::M8PSK)
161 eDebug("satellite_delivery_descriptor non valid modulation type.. force QPSK");
164 rolloff = descriptor.getRollOff();
165 if (system == System::DVB_S2)
167 eDebug("SAT DVB-S2 freq %d, %s, pos %d, sr %d, fec %d, modulation %d, rolloff %d",
169 polarisation ? "hor" : "vert",
177 eDebug("SAT DVB-S freq %d, %s, pos %d, sr %d, fec %d",
179 polarisation ? "hor" : "vert",
185 void eDVBFrontendParametersCable::set(const CableDeliverySystemDescriptor &descriptor)
187 frequency = descriptor.getFrequency() / 10;
188 symbol_rate = descriptor.getSymbolRate() * 100;
189 fec_inner = descriptor.getFecInner();
190 if ( fec_inner == 0xF )
191 fec_inner = FEC::fNone;
192 modulation = descriptor.getModulation();
193 if ( modulation > 0x5 )
194 modulation = Modulation::Auto;
195 inversion = Inversion::Unknown;
196 eDebug("Cable freq %d, mod %d, sr %d, fec %d",
198 modulation, symbol_rate, fec_inner);
201 void eDVBFrontendParametersTerrestrial::set(const TerrestrialDeliverySystemDescriptor &descriptor)
203 frequency = descriptor.getCentreFrequency() * 10;
204 bandwidth = descriptor.getBandwidth();
205 if ( bandwidth > 2 ) // 5Mhz forced to auto
206 bandwidth = Bandwidth::BwAuto;
207 code_rate_HP = descriptor.getCodeRateHpStream();
208 if (code_rate_HP > 4)
209 code_rate_HP = FEC::fAuto;
210 code_rate_LP = descriptor.getCodeRateLpStream();
211 if (code_rate_LP > 4)
212 code_rate_LP = FEC::fAuto;
213 transmission_mode = descriptor.getTransmissionMode();
214 if (transmission_mode > 1) // TM4k forced to auto
215 transmission_mode = TransmissionMode::TMAuto;
216 guard_interval = descriptor.getGuardInterval();
217 if (guard_interval > 3)
218 guard_interval = GuardInterval::GI_Auto;
219 hierarchy = descriptor.getHierarchyInformation()&3;
220 modulation = descriptor.getConstellation();
222 modulation = Modulation::Auto;
223 inversion = Inversion::Unknown;
224 eDebug("Terr freq %d, bw %d, cr_hp %d, cr_lp %d, tm_mode %d, guard %d, hierarchy %d, const %d",
225 frequency, bandwidth, code_rate_HP, code_rate_LP, transmission_mode,
226 guard_interval, hierarchy, modulation);
229 eDVBFrontendParameters::eDVBFrontendParameters()
230 :m_type(-1), m_flags(0)
234 DEFINE_REF(eDVBFrontendParameters);
236 RESULT eDVBFrontendParameters::getSystem(int &t) const
244 RESULT eDVBFrontendParameters::getDVBS(eDVBFrontendParametersSatellite &p) const
246 if (m_type != iDVBFrontend::feSatellite)
252 RESULT eDVBFrontendParameters::getDVBC(eDVBFrontendParametersCable &p) const
254 if (m_type != iDVBFrontend::feCable)
260 RESULT eDVBFrontendParameters::getDVBT(eDVBFrontendParametersTerrestrial &p) const
262 if (m_type != iDVBFrontend::feTerrestrial)
268 RESULT eDVBFrontendParameters::setDVBS(const eDVBFrontendParametersSatellite &p, bool no_rotor_command_on_tune)
271 sat.no_rotor_command_on_tune = no_rotor_command_on_tune;
272 m_type = iDVBFrontend::feSatellite;
276 RESULT eDVBFrontendParameters::setDVBC(const eDVBFrontendParametersCable &p)
279 m_type = iDVBFrontend::feCable;
283 RESULT eDVBFrontendParameters::setDVBT(const eDVBFrontendParametersTerrestrial &p)
286 m_type = iDVBFrontend::feTerrestrial;
290 RESULT eDVBFrontendParameters::calculateDifference(const iDVBFrontendParameters *parm, int &diff, bool exact) const
295 if (parm->getSystem(type))
299 diff = 1<<30; // big difference
305 case iDVBFrontend::feSatellite:
307 eDVBFrontendParametersSatellite osat;
308 if (parm->getDVBS(osat))
311 if (sat.orbital_position != osat.orbital_position)
313 else if (sat.polarisation != osat.polarisation)
315 else if (exact && sat.fec != osat.fec && sat.fec != eDVBFrontendParametersSatellite::FEC::fAuto && osat.fec != eDVBFrontendParametersSatellite::FEC::fAuto)
317 else if (exact && sat.modulation != osat.modulation && sat.modulation != eDVBFrontendParametersSatellite::Modulation::Auto && osat.modulation != eDVBFrontendParametersSatellite::Modulation::Auto)
321 diff = abs(sat.frequency - osat.frequency);
322 diff += abs(sat.symbol_rate - osat.symbol_rate);
326 case iDVBFrontend::feCable:
327 eDVBFrontendParametersCable ocable;
328 if (parm->getDVBC(ocable))
331 if (exact && cable.modulation != ocable.modulation
332 && cable.modulation != eDVBFrontendParametersCable::Modulation::Auto
333 && ocable.modulation != eDVBFrontendParametersCable::Modulation::Auto)
335 else if (exact && cable.fec_inner != ocable.fec_inner && cable.fec_inner != eDVBFrontendParametersCable::FEC::fAuto && ocable.fec_inner != eDVBFrontendParametersCable::FEC::fAuto)
339 diff = abs(cable.frequency - ocable.frequency);
340 diff += abs(cable.symbol_rate - ocable.symbol_rate);
343 case iDVBFrontend::feTerrestrial:
344 eDVBFrontendParametersTerrestrial oterrestrial;
345 if (parm->getDVBT(oterrestrial))
348 if (exact && oterrestrial.bandwidth != terrestrial.bandwidth &&
349 oterrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto &&
350 terrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto)
352 else if (exact && oterrestrial.modulation != terrestrial.modulation &&
353 oterrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation::Auto &&
354 terrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation::Auto)
356 else if (exact && oterrestrial.transmission_mode != terrestrial.transmission_mode &&
357 oterrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto &&
358 terrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto)
360 else if (exact && oterrestrial.guard_interval != terrestrial.guard_interval &&
361 oterrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto &&
362 terrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto)
364 else if (exact && oterrestrial.hierarchy != terrestrial.hierarchy &&
365 oterrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy::HAuto &&
366 terrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy::HAuto)
368 else if (exact && oterrestrial.code_rate_LP != terrestrial.code_rate_LP &&
369 oterrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC::fAuto &&
370 terrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC::fAuto)
372 else if (exact && oterrestrial.code_rate_HP != terrestrial.code_rate_HP &&
373 oterrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC::fAuto &&
374 terrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC::fAuto)
377 diff = abs(terrestrial.frequency - oterrestrial.frequency);
385 RESULT eDVBFrontendParameters::getHash(unsigned long &hash) const
389 case iDVBFrontend::feSatellite:
391 hash = (sat.orbital_position << 16);
392 hash |= ((sat.frequency/1000)&0xFFFF)|((sat.polarisation&1) << 15);
395 case iDVBFrontend::feCable:
397 hash |= (cable.frequency/1000)&0xFFFF;
399 case iDVBFrontend::feTerrestrial:
401 hash |= (terrestrial.frequency/1000)&0xFFFF;
408 RESULT eDVBFrontendParameters::calcLockTimeout(unsigned int &timeout) const
412 case iDVBFrontend::feSatellite:
414 /* high symbol rate transponders tune faster, due to
415 requiring less zigzag and giving more symbols faster.
417 5s are definitely not enough on really low SR when
418 zigzag has to find the exact frequency first.
420 if (sat.symbol_rate > 20000000)
422 else if (sat.symbol_rate > 10000000)
428 case iDVBFrontend::feCable:
431 case iDVBFrontend::feTerrestrial:
439 DEFINE_REF(eDVBFrontend);
441 int eDVBFrontend::PriorityOrder=0;
443 eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok, bool simulate)
444 :m_simulate(simulate), m_enabled(false), m_type(-1), m_dvbid(fe), m_slotid(fe)
445 ,m_fd(-1), m_need_rotor_workaround(false), m_can_handle_dvbs2(false)
446 ,m_sn(0), m_timeout(0), m_tuneTimer(0)
447 #if HAVE_DVB_API_VERSION < 3
451 #if HAVE_DVB_API_VERSION < 3
452 sprintf(m_filename, "/dev/dvb/card%d/frontend%d", adap, fe);
453 sprintf(m_sec_filename, "/dev/dvb/card%d/sec%d", adap, fe);
455 sprintf(m_filename, "/dev/dvb/adapter%d/frontend%d", adap, fe);
458 m_timeout = new eTimer(eApp);
459 CONNECT(m_timeout->timeout, eDVBFrontend::timeout);
461 m_tuneTimer = new eTimer(eApp);
462 CONNECT(m_tuneTimer->timeout, eDVBFrontend::tuneLoop);
464 for (int i=0; i<eDVBFrontend::NUM_DATA_ENTRIES; ++i)
467 m_idleInputpower[0]=m_idleInputpower[1]=0;
469 ok = !openFrontend();
473 int eDVBFrontend::openFrontend()
476 return -1; // already opened
481 #if HAVE_DVB_API_VERSION < 3
482 FrontendInfo fe_info;
484 dvb_frontend_info fe_info;
486 eDebugNoSimulate("opening frontend %d", m_dvbid);
489 if (!m_simulate || m_type == -1)
491 m_fd = ::open(m_filename, O_RDWR|O_NONBLOCK);
494 eWarning("failed! (%s) %m", m_filename);
500 eWarning("frontend %d already opened", m_dvbid);
503 if (::ioctl(m_fd, FE_GET_INFO, &fe_info) < 0)
505 eWarning("ioctl FE_GET_INFO failed");
511 switch (fe_info.type)
514 m_type = iDVBFrontend::feSatellite;
517 m_type = iDVBFrontend::feCable;
520 m_type = iDVBFrontend::feTerrestrial;
523 eWarning("unknown frontend type.");
528 eDebugNoSimulate("detected %s frontend", "satellite\0cable\0 terrestrial"+fe_info.type*10);
531 #if HAVE_DVB_API_VERSION < 3
532 if (m_type == iDVBFrontend::feSatellite)
538 m_secfd = ::open(m_sec_filename, O_RDWR);
541 eWarning("failed! (%s) %m", m_sec_filename);
549 eWarning("sec %d already opened", m_dvbid);
553 setTone(iDVBFrontend::toneOff);
554 setVoltage(iDVBFrontend::voltageOff);
558 m_sn = new eSocketNotifier(eApp, m_fd, eSocketNotifier::Read, false);
559 CONNECT(m_sn->activated, eDVBFrontend::feEvent);
565 int eDVBFrontend::closeFrontend(bool force)
567 if (!force && m_data[CUR_VOLTAGE] != -1 && m_data[CUR_VOLTAGE] != iDVBFrontend::voltageOff)
569 long tmp = m_data[LINKED_NEXT_PTR];
572 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
573 if (linked_fe->m_inuse)
575 eDebugNoSimulate("dont close frontend %d until the linked frontend %d in slot %d is still in use",
576 m_dvbid, linked_fe->m_frontend->getDVBID(), linked_fe->m_frontend->getSlotID());
579 linked_fe->m_frontend->getData(LINKED_NEXT_PTR, tmp);
585 eDebugNoSimulate("close frontend %d", m_dvbid);
586 setTone(iDVBFrontend::toneOff);
587 setVoltage(iDVBFrontend::voltageOff);
589 if (m_sec && !m_simulate)
590 m_sec->setRotorMoving(false);
594 eWarning("couldnt close frontend %d", m_dvbid);
598 setTone(iDVBFrontend::toneOff);
599 setVoltage(iDVBFrontend::voltageOff);
601 #if HAVE_DVB_API_VERSION < 3
604 if (!::close(m_secfd))
607 eWarning("couldnt close sec %d", m_dvbid);
612 m_state = stateClosed;
617 eDVBFrontend::~eDVBFrontend()
619 m_data[LINKED_PREV_PTR] = m_data[LINKED_NEXT_PTR] = -1;
625 void eDVBFrontend::feEvent(int w)
627 eDVBFrontend *sec_fe = this;
628 long tmp = m_data[LINKED_PREV_PTR];
631 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
632 sec_fe = linked_fe->m_frontend;
633 sec_fe->getData(LINKED_NEXT_PTR, tmp);
637 #if HAVE_DVB_API_VERSION < 3
640 dvb_frontend_event event;
644 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
646 if (res && (errno == EAGAIN))
651 eWarning("FE_GET_EVENT failed! %m");
658 #if HAVE_DVB_API_VERSION < 3
659 if (event.type == FE_COMPLETION_EV)
661 eDebug("(%d)fe event: status %x, inversion %s", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off");
662 if (event.status & FE_HAS_LOCK)
672 eDebug("stateLostLock");
673 state = stateLostLock;
674 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
677 if (m_state != state)
680 m_stateChanged(this);
685 void eDVBFrontend::timeout()
688 if (m_state == stateTuning)
690 m_state = stateFailed;
691 m_stateChanged(this);
695 #define INRANGE(X,Y,Z) (((X<=Y) && (Y<=Z))||((Z<=Y) && (Y<=X)) ? 1 : 0)
697 int eDVBFrontend::readFrontendData(int type)
706 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
707 eDebug("FE_READ_BER failed (%m)");
716 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
717 eDebug("FE_READ_SNR failed (%m)");
721 case signalQualitydB: /* this will move into the driver */
726 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
727 eDebug("FE_READ_SNR failed (%m)");
728 if (!strcmp(m_description, "BCM4501 (internal)"))
730 unsigned int SDS_SNRE = snr << 16;
732 static float SNR_COEFF[6] = {
735 197418.0 / 4194304.0,
736 -2602183.0 / 4194304.0,
737 20377212.0 / 4194304.0,
738 -37791203.0 / 4194304.0,
741 float fval1, fval2, snr_in_db;
743 fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0));
744 fval2 = pow(10.0, fval1)-1;
745 fval1 = 10.0 * log10(fval2);
749 fval2 = SNR_COEFF[0];
753 fval2 += SNR_COEFF[i];
759 return (int)(snr_in_db * 100.0);
761 else if (strstr(m_description, "Alps BSBE1 C01A") ||
762 !strcmp(m_description, "Alps -S(STV0288)"))
766 else if (snr == 0xFFFF) // i think this should not happen
770 enum { REALVAL, REGVAL };
771 const long CN_lookup[31][2] = {
772 {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
773 {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
774 {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
775 {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
776 {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
777 {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
780 int add=strchr(m_description, '.') ? 0xA250 : 0xA100;
781 long regval = 0xFFFF - ((snr / 3) + add), // revert some dvb api calulations to get the real register value
785 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
791 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[i][REGVAL]))
796 return (((regval - CN_lookup[Imin][REGVAL])
797 * (CN_lookup[Imax][REALVAL] - CN_lookup[Imin][REALVAL])
798 / (CN_lookup[Imax][REGVAL] - CN_lookup[Imin][REGVAL]))
799 + CN_lookup[Imin][REALVAL]) * 10;
805 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
806 !strcmp(m_description, "Alps -S") ||
807 !strcmp(m_description, "Philips -S") ||
808 !strcmp(m_description, "LG -S") )
810 float snr_in_db=(snr-39075)/1764.7;
811 return (int)(snr_in_db * 100.0);
812 } else if (!strcmp(m_description, "Alps BSBE2"))
814 return (int)((snr >> 7) * 10.0);
816 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
824 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
825 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
831 #if HAVE_DVB_API_VERSION < 3
832 FrontendStatus status=0;
838 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
839 eDebug("FE_READ_STATUS failed (%m)");
840 return !!(status&FE_HAS_LOCK);
846 #if HAVE_DVB_API_VERSION < 3
847 FrontendStatus status=0;
853 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
854 eDebug("FE_READ_STATUS failed (%m)");
855 return !!(status&FE_HAS_SYNC);
865 void PutToDict(ePyObject &dict, const char*key, long value)
867 ePyObject item = PyInt_FromLong(value);
870 if (PyDict_SetItemString(dict, key, item))
871 eDebug("put %s to dict failed", key);
875 eDebug("could not create PyObject for %s", key);
878 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
882 if (PyDict_SetItemString(dict, key, item))
883 eDebug("put %s to dict failed", key);
887 eDebug("invalid PyObject for %s", key);
890 void PutToDict(ePyObject &dict, const char*key, const char *value)
892 ePyObject item = PyString_FromString(value);
895 if (PyDict_SetItemString(dict, key, item))
896 eDebug("put %s to dict failed", key);
900 eDebug("could not create PyObject for %s", key);
903 void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, eDVBFrontend *fe)
907 fe->getData(eDVBFrontend::FREQ_OFFSET, freq_offset);
908 int frequency = parm_frequency + freq_offset;
909 PutToDict(dict, "frequency", frequency);
910 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
911 switch(parm_u_qpsk_fec_inner)
934 #if HAVE_DVB_API_VERSION >=3
935 case FEC_S2_8PSK_1_2:
936 case FEC_S2_QPSK_1_2:
939 case FEC_S2_8PSK_2_3:
940 case FEC_S2_QPSK_2_3:
943 case FEC_S2_8PSK_3_4:
944 case FEC_S2_QPSK_3_4:
947 case FEC_S2_8PSK_5_6:
948 case FEC_S2_QPSK_5_6:
951 case FEC_S2_8PSK_7_8:
952 case FEC_S2_QPSK_7_8:
955 case FEC_S2_8PSK_8_9:
956 case FEC_S2_QPSK_8_9:
959 case FEC_S2_8PSK_3_5:
960 case FEC_S2_QPSK_3_5:
963 case FEC_S2_8PSK_4_5:
964 case FEC_S2_QPSK_4_5:
967 case FEC_S2_8PSK_9_10:
968 case FEC_S2_QPSK_9_10:
973 PutToDict(dict, "fec_inner", tmp);
974 #if HAVE_DVB_API_VERSION >=3
975 PutToDict(dict, "modulation",
976 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ? "8PSK": "QPSK" );
977 if (parm_u_qpsk_fec_inner > FEC_AUTO)
979 switch(parm_inversion & 0xc)
981 default: // unknown rolloff
983 tmp = "ROLLOFF_0_35";
986 tmp = "ROLLOFF_0_25";
989 tmp = "ROLLOFF_0_20";
992 PutToDict(dict, "rolloff", tmp);
993 if (parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10)
995 switch(parm_inversion & 0x30)
1000 case 0x10: // pilot on
1003 case 0x20: // pilot auto
1007 PutToDict(dict, "pilot", tmp);
1014 PutToDict(dict, "modulation", "QPSK" );
1017 PutToDict(dict, "system", tmp);
1020 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1023 #if HAVE_DVB_API_VERSION < 3
1024 PutToDict(dict, "frequency", parm_frequency);
1026 PutToDict(dict, "frequency", parm_frequency/1000);
1028 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1029 switch(parm_u_qam_fec_inner)
1049 #if HAVE_DVB_API_VERSION >= 3
1059 PutToDict(dict, "fec_inner", tmp);
1060 switch(parm_u_qam_modulation)
1082 PutToDict(dict, "modulation", tmp);
1085 void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1088 PutToDict(dict, "frequency", parm_frequency);
1089 switch (parm_u_ofdm_bandwidth)
1091 case BANDWIDTH_8_MHZ:
1092 tmp = "BANDWIDTH_8_MHZ";
1094 case BANDWIDTH_7_MHZ:
1095 tmp = "BANDWIDTH_7_MHZ";
1097 case BANDWIDTH_6_MHZ:
1098 tmp = "BANDWIDTH_6_MHZ";
1101 case BANDWIDTH_AUTO:
1102 tmp = "BANDWIDTH_AUTO";
1105 PutToDict(dict, "bandwidth", tmp);
1106 switch (parm_u_ofdm_code_rate_LP)
1128 PutToDict(dict, "code_rate_lp", tmp);
1129 switch (parm_u_ofdm_code_rate_HP)
1151 PutToDict(dict, "code_rate_hp", tmp);
1152 switch (parm_u_ofdm_constellation)
1168 PutToDict(dict, "constellation", tmp);
1169 switch (parm_u_ofdm_transmission_mode)
1171 case TRANSMISSION_MODE_2K:
1172 tmp = "TRANSMISSION_MODE_2K";
1174 case TRANSMISSION_MODE_8K:
1175 tmp = "TRANSMISSION_MODE_8K";
1178 case TRANSMISSION_MODE_AUTO:
1179 tmp = "TRANSMISSION_MODE_AUTO";
1182 PutToDict(dict, "transmission_mode", tmp);
1183 switch (parm_u_ofdm_guard_interval)
1185 case GUARD_INTERVAL_1_32:
1186 tmp = "GUARD_INTERVAL_1_32";
1188 case GUARD_INTERVAL_1_16:
1189 tmp = "GUARD_INTERVAL_1_16";
1191 case GUARD_INTERVAL_1_8:
1192 tmp = "GUARD_INTERVAL_1_8";
1194 case GUARD_INTERVAL_1_4:
1195 tmp = "GUARD_INTERVAL_1_4";
1198 case GUARD_INTERVAL_AUTO:
1199 tmp = "GUARD_INTERVAL_AUTO";
1202 PutToDict(dict, "guard_interval", tmp);
1203 switch (parm_u_ofdm_hierarchy_information)
1205 case HIERARCHY_NONE:
1206 tmp = "HIERARCHY_NONE";
1209 tmp = "HIERARCHY_1";
1212 tmp = "HIERARCHY_2";
1215 tmp = "HIERARCHY_4";
1218 case HIERARCHY_AUTO:
1219 tmp = "HIERARCHY_AUTO";
1222 PutToDict(dict, "hierarchy_information", tmp);
1225 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1227 if (dest && PyDict_Check(dest))
1229 const char *tmp = "UNKNOWN";
1250 PutToDict(dest, "tuner_state", tmp);
1251 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1252 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1253 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1254 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1255 int sigQualitydB = readFrontendData(signalQualitydB);
1256 if (sigQualitydB == 0x12345678) // not support yet
1258 ePyObject obj=Py_None;
1260 PutToDict(dest, "tuner_signal_quality_db", obj);
1263 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1264 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1268 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1270 if (dest && PyDict_Check(dest))
1278 FRONTENDPARAMETERS front;
1281 if (!m_simulate && m_fd != -1 && ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1282 eDebug("FE_GET_FRONTEND (%m)");
1286 const FRONTENDPARAMETERS &parm = original ? this->parm : front;
1287 const char *tmp = "INVERSION_AUTO";
1288 switch(parm_inversion)
1291 tmp = "INVERSION_ON";
1294 tmp = "INVERSION_OFF";
1300 PutToDict(dest, "inversion", tmp);
1305 fillDictWithSatelliteData(dest, original?parm:front, this);
1308 fillDictWithCableData(dest, original?parm:front);
1311 fillDictWithTerrestrialData(dest, original?parm:front);
1322 void eDVBFrontend::getFrontendData(ePyObject dest)
1324 if (dest && PyDict_Check(dest))
1327 PutToDict(dest, "tuner_number", m_slotid);
1343 PutToDict(dest, "tuner_type", tmp);
1347 #ifndef FP_IOCTL_GET_ID
1348 #define FP_IOCTL_GET_ID 0
1350 int eDVBFrontend::readInputpower()
1354 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1356 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1357 FILE *f=fopen(proc_name, "r");
1360 if (fscanf(f, "%d", &power) != 1)
1361 eDebug("read %s failed!! (%m)", proc_name);
1363 eDebug("%s is %d\n", proc_name, power);
1368 // open front prozessor
1369 int fp=::open("/dev/dbox/fp0", O_RDWR);
1372 eDebug("couldn't open fp");
1375 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1376 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1378 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1387 bool eDVBFrontend::setSecSequencePos(int steps)
1389 eDebugNoSimulate("set sequence pos %d", steps);
1394 if (m_sec_sequence.current() != m_sec_sequence.end())
1395 ++m_sec_sequence.current();
1400 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1401 --m_sec_sequence.current();
1407 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1410 eDVBFrontend *sec_fe = this;
1411 eDVBRegisteredFrontend *regFE = 0;
1412 long tmp = m_data[LINKED_PREV_PTR];
1415 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1416 sec_fe = prev->m_frontend;
1417 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1418 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1419 int state = sec_fe->m_state;
1420 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1422 sec_fe->closeFrontend(true);
1423 state = sec_fe->m_state;
1425 if (state == eDVBFrontend::stateClosed)
1433 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1435 long *sec_fe_data = sec_fe->m_data;
1436 // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1437 switch (m_sec_sequence.current()->cmd)
1439 case eSecCommand::SLEEP:
1440 delay = m_sec_sequence.current()++->msec;
1441 eDebugNoSimulate("[SEC] sleep %dms", delay);
1443 case eSecCommand::GOTO:
1444 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1445 ++m_sec_sequence.current();
1447 case eSecCommand::SET_VOLTAGE:
1449 int voltage = m_sec_sequence.current()++->voltage;
1450 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1451 sec_fe->setVoltage(voltage);
1454 case eSecCommand::IF_VOLTAGE_GOTO:
1456 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1457 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1459 ++m_sec_sequence.current();
1462 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1464 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1465 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1467 ++m_sec_sequence.current();
1470 case eSecCommand::IF_TONE_GOTO:
1472 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1473 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1475 ++m_sec_sequence.current();
1478 case eSecCommand::IF_NOT_TONE_GOTO:
1480 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1481 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1483 ++m_sec_sequence.current();
1486 case eSecCommand::SET_TONE:
1487 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1488 sec_fe->setTone(m_sec_sequence.current()++->tone);
1490 case eSecCommand::SEND_DISEQC:
1491 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1492 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1493 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1494 eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1495 eDebugNoSimulate("");
1496 ++m_sec_sequence.current();
1498 case eSecCommand::SEND_TONEBURST:
1499 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1500 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1502 case eSecCommand::SET_FRONTEND:
1503 eDebugNoSimulate("[SEC] setFrontend");
1505 ++m_sec_sequence.current();
1507 case eSecCommand::START_TUNE_TIMEOUT:
1510 m_timeout->start(m_sec_sequence.current()->timeout, 1);
1511 ++m_sec_sequence.current();
1514 case eSecCommand::SET_TIMEOUT:
1515 m_timeoutCount = m_sec_sequence.current()++->val;
1516 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1518 case eSecCommand::IF_TIMEOUT_GOTO:
1519 if (!m_timeoutCount)
1521 eDebugNoSimulate("[SEC] rotor timout");
1522 setSecSequencePos(m_sec_sequence.current()->steps);
1525 ++m_sec_sequence.current();
1527 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1529 int idx = m_sec_sequence.current()++->val;
1530 if ( idx == 0 || idx == 1 )
1532 m_idleInputpower[idx] = sec_fe->readInputpower();
1533 eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1536 eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1539 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1541 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1542 int idx = compare.val;
1543 if ( !m_simulate && (idx == 0 || idx == 1) )
1545 int idle = sec_fe->readInputpower();
1546 int diff = abs(idle-m_idleInputpower[idx]);
1549 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1550 setSecSequencePos(compare.steps);
1554 ++m_sec_sequence.current();
1557 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1559 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1562 setSecSequencePos(cmd.steps);
1566 int isLocked = readFrontendData(locked);
1567 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1568 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 50) || !cmd.lastSignal))
1571 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1574 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1575 cmd.lastSignal = signal;
1578 if (cmd.okcount > 4)
1580 eDebugNoSimulate("ok > 4 .. goto %d\n",cmd.steps);
1581 setSecSequencePos(cmd.steps);
1582 m_state = stateLock;
1583 m_stateChanged(this);
1592 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1594 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1596 if (!m_timeoutCount && m_retryCount > 0)
1601 ++m_sec_sequence.current();
1604 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1605 m_runningInputpower = sec_fe->readInputpower();
1606 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1607 ++m_sec_sequence.current();
1609 case eSecCommand::SET_ROTOR_MOVING:
1611 m_sec->setRotorMoving(true);
1612 ++m_sec_sequence.current();
1614 case eSecCommand::SET_ROTOR_STOPPED:
1616 m_sec->setRotorMoving(false);
1617 ++m_sec_sequence.current();
1619 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1621 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1624 setSecSequencePos(cmd.steps);
1627 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1628 const char *txt = cmd.direction ? "running" : "stopped";
1629 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1631 m_runningInputpower,
1634 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1635 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1638 eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1639 if ( cmd.okcount > 6 )
1641 eDebugNoSimulate("[SEC] rotor is %s", txt);
1642 if (setSecSequencePos(cmd.steps))
1648 eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1650 if (!m_timeoutCount && m_retryCount > 0)
1654 ++m_sec_sequence.current();
1657 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1658 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1659 setSecSequencePos(m_sec_sequence.current()->steps);
1661 ++m_sec_sequence.current();
1663 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1664 eDebugNoSimulate("[SEC] invalidate current switch params");
1665 sec_fe_data[CSW] = -1;
1666 sec_fe_data[UCSW] = -1;
1667 sec_fe_data[TONEBURST] = -1;
1668 ++m_sec_sequence.current();
1670 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1671 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1672 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1673 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1674 eDebugNoSimulate("[SEC] update current switch params");
1675 ++m_sec_sequence.current();
1677 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1678 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1679 sec_fe_data[ROTOR_CMD] = -1;
1680 sec_fe_data[ROTOR_POS] = -1;
1681 ++m_sec_sequence.current();
1683 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1684 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1685 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1686 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1687 ++m_sec_sequence.current();
1689 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1690 m_retryCount = m_sec_sequence.current()++->val;
1691 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1693 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1696 eDebugNoSimulate("[SEC] no more rotor retrys");
1697 setSecSequencePos(m_sec_sequence.current()->steps);
1700 ++m_sec_sequence.current();
1702 case eSecCommand::SET_POWER_LIMITING_MODE:
1707 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1708 FILE *f=fopen(proc_name, "w");
1709 if (f) // new interface exist?
1711 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1712 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1713 eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1715 eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1718 else if (sec_fe->m_need_rotor_workaround)
1721 int slotid = sec_fe->m_slotid;
1722 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1724 sprintf(dev, "/dev/i2c/%d", slotid);
1725 else if (slotid == 2)
1726 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1727 else if (slotid == 3)
1728 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1729 int fd = ::open(dev, O_RDWR);
1731 unsigned char data[2];
1732 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1733 if(::read(fd, data, 1) != 1)
1734 eDebugNoSimulate("[SEC] error read lnbp (%m)");
1735 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1737 data[0] |= 0x80; // enable static current limiting
1738 eDebugNoSimulate("[SEC] set static current limiting");
1742 data[0] &= ~0x80; // enable dynamic current limiting
1743 eDebugNoSimulate("[SEC] set dynamic current limiting");
1745 if(::write(fd, data, 1) != 1)
1746 eDebugNoSimulate("[SEC] error write lnbp (%m)");
1750 ++m_sec_sequence.current();
1754 eDebugNoSimulate("[SEC] unhandled sec command %d",
1755 ++m_sec_sequence.current()->cmd);
1756 ++m_sec_sequence.current();
1759 m_tuneTimer->start(delay,true);
1763 if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1767 void eDVBFrontend::setFrontend()
1771 eDebug("setting frontend %d", m_dvbid);
1774 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1776 perror("FE_SET_FRONTEND failed");
1782 RESULT eDVBFrontend::getFrontendType(int &t)
1790 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1795 eWarning("no SEC module active!");
1798 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1801 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1804 feparm.polarisation,
1808 feparm.orbital_position);
1809 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1810 switch (feparm.inversion)
1812 case eDVBFrontendParametersSatellite::Inversion::On:
1813 parm_inversion = INVERSION_ON;
1815 case eDVBFrontendParametersSatellite::Inversion::Off:
1816 parm_inversion = INVERSION_OFF;
1819 case eDVBFrontendParametersSatellite::Inversion::Unknown:
1820 parm_inversion = INVERSION_AUTO;
1823 if (feparm.system == eDVBFrontendParametersSatellite::System::DVB_S)
1826 case eDVBFrontendParametersSatellite::FEC::fNone:
1827 parm_u_qpsk_fec_inner = FEC_NONE;
1829 case eDVBFrontendParametersSatellite::FEC::f1_2:
1830 parm_u_qpsk_fec_inner = FEC_1_2;
1832 case eDVBFrontendParametersSatellite::FEC::f2_3:
1833 parm_u_qpsk_fec_inner = FEC_2_3;
1835 case eDVBFrontendParametersSatellite::FEC::f3_4:
1836 parm_u_qpsk_fec_inner = FEC_3_4;
1838 case eDVBFrontendParametersSatellite::FEC::f5_6:
1839 parm_u_qpsk_fec_inner = FEC_5_6;
1841 case eDVBFrontendParametersSatellite::FEC::f7_8:
1842 parm_u_qpsk_fec_inner = FEC_7_8;
1845 eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
1846 case eDVBFrontendParametersSatellite::FEC::fAuto:
1847 parm_u_qpsk_fec_inner = FEC_AUTO;
1850 #if HAVE_DVB_API_VERSION >= 3
1855 case eDVBFrontendParametersSatellite::FEC::f1_2:
1856 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1858 case eDVBFrontendParametersSatellite::FEC::f2_3:
1859 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1861 case eDVBFrontendParametersSatellite::FEC::f3_4:
1862 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1864 case eDVBFrontendParametersSatellite::FEC::f3_5:
1865 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1867 case eDVBFrontendParametersSatellite::FEC::f4_5:
1868 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1870 case eDVBFrontendParametersSatellite::FEC::f5_6:
1871 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1873 case eDVBFrontendParametersSatellite::FEC::f7_8:
1874 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1876 case eDVBFrontendParametersSatellite::FEC::f8_9:
1877 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1879 case eDVBFrontendParametersSatellite::FEC::f9_10:
1880 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1883 eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
1886 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1887 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK) {
1888 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1889 // 8PSK fec driver values are decimal 9 bigger
1890 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1894 // FIXME !!! get frequency range from tuner
1895 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1897 eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1900 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
1905 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1907 #if HAVE_DVB_API_VERSION < 3
1908 parm_frequency = feparm.frequency;
1910 parm_frequency = feparm.frequency * 1000;
1912 parm_u_qam_symbol_rate = feparm.symbol_rate;
1913 switch (feparm.modulation)
1915 case eDVBFrontendParametersCable::Modulation::QAM16:
1916 parm_u_qam_modulation = QAM_16;
1918 case eDVBFrontendParametersCable::Modulation::QAM32:
1919 parm_u_qam_modulation = QAM_32;
1921 case eDVBFrontendParametersCable::Modulation::QAM64:
1922 parm_u_qam_modulation = QAM_64;
1924 case eDVBFrontendParametersCable::Modulation::QAM128:
1925 parm_u_qam_modulation = QAM_128;
1927 case eDVBFrontendParametersCable::Modulation::QAM256:
1928 parm_u_qam_modulation = QAM_256;
1931 case eDVBFrontendParametersCable::Modulation::Auto:
1932 parm_u_qam_modulation = QAM_AUTO;
1935 switch (feparm.inversion)
1937 case eDVBFrontendParametersCable::Inversion::On:
1938 parm_inversion = INVERSION_ON;
1940 case eDVBFrontendParametersCable::Inversion::Off:
1941 parm_inversion = INVERSION_OFF;
1944 case eDVBFrontendParametersCable::Inversion::Unknown:
1945 parm_inversion = INVERSION_AUTO;
1948 switch (feparm.fec_inner)
1950 case eDVBFrontendParametersCable::FEC::fNone:
1951 parm_u_qam_fec_inner = FEC_NONE;
1953 case eDVBFrontendParametersCable::FEC::f1_2:
1954 parm_u_qam_fec_inner = FEC_1_2;
1956 case eDVBFrontendParametersCable::FEC::f2_3:
1957 parm_u_qam_fec_inner = FEC_2_3;
1959 case eDVBFrontendParametersCable::FEC::f3_4:
1960 parm_u_qam_fec_inner = FEC_3_4;
1962 case eDVBFrontendParametersCable::FEC::f5_6:
1963 parm_u_qam_fec_inner = FEC_5_6;
1965 case eDVBFrontendParametersCable::FEC::f7_8:
1966 parm_u_qam_fec_inner = FEC_7_8;
1968 #if HAVE_DVB_API_VERSION >= 3
1969 case eDVBFrontendParametersCable::FEC::f8_9:
1970 parm_u_qam_fec_inner = FEC_8_9;
1974 case eDVBFrontendParametersCable::FEC::fAuto:
1975 parm_u_qam_fec_inner = FEC_AUTO;
1978 eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
1979 parm_frequency/1000,
1980 parm_u_qam_symbol_rate,
1981 parm_u_qam_fec_inner,
1982 parm_u_qam_modulation,
1987 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
1989 parm_frequency = feparm.frequency;
1991 switch (feparm.bandwidth)
1993 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
1994 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
1996 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
1997 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
1999 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
2000 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
2003 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
2004 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
2007 switch (feparm.code_rate_LP)
2009 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
2010 parm_u_ofdm_code_rate_LP = FEC_1_2;
2012 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
2013 parm_u_ofdm_code_rate_LP = FEC_2_3;
2015 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
2016 parm_u_ofdm_code_rate_LP = FEC_3_4;
2018 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
2019 parm_u_ofdm_code_rate_LP = FEC_5_6;
2021 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
2022 parm_u_ofdm_code_rate_LP = FEC_7_8;
2025 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
2026 parm_u_ofdm_code_rate_LP = FEC_AUTO;
2029 switch (feparm.code_rate_HP)
2031 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
2032 parm_u_ofdm_code_rate_HP = FEC_1_2;
2034 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
2035 parm_u_ofdm_code_rate_HP = FEC_2_3;
2037 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
2038 parm_u_ofdm_code_rate_HP = FEC_3_4;
2040 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
2041 parm_u_ofdm_code_rate_HP = FEC_5_6;
2043 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
2044 parm_u_ofdm_code_rate_HP = FEC_7_8;
2047 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
2048 parm_u_ofdm_code_rate_HP = FEC_AUTO;
2051 switch (feparm.modulation)
2053 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
2054 parm_u_ofdm_constellation = QPSK;
2056 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
2057 parm_u_ofdm_constellation = QAM_16;
2059 case eDVBFrontendParametersTerrestrial::Modulation::QAM64:
2060 parm_u_ofdm_constellation = QAM_64;
2063 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
2064 parm_u_ofdm_constellation = QAM_AUTO;
2067 switch (feparm.transmission_mode)
2069 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
2070 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2072 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
2073 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2076 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
2077 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2080 switch (feparm.guard_interval)
2082 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32:
2083 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2085 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16:
2086 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2088 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8:
2089 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2091 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4:
2092 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2095 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto:
2096 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2099 switch (feparm.hierarchy)
2101 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone:
2102 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2104 case eDVBFrontendParametersTerrestrial::Hierarchy::H1:
2105 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2107 case eDVBFrontendParametersTerrestrial::Hierarchy::H2:
2108 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2110 case eDVBFrontendParametersTerrestrial::Hierarchy::H4:
2111 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2114 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto:
2115 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2118 switch (feparm.inversion)
2120 case eDVBFrontendParametersTerrestrial::Inversion::On:
2121 parm_inversion = INVERSION_ON;
2123 case eDVBFrontendParametersTerrestrial::Inversion::Off:
2124 parm_inversion = INVERSION_OFF;
2127 case eDVBFrontendParametersTerrestrial::Inversion::Unknown:
2128 parm_inversion = INVERSION_AUTO;
2134 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2136 unsigned int timeout = 5000;
2137 eDebugNoSimulate("(%d)tune", m_dvbid);
2143 if (!m_sn && !m_simulate)
2145 eDebug("no frontend device opened... do not try to tune !!!");
2159 m_sec_sequence.clear();
2161 where.calcLockTimeout(timeout);
2167 eDVBFrontendParametersSatellite feparm;
2168 if (where.getDVBS(feparm))
2170 eDebug("no dvbs data!");
2175 m_sec->setRotorMoving(false);
2176 res=prepare_sat(feparm, timeout);
2184 eDVBFrontendParametersCable feparm;
2185 if (where.getDVBC(feparm))
2190 res=prepare_cable(feparm);
2194 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2195 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2200 eDVBFrontendParametersTerrestrial feparm;
2201 if (where.getDVBT(feparm))
2203 eDebug("no -T data");
2207 res=prepare_terrestrial(feparm);
2211 std::string enable_5V;
2212 char configStr[255];
2213 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2214 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2215 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2216 if (enable_5V == "True")
2217 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2219 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2220 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2226 m_sec_sequence.current() = m_sec_sequence.begin();
2230 m_tuneTimer->start(0,true);
2231 if (m_state != stateTuning)
2234 m_state = stateTuning;
2235 m_stateChanged(this);
2244 m_tuneTimer->stop();
2248 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2250 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2254 RESULT eDVBFrontend::setVoltage(int voltage)
2256 if (m_type == feCable)
2258 #if HAVE_DVB_API_VERSION < 3
2261 bool increased=false;
2262 fe_sec_voltage_t vlt;
2264 m_data[CUR_VOLTAGE]=voltage;
2268 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2269 vlt = SEC_VOLTAGE_OFF;
2272 #if HAVE_DVB_API_VERSION < 3
2273 vlt = SEC_VOLTAGE_13_5;
2279 vlt = SEC_VOLTAGE_13;
2282 #if HAVE_DVB_API_VERSION < 3
2283 vlt = SEC_VOLTAGE_18_5;
2289 vlt = SEC_VOLTAGE_18;
2296 #if HAVE_DVB_API_VERSION < 3
2297 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2299 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2300 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2301 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2305 RESULT eDVBFrontend::getState(int &state)
2311 RESULT eDVBFrontend::setTone(int t)
2313 if (m_type != feSatellite)
2315 #if HAVE_DVB_API_VERSION < 3
2318 fe_sec_tone_mode_t tone;
2327 tone = SEC_TONE_OFF;
2334 #if HAVE_DVB_API_VERSION < 3
2335 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2337 return ::ioctl(m_fd, FE_SET_TONE, tone);
2341 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2342 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2345 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2349 #if HAVE_DVB_API_VERSION < 3
2350 struct secCommand cmd;
2351 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2352 cmd.u.diseqc.cmdtype = diseqc.data[0];
2353 cmd.u.diseqc.addr = diseqc.data[1];
2354 cmd.u.diseqc.cmd = diseqc.data[2];
2355 cmd.u.diseqc.numParams = diseqc.len-3;
2356 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2357 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2359 struct dvb_diseqc_master_cmd cmd;
2360 memcpy(cmd.msg, diseqc.data, diseqc.len);
2361 cmd.msg_len = diseqc.len;
2362 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2368 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2369 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2371 RESULT eDVBFrontend::sendToneburst(int burst)
2375 #if HAVE_DVB_API_VERSION < 3
2376 secMiniCmd cmd = SEC_MINI_NONE;
2378 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2380 if ( burst == eDVBSatelliteDiseqcParameters::A )
2382 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2384 #if HAVE_DVB_API_VERSION < 3
2385 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2388 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2394 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2400 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2402 m_sec_sequence = list;
2406 RESULT eDVBFrontend::getData(int num, long &data)
2408 if ( num < NUM_DATA_ENTRIES )
2416 RESULT eDVBFrontend::setData(int num, long val)
2418 if ( num < NUM_DATA_ENTRIES )
2426 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2429 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2431 if (m_type == eDVBFrontend::feSatellite)
2434 eDVBFrontendParametersSatellite sat_parm;
2435 int ret = feparm->getDVBS(sat_parm);
2437 if (sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S2 && !m_can_handle_dvbs2)
2439 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2440 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S && m_can_handle_dvbs2)
2444 else if (m_type == eDVBFrontend::feCable)
2445 return 2; // more prio for cable frontends
2446 else if (m_type == eDVBFrontend::feTerrestrial)
2451 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2453 ePyObject Id, Descr, Enabled, IsDVBS2;
2454 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4)
2456 Id = PyTuple_GET_ITEM(obj, 0);
2457 Descr = PyTuple_GET_ITEM(obj, 1);
2458 Enabled = PyTuple_GET_ITEM(obj, 2);
2459 IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2460 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2))
2462 strcpy(m_description, PyString_AS_STRING(Descr));
2463 m_slotid = PyInt_AsLong(Id);
2464 m_enabled = Enabled == Py_True;
2465 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2466 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2467 !!strstr(m_description, "Alps BSBE2") ||
2468 !!strstr(m_description, "Alps -S") ||
2469 !!strstr(m_description, "BCM4501");
2470 m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2471 eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2472 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2475 PyErr_SetString(PyExc_StandardError,
2476 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");