[mythtv-users] HD-PVR & Live TV

Alan Young ayoung at teleport.com
Tue May 18 18:30:08 UTC 2010


On 05/18/2010 09:26 AM, Joe Friedrich wrote:
> Alan, would you mind sharing your channel change script?  I have a  d-11 stb.
>
>
> Joe Friedrich
>    
Joe,

Sure.  I'm using this with a H20 stb and a usb->serial cable on ttyS0.  
There's two parts.  The first is a bash script.  The script invokes a C 
program to do the channel change and check to verify the channel was 
changed.  I did it in C to keep is small and not have to load a perl or 
python interpreter.   If you need a binary, I can send you mine.

Alan

The shell script:
<<cut here>>
#!/bin/sh
# Get the last channel that was set.  If it's the same just exit.
# Otherwise try to change the channel.
lc="`cat /dev/last_dtv`"
if [ "$lc" -ne "$*" ]; then
/usr/local/bin/change-channel-dtv.bin $*
rc=$?
if [ $rc -eq 0 ]; then
echo $* >/dev/last_dtv
# hdpvr pause
#sleep 2.75
#sleep 1.5
sleep 2.6
else
echo 0 >/dev/last_dtv
fi
exit $rc
fi
<<cut here>>

The C program:
<<cut here>>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>
#include <byteswap.h>

#define _POSIX_SOURCE 1 /* POSIX compliant source */
#define FALSE 0
#define TRUE 1

volatile int STOP=FALSE;
int serport;
struct termios oldtio;


/* Define Command Structures */
struct CommandNoParms{
   unsigned char command_signal_char;
   unsigned char command_ID_char;
};

/* Use the OpenUserChannel command to change channels */
struct OpenUserChannelParms{
   unsigned char command_signal_char;
   unsigned char command_ID_char;
   union {
     unsigned short id;
     unsigned char  idc[2];
   } channel;
   unsigned short subchannel;
};

/* Define command bytes...*/
struct CommandNoParms SetSTBtoStandby        ={0xFA,0x81};

struct CommandNoParms SetSTBtoActive        ={0xFA,0x82};

struct CommandNoParms GetCurrentChannel        ={0xFA,0x87};

struct CommandNoParms GetSignalQuality        ={0xFA,0x90};

struct CommandNoParms GetReturnValueParms    ={0xFA,0x95};

struct CommandNoParms RebootSTB            ={0xFA,0x96};

struct OpenUserChannelParms ChgChannel        ={0xFA,0xa6,0,65535};


int main(int argc, unsigned char *argv[]);
void myexit(unsigned int rc);


int main(int argc, unsigned char *argv[])
{

  struct termios newtio;
  unsigned char digit;
  int c=0, n=0;
  unsigned char retbuffer[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};


  for(c=0;;c++)
  {
   /* get the ASCII digit character */
   digit=argv[1][c];

   if(digit=='-')
   {
    /* not pretty but it works */
    argv[1][c]=0x00;
    c++;
    break;
   }

   /* If it's a null, then its the end of the string. So exit the loop. */
   if(digit==0x00)
    break;
  }

   ChgChannel.channel.id= bswap_16( atoi((unsigned char *) &argv[1][0]) );

   if(digit=='-')
     ChgChannel.subchannel= bswap_16( atoi((unsigned char *) &argv[1][c]) );



  /* Write the string to com port/send to the DirecTV box*/
  /* Baud rate should be set with setserial at bootup */
  /* D1* boxen are 9600 baud.  HD2* boxen are 115200 baud */
  serport = open("/dev/ttyS0", O_RDWR | O_NOCTTY);
  if (serport == -1) {
   perror("Error opening ttyS0");
   exit(1);
  }

  tcgetattr(serport,&oldtio); /* save current port settings */

  bzero(&newtio, sizeof(newtio));
newtio.c_cflag = B9600 | CS8 | CLOCAL | CREAD;
  newtio.c_iflag = IGNPAR;
  newtio.c_oflag = 0;

  /* set input mode (non-canonical, no echo,...) */
  newtio.c_lflag = 0;
  newtio.c_cc[VTIME]    = 0;   /* inter-character timer unused */

  tcflush(serport, TCIFLUSH);

  newtio.c_cc[VMIN]     = 3;   /* blocking read until 3 chars received */
  tcsetattr(serport,TCSANOW,&newtio);


  n = write(serport,&ChgChannel,sizeof(struct OpenUserChannelParms));
  if (n < 0) {
   perror("Could not send change cmd");
   myexit(1);
  }

  while (STOP==FALSE) {            /* loop for input */
    n = read(serport,&retbuffer[0],3);
    if ((retbuffer[2]==0xF4) || (retbuffer[2]==0xF5)) STOP=TRUE;
  }

  if (retbuffer[2]==0xF5) {
   puts("Channel change returned NACK");
   myexit(1);
  }


  newtio.c_cc[VMIN]     = 6;   /* blocking read until 6 chars received */
  tcsetattr(serport,TCSANOW,&newtio);

  // loop and wait for the box to change the channel
  // just keep checking the current channel id for it to change
  c=0;
  while(1) {

    STOP=FALSE;

    n = write(serport,&GetCurrentChannel,sizeof(struct CommandNoParms));
    if (n < 0) {
     perror("Could not send get channel");
     myexit(1);
    }

    while (STOP==FALSE) {            /* loop for input */
      n = read(serport,&retbuffer[0],6);    /* returns after 6 chars 
have been input */

//   printf("%x %x %x %x %x 
%x\n",retbuffer[0],retbuffer[1],retbuffer[2],retbuffer[3],retbuffer[4],retbuffer[5]);

      if ((retbuffer[5]==0xF4) || (retbuffer[5]==0xF5)) STOP=TRUE;
    }

    // If the channel has changed to what we asked for, then exit
    if ((ChgChannel.channel.idc[0]==retbuffer[1]) && 
(ChgChannel.channel.idc[1]==retbuffer[2]))
      break;

    if (c > 25) /* 200ms * 25 = 5000ms / 1000ms = 5 second max wait */
    {
      puts("Timeout waiting for change");
      myexit(1);
    }

    c++;
    usleep(200000);    // 200ms
  }

  myexit(0);
}


void myexit(unsigned int rc){
  tcsetattr(serport,TCSANOW,&oldtio);
  close(serport);
  exit(rc);
}
<<cut here>>





More information about the mythtv-users mailing list