don't shut down enigma 2 when deleting a timer which has an after event "shutdown...
[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_inversion parm.Inversion
22 #define parm_u_qpsk_symbol_rate parm.u.qpsk.SymbolRate
23 #define parm_u_qpsk_fec_inner parm.u.qpsk.FEC_inner
24 #define parm_u_qam_symbol_rate parm.u.qam.SymbolRate
25 #define parm_u_qam_fec_inner parm.u.qam.FEC_inner
26 #define parm_u_qam_modulation parm.u.qam.QAM
27 #define parm_u_ofdm_bandwidth parm.u.ofdm.bandWidth
28 #define parm_u_ofdm_code_rate_LP parm.u.ofdm.LP_CodeRate
29 #define parm_u_ofdm_code_rate_HP parm.u.ofdm.HP_CodeRate
30 #define parm_u_ofdm_constellation parm.u.ofdm.Constellation
31 #define parm_u_ofdm_transmission_mode parm.u.ofdm.TransmissionMode
32 #define parm_u_ofdm_guard_interval parm.u.ofdm.guardInterval
33 #define parm_u_ofdm_hierarchy_information parm.u.ofdm.HierarchyInformation
34 #else
35 #include <linux/dvb/frontend.h>
36 #define parm_frequency parm.frequency
37 #define parm_inversion parm.inversion
38 #define parm_u_qpsk_symbol_rate parm.u.qpsk.symbol_rate
39 #define parm_u_qpsk_fec_inner parm.u.qpsk.fec_inner
40 #define parm_u_qam_symbol_rate parm.u.qam.symbol_rate
41 #define parm_u_qam_fec_inner parm.u.qam.fec_inner
42 #define parm_u_qam_modulation parm.u.qam.modulation
43 #define parm_u_ofdm_bandwidth parm.u.ofdm.bandwidth
44 #define parm_u_ofdm_code_rate_LP parm.u.ofdm.code_rate_LP
45 #define parm_u_ofdm_code_rate_HP parm.u.ofdm.code_rate_HP
46 #define parm_u_ofdm_constellation parm.u.ofdm.constellation
47 #define parm_u_ofdm_transmission_mode parm.u.ofdm.transmission_mode
48 #define parm_u_ofdm_guard_interval parm.u.ofdm.guard_interval
49 #define parm_u_ofdm_hierarchy_information parm.u.ofdm.hierarchy_information
50 #ifdef FEC_9_10
51         #warning "FEC_9_10 already exist in dvb api ... it seems it is now ready for DVB-S2"
52 #else
53         #define FEC_9_10 (fe_code_rate_t)(FEC_AUTO+1)
54 #endif
55 #endif
56
57 #include <dvbsi++/satellite_delivery_system_descriptor.h>
58 #include <dvbsi++/cable_delivery_system_descriptor.h>
59 #include <dvbsi++/terrestrial_delivery_system_descriptor.h>
60
61 void eDVBDiseqcCommand::setCommandString(const char *str)
62 {
63         if (!str)
64                 return;
65         len=0;
66         int slen = strlen(str);
67         if (slen % 2)
68         {
69                 eDebug("invalid diseqc command string length (not 2 byte aligned)");
70                 return;
71         }
72         if (slen > MAX_DISEQC_LENGTH*2)
73         {
74                 eDebug("invalid diseqc command string length (string is to long)");
75                 return;
76         }
77         unsigned char val=0;
78         for (int i=0; i < slen; ++i)
79         {
80                 unsigned char c = str[i];
81                 switch(c)
82                 {
83                         case '0' ... '9': c-=48; break;
84                         case 'a' ... 'f': c-=87; break;
85                         case 'A' ... 'F': c-=55; break;
86                         default:
87                                 eDebug("invalid character in hex string..ignore complete diseqc command !");
88                                 return;
89                 }
90                 if ( i % 2 )
91                 {
92                         val |= c;
93                         data[i/2] = val;
94                 }
95                 else
96                         val = c << 4;
97         }
98         len = slen/2;
99 }
100
101 void eDVBFrontendParametersSatellite::set(const SatelliteDeliverySystemDescriptor &descriptor)
102 {
103         frequency    = descriptor.getFrequency() * 10;
104         symbol_rate  = descriptor.getSymbolRate() * 100;
105         polarisation = descriptor.getPolarization();
106         fec = descriptor.getFecInner();
107         if ( fec != FEC::fNone && fec > FEC::f9_10 )
108                 fec = FEC::fAuto;
109         inversion = Inversion::Unknown;
110         orbital_position  = ((descriptor.getOrbitalPosition() >> 12) & 0xF) * 1000;
111         orbital_position += ((descriptor.getOrbitalPosition() >> 8) & 0xF) * 100;
112         orbital_position += ((descriptor.getOrbitalPosition() >> 4) & 0xF) * 10;
113         orbital_position += ((descriptor.getOrbitalPosition()) & 0xF);
114         if (orbital_position && (!descriptor.getWestEastFlag()))
115                 orbital_position = 3600 - orbital_position;
116         system = descriptor.getModulationSystem();
117         modulation = descriptor.getModulation();
118         if (system == System::DVB_S && modulation == Modulation::M8PSK)
119         {
120                 eDebug("satellite_delivery_descriptor non valid modulation type.. force QPSK");
121                 modulation=QPSK;
122         }
123         roll_off = descriptor.getRollOff();
124         if (system == System::DVB_S2)
125         {
126                 eDebug("SAT DVB-S2 freq %d, %s, pos %d, sr %d, fec %d, modulation %d, roll_off %d",
127                         frequency,
128                         polarisation ? "hor" : "vert",
129                         orbital_position,
130                         symbol_rate, fec,
131                         modulation,
132                         roll_off);
133         }
134         else
135         {
136                 eDebug("SAT DVB-S freq %d, %s, pos %d, sr %d, fec %d",
137                         frequency,
138                         polarisation ? "hor" : "vert",
139                         orbital_position,
140                         symbol_rate, fec);
141         }
142 }
143
144 void eDVBFrontendParametersCable::set(const CableDeliverySystemDescriptor &descriptor)
145 {
146         frequency = descriptor.getFrequency() / 10;
147         symbol_rate = descriptor.getSymbolRate() * 100;
148         fec_inner = descriptor.getFecInner();
149         if ( fec_inner == 0xF )
150                 fec_inner = FEC::fNone;
151         modulation = descriptor.getModulation();
152         if ( modulation > 0x5 )
153                 modulation = Modulation::Auto;
154         inversion = Inversion::Unknown;
155         eDebug("Cable freq %d, mod %d, sr %d, fec %d",
156                 frequency,
157                 modulation, symbol_rate, fec_inner);
158 }
159
160 void eDVBFrontendParametersTerrestrial::set(const TerrestrialDeliverySystemDescriptor &descriptor)
161 {
162         frequency = descriptor.getCentreFrequency() * 10;
163         bandwidth = descriptor.getBandwidth();
164         if ( bandwidth > 2 ) // 5Mhz forced to auto
165                 bandwidth = Bandwidth::BwAuto;
166         code_rate_HP = descriptor.getCodeRateHpStream();
167         if (code_rate_HP > 4)
168                 code_rate_HP = FEC::fAuto;
169         code_rate_LP = descriptor.getCodeRateLpStream();
170         if (code_rate_LP > 4)
171                 code_rate_LP = FEC::fAuto;
172         transmission_mode = descriptor.getTransmissionMode();
173         if (transmission_mode > 1) // TM4k forced to auto
174                 transmission_mode = TransmissionMode::TMAuto;
175         guard_interval = descriptor.getGuardInterval();
176         if (guard_interval > 3)
177                 guard_interval = GuardInterval::GI_Auto;
178         hierarchy = descriptor.getHierarchyInformation()&3;
179         modulation = descriptor.getConstellation();
180         if (modulation > 2)
181                 modulation = Modulation::Auto;
182         inversion = Inversion::Unknown;
183         eDebug("Terr freq %d, bw %d, cr_hp %d, cr_lp %d, tm_mode %d, guard %d, hierarchy %d, const %d",
184                 frequency, bandwidth, code_rate_HP, code_rate_LP, transmission_mode,
185                 guard_interval, hierarchy, modulation);
186 }
187
188 eDVBFrontendParameters::eDVBFrontendParameters(): m_type(-1)
189 {
190 }
191
192 DEFINE_REF(eDVBFrontendParameters);
193
194 RESULT eDVBFrontendParameters::getSystem(int &t) const
195 {
196         if (m_type == -1)
197                 return -1;
198         t = m_type;
199         return 0;
200 }
201
202 RESULT eDVBFrontendParameters::getDVBS(eDVBFrontendParametersSatellite &p) const
203 {
204         if (m_type != iDVBFrontend::feSatellite)
205                 return -1;
206         p = sat;
207         return 0;
208 }
209
210 RESULT eDVBFrontendParameters::getDVBC(eDVBFrontendParametersCable &p) const
211 {
212         if (m_type != iDVBFrontend::feCable)
213                 return -1;
214         p = cable;
215         return 0;
216 }
217
218 RESULT eDVBFrontendParameters::getDVBT(eDVBFrontendParametersTerrestrial &p) const
219 {
220         if (m_type != iDVBFrontend::feTerrestrial)
221                 return -1;
222         p = terrestrial;
223         return 0;
224 }
225
226 RESULT eDVBFrontendParameters::setDVBS(const eDVBFrontendParametersSatellite &p, bool no_rotor_command_on_tune)
227 {
228         sat = p;
229         sat.no_rotor_command_on_tune = no_rotor_command_on_tune;
230         m_type = iDVBFrontend::feSatellite;
231         return 0;
232 }
233
234 RESULT eDVBFrontendParameters::setDVBC(const eDVBFrontendParametersCable &p)
235 {
236         cable = p;
237         m_type = iDVBFrontend::feCable;
238         return 0;
239 }
240
241 RESULT eDVBFrontendParameters::setDVBT(const eDVBFrontendParametersTerrestrial &p)
242 {
243         terrestrial = p;
244         m_type = iDVBFrontend::feTerrestrial;
245         return 0;
246 }
247
248 RESULT eDVBFrontendParameters::calculateDifference(const iDVBFrontendParameters *parm, int &diff) const
249 {
250         if (!parm)
251                 return -1;
252         int type;
253         if (parm->getSystem(type))
254                 return -1;
255         if (type != m_type)
256         {
257                 diff = 1<<30; // big difference
258                 return 0;
259         }
260         
261         switch (type)
262         {
263         case iDVBFrontend::feSatellite:
264         {
265                 eDVBFrontendParametersSatellite osat;
266                 if (parm->getDVBS(osat))
267                         return -2;
268                 
269                 if (sat.orbital_position != osat.orbital_position)
270                         diff = 1<<29;
271                 else if (sat.polarisation != osat.polarisation)
272                         diff = 1<<28;
273                 else
274                 {
275                         diff = abs(sat.frequency - osat.frequency);
276                         diff += abs(sat.symbol_rate - osat.symbol_rate);
277                 }
278                 return 0;
279         }
280         case iDVBFrontend::feCable:
281                 eDVBFrontendParametersCable ocable;
282                 if (parm->getDVBC(ocable))
283                         return -2;
284                 
285                 if (cable.modulation != ocable.modulation && cable.modulation != eDVBFrontendParametersCable::Modulation::Auto && ocable.modulation != eDVBFrontendParametersCable::Modulation::Auto)
286                         diff = 1 << 29;
287                 else if (cable.inversion != ocable.inversion && cable.inversion != eDVBFrontendParametersCable::Inversion::Unknown && ocable.inversion != eDVBFrontendParametersCable::Inversion::Unknown)
288                         diff = 1 << 28;
289                 else
290                 {
291                         diff = abs(cable.frequency - ocable.frequency);
292                         diff += abs(cable.symbol_rate - ocable.symbol_rate);
293                 }
294                 
295                 return 0;
296         case iDVBFrontend::feTerrestrial:
297                 eDVBFrontendParametersTerrestrial oterrestrial;
298                 if (parm->getDVBT(oterrestrial))
299                         return -2;
300                 
301                 diff = abs(terrestrial.frequency - oterrestrial.frequency);
302
303                 return 0;
304         default:
305                 return -1;
306         }
307         return 0;
308 }
309
310 RESULT eDVBFrontendParameters::getHash(unsigned long &hash) const
311 {
312         switch (m_type)
313         {
314         case iDVBFrontend::feSatellite:
315         {
316                 hash = (sat.orbital_position << 16);
317                 hash |= ((sat.frequency/1000)&0xFFFF)|((sat.polarisation&1) << 15);
318                 return 0;
319         }
320         case iDVBFrontend::feCable:
321                 hash = 0xFFFF0000;
322                 return 0;
323         case iDVBFrontend::feTerrestrial:
324                 hash = 0xEEEE0000;
325                 return 0;
326         default:
327                 return -1;
328         }
329 }
330
331 DEFINE_REF(eDVBFrontend);
332
333 eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok)
334         :m_type(-1), m_fe(fe), m_fd(-1), m_sn(0), m_timeout(0), m_tuneTimer(0)
335 #if HAVE_DVB_API_VERSION < 3
336         ,m_secfd(-1)
337 #endif
338 {
339 #if HAVE_DVB_API_VERSION < 3
340         sprintf(m_filename, "/dev/dvb/card%d/frontend%d", adap, fe);
341         sprintf(m_sec_filename, "/dev/dvb/card%d/sec%d", adap, fe);
342 #else
343         sprintf(m_filename, "/dev/dvb/adapter%d/frontend%d", adap, fe);
344 #endif
345         m_timeout = new eTimer(eApp);
346         CONNECT(m_timeout->timeout, eDVBFrontend::timeout);
347
348         m_tuneTimer = new eTimer(eApp);
349         CONNECT(m_tuneTimer->timeout, eDVBFrontend::tuneLoop);
350
351         int entries = sizeof(m_data) / sizeof(int);
352         for (int i=0; i<entries; ++i)
353                 m_data[i] = -1;
354
355         m_idleInputpower[0]=m_idleInputpower[1]=0;
356
357         ok = !openFrontend();
358         closeFrontend();
359 }
360
361 int eDVBFrontend::openFrontend()
362 {
363         if (m_sn)
364                 return -1;  // already opened
365
366         m_state=0;
367         m_tuning=0;
368
369 #if HAVE_DVB_API_VERSION < 3
370         if (m_secfd < 0)
371         {
372                 m_secfd = ::open(m_sec_filename, O_RDWR);
373                 if (m_secfd < 0)
374                 {
375                         eWarning("failed! (%s) %m", m_sec_filename);
376                         return -1;
377                 }
378         }
379         else
380                 eWarning("sec %d already opened", m_fe);
381         FrontendInfo fe_info;
382 #else
383         dvb_frontend_info fe_info;
384 #endif
385         eDebug("opening frontend %d", m_fe);
386         if (m_fd < 0)
387         {
388                 m_fd = ::open(m_filename, O_RDWR|O_NONBLOCK);
389                 if (m_fd < 0)
390                 {
391                         eWarning("failed! (%s) %m", m_filename);
392 #if HAVE_DVB_API_VERSION < 3
393                         ::close(m_secfd);
394                         m_secfd=-1;
395 #endif
396                         return -1;
397                 }
398         }
399         else
400                 eWarning("frontend %d already opened", m_fe);
401         if (m_type == -1)
402         {
403                 if (::ioctl(m_fd, FE_GET_INFO, &fe_info) < 0)
404                 {
405                         eWarning("ioctl FE_GET_INFO failed");
406                         ::close(m_fd);
407                         m_fd = -1;
408 #if HAVE_DVB_API_VERSION < 3
409                         ::close(m_secfd);
410                         m_secfd=-1;
411 #endif
412                         return -1;
413                 }
414
415                 switch (fe_info.type)
416                 {
417                 case FE_QPSK:
418                         m_type = iDVBFrontend::feSatellite;
419                         break;
420                 case FE_QAM:
421                         m_type = iDVBFrontend::feCable;
422                         break;
423                 case FE_OFDM:
424                         m_type = iDVBFrontend::feTerrestrial;
425                         break;
426                 default:
427                         eWarning("unknown frontend type.");
428                         ::close(m_fd);
429                         m_fd = -1;
430 #if HAVE_DVB_API_VERSION < 3
431                         ::close(m_secfd);
432                         m_secfd=-1;
433 #endif
434                         return -1;
435                 }
436                 eDebug("detected %s frontend", "satellite\0cable\0    terrestrial"+fe_info.type*10);
437         }
438
439         setTone(iDVBFrontend::toneOff);
440         setVoltage(iDVBFrontend::voltageOff);
441
442         m_sn = new eSocketNotifier(eApp, m_fd, eSocketNotifier::Read);
443         CONNECT(m_sn->activated, eDVBFrontend::feEvent);
444
445         return 0;
446 }
447
448 int eDVBFrontend::closeFrontend()
449 {
450         if (!m_fe && m_data[7] != -1)
451         {
452                 // try to close the first frontend.. but the second is linked to the first
453                 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)m_data[7];
454                 if (linked_fe->m_inuse)
455                 {
456                         eDebug("dont close frontend %d until the linked frontend %d is still in use",
457                                 m_fe, linked_fe->m_frontend->getID());
458                         return -1;
459                 }
460         }
461         if (m_fd >= 0)
462         {
463                 eDebug("close frontend %d", m_fe);
464                 m_tuneTimer->stop();
465                 setTone(iDVBFrontend::toneOff);
466                 setVoltage(iDVBFrontend::voltageOff);
467                 if (m_sec)
468                         m_sec->setRotorMoving(false);
469                 if (!::close(m_fd))
470                         m_fd=-1;
471                 else
472                         eWarning("couldnt close frontend %d", m_fe);
473                 m_data[0] = m_data[1] = m_data[2] = -1;
474         }
475 #if HAVE_DVB_API_VERSION < 3
476         if (m_secfd >= 0)
477         {
478                 if (!::close(m_secfd))
479                         m_secfd=-1;
480                 else
481                         eWarning("couldnt close sec %d", m_fe);
482         }
483 #endif
484         delete m_sn;
485         m_sn=0;
486
487         return 0;
488 }
489
490 eDVBFrontend::~eDVBFrontend()
491 {
492         closeFrontend();
493         delete m_timeout;
494         delete m_tuneTimer;
495 }
496
497 void eDVBFrontend::feEvent(int w)
498 {
499         while (1)
500         {
501 #if HAVE_DVB_API_VERSION < 3
502                 FrontendEvent event;
503 #else
504                 dvb_frontend_event event;
505 #endif
506                 int res;
507                 int state;
508                 res = ::ioctl(m_fd, FE_GET_EVENT, &event);
509                 
510                 if (res && (errno == EAGAIN))
511                         break;
512
513                 if (res)
514                 {
515                         eWarning("FE_GET_EVENT failed! %m");
516                         return;
517                 }
518                 
519                 if (w < 0)
520                         continue;
521
522 #if HAVE_DVB_API_VERSION < 3
523                 if (event.type == FE_COMPLETION_EV)
524 #else
525                 eDebug("(%d)fe event: status %x, inversion %s", m_fe, event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off");
526                 if (event.status & FE_HAS_LOCK)
527 #endif
528                 {
529                         state = stateLock;
530                 } else
531                 {
532                         if (m_tuning)
533                                 state = stateTuning;
534                         else
535                         {
536                                 state = stateLostLock;
537                                 m_data[0] = m_data[1] = m_data[2] = -1; // reset diseqc
538                         }
539                 }
540                 if (m_state != state)
541                 {
542                         m_state = state;
543                         m_stateChanged(this);
544                 }
545         }
546 }
547
548 void eDVBFrontend::timeout()
549 {
550         m_tuning = 0;
551         if (m_state == stateTuning)
552         {
553                 m_state = stateFailed;
554                 m_stateChanged(this);
555         }
556 }
557
558 int eDVBFrontend::readFrontendData(int type)
559 {
560         switch(type)
561         {
562                 case bitErrorRate:
563                 {
564                         uint32_t ber=0;
565                         if (ioctl(m_fd, FE_READ_BER, &ber) < 0 && errno != ERANGE)
566                                 eDebug("FE_READ_BER failed (%m)");
567                         return ber;
568                 }
569                 case signalPower:
570                 {
571                         uint16_t snr=0;
572                         if (ioctl(m_fd, FE_READ_SNR, &snr) < 0 && errno != ERANGE)
573                                 eDebug("FE_READ_SNR failed (%m)");
574                         return snr;
575                 }
576                 case signalQuality:
577                 {
578                         uint16_t strength=0;
579                         if (ioctl(m_fd, FE_READ_SIGNAL_STRENGTH, &strength) < 0 && errno != ERANGE)
580                                 eDebug("FE_READ_SIGNAL_STRENGTH failed (%m)");
581                         return strength;
582                 }
583                 case Locked:
584                 {
585 #if HAVE_DVB_API_VERSION < 3
586                         FrontendStatus status=0;
587 #else
588                         fe_status_t status;
589 #endif
590                         if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
591                                 eDebug("FE_READ_STATUS failed (%m)");
592                         return !!(status&FE_HAS_LOCK);
593                 }
594                 case Synced:
595                 {
596 #if HAVE_DVB_API_VERSION < 3
597                         FrontendStatus status=0;
598 #else
599                         fe_status_t status;
600 #endif
601                         if ( ioctl(m_fd, FE_READ_STATUS, &status) < 0 && errno != ERANGE )
602                                 eDebug("FE_READ_STATUS failed (%m)");
603                         return !!(status&FE_HAS_SYNC);
604                 }
605         }
606         return 0;
607 }
608
609 void PutToDict(PyObject *dict, const char*key, long value)
610 {
611         PyObject *item = PyInt_FromLong(value);
612         if (item)
613         {
614                 if (PyDict_SetItemString(dict, key, item))
615                         eDebug("put %s to dict failed", key);
616                 Py_DECREF(item);
617         }
618         else
619                 eDebug("could not create PyObject for %s", key);
620 }
621
622 void PutToDict(PyObject *dict, const char*key, const char *value)
623 {
624         PyObject *item = PyString_FromString(value);
625         if (item)
626         {
627                 if (PyDict_SetItemString(dict, key, item))
628                         eDebug("put %s to dict failed", key);
629                 Py_DECREF(item);
630         }
631         else
632                 eDebug("could not create PyObject for %s", key);
633 }
634
635 void fillDictWithSatelliteData(PyObject *dict, const FRONTENDPARAMETERS &parm, eDVBFrontend *fe)
636 {
637         int freq_offset=0;
638         int csw=0;
639         const char *fec=0;
640         fe->getData(0, csw);
641         fe->getData(9, freq_offset);
642         int frequency = parm_frequency + freq_offset;
643         PutToDict(dict, "frequency", frequency);
644         PutToDict(dict, "symbol_rate", parm_u_qpsk_symbol_rate);
645
646         switch(parm_u_qpsk_fec_inner)
647         {
648         case FEC_1_2:
649                 fec = "FEC_1_2";
650                 break;
651         case FEC_2_3:
652                 fec = "FEC_2_3";
653                 break;
654         case FEC_3_4:
655                 fec = "FEC_3_4";
656                 break;
657         case FEC_5_6:
658                 fec = "FEC_5_6";
659                 break;
660         case FEC_7_8:
661                 fec = "FEC_7_8";
662                 break;
663         default:
664         case FEC_AUTO:
665                 fec = "FEC_AUTO";
666                 break;
667         }
668         PutToDict(dict, "fec_inner", fec);
669 }
670
671 void fillDictWithCableData(PyObject *dict, const FRONTENDPARAMETERS &parm)
672 {
673         const char *tmp=0;
674         PutToDict(dict, "frequency", parm_frequency/1000);
675         PutToDict(dict, "symbol_rate", parm_u_qam_symbol_rate);
676         switch(parm_u_qam_fec_inner)
677         {
678         case FEC_NONE:
679                 tmp = "FEC_NONE";
680                 break;
681         case FEC_1_2:
682                 tmp = "FEC_1_2";
683                 break;
684         case FEC_2_3:
685                 tmp = "FEC_2_3";
686                 break;
687         case FEC_3_4:
688                 tmp = "FEC_3_4";
689                 break;
690         case FEC_5_6:
691                 tmp = "FEC_5_6";
692                 break;
693         case FEC_7_8:
694                 tmp = "FEC_7_8";
695                 break;
696 #if HAVE_DVB_API_VERSION >= 3
697         case FEC_8_9:
698                 tmp = "FEC_8_9";
699                 break;
700 #endif
701         default:
702         case FEC_AUTO:
703                 tmp = "FEC_AUTO";
704                 break;
705         }
706         PutToDict(dict, "fec_inner", tmp);
707         switch(parm_u_qam_modulation)
708         {
709         case QAM_16:
710                 tmp = "QAM_16";
711                 break;
712         case QAM_32:
713                 tmp = "QAM_32";
714                 break;
715         case QAM_64:
716                 tmp = "QAM_64";
717                 break;
718         case QAM_128:
719                 tmp = "QAM_128";
720                 break;
721         case QAM_256:
722                 tmp = "QAM_256";
723                 break;
724         default:
725         case QAM_AUTO:
726                 tmp = "QAM_AUTO";
727                 break;
728         }
729         PutToDict(dict, "modulation", tmp);
730 }
731
732 void fillDictWithTerrestrialData(PyObject *dict, const FRONTENDPARAMETERS &parm)
733 {
734         const char *tmp=0;
735         PutToDict(dict, "frequency", parm_frequency);
736         switch (parm_u_ofdm_bandwidth)
737         {
738         case BANDWIDTH_8_MHZ:
739                 tmp = "BANDWIDTH_8_MHZ";
740                 break;
741         case BANDWIDTH_7_MHZ:
742                 tmp = "BANDWIDTH_7_MHZ";
743                 break;
744         case BANDWIDTH_6_MHZ:
745                 tmp = "BANDWIDTH_6_MHZ";
746                 break;
747         default:
748         case BANDWIDTH_AUTO:
749                 tmp = "BANDWIDTH_AUTO";
750                 break;
751         }
752         PutToDict(dict, "bandwidth", tmp);
753         switch (parm_u_ofdm_code_rate_LP)
754         {
755         case FEC_1_2:
756                 tmp = "FEC_1_2";
757                 break;
758         case FEC_2_3:
759                 tmp = "FEC_2_3";
760                 break;
761         case FEC_3_4:
762                 tmp = "FEC_3_4";
763                 break;
764         case FEC_5_6:
765                 tmp = "FEC_5_6";
766                 break;
767         case FEC_7_8:
768                 tmp = "FEC_7_8";
769                 break;
770         default:
771         case FEC_AUTO:
772                 tmp = "FEC_AUTO";
773                 break;
774         }
775         PutToDict(dict, "code_rate_lp", tmp);
776         switch (parm_u_ofdm_code_rate_HP)
777         {
778         case FEC_1_2:
779                 tmp = "FEC_1_2";
780                 break;
781         case FEC_2_3:
782                 tmp = "FEC_2_3";
783                 break;
784         case FEC_3_4:
785                 tmp = "FEC_3_4";
786                 break;
787         case FEC_5_6:
788                 tmp = "FEC_5_6";
789                 break;
790         case FEC_7_8:
791                 tmp = "FEC_7_8";
792                 break;
793         default:
794         case FEC_AUTO:
795                 tmp = "FEC_AUTO";
796                 break;
797         }
798         PutToDict(dict, "code_rate_hp", tmp);
799         switch (parm_u_ofdm_constellation)
800         {
801         case QPSK:
802                 tmp = "QPSK";
803                 break;
804         case QAM_16:
805                 tmp = "QAM_16";
806                 break;
807         case QAM_64:
808                 tmp = "QAM_64";
809                 break;
810         default:
811         case QAM_AUTO:
812                 tmp = "QAM_AUTO";
813                 break;
814         }
815         PutToDict(dict, "constellation", tmp);
816         switch (parm_u_ofdm_transmission_mode)
817         {
818         case TRANSMISSION_MODE_2K:
819                 tmp = "TRANSMISSION_MODE_2K";
820                 break;
821         case TRANSMISSION_MODE_8K:
822                 tmp = "TRANSMISSION_MODE_8K";
823                 break;
824         default:
825         case TRANSMISSION_MODE_AUTO:
826                 tmp = "TRANSMISSION_MODE_AUTO";
827                 break;
828         }
829         PutToDict(dict, "transmission_mode", tmp);
830         switch (parm_u_ofdm_guard_interval)
831         {
832                 case GUARD_INTERVAL_1_32:
833                         tmp = "GUARD_INTERVAL_1_32";
834                         break;
835                 case GUARD_INTERVAL_1_16:
836                         tmp = "GUARD_INTERVAL_1_16";
837                         break;
838                 case GUARD_INTERVAL_1_8:
839                         tmp = "GUARD_INTERVAL_1_8";
840                         break;
841                 case GUARD_INTERVAL_1_4:
842                         tmp = "GUARD_INTERVAL_1_4";
843                         break;
844                 default:
845                 case GUARD_INTERVAL_AUTO:
846                         tmp = "GUARD_INTERVAL_AUTO";
847                         break;
848         }
849         PutToDict(dict, "guard_interval", tmp);
850         switch (parm_u_ofdm_hierarchy_information)
851         {
852                 case HIERARCHY_NONE:
853                         tmp = "HIERARCHY_NONE";
854                         break;
855                 case HIERARCHY_1:
856                         tmp = "HIERARCHY_1";
857                         break;
858                 case HIERARCHY_2:
859                         tmp = "HIERARCHY_2";
860                         break;
861                 case HIERARCHY_4:
862                         tmp = "HIERARCHY_4";
863                         break;
864                 default:
865                 case HIERARCHY_AUTO:
866                         tmp = "HIERARCHY_AUTO";
867                         break;
868         }
869         PutToDict(dict, "hierarchy_information", tmp);
870 }
871
872 PyObject *eDVBFrontend::readTransponderData(bool original)
873 {
874         PyObject *ret=PyDict_New();
875
876         if (ret)
877         {
878                 bool read=m_fd != -1;
879                 const char *tmp=0;
880
881                 PutToDict(ret, "tuner_number", m_fe);
882
883                 switch(m_type)
884                 {
885                         case feSatellite:
886                                 tmp = "DVB-S";
887                                 break;
888                         case feCable:
889                                 tmp = "DVB-C";
890                                 break;
891                         case feTerrestrial:
892                                 tmp = "DVB-T";
893                                 break;
894                         default:
895                                 tmp = "UNKNOWN";
896                                 read=false;
897                                 break;
898                 }
899                 PutToDict(ret, "tuner_type", tmp);
900
901                 if (read)
902                 {
903                         FRONTENDPARAMETERS front;
904
905                         tmp = "UNKNOWN";
906                         switch(m_state)
907                         {
908                                 case stateIdle:
909                                         tmp="IDLE";
910                                         break;
911                                 case stateTuning:
912                                         tmp="TUNING";
913                                         break;
914                                 case stateFailed:
915                                         tmp="FAILED";
916                                         break;
917                                 case stateLock:
918                                         tmp="LOCKED";
919                                         break;
920                                 case stateLostLock:
921                                         tmp="LOSTLOCK";
922                                         break;
923                                 default:
924                                         break;
925                         }
926                         PutToDict(ret, "tuner_state", tmp);
927
928                         PutToDict(ret, "tuner_locked", readFrontendData(Locked));
929                         PutToDict(ret, "tuner_synced", readFrontendData(Synced));
930                         PutToDict(ret, "tuner_bit_error_rate", readFrontendData(bitErrorRate));
931                         PutToDict(ret, "tuner_signal_power", readFrontendData(signalPower));
932                         PutToDict(ret, "tuner_signal_quality", readFrontendData(signalQuality));
933
934                         if (!original && ioctl(m_fd, FE_GET_FRONTEND, &front)<0)
935                                 eDebug("FE_GET_FRONTEND (%m)");
936                         else
937                         {
938                                 tmp = "INVERSION_AUTO";
939                                 switch(parm_inversion)
940                                 {
941                                         case INVERSION_ON:
942                                                 tmp = "INVERSION_ON";
943                                                 break;
944                                         case INVERSION_OFF:
945                                                 tmp = "INVERSION_OFF";
946                                                 break;
947                                         default:
948                                                 break;
949                                 }
950                                 if (tmp)
951                                         PutToDict(ret, "inversion", tmp);
952
953                                 switch(m_type)
954                                 {
955                                         case feSatellite:
956                                                 fillDictWithSatelliteData(ret, original?parm:front, this);
957                                                 break;
958                                         case feCable:
959                                                 fillDictWithCableData(ret, original?parm:front);
960                                                 break;
961                                         case feTerrestrial:
962                                                 fillDictWithTerrestrialData(ret, original?parm:front);
963                                                 break;
964                                 }
965                         }
966                 }
967         }
968         else
969         {
970                 Py_INCREF(Py_None);
971                 ret = Py_None;
972         }
973         return ret;
974 }
975
976 #ifndef FP_IOCTL_GET_ID
977 #define FP_IOCTL_GET_ID 0
978 #endif
979 int eDVBFrontend::readInputpower()
980 {
981         int power=m_fe;  // this is needed for read inputpower from the correct tuner !
982
983         // open front prozessor
984         int fp=::open("/dev/dbox/fp0", O_RDWR);
985         if (fp < 0)
986         {
987                 eDebug("couldn't open fp");
988                 return -1;
989         }
990         static bool old_fp = (::ioctl(fp, FP_IOCTL_GET_ID) < 0);
991         if ( ioctl( fp, old_fp ? 9 : 0x100, &power ) < 0 )
992         {
993                 eDebug("FP_IOCTL_GET_LNB_CURRENT failed (%m)");
994                 return -1;
995         }
996         ::close(fp);
997
998         return power;
999 }
1000
1001 bool eDVBFrontend::setSecSequencePos(int steps)
1002 {
1003         eDebug("set sequence pos %d", steps);
1004         if (!steps)
1005                 return false;
1006         while( steps > 0 )
1007         {
1008                 if (m_sec_sequence.current() != m_sec_sequence.end())
1009                         ++m_sec_sequence.current();
1010                 --steps;
1011         }
1012         while( steps < 0 )
1013         {
1014                 if (m_sec_sequence.current() != m_sec_sequence.begin() && m_sec_sequence.current() != m_sec_sequence.end())
1015                         --m_sec_sequence.current();
1016                 ++steps;
1017         }
1018         return true;
1019 }
1020
1021 void eDVBFrontend::tuneLoop()  // called by m_tuneTimer
1022 {
1023         int delay=0;
1024         if ( m_sec_sequence && m_sec_sequence.current() != m_sec_sequence.end() )
1025         {
1026 //              eDebug("tuneLoop %d\n", m_sec_sequence.current()->cmd);
1027                 switch (m_sec_sequence.current()->cmd)
1028                 {
1029                         case eSecCommand::SLEEP:
1030                                 delay = m_sec_sequence.current()++->msec;
1031                                 eDebug("[SEC] sleep %dms", delay);
1032                                 break;
1033                         case eSecCommand::GOTO:
1034                                 if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
1035                                         ++m_sec_sequence.current();
1036                                 break;
1037                         case eSecCommand::SET_VOLTAGE:
1038                         {
1039                                 int voltage = m_sec_sequence.current()++->voltage;
1040                                 eDebug("[SEC] setVoltage %d", voltage);
1041                                 setVoltage(voltage);
1042                                 break;
1043                         }
1044                         case eSecCommand::IF_VOLTAGE_GOTO:
1045                         {
1046                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1047                                 if ( compare.voltage == m_curVoltage && setSecSequencePos(compare.steps) )
1048                                         break;
1049                                 ++m_sec_sequence.current();
1050                                 break;
1051                         }
1052                         case eSecCommand::IF_NOT_VOLTAGE_GOTO:
1053                         {
1054                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1055                                 if ( compare.voltage != m_curVoltage && setSecSequencePos(compare.steps) )
1056                                         break;
1057                                 ++m_sec_sequence.current();
1058                                 break;
1059                         }
1060                         case eSecCommand::SET_TONE:
1061                                 eDebug("[SEC] setTone %d", m_sec_sequence.current()->tone);
1062                                 setTone(m_sec_sequence.current()++->tone);
1063                                 break;
1064                         case eSecCommand::SEND_DISEQC:
1065                                 sendDiseqc(m_sec_sequence.current()->diseqc);
1066                                 eDebugNoNewLine("[SEC] sendDiseqc: ");
1067                                 for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
1068                                     eDebugNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
1069                                 eDebug("");
1070                                 ++m_sec_sequence.current();
1071                                 break;
1072                         case eSecCommand::SEND_TONEBURST:
1073                                 eDebug("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
1074                                 sendToneburst(m_sec_sequence.current()++->toneburst);
1075                                 break;
1076                         case eSecCommand::SET_FRONTEND:
1077                                 eDebug("[SEC] setFrontend");
1078                                 setFrontend();
1079                                 ++m_sec_sequence.current();
1080                                 break;
1081                         case eSecCommand::START_TUNE_TIMEOUT:
1082                                 m_timeout->start(5000, 1); // 5 sec timeout. TODO: symbolrate dependent
1083                                 ++m_sec_sequence.current();
1084                                 break;
1085                         case eSecCommand::SET_TIMEOUT:
1086                                 m_timeoutCount = m_sec_sequence.current()++->val;
1087                                 eDebug("[SEC] set timeout %d", m_timeoutCount);
1088                                 break;
1089                         case eSecCommand::IF_TIMEOUT_GOTO:
1090                                 if (!m_timeoutCount)
1091                                 {
1092                                         eDebug("[SEC] rotor timout");
1093                                         m_sec->setRotorMoving(false);
1094                                         setSecSequencePos(m_sec_sequence.current()->steps);
1095                                 }
1096                                 else
1097                                         ++m_sec_sequence.current();
1098                                 break;
1099                         case eSecCommand::MEASURE_IDLE_INPUTPOWER:
1100                         {
1101                                 int idx = m_sec_sequence.current()++->val;
1102                                 if ( idx == 0 || idx == 1 )
1103                                 {
1104                                         m_idleInputpower[idx] = readInputpower();
1105                                         eDebug("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
1106                                 }
1107                                 else
1108                                         eDebug("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
1109                                 break;
1110                         }
1111                         case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
1112                         {
1113                                 eSecCommand::pair &compare = m_sec_sequence.current()->compare;
1114                                 int idx = compare.voltage;
1115                                 if ( idx == 0 || idx == 1 )
1116                                 {
1117                                         int idle = readInputpower();
1118                                         int diff = abs(idle-m_idleInputpower[idx]);
1119                                         if ( diff > 0)
1120                                         {
1121                                                 eDebug("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
1122                                                 setSecSequencePos(compare.steps);
1123                                                 break;
1124                                         }
1125                                 }
1126                                 ++m_sec_sequence.current();
1127                                 break;
1128                         }
1129                         case eSecCommand::IF_TUNER_LOCKED_GOTO:
1130                         {
1131                                 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1132                                 if (readFrontendData(Locked))
1133                                 {
1134                                         eDebug("[SEC] locked step %d ok", cmd.okcount);
1135                                         ++cmd.okcount;
1136                                         if (cmd.okcount > 12)
1137                                         {
1138                                                 eDebug("ok > 12 .. goto %d\n",m_sec_sequence.current()->steps);
1139                                                 setSecSequencePos(cmd.steps);
1140                                                 break;
1141                                         }
1142                                 }
1143                                 else
1144                                 {
1145                                         eDebug("[SEC] rotor locked step %d failed", cmd.okcount);
1146                                         --m_timeoutCount;
1147                                         if (!m_timeoutCount && m_retryCount > 0)
1148                                                 --m_retryCount;
1149                                         cmd.okcount=0;
1150                                 }
1151                                 ++m_sec_sequence.current();
1152                                 break;
1153                         }
1154                         case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
1155                                 m_runningInputpower = readInputpower();
1156                                 eDebug("[SEC] runningInputpower is %d", m_runningInputpower);
1157                                 ++m_sec_sequence.current();
1158                                 break;
1159                         case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
1160                         {
1161                                 int idleInputpower = m_idleInputpower[ (m_curVoltage&1) ? 0 : 1];
1162                                 eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
1163                                 const char *txt = cmd.direction ? "running" : "stopped";
1164                                 eDebug("[SEC] waiting for rotor %s %d, idle %d, delta %d",
1165                                         txt,
1166                                         m_runningInputpower,
1167                                         idleInputpower,
1168                                         cmd.deltaA);
1169                                 if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
1170                                         || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
1171                                 {
1172                                         ++cmd.okcount;
1173                                         eDebug("[SEC] rotor %s step %d ok", txt, cmd.okcount);
1174                                         if ( cmd.okcount > 6 )
1175                                         {
1176                                                 m_sec->setRotorMoving(cmd.direction);
1177                                                 eDebug("[SEC] rotor is %s", txt);
1178                                                 if (setSecSequencePos(cmd.steps))
1179                                                         break;
1180                                         }
1181                                 }
1182                                 else
1183                                 {
1184                                         eDebug("[SEC] rotor not %s... reset counter.. increase timeout", txt);
1185                                         --m_timeoutCount;
1186                                         if (!m_timeoutCount && m_retryCount > 0)
1187                                                 --m_retryCount;
1188                                         cmd.okcount=0;
1189                                 }
1190                                 ++m_sec_sequence.current();
1191                                 break;
1192                         }
1193                         case eSecCommand::IF_ROTORPOS_VALID_GOTO:
1194                                 if (m_data[5] != -1 && m_data[6] != -1)
1195                                         setSecSequencePos(m_sec_sequence.current()->steps);
1196                                 else
1197                                         ++m_sec_sequence.current();
1198                                 break;
1199                         case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
1200                                 m_data[5] = m_data[6] = -1;
1201                                 eDebug("[SEC] invalidate current rotorparams");
1202                                 ++m_sec_sequence.current();
1203                                 break;
1204                         case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
1205                                 m_data[5] = m_data[3];
1206                                 m_data[6] = m_data[4];
1207                                 eDebug("[SEC] update current rotorparams %d %04x %d", m_timeoutCount, m_data[5], m_data[6]);
1208                                 ++m_sec_sequence.current();
1209                                 break;
1210                         case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
1211                                 m_retryCount = m_sec_sequence.current()++->val;
1212                                 eDebug("[SEC] set rotor retries %d", m_retryCount);
1213                                 break;
1214                         case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
1215                                 if (!m_retryCount)
1216                                 {
1217                                         eDebug("[SEC] no more rotor retrys");
1218                                         setSecSequencePos(m_sec_sequence.current()->steps);
1219                                 }
1220                                 else
1221                                         ++m_sec_sequence.current();
1222                                 break;
1223                         case eSecCommand::SET_POWER_LIMITING_MODE:
1224                         {
1225                                 int fd = m_fe ?
1226                                         ::open("/dev/i2c/1", O_RDWR) :
1227                                         ::open("/dev/i2c/0", O_RDWR);
1228
1229                                 unsigned char data[2];
1230                                 ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
1231                                 if(::read(fd, data, 1) != 1)
1232                                         eDebug("[SEC] error read lnbp (%m)");
1233                                 if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
1234                                 {
1235                                         data[0] |= 0x80;  // enable static current limiting
1236                                         eDebug("[SEC] set static current limiting");
1237                                 }
1238                                 else
1239                                 {
1240                                         data[0] &= ~0x80;  // enable dynamic current limiting
1241                                         eDebug("[SEC] set dynamic current limiting");
1242                                 }
1243                                 if(::write(fd, data, 1) != 1)
1244                                         eDebug("[SEC] error write lnbp (%m)");
1245                                 ::close(fd);
1246                                 ++m_sec_sequence.current();
1247                                 break;
1248                         }
1249                         default:
1250                                 ++m_sec_sequence.current();
1251                                 eDebug("[SEC] unhandled sec command");
1252                 }
1253                 m_tuneTimer->start(delay,true);
1254         }
1255 }
1256
1257 void eDVBFrontend::setFrontend()
1258 {
1259         eDebug("setting frontend %d", m_fe);
1260         m_sn->start();
1261         feEvent(-1);
1262         if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
1263         {
1264                 perror("FE_SET_FRONTEND failed");
1265                 return;
1266         }
1267 }
1268
1269 RESULT eDVBFrontend::getFrontendType(int &t)
1270 {
1271         if (m_type == -1)
1272                 return -ENODEV;
1273         t = m_type;
1274         return 0;
1275 }
1276
1277 RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm)
1278 {
1279         int res;
1280         if (!m_sec)
1281         {
1282                 eWarning("no SEC module active!");
1283                 return -ENOENT;
1284         }
1285         res = m_sec->prepare(*this, parm, feparm, 1 << m_fe);
1286         if (!res)
1287         {
1288                 parm_u_qpsk_symbol_rate = feparm.symbol_rate;
1289                 switch (feparm.inversion)
1290                 {
1291                         case eDVBFrontendParametersSatellite::Inversion::On:
1292                                 parm_inversion = INVERSION_ON;
1293                                 break;
1294                         case eDVBFrontendParametersSatellite::Inversion::Off:
1295                                 parm_inversion = INVERSION_OFF;
1296                                 break;
1297                         default:
1298                         case eDVBFrontendParametersSatellite::Inversion::Unknown:
1299                                 parm_inversion = INVERSION_AUTO;
1300                                 break;
1301                 }
1302                 switch (feparm.fec)
1303                 {
1304                         default:
1305                                 eDebug("no valid fec set.. assume auto");
1306                         case eDVBFrontendParametersSatellite::FEC::fAuto:
1307                                 parm_u_qpsk_fec_inner = FEC_AUTO;
1308                                 break;
1309                         case eDVBFrontendParametersSatellite::FEC::fNone:
1310                                 parm_u_qpsk_fec_inner = FEC_NONE;
1311                         case eDVBFrontendParametersSatellite::FEC::f1_2:
1312                                 parm_u_qpsk_fec_inner = FEC_1_2;
1313                                 break;
1314                         case eDVBFrontendParametersSatellite::FEC::f2_3:
1315                                 parm_u_qpsk_fec_inner = FEC_2_3;
1316                                 break;
1317                         case eDVBFrontendParametersSatellite::FEC::f3_4:
1318                                 parm_u_qpsk_fec_inner = FEC_3_4;
1319                                 break;
1320                         case eDVBFrontendParametersSatellite::FEC::f5_6:
1321                                 parm_u_qpsk_fec_inner = FEC_5_6;
1322                                 break;
1323                         case eDVBFrontendParametersSatellite::FEC::f7_8:
1324                                 parm_u_qpsk_fec_inner = FEC_7_8;
1325                                 break;
1326 #if HAVE_DVB_API_VERSION >= 3
1327                         case eDVBFrontendParametersSatellite::FEC::f9_10:
1328                                 parm_u_qpsk_fec_inner = FEC_9_10;
1329                                 break;
1330 #endif
1331                 }
1332                 // FIXME !!! get frequency range from tuner
1333                 if ( parm_frequency < 900000 || parm_frequency > 2200000 )
1334                 {
1335                         eDebug("%d mhz out of tuner range.. dont tune", parm_frequency/1000);
1336                         return -EINVAL;
1337                 }
1338                 eDebug("tuning to %d mhz", parm_frequency/1000);
1339         }
1340         return res;
1341 }
1342
1343 RESULT eDVBFrontend::prepare_cable(const eDVBFrontendParametersCable &feparm)
1344 {
1345         parm_frequency = feparm.frequency * 1000;
1346         parm_u_qam_symbol_rate = feparm.symbol_rate;
1347         switch (feparm.modulation)
1348         {
1349         case eDVBFrontendParametersCable::Modulation::QAM16:
1350                 parm_u_qam_modulation = QAM_16;
1351                 break;
1352         case eDVBFrontendParametersCable::Modulation::QAM32:
1353                 parm_u_qam_modulation = QAM_32;
1354                 break;
1355         case eDVBFrontendParametersCable::Modulation::QAM64:
1356                 parm_u_qam_modulation = QAM_64;
1357                 break;
1358         case eDVBFrontendParametersCable::Modulation::QAM128:
1359                 parm_u_qam_modulation = QAM_128;
1360                 break;
1361         case eDVBFrontendParametersCable::Modulation::QAM256:
1362                 parm_u_qam_modulation = QAM_256;
1363                 break;
1364         default:
1365         case eDVBFrontendParametersCable::Modulation::Auto:
1366                 parm_u_qam_modulation = QAM_AUTO;
1367                 break;
1368         }
1369         switch (feparm.inversion)
1370         {
1371         case eDVBFrontendParametersCable::Inversion::On:
1372                 parm_inversion = INVERSION_ON;
1373                 break;
1374         case eDVBFrontendParametersCable::Inversion::Off:
1375                 parm_inversion = INVERSION_OFF;
1376                 break;
1377         default:
1378         case eDVBFrontendParametersCable::Inversion::Unknown:
1379                 parm_inversion = INVERSION_AUTO;
1380                 break;
1381         }
1382         switch (feparm.fec_inner)
1383         {
1384         case eDVBFrontendParametersCable::FEC::fNone:
1385                 parm_u_qam_fec_inner = FEC_NONE;
1386                 break;
1387         case eDVBFrontendParametersCable::FEC::f1_2:
1388                 parm_u_qam_fec_inner = FEC_1_2;
1389                 break;
1390         case eDVBFrontendParametersCable::FEC::f2_3:
1391                 parm_u_qam_fec_inner = FEC_2_3;
1392                 break;
1393         case eDVBFrontendParametersCable::FEC::f3_4:
1394                 parm_u_qam_fec_inner = FEC_3_4;
1395                 break;
1396         case eDVBFrontendParametersCable::FEC::f5_6:
1397                 parm_u_qam_fec_inner = FEC_5_6;
1398                 break;
1399         case eDVBFrontendParametersCable::FEC::f7_8:
1400                 parm_u_qam_fec_inner = FEC_7_8;
1401                 break;
1402 #if HAVE_DVB_API_VERSION >= 3
1403         case eDVBFrontendParametersCable::FEC::f8_9:
1404                 parm_u_qam_fec_inner = FEC_8_9;
1405                 break;
1406 #endif
1407         default:
1408         case eDVBFrontendParametersCable::FEC::fAuto:
1409                 parm_u_qam_fec_inner = FEC_AUTO;
1410                 break;
1411         }
1412         return 0;
1413 }
1414
1415 RESULT eDVBFrontend::prepare_terrestrial(const eDVBFrontendParametersTerrestrial &feparm)
1416 {
1417         parm_frequency = feparm.frequency;
1418
1419         switch (feparm.bandwidth)
1420         {
1421         case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz:
1422                 parm_u_ofdm_bandwidth = BANDWIDTH_8_MHZ;
1423                 break;
1424         case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz:
1425                 parm_u_ofdm_bandwidth = BANDWIDTH_7_MHZ;
1426                 break;
1427         case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz:
1428                 parm_u_ofdm_bandwidth = BANDWIDTH_6_MHZ;
1429                 break;
1430         default:
1431         case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto:
1432                 parm_u_ofdm_bandwidth = BANDWIDTH_AUTO;
1433                 break;
1434         }
1435         switch (feparm.code_rate_LP)
1436         {
1437         case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1438                 parm_u_ofdm_code_rate_LP = FEC_1_2;
1439                 break;
1440         case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1441                 parm_u_ofdm_code_rate_LP = FEC_2_3;
1442                 break;
1443         case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1444                 parm_u_ofdm_code_rate_LP = FEC_3_4;
1445                 break;
1446         case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1447                 parm_u_ofdm_code_rate_LP = FEC_5_6;
1448                 break;
1449         case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1450                 parm_u_ofdm_code_rate_LP = FEC_7_8;
1451                 break;
1452         default:
1453         case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1454                 parm_u_ofdm_code_rate_LP = FEC_AUTO;
1455                 break;
1456         }
1457         switch (feparm.code_rate_HP)
1458         {
1459         case eDVBFrontendParametersTerrestrial::FEC::f1_2:
1460                 parm_u_ofdm_code_rate_HP = FEC_1_2;
1461                 break;
1462         case eDVBFrontendParametersTerrestrial::FEC::f2_3:
1463                 parm_u_ofdm_code_rate_HP = FEC_2_3;
1464                 break;
1465         case eDVBFrontendParametersTerrestrial::FEC::f3_4:
1466                 parm_u_ofdm_code_rate_HP = FEC_3_4;
1467                 break;
1468         case eDVBFrontendParametersTerrestrial::FEC::f5_6:
1469                 parm_u_ofdm_code_rate_HP = FEC_5_6;
1470                 break;
1471         case eDVBFrontendParametersTerrestrial::FEC::f7_8:
1472                 parm_u_ofdm_code_rate_HP = FEC_7_8;
1473                 break;
1474         default:
1475         case eDVBFrontendParametersTerrestrial::FEC::fAuto:
1476                 parm_u_ofdm_code_rate_HP = FEC_AUTO;
1477                 break;
1478         }
1479         switch (feparm.modulation)
1480         {
1481         case eDVBFrontendParametersTerrestrial::Modulation::QPSK:
1482                 parm_u_ofdm_constellation = QPSK;
1483                 break;
1484         case eDVBFrontendParametersTerrestrial::Modulation::QAM16:
1485                 parm_u_ofdm_constellation = QAM_16;
1486                 break;
1487         case eDVBFrontendParametersTerrestrial::Modulation::QAM64:
1488                 parm_u_ofdm_constellation = QAM_64;
1489                 break;
1490         default:
1491         case eDVBFrontendParametersTerrestrial::Modulation::Auto:
1492                 parm_u_ofdm_constellation = QAM_AUTO;
1493                 break;
1494         }
1495         switch (feparm.transmission_mode)
1496         {
1497         case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k:
1498                 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_2K;
1499                 break;
1500         case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k:
1501                 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_8K;
1502                 break;
1503         default:
1504         case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto:
1505                 parm_u_ofdm_transmission_mode = TRANSMISSION_MODE_AUTO;
1506                 break;
1507         }
1508         switch (feparm.guard_interval)
1509         {
1510                 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32:
1511                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_32;
1512                         break;
1513                 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16:
1514                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_16;
1515                         break;
1516                 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8:
1517                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_8;
1518                         break;
1519                 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4:
1520                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_1_4;
1521                         break;
1522                 default:
1523                 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto:
1524                         parm_u_ofdm_guard_interval = GUARD_INTERVAL_AUTO;
1525                         break;
1526         }
1527         switch (feparm.hierarchy)
1528         {
1529                 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone:
1530                         parm_u_ofdm_hierarchy_information = HIERARCHY_NONE;
1531                         break;
1532                 case eDVBFrontendParametersTerrestrial::Hierarchy::H1:
1533                         parm_u_ofdm_hierarchy_information = HIERARCHY_1;
1534                         break;
1535                 case eDVBFrontendParametersTerrestrial::Hierarchy::H2:
1536                         parm_u_ofdm_hierarchy_information = HIERARCHY_2;
1537                         break;
1538                 case eDVBFrontendParametersTerrestrial::Hierarchy::H4:
1539                         parm_u_ofdm_hierarchy_information = HIERARCHY_4;
1540                         break;
1541                 default:
1542                 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto:
1543                         parm_u_ofdm_hierarchy_information = HIERARCHY_AUTO;
1544                         break;
1545         }
1546         switch (feparm.inversion)
1547         {
1548         case eDVBFrontendParametersTerrestrial::Inversion::On:
1549                 parm_inversion = INVERSION_ON;
1550                 break;
1551         case eDVBFrontendParametersTerrestrial::Inversion::Off:
1552                 parm_inversion = INVERSION_OFF;
1553                 break;
1554         default:
1555         case eDVBFrontendParametersTerrestrial::Inversion::Unknown:
1556                 parm_inversion = INVERSION_AUTO;
1557                 break;
1558         }
1559         return 0;
1560 }
1561
1562 RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
1563 {
1564         eDebug("(%d)tune", m_fe);
1565
1566         m_timeout->stop();
1567
1568         int res=0;
1569
1570         if (m_type == -1)
1571                 return -ENODEV;
1572
1573         m_sn->stop();
1574         m_sec_sequence.clear();
1575
1576         switch (m_type)
1577         {
1578         case feSatellite:
1579         {
1580                 eDVBFrontendParametersSatellite feparm;
1581                 if (where.getDVBS(feparm))
1582                 {
1583                         eDebug("no dvbs data!");
1584                         return -EINVAL;
1585                 }
1586                 res=prepare_sat(feparm);
1587                 m_sec->setRotorMoving(false);
1588                 break;
1589         }
1590         case feCable:
1591         {
1592                 eDVBFrontendParametersCable feparm;
1593                 if (where.getDVBC(feparm))
1594                         return -EINVAL;
1595                 res=prepare_cable(feparm);
1596                 if (!res)
1597                 {
1598                         m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT) );
1599                         m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
1600                 }
1601                 break;
1602         }
1603         case feTerrestrial:
1604         {
1605                 eDVBFrontendParametersTerrestrial feparm;
1606                 if (where.getDVBT(feparm))
1607                 {
1608                         eDebug("no -T data");
1609                         return -EINVAL;
1610                 }
1611                 res=prepare_terrestrial(feparm);
1612                 if (!res)
1613                 {
1614                         m_sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT) );
1615                         m_sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
1616                 }
1617                 break;
1618         }
1619         }
1620
1621         if (!res)  // prepare ok
1622         {
1623                 m_tuneTimer->start(0,true);
1624                 m_sec_sequence.current() = m_sec_sequence.begin();
1625
1626                 if (m_state != stateTuning)
1627                 {
1628                         m_tuning = 1;
1629                         m_state = stateTuning;
1630                         m_stateChanged(this);
1631                 }
1632         }
1633
1634         return res;
1635 }
1636
1637 RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateChange, ePtr<eConnection> &connection)
1638 {
1639         connection = new eConnection(this, m_stateChanged.connect(stateChange));
1640         return 0;
1641 }
1642
1643 RESULT eDVBFrontend::setVoltage(int voltage)
1644 {
1645         if (m_type != feSatellite)
1646                 return -1;
1647 #if HAVE_DVB_API_VERSION < 3
1648         secVoltage vlt;
1649 #else
1650         bool increased=false;
1651         fe_sec_voltage_t vlt;
1652 #endif
1653         m_curVoltage=voltage;
1654         switch (voltage)
1655         {
1656         case voltageOff:
1657                 for (int i=0; i < 3; ++i)  // reset diseqc
1658                         m_data[i]=-1;
1659                 vlt = SEC_VOLTAGE_OFF;
1660                 break;
1661         case voltage13_5:
1662 #if HAVE_DVB_API_VERSION < 3
1663                 vlt = SEC_VOLTAGE_13_5;
1664                 break;
1665 #else
1666                 increased = true;
1667 #endif
1668         case voltage13:
1669                 vlt = SEC_VOLTAGE_13;
1670                 break;
1671         case voltage18_5:
1672 #if HAVE_DVB_API_VERSION < 3
1673                 vlt = SEC_VOLTAGE_18_5;
1674                 break;
1675 #else
1676                 increased = true;
1677 #endif
1678         case voltage18:
1679                 vlt = SEC_VOLTAGE_18;
1680                 break;
1681         default:
1682                 return -ENODEV;
1683         }
1684 #if HAVE_DVB_API_VERSION < 3
1685         return ::ioctl(m_secfd, SEC_SET_VOLTAGE, vlt);
1686 #else
1687         if (::ioctl(m_fd, FE_ENABLE_HIGH_LNB_VOLTAGE, increased) < 0)
1688                 perror("FE_ENABLE_HIGH_LNB_VOLTAGE");
1689         return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt);
1690 #endif
1691 }
1692
1693 RESULT eDVBFrontend::getState(int &state)
1694 {
1695         state = m_state;
1696         return 0;
1697 }
1698
1699 RESULT eDVBFrontend::setTone(int t)
1700 {
1701         if (m_type != feSatellite)
1702                 return -1;
1703 #if HAVE_DVB_API_VERSION < 3
1704         secToneMode_t tone;
1705 #else
1706         fe_sec_tone_mode_t tone;
1707 #endif
1708
1709         switch (t)
1710         {
1711         case toneOn:
1712                 tone = SEC_TONE_ON;
1713                 break;
1714         case toneOff:
1715                 tone = SEC_TONE_OFF;
1716                 break;
1717         default:
1718                 return -ENODEV;
1719         }
1720 #if HAVE_DVB_API_VERSION < 3    
1721         return ::ioctl(m_secfd, SEC_SET_TONE, tone);
1722 #else   
1723         return ::ioctl(m_fd, FE_SET_TONE, tone);
1724 #endif
1725 }
1726
1727 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_MASTER_CMD)
1728         #define SEC_DISEQC_SEND_MASTER_CMD _IOW('o', 97, struct secCommand *)
1729 #endif
1730
1731 RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
1732 {
1733 #if HAVE_DVB_API_VERSION < 3
1734         struct secCommand cmd;
1735         cmd.type = SEC_CMDTYPE_DISEQC_RAW;
1736         cmd.u.diseqc.cmdtype = diseqc.data[0];
1737         cmd.u.diseqc.addr = diseqc.data[1];
1738         cmd.u.diseqc.cmd = diseqc.data[2];
1739         cmd.u.diseqc.numParams = diseqc.len-3;
1740         memcpy(cmd.u.diseqc.params, diseqc.data+3, diseqc.len-3);
1741         if (::ioctl(m_secfd, SEC_DISEQC_SEND_MASTER_CMD, &cmd))
1742 #else
1743         struct dvb_diseqc_master_cmd cmd;
1744         memcpy(cmd.msg, diseqc.data, diseqc.len);
1745         cmd.msg_len = diseqc.len;
1746         if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd))
1747 #endif
1748                 return -EINVAL;
1749         return 0;
1750 }
1751
1752 #if HAVE_DVB_API_VERSION < 3 && !defined(SEC_DISEQC_SEND_BURST)
1753         #define SEC_DISEQC_SEND_BURST _IO('o', 96)
1754 #endif
1755 RESULT eDVBFrontend::sendToneburst(int burst)
1756 {
1757 #if HAVE_DVB_API_VERSION < 3
1758         secMiniCmd cmd = SEC_MINI_NONE;
1759 #else
1760         fe_sec_mini_cmd_t cmd = SEC_MINI_A;
1761 #endif
1762         if ( burst == eDVBSatelliteDiseqcParameters::A )
1763                 cmd = SEC_MINI_A;
1764         else if ( burst == eDVBSatelliteDiseqcParameters::B )
1765                 cmd = SEC_MINI_B;
1766 #if HAVE_DVB_API_VERSION < 3
1767         if (::ioctl(m_secfd, SEC_DISEQC_SEND_BURST, cmd))
1768                 return -EINVAL;
1769 #else
1770         if (::ioctl(m_fd, FE_DISEQC_SEND_BURST, cmd))
1771                 return -EINVAL;
1772 #endif
1773         return 0;
1774 }
1775
1776 RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec)
1777 {
1778         m_sec = sec;
1779         return 0;
1780 }
1781
1782 RESULT eDVBFrontend::setSecSequence(const eSecCommandList &list)
1783 {
1784         m_sec_sequence = list;
1785         return 0;
1786 }
1787
1788 RESULT eDVBFrontend::getData(int num, int &data)
1789 {
1790         if ( num < (int)(sizeof(m_data)/sizeof(int)) )
1791         {
1792                 data = m_data[num];
1793                 return 0;
1794         }
1795         return -EINVAL;
1796 }
1797
1798 RESULT eDVBFrontend::setData(int num, int val)
1799 {
1800         if ( num < (int)(sizeof(m_data)/sizeof(int)) )
1801         {
1802                 m_data[num] = val;
1803                 return 0;
1804         }
1805         return -EINVAL;
1806 }
1807
1808 int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
1809 {
1810         int type;
1811         if (feparm->getSystem(type) || type != m_type)
1812                 return 0;
1813
1814         if (m_type == eDVBFrontend::feSatellite)
1815         {
1816                 ASSERT(m_sec);
1817                 eDVBFrontendParametersSatellite sat_parm;
1818                 ASSERT(!feparm->getDVBS(sat_parm));
1819                 return m_sec->canTune(sat_parm, this, 1 << m_fe);
1820         }
1821         return 1;
1822 }