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