| #include <stdio.h> |
| #include <stdlib.h> |
| #include <fcntl.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <string.h> |
| #include <errno.h> |
| #include <termios.h> |
| #include <unistd.h> |
| |
| #include "mbtk_log.h" |
| #include "ql/ql_uart.h" |
| |
| int Ql_UART_Open(const char* port, Enum_BaudRate baudrate, Enum_FlowCtrl flowctrl) |
| { |
| int fd; |
| if((fd = open(port, O_RDWR | O_NOCTTY)) < 0) |
| { |
| LOGE("open %s failed - %d", port, errno); |
| return -1; |
| } |
| |
| LOGD("Open %s success.", port); |
| |
| /* set newtio */ |
| struct termios newtio; |
| memset(&newtio, 0, sizeof(newtio)); |
| if (tcflush(fd, TCIOFLUSH) < 0) { |
| LOGE("Could not flush uart port"); |
| return -1; |
| } |
| |
| newtio.c_cc[VTIME] = 0; /* inter-character timer unused */ |
| newtio.c_cc[VMIN] = 0; /* blocking read until 5 chars received */ |
| |
| if(flowctrl == FC_RTSCTS) { |
| newtio.c_cflag |= CRTSCTS; |
| } else if(flowctrl == FC_XONXOFF) { |
| newtio.c_cflag |= (IXON | IXOFF); |
| } else { |
| // newtio.c_cflag |= CRTSCTS; |
| } |
| /* c_iflag 输入模式 */ |
| newtio.c_iflag &= ~(ICRNL | INLCR); |
| newtio.c_iflag &= ~(IXON | IXOFF | IXANY); |
| |
| // /* c_lflag 本地模式 */ |
| newtio.c_cflag &= ~ INPCK; |
| newtio.c_cflag |= (CLOCAL | CREAD); |
| |
| // /* c_lflag 本地模式 */ |
| newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); |
| /* c_oflag 输出模式 */ |
| newtio.c_oflag &= ~ OPOST; |
| newtio.c_oflag &= ~(ONLCR | OCRNL); |
| |
| /* c_cflag 控制模式 */ |
| newtio.c_cflag &= ~ CSIZE; |
| newtio.c_cflag |= CS8; |
| newtio.c_cflag &= ~ CSTOPB; |
| newtio.c_cflag &= ~ PARENB; |
| |
| switch(baudrate) |
| { |
| case B_300: |
| cfsetospeed(&newtio, B300); |
| cfsetispeed(&newtio, B300); |
| break; |
| case B_600: |
| cfsetospeed(&newtio, B600); |
| cfsetispeed(&newtio, B600); |
| break; |
| case B_1200: |
| cfsetospeed(&newtio, B1200); |
| cfsetispeed(&newtio, B1200); |
| break; |
| case B_2400: |
| cfsetospeed(&newtio, B2400); |
| cfsetispeed(&newtio, B2400); |
| break; |
| case B_4800: |
| cfsetospeed(&newtio, B4800); |
| cfsetispeed(&newtio, B4800); |
| break; |
| case B_9600: |
| cfsetospeed(&newtio, B9600); |
| cfsetispeed(&newtio, B9600); |
| break; |
| case B_19200: |
| cfsetospeed(&newtio, B19200); |
| cfsetispeed(&newtio, B19200); |
| break; |
| case B_38400: |
| cfsetospeed(&newtio, B38400); |
| cfsetispeed(&newtio, B38400); |
| break; |
| case B_57600: |
| cfsetospeed(&newtio, B57600); |
| cfsetispeed(&newtio, B57600); |
| break; |
| case B_115200: |
| cfsetospeed(&newtio, B115200); |
| cfsetispeed(&newtio, B115200); |
| break; |
| case B_230400: |
| cfsetospeed(&newtio, B230400); |
| cfsetispeed(&newtio, B230400); |
| break; |
| case B_460800: |
| cfsetospeed(&newtio, B460800); |
| cfsetispeed(&newtio, B460800); |
| break; |
| case B_921600: |
| cfsetospeed(&newtio, B921600); |
| cfsetispeed(&newtio, B921600); |
| break; |
| case B_3000000: |
| cfsetospeed(&newtio, B3000000); |
| cfsetispeed(&newtio, B3000000); |
| break; |
| case B_4000000: |
| cfsetospeed(&newtio, B4000000); |
| cfsetispeed(&newtio, B4000000); |
| break; |
| default: |
| cfsetospeed(&newtio, B115200); |
| cfsetispeed(&newtio, B115200); |
| break; |
| } |
| |
| if (tcsetattr(fd, TCSANOW, &newtio) < 0) { |
| LOGE("Can't set port setting"); |
| return -1; |
| } |
| /* Blocking behavior */ |
| fcntl(fd, F_SETFL, 0); |
| |
| return fd; |
| } |
| |
| int Ql_UART_Read(int fd, char* buf, unsigned int buf_len) |
| { |
| return read(fd, buf, buf_len); |
| } |
| |
| |
| int Ql_UART_Write(int fd, const char* buf, unsigned int buf_len) |
| { |
| return write(fd, buf, buf_len); |
| } |
| |
| |
| int Ql_UART_SetDCB(int fd, ST_UARTDCB *dcb) |
| { |
| struct termios newtio; |
| memset(&newtio, 0, sizeof(newtio)); |
| |
| if(tcgetattr(fd, &newtio) != 0) |
| { |
| LOGE("Serial port configuration backup errno"); |
| return -1; |
| } |
| |
| switch(dcb->baudrate) |
| { |
| case B_300: |
| cfsetospeed(&newtio, B300); |
| cfsetispeed(&newtio, B300); |
| break; |
| case B_600: |
| cfsetospeed(&newtio, B600); |
| cfsetispeed(&newtio, B600); |
| break; |
| case B_1200: |
| cfsetospeed(&newtio, B1200); |
| cfsetispeed(&newtio, B1200); |
| break; |
| case B_2400: |
| cfsetospeed(&newtio, B2400); |
| cfsetispeed(&newtio, B2400); |
| break; |
| case B_4800: |
| cfsetospeed(&newtio, B4800); |
| cfsetispeed(&newtio, B4800); |
| break; |
| case B_9600: |
| cfsetospeed(&newtio, B9600); |
| cfsetispeed(&newtio, B9600); |
| break; |
| case B_19200: |
| cfsetospeed(&newtio, B19200); |
| cfsetispeed(&newtio, B19200); |
| break; |
| case B_38400: |
| cfsetospeed(&newtio, B38400); |
| cfsetispeed(&newtio, B38400); |
| break; |
| case B_57600: |
| cfsetospeed(&newtio, B57600); |
| cfsetispeed(&newtio, B57600); |
| break; |
| case B_115200: |
| cfsetospeed(&newtio, B115200); |
| cfsetispeed(&newtio, B115200); |
| break; |
| case B_230400: |
| cfsetospeed(&newtio, B230400); |
| cfsetispeed(&newtio, B230400); |
| break; |
| case B_460800: |
| cfsetospeed(&newtio, B460800); |
| cfsetispeed(&newtio, B460800); |
| break; |
| case B_921600: |
| cfsetospeed(&newtio, B921600); |
| cfsetispeed(&newtio, B921600); |
| break; |
| case B_3000000: |
| cfsetospeed(&newtio, B3000000); |
| cfsetispeed(&newtio, B3000000); |
| break; |
| case B_4000000: |
| cfsetospeed(&newtio, B4000000); |
| cfsetispeed(&newtio, B4000000); |
| break; |
| default: |
| LOGD("No set speed."); |
| break; |
| } |
| |
| switch(dcb->databit) |
| { |
| case DB_CS5: |
| newtio.c_cflag &= ~CSIZE; |
| newtio.c_cflag |= CS5; |
| break; |
| case DB_CS6: |
| newtio.c_cflag &= ~CSIZE; |
| newtio.c_cflag |= CS6; |
| break; |
| case DB_CS7: |
| newtio.c_cflag &= ~CSIZE; |
| newtio.c_cflag |= CS7; |
| break; |
| case DB_CS8: |
| newtio.c_cflag &= ~CSIZE; |
| newtio.c_cflag |= CS8; |
| break; |
| default: |
| LOGD("No set databit."); |
| break; |
| } |
| |
| if(dcb->stopbit == SB_2) { |
| newtio.c_cflag |= CSTOPB; |
| } else { |
| newtio.c_cflag &= ~CSTOPB; |
| } |
| |
| switch (dcb->parity) |
| { |
| case PB_ODD:// 奇校验 |
| newtio.c_cflag |= PARENB; |
| newtio.c_cflag |= PARODD; |
| break; |
| case PB_EVEN:// 偶校验 |
| newtio.c_cflag |= PARENB; |
| newtio.c_cflag &= ~PARODD; |
| break; |
| case PB_NONE:// 无奇偶校验 |
| newtio.c_cflag &= ~PARENB; |
| break; |
| default: |
| LOGD("No set parity."); |
| break; |
| } |
| |
| switch (dcb->flowctrl) |
| { |
| case FC_RTSCTS: |
| newtio.c_cflag |= CRTSCTS; |
| tcflush(fd, TCIFLUSH); |
| break; |
| case FC_XONXOFF: |
| newtio.c_iflag |= (IXON | IXOFF); |
| tcflush(fd, TCIFLUSH); |
| break; |
| case FC_NONE: |
| newtio.c_cflag &= ~CRTSCTS; |
| newtio.c_iflag &= ~(IXON | IXOFF); |
| tcflush(fd, TCIFLUSH); |
| break; |
| default: |
| LOGD("No set flow ctrl."); |
| break; |
| } |
| |
| if(tcsetattr(fd, TCSANOW, &newtio) != 0) |
| { |
| LOGE("Serial port configuration backup errno"); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| |
| int Ql_UART_GetDCB(int fd, ST_UARTDCB *dcb) |
| { |
| struct termios newtio; |
| memset(&newtio, 0, sizeof(newtio)); |
| |
| if(tcgetattr(fd, &newtio) != 0) |
| { |
| LOGE("Serial port configuration backup errno"); |
| return -1; |
| } |
| |
| switch(cfgetispeed(&newtio)) |
| { |
| case B300: |
| dcb->baudrate = B_300; |
| break; |
| case B600: |
| dcb->baudrate = B_600; |
| break; |
| case B1200: |
| dcb->baudrate = B_1200; |
| break; |
| case B2400: |
| dcb->baudrate = B_2400; |
| break; |
| case B4800: |
| dcb->baudrate = B_4800; |
| break; |
| case B9600: |
| dcb->baudrate = B_9600; |
| break; |
| case B19200: |
| dcb->baudrate = B_19200; |
| break; |
| case B38400: |
| dcb->baudrate = B_38400; |
| break; |
| case B57600: |
| dcb->baudrate = B_57600; |
| break; |
| case B115200: |
| dcb->baudrate = B_115200; |
| break; |
| case B230400: |
| dcb->baudrate = B_230400; |
| break; |
| case B460800: |
| dcb->baudrate = B_460800; |
| break; |
| case B921600: |
| dcb->baudrate = B_921600; |
| break; |
| case B3000000: |
| dcb->baudrate = B_3000000; |
| break; |
| case B4000000: |
| dcb->baudrate = B_4000000; |
| break; |
| default: |
| dcb->baudrate = B_115200; |
| break; |
| } |
| |
| switch(newtio.c_cflag & CSIZE) |
| { |
| case CS5: |
| dcb->databit = DB_CS5; |
| break; |
| case CS6: |
| dcb->databit = DB_CS6; |
| break; |
| case CS7: |
| dcb->databit = DB_CS7; |
| break; |
| case CS8: |
| dcb->databit = DB_CS8; |
| break; |
| default: |
| dcb->databit = DB_CS8; |
| break; |
| } |
| |
| if(newtio.c_cflag & CSTOPB) { |
| dcb->stopbit = SB_2; |
| } else { |
| dcb->stopbit = SB_1; |
| } |
| |
| if(newtio.c_cflag & PARENB) { // 启用了奇偶校验 |
| if(newtio.c_cflag & PARODD) { |
| dcb->parity = PB_ODD; // 奇校验 |
| } else { |
| dcb->parity = PB_EVEN; // 偶校验 |
| } |
| } else { |
| dcb->parity = PB_NONE; |
| } |
| |
| if(newtio.c_cflag & CRTSCTS) { |
| dcb->flowctrl = FC_RTSCTS; |
| } else if(newtio.c_iflag & (IXON | IXOFF) == (IXON | IXOFF)){ |
| dcb->flowctrl = FC_XONXOFF; |
| } else { |
| dcb->flowctrl = FC_NONE; |
| } |
| |
| return 0; |
| } |
| |
| |
| int Ql_UART_IoCtl(int fd, unsigned int cmd, void* pValue) |
| { |
| return 0; |
| } |
| |
| |
| int Ql_UART_Close(int fd) |
| { |
| if (fd <= 0) |
| return -1; |
| |
| close(fd); |
| return 0; |
| } |
| |