vdr  2.2.0
dvbdevice.c
Go to the documentation of this file.
1 /*
2  * dvbdevice.c: The DVB device tuner interface
3  *
4  * See the main source file 'vdr.c' for copyright information and
5  * how to reach the author.
6  *
7  * $Id: dvbdevice.c 3.14 2015/01/14 12:09:19 kls Exp $
8  */
9 
10 #include "dvbdevice.h"
11 #include <ctype.h>
12 #include <errno.h>
13 #include <limits.h>
14 #include <linux/dvb/dmx.h>
15 #include <linux/dvb/frontend.h>
16 #include <sys/ioctl.h>
17 #include <sys/mman.h>
18 #include "channels.h"
19 #include "diseqc.h"
20 #include "dvbci.h"
21 #include "menuitems.h"
22 #include "sourceparams.h"
23 
24 static int DvbApiVersion = 0x0000; // the version of the DVB driver actually in use (will be determined by the first device created)
25 
26 #define DVBS_TUNE_TIMEOUT 9000 //ms
27 #define DVBS_LOCK_TIMEOUT 2000 //ms
28 #define DVBC_TUNE_TIMEOUT 9000 //ms
29 #define DVBC_LOCK_TIMEOUT 2000 //ms
30 #define DVBT_TUNE_TIMEOUT 9000 //ms
31 #define DVBT_LOCK_TIMEOUT 2000 //ms
32 #define ATSC_TUNE_TIMEOUT 9000 //ms
33 #define ATSC_LOCK_TIMEOUT 2000 //ms
34 
35 #define SCR_RANDOM_TIMEOUT 500 // ms (add random value up to this when tuning SCR device to avoid lockups)
36 
37 // --- DVB Parameter Maps ----------------------------------------------------
38 
40  { 0, PILOT_OFF, trNOOP("off") },
41  { 1, PILOT_ON, trNOOP("on") },
42  { 999, PILOT_AUTO, trNOOP("auto") },
43  { -1, 0, NULL }
44  };
45 
47  { 0, INVERSION_OFF, trNOOP("off") },
48  { 1, INVERSION_ON, trNOOP("on") },
49  { 999, INVERSION_AUTO, trNOOP("auto") },
50  { -1, 0, NULL }
51  };
52 
54  { 5, 5000000, "5 MHz" },
55  { 6, 6000000, "6 MHz" },
56  { 7, 7000000, "7 MHz" },
57  { 8, 8000000, "8 MHz" },
58  { 10, 10000000, "10 MHz" },
59  { 1712, 1712000, "1.712 MHz" },
60  { -1, 0, NULL }
61  };
62 
64  { 0, FEC_NONE, trNOOP("none") },
65  { 12, FEC_1_2, "1/2" },
66  { 23, FEC_2_3, "2/3" },
67  { 34, FEC_3_4, "3/4" },
68  { 35, FEC_3_5, "3/5" },
69  { 45, FEC_4_5, "4/5" },
70  { 56, FEC_5_6, "5/6" },
71  { 67, FEC_6_7, "6/7" },
72  { 78, FEC_7_8, "7/8" },
73  { 89, FEC_8_9, "8/9" },
74  { 910, FEC_9_10, "9/10" },
75  { 999, FEC_AUTO, trNOOP("auto") },
76  { -1, 0, NULL }
77  };
78 
80  { 16, QAM_16, "QAM16" },
81  { 32, QAM_32, "QAM32" },
82  { 64, QAM_64, "QAM64" },
83  { 128, QAM_128, "QAM128" },
84  { 256, QAM_256, "QAM256" },
85  { 2, QPSK, "QPSK" },
86  { 5, PSK_8, "8PSK" },
87  { 6, APSK_16, "16APSK" },
88  { 7, APSK_32, "32APSK" },
89  { 10, VSB_8, "VSB8" },
90  { 11, VSB_16, "VSB16" },
91  { 12, DQPSK, "DQPSK" },
92  { 999, QAM_AUTO, trNOOP("auto") },
93  { -1, 0, NULL }
94  };
95 
96 #define DVB_SYSTEM_1 0 // see also nit.c
97 #define DVB_SYSTEM_2 1
98 
100  { 0, DVB_SYSTEM_1, "DVB-S" },
101  { 1, DVB_SYSTEM_2, "DVB-S2" },
102  { -1, 0, NULL }
103  };
104 
106  { 0, DVB_SYSTEM_1, "DVB-T" },
107  { 1, DVB_SYSTEM_2, "DVB-T2" },
108  { -1, 0, NULL }
109  };
110 
112  { 1, TRANSMISSION_MODE_1K, "1K" },
113  { 2, TRANSMISSION_MODE_2K, "2K" },
114  { 4, TRANSMISSION_MODE_4K, "4K" },
115  { 8, TRANSMISSION_MODE_8K, "8K" },
116  { 16, TRANSMISSION_MODE_16K, "16K" },
117  { 32, TRANSMISSION_MODE_32K, "32K" },
118  { 999, TRANSMISSION_MODE_AUTO, trNOOP("auto") },
119  { -1, 0, NULL }
120  };
121 
123  { 4, GUARD_INTERVAL_1_4, "1/4" },
124  { 8, GUARD_INTERVAL_1_8, "1/8" },
125  { 16, GUARD_INTERVAL_1_16, "1/16" },
126  { 32, GUARD_INTERVAL_1_32, "1/32" },
127  { 128, GUARD_INTERVAL_1_128, "1/128" },
128  { 19128, GUARD_INTERVAL_19_128, "19/128" },
129  { 19256, GUARD_INTERVAL_19_256, "19/256" },
130  { 999, GUARD_INTERVAL_AUTO, trNOOP("auto") },
131  { -1, 0, NULL }
132  };
133 
135  { 0, HIERARCHY_NONE, trNOOP("none") },
136  { 1, HIERARCHY_1, "1" },
137  { 2, HIERARCHY_2, "2" },
138  { 4, HIERARCHY_4, "4" },
139  { 999, HIERARCHY_AUTO, trNOOP("auto") },
140  { -1, 0, NULL }
141  };
142 
144  { 0, ROLLOFF_AUTO, trNOOP("auto") },
145  { 20, ROLLOFF_20, "0.20" },
146  { 25, ROLLOFF_25, "0.25" },
147  { 35, ROLLOFF_35, "0.35" },
148  { -1, 0, NULL }
149  };
150 
151 int UserIndex(int Value, const tDvbParameterMap *Map)
152 {
153  const tDvbParameterMap *map = Map;
154  while (map && map->userValue != -1) {
155  if (map->userValue == Value)
156  return map - Map;
157  map++;
158  }
159  return -1;
160 }
161 
162 int DriverIndex(int Value, const tDvbParameterMap *Map)
163 {
164  const tDvbParameterMap *map = Map;
165  while (map && map->userValue != -1) {
166  if (map->driverValue == Value)
167  return map - Map;
168  map++;
169  }
170  return -1;
171 }
172 
173 int MapToUser(int Value, const tDvbParameterMap *Map, const char **String)
174 {
175  int n = DriverIndex(Value, Map);
176  if (n >= 0) {
177  if (String)
178  *String = tr(Map[n].userString);
179  return Map[n].userValue;
180  }
181  return -1;
182 }
183 
184 const char *MapToUserString(int Value, const tDvbParameterMap *Map)
185 {
186  int n = DriverIndex(Value, Map);
187  if (n >= 0)
188  return Map[n].userString;
189  return "???";
190 }
191 
192 int MapToDriver(int Value, const tDvbParameterMap *Map)
193 {
194  int n = UserIndex(Value, Map);
195  if (n >= 0)
196  return Map[n].driverValue;
197  return -1;
198 }
199 
200 // --- cDvbTransponderParameters ---------------------------------------------
201 
203 {
204  polarization = 0;
205  inversion = INVERSION_AUTO;
206  bandwidth = 8000000;
207  coderateH = FEC_AUTO;
208  coderateL = FEC_AUTO;
209  modulation = QPSK;
211  transmission = TRANSMISSION_MODE_AUTO;
212  guard = GUARD_INTERVAL_AUTO;
213  hierarchy = HIERARCHY_AUTO;
214  rollOff = ROLLOFF_AUTO;
215  streamId = 0;
216  t2systemId = 0;
217  sisoMiso = 0;
218  pilot = PILOT_AUTO;
219  Parse(Parameters);
220 }
221 
222 int cDvbTransponderParameters::PrintParameter(char *p, char Name, int Value) const
223 {
224  return Value >= 0 && Value != 999 ? sprintf(p, "%c%d", Name, Value) : 0;
225 }
226 
228 {
229 #define ST(s) if (strchr(s, Type) && (strchr(s, '0' + system + 1) || strchr(s, '*')))
230  char buffer[64];
231  char *q = buffer;
232  *q = 0;
233  ST(" S *") q += sprintf(q, "%c", polarization);
234  ST(" T*") q += PrintParameter(q, 'B', MapToUser(bandwidth, BandwidthValues));
235  ST(" CST*") q += PrintParameter(q, 'C', MapToUser(coderateH, CoderateValues));
236  ST(" T*") q += PrintParameter(q, 'D', MapToUser(coderateL, CoderateValues));
237  ST(" T*") q += PrintParameter(q, 'G', MapToUser(guard, GuardValues));
238  ST("ACST*") q += PrintParameter(q, 'I', MapToUser(inversion, InversionValues));
239  ST("ACST*") q += PrintParameter(q, 'M', MapToUser(modulation, ModulationValues));
240  ST(" S 2") q += PrintParameter(q, 'N', MapToUser(pilot, PilotValues));
241  ST(" S 2") q += PrintParameter(q, 'O', MapToUser(rollOff, RollOffValues));
242  ST(" ST2") q += PrintParameter(q, 'P', streamId);
243  ST(" T2") q += PrintParameter(q, 'Q', t2systemId);
244  ST(" ST*") q += PrintParameter(q, 'S', MapToUser(system, SystemValuesSat)); // we only need the numerical value, so Sat or Terr doesn't matter
245  ST(" T*") q += PrintParameter(q, 'T', MapToUser(transmission, TransmissionValues));
246  ST(" T2") q += PrintParameter(q, 'X', sisoMiso);
247  ST(" T*") q += PrintParameter(q, 'Y', MapToUser(hierarchy, HierarchyValues));
248  return buffer;
249 }
250 
251 const char *cDvbTransponderParameters::ParseParameter(const char *s, int &Value, const tDvbParameterMap *Map)
252 {
253  if (*++s) {
254  char *p = NULL;
255  errno = 0;
256  int n = strtol(s, &p, 10);
257  if (!errno && p != s) {
258  Value = Map ? MapToDriver(n, Map) : n;
259  if (Value >= 0)
260  return p;
261  }
262  }
263  esyslog("ERROR: invalid value for parameter '%c'", *(s - 1));
264  return NULL;
265 }
266 
268 {
269  while (s && *s) {
270  switch (toupper(*s)) {
271  case 'B': s = ParseParameter(s, bandwidth, BandwidthValues); break;
272  case 'C': s = ParseParameter(s, coderateH, CoderateValues); break;
273  case 'D': s = ParseParameter(s, coderateL, CoderateValues); break;
274  case 'G': s = ParseParameter(s, guard, GuardValues); break;
275  case 'H': polarization = 'H'; s++; break;
276  case 'I': s = ParseParameter(s, inversion, InversionValues); break;
277  case 'L': polarization = 'L'; s++; break;
278  case 'M': s = ParseParameter(s, modulation, ModulationValues); break;
279  case 'N': s = ParseParameter(s, pilot, PilotValues); break;
280  case 'O': s = ParseParameter(s, rollOff, RollOffValues); break;
281  case 'P': s = ParseParameter(s, streamId); break;
282  case 'Q': s = ParseParameter(s, t2systemId); break;
283  case 'R': polarization = 'R'; s++; break;
284  case 'S': s = ParseParameter(s, system, SystemValuesSat); break; // we only need the numerical value, so Sat or Terr doesn't matter
285  case 'T': s = ParseParameter(s, transmission, TransmissionValues); break;
286  case 'V': polarization = 'V'; s++; break;
287  case 'X': s = ParseParameter(s, sisoMiso); break;
288  case 'Y': s = ParseParameter(s, hierarchy, HierarchyValues); break;
289  default: esyslog("ERROR: unknown parameter key '%c'", *s);
290  return false;
291  }
292  }
293  return true;
294 }
295 
296 // --- cDvbTuner -------------------------------------------------------------
297 
298 #define TUNER_POLL_TIMEOUT 10 // ms
299 
300 class cDvbTuner : public cThread {
301 private:
303  enum eTunerStatus { tsIdle, tsSet, tsPositioning, tsTuned, tsLocked };
306  mutable int fd_frontend;
307  int adapter, frontend;
308  uint32_t subsystemId;
317  const cScr *scr;
320  mutable cMutex mutex;
325  bool SetFrontendType(const cChannel *Channel);
326  cString GetBondingParams(const cChannel *Channel = NULL) const;
327  cDvbTuner *GetBondedMaster(void);
328  bool IsBondedMaster(void) const { return !bondedTuner || bondedMaster; }
329  void ClearEventQueue(void) const;
330  bool GetFrontendStatus(fe_status_t &Status) const;
331  cPositioner *GetPositioner(void);
332  void ExecuteDiseqc(const cDiseqc *Diseqc, unsigned int *Frequency);
333  void ResetToneAndVoltage(void);
334  bool SetFrontend(void);
335  virtual void Action(void);
336 
337  mutable bool isIdle;
338  bool OpenFrontend(void) const;
339  bool CloseFrontend(void);
340 public:
341  cDvbTuner(const cDvbDevice *Device, int Fd_Frontend, int Adapter, int Frontend);
342  virtual ~cDvbTuner();
343  int FrontendType(void) const { return frontendType; }
344  bool Bond(cDvbTuner *Tuner);
345  void UnBond(void);
346  bool BondingOk(const cChannel *Channel, bool ConsiderOccupied = false) const;
347  const cChannel *GetTransponder(void) const { return &channel; }
348  uint32_t SubsystemId(void) const { return subsystemId; }
349  bool IsTunedTo(const cChannel *Channel) const;
350  void SetChannel(const cChannel *Channel);
351  bool Locked(int TimeoutMs = 0);
352  const cPositioner *Positioner(void) const { return positioner; }
353  int GetSignalStrength(void) const;
354  int GetSignalQuality(void) const;
355 
356  bool SetIdle(bool Idle);
357  bool IsIdle(void) const { return isIdle; }
358  };
359 
361 
362 cDvbTuner::cDvbTuner(const cDvbDevice *Device, int Fd_Frontend, int Adapter, int Frontend)
363 {
364  frontendType = SYS_UNDEFINED;
365  device = Device;
366  fd_frontend = Fd_Frontend;
367  adapter = Adapter;
368  frontend = Frontend;
369  subsystemId = cDvbDeviceProbe::GetSubsystemId(adapter, frontend);
370  tuneTimeout = 0;
371  lockTimeout = 0;
372  lastTimeoutReport = 0;
373  lastDiseqc = NULL;
374  diseqcOffset = 0;
375  lastSource = 0;
376  positioner = NULL;
377  scr = NULL;
378  lnbPowerTurnedOn = false;
379  tunerStatus = tsIdle;
380  bondedTuner = NULL;
381  bondedMaster = false;
382  isIdle = false;
383  SetDescription("frontend %d/%d tuner", adapter, frontend);
384  Start();
385 }
386 
388 {
389  tunerStatus = tsIdle;
390  newSet.Broadcast();
391  locked.Broadcast();
392  Cancel(3);
393  UnBond();
394  /* looks like this irritates the SCR switch, so let's leave it out for now
395  if (lastDiseqc && lastDiseqc->IsScr()) {
396  unsigned int Frequency = 0;
397  ExecuteDiseqc(lastDiseqc, &Frequency);
398  }
399  */
400  if (device && device->IsSubDevice())
401  CloseFrontend();
402 }
403 
405 {
406  cMutexLock MutexLock(&bondMutex);
407  if (!bondedTuner) {
408  ResetToneAndVoltage();
409  bondedMaster = false; // makes sure we don't disturb an existing master
410  bondedTuner = Tuner->bondedTuner ? Tuner->bondedTuner : Tuner;
411  Tuner->bondedTuner = this;
412  dsyslog("tuner %d/%d bonded with tuner %d/%d", adapter, frontend, bondedTuner->adapter, bondedTuner->frontend);
413  return true;
414  }
415  else
416  esyslog("ERROR: tuner %d/%d already bonded with tuner %d/%d, can't bond with tuner %d/%d", adapter, frontend, bondedTuner->adapter, bondedTuner->frontend, Tuner->adapter, Tuner->frontend);
417  return false;
418 }
419 
421 {
422  cMutexLock MutexLock(&bondMutex);
423  if (cDvbTuner *t = bondedTuner) {
424  dsyslog("tuner %d/%d unbonded from tuner %d/%d", adapter, frontend, bondedTuner->adapter, bondedTuner->frontend);
425  while (t->bondedTuner != this)
426  t = t->bondedTuner;
427  if (t == bondedTuner)
428  t->bondedTuner = NULL;
429  else
430  t->bondedTuner = bondedTuner;
431  bondedMaster = false; // another one will automatically become master whenever necessary
432  bondedTuner = NULL;
433  }
434 }
435 
437 {
438  if (!Channel)
439  Channel = &channel;
440  cDvbTransponderParameters dtp(Channel->Parameters());
441  if (Setup.DiSEqC) {
442  if (const cDiseqc *diseqc = Diseqcs.Get(device->CardIndex() + 1, Channel->Source(), Channel->Frequency(), dtp.Polarization(), NULL))
443  return diseqc->Commands();
444  }
445  else {
446  bool ToneOff = Channel->Frequency() < Setup.LnbSLOF;
447  bool VoltOff = dtp.Polarization() == 'V' || dtp.Polarization() == 'R';
448  return cString::sprintf("%c %c", ToneOff ? 't' : 'T', VoltOff ? 'v' : 'V');
449  }
450  return "";
451 }
452 
453 bool cDvbTuner::BondingOk(const cChannel *Channel, bool ConsiderOccupied) const
454 {
455  cMutexLock MutexLock(&bondMutex);
456  if (cDvbTuner *t = bondedTuner) {
457  cString BondingParams = GetBondingParams(Channel);
458  do {
459  if (t->device->Priority() > IDLEPRIORITY || ConsiderOccupied && t->device->Occupied()) {
460  if (strcmp(BondingParams, t->GetBondedMaster()->GetBondingParams()) != 0)
461  return false;
462  }
463  t = t->bondedTuner;
464  } while (t != bondedTuner);
465  }
466  return true;
467 }
468 
470 {
471  if (!bondedTuner)
472  return this; // an unbonded tuner is always "master"
473  cMutexLock MutexLock(&bondMutex);
474  if (bondedMaster)
475  return this;
476  // This tuner is bonded, but it's not the master, so let's see if there is a master at all:
477  if (cDvbTuner *t = bondedTuner) {
478  while (t != this) {
479  if (t->bondedMaster)
480  return t;
481  t = t->bondedTuner;
482  }
483  }
484  // None of the other bonded tuners is master, so make this one the master:
485  bondedMaster = true;
486  dsyslog("tuner %d/%d is now bonded master", adapter, frontend);
487  return this;
488 }
489 
490 bool cDvbTuner::IsTunedTo(const cChannel *Channel) const
491 {
492  if (tunerStatus == tsIdle)
493  return false; // not tuned to
494  if (channel.Source() != Channel->Source() || channel.Transponder() != Channel->Transponder())
495  return false; // sufficient mismatch
496  // Polarization is already checked as part of the Transponder.
497  return strcmp(channel.Parameters(), Channel->Parameters()) == 0;
498 }
499 
500 void cDvbTuner::SetChannel(const cChannel *Channel)
501 {
502  if (Channel) {
503  if (bondedTuner) {
504  cMutexLock MutexLock(&bondMutex);
505  cDvbTuner *BondedMaster = GetBondedMaster();
506  if (BondedMaster == this) {
507  if (strcmp(GetBondingParams(Channel), GetBondingParams()) != 0) {
508  // switching to a completely different band, so set all others to idle:
509  for (cDvbTuner *t = bondedTuner; t && t != this; t = t->bondedTuner)
510  t->SetChannel(NULL);
511  }
512  }
513  else if (strcmp(GetBondingParams(Channel), BondedMaster->GetBondingParams()) != 0)
514  BondedMaster->SetChannel(Channel);
515  }
516  cMutexLock MutexLock(&mutex);
517  if (!IsTunedTo(Channel))
518  tunerStatus = tsSet;
519  diseqcOffset = 0;
520  channel = *Channel;
521  lastTimeoutReport = 0;
522  newSet.Broadcast();
523  }
524  else {
525  cMutexLock MutexLock(&mutex);
526  tunerStatus = tsIdle;
527  ResetToneAndVoltage();
528  }
529  if (bondedTuner && device->IsPrimaryDevice())
530  cDevice::PrimaryDevice()->DelLivePids(); // 'device' is const, so we must do it this way
531 }
532 
533 bool cDvbTuner::Locked(int TimeoutMs)
534 {
535  bool isLocked = (tunerStatus >= tsLocked);
536  if (isLocked || !TimeoutMs)
537  return isLocked;
538 
539  cMutexLock MutexLock(&mutex);
540  if (TimeoutMs && tunerStatus < tsLocked)
541  locked.TimedWait(mutex, TimeoutMs);
542  return tunerStatus >= tsLocked;
543 }
544 
546 {
547  if (!OpenFrontend())
548  return;
549  cPoller Poller(fd_frontend);
550  if (Poller.Poll(TUNER_POLL_TIMEOUT)) {
551  dvb_frontend_event Event;
552  while (ioctl(fd_frontend, FE_GET_EVENT, &Event) == 0)
553  ; // just to clear the event queue - we'll read the actual status below
554  }
555 }
556 
557 bool cDvbTuner::GetFrontendStatus(fe_status_t &Status) const
558 {
559  ClearEventQueue();
560  while (1) {
561  if (ioctl(fd_frontend, FE_READ_STATUS, &Status) != -1)
562  return true;
563  if (errno != EINTR)
564  break;
565  }
566  return false;
567 }
568 
569 //#define DEBUG_SIGNALSTRENGTH
570 //#define DEBUG_SIGNALQUALITY
571 
573 {
574  ClearEventQueue();
575  uint16_t Signal;
576  while (1) {
577  if (ioctl(fd_frontend, FE_READ_SIGNAL_STRENGTH, &Signal) != -1)
578  break;
579  if (errno != EINTR)
580  return -1;
581  }
582  uint16_t MaxSignal = 0xFFFF; // Let's assume the default is using the entire range.
583  // Use the subsystemId to identify individual devices in case they need
584  // special treatment to map their Signal value into the range 0...0xFFFF.
585  switch (subsystemId) {
586  case 0x13C21019: // TT-budget S2-3200 (DVB-S/DVB-S2)
587  case 0x1AE40001: // TechniSat SkyStar HD2 (DVB-S/DVB-S2)
588  MaxSignal = 670; break;
589  }
590  int s = int(Signal) * 100 / MaxSignal;
591  if (s > 100)
592  s = 100;
593 #ifdef DEBUG_SIGNALSTRENGTH
594  fprintf(stderr, "FE %d/%d: %08X S = %04X %04X %3d%%\n", adapter, frontend, subsystemId, MaxSignal, Signal, s);
595 #endif
596  return s;
597 }
598 
599 #define LOCK_THRESHOLD 5 // indicates that all 5 FE_HAS_* flags are set
600 
602 {
603  fe_status_t Status;
604  if (GetFrontendStatus(Status)) {
605  // Actually one would expect these checks to be done from FE_HAS_SIGNAL to FE_HAS_LOCK, but some drivers (like the stb0899) are broken, so FE_HAS_LOCK is the only one that (hopefully) is generally reliable...
606  if ((Status & FE_HAS_LOCK) == 0) {
607  if ((Status & FE_HAS_SIGNAL) == 0)
608  return 0;
609  if ((Status & FE_HAS_CARRIER) == 0)
610  return 1;
611  if ((Status & FE_HAS_VITERBI) == 0)
612  return 2;
613  if ((Status & FE_HAS_SYNC) == 0)
614  return 3;
615  return 4;
616  }
617 #ifdef DEBUG_SIGNALQUALITY
618  bool HasSnr = true;
619 #endif
620  uint16_t Snr;
621  while (1) {
622  if (ioctl(fd_frontend, FE_READ_SNR, &Snr) != -1)
623  break;
624  if (errno != EINTR) {
625  Snr = 0xFFFF;
626 #ifdef DEBUG_SIGNALQUALITY
627  HasSnr = false;
628 #endif
629  break;
630  }
631  }
632 #ifdef DEBUG_SIGNALQUALITY
633  bool HasBer = true;
634 #endif
635  uint32_t Ber;
636  while (1) {
637  if (ioctl(fd_frontend, FE_READ_BER, &Ber) != -1)
638  break;
639  if (errno != EINTR) {
640  Ber = 0;
641 #ifdef DEBUG_SIGNALQUALITY
642  HasBer = false;
643 #endif
644  break;
645  }
646  }
647 #ifdef DEBUG_SIGNALQUALITY
648  bool HasUnc = true;
649 #endif
650  uint32_t Unc;
651  while (1) {
652  if (ioctl(fd_frontend, FE_READ_UNCORRECTED_BLOCKS, &Unc) != -1)
653  break;
654  if (errno != EINTR) {
655  Unc = 0;
656 #ifdef DEBUG_SIGNALQUALITY
657  HasUnc = false;
658 #endif
659  break;
660  }
661  }
662  uint16_t MinSnr = 0x0000;
663  uint16_t MaxSnr = 0xFFFF; // Let's assume the default is using the entire range.
664  // Use the subsystemId to identify individual devices in case they need
665  // special treatment to map their Snr value into the range 0...0xFFFF.
666  switch (subsystemId) {
667  case 0x13C21019: // TT-budget S2-3200 (DVB-S/DVB-S2)
668  case 0x1AE40001: // TechniSat SkyStar HD2 (DVB-S/DVB-S2)
669  if (frontendType == SYS_DVBS2) {
670  MinSnr = 10;
671  MaxSnr = 70;
672  }
673  else
674  MaxSnr = 200;
675  break;
676  case 0x20130245: // PCTV Systems PCTV 73ESE
677  case 0x2013024F: // PCTV Systems nanoStick T2 290e
678  MaxSnr = 255; break;
679  }
680  int a = int(constrain(Snr, MinSnr, MaxSnr)) * 100 / (MaxSnr - MinSnr);
681  int b = 100 - (Unc * 10 + (Ber / 256) * 5);
682  if (b < 0)
683  b = 0;
684  int q = LOCK_THRESHOLD + a * b * (100 - LOCK_THRESHOLD) / 100 / 100;
685  if (q > 100)
686  q = 100;
687 #ifdef DEBUG_SIGNALQUALITY
688  fprintf(stderr, "FE %d/%d: %08X Q = %04X %04X %d %5d %5d %3d%%\n", adapter, frontend, subsystemId, MaxSnr, Snr, HasSnr, HasBer ? int(Ber) : -1, HasUnc ? int(Unc) : -1, q);
689 #endif
690  return q;
691  }
692  return -1;
693 }
694 
695 static unsigned int FrequencyToHz(unsigned int f)
696 {
697  while (f && f < 1000000)
698  f *= 1000;
699  return f;
700 }
701 
703 {
704  if (!positioner) {
705  positioner = cPositioner::GetPositioner();
706  positioner->SetFrontend(fd_frontend);
707  }
708  return positioner;
709 }
710 
711 void cDvbTuner::ExecuteDiseqc(const cDiseqc *Diseqc, unsigned int *Frequency)
712 {
713  if (!lnbPowerTurnedOn) {
714  CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); // must explicitly turn on LNB power
715  lnbPowerTurnedOn = true;
716  }
717  static cMutex Mutex;
718  if (Diseqc->IsScr())
719  Mutex.Lock();
720  struct dvb_diseqc_master_cmd cmd;
721  const char *CurrentAction = NULL;
722  cPositioner *Positioner = NULL;
723  bool Break = false;
724  for (int i = 0; !Break; i++) {
725  cmd.msg_len = sizeof(cmd.msg);
726  cDiseqc::eDiseqcActions da = Diseqc->Execute(&CurrentAction, cmd.msg, &cmd.msg_len, scr, Frequency);
727  if (da == cDiseqc::daNone) {
728  diseqcOffset = 0;
729  break;
730  }
731  bool d = i >= diseqcOffset;
732  switch (da) {
733  case cDiseqc::daToneOff: if (d) CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF)); break;
734  case cDiseqc::daToneOn: if (d) CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_ON)); break;
735  case cDiseqc::daVoltage13: if (d) CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); break;
736  case cDiseqc::daVoltage18: if (d) CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_18)); break;
737  case cDiseqc::daMiniA: if (d) CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_A)); break;
738  case cDiseqc::daMiniB: if (d) CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_B)); break;
739  case cDiseqc::daCodes: if (d) CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd)); break;
740  case cDiseqc::daPositionN: if ((Positioner = GetPositioner()) != NULL) {
741  if (d) {
742  Positioner->GotoPosition(Diseqc->Position(), cSource::Position(channel.Source()));
743  Break = Positioner->IsMoving();
744  }
745  }
746  break;
747  case cDiseqc::daPositionA: if ((Positioner = GetPositioner()) != NULL) {
748  if (d) {
749  Positioner->GotoAngle(cSource::Position(channel.Source()));
750  Break = Positioner->IsMoving();
751  }
752  }
753  break;
754  case cDiseqc::daScr:
755  case cDiseqc::daWait: break;
756  default: esyslog("ERROR: unknown diseqc command %d", da);
757  }
758  if (Break)
759  diseqcOffset = i + 1;
760  }
761  positioner = Positioner;
762  if (scr && !Break)
763  ResetToneAndVoltage(); // makes sure we don't block the bus!
764  if (Diseqc->IsScr())
765  Mutex.Unlock();
766 }
767 
769 {
770  CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, bondedTuner ? SEC_VOLTAGE_OFF : SEC_VOLTAGE_13));
771  CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF));
772 }
773 
774 static int GetRequiredDeliverySystem(const cChannel *Channel, const cDvbTransponderParameters *Dtp)
775 {
776  int ds = SYS_UNDEFINED;
777  if (Channel->IsAtsc())
778  ds = SYS_ATSC;
779  else if (Channel->IsCable())
780  ds = SYS_DVBC_ANNEX_AC;
781  else if (Channel->IsSat())
782  ds = Dtp->System() == DVB_SYSTEM_1 ? SYS_DVBS : SYS_DVBS2;
783  else if (Channel->IsTerr())
784  ds = Dtp->System() == DVB_SYSTEM_1 ? SYS_DVBT : SYS_DVBT2;
785  else
786  esyslog("ERROR: can't determine frontend type for channel %d (%s)", Channel->Number(), Channel->Name());
787  return ds;
788 }
789 
791 {
792  if (!OpenFrontend())
793  return false;
794 #define MAXFRONTENDCMDS 16
795 #define SETCMD(c, d) { Frontend[CmdSeq.num].cmd = (c);\
796  Frontend[CmdSeq.num].u.data = (d);\
797  if (CmdSeq.num++ > MAXFRONTENDCMDS) {\
798  esyslog("ERROR: too many tuning commands on frontend %d/%d", adapter, frontend);\
799  return false;\
800  }\
801  }
802  dtv_property Frontend[MAXFRONTENDCMDS];
803  memset(&Frontend, 0, sizeof(Frontend));
804  dtv_properties CmdSeq;
805  memset(&CmdSeq, 0, sizeof(CmdSeq));
806  CmdSeq.props = Frontend;
807  SETCMD(DTV_CLEAR, 0);
808  if (ioctl(fd_frontend, FE_SET_PROPERTY, &CmdSeq) < 0) {
809  esyslog("ERROR: frontend %d/%d: %m", adapter, frontend);
810  return false;
811  }
812  CmdSeq.num = 0;
813 
814  cDvbTransponderParameters dtp(channel.Parameters());
815 
816  // Determine the required frontend type:
817  frontendType = GetRequiredDeliverySystem(&channel, &dtp);
818  if (frontendType == SYS_UNDEFINED)
819  return false;
820 
821  SETCMD(DTV_DELIVERY_SYSTEM, frontendType);
822  if (frontendType == SYS_DVBS || frontendType == SYS_DVBS2) {
823  unsigned int frequency = channel.Frequency();
824  if (Setup.DiSEqC) {
825  if (const cDiseqc *diseqc = Diseqcs.Get(device->CardIndex() + 1, channel.Source(), frequency, dtp.Polarization(), &scr)) {
826  frequency -= diseqc->Lof();
827  if (diseqc != lastDiseqc || diseqc->IsScr() || diseqc->Position() >= 0 && channel.Source() != lastSource) {
828  if (IsBondedMaster()) {
829  ExecuteDiseqc(diseqc, &frequency);
830  if (frequency == 0)
831  return false;
832  }
833  else
834  ResetToneAndVoltage();
835  lastDiseqc = diseqc;
836  lastSource = channel.Source();
837  }
838  }
839  else {
840  esyslog("ERROR: no DiSEqC parameters found for channel %d (%s)", channel.Number(), channel.Name());
841  return false;
842  }
843  }
844  else {
845  int tone = SEC_TONE_OFF;
846  if (frequency < (unsigned int)Setup.LnbSLOF) {
847  frequency -= Setup.LnbFrequLo;
848  tone = SEC_TONE_OFF;
849  }
850  else {
851  frequency -= Setup.LnbFrequHi;
852  tone = SEC_TONE_ON;
853  }
854  int volt = (dtp.Polarization() == 'V' || dtp.Polarization() == 'R') ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18;
855  if (!IsBondedMaster()) {
856  tone = SEC_TONE_OFF;
857  volt = SEC_VOLTAGE_13;
858  }
859  CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, volt));
860  CHECK(ioctl(fd_frontend, FE_SET_TONE, tone));
861  }
862  frequency = abs(frequency); // Allow for C-band, where the frequency is less than the LOF
863 
864  // DVB-S/DVB-S2 (common parts)
865  SETCMD(DTV_FREQUENCY, frequency * 1000UL);
866  SETCMD(DTV_MODULATION, dtp.Modulation());
867  SETCMD(DTV_SYMBOL_RATE, channel.Srate() * 1000UL);
868  SETCMD(DTV_INNER_FEC, dtp.CoderateH());
869  SETCMD(DTV_INVERSION, dtp.Inversion());
870  if (frontendType == SYS_DVBS2) {
871  // DVB-S2
872  SETCMD(DTV_PILOT, dtp.Pilot());
873  SETCMD(DTV_ROLLOFF, dtp.RollOff());
874  if (DvbApiVersion >= 0x0508)
875  SETCMD(DTV_STREAM_ID, dtp.StreamId());
876  }
877  else {
878  // DVB-S
879  SETCMD(DTV_ROLLOFF, ROLLOFF_35); // DVB-S always has a ROLLOFF of 0.35
880  }
881 
882  tuneTimeout = DVBS_TUNE_TIMEOUT;
883  lockTimeout = DVBS_LOCK_TIMEOUT;
884  }
885  else if (frontendType == SYS_DVBC_ANNEX_AC || frontendType == SYS_DVBC_ANNEX_B) {
886  // DVB-C
887  SETCMD(DTV_FREQUENCY, FrequencyToHz(channel.Frequency()));
888  SETCMD(DTV_INVERSION, dtp.Inversion());
889  SETCMD(DTV_SYMBOL_RATE, channel.Srate() * 1000UL);
890  SETCMD(DTV_INNER_FEC, dtp.CoderateH());
891  SETCMD(DTV_MODULATION, dtp.Modulation());
892 
893  tuneTimeout = DVBC_TUNE_TIMEOUT;
894  lockTimeout = DVBC_LOCK_TIMEOUT;
895  }
896  else if (frontendType == SYS_DVBT || frontendType == SYS_DVBT2) {
897  // DVB-T/DVB-T2 (common parts)
898  SETCMD(DTV_FREQUENCY, FrequencyToHz(channel.Frequency()));
899  SETCMD(DTV_INVERSION, dtp.Inversion());
900  SETCMD(DTV_BANDWIDTH_HZ, dtp.Bandwidth());
901  SETCMD(DTV_CODE_RATE_HP, dtp.CoderateH());
902  SETCMD(DTV_CODE_RATE_LP, dtp.CoderateL());
903  SETCMD(DTV_MODULATION, dtp.Modulation());
904  SETCMD(DTV_TRANSMISSION_MODE, dtp.Transmission());
905  SETCMD(DTV_GUARD_INTERVAL, dtp.Guard());
906  SETCMD(DTV_HIERARCHY, dtp.Hierarchy());
907  if (frontendType == SYS_DVBT2) {
908  // DVB-T2
909  if (DvbApiVersion >= 0x0508) {
910  SETCMD(DTV_STREAM_ID, dtp.StreamId());
911  }
912  else if (DvbApiVersion >= 0x0503)
913  SETCMD(DTV_DVBT2_PLP_ID_LEGACY, dtp.StreamId());
914  }
915 
916  tuneTimeout = DVBT_TUNE_TIMEOUT;
917  lockTimeout = DVBT_LOCK_TIMEOUT;
918  }
919  else if (frontendType == SYS_ATSC) {
920  // ATSC
921  SETCMD(DTV_FREQUENCY, FrequencyToHz(channel.Frequency()));
922  SETCMD(DTV_INVERSION, dtp.Inversion());
923  SETCMD(DTV_MODULATION, dtp.Modulation());
924 
925  tuneTimeout = ATSC_TUNE_TIMEOUT;
926  lockTimeout = ATSC_LOCK_TIMEOUT;
927  }
928  else {
929  esyslog("ERROR: attempt to set channel with unknown DVB frontend type");
930  return false;
931  }
932  SETCMD(DTV_TUNE, 0);
933  if (ioctl(fd_frontend, FE_SET_PROPERTY, &CmdSeq) < 0) {
934  esyslog("ERROR: frontend %d/%d: %m", adapter, frontend);
935  return false;
936  }
937  return true;
938 }
939 
941 {
942  cTimeMs Timer;
943  bool LostLock = false;
944  fe_status_t Status = (fe_status_t)0;
945  while (Running()) {
946  if (!isIdle) {
947  fe_status_t NewStatus;
948  if (GetFrontendStatus(NewStatus))
949  Status = NewStatus;
950  }
951  cMutexLock MutexLock(&mutex);
952  int WaitTime = 1000;
953  switch (tunerStatus) {
954  case tsIdle:
955  break; // we want the TimedWait() below!
956  case tsSet:
957  tunerStatus = SetFrontend() ? tsPositioning : tsIdle;
958  continue;
959  case tsPositioning:
960  if (positioner) {
961  if (positioner->IsMoving())
962  break; // we want the TimedWait() below!
963  else if (diseqcOffset) {
964  lastDiseqc = NULL;
965  tunerStatus = tsSet; // have it process the rest of the DiSEqC sequence
966  continue;
967  }
968  }
969  tunerStatus = tsTuned;
970  Timer.Set(tuneTimeout + (scr ? rand() % SCR_RANDOM_TIMEOUT : 0));
971  if (positioner)
972  continue;
973  // otherwise run directly into tsTuned...
974  case tsTuned:
975  if (Timer.TimedOut()) {
976  tunerStatus = tsSet;
977  lastDiseqc = NULL;
978  lastSource = 0;
979  if (time(NULL) - lastTimeoutReport > 60) { // let's not get too many of these
980  isyslog("frontend %d/%d timed out while tuning to channel %d (%s), tp %d", adapter, frontend, channel.Number(), channel.Name(), channel.Transponder());
981  lastTimeoutReport = time(NULL);
982  }
983  continue;
984  }
985  WaitTime = 100; // allows for a quick change from tsTuned to tsLocked
986  // run into tsLocked...
987  case tsLocked:
988  if (Status & FE_REINIT) {
989  tunerStatus = tsSet;
990  lastDiseqc = NULL;
991  lastSource = 0;
992  isyslog("frontend %d/%d was reinitialized", adapter, frontend);
993  lastTimeoutReport = 0;
994  continue;
995  }
996  else if (Status & FE_HAS_LOCK) {
997  if (LostLock) {
998  isyslog("frontend %d/%d regained lock on channel %d (%s), tp %d", adapter, frontend, channel.Number(), channel.Name(), channel.Transponder());
999  LostLock = false;
1000  }
1001  tunerStatus = tsLocked;
1002  locked.Broadcast();
1003  lastTimeoutReport = 0;
1004  }
1005  else if (tunerStatus == tsLocked) {
1006  LostLock = true;
1007  isyslog("frontend %d/%d lost lock on channel %d (%s), tp %d", adapter, frontend, channel.Number(), channel.Name(), channel.Transponder());
1008  tunerStatus = tsTuned;
1009  Timer.Set(lockTimeout);
1010  lastTimeoutReport = 0;
1011  continue;
1012  }
1013  break;
1014  default: esyslog("ERROR: unknown tuner status %d", tunerStatus);
1015  }
1016  newSet.TimedWait(mutex, WaitTime);
1017  }
1018 }
1019 
1020 bool cDvbTuner::SetIdle(bool Idle)
1021 {
1022  if (isIdle == Idle)
1023  return true;
1024  isIdle = Idle;
1025  if (Idle)
1026  return CloseFrontend();
1027  return OpenFrontend();
1028 }
1029 
1030 bool cDvbTuner::OpenFrontend(void) const
1031 {
1032  if (fd_frontend >= 0)
1033  return true;
1034  cMutexLock MutexLock(&mutex);
1035  fd_frontend = cDvbDevice::DvbOpen(DEV_DVB_FRONTEND, adapter, frontend, O_RDWR | O_NONBLOCK);
1036  if (fd_frontend < 0)
1037  return false;
1038  isIdle = false;
1039  return true;
1040 }
1041 
1043 {
1044  if (fd_frontend < 0)
1045  return true;
1046  cMutexLock MutexLock(&mutex);
1047  tunerStatus = tsIdle;
1048  newSet.Broadcast();
1049  close(fd_frontend);
1050  fd_frontend = -1;
1051  return true;
1052 }
1053 
1054 // --- cDvbSourceParam -------------------------------------------------------
1055 
1057 private:
1058  int param;
1059  int srate;
1061 public:
1062  cDvbSourceParam(char Source, const char *Description);
1063  virtual void SetData(cChannel *Channel);
1064  virtual void GetData(cChannel *Channel);
1065  virtual cOsdItem *GetOsdItem(void);
1066  };
1067 
1068 cDvbSourceParam::cDvbSourceParam(char Source, const char *Description)
1069 :cSourceParam(Source, Description)
1070 {
1071  param = 0;
1072  srate = 0;
1073 }
1074 
1076 {
1077  srate = Channel->Srate();
1078  dtp.Parse(Channel->Parameters());
1079  param = 0;
1080 }
1081 
1083 {
1084  Channel->SetTransponderData(Channel->Source(), Channel->Frequency(), srate, dtp.ToString(Source()), true);
1085 }
1086 
1088 {
1089  char type = Source();
1090  const tDvbParameterMap *SystemValues = type == 'S' ? SystemValuesSat : SystemValuesTerr;
1091 #undef ST
1092 #define ST(s) if (strchr(s, type))
1093  switch (param++) {
1094  case 0: ST(" S ") return new cMenuEditChrItem( tr("Polarization"), &dtp.polarization, "HVLR"); else return GetOsdItem();
1095  case 1: ST(" ST") return new cMenuEditMapItem( tr("System"), &dtp.system, SystemValues); else return GetOsdItem();
1096  case 2: ST(" CS ") return new cMenuEditIntItem( tr("Srate"), &srate); else return GetOsdItem();
1097  case 3: ST("ACST") return new cMenuEditMapItem( tr("Inversion"), &dtp.inversion, InversionValues); else return GetOsdItem();
1098  case 4: ST(" CST") return new cMenuEditMapItem( tr("CoderateH"), &dtp.coderateH, CoderateValues); else return GetOsdItem();
1099  case 5: ST(" T") return new cMenuEditMapItem( tr("CoderateL"), &dtp.coderateL, CoderateValues); else return GetOsdItem();
1100  case 6: ST("ACST") return new cMenuEditMapItem( tr("Modulation"), &dtp.modulation, ModulationValues); else return GetOsdItem();
1101  case 7: ST(" T") return new cMenuEditMapItem( tr("Bandwidth"), &dtp.bandwidth, BandwidthValues); else return GetOsdItem();
1102  case 8: ST(" T") return new cMenuEditMapItem( tr("Transmission"), &dtp.transmission, TransmissionValues); else return GetOsdItem();
1103  case 9: ST(" T") return new cMenuEditMapItem( tr("Guard"), &dtp.guard, GuardValues); else return GetOsdItem();
1104  case 10: ST(" T") return new cMenuEditMapItem( tr("Hierarchy"), &dtp.hierarchy, HierarchyValues); else return GetOsdItem();
1105  case 11: ST(" S ") return new cMenuEditMapItem( tr("Rolloff"), &dtp.rollOff, RollOffValues); else return GetOsdItem();
1106  case 12: ST(" ST") return new cMenuEditIntItem( tr("StreamId"), &dtp.streamId, 0, 255); else return GetOsdItem();
1107  case 13: ST(" S ") return new cMenuEditMapItem( tr("Pilot"), &dtp.pilot, PilotValues); else return GetOsdItem();
1108  case 14: ST(" T") return new cMenuEditIntItem( tr("T2SystemId"), &dtp.t2systemId, 0, 65535); else return GetOsdItem();
1109  case 15: ST(" T") return new cMenuEditIntItem( tr("SISO/MISO"), &dtp.sisoMiso, 0, 1); else return GetOsdItem();
1110  default: return NULL;
1111  }
1112  return NULL;
1113 }
1114 
1115 // --- cDvbDevice ------------------------------------------------------------
1116 
1119 
1120 const char *DeliverySystemNames[] = {
1121  "",
1122  "DVB-C",
1123  "DVB-C",
1124  "DVB-T",
1125  "DSS",
1126  "DVB-S",
1127  "DVB-S2",
1128  "DVB-H",
1129  "ISDBT",
1130  "ISDBS",
1131  "ISDBC",
1132  "ATSC",
1133  "ATSCMH",
1134  "DMBTH",
1135  "CMMB",
1136  "DAB",
1137  "DVB-T2",
1138  "TURBO",
1139  NULL
1140  };
1141 
1142 cDvbDevice::cDvbDevice(int Adapter, int Frontend, cDevice *ParentDevice)
1143 :cDevice(ParentDevice)
1144 {
1145  adapter = Adapter;
1146  frontend = Frontend;
1147  ciAdapter = NULL;
1148  dvbTuner = NULL;
1149  numDeliverySystems = 0;
1150  numModulations = 0;
1151  bondedDevice = NULL;
1153  tsBuffer = NULL;
1154 
1155  // Devices that are present on all card types:
1156 
1157  int fd_frontend = DvbOpen(DEV_DVB_FRONTEND, adapter, frontend, O_RDWR | O_NONBLOCK);
1158 
1159  // Common Interface:
1160 
1161  fd_ca = DvbOpen(DEV_DVB_CA, adapter, frontend, O_RDWR);
1162  if (fd_ca >= 0)
1164 
1165  // The DVR device (will be opened and closed as needed):
1166 
1167  fd_dvr = -1;
1168 
1169  // We only check the devices that must be present - the others will be checked before accessing them://XXX
1170 
1171  if (fd_frontend >= 0) {
1172  if (QueryDeliverySystems(fd_frontend))
1173  dvbTuner = new cDvbTuner(this, fd_frontend, adapter, frontend);
1174  }
1175  else
1176  esyslog("ERROR: can't open DVB device %d/%d", adapter, frontend);
1177 
1179 }
1180 
1182 {
1184  delete dvbTuner;
1185  delete ciAdapter;
1186  UnBond();
1187  // We're not explicitly closing any device files here, since this sometimes
1188  // caused segfaults. Besides, the program is about to terminate anyway...
1189 }
1190 
1191 cString cDvbDevice::DvbName(const char *Name, int Adapter, int Frontend)
1192 {
1193  return cString::sprintf("%s/%s%d/%s%d", DEV_DVB_BASE, DEV_DVB_ADAPTER, Adapter, Name, Frontend);
1194 }
1195 
1196 int cDvbDevice::DvbOpen(const char *Name, int Adapter, int Frontend, int Mode, bool ReportError)
1197 {
1198  cString FileName = DvbName(Name, Adapter, Frontend);
1199  int fd = open(FileName, Mode);
1200  if (fd < 0 && ReportError)
1201  LOG_ERROR_STR(*FileName);
1202  return fd;
1203 }
1204 
1206 {
1207  cString FileName = DvbName(DEV_DVB_FRONTEND, Adapter, Frontend);
1208  if (access(FileName, F_OK) == 0) {
1209  int f = open(FileName, O_RDONLY);
1210  if (f >= 0) {
1211  close(f);
1212  return true;
1213  }
1214  else if (errno != ENODEV && errno != EINVAL)
1215  LOG_ERROR_STR(*FileName);
1216  }
1217  else if (errno != ENOENT)
1218  LOG_ERROR_STR(*FileName);
1219  return false;
1220 }
1221 
1223 {
1224  cString FileName = DvbName(DEV_DVB_FRONTEND, Adapter, Frontend);
1225  dsyslog("probing %s", *FileName);
1226  for (cDvbDeviceProbe *dp = DvbDeviceProbes.First(); dp; dp = DvbDeviceProbes.Next(dp)) {
1227  if (dp->Probe(Adapter, Frontend))
1228  return true; // a plugin has created the actual device
1229  }
1230  dsyslog("creating cDvbDevice");
1231  new cDvbDevice(Adapter, Frontend); // it's a "budget" device
1232  return true;
1233 }
1234 
1236 {
1237  if (dvbTuner) {
1238  if (dvbTuner->FrontendType() != SYS_UNDEFINED)
1240  if (numDeliverySystems)
1241  return DeliverySystemNames[deliverySystems[0]]; // to have some reasonable default
1242  }
1243  return "";
1244 }
1245 
1247 {
1248  return frontendInfo.name;
1249 }
1250 
1252 {
1253  new cDvbSourceParam('A', "ATSC");
1254  new cDvbSourceParam('C', "DVB-C");
1255  new cDvbSourceParam('S', "DVB-S");
1256  new cDvbSourceParam('T', "DVB-T");
1257  cStringList Nodes;
1258  cReadDir DvbDir(DEV_DVB_BASE);
1259  if (DvbDir.Ok()) {
1260  struct dirent *a;
1261  while ((a = DvbDir.Next()) != NULL) {
1262  if (strstr(a->d_name, DEV_DVB_ADAPTER) == a->d_name) {
1263  int Adapter = strtol(a->d_name + strlen(DEV_DVB_ADAPTER), NULL, 10);
1264  cReadDir AdapterDir(AddDirectory(DEV_DVB_BASE, a->d_name));
1265  if (AdapterDir.Ok()) {
1266  struct dirent *f;
1267  while ((f = AdapterDir.Next()) != NULL) {
1268  if (strstr(f->d_name, DEV_DVB_FRONTEND) == f->d_name) {
1269  int Frontend = strtol(f->d_name + strlen(DEV_DVB_FRONTEND), NULL, 10);
1270  Nodes.Append(strdup(cString::sprintf("%2d %2d", Adapter, Frontend)));
1271  }
1272  }
1273  }
1274  }
1275  }
1276  }
1277  int Found = 0;
1278  int Used = 0;
1279  if (Nodes.Size() > 0) {
1280  Nodes.Sort();
1281  for (int i = 0; i < Nodes.Size(); i++) {
1282  int Adapter;
1283  int Frontend;
1284  if (2 == sscanf(Nodes[i], "%d %d", &Adapter, &Frontend)) {
1285  if (Exists(Adapter, Frontend)) {
1286  if (Found < MAXDEVICES) {
1287  Found++;
1288  if (UseDevice(NextCardIndex())) {
1289  if (Probe(Adapter, Frontend))
1290  Used++;
1291  }
1292  else
1293  NextCardIndex(1); // skips this one
1294  }
1295  }
1296  }
1297  }
1298  }
1299  if (Found > 0) {
1300  isyslog("found %d DVB device%s", Found, Found > 1 ? "s" : "");
1301  if (Used != Found)
1302  isyslog("using only %d DVB device%s", Used, Used > 1 ? "s" : "");
1303  }
1304  else
1305  isyslog("no DVB device found");
1306  return Found > 0;
1307 }
1308 
1310 {
1311  numDeliverySystems = 0;
1312  if (ioctl(fd_frontend, FE_GET_INFO, &frontendInfo) < 0) {
1313  LOG_ERROR;
1314  return false;
1315  }
1316  dtv_property Frontend[1];
1317  dtv_properties CmdSeq;
1318  // Determine the version of the running DVB API:
1319  if (!DvbApiVersion) {
1320  memset(&Frontend, 0, sizeof(Frontend));
1321  memset(&CmdSeq, 0, sizeof(CmdSeq));
1322  CmdSeq.props = Frontend;
1323  SETCMD(DTV_API_VERSION, 0);
1324  if (ioctl(fd_frontend, FE_GET_PROPERTY, &CmdSeq) != 0) {
1325  LOG_ERROR;
1326  return false;
1327  }
1328  DvbApiVersion = Frontend[0].u.data;
1329  isyslog("DVB API version is 0x%04X (VDR was built with 0x%04X)", DvbApiVersion, DVBAPIVERSION);
1330  }
1331  // Determine the types of delivery systems this device provides:
1332  bool LegacyMode = true;
1333  if (DvbApiVersion >= 0x0505) {
1334  memset(&Frontend, 0, sizeof(Frontend));
1335  memset(&CmdSeq, 0, sizeof(CmdSeq));
1336  CmdSeq.props = Frontend;
1337  SETCMD(DTV_ENUM_DELSYS, 0);
1338  int Result = ioctl(fd_frontend, FE_GET_PROPERTY, &CmdSeq);
1339  if (Result == 0) {
1340  for (uint i = 0; i < Frontend[0].u.buffer.len; i++) {
1342  esyslog("ERROR: too many delivery systems on frontend %d/%d", adapter, frontend);
1343  break;
1344  }
1345  deliverySystems[numDeliverySystems++] = Frontend[0].u.buffer.data[i];
1346  }
1347  LegacyMode = false;
1348  }
1349  else {
1350  esyslog("ERROR: can't query delivery systems on frontend %d/%d - falling back to legacy mode", adapter, frontend);
1351  }
1352  }
1353  if (LegacyMode) {
1354  // Legacy mode (DVB-API < 5.5):
1355  switch (frontendInfo.type) {
1356  case FE_QPSK: deliverySystems[numDeliverySystems++] = SYS_DVBS;
1358  deliverySystems[numDeliverySystems++] = SYS_DVBS2;
1359  break;
1360  case FE_OFDM: deliverySystems[numDeliverySystems++] = SYS_DVBT;
1363  break;
1364  case FE_QAM: deliverySystems[numDeliverySystems++] = SYS_DVBC_ANNEX_AC; break;
1365  case FE_ATSC: deliverySystems[numDeliverySystems++] = SYS_ATSC; break;
1366  default: esyslog("ERROR: unknown frontend type %d on frontend %d/%d", frontendInfo.type, adapter, frontend);
1367  }
1368  }
1369  if (numDeliverySystems > 0) {
1370  cString ds("");
1371  for (int i = 0; i < numDeliverySystems; i++)
1372  ds = cString::sprintf("%s%s%s", *ds, i ? "," : "", DeliverySystemNames[deliverySystems[i]]);
1373  cString ms("");
1374  if (frontendInfo.caps & FE_CAN_QPSK) { numModulations++; ms = cString::sprintf("%s%s%s", *ms, **ms ? "," : "", MapToUserString(QPSK, ModulationValues)); }
1375  if (frontendInfo.caps & FE_CAN_QAM_16) { numModulations++; ms = cString::sprintf("%s%s%s", *ms, **ms ? "," : "", MapToUserString(QAM_16, ModulationValues)); }
1376  if (frontendInfo.caps & FE_CAN_QAM_32) { numModulations++; ms = cString::sprintf("%s%s%s", *ms, **ms ? "," : "", MapToUserString(QAM_32, ModulationValues)); }
1377  if (frontendInfo.caps & FE_CAN_QAM_64) { numModulations++; ms = cString::sprintf("%s%s%s", *ms, **ms ? "," : "", MapToUserString(QAM_64, ModulationValues)); }
1378  if (frontendInfo.caps & FE_CAN_QAM_128) { numModulations++; ms = cString::sprintf("%s%s%s", *ms, **ms ? "," : "", MapToUserString(QAM_128, ModulationValues)); }
1379  if (frontendInfo.caps & FE_CAN_QAM_256) { numModulations++; ms = cString::sprintf("%s%s%s", *ms, **ms ? "," : "", MapToUserString(QAM_256, ModulationValues)); }
1380  if (frontendInfo.caps & FE_CAN_8VSB) { numModulations++; ms = cString::sprintf("%s%s%s", *ms, **ms ? "," : "", MapToUserString(VSB_8, ModulationValues)); }
1381  if (frontendInfo.caps & FE_CAN_16VSB) { numModulations++; ms = cString::sprintf("%s%s%s", *ms, **ms ? "," : "", MapToUserString(VSB_16, ModulationValues)); }
1382  if (frontendInfo.caps & FE_CAN_TURBO_FEC) { numModulations++; ms = cString::sprintf("%s%s%s", *ms, **ms ? "," : "", "TURBO_FEC"); }
1383  if (!**ms)
1384  ms = "unknown modulations";
1385  isyslog("frontend %d/%d provides %s with %s (\"%s\")", adapter, frontend, *ds, *ms, frontendInfo.name);
1386  return true;
1387  }
1388  else
1389  esyslog("ERROR: frontend %d/%d doesn't provide any delivery systems", adapter, frontend);
1390  return false;
1391 }
1392 
1393 bool cDvbDevice::BondDevices(const char *Bondings)
1394 {
1395  UnBondDevices();
1396  if (Bondings) {
1397  cSatCableNumbers SatCableNumbers(MAXDEVICES, Bondings);
1398  for (int i = 0; i < cDevice::NumDevices(); i++) {
1399  int d = SatCableNumbers.FirstDeviceIndex(i);
1400  if (d >= 0) {
1401  int ErrorDevice = 0;
1402  if (cDevice *Device1 = cDevice::GetDevice(i)) {
1403  if (Device1->HasSubDevice())
1404  Device1 = Device1->SubDevice();
1405  if (cDevice *Device2 = cDevice::GetDevice(d)) {
1406  if (Device2->HasSubDevice())
1407  Device2 = Device2->SubDevice();
1408  if (cDvbDevice *DvbDevice1 = dynamic_cast<cDvbDevice *>(Device1)) {
1409  if (cDvbDevice *DvbDevice2 = dynamic_cast<cDvbDevice *>(Device2)) {
1410  if (!DvbDevice1->Bond(DvbDevice2))
1411  return false; // Bond() has already logged the error
1412  }
1413  else
1414  ErrorDevice = d + 1;
1415  }
1416  else
1417  ErrorDevice = i + 1;
1418  if (ErrorDevice) {
1419  esyslog("ERROR: device '%d' in device bondings '%s' is not a cDvbDevice", ErrorDevice, Bondings);
1420  return false;
1421  }
1422  }
1423  else
1424  ErrorDevice = d + 1;
1425  }
1426  else
1427  ErrorDevice = i + 1;
1428  if (ErrorDevice) {
1429  esyslog("ERROR: unknown device '%d' in device bondings '%s'", ErrorDevice, Bondings);
1430  return false;
1431  }
1432  }
1433  }
1434  }
1435  return true;
1436 }
1437 
1439 {
1440  for (int i = 0; i < cDevice::NumDevices(); i++) {
1441  cDevice *dev = cDevice::GetDevice(i);
1442  if (dev && dev->HasSubDevice())
1443  dev = dev->SubDevice();
1444  if (cDvbDevice *d = dynamic_cast<cDvbDevice *>(dev))
1445  d->UnBond();
1446  }
1447 }
1448 
1450 {
1451  cMutexLock MutexLock(&bondMutex);
1452  if (!bondedDevice) {
1453  if (Device != this) {
1454  if ((ProvidesDeliverySystem(SYS_DVBS) || ProvidesDeliverySystem(SYS_DVBS2)) && (Device->ProvidesDeliverySystem(SYS_DVBS) || Device->ProvidesDeliverySystem(SYS_DVBS2))) {
1455  if (dvbTuner && Device->dvbTuner && dvbTuner->Bond(Device->dvbTuner)) {
1456  bondedDevice = Device->bondedDevice ? Device->bondedDevice : Device;
1457  Device->bondedDevice = this;
1458  dsyslog("device %d bonded with device %d", CardIndex() + 1, bondedDevice->CardIndex() + 1);
1459  return true;
1460  }
1461  }
1462  else
1463  esyslog("ERROR: can't bond device %d with device %d (only DVB-S(2) devices can be bonded)", CardIndex() + 1, Device->CardIndex() + 1);
1464  }
1465  else
1466  esyslog("ERROR: can't bond device %d with itself", CardIndex() + 1);
1467  }
1468  else
1469  esyslog("ERROR: device %d already bonded with device %d, can't bond with device %d", CardIndex() + 1, bondedDevice->CardIndex() + 1, Device->CardIndex() + 1);
1470  return false;
1471 }
1472 
1474 {
1475  cMutexLock MutexLock(&bondMutex);
1476  if (cDvbDevice *d = bondedDevice) {
1477  if (dvbTuner)
1478  dvbTuner->UnBond();
1479  dsyslog("device %d unbonded from device %d", CardIndex() + 1, bondedDevice->CardIndex() + 1);
1480  while (d->bondedDevice != this)
1481  d = d->bondedDevice;
1482  if (d == bondedDevice)
1483  d->bondedDevice = NULL;
1484  else
1485  d->bondedDevice = bondedDevice;
1486  bondedDevice = NULL;
1487  }
1488 }
1489 
1490 bool cDvbDevice::BondingOk(const cChannel *Channel, bool ConsiderOccupied) const
1491 {
1492  cMutexLock MutexLock(&bondMutex);
1493  if (bondedDevice || Positioner())
1494  return dvbTuner && dvbTuner->BondingOk(Channel, ConsiderOccupied);
1495  return true;
1496 }
1497 
1498 bool cDvbDevice::SetIdleDevice(bool Idle, bool TestOnly)
1499 {
1500  if (TestOnly) {
1501  if (ciAdapter)
1502  return ciAdapter->SetIdle(Idle, true);
1503  return true;
1504  }
1505  if (!dvbTuner->SetIdle(Idle))
1506  return false;
1507  if (ciAdapter && !ciAdapter->SetIdle(Idle, false)) {
1508  dvbTuner->SetIdle(!Idle);
1509  return false;
1510  }
1511  if (Idle)
1513  else
1515  return true;
1516 }
1517 
1519 {
1520  return ciAdapter;
1521 }
1522 
1523 bool cDvbDevice::SetPid(cPidHandle *Handle, int Type, bool On)
1524 {
1525  if (Handle->pid) {
1526  dmx_pes_filter_params pesFilterParams;
1527  memset(&pesFilterParams, 0, sizeof(pesFilterParams));
1528  if (On) {
1529  if (Handle->handle < 0) {
1530  Handle->handle = DvbOpen(DEV_DVB_DEMUX, adapter, frontend, O_RDWR | O_NONBLOCK, true);
1531  if (Handle->handle < 0) {
1532  LOG_ERROR;
1533  return false;
1534  }
1535  }
1536  pesFilterParams.pid = Handle->pid;
1537  pesFilterParams.input = DMX_IN_FRONTEND;
1538  pesFilterParams.output = DMX_OUT_TS_TAP;
1539  pesFilterParams.pes_type= DMX_PES_OTHER;
1540  pesFilterParams.flags = DMX_IMMEDIATE_START;
1541  if (ioctl(Handle->handle, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
1542  LOG_ERROR;
1543  return false;
1544  }
1545  }
1546  else if (!Handle->used) {
1547  CHECK(ioctl(Handle->handle, DMX_STOP));
1548  if (Type <= ptTeletext) {
1549  pesFilterParams.pid = 0x1FFF;
1550  pesFilterParams.input = DMX_IN_FRONTEND;
1551  pesFilterParams.output = DMX_OUT_DECODER;
1552  pesFilterParams.pes_type= DMX_PES_OTHER;
1553  pesFilterParams.flags = DMX_IMMEDIATE_START;
1554  CHECK(ioctl(Handle->handle, DMX_SET_PES_FILTER, &pesFilterParams));
1555  }
1556  close(Handle->handle);
1557  Handle->handle = -1;
1558  }
1559  }
1560  return true;
1561 }
1562 
1563 int cDvbDevice::OpenFilter(u_short Pid, u_char Tid, u_char Mask)
1564 {
1566  int f = open(FileName, O_RDWR | O_NONBLOCK);
1567  if (f >= 0) {
1568  dmx_sct_filter_params sctFilterParams;
1569  memset(&sctFilterParams, 0, sizeof(sctFilterParams));
1570  sctFilterParams.pid = Pid;
1571  sctFilterParams.timeout = 0;
1572  sctFilterParams.flags = DMX_IMMEDIATE_START;
1573  sctFilterParams.filter.filter[0] = Tid;
1574  sctFilterParams.filter.mask[0] = Mask;
1575  if (ioctl(f, DMX_SET_FILTER, &sctFilterParams) >= 0)
1576  return f;
1577  else {
1578  esyslog("ERROR: can't set filter (pid=%d, tid=%02X, mask=%02X): %m", Pid, Tid, Mask);
1579  close(f);
1580  }
1581  }
1582  else
1583  esyslog("ERROR: can't open filter handle on '%s'", *FileName);
1584  return -1;
1585 }
1586 
1587 void cDvbDevice::CloseFilter(int Handle)
1588 {
1589  close(Handle);
1590 }
1591 
1592 bool cDvbDevice::ProvidesDeliverySystem(int DeliverySystem) const
1593 {
1594  for (int i = 0; i < numDeliverySystems; i++) {
1595  if (deliverySystems[i] == DeliverySystem)
1596  return true;
1597  }
1598  return false;
1599 }
1600 
1601 bool cDvbDevice::ProvidesSource(int Source) const
1602 {
1603  int type = Source & cSource::st_Mask;
1604  return type == cSource::stNone
1605  || type == cSource::stAtsc && ProvidesDeliverySystem(SYS_ATSC)
1606  || type == cSource::stCable && (ProvidesDeliverySystem(SYS_DVBC_ANNEX_AC) || ProvidesDeliverySystem(SYS_DVBC_ANNEX_B))
1607  || type == cSource::stSat && (ProvidesDeliverySystem(SYS_DVBS) || ProvidesDeliverySystem(SYS_DVBS2))
1609 }
1610 
1611 bool cDvbDevice::ProvidesTransponder(const cChannel *Channel) const
1612 {
1613  if (!ProvidesSource(Channel->Source()))
1614  return false; // doesn't provide source
1615  cDvbTransponderParameters dtp(Channel->Parameters());
1616  if (!ProvidesDeliverySystem(GetRequiredDeliverySystem(Channel, &dtp)) ||
1617  dtp.StreamId() != 0 && !(frontendInfo.caps & FE_CAN_MULTISTREAM) ||
1618  dtp.Modulation() == QPSK && !(frontendInfo.caps & FE_CAN_QPSK) ||
1619  dtp.Modulation() == QAM_16 && !(frontendInfo.caps & FE_CAN_QAM_16) ||
1620  dtp.Modulation() == QAM_32 && !(frontendInfo.caps & FE_CAN_QAM_32) ||
1621  dtp.Modulation() == QAM_64 && !(frontendInfo.caps & FE_CAN_QAM_64) ||
1622  dtp.Modulation() == QAM_128 && !(frontendInfo.caps & FE_CAN_QAM_128) ||
1623  dtp.Modulation() == QAM_256 && !(frontendInfo.caps & FE_CAN_QAM_256) ||
1624  dtp.Modulation() == QAM_AUTO && !(frontendInfo.caps & FE_CAN_QAM_AUTO) ||
1625  dtp.Modulation() == VSB_8 && !(frontendInfo.caps & FE_CAN_8VSB) ||
1626  dtp.Modulation() == VSB_16 && !(frontendInfo.caps & FE_CAN_16VSB) ||
1627  dtp.Modulation() == PSK_8 && !(frontendInfo.caps & FE_CAN_TURBO_FEC) && dtp.System() == SYS_DVBS) // "turbo fec" is a non standard FEC used by North American broadcasters - this is a best guess to determine this condition
1628  return false; // requires modulation system which frontend doesn't provide
1629  if (!cSource::IsSat(Channel->Source()) ||
1630  (!Setup.DiSEqC || Diseqcs.Get(CardIndex() + 1, Channel->Source(), Channel->Frequency(), dtp.Polarization(), NULL)))
1631  return DeviceHooksProvidesTransponder(Channel);
1632  return false;
1633 }
1634 
1635 bool cDvbDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) const
1636 {
1637  bool result = false;
1638  bool hasPriority = Priority == IDLEPRIORITY || Priority > this->Priority();
1639  bool needsDetachReceivers = false;
1641 
1642  if (dvbTuner && ProvidesTransponder(Channel)) {
1643  result = hasPriority;
1644  if (Priority > IDLEPRIORITY) {
1645  if (Receiving()) {
1646  if (dvbTuner->IsTunedTo(Channel)) {
1647  if (Channel->Vpid() && !HasPid(Channel->Vpid()) || Channel->Apid(0) && !HasPid(Channel->Apid(0)) || Channel->Dpid(0) && !HasPid(Channel->Dpid(0))) {
1648  if (CamSlot() && Channel->Ca() >= CA_ENCRYPTED_MIN) {
1649  if (CamSlot()->CanDecrypt(Channel))
1650  result = true;
1651  else
1652  needsDetachReceivers = true;
1653  }
1654  else
1655  result = true;
1656  }
1657  else
1658  result = true;
1659  }
1660  else
1661  needsDetachReceivers = Receiving();
1662  }
1663  if (result) {
1664  cMutexLock MutexLock(&bondMutex);
1665  if (!BondingOk(Channel)) {
1666  // This device is bonded, so we need to check the priorities of the others:
1667  for (cDvbDevice *d = bondedDevice; d && d != this; d = d->bondedDevice) {
1668  if (d->Priority() >= Priority) {
1669  result = false;
1670  break;
1671  }
1672  needsDetachReceivers |= d->Receiving();
1673  }
1675  needsDetachReceivers |= Receiving();
1676  }
1677  }
1678  }
1679  }
1680  if (NeedsDetachReceivers)
1681  *NeedsDetachReceivers = needsDetachReceivers;
1682  return result;
1683 }
1684 
1685 bool cDvbDevice::ProvidesEIT(void) const
1686 {
1687  return !IsIdle() && (dvbTuner != NULL) && !dvbTuner->IsIdle() && ((ciAdapter == NULL) || !ciAdapter->IsIdle());
1688 }
1689 
1691 {
1693 }
1694 
1696 {
1697  return dvbTuner ? dvbTuner->Positioner() : NULL;
1698 }
1699 
1701 {
1702  return dvbTuner ? dvbTuner->GetSignalStrength() : -1;
1703 }
1704 
1706 {
1707  return dvbTuner ? dvbTuner->GetSignalQuality() : -1;
1708 }
1709 
1711 {
1712  return dvbTuner ? dvbTuner->GetTransponder() : NULL;
1713 }
1714 
1715 bool cDvbDevice::IsTunedToTransponder(const cChannel *Channel) const
1716 {
1717  return dvbTuner ? dvbTuner->IsTunedTo(Channel) : false;
1718 }
1719 
1720 bool cDvbDevice::MaySwitchTransponder(const cChannel *Channel) const
1721 {
1722  return BondingOk(Channel, true) && cDevice::MaySwitchTransponder(Channel);
1723 }
1724 
1725 bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
1726 {
1727  if (dvbTuner)
1728  dvbTuner->SetChannel(Channel);
1729  return true;
1730 }
1731 
1732 bool cDvbDevice::HasLock(int TimeoutMs) const
1733 {
1734  return dvbTuner ? dvbTuner->Locked(TimeoutMs) : false;
1735 }
1736 
1738 {
1740 }
1741 
1743 {
1744  CloseDvr();
1745  fd_dvr = DvbOpen(DEV_DVB_DVR, adapter, frontend, O_RDONLY | O_NONBLOCK, true);
1746  if (fd_dvr >= 0)
1747  tsBuffer = new cTSBuffer(fd_dvr, MEGABYTE(5), CardIndex() + 1);
1748  return fd_dvr >= 0;
1749 }
1750 
1752 {
1753  if (fd_dvr >= 0) {
1754  delete tsBuffer;
1755  tsBuffer = NULL;
1756  close(fd_dvr);
1757  fd_dvr = -1;
1758  }
1759 }
1760 
1762 {
1763  if (tsBuffer) {
1764  if (cCamSlot *cs = CamSlot()) {
1765  if (cs->WantsTsData()) {
1766  int Available;
1767  Data = tsBuffer->Get(&Available);
1768  if (Data) {
1769  Data = cs->Decrypt(Data, Available);
1770  tsBuffer->Skip(Available);
1771  }
1772  return true;
1773  }
1774  }
1775  Data = tsBuffer->Get();
1776  return true;
1777  }
1778  return false;
1779 }
1780 
1782 {
1783  cMutexLock MutexLock(&bondMutex);
1784  cDvbDevice *d = this;
1785  do {
1786  d->cDevice::DetachAllReceivers();
1787  d = d->bondedDevice;
1788  } while (d && d != this && needsDetachBondedReceivers);
1790 }
1791 
1792 // --- cDvbDeviceProbe -------------------------------------------------------
1793 
1795 
1797 {
1798  DvbDeviceProbes.Add(this);
1799 }
1800 
1802 {
1803  DvbDeviceProbes.Del(this, false);
1804 }
1805 
1807 {
1808  uint32_t SubsystemId = 0;
1809  cString FileName = cString::sprintf("/dev/dvb/adapter%d/frontend%d", Adapter, Frontend);
1810  struct stat st;
1811  if (stat(FileName, &st) == 0) {
1812  cReadDir d("/sys/class/dvb");
1813  if (d.Ok()) {
1814  struct dirent *e;
1815  while ((e = d.Next()) != NULL) {
1816  if (strstr(e->d_name, "frontend")) {
1817  FileName = cString::sprintf("/sys/class/dvb/%s/dev", e->d_name);
1818  if (FILE *f = fopen(FileName, "r")) {
1819  cReadLine ReadLine;
1820  char *s = ReadLine.Read(f);
1821  fclose(f);
1822  unsigned Major;
1823  unsigned Minor;
1824  if (s && 2 == sscanf(s, "%u:%u", &Major, &Minor)) {
1825  if (((Major << 8) | Minor) == st.st_rdev) {
1826  FileName = cString::sprintf("/sys/class/dvb/%s/device/subsystem_vendor", e->d_name);
1827  if ((f = fopen(FileName, "r")) != NULL) {
1828  if (char *s = ReadLine.Read(f))
1829  SubsystemId = strtoul(s, NULL, 0) << 16;
1830  fclose(f);
1831  }
1832  else {
1833  FileName = cString::sprintf("/sys/class/dvb/%s/device/idVendor", e->d_name);
1834  if ((f = fopen(FileName, "r")) != NULL) {
1835  if (char *s = ReadLine.Read(f))
1836  SubsystemId = strtoul(s, NULL, 16) << 16;
1837  fclose(f);
1838  }
1839  }
1840  FileName = cString::sprintf("/sys/class/dvb/%s/device/subsystem_device", e->d_name);
1841  if ((f = fopen(FileName, "r")) != NULL) {
1842  if (char *s = ReadLine.Read(f))
1843  SubsystemId |= strtoul(s, NULL, 0);
1844  fclose(f);
1845  }
1846  else {
1847  FileName = cString::sprintf("/sys/class/dvb/%s/device/idProduct", e->d_name);
1848  if ((f = fopen(FileName, "r")) != NULL) {
1849  if (char *s = ReadLine.Read(f))
1850  SubsystemId |= strtoul(s, NULL, 16);
1851  fclose(f);
1852  }
1853  }
1854  break;
1855  }
1856  }
1857  }
1858  }
1859  }
1860  }
1861  }
1862  return SubsystemId;
1863 }
static unsigned int FrequencyToHz(unsigned int f)
Definition: dvbdevice.c:695
#define SETCMD(c, d)
#define DVB_SYSTEM_1
Definition: dvbdevice.c:96
struct dirent * Next(void)
Definition: tools.c:1466
int lastSource
Definition: dvbdevice.c:315
virtual ~cDvbDeviceProbe()
Definition: dvbdevice.c:1801
cDiseqcs Diseqcs
Definition: diseqc.c:439
static bool UseDevice(int n)
Tells whether the device with the given card index shall be used in this instance of VDR...
Definition: device.h:130
const char * DeliverySystemNames[]
Definition: dvbdevice.c:1120
virtual ~cDvbTuner()
Definition: dvbdevice.c:387
cDvbTransponderParameters(const char *Parameters=NULL)
Definition: dvbdevice.c:202
unsigned char uchar
Definition: tools.h:30
virtual ~cDvbDevice()
Definition: dvbdevice.c:1181
void Lock(void)
Definition: thread.c:191
virtual bool ProvidesSource(int Source) const
Returns true if this device can provide the given source.
Definition: dvbdevice.c:1601
int PrintParameter(char *p, char Name, int Value) const
Definition: dvbdevice.c:222
virtual cString DeviceType(void) const
Returns a string identifying the type of this device (like "DVB-S").
Definition: dvbdevice.c:1235
bool IsBondedMaster(void) const
Definition: dvbdevice.c:328
uchar * Get(int *Available=NULL)
Returns a pointer to the first TS packet in the buffer.
Definition: device.c:1857
virtual bool SetIdle(bool Idle, bool TestOnly)
Definition: ci.h:120
int Vpid(void) const
Definition: channels.h:154
#define DEV_DVB_BASE
Definition: dvbdevice.h:73
static bool Exists(int Adapter, int Frontend)
Checks whether the given adapter/frontend exists.
Definition: dvbdevice.c:1205
int Number(void) const
Definition: channels.h:179
bool IsScr(void) const
Returns true if this DiSEqC sequence uses Satellite Channel Routing.
Definition: diseqc.h:132
cPositioner * positioner
Definition: dvbdevice.c:316
void ResetToneAndVoltage(void)
Definition: dvbdevice.c:768
#define SCR_RANDOM_TIMEOUT
Definition: dvbdevice.c:35
#define dsyslog(a...)
Definition: tools.h:36
cString AddDirectory(const char *DirName, const char *FileName)
Definition: tools.c:350
#define CA_ENCRYPTED_MIN
Definition: channels.h:48
bool Receiving(bool Dummy=false) const
Returns true if we are currently receiving. The parameter has no meaning (for backwards compatibility...
Definition: device.c:1634
friend class cDvbSourceParam
Definition: dvbdevice.h:108
void Set(int Ms=0)
Definition: tools.c:738
const char * ParseParameter(const char *s, int &Value, const tDvbParameterMap *Map=NULL)
Definition: dvbdevice.c:251
virtual bool IsTunedToTransponder(const cChannel *Channel) const
Returns true if this device is currently tuned to the given Channel&#39;s transponder.
Definition: dvbdevice.c:1715
int Position(void) const
Indicates which positioning mode to use in order to move the dish to a given satellite position...
Definition: diseqc.h:126
static bool Initialize(void)
Initializes the DVB devices.
Definition: dvbdevice.c:1251
virtual bool GetTSPacket(uchar *&Data)
Gets exactly one TS packet from the DVR of this device and returns a pointer to it in Data...
Definition: dvbdevice.c:1761
#define LOG_ERROR
Definition: tools.h:38
cDvbTuner * dvbTuner
Definition: dvbdevice.h:237
#define DVBT_TUNE_TIMEOUT
Definition: dvbdevice.c:30
int UserIndex(int Value, const tDvbParameterMap *Map)
Definition: dvbdevice.c:151
void Add(cListObject *Object, cListObject *After=NULL)
Definition: tools.c:2014
virtual const cPositioner * Positioner(void) const
Returns a pointer to the positioner (if any) this device has used to move the satellite dish to the r...
Definition: dvbdevice.c:1695
int fd_dvr
Definition: dvbdevice.h:188
int fd_frontend
Definition: dvbdevice.c:306
void UnBond(void)
Removes this device from any bonding it might have with other devices.
Definition: dvbdevice.c:1473
cTSBuffer * tsBuffer
< Controls how the DVB device handles Transfer Mode when replaying Dolby Digital audio.
Definition: dvbdevice.h:287
#define DVBC_TUNE_TIMEOUT
Definition: dvbdevice.c:28
int Ca(int Index=0) const
Definition: channels.h:173
void ClearEventQueue(void) const
Definition: dvbdevice.c:545
bool DeviceHooksProvidesTransponder(const cChannel *Channel) const
Definition: device.c:680
int Dpid(int i) const
Definition: channels.h:161
virtual int SignalQuality(void) const
Returns the "quality" of the currently received signal.
Definition: dvbdevice.c:1705
virtual cOsdItem * GetOsdItem(void)
Returns all the OSD items necessary for editing the source specific parameters of the channel that wa...
Definition: dvbdevice.c:1087
#define DVBS_LOCK_TIMEOUT
Definition: dvbdevice.c:27
virtual void GotoPosition(uint Number, int Longitude)
Move the dish to the satellite position stored under the given Number.
Definition: positioner.c:100
void ExecuteDiseqc(const cDiseqc *Diseqc, unsigned int *Frequency)
Definition: dvbdevice.c:711
static cString sprintf(const char *fmt,...) __attribute__((format(printf
Definition: tools.c:1080
#define DVBC_LOCK_TIMEOUT
Definition: dvbdevice.c:29
int Adapter(void) const
Definition: dvbdevice.h:196
const tDvbParameterMap SystemValuesSat[]
Definition: dvbdevice.c:99
virtual void Append(T Data)
Definition: tools.h:571
#define DVBT_LOCK_TIMEOUT
Definition: dvbdevice.c:31
cDvbDeviceProbe(void)
Definition: dvbdevice.c:1796
static uint32_t GetSubsystemId(int Adapter, int Frontend)
Definition: dvbdevice.c:1806
const tDvbParameterMap InversionValues[]
Definition: dvbdevice.c:46
#define MAXDEVICES
Definition: device.h:29
#define esyslog(a...)
Definition: tools.h:34
int Srate(void) const
Definition: channels.h:153
bool Parse(const char *s)
Definition: dvbdevice.c:267
int frontend
Definition: dvbdevice.c:307
static cDevice * GetDevice(int Index)
Gets the device with the given Index.
Definition: device.c:261
virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView)
Sets the device to the given channel (actual physical setup).
Definition: dvbdevice.c:1725
bool SetIdle(bool Idle)
Definition: dvbdevice.c:1020
#define LOG_ERROR_STR(s)
Definition: tools.h:39
eDiseqcActions Execute(const char **CurrentAction, uchar *Codes, uint8_t *MaxCodes, const cScr *Scr, uint *Frequency) const
Parses the DiSEqC commands and returns the appropriate action code with every call.
Definition: diseqc.c:402
Definition: tools.h:489
int frontendType
Definition: dvbdevice.c:304
static int NumDevices(void)
Returns the total number of devices.
Definition: device.h:118
#define DEV_DVB_ADAPTER
Definition: dvbdevice.h:74
bool IsTunedTo(const cChannel *Channel) const
Definition: dvbdevice.c:490
#define TUNER_POLL_TIMEOUT
Definition: dvbdevice.c:298
void DelLivePids(void)
Deletes the live viewing PIDs.
Definition: device.c:600
int GetSignalStrength(void) const
Definition: dvbdevice.c:572
int Transponder(void) const
Returns the transponder frequency in MHz, plus the polarization in case of sat.
Definition: channels.c:157
cDvbTuner * GetBondedMaster(void)
Definition: dvbdevice.c:469
cString ToString(char Type) const
Definition: dvbdevice.c:227
bool Poll(int TimeoutMs=0)
Definition: tools.c:1443
uint32_t subsystemId
Definition: dvbdevice.c:308
int MapToDriver(int Value, const tDvbParameterMap *Map)
Definition: dvbdevice.c:192
bool isIdle
Definition: dvbdevice.c:337
int adapter
Definition: dvbdevice.c:307
char * Read(FILE *f)
Definition: tools.c:1398
bool QueryDeliverySystems(int fd_frontend)
Definition: dvbdevice.c:1309
cPositioner * GetPositioner(void)
Definition: dvbdevice.c:702
Definition: diseqc.h:62
const char * Parameters(void) const
Definition: channels.h:182
bool needsDetachBondedReceivers
Definition: dvbdevice.h:191
static int NextCardIndex(int n=0)
Calculates the next card index.
Definition: device.c:185
bool SetTransponderData(int Source, int Frequency, int Srate, const char *Parameters, bool Quiet=false)
Definition: channels.c:196
static cPositioner * GetPositioner(void)
Returns a previously created positioner.
Definition: positioner.c:133
int frontend
Definition: dvbdevice.h:182
int LnbFrequLo
Definition: config.h:272
A steerable satellite dish generally points to the south on the northern hemisphere, and to the north on the southern hemisphere (unless you&#39;re located directly on the equator, in which case the general direction is "up").
Definition: positioner.h:31
cMutex mutex
Definition: dvbdevice.c:320
static int DvbApiVersion
Definition: dvbdevice.c:24
virtual void GotoAngle(int Longitude)
Move the dish to the given angular position.
Definition: positioner.c:107
cCamSlot * CamSlot(void) const
Returns the CAM slot that is currently used with this device, or NULL if no CAM slot is in use...
Definition: device.h:833
cCondVar newSet
Definition: dvbdevice.c:322
virtual bool MaySwitchTransponder(const cChannel *Channel) const
Returns true if it is ok to switch to the Channel&#39;s transponder on this device, without disturbing an...
Definition: device.c:745
cDvbDevice(int Adapter, int Frontend, cDevice *ParentDevice=NULL)
Definition: dvbdevice.c:1142
const tDvbParameterMap HierarchyValues[]
Definition: dvbdevice.c:134
#define IDLEPRIORITY
Definition: config.h:47
const char * Name(void) const
Definition: channels.c:122
int Frontend(void) const
Definition: dvbdevice.h:197
cCiAdapter * ciAdapter
Definition: dvbdevice.h:232
void StartSectionHandler(void)
A derived device that provides section data must call this function (typically in its constructor) to...
Definition: device.c:608
int Source(void) const
Definition: channels.h:152
static bool BondDevices(const char *Bondings)
Bonds the devices as defined in the given Bondings string.
Definition: dvbdevice.c:1393
#define trNOOP(s)
Definition: i18n.h:88
#define CHECK(s)
Definition: tools.h:50
cChannel channel
Definition: dvbdevice.c:312
static bool Probe(int Adapter, int Frontend)
Probes for existing DVB devices.
Definition: dvbdevice.c:1222
bool bondedMaster
Definition: dvbdevice.c:324
T constrain(T v, T l, T h)
Definition: tools.h:60
virtual bool SetPid(cPidHandle *Handle, int Type, bool On)
Does the actual PID setting on this device.
Definition: dvbdevice.c:1523
uint32_t SubsystemId(void) const
Definition: dvbdevice.c:348
void StopSectionHandler(void)
A device that has called StartSectionHandler() must call this function (typically in its destructor) ...
Definition: device.c:623
int numModulations
Definition: dvbdevice.h:187
const cScr * scr
Definition: dvbdevice.c:317
#define MAXDELIVERYSYSTEMS
Definition: dvbdevice.h:70
virtual bool CanDecrypt(const cChannel *Channel)
Returns true if there is a CAM in this slot that is able to decrypt the given Channel (or at least cl...
Definition: ci.c:2163
static cMutex bondMutex
Definition: dvbdevice.c:302
virtual void SetData(cChannel *Channel)
Sets all source specific parameters to those of the given Channel.
Definition: dvbdevice.c:1075
cDvbDevice * bondedDevice
Definition: dvbdevice.h:190
cDvbSourceParam(char Source, const char *Description)
Definition: dvbdevice.c:1068
int LnbSLOF
Definition: config.h:271
int MapToUser(int Value, const tDvbParameterMap *Map, const char **String)
Definition: dvbdevice.c:173
bool TimedOut(void) const
Definition: tools.c:743
virtual bool IsMoving(void) const
Returns true if the dish is currently moving as a result of a call to GotoPosition() or GotoAngle()...
Definition: positioner.c:127
#define DVBAPIVERSION
Definition: dvbdevice.h:17
cList< cDvbDeviceProbe > DvbDeviceProbes
Definition: dvbdevice.c:1794
static cMutex bondMutex
Definition: dvbdevice.h:189
virtual cString DeviceName(void) const
Returns a string identifying the name of this device.
Definition: dvbdevice.c:1246
virtual void CloseDvr(void)
Shuts down the DVR.
Definition: dvbdevice.c:1751
#define DEV_DVB_FRONTEND
Definition: dvbdevice.h:76
#define DVBS_TUNE_TIMEOUT
Definition: dvbdevice.c:26
virtual void CloseFilter(int Handle)
Closes a file handle that has previously been opened by OpenFilter().
Definition: dvbdevice.c:1587
static bool IsSat(int Code)
Definition: sources.h:57
bool Ok(void)
Definition: tools.h:379
#define DEV_DVB_CA
Definition: dvbdevice.h:81
bool HasSubDevice(void) const
Definition: device.h:837
cSetup Setup
Definition: config.c:372
int DriverIndex(int Value, const tDvbParameterMap *Map)
Definition: dvbdevice.c:162
int adapter
Definition: dvbdevice.h:182
#define MAXFRONTENDCMDS
void UnBond(void)
Definition: dvbdevice.c:420
Definition: ci.h:131
#define ATSC_LOCK_TIMEOUT
Definition: dvbdevice.c:33
bool OpenFrontend(void) const
Definition: dvbdevice.c:1030
const tDvbParameterMap ModulationValues[]
Definition: dvbdevice.c:79
int deliverySystems[MAXDELIVERYSYSTEMS]
Definition: dvbdevice.h:185
bool lnbPowerTurnedOn
Definition: dvbdevice.c:318
Definition: thread.h:63
bool Locked(int TimeoutMs=0)
Definition: dvbdevice.c:533
static cDvbCiAdapter * CreateCiAdapter(cDevice *Device, int Fd, int Adapter=-1, int Frontend=-1)
Definition: dvbci.c:145
int Frequency(void) const
Returns the actual frequency, as given in &#39;channels.conf&#39;.
Definition: channels.h:149
#define DVB_SYSTEM_2
Definition: dvbdevice.c:97
int Size(void) const
Definition: tools.h:551
cDevice * parentDevice
Definition: device.h:823
void Skip(int Count)
If after a call to Get() more or less than TS_SIZE of the available data has been processed...
Definition: device.c:1885
virtual bool OpenDvr(void)
Opens the DVR of this device and prepares it to deliver a Transport Stream for use in a cReceiver...
Definition: dvbdevice.c:1742
int LnbFrequHi
Definition: config.h:273
#define DEV_DVB_DVR
Definition: dvbdevice.h:77
int GetSignalQuality(void) const
Definition: dvbdevice.c:601
bool IsIdle(void) const
Definition: dvbdevice.c:357
int diseqcOffset
Definition: dvbdevice.c:314
bool Bond(cDvbTuner *Tuner)
Definition: dvbdevice.c:404
virtual void DetachAllReceivers(void)
Detaches all receivers from this device.
Definition: dvbdevice.c:1781
static void UnBondDevices(void)
Unbonds all devices.
Definition: dvbdevice.c:1438
#define DTV_ENUM_DELSYS
Definition: dvbdevice.h:57
const char * MapToUserString(int Value, const tDvbParameterMap *Map)
Definition: dvbdevice.c:184
virtual const cChannel * GetCurrentlyTunedTransponder(void) const
Returns a pointer to the currently tuned transponder.
Definition: dvbdevice.c:1710
virtual bool HasCi(void)
Returns true if this device has a Common Interface.
Definition: dvbdevice.c:1518
int CardIndex(void) const
Returns the card index of this device (0 ... MAXDEVICES - 1).
Definition: device.h:831
const tDvbParameterMap PilotValues[]
Definition: dvbdevice.c:39
int Priority(void) const
Returns the priority of the current receiving session (-MAXPRIORITY..MAXPRIORITY), or IDLEPRIORITY if no receiver is currently active.
Definition: device.c:1614
virtual bool HasLock(int TimeoutMs=0) const
Returns true if the device has a lock on the requested transponder.
Definition: dvbdevice.c:1732
virtual int NumProvidedSystems(void) const
Returns the number of individual "delivery systems" this device provides.
Definition: dvbdevice.c:1690
dvb_frontend_info frontendInfo
Definition: dvbdevice.h:184
int FrontendType(void) const
Definition: dvbdevice.c:343
bool IsSat(void) const
Definition: channels.h:187
#define MEGABYTE(n)
Definition: tools.h:44
char Source(void) const
Definition: sourceparams.h:31
eTunerStatus tunerStatus
Definition: dvbdevice.c:319
virtual bool IsIdle(void) const
Definition: ci.h:121
const cDiseqc * lastDiseqc
Definition: dvbdevice.c:313
static int GetRequiredDeliverySystem(const cChannel *Channel, const cDvbTransponderParameters *Dtp)
Definition: dvbdevice.c:774
void Del(cListObject *Object, bool DeleteObject=true)
Definition: tools.c:2046
cDvbTuner(const cDvbDevice *Device, int Fd_Frontend, int Adapter, int Frontend)
Definition: dvbdevice.c:362
int FirstDeviceIndex(int DeviceIndex) const
Returns the first device index (starting at 0) that uses the same sat cable number as the device with...
Definition: config.c:116
virtual bool ProvidesDeliverySystem(int DeliverySystem) const
Definition: dvbdevice.c:1592
const tDvbParameterMap RollOffValues[]
Definition: dvbdevice.c:143
bool IsTerr(void) const
Definition: channels.h:188
static cDevice * PrimaryDevice(void)
Returns the primary device.
Definition: device.h:137
static int setTransferModeForDolbyDigital
Definition: dvbdevice.h:275
Definition: diseqc.h:34
const tDvbParameterMap CoderateValues[]
Definition: dvbdevice.c:63
int Apid(int i) const
Definition: channels.h:160
#define tr(s)
Definition: i18n.h:85
unsigned char u_char
Definition: headers.h:24
bool CloseFrontend(void)
Definition: dvbdevice.c:1042
bool Bond(cDvbDevice *Device)
Bonds this device with the given Device, making both of them use the same satellite cable and LNB...
Definition: dvbdevice.c:1449
const cPositioner * Positioner(void) const
Definition: dvbdevice.c:352
#define DEV_DVB_DEMUX
Definition: dvbdevice.h:78
const cChannel * GetTransponder(void) const
Definition: dvbdevice.c:347
virtual bool ProvidesTransponder(const cChannel *Channel) const
Returns true if this device can provide the transponder of the given Channel (which implies that it c...
Definition: dvbdevice.c:1611
#define ST(s)
#define isyslog(a...)
Definition: tools.h:35
eDiseqcActions
Definition: diseqc.h:64
const cDiseqc * Get(int Device, int Source, int Frequency, char Polarization, const cScr **Scr) const
Selects a DiSEqC entry suitable for the given Device and tuning parameters.
Definition: diseqc.c:447
Definition: thread.h:77
virtual bool ProvidesChannel(const cChannel *Channel, int Priority=IDLEPRIORITY, bool *NeedsDetachReceivers=NULL) const
Returns true if this device can provide the given channel.
Definition: dvbdevice.c:1635
bool SetFrontend(void)
Definition: dvbdevice.c:790
void Sort(bool IgnoreCase=false)
Definition: tools.h:629
#define DTV_STREAM_ID
Definition: dvbdevice.h:64
bool BondingOk(const cChannel *Channel, bool ConsiderOccupied=false) const
Definition: dvbdevice.c:453
The cDvbDevice implements a DVB device which can be accessed through the Linux DVB driver API...
Definition: dvbdevice.h:167
virtual bool SetIdleDevice(bool Idle, bool TestOnly)
Called by SetIdle if TestOnly, don&#39;t do anything, just return, if the device can be set to the new id...
Definition: dvbdevice.c:1498
void SetChannel(const cChannel *Channel)
Definition: dvbdevice.c:500
Definition: tools.h:333
int Position(void)
Returns the orbital position of the satellite in case this is a DVB-S source (zero otherwise)...
Definition: sources.h:35
#define LOCK_THRESHOLD
Definition: dvbdevice.c:599
bool HasPid(int Pid) const
Returns true if this device is currently receiving the given PID.
Definition: device.c:492
bool GetFrontendStatus(fe_status_t &Status) const
Definition: dvbdevice.c:557
#define DTV_DVBT2_PLP_ID_LEGACY
Definition: dvbdevice.h:65
const tDvbParameterMap SystemValuesTerr[]
Definition: dvbdevice.c:105
virtual void Action(void)
A derived cThread class must implement the code it wants to execute as a separate thread in this func...
Definition: dvbdevice.c:940
cDevice * SubDevice(void) const
Definition: device.h:838
const tDvbParameterMap BandwidthValues[]
Definition: dvbdevice.c:53
int lockTimeout
Definition: dvbdevice.c:310
bool BondingOk(const cChannel *Channel, bool ConsiderOccupied=false) const
Returns true if this device is either not bonded to any other device, or the given Channel is on the ...
Definition: dvbdevice.c:1490
bool IsCable(void) const
Definition: channels.h:186
int System(void) const
Definition: dvbdevice.h:135
int tuneTimeout
Definition: dvbdevice.c:309
bool IsIdle(void) const
Definition: device.h:839
cCondVar locked
Definition: dvbdevice.c:321
Definition: tools.h:357
Derived cDevice classes that can receive channels will have to provide Transport Stream (TS) packets ...
Definition: device.h:856
virtual int OpenFilter(u_short Pid, u_char Tid, u_char Mask)
Opens a file handle for the given filter data.
Definition: dvbdevice.c:1563
time_t lastTimeoutReport
Definition: dvbdevice.c:311
int numDeliverySystems
Definition: dvbdevice.h:186
virtual int SignalStrength(void) const
Returns the "strength" of the currently received signal.
Definition: dvbdevice.c:1700
bool IsAtsc(void) const
Definition: channels.h:185
cString GetBondingParams(const cChannel *Channel=NULL) const
Definition: dvbdevice.c:436
#define ATSC_TUNE_TIMEOUT
Definition: dvbdevice.c:32
const char * userString
Definition: dvbdevice.h:86
virtual bool MaySwitchTransponder(const cChannel *Channel) const
Returns true if it is ok to switch to the Channel&#39;s transponder on this device, without disturbing an...
Definition: dvbdevice.c:1720
cDvbTransponderParameters dtp
Definition: dvbdevice.c:1060
static cString DvbName(const char *Name, int Adapter, int Frontend)
Definition: dvbdevice.c:1191
The cDevice class is the base from which actual devices can be derived.
Definition: device.h:109
Definition: tools.h:168
static int DvbOpen(const char *Name, int Adapter, int Frontend, int Mode, bool ReportError=false)
Definition: dvbdevice.c:1196
cDvbTuner * bondedTuner
Definition: dvbdevice.c:323
const cDvbDevice * device
Definition: dvbdevice.c:305
const tDvbParameterMap GuardValues[]
Definition: dvbdevice.c:122
virtual void GetData(cChannel *Channel)
Copies all source specific parameters to the given Channel.
Definition: dvbdevice.c:1082
const tDvbParameterMap TransmissionValues[]
Definition: dvbdevice.c:111
static void SetTransferModeForDolbyDigital(int Mode)
Definition: dvbdevice.c:1737
void Unlock(void)
Definition: thread.c:197
virtual bool ProvidesEIT(void) const
Returns true if this device provides EIT data and thus wants to be tuned to the channels it can recei...
Definition: dvbdevice.c:1685
int DiSEqC
Definition: config.h:274