VDR now supports "Satellite Channel Routing" (SCR)

This commit is contained in:
Klaus Schmidinger 2011-09-11 14:09:03 +02:00
parent 78e89efee8
commit 413a0e6373
10 changed files with 292 additions and 52 deletions

View File

@ -2661,6 +2661,7 @@ Stephan Austerm
Lars Hanisch <dvb@flensrocker.de> Lars Hanisch <dvb@flensrocker.de>
for suggesting to assign the source character 'V' to "Analog Video" for suggesting to assign the source character 'V' to "Analog Video"
for a patch that was used to implement SCR (Satellite Channel Routing)
Alex Lasnier <alex@fepg.org> Alex Lasnier <alex@fepg.org>
for adding tuning support for ATSC devices for adding tuning support for ATSC devices

View File

@ -6743,8 +6743,15 @@ Video Disk Recorder Revision History
extends over TS packet boundaries is now done by locally skipping TS packets extends over TS packet boundaries is now done by locally skipping TS packets
in cFrameDetector. in cFrameDetector.
2011-09-10: Version 1.7.22 2011-09-11: Version 1.7.22
- Fixed scaling subtitles in case the primary device's GetVideoSize() function doesn't - Fixed scaling subtitles in case the primary device's GetVideoSize() function doesn't
return actual values (thanks to Luca Olivetti). return actual values (thanks to Luca Olivetti).
- The DiSEqC codes are now copied in the call to cDiseqc::Execute(). - The DiSEqC codes are now copied in the call to cDiseqc::Execute().
- VDR now supports "Satellite Channel Routing" (SCR) (based on the "unicable" patch
from Lars Hanisch). Since "Unicable" is a registered trademark and stands for only
one of many implementations of SCR, the following changes have been made compared
to the patch, which need to be taken into account by people who have set up their
system using the patch:
- The 'U' parameter in the diseqc.conf file has been changed to 'S' ("Scr").
- The configuration file name has been changed from "unicable.conf" to "scr.conf".

View File

@ -386,6 +386,12 @@ accessed using DiSEqC, you have to go to the "Setup" menu and set the "DiSEqC"
parameter to "on". You also need to set up the file 'diseqc.conf' to properly parameter to "on". You also need to set up the file 'diseqc.conf' to properly
access your DiSEqC equipment (see man vdr(5) for details). access your DiSEqC equipment (see man vdr(5) for details).
A special form of DiSEqC is used to connect several receivers to one signal
source using only a single cable. This method, known as "Satellite Channel Routing"
according to EN50494 (aka "Unicable(TM)", "OLT(TM)", "SatCR", "Single Cable
Distribution", "Channel Stacking System" or "Single Cable Interface") uses
the file "scr.conf" to specify which SCR channels use which user band frequency.
Running VDR with DVB-C (cable) or DVB-T (terrestrial): Running VDR with DVB-C (cable) or DVB-T (terrestrial):
------------------------------------------------------ ------------------------------------------------------

118
diseqc.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "diseqc.h"
@ -12,6 +12,51 @@
#include "sources.h" #include "sources.h"
#include "thread.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::cDiseqc(void) cDiseqc::cDiseqc(void)
@ -21,6 +66,7 @@ cDiseqc::cDiseqc(void)
slof = 0; slof = 0;
polarization = 0; polarization = 0;
lof = 0; lof = 0;
scrBank = -1;
commands = NULL; commands = NULL;
parsing = false; parsing = false;
} }
@ -59,7 +105,7 @@ bool cDiseqc::Parse(const char *s)
if (polarization == 'V' || polarization == 'H' || polarization == 'L' || polarization == 'R') { if (polarization == 'V' || polarization == 'H' || polarization == 'L' || polarization == 'R') {
parsing = true; parsing = true;
const char *CurrentAction = NULL; const char *CurrentAction = NULL;
while (Execute(&CurrentAction, NULL, NULL) != daNone) while (Execute(&CurrentAction, NULL, NULL, NULL, NULL) != daNone)
; ;
parsing = false; parsing = false;
result = !commands || !*CurrentAction; result = !commands || !*CurrentAction;
@ -74,6 +120,31 @@ bool cDiseqc::Parse(const char *s)
return result; 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 const char *cDiseqc::Wait(const char *s) const
{ {
char *p = NULL; char *p = NULL;
@ -88,6 +159,24 @@ const char *cDiseqc::Wait(const char *s) const
return NULL; 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 *cDiseqc::GetCodes(const char *s, uchar *Codes, uint8_t *MaxCodes) const
{ {
const char *e = strchr(s, ']'); const char *e = strchr(s, ']');
@ -129,7 +218,7 @@ const char *cDiseqc::GetCodes(const char *s, uchar *Codes, uint8_t *MaxCodes) co
return NULL; 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) if (!*CurrentAction)
*CurrentAction = commands; *CurrentAction = commands;
@ -143,7 +232,16 @@ cDiseqc::eDiseqcActions cDiseqc::Execute(const char **CurrentAction, uchar *Code
case 'A': return daMiniA; case 'A': return daMiniA;
case 'B': return daMiniB; case 'B': return daMiniB;
case 'W': *CurrentAction = Wait(*CurrentAction); break; 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; default: return daNone;
} }
} }
@ -154,7 +252,7 @@ cDiseqc::eDiseqcActions cDiseqc::Execute(const char **CurrentAction, uchar *Code
cDiseqcs Diseqcs; 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; int Devices = 0;
for (const cDiseqc *p = First(); p; p = Next(p)) { 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))) if (Devices && !(Devices & (1 << Device - 1)))
continue; 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 p;
}
} }
return NULL; return NULL;
} }

View File

@ -18,6 +18,7 @@
# V voltage high (18V) # V voltage high (18V)
# A mini A # A mini A
# B mini B # B mini B
# Sn Satellite channel routing code sequence for bank n follows
# Wnn wait nn milliseconds (nn may be any positive integer number) # Wnn wait nn milliseconds (nn may be any positive integer number)
# [xx ...] hex code sequence (max. 6) # [xx ...] hex code sequence (max. 6)
# #
@ -75,3 +76,15 @@ S13.0E 99999 H 10600 t V W15 [E0 10 38 F7] W15 B W15 T
# S19.2E 99999 H 10560 t v # S19.2E 99999 H 10560 t v
# S19.2E 12110 V 11080 t v # S19.2E 12110 V 11080 t v
# S19.2E 99999 V 10720 t v # S19.2E 99999 V 10720 t v
#
# SCR (Satellite Channel Routing):
#
# S19.2E 11700 V 9750 t V W10 S0 [E0 10 5A 00 00] W10 v
# S19.2E 99999 V 10600 t V W10 S1 [E0 10 5A 00 00] W10 v
# S19.2E 11700 H 9750 t V W10 S2 [E0 10 5A 00 00] W10 v
# S19.2E 99999 H 10600 t V W10 S3 [E0 10 5A 00 00] W10 v
#
# S13.0E 11700 V 9750 t V W10 S4 [E0 10 5A 00 00] W10 v
# S13.0E 99999 V 10600 t V W10 S5 [E0 10 5A 00 00] W10 v
# S13.0E 11700 H 9750 t V W10 S6 [E0 10 5A 00 00] W10 v
# S13.0E 99999 H 10600 t V W10 S7 [E0 10 5A 00 00] W10 v

View File

@ -4,13 +4,39 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: diseqc.h 2.3 2011/09/10 13:36:50 kls Exp $ * $Id: diseqc.h 2.4 2011/09/11 13:40:16 kls Exp $
*/ */
#ifndef __DISEQC_H #ifndef __DISEQC_H
#define __DISEQC_H #define __DISEQC_H
#include "config.h" #include "config.h"
#include "thread.h"
class cScr : public cListObject {
private:
int channel;
uint userBand;
int pin;
bool used;
public:
cScr(void);
bool Parse(const char *s);
int Channel(void) const { return channel; }
uint UserBand(void) const { return userBand; }
int Pin(void) const { return pin; }
bool Used(void) const { return used; }
void SetUsed(bool Used) { used = Used; }
};
class cScrs : public cConfig<cScr> {
private:
cMutex mutex;
public:
cScr *GetUnused(void);
};
extern cScrs Scrs;
class cDiseqc : public cListObject { class cDiseqc : public cListObject {
public: public:
@ -22,6 +48,7 @@ public:
daVoltage18, daVoltage18,
daMiniA, daMiniA,
daMiniB, daMiniB,
daScr,
daCodes, daCodes,
}; };
enum { MaxDiseqcCodes = 6 }; enum { MaxDiseqcCodes = 6 };
@ -31,37 +58,53 @@ private:
int slof; int slof;
char polarization; char polarization;
int lof; int lof;
mutable int scrBank;
char *commands; char *commands;
bool parsing; bool parsing;
uint SetScrFrequency(uint SatFrequency, const cScr *Scr, uint8_t *Codes) const;
int SetScrPin(const cScr *Scr, uint8_t *Codes) const;
const char *Wait(const char *s) const; const char *Wait(const char *s) const;
const char *GetScrBank(const char *s) const;
const char *GetCodes(const char *s, uchar *Codes = NULL, uint8_t *MaxCodes = NULL) const; const char *GetCodes(const char *s, uchar *Codes = NULL, uint8_t *MaxCodes = NULL) const;
public: public:
cDiseqc(void); cDiseqc(void);
~cDiseqc(); ~cDiseqc();
bool Parse(const char *s); bool Parse(const char *s);
eDiseqcActions Execute(const char **CurrentAction, uchar *Codes, uint8_t *MaxCodes) const; eDiseqcActions Execute(const char **CurrentAction, uchar *Codes, uint8_t *MaxCodes, const cScr *Scr, uint *Frequency) const;
// Parses the DiSEqC commands and returns the appropriate action code ///< Parses the DiSEqC commands and returns the appropriate action code
// with every call. CurrentAction must be the address of a character pointer, ///< with every call. CurrentAction must be the address of a character pointer,
// which is initialized to NULL. This pointer is used internally while parsing ///< which is initialized to NULL. This pointer is used internally while parsing
// the commands and shall not be modified once Execute() has been called with ///< the commands and shall not be modified once Execute() has been called with
// it. Call Execute() repeatedly (always providing the same CurrentAction pointer) ///< it. Call Execute() repeatedly (always providing the same CurrentAction pointer)
// until it returns daNone. After a successful execution of all commands ///< until it returns daNone. After a successful execution of all commands
// *CurrentAction points to the value 0x00. ///< *CurrentAction points to the value 0x00.
// If the current action consists of sending code bytes to the device, those ///< If the current action consists of sending code bytes to the device, those
// bytes will be copied into Codes. MaxCodes must be initialized to the maximum ///< bytes will be copied into Codes. MaxCodes must be initialized to the maximum
// number of bytes Codes can handle, and will be set to the actual number of ///< number of bytes Codes can handle, and will be set to the actual number of
// bytes copied to Codes upon return. ///< bytes copied to Codes upon return.
///< If this DiSEqC entry requires SCR, the given Scr will be used. This must
///< be a pointer returned from a previous call to cDiseqcs::Get().
///< Frequency must be the frequency the tuner will be tuned to, and will be
///< set to the proper SCR frequency upon return (if SCR is used).
int Devices(void) const { return devices; } int Devices(void) const { return devices; }
int Source(void) const { return source; } int Source(void) const { return source; }
int Slof(void) const { return slof; } int Slof(void) const { return slof; }
char Polarization(void) const { return polarization; } char Polarization(void) const { return polarization; }
int Lof(void) const { return lof; } int Lof(void) const { return lof; }
bool IsScr() const { return scrBank >= 0; }
const char *Commands(void) const { return commands; } const char *Commands(void) const { return commands; }
}; };
class cDiseqcs : public cConfig<cDiseqc> { class cDiseqcs : public cConfig<cDiseqc> {
public: public:
const cDiseqc *Get(int Device, int Source, int Frequency, char Polarization) const; const cDiseqc *Get(int Device, int Source, int Frequency, char Polarization, const cScr **Scr) const;
///< Selects a DiSEqC entry suitable for the given Device and tuning parameters.
///< If this DiSEqC entry requires SCR and the given *Scr is NULL
///< a free one will be selected from the Scrs and a pointer to that will
///< be returned in Scr. The caller shall memorize that pointer and reuse it in
///< subsequent calls.
///< Scr may be NULL for checking whether there is any DiSEqC entry for the
///< given transponder.
}; };
extern cDiseqcs Diseqcs; extern cDiseqcs Diseqcs;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: dvbdevice.c 2.44 2011/09/10 13:34:02 kls Exp $ * $Id: dvbdevice.c 2.45 2011/09/11 13:50:20 kls Exp $
*/ */
#include "dvbdevice.h" #include "dvbdevice.h"
@ -267,13 +267,15 @@ private:
time_t lastTimeoutReport; time_t lastTimeoutReport;
fe_delivery_system frontendType; fe_delivery_system frontendType;
cChannel channel; cChannel channel;
const char *diseqcCommands; const cDiseqc *lastDiseqc;
const cScr *scr;
eTunerStatus tunerStatus; eTunerStatus tunerStatus;
cMutex mutex; cMutex mutex;
cCondVar locked; cCondVar locked;
cCondVar newSet; cCondVar newSet;
void ClearEventQueue(void) const; void ClearEventQueue(void) const;
bool GetFrontendStatus(fe_status_t &Status) const; bool GetFrontendStatus(fe_status_t &Status) const;
void ExecuteDiseqc(const cDiseqc *Diseqc, unsigned int *Frequency) const;
bool SetFrontend(void); bool SetFrontend(void);
virtual void Action(void); virtual void Action(void);
public: public:
@ -299,7 +301,8 @@ cDvbTuner::cDvbTuner(int Device, int Fd_Frontend, int Adapter, int Frontend, fe_
tuneTimeout = 0; tuneTimeout = 0;
lockTimeout = 0; lockTimeout = 0;
lastTimeoutReport = 0; lastTimeoutReport = 0;
diseqcCommands = NULL; lastDiseqc = NULL;
scr = NULL;
tunerStatus = tsIdle; tunerStatus = tsIdle;
if (frontendType == SYS_DVBS || frontendType == SYS_DVBS2) if (frontendType == SYS_DVBS || frontendType == SYS_DVBS2)
CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); // must explicitly turn on LNB power CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); // must explicitly turn on LNB power
@ -313,6 +316,10 @@ cDvbTuner::~cDvbTuner()
newSet.Broadcast(); newSet.Broadcast();
locked.Broadcast(); locked.Broadcast();
Cancel(3); Cancel(3);
if (lastDiseqc && lastDiseqc->IsScr()) {
unsigned int Frequency = 0;
ExecuteDiseqc(lastDiseqc, &Frequency);
}
} }
bool cDvbTuner::IsTunedTo(const cChannel *Channel) const bool cDvbTuner::IsTunedTo(const cChannel *Channel) const
@ -482,6 +489,30 @@ static unsigned int FrequencyToHz(unsigned int f)
return f; return f;
} }
void cDvbTuner::ExecuteDiseqc(const cDiseqc *Diseqc, unsigned int *Frequency) const
{
struct dvb_diseqc_master_cmd cmd;
const char *CurrentAction = NULL;
for (;;) {
cmd.msg_len = sizeof(cmd.msg);
cDiseqc::eDiseqcActions da = Diseqc->Execute(&CurrentAction, cmd.msg, &cmd.msg_len, scr, Frequency);
if (da == cDiseqc::daNone)
break;
switch (da) {
case cDiseqc::daToneOff: CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF)); break;
case cDiseqc::daToneOn: CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_ON)); break;
case cDiseqc::daVoltage13: CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); break;
case cDiseqc::daVoltage18: CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_18)); break;
case cDiseqc::daMiniA: CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_A)); break;
case cDiseqc::daMiniB: CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_B)); break;
case cDiseqc::daCodes: CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd)); break;
default: esyslog("ERROR: unknown diseqc command %d", da);
}
}
if (scr)
CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); // makes sure we don't block the bus!
}
bool cDvbTuner::SetFrontend(void) bool cDvbTuner::SetFrontend(void)
{ {
#define MAXFRONTENDCMDS 16 #define MAXFRONTENDCMDS 16
@ -509,30 +540,14 @@ bool cDvbTuner::SetFrontend(void)
if (frontendType == SYS_DVBS || frontendType == SYS_DVBS2) { if (frontendType == SYS_DVBS || frontendType == SYS_DVBS2) {
unsigned int frequency = channel.Frequency(); unsigned int frequency = channel.Frequency();
if (Setup.DiSEqC) { if (Setup.DiSEqC) {
const cDiseqc *diseqc = Diseqcs.Get(device, channel.Source(), frequency, dtp.Polarization()); if (const cDiseqc *diseqc = Diseqcs.Get(device, channel.Source(), frequency, dtp.Polarization(), &scr)) {
if (diseqc) {
if (diseqc->Commands() && (!diseqcCommands || strcmp(diseqcCommands, diseqc->Commands()) != 0)) {
struct dvb_diseqc_master_cmd cmd;
const char *CurrentAction = NULL;
for (;;) {
cmd.msg_len = sizeof(cmd.msg);
cDiseqc::eDiseqcActions da = diseqc->Execute(&CurrentAction, cmd.msg, &cmd.msg_len);
if (da == cDiseqc::daNone)
break;
switch (da) {
case cDiseqc::daToneOff: CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF)); break;
case cDiseqc::daToneOn: CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_ON)); break;
case cDiseqc::daVoltage13: CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); break;
case cDiseqc::daVoltage18: CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_18)); break;
case cDiseqc::daMiniA: CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_A)); break;
case cDiseqc::daMiniB: CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_B)); break;
case cDiseqc::daCodes: CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd)); break;
default: esyslog("ERROR: unknown diseqc command %d", da);
}
}
diseqcCommands = diseqc->Commands();
}
frequency -= diseqc->Lof(); frequency -= diseqc->Lof();
if (diseqc != lastDiseqc || diseqc->IsScr()) {
ExecuteDiseqc(diseqc, &frequency);
if (frequency == 0)
return false;
lastDiseqc = diseqc;
}
} }
else { else {
esyslog("ERROR: no DiSEqC parameters found for channel %d", channel.Number()); esyslog("ERROR: no DiSEqC parameters found for channel %d", channel.Number());
@ -651,7 +666,7 @@ void cDvbTuner::Action(void)
case tsTuned: case tsTuned:
if (Timer.TimedOut()) { if (Timer.TimedOut()) {
tunerStatus = tsSet; tunerStatus = tsSet;
diseqcCommands = NULL; lastDiseqc = NULL;
if (time(NULL) - lastTimeoutReport > 60) { // let's not get too many of these if (time(NULL) - lastTimeoutReport > 60) { // let's not get too many of these
isyslog("frontend %d/%d timed out while tuning to channel %d, tp %d", adapter, frontend, channel.Number(), channel.Transponder()); isyslog("frontend %d/%d timed out while tuning to channel %d, tp %d", adapter, frontend, channel.Number(), channel.Transponder());
lastTimeoutReport = time(NULL); lastTimeoutReport = time(NULL);
@ -661,7 +676,7 @@ void cDvbTuner::Action(void)
case tsLocked: case tsLocked:
if (Status & FE_REINIT) { if (Status & FE_REINIT) {
tunerStatus = tsSet; tunerStatus = tsSet;
diseqcCommands = NULL; lastDiseqc = NULL;
isyslog("frontend %d/%d was reinitialized", adapter, frontend); isyslog("frontend %d/%d was reinitialized", adapter, frontend);
lastTimeoutReport = 0; lastTimeoutReport = 0;
continue; continue;
@ -1036,7 +1051,7 @@ bool cDvbDevice::ProvidesTransponder(const cChannel *Channel) const
dtp.Modulation() == PSK_8 && !(frontendInfo.caps & FE_CAN_TURBO_FEC) && dtp.System() == SYS_DVBS) // "turbo fec" is a non standard FEC used by North American broadcasters - this is a best guess to determine this condition dtp.Modulation() == PSK_8 && !(frontendInfo.caps & FE_CAN_TURBO_FEC) && dtp.System() == SYS_DVBS) // "turbo fec" is a non standard FEC used by North American broadcasters - this is a best guess to determine this condition
return false; // requires modulation system which frontend doesn't provide return false; // requires modulation system which frontend doesn't provide
if (!cSource::IsSat(Channel->Source()) || if (!cSource::IsSat(Channel->Source()) ||
!Setup.DiSEqC || Diseqcs.Get(CardIndex() + 1, Channel->Source(), Channel->Frequency(), dtp.Polarization())) !Setup.DiSEqC || Diseqcs.Get(CardIndex() + 1, Channel->Source(), Channel->Frequency(), dtp.Polarization(), NULL))
return DeviceHooksProvidesTransponder(Channel); return DeviceHooksProvidesTransponder(Channel);
return false; return false;
} }

20
scr.conf Normal file
View File

@ -0,0 +1,20 @@
# SCR (Satellite Channel Routing) configuration for VDR
#
# Format:
#
# channel frequency [pin]
#
# channel: SCR channel index (0-7)
# frequency: frequency of the SCR channel ("user band")
# pin: optional pin of the SCR channel (0-255)
#
# Examples:
# 0 1284
# 1 1400
# 2 1516
# 3 1632
# 4 1748
# 5 1864
# 6 1980
# 7 2096

30
vdr.5
View File

@ -8,7 +8,7 @@
.\" License as specified in the file COPYING that comes with the .\" License as specified in the file COPYING that comes with the
.\" vdr distribution. .\" vdr distribution.
.\" .\"
.\" $Id: vdr.5 2.23 2011/08/21 14:06:50 kls Exp $ .\" $Id: vdr.5 2.24 2011/09/10 14:45:00 kls Exp $
.\" .\"
.TH vdr 5 "10 Feb 2008" "1.6" "Video Disk Recorder Files" .TH vdr 5 "10 Feb 2008" "1.6" "Video Disk Recorder Files"
.SH NAME .SH NAME
@ -467,6 +467,7 @@ l l.
\fBV\fR@voltage high (18V) \fBV\fR@voltage high (18V)
\fBA\fR@mini A \fBA\fR@mini A
\fBB\fR@mini B \fBB\fR@mini B
\fBSn\fR@Satellite channel routing code sequence for bank n follows
\fBWnn\fR@wait nn milliseconds (nn may be any positive integer number) \fBWnn\fR@wait nn milliseconds (nn may be any positive integer number)
\fB[xx ...]\fR@hex code sequence (max. 6) \fB[xx ...]\fR@hex code sequence (max. 6)
.TE .TE
@ -484,6 +485,33 @@ to receive the satellites following thereafter. In this case, only the devices
1, 2 and 4 would be able to receive any satellites following this line and up 1, 2 and 4 would be able to receive any satellites following this line and up
to the next such line, or the end of the file. Devices may be listed more than to the next such line, or the end of the file. Devices may be listed more than
once. once.
.SS SATELLITE CHANNEL ROUTING (SCR)
The file \fIscr.conf\fR contains the channel definitions of the SCR device in use.
The format is
channel frequency [pin]
where channel is the SCR device's channel index (0-7), frequency is the user band
frequency of the given channel, and pin is an optional pin number (0-255). The
actual values are device specific and can be found in the SCR device's manual.
Examples:
0 1284
.br
1 1400
.br
2 1516
.br
3 1632
.br
4 1748
.br
5 1864
.br
6 1980
.br
7 2096
.SS REMOTE CONTROL KEYS .SS REMOTE CONTROL KEYS
The file \fIremote.conf\fR contains the key assignments for all remote control The file \fIremote.conf\fR contains the key assignments for all remote control
units. Each line consists of one key assignment in the following format: units. Each line consists of one key assignment in the following format:

3
vdr.c
View File

@ -22,7 +22,7 @@
* *
* The project's page is at http://www.tvdr.de * The project's page is at http://www.tvdr.de
* *
* $Id: vdr.c 2.23 2011/08/15 12:42:39 kls Exp $ * $Id: vdr.c 2.24 2011/09/10 15:03:23 kls Exp $
*/ */
#include <getopt.h> #include <getopt.h>
@ -598,6 +598,7 @@ int main(int argc, char *argv[])
Setup.Load(AddDirectory(ConfigDirectory, "setup.conf")); Setup.Load(AddDirectory(ConfigDirectory, "setup.conf"));
Sources.Load(AddDirectory(ConfigDirectory, "sources.conf"), true, true); Sources.Load(AddDirectory(ConfigDirectory, "sources.conf"), true, true);
Diseqcs.Load(AddDirectory(ConfigDirectory, "diseqc.conf"), true, Setup.DiSEqC); Diseqcs.Load(AddDirectory(ConfigDirectory, "diseqc.conf"), true, Setup.DiSEqC);
Scrs.Load(AddDirectory(ConfigDirectory, "scr.conf"), true);
Channels.Load(AddDirectory(ConfigDirectory, "channels.conf"), false, true); Channels.Load(AddDirectory(ConfigDirectory, "channels.conf"), false, true);
Timers.Load(AddDirectory(ConfigDirectory, "timers.conf")); Timers.Load(AddDirectory(ConfigDirectory, "timers.conf"));
Commands.Load(AddDirectory(ConfigDirectory, "commands.conf")); Commands.Load(AddDirectory(ConfigDirectory, "commands.conf"));