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