]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
linuxdvb diseqc: fix and improve command caching, fixes #2547
authorJaroslav Kysela <perex@perex.cz>
Sun, 14 Dec 2014 12:28:44 +0000 (13:28 +0100)
committerJaroslav Kysela <perex@perex.cz>
Sun, 14 Dec 2014 12:28:44 +0000 (13:28 +0100)
src/input/mpegts/linuxdvb/linuxdvb_lnb.c
src/input/mpegts/linuxdvb/linuxdvb_private.h
src/input/mpegts/linuxdvb/linuxdvb_switch.c

index 8fb7bf14bfbdf5f685a839976d2fb7457c30bcb8..d6a63721231d49c3266e1316cf33534b968304a1 100644 (file)
@@ -118,7 +118,13 @@ linuxdvb_lnb_standard_tune
 
   /* note: differentiate between linuxdvb_lnb_standard_pol / linuxdvb_lnb_inverted_pol */
   int pol = ((linuxdvb_lnb_t*)ld)->lnb_pol((linuxdvb_lnb_t*)ld, lm);
-  return linuxdvb_diseqc_set_volt(fd, pol);
+
+  if (ls->lse_parent->ls_diseqc_full || ls->lse_parent->ls_last_pol != pol + 1) {
+    ls->lse_parent->ls_last_pol = pol + 1;
+    return linuxdvb_diseqc_set_volt(fd, pol);
+  }
+
+  return 0;
 }
 
 /*
index aec6b0c5608e4f658588dc4b7d9caa55e6f4a912..292f0993d1ae45054ac005e0751c43abcda2a6af 100644 (file)
@@ -159,6 +159,8 @@ struct linuxdvb_satconf
    */
   linuxdvb_satconf_ele_list_t ls_elements;
   linuxdvb_satconf_ele_t *ls_last_switch;
+  int                    ls_last_pol;
+  int                    ls_last_toneburst;
 };
 
 /*
index 6dffe8c2a02716dfda93d8b19eeb065022b83db3..6f8324ec86c62286a0915326cf0f7b1f4e0b131f 100644 (file)
@@ -149,65 +149,80 @@ linuxdvb_switch_tune
   int i, com, r1 = 0, r2 = 0;
   int pol, band;
   linuxdvb_switch_t *ls = (linuxdvb_switch_t*)ld;
-
-  if (!sc->lse_parent->ls_diseqc_full && sc->lse_parent->ls_last_switch == sc)
-    return 0;
-
-  sc->lse_parent->ls_last_switch = NULL;
+  linuxdvb_satconf_t *lsp = sc->lse_parent;
 
   /* LNB settings */
   pol  = (sc->lse_lnb) ? sc->lse_lnb->lnb_pol (sc->lse_lnb, lm) & 0x1 : 0;
-  band = (sc->lse_lnb) ? sc->lse_lnb->lnb_band(sc->lse_lnb, lm) & 0x1 : 0;
-  com  = 0xF0 | (ls->ls_committed << 2) | (pol << 1) | band;
-  
-  /* Set the voltage */
-  if (linuxdvb_diseqc_set_volt(fd, pol))
-    return -1;
-
-  /* Single committed (before repeats) */
-  if (ls->ls_committed >= 0) {
-    if (sc->lse_parent->ls_diseqc_repeats > 0) {
-      r2 = 1;
-      if (linuxdvb_diseqc_send(fd, 0xE0, 0x10, 0x38, 1, com))
-        return -1;
-      usleep(25000); // 25ms
-    }
+
+  if (lsp->ls_diseqc_full || lsp->ls_last_pol != pol + 1) {
+
+    lsp->ls_last_pol = 0;
+
+    /* Set the voltage */
+    if (linuxdvb_diseqc_set_volt(fd, pol))
+      return -1;
+
+    lsp->ls_last_pol = pol + 1;
   }
 
-  /* Repeats */
-  for (i = 0; i <= sc->lse_parent->ls_diseqc_repeats; i++) {
+  if (lsp->ls_diseqc_full || lsp->ls_last_switch != sc) {
 
-    /* Uncommitted */
-    if (ls->ls_uncommitted >= 0) {
-      if (linuxdvb_diseqc_send(fd, 0xE0 | r1, 0x10, 0x39, 1,
-                               0xF0 | ls->ls_uncommitted))
-        return -1;
-      usleep(25000);
-    }
+    lsp->ls_last_switch = NULL;
+
+    band = (sc->lse_lnb) ? sc->lse_lnb->lnb_band(sc->lse_lnb, lm) & 0x1 : 0;
+    com  = 0xF0 | (ls->ls_committed << 2) | (pol << 1) | band;
 
-    /* Committed */
+    /* Single committed (before repeats) */
     if (ls->ls_committed >= 0) {
-      if (linuxdvb_diseqc_send(fd, 0xE0 | r2, 0x10, 0x38, 1, com))
-        return -1;
-      usleep(25000);
+      if (lsp->ls_diseqc_repeats > 0) {
+        r2 = 1;
+        if (linuxdvb_diseqc_send(fd, 0xE0, 0x10, 0x38, 1, com))
+          return -1;
+        usleep(25000); // 25ms
+      }
+    }
+
+    /* Repeats */
+    for (i = 0; i <= lsp->ls_diseqc_repeats; i++) {
+
+      /* Uncommitted */
+      if (ls->ls_uncommitted >= 0) {
+        if (linuxdvb_diseqc_send(fd, 0xE0 | r1, 0x10, 0x39, 1,
+                                 0xF0 | ls->ls_uncommitted))
+          return -1;
+        usleep(25000);
+      }
+
+      /* Committed */
+      if (ls->ls_committed >= 0) {
+        if (linuxdvb_diseqc_send(fd, 0xE0 | r2, 0x10, 0x38, 1, com))
+          return -1;
+        usleep(25000);
+      }
+
+      /* repeat flag */
+      r1 = r2 = 1;
     }
 
-    /* repeat flag */
-    r1 = r2 = 1;
+    lsp->ls_last_switch = sc;
+
+    /* port was changed, new LNB has not received toneburst yet */
+    lsp->ls_last_toneburst = 0;
   }
 
   /* Tone burst */
-  if (ls->ls_toneburst >= 0) {
+  if (ls->ls_toneburst >= 0 &&
+      (lsp->ls_diseqc_full || lsp->ls_last_toneburst != ls->ls_toneburst + 1)) {
+    lsp->ls_last_toneburst = 0;
     tvhtrace("diseqc", "toneburst %s", ls->ls_toneburst ? "B" : "A");
     if (ioctl(fd, FE_DISEQC_SEND_BURST,
               ls->ls_toneburst ? SEC_MINI_B : SEC_MINI_A)) {
       tvherror("diseqc", "failed to set toneburst (e=%s)", strerror(errno));
       return -1;
     }
+    lsp->ls_last_toneburst = ls->ls_toneburst + 1;
   }
 
-  sc->lse_parent->ls_last_switch = sc;
-
   return 0;
 }