Re: serial drivers

Rob Riggs (rriggs@tesser.com)
Mon, 04 Aug 1997 23:26:28 -0600 (MDT)


On 04-Aug-97 Gael Gence wrote:
>I'm wondering about a way (any way, even a trick) to know if the serial
>port has received something. I'd like to write a program able to report
>port state in "real time". I'm using TIOCSERGETLSR to see if data is
>sent -> how can i know if data is received ? I was talking about LSR
>because get_lsr_status is the last thing i've tried.

There is currently no way to tell when data is sent or
received from the serial port (except the program that
has the port open for reading and writing - it knows
when it sends and receives). You will need to modify
serial.c in the kernel to get the data you need.

There are a couple of ways to go about it. You don't
really need the LSR register info. You just need to
know when data is sent and/or received.

The easiest way is to set some unused bits in the
'flags' member of async_struct when in receive_chars()
and transmit_chars(). You can then read them with a
simple TIOCGSERIAL ioctl. Something like the patch
included below (against 2.0.30) should do the trick.

A better solution would be to modify struct async_icount
and TIOCMIWAIT do hold and report the info to you. This
has the benifit of blocking until status actually changes.
No need to constantly poll the device. If you try this,
don't forget to wakeup the sleeping process when the
async_icount xmit or recv values change.

What you want can be done, but requires a little kernel
hacking.

Hope this helps.

-Rob

--- serial.h.orig Tue Aug 5 00:13:19 1997
+++ serial.h Tue Aug 5 00:14:39 1997
@@ -80,6 +80,8 @@
#define ASYNC_CTS_FLOW 0x04000000 /* Do CTS flow control */
#define ASYNC_CHECK_CD 0x02000000 /* i.e., CLOCAL */
#define ASYNC_SHARE_IRQ 0x01000000 /* for multifunction cards */
+#define ASYNC_DATA_RECV 0x00800000 /* Data received */
+#define ASYNC_DATA_XMIT 0x00400000 /* Data sent */

/*
* Multiport serial configuration structure --- external structure
--- serial.c.orig Tue Aug 5 00:12:56 1997
+++ serial.c Tue Aug 5 00:20:36 1997
@@ -400,6 +400,7 @@

do {
ch = serial_inp(info, UART_RX);
+ info->flags |= ASYNC_DATA_RECV;
if (*status & info->ignore_status_mask) {
if (++ignored > 100)
break;
@@ -451,6 +452,8 @@
return;
}

+ info->flags |= ASYNC_DATA_XMIT;
+
count = info->xmit_fifo_size;
do {
serial_out(info, UART_TX, info->xmit_buf[info->xmit_tail++]);
@@ -1513,6 +1516,8 @@
tmp.port = info->port;
tmp.irq = info->irq;
tmp.flags = info->flags;
+ /* Clear data flags every time they are read */
+ info->flags &= ~(ASYNC_DATA_RECV | ASYNC_DATA_XMIT);
tmp.baud_base = info->baud_base;
tmp.close_delay = info->close_delay;
tmp.closing_wait = info->closing_wait;