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