blob: 68c32f1271d374eee1bdfa1f47f1e81dd029cf43 [file] [log] [blame]
#include "port.h"
/**
* @brief Send Data to serial port
* @param fd:file desc
* @param cmd:data pointer
* @param cmd_len:data length
* @retval SUCCESS/FAIL
*/
int uart_send(int fd, const uint8_t *cmd, int cmd_len)
{
int ret = FAIL;
ret = write(fd, cmd, cmd_len);
if(ret < 0)
{
HDBD_LOG("[%s %d]write port failed,ret: %d\n", __FUNCTION__, __LINE__, ret);
return FAIL;
}
return SUCCESS;
}
/**
* @brief Receive data from serial port0
* @param fd:file desc
* @param buf:receive buffer
* @param actual_length:receive data length
* @param timeout:para of timeout
* @retval SUCCESS/FAIL
*/
int uart_recv(int fd, uint8_t *buf, int *actual_length, int timeout)
{
int ret;
int temp = 0;
int len = *actual_length;
uint8_t tempBuf[128] = {0};
int errorCount = 0;
fd_set rd;
struct timeval tv;
tv.tv_sec = timeout;
tv.tv_usec = 0;
FD_ZERO(&rd);
FD_SET(fd, &rd);
*actual_length = 0;
HDBD_LOG("[%s %d] len:%d\n", __FUNCTION__, __LINE__, len);
while(1)
{
ret = select(fd + 1, &rd, NULL, NULL, &tv);
if(ret > 0){
if (FD_ISSET(fd, &rd)) {
temp = read(fd, tempBuf, 128);
if(temp > 0)
{
errorCount = 0;
if((*actual_length + temp) <= len)
{
memcpy(buf+*actual_length, tempBuf, temp);
*actual_length += temp;
}
else
{
memcpy(buf+*actual_length, tempBuf, (len - *actual_length));
*actual_length = len;
}
}
else
{
errorCount++;
}
HDBD_LOG("[%s %d]len:%d, *actual_length:%d, temp:%d\n", __FUNCTION__, __LINE__, len, *actual_length, temp);
}
}
else if(ret == 0)
{
HDBD_LOG("[%s %d]timeout\n", __FUNCTION__, __LINE__);
if(*actual_length <= 2)
{
goto ERR1;
}
else
{
break;
}
}
else
{
HDBD_LOG("[%s %d] select error!\n", __FUNCTION__, __LINE__);
goto ERR1;
}
if((*actual_length >= len) || (errorCount >= 5))
{
HDBD_LOG("[%s %d]*actual_length:%d, recv sucess,break\n", __FUNCTION__, __LINE__, *actual_length);
break;
}
}
HDBD_LOG("[%s %d]*actual_length:%d, ret:%d\n", __FUNCTION__, __LINE__, *actual_length, ret);
return SUCCESS;
ERR1:
return FAIL;
}
int UartRead(int fd, uint8_t *RxBuff, long RxLen)
{
#if 1
int GetRxLen=0;
int index;
while(RxLen){
//printf("RxLen=%d\r\n", RxLen);
index = read(fd, RxBuff+GetRxLen, 1);
//printf("index=%d\r\n", index);
GetRxLen += index;
//printf("GetRxLen=%d\r\n", GetRxLen);
RxLen--;
//printf("RxLen=%d\r\n", RxLen);
if(index == 0)
{
return GetRxLen;
}
}
return GetRxLen ;
#else
int GetRxLen=0;
while(RxLen){
//printf("[RxLen=%ld]\r\n", RxLen);
GetRxLen += read(fd, RxBuff+GetRxLen, 1);
RxLen--;
}
return GetRxLen ;
#endif
}
/**
* @brief Write gpio node
* @param path:path of gpio node
* @param value:'1' or '0'
* @retval SUCCESS/FAIL
*/
int write_gpio(char const* path, int value)
{
int fd = -1;
char buffer[20] = {0};
int bytes = 0;
ssize_t amt = 0;
memset(buffer, 0x0, sizeof(buffer));
fd = open(path, O_RDWR);
if (fd >= 0)
{
bytes = snprintf(buffer, sizeof(buffer), "%d\n", value);
amt = write(fd, buffer, (size_t)bytes);
close(fd);
return amt == -1 ? -errno : 0;
}
else
{
HDBD_LOG("[%s %d]write_int failed to open %s, errno is %d \n", __FUNCTION__, __LINE__, path, errno);
}
return -errno;
}
/**
* @brief Read gpio node
* @param path:path of gpio node
* @param value:'1' or '0'
* @retval SUCCESS/FAIL
*/
int read_gpio(char const* path)
{
int fd = -1;
char buffer[20] = {0};
ssize_t amt = 0;
memset(buffer, 0x0, sizeof(buffer));
fd = open(path, O_RDWR);
if (fd >= 0)
{
amt = read(fd, buffer, 1);
close(fd);
HDBD_LOG("[%s %d]read to <%s>, value is <%zd> \n", __FUNCTION__, __LINE__, path, amt);
return 0;
}
else
{
HDBD_LOG("[%s %d]read failed to open <%s>, errno is <%d> \n", __FUNCTION__, __LINE__, path, errno);
}
return -1;
}
/**
* @brief Set serial port Para
* @param fd:file desc
* @param speed:baudrate
* @param flow_ctrl:flow control flag
* @param databits:data bits
* @param stopbits:stop bits
* @param parity:parity flag
* @retval SUCCESS/FAIL
*/
int uart_set(int fd, int speed, int flow_ctrl, int databits, int stopbits, int parity)
{
int i;
int speed_arr[11] = {B921600, B576000, B460800,B230400, B115200, B19200, B9600, B4800, B2400, B1200, B300};
int name_arr[11] = {921600,576000,460800,230400, 115200, 19200, 9600, 4800, 2400, 1200, 300};
struct termios options;
if ( tcgetattr( fd, &options) != 0)
{
HDBD_LOG("[%s %d]get serial options Fail\n", __FUNCTION__, __LINE__);
return FAIL;
}
for ( i = 0; i < 11; i++) /* sizeof(speed_arr) / sizeof(int) */
{
if (speed == name_arr[i])
{
cfsetispeed(&options, speed_arr[i]);
cfsetospeed(&options, speed_arr[i]);
break;
}
}
options.c_cflag |= CLOCAL;
options.c_cflag |= CREAD;
switch (flow_ctrl)
{
case 0 :
options.c_cflag &= ~CRTSCTS;
break;
case 1 :
options.c_cflag |= CRTSCTS;
break;
case 2 :
options.c_cflag |= IXON | IXOFF | IXANY;
break;
}
options.c_cflag &= ~CSIZE;
switch (databits)
{
case 5 :
options.c_cflag |= CS5;
break;
case 6 :
options.c_cflag |= CS6;
break;
case 7 :
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag |= CS8;
break;
default:
HDBD_LOG("[%s %d] Unsupported data size\n", __FUNCTION__, __LINE__);
return FAIL;
}
switch (parity)
{
case 'n':
case 'N':
options.c_cflag &= ~PARENB;
options.c_iflag &= ~INPCK;
break;
case 'o':
case 'O':
options.c_cflag |= (PARODD | PARENB);
options.c_iflag |= INPCK;
break;
case 'e':
case 'E':
options.c_cflag |= PARENB;
options.c_cflag &= ~PARODD;
options.c_iflag |= INPCK;
break;
case 's':
case 'S':
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
break;
default:
HDBD_LOG("[%s %d] Unsupported parity\n", __FUNCTION__, __LINE__);
return FAIL;
}
switch (stopbits)
{
case 1:
options.c_cflag &= ~CSTOPB; break;
case 2:
options.c_cflag |= CSTOPB; break;
default:
HDBD_LOG("[%s %d] Unsupported stop bits\n", __FUNCTION__, __LINE__);
return FAIL;
}
options.c_oflag &= ~OPOST;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
//options.c_lflag &= ~(ISIG | ICANON);
options.c_cc[VTIME] = 1;
options.c_cc[VMIN] = 1;
tcflush(fd, TCIFLUSH);
if (tcsetattr(fd, TCSANOW, &options) != 0)
{
HDBD_LOG("[%s %d] com set error!\n", __FUNCTION__, __LINE__);
return FAIL;
}
return SUCCESS;
}
/**
* @brief Init serial port
* @param fd:file desc
* @param speed:baudrate
* @param flow_ctrl:flow control flag
* @param databits:data bits
* @param stopbits:stop bits
* @param parity:parity flag
* @retval SUCCESS/FAIL
*/
int uart_init(int fd, int speed, int flow_ctrl, int databits, int stopbits, int parity)
{
if (uart_set(fd, speed, flow_ctrl, databits, stopbits, parity) == FAIL)
{
HDBD_LOG("[%s %d] Uart init false\n", __FUNCTION__, __LINE__);
return FAIL;
}
else
{
return SUCCESS;
}
}
/**
* @brief Init serial port
* @param fd:uart fd
* @param selector:TCIOFLUSH/TCIFLUSH
*/
void clearBuffer(int fd, int selector)
{
tcflush(fd, selector);
}
/**
* @brief open serial port
* @param GPS_DEVICE:uart port
* @retval SUCCESS/FAIL
*/
int uart_open(unsigned char * GPS_DEVICE)
{
int fd = -1;
int uart_init_ret = -1;
//*****************************************************************************
fd = open((char *)GPS_DEVICE, O_RDWR|O_NOCTTY|O_NDELAY);
if( fd < 0)
{
HDBD_LOG("[%s %d] : open port ERROR..state->fd=%d, errno=%d\n",__FUNCTION__, __LINE__, fd, errno);
return -1;
}
HDBD_LOG("[%s %d] : open port succceed..state->fd=%d OK\n", __FUNCTION__, __LINE__, fd);
/* set port */
if(fcntl( fd,F_SETFL,0)<0)
{
HDBD_LOG("[%s %d] : fcntl F_SETFL Fail\n", __FUNCTION__, __LINE__);
return -1;
}
tcflush(fd, TCIOFLUSH);
uart_init_ret = uart_init(fd, 115200, 0, 8, 1, 'N');
if (-1 == uart_init_ret)
{
HDBD_LOG("[%s %d] : uart_init_ret is <%d>, return -1\n", __FUNCTION__, __LINE__, uart_init_ret);
return -1;
}
HDBD_LOG("[%s %d] : Port setup finished..OK\n", __FUNCTION__, __LINE__);
//**********************************************************************
return fd;
}
int uart_close(int fd)
{
close(fd);
return 0;
}
void SetOpt(int fd)
{
static struct termios termold, termnew;
tcgetattr(fd, &termold);
bzero(&termnew, sizeof(termnew));
termnew.c_iflag &= ~(ICRNL | IGNCR);
termnew.c_cflag |= CLOCAL | CREAD; //CLOCAL:忽略modem控制线 CREAD:打开接受者
termnew.c_cflag &= ~CSIZE;
termnew.c_cflag |= CS8;
termnew.c_cflag &= ~CRTSCTS;
termnew.c_cflag &= ~PARENB;
cfsetispeed(&termnew, B115200);
cfsetospeed(&termnew, B115200);
termnew.c_cflag &= ~CSTOPB;
termnew.c_cc[VTIME] = 1; //VTIME:非cannoical模式读时的延时,以十分之一秒位单位
termnew.c_cc[VMIN] = 0; //VMIN:非canonical模式读到最小字符数
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &termnew);
}
/*
* band : 0->460800, 1->115200, 2->9600, other->115200
*/
int set_baudrate(int fd, uint8_t baud)
{
static struct termios termold, termnew;
tcgetattr(fd, &termold);
bzero(&termnew, sizeof(termnew));
termnew.c_iflag &= ~(ICRNL | IGNCR);
termnew.c_cflag |= CLOCAL | CREAD; //CLOCAL:忽略modem控制线 CREAD:打开接受者
termnew.c_cflag &= ~CSIZE;
termnew.c_cflag |= CS8;
termnew.c_cflag &= ~CRTSCTS;
termnew.c_cflag &= ~PARENB;
if(baud == 1)
{
cfsetispeed(&termnew, B460800);
cfsetospeed(&termnew, B460800);
}
else if(baud == 2)
{
cfsetispeed(&termnew, B115200);
cfsetospeed(&termnew, B115200);
}
else if(baud)
{
cfsetispeed(&termnew, B9600);
cfsetospeed(&termnew, B9600);
}
else
{
cfsetispeed(&termnew, B115200);
cfsetospeed(&termnew, B115200);
}
termnew.c_cflag &= ~CSTOPB;
termnew.c_cc[VTIME] = 1; //VTIME:非cannoical模式读时的延时,以十分之一秒位单位
termnew.c_cc[VMIN] = 0; //VMIN:非canonical模式读到最小字符数
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &termnew);
return 0;
}
int OpenUart(const char* UART_DEV)
{
int fd=0;
/*第1个参数:想要打开的文件路径名,或者文件名
*第2个参数:open_Status:文件打开方式,可采用下面的文件打开模式:
O_RDONLY:以只读方式打开文件
O_WRONLY:以只写方式打开文件
O_RDWR:以读写方式打开文件
O_APPEND:写入数据时添加到文件末尾
O_CREATE:如果文件不存在则产生该文件,使用该标志需要设置访问权限位mode_t
O_EXCL:指定该标志,并且指定了O_CREATE标志,如果打开的文件存在则会产生一个错误
O_TRUNC:如果文件存在并且成功以写或者只写方式打开,则清除文件所有内容,使得文件长度变为0
O_NOCTTY:如果打开的是一个终端设备,这个程序不会成为对应这个端口的控制终端,如果没有该标志,任何一个输入,例如键盘中止信号等,都将影响进程。
O_NONBLOCK:该标志与早期使用的O_NDELAY标志作用差不多。程序不关心DCD信号线的状态,如果指定该标志,进程将一直在休眠状态,直到DCD信号线为0。
O_NONBLOCK和O_NDELAY所产生的结果都是使I/O变成非搁置模式(non-blocking),在读取不到数据或是写入缓冲区已满会马上return,而不会搁置程序动作,直到有数据或写入完成;
它们的差别在于设立O_NDELAY会使I/O函式马上回传0,但是又衍生出一个问题,因为读取到档案结尾时所回传的也是0,这样无法得知是哪中情况;因此,O_NONBLOCK就产生出来,它在读取不到数据时会回传-1,并且设置errno为EAGAIN。
第3个参数:设置文件访问权限的初始值
*/
fd = open(UART_DEV , O_RDWR|O_NOCTTY);
if (fd < 0)
{
return -1;
}
SetOpt(fd);
return fd;
}