Fixed the RCU remote control handling to avoid problems with NPTL

This commit is contained in:
Klaus Schmidinger 2005-12-16 14:53:58 +01:00
parent 72759ed131
commit db35165e25
4 changed files with 59 additions and 50 deletions

View File

@ -310,6 +310,7 @@ Andreas Share <a.share@t-online.de>
for his support in keeping the Premiere World channels up to date in 'channels.conf' for his support in keeping the Premiere World channels up to date in 'channels.conf'
for pointing out that section filters should only be set if the device actually has for pointing out that section filters should only be set if the device actually has
a lock a lock
for reporting a lockup with the RCU on NPTL systems
Simon Bauschulte <SemiSchwabe@Brutzel.de> Simon Bauschulte <SemiSchwabe@Brutzel.de>
for his support in keeping the Premiere World channels up to date in 'channels.conf' for his support in keeping the Premiere World channels up to date in 'channels.conf'

View File

@ -3963,7 +3963,7 @@ Video Disk Recorder Revision History
commands may now be executed at any time, and the message will be displayed commands may now be executed at any time, and the message will be displayed
(no more "pending message"). (no more "pending message").
2005-12-11: Version 1.3.38 2005-12-16: Version 1.3.38
- Fixed handling second audio and Dolby Digital PIDs for encrypted channels - Fixed handling second audio and Dolby Digital PIDs for encrypted channels
(was broken in version 1.3.37). (was broken in version 1.3.37).
@ -3974,3 +3974,5 @@ Video Disk Recorder Revision History
- Limited the frequency of log messages from the cRepackers. - Limited the frequency of log messages from the cRepackers.
- Now using the gettid() syscall to get a thread's pid, so that we get a - Now using the gettid() syscall to get a thread's pid, so that we get a
useful value on NPTL systems (suggested by Johannes Stezenbach). useful value on NPTL systems (suggested by Johannes Stezenbach).
- Fixed the RCU remote control handling to avoid problems with NPTL (thanks
to Andreas Share for reporting a lockup with the RCU on NPTL systems).

88
rcu.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: rcu.c 1.10 2005/08/15 12:30:21 kls Exp $ * $Id: rcu.c 1.11 2005/12/16 14:43:37 kls Exp $
*/ */
#include "rcu.h" #include "rcu.h"
@ -23,8 +23,8 @@ cRcuRemote::cRcuRemote(const char *DeviceName)
dp = 0; dp = 0;
mode = modeB; mode = modeB;
code = 0; code = 0;
numberToSend = -1; number = 0;
lastNumber = 0; data = 0;
receivedCommand = false; receivedCommand = false;
if ((f = open(DeviceName, O_RDWR | O_NONBLOCK)) >= 0) { if ((f = open(DeviceName, O_RDWR | O_NONBLOCK)) >= 0) {
struct termios t; struct termios t;
@ -32,7 +32,7 @@ cRcuRemote::cRcuRemote(const char *DeviceName)
cfsetspeed(&t, B9600); cfsetspeed(&t, B9600);
cfmakeraw(&t); cfmakeraw(&t);
if (tcsetattr(f, TCSAFLUSH, &t) == 0) { if (tcsetattr(f, TCSAFLUSH, &t) == 0) {
Number(0);//XXX 8888??? SetNumber(8888);
const char *Setup = GetSetup(); const char *Setup = GetSetup();
if (Setup) { if (Setup) {
code = *Setup; code = *Setup;
@ -95,13 +95,12 @@ void cRcuRemote::Action(void)
time_t LastCodeRefresh = 0; time_t LastCodeRefresh = 0;
cTimeMs FirstTime; cTimeMs FirstTime;
unsigned char LastCode = 0, LastMode = 0;
uint64 LastCommand = 0; uint64 LastCommand = 0;
unsigned int LastData = 0;
bool repeat = false; bool repeat = false;
while (Running() && f >= 0) { while (Running() && f >= 0) {
LOCK_THREAD;
if (ReceiveByte(REPEATLIMIT) == 'X') { if (ReceiveByte(REPEATLIMIT) == 'X') {
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
int b = ReceiveByte(); int b = ReceiveByte();
@ -140,11 +139,22 @@ void cRcuRemote::Action(void)
LastCommand = 0; LastCommand = 0;
} }
else { else {
LastCommand = 0; unsigned int d = data;
if (numberToSend >= 0) { if (d != LastData) {
Number(numberToSend); SendData(d);
numberToSend = -1; LastData = d;
} }
unsigned char c = code;
if (c != LastCode) {
SendCommand(c);
LastCode = c;
}
unsigned char m = mode;
if (m != LastMode) {
SendCommand(m);
LastMode = m;
}
LastCommand = 0;
} }
if (code && time(NULL) - LastCodeRefresh > 60) { if (code && time(NULL) - LastCodeRefresh > 60) {
SendCommand(code); // in case the PIC listens to the wrong code SendCommand(code); // in case the PIC listens to the wrong code
@ -192,8 +202,6 @@ bool cRcuRemote::SendByteHandshake(unsigned char c)
bool cRcuRemote::SendByte(unsigned char c) bool cRcuRemote::SendByte(unsigned char c)
{ {
LOCK_THREAD;
for (int retry = 5; retry--;) { for (int retry = 5; retry--;) {
if (SendByteHandshake(c)) if (SendByteHandshake(c))
return true; return true;
@ -201,16 +209,24 @@ bool cRcuRemote::SendByte(unsigned char c)
return false; return false;
} }
bool cRcuRemote::SetCode(unsigned char Code) bool cRcuRemote::SendData(unsigned int n)
{ {
code = Code; for (int i = 0; i < 4; i++) {
return SendCommand(code); if (!SendByte(n & 0x7F))
return false;
n >>= 8;
}
return SendCommand(mode);
} }
bool cRcuRemote::SetMode(unsigned char Mode) void cRcuRemote::SetCode(unsigned char Code)
{
code = Code;
}
void cRcuRemote::SetMode(unsigned char Mode)
{ {
mode = Mode; mode = Mode;
return SendCommand(mode);
} }
bool cRcuRemote::SendCommand(unsigned char Cmd) bool cRcuRemote::SendCommand(unsigned char Cmd)
@ -218,15 +234,9 @@ bool cRcuRemote::SendCommand(unsigned char Cmd)
return SendByte(Cmd | 0x80); return SendByte(Cmd | 0x80);
} }
bool cRcuRemote::Digit(int n, int v) void cRcuRemote::SetNumber(int n, bool Hex)
{
return SendByte(((n & 0x03) << 5) | (v & 0x0F) | (((dp >> n) & 0x01) << 4));
}
bool cRcuRemote::Number(int n, bool Hex)
{ {
LOCK_THREAD; number = n;
if (!Hex) { if (!Hex) {
char buf[8]; char buf[8];
sprintf(buf, "%4d", n & 0xFFFF); sprintf(buf, "%4d", n & 0xFFFF);
@ -237,19 +247,17 @@ bool cRcuRemote::Number(int n, bool Hex)
n = (n << 4) | ((*d - '0') & 0x0F); n = (n << 4) | ((*d - '0') & 0x0F);
} }
} }
lastNumber = n; unsigned int m = 0;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
if (!Digit(i, n)) m <<= 8;
return false; m |= ((i & 0x03) << 5) | (n & 0x0F) | (((dp >> i) & 0x01) << 4);
n >>= 4; n >>= 4;
} }
return SendCommand(mode); data = m;
} }
bool cRcuRemote::String(char *s) void cRcuRemote::SetString(char *s)
{ {
LOCK_THREAD;
const char *chars = mode == modeH ? "0123456789ABCDEF" : "0123456789-EHLP "; const char *chars = mode == modeH ? "0123456789ABCDEF" : "0123456789-EHLP ";
int n = 0; int n = 0;
@ -262,7 +270,7 @@ bool cRcuRemote::String(char *s)
} }
} }
} }
return Number(n, true); SetNumber(n, true);
} }
void cRcuRemote::SetPoints(unsigned char Dp, bool On) void cRcuRemote::SetPoints(unsigned char Dp, bool On)
@ -271,7 +279,7 @@ void cRcuRemote::SetPoints(unsigned char Dp, bool On)
dp |= Dp; dp |= Dp;
else else
dp &= ~Dp; dp &= ~Dp;
Number(lastNumber, true); SetNumber(number);
} }
bool cRcuRemote::DetectCode(unsigned char *Code) bool cRcuRemote::DetectCode(unsigned char *Code)
@ -291,12 +299,12 @@ bool cRcuRemote::DetectCode(unsigned char *Code)
SetMode(modeH); SetMode(modeH);
char buf[5]; char buf[5];
sprintf(buf, "C0D%c", *Code); sprintf(buf, "C0D%c", *Code);
String(buf); SetString(buf);
SetCode(*Code); SetCode(*Code);
cCondWait::SleepMs(2 * REPEATDELAY); cCondWait::SleepMs(2 * REPEATDELAY);
if (receivedCommand) { if (receivedCommand) {
SetMode(modeB); SetMode(modeB);
String("----"); SetString("----");
return true; return true;
} }
if (*Code < 'D') { if (*Code < 'D') {
@ -310,10 +318,8 @@ bool cRcuRemote::DetectCode(unsigned char *Code)
void cRcuRemote::ChannelSwitch(const cDevice *Device, int ChannelNumber) void cRcuRemote::ChannelSwitch(const cDevice *Device, int ChannelNumber)
{ {
if (ChannelNumber && Device->IsPrimaryDevice()) { if (ChannelNumber && Device->IsPrimaryDevice())
LOCK_THREAD; SetNumber(cDevice::CurrentChannel());
numberToSend = cDevice::CurrentChannel();
}
} }
void cRcuRemote::Recording(const cDevice *Device, const char *Name) void cRcuRemote::Recording(const cDevice *Device, const char *Name)

16
rcu.h
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: rcu.h 1.4 2005/07/31 10:18:00 kls Exp $ * $Id: rcu.h 1.5 2005/12/16 14:21:20 kls Exp $
*/ */
#ifndef __RCU_H #ifndef __RCU_H
@ -19,19 +19,19 @@ private:
enum { modeH = 'h', modeB = 'b', modeS = 's' }; enum { modeH = 'h', modeB = 'b', modeS = 's' };
int f; int f;
unsigned char dp, code, mode; unsigned char dp, code, mode;
int numberToSend; int number;
int lastNumber; unsigned int data;
bool receivedCommand; bool receivedCommand;
bool SendCommand(unsigned char Cmd); bool SendCommand(unsigned char Cmd);
int ReceiveByte(int TimeoutMs = 0); int ReceiveByte(int TimeoutMs = 0);
bool SendByteHandshake(unsigned char c); bool SendByteHandshake(unsigned char c);
bool SendByte(unsigned char c); bool SendByte(unsigned char c);
bool Digit(int n, int v); bool SendData(unsigned int n);
bool SetCode(unsigned char Code); void SetCode(unsigned char Code);
bool SetMode(unsigned char Mode); void SetMode(unsigned char Mode);
bool Number(int n, bool Hex = false); void SetNumber(int n, bool Hex = false);
void SetPoints(unsigned char Dp, bool On); void SetPoints(unsigned char Dp, bool On);
bool String(char *s); void SetString(char *s);
bool DetectCode(unsigned char *Code); bool DetectCode(unsigned char *Code);
virtual void Action(void); virtual void Action(void);
virtual void ChannelSwitch(const cDevice *Device, int ChannelNumber); virtual void ChannelSwitch(const cDevice *Device, int ChannelNumber);