diff options
author | Klaus Schmidinger <vdr@tvdr.de> | 2011-09-11 14:09:03 +0200 |
---|---|---|
committer | Klaus Schmidinger <vdr@tvdr.de> | 2011-09-11 14:09:03 +0200 |
commit | 413a0e6373f272f687db611185bc268c0d44f3b3 (patch) | |
tree | 046714f5e79e8ec57b4e7c64684dfe231d0109da /diseqc.c | |
parent | 78e89efee8a54d4343183fc98a34d13f9e0ef478 (diff) | |
download | vdr-413a0e6373f272f687db611185bc268c0d44f3b3.tar.gz vdr-413a0e6373f272f687db611185bc268c0d44f3b3.tar.bz2 |
VDR now supports "Satellite Channel Routing" (SCR)
Diffstat (limited to 'diseqc.c')
-rw-r--r-- | diseqc.c | 118 |
1 files changed, 112 insertions, 6 deletions
@@ -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; } |