Subject: | Opening serial ports under macOS indefinitely blocks |
I run Perl v5.26.1 on macOS 10.13.4 (High Sierra) and want to communicate with the Bus Pirate. I can't reproduce this on Linux, but you probably know that.
I wanted to use your Device::BusPirate, but opening the serial port inside IO::Termios->open indefinitely blocks.
Looking at the Serial Programming Guide for POSIX Operating Systems: https://www.cmrr.umn.edu/~strupp/serial.html,
it seems you are supposed to always open the serial port with O_NDELAY|O_NOCTTY first. Doing so makes the sysopen return, but now the syswrite returns EAGAIN.
Following the advice of the guide, I set CLOCAL and CREAD on the fd and now it works as expected. I noticed CREAD doesn't seem necessary in my case, but I rather stick to what's in the guide.
I attached an example script that shows what worked for me on macOS. I am using IO::Termios->new, but it would be nice if IO::Termios->open could do this as well, as it seems to me that would be the more portable approach. Script ran successfully on Linux as well.
Subject: | termios.pl |
#!/usr/bin/env perl
use strict;
use warnings;
use IO::Termios;
use Fcntl;
use IO::Select;
$|++;
my $serial = $ENV{BUS_PIRATE} || "/dev/tty.usbserial-A603PKBX";
my $baud = 115200;
sysopen my $fd, $serial, O_RDWR|O_NDELAY|O_NOCTTY
or die "Cannot open serial port $serial - $!";
my $fh = IO::Termios->new($fd)
or die "Cannot wrap serial port $serial - $!";
$fh->set_mode( "$baud,8,n,1" )
or die "Cannot set mode on serial port $serial";
$fh->setflag_icanon( 0 );
$fh->setflag_echo( 0 );
$fh->blocking( 0 );
$fh->setflag_clocal( 1 );
$fh->setflag_cread( 1 );
print "Writing...";
if (IO::Select->new($fh)->can_write) {
$fh->syswrite("\r\n")
or die "Error writing to serial port - $!";
print " [DONE]\n";
}
print "Reading...";
my $buf;
if (IO::Select->new($fh)->can_read) {
$fh->sysread($buf, 6)
or die "Error reading from serial port - $!";
print " [DONE]\n"
}
die "Unexpected output: `$buf'\n" if $buf !~ /HiZ>$/;
print "All is well!\n";