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 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
1818  QStringList pos = positions.split(":", QString::SkipEmptyParts);
1819 #else
1820  QStringList pos = positions.split(":", Qt::SkipEmptyParts);
1821 #endif
1822  for (const auto & kv : qAsConst(pos))
1823  {
1824 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
1825  const QStringList eq = kv.split("=", QString::SkipEmptyParts);
1826 #else
1827  const QStringList eq = kv.split("=", Qt::SkipEmptyParts);
1828 #endif
1829  if (eq.size() == 2)
1830  m_posmap[eq[0].toFloat()] = eq[1].toUInt();
1831  }
1832  }
1833 
1834  // load children from db
1835  if (m_child)
1836  {
1837  delete m_child;
1838  m_child = nullptr;
1839  }
1840 
1841  query.prepare(
1842  "SELECT diseqcid "
1843  "FROM diseqc_tree "
1844  "WHERE parentid = :DEVID");
1845  query.bindValue(":DEVID", GetDeviceID());
1846 
1847  if (!query.exec() || !query.isActive())
1848  {
1849  MythDB::DBError("DiSEqCDevRotor::Load 2", query);
1850  return false;
1851  }
1852  if (query.next())
1853  {
1854  uint child_dev_id = query.value(0).toUInt();
1855  SetChild(0, CreateById(m_tree, child_dev_id));
1856  }
1857 
1858  return true;
1859 }
1860 
1861 bool DiSEqCDevRotor::Store(void) const
1862 {
1863  QString posmap = "";
1864  QString type = RotorTypeToString(m_type);
1865 
1866  if (!m_posmap.empty())
1867  {
1868  QStringList pos;
1869 
1870  dbl_to_uint_t::const_iterator it = m_posmap.begin();
1871  for (; it != m_posmap.end(); ++it)
1872  pos.push_back(QString("%1=%2").arg(it.key()).arg(*it));
1873 
1874  posmap = pos.join(":");
1875  }
1876 
1877  MSqlQuery query(MSqlQuery::InitCon());
1878 
1879  // insert new or update old
1880  if (IsRealDeviceID())
1881  {
1882  query.prepare(
1883  "UPDATE diseqc_tree "
1884  "SET parentid = :PARENT, "
1885  " ordinal = :ORDINAL, "
1886  " type = 'rotor', "
1887  " description = :DESC, "
1888  " subtype = :TYPE, "
1889  " rotor_hi_speed = :HISPEED, "
1890  " rotor_lo_speed = :LOSPEED, "
1891  " rotor_positions = :POSMAP, "
1892  " cmd_repeat = :REPEAT "
1893  "WHERE diseqcid = :DEVID");
1894  query.bindValue(":DEVID", GetDeviceID());
1895  }
1896  else
1897  {
1898  query.prepare(
1899  "INSERT INTO diseqc_tree "
1900  " ( parentid, ordinal, type, "
1901  " description, subtype, rotor_hi_speed, "
1902  " rotor_lo_speed, rotor_positions, cmd_repeat ) "
1903  "VALUES "
1904  " (:PARENT, :ORDINAL, 'rotor', "
1905  " :DESC, :TYPE, :HISPEED, "
1906  " :LOSPEED, :POSMAP, :REPEAT )");
1907  }
1908 
1909  if (m_parent)
1910  query.bindValue(":PARENT", m_parent->GetDeviceID());
1911 
1912  query.bindValue(":ORDINAL", m_ordinal);
1913  query.bindValue(":DESC", GetDescription());
1914  query.bindValue(":TYPE", type);
1915  query.bindValue(":HISPEED", m_speedHi);
1916  query.bindValue(":LOSPEED", m_speedLo);
1917  query.bindValue(":POSMAP", posmap);
1918  query.bindValue(":REPEAT", m_repeat);
1919 
1920  if (!query.exec())
1921  {
1922  MythDB::DBError("DiSEqCDevRotor::Store", query);
1923  return false;
1924  }
1925 
1926  // figure out devid if we did an insert
1927  if (!IsRealDeviceID())
1928  SetDeviceID(query.lastInsertId().toUInt());
1929 
1930  // chain to child
1931  if (m_child)
1932  return m_child->Store();
1933 
1934  return true;
1935 }
1936 
1943 {
1944  if (m_moveTime == 0.0)
1945  return 1.0;
1946 
1947  // calculate duration of move
1948  double speed = ((m_tree.GetVoltage() == SEC_VOLTAGE_18) ?
1949  m_speedHi : m_speedLo);
1950  double change = abs(m_desiredAzimuth - m_lastAzimuth);
1951  double duration = change / speed;
1952 
1953  // determine completion percentage
1954  double time_since_move = GetCurTimeFloating() - m_moveTime;
1955  double completed = time_since_move / duration;
1956  if(completed > 1.0)
1957  {
1958  RotationComplete();
1959  completed = 1.0;
1960  }
1961 
1962  return completed;
1963 }
1964 
1973 {
1974  return m_lastPosKnown;
1975 }
1976 
1978 {
1979  uint_to_dbl_t inv_posmap;
1980  dbl_to_uint_t::const_iterator it;
1981  for (it = m_posmap.begin(); it != m_posmap.end(); ++it)
1982  inv_posmap[*it] = it.key();
1983 
1984  return inv_posmap;
1985 }
1986 
1988 {
1989  m_posmap.clear();
1990 
1991  uint_to_dbl_t::const_iterator it;
1992  for (it = inv_posmap.begin(); it != inv_posmap.end(); ++it)
1993  m_posmap[*it] = it.key();
1994 }
1995 
1997  const DTVMultiplex& /*tuning*/,
1998  double angle)
1999 {
2000  // determine stored position from position map
2001  dbl_to_uint_t::const_iterator it =
2002  m_posmap.lowerBound(angle - EPS); // clazy:exclude=strict-iterators
2003  cmd_vec_t index { static_cast<uint8_t>(angle) };
2004  if (it != m_posmap.cend())
2005  {
2006  index[0] = *it;
2008  }
2009 
2010  LOG(VB_CHANNEL, LOG_INFO, LOC + "Rotor - " +
2011  QString("Goto Stored Position %1").arg(index[0]));
2012 
2014  m_repeat, index);
2015 }
2016 
2018  const DTVMultiplex& /*tuning*/,
2019  double angle)
2020 {
2021  double azimuth = CalculateAzimuth(angle);
2022  StartRotorPositionTracking(azimuth);
2023 
2024  LOG(VB_CHANNEL, LOG_INFO, LOC + "USALS Rotor - " +
2025  QString("Goto %1 (Azimuth %2)").arg(angle).arg(azimuth));
2026 
2027  uint az16 = (uint) (abs(azimuth) * 16.0);
2028  cmd_vec_t cmd {
2029  static_cast<uint8_t>(((azimuth > 0.0) ? 0xE0 : 0xD0) | ((az16 >> 8) & 0x0f)),
2030  static_cast<uint8_t>(az16 & 0xff) };
2031 
2033  m_repeat, cmd);
2034 }
2035 
2037 {
2038  // Azimuth Calculation references:
2039  // http://engr.nmsu.edu/~etti/3_2/3_2e.html
2040  // http://www.angelfire.com/trek/ismail/theory.html
2041 
2042  // Earth Station Latitude and Longitude in radians
2043  double P = gCoreContext->GetSetting("Latitude", "").toDouble() * TO_RADS;
2044  double Ue = gCoreContext->GetSetting("Longitude", "").toDouble() * TO_RADS;
2045 
2046  // Satellite Longitude in radians
2047  double Us = angle * TO_RADS;
2048 
2049  return TO_DEC * atan( tan(Us - Ue) / sin(P) );
2050 }
2051 
2053 {
2054  if (m_moveTime == 0.0)
2055  return m_lastAzimuth;
2056 
2057  double change = m_desiredAzimuth - m_lastAzimuth;
2058  return m_lastAzimuth + (change * GetProgress());
2059 }
2060 
2062 {
2063  // save time and angle of this command
2064  m_desiredAzimuth = azimuth;
2065 
2066  // set last to approximate current position (or worst case if unknown)
2067  if (m_lastPosKnown || m_moveTime > 0.0)
2069  else
2070  m_lastAzimuth = azimuth > 0.0 ? -75.0 : 75.0;
2071 
2073 }
2074 
2076 {
2077  m_moveTime = 0.0;
2078  m_lastPosKnown = true;
2080 }
2081 
2083 
2088 const std::vector<DiSEqCDevDevice::TypeTable> DiSEqCDevSCR::kSCRPositionTable
2089 {
2090  { "A", kTypeScrPosA },
2091  { "B", kTypeScrPosB },
2092  { QString(), kTypeScrPosA },
2093 };
2094 
2096 {
2097  delete m_child;
2098 }
2099 
2101 {
2102  if (m_child)
2103  m_child->Reset();
2104 }
2105 
2106 bool DiSEqCDevSCR::Execute(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning)
2107 {
2108  // retrieve LNB info
2109  DiSEqCDevLNB *lnb = m_tree.FindLNB(settings);
2110  if (!lnb)
2111  {
2112  LOG(VB_GENERAL, LOG_ERR, LOC + "SCR: No LNB for this configuration!");
2113  return false;
2114  }
2115 
2116  bool high_band = lnb->IsHighBand(tuning);
2117  bool horizontal = lnb->IsHorizontal(tuning);
2118  uint32_t frequency = lnb->GetIntermediateFrequency(settings, tuning);
2119  uint t = (frequency / 1000 + m_scrFrequency + 2) / 4 - 350;
2120 
2121  // retrieve position settings (value should be 0 or 1)
2122  auto scr_position = (dvbdev_pos_t)int(settings.GetValue(GetDeviceID()));
2123 
2124  // check parameters
2125  if (m_scrUserband > 7)
2126  {
2127  LOG(VB_GENERAL, LOG_ERR, LOC + QString("SCR: Userband ID=%1 is out of range (0-7)!")
2128  .arg(m_scrUserband));
2129  return false;
2130  }
2131 
2132  if (t >= 1024)
2133  {
2134  LOG(VB_GENERAL, LOG_ERR, LOC + QString("SCR: T=%1 is out of range!").arg(t));
2135  return false;
2136  }
2137 
2138  LOG(VB_GENERAL, LOG_INFO, QString("SCR: Tuning to %1kHz, %2, %3 using UB=%4, FREQ=%5MHz, POS=%6%7")
2139  .arg(tuning.m_frequency)
2140  .arg(high_band ? "HiBand" : "LoBand",
2141  horizontal ? "H" : "V")
2142  .arg(m_scrUserband)
2143  .arg(m_scrFrequency)
2144  .arg((scr_position) ? "B" : "A",
2145  (m_scrPin >= 0 && m_scrPin <= 255) ?
2146  QString(", PIN=%1").arg(m_scrPin) : QString("")));
2147 
2148  // build command
2149  cmd_vec_t data {
2150  static_cast<uint8_t>(t >> 8 | m_scrUserband << 5),
2151  static_cast<uint8_t>(t & 0x00FF) };
2152 
2153  if (high_band)
2154  data[0] |= (1 << 2);
2155 
2156  if (horizontal)
2157  data[0] |= (1 << 3);
2158 
2159  if (scr_position)
2160  data[0] |= (1 << 4);
2161 
2162  // send command
2163  if (m_scrPin >= 0 && m_scrPin <= 255)
2164  data.push_back(m_scrPin);
2165  return SendCommand(DISEQC_CMD_ODU, m_repeat, data);
2166 }
2167 
2168 bool DiSEqCDevSCR::PowerOff(void) const
2169 {
2170  // check parameters
2171  if (m_scrUserband > 7)
2172  {
2173  LOG(VB_GENERAL, LOG_ERR, LOC + QString("SCR: Userband ID=%1 is out of range (0-7)!")
2174  .arg(m_scrUserband));
2175  return false;
2176  }
2177 
2178  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("SCR: Power off UB=%1%7")
2179  .arg(m_scrUserband)
2180  .arg((m_scrPin >= 0 && m_scrPin <= 255)
2181  ? QString(", PIN=%1").arg(m_scrPin)
2182  : QString("")));
2183 
2184  // build command
2185  cmd_vec_t data {
2186  static_cast<uint8_t>(m_scrUserband << 5), 0x00 };
2187 
2188  // send command
2189  if (m_scrPin >= 0 && m_scrPin <= 255)
2190  data.push_back(m_scrPin);
2191  return SendCommand(DISEQC_CMD_ODU, m_repeat, data);
2192 }
2193 
2195  [[maybe_unused]] uint repeats,
2196  cmd_vec_t &data) const
2197 {
2198  // power on bus
2199  if (!m_tree.SetVoltage(SEC_VOLTAGE_18))
2200  return false;
2201  usleep(DISEQC_LONG_WAIT);
2202 
2203  // send command
2204  bool ret = m_tree.SendCommand(DISEQC_ADR_SW_ALL, cmd, repeats, data);
2205 
2206  // power off bus
2207  if (!m_tree.SetVoltage(SEC_VOLTAGE_13))
2208  return false;
2209 
2210  return ret;
2211 }
2212 
2214  const DTVMultiplex &/*tuning*/) const
2215 {
2216  return SEC_VOLTAGE_13;
2217 }
2218 
2219 uint32_t DiSEqCDevSCR::GetIntermediateFrequency(const uint32_t frequency) const
2220 {
2221  uint t = (frequency / 1000 + m_scrFrequency + 2) / 4 - 350;
2222  return ((t + 350) * 4) * 1000 - frequency;
2223 }
2224 
2226 {
2227  // populate scr parameters from db
2228  MSqlQuery query(MSqlQuery::InitCon());
2229  query.prepare(
2230  "SELECT scr_userband, scr_frequency, "
2231  " scr_pin, cmd_repeat "
2232  "FROM diseqc_tree "
2233  "WHERE diseqcid = :DEVID");
2234  query.bindValue(":DEVID", GetDeviceID());
2235 
2236  if (!query.exec() || !query.isActive())
2237  {
2238  MythDB::DBError("DiSEqCDevSCR::Load 1", query);
2239  return false;
2240  }
2241  if (query.next())
2242  {
2243  m_scrUserband = query.value(0).toUInt();
2244  m_scrFrequency = query.value(1).toUInt();
2245  m_scrPin = query.value(2).toInt();
2246  m_repeat = query.value(3).toUInt();
2247  }
2248 
2249  // load children from db
2250  if (m_child)
2251  {
2252  delete m_child;
2253  m_child = nullptr;
2254  }
2255 
2256  query.prepare(
2257  "SELECT diseqcid "
2258  "FROM diseqc_tree "
2259  "WHERE parentid = :DEVID");
2260  query.bindValue(":DEVID", GetDeviceID());
2261 
2262  if (!query.exec() || !query.isActive())
2263  {
2264  MythDB::DBError("DiSEqCDevSCR::Load 2", query);
2265  return false;
2266  }
2267  if (query.next())
2268  {
2269  uint child_dev_id = query.value(0).toUInt();
2270  SetChild(0, CreateById(m_tree, child_dev_id));
2271  }
2272 
2273  return true;
2274 }
2275 
2276 bool DiSEqCDevSCR::Store(void) const
2277 {
2278  MSqlQuery query(MSqlQuery::InitCon());
2279 
2280  // insert new or update old
2281  if (IsRealDeviceID())
2282  {
2283  query.prepare(
2284  "UPDATE diseqc_tree "
2285  "SET parentid = :PARENT, "
2286  " ordinal = :ORDINAL, "
2287  " type = 'scr', "
2288  " description = :DESC, "
2289  " scr_userband = :USERBAND, "
2290  " scr_frequency = :FREQUENCY, "
2291  " scr_pin = :PIN, "
2292  " cmd_repeat = :REPEAT "
2293  "WHERE diseqcid = :DEVID");
2294  query.bindValue(":DEVID", GetDeviceID());
2295  }
2296  else
2297  {
2298  query.prepare(
2299  "INSERT INTO diseqc_tree"
2300  " ( parentid, ordinal, type, "
2301  " description, scr_userband, scr_frequency, "
2302  " scr_pin, cmd_repeat) "
2303  "VALUES "
2304  " (:PARENT, :ORDINAL, 'scr', "
2305  " :DESC, :USERBAND, :FREQUENCY,"
2306  " :PIN, :REPEAT) ");
2307  }
2308 
2309  if (m_parent)
2310  query.bindValue(":PARENT", m_parent->GetDeviceID());
2311 
2312  query.bindValue(":ORDINAL", m_ordinal);
2313  query.bindValue(":DESC", GetDescription());
2314  query.bindValue(":USERBAND", m_scrUserband);
2315  query.bindValue(":FREQUENCY", m_scrFrequency);
2316  query.bindValue(":PIN", m_scrPin);
2317  query.bindValue(":REPEAT", m_repeat);
2318 
2319  // update dev_id
2320  if (!query.exec())
2321  {
2322  MythDB::DBError("DiSEqCDevSCR::Store", query);
2323  return false;
2324  }
2325 
2326  // figure out devid if we did an insert
2327  if (!IsRealDeviceID())
2328  SetDeviceID(query.lastInsertId().toUInt());
2329 
2330  // chain to child
2331  if (m_child)
2332  return m_child->Store();
2333 
2334  return true;
2335 }
2336 
2338 {
2339  if (ordinal)
2340  return false;
2341 
2342  DiSEqCDevDevice *old_child = m_child;
2343  m_child = nullptr;
2344  delete old_child;
2345 
2346  m_child = device;
2347  if (m_child)
2348  {
2349  m_child->SetOrdinal(ordinal);
2350  m_child->SetParent(this);
2351  }
2352 
2353  return true;
2354 }
2355 
2357 
2362 const std::vector<DiSEqCDevDevice::TypeTable> DiSEqCDevLNB::kLNBTypeTable
2363 {
2364  { "fixed", kTypeFixed },
2365  { "voltage", kTypeVoltageControl },
2366  { "voltage_tone", kTypeVoltageAndToneControl },
2367  { "bandstacked", kTypeBandstacked },
2368  { QString(), kTypeVoltageAndToneControl },
2369 };
2370 
2371 bool DiSEqCDevLNB::Execute(const DiSEqCDevSettings& /*settings*/, const DTVMultiplex &tuning)
2372 {
2373  // set tone for bandselect
2375  m_tree.SetTone(IsHighBand(tuning));
2376 
2377  return true;
2378 }
2379 
2381  const DTVMultiplex &tuning) const
2382 {
2383  uint voltage = SEC_VOLTAGE_18;
2384 
2385  if ((kTypeVoltageControl == m_type) ||
2387  {
2388  voltage = (IsHorizontal(tuning) ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13);
2389  }
2390 
2391  return voltage;
2392 }
2393 
2395 {
2396  // populate lnb parameters from db
2397  MSqlQuery query(MSqlQuery::InitCon());
2398  query.prepare(
2399  "SELECT subtype, lnb_lof_switch, "
2400  " lnb_lof_hi, lnb_lof_lo, "
2401  " lnb_pol_inv, cmd_repeat "
2402  "FROM diseqc_tree "
2403  "WHERE diseqcid = :DEVID");
2404  query.bindValue(":DEVID", GetDeviceID());
2405 
2406  if (!query.exec() || !query.isActive())
2407  {
2408  MythDB::DBError("DiSEqCDevLNB::Load", query);
2409  return false;
2410  }
2411  if (query.next())
2412  {
2413  m_type = LNBTypeFromString(query.value(0).toString());
2414  m_lofSwitch = query.value(1).toInt();
2415  m_lofHi = query.value(2).toInt();
2416  m_lofLo = query.value(3).toInt();
2417  m_polInv = query.value(4).toBool();
2418  m_repeat = query.value(5).toUInt();
2419  }
2420 
2421  return true;
2422 }
2423 
2424 bool DiSEqCDevLNB::Store(void) const
2425 {
2426  QString type = LNBTypeToString(m_type);
2427  MSqlQuery query(MSqlQuery::InitCon());
2428 
2429  // insert new or update old
2430  if (IsRealDeviceID())
2431  {
2432  query.prepare(
2433  "UPDATE diseqc_tree "
2434  "SET parentid = :PARENT, "
2435  " ordinal = :ORDINAL, "
2436  " type = 'lnb', "
2437  " description = :DESC, "
2438  " subtype = :TYPE, "
2439  " lnb_lof_switch = :LOFSW, "
2440  " lnb_lof_lo = :LOFLO, "
2441  " lnb_lof_hi = :LOFHI, "
2442  " lnb_pol_inv = :POLINV, "
2443  " cmd_repeat = :REPEAT "
2444  "WHERE diseqcid = :DEVID");
2445  query.bindValue(":DEVID", GetDeviceID());
2446  }
2447  else
2448  {
2449  query.prepare(
2450  "INSERT INTO diseqc_tree"
2451  " ( parentid, ordinal, type, "
2452  " description, subtype, lnb_lof_switch, "
2453  " lnb_lof_lo, lnb_lof_hi, lnb_pol_inv, "
2454  " cmd_repeat ) "
2455  "VALUES "
2456  " (:PARENT, :ORDINAL, 'lnb', "
2457  " :DESC, :TYPE, :LOFSW, "
2458  " :LOFLO, :LOFHI, :POLINV, "
2459  " :REPEAT ) ");
2460  }
2461 
2462  if (m_parent)
2463  query.bindValue(":PARENT", m_parent->GetDeviceID());
2464 
2465  query.bindValue(":ORDINAL", m_ordinal);
2466  query.bindValue(":DESC", GetDescription());
2467  query.bindValue(":TYPE", type);
2468  query.bindValue(":LOFSW", m_lofSwitch);
2469  query.bindValue(":LOFLO", m_lofLo);
2470  query.bindValue(":LOFHI", m_lofHi);
2471  query.bindValue(":POLINV", m_polInv);
2472  query.bindValue(":REPEAT", m_repeat);
2473 
2474  // update dev_id
2475  if (!query.exec())
2476  {
2477  MythDB::DBError("DiSEqCDevLNB::Store", query);
2478  return false;
2479  }
2480 
2481  // figure out devid if we did an insert
2482  if (!IsRealDeviceID())
2483  SetDeviceID(query.lastInsertId().toUInt());
2484 
2485  return true;
2486 }
2487 
2494 bool DiSEqCDevLNB::IsHighBand(const DTVMultiplex &tuning) const
2495 {
2496  switch (m_type)
2497  {
2499  return (tuning.m_frequency > m_lofSwitch);
2500  case kTypeBandstacked:
2501  return IsHorizontal(tuning);
2502  default:
2503  return false;
2504  }
2505 
2506  return false;
2507 }
2508 
2514 bool DiSEqCDevLNB::IsHorizontal(const DTVMultiplex &tuning) const
2515 {
2516  QString pol = tuning.m_polarity.toString().toLower();
2517  return (pol == "h" || pol == "l") ^ IsPolarityInverted();
2518 }
2519 
2527  const DiSEqCDevSettings& /*settings*/, const DTVMultiplex &tuning) const
2528 {
2529  uint64_t abs_freq = tuning.m_frequency;
2530  uint lof = (IsHighBand(tuning)) ? m_lofHi : m_lofLo;
2531 
2532  return (lof > abs_freq) ? (lof - abs_freq) : (abs_freq - lof);
2533 }
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:216
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:811
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:128
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:2424
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:2219
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:2213
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:934
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:2194
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:205
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:1987
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:617
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:1996
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:1942
cmd_vec_t
std::vector< uint8_t > cmd_vec_t
Definition: diseqc.h:34
DiSEqCDevRotor::CalculateAzimuth
static double CalculateAzimuth(double angle)
Definition: diseqc.cpp:2036
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:1861
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:2276
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:549
compat.h
DiSEqCDevDevice::TypeTableVec
std::vector< TypeTable > TypeTableVec
Definition: diseqc.h:214
DiSEqCDevSCR::~DiSEqCDevSCR
~DiSEqCDevSCR() override
Definition: diseqc.cpp:2095
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:1972
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:2106
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:2075
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:2394
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:2514
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:1977
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:2371
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:2337
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:2168
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:2061
DiSEqCDevRotor::ExecuteUSALS
bool ExecuteUSALS(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning, double angle)
Definition: diseqc.cpp:2017
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:887
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:2052
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:2225
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:2494
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:837
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:2100
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:2380
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:897
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:2526
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:836
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