lkml.org 
[lkml]   [1999]   [Nov]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: serial port - ioctl's prevent subsequent reads
   Date:   Thu, 18 Nov 1999 00:26:11 +0100 (MET)
From: David Monniaux <David.Monniaux@ens.fr>

using kernel 2.2.5 and glibc 2.1 (RedHat 6.0), I get the following weird
behaviour: the serial port being -crtscts and clocal, the following
program waits forever in tcdrain():

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/ioctl.h>

main()
{
int fd, foo;
char totor[300];
fd=3Dopen("/dev/ttyS0", O_RDWR);
ioctl (fd, TIOCMSET, &foo);
write(fd, totor, 300);
fprintf(stderr, "maa\n");
tcdrain(fd);
fprintf(stderr, "moo\n");
}

It seems that the system does not transmit any data. However, removing the
ioctl line makes it run fine.

Why would i/o get blocked after such an ioctl?

It's very simple. You should never never call TIOCMSET raw and pass
garbage to it. You should always call TIOCMGET, then modify whatever
modem lines you want, and then call TIOCMSET. What you did by passing
garbage to TIOCMSET was that you turned off the OUT2 line to the uart,
which disabled interrupts to the UART. This caused the tcdrain to take
a *long* time, since characters weren't moving all that rapidly with
interrupts turned off.


[I'm becoming sick and tired of the serial driver second-guessing the
programmer. First, even when clocal is on, it resets the modem lines on
opening the device, which is plain stupid since clocal tells it to leave
these lines alone.

That's not what CLOCAL means. Read the POSIX specification. POSIX
specifically states CLOCAL means to ignore the modem control lines
(specifically "wait until a connection is established", so it is
referring to the RS-232 Carrier Detect line) for the purposes of
determining whether or not open() should block. See sections 7.1.2.4
and sections 7.1.1.1.

As far as the serial driver's enabling DTR when the port is opened; this
is necessary. In the normal case, when you're talking to a modem, you
may want to set CLOCAL so that you don't get disconnected when the modem
drops carrier detect. As discussed above, this is the definition of
CLOCAL as defined by POSIX. However, DTR must be high or some modems
won't pay attention to you at all (and this is specified by the RS-232
specification). So in the general case you have to raise DTR when you
open the port, or a number of standard serial devices will refuse to
function.

(Similarly, if the RS-232 port is configured as a DCE, the DTR line
becomes the DSR line, and DSR has to be raised or some terminals will
refuse to talk to the serial port.)

Also, normally DTR is not referred to as "modem control line" so your
argument that CLOCAL means the serial driver shouldn't touch DTR is
bogus for two different reasons.

Then it does weird things if I fiddle with them myself.
I add that code similar to the one above worked under 2.0 / libc 5.]

That's because you wrote non portable code and didn't call TIOCMGET to
obtain the current value before modifying them and calling TIOCMSET.
You would have also been fine if you had used TIOCMBIC and TIOCMBIS.

The reason why it worked under Linux 2.0 was that under Linux 2.0
TIOCMSET didn't have the power to set the OUT1 and OUT2 UART lines, and
I got a number of feature requests to allow the serial driver to do so.
I did, but it meant making the serial driver more powerful and flexible
at the cost of causing folks who wrote non-portable code to lose. I'd
hardly called that second-guessing the programmer; I'm just assuming the
programmer is writing good code. (Clearly that was a bad assumption.)

- Ted

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:55    [W:0.070 / U:0.208 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site