#!/usr/bin/perl -w # Copyright (C) 2001 Neil Cherry # 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # X10Sniffer.pl - Reads serial port and Output 0 & 1's to the screen # # This program reads the data sent from my modified TW523 (could work with an # unmodified but there's not much benefit to that) and my PIC chip. The only # outputs from the PIC chip are the startup message (a '*'), a 1, a 0 # a (^M/0x0D), or a (^J/0x0A). A will be output after the # mTW523 gets 6 idle half cycles at which time it stops sending until a 1 1/2 # bit is received off the power line. # # Date: 07/15/2001 # Neil Cherry (ncherry@linuxha.com) # http://www.linuxha.com/ #use SerialPort; # You'll need the SerialPort.pm ' BEGIN {$Curses::OldCurses = 1;} use Curses; # and also need the Curses.pm use Device::SerialPort qw( :PARAM :STAT 0.07 ); use IO::Select; use Env qw(LINES, COLUMNS); # This will do you no good if it isn't export'd # If $LINE or $COLUMNS has not been exported in shell then we won't see them ' $COLS = ($ENV{'COLUMNS'} || 80); # 80 is a default $LINES = ($ENV{'LINES'} || 24); # 24 is also a default # be nice and clean up on ^C $SIG{'QUIT'} = 'done'; # $fini = 0; ($PortName) = @ARGV or $PortName = "/dev/ttyD1"; # $Ver = "V0.3"; # Subroutines ################################################################ sub done { if ($fini) { clear(); endwin(); $PortObj->close || die "failed to close"; close(rLog); undef $PortObj; } exit(0); } # sub print_raw { local @str = @_; addstr($wRaw, @str); refresh($wRaw); } sub print_main { local @str = @_; addstr($wMain, @str); refresh($wMain); } sub print_cmd { local @str = @_; addstr($wCmd, @str); refresh($wCmd); } #[ Main ]##################################################################### #[ Serial port ]############################################################## select(STDOUT); $| = 1; # Make unbuffered ($a, $b, $name) = split('/', $PortName); #$Configuration_File_Name = "$name.cfg"; $PortObj = new Device::SerialPort ($PortName) || die "Can't open $PortName: $!\n"; ## TIEHANDLE ## #$PortObj = tie (*FH, 'Device::SerialPort', $Configuration_File_Name) || die "Can't tie: $!\n"; $PortObj->stty_icanon(1); $PortObj->user_msg(ON); $PortObj->baudrate(9600); $PortObj->parity("none"); $PortObj->databits(8); $PortObj->stopbits(1); # POSIX does not support 1.5 stopbits $PortObj->handshake("none"); # set parameter $PortObj->debug(0); #$PortObj->save($Configuration_File_Name) || warn "Can't save $Configuration_File_Name: $!\n"; ############################################################################## initscr(); cbreak(); echo(); $fini = 1; clear(); # There are 4 windows, 1) Title 2) Main 3) raw (or Error) 4) Command (CLI) #[ Title Win ]################################################################ $wTitle = subwin( 2, $COLS, 0, 0); scrollok($wTitle, 0); addstr($wTitle, 0, 0, "Starting $Ver"); addstr($wTitle, 0, ($COLS/3)-5 , "X10 Sniffer"); $break = "=" x ($COLS-1); addstr($wTitle, 1, 0 , $break); refresh($wTitle); #[ Main Win ]################################################################# $wMain = subwin( $LINES-19, $COLS, 2, 0); scrollok($wMain, 1); # A simple Box window $bWin = subwin(16, $COLS, $LINES-17, 0); scrollok($bWin, 0); box($bWin, '|', '-'); addstr($bWin, 0, 1, "-[ Raw Data ]-"); refresh($bWin); #[ Raw Win ]################################################################## # Raw (or Error) message window $wRaw = subwin(14, $COLS-2, $LINES-16, 1); scrollok($wRaw, 1); refresh($wRaw); #[ Cmd win ]################################################################## $wCmd = subwin( 1, $COLS, $LINES-1, 0); scrollok($wCmd, 1); ############################################################################## # Get a line # Get a time stamp # print the time stamp and the line ($sec,$min,$hour,$mday) = localtime(time); $buf = "Time started"; $tmp = sprintf("\n%02d %02d:%02d:%02d - %s",$mday,$hour,$min,$sec,$buf); print_main("$tmp"); print_cmd("\nSniffer > "); #($a, $b, $name) = split('/', $PortName); open(rLog, ">>log.raw.$name"); autoflush rLog 1; #[ Main loop ]################################################################ $read_set = new IO::Select; $read_set->add(\*STDIN); # This works just fine. $read_set->add($PortObj->{FD}); # This works but I cna't get it to read! while(1) { ($new_read) = IO::Select->select($read_set, undef, undef, undef); # 0 for polling, undef for blocking foreach $fd (@$new_read) { #[ Serial Port Handler ]############################################## if($fd == $PortObj->{FD}) { # read the serial port # # Below is my old code # # Yikes! This works but it stops the program dead until it # gets it's EOL. # REWRITE! I'll switch this over to a get character routine that # way I can read in one character at a time and format the ouput # nicely. $buf = $PortObj->input; if($buf) { $buf =~ y/\*01//cd; # Eat the ^M^J ($sec,$min,$hour,$mday) = localtime(time); $tmp = sprintf("\n%02d %02d:%02d:%02d - %s",$mday,$hour,$min,$sec,$buf); print rLog "$tmp"; # Print it to the log file print_raw("$tmp"); # Print it to the error messages window (for raw codes) # $output = parse($tmp); # Parse the output and output it's command print_main("$tmp"); # Print it to the main window (for decodes) print_cmd("\nSniffer > "); # and put the cursor back at the CLI prompt. } } #[ STDIN Handler ]#################################################### if($fd == \*STDIN) { # read from the user and act on the commands # Yikes! This works but it stops the program dead until it # gets it's EOL. # REWRITE! I'll switch this to a wgetchar so that it won't hang # the process while blocking. wgetstr($wCmd, $str); $str =~ y/\*[A-z]//cd; # Eat the ^M^J (actually anything not [A-z] if($str) { ($sec,$min,$hour,$mday) = localtime(time); $tmp = sprintf("\n%02d %02d:%02d:%02d - %s\n",$mday,$hour,$min,$sec,$str); #print rLog "$tmp"; # Print it to the log file print_raw("$tmp"); if('Q' eq $str) { done(); } elsif('C' eq $str) { werase($wMain); werase($wRaw); refresh($wMain); refresh($wRaw); } elsif('c' eq $str) { werase($wMain); refresh($wMain); } else { # Error handling } } print_cmd("\nSniffer > "); # and put the cursor back at the CLI prompt. } } } END { if ($fini) { clear(); endwin(); $PortObj->close || die "failed to close"; close(rLog); undef $PortObj; } exit(0); }