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