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
59  DISEQC_ADR_SW = 0x15,
66 };
67 
68 // Command byte
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 = ((voltage == SEC_VOLTAGE_18) ? 18 :
804  ((voltage == SEC_VOLTAGE_13) ? 13 : 0));
805 
806  LOG(VB_CHANNEL, LOG_INFO, LOC + "Changing LNB voltage to " +
807  QString("%1V").arg(volts));
808 
809  bool success = false;
810 
811 #ifdef USING_DVB
812  for (uint retry = 0; !success && retry < TIMEOUT_RETRIES; retry++)
813  {
814  if (ioctl(m_fdFrontend, FE_SET_VOLTAGE, voltage) == 0)
815  success = true;
816  else
817  usleep(TIMEOUT_WAIT);
818  }
819 #endif // USING_DVB
820 
821  if (!success)
822  {
823  LOG(VB_GENERAL, LOG_ERR, LOC + "FE_SET_VOLTAGE failed" + ENO);
824  return false;
825  }
826 
827  m_lastVoltage = voltage;
828  return true;
829 }
830 
832 {
833  if (m_root)
835 
836  return false;
837 }
838 
840  const DTVMultiplex &tuning)
841 {
842  uint voltage = SEC_VOLTAGE_18;
843 
844  if (m_root)
845  voltage = m_root->GetVoltage(settings, tuning);
846 
847  return SetVoltage(voltage);
848 }
849 
851 
856 const std::vector<DiSEqCDevDevice::TypeTable> DiSEqCDevDevice::kDvbdevLookup
857 {
858  { "switch", kTypeSwitch },
859  { "rotor", kTypeRotor },
860  { "scr", kTypeSCR },
861  { "lnb", kTypeLNB },
862  { QString(), kTypeLNB },
863 };
864 
865 
867 {
868  if (IsRealDeviceID())
870 }
871 
873 {
874  DiSEqCDevDevice *dev = nullptr;
875 
876  if (GetDeviceID() == dev_id)
877  dev = this;
878 
879  uint num_children = GetChildCount();
880 
881  for (uint ch = 0; !dev && ch < num_children; ch++)
882  {
883  DiSEqCDevDevice *child = GetChild(ch);
884  if (child)
885  {
886  if (child->GetDeviceID() == dev_id)
887  dev = child;
888  else
889  dev = child->FindDevice(dev_id);
890  }
891  }
892 
893  return dev;
894 }
895 
897 {
898  // load settings from DB
899  MSqlQuery query(MSqlQuery::InitCon());
900  query.prepare(
901  "SELECT type, description "
902  "FROM diseqc_tree "
903  "WHERE diseqcid = :DEVID");
904  query.bindValue(":DEVID", devid);
905 
906  if (!query.exec() || !query.isActive())
907  {
908  MythDB::DBError("DiSEqCDevDevice::CreateById", query);
909  return nullptr;
910  }
911  if (!query.next())
912  {
913  LOG(VB_GENERAL, LOG_ERR, LOC + "CreateById failed to find dtv dev " +
914  QString("%1").arg(devid));
915 
916  return nullptr;
917  }
918 
919  dvbdev_t type = DevTypeFromString(query.value(0).toString());
920  QString desc = query.value(1).toString();
921  DiSEqCDevDevice *node = CreateByType(tree, type, devid);
922 
923  if (node)
924  {
925  node->SetDescription(desc);
926  node->Load();
927  }
928 
929  return node;
930 }
931 
933  dvbdev_t type,
934  uint dev_id)
935 {
936  if (!dev_id)
937  dev_id = tree.CreateFakeDiSEqCID();
938 
939  DiSEqCDevDevice *node = nullptr;
940  switch (type)
941  {
942  case kTypeSwitch:
943  node = new DiSEqCDevSwitch(tree, dev_id);
944  if (node)
945  node->SetDescription("Switch");
946  break;
947  case kTypeRotor:
948  node = new DiSEqCDevRotor(tree, dev_id);
949  if (node)
950  node->SetDescription("Rotor");
951  break;
952  case kTypeSCR:
953  node = new DiSEqCDevSCR(tree, dev_id);
954  if (node)
955  node->SetDescription("Unicable");
956  break;
957  case kTypeLNB:
958  node = new DiSEqCDevLNB(tree, dev_id);
959  if (node)
960  node->SetDescription("LNB");
961  break;
962  default:
963  break;
964  }
965 
966  if (node)
967  node->SetDeviceType(type);
968 
969  return node;
970 }
971 
1041 
1047 const std::vector<DiSEqCDevDevice::TypeTable> DiSEqCDevSwitch::kSwitchTypeTable
1048 {
1049  { "legacy_sw21", kTypeLegacySW21 },
1050  { "legacy_sw42", kTypeLegacySW42 },
1051  { "legacy_sw64", kTypeLegacySW64 },
1052  { "tone", kTypeTone },
1053  { "diseqc", kTypeDiSEqCCommitted },
1054  { "diseqc_uncom", kTypeDiSEqCUncommitted },
1055  { "voltage", kTypeVoltage },
1056  { "mini_diseqc", kTypeMiniDiSEqC },
1057  { QString(), kTypeTone },
1058 };
1059 
1061  : DiSEqCDevDevice(tree, devid)
1062 {
1063  m_children.resize(m_numPorts);
1064 
1065  for (uint i = 0; i < m_numPorts; i++)
1066  m_children[i] = nullptr;
1067 
1069 }
1070 
1072 {
1073  for (auto & child : m_children)
1074  delete child;
1075 }
1076 
1078  const DTVMultiplex &tuning)
1079 {
1080  bool success = true;
1081 
1082  // sanity check switch position
1083  int pos = GetPosition(settings);
1084  if (pos < 0)
1085  return false;
1086 
1087  // perform switching
1088  if (ShouldSwitch(settings, tuning))
1089  {
1090  switch (m_type)
1091  {
1092  case kTypeTone:
1093  success = ExecuteTone(settings, tuning, pos);
1094  break;
1095  case kTypeDiSEqCCommitted:
1097  success = ExecuteDiseqc(settings, tuning, pos);
1098  break;
1099  case kTypeLegacySW21:
1100  case kTypeLegacySW42:
1101  case kTypeLegacySW64:
1102  success = ExecuteLegacy(settings, tuning, pos);
1103  break;
1104  case kTypeVoltage:
1105  success = ExecuteVoltage(settings, tuning, pos);
1106  break;
1107  case kTypeMiniDiSEqC:
1108  success = ExecuteMiniDiSEqC(settings, tuning, pos);
1109  break;
1110  default:
1111  success = false;
1112  LOG(VB_GENERAL, LOG_ERR, LOC +
1113  QString("Unknown switch type (%1)").arg((uint)m_type));
1114  break;
1115  }
1116 
1117  // if a child device will be sending a diseqc command, wait 100ms
1118  if (m_children[pos]->IsCommandNeeded(settings, tuning))
1119  {
1120  LOG(VB_CHANNEL, LOG_INFO, LOC + "Waiting for switch");
1121  usleep(DISEQC_LONG_WAIT);
1122  }
1123 
1124  m_lastPos = pos;
1125  }
1126 
1127  // chain to child if the switch was successful
1128  if (success)
1129  success = m_children[pos]->Execute(settings, tuning);
1130 
1131  return success;
1132 }
1133 
1135 {
1136  m_lastPos = UINT_MAX;
1137  m_lastHighBand = UINT_MAX;
1138  m_lastHorizontal = UINT_MAX;
1139  for (auto & child : m_children)
1140  {
1141  if (child)
1142  child->Reset();
1143  }
1144 }
1145 
1147  const DTVMultiplex &tuning) const
1148 {
1149  int pos = GetPosition(settings);
1150  if (pos < 0)
1151  return false;
1152 
1153  return (ShouldSwitch(settings, tuning) ||
1154  m_children[pos]->IsCommandNeeded(settings, tuning));
1155 }
1156 
1158 {
1159  // sanity check switch position
1160  int pos = GetPosition(settings);
1161  if (pos < 0)
1162  return nullptr;
1163 
1164  return m_children[pos];
1165 }
1166 
1168 {
1169  return m_numPorts;
1170 }
1171 
1173 {
1174  if (ordinal < m_children.size())
1175  return m_children[ordinal];
1176 
1177  return nullptr;
1178 }
1179 
1181 {
1182  if (ordinal >= m_children.size())
1183  return false;
1184 
1185  if (m_children[ordinal])
1186  delete m_children[ordinal];
1187 
1188  m_children[ordinal] = device;
1189  if (device)
1190  {
1191  device->SetOrdinal(ordinal);
1192  device->SetParent(this);
1193  }
1194 
1195  return true;
1196 }
1197 
1199  const DTVMultiplex &tuning) const
1200 {
1201  uint voltage = SEC_VOLTAGE_18;
1202  DiSEqCDevDevice *child = GetSelectedChild(settings);
1203 
1204  if (child)
1205  voltage = child->GetVoltage(settings, tuning);
1206 
1207  return voltage;
1208 }
1209 
1211 {
1212  // clear old children
1213  for (auto & child : m_children)
1214  delete child;
1215 
1216  m_children.clear();
1217 
1218  // populate switch parameters from db
1219  MSqlQuery query(MSqlQuery::InitCon());
1220  query.prepare(
1221  "SELECT subtype, address, switch_ports, cmd_repeat "
1222  "FROM diseqc_tree "
1223  "WHERE diseqcid = :DEVID");
1224  query.bindValue(":DEVID", GetDeviceID());
1225 
1226  if (!query.exec() || !query.isActive())
1227  {
1228  MythDB::DBError("DiSEqCDevSwitch::Load 1", query);
1229  return false;
1230  }
1231  if (query.next())
1232  {
1233  m_type = SwitchTypeFromString(query.value(0).toString());
1234  m_address = query.value(1).toUInt();
1235  m_numPorts = query.value(2).toUInt();
1236  m_repeat = query.value(3).toUInt();
1237  m_children.resize(m_numPorts);
1238  for (uint i = 0; i < m_numPorts; i++)
1239  m_children[i] = nullptr;
1240  }
1241 
1242  // load children from db
1243  query.prepare(
1244  "SELECT diseqcid, ordinal "
1245  "FROM diseqc_tree "
1246  "WHERE parentid = :DEVID");
1247  query.bindValue(":DEVID", GetDeviceID());
1248  if (!query.exec() || !query.isActive())
1249  {
1250  MythDB::DBError("DiSEqCDevSwitch::Load 2", query);
1251  return false;
1252  }
1253 
1254  while (query.next())
1255  {
1256  uint child_dev_id = query.value(0).toUInt();
1257  uint ordinal = query.value(1).toUInt();
1258  DiSEqCDevDevice *child = CreateById(m_tree, child_dev_id);
1259  if (child && !SetChild(ordinal, child))
1260  {
1261  LOG(VB_GENERAL, LOG_ERR, LOC +
1262  QString("Switch port out of range (%1 > %2)")
1263  .arg(ordinal + 1).arg(m_numPorts));
1264  delete child;
1265  }
1266  }
1267 
1268  return true;
1269 }
1270 
1271 bool DiSEqCDevSwitch::Store(void) const
1272 {
1273  QString type = SwitchTypeToString(m_type);
1274  MSqlQuery query(MSqlQuery::InitCon());
1275 
1276  // insert new or update old
1277  if (IsRealDeviceID())
1278  {
1279  query.prepare(
1280  "UPDATE diseqc_tree "
1281  "SET parentid = :PARENT, "
1282  " ordinal = :ORDINAL, "
1283  " type = 'switch', "
1284  " description = :DESC, "
1285  " subtype = :TYPE, "
1286  " address = :ADDRESS, "
1287  " switch_ports = :PORTS, "
1288  " cmd_repeat = :REPEAT "
1289  "WHERE diseqcid = :DEVID");
1290  query.bindValue(":DEVID", GetDeviceID());
1291  }
1292  else
1293  {
1294  query.prepare(
1295  "INSERT INTO diseqc_tree"
1296  " ( parentid, ordinal, type, "
1297  " description, address, subtype, "
1298  " switch_ports, cmd_repeat ) "
1299  "VALUES "
1300  " (:PARENT, :ORDINAL, 'switch', "
1301  " :DESC, :ADDRESS, :TYPE, "
1302  " :PORTS, :REPEAT )");
1303  }
1304 
1305  if (m_parent)
1306  query.bindValue(":PARENT", m_parent->GetDeviceID());
1307 
1308  query.bindValue(":ORDINAL", m_ordinal);
1309  query.bindValue(":DESC", GetDescription());
1310  query.bindValue(":ADDRESS", m_address);
1311  query.bindValue(":TYPE", type);
1312  query.bindValue(":PORTS", m_numPorts);
1313  query.bindValue(":REPEAT", m_repeat);
1314 
1315  if (!query.exec())
1316  {
1317  MythDB::DBError("DiSEqCDevSwitch::Store", query);
1318  return false;
1319  }
1320 
1321  // figure out devid if we did an insert
1322  if (!IsRealDeviceID())
1323  SetDeviceID(query.lastInsertId().toUInt());
1324 
1325  // chain to children
1326  bool success = true;
1327  for (auto *child : m_children)
1328  {
1329  if (child)
1330  success &= child->Store();
1331  }
1332 
1333  return success;
1334 }
1335 
1337 {
1338  uint old_num = m_children.size();
1339 
1340  if (old_num > num_ports)
1341  {
1342  for (uint ch = num_ports; ch < old_num; ch++)
1343  {
1344  if (m_children[ch])
1345  delete m_children[ch];
1346  }
1347  m_children.resize(num_ports);
1348  }
1349  else if (old_num < num_ports)
1350  {
1351  m_children.resize(num_ports);
1352  for (uint ch = old_num; ch < num_ports; ch++)
1353  m_children[ch] = nullptr;
1354  }
1355 
1356  m_numPorts = num_ports;
1357 }
1358 
1359 bool DiSEqCDevSwitch::ExecuteLegacy([[maybe_unused]] const DiSEqCDevSettings &settings,
1360  [[maybe_unused]] const DTVMultiplex &tuning,
1361  [[maybe_unused]] uint pos)
1362 {
1363 #if defined(USING_DVB) && defined(FE_DISHNETWORK_SEND_LEGACY_CMD)
1364  static const cmd_vec_t kSw21Cmds { 0x34, 0x65, };
1365  static const cmd_vec_t kSw42Cmds { 0x46, 0x17, };
1366  static const cmd_vec_t kSw64VCmds { 0x39, 0x4b, 0x0d, };
1367  static const cmd_vec_t kSw64HCmds { 0x1a, 0x5c, 0x2e, };
1368 
1369  cmd_vec_t cmds {};
1370  unsigned char horizcmd = 0x00;
1371 
1372  // determine polarity from lnb
1373  bool horizontal = false;
1374  DiSEqCDevLNB *lnb = m_tree.FindLNB(settings);
1375  if (lnb)
1376  horizontal = lnb->IsHorizontal(tuning);
1377 
1378  // get command table for this switch
1379  switch (m_type)
1380  {
1381  case kTypeLegacySW21:
1382  cmds = kSw21Cmds;
1383  if (horizontal)
1384  horizcmd = 0x80;
1385  break;
1386  case kTypeLegacySW42:
1387  cmds = kSw42Cmds;
1388  break;
1389  case kTypeLegacySW64:
1390  if (horizontal)
1391  cmds = kSw64HCmds;
1392  else
1393  cmds = kSw64VCmds;
1394  break;
1395  default:
1396  return false;
1397  }
1398  pos %= cmds.size();
1399 
1400  LOG(VB_CHANNEL, LOG_INFO, LOC +
1401  QString("Changing to Legacy switch port %1/%2")
1402  .arg(pos + 1).arg(cmds.size()));
1403 
1404  // send command
1405  if (ioctl(m_tree.GetFD(), FE_DISHNETWORK_SEND_LEGACY_CMD,
1406  cmds[pos] | horizcmd) == -1)
1407  {
1408  LOG(VB_GENERAL, LOG_ERR, LOC +
1409  "FE_DISHNETWORK_SEND_LEGACY_CMD failed" + ENO);
1410 
1411  return false;
1412  }
1413 
1414  return true;
1415 
1416 #else // !FE_DISHNETWORK_SEND_LEGACY_CMD
1417 
1418  LOG(VB_GENERAL, LOG_ERR, LOC + "You must compile with a newer "
1419  "version of the linux headers for DishNet Legacy switch support.");
1420  return false;
1421 
1422 #endif // !FE_DISHNETWORK_SEND_LEGACY_CMD
1423 }
1424 
1425 #ifdef USING_DVB
1426 static bool set_tone(int fd, fe_sec_tone_mode tone)
1427 {
1428  bool success = false;
1429 
1430  for (uint retry = 0; !success && (retry < TIMEOUT_RETRIES); retry++)
1431  {
1432  if (ioctl(fd, FE_SET_TONE, tone) == 0)
1433  success = true;
1434  else
1435  usleep(TIMEOUT_WAIT);
1436  }
1437 
1438  if (!success)
1439  {
1440  LOG(VB_GENERAL, LOG_ERR, LOC + "set_tone failed" + ENO);
1441  }
1442 
1443  return success;
1444 }
1445 #endif // USING_DVB
1446 
1447 #ifdef USING_DVB
1448 static bool set_voltage(int fd, fe_sec_voltage volt)
1449 {
1450  bool success = false;
1451 
1452  for (uint retry = 0; !success && (retry < TIMEOUT_RETRIES); retry++)
1453  {
1454  if (0 == ioctl(fd, FE_SET_VOLTAGE, volt))
1455  success = true;
1456  else
1457  usleep(TIMEOUT_WAIT);
1458  }
1459 
1460  if (!success)
1461  {
1462  LOG(VB_GENERAL, LOG_ERR, LOC + "FE_SET_VOLTAGE failed" + ENO);
1463  }
1464 
1465  return success;
1466 }
1467 #endif // USING_DVB
1468 
1469 #ifdef USING_DVB
1470 static bool mini_diseqc(int fd, fe_sec_mini_cmd cmd)
1471 {
1472  bool success = false;
1473 
1474  for (uint retry = 0; !success && (retry < TIMEOUT_RETRIES); retry++)
1475  {
1476  if (ioctl(fd, FE_DISEQC_SEND_BURST, cmd) == 0)
1477  success = true;
1478  else
1479  usleep(TIMEOUT_WAIT);
1480  }
1481 
1482  if (!success)
1483  {
1484  LOG(VB_GENERAL, LOG_ERR, LOC +
1485  "mini_diseqc FE_DISEQC_SEND_BURST failed" + ENO);
1486  }
1487 
1488  return success;
1489 }
1490 #endif // USING_DVB
1491 
1493  const DTVMultiplex &/*tuning*/,
1494  uint pos)
1495 {
1496  LOG(VB_CHANNEL, LOG_INFO, LOC + "Changing to Tone switch port " +
1497  QString("%1/2").arg(pos + 1));
1498 
1499 #ifdef USING_DVB
1500  if (set_tone(m_tree.GetFD(), (0 == pos) ? SEC_TONE_OFF : SEC_TONE_ON))
1501  return true;
1502 #endif // USING_DVB
1503 
1504  LOG(VB_GENERAL, LOG_ERR, LOC + "Setting Tone Switch failed." + ENO);
1505  return false;
1506 }
1507 
1508 bool DiSEqCDevSwitch::ExecuteVoltage([[maybe_unused]] const DiSEqCDevSettings &settings,
1509  [[maybe_unused]] const DTVMultiplex &tuning,
1510  uint pos)
1511 {
1512  LOG(VB_CHANNEL, LOG_INFO, LOC + "Changing to Voltage Switch port " +
1513  QString("%1/2").arg(pos + 1));
1514 
1515 #ifdef USING_DVB
1516  if (set_voltage(m_tree.GetFD(),
1517  (0 == pos) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18))
1518  {
1519  return true;
1520  }
1521 #endif // USING_DVB
1522 
1523  LOG(VB_GENERAL, LOG_ERR, LOC + "Setting Voltage Switch failed." + ENO);
1524 
1525  return false;
1526 }
1527 
1528 bool DiSEqCDevSwitch::ExecuteMiniDiSEqC([[maybe_unused]] const DiSEqCDevSettings &settings,
1529  [[maybe_unused]] const DTVMultiplex &tuning,
1530  uint pos)
1531 {
1532  LOG(VB_CHANNEL, LOG_INFO, LOC + "Changing to MiniDiSEqC Switch port " +
1533  QString("%1/2").arg(pos + 1));
1534 
1535 #ifdef USING_DVB
1536  if (mini_diseqc(m_tree.GetFD(), (0 == pos) ? SEC_MINI_A : SEC_MINI_B))
1537  return true;
1538 #endif // USING_DVB
1539 
1540  LOG(VB_GENERAL, LOG_ERR, LOC + "Setting Mini DiSEqC Switch failed." + ENO);
1541 
1542  return false;
1543 }
1544 
1546  const DTVMultiplex &tuning) const
1547 {
1548  int pos = GetPosition(settings);
1549  if (pos < 0)
1550  return false;
1551 
1552  // committed switch should change for band and polarity as well
1554  {
1555  // retrieve LNB info
1556  bool high_band = false;
1557  bool horizontal = false;
1558  DiSEqCDevLNB *lnb = m_tree.FindLNB(settings);
1559  if (lnb)
1560  {
1561  high_band = lnb->IsHighBand(tuning);
1562  horizontal = lnb->IsHorizontal(tuning);
1563  }
1564 
1565  if(static_cast<uint>(high_band) != m_lastHighBand ||
1566  static_cast<uint>(horizontal) != m_lastHorizontal)
1567  return true;
1568  }
1569  else if (kTypeLegacySW42 == m_type ||
1571  {
1572  // retrieve LNB info
1573  bool horizontal = false;
1574  DiSEqCDevLNB *lnb = m_tree.FindLNB(settings);
1575  if (lnb)
1576  horizontal = lnb->IsHorizontal(tuning);
1577 
1578  if (static_cast<unsigned int>(horizontal) != m_lastHorizontal)
1579  return true;
1580  }
1581  else if (kTypeVoltage == m_type ||
1582  kTypeTone == m_type)
1583  return true;
1584 
1585  return m_lastPos != (uint)pos;
1586 }
1587 
1589  const DTVMultiplex &tuning,
1590  uint pos32)
1591 {
1592  auto pos = static_cast<uint8_t>(pos32);
1593  // retrieve LNB info
1594  bool high_band = false;
1595  bool horizontal = false;
1596  DiSEqCDevLNB *lnb = m_tree.FindLNB(settings);
1597  if (lnb)
1598  {
1599  high_band = lnb->IsHighBand(tuning);
1600  horizontal = lnb->IsHorizontal(tuning);
1601  }
1602 
1603  // check number of ports
1604  if (((kTypeDiSEqCCommitted == m_type) && (m_numPorts > 4)) ||
1605  ((kTypeDiSEqCUncommitted == m_type) && (m_numPorts > 16)))
1606  {
1607  LOG(VB_GENERAL, LOG_ERR, LOC +
1608  QString("Invalid number of ports for DiSEqC 1.x Switch (%1)")
1609  .arg(m_numPorts));
1610  return false;
1611  }
1612 
1613  // build command
1614  uint cmd = DISEQC_CMD_WRITE_N1;
1615  cmd_vec_t data { pos };
1617  {
1618  cmd = DISEQC_CMD_WRITE_N0;
1619  data[0] = ((pos << 2) | (horizontal ? 2 : 0) | (high_band ? 1 : 0));
1620  }
1621  data[0] |= 0xf0;
1622 
1623  LOG(VB_CHANNEL, LOG_INFO, LOC + "Changing to DiSEqC switch port " +
1624  QString("%1/%2").arg(pos + 1).arg(m_numPorts));
1625 
1626  bool ret = m_tree.SendCommand(m_address, cmd, m_repeat, data);
1627  if(ret)
1628  {
1629  m_lastHighBand = static_cast<uint>(high_band);
1630  m_lastHorizontal = static_cast<uint>(horizontal);
1631  }
1632  return ret;
1633 }
1634 
1636 {
1637  int pos = (int) settings.GetValue(GetDeviceID());
1638 
1639  if (pos >= (int)m_numPorts)
1640  {
1641  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Port %1 ").arg(pos + 1) +
1642  QString("is not in range [0..%1)").arg(m_numPorts));
1643 
1644  return -1;
1645  }
1646 
1647  if ((pos >= 0) && !m_children[pos])
1648  {
1649  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Port %1 ").arg(pos + 1) +
1650  "has no connected devices configured.");
1651 
1652  return -1;
1653  }
1654 
1655  return pos;
1656 }
1657 
1659 
1660 static double GetCurTimeFloating(void)
1661 {
1662  struct timeval curtime {};
1663  gettimeofday(&curtime, nullptr);
1664  return (double)curtime.tv_sec + (((double)curtime.tv_usec) / 1000000);
1665 }
1666 
1671 const std::vector<DiSEqCDevDevice::TypeTable> DiSEqCDevRotor::kRotorTypeTable
1672 {
1673  { "diseqc_1_2", kTypeDiSEqC_1_2 },
1674  { "diseqc_1_3", kTypeDiSEqC_1_3 },
1675  { nullptr, kTypeDiSEqC_1_3 }
1676 };
1677 
1679 {
1680  delete m_child;
1681 }
1682 
1684  const DTVMultiplex &tuning)
1685 {
1686  bool success = true;
1687 
1688  double position = settings.GetValue(GetDeviceID());
1689  if (m_reset || (position != m_lastPosition))
1690  {
1691  switch (m_type)
1692  {
1693  case kTypeDiSEqC_1_2:
1694  success = ExecuteRotor(settings, tuning, position);
1695  break;
1696  case kTypeDiSEqC_1_3:
1697  success = ExecuteUSALS(settings, tuning, position);
1698  break;
1699  default:
1700  success = false;
1701  LOG(VB_GENERAL, LOG_ERR, LOC + "Unknown rotor type " +
1702  QString("(%1)").arg((uint) m_type));
1703  break;
1704  }
1705 
1706  m_lastPosition = position;
1707  m_reset = false;
1708  if (success)
1709  // prevent tuning parameters overriding rotor parameters
1710  usleep(DISEQC_LONG_WAIT);
1711  }
1712 
1713  // chain to child
1714  if (success && m_child)
1715  success = m_child->Execute(settings, tuning);
1716 
1717  return success;
1718 }
1719 
1721 {
1722  m_reset = true;
1723  if (m_child)
1724  m_child->Reset();
1725 }
1726 
1728  const DTVMultiplex &tuning) const
1729 {
1730  double position = settings.GetValue(GetDeviceID());
1731 
1732  if (m_reset || (position != m_lastPosition))
1733  return true;
1734 
1735  if (m_child)
1736  return m_child->IsCommandNeeded(settings, tuning);
1737 
1738  return false;
1739 }
1740 
1742 {
1743  return m_child;
1744 }
1745 
1747 {
1748  if (ordinal)
1749  return false;
1750 
1751  DiSEqCDevDevice *old_child = m_child;
1752  m_child = nullptr;
1753  delete old_child;
1754 
1755  m_child = device;
1756  if (m_child)
1757  {
1758  m_child->SetOrdinal(ordinal);
1759  m_child->SetParent(this);
1760  }
1761 
1762  return true;
1763 }
1764 
1765 bool DiSEqCDevRotor::IsMoving(const DiSEqCDevSettings &settings) const
1766 {
1767  double position = settings.GetValue(GetDeviceID());
1768  double completed = GetProgress();
1769  bool moving = (completed < 1.0) || (position != m_lastPosition);
1770 
1771  return (m_lastPosKnown && moving);
1772 }
1773 
1775  const DTVMultiplex &tuning) const
1776 {
1777  // override voltage if the last position is known and the rotor is moving
1778  if (IsMoving(settings))
1779  {
1780  LOG(VB_CHANNEL, LOG_INFO, LOC +
1781  "Overriding voltage to 18V for faster rotor movement");
1782  }
1783  else if (m_child)
1784  {
1785  return m_child->GetVoltage(settings, tuning);
1786  }
1787 
1788  return SEC_VOLTAGE_18;
1789 }
1790 
1792 {
1793  // populate switch parameters from db
1794  MSqlQuery query(MSqlQuery::InitCon());
1795  query.prepare(
1796  "SELECT subtype, rotor_positions, "
1797  " rotor_hi_speed, rotor_lo_speed, "
1798  " cmd_repeat "
1799  "FROM diseqc_tree "
1800  "WHERE diseqcid = :DEVID");
1801  query.bindValue(":DEVID", GetDeviceID());
1802 
1803  if (!query.exec() || !query.isActive())
1804  {
1805  MythDB::DBError("DiSEqCDevRotor::Load 1", query);
1806  return false;
1807  }
1808  if (query.next())
1809  {
1810  m_type = RotorTypeFromString(query.value(0).toString());
1811  m_speedHi = query.value(2).toDouble();
1812  m_speedLo = query.value(3).toDouble();
1813  m_repeat = query.value(4).toUInt();
1814 
1815  // form of "angle1=index1:angle2=index2:..."
1816  QString positions = query.value(1).toString();
1817  QStringList pos = positions.split(":", Qt::SkipEmptyParts);
1818  for (const auto & kv : std::as_const(pos))
1819  {
1820  const QStringList eq = kv.split("=", Qt::SkipEmptyParts);
1821  if (eq.size() == 2)
1822  m_posmap[eq[0].toFloat()] = eq[1].toUInt();
1823  }
1824  }
1825 
1826  // load children from db
1827  if (m_child)
1828  {
1829  delete m_child;
1830  m_child = nullptr;
1831  }
1832 
1833  query.prepare(
1834  "SELECT diseqcid "
1835  "FROM diseqc_tree "
1836  "WHERE parentid = :DEVID");
1837  query.bindValue(":DEVID", GetDeviceID());
1838 
1839  if (!query.exec() || !query.isActive())
1840  {
1841  MythDB::DBError("DiSEqCDevRotor::Load 2", query);
1842  return false;
1843  }
1844  if (query.next())
1845  {
1846  uint child_dev_id = query.value(0).toUInt();
1847  SetChild(0, CreateById(m_tree, child_dev_id));
1848  }
1849 
1850  return true;
1851 }
1852 
1853 bool DiSEqCDevRotor::Store(void) const
1854 {
1855  QString posmap = "";
1856  QString type = RotorTypeToString(m_type);
1857 
1858  if (!m_posmap.empty())
1859  {
1860  QStringList pos;
1861 
1862  dbl_to_uint_t::const_iterator it = m_posmap.begin();
1863  for (; it != m_posmap.end(); ++it)
1864  pos.push_back(QString("%1=%2").arg(it.key()).arg(*it));
1865 
1866  posmap = pos.join(":");
1867  }
1868 
1869  MSqlQuery query(MSqlQuery::InitCon());
1870 
1871  // insert new or update old
1872  if (IsRealDeviceID())
1873  {
1874  query.prepare(
1875  "UPDATE diseqc_tree "
1876  "SET parentid = :PARENT, "
1877  " ordinal = :ORDINAL, "
1878  " type = 'rotor', "
1879  " description = :DESC, "
1880  " subtype = :TYPE, "
1881  " rotor_hi_speed = :HISPEED, "
1882  " rotor_lo_speed = :LOSPEED, "
1883  " rotor_positions = :POSMAP, "
1884  " cmd_repeat = :REPEAT "
1885  "WHERE diseqcid = :DEVID");
1886  query.bindValue(":DEVID", GetDeviceID());
1887  }
1888  else
1889  {
1890  query.prepare(
1891  "INSERT INTO diseqc_tree "
1892  " ( parentid, ordinal, type, "
1893  " description, subtype, rotor_hi_speed, "
1894  " rotor_lo_speed, rotor_positions, cmd_repeat ) "
1895  "VALUES "
1896  " (:PARENT, :ORDINAL, 'rotor', "
1897  " :DESC, :TYPE, :HISPEED, "
1898  " :LOSPEED, :POSMAP, :REPEAT )");
1899  }
1900 
1901  if (m_parent)
1902  query.bindValue(":PARENT", m_parent->GetDeviceID());
1903 
1904  query.bindValue(":ORDINAL", m_ordinal);
1905  query.bindValue(":DESC", GetDescription());
1906  query.bindValue(":TYPE", type);
1907  query.bindValue(":HISPEED", m_speedHi);
1908  query.bindValue(":LOSPEED", m_speedLo);
1909  query.bindValue(":POSMAP", posmap);
1910  query.bindValue(":REPEAT", m_repeat);
1911 
1912  if (!query.exec())
1913  {
1914  MythDB::DBError("DiSEqCDevRotor::Store", query);
1915  return false;
1916  }
1917 
1918  // figure out devid if we did an insert
1919  if (!IsRealDeviceID())
1920  SetDeviceID(query.lastInsertId().toUInt());
1921 
1922  // chain to child
1923  if (m_child)
1924  return m_child->Store();
1925 
1926  return true;
1927 }
1928 
1935 {
1936  if (m_moveTime == 0.0)
1937  return 1.0;
1938 
1939  // calculate duration of move
1940  double speed = ((m_tree.GetVoltage() == SEC_VOLTAGE_18) ?
1941  m_speedHi : m_speedLo);
1942  double change = abs(m_desiredAzimuth - m_lastAzimuth);
1943  double duration = change / speed;
1944 
1945  // determine completion percentage
1946  double time_since_move = GetCurTimeFloating() - m_moveTime;
1947  double completed = time_since_move / duration;
1948  if(completed > 1.0)
1949  {
1950  RotationComplete();
1951  completed = 1.0;
1952  }
1953 
1954  return completed;
1955 }
1956 
1965 {
1966  return m_lastPosKnown;
1967 }
1968 
1970 {
1971  uint_to_dbl_t inv_posmap;
1972  dbl_to_uint_t::const_iterator it;
1973  for (it = m_posmap.begin(); it != m_posmap.end(); ++it)
1974  inv_posmap[*it] = it.key();
1975 
1976  return inv_posmap;
1977 }
1978 
1980 {
1981  m_posmap.clear();
1982 
1983  uint_to_dbl_t::const_iterator it;
1984  for (it = inv_posmap.begin(); it != inv_posmap.end(); ++it)
1985  m_posmap[*it] = it.key();
1986 }
1987 
1989  const DTVMultiplex& /*tuning*/,
1990  double angle)
1991 {
1992  // determine stored position from position map
1993  dbl_to_uint_t::const_iterator it =
1994  m_posmap.lowerBound(angle - EPS); // clazy:exclude=strict-iterators
1995  cmd_vec_t index { static_cast<uint8_t>(angle) };
1996  if (it != m_posmap.cend())
1997  {
1998  index[0] = *it;
2000  }
2001 
2002  LOG(VB_CHANNEL, LOG_INFO, LOC + "Rotor - " +
2003  QString("Goto Stored Position %1").arg(index[0]));
2004 
2006  m_repeat, index);
2007 }
2008 
2010  const DTVMultiplex& /*tuning*/,
2011  double angle)
2012 {
2013  double azimuth = CalculateAzimuth(angle);
2014  StartRotorPositionTracking(azimuth);
2015 
2016  LOG(VB_CHANNEL, LOG_INFO, LOC + "USALS Rotor - " +
2017  QString("Goto %1 (Azimuth %2)").arg(angle).arg(azimuth));
2018 
2019  uint az16 = (uint) (abs(azimuth) * 16.0);
2020  cmd_vec_t cmd {
2021  static_cast<uint8_t>(((azimuth > 0.0) ? 0xE0 : 0xD0) | ((az16 >> 8) & 0x0f)),
2022  static_cast<uint8_t>(az16 & 0xff) };
2023 
2025  m_repeat, cmd);
2026 }
2027 
2029 {
2030  // Azimuth Calculation references:
2031  // http://engr.nmsu.edu/~etti/3_2/3_2e.html
2032  // http://www.angelfire.com/trek/ismail/theory.html
2033 
2034  // Earth Station Latitude and Longitude in radians
2035  double P = gCoreContext->GetSetting("Latitude", "").toDouble() * TO_RADS;
2036  double Ue = gCoreContext->GetSetting("Longitude", "").toDouble() * TO_RADS;
2037 
2038  // Satellite Longitude in radians
2039  double Us = angle * TO_RADS;
2040 
2041  return TO_DEC * atan( tan(Us - Ue) / sin(P) );
2042 }
2043 
2045 {
2046  if (m_moveTime == 0.0)
2047  return m_lastAzimuth;
2048 
2049  double change = m_desiredAzimuth - m_lastAzimuth;
2050  return m_lastAzimuth + (change * GetProgress());
2051 }
2052 
2054 {
2055  // save time and angle of this command
2056  m_desiredAzimuth = azimuth;
2057 
2058  // set last to approximate current position (or worst case if unknown)
2059  if (m_lastPosKnown || m_moveTime > 0.0)
2061  else
2062  m_lastAzimuth = azimuth > 0.0 ? -75.0 : 75.0;
2063 
2065 }
2066 
2068 {
2069  m_moveTime = 0.0;
2070  m_lastPosKnown = true;
2072 }
2073 
2075 
2080 const std::vector<DiSEqCDevDevice::TypeTable> DiSEqCDevSCR::kSCRPositionTable
2081 {
2082  { "A", kTypeScrPosA },
2083  { "B", kTypeScrPosB },
2084  { QString(), kTypeScrPosA },
2085 };
2086 
2088 {
2089  delete m_child;
2090 }
2091 
2093 {
2094  if (m_child)
2095  m_child->Reset();
2096 }
2097 
2098 bool DiSEqCDevSCR::Execute(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning)
2099 {
2100  // retrieve LNB info
2101  DiSEqCDevLNB *lnb = m_tree.FindLNB(settings);
2102  if (!lnb)
2103  {
2104  LOG(VB_GENERAL, LOG_ERR, LOC + "SCR: No LNB for this configuration!");
2105  return false;
2106  }
2107 
2108  bool high_band = lnb->IsHighBand(tuning);
2109  bool horizontal = lnb->IsHorizontal(tuning);
2110  uint32_t frequency = lnb->GetIntermediateFrequency(settings, tuning);
2111  uint t = (frequency / 1000 + m_scrFrequency + 2) / 4 - 350;
2112 
2113  // retrieve position settings (value should be 0 or 1)
2114  auto scr_position = (dvbdev_pos_t)int(settings.GetValue(GetDeviceID()));
2115 
2116  // check parameters
2117  if (m_scrUserband > 7)
2118  {
2119  LOG(VB_GENERAL, LOG_ERR, LOC + QString("SCR: Userband ID=%1 is out of range (0-7)!")
2120  .arg(m_scrUserband));
2121  return false;
2122  }
2123 
2124  if (t >= 1024)
2125  {
2126  LOG(VB_GENERAL, LOG_ERR, LOC + QString("SCR: T=%1 is out of range!").arg(t));
2127  return false;
2128  }
2129 
2130  LOG(VB_GENERAL, LOG_INFO, QString("SCR: Tuning to %1kHz, %2, %3 using UB=%4, FREQ=%5MHz, POS=%6%7")
2131  .arg(tuning.m_frequency)
2132  .arg(high_band ? "HiBand" : "LoBand",
2133  horizontal ? "H" : "V")
2134  .arg(m_scrUserband)
2135  .arg(m_scrFrequency)
2136  .arg((scr_position) ? "B" : "A",
2137  (m_scrPin >= 0 && m_scrPin <= 255) ?
2138  QString(", PIN=%1").arg(m_scrPin) : QString("")));
2139 
2140  // build command
2141  cmd_vec_t data {
2142  static_cast<uint8_t>(t >> 8 | m_scrUserband << 5),
2143  static_cast<uint8_t>(t & 0x00FF) };
2144 
2145  if (high_band)
2146  data[0] |= (1 << 2);
2147 
2148  if (horizontal)
2149  data[0] |= (1 << 3);
2150 
2151  if (scr_position)
2152  data[0] |= (1 << 4);
2153 
2154  // send command
2155  if (m_scrPin >= 0 && m_scrPin <= 255)
2156  data.push_back(m_scrPin);
2157  return SendCommand(DISEQC_CMD_ODU, m_repeat, data);
2158 }
2159 
2160 bool DiSEqCDevSCR::PowerOff(void) const
2161 {
2162  // check parameters
2163  if (m_scrUserband > 7)
2164  {
2165  LOG(VB_GENERAL, LOG_ERR, LOC + QString("SCR: Userband ID=%1 is out of range (0-7)!")
2166  .arg(m_scrUserband));
2167  return false;
2168  }
2169 
2170  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("SCR: Power off UB=%1%7")
2171  .arg(m_scrUserband)
2172  .arg((m_scrPin >= 0 && m_scrPin <= 255)
2173  ? QString(", PIN=%1").arg(m_scrPin)
2174  : QString("")));
2175 
2176  // build command
2177  cmd_vec_t data {
2178  static_cast<uint8_t>(m_scrUserband << 5), 0x00 };
2179 
2180  // send command
2181  if (m_scrPin >= 0 && m_scrPin <= 255)
2182  data.push_back(m_scrPin);
2183  return SendCommand(DISEQC_CMD_ODU, m_repeat, data);
2184 }
2185 
2187  [[maybe_unused]] uint repeats,
2188  cmd_vec_t &data) const
2189 {
2190  // power on bus
2191  if (!m_tree.SetVoltage(SEC_VOLTAGE_18))
2192  return false;
2193  usleep(DISEQC_LONG_WAIT);
2194 
2195  // send command
2196  bool ret = m_tree.SendCommand(DISEQC_ADR_SW_ALL, cmd, repeats, data);
2197 
2198  // power off bus
2199  if (!m_tree.SetVoltage(SEC_VOLTAGE_13))
2200  return false;
2201 
2202  return ret;
2203 }
2204 
2206  const DTVMultiplex &/*tuning*/) const
2207 {
2208  return SEC_VOLTAGE_13;
2209 }
2210 
2211 uint32_t DiSEqCDevSCR::GetIntermediateFrequency(const uint32_t frequency) const
2212 {
2213  uint t = (frequency / 1000 + m_scrFrequency + 2) / 4 - 350;
2214  return ((t + 350) * 4) * 1000 - frequency;
2215 }
2216 
2218 {
2219  // populate scr parameters from db
2220  MSqlQuery query(MSqlQuery::InitCon());
2221  query.prepare(
2222  "SELECT scr_userband, scr_frequency, "
2223  " scr_pin, cmd_repeat "
2224  "FROM diseqc_tree "
2225  "WHERE diseqcid = :DEVID");
2226  query.bindValue(":DEVID", GetDeviceID());
2227 
2228  if (!query.exec() || !query.isActive())
2229  {
2230  MythDB::DBError("DiSEqCDevSCR::Load 1", query);
2231  return false;
2232  }
2233  if (query.next())
2234  {
2235  m_scrUserband = query.value(0).toUInt();
2236  m_scrFrequency = query.value(1).toUInt();
2237  m_scrPin = query.value(2).toInt();
2238  m_repeat = query.value(3).toUInt();
2239  }
2240 
2241  // load children from db
2242  if (m_child)
2243  {
2244  delete m_child;
2245  m_child = nullptr;
2246  }
2247 
2248  query.prepare(
2249  "SELECT diseqcid "
2250  "FROM diseqc_tree "
2251  "WHERE parentid = :DEVID");
2252  query.bindValue(":DEVID", GetDeviceID());
2253 
2254  if (!query.exec() || !query.isActive())
2255  {
2256  MythDB::DBError("DiSEqCDevSCR::Load 2", query);
2257  return false;
2258  }
2259  if (query.next())
2260  {
2261  uint child_dev_id = query.value(0).toUInt();
2262  SetChild(0, CreateById(m_tree, child_dev_id));
2263  }
2264 
2265  return true;
2266 }
2267 
2268 bool DiSEqCDevSCR::Store(void) const
2269 {
2270  MSqlQuery query(MSqlQuery::InitCon());
2271 
2272  // insert new or update old
2273  if (IsRealDeviceID())
2274  {
2275  query.prepare(
2276  "UPDATE diseqc_tree "
2277  "SET parentid = :PARENT, "
2278  " ordinal = :ORDINAL, "
2279  " type = 'scr', "
2280  " description = :DESC, "
2281  " scr_userband = :USERBAND, "
2282  " scr_frequency = :FREQUENCY, "
2283  " scr_pin = :PIN, "
2284  " cmd_repeat = :REPEAT "
2285  "WHERE diseqcid = :DEVID");
2286  query.bindValue(":DEVID", GetDeviceID());
2287  }
2288  else
2289  {
2290  query.prepare(
2291  "INSERT INTO diseqc_tree"
2292  " ( parentid, ordinal, type, "
2293  " description, scr_userband, scr_frequency, "
2294  " scr_pin, cmd_repeat) "
2295  "VALUES "
2296  " (:PARENT, :ORDINAL, 'scr', "
2297  " :DESC, :USERBAND, :FREQUENCY,"
2298  " :PIN, :REPEAT) ");
2299  }
2300 
2301  if (m_parent)
2302  query.bindValue(":PARENT", m_parent->GetDeviceID());
2303 
2304  query.bindValue(":ORDINAL", m_ordinal);
2305  query.bindValue(":DESC", GetDescription());
2306  query.bindValue(":USERBAND", m_scrUserband);
2307  query.bindValue(":FREQUENCY", m_scrFrequency);
2308  query.bindValue(":PIN", m_scrPin);
2309  query.bindValue(":REPEAT", m_repeat);
2310 
2311  // update dev_id
2312  if (!query.exec())
2313  {
2314  MythDB::DBError("DiSEqCDevSCR::Store", query);
2315  return false;
2316  }
2317 
2318  // figure out devid if we did an insert
2319  if (!IsRealDeviceID())
2320  SetDeviceID(query.lastInsertId().toUInt());
2321 
2322  // chain to child
2323  if (m_child)
2324  return m_child->Store();
2325 
2326  return true;
2327 }
2328 
2330 {
2331  if (ordinal)
2332  return false;
2333 
2334  DiSEqCDevDevice *old_child = m_child;
2335  m_child = nullptr;
2336  delete old_child;
2337 
2338  m_child = device;
2339  if (m_child)
2340  {
2341  m_child->SetOrdinal(ordinal);
2342  m_child->SetParent(this);
2343  }
2344 
2345  return true;
2346 }
2347 
2349 
2354 const std::vector<DiSEqCDevDevice::TypeTable> DiSEqCDevLNB::kLNBTypeTable
2355 {
2356  { "fixed", kTypeFixed },
2357  { "voltage", kTypeVoltageControl },
2358  { "voltage_tone", kTypeVoltageAndToneControl },
2359  { "bandstacked", kTypeBandstacked },
2360  { QString(), kTypeVoltageAndToneControl },
2361 };
2362 
2363 bool DiSEqCDevLNB::Execute(const DiSEqCDevSettings& /*settings*/, const DTVMultiplex &tuning)
2364 {
2365  // set tone for bandselect
2367  m_tree.SetTone(IsHighBand(tuning));
2368 
2369  return true;
2370 }
2371 
2373  const DTVMultiplex &tuning) const
2374 {
2375  uint voltage = SEC_VOLTAGE_18;
2376 
2377  if ((kTypeVoltageControl == m_type) ||
2379  {
2380  voltage = (IsHorizontal(tuning) ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13);
2381  }
2382 
2383  return voltage;
2384 }
2385 
2387 {
2388  // populate lnb parameters from db
2389  MSqlQuery query(MSqlQuery::InitCon());
2390  query.prepare(
2391  "SELECT subtype, lnb_lof_switch, "
2392  " lnb_lof_hi, lnb_lof_lo, "
2393  " lnb_pol_inv, cmd_repeat "
2394  "FROM diseqc_tree "
2395  "WHERE diseqcid = :DEVID");
2396  query.bindValue(":DEVID", GetDeviceID());
2397 
2398  if (!query.exec() || !query.isActive())
2399  {
2400  MythDB::DBError("DiSEqCDevLNB::Load", query);
2401  return false;
2402  }
2403  if (query.next())
2404  {
2405  m_type = LNBTypeFromString(query.value(0).toString());
2406  m_lofSwitch = query.value(1).toInt();
2407  m_lofHi = query.value(2).toInt();
2408  m_lofLo = query.value(3).toInt();
2409  m_polInv = query.value(4).toBool();
2410  m_repeat = query.value(5).toUInt();
2411  }
2412 
2413  return true;
2414 }
2415 
2416 bool DiSEqCDevLNB::Store(void) const
2417 {
2418  QString type = LNBTypeToString(m_type);
2419  MSqlQuery query(MSqlQuery::InitCon());
2420 
2421  // insert new or update old
2422  if (IsRealDeviceID())
2423  {
2424  query.prepare(
2425  "UPDATE diseqc_tree "
2426  "SET parentid = :PARENT, "
2427  " ordinal = :ORDINAL, "
2428  " type = 'lnb', "
2429  " description = :DESC, "
2430  " subtype = :TYPE, "
2431  " lnb_lof_switch = :LOFSW, "
2432  " lnb_lof_lo = :LOFLO, "
2433  " lnb_lof_hi = :LOFHI, "
2434  " lnb_pol_inv = :POLINV, "
2435  " cmd_repeat = :REPEAT "
2436  "WHERE diseqcid = :DEVID");
2437  query.bindValue(":DEVID", GetDeviceID());
2438  }
2439  else
2440  {
2441  query.prepare(
2442  "INSERT INTO diseqc_tree"
2443  " ( parentid, ordinal, type, "
2444  " description, subtype, lnb_lof_switch, "
2445  " lnb_lof_lo, lnb_lof_hi, lnb_pol_inv, "
2446  " cmd_repeat ) "
2447  "VALUES "
2448  " (:PARENT, :ORDINAL, 'lnb', "
2449  " :DESC, :TYPE, :LOFSW, "
2450  " :LOFLO, :LOFHI, :POLINV, "
2451  " :REPEAT ) ");
2452  }
2453 
2454  if (m_parent)
2455  query.bindValue(":PARENT", m_parent->GetDeviceID());
2456 
2457  query.bindValue(":ORDINAL", m_ordinal);
2458  query.bindValue(":DESC", GetDescription());
2459  query.bindValue(":TYPE", type);
2460  query.bindValue(":LOFSW", m_lofSwitch);
2461  query.bindValue(":LOFLO", m_lofLo);
2462  query.bindValue(":LOFHI", m_lofHi);
2463  query.bindValue(":POLINV", m_polInv);
2464  query.bindValue(":REPEAT", m_repeat);
2465 
2466  // update dev_id
2467  if (!query.exec())
2468  {
2469  MythDB::DBError("DiSEqCDevLNB::Store", query);
2470  return false;
2471  }
2472 
2473  // figure out devid if we did an insert
2474  if (!IsRealDeviceID())
2475  SetDeviceID(query.lastInsertId().toUInt());
2476 
2477  return true;
2478 }
2479 
2486 bool DiSEqCDevLNB::IsHighBand(const DTVMultiplex &tuning) const
2487 {
2488  switch (m_type)
2489  {
2491  return (tuning.m_frequency > m_lofSwitch);
2492  case kTypeBandstacked:
2493  return IsHorizontal(tuning);
2494  default:
2495  return false;
2496  }
2497 
2498  return false;
2499 }
2500 
2506 bool DiSEqCDevLNB::IsHorizontal(const DTVMultiplex &tuning) const
2507 {
2508  QString pol = tuning.m_polarity.toString().toLower();
2509  return (pol == "h" || pol == "l") ^ IsPolarityInverted();
2510 }
2511 
2519  const DiSEqCDevSettings& /*settings*/, const DTVMultiplex &tuning) const
2520 {
2521  uint64_t abs_freq = tuning.m_frequency;
2522  uint lof = (IsHighBand(tuning)) ? m_lofHi : m_lofLo;
2523 
2524  return (lof > abs_freq) ? (lof - abs_freq) : (abs_freq - lof);
2525 }
DISEQC_CMDS
DISEQC_CMDS
Definition: diseqc.cpp:69
DiSEqCDevSwitch::SwitchTypeToString
static QString SwitchTypeToString(dvbdev_switch_t type)
Definition: diseqc.h:270
DiSEqCDevDevice::m_ordinal
uint m_ordinal
Definition: diseqc.h:210
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:1727
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
DiSEqCDevTree::~DiSEqCDevTree
~DiSEqCDevTree()
Definition: diseqc.cpp:301
DiSEqCDevRotor::kTypeDiSEqC_1_2
@ kTypeDiSEqC_1_2
Definition: diseqc.h:316
DTVMultiplex
Definition: dtvmultiplex.h:24
DISEQC_ADR_SMATV
@ DISEQC_ADR_SMATV
Definition: diseqc.cpp:60
DiSEqCDevDevice::GetChildCount
virtual uint GetChildCount(void) const
Retrieves the proper number of children for this node.
Definition: diseqc.h:177
DISEQC_ADR_POL_LIN
@ DISEQC_ADR_POL_LIN
Definition: diseqc.cpp:62
DiSEqCDevLNB::Store
bool Store(void) const override
Definition: diseqc.cpp:2416
DiSEqCDevTree::IsInNeedOfConf
bool IsInNeedOfConf(void) const
Definition: diseqc.cpp:831
ENO
#define ENO
This can be appended to the LOG args with "+".
Definition: mythlogging.h:73
DiSEqCDevSwitch::SwitchTypeFromString
static dvbdev_switch_t SwitchTypeFromString(const QString &type)
Definition: diseqc.h:272
DiSEqCDevDevice::FindDevice
DiSEqCDevDevice * FindDevice(uint dev_id)
Definition: diseqc.cpp:872
DISEQC_ADR_POS_ALL
@ DISEQC_ADR_POS_ALL
Definition: diseqc.cpp:63
DiSEqCDevDevice::kTypeRotor
@ kTypeRotor
Definition: diseqc.h:156
DiSEqCDevSCR::GetIntermediateFrequency
uint32_t GetIntermediateFrequency(uint32_t frequency) const
Definition: diseqc.cpp:2211
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:1678
LOC
#define LOC
Definition: diseqc.cpp:93
DiSEqCDevLNB::LNBTypeFromString
static dvbdev_lnb_t LNBTypeFromString(const QString &type)
Definition: diseqc.h:488
DiSEqCDevRotor
Rotor class.
Definition: diseqc.h:302
mythdb.h
DiSEqCDevRotor::kTypeDiSEqC_1_3
@ kTypeDiSEqC_1_3
Definition: diseqc.h:316
DiSEqCDevDevice::SetDeviceID
void SetDeviceID(uint devid) const
Definition: diseqc.h:203
DiSEqCDevSCR::GetVoltage
uint GetVoltage(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning) const override
Retrives the desired voltage for this config.
Definition: diseqc.cpp:2205
set_tone
static bool set_tone(int fd, fe_sec_tone_mode tone)
Definition: diseqc.cpp:1426
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:1180
DISEQC_FRM_REPEAT
static constexpr uint8_t DISEQC_FRM_REPEAT
Definition: diseqc.cpp:48
DiSEqCDevTree::m_fdFrontend
int m_fdFrontend
Definition: diseqc.h:130
DiSEqCDevLNB::kLNBTypeTable
static const TypeTableVec kLNBTypeTable
Definition: diseqc.h:501
DiSEqCDevDevice::m_tree
DiSEqCDevTree & m_tree
Definition: diseqc.h:208
DiSEqCDevTree::SendCommand
bool SendCommand(uint adr, uint cmd, uint repeats, cmd_vec_t &data) const
diseqc.h
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:936
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:2186
DiSEqCDevTree::Execute
bool Execute(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning)
Applies settings to the entire tree.
Definition: diseqc.cpp:509
DiSEqCDevDevice::kTypeSCR
@ kTypeSCR
Definition: diseqc.h:157
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
DiSEqCDevSwitch::GetChild
DiSEqCDevDevice * GetChild(uint ordinal) override
Retrieves the nth child of this node.
Definition: diseqc.cpp:1172
DiSEqCDevRotor::SetPosMap
void SetPosMap(const uint_to_dbl_t &posmap)
Definition: diseqc.cpp:1979
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:619
DiSEqCDevSwitch::m_numPorts
uint m_numPorts
Definition: diseqc.h:293
DiSEqCDevTree::SetTone
bool SetTone(bool on) const
Definition: diseqc.cpp:482
DiSEqCDevSwitch::Execute
bool Execute(const DiSEqCDevSettings &, const DTVMultiplex &) override
Applies DiSEqC settings to this node and any children.
Definition: diseqc.cpp:1077
DiSEqCDevRotor::m_child
DiSEqCDevDevice * m_child
Definition: diseqc.h:366
DiSEqCDevTrees
Static-scoped locked tree list class.
Definition: diseqc.h:61
DISEQC_CMD_ODU
@ DISEQC_CMD_ODU
Definition: diseqc.cpp:75
DiSEqCDevRotor::kRotorTypeTable
static const TypeTableVec kRotorTypeTable
Definition: diseqc.h:379
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
DiSEqCDevSwitch::m_lastPos
uint m_lastPos
Definition: diseqc.h:294
DiSEqCDevLNB::kTypeBandstacked
@ kTypeBandstacked
Definition: diseqc.h:463
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
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:1134
DiSEqCDevSwitch::Store
bool Store(void) const override
Definition: diseqc.cpp:1271
DiSEqCDevSwitch::GetPosition
int GetPosition(const DiSEqCDevSettings &settings) const
Definition: diseqc.cpp:1635
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
DiSEqCDevSwitch::kTypeDiSEqCUncommitted
@ kTypeDiSEqCUncommitted
Definition: diseqc.h:241
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:1746
DiSEqCDevTree::Open
void Open(int fd_frontend, bool is_SCR)
Retrieve device tree.
Definition: diseqc.cpp:790
DiSEqCDevDevice::kTypeSwitch
@ kTypeSwitch
Definition: diseqc.h:155
DiSEqCDevSettings::m_inputId
uint m_inputId
current input id
Definition: diseqc.h:48
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:1492
DISEQC_ADR_SW
@ DISEQC_ADR_SW
Definition: diseqc.cpp:59
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:1988
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
DISEQC_ADR_SW_ALL
@ DISEQC_ADR_SW_ALL
Definition: diseqc.cpp:55
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:1934
cmd_vec_t
std::vector< uint8_t > cmd_vec_t
Definition: diseqc.h:34
DiSEqCDevRotor::CalculateAzimuth
static double CalculateAzimuth(double angle)
Definition: diseqc.cpp:2028
DiSEqCDevSwitch::GetChildCount
uint GetChildCount(void) const override
Retrieves the proper number of children for this node.
Definition: diseqc.cpp:1167
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:1853
mythlogging.h
DiSEqCDevSCR::kSCRPositionTable
static const TypeTableVec kSCRPositionTable
Definition: diseqc.h:443
DISEQC_CMD_ODU_MDU
@ DISEQC_CMD_ODU_MDU
Definition: diseqc.cpp:76
GetCurTimeFloating
static double GetCurTimeFloating(void)
Definition: diseqc.cpp:1660
DISEQC_ADR_POS_EL
@ DISEQC_ADR_POS_EL
Definition: diseqc.cpp:65
DiSEqCDevTree::ApplyVoltage
bool ApplyVoltage(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning)
Definition: diseqc.cpp:839
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:1528
DiSEqCDevSCR::Store
bool Store(void) const override
Definition: diseqc.cpp:2268
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
DISEQC_ADR_LNB_SW
@ DISEQC_ADR_LNB_SW
Definition: diseqc.cpp:57
DISEQC_ADR_LNB
@ DISEQC_ADR_LNB
Definition: diseqc.cpp:56
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:1791
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:551
compat.h
DiSEqCDevDevice::TypeTableVec
std::vector< TypeTable > TypeTableVec
Definition: diseqc.h:214
DiSEqCDevSCR::~DiSEqCDevSCR
~DiSEqCDevSCR() override
Definition: diseqc.cpp:2087
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:226
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:1964
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
DISEQC_CMD_GOTO_X
@ DISEQC_CMD_GOTO_X
Definition: diseqc.cpp:85
DISEQC_CMD_GOTO_POS
@ DISEQC_CMD_GOTO_POS
Definition: diseqc.cpp:84
DISEQC_CMD_CLR_RESET
@ DISEQC_CMD_CLR_RESET
Definition: diseqc.cpp:71
DiSEqCDevDevice::SetOrdinal
void SetOrdinal(uint ordinal)
Definition: diseqc.h:162
DiSEqCDevSCR
Unicable / SCR Class.
Definition: diseqc.h:382
DiSEqCDevDevice::dvbdev_t
dvbdev_t
Definition: diseqc.h:153
DiSEqCDevRotor::m_type
dvbdev_rotor_t m_type
Definition: diseqc.h:362
DiSEqCDevSCR::Execute
bool Execute(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning) override
Applies DiSEqC settings to this node and any children.
Definition: diseqc.cpp:2098
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:2067
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
DiSEqCDevSwitch::ExecuteLegacy
bool ExecuteLegacy(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning, uint pos)
Definition: diseqc.cpp:1359
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:1741
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:2386
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:1146
DISEQC_CMD_WRITE_FREQ
@ DISEQC_CMD_WRITE_FREQ
Definition: diseqc.cpp:74
DiSEqCDevSwitch::GetSelectedChild
DiSEqCDevDevice * GetSelectedChild(const DiSEqCDevSettings &settings) const override
Retrieves the selected child for this configuration, if any.
Definition: diseqc.cpp:1157
DiSEqCDevLNB::IsHorizontal
bool IsHorizontal(const DTVMultiplex &tuning) const
Determine if horizontal polarity is active (for switchable LNBs).
Definition: diseqc.cpp:2506
DISEQC_CMD_LMT_E
@ DISEQC_CMD_LMT_E
Definition: diseqc.cpp:79
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:1683
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
uint
unsigned int uint
Definition: compat.h:81
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:1969
DiSEqCDevSwitch::ExecuteVoltage
bool ExecuteVoltage(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning, uint pos)
Definition: diseqc.cpp:1508
DISEQC_CMD_LMT_OFF
@ DISEQC_CMD_LMT_OFF
Definition: diseqc.cpp:78
DiSEqCDevLNB::Execute
bool Execute(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning) override
Applies DiSEqC settings to this node and any children.
Definition: diseqc.cpp:2363
DiSEqCDev::FindTree
static DiSEqCDevTree * FindTree(uint cardid)
Retrieve device tree.
Definition: diseqc.cpp:237
TO_RADS
static constexpr double TO_RADS
Definition: diseqc.cpp:88
DiSEqCDev::s_trees
static DiSEqCDevTrees s_trees
Definition: diseqc.h:58
DISEQC_CMD_DRIVE_W
@ DISEQC_CMD_DRIVE_W
Definition: diseqc.cpp:82
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:932
DiSEqCDevSCR::SetChild
bool SetChild(uint ordinal, DiSEqCDevDevice *device) override
Changes the nth child of this node.
Definition: diseqc.cpp:2329
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:2160
DiSEqCDevTree::m_lastVoltage
uint m_lastVoltage
Definition: diseqc.h:132
DiSEqCDevDevice::kTypeLNB
@ kTypeLNB
Definition: diseqc.h:158
DiSEqCDevSwitch::Load
bool Load(void) override
Loads this device from the database.
Definition: diseqc.cpp:1210
DiSEqCDevTree::FindLNB
DiSEqCDevLNB * FindLNB(const DiSEqCDevSettings &settings)
Returns the LNB device object selected by the configuration chain.
Definition: diseqc.cpp:573
DISEQC_CMD_LMT_W
@ DISEQC_CMD_LMT_W
Definition: diseqc.cpp:80
DISEQC_ADR_ALL
@ DISEQC_ADR_ALL
Definition: diseqc.cpp:54
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
DiSEqCDevSwitch::kTypeDiSEqCCommitted
@ kTypeDiSEqCCommitted
Definition: diseqc.h:240
DiSEqCDevRotor::StartRotorPositionTracking
void StartRotorPositionTracking(double azimuth)
Definition: diseqc.cpp:2053
DiSEqCDevRotor::ExecuteUSALS
bool ExecuteUSALS(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning, double angle)
Definition: diseqc.cpp:2009
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:1448
DISEQC_CMD_WRITE_N0
@ DISEQC_CMD_WRITE_N0
Definition: diseqc.cpp:72
DTVPolarity::toString
QString toString() const
Definition: dtvconfparserhelpers.h:632
DiSEqCDevSwitch::kTypeMiniDiSEqC
@ kTypeMiniDiSEqC
Definition: diseqc.h:246
diseqc_bus_already_reset
bool diseqc_bus_already_reset
Definition: diseqc.cpp:95
DiSEqCDevSwitch::SetNumPorts
void SetNumPorts(uint num_ports)
Definition: diseqc.cpp:1336
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
DiSEqCDevDevice::~DiSEqCDevDevice
virtual ~DiSEqCDevDevice()
Definition: diseqc.cpp:866
DiSEqCDevDevice::kDvbdevLookup
static const TypeTableVec kDvbdevLookup
Definition: diseqc.h:220
DiSEqCDevRotor::m_lastAzimuth
double m_lastAzimuth
Definition: diseqc.h:376
DiSEqCDevSwitch::kTypeTone
@ kTypeTone
Definition: diseqc.h:239
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
DiSEqCDevSwitch::kTypeLegacySW64
@ kTypeLegacySW64
Definition: diseqc.h:244
DiSEqCDevRotor::GetVoltage
uint GetVoltage(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning) const override
Retrives the desired voltage for this config.
Definition: diseqc.cpp:1774
DiSEqCDevSwitch::kTypeLegacySW42
@ kTypeLegacySW42
Definition: diseqc.h:243
DISEQC_SHORT_WAIT
static constexpr useconds_t DISEQC_SHORT_WAIT
Definition: diseqc.cpp:36
DiSEqCDevDevice::CreateById
static DiSEqCDevDevice * CreateById(DiSEqCDevTree &tree, uint devid)
Definition: diseqc.cpp:896
DiSEqCDevSwitch::kTypeLegacySW21
@ kTypeLegacySW21
Definition: diseqc.h:242
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:889
DISEQC_ADR_POS_AZ
@ DISEQC_ADR_POS_AZ
Definition: diseqc.cpp:64
DiSEqCDevSwitch::kTypeVoltage
@ kTypeVoltage
Definition: diseqc.h:245
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:1071
DiSEqCDevTree::FindSCR
DiSEqCDevSCR * FindSCR(const DiSEqCDevSettings &settings)
Returns the SCR device object selected by the configuration chain.
Definition: diseqc.cpp:596
DISEQC_CMD_RESET
@ DISEQC_CMD_RESET
Definition: diseqc.cpp:70
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:1588
DiSEqCDevRotor::Reset
void Reset(void) override
Resets to the last known settings for this device.
Definition: diseqc.cpp:1720
DiSEqCDevRotor::GetApproxAzimuth
double GetApproxAzimuth(void) const
Definition: diseqc.cpp:2044
mini_diseqc
static bool mini_diseqc(int fd, fe_sec_mini_cmd cmd)
Definition: diseqc.cpp:1470
DiSEqCDevRotor::IsMoving
bool IsMoving(const DiSEqCDevSettings &settings) const
Definition: diseqc.cpp:1765
DiSEqCDevSCR::Load
bool Load(void) override
Loads this device from the database.
Definition: diseqc.cpp:2217
DiSEqCDevTree
DVB-S device tree class. Represents a tree of DVB-S devices.
Definition: diseqc.h:74
DISEQC_ADR_POL_ALL
@ DISEQC_ADR_POL_ALL
Definition: diseqc.cpp:61
DiSEqCDevDevice::Store
virtual bool Store(void) const =0
DISEQC_CMD_STORE_POS
@ DISEQC_CMD_STORE_POS
Definition: diseqc.cpp:83
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:2486
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:838
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_CMD_WRITE_N1
@ DISEQC_CMD_WRITE_N1
Definition: diseqc.cpp:73
DiSEqCDevTrees::FindTree
DiSEqCDevTree * FindTree(uint cardid)
Retrieve device tree.
Definition: diseqc.cpp:265
DiSEqCDevDevice::GetDeviceID
uint GetDeviceID(void) const
Definition: diseqc.h:170
DiSEqCDevLNB::kTypeVoltageAndToneControl
@ kTypeVoltageAndToneControl
Definition: diseqc.h:462
DiSEqCDevSwitch::DiSEqCDevSwitch
DiSEqCDevSwitch(DiSEqCDevTree &tree, uint devid)
Definition: diseqc.cpp:1060
DISEQC_CMD_DRIVE_E
@ DISEQC_CMD_DRIVE_E
Definition: diseqc.cpp:81
DiSEqCDevSCR::Reset
void Reset(void) override
Resets to the last known settings for this device.
Definition: diseqc.cpp:2092
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
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
DiSEqCDevSCR::dvbdev_pos_t
dvbdev_pos_t
Definition: diseqc.h:397
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:1198
DISEQC_ADR_SW_BLK
@ DISEQC_ADR_SW_BLK
Definition: diseqc.cpp:58
DISEQC_ADRS
DISEQC_ADRS
Definition: diseqc.cpp:53
DiSEqCDevLNB::GetVoltage
uint GetVoltage(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning) const override
Retrives the desired voltage for this config.
Definition: diseqc.cpp:2372
DiSEqCDevTree::Reset
void Reset(void)
Reset state of nodes in tree, forcing updates on the next Execute command.
Definition: diseqc.cpp:536
DiSEqCDevSwitch::m_address
uint m_address
Definition: diseqc.h:292
DiSEqCDevLNB::kTypeVoltageControl
@ kTypeVoltageControl
Definition: diseqc.h:461
M_PI
static constexpr double M_PI
Definition: goom_tools.h:9
DiSEqCDevSwitch::m_lastHighBand
uint m_lastHighBand
Definition: diseqc.h:295
DISEQC_CMD_HALT
@ DISEQC_CMD_HALT
Definition: diseqc.cpp:77
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:898
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
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:838
DiSEqCDevTree::AddDeferredDelete
void AddDeferredDelete(uint dev_id)
Definition: diseqc.h:120
DiSEqCDevSwitch
Switch class, including tone, legacy and DiSEqC switches.
Definition: diseqc.h:223
DiSEqCDevSwitch::ShouldSwitch
bool ShouldSwitch(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning) const
Definition: diseqc.cpp:1545