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 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1423 sec_fe->closeFrontend(true);
1424 state = sec_fe->m_state;
1426 if (state == eDVBFrontend::stateClosed)
1434 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1436 long *sec_fe_data = sec_fe->m_data;
1437 // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1438 switch (m_sec_sequence.current()->cmd)
1440 case eSecCommand::SLEEP:
1441 delay = m_sec_sequence.current()++->msec;
1442 eDebugNoSimulate("[SEC] sleep %dms", delay);
1444 case eSecCommand::GOTO:
1445 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1446 ++m_sec_sequence.current();
1448 case eSecCommand::SET_VOLTAGE:
1450 int voltage = m_sec_sequence.current()++->voltage;
1451 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1452 sec_fe->setVoltage(voltage);
1455 case eSecCommand::IF_VOLTAGE_GOTO:
1457 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1458 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1460 ++m_sec_sequence.current();
1463 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1465 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1466 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1468 ++m_sec_sequence.current();
1471 case eSecCommand::IF_TONE_GOTO:
1473 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1474 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1476 ++m_sec_sequence.current();
1479 case eSecCommand::IF_NOT_TONE_GOTO:
1481 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1482 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1484 ++m_sec_sequence.current();
1487 case eSecCommand::SET_TONE:
1488 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1489 sec_fe->setTone(m_sec_sequence.current()++->tone);
1491 case eSecCommand::SEND_DISEQC:
1492 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1493 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1494 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1495 eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1496 eDebugNoSimulate("");
1497 ++m_sec_sequence.current();
1499 case eSecCommand::SEND_TONEBURST:
1500 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1501 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1503 case eSecCommand::SET_FRONTEND:
1504 eDebugNoSimulate("[SEC] setFrontend");
1506 ++m_sec_sequence.current();
1508 case eSecCommand::START_TUNE_TIMEOUT:
1511 m_timeout->start(m_sec_sequence.current()->timeout, 1);
1512 ++m_sec_sequence.current();
1515 case eSecCommand::SET_TIMEOUT:
1516 m_timeoutCount = m_sec_sequence.current()++->val;
1517 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1519 case eSecCommand::IF_TIMEOUT_GOTO:
1520 if (!m_timeoutCount)
1522 eDebugNoSimulate("[SEC] rotor timout");
1523 setSecSequencePos(m_sec_sequence.current()->steps);
1526 ++m_sec_sequence.current();
1528 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1530 int idx = m_sec_sequence.current()++->val;
1531 if ( idx == 0 || idx == 1 )
1533 m_idleInputpower[idx] = sec_fe->readInputpower();
1534 eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1537 eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1540 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1542 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1543 int idx = compare.val;
1544 if ( !m_simulate && (idx == 0 || idx == 1) )
1546 int idle = sec_fe->readInputpower();
1547 int diff = abs(idle-m_idleInputpower[idx]);
1550 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1551 setSecSequencePos(compare.steps);
1555 ++m_sec_sequence.current();
1558 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1560 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1563 setSecSequencePos(cmd.steps);
1567 int isLocked = readFrontendData(locked);
1568 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1569 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 50) || !cmd.lastSignal))
1572 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1575 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1576 cmd.lastSignal = signal;
1579 if (cmd.okcount > 4)
1581 eDebugNoSimulate("ok > 4 .. goto %d\n",cmd.steps);
1582 setSecSequencePos(cmd.steps);
1583 m_state = stateLock;
1584 m_stateChanged(this);
1593 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1595 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1597 if (!m_timeoutCount && m_retryCount > 0)
1602 ++m_sec_sequence.current();
1605 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1606 m_runningInputpower = sec_fe->readInputpower();
1607 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1608 ++m_sec_sequence.current();
1610 case eSecCommand::SET_ROTOR_MOVING:
1612 m_sec->setRotorMoving(true);
1613 ++m_sec_sequence.current();
1615 case eSecCommand::SET_ROTOR_STOPPED:
1617 m_sec->setRotorMoving(false);
1618 ++m_sec_sequence.current();
1620 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1622 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1625 setSecSequencePos(cmd.steps);
1628 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1629 const char *txt = cmd.direction ? "running" : "stopped";
1630 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1632 m_runningInputpower,
1635 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1636 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1639 eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1640 if ( cmd.okcount > 6 )
1642 eDebugNoSimulate("[SEC] rotor is %s", txt);
1643 if (setSecSequencePos(cmd.steps))
1649 eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1651 if (!m_timeoutCount && m_retryCount > 0)
1655 ++m_sec_sequence.current();
1658 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1659 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1660 setSecSequencePos(m_sec_sequence.current()->steps);
1662 ++m_sec_sequence.current();
1664 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1665 eDebugNoSimulate("[SEC] invalidate current switch params");
1666 sec_fe_data[CSW] = -1;
1667 sec_fe_data[UCSW] = -1;
1668 sec_fe_data[TONEBURST] = -1;
1669 ++m_sec_sequence.current();
1671 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1672 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1673 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1674 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1675 eDebugNoSimulate("[SEC] update current switch params");
1676 ++m_sec_sequence.current();
1678 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1679 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1680 sec_fe_data[ROTOR_CMD] = -1;
1681 sec_fe_data[ROTOR_POS] = -1;
1682 ++m_sec_sequence.current();
1684 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1685 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1686 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1687 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1688 ++m_sec_sequence.current();
1690 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1691 m_retryCount = m_sec_sequence.current()++->val;
1692 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1694 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1697 eDebugNoSimulate("[SEC] no more rotor retrys");
1698 setSecSequencePos(m_sec_sequence.current()->steps);
1701 ++m_sec_sequence.current();
1703 case eSecCommand::SET_POWER_LIMITING_MODE:
1708 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1709 FILE *f=fopen(proc_name, "w");
1710 if (f) // new interface exist?
1712 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1713 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1714 eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1716 eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1719 else if (sec_fe->m_need_rotor_workaround)
1722 int slotid = sec_fe->m_slotid;
1723 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1725 sprintf(dev, "/dev/i2c/%d", slotid);
1726 else if (slotid == 2)
1727 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1728 else if (slotid == 3)
1729 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1730 int fd = ::open(dev, O_RDWR);
1732 unsigned char data[2];
1733 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1734 if(::read(fd, data, 1) != 1)
1735 eDebugNoSimulate("[SEC] error read lnbp (%m)");
1736 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1738 data[0] |= 0x80; // enable static current limiting
1739 eDebugNoSimulate("[SEC] set static current limiting");
1743 data[0] &= ~0x80; // enable dynamic current limiting
1744 eDebugNoSimulate("[SEC] set dynamic current limiting");
1746 if(::write(fd, data, 1) != 1)
1747 eDebugNoSimulate("[SEC] error write lnbp (%m)");
1751 ++m_sec_sequence.current();
1755 eDebugNoSimulate("[SEC] unhandled sec command %d",
1756 ++m_sec_sequence.current()->cmd);
1757 ++m_sec_sequence.current();
1760 m_tuneTimer->start(delay,true);
1764 if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1768 void eDVBFrontend::setFrontend()
1772 eDebug("setting frontend %d", m_dvbid);
1775 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1777 perror("FE_SET_FRONTEND failed");
1783 RESULT eDVBFrontend::getFrontendType(int &t)
1791 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1796 eWarning("no SEC module active!");
1799 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1802 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1805 feparm.polarisation,
1809 feparm.orbital_position);
1810 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1811 switch (feparm.inversion)
1813 case eDVBFrontendParametersSatellite::Inversion::On:
1814 parm_inversion = INVERSION_ON;
1816 case eDVBFrontendParametersSatellite::Inversion::Off:
1817 parm_inversion = INVERSION_OFF;
1820 case eDVBFrontendParametersSatellite::Inversion::Unknown:
1821 parm_inversion = INVERSION_AUTO;
1824 if (feparm.system == eDVBFrontendParametersSatellite::System::DVB_S)
1827 case eDVBFrontendParametersSatellite::FEC::fNone:
1828 parm_u_qpsk_fec_inner = FEC_NONE;
1830 case eDVBFrontendParametersSatellite::FEC::f1_2:
1831 parm_u_qpsk_fec_inner = FEC_1_2;
1833 case eDVBFrontendParametersSatellite::FEC::f2_3:
1834 parm_u_qpsk_fec_inner = FEC_2_3;
1836 case eDVBFrontendParametersSatellite::FEC::f3_4:
1837 parm_u_qpsk_fec_inner = FEC_3_4;
1839 case eDVBFrontendParametersSatellite::FEC::f5_6:
1840 parm_u_qpsk_fec_inner = FEC_5_6;
1842 case eDVBFrontendParametersSatellite::FEC::f7_8:
1843 parm_u_qpsk_fec_inner = FEC_7_8;
1846 eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
1847 case eDVBFrontendParametersSatellite::FEC::fAuto:
1848 parm_u_qpsk_fec_inner = FEC_AUTO;
1851 #if HAVE_DVB_API_VERSION >= 3
1856 case eDVBFrontendParametersSatellite::FEC::f1_2:
1857 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1859 case eDVBFrontendParametersSatellite::FEC::f2_3:
1860 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1862 case eDVBFrontendParametersSatellite::FEC::f3_4:
1863 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1865 case eDVBFrontendParametersSatellite::FEC::f3_5:
1866 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1868 case eDVBFrontendParametersSatellite::FEC::f4_5:
1869 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1871 case eDVBFrontendParametersSatellite::FEC::f5_6:
1872 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1874 case eDVBFrontendParametersSatellite::FEC::f7_8:
1875 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1877 case eDVBFrontendParametersSatellite::FEC::f8_9:
1878 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1880 case eDVBFrontendParametersSatellite::FEC::f9_10:
1881 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1884 eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
1887 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1888 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK) {
1889 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1890 // 8PSK fec driver values are decimal 9 bigger
1891 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1895 // FIXME !!! get frequency range from tuner
1896 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1898 eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1901 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
1906 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1908 #if HAVE_DVB_API_VERSION < 3
1909 parm_frequency = feparm.frequency;
1911 parm_frequency = feparm.frequency * 1000;
1913 parm_u_qam_symbol_rate = feparm.symbol_rate;
1914 switch (feparm.modulation)
1916 case eDVBFrontendParametersCable::Modulation::QAM16:
1917 parm_u_qam_modulation = QAM_16;
1919 case eDVBFrontendParametersCable::Modulation::QAM32:
1920 parm_u_qam_modulation = QAM_32;
1922 case eDVBFrontendParametersCable::Modulation::QAM64:
1923 parm_u_qam_modulation = QAM_64;
1925 case eDVBFrontendParametersCable::Modulation::QAM128:
1926 parm_u_qam_modulation = QAM_128;
1928 case eDVBFrontendParametersCable::Modulation::QAM256:
1929 parm_u_qam_modulation = QAM_256;
1932 case eDVBFrontendParametersCable::Modulation::Auto:
1933 parm_u_qam_modulation = QAM_AUTO;
1936 switch (feparm.inversion)
1938 case eDVBFrontendParametersCable::Inversion::On:
1939 parm_inversion = INVERSION_ON;
1941 case eDVBFrontendParametersCable::Inversion::Off:
1942 parm_inversion = INVERSION_OFF;
1945 case eDVBFrontendParametersCable::Inversion::Unknown:
1946 parm_inversion = INVERSION_AUTO;
1949 switch (feparm.fec_inner)
1951 case eDVBFrontendParametersCable::FEC::fNone:
1952 parm_u_qam_fec_inner = FEC_NONE;
1954 case eDVBFrontendParametersCable::FEC::f1_2:
1955 parm_u_qam_fec_inner = FEC_1_2;
1957 case eDVBFrontendParametersCable::FEC::f2_3:
1958 parm_u_qam_fec_inner = FEC_2_3;
1960 case eDVBFrontendParametersCable::FEC::f3_4:
1961 parm_u_qam_fec_inner = FEC_3_4;
1963 case eDVBFrontendParametersCable::FEC::f5_6:
1964 parm_u_qam_fec_inner = FEC_5_6;
1966 case eDVBFrontendParametersCable::FEC::f7_8:
1967 parm_u_qam_fec_inner = FEC_7_8;
1969 #if HAVE_DVB_API_VERSION >= 3
1970 case eDVBFrontendParametersCable::FEC::f8_9:
1971 parm_u_qam_fec_inner = FEC_8_9;
1975 case eDVBFrontendParametersCable::FEC::fAuto:
1976 parm_u_qam_fec_inner = FEC_AUTO;
1979 eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
1980 parm_frequency/1000,
1981 parm_u_qam_symbol_rate,
1982 parm_u_qam_fec_inner,
1983 parm_u_qam_modulation,
1988 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
1990 parm_frequency = feparm.frequency;
1992 switch (feparm.bandwidth)
1994 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
1995 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
1997 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
1998 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
2000 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
2001 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
2004 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
2005 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
2008 switch (feparm.code_rate_LP)
2010 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
2011 parm_u_ofdm_code_rate_LP = FEC_1_2;
2013 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
2014 parm_u_ofdm_code_rate_LP = FEC_2_3;
2016 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
2017 parm_u_ofdm_code_rate_LP = FEC_3_4;
2019 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
2020 parm_u_ofdm_code_rate_LP = FEC_5_6;
2022 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
2023 parm_u_ofdm_code_rate_LP = FEC_7_8;
2026 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
2027 parm_u_ofdm_code_rate_LP = FEC_AUTO;
2030 switch (feparm.code_rate_HP)
2032 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
2033 parm_u_ofdm_code_rate_HP = FEC_1_2;
2035 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
2036 parm_u_ofdm_code_rate_HP = FEC_2_3;
2038 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
2039 parm_u_ofdm_code_rate_HP = FEC_3_4;
2041 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
2042 parm_u_ofdm_code_rate_HP = FEC_5_6;
2044 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
2045 parm_u_ofdm_code_rate_HP = FEC_7_8;
2048 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
2049 parm_u_ofdm_code_rate_HP = FEC_AUTO;
2052 switch (feparm.modulation)
2054 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
2055 parm_u_ofdm_constellation = QPSK;
2057 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
2058 parm_u_ofdm_constellation = QAM_16;
2060 case eDVBFrontendParametersTerrestrial::Modulation::QAM64:
2061 parm_u_ofdm_constellation = QAM_64;
2064 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
2065 parm_u_ofdm_constellation = QAM_AUTO;
2068 switch (feparm.transmission_mode)
2070 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
2071 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2073 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
2074 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2077 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
2078 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2081 switch (feparm.guard_interval)
2083 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32:
2084 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2086 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16:
2087 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2089 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8:
2090 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2092 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4:
2093 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2096 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto:
2097 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2100 switch (feparm.hierarchy)
2102 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone:
2103 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2105 case eDVBFrontendParametersTerrestrial::Hierarchy::H1:
2106 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2108 case eDVBFrontendParametersTerrestrial::Hierarchy::H2:
2109 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2111 case eDVBFrontendParametersTerrestrial::Hierarchy::H4:
2112 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2115 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto:
2116 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2119 switch (feparm.inversion)
2121 case eDVBFrontendParametersTerrestrial::Inversion::On:
2122 parm_inversion = INVERSION_ON;
2124 case eDVBFrontendParametersTerrestrial::Inversion::Off:
2125 parm_inversion = INVERSION_OFF;
2128 case eDVBFrontendParametersTerrestrial::Inversion::Unknown:
2129 parm_inversion = INVERSION_AUTO;
2135 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2137 unsigned int timeout = 5000;
2138 eDebugNoSimulate("(%d)tune", m_dvbid);
2144 if (!m_sn && !m_simulate)
2146 eDebug("no frontend device opened... do not try to tune !!!");
2160 m_sec_sequence.clear();
2162 where.calcLockTimeout(timeout);
2168 eDVBFrontendParametersSatellite feparm;
2169 if (where.getDVBS(feparm))
2171 eDebug("no dvbs data!");
2176 m_sec->setRotorMoving(false);
2177 res=prepare_sat(feparm, timeout);
2185 eDVBFrontendParametersCable feparm;
2186 if (where.getDVBC(feparm))
2191 res=prepare_cable(feparm);
2195 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2196 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2201 eDVBFrontendParametersTerrestrial feparm;
2202 if (where.getDVBT(feparm))
2204 eDebug("no -T data");
2208 res=prepare_terrestrial(feparm);
2212 std::string enable_5V;
2213 char configStr[255];
2214 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2215 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2216 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2217 if (enable_5V == "True")
2218 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2220 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2221 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2227 m_sec_sequence.current() = m_sec_sequence.begin();
2231 m_tuneTimer->start(0,true);
2232 if (m_state != stateTuning)
2235 m_state = stateTuning;
2236 m_stateChanged(this);
2245 m_tuneTimer->stop();
2249 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2251 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2255 RESULT eDVBFrontend::setVoltage(int voltage)
2257 if (m_type == feCable)
2259 #if HAVE_DVB_API_VERSION < 3
2262 bool increased=false;
2263 fe_sec_voltage_t vlt;
2265 m_data[CUR_VOLTAGE]=voltage;
2269 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2270 vlt = SEC_VOLTAGE_OFF;
2273 #if HAVE_DVB_API_VERSION < 3
2274 vlt = SEC_VOLTAGE_13_5;
2280 vlt = SEC_VOLTAGE_13;
2283 #if HAVE_DVB_API_VERSION < 3
2284 vlt = SEC_VOLTAGE_18_5;
2290 vlt = SEC_VOLTAGE_18;
2297 #if HAVE_DVB_API_VERSION < 3
2298 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2300 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2301 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2302 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2306 RESULT eDVBFrontend::getState(int &state)
2312 RESULT eDVBFrontend::setTone(int t)
2314 if (m_type != feSatellite)
2316 #if HAVE_DVB_API_VERSION < 3
2319 fe_sec_tone_mode_t tone;
2328 tone = SEC_TONE_OFF;
2335 #if HAVE_DVB_API_VERSION < 3
2336 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2338 return ::ioctl(m_fd, FE_SET_TONE, tone);
2342 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2343 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2346 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2350 #if HAVE_DVB_API_VERSION < 3
2351 struct secCommand cmd;
2352 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2353 cmd.u.diseqc.cmdtype = diseqc.data[0];
2354 cmd.u.diseqc.addr = diseqc.data[1];
2355 cmd.u.diseqc.cmd = diseqc.data[2];
2356 cmd.u.diseqc.numParams = diseqc.len-3;
2357 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2358 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2360 struct dvb_diseqc_master_cmd cmd;
2361 memcpy(cmd.msg, diseqc.data, diseqc.len);
2362 cmd.msg_len = diseqc.len;
2363 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2369 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2370 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2372 RESULT eDVBFrontend::sendToneburst(int burst)
2376 #if HAVE_DVB_API_VERSION < 3
2377 secMiniCmd cmd = SEC_MINI_NONE;
2379 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2381 if ( burst == eDVBSatelliteDiseqcParameters::A )
2383 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2385 #if HAVE_DVB_API_VERSION < 3
2386 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2389 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2395 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2401 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2403 m_sec_sequence = list;
2407 RESULT eDVBFrontend::getData(int num, long &data)
2409 if ( num < NUM_DATA_ENTRIES )
2417 RESULT eDVBFrontend::setData(int num, long val)
2419 if ( num < NUM_DATA_ENTRIES )
2427 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2430 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2432 if (m_type == eDVBFrontend::feSatellite)
2435 eDVBFrontendParametersSatellite sat_parm;
2436 int ret = feparm->getDVBS(sat_parm);
2438 if (sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S2 && !m_can_handle_dvbs2)
2440 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2441 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S && m_can_handle_dvbs2)
2445 else if (m_type == eDVBFrontend::feCable)
2446 return 2; // more prio for cable frontends
2447 else if (m_type == eDVBFrontend::feTerrestrial)
2452 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2454 ePyObject Id, Descr, Enabled, IsDVBS2;
2455 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4)
2457 Id = PyTuple_GET_ITEM(obj, 0);
2458 Descr = PyTuple_GET_ITEM(obj, 1);
2459 Enabled = PyTuple_GET_ITEM(obj, 2);
2460 IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2461 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2))
2463 strcpy(m_description, PyString_AS_STRING(Descr));
2464 m_slotid = PyInt_AsLong(Id);
2465 m_enabled = Enabled == Py_True;
2466 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2467 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2468 !!strstr(m_description, "Alps BSBE2") ||
2469 !!strstr(m_description, "Alps -S") ||
2470 !!strstr(m_description, "BCM4501");
2471 m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2472 eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2473 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2476 PyErr_SetString(PyExc_StandardError,
2477 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");