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