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