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