/* * File Name: uart_api.c * Workflow: implementation of the uart apis * Return Value: open_port return file describer as successful, * set_comfig return 0 as successful, * both function would return -1 as erroneaous */ /* Header files */ #include "uart_api.h" /* * Function Name: open_port * Workflow: get a file describer that follows the under requests: * 1, it must be a terminal device * 2, it is NONBLOCK mode */ int open_port(const char *com_port) { int fd; int flags; /* open port in read/write mode */ fd = open(com_port, O_RDWR, S_IRUSR | S_IWUSR); DebugLog("[DEBUG-INFO %s:%d]:Open from \"%s\" get fd: %d\n", __FUNCTION__, __LINE__, com_port, fd); if (fd < 0) { fprintf(stderr, "[%s:%d] open(): %s", __FUNCTION__, __LINE__, strerror(errno)); return -1; } /* check if fd is associated with a terminal */ if (isatty(fd) == 0) { fprintf(stderr, "[%s:%d] isatty(): %s", __FUNCTION__, __LINE__, strerror(errno)); close(fd); return -1; } /* file describer is set to non-block mode */ flags = fcntl(fd, F_GETFL); if (flags == -1) { fprintf(stderr, "[%s:%d] fcntl(): %s", __FUNCTION__, __LINE__, strerror(errno)); close(fd); return -1; } if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { fprintf(stderr, "[%s:%d] fcntl(): %s", __FUNCTION__, __LINE__, strerror(errno)); close(fd); return -1; } return fd; } /* * Function Name: set_comfig * Workflow: use termios to set the port under these requests: * 1, data bit fixed to 8 * 2, no parity check * 3, 1 stop bit * 4, no hardware control flow * 5, wait 3 seconds OR read 6 bytes, either reaches read * would return 6, buffer must be clean */ int set_comfig(int serial_fd, int baud_rate) { struct termios term_new, term_old; /* save old config */ if (tcgetattr(serial_fd, &term_old) == -1) { fprintf(stderr, "[%s:%d] tcgetattr(): %s", __FUNCTION__, __LINE__, strerror(errno)); return -1; } /* prepare new config struct to be used */ cfmakeraw(&term_new); term_new.c_cflag &= ~CSIZE; /* set baud rate */ switch (baud_rate) { case 9600: cfsetispeed(&term_new, B9600); cfsetospeed(&term_new, B9600); break; case 115200: cfsetispeed(&term_new, B115200); cfsetospeed(&term_new, B115200); break; default: fprintf(stderr, "[%s:%d] switch(baud_rate): %s", __FUNCTION__, __LINE__, strerror(errno)); return -1; } /* set data bit to 8 */ term_new.c_cflag &= ~CSIZE; term_new.c_cflag |= CS8; /* set no parity check */ term_new.c_cflag &= ~PARENB; term_new.c_iflag &= ~INPCK; /* set stop bit to 1 */ term_new.c_cflag &= ~CSTOPB; /* disable hardware flow control * term_new.c_cflag &= ~CRTSCTS; */ /* set to line buffered */ term_new.c_lflag |= ICANON; /* set EOF and EOF */ term_new.c_cc[VEOL] = '\0'; /* read() function would wait 3 seconds before return */ term_new.c_cc[VTIME] = 30; /* read() fuction would return if 6 bytes read */ term_new.c_cc[VMIN] = 6; /* flush IO buffer area */ tcflush(serial_fd, TCIFLUSH); tcflush(serial_fd, TCOFLUSH); /* enable setting */ if (tcsetattr(serial_fd, TCSANOW, &term_new) == -1) { fprintf(stderr, "[%s:%d] tcsetattr: %s", __FUNCTION__, __LINE__, strerror(errno)); return -1; } return 0; }