make eDVBSatelliteEquipmentControl useable from python
[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(eDVBFrontendParametersSatellite &p)
135 {
136         sat = p;
137         m_type = iDVBFrontend::feSatellite;
138         return 0;
139 }
140
141 RESULT eDVBFrontendParameters::setDVBC(eDVBFrontendParametersCable &p)
142 {
143         cable = p;
144         m_type = iDVBFrontend::feCable;
145         return 0;
146 }
147
148 RESULT eDVBFrontendParameters::setDVBT(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_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*9);
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         memset(m_data, 0xFFFF, sizeof(m_data));
292
293         return;
294 }
295
296 eDVBFrontend::~eDVBFrontend()
297 {
298         if (m_fd >= 0)
299                 ::close(m_fd);
300         if (m_sn)
301                 delete m_sn;
302         if (m_timeout)
303                 delete m_timeout;
304 }
305
306 void eDVBFrontend::feEvent(int w)
307 {
308         while (1)
309         {
310 #if HAVE_DVB_API_VERSION < 3
311                 FrontendEvent event;
312 #else
313                 dvb_frontend_event event;
314 #endif
315                 int res;
316                 int state;
317                 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
318                 
319                 if (res && (errno == EAGAIN))
320                         break;
321
322                 if (res)
323                 {
324                         eWarning("FE_GET_EVENT failed! %m");
325                         return;
326                 }
327                 
328                 if (w < 0)
329                         continue;
330
331 #if HAVE_DVB_API_VERSION < 3
332                 if (event.type == FE_COMPLETION_EV)
333 #else
334                 eDebug("fe event: status %x, inversion %s", event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off");
335                 if (event.status & FE_HAS_LOCK)
336 #endif
337                 {
338                         state = stateLock;
339                 } else
340                 {
341                         if (m_tuning)
342                                 state = stateTuning;
343                         else
344                                 state = stateFailed;
345                 }
346                 if (m_state != state)
347                 {
348                         m_state = state;
349                         m_stateChanged(this);
350                 }
351         }
352 }
353
354 void eDVBFrontend::timeout()
355 {
356         int state;
357         if (m_state == stateTuning)
358         {
359                 state = stateFailed;
360                 eDebug("DVBFrontend: timeout");
361                 if (m_state != state)
362                 {
363                         m_state = state;
364                         m_stateChanged(this);
365                 }
366         } else
367                 m_tuning = 0;
368 }
369
370 #ifndef FP_IOCTL_GET_ID
371 #define FP_IOCTL_GET_ID 0
372 #endif
373 int eDVBFrontend::readInputpower()
374 {
375         int power=0;
376 //      if ( eSystemInfo::getInstance()->canMeasureLNBCurrent() )
377         {
378 //              switch ( eSystemInfo::getInstance()->getHwType() )
379                 {
380 //                      case eSystemInfo::DM7000:
381 //                      case eSystemInfo::DM7020:
382                         {
383                                 // open front prozessor
384                                 int fp=::open("/dev/dbox/fp0", O_RDWR);
385                                 if (fp < 0)
386                                 {
387                                         eDebug("couldn't open fp");
388                                         return -1;
389                                 }
390                                 static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
391                                 if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
392                                 {
393                                         eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
394                                         return -1;
395                                 }
396                                 ::close(fp);
397 //                              break;
398                         }
399 //                      default:
400 //                              eDebug("Inputpower read for platform %d not yet implemented", eSystemInfo::getInstance()->getHwType());
401                 }
402         }
403         return power;
404 }
405
406 bool eDVBFrontend::setSecSequencePos(int steps)
407 {
408         eDebug("set sequence pos %d", steps);
409         if (!steps)
410                 return false;
411         while( steps > 0 )
412         {
413                 if (m_sec_sequence.current() != m_sec_sequence.end())
414                         ++m_sec_sequence.current();
415                 --steps;
416         }
417         while( steps < 0 )
418         {
419                 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
420                         --m_sec_sequence.current();
421                 ++steps;
422         }
423         return true;
424 }
425
426 void eDVBFrontend::tuneLoop()  // called by m_tuneTimer
427 {
428         int delay=0;
429         if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
430         {
431                 switch (m_sec_sequence.current()->cmd)
432                 {
433                         case eSecCommand::SLEEP:
434                                 delay = m_sec_sequence.current()++->msec;
435                                 eDebug("[SEC] sleep %dms", delay);
436                                 break;
437                         case eSecCommand::GOTO:
438                                 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
439                                         ++m_sec_sequence.current();
440                                 break;
441                         case eSecCommand::SET_VOLTAGE:
442                                 int voltage = m_sec_sequence.current()++->voltage;
443                                 eDebug("[SEC] setVoltage %d", voltage);
444                                 setVoltage(voltage);
445                                 break;
446                         case eSecCommand::SET_TONE:
447                                 eDebug("[SEC] setTone %d", m_sec_sequence.current()->tone);
448                                 setTone(m_sec_sequence.current()++->tone);
449                                 break;
450                         case eSecCommand::SEND_DISEQC:
451                                 sendDiseqc(m_sec_sequence.current()->diseqc);
452                                 eDebugNoNewLine("[SEC] sendDiseqc: ");
453                                 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
454                                     eDebugNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
455                                 eDebug("");
456                                 ++m_sec_sequence.current();
457                                 break;
458                         case eSecCommand::SEND_TONEBURST:
459                                 eDebug("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
460                                 sendToneburst(m_sec_sequence.current()++->toneburst);
461                                 break;
462                         case eSecCommand::SET_FRONTEND:
463                                 eDebug("[SEC] setFrontend");
464                                 setFrontend();
465                                 ++m_sec_sequence.current();
466                                 break;
467                         case eSecCommand::MEASURE_IDLE_INPUTPOWER:
468                         {
469                                 int idx = m_sec_sequence.current()++->val;
470                                 if ( idx == 0 || idx == 1 )
471                                 {
472                                         m_idleInputpower[idx] = readInputpower();
473                                         eDebug("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
474                                 }
475                                 else
476                                         eDebug("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
477                                 break;
478                         }
479                         case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
480                                 m_runningInputpower = readInputpower();
481                                 eDebug("[SEC] runningInputpower is %d", m_runningInputpower);
482                                 ++m_sec_sequence.current();
483                                 break;
484                         case eSecCommand::SET_TIMEOUT:
485                                 m_timeoutCount = m_sec_sequence.current()++->val;
486                                 eDebug("[SEC] set timeout %d", m_timeoutCount);
487                                 break;
488                         case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
489                                 m_data[5] = m_data[3];
490                                 m_data[6] = m_data[4];
491                                 eDebug("[SEC] update current rotorparams %d %04x %d", m_timeoutCount, m_data[5], m_data[6]);
492                                 ++m_sec_sequence.current();
493                                 break;
494                         case eSecCommand::IF_TIMEOUT_GOTO:
495                                 if (!m_timeoutCount)
496                                 {
497                                         eDebug("[SEC] rotor timout");
498                                         setSecSequencePos(m_sec_sequence.current()->steps);
499                                 }
500                                 else
501                                         ++m_sec_sequence.current();
502                                 break;
503                         case eSecCommand::SET_POWER_LIMITING_MODE:
504                         {
505                                 int fd=::open("/dev/i2c/0", O_RDWR);
506                                 unsigned char data[2];
507                                 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
508                                 if(::read(fd, data, 1) != 1)
509                                         eDebug("[SEC] error read lnbp (%m)");
510                                 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
511                                 {
512                                         data[0] |= 0x90;  // enable static current limiting
513                                         eDebug("[SEC] set static current limiting");
514                                 }
515                                 else
516                                 {
517                                         data[0] &= ~0x90;  // enable dynamic current limiting
518                                         eDebug("[SEC] set dynamic current limiting");
519                                 }
520                                 if(::write(fd, data, 1) != 1)
521                                         eDebug("[SEC] error write lnbp (%m)");
522                                 ::close(fd);
523                                 ++m_sec_sequence.current();
524                                 break;
525                         }
526                         case eSecCommand::IF_IDLE_INPUTPOWER_AVAIL_GOTO:
527                                 if (m_idleInputpower[0] && m_idleInputpower[1] && setSecSequencePos(m_sec_sequence.current()->steps))
528                                         break;
529                                 ++m_sec_sequence.current();
530                                 break;
531                         case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
532                         {
533                                 int idleInputpower = m_idleInputpower[m_curVoltage == iDVBFrontend::voltage13 ? 0 : 1];
534                                 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
535                                 const char *txt = cmd.direction ? "running" : "stopped";
536                                 eDebug("[SEC] waiting for rotor %s %d, idle %d, delta %d",
537                                         txt,
538                                         m_runningInputpower,
539                                         idleInputpower,
540                                         cmd.deltaA);
541                                 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
542                                         || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
543                                 {
544                                         ++cmd.okcount;
545                                         eDebug("[SEC] rotor %s step %d ok", txt, cmd.okcount);
546                                         if ( cmd.okcount > 6 )
547                                         {
548                                                 eDebug("[SEC] rotor is %s", txt);
549                                                 if (setSecSequencePos(cmd.steps))
550                                                         break;
551                                         }
552                                 }
553                                 else
554                                 {
555                                         eDebug("[SEC] rotor not %s... reset counter.. increase timeout", txt);
556                                         --m_timeoutCount;
557                                         cmd.okcount=0;
558                                 }
559                                 ++m_sec_sequence.current();
560                                 break;
561                         }
562                         case eSecCommand::IF_VOLTAGE_GOTO:
563                         {
564                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
565                                 if ( compare.voltage == m_curVoltage && setSecSequencePos(compare.steps) )
566                                         break;
567                                 ++m_sec_sequence.current();
568                                 break;
569                         }
570                         default:
571                                 ++m_sec_sequence.current();
572                                 eDebug("[SEC] unhandled sec command");
573                 }
574                 m_tuneTimer->start(delay,true);
575         }
576 }
577
578 void eDVBFrontend::setFrontend()
579 {
580         eDebug("setting frontend..\n");
581         if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
582         {
583                 perror("FE_SET_FRONTEND failed");
584                 return;
585         }
586
587         if (m_state != stateTuning)
588         {
589                 m_tuning = 1;
590                 m_state = stateTuning;
591                 m_stateChanged(this);
592         }
593         m_timeout->start(5000, 1); // 5 sec timeout. TODO: symbolrate dependent
594 }
595
596 RESULT eDVBFrontend::getFrontendType(int &t)
597 {
598         if (m_type == -1)
599                 return -ENODEV;
600         t = m_type;
601         return 0;
602 }
603
604 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
605 {
606         if (m_type == -1)
607                 return -ENODEV;
608
609         feEvent(-1);
610
611         m_sec_sequence.clear();
612
613         eDebug("eDVBFrontend::tune. type: %d", m_type);
614
615         switch (m_type)
616         {
617         case feSatellite:
618         {
619                 int res;
620                 eDVBFrontendParametersSatellite feparm;
621                 if (where.getDVBS(feparm))
622                 {
623                         eDebug("no dvbs data!");
624                         return -EINVAL;
625                 }
626                 if (!m_sec)
627                 {
628                         eWarning("no SEC module active!");
629                         return -ENOENT;
630                 }
631                 
632                 res = m_sec->prepare(*this, parm, feparm);
633                 if (res)
634                         return res;
635 #if HAVE_DVB_API_VERSION < 3
636                 eDebug("tuning to %d mhz", parm.Frequency/1000);
637 #else
638                 eDebug("tuning to %d mhz", parm.frequency/1000);
639 #endif
640                 break;
641         }
642         case feCable:
643         {
644                 eDVBFrontendParametersCable feparm;
645                 if (where.getDVBC(feparm))
646                         return -EINVAL;
647                 eFatal("cable tuning nyi");
648         }
649         case feTerrestrial:
650         {
651                 eDVBFrontendParametersTerrestrial feparm;
652                 if (where.getDVBT(feparm))
653                 {
654                         eDebug("no -T data");
655                         return -EINVAL;
656                 }
657 #if HAVE_DVB_API_VERSION < 3
658                 parm.Frequency = feparm.frequency;
659 #else
660                 parm.frequency = feparm.frequency;
661 #endif
662
663                 switch (feparm.bandwidth)
664                 {
665                 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
666 #if HAVE_DVB_API_VERSION < 3
667                         parm.u.ofdm.bandWidth =
668 #else
669                         parm.u.ofdm.bandwidth =
670 #endif
671                                 BANDWIDTH_8_MHZ;
672                         break;
673                 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
674 #if HAVE_DVB_API_VERSION < 3
675                         parm.u.ofdm.bandWidth =
676 #else
677                         parm.u.ofdm.bandwidth =
678 #endif
679                                 BANDWIDTH_7_MHZ;
680                         break;
681                 case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
682 #if HAVE_DVB_API_VERSION < 3
683                         parm.u.ofdm.bandWidth =
684 #else
685                         parm.u.ofdm.bandwidth =
686 #endif
687                                 BANDWIDTH_6_MHZ;
688                         break;
689                 case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
690 #if HAVE_DVB_API_VERSION < 3
691                         parm.u.ofdm.bandWidth =
692 #else
693                         parm.u.ofdm.bandwidth =
694 #endif
695                                 BANDWIDTH_AUTO;
696                         break;
697                 default:
698                         eWarning("invalid OFDM bandwith");
699                         return -EINVAL;
700                 }
701                 
702                 parm.u.ofdm.code_rate_HP = FEC_AUTO;
703                 parm.u.ofdm.code_rate_LP = FEC_AUTO;
704                 
705                 switch (feparm.modulation)
706                 {
707                 case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
708                         parm.u.ofdm.constellation = QPSK;
709                         break;
710                 case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
711                         parm.u.ofdm.constellation = QAM_16;
712                         break;
713                 case eDVBFrontendParametersTerrestrial::Modulation::Auto:
714                         parm.u.ofdm.constellation = QAM_AUTO;
715                         break;
716                 }
717                 
718                 switch (feparm.transmission_mode)
719                 {
720                 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
721 #if HAVE_DVB_API_VERSION < 3
722                         parm.u.ofdm.TransmissionMode =
723 #else
724                         parm.u.ofdm.transmission_mode =
725 #endif
726                                 TRANSMISSION_MODE_2K;
727                         break;
728                 case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
729 #if HAVE_DVB_API_VERSION < 3
730                         parm.u.ofdm.TransmissionMode =
731 #else
732                         parm.u.ofdm.transmission_mode =
733 #endif
734                                 TRANSMISSION_MODE_8K;
735                         break;
736                 case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
737 #if HAVE_DVB_API_VERSION < 3
738                         parm.u.ofdm.TransmissionMode =
739 #else
740                         parm.u.ofdm.transmission_mode =
741 #endif
742                                 TRANSMISSION_MODE_AUTO;
743                         break;
744                 }
745                 
746                 parm.u.ofdm.guard_interval = GUARD_INTERVAL_AUTO;
747                 parm.u.ofdm.hierarchy_information = HIERARCHY_AUTO;
748 #if HAVE_DVB_API_VERSION < 3
749                 parm.Inversion =
750 #else
751                 parm.inversion =
752 #endif
753                         INVERSION_AUTO;
754                 break;
755         }
756         }
757
758         m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
759         m_tuneTimer->start(0,true);
760         m_sec_sequence.current() = m_sec_sequence.begin();
761
762         return 0;
763 }
764
765 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
766 {
767         connection = new eConnection(this, m_stateChanged.connect(stateChange));
768         return 0;
769 }
770
771 RESULT eDVBFrontend::setVoltage(int voltage)
772 {
773 #if HAVE_DVB_API_VERSION < 3
774         secVoltage vlt;
775 #else
776         fe_sec_voltage_t vlt;
777 #endif
778
779         m_curVoltage=voltage;
780         switch (voltage)
781         {
782         case voltageOff:
783                 vlt = SEC_VOLTAGE_OFF;
784                 break;
785         case voltage13:
786                 vlt = SEC_VOLTAGE_13;
787                 break;
788         case voltage18:
789                 vlt = SEC_VOLTAGE_18;
790                 break;
791         default:
792                 return -ENODEV;
793         }
794 #if HAVE_DVB_API_VERSION < 3
795         return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
796 #else
797         return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
798 #endif
799 }
800
801 RESULT eDVBFrontend::getState(int &state)
802 {
803         state = m_state;
804         return 0;
805 }
806
807 RESULT eDVBFrontend::setTone(int t)
808 {
809 #if HAVE_DVB_API_VERSION < 3
810         secToneMode_t tone;
811 #else
812         fe_sec_tone_mode_t tone;
813 #endif
814
815         switch (t)
816         {
817         case toneOn:
818                 tone = SEC_TONE_ON;
819                 break;
820         case toneOff:
821                 tone = SEC_TONE_OFF;
822                 break;
823         default:
824                 return -ENODEV;
825         }
826 #if HAVE_DVB_API_VERSION < 3    
827         return ::ioctl(m_secfd, SEC_SET_TONE, tone);
828 #else   
829         return ::ioctl(m_fd, FE_SET_TONE, tone);
830 #endif
831 }
832
833 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
834         #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
835 #endif
836
837 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
838 {
839 #if HAVE_DVB_API_VERSION < 3
840         struct secCommand cmd;
841         cmd.type = SEC_CMDTYPE_DISEQC_RAW;
842         cmd.u.diseqc.cmdtype = diseqc.data[0];
843         cmd.u.diseqc.addr = diseqc.data[1];
844         cmd.u.diseqc.cmd = diseqc.data[2];
845         cmd.u.diseqc.numParams = diseqc.len-3;
846         memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
847         if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
848 #else
849         struct dvb_diseqc_master_cmd cmd;
850         memcpy(cmd.msg, diseqc.data, diseqc.len);
851         cmd.msg_len = diseqc.len;
852         if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
853 #endif
854                 return -EINVAL;
855         return 0;
856 }
857
858 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
859         #define SEC_DISEQC_SEND_BURST _IO('o', 96)
860 #endif
861 RESULT eDVBFrontend::sendToneburst(int burst)
862 {
863 #if HAVE_DVB_API_VERSION < 3
864         secMiniCmd cmd = SEC_MINI_NONE;
865         if ( burst == eDVBSatelliteDiseqcParameters::A )
866                 cmd = SEC_MINI_A;
867         else if ( burst == eDVBSatelliteDiseqcParameters::B )
868                 cmd = SEC_MINI_B;
869         if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
870                 return -EINVAL;
871 #endif
872         return 0;
873 }
874
875 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
876 {
877         m_sec = sec;
878         return 0;
879 }
880
881 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
882 {
883         m_sec_sequence = list;
884         return 0;
885 }
886
887 RESULT eDVBFrontend::getData(int num, int &data)
888 {
889         if ( num < 7 )
890         {
891                 data = m_data[num];
892                 return 0;
893         }
894         return -EINVAL;
895 }
896
897 RESULT eDVBFrontend::setData(int num, int val)
898 {
899         if ( num < 7 )
900         {
901                 m_data[num] = val;
902                 return 0;
903         }
904         return -EINVAL;
905 }
906