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