ref: delete active_components after execEnd on them
[enigma2.git] / lib / dvb / frontend.cpp
1 #include <config.h>
2 #include <lib/dvb/dvb.h>
3 #include <lib/base/eerror.h>
4 #include <errno.h>
5 #include <unistd.h>
6 #include <fcntl.h>
7 #include <sys/ioctl.h>
8
9 #ifndef I2C_SLAVE_FORCE
10 #define I2C_SLAVE_FORCE 0x0706
11 #endif
12
13 #if HAVE_DVB_API_VERSION < 3
14 #include <ost/frontend.h>
15 #include <ost/sec.h>
16 #define QAM_AUTO                                (Modulation)6
17 #define TRANSMISSION_MODE_AUTO  (TransmitMode)2
18 #define BANDWIDTH_AUTO                  (BandWidth)3
19 #define GUARD_INTERVAL_AUTO             (GuardInterval)4
20 #define HIERARCHY_AUTO                  (Hierarchy)4
21 #define constellation Constellation
22 #define guard_interval guardInterval
23 #define hierarchy_information HierarchyInformation
24 #define code_rate_HP HP_CodeRate
25 #define code_rate_LP LP_CodeRate
26 #else
27 #include <linux/dvb/frontend.h>
28 #endif
29
30 #include <dvbsi++/satellite_delivery_system_descriptor.h>
31 #include <dvbsi++/cable_delivery_system_descriptor.h>
32 #include <dvbsi++/terrestrial_delivery_system_descriptor.h>
33
34 void eDVBFrontendParametersSatellite::set(const SatelliteDeliverySystemDescriptor &descriptor)
35 {
36         frequency    = descriptor.getFrequency() * 10;
37         symbol_rate  = descriptor.getSymbolRate() * 100;
38         switch (descriptor.getPolarization())
39         {
40         case 0:
41                 polarisation = Polarisation::Horizontal;
42                 break;
43         case 1:
44                 polarisation = Polarisation::Vertical;
45                 break;
46         case 2:
47                 polarisation = Polarisation::CircularLeft;
48                 break;
49         case 3:
50                 polarisation = Polarisation::CircularRight;
51                 break;
52         }
53         switch (descriptor.getFecInner())
54         {
55         case 1:
56                 fec = FEC::f1_2;
57                 break;
58         case 2:
59                 fec = FEC::f2_3;
60                 break;
61         case 3:
62                 fec = FEC::f3_4;
63                 break;
64         case 4:
65                 fec = FEC::f5_6;
66                 break;
67         case 5:
68                 fec = FEC::f7_8;
69                 break;
70         case 0xF:
71                 fec = FEC::fNone;
72                 break;
73         default:
74                 fec = FEC::fAuto;
75                 break;
76         }
77         inversion = Inversion::Unknown;
78         orbital_position  = ((descriptor.getOrbitalPosition() >> 12) & 0xF) * 1000;
79         orbital_position += ((descriptor.getOrbitalPosition() >> 8) & 0xF) * 100;
80         orbital_position += ((descriptor.getOrbitalPosition() >> 4) & 0xF) * 10;
81         orbital_position += ((descriptor.getOrbitalPosition()) & 0xF);
82         if (orbital_position && (!descriptor.getWestEastFlag()))
83                 orbital_position = 3600 - orbital_position;
84 }
85
86 void eDVBFrontendParametersCable::set(const CableDeliverySystemDescriptor &descriptor)
87 {
88         eFatal("nyi");
89 }
90
91 void eDVBFrontendParametersTerrestrial::set(const TerrestrialDeliverySystemDescriptor  &)
92 {
93         eFatal("nyi");
94 }
95
96 eDVBFrontendParameters::eDVBFrontendParameters(): m_type(-1)
97 {
98 }
99
100 DEFINE_REF(eDVBFrontendParameters);
101
102 RESULT eDVBFrontendParameters::getSystem(int &t) const
103 {
104         if (m_type == -1)
105                 return -1;
106         t = m_type;
107         return 0;
108 }
109
110 RESULT eDVBFrontendParameters::getDVBS(eDVBFrontendParametersSatellite &p) const
111 {
112         if (m_type != iDVBFrontend::feSatellite)
113                 return -1;
114         p = sat;
115         return 0;
116 }
117
118 RESULT eDVBFrontendParameters::getDVBC(eDVBFrontendParametersCable &p) const
119 {
120         if (m_type != iDVBFrontend::feCable)
121                 return -1;
122         p = cable;
123         return 0;
124 }
125
126 RESULT eDVBFrontendParameters::getDVBT(eDVBFrontendParametersTerrestrial &p) const
127 {
128         if (m_type != iDVBFrontend::feTerrestrial)
129                 return -1;
130         p = terrestrial;
131         return 0;
132 }
133
134 RESULT eDVBFrontendParameters::setDVBS(const eDVBFrontendParametersSatellite &p)
135 {
136         sat = p;
137         m_type = iDVBFrontend::feSatellite;
138         return 0;
139 }
140
141 RESULT eDVBFrontendParameters::setDVBC(const eDVBFrontendParametersCable &p)
142 {
143         cable = p;
144         m_type = iDVBFrontend::feCable;
145         return 0;
146 }
147
148 RESULT eDVBFrontendParameters::setDVBT(const eDVBFrontendParametersTerrestrial &p)
149 {
150         terrestrial = p;
151         m_type = iDVBFrontend::feTerrestrial;
152         return 0;
153 }
154
155 RESULT eDVBFrontendParameters::calculateDifference(const iDVBFrontendParameters *parm, int &diff) const
156 {
157         if (!parm)
158                 return -1;
159         int type;
160         if (parm->getSystem(type))
161                 return -1;
162         if (type != m_type)
163         {
164                 diff = 1<<30; // big difference
165                 return 0;
166         }
167         
168         switch (type)
169         {
170         case iDVBFrontend::feSatellite:
171         {
172                 eDVBFrontendParametersSatellite osat;
173                 if (parm->getDVBS(osat))
174                         return -2;
175                 
176                 if (sat.orbital_position != osat.orbital_position)
177                         diff = 1<<29;
178                 else if (sat.polarisation != osat.polarisation)
179                         diff = 1<<28;
180                 else 
181                         diff = abs(sat.frequency - osat.frequency);
182                 return 0;
183         }
184         case iDVBFrontend::feCable:
185         case iDVBFrontend::feTerrestrial:
186         default:
187                 return -1;
188         }
189         return 0;
190 }
191
192 RESULT eDVBFrontendParameters::getHash(unsigned long &hash) const 
193 {
194         switch (m_type)
195         {
196         case iDVBFrontend::feSatellite:
197         {
198                 hash  = sat.frequency & 0xFFFF;
199                 hash |= sat.orbital_position << 16;
200                 return 0;
201         }
202         case iDVBFrontend::feCable:
203         case iDVBFrontend::feTerrestrial:
204         default:
205                 return -1;
206         }
207 }
208
209 DEFINE_REF(eDVBFrontend);
210
211 eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok): m_type(-1), m_fe(fe), m_curVoltage(-1)
212 {
213 #if HAVE_DVB_API_VERSION < 3
214         char sec_filename[128];
215 #endif
216         char filename[128];
217
218         int result;
219
220         m_sn = 0;
221         m_timeout = 0;
222
223 #if HAVE_DVB_API_VERSION < 3
224         sprintf(sec_filename, "/dev/dvb/card%d/sec%d", adap, fe);
225         m_secfd = ::open(sec_filename, O_RDWR);
226         if (m_secfd < 0)
227         {
228                 eWarning("failed! (%s) %m", sec_filename);
229                 ok = 0;
230                 return;
231         }
232         else
233                 eDebug("m_secfd is %d", m_secfd);
234
235         FrontendInfo fe_info;
236         sprintf(filename, "/dev/dvb/card%d/frontend%d", adap, fe);
237 #else
238         dvb_frontend_info fe_info;      
239         sprintf(filename, "/dev/dvb/adapter%d/frontend%d", adap, fe);
240 #endif
241         eDebug("opening frontend.");
242         m_fd = ::open(filename, O_RDWR|O_NONBLOCK);
243         if (m_fd < 0)
244         {
245                 eWarning("failed! (%s) %m", filename);
246                 ok = 0;
247                 return;
248         }
249
250         result = ::ioctl(m_fd, FE_GET_INFO, &fe_info);
251         
252         if (result < 0) {
253                 eWarning("ioctl FE_GET_INFO failed");
254                 ::close(m_fd);
255                 m_fd = -1;
256                 ok = 0;
257                 return;
258         }
259
260         switch (fe_info.type) 
261         {
262         case FE_QPSK:
263                 m_type = feSatellite;
264                 break;
265         case FE_QAM:
266                 m_type = feCable;
267                 break;
268         case FE_OFDM:
269                 m_type = feTerrestrial;
270                 break;
271         default:
272                 eWarning("unknown frontend type.");
273                 ::close(m_fd);
274                 m_fd = -1;
275                 ok = 0;
276                 return;
277         }
278         eDebug("detected %s frontend", "satellite\0cable\0    terrestrial"+fe_info.type*10);
279         ok = 1;
280
281         m_sn = new eSocketNotifier(eApp, m_fd, eSocketNotifier::Read);
282         CONNECT(m_sn->activated, eDVBFrontend::feEvent);
283         m_sn->start();
284
285         m_timeout = new eTimer(eApp);
286         CONNECT(m_timeout->timeout, eDVBFrontend::timeout);
287
288         m_tuneTimer = new eTimer(eApp);
289         CONNECT(m_tuneTimer->timeout, eDVBFrontend::tuneLoop);
290
291         int entries = sizeof(m_data) / sizeof(int);
292         for (int i=0; i<entries; ++i)
293                 m_data[i] = -1;
294
295         m_data[7] = !m_fe;
296
297         eDebug("m_data[7] = %d %d", m_data[7], m_fe);
298
299         return;
300 }
301
302 eDVBFrontend::~eDVBFrontend()
303 {
304         if (m_fd >= 0)
305                 ::close(m_fd);
306         if (m_sn)
307                 delete m_sn;
308         if (m_timeout)
309                 delete m_timeout;
310 }
311
312 void eDVBFrontend::feEvent(int w)
313 {
314         while (1)
315         {
316 #if HAVE_DVB_API_VERSION < 3
317                 FrontendEvent event;
318 #else
319                 dvb_frontend_event event;
320 #endif
321                 int res;
322                 int state;
323                 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
324                 
325                 if (res && (errno == EAGAIN))
326                         break;
327
328                 if (res)
329                 {
330                         eWarning("FE_GET_EVENT failed! %m");
331                         return;
332                 }
333                 
334                 if (w < 0)
335                         continue;
336
337 #if HAVE_DVB_API_VERSION < 3
338                 if (event.type == FE_COMPLETION_EV)
339 #else
340                 eDebug("(%d)fe event: status %x, inversion %s", m_fe, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off");
341                 if (event.status & FE_HAS_LOCK)
342 #endif
343                 {
344                         state = stateLock;
345                 } else
346                 {
347                         if (m_tuning)
348                                 state = stateTuning;
349                         else
350                         {
351                                 state = stateLostLock;
352
353                                 if (m_state != stateLostLock)
354                                         eDebug("FIXME: we lost lock, so we might have to retune.");
355                         }
356                 }
357                 if (m_state != state)
358                 {
359                         m_state = state;
360                         m_stateChanged(this);
361                 }
362         }
363 }
364
365 void eDVBFrontend::timeout()
366 {
367         int state;
368         if (m_state == stateTuning)
369         {
370                 state = stateFailed;
371                 eDebug("DVBFrontend: timeout");
372                 if (m_state != state)
373                 {
374                         m_state = state;
375                         m_stateChanged(this);
376                 }
377                 m_tuning = 0;
378         } else
379                 m_tuning = 0;
380 }
381
382 #ifndef FP_IOCTL_GET_ID
383 #define FP_IOCTL_GET_ID 0
384 #endif
385 int eDVBFrontend::readInputpower()
386 {
387         int power=0;
388 //      if ( eSystemInfo::getInstance()->canMeasureLNBCurrent() )
389         {
390 //              switch ( eSystemInfo::getInstance()->getHwType() )
391                 {
392 //                      case eSystemInfo::DM7000:
393 //                      case eSystemInfo::DM7020:
394                         {
395                                 // open front prozessor
396                                 int fp=::open("/dev/dbox/fp0", O_RDWR);
397                                 if (fp < 0)
398                                 {
399                                         eDebug("couldn't open fp");
400                                         return -1;
401                                 }
402                                 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
403                                 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
404                                 {
405                                         eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
406                                         return -1;
407                                 }
408                                 ::close(fp);
409 //                              break;
410                         }
411 //                      default:
412 //                              eDebug("Inputpower read for platform %d not yet implemented", eSystemInfo::getInstance()->getHwType());
413                 }
414         }
415         return power;
416 }
417
418 bool eDVBFrontend::setSecSequencePos(int steps)
419 {
420         eDebug("set sequence pos %d", steps);
421         if (!steps)
422                 return false;
423         while( steps > 0 )
424         {
425                 if (m_sec_sequence.current() != m_sec_sequence.end())
426                         ++m_sec_sequence.current();
427                 --steps;
428         }
429         while( steps < 0 )
430         {
431                 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
432                         --m_sec_sequence.current();
433                 ++steps;
434         }
435         return true;
436 }
437
438 void eDVBFrontend::tuneLoop()  // called by m_tuneTimer
439 {
440         int delay=0;
441         if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
442         {
443                 switch (m_sec_sequence.current()->cmd)
444                 {
445                         case eSecCommand::SLEEP:
446                                 delay = m_sec_sequence.current()++->msec;
447                                 eDebug("[SEC] sleep %dms", delay);
448                                 break;
449                         case eSecCommand::GOTO:
450                                 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
451                                         ++m_sec_sequence.current();
452                                 break;
453                         case eSecCommand::SET_VOLTAGE:
454                                 int voltage = m_sec_sequence.current()++->voltage;
455                                 eDebug("[SEC] setVoltage %d", voltage);
456                                 setVoltage(voltage);
457                                 break;
458                         case eSecCommand::SET_TONE:
459                                 eDebug("[SEC] setTone %d", m_sec_sequence.current()->tone);
460                                 setTone(m_sec_sequence.current()++->tone);
461                                 break;
462                         case eSecCommand::SEND_DISEQC:
463                                 sendDiseqc(m_sec_sequence.current()->diseqc);
464                                 eDebugNoNewLine("[SEC] sendDiseqc: ");
465                                 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
466                                     eDebugNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
467                                 eDebug("");
468                                 ++m_sec_sequence.current();
469                                 break;
470                         case eSecCommand::SEND_TONEBURST:
471                                 eDebug("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
472                                 sendToneburst(m_sec_sequence.current()++->toneburst);
473                                 break;
474                         case eSecCommand::SET_FRONTEND:
475                                 eDebug("[SEC] setFrontend");
476                                 setFrontend();
477                                 ++m_sec_sequence.current();
478                                 break;
479                         case eSecCommand::MEASURE_IDLE_INPUTPOWER:
480                         {
481                                 int idx = m_sec_sequence.current()++->val;
482                                 if ( idx == 0 || idx == 1 )
483                                 {
484                                         m_idleInputpower[idx] = readInputpower();
485                                         eDebug("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
486                                 }
487                                 else
488                                         eDebug("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
489                                 break;
490                         }
491                         case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
492                                 m_runningInputpower = readInputpower();
493                                 eDebug("[SEC] runningInputpower is %d", m_runningInputpower);
494                                 ++m_sec_sequence.current();
495                                 break;
496                         case eSecCommand::SET_TIMEOUT:
497                                 m_timeoutCount = m_sec_sequence.current()++->val;
498                                 eDebug("[SEC] set timeout %d", m_timeoutCount);
499                                 break;
500                         case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
501                                 m_data[5] = m_data[3];
502                                 m_data[6] = m_data[4];
503                                 eDebug("[SEC] update current rotorparams %d %04x %d", m_timeoutCount, m_data[5], m_data[6]);
504                                 ++m_sec_sequence.current();
505                                 break;
506                         case eSecCommand::IF_TIMEOUT_GOTO:
507                                 if (!m_timeoutCount)
508                                 {
509                                         eDebug("[SEC] rotor timout");
510                                         m_sec->setRotorMoving(false);
511                                         setSecSequencePos(m_sec_sequence.current()->steps);
512                                 }
513                                 else
514                                         ++m_sec_sequence.current();
515                                 break;
516                         case eSecCommand::SET_POWER_LIMITING_MODE:
517                         {
518                                 int fd=::open("/dev/i2c/0", O_RDWR);
519                                 unsigned char data[2];
520                                 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
521                                 if(::read(fd, data, 1) != 1)
522                                         eDebug("[SEC] error read lnbp (%m)");
523                                 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
524                                 {
525                                         data[0] |= 0x90;  // enable static current limiting
526                                         eDebug("[SEC] set static current limiting");
527                                 }
528                                 else
529                                 {
530                                         data[0] &= ~0x90;  // enable dynamic current limiting
531                                         eDebug("[SEC] set dynamic current limiting");
532                                 }
533                                 if(::write(fd, data, 1) != 1)
534                                         eDebug("[SEC] error write lnbp (%m)");
535                                 ::close(fd);
536                                 ++m_sec_sequence.current();
537                                 break;
538                         }
539                         case eSecCommand::IF_IDLE_INPUTPOWER_AVAIL_GOTO:
540                                 if (m_idleInputpower[0] && m_idleInputpower[1] && setSecSequencePos(m_sec_sequence.current()->steps))
541                                         break;
542                                 ++m_sec_sequence.current();
543                                 break;
544                         case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
545                         {
546                                 int idleInputpower = m_idleInputpower[m_curVoltage == iDVBFrontend::voltage13 ? 0 : 1];
547                                 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
548                                 const char *txt = cmd.direction ? "running" : "stopped";
549                                 eDebug("[SEC] waiting for rotor %s %d, idle %d, delta %d",
550                                         txt,
551                                         m_runningInputpower,
552                                         idleInputpower,
553                                         cmd.deltaA);
554                                 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
555                                         || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
556                                 {
557                                         ++cmd.okcount;
558                                         eDebug("[SEC] rotor %s step %d ok", txt, cmd.okcount);
559                                         if ( cmd.okcount > 6 )
560                                         {
561                                                 m_sec->setRotorMoving(cmd.direction);
562                                                 eDebug("[SEC] rotor is %s", txt);
563                                                 if (setSecSequencePos(cmd.steps))
564                                                         break;
565                                         }
566                                 }
567                                 else
568                                 {
569                                         eDebug("[SEC] rotor not %s... reset counter.. increase timeout", txt);
570                                         --m_timeoutCount;
571                                         cmd.okcount=0;
572                                 }
573                                 ++m_sec_sequence.current();
574                                 break;
575                         }
576                         case eSecCommand::IF_VOLTAGE_GOTO:
577                         {
578                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
579                                 if ( compare.voltage == m_curVoltage && setSecSequencePos(compare.steps) )
580                                         break;
581                                 ++m_sec_sequence.current();
582                                 break;
583                         }
584                         default:
585                                 ++m_sec_sequence.current();
586                                 eDebug("[SEC] unhandled sec command");
587                 }
588                 m_tuneTimer->start(delay,true);
589         }
590 }
591
592 void eDVBFrontend::setFrontend()
593 {
594         eDebug("setting frontend..\n");
595         if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
596         {
597                 perror("FE_SET_FRONTEND failed");
598                 return;
599         }
600
601         if (m_state != stateTuning)
602         {
603                 m_tuning = 1;
604                 m_state = stateTuning;
605                 m_stateChanged(this);
606         }
607         m_timeout->start(5000, 1); // 5 sec timeout. TODO: symbolrate dependent
608 }
609
610 RESULT eDVBFrontend::getFrontendType(int &t)
611 {
612         if (m_type == -1)
613                 return -ENODEV;
614         t = m_type;
615         return 0;
616 }
617
618 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
619 {
620         eDebug("(%d)tune", m_fe);
621
622         if (m_type == -1)
623                 return -ENODEV;
624
625         feEvent(-1);
626
627         m_sec_sequence.clear();
628
629         switch (m_type)
630         {
631         case feSatellite:
632         {
633                 int res;
634                 eDVBFrontendParametersSatellite feparm;
635                 if (where.getDVBS(feparm))
636                 {
637                         eDebug("no dvbs data!");
638                         return -EINVAL;
639                 }
640                 if (!m_sec)
641                 {
642                         eWarning("no SEC module active!");
643                         return -ENOENT;
644                 }
645                 
646                 res = m_sec->prepare(*this, parm, feparm, 1 << m_fe);
647                 if (res)
648                         return res;
649 #if HAVE_DVB_API_VERSION < 3
650                 eDebug("tuning to %d mhz", parm.Frequency/1000);
651 #else
652                 eDebug("tuning to %d mhz", parm.frequency/1000);
653 #endif
654                 break;
655         }
656         case feCable:
657         {
658 #if HAVE_DVB_API_VERSION >= 3
659                 eDVBFrontendParametersCable feparm;
660                 if (where.getDVBC(feparm))
661                         return -EINVAL;
662 #if HAVE_DVB_API_VERSION < 3
663                 parm.Frequency = feparm.frequency * 1000;
664                 parm.u.qam.SymbolRate = feparm.symbol_rate;
665 #else
666                 parm.frequency = feparm.frequency * 1000;
667                 parm.u.qam.symbol_rate = feparm.symbol_rate;
668 #endif
669                 fe_modulation_t mod;
670                 switch (feparm.modulation)
671                 {
672                 case eDVBFrontendParametersCable::Modulation::QAM16:
673                         mod = QAM_16;
674                         break;
675                 case eDVBFrontendParametersCable::Modulation::QAM32:
676                         mod = QAM_32;
677                         break;
678                 case eDVBFrontendParametersCable::Modulation::QAM64:
679                         mod = QAM_64;
680                         break;
681                 case eDVBFrontendParametersCable::Modulation::QAM128:
682                         mod = QAM_128;
683                         break;
684                 case eDVBFrontendParametersCable::Modulation::QAM256:
685                         mod = QAM_256;
686                         break;                  
687                 case eDVBFrontendParametersCable::Modulation::Auto:
688                         mod = QAM_AUTO;
689                         break;                  
690                 }
691 #if HAVE_DVB_API_VERSION < 3
692                 parm.u.qam.QAM = mod;
693 #else
694                 parm.u.qam.modulation = mod;
695 #endif
696                 switch (feparm.inversion)
697                 {               
698                 case eDVBFrontendParametersCable::Inversion::On:
699                         #if HAVE_DVB_API_VERSION < 3
700                         parm.Inversion =
701                         #else
702                         parm.inversion =
703                         #endif
704                                 INVERSION_ON;
705                         break;
706                 case eDVBFrontendParametersCable::Inversion::Off:
707                         #if HAVE_DVB_API_VERSION < 3
708                         parm.Inversion =
709                         #else
710                         parm.inversion =
711                         #endif
712                                 INVERSION_OFF;
713                         break;
714                 case eDVBFrontendParametersCable::Inversion::Unknown:
715                         #if HAVE_DVB_API_VERSION < 3
716                         parm.Inversion =
717                         #else
718                         parm.inversion =
719                         #endif
720                                 INVERSION_AUTO;
721                         break;
722                 }
723                 
724                 fe_code_rate_t fec_inner;
725                 switch (feparm.fec_inner)
726                 {               
727                 case eDVBFrontendParametersCable::FEC::fNone:
728                         fec_inner = FEC_NONE;
729                         break;
730                 case eDVBFrontendParametersCable::FEC::f1_2:
731                         fec_inner = FEC_1_2;
732                         break;
733                 case eDVBFrontendParametersCable::FEC::f2_3:
734                         fec_inner = FEC_2_3;
735                         break;
736                 case eDVBFrontendParametersCable::FEC::f3_4:
737                         fec_inner = FEC_3_4;
738                         break;
739                 case eDVBFrontendParametersCable::FEC::f4_5:
740                         fec_inner = FEC_4_5;
741                         break;
742                 case eDVBFrontendParametersCable::FEC::f5_6:
743                         fec_inner = FEC_5_6;
744                         break;
745                 case eDVBFrontendParametersCable::FEC::f6_7:
746                         fec_inner = FEC_6_7;
747                         break;
748                 case eDVBFrontendParametersCable::FEC::f7_8:
749                         fec_inner = FEC_7_8;
750                         break;
751                 case eDVBFrontendParametersCable::FEC::f8_9:
752                         fec_inner = FEC_8_9;
753                         break;
754                 case eDVBFrontendParametersCable::FEC::fAuto:
755                         fec_inner = FEC_AUTO;
756                         break;
757                 }
758 #if HAVE_DVB_API_VERSION < 3
759                 parm.u.qam.FEC_inner = fec_inner;
760 #else
761                 parm.u.qam.fec_inner = fec_inner;
762 #endif
763 #else
764                 eFatal("Old API not fully supported");
765 #endif // old api
766                 break;
767         }
768         case feTerrestrial:
769         {
770                 eDVBFrontendParametersTerrestrial feparm;
771                 if (where.getDVBT(feparm))
772                 {
773                         eDebug("no -T data");
774                         return -EINVAL;
775                 }
776 #if HAVE_DVB_API_VERSION < 3
777                 parm.Frequency = feparm.frequency;
778 #else
779                 parm.frequency = feparm.frequency;
780 #endif
781
782                 switch (feparm.bandwidth)
783                 {
784                 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
785 #if HAVE_DVB_API_VERSION < 3
786                         parm.u.ofdm.bandWidth =
787 #else
788                         parm.u.ofdm.bandwidth =
789 #endif
790                                 BANDWIDTH_8_MHZ;
791                         break;
792                 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
793 #if HAVE_DVB_API_VERSION < 3
794                         parm.u.ofdm.bandWidth =
795 #else
796                         parm.u.ofdm.bandwidth =
797 #endif
798                                 BANDWIDTH_7_MHZ;
799                         break;
800                 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
801 #if HAVE_DVB_API_VERSION < 3
802                         parm.u.ofdm.bandWidth =
803 #else
804                         parm.u.ofdm.bandwidth =
805 #endif
806                                 BANDWIDTH_6_MHZ;
807                         break;
808                 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
809 #if HAVE_DVB_API_VERSION < 3
810                         parm.u.ofdm.bandWidth =
811 #else
812                         parm.u.ofdm.bandwidth =
813 #endif
814                                 BANDWIDTH_AUTO;
815                         break;
816                 default:
817                         eWarning("invalid OFDM bandwith");
818                         return -EINVAL;
819                 }
820                 
821                 parm.u.ofdm.code_rate_HP = FEC_AUTO;
822                 parm.u.ofdm.code_rate_LP = FEC_AUTO;
823                 
824                 switch (feparm.modulation)
825                 {
826                 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
827                         parm.u.ofdm.constellation = QPSK;
828                         break;
829                 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
830                         parm.u.ofdm.constellation = QAM_16;
831                         break;
832                 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
833                         parm.u.ofdm.constellation = QAM_AUTO;
834                         break;
835                 }
836                 
837                 switch (feparm.transmission_mode)
838                 {
839                 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
840 #if HAVE_DVB_API_VERSION < 3
841                         parm.u.ofdm.TransmissionMode =
842 #else
843                         parm.u.ofdm.transmission_mode =
844 #endif
845                                 TRANSMISSION_MODE_2K;
846                         break;
847                 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
848 #if HAVE_DVB_API_VERSION < 3
849                         parm.u.ofdm.TransmissionMode =
850 #else
851                         parm.u.ofdm.transmission_mode =
852 #endif
853                                 TRANSMISSION_MODE_8K;
854                         break;
855                 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
856 #if HAVE_DVB_API_VERSION < 3
857                         parm.u.ofdm.TransmissionMode =
858 #else
859                         parm.u.ofdm.transmission_mode =
860 #endif
861                                 TRANSMISSION_MODE_AUTO;
862                         break;
863                 }
864                 
865                 parm.u.ofdm.guard_interval = GUARD_INTERVAL_AUTO;
866                 parm.u.ofdm.hierarchy_information = HIERARCHY_AUTO;
867 #if HAVE_DVB_API_VERSION < 3
868                 parm.Inversion =
869 #else
870                 parm.inversion =
871 #endif
872                         INVERSION_AUTO;
873                 break;
874         }
875         }
876
877         m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
878         m_tuneTimer->start(0,true);
879         m_sec_sequence.current() = m_sec_sequence.begin();
880
881         return 0;
882 }
883
884 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
885 {
886         connection = new eConnection(this, m_stateChanged.connect(stateChange));
887         return 0;
888 }
889
890 RESULT eDVBFrontend::setVoltage(int voltage)
891 {
892 #if HAVE_DVB_API_VERSION < 3
893         secVoltage vlt;
894 #else
895         fe_sec_voltage_t vlt;
896 #endif
897
898         m_curVoltage=voltage;
899         switch (voltage)
900         {
901         case voltageOff:
902                 vlt = SEC_VOLTAGE_OFF;
903                 break;
904         case voltage13:
905                 vlt = SEC_VOLTAGE_13;
906                 break;
907         case voltage18:
908                 vlt = SEC_VOLTAGE_18;
909                 break;
910         default:
911                 return -ENODEV;
912         }
913 #if HAVE_DVB_API_VERSION < 3
914         return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
915 #else
916         return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
917 #endif
918 }
919
920 RESULT eDVBFrontend::getState(int &state)
921 {
922         state = m_state;
923         return 0;
924 }
925
926 RESULT eDVBFrontend::setTone(int t)
927 {
928 #if HAVE_DVB_API_VERSION < 3
929         secToneMode_t tone;
930 #else
931         fe_sec_tone_mode_t tone;
932 #endif
933
934         switch (t)
935         {
936         case toneOn:
937                 tone = SEC_TONE_ON;
938                 break;
939         case toneOff:
940                 tone = SEC_TONE_OFF;
941                 break;
942         default:
943                 return -ENODEV;
944         }
945 #if HAVE_DVB_API_VERSION < 3    
946         return ::ioctl(m_secfd, SEC_SET_TONE, tone);
947 #else   
948         return ::ioctl(m_fd, FE_SET_TONE, tone);
949 #endif
950 }
951
952 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
953         #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
954 #endif
955
956 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
957 {
958 #if HAVE_DVB_API_VERSION < 3
959         struct secCommand cmd;
960         cmd.type = SEC_CMDTYPE_DISEQC_RAW;
961         cmd.u.diseqc.cmdtype = diseqc.data[0];
962         cmd.u.diseqc.addr = diseqc.data[1];
963         cmd.u.diseqc.cmd = diseqc.data[2];
964         cmd.u.diseqc.numParams = diseqc.len-3;
965         memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
966         if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
967 #else
968         struct dvb_diseqc_master_cmd cmd;
969         memcpy(cmd.msg, diseqc.data, diseqc.len);
970         cmd.msg_len = diseqc.len;
971         if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
972 #endif
973                 return -EINVAL;
974         return 0;
975 }
976
977 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
978         #define SEC_DISEQC_SEND_BURST _IO('o', 96)
979 #endif
980 RESULT eDVBFrontend::sendToneburst(int burst)
981 {
982 #if HAVE_DVB_API_VERSION < 3
983         secMiniCmd cmd = SEC_MINI_NONE;
984         if ( burst == eDVBSatelliteDiseqcParameters::A )
985                 cmd = SEC_MINI_A;
986         else if ( burst == eDVBSatelliteDiseqcParameters::B )
987                 cmd = SEC_MINI_B;
988         if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
989                 return -EINVAL;
990 #endif
991         return 0;
992 }
993
994 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
995 {
996         m_sec = sec;
997         return 0;
998 }
999
1000 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
1001 {
1002         m_sec_sequence = list;
1003         return 0;
1004 }
1005
1006 RESULT eDVBFrontend::getData(int num, int &data)
1007 {
1008         if ( num < (int)(sizeof(m_data)/sizeof(int)) )
1009         {
1010                 data = m_data[num];
1011                 return 0;
1012         }
1013         return -EINVAL;
1014 }
1015
1016 RESULT eDVBFrontend::setData(int num, int val)
1017 {
1018         if ( num < (int)(sizeof(m_data)/sizeof(int)) )
1019         {
1020                 if ( num == 0 )
1021                         eDebug("(%d) set csw %02x", m_fe, val);
1022                 m_data[num] = val;
1023                 return 0;
1024         }
1025         return -EINVAL;
1026 }
1027
1028 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
1029 {
1030         int type;
1031         if (feparm->getSystem(type) || type != m_type)
1032                 return 0;
1033
1034         if (m_type == eDVBFrontend::feSatellite)
1035         {
1036                 ASSERT(m_sec);
1037                 eDVBFrontendParametersSatellite sat_parm;
1038                 ASSERT(!feparm->getDVBS(sat_parm));
1039                 return m_sec->canTune(sat_parm, this, 1 << m_fe);
1040         }
1041         return 1;
1042 }