Thread: Serial port read() blocking

  1. #1
    Registered User
    Join Date
    Feb 2008
    Posts
    58

    Red face Serial port read() blocking

    Hi everyone

    I am having an infuriating time trying to get my c code to read from the serial port under Linux. When ever I execute the code the program blocks on the read() function even after I have inputted 5 characters (as defined in c_cc[VMIN]) - it should fall through and end the application however it just sits on the read() function.

    At the serial end I get a block of 5 characters printed to the screen after the obligatory 5 have been entered even though I believe I have told it not to echo the input characters...

    Ahhhhrgg! If can anyone could help me out I would be incredibly great full as this is driving me nuts!

    Many thanks

    Code:
    #include <fcntl.h>
    #include <termios.h>
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
            
    #define BAUDRATE B9600
    #define MODEMDEVICE "/dev/ttyS0"
    #define FALSE 0
    #define TRUE 1
           
          int main() {
          	
          	printf("Start\n");
          	
            int fd, res;
            struct termios oldtio,newtio;
            char buf[255];
            
            fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY ); 
            if (fd <0) {
    			printf("Failed to open %s", MODEMDEVICE);
    		} // if
            
            else {
            	printf("Port Opened\n");
    	        tcgetattr(fd,&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]     = 5;   /* blocking read until 5 chars received */
    	        tcflush(fd, TCIFLUSH);
    	        tcsetattr(fd,TCSANOW,&newtio);
    
    	        res = read(fd,buf,255);   /* returns after 5 chars have been input */
    	        buf[res]=0;               /* so we can printf... */
    	        printf("Input: %s\n", buf);
    	        tcsetattr(fd,TCSANOW,&oldtio);
            } // else */
          	printf("Done\n");
          	return 0;
          } // main

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Perhaps you should check the return values from the tcsetattr() calls, just in case that's what fails?

    Does it work if you get a newline (enter)?

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Registered User
    Join Date
    Feb 2008
    Posts
    58
    Sadly no, If I hit the enter button I get a couple of special characters sent back to the terminal window I am connecting the serial port to.

    ... and ah yes that's a good point; I have captured the output from each of the settings and displayed them below:

    Code:

    Code:
    int a = newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
    	        int b = newtio.c_iflag = IGNPAR;
    	        int c = newtio.c_oflag = 0;
    	        
    	        // set input mode (non-canonical, no echo,...) */
    	        int d = newtio.c_lflag = 0;
    	        int e = newtio.c_cc[VTIME]    = 0;   /* inter-character timer unused */
    	        int f = newtio.c_cc[VMIN]     = 5;   /* blocking read until 5 chars received */
    	        int g = tcflush(fd, TCIFLUSH);
    	        int h = tcsetattr(fd,TCSANOW,&newtio);
    Output:

    Start
    Port Opened
    newtio.c_cflag = -2147481411
    newtio.c_iflag = 4
    newtio.c_oflag = 0
    newtio.c_lflag = 0
    newtio.c_cc[VTIME] = 0
    newtio.c_cc[VMIN] = 5
    tcflush(fd, TCIFLUSH) = 0
    tcsetattr(fd,TCSANOW,&newtio) = 0
    I am not sure which (if any) values should return 0, I take it is encouraging that there are no -1's in there. Does that shed any light on the problem?

    again thank you for your help

  4. #4
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> At the serial end I get a block of 5 characters printed to the screen after the obligatory 5 have been entered even though I believe I have told it not to echo the input characters...

    How and what are you connecting to ttyS0? How are you sending bytes over ttyS0?

    gg

  5. #5
    Registered User
    Join Date
    Feb 2008
    Posts
    58
    I have a serial to USB adapter (that I have been using for a while) connecting to ttyS0 running to a laptop running Putty (all with correct baud, parity and no flow control etc...).

  6. #6
    Registered User
    Join Date
    Feb 2008
    Posts
    12
    Maybe usb-serial driver is not working properly.

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    A thought: Can you do "cat /dev/ttyS0" and send something to the serial port and can you see the result if you do "cat > /dev/ttyS0" to your other machine.

    You may well be able to open the device, but if some other process is also reading from it [for example the login process], then you are not going to get data to your process, nor are any changes you make to the termcap settings going to change the actual device settings.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    Registered User
    Join Date
    Feb 2008
    Posts
    58

    Smile

    You may well be able to open the device, but if some other process is also reading from it [for example the login process], then you are not going to get data to your process, nor are any changes you make to the termcap settings going to change the actual device settings.
    Ah ha! Indeed! - I think I have found the problem, it seems that the Kernel is using the serial port to print error messages to (for some reason) – I have turned it off and it works like a charm now! - though I may need to find out why I was getting errors! - heh

    Thanks everyone for all your help

  9. #9
    Registered User
    Join Date
    Apr 2009
    Posts
    1
    Hi !
    It seems that I am having the same problem as you. My program blocks on read...
    My problem is that I don't know how to know if the Kernel is using the serial port to print errors and of course I have no idea about how to change it !
    Could you please give me some hints about that??

    Thank you very much

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Serial Port Questions
    By valaris in forum Tech Board
    Replies: 2
    Last Post: 05-22-2009, 08:26 AM
  2. FTP program
    By jakemott in forum Linux Programming
    Replies: 14
    Last Post: 10-06-2008, 01:58 PM
  3. Can't Read From Serial Port
    By HalNineThousand in forum Linux Programming
    Replies: 14
    Last Post: 03-20-2008, 05:56 PM
  4. Serial Port problems
    By BeBu in forum Linux Programming
    Replies: 1
    Last Post: 04-01-2005, 08:18 AM
  5. serial port still wont work
    By alcoholic in forum C++ Programming
    Replies: 6
    Last Post: 10-31-2001, 12:51 PM