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;
1279 if (m_fd == -1 && !original)
1281 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1283 eDebug("FE_GET_FRONTEND failed (%m)");
1287 const FRONTENDPARAMETERS &parm = original || m_simulate ? this->parm : front;
1288 const char *tmp = "INVERSION_AUTO";
1289 switch(parm_inversion)
1292 tmp = "INVERSION_ON";
1295 tmp = "INVERSION_OFF";
1301 PutToDict(dest, "inversion", tmp);
1306 fillDictWithSatelliteData(dest, original?parm:front, this);
1309 fillDictWithCableData(dest, original?parm:front);
1312 fillDictWithTerrestrialData(dest, original?parm:front);
1323 void eDVBFrontend::getFrontendData(ePyObject dest)
1325 if (dest && PyDict_Check(dest))
1328 PutToDict(dest, "tuner_number", m_slotid);
1344 PutToDict(dest, "tuner_type", tmp);
1348 #ifndef FP_IOCTL_GET_ID
1349 #define FP_IOCTL_GET_ID 0
1351 int eDVBFrontend::readInputpower()
1355 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1357 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1358 FILE *f=fopen(proc_name, "r");
1361 if (fscanf(f, "%d", &power) != 1)
1362 eDebug("read %s failed!! (%m)", proc_name);
1364 eDebug("%s is %d\n", proc_name, power);
1369 // open front prozessor
1370 int fp=::open("/dev/dbox/fp0", O_RDWR);
1373 eDebug("couldn't open fp");
1376 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1377 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1379 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1388 bool eDVBFrontend::setSecSequencePos(int steps)
1390 eDebugNoSimulate("set sequence pos %d", steps);
1395 if (m_sec_sequence.current() != m_sec_sequence.end())
1396 ++m_sec_sequence.current();
1401 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1402 --m_sec_sequence.current();
1408 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1411 eDVBFrontend *sec_fe = this;
1412 eDVBRegisteredFrontend *regFE = 0;
1413 long tmp = m_data[LINKED_PREV_PTR];
1416 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1417 sec_fe = prev->m_frontend;
1418 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1419 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1420 int state = sec_fe->m_state;
1421 // workaround to put the kernel frontend thread into idle state!
1422 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1424 sec_fe->closeFrontend(true);
1425 state = sec_fe->m_state;
1427 // sec_fe is closed... we must reopen it here..
1428 if (state == eDVBFrontend::stateClosed)
1436 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1438 long *sec_fe_data = sec_fe->m_data;
1439 // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1440 switch (m_sec_sequence.current()->cmd)
1442 case eSecCommand::SLEEP:
1443 delay = m_sec_sequence.current()++->msec;
1444 eDebugNoSimulate("[SEC] sleep %dms", delay);
1446 case eSecCommand::GOTO:
1447 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1448 ++m_sec_sequence.current();
1450 case eSecCommand::SET_VOLTAGE:
1452 int voltage = m_sec_sequence.current()++->voltage;
1453 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1454 sec_fe->setVoltage(voltage);
1457 case eSecCommand::IF_VOLTAGE_GOTO:
1459 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1460 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1462 ++m_sec_sequence.current();
1465 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1467 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1468 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1470 ++m_sec_sequence.current();
1473 case eSecCommand::IF_TONE_GOTO:
1475 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1476 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1478 ++m_sec_sequence.current();
1481 case eSecCommand::IF_NOT_TONE_GOTO:
1483 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1484 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1486 ++m_sec_sequence.current();
1489 case eSecCommand::SET_TONE:
1490 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1491 sec_fe->setTone(m_sec_sequence.current()++->tone);
1493 case eSecCommand::SEND_DISEQC:
1494 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1495 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1496 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1497 eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1498 eDebugNoSimulate("");
1499 ++m_sec_sequence.current();
1501 case eSecCommand::SEND_TONEBURST:
1502 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1503 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1505 case eSecCommand::SET_FRONTEND:
1506 eDebugNoSimulate("[SEC] setFrontend");
1508 ++m_sec_sequence.current();
1510 case eSecCommand::START_TUNE_TIMEOUT:
1513 m_timeout->start(m_sec_sequence.current()->timeout, 1);
1514 ++m_sec_sequence.current();
1517 case eSecCommand::SET_TIMEOUT:
1518 m_timeoutCount = m_sec_sequence.current()++->val;
1519 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1521 case eSecCommand::IF_TIMEOUT_GOTO:
1522 if (!m_timeoutCount)
1524 eDebugNoSimulate("[SEC] rotor timout");
1525 setSecSequencePos(m_sec_sequence.current()->steps);
1528 ++m_sec_sequence.current();
1530 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1532 int idx = m_sec_sequence.current()++->val;
1533 if ( idx == 0 || idx == 1 )
1535 m_idleInputpower[idx] = sec_fe->readInputpower();
1536 eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1539 eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1542 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1544 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1545 int idx = compare.val;
1546 if ( !m_simulate && (idx == 0 || idx == 1) )
1548 int idle = sec_fe->readInputpower();
1549 int diff = abs(idle-m_idleInputpower[idx]);
1552 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1553 setSecSequencePos(compare.steps);
1557 ++m_sec_sequence.current();
1560 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1562 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1565 setSecSequencePos(cmd.steps);
1569 int isLocked = readFrontendData(locked);
1570 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1571 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 50) || !cmd.lastSignal))
1574 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1577 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1578 cmd.lastSignal = signal;
1581 if (cmd.okcount > 4)
1583 eDebugNoSimulate("ok > 4 .. goto %d\n",cmd.steps);
1584 setSecSequencePos(cmd.steps);
1585 m_state = stateLock;
1586 m_stateChanged(this);
1595 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1597 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1599 if (!m_timeoutCount && m_retryCount > 0)
1604 ++m_sec_sequence.current();
1607 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1608 m_runningInputpower = sec_fe->readInputpower();
1609 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1610 ++m_sec_sequence.current();
1612 case eSecCommand::SET_ROTOR_MOVING:
1614 m_sec->setRotorMoving(true);
1615 ++m_sec_sequence.current();
1617 case eSecCommand::SET_ROTOR_STOPPED:
1619 m_sec->setRotorMoving(false);
1620 ++m_sec_sequence.current();
1622 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1624 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1627 setSecSequencePos(cmd.steps);
1630 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1631 const char *txt = cmd.direction ? "running" : "stopped";
1632 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1634 m_runningInputpower,
1637 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1638 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1641 eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1642 if ( cmd.okcount > 6 )
1644 eDebugNoSimulate("[SEC] rotor is %s", txt);
1645 if (setSecSequencePos(cmd.steps))
1651 eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1653 if (!m_timeoutCount && m_retryCount > 0)
1657 ++m_sec_sequence.current();
1660 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1661 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1662 setSecSequencePos(m_sec_sequence.current()->steps);
1664 ++m_sec_sequence.current();
1666 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1667 eDebugNoSimulate("[SEC] invalidate current switch params");
1668 sec_fe_data[CSW] = -1;
1669 sec_fe_data[UCSW] = -1;
1670 sec_fe_data[TONEBURST] = -1;
1671 ++m_sec_sequence.current();
1673 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1674 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1675 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1676 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1677 eDebugNoSimulate("[SEC] update current switch params");
1678 ++m_sec_sequence.current();
1680 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1681 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1682 sec_fe_data[ROTOR_CMD] = -1;
1683 sec_fe_data[ROTOR_POS] = -1;
1684 ++m_sec_sequence.current();
1686 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1687 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1688 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1689 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1690 ++m_sec_sequence.current();
1692 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1693 m_retryCount = m_sec_sequence.current()++->val;
1694 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1696 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1699 eDebugNoSimulate("[SEC] no more rotor retrys");
1700 setSecSequencePos(m_sec_sequence.current()->steps);
1703 ++m_sec_sequence.current();
1705 case eSecCommand::SET_POWER_LIMITING_MODE:
1710 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1711 FILE *f=fopen(proc_name, "w");
1712 if (f) // new interface exist?
1714 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1715 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1716 eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1718 eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1721 else if (sec_fe->m_need_rotor_workaround)
1724 int slotid = sec_fe->m_slotid;
1725 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1727 sprintf(dev, "/dev/i2c/%d", slotid);
1728 else if (slotid == 2)
1729 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1730 else if (slotid == 3)
1731 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1732 int fd = ::open(dev, O_RDWR);
1734 unsigned char data[2];
1735 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1736 if(::read(fd, data, 1) != 1)
1737 eDebugNoSimulate("[SEC] error read lnbp (%m)");
1738 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1740 data[0] |= 0x80; // enable static current limiting
1741 eDebugNoSimulate("[SEC] set static current limiting");
1745 data[0] &= ~0x80; // enable dynamic current limiting
1746 eDebugNoSimulate("[SEC] set dynamic current limiting");
1748 if(::write(fd, data, 1) != 1)
1749 eDebugNoSimulate("[SEC] error write lnbp (%m)");
1753 ++m_sec_sequence.current();
1757 eDebugNoSimulate("[SEC] unhandled sec command %d",
1758 ++m_sec_sequence.current()->cmd);
1759 ++m_sec_sequence.current();
1762 m_tuneTimer->start(delay,true);
1766 if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1770 void eDVBFrontend::setFrontend()
1774 eDebug("setting frontend %d", m_dvbid);
1777 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1779 perror("FE_SET_FRONTEND failed");
1785 RESULT eDVBFrontend::getFrontendType(int &t)
1793 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1798 eWarning("no SEC module active!");
1801 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1804 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1807 feparm.polarisation,
1811 feparm.orbital_position);
1812 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1813 switch (feparm.inversion)
1815 case eDVBFrontendParametersSatellite::Inversion::On:
1816 parm_inversion = INVERSION_ON;
1818 case eDVBFrontendParametersSatellite::Inversion::Off:
1819 parm_inversion = INVERSION_OFF;
1822 case eDVBFrontendParametersSatellite::Inversion::Unknown:
1823 parm_inversion = INVERSION_AUTO;
1826 if (feparm.system == eDVBFrontendParametersSatellite::System::DVB_S)
1829 case eDVBFrontendParametersSatellite::FEC::fNone:
1830 parm_u_qpsk_fec_inner = FEC_NONE;
1832 case eDVBFrontendParametersSatellite::FEC::f1_2:
1833 parm_u_qpsk_fec_inner = FEC_1_2;
1835 case eDVBFrontendParametersSatellite::FEC::f2_3:
1836 parm_u_qpsk_fec_inner = FEC_2_3;
1838 case eDVBFrontendParametersSatellite::FEC::f3_4:
1839 parm_u_qpsk_fec_inner = FEC_3_4;
1841 case eDVBFrontendParametersSatellite::FEC::f5_6:
1842 parm_u_qpsk_fec_inner = FEC_5_6;
1844 case eDVBFrontendParametersSatellite::FEC::f7_8:
1845 parm_u_qpsk_fec_inner = FEC_7_8;
1848 eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
1849 case eDVBFrontendParametersSatellite::FEC::fAuto:
1850 parm_u_qpsk_fec_inner = FEC_AUTO;
1853 #if HAVE_DVB_API_VERSION >= 3
1858 case eDVBFrontendParametersSatellite::FEC::f1_2:
1859 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1861 case eDVBFrontendParametersSatellite::FEC::f2_3:
1862 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1864 case eDVBFrontendParametersSatellite::FEC::f3_4:
1865 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1867 case eDVBFrontendParametersSatellite::FEC::f3_5:
1868 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1870 case eDVBFrontendParametersSatellite::FEC::f4_5:
1871 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1873 case eDVBFrontendParametersSatellite::FEC::f5_6:
1874 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1876 case eDVBFrontendParametersSatellite::FEC::f7_8:
1877 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1879 case eDVBFrontendParametersSatellite::FEC::f8_9:
1880 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1882 case eDVBFrontendParametersSatellite::FEC::f9_10:
1883 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1886 eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
1889 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1890 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK) {
1891 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1892 // 8PSK fec driver values are decimal 9 bigger
1893 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1897 // FIXME !!! get frequency range from tuner
1898 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1900 eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1903 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
1908 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1910 #if HAVE_DVB_API_VERSION < 3
1911 parm_frequency = feparm.frequency;
1913 parm_frequency = feparm.frequency * 1000;
1915 parm_u_qam_symbol_rate = feparm.symbol_rate;
1916 switch (feparm.modulation)
1918 case eDVBFrontendParametersCable::Modulation::QAM16:
1919 parm_u_qam_modulation = QAM_16;
1921 case eDVBFrontendParametersCable::Modulation::QAM32:
1922 parm_u_qam_modulation = QAM_32;
1924 case eDVBFrontendParametersCable::Modulation::QAM64:
1925 parm_u_qam_modulation = QAM_64;
1927 case eDVBFrontendParametersCable::Modulation::QAM128:
1928 parm_u_qam_modulation = QAM_128;
1930 case eDVBFrontendParametersCable::Modulation::QAM256:
1931 parm_u_qam_modulation = QAM_256;
1934 case eDVBFrontendParametersCable::Modulation::Auto:
1935 parm_u_qam_modulation = QAM_AUTO;
1938 switch (feparm.inversion)
1940 case eDVBFrontendParametersCable::Inversion::On:
1941 parm_inversion = INVERSION_ON;
1943 case eDVBFrontendParametersCable::Inversion::Off:
1944 parm_inversion = INVERSION_OFF;
1947 case eDVBFrontendParametersCable::Inversion::Unknown:
1948 parm_inversion = INVERSION_AUTO;
1951 switch (feparm.fec_inner)
1953 case eDVBFrontendParametersCable::FEC::fNone:
1954 parm_u_qam_fec_inner = FEC_NONE;
1956 case eDVBFrontendParametersCable::FEC::f1_2:
1957 parm_u_qam_fec_inner = FEC_1_2;
1959 case eDVBFrontendParametersCable::FEC::f2_3:
1960 parm_u_qam_fec_inner = FEC_2_3;
1962 case eDVBFrontendParametersCable::FEC::f3_4:
1963 parm_u_qam_fec_inner = FEC_3_4;
1965 case eDVBFrontendParametersCable::FEC::f5_6:
1966 parm_u_qam_fec_inner = FEC_5_6;
1968 case eDVBFrontendParametersCable::FEC::f7_8:
1969 parm_u_qam_fec_inner = FEC_7_8;
1971 #if HAVE_DVB_API_VERSION >= 3
1972 case eDVBFrontendParametersCable::FEC::f8_9:
1973 parm_u_qam_fec_inner = FEC_8_9;
1977 case eDVBFrontendParametersCable::FEC::fAuto:
1978 parm_u_qam_fec_inner = FEC_AUTO;
1981 eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
1982 parm_frequency/1000,
1983 parm_u_qam_symbol_rate,
1984 parm_u_qam_fec_inner,
1985 parm_u_qam_modulation,
1990 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
1992 parm_frequency = feparm.frequency;
1994 switch (feparm.bandwidth)
1996 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
1997 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
1999 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
2000 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
2002 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
2003 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
2006 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
2007 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
2010 switch (feparm.code_rate_LP)
2012 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
2013 parm_u_ofdm_code_rate_LP = FEC_1_2;
2015 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
2016 parm_u_ofdm_code_rate_LP = FEC_2_3;
2018 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
2019 parm_u_ofdm_code_rate_LP = FEC_3_4;
2021 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
2022 parm_u_ofdm_code_rate_LP = FEC_5_6;
2024 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
2025 parm_u_ofdm_code_rate_LP = FEC_7_8;
2028 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
2029 parm_u_ofdm_code_rate_LP = FEC_AUTO;
2032 switch (feparm.code_rate_HP)
2034 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
2035 parm_u_ofdm_code_rate_HP = FEC_1_2;
2037 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
2038 parm_u_ofdm_code_rate_HP = FEC_2_3;
2040 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
2041 parm_u_ofdm_code_rate_HP = FEC_3_4;
2043 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
2044 parm_u_ofdm_code_rate_HP = FEC_5_6;
2046 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
2047 parm_u_ofdm_code_rate_HP = FEC_7_8;
2050 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
2051 parm_u_ofdm_code_rate_HP = FEC_AUTO;
2054 switch (feparm.modulation)
2056 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
2057 parm_u_ofdm_constellation = QPSK;
2059 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
2060 parm_u_ofdm_constellation = QAM_16;
2062 case eDVBFrontendParametersTerrestrial::Modulation::QAM64:
2063 parm_u_ofdm_constellation = QAM_64;
2066 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
2067 parm_u_ofdm_constellation = QAM_AUTO;
2070 switch (feparm.transmission_mode)
2072 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
2073 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2075 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
2076 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2079 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
2080 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2083 switch (feparm.guard_interval)
2085 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32:
2086 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2088 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16:
2089 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2091 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8:
2092 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2094 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4:
2095 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2098 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto:
2099 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2102 switch (feparm.hierarchy)
2104 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone:
2105 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2107 case eDVBFrontendParametersTerrestrial::Hierarchy::H1:
2108 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2110 case eDVBFrontendParametersTerrestrial::Hierarchy::H2:
2111 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2113 case eDVBFrontendParametersTerrestrial::Hierarchy::H4:
2114 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2117 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto:
2118 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2121 switch (feparm.inversion)
2123 case eDVBFrontendParametersTerrestrial::Inversion::On:
2124 parm_inversion = INVERSION_ON;
2126 case eDVBFrontendParametersTerrestrial::Inversion::Off:
2127 parm_inversion = INVERSION_OFF;
2130 case eDVBFrontendParametersTerrestrial::Inversion::Unknown:
2131 parm_inversion = INVERSION_AUTO;
2137 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2139 unsigned int timeout = 5000;
2140 eDebugNoSimulate("(%d)tune", m_dvbid);
2146 if (!m_sn && !m_simulate)
2148 eDebug("no frontend device opened... do not try to tune !!!");
2162 m_sec_sequence.clear();
2164 where.calcLockTimeout(timeout);
2170 eDVBFrontendParametersSatellite feparm;
2171 if (where.getDVBS(feparm))
2173 eDebug("no dvbs data!");
2178 m_sec->setRotorMoving(false);
2179 res=prepare_sat(feparm, timeout);
2187 eDVBFrontendParametersCable feparm;
2188 if (where.getDVBC(feparm))
2193 res=prepare_cable(feparm);
2197 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2198 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2203 eDVBFrontendParametersTerrestrial feparm;
2204 if (where.getDVBT(feparm))
2206 eDebug("no -T data");
2210 res=prepare_terrestrial(feparm);
2214 std::string enable_5V;
2215 char configStr[255];
2216 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2217 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2218 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2219 if (enable_5V == "True")
2220 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2222 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2223 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2229 m_sec_sequence.current() = m_sec_sequence.begin();
2233 m_tuneTimer->start(0,true);
2234 if (m_state != stateTuning)
2237 m_state = stateTuning;
2238 m_stateChanged(this);
2247 m_tuneTimer->stop();
2251 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2253 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2257 RESULT eDVBFrontend::setVoltage(int voltage)
2259 if (m_type == feCable)
2261 #if HAVE_DVB_API_VERSION < 3
2264 bool increased=false;
2265 fe_sec_voltage_t vlt;
2267 m_data[CUR_VOLTAGE]=voltage;
2271 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2272 vlt = SEC_VOLTAGE_OFF;
2275 #if HAVE_DVB_API_VERSION < 3
2276 vlt = SEC_VOLTAGE_13_5;
2282 vlt = SEC_VOLTAGE_13;
2285 #if HAVE_DVB_API_VERSION < 3
2286 vlt = SEC_VOLTAGE_18_5;
2292 vlt = SEC_VOLTAGE_18;
2299 #if HAVE_DVB_API_VERSION < 3
2300 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2302 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2303 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2304 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2308 RESULT eDVBFrontend::getState(int &state)
2314 RESULT eDVBFrontend::setTone(int t)
2316 if (m_type != feSatellite)
2318 #if HAVE_DVB_API_VERSION < 3
2321 fe_sec_tone_mode_t tone;
2330 tone = SEC_TONE_OFF;
2337 #if HAVE_DVB_API_VERSION < 3
2338 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2340 return ::ioctl(m_fd, FE_SET_TONE, tone);
2344 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2345 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2348 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2352 #if HAVE_DVB_API_VERSION < 3
2353 struct secCommand cmd;
2354 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2355 cmd.u.diseqc.cmdtype = diseqc.data[0];
2356 cmd.u.diseqc.addr = diseqc.data[1];
2357 cmd.u.diseqc.cmd = diseqc.data[2];
2358 cmd.u.diseqc.numParams = diseqc.len-3;
2359 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2360 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2362 struct dvb_diseqc_master_cmd cmd;
2363 memcpy(cmd.msg, diseqc.data, diseqc.len);
2364 cmd.msg_len = diseqc.len;
2365 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2371 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2372 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2374 RESULT eDVBFrontend::sendToneburst(int burst)
2378 #if HAVE_DVB_API_VERSION < 3
2379 secMiniCmd cmd = SEC_MINI_NONE;
2381 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2383 if ( burst == eDVBSatelliteDiseqcParameters::A )
2385 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2387 #if HAVE_DVB_API_VERSION < 3
2388 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2391 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2397 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2403 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2405 m_sec_sequence = list;
2409 RESULT eDVBFrontend::getData(int num, long &data)
2411 if ( num < NUM_DATA_ENTRIES )
2419 RESULT eDVBFrontend::setData(int num, long val)
2421 if ( num < NUM_DATA_ENTRIES )
2429 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2432 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2434 if (m_type == eDVBFrontend::feSatellite)
2437 eDVBFrontendParametersSatellite sat_parm;
2438 int ret = feparm->getDVBS(sat_parm);
2440 if (sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S2 && !m_can_handle_dvbs2)
2442 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2443 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S && m_can_handle_dvbs2)
2447 else if (m_type == eDVBFrontend::feCable)
2448 return 2; // more prio for cable frontends
2449 else if (m_type == eDVBFrontend::feTerrestrial)
2454 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2456 ePyObject Id, Descr, Enabled, IsDVBS2;
2457 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4)
2459 Id = PyTuple_GET_ITEM(obj, 0);
2460 Descr = PyTuple_GET_ITEM(obj, 1);
2461 Enabled = PyTuple_GET_ITEM(obj, 2);
2462 IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2463 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2))
2465 strcpy(m_description, PyString_AS_STRING(Descr));
2466 m_slotid = PyInt_AsLong(Id);
2467 m_enabled = Enabled == Py_True;
2468 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2469 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2470 !!strstr(m_description, "Alps BSBE2") ||
2471 !!strstr(m_description, "Alps -S") ||
2472 !!strstr(m_description, "BCM4501");
2473 m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2474 eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2475 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2478 PyErr_SetString(PyExc_StandardError,
2479 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");