Thread: Select function

  1. #1
    Registered User
    Join Date
    Nov 2005
    Posts
    13

    Select function

    Hi Guys,

    I am trying to learn how the select function works. The code below seems to work on the serial side. But not on the stdin side. Any ideas ?

    Code:
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <fcntl.h>
          #include <termios.h>
          #include <stdio.h>
          #include <sys/time.h>
          #include <sys/types.h>
          #include <unistd.h>
    
            
          #define BAUDRATE B115200
          #define MODEMDEVICE "/dev/ttyUSB0"
          #define _POSIX_SOURCE 1 /* POSIX compliant source */
          #define FALSE 0
          #define TRUE 1
          #define MAXLINE 50
    
          #ifndef max
          #define max( a, b ) ( ((a) > (b)) ? (a) : (b) )
          #endif
    
          #ifndef min
          #define min( a, b ) ( ((a) < (b)) ? (a) : (b) )
          #endif
    
          void handle_input_from_fd1(int fd1);
    
            
          volatile int STOP=FALSE; 
           
          main()
          {
    
            struct termios oldtio,newtio;
    	char input[MAXLINE];
    
    
            int    fd1;  /* input sources 1 and 2 */
            fd_set readfs;    /* file descriptor set */
            int    maxfd;     /* maximum file desciptor used */
    
    
            
            fd1 = open(MODEMDEVICE, O_RDWR | O_NOCTTY ); 
            if (fd1 <0) {perror(MODEMDEVICE); exit(-1); }
    
    
    
    	FD_ZERO(&readfs);
            
            tcgetattr(fd1,&oldtio); /* save current port settings */
            
            bzero(&newtio, sizeof(newtio));
            newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
            newtio.c_iflag = IGNPAR;
            newtio.c_oflag = 0;
            
            // set input mode (non-canonical, no echo,...) 
    	
            newtio.c_lflag = 0;
             
            newtio.c_cc[VTIME]    = 0;   // inter-character timer unused 
            newtio.c_cc[VMIN]     = 1;   // blocking read until 5 chars received 
            
            tcflush(fd1, TCIFLUSH);
            tcsetattr(fd1,TCSANOW,&newtio);
    
    
    
            
            //loop for input 
            while (1) {
    
              FD_SET(fd1, &readfs);  // set testing for source 1 
              FD_SET(fileno(stdin), &readfs);  // set testing for source 2 
    
            maxfd = max(fileno(stdin), fd1)+1;  // maximum bit entry (fd) to test 
    
              /* block until input becomes available */
              select(maxfd, &readfs, NULL, NULL, NULL);
    
              if (FD_ISSET(fd1,&readfs))  // input from source 1 available 
                handle_input_from_fd1(fd1);
    
              if (FD_ISSET(fileno(stdin),&readfs)) // input from source 2 available 
                //handle_input_from_fd2(stdin,fd1);
    
    	   {
      
    			if (fgets(input,MAXLINE,stdin) == NULL)
    			{
    				return;		/* all done */
    			}
    
    	
    			printf("input is: [%s]",input);
    			write(fd1, input,MAXLINE);
    	   }
    
            }
         
     
            tcsetattr(fd1,TCSANOW,&oldtio);
          }
    
          void handle_input_from_fd1(int fd1)
          {
    
    	int res;
            char buf[255];
    
          // while (STOP==FALSE) {       /* loop for input */
              res = read(fd1,buf,255);   /* returns after 5 chars have been input */
             buf[res]='\0';               /* so we can printf... */
              //printf(":%s:%d\n", buf, res);
              printf("%s", buf);
              //if (buf[0]=='z') STOP=TRUE;
            //}
    
    
          }

  2. #2
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Can you be more specific than just saying it doesn't work? What does happen when you type something in? Does select() hang? Does select() return but no input is read? Does it crash?
    If you understand what you're doing, you're not learning anything.

  3. #3
    Registered User
    Join Date
    Nov 2005
    Posts
    13
    Hi itsme86,

    I am sorry. When I typed in from the keyboard, it seems that it took it but it does not seem it sends to the serial port. So I put in the printf statement and see what is in the sdtin buffer.

    And it seems that the buffer does not contained the CR - That is why when I type and hit Enter it does not write or send to the serial port ? I am not sure.

    for example,

    --------------------------------------------------
    printf("input is: [%s]",input);
    write(fd1, input,MAXLINE);
    --------------------------------------------------

    When I type in: ls[Enter]

    I see the printf statement showed: [ls

    *Note: There is a missing closing right bracket. So I am thinking the stdin does not contained the CR - This is why it does not write to the serial port ?

    I have tried: printf("input is: [%s].\r\n",input);

    But it still does not seem to work.

    Regards,

    z

  4. #4
    Registered User
    Join Date
    Nov 2005
    Posts
    13
    I tried to put in: printf("The length is: [%d]", strlen(input));

    And it seems that when I typed in: ls[Enter]

    The length is: [3] - So, it seems that it is including the CR but for some reasons, it does not send to the serial port.

  5. #5
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Are you confident about how the serial port is set-up? If not, trying to "learn how the select function works" and trying to learn how to work with a serial port at the same time may not be the best idea. I have never done the later, so I can't comment on that part.

    This is a nasty mistake:
    Code:
            write(fd1, input, MAXLINE);
    Write() is not a string oriented function and therefore does not care about '\0'. It's fine to use it with a string, but rather than MAXLINE, you should use something involving strlen(input). Otherwise it is going to write MAXLINE bytes from input -- all the stuff before the null terminator, the null terminator, and all the junk beyond that.

    You should be checking the return value of write:

    Code:
    int sent = write(fd1, input, strlen(input)+1);
    if (!sent) { // most likely, the other end disconnected }
    else if (sent == -1) {
        perror("write");
    }
    The "most likely" bit is: definitely WRT to network sockets, but I dunno about serial ports.

    You should also not assume that write wrote everything, which is another reason to check the return value. So, eg:

    Code:
    char input[]="hello world";
    int sent = 0, len = strlen(input)+1;
    while (sent < len) {
        sent += write(fd1, input+sent, len-sent);
        if (!sent) { // most likely, the other end disconnected }
        else if (sent == -1) {
             perror("write");
             break;
        }
    }
    But ideally, rather than trying to write all the input immediately this way, you would queue the data you want to write somehow and add a write FD_SET to select; if select returns a given fd is ready for writing, you would then call write once with the queued data, checking for an error and to see if all the data was sent. If not, you return the remaining data to the queue.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  6. #6
    Registered User
    Join Date
    Nov 2005
    Posts
    13
    Hi MK27,

    Thanks you for you help and you are right. I did not have the serial port setting up correctly. After I played around, I discovered that if I changed this settings to:

    ---------------------------
    newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    ---------------------------

    And took out the 'CRTSCTS'

    ---------------------------
    newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD;
    ---------------------------

    And it seems to work now. However, this settings are still not work with the modem. I actually intended to read the data from the serial port and not intended to read it from the modem. So, it did not matter.

    I only have Tx,Rx,Ground on the serial port side.

    Kind regards,

    z

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. TCP Server with select() function
    By netpumber in forum Windows Programming
    Replies: 6
    Last Post: 10-24-2011, 10:19 AM
  2. select function help
    By Annonymous in forum Networking/Device Communication
    Replies: 5
    Last Post: 07-24-2011, 03:14 PM
  3. help with select function in C
    By omega666 in forum C Programming
    Replies: 0
    Last Post: 04-05-2011, 04:18 PM
  4. int Select() Function
    By javiercubre in forum C Programming
    Replies: 2
    Last Post: 10-21-2006, 04:32 AM
  5. The select() function
    By Koral in forum C Programming
    Replies: 3
    Last Post: 05-02-2006, 09:19 AM