#!/usr/bin/perl # channel.pl - Version 1.1 (March 18, 2004) # Channel changing script for RCA DSS units via the serial port. # By William Munson [wmunson@rochester.rr.com] # Based on pieces pulled from various other DSS control scripts. # # This script accepts a 1 or more digit channel number on the command line # or a single key command which must be defined in the keymap. The program also # accepts the command 'macro' which is detailed later in the script. # # I take no responsibility for any damage this script might cause. # Feel free to modify and redistribute this as you see fit, but please retain # these comments. # # Version 1.0 - First working version. Only supports channel change commands via # channel number on the command line. # # Version 1.1 - Added support for commands other than a simple channel number. # Also added support for a macro command. For example this could be used # to send the keystrokes to buy a ppv if you associate the macro with a remote key. $|=1; use POSIX qw(:termios_h); use FileHandle; # Use verbose output mode for debugging. $verbose=0; # Time delay between each channel digit when a channel number is entered. $inter_digit_delay=0.25; # Enable to clear the on screen display more quickly. # Warning: This slows down channel scrolling so use browse mode # for best results or leave it disabled if you want snappier channel # changes and can put up with the on screen display. $quick_clear=1; %pkt_decode=("0xF0" => "START PKT", "0xF1" => "ERR 1", "0xF2" => "GOT EXTENDED", "0xF4" => "END PKT", "0xF5" => "ERR 2", "0xFB" => "PROMPT"); %terminal=("0xF1" => -1, "0xF4" => 1, "0xF5" => -1); %keymap=(right => "0x9a", left => "0x9b", up => "0x9c", down => "0x9d", favorite => "0x9e", select => "0xc3", exit => "0xc5", 9 => "0xc6", 8 => "0xc7", 7 => "0xc8", 6 => "0xc9", 5 => "0xca", 4 => "0xcb", 3 => "0xcc", 2 => "0xcd", 1 => "0xce", 0 => "0xcf", ch_up => "0xd2", ch_dn => "0xd3", power => "0xd5", jump => "0xd8", guide => "0xe5", clear => "0xf9", menu => "0xf7"); # Variables used to process the channel number command line. $position=0; $digit=""; # Start of main code. $cmd_line_input=@ARGV[0]; # Defaults to standard COM1 port, 9600 baud. my $serial=init_serial("/dev/ttyS0","9600"); # Start of command decoding if (length($cmd_line_input)) { # Check to see if a channel number was entered. if ($cmd_line_input != 0) { change_channel($cmd_line_input); exit; } if ($cmd_line_input eq "macro") { # Do macro commands. Use your own key sequence here. # Macro usage example:"/channel.pl macro" # on the config line passed to irexec in your .lircrc file. # select,menu,menu,etc., are the actual buttons that would # need to be pressed in order to buy a PPV movie. The # names of these buttons are used as examples. Please # tailor to your needs. The actual number of key sequences # may vary depending on your model receiver. dss_key("select"); sleep(1.0); dss_key("menu"); sleep(1.0); dss_key("menu"); exit; } # No special processing required. Send a single command. dss_key($cmd_line_input); } else { print "You must enter a command for this script to work.\n"; } # begin subroutines. sub change_channel { # Send a serial command for each digit of the channel number my ($channel_num)=@_; if ($verbose){ print "Channel number: "; print $channel_num; print "\n"; } while ($position 8); next if $str eq "0x00"; if ($pkt_decode{$str}) { print $str if ($verbose); print "[$pkt_decode{$str}] " if ($verbose); } else { $_=$str; s/^0x//g; $_=hex($_); printf("$str(%3.3s) ",$_) if ($verbose); push (@ret,$_); } $ok=1 if ($terminal{$str} > 0); last if ($terminal{$str}); last if ($last eq "0xFB" && $str eq "0xFB"); $last=$str; } print "\n\n" if ($verbose); return @ret if ($ok); return undef; } sub init_serial { my($port,$baud)=@_; my($termios,$cflag,$lflag,$iflag,$oflag); my($voice); my $serial=new FileHandle("+>$port") || die "Could not open $port: $!\n"; $termios = POSIX::Termios->new(); $termios->getattr($serial->fileno()) || die "getattr: $!\n"; $cflag= 0 | CS8 | HUPCL | CREAD | CLOCAL; $lflag= 0; $iflag= 0 | IGNBRK | IGNPAR | IXON | IXOFF; $oflag= 0; $termios->setcflag($cflag); $termios->setlflag($lflag); $termios->setiflag($iflag); $termios->setoflag($oflag); $termios->setattr($serial->fileno(),TCSANOW) || die "setattr: $!\n"; eval qq[ \$termios->setospeed(POSIX::B$baud) || die "setospeed: \$!\n"; \$termios->setispeed(POSIX::B$baud) || die "setispeed: \$!\n"; ]; die $@ if $@; $termios->setattr($serial->fileno(),TCSANOW) || die "setattr: $!\n"; # This gets rid of all the special characters.. $termios->getattr($serial->fileno()) || die "getattr: $!\n"; for (0..NCCS) { if ($_ == NCCS) { last; } # Dont mess up XON/XOFF.. if ($_ == VSTART || $_ == VSTOP) { next; } $termios->setcc($_,0); } $termios->setattr($serial->fileno(),TCSANOW) || die "setattr: $!\n"; return $serial; }