2002-10-06 10:25:42 +02:00
|
|
|
/*
|
|
|
|
* diseqc.c: DiSEqC handling
|
|
|
|
*
|
|
|
|
* See the main source file 'vdr.c' for copyright information and
|
|
|
|
* how to reach the author.
|
|
|
|
*
|
2011-08-06 10:45:05 +02:00
|
|
|
* $Id: diseqc.c 2.5 2011/08/06 10:32:18 kls Exp $
|
2002-10-06 10:25:42 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "diseqc.h"
|
|
|
|
#include <ctype.h>
|
|
|
|
#include "sources.h"
|
2004-10-24 11:12:05 +02:00
|
|
|
#include "thread.h"
|
2002-10-06 10:25:42 +02:00
|
|
|
|
2008-02-10 14:11:47 +01:00
|
|
|
// --- cDiseqc ---------------------------------------------------------------
|
2002-10-06 10:25:42 +02:00
|
|
|
|
|
|
|
cDiseqc::cDiseqc(void)
|
|
|
|
{
|
2010-02-06 15:56:01 +01:00
|
|
|
devices = 0;
|
|
|
|
source = 0;
|
|
|
|
slof = 0;
|
|
|
|
polarization = 0;
|
|
|
|
lof = 0;
|
2002-10-06 10:25:42 +02:00
|
|
|
commands = NULL;
|
|
|
|
parsing = false;
|
|
|
|
numCodes = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
cDiseqc::~cDiseqc()
|
|
|
|
{
|
|
|
|
free(commands);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cDiseqc::Parse(const char *s)
|
|
|
|
{
|
|
|
|
bool result = false;
|
|
|
|
char *sourcebuf = NULL;
|
2010-02-06 15:56:01 +01:00
|
|
|
if (*s && s[strlen(s) - 1] == ':') {
|
|
|
|
const char *p = s;
|
|
|
|
while (*p && *p != ':') {
|
|
|
|
char *t = NULL;
|
|
|
|
int d = strtol(p, &t, 10);
|
|
|
|
p = t;
|
|
|
|
if (0 < d && d < 32)
|
|
|
|
devices |= (1 << d - 1);
|
|
|
|
else {
|
|
|
|
esyslog("ERROR: invalid device number %d in '%s'", d, s);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2002-10-06 10:25:42 +02:00
|
|
|
int fields = sscanf(s, "%a[^ ] %d %c %d %a[^\n]", &sourcebuf, &slof, &polarization, &lof, &commands);
|
|
|
|
if (fields == 4)
|
|
|
|
commands = NULL; //XXX Apparently sscanf() doesn't work correctly if the last %a argument results in an empty string
|
|
|
|
if (4 <= fields && fields <= 5) {
|
|
|
|
source = cSource::FromString(sourcebuf);
|
|
|
|
if (Sources.Get(source)) {
|
2009-12-06 12:57:45 +01:00
|
|
|
polarization = char(toupper(polarization));
|
2005-01-09 13:18:15 +01:00
|
|
|
if (polarization == 'V' || polarization == 'H' || polarization == 'L' || polarization == 'R') {
|
2002-10-06 10:25:42 +02:00
|
|
|
parsing = true;
|
2011-05-22 10:51:03 +02:00
|
|
|
const char *CurrentAction = NULL;
|
2002-12-08 09:55:26 +01:00
|
|
|
while (Execute(&CurrentAction) != daNone)
|
|
|
|
;
|
2002-10-06 10:25:42 +02:00
|
|
|
parsing = false;
|
2002-12-08 09:55:26 +01:00
|
|
|
result = !commands || !*CurrentAction;
|
2002-10-06 10:25:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
esyslog("ERROR: unknown polarization '%c'", polarization);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
esyslog("ERROR: unknown source '%s'", sourcebuf);
|
|
|
|
}
|
|
|
|
free(sourcebuf);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2011-05-22 10:51:03 +02:00
|
|
|
const char *cDiseqc::Wait(const char *s) const
|
2002-10-06 10:25:42 +02:00
|
|
|
{
|
|
|
|
char *p = NULL;
|
|
|
|
errno = 0;
|
|
|
|
int n = strtol(s, &p, 10);
|
|
|
|
if (!errno && p != s && n >= 0) {
|
|
|
|
if (!parsing)
|
2004-10-24 11:12:05 +02:00
|
|
|
cCondWait::SleepMs(n);
|
2002-10-06 10:25:42 +02:00
|
|
|
return p;
|
|
|
|
}
|
2005-12-30 15:43:21 +01:00
|
|
|
esyslog("ERROR: invalid value for wait time in '%s'", s - 1);
|
2002-10-06 10:25:42 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2011-05-22 10:51:03 +02:00
|
|
|
const char *cDiseqc::Codes(const char *s) const
|
2002-10-06 10:25:42 +02:00
|
|
|
{
|
2011-05-22 10:51:03 +02:00
|
|
|
const char *e = strchr(s, ']');
|
2002-10-06 10:25:42 +02:00
|
|
|
if (e) {
|
2011-05-22 10:51:03 +02:00
|
|
|
int NumCodes = 0;
|
|
|
|
const char *t = s;
|
2002-10-06 10:25:42 +02:00
|
|
|
while (t < e) {
|
2011-05-22 10:51:03 +02:00
|
|
|
if (NumCodes < MaxDiseqcCodes) {
|
2002-10-06 10:25:42 +02:00
|
|
|
errno = 0;
|
2011-08-06 10:45:05 +02:00
|
|
|
char *p;
|
2002-10-06 10:25:42 +02:00
|
|
|
int n = strtol(t, &p, 16);
|
|
|
|
if (!errno && p != t && 0 <= n && n <= 255) {
|
2011-08-06 10:45:05 +02:00
|
|
|
if (!parsing) {
|
2011-05-22 10:51:03 +02:00
|
|
|
codes[NumCodes++] = uchar(n);
|
|
|
|
numCodes = NumCodes;
|
|
|
|
}
|
2002-10-06 10:25:42 +02:00
|
|
|
t = skipspace(p);
|
|
|
|
}
|
|
|
|
else {
|
2005-12-30 15:43:21 +01:00
|
|
|
esyslog("ERROR: invalid code at '%s'", t);
|
2002-10-06 10:25:42 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
esyslog("ERROR: too many codes in code sequence '%s'", s - 1);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return e + 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
esyslog("ERROR: missing closing ']' in code sequence '%s'", s - 1);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2011-05-22 10:51:03 +02:00
|
|
|
cDiseqc::eDiseqcActions cDiseqc::Execute(const char **CurrentAction) const
|
2002-10-06 10:25:42 +02:00
|
|
|
{
|
2002-12-08 09:55:26 +01:00
|
|
|
if (!*CurrentAction)
|
|
|
|
*CurrentAction = commands;
|
|
|
|
while (*CurrentAction && **CurrentAction) {
|
|
|
|
switch (*(*CurrentAction)++) {
|
2002-10-06 10:25:42 +02:00
|
|
|
case ' ': break;
|
|
|
|
case 't': return daToneOff;
|
|
|
|
case 'T': return daToneOn;
|
|
|
|
case 'v': return daVoltage13;
|
|
|
|
case 'V': return daVoltage18;
|
|
|
|
case 'A': return daMiniA;
|
|
|
|
case 'B': return daMiniB;
|
2002-12-08 09:55:26 +01:00
|
|
|
case 'W': *CurrentAction = Wait(*CurrentAction); break;
|
|
|
|
case '[': *CurrentAction = Codes(*CurrentAction); return *CurrentAction ? daCodes : daNone;
|
2002-10-06 10:25:42 +02:00
|
|
|
default: return daNone;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return daNone;
|
|
|
|
}
|
|
|
|
|
2008-02-10 14:11:47 +01:00
|
|
|
// --- cDiseqcs --------------------------------------------------------------
|
2002-10-06 10:25:42 +02:00
|
|
|
|
|
|
|
cDiseqcs Diseqcs;
|
|
|
|
|
2011-05-22 10:51:03 +02:00
|
|
|
const cDiseqc *cDiseqcs::Get(int Device, int Source, int Frequency, char Polarization) const
|
2002-10-06 10:25:42 +02:00
|
|
|
{
|
2010-02-06 15:56:01 +01:00
|
|
|
int Devices = 0;
|
2011-05-22 10:51:03 +02:00
|
|
|
for (const cDiseqc *p = First(); p; p = Next(p)) {
|
2010-02-06 15:56:01 +01:00
|
|
|
if (p->Devices()) {
|
|
|
|
Devices = p->Devices();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (Devices && !(Devices & (1 << Device - 1)))
|
|
|
|
continue;
|
2002-10-06 10:25:42 +02:00
|
|
|
if (p->Source() == Source && p->Slof() > Frequency && p->Polarization() == toupper(Polarization))
|
2011-05-21 22:07:08 +02:00
|
|
|
return p;
|
2002-10-06 10:25:42 +02:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|