add caluclation for bcm4506 based frontends
[enigma2.git] / lib / dvb / frontend.cpp
1 #include <lib/dvb/dvb.h>
2 #include <lib/dvb/frontendparms.h>
3 #include <lib/base/eerror.h>
4 #include <lib/base/nconfig.h> // access to python config
5 #include <errno.h>
6 #include <unistd.h>
7 #include <fcntl.h>
8 #include <sys/ioctl.h>
9
10 #ifndef I2C_SLAVE_FORCE
11 #define I2C_SLAVE_FORCE 0x0706
12 #endif
13
14 #if HAVE_DVB_API_VERSION < 3
15 #include <ost/frontend.h>
16 #include <ost/sec.h>
17 #define QAM_AUTO                                (Modulation)6
18 #define TRANSMISSION_MODE_AUTO  (TransmitMode)2
19 #define BANDWIDTH_AUTO                  (BandWidth)3
20 #define GUARD_INTERVAL_AUTO             (GuardInterval)4
21 #define HIERARCHY_AUTO                  (Hierarchy)4
22 #define parm_frequency parm.Frequency
23 #define parm_inversion parm.Inversion
24 #define parm_u_qpsk_symbol_rate parm.u.qpsk.SymbolRate
25 #define parm_u_qpsk_fec_inner parm.u.qpsk.FEC_inner
26 #define parm_u_qam_symbol_rate parm.u.qam.SymbolRate
27 #define parm_u_qam_fec_inner parm.u.qam.FEC_inner
28 #define parm_u_qam_modulation parm.u.qam.QAM
29 #define parm_u_ofdm_bandwidth parm.u.ofdm.bandWidth
30 #define parm_u_ofdm_code_rate_LP parm.u.ofdm.LP_CodeRate
31 #define parm_u_ofdm_code_rate_HP parm.u.ofdm.HP_CodeRate
32 #define parm_u_ofdm_constellation parm.u.ofdm.Constellation
33 #define parm_u_ofdm_transmission_mode parm.u.ofdm.TransmissionMode
34 #define parm_u_ofdm_guard_interval parm.u.ofdm.guardInterval
35 #define parm_u_ofdm_hierarchy_information parm.u.ofdm.HierarchyInformation
36 #else
37 #include <linux/dvb/frontend.h>
38 #define parm_frequency parm.frequency
39 #define parm_inversion parm.inversion
40 #define parm_u_qpsk_symbol_rate parm.u.qpsk.symbol_rate
41 #define parm_u_qpsk_fec_inner parm.u.qpsk.fec_inner
42 #define parm_u_qam_symbol_rate parm.u.qam.symbol_rate
43 #define parm_u_qam_fec_inner parm.u.qam.fec_inner
44 #define parm_u_qam_modulation parm.u.qam.modulation
45 #define parm_u_ofdm_bandwidth parm.u.ofdm.bandwidth
46 #define parm_u_ofdm_code_rate_LP parm.u.ofdm.code_rate_LP
47 #define parm_u_ofdm_code_rate_HP parm.u.ofdm.code_rate_HP
48 #define parm_u_ofdm_constellation parm.u.ofdm.constellation
49 #define parm_u_ofdm_transmission_mode parm.u.ofdm.transmission_mode
50 #define parm_u_ofdm_guard_interval parm.u.ofdm.guard_interval
51 #define parm_u_ofdm_hierarchy_information parm.u.ofdm.hierarchy_information
52 #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 != eDVBFrontendParametersCable::FEC_None && fec_inner > eDVBFrontendParametersCable::FEC_8_9 )
196                 fec_inner = eDVBFrontendParametersCable::FEC_Auto;
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                         else if (!strcmp(m_description, "BCM4506"))
862                                 ret = (snr * 100) >> 8;
863
864                         if (type == signalQuality)
865                         {
866                                 if (ret == 0x12345678) // no snr db calculation avail.. return untouched snr value..
867                                         return snr;
868                                 switch(m_type)
869                                 {
870                                         case feSatellite:
871                                                 return ret >= sat_max ? 65536 : ret * 65536 / sat_max;
872                                         case feCable: // we assume a max of 42db here
873                                                 return ret >= 4200 ? 65536 : ret * 65536 / 4200;
874                                         case feTerrestrial: // we assume a max of 24db here
875                                                 return ret >= 2400 ? 65536 : ret * 65536 / 2400;
876                                 }
877                         }
878 /* else
879                                 eDebug("no SNR dB calculation for frontendtype %s yet", m_description); */
880                         return ret;
881                 }
882                 case signalPower:
883                 {
884                         uint16_t strength=0;
885                         if (!m_simulate)
886                         {
887                                 if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
888                                         eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
889                         }
890                         return strength;
891                 }
892                 case locked:
893                 {
894 #if HAVE_DVB_API_VERSION < 3
895                         FrontendStatus status=0;
896 #else
897                         fe_status_t status;
898 #endif
899                         if (!m_simulate)
900                         {
901                                 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
902                                         eDebug("FE_READ_STATUS failed (%m)");
903                                 return !!(status&FE_HAS_LOCK);
904                         }
905                         return 1;
906                 }
907                 case synced:
908                 {
909 #if HAVE_DVB_API_VERSION < 3
910                         FrontendStatus status=0;
911 #else
912                         fe_status_t status;
913 #endif
914                         if (!m_simulate)
915                         {
916                                 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
917                                         eDebug("FE_READ_STATUS failed (%m)");
918                                 return !!(status&FE_HAS_SYNC);
919                         }
920                         return 1;
921                 }
922                 case frontendNumber:
923                         return m_slotid;
924         }
925         return 0;
926 }
927
928 void PutToDict(ePyObject &dict, const char*key, long value)
929 {
930         ePyObject item = PyInt_FromLong(value);
931         if (item)
932         {
933                 if (PyDict_SetItemString(dict, key, item))
934                         eDebug("put %s to dict failed", key);
935                 Py_DECREF(item);
936         }
937         else
938                 eDebug("could not create PyObject for %s", key);
939 }
940
941 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
942 {
943         if (item)
944         {
945                 if (PyDict_SetItemString(dict, key, item))
946                         eDebug("put %s to dict failed", key);
947                 Py_DECREF(item);
948         }
949         else
950                 eDebug("invalid PyObject for %s", key);
951 }
952
953 void PutToDict(ePyObject &dict, const char*key, const char *value)
954 {
955         ePyObject item = PyString_FromString(value);
956         if (item)
957         {
958                 if (PyDict_SetItemString(dict, key, item))
959                         eDebug("put %s to dict failed", key);
960                 Py_DECREF(item);
961         }
962         else
963                 eDebug("could not create PyObject for %s", key);
964 }
965
966 void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, long freq_offset, int orb_pos, int polarization)
967 {
968         long tmp=0;
969         int frequency = parm_frequency + freq_offset;
970         PutToDict(dict, "frequency", frequency);
971         PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
972         PutToDict(dict, "orbital_position", orb_pos);
973         PutToDict(dict, "polarization", polarization);
974
975         switch(parm_u_qpsk_fec_inner)
976         {
977         case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
978         case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
979         case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
980         case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
981         case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
982         case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
983         default:
984         case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
985 #if HAVE_DVB_API_VERSION >=3
986         case FEC_S2_8PSK_1_2: 
987         case FEC_S2_QPSK_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
988         case FEC_S2_8PSK_2_3:
989         case FEC_S2_QPSK_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
990         case FEC_S2_8PSK_3_4:
991         case FEC_S2_QPSK_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
992         case FEC_S2_8PSK_5_6:
993         case FEC_S2_QPSK_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
994         case FEC_S2_8PSK_7_8:
995         case FEC_S2_QPSK_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
996         case FEC_S2_8PSK_8_9:
997         case FEC_S2_QPSK_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
998         case FEC_S2_8PSK_3_5:
999         case FEC_S2_QPSK_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
1000         case FEC_S2_8PSK_4_5:
1001         case FEC_S2_QPSK_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
1002         case FEC_S2_8PSK_9_10:
1003         case FEC_S2_QPSK_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1004 #endif
1005         }
1006         PutToDict(dict, "fec_inner", tmp);
1007 #if HAVE_DVB_API_VERSION >=3
1008         PutToDict(dict, "modulation",
1009                 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ?
1010                         eDVBFrontendParametersSatellite::Modulation_8PSK :
1011                         eDVBFrontendParametersSatellite::Modulation_QPSK );
1012         if (parm_u_qpsk_fec_inner > FEC_AUTO)
1013         {
1014                 switch(parm_inversion & 0xc)
1015                 {
1016                 default: // unknown rolloff
1017                 case 0: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1018                 case 4: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1019                 case 8: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1020                 }
1021                 PutToDict(dict, "rolloff", tmp);
1022                 switch(parm_inversion & 0x30)
1023                 {
1024                 case 0: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1025                 case 0x10: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1026                 case 0x20: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1027                 }
1028                 PutToDict(dict, "pilot", tmp);
1029                 tmp = eDVBFrontendParametersSatellite::System_DVB_S2;
1030         }
1031         else
1032                 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1033 #else
1034         PutToDict(dict, "modulation", eDVBFrontendParametersSatellite::Modulation_QPSK );
1035         tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1036 #endif
1037         PutToDict(dict, "system", tmp);
1038 }
1039
1040 void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1041 {
1042         long tmp=0;
1043 #if HAVE_DVB_API_VERSION < 3
1044         PutToDict(dict, "frequency", parm_frequency);
1045 #else
1046         PutToDict(dict, "frequency", parm_frequency/1000);
1047 #endif
1048         PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1049         switch(parm_u_qam_fec_inner)
1050         {
1051         case FEC_NONE: tmp = eDVBFrontendParametersCable::FEC_None; break;
1052         case FEC_1_2: tmp = eDVBFrontendParametersCable::FEC_1_2; break;
1053         case FEC_2_3: tmp = eDVBFrontendParametersCable::FEC_2_3; break;
1054         case FEC_3_4: tmp = eDVBFrontendParametersCable::FEC_3_4; break;
1055         case FEC_5_6: tmp = eDVBFrontendParametersCable::FEC_5_6; break;
1056         case FEC_7_8: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1057 #if HAVE_DVB_API_VERSION >= 3
1058         case FEC_8_9: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1059 #endif
1060         default:
1061         case FEC_AUTO: tmp = eDVBFrontendParametersCable::FEC_Auto; break;
1062         }
1063         PutToDict(dict, "fec_inner", tmp);
1064         switch(parm_u_qam_modulation)
1065         {
1066         case QAM_16: tmp = eDVBFrontendParametersCable::Modulation_QAM16; break;
1067         case QAM_32: tmp = eDVBFrontendParametersCable::Modulation_QAM32; break;
1068         case QAM_64: tmp = eDVBFrontendParametersCable::Modulation_QAM64; break;
1069         case QAM_128: tmp = eDVBFrontendParametersCable::Modulation_QAM128; break;
1070         case QAM_256: tmp = eDVBFrontendParametersCable::Modulation_QAM256; break;
1071         default:
1072         case QAM_AUTO:   tmp = eDVBFrontendParametersCable::Modulation_Auto; break;
1073         }
1074         PutToDict(dict, "modulation", tmp);
1075 }
1076
1077 void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1078 {
1079         long tmp=0;
1080         PutToDict(dict, "frequency", parm_frequency);
1081         switch (parm_u_ofdm_bandwidth)
1082         {
1083         case BANDWIDTH_8_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_8MHz; break;
1084         case BANDWIDTH_7_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_7MHz; break;
1085         case BANDWIDTH_6_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_6MHz; break;
1086         default:
1087         case BANDWIDTH_AUTO: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_Auto; break;
1088         }
1089         PutToDict(dict, "bandwidth", tmp);
1090         switch (parm_u_ofdm_code_rate_LP)
1091         {
1092         case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1093         case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1094         case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1095         case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1096         case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1097         default:
1098         case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1099         }
1100         PutToDict(dict, "code_rate_lp", tmp);
1101         switch (parm_u_ofdm_code_rate_HP)
1102         {
1103         case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1104         case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1105         case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1106         case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1107         case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1108         default:
1109         case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1110         }
1111         PutToDict(dict, "code_rate_hp", tmp);
1112         switch (parm_u_ofdm_constellation)
1113         {
1114         case QPSK: tmp = eDVBFrontendParametersTerrestrial::Modulation_QPSK; break;
1115         case QAM_16: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM16; break;
1116         case QAM_64: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM64; break;
1117         default:
1118         case QAM_AUTO: tmp = eDVBFrontendParametersTerrestrial::Modulation_Auto; break;
1119         }
1120         PutToDict(dict, "constellation", tmp);
1121         switch (parm_u_ofdm_transmission_mode)
1122         {
1123         case TRANSMISSION_MODE_2K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_2k; break;
1124         case TRANSMISSION_MODE_8K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_8k; break;
1125         default:
1126         case TRANSMISSION_MODE_AUTO: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto; break;
1127         }
1128         PutToDict(dict, "transmission_mode", tmp);
1129         switch (parm_u_ofdm_guard_interval)
1130         {
1131                 case GUARD_INTERVAL_1_32: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_32; break;
1132                 case GUARD_INTERVAL_1_16: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_16; break;
1133                 case GUARD_INTERVAL_1_8: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_8; break;
1134                 case GUARD_INTERVAL_1_4: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_4; break;
1135                 default:
1136                 case GUARD_INTERVAL_AUTO: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_Auto; break;
1137         }
1138         PutToDict(dict, "guard_interval", tmp);
1139         switch (parm_u_ofdm_hierarchy_information)
1140         {
1141                 case HIERARCHY_NONE: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_None; break;
1142                 case HIERARCHY_1: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_1; break;
1143                 case HIERARCHY_2: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_2; break;
1144                 case HIERARCHY_4: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_4; break;
1145                 default:
1146                 case HIERARCHY_AUTO: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_Auto; break;
1147         }
1148         PutToDict(dict, "hierarchy_information", tmp);
1149 }
1150
1151 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1152 {
1153         if (dest && PyDict_Check(dest))
1154         {
1155                 const char *tmp = "UNKNOWN";
1156                 switch(m_state)
1157                 {
1158                         case stateIdle:
1159                                 tmp="IDLE";
1160                                 break;
1161                         case stateTuning:
1162                                 tmp="TUNING";
1163                                 break;
1164                         case stateFailed:
1165                                 tmp="FAILED";
1166                                 break;
1167                         case stateLock:
1168                                 tmp="LOCKED";
1169                                 break;
1170                         case stateLostLock:
1171                                 tmp="LOSTLOCK";
1172                                 break;
1173                         default:
1174                                 break;
1175                 }
1176                 PutToDict(dest, "tuner_state", tmp);
1177                 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1178                 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1179                 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1180                 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1181                 int sigQualitydB = readFrontendData(signalQualitydB);
1182                 if (sigQualitydB == 0x12345678) // not support yet
1183                 {
1184                         ePyObject obj=Py_None;
1185                         Py_INCREF(obj);
1186                         PutToDict(dest, "tuner_signal_quality_db", obj);
1187                 }
1188                 else
1189                         PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1190                 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1191         }
1192 }
1193
1194 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1195 {
1196         if (dest && PyDict_Check(dest))
1197         {
1198                 switch(m_type)
1199                 {
1200                         case feSatellite:
1201                         case feCable:
1202                         case feTerrestrial:
1203                         {
1204                                 FRONTENDPARAMETERS front;
1205                                 if (m_fd == -1 && !original)
1206                                         original = true;
1207                                 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1208                                 {
1209                                         eDebug("FE_GET_FRONTEND failed (%m)");
1210                                         original = true;
1211                                 }
1212                                 {
1213                                         const FRONTENDPARAMETERS &parm = original || m_simulate ? this->parm : front;
1214                                         long tmp = eDVBFrontendParametersSatellite::Inversion_Unknown;
1215                                         switch(parm_inversion & 3)
1216                                         {
1217                                                 case INVERSION_ON:
1218                                                         tmp = eDVBFrontendParametersSatellite::Inversion_On;
1219                                                         break;
1220                                                 case INVERSION_OFF:
1221                                                         tmp = eDVBFrontendParametersSatellite::Inversion_Off;
1222                                                 default:
1223                                                         break;
1224                                         }
1225                                         PutToDict(dest, "inversion", tmp);
1226
1227                                         switch(m_type)
1228                                         {
1229                                                 case feSatellite:
1230                                                         fillDictWithSatelliteData(dest, original?parm:front, m_data[FREQ_OFFSET], m_cur_orbpos, m_cur_pol);
1231                                                         break;
1232                                                 case feCable:
1233                                                         fillDictWithCableData(dest, original?parm:front);
1234                                                         break;
1235                                                 case feTerrestrial:
1236                                                         fillDictWithTerrestrialData(dest, original?parm:front);
1237                                                         break;
1238                                         }
1239                                 }
1240                         }
1241                         default:
1242                                 break;
1243                 }
1244         }
1245 }
1246
1247 void eDVBFrontend::getFrontendData(ePyObject dest)
1248 {
1249         if (dest && PyDict_Check(dest))
1250         {
1251                 const char *tmp=0;
1252                 PutToDict(dest, "tuner_number", m_slotid);
1253                 switch(m_type)
1254                 {
1255                         case feSatellite:
1256                                 tmp = "DVB-S";
1257                                 break;
1258                         case feCable:
1259                                 tmp = "DVB-C";
1260                                 break;
1261                         case feTerrestrial:
1262                                 tmp = "DVB-T";
1263                                 break;
1264                         default:
1265                                 tmp = "UNKNOWN";
1266                                 break;
1267                 }
1268                 PutToDict(dest, "tuner_type", tmp);
1269         }
1270 }
1271
1272 #ifndef FP_IOCTL_GET_ID
1273 #define FP_IOCTL_GET_ID 0
1274 #endif
1275 int eDVBFrontend::readInputpower()
1276 {
1277         if (m_simulate)
1278                 return 0;
1279         int power=m_slotid;  // this is needed for read inputpower from the correct tuner !
1280         char proc_name[64];
1281         sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1282         FILE *f=fopen(proc_name, "r");
1283         if (f)
1284         {
1285                 if (fscanf(f, "%d", &power) != 1)
1286                         eDebug("read %s failed!! (%m)", proc_name);
1287                 else
1288                         eDebug("%s is %d\n", proc_name, power);
1289                 fclose(f);
1290         }
1291         else
1292         {
1293                 // open front prozessor
1294                 int fp=::open("/dev/dbox/fp0", O_RDWR);
1295                 if (fp < 0)
1296                 {
1297                         eDebug("couldn't open fp");
1298                         return -1;
1299                 }
1300                 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1301                 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1302                 {
1303                         eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1304                         return -1;
1305                 }
1306                 ::close(fp);
1307         }
1308
1309         return power;
1310 }
1311
1312 bool eDVBFrontend::setSecSequencePos(int steps)
1313 {
1314         eDebugNoSimulate("set sequence pos %d", steps);
1315         if (!steps)
1316                 return false;
1317         while( steps > 0 )
1318         {
1319                 if (m_sec_sequence.current() != m_sec_sequence.end())
1320                         ++m_sec_sequence.current();
1321                 --steps;
1322         }
1323         while( steps < 0 )
1324         {
1325                 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1326                         --m_sec_sequence.current();
1327                 ++steps;
1328         }
1329         return true;
1330 }
1331
1332 void eDVBFrontend::tuneLoop()  // called by m_tuneTimer
1333 {
1334         int delay=0;
1335         eDVBFrontend *sec_fe = this;
1336         eDVBRegisteredFrontend *regFE = 0;
1337         long tmp = m_data[LINKED_PREV_PTR];
1338         while ( tmp != -1 )
1339         {
1340                 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1341                 sec_fe = prev->m_frontend;
1342                 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1343                 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1344                         int state = sec_fe->m_state;
1345                         // workaround to put the kernel frontend thread into idle state!
1346                         if (state != eDVBFrontend::stateIdle && state != stateClosed)
1347                         {
1348                                 sec_fe->closeFrontend(true);
1349                                 state = sec_fe->m_state;
1350                         }
1351                         // sec_fe is closed... we must reopen it here..
1352                         if (state == eDVBFrontend::stateClosed)
1353                         {
1354                                 regFE = prev;
1355                                 prev->inc_use();
1356                         }
1357                 }
1358         }
1359
1360         if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1361         {
1362                 long *sec_fe_data = sec_fe->m_data;
1363 //              eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1364                 switch (m_sec_sequence.current()->cmd)
1365                 {
1366                         case eSecCommand::SLEEP:
1367                                 delay = m_sec_sequence.current()++->msec;
1368                                 eDebugNoSimulate("[SEC] sleep %dms", delay);
1369                                 break;
1370                         case eSecCommand::GOTO:
1371                                 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1372                                         ++m_sec_sequence.current();
1373                                 break;
1374                         case eSecCommand::SET_VOLTAGE:
1375                         {
1376                                 int voltage = m_sec_sequence.current()++->voltage;
1377                                 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1378                                 sec_fe->setVoltage(voltage);
1379                                 break;
1380                         }
1381                         case eSecCommand::IF_VOLTAGE_GOTO:
1382                         {
1383                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1384                                 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1385                                         break;
1386                                 ++m_sec_sequence.current();
1387                                 break;
1388                         }
1389                         case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1390                         {
1391                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1392                                 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1393                                         break;
1394                                 ++m_sec_sequence.current();
1395                                 break;
1396                         }
1397                         case eSecCommand::IF_TONE_GOTO:
1398                         {
1399                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1400                                 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1401                                         break;
1402                                 ++m_sec_sequence.current();
1403                                 break;
1404                         }
1405                         case eSecCommand::IF_NOT_TONE_GOTO:
1406                         {
1407                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1408                                 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1409                                         break;
1410                                 ++m_sec_sequence.current();
1411                                 break;
1412                         }
1413                         case eSecCommand::SET_TONE:
1414                                 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1415                                 sec_fe->setTone(m_sec_sequence.current()++->tone);
1416                                 break;
1417                         case eSecCommand::SEND_DISEQC:
1418                                 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1419                                 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1420                                 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1421                                     eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1422                                 if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
1423                                         eDebugNoSimulate("(DiSEqC reset)");
1424                                 else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
1425                                         eDebugNoSimulate("(DiSEqC peripherial power on)");
1426                                 else
1427                                         eDebugNoSimulate("");
1428                                 ++m_sec_sequence.current();
1429                                 break;
1430                         case eSecCommand::SEND_TONEBURST:
1431                                 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1432                                 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1433                                 break;
1434                         case eSecCommand::SET_FRONTEND:
1435                                 eDebugNoSimulate("[SEC] setFrontend");
1436                                 setFrontend();
1437                                 ++m_sec_sequence.current();
1438                                 break;
1439                         case eSecCommand::START_TUNE_TIMEOUT:
1440                         {
1441                                 if (!m_simulate)
1442                                         m_timeout->start(m_sec_sequence.current()->timeout, 1);
1443                                 ++m_sec_sequence.current();
1444                                 break;
1445                         }
1446                         case eSecCommand::SET_TIMEOUT:
1447                                 m_timeoutCount = m_sec_sequence.current()++->val;
1448                                 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1449                                 break;
1450                         case eSecCommand::IF_TIMEOUT_GOTO:
1451                                 if (!m_timeoutCount)
1452                                 {
1453                                         eDebugNoSimulate("[SEC] rotor timout");
1454                                         setSecSequencePos(m_sec_sequence.current()->steps);
1455                                 }
1456                                 else
1457                                         ++m_sec_sequence.current();
1458                                 break;
1459                         case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1460                         {
1461                                 int idx = m_sec_sequence.current()++->val;
1462                                 if ( idx == 0 || idx == 1 )
1463                                 {
1464                                         m_idleInputpower[idx] = sec_fe->readInputpower();
1465                                         eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1466                                 }
1467                                 else
1468                                         eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1469                                 break;
1470                         }
1471                         case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1472                         {
1473                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1474                                 int idx = compare.val;
1475                                 if ( !m_simulate && (idx == 0 || idx == 1) )
1476                                 {
1477                                         int idle = sec_fe->readInputpower();
1478                                         int diff = abs(idle-m_idleInputpower[idx]);
1479                                         if ( diff > 0)
1480                                         {
1481                                                 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1482                                                 setSecSequencePos(compare.steps);
1483                                                 break;
1484                                         }
1485                                 }
1486                                 ++m_sec_sequence.current();
1487                                 break;
1488                         }
1489                         case eSecCommand::IF_TUNER_LOCKED_GOTO:
1490                         {
1491                                 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1492                                 if (m_simulate)
1493                                 {
1494                                         setSecSequencePos(cmd.steps);
1495                                         break;
1496                                 }
1497                                 int signal = 0;
1498                                 int isLocked = readFrontendData(locked);
1499                                 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1500                                 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 50) || !cmd.lastSignal))
1501                                 {
1502                                         if (cmd.lastSignal)
1503                                                 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1504                                         else
1505                                         {
1506                                                 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
1507                                                 cmd.lastSignal = signal;
1508                                         }
1509                                         ++cmd.okcount;
1510                                         if (cmd.okcount > 4)
1511                                         {
1512                                                 eDebugNoSimulate("ok > 4 .. goto %d\n",cmd.steps);
1513                                                 setSecSequencePos(cmd.steps);
1514                                                 m_state = stateLock;
1515                                                 m_stateChanged(this);
1516                                                 feEvent(-1);
1517                                                 m_sn->start();
1518                                                 break;
1519                                         }
1520                                 }
1521                                 else
1522                                 {
1523                                         if (isLocked)
1524                                                 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1525                                         else
1526                                                 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
1527                                         --m_timeoutCount;
1528                                         if (!m_timeoutCount && m_retryCount > 0)
1529                                                 --m_retryCount;
1530                                         cmd.okcount=0;
1531                                         cmd.lastSignal=0;
1532                                 }
1533                                 ++m_sec_sequence.current();
1534                                 break;
1535                         }
1536                         case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1537                                 m_runningInputpower = sec_fe->readInputpower();
1538                                 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
1539                                 ++m_sec_sequence.current();
1540                                 break;
1541                         case eSecCommand::SET_ROTOR_MOVING:
1542                                 if (!m_simulate)
1543                                         m_sec->setRotorMoving(true);
1544                                 ++m_sec_sequence.current();
1545                                 break;
1546                         case eSecCommand::SET_ROTOR_STOPPED:
1547                                 if (!m_simulate)
1548                                         m_sec->setRotorMoving(false);
1549                                 ++m_sec_sequence.current();
1550                                 break;
1551                         case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1552                         {
1553                                 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1554                                 if (m_simulate)
1555                                 {
1556                                         setSecSequencePos(cmd.steps);
1557                                         break;
1558                                 }
1559                                 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1560                                 const char *txt = cmd.direction ? "running" : "stopped";
1561                                 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1562                                         txt,
1563                                         m_runningInputpower,
1564                                         idleInputpower,
1565                                         cmd.deltaA);
1566                                 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1567                                         || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1568                                 {
1569                                         ++cmd.okcount;
1570                                         eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1571                                         if ( cmd.okcount > 6 )
1572                                         {
1573                                                 eDebugNoSimulate("[SEC] rotor is %s", txt);
1574                                                 if (setSecSequencePos(cmd.steps))
1575                                                         break;
1576                                         }
1577                                 }
1578                                 else
1579                                 {
1580                                         eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1581                                         --m_timeoutCount;
1582                                         if (!m_timeoutCount && m_retryCount > 0)
1583                                                 --m_retryCount;
1584                                         cmd.okcount=0;
1585                                 }
1586                                 ++m_sec_sequence.current();
1587                                 break;
1588                         }
1589                         case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1590                                 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1591                                         setSecSequencePos(m_sec_sequence.current()->steps);
1592                                 else
1593                                         ++m_sec_sequence.current();
1594                                 break;
1595                         case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1596                                 eDebugNoSimulate("[SEC] invalidate current switch params");
1597                                 sec_fe_data[CSW] = -1;
1598                                 sec_fe_data[UCSW] = -1;
1599                                 sec_fe_data[TONEBURST] = -1;
1600                                 ++m_sec_sequence.current();
1601                                 break;
1602                         case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1603                                 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1604                                 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1605                                 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1606                                 eDebugNoSimulate("[SEC] update current switch params");
1607                                 ++m_sec_sequence.current();
1608                                 break;
1609                         case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1610                                 eDebugNoSimulate("[SEC] invalidate current rotorparams");
1611                                 sec_fe_data[ROTOR_CMD] = -1;
1612                                 sec_fe_data[ROTOR_POS] = -1;
1613                                 ++m_sec_sequence.current();
1614                                 break;
1615                         case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1616                                 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1617                                 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1618                                 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1619                                 ++m_sec_sequence.current();
1620                                 break;
1621                         case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1622                                 m_retryCount = m_sec_sequence.current()++->val;
1623                                 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
1624                                 break;
1625                         case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1626                                 if (!m_retryCount)
1627                                 {
1628                                         eDebugNoSimulate("[SEC] no more rotor retrys");
1629                                         setSecSequencePos(m_sec_sequence.current()->steps);
1630                                 }
1631                                 else
1632                                         ++m_sec_sequence.current();
1633                                 break;
1634                         case eSecCommand::SET_POWER_LIMITING_MODE:
1635                         {
1636                                 if (!m_simulate)
1637                                 {
1638                                         char proc_name[64];
1639                                         sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1640                                         FILE *f=fopen(proc_name, "w");
1641                                         if (f) // new interface exist?
1642                                         {
1643                                                 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1644                                                 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1645                                                         eDebugNoSimulate("write %s failed!! (%m)", proc_name);
1646                                                 else
1647                                                         eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
1648                                                 fclose(f);
1649                                         }
1650                                         else if (sec_fe->m_need_rotor_workaround)
1651                                         {
1652                                                 char dev[16];
1653                                                 int slotid = sec_fe->m_slotid;
1654                                                 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1655                                                 if (slotid < 2)
1656                                                         sprintf(dev, "/dev/i2c/%d", slotid);
1657                                                 else if (slotid == 2)
1658                                                         sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
1659                                                 else if (slotid == 3)
1660                                                         sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
1661                                                 int fd = ::open(dev, O_RDWR);
1662
1663                                                 unsigned char data[2];
1664                                                 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1665                                                 if(::read(fd, data, 1) != 1)
1666                                                         eDebugNoSimulate("[SEC] error read lnbp (%m)");
1667                                                 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1668                                                 {
1669                                                         data[0] |= 0x80;  // enable static current limiting
1670                                                         eDebugNoSimulate("[SEC] set static current limiting");
1671                                                 }
1672                                                 else
1673                                                 {
1674                                                         data[0] &= ~0x80;  // enable dynamic current limiting
1675                                                         eDebugNoSimulate("[SEC] set dynamic current limiting");
1676                                                 }
1677                                                 if(::write(fd, data, 1) != 1)
1678                                                         eDebugNoSimulate("[SEC] error write lnbp (%m)");
1679                                                 ::close(fd);
1680                                         }
1681                                 }
1682                                 ++m_sec_sequence.current();
1683                                 break;
1684                         }
1685                         default:
1686                                 eDebugNoSimulate("[SEC] unhandled sec command %d",
1687                                         ++m_sec_sequence.current()->cmd);
1688                                 ++m_sec_sequence.current();
1689                 }
1690                 if (!m_simulate)
1691                         m_tuneTimer->start(delay,true);
1692         }
1693         if (regFE)
1694                 regFE->dec_use();
1695         if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1696                 tuneLoop();
1697 }
1698
1699 void eDVBFrontend::setFrontend()
1700 {
1701         if (!m_simulate)
1702         {
1703                 eDebug("setting frontend %d", m_dvbid);
1704                 m_sn->start();
1705                 feEvent(-1);
1706                 if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1707                 {
1708                         perror("FE_SET_FRONTEND failed");
1709                         return;
1710                 }
1711         }
1712 }
1713
1714 RESULT eDVBFrontend::getFrontendType(int &t)
1715 {
1716         if (m_type == -1)
1717                 return -ENODEV;
1718         t = m_type;
1719         return 0;
1720 }
1721
1722 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1723 {
1724         int res;
1725         if (!m_sec)
1726         {
1727                 eWarning("no SEC module active!");
1728                 return -ENOENT;
1729         }
1730         res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
1731         if (!res)
1732         {
1733 #if HAVE_DVB_API_VERSION >= 3
1734                 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",
1735                         feparm.system,
1736                         feparm.frequency,
1737                         feparm.polarisation,
1738                         feparm.symbol_rate,
1739                         feparm.inversion,
1740                         feparm.fec,
1741                         feparm.orbital_position,
1742                         feparm.system,
1743                         feparm.modulation,
1744                         feparm.pilot,
1745                         feparm.rolloff);
1746 #else
1747                 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
1748                         feparm.system,
1749                         feparm.frequency,
1750                         feparm.polarisation,
1751                         feparm.symbol_rate,
1752                         feparm.inversion,
1753                         feparm.fec,
1754                         feparm.orbital_position);
1755 #endif
1756                 m_cur_pol = feparm.polarisation;
1757                 m_cur_orbpos = feparm.orbital_position;
1758                 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1759                 switch (feparm.inversion)
1760                 {
1761                         case eDVBFrontendParametersSatellite::Inversion_On:
1762                                 parm_inversion = INVERSION_ON;
1763                                 break;
1764                         case eDVBFrontendParametersSatellite::Inversion_Off:
1765                                 parm_inversion = INVERSION_OFF;
1766                                 break;
1767                         default:
1768                         case eDVBFrontendParametersSatellite::Inversion_Unknown:
1769                                 parm_inversion = INVERSION_AUTO;
1770                                 break;
1771                 }
1772                 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S)
1773                         switch (feparm.fec)
1774                         {
1775                                 case eDVBFrontendParametersSatellite::FEC_None:
1776                                         parm_u_qpsk_fec_inner = FEC_NONE;
1777                                         break;
1778                                 case eDVBFrontendParametersSatellite::FEC_1_2:
1779                                         parm_u_qpsk_fec_inner = FEC_1_2;
1780                                         break;
1781                                 case eDVBFrontendParametersSatellite::FEC_2_3:
1782                                         parm_u_qpsk_fec_inner = FEC_2_3;
1783                                         break;
1784                                 case eDVBFrontendParametersSatellite::FEC_3_4:
1785                                         parm_u_qpsk_fec_inner = FEC_3_4;
1786                                         break;
1787                                 case eDVBFrontendParametersSatellite::FEC_5_6:
1788                                         parm_u_qpsk_fec_inner = FEC_5_6;
1789                                         break;
1790                                 case eDVBFrontendParametersSatellite::FEC_7_8:
1791                                         parm_u_qpsk_fec_inner = FEC_7_8;
1792                                         break;
1793                                 default:
1794                                         eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
1795                                 case eDVBFrontendParametersSatellite::FEC_Auto:
1796                                         parm_u_qpsk_fec_inner = FEC_AUTO;
1797                                         break;
1798                         }
1799 #if HAVE_DVB_API_VERSION >= 3
1800                 else // DVB_S2
1801                 {
1802                         switch (feparm.fec)
1803                         {
1804                                 case eDVBFrontendParametersSatellite::FEC_1_2:
1805                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
1806                                         break;
1807                                 case eDVBFrontendParametersSatellite::FEC_2_3:
1808                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
1809                                         break;
1810                                 case eDVBFrontendParametersSatellite::FEC_3_4:
1811                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
1812                                         break;
1813                                 case eDVBFrontendParametersSatellite::FEC_3_5:
1814                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
1815                                         break;
1816                                 case eDVBFrontendParametersSatellite::FEC_4_5:
1817                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
1818                                         break;
1819                                 case eDVBFrontendParametersSatellite::FEC_5_6:
1820                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
1821                                         break;
1822                                 case eDVBFrontendParametersSatellite::FEC_7_8:
1823                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
1824                                         break;
1825                                 case eDVBFrontendParametersSatellite::FEC_8_9:
1826                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
1827                                         break;
1828                                 case eDVBFrontendParametersSatellite::FEC_9_10:
1829                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
1830                                         break;
1831                                 default:
1832                                         eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
1833                                         return -EINVAL;
1834                         }
1835                         parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
1836                         parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
1837                         if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation_8PSK) {
1838                                 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
1839                                 // 8PSK fec driver values are decimal 9 bigger
1840                         }
1841                 }
1842 #endif
1843                 // FIXME !!! get frequency range from tuner
1844                 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1845                 {
1846                         eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1847                         return -EINVAL;
1848                 }
1849                 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
1850         }
1851         return res;
1852 }
1853
1854 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1855 {
1856 #if HAVE_DVB_API_VERSION < 3
1857         parm_frequency = feparm.frequency;
1858 #else
1859         parm_frequency = feparm.frequency * 1000;
1860 #endif
1861         parm_u_qam_symbol_rate = feparm.symbol_rate;
1862         switch (feparm.modulation)
1863         {
1864         case eDVBFrontendParametersCable::Modulation_QAM16:
1865                 parm_u_qam_modulation = QAM_16;
1866                 break;
1867         case eDVBFrontendParametersCable::Modulation_QAM32:
1868                 parm_u_qam_modulation = QAM_32;
1869                 break;
1870         case eDVBFrontendParametersCable::Modulation_QAM64:
1871                 parm_u_qam_modulation = QAM_64;
1872                 break;
1873         case eDVBFrontendParametersCable::Modulation_QAM128:
1874                 parm_u_qam_modulation = QAM_128;
1875                 break;
1876         case eDVBFrontendParametersCable::Modulation_QAM256:
1877                 parm_u_qam_modulation = QAM_256;
1878                 break;
1879         default:
1880         case eDVBFrontendParametersCable::Modulation_Auto:
1881                 parm_u_qam_modulation = QAM_AUTO;
1882                 break;
1883         }
1884         switch (feparm.inversion)
1885         {
1886         case eDVBFrontendParametersCable::Inversion_On:
1887                 parm_inversion = INVERSION_ON;
1888                 break;
1889         case eDVBFrontendParametersCable::Inversion_Off:
1890                 parm_inversion = INVERSION_OFF;
1891                 break;
1892         default:
1893         case eDVBFrontendParametersCable::Inversion_Unknown:
1894                 parm_inversion = INVERSION_AUTO;
1895                 break;
1896         }
1897         switch (feparm.fec_inner)
1898         {
1899         case eDVBFrontendParametersCable::FEC_None:
1900                 parm_u_qam_fec_inner = FEC_NONE;
1901                 break;
1902         case eDVBFrontendParametersCable::FEC_1_2:
1903                 parm_u_qam_fec_inner = FEC_1_2;
1904                 break;
1905         case eDVBFrontendParametersCable::FEC_2_3:
1906                 parm_u_qam_fec_inner = FEC_2_3;
1907                 break;
1908         case eDVBFrontendParametersCable::FEC_3_4:
1909                 parm_u_qam_fec_inner = FEC_3_4;
1910                 break;
1911         case eDVBFrontendParametersCable::FEC_5_6:
1912                 parm_u_qam_fec_inner = FEC_5_6;
1913                 break;
1914         case eDVBFrontendParametersCable::FEC_7_8:
1915                 parm_u_qam_fec_inner = FEC_7_8;
1916                 break;
1917 #if HAVE_DVB_API_VERSION >= 3
1918         case eDVBFrontendParametersCable::FEC_8_9:
1919                 parm_u_qam_fec_inner = FEC_8_9;
1920                 break;
1921 #endif
1922         default:
1923         case eDVBFrontendParametersCable::FEC_Auto:
1924                 parm_u_qam_fec_inner = FEC_AUTO;
1925                 break;
1926         }
1927         eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
1928                 parm_frequency/1000,
1929                 parm_u_qam_symbol_rate,
1930                 parm_u_qam_fec_inner,
1931                 parm_u_qam_modulation,
1932                 parm_inversion);
1933         return 0;
1934 }
1935
1936 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
1937 {
1938         parm_frequency = feparm.frequency;
1939
1940         switch (feparm.bandwidth)
1941         {
1942         case eDVBFrontendParametersTerrestrial::Bandwidth_8MHz:
1943                 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
1944                 break;
1945         case eDVBFrontendParametersTerrestrial::Bandwidth_7MHz:
1946                 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
1947                 break;
1948         case eDVBFrontendParametersTerrestrial::Bandwidth_6MHz:
1949                 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
1950                 break;
1951         default:
1952         case eDVBFrontendParametersTerrestrial::Bandwidth_Auto:
1953                 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
1954                 break;
1955         }
1956         switch (feparm.code_rate_LP)
1957         {
1958         case eDVBFrontendParametersTerrestrial::FEC_1_2:
1959                 parm_u_ofdm_code_rate_LP = FEC_1_2;
1960                 break;
1961         case eDVBFrontendParametersTerrestrial::FEC_2_3:
1962                 parm_u_ofdm_code_rate_LP = FEC_2_3;
1963                 break;
1964         case eDVBFrontendParametersTerrestrial::FEC_3_4:
1965                 parm_u_ofdm_code_rate_LP = FEC_3_4;
1966                 break;
1967         case eDVBFrontendParametersTerrestrial::FEC_5_6:
1968                 parm_u_ofdm_code_rate_LP = FEC_5_6;
1969                 break;
1970         case eDVBFrontendParametersTerrestrial::FEC_7_8:
1971                 parm_u_ofdm_code_rate_LP = FEC_7_8;
1972                 break;
1973         default:
1974         case eDVBFrontendParametersTerrestrial::FEC_Auto:
1975                 parm_u_ofdm_code_rate_LP = FEC_AUTO;
1976                 break;
1977         }
1978         switch (feparm.code_rate_HP)
1979         {
1980         case eDVBFrontendParametersTerrestrial::FEC_1_2:
1981                 parm_u_ofdm_code_rate_HP = FEC_1_2;
1982                 break;
1983         case eDVBFrontendParametersTerrestrial::FEC_2_3:
1984                 parm_u_ofdm_code_rate_HP = FEC_2_3;
1985                 break;
1986         case eDVBFrontendParametersTerrestrial::FEC_3_4:
1987                 parm_u_ofdm_code_rate_HP = FEC_3_4;
1988                 break;
1989         case eDVBFrontendParametersTerrestrial::FEC_5_6:
1990                 parm_u_ofdm_code_rate_HP = FEC_5_6;
1991                 break;
1992         case eDVBFrontendParametersTerrestrial::FEC_7_8:
1993                 parm_u_ofdm_code_rate_HP = FEC_7_8;
1994                 break;
1995         default:
1996         case eDVBFrontendParametersTerrestrial::FEC_Auto:
1997                 parm_u_ofdm_code_rate_HP = FEC_AUTO;
1998                 break;
1999         }
2000         switch (feparm.modulation)
2001         {
2002         case eDVBFrontendParametersTerrestrial::Modulation_QPSK:
2003                 parm_u_ofdm_constellation = QPSK;
2004                 break;
2005         case eDVBFrontendParametersTerrestrial::Modulation_QAM16:
2006                 parm_u_ofdm_constellation = QAM_16;
2007                 break;
2008         case eDVBFrontendParametersTerrestrial::Modulation_QAM64:
2009                 parm_u_ofdm_constellation = QAM_64;
2010                 break;
2011         default:
2012         case eDVBFrontendParametersTerrestrial::Modulation_Auto:
2013                 parm_u_ofdm_constellation = QAM_AUTO;
2014                 break;
2015         }
2016         switch (feparm.transmission_mode)
2017         {
2018         case eDVBFrontendParametersTerrestrial::TransmissionMode_2k:
2019                 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2020                 break;
2021         case eDVBFrontendParametersTerrestrial::TransmissionMode_8k:
2022                 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2023                 break;
2024         default:
2025         case eDVBFrontendParametersTerrestrial::TransmissionMode_Auto:
2026                 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2027                 break;
2028         }
2029         switch (feparm.guard_interval)
2030         {
2031                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_32:
2032                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2033                         break;
2034                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_16:
2035                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2036                         break;
2037                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_8:
2038                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2039                         break;
2040                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_4:
2041                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2042                         break;
2043                 default:
2044                 case eDVBFrontendParametersTerrestrial::GuardInterval_Auto:
2045                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2046                         break;
2047         }
2048         switch (feparm.hierarchy)
2049         {
2050                 case eDVBFrontendParametersTerrestrial::Hierarchy_None:
2051                         parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2052                         break;
2053                 case eDVBFrontendParametersTerrestrial::Hierarchy_1:
2054                         parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2055                         break;
2056                 case eDVBFrontendParametersTerrestrial::Hierarchy_2:
2057                         parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2058                         break;
2059                 case eDVBFrontendParametersTerrestrial::Hierarchy_4:
2060                         parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2061                         break;
2062                 default:
2063                 case eDVBFrontendParametersTerrestrial::Hierarchy_Auto:
2064                         parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2065                         break;
2066         }
2067         switch (feparm.inversion)
2068         {
2069         case eDVBFrontendParametersTerrestrial::Inversion_On:
2070                 parm_inversion = INVERSION_ON;
2071                 break;
2072         case eDVBFrontendParametersTerrestrial::Inversion_Off:
2073                 parm_inversion = INVERSION_OFF;
2074                 break;
2075         default:
2076         case eDVBFrontendParametersTerrestrial::Inversion_Unknown:
2077                 parm_inversion = INVERSION_AUTO;
2078                 break;
2079         }
2080         return 0;
2081 }
2082
2083 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2084 {
2085         unsigned int timeout = 5000;
2086         eDebugNoSimulate("(%d)tune", m_dvbid);
2087
2088         m_timeout->stop();
2089
2090         int res=0;
2091
2092         if (!m_sn && !m_simulate)
2093         {
2094                 eDebug("no frontend device opened... do not try to tune !!!");
2095                 res = -ENODEV;
2096                 goto tune_error;
2097         }
2098
2099         if (m_type == -1)
2100         {
2101                 res = -ENODEV;
2102                 goto tune_error;
2103         }
2104
2105         if (!m_simulate)
2106                 m_sn->stop();
2107
2108         m_sec_sequence.clear();
2109
2110         where.calcLockTimeout(timeout);
2111
2112         switch (m_type)
2113         {
2114         case feSatellite:
2115         {
2116                 eDVBFrontendParametersSatellite feparm;
2117                 if (where.getDVBS(feparm))
2118                 {
2119                         eDebug("no dvbs data!");
2120                         res = -EINVAL;
2121                         goto tune_error;
2122                 }
2123                 if (!m_simulate)
2124                         m_sec->setRotorMoving(false);
2125                 res=prepare_sat(feparm, timeout);
2126                 if (res)
2127                         goto tune_error;
2128
2129                 break;
2130         }
2131         case feCable:
2132         {
2133                 eDVBFrontendParametersCable feparm;
2134                 if (where.getDVBC(feparm))
2135                 {
2136                         res = -EINVAL;
2137                         goto tune_error;
2138                 }
2139                 res=prepare_cable(feparm);
2140                 if (res)
2141                         goto tune_error;
2142
2143                 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2144                 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2145                 break;
2146         }
2147         case feTerrestrial:
2148         {
2149                 eDVBFrontendParametersTerrestrial feparm;
2150                 if (where.getDVBT(feparm))
2151                 {
2152                         eDebug("no -T data");
2153                         res = -EINVAL;
2154                         goto tune_error;
2155                 }
2156                 res=prepare_terrestrial(feparm);
2157                 if (res)
2158                         goto tune_error;
2159
2160                 std::string enable_5V;
2161                 char configStr[255];
2162                 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2163                 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2164                 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2165                 if (enable_5V == "True")
2166                         m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2167                 else
2168                         m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2169                 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
2170
2171                 break;
2172         }
2173         }
2174
2175         m_sec_sequence.current() = m_sec_sequence.begin();
2176
2177         if (!m_simulate)
2178         {
2179                 m_tuneTimer->start(0,true);
2180                 if (m_state != stateTuning)
2181                 {
2182                         m_tuning = 1;
2183                         m_state = stateTuning;
2184                         m_stateChanged(this);
2185                 }
2186         }
2187         else
2188                 tuneLoop();
2189
2190         return res;
2191
2192 tune_error:
2193         m_tuneTimer->stop();
2194         return res;
2195 }
2196
2197 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2198 {
2199         connection = new eConnection(this, m_stateChanged.connect(stateChange));
2200         return 0;
2201 }
2202
2203 RESULT eDVBFrontend::setVoltage(int voltage)
2204 {
2205         if (m_type == feCable)
2206                 return -1;
2207 #if HAVE_DVB_API_VERSION < 3
2208         secVoltage vlt;
2209 #else
2210         bool increased=false;
2211         fe_sec_voltage_t vlt;
2212 #endif
2213         m_data[CUR_VOLTAGE]=voltage;
2214         switch (voltage)
2215         {
2216         case voltageOff:
2217                 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2218                 vlt = SEC_VOLTAGE_OFF;
2219                 break;
2220         case voltage13_5:
2221 #if HAVE_DVB_API_VERSION < 3
2222                 vlt = SEC_VOLTAGE_13_5;
2223                 break;
2224 #else
2225                 increased = true;
2226 #endif
2227         case voltage13:
2228                 vlt = SEC_VOLTAGE_13;
2229                 break;
2230         case voltage18_5:
2231 #if HAVE_DVB_API_VERSION < 3
2232                 vlt = SEC_VOLTAGE_18_5;
2233                 break;
2234 #else
2235                 increased = true;
2236 #endif
2237         case voltage18:
2238                 vlt = SEC_VOLTAGE_18;
2239                 break;
2240         default:
2241                 return -ENODEV;
2242         }
2243         if (m_simulate)
2244                 return 0;
2245 #if HAVE_DVB_API_VERSION < 3
2246         return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2247 #else
2248         if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2249                 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2250         return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2251 #endif
2252 }
2253
2254 RESULT eDVBFrontend::getState(int &state)
2255 {
2256         state = m_state;
2257         return 0;
2258 }
2259
2260 RESULT eDVBFrontend::setTone(int t)
2261 {
2262         if (m_type != feSatellite)
2263                 return -1;
2264 #if HAVE_DVB_API_VERSION < 3
2265         secToneMode_t tone;
2266 #else
2267         fe_sec_tone_mode_t tone;
2268 #endif
2269         m_data[CUR_TONE]=t;
2270         switch (t)
2271         {
2272         case toneOn:
2273                 tone = SEC_TONE_ON;
2274                 break;
2275         case toneOff:
2276                 tone = SEC_TONE_OFF;
2277                 break;
2278         default:
2279                 return -ENODEV;
2280         }
2281         if (m_simulate)
2282                 return 0;
2283 #if HAVE_DVB_API_VERSION < 3    
2284         return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2285 #else   
2286         return ::ioctl(m_fd, FE_SET_TONE, tone);
2287 #endif
2288 }
2289
2290 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2291         #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2292 #endif
2293
2294 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2295 {
2296         if (m_simulate)
2297                 return 0;
2298 #if HAVE_DVB_API_VERSION < 3
2299         struct secCommand cmd;
2300         cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2301         cmd.u.diseqc.cmdtype = diseqc.data[0];
2302         cmd.u.diseqc.addr = diseqc.data[1];
2303         cmd.u.diseqc.cmd = diseqc.data[2];
2304         cmd.u.diseqc.numParams = diseqc.len-3;
2305         memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
2306         if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
2307 #else
2308         struct dvb_diseqc_master_cmd cmd;
2309         memcpy(cmd.msg, diseqc.data, diseqc.len);
2310         cmd.msg_len = diseqc.len;
2311         if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2312 #endif
2313                 return -EINVAL;
2314         return 0;
2315 }
2316
2317 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
2318         #define SEC_DISEQC_SEND_BURST _IO('o', 96)
2319 #endif
2320 RESULT eDVBFrontend::sendToneburst(int burst)
2321 {
2322         if (m_simulate)
2323                 return 0;
2324 #if HAVE_DVB_API_VERSION < 3
2325         secMiniCmd cmd = SEC_MINI_NONE;
2326 #else
2327         fe_sec_mini_cmd_t cmd = SEC_MINI_A;
2328 #endif
2329         if ( burst == eDVBSatelliteDiseqcParameters::A )
2330                 cmd = SEC_MINI_A;
2331         else if ( burst == eDVBSatelliteDiseqcParameters::B )
2332                 cmd = SEC_MINI_B;
2333 #if HAVE_DVB_API_VERSION < 3
2334         if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
2335                 return -EINVAL;
2336 #else
2337         if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2338                 return -EINVAL;
2339 #endif
2340         return 0;
2341 }
2342
2343 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2344 {
2345         m_sec = sec;
2346         return 0;
2347 }
2348
2349 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
2350 {
2351         m_sec_sequence = list;
2352         return 0;
2353 }
2354
2355 RESULT eDVBFrontend::getData(int num, long &data)
2356 {
2357         if ( num < NUM_DATA_ENTRIES )
2358         {
2359                 data = m_data[num];
2360                 return 0;
2361         }
2362         return -EINVAL;
2363 }
2364
2365 RESULT eDVBFrontend::setData(int num, long val)
2366 {
2367         if ( num < NUM_DATA_ENTRIES )
2368         {
2369                 m_data[num] = val;
2370                 return 0;
2371         }
2372         return -EINVAL;
2373 }
2374
2375 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2376 {
2377         int type;
2378         if (feparm->getSystem(type) || type != m_type || !m_enabled)
2379                 return 0;
2380         if (m_type == eDVBFrontend::feSatellite)
2381         {
2382                 ASSERT(m_sec);
2383                 eDVBFrontendParametersSatellite sat_parm;
2384                 int ret = feparm->getDVBS(sat_parm);
2385                 ASSERT(!ret);
2386                 if (sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S2 && !m_can_handle_dvbs2)
2387                         return 0;
2388                 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
2389                 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S && m_can_handle_dvbs2)
2390                         ret -= 1;
2391                 return ret;
2392         }
2393         else if (m_type == eDVBFrontend::feCable)
2394                 return 2;  // more prio for cable frontends
2395         else if (m_type == eDVBFrontend::feTerrestrial)
2396                 return 1;
2397         return 0;
2398 }
2399
2400 bool eDVBFrontend::setSlotInfo(ePyObject obj)
2401 {
2402         ePyObject Id, Descr, Enabled, IsDVBS2;
2403         if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4)
2404                 goto arg_error;
2405         Id = PyTuple_GET_ITEM(obj, 0);
2406         Descr = PyTuple_GET_ITEM(obj, 1);
2407         Enabled = PyTuple_GET_ITEM(obj, 2);
2408         IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
2409         if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2))
2410                 goto arg_error;
2411         strcpy(m_description, PyString_AS_STRING(Descr));
2412         m_slotid = PyInt_AsLong(Id);
2413         m_enabled = Enabled == Py_True;
2414         // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2415         m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2416                 !!strstr(m_description, "Alps BSBE2") ||
2417                 !!strstr(m_description, "Alps -S") ||
2418                 !!strstr(m_description, "BCM4501");
2419         m_can_handle_dvbs2 = IsDVBS2 == Py_True;
2420         eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2421                 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", m_can_handle_dvbs2 ? "Yes" : "No" );
2422         return true;
2423 arg_error:
2424         PyErr_SetString(PyExc_StandardError,
2425                 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");
2426         return false;
2427 }
2428
2429 RESULT eDVBFrontend::turnOffSatCR(int satcr)
2430 {
2431         eSecCommandList sec_sequence;
2432         // check if voltage is disabled
2433         eSecCommand::pair compare;
2434         compare.steps = +9;     //nothing to do
2435         compare.voltage = iDVBFrontend::voltageOff;
2436         sec_sequence.push_back( eSecCommand(eSecCommand::IF_NOT_VOLTAGE_GOTO, compare) );
2437         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2438         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50 ) );
2439
2440         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage18_5) );
2441         sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
2442         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 250) );
2443
2444         eDVBDiseqcCommand diseqc;
2445         memset(diseqc.data, 0, MAX_DISEQC_LENGTH);
2446         diseqc.len = 5;
2447         diseqc.data[0] = 0xE0;
2448         diseqc.data[1] = 0x10;
2449         diseqc.data[2] = 0x5A;
2450         diseqc.data[3] = satcr << 5;
2451         diseqc.data[4] = 0x00;
2452
2453         sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
2454         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50+20+14*diseqc.len) );
2455         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2456         setSecSequence(sec_sequence);
2457         return 0;
2458 }
2459
2460 RESULT eDVBFrontend::ScanSatCR()
2461 {
2462         setFrontend();
2463         usleep(20000);
2464         setTone(iDVBFrontend::toneOff);
2465         return 0;
2466 }