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