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