ITEM: BX5069L

Read from tty in raw mode still filters out special characters


 ENV:
        AIX 4.1.5
        Model 7060
        Native serial ports attached to data collection device.

PROBLEM:
        I'm porting code from Sun to AIX that reads raw data from a
        serial port.  There are some ioctl calls on SUN to which I
        cannot seem to find an AIX equivalent.  How should I setup
        my code to read raw data from the serial port, including 
        passing of special characters (like ctrl-c, etc) to my
        program instead of them being interpretted before they get
        to my code by AIX?

*ACTION TAKEN:
        You've written your code using motalk as a basis.  Your 
data feed sends 69 bytes of data to your 7060's native serial port.
You have the tty setup for raw (-icanon, -echo, etc.) with VTIME=1
(for 1/10 second) and VMIN=70 so you know your read should try to
read for at least 1/10 second.  read() returns 56 and you do get
the first 56 bytes of your 69 byte packet without problem.  But,
when you try to read() the reamining 13 bytes, read returns 0, 
there is nothing left to read.  The characters missing from the read
are "special" characters, like the interrupt, suspect, kill characters.

I have taken a sample program (motalk.c) and modified it to these
specifications - it sends *ALL* characters that come into the serial
port to your code unmodified.

\#include \
\#include \
\#include \
\#include \
\#include \
 FILE   *fdr, *fdw;
int    fd;
struct termio term_save, stdin_save;
 void Exit(int sig)
{        if (fdr) fclose(fdr);
        if (fdw) fclose(fdw);
        ioctl(fd, TCSETA, &term_save);
        close(fd);
        ioctl(fileno(stdin), TCSETA, &stdin_save);
        exit(sig);
}main(int argc, char *argv[])
{        char   *b, buffer[80];
        int    baud = 0, num;
        struct termio term, tstdin;
        int     i;

          if (argc \< 2 || !strcmp(argv[1], "-?")) {
                  fprintf(stderr, "USAGE:  motalk /dev/tty? [speed]\\n");
                  exit(1);
          }
           if ((fd = open(argv[1], O_RDWR|O_NDELAY)) \< 0 ) {
                  perror(argv[1]);
                  exit(errno);
          }
           if (argc > 2) {
                switch(atoi(argv[2])) {
                        case 300:
                                baud = B300;
                                break;
                        case 1200:
                                baud = B1200;
                                break;
                        case 2400:
                                baud = B2400;
                                break;
                        case 4800:
                                baud = B4800;
                                break;
                        case 9600:
                                baud = B9600;
                                break;
                        case 19200:
                                baud = B19200;
                                break;
                        case 38400:
                                baud = B38400;
                                break;
                        default:
                                baud = 0;
                                fprintf(stderr,
                                        "%s: %s is an unsupported baud\\n",
                                        argv[0], argv[2]);
                                exit(1);
                }
        }
/*      SAVE STDIN AND TTY STATE. ALSO TRAP SIGNALS   */
        ioctl(fd, TCGETA, &term_save);
        ioctl(fileno(stdin), TCGETA, &stdin_save);
        signal(SIGHUP,  Exit);
        signal(SIGINT,  Exit);
        signal(SIGQUIT, Exit);
        signal(SIGTERM, Exit);
 /*      SET STDOM TP RAW MODE, NO ECHO    */
        ioctl(fileno(stdin), TCGETA, &tstdin);
        tstdin.c_iflag = 0;
        tstdin.c_lflag &=  ~(ICANON | ECHO);
        tstdin.c_cc[VMIN] = 0;
        tstdin.c_cc[VTIME] = 0;
        ioctl(fileno(stdin), TCSETA, &tstdin);
 /*      SET TTY STATE   */
        ioctl(fd, TCGETA, &term);
        term.c_cflag |= CLOCAL|HUPCL;
        term.c_iflag &= ~ICRNL;   /*  TO AVOID UN-NEEDED BLANK LINES  */
          if (baud > 0) {
                  term.c_cflag &= ~CBAUD;
                  term.c_cflag |= baud;
          }

 /* Modifications from original motalk.c begin here */
 term.c_iflag  = IGNPAR;                        /* parity off */
 term.c_iflag |= BRKINT;                        /* signal interrupt on break */
 term.c_oflag  = 0;                             /* clear output flag */
 term.c_cflag |= CREAD;                         /* enable character receiver */
 term.c_cflag |= CS8;                           /* 8 bits */
 term.c_cflag &= ~PARENB;                       /* no parity */
 term.c_lflag  = 0;                             /* clear line flag */
 term.c_cc[VINTR] = -1;                         /* turn off interrupt signal */
 term.c_cc[VQUIT] = -1;                         /* turn off quit signal */
 term.c_cc[VERASE] = -1;                        /* turn off erase */
 term.c_cc[VKILL] = -1;                         /* turn off kill */
 /* End of modifications from the original motalk */

        term.c_cc[VMIN] = 0;
        term.c_cc[VTIME] = 10;
        ioctl(fd, TCSETA, &term);
        fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NDELAY);
 /*      OPEN TTY FOR READ AND WRITE  */
          if ((fdr = fopen(argv[1], "r")) == NULL ) {
                  perror(argv[1]);
                  exit(errno);
          }
          if ((fdw = fopen(argv[1], "w")) == NULL ) {
                  perror(argv[1]);
                  exit(errno);
          }
 /*      ALL I/O IS UNBUFFERED */
        setbuf(stdin, 0);
        setbuf(stdout, 0);
        setbuf(fdr, 0);
        setbuf(fdw, 0);
         puts("Ready... \^C to exit");
        while (1) {
                if ((num = read(fileno(fdr), buffer, 80)) > 0)
                {
                  printf("\\nRead %d bytes\\n", num);
                  for (i = 0; i \< num; i++)
                    printf("%2X ", *(buffer + i));
                  printf("\\n");
                  for (i = 0; i \< num; i++)
                        printf("%2c ", " ");
                    else
                        printf("%2c ", *(buffer + i));
                }
        }
        Exit(0);
}       /*       E N D    O F    P R O G R A M        */


The above suggestions worked as desired.



Support Line: Read from tty in raw mode still filters out special characters ITEM: BX5069L
Dated: April 1997 Category: N/A
This HTML file was generated 99/06/24~13:30:19
Comments or suggestions? Contact us