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