fix bug for DVB-T2.
[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[7];
2262                         struct dtv_properties cmdseq;
2263                         cmdseq.props = p;
2264                         p[0].cmd = DTV_CLEAR;
2265                         p[1].cmd = DTV_FREQUENCY,       p[1].u.data = parm_frequency;
2266                         p[2].cmd = DTV_MODULATION,      p[2].u.data = parm_u_qam_modulation;
2267                         p[3].cmd = DTV_SYMBOL_RATE,     p[3].u.data = parm_u_qam_symbol_rate;
2268                         p[4].cmd = DTV_INNER_FEC,       p[4].u.data = parm_u_qam_fec_inner;
2269                         p[5].cmd = DTV_INVERSION,       p[5].u.data = parm_inversion;
2270                         p[6].cmd = DTV_TUNE;
2271                         cmdseq.num = 7;
2272                         if (ioctl(m_fd, FE_SET_PROPERTY, &cmdseq) == -1)
2273                         {
2274                                 perror("FE_SET_PROPERTY failed");
2275                                 return;
2276                         }
2277                 }
2278                 else if (m_type == iDVBFrontend::feTerrestrial)
2279                 {
2280                         fe_delivery_system_t system = SYS_DVBT;
2281                         switch (oparm.ter.system)
2282                         {
2283                                 default:
2284                                 case eDVBFrontendParametersTerrestrial::System_DVB_T: system = SYS_DVBT; break;
2285                                 case eDVBFrontendParametersTerrestrial::System_DVB_T2: system = SYS_DVBT2; break;
2286                         }
2287                         int bandwidth = 0;
2288                         switch (oparm.ter.bandwidth)
2289                         {
2290                                 case eDVBFrontendParametersTerrestrial::Bandwidth_8MHz: bandwidth = 8000000; break;
2291                                 case eDVBFrontendParametersTerrestrial::Bandwidth_7MHz: bandwidth = 7000000; break;
2292                                 case eDVBFrontendParametersTerrestrial::Bandwidth_6MHz: bandwidth = 6000000; break;
2293                                 default:
2294                                 case eDVBFrontendParametersTerrestrial::Bandwidth_Auto: bandwidth = 0; break;
2295                                 case eDVBFrontendParametersTerrestrial::Bandwidth_5MHz: bandwidth = 5000000; break;
2296                                 case eDVBFrontendParametersTerrestrial::Bandwidth_10MHz: bandwidth = 10000000; break;
2297                                 case eDVBFrontendParametersTerrestrial::Bandwidth_1_712MHz: bandwidth = 1712000; break;
2298                         }
2299                         struct dtv_property p[13];
2300                         struct dtv_properties cmdseq;
2301                         cmdseq.props = p;
2302                         cmdseq.num = 0;
2303                         p[cmdseq.num].cmd = DTV_CLEAR, cmdseq.num++;
2304                         p[cmdseq.num].cmd = DTV_DELIVERY_SYSTEM, p[cmdseq.num].u.data = system, cmdseq.num++;
2305                         p[cmdseq.num].cmd = DTV_FREQUENCY,      p[cmdseq.num].u.data = parm_frequency, cmdseq.num++;
2306                         p[cmdseq.num].cmd = DTV_CODE_RATE_LP,   p[cmdseq.num].u.data = parm_u_ofdm_code_rate_LP, cmdseq.num++;
2307                         p[cmdseq.num].cmd = DTV_CODE_RATE_HP,   p[cmdseq.num].u.data = parm_u_ofdm_code_rate_HP, cmdseq.num++;
2308                         p[cmdseq.num].cmd = DTV_MODULATION,     p[cmdseq.num].u.data = parm_u_ofdm_constellation, cmdseq.num++;
2309                         p[cmdseq.num].cmd = DTV_TRANSMISSION_MODE,      p[cmdseq.num].u.data = parm_u_ofdm_transmission_mode, cmdseq.num++;
2310                         p[cmdseq.num].cmd = DTV_GUARD_INTERVAL, p[cmdseq.num].u.data = parm_u_ofdm_guard_interval, cmdseq.num++;
2311                         p[cmdseq.num].cmd = DTV_HIERARCHY,      p[cmdseq.num].u.data = parm_u_ofdm_hierarchy_information, cmdseq.num++;
2312                         p[cmdseq.num].cmd = DTV_BANDWIDTH_HZ,   p[cmdseq.num].u.data = bandwidth, cmdseq.num++;
2313                         p[cmdseq.num].cmd = DTV_INVERSION,      p[cmdseq.num].u.data = parm_inversion, cmdseq.num++;
2314 #ifdef DTV_DVBT2_PLP_ID
2315                         p[cmdseq.num].cmd = DTV_DVBT2_PLP_ID    ,       p[cmdseq.num].u.data = oparm.ter.plpid, cmdseq.num++;
2316 #endif
2317                         p[cmdseq.num].cmd = DTV_TUNE, cmdseq.num++;
2318                         if (ioctl(m_fd, FE_SET_PROPERTY, &cmdseq) == -1)
2319                         {
2320                                 perror("FE_SET_PROPERTY failed");
2321                                 return;
2322                         }
2323                 }
2324                 else
2325 #endif
2326                 {
2327                         if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
2328                         {
2329                                 perror("FE_SET_FRONTEND failed");
2330                                 return;
2331                         }
2332                 }
2333         }
2334 }
2335
2336 RESULT eDVBFrontend::getFrontendType(int &t)
2337 {
2338         if (m_type == -1)
2339                 return -ENODEV;
2340         t = m_type;
2341         return 0;
2342 }
2343
2344 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
2345 {
2346         int res;
2347         if (!m_sec)
2348         {
2349                 eWarning("no SEC module active!");
2350                 return -ENOENT;
2351         }
2352         res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
2353         if (!res)
2354         {
2355 #if HAVE_DVB_API_VERSION >= 3
2356                 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",
2357                         feparm.system,
2358                         feparm.frequency,
2359                         feparm.polarisation,
2360                         feparm.symbol_rate,
2361                         feparm.inversion,
2362                         feparm.fec,
2363                         feparm.orbital_position,
2364                         feparm.system,
2365                         feparm.modulation,
2366                         feparm.pilot,
2367                         feparm.rolloff);
2368 #else
2369                 eDebugNoSimulate("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
2370                         feparm.system,
2371                         feparm.frequency,
2372                         feparm.polarisation,
2373                         feparm.symbol_rate,
2374                         feparm.inversion,
2375                         feparm.fec,
2376                         feparm.orbital_position);
2377 #endif
2378                 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
2379                 switch (feparm.inversion)
2380                 {
2381                         case eDVBFrontendParametersSatellite::Inversion_On:
2382                                 parm_inversion = INVERSION_ON;
2383                                 break;
2384                         case eDVBFrontendParametersSatellite::Inversion_Off:
2385                                 parm_inversion = INVERSION_OFF;
2386                                 break;
2387                         default:
2388                         case eDVBFrontendParametersSatellite::Inversion_Unknown:
2389                                 parm_inversion = INVERSION_AUTO;
2390                                 break;
2391                 }
2392                 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S)
2393                 {
2394                         switch (feparm.fec)
2395                         {
2396                                 case eDVBFrontendParametersSatellite::FEC_None:
2397                                         parm_u_qpsk_fec_inner = FEC_NONE;
2398                                         break;
2399                                 case eDVBFrontendParametersSatellite::FEC_1_2:
2400                                         parm_u_qpsk_fec_inner = FEC_1_2;
2401                                         break;
2402                                 case eDVBFrontendParametersSatellite::FEC_2_3:
2403                                         parm_u_qpsk_fec_inner = FEC_2_3;
2404                                         break;
2405                                 case eDVBFrontendParametersSatellite::FEC_3_4:
2406                                         parm_u_qpsk_fec_inner = FEC_3_4;
2407                                         break;
2408                                 case eDVBFrontendParametersSatellite::FEC_5_6:
2409                                         parm_u_qpsk_fec_inner = FEC_5_6;
2410                                         break;
2411                                 case eDVBFrontendParametersSatellite::FEC_7_8:
2412                                         parm_u_qpsk_fec_inner = FEC_7_8;
2413                                         break;
2414                                 default:
2415                                         eDebugNoSimulate("no valid fec for DVB-S set.. assume auto");
2416                                 case eDVBFrontendParametersSatellite::FEC_Auto:
2417                                         parm_u_qpsk_fec_inner = FEC_AUTO;
2418                                         break;
2419                         }
2420                 }
2421 #if HAVE_DVB_API_VERSION >= 3
2422                 else // DVB_S2
2423                 {
2424                         switch (feparm.fec)
2425                         {
2426                                 case eDVBFrontendParametersSatellite::FEC_1_2:
2427                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
2428                                         break;
2429                                 case eDVBFrontendParametersSatellite::FEC_2_3:
2430                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
2431                                         break;
2432                                 case eDVBFrontendParametersSatellite::FEC_3_4:
2433                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
2434                                         break;
2435                                 case eDVBFrontendParametersSatellite::FEC_3_5:
2436                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
2437                                         break;
2438                                 case eDVBFrontendParametersSatellite::FEC_4_5:
2439                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
2440                                         break;
2441                                 case eDVBFrontendParametersSatellite::FEC_5_6:
2442                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
2443                                         break;
2444                                 case eDVBFrontendParametersSatellite::FEC_7_8:
2445                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
2446                                         break;
2447                                 case eDVBFrontendParametersSatellite::FEC_8_9:
2448                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
2449                                         break;
2450                                 case eDVBFrontendParametersSatellite::FEC_9_10:
2451                                         parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
2452                                         break;
2453                                 default:
2454                                         eDebugNoSimulate("no valid fec for DVB-S2 set.. abort !!");
2455                                         return -EINVAL;
2456                         }
2457 #if HAVE_DVB_API_VERSION < 5
2458                         parm_inversion = (fe_spectral_inversion_t)((feparm.rolloff << 2) | parm_inversion); // Hack.. we use bit 2..3 of inversion param for rolloff
2459                         parm_inversion = (fe_spectral_inversion_t)((feparm.pilot << 4) | parm_inversion); // Hack.. we use bit 4..5 of inversion param for pilot
2460                         if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation_8PSK) 
2461                         {
2462                                 parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
2463                                 // 8PSK fec driver values are decimal 9 bigger
2464                         }
2465 #endif
2466                 }
2467 #endif
2468                 // FIXME !!! get frequency range from tuner
2469                 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
2470                 {
2471                         eDebugNoSimulate("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
2472                         return -EINVAL;
2473                 }
2474                 eDebugNoSimulate("tuning to %d mhz", parm_frequency/1000);
2475         }
2476         oparm.sat = feparm;
2477         return res;
2478 }
2479
2480 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
2481 {
2482 #if HAVE_DVB_API_VERSION < 3
2483         parm_frequency = feparm.frequency;
2484 #else
2485         parm_frequency = feparm.frequency * 1000;
2486 #endif
2487         parm_u_qam_symbol_rate = feparm.symbol_rate;
2488         switch (feparm.modulation)
2489         {
2490         case eDVBFrontendParametersCable::Modulation_QAM16:
2491                 parm_u_qam_modulation = QAM_16;
2492                 break;
2493         case eDVBFrontendParametersCable::Modulation_QAM32:
2494                 parm_u_qam_modulation = QAM_32;
2495                 break;
2496         case eDVBFrontendParametersCable::Modulation_QAM64:
2497                 parm_u_qam_modulation = QAM_64;
2498                 break;
2499         case eDVBFrontendParametersCable::Modulation_QAM128:
2500                 parm_u_qam_modulation = QAM_128;
2501                 break;
2502         case eDVBFrontendParametersCable::Modulation_QAM256:
2503                 parm_u_qam_modulation = QAM_256;
2504                 break;
2505         default:
2506         case eDVBFrontendParametersCable::Modulation_Auto:
2507                 parm_u_qam_modulation = QAM_AUTO;
2508                 break;
2509         }
2510         switch (feparm.inversion)
2511         {
2512         case eDVBFrontendParametersCable::Inversion_On:
2513                 parm_inversion = INVERSION_ON;
2514                 break;
2515         case eDVBFrontendParametersCable::Inversion_Off:
2516                 parm_inversion = INVERSION_OFF;
2517                 break;
2518         default:
2519         case eDVBFrontendParametersCable::Inversion_Unknown:
2520                 parm_inversion = INVERSION_AUTO;
2521                 break;
2522         }
2523         switch (feparm.fec_inner)
2524         {
2525         case eDVBFrontendParametersCable::FEC_None:
2526                 parm_u_qam_fec_inner = FEC_NONE;
2527                 break;
2528         case eDVBFrontendParametersCable::FEC_1_2:
2529                 parm_u_qam_fec_inner = FEC_1_2;
2530                 break;
2531         case eDVBFrontendParametersCable::FEC_2_3:
2532                 parm_u_qam_fec_inner = FEC_2_3;
2533                 break;
2534         case eDVBFrontendParametersCable::FEC_3_4:
2535                 parm_u_qam_fec_inner = FEC_3_4;
2536                 break;
2537         case eDVBFrontendParametersCable::FEC_5_6:
2538                 parm_u_qam_fec_inner = FEC_5_6;
2539                 break;
2540         case eDVBFrontendParametersCable::FEC_7_8:
2541                 parm_u_qam_fec_inner = FEC_7_8;
2542                 break;
2543 #if HAVE_DVB_API_VERSION >= 3
2544         case eDVBFrontendParametersCable::FEC_8_9:
2545                 parm_u_qam_fec_inner = FEC_8_9;
2546                 break;
2547 #endif
2548         default:
2549         case eDVBFrontendParametersCable::FEC_Auto:
2550                 parm_u_qam_fec_inner = FEC_AUTO;
2551                 break;
2552         }
2553         eDebugNoSimulate("tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
2554                 parm_frequency/1000,
2555                 parm_u_qam_symbol_rate,
2556                 parm_u_qam_fec_inner,
2557                 parm_u_qam_modulation,
2558                 parm_inversion);
2559         oparm.cab = feparm;
2560         return 0;
2561 }
2562
2563 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
2564 {
2565         parm_frequency = feparm.frequency;
2566
2567         switch (feparm.bandwidth)
2568         {
2569         case eDVBFrontendParametersTerrestrial::Bandwidth_8MHz:
2570                 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
2571                 break;
2572         case eDVBFrontendParametersTerrestrial::Bandwidth_7MHz:
2573                 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
2574                 break;
2575         case eDVBFrontendParametersTerrestrial::Bandwidth_6MHz:
2576                 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
2577                 break;
2578         case eDVBFrontendParametersTerrestrial::Bandwidth_5MHz:
2579                 parm_u_ofdm_bandwidth = BANDWIDTH_5_MHZ;
2580                 break;
2581         case eDVBFrontendParametersTerrestrial::Bandwidth_10MHz:
2582                 parm_u_ofdm_bandwidth = BANDWIDTH_10_MHZ;
2583                 break;
2584         case eDVBFrontendParametersTerrestrial::Bandwidth_1_712MHz:
2585                 parm_u_ofdm_bandwidth = BANDWIDTH_1_712_MHZ;
2586                 break;
2587         default:
2588         case eDVBFrontendParametersTerrestrial::Bandwidth_Auto:
2589                 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
2590                 break;
2591         }
2592         switch (feparm.code_rate_LP)
2593         {
2594         case eDVBFrontendParametersTerrestrial::FEC_1_2:
2595                 parm_u_ofdm_code_rate_LP = FEC_1_2;
2596                 break;
2597         case eDVBFrontendParametersTerrestrial::FEC_2_3:
2598                 parm_u_ofdm_code_rate_LP = FEC_2_3;
2599                 break;
2600         case eDVBFrontendParametersTerrestrial::FEC_3_4:
2601                 parm_u_ofdm_code_rate_LP = FEC_3_4;
2602                 break;
2603         case eDVBFrontendParametersTerrestrial::FEC_5_6:
2604                 parm_u_ofdm_code_rate_LP = FEC_5_6;
2605                 break;
2606         case eDVBFrontendParametersTerrestrial::FEC_7_8:
2607                 parm_u_ofdm_code_rate_LP = FEC_7_8;
2608                 break;
2609         case eDVBFrontendParametersTerrestrial::FEC_6_7:
2610                 parm_u_ofdm_code_rate_LP = FEC_6_7;
2611                 break;
2612         case eDVBFrontendParametersTerrestrial::FEC_8_9:
2613                 parm_u_ofdm_code_rate_LP = FEC_8_9;
2614                 break;
2615         default:
2616         case eDVBFrontendParametersTerrestrial::FEC_Auto:
2617                 parm_u_ofdm_code_rate_LP = FEC_AUTO;
2618                 break;
2619         }
2620         switch (feparm.code_rate_HP)
2621         {
2622         case eDVBFrontendParametersTerrestrial::FEC_1_2:
2623                 parm_u_ofdm_code_rate_HP = FEC_1_2;
2624                 break;
2625         case eDVBFrontendParametersTerrestrial::FEC_2_3:
2626                 parm_u_ofdm_code_rate_HP = FEC_2_3;
2627                 break;
2628         case eDVBFrontendParametersTerrestrial::FEC_3_4:
2629                 parm_u_ofdm_code_rate_HP = FEC_3_4;
2630                 break;
2631         case eDVBFrontendParametersTerrestrial::FEC_5_6:
2632                 parm_u_ofdm_code_rate_HP = FEC_5_6;
2633                 break;
2634         case eDVBFrontendParametersTerrestrial::FEC_7_8:
2635                 parm_u_ofdm_code_rate_HP = FEC_7_8;
2636                 break;
2637         case eDVBFrontendParametersTerrestrial::FEC_6_7:
2638                 parm_u_ofdm_code_rate_HP = FEC_6_7;
2639                 break;
2640         case eDVBFrontendParametersTerrestrial::FEC_8_9:
2641                 parm_u_ofdm_code_rate_HP = FEC_8_9;
2642                 break;
2643         default:
2644         case eDVBFrontendParametersTerrestrial::FEC_Auto:
2645                 parm_u_ofdm_code_rate_HP = FEC_AUTO;
2646                 break;
2647         }
2648         switch (feparm.modulation)
2649         {
2650         case eDVBFrontendParametersTerrestrial::Modulation_QPSK:
2651                 parm_u_ofdm_constellation = QPSK;
2652                 break;
2653         case eDVBFrontendParametersTerrestrial::Modulation_QAM16:
2654                 parm_u_ofdm_constellation = QAM_16;
2655                 break;
2656         case eDVBFrontendParametersTerrestrial::Modulation_QAM64:
2657                 parm_u_ofdm_constellation = QAM_64;
2658                 break;
2659         case eDVBFrontendParametersTerrestrial::Modulation_QAM256:
2660                 parm_u_ofdm_constellation = QAM_256;
2661                 break;
2662         default:
2663         case eDVBFrontendParametersTerrestrial::Modulation_Auto:
2664                 parm_u_ofdm_constellation = QAM_AUTO;
2665                 break;
2666         }
2667         switch (feparm.transmission_mode)
2668         {
2669         case eDVBFrontendParametersTerrestrial::TransmissionMode_2k:
2670                 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
2671                 break;
2672         case eDVBFrontendParametersTerrestrial::TransmissionMode_8k:
2673                 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
2674                 break;
2675         case eDVBFrontendParametersTerrestrial::TransmissionMode_4k:
2676                 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_4K;
2677                 break;
2678         case eDVBFrontendParametersTerrestrial::TransmissionMode_1k:
2679                 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_1K;
2680                 break;
2681         case eDVBFrontendParametersTerrestrial::TransmissionMode_16k:
2682                 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_16K;
2683                 break;
2684         case eDVBFrontendParametersTerrestrial::TransmissionMode_32k:
2685                 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_32K;
2686                 break;
2687         default:
2688         case eDVBFrontendParametersTerrestrial::TransmissionMode_Auto:
2689                 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
2690                 break;
2691         }
2692         switch (feparm.guard_interval)
2693         {
2694                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_32:
2695                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
2696                         break;
2697                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_16:
2698                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
2699                         break;
2700                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_8:
2701                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
2702                         break;
2703                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_4:
2704                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
2705                         break;
2706                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_128:
2707                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_128;
2708                         break;
2709                 case eDVBFrontendParametersTerrestrial::GuardInterval_19_128:
2710                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_19_128;
2711                         break;
2712                 case eDVBFrontendParametersTerrestrial::GuardInterval_19_256:
2713                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_19_256;
2714                         break;
2715                 default:
2716                 case eDVBFrontendParametersTerrestrial::GuardInterval_Auto:
2717                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
2718                         break;
2719         }
2720         switch (feparm.hierarchy)
2721         {
2722                 case eDVBFrontendParametersTerrestrial::Hierarchy_None:
2723                         parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
2724                         break;
2725                 case eDVBFrontendParametersTerrestrial::Hierarchy_1:
2726                         parm_u_ofdm_hierarchy_information = HIERARCHY_1;
2727                         break;
2728                 case eDVBFrontendParametersTerrestrial::Hierarchy_2:
2729                         parm_u_ofdm_hierarchy_information = HIERARCHY_2;
2730                         break;
2731                 case eDVBFrontendParametersTerrestrial::Hierarchy_4:
2732                         parm_u_ofdm_hierarchy_information = HIERARCHY_4;
2733                         break;
2734                 default:
2735                 case eDVBFrontendParametersTerrestrial::Hierarchy_Auto:
2736                         parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
2737                         break;
2738         }
2739         switch (feparm.inversion)
2740         {
2741         case eDVBFrontendParametersTerrestrial::Inversion_On:
2742                 parm_inversion = INVERSION_ON;
2743                 break;
2744         case eDVBFrontendParametersTerrestrial::Inversion_Off:
2745                 parm_inversion = INVERSION_OFF;
2746                 break;
2747         default:
2748         case eDVBFrontendParametersTerrestrial::Inversion_Unknown:
2749                 parm_inversion = INVERSION_AUTO;
2750                 break;
2751         }
2752         eDebug("tuning to %d khz, bandwidth %d, crl %d, crh %d, modulation %d, tm %d, guard %d, hierarchy %d, inversion %d",
2753                 parm_frequency/1000,
2754                 parm_u_ofdm_bandwidth,
2755                 parm_u_ofdm_code_rate_LP,
2756                 parm_u_ofdm_code_rate_HP,
2757                 parm_u_ofdm_constellation,
2758                 parm_u_ofdm_transmission_mode,
2759                 parm_u_ofdm_guard_interval,
2760                 parm_u_ofdm_hierarchy_information,
2761                 parm_inversion);
2762         oparm.ter = feparm;
2763         return 0;
2764 }
2765
2766 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2767 {
2768         unsigned int timeout = 5000;
2769         eDebugNoSimulate("(%d)tune", m_dvbid);
2770
2771         m_timeout->stop();
2772
2773         int res=0;
2774
2775         if (!m_sn && !m_simulate)
2776         {
2777                 eDebug("no frontend device opened... do not try to tune !!!");
2778                 res = -ENODEV;
2779                 goto tune_error;
2780         }
2781
2782         if (m_type == -1)
2783         {
2784                 res = -ENODEV;
2785                 goto tune_error;
2786         }
2787
2788         if (!m_simulate)
2789                 m_sn->stop();
2790
2791         m_sec_sequence.clear();
2792
2793         where.calcLockTimeout(timeout);
2794
2795         switch (m_type)
2796         {
2797         case feSatellite:
2798         {
2799                 eDVBFrontendParametersSatellite feparm;
2800                 if (where.getDVBS(feparm))
2801                 {
2802                         eDebug("no dvbs data!");
2803                         res = -EINVAL;
2804                         goto tune_error;
2805                 }
2806                 if (m_rotor_mode != feparm.no_rotor_command_on_tune && !feparm.no_rotor_command_on_tune)
2807                 {
2808                         eDVBFrontend *sec_fe = this;
2809                         long tmp = m_data[LINKED_PREV_PTR];
2810                         while (tmp != -1)
2811                         {
2812                                 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
2813                                 sec_fe = linked_fe->m_frontend;
2814                                 sec_fe->getData(LINKED_NEXT_PTR, tmp);
2815                         }
2816                         eDebug("(fe%d) reset diseqc after leave rotor mode!", m_dvbid);
2817                         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
2818                 }
2819                 m_rotor_mode = feparm.no_rotor_command_on_tune;
2820                 if (!m_simulate)
2821                         m_sec->setRotorMoving(m_slotid, false);
2822                 res=prepare_sat(feparm, timeout);
2823                 if (res)
2824                         goto tune_error;
2825
2826                 break;
2827         }
2828         case feCable:
2829         {
2830                 eDVBFrontendParametersCable feparm;
2831                 if (where.getDVBC(feparm))
2832                 {
2833                         res = -EINVAL;
2834                         goto tune_error;
2835                 }
2836                 res=prepare_cable(feparm);
2837                 if (res)
2838                         goto tune_error;
2839
2840                 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2841                 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2842                 break;
2843         }
2844         case feTerrestrial:
2845         {
2846                 eDVBFrontendParametersTerrestrial feparm;
2847                 if (where.getDVBT(feparm))
2848                 {
2849                         eDebug("no -T data");
2850                         res = -EINVAL;
2851                         goto tune_error;
2852                 }
2853                 res=prepare_terrestrial(feparm);
2854                 if (res)
2855                         goto tune_error;
2856
2857                 std::string enable_5V;
2858                 char configStr[255];
2859                 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2860                 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2861                 ePythonConfigQuery::getConfigValue(configStr, enable_5V);
2862                 if (enable_5V == "True")
2863                         m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2864                 else
2865                         m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2866                 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2867
2868                 break;
2869         }
2870         }
2871
2872         m_sec_sequence.current() = m_sec_sequence.begin();
2873
2874         if (!m_simulate)
2875         {
2876                 m_tuneTimer->start(0,true);
2877                 m_tuning = 1;
2878                 if (m_state != stateTuning)
2879                 {
2880                         m_state = stateTuning;
2881                         m_stateChanged(this);
2882                 }
2883         }
2884         else
2885                 tuneLoop();
2886
2887         return res;
2888
2889 tune_error:
2890         m_tuneTimer->stop();
2891         return res;
2892 }
2893
2894 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2895 {
2896         connection = new eConnection(this, m_stateChanged.connect(stateChange));
2897         return 0;
2898 }
2899
2900 RESULT eDVBFrontend::setVoltage(int voltage)
2901 {
2902         if (m_type == feCable)
2903                 return -1;
2904 #if HAVE_DVB_API_VERSION < 3
2905         secVoltage vlt;
2906 #else
2907         bool increased=false;
2908         fe_sec_voltage_t vlt;
2909 #endif
2910         m_data[CUR_VOLTAGE]=voltage;
2911         switch (voltage)
2912         {
2913         case voltageOff:
2914                 m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2915                 vlt = SEC_VOLTAGE_OFF;
2916                 break;
2917         case voltage13_5:
2918 #if HAVE_DVB_API_VERSION < 3
2919                 vlt = SEC_VOLTAGE_13_5;
2920                 break;
2921 #else
2922                 increased = true;
2923 #endif
2924         case voltage13:
2925                 vlt = SEC_VOLTAGE_13;
2926                 break;
2927         case voltage18_5:
2928 #if HAVE_DVB_API_VERSION < 3
2929                 vlt = SEC_VOLTAGE_18_5;
2930                 break;
2931 #else
2932                 increased = true;
2933 #endif
2934         case voltage18:
2935                 vlt = SEC_VOLTAGE_18;
2936                 break;
2937         default:
2938                 return -ENODEV;
2939         }
2940         if (m_simulate)
2941                 return 0;
2942 #if HAVE_DVB_API_VERSION < 3
2943         return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
2944 #else
2945         if (m_type == feSatellite && ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
2946                 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
2947         return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2948 #endif
2949 }
2950
2951 RESULT eDVBFrontend::getState(int &state)
2952 {
2953         state = m_state;
2954         return 0;
2955 }
2956
2957 RESULT eDVBFrontend::setTone(int t)
2958 {
2959         if (m_type != feSatellite)
2960                 return -1;
2961 #if HAVE_DVB_API_VERSION < 3
2962         secToneMode_t tone;
2963 #else
2964         fe_sec_tone_mode_t tone;
2965 #endif
2966         m_data[CUR_TONE]=t;
2967         switch (t)
2968         {
2969         case toneOn:
2970                 tone = SEC_TONE_ON;
2971                 break;
2972         case toneOff:
2973                 tone = SEC_TONE_OFF;
2974                 break;
2975         default:
2976                 return -ENODEV;
2977         }
2978         if (m_simulate)
2979                 return 0;
2980 #if HAVE_DVB_API_VERSION < 3    
2981         return ::ioctl(m_secfd, SEC_SET_TONE, tone);
2982 #else   
2983         return ::ioctl(m_fd, FE_SET_TONE, tone);
2984 #endif
2985 }
2986
2987 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
2988         #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
2989 #endif
2990
2991 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2992 {
2993         if (m_simulate)
2994                 return 0;
2995 #if HAVE_DVB_API_VERSION < 3
2996         struct secCommand cmd;
2997         cmd.type = SEC_CMDTYPE_DISEQC_RAW;
2998         cmd.u.diseqc.cmdtype = diseqc.data[0];
2999         cmd.u.diseqc.addr = diseqc.data[1];
3000         cmd.u.diseqc.cmd = diseqc.data[2];
3001         cmd.u.diseqc.numParams = diseqc.len-3;
3002         memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
3003         if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
3004 #else
3005         struct dvb_diseqc_master_cmd cmd;
3006         memcpy(cmd.msg, diseqc.data, diseqc.len);
3007         cmd.msg_len = diseqc.len;
3008         if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
3009 #endif
3010                 return -EINVAL;
3011         return 0;
3012 }
3013
3014 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
3015         #define SEC_DISEQC_SEND_BURST _IO('o', 96)
3016 #endif
3017 RESULT eDVBFrontend::sendToneburst(int burst)
3018 {
3019         if (m_simulate)
3020                 return 0;
3021 #if HAVE_DVB_API_VERSION < 3
3022         secMiniCmd cmd = SEC_MINI_NONE;
3023 #else
3024         fe_sec_mini_cmd_t cmd = SEC_MINI_A;
3025 #endif
3026         if ( burst == eDVBSatelliteDiseqcParameters::A )
3027                 cmd = SEC_MINI_A;
3028         else if ( burst == eDVBSatelliteDiseqcParameters::B )
3029                 cmd = SEC_MINI_B;
3030 #if HAVE_DVB_API_VERSION < 3
3031         if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
3032                 return -EINVAL;
3033 #else
3034         if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
3035                 return -EINVAL;
3036 #endif
3037         return 0;
3038 }
3039
3040 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
3041 {
3042         m_sec = sec;
3043         return 0;
3044 }
3045
3046 RESULT eDVBFrontend::setSecSequence(eSecCommandList &list)
3047 {
3048         if (m_data[SATCR] != -1 && m_sec_sequence.current() != m_sec_sequence.end())
3049                 m_sec_sequence.push_back(list);
3050         else
3051                 m_sec_sequence = list;
3052         return 0;
3053 }
3054
3055 RESULT eDVBFrontend::getData(int num, long &data)
3056 {
3057         if ( num < NUM_DATA_ENTRIES )
3058         {
3059                 data = m_data[num];
3060                 return 0;
3061         }
3062         return -EINVAL;
3063 }
3064
3065 RESULT eDVBFrontend::setData(int num, long val)
3066 {
3067         if ( num < NUM_DATA_ENTRIES )
3068         {
3069                 m_data[num] = val;
3070                 return 0;
3071         }
3072         return -EINVAL;
3073 }
3074
3075 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
3076 {
3077         int type;
3078         if (feparm->getSystem(type) || type != m_type || !m_enabled)
3079                 return 0;
3080         if (m_type == eDVBFrontend::feSatellite)
3081         {
3082                 ASSERT(m_sec);
3083                 eDVBFrontendParametersSatellite sat_parm;
3084                 int ret = feparm->getDVBS(sat_parm);
3085                 ASSERT(!ret);
3086                 if (sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S2 && !m_can_handle_dvbs2)
3087                         return 0;
3088                 ret = m_sec->canTune(sat_parm, this, 1 << m_slotid);
3089                 if (ret > 1 && sat_parm.system == eDVBFrontendParametersSatellite::System_DVB_S && m_can_handle_dvbs2)
3090                         ret -= 1;
3091                 return ret;
3092         }
3093         else if (m_type == eDVBFrontend::feCable)
3094                 return 2;  // more prio for cable frontends
3095         else if (m_type == eDVBFrontend::feTerrestrial)
3096         {
3097                 eDVBFrontendParametersTerrestrial ter_parm;
3098                 if ( feparm->getDVBT(ter_parm) )
3099                 {
3100                         return 0;
3101                 }
3102                 if (ter_parm.system == eDVBFrontendParametersTerrestrial::System_DVB_T2)
3103                 {
3104                         return m_can_handle_dvbt2 ? 1 : 0;
3105                 }
3106                 else // DVB-T
3107                 {
3108                         return m_can_handle_dvbt2 ? 1 : 2;
3109                 }
3110         }
3111         return 0;
3112 }
3113
3114 bool eDVBFrontend::setSlotInfo(ePyObject obj)
3115 {
3116         ePyObject Id, Descr, Enabled, IsDVBS2, IsDVBT2, frontendId;
3117         if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 6)
3118                 goto arg_error;
3119         Id = PyTuple_GET_ITEM(obj, 0);
3120         Descr = PyTuple_GET_ITEM(obj, 1);
3121         Enabled = PyTuple_GET_ITEM(obj, 2);
3122         IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
3123         IsDVBT2 = PyTuple_GET_ITEM(obj, 4);
3124         frontendId = PyTuple_GET_ITEM(obj, 5);
3125         m_slotid = PyInt_AsLong(Id);
3126         if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2) || !PyBool_Check(IsDVBT2) || !PyInt_Check(frontendId))
3127                 goto arg_error;
3128         strcpy(m_description, PyString_AS_STRING(Descr));
3129         if (PyInt_AsLong(frontendId) == -1 || PyInt_AsLong(frontendId) != m_dvbid) {
3130 //              eDebugNoSimulate("skip slotinfo for slotid %d, descr %s",
3131 //                      m_slotid, m_description);
3132                 return false;
3133         }
3134         m_enabled = Enabled == Py_True;
3135         // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
3136         m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
3137                 !!strstr(m_description, "Alps BSBE2") ||
3138                 !!strstr(m_description, "Alps -S") ||
3139                 !!strstr(m_description, "BCM4501");
3140         m_can_handle_dvbs2 = IsDVBS2 == Py_True;
3141         m_can_handle_dvbt2 = IsDVBT2 == Py_True;
3142         eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s, DVB-T2 %s",
3143                 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" );
3144         return true;
3145 arg_error:
3146         PyErr_SetString(PyExc_StandardError,
3147                 "eDVBFrontend::setSlotInfo must get a tuple with first param slotid, second param slot description and third param enabled boolean");
3148         return false;
3149 }