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