I'm have a Linux application that is supposed to read from serial device /dev/ttyS0
. The serial device is opened in the following manner:
// Open the serial port
if((serial_device = open("/dev/ttyS0", O_RDWR | O_NOCTTY)) < 0){
fprintf(stderr, "ERROR: Open\n");
exit(EXIT_FAILURE);
}
// Get serial device attributes
if(tcgetattr(serial_device,&options)){
fprintf(stderr, "ERROR: Terminal Get Attributes\n");
exit(EXIT_FAILURE);
}
cfsetspeed(&options,speed); // Set I/O baud rates
cfmakeraw(&options); // Set options to transceive raw data
options.c_cflag |= (CLOCAL | CREAD); // Enable the receiver and set local mode
options.c_cflag &= ~CSTOPB; // 1 stop bit
options.c_cflag &= ~CRTSCTS; // Disable hardware flow control
options.c_cc[VMIN] = 1; // Minimum number of characters to read
options.c_cc[VTIME] = 10; // One second timeout
// Set the new serial device attributes
if(tcsetattr(serial_device, TCSANOW, &options)){
fprintf(stderr, "ERROR: Terminal Set Attributes\n");
exit(EXIT_FAILURE);
}
I then use the select
function to try and read from the serial device:
// Flush I/O Bffer
if(tcflush(serial_device,TCIOFLUSH)){
fprintf(stderr, "ERROR: I/O Flush\n");
exit(EXIT_FAILURE);
}
// Write message to board
if(write(serial_device,msg, strlen(msg)) != (int)strlen(msg)){
fprintf(stderr, "ERROR: Write\n");
exit(EXIT_FAILURE);
}
switch(select(serial_device+1, &set, NULL, NULL, &timeout)){
// Error
case -1:
fprintf(stderr, "ERROR: Select\n");
exit(EXIT_FAILURE);
// Timeout
case 0:
success = false;
break;
// Input ready
default:
// Try to read a character
switch(read(serial_device, &c, 1)){
// Error (miss)
case -1:
success = false;
break;
// Got a character
default:
msg[i++] = c;
break;
}
break;
}
// Set 200ms timeout
this->timeout.tv_sec = 0;
this->timeout.tv_usec = 200000;
}
I've tried reopening the port by determining if the read was not successful:
if(!success)
close(serial_device);
openPort(); // Same as above
}
However, the act of physically unplugging the serial connector will result in the application being unable to read anything further, and select will do nothing but time out. Plugging the connector back in while the application is running will not fix the issue, and select will continue to detect nothing.
The only way to successfully read from the serial port again is to restart the application. I'm wondering why this is, and how I can recover from the serial connector being unplugged at runtime.
read
returns 0). Perhaps that could be an issue? – Celadasuccess = failure
" is quite a humorous line of code! – Celadasuccess = false;
but neversuccess = true;
, so once an error occurs, you appear forever un-successful. – chux - Reinstate Monica