// // Created by YY on 2017/9/5. // #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../jni_log.h" #include "serial_port.h" using namespace std; SerialPort::SerialPort(struct serial_config cfg) { this->cfg = cfg; } SerialPort::~SerialPort() { UninitSerialPort(); } int SerialPort::setRTS(int level) { int status; if (ioctl(fd, TIOCMGET, &status) == -1) { LOGD("setRTS(): TIOCMGET"); return 0; } if (level) status |= TIOCM_RTS; else status &= ~TIOCM_RTS; if (ioctl(fd, TIOCMSET, &status) == -1) { LOGD("setRTS(): TIOCMSET"); return 0; } return 1; } /********************************************************************* * PUBLIC FUNCTIONS */ int SerialPort::SetSerialPort(int fd, int speed, int databits, char parity, int stopbits, int flowctrl) { int status = 0; struct termios opt; int speed_arr[] = {B921600, B576000, B500000, B460800, B230400, B115200, B38400, B19200, B9600, B4800, B2400, B1200, B300}; int name_arr[] = {921600, 576000, 500000, 460800, 230400, 115200, 38400, 19200, 9600, 4800, 2400, 1200, 300}; status = tcgetattr(fd, &opt); if (status != 0) { goto SET_SERIAL_PORT_END; } status = tcflush(fd, TCIOFLUSH); if (status != 0) { goto SET_SERIAL_PORT_END; } //Set baud for (int i = 0; i < sizeof(speed_arr) / sizeof(int); i++) { if (speed == name_arr[i]) { cfsetispeed(&opt, speed_arr[i]); cfsetospeed(&opt, speed_arr[i]); break; } } //Set databit opt.c_cflag &= ~CSIZE; if (databits == 7) { opt.c_cflag |= CS7; } else { opt.c_cflag |= CS8; } //Set parity switch (parity) { case 'E': case 'e': opt.c_cflag |= PARENB; /*Enable parity*/ opt.c_cflag &= ~PARODD; opt.c_iflag |= INPCK; /*Enable pairty checking*/ break; case 'O': case 'o': opt.c_cflag |= PARENB | PARODD; opt.c_iflag |= INPCK; break; case 'N': case 'n': default: opt.c_cflag &= ~PARENB; opt.c_iflag &= ~INPCK; break; } //Set stop if (stopbits == 2) { opt.c_cflag |= CSTOPB; } else { opt.c_cflag &= ~CSTOPB; } opt.c_cflag |= CLOCAL | CREAD; //Set raw mode opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/ opt.c_oflag &= ~OPOST; /*Output*/ opt.c_iflag &= ~(IXON | IXOFF | IXANY | ICRNL); //Disable XON/XOFF flowcontrol opt.c_iflag &= ~(ICRNL | INLCR); //Disable 0x0d and 0x0a convert opt.c_cc[VTIME] = 0;//150; //15 seconds 150x100ms = 15s opt.c_cc[VMIN] = 1; //Recv one char, read() will return if (flowctrl) { opt.c_cflag |= CRTSCTS; } else { opt.c_cflag &= ~CRTSCTS; //Disable hard flowcontrol } tcflush(fd, TCIOFLUSH); status = tcsetattr(fd, TCSANOW, &opt); SET_SERIAL_PORT_END: if (status != 0) { LOGD("Serial Port set fail"); } else { LOGD("Serial Port set success"); } // setRTS(fd, 1); return status; } int SerialPort::OpenSerialPort(const char *name) { int uart_fd; // uart_fd = open(name, O_RDWR /*| O_NONBLOCK/*| O_NOCTTY | O_NDELAY*/); uart_fd = open(name, O_RDWR | O_NOCTTY); LOGD("open serial port fd = %d", uart_fd); return uart_fd; } void SerialPort::CloseSerialPort(int fd) { close(fd); } int SerialPort::WriteSerialPort(const void *buf, int len) { int ret = -1; int fds_ret; struct timeval tv; fd_set wrfds; if (fd <= 0) { return -1; } tv.tv_sec = 1; tv.tv_usec = 0; FD_ZERO(&wrfds); //clean FD_SET(fd, &wrfds); //set lock_guard lock(mtx); fds_ret = select(fd + 1, NULL, &wrfds, NULL, &tv); if (fds_ret < 0) { LOGE("Serial port select error\n"); } else if(fds_ret == 0) { LOGE("Serial port write timeout\n"); } else if(FD_ISSET(fd, &wrfds)) { ret = write(fd, buf, len); //serial write data if (ret != len ) { LOGE("Serial Port Error\n"); tcflush(fd, TCOFLUSH); } } else { LOGE("Serial Port error 2\n"); } return ret; } int SerialPort::InitSerialPort(void) { // char name[32]; // // if (id == UART_0) { // strcpy(name, "/dev/ttyCH341USB5"); // } else if (id == UART_1) { // strcpy(name, "/dev/ttyCH341USB6"); // } else { // return -1; // } fd = OpenSerialPort(cfg.name); if (fd <= 0) { return -1; } if (SetSerialPort(fd, cfg.baud, cfg.data_bit, cfg.verify_bit, cfg.stop_bit, cfg.flow_ctrl) != 0) { return -2; } return 0; } void SerialPort::UninitSerialPort(void) { if (fd > 0) { CloseSerialPort(fd); fd = 0; } } int SerialPort::ReadSerialPort(uint8_t *out, uint16_t length) { if (fd <= 0) return 0; struct timeval tv; fd_set wrfds; tv.tv_sec = 5; tv.tv_usec = 0; FD_ZERO(&wrfds); //clean FD_SET(fd, &wrfds); //set int fds_ret = select(fd + 1, &wrfds, NULL, NULL, &tv); if (fds_ret < 0) { return -1; } else if(fds_ret == 0) { // timeout return -2; } else if(FD_ISSET(fd, &wrfds)) { return read(fd, out, length); } return -3; }