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