use strict;
use warnings;
use Win32::SerialPort;

# Array mit den stty-Optionen
my @settings;
# Kommandozeilenargument (Spezialfaelle)
my $arg = "stty";

# Spezialargumente bearbeiten
if (@ARGV)
  {
  $arg = $ARGV[0];
  if ($arg eq "-a")
    { shift @ARGV; }
  elsif ($arg eq "-h")
    { help(); }
  elsif ($arg eq "-v")
    {
    print "Win32::SerialPort Version = $Win32::SerialPort::VERSION\n";
	  exit;
    }
  else
    { $arg = ""; }
  }

# stty-Optionen bearbeiten
my $port = pop @ARGV;
if (defined $port)
  {
  chomp $port;
  unless ($port =~ /^COM[1-4]$/)
     {
     warn "\nInvalid port: only COM1, COM2, COM3, or COM4 allowed\n";
     $port = "";
     }
  }
else
  { $port = ""; }
help() unless ($port);

die "\nstty_settings not permitted with option $arg\n" if ($arg && @ARGV);

# Port oeffenen
my $ob = Win32::SerialPort->new ("$port")
         or die "Can't open port $port: $!\n";

# Schnittstellenparameter testen
my $baud = $ob->baudrate;
if ($baud) { $ob->baudrate($baud)	|| die "fail setting baud"; }
else { defined $ob->baudrate(9600)	|| die "fail setting baud after 0"; }

my $value = $ob->parity;
$ob->parity($value)		  || die "fail setting parity";
$value = $ob->databits;
$ob->databits($value)		|| die "fail setting databits";
$value = $ob->stopbits;
$ob->stopbits($value)		|| die "fail setting stopbits";
$value = $ob->handshake;
$ob->handshake($value)	|| die "fail setting handshake";
$ob->write_settings     || die "no settings";

# stty-Optionen verarbeiten
if (@ARGV) { $ob->stty(@ARGV); }
$baud = $ob->baudrate;

if ($arg eq "-a")
  {
  @settings = $ob->stty();
  listall(@settings);
  }
else
  { print "\nSpeed $baud baud\n"; }

$ob->close;
undef $ob;


sub listall # @settings
  {
  # alle Settings auflisten
  my ($token, $value);
  my $count = 0;
  # als Erstes kommt die Baudrate
  $token = shift;
  print "Speed $token baud\n";
  # zweielementige Settings
  while (1)
    {
    $token = shift;
    $value = shift;
    printf "%8s = %2s", $token, $value;
    $count++;
    print "\n" if ($count % 3 == 0);
    # "stop" ist immer das letzte token der Paare
    if ($token eq "stop")
      {
      print "\n" if ($count %3 != 0);
      $count = 0;
      last;
      }
    }
  print "\n";
  # einelementige Settings
  for $token (sort(@_))
    {
    printf "%10s", $token;
    $count++;
    print "\n" if ($count % 5 == 0) ;
    }
  print "\n" if ($count % 5 != 0) ;
  }


sub help
  {
  # Hilfetext ausgeben
  print qq~
  Usage: $0 OPTION|SETTING COMx
  Print or change terminal characteristics.

  -a        print all current settings in human-readable form
  -h        display this help and exit
  -v        output version information and exit

  Optional - before SETTING indicates negation.
  An * marks non-POSIX settings.

  Special characters:
  eof char      char will send an end of file (terminate the input)
  eol char      char will end the line
  erase char    char will erase the last character typed
  intr char     char will send an interrupt signal
  kill char     char will erase the current line
  quit char     char will send a quit signal
  start char    char will restart the output after stopping it
  stop char     char will stop the output

  Special settings:
  N             set the input and output speeds to N bauds

  Control settings:
    [-]clocal     disable modem control signals
  * [-]crtscts    enable RTS/CTS handshaking
    csN           set character size to N bits, N in [5..8]
    [-]cstopb     use two stop bits per character (one with `-')
    [-]parenb     generate parity bit in output and expect parity bit in input

  Input settings:
    [-]icrnl      translate carriage return to newline
    [-]igncr      ignore carriage return
    [-]inlcr      translate newline to carriage return
    [-]inpck      enable input parity checking
    [-]istrip     clear high (8th) bit of input characters
    [-]ixoff      enable sending of start/stop characters
    [-]ixon       enable XON/XOFF flow control

  Output settings:
  * [-]ocrnl      translate carriage return to newline
  * [-]onlcr      translate newline to carriage return-newline
    [-]opost      postprocess output

  Local settings:
  * [-]echoctl    echo control characters in hat notation (`^c')
    [-]echo       echo input characters
    [-]echoe      same as [-]crterase
    [-]echok      echo a newline after a kill character
  * [-]echoke     same as [-]crtkill
    [-]echonl     echo newline even if not echoing other characters
    [-]icanon     enable erase, kill, werase, and rprnt special characters
    [-]isig       enable interrupt, quit, and suspend special characters


  Handle the COMx line specified.  Without arguments, prints baud rate.
  In settings, char is taken literally, or coded as in ^c, 0x37, 0177 or 127;
  special values ^- or undef used to disable special characters.
  ~;
  exit 0;
  }