a9b051333bba154a8069bb5f98c7329c19fe003b
[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         int ter_max = 2900;
785         if (!strcmp(m_description, "AVL2108")) // ET9000
786         {
787                 ret = (int)(snr / 40.5);
788                 sat_max = 1618;
789         }
790         if (!strcmp(m_description, "AVL6211")) // ET10000
791         {
792                 ret = (int)(snr / 37.5);
793                 sat_max = 1700;
794         }
795         else if (strstr("Nova-T StickNovaT 500StickDTB03", m_description)) // dib0700
796         {
797                 if ( snr > 300 )
798                         ret = 0; //error condition
799                 else
800                         ret = (int)(snr * 10);
801         }
802         else if (!strcmp(m_description, "BCM4501 (internal)"))
803         {
804                 eDVBFrontendParametersSatellite parm;
805                 float SDS_SNRE = snr << 16;
806                 float snr_in_db;
807                 oparm.getDVBS(parm);
808
809                 if (parm.system == eDVBFrontendParametersSatellite::System_DVB_S) // DVB-S1 / QPSK
810                 {
811                         static float SNR_COEFF[6] = {
812                                 100.0 / 4194304.0,
813                                 -7136.0 / 4194304.0,
814                                 197418.0 / 4194304.0,
815                                 -2602183.0 / 4194304.0,
816                                 20377212.0 / 4194304.0,
817                                 -37791203.0 / 4194304.0,
818                         };
819                         float fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0)),
820                                                 fval2 = pow(10.0, fval1)-1;
821                         fval1 = 10.0 * log10(fval2);
822
823                         if (fval1 < 10.0)
824                         {
825                                 fval2 = SNR_COEFF[0];
826                                 for (int i=1; i<6; ++i)
827                                 {
828                                         fval2 *= fval1;
829                                         fval2 += SNR_COEFF[i];
830                                 }
831                                 fval1 = fval2;
832                         }
833                         snr_in_db = fval1;
834                 }
835                 else
836                 {
837                         float fval1 = SDS_SNRE / 268435456.0,
838                                         fval2, fval3, fval4;
839
840                         if (parm.modulation == eDVBFrontendParametersSatellite::Modulation_QPSK)
841                         {
842                                 fval2 = 6.76;
843                                 fval3 = 4.35;
844                         }
845                         else // 8PSK
846                         {
847                                 fval1 *= 0.5;
848                                 fval2 = 8.06;
849                                 fval3 = 6.18;
850                         }
851                         fval4 = -10.0 * log10(fval1);
852                         fval1 = fval4;
853                         for (int i=0; i < 5; ++i)
854                                 fval1 = fval4 - fval2 * log10(1.0+pow(10.0, (fval3-fval1)/fval2));
855                         snr_in_db = fval1;
856                 }
857                 sat_max = 1750;
858                 ret = (int)(snr_in_db * 100);
859         }
860         else if (strstr(m_description, "Alps BSBE1 C01A") ||
861                 strstr(m_description, "Alps -S(STV0288)"))
862         {
863                 if (snr == 0)
864                         ret = 0;
865                 else if (snr == 0xFFFF) // i think this should not happen
866                         ret = 100*100;
867                 else
868                 {
869                         enum { REALVAL, REGVAL };
870                         const long CN_lookup[31][2] = {
871                                 {20,8900}, {25,8680}, {30,8420}, {35,8217}, {40,7897},
872                                 {50,7333}, {60,6747}, {70,6162}, {80,5580}, {90,5029},
873                                 {100,4529}, {110,4080}, {120,3685}, {130,3316}, {140,2982},
874                                 {150,2688}, {160,2418}, {170,2188}, {180,1982}, {190,1802},
875                                 {200,1663}, {210,1520}, {220,1400}, {230,1295}, {240,1201},
876                                 {250,1123}, {260,1058}, {270,1004}, {280,957}, {290,920},
877                                 {300,890}
878                         };
879                         int add=strchr(m_description, '.') ? 0xA250 : 0xA100;
880                         long regval = 0xFFFF - ((snr / 3) + add), // revert some dvb api calulations to get the real register value
881                                 Imin=0,
882                                 Imax=30,
883                                 i;
884                         if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
885                         {
886                                 while((Imax-Imin)>1)
887                                 {
888                                         i=(Imax+Imin)/2;
889                                         if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[i][REGVAL]))
890                                                 Imax = i;
891                                         else
892                                                 Imin = i;
893                                 }
894                                 ret = (((regval - CN_lookup[Imin][REGVAL])
895                                                 * (CN_lookup[Imax][REALVAL] - CN_lookup[Imin][REALVAL])
896                                                 / (CN_lookup[Imax][REGVAL] - CN_lookup[Imin][REGVAL]))
897                                                 + CN_lookup[Imin][REALVAL]) * 10;
898                         }
899                         else
900                                 ret = 100;
901                 }
902         }
903         else if (!strcmp(m_description, "Alps BSBE1 702A") ||  // some frontends with STV0299
904                 !strcmp(m_description, "Alps -S") ||
905                 !strcmp(m_description, "Philips -S") ||
906                 !strcmp(m_description, "LG -S") )
907         {
908                 sat_max = 1500;
909                 ret = (int)((snr-39075)/17.647);
910         }
911         else if (!strcmp(m_description, "Alps BSBE2"))
912         {
913                 ret = (int)((snr >> 7) * 10);
914         }
915         else if (!strcmp(m_description, "Philips CU1216Mk3"))
916         {
917                 eDVBFrontendParametersCable parm;
918                 int mse = (~snr) & 0xFF;
919                 oparm.getDVBC(parm);
920                 switch (parm.modulation)
921                 {
922                 case eDVBFrontendParametersCable::Modulation_QAM16: ret = fe_udiv(1950000, (32 * mse) + 138) + 1000; break;
923                 case eDVBFrontendParametersCable::Modulation_QAM32: ret = fe_udiv(2150000, (40 * mse) + 500) + 1350; break;
924                 case eDVBFrontendParametersCable::Modulation_QAM64: ret = fe_udiv(2100000, (40 * mse) + 500) + 1250; break;
925                 case eDVBFrontendParametersCable::Modulation_QAM128: ret = fe_udiv(1850000, (38 * mse) + 400) + 1380; break;
926                 case eDVBFrontendParametersCable::Modulation_QAM256: ret = fe_udiv(1800000, (100 * mse) + 40) + 2030; break;
927                 default: break;
928                 }
929         }
930         else if (!strcmp(m_description, "Philips TU1216"))
931         {
932                 snr = 0xFF - (snr & 0xFF);
933                 if (snr != 0)
934                         ret = 10 * (int)(-100 * (log10(snr) - log10(255)));
935         }
936         else if (strstr(m_description, "BCM4506") || strstr(m_description, "BCM4505"))
937         {
938                 ret = (snr * 100) >> 8;
939         }
940         else if (!strcmp(m_description, "Vuplus DVB-S NIM(AVL2108)")) // VU+Ultimo/VU+Uno DVB-S2 NIM
941         {
942                 ret = (int)((((double(snr) / (65536.0 / 100.0)) * 0.1600) + 0.2100) * 100);
943         }
944         else if (!strcmp(m_description, "Vuplus DVB-S NIM(AVL6222)")) // VU+ DVB-S2 Dual NIM
945         {
946                 ret = (int)((((double(snr) / (65536.0 / 100.0)) * 0.1244) + 2.5079) * 100);
947         }
948         else if (!strcmp(m_description, "Vuplus DVB-S NIM(AVL6211)")) // VU+ DVB-S2 Dual NIM
949         {
950                 ret = (int)((((double(snr) / (65536.0 / 100.0)) * 0.1244) + 2.5079) * 100);
951         }
952         else if (!strcmp(m_description, "BCM7335 DVB-S2 NIM (internal)")) // VU+DUO DVB-S2 NIM
953         {
954                 ret = (int)((((double(snr) / (65536.0 / 100.0)) * 0.1244) + 2.5079) * 100);
955         }
956         else if (!strcmp(m_description, "BCM7346 (internal)")) // MaxDigital XP1000
957         {
958                 ret = (int)((((double(snr) / (65536.0 / 100.0)) * 0.1880) + 0.1959) * 100);
959         }
960         else if (!strcmp(m_description, "BCM7356 DVB-S2 NIM (internal)")) // VU+ Solo2
961         {
962                 ret = (int)((((double(snr) / (65536.0 / 100.0)) * 0.1800) - 1.0000) * 100);
963         }
964         else if (!strcmp(m_description, "Genpix"))
965         {
966                 ret = (int)((snr << 1) / 5);
967         }
968         else if (!strcmp(m_description, "CXD1981"))
969         {
970                 eDVBFrontendParametersCable parm;
971                 int mse = (~snr) & 0xFF;
972                 oparm.getDVBC(parm);
973                 switch (parm.modulation)
974                 {
975                 case eDVBFrontendParametersCable::Modulation_QAM16:
976                 case eDVBFrontendParametersCable::Modulation_QAM64:
977                 case eDVBFrontendParametersCable::Modulation_QAM256: ret = (int)(-950 * log(((double)mse) / 760)); break;
978                 case eDVBFrontendParametersCable::Modulation_QAM32:
979                 case eDVBFrontendParametersCable::Modulation_QAM128: ret = (int)(-875 * log(((double)mse) / 650)); break;
980                 default: break;
981                 }
982         }
983         else if (!strcmp(m_description, "Si216x"))
984         {
985                 eDVBFrontendParametersTerrestrial parm;
986
987                 oparm.getDVBT(parm);
988
989                 switch (parm.system)
990                 {
991                         case eDVBFrontendParametersTerrestrial::System_DVB_T:
992                         case eDVBFrontendParametersTerrestrial::System_DVB_T2: 
993                         case eDVBFrontendParametersTerrestrial::System_DVB_T_T2: ret = (int)(snr / 58); ter_max = 1700; break;
994                         default: break;
995                 }
996         }
997
998         signalqualitydb = ret;
999         if (ret == 0x12345678) // no snr db calculation avail.. return untouched snr value..
1000         {
1001                 signalquality = snr;
1002         }
1003         else
1004         {
1005                 int type = -1;
1006                 oparm.getSystem(type);
1007                 switch (type)
1008                 {
1009                 case feSatellite:
1010                         signalquality = (ret >= sat_max ? 65536 : ret * 65536 / sat_max);
1011                         break;
1012                 case feCable: // we assume a max of 42db here
1013                         signalquality = (ret >= 4200 ? 65536 : ret * 65536 / 4200);
1014                         break;
1015                 case feTerrestrial: // we assume a max of 29db here
1016                         signalquality = (ret >= ter_max ? 65536 : ret * 65536 / ter_max);
1017                         break;
1018                 case feATSC: // we assume a max of 42db here
1019                         signalquality = (ret >= 4200 ? 65536 : ret * 65536 / 4200);
1020                         break;
1021                 }
1022         }
1023 }
1024
1025 int eDVBFrontend::readFrontendData(int type)
1026 {
1027         switch(type)
1028         {
1029                 case iFrontendInformation_ENUMS::bitErrorRate:
1030                         if (m_state == stateLock)
1031                         {
1032                                 uint32_t ber=0;
1033                                 if (!m_simulate)
1034                                 {
1035                                         if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
1036                                                 eDebug("[eDVBFrontend] FE_READ_BER failed: %m");
1037                                 }
1038                                 return ber;
1039                         }
1040                         break;
1041                 case iFrontendInformation_ENUMS::snrValue:
1042                         if (m_state == stateLock)
1043                         {
1044                                 uint16_t snr = 0;
1045                                 if (!m_simulate)
1046                                 {
1047                                         if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
1048                                                 eDebug("[eDVBFrontend] FE_READ_SNR failed: %m");
1049                                 }
1050                                 return snr;
1051                         }
1052                         break;
1053                 case iFrontendInformation_ENUMS::signalQuality:
1054                 case iFrontendInformation_ENUMS::signalQualitydB: /* this will move into the driver */
1055                         if (m_state == stateLock)
1056                         {
1057                                 int snr = readFrontendData(iFrontendInformation_ENUMS::snrValue);
1058                                 int signalquality = 0;
1059                                 int signalqualitydb = 0;
1060                                 calculateSignalQuality(snr, signalquality, signalqualitydb);
1061                                 if (type == iFrontendInformation_ENUMS::signalQuality)
1062                                 {
1063                                         return signalquality;
1064                                 }
1065                                 else
1066                                 {
1067                                         return signalqualitydb;
1068                                 }
1069                         }
1070                         break;
1071                 case iFrontendInformation_ENUMS::signalPower:
1072                         if (m_state == stateLock)
1073                         {
1074                                 uint16_t strength=0;
1075                                 if (!m_simulate)
1076                                 {
1077                                         if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
1078                                                 eDebug("[eDVBFrontend] FE_READ_SIGNAL_STRENGTH failed: %m");
1079                                 }
1080                                 return strength;
1081                         }
1082                         break;
1083                 case iFrontendInformation_ENUMS::lockState:
1084                         return !!(readFrontendData(iFrontendInformation_ENUMS::frontendStatus) & FE_HAS_LOCK);
1085                 case iFrontendInformation_ENUMS::syncState:
1086                         return !!(readFrontendData(iFrontendInformation_ENUMS::frontendStatus) & FE_HAS_SYNC);
1087                 case iFrontendInformation_ENUMS::frontendNumber:
1088                         return m_slotid;
1089                 case iFrontendInformation_ENUMS::frontendStatus:
1090                 {
1091                         fe_status_t status;
1092                         if (!m_simulate)
1093                         {
1094                                 if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
1095                                         eDebug("[eDVBFrontend] FE_READ_STATUS failed: %m");
1096                                 return (int)status;
1097                         }
1098                         return (FE_HAS_SYNC | FE_HAS_LOCK);
1099                 }
1100                 case iFrontendInformation_ENUMS::frequency:
1101                 {
1102                         struct dtv_property p;
1103                         struct dtv_properties cmdseq;
1104                         oparm.getSystem(type);
1105                         cmdseq.props = &p;
1106                         cmdseq.num = 1;
1107                         p.cmd = DTV_FREQUENCY;
1108                         if (ioctl(m_fd, FE_GET_PROPERTY, &cmdseq) < 0)
1109                         {
1110                                 return 0;
1111                         }
1112                         return p.u.data + m_data[FREQ_OFFSET];
1113                 }
1114         }
1115         return 0;
1116 }
1117
1118 void eDVBFrontend::getFrontendStatus(ePtr<iDVBFrontendStatus> &dest)
1119 {
1120         ePtr<eDVBFrontend> fe = this;
1121         dest = new eDVBFrontendStatus(fe);
1122 }
1123
1124 void eDVBFrontend::getTransponderData(ePtr<iDVBTransponderData> &dest, bool original)
1125 {
1126         int type = -1;
1127         struct dtv_property p[16];
1128         struct dtv_properties cmdseq;
1129         oparm.getSystem(type);
1130         cmdseq.props = p;
1131         cmdseq.num = 0;
1132         if (m_simulate || m_fd == -1 || original)
1133         {
1134                 original = true;
1135         }
1136         else
1137         {
1138                 p[cmdseq.num++].cmd = DTV_DELIVERY_SYSTEM;
1139                 p[cmdseq.num++].cmd = DTV_FREQUENCY;
1140                 p[cmdseq.num++].cmd = DTV_INVERSION;
1141                 p[cmdseq.num++].cmd = DTV_MODULATION;
1142                 if (type == feSatellite)
1143                 {
1144                         p[cmdseq.num++].cmd = DTV_SYMBOL_RATE;
1145                         p[cmdseq.num++].cmd = DTV_INNER_FEC;
1146                         p[cmdseq.num++].cmd = DTV_ROLLOFF;
1147                         p[cmdseq.num++].cmd = DTV_PILOT;
1148                 }
1149                 else if (type == feCable)
1150                 {
1151                         p[cmdseq.num++].cmd = DTV_SYMBOL_RATE;
1152                         p[cmdseq.num++].cmd = DTV_INNER_FEC;
1153                 }
1154                 else if (type == feTerrestrial)
1155                 {
1156                         p[cmdseq.num++].cmd = DTV_BANDWIDTH_HZ;
1157                         p[cmdseq.num++].cmd = DTV_CODE_RATE_HP;
1158                         p[cmdseq.num++].cmd = DTV_CODE_RATE_LP;
1159                         p[cmdseq.num++].cmd = DTV_TRANSMISSION_MODE;
1160                         p[cmdseq.num++].cmd = DTV_GUARD_INTERVAL;
1161                         p[cmdseq.num++].cmd = DTV_HIERARCHY;
1162                 }
1163                 else if (type == feATSC)
1164                 {
1165                 }
1166                 if (ioctl(m_fd, FE_GET_PROPERTY, &cmdseq) < 0)
1167                 {
1168                         eDebug("[eDVBFrontend] FE_GET_PROPERTY failed: %m");
1169                         original = true;
1170                 }
1171         }
1172         switch (type)
1173         {
1174         case feSatellite:
1175                 {
1176                         eDVBFrontendParametersSatellite s;
1177                         oparm.getDVBS(s);
1178                         dest = new eDVBSatelliteTransponderData(cmdseq.props, cmdseq.num, s, m_data[FREQ_OFFSET], original);
1179                         break;
1180                 }
1181         case feCable:
1182                 {
1183                         eDVBFrontendParametersCable c;
1184                         oparm.getDVBC(c);
1185                         dest = new eDVBCableTransponderData(cmdseq.props, cmdseq.num, c, original);
1186                         break;
1187                 }
1188         case feTerrestrial:
1189                 {
1190                         eDVBFrontendParametersTerrestrial t;
1191                         oparm.getDVBT(t);
1192                         dest = new eDVBTerrestrialTransponderData(cmdseq.props, cmdseq.num, t, original);
1193                         break;
1194                 }
1195         case feATSC:
1196                 {
1197                         eDVBFrontendParametersATSC a;
1198                         oparm.getATSC(a);
1199                         dest = new eDVBATSCTransponderData(cmdseq.props, cmdseq.num, a, original);
1200                         break;
1201                 }
1202         }
1203 }
1204
1205 void eDVBFrontend::getFrontendData(ePtr<iDVBFrontendData> &dest)
1206 {
1207         ePtr<eDVBFrontend> fe = this;
1208         dest = new eDVBFrontendData(fe);
1209 }
1210
1211 #ifndef FP_IOCTL_GET_ID
1212 #define FP_IOCTL_GET_ID 0
1213 #endif
1214 int eDVBFrontend::readInputpower()
1215 {
1216         if (m_simulate)
1217                 return 0;
1218         int power=m_slotid;  // this is needed for read inputpower from the correct tuner !
1219         char proc_name[64];
1220         sprintf(proc_name, "/proc/stb/frontend/%d/lnb_sense", m_slotid);
1221
1222         if (CFile::parseInt(&power, proc_name) == 0)
1223                 return power;
1224
1225         sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
1226         if (CFile::parseInt(&power, proc_name) == 0)
1227                 return power;
1228
1229         // open front processor
1230         int fp=::open("/dev/dbox/fp0", O_RDWR);
1231         if (fp < 0)
1232         {
1233                 eDebug("[eDVBFrontend] Failed to open /dev/dbox/fp0");
1234                 return -1;
1235         }
1236         static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
1237         if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
1238         {
1239                 eDebug("[eDVBFrontend] FP_IOCTL_GET_LNB_CURRENT failed: %m");
1240                 power = -1;
1241         }
1242         ::close(fp);
1243
1244         return power;
1245 }
1246
1247 bool eDVBFrontend::setSecSequencePos(int steps)
1248 {
1249         eDebugNoSimulate("[eDVBFrontend] set sequence pos %d", steps);
1250         if (!steps)
1251                 return false;
1252         while( steps > 0 )
1253         {
1254                 if (m_sec_sequence.current() != m_sec_sequence.end())
1255                         ++m_sec_sequence.current();
1256                 --steps;
1257         }
1258         while( steps < 0 )
1259         {
1260                 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1261                         --m_sec_sequence.current();
1262                 ++steps;
1263         }
1264         return true;
1265 }
1266
1267 void eDVBFrontend::tuneLoop()
1268 {
1269         tuneLoopInt();
1270 }
1271
1272 int eDVBFrontend::tuneLoopInt()  // called by m_tuneTimer
1273 {
1274         int delay=-1;
1275         eDVBFrontend *sec_fe = this;
1276         eDVBRegisteredFrontend *regFE = 0;
1277         long tmp = m_data[LINKED_PREV_PTR];
1278         while ( tmp != -1 )
1279         {
1280                 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)tmp;
1281                 sec_fe = prev->m_frontend;
1282                 tmp = prev->m_frontend->m_data[LINKED_PREV_PTR];
1283                 if (tmp == -1 && sec_fe != this && !prev->m_inuse) {
1284                         int state = sec_fe->m_state;
1285                         // workaround to put the kernel frontend thread into idle state!
1286                         if (state != eDVBFrontend::stateIdle && state != stateClosed)
1287                         {
1288                                 sec_fe->closeFrontend(true);
1289                                 state = sec_fe->m_state;
1290                         }
1291                         // sec_fe is closed... we must reopen it here..
1292                         if (state == stateClosed)
1293                         {
1294                                 regFE = prev;
1295                                 prev->inc_use();
1296                         }
1297                 }
1298         }
1299
1300         if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1301         {
1302                 long *sec_fe_data = sec_fe->m_data;
1303 //              eDebugNoSimulate("[eDVBFrontend] tuneLoop %d\n", m_sec_sequence.current()->cmd);
1304                 delay = 0;
1305                 switch (m_sec_sequence.current()->cmd)
1306                 {
1307                         case eSecCommand::SLEEP:
1308                                 delay = m_sec_sequence.current()++->msec;
1309                                 eDebugNoSimulate("[eDVBFrontend] sleep %dms", delay);
1310                                 break;
1311                         case eSecCommand::GOTO:
1312                                 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1313                                         ++m_sec_sequence.current();
1314                                 break;
1315                         case eSecCommand::SET_VOLTAGE:
1316                         {
1317                                 int voltage = m_sec_sequence.current()++->voltage;
1318                                 eDebugNoSimulate("[eDVBFrontend] setVoltage %d", voltage);
1319                                 sec_fe->setVoltage(voltage);
1320                                 break;
1321                         }
1322                         case eSecCommand::IF_VOLTAGE_GOTO:
1323                         {
1324                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1325                                 if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1326                                         break;
1327                                 ++m_sec_sequence.current();
1328                                 break;
1329                         }
1330                         case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1331                         {
1332                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1333                                 if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
1334                                         break;
1335                                 ++m_sec_sequence.current();
1336                                 break;
1337                         }
1338                         case eSecCommand::IF_TONE_GOTO:
1339                         {
1340                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1341                                 if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1342                                         break;
1343                                 ++m_sec_sequence.current();
1344                                 break;
1345                         }
1346                         case eSecCommand::IF_NOT_TONE_GOTO:
1347                         {
1348                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1349                                 if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
1350                                         break;
1351                                 ++m_sec_sequence.current();
1352                                 break;
1353                         }
1354                         case eSecCommand::SET_TONE:
1355                                 eDebugNoSimulate("[eDVBFrontend] setTone %d", m_sec_sequence.current()->tone);
1356                                 sec_fe->setTone(m_sec_sequence.current()++->tone);
1357                                 break;
1358                         case eSecCommand::SEND_DISEQC:
1359                                 sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
1360                                 eDebugNoSimulateNoNewLineStart("[eDVBFrontend] sendDiseqc: ");
1361                                 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1362                                     eDebugNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1363  
1364                                 if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x00", 3))
1365                                         eDebugNoNewLine("(DiSEqC reset)\n");
1366                                 else if (!memcmp(m_sec_sequence.current()->diseqc.data, "\xE0\x00\x03", 3))
1367                                         eDebugNoNewLine("(DiSEqC peripherial power on)\n");
1368                                 else
1369                                         eDebugNoNewLine("(?)\n");
1370                                 ++m_sec_sequence.current();
1371                                 break;
1372                         case eSecCommand::SEND_TONEBURST:
1373                                 eDebugNoSimulate("[eDVBFrontend] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1374                                 sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
1375                                 break;
1376                         case eSecCommand::SET_FRONTEND:
1377                         {
1378                                 int enableEvents = (m_sec_sequence.current()++)->val;
1379                                 eDebugNoSimulate("[eDVBFrontend] setFrontend %d", enableEvents);
1380                                 setFrontend(enableEvents);
1381                                 break;
1382                         }
1383                         case eSecCommand::START_TUNE_TIMEOUT:
1384                         {
1385                                 int tuneTimeout = m_sec_sequence.current()->timeout;
1386                                 eDebugNoSimulate("[eDVBFrontend] startTuneTimeout %d", tuneTimeout);
1387                                 if (!m_simulate)
1388                                         m_timeout->start(tuneTimeout, 1);
1389                                 ++m_sec_sequence.current();
1390                                 break;
1391                         }
1392                         case eSecCommand::SET_TIMEOUT:
1393                                 m_timeoutCount = m_sec_sequence.current()++->val;
1394                                 eDebugNoSimulate("[eDVBFrontend] set timeout %d", m_timeoutCount);
1395                                 break;
1396                         case eSecCommand::IF_TIMEOUT_GOTO:
1397                                 if (!m_timeoutCount)
1398                                 {
1399                                         eDebugNoSimulate("[eDVBFrontend] rotor timout");
1400                                         setSecSequencePos(m_sec_sequence.current()->steps);
1401                                 }
1402                                 else
1403                                         ++m_sec_sequence.current();
1404                                 break;
1405                         case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1406                         {
1407                                 int idx = m_sec_sequence.current()++->val;
1408                                 if ( idx == 0 || idx == 1 )
1409                                 {
1410                                         m_idleInputpower[idx] = sec_fe->readInputpower();
1411                                         eDebugNoSimulate("[eDVBFrontend] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1412                                 }
1413                                 else
1414                                         eDebugNoSimulate("[eDVBFrontend] idleInputpower measure index(%d) out of bound !!!", idx);
1415                                 break;
1416                         }
1417                         case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1418                         {
1419                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1420                                 int idx = compare.val;
1421                                 if ( !m_simulate && (idx == 0 || idx == 1) )
1422                                 {
1423                                         int idle = sec_fe->readInputpower();
1424                                         int diff = abs(idle-m_idleInputpower[idx]);
1425                                         if ( diff > 0)
1426                                         {
1427                                                 eDebugNoSimulate("[eDVBFrontend]   measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1428                                                 setSecSequencePos(compare.steps);
1429                                                 break;
1430                                         }
1431                                 }
1432                                 ++m_sec_sequence.current();
1433                                 break;
1434                         }
1435                         case eSecCommand::IF_TUNER_LOCKED_GOTO:
1436                         {
1437                                 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1438                                 if (m_simulate)
1439                                 {
1440                                         setSecSequencePos(cmd.steps);
1441                                         break;
1442                                 }
1443                                 int signal = 0;
1444                                 int isLocked = readFrontendData(iFrontendInformation_ENUMS::lockState);
1445                                 m_idleInputpower[0] = m_idleInputpower[1] = 0;
1446                                 --m_timeoutCount;
1447                                 if (!m_timeoutCount && m_retryCount > 0)
1448                                         --m_retryCount;
1449                                 if (isLocked && ((abs((signal = readFrontendData(iFrontendInformation_ENUMS::signalQualitydB)) - cmd.lastSignal) < 40) || !cmd.lastSignal))
1450                                 {
1451                                         if (cmd.lastSignal)
1452                                                 eDebugNoSimulate("[eDVBFrontend] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
1453                                         else
1454                                         {
1455                                                 eDebugNoSimulate("[eDVBFrontend] locked step %d ok", cmd.okcount);
1456                                                 if (!cmd.okcount)
1457                                                         cmd.lastSignal = signal;
1458                                         }
1459                                         ++cmd.okcount;
1460                                         if (cmd.okcount > 4)
1461                                         {
1462                                                 eDebugNoSimulate("[eDVBFrontend] ok > 4 .. goto %d\n", cmd.steps);
1463                                                 setSecSequencePos(cmd.steps);
1464                                                 m_state = stateLock;
1465                                                 m_stateChanged(this);
1466                                                 feEvent(-1); // flush events
1467                                                 m_sn->start();
1468                                                 break;
1469                                         }
1470                                 }
1471                                 else
1472                                 {
1473                                         if (isLocked)
1474                                                 eDebugNoSimulate("[eDVBFrontend] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
1475                                         else
1476                                                 eDebugNoSimulate("[eDVBFrontend] rotor locked step %d failed (not locked)", cmd.okcount);
1477                                         cmd.okcount=0;
1478                                         cmd.lastSignal=0;
1479                                 }
1480                                 ++m_sec_sequence.current();
1481                                 break;
1482                         }
1483                         case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1484                                 m_runningInputpower = sec_fe->readInputpower();
1485                                 eDebugNoSimulate("[eDVBFrontend] runningInputpower is %d", m_runningInputpower);
1486                                 ++m_sec_sequence.current();
1487                                 break;
1488                         case eSecCommand::SET_ROTOR_MOVING:
1489                                 if (!m_simulate)
1490                                         m_sec->setRotorMoving(m_slotid, true);
1491                                 ++m_sec_sequence.current();
1492                                 break;
1493                         case eSecCommand::SET_ROTOR_STOPPED:
1494                                 if (!m_simulate)
1495                                         m_sec->setRotorMoving(m_slotid, false);
1496                                 ++m_sec_sequence.current();
1497                                 break;
1498                         case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1499                         {
1500                                 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1501                                 if (m_simulate)
1502                                 {
1503                                         setSecSequencePos(cmd.steps);
1504                                         break;
1505                                 }
1506                                 int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
1507                                 const char *txt = cmd.direction ? "running" : "stopped";
1508                                 --m_timeoutCount;
1509                                 if (!m_timeoutCount && m_retryCount > 0)
1510                                         --m_retryCount;
1511                                 eDebugNoSimulate("[eDVBFrontend] waiting for rotor %s %d, idle %d, delta %d",
1512                                         txt,
1513                                         m_runningInputpower,
1514                                         idleInputpower,
1515                                         cmd.deltaA);
1516                                 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1517                                         || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1518                                 {
1519                                         ++cmd.okcount;
1520                                         eDebugNoSimulate("[eDVBFrontend] rotor %s step %d ok", txt, cmd.okcount);
1521                                         if ( cmd.okcount > 6 )
1522                                         {
1523                                                 eDebugNoSimulate("[eDVBFrontend] rotor is %s", txt);
1524                                                 if (setSecSequencePos(cmd.steps))
1525                                                         break;
1526                                         }
1527                                 }
1528                                 else
1529                                 {
1530                                         eDebugNoSimulate("[eDVBFrontend] rotor not %s... reset counter.. increase timeout", txt);
1531                                         cmd.okcount=0;
1532                                 }
1533                                 ++m_sec_sequence.current();
1534                                 break;
1535                         }
1536                         case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1537                                 if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
1538                                         setSecSequencePos(m_sec_sequence.current()->steps);
1539                                 else
1540                                         ++m_sec_sequence.current();
1541                                 break;
1542                         case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
1543                                 eDebugNoSimulate("[eDVBFrontend] invalidate current switch params");
1544                                 sec_fe_data[CSW] = -1;
1545                                 sec_fe_data[UCSW] = -1;
1546                                 sec_fe_data[TONEBURST] = -1;
1547                                 ++m_sec_sequence.current();
1548                                 break;
1549                         case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
1550                                 sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
1551                                 sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
1552                                 sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
1553                                 eDebugNoSimulate("[eDVBFrontend] update current switch params");
1554                                 ++m_sec_sequence.current();
1555                                 break;
1556                         case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1557                                 eDebugNoSimulate("[eDVBFrontend] invalidate current rotorparams");
1558                                 sec_fe_data[ROTOR_CMD] = -1;
1559                                 sec_fe_data[ROTOR_POS] = -1;
1560                                 ++m_sec_sequence.current();
1561                                 break;
1562                         case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1563                                 sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
1564                                 sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
1565                                 eDebugNoSimulate("[eDVBFrontend] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
1566                                 ++m_sec_sequence.current();
1567                                 break;
1568                         case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1569                                 m_retryCount = m_sec_sequence.current()++->val;
1570                                 eDebugNoSimulate("[eDVBFrontend] set rotor retries %d", m_retryCount);
1571                                 break;
1572                         case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1573                                 if (!m_retryCount)
1574                                 {
1575                                         eDebugNoSimulate("[eDVBFrontend] no more rotor retrys");
1576                                         setSecSequencePos(m_sec_sequence.current()->steps);
1577                                 }
1578                                 else
1579                                         ++m_sec_sequence.current();
1580                                 break;
1581                         case eSecCommand::SET_POWER_LIMITING_MODE:
1582                         {
1583                                 if (!m_simulate)
1584                                 {
1585                                         char proc_name[64];
1586                                         sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
1587                                         CFile f(proc_name, "w");
1588                                         if (f) // new interface exist?
1589                                         {
1590                                                 bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
1591                                                 if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
1592                                                         eDebugNoSimulate("[eDVBFrontend] write %s failed: %m", proc_name);
1593                                                 else
1594                                                         eDebugNoSimulate("[eDVBFrontend] set %s current limiting", slimiting ? "static" : "dynamic");
1595                                         }
1596                                         else if (sec_fe->m_need_rotor_workaround)
1597                                         {
1598                                                 char dev[16];
1599                                                 int slotid = sec_fe->m_slotid;
1600                                                 // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
1601                                                 if (slotid < 2)
1602                                                         sprintf(dev, "/dev/i2c-%d", slotid);
1603                                                 else if (slotid == 2)
1604                                                         sprintf(dev, "/dev/i2c-2"); // first nim socket on DM8000 use /dev/i2c-2
1605                                                 else if (slotid == 3)
1606                                                         sprintf(dev, "/dev/i2c-4"); // second nim socket on DM8000 use /dev/i2c-4
1607                                                 int fd = ::open(dev, O_RDWR);
1608                                                 if (fd >= 0)
1609                                                 {
1610                                                         unsigned char data[2];
1611                                                         ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1612                                                         if(::read(fd, data, 1) != 1)
1613                                                                 eDebugNoSimulate("[eDVBFrontend] error read lnbp: %m");
1614                                                         if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1615                                                         {
1616                                                                 data[0] |= 0x80;  // enable static current limiting
1617                                                                 eDebugNoSimulate("[eDVBFrontend] set static current limiting");
1618                                                         }
1619                                                         else
1620                                                         {
1621                                                                 data[0] &= ~0x80;  // enable dynamic current limiting
1622                                                                 eDebugNoSimulate("[eDVBFrontend] set dynamic current limiting");
1623                                                         }
1624                                                         if(::write(fd, data, 1) != 1)
1625                                                                 eDebugNoSimulate("[eDVBFrontend] error write lnbp: %m");
1626                                                         ::close(fd);
1627                                                 }
1628                                         }
1629                                 }
1630                                 ++m_sec_sequence.current();
1631                                 break;
1632                         }
1633                         case eSecCommand::DELAYED_CLOSE_FRONTEND:
1634                         {
1635                                 eDebugNoSimulate("[eDVBFrontend] delayed close frontend");
1636                                 closeFrontend(false, true);
1637                                 ++m_sec_sequence.current();
1638                                 break;
1639                         }
1640                         default:
1641                                 eDebugNoSimulate("[eDVBFrontend] unhandled sec command %d",
1642                                         ++m_sec_sequence.current()->cmd);
1643                                 ++m_sec_sequence.current();
1644                 }
1645                 if (!m_simulate)
1646                         m_tuneTimer->start(delay,true);
1647         }
1648         if (regFE)
1649                 regFE->dec_use();
1650         if (m_simulate && m_sec_sequence.current() != m_sec_sequence.end())
1651                 tuneLoop();
1652         return delay;
1653 }
1654
1655 void eDVBFrontend::setFrontend(bool recvEvents)
1656 {
1657         if (!m_simulate)
1658         {
1659                 int type = -1;
1660                 oparm.getSystem(type);
1661                 eDebug("[eDVBFrontend] setting frontend %d", m_dvbid);
1662                 if (recvEvents)
1663                         m_sn->start();
1664                 feEvent(-1); // flush events
1665                 struct dtv_property p[16];
1666                 struct dtv_properties cmdseq;
1667                 cmdseq.props = p;
1668                 cmdseq.num = 0;
1669                 p[cmdseq.num].cmd = DTV_CLEAR, cmdseq.num++;
1670                 if (type == iDVBFrontend::feSatellite)
1671                 {
1672                         eDVBFrontendParametersSatellite parm;
1673                         fe_rolloff_t rolloff = ROLLOFF_35;
1674                         fe_pilot_t pilot = PILOT_OFF;
1675                         fe_modulation_t modulation = QPSK;
1676                         fe_delivery_system_t system = SYS_DVBS;
1677                         oparm.getDVBS(parm);
1678
1679                         p[cmdseq.num].cmd = DTV_INVERSION;
1680                         switch (parm.inversion)
1681                         {
1682                                 case eDVBFrontendParametersSatellite::Inversion_Off: p[cmdseq.num].u.data = INVERSION_OFF; break;
1683                                 case eDVBFrontendParametersSatellite::Inversion_On: p[cmdseq.num].u.data = INVERSION_ON; break;
1684                                 default:
1685                                 case eDVBFrontendParametersSatellite::Inversion_Unknown: p[cmdseq.num].u.data = INVERSION_AUTO; break;
1686                         }
1687                         cmdseq.num++;
1688
1689                         switch (parm.system)
1690                         {
1691                                 default:
1692                                 case eDVBFrontendParametersSatellite::System_DVB_S: system = SYS_DVBS; break;
1693                                 case eDVBFrontendParametersSatellite::System_DVB_S2: system = SYS_DVBS2; break;
1694                         }
1695                         switch (parm.modulation)
1696                         {
1697                                 case eDVBFrontendParametersSatellite::Modulation_QPSK: modulation = QPSK; break;
1698                                 case eDVBFrontendParametersSatellite::Modulation_8PSK: modulation = PSK_8; break;
1699                                 case eDVBFrontendParametersSatellite::Modulation_QAM16: modulation = QAM_16; break;
1700                         }
1701                         switch (parm.pilot)
1702                         {
1703                                 case eDVBFrontendParametersSatellite::Pilot_Off: pilot = PILOT_OFF; break;
1704                                 case eDVBFrontendParametersSatellite::Pilot_On: pilot = PILOT_ON; break;
1705                                 default:
1706                                 case eDVBFrontendParametersSatellite::Pilot_Unknown: pilot = PILOT_AUTO; break;
1707                         }
1708                         switch (parm.rolloff)
1709                         {
1710                                 case eDVBFrontendParametersSatellite::RollOff_alpha_0_20: rolloff = ROLLOFF_20; break;
1711                                 case eDVBFrontendParametersSatellite::RollOff_alpha_0_25: rolloff = ROLLOFF_25; break;
1712                                 case eDVBFrontendParametersSatellite::RollOff_alpha_0_35: rolloff = ROLLOFF_35; break;
1713                                 default:
1714                                 case eDVBFrontendParametersSatellite::RollOff_auto: rolloff = ROLLOFF_AUTO; break;
1715                         }
1716                         p[cmdseq.num].cmd = DTV_FREQUENCY, p[cmdseq.num].u.data = satfrequency, cmdseq.num++;
1717                         p[cmdseq.num].cmd = DTV_DELIVERY_SYSTEM, p[cmdseq.num].u.data = system, cmdseq.num++;
1718                         p[cmdseq.num].cmd = DTV_MODULATION, p[cmdseq.num].u.data = modulation, cmdseq.num++;
1719                         p[cmdseq.num].cmd = DTV_SYMBOL_RATE, p[cmdseq.num].u.data = parm.symbol_rate, cmdseq.num++;
1720
1721                         p[cmdseq.num].cmd = DTV_INNER_FEC;
1722                         switch (parm.fec)
1723                         {
1724                                 case eDVBFrontendParametersSatellite::FEC_1_2: p[cmdseq.num].u.data = FEC_1_2; break;
1725                                 case eDVBFrontendParametersSatellite::FEC_2_3: p[cmdseq.num].u.data = FEC_2_3; break;
1726                                 case eDVBFrontendParametersSatellite::FEC_3_4: p[cmdseq.num].u.data = FEC_3_4; break;
1727                                 case eDVBFrontendParametersSatellite::FEC_3_5: p[cmdseq.num].u.data = FEC_3_5; break;
1728                                 case eDVBFrontendParametersSatellite::FEC_4_5: p[cmdseq.num].u.data = FEC_4_5; break;
1729                                 case eDVBFrontendParametersSatellite::FEC_5_6: p[cmdseq.num].u.data = FEC_5_6; break;
1730                                 case eDVBFrontendParametersSatellite::FEC_6_7: p[cmdseq.num].u.data = FEC_6_7; break;
1731                                 case eDVBFrontendParametersSatellite::FEC_7_8: p[cmdseq.num].u.data = FEC_7_8; break;
1732                                 case eDVBFrontendParametersSatellite::FEC_8_9: p[cmdseq.num].u.data = FEC_8_9; break;
1733                                 case eDVBFrontendParametersSatellite::FEC_9_10: p[cmdseq.num].u.data = FEC_9_10; break;
1734                                 case eDVBFrontendParametersSatellite::FEC_None: p[cmdseq.num].u.data = FEC_NONE; break;
1735                                 default:
1736                                 case eDVBFrontendParametersSatellite::FEC_Auto: p[cmdseq.num].u.data = FEC_AUTO; break;
1737                         }
1738                         cmdseq.num++;
1739                         if (system == SYS_DVBS2)
1740                         {
1741                                 p[cmdseq.num].cmd = DTV_ROLLOFF, p[cmdseq.num].u.data = rolloff, cmdseq.num++;
1742                                 p[cmdseq.num].cmd = DTV_PILOT, p[cmdseq.num].u.data = pilot, cmdseq.num++;
1743                         }
1744                 }
1745                 else if (type == iDVBFrontend::feCable)
1746                 {
1747                         eDVBFrontendParametersCable parm;
1748                         oparm.getDVBC(parm);
1749                         p[cmdseq.num].cmd = DTV_FREQUENCY, p[cmdseq.num].u.data = parm.frequency * 1000, cmdseq.num++;
1750
1751                         p[cmdseq.num].cmd = DTV_INVERSION;
1752                         switch (parm.inversion)
1753                         {
1754                                 case eDVBFrontendParametersCable::Inversion_Off: p[cmdseq.num].u.data = INVERSION_OFF; break;
1755                                 case eDVBFrontendParametersCable::Inversion_On: p[cmdseq.num].u.data = INVERSION_ON; break;
1756                                 default:
1757                                 case eDVBFrontendParametersCable::Inversion_Unknown: p[cmdseq.num].u.data = INVERSION_AUTO; break;
1758                         }
1759                         cmdseq.num++;
1760
1761                         p[cmdseq.num].cmd = DTV_DELIVERY_SYSTEM;
1762 #if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 6
1763                         if (m_dvbversion >= DVB_VERSION(5, 6))
1764                         {
1765                                 switch (parm.system)
1766                                 {
1767                                         default:
1768                                         case eDVBFrontendParametersCable::System_DVB_C_ANNEX_A: p[cmdseq.num].u.data = SYS_DVBC_ANNEX_A; break;
1769                                         case eDVBFrontendParametersCable::System_DVB_C_ANNEX_C: p[cmdseq.num].u.data = SYS_DVBC_ANNEX_C; break;
1770                                 }
1771                         }
1772                         else
1773                         {
1774                                 p[cmdseq.num].u.data = SYS_DVBC_ANNEX_A; /* old value for SYS_DVBC_ANNEX_AC */
1775                         }
1776 #else
1777                         p[cmdseq.num].u.data = SYS_DVBC_ANNEX_AC;
1778 #endif
1779                         cmdseq.num++;
1780
1781                         p[cmdseq.num].cmd = DTV_SYMBOL_RATE, p[cmdseq.num].u.data = parm.symbol_rate, cmdseq.num++;
1782
1783                         p[cmdseq.num].cmd = DTV_INNER_FEC;
1784                         switch (parm.fec_inner)
1785                         {
1786                                 default:
1787                                 case eDVBFrontendParametersCable::FEC_Auto: p[cmdseq.num].u.data = FEC_AUTO; break;
1788                                 case eDVBFrontendParametersCable::FEC_1_2: p[cmdseq.num].u.data = FEC_1_2; break;
1789                                 case eDVBFrontendParametersCable::FEC_2_3: p[cmdseq.num].u.data = FEC_2_3; break;
1790                                 case eDVBFrontendParametersCable::FEC_3_4: p[cmdseq.num].u.data = FEC_3_4; break;
1791                                 case eDVBFrontendParametersCable::FEC_5_6: p[cmdseq.num].u.data = FEC_5_6; break;
1792                                 case eDVBFrontendParametersCable::FEC_7_8: p[cmdseq.num].u.data = FEC_7_8; break;
1793                                 case eDVBFrontendParametersCable::FEC_8_9: p[cmdseq.num].u.data = FEC_8_9; break;
1794                                 case eDVBFrontendParametersCable::FEC_3_5: p[cmdseq.num].u.data = FEC_3_5; break;
1795                                 case eDVBFrontendParametersCable::FEC_4_5: p[cmdseq.num].u.data = FEC_4_5; break;
1796                                 case eDVBFrontendParametersCable::FEC_9_10: p[cmdseq.num].u.data = FEC_9_10; break;
1797                         }
1798                         cmdseq.num++;
1799
1800                         p[cmdseq.num].cmd = DTV_MODULATION;
1801                         switch (parm.modulation)
1802                         {
1803                                 default:
1804                                 case eDVBFrontendParametersCable::Modulation_Auto: p[cmdseq.num].u.data = QAM_AUTO; break;
1805                                 case eDVBFrontendParametersCable::Modulation_QAM16: p[cmdseq.num].u.data = QAM_16; break;
1806                                 case eDVBFrontendParametersCable::Modulation_QAM32: p[cmdseq.num].u.data = QAM_32; break;
1807                                 case eDVBFrontendParametersCable::Modulation_QAM64: p[cmdseq.num].u.data = QAM_64; break;
1808                                 case eDVBFrontendParametersCable::Modulation_QAM128: p[cmdseq.num].u.data = QAM_128; break;
1809                                 case eDVBFrontendParametersCable::Modulation_QAM256: p[cmdseq.num].u.data = QAM_256; break;
1810                         }
1811                         cmdseq.num++;
1812                 }
1813                 else if (type == iDVBFrontend::feTerrestrial)
1814                 {
1815                         eDVBFrontendParametersTerrestrial parm;
1816                         fe_delivery_system_t system = SYS_DVBT;
1817                         oparm.getDVBT(parm);
1818                         switch (parm.system)
1819                         {
1820                                 default:
1821                                 case eDVBFrontendParametersTerrestrial::System_DVB_T: system = SYS_DVBT; break;
1822                                 case eDVBFrontendParametersTerrestrial::System_DVB_T2: system = SYS_DVBT2; break;
1823                         }
1824
1825                         p[cmdseq.num].cmd = DTV_DELIVERY_SYSTEM, p[cmdseq.num].u.data = system, cmdseq.num++;
1826                         p[cmdseq.num].cmd = DTV_FREQUENCY, p[cmdseq.num].u.data = parm.frequency, cmdseq.num++;
1827
1828                         p[cmdseq.num].cmd = DTV_INVERSION;
1829                         switch (parm.inversion)
1830                         {
1831                                 case eDVBFrontendParametersTerrestrial::Inversion_Off: p[cmdseq.num].u.data = INVERSION_OFF; break;
1832                                 case eDVBFrontendParametersTerrestrial::Inversion_On: p[cmdseq.num].u.data = INVERSION_ON; break;
1833                                 default:
1834                                 case eDVBFrontendParametersTerrestrial::Inversion_Unknown: p[cmdseq.num].u.data = INVERSION_AUTO; break;
1835                         }
1836                         cmdseq.num++;
1837
1838                         p[cmdseq.num].cmd = DTV_CODE_RATE_LP;
1839                         switch (parm.code_rate_LP)
1840                         {
1841                                 case eDVBFrontendParametersTerrestrial::FEC_1_2: p[cmdseq.num].u.data = FEC_1_2; break;
1842                                 case eDVBFrontendParametersTerrestrial::FEC_2_3: p[cmdseq.num].u.data = FEC_2_3; break;
1843                                 case eDVBFrontendParametersTerrestrial::FEC_3_4: p[cmdseq.num].u.data = FEC_3_4; break;
1844                                 case eDVBFrontendParametersTerrestrial::FEC_5_6: p[cmdseq.num].u.data = FEC_5_6; break;
1845                                 case eDVBFrontendParametersTerrestrial::FEC_6_7: p[cmdseq.num].u.data = FEC_6_7; break;
1846                                 case eDVBFrontendParametersTerrestrial::FEC_7_8: p[cmdseq.num].u.data = FEC_7_8; break;
1847                                 case eDVBFrontendParametersTerrestrial::FEC_8_9: p[cmdseq.num].u.data = FEC_8_9; break;
1848                                 default:
1849                                 case eDVBFrontendParametersTerrestrial::FEC_Auto: p[cmdseq.num].u.data = FEC_AUTO; break;
1850                         }
1851                         cmdseq.num++;
1852
1853                         p[cmdseq.num].cmd = DTV_CODE_RATE_HP;
1854                         switch (parm.code_rate_HP)
1855                         {
1856                                 case eDVBFrontendParametersTerrestrial::FEC_1_2: p[cmdseq.num].u.data = FEC_1_2; break;
1857                                 case eDVBFrontendParametersTerrestrial::FEC_2_3: p[cmdseq.num].u.data = FEC_2_3; break;
1858                                 case eDVBFrontendParametersTerrestrial::FEC_3_4: p[cmdseq.num].u.data = FEC_3_4; break;
1859                                 case eDVBFrontendParametersTerrestrial::FEC_5_6: p[cmdseq.num].u.data = FEC_5_6; break;
1860                                 case eDVBFrontendParametersTerrestrial::FEC_6_7: p[cmdseq.num].u.data = FEC_6_7; break;
1861                                 case eDVBFrontendParametersTerrestrial::FEC_7_8: p[cmdseq.num].u.data = FEC_7_8; break;
1862                                 case eDVBFrontendParametersTerrestrial::FEC_8_9: p[cmdseq.num].u.data = FEC_8_9; break;
1863                                 default:
1864                                 case eDVBFrontendParametersTerrestrial::FEC_Auto: p[cmdseq.num].u.data = FEC_AUTO; break;
1865                         }
1866                         cmdseq.num++;
1867
1868                         p[cmdseq.num].cmd = DTV_MODULATION;
1869                         switch (parm.modulation)
1870                         {
1871                                 case eDVBFrontendParametersTerrestrial::Modulation_QPSK: p[cmdseq.num].u.data = QPSK; break;
1872                                 case eDVBFrontendParametersTerrestrial::Modulation_QAM16: p[cmdseq.num].u.data = QAM_16; break;
1873                                 case eDVBFrontendParametersTerrestrial::Modulation_QAM64: p[cmdseq.num].u.data = QAM_64; break;
1874                                 case eDVBFrontendParametersTerrestrial::Modulation_QAM256: p[cmdseq.num].u.data = QAM_256; break;
1875                                 default:
1876                                 case eDVBFrontendParametersTerrestrial::Modulation_Auto: p[cmdseq.num].u.data = QAM_AUTO; break;
1877                         }
1878                         cmdseq.num++;
1879
1880                         p[cmdseq.num].cmd = DTV_TRANSMISSION_MODE;
1881                         switch (parm.transmission_mode)
1882                         {
1883                                 case eDVBFrontendParametersTerrestrial::TransmissionMode_2k: p[cmdseq.num].u.data = TRANSMISSION_MODE_2K; break;
1884                                 case eDVBFrontendParametersTerrestrial::TransmissionMode_4k: p[cmdseq.num].u.data = TRANSMISSION_MODE_4K; break;
1885                                 case eDVBFrontendParametersTerrestrial::TransmissionMode_8k: p[cmdseq.num].u.data = TRANSMISSION_MODE_8K; break;
1886 #if defined TRANSMISSION_MODE_1K
1887                                 case eDVBFrontendParametersTerrestrial::TransmissionMode_1k: p[cmdseq.num].u.data = TRANSMISSION_MODE_1K; break;
1888                                 case eDVBFrontendParametersTerrestrial::TransmissionMode_16k: p[cmdseq.num].u.data = TRANSMISSION_MODE_16K; break;
1889                                 case eDVBFrontendParametersTerrestrial::TransmissionMode_32k: p[cmdseq.num].u.data = TRANSMISSION_MODE_32K; break;
1890 #endif
1891                                 default:
1892                                 case eDVBFrontendParametersTerrestrial::TransmissionMode_Auto: p[cmdseq.num].u.data = TRANSMISSION_MODE_AUTO; break;
1893                         }
1894                         cmdseq.num++;
1895
1896                         p[cmdseq.num].cmd = DTV_GUARD_INTERVAL;
1897                         switch (parm.guard_interval)
1898                         {
1899                                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_32: p[cmdseq.num].u.data = GUARD_INTERVAL_1_32; break;
1900                                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_16: p[cmdseq.num].u.data = GUARD_INTERVAL_1_16; break;
1901                                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_8: p[cmdseq.num].u.data = GUARD_INTERVAL_1_8; break;
1902                                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_4: p[cmdseq.num].u.data = GUARD_INTERVAL_1_4; break;
1903 #if defined GUARD_INTERVAL_1_128
1904                                 case eDVBFrontendParametersTerrestrial::GuardInterval_1_128: p[cmdseq.num].u.data = GUARD_INTERVAL_1_128; break;
1905                                 case eDVBFrontendParametersTerrestrial::GuardInterval_19_128: p[cmdseq.num].u.data = GUARD_INTERVAL_19_128; break;
1906                                 case eDVBFrontendParametersTerrestrial::GuardInterval_19_256: p[cmdseq.num].u.data = GUARD_INTERVAL_19_256; break;
1907 #endif
1908                                 default:
1909                                 case eDVBFrontendParametersTerrestrial::GuardInterval_Auto: p[cmdseq.num].u.data = GUARD_INTERVAL_AUTO; break;
1910                         }
1911                         cmdseq.num++;
1912
1913                         p[cmdseq.num].cmd = DTV_HIERARCHY;
1914                         switch (parm.hierarchy)
1915                         {
1916                                 case eDVBFrontendParametersTerrestrial::Hierarchy_None: p[cmdseq.num].u.data = HIERARCHY_NONE; break;
1917                                 case eDVBFrontendParametersTerrestrial::Hierarchy_1: p[cmdseq.num].u.data = HIERARCHY_1; break;
1918                                 case eDVBFrontendParametersTerrestrial::Hierarchy_2: p[cmdseq.num].u.data = HIERARCHY_2; break;
1919                                 case eDVBFrontendParametersTerrestrial::Hierarchy_4: p[cmdseq.num].u.data = HIERARCHY_4; break;
1920                                 default:
1921                                 case eDVBFrontendParametersTerrestrial::Hierarchy_Auto: p[cmdseq.num].u.data = HIERARCHY_AUTO; break;
1922                         }
1923                         cmdseq.num++;
1924
1925                         p[cmdseq.num].cmd = DTV_BANDWIDTH_HZ, p[cmdseq.num].u.data = parm.bandwidth, cmdseq.num++;
1926                         if (system == SYS_DVBT2)
1927                         {
1928                                 if (m_dvbversion >= DVB_VERSION(5, 3))
1929                                 {
1930 #if defined DTV_STREAM_ID
1931                                         p[cmdseq.num].cmd = DTV_STREAM_ID, p[cmdseq.num].u.data = parm.plpid, cmdseq.num++;
1932 #elif defined DTV_DVBT2_PLP_ID
1933                                         p[cmdseq.num].cmd = DTV_DVBT2_PLP_ID, p[cmdseq.num].u.data = parm.plpid, cmdseq.num++;
1934 #endif
1935                                 }
1936                         }
1937                 }
1938                 else if (type == iDVBFrontend::feATSC)
1939                 {
1940                         eDVBFrontendParametersATSC parm;
1941                         oparm.getATSC(parm);
1942                         p[cmdseq.num].cmd = DTV_DELIVERY_SYSTEM;
1943                         switch (parm.system)
1944                         {
1945                                 default:
1946                                 case eDVBFrontendParametersATSC::System_ATSC: p[cmdseq.num].u.data = SYS_ATSC; break;
1947                                 case eDVBFrontendParametersATSC::System_DVB_C_ANNEX_B: p[cmdseq.num].u.data = SYS_DVBC_ANNEX_B; break;
1948                         }
1949                         cmdseq.num++;
1950
1951                         p[cmdseq.num].cmd = DTV_FREQUENCY, p[cmdseq.num].u.data = parm.frequency, cmdseq.num++;
1952
1953                         p[cmdseq.num].cmd = DTV_INVERSION;
1954                         switch (parm.inversion)
1955                         {
1956                                 case eDVBFrontendParametersATSC::Inversion_Off: p[cmdseq.num].u.data = INVERSION_OFF; break;
1957                                 case eDVBFrontendParametersATSC::Inversion_On: p[cmdseq.num].u.data = INVERSION_ON; break;
1958                                 default:
1959                                 case eDVBFrontendParametersATSC::Inversion_Unknown: p[cmdseq.num].u.data = INVERSION_AUTO; break;
1960                         }
1961                         cmdseq.num++;
1962
1963                         p[cmdseq.num].cmd = DTV_MODULATION;
1964                         switch (parm.modulation)
1965                         {
1966                                 default:
1967                                 case eDVBFrontendParametersATSC::Modulation_Auto: p[cmdseq.num].u.data = QAM_AUTO; break;
1968                                 case eDVBFrontendParametersATSC::Modulation_QAM16: p[cmdseq.num].u.data = QAM_16; break;
1969                                 case eDVBFrontendParametersATSC::Modulation_QAM32: p[cmdseq.num].u.data = QAM_32; break;
1970                                 case eDVBFrontendParametersATSC::Modulation_QAM64: p[cmdseq.num].u.data = QAM_64; break;
1971                                 case eDVBFrontendParametersATSC::Modulation_QAM128: p[cmdseq.num].u.data = QAM_128; break;
1972                                 case eDVBFrontendParametersATSC::Modulation_QAM256: p[cmdseq.num].u.data = QAM_256; break;
1973                                 case eDVBFrontendParametersATSC::Modulation_VSB_8: p[cmdseq.num].u.data = VSB_8; break;
1974                                 case eDVBFrontendParametersATSC::Modulation_VSB_16: p[cmdseq.num].u.data = VSB_16; break;
1975                         }
1976                         cmdseq.num++;
1977                 }
1978                 p[cmdseq.num].cmd = DTV_TUNE, cmdseq.num++;
1979                 if (ioctl(m_fd, FE_SET_PROPERTY, &cmdseq) == -1)
1980                 {
1981                         perror("FE_SET_PROPERTY failed");
1982                         return;
1983                 }
1984         }
1985 }
1986
1987 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
1988 {
1989         int res;
1990         satfrequency = feparm.frequency;
1991         if (!m_sec)
1992         {
1993                 eWarning("[eDVBFrontend] no SEC module active!");
1994                 return -ENOENT;
1995         }
1996         res = m_sec->prepare(*this, feparm, satfrequency, 1 << m_slotid, tunetimeout);
1997         if (!res)
1998         {
1999                 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",
2000                         feparm.system,
2001                         feparm.frequency,
2002                         feparm.polarisation,
2003                         feparm.symbol_rate,
2004                         feparm.inversion,
2005                         feparm.fec,
2006                         feparm.orbital_position,
2007                         feparm.system,
2008                         feparm.modulation,
2009                         feparm.pilot,
2010                         feparm.rolloff);
2011                 if ((unsigned int)satfrequency < fe_info.frequency_min || (unsigned int)satfrequency > fe_info.frequency_max)
2012                 {
2013                         eDebugNoSimulate("[eDVBFrontend] %d mhz out of tuner range.. dont tune", satfrequency / 1000);
2014                         return -EINVAL;
2015                 }
2016                 eDebugNoSimulate("[eDVBFrontend] tuning to %d mhz", satfrequency / 1000);
2017         }
2018         oparm.setDVBS(feparm, feparm.no_rotor_command_on_tune);
2019         return res;
2020 }
2021
2022 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
2023 {
2024         eDebugNoSimulate("[eDVBFrontend] tuning to %d khz, sr %d, fec %d, modulation %d, inversion %d",
2025                 feparm.frequency,
2026                 feparm.symbol_rate,
2027                 feparm.fec_inner,
2028                 feparm.modulation,
2029                 feparm.inversion);
2030         oparm.setDVBC(feparm);
2031         return 0;
2032 }
2033
2034 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
2035 {
2036         oparm.setDVBT(feparm);
2037         return 0;
2038 }
2039
2040 RESULT eDVBFrontend::prepare_atsc(const eDVBFrontendParametersATSC &feparm)
2041 {
2042         oparm.setATSC(feparm);
2043         return 0;
2044 }
2045
2046 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
2047 {
2048         unsigned int timeout = 5000;
2049         int type;
2050         eDebugNoSimulate("[eDVBFrontend] (%d)tune", m_dvbid);
2051
2052         m_timeout->stop();
2053
2054         int res=0;
2055
2056         if (where.getSystem(type) < 0)
2057         {
2058                 res = -EINVAL;
2059                 goto tune_error;
2060         }
2061
2062         if (!m_sn && !m_simulate)
2063         {
2064                 eDebug("[eDVBFrontend] no frontend device opened... do not try to tune !!!");
2065                 res = -ENODEV;
2066                 goto tune_error;
2067         }
2068
2069         if (!m_simulate)
2070                 m_sn->stop();
2071
2072         m_sec_sequence.clear();
2073
2074         where.calcLockTimeout(timeout);
2075
2076         switch (type)
2077         {
2078         case feSatellite:
2079         {
2080                 eDVBFrontendParametersSatellite feparm;
2081                 if (where.getDVBS(feparm))
2082                 {
2083                         eDebug("[eDVBFrontend] no dvbs data!");
2084                         res = -EINVAL;
2085                         goto tune_error;
2086                 }
2087                 if (m_rotor_mode != feparm.no_rotor_command_on_tune && !feparm.no_rotor_command_on_tune)
2088                 {
2089                         eDVBFrontend *sec_fe = this;
2090                         long tmp = m_data[LINKED_PREV_PTR];
2091                         while (tmp != -1)
2092                         {
2093                                 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)tmp;
2094                                 sec_fe = linked_fe->m_frontend;
2095                                 sec_fe->getData(LINKED_NEXT_PTR, tmp);
2096                         }
2097                         eDebug("[eDVBFrontend] (fe%d) reset diseqc after leave rotor mode!", m_dvbid);
2098                         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
2099                 }
2100                 m_rotor_mode = feparm.no_rotor_command_on_tune;
2101                 if (!m_simulate)
2102                         m_sec->setRotorMoving(m_slotid, false);
2103                 res=prepare_sat(feparm, timeout);
2104                 if (res)
2105                         goto tune_error;
2106
2107                 break;
2108         }
2109         case feCable:
2110         {
2111                 eDVBFrontendParametersCable feparm;
2112                 if (where.getDVBC(feparm))
2113                 {
2114                         res = -EINVAL;
2115                         goto tune_error;
2116                 }
2117                 res=prepare_cable(feparm);
2118                 if (res)
2119                         goto tune_error;
2120
2121                 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2122                 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2123                 break;
2124         }
2125         case feTerrestrial:
2126         {
2127                 eDVBFrontendParametersTerrestrial feparm;
2128                 if (where.getDVBT(feparm))
2129                 {
2130                         eDebug("[eDVBFrontend] no -T data");
2131                         res = -EINVAL;
2132                         goto tune_error;
2133                 }
2134                 res=prepare_terrestrial(feparm);
2135                 if (res)
2136                         goto tune_error;
2137
2138                 char configStr[255];
2139                 snprintf(configStr, 255, "config.Nims.%d.terrestrial_5V", m_slotid);
2140                 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2141                 if (eConfigManager::getConfigBoolValue(configStr))
2142                         m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
2143                 else
2144                         m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltageOff) );
2145                 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2146                 break;
2147         }
2148         case feATSC:
2149         {
2150                 eDVBFrontendParametersATSC feparm;
2151                 if (where.getATSC(feparm))
2152                 {
2153                         res = -EINVAL;
2154                         goto tune_error;
2155                 }
2156                 res=prepare_atsc(feparm);
2157                 if (res)
2158                         goto tune_error;
2159
2160                 m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, timeout) );
2161                 m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
2162                 break;
2163         }
2164         default:
2165                 res = -EINVAL;
2166                 goto tune_error;
2167         }
2168
2169         m_sec_sequence.current() = m_sec_sequence.begin();
2170
2171         if (!m_simulate)
2172         {
2173                 m_tuneTimer->start(0,true);
2174                 m_tuning = 1;
2175                 if (m_state != stateTuning)
2176                 {
2177                         m_state = stateTuning;
2178                         m_stateChanged(this);
2179                 }
2180         }
2181         else
2182                 tuneLoop();
2183
2184         return res;
2185
2186 tune_error:
2187         m_tuneTimer->stop();
2188         return res;
2189 }
2190
2191 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
2192 {
2193         connection = new eConnection(this, m_stateChanged.connect(stateChange));
2194         return 0;
2195 }
2196
2197 RESULT eDVBFrontend::setVoltage(int voltage)
2198 {
2199         bool increased=false;
2200         fe_sec_voltage_t vlt;
2201         m_data[CUR_VOLTAGE]=voltage;
2202         switch (voltage)
2203         {
2204                 case voltageOff:
2205                         m_data[CSW]=m_data[UCSW]=m_data[TONEBURST]=-1; // reset diseqc
2206                         vlt = SEC_VOLTAGE_OFF;
2207                         break;
2208                 case voltage13_5:
2209                         increased = true;
2210                 case voltage13:
2211                         vlt = SEC_VOLTAGE_13;
2212                         break;
2213                 case voltage18_5:
2214                         increased = true;
2215                 case voltage18:
2216                         vlt = SEC_VOLTAGE_18;
2217                         break;
2218                 default:
2219                         return -ENODEV;
2220         }
2221         if (m_simulate)
2222                 return 0;
2223         ::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased);
2224         return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
2225 }
2226
2227 RESULT eDVBFrontend::getState(int &state)
2228 {
2229         state = m_state;
2230         return 0;
2231 }
2232
2233 RESULT eDVBFrontend::setTone(int t)
2234 {
2235         fe_sec_tone_mode_t tone;
2236         if (m_simulate)
2237                 return 0;
2238         m_data[CUR_TONE]=t;
2239         switch (t)
2240         {
2241                 case toneOn:
2242                         tone = SEC_TONE_ON;
2243                         break;
2244                 case toneOff:
2245                         tone = SEC_TONE_OFF;
2246                         break;
2247                 default:
2248                         return -ENODEV;
2249         }
2250         return ::ioctl(m_fd, FE_SET_TONE, tone);
2251 }
2252
2253 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
2254 {
2255         struct dvb_diseqc_master_cmd cmd;
2256         if (m_simulate)
2257                 return 0;
2258         memcpy(cmd.msg, diseqc.data, diseqc.len);
2259         cmd.msg_len = diseqc.len;
2260         if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
2261                 return -EINVAL;
2262         return 0;
2263 }
2264
2265 RESULT eDVBFrontend::sendToneburst(int burst)
2266 {
2267         fe_sec_mini_cmd_t cmd;
2268         if (m_simulate)
2269                 return 0;
2270         if (burst == eDVBSatelliteDiseqcParameters::B)
2271                 cmd = SEC_MINI_B;
2272         else
2273                 cmd = SEC_MINI_A;
2274
2275         if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
2276                 return -EINVAL;
2277         return 0;
2278 }
2279
2280 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
2281 {
2282         m_sec = sec;
2283         return 0;
2284 }
2285
2286 RESULT eDVBFrontend::setSecSequence(eSecCommandList &list)
2287 {
2288         if (m_data[SATCR] != -1 && m_sec_sequence.current() != m_sec_sequence.end())
2289                 m_sec_sequence.push_back(list);
2290         else
2291                 m_sec_sequence = list;
2292         return 0;
2293 }
2294
2295 RESULT eDVBFrontend::getData(int num, long &data)
2296 {
2297         if ( num < NUM_DATA_ENTRIES )
2298         {
2299                 data = m_data[num];
2300                 return 0;
2301         }
2302         return -EINVAL;
2303 }
2304
2305 RESULT eDVBFrontend::setData(int num, long val)
2306 {
2307         if ( num < NUM_DATA_ENTRIES )
2308         {
2309                 m_data[num] = val;
2310                 return 0;
2311         }
2312         return -EINVAL;
2313 }
2314
2315 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
2316 {
2317         int type;
2318         int score = 0;
2319         bool preferred = (eDVBFrontend::getPreferredFrontend() >= 0 && m_slotid == eDVBFrontend::getPreferredFrontend());
2320         if (feparm->getSystem(type) || !m_enabled)
2321         {
2322                 return 0;
2323         }
2324         if (type == eDVBFrontend::feSatellite)
2325         {
2326                 eDVBFrontendParametersSatellite parm;
2327                 bool can_handle_dvbs, can_handle_dvbs2;
2328                 if (feparm->getDVBS(parm) < 0)
2329                 {
2330                         return 0;
2331                 }
2332                 can_handle_dvbs = supportsDeliverySystem(SYS_DVBS, true);
2333                 can_handle_dvbs2 = supportsDeliverySystem(SYS_DVBS2, true);
2334                 if (parm.system == eDVBFrontendParametersSatellite::System_DVB_S2 && !can_handle_dvbs2)
2335                 {
2336                         return 0;
2337                 }
2338                 if (parm.system == eDVBFrontendParametersSatellite::System_DVB_S && !can_handle_dvbs)
2339                 {
2340                         return 0;
2341                 }
2342                 score = m_sec ? m_sec->canTune(parm, this, 1 << m_slotid) : 0;
2343                 if (score > 1 && parm.system == eDVBFrontendParametersSatellite::System_DVB_S && can_handle_dvbs2)
2344                 {
2345                         /* prefer to use an S tuner, try to keep S2 free for S2 transponders */
2346                         score--;
2347                 }
2348         }
2349         else if (type == eDVBFrontend::feCable)
2350         {
2351                 eDVBFrontendParametersCable parm;
2352                 bool can_handle_dvbc_annex_a, can_handle_dvbc_annex_c;
2353                 if (feparm->getDVBC(parm) < 0)
2354                 {
2355                         return 0;
2356                 }
2357 #if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 6
2358                 if (m_dvbversion >= DVB_VERSION(5, 6))
2359                 {
2360                         can_handle_dvbc_annex_a = supportsDeliverySystem(SYS_DVBC_ANNEX_A, true);
2361                         can_handle_dvbc_annex_c = supportsDeliverySystem(SYS_DVBC_ANNEX_C, true);
2362                 }
2363                 else
2364                 {
2365                         can_handle_dvbc_annex_a = can_handle_dvbc_annex_c = supportsDeliverySystem(SYS_DVBC_ANNEX_A, true); /* new value for SYS_DVB_ANNEX_AC */
2366                 }
2367 #else
2368                 can_handle_dvbc_annex_a = can_handle_dvbc_annex_c = supportsDeliverySystem(SYS_DVBC_ANNEX_AC, true);
2369 #endif
2370                 if (parm.system == eDVBFrontendParametersCable::System_DVB_C_ANNEX_A && !can_handle_dvbc_annex_a)
2371                 {
2372                         return 0;
2373                 }
2374                 if (parm.system == eDVBFrontendParametersCable::System_DVB_C_ANNEX_C && !can_handle_dvbc_annex_c)
2375                 {
2376                         return 0;
2377                 }
2378                 score = 2;
2379         }
2380         else if (type == eDVBFrontend::feTerrestrial)
2381         {
2382                 eDVBFrontendParametersTerrestrial parm;
2383                 bool can_handle_dvbt, can_handle_dvbt2;
2384                 can_handle_dvbt = supportsDeliverySystem(SYS_DVBT, true);
2385                 can_handle_dvbt2 = supportsDeliverySystem(SYS_DVBT2, true);
2386                 if (feparm->getDVBT(parm) < 0)
2387                 {
2388                         return 0;
2389                 }
2390                 if (parm.system == eDVBFrontendParametersTerrestrial::System_DVB_T && !can_handle_dvbt)
2391                 {
2392                         return 0;
2393                 }
2394                 if (parm.system == eDVBFrontendParametersTerrestrial::System_DVB_T2 && !can_handle_dvbt2)
2395                 {
2396                         return 0;
2397                 }
2398                 if (parm.system == eDVBFrontendParametersTerrestrial::System_DVB_T_T2 && !(can_handle_dvbt || can_handle_dvbt2))
2399                 {
2400                         return 0;
2401                 }
2402                 score = 2;
2403                 if (parm.system == eDVBFrontendParametersTerrestrial::System_DVB_T && can_handle_dvbt2)
2404                 {
2405                         /* prefer to use a T tuner, try to keep T2 free for T2 transponders */
2406                         score--;
2407                 }
2408         }
2409         else if (type == eDVBFrontend::feATSC)
2410         {
2411                 eDVBFrontendParametersATSC parm;
2412                 bool can_handle_atsc, can_handle_dvbc_annex_b;
2413                 can_handle_dvbc_annex_b = supportsDeliverySystem(SYS_DVBC_ANNEX_B, true);
2414                 can_handle_atsc = supportsDeliverySystem(SYS_ATSC, true);
2415                 if (feparm->getATSC(parm) < 0)
2416                 {
2417                         return 0;
2418                 }
2419                 if (parm.system == eDVBFrontendParametersATSC::System_DVB_C_ANNEX_B && !can_handle_dvbc_annex_b)
2420                 {
2421                         return 0;
2422                 }
2423                 if (parm.system == eDVBFrontendParametersATSC::System_ATSC && !can_handle_atsc)
2424                 {
2425                         return 0;
2426                 }
2427                 score = 2;
2428         }
2429
2430         if (score && preferred)
2431         {
2432                 /* make 'sure' we always prefer this frontend */
2433                 score += 100000; /* the offset has to be so ridiculously high because of the high scores which are used for DVB-S(2) */
2434         }
2435         return score;
2436 }
2437
2438 bool eDVBFrontend::supportsDeliverySystem(const fe_delivery_system_t &sys, bool obeywhitelist)
2439 {
2440         std::map<fe_delivery_system_t, bool>::iterator it = m_delsys.find(sys);
2441         if (it != m_delsys.end() && it->second)
2442         {
2443                 if (obeywhitelist && !m_delsys_whitelist.empty())
2444                 {
2445                         it = m_delsys_whitelist.find(sys);
2446                         if (it == m_delsys_whitelist.end() || !it->second) return false;
2447                 }
2448                 return true;
2449         }
2450         return false;
2451 }
2452
2453 void eDVBFrontend::setDeliverySystemWhitelist(const std::vector<fe_delivery_system_t> &whitelist)
2454 {
2455         m_delsys_whitelist.clear();
2456         for (unsigned int i = 0; i < whitelist.size(); i++)
2457         {
2458                 m_delsys_whitelist[whitelist[i]] = true;
2459         }
2460         if (m_simulate_fe)
2461         {
2462                 m_simulate_fe->setDeliverySystemWhitelist(whitelist);
2463         }
2464 }
2465
2466 bool eDVBFrontend::setSlotInfo(int id, const char *descr, bool enabled, bool isDVBS2, int frontendid)
2467 {
2468         if (frontendid < 0 || frontendid != m_dvbid)
2469         {
2470                 return false;
2471         }
2472         m_slotid = id;
2473         m_enabled = enabled;
2474         strncpy(m_description, descr, sizeof(m_description));
2475
2476         // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
2477         m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
2478                 !!strstr(m_description, "Alps BSBE2") ||
2479                 !!strstr(m_description, "Alps -S") ||
2480                 !!strstr(m_description, "BCM4501");
2481         if (isDVBS2)
2482         {
2483                 /* HACK for legacy dvb api without DELSYS support */
2484                 m_delsys[SYS_DVBS2] = true;
2485         }
2486         eDebugNoSimulate("[eDVBFrontend] setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s",
2487                 m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled ? "Yes" : "No", isDVBS2 ? "Yes" : "No" );
2488         return true;
2489 }