Re: Keyboard/Serial port monitoring using select()
From: Floyd L. Davidson (floyd_at_barrow.com)
Date: 07/14/04
- Next message: Otto Wyss: "Defered loading of shared libraries"
- Previous message: Nils O. Selåsdal: "Re: (gcc) warning: no newline at end of file"
- In reply to: Kim Adil: "Re: Keyboard/Serial port monitoring using select()"
- Next in thread: Kim Adil: "Re: Keyboard/Serial port monitoring using select()"
- Reply: Kim Adil: "Re: Keyboard/Serial port monitoring using select()"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Wed, 14 Jul 2004 08:50:53 -0800
Kim Adil <ksadil@bigpond.net.au> wrote:
>Floyd L. Davidson wrote:
>
>> Kim Adil <ksadil@bigpond.net.au> wrote:
>
>>
>> Well... hmmm, just like I showed!
>>
>> options.c_iflag = IGNBRK | IGNPAR;
>> options.c_cflag = CREAD | CRTSCTS | CS8;
>> options.c_lflag = 0;
>> options.c_oflag = 0;
>>.
>
>Doh! OK, no my terminal raw mode monitoring works a treat, but my new serial
>port select does not fire. I have a modem connected to ttyS0 and when I
>call it from my mobile, I know thet it broadcasts "RING" but my new code
>does not detect any activity on ttyS0. Any ideas? I suspect it is in the
>options. I wan to set them difinitively, as per your advice. My new code:
>
>#include <sys/types.h>
>#include <sys/stat.h>
>#include <sys/select.h>
There is no need to include sys/select.h, because both sys/types.h
and sys/time.h include it for you.
>#include <sys/time.h>
>#include <fcntl.h>
>#include <errno.h>
>#include <stdio.h>
>#include <termios.h>
>#include <unistd.h>
>#include <linux/serial.h>
>
> int fd;
> char ch;
> int max_fd;
> int status;
> fd_set input;
> struct termios options;
> struct termios toptionsold;
> struct termios toptions;
> struct timeval timeout;
>
>int setterm(void)
> {
> tcgetattr(0,&toptions);
> tcgetattr(0,&toptionsold);
> toptions.c_lflag =0;
Heh heh, when you diddle the flags for stdin, you probably *don't*
want to reset everything! Instead, this is where the examples you
were using previously are correct. Just &= ~(ICANON) to selectively
leave everything the way it was with the exception of the one set of
bits you want to clear. You might, or might not, want to also clear
ISIG along with ICANON.
> tcsetattr(0,TCSANOW,&toptions);
>
> }
>
>int setser(void)
> {
>
> if((fd=open("/dev/ttyS0", O_RDWR|O_NDELAY))!=-1)
> {
> printf("fd=%d\n",fd);
> options.c_iflag = IGNBRK|IGNPAR; //ignore parity errors
> options.c_cflag = CREAD | CRTSCTS |CS8;
> options.c_lflag = ICANON;
> options.c_line = 0;
> cfsetospeed(&options,B38400);
> cfsetispeed(&options,B38400);
> options.c_cc[VTIME]=5;
> options.c_cc[VMIN]= 1;
> tcflush(fd,TCIFLUSH);
> status=tcsetattr(fd,TCSANOW,&options);
> if(status==-1)
> {
> printf("cannot set serial port options\n");
> exit(0);
> }
> }
> max_fd = (0 > fd ? 0 : fd) + 1;
> }
>
>int checkselect(void)
> {
> int retval;
>
> FD_ZERO(&input);
> /* Watch stdin (fd 0) to see when it has input. */
> FD_SET(0, &input);
> /* Watch serial port (fd) to see when it has input. */
> FD_SET(fd, &input);
>
> timeout.tv_sec = 0;
> timeout.tv_usec = 500;
>
> retval = select(max_fd, &options, NULL, NULL, NULL);
This is *not* the way to call select(), and if your compiler
didn't complain then you aren't invoking it with a high enough
level of warnings! See below for the warning about line 69.
Plus, you've set the timeout values, but didn't provide that
to select().
The sensible way to do this is with a Makefile, because you
don't want to type in all the options that gcc requires every
time. Here is what happened when I plugged this into my
standard "test" Makefile by dropping your code into foo.c and
running make. I've folded the long lines to make them fit.
What you are interested in is the huge list of options,
gcc -O6 -march=i686 -mcpu=i686 -Wall -W -Wcast-align \
-Wcast-qual -Wmissing-prototypes -Wshadow \
-Wnested-externs -Wstrict-prototypes \
-Waggregate-return -finline-functions -c foo.c
Here are the warnings gcc provided:
foo.c:23: warning: no previous prototype for `setterm'
foo.c: In function `setterm':
foo.c:29: warning: control reaches end of non-void function
foo.c: At top level:
foo.c:32: warning: no previous prototype for `setser'
foo.c: In function `setser':
foo.c:54: warning: control reaches end of non-void function
foo.c: At top level:
foo.c:57: warning: no previous prototype for `checkselect'
foo.c: In function `checkselect':
foo.c:69: warning: passing arg 2 of `select' from incompatible pointer type
foo.c:77: warning: empty body in an if-statement
foo.c: At top level:
foo.c:81: warning: return-type defaults to `int'
foo.c:81: warning: function declaration isn't a prototype
foo.c: In function `main':
foo.c:101: warning: zero-length format string
foo.c:104: warning: zero-length format string
foo.c:110: warning: control reaches end of non-void function
gcc foo.o -o foo
The minimum level of warnings you would ever want to invoke gcc
with are "gcc -O -Wall -W". But obviously the others are very
helpful too.
You also really do not want to use global variables for
everything. This should use local variables, but in this case I
can't see any reason for putting this wrapper around select()
and having it in a separate function.
> if (retval == -1 )
> return -1;
> if (retval == 0)
> return 0;
> if ( FD_ISSET(0, &input))
> return 1 ;
> if ( FD_ISSET(fd, &input));
> return 3 ;
The fundamental problem with this method is that select() may
return with a true status for *all* of the descriptors tested!
You can only indicate one, and will miss the other. Instead,
put select() inside a loop, and if it returns indicating that
any descriptor is valid, check each of them in turn and read
each that is ready.
Isn't there a nice example in the man page for select()? Copy
it!
> }
>
>main(){
int main(void)
Also you should have a return statement at the end of the main
function.
> /* Initialize the input set */
>
> setterm();
> setser();
>
> /* Initialize the timeout structure */
>
> do
> {
> switch (status = checkselect()) {
> case 1: //got stdin
> read(0,&ch,1);
> printf("Stdin got selected with %c\n",ch);
> break;
> case 3: //got port
> read(fd,&ch,1);
> printf("Modem got selected %c\n",ch);
> break;
> case 0:
> printf("");
> break;
> default:
> printf("");
> }
> }
> while ( ch != 'q' );
Hmmm... one more problem. You are reading only 1 character from
either descriptor. But there might be one or hundreds of
characters waiting.
> tcsetattr(0,TCSANOW,&toptionsold);
return 0;
>}
-- FloydL. Davidson <http://web.newsguy.com/floyd_davidson> Ukpeagvik (Barrow, Alaska) floyd@barrow.com
- Next message: Otto Wyss: "Defered loading of shared libraries"
- Previous message: Nils O. Selåsdal: "Re: (gcc) warning: no newline at end of file"
- In reply to: Kim Adil: "Re: Keyboard/Serial port monitoring using select()"
- Next in thread: Kim Adil: "Re: Keyboard/Serial port monitoring using select()"
- Reply: Kim Adil: "Re: Keyboard/Serial port monitoring using select()"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|