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