[mythtv-users] Re: add skybox to my MythTV system

Neil Bird neil at fnxweb.com
Tue Aug 9 11:09:12 UTC 2005


Around about 09/08/05 02:29, Craig Tinson typed ...
> I use redeye serial too.. but with a *very* simple one line bash 
> script.. would be interested in what you've done with redeye.c and the 
> script too..

   Okey-doke.  I make no pretention that I'm the original author/modifier! 
The 'digibox.c' [née red_eye.c] and its Makefile I purloined from somewhere 
and then fine-tuned to speed it up (near-instant channel changes now).

   The skychannel bash script (which does the deed from Myth & uses digibox) 
is pretty much my own, but with some file-locking thrown in.  I did purloin 
the file locking originally, but I think I completely re-wrote the mechanism 
after a while.


   usage: skychannel <channum>    [100 <= channum <= 999]

   Copes with turning on the digibox if its off, and also (as it's once 
happened to me while I was hammering another remote at the exact same time the 
script ran) tries turning it on a second time in case the first power-on got 
missed.

   Also blats the zap-banner upon channel change (as Myth provides one).

   [don't forget Sky now has a setup option to timeout the little red dot 
interactive logo things]

   Also hangs about for a little over 4 hours and turns the box off (unless 
called again in the meantime) to 'reduce' power and ensure the box gets resets 
to cope with S/W updates, etc.  It's a timeout as I couldn't easily tell when 
progs. finished and deserved a power-off.  4 hours seemed enough (if you think 
you'll record individual progs. longer that that, change the timeout).

-- 
[neil at fnx ~]# rm -f .signature
[neil at fnx ~]# ls -l .signature
ls: .signature: No such file or directory
[neil at fnx ~]# exit
-------------- next part --------------
#include <unistd.h>
#include <stdio.h>		/* Standard input/output definitions */
#include <string.h>		/* String function definitions */
#include <unistd.h>		/* UNIX standard function definitions */
#include <fcntl.h>		/* File control definitions */
#include <errno.h>		/* Error number definitions */
#include <asm/ioctls.h>
#include <asm/termios.h>	/* POSIX terminal control definitions */
#include <time.h>

#ifndef COM_PORT
# define COM_PORT		"/dev/ttyS0"
#endif

#ifndef WAIT_TIME
# define WAIT_TIME		2
#endif

#ifndef DEBUG
# define DEBUG			0
#endif

static int debug = DEBUG;

/* the "RTS" line is actually the DTR line in linux */
#ifdef linux
# define BIT_TO_TWIDDLE		TIOCM_DTR
#else
# define BIT_TO_TWIDDLE		TIOCM_RTS
#endif

/*
 * open_port() - Open serial port
 * returns the file descriptor on success or -1 on error
 */
int open_port(char *com_port)
{
  int fd;			/* file descriptor for the port */
  struct termios options;

  fd = open (com_port, O_WRONLY | O_NOCTTY | O_NDELAY);
  if (fd == -1)
  {
    /* Could not open the port. */
    perror ("open_port(): unable to open com port");
    exit (-1);
  }
  else
  {
    fcntl (fd, F_SETFL, 0);
  }

  /* get the current options for the port */
  tcgetattr (fd, &options);

  /* Set the baud rates to 9600 */
  cfsetispeed (&options, B9600);
  cfsetospeed (&options, B9600);

  /* 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);

  /* set the new options for the port */
  tcsetattr (fd, TCSANOW, &options);
  return (fd);
}

void set_rts(int fd)
{
  int status;
  int bitset = BIT_TO_TWIDDLE;
  ioctl (fd, TIOCMGET, &status);
  if (debug)
  {
    if (status & bitset)
    {
      printf("RTS bit is set\n");
    }
    else
    {
      printf("RTS bit is unset\n");
    }
  }
  status |= bitset;
  ioctl (fd, TIOCMSET, &status);
  ioctl (fd, TIOCMGET, &status);
  if (status & bitset)
  {
    if (debug) printf("RTS bit set ok\n");
  }
  else
  {
    perror("set_rts(): failed to set RTS bit");
    exit(-1);
  }
}

int main (int argc, char **argv)
{
  int fd;
  char *com_port = COM_PORT;
  int n;
  char *data;
  int wait_time = WAIT_TIME;

  if (argc == 1 || argc > 4)
  {
      printf("usage: digibox codestring [waittime [device]]\n");
      return -1;
  }

  data = argv[1];
  if (argc > 2)
      wait_time = atoi(argv[2]);
  if (argc > 3)
      com_port = argv[3];

  if (debug) printf("opening port for %s and setting RTS\n", com_port);
  fd = open_port(com_port);
  set_rts (fd);

  /* needed to power up the IR system */
  {
    int done = 0;
    struct timespec poweruptime;
    poweruptime.tv_sec = 0;
    poweruptime.tv_nsec = 20000000;
    while (!done)
    {
      int status = nanosleep(&poweruptime,&poweruptime);
      if (status == 0)
      {
        done = 1;
      }
      else if (status == -1)
      {
        if (errno != EINTR)
        {
          sleep(1);
          done = 1;
        }
      }
    }
  }

  if (debug) printf("writing data (\"%s\") now\n",data);
  n = write (fd, data, strlen (data));
  if (n < 0)
  {
    perror("main(): write failed");
    exit(-1);
  }
  if (debug) printf("data written\n");
  tcdrain (fd);
  if (wait_time > 0)
  {
    if (debug) printf("sleeping for %d seconds\n",wait_time);
    sleep (wait_time);
  }
  if (debug) printf("start close\n");
  close (fd);
  if (debug) printf("finished\n");

  return 0;
}
-------------- next part --------------
#
# Makefile to build digibox interface
#

#
# where to install binary
#
INSTALLDIR=/usr/local/bin

#
# which serial port the device is connected to
#
COM_PORT=\"/dev/ttyS0\"

#
# seconds to wait after sending the command before finishing
# see comment about about milliseconds
#
WAIT_TIME=2

#
# this should be fairly obvious!
# do you want debugging output
# 0=none, 1=some
#
DEBUG=0

CFLAGS=-DCOM_PORT=${COM_PORT} -DWAIT_TIME=${WAIT_TIME} -DDEBUG=${DEBUG}

all: digibox

digibox: digibox.o
	cc -o digibox digibox.o

install: digibox
	install digibox ${INSTALLDIR}

clean:
	rm digibox.o
-------------- next part --------------
#!/bin/bash

# Debug
##exec 1>/tmp/skychannel.dbg
##exec 2>&1
##set -x -v
##chmod a+rw /tmp/skychannel


# Locking functions
LOCKFILE=/tmp/skychannel.lock

function locksc()  {
    if lockfile -1 -r 10 $LOCKFILE >/dev/null 2>&1;  then
        return 0
    else
        exit 1
    fi
}

function unlocksc()  {
    rm -f $LOCKFILE >/dev/null 2>&1;
}


# Exit if no args.
[ -z "$1" ] && exit 1

# Jump into b/g for Myth
(
    subpid=$!

    STAT=/tmp/skychannel
    PATH=${PATH}:/usr/local/bin


    # Turn off?
    if [ "$1" = "off" ]; then

        # Wait 4 mins., then find out time
        sleep $((4*30))
        now=`date '+%s'`

        # Get last channel-change
        locksc
        . $STAT
        echo "$2" > /tmp/skychannel-off

        # Is it more than 25 mins, ago?
        # TBD

        unlocksc


    # Cope with Sky channels
    elif [ $1 -ge 100 -a $1 -lt 1000 ]; then

        # Break down channel digits
        channel=`printf '%03d' $1`
        chno=$channel
        d1=$((chno/100))
        chno=$(( chno-(d1*100) ))
        d2=$((chno/10))
        chno=$(( chno-(d2*10) ))
        d3=$chno

        # Assert ownership
        locksc
        [ -f $STAT ] && . $STAT
        echo -e "SCPID=$subpid\nSCCHAN=$channel\nSCTIME=`date '+%s'`" > $STAT

        # Kill previous script
        [ "$SCPID" != ""  -a  -d /proc/$SCPID ]  &&  kill -9 $SCPID >/dev/null 2>&1

        # Change channel, or power up
        digibox "${d1}${d2}${d3}KT"
        unlocksc

        # Wait a bit then check to see if we've been called since
        sleep 1
        locksc
        . $STAT
        # Called again since?
        if [ $SCPID -ne $subpid ]; then
            # Yep;  abort
            unlocksc
            exit 0
        fi

        # Nope, our channel still stands (also try powering up again just in case last code got missed)
        digibox "K${d1}${d2}${d3}KT"
        unlocksc

        # Wait a bit more then check to see if we've been called since
        sleep 5
        locksc
        . $STAT
        # Called again since?
        if [ $SCPID -ne $subpid ]; then
            # Yep;  abort
            unlocksc
            exit 0
        fi

        # Nope, our channel still stands
        digibox "K${d1}${d2}${d3}K"
        unlocksc

        # Turn off in 4:05
        sleep $((4*60*60+5*60))
        locksc
        . $STAT
        # Called again since?
        if [ $SCPID -eq $subpid ]; then
            # Nope;  turn off box (4 s. sequence)
            digibox 'T!!!!K!!!!P' 4
        fi
        unlocksc
    fi
) &

# vim: set et sts=4 ts=4 sw=4 ai :


More information about the mythtv-users mailing list