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