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