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