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