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