Skip to content

Commit

Permalink
unicable2.vdr-1.7.15 patch from fds2001
Browse files Browse the repository at this point in the history
  • Loading branch information
flensrocker committed Aug 17, 2011
1 parent 139b6f1 commit 7643361
Show file tree
Hide file tree
Showing 6 changed files with 210 additions and 36 deletions.
94 changes: 90 additions & 4 deletions diseqc.c
Expand Up @@ -24,6 +24,7 @@ cDiseqc::cDiseqc(void)
commands = NULL;
parsing = false;
numCodes = 0;
unicable = -1;
}

cDiseqc::~cDiseqc()
Expand Down Expand Up @@ -101,10 +102,9 @@ const char *cDiseqc::Codes(const char *s) const
char *p;
int n = strtol(t, &p, 16);
if (!errno && p != t && 0 <= n && n <= 255) {
if (!parsing) {
codes[NumCodes++] = uchar(n);
numCodes = NumCodes;
}
if (!parsing)
codes[NumCodes] = uchar(n);
++NumCodes;
t = skipspace(p);
}
else {
Expand All @@ -117,13 +117,55 @@ const char *cDiseqc::Codes(const char *s) const
return NULL;
}
}
if (parsing)
numCodes = NumCodes;
return e + 1;
}
else
esyslog("ERROR: missing closing ']' in code sequence '%s'", s - 1);
return NULL;
}

const char *cDiseqc::Unicable(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)
unicable = n;
return p;
}
esyslog("ERROR: invalid unicable sat in '%s'", s - 1);
return NULL;
}

unsigned int cDiseqc::UnicableFreq(unsigned int frequency, int satcr, unsigned int bpf) const
{
unsigned int t = frequency == 0 ? 0 : (frequency + bpf + 2) / 4 - 350;
if (t < 1024 && satcr >= 0 && satcr < 8)
{
codes[3] = t >> 8 | (t == 0 ? 0 : unicable << 2) | satcr << 5;
codes[4] = t;
return (t + 350) * 4 - frequency;
}

return 0;
}

void cDiseqc::UnicablePin(int pin) const
{
if (pin >= 0 && pin <= 255) {
numCodes = 6;
codes[2] = 0x5c;
codes[5] = pin;
}
else {
numCodes = 5;
codes[2] = 0x5a;
}
}

cDiseqc::eDiseqcActions cDiseqc::Execute(const char **CurrentAction) const
{
if (!*CurrentAction)
Expand All @@ -139,6 +181,7 @@ cDiseqc::eDiseqcActions cDiseqc::Execute(const char **CurrentAction) const
case 'B': return daMiniB;
case 'W': *CurrentAction = Wait(*CurrentAction); break;
case '[': *CurrentAction = Codes(*CurrentAction); return *CurrentAction ? daCodes : daNone;
case 'U': *CurrentAction = Unicable(*CurrentAction); return *CurrentAction ? daUnicable : daNone;
default: return daNone;
}
}
Expand All @@ -164,3 +207,46 @@ const cDiseqc *cDiseqcs::Get(int Device, int Source, int Frequency, char Polariz
}
return NULL;
}

// --- cUnicable --------------------------------------------------------------

cUnicable::cUnicable()
{
satcr = -1;
bpf = 0;
pin = -1;
unused = true;
}

bool cUnicable::Parse(const char *s)
{
bool result = false;
int fields = sscanf(s, "%d %u %d", &satcr, &bpf, &pin);
if (fields >= 2) {
if (satcr >= 0 && satcr < 8)
result = true;
else
esyslog("Error: invalid unicable channel '%d'", satcr);
if (result && fields == 3 && (pin < 0 || pin > 255)) {
esyslog("Error: invalid unicable pin '%d'", pin);
result = false;
}
}
return result;
}


// --- cUnicables --------------------------------------------------------------

cUnicables Unicables;

cUnicable *cUnicables::GetUnused()
{
for (cUnicable *p = First(); p; p = Next(p)) {
if (p->Unused()) {
p->Use();
return p;
}
}
return NULL;
}
14 changes: 14 additions & 0 deletions diseqc.conf
Expand Up @@ -18,6 +18,7 @@
# V voltage high (18V)
# A mini A
# B mini B
# Un unicable code sequence for bank n follows
# Wnn wait nn milliseconds (nn may be any positive integer number)
# [xx ...] hex code sequence (max. 6)
#
Expand Down Expand Up @@ -75,3 +76,16 @@ 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 12110 V 11080 t v
# S19.2E 99999 V 10720 t v
#
# Unicable
#
# S19.2E 11700 V 9750 t V U0 W10 [E0 10 5A 00 00] W10 v
# S19.2E 99999 V 10600 t V U1 W10 [E0 10 5A 00 00] W10 v
# S19.2E 11700 H 9750 t V U2 W10 [E0 10 5A 00 00] W10 v
# S19.2E 99999 H 10600 t V U3 W10 [E0 10 5A 00 00] W10 v
#
# S13.0E 11700 V 9750 t V U4 W10 [E0 10 5A 00 00] W10 v
# S13.0E 99999 V 10600 t V U5 W10 [E0 10 5A 00 00] W10 v
# S13.0E 11700 H 9750 t V U6 W10 [E0 10 5A 00 00] W10 v
# S13.0E 99999 H 10600 t V U7 W10 [E0 10 5A 00 00] W10 v

29 changes: 29 additions & 0 deletions diseqc.h
Expand Up @@ -23,6 +23,7 @@ class cDiseqc : public cListObject {
daMiniA,
daMiniB,
daCodes,
daUnicable,
};
enum { MaxDiseqcCodes = 6 };
private:
Expand All @@ -32,11 +33,13 @@ class cDiseqc : public cListObject {
char polarization;
int lof;
char *commands;
mutable int unicable;
bool parsing;
mutable uchar codes[MaxDiseqcCodes];
mutable int numCodes;
const char *Wait(const char *s) const;
const char *Codes(const char *s) const;
const char *Unicable(const char *s) const;
public:
cDiseqc(void);
~cDiseqc();
Expand All @@ -56,6 +59,9 @@ class cDiseqc : public cListObject {
int Lof(void) const { return lof; }
const char *Commands(void) const { return commands; }
const uchar *Codes(int &NumCodes) const { NumCodes = numCodes; return numCodes ? codes : NULL; }
bool Unicable() const { return unicable >= 0; }
unsigned int UnicableFreq(unsigned int frequency, int satcr, unsigned int bpf) const;
void UnicablePin(int pin) const;
};

class cDiseqcs : public cConfig<cDiseqc> {
Expand All @@ -65,4 +71,27 @@ class cDiseqcs : public cConfig<cDiseqc> {

extern cDiseqcs Diseqcs;

class cUnicable : public cListObject {
private:
int satcr;
unsigned int bpf;
int pin;
bool unused;
public:
cUnicable();
bool Parse(const char *s);
int Satcr() const { return satcr; }
unsigned int Bpf() const { return bpf; }
int Pin() const { return pin; }
bool Unused() const { return unused; }
void Use() { unused = false; }
};

class cUnicables : public cConfig<cUnicable> {
public:
cUnicable *GetUnused();
};

extern cUnicables Unicables;

#endif //__DISEQC_H
93 changes: 61 additions & 32 deletions dvbdevice.c
Expand Up @@ -267,13 +267,15 @@ class cDvbTuner : public cThread {
time_t lastTimeoutReport;
fe_delivery_system frontendType;
cChannel channel;
const char *diseqcCommands;
cUnicable *unicable;
const cDiseqc *diseqcLast;
eTunerStatus tunerStatus;
cMutex mutex;
cCondVar locked;
cCondVar newSet;
void ClearEventQueue(void) const;
bool GetFrontendStatus(fe_status_t &Status) const;
void ExecuteDiseqc(const cDiseqc *diseqc, unsigned int &frequency);
bool SetFrontend(void);
virtual void Action(void);
public:
Expand All @@ -286,6 +288,9 @@ class cDvbTuner : public cThread {
bool Locked(int TimeoutMs = 0);
int GetSignalStrength(void) const;
int GetSignalQuality(void) const;
int UnicableSatcr() const { return unicable ? unicable->Satcr() : -1; }
int UnicableBpf() const { return unicable ? unicable->Bpf() : 0; }
int UnicablePin() const { return unicable ? unicable->Pin() : -1; }
};

cDvbTuner::cDvbTuner(int Device, int Fd_Frontend, int Adapter, int Frontend, fe_delivery_system FrontendType)
Expand All @@ -299,10 +304,13 @@ cDvbTuner::cDvbTuner(int Device, int Fd_Frontend, int Adapter, int Frontend, fe_
tuneTimeout = 0;
lockTimeout = 0;
lastTimeoutReport = 0;
diseqcCommands = NULL;
unicable = NULL;
diseqcLast = NULL;
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
unicable = Unicables.GetUnused();
}
SetDescription("tuner on frontend %d/%d", adapter, frontend);
Start();
}
Expand All @@ -313,6 +321,10 @@ cDvbTuner::~cDvbTuner()
newSet.Broadcast();
locked.Broadcast();
Cancel(3);
if (diseqcLast && diseqcLast->Unicable()) {
unsigned int frequency = 0;
ExecuteDiseqc(diseqcLast, frequency);
}
}

bool cDvbTuner::IsTunedTo(const cChannel *Channel) const
Expand Down Expand Up @@ -482,6 +494,43 @@ static unsigned int FrequencyToHz(unsigned int f)
return f;
}

void cDvbTuner::ExecuteDiseqc(const cDiseqc *diseqc, unsigned int &frequency)
{
cDiseqc::eDiseqcActions da;
for (const char *CurrentAction = NULL; (da = diseqc->Execute(&CurrentAction)) != cDiseqc::daNone; ) {
switch (da) {
case cDiseqc::daNone: break;
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: {
int n = 0;
const uchar *codes = diseqc->Codes(n);
if (codes) {
struct dvb_diseqc_master_cmd cmd;
cmd.msg_len = min(n, int(sizeof(cmd.msg)));
memcpy(cmd.msg, codes, cmd.msg_len);
CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd));
}
}
break;
case cDiseqc::daUnicable: {
frequency = diseqc->UnicableFreq(frequency, UnicableSatcr(), UnicableBpf());
diseqc->UnicablePin(UnicablePin());
if (frequency == 0) {
CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13));
esyslog("ERROR: unable to setup unicable frequency for channel %d (f=%u, s=%d, b=%d)", channel.Number(), frequency, UnicableSatcr(), UnicableBpf());
}
}
break;
default: esyslog("ERROR: unknown diseqc command %d", da);
}
}
}

bool cDvbTuner::SetFrontend(void)
{
#define MAXFRONTENDCMDS 16
Expand Down Expand Up @@ -511,34 +560,14 @@ bool cDvbTuner::SetFrontend(void)
if (Setup.DiSEqC) {
const cDiseqc *diseqc = Diseqcs.Get(device, channel.Source(), channel.Frequency(), dtp.Polarization());
if (diseqc) {
if (diseqc->Commands() && (!diseqcCommands || strcmp(diseqcCommands, diseqc->Commands()) != 0)) {
cDiseqc::eDiseqcActions da;
for (const char *CurrentAction = NULL; (da = diseqc->Execute(&CurrentAction)) != cDiseqc::daNone; ) {
switch (da) {
case cDiseqc::daNone: break;
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: {
int n = 0;
const uchar *codes = diseqc->Codes(n);
if (codes) {
struct dvb_diseqc_master_cmd cmd;
cmd.msg_len = min(n, int(sizeof(cmd.msg)));
memcpy(cmd.msg, codes, cmd.msg_len);
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();
if (diseqc->Commands() && (!diseqcLast || strcmp(diseqcLast->Commands(), diseqc->Commands()) != 0 || diseqc->Unicable())) {
ExecuteDiseqc(diseqc, frequency);
if (frequency == 0) {
return false;
}
diseqcLast = diseqc;
}
}
else {
esyslog("ERROR: no DiSEqC parameters found for channel %d", channel.Number());
Expand Down Expand Up @@ -657,7 +686,7 @@ void cDvbTuner::Action(void)
case tsTuned:
if (Timer.TimedOut()) {
tunerStatus = tsSet;
diseqcCommands = NULL;
diseqcLast = NULL;
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());
lastTimeoutReport = time(NULL);
Expand All @@ -667,7 +696,7 @@ void cDvbTuner::Action(void)
case tsLocked:
if (Status & FE_REINIT) {
tunerStatus = tsSet;
diseqcCommands = NULL;
diseqcLast = NULL;
isyslog("frontend %d/%d was reinitialized", adapter, frontend);
lastTimeoutReport = 0;
continue;
Expand Down
15 changes: 15 additions & 0 deletions unicable.conf
@@ -0,0 +1,15 @@
# Unicable configuration for VDR
#
# Format:
#
# channel frequency [pin]
#
# channel: unicable channel (0-7)
# frequency: frequency of the unicable channel
# pin: optional pin of the unicable channel (0-255)
#
# Examples:

0 1400
1 1516

1 change: 1 addition & 0 deletions vdr.c
Expand Up @@ -598,6 +598,7 @@ int main(int argc, char *argv[])
Setup.Load(AddDirectory(ConfigDirectory, "setup.conf"));
Sources.Load(AddDirectory(ConfigDirectory, "sources.conf"), true, true);
Diseqcs.Load(AddDirectory(ConfigDirectory, "diseqc.conf"), true, Setup.DiSEqC);
Unicables.Load(AddDirectory(ConfigDirectory, "unicable.conf"), true);
Channels.Load(AddDirectory(ConfigDirectory, "channels.conf"), false, true);
Timers.Load(AddDirectory(ConfigDirectory, "timers.conf"));
Commands.Load(AddDirectory(ConfigDirectory, "commands.conf"));
Expand Down

0 comments on commit 7643361

Please sign in to comment.