MythTV  master
diseqc.cpp
Go to the documentation of this file.
1 /* -*- Mode: c++ -*-
2  * \file dvbdevtree.cpp
3  * \brief DVB-S Device Tree Control Classes.
4  * \author Copyright (C) 2006, Yeasah Pell
5  */
6 
7 // Std C headers
8 #include <cstring>
9 #include <cmath>
10 #include <unistd.h>
11 
12 // POSIX headers
13 #include <sys/time.h>
14 
15 // Qt headers
16 #include <QString>
17 
18 // MythTV headers
19 #include "libmythbase/compat.h"
21 #include "libmythbase/mythdb.h"
23 
24 #include "diseqc.h"
25 #include "dtvmultiplex.h"
26 
27 #ifdef USING_DVB
28 # include "recorders/dvbtypes.h"
29 #else
30 static constexpr uint8_t SEC_VOLTAGE_13 { 0 };
31 static constexpr uint8_t SEC_VOLTAGE_18 { 1 };
32 static constexpr uint8_t SEC_VOLTAGE_OFF { 2 };
33 #endif
34 
35 // DiSEqC sleep intervals per eutelsat spec
36 static constexpr useconds_t DISEQC_SHORT_WAIT { 15 * 1000 };
37 static constexpr useconds_t DISEQC_LONG_WAIT { 100 * 1000 };
38 static constexpr useconds_t DISEQC_POWER_ON_WAIT { 500 * 1000 };
39 static constexpr useconds_t DISEQC_POWER_OFF_WAIT { (1000 * 1000) - 1 };
40 
41 #ifdef USING_DVB
42 // Number of times to retry ioctls after receiving ETIMEDOUT before giving up
43 static constexpr uint8_t TIMEOUT_RETRIES { 10 };
44 static constexpr useconds_t TIMEOUT_WAIT { 250 * 1000 };
45 
46 // Framing byte
47 static constexpr uint8_t DISEQC_FRM { 0xe0 };
48 static constexpr uint8_t DISEQC_FRM_REPEAT {1 << 0};
49 //static constexpr uint8_t DISEQC_FRM_REPLY_REQ {1 << 1};
50 #endif
51 
52 // Address byte
53 enum DISEQC_ADRS : std::uint8_t {
59  DISEQC_ADR_SW = 0x15,
66 };
67 
68 // Command byte
69 enum DISEQC_CMDS : std::uint8_t {
86 };
87 
88 static constexpr double TO_RADS { M_PI / 180.0 };
89 static constexpr double TO_DEC { 180.0 / M_PI };
90 
91 static constexpr double EPS { 1E-4 };
92 
93 #define LOC QString("DiSEqCDevTree: ")
94 
96 
98 {
99  for (const auto &item : table)
100  if (type == item.value)
101  return item.name;
102  return {};
103 }
104 
106  const TypeTableVec &table)
107 {
108  for (const auto &item : table)
109  if (type == item.name)
110  return item.value;
111  return table[0].value;
112 }
113 
115 
128 bool DiSEqCDevSettings::Load(uint card_input_id)
129 {
130  if (card_input_id == m_inputId)
131  return true;
132 
133  m_config.clear();
134 
135  // load settings from DB
136  MSqlQuery query(MSqlQuery::InitCon());
137  query.prepare(
138  "SELECT diseqcid, value "
139  "FROM diseqc_config "
140  "WHERE cardinputid = :INPUTID");
141 
142  query.bindValue(":INPUTID", card_input_id);
143  if (!query.exec() || !query.isActive())
144  {
145  MythDB::DBError("DiSEqCDevSettings::Load", query);
146  return false;
147  }
148 
149  while (query.next())
150  m_config[query.value(0).toUInt()] = query.value(1).toDouble();
151 
152  m_inputId = card_input_id;
153 
154  return true;
155 }
156 
162 bool DiSEqCDevSettings::Store(uint card_input_id) const
163 {
164  MSqlQuery query(MSqlQuery::InitCon());
165 
166  // clear out previous settings
167  query.prepare(
168  "DELETE from diseqc_config "
169  "WHERE cardinputid = :INPUTID");
170  query.bindValue(":INPUTID", card_input_id);
171 
172  if (!query.exec() || !query.isActive())
173  {
174  MythDB::DBError("DiSEqCDevSettings::Store 1", query);
175  return false;
176  }
177 
178  // insert new settings
179  query.prepare(
180  "INSERT INTO diseqc_config "
181  " ( cardinputid, diseqcid, value) "
182  "VALUES (:INPUTID, :DEVID, :VALUE) ");
183 
184  for (auto it = m_config.cbegin(); it != m_config.cend(); ++it)
185  {
186  query.bindValue(":INPUTID", card_input_id);
187  query.bindValue(":DEVID", it.key());
188  query.bindValue(":VALUE", *it);
189  if (!query.exec() || !query.isActive())
190  {
191  MythDB::DBError("DiSEqCDevSettings::Store 2", query);
192  return false;
193  }
194  }
195 
196  return true;
197 }
198 
205 {
206  uint_to_dbl_t::const_iterator it = m_config.find(devid);
207 
208  if (it != m_config.end())
209  return *it;
210 
211  return 0.0;
212 }
213 
219 void DiSEqCDevSettings::SetValue(uint devid, double value)
220 {
221  m_config[devid] = value;
222  m_inputId = UINT_MAX;
223 }
224 
226 
232 
238 {
239  return s_trees.FindTree(cardid);
240 }
241 
246 {
248 }
249 
251 
257 {
258  InvalidateTrees();
259 }
260 
266 {
267  QMutexLocker lock(&m_treesLock);
268 
269  cardid_to_diseqc_tree_t::iterator it = m_trees.find(cardid);
270  if (it != m_trees.end())
271  return *it;
272 
273  auto *tree = new DiSEqCDevTree;
274  tree->Load(cardid);
275  m_trees[cardid] = tree;
276 
277  return tree;
278 }
279 
284 {
285  QMutexLocker lock(&m_treesLock);
286 
287  for (auto & tree : m_trees)
288  delete tree;
289 
290  m_trees.clear();
291 }
292 
294 
299 const uint DiSEqCDevTree::kFirstFakeDiSEqCID = 0xf0000000;
300 
302 {
303  delete m_root;
304 }
305 
311 bool DiSEqCDevTree::Load(const QString &device)
312 {
313  // lookup configuration for this card
314  MSqlQuery query(MSqlQuery::InitCon());
315  query.prepare(
316  "SELECT cardid "
317  "FROM capturecard "
318  "WHERE hostname = :HOSTNAME AND "
319  " videodevice = :VIDEODEVICE "
320  "LIMIT 1");
321  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
322  query.bindValue(":VIDEODEVICE", device);
323 
324  uint cardid = 0;
325 
326  if (!query.exec())
327  {
328  MythDB::DBError("DiSEqCDevTree::Load", query);
329  }
330  else if (query.next())
331  {
332  cardid = query.value(0).toUInt();
333  }
334 
335  return Load(cardid);
336 }
337 
344 {
345  // clear children
346 
347  // TODO find root cause so that "delete m_root" can be enabled again, see ticket #13465
348  // Not doing the "delete m_root" fixes a segfault but creates a memory leak
349 #if 0
350  delete m_root;
351 #endif
352  m_delete.clear();
353  m_root = nullptr;
354 
355  // lookup configuration for this card
356  MSqlQuery query(MSqlQuery::InitCon());
357  query.prepare(
358  "SELECT diseqcid, cardtype, inputname "
359  "FROM capturecard "
360  "WHERE cardid = :CARDID");
361  query.bindValue(":CARDID", cardid);
362 
363  if (!query.exec())
364  {
365  MythDB::DBError("DiSEqCDevTree::Load", query);
366  }
367  else if (!query.next())
368  {
369  return m_root;
370  }
371 
372  if (query.value(0).toBool())
373  {
375  *this, query.value(0).toUInt());
376  }
377  else if ((query.value(1).toString().toUpper() == "DVB") &&
378  ((query.value(2).toString().toUpper() == "DVB-S" ) ||
379  (query.value(2).toString().toUpper() == "DVB-S2") ))
380  {
381  LOG(VB_GENERAL, LOG_WARNING, LOC +
382  QString("No device tree for cardid %1").arg(cardid));
383  }
384 
385  return m_root;
386 }
387 
393 bool DiSEqCDevTree::Exists(int cardid)
394 {
395  // lookup configuration for this card
396  MSqlQuery query(MSqlQuery::InitCon());
397  query.prepare(
398  "SELECT diseqcid "
399  "FROM capturecard "
400  "WHERE cardid = :CARDID");
401  query.bindValue(":CARDID", cardid);
402 
403  if (!query.exec())
404  {
405  MythDB::DBError("DiSEqCDevTree::Load", query);
406  }
407  else if (query.next())
408  {
409  if (query.value(0).toUInt() > 0)
410  return true;
411  }
412 
413  return false;
414 }
415 
422 bool DiSEqCDevTree::Store(uint cardid, const QString &device)
423 {
424  MSqlQuery query0(MSqlQuery::InitCon());
425 
426  // apply pending node deletions
427  if (!m_delete.empty())
428  {
429  MSqlQuery query1(MSqlQuery::InitCon());
430 
431  query0.prepare(
432  "DELETE FROM diseqc_tree "
433  "WHERE diseqcid = :DEVID");
434  query1.prepare(
435  "DELETE FROM diseqc_config "
436  "WHERE diseqcid = :DEVID");
437 
438  for (uint devid : m_delete)
439  {
440  query0.bindValue(":DEVID", devid);
441  if (!query0.exec())
442  MythDB::DBError("DiSEqCDevTree::Store 1", query0);
443 
444  query1.bindValue(":DEVID", devid);
445  if (!query1.exec())
446  MythDB::DBError("DiSEqCDevTree::Store 2", query1);
447 
448  }
449  m_delete.clear();
450  }
451 
452  // store changed and new nodes
453  uint devid = 0;
454  if (m_root && m_root->Store())
455  devid = m_root->GetDeviceID();
456  else if (m_root)
457  {
458  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to save DiSEqC tree.");
459  return false;
460  }
461 
462  // update capture card to point to tree, or 0 if there is no tree
463  query0.prepare(
464  "UPDATE capturecard "
465  "SET diseqcid = :DEVID "
466  "WHERE (hostname = :HOSTNAME AND "
467  " videodevice = :VIDEODEVICE) "
468  " OR cardid = :CARDID");
469  query0.bindValue(":DEVID", devid);
470  query0.bindValue(":HOSTNAME", gCoreContext->GetHostName());
471  query0.bindValue(":VIDEODEVICE", device);
472  query0.bindValue(":CARDID", cardid);
473  if (!query0.exec())
474  {
475  MythDB::DBError("DiSEqCDevTree::Store 3", query0);
476  return false;
477  }
478 
479  return true;
480 }
481 
482 bool DiSEqCDevTree::SetTone([[maybe_unused]] bool on) const
483 {
484  bool success = false;
485 
486 #ifdef USING_DVB
487  for (uint retry = 0; !success && (retry < TIMEOUT_RETRIES); retry++)
488  {
489  if (ioctl(m_fdFrontend, FE_SET_TONE,
490  on ? SEC_TONE_ON : SEC_TONE_OFF) == 0)
491  success = true;
492  else
493  usleep(TIMEOUT_WAIT);
494  }
495 #endif // USING_DVB
496 
497  if (!success)
498  LOG(VB_GENERAL, LOG_ERR, LOC + "FE_SET_TONE failed" + ENO);
499 
500  return success;
501 }
502 
510  const DTVMultiplex &tuning)
511 {
512  if (!m_root)
513  {
514  LOG(VB_GENERAL, LOG_ERR, LOC + "No root device tree node!");
515  return false;
516  }
517 
518  // apply any voltage change
519  ApplyVoltage(settings, tuning);
520 
521  // turn off tone burst first if commands need to be sent
522  if (m_root->IsCommandNeeded(settings, tuning))
523  {
524  SetTone(false);
525  usleep(DISEQC_SHORT_WAIT);
526  }
527 
528  return m_root->Execute(settings, tuning);
529 }
530 
537 {
538  if (m_root)
539  m_root->Reset();
540 
541  m_lastVoltage = UINT_MAX;
542 }
543 
551 {
552  DiSEqCDevDevice *node = m_root;
553  DiSEqCDevRotor *rotor = nullptr;
554 
555  for (uint count = 0; node;)
556  {
557  rotor = dynamic_cast<DiSEqCDevRotor*>(node);
558 
559  if (rotor && (++count > index))
560  break;
561 
562  node = node->GetSelectedChild(settings);
563  }
564 
565  return rotor;
566 }
567 
574 {
575  DiSEqCDevDevice *node = m_root;
576  DiSEqCDevLNB *lnb = nullptr;
577 
578  while (node)
579  {
580  lnb = dynamic_cast<DiSEqCDevLNB*>(node);
581 
582  if (lnb)
583  break;
584 
585  node = node->GetSelectedChild(settings);
586  }
587 
588  return lnb;
589 }
590 
597 {
598  DiSEqCDevDevice *node = m_root;
599  DiSEqCDevSCR *scr = nullptr;
600 
601  while (node)
602  {
603  scr = dynamic_cast<DiSEqCDevSCR*>(node);
604 
605  if (scr)
606  break;
607 
608  node = node->GetSelectedChild(settings);
609  }
610 
611  return scr;
612 }
613 
614 
621 {
622  if (m_root)
623  return m_root->FindDevice(dev_id);
624 
625  return nullptr;
626 }
627 
633 {
634  DiSEqCDevDevice *old_root = m_root;
635 
636  m_root = root;
637 
638  delete old_root;
639 }
640 
641 #ifdef USING_DVB
642 static bool send_diseqc(int fd, const dvb_diseqc_master_cmd cmd)
643 {
644  bool success = false;
645 
646  for (uint retry = 0; !success && (retry < TIMEOUT_RETRIES); retry++)
647  {
648  if (ioctl(fd, FE_DISEQC_SEND_MASTER_CMD, &cmd) == 0)
649  success = true;
650  else
651  usleep(TIMEOUT_WAIT);
652  }
653 
654  if (!success)
655  {
656  LOG(VB_GENERAL, LOG_ERR, LOC +
657  "send_diseqc FE_DISEQC_SEND_MASTER_CMD failed" + ENO);
658  }
659 
660  return success;
661 }
662 #endif //USING_DVB
663 
672 bool DiSEqCDevTree::SendCommand([[maybe_unused]] uint adr,
673  [[maybe_unused]] uint cmd,
674  [[maybe_unused]] uint repeats,
675  cmd_vec_t &data) const
676 {
677  // check payload validity
678  if (data.size() > 3)
679  {
680  LOG(VB_GENERAL, LOG_ERR, LOC + "Bad DiSEqC command");
681  return false;
682  }
683 
684 #ifndef USING_DVB
685 
686  return false;
687 
688 #else // if USING_DVB
689 
690  bool resend_cmd = false;
691 
692  // prepare command
693  dvb_diseqc_master_cmd mcmd = {};
694  mcmd.msg[0] = DISEQC_FRM;
695  mcmd.msg[1] = adr;
696  mcmd.msg[2] = cmd;
697  mcmd.msg_len = data.size() + 3;
698 
699  if (!data.empty())
700  std::copy(data.cbegin(), data.cend(), mcmd.msg + 3);
701 
702  // diagnostic
703  QString cmdstr;
704  for (uint byte = 0; byte < mcmd.msg_len; byte++)
705  cmdstr += QString("%1 ").arg(mcmd.msg[byte], 2, 16);
706 
707  LOG(VB_CHANNEL, LOG_INFO, LOC + "Sending DiSEqC Command: " + cmdstr);
708 
709  if (repeats >= 10)
710  {
711  repeats = repeats - 10;
712  resend_cmd = true;
713  }
714 
715  // send the command
716  for (uint i = 0; i <= repeats; i++)
717  {
718  if (!send_diseqc(GetFD(), mcmd))
719  {
720  LOG(VB_GENERAL, LOG_ERR, LOC + "DiSEqC command failed" + ENO);
721  return false;
722  }
723 
724  if (!resend_cmd)
725  mcmd.msg[0] |= DISEQC_FRM_REPEAT;
726 
727  usleep(DISEQC_SHORT_WAIT);
728  }
729 
730  return true;
731 
732 #endif // USING_DVB
733 }
734 
741 bool DiSEqCDevTree::ResetDiseqc(bool hard_reset, bool is_SCR)
742 {
743  Reset();
744 
745  // power cycle the bus if requested
746  // tests show that the wait times required can be very long (~1sec)
747  if (hard_reset)
748  {
749  LOG(VB_CHANNEL, LOG_INFO, LOC + "Power-cycling DiSEqC Bus");
750 
751  SetVoltage(SEC_VOLTAGE_OFF);
752  usleep(DISEQC_POWER_OFF_WAIT);
753  diseqc_bus_already_reset = false;
754  }
755 
756  if (!diseqc_bus_already_reset || !is_SCR)
757  {
758  // make sure the bus is powered
759  SetVoltage(SEC_VOLTAGE_18);
760  usleep(DISEQC_POWER_ON_WAIT);
761  // some DiSEqC devices need more time. see #8465
762  usleep(DISEQC_POWER_ON_WAIT);
763 
764  // issue a global reset command
765  LOG(VB_CHANNEL, LOG_INFO, LOC + "Resetting DiSEqC Bus");
767  {
768  LOG(VB_GENERAL, LOG_ERR, LOC + "DiSEqC reset failed" + ENO);
769  return false;
770  }
771 
772  if (is_SCR)
774  }
775  else
776  {
777  LOG(VB_CHANNEL, LOG_INFO, LOC + "Skipping reset: already done for this SCR bus");
778  }
779 
780  usleep(DISEQC_LONG_WAIT);
781 
782  return true;
783 }
784 
790 void DiSEqCDevTree::Open(int fd_frontend, bool is_SCR)
791 {
792  m_fdFrontend = fd_frontend;
793 
794  // issue reset command
795  ResetDiseqc(false, is_SCR);
796 }
797 
799 {
800  if (voltage == m_lastVoltage)
801  return true;
802 
803  int volts {0};
804  if (voltage == SEC_VOLTAGE_18)
805  volts = 18;
806  else if (voltage == SEC_VOLTAGE_13)
807  volts = 13;
808 
809  LOG(VB_CHANNEL, LOG_INFO, LOC + "Changing LNB voltage to " +
810  QString("%1V").arg(volts));
811 
812  bool success = false;
813 
814 #ifdef USING_DVB
815  for (uint retry = 0; !success && retry < TIMEOUT_RETRIES; retry++)
816  {
817  if (ioctl(m_fdFrontend, FE_SET_VOLTAGE, voltage) == 0)
818  success = true;
819  else
820  usleep(TIMEOUT_WAIT);
821  }
822 #endif // USING_DVB
823 
824  if (!success)
825  {
826  LOG(VB_GENERAL, LOG_ERR, LOC + "FE_SET_VOLTAGE failed" + ENO);
827  return false;
828  }
829 
830  m_lastVoltage = voltage;
831  return true;
832 }
833 
835 {
836  if (m_root)
838 
839  return false;
840 }
841 
843  const DTVMultiplex &tuning)
844 {
845  uint voltage = SEC_VOLTAGE_18;
846 
847  if (m_root)
848  voltage = m_root->GetVoltage(settings, tuning);
849 
850  return SetVoltage(voltage);
851 }
852 
854 
859 const std::vector<DiSEqCDevDevice::TypeTable> DiSEqCDevDevice::kDvbdevLookup
860 {
861  { "switch", kTypeSwitch },
862  { "rotor", kTypeRotor },
863  { "scr", kTypeSCR },
864  { "lnb", kTypeLNB },
865  { QString(), kTypeLNB },
866 };
867 
868 
870 {
871  if (IsRealDeviceID())
873 }
874 
876 {
877  DiSEqCDevDevice *dev = nullptr;
878 
879  if (GetDeviceID() == dev_id)
880  dev = this;
881 
882  uint num_children = GetChildCount();
883 
884  for (uint ch = 0; !dev && ch < num_children; ch++)
885  {
886  DiSEqCDevDevice *child = GetChild(ch);
887  if (child)
888  {
889  if (child->GetDeviceID() == dev_id)
890  dev = child;
891  else
892  dev = child->FindDevice(dev_id);
893  }
894  }
895 
896  return dev;
897 }
898 
900 {
901  // load settings from DB
902  MSqlQuery query(MSqlQuery::InitCon());
903  query.prepare(
904  "SELECT type, description "
905  "FROM diseqc_tree "
906  "WHERE diseqcid = :DEVID");
907  query.bindValue(":DEVID", devid);
908 
909  if (!query.exec() || !query.isActive())
910  {
911  MythDB::DBError("DiSEqCDevDevice::CreateById", query);
912  return nullptr;
913  }
914  if (!query.next())
915  {
916  LOG(VB_GENERAL, LOG_ERR, LOC + "CreateById failed to find dtv dev " +
917  QString("%1").arg(devid));
918 
919  return nullptr;
920  }
921 
922  dvbdev_t type = DevTypeFromString(query.value(0).toString());
923  QString desc = query.value(1).toString();
924  DiSEqCDevDevice *node = CreateByType(tree, type, devid);
925 
926  if (node)
927  {
928  node->SetDescription(desc);
929  node->Load();
930  }
931 
932  return node;
933 }
934 
936  dvbdev_t type,
937  uint dev_id)
938 {
939  if (!dev_id)
940  dev_id = tree.CreateFakeDiSEqCID();
941 
942  DiSEqCDevDevice *node = nullptr;
943  switch (type)
944  {
945  case kTypeSwitch:
946  node = new DiSEqCDevSwitch(tree, dev_id);
947  if (node)
948  node->SetDescription("Switch");
949  break;
950  case kTypeRotor:
951  node = new DiSEqCDevRotor(tree, dev_id);
952  if (node)
953  node->SetDescription("Rotor");
954  break;
955  case kTypeSCR:
956  node = new DiSEqCDevSCR(tree, dev_id);
957  if (node)
958  node->SetDescription("Unicable");
959  break;
960  case kTypeLNB:
961  node = new DiSEqCDevLNB(tree, dev_id);
962  if (node)
963  node->SetDescription("LNB");
964  break;
965  default:
966  break;
967  }
968 
969  if (node)
970  node->SetDeviceType(type);
971 
972  return node;
973 }
974 
1044 
1050 const std::vector<DiSEqCDevDevice::TypeTable> DiSEqCDevSwitch::kSwitchTypeTable
1051 {
1052  { "legacy_sw21", kTypeLegacySW21 },
1053  { "legacy_sw42", kTypeLegacySW42 },
1054  { "legacy_sw64", kTypeLegacySW64 },
1055  { "tone", kTypeTone },
1056  { "diseqc", kTypeDiSEqCCommitted },
1057  { "diseqc_uncom", kTypeDiSEqCUncommitted },
1058  { "voltage", kTypeVoltage },
1059  { "mini_diseqc", kTypeMiniDiSEqC },
1060  { QString(), kTypeTone },
1061 };
1062 
1064  : DiSEqCDevDevice(tree, devid)
1065 {
1066  m_children.resize(m_numPorts);
1067 
1068  for (uint i = 0; i < m_numPorts; i++)
1069  m_children[i] = nullptr;
1070 
1072 }
1073 
1075 {
1076  for (auto & child : m_children)
1077  delete child;
1078 }
1079 
1081  const DTVMultiplex &tuning)
1082 {
1083  bool success = true;
1084 
1085  // sanity check switch position
1086  int pos = GetPosition(settings);
1087  if (pos < 0)
1088  return false;
1089 
1090  // perform switching
1091  if (ShouldSwitch(settings, tuning))
1092  {
1093  switch (m_type)
1094  {
1095  case kTypeTone:
1096  success = ExecuteTone(settings, tuning, pos);
1097  break;
1098  case kTypeDiSEqCCommitted:
1100  success = ExecuteDiseqc(settings, tuning, pos);
1101  break;
1102  case kTypeLegacySW21:
1103  case kTypeLegacySW42:
1104  case kTypeLegacySW64:
1105  success = ExecuteLegacy(settings, tuning, pos);
1106  break;
1107  case kTypeVoltage:
1108  success = ExecuteVoltage(settings, tuning, pos);
1109  break;
1110  case kTypeMiniDiSEqC:
1111  success = ExecuteMiniDiSEqC(settings, tuning, pos);
1112  break;
1113  default:
1114  success = false;
1115  LOG(VB_GENERAL, LOG_ERR, LOC +
1116  QString("Unknown switch type (%1)").arg((uint)m_type));
1117  break;
1118  }
1119 
1120  // if a child device will be sending a diseqc command, wait 100ms
1121  if (m_children[pos]->IsCommandNeeded(settings, tuning))
1122  {
1123  LOG(VB_CHANNEL, LOG_INFO, LOC + "Waiting for switch");
1124  usleep(DISEQC_LONG_WAIT);
1125  }
1126 
1127  m_lastPos = pos;
1128  }
1129 
1130  // chain to child if the switch was successful
1131  if (success)
1132  success = m_children[pos]->Execute(settings, tuning);
1133 
1134  return success;
1135 }
1136 
1138 {
1139  m_lastPos = UINT_MAX;
1140  m_lastHighBand = UINT_MAX;
1141  m_lastHorizontal = UINT_MAX;
1142  for (auto & child : m_children)
1143  {
1144  if (child)
1145  child->Reset();
1146  }
1147 }
1148 
1150  const DTVMultiplex &tuning) const
1151 {
1152  int pos = GetPosition(settings);
1153  if (pos < 0)
1154  return false;
1155 
1156  return (ShouldSwitch(settings, tuning) ||
1157  m_children[pos]->IsCommandNeeded(settings, tuning));
1158 }
1159 
1161 {
1162  // sanity check switch position
1163  int pos = GetPosition(settings);
1164  if (pos < 0)
1165  return nullptr;
1166 
1167  return m_children[pos];
1168 }
1169 
1171 {
1172  return m_numPorts;
1173 }
1174 
1176 {
1177  if (ordinal < m_children.size())
1178  return m_children[ordinal];
1179 
1180  return nullptr;
1181 }
1182 
1184 {
1185  if (ordinal >= m_children.size())
1186  return false;
1187 
1188  if (m_children[ordinal])
1189  delete m_children[ordinal];
1190 
1191  m_children[ordinal] = device;
1192  if (device)
1193  {
1194  device->SetOrdinal(ordinal);
1195  device->SetParent(this);
1196  }
1197 
1198  return true;
1199 }
1200 
1202  const DTVMultiplex &tuning) const
1203 {
1204  uint voltage = SEC_VOLTAGE_18;
1205  DiSEqCDevDevice *child = GetSelectedChild(settings);
1206 
1207  if (child)
1208  voltage = child->GetVoltage(settings, tuning);
1209 
1210  return voltage;
1211 }
1212 
1214 {
1215  // clear old children
1216  for (auto & child : m_children)
1217  delete child;
1218 
1219  m_children.clear();
1220 
1221  // populate switch parameters from db
1222  MSqlQuery query(MSqlQuery::InitCon());
1223  query.prepare(
1224  "SELECT subtype, address, switch_ports, cmd_repeat "
1225  "FROM diseqc_tree "
1226  "WHERE diseqcid = :DEVID");
1227  query.bindValue(":DEVID", GetDeviceID());
1228 
1229  if (!query.exec() || !query.isActive())
1230  {
1231  MythDB::DBError("DiSEqCDevSwitch::Load 1", query);
1232  return false;
1233  }
1234  if (query.next())
1235  {
1236  m_type = SwitchTypeFromString(query.value(0).toString());
1237  m_address = query.value(1).toUInt();
1238  m_numPorts = query.value(2).toUInt();
1239  m_repeat = query.value(3).toUInt();
1240  m_children.resize(m_numPorts);
1241  for (uint i = 0; i < m_numPorts; i++)
1242  m_children[i] = nullptr;
1243  }
1244 
1245  // load children from db
1246  query.prepare(
1247  "SELECT diseqcid, ordinal "
1248  "FROM diseqc_tree "
1249  "WHERE parentid = :DEVID");
1250  query.bindValue(":DEVID", GetDeviceID());
1251  if (!query.exec() || !query.isActive())
1252  {
1253  MythDB::DBError("DiSEqCDevSwitch::Load 2", query);
1254  return false;
1255  }
1256 
1257  while (query.next())
1258  {
1259  uint child_dev_id = query.value(0).toUInt();
1260  uint ordinal = query.value(1).toUInt();
1261  DiSEqCDevDevice *child = CreateById(m_tree, child_dev_id);
1262  if (child && !SetChild(ordinal, child))
1263  {
1264  LOG(VB_GENERAL, LOG_ERR, LOC +
1265  QString("Switch port out of range (%1 > %2)")
1266  .arg(ordinal + 1).arg(m_numPorts));
1267  delete child;
1268  }
1269  }
1270 
1271  return true;
1272 }
1273 
1274 bool DiSEqCDevSwitch::Store(void) const
1275 {
1276  QString type = SwitchTypeToString(m_type);
1277  MSqlQuery query(MSqlQuery::InitCon());
1278 
1279  // insert new or update old
1280  if (IsRealDeviceID())
1281  {
1282  query.prepare(
1283  "UPDATE diseqc_tree "
1284  "SET parentid = :PARENT, "
1285  " ordinal = :ORDINAL, "
1286  " type = 'switch', "
1287  " description = :DESC, "
1288  " subtype = :TYPE, "
1289  " address = :ADDRESS, "
1290  " switch_ports = :PORTS, "
1291  " cmd_repeat = :REPEAT "
1292  "WHERE diseqcid = :DEVID");
1293  query.bindValue(":DEVID", GetDeviceID());
1294  }
1295  else
1296  {
1297  query.prepare(
1298  "INSERT INTO diseqc_tree"
1299  " ( parentid, ordinal, type, "
1300  " description, address, subtype, "
1301  " switch_ports, cmd_repeat ) "
1302  "VALUES "
1303  " (:PARENT, :ORDINAL, 'switch', "
1304  " :DESC, :ADDRESS, :TYPE, "
1305  " :PORTS, :REPEAT )");
1306  }
1307 
1308  if (m_parent)
1309  query.bindValue(":PARENT", m_parent->GetDeviceID());
1310 
1311  query.bindValue(":ORDINAL", m_ordinal);
1312  query.bindValue(":DESC", GetDescription());
1313  query.bindValue(":ADDRESS", m_address);
1314  query.bindValue(":TYPE", type);
1315  query.bindValue(":PORTS", m_numPorts);
1316  query.bindValue(":REPEAT", m_repeat);
1317 
1318  if (!query.exec())
1319  {
1320  MythDB::DBError("DiSEqCDevSwitch::Store", query);
1321  return false;
1322  }
1323 
1324  // figure out devid if we did an insert
1325  if (!IsRealDeviceID())
1326  SetDeviceID(query.lastInsertId().toUInt());
1327 
1328  // chain to children
1329  bool success = true;
1330  for (auto *child : m_children)
1331  {
1332  if (child)
1333  success &= child->Store();
1334  }
1335 
1336  return success;
1337 }
1338 
1340 {
1341  uint old_num = m_children.size();
1342 
1343  if (old_num > num_ports)
1344  {
1345  for (uint ch = num_ports; ch < old_num; ch++)
1346  {
1347  if (m_children[ch])
1348  delete m_children[ch];
1349  }
1350  m_children.resize(num_ports);
1351  }
1352  else if (old_num < num_ports)
1353  {
1354  m_children.resize(num_ports);
1355  for (uint ch = old_num; ch < num_ports; ch++)
1356  m_children[ch] = nullptr;
1357  }
1358 
1359  m_numPorts = num_ports;
1360 }
1361 
1362 bool DiSEqCDevSwitch::ExecuteLegacy([[maybe_unused]] const DiSEqCDevSettings &settings,
1363  [[maybe_unused]] const DTVMultiplex &tuning,
1364  [[maybe_unused]] uint pos)
1365 {
1366 #if defined(USING_DVB) && defined(FE_DISHNETWORK_SEND_LEGACY_CMD)
1367  static const cmd_vec_t kSw21Cmds { 0x34, 0x65, };
1368  static const cmd_vec_t kSw42Cmds { 0x46, 0x17, };
1369  static const cmd_vec_t kSw64VCmds { 0x39, 0x4b, 0x0d, };
1370  static const cmd_vec_t kSw64HCmds { 0x1a, 0x5c, 0x2e, };
1371 
1372  cmd_vec_t cmds {};
1373  unsigned char horizcmd = 0x00;
1374 
1375  // determine polarity from lnb
1376  bool horizontal = false;
1377  DiSEqCDevLNB *lnb = m_tree.FindLNB(settings);
1378  if (lnb)
1379  horizontal = lnb->IsHorizontal(tuning);
1380 
1381  // get command table for this switch
1382  switch (m_type)
1383  {
1384  case kTypeLegacySW21:
1385  cmds = kSw21Cmds;
1386  if (horizontal)
1387  horizcmd = 0x80;
1388  break;
1389  case kTypeLegacySW42:
1390  cmds = kSw42Cmds;
1391  break;
1392  case kTypeLegacySW64:
1393  if (horizontal)
1394  cmds = kSw64HCmds;
1395  else
1396  cmds = kSw64VCmds;
1397  break;
1398  default:
1399  return false;
1400  }
1401  pos %= cmds.size();
1402 
1403  LOG(VB_CHANNEL, LOG_INFO, LOC +
1404  QString("Changing to Legacy switch port %1/%2")
1405  .arg(pos + 1).arg(cmds.size()));
1406 
1407  // send command
1408  if (ioctl(m_tree.GetFD(), FE_DISHNETWORK_SEND_LEGACY_CMD,
1409  cmds[pos] | horizcmd) == -1)
1410  {
1411  LOG(VB_GENERAL, LOG_ERR, LOC +
1412  "FE_DISHNETWORK_SEND_LEGACY_CMD failed" + ENO);
1413 
1414  return false;
1415  }
1416 
1417  return true;
1418 
1419 #else // !FE_DISHNETWORK_SEND_LEGACY_CMD
1420 
1421  LOG(VB_GENERAL, LOG_ERR, LOC + "You must compile with a newer "
1422  "version of the linux headers for DishNet Legacy switch support.");
1423  return false;
1424 
1425 #endif // !FE_DISHNETWORK_SEND_LEGACY_CMD
1426 }
1427 
1428 #ifdef USING_DVB
1429 static bool set_tone(int fd, fe_sec_tone_mode tone)
1430 {
1431  bool success = false;
1432 
1433  for (uint retry = 0; !success && (retry < TIMEOUT_RETRIES); retry++)
1434  {
1435  if (ioctl(fd, FE_SET_TONE, tone) == 0)
1436  success = true;
1437  else
1438  usleep(TIMEOUT_WAIT);
1439  }
1440 
1441  if (!success)
1442  {
1443  LOG(VB_GENERAL, LOG_ERR, LOC + "set_tone failed" + ENO);
1444  }
1445 
1446  return success;
1447 }
1448 #endif // USING_DVB
1449 
1450 #ifdef USING_DVB
1451 static bool set_voltage(int fd, fe_sec_voltage volt)
1452 {
1453  bool success = false;
1454 
1455  for (uint retry = 0; !success && (retry < TIMEOUT_RETRIES); retry++)
1456  {
1457  if (0 == ioctl(fd, FE_SET_VOLTAGE, volt))
1458  success = true;
1459  else
1460  usleep(TIMEOUT_WAIT);
1461  }
1462 
1463  if (!success)
1464  {
1465  LOG(VB_GENERAL, LOG_ERR, LOC + "FE_SET_VOLTAGE failed" + ENO);
1466  }
1467 
1468  return success;
1469 }
1470 #endif // USING_DVB
1471 
1472 #ifdef USING_DVB
1473 static bool mini_diseqc(int fd, fe_sec_mini_cmd cmd)
1474 {
1475  bool success = false;
1476 
1477  for (uint retry = 0; !success && (retry < TIMEOUT_RETRIES); retry++)
1478  {
1479  if (ioctl(fd, FE_DISEQC_SEND_BURST, cmd) == 0)
1480  success = true;
1481  else
1482  usleep(TIMEOUT_WAIT);
1483  }
1484 
1485  if (!success)
1486  {
1487  LOG(VB_GENERAL, LOG_ERR, LOC +
1488  "mini_diseqc FE_DISEQC_SEND_BURST failed" + ENO);
1489  }
1490 
1491  return success;
1492 }
1493 #endif // USING_DVB
1494 
1496  const DTVMultiplex &/*tuning*/,
1497  uint pos)
1498 {
1499  LOG(VB_CHANNEL, LOG_INFO, LOC + "Changing to Tone switch port " +
1500  QString("%1/2").arg(pos + 1));
1501 
1502 #ifdef USING_DVB
1503  if (set_tone(m_tree.GetFD(), (0 == pos) ? SEC_TONE_OFF : SEC_TONE_ON))
1504  return true;
1505 #endif // USING_DVB
1506 
1507  LOG(VB_GENERAL, LOG_ERR, LOC + "Setting Tone Switch failed." + ENO);
1508  return false;
1509 }
1510 
1511 bool DiSEqCDevSwitch::ExecuteVoltage([[maybe_unused]] const DiSEqCDevSettings &settings,
1512  [[maybe_unused]] const DTVMultiplex &tuning,
1513  uint pos)
1514 {
1515  LOG(VB_CHANNEL, LOG_INFO, LOC + "Changing to Voltage Switch port " +
1516  QString("%1/2").arg(pos + 1));
1517 
1518 #ifdef USING_DVB
1519  if (set_voltage(m_tree.GetFD(),
1520  (0 == pos) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18))
1521  {
1522  return true;
1523  }
1524 #endif // USING_DVB
1525 
1526  LOG(VB_GENERAL, LOG_ERR, LOC + "Setting Voltage Switch failed." + ENO);
1527 
1528  return false;
1529 }
1530 
1531 bool DiSEqCDevSwitch::ExecuteMiniDiSEqC([[maybe_unused]] const DiSEqCDevSettings &settings,
1532  [[maybe_unused]] const DTVMultiplex &tuning,
1533  uint pos)
1534 {
1535  LOG(VB_CHANNEL, LOG_INFO, LOC + "Changing to MiniDiSEqC Switch port " +
1536  QString("%1/2").arg(pos + 1));
1537 
1538 #ifdef USING_DVB
1539  if (mini_diseqc(m_tree.GetFD(), (0 == pos) ? SEC_MINI_A : SEC_MINI_B))
1540  return true;
1541 #endif // USING_DVB
1542 
1543  LOG(VB_GENERAL, LOG_ERR, LOC + "Setting Mini DiSEqC Switch failed." + ENO);
1544 
1545  return false;
1546 }
1547 
1549  const DTVMultiplex &tuning) const
1550 {
1551  int pos = GetPosition(settings);
1552  if (pos < 0)
1553  return false;
1554 
1555  // committed switch should change for band and polarity as well
1557  {
1558  // retrieve LNB info
1559  bool high_band = false;
1560  bool horizontal = false;
1561  DiSEqCDevLNB *lnb = m_tree.FindLNB(settings);
1562  if (lnb)
1563  {
1564  high_band = lnb->IsHighBand(tuning);
1565  horizontal = lnb->IsHorizontal(tuning);
1566  }
1567 
1568  if(static_cast<uint>(high_band) != m_lastHighBand ||
1569  static_cast<uint>(horizontal) != m_lastHorizontal)
1570  return true;
1571  }
1572  else if (kTypeLegacySW42 == m_type ||
1574  {
1575  // retrieve LNB info
1576  bool horizontal = false;
1577  DiSEqCDevLNB *lnb = m_tree.FindLNB(settings);
1578  if (lnb)
1579  horizontal = lnb->IsHorizontal(tuning);
1580 
1581  if (static_cast<unsigned int>(horizontal) != m_lastHorizontal)
1582  return true;
1583  }
1584  else if (kTypeVoltage == m_type ||
1585  kTypeTone == m_type)
1586  {
1587  return true;
1588  }
1589 
1590  return m_lastPos != (uint)pos;
1591 }
1592 
1594  const DTVMultiplex &tuning,
1595  uint pos32)
1596 {
1597  auto pos = static_cast<uint8_t>(pos32);
1598  // retrieve LNB info
1599  bool high_band = false;
1600  bool horizontal = false;
1601  DiSEqCDevLNB *lnb = m_tree.FindLNB(settings);
1602  if (lnb)
1603  {
1604  high_band = lnb->IsHighBand(tuning);
1605  horizontal = lnb->IsHorizontal(tuning);
1606  }
1607 
1608  // check number of ports
1609  if (((kTypeDiSEqCCommitted == m_type) && (m_numPorts > 4)) ||
1610  ((kTypeDiSEqCUncommitted == m_type) && (m_numPorts > 16)))
1611  {
1612  LOG(VB_GENERAL, LOG_ERR, LOC +
1613  QString("Invalid number of ports for DiSEqC 1.x Switch (%1)")
1614  .arg(m_numPorts));
1615  return false;
1616  }
1617 
1618  // build command
1619  uint cmd = DISEQC_CMD_WRITE_N1;
1620  cmd_vec_t data { pos };
1622  {
1623  cmd = DISEQC_CMD_WRITE_N0;
1624  data[0] = ((pos << 2) | (horizontal ? 2 : 0) | (high_band ? 1 : 0));
1625  }
1626  data[0] |= 0xf0;
1627 
1628  LOG(VB_CHANNEL, LOG_INFO, LOC + "Changing to DiSEqC switch port " +
1629  QString("%1/%2").arg(pos + 1).arg(m_numPorts));
1630 
1631  bool ret = m_tree.SendCommand(m_address, cmd, m_repeat, data);
1632  if(ret)
1633  {
1634  m_lastHighBand = static_cast<uint>(high_band);
1635  m_lastHorizontal = static_cast<uint>(horizontal);
1636  }
1637  return ret;
1638 }
1639 
1641 {
1642  int pos = (int) settings.GetValue(GetDeviceID());
1643 
1644  if (pos >= (int)m_numPorts)
1645  {
1646  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Port %1 ").arg(pos + 1) +
1647  QString("is not in range [0..%1)").arg(m_numPorts));
1648 
1649  return -1;
1650  }
1651 
1652  if ((pos >= 0) && !m_children[pos])
1653  {
1654  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Port %1 ").arg(pos + 1) +
1655  "has no connected devices configured.");
1656 
1657  return -1;
1658  }
1659 
1660  return pos;
1661 }
1662 
1664 
1665 static double GetCurTimeFloating(void)
1666 {
1667  struct timeval curtime {};
1668  gettimeofday(&curtime, nullptr);
1669  return (double)curtime.tv_sec + (((double)curtime.tv_usec) / 1000000);
1670 }
1671 
1676 const std::vector<DiSEqCDevDevice::TypeTable> DiSEqCDevRotor::kRotorTypeTable
1677 {
1678  { "diseqc_1_2", kTypeDiSEqC_1_2 },
1679  { "diseqc_1_3", kTypeDiSEqC_1_3 },
1680  { nullptr, kTypeDiSEqC_1_3 }
1681 };
1682 
1684 {
1685  delete m_child;
1686 }
1687 
1689  const DTVMultiplex &tuning)
1690 {
1691  bool success = true;
1692 
1693  double position = settings.GetValue(GetDeviceID());
1694  if (m_reset || (position != m_lastPosition))
1695  {
1696  switch (m_type)
1697  {
1698  case kTypeDiSEqC_1_2:
1699  success = ExecuteRotor(settings, tuning, position);
1700  break;
1701  case kTypeDiSEqC_1_3:
1702  success = ExecuteUSALS(settings, tuning, position);
1703  break;
1704  default:
1705  success = false;
1706  LOG(VB_GENERAL, LOG_ERR, LOC + "Unknown rotor type " +
1707  QString("(%1)").arg((uint) m_type));
1708  break;
1709  }
1710 
1711  m_lastPosition = position;
1712  m_reset = false;
1713  if (success)
1714  // prevent tuning parameters overriding rotor parameters
1715  usleep(DISEQC_LONG_WAIT);
1716  }
1717 
1718  // chain to child
1719  if (success && m_child)
1720  success = m_child->Execute(settings, tuning);
1721 
1722  return success;
1723 }
1724 
1726 {
1727  m_reset = true;
1728  if (m_child)
1729  m_child->Reset();
1730 }
1731 
1733  const DTVMultiplex &tuning) const
1734 {
1735  double position = settings.GetValue(GetDeviceID());
1736 
1737  if (m_reset || (position != m_lastPosition))
1738  return true;
1739 
1740  if (m_child)
1741  return m_child->IsCommandNeeded(settings, tuning);
1742 
1743  return false;
1744 }
1745 
1747 {
1748  return m_child;
1749 }
1750 
1752 {
1753  if (ordinal)
1754  return false;
1755 
1756  DiSEqCDevDevice *old_child = m_child;
1757  m_child = nullptr;
1758  delete old_child;
1759 
1760  m_child = device;
1761  if (m_child)
1762  {
1763  m_child->SetOrdinal(ordinal);
1764  m_child->SetParent(this);
1765  }
1766 
1767  return true;
1768 }
1769 
1770 bool DiSEqCDevRotor::IsMoving(const DiSEqCDevSettings &settings) const
1771 {
1772  double position = settings.GetValue(GetDeviceID());
1773  double completed = GetProgress();
1774  bool moving = (completed < 1.0) || (position != m_lastPosition);
1775 
1776  return (m_lastPosKnown && moving);
1777 }
1778 
1780  const DTVMultiplex &tuning) const
1781 {
1782  // override voltage if the last position is known and the rotor is moving
1783  if (IsMoving(settings))
1784  {
1785  LOG(VB_CHANNEL, LOG_INFO, LOC +
1786  "Overriding voltage to 18V for faster rotor movement");
1787  }
1788  else if (m_child)
1789  {
1790  return m_child->GetVoltage(settings, tuning);
1791  }
1792 
1793  return SEC_VOLTAGE_18;
1794 }
1795 
1797 {
1798  // populate switch parameters from db
1799  MSqlQuery query(MSqlQuery::InitCon());
1800  query.prepare(
1801  "SELECT subtype, rotor_positions, "
1802  " rotor_hi_speed, rotor_lo_speed, "
1803  " cmd_repeat "
1804  "FROM diseqc_tree "
1805  "WHERE diseqcid = :DEVID");
1806  query.bindValue(":DEVID", GetDeviceID());
1807 
1808  if (!query.exec() || !query.isActive())
1809  {
1810  MythDB::DBError("DiSEqCDevRotor::Load 1", query);
1811  return false;
1812  }
1813  if (query.next())
1814  {
1815  m_type = RotorTypeFromString(query.value(0).toString());
1816  m_speedHi = query.value(2).toDouble();
1817  m_speedLo = query.value(3).toDouble();
1818  m_repeat = query.value(4).toUInt();
1819 
1820  // form of "angle1=index1:angle2=index2:..."
1821  QString positions = query.value(1).toString();
1822  QStringList pos = positions.split(":", Qt::SkipEmptyParts);
1823  for (const auto & kv : std::as_const(pos))
1824  {
1825  const QStringList eq = kv.split("=", Qt::SkipEmptyParts);
1826  if (eq.size() == 2)
1827  m_posmap[eq[0].toFloat()] = eq[1].toUInt();
1828  }
1829  }
1830 
1831  // load children from db
1832  if (m_child)
1833  {
1834  delete m_child;
1835  m_child = nullptr;
1836  }
1837 
1838  query.prepare(
1839  "SELECT diseqcid "
1840  "FROM diseqc_tree "
1841  "WHERE parentid = :DEVID");
1842  query.bindValue(":DEVID", GetDeviceID());
1843 
1844  if (!query.exec() || !query.isActive())
1845  {
1846  MythDB::DBError("DiSEqCDevRotor::Load 2", query);
1847  return false;
1848  }
1849  if (query.next())
1850  {
1851  uint child_dev_id = query.value(0).toUInt();
1852  SetChild(0, CreateById(m_tree, child_dev_id));
1853  }
1854 
1855  return true;
1856 }
1857 
1858 bool DiSEqCDevRotor::Store(void) const
1859 {
1860  QString posmap = "";
1861  QString type = RotorTypeToString(m_type);
1862 
1863  if (!m_posmap.empty())
1864  {
1865  QStringList pos;
1866 
1867  dbl_to_uint_t::const_iterator it = m_posmap.begin();
1868  for (; it != m_posmap.end(); ++it)
1869  pos.push_back(QString("%1=%2").arg(it.key()).arg(*it));
1870 
1871  posmap = pos.join(":");
1872  }
1873 
1874  MSqlQuery query(MSqlQuery::InitCon());
1875 
1876  // insert new or update old
1877  if (IsRealDeviceID())
1878  {
1879  query.prepare(
1880  "UPDATE diseqc_tree "
1881  "SET parentid = :PARENT, "
1882  " ordinal = :ORDINAL, "
1883  " type = 'rotor', "
1884  " description = :DESC, "
1885  " subtype = :TYPE, "
1886  " rotor_hi_speed = :HISPEED, "
1887  " rotor_lo_speed = :LOSPEED, "
1888  " rotor_positions = :POSMAP, "
1889  " cmd_repeat = :REPEAT "
1890  "WHERE diseqcid = :DEVID");
1891  query.bindValue(":DEVID", GetDeviceID());
1892  }
1893  else
1894  {
1895  query.prepare(
1896  "INSERT INTO diseqc_tree "
1897  " ( parentid, ordinal, type, "
1898  " description, subtype, rotor_hi_speed, "
1899  " rotor_lo_speed, rotor_positions, cmd_repeat ) "
1900  "VALUES "
1901  " (:PARENT, :ORDINAL, 'rotor', "
1902  " :DESC, :TYPE, :HISPEED, "
1903  " :LOSPEED, :POSMAP, :REPEAT )");
1904  }
1905 
1906  if (m_parent)
1907  query.bindValue(":PARENT", m_parent->GetDeviceID());
1908 
1909  query.bindValue(":ORDINAL", m_ordinal);
1910  query.bindValue(":DESC", GetDescription());
1911  query.bindValue(":TYPE", type);
1912  query.bindValue(":HISPEED", m_speedHi);
1913  query.bindValue(":LOSPEED", m_speedLo);
1914  query.bindValue(":POSMAP", posmap);
1915  query.bindValue(":REPEAT", m_repeat);
1916 
1917  if (!query.exec())
1918  {
1919  MythDB::DBError("DiSEqCDevRotor::Store", query);
1920  return false;
1921  }
1922 
1923  // figure out devid if we did an insert
1924  if (!IsRealDeviceID())
1925  SetDeviceID(query.lastInsertId().toUInt());
1926 
1927  // chain to child
1928  if (m_child)
1929  return m_child->Store();
1930 
1931  return true;
1932 }
1933 
1940 {
1941  if (m_moveTime == 0.0)
1942  return 1.0;
1943 
1944  // calculate duration of move
1945  double speed = ((m_tree.GetVoltage() == SEC_VOLTAGE_18) ?
1946  m_speedHi : m_speedLo);
1947  double change = abs(m_desiredAzimuth - m_lastAzimuth);
1948  double duration = change / speed;
1949 
1950  // determine completion percentage
1951  double time_since_move = GetCurTimeFloating() - m_moveTime;
1952  double completed = time_since_move / duration;
1953  if(completed > 1.0)
1954  {
1955  RotationComplete();
1956  completed = 1.0;
1957  }
1958 
1959  return completed;
1960 }
1961 
1970 {
1971  return m_lastPosKnown;
1972 }
1973 
1975 {
1976  uint_to_dbl_t inv_posmap;
1977  dbl_to_uint_t::const_iterator it;
1978  for (it = m_posmap.begin(); it != m_posmap.end(); ++it)
1979  inv_posmap[*it] = it.key();
1980 
1981  return inv_posmap;
1982 }
1983 
1985 {
1986  m_posmap.clear();
1987 
1988  uint_to_dbl_t::const_iterator it;
1989  for (it = inv_posmap.begin(); it != inv_posmap.end(); ++it)
1990  m_posmap[*it] = it.key();
1991 }
1992 
1994  const DTVMultiplex& /*tuning*/,
1995  double angle)
1996 {
1997  // determine stored position from position map
1998  dbl_to_uint_t::const_iterator it =
1999  m_posmap.lowerBound(angle - EPS); // clazy:exclude=strict-iterators
2000  cmd_vec_t index { static_cast<uint8_t>(angle) };
2001  if (it != m_posmap.cend())
2002  {
2003  index[0] = *it;
2005  }
2006 
2007  LOG(VB_CHANNEL, LOG_INFO, LOC + "Rotor - " +
2008  QString("Goto Stored Position %1").arg(index[0]));
2009 
2011  m_repeat, index);
2012 }
2013 
2015  const DTVMultiplex& /*tuning*/,
2016  double angle)
2017 {
2018  double azimuth = CalculateAzimuth(angle);
2019  StartRotorPositionTracking(azimuth);
2020 
2021  LOG(VB_CHANNEL, LOG_INFO, LOC + "USALS Rotor - " +
2022  QString("Goto %1 (Azimuth %2)").arg(angle).arg(azimuth));
2023 
2024  uint az16 = (uint) (abs(azimuth) * 16.0);
2025  cmd_vec_t cmd {
2026  static_cast<uint8_t>(((azimuth > 0.0) ? 0xE0 : 0xD0) | ((az16 >> 8) & 0x0f)),
2027  static_cast<uint8_t>(az16 & 0xff) };
2028 
2030  m_repeat, cmd);
2031 }
2032 
2034 {
2035  // Azimuth Calculation references:
2036  // http://engr.nmsu.edu/~etti/3_2/3_2e.html
2037  // http://www.angelfire.com/trek/ismail/theory.html
2038 
2039  // Earth Station Latitude and Longitude in radians
2040  double P = gCoreContext->GetSetting("Latitude", "").toDouble() * TO_RADS;
2041  double Ue = gCoreContext->GetSetting("Longitude", "").toDouble() * TO_RADS;
2042 
2043  // Satellite Longitude in radians
2044  double Us = angle * TO_RADS;
2045 
2046  return TO_DEC * atan( tan(Us - Ue) / sin(P) );
2047 }
2048 
2050 {
2051  if (m_moveTime == 0.0)
2052  return m_lastAzimuth;
2053 
2054  double change = m_desiredAzimuth - m_lastAzimuth;
2055  return m_lastAzimuth + (change * GetProgress());
2056 }
2057 
2059 {
2060  // save time and angle of this command
2061  m_desiredAzimuth = azimuth;
2062 
2063  // set last to approximate current position (or worst case if unknown)
2064  if (m_lastPosKnown || m_moveTime > 0.0)
2066  else
2067  m_lastAzimuth = azimuth > 0.0 ? -75.0 : 75.0;
2068 
2070 }
2071 
2073 {
2074  m_moveTime = 0.0;
2075  m_lastPosKnown = true;
2077 }
2078 
2080 
2085 const std::vector<DiSEqCDevDevice::TypeTable> DiSEqCDevSCR::kSCRPositionTable
2086 {
2087  { "A", kTypeScrPosA },
2088  { "B", kTypeScrPosB },
2089  { QString(), kTypeScrPosA },
2090 };
2091 
2093 {
2094  delete m_child;
2095 }
2096 
2098 {
2099  if (m_child)
2100  m_child->Reset();
2101 }
2102 
2103 bool DiSEqCDevSCR::Execute(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning)
2104 {
2105  // retrieve LNB info
2106  DiSEqCDevLNB *lnb = m_tree.FindLNB(settings);
2107  if (!lnb)
2108  {
2109  LOG(VB_GENERAL, LOG_ERR, LOC + "SCR: No LNB for this configuration!");
2110  return false;
2111  }
2112 
2113  bool high_band = lnb->IsHighBand(tuning);
2114  bool horizontal = lnb->IsHorizontal(tuning);
2115  uint32_t frequency = lnb->GetIntermediateFrequency(settings, tuning);
2116  uint t = ((frequency / 1000 + m_scrFrequency + 2) / 4) - 350;
2117 
2118  // retrieve position settings (value should be 0 or 1)
2119  auto scr_position = (dvbdev_pos_t)int(settings.GetValue(GetDeviceID()));
2120 
2121  // check parameters
2122  if (m_scrUserband > 7)
2123  {
2124  LOG(VB_GENERAL, LOG_ERR, LOC + QString("SCR: Userband ID=%1 is out of range (0-7)!")
2125  .arg(m_scrUserband));
2126  return false;
2127  }
2128 
2129  if (t >= 1024)
2130  {
2131  LOG(VB_GENERAL, LOG_ERR, LOC + QString("SCR: T=%1 is out of range!").arg(t));
2132  return false;
2133  }
2134 
2135  LOG(VB_GENERAL, LOG_INFO, QString("SCR: Tuning to %1kHz, %2, %3 using UB=%4, FREQ=%5MHz, POS=%6%7")
2136  .arg(tuning.m_frequency)
2137  .arg(high_band ? "HiBand" : "LoBand",
2138  horizontal ? "H" : "V")
2139  .arg(m_scrUserband)
2140  .arg(m_scrFrequency)
2141  .arg((scr_position) ? "B" : "A",
2142  (m_scrPin >= 0 && m_scrPin <= 255) ?
2143  QString(", PIN=%1").arg(m_scrPin) : QString("")));
2144 
2145  // build command
2146  cmd_vec_t data {
2147  static_cast<uint8_t>(t >> 8 | m_scrUserband << 5),
2148  static_cast<uint8_t>(t & 0x00FF) };
2149 
2150  if (high_band)
2151  data[0] |= (1 << 2);
2152 
2153  if (horizontal)
2154  data[0] |= (1 << 3);
2155 
2156  if (scr_position)
2157  data[0] |= (1 << 4);
2158 
2159  // send command
2160  if (m_scrPin >= 0 && m_scrPin <= 255)
2161  data.push_back(m_scrPin);
2162  return SendCommand(DISEQC_CMD_ODU, m_repeat, data);
2163 }
2164 
2165 bool DiSEqCDevSCR::PowerOff(void) const
2166 {
2167  // check parameters
2168  if (m_scrUserband > 7)
2169  {
2170  LOG(VB_GENERAL, LOG_ERR, LOC + QString("SCR: Userband ID=%1 is out of range (0-7)!")
2171  .arg(m_scrUserband));
2172  return false;
2173  }
2174 
2175  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("SCR: Power off UB=%1%7")
2176  .arg(m_scrUserband)
2177  .arg((m_scrPin >= 0 && m_scrPin <= 255)
2178  ? QString(", PIN=%1").arg(m_scrPin)
2179  : QString("")));
2180 
2181  // build command
2182  cmd_vec_t data {
2183  static_cast<uint8_t>(m_scrUserband << 5), 0x00 };
2184 
2185  // send command
2186  if (m_scrPin >= 0 && m_scrPin <= 255)
2187  data.push_back(m_scrPin);
2188  return SendCommand(DISEQC_CMD_ODU, m_repeat, data);
2189 }
2190 
2192  [[maybe_unused]] uint repeats,
2193  cmd_vec_t &data) const
2194 {
2195  // power on bus
2196  if (!m_tree.SetVoltage(SEC_VOLTAGE_18))
2197  return false;
2198  usleep(DISEQC_LONG_WAIT);
2199 
2200  // send command
2201  bool ret = m_tree.SendCommand(DISEQC_ADR_SW_ALL, cmd, repeats, data);
2202 
2203  // power off bus
2204  if (!m_tree.SetVoltage(SEC_VOLTAGE_13))
2205  return false;
2206 
2207  return ret;
2208 }
2209 
2211  const DTVMultiplex &/*tuning*/) const
2212 {
2213  return SEC_VOLTAGE_13;
2214 }
2215 
2216 uint32_t DiSEqCDevSCR::GetIntermediateFrequency(const uint32_t frequency) const
2217 {
2218  uint t = ((frequency / 1000 + m_scrFrequency + 2) / 4) - 350;
2219  return (((t + 350) * 4) * 1000) - frequency;
2220 }
2221 
2223 {
2224  // populate scr parameters from db
2225  MSqlQuery query(MSqlQuery::InitCon());
2226  query.prepare(
2227  "SELECT scr_userband, scr_frequency, "
2228  " scr_pin, cmd_repeat "
2229  "FROM diseqc_tree "
2230  "WHERE diseqcid = :DEVID");
2231  query.bindValue(":DEVID", GetDeviceID());
2232 
2233  if (!query.exec() || !query.isActive())
2234  {
2235  MythDB::DBError("DiSEqCDevSCR::Load 1", query);
2236  return false;
2237  }
2238  if (query.next())
2239  {
2240  m_scrUserband = query.value(0).toUInt();
2241  m_scrFrequency = query.value(1).toUInt();
2242  m_scrPin = query.value(2).toInt();
2243  m_repeat = query.value(3).toUInt();
2244  }
2245 
2246  // load children from db
2247  if (m_child)
2248  {
2249  delete m_child;
2250  m_child = nullptr;
2251  }
2252 
2253  query.prepare(
2254  "SELECT diseqcid "
2255  "FROM diseqc_tree "
2256  "WHERE parentid = :DEVID");
2257  query.bindValue(":DEVID", GetDeviceID());
2258 
2259  if (!query.exec() || !query.isActive())
2260  {
2261  MythDB::DBError("DiSEqCDevSCR::Load 2", query);
2262  return false;
2263  }
2264  if (query.next())
2265  {
2266  uint child_dev_id = query.value(0).toUInt();
2267  SetChild(0, CreateById(m_tree, child_dev_id));
2268  }
2269 
2270  return true;
2271 }
2272 
2273 bool DiSEqCDevSCR::Store(void) const
2274 {
2275  MSqlQuery query(MSqlQuery::InitCon());
2276 
2277  // insert new or update old
2278  if (IsRealDeviceID())
2279  {
2280  query.prepare(
2281  "UPDATE diseqc_tree "
2282  "SET parentid = :PARENT, "
2283  " ordinal = :ORDINAL, "
2284  " type = 'scr', "
2285  " description = :DESC, "
2286  " scr_userband = :USERBAND, "
2287  " scr_frequency = :FREQUENCY, "
2288  " scr_pin = :PIN, "
2289  " cmd_repeat = :REPEAT "
2290  "WHERE diseqcid = :DEVID");
2291  query.bindValue(":DEVID", GetDeviceID());
2292  }
2293  else
2294  {
2295  query.prepare(
2296  "INSERT INTO diseqc_tree"
2297  " ( parentid, ordinal, type, "
2298  " description, scr_userband, scr_frequency, "
2299  " scr_pin, cmd_repeat) "
2300  "VALUES "
2301  " (:PARENT, :ORDINAL, 'scr', "
2302  " :DESC, :USERBAND, :FREQUENCY,"
2303  " :PIN, :REPEAT) ");
2304  }
2305 
2306  if (m_parent)
2307  query.bindValue(":PARENT", m_parent->GetDeviceID());
2308 
2309  query.bindValue(":ORDINAL", m_ordinal);
2310  query.bindValue(":DESC", GetDescription());
2311  query.bindValue(":USERBAND", m_scrUserband);
2312  query.bindValue(":FREQUENCY", m_scrFrequency);
2313  query.bindValue(":PIN", m_scrPin);
2314  query.bindValue(":REPEAT", m_repeat);
2315 
2316  // update dev_id
2317  if (!query.exec())
2318  {
2319  MythDB::DBError("DiSEqCDevSCR::Store", query);
2320  return false;
2321  }
2322 
2323  // figure out devid if we did an insert
2324  if (!IsRealDeviceID())
2325  SetDeviceID(query.lastInsertId().toUInt());
2326 
2327  // chain to child
2328  if (m_child)
2329  return m_child->Store();
2330 
2331  return true;
2332 }
2333 
2335 {
2336  if (ordinal)
2337  return false;
2338 
2339  DiSEqCDevDevice *old_child = m_child;
2340  m_child = nullptr;
2341  delete old_child;
2342 
2343  m_child = device;
2344  if (m_child)
2345  {
2346  m_child->SetOrdinal(ordinal);
2347  m_child->SetParent(this);
2348  }
2349 
2350  return true;
2351 }
2352 
2354 
2359 const std::vector<DiSEqCDevDevice::TypeTable> DiSEqCDevLNB::kLNBTypeTable
2360 {
2361  { "fixed", kTypeFixed },
2362  { "voltage", kTypeVoltageControl },
2363  { "voltage_tone", kTypeVoltageAndToneControl },
2364  { "bandstacked", kTypeBandstacked },
2365  { QString(), kTypeVoltageAndToneControl },
2366 };
2367 
2368 bool DiSEqCDevLNB::Execute(const DiSEqCDevSettings& /*settings*/, const DTVMultiplex &tuning)
2369 {
2370  // set tone for bandselect
2372  m_tree.SetTone(IsHighBand(tuning));
2373 
2374  return true;
2375 }
2376 
2378  const DTVMultiplex &tuning) const
2379 {
2380  uint voltage = SEC_VOLTAGE_18;
2381 
2382  if ((kTypeVoltageControl == m_type) ||
2384  {
2385  voltage = (IsHorizontal(tuning) ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13);
2386  }
2387 
2388  return voltage;
2389 }
2390 
2392 {
2393  // populate lnb parameters from db
2394  MSqlQuery query(MSqlQuery::InitCon());
2395  query.prepare(
2396  "SELECT subtype, lnb_lof_switch, "
2397  " lnb_lof_hi, lnb_lof_lo, "
2398  " lnb_pol_inv, cmd_repeat "
2399  "FROM diseqc_tree "
2400  "WHERE diseqcid = :DEVID");
2401  query.bindValue(":DEVID", GetDeviceID());
2402 
2403  if (!query.exec() || !query.isActive())
2404  {
2405  MythDB::DBError("DiSEqCDevLNB::Load", query);
2406  return false;
2407  }
2408  if (query.next())
2409  {
2410  m_type = LNBTypeFromString(query.value(0).toString());
2411  m_lofSwitch = query.value(1).toInt();
2412  m_lofHi = query.value(2).toInt();
2413  m_lofLo = query.value(3).toInt();
2414  m_polInv = query.value(4).toBool();
2415  m_repeat = query.value(5).toUInt();
2416  }
2417 
2418  return true;
2419 }
2420 
2421 bool DiSEqCDevLNB::Store(void) const
2422 {
2423  QString type = LNBTypeToString(m_type);
2424  MSqlQuery query(MSqlQuery::InitCon());
2425 
2426  // insert new or update old
2427  if (IsRealDeviceID())
2428  {
2429  query.prepare(
2430  "UPDATE diseqc_tree "
2431  "SET parentid = :PARENT, "
2432  " ordinal = :ORDINAL, "
2433  " type = 'lnb', "
2434  " description = :DESC, "
2435  " subtype = :TYPE, "
2436  " lnb_lof_switch = :LOFSW, "
2437  " lnb_lof_lo = :LOFLO, "
2438  " lnb_lof_hi = :LOFHI, "
2439  " lnb_pol_inv = :POLINV, "
2440  " cmd_repeat = :REPEAT "
2441  "WHERE diseqcid = :DEVID");
2442  query.bindValue(":DEVID", GetDeviceID());
2443  }
2444  else
2445  {
2446  query.prepare(
2447  "INSERT INTO diseqc_tree"
2448  " ( parentid, ordinal, type, "
2449  " description, subtype, lnb_lof_switch, "
2450  " lnb_lof_lo, lnb_lof_hi, lnb_pol_inv, "
2451  " cmd_repeat ) "
2452  "VALUES "
2453  " (:PARENT, :ORDINAL, 'lnb', "
2454  " :DESC, :TYPE, :LOFSW, "
2455  " :LOFLO, :LOFHI, :POLINV, "
2456  " :REPEAT ) ");
2457  }
2458 
2459  if (m_parent)
2460  query.bindValue(":PARENT", m_parent->GetDeviceID());
2461 
2462  query.bindValue(":ORDINAL", m_ordinal);
2463  query.bindValue(":DESC", GetDescription());
2464  query.bindValue(":TYPE", type);
2465  query.bindValue(":LOFSW", m_lofSwitch);
2466  query.bindValue(":LOFLO", m_lofLo);
2467  query.bindValue(":LOFHI", m_lofHi);
2468  query.bindValue(":POLINV", m_polInv);
2469  query.bindValue(":REPEAT", m_repeat);
2470 
2471  // update dev_id
2472  if (!query.exec())
2473  {
2474  MythDB::DBError("DiSEqCDevLNB::Store", query);
2475  return false;
2476  }
2477 
2478  // figure out devid if we did an insert
2479  if (!IsRealDeviceID())
2480  SetDeviceID(query.lastInsertId().toUInt());
2481 
2482  return true;
2483 }
2484 
2491 bool DiSEqCDevLNB::IsHighBand(const DTVMultiplex &tuning) const
2492 {
2493  switch (m_type)
2494  {
2496  return (tuning.m_frequency > m_lofSwitch);
2497  case kTypeBandstacked:
2498  return IsHorizontal(tuning);
2499  default:
2500  return false;
2501  }
2502 
2503  return false;
2504 }
2505 
2511 bool DiSEqCDevLNB::IsHorizontal(const DTVMultiplex &tuning) const
2512 {
2513  QString pol = tuning.m_polarity.toString().toLower();
2514  return (pol == "h" || pol == "l") ^ IsPolarityInverted();
2515 }
2516 
2524  const DiSEqCDevSettings& /*settings*/, const DTVMultiplex &tuning) const
2525 {
2526  uint64_t abs_freq = tuning.m_frequency;
2527  uint lof = (IsHighBand(tuning)) ? m_lofHi : m_lofLo;
2528 
2529  return (lof > abs_freq) ? (lof - abs_freq) : (abs_freq - lof);
2530 }
DiSEqCDevSwitch::SwitchTypeToString
static QString SwitchTypeToString(dvbdev_switch_t type)
Definition: diseqc.h:270
DiSEqCDevSwitch::kTypeVoltage
@ kTypeVoltage
Definition: diseqc.h:245
DiSEqCDevDevice::m_ordinal
uint m_ordinal
Definition: diseqc.h:210
DISEQC_CMD_WRITE_FREQ
@ DISEQC_CMD_WRITE_FREQ
Definition: diseqc.cpp:74
DTVMultiplex::m_frequency
uint64_t m_frequency
Definition: dtvmultiplex.h:94
MSqlQuery::isActive
bool isActive(void) const
Definition: mythdbcon.h:215
DiSEqCDevRotor::IsCommandNeeded
bool IsCommandNeeded(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning) const override
Determines if this device or any child will be sending a command for the given configuration chain.
Definition: diseqc.cpp:1732
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:812
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:127
DiSEqCDevTree::~DiSEqCDevTree
~DiSEqCDevTree()
Definition: diseqc.cpp:301
DTVMultiplex
Definition: dtvmultiplex.h:24
DISEQC_ADR_LNB
@ DISEQC_ADR_LNB
Definition: diseqc.cpp:56
DiSEqCDevDevice::GetChildCount
virtual uint GetChildCount(void) const
Retrieves the proper number of children for this node.
Definition: diseqc.h:177
DiSEqCDevLNB::Store
bool Store(void) const override
Definition: diseqc.cpp:2421
DiSEqCDevTree::IsInNeedOfConf
bool IsInNeedOfConf(void) const
Definition: diseqc.cpp:834
ENO
#define ENO
This can be appended to the LOG args with "+".
Definition: mythlogging.h:74
DiSEqCDevSwitch::SwitchTypeFromString
static dvbdev_switch_t SwitchTypeFromString(const QString &type)
Definition: diseqc.h:272
DiSEqCDevDevice::FindDevice
DiSEqCDevDevice * FindDevice(uint dev_id)
Definition: diseqc.cpp:875
DiSEqCDevLNB::kTypeVoltageControl
@ kTypeVoltageControl
Definition: diseqc.h:461
DISEQC_ADR_POS_ALL
@ DISEQC_ADR_POS_ALL
Definition: diseqc.cpp:63
DiSEqCDevSCR::GetIntermediateFrequency
uint32_t GetIntermediateFrequency(uint32_t frequency) const
Definition: diseqc.cpp:2216
DiSEqCDevSwitch::kSwitchTypeTable
static const TypeTableVec kSwitchTypeTable
Definition: diseqc.h:299
DISEQC_LONG_WAIT
static constexpr useconds_t DISEQC_LONG_WAIT
Definition: diseqc.cpp:37
DiSEqCDevSettings::GetValue
double GetValue(uint devid) const
Retrieves a value from this configuration chain by device id.
Definition: diseqc.cpp:204
DiSEqCDevRotor::~DiSEqCDevRotor
~DiSEqCDevRotor() override
Definition: diseqc.cpp:1683
LOC
#define LOC
Definition: diseqc.cpp:93
DiSEqCDevLNB::kTypeVoltageAndToneControl
@ kTypeVoltageAndToneControl
Definition: diseqc.h:462
DiSEqCDevLNB::LNBTypeFromString
static dvbdev_lnb_t LNBTypeFromString(const QString &type)
Definition: diseqc.h:488
DiSEqCDevRotor
Rotor class.
Definition: diseqc.h:302
mythdb.h
DISEQC_ADR_POS_AZ
@ DISEQC_ADR_POS_AZ
Definition: diseqc.cpp:64
DiSEqCDevDevice::SetDeviceID
void SetDeviceID(uint devid) const
Definition: diseqc.h:203
DISEQC_CMD_GOTO_POS
@ DISEQC_CMD_GOTO_POS
Definition: diseqc.cpp:84
DiSEqCDevSCR::GetVoltage
uint GetVoltage(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning) const override
Retrives the desired voltage for this config.
Definition: diseqc.cpp:2210
set_tone
static bool set_tone(int fd, fe_sec_tone_mode tone)
Definition: diseqc.cpp:1429
DiSEqCDevTree::m_delete
std::vector< uint > m_delete
Definition: diseqc.h:134
DiSEqCDevSwitch::SetChild
bool SetChild(uint ordinal, DiSEqCDevDevice *device) override
Changes the nth child of this node.
Definition: diseqc.cpp:1183
DISEQC_FRM_REPEAT
static constexpr uint8_t DISEQC_FRM_REPEAT
Definition: diseqc.cpp:48
DISEQC_ADRS
DISEQC_ADRS
Definition: diseqc.cpp:53
DiSEqCDevTree::m_fdFrontend
int m_fdFrontend
Definition: diseqc.h:130
DISEQC_ADR_POL_ALL
@ DISEQC_ADR_POL_ALL
Definition: diseqc.cpp:61
DiSEqCDevLNB::kLNBTypeTable
static const TypeTableVec kLNBTypeTable
Definition: diseqc.h:501
DiSEqCDevDevice::m_tree
DiSEqCDevTree & m_tree
Definition: diseqc.h:208
DISEQC_CMD_RESET
@ DISEQC_CMD_RESET
Definition: diseqc.cpp:70
DiSEqCDevTree::SendCommand
bool SendCommand(uint adr, uint cmd, uint repeats, cmd_vec_t &data) const
DISEQC_ADR_POL_LIN
@ DISEQC_ADR_POL_LIN
Definition: diseqc.cpp:62
diseqc.h
DiSEqCDevLNB::kTypeBandstacked
@ kTypeBandstacked
Definition: diseqc.h:463
DiSEqCDevSettings::SetValue
void SetValue(uint devid, double value)
Sets a value for this configuration chain by device id.
Definition: diseqc.cpp:219
DiSEqCDevDevice::GetDescription
QString GetDescription(void) const
Definition: diseqc.h:175
MSqlQuery::lastInsertId
QVariant lastInsertId()
Return the id of the last inserted row.
Definition: mythdbcon.cpp:935
DiSEqCDevSettings::m_config
uint_to_dbl_t m_config
Definition: diseqc.h:47
DiSEqCDevSCR::SendCommand
bool SendCommand(uint cmd, uint repeats, cmd_vec_t &data) const
Definition: diseqc.cpp:2191
DiSEqCDevTree::Execute
bool Execute(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning)
Applies settings to the entire tree.
Definition: diseqc.cpp:509
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:204
DiSEqCDevRotor::m_moveTime
double m_moveTime
Definition: diseqc.h:374
DiSEqCDevRotor::RotorTypeToString
static QString RotorTypeToString(dvbdev_rotor_t type)
Definition: diseqc.h:345
DISEQC_CMD_DRIVE_E
@ DISEQC_CMD_DRIVE_E
Definition: diseqc.cpp:81
DiSEqCDevSwitch::GetChild
DiSEqCDevDevice * GetChild(uint ordinal) override
Retrieves the nth child of this node.
Definition: diseqc.cpp:1175
DiSEqCDevRotor::SetPosMap
void SetPosMap(const uint_to_dbl_t &posmap)
Definition: diseqc.cpp:1984
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:618
DiSEqCDevSwitch::m_numPorts
uint m_numPorts
Definition: diseqc.h:293
DiSEqCDevDevice::kTypeSwitch
@ kTypeSwitch
Definition: diseqc.h:155
DiSEqCDevTree::SetTone
bool SetTone(bool on) const
Definition: diseqc.cpp:482
DISEQC_CMD_CLR_RESET
@ DISEQC_CMD_CLR_RESET
Definition: diseqc.cpp:71
DiSEqCDevSwitch::Execute
bool Execute(const DiSEqCDevSettings &, const DTVMultiplex &) override
Applies DiSEqC settings to this node and any children.
Definition: diseqc.cpp:1080
DiSEqCDevRotor::m_child
DiSEqCDevDevice * m_child
Definition: diseqc.h:366
DiSEqCDevTrees
Static-scoped locked tree list class.
Definition: diseqc.h:61
DiSEqCDevRotor::kRotorTypeTable
static const TypeTableVec kRotorTypeTable
Definition: diseqc.h:379
DISEQC_CMD_WRITE_N0
@ DISEQC_CMD_WRITE_N0
Definition: diseqc.cpp:72
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
DiSEqCDevSwitch::m_lastPos
uint m_lastPos
Definition: diseqc.h:294
DiSEqCDevDevice
Represents a node in a DVB-S device network.
Definition: diseqc.h:139
DiSEqCDevDevice::GetVoltage
virtual uint GetVoltage(const DiSEqCDevSettings &, const DTVMultiplex &) const =0
Retrives the desired voltage for this config.
DiSEqCDevSCR::m_scrUserband
uint m_scrUserband
Definition: diseqc.h:437
DiSEqCDevSwitch::m_type
dvbdev_switch_t m_type
Definition: diseqc.h:291
DISEQC_FRM
static constexpr uint8_t DISEQC_FRM
Definition: diseqc.cpp:47
DiSEqCDevDevice::kTypeSCR
@ kTypeSCR
Definition: diseqc.h:157
DISEQC_CMD_DRIVE_W
@ DISEQC_CMD_DRIVE_W
Definition: diseqc.cpp:82
DiSEqCDevSettings::Load
bool Load(uint card_input_id)
Loads configuration chain from DB for specified card input id.
Definition: diseqc.cpp:128
DiSEqCDevSwitch::Reset
void Reset(void) override
Resets to the last known settings for this device.
Definition: diseqc.cpp:1137
DiSEqCDevSwitch::Store
bool Store(void) const override
Definition: diseqc.cpp:1274
DiSEqCDevSwitch::GetPosition
int GetPosition(const DiSEqCDevSettings &settings) const
Definition: diseqc.cpp:1640
DiSEqCDevTrees::m_treesLock
QMutex m_treesLock
Definition: diseqc.h:71
DiSEqCDevRotor::m_speedLo
double m_speedLo
Definition: diseqc.h:364
TIMEOUT_WAIT
static constexpr useconds_t TIMEOUT_WAIT
Definition: diseqc.cpp:44
DISEQC_ADR_POS_EL
@ DISEQC_ADR_POS_EL
Definition: diseqc.cpp:65
dtvmultiplex.h
DiSEqCDevTree::Exists
static bool Exists(int cardid)
Check if a Diseqc device tree exists.
Definition: diseqc.cpp:393
DiSEqCDevRotor::SetChild
bool SetChild(uint ordinal, DiSEqCDevDevice *device) override
Changes the nth child of this node.
Definition: diseqc.cpp:1751
DiSEqCDevTree::Open
void Open(int fd_frontend, bool is_SCR)
Retrieve device tree.
Definition: diseqc.cpp:790
DiSEqCDevSettings::m_inputId
uint m_inputId
current input id
Definition: diseqc.h:48
DiSEqCDevDevice::kTypeLNB
@ kTypeLNB
Definition: diseqc.h:158
DiSEqCDevDevice::Reset
virtual void Reset(void)
Resets to the last known settings for this device.
Definition: diseqc.h:147
DiSEqCDevSwitch::ExecuteTone
bool ExecuteTone(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning, uint pos)
Definition: diseqc.cpp:1495
DiSEqCDevSwitch::kTypeLegacySW42
@ kTypeLegacySW42
Definition: diseqc.h:243
TO_DEC
static constexpr double TO_DEC
Definition: diseqc.cpp:89
DiSEqCDevTrees::~DiSEqCDevTrees
~DiSEqCDevTrees()
Definition: diseqc.cpp:256
DiSEqCDevLNB::m_lofHi
uint m_lofHi
Definition: diseqc.h:494
DiSEqCDevRotor::ExecuteRotor
bool ExecuteRotor(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning, double angle)
Definition: diseqc.cpp:1993
DiSEqCDevSettings
DVB-S device settings class.
Definition: diseqc.h:36
DiSEqCDevRotor::m_lastPosition
double m_lastPosition
Definition: diseqc.h:369
DiSEqCDevLNB::m_lofLo
uint m_lofLo
Definition: diseqc.h:495
DiSEqCDevTree::kFirstFakeDiSEqCID
static const uint kFirstFakeDiSEqCID
Definition: diseqc.h:136
DiSEqCDevDevice::GetDeviceType
dvbdev_t GetDeviceType(void) const
Definition: diseqc.h:169
DiSEqCDevRotor::GetProgress
double GetProgress(void) const
Returns an indication of rotor progress.
Definition: diseqc.cpp:1939
cmd_vec_t
std::vector< uint8_t > cmd_vec_t
Definition: diseqc.h:34
DiSEqCDevRotor::CalculateAzimuth
static double CalculateAzimuth(double angle)
Definition: diseqc.cpp:2033
DiSEqCDevSwitch::GetChildCount
uint GetChildCount(void) const override
Retrieves the proper number of children for this node.
Definition: diseqc.cpp:1170
DiSEqCDevDevice::TableToString
static QString TableToString(uint type, const TypeTableVec &table)
Definition: diseqc.cpp:97
DiSEqCDevLNB::m_lofSwitch
uint m_lofSwitch
Definition: diseqc.h:493
DiSEqCDevLNB::IsPolarityInverted
bool IsPolarityInverted(void) const
Definition: diseqc.h:476
dvbtypes.h
DiSEqCDevRotor::Store
bool Store(void) const override
Definition: diseqc.cpp:1858
mythlogging.h
DiSEqCDevSCR::kSCRPositionTable
static const TypeTableVec kSCRPositionTable
Definition: diseqc.h:443
GetCurTimeFloating
static double GetCurTimeFloating(void)
Definition: diseqc.cpp:1665
DISEQC_ADR_ALL
@ DISEQC_ADR_ALL
Definition: diseqc.cpp:54
DiSEqCDevTree::ApplyVoltage
bool ApplyVoltage(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning)
Definition: diseqc.cpp:842
DiSEqCDevLNB::m_polInv
bool m_polInv
If a signal is circularly polarized the polarity will flip on each reflection, so antenna systems wit...
Definition: diseqc.h:499
DiSEqCDevSwitch::ExecuteMiniDiSEqC
bool ExecuteMiniDiSEqC(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning, uint pos)
Definition: diseqc.cpp:1531
DiSEqCDevSCR::Store
bool Store(void) const override
Definition: diseqc.cpp:2273
MythFile::copy
MBASE_PUBLIC long long copy(QFile &dst, QFile &src, uint block_size=0)
Copies src file to dst file.
Definition: mythmiscutil.cpp:263
DiSEqCDevDevice::TableFromString
static uint TableFromString(const QString &type, const TypeTableVec &table)
Definition: diseqc.cpp:105
DiSEqCDevTree::SetVoltage
bool SetVoltage(uint voltage)
Definition: diseqc.cpp:798
hardwareprofile.i18n.t
t
Definition: i18n.py:36
DiSEqCDevDevice::SetDeviceType
void SetDeviceType(dvbdev_t type)
Definition: diseqc.h:160
DiSEqCDevRotor::Load
bool Load(void) override
Loads this device from the database.
Definition: diseqc.cpp:1796
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:550
compat.h
DiSEqCDevDevice::TypeTableVec
std::vector< TypeTable > TypeTableVec
Definition: diseqc.h:214
DiSEqCDevSCR::~DiSEqCDevSCR
~DiSEqCDevSCR() override
Definition: diseqc.cpp:2092
DISEQC_CMD_LMT_W
@ DISEQC_CMD_LMT_W
Definition: diseqc.cpp:80
DiSEqCDevDevice::Load
virtual bool Load(void)=0
Loads this device from the database.
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:225
DiSEqCDevRotor::m_posmap
dbl_to_uint_t m_posmap
Definition: diseqc.h:365
DiSEqCDevRotor::IsPositionKnown
bool IsPositionKnown(void) const
Returns true if there is reasonable confidence in the value returned by GetProgress().
Definition: diseqc.cpp:1969
send_diseqc
static bool send_diseqc(int fd, const dvb_diseqc_master_cmd cmd)
Definition: diseqc.cpp:642
DiSEqCDevTree::CreateFakeDiSEqCID
uint CreateFakeDiSEqCID(void)
Definition: diseqc.h:121
uint_to_dbl_t
QMap< uint, double > uint_to_dbl_t
Definition: diseqc.h:30
DiSEqCDevSwitch::m_lastHorizontal
uint m_lastHorizontal
Definition: diseqc.h:296
DiSEqCDevDevice::kTypeRotor
@ kTypeRotor
Definition: diseqc.h:156
DiSEqCDevDevice::SetOrdinal
void SetOrdinal(uint ordinal)
Definition: diseqc.h:162
DiSEqCDevSCR
Unicable / SCR Class.
Definition: diseqc.h:382
DISEQC_CMD_LMT_E
@ DISEQC_CMD_LMT_E
Definition: diseqc.cpp:79
DiSEqCDevRotor::m_type
dvbdev_rotor_t m_type
Definition: diseqc.h:362
DISEQC_CMD_ODU
@ DISEQC_CMD_ODU
Definition: diseqc.cpp:75
DiSEqCDevSCR::Execute
bool Execute(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning) override
Applies DiSEqC settings to this node and any children.
Definition: diseqc.cpp:2103
DiSEqCDevDevice::m_repeat
uint m_repeat
Definition: diseqc.h:211
DiSEqCDevRotor::RotorTypeFromString
static dvbdev_rotor_t RotorTypeFromString(const QString &type)
Definition: diseqc.h:347
DiSEqCDevRotor::RotationComplete
void RotationComplete(void) const
Definition: diseqc.cpp:2072
DiSEqCDevTree::Load
bool Load(const QString &device)
Loads the device tree from the database.
Definition: diseqc.cpp:311
DiSEqCDevDevice::SetParent
void SetParent(DiSEqCDevDevice *parent)
Definition: diseqc.h:161
DISEQC_CMD_HALT
@ DISEQC_CMD_HALT
Definition: diseqc.cpp:77
DiSEqCDevSwitch::ExecuteLegacy
bool ExecuteLegacy(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning, uint pos)
Definition: diseqc.cpp:1362
DiSEqCDevTree::SetRoot
void SetRoot(DiSEqCDevDevice *root)
Changes the root node of the tree.
Definition: diseqc.cpp:632
DiSEqCDevLNB
LNB Class.
Definition: diseqc.h:446
DISEQC_POWER_ON_WAIT
static constexpr useconds_t DISEQC_POWER_ON_WAIT
Definition: diseqc.cpp:38
DiSEqCDevRotor::GetSelectedChild
DiSEqCDevDevice * GetSelectedChild(const DiSEqCDevSettings &setting) const override
Retrieves the selected child for this configuration, if any.
Definition: diseqc.cpp:1746
DiSEqCDevDevice::GetChild
virtual DiSEqCDevDevice * GetChild(uint)
Retrieves the nth child of this node.
Definition: diseqc.h:188
DiSEqCDevLNB::Load
bool Load(void) override
Loads this device from the database.
Definition: diseqc.cpp:2391
DiSEqCDevSwitch::IsCommandNeeded
bool IsCommandNeeded(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning) const override
Determines if this device or any child will be sending a command for the given configuration chain.
Definition: diseqc.cpp:1149
DISEQC_ADR_SW
@ DISEQC_ADR_SW
Definition: diseqc.cpp:59
DiSEqCDevSwitch::GetSelectedChild
DiSEqCDevDevice * GetSelectedChild(const DiSEqCDevSettings &settings) const override
Retrieves the selected child for this configuration, if any.
Definition: diseqc.cpp:1160
DiSEqCDevLNB::IsHorizontal
bool IsHorizontal(const DTVMultiplex &tuning) const
Determine if horizontal polarity is active (for switchable LNBs).
Definition: diseqc.cpp:2511
DiSEqCDevTree::GetFD
int GetFD(void) const
Definition: diseqc.h:109
DiSEqCDevRotor::Execute
bool Execute(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning) override
Applies DiSEqC settings to this node and any children.
Definition: diseqc.cpp:1688
DiSEqCDevRotor::kTypeDiSEqC_1_3
@ kTypeDiSEqC_1_3
Definition: diseqc.h:316
DiSEqCDevRotor::m_lastPosKnown
bool m_lastPosKnown
Definition: diseqc.h:375
DiSEqCDevDevice::m_parent
DiSEqCDevDevice * m_parent
Definition: diseqc.h:209
DiSEqCDevSCR::m_scrFrequency
uint m_scrFrequency
Definition: diseqc.h:438
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
DiSEqCDevRotor::GetPosMap
uint_to_dbl_t GetPosMap(void) const
Definition: diseqc.cpp:1974
DiSEqCDevSwitch::ExecuteVoltage
bool ExecuteVoltage(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning, uint pos)
Definition: diseqc.cpp:1511
DiSEqCDevLNB::Execute
bool Execute(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning) override
Applies DiSEqC settings to this node and any children.
Definition: diseqc.cpp:2368
DiSEqCDev::FindTree
static DiSEqCDevTree * FindTree(uint cardid)
Retrieve device tree.
Definition: diseqc.cpp:237
DiSEqCDevRotor::kTypeDiSEqC_1_2
@ kTypeDiSEqC_1_2
Definition: diseqc.h:316
TO_RADS
static constexpr double TO_RADS
Definition: diseqc.cpp:88
DiSEqCDev::s_trees
static DiSEqCDevTrees s_trees
Definition: diseqc.h:58
DISEQC_CMD_WRITE_N1
@ DISEQC_CMD_WRITE_N1
Definition: diseqc.cpp:73
DISEQC_CMD_STORE_POS
@ DISEQC_CMD_STORE_POS
Definition: diseqc.cpp:83
DiSEqCDevDevice::IsCommandNeeded
virtual bool IsCommandNeeded(const DiSEqCDevSettings &, const DTVMultiplex &) const
Determines if this device or any child will be sending a command for the given configuration chain.
Definition: diseqc.h:178
DiSEqCDevDevice::CreateByType
static DiSEqCDevDevice * CreateByType(DiSEqCDevTree &tree, dvbdev_t type, uint dev_id=0)
Definition: diseqc.cpp:935
DiSEqCDevSCR::SetChild
bool SetChild(uint ordinal, DiSEqCDevDevice *device) override
Changes the nth child of this node.
Definition: diseqc.cpp:2334
DiSEqCDevTree::FindDevice
DiSEqCDevDevice * FindDevice(uint dev_id)
Returns a device by ID.
Definition: diseqc.cpp:620
DiSEqCDevSCR::PowerOff
bool PowerOff(void) const
Definition: diseqc.cpp:2165
DiSEqCDevTree::m_lastVoltage
uint m_lastVoltage
Definition: diseqc.h:132
DiSEqCDevSwitch::Load
bool Load(void) override
Loads this device from the database.
Definition: diseqc.cpp:1213
DiSEqCDevTree::FindLNB
DiSEqCDevLNB * FindLNB(const DiSEqCDevSettings &settings)
Returns the LNB device object selected by the configuration chain.
Definition: diseqc.cpp:573
DiSEqCDevLNB::LNBTypeToString
static QString LNBTypeToString(dvbdev_lnb_t type)
Definition: diseqc.h:485
DiSEqCDevSwitch::m_children
dvbdev_vec_t m_children
Definition: diseqc.h:297
DiSEqCDevRotor::StartRotorPositionTracking
void StartRotorPositionTracking(double azimuth)
Definition: diseqc.cpp:2058
DiSEqCDevRotor::ExecuteUSALS
bool ExecuteUSALS(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning, double angle)
Definition: diseqc.cpp:2014
DiSEqCDevSwitch::kTypeTone
@ kTypeTone
Definition: diseqc.h:239
DiSEqCDevSwitch::kTypeDiSEqCCommitted
@ kTypeDiSEqCCommitted
Definition: diseqc.h:240
DiSEqCDevSCR::m_scrPin
int m_scrPin
Definition: diseqc.h:439
set_voltage
static bool set_voltage(int fd, fe_sec_voltage volt)
Definition: diseqc.cpp:1451
DTVPolarity::toString
QString toString() const
Definition: dtvconfparserhelpers.h:632
diseqc_bus_already_reset
bool diseqc_bus_already_reset
Definition: diseqc.cpp:95
DiSEqCDevSwitch::SetNumPorts
void SetNumPorts(uint num_ports)
Definition: diseqc.cpp:1339
DiSEqCDevSettings::Store
bool Store(uint card_input_id) const
Stores configuration chain to DB for specified card input id.
Definition: diseqc.cpp:162
DiSEqCDev::InvalidateTrees
static void InvalidateTrees(void)
Invalidate cached trees.
Definition: diseqc.cpp:245
DiSEqCDevTree::ResetDiseqc
bool ResetDiseqc(bool hard_reset, bool is_SCR)
Resets the DiSEqC bus.
Definition: diseqc.cpp:741
DiSEqCDevSwitch::kTypeLegacySW64
@ kTypeLegacySW64
Definition: diseqc.h:244
DiSEqCDevDevice::~DiSEqCDevDevice
virtual ~DiSEqCDevDevice()
Definition: diseqc.cpp:869
DiSEqCDevDevice::kDvbdevLookup
static const TypeTableVec kDvbdevLookup
Definition: diseqc.h:220
DiSEqCDevRotor::m_lastAzimuth
double m_lastAzimuth
Definition: diseqc.h:376
DiSEqCDevSwitch::kTypeDiSEqCUncommitted
@ kTypeDiSEqCUncommitted
Definition: diseqc.h:241
DiSEqCDevTree::FindRotor
DiSEqCDevRotor * FindRotor(const DiSEqCDevSettings &settings, uint index=0)
Returns the nth rotor device object in the tree.
Definition: diseqc.cpp:550
mythcorecontext.h
DiSEqCDevRotor::GetVoltage
uint GetVoltage(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning) const override
Retrives the desired voltage for this config.
Definition: diseqc.cpp:1779
DiSEqCDevSwitch::kTypeMiniDiSEqC
@ kTypeMiniDiSEqC
Definition: diseqc.h:246
DISEQC_SHORT_WAIT
static constexpr useconds_t DISEQC_SHORT_WAIT
Definition: diseqc.cpp:36
DiSEqCDevDevice::dvbdev_t
dvbdev_t
Definition: diseqc.h:153
DiSEqCDevDevice::CreateById
static DiSEqCDevDevice * CreateById(DiSEqCDevTree &tree, uint devid)
Definition: diseqc.cpp:899
DiSEqCDevSCR::m_child
DiSEqCDevDevice * m_child
Definition: diseqc.h:441
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:888
DISEQC_CMD_ODU_MDU
@ DISEQC_CMD_ODU_MDU
Definition: diseqc.cpp:76
DiSEqCDevRotor::m_reset
bool m_reset
Definition: diseqc.h:371
DiSEqCDevTree::m_root
DiSEqCDevDevice * m_root
Definition: diseqc.h:131
DiSEqCDevDevice::DevTypeFromString
static dvbdev_t DevTypeFromString(const QString &type)
Definition: diseqc.h:193
DiSEqCDevSwitch::~DiSEqCDevSwitch
~DiSEqCDevSwitch() override
Definition: diseqc.cpp:1074
DISEQC_ADR_SMATV
@ DISEQC_ADR_SMATV
Definition: diseqc.cpp:60
DISEQC_ADR_SW_BLK
@ DISEQC_ADR_SW_BLK
Definition: diseqc.cpp:58
DiSEqCDevTree::FindSCR
DiSEqCDevSCR * FindSCR(const DiSEqCDevSettings &settings)
Returns the SCR device object selected by the configuration chain.
Definition: diseqc.cpp:596
DiSEqCDevDevice::IsRealDeviceID
bool IsRealDeviceID(void) const
Definition: diseqc.h:171
DiSEqCDevSwitch::ExecuteDiseqc
bool ExecuteDiseqc(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning, uint pos)
Definition: diseqc.cpp:1593
DiSEqCDevRotor::Reset
void Reset(void) override
Resets to the last known settings for this device.
Definition: diseqc.cpp:1725
DiSEqCDevRotor::GetApproxAzimuth
double GetApproxAzimuth(void) const
Definition: diseqc.cpp:2049
mini_diseqc
static bool mini_diseqc(int fd, fe_sec_mini_cmd cmd)
Definition: diseqc.cpp:1473
DiSEqCDevRotor::IsMoving
bool IsMoving(const DiSEqCDevSettings &settings) const
Definition: diseqc.cpp:1770
DiSEqCDevSCR::Load
bool Load(void) override
Loads this device from the database.
Definition: diseqc.cpp:2222
DiSEqCDevTree
DVB-S device tree class. Represents a tree of DVB-S devices.
Definition: diseqc.h:74
DiSEqCDevDevice::Store
virtual bool Store(void) const =0
DiSEqCDevDevice::SetDescription
void SetDescription(const QString &desc)
Definition: diseqc.h:163
DiSEqCDevLNB::IsHighBand
bool IsHighBand(const DTVMultiplex &tuning) const
Determine if the high frequency band is active (for switchable LNBs).
Definition: diseqc.cpp:2491
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:842
DTVMultiplex::m_polarity
DTVPolarity m_polarity
Definition: dtvmultiplex.h:104
DiSEqCDevTree::Store
bool Store(uint cardid, const QString &device="")
Stores the device tree to the database.
Definition: diseqc.cpp:422
DISEQC_ADR_LNB_SW
@ DISEQC_ADR_LNB_SW
Definition: diseqc.cpp:57
DISEQC_CMDS
DISEQC_CMDS
Definition: diseqc.cpp:69
DiSEqCDevTrees::FindTree
DiSEqCDevTree * FindTree(uint cardid)
Retrieve device tree.
Definition: diseqc.cpp:265
DiSEqCDevDevice::GetDeviceID
uint GetDeviceID(void) const
Definition: diseqc.h:170
DiSEqCDevSwitch::DiSEqCDevSwitch
DiSEqCDevSwitch(DiSEqCDevTree &tree, uint devid)
Definition: diseqc.cpp:1063
DiSEqCDevSwitch::kTypeLegacySW21
@ kTypeLegacySW21
Definition: diseqc.h:242
DiSEqCDevSCR::Reset
void Reset(void) override
Resets to the last known settings for this device.
Definition: diseqc.cpp:2097
DiSEqCDevTree::GetVoltage
uint GetVoltage(void) const
Definition: diseqc.h:116
DISEQC_POWER_OFF_WAIT
static constexpr useconds_t DISEQC_POWER_OFF_WAIT
Definition: diseqc.cpp:39
DiSEqCDevLNB::m_type
dvbdev_lnb_t m_type
Definition: diseqc.h:492
TIMEOUT_RETRIES
static constexpr uint8_t TIMEOUT_RETRIES
Definition: diseqc.cpp:43
DISEQC_CMD_GOTO_X
@ DISEQC_CMD_GOTO_X
Definition: diseqc.cpp:85
DiSEqCDevDevice::GetSelectedChild
virtual DiSEqCDevDevice * GetSelectedChild(const DiSEqCDevSettings &) const
Retrieves the selected child for this configuration, if any.
Definition: diseqc.h:186
DiSEqCDevDevice::Execute
virtual bool Execute(const DiSEqCDevSettings &, const DTVMultiplex &)=0
Applies DiSEqC settings to this node and any children.
DiSEqCDevRotor::m_speedHi
double m_speedHi
Definition: diseqc.h:363
DiSEqCDevTrees::m_trees
cardid_to_diseqc_tree_t m_trees
Definition: diseqc.h:70
DiSEqCDevRotor::m_desiredAzimuth
double m_desiredAzimuth
Definition: diseqc.h:370
EPS
static constexpr double EPS
Definition: diseqc.cpp:91
DiSEqCDevTrees::InvalidateTrees
void InvalidateTrees(void)
Invalidate cached trees.
Definition: diseqc.cpp:283
DiSEqCDevSwitch::GetVoltage
uint GetVoltage(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning) const override
Retrives the desired voltage for this config.
Definition: diseqc.cpp:1201
DiSEqCDevLNB::GetVoltage
uint GetVoltage(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning) const override
Retrives the desired voltage for this config.
Definition: diseqc.cpp:2377
DiSEqCDevTree::Reset
void Reset(void)
Reset state of nodes in tree, forcing updates on the next Execute command.
Definition: diseqc.cpp:536
DiSEqCDevSCR::dvbdev_pos_t
dvbdev_pos_t
Definition: diseqc.h:397
DiSEqCDevSwitch::m_address
uint m_address
Definition: diseqc.h:292
DISEQC_CMD_LMT_OFF
@ DISEQC_CMD_LMT_OFF
Definition: diseqc.cpp:78
M_PI
static constexpr double M_PI
Definition: goom_tools.h:9
DiSEqCDevSwitch::m_lastHighBand
uint m_lastHighBand
Definition: diseqc.h:295
uint
unsigned int uint
Definition: freesurround.h:24
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:902
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:2523
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:837
DiSEqCDevTree::AddDeferredDelete
void AddDeferredDelete(uint dev_id)
Definition: diseqc.h:120
DiSEqCDevSwitch
Switch class, including tone, legacy and DiSEqC switches.
Definition: diseqc.h:223
DISEQC_ADR_SW_ALL
@ DISEQC_ADR_SW_ALL
Definition: diseqc.cpp:55
DiSEqCDevSwitch::ShouldSwitch
bool ShouldSwitch(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning) const
Definition: diseqc.cpp:1548