summaryrefslogtreecommitdiff
path: root/diseqc.c
diff options
context:
space:
mode:
authorKlaus Schmidinger <vdr@tvdr.de>2011-09-11 14:09:03 +0200
committerKlaus Schmidinger <vdr@tvdr.de>2011-09-11 14:09:03 +0200
commit413a0e6373f272f687db611185bc268c0d44f3b3 (patch)
tree046714f5e79e8ec57b4e7c64684dfe231d0109da /diseqc.c
parent78e89efee8a54d4343183fc98a34d13f9e0ef478 (diff)
downloadvdr-413a0e6373f272f687db611185bc268c0d44f3b3.tar.gz
vdr-413a0e6373f272f687db611185bc268c0d44f3b3.tar.bz2
VDR now supports "Satellite Channel Routing" (SCR)
Diffstat (limited to 'diseqc.c')
-rw-r--r--diseqc.c118
1 files changed, 112 insertions, 6 deletions
diff --git a/diseqc.c b/diseqc.c
index 591d31d8..07529606 100644
--- a/diseqc.c
+++ b/diseqc.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: diseqc.c 2.6 2011/09/10 13:38:38 kls Exp $
+ * $Id: diseqc.c 2.7 2011/09/11 13:39:48 kls Exp $
*/
#include "diseqc.h"
@@ -12,6 +12,51 @@
#include "sources.h"
#include "thread.h"
+// --- cScr ------------------------------------------------------------------
+
+cScr::cScr(void)
+{
+ channel = -1;
+ userBand = 0;
+ pin = -1;
+ used = false;
+}
+
+bool cScr::Parse(const char *s)
+{
+ bool result = false;
+ int fields = sscanf(s, "%d %u %d", &channel, &userBand, &pin);
+ if (fields == 2 || fields == 3) {
+ if (channel >= 0 && channel < 8) {
+ result = true;
+ if (fields == 3 && (pin < 0 || pin > 255)) {
+ esyslog("Error: invalid SCR pin '%d'", pin);
+ result = false;
+ }
+ }
+ else
+ esyslog("Error: invalid SCR channel '%d'", channel);
+ }
+ return result;
+}
+
+
+// --- cScrs -----------------------------------------------------------------
+
+cScrs Scrs;
+
+cScr *cScrs::GetUnused(void)
+{
+ cMutexLock MutexLock(&mutex);
+ for (cScr *p = First(); p; p = Next(p)) {
+ if (!p->Used()) {
+ p->SetUsed(true);
+ return p;
+ }
+ }
+ return NULL;
+}
+
// --- cDiseqc ---------------------------------------------------------------
cDiseqc::cDiseqc(void)
@@ -21,6 +66,7 @@ cDiseqc::cDiseqc(void)
slof = 0;
polarization = 0;
lof = 0;
+ scrBank = -1;
commands = NULL;
parsing = false;
}
@@ -59,7 +105,7 @@ bool cDiseqc::Parse(const char *s)
if (polarization == 'V' || polarization == 'H' || polarization == 'L' || polarization == 'R') {
parsing = true;
const char *CurrentAction = NULL;
- while (Execute(&CurrentAction, NULL, NULL) != daNone)
+ while (Execute(&CurrentAction, NULL, NULL, NULL, NULL) != daNone)
;
parsing = false;
result = !commands || !*CurrentAction;
@@ -74,6 +120,31 @@ bool cDiseqc::Parse(const char *s)
return result;
}
+uint cDiseqc::SetScrFrequency(uint SatFrequency, const cScr *Scr, uint8_t *Codes) const
+{
+ uint t = SatFrequency == 0 ? 0 : (SatFrequency + Scr->UserBand() + 2) / 4 - 350;
+ if (t < 1024 && Scr->Channel() >= 0 && Scr->Channel() < 8) {
+ Codes[3] = t >> 8 | (t == 0 ? 0 : scrBank << 2) | Scr->Channel() << 5;
+ Codes[4] = t;
+ if (t)
+ return (t + 350) * 4 - SatFrequency;
+ }
+ return 0;
+}
+
+int cDiseqc::SetScrPin(const cScr *Scr, uint8_t *Codes) const
+{
+ if (Scr->Pin() >= 0 && Scr->Pin() <= 255) {
+ Codes[2] = 0x5C;
+ Codes[5] = Scr->Pin();
+ return 6;
+ }
+ else {
+ Codes[2] = 0x5A;
+ return 5;
+ }
+}
+
const char *cDiseqc::Wait(const char *s) const
{
char *p = NULL;
@@ -88,6 +159,24 @@ const char *cDiseqc::Wait(const char *s) const
return NULL;
}
+const char *cDiseqc::GetScrBank(const char *s) const
+{
+ char *p = NULL;
+ errno = 0;
+ int n = strtol(s, &p, 10);
+ if (!errno && p != s && n >= 0 && n < 8) {
+ if (parsing) {
+ if (scrBank < 0)
+ scrBank = n;
+ else
+ esyslog("ERROR: more than one scr bank in '%s'", s - 1);
+ }
+ return p;
+ }
+ esyslog("ERROR: more than one scr bank in '%s'", s - 1);
+ return NULL;
+}
+
const char *cDiseqc::GetCodes(const char *s, uchar *Codes, uint8_t *MaxCodes) const
{
const char *e = strchr(s, ']');
@@ -129,7 +218,7 @@ const char *cDiseqc::GetCodes(const char *s, uchar *Codes, uint8_t *MaxCodes) co
return NULL;
}
-cDiseqc::eDiseqcActions cDiseqc::Execute(const char **CurrentAction, uchar *Codes, uint8_t *MaxCodes) const
+cDiseqc::eDiseqcActions cDiseqc::Execute(const char **CurrentAction, uchar *Codes, uint8_t *MaxCodes, const cScr *Scr, uint *Frequency) const
{
if (!*CurrentAction)
*CurrentAction = commands;
@@ -143,7 +232,16 @@ cDiseqc::eDiseqcActions cDiseqc::Execute(const char **CurrentAction, uchar *Code
case 'A': return daMiniA;
case 'B': return daMiniB;
case 'W': *CurrentAction = Wait(*CurrentAction); break;
- case '[': *CurrentAction = GetCodes(*CurrentAction, Codes, MaxCodes); return *CurrentAction ? daCodes : daNone;
+ case 'S': *CurrentAction = GetScrBank(*CurrentAction); break;
+ case '[': *CurrentAction = GetCodes(*CurrentAction, Codes, MaxCodes);
+ if (*CurrentAction) {
+ if (Scr && Frequency) {
+ *Frequency = SetScrFrequency(*Frequency, Scr, Codes);
+ *MaxCodes = SetScrPin(Scr, Codes);
+ }
+ return daCodes;
+ }
+ break;
default: return daNone;
}
}
@@ -154,7 +252,7 @@ cDiseqc::eDiseqcActions cDiseqc::Execute(const char **CurrentAction, uchar *Code
cDiseqcs Diseqcs;
-const cDiseqc *cDiseqcs::Get(int Device, int Source, int Frequency, char Polarization) const
+const cDiseqc *cDiseqcs::Get(int Device, int Source, int Frequency, char Polarization, const cScr **Scr) const
{
int Devices = 0;
for (const cDiseqc *p = First(); p; p = Next(p)) {
@@ -164,8 +262,16 @@ const cDiseqc *cDiseqcs::Get(int Device, int Source, int Frequency, char Polariz
}
if (Devices && !(Devices & (1 << Device - 1)))
continue;
- if (p->Source() == Source && p->Slof() > Frequency && p->Polarization() == toupper(Polarization))
+ if (p->Source() == Source && p->Slof() > Frequency && p->Polarization() == toupper(Polarization)) {
+ if (p->IsScr() && Scr && !*Scr) {
+ *Scr = Scrs.GetUnused();
+ if (*Scr)
+ dsyslog("SCR %d assigned to device %d", (*Scr)->Index(), Device);
+ else
+ esyslog("ERROR: no free SCR entry available for device %d", Device);
+ }
return p;
+ }
}
return NULL;
}