Red eye
Note: The correct title of this article is red_eye. It appears incorrectly here due to technical restrictions.
| Author | Michael Thomson |
| Description | Linux driver for Red-Eye Serial, a serial remote control interface for Pace(r) Digital Cable Receivers. |
| Supports |
Linux driver for Red-Eye Serial: A serial remote control interface for Pace(r) Digital Cable Receivers
Contents |
Introduction
White Wing Logic make a serial-controlled IR transmitter for controlling Pace(r) digital cable receivers as used by some CableTV companies in the UK (notably Telewest).
The original software for Linux was written by Malcolm Smith and was distributed from the website with no copyright, license or attribution.
I decided to rework the code to compile under GCC 4.x and a 2.6 kernel. in the process I added some debug control to the original, and a little argv handling, though very fragile.
I have offered this code to White Wing Logic and also to the MythTV project in the hope that others find it useful.
Installation
Compile the source
$ gcc -o red_eye red_eye.c
Copy to bin directory and set permissions
$ cp ./red_eye /usr/local/bin/red_eye
$ chown root:root /usr/local/bin/red_eye
$ chmod 0555 /usr/local/bin/red_eye
Test the binary
$ red_eye
usage: red_eye deviceComPort sendString waitSecs [debug]
-or- red_eye sendString [debug]
where deviceComPort is e.g. /dev/ttyS0
sendString is your desired command to the RedEye Serial
waitSecs is pause time after command (in seconds 0-9)
debug is debug level (0=off, 9=max)
$ red_eye 101 2
Opening port for /dev/ttyS0
Entering function open_port()
Opening port...
Opening port succeeded!
Setting file options...
Setting file options suceeded!
Getting current options for the port...
Getting current options for the port succeeded!
Setting baud rates for the port...
Setting baud rates for the port succeeded!
Setting local mode...
Setting local mode suceeded!
Leaving function open_port()
Setting RTS for /dev/ttyS0
Entering function set_rts()
Checking current state of RTS line...
RTS bit is set
Checking current state of RTS line suceeded
Setting RTS line...
Setting RTS line succeeded
Checking new state of RTS line...
RTS bit was set correctly
Checking new state of RTS line suceeded
Leaving function set_rts()
Pausing for 2 seconds to allow IR system to power up
Writing data ("101") now
Writing data suceeded
Sleeping for 1 seconds ....
Start close... finished
$ echo $?
0
$ red_eye 101
$ echo $?
0
Contacts
White Wing Logic
http://www.whitewing.co.uk/ Mike Harrison ( info a whitewing co uk ) http://www.redremote.co.uk/ info a redremote d co d uk
Red-Eye Serial
http://www.redremote.co.uk/serial/
Current code
This program was rewritten by Michael Thomson
( redeye a m-thomson d net )
Original code
This program is based on red_eye.c by Malcolm Smith,
distributed with no copyright or license from:
http://www.redremote.co.uk/serial/resdown.html
The original software may still be available from:
http://www.redremote.co.uk/serial/red_eye.tgz
License
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
The Code
/* === === === === === === === === === === === === === === === === === === ===
*
* Copyright (C) 2006 Michael Thomson ( redeye a m-thomson d net )
*
* Based on red_eye.c by Malcolm Smith distributed with no copyright or license
* from http://www.redremote.co.uk/serial/resdown.html
*
* The original software may still be available from:
* http://www.redremote.co.uk/serial/red_eye.tgz
*
* This version was modified to compile under gcc 4.x on Fedora Core 4, other
* platforms may also work. Additional debugging controls were added.
*
* === === === === === === === === === === === === === === === === === === ===
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
*
* === === === === === === === === === === === === === === === === === === ===
*/
#include <stdlib.h> /* standard library definitions */
#include <stdio.h> /* standard buffered input/output */
#include <fcntl.h> /* file control options */
#include <unistd.h> /* standard symbolic constants and types */
#include <termios.h> /* define values for termios */
#include <sys/ioctl.h> /* define values for ioctl operations */
#include <string.h> /* string operations */
#define COM_PORT "/dev/ttyS0";
/* default port, can be overridden in arguments */
int debug = 0; /* global debug level */
int open_port(char * com_port) {
int fd;
int err;
struct termios options;
if ( debug >= 1 ) {
printf("Entering function open_port()\n");
}
if ( debug >= 2 ) {
printf(" Opening port...\n");
}
fd = open(com_port, O_WRONLY | O_NOCTTY | O_NDELAY);
if ( fd == -1 ) {
perror(" open: Unable to open com port - ");
exit(EXIT_FAILURE);
}
if ( debug >= 2 ) {
printf(" Opening port succeeded!\n");
printf(" Setting file options...\n");
}
err = fcntl(fd, F_SETFL, 0);
if ( err != 0 ) {
perror(" fcntl: Setting file options failed - ");
exit(EXIT_FAILURE);
}
if ( debug >= 2 ) {
printf(" Setting file options succeeded!\n");
printf(" Getting current options for the port...\n");
}
err = tcgetattr(fd, &options);
if ( err != 0 ) {
perror(" tcgetattr: Getting file options failed - ");
exit(EXIT_FAILURE);
}
if ( debug >= 2 ) {
printf(" Getting current options for the port succeeded!\n");
printf(" Setting baud rates for the port...\n");
}
err = cfsetispeed(&options, B9600);
if ( err != 0 ) {
perror(" cfsetispeed: Setting input baud rate failed - ");
exit(EXIT_FAILURE);
}
err = cfsetospeed(&options, B9600);
if ( err != 0 ) {
perror(" cfsetospeed: Setting output baud rate failed - ");
exit(EXIT_FAILURE);
}
if ( debug >= 2 ) {
printf(" Setting baud rates for the port succeeded!\n");
printf(" Setting local mode...\n");
}
/* Enable the receiver and set local mode... */
options.c_cflag |= (CLOCAL );
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
options.c_cflag &= ~CREAD;
options.c_cflag &= ~CRTSCTS;
options.c_iflag &= ~(IXON | IXOFF | IXANY);
err = tcsetattr(fd, TCSANOW, &options);
if ( err != 0 ) {
perror(" tcsetattr: Setting local mode failed - ");
exit(EXIT_FAILURE);
}
if ( debug >= 2 ) {
printf(" Setting local mode succeeded!\n");
}
if ( debug >= 1 ) {
printf("Leaving function open_port()\n");
}
return(fd);
}
void set_rts(int fd) {
/* It appears that the "RTS" line is actually the DTR line in Linux!!! */
int bitset = TIOCM_DTR;
int status;
int err;
if ( debug >= 1 ) {
printf("Entering function set_rts()\n");
}
if ( debug >= 2 ) {
printf(" Checking current state of RTS line...\n");
}
err = ioctl(fd, TIOCMGET, &status);
if ( err != 0 ) {
perror(" ioctl: Checking RTS line failed - ");
exit(EXIT_FAILURE);
}
if ( debug >= 2 ) {
if ( status & bitset ) {
printf(" RTS bit is set \n");
} else {
printf(" RTS bit is unset\n");
}
printf(" Checking current state of RTS line succeeded\n");
printf(" Setting RTS line...\n");
}
status |= bitset;
err = ioctl(fd, TIOCMSET, &status);
if ( err != 0 ) {
perror(" ioctl: Setting RTS line failed - ");
exit(EXIT_FAILURE);
}
if ( debug >= 2 ) {
printf(" Setting RTS line succeeded\n");
printf(" Checking new state of RTS line...\n");
}
err = ioctl(fd, TIOCMGET, &status);
if ( err != 0 ) {
perror(" ioctl: Checking RTS line failed - ");
exit(EXIT_FAILURE);
}
if ( debug >= 2 ) {
if ( status & bitset ) {
printf(" RTS bit was set correctly \n");
} else {
printf(" FAILED to set RTS bit\n");
exit(EXIT_FAILURE);
}
printf(" Checking new state of RTS line succeeded\n");
}
if ( debug >= 1 ) {
printf("Leaving function set_rts()\n");
}
}
int main (int argc, char **argv) {
int fd; /* File descriptor for access to serial port */
char *com_port = COM_PORT;
char *data;
char *message;
int wait_time;
int n;
debug = 0;
/* Very crude argv / argc handling as yet */
switch (argc) {
case 5: {
com_port = argv[1];
data = argv[2];
wait_time = atoi(argv[3]);
debug = atoi(argv[4]);
break;
};
case 4: {
com_port = argv[1];
data = argv[2];
wait_time = atoi(argv[3]);
break;
};
case 3: {
com_port = COM_PORT;
data = argv[1];
debug = atoi(argv[2]);
wait_time = 1;
break;
};
case 2: {
com_port = COM_PORT;
data = argv[1];
wait_time = 1;
break;
};
default: {
fputs("usage: red_eye deviceComPort sendString waitSecs [debug]\n",stderr);
fputs(" -or- red_eye sendString [debug]\n",stderr);
fputs("\n",stderr);
fputs(" where deviceComPort is e.g. /dev/ttyS0\n",stderr);
fputs(" sendString is your desired command to the RedEye Serial\n",stderr);
fputs(" waitSecs is pause time after command (in seconds 0-9)\n",stderr);
fputs(" debug is debug level (0=off, 9=max)\n",stderr);
exit(EXIT_FAILURE);
};
}
if ( 0 > wait_time ) wait_time = 0;
if ( 9 < wait_time ) wait_time = 9;
if ( 0 > debug ) debug = 0;
if ( 9 < debug ) debug = 9;
if ( debug >= 1 ) {
printf("Opening port for %s\n", com_port);
}
fd = open_port(com_port) ;
if ( debug >= 1 ) {
printf("Setting RTS for %s\n", com_port);
}
set_rts(fd);
if ( debug >= 1 ) {
printf("Pausing for 2 seconds to allow IR system to power up\n");
}
sleep(2);
if ( debug >= 1 ) {
printf("Writing data (\"%s\") now\n",data);
}
n = write(fd, strcat(data,"O"), strlen(data)+1);
if (n < 0) {
perror(" write: Writing data failed - ");
exit(EXIT_FAILURE);
}
if ( debug >= 1 ) {
printf("Writing data succeeded\n");
}
tcdrain(fd);
if ( debug >= 1 ) {
printf("Sleeping for %d seconds ....\n",wait_time);
}
sleep(wait_time);
if ( debug >= 1 ) {
printf("Start close... ");
}
close(fd);
if ( debug >= 1 ) {
printf("finished\n");
}
exit(EXIT_SUCCESS);
}