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