Date: Wed, 21 Jan 2004 16:43:15 -0500 From: "J. Seth Henry" <jshamlet@comcast.net> To: freebsd-questions@freebsd.org Subject: Need help finding bug using select() Message-ID: <200401211643.15164.jshamlet@comcast.net>
next in thread | raw e-mail | index | archive | help
Guys, I am, needless to say, still fairly new to programming under *nix - despite months of learning. So far, I have been able to work out a lot of things, but this issue with the select statement has me stumped. I am attempting to listen to a serial port, and perform actions when data is received -or- simply wait a fixed amount of time. The waiting a fixed amount of time works great, but select doesn't return on serial events. Would anyone be so kind as to tell me what I'm doing wrong? I know the data is being received - as I can read the port periodically (via the timeout) and I get what I am expecting. I would rather not wait until the timer expires, though. Here is the code: (from main.c) #ifdef HAVE_CONFIG_H #include <config.h> #endif #include <stdio.h> #include <unistd.h> #include <signal.h> #include <string.h> #include <stdarg.h> /* local includes */ #include <params.h> #include <io_func.h> #include <utility_func.h> int message_proc(daemon_obj *daemon_info); int main(int argc, char **argv) { int retval, i; /* Setup the structures */ daemon_obj daemon_info; thermostat_obj stat_info[MAX_STATS]; fd_set stat_set; struct timeval tick_info; init_daemon_info(&daemon_info); init_stat_info(stat_info); retval = read_conf_file(&daemon_info, stat_info); /* At least for now, the thermostat is the only device that can generate unanticipated data */ if(open_ioport(&daemon_info, STAT) == SUCCESS) { FD_ZERO(&stat_set); FD_SET(daemon_info.ioport.stat_fd, &stat_set); } else { return IO_ERROR; } /* They relay board doesn't generate unanticipated data so there is no point in selecting on it */ if(open_ioport(&daemon_info, OVRD) != SUCCESS) return IO_ERROR; tick_info.tv_sec = daemon_info.params.tick_rate; tick_info.tv_usec = 0; retval = sync_stat_time(&daemon_info); printf("Thermostat time/date updated\n"); do{ retval = query_sensors(&daemon_info, stat_info, 0); if(retval != SUCCESS) return retval; retval = query_status(&daemon_info, stat_info, 0); for(i = 0; i < MAX_SENSORS; i++) if(stat_info[0].sensor_info[i].is_present == TRUE) printf("%d: %d%c ", i, stat_info[0].sensor_info[i].value, stat_info[0].sensor_info[i].suffix); printf("SYS_MODE: %d ",stat_info[0].status_info.sys_status); printf("SAMPLE: %e ", stat_info[0].samples); retval = select(FD_SETSIZE, &stat_set, NULL, NULL, &tick_info); if(retval != 0) message_proc(&daemon_info); printf("Returned: %d \n", retval); } while(1); return 0; } int message_proc(daemon_obj *daemon_info) { char tbuffer[MAX_RX_LEN]; char *bufptr; int nbytes, tries, int_fd; int i; i = MAX_RX_LEN; while ((nbytes = read(int_fd, bufptr, tbuffer + sizeof(tbuffer) - bufptr - 1)) > 0) { bufptr += nbytes; i--; if (bufptr[-1] == '\n' || bufptr[-1] == '\r') break; if (i == 0) return(OVR_FLOW); } *bufptr = '\0'; bufptr = tbuffer; printf("%s\n",tbuffer); return (SUCCESS); } (from io_func.c) #include <stdio.h> /* Standard input/output definitions */ #include <stdlib.h> #include <unistd.h> /* UNIX standard function definitions */ #include <fcntl.h> /* File control definitions */ #include <termios.h> /* POSIX terminal control definitions */ #include <sys/types.h> /* Local includes */ #include <params.h> /* open_port opens a serial port for I/O daemon_info -> points to the common daemon_info structure stat_or_ovrd -> determines which set of io information to use 0 = statnet info, 1 = override relay info */ int open_ioport(daemon_obj *daemon_info, int stat_or_ovrd) { char *device, *buffer_to, *buffer_from; int int_fd, int_baudrate; struct termios options; if(stat_or_ovrd == STAT) { device = daemon_info->ioport.stat_ioport; int_baudrate = daemon_info->ioport.stat_baudrate; } else if(stat_or_ovrd == OVRD) { if( daemon_info->ioport.port_linked == FALSE) { device = daemon_info->ioport.ovrd_ioport; int_baudrate = daemon_info->ioport.ovrd_baudrate; } else if( daemon_info->ioport.port_linked == TRUE) { buffer_from = daemon_info->ioport.stat_ioport; buffer_to = daemon_info->ioport.ovrd_ioport; strcpy(buffer_to, buffer_from); buffer_to[sizeof(buffer_to) - 1] = NULL; daemon_info->ioport.ovrd_baudrate = daemon_info->ioport.stat_baudrate; daemon_info->ioport.ovrd_fd = daemon_info->ioport.stat_fd; return SUCCESS; } } else { return FAILURE; } int_fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY); if(stat_or_ovrd == STAT){ daemon_info->ioport.stat_fd = int_fd; } else { daemon_info->ioport.ovrd_fd = int_fd; } if (int_fd == FAILURE) { if(stat_or_ovrd == 0){ printf("Unable to open thermostat port at %s\n", device); } else { printf("Unable to open override relay at %s\n", device); } return(IO_ERROR); } else { fcntl(int_fd, F_SETFL, 0); } tcgetattr(int_fd, &options); if(int_baudrate == 19200) { cfsetispeed(&options, B19200); cfsetospeed(&options, B19200); } else { if(int_baudrate == 9600) { cfsetispeed(&options, B9600); cfsetospeed(&options, B9600); } else { printf("Invalid port speed selected!\n"); if(stat_or_ovrd == 0){ daemon_info->ioport.stat_fd = FAILURE; } else { daemon_info->ioport.ovrd_fd = FAILURE; } return(IO_ERROR); } } options.c_cflag |= (CLOCAL | CREAD ); options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CSIZE; options.c_cflag |= CS8; options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); options.c_iflag |= (INPCK | ISTRIP); options.c_oflag &= ~OPOST; options.c_cc[VMIN] = 0; options.c_cc[VTIME] = 10; tcsetattr(int_fd, TCSANOW, &options); return SUCCESS; } /* stat_comm writes out the contents of an incoming buffer to the thermostat, and posts the results in an outgoing buffer. daemon_info -> points to the file descriptors stat_or_ovrd -> determines which device to send data to (0 = statnet, else = relay) wr_buffer -> incoming buffer (text to print) rd_buffer -> results of communications */ int stat_comm(daemon_obj *daemon_info, int stat_or_ovrd, char *wr_buffer, char *rd_buffer) { char tbuffer[MAX_RX_LEN]; char *bufptr; int nbytes, tries, int_fd; int i; if(stat_or_ovrd == 0){ int_fd = daemon_info->ioport.stat_fd; } else { int_fd = daemon_info->ioport.ovrd_fd; } bufptr = wr_buffer; for (tries = 0; tries < 3; tries ++) { if (write(int_fd, bufptr, strlen(bufptr)) < 3) continue; bufptr = tbuffer; i = MAX_RX_LEN; while ((nbytes = read(int_fd, bufptr, tbuffer + sizeof(tbuffer) - bufptr - 1)) > 0) { bufptr += nbytes; i--; if (bufptr[-1] == '\n' || bufptr[-1] == '\r') break; if (i == 0) return(COMM_ERROR); } *bufptr = '\0'; bufptr = tbuffer; sprintf(rd_buffer,"%s\n",tbuffer); if( strlen(bufptr) > 1 ){ return (SUCCESS); } else { sprintf(rd_buffer,"ERROR\n"); return(CMD_ERROR); } } return (COMM_ERROR); } I have verified that the functions do work, and the hardware is being set up correctly. BTW - the code in message_proc is temporary. I will add the real code once I get past this problem. (don't laugh - I'm learning as I go, and I will probably completely rewrite all of this once I understand what to do) Thanks! Seth Henry
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200401211643.15164.jshamlet>