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 = eTimer::create(eApp);
459 CONNECT(m_timeout->timeout, eDVBFrontend::timeout);
461 m_tuneTimer = eTimer::create(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;
622 void eDVBFrontend::feEvent(int w)
624 eDVBFrontend *sec_fe = this;
625 long tmp = m_data[LINKED_PREV_PTR];
628 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
629 sec_fe = linked_fe->m_frontend;
630 sec_fe->getData(LINKED_NEXT_PTR, tmp);
634 #if HAVE_DVB_API_VERSION < 3
637 dvb_frontend_event event;
641 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
643 if (res && (errno == EAGAIN))
648 eWarning("FE_GET_EVENT failed! %m");
655 #if HAVE_DVB_API_VERSION < 3
656 if (event.type == FE_COMPLETION_EV)
658 eDebug("(%d)fe event: status %x, inversion %s", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off");
659 if (event.status & FE_HAS_LOCK)
669 eDebug("stateLostLock");
670 state = stateLostLock;
671 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
674 if (m_state != state)
677 m_stateChanged(this);
682 void eDVBFrontend::timeout()
685 if (m_state == stateTuning)
687 m_state = stateFailed;
688 m_stateChanged(this);
692 #define INRANGE(X,Y,Z) (((X<=Y) && (Y<=Z))||((Z<=Y) && (Y<=X)) ? 1 : 0)
694 int eDVBFrontend::readFrontendData(int type)
703 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
704 eDebug("FE_READ_BER failed (%m)");
713 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
714 eDebug("FE_READ_SNR failed (%m)");
718 case signalQualitydB: /* this will move into the driver */
723 if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
724 eDebug("FE_READ_SNR failed (%m)");
725 if (!strcmp(m_description, "BCM4501 (internal)"))
727 unsigned int SDS_SNRE = snr << 16;
729 static float SNR_COEFF[6] = {
732 197418.0 / 4194304.0,
733 -2602183.0 / 4194304.0,
734 20377212.0 / 4194304.0,
735 -37791203.0 / 4194304.0,
738 float fval1, fval2, snr_in_db;
740 fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0));
741 fval2 = pow(10.0, fval1)-1;
742 fval1 = 10.0 * log10(fval2);
746 fval2 = SNR_COEFF[0];
750 fval2 += SNR_COEFF[i];
756 return (int)(snr_in_db * 100.0);
758 else if (strstr(m_description, "Alps BSBE1 C01A") ||
759 !strcmp(m_description, "Alps -S(STV0288)"))
763 else if (snr == 0xFFFF) // i think this should not happen
767 enum { REALVAL, REGVAL };
768 const long CN_lookup[31][2] = {
769 {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
770 {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
771 {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
772 {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
773 {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
774 {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
777 int add=strchr(m_description, '.') ? 0xA250 : 0xA100;
778 long regval = 0xFFFF - ((snr / 3) + add), // revert some dvb api calulations to get the real register value
782 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
788 if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[i][REGVAL]))
793 return (((regval - CN_lookup[Imin][REGVAL])
794 * (CN_lookup[Imax][REALVAL] - CN_lookup[Imin][REALVAL])
795 / (CN_lookup[Imax][REGVAL] - CN_lookup[Imin][REGVAL]))
796 + CN_lookup[Imin][REALVAL]) * 10;
802 else if (!strcmp(m_description, "Alps BSBE1 702A") || // some frontends with STV0299
803 !strcmp(m_description, "Alps -S") ||
804 !strcmp(m_description, "Philips -S") ||
805 !strcmp(m_description, "LG -S") )
807 float snr_in_db=(snr-39075)/1764.7;
808 return (int)(snr_in_db * 100.0);
809 } else if (!strcmp(m_description, "Alps BSBE2"))
811 return (int)((snr >> 7) * 10.0);
813 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
821 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
822 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
828 #if HAVE_DVB_API_VERSION < 3
829 FrontendStatus status=0;
835 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
836 eDebug("FE_READ_STATUS failed (%m)");
837 return !!(status&FE_HAS_LOCK);
843 #if HAVE_DVB_API_VERSION < 3
844 FrontendStatus status=0;
850 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
851 eDebug("FE_READ_STATUS failed (%m)");
852 return !!(status&FE_HAS_SYNC);
862 void PutToDict(ePyObject &dict, const char*key, long value)
864 ePyObject item = PyInt_FromLong(value);
867 if (PyDict_SetItemString(dict, key, item))
868 eDebug("put %s to dict failed", key);
872 eDebug("could not create PyObject for %s", key);
875 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
879 if (PyDict_SetItemString(dict, key, item))
880 eDebug("put %s to dict failed", key);
884 eDebug("invalid PyObject for %s", key);
887 void PutToDict(ePyObject &dict, const char*key, const char *value)
889 ePyObject item = PyString_FromString(value);
892 if (PyDict_SetItemString(dict, key, item))
893 eDebug("put %s to dict failed", key);
897 eDebug("could not create PyObject for %s", key);
900 void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, eDVBFrontend *fe)
904 fe->getData(eDVBFrontend::FREQ_OFFSET, freq_offset);
905 int frequency = parm_frequency + freq_offset;
906 PutToDict(dict, "frequency", frequency);
907 PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
908 switch(parm_u_qpsk_fec_inner)
931 #if HAVE_DVB_API_VERSION >=3
932 case FEC_S2_8PSK_1_2:
933 case FEC_S2_QPSK_1_2:
936 case FEC_S2_8PSK_2_3:
937 case FEC_S2_QPSK_2_3:
940 case FEC_S2_8PSK_3_4:
941 case FEC_S2_QPSK_3_4:
944 case FEC_S2_8PSK_5_6:
945 case FEC_S2_QPSK_5_6:
948 case FEC_S2_8PSK_7_8:
949 case FEC_S2_QPSK_7_8:
952 case FEC_S2_8PSK_8_9:
953 case FEC_S2_QPSK_8_9:
956 case FEC_S2_8PSK_3_5:
957 case FEC_S2_QPSK_3_5:
960 case FEC_S2_8PSK_4_5:
961 case FEC_S2_QPSK_4_5:
964 case FEC_S2_8PSK_9_10:
965 case FEC_S2_QPSK_9_10:
970 PutToDict(dict, "fec_inner", tmp);
971 #if HAVE_DVB_API_VERSION >=3
972 PutToDict(dict, "modulation",
973 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ? "8PSK": "QPSK" );
974 if (parm_u_qpsk_fec_inner > FEC_AUTO)
976 switch(parm_inversion & 0xc)
978 default: // unknown rolloff
980 tmp = "ROLLOFF_0_35";
983 tmp = "ROLLOFF_0_25";
986 tmp = "ROLLOFF_0_20";
989 PutToDict(dict, "rolloff", tmp);
990 if (parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10)
992 switch(parm_inversion & 0x30)
997 case 0x10: // pilot on
1000 case 0x20: // pilot auto
1004 PutToDict(dict, "pilot", tmp);
1011 PutToDict(dict, "modulation", "QPSK" );
1014 PutToDict(dict, "system", tmp);
1017 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1020 #if HAVE_DVB_API_VERSION < 3
1021 PutToDict(dict, "frequency", parm_frequency);
1023 PutToDict(dict, "frequency", parm_frequency/1000);
1025 PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1026 switch(parm_u_qam_fec_inner)
1046 #if HAVE_DVB_API_VERSION >= 3
1056 PutToDict(dict, "fec_inner", tmp);
1057 switch(parm_u_qam_modulation)
1079 PutToDict(dict, "modulation", tmp);
1082 void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1085 PutToDict(dict, "frequency", parm_frequency);
1086 switch (parm_u_ofdm_bandwidth)
1088 case BANDWIDTH_8_MHZ:
1089 tmp = "BANDWIDTH_8_MHZ";
1091 case BANDWIDTH_7_MHZ:
1092 tmp = "BANDWIDTH_7_MHZ";
1094 case BANDWIDTH_6_MHZ:
1095 tmp = "BANDWIDTH_6_MHZ";
1098 case BANDWIDTH_AUTO:
1099 tmp = "BANDWIDTH_AUTO";
1102 PutToDict(dict, "bandwidth", tmp);
1103 switch (parm_u_ofdm_code_rate_LP)
1125 PutToDict(dict, "code_rate_lp", tmp);
1126 switch (parm_u_ofdm_code_rate_HP)
1148 PutToDict(dict, "code_rate_hp", tmp);
1149 switch (parm_u_ofdm_constellation)
1165 PutToDict(dict, "constellation", tmp);
1166 switch (parm_u_ofdm_transmission_mode)
1168 case TRANSMISSION_MODE_2K:
1169 tmp = "TRANSMISSION_MODE_2K";
1171 case TRANSMISSION_MODE_8K:
1172 tmp = "TRANSMISSION_MODE_8K";
1175 case TRANSMISSION_MODE_AUTO:
1176 tmp = "TRANSMISSION_MODE_AUTO";
1179 PutToDict(dict, "transmission_mode", tmp);
1180 switch (parm_u_ofdm_guard_interval)
1182 case GUARD_INTERVAL_1_32:
1183 tmp = "GUARD_INTERVAL_1_32";
1185 case GUARD_INTERVAL_1_16:
1186 tmp = "GUARD_INTERVAL_1_16";
1188 case GUARD_INTERVAL_1_8:
1189 tmp = "GUARD_INTERVAL_1_8";
1191 case GUARD_INTERVAL_1_4:
1192 tmp = "GUARD_INTERVAL_1_4";
1195 case GUARD_INTERVAL_AUTO:
1196 tmp = "GUARD_INTERVAL_AUTO";
1199 PutToDict(dict, "guard_interval", tmp);
1200 switch (parm_u_ofdm_hierarchy_information)
1202 case HIERARCHY_NONE:
1203 tmp = "HIERARCHY_NONE";
1206 tmp = "HIERARCHY_1";
1209 tmp = "HIERARCHY_2";
1212 tmp = "HIERARCHY_4";
1215 case HIERARCHY_AUTO:
1216 tmp = "HIERARCHY_AUTO";
1219 PutToDict(dict, "hierarchy_information", tmp);
1222 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1224 if (dest && PyDict_Check(dest))
1226 const char *tmp = "UNKNOWN";
1247 PutToDict(dest, "tuner_state", tmp);
1248 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1249 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1250 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1251 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1252 int sigQualitydB = readFrontendData(signalQualitydB);
1253 if (sigQualitydB == 0x12345678) // not support yet
1255 ePyObject obj=Py_None;
1257 PutToDict(dest, "tuner_signal_quality_db", obj);
1260 PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1261 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1265 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1267 if (dest && PyDict_Check(dest))
1275 FRONTENDPARAMETERS front;
1276 if (m_fd == -1 && !original)
1278 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1280 eDebug("FE_GET_FRONTEND failed (%m)");
1284 const FRONTENDPARAMETERS &parm = original || m_simulate ? this->parm : front;
1285 const char *tmp = "INVERSION_AUTO";
1286 switch(parm_inversion)
1289 tmp = "INVERSION_ON";
1292 tmp = "INVERSION_OFF";
1298 PutToDict(dest, "inversion", tmp);
1303 fillDictWithSatelliteData(dest, original?parm:front, this);
1306 fillDictWithCableData(dest, original?parm:front);
1309 fillDictWithTerrestrialData(dest, original?parm:front);
1320 void eDVBFrontend::getFrontendData(ePyObject dest)
1322 if (dest && PyDict_Check(dest))
1325 PutToDict(dest, "tuner_number", m_slotid);
1341 PutToDict(dest, "tuner_type", tmp);
1345 #ifndef FP_IOCTL_GET_ID
1346 #define FP_IOCTL_GET_ID 0
1348 int eDVBFrontend::readInputpower()
1352 int power=m_slotid; // this is needed for read inputpower from the correct tuner !
1354 sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1355 FILE *f=fopen(proc_name, "r");
1358 if (fscanf(f, "%d", &power) != 1)
1359 eDebug("read %s failed!! (%m)", proc_name);
1361 eDebug("%s is %d\n", proc_name, power);
1366 // open front prozessor
1367 int fp=::open("/dev/dbox/fp0", O_RDWR);
1370 eDebug("couldn't open fp");
1373 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1374 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1376 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1385 bool eDVBFrontend::setSecSequencePos(int steps)
1387 eDebugNoSimulate("set sequence pos %d", steps);
1392 if (m_sec_sequence.current() != m_sec_sequence.end())
1393 ++m_sec_sequence.current();
1398 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1399 --m_sec_sequence.current();
1405 void eDVBFrontend::tuneLoop() // called by m_tuneTimer
1408 eDVBFrontend *sec_fe = this;
1409 eDVBRegisteredFrontend *regFE = 0;
1410 long tmp = m_data[LINKED_PREV_PTR];
1413 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1414 sec_fe = prev->m_frontend;
1415 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1416 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1417 int state = sec_fe->m_state;
1418 // workaround to put the kernel frontend thread into idle state!
1419 if (state != eDVBFrontend::stateIdle && state != stateClosed)
1421 sec_fe->closeFrontend(true);
1422 state = sec_fe->m_state;
1424 // sec_fe is closed... we must reopen it here..
1425 if (state == eDVBFrontend::stateClosed)
1433 if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1435 long *sec_fe_data = sec_fe->m_data;
1436 // eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1437 switch (m_sec_sequence.current()->cmd)
1439 case eSecCommand::SLEEP:
1440 delay = m_sec_sequence.current()++->msec;
1441 eDebugNoSimulate("[SEC] sleep %dms", delay);
1443 case eSecCommand::GOTO:
1444 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1445 ++m_sec_sequence.current();
1447 case eSecCommand::SET_VOLTAGE:
1449 int voltage = m_sec_sequence.current()++->voltage;
1450 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1451 sec_fe->setVoltage(voltage);
1454 case eSecCommand::IF_VOLTAGE_GOTO:
1456 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1457 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1459 ++m_sec_sequence.current();
1462 case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1464 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1465 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1467 ++m_sec_sequence.current();
1470 case eSecCommand::IF_TONE_GOTO:
1472 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1473 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1475 ++m_sec_sequence.current();
1478 case eSecCommand::IF_NOT_TONE_GOTO:
1480 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1481 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1483 ++m_sec_sequence.current();
1486 case eSecCommand::SET_TONE:
1487 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1488 sec_fe->setTone(m_sec_sequence.current()++->tone);
1490 case eSecCommand::SEND_DISEQC:
1491 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1492 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1493 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1494 eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1495 eDebugNoSimulate("");
1496 ++m_sec_sequence.current();
1498 case eSecCommand::SEND_TONEBURST:
1499 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1500 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1502 case eSecCommand::SET_FRONTEND:
1503 eDebugNoSimulate("[SEC] setFrontend");
1505 ++m_sec_sequence.current();
1507 case eSecCommand::START_TUNE_TIMEOUT:
1510 m_timeout->start(m_sec_sequence.current()->timeout, 1);
1511 ++m_sec_sequence.current();
1514 case eSecCommand::SET_TIMEOUT:
1515 m_timeoutCount = m_sec_sequence.current()++->val;
1516 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1518 case eSecCommand::IF_TIMEOUT_GOTO:
1519 if (!m_timeoutCount)
1521 eDebugNoSimulate("[SEC] rotor timout");
1522 setSecSequencePos(m_sec_sequence.current()->steps);
1525 ++m_sec_sequence.current();
1527 case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1529 int idx = m_sec_sequence.current()++->val;
1530 if ( idx == 0 || idx == 1 )
1532 m_idleInputpower[idx] = sec_fe->readInputpower();
1533 eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1536 eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1539 case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1541 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1542 int idx = compare.val;
1543 if ( !m_simulate && (idx == 0 || idx == 1) )
1545 int idle = sec_fe->readInputpower();
1546 int diff = abs(idle-m_idleInputpower[idx]);
1549 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1550 setSecSequencePos(compare.steps);
1554 ++m_sec_sequence.current();
1557 case eSecCommand::IF_TUNER_LOCKED_GOTO:
1559 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1562 setSecSequencePos(cmd.steps);
1566 int isLocked = readFrontendData(locked);
1567 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1568 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 50) || !cmd.lastSignal))
1571 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1574 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1575 cmd.lastSignal = signal;
1578 if (cmd.okcount > 4)
1580 eDebugNoSimulate("ok > 4 .. goto %d\n",cmd.steps);
1581 setSecSequencePos(cmd.steps);
1582 m_state = stateLock;
1583 m_stateChanged(this);
1592 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1594 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1596 if (!m_timeoutCount && m_retryCount > 0)
1601 ++m_sec_sequence.current();
1604 case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1605 m_runningInputpower = sec_fe->readInputpower();
1606 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1607 ++m_sec_sequence.current();
1609 case eSecCommand::SET_ROTOR_MOVING:
1611 m_sec->setRotorMoving(true);
1612 ++m_sec_sequence.current();
1614 case eSecCommand::SET_ROTOR_STOPPED:
1616 m_sec->setRotorMoving(false);
1617 ++m_sec_sequence.current();
1619 case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1621 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1624 setSecSequencePos(cmd.steps);
1627 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1628 const char *txt = cmd.direction ? "running" : "stopped";
1629 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1631 m_runningInputpower,
1634 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1635 || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1638 eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1639 if ( cmd.okcount > 6 )
1641 eDebugNoSimulate("[SEC] rotor is %s", txt);
1642 if (setSecSequencePos(cmd.steps))
1648 eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1650 if (!m_timeoutCount && m_retryCount > 0)
1654 ++m_sec_sequence.current();
1657 case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1658 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1659 setSecSequencePos(m_sec_sequence.current()->steps);
1661 ++m_sec_sequence.current();
1663 case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1664 eDebugNoSimulate("[SEC] invalidate current switch params");
1665 sec_fe_data[CSW] = -1;
1666 sec_fe_data[UCSW] = -1;
1667 sec_fe_data[TONEBURST] = -1;
1668 ++m_sec_sequence.current();
1670 case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1671 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1672 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1673 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1674 eDebugNoSimulate("[SEC] update current switch params");
1675 ++m_sec_sequence.current();
1677 case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1678 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1679 sec_fe_data[ROTOR_CMD] = -1;
1680 sec_fe_data[ROTOR_POS] = -1;
1681 ++m_sec_sequence.current();
1683 case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1684 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1685 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1686 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1687 ++m_sec_sequence.current();
1689 case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1690 m_retryCount = m_sec_sequence.current()++->val;
1691 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1693 case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1696 eDebugNoSimulate("[SEC] no more rotor retrys");
1697 setSecSequencePos(m_sec_sequence.current()->steps);
1700 ++m_sec_sequence.current();
1702 case eSecCommand::SET_POWER_LIMITING_MODE:
1707 sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1708 FILE *f=fopen(proc_name, "w");
1709 if (f) // new interface exist?
1711 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1712 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1713 eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1715 eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1718 else if (sec_fe->m_need_rotor_workaround)
1721 int slotid = sec_fe->m_slotid;
1722 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1724 sprintf(dev, "/dev/i2c/%d", slotid);
1725 else if (slotid == 2)
1726 sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1727 else if (slotid == 3)
1728 sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1729 int fd = ::open(dev, O_RDWR);
1731 unsigned char data[2];
1732 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1733 if(::read(fd, data, 1) != 1)
1734 eDebugNoSimulate("[SEC] error read lnbp (%m)");
1735 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1737 data[0] |= 0x80; // enable static current limiting
1738 eDebugNoSimulate("[SEC] set static current limiting");
1742 data[0] &= ~0x80; // enable dynamic current limiting
1743 eDebugNoSimulate("[SEC] set dynamic current limiting");
1745 if(::write(fd, data, 1) != 1)
1746 eDebugNoSimulate("[SEC] error write lnbp (%m)");
1750 ++m_sec_sequence.current();
1754 eDebugNoSimulate("[SEC] unhandled sec command %d",
1755 ++m_sec_sequence.current()->cmd);
1756 ++m_sec_sequence.current();
1759 m_tuneTimer->start(delay,true);
1763 if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1767 void eDVBFrontend::setFrontend()
1771 eDebug("setting frontend %d", m_dvbid);
1774 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1776 perror("FE_SET_FRONTEND failed");
1782 RESULT eDVBFrontend::getFrontendType(int &t)
1790 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1795 eWarning("no SEC module active!");
1798 res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1801 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1804 feparm.polarisation,
1808 feparm.orbital_position);
1809 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1810 switch (feparm.inversion)
1812 case eDVBFrontendParametersSatellite::Inversion::On:
1813 parm_inversion = INVERSION_ON;
1815 case eDVBFrontendParametersSatellite::Inversion::Off:
1816 parm_inversion = INVERSION_OFF;
1819 case eDVBFrontendParametersSatellite::Inversion::Unknown:
1820 parm_inversion = INVERSION_AUTO;
1823 if (feparm.system == eDVBFrontendParametersSatellite::System::DVB_S)
1826 case eDVBFrontendParametersSatellite::FEC::fNone:
1827 parm_u_qpsk_fec_inner = FEC_NONE;
1829 case eDVBFrontendParametersSatellite::FEC::f1_2:
1830 parm_u_qpsk_fec_inner = FEC_1_2;
1832 case eDVBFrontendParametersSatellite::FEC::f2_3:
1833 parm_u_qpsk_fec_inner = FEC_2_3;
1835 case eDVBFrontendParametersSatellite::FEC::f3_4:
1836 parm_u_qpsk_fec_inner = FEC_3_4;
1838 case eDVBFrontendParametersSatellite::FEC::f5_6:
1839 parm_u_qpsk_fec_inner = FEC_5_6;
1841 case eDVBFrontendParametersSatellite::FEC::f7_8:
1842 parm_u_qpsk_fec_inner = FEC_7_8;
1845 eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
1846 case eDVBFrontendParametersSatellite::FEC::fAuto:
1847 parm_u_qpsk_fec_inner = FEC_AUTO;
1850 #if HAVE_DVB_API_VERSION >= 3
1855 case eDVBFrontendParametersSatellite::FEC::f1_2:
1856 parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1858 case eDVBFrontendParametersSatellite::FEC::f2_3:
1859 parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1861 case eDVBFrontendParametersSatellite::FEC::f3_4:
1862 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1864 case eDVBFrontendParametersSatellite::FEC::f3_5:
1865 parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1867 case eDVBFrontendParametersSatellite::FEC::f4_5:
1868 parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1870 case eDVBFrontendParametersSatellite::FEC::f5_6:
1871 parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1873 case eDVBFrontendParametersSatellite::FEC::f7_8:
1874 parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1876 case eDVBFrontendParametersSatellite::FEC::f8_9:
1877 parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1879 case eDVBFrontendParametersSatellite::FEC::f9_10:
1880 parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1883 eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
1886 parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1887 if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK) {
1888 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1889 // 8PSK fec driver values are decimal 9 bigger
1890 parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1894 // FIXME !!! get frequency range from tuner
1895 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1897 eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1900 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
1905 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1907 #if HAVE_DVB_API_VERSION < 3
1908 parm_frequency = feparm.frequency;
1910 parm_frequency = feparm.frequency * 1000;
1912 parm_u_qam_symbol_rate = feparm.symbol_rate;
1913 switch (feparm.modulation)
1915 case eDVBFrontendParametersCable::Modulation::QAM16:
1916 parm_u_qam_modulation = QAM_16;
1918 case eDVBFrontendParametersCable::Modulation::QAM32:
1919 parm_u_qam_modulation = QAM_32;
1921 case eDVBFrontendParametersCable::Modulation::QAM64:
1922 parm_u_qam_modulation = QAM_64;
1924 case eDVBFrontendParametersCable::Modulation::QAM128:
1925 parm_u_qam_modulation = QAM_128;
1927 case eDVBFrontendParametersCable::Modulation::QAM256:
1928 parm_u_qam_modulation = QAM_256;
1931 case eDVBFrontendParametersCable::Modulation::Auto:
1932 parm_u_qam_modulation = QAM_AUTO;
1935 switch (feparm.inversion)
1937 case eDVBFrontendParametersCable::Inversion::On:
1938 parm_inversion = INVERSION_ON;
1940 case eDVBFrontendParametersCable::Inversion::Off:
1941 parm_inversion = INVERSION_OFF;
1944 case eDVBFrontendParametersCable::Inversion::Unknown:
1945 parm_inversion = INVERSION_AUTO;
1948 switch (feparm.fec_inner)
1950 case eDVBFrontendParametersCable::FEC::fNone:
1951 parm_u_qam_fec_inner = FEC_NONE;
1953 case eDVBFrontendParametersCable::FEC::f1_2:
1954 parm_u_qam_fec_inner = FEC_1_2;
1956 case eDVBFrontendParametersCable::FEC::f2_3:
1957 parm_u_qam_fec_inner = FEC_2_3;
1959 case eDVBFrontendParametersCable::FEC::f3_4:
1960 parm_u_qam_fec_inner = FEC_3_4;
1962 case eDVBFrontendParametersCable::FEC::f5_6:
1963 parm_u_qam_fec_inner = FEC_5_6;
1965 case eDVBFrontendParametersCable::FEC::f7_8:
1966 parm_u_qam_fec_inner = FEC_7_8;
1968 #if HAVE_DVB_API_VERSION >= 3
1969 case eDVBFrontendParametersCable::FEC::f8_9:
1970 parm_u_qam_fec_inner = FEC_8_9;
1974 case eDVBFrontendParametersCable::FEC::fAuto:
1975 parm_u_qam_fec_inner = FEC_AUTO;
1978 eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
1979 parm_frequency/1000,
1980 parm_u_qam_symbol_rate,
1981 parm_u_qam_fec_inner,
1982 parm_u_qam_modulation,
1987 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
1989 parm_frequency = feparm.frequency;
1991 switch (feparm.bandwidth)
1993 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
1994 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
1996 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
1997 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
1999 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
2000 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
2003 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
2004 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
2007 switch (feparm.code_rate_LP)
2009 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
2010 parm_u_ofdm_code_rate_LP = FEC_1_2;
2012 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
2013 parm_u_ofdm_code_rate_LP = FEC_2_3;
2015 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
2016 parm_u_ofdm_code_rate_LP = FEC_3_4;
2018 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
2019 parm_u_ofdm_code_rate_LP = FEC_5_6;
2021 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
2022 parm_u_ofdm_code_rate_LP = FEC_7_8;
2025 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
2026 parm_u_ofdm_code_rate_LP = FEC_AUTO;
2029 switch (feparm.code_rate_HP)
2031 case eDVBFrontendParametersTerrestrial::FEC::f1_2:
2032 parm_u_ofdm_code_rate_HP = FEC_1_2;
2034 case eDVBFrontendParametersTerrestrial::FEC::f2_3:
2035 parm_u_ofdm_code_rate_HP = FEC_2_3;
2037 case eDVBFrontendParametersTerrestrial::FEC::f3_4:
2038 parm_u_ofdm_code_rate_HP = FEC_3_4;
2040 case eDVBFrontendParametersTerrestrial::FEC::f5_6:
2041 parm_u_ofdm_code_rate_HP = FEC_5_6;
2043 case eDVBFrontendParametersTerrestrial::FEC::f7_8:
2044 parm_u_ofdm_code_rate_HP = FEC_7_8;
2047 case eDVBFrontendParametersTerrestrial::FEC::fAuto:
2048 parm_u_ofdm_code_rate_HP = FEC_AUTO;
2051 switch (feparm.modulation)
2053 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
2054 parm_u_ofdm_constellation = QPSK;
2056 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
2057 parm_u_ofdm_constellation = QAM_16;
2059 case eDVBFrontendParametersTerrestrial::Modulation::QAM64:
2060 parm_u_ofdm_constellation = QAM_64;
2063 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
2064 parm_u_ofdm_constellation = QAM_AUTO;
2067 switch (feparm.transmission_mode)
2069 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
2070 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2072 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
2073 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2076 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
2077 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2080 switch (feparm.guard_interval)
2082 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32:
2083 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2085 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16:
2086 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2088 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8:
2089 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2091 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4:
2092 parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2095 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto:
2096 parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2099 switch (feparm.hierarchy)
2101 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone:
2102 parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2104 case eDVBFrontendParametersTerrestrial::Hierarchy::H1:
2105 parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2107 case eDVBFrontendParametersTerrestrial::Hierarchy::H2:
2108 parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2110 case eDVBFrontendParametersTerrestrial::Hierarchy::H4:
2111 parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2114 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto:
2115 parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2118 switch (feparm.inversion)
2120 case eDVBFrontendParametersTerrestrial::Inversion::On:
2121 parm_inversion = INVERSION_ON;
2123 case eDVBFrontendParametersTerrestrial::Inversion::Off:
2124 parm_inversion = INVERSION_OFF;
2127 case eDVBFrontendParametersTerrestrial::Inversion::Unknown:
2128 parm_inversion = INVERSION_AUTO;
2134 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2136 unsigned int timeout = 5000;
2137 eDebugNoSimulate("(%d)tune", m_dvbid);
2143 if (!m_sn && !m_simulate)
2145 eDebug("no frontend device opened... do not try to tune !!!");
2159 m_sec_sequence.clear();
2161 where.calcLockTimeout(timeout);
2167 eDVBFrontendParametersSatellite feparm;
2168 if (where.getDVBS(feparm))
2170 eDebug("no dvbs data!");
2175 m_sec->setRotorMoving(false);
2176 res=prepare_sat(feparm, timeout);
2184 eDVBFrontendParametersCable feparm;
2185 if (where.getDVBC(feparm))
2190 res=prepare_cable(feparm);
2194 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2195 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2200 eDVBFrontendParametersTerrestrial feparm;
2201 if (where.getDVBT(feparm))
2203 eDebug("no -T data");
2207 res=prepare_terrestrial(feparm);
2211 std::string enable_5V;
2212 char configStr[255];
2213 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2214 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2215 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2216 if (enable_5V == "True")
2217 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2219 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2220 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2226 m_sec_sequence.current() = m_sec_sequence.begin();
2230 m_tuneTimer->start(0,true);
2231 if (m_state != stateTuning)
2234 m_state = stateTuning;
2235 m_stateChanged(this);
2244 m_tuneTimer->stop();
2248 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2250 connection = new eConnection(this, m_stateChanged.connect(stateChange));
2254 RESULT eDVBFrontend::setVoltage(int voltage)
2256 if (m_type == feCable)
2258 #if HAVE_DVB_API_VERSION < 3
2261 bool increased=false;
2262 fe_sec_voltage_t vlt;
2264 m_data[CUR_VOLTAGE]=voltage;
2268 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2269 vlt = SEC_VOLTAGE_OFF;
2272 #if HAVE_DVB_API_VERSION < 3
2273 vlt = SEC_VOLTAGE_13_5;
2279 vlt = SEC_VOLTAGE_13;
2282 #if HAVE_DVB_API_VERSION < 3
2283 vlt = SEC_VOLTAGE_18_5;
2289 vlt = SEC_VOLTAGE_18;
2296 #if HAVE_DVB_API_VERSION < 3
2297 return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2299 if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2300 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2301 return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2305 RESULT eDVBFrontend::getState(int &state)
2311 RESULT eDVBFrontend::setTone(int t)
2313 if (m_type != feSatellite)
2315 #if HAVE_DVB_API_VERSION < 3
2318 fe_sec_tone_mode_t tone;
2327 tone = SEC_TONE_OFF;
2334 #if HAVE_DVB_API_VERSION < 3
2335 return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2337 return ::ioctl(m_fd, FE_SET_TONE, tone);
2341 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2342 #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2345 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2349 #if HAVE_DVB_API_VERSION < 3
2350 struct secCommand cmd;
2351 cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2352 cmd.u.diseqc.cmdtype = diseqc.data[0];
2353 cmd.u.diseqc.addr = diseqc.data[1];
2354 cmd.u.diseqc.cmd = diseqc.data[2];
2355 cmd.u.diseqc.numParams = diseqc.len-3;
2356 memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2357 if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2359 struct dvb_diseqc_master_cmd cmd;
2360 memcpy(cmd.msg, diseqc.data, diseqc.len);
2361 cmd.msg_len = diseqc.len;
2362 if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2368 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2369 #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2371 RESULT eDVBFrontend::sendToneburst(int burst)
2375 #if HAVE_DVB_API_VERSION < 3
2376 secMiniCmd cmd = SEC_MINI_NONE;
2378 fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2380 if ( burst == eDVBSatelliteDiseqcParameters::A )
2382 else if ( burst == eDVBSatelliteDiseqcParameters::B )
2384 #if HAVE_DVB_API_VERSION < 3
2385 if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2388 if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2394 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2400 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2402 m_sec_sequence = list;
2406 RESULT eDVBFrontend::getData(int num, long &data)
2408 if ( num < NUM_DATA_ENTRIES )
2416 RESULT eDVBFrontend::setData(int num, long val)
2418 if ( num < NUM_DATA_ENTRIES )
2426 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2429 if (feparm->getSystem(type) || type != m_type || !m_enabled)
2431 if (m_type == eDVBFrontend::feSatellite)
2434 eDVBFrontendParametersSatellite sat_parm;
2435 int ret = feparm->getDVBS(sat_parm);
2437 if (sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S2 && !m_can_handle_dvbs2)
2439 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2440 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System::DVB_S && m_can_handle_dvbs2)
2444 else if (m_type == eDVBFrontend::feCable)
2445 return 2; // more prio for cable frontends
2446 else if (m_type == eDVBFrontend::feTerrestrial)
2451 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2453 ePyObject Id, Descr, Enabled, IsDVBS2;
2454 if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4)
2456 Id = PyTuple_GET_ITEM(obj, 0);
2457 Descr = PyTuple_GET_ITEM(obj, 1);
2458 Enabled = PyTuple_GET_ITEM(obj, 2);
2459 IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2460 if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2))
2462 strcpy(m_description, PyString_AS_STRING(Descr));
2463 m_slotid = PyInt_AsLong(Id);
2464 m_enabled = Enabled == Py_True;
2465 // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2466 m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2467 !!strstr(m_description, "Alps BSBE2") ||
2468 !!strstr(m_description, "Alps -S") ||
2469 !!strstr(m_description, "BCM4501");
2470 m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2471 eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2472 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2475 PyErr_SetString(PyExc_StandardError,
2476 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");