[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