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