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