Re: Serial device open(2) hang.
Re: Serial device open(2) hang.
- Subject: Re: Serial device open(2) hang.
- From: Kevin Van Vechten <email@hidden>
- Date: Sat, 27 Jun 2009 22:34:23 -0700
Yes fork/exec is better than system, and posix_spawn is better still.
Sent from my iPhone
On Jun 27, 2009, at 9:14 PM, David Elliott <email@hidden> wrote:
Hi Steve,
On Jun 27, 2009, at 8:55 PM, Steve Checkoway wrote:
I have a Keyspan USA-49WLC USB to 4 serial ports adapter which,
when plugged in, correctly shows 4 /dev/tty.USA* and 4 /dev/cu.USA*
devices. I'm trying to talk to a microcontroller on the other end
of the serial, reading and writing data, so the first step I'm
taking is to open(2) the appropriate tty. As far as I can tell,
this is hanging until I unplug the USB cable. Once I unplug it, it
returns -1.
Change your open call to O_RDWR | O_NONBLOCK. This will cause open
not to block thus allowing you to get a working file descriptor and
keeping a handle open to the device (this is important).
Once you have that you need to run stty against it or I suppose you
can use termios functions but honestly I am not all that familiar
with serial programming, I just happened to be doing it the other
week on another project.
What I came up with was this:
void stty_serial(int ser)
{
pid_t pid = fork();
if(pid < 0)
{
fprintf(stderr, "Couldn't fork to exec stty\n");
return;
}
else if(pid > 0)
{
// parent.. wait for child
int stat_loc;
waitpid(pid, &stat_loc, 0);
return;
}
// child
if(dup2(ser, STDIN_FILENO) != 0)
{
fprintf(stderr,"Shit\n");
_exit(1);
}
// Make sure (now duped) stdin; stdout; and stderr stay open
across exec
fcntl(STDIN_FILENO, F_SETFD, 0);
fcntl(STDOUT_FILENO, F_SETFD, 0);
fcntl(STDERR_FILENO, F_SETFD, 0);
execlp("/bin/stty", "/bin/stty", "115200", "raw", "clocal",
"crtscts", NULL);
// NOTREACHED (or at least.. shouldn't be)
fprintf(stderr, "Failed exec\n");
_exit(1);
for(;;)
;
}
The argument to the function is the fd returned from open. The stty
setting you need more than anything is the clocal setting which
causes it to ignore the modem control signals (DSR/DTR I think).
Without that, open blocks. Once I have run this function I use fcntl
(ser, F_SETFL, fcntl(ser, F_GETFL) & ~O_NONBLOCK); to put the fd
back into blocking mode.
I got most of my clues here from the manpage for stty. What isn't
mentioned though is that you can't just run stty and then run your
program because once the last open file descriptor to a port is
closed, everything resets to the defaults, e.g. 9600 baud, -clocal,
etc. So it seems to me that stty can never really be run
effectively except in the case as above where it's run on an already
open file descriptor dup2'd into the child process.
An alternative might be to open with O_NONBLOCK then you could
probably get away with system("stty -f /dev/tty.wtf 115200 raw
clocal crtscts") to set your params. But I figured that fork/dup2/
exec was probably a better way to go about it.
Hope that helps. And maybe someone else with more serial
programming experience could chime in. But this worked for me.
This same code, when run on Linux using /dev/ttyS0, works as I
would expect: It prints "Opening a file" and then "Opened!".
Is this a problem with the Keyspan driver or (as is more likely) am
I doing something wrong?
I believe it's a behavioral difference between Linux and BSD.
Oh, one other little gotcha before you run into it as I did. The
poll system call on OS X does not support tty devices. So use
select instead. I had recalled back in the day that poll was not
supported at all on OS X (except through a bit of code that
translated it into select). But I did not realize, and did not
notice the warning in the BUGS section of its manpage, that when
Apple finally did implement poll they did not allow it to support
devices, only network sockets.
-Dave
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden