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