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