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