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_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 = eSocketNotifier::create(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);
611 m_state = stateClosed;
616 eDVBFrontend::~eDVBFrontend()
618 m_data[LINKED_PREV_PTR] = m_data[LINKED_NEXT_PTR] = -1;
624 void eDVBFrontend::feEvent(int w)
626 eDVBFrontend *sec_fe = this;
627 long tmp = m_data[LINKED_PREV_PTR];
630 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
631 sec_fe = linked_fe->m_frontend;
632 sec_fe->getData(LINKED_NEXT_PTR, tmp);
636 #if HAVE_DVB_API_VERSION < 3
639 dvb_frontend_event event;
643 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
645 if (res && (errno == EAGAIN))
650 eWarning("FE_GET_EVENT failed! %m");
657 #if HAVE_DVB_API_VERSION < 3
658 if (event.type == FE_COMPLETION_EV)
660 eDebug("(%d)fe event: status %x, inversion %s", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off");
661 if (event.status & FE_HAS_LOCK)
671 eDebug("stateLostLock");
672 state = stateLostLock;
673 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
676 if (m_state != state)
679 m_stateChanged(this);
684 void eDVBFrontend::timeout()
687 if (m_state == stateTuning)
689 m_state = stateFailed;
690 m_stateChanged(this);
694 #define INRANGE(X,Y,Z) (((X<=Y) && (Y<=Z))||((Z<=Y) && (Y<=X)) ? 1 : 0)
696 int eDVBFrontend::readFrontendData(int type)
705 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
706 eDebug("FE_READ_BER failed (%m)");
715 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
716 eDebug("FE_READ_SNR failed (%m)");
720 case signalQualitydB: /* this will move into the driver */
725 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
726 eDebug("FE_READ_SNR failed (%m)");
727 if (!strcmp(m_description, "BCM4501 (internal)"))
729 unsigned int SDS_SNRE = snr << 16;
731 static float SNR_COEFF[6] = {
734 197418.0 / 4194304.0,
735 -2602183.0 / 4194304.0,
736 20377212.0 / 4194304.0,
737 -37791203.0 / 4194304.0,
740 float fval1, fval2, snr_in_db;
742 fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0));
743 fval2 = pow(10.0, fval1)-1;
744 fval1 = 10.0 * log10(fval2);
748 fval2 = SNR_COEFF[0];
752 fval2 += SNR_COEFF[i];
758 return (int)(snr_in_db * 100.0);
760 else if (strstr(m_description, "Alps BSBE1 C01A") ||
761 !strcmp(m_description, "Alps -S(STV0288)"))
765 else if (snr == 0xFFFF) // i think this should not happen
769 enum { REALVAL, REGVAL };
770 const long CN_lookup[31][2] = {
771 {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
772 {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
773 {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
774 {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
775 {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
776 {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
779 int add=strchr(m_description, '.') ? 0xA250 : 0xA100;
780 long regval = 0xFFFF - ((snr / 3) + add), // revert some dvb api calulations to get the real register value
784 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
790 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[i][REGVAL]))
795 return (((regval - CN_lookup[Imin][REGVAL])
796 * (CN_lookup[Imax][REALVAL] - CN_lookup[Imin][REALVAL])
797 / (CN_lookup[Imax][REGVAL] - CN_lookup[Imin][REGVAL]))
798 + CN_lookup[Imin][REALVAL]) * 10;
804 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
805 !strcmp(m_description, "Alps -S") ||
806 !strcmp(m_description, "Philips -S") ||
807 !strcmp(m_description, "LG -S") )
809 float snr_in_db=(snr-39075)/1764.7;
810 return (int)(snr_in_db * 100.0);
811 } else if (!strcmp(m_description, "Alps BSBE2"))
813 return (int)((snr >> 7) * 10.0);
815 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
823 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
824 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
830 #if HAVE_DVB_API_VERSION < 3
831 FrontendStatus status=0;
837 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
838 eDebug("FE_READ_STATUS failed (%m)");
839 return !!(status&FE_HAS_LOCK);
845 #if HAVE_DVB_API_VERSION < 3
846 FrontendStatus status=0;
852 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
853 eDebug("FE_READ_STATUS failed (%m)");
854 return !!(status&FE_HAS_SYNC);
864 void PutToDict(ePyObject &dict, const char*key, long value)
866 ePyObject item = PyInt_FromLong(value);
869 if (PyDict_SetItemString(dict, key, item))
870 eDebug("put %s to dict failed", key);
874 eDebug("could not create PyObject for %s", key);
877 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
881 if (PyDict_SetItemString(dict, key, item))
882 eDebug("put %s to dict failed", key);
886 eDebug("invalid PyObject for %s", key);
889 void PutToDict(ePyObject &dict, const char*key, const char *value)
891 ePyObject item = PyString_FromString(value);
894 if (PyDict_SetItemString(dict, key, item))
895 eDebug("put %s to dict failed", key);
899 eDebug("could not create PyObject for %s", key);
902 void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, eDVBFrontend *fe)
906 fe->getData(eDVBFrontend::FREQ_OFFSET, freq_offset);
907 int frequency = parm_frequency + freq_offset;
908 PutToDict(dict, "frequency", frequency);
909 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
910 switch(parm_u_qpsk_fec_inner)
933 #if HAVE_DVB_API_VERSION >=3
934 case FEC_S2_8PSK_1_2:
935 case FEC_S2_QPSK_1_2:
938 case FEC_S2_8PSK_2_3:
939 case FEC_S2_QPSK_2_3:
942 case FEC_S2_8PSK_3_4:
943 case FEC_S2_QPSK_3_4:
946 case FEC_S2_8PSK_5_6:
947 case FEC_S2_QPSK_5_6:
950 case FEC_S2_8PSK_7_8:
951 case FEC_S2_QPSK_7_8:
954 case FEC_S2_8PSK_8_9:
955 case FEC_S2_QPSK_8_9:
958 case FEC_S2_8PSK_3_5:
959 case FEC_S2_QPSK_3_5:
962 case FEC_S2_8PSK_4_5:
963 case FEC_S2_QPSK_4_5:
966 case FEC_S2_8PSK_9_10:
967 case FEC_S2_QPSK_9_10:
972 PutToDict(dict, "fec_inner", tmp);
973 #if HAVE_DVB_API_VERSION >=3
974 PutToDict(dict, "modulation",
975 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ? "8PSK": "QPSK" );
976 if (parm_u_qpsk_fec_inner > FEC_AUTO)
978 switch(parm_inversion & 0xc)
980 default: // unknown rolloff
982 tmp = "ROLLOFF_0_35";
985 tmp = "ROLLOFF_0_25";
988 tmp = "ROLLOFF_0_20";
991 PutToDict(dict, "rolloff", tmp);
992 if (parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10)
994 switch(parm_inversion & 0x30)
999 case 0x10: // pilot on
1002 case 0x20: // pilot auto
1006 PutToDict(dict, "pilot", tmp);
1013 PutToDict(dict, "modulation", "QPSK" );
1016 PutToDict(dict, "system", tmp);
1019 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1022 #if HAVE_DVB_API_VERSION < 3
1023 PutToDict(dict, "frequency", parm_frequency);
1025 PutToDict(dict, "frequency", parm_frequency/1000);
1027 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1028 switch(parm_u_qam_fec_inner)
1048 #if HAVE_DVB_API_VERSION >= 3
1058 PutToDict(dict, "fec_inner", tmp);
1059 switch(parm_u_qam_modulation)
1081 PutToDict(dict, "modulation", tmp);
1084 void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1087 PutToDict(dict, "frequency", parm_frequency);
1088 switch (parm_u_ofdm_bandwidth)
1090 case BANDWIDTH_8_MHZ:
1091 tmp = "BANDWIDTH_8_MHZ";
1093 case BANDWIDTH_7_MHZ:
1094 tmp = "BANDWIDTH_7_MHZ";
1096 case BANDWIDTH_6_MHZ:
1097 tmp = "BANDWIDTH_6_MHZ";
1100 case BANDWIDTH_AUTO:
1101 tmp = "BANDWIDTH_AUTO";
1104 PutToDict(dict, "bandwidth", tmp);
1105 switch (parm_u_ofdm_code_rate_LP)
1127 PutToDict(dict, "code_rate_lp", tmp);
1128 switch (parm_u_ofdm_code_rate_HP)
1150 PutToDict(dict, "code_rate_hp", tmp);
1151 switch (parm_u_ofdm_constellation)
1167 PutToDict(dict, "constellation", tmp);
1168 switch (parm_u_ofdm_transmission_mode)
1170 case TRANSMISSION_MODE_2K:
1171 tmp = "TRANSMISSION_MODE_2K";
1173 case TRANSMISSION_MODE_8K:
1174 tmp = "TRANSMISSION_MODE_8K";
1177 case TRANSMISSION_MODE_AUTO:
1178 tmp = "TRANSMISSION_MODE_AUTO";
1181 PutToDict(dict, "transmission_mode", tmp);
1182 switch (parm_u_ofdm_guard_interval)
1184 case GUARD_INTERVAL_1_32:
1185 tmp = "GUARD_INTERVAL_1_32";
1187 case GUARD_INTERVAL_1_16:
1188 tmp = "GUARD_INTERVAL_1_16";
1190 case GUARD_INTERVAL_1_8:
1191 tmp = "GUARD_INTERVAL_1_8";
1193 case GUARD_INTERVAL_1_4:
1194 tmp = "GUARD_INTERVAL_1_4";
1197 case GUARD_INTERVAL_AUTO:
1198 tmp = "GUARD_INTERVAL_AUTO";
1201 PutToDict(dict, "guard_interval", tmp);
1202 switch (parm_u_ofdm_hierarchy_information)
1204 case HIERARCHY_NONE:
1205 tmp = "HIERARCHY_NONE";
1208 tmp = "HIERARCHY_1";
1211 tmp = "HIERARCHY_2";
1214 tmp = "HIERARCHY_4";
1217 case HIERARCHY_AUTO:
1218 tmp = "HIERARCHY_AUTO";
1221 PutToDict(dict, "hierarchy_information", tmp);
1224 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1226 if (dest && PyDict_Check(dest))
1228 const char *tmp = "UNKNOWN";
1249 PutToDict(dest, "tuner_state", tmp);
1250 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1251 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1252 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1253 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1254 int sigQualitydB = readFrontendData(signalQualitydB);
1255 if (sigQualitydB == 0x12345678) // not support yet
1257 ePyObject obj=Py_None;
1259 PutToDict(dest, "tuner_signal_quality_db", obj);
1262 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1263 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1267 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1269 if (dest && PyDict_Check(dest))
1277 FRONTENDPARAMETERS front;
1278 if (m_fd == -1 && !original)
1280 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1282 eDebug("FE_GET_FRONTEND failed (%m)");
1286 const FRONTENDPARAMETERS &parm = original || m_simulate ? this->parm : front;
1287 const char *tmp = "INVERSION_AUTO";
1288 switch(parm_inversion)
1291 tmp = "INVERSION_ON";
1294 tmp = "INVERSION_OFF";
1300 PutToDict(dest, "inversion", tmp);
1305 fillDictWithSatelliteData(dest, original?parm:front, this);
1308 fillDictWithCableData(dest, original?parm:front);
1311 fillDictWithTerrestrialData(dest, original?parm:front);
1322 void eDVBFrontend::getFrontendData(ePyObject dest)
1324 if (dest && PyDict_Check(dest))
1327 PutToDict(dest, "tuner_number", m_slotid);
1343 PutToDict(dest, "tuner_type", tmp);
1347 #ifndef FP_IOCTL_GET_ID
1348 #define FP_IOCTL_GET_ID 0
1350 int eDVBFrontend::readInputpower()
1354 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1356 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1357 FILE *f=fopen(proc_name, "r");
1360 if (fscanf(f, "%d", &power) != 1)
1361 eDebug("read %s failed!! (%m)", proc_name);
1363 eDebug("%s is %d\n", proc_name, power);
1368 // open front prozessor
1369 int fp=::open("/dev/dbox/fp0", O_RDWR);
1372 eDebug("couldn't open fp");
1375 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1376 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1378 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1387 bool eDVBFrontend::setSecSequencePos(int steps)
1389 eDebugNoSimulate("set sequence pos %d", steps);
1394 if (m_sec_sequence.current() != m_sec_sequence.end())
1395 ++m_sec_sequence.current();
1400 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1401 --m_sec_sequence.current();
1407 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1410 eDVBFrontend *sec_fe = this;
1411 eDVBRegisteredFrontend *regFE = 0;
1412 long tmp = m_data[LINKED_PREV_PTR];
1415 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1416 sec_fe = prev->m_frontend;
1417 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1418 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1419 int state = sec_fe->m_state;
1420 // workaround to put the kernel frontend thread into idle state!
1421 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1423 sec_fe->closeFrontend(true);
1424 state = sec_fe->m_state;
1426 // sec_fe is closed... we must reopen it here..
1427 if (state == eDVBFrontend::stateClosed)
1435 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1437 long *sec_fe_data = sec_fe->m_data;
1438 // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1439 switch (m_sec_sequence.current()->cmd)
1441 case eSecCommand::SLEEP:
1442 delay = m_sec_sequence.current()++->msec;
1443 eDebugNoSimulate("[SEC] sleep %dms", delay);
1445 case eSecCommand::GOTO:
1446 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1447 ++m_sec_sequence.current();
1449 case eSecCommand::SET_VOLTAGE:
1451 int voltage = m_sec_sequence.current()++->voltage;
1452 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1453 sec_fe->setVoltage(voltage);
1456 case eSecCommand::IF_VOLTAGE_GOTO:
1458 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1459 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1461 ++m_sec_sequence.current();
1464 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1466 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1467 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1469 ++m_sec_sequence.current();
1472 case eSecCommand::IF_TONE_GOTO:
1474 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1475 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1477 ++m_sec_sequence.current();
1480 case eSecCommand::IF_NOT_TONE_GOTO:
1482 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1483 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1485 ++m_sec_sequence.current();
1488 case eSecCommand::SET_TONE:
1489 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1490 sec_fe->setTone(m_sec_sequence.current()++->tone);
1492 case eSecCommand::SEND_DISEQC:
1493 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1494 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1495 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1496 eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1497 eDebugNoSimulate("");
1498 ++m_sec_sequence.current();
1500 case eSecCommand::SEND_TONEBURST:
1501 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1502 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1504 case eSecCommand::SET_FRONTEND:
1505 eDebugNoSimulate("[SEC] setFrontend");
1507 ++m_sec_sequence.current();
1509 case eSecCommand::START_TUNE_TIMEOUT:
1512 m_timeout->start(m_sec_sequence.current()->timeout, 1);
1513 ++m_sec_sequence.current();
1516 case eSecCommand::SET_TIMEOUT:
1517 m_timeoutCount = m_sec_sequence.current()++->val;
1518 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1520 case eSecCommand::IF_TIMEOUT_GOTO:
1521 if (!m_timeoutCount)
1523 eDebugNoSimulate("[SEC] rotor timout");
1524 setSecSequencePos(m_sec_sequence.current()->steps);
1527 ++m_sec_sequence.current();
1529 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1531 int idx = m_sec_sequence.current()++->val;
1532 if ( idx == 0 || idx == 1 )
1534 m_idleInputpower[idx] = sec_fe->readInputpower();
1535 eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1538 eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1541 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1543 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1544 int idx = compare.val;
1545 if ( !m_simulate && (idx == 0 || idx == 1) )
1547 int idle = sec_fe->readInputpower();
1548 int diff = abs(idle-m_idleInputpower[idx]);
1551 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1552 setSecSequencePos(compare.steps);
1556 ++m_sec_sequence.current();
1559 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1561 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1564 setSecSequencePos(cmd.steps);
1568 int isLocked = readFrontendData(locked);
1569 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1570 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 50) || !cmd.lastSignal))
1573 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1576 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1577 cmd.lastSignal = signal;
1580 if (cmd.okcount > 4)
1582 eDebugNoSimulate("ok > 4 .. goto %d\n",cmd.steps);
1583 setSecSequencePos(cmd.steps);
1584 m_state = stateLock;
1585 m_stateChanged(this);
1594 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1596 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1598 if (!m_timeoutCount && m_retryCount > 0)
1603 ++m_sec_sequence.current();
1606 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1607 m_runningInputpower = sec_fe->readInputpower();
1608 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1609 ++m_sec_sequence.current();
1611 case eSecCommand::SET_ROTOR_MOVING:
1613 m_sec->setRotorMoving(true);
1614 ++m_sec_sequence.current();
1616 case eSecCommand::SET_ROTOR_STOPPED:
1618 m_sec->setRotorMoving(false);
1619 ++m_sec_sequence.current();
1621 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1623 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1626 setSecSequencePos(cmd.steps);
1629 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1630 const char *txt = cmd.direction ? "running" : "stopped";
1631 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1633 m_runningInputpower,
1636 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1637 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1640 eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1641 if ( cmd.okcount > 6 )
1643 eDebugNoSimulate("[SEC] rotor is %s", txt);
1644 if (setSecSequencePos(cmd.steps))
1650 eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1652 if (!m_timeoutCount && m_retryCount > 0)
1656 ++m_sec_sequence.current();
1659 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1660 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1661 setSecSequencePos(m_sec_sequence.current()->steps);
1663 ++m_sec_sequence.current();
1665 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1666 eDebugNoSimulate("[SEC] invalidate current switch params");
1667 sec_fe_data[CSW] = -1;
1668 sec_fe_data[UCSW] = -1;
1669 sec_fe_data[TONEBURST] = -1;
1670 ++m_sec_sequence.current();
1672 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1673 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1674 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1675 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1676 eDebugNoSimulate("[SEC] update current switch params");
1677 ++m_sec_sequence.current();
1679 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1680 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1681 sec_fe_data[ROTOR_CMD] = -1;
1682 sec_fe_data[ROTOR_POS] = -1;
1683 ++m_sec_sequence.current();
1685 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1686 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1687 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1688 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1689 ++m_sec_sequence.current();
1691 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1692 m_retryCount = m_sec_sequence.current()++->val;
1693 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1695 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1698 eDebugNoSimulate("[SEC] no more rotor retrys");
1699 setSecSequencePos(m_sec_sequence.current()->steps);
1702 ++m_sec_sequence.current();
1704 case eSecCommand::SET_POWER_LIMITING_MODE:
1709 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1710 FILE *f=fopen(proc_name, "w");
1711 if (f) // new interface exist?
1713 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1714 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1715 eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1717 eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1720 else if (sec_fe->m_need_rotor_workaround)
1723 int slotid = sec_fe->m_slotid;
1724 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1726 sprintf(dev, "/dev/i2c/%d", slotid);
1727 else if (slotid == 2)
1728 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1729 else if (slotid == 3)
1730 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1731 int fd = ::open(dev, O_RDWR);
1733 unsigned char data[2];
1734 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1735 if(::read(fd, data, 1) != 1)
1736 eDebugNoSimulate("[SEC] error read lnbp (%m)");
1737 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1739 data[0] |= 0x80; // enable static current limiting
1740 eDebugNoSimulate("[SEC] set static current limiting");
1744 data[0] &= ~0x80; // enable dynamic current limiting
1745 eDebugNoSimulate("[SEC] set dynamic current limiting");
1747 if(::write(fd, data, 1) != 1)
1748 eDebugNoSimulate("[SEC] error write lnbp (%m)");
1752 ++m_sec_sequence.current();
1756 eDebugNoSimulate("[SEC] unhandled sec command %d",
1757 ++m_sec_sequence.current()->cmd);
1758 ++m_sec_sequence.current();
1761 m_tuneTimer->start(delay,true);
1765 if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1769 void eDVBFrontend::setFrontend()
1773 eDebug("setting frontend %d", m_dvbid);
1776 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1778 perror("FE_SET_FRONTEND failed");
1784 RESULT eDVBFrontend::getFrontendType(int &t)
1792 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1797 eWarning("no SEC module active!");
1800 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1803 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1806 feparm.polarisation,
1810 feparm.orbital_position);
1811 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1812 switch (feparm.inversion)
1814 case eDVBFrontendParametersSatellite::Inversion::On:
1815 parm_inversion = INVERSION_ON;
1817 case eDVBFrontendParametersSatellite::Inversion::Off:
1818 parm_inversion = INVERSION_OFF;
1821 case eDVBFrontendParametersSatellite::Inversion::Unknown:
1822 parm_inversion = INVERSION_AUTO;
1825 if (feparm.system == eDVBFrontendParametersSatellite::System::DVB_S)
1828 case eDVBFrontendParametersSatellite::FEC::fNone:
1829 parm_u_qpsk_fec_inner = FEC_NONE;
1831 case eDVBFrontendParametersSatellite::FEC::f1_2:
1832 parm_u_qpsk_fec_inner = FEC_1_2;
1834 case eDVBFrontendParametersSatellite::FEC::f2_3:
1835 parm_u_qpsk_fec_inner = FEC_2_3;
1837 case eDVBFrontendParametersSatellite::FEC::f3_4:
1838 parm_u_qpsk_fec_inner = FEC_3_4;
1840 case eDVBFrontendParametersSatellite::FEC::f5_6:
1841 parm_u_qpsk_fec_inner = FEC_5_6;
1843 case eDVBFrontendParametersSatellite::FEC::f7_8:
1844 parm_u_qpsk_fec_inner = FEC_7_8;
1847 eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
1848 case eDVBFrontendParametersSatellite::FEC::fAuto:
1849 parm_u_qpsk_fec_inner = FEC_AUTO;
1852 #if HAVE_DVB_API_VERSION >= 3
1857 case eDVBFrontendParametersSatellite::FEC::f1_2:
1858 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1860 case eDVBFrontendParametersSatellite::FEC::f2_3:
1861 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1863 case eDVBFrontendParametersSatellite::FEC::f3_4:
1864 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1866 case eDVBFrontendParametersSatellite::FEC::f3_5:
1867 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1869 case eDVBFrontendParametersSatellite::FEC::f4_5:
1870 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1872 case eDVBFrontendParametersSatellite::FEC::f5_6:
1873 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1875 case eDVBFrontendParametersSatellite::FEC::f7_8:
1876 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1878 case eDVBFrontendParametersSatellite::FEC::f8_9:
1879 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1881 case eDVBFrontendParametersSatellite::FEC::f9_10:
1882 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1885 eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
1888 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1889 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK) {
1890 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1891 // 8PSK fec driver values are decimal 9 bigger
1892 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1896 // FIXME !!! get frequency range from tuner
1897 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1899 eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1902 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
1907 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1909 #if HAVE_DVB_API_VERSION < 3
1910 parm_frequency = feparm.frequency;
1912 parm_frequency = feparm.frequency * 1000;
1914 parm_u_qam_symbol_rate = feparm.symbol_rate;
1915 switch (feparm.modulation)
1917 case eDVBFrontendParametersCable::Modulation::QAM16:
1918 parm_u_qam_modulation = QAM_16;
1920 case eDVBFrontendParametersCable::Modulation::QAM32:
1921 parm_u_qam_modulation = QAM_32;
1923 case eDVBFrontendParametersCable::Modulation::QAM64:
1924 parm_u_qam_modulation = QAM_64;
1926 case eDVBFrontendParametersCable::Modulation::QAM128:
1927 parm_u_qam_modulation = QAM_128;
1929 case eDVBFrontendParametersCable::Modulation::QAM256:
1930 parm_u_qam_modulation = QAM_256;
1933 case eDVBFrontendParametersCable::Modulation::Auto:
1934 parm_u_qam_modulation = QAM_AUTO;
1937 switch (feparm.inversion)
1939 case eDVBFrontendParametersCable::Inversion::On:
1940 parm_inversion = INVERSION_ON;
1942 case eDVBFrontendParametersCable::Inversion::Off:
1943 parm_inversion = INVERSION_OFF;
1946 case eDVBFrontendParametersCable::Inversion::Unknown:
1947 parm_inversion = INVERSION_AUTO;
1950 switch (feparm.fec_inner)
1952 case eDVBFrontendParametersCable::FEC::fNone:
1953 parm_u_qam_fec_inner = FEC_NONE;
1955 case eDVBFrontendParametersCable::FEC::f1_2:
1956 parm_u_qam_fec_inner = FEC_1_2;
1958 case eDVBFrontendParametersCable::FEC::f2_3:
1959 parm_u_qam_fec_inner = FEC_2_3;
1961 case eDVBFrontendParametersCable::FEC::f3_4:
1962 parm_u_qam_fec_inner = FEC_3_4;
1964 case eDVBFrontendParametersCable::FEC::f5_6:
1965 parm_u_qam_fec_inner = FEC_5_6;
1967 case eDVBFrontendParametersCable::FEC::f7_8:
1968 parm_u_qam_fec_inner = FEC_7_8;
1970 #if HAVE_DVB_API_VERSION >= 3
1971 case eDVBFrontendParametersCable::FEC::f8_9:
1972 parm_u_qam_fec_inner = FEC_8_9;
1976 case eDVBFrontendParametersCable::FEC::fAuto:
1977 parm_u_qam_fec_inner = FEC_AUTO;
1980 eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
1981 parm_frequency/1000,
1982 parm_u_qam_symbol_rate,
1983 parm_u_qam_fec_inner,
1984 parm_u_qam_modulation,
1989 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
1991 parm_frequency = feparm.frequency;
1993 switch (feparm.bandwidth)
1995 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
1996 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
1998 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
1999 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
2001 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
2002 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
2005 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
2006 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
2009 switch (feparm.code_rate_LP)
2011 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
2012 parm_u_ofdm_code_rate_LP = FEC_1_2;
2014 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
2015 parm_u_ofdm_code_rate_LP = FEC_2_3;
2017 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
2018 parm_u_ofdm_code_rate_LP = FEC_3_4;
2020 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
2021 parm_u_ofdm_code_rate_LP = FEC_5_6;
2023 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
2024 parm_u_ofdm_code_rate_LP = FEC_7_8;
2027 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
2028 parm_u_ofdm_code_rate_LP = FEC_AUTO;
2031 switch (feparm.code_rate_HP)
2033 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
2034 parm_u_ofdm_code_rate_HP = FEC_1_2;
2036 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
2037 parm_u_ofdm_code_rate_HP = FEC_2_3;
2039 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
2040 parm_u_ofdm_code_rate_HP = FEC_3_4;
2042 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
2043 parm_u_ofdm_code_rate_HP = FEC_5_6;
2045 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
2046 parm_u_ofdm_code_rate_HP = FEC_7_8;
2049 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
2050 parm_u_ofdm_code_rate_HP = FEC_AUTO;
2053 switch (feparm.modulation)
2055 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
2056 parm_u_ofdm_constellation = QPSK;
2058 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
2059 parm_u_ofdm_constellation = QAM_16;
2061 case eDVBFrontendParametersTerrestrial::Modulation::QAM64:
2062 parm_u_ofdm_constellation = QAM_64;
2065 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
2066 parm_u_ofdm_constellation = QAM_AUTO;
2069 switch (feparm.transmission_mode)
2071 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
2072 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2074 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
2075 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2078 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
2079 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2082 switch (feparm.guard_interval)
2084 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32:
2085 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2087 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16:
2088 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2090 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8:
2091 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2093 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4:
2094 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2097 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto:
2098 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2101 switch (feparm.hierarchy)
2103 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone:
2104 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2106 case eDVBFrontendParametersTerrestrial::Hierarchy::H1:
2107 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2109 case eDVBFrontendParametersTerrestrial::Hierarchy::H2:
2110 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2112 case eDVBFrontendParametersTerrestrial::Hierarchy::H4:
2113 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2116 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto:
2117 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2120 switch (feparm.inversion)
2122 case eDVBFrontendParametersTerrestrial::Inversion::On:
2123 parm_inversion = INVERSION_ON;
2125 case eDVBFrontendParametersTerrestrial::Inversion::Off:
2126 parm_inversion = INVERSION_OFF;
2129 case eDVBFrontendParametersTerrestrial::Inversion::Unknown:
2130 parm_inversion = INVERSION_AUTO;
2136 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2138 unsigned int timeout = 5000;
2139 eDebugNoSimulate("(%d)tune", m_dvbid);
2145 if (!m_sn && !m_simulate)
2147 eDebug("no frontend device opened... do not try to tune !!!");
2161 m_sec_sequence.clear();
2163 where.calcLockTimeout(timeout);
2169 eDVBFrontendParametersSatellite feparm;
2170 if (where.getDVBS(feparm))
2172 eDebug("no dvbs data!");
2177 m_sec->setRotorMoving(false);
2178 res=prepare_sat(feparm, timeout);
2186 eDVBFrontendParametersCable feparm;
2187 if (where.getDVBC(feparm))
2192 res=prepare_cable(feparm);
2196 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2197 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2202 eDVBFrontendParametersTerrestrial feparm;
2203 if (where.getDVBT(feparm))
2205 eDebug("no -T data");
2209 res=prepare_terrestrial(feparm);
2213 std::string enable_5V;
2214 char configStr[255];
2215 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2216 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2217 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2218 if (enable_5V == "True")
2219 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2221 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2222 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2228 m_sec_sequence.current() = m_sec_sequence.begin();
2232 m_tuneTimer->start(0,true);
2233 if (m_state != stateTuning)
2236 m_state = stateTuning;
2237 m_stateChanged(this);
2246 m_tuneTimer->stop();
2250 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2252 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2256 RESULT eDVBFrontend::setVoltage(int voltage)
2258 if (m_type == feCable)
2260 #if HAVE_DVB_API_VERSION < 3
2263 bool increased=false;
2264 fe_sec_voltage_t vlt;
2266 m_data[CUR_VOLTAGE]=voltage;
2270 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2271 vlt = SEC_VOLTAGE_OFF;
2274 #if HAVE_DVB_API_VERSION < 3
2275 vlt = SEC_VOLTAGE_13_5;
2281 vlt = SEC_VOLTAGE_13;
2284 #if HAVE_DVB_API_VERSION < 3
2285 vlt = SEC_VOLTAGE_18_5;
2291 vlt = SEC_VOLTAGE_18;
2298 #if HAVE_DVB_API_VERSION < 3
2299 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2301 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2302 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2303 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2307 RESULT eDVBFrontend::getState(int &state)
2313 RESULT eDVBFrontend::setTone(int t)
2315 if (m_type != feSatellite)
2317 #if HAVE_DVB_API_VERSION < 3
2320 fe_sec_tone_mode_t tone;
2329 tone = SEC_TONE_OFF;
2336 #if HAVE_DVB_API_VERSION < 3
2337 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2339 return ::ioctl(m_fd, FE_SET_TONE, tone);
2343 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2344 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2347 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2351 #if HAVE_DVB_API_VERSION < 3
2352 struct secCommand cmd;
2353 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2354 cmd.u.diseqc.cmdtype = diseqc.data[0];
2355 cmd.u.diseqc.addr = diseqc.data[1];
2356 cmd.u.diseqc.cmd = diseqc.data[2];
2357 cmd.u.diseqc.numParams = diseqc.len-3;
2358 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2359 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2361 struct dvb_diseqc_master_cmd cmd;
2362 memcpy(cmd.msg, diseqc.data, diseqc.len);
2363 cmd.msg_len = diseqc.len;
2364 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2370 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2371 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2373 RESULT eDVBFrontend::sendToneburst(int burst)
2377 #if HAVE_DVB_API_VERSION < 3
2378 secMiniCmd cmd = SEC_MINI_NONE;
2380 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2382 if ( burst == eDVBSatelliteDiseqcParameters::A )
2384 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2386 #if HAVE_DVB_API_VERSION < 3
2387 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2390 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2396 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2402 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2404 m_sec_sequence = list;
2408 RESULT eDVBFrontend::getData(int num, long &data)
2410 if ( num < NUM_DATA_ENTRIES )
2418 RESULT eDVBFrontend::setData(int num, long val)
2420 if ( num < NUM_DATA_ENTRIES )
2428 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2431 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2433 if (m_type == eDVBFrontend::feSatellite)
2436 eDVBFrontendParametersSatellite sat_parm;
2437 int ret = feparm->getDVBS(sat_parm);
2439 if (sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S2 && !m_can_handle_dvbs2)
2441 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2442 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S && m_can_handle_dvbs2)
2446 else if (m_type == eDVBFrontend::feCable)
2447 return 2; // more prio for cable frontends
2448 else if (m_type == eDVBFrontend::feTerrestrial)
2453 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2455 ePyObject Id, Descr, Enabled, IsDVBS2;
2456 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4)
2458 Id = PyTuple_GET_ITEM(obj, 0);
2459 Descr = PyTuple_GET_ITEM(obj, 1);
2460 Enabled = PyTuple_GET_ITEM(obj, 2);
2461 IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2462 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2))
2464 strcpy(m_description, PyString_AS_STRING(Descr));
2465 m_slotid = PyInt_AsLong(Id);
2466 m_enabled = Enabled == Py_True;
2467 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2468 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2469 !!strstr(m_description, "Alps BSBE2") ||
2470 !!strstr(m_description, "Alps -S") ||
2471 !!strstr(m_description, "BCM4501");
2472 m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2473 eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2474 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2477 PyErr_SetString(PyExc_StandardError,
2478 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");