#include #include #include #include #include #include #include #include #include #include /** Reads the serial port, implementing a timeout. * * @param serialfd Fd returned earlier from serial_init (...) * @param buffer The destination address for received bytes. * @param buflen The maximum amount of space available in the buffer. * @param timeout_ms Timeout in milliseconds; zero to poll, -ve for infinite. * * @return -1 if error, 0 if timeout before any data rx'd, else num * bytes placed into buffer (up to max of buflen). * * @todo Perhaps implement win32 style serial handling */ int serial_read_with_timeout (int serialfd, void *buffer, int buflen, int timeout_ms) { struct timeval tmo, *tmoptr; int rv; fd_set readfds; //fd_set dummy1, dummy2; //FD_ZERO (&dummy1); FD_ZERO (&dummy2); FD_ZERO (&readfds); FD_SET (serialfd, &readfds); tmo.tv_sec = timeout_ms / 1000; tmo.tv_usec = (timeout_ms - (1000 * tmo.tv_sec)) * 1000; tmoptr = (timeout_ms < 0) ? NULL : &tmo; printf ("b4sel %d, %p, 0, 0, %p { %ld, %ld }\n", 1+serialfd, &readfds, tmoptr, tmo.tv_sec, tmo.tv_usec); rv = select (1 + serialfd, &readfds, NULL, NULL, tmoptr); //rv = select (1 + serialfd, &readfds, &dummy1, &dummy2, tmoptr); printf ("afsel\n"); // So what happened? rv is 0 => no fd set, -1 = error, else there must be readable data if (rv <= 0) return rv; // huzzah! there is some data to actually read.... // we could always do int bytes; ioctl(fd, FIONREAD, &bytes); // at this point, but nonblocking means we should be ok anyway....... rv = read (serialfd, buffer, buflen); return rv; } int main (int argc, const char **argv) { int rv, fd; char buff[8]; struct termios tio; fd = open ("/dev/com1", O_RDWR | O_BINARY | /* O_NONBLOCK | */ O_NOCTTY | O_NDELAY ); if (fd < 0) { fprintf (stderr, "oops error opening com1 %d\n", errno); return -1; } // Dunno for sure if this just duplicates setting O_NONBLOCK fcntl(fd, F_SETFL, FNDELAY); // Set the serial port to the baud rate chosen and 8n1. rv = tcgetattr (fd, &tio); if (rv) { fprintf (stderr, "Can't get options - error %d\n", errno); close (fd); return -1; } // Not implemented.... cfmakeraw (&tio); ... equivalent is.... tio.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON|IXOFF|IXANY|INPCK|IUCLC); tio.c_oflag &= ~OPOST; tio.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN|ECHOE); tio.c_cflag &= ~(CSIZE|PARENB); tio.c_cflag |= CS8 | CLOCAL | CREAD; // Now modify the defaults with chosen settings. rv = cfsetospeed (&tio, B57600); if (!rv) rv = cfsetispeed (&tio, B57600); if (rv) fprintf (stderr, "ERROR: Baud rate not recognized\n"); tio.c_cflag = (tio.c_cflag & ~CSIZE) | CS8; tio.c_cflag = (tio.c_cflag & ~PARENB); tio.c_cflag = (tio.c_cflag & ~CSTOPB); // and implement those settings. rv = tcsetattr (fd, TCSANOW, &tio); if (rv) { fprintf (stderr, "Error %d setting options\n", errno); close (fd); return -1; } // so try reading it rv = serial_read_with_timeout (fd, buff, 1, 250); fprintf (stderr, "serial read: rv %d char $%02x\n", rv, (unsigned int)buff[0]); // we done now. rv = close (fd); fprintf (stderr, "close gives %d\n", fd); return 0; }