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