I'm receiving data from a serial port in C, using Serial Programming Guide for POSIX Operating Systems as a guide.
The data I receive should be always 10 bytes in length but I want to be sure that, if there is any error (more or less bytes received), reading will clear buffer before the next data arrive, so that there is always proper data in the buffer to be processed. I'm using select to monitor serial file descriptor and local socket. I figured out that I can clean serial buffer in case there was something left from previous transmission, when device is not sending for some period of time.
Question is: is this the right solution?
main.c:
loop_num=0;
si_processed=0;
while(TRUE) {
/* copy fd_set for select */
tmp_input=input;
n = select(max_fd,&tmp_input,NULL,NULL,NULL/*&timeout*/);
/* See if there was an error */
if (n<0)
perror("select failed");
else {
/* We have input */
if (FD_ISSET(serial_fd, &input)) {
if(!process_serial(serial_fd))
loop_num++;
}
if (FD_ISSET(local_socket, &input))
process_socket(local_socket);
}
if(loop_num>10) {
/* clear buffer */
si_processed=0;
loop_num=0;
}
fflush(stdout);
usleep(20000);
}
serial_port.c
char serial_buffer[256];
int process_serial(int serial_fd) {
int bytes;
int n,i;
char tmp_buffer[32];
ioctl(serial_fd, FIONREAD, &bytes);
if(!bytes)
return 0;
n=read(serial_fd, tmp_buffer, sizeof(tmp_buffer));
for(i=0;i<n;i++) {
serial_buffer[si_processed+i]=tmp_buffer[i];
}
si_processed+=n;
if(si_processed>=INPUT_BYTES_NUM/* defined as 10 */) {
serial_buffer[si_processed]='\0';
printf("read:%s\n",serial_buffer);
si_processed=0;
fflush(stdout);
}
return 1;
}
Some more info. I'm querying device every 5 seconds for data, and it should always respond with 10 bytes packets: so data should come fairly quickly into serial buffer, and then a few seconds of silence; sometimes however the device can send data on its own, I don't know when, but also as a 10 bytes packets.
I was doing some test with my program and minicom connected on the other side.
Until I was sending data like
1234567890
1234567890
program was reading what it supposed to read:
1234567890
Problem arises when I send on minicom:
12345678901234567890
Usually what was read was:
1234567890123456
so next, when I wrote on minicom proper data:
1234567890
program was reading
7890123456
and every next read was bad because of leftovers in buffer from previous read.
When I added clearing buffer after 1 or 2 seconds when nothing is read, then I'm sure any leftovers are cleared before next transmission.
I read about this VMIN settings but decided against because of this leftovers.
Also this data 1234567890
is just an example. In fact 10 bytes consist of:
- Byte #1 - always some constant to mark begining of transmission like 0xA5
- Byte #2 through #9 byte - data
- Byte #10 - control sum from all previous bytes.
So after I have 10 bytes packet received I can verify if it has proper data or is somehow corrupted: so if one transmission fails, I should be ok, especially when I can clear the buffer before next data coming in.