f163b8b7eb24d3d51647b97d27d337f54bd29d33
[openblackhole/openblackhole-enigma2.git] / lib / dvb / frontend.cpp
1 #include <linux/dvb/version.h>
2
3 #include <lib/dvb/dvb.h>
4 #include <lib/dvb/frontendparms.h>
5 #include <lib/base/cfile.h>
6 #include <lib/base/eerror.h>
7 #include <lib/base/nconfig.h> // access to python config
8 #include <errno.h>
9 #include <unistd.h>
10 #include <fcntl.h>
11 #include <sys/ioctl.h>
12
13 #ifndef I2C_SLAVE_FORCE
14 #define I2C_SLAVE_FORCE 0x0706
15 #endif
16
17 #define eDebugNoSimulate(x...) \
18         do { \
19                 if (!m_simulate) \
20                         eDebug(x); \
21         } while(0)
22 #if 0
23                 else \
24                 { \
25                         eDebugNoNewLineStart("SIMULATE:"); \
26                         eDebugNoNewline(x); \
27                         eDebugNoNewline("\n"); \
28                 }
29 #endif
30
31 #define eDebugNoSimulateNoNewLineStart(x...) \
32         do { \
33                 if (!m_simulate) \
34                         eDebugNoNewLineStart(x); \
35         } while(0)
36 #if 0
37                 else \
38                 { \
39                         eDebugNoNewLineStart("SIMULATE:"); \
40                         eDebugNoNewLine(x); \
41                 }
42 #endif
43
44 void eDVBDiseqcCommand::setCommandString(const char *str)
45 {
46         if (!str)
47                 return;
48         len=0;
49         int slen = strlen(str);
50         if (slen % 2)
51         {
52                 eDebug("[eDVBDiseqcCommand] invalid diseqc command string length (not 2 byte aligned)");
53                 return;
54         }
55         if (slen > MAX_DISEQC_LENGTH*2)
56         {
57                 eDebug("[eDVBDiseqcCommand] invalid diseqc command string length (string is to long)");
58                 return;
59         }
60         unsigned char val=0;
61         for (int i=0; i < slen; ++i)
62         {
63                 unsigned char c = str[i];
64                 switch(c)
65                 {
66                         case '0' ... '9': c-=48; break;
67                         case 'a' ... 'f': c-=87; break;
68                         case 'A' ... 'F': c-=55; break;
69                         default:
70                                 eDebug("[eDVBDiseqcCommand] invalid character in hex string..ignore complete diseqc command !");
71                                 return;
72                 }
73                 if ( i % 2 )
74                 {
75                         val |= c;
76                         data[i/2] = val;
77                 }
78                 else
79                         val = c << 4;
80         }
81         len = slen/2;
82 }
83
84 void eDVBFrontendParametersSatellite::set(const SatelliteDeliverySystemDescriptor &descriptor)
85 {
86         frequency    = descriptor.getFrequency() * 10;
87         symbol_rate  = descriptor.getSymbolRate() * 100;
88         polarisation = descriptor.getPolarization();
89         fec = descriptor.getFecInner();
90         if (fec != FEC_None && fec > FEC_9_10 )
91                 fec = FEC_Auto;
92         inversion = eDVBFrontendParametersSatellite::Inversion_Unknown;
93         pilot = eDVBFrontendParametersSatellite::Pilot_Unknown;
94         orbital_position  = ((descriptor.getOrbitalPosition() >> 12) & 0xF) * 1000;
95         orbital_position += ((descriptor.getOrbitalPosition() >> 8) & 0xF) * 100;
96         orbital_position += ((descriptor.getOrbitalPosition() >> 4) & 0xF) * 10;
97         orbital_position += ((descriptor.getOrbitalPosition()) & 0xF);
98         if (orbital_position && (!descriptor.getWestEastFlag()))
99                 orbital_position = 3600 - orbital_position;
100         system = descriptor.getModulationSystem();
101         modulation = descriptor.getModulation();
102         if (system == System_DVB_S && modulation == Modulation_8PSK)
103         {
104                 eDebug("[eDVBFrontendParametersSatellite] satellite_delivery_descriptor invalid modulation type.. force QPSK");
105                 modulation = Modulation_QPSK;
106         }
107         rolloff = descriptor.getRollOff();
108         if (system == System_DVB_S2)
109         {
110                 eDebug("[eDVBFrontendParametersSatellite] SAT DVB-S2 freq %d, %s, pos %d, sr %d, fec %d, modulation %d, rolloff %d",
111                         frequency,
112                         polarisation ? "hor" : "vert",
113                         orbital_position,
114                         symbol_rate, fec,
115                         modulation,
116                         rolloff);
117         }
118         else
119         {
120                 eDebug("[eDVBFrontendParametersSatellite] SAT DVB-S freq %d, %s, pos %d, sr %d, fec %d",
121                         frequency,
122                         polarisation ? "hor" : "vert",
123                         orbital_position,
124                         symbol_rate, fec);
125         }
126 }
127
128 void eDVBFrontendParametersCable::set(const CableDeliverySystemDescriptor &descriptor)
129 {
130         frequency = descriptor.getFrequency() / 10;
131         symbol_rate = descriptor.getSymbolRate() * 100;
132         switch (descriptor.getFecInner())
133         {
134                 default:
135                 case 0: fec_inner = FEC_Auto; break;
136                 case 1: fec_inner = FEC_1_2; break;
137                 case 2: fec_inner = FEC_2_3; break;
138                 case 3: fec_inner = FEC_3_4; break;
139                 case 4: fec_inner = FEC_5_6; break;
140                 case 5: fec_inner = FEC_7_8; break;
141                 case 6: fec_inner = FEC_8_9; break;
142                 case 7: fec_inner = FEC_3_5; break;
143                 case 8: fec_inner = FEC_4_5; break;
144                 case 9: fec_inner = FEC_9_10; break;
145         }
146         modulation = descriptor.getModulation();
147         if (modulation > Modulation_QAM256)
148                 modulation = Modulation_Auto;
149         inversion = Inversion_Unknown;
150         system = System_DVB_C_ANNEX_A;
151         eDebug("[eDVBFrontendParametersCable] Cable freq %d, mod %d, sr %d, fec %d",
152                 frequency,
153                 modulation, symbol_rate, fec_inner);
154 }
155
156 void eDVBFrontendParametersTerrestrial::set(const TerrestrialDeliverySystemDescriptor &descriptor)
157 {
158         frequency = descriptor.getCentreFrequency() * 10;
159         switch (descriptor.getBandwidth())
160         {
161                 case 0: bandwidth = 8000000; break;
162                 case 1: bandwidth = 7000000; break;
163                 case 2: bandwidth = 6000000; break;
164                 case 3: bandwidth = 5000000; break;
165                 default: bandwidth = 0; break;
166         }
167         code_rate_HP = descriptor.getCodeRateHpStream();
168         if (code_rate_HP > FEC_Auto)
169                 code_rate_HP = FEC_Auto;
170         code_rate_LP = descriptor.getCodeRateLpStream();
171         if (code_rate_LP > FEC_Auto)
172                 code_rate_LP = FEC_Auto;
173         switch (descriptor.getTransmissionMode())
174         {
175                 case 0: transmission_mode = TransmissionMode_2k; break;
176                 case 1: transmission_mode = TransmissionMode_8k; break;
177                 case 2: transmission_mode = TransmissionMode_4k; break;
178                 default: transmission_mode = TransmissionMode_Auto; break;
179         }
180         guard_interval = descriptor.getGuardInterval();
181         if (guard_interval > GuardInterval_1_4)
182                 guard_interval = GuardInterval_Auto;
183         hierarchy = descriptor.getHierarchyInformation();
184         if (hierarchy > Hierarchy_Auto)
185                 hierarchy = Hierarchy_Auto;
186         modulation = descriptor.getConstellation();
187         if (modulation > Modulation_Auto)
188                 modulation = Modulation_Auto;
189         inversion = Inversion_Unknown;
190         system = System_DVB_T;
191         plpid = 0;
192         eDebug("[eDVBFrontendParametersTerrestrial] Terr freq %d, bw %d, cr_hp %d, cr_lp %d, tm_mode %d, guard %d, hierarchy %d, const %d",
193                 frequency, bandwidth, code_rate_HP, code_rate_LP, transmission_mode,
194                 guard_interval, hierarchy, modulation);
195 }
196
197 eDVBFrontendParameters::eDVBFrontendParameters()
198         :m_type(-1), m_flags(0)
199 {
200 }
201
202 DEFINE_REF(eDVBFrontendParameters);
203
204 RESULT eDVBFrontendParameters::getSystem(int &t) const
205 {
206         t = m_type;
207         return (m_type == -1) ? -1 : 0;
208 }
209
210 RESULT eDVBFrontendParameters::getDVBS(eDVBFrontendParametersSatellite &p) const
211 {
212         if (m_type != iDVBFrontend::feSatellite)
213                 return -1;
214         p = sat;
215         return 0;
216 }
217
218 RESULT eDVBFrontendParameters::getDVBC(eDVBFrontendParametersCable &p) const
219 {
220         if (m_type != iDVBFrontend::feCable)
221                 return -1;
222         p = cable;
223         return 0;
224 }
225
226 RESULT eDVBFrontendParameters::getDVBT(eDVBFrontendParametersTerrestrial &p) const
227 {
228         if (m_type != iDVBFrontend::feTerrestrial)
229                 return -1;
230         p = terrestrial;
231         return 0;
232 }
233
234 RESULT eDVBFrontendParameters::getATSC(eDVBFrontendParametersATSC &p) const
235 {
236         if (m_type != iDVBFrontend::feATSC)
237                 return -1;
238         p = atsc;
239         return 0;
240 }
241
242 RESULT eDVBFrontendParameters::setDVBS(const eDVBFrontendParametersSatellite &p, bool no_rotor_command_on_tune)
243 {
244         sat = p;
245         sat.no_rotor_command_on_tune = no_rotor_command_on_tune;
246         m_type = iDVBFrontend::feSatellite;
247         return 0;
248 }
249
250 RESULT eDVBFrontendParameters::setDVBC(const eDVBFrontendParametersCable &p)
251 {
252         cable = p;
253         m_type = iDVBFrontend::feCable;
254         return 0;
255 }
256
257 RESULT eDVBFrontendParameters::setDVBT(const eDVBFrontendParametersTerrestrial &p)
258 {
259         terrestrial = p;
260         m_type = iDVBFrontend::feTerrestrial;
261         return 0;
262 }
263
264 RESULT eDVBFrontendParameters::setATSC(const eDVBFrontendParametersATSC &p)
265 {
266         atsc = p;
267         m_type = iDVBFrontend::feATSC;
268         return 0;
269 }
270
271 RESULT eDVBFrontendParameters::calculateDifference(const iDVBFrontendParameters *parm, int &diff, bool exact) const
272 {
273         if (!parm)
274                 return -1;
275         int type;
276         parm->getSystem(type);
277         if (type != m_type)
278         {
279                 diff = 1<<30; // big difference
280                 return 0;
281         }
282
283         switch (type)
284         {
285                 case iDVBFrontend::feSatellite:
286                 {
287                         eDVBFrontendParametersSatellite osat;
288                         if (parm->getDVBS(osat))
289                                 return -2;
290
291                         if (sat.orbital_position != osat.orbital_position)
292                                 diff = 1<<29;
293                         else if (sat.polarisation != osat.polarisation)
294                                 diff = 1<<28;
295                         else if (exact && sat.fec != osat.fec && sat.fec != eDVBFrontendParametersSatellite::FEC_Auto && osat.fec != eDVBFrontendParametersSatellite::FEC_Auto)
296                                 diff = 1<<27;
297                         else if (exact && sat.modulation != osat.modulation && sat.modulation != eDVBFrontendParametersSatellite::Modulation_Auto && osat.modulation != eDVBFrontendParametersSatellite::Modulation_Auto)
298                                 diff = 1<<27;
299                         else
300                         {
301                                 diff = abs(sat.frequency - osat.frequency);
302                                 diff += abs(sat.symbol_rate - osat.symbol_rate);
303                         }
304                         return 0;
305                 }
306                 case iDVBFrontend::feCable:
307                 {
308                         eDVBFrontendParametersCable ocable;
309                         if (parm->getDVBC(ocable))
310                                 return -2;
311
312                         if (exact && cable.modulation != ocable.modulation
313                                 && cable.modulation != eDVBFrontendParametersCable::Modulation_Auto
314                                 && ocable.modulation != eDVBFrontendParametersCable::Modulation_Auto)
315                                 diff = 1 << 29;
316                         else if (exact && cable.fec_inner != ocable.fec_inner && cable.fec_inner != eDVBFrontendParametersCable::FEC_Auto && ocable.fec_inner != eDVBFrontendParametersCable::FEC_Auto)
317                                 diff = 1 << 27;
318                         else
319                         {
320                                 diff = abs(cable.frequency - ocable.frequency);
321                                 diff += abs(cable.symbol_rate - ocable.symbol_rate);
322                         }
323                         return 0;
324                 }
325                 case iDVBFrontend::feTerrestrial:
326                 {
327                         eDVBFrontendParametersTerrestrial oterrestrial;
328                         if (parm->getDVBT(oterrestrial))
329                                 return -2;
330
331                         if (exact && oterrestrial.bandwidth != terrestrial.bandwidth &&
332                                 oterrestrial.bandwidth && terrestrial.bandwidth)
333                                 diff = 1 << 30;
334                         else if (exact && oterrestrial.modulation != terrestrial.modulation &&
335                                 oterrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation_Auto &&
336                                 terrestrial.modulation != eDVBFrontendParametersTerrestrial::Modulation_Auto)
337                                 diff = 1 << 30;
338                         else if (exact && oterrestrial.transmission_mode != terrestrial.transmission_mode &&
339                                 oterrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode_Auto &&
340                                 terrestrial.transmission_mode != eDVBFrontendParametersTerrestrial::TransmissionMode_Auto)
341                                 diff = 1 << 30;
342                         else if (exact && oterrestrial.guard_interval != terrestrial.guard_interval &&
343                                 oterrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval_Auto &&
344                                 terrestrial.guard_interval != eDVBFrontendParametersTerrestrial::GuardInterval_Auto)
345                                 diff = 1 << 30;
346                         else if (exact && oterrestrial.hierarchy != terrestrial.hierarchy &&
347                                 oterrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy_Auto &&
348                                 terrestrial.hierarchy != eDVBFrontendParametersTerrestrial::Hierarchy_Auto)
349                                 diff = 1 << 30;
350                         else if (exact && oterrestrial.code_rate_LP != terrestrial.code_rate_LP &&
351                                 oterrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC_Auto &&
352                                 terrestrial.code_rate_LP != eDVBFrontendParametersTerrestrial::FEC_Auto)
353                                 diff = 1 << 30;
354                         else if (exact && oterrestrial.code_rate_HP != terrestrial.code_rate_HP &&
355                                 oterrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC_Auto &&
356                                 terrestrial.code_rate_HP != eDVBFrontendParametersTerrestrial::FEC_Auto)
357                                 diff = 1 << 30;
358                         else if (oterrestrial.plpid != terrestrial.plpid)
359                                 diff = 1 << 27;
360                         else if (oterrestrial.system != terrestrial.system)
361                                 diff = 1 << 30;
362                         else
363                                 diff = abs(terrestrial.frequency - oterrestrial.frequency) / 1000;
364                         return 0;
365                 }
366                 case iDVBFrontend::feATSC:
367                 {
368                         eDVBFrontendParametersATSC oatsc;
369                         if (parm->getATSC(oatsc))
370                                 return -2;
371
372                         if (exact && atsc.modulation != oatsc.modulation
373                                 && atsc.modulation != eDVBFrontendParametersATSC::Modulation_Auto
374                                 && oatsc.modulation != eDVBFrontendParametersATSC::Modulation_Auto)
375                                 diff = 1 << 29;
376                         else
377                         {
378                                 diff = abs(atsc.frequency - oatsc.frequency);
379                         }
380                         return 0;
381                 }
382                 default:
383                         return -1;
384         }
385         return 0;
386 }
387
388 RESULT eDVBFrontendParameters::getHash(unsigned long &hash) const
389 {
390         switch (m_type)
391         {
392                 case iDVBFrontend::feSatellite:
393                 {
394                         hash = (sat.orbital_position << 16);
395                         hash |= ((sat.frequency/1000)&0xFFFF)|((sat.polarisation&1) << 15);
396                         return 0;
397                 }
398                 case iDVBFrontend::feCable:
399                 {
400                         hash = 0xFFFF0000;
401                         hash |= (cable.frequency/1000)&0xFFFF;
402                         return 0;
403                 }
404                 case iDVBFrontend::feTerrestrial:
405                 {
406                         hash = 0xEEEE0000;
407                         hash |= (terrestrial.frequency/1000000)&0xFFFF;
408                         return 0;
409                 }
410                 case iDVBFrontend::feATSC:
411                 {
412                         hash = 0xDDDD0000;
413                         hash |= (atsc.frequency/1000)&0xFFFF;
414                         return 0;
415                 }
416                 default:
417                 {
418                         return -1;
419                 }
420         }
421 }
422
423 RESULT eDVBFrontendParameters::calcLockTimeout(unsigned int &timeout) const
424 {
425         switch (m_type)
426         {
427                 case iDVBFrontend::feSatellite:
428                 {
429                                 /* high symbol rate transponders tune faster, due to
430                                         requiring less zigzag and giving more symbols faster.
431
432                                         5s are definitely not enough on really low SR when
433                                         zigzag has to find the exact frequency first.
434                                 */
435                         if (sat.symbol_rate > 20000000)
436                                 timeout = 5000;
437                         else if (sat.symbol_rate > 10000000)
438                                 timeout = 10000;
439                         else
440                                 timeout = 20000;
441                         return 0;
442                 }
443                 case iDVBFrontend::feCable:
444                 {
445                         timeout = 5000;
446                         return 0;
447                 }
448                 case iDVBFrontend::feTerrestrial:
449                 {
450                         timeout = 5000;
451                         return 0;
452                 }
453                 case iDVBFrontend::feATSC:
454                 {
455                         timeout = 5000;
456                         return 0;
457                 }
458                 default:
459                 {
460                         return -1;
461                 }
462         }
463 }
464
465 DEFINE_REF(eDVBFrontend);
466
467 int eDVBFrontend::PriorityOrder=0;
468 int eDVBFrontend::PreferredFrontendIndex = -1;
469
470 eDVBFrontend::eDVBFrontend(const char *devicenodename, int fe, int &ok, bool simulate, eDVBFrontend *simulate_fe)
471         :m_simulate(simulate), m_enabled(false), m_simulate_fe(simulate_fe), m_dvbid(fe), m_slotid(fe)
472         ,m_fd(-1), m_dvbversion(0), m_rotor_mode(false), m_need_rotor_workaround(false)
473         ,m_state(stateClosed), m_timeout(0), m_tuneTimer(0)
474 {
475         m_filename = devicenodename;
476
477         m_timeout = eTimer::create(eApp);
478         CONNECT(m_timeout->timeout, eDVBFrontend::timeout);
479
480         m_tuneTimer = eTimer::create(eApp);
481         CONNECT(m_tuneTimer->timeout, eDVBFrontend::tuneLoop);
482
483         for (int i=0; i<eDVBFrontend::NUM_DATA_ENTRIES; ++i)
484                 m_data[i] = -1;
485
486         m_idleInputpower[0]=m_idleInputpower[1]=0;
487
488         ok = !openFrontend();
489         closeFrontend();
490 }
491
492 void eDVBFrontend::reopenFrontend()
493 {
494         sleep(1);
495         m_delsys.clear();
496         openFrontend();
497 }
498
499 int eDVBFrontend::openFrontend()
500 {
501         if (m_state != stateClosed)
502                 return -1;  // already opened
503
504         m_state=stateIdle;
505         m_tuning=0;
506
507         if (!m_simulate)
508         {
509                 eDebug("[eDVBFrontend] opening frontend %d", m_dvbid);
510                 if (m_fd < 0)
511                 {
512                         m_fd = ::open(m_filename.c_str(), O_RDWR | O_NONBLOCK | O_CLOEXEC);
513                         if (m_fd < 0)
514                         {
515                                 eWarning("[eDVBFrontend] opening %s failed: %m", m_filename.c_str());
516                                 return -1;
517                         }
518                 }
519                 else
520                         eWarning("[eDVBFrontend] frontend %d already opened", m_dvbid);
521                 if (m_dvbversion == 0)
522                 {
523                         m_dvbversion = DVB_VERSION(3, 0);
524 #if defined DTV_API_VERSION
525                         struct dtv_property p;
526                         struct dtv_properties cmdseq;
527                         cmdseq.props = &p;
528                         cmdseq.num = 1;
529                         p.cmd = DTV_API_VERSION;
530                         if (ioctl(m_fd, FE_GET_PROPERTY, &cmdseq) >= 0)
531                         {
532                                 m_dvbversion = p.u.data;
533                         }
534 #endif
535                 }
536                 if (m_delsys.empty())
537                 {
538                         if (::ioctl(m_fd, FE_GET_INFO, &fe_info) < 0)
539                         {
540                                 eWarning("[eDVBFrontend] ioctl FE_GET_INFO failed");
541                                 ::close(m_fd);
542                                 m_fd = -1;
543                                 return -1;
544                         }
545                         strncpy(m_description, fe_info.name, sizeof(m_description));
546 #if defined DTV_ENUM_DELSYS
547                         struct dtv_property p[1];
548                         p[0].cmd = DTV_ENUM_DELSYS;
549                         struct dtv_properties cmdseq;
550                         cmdseq.num = 1;
551                         cmdseq.props = p;
552                         if (::ioctl(m_fd, FE_GET_PROPERTY, &cmdseq) >= 0)
553                         {
554                                 m_delsys.clear();
555                                 for (; p[0].u.buffer.len > 0; p[0].u.buffer.len--)
556                                 {
557                                         fe_delivery_system_t delsys = (fe_delivery_system_t)p[0].u.buffer.data[p[0].u.buffer.len - 1];
558                                         m_delsys[delsys] = true;
559                                 }
560                         }
561                         else
562 #else
563                         /* no DTV_ENUM_DELSYS support */
564                         if (1)
565 #endif
566                         {
567                                 /* old DVB API, fill delsys map with some defaults */
568                                 switch (fe_info.type)
569                                 {
570                                         case FE_QPSK:
571                                         {
572                                                 m_delsys[SYS_DVBS] = true;
573 #if DVB_API_VERSION >= 5
574                                                 if (m_dvbversion >= DVB_VERSION(5, 0))
575                                                 {
576                                                         if (fe_info.caps & FE_CAN_2G_MODULATION) m_delsys[SYS_DVBS2] = true;
577                                                 }
578 #endif
579                                                 break;
580                                         }
581                                         case FE_QAM:
582                                         {
583 #if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 6
584                                                 /* no need for a m_dvbversion check, SYS_DVBC_ANNEX_A replaced SYS_DVBC_ANNEX_AC (same value) */
585                                                 m_delsys[SYS_DVBC_ANNEX_A] = true;
586 #else
587                                                 m_delsys[SYS_DVBC_ANNEX_AC] = true;
588 #endif
589                                                 break;
590                                         }
591                                         case FE_OFDM:
592                                         {
593                                                 m_delsys[SYS_DVBT] = true;
594 #if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 3
595                                                 if (m_dvbversion >= DVB_VERSION(5, 3))
596                                                 {
597                                                         if (fe_info.caps & FE_CAN_2G_MODULATION) m_delsys[SYS_DVBT2] = true;
598                                                 }
599 #endif
600                                                 break;
601                                         }
602                                         case FE_ATSC:   // placeholder to prevent warning
603                                         {
604                                                 break;
605                                         }
606                                 }
607                         }
608                 }
609
610                 if (m_simulate_fe)
611                 {
612                         m_simulate_fe->m_delsys = m_delsys;
613                 }
614                 m_sn = eSocketNotifier::create(eApp, m_fd, eSocketNotifier::Read, false);
615                 CONNECT(m_sn->activated, eDVBFrontend::feEvent);
616         }
617         else
618         {
619                 fe_info.frequency_min = 900000;
620                 fe_info.frequency_max = 2200000;
621         }
622
623         setTone(iDVBFrontend::toneOff);
624         setVoltage(iDVBFrontend::voltageOff);
625
626         return 0;
627 }
628
629 int eDVBFrontend::closeFrontend(bool force, bool no_delayed)
630 {
631         if (!force && m_data[CUR_VOLTAGE] != -1 && m_data[CUR_VOLTAGE] != iDVBFrontend::voltageOff)
632         {
633                 long tmp = m_data[LINKED_NEXT_PTR];
634                 while (tmp != -1)
635                 {
636                         eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
637                         if (linked_fe->m_inuse)
638                         {
639                                 eDebugNoSimulate("[eDVBFrontend] dont close frontend %d until the linked frontend %d in slot %d is still in use",
640                                         m_dvbid, linked_fe->m_frontend->getDVBID(), linked_fe->m_frontend->getSlotID());
641                                 return -1;
642                         }
643                         linked_fe->m_frontend->getData(LINKED_NEXT_PTR, tmp);
644                 }
645         }
646
647         if (m_fd >= 0)
648         {
649                 eDebugNoSimulate("[eDVBFrontend] close frontend %d", m_dvbid);
650                 if (m_data[SATCR] != -1)
651                 {
652                         if (!no_delayed)
653                         {
654                                 m_sec->prepareTurnOffSatCR(*this, m_data[SATCR]);
655                                 m_tuneTimer->start(0, true);
656                                 if(!m_tuneTimer->isActive())
657                                 {
658                                         int timeout=0;
659                                         eDebug("[eDVBFrontend] [turnOffSatCR] no mainloop");
660                                         while(true)
661                                         {
662                                                 timeout = tuneLoopInt();
663                                                 if (timeout == -1)
664                                                         break;
665                                                 usleep(timeout*1000); // blockierendes wait.. eTimer gibts ja nicht mehr
666                                         }
667                                 }
668                                 else
669                                         eDebug("[eDVBFrontend] [turnOffSatCR] running mainloop");
670                                 return 0;
671                         }
672                         else
673                                 m_data[ROTOR_CMD] = -1;
674                 }
675
676                 setTone(iDVBFrontend::toneOff);
677                 setVoltage(iDVBFrontend::voltageOff);
678                 m_tuneTimer->stop();
679
680                 if (m_sec && !m_simulate)
681                         m_sec->setRotorMoving(m_slotid, false);
682                 if (!::close(m_fd))
683                         m_fd=-1;
684                 else
685                         eWarning("[eDVBFrontend] couldnt close frontend %d", m_dvbid);
686         }
687         else if (m_simulate)
688         {
689                 setTone(iDVBFrontend::toneOff);
690                 setVoltage(iDVBFrontend::voltageOff);
691         }
692
693         m_sn=0;
694         m_state = stateClosed;
695
696         return 0;
697 }
698
699 eDVBFrontend::~eDVBFrontend()
700 {
701         m_data[LINKED_PREV_PTR] = m_data[LINKED_NEXT_PTR] = -1;
702         closeFrontend();
703 }
704
705 void eDVBFrontend::feEvent(int w)
706 {
707         eDVBFrontend *sec_fe = this;
708         long tmp = m_data[LINKED_PREV_PTR];
709         while (tmp != -1)
710         {
711                 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
712                 sec_fe = linked_fe->m_frontend;
713                 sec_fe->getData(LINKED_NEXT_PTR, tmp);
714         }
715         while (1)
716         {
717                 dvb_frontend_event event;
718                 int res;
719                 int state;
720                 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
721
722                 if (res && (errno == EAGAIN))
723                         break;
724
725                 if (w < 0)
726                         continue;
727
728                 eDebug("[eDVBFrontend] (%d)fe event: status %x, inversion %s, m_tuning %d", m_dvbid, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off", m_tuning);
729                 if (event.status & FE_HAS_LOCK)
730                 {
731                         state = stateLock;
732                 }
733                 else
734                 {
735                         if (m_tuning) {
736                                 state = stateTuning;
737                                 if (event.status & FE_TIMEDOUT) {
738                                         eDebug("[eDVBFrontend] FE_TIMEDOUT! ..abort");
739                                         m_tuneTimer->stop();
740                                         timeout();
741                                         return;
742                                 }
743                                 ++m_tuning;
744                         }
745                         else
746                         {
747                                 eDebug("[eDVBFrontend] stateLostLock");
748                                 state = stateLostLock;
749                                 if (!m_rotor_mode)
750                                         sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = -1; // reset diseqc
751                         }
752                 }
753                 if (m_state != state)
754                 {
755                         m_state = state;
756                         m_stateChanged(this);
757                 }
758         }
759 }
760
761 void eDVBFrontend::timeout()
762 {
763         m_tuning = 0;
764         if (m_state == stateTuning)
765         {
766                 m_state = stateFailed;
767                 m_data[CSW] = m_data[UCSW] = m_data[TONEBURST] = -1; // reset diseqc
768                 m_stateChanged(this);
769         }
770 }
771
772 #define INRANGE(X,Y,Z) (((X<=Y) && (Y<=Z))||((Z<=Y) && (Y<=X)) ? 1 : 0)
773
774 /* unsigned 32 bit division */
775 static inline uint32_t fe_udiv(uint32_t a, uint32_t b)
776 {
777         return (a + b / 2) / b;
778 }
779
780 void eDVBFrontend::calculateSignalQuality(int snr, int &signalquality, int &signalqualitydb)
781 {
782         int sat_max = 1600; // for stv0288 / bsbe2
783         int ret = 0x12345678;
784         if (!strcmp(m_description, "AVL2108")) // ET9000
785         {
786                 ret = (int)(snr / 40.5);
787                 sat_max = 1618;
788         }
789         if (!strcmp(m_description, "AVL6211")) // ET10000
790         {
791                 ret = (int)(snr / 37.5);
792                 sat_max = 1700;
793         }
794         else if (strstr("Nova-T StickNovaT 500StickDTB03", m_description)) // dib0700
795         {
796                 if ( snr > 300 )
797                         ret = 0; //error condition
798                 else
799                         ret = (int)(snr * 10);
800         }
801         else if (!strcmp(m_description, "BCM4501 (internal)"))
802         {
803                 eDVBFrontendParametersSatellite parm;
804                 float SDS_SNRE = snr << 16;
805                 float snr_in_db;
806                 oparm.getDVBS(parm);
807
808                 if (parm.system == eDVBFrontendParametersSatellite::System_DVB_S) // DVB-S1 / QPSK
809                 {
810                         static float SNR_COEFF[6] = {
811                                 100.0 / 4194304.0,
812                                 -7136.0 / 4194304.0,
813                                 197418.0 / 4194304.0,
814                                 -2602183.0 / 4194304.0,
815                                 20377212.0 / 4194304.0,
816                                 -37791203.0 / 4194304.0,
817                         };
818                         float fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0)),
819                                                 fval2 = pow(10.0, fval1)-1;
820                         fval1 = 10.0 * log10(fval2);
821
822                         if (fval1 < 10.0)
823                         {
824                                 fval2 = SNR_COEFF[0];
825                                 for (int i=1; i<6; ++i)
826                                 {
827                                         fval2 *= fval1;
828                                         fval2 += SNR_COEFF[i];
829                                 }
830                                 fval1 = fval2;
831                         }
832                         snr_in_db = fval1;
833                 }
834                 else
835                 {
836                         float fval1 = SDS_SNRE / 268435456.0,
837                                         fval2, fval3, fval4;
838
839                         if (parm.modulation == eDVBFrontendParametersSatellite::Modulation_QPSK)
840                         {
841                                 fval2 = 6.76;
842                                 fval3 = 4.35;
843                         }
844                         else // 8PSK
845                         {
846                                 fval1 *= 0.5;
847                                 fval2 = 8.06;
848                                 fval3 = 6.18;
849                         }
850                         fval4 = -10.0 * log10(fval1);
851                         fval1 = fval4;
852                         for (int i=0; i < 5; ++i)
853                                 fval1 = fval4 - fval2 * log10(1.0+pow(10.0, (fval3-fval1)/fval2));
854                         snr_in_db = fval1;
855                 }
856                 sat_max = 1750;
857                 ret = (int)(snr_in_db * 100);
858         }
859         else if (strstr(m_description, "Alps BSBE1 C01A") ||
860                 strstr(m_description, "Alps -S(STV0288)"))
861         {
862                 if (snr == 0)
863                         ret = 0;
864                 else if (snr == 0xFFFF) // i think this should not happen
865                         ret = 100*100;
866                 else
867                 {
868                         enum { REALVAL, REGVAL };
869                         const long CN_lookup[31][2] = {
870                                 {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
871                                 {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
872                                 {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
873                                 {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
874                                 {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
875                                 {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
876                                 {300,890}
877                         };
878                         int add=strchr(m_description, '.') ? 0xA250 : 0xA100;
879                         long regval = 0xFFFF - ((snr / 3) + add), // revert some dvb api calulations to get the real register value
880                                 Imin=0,
881                                 Imax=30,
882                                 i;
883                         if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
884                         {
885                                 while((Imax-Imin)>1)
886                                 {
887                                         i=(Imax+Imin)/2;
888                                         if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[i][REGVAL]))
889                                                 Imax = i;
890                                         else
891                                                 Imin = i;
892                                 }
893                                 ret = (((regval - CN_lookup[Imin][REGVAL])
894                                                 * (CN_lookup[Imax][REALVAL] - CN_lookup[Imin][REALVAL])
895                                                 / (CN_lookup[Imax][REGVAL] - CN_lookup[Imin][REGVAL]))
896                                                 + CN_lookup[Imin][REALVAL]) * 10;
897                         }
898                         else
899                                 ret = 100;
900                 }
901         }
902         else if (!strcmp(m_description, "Alps BSBE1 702A") ||  // some frontends with STV0299
903                 !strcmp(m_description, "Alps -S") ||
904                 !strcmp(m_description, "Philips -S") ||
905                 !strcmp(m_description, "LG -S") )
906         {
907                 sat_max = 1500;
908                 ret = (int)((snr-39075)/17.647);
909         }
910         else if (!strcmp(m_description, "Alps BSBE2"))
911         {
912                 ret = (int)((snr >> 7) * 10);
913         }
914         else if (!strcmp(m_description, "Philips CU1216Mk3"))
915         {
916                 eDVBFrontendParametersCable parm;
917                 int mse = (~snr) & 0xFF;
918                 oparm.getDVBC(parm);
919                 switch (parm.modulation)
920                 {
921                 case eDVBFrontendParametersCable::Modulation_QAM16: ret = fe_udiv(1950000, (32 * mse) + 138) + 1000; break;
922                 case eDVBFrontendParametersCable::Modulation_QAM32: ret = fe_udiv(2150000, (40 * mse) + 500) + 1350; break;
923                 case eDVBFrontendParametersCable::Modulation_QAM64: ret = fe_udiv(2100000, (40 * mse) + 500) + 1250; break;
924                 case eDVBFrontendParametersCable::Modulation_QAM128: ret = fe_udiv(1850000, (38 * mse) + 400) + 1380; break;
925                 case eDVBFrontendParametersCable::Modulation_QAM256: ret = fe_udiv(1800000, (100 * mse) + 40) + 2030; break;
926                 default: break;
927                 }
928         }
929         else if (!strcmp(m_description, "Philips TU1216"))
930         {
931                 snr = 0xFF - (snr & 0xFF);
932                 if (snr != 0)
933                         ret = 10 * (int)(-100 * (log10(snr) - log10(255)));
934         }
935         else if (strstr(m_description, "BCM4506") || strstr(m_description, "BCM4505"))
936         {
937                 ret = (snr * 100) >> 8;
938         }
939         else if (!strcmp(m_description, "Vuplus DVB-S NIM(AVL2108)")) // VU+Ultimo/VU+Uno DVB-S2 NIM
940         {
941                 ret = (int)((((double(snr) / (65536.0 / 100.0)) * 0.1600) + 0.2100) * 100);
942         }
943         else if (!strcmp(m_description, "Vuplus DVB-S NIM(AVL6222)")) // VU+ DVB-S2 Dual NIM
944         {
945                 ret = (int)((((double(snr) / (65536.0 / 100.0)) * 0.1244) + 2.5079) * 100);
946         }
947         else if (!strcmp(m_description, "Vuplus DVB-S NIM(AVL6211)")) // VU+ DVB-S2 Dual NIM
948         {
949                 ret = (int)((((double(snr) / (65536.0 / 100.0)) * 0.1244) + 2.5079) * 100);
950         }
951         else if (!strcmp(m_description, "BCM7335 DVB-S2 NIM (internal)")) // VU+DUO DVB-S2 NIM
952         {
953                 ret = (int)((((double(snr) / (65536.0 / 100.0)) * 0.1244) + 2.5079) * 100);
954         }
955         else if (!strcmp(m_description, "BCM7346 (internal)")) // MaxDigital XP1000
956         {
957                 ret = (int)((((double(snr) / (65536.0 / 100.0)) * 0.1880) + 0.1959) * 100);
958         }
959         else if (!strcmp(m_description, "BCM7356 DVB-S2 NIM (internal)")) // VU+ Solo2
960         {
961                 ret = (int)((((double(snr) / (65536.0 / 100.0)) * 0.1800) - 1.0000) * 100);
962         }
963         else if (!strcmp(m_description, "Genpix"))
964         {
965                 ret = (int)((snr << 1) / 5);
966         }
967         else if (!strcmp(m_description, "CXD1981"))
968         {
969                 eDVBFrontendParametersCable parm;
970                 int mse = (~snr) & 0xFF;
971                 oparm.getDVBC(parm);
972                 switch (parm.modulation)
973                 {
974                 case eDVBFrontendParametersCable::Modulation_QAM16:
975                 case eDVBFrontendParametersCable::Modulation_QAM64:
976                 case eDVBFrontendParametersCable::Modulation_QAM256: ret = (int)(-950 * log(((double)mse) / 760)); break;
977                 case eDVBFrontendParametersCable::Modulation_QAM32:
978                 case eDVBFrontendParametersCable::Modulation_QAM128: ret = (int)(-875 * log(((double)mse) / 650)); break;
979                 default: break;
980                 }
981         }
982         else if (!strcmp(m_description, "Si216x"))
983         {
984                 eDVBFrontendParametersTerrestrial parm;
985
986                 oparm.getDVBT(parm);
987
988                 switch (parm.system)
989                 {
990                         case eDVBFrontendParametersTerrestrial::System_DVB_T:
991                         case eDVBFrontendParametersTerrestrial::System_DVB_T2: 
992                         case eDVBFrontendParametersTerrestrial::System_DVB_T_T2: ret = (int)((snr * 10) / 15); break;
993                         default: break;
994                 }
995         }
996
997         signalqualitydb = ret;
998         if (ret == 0x12345678) // no snr db calculation avail.. return untouched snr value..
999         {
1000                 signalquality = snr;
1001         }
1002         else
1003         {
1004                 int type = -1;
1005                 oparm.getSystem(type);
1006                 switch (type)
1007                 {
1008                 case feSatellite:
1009                         signalquality = (ret >= sat_max ? 65536 : ret * 65536 / sat_max);
1010                         break;
1011                 case feCable: // we assume a max of 42db here
1012                         signalquality = (ret >= 4200 ? 65536 : ret * 65536 / 4200);
1013                         break;
1014                 case feTerrestrial: // we assume a max of 29db here
1015                         signalquality = (ret >= 2900 ? 65536 : ret * 65536 / 2900);
1016                         break;
1017                 case feATSC: // we assume a max of 42db here
1018                         signalquality = (ret >= 4200 ? 65536 : ret * 65536 / 4200);
1019                         break;
1020                 }
1021         }
1022 }
1023
1024 int eDVBFrontend::readFrontendData(int type)
1025 {
1026         switch(type)
1027         {
1028                 case iFrontendInformation_ENUMS::bitErrorRate:
1029                         if (m_state == stateLock)
1030                         {
1031                                 uint32_t ber=0;
1032                                 if (!m_simulate)
1033                                 {
1034                                         if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
1035                                                 eDebug("[eDVBFrontend] FE_READ_BER failed: %m");
1036                                 }
1037                                 return ber;
1038                         }
1039                         break;
1040                 case iFrontendInformation_ENUMS::snrValue:
1041                         if (m_state == stateLock)
1042                         {
1043                                 uint16_t snr = 0;
1044                                 if (!m_simulate)
1045                                 {
1046                                         if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
1047                                                 eDebug("[eDVBFrontend] FE_READ_SNR failed: %m");
1048                                 }
1049                                 return snr;
1050                         }
1051                         break;
1052                 case iFrontendInformation_ENUMS::signalQuality:
1053                 case iFrontendInformation_ENUMS::signalQualitydB: /* this will move into the driver */
1054                         if (m_state == stateLock)
1055                         {
1056                                 int snr = readFrontendData(iFrontendInformation_ENUMS::snrValue);
1057                                 int signalquality = 0;
1058                                 int signalqualitydb = 0;
1059                                 calculateSignalQuality(snr, signalquality, signalqualitydb);
1060                                 if (type == iFrontendInformation_ENUMS::signalQuality)
1061                                 {
1062                                         return signalquality;
1063                                 }
1064                                 else
1065                                 {
1066                                         return signalqualitydb;
1067                                 }
1068                         }
1069                         break;
1070                 case iFrontendInformation_ENUMS::signalPower:
1071                         if (m_state == stateLock)
1072                         {
1073                                 uint16_t strength=0;
1074                                 if (!m_simulate)
1075                                 {
1076                                         if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
1077                                                 eDebug("[eDVBFrontend] FE_READ_SIGNAL_STRENGTH failed: %m");
1078                                 }
1079                                 return strength;
1080                         }
1081                         break;
1082                 case iFrontendInformation_ENUMS::lockState:
1083                         return !!(readFrontendData(iFrontendInformation_ENUMS::frontendStatus) & FE_HAS_LOCK);
1084                 case iFrontendInformation_ENUMS::syncState:
1085                         return !!(readFrontendData(iFrontendInformation_ENUMS::frontendStatus) & FE_HAS_SYNC);
1086                 case iFrontendInformation_ENUMS::frontendNumber:
1087                         return m_slotid;
1088                 case iFrontendInformation_ENUMS::frontendStatus:
1089                 {
1090                         fe_status_t status;
1091                         if (!m_simulate)
1092                         {
1093                                 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
1094                                         eDebug("[eDVBFrontend] FE_READ_STATUS failed: %m");
1095                                 return (int)status;
1096                         }
1097                         return (FE_HAS_SYNC | FE_HAS_LOCK);
1098                 }
1099                 case iFrontendInformation_ENUMS::frequency:
1100                 {
1101                         struct dtv_property p;
1102                         struct dtv_properties cmdseq;
1103                         oparm.getSystem(type);
1104                         cmdseq.props = &p;
1105                         cmdseq.num = 1;
1106                         p.cmd = DTV_FREQUENCY;
1107                         if (ioctl(m_fd, FE_GET_PROPERTY, &cmdseq) < 0)
1108                         {
1109                                 return 0;
1110                         }
1111                         return p.u.data + m_data[FREQ_OFFSET];
1112                 }
1113         }
1114         return 0;
1115 }
1116
1117 void eDVBFrontend::getFrontendStatus(ePtr<iDVBFrontendStatus> &dest)
1118 {
1119         ePtr<eDVBFrontend> fe = this;
1120         dest = new eDVBFrontendStatus(fe);
1121 }
1122
1123 void eDVBFrontend::getTransponderData(ePtr<iDVBTransponderData> &dest, bool original)
1124 {
1125         int type = -1;
1126         struct dtv_property p[16];
1127         struct dtv_properties cmdseq;
1128         oparm.getSystem(type);
1129         cmdseq.props = p;
1130         cmdseq.num = 0;
1131         if (m_simulate || m_fd == -1 || original)
1132         {
1133                 original = true;
1134         }
1135         else
1136         {
1137                 p[cmdseq.num++].cmd = DTV_DELIVERY_SYSTEM;
1138                 p[cmdseq.num++].cmd = DTV_FREQUENCY;
1139                 p[cmdseq.num++].cmd = DTV_INVERSION;
1140                 p[cmdseq.num++].cmd = DTV_MODULATION;
1141                 if (type == feSatellite)
1142                 {
1143                         p[cmdseq.num++].cmd = DTV_SYMBOL_RATE;
1144                         p[cmdseq.num++].cmd = DTV_INNER_FEC;
1145                         p[cmdseq.num++].cmd = DTV_ROLLOFF;
1146                         p[cmdseq.num++].cmd = DTV_PILOT;
1147                 }
1148                 else if (type == feCable)
1149                 {
1150                         p[cmdseq.num++].cmd = DTV_SYMBOL_RATE;
1151                         p[cmdseq.num++].cmd = DTV_INNER_FEC;
1152                 }
1153                 else if (type == feTerrestrial)
1154                 {
1155                         p[cmdseq.num++].cmd = DTV_BANDWIDTH_HZ;
1156                         p[cmdseq.num++].cmd = DTV_CODE_RATE_HP;
1157                         p[cmdseq.num++].cmd = DTV_CODE_RATE_LP;
1158                         p[cmdseq.num++].cmd = DTV_TRANSMISSION_MODE;
1159                         p[cmdseq.num++].cmd = DTV_GUARD_INTERVAL;
1160                         p[cmdseq.num++].cmd = DTV_HIERARCHY;
1161                 }
1162                 else if (type == feATSC)
1163                 {
1164                 }
1165                 if (ioctl(m_fd, FE_GET_PROPERTY, &cmdseq) < 0)
1166                 {
1167                         eDebug("[eDVBFrontend] FE_GET_PROPERTY failed: %m");
1168                         original = true;
1169                 }
1170         }
1171         switch (type)
1172         {
1173         case feSatellite:
1174                 {
1175                         eDVBFrontendParametersSatellite s;
1176                         oparm.getDVBS(s);
1177                         dest = new eDVBSatelliteTransponderData(cmdseq.props, cmdseq.num, s, m_data[FREQ_OFFSET], original);
1178                         break;
1179                 }
1180         case feCable:
1181                 {
1182                         eDVBFrontendParametersCable c;
1183                         oparm.getDVBC(c);
1184                         dest = new eDVBCableTransponderData(cmdseq.props, cmdseq.num, c, original);
1185                         break;
1186                 }
1187         case feTerrestrial:
1188                 {
1189                         eDVBFrontendParametersTerrestrial t;
1190                         oparm.getDVBT(t);
1191                         dest = new eDVBTerrestrialTransponderData(cmdseq.props, cmdseq.num, t, original);
1192                         break;
1193                 }
1194         case feATSC:
1195                 {
1196                         eDVBFrontendParametersATSC a;
1197                         oparm.getATSC(a);
1198                         dest = new eDVBATSCTransponderData(cmdseq.props, cmdseq.num, a, original);
1199                         break;
1200                 }
1201         }
1202 }
1203
1204 void eDVBFrontend::getFrontendData(ePtr<iDVBFrontendData> &dest)
1205 {
1206         ePtr<eDVBFrontend> fe = this;
1207         dest = new eDVBFrontendData(fe);
1208 }
1209
1210 #ifndef FP_IOCTL_GET_ID
1211 #define FP_IOCTL_GET_ID 0
1212 #endif
1213 int eDVBFrontend::readInputpower()
1214 {
1215         if (m_simulate)
1216                 return 0;
1217         int power=m_slotid;  // this is needed for read inputpower from the correct tuner !
1218         char proc_name[64];
1219         sprintf(proc_name, "/proc/stb/frontend/%d/lnb_sense", m_slotid);
1220
1221         if (CFile::parseInt(&power, proc_name) == 0)
1222                 return power;
1223
1224         sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1225         if (CFile::parseInt(&power, proc_name) == 0)
1226                 return power;
1227
1228         // open front processor
1229         int fp=::open("/dev/dbox/fp0", O_RDWR);
1230         if (fp < 0)
1231         {
1232                 eDebug("[eDVBFrontend] Failed to open /dev/dbox/fp0");
1233                 return -1;
1234         }
1235         static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1236         if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1237         {
1238                 eDebug("[eDVBFrontend] FP_IOCTL_GET_LNB_CURRENT failed: %m");
1239                 power = -1;
1240         }
1241         ::close(fp);
1242
1243         return power;
1244 }
1245
1246 bool eDVBFrontend::setSecSequencePos(int steps)
1247 {
1248         eDebugNoSimulate("[eDVBFrontend] set sequence pos %d", steps);
1249         if (!steps)
1250                 return false;
1251         while( steps > 0 )
1252         {
1253                 if (m_sec_sequence.current() != m_sec_sequence.end())
1254                         ++m_sec_sequence.current();
1255                 --steps;
1256         }
1257         while( steps < 0 )
1258         {
1259                 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1260                         --m_sec_sequence.current();
1261                 ++steps;
1262         }
1263         return true;
1264 }
1265
1266 void eDVBFrontend::tuneLoop()
1267 {
1268         tuneLoopInt();
1269 }
1270
1271 int eDVBFrontend::tuneLoopInt()  // called by m_tuneTimer
1272 {
1273         int delay=-1;
1274         eDVBFrontend *sec_fe = this;
1275         eDVBRegisteredFrontend *regFE = 0;
1276         long tmp = m_data[LINKED_PREV_PTR];
1277         while ( tmp != -1 )
1278         {
1279                 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1280                 sec_fe = prev->m_frontend;
1281                 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1282                 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1283                         int state = sec_fe->m_state;
1284                         // workaround to put the kernel frontend thread into idle state!
1285                         if (state != eDVBFrontend::stateIdle && state != stateClosed)
1286                         {
1287                                 sec_fe->closeFrontend(true);
1288                                 state = sec_fe->m_state;
1289                         }
1290                         // sec_fe is closed... we must reopen it here..
1291                         if (state == stateClosed)
1292                         {
1293                                 regFE = prev;
1294                                 prev->inc_use();
1295                         }
1296                 }
1297         }
1298
1299         if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1300         {
1301                 long *sec_fe_data = sec_fe->m_data;
1302 //              eDebugNoSimulate("[eDVBFrontend] tuneLoop %d\n", m_sec_sequence.current()->cmd);
1303                 delay = 0;
1304                 switch (m_sec_sequence.current()->cmd)
1305                 {
1306                         case eSecCommand::SLEEP:
1307                                 delay = m_sec_sequence.current()++->msec;
1308                                 eDebugNoSimulate("[eDVBFrontend] sleep %dms", delay);
1309                                 break;
1310                         case eSecCommand::GOTO:
1311                                 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1312                                         ++m_sec_sequence.current();
1313                                 break;
1314                         case eSecCommand::SET_VOLTAGE:
1315                         {
1316                                 int voltage = m_sec_sequence.current()++->voltage;
1317                                 eDebugNoSimulate("[eDVBFrontend] setVoltage %d", voltage);
1318                                 sec_fe->setVoltage(voltage);
1319                                 break;
1320                         }
1321                         case eSecCommand::IF_VOLTAGE_GOTO:
1322                         {
1323                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1324                                 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1325                                         break;
1326                                 ++m_sec_sequence.current();
1327                                 break;
1328                         }
1329                         case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1330                         {
1331                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1332                                 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1333                                         break;
1334                                 ++m_sec_sequence.current();
1335                                 break;
1336                         }
1337                         case eSecCommand::IF_TONE_GOTO:
1338                         {
1339                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1340                                 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1341                                         break;
1342                                 ++m_sec_sequence.current();
1343                                 break;
1344                         }
1345                         case eSecCommand::IF_NOT_TONE_GOTO:
1346                         {
1347                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1348                                 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1349                                         break;
1350                                 ++m_sec_sequence.current();
1351                                 break;
1352                         }
1353                         case eSecCommand::SET_TONE:
1354                                 eDebugNoSimulate("[eDVBFrontend] setTone %d", m_sec_sequence.current()->tone);
1355                                 sec_fe->setTone(m_sec_sequence.current()++->tone);
1356                                 break;
1357                         case eSecCommand::SEND_DISEQC:
1358                                 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1359                                 eDebugNoSimulateNoNewLineStart("[eDVBFrontend] sendDiseqc: ");
1360                                 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1361                                     eDebugNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1362  
1363                                 if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
1364                                         eDebugNoNewLine("(DiSEqC reset)\n");
1365                                 else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
1366                                         eDebugNoNewLine("(DiSEqC peripherial power on)\n");
1367                                 else
1368                                         eDebugNoNewLine("(?)\n");
1369                                 ++m_sec_sequence.current();
1370                                 break;
1371                         case eSecCommand::SEND_TONEBURST:
1372                                 eDebugNoSimulate("[eDVBFrontend] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1373                                 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1374                                 break;
1375                         case eSecCommand::SET_FRONTEND:
1376                         {
1377                                 int enableEvents = (m_sec_sequence.current()++)->val;
1378                                 eDebugNoSimulate("[eDVBFrontend] setFrontend %d", enableEvents);
1379                                 setFrontend(enableEvents);
1380                                 break;
1381                         }
1382                         case eSecCommand::START_TUNE_TIMEOUT:
1383                         {
1384                                 int tuneTimeout = m_sec_sequence.current()->timeout;
1385                                 eDebugNoSimulate("[eDVBFrontend] startTuneTimeout %d", tuneTimeout);
1386                                 if (!m_simulate)
1387                                         m_timeout->start(tuneTimeout, 1);
1388                                 ++m_sec_sequence.current();
1389                                 break;
1390                         }
1391                         case eSecCommand::SET_TIMEOUT:
1392                                 m_timeoutCount = m_sec_sequence.current()++->val;
1393                                 eDebugNoSimulate("[eDVBFrontend] set timeout %d", m_timeoutCount);
1394                                 break;
1395                         case eSecCommand::IF_TIMEOUT_GOTO:
1396                                 if (!m_timeoutCount)
1397                                 {
1398                                         eDebugNoSimulate("[eDVBFrontend] rotor timout");
1399                                         setSecSequencePos(m_sec_sequence.current()->steps);
1400                                 }
1401                                 else
1402                                         ++m_sec_sequence.current();
1403                                 break;
1404                         case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1405                         {
1406                                 int idx = m_sec_sequence.current()++->val;
1407                                 if ( idx == 0 || idx == 1 )
1408                                 {
1409                                         m_idleInputpower[idx] = sec_fe->readInputpower();
1410                                         eDebugNoSimulate("[eDVBFrontend] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1411                                 }
1412                                 else
1413                                         eDebugNoSimulate("[eDVBFrontend] idleInputpower measure index(%d) out of bound !!!", idx);
1414                                 break;
1415                         }
1416                         case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1417                         {
1418                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1419                                 int idx = compare.val;
1420                                 if ( !m_simulate && (idx == 0 || idx == 1) )
1421                                 {
1422                                         int idle = sec_fe->readInputpower();
1423                                         int diff = abs(idle-m_idleInputpower[idx]);
1424                                         if ( diff > 0)
1425                                         {
1426                                                 eDebugNoSimulate("[eDVBFrontend]   measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1427                                                 setSecSequencePos(compare.steps);
1428                                                 break;
1429                                         }
1430                                 }
1431                                 ++m_sec_sequence.current();
1432                                 break;
1433                         }
1434                         case eSecCommand::IF_TUNER_LOCKED_GOTO:
1435                         {
1436                                 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1437                                 if (m_simulate)
1438                                 {
1439                                         setSecSequencePos(cmd.steps);
1440                                         break;
1441                                 }
1442                                 int signal = 0;
1443                                 int isLocked = readFrontendData(iFrontendInformation_ENUMS::lockState);
1444                                 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1445                                 --m_timeoutCount;
1446                                 if (!m_timeoutCount && m_retryCount > 0)
1447                                         --m_retryCount;
1448                                 if (isLocked && ((abs((signal = readFrontendData(iFrontendInformation_ENUMS::signalQualitydB)) - cmd.lastSignal) < 40) || !cmd.lastSignal))
1449                                 {
1450                                         if (cmd.lastSignal)
1451                                                 eDebugNoSimulate("[eDVBFrontend] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1452                                         else
1453                                         {
1454                                                 eDebugNoSimulate("[eDVBFrontend] locked step %d ok", cmd.okcount);
1455                                                 if (!cmd.okcount)
1456                                                         cmd.lastSignal = signal;
1457                                         }
1458                                         ++cmd.okcount;
1459                                         if (cmd.okcount > 4)
1460                                         {
1461                                                 eDebugNoSimulate("[eDVBFrontend] ok > 4 .. goto %d\n", cmd.steps);
1462                                                 setSecSequencePos(cmd.steps);
1463                                                 m_state = stateLock;
1464                                                 m_stateChanged(this);
1465                                                 feEvent(-1); // flush events
1466                                                 m_sn->start();
1467                                                 break;
1468                                         }
1469                                 }
1470                                 else
1471                                 {
1472                                         if (isLocked)
1473                                                 eDebugNoSimulate("[eDVBFrontend] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1474                                         else
1475                                                 eDebugNoSimulate("[eDVBFrontend] rotor locked step %d failed (not locked)", cmd.okcount);
1476                                         cmd.okcount=0;
1477                                         cmd.lastSignal=0;
1478                                 }
1479                                 ++m_sec_sequence.current();
1480                                 break;
1481                         }
1482                         case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1483                                 m_runningInputpower = sec_fe->readInputpower();
1484                                 eDebugNoSimulate("[eDVBFrontend] runningInputpower is %d", m_runningInputpower);
1485                                 ++m_sec_sequence.current();
1486                                 break;
1487                         case eSecCommand::SET_ROTOR_MOVING:
1488                                 if (!m_simulate)
1489                                         m_sec->setRotorMoving(m_slotid, true);
1490                                 ++m_sec_sequence.current();
1491                                 break;
1492                         case eSecCommand::SET_ROTOR_STOPPED:
1493                                 if (!m_simulate)
1494                                         m_sec->setRotorMoving(m_slotid, false);
1495                                 ++m_sec_sequence.current();
1496                                 break;
1497                         case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1498                         {
1499                                 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1500                                 if (m_simulate)
1501                                 {
1502                                         setSecSequencePos(cmd.steps);
1503                                         break;
1504                                 }
1505                                 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1506                                 const char *txt = cmd.direction ? "running" : "stopped";
1507                                 --m_timeoutCount;
1508                                 if (!m_timeoutCount && m_retryCount > 0)
1509                                         --m_retryCount;
1510                                 eDebugNoSimulate("[eDVBFrontend] waiting for rotor %s %d, idle %d, delta %d",
1511                                         txt,
1512                                         m_runningInputpower,
1513                                         idleInputpower,
1514                                         cmd.deltaA);
1515                                 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1516                                         || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1517                                 {
1518                                         ++cmd.okcount;
1519                                         eDebugNoSimulate("[eDVBFrontend] rotor %s step %d ok", txt, cmd.okcount);
1520                                         if ( cmd.okcount > 6 )
1521                                         {
1522                                                 eDebugNoSimulate("[eDVBFrontend] rotor is %s", txt);
1523                                                 if (setSecSequencePos(cmd.steps))
1524                                                         break;
1525                                         }
1526                                 }
1527                                 else
1528                                 {
1529                                         eDebugNoSimulate("[eDVBFrontend] rotor not %s... reset counter.. increase timeout", txt);
1530                                         cmd.okcount=0;
1531                                 }
1532                                 ++m_sec_sequence.current();
1533                                 break;
1534                         }
1535                         case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1536                                 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1537                                         setSecSequencePos(m_sec_sequence.current()->steps);
1538                                 else
1539                                         ++m_sec_sequence.current();
1540                                 break;
1541                         case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1542                                 eDebugNoSimulate("[eDVBFrontend] invalidate current switch params");
1543                                 sec_fe_data[CSW] = -1;
1544                                 sec_fe_data[UCSW] = -1;
1545                                 sec_fe_data[TONEBURST] = -1;
1546                                 ++m_sec_sequence.current();
1547                                 break;
1548                         case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1549                                 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1550                                 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1551                                 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1552                                 eDebugNoSimulate("[eDVBFrontend] update current switch params");
1553                                 ++m_sec_sequence.current();
1554                                 break;
1555                         case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1556                                 eDebugNoSimulate("[eDVBFrontend] invalidate current rotorparams");
1557                                 sec_fe_data[ROTOR_CMD] = -1;
1558                                 sec_fe_data[ROTOR_POS] = -1;
1559                                 ++m_sec_sequence.current();
1560                                 break;
1561                         case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1562                                 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1563                                 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1564                                 eDebugNoSimulate("[eDVBFrontend] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1565                                 ++m_sec_sequence.current();
1566                                 break;
1567                         case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1568                                 m_retryCount = m_sec_sequence.current()++->val;
1569                                 eDebugNoSimulate("[eDVBFrontend] set rotor retries %d", m_retryCount);
1570                                 break;
1571                         case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1572                                 if (!m_retryCount)
1573                                 {
1574                                         eDebugNoSimulate("[eDVBFrontend] no more rotor retrys");
1575                                         setSecSequencePos(m_sec_sequence.current()->steps);
1576                                 }
1577                                 else
1578                                         ++m_sec_sequence.current();
1579                                 break;
1580                         case eSecCommand::SET_POWER_LIMITING_MODE:
1581                         {
1582                                 if (!m_simulate)
1583                                 {
1584                                         char proc_name[64];
1585                                         sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1586                                         CFile f(proc_name, "w");
1587                                         if (f) // new interface exist?
1588                                         {
1589                                                 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1590                                                 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1591                                                         eDebugNoSimulate("[eDVBFrontend] write %s failed: %m", proc_name);
1592                                                 else
1593                                                         eDebugNoSimulate("[eDVBFrontend] set %s current limiting", slimiting ? "static" : "dynamic");
1594                                         }
1595                                         else if (sec_fe->m_need_rotor_workaround)
1596                                         {
1597                                                 char dev[16];
1598                                                 int slotid = sec_fe->m_slotid;
1599                                                 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1600                                                 if (slotid < 2)
1601                                                         sprintf(dev, "/dev/i2c-%d", slotid);
1602                                                 else if (slotid == 2)
1603                                                         sprintf(dev, "/dev/i2c-2"); // first nim socket on DM8000 use /dev/i2c-2
1604                                                 else if (slotid == 3)
1605                                                         sprintf(dev, "/dev/i2c-4"); // second nim socket on DM8000 use /dev/i2c-4
1606                                                 int fd = ::open(dev, O_RDWR);
1607                                                 if (fd >= 0)
1608                                                 {
1609                                                         unsigned char data[2];
1610                                                         ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1611                                                         if(::read(fd, data, 1) != 1)
1612                                                                 eDebugNoSimulate("[eDVBFrontend] error read lnbp: %m");
1613                                                         if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1614                                                         {
1615                                                                 data[0] |= 0x80;  // enable static current limiting
1616                                                                 eDebugNoSimulate("[eDVBFrontend] set static current limiting");
1617                                                         }
1618                                                         else
1619                                                         {
1620                                                                 data[0] &= ~0x80;  // enable dynamic current limiting
1621                                                                 eDebugNoSimulate("[eDVBFrontend] set dynamic current limiting");
1622                                                         }
1623                                                         if(::write(fd, data, 1) != 1)
1624                                                                 eDebugNoSimulate("[eDVBFrontend] error write lnbp: %m");
1625                                                         ::close(fd);
1626                                                 }
1627                                         }
1628                                 }
1629                                 ++m_sec_sequence.current();
1630                                 break;
1631                         }
1632                         case eSecCommand::DELAYED_CLOSE_FRONTEND:
1633                         {
1634                                 eDebugNoSimulate("[eDVBFrontend] delayed close frontend");
1635                                 closeFrontend(false, true);
1636                                 ++m_sec_sequence.current();
1637                                 break;
1638                         }
1639                         default:
1640                                 eDebugNoSimulate("[eDVBFrontend] unhandled sec command %d",
1641                                         ++m_sec_sequence.current()->cmd);
1642                                 ++m_sec_sequence.current();
1643                 }
1644                 if (!m_simulate)
1645                         m_tuneTimer->start(delay,true);
1646         }
1647         if (regFE)
1648                 regFE->dec_use();
1649         if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1650                 tuneLoop();
1651         return delay;
1652 }
1653
1654 void eDVBFrontend::setFrontend(bool recvEvents)
1655 {
1656         if (!m_simulate)
1657         {
1658                 int type = -1;
1659                 oparm.getSystem(type);
1660                 eDebug("[eDVBFrontend] setting frontend %d", m_dvbid);
1661                 if (recvEvents)
1662                         m_sn->start();
1663                 feEvent(-1); // flush events
1664                 struct dtv_property p[16];
1665                 struct dtv_properties cmdseq;
1666                 cmdseq.props = p;
1667                 cmdseq.num = 0;
1668                 p[cmdseq.num].cmd = DTV_CLEAR, cmdseq.num++;
1669                 if (type == iDVBFrontend::feSatellite)
1670                 {
1671                         eDVBFrontendParametersSatellite parm;
1672                         fe_rolloff_t rolloff = ROLLOFF_35;
1673                         fe_pilot_t pilot = PILOT_OFF;
1674                         fe_modulation_t modulation = QPSK;
1675                         fe_delivery_system_t system = SYS_DVBS;
1676                         oparm.getDVBS(parm);
1677
1678                         p[cmdseq.num].cmd = DTV_INVERSION;
1679                         switch (parm.inversion)
1680                         {
1681                                 case eDVBFrontendParametersSatellite::Inversion_Off: p[cmdseq.num].u.data = INVERSION_OFF; break;
1682                                 case eDVBFrontendParametersSatellite::Inversion_On: p[cmdseq.num].u.data = INVERSION_ON; break;
1683                                 default:
1684                                 case eDVBFrontendParametersSatellite::Inversion_Unknown: p[cmdseq.num].u.data = INVERSION_AUTO; break;
1685                         }
1686                         cmdseq.num++;
1687
1688                         switch (parm.system)
1689                         {
1690                                 default:
1691                                 case eDVBFrontendParametersSatellite::System_DVB_S: system = SYS_DVBS; break;
1692                                 case eDVBFrontendParametersSatellite::System_DVB_S2: system = SYS_DVBS2; break;
1693                         }
1694                         switch (parm.modulation)
1695                         {
1696                                 case eDVBFrontendParametersSatellite::Modulation_QPSK: modulation = QPSK; break;
1697                                 case eDVBFrontendParametersSatellite::Modulation_8PSK: modulation = PSK_8; break;
1698                                 case eDVBFrontendParametersSatellite::Modulation_QAM16: modulation = QAM_16; break;
1699                         }
1700                         switch (parm.pilot)
1701                         {
1702                                 case eDVBFrontendParametersSatellite::Pilot_Off: pilot = PILOT_OFF; break;
1703                                 case eDVBFrontendParametersSatellite::Pilot_On: pilot = PILOT_ON; break;
1704                                 default:
1705                                 case eDVBFrontendParametersSatellite::Pilot_Unknown: pilot = PILOT_AUTO; break;
1706                         }
1707                         switch (parm.rolloff)
1708                         {
1709                                 case eDVBFrontendParametersSatellite::RollOff_alpha_0_20: rolloff = ROLLOFF_20; break;
1710                                 case eDVBFrontendParametersSatellite::RollOff_alpha_0_25: rolloff = ROLLOFF_25; break;
1711                                 case eDVBFrontendParametersSatellite::RollOff_alpha_0_35: rolloff = ROLLOFF_35; break;
1712                                 default:
1713                                 case eDVBFrontendParametersSatellite::RollOff_auto: rolloff = ROLLOFF_AUTO; break;
1714                         }
1715                         p[cmdseq.num].cmd = DTV_FREQUENCY, p[cmdseq.num].u.data = satfrequency, cmdseq.num++;
1716                         p[cmdseq.num].cmd = DTV_DELIVERY_SYSTEM, p[cmdseq.num].u.data = system, cmdseq.num++;
1717                         p[cmdseq.num].cmd = DTV_MODULATION, p[cmdseq.num].u.data = modulation, cmdseq.num++;
1718                         p[cmdseq.num].cmd = DTV_SYMBOL_RATE, p[cmdseq.num].u.data = parm.symbol_rate, cmdseq.num++;
1719
1720                         p[cmdseq.num].cmd = DTV_INNER_FEC;
1721                         switch (parm.fec)
1722                         {
1723                                 case eDVBFrontendParametersSatellite::FEC_1_2: p[cmdseq.num].u.data = FEC_1_2; break;
1724                                 case eDVBFrontendParametersSatellite::FEC_2_3: p[cmdseq.num].u.data = FEC_2_3; break;
1725                                 case eDVBFrontendParametersSatellite::FEC_3_4: p[cmdseq.num].u.data = FEC_3_4; break;
1726                                 case eDVBFrontendParametersSatellite::FEC_3_5: p[cmdseq.num].u.data = FEC_3_5; break;
1727                                 case eDVBFrontendParametersSatellite::FEC_4_5: p[cmdseq.num].u.data = FEC_4_5; break;
1728                                 case eDVBFrontendParametersSatellite::FEC_5_6: p[cmdseq.num].u.data = FEC_5_6; break;
1729                                 case eDVBFrontendParametersSatellite::FEC_6_7: p[cmdseq.num].u.data = FEC_6_7; break;
1730                                 case eDVBFrontendParametersSatellite::FEC_7_8: p[cmdseq.num].u.data = FEC_7_8; break;
1731                                 case eDVBFrontendParametersSatellite::FEC_8_9: p[cmdseq.num].u.data = FEC_8_9; break;
1732                                 case eDVBFrontendParametersSatellite::FEC_9_10: p[cmdseq.num].u.data = FEC_9_10; break;
1733                                 case eDVBFrontendParametersSatellite::FEC_None: p[cmdseq.num].u.data = FEC_NONE; break;
1734                                 default:
1735                                 case eDVBFrontendParametersSatellite::FEC_Auto: p[cmdseq.num].u.data = FEC_AUTO; break;
1736                         }
1737                         cmdseq.num++;
1738                         if (system == SYS_DVBS2)
1739                         {
1740                                 p[cmdseq.num].cmd = DTV_ROLLOFF, p[cmdseq.num].u.data = rolloff, cmdseq.num++;
1741                                 p[cmdseq.num].cmd = DTV_PILOT, p[cmdseq.num].u.data = pilot, cmdseq.num++;
1742                         }
1743                 }
1744                 else if (type == iDVBFrontend::feCable)
1745                 {
1746                         eDVBFrontendParametersCable parm;
1747                         oparm.getDVBC(parm);
1748                         p[cmdseq.num].cmd = DTV_FREQUENCY, p[cmdseq.num].u.data = parm.frequency * 1000, cmdseq.num++;
1749
1750                         p[cmdseq.num].cmd = DTV_INVERSION;
1751                         switch (parm.inversion)
1752                         {
1753                                 case eDVBFrontendParametersCable::Inversion_Off: p[cmdseq.num].u.data = INVERSION_OFF; break;
1754                                 case eDVBFrontendParametersCable::Inversion_On: p[cmdseq.num].u.data = INVERSION_ON; break;
1755                                 default:
1756                                 case eDVBFrontendParametersCable::Inversion_Unknown: p[cmdseq.num].u.data = INVERSION_AUTO; break;
1757                         }
1758                         cmdseq.num++;
1759
1760                         p[cmdseq.num].cmd = DTV_DELIVERY_SYSTEM;
1761 #if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 6
1762                         if (m_dvbversion >= DVB_VERSION(5, 6))
1763                         {
1764                                 switch (parm.system)
1765                                 {
1766                                         default:
1767                                         case eDVBFrontendParametersCable::System_DVB_C_ANNEX_A: p[cmdseq.num].u.data = SYS_DVBC_ANNEX_A; break;
1768                                         case eDVBFrontendParametersCable::System_DVB_C_ANNEX_C: p[cmdseq.num].u.data = SYS_DVBC_ANNEX_C; break;
1769                                 }
1770                         }
1771                         else
1772                         {
1773                                 p[cmdseq.num].u.data = SYS_DVBC_ANNEX_A; /* old value for SYS_DVBC_ANNEX_AC */
1774                         }
1775 #else
1776                         p[cmdseq.num].u.data = SYS_DVBC_ANNEX_AC;
1777 #endif
1778                         cmdseq.num++;
1779
1780                         p[cmdseq.num].cmd = DTV_SYMBOL_RATE, p[cmdseq.num].u.data = parm.symbol_rate, cmdseq.num++;
1781
1782                         p[cmdseq.num].cmd = DTV_INNER_FEC;
1783                         switch (parm.fec_inner)
1784                         {
1785                                 default:
1786                                 case eDVBFrontendParametersCable::FEC_Auto: p[cmdseq.num].u.data = FEC_AUTO; break;
1787                                 case eDVBFrontendParametersCable::FEC_1_2: p[cmdseq.num].u.data = FEC_1_2; break;
1788                                 case eDVBFrontendParametersCable::FEC_2_3: p[cmdseq.num].u.data = FEC_2_3; break;
1789                                 case eDVBFrontendParametersCable::FEC_3_4: p[cmdseq.num].u.data = FEC_3_4; break;
1790                                 case eDVBFrontendParametersCable::FEC_5_6: p[cmdseq.num].u.data = FEC_5_6; break;
1791                                 case eDVBFrontendParametersCable::FEC_7_8: p[cmdseq.num].u.data = FEC_7_8; break;
1792                                 case eDVBFrontendParametersCable::FEC_8_9: p[cmdseq.num].u.data = FEC_8_9; break;
1793                                 case eDVBFrontendParametersCable::FEC_3_5: p[cmdseq.num].u.data = FEC_3_5; break;
1794                                 case eDVBFrontendParametersCable::FEC_4_5: p[cmdseq.num].u.data = FEC_4_5; break;
1795                                 case eDVBFrontendParametersCable::FEC_9_10: p[cmdseq.num].u.data = FEC_9_10; break;
1796                         }
1797                         cmdseq.num++;
1798
1799                         p[cmdseq.num].cmd = DTV_MODULATION;
1800                         switch (parm.modulation)
1801                         {
1802                                 default:
1803                                 case eDVBFrontendParametersCable::Modulation_Auto: p[cmdseq.num].u.data = QAM_AUTO; break;
1804                                 case eDVBFrontendParametersCable::Modulation_QAM16: p[cmdseq.num].u.data = QAM_16; break;
1805                                 case eDVBFrontendParametersCable::Modulation_QAM32: p[cmdseq.num].u.data = QAM_32; break;
1806                                 case eDVBFrontendParametersCable::Modulation_QAM64: p[cmdseq.num].u.data = QAM_64; break;
1807                                 case eDVBFrontendParametersCable::Modulation_QAM128: p[cmdseq.num].u.data = QAM_128; break;
1808                                 case eDVBFrontendParametersCable::Modulation_QAM256: p[cmdseq.num].u.data = QAM_256; break;
1809                         }
1810                         cmdseq.num++;
1811                 }
1812                 else if (type == iDVBFrontend::feTerrestrial)
1813                 {
1814                         eDVBFrontendParametersTerrestrial parm;
1815                         fe_delivery_system_t system = SYS_DVBT;
1816                         oparm.getDVBT(parm);
1817                         switch (parm.system)
1818                         {
1819                                 default:
1820                                 case eDVBFrontendParametersTerrestrial::System_DVB_T: system = SYS_DVBT; break;
1821                                 case eDVBFrontendParametersTerrestrial::System_DVB_T2: system = SYS_DVBT2; break;
1822                         }
1823
1824                         p[cmdseq.num].cmd = DTV_DELIVERY_SYSTEM, p[cmdseq.num].u.data = system, cmdseq.num++;
1825                         p[cmdseq.num].cmd = DTV_FREQUENCY, p[cmdseq.num].u.data = parm.frequency, cmdseq.num++;
1826
1827                         p[cmdseq.num].cmd = DTV_INVERSION;
1828                         switch (parm.inversion)
1829                         {
1830                                 case eDVBFrontendParametersTerrestrial::Inversion_Off: p[cmdseq.num].u.data = INVERSION_OFF; break;
1831                                 case eDVBFrontendParametersTerrestrial::Inversion_On: p[cmdseq.num].u.data = INVERSION_ON; break;
1832                                 default:
1833                                 case eDVBFrontendParametersTerrestrial::Inversion_Unknown: p[cmdseq.num].u.data = INVERSION_AUTO; break;
1834                         }
1835                         cmdseq.num++;
1836
1837                         p[cmdseq.num].cmd = DTV_CODE_RATE_LP;
1838                         switch (parm.code_rate_LP)
1839                         {
1840                                 case eDVBFrontendParametersTerrestrial::FEC_1_2: p[cmdseq.num].u.data = FEC_1_2; break;
1841                                 case eDVBFrontendParametersTerrestrial::FEC_2_3: p[cmdseq.num].u.data = FEC_2_3; break;
1842                                 case eDVBFrontendParametersTerrestrial::FEC_3_4: p[cmdseq.num].u.data = FEC_3_4; break;
1843                                 case eDVBFrontendParametersTerrestrial::FEC_5_6: p[cmdseq.num].u.data = FEC_5_6; break;
1844                                 case eDVBFrontendParametersTerrestrial::FEC_6_7: p[cmdseq.num].u.data = FEC_6_7; break;
1845                                 case eDVBFrontendParametersTerrestrial::FEC_7_8: p[cmdseq.num].u.data = FEC_7_8; break;
1846                                 case eDVBFrontendParametersTerrestrial::FEC_8_9: p[cmdseq.num].u.data = FEC_8_9; break;
1847                                 default:
1848                                 case eDVBFrontendParametersTerrestrial::FEC_Auto: p[cmdseq.num].u.data = FEC_AUTO; break;
1849                         }
1850                         cmdseq.num++;
1851
1852                         p[cmdseq.num].cmd = DTV_CODE_RATE_HP;
1853                         switch (parm.code_rate_HP)
1854                         {
1855                                 case eDVBFrontendParametersTerrestrial::FEC_1_2: p[cmdseq.num].u.data = FEC_1_2; break;
1856                                 case eDVBFrontendParametersTerrestrial::FEC_2_3: p[cmdseq.num].u.data = FEC_2_3; break;
1857                                 case eDVBFrontendParametersTerrestrial::FEC_3_4: p[cmdseq.num].u.data = FEC_3_4; break;
1858                                 case eDVBFrontendParametersTerrestrial::FEC_5_6: p[cmdseq.num].u.data = FEC_5_6; break;
1859                                 case eDVBFrontendParametersTerrestrial::FEC_6_7: p[cmdseq.num].u.data = FEC_6_7; break;
1860                                 case eDVBFrontendParametersTerrestrial::FEC_7_8: p[cmdseq.num].u.data = FEC_7_8; break;
1861                                 case eDVBFrontendParametersTerrestrial::FEC_8_9: p[cmdseq.num].u.data = FEC_8_9; break;
1862                                 default:
1863                                 case eDVBFrontendParametersTerrestrial::FEC_Auto: p[cmdseq.num].u.data = FEC_AUTO; break;
1864                         }
1865                         cmdseq.num++;
1866
1867                         p[cmdseq.num].cmd = DTV_MODULATION;
1868                         switch (parm.modulation)
1869                         {
1870                                 case eDVBFrontendParametersTerrestrial::Modulation_QPSK: p[cmdseq.num].u.data = QPSK; break;
1871                                 case eDVBFrontendParametersTerrestrial::Modulation_QAM16: p[cmdseq.num].u.data = QAM_16; break;
1872                                 case eDVBFrontendParametersTerrestrial::Modulation_QAM64: p[cmdseq.num].u.data = QAM_64; break;
1873                                 case eDVBFrontendParametersTerrestrial::Modulation_QAM256: p[cmdseq.num].u.data = QAM_256; break;
1874                                 default:
1875                                 case eDVBFrontendParametersTerrestrial::Modulation_Auto: p[cmdseq.num].u.data = QAM_AUTO; break;
1876                         }
1877                         cmdseq.num++;
1878
1879                         p[cmdseq.num].cmd = DTV_TRANSMISSION_MODE;
1880                         switch (parm.transmission_mode)
1881                         {
1882                                 case eDVBFrontendParametersTerrestrial::TransmissionMode_2k: p[cmdseq.num].u.data = TRANSMISSION_MODE_2K; break;
1883                                 case eDVBFrontendParametersTerrestrial::TransmissionMode_4k: p[cmdseq.num].u.data = TRANSMISSION_MODE_4K; break;
1884                                 case eDVBFrontendParametersTerrestrial::TransmissionMode_8k: p[cmdseq.num].u.data = TRANSMISSION_MODE_8K; break;
1885 #if defined TRANSMISSION_MODE_1K
1886                                 case eDVBFrontendParametersTerrestrial::TransmissionMode_1k: p[cmdseq.num].u.data = TRANSMISSION_MODE_1K; break;
1887                                 case eDVBFrontendParametersTerrestrial::TransmissionMode_16k: p[cmdseq.num].u.data = TRANSMISSION_MODE_16K; break;
1888                                 case eDVBFrontendParametersTerrestrial::TransmissionMode_32k: p[cmdseq.num].u.data = TRANSMISSION_MODE_32K; break;
1889 #endif
1890                                 default:
1891                                 case eDVBFrontendParametersTerrestrial::TransmissionMode_Auto: p[cmdseq.num].u.data = TRANSMISSION_MODE_AUTO; break;
1892                         }
1893                         cmdseq.num++;
1894
1895                         p[cmdseq.num].cmd = DTV_GUARD_INTERVAL;
1896                         switch (parm.guard_interval)
1897                         {
1898                                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_32: p[cmdseq.num].u.data = GUARD_INTERVAL_1_32; break;
1899                                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_16: p[cmdseq.num].u.data = GUARD_INTERVAL_1_16; break;
1900                                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_8: p[cmdseq.num].u.data = GUARD_INTERVAL_1_8; break;
1901                                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_4: p[cmdseq.num].u.data = GUARD_INTERVAL_1_4; break;
1902 #if defined GUARD_INTERVAL_1_128
1903                                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_128: p[cmdseq.num].u.data = GUARD_INTERVAL_1_128; break;
1904                                 case eDVBFrontendParametersTerrestrial::GuardInterval_19_128: p[cmdseq.num].u.data = GUARD_INTERVAL_19_128; break;
1905                                 case eDVBFrontendParametersTerrestrial::GuardInterval_19_256: p[cmdseq.num].u.data = GUARD_INTERVAL_19_256; break;
1906 #endif
1907                                 default:
1908                                 case eDVBFrontendParametersTerrestrial::GuardInterval_Auto: p[cmdseq.num].u.data = GUARD_INTERVAL_AUTO; break;
1909                         }
1910                         cmdseq.num++;
1911
1912                         p[cmdseq.num].cmd = DTV_HIERARCHY;
1913                         switch (parm.hierarchy)
1914                         {
1915                                 case eDVBFrontendParametersTerrestrial::Hierarchy_None: p[cmdseq.num].u.data = HIERARCHY_NONE; break;
1916                                 case eDVBFrontendParametersTerrestrial::Hierarchy_1: p[cmdseq.num].u.data = HIERARCHY_1; break;
1917                                 case eDVBFrontendParametersTerrestrial::Hierarchy_2: p[cmdseq.num].u.data = HIERARCHY_2; break;
1918                                 case eDVBFrontendParametersTerrestrial::Hierarchy_4: p[cmdseq.num].u.data = HIERARCHY_4; break;
1919                                 default:
1920                                 case eDVBFrontendParametersTerrestrial::Hierarchy_Auto: p[cmdseq.num].u.data = HIERARCHY_AUTO; break;
1921                         }
1922                         cmdseq.num++;
1923
1924                         p[cmdseq.num].cmd = DTV_BANDWIDTH_HZ, p[cmdseq.num].u.data = parm.bandwidth, cmdseq.num++;
1925                         if (system == SYS_DVBT2)
1926                         {
1927                                 if (m_dvbversion >= DVB_VERSION(5, 3))
1928                                 {
1929 #if defined DTV_STREAM_ID
1930                                         p[cmdseq.num].cmd = DTV_STREAM_ID, p[cmdseq.num].u.data = parm.plpid, cmdseq.num++;
1931 #elif defined DTV_DVBT2_PLP_ID
1932                                         p[cmdseq.num].cmd = DTV_DVBT2_PLP_ID, p[cmdseq.num].u.data = parm.plpid, cmdseq.num++;
1933 #endif
1934                                 }
1935                         }
1936                 }
1937                 else if (type == iDVBFrontend::feATSC)
1938                 {
1939                         eDVBFrontendParametersATSC parm;
1940                         oparm.getATSC(parm);
1941                         p[cmdseq.num].cmd = DTV_DELIVERY_SYSTEM;
1942                         switch (parm.system)
1943                         {
1944                                 default:
1945                                 case eDVBFrontendParametersATSC::System_ATSC: p[cmdseq.num].u.data = SYS_ATSC; break;
1946                                 case eDVBFrontendParametersATSC::System_DVB_C_ANNEX_B: p[cmdseq.num].u.data = SYS_DVBC_ANNEX_B; break;
1947                         }
1948                         cmdseq.num++;
1949
1950                         p[cmdseq.num].cmd = DTV_FREQUENCY, p[cmdseq.num].u.data = parm.frequency, cmdseq.num++;
1951
1952                         p[cmdseq.num].cmd = DTV_INVERSION;
1953                         switch (parm.inversion)
1954                         {
1955                                 case eDVBFrontendParametersATSC::Inversion_Off: p[cmdseq.num].u.data = INVERSION_OFF; break;
1956                                 case eDVBFrontendParametersATSC::Inversion_On: p[cmdseq.num].u.data = INVERSION_ON; break;
1957                                 default:
1958                                 case eDVBFrontendParametersATSC::Inversion_Unknown: p[cmdseq.num].u.data = INVERSION_AUTO; break;
1959                         }
1960                         cmdseq.num++;
1961
1962                         p[cmdseq.num].cmd = DTV_MODULATION;
1963                         switch (parm.modulation)
1964                         {
1965                                 default:
1966                                 case eDVBFrontendParametersATSC::Modulation_Auto: p[cmdseq.num].u.data = QAM_AUTO; break;
1967                                 case eDVBFrontendParametersATSC::Modulation_QAM16: p[cmdseq.num].u.data = QAM_16; break;
1968                                 case eDVBFrontendParametersATSC::Modulation_QAM32: p[cmdseq.num].u.data = QAM_32; break;
1969                                 case eDVBFrontendParametersATSC::Modulation_QAM64: p[cmdseq.num].u.data = QAM_64; break;
1970                                 case eDVBFrontendParametersATSC::Modulation_QAM128: p[cmdseq.num].u.data = QAM_128; break;
1971                                 case eDVBFrontendParametersATSC::Modulation_QAM256: p[cmdseq.num].u.data = QAM_256; break;
1972                                 case eDVBFrontendParametersATSC::Modulation_VSB_8: p[cmdseq.num].u.data = VSB_8; break;
1973                                 case eDVBFrontendParametersATSC::Modulation_VSB_16: p[cmdseq.num].u.data = VSB_16; break;
1974                         }
1975                         cmdseq.num++;
1976                 }
1977                 p[cmdseq.num].cmd = DTV_TUNE, cmdseq.num++;
1978                 if (ioctl(m_fd, FE_SET_PROPERTY, &cmdseq) == -1)
1979                 {
1980                         perror("FE_SET_PROPERTY failed");
1981                         return;
1982                 }
1983         }
1984 }
1985
1986 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1987 {
1988         int res;
1989         satfrequency = feparm.frequency;
1990         if (!m_sec)
1991         {
1992                 eWarning("[eDVBFrontend] no SEC module active!");
1993                 return -ENOENT;
1994         }
1995         res = m_sec->prepare(*this, feparm, satfrequency, 1 << m_slotid, tunetimeout);
1996         if (!res)
1997         {
1998                 eDebugNoSimulate("[eDVBFrontend] prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d system %d modulation %d pilot %d, rolloff %d",
1999                         feparm.system,
2000                         feparm.frequency,
2001                         feparm.polarisation,
2002                         feparm.symbol_rate,
2003                         feparm.inversion,
2004                         feparm.fec,
2005                         feparm.orbital_position,
2006                         feparm.system,
2007                         feparm.modulation,
2008                         feparm.pilot,
2009                         feparm.rolloff);
2010                 if ((unsigned int)satfrequency < fe_info.frequency_min || (unsigned int)satfrequency > fe_info.frequency_max)
2011                 {
2012                         eDebugNoSimulate("[eDVBFrontend] %d mhz out of tuner range.. dont tune", satfrequency / 1000);
2013                         return -EINVAL;
2014                 }
2015                 eDebugNoSimulate("[eDVBFrontend] tuning to %d mhz", satfrequency / 1000);
2016         }
2017         oparm.setDVBS(feparm, feparm.no_rotor_command_on_tune);
2018         return res;
2019 }
2020
2021 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
2022 {
2023         eDebugNoSimulate("[eDVBFrontend] tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
2024                 feparm.frequency,
2025                 feparm.symbol_rate,
2026                 feparm.fec_inner,
2027                 feparm.modulation,
2028                 feparm.inversion);
2029         oparm.setDVBC(feparm);
2030         return 0;
2031 }
2032
2033 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
2034 {
2035         oparm.setDVBT(feparm);
2036         return 0;
2037 }
2038
2039 RESULT eDVBFrontend::prepare_atsc(const eDVBFrontendParametersATSC &feparm)
2040 {
2041         oparm.setATSC(feparm);
2042         return 0;
2043 }
2044
2045 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2046 {
2047         unsigned int timeout = 5000;
2048         int type;
2049         eDebugNoSimulate("[eDVBFrontend] (%d)tune", m_dvbid);
2050
2051         m_timeout->stop();
2052
2053         int res=0;
2054
2055         if (where.getSystem(type) < 0)
2056         {
2057                 res = -EINVAL;
2058                 goto tune_error;
2059         }
2060
2061         if (!m_sn && !m_simulate)
2062         {
2063                 eDebug("[eDVBFrontend] no frontend device opened... do not try to tune !!!");
2064                 res = -ENODEV;
2065                 goto tune_error;
2066         }
2067
2068         if (!m_simulate)
2069                 m_sn->stop();
2070
2071         m_sec_sequence.clear();
2072
2073         where.calcLockTimeout(timeout);
2074
2075         switch (type)
2076         {
2077         case feSatellite:
2078         {
2079                 eDVBFrontendParametersSatellite feparm;
2080                 if (where.getDVBS(feparm))
2081                 {
2082                         eDebug("[eDVBFrontend] no dvbs data!");
2083                         res = -EINVAL;
2084                         goto tune_error;
2085                 }
2086                 if (m_rotor_mode != feparm.no_rotor_command_on_tune && !feparm.no_rotor_command_on_tune)
2087                 {
2088                         eDVBFrontend *sec_fe = this;
2089                         long tmp = m_data[LINKED_PREV_PTR];
2090                         while (tmp != -1)
2091                         {
2092                                 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
2093                                 sec_fe = linked_fe->m_frontend;
2094                                 sec_fe->getData(LINKED_NEXT_PTR, tmp);
2095                         }
2096                         eDebug("[eDVBFrontend] (fe%d) reset diseqc after leave rotor mode!", m_dvbid);
2097                         sec_fe->m_data[CSW] = sec_fe->m_data[UCSW] = sec_fe->m_data[TONEBURST] = sec_fe->m_data[ROTOR_CMD] = sec_fe->m_data[ROTOR_POS] = -1; // reset diseqc
2098                 }
2099                 m_rotor_mode = feparm.no_rotor_command_on_tune;
2100                 if (!m_simulate)
2101                         m_sec->setRotorMoving(m_slotid, false);
2102                 res=prepare_sat(feparm, timeout);
2103                 if (res)
2104                         goto tune_error;
2105
2106                 break;
2107         }
2108         case feCable:
2109         {
2110                 eDVBFrontendParametersCable feparm;
2111                 if (where.getDVBC(feparm))
2112                 {
2113                         res = -EINVAL;
2114                         goto tune_error;
2115                 }
2116                 res=prepare_cable(feparm);
2117                 if (res)
2118                         goto tune_error;
2119
2120                 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2121                 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2122                 break;
2123         }
2124         case feTerrestrial:
2125         {
2126                 eDVBFrontendParametersTerrestrial feparm;
2127                 if (where.getDVBT(feparm))
2128                 {
2129                         eDebug("[eDVBFrontend] no -T data");
2130                         res = -EINVAL;
2131                         goto tune_error;
2132                 }
2133                 res=prepare_terrestrial(feparm);
2134                 if (res)
2135                         goto tune_error;
2136
2137                 char configStr[255];
2138                 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2139                 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2140                 if (eConfigManager::getConfigBoolValue(configStr))
2141                         m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2142                 else
2143                         m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2144                 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2145                 break;
2146         }
2147         case feATSC:
2148         {
2149                 eDVBFrontendParametersATSC feparm;
2150                 if (where.getATSC(feparm))
2151                 {
2152                         res = -EINVAL;
2153                         goto tune_error;
2154                 }
2155                 res=prepare_atsc(feparm);
2156                 if (res)
2157                         goto tune_error;
2158
2159                 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2160                 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2161                 break;
2162         }
2163         default:
2164                 res = -EINVAL;
2165                 goto tune_error;
2166         }
2167
2168         m_sec_sequence.current() = m_sec_sequence.begin();
2169
2170         if (!m_simulate)
2171         {
2172                 m_tuneTimer->start(0,true);
2173                 m_tuning = 1;
2174                 if (m_state != stateTuning)
2175                 {
2176                         m_state = stateTuning;
2177                         m_stateChanged(this);
2178                 }
2179         }
2180         else
2181                 tuneLoop();
2182
2183         return res;
2184
2185 tune_error:
2186         m_tuneTimer->stop();
2187         return res;
2188 }
2189
2190 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2191 {
2192         connection = new eConnection(this, m_stateChanged.connect(stateChange));
2193         return 0;
2194 }
2195
2196 RESULT eDVBFrontend::setVoltage(int voltage)
2197 {
2198         bool increased=false;
2199         fe_sec_voltage_t vlt;
2200         m_data[CUR_VOLTAGE]=voltage;
2201         switch (voltage)
2202         {
2203                 case voltageOff:
2204                         m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2205                         vlt = SEC_VOLTAGE_OFF;
2206                         break;
2207                 case voltage13_5:
2208                         increased = true;
2209                 case voltage13:
2210                         vlt = SEC_VOLTAGE_13;
2211                         break;
2212                 case voltage18_5:
2213                         increased = true;
2214                 case voltage18:
2215                         vlt = SEC_VOLTAGE_18;
2216                         break;
2217                 default:
2218                         return -ENODEV;
2219         }
2220         if (m_simulate)
2221                 return 0;
2222         ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased);
2223         return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2224 }
2225
2226 RESULT eDVBFrontend::getState(int &state)
2227 {
2228         state = m_state;
2229         return 0;
2230 }
2231
2232 RESULT eDVBFrontend::setTone(int t)
2233 {
2234         fe_sec_tone_mode_t tone;
2235         if (m_simulate)
2236                 return 0;
2237         m_data[CUR_TONE]=t;
2238         switch (t)
2239         {
2240                 case toneOn:
2241                         tone = SEC_TONE_ON;
2242                         break;
2243                 case toneOff:
2244                         tone = SEC_TONE_OFF;
2245                         break;
2246                 default:
2247                         return -ENODEV;
2248         }
2249         return ::ioctl(m_fd, FE_SET_TONE, tone);
2250 }
2251
2252 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2253 {
2254         struct dvb_diseqc_master_cmd cmd;
2255         if (m_simulate)
2256                 return 0;
2257         memcpy(cmd.msg, diseqc.data, diseqc.len);
2258         cmd.msg_len = diseqc.len;
2259         if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2260                 return -EINVAL;
2261         return 0;
2262 }
2263
2264 RESULT eDVBFrontend::sendToneburst(int burst)
2265 {
2266         fe_sec_mini_cmd_t cmd;
2267         if (m_simulate)
2268                 return 0;
2269         if (burst == eDVBSatelliteDiseqcParameters::B)
2270                 cmd = SEC_MINI_B;
2271         else
2272                 cmd = SEC_MINI_A;
2273
2274         if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2275                 return -EINVAL;
2276         return 0;
2277 }
2278
2279 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2280 {
2281         m_sec = sec;
2282         return 0;
2283 }
2284
2285 RESULT eDVBFrontend::setSecSequence(eSecCommandList &list)
2286 {
2287         if (m_data[SATCR] != -1 && m_sec_sequence.current() != m_sec_sequence.end())
2288                 m_sec_sequence.push_back(list);
2289         else
2290                 m_sec_sequence = list;
2291         return 0;
2292 }
2293
2294 RESULT eDVBFrontend::getData(int num, long &data)
2295 {
2296         if ( num < NUM_DATA_ENTRIES )
2297         {
2298                 data = m_data[num];
2299                 return 0;
2300         }
2301         return -EINVAL;
2302 }
2303
2304 RESULT eDVBFrontend::setData(int num, long val)
2305 {
2306         if ( num < NUM_DATA_ENTRIES )
2307         {
2308                 m_data[num] = val;
2309                 return 0;
2310         }
2311         return -EINVAL;
2312 }
2313
2314 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2315 {
2316         int type;
2317         int score = 0;
2318         bool preferred = (eDVBFrontend::getPreferredFrontend() >= 0 && m_slotid == eDVBFrontend::getPreferredFrontend());
2319         if (feparm->getSystem(type) || !m_enabled)
2320         {
2321                 return 0;
2322         }
2323         if (type == eDVBFrontend::feSatellite)
2324         {
2325                 eDVBFrontendParametersSatellite parm;
2326                 bool can_handle_dvbs, can_handle_dvbs2;
2327                 if (feparm->getDVBS(parm) < 0)
2328                 {
2329                         return 0;
2330                 }
2331                 can_handle_dvbs = supportsDeliverySystem(SYS_DVBS, true);
2332                 can_handle_dvbs2 = supportsDeliverySystem(SYS_DVBS2, true);
2333                 if (parm.system == eDVBFrontendParametersSatellite::System_DVB_S2 && !can_handle_dvbs2)
2334                 {
2335                         return 0;
2336                 }
2337                 if (parm.system == eDVBFrontendParametersSatellite::System_DVB_S && !can_handle_dvbs)
2338                 {
2339                         return 0;
2340                 }
2341                 score = m_sec ? m_sec->canTune(parm, this, 1 << m_slotid) : 0;
2342                 if (score > 1 && parm.system == eDVBFrontendParametersSatellite::System_DVB_S && can_handle_dvbs2)
2343                 {
2344                         /* prefer to use an S tuner, try to keep S2 free for S2 transponders */
2345                         score--;
2346                 }
2347         }
2348         else if (type == eDVBFrontend::feCable)
2349         {
2350                 eDVBFrontendParametersCable parm;
2351                 bool can_handle_dvbc_annex_a, can_handle_dvbc_annex_c;
2352                 if (feparm->getDVBC(parm) < 0)
2353                 {
2354                         return 0;
2355                 }
2356 #if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 6
2357                 if (m_dvbversion >= DVB_VERSION(5, 6))
2358                 {
2359                         can_handle_dvbc_annex_a = supportsDeliverySystem(SYS_DVBC_ANNEX_A, true);
2360                         can_handle_dvbc_annex_c = supportsDeliverySystem(SYS_DVBC_ANNEX_C, true);
2361                 }
2362                 else
2363                 {
2364                         can_handle_dvbc_annex_a = can_handle_dvbc_annex_c = supportsDeliverySystem(SYS_DVBC_ANNEX_A, true); /* new value for SYS_DVB_ANNEX_AC */
2365                 }
2366 #else
2367                 can_handle_dvbc_annex_a = can_handle_dvbc_annex_c = supportsDeliverySystem(SYS_DVBC_ANNEX_AC, true);
2368 #endif
2369                 if (parm.system == eDVBFrontendParametersCable::System_DVB_C_ANNEX_A && !can_handle_dvbc_annex_a)
2370                 {
2371                         return 0;
2372                 }
2373                 if (parm.system == eDVBFrontendParametersCable::System_DVB_C_ANNEX_C && !can_handle_dvbc_annex_c)
2374                 {
2375                         return 0;
2376                 }
2377                 score = 2;
2378         }
2379         else if (type == eDVBFrontend::feTerrestrial)
2380         {
2381                 eDVBFrontendParametersTerrestrial parm;
2382                 bool can_handle_dvbt, can_handle_dvbt2;
2383                 can_handle_dvbt = supportsDeliverySystem(SYS_DVBT, true);
2384                 can_handle_dvbt2 = supportsDeliverySystem(SYS_DVBT2, true);
2385                 if (feparm->getDVBT(parm) < 0)
2386                 {
2387                         return 0;
2388                 }
2389                 if (parm.system == eDVBFrontendParametersTerrestrial::System_DVB_T && !can_handle_dvbt)
2390                 {
2391                         return 0;
2392                 }
2393                 if (parm.system == eDVBFrontendParametersTerrestrial::System_DVB_T2 && !can_handle_dvbt2)
2394                 {
2395                         return 0;
2396                 }
2397                 if (parm.system == eDVBFrontendParametersTerrestrial::System_DVB_T_T2 && !(can_handle_dvbt || can_handle_dvbt2))
2398                 {
2399                         return 0;
2400                 }
2401                 score = 2;
2402                 if (parm.system == eDVBFrontendParametersTerrestrial::System_DVB_T && can_handle_dvbt2)
2403                 {
2404                         /* prefer to use a T tuner, try to keep T2 free for T2 transponders */
2405                         score--;
2406                 }
2407         }
2408         else if (type == eDVBFrontend::feATSC)
2409         {
2410                 eDVBFrontendParametersATSC parm;
2411                 bool can_handle_atsc, can_handle_dvbc_annex_b;
2412                 can_handle_dvbc_annex_b = supportsDeliverySystem(SYS_DVBC_ANNEX_B, true);
2413                 can_handle_atsc = supportsDeliverySystem(SYS_ATSC, true);
2414                 if (feparm->getATSC(parm) < 0)
2415                 {
2416                         return 0;
2417                 }
2418                 if (parm.system == eDVBFrontendParametersATSC::System_DVB_C_ANNEX_B && !can_handle_dvbc_annex_b)
2419                 {
2420                         return 0;
2421                 }
2422                 if (parm.system == eDVBFrontendParametersATSC::System_ATSC && !can_handle_atsc)
2423                 {
2424                         return 0;
2425                 }
2426                 score = 2;
2427         }
2428
2429         if (score && preferred)
2430         {
2431                 /* make 'sure' we always prefer this frontend */
2432                 score += 100000; /* the offset has to be so ridiculously high because of the high scores which are used for DVB-S(2) */
2433         }
2434         return score;
2435 }
2436
2437 bool eDVBFrontend::supportsDeliverySystem(const fe_delivery_system_t &sys, bool obeywhitelist)
2438 {
2439         std::map<fe_delivery_system_t, bool>::iterator it = m_delsys.find(sys);
2440         if (it != m_delsys.end() && it->second)
2441         {
2442                 if (obeywhitelist && !m_delsys_whitelist.empty())
2443                 {
2444                         it = m_delsys_whitelist.find(sys);
2445                         if (it == m_delsys_whitelist.end() || !it->second) return false;
2446                 }
2447                 return true;
2448         }
2449         return false;
2450 }
2451
2452 void eDVBFrontend::setDeliverySystemWhitelist(const std::vector<fe_delivery_system_t> &whitelist)
2453 {
2454         m_delsys_whitelist.clear();
2455         for (unsigned int i = 0; i < whitelist.size(); i++)
2456         {
2457                 m_delsys_whitelist[whitelist[i]] = true;
2458         }
2459         if (m_simulate_fe)
2460         {
2461                 m_simulate_fe->setDeliverySystemWhitelist(whitelist);
2462         }
2463 }
2464
2465 bool eDVBFrontend::setSlotInfo(int id, const char *descr, bool enabled, bool isDVBS2, int frontendid)
2466 {
2467         if (frontendid < 0 || frontendid != m_dvbid)
2468         {
2469                 return false;
2470         }
2471         m_slotid = id;
2472         m_enabled = enabled;
2473         strncpy(m_description, descr, sizeof(m_description));
2474
2475         // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2476         m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2477                 !!strstr(m_description, "Alps BSBE2") ||
2478                 !!strstr(m_description, "Alps -S") ||
2479                 !!strstr(m_description, "BCM4501");
2480         if (isDVBS2)
2481         {
2482                 /* HACK for legacy dvb api without DELSYS support */
2483                 m_delsys[SYS_DVBS2] = true;
2484         }
2485         eDebugNoSimulate("[eDVBFrontend] setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2486                 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", isDVBS2 ? "Yes" : "No" );
2487         return true;
2488 }