Support Uno4k/Ultimo4k
[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)
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         }
1057         return 0;
1058 }
1059
1060 void PutToDict(ePyObject &dict, const char*key, long value)
1061 {
1062         ePyObject item = PyInt_FromLong(value);
1063         if (item)
1064         {
1065                 if (PyDict_SetItemString(dict, key, item))
1066                         eDebug("put %s to dict failed", key);
1067                 Py_DECREF(item);
1068         }
1069         else
1070                 eDebug("could not create PyObject for %s", key);
1071 }
1072
1073 void PutToDict(ePyObject &dict, const char*key, ePyObject item)
1074 {
1075         if (item)
1076         {
1077                 if (PyDict_SetItemString(dict, key, item))
1078                         eDebug("put %s to dict failed", key);
1079                 Py_DECREF(item);
1080         }
1081         else
1082                 eDebug("invalid PyObject for %s", key);
1083 }
1084
1085 void PutToDict(ePyObject &dict, const char*key, const char *value)
1086 {
1087         ePyObject item = PyString_FromString(value);
1088         if (item)
1089         {
1090                 if (PyDict_SetItemString(dict, key, item))
1091                         eDebug("put %s to dict failed", key);
1092                 Py_DECREF(item);
1093         }
1094         else
1095                 eDebug("could not create PyObject for %s", key);
1096 }
1097
1098 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
1099 {
1100         PutToDict(dict, "tuner_type", "DVB-S");
1101         PutToDict(dict, "frequency", feparm.frequency);
1102         PutToDict(dict, "symbol_rate", feparm.symbol_rate);
1103         PutToDict(dict, "orbital_position", feparm.orbital_position);
1104         PutToDict(dict, "inversion", feparm.inversion);
1105         PutToDict(dict, "fec_inner", feparm.fec);
1106         PutToDict(dict, "modulation", feparm.modulation);
1107         PutToDict(dict, "polarization", feparm.polarisation);
1108         if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S2)
1109         {
1110                 PutToDict(dict, "rolloff", feparm.rolloff);
1111                 PutToDict(dict, "pilot", feparm.pilot);
1112         }
1113         PutToDict(dict, "system", feparm.system);
1114 }
1115
1116 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
1117 {
1118         PutToDict(dict, "tuner_type", "DVB-T");
1119         PutToDict(dict, "frequency", feparm.frequency);
1120         PutToDict(dict, "bandwidth", feparm.bandwidth);
1121         PutToDict(dict, "code_rate_lp", feparm.code_rate_LP);
1122         PutToDict(dict, "code_rate_hp", feparm.code_rate_HP);
1123         PutToDict(dict, "constellation", feparm.modulation);
1124         PutToDict(dict, "transmission_mode", feparm.transmission_mode);
1125         PutToDict(dict, "guard_interval", feparm.guard_interval);
1126         PutToDict(dict, "hierarchy_information", feparm.hierarchy);
1127         PutToDict(dict, "inversion", feparm.inversion);
1128         PutToDict(dict, "system", feparm.system);
1129         if (feparm.system == eDVBFrontendParametersTerrestrial::System_DVB_T2)
1130         {
1131                 PutToDict(dict, "plp_id", feparm.plpid);
1132         }
1133 }
1134
1135 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
1136 {
1137         PutToDict(dict, "tuner_type", "DVB-C");
1138         PutToDict(dict, "frequency", feparm.frequency);
1139         PutToDict(dict, "symbol_rate", feparm.symbol_rate);
1140         PutToDict(dict, "modulation", feparm.modulation);
1141         PutToDict(dict, "inversion", feparm.inversion);
1142         PutToDict(dict, "fec_inner", feparm.fec_inner);
1143 }
1144
1145 #if HAVE_DVB_API_VERSION >= 5
1146 static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, struct dtv_property *p, long freq_offset, int orb_pos, int polarization)
1147 {
1148         long tmp=0;
1149         int frequency = parm_frequency + freq_offset;
1150         PutToDict(dict, "frequency", frequency);
1151         PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
1152         PutToDict(dict, "orbital_position", orb_pos);
1153         PutToDict(dict, "polarization", polarization);
1154
1155         switch(parm_u_qpsk_fec_inner)
1156         {
1157         case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1158         case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1159         case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1160         case FEC_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
1161         case FEC_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
1162         case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1163         case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1164         case FEC_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
1165         case FEC_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1166         case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
1167         case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
1168         default: eDebug("got unsupported FEC from frontend! report as FEC_AUTO!\n");
1169         }
1170         PutToDict(dict, "fec_inner", tmp);
1171
1172         switch (p[0].u.data)
1173         {
1174         default: eDebug("got unsupported system from frontend! report as DVBS!");
1175         case SYS_DVBS: tmp = eDVBFrontendParametersSatellite::System_DVB_S; break;
1176         case SYS_DVBS2:
1177         {
1178                 switch (p[2].u.data)
1179                 {
1180                 default: eDebug("got unsupported rolloff from frontend! report as 0_20!");
1181                 case ROLLOFF_20: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1182                 case ROLLOFF_25: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1183                 case ROLLOFF_35: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1184                 }
1185                 PutToDict(dict, "rolloff", tmp);
1186
1187                 switch (p[3].u.data)
1188                 {
1189                 case PILOT_OFF: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1190                 case PILOT_ON: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1191                 case PILOT_AUTO: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1192                 }
1193                 PutToDict(dict, "pilot", tmp);
1194
1195                 tmp = eDVBFrontendParametersSatellite::System_DVB_S2; break;
1196         }
1197         }
1198         PutToDict(dict, "system", tmp);
1199
1200         switch (p[1].u.data)
1201         {
1202         default: eDebug("got unsupported modulation from frontend! report as QPSK!");
1203         case QPSK: tmp = eDVBFrontendParametersSatellite::Modulation_QPSK; break;
1204         case PSK_8: tmp = eDVBFrontendParametersSatellite::Modulation_8PSK; break;
1205         }
1206         PutToDict(dict, "modulation", tmp);
1207
1208         switch(parm_inversion & 3)
1209         {
1210                 case INVERSION_ON: tmp = eDVBFrontendParametersSatellite::Inversion_On; break;
1211                 case INVERSION_OFF: tmp = eDVBFrontendParametersSatellite::Inversion_Off; break;
1212                 default: tmp = eDVBFrontendParametersSatellite::Inversion_Unknown; break;
1213         }
1214         PutToDict(dict, "inversion", tmp);
1215 }
1216
1217 static void fillDictWithCableData(ePyObject dict, struct dtv_property *p)
1218 {
1219         long tmp = 0;
1220 // frequency
1221         tmp = p[1].u.data/1000;
1222         PutToDict(dict, "frequency", tmp);
1223 // sysbolrate
1224         PutToDict(dict, "symbol_rate", p[2].u.data);
1225 // inner fec
1226         switch (p[3].u.data)
1227         {
1228                 case FEC_NONE: tmp = eDVBFrontendParametersCable::FEC_None; break;
1229                 case FEC_1_2: tmp = eDVBFrontendParametersCable::FEC_1_2; break;
1230                 case FEC_2_3: tmp = eDVBFrontendParametersCable::FEC_2_3; break;
1231                 case FEC_3_4: tmp = eDVBFrontendParametersCable::FEC_3_4; break;
1232                 case FEC_5_6: tmp = eDVBFrontendParametersCable::FEC_5_6; break;
1233                 case FEC_7_8: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1234                 case FEC_8_9: tmp = eDVBFrontendParametersCable::FEC_8_9; break;
1235                 default:
1236                 case FEC_AUTO: tmp = eDVBFrontendParametersCable::FEC_Auto; break;
1237         }
1238         PutToDict(dict, "fec_inner", tmp);
1239 // modulation
1240         switch (p[4].u.data)
1241         {
1242                 case QAM_16: tmp = eDVBFrontendParametersCable::Modulation_QAM16; break;
1243                 case QAM_32: tmp = eDVBFrontendParametersCable::Modulation_QAM32; break;
1244                 case QAM_64: tmp = eDVBFrontendParametersCable::Modulation_QAM64; break;
1245                 case QAM_128: tmp = eDVBFrontendParametersCable::Modulation_QAM128; break;
1246                 case QAM_256: tmp = eDVBFrontendParametersCable::Modulation_QAM256; break;
1247                 default:
1248                 case QAM_AUTO: tmp = eDVBFrontendParametersCable::Modulation_Auto; break;
1249         }
1250         PutToDict(dict, "modulation", tmp);
1251 // inversion
1252         switch (p[5].u.data)
1253         {
1254                 case INVERSION_OFF: tmp = eDVBFrontendParametersTerrestrial::Inversion_Off; break;
1255                 case INVERSION_ON: tmp = eDVBFrontendParametersTerrestrial::Inversion_On; break;
1256                 default:
1257                 case INVERSION_AUTO: tmp = eDVBFrontendParametersTerrestrial::Inversion_Unknown; break;
1258         }
1259         PutToDict(dict, "inversion", tmp);
1260 }
1261
1262 static void fillDictWithTerrestrialData(ePyObject dict, struct dtv_property *p)
1263 {
1264         long tmp =0;
1265 // system
1266         switch (p[0].u.data)
1267         {
1268                 default: eDebug("got unsupported system from frontend! report as DVBT!");
1269                 case SYS_DVBT: tmp = eDVBFrontendParametersTerrestrial::System_DVB_T; break;
1270                 case SYS_DVBT2:
1271                 {
1272 #if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 3
1273                         tmp = p[10].u.data;
1274                         PutToDict(dict, "plp_id", tmp);
1275 #endif
1276                         tmp = eDVBFrontendParametersTerrestrial::System_DVB_T2; break;
1277                 }
1278         }
1279         PutToDict(dict, "system", tmp);
1280 // frequency
1281         tmp = p[1].u.data;
1282         PutToDict(dict, "frequency", tmp);
1283 // bandwidth
1284         switch (p[2].u.data)
1285         {
1286                 case 8000000: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_8MHz; break;
1287                 case 7000000: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_7MHz; break;
1288                 case 6000000: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_6MHz; break;
1289                 case 5000000: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_5MHz; break;
1290                 case 10000000: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_10MHz; break;
1291                 case 1712000: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_1_712MHz; break;
1292                 default:
1293                 case BANDWIDTH_AUTO: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_Auto; break;
1294         }
1295         PutToDict(dict, "bandwidth", tmp);
1296 // code rate LP
1297         switch (p[3].u.data)
1298         {
1299                 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1300                 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1301                 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1302                 case FEC_4_5: tmp = eDVBFrontendParametersTerrestrial::FEC_4_5; break;
1303                 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1304                 case FEC_6_7: tmp = eDVBFrontendParametersTerrestrial::FEC_6_7; break;
1305                 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1306                 case FEC_8_9: tmp = eDVBFrontendParametersTerrestrial::FEC_8_9; break;
1307                 default:
1308                 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1309         }
1310         PutToDict(dict, "code_rate_lp", tmp);
1311 // code rate HP
1312         switch (p[4].u.data)
1313         {
1314                 case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1315                 case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1316                 case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1317                 case FEC_4_5: tmp = eDVBFrontendParametersTerrestrial::FEC_4_5; break;
1318                 case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1319                 case FEC_6_7: tmp = eDVBFrontendParametersTerrestrial::FEC_6_7; break;
1320                 case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1321                 case FEC_8_9: tmp = eDVBFrontendParametersTerrestrial::FEC_8_9; break;
1322                 default:
1323                 case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1324         }
1325         PutToDict(dict, "code_rate_hp", tmp);
1326 // constellation
1327         switch (p[5].u.data)
1328         {
1329                 case QPSK: tmp = eDVBFrontendParametersTerrestrial::Modulation_QPSK; break;
1330                 case QAM_16: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM16; break;
1331                 case QAM_64: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM64; break;
1332                 case QAM_256: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM256; break;
1333                 default:
1334                 case QAM_AUTO: tmp = eDVBFrontendParametersTerrestrial::Modulation_Auto; break;
1335         }
1336         PutToDict(dict, "constellation", tmp);
1337
1338 // transmission
1339         switch (p[6].u.data)
1340         {
1341         case TRANSMISSION_MODE_1K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_1k; break;
1342         case TRANSMISSION_MODE_2K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_2k; break;
1343         case TRANSMISSION_MODE_4K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_4k; break;
1344         case TRANSMISSION_MODE_8K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_8k; break;
1345         case TRANSMISSION_MODE_16K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_16k; break;
1346         case TRANSMISSION_MODE_32K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_32k; break;
1347         default:
1348         case TRANSMISSION_MODE_AUTO: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto; break;
1349         }
1350         PutToDict(dict, "transmission_mode", tmp);
1351 // guard interval
1352         switch (p[7].u.data)
1353         {
1354                 case GUARD_INTERVAL_19_256: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_19_256; break;
1355                 case GUARD_INTERVAL_19_128: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_19_128; break;
1356                 case GUARD_INTERVAL_1_128: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_128; break;
1357                 case GUARD_INTERVAL_1_32: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_32; break;
1358                 case GUARD_INTERVAL_1_16: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_16; break;
1359                 case GUARD_INTERVAL_1_8: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_8; break;
1360                 case GUARD_INTERVAL_1_4: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_4; break;
1361                 default:
1362                 case GUARD_INTERVAL_AUTO: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_Auto; break;
1363         }
1364         PutToDict(dict, "guard_interval", tmp);
1365 // hierarchy
1366         switch (p[8].u.data)
1367         {
1368                 case HIERARCHY_NONE: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_None; break;
1369                 case HIERARCHY_1: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_1; break;
1370                 case HIERARCHY_2: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_2; break;
1371                 case HIERARCHY_4: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_4; break;
1372                 default:
1373                 case HIERARCHY_AUTO: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_Auto; break;
1374         }
1375         PutToDict(dict, "hierarchy_information", tmp);
1376 // inversion
1377         switch (p[9].u.data)
1378         {
1379                 case INVERSION_OFF: tmp = eDVBFrontendParametersTerrestrial::Inversion_Off;  break;
1380                 case INVERSION_ON: tmp = eDVBFrontendParametersTerrestrial::Inversion_On;  break;
1381                 default:
1382                 case INVERSION_AUTO: tmp = eDVBFrontendParametersTerrestrial::Inversion_Unknown;  break;
1383         }
1384         PutToDict(dict, "inversion", tmp);
1385 }
1386
1387 #else // #if HAVE_DVB_API_VERSION >= 5
1388 static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, long freq_offset, int orb_pos, int polarization)
1389 {
1390         long tmp=0;
1391         int frequency = parm_frequency + freq_offset;
1392         PutToDict(dict, "frequency", frequency);
1393         PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
1394         PutToDict(dict, "orbital_position", orb_pos);
1395         PutToDict(dict, "polarization", polarization);
1396
1397         switch((int)parm_u_qpsk_fec_inner)
1398         {
1399         case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1400         case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1401         case FEC_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1402         case FEC_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1403         case FEC_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1404         case FEC_NONE: tmp = eDVBFrontendParametersSatellite::FEC_None; break;
1405         default:
1406         case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
1407 #if HAVE_DVB_API_VERSION >=3
1408         case FEC_S2_8PSK_1_2:
1409         case FEC_S2_QPSK_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
1410         case FEC_S2_8PSK_2_3:
1411         case FEC_S2_QPSK_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
1412         case FEC_S2_8PSK_3_4:
1413         case FEC_S2_QPSK_3_4: tmp = eDVBFrontendParametersSatellite::FEC_3_4; break;
1414         case FEC_S2_8PSK_5_6:
1415         case FEC_S2_QPSK_5_6: tmp = eDVBFrontendParametersSatellite::FEC_5_6; break;
1416         case FEC_S2_8PSK_7_8:
1417         case FEC_S2_QPSK_7_8: tmp = eDVBFrontendParametersSatellite::FEC_7_8; break;
1418         case FEC_S2_8PSK_8_9:
1419         case FEC_S2_QPSK_8_9: tmp = eDVBFrontendParametersSatellite::FEC_8_9; break;
1420         case FEC_S2_8PSK_3_5:
1421         case FEC_S2_QPSK_3_5: tmp = eDVBFrontendParametersSatellite::FEC_3_5; break;
1422         case FEC_S2_8PSK_4_5:
1423         case FEC_S2_QPSK_4_5: tmp = eDVBFrontendParametersSatellite::FEC_4_5; break;
1424         case FEC_S2_8PSK_9_10:
1425         case FEC_S2_QPSK_9_10: tmp = eDVBFrontendParametersSatellite::FEC_9_10; break;
1426 #endif
1427         }
1428         PutToDict(dict, "fec_inner", tmp);
1429 #if HAVE_DVB_API_VERSION >=3
1430         PutToDict(dict, "modulation",
1431                 parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10 ?
1432                         eDVBFrontendParametersSatellite::Modulation_8PSK :
1433                         eDVBFrontendParametersSatellite::Modulation_QPSK );
1434         if (parm_u_qpsk_fec_inner > FEC_AUTO)
1435         {
1436                 switch(parm_inversion & 0xc)
1437                 {
1438                 default: // unknown rolloff
1439                 case 0: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_35; break;
1440                 case 4: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_25; break;
1441                 case 8: tmp = eDVBFrontendParametersSatellite::RollOff_alpha_0_20; break;
1442                 }
1443                 PutToDict(dict, "rolloff", tmp);
1444                 switch(parm_inversion & 0x30)
1445                 {
1446                 case 0: tmp = eDVBFrontendParametersSatellite::Pilot_Off; break;
1447                 case 0x10: tmp = eDVBFrontendParametersSatellite::Pilot_On; break;
1448                 case 0x20: tmp = eDVBFrontendParametersSatellite::Pilot_Unknown; break;
1449                 }
1450                 PutToDict(dict, "pilot", tmp);
1451                 tmp = eDVBFrontendParametersSatellite::System_DVB_S2;
1452         }
1453         else
1454                 tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1455 #else
1456         PutToDict(dict, "modulation", eDVBFrontendParametersSatellite::Modulation_QPSK );
1457         tmp = eDVBFrontendParametersSatellite::System_DVB_S;
1458 #endif
1459         PutToDict(dict, "system", tmp);
1460 }
1461
1462 static void fillDictWithCableData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1463 {
1464         long tmp=0;
1465 #if HAVE_DVB_API_VERSION < 3
1466         PutToDict(dict, "frequency", parm_frequency);
1467 #else
1468         PutToDict(dict, "frequency", parm_frequency/1000);
1469 #endif
1470         PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
1471         switch(parm_u_qam_fec_inner)
1472         {
1473         case FEC_NONE: tmp = eDVBFrontendParametersCable::FEC_None; break;
1474         case FEC_1_2: tmp = eDVBFrontendParametersCable::FEC_1_2; break;
1475         case FEC_2_3: tmp = eDVBFrontendParametersCable::FEC_2_3; break;
1476         case FEC_3_4: tmp = eDVBFrontendParametersCable::FEC_3_4; break;
1477         case FEC_5_6: tmp = eDVBFrontendParametersCable::FEC_5_6; break;
1478         case FEC_7_8: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1479 #if HAVE_DVB_API_VERSION >= 3
1480         case FEC_8_9: tmp = eDVBFrontendParametersCable::FEC_7_8; break;
1481 #endif
1482         default:
1483         case FEC_AUTO: tmp = eDVBFrontendParametersCable::FEC_Auto; break;
1484         }
1485         PutToDict(dict, "fec_inner", tmp);
1486         switch(parm_u_qam_modulation)
1487         {
1488         case QAM_16: tmp = eDVBFrontendParametersCable::Modulation_QAM16; break;
1489         case QAM_32: tmp = eDVBFrontendParametersCable::Modulation_QAM32; break;
1490         case QAM_64: tmp = eDVBFrontendParametersCable::Modulation_QAM64; break;
1491         case QAM_128: tmp = eDVBFrontendParametersCable::Modulation_QAM128; break;
1492         case QAM_256: tmp = eDVBFrontendParametersCable::Modulation_QAM256; break;
1493         default:
1494         case QAM_AUTO:   tmp = eDVBFrontendParametersCable::Modulation_Auto; break;
1495         }
1496         PutToDict(dict, "modulation", tmp);
1497 }
1498
1499 static void fillDictWithTerrestrialData(ePyObject dict, const FRONTENDPARAMETERS &parm)
1500 {
1501         long tmp=0;
1502         PutToDict(dict, "frequency", parm_frequency);
1503         switch (parm_u_ofdm_bandwidth)
1504         {
1505         case BANDWIDTH_8_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_8MHz; break;
1506         case BANDWIDTH_7_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_7MHz; break;
1507         case BANDWIDTH_6_MHZ: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_6MHz; break;
1508         default:
1509         case BANDWIDTH_AUTO: tmp = eDVBFrontendParametersTerrestrial::Bandwidth_Auto; break;
1510         }
1511         PutToDict(dict, "bandwidth", tmp);
1512         switch (parm_u_ofdm_code_rate_LP)
1513         {
1514         case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1515         case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1516         case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1517         case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1518         case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1519         default:
1520         case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1521         }
1522         PutToDict(dict, "code_rate_lp", tmp);
1523         switch (parm_u_ofdm_code_rate_HP)
1524         {
1525         case FEC_1_2: tmp = eDVBFrontendParametersTerrestrial::FEC_1_2; break;
1526         case FEC_2_3: tmp = eDVBFrontendParametersTerrestrial::FEC_2_3; break;
1527         case FEC_3_4: tmp = eDVBFrontendParametersTerrestrial::FEC_3_4; break;
1528         case FEC_5_6: tmp = eDVBFrontendParametersTerrestrial::FEC_5_6; break;
1529         case FEC_7_8: tmp = eDVBFrontendParametersTerrestrial::FEC_7_8; break;
1530         default:
1531         case FEC_AUTO: tmp = eDVBFrontendParametersTerrestrial::FEC_Auto; break;
1532         }
1533         PutToDict(dict, "code_rate_hp", tmp);
1534         switch (parm_u_ofdm_constellation)
1535         {
1536         case QPSK: tmp = eDVBFrontendParametersTerrestrial::Modulation_QPSK; break;
1537         case QAM_16: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM16; break;
1538         case QAM_64: tmp = eDVBFrontendParametersTerrestrial::Modulation_QAM64; break;
1539         default:
1540         case QAM_AUTO: tmp = eDVBFrontendParametersTerrestrial::Modulation_Auto; break;
1541         }
1542         PutToDict(dict, "constellation", tmp);
1543         switch (parm_u_ofdm_transmission_mode)
1544         {
1545         case TRANSMISSION_MODE_2K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_2k; break;
1546         case TRANSMISSION_MODE_8K: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_8k; break;
1547         default:
1548         case TRANSMISSION_MODE_AUTO: tmp = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto; break;
1549         }
1550         PutToDict(dict, "transmission_mode", tmp);
1551         switch (parm_u_ofdm_guard_interval)
1552         {
1553                 case GUARD_INTERVAL_1_32: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_32; break;
1554                 case GUARD_INTERVAL_1_16: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_16; break;
1555                 case GUARD_INTERVAL_1_8: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_8; break;
1556                 case GUARD_INTERVAL_1_4: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_1_4; break;
1557                 default:
1558                 case GUARD_INTERVAL_AUTO: tmp = eDVBFrontendParametersTerrestrial::GuardInterval_Auto; break;
1559         }
1560         PutToDict(dict, "guard_interval", tmp);
1561         switch (parm_u_ofdm_hierarchy_information)
1562         {
1563                 case HIERARCHY_NONE: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_None; break;
1564                 case HIERARCHY_1: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_1; break;
1565                 case HIERARCHY_2: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_2; break;
1566                 case HIERARCHY_4: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_4; break;
1567                 default:
1568                 case HIERARCHY_AUTO: tmp = eDVBFrontendParametersTerrestrial::Hierarchy_Auto; break;
1569         }
1570         PutToDict(dict, "hierarchy_information", tmp);
1571 }
1572
1573 #endif // #if HAVE_DVB_API_VERSION >= 5
1574
1575 void eDVBFrontend::getFrontendStatus(ePyObject dest)
1576 {
1577         if (dest && PyDict_Check(dest))
1578         {
1579                 const char *tmp = "UNKNOWN";
1580                 switch(m_state)
1581                 {
1582                         case stateIdle:
1583                                 tmp="IDLE";
1584                                 break;
1585                         case stateTuning:
1586                                 tmp="TUNING";
1587                                 break;
1588                         case stateFailed:
1589                                 tmp="FAILED";
1590                                 break;
1591                         case stateLock:
1592                                 tmp="LOCKED";
1593                                 break;
1594                         case stateLostLock:
1595                                 tmp="LOSTLOCK";
1596                                 break;
1597                         default:
1598                                 break;
1599                 }
1600                 PutToDict(dest, "tuner_state", tmp);
1601                 PutToDict(dest, "tuner_locked", readFrontendData(locked));
1602                 PutToDict(dest, "tuner_synced", readFrontendData(synced));
1603                 PutToDict(dest, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
1604                 PutToDict(dest, "tuner_signal_quality", readFrontendData(signalQuality));
1605                 int sigQualitydB = readFrontendData(signalQualitydB);
1606                 if (sigQualitydB == 0x12345678) // not support yet
1607                 {
1608                         ePyObject obj=Py_None;
1609                         Py_INCREF(obj);
1610                         PutToDict(dest, "tuner_signal_quality_db", obj);
1611                 }
1612                 else
1613                         PutToDict(dest, "tuner_signal_quality_db", sigQualitydB);
1614                 PutToDict(dest, "tuner_signal_power", readFrontendData(signalPower));
1615         }
1616 }
1617
1618 void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
1619 {
1620         if (dest && PyDict_Check(dest))
1621         {
1622                 int type = -1;
1623                 FRONTENDPARAMETERS front;
1624 #if HAVE_DVB_API_VERSION >= 5
1625                 struct dtv_property p[16];
1626                 struct dtv_properties cmdseq;
1627                 cmdseq.props = p;
1628                 cmdseq.num = 0;
1629                 oparm.getSystem(type);
1630                 switch(type)
1631                 {
1632                         case feSatellite:
1633                                 p[0].cmd = DTV_DELIVERY_SYSTEM;
1634                                 p[1].cmd = DTV_MODULATION;
1635                                 p[2].cmd = DTV_ROLLOFF;
1636                                 p[3].cmd = DTV_PILOT;
1637                                 cmdseq.num = 4;
1638                                 break;
1639                         case feCable:
1640                                 p[0].cmd = DTV_DELIVERY_SYSTEM;
1641                                 p[1].cmd = DTV_FREQUENCY;
1642                                 p[2].cmd = DTV_SYMBOL_RATE;
1643                                 p[3].cmd = DTV_INNER_FEC;
1644                                 p[4].cmd = DTV_MODULATION;
1645                                 p[5].cmd = DTV_INVERSION;
1646                                 cmdseq.num = 6;
1647                                 break;
1648                         case feTerrestrial:
1649                                 p[0].cmd = DTV_DELIVERY_SYSTEM;
1650                                 p[1].cmd = DTV_FREQUENCY;
1651                                 p[2].cmd = DTV_BANDWIDTH_HZ;
1652                                 p[3].cmd = DTV_CODE_RATE_LP;
1653                                 p[4].cmd = DTV_CODE_RATE_HP;
1654                                 p[5].cmd = DTV_MODULATION;
1655                                 p[6].cmd = DTV_TRANSMISSION_MODE;
1656                                 p[7].cmd = DTV_GUARD_INTERVAL;
1657                                 p[8].cmd = DTV_HIERARCHY;
1658                                 p[9].cmd = DTV_INVERSION;
1659 #if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 9
1660                                 p[10].cmd = DTV_STREAM_ID;
1661                                 cmdseq.num = 11;
1662 #elif DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 3
1663                                 p[10].cmd = DTV_DVBT2_PLP_ID;
1664                                 cmdseq.num = 11;
1665 #else
1666                                 cmdseq.num = 10;
1667 #endif
1668                                 break;
1669                 }
1670 #endif
1671                 if (m_simulate || m_fd == -1 || original)
1672                 {
1673                         original = true;
1674                 }
1675 #if HAVE_DVB_API_VERSION >= 5
1676                 else if (ioctl(m_fd, FE_GET_PROPERTY, &cmdseq)<0)
1677                 {
1678                         eDebug("FE_GET_PROPERTY failed (%m)");
1679                         original = true;
1680                 }
1681                 else if (type == feSatellite && // use for DVB-S(2) only
1682                         ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1683                 {
1684                         eDebug("FE_GET_FRONTEND failed (%m)");
1685                         original = true;
1686                 }
1687 #else
1688                 else if (ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
1689                 {
1690                         eDebug("FE_GET_FRONTEND failed (%m)");
1691                         original = true;
1692                 }
1693 #endif
1694                 if (original)
1695                 {
1696                         switch(type)
1697                         {
1698                                 case feSatellite:
1699                                         eDVBFrontendParametersSatellite sparm;
1700                                         oparm.getDVBS(sparm);
1701                                         PutSatelliteDataToDict(dest, sparm);
1702                                         break;
1703                                 case feCable:
1704                                         eDVBFrontendParametersCable cparm;
1705                                         oparm.getDVBC(cparm);
1706                                         PutCableDataToDict(dest, cparm);
1707                                         break;
1708                                 case feTerrestrial:
1709                                         eDVBFrontendParametersTerrestrial tparm;
1710                                         oparm.getDVBT(tparm);
1711                                         PutTerrestrialDataToDict(dest, tparm);
1712                                         break;
1713                         }
1714                 }
1715                 else
1716                 {
1717                         FRONTENDPARAMETERS &parm = front;
1718 #if HAVE_DVB_API_VERSION >= 5
1719                         switch(type)
1720                         {
1721                                 case feSatellite:
1722                                         eDVBFrontendParametersSatellite sparm;
1723                                         oparm.getDVBS(sparm);
1724                                         fillDictWithSatelliteData(dest, parm, p, m_data[FREQ_OFFSET], sparm.orbital_position, sparm.polarisation);
1725                                         break;
1726                                 case feCable:
1727                                         fillDictWithCableData(dest, p);
1728                                         break;
1729                                 case feTerrestrial:
1730                                         fillDictWithTerrestrialData(dest, p);
1731                                         break;
1732                         }
1733 #else
1734                         long tmp = eDVBFrontendParametersSatellite::Inversion_Unknown;
1735                         switch(parm_inversion & 3)
1736                         {
1737                                 case INVERSION_ON:
1738                                         tmp = eDVBFrontendParametersSatellite::Inversion_On;
1739                                         break;
1740                                 case INVERSION_OFF:
1741                                         tmp = eDVBFrontendParametersSatellite::Inversion_Off;
1742                                 default:
1743                                         break;
1744                         }
1745                         PutToDict(dest, "inversion", tmp);
1746                         switch(type)
1747                         {
1748                                 eDVBFrontendParametersSatellite sparm;
1749                                 oparm.getDVBS(sparm);
1750                                 case feSatellite:
1751                                         fillDictWithSatelliteData(dest, parm, m_data[FREQ_OFFSET], sparm.orbital_position, sparm.polarisation);
1752                                         break;
1753                                 case feCable:
1754                                         fillDictWithCableData(dest, parm);
1755                                         break;
1756                                 case feTerrestrial:
1757                                         fillDictWithTerrestrialData(dest, parm);
1758                                         break;
1759                         }
1760 #endif
1761                 }
1762         }
1763 }
1764
1765 void eDVBFrontend::getFrontendData(ePyObject dest)
1766 {
1767         if (dest && PyDict_Check(dest))
1768         {
1769                 const char *tmp=0;
1770                 PutToDict(dest, "tuner_number", m_slotid);
1771
1772                 if (supportsDeliverySystem(SYS_DVBS, true) || supportsDeliverySystem(SYS_DVBS2, true))
1773                 {
1774                         tmp = "DVB-S";
1775                 }
1776 #if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 6
1777                 else if (supportsDeliverySystem(SYS_DVBC_ANNEX_A, true))
1778 #else
1779                 else if (supportsDeliverySystem(SYS_DVBC_ANNEX_AC, true))
1780 #endif
1781                 {
1782                         tmp = "DVB-C";
1783                 }
1784                 else if (supportsDeliverySystem(SYS_DVBT, true) || supportsDeliverySystem(SYS_DVBT2, true))
1785                 {
1786                         tmp = "DVB-T";
1787                 }
1788                 else
1789                 {
1790                         tmp = "UNKNOWN";
1791                 }
1792                 PutToDict(dest, "tuner_type", tmp);
1793         }
1794 }
1795
1796 #ifndef FP_IOCTL_GET_ID
1797 #define FP_IOCTL_GET_ID 0
1798 #endif
1799 int eDVBFrontend::readInputpower()
1800 {
1801         if (m_simulate)
1802                 return 0;
1803         int power=m_slotid;  // this is needed for read inputpower from the correct tuner !
1804         char proc_name[64];
1805         char proc_name2[64];
1806         sprintf(proc_name, "/proc/stb/frontend/%d/lnb_sense", m_slotid);
1807         sprintf(proc_name2, "/proc/stb/fp/lnb_sense%d", m_slotid);
1808         FILE *f;
1809         if ((f=fopen(proc_name, "r")) || (f=fopen(proc_name2, "r")))
1810         {
1811                 if (fscanf(f, "%d", &power) != 1)
1812                         eDebug("read %s failed!! (%m)", proc_name);
1813                 else
1814                         eDebug("%s is %d\n", proc_name, power);
1815                 fclose(f);
1816         }
1817         else
1818         {
1819                 // open front prozessor
1820                 int fp=::open("/dev/dbox/fp0", O_RDWR);
1821                 if (fp < 0)
1822                 {
1823                         eDebug("couldn't open fp");
1824                         return -1;
1825                 }
1826                 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1827                 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1828                 {
1829                         eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
1830                         return -1;
1831                 }
1832                 ::close(fp);
1833         }
1834
1835         return power;
1836 }
1837
1838 bool eDVBFrontend::setSecSequencePos(int steps)
1839 {
1840         eDebugNoSimulate("set sequence pos %d", steps);
1841         if (!steps)
1842                 return false;
1843         while( steps > 0 )
1844         {
1845                 if (m_sec_sequence.current() != m_sec_sequence.end())
1846                         ++m_sec_sequence.current();
1847                 --steps;
1848         }
1849         while( steps < 0 )
1850         {
1851                 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1852                         --m_sec_sequence.current();
1853                 ++steps;
1854         }
1855         return true;
1856 }
1857
1858 void eDVBFrontend::tuneLoop()
1859 {
1860         tuneLoopInt();
1861 }
1862
1863 int eDVBFrontend::tuneLoopInt()  // called by m_tuneTimer
1864 {
1865         int delay=-1;
1866         eDVBFrontend *sec_fe = this;
1867         eDVBRegisteredFrontend *regFE = 0;
1868         long tmp = m_data[LINKED_PREV_PTR];
1869         while ( tmp != -1 )
1870         {
1871                 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1872                 sec_fe = prev->m_frontend;
1873                 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1874                 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1875                         int state = sec_fe->m_state;
1876 #if 0 // Since following code causes lock fail for linked tuners in certain conditions, it does not apply.
1877                         // workaround to put the kernel frontend thread into idle state!
1878                         if (state != eDVBFrontend::stateIdle && state != stateClosed)
1879                         {
1880                                 sec_fe->closeFrontend(true);
1881                                 state = sec_fe->m_state;
1882                         }
1883 #endif
1884                         // sec_fe is closed... we must reopen it here..
1885                         if (state == stateClosed)
1886                         {
1887                                 regFE = prev;
1888                                 prev->inc_use();
1889                         }
1890                 }
1891         }
1892
1893         if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1894         {
1895                 long *sec_fe_data = sec_fe->m_data;
1896 //              eDebugNoSimulate("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1897                 delay = 0;
1898                 switch (m_sec_sequence.current()->cmd)
1899                 {
1900                         case eSecCommand::SLEEP:
1901                                 delay = m_sec_sequence.current()++->msec;
1902                                 eDebugNoSimulate("[SEC] sleep %dms", delay);
1903                                 break;
1904                         case eSecCommand::GOTO:
1905                                 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1906                                         ++m_sec_sequence.current();
1907                                 break;
1908                         case eSecCommand::SET_VOLTAGE:
1909                         {
1910                                 int voltage = m_sec_sequence.current()++->voltage;
1911                                 eDebugNoSimulate("[SEC] setVoltage %d", voltage);
1912                                 sec_fe->setVoltage(voltage);
1913                                 break;
1914                         }
1915                         case eSecCommand::IF_VOLTAGE_GOTO:
1916                         {
1917                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1918                                 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1919                                         break;
1920                                 ++m_sec_sequence.current();
1921                                 break;
1922                         }
1923                         case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1924                         {
1925                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1926                                 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1927                                         break;
1928                                 ++m_sec_sequence.current();
1929                                 break;
1930                         }
1931                         case eSecCommand::IF_TONE_GOTO:
1932                         {
1933                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1934                                 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1935                                         break;
1936                                 ++m_sec_sequence.current();
1937                                 break;
1938                         }
1939                         case eSecCommand::IF_NOT_TONE_GOTO:
1940                         {
1941                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1942                                 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1943                                         break;
1944                                 ++m_sec_sequence.current();
1945                                 break;
1946                         }
1947                         case eSecCommand::SET_TONE:
1948                                 eDebugNoSimulate("[SEC] setTone %d", m_sec_sequence.current()->tone);
1949                                 sec_fe->setTone(m_sec_sequence.current()++->tone);
1950                                 break;
1951                         case eSecCommand::SEND_DISEQC:
1952                                 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1953                                 eDebugNoSimulateNoNewLine("[SEC] sendDiseqc: ");
1954                                 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1955                                     eDebugNoSimulateNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1956                                 if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
1957                                         eDebugNoSimulate("(DiSEqC reset)");
1958                                 else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
1959                                         eDebugNoSimulate("(DiSEqC peripherial power on)");
1960                                 else
1961                                         eDebugNoSimulate("");
1962                                 ++m_sec_sequence.current();
1963                                 break;
1964                         case eSecCommand::SEND_TONEBURST:
1965                                 eDebugNoSimulate("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1966                                 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1967                                 break;
1968                         case eSecCommand::SET_FRONTEND:
1969                         {
1970                                 int enableEvents = (m_sec_sequence.current()++)->val;
1971                                 eDebugNoSimulate("[SEC] setFrontend %d", enableEvents);
1972                                 setFrontend(enableEvents);
1973                                 break;
1974                         }
1975                         case eSecCommand::START_TUNE_TIMEOUT:
1976                         {
1977                                 int tuneTimeout = m_sec_sequence.current()->timeout;
1978                                 eDebugNoSimulate("[SEC] startTuneTimeout %d", tuneTimeout);
1979                                 if (!m_simulate)
1980                                         m_timeout->start(tuneTimeout, 1);
1981                                 ++m_sec_sequence.current();
1982                                 break;
1983                         }
1984                         case eSecCommand::SET_TIMEOUT:
1985                                 m_timeoutCount = m_sec_sequence.current()++->val;
1986                                 eDebugNoSimulate("[SEC] set timeout %d", m_timeoutCount);
1987                                 break;
1988                         case eSecCommand::IF_TIMEOUT_GOTO:
1989                                 if (!m_timeoutCount)
1990                                 {
1991                                         eDebugNoSimulate("[SEC] rotor timout");
1992                                         setSecSequencePos(m_sec_sequence.current()->steps);
1993                                 }
1994                                 else
1995                                         ++m_sec_sequence.current();
1996                                 break;
1997                         case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1998                         {
1999                                 int idx = m_sec_sequence.current()++->val;
2000                                 if ( idx == 0 || idx == 1 )
2001                                 {
2002                                         m_idleInputpower[idx] = sec_fe->readInputpower();
2003                                         eDebugNoSimulate("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
2004                                 }
2005                                 else
2006                                         eDebugNoSimulate("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
2007                                 break;
2008                         }
2009                         case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
2010                         {
2011                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
2012                                 int idx = compare.val;
2013                                 if ( !m_simulate && (idx == 0 || idx == 1) )
2014                                 {
2015                                         int idle = sec_fe->readInputpower();
2016                                         int diff = abs(idle-m_idleInputpower[idx]);
2017                                         if ( diff > 0)
2018                                         {
2019                                                 eDebugNoSimulate("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
2020                                                 setSecSequencePos(compare.steps);
2021                                                 break;
2022                                         }
2023                                 }
2024                                 ++m_sec_sequence.current();
2025                                 break;
2026                         }
2027                         case eSecCommand::IF_TUNER_LOCKED_GOTO:
2028                         {
2029                                 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
2030                                 if (m_simulate)
2031                                 {
2032                                         setSecSequencePos(cmd.steps);
2033                                         break;
2034                                 }
2035                                 int signal = 0;
2036                                 int isLocked = readFrontendData(locked);
2037                                 m_idleInputpower[0] = m_idleInputpower[1] = 0;
2038                                 --m_timeoutCount;
2039                                 if (!m_timeoutCount && m_retryCount > 0)
2040                                         --m_retryCount;
2041                                 if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 40) || !cmd.lastSignal))
2042                                 {
2043                                         if (cmd.lastSignal)
2044                                                 eDebugNoSimulate("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
2045                                         else
2046                                         {
2047                                                 eDebugNoSimulate("[SEC] locked step %d ok", cmd.okcount);
2048                                                 if (!cmd.okcount)
2049                                                         cmd.lastSignal = signal;
2050                                         }
2051                                         ++cmd.okcount;
2052                                         if (cmd.okcount > 4)
2053                                         {
2054                                                 eDebugNoSimulate("ok > 4 .. goto %d\n", cmd.steps);
2055                                                 setSecSequencePos(cmd.steps);
2056                                                 m_state = stateLock;
2057                                                 m_stateChanged(this);
2058                                                 feEvent(-1); // flush events
2059                                                 m_sn->start();
2060                                                 break;
2061                                         }
2062                                 }
2063                                 else
2064                                 {
2065                                         if (isLocked)
2066                                                 eDebugNoSimulate("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
2067                                         else
2068                                                 eDebugNoSimulate("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
2069                                         cmd.okcount=0;
2070                                         cmd.lastSignal=0;
2071                                 }
2072                                 ++m_sec_sequence.current();
2073                                 break;
2074                         }
2075                         case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
2076                                 m_runningInputpower = sec_fe->readInputpower();
2077                                 eDebugNoSimulate("[SEC] runningInputpower is %d", m_runningInputpower);
2078                                 ++m_sec_sequence.current();
2079                                 break;
2080                         case eSecCommand::SET_ROTOR_MOVING:
2081                                 if (!m_simulate)
2082                                         m_sec->setRotorMoving(m_slotid, true);
2083                                 ++m_sec_sequence.current();
2084                                 break;
2085                         case eSecCommand::SET_ROTOR_STOPPED:
2086                                 if (!m_simulate)
2087                                         m_sec->setRotorMoving(m_slotid, false);
2088                                 ++m_sec_sequence.current();
2089                                 break;
2090                         case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
2091                         {
2092                                 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
2093                                 if (m_simulate)
2094                                 {
2095                                         setSecSequencePos(cmd.steps);
2096                                         break;
2097                                 }
2098                                 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
2099                                 const char *txt = cmd.direction ? "running" : "stopped";
2100                                 --m_timeoutCount;
2101                                 if (!m_timeoutCount && m_retryCount > 0)
2102                                         --m_retryCount;
2103                                 eDebugNoSimulate("[SEC] waiting for rotor %s %d, idle %d, delta %d",
2104                                         txt,
2105                                         m_runningInputpower,
2106                                         idleInputpower,
2107                                         cmd.deltaA);
2108                                 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
2109                                         || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
2110                                 {
2111                                         ++cmd.okcount;
2112                                         eDebugNoSimulate("[SEC] rotor %s step %d ok", txt, cmd.okcount);
2113                                         if ( cmd.okcount > 6 )
2114                                         {
2115                                                 eDebugNoSimulate("[SEC] rotor is %s", txt);
2116                                                 if (setSecSequencePos(cmd.steps))
2117                                                         break;
2118                                         }
2119                                 }
2120                                 else
2121                                 {
2122                                         eDebugNoSimulate("[SEC] rotor not %s... reset counter.. increase timeout", txt);
2123                                         cmd.okcount=0;
2124                                 }
2125                                 ++m_sec_sequence.current();
2126                                 break;
2127                         }
2128                         case eSecCommand::IF_ROTORPOS_VALID_GOTO:
2129                                 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
2130                                         setSecSequencePos(m_sec_sequence.current()->steps);
2131                                 else
2132                                         ++m_sec_sequence.current();
2133                                 break;
2134                         case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
2135                                 eDebugNoSimulate("[SEC] invalidate current switch params");
2136                                 sec_fe_data[CSW] = -1;
2137                                 sec_fe_data[UCSW] = -1;
2138                                 sec_fe_data[TONEBURST] = -1;
2139                                 ++m_sec_sequence.current();
2140                                 break;
2141                         case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
2142                                 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
2143                                 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
2144                                 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
2145                                 eDebugNoSimulate("[SEC] update current switch params");
2146                                 ++m_sec_sequence.current();
2147                                 break;
2148                         case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
2149                                 eDebugNoSimulate("[SEC] invalidate current rotorparams");
2150                                 sec_fe_data[ROTOR_CMD] = -1;
2151                                 sec_fe_data[ROTOR_POS] = -1;
2152                                 ++m_sec_sequence.current();
2153                                 break;
2154                         case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
2155                                 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
2156                                 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
2157                                 eDebugNoSimulate("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
2158                                 ++m_sec_sequence.current();
2159                                 break;
2160                         case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
2161                                 m_retryCount = m_sec_sequence.current()++->val;
2162                                 eDebugNoSimulate("[SEC] set rotor retries %d", m_retryCount);
2163                                 break;
2164                         case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
2165                                 if (!m_retryCount)
2166                                 {
2167                                         eDebugNoSimulate("[SEC] no more rotor retrys");
2168                                         setSecSequencePos(m_sec_sequence.current()->steps);
2169                                 }
2170                                 else
2171                                         ++m_sec_sequence.current();
2172                                 break;
2173                         case eSecCommand::SET_POWER_LIMITING_MODE:
2174                         {
2175                                 if (!m_simulate)
2176                                 {
2177                                         char proc_name[64];
2178                                         sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
2179                                         FILE *f=fopen(proc_name, "w");
2180                                         if (f) // new interface exist?
2181                                         {
2182                                                 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
2183                                                 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
2184                                                         eDebugNoSimulate("write %s failed!! (%m)", proc_name);
2185                                                 else
2186                                                         eDebugNoSimulate("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
2187                                                 fclose(f);
2188                                         }
2189                                         else if (sec_fe->m_need_rotor_workaround)
2190                                         {
2191                                                 char dev[16];
2192                                                 int slotid = sec_fe->m_slotid;
2193                                                 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
2194                                                 if (slotid < 2)
2195                                                         sprintf(dev, "/dev/i2c-%d", slotid);
2196                                                 else if (slotid == 2)
2197                                                         sprintf(dev, "/dev/i2c-2"); // first nim socket on DM8000 use /dev/i2c-2
2198                                                 else if (slotid == 3)
2199                                                         sprintf(dev, "/dev/i2c-4"); // second nim socket on DM8000 use /dev/i2c-4
2200                                                 int fd = ::open(dev, O_RDWR);
2201
2202                                                 unsigned char data[2];
2203                                                 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
2204                                                 if(::read(fd, data, 1) != 1)
2205                                                         eDebugNoSimulate("[SEC] error read lnbp (%m)");
2206                                                 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
2207                                                 {
2208                                                         data[0] |= 0x80;  // enable static current limiting
2209                                                         eDebugNoSimulate("[SEC] set static current limiting");
2210                                                 }
2211                                                 else
2212                                                 {
2213                                                         data[0] &= ~0x80;  // enable dynamic current limiting
2214                                                         eDebugNoSimulate("[SEC] set dynamic current limiting");
2215                                                 }
2216                                                 if(::write(fd, data, 1) != 1)
2217                                                         eDebugNoSimulate("[SEC] error write lnbp (%m)");
2218                                                 ::close(fd);
2219                                         }
2220                                 }
2221                                 ++m_sec_sequence.current();
2222                                 break;
2223                         }
2224                         case eSecCommand::DELAYED_CLOSE_FRONTEND:
2225                         {
2226                                 eDebugNoSimulate("[SEC] delayed close frontend");
2227                                 closeFrontend(false, true);
2228                                 ++m_sec_sequence.current();
2229                                 break;
2230                         }
2231                         default:
2232                                 eDebugNoSimulate("[SEC] unhandled sec command %d",
2233                                         ++m_sec_sequence.current()->cmd);
2234                                 ++m_sec_sequence.current();
2235                 }
2236                 if (!m_simulate)
2237                         m_tuneTimer->start(delay,true);
2238         }
2239         if (regFE)
2240                 regFE->dec_use();
2241         if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
2242                 tuneLoop();
2243         return delay;
2244 }
2245
2246 void eDVBFrontend::setFrontend(bool recvEvents)
2247 {
2248         if (!m_simulate)
2249         {
2250                 eDebug("setting frontend %d", m_dvbid);
2251
2252                 int type = -1;
2253                 oparm.getSystem(type);
2254
2255                 if (recvEvents)
2256                         m_sn->start();
2257                 feEvent(-1); // flush events
2258 #if HAVE_DVB_API_VERSION >= 5
2259                 if (type == iDVBFrontend::feSatellite)
2260                 {
2261                         fe_rolloff_t rolloff = ROLLOFF_35;
2262                         fe_pilot_t pilot = PILOT_OFF;
2263                         fe_modulation_t modulation = QPSK;
2264                         fe_delivery_system_t system = SYS_DVBS;
2265                         eDVBFrontendParametersSatellite sparm;
2266                         oparm.getDVBS(sparm);
2267                         switch(sparm.system)
2268                         {
2269                         case eDVBFrontendParametersSatellite::System_DVB_S: system = SYS_DVBS; break;
2270                         case eDVBFrontendParametersSatellite::System_DVB_S2: system = SYS_DVBS2; break;
2271                         };
2272                         switch(sparm.modulation)
2273                         {
2274                         case eDVBFrontendParametersSatellite::Modulation_QPSK: modulation = QPSK; break;
2275                         case eDVBFrontendParametersSatellite::Modulation_8PSK: modulation = PSK_8; break;
2276                         case eDVBFrontendParametersSatellite::Modulation_QAM16: modulation = QAM_16; break;
2277                         };
2278                         switch(sparm.pilot)
2279                         {
2280                         case eDVBFrontendParametersSatellite::Pilot_Off: pilot = PILOT_OFF; break;
2281                         case eDVBFrontendParametersSatellite::Pilot_On: pilot = PILOT_ON; break;
2282                         case eDVBFrontendParametersSatellite::Pilot_Unknown: pilot = PILOT_AUTO; break;
2283                         };
2284                         switch(sparm.rolloff)
2285                         {
2286                         case eDVBFrontendParametersSatellite::RollOff_alpha_0_20: rolloff = ROLLOFF_20; break;
2287                         case eDVBFrontendParametersSatellite::RollOff_alpha_0_25: rolloff = ROLLOFF_25; break;
2288                         case eDVBFrontendParametersSatellite::RollOff_alpha_0_35: rolloff = ROLLOFF_35; break;
2289                         };
2290                         struct dtv_property p[10];
2291                         struct dtv_properties cmdseq;
2292                         cmdseq.props = p;
2293                         p[0].cmd = DTV_CLEAR;
2294                         p[1].cmd = DTV_DELIVERY_SYSTEM, p[1].u.data = system;
2295                         p[2].cmd = DTV_FREQUENCY,       p[2].u.data = parm_frequency;
2296                         p[3].cmd = DTV_MODULATION,      p[3].u.data = modulation;
2297                         p[4].cmd = DTV_SYMBOL_RATE,     p[4].u.data = parm_u_qpsk_symbol_rate;
2298                         p[5].cmd = DTV_INNER_FEC,       p[5].u.data = parm_u_qpsk_fec_inner;
2299                         p[6].cmd = DTV_INVERSION,       p[6].u.data = parm_inversion;
2300                         if (system == SYS_DVBS2)
2301                         {
2302                                 p[7].cmd = DTV_ROLLOFF,         p[7].u.data = rolloff;
2303                                 p[8].cmd = DTV_PILOT,           p[8].u.data = pilot;
2304                                 p[9].cmd = DTV_TUNE;
2305                                 cmdseq.num = 10;
2306                         }
2307                         else
2308                         {
2309                                 p[7].cmd = DTV_TUNE;
2310                                 cmdseq.num = 8;
2311                         }
2312                         if (ioctl(m_fd, FE_SET_PROPERTY, &cmdseq) == -1)
2313                         {
2314                                 perror("FE_SET_PROPERTY failed");
2315                                 return;
2316                         }
2317                 }
2318                 else if (type == iDVBFrontend::feCable)
2319                 {
2320                         struct dtv_property p[8];
2321                         struct dtv_properties cmdseq;
2322                         cmdseq.props = p;
2323                         p[0].cmd = DTV_CLEAR;
2324 #if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 6
2325                         p[1].cmd = DTV_DELIVERY_SYSTEM, p[1].u.data = SYS_DVBC_ANNEX_A;
2326 #else
2327                         p[1].cmd = DTV_DELIVERY_SYSTEM, p[1].u.data = SYS_DVBC_ANNEX_AC;
2328 #endif
2329                         p[2].cmd = DTV_FREQUENCY,       p[2].u.data = parm_frequency;
2330                         p[3].cmd = DTV_MODULATION,      p[3].u.data = parm_u_qam_modulation;
2331                         p[4].cmd = DTV_SYMBOL_RATE,     p[4].u.data = parm_u_qam_symbol_rate;
2332                         p[5].cmd = DTV_INNER_FEC,       p[5].u.data = parm_u_qam_fec_inner;
2333                         p[6].cmd = DTV_INVERSION,       p[6].u.data = parm_inversion;
2334                         p[7].cmd = DTV_TUNE;
2335                         cmdseq.num = 8;
2336                         if (ioctl(m_fd, FE_SET_PROPERTY, &cmdseq) == -1)
2337                         {
2338                                 perror("FE_SET_PROPERTY failed");
2339                                 return;
2340                         }
2341                 }
2342                 else if (type == iDVBFrontend::feTerrestrial)
2343                 {
2344                         fe_delivery_system_t system = SYS_DVBT;
2345                         eDVBFrontendParametersTerrestrial tparm;
2346                         oparm.getDVBT(tparm);
2347                         switch (tparm.system)
2348                         {
2349                                 default:
2350                                 case eDVBFrontendParametersTerrestrial::System_DVB_T: system = SYS_DVBT; break;
2351                                 case eDVBFrontendParametersTerrestrial::System_DVB_T2: system = SYS_DVBT2; break;
2352                         }
2353                         int bandwidth = 0;
2354                         switch (tparm.bandwidth)
2355                         {
2356                                 case eDVBFrontendParametersTerrestrial::Bandwidth_8MHz: bandwidth = 8000000; break;
2357                                 case eDVBFrontendParametersTerrestrial::Bandwidth_7MHz: bandwidth = 7000000; break;
2358                                 case eDVBFrontendParametersTerrestrial::Bandwidth_6MHz: bandwidth = 6000000; break;
2359                                 default:
2360                                 case eDVBFrontendParametersTerrestrial::Bandwidth_Auto: bandwidth = 0; break;
2361                                 case eDVBFrontendParametersTerrestrial::Bandwidth_5MHz: bandwidth = 5000000; break;
2362                                 case eDVBFrontendParametersTerrestrial::Bandwidth_10MHz: bandwidth = 10000000; break;
2363                                 case eDVBFrontendParametersTerrestrial::Bandwidth_1_712MHz: bandwidth = 1712000; break;
2364                         }
2365                         struct dtv_property p[13];
2366                         struct dtv_properties cmdseq;
2367                         cmdseq.props = p;
2368                         cmdseq.num = 0;
2369                         p[cmdseq.num].cmd = DTV_CLEAR, cmdseq.num++;
2370                         p[cmdseq.num].cmd = DTV_DELIVERY_SYSTEM, p[cmdseq.num].u.data = system, cmdseq.num++;
2371                         p[cmdseq.num].cmd = DTV_FREQUENCY,      p[cmdseq.num].u.data = parm_frequency, cmdseq.num++;
2372                         p[cmdseq.num].cmd = DTV_CODE_RATE_LP,   p[cmdseq.num].u.data = parm_u_ofdm_code_rate_LP, cmdseq.num++;
2373                         p[cmdseq.num].cmd = DTV_CODE_RATE_HP,   p[cmdseq.num].u.data = parm_u_ofdm_code_rate_HP, cmdseq.num++;
2374                         p[cmdseq.num].cmd = DTV_MODULATION,     p[cmdseq.num].u.data = parm_u_ofdm_constellation, cmdseq.num++;
2375                         p[cmdseq.num].cmd = DTV_TRANSMISSION_MODE,      p[cmdseq.num].u.data = parm_u_ofdm_transmission_mode, cmdseq.num++;
2376                         p[cmdseq.num].cmd = DTV_GUARD_INTERVAL, p[cmdseq.num].u.data = parm_u_ofdm_guard_interval, cmdseq.num++;
2377                         p[cmdseq.num].cmd = DTV_HIERARCHY,      p[cmdseq.num].u.data = parm_u_ofdm_hierarchy_information, cmdseq.num++;
2378                         p[cmdseq.num].cmd = DTV_BANDWIDTH_HZ,   p[cmdseq.num].u.data = bandwidth, cmdseq.num++;
2379                         p[cmdseq.num].cmd = DTV_INVERSION,      p[cmdseq.num].u.data = parm_inversion, cmdseq.num++;
2380 #if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 9
2381                         p[cmdseq.num].cmd = DTV_STREAM_ID       ,       p[cmdseq.num].u.data = tparm.plpid, cmdseq.num++;
2382 #elif DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 3
2383                         p[cmdseq.num].cmd = DTV_DVBT2_PLP_ID    ,       p[cmdseq.num].u.data = tparm.plpid, cmdseq.num++;
2384 #endif
2385                         p[cmdseq.num].cmd = DTV_TUNE, cmdseq.num++;
2386                         if (ioctl(m_fd, FE_SET_PROPERTY, &cmdseq) == -1)
2387                         {
2388                                 perror("FE_SET_PROPERTY failed");
2389                                 return;
2390                         }
2391                 }
2392                 else
2393 #endif /* HAVE_DVB_API_VERSION >= 5 */
2394                 {
2395                         if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
2396                         {
2397                                 perror("FE_SET_FRONTEND failed");
2398                                 return;
2399                         }
2400                 }
2401         }
2402 }
2403
2404 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
2405 {
2406         int res;
2407         if (!m_sec)
2408         {
2409                 eWarning("no SEC module active!");
2410                 return -ENOENT;
2411         }
2412         res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
2413         if (!res)
2414         {
2415 #if HAVE_DVB_API_VERSION >= 3
2416                 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",
2417                         feparm.system,
2418                         feparm.frequency,
2419                         feparm.polarisation,
2420                         feparm.symbol_rate,
2421                         feparm.inversion,
2422                         feparm.fec,
2423                         feparm.orbital_position,
2424                         feparm.system,
2425                         feparm.modulation,
2426                         feparm.pilot,
2427                         feparm.rolloff);
2428 #else
2429                 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
2430                         feparm.system,
2431                         feparm.frequency,
2432                         feparm.polarisation,
2433                         feparm.symbol_rate,
2434                         feparm.inversion,
2435                         feparm.fec,
2436                         feparm.orbital_position);
2437 #endif
2438                 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
2439                 switch (feparm.inversion)
2440                 {
2441                         case eDVBFrontendParametersSatellite::Inversion_On:
2442                                 parm_inversion = INVERSION_ON;
2443                                 break;
2444                         case eDVBFrontendParametersSatellite::Inversion_Off:
2445                                 parm_inversion = INVERSION_OFF;
2446                                 break;
2447                         default:
2448                         case eDVBFrontendParametersSatellite::Inversion_Unknown:
2449                                 parm_inversion = INVERSION_AUTO;
2450                                 break;
2451                 }
2452                 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S)
2453                 {
2454                         switch (feparm.fec)
2455                         {
2456                                 case eDVBFrontendParametersSatellite::FEC_None:
2457                                         parm_u_qpsk_fec_inner = FEC_NONE;
2458                                         break;
2459                                 case eDVBFrontendParametersSatellite::FEC_1_2:
2460                                         parm_u_qpsk_fec_inner = FEC_1_2;
2461                                         break;
2462                                 case eDVBFrontendParametersSatellite::FEC_2_3:
2463                                         parm_u_qpsk_fec_inner = FEC_2_3;
2464                                         break;
2465                                 case eDVBFrontendParametersSatellite::FEC_3_4:
2466                                         parm_u_qpsk_fec_inner = FEC_3_4;
2467                                         break;
2468                                 case eDVBFrontendParametersSatellite::FEC_5_6:
2469                                         parm_u_qpsk_fec_inner = FEC_5_6;
2470                                         break;
2471                                 case eDVBFrontendParametersSatellite::FEC_7_8:
2472                                         parm_u_qpsk_fec_inner = FEC_7_8;
2473                                         break;
2474                                 default:
2475                                         eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
2476                                 case eDVBFrontendParametersSatellite::FEC_Auto:
2477                                         parm_u_qpsk_fec_inner = FEC_AUTO;
2478                                         break;
2479                         }
2480                 }
2481 #if HAVE_DVB_API_VERSION >= 3
2482                 else // DVB_S2
2483                 {
2484                         switch (feparm.fec)
2485                         {
2486                                 case eDVBFrontendParametersSatellite::FEC_1_2:
2487                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
2488                                         break;
2489                                 case eDVBFrontendParametersSatellite::FEC_2_3:
2490                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
2491                                         break;
2492                                 case eDVBFrontendParametersSatellite::FEC_3_4:
2493                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
2494                                         break;
2495                                 case eDVBFrontendParametersSatellite::FEC_3_5:
2496                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
2497                                         break;
2498                                 case eDVBFrontendParametersSatellite::FEC_4_5:
2499                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
2500                                         break;
2501                                 case eDVBFrontendParametersSatellite::FEC_5_6:
2502                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
2503                                         break;
2504                                 case eDVBFrontendParametersSatellite::FEC_7_8:
2505                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
2506                                         break;
2507                                 case eDVBFrontendParametersSatellite::FEC_8_9:
2508                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
2509                                         break;
2510                                 case eDVBFrontendParametersSatellite::FEC_9_10:
2511                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
2512                                         break;
2513                                 default:
2514                                         eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
2515                                         return -EINVAL;
2516                         }
2517 #if HAVE_DVB_API_VERSION < 5
2518                         parm_inversion = (fe_spectral_inversion_t)((feparm.rolloff << 2) | parm_inversion); // Hack.. we use bit 2..3 of inversion param for rolloff
2519                         parm_inversion = (fe_spectral_inversion_t)((feparm.pilot << 4) | parm_inversion); // Hack.. we use bit 4..5 of inversion param for pilot
2520                         if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation_8PSK) 
2521                         {
2522                                 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
2523                                 // 8PSK fec driver values are decimal 9 bigger
2524                         }
2525 #endif
2526                 }
2527 #endif
2528                 // FIXME !!! get frequency range from tuner
2529                 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
2530                 {
2531                         eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
2532                         return -EINVAL;
2533                 }
2534                 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
2535         }
2536         oparm.setDVBS(feparm, feparm.no_rotor_command_on_tune);
2537         return res;
2538 }
2539
2540 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
2541 {
2542 #if HAVE_DVB_API_VERSION < 3
2543         parm_frequency = feparm.frequency;
2544 #else
2545         parm_frequency = feparm.frequency * 1000;
2546 #endif
2547         parm_u_qam_symbol_rate = feparm.symbol_rate;
2548         switch (feparm.modulation)
2549         {
2550         case eDVBFrontendParametersCable::Modulation_QAM16:
2551                 parm_u_qam_modulation = QAM_16;
2552                 break;
2553         case eDVBFrontendParametersCable::Modulation_QAM32:
2554                 parm_u_qam_modulation = QAM_32;
2555                 break;
2556         case eDVBFrontendParametersCable::Modulation_QAM64:
2557                 parm_u_qam_modulation = QAM_64;
2558                 break;
2559         case eDVBFrontendParametersCable::Modulation_QAM128:
2560                 parm_u_qam_modulation = QAM_128;
2561                 break;
2562         case eDVBFrontendParametersCable::Modulation_QAM256:
2563                 parm_u_qam_modulation = QAM_256;
2564                 break;
2565         default:
2566         case eDVBFrontendParametersCable::Modulation_Auto:
2567                 parm_u_qam_modulation = QAM_AUTO;
2568                 break;
2569         }
2570         switch (feparm.inversion)
2571         {
2572         case eDVBFrontendParametersCable::Inversion_On:
2573                 parm_inversion = INVERSION_ON;
2574                 break;
2575         case eDVBFrontendParametersCable::Inversion_Off:
2576                 parm_inversion = INVERSION_OFF;
2577                 break;
2578         default:
2579         case eDVBFrontendParametersCable::Inversion_Unknown:
2580                 parm_inversion = INVERSION_AUTO;
2581                 break;
2582         }
2583         switch (feparm.fec_inner)
2584         {
2585         case eDVBFrontendParametersCable::FEC_None:
2586                 parm_u_qam_fec_inner = FEC_NONE;
2587                 break;
2588         case eDVBFrontendParametersCable::FEC_1_2:
2589                 parm_u_qam_fec_inner = FEC_1_2;
2590                 break;
2591         case eDVBFrontendParametersCable::FEC_2_3:
2592                 parm_u_qam_fec_inner = FEC_2_3;
2593                 break;
2594         case eDVBFrontendParametersCable::FEC_3_4:
2595                 parm_u_qam_fec_inner = FEC_3_4;
2596                 break;
2597         case eDVBFrontendParametersCable::FEC_5_6:
2598                 parm_u_qam_fec_inner = FEC_5_6;
2599                 break;
2600         case eDVBFrontendParametersCable::FEC_7_8:
2601                 parm_u_qam_fec_inner = FEC_7_8;
2602                 break;
2603 #if HAVE_DVB_API_VERSION >= 3
2604         case eDVBFrontendParametersCable::FEC_8_9:
2605                 parm_u_qam_fec_inner = FEC_8_9;
2606                 break;
2607 #endif
2608         default:
2609         case eDVBFrontendParametersCable::FEC_Auto:
2610                 parm_u_qam_fec_inner = FEC_AUTO;
2611                 break;
2612         }
2613         eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
2614                 parm_frequency/1000,
2615                 parm_u_qam_symbol_rate,
2616                 parm_u_qam_fec_inner,
2617                 parm_u_qam_modulation,
2618                 parm_inversion);
2619         oparm.setDVBC(feparm);
2620         return 0;
2621 }
2622
2623 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
2624 {
2625         parm_frequency = feparm.frequency;
2626
2627         switch (feparm.bandwidth)
2628         {
2629         case eDVBFrontendParametersTerrestrial::Bandwidth_8MHz:
2630                 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
2631                 break;
2632         case eDVBFrontendParametersTerrestrial::Bandwidth_7MHz:
2633                 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
2634                 break;
2635         case eDVBFrontendParametersTerrestrial::Bandwidth_6MHz:
2636                 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
2637                 break;
2638         case eDVBFrontendParametersTerrestrial::Bandwidth_5MHz:
2639                 parm_u_ofdm_bandwidth = BANDWIDTH_5_MHZ;
2640                 break;
2641         case eDVBFrontendParametersTerrestrial::Bandwidth_10MHz:
2642                 parm_u_ofdm_bandwidth = BANDWIDTH_10_MHZ;
2643                 break;
2644         case eDVBFrontendParametersTerrestrial::Bandwidth_1_712MHz:
2645                 parm_u_ofdm_bandwidth = BANDWIDTH_1_712_MHZ;
2646                 break;
2647         default:
2648         case eDVBFrontendParametersTerrestrial::Bandwidth_Auto:
2649                 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
2650                 break;
2651         }
2652         switch (feparm.code_rate_LP)
2653         {
2654         case eDVBFrontendParametersTerrestrial::FEC_1_2:
2655                 parm_u_ofdm_code_rate_LP = FEC_1_2;
2656                 break;
2657         case eDVBFrontendParametersTerrestrial::FEC_2_3:
2658                 parm_u_ofdm_code_rate_LP = FEC_2_3;
2659                 break;
2660         case eDVBFrontendParametersTerrestrial::FEC_3_4:
2661                 parm_u_ofdm_code_rate_LP = FEC_3_4;
2662                 break;
2663         case eDVBFrontendParametersTerrestrial::FEC_5_6:
2664                 parm_u_ofdm_code_rate_LP = FEC_5_6;
2665                 break;
2666         case eDVBFrontendParametersTerrestrial::FEC_7_8:
2667                 parm_u_ofdm_code_rate_LP = FEC_7_8;
2668                 break;
2669         case eDVBFrontendParametersTerrestrial::FEC_6_7:
2670                 parm_u_ofdm_code_rate_LP = FEC_6_7;
2671                 break;
2672         case eDVBFrontendParametersTerrestrial::FEC_8_9:
2673                 parm_u_ofdm_code_rate_LP = FEC_8_9;
2674                 break;
2675         default:
2676         case eDVBFrontendParametersTerrestrial::FEC_Auto:
2677                 parm_u_ofdm_code_rate_LP = FEC_AUTO;
2678                 break;
2679         }
2680         switch (feparm.code_rate_HP)
2681         {
2682         case eDVBFrontendParametersTerrestrial::FEC_1_2:
2683                 parm_u_ofdm_code_rate_HP = FEC_1_2;
2684                 break;
2685         case eDVBFrontendParametersTerrestrial::FEC_2_3:
2686                 parm_u_ofdm_code_rate_HP = FEC_2_3;
2687                 break;
2688         case eDVBFrontendParametersTerrestrial::FEC_3_4:
2689                 parm_u_ofdm_code_rate_HP = FEC_3_4;
2690                 break;
2691         case eDVBFrontendParametersTerrestrial::FEC_5_6:
2692                 parm_u_ofdm_code_rate_HP = FEC_5_6;
2693                 break;
2694         case eDVBFrontendParametersTerrestrial::FEC_7_8:
2695                 parm_u_ofdm_code_rate_HP = FEC_7_8;
2696                 break;
2697         case eDVBFrontendParametersTerrestrial::FEC_6_7:
2698                 parm_u_ofdm_code_rate_HP = FEC_6_7;
2699                 break;
2700         case eDVBFrontendParametersTerrestrial::FEC_8_9:
2701                 parm_u_ofdm_code_rate_HP = FEC_8_9;
2702                 break;
2703         default:
2704         case eDVBFrontendParametersTerrestrial::FEC_Auto:
2705                 parm_u_ofdm_code_rate_HP = FEC_AUTO;
2706                 break;
2707         }
2708         switch (feparm.modulation)
2709         {
2710         case eDVBFrontendParametersTerrestrial::Modulation_QPSK:
2711                 parm_u_ofdm_constellation = QPSK;
2712                 break;
2713         case eDVBFrontendParametersTerrestrial::Modulation_QAM16:
2714                 parm_u_ofdm_constellation = QAM_16;
2715                 break;
2716         case eDVBFrontendParametersTerrestrial::Modulation_QAM64:
2717                 parm_u_ofdm_constellation = QAM_64;
2718                 break;
2719         case eDVBFrontendParametersTerrestrial::Modulation_QAM256:
2720                 parm_u_ofdm_constellation = QAM_256;
2721                 break;
2722         default:
2723         case eDVBFrontendParametersTerrestrial::Modulation_Auto:
2724                 parm_u_ofdm_constellation = QAM_AUTO;
2725                 break;
2726         }
2727         switch (feparm.transmission_mode)
2728         {
2729         case eDVBFrontendParametersTerrestrial::TransmissionMode_2k:
2730                 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2731                 break;
2732         case eDVBFrontendParametersTerrestrial::TransmissionMode_8k:
2733                 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2734                 break;
2735         case eDVBFrontendParametersTerrestrial::TransmissionMode_4k:
2736                 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_4K;
2737                 break;
2738         case eDVBFrontendParametersTerrestrial::TransmissionMode_1k:
2739                 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_1K;
2740                 break;
2741         case eDVBFrontendParametersTerrestrial::TransmissionMode_16k:
2742                 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_16K;
2743                 break;
2744         case eDVBFrontendParametersTerrestrial::TransmissionMode_32k:
2745                 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_32K;
2746                 break;
2747         default:
2748         case eDVBFrontendParametersTerrestrial::TransmissionMode_Auto:
2749                 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2750                 break;
2751         }
2752         switch (feparm.guard_interval)
2753         {
2754                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_32:
2755                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2756                         break;
2757                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_16:
2758                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2759                         break;
2760                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_8:
2761                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2762                         break;
2763                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_4:
2764                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2765                         break;
2766                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_128:
2767                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_128;
2768                         break;
2769                 case eDVBFrontendParametersTerrestrial::GuardInterval_19_128:
2770                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_19_128;
2771                         break;
2772                 case eDVBFrontendParametersTerrestrial::GuardInterval_19_256:
2773                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_19_256;
2774                         break;
2775                 default:
2776                 case eDVBFrontendParametersTerrestrial::GuardInterval_Auto:
2777                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2778                         break;
2779         }
2780         switch (feparm.hierarchy)
2781         {
2782                 case eDVBFrontendParametersTerrestrial::Hierarchy_None:
2783                         parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2784                         break;
2785                 case eDVBFrontendParametersTerrestrial::Hierarchy_1:
2786                         parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2787                         break;
2788                 case eDVBFrontendParametersTerrestrial::Hierarchy_2:
2789                         parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2790                         break;
2791                 case eDVBFrontendParametersTerrestrial::Hierarchy_4:
2792                         parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2793                         break;
2794                 default:
2795                 case eDVBFrontendParametersTerrestrial::Hierarchy_Auto:
2796                         parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2797                         break;
2798         }
2799         switch (feparm.inversion)
2800         {
2801         case eDVBFrontendParametersTerrestrial::Inversion_On:
2802                 parm_inversion = INVERSION_ON;
2803                 break;
2804         case eDVBFrontendParametersTerrestrial::Inversion_Off:
2805                 parm_inversion = INVERSION_OFF;
2806                 break;
2807         default:
2808         case eDVBFrontendParametersTerrestrial::Inversion_Unknown:
2809                 parm_inversion = INVERSION_AUTO;
2810                 break;
2811         }
2812         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",
2813                 parm_frequency/1000,
2814                 parm_u_ofdm_bandwidth,
2815                 parm_u_ofdm_code_rate_LP,
2816                 parm_u_ofdm_code_rate_HP,
2817                 parm_u_ofdm_constellation,
2818                 parm_u_ofdm_transmission_mode,
2819                 parm_u_ofdm_guard_interval,
2820                 parm_u_ofdm_hierarchy_information,
2821                 parm_inversion,
2822                 feparm.system,
2823                 feparm.plpid);
2824         oparm.setDVBT(feparm);
2825         return 0;
2826 }
2827
2828 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2829 {
2830         unsigned int timeout = 5000;
2831         eDebugNoSimulate("(%d)tune", m_dvbid);
2832
2833         m_timeout->stop();
2834
2835         int res=0;
2836
2837         int type;
2838         if (where.getSystem(type) < 0)
2839         {
2840                 res = -EINVAL;
2841                 goto tune_error;
2842         }
2843
2844         if (!m_sn && !m_simulate)
2845         {
2846                 eDebug("no frontend device opened... do not try to tune !!!");
2847                 res = -ENODEV;
2848                 goto tune_error;
2849         }
2850
2851         if (!m_simulate)
2852                 m_sn->stop();
2853
2854         m_sec_sequence.clear();
2855
2856         where.calcLockTimeout(timeout);
2857
2858         switch (type)
2859         {
2860         case feSatellite:
2861         {
2862                 eDVBFrontendParametersSatellite feparm;
2863                 if (where.getDVBS(feparm))
2864                 {
2865                         eDebug("no dvbs data!");
2866                         res = -EINVAL;
2867                         goto tune_error;
2868                 }
2869                 if (m_rotor_mode != feparm.no_rotor_command_on_tune && !feparm.no_rotor_command_on_tune)
2870                 {
2871                         eDVBFrontend *sec_fe = this;
2872                         long tmp = m_data[LINKED_PREV_PTR];
2873                         while (tmp != -1)
2874                         {
2875                                 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
2876                                 sec_fe = linked_fe->m_frontend;
2877                                 sec_fe->getData(LINKED_NEXT_PTR, tmp);
2878                         }
2879                         eDebug("(fe%d) reset diseqc after leave rotor mode!", m_dvbid);
2880                         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
2881                 }
2882                 m_rotor_mode = feparm.no_rotor_command_on_tune;
2883                 if (!m_simulate)
2884                         m_sec->setRotorMoving(m_slotid, false);
2885                 res=prepare_sat(feparm, timeout);
2886                 if (res)
2887                         goto tune_error;
2888
2889                 break;
2890         }
2891         case feCable:
2892         {
2893                 eDVBFrontendParametersCable feparm;
2894                 if (where.getDVBC(feparm))
2895                 {
2896                         res = -EINVAL;
2897                         goto tune_error;
2898                 }
2899                 res=prepare_cable(feparm);
2900                 if (res)
2901                         goto tune_error;
2902
2903                 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2904                 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2905                 break;
2906         }
2907         case feTerrestrial:
2908         {
2909                 eDVBFrontendParametersTerrestrial feparm;
2910                 if (where.getDVBT(feparm))
2911                 {
2912                         eDebug("no -T data");
2913                         res = -EINVAL;
2914                         goto tune_error;
2915                 }
2916                 res=prepare_terrestrial(feparm);
2917                 if (res)
2918                         goto tune_error;
2919
2920                 std::string enable_5V;
2921                 char configStr[255];
2922                 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2923                 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2924                 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2925                 if (enable_5V == "True")
2926                         m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2927                 else
2928                         m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2929                 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2930
2931                 break;
2932         }
2933         default:
2934         {
2935                         res = -EINVAL;
2936                         goto tune_error;
2937         }
2938         }
2939
2940         m_sec_sequence.current() = m_sec_sequence.begin();
2941
2942         if (!m_simulate)
2943         {
2944                 m_tuneTimer->start(0,true);
2945                 m_tuning = 1;
2946                 if (m_state != stateTuning)
2947                 {
2948                         m_state = stateTuning;
2949                         m_stateChanged(this);
2950                 }
2951         }
2952         else
2953                 tuneLoop();
2954
2955         return res;
2956
2957 tune_error:
2958         m_tuneTimer->stop();
2959         return res;
2960 }
2961
2962 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2963 {
2964         connection = new eConnection(this, m_stateChanged.connect(stateChange));
2965         return 0;
2966 }
2967
2968 RESULT eDVBFrontend::setVoltage(int voltage)
2969 {
2970 #if HAVE_DVB_API_VERSION < 3
2971         secVoltage vlt;
2972 #else
2973         bool increased=false;
2974         fe_sec_voltage_t vlt;
2975 #endif
2976         m_data[CUR_VOLTAGE]=voltage;
2977         switch (voltage)
2978         {
2979         case voltageOff:
2980                 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2981                 vlt = SEC_VOLTAGE_OFF;
2982                 break;
2983         case voltage13_5:
2984 #if HAVE_DVB_API_VERSION < 3
2985                 vlt = SEC_VOLTAGE_13_5;
2986                 break;
2987 #else
2988                 increased = true;
2989 #endif
2990         case voltage13:
2991                 vlt = SEC_VOLTAGE_13;
2992                 break;
2993         case voltage18_5:
2994 #if HAVE_DVB_API_VERSION < 3
2995                 vlt = SEC_VOLTAGE_18_5;
2996                 break;
2997 #else
2998                 increased = true;
2999 #endif
3000         case voltage18:
3001                 vlt = SEC_VOLTAGE_18;
3002                 break;
3003         default:
3004                 return -ENODEV;
3005         }
3006         if (m_simulate)
3007                 return 0;
3008 #if HAVE_DVB_API_VERSION < 3
3009         return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
3010 #else
3011         ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased);
3012         return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
3013 #endif
3014 }
3015
3016 RESULT eDVBFrontend::getState(int &state)
3017 {
3018         state = m_state;
3019         return 0;
3020 }
3021
3022 RESULT eDVBFrontend::setTone(int t)
3023 {
3024 #if HAVE_DVB_API_VERSION < 3
3025         secToneMode_t tone;
3026 #else
3027         fe_sec_tone_mode_t tone;
3028 #endif
3029         m_data[CUR_TONE]=t;
3030         switch (t)
3031         {
3032         case toneOn:
3033                 tone = SEC_TONE_ON;
3034                 break;
3035         case toneOff:
3036                 tone = SEC_TONE_OFF;
3037                 break;
3038         default:
3039                 return -ENODEV;
3040         }
3041         if (m_simulate)
3042                 return 0;
3043 #if HAVE_DVB_API_VERSION < 3    
3044         return ::ioctl(m_secfd, SEC_SET_TONE, tone);
3045 #else   
3046         return ::ioctl(m_fd, FE_SET_TONE, tone);
3047 #endif
3048 }
3049
3050 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
3051         #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
3052 #endif
3053
3054 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
3055 {
3056         if (m_simulate)
3057                 return 0;
3058
3059 #if HAVE_DVB_API_VERSION < 3
3060         struct secCommand cmd;
3061         cmd.type = SEC_CMDTYPE_DISEQC_RAW;
3062         cmd.u.diseqc.cmdtype = diseqc.data[0];
3063         cmd.u.diseqc.addr = diseqc.data[1];
3064         cmd.u.diseqc.cmd = diseqc.data[2];
3065         cmd.u.diseqc.numParams = diseqc.len-3;
3066         memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
3067         if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
3068 #else
3069         struct dvb_diseqc_master_cmd cmd;
3070         memcpy(cmd.msg, diseqc.data, diseqc.len);
3071         cmd.msg_len = diseqc.len;
3072         if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
3073 #endif
3074                 return -EINVAL;
3075         return 0;
3076 }
3077
3078 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
3079         #define SEC_DISEQC_SEND_BURST _IO('o', 96)
3080 #endif
3081 RESULT eDVBFrontend::sendToneburst(int burst)
3082 {
3083         if (m_simulate)
3084                 return 0;
3085 #if HAVE_DVB_API_VERSION < 3
3086         secMiniCmd cmd = SEC_MINI_NONE;
3087 #else
3088         fe_sec_mini_cmd_t cmd = SEC_MINI_A;
3089 #endif
3090         if ( burst == eDVBSatelliteDiseqcParameters::A )
3091                 cmd = SEC_MINI_A;
3092         else if ( burst == eDVBSatelliteDiseqcParameters::B )
3093                 cmd = SEC_MINI_B;
3094 #if HAVE_DVB_API_VERSION < 3
3095         if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
3096                 return -EINVAL;
3097 #else
3098         if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
3099                 return -EINVAL;
3100 #endif
3101         return 0;
3102 }
3103
3104 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
3105 {
3106         m_sec = sec;
3107         return 0;
3108 }
3109
3110 RESULT eDVBFrontend::setSecSequence(eSecCommandList &list)
3111 {
3112         if (m_data[SATCR] != -1 && m_sec_sequence.current() != m_sec_sequence.end())
3113                 m_sec_sequence.push_back(list);
3114         else
3115                 m_sec_sequence = list;
3116         return 0;
3117 }
3118
3119 bool eDVBFrontend::isScheduledSendDiseqc()
3120 {
3121         bool has_senddiseqc = false;
3122         if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
3123         {
3124                 eSecCommandList::iterator cur = m_sec_sequence.current();
3125                 while(cur != m_sec_sequence.end())
3126                 {
3127                         if (((cur++)->cmd == eSecCommand::SEND_DISEQC))
3128                         {
3129                                 has_senddiseqc = true;
3130                                 break;
3131                         }
3132                 }
3133         }
3134         return has_senddiseqc;
3135 }
3136
3137 RESULT eDVBFrontend::getData(int num, long &data)
3138 {
3139         if ( num < NUM_DATA_ENTRIES )
3140         {
3141                 data = m_data[num];
3142                 return 0;
3143         }
3144         return -EINVAL;
3145 }
3146
3147 RESULT eDVBFrontend::setData(int num, long val)
3148 {
3149         if ( num < NUM_DATA_ENTRIES )
3150         {
3151                 m_data[num] = val;
3152                 return 0;
3153         }
3154         return -EINVAL;
3155 }
3156
3157 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
3158 {
3159         int type;
3160         int score = 0;
3161         bool preferred = (eDVBFrontend::getPreferredFrontend() >= 0 && m_slotid == eDVBFrontend::getPreferredFrontend());
3162
3163         if (feparm->getSystem(type) || !m_enabled)
3164                 return 0;
3165
3166         if (type == eDVBFrontend::feSatellite)
3167         {
3168                 eDVBFrontendParametersSatellite sat_parm;
3169                 bool can_handle_dvbs, can_handle_dvbs2;
3170                 can_handle_dvbs = supportsDeliverySystem(SYS_DVBS, true);
3171                 can_handle_dvbs2 = supportsDeliverySystem(SYS_DVBS2, true);
3172                 if (feparm->getDVBS(sat_parm) < 0)
3173                 {
3174                         return 0;
3175                 }
3176                 if (sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S2 && !can_handle_dvbs2)
3177                 {
3178                         return 0;
3179                 }
3180                 if (sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S && !can_handle_dvbs)
3181                 {
3182                         return 0;
3183                 }
3184                 score = m_sec ? m_sec->canTune(sat_parm, this, 1 << m_slotid) : 0;
3185                 if (score > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S && can_handle_dvbs2)
3186                 {
3187                         /* prefer to use a S tuner, try to keep S2 free for S2 transponders */
3188                         score--;
3189                 }
3190         }
3191
3192         else if (type == eDVBFrontend::feCable)
3193         {
3194                 eDVBFrontendParametersCable cab_parm;
3195                 if (feparm->getDVBC(cab_parm) < 0)
3196                 {
3197                         return 0;
3198                 }
3199 #if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 6
3200                 if (!supportsDeliverySystem(SYS_DVBC_ANNEX_A, true))
3201                 {
3202                         return 0;
3203                 }
3204 #else
3205                 if (!supportsDeliverySystem(SYS_DVBC_ANNEX_AC, true))
3206                 {
3207                         return 0;
3208                 }
3209 #endif
3210                 score = 2;
3211         }
3212
3213         else if (type == eDVBFrontend::feTerrestrial)
3214         {
3215                 eDVBFrontendParametersTerrestrial ter_parm;
3216                 bool can_handle_dvbt, can_handle_dvbt2;
3217                 can_handle_dvbt = supportsDeliverySystem(SYS_DVBT, true);
3218                 can_handle_dvbt2 = supportsDeliverySystem(SYS_DVBT2, true);
3219                 if (feparm->getDVBT(ter_parm) < 0)
3220                 {
3221                         return 0;
3222                 }
3223                 if (ter_parm.system == eDVBFrontendParametersTerrestrial::System_DVB_T && !can_handle_dvbt)
3224                 {
3225                         return 0;
3226                 }
3227                 if (ter_parm.system == eDVBFrontendParametersTerrestrial::System_DVB_T2 && !can_handle_dvbt2)
3228                 {
3229                         return 0;
3230                 }
3231                 score = 2;
3232                 if (ter_parm.system == eDVBFrontendParametersTerrestrial::System_DVB_T && can_handle_dvbt2)
3233                 {
3234                         /* prefer to use a T tuner, try to keep T2 free for T2 transponders */
3235                         score--;
3236                 }
3237         }
3238
3239         if (score && preferred)
3240         {
3241                 /* make 'sure' we always prefer this frontend */
3242                 score += 100000;
3243         }
3244
3245         return score;
3246 }
3247
3248 bool eDVBFrontend::supportsDeliverySystem(const fe_delivery_system_t &sys, bool obeywhitelist)
3249 {
3250         std::map<fe_delivery_system_t, bool>::iterator it = m_delsys.find(sys);
3251         if (it != m_delsys.end() && it->second)
3252         {
3253                 if (obeywhitelist && !m_delsys_whitelist.empty())
3254                 {
3255                         it = m_delsys_whitelist.find(sys);
3256                         if (it == m_delsys_whitelist.end() || !it->second) return false;
3257                 }
3258                 return true;
3259         }
3260         return false;
3261 }
3262
3263 void eDVBFrontend::setDeliverySystemWhitelist(const std::vector<fe_delivery_system_t> &whitelist)
3264 {
3265         m_delsys_whitelist.clear();
3266         for (unsigned int i = 0; i < whitelist.size(); i++)
3267         {
3268                 m_delsys_whitelist[whitelist[i]] = true;
3269         }
3270         if (m_simulate_fe)
3271         {
3272                 m_simulate_fe->setDeliverySystemWhitelist(whitelist);
3273         }
3274 }
3275
3276 bool eDVBFrontend::setSlotInfo(ePyObject obj)
3277 {
3278         ePyObject Id, Descr, Enabled, IsDVBS2, IsDVBT2, frontendId;
3279         if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 6)
3280                 goto arg_error;
3281         Id = PyTuple_GET_ITEM(obj, 0);
3282         Descr = PyTuple_GET_ITEM(obj, 1);
3283         Enabled = PyTuple_GET_ITEM(obj, 2);
3284         IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
3285         IsDVBT2 = PyTuple_GET_ITEM(obj, 4);
3286         frontendId = PyTuple_GET_ITEM(obj, 5);
3287         m_slotid = PyInt_AsLong(Id);
3288         if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2) || !PyBool_Check(IsDVBT2) || !PyInt_Check(frontendId))
3289                 goto arg_error;
3290         strcpy(m_description, PyString_AS_STRING(Descr));
3291         if (PyInt_AsLong(frontendId) == -1 || PyInt_AsLong(frontendId) != m_dvbid) {
3292 //              eDebugNoSimulate("skip slotinfo for slotid %d, descr %s",
3293 //                      m_slotid, m_description);
3294                 return false;
3295         }
3296         m_enabled = (Enabled == Py_True);
3297         // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
3298         m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
3299                 !!strstr(m_description, "Alps BSBE2") ||
3300                 !!strstr(m_description, "Alps -S") ||
3301                 !!strstr(m_description, "BCM4501");
3302         if (IsDVBS2 == Py_True)
3303         {
3304                 /* HACK for legacy dvb api without DELSYS support */
3305                 m_delsys[SYS_DVBS2] = true;
3306         }
3307         if (IsDVBT2 == Py_True)
3308         {
3309                 /* HACK for legacy dvb api without DELSYS support */
3310                 m_delsys[SYS_DVBT2] = true;
3311         }
3312
3313         eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s, DVB-T2 %s",
3314                 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" );
3315         return true;
3316 arg_error:
3317         PyErr_SetString(PyExc_StandardError,
3318                 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");
3319         return false;
3320 }