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