MythTV  master
dvbchannel.cpp
Go to the documentation of this file.
1 /*
2  * Class DVBChannel
3  *
4  * Copyright (C) Kenneth Aafloy 2003
5  *
6  * Description:
7  * Has the responsibility of opening the Frontend device and
8  * setting the options to tune a channel. It also keeps other
9  * channel options used by the dvb hierarcy.
10  *
11  * Author(s):
12  * Taylor Jacob (rtjacob at earthlink.net)
13  * - Changed tuning and DB structure
14  * Kenneth Aafloy (ke-aa at frisurf.no)
15  * - Rewritten for faster tuning.
16  * Ben Bucksch
17  * - Wrote the original implementation
18  *
19  * This program is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 2 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program; if not, write to the Free Software
31  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
32  */
33 
34 // POSIX headers
35 #include <fcntl.h>
36 #include <unistd.h>
37 #include <utility>
38 #include <sys/poll.h>
39 #include <sys/select.h>
40 #include <sys/time.h>
41 #include <sys/types.h>
42 
43 // C++ headers
44 #include <chrono>
45 #include <thread>
46 
47 // MythTV headers
48 #include "libmythbase/mythconfig.h"
49 #include "libmythbase/mythdb.h"
50 #include "cardutil.h"
51 #include "channelutil.h"
52 #include "dvbtypes.h"
53 #include "dvbchannel.h"
54 #include "dvbcam.h"
55 #include "tv_rec.h"
56 
57 
58 // Local functions
59 static struct dvb_frontend_parameters dtvmultiplex_to_dvbparams(
60  DTVTunerType tuner_type, const DTVMultiplex& tuning, uint intermediate_freq, bool can_fec_auto);
62  DTVTunerType tuner_type, const dvb_frontend_parameters& params);
63 static struct dtv_properties *dtvmultiplex_to_dtvproperties(uint inputId,
64  DTVTunerType tuner_type, DTVModulationSystem current_sys, const DTVMultiplex &tuning,
65  uint intermediate_freq, bool can_fec_auto, bool do_tune = true);
66 
67 static constexpr std::chrono::milliseconds concurrent_tunings_delay { 1s };
69 
70 #define LOC QString("DVBChan[%1](%2): ").arg(m_inputId).arg(DVBChannel::GetDevice())
71 
72 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
73 #define DTV_STAT_FULL_DEBUG 0 // All DTV_STAT_xxx values
74 
80 DVBChannel::DVBChannel(QString aDevice, TVRec *parent)
81  : DTVChannel(parent), m_device(std::move(aDevice))
82 {
83  s_master_map_lock.lockForWrite();
85  if (m_pParent)
86  m_key += QString(":%1")
88 
89  s_master_map[m_key].push_back(this); // == RegisterForMaster
90  auto *master = dynamic_cast<DVBChannel*>(s_master_map[m_key].front());
91  if (master == this)
92  {
93  m_dvbCam = new DVBCam(m_device);
95  }
96  else if (master != nullptr)
97  {
98  m_dvbCam = master->m_dvbCam;
99  m_hasCrcBug = master->m_hasCrcBug;
100  }
101  s_master_map_lock.unlock();
102 
104 }
105 
107 {
108  // Set a new master if there are other instances and we're the master
109  // whether we are the master or not remove us from the map..
110  s_master_map_lock.lockForWrite();
111  auto *master = dynamic_cast<DVBChannel*>(s_master_map[m_key].front());
112  if (master == this)
113  {
114  s_master_map[m_key].pop_front();
115  DVBChannel *new_master = nullptr;
116  if (!s_master_map[m_key].empty())
117  new_master = dynamic_cast<DVBChannel*>(s_master_map[m_key].front());
118  if (new_master)
119  {
120  QMutexLocker master_locker(&(master->m_hwLock));
121  QMutexLocker new_master_locker(&(new_master->m_hwLock));
122  new_master->m_isOpen = master->m_isOpen;
123  }
124  }
125  else
126  {
127  s_master_map[m_key].removeAll(this);
128  }
129  s_master_map_lock.unlock();
130 
132 
133  // If we're the last one out delete dvbcam
134  s_master_map_lock.lockForRead();
135  MasterMap::iterator mit = s_master_map.find(m_key);
136  if ((*mit).empty())
137  delete m_dvbCam;
138  m_dvbCam = nullptr;
139  s_master_map_lock.unlock();
140 
141  // diseqc_tree is managed elsewhere
142 }
143 
145 {
146  LOG(VB_CHANNEL, LOG_INFO, LOC + "Closing DVB channel");
147 
148  QMutexLocker locker(&m_hwLock);
149 
150  IsOpenMap::iterator it = m_isOpen.find(who);
151  if (it == m_isOpen.end())
152  return; // This caller didn't have it open in the first place..
153 
154  m_isOpen.erase(it);
155 
156  DVBChannel *master = GetMasterLock();
157  if (master != nullptr && master != this)
158  {
159  if (m_dvbCam->IsRunning())
160  m_dvbCam->SetPMT(this, nullptr);
161  master->Close(this);
162  m_fdFrontend = -1;
163  ReturnMasterLock(master);
164  return;
165  }
166  ReturnMasterLock(master); // If we're the master we don't need this lock.
167 
168  if (!m_isOpen.empty())
169  return; // Not all callers have closed the DVB channel yet..
170 
171  if (m_diseqcTree)
172  m_diseqcTree->Close();
173 
174  if (m_fdFrontend >= 0)
175  {
177  m_fdFrontend = -1;
178 
179  m_dvbCam->Stop();
180  }
181 }
182 
184 {
185  if (!m_inputId)
186  {
187  if (!InitializeInput())
188  return false;
189  }
190 
191  LOG(VB_CHANNEL, LOG_INFO, LOC + "Opening DVB channel");
192 
194  if (m_legacyFe)
195  {
196  LOG(VB_CHANNEL, LOG_INFO, LOC + "Use legacy DVBv3 API");
197  }
198 
199  QMutexLocker locker(&m_hwLock);
200 
201  if (m_fdFrontend >= 0)
202  {
203  m_isOpen[who] = true;
204  return true;
205  }
206 
207  DVBChannel *master = GetMasterLock();
208  if (master != this)
209  {
210  if (!master->Open(who))
211  {
212  ReturnMasterLock(master);
213  return false;
214  }
215 
216  m_fdFrontend = master->m_fdFrontend;
217  m_frontendName = master->m_frontendName;
218  m_tunerType = master->m_tunerType;
219  m_capabilities = master->m_capabilities;
225  m_version = master->m_version;
226  m_legacyFe = master->m_legacyFe;
227  m_hasV5Stats = master->m_hasV5Stats;
228  m_currentSys = master->m_currentSys;
229  m_sysList = master->m_sysList;
230 
231  m_isOpen[who] = true;
232 
233  if (!InitializeInput())
234  {
235  Close();
236  ReturnMasterLock(master);
237  return false;
238  }
239 
240  ReturnMasterLock(master);
241  return true;
242  }
243  ReturnMasterLock(master); // If we're the master we don't need this lock.
244 
245  // Open the DVB device
246  //
248  QByteArray devn = dvbdev.toLatin1();
249 
250  for (int tries = 1; ; ++tries)
251  {
252  m_fdFrontend = open(devn.constData(), O_RDWR | O_NONBLOCK);
253  if (m_fdFrontend >= 0)
254  break;
255  if (tries == 1)
256  {
257  LOG(VB_GENERAL, LOG_WARNING, LOC +
258  "Opening DVB frontend device failed." + ENO);
259  }
260  if (tries >= 5 || (errno != EBUSY && errno != EAGAIN))
261  {
262  LOG(VB_GENERAL, LOG_ERR, LOC +
263  QString("Failed to open DVB frontend device due to "
264  "fatal error or too many attempts."));
265  return false;
266  }
267  std::this_thread::sleep_for(50ms);
268  }
269 
270  // Get the basic information from the frontend
271  //
272  dvb_frontend_info info {};
273  if (ioctl(m_fdFrontend, FE_GET_INFO, &info) < 0)
274  {
275  LOG(VB_GENERAL, LOG_ERR, LOC +
276  "Failed to get frontend information." + ENO);
277 
279  m_fdFrontend = -1;
280  return false;
281  }
282 
283  m_frontendName = info.name;
284  m_capabilities = info.caps;
285  m_frequencyMinimum = info.frequency_min;
286  m_frequencyMaximum = info.frequency_max;
287  m_symbolRateMinimum = info.symbol_rate_min;
288  m_symbolRateMaximum = info.symbol_rate_max;
289 
290  LOG(VB_CHANNEL, LOG_INFO, LOC +
291  QString("Frontend '%1' capabilities:").arg(m_frontendName));
292  for (auto & capstr : CardUtil::CapabilitiesToString(m_capabilities))
293  {
294  LOG(VB_CHANNEL, LOG_INFO, QString(" %1").arg(capstr));
295  }
296 
297  // Does this card use the DVBv5 or the legacy DVBv3 API?
298  {
299  std::array<struct dtv_property,2> prop = {};
300  struct dtv_properties cmd = {};
301 
302  prop[0].cmd = DTV_API_VERSION;
303  prop[1].cmd = DTV_DELIVERY_SYSTEM;
304 
305  cmd.num = 2;
306  cmd.props = prop.data();
307 
308  if (ioctl(m_fdFrontend, FE_GET_PROPERTY, &cmd) == -1)
309  {
310  prop[0].u.data = 0x300;
311  prop[1].u.data = SYS_UNDEFINED;
312  }
313 
314  m_version = prop[0].u.data;
315  m_currentSys = prop[1].u.data;
316 
317  m_legacyFe = m_version < 0x500 ? true : m_legacyFe;
318  m_hasV5Stats = m_version >= 0x50a;
319  }
320 
321  // Determine tuner capabilities and configured delivery system
322  //
323  m_sysList.clear();
324  if (m_legacyFe || m_version < 0x505)
325  {
326  // Legacy DVBv3 API
327  //
328  DTVModulationSystem delsys;
329  m_legacyFe = true;
330  switch (info.type) {
331  case FE_QPSK:
332  m_currentSys = SYS_DVBS;
333  m_sysList.append(m_currentSys);
334 
335  if (m_version < 0x0500)
336  break;
337  if (info.caps & FE_CAN_2G_MODULATION)
338  {
339  delsys = SYS_DVBS2;
340  m_sysList.append(delsys);
341  }
342  if (info.caps & FE_CAN_TURBO_FEC)
343  {
344  delsys = SYS_TURBO;
345  m_sysList.append(delsys);
346  }
347  break;
348  case FE_QAM:
349  m_currentSys = SYS_DVBC_ANNEX_A;
350  m_sysList.append(m_currentSys);
351  break;
352  case FE_OFDM:
353  m_currentSys = SYS_DVBT;
354  m_sysList.append(m_currentSys);
355  if (m_version < 0x0500)
356  break;
357  if (info.caps & FE_CAN_2G_MODULATION)
358  {
359  delsys = SYS_DVBT2;
360  m_sysList.append(delsys);
361  }
362  break;
363  case FE_ATSC:
364  if (info.caps & (FE_CAN_8VSB | FE_CAN_16VSB))
365  {
366  delsys = SYS_ATSC;
367  m_sysList.append(delsys);
368  }
369  if (info.caps & (FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_QAM_AUTO))
370  {
371  delsys = SYS_DVBC_ANNEX_B;
372  m_sysList.append(delsys);
373  }
374  m_currentSys = m_sysList.value(0);
375  break;
376  }
377  if (m_sysList.isEmpty())
378  {
379  LOG(VB_GENERAL, LOG_ERR, LOC +
380  QString("Frontend '%1' delivery system not detected.").arg(m_frontendName));
382  return false;
383  }
384  }
385  else
386  {
387  // DVBv5 API
388  //
389  std::array<struct dtv_property,1> prop = {};
390  struct dtv_properties cmd = {};
391 
392  prop[0].cmd = DTV_ENUM_DELSYS;
393 
394  cmd.num = 1;
395  cmd.props = prop.data();
396 
397  if (ioctl(m_fdFrontend, FE_GET_PROPERTY, &cmd) == -1)
398  {
399  LOG(VB_GENERAL, LOG_ERR, LOC +
400  QString("Frontend '%1' FE_GET_PROPERTY failed.").arg(m_frontendName));
402  return false;
403  }
404 
405  int p_num_systems = prop[0].u.buffer.len;
406  for (int i = 0; i < p_num_systems; i++)
407  {
408  DTVModulationSystem delsys(prop[0].u.buffer.data[i]);
409  m_sysList.append(delsys);
410  }
411 
412  if (p_num_systems == 0) {
413  LOG(VB_GENERAL, LOG_ERR, LOC +
414  QString("Frontend '%1' returned 0 supported delivery systems!").arg(m_frontendName));
416  return false;
417  }
418  }
419 
420  // Frontend info
421  //
422  if (VERBOSE_LEVEL_CHECK(VB_CHANNEL, LOG_INFO))
423  {
424  LOG(VB_CHANNEL, LOG_INFO, LOC +
425  QString("Frontend '%1' ").arg(m_frontendName));
426  LOG(VB_CHANNEL, LOG_INFO, LOC +
427  QString("DVB version:0x%1 ").arg(m_version,3,16,QChar('0')) +
428  QString("Delivery system:%1 ").arg(m_currentSys.toString()) +
429  QString("Legacy FE:%1 ").arg(m_legacyFe) +
430  QString("Has DVBv5 stats:%1").arg(m_hasV5Stats));
431 
432  LOG(VB_CHANNEL, LOG_INFO, "Supported delivery systems: ");
433  for (auto & delsys : m_sysList)
434  {
435  if (delsys == m_currentSys)
436  {
437  LOG(VB_CHANNEL, LOG_INFO, QString(" [%1]")
438  .arg(delsys.toString()));
439  }
440  else
441  {
442  LOG(VB_CHANNEL, LOG_INFO, QString(" %1")
443  .arg(delsys.toString()));
444  }
445  }
446 
447  uint32_t frq_min = info.frequency_min;
448  uint32_t frq_max = info.frequency_max;
449  uint32_t frq_stp = info.frequency_stepsize;
450 // uint32_t frq_tol = info.frequency_tolerance;
451  if (info.type == FE_QPSK) // Satellite frequencies are in kHz
452  {
453  frq_min *= 1000;
454  frq_max *= 1000;
455  frq_stp *= 1000;
456 // frq_tol *= 1000;
457  }
458 
459  LOG(VB_CHANNEL, LOG_INFO, QString("Frequency range for the current standard:"));
460  LOG(VB_CHANNEL, LOG_INFO, QString(" From: %1 Hz").arg(frq_min,11));
461  LOG(VB_CHANNEL, LOG_INFO, QString(" To: %1 Hz").arg(frq_max,11));
462  LOG(VB_CHANNEL, LOG_INFO, QString(" Step: %1 Hz").arg(frq_stp,11));
463 
464  if (info.type == FE_QPSK || info.type == FE_QAM)
465  {
466  LOG(VB_CHANNEL, LOG_INFO, QString("Symbol rate ranges for the current standard:"));
467  LOG(VB_CHANNEL, LOG_INFO, QString(" From: %1 Baud").arg(info.symbol_rate_min,11));
468  LOG(VB_CHANNEL, LOG_INFO, QString(" To: %1 Baud").arg(info.symbol_rate_max,11));
469  }
470  }
471 
472  if (m_currentSys == SYS_UNDEFINED)
473  m_currentSys = m_sysList.value(0);
474 
475  // Get delivery system from database and configure the tuner if needed.
478  {
479  if (delsys != m_currentSys)
480  {
481  LOG(VB_CHANNEL, LOG_INFO, LOC +
482  QString("Change delivery system from %1 to %2.")
483  .arg(m_currentSys.toString(),
484  delsys.toString()));
485 
487  m_currentSys = delsys;
488  }
489  else
490  {
491  LOG(VB_CHANNEL, LOG_INFO, LOC +
492  QString("Delivery system in database and in card equal, leave at %1.")
493  .arg(m_currentSys.toString()));
494  }
495  }
496  else
497  {
498  LOG(VB_CHANNEL, LOG_INFO, LOC +
499  QString("No delivery system in database, leave card at %1.").arg(m_currentSys.toString()));
500  }
502 
503  // Turn on the power to the LNB
505  {
506 
508  if (m_diseqcTree)
509  {
510  bool is_SCR = false;
511 
513  if (scr)
514  {
515  is_SCR = true;
516  LOG(VB_CHANNEL, LOG_INFO, LOC +
517  QString("Requested %1 channel is on SCR system")
518  .arg(m_tunerType.toString()));
519  }
520  else
521  {
522  LOG(VB_CHANNEL, LOG_INFO, LOC +
523  QString("Requested %1 channel is on non-SCR system")
524  .arg(m_tunerType.toString()));
525  }
526  m_diseqcTree->Open(m_fdFrontend, is_SCR);
527  }
528  }
529 
530  m_firstTune = true;
531 
532  if (!InitializeInput())
533  {
534  Close();
535  return false;
536  }
537 
538  if (m_fdFrontend >= 0)
539  m_isOpen[who] = true;
540 
541  return (m_fdFrontend >= 0);
542 }
543 
544 bool DVBChannel::IsOpen(void) const
545 {
546  // Have to acquire the hw lock to prevent m_isOpen being modified whilst we're searching it.
547  QMutexLocker locker(&m_hwLock);
548  IsOpenMap::const_iterator it = m_isOpen.find(this);
549  return it != m_isOpen.end();
550 }
551 
552 bool DVBChannel::Init(QString &startchannel, bool setchan)
553 {
554  if (setchan && !IsOpen())
555  Open(this);
556 
557  return ChannelBase::Init(startchannel, setchan);
558 }
559 
563 void DVBChannel::CheckFrequency(uint64_t frequency) const
564 {
567  (frequency < m_frequencyMinimum || frequency > m_frequencyMaximum))
568  {
569  LOG(VB_GENERAL, LOG_WARNING, LOC +
570  QString("Frequency setting (%1) is out of range (min/max:%2/%3)")
571  .arg(frequency).arg(m_frequencyMinimum).arg(m_frequencyMaximum));
572  }
573 }
574 
576 {
577  if ((tuning.m_inversion == DTVInversion::kInversionAuto) &&
578  ((m_capabilities & FE_CAN_INVERSION_AUTO) == 0U))
579  {
580  LOG(VB_GENERAL, LOG_WARNING, LOC +
581  "'Auto' inversion parameter unsupported by this driver, "
582  "falling back to 'off'.");
584  }
585 
586  // DVB-S/S2 needs a fully initialized DiSEqC tree and is checked later in Tune
587  if (!m_diseqcTree)
588  {
589  DVBChannel *master = GetMasterLock();
590  if (master == nullptr || !master->m_diseqcTree)
591  CheckFrequency(tuning.m_frequency);
592  ReturnMasterLock(master);
593  }
594 
595  if (m_tunerType.IsFECVariable() &&
598  (tuning.m_symbolRate < m_symbolRateMinimum ||
600  {
601  LOG(VB_GENERAL, LOG_WARNING, LOC +
602  QString("Symbol Rate setting (%1) is out of range (min/max:%2/%3)")
603  .arg(tuning.m_symbolRate)
605  }
606 
607  if (m_tunerType.IsFECVariable() && !CheckCodeRate(tuning.m_fec))
608  {
609  LOG(VB_GENERAL, LOG_WARNING, LOC +
610  "Selected fec_inner parameter unsupported by this driver.");
611  }
612 
614  {
615  LOG(VB_GENERAL, LOG_WARNING, LOC +
616  "Selected modulation parameter unsupported by this driver.");
617  }
618 
621  {
622  LOG(VB_CHANNEL, LOG_DEBUG, LOC + tuning.toString());
623  return;
624  }
625 
626  // ------ Below only DVB-T/T2 tuning parameters ------
627 
628  // Check OFDM Tuning params
629 
630  if (!CheckCodeRate(tuning.m_hpCodeRate))
631  {
632  LOG(VB_GENERAL, LOG_WARNING, LOC +
633  "Selected code_rate_hp parameter unsupported by this driver.");
634  }
635 
636  if (!CheckCodeRate(tuning.m_lpCodeRate))
637  {
638  LOG(VB_GENERAL, LOG_WARNING, LOC +
639  "Selected code_rate_lp parameter unsupported by this driver.");
640  }
641 
642  if ((tuning.m_bandwidth == DTVBandwidth::kBandwidthAuto) &&
643  ((m_capabilities & FE_CAN_BANDWIDTH_AUTO) == 0U))
644  {
645  LOG(VB_GENERAL, LOG_WARNING, LOC +
646  "'Auto' bandwidth parameter unsupported by this driver.");
647  }
648 
650  ((m_capabilities & FE_CAN_TRANSMISSION_MODE_AUTO) == 0U))
651  {
652  LOG(VB_GENERAL, LOG_WARNING, LOC +
653  "'Auto' transmission_mode parameter unsupported by this driver.");
654  }
655 
657  ((m_capabilities & FE_CAN_GUARD_INTERVAL_AUTO) == 0U))
658  {
659  LOG(VB_GENERAL, LOG_WARNING, LOC +
660  "'Auto' guard_interval parameter unsupported by this driver.");
661  }
662 
663  if ((tuning.m_hierarchy == DTVHierarchy::kHierarchyAuto) &&
664  ((m_capabilities & FE_CAN_HIERARCHY_AUTO) == 0U))
665  {
666  LOG(VB_GENERAL, LOG_WARNING, LOC +
667  "'Auto' hierarchy parameter unsupported by this driver. ");
668  }
669 
670  if (!CheckModulation(tuning.m_modulation))
671  {
672  LOG(VB_GENERAL, LOG_WARNING, LOC +
673  "Selected modulation parameter unsupported by this driver.");
674  }
675 
676  LOG(VB_CHANNEL, LOG_DEBUG, LOC + tuning.toString());
677 }
678 
683 {
684  const uint64_t caps = m_capabilities;
685  return
686  ((DTVCodeRate::kFECNone == rate)) ||
687  ((DTVCodeRate::kFEC_1_2 == rate) && ((caps & FE_CAN_FEC_1_2) != 0U)) ||
688  ((DTVCodeRate::kFEC_2_3 == rate) && ((caps & FE_CAN_FEC_2_3) != 0U)) ||
689  ((DTVCodeRate::kFEC_3_4 == rate) && ((caps & FE_CAN_FEC_3_4) != 0U)) ||
690  ((DTVCodeRate::kFEC_4_5 == rate) && ((caps & FE_CAN_FEC_4_5) != 0U)) ||
691  ((DTVCodeRate::kFEC_5_6 == rate) && ((caps & FE_CAN_FEC_5_6) != 0U)) ||
692  ((DTVCodeRate::kFEC_6_7 == rate) && ((caps & FE_CAN_FEC_6_7) != 0U)) ||
693  ((DTVCodeRate::kFEC_7_8 == rate) && ((caps & FE_CAN_FEC_7_8) != 0U)) ||
694  ((DTVCodeRate::kFEC_8_9 == rate) && ((caps & FE_CAN_FEC_8_9) != 0U)) ||
695  ((DTVCodeRate::kFECAuto == rate) && ((caps & FE_CAN_FEC_AUTO) != 0U));
696 }
697 
702 {
703  const DTVModulation m = modulation;
704  const uint64_t c = m_capabilities;
705 
706  return
707  ((DTVModulation::kModulationQPSK == m) && ((c & FE_CAN_QPSK) != 0U)) ||
708 #if HAVE_FE_CAN_2G_MODULATION
709  ((DTVModulation::kModulation8PSK == m) && ((c & FE_CAN_2G_MODULATION) != 0U)) ||
710  ((DTVModulation::kModulation16APSK == m) && ((c & FE_CAN_2G_MODULATION) != 0U)) ||
711  ((DTVModulation::kModulation32APSK == m) && ((c & FE_CAN_2G_MODULATION) != 0U)) ||
712 #endif //HAVE_FE_CAN_2G_MODULATION
713  ((DTVModulation::kModulationQAM16 == m) && ((c & FE_CAN_QAM_16) != 0U)) ||
714  ((DTVModulation::kModulationQAM32 == m) && ((c & FE_CAN_QAM_32) != 0U)) ||
715  ((DTVModulation::kModulationQAM64 == m) && ((c & FE_CAN_QAM_64) != 0U)) ||
716  ((DTVModulation::kModulationQAM128 == m) && ((c & FE_CAN_QAM_128) != 0U)) ||
717  ((DTVModulation::kModulationQAM256 == m) && ((c & FE_CAN_QAM_256) != 0U)) ||
718  ((DTVModulation::kModulationQAMAuto == m) && ((c & FE_CAN_QAM_AUTO) != 0U)) ||
719  ((DTVModulation::kModulation8VSB == m) && ((c & FE_CAN_8VSB) != 0U)) ||
720  ((DTVModulation::kModulation16VSB == m) && ((c & FE_CAN_16VSB) != 0U));
721 }
722 
727 {
728  if (!m_dvbCam->IsRunning())
729  m_dvbCam->Start();
730  if (pmt && m_dvbCam->IsRunning())
731  m_dvbCam->SetPMT(this, pmt);
732 }
733 
738 void DVBChannel::SetTimeOffset(double offset)
739 {
740  if (m_dvbCam->IsRunning())
741  m_dvbCam->SetTimeOffset(offset);
742 }
743 
744 bool DVBChannel::Tune(const DTVMultiplex &tuning)
745 {
746  if (!m_inputId)
747  {
748  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Tune(): Invalid input."));
749  return false;
750  }
751  return Tune(tuning, false, false);
752 }
753 
754 
755 /*****************************************************************************
756  Tuning functions for each of the five types of cards.
757  *****************************************************************************/
758 
770 bool DVBChannel::Tune(const DTVMultiplex &tuning,
771  bool force_reset,
772  bool same_input)
773 {
774  QMutexLocker lock(&m_tuneLock);
775  QMutexLocker locker(&m_hwLock);
776 
777  DVBChannel *master = GetMasterLock();
778  if (master != this)
779  {
780  LOG(VB_CHANNEL, LOG_INFO, LOC + "Tuning on slave channel");
781  SetSIStandard(tuning.m_sistandard);
782  bool ok = master->Tune(tuning, force_reset, false);
783  ReturnMasterLock(master);
784  return ok;
785  }
786  ReturnMasterLock(master); // If we're the master we don't need this lock.
787 
788 
789  uint intermediate_freq = 0;
790  bool can_fec_auto = false;
791  bool reset = (force_reset || m_firstTune);
792 
794  {
795  LOG(VB_GENERAL, LOG_ERR, LOC +
796  "DVB-S/S2 needs device tree for LNB handling");
797  return false;
798  }
799 
800  m_desiredTuning = tuning;
801 
802  if (m_fdFrontend < 0)
803  {
804  LOG(VB_GENERAL, LOG_ERR, LOC + "Tune(): Card not open!");
805 
806  return false;
807  }
808 
809  // Remove all events in queue before tuning.
810  DrainDVBEvents();
811 
812  LOG(VB_CHANNEL, LOG_INFO, LOC + "Tuning parameters:");
813  LOG(VB_CHANNEL, LOG_INFO, " Old: " + m_prevTuning.toString());
814  LOG(VB_CHANNEL, LOG_INFO, " New: " + tuning.toString());
815 
816  // DVB-S/S2 is in kHz, other DVB is in Hz
817  bool is_dvbs = ((DTVTunerType::kTunerTypeDVBS1 == m_tunerType) ||
819  int freq_mult = (is_dvbs) ? 1 : 1000;
820  QString suffix = (is_dvbs) ? "kHz" : "Hz";
821 
822  if (reset || !m_prevTuning.IsEqual(m_tunerType, tuning, 500 * freq_mult))
823  {
824  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Tune(): Tuning to %1%2")
825  .arg(intermediate_freq ? intermediate_freq : tuning.m_frequency)
826  .arg(suffix));
827 
828  m_tuneDelayLock.lock();
829 
830  std::chrono::milliseconds this_tuning = MythDate::currentMSecsSinceEpochAsDuration();
831  std::chrono::milliseconds tuning_delay = s_lastTuning + concurrent_tunings_delay - this_tuning;
832  if (tuning_delay > 0ms)
833  {
834  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Next tuning after less than %1ms, delaying by %2ms")
835  .arg(concurrent_tunings_delay.count()).arg(tuning_delay.count()));
836  std::this_thread::sleep_for(tuning_delay);
837  }
839 
840  m_tuneDelayLock.unlock();
841 
842  // For DVB-S/S2 configure DiSEqC and determine intermediate frequency
843  if (m_diseqcTree)
844  {
845  // Configure for new input
846  if (!same_input)
848 
849  // Execute DiSEqC commands
850  if (!m_diseqcTree->Execute(m_diseqcSettings, tuning))
851  {
852  LOG(VB_GENERAL, LOG_ERR, LOC +
853  "Tune(): Failed to setup DiSEqC devices");
854  return false;
855  }
856 
857  // Retrieve actual intermediate frequency
859  if (!lnb)
860  {
861  LOG(VB_GENERAL, LOG_ERR, LOC +
862  "Tune(): No LNB for this configuration");
863  return false;
864  }
865 
866  if (lnb->GetDeviceID() != m_lastLnbDevId)
867  {
868  m_lastLnbDevId = lnb->GetDeviceID();
869  // Make sure we tune to frequency, if the lnb has changed
870  m_firstTune = true;
871  }
872 
873  intermediate_freq = lnb->GetIntermediateFrequency(
874  m_diseqcSettings, tuning);
875 
876  // Retrieve SCR intermediate frequency
878  if (lnb && scr)
879  {
880  intermediate_freq = scr->GetIntermediateFrequency(intermediate_freq);
881  }
882 
883  // If card can auto-FEC, use it -- sometimes NITs are inaccurate
884  if (m_capabilities & FE_CAN_FEC_AUTO)
885  can_fec_auto = true;
886 
887  // Check DVB-S intermediate frequency here since it requires a fully
888  // initialized diseqc tree
889  CheckFrequency(intermediate_freq);
890  }
891 
892  // DVBv5 or legacy DVBv3 API
893  if (!m_legacyFe)
894  {
895  // DVBv5 API
896  struct dtv_property p_clear = {};
897  struct dtv_properties cmdseq_clear = {};
898 
899  p_clear.cmd = DTV_CLEAR;
900  cmdseq_clear.num = 1;
901  cmdseq_clear.props = &p_clear;
902 
903  if ((ioctl(m_fdFrontend, FE_SET_PROPERTY, &cmdseq_clear)) < 0)
904  {
905  LOG(VB_GENERAL, LOG_ERR, LOC +
906  "Tune(): Clearing DTV properties cache failed." + ENO);
907  return false;
908  }
909 
910  struct dtv_properties *cmds = dtvmultiplex_to_dtvproperties(m_inputId,
911  m_tunerType, m_currentSys, tuning, intermediate_freq, can_fec_auto);
912 
913  if (!cmds) {
914  LOG(VB_GENERAL, LOG_ERR, LOC +
915  "Failed to convert DTVMultiplex to DTV_PROPERTY sequence");
916  return false;
917  }
918 
919  if (VERBOSE_LEVEL_CHECK(VB_CHANNEL, LOG_DEBUG))
920  {
921  for (uint i = 0; i < cmds->num; i++)
922  {
923  LOG(VB_CHANNEL, LOG_DEBUG, LOC +
924  QString("prop %1: cmd = %2, data %3")
925  .arg(i).arg(cmds->props[i].cmd)
926  .arg(cmds->props[i].u.data));
927  }
928  }
929 
930  int res = ioctl(m_fdFrontend, FE_SET_PROPERTY, cmds);
931 
932  free(cmds->props);
933  free(cmds);
934 
935  if (res < 0)
936  {
937  LOG(VB_GENERAL, LOG_ERR, LOC +
938  "Tune(): Setting Frontend tuning parameters failed." + ENO);
939  return false;
940  }
941  }
942  else
943  {
944  // Legacy DVBv3 API
945  struct dvb_frontend_parameters params = dtvmultiplex_to_dvbparams(
946  m_tunerType, tuning, intermediate_freq, can_fec_auto);
947 
948  if (ioctl(m_fdFrontend, FE_SET_FRONTEND, &params) < 0)
949  {
950  LOG(VB_GENERAL, LOG_ERR, LOC +
951  "Tune(): Setting Frontend tuning parameters failed." + ENO);
952  return false;
953  }
954  }
955 
956  // Extra delay to add for broken DVB drivers
957  if (m_tuningDelay > 0ms)
958  std::this_thread::sleep_for(m_tuningDelay);
959 
960  WaitForBackend(50ms);
961 
962  m_prevTuning = tuning;
963  m_firstTune = false;
964  }
965  else
966  {
967  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Tune(): Tuning to %1%2 skipped, already tuned")
968  .arg(intermediate_freq ? intermediate_freq : tuning.m_frequency)
969  .arg(suffix));
970  }
971 
972 
973  SetSIStandard(tuning.m_sistandard);
974 
975  LOG(VB_CHANNEL, LOG_INFO, LOC + "Tune(): Frequency tuning successful");
976 
977  return true;
978 }
979 
981 {
982  return Tune(m_desiredTuning, true, true);
983 }
984 
989 {
990  QMutexLocker locker(&m_hwLock);
991 
992  if (m_fdFrontend < 0)
993  {
994  LOG(VB_GENERAL, LOG_ERR, LOC + "Card not open!");
995 
996  return false;
997  }
998 
999  DVBChannel *master = GetMasterLock();
1000  if (master != this)
1001  {
1002  bool ok = master->IsTuningParamsProbeSupported();
1003  ReturnMasterLock(master);
1004  return ok;
1005  }
1006  ReturnMasterLock(master); // If we're the master we don't need this lock.
1007 
1008  if (m_diseqcTree)
1009  {
1010  // TODO We need to implement the inverse of
1011  // lnb->GetIntermediateFrequency() for ProbeTuningParams()
1012  // to accurately reflect the frequency before LNB transform.
1013  return false;
1014  }
1015 
1016  dvb_frontend_parameters params {};
1017 
1018  int res = ioctl(m_fdFrontend, FE_GET_FRONTEND, &params);
1019  if (res < 0)
1020  {
1021  LOG(VB_CHANNEL, LOG_ERR, LOC + "FE_GET_FRONTEND failed." + ENO);
1022  }
1023 
1024  return (res >= 0);
1025 }
1026 
1035 {
1036  QMutexLocker locker(&m_hwLock);
1037 
1038  if (m_fdFrontend < 0)
1039  {
1040  LOG(VB_GENERAL, LOG_ERR, LOC + "Card not open!");
1041 
1042  return false;
1043  }
1044 
1045  DVBChannel *master = GetMasterLock();
1046  if (master != this)
1047  {
1048  bool ok = master->ProbeTuningParams(tuning);
1049  ReturnMasterLock(master);
1050  return ok;
1051  }
1052  ReturnMasterLock(master); // If we're the master we don't need this lock.
1053 
1054  if (m_diseqcTree)
1055  {
1056  // TODO We need to implement the inverse of
1057  // lnb->GetIntermediateFrequency() for ProbeTuningParams()
1058  // to accurately reflect the frequency before LNB transform.
1059  return false;
1060  }
1061 
1062  // DVBv5 API
1063  if (!m_legacyFe)
1064  {
1065  // TODO implement probing of tuning parameters with FE_GET_PROPERTY
1066  return false;
1067  }
1068 
1069  // Legacy DVBv3 API
1070  dvb_frontend_parameters params {};
1071  if (ioctl(m_fdFrontend, FE_GET_FRONTEND, &params) < 0)
1072  {
1073  LOG(VB_GENERAL, LOG_ERR, LOC +
1074  "Getting Frontend tuning parameters failed." + ENO);
1075 
1076  return false;
1077  }
1078 
1079  uint mplex = tuning.m_mplex;
1080  QString sistandard = tuning.m_sistandard;
1081 
1082  tuning = dvbparams_to_dtvmultiplex(m_tunerType, params);
1083 
1084  tuning.m_mplex = mplex;
1085  tuning.m_sistandard = sistandard;
1086 
1087  return true;
1088 }
1089 
1095 {
1096  QList<int> idlist;
1097  int id = -1;
1098 
1099  MSqlQuery query(MSqlQuery::InitCon());
1100 
1101  query.prepare("SELECT chanid, visible "
1102  "FROM channel, capturecard "
1103  "WHERE channel.deleted IS NULL AND "
1104  " capturecard.sourceid = channel.sourceid AND "
1105  " channel.channum = :CHANNUM AND "
1106  " capturecard.cardid = :INPUTID");
1107 
1108  query.bindValue(":CHANNUM", m_curChannelName);
1109  query.bindValue(":INPUTID", m_inputId);
1110 
1111  if (!query.exec() || !query.isActive())
1112  {
1113  MythDB::DBError("fetching chanid", query);
1114  return -1;
1115  }
1116 
1117  while (query.next())
1118  {
1119  bool visible = query.value(1).toInt() > 0;
1120  if (visible)
1121  {
1122  int chanid = query.value(0).toInt();
1123  idlist.append(chanid);
1124  }
1125  }
1126 
1127  if (idlist.isEmpty())
1128  {
1129  LOG(VB_GENERAL, LOG_WARNING, LOC +
1130  QString("No visible channel ID for %1")
1131  .arg(m_curChannelName));
1132  }
1133  else
1134  {
1135  id = idlist.value(0);
1136  if (idlist.count() > 1)
1137  {
1138  QStringList sl;
1139  for (auto chanid : idlist)
1140  {
1141  sl.append(QString::number(chanid));
1142  }
1143  LOG(VB_CHANNEL, LOG_DEBUG, LOC +
1144  QString("Found for '%1' multiple visible channel IDs: %2")
1145  .arg(m_curChannelName, sl.join(" ")));
1146  }
1147  else
1148  {
1149  LOG(VB_CHANNEL, LOG_DEBUG, LOC +
1150  QString("Found visible channel ID %1 for '%2'")
1151  .arg(id).arg(m_curChannelName));
1152  }
1153  }
1154 
1155  return id;
1156 }
1157 
1159 {
1160  if (m_diseqcTree)
1162 
1163  return nullptr;
1164 }
1165 
1166 bool DVBChannel::HasLock(bool *ok) const
1167 {
1168  DVBChannel *master = GetMasterLock();
1169  if (master != this)
1170  {
1171  bool haslock = master->HasLock(ok);
1172  ReturnMasterLock(master);
1173  return haslock;
1174  }
1175  ReturnMasterLock(master); // If we're the master we don't need this lock.
1176 
1177 #if ((DVB_API_VERSION > 5) || ((DVB_API_VERSION == 5) && (DVB_API_VERSION_MINOR > 10)))
1178  fe_status_t status = FE_NONE;
1179 #else // debian9, centos7
1180  fe_status_t status = (fe_status_t)0;
1181 #endif
1182 
1183  int ret = ioctl(m_fdFrontend, FE_READ_STATUS, &status);
1184  if (ret < 0)
1185  {
1186  LOG(VB_GENERAL, LOG_ERR, LOC + "FE_READ_STATUS failed" + ENO);
1187  }
1188  else
1189  {
1190  LOG(VB_CHANNEL, LOG_DEBUG, LOC + QString("%1 status: 0x%2 %3")
1191  .arg(__func__).arg(status,2,16,QChar('0')).arg(toString(status)));
1192  }
1193 
1194  if (ok)
1195  *ok = (0 == ret);
1196 
1197  return (status & FE_HAS_LOCK) != 0;
1198 }
1199 
1201 {
1202  struct dtv_property prop = {};
1203  struct dtv_properties cmd = {};
1204 
1205  prop.cmd = DTV_STAT_SIGNAL_STRENGTH;
1206  cmd.num = 1;
1207  cmd.props = &prop;
1208  int ret = ioctl(m_fdFrontend, FE_GET_PROPERTY, &cmd);
1209  if (ret < 0)
1210  {
1211  LOG(VB_CHANNEL, LOG_DEBUG, LOC + "FE_GET_PROPERTY DTV_STAT_SIGNAL_STRENGTH failed" + ENO);
1212  }
1213  else
1214  {
1215 #if DTV_STAT_FULL_DEBUG
1216  LOG(VB_CHANNEL, LOG_DEBUG, LOC + "DTV_STAT_SIGNAL_STRENGTH " +
1217  QString("res=%1 len=%2 scale=%3 val=%4")
1218  .arg(cmd.props->result)
1219  .arg(cmd.props->u.st.len)
1220  .arg(cmd.props->u.st.stat[0].scale)
1221  .arg(cmd.props->u.st.stat[0].svalue));
1222 #endif
1223  }
1224 
1225  bool tmpOk = (ret == 0) && (cmd.props->u.st.len > 0);
1226  if (ok)
1227  *ok = tmpOk;
1228 
1229  double value = 0;
1230  if (tmpOk)
1231  {
1232  if (cmd.props->u.st.stat[0].scale == FE_SCALE_DECIBEL)
1233  {
1234  // Convert range of -100dBm .. 0dBm to 0% .. 100%
1235  // Note that -100dBm is lower than the noise floor.
1236  // The measured svalue is in units of 0.001 dBm.
1237  // If the value is outside the range -100 to 0 dBm we do not believe it.
1238  int64_t svalue = cmd.props->u.st.stat[0].svalue;
1239  if (svalue >= -100000 && svalue <= 0)
1240  {
1241  // convert value from -100dBm to 0dBm to a 0-1 range
1242  value = svalue + 100000;
1243  value = value / 100000.0;
1244  if (value > 1.0)
1245  value = 1.0;
1246  }
1247  }
1248  else if (cmd.props->u.st.stat[0].scale == FE_SCALE_RELATIVE)
1249  {
1250  // Return as 16 bit unsigned
1251  value = cmd.props->u.st.stat[0].uvalue / 65535.0;
1252  }
1253  }
1254  return value;
1255 }
1256 
1257 double DVBChannel::GetSignalStrength(bool *ok) const
1258 {
1259  DVBChannel *master = GetMasterLock();
1260  if (master != this)
1261  {
1262  double val = master->GetSignalStrength(ok);
1263  ReturnMasterLock(master);
1264  return val;
1265  }
1266  ReturnMasterLock(master); // If we're the master we don't need this lock.
1267 
1268  if (!m_legacyFe && m_hasV5Stats)
1269  {
1270  bool v5_ok = false;
1271  double value = GetSignalStrengthDVBv5(&v5_ok);
1272  if (v5_ok)
1273  {
1274  if (ok)
1275  *ok = v5_ok;
1276  return value;
1277  }
1278  }
1279 
1280  // We use uint16_t for sig because this is correct for DVB API 4.0,
1281  // and works better than the correct int16_t for the 3.x API
1282  uint16_t sig = 0;
1283  int ret = ioctl(m_fdFrontend, FE_READ_SIGNAL_STRENGTH, &sig);
1284  if (ok)
1285  *ok = (0 == ret);
1286 
1287  return sig * (1.0 / 65535.0);
1288 }
1289 
1290 double DVBChannel::GetSNRDVBv5(bool *ok) const
1291 {
1292  struct dtv_property prop = {};
1293  struct dtv_properties cmd = {};
1294 
1295  prop.cmd = DTV_STAT_CNR;
1296  cmd.num = 1;
1297  cmd.props = &prop;
1298  int ret = ioctl(m_fdFrontend, FE_GET_PROPERTY, &cmd);
1299  if (ret < 0)
1300  {
1301  LOG(VB_CHANNEL, LOG_DEBUG, LOC + "FE_GET_PROPERTY DTV_STAT_CNR failed" + ENO);
1302  }
1303  else
1304  {
1305 #if DTV_STAT_FULL_DEBUG
1306  LOG(VB_CHANNEL, LOG_DEBUG, LOC + "DTV_STAT_CNR " +
1307  QString("res=%1 len=%2 scale=%3 val=%4")
1308  .arg(cmd.props->result)
1309  .arg(cmd.props->u.st.len)
1310  .arg(cmd.props->u.st.stat[0].scale)
1311  .arg(cmd.props->u.st.stat[0].svalue));
1312 #endif
1313  }
1314 
1315  bool tmpOk = (ret == 0) && (cmd.props->u.st.len > 0);
1316  if (ok)
1317  *ok = tmpOk;
1318  double value = 0;
1319  if (tmpOk)
1320  {
1321  if (cmd.props->u.st.stat[0].scale == FE_SCALE_DECIBEL)
1322  {
1323  // The measured svalue is in units of 0.001 dB
1324  // Let 50dB+ CNR be 100% quality and 0dB be 0%
1325  // Convert 0.001 dB from 0-50000 to a 0-1 range
1326  value = cmd.props->u.st.stat[0].svalue;
1327  value = value / 50000.0;
1328  if (value > 1.0)
1329  value = 1.0;
1330  else if (value < 0)
1331  value = 0.0;
1332  }
1333  else if (cmd.props->u.st.stat[0].scale == FE_SCALE_RELATIVE)
1334  {
1335  // Return as 16 bit unsigned
1336  value = cmd.props->u.st.stat[0].uvalue / 65535.0;
1337  }
1338  }
1339  return value;
1340 }
1341 
1342 double DVBChannel::GetSNR(bool *ok) const
1343 {
1344  DVBChannel *master = GetMasterLock();
1345  if (master != this)
1346  {
1347  double val = master->GetSNR(ok);
1348  ReturnMasterLock(master);
1349  return val;
1350  }
1351  ReturnMasterLock(master); // If we're the master we don't need this lock.
1352 
1353  if (!m_legacyFe && m_hasV5Stats)
1354  {
1355  bool v5_ok = false;
1356  double value = GetSNRDVBv5(&v5_ok);
1357  if (v5_ok)
1358  {
1359  if (ok)
1360  *ok = v5_ok;
1361  return value;
1362  }
1363  }
1364 
1365  // We use uint16_t for sig because this is correct for DVB API 4.0,
1366  // and works better than the correct int16_t for the 3.x API
1367  uint16_t snr = 0;
1368  int ret = ioctl(m_fdFrontend, FE_READ_SNR, &snr);
1369  if (ok)
1370  *ok = (0 == ret);
1371 
1372  return snr * (1.0 / 65535.0);
1373 }
1374 
1375 double DVBChannel::GetBitErrorRateDVBv5(bool *ok) const
1376 {
1377  std::array<struct dtv_property,2> prop {};
1378  struct dtv_properties cmd = {};
1379 
1380  prop[0].cmd = DTV_STAT_POST_ERROR_BIT_COUNT;
1381  prop[1].cmd = DTV_STAT_POST_TOTAL_BIT_COUNT;
1382  cmd.num = prop.size();
1383  cmd.props = prop.data();
1384  int ret = ioctl(m_fdFrontend, FE_GET_PROPERTY, &cmd);
1385  if (ret < 0)
1386  {
1387  LOG(VB_CHANNEL, LOG_DEBUG, LOC + "FE_GET_PROPERTY DTV_STAT_POST_ERROR_BIT_COUNT failed" + ENO);
1388  }
1389  else
1390  {
1391 #if DTV_STAT_FULL_DEBUG
1392  LOG(VB_CHANNEL, LOG_DEBUG, LOC + "DTV_STAT_POST_ERROR_BIT_COUNT " +
1393  QString("res=%1 len=%2 scale=%3 val=%4 res=%5 len=%6 scale=%7 val=%8")
1394  .arg(cmd.props[0].result)
1395  .arg(cmd.props[0].u.st.len)
1396  .arg(cmd.props[0].u.st.stat[0].scale)
1397  .arg(cmd.props[0].u.st.stat[0].uvalue)
1398  .arg(cmd.props[1].result)
1399  .arg(cmd.props[1].u.st.len)
1400  .arg(cmd.props[1].u.st.stat[0].scale)
1401  .arg(cmd.props[1].u.st.stat[0].uvalue));
1402 #endif
1403  }
1404 
1405  bool tmpOk = (ret == 0) &&
1406  (cmd.props[0].u.st.len > 0) &&
1407  (cmd.props[1].u.st.len > 0);
1408  if (ok)
1409  *ok = tmpOk;
1410  double value = 0;
1411  if (tmpOk)
1412  {
1413  if ((cmd.props[0].u.st.stat[0].scale == FE_SCALE_COUNTER) &&
1414  (cmd.props[1].u.st.stat[0].scale == FE_SCALE_COUNTER) &&
1415  (cmd.props[1].u.st.stat[0].uvalue != 0))
1416  {
1417  value = static_cast<double>(
1418  static_cast<long double>(cmd.props[0].u.st.stat[0].uvalue) /
1419  cmd.props[1].u.st.stat[0].uvalue);
1420  }
1421  }
1422  return value;
1423 }
1424 
1425 double DVBChannel::GetBitErrorRate(bool *ok) const
1426 {
1427  DVBChannel *master = GetMasterLock();
1428  if (master != this)
1429  {
1430  double val = master->GetBitErrorRate(ok);
1431  ReturnMasterLock(master);
1432  return val;
1433  }
1434  ReturnMasterLock(master); // If we're the master we don't need this lock.
1435 
1436  if (!m_legacyFe && m_hasV5Stats)
1437  {
1438  bool v5_ok = false;
1439  double value = GetBitErrorRateDVBv5(&v5_ok);
1440  if (v5_ok)
1441  {
1442  if (ok)
1443  *ok = v5_ok;
1444  return value;
1445  }
1446  }
1447 
1448  uint32_t ber = 0;
1449  int ret = ioctl(m_fdFrontend, FE_READ_BER, &ber);
1450  if (ok)
1451  *ok = (0 == ret);
1452 
1453  return (double) ber;
1454 }
1455 
1457 {
1458  struct dtv_property prop = {};
1459  struct dtv_properties cmd = {};
1460 
1461  prop.cmd = DTV_STAT_ERROR_BLOCK_COUNT;
1462  cmd.num = 1;
1463  cmd.props = &prop;
1464  int ret = ioctl(m_fdFrontend, FE_GET_PROPERTY, &cmd);
1465  if (ret < 0)
1466  {
1467  LOG(VB_CHANNEL, LOG_DEBUG, LOC + "FE_GET_PROPERTY DTV_STAT_ERROR_BLOCK_COUNT failed" + ENO);
1468  }
1469  else
1470  {
1471 #if DTV_STAT_FULL_DEBUG
1472  LOG(VB_CHANNEL, LOG_DEBUG, LOC + "DTV_STAT_ERROR_BLOCK_COUNT " +
1473  QString("res=%1 len=%2 scale=%3 val=%4")
1474  .arg(cmd.props[0].result)
1475  .arg(cmd.props[0].u.st.len)
1476  .arg(cmd.props[0].u.st.stat[0].scale)
1477  .arg(cmd.props[0].u.st.stat[0].svalue));
1478 #endif
1479  }
1480 
1481  bool tmpOk = (ret == 0) && (cmd.props->u.st.len > 0);
1482  if (ok)
1483  *ok = tmpOk;
1484  double value = 0;
1485  if (tmpOk)
1486  {
1487  if (cmd.props->u.st.stat[0].scale == FE_SCALE_COUNTER)
1488  value = cmd.props->u.st.stat[0].uvalue;
1489  }
1490  return value;
1491 }
1492 
1494 {
1495  DVBChannel *master = GetMasterLock();
1496  if (master != this)
1497  {
1498  double val = master->GetUncorrectedBlockCount(ok);
1499  ReturnMasterLock(master);
1500  return val;
1501  }
1502  ReturnMasterLock(master); // If we're the master we don't need this lock.
1503 
1504  if (!m_legacyFe && m_hasV5Stats)
1505  {
1506  bool v5_ok = false;
1507  double value = GetUncorrectedBlockCountDVBv5(&v5_ok);
1508  if (v5_ok)
1509  {
1510  if (ok)
1511  *ok = v5_ok;
1512  return value;
1513  }
1514  }
1515 
1516  uint32_t ublocks = 0;
1517  int ret = ioctl(m_fdFrontend, FE_READ_UNCORRECTED_BLOCKS, &ublocks);
1518  if (ok)
1519  *ok = (0 == ret);
1520 
1521  return static_cast<double>(ublocks);
1522 }
1523 
1525 {
1526  DTVChannel *chan = dvbm;
1528  dvbm = nullptr;
1529 }
1530 
1532 {
1534  auto *dvbm = dynamic_cast<DVBChannel*>(master);
1535  if (master && !dvbm)
1537  return dvbm;
1538 }
1539 
1540 bool DVBChannel::IsMaster(void) const
1541 {
1542  DVBChannel *master = GetMasterLock();
1543  bool is_master = (master == this);
1544  ReturnMasterLock(master);
1545  return is_master;
1546 }
1547 
1548 // Reads all the events off the queue, so we can use select in WaitForBackend.
1549 //
1550 // Note that FE_GET_EVENT is deprecated but there is no alternative yet.
1551 //
1553 {
1554  const int fd = m_fdFrontend;
1555  struct dvb_frontend_event event {};
1556  int ret = 0;
1557  while ((ret = ioctl(fd, FE_GET_EVENT, &event)) == 0);
1558  if ((ret < 0) && (EAGAIN != errno) && (EWOULDBLOCK != errno) && (EOVERFLOW != errno))
1559  {
1560  LOG(VB_CHANNEL, LOG_ERR, LOC +
1561  QString("%1 FE_GET_EVENT failed: ").arg(__func__) + logStrerror(errno));
1562  }
1563 }
1564 
1587 bool DVBChannel::WaitForBackend(std::chrono::milliseconds timeout_ms)
1588 {
1589  const int fd = m_fdFrontend;
1590  auto seconds = duration_cast<std::chrono::seconds>(timeout_ms);
1591  auto usecs = duration_cast<std::chrono::microseconds>(timeout_ms) - seconds;
1592  struct timeval select_timeout = {
1593  static_cast<typeof(select_timeout.tv_sec)>(seconds.count()),
1594  static_cast<typeof(select_timeout.tv_usec)>(usecs.count())};
1595  fd_set fd_select_set;
1596  FD_ZERO( &fd_select_set); // NOLINT(readability-isolate-declaration)
1597  FD_SET (fd, &fd_select_set);
1598 
1599  // Try to wait for some output like an event, unfortunately
1600  // this fails on several DVB cards, so we have a timeout.
1601  int ret = 0;
1602  do ret = select(fd+1, &fd_select_set, nullptr, nullptr, &select_timeout);
1603  while ((-1 == ret) && (EINTR == errno));
1604 
1605  if (-1 == ret)
1606  {
1607  LOG(VB_GENERAL, LOG_ERR, LOC +
1608  QString("%1: Failed to wait on output.").arg(__func__) + ENO);
1609 
1610  return false;
1611  }
1612 
1613  // This is supposed to work on all cards, post 2.6.12...
1614 #if ((DVB_API_VERSION > 5) || ((DVB_API_VERSION == 5) && (DVB_API_VERSION_MINOR > 10)))
1615  fe_status_t status = FE_NONE;
1616 #else // debian9, centos7
1617  fe_status_t status = (fe_status_t)0;
1618 #endif
1619 
1620  if (ioctl(fd, FE_READ_STATUS, &status) < 0)
1621  {
1622  LOG(VB_GENERAL, LOG_ERR, LOC +
1623  QString("%1: FE_READ_STATUS failed.").arg(__func__) + ENO);
1624 
1625  return false;
1626  }
1627 
1628  LOG(VB_CHANNEL, LOG_DEBUG, LOC +
1629  QString("%1: status: 0x%2 %3") .arg(__func__)
1630  .arg(status,2,16,QChar('0')).arg(toString(status)));
1631 
1632  return true;
1633 }
1634 
1635 // Create legacy DVBv3 frontend parameters from DTVMultiplex.
1636 //
1637 static struct dvb_frontend_parameters dtvmultiplex_to_dvbparams(
1638  DTVTunerType tuner_type, const DTVMultiplex &tuning,
1639  uint intermediate_freq, bool can_fec_auto)
1640 {
1641  dvb_frontend_parameters params {};
1642 
1643  params.frequency = tuning.m_frequency;
1644  params.inversion = (fe_spectral_inversion_t) (int) tuning.m_inversion;
1645 
1646  if (DTVTunerType::kTunerTypeDVBS1 == tuner_type)
1647  {
1648  if (tuning.m_modSys == DTVModulationSystem::kModulationSystem_DVBS2)
1649  {
1650  LOG(VB_GENERAL, LOG_ERR,
1651  "DVBChan: Cannot tune to DVB-S2 transport with DVB-S card.");
1652  }
1653 
1654  params.frequency = intermediate_freq;
1655  params.u.qpsk.symbol_rate = tuning.m_symbolRate;
1656  params.u.qpsk.fec_inner = can_fec_auto ? FEC_AUTO
1657  : (fe_code_rate_t) (int) tuning.m_fec;
1658  }
1659 
1660  if (DTVTunerType::kTunerTypeDVBS2 == tuner_type)
1661  {
1662  LOG(VB_GENERAL, LOG_ERR,
1663  "DVBChan: Cannot tune DVB-S2 card with DVBv3 API.");
1664  }
1665 
1666  if (DTVTunerType::kTunerTypeDVBC == tuner_type)
1667  {
1668  params.u.qam.symbol_rate = tuning.m_symbolRate;
1669  params.u.qam.fec_inner = (fe_code_rate_t) (int) tuning.m_fec;
1670  params.u.qam.modulation = (fe_modulation_t) (int) tuning.m_modulation;
1671  }
1672 
1673  if (DTVTunerType::kTunerTypeDVBT == tuner_type ||
1674  DTVTunerType::kTunerTypeDVBT2 == tuner_type)
1675  {
1676  params.u.ofdm.bandwidth = (fe_bandwidth_t) (int) tuning.m_bandwidth;
1677  params.u.ofdm.code_rate_HP = (fe_code_rate_t) (int) tuning.m_hpCodeRate;
1678  params.u.ofdm.code_rate_LP = (fe_code_rate_t) (int) tuning.m_lpCodeRate;
1679  params.u.ofdm.constellation = (fe_modulation_t) (int) tuning.m_modulation;
1680  params.u.ofdm.transmission_mode = (fe_transmit_mode_t) (int) tuning.m_transMode;
1681  params.u.ofdm.guard_interval = (fe_guard_interval_t) (int) tuning.m_guardInterval;
1682  params.u.ofdm.hierarchy_information = (fe_hierarchy_t) (int) tuning.m_hierarchy;
1683  }
1684 
1685  if (DTVTunerType::kTunerTypeATSC == tuner_type)
1686  {
1687  params.u.vsb.modulation = (fe_modulation_t) (int) tuning.m_modulation;
1688  }
1689 
1690  return params;
1691 }
1692 
1693 // Create DTVMultiplex from legacy DVBv3 frontend parameters.
1694 //
1696  DTVTunerType tuner_type, const dvb_frontend_parameters &params)
1697 {
1698  DTVMultiplex tuning;
1699 
1700  tuning.m_frequency = params.frequency;
1701  tuning.m_inversion = params.inversion;
1702 
1703  if ((DTVTunerType::kTunerTypeDVBS1 == tuner_type) ||
1704  (DTVTunerType::kTunerTypeDVBS2 == tuner_type))
1705  {
1706  tuning.m_symbolRate = params.u.qpsk.symbol_rate;
1707  tuning.m_fec = params.u.qpsk.fec_inner;
1708  }
1709 
1710  if (DTVTunerType::kTunerTypeDVBC == tuner_type)
1711  {
1712  tuning.m_symbolRate = params.u.qam.symbol_rate;
1713  tuning.m_fec = params.u.qam.fec_inner;
1714  tuning.m_modulation = params.u.qam.modulation;
1715  }
1716 
1717  if (DTVTunerType::kTunerTypeDVBT == tuner_type ||
1718  DTVTunerType::kTunerTypeDVBT2 == tuner_type)
1719  {
1720  tuning.m_bandwidth = params.u.ofdm.bandwidth;
1721  tuning.m_hpCodeRate = params.u.ofdm.code_rate_HP;
1722  tuning.m_lpCodeRate = params.u.ofdm.code_rate_LP;
1723  tuning.m_modulation = params.u.ofdm.constellation;
1724  tuning.m_transMode = params.u.ofdm.transmission_mode;
1725  tuning.m_guardInterval = params.u.ofdm.guard_interval;
1726  tuning.m_hierarchy = params.u.ofdm.hierarchy_information;
1727  }
1728 
1729  if (DTVTunerType::kTunerTypeATSC == tuner_type)
1730  {
1731  tuning.m_modulation = params.u.vsb.modulation;
1732  }
1733 
1734  return tuning;
1735 }
1736 
1737 // Create a DVBv5 property list from the dtv_multiplex
1738 //
1739 static struct dtv_properties *dtvmultiplex_to_dtvproperties(uint inputId,
1740  DTVTunerType tuner_type, DTVModulationSystem current_sys, const DTVMultiplex &tuning,
1741  uint intermediate_freq, bool can_fec_auto, bool do_tune)
1742 {
1743  DTVModulationSystem delivery_system = current_sys;
1744  uint c = 0;
1745 
1746  LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]: m_modsys:%2 current_sys:%3")
1747  .arg(QString::number(inputId),
1748  tuning.m_modSys.toString(),
1749  current_sys.toString()));
1750 
1751  auto *cmdseq = (struct dtv_properties*) calloc(1, sizeof(struct dtv_properties));
1752  if (!cmdseq)
1753  return nullptr;
1754 
1755  cmdseq->props = (struct dtv_property*) calloc(20, sizeof(*(cmdseq->props)));
1756  if (!(cmdseq->props))
1757  {
1758  free(cmdseq);
1759  return nullptr;
1760  }
1761 
1762  // 20201117 TODO do this only for cx24116 but not for all DVB-S2 demods
1763  //
1764  // The cx24116 DVB-S2 demod announces FE_CAN_FEC_AUTO but has apparently
1765  // trouble with FEC_AUTO on DVB-S2 transponders
1767  can_fec_auto = false;
1768 
1769  // Select delivery system in this order
1770  // - from dtv_multiplex
1771  // - modulation system in the card
1772  // - default based on tuner type
1773  //
1775  {
1776  delivery_system = tuning.m_modSys;
1777  LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1778  .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1779  }
1780  else if (current_sys != DTVModulationSystem::kModulationSystem_UNDEFINED)
1781  {
1782  delivery_system = current_sys;
1783  LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1784  .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1785  }
1786  else if (tuner_type == DTVTunerType::kTunerTypeDVBC)
1787  {
1789  LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1790  .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1791  }
1792  else if (tuner_type == DTVTunerType::kTunerTypeATSC)
1793  {
1795  LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1796  .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1797  }
1798  else if (tuner_type == DTVTunerType::kTunerTypeDVBT)
1799  {
1801  LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1802  .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1803  }
1804  else if (tuner_type == DTVTunerType::kTunerTypeDVBT2)
1805  {
1807  LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1808  .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1809  }
1810  else if (tuner_type == DTVTunerType::kTunerTypeDVBS1)
1811  {
1813  LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1814  .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1815  }
1816  else if (tuner_type == DTVTunerType::kTunerTypeDVBS2)
1817  {
1819  LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1820  .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1821  }
1822 
1823  LOG(VB_CHANNEL, LOG_INFO, QString("DVBChan[%1]: Delivery system: %2")
1824  .arg(inputId).arg(delivery_system.toString()));
1825 
1826  if (delivery_system != DTVModulationSystem::kModulationSystem_UNDEFINED)
1827  {
1828  cmdseq->props[c].cmd = DTV_DELIVERY_SYSTEM;
1829  cmdseq->props[c++].u.data = delivery_system;
1830  }
1831  else
1832  {
1833  LOG(VB_GENERAL, LOG_ERR, QString("DVBChan[%1]: Delivery system: %2")
1834  .arg(inputId).arg(delivery_system.toString()));
1835  }
1836 
1837  // Frequency, modulation and inversion
1838  cmdseq->props[c].cmd = DTV_FREQUENCY;
1839  cmdseq->props[c++].u.data = intermediate_freq ? intermediate_freq : tuning.m_frequency;
1840  cmdseq->props[c].cmd = DTV_MODULATION;
1841  cmdseq->props[c++].u.data = tuning.m_modulation;
1842  cmdseq->props[c].cmd = DTV_INVERSION;
1843  cmdseq->props[c++].u.data = tuning.m_inversion;
1844 
1845  // Symbol rate
1846  if (tuner_type == DTVTunerType::kTunerTypeDVBS1 ||
1847  tuner_type == DTVTunerType::kTunerTypeDVBS2 ||
1848  tuner_type == DTVTunerType::kTunerTypeDVBC)
1849  {
1850  cmdseq->props[c].cmd = DTV_SYMBOL_RATE;
1851  cmdseq->props[c++].u.data = tuning.m_symbolRate;
1852  }
1853 
1854  // Forward error correction
1855  if (tuner_type.IsFECVariable())
1856  {
1857  cmdseq->props[c].cmd = DTV_INNER_FEC;
1858  cmdseq->props[c++].u.data = can_fec_auto ? FEC_AUTO
1859  : (fe_code_rate_t) (int) tuning.m_fec;
1860  }
1861 
1862  // DVB-T/T2 properties
1863  if (tuner_type == DTVTunerType::kTunerTypeDVBT ||
1864  tuner_type == DTVTunerType::kTunerTypeDVBT2)
1865  {
1866  cmdseq->props[c].cmd = DTV_BANDWIDTH_HZ;
1867  cmdseq->props[c++].u.data = (8-tuning.m_bandwidth) * 1000000;
1868  cmdseq->props[c].cmd = DTV_CODE_RATE_HP;
1869  cmdseq->props[c++].u.data = tuning.m_hpCodeRate;
1870  cmdseq->props[c].cmd = DTV_CODE_RATE_LP;
1871  cmdseq->props[c++].u.data = tuning.m_lpCodeRate;
1872  cmdseq->props[c].cmd = DTV_TRANSMISSION_MODE;
1873  cmdseq->props[c++].u.data = tuning.m_transMode;
1874  cmdseq->props[c].cmd = DTV_GUARD_INTERVAL;
1875  cmdseq->props[c++].u.data = tuning.m_guardInterval;
1876  cmdseq->props[c].cmd = DTV_HIERARCHY;
1877  cmdseq->props[c++].u.data = tuning.m_hierarchy;
1878  }
1879 
1880  // DVB-S properties can be set on DVB-S2 tuner
1881  if (delivery_system == DTVModulationSystem::kModulationSystem_DVBS)
1882  {
1883  cmdseq->props[c].cmd = DTV_ROLLOFF;
1884  cmdseq->props[c++].u.data = DTVRollOff::kRollOff_35;
1885  }
1886 
1887  // DVB-S2 properties
1888  if (delivery_system == DTVModulationSystem::kModulationSystem_DVBS2)
1889  {
1890  cmdseq->props[c].cmd = DTV_PILOT;
1891  cmdseq->props[c++].u.data = PILOT_AUTO;
1892  cmdseq->props[c].cmd = DTV_ROLLOFF;
1893  cmdseq->props[c++].u.data = tuning.m_rolloff;
1894  }
1895 
1896  if (do_tune)
1897  cmdseq->props[c++].cmd = DTV_TUNE;
1898 
1899  cmdseq->num = c;
1900 
1901  return cmdseq;
1902 }
DTVMultiplex::m_frequency
uint64_t m_frequency
Definition: dtvmultiplex.h:94
MSqlQuery::isActive
bool isActive(void) const
Definition: mythdbcon.h:215
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:813
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:127
DVBChannel::CheckModulation
bool CheckModulation(DTVModulation modulation) const
Return true iff modulation is supported modulation on the frontend.
Definition: dvbchannel.cpp:701
DTVMultiplex
Definition: dtvmultiplex.h:24
O_NONBLOCK
#define O_NONBLOCK
Definition: compat.h:341
DVBChannel::GetUncorrectedBlockCount
double GetUncorrectedBlockCount(bool *ok=nullptr) const
Returns # of uncorrected blocks since last call. First call undefined.
Definition: dvbchannel.cpp:1493
ChannelBase::Init
virtual bool Init(QString &startchannel, bool setchan)
Definition: channelbase.cpp:66
DVBChannel::Init
bool Init(QString &startchannel, bool setchan) override
Definition: dvbchannel.cpp:552
MythDate::toString
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:84
DVBChannel::m_extModulations
uint64_t m_extModulations
Definition: dvbchannel.h:145
logStrerror
QString logStrerror(int errnum)
Verbose helper function for ENO macro.
Definition: logging.cpp:1019
ENO
#define ENO
This can be appended to the LOG args with "+".
Definition: mythlogging.h:73
DTVCodeRate::kFEC_3_4
@ kFEC_3_4
Definition: dtvconfparserhelpers.h:294
DVBChannel::ReturnMasterLock
static void ReturnMasterLock(DVBChannel *&dvbm)
Definition: dvbchannel.cpp:1524
DTVChannel::ReturnMasterLock
static void ReturnMasterLock(DTVChannelP &chan)
Definition: dtvchannel.cpp:148
DVBChannel::m_currentSys
DTVModulationSystem m_currentSys
Definition: dvbchannel.h:154
DTVTunerType::kTunerTypeDVBC
static const int kTunerTypeDVBC
Definition: dtvconfparserhelpers.h:95
dvbcam.h
DVBChannel::m_tuneLock
QMutex m_tuneLock
Definition: dvbchannel.h:158
DVBChannel::IsTuningParamsProbeSupported
bool IsTuningParamsProbeSupported(void) const
Returns true iff tuning info probing is working.
Definition: dvbchannel.cpp:988
DiSEqCDevSCR::GetIntermediateFrequency
uint32_t GetIntermediateFrequency(uint32_t frequency) const
Definition: diseqc.cpp:2211
DVBChannel::m_frontendName
QString m_frontendName
Definition: dvbchannel.h:143
DVBChannel::GetRotor
const DiSEqCDevRotor * GetRotor(void) const
Returns rotor object if it exists, nullptr otherwise.
Definition: dvbchannel.cpp:1158
DTVMultiplex::m_rolloff
DTVRollOff m_rolloff
Definition: dtvmultiplex.h:107
DiSEqCDevRotor
Rotor class.
Definition: diseqc.h:302
DVBChannel::m_frequencyMinimum
uint64_t m_frequencyMinimum
Definition: dvbchannel.h:146
DVBChannel::DVBChannel
DVBChannel(QString device, TVRec *parent=nullptr)
Definition: dvbchannel.cpp:80
DTVGuardInterval::kGuardIntervalAuto
@ kGuardIntervalAuto
Definition: dtvconfparserhelpers.h:502
mythdb.h
DTVModulationSystem::kModulationSystem_DVBS2
@ kModulationSystem_DVBS2
Definition: dtvconfparserhelpers.h:662
DVBChannel::GetBitErrorRateDVBv5
double GetBitErrorRateDVBv5(bool *ok) const
Get Bit Error Rate from the DVBv5 interface.
Definition: dvbchannel.cpp:1375
DVBChannel::CheckCodeRate
bool CheckCodeRate(DTVCodeRate rate) const
Return true iff rate is supported rate on the frontend.
Definition: dvbchannel.cpp:682
DTVCodeRate::kFEC_2_3
@ kFEC_2_3
Definition: dtvconfparserhelpers.h:293
DTVChannel::s_master_map
static MasterMap s_master_map
Definition: dtvchannel.h:179
DTVModulation::kModulation32APSK
@ kModulation32APSK
Definition: dtvconfparserhelpers.h:369
DTVCodeRate::kFEC_5_6
@ kFEC_5_6
Definition: dtvconfparserhelpers.h:296
DTVTunerType::kTunerTypeDVBS1
static const int kTunerTypeDVBS1
Definition: dtvconfparserhelpers.h:93
DTVCodeRate::kFECNone
@ kFECNone
Definition: dtvconfparserhelpers.h:291
DTVModulation::kModulation16VSB
@ kModulation16VSB
Definition: dtvconfparserhelpers.h:366
DTVModulation::kModulation16APSK
@ kModulation16APSK
Definition: dtvconfparserhelpers.h:368
ProgramMapTable
A PMT table maps a program described in the ProgramAssociationTable to various PID's which describe t...
Definition: mpegtables.h:694
DiSEqCDevTree::Execute
bool Execute(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning)
Applies settings to the entire tree.
Definition: diseqc.cpp:509
dvbparams_to_dtvmultiplex
static DTVMultiplex dvbparams_to_dtvmultiplex(DTVTunerType tuner_type, const dvb_frontend_parameters &params)
Definition: dvbchannel.cpp:1695
VERBOSE_LEVEL_CHECK
static bool VERBOSE_LEVEL_CHECK(uint64_t mask, LogLevel_t level)
Definition: mythlogging.h:29
DVBChannel::CheckOptions
void CheckOptions(DTVMultiplex &t) const override
Checks tuning for problems, and tries to fix them.
Definition: dvbchannel.cpp:575
DVBCam::Stop
bool Stop(void)
Definition: dvbcam.cpp:120
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:204
DTVMultiplex::m_hierarchy
DTVHierarchy m_hierarchy
Definition: dtvmultiplex.h:103
DVBChannel::m_symbolRateMaximum
uint m_symbolRateMaximum
Definition: dvbchannel.h:149
CardUtil::HasDVBCRCBug
static bool HasDVBCRCBug(const QString &device)
Returns true if and only if the device munges PAT/PMT tables, and then doesn't fix the CRC.
Definition: cardutil.cpp:788
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:619
DTVHierarchy::kHierarchyAuto
@ kHierarchyAuto
Definition: dtvconfparserhelpers.h:561
ChannelBase::m_inputId
uint m_inputId
Definition: channelbase.h:137
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
DTVChannel::GetMasterLock
static DTVChannel * GetMasterLock(const QString &key)
Definition: dtvchannel.cpp:136
DTVRollOff::kRollOff_35
@ kRollOff_35
Definition: dtvconfparserhelpers.h:736
DTVMultiplex::m_bandwidth
DTVBandwidth m_bandwidth
Definition: dtvmultiplex.h:97
DiSEqCDevSettings::Load
bool Load(uint card_input_id)
Loads configuration chain from DB for specified card input id.
Definition: diseqc.cpp:128
DVBChannel::m_key
QString m_key
Definition: dvbchannel.h:173
DVBChannel::GetSignalStrength
double GetSignalStrength(bool *ok=nullptr) const
Returns signal strength in the range [0.0..1.0] (non-calibrated).
Definition: dvbchannel.cpp:1257
DVBChannel::SetPMT
void SetPMT(const ProgramMapTable *pmt)
Tells the Conditional Access Module which streams we wish to decode.
Definition: dvbchannel.cpp:726
DVBChannel::m_isOpen
IsOpenMap m_isOpen
Definition: dvbchannel.h:135
DVBChannel::m_frequencyMaximum
uint64_t m_frequencyMaximum
Definition: dvbchannel.h:147
DTVModulation::kModulationQPSK
@ kModulationQPSK
Definition: dtvconfparserhelpers.h:358
DTVCodeRate::kFECAuto
@ kFECAuto
Definition: dtvconfparserhelpers.h:300
DVBCam::IsRunning
bool IsRunning(void) const
Definition: dvbcam.h:30
dvbchannel.h
DiSEqCDevTree::Open
void Open(int fd_frontend, bool is_SCR)
Retrieve device tree.
Definition: diseqc.cpp:790
true
VERBOSE_PREAMBLE Most true
Definition: verbosedefs.h:95
dtvmultiplex_to_dvbparams
static struct dvb_frontend_parameters dtvmultiplex_to_dvbparams(DTVTunerType tuner_type, const DTVMultiplex &tuning, uint intermediate_freq, bool can_fec_auto)
Definition: dvbchannel.cpp:1637
close
#define close
Definition: compat.h:43
DVBChannel::IsMaster
bool IsMaster(void) const override
Returns true if this is the first of a number of multi-rec devs.
Definition: dvbchannel.cpp:1540
DTVModulationSystem::kModulationSystem_UNDEFINED
@ kModulationSystem_UNDEFINED
Definition: dtvconfparserhelpers.h:656
DTVCodeRate
Definition: dtvconfparserhelpers.h:280
DTVTunerType
Definition: dtvconfparserhelpers.h:76
DVBChannel::m_capabilities
uint64_t m_capabilities
Definition: dvbchannel.h:144
DVBCam::SetTimeOffset
void SetTimeOffset(double offset_in_seconds)
Definition: dvbcam.cpp:375
DTVTransmitMode::kTransmissionModeAuto
@ kTransmissionModeAuto
Definition: dtvconfparserhelpers.h:437
DTVModulation::kModulationQAM256
@ kModulationQAM256
Definition: dtvconfparserhelpers.h:363
CardUtil::SetDeliverySystem
static int SetDeliverySystem(uint inputid)
DTVMultiplex::m_inversion
DTVInversion m_inversion
Definition: dtvmultiplex.h:96
DVBCam
Definition: dvbcam.h:22
DTVModulation::kModulationQAM16
@ kModulationQAM16
Definition: dtvconfparserhelpers.h:359
TVRec::GetInputId
uint GetInputId(void) const
Returns the inputid.
Definition: tv_rec.h:234
DVBChannel::m_prevTuning
DTVMultiplex m_prevTuning
Definition: dvbchannel.h:162
DTVCodeRate::kFEC_1_2
@ kFEC_1_2
Definition: dtvconfparserhelpers.h:292
DVBChannel::m_dvbCam
DVBCam * m_dvbCam
Definition: dvbchannel.h:140
dvbtypes.h
DTVMultiplex::m_mplex
uint m_mplex
Definition: dtvmultiplex.h:110
CardUtil::GetMinSignalMonitoringDelay
static std::chrono::milliseconds GetMinSignalMonitoringDelay(const QString &device)
Definition: cardutil.cpp:795
DVBChannel::m_hasV5Stats
bool m_hasV5Stats
Definition: dvbchannel.h:153
ChannelBase::m_curChannelName
QString m_curChannelName
Definition: channelbase.h:135
DTVMultiplex::m_guardInterval
DTVGuardInterval m_guardInterval
Definition: dtvmultiplex.h:102
DVBChannel::WaitForBackend
bool WaitForBackend(std::chrono::milliseconds timeout_ms)
Waits for backend to get tune message.
Definition: dvbchannel.cpp:1587
DVBChannel::Tune
bool Tune(const DTVMultiplex &tuning) override
This performs the actual frequency tuning and in some cases input switching.
Definition: dvbchannel.cpp:744
DVBChannel::Close
void Close(void) override
Closes the channel changing hardware to use.
Definition: dvbchannel.h:39
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:551
DTVChannel::SetSIStandard
void SetSIStandard(const QString &si_std)
Sets PSIP table standard: MPEG, DVB, ATSC, or OpenCable.
Definition: dtvchannel.cpp:51
DVBChannel::~DVBChannel
~DVBChannel() override
Definition: dvbchannel.cpp:106
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:226
DTVTunerType::IsModulationVariable
bool IsModulationVariable(void) const
Definition: dtvconfparserhelpers.h:141
DVBCam::Start
bool Start(void)
Definition: dvbcam.cpp:88
DVBChannel::GetSNR
double GetSNR(bool *ok=nullptr) const
Returns signal/noise in the range [0..1.0].
Definition: dvbchannel.cpp:1342
DVBChannel::m_symbolRateMinimum
uint m_symbolRateMinimum
Definition: dvbchannel.h:148
DVBChannel::m_sysList
QList< DTVModulationSystem > m_sysList
Definition: dvbchannel.h:155
DVBChannel::m_fdFrontend
int m_fdFrontend
Definition: dvbchannel.h:171
DiSEqCDevSCR
Unicable / SCR Class.
Definition: diseqc.h:382
DVBChannel::m_version
uint m_version
Definition: dvbchannel.h:151
DTVTunerType::toString
QString toString() const
Definition: dtvconfparserhelpers.h:154
DTVModulation::kModulationQAM128
@ kModulationQAM128
Definition: dtvconfparserhelpers.h:362
DTVMultiplex::m_hpCodeRate
DTVCodeRate m_hpCodeRate
Definition: dtvmultiplex.h:98
DTVInversion::kInversionAuto
@ kInversionAuto
Definition: dtvconfparserhelpers.h:175
LOC
#define LOC
Definition: dvbchannel.cpp:70
DTVModulation::kModulationQAM32
@ kModulationQAM32
Definition: dtvconfparserhelpers.h:360
DVBChannel::m_diseqcSettings
DiSEqCDevSettings m_diseqcSettings
Definition: dvbchannel.h:138
DTVInversion::kInversionOff
@ kInversionOff
Definition: dtvconfparserhelpers.h:173
DiSEqCDevLNB
LNB Class.
Definition: diseqc.h:446
DTVMultiplex::m_modSys
DTVModulationSystem m_modSys
Definition: dtvmultiplex.h:106
DTVModulation::kModulationQAMAuto
@ kModulationQAMAuto
Definition: dtvconfparserhelpers.h:364
DTVMultiplex::m_fec
DTVCodeRate m_fec
Definition: dtvmultiplex.h:105
DTVMultiplex::toString
QString toString() const
Definition: dtvmultiplex.cpp:35
DVBChannel::m_sigMonDelay
std::chrono::milliseconds m_sigMonDelay
Definition: dvbchannel.h:167
uint
unsigned int uint
Definition: compat.h:81
MythCoreContext::GetDVBv3
bool GetDVBv3(void) const
Definition: mythcorecontext.h:330
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
DVBChannel::m_legacyFe
bool m_legacyFe
Definition: dvbchannel.h:152
DVBChannel::m_lastLnbDevId
uint m_lastLnbDevId
Definition: dvbchannel.h:164
DiSEqCDev::FindTree
static DiSEqCDevTree * FindTree(uint cardid)
Retrieve device tree.
Definition: diseqc.cpp:237
DTVModulationSystem::kModulationSystem_ATSC
@ kModulationSystem_ATSC
Definition: dtvconfparserhelpers.h:667
DVBChannel::m_desiredTuning
DTVMultiplex m_desiredTuning
Definition: dvbchannel.h:161
DVBChannel::GetUncorrectedBlockCountDVBv5
double GetUncorrectedBlockCountDVBv5(bool *ok) const
Get Uncorrected Block Count from the DVBv5 interface.
Definition: dvbchannel.cpp:1456
DTVTunerType::IsFECVariable
bool IsFECVariable(void) const
Definition: dtvconfparserhelpers.h:134
DVBChannel::Retune
bool Retune(void) override
Definition: dvbchannel.cpp:980
DTVBandwidth::kBandwidthAuto
@ kBandwidthAuto
Definition: dtvconfparserhelpers.h:231
channelutil.h
DTVTunerType::kTunerTypeDVBS2
static const int kTunerTypeDVBS2
Definition: dtvconfparserhelpers.h:94
DTVMultiplex::m_symbolRate
uint64_t m_symbolRate
Definition: dtvmultiplex.h:95
DiSEqCDevTree::FindLNB
DiSEqCDevLNB * FindLNB(const DiSEqCDevSettings &settings)
Returns the LNB device object selected by the configuration chain.
Definition: diseqc.cpp:573
DTVModulationSystem::toString
QString toString() const
Definition: dtvconfparserhelpers.h:719
CardUtil::GetDeviceName
static QString GetDeviceName(dvb_dev_type_t type, const QString &device)
Definition: cardutil.cpp:2954
DVBChannel::GetBitErrorRate
double GetBitErrorRate(bool *ok=nullptr) const
Returns # of corrected bits since last call. First call undefined.
Definition: dvbchannel.cpp:1425
DiSEqCDevTree::Close
void Close(void)
Definition: diseqc.h:108
MythDate::currentMSecsSinceEpochAsDuration
std::chrono::milliseconds currentMSecsSinceEpochAsDuration(void)
Definition: mythdate.cpp:198
DVBChannel
Provides interface to the tuning hardware when using DVB drivers.
Definition: dvbchannel.h:31
DVBChannel::Open
bool Open(void) override
Opens the channel changing hardware for use.
Definition: dvbchannel.h:37
DVBChannel::GetSNRDVBv5
double GetSNRDVBv5(bool *ok) const
Get SNR from the DVBv5 interface [0-1.0] It is transformed to a linear relative scale if provided in ...
Definition: dvbchannel.cpp:1290
DTVChannel::m_tunerType
DTVTunerType m_tunerType
Definition: dtvchannel.h:161
DTVChannel::s_master_map_lock
static QReadWriteLock s_master_map_lock
Definition: dtvchannel.h:178
dtvmultiplex_to_dtvproperties
static struct dtv_properties * dtvmultiplex_to_dtvproperties(uint inputId, DTVTunerType tuner_type, DTVModulationSystem current_sys, const DTVMultiplex &tuning, uint intermediate_freq, bool can_fec_auto, bool do_tune=true)
Definition: dvbchannel.cpp:1739
DVBChannel::m_hwLock
QRecursiveMutex m_hwLock
Definition: dvbchannel.h:159
DiSEqCDevTree::FindRotor
DiSEqCDevRotor * FindRotor(const DiSEqCDevSettings &settings, uint index=0)
Returns the nth rotor device object in the tree.
Definition: diseqc.cpp:550
DTVModulationSystem
Definition: dtvconfparserhelpers.h:644
cardutil.h
DVBChannel::m_firstTune
bool m_firstTune
Definition: dvbchannel.h:168
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:889
std
Definition: mythchrono.h:23
DVBChannel::SetTimeOffset
void SetTimeOffset(double offset)
Tells the Conditional Access Module the offset from the computers utc time to dvb time.
Definition: dvbchannel.cpp:738
DVBChannel::m_tuningDelay
std::chrono::milliseconds m_tuningDelay
Definition: dvbchannel.h:166
DVBChannel::CheckFrequency
void CheckFrequency(uint64_t frequency) const
Checks tuning frequency.
Definition: dvbchannel.cpp:563
DVBChannel::m_diseqcTree
DiSEqCDevTree * m_diseqcTree
Definition: dvbchannel.h:139
DTVTunerType::IsDiSEqCSupported
bool IsDiSEqCSupported(void) const
Definition: dtvconfparserhelpers.h:148
CardUtil::GetDeliverySystem
static DTVModulationSystem GetDeliverySystem(uint inputid)
Definition: cardutil.cpp:906
TVRec
This is the coordinating class of the Recorder Subsystem.
Definition: tv_rec.h:142
DTVMultiplex::m_sistandard
QString m_sistandard
Definition: dtvmultiplex.h:111
DVBCam::SetPMT
void SetPMT(const ChannelBase *chan, const ProgramMapTable *pmt)
Definition: dvbcam.cpp:342
DiSEqCDevTree::FindSCR
DiSEqCDevSCR * FindSCR(const DiSEqCDevSettings &settings)
Returns the SCR device object selected by the configuration chain.
Definition: diseqc.cpp:596
CardUtil::GetSourceID
static uint GetSourceID(uint inputid)
Definition: cardutil.cpp:1944
DVBChannel::ProbeTuningParams
bool ProbeTuningParams(DTVMultiplex &tuning) const
Fetches DTVMultiplex params from driver.
Definition: dvbchannel.cpp:1034
DVBChannel::HasLock
bool HasLock(bool *ok=nullptr) const
Returns true iff we have a signal carrier lock.
Definition: dvbchannel.cpp:1166
tv_rec.h
DVBChannel::m_hasCrcBug
bool m_hasCrcBug
Definition: dvbchannel.h:174
DVBChannel::m_device
QString m_device
Definition: dvbchannel.h:172
DVBChannel::GetMasterLock
DVBChannel * GetMasterLock(void) const
Definition: dvbchannel.cpp:1531
concurrent_tunings_delay
static constexpr std::chrono::milliseconds concurrent_tunings_delay
Definition: dvbchannel.cpp:67
CardUtil::ConvertToTunerType
static DTVTunerType ConvertToTunerType(DTVModulationSystem delsys)
Definition: cardutil.cpp:805
DTVModulation::kModulation8VSB
@ kModulation8VSB
Definition: dtvconfparserhelpers.h:365
DTVMultiplex::m_modulation
DTVModulation m_modulation
Definition: dtvmultiplex.h:100
DTVTunerType::kTunerTypeATSC
static const int kTunerTypeATSC
Definition: dtvconfparserhelpers.h:98
DVBChannel::IsOpen
bool IsOpen(void) const override
Reports whether channel is already open.
Definition: dvbchannel.cpp:544
uint16_t
unsigned short uint16_t
Definition: iso6937tables.h:3
DVBChannel::GetChanID
int GetChanID(void) const override
Returns Channel ID.
Definition: dvbchannel.cpp:1094
DVB_DEV_FRONTEND
@ DVB_DEV_FRONTEND
Definition: cardutil.h:30
DTVChannel
Class providing a generic interface to digital tuning hardware.
Definition: dtvchannel.h:33
DTVCodeRate::kFEC_7_8
@ kFEC_7_8
Definition: dtvconfparserhelpers.h:298
DiSEqCDevDevice::GetDeviceID
uint GetDeviceID(void) const
Definition: diseqc.h:170
DTVModulationSystem::kModulationSystem_DVBT2
@ kModulationSystem_DVBT2
Definition: dtvconfparserhelpers.h:672
DTVTunerType::kTunerTypeDVBT
static const int kTunerTypeDVBT
Definition: dtvconfparserhelpers.h:96
DVBChannel::DrainDVBEvents
void DrainDVBEvents(void)
Definition: dvbchannel.cpp:1552
CardUtil::CapabilitiesToString
static QStringList CapabilitiesToString(uint64_t capabilities)
Definition: cardutil.cpp:2471
DTVMultiplex::IsEqual
bool IsEqual(DTVTunerType type, const DTVMultiplex &other, uint freq_range=0, bool fuzzy=false) const
Definition: dtvmultiplex.cpp:52
DTVTunerType::kTunerTypeDVBT2
static const int kTunerTypeDVBT2
Definition: dtvconfparserhelpers.h:97
DVBChannel::GetSignalStrengthDVBv5
double GetSignalStrengthDVBv5(bool *ok) const
Get Signal strength from the DVBv5 interface [0-1.0] It is transformed to a linear relative scale if ...
Definition: dvbchannel.cpp:1200
ChannelBase::InitializeInput
virtual bool InitializeInput(void)
Fills in input map from DB.
Definition: channelbase.cpp:548
DVBChannel::m_tuneDelayLock
QMutex m_tuneDelayLock
Definition: dvbchannel.h:177
DTVCodeRate::kFEC_8_9
@ kFEC_8_9
Definition: dtvconfparserhelpers.h:299
DVBChannel::s_lastTuning
static std::chrono::milliseconds s_lastTuning
Definition: dvbchannel.h:176
DTVModulation::kModulationQAM64
@ kModulationQAM64
Definition: dtvconfparserhelpers.h:361
DTVCodeRate::kFEC_6_7
@ kFEC_6_7
Definition: dtvconfparserhelpers.h:297
DTVModulationSystem::kModulationSystem_DVBS
@ kModulationSystem_DVBS
Definition: dtvconfparserhelpers.h:661
DTVModulationSystem::kModulationSystem_DVBT
@ kModulationSystem_DVBT
Definition: dtvconfparserhelpers.h:659
DTVMultiplex::m_transMode
DTVTransmitMode m_transMode
Definition: dtvmultiplex.h:101
DTVModulation::kModulation8PSK
@ kModulation8PSK
Definition: dtvconfparserhelpers.h:367
ChannelBase::m_pParent
TVRec * m_pParent
Definition: channelbase.h:134
DTVModulation
Definition: dtvconfparserhelpers.h:347
DTVModulationSystem::kModulationSystem_DVBC_ANNEX_A
@ kModulationSystem_DVBC_ANNEX_A
Definition: dtvconfparserhelpers.h:657
DiSEqCDevLNB::GetIntermediateFrequency
uint32_t GetIntermediateFrequency(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning) const
Calculate proper intermediate frequency for the given settings and tuning parameters.
Definition: diseqc.cpp:2518
DTVCodeRate::kFEC_4_5
@ kFEC_4_5
Definition: dtvconfparserhelpers.h:295
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:838
DTVMultiplex::m_lpCodeRate
DTVCodeRate m_lpCodeRate
Definition: dtvmultiplex.h:99