blob: ca6f779c4094a8113ba6664d542f7064bcf7a89b [file] [log] [blame]
#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;
}