Asynchronous Serial I/O

This is a discussion on Asynchronous Serial I/O within the Linux Programming forums, part of the Platform Specific Boards category; Folks, This is my first post here. I am trying to configure a serial port under Ubuntu 10.04 to performer ...

  1. #1
    Registered User
    Join Date
    Oct 2010
    Posts
    2

    Asynchronous Serial I/O

    Folks,

    This is my first post here.

    I am trying to configure a serial port under Ubuntu 10.04 to performer asynchronous serial I/O. The idea is to use the signal SIGIO to raise the flags for "data available to read" and "sand buffer is not in use". I would like to have my signal handler be able to tell whether the signal is caused by a "send" or a "receive", so I activated the SA_SIGINFO flag in the sa_flags field of the sigaction structure. Two additional arguments are passed to the signal-catching function. If the second argument is not equal to NULL, it points to a siginfo_t structure containing the reason why the signal was generated. the third argument points to a ucontext_t structure containing the receiving process's context when the signal was delivered.

    I hook my linux machine to a windows machine via serial cable. However, my code is not working as I expected when I sent strings from my windows machine to the linux machine. The program succeeded in invoking the signal-catching function whenever new characters were received, and the received signal turns to be 29 (correspond to the signal SIGIO). But the member si_code in struct siginfo_t failed to be updated to reflect the reason of the signal. When characters are received, I expect the si_code to be up dated to POLL_IN (which is 1). But the actual value printed in the signal-catching program is 128, which does not make sense to me.

    Can anybody take a look at my code and shine some light on it if at all possible? I cannot figure out what I missed.

    Thanks.

    Meng Fang

    ======================MY CODE===============================
    Code:
          #include <termios.h>
          #include <stdio.h>
          #include <unistd.h>
          #include <fcntl.h>
          #include <sys/signal.h>
          #include <sys/types.h>
    	  #include <signal.h>
    	  #include <bits/siginfo.h>
    
          #define BAUDRATE B57600
          #define MODEMDEVICE "/dev/ttyS1"
          #define _POSIX_SOURCE 1 /* POSIX compliant source */
          #define FALSE 0
          #define TRUE 1
    	  void signal_handler_IO (int status, siginfo_t *ioinfo, void *context );
    
          volatile int STOP=FALSE;
    
    
          int wait_flag=TRUE;                    /* TRUE while no signal received */
    
         int main()
          {
            int fd, res;
            struct termios oldtio,newtio;
            struct sigaction saio;           /* definition of signal action */
            char buf[255];
    
            /* open the device to be non-blocking (read will return immediatly) */
            fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
    
    
            /* install the signal handler before making the device asynchronous */
            //saio.sa_handler = signal_handler_IO;
            sigemptyset(&saio.sa_mask);
            saio.sa_flags = saio.sa_flags|SA_SIGINFO;
            saio.sa_restorer = NULL;
            saio.sa_sigaction = signal_handler_IO;
    
            sigaction(SIGIO,&saio,NULL);
    
            /* allow the process to receive SIGIO */
            fcntl(fd, F_SETOWN, getpid());
            /* Make the file descriptor asynchronous (the manual page says only
               O_APPEND and O_NONBLOCK, will work with F_SETFL...) */
            fcntl(fd, F_SETFL, FASYNC);
    
            tcgetattr(fd,&oldtio); /* save current port settings */
            /* set new port settings for canonical input processing */
            newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD;
            newtio.c_iflag = IGNPAR | ICRNL;
            newtio.c_oflag = 0;
            newtio.c_lflag = 0;
            newtio.c_cc[VMIN]=1;
            newtio.c_cc[VTIME]=0;
            tcflush(fd, TCIFLUSH);
            tcsetattr(fd,TCSANOW,&newtio);
    
            /* loop while waiting for input. normally we would do something
               useful here */
            while (STOP==FALSE) {
              printf(".");usleep(100000);
              /* after receiving SIGIO, wait_flag = FALSE, input is available
                 and can be read */
              if (wait_flag==FALSE) {
                res = read(fd,buf,255);
                buf[res]=0;
                printf(":%s:%d\n", buf, res);
                if (res==1) STOP=TRUE; /* stop loop if only a CR was input */
                wait_flag = TRUE;      /* wait for new input */
              }
            }
            /* restore old port settings */
            tcsetattr(fd,TCSANOW,&oldtio);
            return 1;
          }
    
          /***************************************************************************
          * signal handler. sets wait_flag to FALSE, to indicate above loop that     *
          * characters have been received.                                           *
          ***************************************************************************/
    
          void signal_handler_IO (int status, siginfo_t *ioinfo, void * context )
          {
            switch (ioinfo->si_code)
            {
            case POLL_IN:
            printf("signal received for input chars.sig:%d -%d\n",status, ioinfo->si_code);
            wait_flag = FALSE;
            break;
    
            case POLL_OUT:
            default:
            printf("signal received for something else.sig:%d -%d\n",status, ioinfo->si_code);
            break;
            }
    
    
          }
    Last edited by Salem; 10-13-2010 at 01:49 AM. Reason: Added code tags - learn to use them yourself

  2. #2
    Unregistered User Yarin's Avatar
    Join Date
    Jul 2007
    Posts
    1,597
    Personally, I try to avoid SIGIO because it's not portable, and, well, signals are disgusting.

    I don't know what's causing the problem, but I advise using poll() instead of SIGIO. If you must preform a simultaneous operation that won't realistically be able to check the descriptor's status, create another thread. I love threads, they are an easy way to solve a lot of problems. ;-)
    A class that doesn't overload all operators just isn't finished yet. -- SmugCeePlusPlusWeenie
    A year spent in artificial intelligence is enough to make one believe in God. -- Alan J. Perlis

  3. #3
    Registered User
    Join Date
    Oct 2010
    Posts
    2
    Yarin,

    Thank you so much for your advices. The "poll()" idea you brought up is really great! I used that function and solved my problem!!!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Synchronous and asynchronous I/O
    By starcatcher in forum Windows Programming
    Replies: 4
    Last Post: 04-11-2010, 10:57 PM
  2. Asynchronous serial port (or SerialPortStream)
    By Perspective in forum C# Programming
    Replies: 0
    Last Post: 07-31-2008, 11:14 AM
  3. Recommend some asynchronous I/O tutorial?
    By George2 in forum Windows Programming
    Replies: 8
    Last Post: 01-29-2008, 06:11 PM
  4. Overlapped I/O and Completion Port :: Winsock
    By kuphryn in forum Windows Programming
    Replies: 0
    Last Post: 10-30-2002, 04:14 PM
  5. Carrying out Serial I/O btw 2 comps using interrupts
    By Unregistered in forum C Programming
    Replies: 1
    Last Post: 06-06-2002, 11:28 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21