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