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