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