Serial Programming in POSIX

Serial Programming in POSIX

Post by Angel Galindo Mu?o » Thu, 23 Mar 2000 04:00:00



        Hello!

        I'm trying to communicate synchronously with a GSM-modem (really
doesn't matter what's on the other side of the Serial Port!) using
linux-Unix.
        My real problem is to do a synchronous serial communication with
whatever be connected to the serial port.

____________________________________
And I have opened the port this way:
____________________________________

{
int fd;
struct termios options,xivato;  /* doesn't use xivato ... ;-) */

bzero(&options,sizeof(struct termios));
bzero(&xivato,sizeof(struct termios));
tcgetattr(fd,&xivato);

fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NDELAY);  /* opens the
port */
fcntl(fd, F_SETFL, 0);
cfmakeraw(&options);
        /* which uses this flags with the termos structure:
                   termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
                                   |INLCR|IGNCR|ICRNL|IXON);
                   termios_p->c_oflag &= ~OPOST;
                   termios_p->c_lflag &=
~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
                   termios_p->c_cflag &= ~(CSIZE|PARENB);
                   termios_p->c_cflag |= CS8;
        */
tcsetattr(fd, TCSAFLUSH, &options);
return (fd);

Quote:}

__________________________
But I still have problems:
__________________________

        Doing it this way, I can  do this communication, so I can send AT
commands to the modem and I can read his answers but I've got already
two problems:

        -I can't do a blocking read: I mean that what I need is to call a
function to read which doesn't return until there's anything in the
buffer to be read, or which could wait for a little time  (I could read
untill the data read is not null, but I prefer do it right!).   (I've
tried to un-use the "O_NDELAY" flag, but this doesn't seem to work at
all!)

        -The program I've wrote runs right once, but I want to run it a second
time, the program blocks trying to read the answer to the firs "AT\r"
command which I send to initialize the modem. When this happens, I've to
run "minicom" and re-initialize the modem, this evidently is not valid
to my program and also means that my program is not good!!!!

_____________________________
Some resources of information
_____________________________

        The links in which I have found some interesting information are:

http://www.prairienet.org/~rmasoner/serial.html
http://mops.uci.agh.edu.pl/doc/Linux-mini-HOWTOs/Serial-Port-Programming
http://www.linuxdoc.org/HOWTO/Modem-HOWTO.html
http://www.linuxdoc.org/HOWTO/Serial-Programming-HOWTO.html
http://www.easysw.com/~mike/serial

______________________
That's what I need ;-)
______________________

        ?Does anybody has already done something like this? ?Can I take a look
to this code?
        ?Does someone know how can I do this "blocking read" or what's the
matter that I cannot read anymore once I've executed the program once?
        ?Does anybody know any other resource of information, any link, any
book... anything?

        I have no problem to give the C's source of what I've done to anybody
who also has to do something like this and doesn't want to start from
zero.

        I'm waiting for some holy answer ...    Thanks in advance!!!

Angel Galindo Mu?oz

 
 
 

Serial Programming in POSIX

Post by Andrew Gabri » Thu, 23 Mar 2000 04:00:00



Quote:>       -I can't do a blocking read: I mean that what I need is to call a
> function to read which doesn't return until there's anything in the
> buffer to be read, or which could wait for a little time  (I could read
> untill the data read is not null, but I prefer do it right!).   (I've
> tried to un-use the "O_NDELAY" flag, but this doesn't seem to work at
> all!)

You want to add:

          termios_p->working.c_cc[VMIN] = 1;
          termios_p->working.c_cc[VTIME] = 1;

and use a blocking read (at least, this is the way with streams-based
serial comms - I believe this also works on Linux).

--
Andrew Gabriel
Consultant Software Engineer

 
 
 

Serial Programming in POSIX

Post by Angel Galindo Mu?o » Fri, 24 Mar 2000 04:00:00


        First of all, let's take a look at some documentation:
________________________________________________
________________________________________________
VMIN :  ( struct termios ' flag)
        "Serial Programming Guide for POSIX Operating Systems" tells that VMIN
is the "Minimum number of characters to read".

VTIME : ( struct termios ' flag)
        I've also found that it's the "Time to wait for data in tenths of
seconds".

O_NONBLOCK or O_NDELAY  ( open()'s flag )
              The manual tells that with this flag "the  file  is opened
in non-blocking mode. Neither the open nor any subsequent operations on
the file descriptor which is returned will  cause  the  calling
process  to" wait."

O_SYNC  ( open()'s flag )
        The  file  is opened for synchronous I/O. Any writes on the resulting
file descriptor will block the calling process until the data has  been
physically  written  to  the underlying hardware.
________________________________________________
________________________________________________

        I can't understand right now how must I connect it all to perform my
serial synchronous communication.

---> Does it mean that a read instruction on that file descriptor will
never return until the read of "VMIN" characters?     Then, if I set
VMIN=0 it will allow reads to return without any read, and if I set
VMIN=1 it won't return until it could read one bit at last in the
buffer,    ISN'T IT???  How does it connect with BLOCKING reading
(O_NONBLOCK or O_NDELAY flag)???

---> Do you wait exactly one tenth of second for any reason?

---> It seems necessary to NEVER USE O_NONBLOCK (O_NDELAY) flag, because
if I open the file descriptor using this flag it would turn to NON
BLOCKING READING, I mean that never any read would wait if the
reading-buffer is still void...   ISN'T IT?
        I'm sure this is what you mean when you say "use a blocking read": to
UNUSE this flag!... tell me!

---> Must I use O_SYNC flag in open() ?????

        Thanks a lot, Andrew!

Angel Galindo Mu?oz

En/Na Andrew Gabriel ha escrit:


> >       -I can't do a blocking read: I mean that what I need is to call a
> > function to read which doesn't return until there's anything in the
> > buffer to be read, or which could wait for a little time  (I could read
> > untill the data read is not null, but I prefer do it right!).   (I've
> > tried to un-use the "O_NDELAY" flag, but this doesn't seem to work at
> > all!)

> You want to add:

>           termios_p->working.c_cc[VMIN] = 1;
>           termios_p->working.c_cc[VTIME] = 1;

> and use a blocking read (at least, this is the way with streams-based
> serial comms - I believe this also works on Linux).

> --
> Andrew Gabriel
> Consultant Software Engineer

 
 
 

1. Serial programming problems (POSIX)

Hi.  I am trying to develop a primitive 'cu' command on Linux, much
like the one that is available on SVR4 systems, and I've had partial
success. My aim is to remain fully POSIX in my programming and I would
like to (if possible) try to stay away from any non-POSIX way of
accessing the serial ports.

What I did in my program which I do not have at hand was like this
(pseudo code):

portfd=open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NONBLOCK);
[checks here for success...]
tcgetattr(portfd);
cfsetispeed/cfsetospeed(portfd);
cfmakeraw(portfd);
tcsetattr(portfd);

then (here's where my trouble begins):

while (1)
{
        char ch, buf[1024];
        cnt = read(portfd, buf, 1024);
        [if cnt != 0, then I echo the characters to the terminal,
meaning that there was something coming back from the serial port,
i.e. an OK from the modem]]
        cnt = read(STDIN_FILENO, &ch, 1); // get kbd input
        [checks here for success...]
        write(portfd, &ch, 1);                  // send it right away on a
char by char basis to the port
        [checks here for success...]

Now, when I did something like this, don't remember the EXACT code, I
managed to be able to issue commands to the port, however, everything
I typed was echoed back a character later. I.E. if I wanted to issue
an AT\r, I'd hit A, then nothing would be echoed back (and it
supposedly should be echoed back at the beginning of the loop on the
next iteration), and then when I'd hit the T, the A would be echoed
back to me, then I'd hit <Enter>, then the T would be echoed back, and
then I'd finally hit <enter> or some other key, and the OK result
would be echoed back to me.

What am I doing wrong here?  Do I need to have separate processes that
will handle keyboard input and serial port output or no? I was looking
at some MINICOM code and it looks like he's managing to do all this in
a single while (1) loop, using select() and not having to fork
separate processes for keyboard handling or for ser. output handling.

Can someone experienced more than I tell me what is the _correct_, by
the book way, of doing this sort of thing, that is, handling serial
input and output mixed with keyboard input?  Do I need separate
processes ? I booted 'cu' on an SVR4 machine, it looked like it was
forking twice, which makes me think the correct way of doing this now
is to use 2 processes, one for kbd input, one for ser. output
handling? I have no experience in this area so any books recommended
would help, or at least some unix lovers' :-) advice would help.

Please help.
thank you.
Martin
p.s. what I really want to eventually do is write up an API for my
Kodak DC210 camera, which what I'll do once I learn proper RS232
handling techniques and give the API source away for free to support
Linux and POSIX at the same time. I just need a little boost on rs232
techniques :-).

Thanks.

2. RH5 Kernel compiling problem

3. POSIX Serial programming problem

4. Apache 1.2.0 User authentication.

5. POSIX Serial Programming

6. FTP uploaded file user permissions

7. Serial Programming in POSIX

8. Maintainer update: www/orion (1.4.5_7)

9. How to set up serial port when programming serial communication

10. Parallel Port programming question, was "Serial Port Programming"

11. serial port access on POSIX

12. POSIX.1 method of setting serial communications speed above 38400 Baud