#!/usr/bin/perl # Serial loopback tester # # (C) Copyright (C) 2000 # Bill Ryder (bryder@sgi.com) # # 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 will check serial port functionality - you need to have a # loopback plug connected to the serial port. # The one I tested had 2-3, 4-5, 6-20-8-22 use strict; use Fcntl; # # Note you will probably have to run h2ph # cd /usr/include ; h2ph -r -l . use POSIX qw(:termios_h); use IO::Handle; # use Getopt::Std; - Don't like this library require "getopts.pl"; # Command line options my ($verbose, $min_count, $max_count, $tty_dev_name); $verbose = 0; $min_count = 1; $max_count = 256; $tty_dev_name = "/dev/ttyUSB0"; # Used to control serial line discipline et cetera my ($term, $oterm, $noecho, $echo); # Files etc my ($fd_ser); # Temps my ($count_read, $count_towrite); my ($data_read, $data_towrite, $xes, $str_size, $match_failed); # Parse command line options # use strict mandates these definitions use vars qw/ $opt_v $opt_s $opt_e $opt_t /; Getopts('vs:e:t:') || print_usage() ; # man Getopt::Std $verbose = 1 if $opt_v; $min_count = $opt_s if $opt_s; $max_count = $opt_e if $opt_e; $tty_dev_name = $opt_t if $opt_t; if ($max_count > 255) { print "The test will fail (probably) if > 255 bytes is written\n"; print " this is because of the simplistic way the data is read\n"; # If you run with > 255 you will see that the sysread returns less # data then you would expect - but the data is OK - it just doesn't # get returned in the read.n } if ($verbose) { print "Min Count: $min_count, Max Count: $max_count, Device: $tty_dev_name\n"; } sub print_usage() { print "Usage: $0 [-s start bytes] [-e end bytes] [-t ttydevName] -v\n"; print " EG: $0 -s 1 -e 240 -v -t /dev/ttyUSB0\n"; exit(-1); } # Have to turn off echo to make the loopback work sysopen(SER, $tty_dev_name, O_RDWR) || die ("Can't open '$tty_dev_name' - error : $!"); # See perlfaq8 for details on this stuff $fd_ser = fileno(SER); $term = POSIX::Termios->new(); $term->getattr($fd_ser) || die("Failed getattr: $!"); $oterm = $term->getlflag() || die("Failed getlflag: $!"); $echo = ECHO | ECHOK | ICANON; $noecho = $oterm & ~$echo; $term->setlflag($noecho); # Have to have no echo for this to work $term->setcc(VTIME, 0); $term->setattr($fd_ser, TCSANOW) || die "Failed setattr: $!"; my $count ; # will be actual byte count $count = $min_count; while (1 == 1) # Loop exited at the end of the block (see last if) { # Could make this data more rigorous - ie random $xes = 'X' x ($count - 2) ; # The correction is for the start/end bangs if ($count > 2) { $data_towrite = "!$xes!"; } elsif ($count == 2) { $data_towrite = "!!"; } elsif ($count <= 1) { #Zero count still makes one byte $data_towrite = "!"; } $match_failed = 0; $count_towrite = length($data_towrite); $term->setcc(VMIN, $count_towrite); $term->setattr($fd_ser, TCSANOW) || die "Failed setattr: $!"; syswrite(SER,$data_towrite,$count_towrite) || die("Failed to write: $!"); $count_read = sysread(SER,$data_read,$count_towrite); print "count: $count, bytes read: $count_read\n"; if ($count_towrite != $count_read) { print "Lengths don't match, Wrote: $count_towrite bytes Read: ", length($data_read), " bytes \n"; } if ( $data_towrite eq $data_read) { $verbose && print "MATCH OK\n"; } else { print "ERROR - NON MATCH \n"; $match_failed = 1; } ( $verbose || $match_failed ) && print "\tWrote: '$data_towrite'\n"; ( $verbose || $match_failed ) && print "\t Read: '$data_read'\n"; $count++; last if ( $count > $max_count); }