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