package Interface6051::LinuxAsyncHack;
use strict;
use Interface6051;
use Device::SerialPort;
our @ISA = ('Interface6051');
1;

sub new {
    my $class = shift;
    my $self = $class->SUPER::new(@_);
    $self->{port} = '/dev/ttyS0';
    open($self->{fh}, '+<', $self->{port}) or die "Can't open port: $!\n";
    system("stty 2400 -echo -crtscts -parenb cs8 cstopb raw < $self->{port}"); # ew, we should do this ourselves
    $self->{pid} = open(SERIALPIPE, '|-');
    die "Couldn't fork serial port thread: $!" unless defined $self->{pid};
    if (!$self->{pid}) {
        # this is a forked child whose STDIN is connected to $self->{pipe} in the parent process
        local $SIG{PIPE} = sub { die 'Pipe leaked.\n'; };
        while (<STDIN>) {
            print STDERR "TRANSMITTING $_\n";
            system(sprintf('echo -ne \\\\%03o > %s', $_, $self->{port})); # ew, horrible hack
            select(undef, undef, undef, 0.25); # XXX this is terrible
        }
        exit;        
    }
    return $self;
}

sub transmit {
    my $self = shift;
    foreach (@_) {
        print SERIALPIPE $_ or die "Pipe broke: $!\n";
    }
}

sub receive {
    my $self = shift;

    # prepare fields
    my $fh = '';
    vec($fh, fileno($self->{fh}), 1) = 1;

    # read one character at a time until no more data is forthcoming
    my $data = '';
    my $ready;
    while (select($ready = $fh, undef, undef, 0.15) and vec($fh, fileno($self->{fh}), 1)) {
        # select can return true for filehandles that aren't in the
        # list, so that's why we check the right filehandle is there
        # in the returned $ready variable.
	sysread($self->{fh}, $data, 1, length($data));
    }

    return $data;
}

sub DESTROY {
    close SERIALPIPE;
}
