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