Merge branch 'master' of git.opendreambox.org:/git/enigma2
[vuplus_dvbapp] / lib / dvb / frontend.cpp
1 #include <lib/dvb/dvb.h>
2 #include <lib/dvb/frontendparms.h>
3 #include <lib/base/eerror.h>
4 #include <lib/base/nconfig.h> // access to python config
5 #include <errno.h>
6 #include <unistd.h>
7 #include <fcntl.h>
8 #include <sys/ioctl.h>
9
10 #ifndef I2C_SLAVE_FORCE
11 #define I2C_SLAVE_FORCE 0x0706
12 #endif
13
14 #if HAVE_DVB_API_VERSION < 3
15 #include <ost/frontend.h>
16 #include <ost/sec.h>
17 #define QAM_AUTO                                (Modulation)6
18 #define TRANSMISSION_MODE_AUTO  (TransmitMode)2
19 #define BANDWIDTH_AUTO                  (BandWidth)3
20 #define GUARD_INTERVAL_AUTO             (GuardInterval)4
21 #define HIERARCHY_AUTO                  (Hierarchy)4
22 #define parm_frequency parm.Frequency
23 #define parm_inversion parm.Inversion
24 #define parm_u_qpsk_symbol_rate parm.u.qpsk.SymbolRate
25 #define parm_u_qpsk_fec_inner parm.u.qpsk.FEC_inner
26 #define parm_u_qam_symbol_rate parm.u.qam.SymbolRate
27 #define parm_u_qam_fec_inner parm.u.qam.FEC_inner
28 #define parm_u_qam_modulation parm.u.qam.QAM
29 #define parm_u_ofdm_bandwidth parm.u.ofdm.bandWidth
30 #define parm_u_ofdm_code_rate_LP parm.u.ofdm.LP_CodeRate
31 #define parm_u_ofdm_code_rate_HP parm.u.ofdm.HP_CodeRate
32 #define parm_u_ofdm_constellation parm.u.ofdm.Constellation
33 #define parm_u_ofdm_transmission_mode parm.u.ofdm.TransmissionMode
34 #define parm_u_ofdm_guard_interval parm.u.ofdm.guardInterval
35 #define parm_u_ofdm_hierarchy_information parm.u.ofdm.HierarchyInformation
36 #else
37 #include <linux/dvb/frontend.h>
38 #define parm_frequency parm.frequency
39 #define parm_inversion parm.inversion
40 #define parm_u_qpsk_symbol_rate parm.u.qpsk.symbol_rate
41 #define parm_u_qpsk_fec_inner parm.u.qpsk.fec_inner
42 #define parm_u_qam_symbol_rate parm.u.qam.symbol_rate
43 #define parm_u_qam_fec_inner parm.u.qam.fec_inner
44 #define parm_u_qam_modulation parm.u.qam.modulation
45 #define parm_u_ofdm_bandwidth parm.u.ofdm.bandwidth
46 #define parm_u_ofdm_code_rate_LP parm.u.ofdm.code_rate_LP
47 #define parm_u_ofdm_code_rate_HP parm.u.ofdm.code_rate_HP
48 #define parm_u_ofdm_constellation parm.u.ofdm.constellation
49 #define parm_u_ofdm_transmission_mode parm.u.ofdm.transmission_mode
50 #define parm_u_ofdm_guard_interval parm.u.ofdm.guard_interval
51 #define parm_u_ofdm_hierarchy_information parm.u.ofdm.hierarchy_information
52 #ifdef FEC_9_10
53         #warning "FEC_9_10 already exist in dvb api ... it seems it is now ready for DVB-S2"
54 #else
55         #define FEC_S2_QPSK_1_2 (fe_code_rate_t)(FEC_AUTO+1)
56         #define FEC_S2_QPSK_2_3 (fe_code_rate_t)(FEC_S2_QPSK_1_2+1)
57         #define FEC_S2_QPSK_3_4 (fe_code_rate_t)(FEC_S2_QPSK_2_3+1)
58         #define FEC_S2_QPSK_5_6 (fe_code_rate_t)(FEC_S2_QPSK_3_4+1)
59         #define FEC_S2_QPSK_7_8 (fe_code_rate_t)(FEC_S2_QPSK_5_6+1)
60         #define FEC_S2_QPSK_8_9 (fe_code_rate_t)(FEC_S2_QPSK_7_8+1)
61         #define FEC_S2_QPSK_3_5 (fe_code_rate_t)(FEC_S2_QPSK_8_9+1)
62         #define FEC_S2_QPSK_4_5 (fe_code_rate_t)(FEC_S2_QPSK_3_5+1)
63         #define FEC_S2_QPSK_9_10 (fe_code_rate_t)(FEC_S2_QPSK_4_5+1)
64         #define FEC_S2_8PSK_1_2 (fe_code_rate_t)(FEC_S2_QPSK_9_10+1)
65         #define FEC_S2_8PSK_2_3 (fe_code_rate_t)(FEC_S2_8PSK_1_2+1)
66         #define FEC_S2_8PSK_3_4 (fe_code_rate_t)(FEC_S2_8PSK_2_3+1)
67         #define FEC_S2_8PSK_5_6 (fe_code_rate_t)(FEC_S2_8PSK_3_4+1)
68         #define FEC_S2_8PSK_7_8 (fe_code_rate_t)(FEC_S2_8PSK_5_6+1)
69         #define FEC_S2_8PSK_8_9 (fe_code_rate_t)(FEC_S2_8PSK_7_8+1)
70         #define FEC_S2_8PSK_3_5 (fe_code_rate_t)(FEC_S2_8PSK_8_9+1)
71         #define FEC_S2_8PSK_4_5 (fe_code_rate_t)(FEC_S2_8PSK_3_5+1)
72         #define FEC_S2_8PSK_9_10 (fe_code_rate_t)(FEC_S2_8PSK_4_5+1)
73 #endif
74 #endif
75
76 #include <dvbsi++/satellite_delivery_system_descriptor.h>
77 #include <dvbsi++/cable_delivery_system_descriptor.h>
78 #include <dvbsi++/terrestrial_delivery_system_descriptor.h>
79
80 #define eDebugNoSimulate(x...) \
81         do { \
82                 if (!m_simulate) \
83                         eDebug(x); \
84         } while(0)
85 #if 0
86                 else \
87                 { \
88                         eDebugNoNewLine("SIMULATE:"); \
89                         eDebug(x); \
90                 }
91 #endif
92
93 #define eDebugNoSimulateNoNewLine(x...) \
94         do { \
95                 if (!m_simulate) \
96                         eDebugNoNewLine(x); \
97         } while(0)
98 #if 0
99                 else \
100                 { \
101                         eDebugNoNewLine("SIMULATE:"); \
102                         eDebugNoNewLine(x); \
103                 }
104 #endif
105
106 void eDVBDiseqcCommand::setCommandString(const char *str)
107 {
108         if (!str)
109                 return;
110         len=0;
111         int slen = strlen(str);
112         if (slen % 2)
113         {
114                 eDebug("invalid diseqc command string length (not 2 byte aligned)");
115                 return;
116         }
117         if (slen > MAX_DISEQC_LENGTH*2)
118         {
119                 eDebug("invalid diseqc command string length (string is to long)");
120                 return;
121         }
122         unsigned char val=0;
123         for (int i=0; i < slen; ++i)
124         {
125                 unsigned char c = str[i];
126                 switch(c)
127                 {
128                         case '0' ... '9': c-=48; break;
129                         case 'a' ... 'f': c-=87; break;
130                         case 'A' ... 'F': c-=55; break;
131                         default:
132                                 eDebug("invalid character in hex string..ignore complete diseqc command !");
133                                 return;
134                 }
135                 if ( i % 2 )
136                 {
137                         val |= c;
138                         data[i/2] = val;
139                 }
140                 else
141                         val = c << 4;
142         }
143         len = slen/2;
144 }
145
146 void eDVBFrontendParametersSatellite::set(const SatelliteDeliverySystemDescriptor &descriptor)
147 {
148         frequency    = descriptor.getFrequency() * 10;
149         symbol_rate  = descriptor.getSymbolRate() * 100;
150         polarisation = descriptor.getPolarization();
151         fec = descriptor.getFecInner();
152         if ( fec != eDVBFrontendParametersSatellite::FEC_None && fec > eDVBFrontendParametersSatellite::FEC_9_10 )
153                 fec = eDVBFrontendParametersSatellite::FEC_Auto;
154         inversion = eDVBFrontendParametersSatellite::Inversion_Unknown;
155         pilot = eDVBFrontendParametersSatellite::Pilot_Unknown;
156         orbital_position  = ((descriptor.getOrbitalPosition() >> 12) & 0xF) * 1000;
157         orbital_position += ((descriptor.getOrbitalPosition() >> 8) & 0xF) * 100;
158         orbital_position += ((descriptor.getOrbitalPosition() >> 4) & 0xF) * 10;
159         orbital_position += ((descriptor.getOrbitalPosition()) & 0xF);
160         if (orbital_position && (!descriptor.getWestEastFlag()))
161                 orbital_position = 3600 - orbital_position;
162         system = descriptor.getModulationSystem();
163         modulation = descriptor.getModulation();
164         if (system == eDVBFrontendParametersSatellite::System_DVB_S && modulation == eDVBFrontendParametersSatellite::Modulation_8PSK)
165         {
166                 eDebug("satellite_delivery_descriptor non valid modulation type.. force QPSK");
167                 modulation=eDVBFrontendParametersSatellite::Modulation_QPSK;
168         }
169         rolloff = descriptor.getRollOff();
170         if (system == eDVBFrontendParametersSatellite::System_DVB_S2)
171         {
172                 eDebug("SAT DVB-S2 freq %d, %s, pos %d, sr %d, fec %d, modulation %d, rolloff %d",
173                         frequency,
174                         polarisation ? "hor" : "vert",
175                         orbital_position,
176                         symbol_rate, fec,
177                         modulation,
178                         rolloff);
179         }
180         else
181         {
182                 eDebug("SAT DVB-S freq %d, %s, pos %d, sr %d, fec %d",
183                         frequency,
184                         polarisation ? "hor" : "vert",
185                         orbital_position,
186                         symbol_rate, fec);
187         }
188 }
189
190 void eDVBFrontendParametersCable::set(const CableDeliverySystemDescriptor &descriptor)
191 {
192         frequency = descriptor.getFrequency() / 10;
193         symbol_rate = descriptor.getSymbolRate() * 100;
194         fec_inner = descriptor.getFecInner();
195         if ( fec_inner != eDVBFrontendParametersCable::FEC_None && fec_inner > eDVBFrontendParametersCable::FEC_8_9 )
196                 fec_inner = eDVBFrontendParametersCable::FEC_Auto;
197         modulation = descriptor.getModulation();
198         if ( modulation > 0x5 )
199                 modulation = eDVBFrontendParametersCable::Modulation_Auto;
200         inversion = eDVBFrontendParametersCable::Inversion_Unknown;
201         eDebug("Cable freq %d, mod %d, sr %d, fec %d",
202                 frequency,
203                 modulation, symbol_rate, fec_inner);
204 }
205
206 void eDVBFrontendParametersTerrestrial::set(const TerrestrialDeliverySystemDescriptor &descriptor)
207 {
208         frequency = descriptor.getCentreFrequency() * 10;
209         bandwidth = descriptor.getBandwidth();
210         if ( bandwidth > 2 ) // 5Mhz forced to auto
211                 bandwidth = eDVBFrontendParametersTerrestrial::Bandwidth_Auto;
212         code_rate_HP = descriptor.getCodeRateHpStream();
213         if (code_rate_HP > 4)
214                 code_rate_HP = eDVBFrontendParametersTerrestrial::FEC_Auto;
215         code_rate_LP = descriptor.getCodeRateLpStream();
216         if (code_rate_LP > 4)
217                 code_rate_LP = eDVBFrontendParametersTerrestrial::FEC_Auto;
218         transmission_mode = descriptor.getTransmissionMode();
219         if (transmission_mode > 1) // TM4k forced to auto
220                 transmission_mode = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto;
221         guard_interval = descriptor.getGuardInterval();
222         if (guard_interval > 3)
223                 guard_interval = eDVBFrontendParametersTerrestrial::GuardInterval_Auto;
224         hierarchy = descriptor.getHierarchyInformation()&3;
225         modulation = descriptor.getConstellation();
226         if (modulation > 2)
227                 modulation = eDVBFrontendParametersTerrestrial::Modulation_Auto;
228         inversion = eDVBFrontendParametersTerrestrial::Inversion_Unknown;
229         eDebug("Terr freq %d, bw %d, cr_hp %d, cr_lp %d, tm_mode %d, guard %d, hierarchy %d, const %d",
230                 frequency, bandwidth, code_rate_HP, code_rate_LP, transmission_mode,
231                 guard_interval, hierarchy, modulation);
232 }
233
234 eDVBFrontendParameters::eDVBFrontendParameters()
235         :m_type(-1), m_flags(0)
236 {
237 }
238
239 DEFINE_REF(eDVBFrontendParameters);
240
241 RESULT eDVBFrontendParameters::getSystem(int &t) const
242 {
243         if (m_type == -1)
244                 return -1;
245         t = m_type;
246         return 0;
247 }
248
249 RESULT eDVBFrontendParameters::getDVBS(eDVBFrontendParametersSatellite &p) const
250 {
251         if (m_type != iDVBFrontend::feSatellite)
252                 return -1;
253         p = sat;
254         return 0;
255 }
256
257 RESULT eDVBFrontendParameters::getDVBC(eDVBFrontendParametersCable &p) const
258 {
259         if (m_type != iDVBFrontend::feCable)
260                 return -1;
261         p = cable;
262         return 0;
263 }
264
265 RESULT eDVBFrontendParameters::getDVBT(eDVBFrontendParametersTerrestrial &p) const
266 {
267         if (m_type != iDVBFrontend::feTerrestrial)
268                 return -1;
269         p = terrestrial;
270         return 0;
271 }
272
273 RESULT eDVBFrontendParameters::setDVBS(const eDVBFrontendParametersSatellite &p, bool no_rotor_command_on_tune)
274 {
275         sat = p;
276         sat.no_rotor_command_on_tune = no_rotor_command_on_tune;
277         m_type = iDVBFrontend::feSatellite;
278         return 0;
279 }
280
281 RESULT eDVBFrontendParameters::setDVBC(const eDVBFrontendParametersCable &p)
282 {
283         cable = p;
284         m_type = iDVBFrontend::feCable;
285         return 0;
286 }
287
288 RESULT eDVBFrontendParameters::setDVBT(const eDVBFrontendParametersTerrestrial &p)
289 {
290         terrestrial = p;
291         m_type = iDVBFrontend::feTerrestrial;
292         return 0;
293 }
294
295 RESULT eDVBFrontendParameters::calculateDifference(const iDVBFrontendParameters *parm, int &diff, bool exact) const
296 {
297         if (!parm)
298                 return -1;
299         int type;
300         if (parm->getSystem(type))
301                 return -1;
302         if (type != m_type)
303         {
304                 diff = 1<<30; // big difference
305                 return 0;
306         }
307
308         switch (type)
309         {
310         case iDVBFrontend::feSatellite:
311         {
312                 eDVBFrontendParametersSatellite osat;
313                 if (parm->getDVBS(osat))
314                         return -2;
315
316                 if (sat.orbital_position != osat.orbital_position)
317                         diff = 1<<29;
318                 else if (sat.polarisation != osat.polarisation)
319                         diff = 1<<28;
320                 else if (exact && sat.fec != osat.fec && sat.fec != eDVBFrontendParametersSatellite::FEC_Auto && osat.fec != eDVBFrontendParametersSatellite::FEC_Auto)
321                         diff = 1<<27;
322                 else if (exact && sat.modulation != osat.modulation && sat.modulation != eDVBFrontendParametersSatellite::Modulation_Auto && osat.modulation != eDVBFrontendParametersSatellite::Modulation_Auto)
323                         diff = 1<<27;
324                 else
325                 {
326                         diff = abs(sat.frequency - osat.frequency);
327                         diff += abs(sat.symbol_rate - osat.symbol_rate);
328                 }
329                 return 0;
330         }
331         case iDVBFrontend::feCable:
332                 eDVBFrontendParametersCable ocable;
333                 if (parm->getDVBC(ocable))
334                         return -2;
335
336                 if (exact && cable.modulation != ocable.modulation
337                         && cable.modulation != eDVBFrontendParametersCable::Modulation_Auto
338                         && ocable.modulation != eDVBFrontendParametersCable::Modulation_Auto)
339                         diff = 1 << 29;
340                 else if (exact && cable.fec_inner != ocable.fec_inner && cable.fec_inner != eDVBFrontendParametersCable::FEC_Auto && ocable.fec_inner != eDVBFrontendParametersCable::FEC_Auto)
341                         diff = 1 << 27;
342                 else
343                 {
344                         diff = abs(cable.frequency - ocable.frequency);
345                         diff += abs(cable.symbol_rate - ocable.symbol_rate);
346                 }
347                 return 0;
348         case iDVBFrontend::feTerrestrial:
349                 eDVBFrontendParametersTerrestrial oterrestrial;
350                 if (parm->getDVBT(oterrestrial))
351                         return -2;
352
353                 if (exact && oterrestrial.bandwidth != terrestrial.bandwidth &&
354                         oterrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth_Auto &&
355                         terrestrial.bandwidth != eDVBFrontendParametersTerrestrial::Bandwidth_Auto)
356                         diff = 1 << 30;
357                 else if (exact && oterrestrial.modulation != terrestrial.modulation &&
358                         oterrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation_Auto &&
359                         terrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation_Auto)
360                         diff = 1 << 30;
361                 else if (exact && oterrestrial.transmission_mode != terrestrial.transmission_mode &&
362                         oterrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode_Auto &&
363                         terrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode_Auto)
364                         diff = 1 << 30;
365                 else if (exact && oterrestrial.guard_interval != terrestrial.guard_interval &&
366                         oterrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval_Auto &&
367                         terrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval_Auto)
368                         diff = 1 << 30;
369                 else if (exact && oterrestrial.hierarchy != terrestrial.hierarchy &&
370                         oterrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy_Auto &&
371                         terrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy_Auto)
372                         diff = 1 << 30;
373                 else if (exact && oterrestrial.code_rate_LP != terrestrial.code_rate_LP &&
374                         oterrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC_Auto &&
375                         terrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC_Auto)
376                         diff = 1 << 30;
377                 else if (exact && oterrestrial.code_rate_HP != terrestrial.code_rate_HP &&
378                         oterrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC_Auto &&
379                         terrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC_Auto)
380                         diff = 1 << 30;
381                 else
382                         diff = abs(terrestrial.frequency - oterrestrial.frequency) / 1000;
383                 return 0;
384         default:
385                 return -1;
386         }
387         return 0;
388 }
389
390 RESULT eDVBFrontendParameters::getHash(unsigned long &hash) const
391 {
392         switch (m_type)
393         {
394         case iDVBFrontend::feSatellite:
395         {
396                 hash = (sat.orbital_position << 16);
397                 hash |= ((sat.frequency/1000)&0xFFFF)|((sat.polarisation&1) << 15);
398                 return 0;
399         }
400         case iDVBFrontend::feCable:
401                 hash = 0xFFFF0000;
402                 hash |= (cable.frequency/1000)&0xFFFF;
403                 return 0;
404         case iDVBFrontend::feTerrestrial:
405                 hash = 0xEEEE0000;
406                 hash |= (terrestrial.frequency/1000000)&0xFFFF;
407                 return 0;
408         default:
409                 return -1;
410         }
411 }
412
413 RESULT eDVBFrontendParameters::calcLockTimeout(unsigned int &timeout) const
414 {
415         switch (m_type)
416         {
417         case iDVBFrontend::feSatellite:
418         {
419                         /* high symbol rate transponders tune faster, due to 
420                                 requiring less zigzag and giving more symbols faster. 
421
422                                 5s are definitely not enough on really low SR when
423                                 zigzag has to find the exact frequency first.
424                         */
425                 if (sat.symbol_rate > 20000000)
426                         timeout = 5000;
427                 else if (sat.symbol_rate > 10000000)
428                         timeout = 10000;
429                 else
430                         timeout = 20000;
431                 return 0;
432         }
433         case iDVBFrontend::feCable:
434                 timeout = 5000;
435                 return 0;
436         case iDVBFrontend::feTerrestrial:
437                 timeout = 5000;
438                 return 0;
439         default:
440                 return -1;
441         }
442 }
443
444 DEFINE_REF(eDVBFrontend);
445
446 int eDVBFrontend::PriorityOrder=0;
447
448 eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok, bool simulate)
449         :m_simulate(simulate), m_enabled(false), m_type(-1), m_dvbid(fe), m_slotid(fe)
450         ,m_fd(-1), m_need_rotor_workaround(false), m_can_handle_dvbs2(false)
451         ,m_state(stateClosed), m_timeout(0), m_tuneTimer(0)
452 #if HAVE_DVB_API_VERSION < 3
453         ,m_secfd(-1)
454 #endif
455 {
456 #if HAVE_DVB_API_VERSION < 3
457         sprintf(m_filename, "/dev/dvb/card%d/frontend%d", adap, fe);
458         sprintf(m_sec_filename, "/dev/dvb/card%d/sec%d", adap, fe);
459 #else
460         sprintf(m_filename, "/dev/dvb/adapter%d/frontend%d", adap, fe);
461 #endif
462
463         m_timeout = eTimer::create(eApp);
464         CONNECT(m_timeout->timeout, eDVBFrontend::timeout);
465
466         m_tuneTimer = eTimer::create(eApp);
467         CONNECT(m_tuneTimer->timeout, eDVBFrontend::tuneLoop);
468
469         for (int i=0; i<eDVBFrontend::NUM_DATA_ENTRIES; ++i)
470                 m_data[i] = -1;
471
472         m_idleInputpower[0]=m_idleInputpower[1]=0;
473
474         ok = !openFrontend();
475         closeFrontend();
476 }
477
478 int eDVBFrontend::openFrontend()
479 {
480         if (m_state != stateClosed)
481                 return -1;  // already opened
482
483         m_state=stateIdle;
484         m_tuning=0;
485
486 #if HAVE_DVB_API_VERSION < 3
487         FrontendInfo fe_info;
488 #else
489         dvb_frontend_info fe_info;
490 #endif
491         eDebugNoSimulate("opening frontend %d", m_dvbid);
492         if (m_fd < 0)
493         {
494                 if (!m_simulate || m_type == -1)
495                 {
496                         m_fd = ::open(m_filename, O_RDWR|O_NONBLOCK);
497                         if (m_fd < 0)
498                         {
499                                 eWarning("failed! (%s) %m", m_filename);
500                                 return -1;
501                         }
502                 }
503         }
504         else
505                 eWarning("frontend %d already opened", m_dvbid);
506         if (m_type == -1)
507         {
508                 if (::ioctl(m_fd, FE_GET_INFO, &fe_info) < 0)
509                 {
510                         eWarning("ioctl FE_GET_INFO failed");
511                         ::close(m_fd);
512                         m_fd = -1;
513                         return -1;
514                 }
515
516                 switch (fe_info.type)
517                 {
518                 case FE_QPSK:
519                         m_type = iDVBFrontend::feSatellite;
520                         break;
521                 case FE_QAM:
522                         m_type = iDVBFrontend::feCable;
523                         break;
524                 case FE_OFDM:
525                         m_type = iDVBFrontend::feTerrestrial;
526                         break;
527                 default:
528                         eWarning("unknown frontend type.");
529                         ::close(m_fd);
530                         m_fd = -1;
531                         return -1;
532                 }
533                 eDebugNoSimulate("detected %s frontend", "satellite\0cable\0    terrestrial"+fe_info.type*10);
534         }
535
536 #if HAVE_DVB_API_VERSION < 3
537         if (m_type == iDVBFrontend::feSatellite)
538         {
539                         if (m_secfd < 0)
540                         {
541                                 if (!m_simulate)
542                                 {
543                                         m_secfd = ::open(m_sec_filename, O_RDWR);
544                                         if (m_secfd < 0)
545                                         {
546                                                 eWarning("failed! (%s) %m", m_sec_filename);
547                                                 ::close(m_fd);
548                                                 m_fd=-1;
549                                                 return -1;
550                                         }
551                                 }
552                         }
553                         else
554                                 eWarning("sec %d already opened", m_dvbid);
555         }
556 #endif
557
558         setTone(iDVBFrontend::toneOff);
559         setVoltage(iDVBFrontend::voltageOff);
560
561         if (!m_simulate)
562         {
563                 m_sn = eSocketNotifier::create(eApp, m_fd, eSocketNotifier::Read, false);
564                 CONNECT(m_sn->activated, eDVBFrontend::feEvent);
565         }
566
567         return 0;
568 }
569
570 int eDVBFrontend::closeFrontend(bool force)
571 {
572         if (!force && m_data[CUR_VOLTAGE] != -1 && m_data[CUR_VOLTAGE] != iDVBFrontend::voltageOff)
573         {
574                 long tmp = m_data[LINKED_NEXT_PTR];
575                 while (tmp != -1)
576                 {
577                         eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
578                         if (linked_fe->m_inuse)
579                         {
580                                 eDebugNoSimulate("dont close frontend %d until the linked frontend %d in slot %d is still in use",
581                                         m_dvbid, linked_fe->m_frontend->getDVBID(), linked_fe->m_frontend->getSlotID());
582                                 return -1;
583                         }
584                         linked_fe->m_frontend->getData(LINKED_NEXT_PTR, tmp);
585                 }
586         }
587
588         if (m_fd >= 0)
589         {
590                 eDebugNoSimulate("close frontend %d", m_dvbid);
591                 if (m_data[SATCR] != -1)
592                 {
593                         turnOffSatCR(m_data[SATCR]);
594                 }
595                 setTone(iDVBFrontend::toneOff);
596                 setVoltage(iDVBFrontend::voltageOff);
597                 m_tuneTimer->stop();
598                 if (m_sec && !m_simulate)
599                         m_sec->setRotorMoving(false);
600                 if (!::close(m_fd))
601                         m_fd=-1;
602                 else
603                         eWarning("couldnt close frontend %d", m_dvbid);
604         }
605         else if (m_simulate)
606         {
607                 setTone(iDVBFrontend::toneOff);
608                 setVoltage(iDVBFrontend::voltageOff);
609         }
610 #if HAVE_DVB_API_VERSION < 3
611         if (m_secfd >= 0)
612         {
613                 if (!::close(m_secfd))
614                         m_secfd=-1;
615                 else
616                         eWarning("couldnt close sec %d", m_dvbid);
617         }
618 #endif
619         m_sn=0;
620         m_state = stateClosed;
621
622         return 0;
623 }
624
625 eDVBFrontend::~eDVBFrontend()
626 {
627         m_data[LINKED_PREV_PTR] = m_data[LINKED_NEXT_PTR] = -1;
628         closeFrontend();
629 }
630
631 void eDVBFrontend::feEvent(int w)
632 {
633         eDVBFrontend *sec_fe = this;
634         long tmp = m_data[LINKED_PREV_PTR];
635         while (tmp != -1)
636         {
637                 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
638                 sec_fe = linked_fe->m_frontend;
639                 sec_fe->getData(LINKED_NEXT_PTR, tmp);
640         }
641         while (1)
642         {
643 #if HAVE_DVB_API_VERSION < 3
644                 FrontendEvent event;
645 #else
646                 dvb_frontend_event event;
647 #endif
648                 int res;
649                 int state;
650                 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
651
652                 if (res && (errno == EAGAIN))
653                         break;
654
655                 if (w < 0)
656                         continue;
657
658 #if HAVE_DVB_API_VERSION < 3
659                 if (event.type == FE_COMPLETION_EV)
660 #else
661                 eDebug("(%d)fe event: status %x, inversion %s", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off");
662                 if (event.status & FE_HAS_LOCK)
663 #endif
664                 {
665                         state = stateLock;
666                 } else
667                 {
668                         if (m_tuning)
669                                 state = stateTuning;
670                         else
671                         {
672                                 eDebug("stateLostLock");
673                                 state = stateLostLock;
674                                 sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
675                         }
676                 }
677                 if (m_state != state)
678                 {
679                         m_state = state;
680                         m_stateChanged(this);
681                 }
682         }
683 }
684
685 void eDVBFrontend::timeout()
686 {
687         m_tuning = 0;
688         if (m_state == stateTuning)
689         {
690                 m_state = stateFailed;
691                 m_stateChanged(this);
692         }
693 }
694
695 #define INRANGE(X,Y,Z) (((X<=Y) && (Y<=Z))||((Z<=Y) && (Y<=X)) ? 1 : 0)
696
697 /* unsigned 32 bit division */
698 static inline uint32_t fe_udiv(uint32_t a, uint32_t b)
699 {
700         return (a + b / 2) / b;
701 }
702
703 int eDVBFrontend::readFrontendData(int type)
704 {
705         switch(type)
706         {
707                 case bitErrorRate:
708                 {
709                         uint32_t ber=0;
710                         if (!m_simulate)
711                         {
712                                 if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
713                                         eDebug("FE_READ_BER failed (%m)");
714                         }
715                         return ber;
716                 }
717                 case signalQuality:
718                 case signalQualitydB: /* this will move into the driver */
719                 {
720                         int sat_max = 1600; // for stv0288 / bsbe2
721                         int ret = 0x12345678;
722                         uint16_t snr=0;
723                         if (m_simulate)
724                                 return 0;
725                         if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
726                                 eDebug("FE_READ_SNR failed (%m)");
727                         else if (!strcmp(m_description, "BCM4501 (internal)"))
728                         {
729                                 float SDS_SNRE = snr << 16;
730                                 float snr_in_db;
731
732                                 if (parm_u_qpsk_fec_inner <= FEC_AUTO) // DVB-S1 / QPSK
733                                 {
734                                         static float SNR_COEFF[6] = {
735                                                 100.0 / 4194304.0,
736                                                 -7136.0 / 4194304.0,
737                                                 197418.0 / 4194304.0,
738                                                 -2602183.0 / 4194304.0,
739                                                 20377212.0 / 4194304.0,
740                                                 -37791203.0 / 4194304.0,
741                                         };
742                                         float fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0)),
743                                           fval2 = pow(10.0, fval1)-1;
744                                         fval1 = 10.0 * log10(fval2);
745
746                                         if (fval1 < 10.0)
747                                         {
748                                                 fval2 = SNR_COEFF[0];
749                                                 for (int i=1; i<6; ++i)
750                                                 {
751                                                         fval2 *= fval1;
752                                                         fval2 += SNR_COEFF[i];
753                                                 }
754                                                 fval1 = fval2;
755                                         }
756                                         snr_in_db = fval1;
757                                 }
758 #if HAVE_DVB_API_VERSION >= 3
759                                 else
760                                 {
761                                         float fval1 = SDS_SNRE / 268435456.0,
762                                                   fval2, fval3, fval4;
763
764                                         if (parm_u_qpsk_fec_inner <= FEC_S2_QPSK_9_10) // DVB-S2 QPSK
765                                         {
766                                                 fval2 = 6.76;
767                                                 fval3 = 4.35;
768                                         }
769                                         else // 8PSK
770                                         {
771                                                 fval1 *= 0.5;
772                                                 fval2 = 8.06;
773                                                 fval3 = 6.18;
774                                         }
775                                         fval4 = -10.0 * log10(fval1);
776                                         fval1 = fval4;
777                                         for (int i=0; i < 5; ++i)
778                                                 fval1 = fval4 - fval2 * log10(1.0+pow(10.0, (fval3-fval1)/fval2));
779                                         snr_in_db = fval1;
780                                 }
781 #endif
782                                 sat_max = 1750;
783                                 ret = (int)(snr_in_db * 100);
784                         }
785                         else if (strstr(m_description, "Alps BSBE1 C01A") ||
786                                 !strcmp(m_description, "Alps -S(STV0288)"))
787                         {
788                                 if (snr == 0)
789                                         ret = 0;
790                                 else if (snr == 0xFFFF) // i think this should not happen
791                                         ret = 100*100;
792                                 else
793                                 {
794                                         enum { REALVAL, REGVAL };
795                                         const long CN_lookup[31][2] = {
796                                                 {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
797                                                 {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
798                                                 {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
799                                                 {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
800                                                 {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
801                                                 {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
802                                                 {300,890}
803                                         };
804                                         int add=strchr(m_description, '.') ? 0xA250 : 0xA100;
805                                         long regval = 0xFFFF - ((snr / 3) + add), // revert some dvb api calulations to get the real register value
806                                                 Imin=0,
807                                                 Imax=30,
808                                                 i;
809                                         if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
810                                         {
811                                                 while((Imax-Imin)>1)
812                                                 {
813                                                         i=(Imax+Imin)/2;
814                                                         if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[i][REGVAL]))
815                                                                 Imax = i;
816                                                         else
817                                                                 Imin = i;
818                                                 }
819                                                 ret = (((regval - CN_lookup[Imin][REGVAL])
820                                                                 * (CN_lookup[Imax][REALVAL] - CN_lookup[Imin][REALVAL])
821                                                                 / (CN_lookup[Imax][REGVAL] - CN_lookup[Imin][REGVAL]))
822                                                                 + CN_lookup[Imin][REALVAL]) * 10;
823                                         }
824                                         else
825                                                 ret = 100;
826                                 }
827                         }
828                         else if (!strcmp(m_description, "Alps BSBE1 702A") ||  // some frontends with STV0299
829                                 !strcmp(m_description, "Alps -S") ||
830                                 !strcmp(m_description, "Philips -S") ||
831                                 !strcmp(m_description, "LG -S") )
832                         {
833                                 sat_max = 1500;
834                                 ret = (int)((snr-39075)/17.647);
835                         } else if (!strcmp(m_description, "Alps BSBE2"))
836                         {
837                                 ret = (int)((snr >> 7) * 10);
838                         } else if (!strcmp(m_description, "Philips CU1216Mk3"))
839                         {
840                                 int mse = (~snr) & 0xFF;
841                                 switch (parm_u_qam_modulation) {
842                                 case QAM_16: ret = fe_udiv(1950000, (32 * mse) + 138) + 1000; break;
843                                 case QAM_32: ret = fe_udiv(2150000, (40 * mse) + 500) + 1350; break;
844                                 case QAM_64: ret = fe_udiv(2100000, (40 * mse) + 500) + 1250; break;
845                                 case QAM_128: ret = fe_udiv(1850000, (38 * mse) + 400) + 1380; break;
846                                 case QAM_256: ret = fe_udiv(1800000, (100 * mse) + 40) + 2030; break;
847                                 default: break;
848                                 }
849                         } else if (!strcmp(m_description, "Philips TU1216"))
850                         {
851                                 snr = 0xFF - (snr & 0xFF);
852                                 if (snr != 0)
853                                         ret = 10 * (int)(-100 * (log10(snr) - log10(255)));
854                         }
855                         else if (!strcmp(m_description, "BCM4506"))
856                                 ret = (snr * 100) >> 8;
857
858                         if (type == signalQuality)
859                         {
860                                 if (ret == 0x12345678) // no snr db calculation avail.. return untouched snr value..
861                                         return snr;
862                                 switch(m_type)
863                                 {
864                                         case feSatellite:
865                                                 return ret >= sat_max ? 65536 : ret * 65536 / sat_max;
866                                         case feCable: // we assume a max of 42db here
867                                                 return ret >= 4200 ? 65536 : ret * 65536 / 4200;
868                                         case feTerrestrial: // we assume a max of 24db here
869                                                 return ret >= 2400 ? 65536 : ret * 65536 / 2400;
870                                 }
871                         }
872 /* else
873                                 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
874                         return ret;
875                 }
876                 case signalPower:
877                 {
878                         uint16_t strength=0;
879                         if (!m_simulate)
880                         {
881                                 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
882                                         eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
883                         }
884                         return strength;
885                 }
886                 case locked:
887                 {
888 #if HAVE_DVB_API_VERSION < 3
889                         FrontendStatus status=0;
890 #else
891                         fe_status_t status;
892 #endif
893                         if (!m_simulate)
894                         {
895                                 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
896                                         eDebug("FE_READ_STATUS failed (%m)");
897                                 return !!(status&FE_HAS_LOCK);
898                         }
899                         return 1;
900                 }
901                 case synced:
902                 {
903 #if HAVE_DVB_API_VERSION < 3
904                         FrontendStatus status=0;
905 #else
906                         fe_status_t status;
907 #endif
908                         if (!m_simulate)
909                         {
910                                 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
911                                         eDebug("FE_READ_STATUS failed (%m)");
912                                 return !!(status&FE_HAS_SYNC);
913                         }
914                         return 1;
915                 }
916                 case frontendNumber:
917                         return m_slotid;
918         }
919         return 0;
920 }
921
922 void PutToDict(ePyObject &dict, const char*key, long value)
923 {
924         ePyObject item = PyInt_FromLong(value);
925         if (item)
926         {
927                 if (PyDict_SetItemString(dict, key, item))
928                         eDebug("put %s to dict failed", key);
929                 Py_DECREF(item);
930         }
931         else
932                 eDebug("could not create PyObject for %s", key);
933 }
934
935 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
936 {
937         if (item)
938         {
939                 if (PyDict_SetItemString(dict, key, item))
940                         eDebug("put %s to dict failed", key);
941                 Py_DECREF(item);
942         }
943         else
944                 eDebug("invalid PyObject for %s", key);
945 }
946
947 void PutToDict(ePyObject &dict, const char*key, const char *value)
948 {
949         ePyObject item = PyString_FromString(value);
950         if (item)
951         {
952                 if (PyDict_SetItemString(dict, key, item))
953                         eDebug("put %s to dict failed", key);
954                 Py_DECREF(item);
955         }
956         else
957                 eDebug("could not create PyObject for %s", key);
958 }
959
960 void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, long freq_offset, int orb_pos, int polarization)
961 {
962         long tmp=0;
963         int frequency = parm_frequency + freq_offset;
964         PutToDict(dict, "frequency", frequency);
965         PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
966         PutToDict(dict, "orbital_position", orb_pos);
967         PutToDict(dict, "polarization", polarization);
968
969         switch(parm_u_qpsk_fec_inner)
970         {
971         case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
972         case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
973         case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
974         case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
975         case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
976         case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
977         default:
978         case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
979 #if HAVE_DVB_API_VERSION >=3
980         case FEC_S2_8PSK_1_2: 
981         case FEC_S2_QPSK_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
982         case FEC_S2_8PSK_2_3:
983         case FEC_S2_QPSK_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
984         case FEC_S2_8PSK_3_4:
985         case FEC_S2_QPSK_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
986         case FEC_S2_8PSK_5_6:
987         case FEC_S2_QPSK_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
988         case FEC_S2_8PSK_7_8:
989         case FEC_S2_QPSK_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
990         case FEC_S2_8PSK_8_9:
991         case FEC_S2_QPSK_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
992         case FEC_S2_8PSK_3_5:
993         case FEC_S2_QPSK_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
994         case FEC_S2_8PSK_4_5:
995         case FEC_S2_QPSK_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
996         case FEC_S2_8PSK_9_10:
997         case FEC_S2_QPSK_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
998 #endif
999         }
1000         PutToDict(dict, "fec_inner", tmp);
1001 #if HAVE_DVB_API_VERSION >=3
1002         PutToDict(dict, "modulation",
1003                 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ?
1004                         eDVBFrontendParametersSatellite::Modulation_8PSK :
1005                         eDVBFrontendParametersSatellite::Modulation_QPSK );
1006         if (parm_u_qpsk_fec_inner > FEC_AUTO)
1007         {
1008                 switch(parm_inversion & 0xc)
1009                 {
1010                 default: // unknown rolloff
1011                 case 0: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1012                 case 4: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1013                 case 8: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1014                 }
1015                 PutToDict(dict, "rolloff", tmp);
1016                 switch(parm_inversion & 0x30)
1017                 {
1018                 case 0: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1019                 case 0x10: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1020                 case 0x20: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1021                 }
1022                 PutToDict(dict, "pilot", tmp);
1023                 tmp = eDVBFrontendParametersSatellite::System_DVB_S2;
1024         }
1025         else
1026                 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1027 #else
1028         PutToDict(dict, "modulation", eDVBFrontendParametersSatellite::Modulation_QPSK );
1029         tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1030 #endif
1031         PutToDict(dict, "system", tmp);
1032 }
1033
1034 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1035 {
1036         long tmp=0;
1037 #if HAVE_DVB_API_VERSION < 3
1038         PutToDict(dict, "frequency", parm_frequency);
1039 #else
1040         PutToDict(dict, "frequency", parm_frequency/1000);
1041 #endif
1042         PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1043         switch(parm_u_qam_fec_inner)
1044         {
1045         case FEC_NONE: tmp = eDVBFrontendParametersCable::FEC_None; break;
1046         case FEC_1_2: tmp = eDVBFrontendParametersCable::FEC_1_2; break;
1047         case FEC_2_3: tmp = eDVBFrontendParametersCable::FEC_2_3; break;
1048         case FEC_3_4: tmp = eDVBFrontendParametersCable::FEC_3_4; break;
1049         case FEC_5_6: tmp = eDVBFrontendParametersCable::FEC_5_6; break;
1050         case FEC_7_8: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1051 #if HAVE_DVB_API_VERSION >= 3
1052         case FEC_8_9: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1053 #endif
1054         default:
1055         case FEC_AUTO: tmp = eDVBFrontendParametersCable::FEC_Auto; break;
1056         }
1057         PutToDict(dict, "fec_inner", tmp);
1058         switch(parm_u_qam_modulation)
1059         {
1060         case QAM_16: tmp = eDVBFrontendParametersCable::Modulation_QAM16; break;
1061         case QAM_32: tmp = eDVBFrontendParametersCable::Modulation_QAM32; break;
1062         case QAM_64: tmp = eDVBFrontendParametersCable::Modulation_QAM64; break;
1063         case QAM_128: tmp = eDVBFrontendParametersCable::Modulation_QAM128; break;
1064         case QAM_256: tmp = eDVBFrontendParametersCable::Modulation_QAM256; break;
1065         default:
1066         case QAM_AUTO:   tmp = eDVBFrontendParametersCable::Modulation_Auto; break;
1067         }
1068         PutToDict(dict, "modulation", tmp);
1069 }
1070
1071 void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1072 {
1073         long tmp=0;
1074         PutToDict(dict, "frequency", parm_frequency);
1075         switch (parm_u_ofdm_bandwidth)
1076         {
1077         case BANDWIDTH_8_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_8MHz; break;
1078         case BANDWIDTH_7_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_7MHz; break;
1079         case BANDWIDTH_6_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_6MHz; break;
1080         default:
1081         case BANDWIDTH_AUTO: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_Auto; break;
1082         }
1083         PutToDict(dict, "bandwidth", tmp);
1084         switch (parm_u_ofdm_code_rate_LP)
1085         {
1086         case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1087         case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1088         case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1089         case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1090         case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1091         default:
1092         case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1093         }
1094         PutToDict(dict, "code_rate_lp", tmp);
1095         switch (parm_u_ofdm_code_rate_HP)
1096         {
1097         case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1098         case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1099         case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1100         case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1101         case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1102         default:
1103         case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1104         }
1105         PutToDict(dict, "code_rate_hp", tmp);
1106         switch (parm_u_ofdm_constellation)
1107         {
1108         case QPSK: tmp = eDVBFrontendParametersTerrestrial::Modulation_QPSK; break;
1109         case QAM_16: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM16; break;
1110         case QAM_64: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM64; break;
1111         default:
1112         case QAM_AUTO: tmp = eDVBFrontendParametersTerrestrial::Modulation_Auto; break;
1113         }
1114         PutToDict(dict, "constellation", tmp);
1115         switch (parm_u_ofdm_transmission_mode)
1116         {
1117         case TRANSMISSION_MODE_2K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_2k; break;
1118         case TRANSMISSION_MODE_8K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_8k; break;
1119         default:
1120         case TRANSMISSION_MODE_AUTO: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto; break;
1121         }
1122         PutToDict(dict, "transmission_mode", tmp);
1123         switch (parm_u_ofdm_guard_interval)
1124         {
1125                 case GUARD_INTERVAL_1_32: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_32; break;
1126                 case GUARD_INTERVAL_1_16: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_16; break;
1127                 case GUARD_INTERVAL_1_8: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_8; break;
1128                 case GUARD_INTERVAL_1_4: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_4; break;
1129                 default:
1130                 case GUARD_INTERVAL_AUTO: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_Auto; break;
1131         }
1132         PutToDict(dict, "guard_interval", tmp);
1133         switch (parm_u_ofdm_hierarchy_information)
1134         {
1135                 case HIERARCHY_NONE: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_None; break;
1136                 case HIERARCHY_1: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_1; break;
1137                 case HIERARCHY_2: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_2; break;
1138                 case HIERARCHY_4: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_4; break;
1139                 default:
1140                 case HIERARCHY_AUTO: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_Auto; break;
1141         }
1142         PutToDict(dict, "hierarchy_information", tmp);
1143 }
1144
1145 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1146 {
1147         if (dest && PyDict_Check(dest))
1148         {
1149                 const char *tmp = "UNKNOWN";
1150                 switch(m_state)
1151                 {
1152                         case stateIdle:
1153                                 tmp="IDLE";
1154                                 break;
1155                         case stateTuning:
1156                                 tmp="TUNING";
1157                                 break;
1158                         case stateFailed:
1159                                 tmp="FAILED";
1160                                 break;
1161                         case stateLock:
1162                                 tmp="LOCKED";
1163                                 break;
1164                         case stateLostLock:
1165                                 tmp="LOSTLOCK";
1166                                 break;
1167                         default:
1168                                 break;
1169                 }
1170                 PutToDict(dest, "tuner_state", tmp);
1171                 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1172                 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1173                 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1174                 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1175                 int sigQualitydB = readFrontendData(signalQualitydB);
1176                 if (sigQualitydB == 0x12345678) // not support yet
1177                 {
1178                         ePyObject obj=Py_None;
1179                         Py_INCREF(obj);
1180                         PutToDict(dest, "tuner_signal_quality_db", obj);
1181                 }
1182                 else
1183                         PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1184                 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1185         }
1186 }
1187
1188 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1189 {
1190         if (dest && PyDict_Check(dest))
1191         {
1192                 switch(m_type)
1193                 {
1194                         case feSatellite:
1195                         case feCable:
1196                         case feTerrestrial:
1197                         {
1198                                 FRONTENDPARAMETERS front;
1199                                 if (m_fd == -1 && !original)
1200                                         original = true;
1201                                 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1202                                 {
1203                                         eDebug("FE_GET_FRONTEND failed (%m)");
1204                                         original = true;
1205                                 }
1206                                 {
1207                                         const FRONTENDPARAMETERS &parm = original || m_simulate ? this->parm : front;
1208                                         long tmp = eDVBFrontendParametersSatellite::Inversion_Unknown;
1209                                         switch(parm_inversion & 3)
1210                                         {
1211                                                 case INVERSION_ON:
1212                                                         tmp = eDVBFrontendParametersSatellite::Inversion_On;
1213                                                         break;
1214                                                 case INVERSION_OFF:
1215                                                         tmp = eDVBFrontendParametersSatellite::Inversion_Off;
1216                                                 default:
1217                                                         break;
1218                                         }
1219                                         PutToDict(dest, "inversion", tmp);
1220
1221                                         switch(m_type)
1222                                         {
1223                                                 case feSatellite:
1224                                                         fillDictWithSatelliteData(dest, original?parm:front, m_data[FREQ_OFFSET], m_cur_orbpos, m_cur_pol);
1225                                                         break;
1226                                                 case feCable:
1227                                                         fillDictWithCableData(dest, original?parm:front);
1228                                                         break;
1229                                                 case feTerrestrial:
1230                                                         fillDictWithTerrestrialData(dest, original?parm:front);
1231                                                         break;
1232                                         }
1233                                 }
1234                         }
1235                         default:
1236                                 break;
1237                 }
1238         }
1239 }
1240
1241 void eDVBFrontend::getFrontendData(ePyObject dest)
1242 {
1243         if (dest && PyDict_Check(dest))
1244         {
1245                 const char *tmp=0;
1246                 PutToDict(dest, "tuner_number", m_slotid);
1247                 switch(m_type)
1248                 {
1249                         case feSatellite:
1250                                 tmp = "DVB-S";
1251                                 break;
1252                         case feCable:
1253                                 tmp = "DVB-C";
1254                                 break;
1255                         case feTerrestrial:
1256                                 tmp = "DVB-T";
1257                                 break;
1258                         default:
1259                                 tmp = "UNKNOWN";
1260                                 break;
1261                 }
1262                 PutToDict(dest, "tuner_type", tmp);
1263         }
1264 }
1265
1266 #ifndef FP_IOCTL_GET_ID
1267 #define FP_IOCTL_GET_ID 0
1268 #endif
1269 int eDVBFrontend::readInputpower()
1270 {
1271         if (m_simulate)
1272                 return 0;
1273         int power=m_slotid;  // this is needed for read inputpower from the correct tuner !
1274         char proc_name[64];
1275         sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1276         FILE *f=fopen(proc_name, "r");
1277         if (f)
1278         {
1279                 if (fscanf(f, "%d", &power) != 1)
1280                         eDebug("read %s failed!! (%m)", proc_name);
1281                 else
1282                         eDebug("%s is %d\n", proc_name, power);
1283                 fclose(f);
1284         }
1285         else
1286         {
1287                 // open front prozessor
1288                 int fp=::open("/dev/dbox/fp0", O_RDWR);
1289                 if (fp < 0)
1290                 {
1291                         eDebug("couldn't open fp");
1292                         return -1;
1293                 }
1294                 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1295                 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1296                 {
1297                         eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1298                         return -1;
1299                 }
1300                 ::close(fp);
1301         }
1302
1303         return power;
1304 }
1305
1306 bool eDVBFrontend::setSecSequencePos(int steps)
1307 {
1308         eDebugNoSimulate("set sequence pos %d", steps);
1309         if (!steps)
1310                 return false;
1311         while( steps > 0 )
1312         {
1313                 if (m_sec_sequence.current() != m_sec_sequence.end())
1314                         ++m_sec_sequence.current();
1315                 --steps;
1316         }
1317         while( steps < 0 )
1318         {
1319                 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1320                         --m_sec_sequence.current();
1321                 ++steps;
1322         }
1323         return true;
1324 }
1325
1326 void eDVBFrontend::tuneLoop()  // called by m_tuneTimer
1327 {
1328         int delay=0;
1329         eDVBFrontend *sec_fe = this;
1330         eDVBRegisteredFrontend *regFE = 0;
1331         long tmp = m_data[LINKED_PREV_PTR];
1332         while ( tmp != -1 )
1333         {
1334                 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1335                 sec_fe = prev->m_frontend;
1336                 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1337                 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1338                         int state = sec_fe->m_state;
1339                         // workaround to put the kernel frontend thread into idle state!
1340                         if (state != eDVBFrontend::stateIdle && state != stateClosed)
1341                         {
1342                                 sec_fe->closeFrontend(true);
1343                                 state = sec_fe->m_state;
1344                         }
1345                         // sec_fe is closed... we must reopen it here..
1346                         if (state == stateClosed)
1347                         {
1348                                 regFE = prev;
1349                                 prev->inc_use();
1350                         }
1351                 }
1352         }
1353
1354         if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1355         {
1356                 long *sec_fe_data = sec_fe->m_data;
1357 //              eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1358                 switch (m_sec_sequence.current()->cmd)
1359                 {
1360                         case eSecCommand::SLEEP:
1361                                 delay = m_sec_sequence.current()++->msec;
1362                                 eDebugNoSimulate("[SEC] sleep %dms", delay);
1363                                 break;
1364                         case eSecCommand::GOTO:
1365                                 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1366                                         ++m_sec_sequence.current();
1367                                 break;
1368                         case eSecCommand::SET_VOLTAGE:
1369                         {
1370                                 int voltage = m_sec_sequence.current()++->voltage;
1371                                 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1372                                 sec_fe->setVoltage(voltage);
1373                                 break;
1374                         }
1375                         case eSecCommand::IF_VOLTAGE_GOTO:
1376                         {
1377                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1378                                 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1379                                         break;
1380                                 ++m_sec_sequence.current();
1381                                 break;
1382                         }
1383                         case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1384                         {
1385                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1386                                 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1387                                         break;
1388                                 ++m_sec_sequence.current();
1389                                 break;
1390                         }
1391                         case eSecCommand::IF_TONE_GOTO:
1392                         {
1393                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1394                                 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1395                                         break;
1396                                 ++m_sec_sequence.current();
1397                                 break;
1398                         }
1399                         case eSecCommand::IF_NOT_TONE_GOTO:
1400                         {
1401                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1402                                 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1403                                         break;
1404                                 ++m_sec_sequence.current();
1405                                 break;
1406                         }
1407                         case eSecCommand::SET_TONE:
1408                                 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1409                                 sec_fe->setTone(m_sec_sequence.current()++->tone);
1410                                 break;
1411                         case eSecCommand::SEND_DISEQC:
1412                                 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1413                                 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1414                                 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1415                                     eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1416                                 if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
1417                                         eDebugNoSimulate("(DiSEqC reset)");
1418                                 else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
1419                                         eDebugNoSimulate("(DiSEqC peripherial power on)");
1420                                 else
1421                                         eDebugNoSimulate("");
1422                                 ++m_sec_sequence.current();
1423                                 break;
1424                         case eSecCommand::SEND_TONEBURST:
1425                                 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1426                                 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1427                                 break;
1428                         case eSecCommand::SET_FRONTEND:
1429                         {
1430                                 int enableEvents = (m_sec_sequence.current()++)->val;
1431                                 eDebugNoSimulate("[SEC] setFrontend %d", enableEvents);
1432                                 setFrontend(enableEvents);
1433                                 break;
1434                         }
1435                         case eSecCommand::START_TUNE_TIMEOUT:
1436                         {
1437                                 int tuneTimeout = m_sec_sequence.current()->timeout;
1438                                 eDebugNoSimulate("[SEC] startTuneTimeout %d", tuneTimeout);
1439                                 if (!m_simulate)
1440                                         m_timeout->start(tuneTimeout, 1);
1441                                 ++m_sec_sequence.current();
1442                                 break;
1443                         }
1444                         case eSecCommand::SET_TIMEOUT:
1445                                 m_timeoutCount = m_sec_sequence.current()++->val;
1446                                 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1447                                 break;
1448                         case eSecCommand::IF_TIMEOUT_GOTO:
1449                                 if (!m_timeoutCount)
1450                                 {
1451                                         eDebugNoSimulate("[SEC] rotor timout");
1452                                         setSecSequencePos(m_sec_sequence.current()->steps);
1453                                 }
1454                                 else
1455                                         ++m_sec_sequence.current();
1456                                 break;
1457                         case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1458                         {
1459                                 int idx = m_sec_sequence.current()++->val;
1460                                 if ( idx == 0 || idx == 1 )
1461                                 {
1462                                         m_idleInputpower[idx] = sec_fe->readInputpower();
1463                                         eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1464                                 }
1465                                 else
1466                                         eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1467                                 break;
1468                         }
1469                         case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1470                         {
1471                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1472                                 int idx = compare.val;
1473                                 if ( !m_simulate && (idx == 0 || idx == 1) )
1474                                 {
1475                                         int idle = sec_fe->readInputpower();
1476                                         int diff = abs(idle-m_idleInputpower[idx]);
1477                                         if ( diff > 0)
1478                                         {
1479                                                 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1480                                                 setSecSequencePos(compare.steps);
1481                                                 break;
1482                                         }
1483                                 }
1484                                 ++m_sec_sequence.current();
1485                                 break;
1486                         }
1487                         case eSecCommand::IF_TUNER_LOCKED_GOTO:
1488                         {
1489                                 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1490                                 if (m_simulate)
1491                                 {
1492                                         setSecSequencePos(cmd.steps);
1493                                         break;
1494                                 }
1495                                 int signal = 0;
1496                                 int isLocked = readFrontendData(locked);
1497                                 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1498                                 --m_timeoutCount;
1499                                 if (!m_timeoutCount && m_retryCount > 0)
1500                                         --m_retryCount;
1501                                 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 40) || !cmd.lastSignal))
1502                                 {
1503                                         if (cmd.lastSignal)
1504                                                 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1505                                         else
1506                                         {
1507                                                 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1508                                                 if (!cmd.okcount)
1509                                                         cmd.lastSignal = signal;
1510                                         }
1511                                         ++cmd.okcount;
1512                                         if (cmd.okcount > 4)
1513                                         {
1514                                                 eDebugNoSimulate("ok > 4 .. goto %d\n", cmd.steps);
1515                                                 setSecSequencePos(cmd.steps);
1516                                                 m_state = stateLock;
1517                                                 m_stateChanged(this);
1518                                                 feEvent(-1); // flush events
1519                                                 m_sn->start();
1520                                                 break;
1521                                         }
1522                                 }
1523                                 else
1524                                 {
1525                                         if (isLocked)
1526                                                 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1527                                         else
1528                                                 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1529                                         cmd.okcount=0;
1530                                         cmd.lastSignal=0;
1531                                 }
1532                                 ++m_sec_sequence.current();
1533                                 break;
1534                         }
1535                         case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1536                                 m_runningInputpower = sec_fe->readInputpower();
1537                                 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1538                                 ++m_sec_sequence.current();
1539                                 break;
1540                         case eSecCommand::SET_ROTOR_MOVING:
1541                                 if (!m_simulate)
1542                                         m_sec->setRotorMoving(true);
1543                                 ++m_sec_sequence.current();
1544                                 break;
1545                         case eSecCommand::SET_ROTOR_STOPPED:
1546                                 if (!m_simulate)
1547                                         m_sec->setRotorMoving(false);
1548                                 ++m_sec_sequence.current();
1549                                 break;
1550                         case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1551                         {
1552                                 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1553                                 if (m_simulate)
1554                                 {
1555                                         setSecSequencePos(cmd.steps);
1556                                         break;
1557                                 }
1558                                 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1559                                 const char *txt = cmd.direction ? "running" : "stopped";
1560                                 --m_timeoutCount;
1561                                 if (!m_timeoutCount && m_retryCount > 0)
1562                                         --m_retryCount;
1563                                 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1564                                         txt,
1565                                         m_runningInputpower,
1566                                         idleInputpower,
1567                                         cmd.deltaA);
1568                                 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1569                                         || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1570                                 {
1571                                         ++cmd.okcount;
1572                                         eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1573                                         if ( cmd.okcount > 6 )
1574                                         {
1575                                                 eDebugNoSimulate("[SEC] rotor is %s", txt);
1576                                                 if (setSecSequencePos(cmd.steps))
1577                                                         break;
1578                                         }
1579                                 }
1580                                 else
1581                                 {
1582                                         eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1583                                         cmd.okcount=0;
1584                                 }
1585                                 ++m_sec_sequence.current();
1586                                 break;
1587                         }
1588                         case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1589                                 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1590                                         setSecSequencePos(m_sec_sequence.current()->steps);
1591                                 else
1592                                         ++m_sec_sequence.current();
1593                                 break;
1594                         case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1595                                 eDebugNoSimulate("[SEC] invalidate current switch params");
1596                                 sec_fe_data[CSW] = -1;
1597                                 sec_fe_data[UCSW] = -1;
1598                                 sec_fe_data[TONEBURST] = -1;
1599                                 ++m_sec_sequence.current();
1600                                 break;
1601                         case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1602                                 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1603                                 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1604                                 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1605                                 eDebugNoSimulate("[SEC] update current switch params");
1606                                 ++m_sec_sequence.current();
1607                                 break;
1608                         case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1609                                 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1610                                 sec_fe_data[ROTOR_CMD] = -1;
1611                                 sec_fe_data[ROTOR_POS] = -1;
1612                                 ++m_sec_sequence.current();
1613                                 break;
1614                         case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1615                                 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1616                                 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1617                                 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1618                                 ++m_sec_sequence.current();
1619                                 break;
1620                         case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1621                                 m_retryCount = m_sec_sequence.current()++->val;
1622                                 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1623                                 break;
1624                         case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1625                                 if (!m_retryCount)
1626                                 {
1627                                         eDebugNoSimulate("[SEC] no more rotor retrys");
1628                                         setSecSequencePos(m_sec_sequence.current()->steps);
1629                                 }
1630                                 else
1631                                         ++m_sec_sequence.current();
1632                                 break;
1633                         case eSecCommand::SET_POWER_LIMITING_MODE:
1634                         {
1635                                 if (!m_simulate)
1636                                 {
1637                                         char proc_name[64];
1638                                         sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1639                                         FILE *f=fopen(proc_name, "w");
1640                                         if (f) // new interface exist?
1641                                         {
1642                                                 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1643                                                 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1644                                                         eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1645                                                 else
1646                                                         eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1647                                                 fclose(f);
1648                                         }
1649                                         else if (sec_fe->m_need_rotor_workaround)
1650                                         {
1651                                                 char dev[16];
1652                                                 int slotid = sec_fe->m_slotid;
1653                                                 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1654                                                 if (slotid < 2)
1655                                                         sprintf(dev, "/dev/i2c/%d", slotid);
1656                                                 else if (slotid == 2)
1657                                                         sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1658                                                 else if (slotid == 3)
1659                                                         sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1660                                                 int fd = ::open(dev, O_RDWR);
1661
1662                                                 unsigned char data[2];
1663                                                 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1664                                                 if(::read(fd, data, 1) != 1)
1665                                                         eDebugNoSimulate("[SEC] error read lnbp (%m)");
1666                                                 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1667                                                 {
1668                                                         data[0] |= 0x80;  // enable static current limiting
1669                                                         eDebugNoSimulate("[SEC] set static current limiting");
1670                                                 }
1671                                                 else
1672                                                 {
1673                                                         data[0] &= ~0x80;  // enable dynamic current limiting
1674                                                         eDebugNoSimulate("[SEC] set dynamic current limiting");
1675                                                 }
1676                                                 if(::write(fd, data, 1) != 1)
1677                                                         eDebugNoSimulate("[SEC] error write lnbp (%m)");
1678                                                 ::close(fd);
1679                                         }
1680                                 }
1681                                 ++m_sec_sequence.current();
1682                                 break;
1683                         }
1684                         default:
1685                                 eDebugNoSimulate("[SEC] unhandled sec command %d",
1686                                         ++m_sec_sequence.current()->cmd);
1687                                 ++m_sec_sequence.current();
1688                 }
1689                 if (!m_simulate)
1690                         m_tuneTimer->start(delay,true);
1691         }
1692         if (regFE)
1693                 regFE->dec_use();
1694         if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1695                 tuneLoop();
1696 }
1697
1698 void eDVBFrontend::setFrontend(bool recvEvents)
1699 {
1700         if (!m_simulate)
1701         {
1702                 eDebug("setting frontend %d", m_dvbid);
1703                 if (recvEvents)
1704                         m_sn->start();
1705                 feEvent(-1); // flush events
1706                 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1707                 {
1708                         perror("FE_SET_FRONTEND failed");
1709                         return;
1710                 }
1711         }
1712 }
1713
1714 RESULT eDVBFrontend::getFrontendType(int &t)
1715 {
1716         if (m_type == -1)
1717                 return -ENODEV;
1718         t = m_type;
1719         return 0;
1720 }
1721
1722 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1723 {
1724         int res;
1725         if (!m_sec)
1726         {
1727                 eWarning("no SEC module active!");
1728                 return -ENOENT;
1729         }
1730         res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1731         if (!res)
1732         {
1733 #if HAVE_DVB_API_VERSION >= 3
1734                 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d system %d modulation %d pilot %d, rolloff %d",
1735                         feparm.system,
1736                         feparm.frequency,
1737                         feparm.polarisation,
1738                         feparm.symbol_rate,
1739                         feparm.inversion,
1740                         feparm.fec,
1741                         feparm.orbital_position,
1742                         feparm.system,
1743                         feparm.modulation,
1744                         feparm.pilot,
1745                         feparm.rolloff);
1746 #else
1747                 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1748                         feparm.system,
1749                         feparm.frequency,
1750                         feparm.polarisation,
1751                         feparm.symbol_rate,
1752                         feparm.inversion,
1753                         feparm.fec,
1754                         feparm.orbital_position);
1755 #endif
1756                 m_cur_pol = feparm.polarisation;
1757                 m_cur_orbpos = feparm.orbital_position;
1758                 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1759                 switch (feparm.inversion)
1760                 {
1761                         case eDVBFrontendParametersSatellite::Inversion_On:
1762                                 parm_inversion = INVERSION_ON;
1763                                 break;
1764                         case eDVBFrontendParametersSatellite::Inversion_Off:
1765                                 parm_inversion = INVERSION_OFF;
1766                                 break;
1767                         default:
1768                         case eDVBFrontendParametersSatellite::Inversion_Unknown:
1769                                 parm_inversion = INVERSION_AUTO;
1770                                 break;
1771                 }
1772                 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S)
1773                         switch (feparm.fec)
1774                         {
1775                                 case eDVBFrontendParametersSatellite::FEC_None:
1776                                         parm_u_qpsk_fec_inner = FEC_NONE;
1777                                         break;
1778                                 case eDVBFrontendParametersSatellite::FEC_1_2:
1779                                         parm_u_qpsk_fec_inner = FEC_1_2;
1780                                         break;
1781                                 case eDVBFrontendParametersSatellite::FEC_2_3:
1782                                         parm_u_qpsk_fec_inner = FEC_2_3;
1783                                         break;
1784                                 case eDVBFrontendParametersSatellite::FEC_3_4:
1785                                         parm_u_qpsk_fec_inner = FEC_3_4;
1786                                         break;
1787                                 case eDVBFrontendParametersSatellite::FEC_5_6:
1788                                         parm_u_qpsk_fec_inner = FEC_5_6;
1789                                         break;
1790                                 case eDVBFrontendParametersSatellite::FEC_7_8:
1791                                         parm_u_qpsk_fec_inner = FEC_7_8;
1792                                         break;
1793                                 default:
1794                                         eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
1795                                 case eDVBFrontendParametersSatellite::FEC_Auto:
1796                                         parm_u_qpsk_fec_inner = FEC_AUTO;
1797                                         break;
1798                         }
1799 #if HAVE_DVB_API_VERSION >= 3
1800                 else // DVB_S2
1801                 {
1802                         switch (feparm.fec)
1803                         {
1804                                 case eDVBFrontendParametersSatellite::FEC_1_2:
1805                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1806                                         break;
1807                                 case eDVBFrontendParametersSatellite::FEC_2_3:
1808                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1809                                         break;
1810                                 case eDVBFrontendParametersSatellite::FEC_3_4:
1811                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1812                                         break;
1813                                 case eDVBFrontendParametersSatellite::FEC_3_5:
1814                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1815                                         break;
1816                                 case eDVBFrontendParametersSatellite::FEC_4_5:
1817                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1818                                         break;
1819                                 case eDVBFrontendParametersSatellite::FEC_5_6:
1820                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1821                                         break;
1822                                 case eDVBFrontendParametersSatellite::FEC_7_8:
1823                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1824                                         break;
1825                                 case eDVBFrontendParametersSatellite::FEC_8_9:
1826                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1827                                         break;
1828                                 case eDVBFrontendParametersSatellite::FEC_9_10:
1829                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1830                                         break;
1831                                 default:
1832                                         eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
1833                                         return -EINVAL;
1834                         }
1835                         parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1836                         parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1837                         if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation_8PSK) {
1838                                 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1839                                 // 8PSK fec driver values are decimal 9 bigger
1840                         }
1841                 }
1842 #endif
1843                 // FIXME !!! get frequency range from tuner
1844                 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1845                 {
1846                         eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1847                         return -EINVAL;
1848                 }
1849                 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
1850         }
1851         return res;
1852 }
1853
1854 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1855 {
1856 #if HAVE_DVB_API_VERSION < 3
1857         parm_frequency = feparm.frequency;
1858 #else
1859         parm_frequency = feparm.frequency * 1000;
1860 #endif
1861         parm_u_qam_symbol_rate = feparm.symbol_rate;
1862         switch (feparm.modulation)
1863         {
1864         case eDVBFrontendParametersCable::Modulation_QAM16:
1865                 parm_u_qam_modulation = QAM_16;
1866                 break;
1867         case eDVBFrontendParametersCable::Modulation_QAM32:
1868                 parm_u_qam_modulation = QAM_32;
1869                 break;
1870         case eDVBFrontendParametersCable::Modulation_QAM64:
1871                 parm_u_qam_modulation = QAM_64;
1872                 break;
1873         case eDVBFrontendParametersCable::Modulation_QAM128:
1874                 parm_u_qam_modulation = QAM_128;
1875                 break;
1876         case eDVBFrontendParametersCable::Modulation_QAM256:
1877                 parm_u_qam_modulation = QAM_256;
1878                 break;
1879         default:
1880         case eDVBFrontendParametersCable::Modulation_Auto:
1881                 parm_u_qam_modulation = QAM_AUTO;
1882                 break;
1883         }
1884         switch (feparm.inversion)
1885         {
1886         case eDVBFrontendParametersCable::Inversion_On:
1887                 parm_inversion = INVERSION_ON;
1888                 break;
1889         case eDVBFrontendParametersCable::Inversion_Off:
1890                 parm_inversion = INVERSION_OFF;
1891                 break;
1892         default:
1893         case eDVBFrontendParametersCable::Inversion_Unknown:
1894                 parm_inversion = INVERSION_AUTO;
1895                 break;
1896         }
1897         switch (feparm.fec_inner)
1898         {
1899         case eDVBFrontendParametersCable::FEC_None:
1900                 parm_u_qam_fec_inner = FEC_NONE;
1901                 break;
1902         case eDVBFrontendParametersCable::FEC_1_2:
1903                 parm_u_qam_fec_inner = FEC_1_2;
1904                 break;
1905         case eDVBFrontendParametersCable::FEC_2_3:
1906                 parm_u_qam_fec_inner = FEC_2_3;
1907                 break;
1908         case eDVBFrontendParametersCable::FEC_3_4:
1909                 parm_u_qam_fec_inner = FEC_3_4;
1910                 break;
1911         case eDVBFrontendParametersCable::FEC_5_6:
1912                 parm_u_qam_fec_inner = FEC_5_6;
1913                 break;
1914         case eDVBFrontendParametersCable::FEC_7_8:
1915                 parm_u_qam_fec_inner = FEC_7_8;
1916                 break;
1917 #if HAVE_DVB_API_VERSION >= 3
1918         case eDVBFrontendParametersCable::FEC_8_9:
1919                 parm_u_qam_fec_inner = FEC_8_9;
1920                 break;
1921 #endif
1922         default:
1923         case eDVBFrontendParametersCable::FEC_Auto:
1924                 parm_u_qam_fec_inner = FEC_AUTO;
1925                 break;
1926         }
1927         eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
1928                 parm_frequency/1000,
1929                 parm_u_qam_symbol_rate,
1930                 parm_u_qam_fec_inner,
1931                 parm_u_qam_modulation,
1932                 parm_inversion);
1933         return 0;
1934 }
1935
1936 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
1937 {
1938         parm_frequency = feparm.frequency;
1939
1940         switch (feparm.bandwidth)
1941         {
1942         case eDVBFrontendParametersTerrestrial::Bandwidth_8MHz:
1943                 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
1944                 break;
1945         case eDVBFrontendParametersTerrestrial::Bandwidth_7MHz:
1946                 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
1947                 break;
1948         case eDVBFrontendParametersTerrestrial::Bandwidth_6MHz:
1949                 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
1950                 break;
1951         default:
1952         case eDVBFrontendParametersTerrestrial::Bandwidth_Auto:
1953                 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
1954                 break;
1955         }
1956         switch (feparm.code_rate_LP)
1957         {
1958         case eDVBFrontendParametersTerrestrial::FEC_1_2:
1959                 parm_u_ofdm_code_rate_LP = FEC_1_2;
1960                 break;
1961         case eDVBFrontendParametersTerrestrial::FEC_2_3:
1962                 parm_u_ofdm_code_rate_LP = FEC_2_3;
1963                 break;
1964         case eDVBFrontendParametersTerrestrial::FEC_3_4:
1965                 parm_u_ofdm_code_rate_LP = FEC_3_4;
1966                 break;
1967         case eDVBFrontendParametersTerrestrial::FEC_5_6:
1968                 parm_u_ofdm_code_rate_LP = FEC_5_6;
1969                 break;
1970         case eDVBFrontendParametersTerrestrial::FEC_7_8:
1971                 parm_u_ofdm_code_rate_LP = FEC_7_8;
1972                 break;
1973         default:
1974         case eDVBFrontendParametersTerrestrial::FEC_Auto:
1975                 parm_u_ofdm_code_rate_LP = FEC_AUTO;
1976                 break;
1977         }
1978         switch (feparm.code_rate_HP)
1979         {
1980         case eDVBFrontendParametersTerrestrial::FEC_1_2:
1981                 parm_u_ofdm_code_rate_HP = FEC_1_2;
1982                 break;
1983         case eDVBFrontendParametersTerrestrial::FEC_2_3:
1984                 parm_u_ofdm_code_rate_HP = FEC_2_3;
1985                 break;
1986         case eDVBFrontendParametersTerrestrial::FEC_3_4:
1987                 parm_u_ofdm_code_rate_HP = FEC_3_4;
1988                 break;
1989         case eDVBFrontendParametersTerrestrial::FEC_5_6:
1990                 parm_u_ofdm_code_rate_HP = FEC_5_6;
1991                 break;
1992         case eDVBFrontendParametersTerrestrial::FEC_7_8:
1993                 parm_u_ofdm_code_rate_HP = FEC_7_8;
1994                 break;
1995         default:
1996         case eDVBFrontendParametersTerrestrial::FEC_Auto:
1997                 parm_u_ofdm_code_rate_HP = FEC_AUTO;
1998                 break;
1999         }
2000         switch (feparm.modulation)
2001         {
2002         case eDVBFrontendParametersTerrestrial::Modulation_QPSK:
2003                 parm_u_ofdm_constellation = QPSK;
2004                 break;
2005         case eDVBFrontendParametersTerrestrial::Modulation_QAM16:
2006                 parm_u_ofdm_constellation = QAM_16;
2007                 break;
2008         case eDVBFrontendParametersTerrestrial::Modulation_QAM64:
2009                 parm_u_ofdm_constellation = QAM_64;
2010                 break;
2011         default:
2012         case eDVBFrontendParametersTerrestrial::Modulation_Auto:
2013                 parm_u_ofdm_constellation = QAM_AUTO;
2014                 break;
2015         }
2016         switch (feparm.transmission_mode)
2017         {
2018         case eDVBFrontendParametersTerrestrial::TransmissionMode_2k:
2019                 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2020                 break;
2021         case eDVBFrontendParametersTerrestrial::TransmissionMode_8k:
2022                 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2023                 break;
2024         default:
2025         case eDVBFrontendParametersTerrestrial::TransmissionMode_Auto:
2026                 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2027                 break;
2028         }
2029         switch (feparm.guard_interval)
2030         {
2031                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_32:
2032                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2033                         break;
2034                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_16:
2035                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2036                         break;
2037                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_8:
2038                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2039                         break;
2040                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_4:
2041                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2042                         break;
2043                 default:
2044                 case eDVBFrontendParametersTerrestrial::GuardInterval_Auto:
2045                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2046                         break;
2047         }
2048         switch (feparm.hierarchy)
2049         {
2050                 case eDVBFrontendParametersTerrestrial::Hierarchy_None:
2051                         parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2052                         break;
2053                 case eDVBFrontendParametersTerrestrial::Hierarchy_1:
2054                         parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2055                         break;
2056                 case eDVBFrontendParametersTerrestrial::Hierarchy_2:
2057                         parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2058                         break;
2059                 case eDVBFrontendParametersTerrestrial::Hierarchy_4:
2060                         parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2061                         break;
2062                 default:
2063                 case eDVBFrontendParametersTerrestrial::Hierarchy_Auto:
2064                         parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2065                         break;
2066         }
2067         switch (feparm.inversion)
2068         {
2069         case eDVBFrontendParametersTerrestrial::Inversion_On:
2070                 parm_inversion = INVERSION_ON;
2071                 break;
2072         case eDVBFrontendParametersTerrestrial::Inversion_Off:
2073                 parm_inversion = INVERSION_OFF;
2074                 break;
2075         default:
2076         case eDVBFrontendParametersTerrestrial::Inversion_Unknown:
2077                 parm_inversion = INVERSION_AUTO;
2078                 break;
2079         }
2080         return 0;
2081 }
2082
2083 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2084 {
2085         unsigned int timeout = 5000;
2086         eDebugNoSimulate("(%d)tune", m_dvbid);
2087
2088         m_timeout->stop();
2089
2090         int res=0;
2091
2092         if (!m_sn && !m_simulate)
2093         {
2094                 eDebug("no frontend device opened... do not try to tune !!!");
2095                 res = -ENODEV;
2096                 goto tune_error;
2097         }
2098
2099         if (m_type == -1)
2100         {
2101                 res = -ENODEV;
2102                 goto tune_error;
2103         }
2104
2105         if (!m_simulate)
2106                 m_sn->stop();
2107
2108         m_sec_sequence.clear();
2109
2110         where.calcLockTimeout(timeout);
2111
2112         switch (m_type)
2113         {
2114         case feSatellite:
2115         {
2116                 eDVBFrontendParametersSatellite feparm;
2117                 if (where.getDVBS(feparm))
2118                 {
2119                         eDebug("no dvbs data!");
2120                         res = -EINVAL;
2121                         goto tune_error;
2122                 }
2123                 if (!m_simulate)
2124                         m_sec->setRotorMoving(false);
2125                 res=prepare_sat(feparm, timeout);
2126                 if (res)
2127                         goto tune_error;
2128
2129                 break;
2130         }
2131         case feCable:
2132         {
2133                 eDVBFrontendParametersCable feparm;
2134                 if (where.getDVBC(feparm))
2135                 {
2136                         res = -EINVAL;
2137                         goto tune_error;
2138                 }
2139                 res=prepare_cable(feparm);
2140                 if (res)
2141                         goto tune_error;
2142
2143                 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2144                 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2145                 break;
2146         }
2147         case feTerrestrial:
2148         {
2149                 eDVBFrontendParametersTerrestrial feparm;
2150                 if (where.getDVBT(feparm))
2151                 {
2152                         eDebug("no -T data");
2153                         res = -EINVAL;
2154                         goto tune_error;
2155                 }
2156                 res=prepare_terrestrial(feparm);
2157                 if (res)
2158                         goto tune_error;
2159
2160                 std::string enable_5V;
2161                 char configStr[255];
2162                 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2163                 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2164                 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2165                 if (enable_5V == "True")
2166                         m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2167                 else
2168                         m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2169                 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2170
2171                 break;
2172         }
2173         }
2174
2175         m_sec_sequence.current() = m_sec_sequence.begin();
2176
2177         if (!m_simulate)
2178         {
2179                 m_tuneTimer->start(0,true);
2180                 if (m_state != stateTuning)
2181                 {
2182                         m_tuning = 1;
2183                         m_state = stateTuning;
2184                         m_stateChanged(this);
2185                 }
2186         }
2187         else
2188                 tuneLoop();
2189
2190         return res;
2191
2192 tune_error:
2193         m_tuneTimer->stop();
2194         return res;
2195 }
2196
2197 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2198 {
2199         connection = new eConnection(this, m_stateChanged.connect(stateChange));
2200         return 0;
2201 }
2202
2203 RESULT eDVBFrontend::setVoltage(int voltage)
2204 {
2205         if (m_type == feCable)
2206                 return -1;
2207 #if HAVE_DVB_API_VERSION < 3
2208         secVoltage vlt;
2209 #else
2210         bool increased=false;
2211         fe_sec_voltage_t vlt;
2212 #endif
2213         m_data[CUR_VOLTAGE]=voltage;
2214         switch (voltage)
2215         {
2216         case voltageOff:
2217                 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2218                 vlt = SEC_VOLTAGE_OFF;
2219                 break;
2220         case voltage13_5:
2221 #if HAVE_DVB_API_VERSION < 3
2222                 vlt = SEC_VOLTAGE_13_5;
2223                 break;
2224 #else
2225                 increased = true;
2226 #endif
2227         case voltage13:
2228                 vlt = SEC_VOLTAGE_13;
2229                 break;
2230         case voltage18_5:
2231 #if HAVE_DVB_API_VERSION < 3
2232                 vlt = SEC_VOLTAGE_18_5;
2233                 break;
2234 #else
2235                 increased = true;
2236 #endif
2237         case voltage18:
2238                 vlt = SEC_VOLTAGE_18;
2239                 break;
2240         default:
2241                 return -ENODEV;
2242         }
2243         if (m_simulate)
2244                 return 0;
2245 #if HAVE_DVB_API_VERSION < 3
2246         return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2247 #else
2248         if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2249                 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2250         return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2251 #endif
2252 }
2253
2254 RESULT eDVBFrontend::getState(int &state)
2255 {
2256         state = m_state;
2257         return 0;
2258 }
2259
2260 RESULT eDVBFrontend::setTone(int t)
2261 {
2262         if (m_type != feSatellite)
2263                 return -1;
2264 #if HAVE_DVB_API_VERSION < 3
2265         secToneMode_t tone;
2266 #else
2267         fe_sec_tone_mode_t tone;
2268 #endif
2269         m_data[CUR_TONE]=t;
2270         switch (t)
2271         {
2272         case toneOn:
2273                 tone = SEC_TONE_ON;
2274                 break;
2275         case toneOff:
2276                 tone = SEC_TONE_OFF;
2277                 break;
2278         default:
2279                 return -ENODEV;
2280         }
2281         if (m_simulate)
2282                 return 0;
2283 #if HAVE_DVB_API_VERSION < 3    
2284         return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2285 #else   
2286         return ::ioctl(m_fd, FE_SET_TONE, tone);
2287 #endif
2288 }
2289
2290 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2291         #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2292 #endif
2293
2294 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2295 {
2296         if (m_simulate)
2297                 return 0;
2298 #if HAVE_DVB_API_VERSION < 3
2299         struct secCommand cmd;
2300         cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2301         cmd.u.diseqc.cmdtype = diseqc.data[0];
2302         cmd.u.diseqc.addr = diseqc.data[1];
2303         cmd.u.diseqc.cmd = diseqc.data[2];
2304         cmd.u.diseqc.numParams = diseqc.len-3;
2305         memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2306         if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2307 #else
2308         struct dvb_diseqc_master_cmd cmd;
2309         memcpy(cmd.msg, diseqc.data, diseqc.len);
2310         cmd.msg_len = diseqc.len;
2311         if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2312 #endif
2313                 return -EINVAL;
2314         return 0;
2315 }
2316
2317 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2318         #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2319 #endif
2320 RESULT eDVBFrontend::sendToneburst(int burst)
2321 {
2322         if (m_simulate)
2323                 return 0;
2324 #if HAVE_DVB_API_VERSION < 3
2325         secMiniCmd cmd = SEC_MINI_NONE;
2326 #else
2327         fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2328 #endif
2329         if ( burst == eDVBSatelliteDiseqcParameters::A )
2330                 cmd = SEC_MINI_A;
2331         else if ( burst == eDVBSatelliteDiseqcParameters::B )
2332                 cmd = SEC_MINI_B;
2333 #if HAVE_DVB_API_VERSION < 3
2334         if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2335                 return -EINVAL;
2336 #else
2337         if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2338                 return -EINVAL;
2339 #endif
2340         return 0;
2341 }
2342
2343 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2344 {
2345         m_sec = sec;
2346         return 0;
2347 }
2348
2349 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2350 {
2351         m_sec_sequence = list;
2352         return 0;
2353 }
2354
2355 RESULT eDVBFrontend::getData(int num, long &data)
2356 {
2357         if ( num < NUM_DATA_ENTRIES )
2358         {
2359                 data = m_data[num];
2360                 return 0;
2361         }
2362         return -EINVAL;
2363 }
2364
2365 RESULT eDVBFrontend::setData(int num, long val)
2366 {
2367         if ( num < NUM_DATA_ENTRIES )
2368         {
2369                 m_data[num] = val;
2370                 return 0;
2371         }
2372         return -EINVAL;
2373 }
2374
2375 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2376 {
2377         int type;
2378         if (feparm->getSystem(type) || type != m_type || !m_enabled)
2379                 return 0;
2380         if (m_type == eDVBFrontend::feSatellite)
2381         {
2382                 ASSERT(m_sec);
2383                 eDVBFrontendParametersSatellite sat_parm;
2384                 int ret = feparm->getDVBS(sat_parm);
2385                 ASSERT(!ret);
2386                 if (sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S2 && !m_can_handle_dvbs2)
2387                         return 0;
2388                 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2389                 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S && m_can_handle_dvbs2)
2390                         ret -= 1;
2391                 return ret;
2392         }
2393         else if (m_type == eDVBFrontend::feCable)
2394                 return 2;  // more prio for cable frontends
2395         else if (m_type == eDVBFrontend::feTerrestrial)
2396                 return 1;
2397         return 0;
2398 }
2399
2400 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2401 {
2402         ePyObject Id, Descr, Enabled, IsDVBS2;
2403         if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4)
2404                 goto arg_error;
2405         Id = PyTuple_GET_ITEM(obj, 0);
2406         Descr = PyTuple_GET_ITEM(obj, 1);
2407         Enabled = PyTuple_GET_ITEM(obj, 2);
2408         IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2409         if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2))
2410                 goto arg_error;
2411         strcpy(m_description, PyString_AS_STRING(Descr));
2412         m_slotid = PyInt_AsLong(Id);
2413         m_enabled = Enabled == Py_True;
2414         // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2415         m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2416                 !!strstr(m_description, "Alps BSBE2") ||
2417                 !!strstr(m_description, "Alps -S") ||
2418                 !!strstr(m_description, "BCM4501");
2419         m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2420         eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2421                 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2422         return true;
2423 arg_error:
2424         PyErr_SetString(PyExc_StandardError,
2425                 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");
2426         return false;
2427 }
2428
2429 RESULT eDVBFrontend::turnOffSatCR(int satcr)
2430 {
2431         eSecCommandList sec_sequence;
2432         // check if voltage is disabled
2433         eSecCommand::pair compare;
2434         compare.steps = +9;     //nothing to do
2435         compare.voltage = iDVBFrontend::voltageOff;
2436         sec_sequence.push_back( eSecCommand(eSecCommand::IF_NOT_VOLTAGE_GOTO, compare) );
2437         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2438         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50 ) );
2439
2440         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage18_5) );
2441         sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
2442         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 250) );
2443
2444         eDVBDiseqcCommand diseqc;
2445         memset(diseqc.data, 0, MAX_DISEQC_LENGTH);
2446         diseqc.len = 5;
2447         diseqc.data[0] = 0xE0;
2448         diseqc.data[1] = 0x10;
2449         diseqc.data[2] = 0x5A;
2450         diseqc.data[3] = satcr << 5;
2451         diseqc.data[4] = 0x00;
2452
2453         sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
2454         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50+20+14*diseqc.len) );
2455         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2456         setSecSequence(sec_sequence);
2457         return 0;
2458 }
2459
2460 RESULT eDVBFrontend::ScanSatCR()
2461 {
2462         setFrontend();
2463         usleep(20000);
2464         setTone(iDVBFrontend::toneOff);
2465         return 0;
2466 }